[
  {
    "path": ".agents/skills/code_style/SKILL.md",
    "content": "---\nname: Code style\ndescription:\n    Instructions for code formatting and style guidelines in the Carbon\n    toolchain.\n---\n\n# Code style\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## License\n\n-   **Licenses**: All Carbon files outside of `third_party/` should have a\n    license following\n    [CONTRIBUTING license instructions](/CONTRIBUTING.md#license).\n\n## Formatting\n\n-   **Bazel**: Use `pre-commit run buildifier --files <file.bzl>` to format\n    Bazel files.\n-   **C++**: Use `pre-commit run clang-format --files <file.cpp>` to format C++\n    files.\n-   **Carbon**: The toolchain's `format` command doesn't work well right now.\n    Instead, try to format Carbon code based on other Carbon files and the C++\n    style.\n-   **Markdown**: Use `pre-commit run prettier --files <file.md>` to format\n    markdown files.\n-   **Python**: Use `pre-commit run black --files <file.py>` to format Python\n    files.\n\n## Style Guides\n\n-   **C++ style**: Follow the\n    [Carbon C++ Project Style Guide](/docs/project/cpp_style_guide.md).\n-   **Markdown style**: Follow the\n    [Google developer documentation style guide](https://developers.google.com/style).\n-   **Python style**: Follow the [PEP 8](https://peps.python.org/pep-0008/)\n    style guide.\n    -   Wrap code and comments to 80 columns.\n    -   Run `pre-commit run flake8 --files <file.py>` to check Python style.\n"
  },
  {
    "path": ".agents/skills/summarize_testdata_changes/SKILL.md",
    "content": "<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n---\n\nname: Summarize testdata changes description: Instructions for summarizing\nchanges to Carbon testdata files (`toolchain/*/testdata`).\n\n---\n\n# Summarize testdata changes\n\nThis skill provides instructions for creating a comprehensive report summarizing\nchanges to Carbon testdata files (`toolchain/*/testdata`) and associating them\nwith related code changes.\n\n## Goals\n\nProduce a report that:\n\n1.  Summarizes code changes outside of testdata.\n2.  Groups similar testdata changes together, listing all affected files for\n    each group. **Every change to testdata must be represented by at least one\n    group. This includes changes to CHECK lines.**\n3.  Provides detailed breakdowns of test input changes and diagnostic output\n    changes in the corresponding group. **Every single change to inputs or to\n    STDERR checks must be explicitly mentioned in the group, with either an\n    inline diff or a link to the file.**\n\n## Process\n\n### 1. Identify Changes\n\nUse your VCS (Git or Jujutsu) or query Github to identify changes. For large\nchanges, it is recommended to use the included helper script to extract test\ninput changes.\n\n#### For Git Users:\n\n-   **Summarize code changes**: `git diff --stat -- ':!toolchain/*/testdata'`\n    -   To see content of non-testdata changes:\n        `git diff -- ':!toolchain/*/testdata'`\n-   **Identify testdata changes**: `git diff --name-only 'toolchain/*/testdata'`\n\n#### For Jujutsu (jj) Users:\n\n-   **Summarize code changes**:\n    `jj --no-pager diff --stat '~toolchain/*/testdata'`\n    -   Note: Quoting the fileset `'~toolchain/*/testdata'` is critical if it\n        contains wildcards.\n    -   To see content of non-testdata changes, use `--git` to get standard\n        unified diff format: `jj --no-pager diff --git '~toolchain/*/testdata'`\n-   **Identify testdata changes**:\n    `jj --no-pager diff --name-only 'toolchain/*/testdata'`\n\n#### For Github Pull Requests:\n\n-   **Summarize code changes**: `gh pr diff`\n-   **Identify testdata changes**:\n    `gh pr diff --name-only | grep '^toolchain/.*/testdata'`\n\n#### Handling Specific Revisions:\n\nIf you are summarizing changes in a specific revision (for example, `@-`) or\npull request (for example, #1234), add `-r <rev>` or `<pr_number>` to the\ncommands:\n\n-   `git diff <rev>^ <rev> ...` (or use `git show <rev>`)\n-   `jj --no-pager diff -r <rev> ...`\n-   `gh pr diff <pr_number>`\n\n### 2. Extract Test Input Changes (Recommended)\n\nTo easily identify changes, use the included Python helper script to extract all\ntext additions and removals from the diff, categorized by Input, STDERR, and\nSTDOUT changes. This script reads a unified diff from stdin.\n\n```bash\n# For Git:\ngit diff -- 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For Jujutsu (jj):\njj diff --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific revision with jj:\njj diff -r @- --git 'toolchain/*/testdata' | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n\n# For a specific PR with Github:\ngh pr diff 1234 | python3 .agents/skills/summarize_testdata_changes/scripts/parse_diff.py\n```\n\n### 3. Identify Patterns and Produce a List of Groups\n\n-   Read the diff and produce a list of groups of changes that share a common\n    theme or cause (for example, \"Updated expected output for integer literals\",\n    \"Added tests for new keyword\").\n-   **CRITICAL**: _Every single change_ in the testdata diff must be represented\n    by at least one group. Do not ignore changes to `CHECK` lines.\n    -   If it's not clear what group a change belongs to, create a new group for\n        it.\n-   For each group:\n    -   Provide a brief description of the group.\n    -   (Optional) Briefly note if the group appears to be an intended or\n        unintended consequence of the code changes.\n-   Divide the groups into sections:\n    -   Test Changes: Changes to test inputs (lines not prefixed with\n        `// CHECK`), along with diagnostic output changes where relevant\n    -   Diagnostic Changes: Changes to diagnostic output (lines prefixed with\n        `// CHECK:STDERR`) with no corresponding changes to test inputs\n    -   [Output Type] Changes: Changes to STDOUT (lines prefixed with `// CHECK:STDOUT`)\n        -   Create one section for each relevant kind of test. For example,\n            parser tests should typically be in a \"Parse Tree Changes\" section,\n            check tests should typically be in a \"SemIR Changes\" section, and\n            lower tests should typically be in an \"LLVM IR Changes\" section.\n\n### 4. Improve Grouping\n\n-   Read the list of groups and check to see if any of them should be combined\n    or split apart. If needed, do so.\n\n### 5. Assign Changes to Groups\n\n-   Read the diff again, and then for _each_ change in the diff:\n    -   Add the change to the appropriate group (or, rarely, groups).\n    -   **CRITICAL**: _Every single change_ in the testdata diff must be\n        represented by at least one group. Do not ignore changes to `CHECK`\n        lines.\n    -   If the change affects _test inputs_ (lines not prefixed with `// CHECK`)\n        or _diagnostic output_ (lines prefixed with `// CHECK:STDERR`):\n        -   List the file within the group. Don't just give one or a few\n            examples. Include every file.\n        -   Provide an inline diff if the change is small.\n        -   Provide a link to the file if the change is large.\n    -   Otherwise, if the change only affects _STDOUT_ (lines prefixed with\n        `// CHECK:STDOUT`):\n        -   Ensure the group contains a representative example that matches the\n            current change.\n        -   The representative example should be an inline diff of the change.\n    -   **CRITICAL**: _Every single change_ to test inputs and diagnostic\n        outputs in the files being summarized must be explicitly listed in at\n        least one group. Do not skip changes, even if they are similar to\n        changes you've already seen, and do not just give examples.\n\n### 6. Validation\n\nAs a final validation step:\n\n-   Read through the testdata diff again.\n-   Ensure that every change in the diff is reflected by at least one group in\n    the report.\n\n## Report Template\n\nUse the following template for the generated report:\n\n```markdown\n# `testdata` Change Summary\n\n## Code Changes\n\n[One paragraph summarizing changes outside of testdata.]\n\n## Test Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## Diagnostic Changes\n\n### [Group Name]\n\n[Description of the group.]\n\n[Change 1: diff context OR link]\n\n[Change 2: diff context OR link]\n\n...\n\n## [Output Type] Changes\n\n### [File Path]\n\n[Description of the group.]\n\n[Example diff context]\n\nChanges of this kind were found in [Number] files. Examples: [List of files]\n\n...\n```\n\nSkip sections that would be empty.\n"
  },
  {
    "path": ".agents/skills/summarize_testdata_changes/scripts/parse_diff.py",
    "content": "__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport sys\nfrom collections import defaultdict\nfrom typing import TextIO, Dict, List\n\n\ndef parse_diff(stream: TextIO) -> None:\n    current_file: str = \"\"\n    file_changes: Dict[str, Dict[str, List[str]]] = defaultdict(\n        lambda: {\"input\": [], \"stderr\": [], \"stdout\": []}\n    )\n\n    for line in stream:\n        if line.startswith(\"diff --git\"):\n            parts = line.split()\n            if len(parts) >= 4:\n                current_file = (\n                    parts[3][2:] if parts[3].startswith(\"b/\") else parts[3]\n                )\n        elif line.startswith(\"+\") or line.startswith(\"-\"):\n            if not line.startswith(\"+++\") and not line.startswith(\"---\"):\n                stripped = line[1:].strip()\n                if stripped.startswith(\"// CHECK:STDERR\"):\n                    file_changes[current_file][\"stderr\"].append(\n                        line.rstrip(\"\\n\")\n                    )\n                elif stripped.startswith(\"// CHECK:STDOUT\"):\n                    file_changes[current_file][\"stdout\"].append(\n                        line.rstrip(\"\\n\")\n                    )\n                elif stripped.startswith(\"// CHECK\"):\n                    file_changes[current_file][\"stdout\"].append(\n                        line.rstrip(\"\\n\")\n                    )\n                else:\n                    file_changes[current_file][\"input\"].append(\n                        line.rstrip(\"\\n\")\n                    )\n\n    for f, c in file_changes.items():\n        if not c[\"input\"] and not c[\"stderr\"] and not c[\"stdout\"]:\n            continue\n        print(f\"File: {f}\")\n        if c[\"input\"]:\n            print(\"  --- Input Changes ---\")\n            for change in c[\"input\"]:\n                print(f\"  {change}\")\n        if c[\"stderr\"]:\n            print(\"  --- STDERR Changes ---\")\n            for change in c[\"stderr\"]:\n                print(f\"  {change}\")\n        if c[\"stdout\"]:\n            print(\"  --- STDOUT Changes ---\")\n            for change in c[\"stdout\"]:\n                print(f\"  {change}\")\n        print(\"-\" * 40)\n\n\nif __name__ == \"__main__\":\n    parse_diff(sys.stdin)\n"
  },
  {
    "path": ".agents/skills/tool_usage/SKILL.md",
    "content": "---\nname: Tool usage\ndescription:\n    Instructions for AI assistants on what tools to use in the carbon-lang\n    project.\n---\n\n# Tool usage\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Bazelisk and Bazel\n\nWe use `bazelisk` for build and test.\n\n**IMPORTANT**: AI assistants use `bazelisk` instead of `bazel`.\n\n## Pre-commit\n\nRunning `pre-commit` is mandatory. To run it on all files:\n\n```bash\npre-commit run -a\n```\n\nTo validate a specific list of files:\n\n```bash\npre-commit run --files <files>\n```\n"
  },
  {
    "path": ".agents/skills/toolchain_development/SKILL.md",
    "content": "---\nname: Toolchain development\ndescription:\n    Instructions for checking, building, debugging, and understanding the Carbon\n    toolchain.\n---\n\n# Toolchain development\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Toolchain structure\n\n-   Under [`toolchain/`](/toolchain/):\n    -   [`base/`](/toolchain/base/): Base infrastructure and common utilities.\n    -   [`check/`](/toolchain/check/): Semantic analysis (SemIR generation).\n    -   [`lex/`](/toolchain/lex/): Lexing (Source -> Tokens).\n    -   [`lower/`](/toolchain/lower/): Lowering to LLVM IR.\n    -   [`parse/`](/toolchain/parse/): Parsing (Token -> Parse Tree).\n    -   [`sem_ir/`](/toolchain/sem_ir/): Semantic Intermediate Representation\n        (SemIR) definitions.\n\n## Toolchain architecture\n\n-   **Documentation**: Refer to [`toolchain/docs`](/toolchain/docs) for detailed\n    architecture design and patterns.\n    -   Refer to [Toolchain Idioms](/toolchain/docs/idioms.md) for a\n        comprehensive list of patterns (for example, `ValueStore`, formatting\n        `.def` files, struct reflection) used throughout the implementation.\n-   **Phases**: Lex -> Parse -> Check -> Lower.\n-   **Definitions**: Many kinds (tokens, parse nodes, SemIR instructions) are\n    defined in `.def` files and expanded by way of macros.\n-   **Handlers**:\n    -   Parser: `Handle<StateName>` in `parse/handle_*.cpp`.\n    -   Checker: `HandleParseNode` in `check/handle_*.cpp`.\n    -   Lowering: `HandleInst` in `lower/handle_*.cpp`.\n-   **Iteration**: Prefer iterative algorithms over recursive ones to prevent\n    stack exhaustion on complex codebases.\n\n### Essential commands\n\n-   **Test everything**: `bazelisk test //...`\n-   **Test specific target**: `bazelisk test //toolchain/testing:file_test`\n-   **Test specific file**:\n    `bazelisk test //toolchain/testing:file_test --test_arg=--file_tests=<path_to_carbon_file>`\n-   **Build toolchain**: `bazelisk build //toolchain/...`\n\n### Updating test data\n\nCarbon tests often use `file_test` (for example,\n`//toolchain/testing/file_test`). If you change compiler behavior, you likely\nneed to update expected test outputs. **Do not manually edit thousands of lines\nof expected output.** Use the script:\n\n```bash\n./toolchain/autoupdate_testdata.py\n# Or for a specific file:\n./toolchain/autoupdate_testdata.py toolchain/check/testdata/my_test.carbon\n```\n\n## Debugging and diagnostics\n\n-   **Printing to stderr**: Use `llvm::errs() << \"debug info\\n\";`.\n    -   Avoid `std::cout` (it may interfere with tool output).\n-   **SemIR Stringification**:\n    -   SemIR objects often have a `Print` method or `operator<<`.\n    -   `inst.Print(llvm::errs())`\n-   **Debugging Crashes**:\n    -   Bazel sandboxing can hide artifacts. Use `--sandbox_debug` if needed,\n        but often running the binary directly from `bazel-bin/` is easier for\n        debugging.\n\n## Error handling\n\n-   **No exceptions**: Do not use C++ exceptions.\n-   **`ErrorOr<T>`**: Return `ErrorOr<T>` for fallible operations.\n    -   Check with `if (auto result = Function(); result) { Use(*result); }`\n-   **`llvm::Expected<T>`**: Similar to `ErrorOr`, used when interfacing with\n    LLVM.\n\n### Casting (LLVM style)\n\n-   Use `llvm::cast<T>(obj)` (checked, asserts on failure).\n-   Use `llvm::dyn_cast<T>(obj)` (returns null on failure).\n-   Use `llvm::isa<T>(obj)` (boolean check).\n-   **Avoid** `dynamic_cast` and standard RTTI.\n\n### Data structures\n\n-   Prefer APIs in `common/` and `toolchain/base/` over LLVM ADTs. For example,\n    use `Map` instead of `llvm::DenseMap`.\n-   If no Carbon API exists, prefer LLVM ADTs over standard library ones (for\n    example `llvm::SmallVector`, `llvm::StringRef`).\n-   `StringRef` is a view; be careful with lifetimes.\n\n## Common pitfalls\n\n1.  **Legacy `explorer` references**: The `explorer` prototype has been moved.\n    Ignore references to it in proposals or old docs; focus on `toolchain`.\n2.  **Manually updating test files**: Always check if `autoupdate_testdata.py`\n    can do it for you.\n3.  **Using `std::string` unnecessarily**: Prefer `llvm::StringRef` for\n    arguments.\n4.  **Header includes**: Use specific include orders (often enforced by\n    `clang-format`).\n5.  **Parse node order**: Semantics processes parse nodes in post-order; ensure\n    your parser transitions support this.\n"
  },
  {
    "path": ".bazelignore",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Carbon creates some non-standard bazel directories, so ignore them.\nbazel-carbon-lang\n\n# See github_tools/MODULE.bazel.\ngithub_tools\n\n# Example Bazel project.\nexamples/bazel\n"
  },
  {
    "path": ".bazelrc",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Setup stamping with Carbon's workspace status attached but disable it by\n# default.\n#\n# Note that while we have minimized the impact of stamping on build caching, it\n# still has a meaningful impact, especially during development. So we disable\n# stamping by default and builds that need to include the workspace status\n# should explicitly enable it with `--stamp`.\ncommon --workspace_status_command=./scripts/workspace_status.py\ncommon --nostamp\n\n# Provide aliases for configuring the release and pre-release version being\n# built. For documentation of these flags, see //bazel/version/BUILD.\ncommon --flag_alias=release=//bazel/version:release\ncommon --flag_alias=pre_release=//bazel/version:pre_release\ncommon --flag_alias=rc_number=//bazel/version:rc_number\ncommon --flag_alias=nightly_date=//bazel/version:nightly_date\n\n# Support running clang-tidy with:\n#   bazel build --config=clang-tidy -k //...\n# See: https://github.com/erenon/bazel_clang_tidy\ncommon:clang-tidy --aspects @bazel_clang_tidy//clang_tidy:clang_tidy.bzl%clang_tidy_aspect\ncommon:clang-tidy --output_groups=report\ncommon:clang-tidy --@bazel_clang_tidy//:clang_tidy_config=//:clang_tidy_config\ncommon:clang-tidy --action_env=PATH --host_action_env=PATH\n\n# This warning seems to incorrectly fire in this build configuration, despite\n# not firing in our normal builds.\ncommon:clang-tidy --copt=-Wno-unknown-pragmas\n\n# --config=non-fatal-checks makes CHECK failures not terminate compilation.\ncommon:non-fatal-checks --per_file_copt=common/check_internal.cpp@-DCARBON_NON_FATAL_CHECKS\n\n# Provide an alias for controlling the `carbon_*` Bazel rules' configuration. We\n# enable use of the target config here to make our build and tests more\n# efficient, see the documentation in //bazel/carbon_rules/BUILD for details.\ncommon --flag_alias=use_target_config_carbon_rules=//bazel/carbon_rules:use_target_config_carbon_rules\ncommon --flag_alias=use_target_config_runtimes_builder=//toolchain/driver:use_target_config_runtimes_builder\n# Bazel doesn't track what commands the flag_alias is valid for, so we can't use\n# common here.\nbuild --use_target_config_carbon_rules\nbuild --use_target_config_runtimes_builder\n\n# Default to using a disk cache to minimize re-building LLVM and Clang which we\n# try to avoid updating too frequently to minimize rebuild cost. The location\n# here can be overridden in the user configuration where needed.\ncommon --disk_cache=~/.cache/carbon-lang-build-cache\n# If you'd like a different disk cache size, override it by copying this\n# line to `user.bazelrc` in the repository root and modify the number there.\ncommon --experimental_disk_cache_gc_max_size=100G\n\n# Enable some safety when using the build cache. Defaults to `lite`.\ncommon --guard_against_concurrent_changes=full\n\n# Used by clang_configuration.bzl.\ncommon --action_env=CC --host_action_env=CC\ncommon --action_env=CMAKE_SYSROOT --host_action_env=CMAKE_SYSROOT\n\n# Disable warnings for all external compilations. These involve code that isn't\n# developed as part of Carbon and may be difficult or impossible to patch, so\n# warnings aren't likely to be actionable.\ncommon --per_file_copt=external/.*\\.(c|cc|cpp|cxx)$@-w\ncommon --host_per_file_copt=external/.*\\.(c|cc|cpp|cxx)$@-w\n\n# Default dynamic linking to off. While this can help build performance in some\n# edge cases with very large linked executables and a slow linker, between using\n# fast linkers on all platforms (LLD and the Apple linker), as well as having\n# relatively few such executables, shared objects simply waste too much space in\n# our builds.\ncommon --dynamic_mode=off\n\n# Always compile PIC code. There are few if any disadvantages on the platforms\n# and architectures we care about and it avoids the need to compile files twice.\ncommon --force_pic\n\n# Completely disable Bazel's automatic stripping of debug information. Removing\n# that information causes unhelpful backtraces from unittest failures and other\n# crashes. Optimized builds already avoid using debug information by default.\ncommon --strip=never\n\n# Enable Abseil for GoogleTest.\ncommon --define=absl=1\n\n# Enable TCMalloc on Linux in optimized builds.\ncommon --custom_malloc=//bazel/malloc:tcmalloc_if_linux_opt\n\n# Configuration for enabling Address Sanitizer. Note that this is enabled by\n# default for fastbuild. The config is provided to enable ASan even in\n# optimized or other build configurations. Note that ASan and TCMalloc are\n# incompatible so this explicitly forces the system malloc.\ncommon:asan --features=asan\ncommon:asan --custom_malloc=@bazel_tools//tools/cpp:malloc\n\n# Configuration for enabling LibFuzzer (along with ASan).\ncommon:fuzzer --features=fuzzer\n\n# Force actions to have a UTF-8 language encoding.\n# TODO: Need to investigate what this should be on Windows, but at least for\n# Linux and macOS this seems strictly better than the Bazel default of just\n# `en_US`.\ncommon --action_env=LANG=en_US.UTF-8\n\n# Allow per-platform configuration.\ncommon --enable_platform_specific_config\n\n# Enable libpfm for google_benchmark on Linux only.\ncommon:linux --define=pfm=1\n\n# Enable split debug info on Linux, which is significantly more space efficient\n# and should work well with modern debuggers. Note that this is Linux specific\n# as macOS has its own approach that is always partially but not completely\n# split.\n#\n# Note: if using GDB, see documentation to get that working:\n# https://docs.carbon-lang.dev/docs/project/contribution_tools.html#debugging-with-gdb-instead-of-lldb\n#\n# TODO: Bazel has a bug where it doesn't manage dwo files in the cache correctly.\n# common:linux --fission=yes\n\n# Disables `actions.declare_symlink`. Done for cross-environment support.\ncommon --allow_unresolved_symlinks=false\n\n# Allow users to override any of the flags desired by importing a user-specific\n# RC file here if present.\ntry-import %workspace%/user.bazelrc\n\n# Query error in `@bazel_tools`. This reproduces with\n# `bazel query 'deps(//...)'`.\n# TODO: Enable the flag once compatibility issues are fixed.\n# common --incompatible_disable_non_executable_java_binary\n\n# Incompatible with the clang-tidy build mode.\n# TODO: Enable the flag once compatibility issues are fixed.\n# common --incompatible_auto_exec_groups\n\n# Incompatible with `rules_cc`.\n# TODO: Enable the flag once compatibility issues are fixed.\n# common --incompatible_no_rule_outputs_param\n# common --incompatible_stop_exporting_language_modules\n\n# Incompatible with `rules_pkg`.\n# TODO: Enable the flag once compatibility issues are fixed.\n# common --incompatible_disable_target_default_provider_fields\n\n# Incompatible with `rules_shell`.\n# TODO: Enable the flag once compatibility issues are fixed.\n# common --incompatible_check_visibility_for_toolchains\n\n# Enable as many incompatible flags as we can, per\n# https://bazel.build/release/backward-compatibility. To get the latest list,\n# using `bazelisk --migrate build //...` will help.\ncommon --incompatible_allow_tags_propagation\ncommon --incompatible_always_check_depset_elements\ncommon --incompatible_always_include_files_in_data\ncommon --incompatible_bazel_test_exec_run_under\ncommon --incompatible_check_sharding_support\ncommon --incompatible_check_testonly_for_output_files\ncommon --incompatible_config_setting_private_default_visibility\ncommon --incompatible_default_to_explicit_init_py\ncommon --incompatible_depset_for_java_output_source_jars\ncommon --incompatible_depset_for_libraries_to_link_getter\ncommon --incompatible_disable_autoloads_in_main_repo\ncommon --incompatible_disable_native_android_rules\ncommon --incompatible_disable_native_repo_rules\ncommon --incompatible_disable_objc_library_transition\ncommon --incompatible_disable_starlark_host_transitions\ncommon --incompatible_disable_target_provider_fields\ncommon --incompatible_disallow_ctx_resolve_tools\ncommon --incompatible_disallow_empty_glob\ncommon --incompatible_disallow_legacy_py_provider\ncommon --incompatible_disallow_sdk_frameworks_attributes\ncommon --incompatible_disallow_struct_provider_syntax\ncommon --incompatible_do_not_split_linking_cmdline\ncommon --incompatible_dont_enable_host_nonhost_crosstool_features\ncommon --incompatible_dont_use_javasourceinfoprovider\ncommon --incompatible_enable_apple_toolchain_resolution\ncommon --incompatible_enable_deprecated_label_apis\ncommon --incompatible_enable_proto_toolchain_resolution\ncommon --incompatible_enforce_config_setting_visibility\ncommon --incompatible_enforce_starlark_utf8\ncommon --incompatible_exclusive_test_sandboxed\ncommon --incompatible_fail_on_unknown_attributes\ncommon --incompatible_fix_package_group_reporoot_syntax\ncommon --incompatible_java_common_parameters\ncommon --incompatible_legacy_local_fallback\ncommon --incompatible_locations_prefers_executable\ncommon --incompatible_make_thinlto_command_lines_standalone\ncommon --incompatible_merge_fixed_and_default_shell_env\ncommon --incompatible_merge_genfiles_directory\ncommon --incompatible_modify_execution_info_additive\ncommon --incompatible_new_actions_api\ncommon --incompatible_no_attr_license\ncommon --incompatible_no_implicit_file_export\ncommon --incompatible_no_implicit_watch_label\ncommon --incompatible_objc_alwayslink_by_default\ncommon --incompatible_package_group_has_public_syntax\ncommon --incompatible_py2_outputs_are_suffixed\ncommon --incompatible_py3_is_default\ncommon --incompatible_python_disable_py2\ncommon --incompatible_python_disallow_native_rules\ncommon --incompatible_remote_use_new_exit_code_for_lost_inputs\ncommon --incompatible_remove_legacy_whole_archive\ncommon --incompatible_require_ctx_in_configure_features\ncommon --incompatible_require_linker_input_cc_api\ncommon --incompatible_run_shell_command_string\ncommon --incompatible_sandbox_hermetic_tmp\ncommon --incompatible_simplify_unconditional_selects_in_rule_attrs\ncommon --incompatible_stop_exporting_build_file_path\ncommon --incompatible_strict_action_env\ncommon --incompatible_strip_executable_safely\ncommon --incompatible_top_level_aspects_require_providers\ncommon --incompatible_unambiguous_label_stringification\ncommon --incompatible_use_cc_configure_from_rules_cc\ncommon --incompatible_use_new_cgroup_implementation\ncommon --incompatible_use_plus_in_repo_names\ncommon --incompatible_use_python_toolchains\ncommon --incompatible_validate_top_level_header_inclusions\ncommon --incompatible_visibility_private_attributes_at_definition\n"
  },
  {
    "path": ".bazelversion",
    "content": "8.5.1\n"
  },
  {
    "path": ".clang-format",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n---\nBasedOnStyle: Google\nAllowShortBlocksOnASingleLine: 'false'\nAllowShortIfStatementsOnASingleLine: Never\nAllowShortLoopsOnASingleLine: 'false'\nDerivePointerAlignment: 'false'\nExperimentalAutoDetectBinPacking: 'false'\nFixNamespaceComments: 'true'\nInsertBraces: 'true'\nPointerAlignment: Left\n# We abuse control macros for formatting other kinds of macros.\nSpaceBeforeParens: ControlStatementsExceptControlMacros\nIfMacros:\n  [\n    'CARBON_DEFINE_RAW_ENUM_CLASS',\n    'CARBON_DEFINE_ENUM_CLASS_NAMES',\n    'CARBON_DEFINE_RAW_ENUM_MASK',\n    'CARBON_DEFINE_ENUM_MASK_NAMES',\n    'CARBON_KIND_SWITCH',\n  ]\nStatementMacros: ['ABSTRACT']\nQualifierAlignment: Custom\nQualifierOrder:\n  [inline, static, friend, constexpr, const, volatile, restrict, type]\n"
  },
  {
    "path": ".clang-tidy",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n---\n# Get colors when outputting through `bazel build --config=clang-tidy`.\nUseColor: true\n# This is necessary for `--config=clang-tidy` to catch errors.\nWarningsAsErrors: '*'\n\nChecks:\n  # We turn on all of a few categories by default.\n  - '-*'\n  - 'bugprone-*'\n  - 'google-*'\n  - 'misc-*'\n  - 'modernize-*'\n  - 'performance-*'\n  - 'readability-*'\n\n  # Disabled due to the implied style choices.\n  - '-misc-const-correctness'\n  - '-misc-include-cleaner'\n  - '-misc-use-anonymous-namespace'\n  - '-modernize-deprecated-headers'\n  - '-modernize-return-braced-init-list'\n  - '-modernize-use-default-member-init'\n  - '-modernize-use-integer-sign-comparison'\n  - '-modernize-use-emplace'\n  - '-readability-avoid-nested-conditional-operator'\n  - '-readability-convert-member-functions-to-static'\n  - '-readability-else-after-return'\n  - '-readability-identifier-length'\n  - '-readability-implicit-bool-conversion'\n  - '-readability-make-member-function-const'\n  - '-readability-math-missing-parentheses'\n  - '-readability-static-definition-in-anonymous-namespace'\n  - '-readability-use-anyofallof'\n\n  # Warns when we have multiple empty cases in switches, which we do for comment\n  # reasons.\n  - '-bugprone-branch-clone'\n  # Frequently warns on multiple parameters of the same type.\n  - '-bugprone-easily-swappable-parameters'\n  # Finds issues like out-of-memory in main(). We don't use exceptions, so it's\n  # unlikely to find real issues.\n  - '-bugprone-exception-escape'\n  # Has false positives in places such as using an argument to declare a name,\n  # which cannot have parentheses. For our limited use of macros, this is a\n  # common conflict.\n  - '-bugprone-macro-parentheses'\n  # Conflicts with integer type C++ style.\n  - '-bugprone-narrowing-conversions'\n  # Has false positives for `enum_base.h`. Clang's built-in switch warnings\n  # cover most of our risk of bugs here.\n  - '-bugprone-switch-missing-default-case'\n  # In clang-tidy 16, has false positives on code like:\n  #     while (auto name_ref = insts().Get(inst_id).TryAs<SemIR::NameRef>()) {\n  #       inst_id = name_ref->value_id;\n  #                 ^ unchecked access to optional value\n  #     }\n  - '-bugprone-unchecked-optional-access'\n  # Overlaps with `readability-function-size`.\n  - '-google-readability-function-size'\n  # Suggests usernames on TODOs, which we don't want.\n  - '-google-readability-todo'\n  # Extremely slow. TODO: Re-enable once\n  # https://github.com/llvm/llvm-project/issues/128797 is fixed.\n  - '-misc-confusable-identifiers'\n  # Overlaps with `-Wno-missing-prototypes`.\n  - '-misc-use-internal-linkage'\n  # Suggests `std::array`, which we could migrate to, but conflicts with the\n  # status quo.\n  - '-modernize-avoid-c-arrays'\n  # Warns on creation of SemIR typed insts, for which we do not currently want\n  # to use designated initialization.\n  - '-modernize-use-designated-initializers'\n  # Only fixes const methods, not non-const, which yields distracting results on\n  # accessors.\n  - '-modernize-use-nodiscard'\n  # We aren't using the ranges library due to performance concerns.\n  - '-modernize-use-ranges'\n  # Low value compared to the engineering cost.\n  - '-performance-enum-size'\n  # Duplicates `modernize-pass-by-value`.\n  - '-performance-unnecessary-value-param'\n  # Warns on enums which use the `LastValue = Value` pattern if all the other\n  # discriminants aren't given an explicit value.\n  - '-readability-enum-initial-value'\n  # Warns too frequently.\n  - '-readability-function-cognitive-complexity'\n  # Warns in reasonably documented situations.\n  - '-readability-magic-numbers'\n  # Warns on `= {}` which is also used to indicate which fields do not need to\n  # be explicitly initialized in aggregate initialization.\n  - '-readability-redundant-member-init'\n  # Warns when callers use similar names as different parameters.\n  - '-readability-suspicious-call-argument'\n\nCheckOptions:\n  # Don't warn on structs; done by ignoring when there are only public members.\n  - key: misc-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic\n    value: true\n\n  # CamelCase names.\n  - key: readability-identifier-naming.ClassCase\n    value: CamelCase\n  - key: readability-identifier-naming.ClassConstantCase\n    value: CamelCase\n  - key: readability-identifier-naming.ConstexprVariableCase\n    value: CamelCase\n  - key: readability-identifier-naming.NamespaceCase\n    value: CamelCase\n  - key: readability-identifier-naming.StructCase\n    value: CamelCase\n  - key: readability-identifier-naming.TemplateParameterCase\n    value: CamelCase\n  - key: readability-identifier-naming.TypeAliasCase\n    value: CamelCase\n  - key: readability-identifier-naming.TypedefCase\n    value: CamelCase\n  - key: readability-identifier-naming.UnionCase\n    value: CamelCase\n\n  # lower_case names.\n  - key: readability-identifier-naming.ClassMemberCase\n    value: lower_case\n  - key: readability-identifier-naming.ParameterCase\n    value: lower_case\n  - key: readability-identifier-naming.VariableCase\n    value: lower_case\n\n  # TODO: This is for explorer's use of LLVM casting support, so we should be\n  # able to remove it once explorer is deleted.\n  - key: readability-identifier-naming.MethodIgnoredRegexp\n    value: '^classof$'\n\n  # This erroneously fires in C++20 mode with LLVM 16 clang-tidy, due to:\n  # https://github.com/llvm/llvm-project/issues/46097\n  - key: readability-identifier-naming.TemplateParameterIgnoredRegexp\n    value: '^expr-type$'\n\n  # Don't require writing a return type on lambdas.\n  - key: modernize-use-trailing-return-type.TransformLambdas\n    value: none\n\n  # Use lines rather than statements to measure function size, because\n  # for readability purposes we care about the code as written, before\n  # preprocessing.\n  - key: readability-function-size.StatementThreshold\n    value: none\n  - key: readability-function-size.LineThreshold\n    # Chose 800 to match the default for StatementThreshold.\n    value: 800\n"
  },
  {
    "path": ".clangd",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nCompileFlags:\n  # Workaround for https://github.com/clangd/clangd/issues/1582\n  Remove: [-march=*]\nDiagnostics:\n  # `unused-includes`: has false positives, reporting includes unused when\n  #   they are used.\n  Suppress: [unused-includes]\n\n---\n\n# Suppress common diagnostics for x-macro files.\nIf:\n  PathMatch: .*\\.def\nDiagnostics:\n  Suppress:\n    # The `#error` requiring a macro definition.\n    - pp_hash_error\n\n---\n\n# Suppress diagnostics for template source files.\nIf:\n  PathMatch: .*\\.tpl\\.h\nDiagnostics:\n  Suppress:\n    - undeclared_var_use\n"
  },
  {
    "path": ".codespell_ignore",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nAggregateT\nArchType\natleast\ncircularly\ncompiletime\ncopyable\ncrate\ncreateor\ncrossreference\nfalsy\nforin\ngroupt\nindext\ninout\nisELF\nparameteras\npullrequest\nrightt\nrouge\nstatics\nswitcht\n"
  },
  {
    "path": ".gdbinit",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nsource external/+llvm_project+llvm-project/llvm/utils/gdb-scripts/prettyprinters.py\nsource external/+llvm_project+llvm-project/libcxx/utils/gdb/libcxx/printers.py\npython register_libcxx_printer_loader()\n"
  },
  {
    "path": ".gitattributes",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# This tells Github to detect files having the extension `.def` as `C++` files, which\n# ensures that these files get syntax highlighted properly.\n*.def linguist-language=C++\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/01_toolchain_bug.yml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Toolchain bug\ndescription: >\n  Report a bug with the toolchain.\nlabels: [toolchain]\nbody:\n  - type: markdown\n    attributes:\n      value: >\n        **Attention:** If this is a _question_, please use either [GitHub\n        Discussions](https://github.com/carbon-language/carbon-lang/discussions)\n        or [Discord](https://discord.gg/ZjVdShJDAs).\n  - type: textarea\n    id: desc\n    attributes:\n      label: >\n        Description of the bug:\n  - type: textarea\n    id: repro\n    attributes:\n      label: >\n        What did you do, or what's a simple way to reproduce the bug?\n      description: >\n        Please provide example code and errors; a shortlink to the execution on\n        carbon.compiler-explorer.com can also help.\n  - type: textarea\n    id: expected\n    attributes:\n      label: >\n        What did you expect to happen?\n  - type: textarea\n    id: actual\n    attributes:\n      label: >\n        What actually happened?\n  - type: textarea\n    id: extras\n    attributes:\n      label: >\n        Any other information, logs, or outputs that you want to share?\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/02_documentation_bug.yml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Documentation bug\ndescription: >\n  Report a bug with the Carbon Language project documentation.\nbody:\n  - type: markdown\n    attributes:\n      value: >\n        **Attention:** If this is a _question_, please use either [GitHub\n        Discussions](https://github.com/carbon-language/carbon-lang/discussions)\n        or [Discord](https://discord.gg/ZjVdShJDAs).\n  - type: textarea\n    id: desc\n    attributes:\n      label: >\n        Description of the bug:\n  - type: textarea\n    id: input\n    attributes:\n      label: >\n        Link to documentation:\n  - type: textarea\n    id: actual\n    attributes:\n      label: >\n        What should it say instead?\n  - type: textarea\n    id: extras\n    attributes:\n      label: >\n        Any other information, logs, or outputs that you want to share?\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/03_leads_question.yml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Leads question\ndescription: >\n  Ask the leads for feedback on an important issue, such as a language design\n  choice.\nlabels: [leads question]\nbody:\n  - type: markdown\n    attributes:\n      value: >\n        **Attention:** If this is a _question_, please use either [GitHub\n        Discussions](https://github.com/carbon-language/carbon-lang/discussions)\n        or [Discord](https://discord.gg/ZjVdShJDAs).\n  - type: textarea\n    id: summary\n    attributes:\n      label: >\n        Summary of issue:\n      description: >\n        Provide a short, one-paragraph summary of the issue.\n  - type: textarea\n    id: detail\n    attributes:\n      label: >\n        Details:\n      description: >\n        Provide detailed information about the issue. For example, on a language\n        design choice, it can help to provide various options with a summary of\n        trade-offs.\n  - type: textarea\n    id: extras\n    attributes:\n      label: >\n        Any other information that you want to share?\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nblank_issues_enabled: true\ncontact_links:\n  - name: I have a question about Carbon\n    url: https://github.com/carbon-language/carbon-lang/discussions/categories/getting-started\n    about: Ask questions about Carbon in GitHub Discussions.\n  - name: I want to join the Discord\n    url: https://discord.gg/ZjVdShJDAs\n    about: Discord is where a lot of design discussion occurs.\n"
  },
  {
    "path": ".github/actions/build-setup-common/action.yml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Setup build environment (macOS)\ninputs:\n  matrix_runner:\n    required: true\n  remote_cache_upload:\n    required: true\nruns:\n  using: composite\n  steps:\n    # Setup Python and related tools.\n    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n      with:\n        # Match the min version listed in docs/project/contribution_tools.md\n        # or the oldest version available on the OS.\n        python-version:\n          ${{ inputs.matrix_runner == 'macos-14' && '3.11' || '3.10' }}\n\n    - uses: ./.github/actions/build-setup-macos\n      if: startsWith(inputs.matrix_runner, 'macos')\n      with:\n        matrix_runner: ${{ inputs.matrix_runner }}\n\n    - uses: ./.github/actions/build-setup-ubuntu\n      if: startsWith(inputs.matrix_runner, 'ubuntu')\n\n    # Print the various tool paths and versions to help in debugging.\n    - name: Print tool debugging info\n      shell: bash\n      run: |\n        echo '*** PATH'\n        echo $PATH\n        echo '*** bazelisk'\n        which bazelisk\n        bazelisk --version\n        echo '*** run_bazel.py'\n        ./scripts/run_bazel.py --version\n        echo '*** python'\n        which python\n        python --version\n        echo '*** clang'\n        which clang\n        clang --version\n        echo '*** clang++'\n        which clang++\n        clang++ --version\n        echo '*** clang-tidy'\n        which clang-tidy\n        clang-tidy --version\n\n    # Add our bazel configuration and print basic info to ease debugging.\n    - name: Configure Bazel and print info\n      env:\n        # Add a cache version for changes that bazel won't otherwise detect,\n        # like llvm version changes.\n        CACHE_VERSION: 1\n      shell: bash\n      run: |\n        cat >user.bazelrc <<EOF\n        # Disable the local disk cache as we use a remote cache and don't want\n        # two copies of every output taking up disk space. The only way to\n        # disable the disk cache is with an empty string:\n        # https://github.com/bazelbuild/bazel/issues/5308\n        build --disk_cache=\n\n        # Enable remote cache for our CI but minimize downloads.\n        build --remote_cache=https://storage.googleapis.com/carbon-builds-github-v${CACHE_VERSION}\n        build --remote_download_outputs=minimal\n\n        # We import a special key into every action in order to key the Bazel\n        # remote cache in a way that avoids collisions between different\n        # runners. Anything that might change the system external to Bazel but\n        # not be fully captured by the sand-boxing of the build should be used\n        # as part of the key. We don't need to use the CPU target for example,\n        # as that is captured by Bazel's configuration of each action. And the\n        # Clang version is incorporated by our Clang toolchain setup. But we\n        # do need to capture any differences between GitHub runner OSes that\n        # don't impact the Bazel configuration to avoid collisions between\n        # those.\n        build --action_env=BAZEL_REMOTE_CACHE_KEY=github-action-${{ inputs.matrix_runner }}\n\n        build ${{ inputs.remote_cache_upload }}\n\n        # Set an artificially high jobs count. This flag controls the number\n        # of concurrency Bazel itself uses, which is essential for actions\n        # that are internally blocked on for example downloading results form\n        # the cache above. Without setting this high, Bazel will pick a small\n        # number based on the available host CPUs and the reality will be a\n        # long chain of largely serialized download events with little or no\n        # usage of the host machine. Fortunately, local actions are\n        # *separately* gated on '--local_*_resources' that will avoid a large\n        # jobs value overwhelming the host. There is a bug to make downloads\n        # behave completely asynchronously and remove the need for this filed\n        # back in 2018 but work seemed to not finish:\n        # https://github.com/bazelbuild/bazel/issues/6394\n        #\n        # There is a new effort (yay!) but until then it seems worth using the\n        # workaround of a high jobs value. The biggest downside (increased\n        # heap usage) seems like it isn't currently a big loss for our builds.\n        #\n        # Higher values like 50 have led to CI failures with network errors\n        # and IOExceptions, see\n        # https://discord.com/channels/655572317891461132/707150492370862090/1151605725576056934\n        build --jobs=32\n\n        # Avoid any cache impact from build stamping in CI.\n        build --nostamp\n\n        # General build options.\n        build --verbose_failures\n        test --test_output=errors\n        EOF\n        ./scripts/run_bazel.py info\n\n    - name: Run bazel to sync deps with retry\n      shell: bash\n      run: |\n        # GitHub sometimes has a high failure rate for Bazel's downloads (even\n        # from GitHub URLs). Bazel exits with `1` on HTTP errors, which is hard\n        # to distinguish from a normal, permanent error.\n        #\n        # This workaround runs fast commands that should always pass (although\n        # they may be broken by an invalid PR). All errors are retried. The hope\n        # is that this caches necessary downloads, allowing later commands to\n        # more reliably succeed without retrying \"permanent\" errors.\n        #\n        # Disable lockfile updates, because some actions want to see\n        # differences.\n        ./scripts/run_bazel.py --attempts=5 --retry-all-errors \\\n          mod --lockfile_mode=off deps\n        ./scripts/run_bazel.py --attempts=5 --retry-all-errors \\\n          cquery --lockfile_mode=off //... | wc -l\n"
  },
  {
    "path": ".github/actions/build-setup-macos/action.yml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Setup build environment (macOS)\ninputs:\n  matrix_runner:\n    required: true\nruns:\n  using: composite\n  steps:\n    # Free up disk space as the macOS runners end up using most for Xcode\n    # versions we don't need and iOS simulators.\n    - name: Free up disk space\n      shell: bash\n      run: |\n        # The xcrun occasionally fails (maybe a race condition?), so retry a few\n        # times. Example failure:\n        #   \"data\" couldn't be moved to \"Deleting-<ID>\"\n        echo '*** Delete iOS simulators'\n        xcrun simctl delete all || \\\n          xcrun simctl delete all || \\\n          xcrun simctl delete all\n        sudo rm -rf ~/Library/Developer/CoreSimulator/Caches/*\n\n    # Install and cache LLVM 19 from Homebrew. Some runners may have LLVM 19,\n    # but this is reliable (including with libc++), and gives us testing at the\n    # minimum supported LLVM version.\n    - name: Cache Homebrew\n      id: cache-homebrew-macos\n      uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3\n      with:\n        # Cover all the critical parts of Homebrew here. Homebrew on Arm macOS\n        # uses its own prefix making this easy to cover, but we need a few\n        # different paths for Intel.\n        path: |\n          ${{\n            runner.arch == 'ARM64' && '/opt/homebrew' ||\n            '\n              /usr/local/Homebrew\n              /usr/local/Cellar\n              /usr/local/Frameworks\n              /usr/local/bin\n              /usr/local/opt\n            '\n          }}\n        # Note the key needs to include all the packages we're adding.\n        key:\n          Homebrew-Cache-${{ inputs.matrix_runner }}-${{ runner.arch }}-llvm@19\n\n    - name: Install LLVM and Clang with Homebrew\n      if: steps.cache-homebrew-macos.outputs.cache-hit != 'true'\n      shell: bash\n      run: |\n        echo '*** Prune brew leaves'\n        # We prune all the leaf packages to have a minimal environment. This\n        # both minimizes the install space and avoids accidental dependencies\n        # on installed packages.\n        brew leaves\n        LEAVES=$(brew leaves | egrep -v '^(bazelisk|gh|git|git-lfs|gnu-tar|go@.*|jq|pipx|node@.*|openssl@.*|wget|yq|zlib)$')\n        brew uninstall -f --ignore-dependencies $LEAVES\n        echo '*** Installing LLVM deps'\n        brew install --force-bottle --only-dependencies llvm@19\n        echo '*** Installing LLVM itself'\n        brew install --force-bottle --force --verbose llvm@19\n        echo '*** brew info llvm@19'\n        brew info llvm@19\n        echo '*** brew autoremove'\n        brew autoremove\n        echo '*** brew info'\n        brew info\n        echo '*** brew leaves'\n        brew leaves\n        echo '*** brew config'\n        brew config\n\n    - name: Setup LLVM and Clang\n      shell: bash\n      run: |\n        LLVM_PATH=\"$(brew --prefix llvm@19)\"\n        echo \"Using ${LLVM_PATH}\"\n        echo \"${LLVM_PATH}/bin\" >> $GITHUB_PATH\n        echo '*** ls \"${LLVM_PATH}\"'\n        ls \"${LLVM_PATH}\"\n        echo '*** ls \"${LLVM_PATH}/bin\"'\n        ls \"${LLVM_PATH}/bin\"\n"
  },
  {
    "path": ".github/actions/build-setup-ubuntu/action.yml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Setup build environment (Ubuntu)\nruns:\n  using: composite\n  steps:\n    # Ubuntu images start with ~23GB available; this takes a few seconds to add\n    # ~22GB more.\n    #\n    # Although we could delete more, if we run into a limit, not deleting\n    # everything provides a little flexibility to get space while trying\n    # to shrink the build.\n    - name: Free up disk space\n      uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1\n      with:\n        android: true\n        dotnet: true\n        haskell: true\n        # Enabling large-packages adds ~3 minutes to save ~4GB, so turn it off\n        # to save time.\n        large-packages: false\n\n    # Cache and install a recent version of LLVM. This uses the GitHub action\n    # cache to avoid directly downloading on each iteration and improve\n    # reliability.\n    - name: Cache LLVM and Clang installation\n      id: cache-llvm-ubuntu\n      uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3\n      with:\n        path: ~/llvm\n        key: LLVM-19.1.7-Cache-ubuntu-${{ runner.arch }}\n\n    - name: Download LLVM and Clang installation\n      if: steps.cache-llvm-ubuntu.outputs.cache-hit != 'true'\n      shell: bash\n      run: |\n        cd ~\n        LLVM_RELEASE=19.1.7\n        LLVM_TARBALL_NAME=LLVM-$LLVM_RELEASE-Linux-X64\n        LLVM_PATH=~/llvm\n        echo \"*** Downloading $LLVM_RELEASE\"\n        wget --show-progress=off \"https://github.com/llvm/llvm-project/releases/download/llvmorg-$LLVM_RELEASE/$LLVM_TARBALL_NAME.tar.xz\"\n        echo \"*** Extracting $LLVM_TARBALL_NAME.tar.xz\"\n        mkdir $LLVM_PATH\n        tar -xJf $LLVM_TARBALL_NAME.tar.xz --strip-components=1 -C $LLVM_PATH\n        echo \"*** Deleting $LLVM_TARBALL_NAME.tar.xz\"\n        rm $LLVM_TARBALL_NAME.tar.xz\n        echo \"*** Testing `clang++ --version`\"\n        $LLVM_PATH/bin/clang++ --version\n        # The installation contains *huge* parts of LLVM we don't need for the\n        # toolchain. Prune them here to keep our cache small.\n        echo \"*** Cleaning the 'llvm' directory\"\n        rm $LLVM_PATH/lib/{*.a,*.so,*.so.*}\n        rm $LLVM_PATH/bin/{flang-*,mlir-*,clang-{scan-deps,check,repl},*-test,llvm-{lto*,reduce,bolt*,exegesis,jitlink},bugpoint,opt,llc}\n        echo \"*** Size of the 'llvm' directory\"\n        du -hs $LLVM_PATH\n\n    - name: Setup LLVM and Clang paths\n      shell: bash\n      run: |\n        LLVM_PATH=~/llvm\n        echo \"Using ${LLVM_PATH}\"\n        echo \"${LLVM_PATH}/bin\" >> $GITHUB_PATH\n        echo '*** ls \"${LLVM_PATH}\"'\n        ls \"${LLVM_PATH}\"\n        echo '*** ls \"${LLVM_PATH}/bin\"'\n        ls \"${LLVM_PATH}/bin\"\n"
  },
  {
    "path": ".github/actions/test-setup/action.yml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Test setup\n\ninputs:\n  matrix_runner:\n    required: true\n  base_sha:\n    required: true\n  remote_cache_key:\n    required: true\n  targets_file:\n    required: true\n  use_direct_targets:\n    default: 'false'\n\noutputs:\n  has_code:\n    value: ${{ steps.filter.outputs.has_code}}\n  has_cpp_files:\n    value: ${{ steps.filter.outputs.has_cpp_files}}\n\nruns:\n  using: composite\n  steps:\n    # Tests should only run on applicable paths, but we still need to have an\n    # action run for the merge queue. We filter steps based on the paths here,\n    # and condition steps on the output.\n    - id: filter\n      uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2\n      with:\n        filters: |\n          has_code:\n            - '!{**/*.md,LICENSE,CODEOWNERS,.git*}'\n          has_cpp_files:\n            - '{**/*.cpp,**/*.h}'\n\n    # Disable uploads when the remote cache is read-only.\n    - name: Set up remote cache access (read-only)\n      if:\n        steps.filter.outputs.has_code == 'true' && github.event_name ==\n        'pull_request'\n      shell: bash\n      run: |\n        echo \"remote_cache_upload=--remote_upload_local_results=false\" \\\n            >> $GITHUB_ENV\n\n    # Provide a cache key when the remote cache is read-write.\n    - name: Set up remote cache access (read-write)\n      if:\n        steps.filter.outputs.has_code == 'true' && github.event_name !=\n        'pull_request'\n      shell: bash\n      env:\n        REMOTE_CACHE_KEY: ${{ inputs.remote_cache_key }}\n      run: |\n        echo \"$REMOTE_CACHE_KEY\" | base64 -d > $HOME/remote_cache_key.json\n        echo \"remote_cache_upload=--google_credentials=$HOME/remote_cache_key.json\" \\\n            >> $GITHUB_ENV\n\n    - uses: ./.github/actions/build-setup-common\n      if: steps.filter.outputs.has_code == 'true'\n      with:\n        matrix_runner: ${{ inputs.matrix_runner }}\n        remote_cache_upload: ${{ env.remote_cache_upload }}\n\n    # Just for visibility, print space before and after the build.\n    - name: Disk space before build\n      if: steps.filter.outputs.has_code == 'true'\n      shell: bash\n      run: df -h\n\n    - name: Verify MODULE.bazel.lock\n      if: steps.filter.outputs.has_code == 'true'\n      shell: bash\n      run: |\n        exit_code=0\n        ./scripts/run_bazel.py \\\n          --attempts=5 \\\n          mod deps --lockfile_mode=error || exit_code=$?\n        if (( $exit_code != 0 )); then\n          ./scripts/run_bazel.py \\\n            --attempts=5 \\\n            mod deps --lockfile_mode=update\n          echo \"MODULE.bazel.lock is out of date! Use below file for update.\"\n          echo \"Platforms may require merging output, for example by applying\"\n          echo \"an update, re-running triggers, and applying the next update.\"\n          echo \"============================================================\"\n          cat MODULE.bazel.lock\n          echo \"============================================================\"\n          exit 1\n        fi\n\n    # Build and run all targets on branch pushes to ensure we always have a\n    # clean tree. We don't expect this to be an interactive path and so don't\n    # optimize the latency of this step.\n    - name: Using all targets for push\n      if: steps.filter.outputs.has_code == 'true' && github.event_name == 'push'\n      shell: bash\n      env:\n        TARGETS_FILE: ${{ inputs.targets_file }}\n      run: |\n        echo \"//...\" >$TARGETS_FILE\n\n    # Compute the set of possible rules impacted by this change using\n    # Bazel-based diffing. This lets PRs and the merge queue have a much more\n    # efficient test CI action by avoiding even enumerating (and downloading)\n    # all of the unaffected Bazel targets.\n    - name: Compute indirect pull request targets\n      if:\n        steps.filter.outputs.has_code == 'true' && github.event_name != 'push'\n        && inputs.use_direct_targets != 'true'\n      shell: bash\n      env:\n        # Compute the base SHA from the different event structures.\n        GIT_BASE_SHA: ${{ inputs.base_sha }}\n        TARGETS_FILE: ${{ inputs.targets_file }}\n      run: |\n        # First fetch the relevant base into the git repository.\n        git fetch --depth=1 origin $GIT_BASE_SHA\n\n        # Do a retried query to try to download things for target-determinator.\n        ./scripts/run_bazel.py --attempts=5 cquery //... > /dev/null\n\n        # Then use `target-determinator` as wrapped by our script.\n        ./scripts/target_determinator.py $GIT_BASE_SHA >$TARGETS_FILE\n\n        # Bazel requires a test target to run the test command. There may be\n        # no targets or there may only be non-test targets that we want to\n        # build, so simply inject an explicit no-op test target.\n        echo \"//scripts:no_op_test\" >> $TARGETS_FILE\n\n    # Run the query to generate the targets file.\n    - name: Compute direct pull request targets\n      if:\n        steps.filter.outputs.has_code == 'true' && github.event_name != 'push'\n        && inputs.use_direct_targets == 'true'\n      shell: bash\n      env:\n        GIT_BASE_SHA: ${{ inputs.base_sha }}\n        QUERY_FILE: ${{ inputs.targets_file }}.query\n        TARGETS_FILE: ${{ inputs.targets_file }}\n      run: |\n        # First fetch the relevant base into the git repository.\n        git fetch --depth=1 origin $GIT_BASE_SHA\n\n        # Generate the query file. `same_pkg_direct_rdeps` is used to try to\n        # only get targets that contain modified files as srcs or hdrs (or\n        # similar artifacts).\n        echo 'same_pkg_direct_rdeps(' > $QUERY_FILE\n\n        # Start with an uninteresting file so that we can `union` below.\n        echo '  scripts/no_op_test.py' >> $QUERY_FILE\n\n        # Use `union` to join the list of files. Add quotes to defend against\n        # spaces. Note we can filter to the intersection of Carbon extensions\n        # and the supported list at:\n        # https://github.com/erenon/bazel_clang_tidy/blob/master/clang_tidy/clang_tidy.bzl#L65\n        for f in $(git diff --name-only --diff-filter=d \\\n                     $GIT_BASE_SHA -- '**/*.h' '**/*.cpp'); do\n          echo \"  union '$f'\" >> $QUERY_FILE\n        done\n\n        echo ')' >> $QUERY_FILE\n\n        # Use query because cquery doesn't support `same_pkg_direct_rdeps`.\n        ./scripts/run_bazel.py \\\n          --attempts=5 \\\n          query --query_file=$QUERY_FILE \\\n          > $TARGETS_FILE\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "**Replace this paragraph with a description of what this PR is changing or\nadding, and why.**\n\nCloses #ISSUE\n"
  },
  {
    "path": ".github/release.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n#\n# Provide the configuration and categorization for generated release notes.\n\nchangelog:\n  exclude:\n    labels:\n      - ignore-for-release\n\n  categories:\n    - title: 'Proposals accepted and merged :scroll:'\n      labels:\n        - proposal\n      exclude.labels:\n        - bot\n    - title: 'Toolchain and implementation changes :hammer_and_wrench:'\n      labels:\n        - toolchain\n      exclude.labels:\n        - bot\n    - title: 'Documentation changes :memo:'\n      labels:\n        - documentation\n      exclude.labels:\n        - bot\n    - title: 'Utilities :triangular_ruler:'\n      labels:\n        - utilities\n      exclude.labels:\n        - bot\n    - title: 'Infrastructure changes :building_construction:'\n      labels:\n        - infrastructure\n      exclude.labels:\n        - bot\n    - title: 'Automated robot PRs :robot:'\n      labels:\n        - bot\n    - title: 'Other changes'\n      labels:\n        - '*'\n"
  },
  {
    "path": ".github/workflows/README.md",
    "content": "# Workflows\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Hardening\n\nWorkflows are hardened using\n[Step Security tool](https://app.stepsecurity.io/secureworkflow). Findings for\nthe \"Harden Runner\" steps are\n[available online](https://app.stepsecurity.io/github/carbon-language/carbon-lang/actions/runs).\n\n### Allowed endpoints\n\nMost jobs only have a few endpoints, but due to tools which do downloads, a few\nhave significantly more. These are:\n\n-   clangd_tidy.yaml (Bazel)\n-   pre_commit.yaml (Bazel, pre-commit)\n-   nightly_release.yaml (Bazel)\n-   tests.yaml (Bazel)\n\nWhen updating one of these, consider updating all of them.\n\nWe try to keep `allowed-endpoints` with one per line. Prettier wants to wrap\nthem, which we fix this with `prettier-ignore`.\n\n## Testing\n\nWe keep around an `action-test` branch in carbon-lang, which can be used to test\ntriggers with `push:` configurations. For example:\n\n```\non:\n  push:\n    branches: [action-test]\n```\n"
  },
  {
    "path": ".github/workflows/auto_label_prs.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: 'Auto label PRs'\non:\n  pull_request_target:\n    types: [opened, ready_for_review]\n\npermissions:\n  pull-requests: write # For gh to edit labels.\n\n# TODO: `--repo carbon-language/carbon-lang` is a temporary workaround for:\n# https://github.com/cli/cli/issues/11055\n# Once a later version is released on runners, maybe August 2025, we should be\n# able to remove the extra flag.\njobs:\n  set_labels:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          disable-sudo: true\n          egress-policy: block\n          # prettier-ignore\n          allowed-endpoints: >\n            api.github.com:443\n\n      - id: filter\n        uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2\n        with:\n          filters: |\n            documentation:\n              - '*.md'\n              - 'docs/**'\n              - 'examples/**'\n              - 'third_party/examples/**'\n\n            infrastructure:\n              - '*.bzl'\n              - '*.cfg'\n              - '*.toml'\n              - '.*'\n              - '.*/**'\n              - 'BUILD'\n              - 'MODULE.*'\n              - 'WORKSPACE'\n              - 'bazel/**'\n              - 'github_tools/**'\n              - 'proposal/scripts/**'\n              - 'scripts/**'\n\n            # Here we only want the `proposal` label when a *new* file is added\n            # directly in this directory. We use `added` and a single level glob\n            # to achieve that.\n            proposal:\n              - added: 'proposals/*'\n\n            # We include common, shared code into the toolchain label for\n            # convenience. Essentially, this is everything we intend to ship as\n            # part of the reference implementation of the language.\n            toolchain:\n              - 'common/**'\n              - 'core/**'\n              - 'testing/**'\n              - 'toolchain/**'\n\n            utilities:\n              - 'utils/**'\n\n      - id: documentation\n        if: steps.filter.outputs.documentation == 'true'\n        run: |\n          gh pr edit \"${PR}\" --add-label \"documentation\" --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n\n      - id: infrastructure\n        if: steps.filter.outputs.infrastructure == 'true'\n        run: |\n          gh pr edit \"${PR}\" --add-label \"infrastructure\" --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n\n      - id: proposal\n        if: steps.filter.outputs.proposal == 'true'\n        run: |\n          gh pr edit \"${PR}\" --add-label \"proposal\" --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n\n      - id: toolchain\n        if: steps.filter.outputs.toolchain == 'true'\n        run: |\n          gh pr edit \"${PR}\" --add-label \"toolchain\" --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n\n      - id: utilities\n        if: steps.filter.outputs.utilities == 'true'\n        run: |\n          gh pr edit \"${PR}\" --add-label \"utilities\" --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n\n      # Note that this is not a path-based label, but an *author* based label,\n      # and it applies orthogonally to the others.\n      - id: automated\n        if:\n          contains(fromJSON('[\"CarbonInfraBot\", \"dependabot\"]'),\n          github.event.pull_request.user.login)\n        run: |\n          gh pr edit \"${PR}\" --add-label \"automated\" --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n"
  },
  {
    "path": ".github/workflows/clangd_tidy.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: 'Clang Tidy (clangd)'\n\non:\n  push:\n    branches: [trunk, action-test]\n  pull_request:\n  merge_group:\n\npermissions:\n  contents: read # For actions/checkout.\n  pull-requests: read # For dorny/paths-filter to read pull requests.\n\n# Cancel previous workflows on the PR when there are multiple fast commits.\n# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  clangd-tidy:\n    runs-on: ubuntu-22.04\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          egress-policy: block\n          # When adding endpoints, see README.md.\n          # prettier-ignore\n          allowed-endpoints: >\n            *.blob.storage.azure.net:443\n            *.githubapp.com:443\n            *.sourceforge.net:443\n            api.github.com:443\n            api.ipify.org:443\n            bcr.bazel.build:443\n            downloads.sourceforge.net:443\n            files.pythonhosted.org:443\n            github.com:443\n            go.dev:443\n            mirror.bazel.build:443\n            mirrors.kernel.org:443\n            nodejs.org:443\n            oauth2.googleapis.com:443\n            objects.githubusercontent.com:443\n            pypi.org:443\n            registry.npmjs.org:443\n            release-assets.githubusercontent.com:443\n            releases.bazel.build:443\n            storage.googleapis.com:443\n            uploads.github.com:443\n            www.googleapis.com:443\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - id: filter\n        uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2\n        with:\n          filters: |\n            has_cpp:\n              - added|modified: '{**/*.cpp,**/*.h}'\n          list-files: 'shell'\n\n      - uses: ./.github/actions/build-setup-common\n        if: steps.filter.outputs.has_cpp == 'true'\n        with:\n          matrix_runner: 'ubuntu-22.04'\n          remote_cache_upload: '--remote_upload_local_results=false'\n\n      - name: Create compile commands\n        if: steps.filter.outputs.has_cpp == 'true'\n        run: ./scripts/create_compdb.py\n\n      - name: Build deps for clangd-tidy\n        if: steps.filter.outputs.has_cpp == 'true'\n        run: ./scripts/run_bazel.py build //scripts:deps_for_clangd_tidy\n\n      - name: Install clangd-tidy\n        if: steps.filter.outputs.has_cpp == 'true'\n        run: pip install clangd-tidy==1.1.0.post2\n\n      - name: Run clangd-tidy\n        if: steps.filter.outputs.has_cpp == 'true'\n        env:\n          FILTER_FILES: ${{ steps.filter.outputs.has_cpp_files }}\n        run: |\n          clangd-tidy -p . -j 10 $FILTER_FILES\n"
  },
  {
    "path": ".github/workflows/discord_wiki.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Discord Wiki Change Notifications\n\non: gollum\n\n# Minimum permissions.\npermissions:\n  contents: read\n\njobs:\n  notify:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          egress-policy: audit\n\n      - uses: oznu/gh-wiki-edit-discord-notification@1f5b688c27310fba606368b20469c81f5ffd9a2f # v1.0.0\n        with:\n          discord-webhook-url: ${{ secrets.DISCORD_WEBHOOK_WIKI_EDIT }}\n"
  },
  {
    "path": ".github/workflows/gh_pages_ci.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: GitHub Pages CI\n\non:\n  pull_request:\n\n# Cancel previous workflows on the PR when there are multiple fast commits.\n# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\npermissions:\n  contents: read\n\njobs:\n  # Build job\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          egress-policy: audit\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n      - name: Prebuild actions\n        run: ./website/prebuild.py\n      - name: Setup Ruby\n        uses: ruby/setup-ruby@6ca151fd1bfcfd6fe0c4eb6837eb0584d0134a0c # v1.290.0\n        with:\n          # Runs 'bundle install' and caches installed gems automatically.\n          bundler-cache: true\n          # Increment this number if you need to re-download cached gems.\n          cache-version: 0\n      - name: Build with Jekyll\n        run: bundle exec jekyll build\n"
  },
  {
    "path": ".github/workflows/gh_pages_deploy.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: GitHub Pages deploy\n\non:\n  # Runs on pushes targeting the default branch.\n  push:\n    branches: ['trunk']\n\n  # Allows you to run this workflow manually from the Actions tab.\n  workflow_dispatch:\n\n# Cancel previous workflows on the PR when there are multiple fast commits.\n# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\n# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages.\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          egress-policy: audit\n\n      - name: Checkout\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n      - name: Prebuild actions\n        run: ./website/prebuild.py\n      - name: Setup Pages\n        uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0\n      - name: Setup Ruby\n        uses: ruby/setup-ruby@6ca151fd1bfcfd6fe0c4eb6837eb0584d0134a0c # v1.290.0\n        with:\n          # Runs 'bundle install' and caches installed gems automatically.\n          bundler-cache: true\n          # Increment this number if you need to re-download cached gems.\n          cache-version: 0\n      - name: Build with Jekyll\n        env:\n          JEKYLL_ENV: production\n        run: |\n          bundle exec jekyll build --verbose \\\n            --source ./ \\\n            --destination ./_site \\\n            --baseurl \"${{ steps.pages.outputs.base_path }}\"\n      - name: Upload artifact\n        # Automatically uploads an artifact from the './_site' directory by\n        # default.\n        uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0\n\n  deploy:\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    runs-on: ubuntu-latest\n    needs: build\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          egress-policy: audit\n\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5\n"
  },
  {
    "path": ".github/workflows/nightly_release.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n#\n# This workflow creates a GitHub \"release\" of a nightly build of the project.\n#\n# Note: This is just an initial rough attempt, there is a lot of future work\n# needed here. A brief summary of TODOs:\n#\n# - Configure a nice release notes template and switch to generating the title\n#   and notes instead of hard coding them.\n#\n# - Do some amount of testing prior to building and uploading the release.\n#   - Tempting to try to examine existing testing workflow, but maybe better to\n#     allow reusing any complex parts and do our own testing. That would, for\n#     example, allow us to narrow or expand the set of tests uses for\n#     pre-release testing to potentially be different from continuous testing.\n#   - Some questions around what to do in the event of a failure... error? Where\n#     does the error go? Create a draft, unpublished release instead?\n#\n# - Build artifacts for all the different OSes we have GitHub runners for rather\n#   than just x86 Linux.\n\nname: Nightly Release\n\non:\n  schedule:\n    - cron: '0 2 * * *'\n  # Enable manual runs for testing or manually (re-)creating a nightly release.\n  workflow_dispatch:\n\npermissions:\n  contents: write # For creating and uploading to releases.\n\njobs:\n  release:\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          egress-policy: block\n          # When adding endpoints, see README.md.\n          # prettier-ignore\n          allowed-endpoints: >\n            *.blob.storage.azure.net:443\n            *.githubapp.com:443\n            *.sourceforge.net:443\n            api.github.com:443\n            api.ipify.org:443\n            bcr.bazel.build:443\n            downloads.sourceforge.net:443\n            files.pythonhosted.org:443\n            github.com:443\n            go.dev:443\n            mirror.bazel.build:443\n            mirrors.kernel.org:443\n            nodejs.org:443\n            oauth2.googleapis.com:443\n            objects.githubusercontent.com:443\n            pypi.org:443\n            registry.npmjs.org:443\n            release-assets.githubusercontent.com:443\n            releases.bazel.build:443\n            storage.googleapis.com:443\n            uploads.github.com:443\n            www.googleapis.com:443\n\n      - name: Checkout branch\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Set up remote cache access\n        env:\n          REMOTE_CACHE_KEY: ${{ secrets.CARBON_BUILDS_GITHUB }}\n        run: |\n          echo \"$REMOTE_CACHE_KEY\" | base64 -d > $HOME/remote_cache_key.json\n          echo \"remote_cache_upload=--google_credentials=$HOME/remote_cache_key.json\" \\\n              >> $GITHUB_ENV\n\n      - uses: ./.github/actions/build-setup-common\n        with:\n          matrix_runner: ubuntu-22.04\n          remote_cache_upload: ${{ env.remote_cache_upload }}\n\n      - name: Get nightly date\n        run: |\n          echo \"nightly_date=$(date '+%Y.%m.%d')\" >> $GITHUB_ENV\n\n      - name: Build release\n        run: |\n          ./scripts/run_bazel.py \\\n            --attempts=5 --jobs-on-last-attempt=4 \\\n            test -c opt --stamp --remote_download_toplevel \\\n            --pre_release=nightly --nightly_date=${{ env.nightly_date }} \\\n            //toolchain \\\n            //toolchain/install:carbon_toolchain_tar_gz_rule \\\n            //toolchain/install:carbon_toolchain_tar_gz_test\n\n      - name: Extract the release version\n        run: |\n          # Make sure we can run the toolchain to get the version.\n          ./bazel-bin/toolchain/carbon version\n\n          # Now stash it in a variable and export it.\n          VERSION=$( \\\n            ./bazel-bin/toolchain/carbon version \\\n            | cut -d' ' -f5 | cut -d'+' -f1)\n          echo \"release_version=$VERSION\" >> $GITHUB_ENV\n\n      - name: Create the release\n        env:\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          gh release create \\\n            --title \"Nightly build ${{ env.nightly_date }}\" \\\n            --generate-notes \\\n            --prerelease \\\n            v${{ env.release_version }} \\\n            \"bazel-bin/toolchain/install/carbon_toolchain-${{ env.release_version }}.tar.gz\"\n"
  },
  {
    "path": ".github/workflows/pre_commit.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: pre-commit\n\non:\n  pull_request:\n  merge_group:\n  push:\n    branches: [trunk]\n\npermissions:\n  contents: read # For actions/checkout.\n\njobs:\n  pre-commit:\n    runs-on: ubuntu-22.04\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          egress-policy: block\n          # When adding endpoints, see README.md.\n          # prettier-ignore\n          allowed-endpoints: >\n            *.blob.storage.azure.net:443\n            *.githubapp.com:443\n            *.sourceforge.net:443\n            api.github.com:443\n            api.ipify.org:443\n            bcr.bazel.build:443\n            downloads.sourceforge.net:443\n            files.pythonhosted.org:443\n            github.com:443\n            go.dev:443\n            mirror.bazel.build:443\n            mirrors.kernel.org:443\n            nodejs.org:443\n            oauth2.googleapis.com:443\n            objects.githubusercontent.com:443\n            pypi.org:443\n            registry.npmjs.org:443\n            release-assets.githubusercontent.com:443\n            releases.bazel.build:443\n            storage.googleapis.com:443\n            uploads.github.com:443\n            www.googleapis.com:443\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0\n\n      # Ensure LLVM is set up consistently.\n      - uses: ./.github/actions/build-setup-common\n        with:\n          matrix_runner: ubuntu-22.04\n          remote_cache_upload: '--remote_upload_local_results=false'\n\n      - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1\n\n      # We want to automatically create github suggestions for pre-commit file\n      # changes for a pull request. But `pull_request` actions never have write\n      # permissions to the repository, so we create the suggestions in a separate\n      # privileged `workflow_run` action in pre_commit_suggestions.yaml. Here,\n      # we upload the diffs and event configuration to an artifact for use by\n      # that action.\n      - name: Collect pre-commit output\n        if: failure()\n        run: |\n          mkdir -p pre-commit-output\n          git diff > pre-commit-output/diff\n          cp $GITHUB_EVENT_PATH pre-commit-output/event\n      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0\n        if: failure()\n        with:\n          name: pre-commit output\n          path: pre-commit-output/*\n"
  },
  {
    "path": ".github/workflows/pre_commit_suggestions.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Create PR suggestions based on problems found by pre-commit action.\nname: 'Add pre-commit suggestions'\n\n# This action is run whenever the `pre-commit` action finishes. Because the\n# `pre-commit` action is an unprivileged action running on (for example) the\n# `pull_request` event, it's run without write permissions to the repository, so\n# we use a separate privileged `workflow_run` action here to pick up its results\n# and convert them into suggestion comments.\n#\n# This action is only run from the workflow file on the trunk branch. Changes to\n# this file will not take effect until they are merged to trunk.\non:\n  workflow_run:\n    workflows: [pre-commit]\n    types:\n      - completed\n\n# Note reviewdog/reviewdog has its own token.\npermissions:\n  contents: read # For actions/checkout.\n\njobs:\n  pull-request-suggestions:\n    # Only generate suggestions if pre-commit for a PR failed.\n    if: |\n      github.event.workflow_run.conclusion == 'failure' &&\n      github.event.workflow_run.event == 'pull_request' &&\n      github.actor != 'jonmeow'\n    runs-on: ubuntu-latest\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          disable-sudo: true\n          egress-policy: block\n          # prettier-ignore\n          allowed-endpoints: >\n            api.github.com:443\n            github.com:443\n            objects.githubusercontent.com:443\n            raw.githubusercontent.com:443\n\n      - uses: reviewdog/action-setup@3f401fe1d58fe77e10d665ab713057375e39b887 # v1.3.0\n        with:\n          reviewdog_version: latest\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - name: Download pre-commit output\n        uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0\n        with:\n          name: pre-commit output\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          run-id: ${{ github.event.workflow_run.id }}\n\n      # Use https://github.com/reviewdog/reviewdog to create PR suggestions\n      # matching the diff that pre-commit created.\n      - name: Create suggestions\n        env:\n          REVIEWDOG_GITHUB_API_TOKEN:\n            ${{ secrets.CARBON_INFRA_BOT_FOR_REVIEWDOG }}\n        run: |\n          cat ./diff | \\\n          GITHUB_EVENT_PATH=./event \\\n            reviewdog -f=diff -f.diff.strip=1 -reporter=github-pr-review\n"
  },
  {
    "path": ".github/workflows/proposal_labeled.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Applies mutual exclusivity between states labels:\n# - proposal draft\n# - proposal rfc\n# - proposal accepted\n# - proposal declined\n# - proposal deferred\n#\n# The \"proposal\" label is always applied in order to make searching for all\n# proposals (regardless of state) easy, although it will typically already be\n# present.\n\nname: Proposal labeled\non:\n  pull_request_target:\n    types:\n      - labeled\n\npermissions:\n  pull-requests: write # For gh to edit labels.\n\n# TODO: `--repo carbon-language/carbon-lang` is a temporary workaround for:\n# https://github.com/cli/cli/issues/11055\n# Once a later version is released on runners, maybe August 2025, we should be\n# able to remove the extra flag.\njobs:\n  proposal_labeled:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          disable-sudo: true\n          egress-policy: block\n          # prettier-ignore\n          allowed-endpoints: >\n            api.github.com:443\n\n      - name: draft\n        if: |\n          github.event.label.name == 'proposal draft'\n        run: |\n          gh pr edit \"${PR}\" \\\n            --remove-label \"proposal rfc\" \\\n            --remove-label \"proposal accepted\" \\\n            --remove-label \"proposal declined\" \\\n            --remove-label \"proposal deferred\" \\\n            --add-label \"proposal\" \\\n            --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n\n      - name: rfc\n        if: |\n          github.event.label.name == 'proposal rfc'\n        run: |\n          gh pr edit \"${PR}\" \\\n            --remove-label \"proposal draft\" \\\n            --remove-label \"proposal accepted\" \\\n            --remove-label \"proposal declined\" \\\n            --remove-label \"proposal deferred\" \\\n            --add-label \"proposal\" \\\n            --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n\n      - name: accepted\n        if: |\n          github.event.label.name == 'proposal accepted'\n        run: |\n          gh pr edit \"${PR}\" \\\n            --remove-label \"proposal draft\" \\\n            --remove-label \"proposal rfc\" \\\n            --remove-label \"proposal declined\" \\\n            --remove-label \"proposal deferred\" \\\n            --add-label \"proposal\" \\\n            --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n\n      - name: declined\n        if: |\n          github.event.label.name == 'proposal declined'\n        run: |\n          gh pr edit \"${PR}\" \\\n            --remove-label \"proposal draft\" \\\n            --remove-label \"proposal rfc\" \\\n            --remove-label \"proposal accepted\" \\\n            --remove-label \"proposal deferred\" \\\n            --add-label \"proposal\" \\\n            --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n\n      - name: deferred\n        if: |\n          github.event.label.name == 'proposal deferred'\n        run: |\n          gh pr edit \"${PR}\" \\\n            --remove-label \"proposal draft\" \\\n            --remove-label \"proposal rfc\" \\\n            --remove-label \"proposal accepted\" \\\n            --remove-label \"proposal declined\" \\\n            --add-label \"proposal\" \\\n            --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n"
  },
  {
    "path": ".github/workflows/proposal_ready.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Applies the \"proposal rfc\" label when a proposal is marked ready for review.\n\nname: Proposal ready for review\non:\n  pull_request_target:\n    types:\n      - ready_for_review\n\npermissions:\n  pull-requests: write # For gh to edit labels.\n\n# TODO: `--repo carbon-language/carbon-lang` is a temporary workaround for:\n# https://github.com/cli/cli/issues/11055\n# Once a later version is released on runners, maybe August 2025, we should be\n# able to remove the extra flag.\njobs:\n  proposal_ready:\n    if: contains(github.event.pull_request.labels.*.name, 'proposal')\n    runs-on: ubuntu-latest\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          disable-sudo: true\n          egress-policy: block\n          # prettier-ignore\n          allowed-endpoints: >\n            api.github.com:443\n\n      - name: rfc\n        run: |\n          gh pr edit \"${PR}\" \\\n            --remove-label \"proposal draft\" \\\n            --remove-label \"proposal accepted\" \\\n            --remove-label \"proposal declined\" \\\n            --remove-label \"proposal deferred\" \\\n            --add-label \"proposal rfc\" \\\n            --repo carbon-language/carbon-lang\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          PR: ${{ github.event.pull_request.html_url }}\n"
  },
  {
    "path": ".github/workflows/sync_repos.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Sync repos\n\non:\n  push:\n    branches: [trunk]\n    paths:\n      # Minimize where we run this to changes to the top-level files and\n      # specific trees that we sync to other repositories.\n      - '*'\n      - 'utils/**'\n      # Also run if the action itself is updated.\n      - '.github/workflows/sync_repos.yaml'\n      - 'scripts/sync_repos.sh'\n\n# Note the sync script has its own token.\npermissions:\n  contents: read # For actions/checkout.\n\njobs:\n  sync-repos:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          egress-policy: audit\n\n      # Checkout our main repository.\n      - name: Checkout the main repository\n        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      # Run the sync script.\n      - name: Sync to other repositories\n        env:\n          API_TOKEN_GITHUB: ${{ secrets.SYNC_REPOS_API_TOKEN_GITHUB }}\n        run: ./scripts/sync_repos.sh\n"
  },
  {
    "path": ".github/workflows/tests.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: Tests\n\non:\n  push:\n    branches: [trunk, action-test]\n  pull_request:\n  merge_group:\n\npermissions:\n  contents: read # For actions/checkout.\n  pull-requests: read # For dorny/paths-filter to read pull requests.\n\n# Cancel previous workflows on the PR when there are multiple fast commits.\n# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  test:\n    strategy:\n      matrix:\n        # Test a recent version of each supported OS.\n        runner: ['ubuntu-22.04', 'macos-14']\n        build_mode: [fastbuild, opt]\n    runs-on: ${{ matrix.runner }}\n\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          egress-policy: block\n          # When adding endpoints, see README.md.\n          # prettier-ignore\n          allowed-endpoints: >\n            *.blob.storage.azure.net:443\n            *.githubapp.com:443\n            *.sourceforge.net:443\n            api.github.com:443\n            api.ipify.org:443\n            bcr.bazel.build:443\n            downloads.sourceforge.net:443\n            files.pythonhosted.org:443\n            github.com:443\n            go.dev:443\n            mirror.bazel.build:443\n            mirrors.kernel.org:443\n            nodejs.org:443\n            oauth2.googleapis.com:443\n            objects.githubusercontent.com:443\n            pypi.org:443\n            registry.npmjs.org:443\n            release-assets.githubusercontent.com:443\n            releases.bazel.build:443\n            storage.googleapis.com:443\n            uploads.github.com:443\n            www.googleapis.com:443\n\n      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2\n\n      - id: test-setup\n        uses: ./.github/actions/test-setup\n        with:\n          matrix_runner: ${{ matrix.runner }}\n          base_sha:\n            ${{ github.event_name == 'pull_request' &&\n            github.event.pull_request.base.sha ||\n            github.event.merge_group.base_sha }}\n          remote_cache_key: ${{ secrets.CARBON_BUILDS_GITHUB }}\n          targets_file: ${{ runner.temp }}/targets\n\n      # Build and run just the tests impacted by the PR or merge group.\n      - name: Test (${{ matrix.build_mode }})\n        if: steps.test-setup.outputs.has_code == 'true'\n        shell: bash\n        env:\n          # 'libtool_check_unique failed to generate' workaround.\n          # https://github.com/bazelbuild/bazel/issues/14113#issuecomment-999794586\n          BAZEL_USE_CPP_ONLY_TOOLCHAIN: 1\n          TARGETS_FILE: ${{ runner.temp }}/targets\n        run: |\n          # Decrease the jobs sharply if we see repeated failures to try to\n          # work around transient network errors even if it makes things\n          # slower.\n          ./scripts/run_bazel.py \\\n            --attempts=5 --jobs-on-last-attempt=4 \\\n            test -c ${{ matrix.build_mode }} \\\n            --target_pattern_file=$TARGETS_FILE\n\n      # See \"Disk space before build\" in `test-setup`.\n      - name: Disk space after build\n        if: steps.test-setup.outputs.has_code == 'true'\n        run: df -h\n"
  },
  {
    "path": ".github/workflows/triage_inactive.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nname: 'Triage inactive issues and PRs'\non:\n  schedule:\n    - cron: '30 1 * * *'\n\npermissions:\n  issues: write # For actions/stale to close stale issues.\n  pull-requests: write # For actions/stale to close stale PRs.\n\njobs:\n  stale:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Harden Runner\n        uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1\n        with:\n          disable-sudo: true\n          egress-policy: block\n          # prettier-ignore\n          allowed-endpoints: >\n            api.github.com:443\n\n      - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0\n        with:\n          stale-issue-message: >\n            We triage inactive PRs and issues in order to make it easier to find\n            active work. If this issue should remain active or becomes active\n            again, please comment or remove the `inactive` label. The `long term\n            issue` label can also be added for issues which are expected to take\n            time.\n\n\n            This issue is labeled `inactive` because the last activity was over\n            90 days ago.\n          stale-pr-message: >\n            We triage inactive PRs and issues in order to make it easier to find\n            active work. If this PR should remain active, please comment or\n            remove the `inactive` label.\n\n\n            This PR is labeled `inactive` because the last activity was over 90\n            days ago. This PR will be closed and archived after 14 additional\n            days without activity.\n          close-pr-message: >\n            We triage inactive PRs and issues in order to make it easier to find\n            active work. If this PR should remain active or becomes active\n            again, please reopen it.\n\n\n            This PR was closed and archived because there has been no new\n            activity in the 14 days since the `inactive` label was added.\n          stale-issue-label: 'inactive'\n          stale-pr-label: 'inactive'\n          exempt-issue-labels:\n            'long term issue,design idea,design update,good first issue,leads\n            question'\n          days-before-stale: 90\n          days-before-close: 14\n          days-before-issue-close: -1\n          operations-per-run: 100\n"
  },
  {
    "path": ".gitignore",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Directories and symlinks generated by bazel.\n/bazel-*\n\n# See github_tools/MODULE.bazel.\n/github_tools/bazel-*\n/github_tools/MODULE.bazel.lock\n\n# We also have example Bazel projects that shouldn't have their implementation\n# details committed.\n/examples/**/bazel-*\n/examples/**/MODULE.bazel.lock\n\n# Directories created by python.\n**/__pycache__/\n\n# Ignore the user's VSCode settings and debug setup.\n/.vscode/settings.json\n/.vscode/launch.json\n\n# Ignore the user's Idea settings.\n/.idea/\n\n# Directories created by clangd\n/.cache/clangd\n\n# User-specific Bazel configuration.\n/user.bazelrc\n\n# Compilation database used by clangd\n/compile_commands.json\n\n# Emacs temporary files\n*~\n\\#*\\#\n\n# vim temporary files\n.*.sw[a-p]\n.swp\n\n# generated by utils/tree_sitter/helix.sh\n/.helix/\n\n# Ignore .DS_Store files\n.DS_Store\n\n# Ignore the .gdb_history that's created next to the project-specific .gdbinit\n.gdb_history\n"
  },
  {
    "path": ".lldbinit",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\ncommand script import external/+llvm_project+llvm-project/llvm/utils/lldbDataFormatters.py\ncommand script import scripts/lldbinit.py\nsettings set escape-non-printables false\nsettings set target.max-string-summary-length 10000\n"
  },
  {
    "path": ".pre-commit-config.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Update versions with:\n#   pre-commit autoupdate --freeze && pre-commit run -a\n# See https://pre-commit.com for more information\n# See https://pre-commit.com/hooks.html for more hooks\n\ndefault_language_version:\n  python: python3 # Defaults to python2, so override it.\n\nrepos:\n  - repo: https://github.com/pre-commit/pre-commit-hooks\n    rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0\n    hooks:\n      - id: check-added-large-files\n      - id: check-case-conflict\n      - id: check-executables-have-shebangs\n      - id: check-merge-conflict\n      - id: check-symlinks\n        exclude: ^bazel-execroot$\n      - id: check-yaml\n      - id: detect-private-key\n      - id: end-of-file-fixer\n        exclude: '^(.*/fuzzer_corpus/.*|.*\\.svg)$'\n      - id: mixed-line-ending\n        args: ['--fix=lf']\n        exclude: '^(.*/fuzzer_corpus/.*|.*\\.svg)$'\n      - id: trailing-whitespace\n        exclude: '^(.*/fuzzer_corpus/.*|.*/testdata/.*\\.golden|.*\\.svg)$'\n  - repo: https://github.com/google/pre-commit-tool-hooks\n    rev: efaea7c61c774c0b1a9805fd999e754a2d19dbd1 # frozen: v1.2.5\n    hooks:\n      - id: check-google-doc-style\n      - id: markdown-toc\n  - repo: local\n    hooks:\n      - id: fix-cc-deps\n        name: Fix missing C++ deps\n        entry: scripts/fix_cc_deps.py\n        language: python\n        files: ^.*/(BUILD|[^/]+\\.(h|cpp))$\n        pass_filenames: false\n\n  # Formatters should be run late so that they can re-format any prior changes.\n  - repo: https://github.com/psf/black\n    rev: 35ea67920b7f6ac8e09be1c47278752b1e827f76 # frozen: 26.3.0\n    hooks:\n      - id: black\n  - repo: local\n    hooks:\n      - id: prettier\n        name: prettier\n        language: node\n        # TODO: Not upgrading to/past 3.4.0 due to list indent changes that may\n        # get fixed. See: https://github.com/prettier/prettier/issues/16929\n        additional_dependencies: ['prettier@3.3.3']\n        types_or: [html, javascript, json, markdown, yaml]\n        entry: npx prettier@3.3.3 --write --log-level=warn\n  - repo: local\n    hooks:\n      - id: buildifier\n        name: Bazel buildifier\n        entry: scripts/run_buildifier.py\n        # Beyond just formatting, explicitly fix lint warnings.\n        args: ['--lint=fix', '--warnings=all', '-r', '.']\n        language: python\n        files: |\n          (?x)^(\n            .*BUILD.*|\n            .*MODULE.bazel.*|\n            .*WORKSPACE.*|\n            .*\\.bzl\n          )$\n      - id: check-bazel-mod-deps\n        # Check this after buildifier because buildifier may modify inputs, and\n        # MODULE.bazel.lock includes line/column details.\n        name: Check bazel mod deps\n        entry: scripts/bazel_mod_deps.py\n        language: python\n        files: |\n          (?x)^(\n            .*MODULE.bazel.*|\n            .*WORKSPACE.*\n          )$\n      - id: clang-format\n        name: clang-format\n        entry: clang-format\n        types_or: [c++, def]\n        language: python\n        args: ['-i']\n        additional_dependencies: ['clang-format==21.1.8']\n\n  - repo: local\n    hooks:\n      - id: check-header-guards\n        # This should run after clang-format, which may reformat a guard.\n        name: Check header guards\n        entry: scripts/check_header_guards.py\n        language: python\n        files: ^.*\\.h$\n      - id: check-sha-filenames\n        # This may rename files, so it's deliberately between formatters and\n        # linters.\n        name: Check fuzzer SHA filenames\n        entry: scripts/check_sha_filenames.py\n        language: python\n        files: ^.*/fuzzer_corpus/.*$\n      - id: check-toolchain-diagnostics\n        name: Check toolchain diagnostics\n        entry: toolchain/diagnostics/check_diagnostics.py\n        language: python\n        files: |\n          (?x)^(\n              toolchain/.*\\.cpp|\n              toolchain/.*\\.h|\n              toolchain/diagnostics/check_diagnostics\\.py|\n              toolchain/diagnostics/diagnostic_kind\\.def\n          )$\n        pass_filenames: false\n\n  # Run linters last, as formatters and other checks may fix issues.\n  - repo: local\n    hooks:\n      - id: forbid-llvm-googletest\n        name: Checks for deps on LLVM's version of GoogleTest\n        entry: scripts/forbid_llvm_googletest.py\n        language: python\n        files: ^.*/BUILD$\n        pass_filenames: false\n  - repo: https://github.com/PyCQA/flake8\n    rev: d93590f5be797aabb60e3b09f2f52dddb02f349f # frozen: 7.3.0\n    hooks:\n      - id: flake8\n  - repo: https://github.com/pre-commit/mirrors-mypy\n    rev: 'a66e98df7b4aeeb3724184b332785976d062b92e' # frozen: v1.19.1\n    hooks:\n      - id: mypy\n        # Use setup.cfg to match the command line.\n        args:\n          - --config-file=setup.cfg\n        # This should match the requirements added in the WORKSPACE pip_install.\n        additional_dependencies:\n          - gql >= 2.0.0, < 3.0.0\n          - PyGitHub\n          - rich\n        # Exclusions are:\n        # - p#### scripts because they're not tested or maintained.\n        # - lit.cfg.py because it has multiple copies, breaking mypy.\n        # - `bazel_test_runner.py` which depends on Bazel-specific imports.\n        # - Unit tests because they sometimes violate typing, such as by\n        #   assigning a mock to a function.\n        exclude: |\n          (?x)^(\n              proposals/(?!scripts/).*|\n              .*/lit\\.cfg\\.py|\n              examples/bazel_test_runner\\.py|\n              .*_test\\.py\n          )$\n  - repo: https://github.com/codespell-project/codespell\n    rev: 2ccb47ff45ad361a21071a7eedda4c37e6ae8c5a # frozen: v2.4.2\n    hooks:\n      - id: codespell\n        args: ['-I', '.codespell_ignore', '--uri-ignore-words-list', '*']\n        # Test data may contain intentional misspellings, as well as short,\n        # meaningless identifiers that codespell incorrectly identifies as\n        # typos but that we would want to detect in other contexts.\n        exclude: |\n          (?x)^(\n              .*/testdata/.*|\n              .*/fuzzer_corpus/.*\n          )$\n  - repo: https://github.com/google/pre-commit-tool-hooks\n    rev: efaea7c61c774c0b1a9805fd999e754a2d19dbd1 # frozen: v1.2.5\n    hooks:\n      - id: check-copyright\n        args:\n          - --copyright\n          - |+\n            Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n            Exceptions. See /LICENSE for license information.\n            SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n          - --custom_format\n          - '\\.(carbon|c|json|scss|ypp)(\\.tmpl)?$'\n          - ''\n          - '// '\n          - ''\n          - --custom_format\n          - '\\.(js|ts|mjs)$'\n          - '/*'\n          - ' * '\n          - ' */'\n          - --custom_format\n          - '\\.(l|lpp|y)$'\n          - '/*'\n          - ''\n          - '*/'\n          - --custom_format\n          - '\\.(plist)$'\n          - '<!--'\n          - ''\n          - '\\-->'\n          - --custom_format\n          - '\\.vim$'\n          - ''\n          - '\" '\n          - ''\n          - --custom_format\n          - '\\.scm$'\n          - ''\n          - '; '\n          - ''\n          - --custom_format\n          - '\\.lua$'\n          - ''\n          - '-- '\n          - ''\n        exclude: |\n          (?x)^(\n              .bazelversion|\n              .github/pull_request_template.md|\n              .python-version|\n              compile_flags.txt|\n              github_tools/requirements.txt|\n              third_party/.*|\n              utils/vscode/esbuild.js|\n              website/.ruby-version|\n              website/Gemfile.lock|\n              .*\\.def|\n              .*\\.png|\n              .*\\.svg|\n              .*/fuzzer_corpus/.*|\n              .*/testdata/.*\\.golden\n          )$\n      - id: check-links\n  - repo: local\n    hooks:\n      - id: check-build-graph\n        name: Check build graph\n        entry: scripts/check_build_graph.py\n        language: python\n        files: |\n          (?x)^(\n            .*BUILD.*|\n            .*MODULE.bazel.*|\n            .*WORKSPACE.*|\n            .*\\.bzl\n          )$\n\n# This excludes third-party code, and patches to third-party code.\nexclude: |\n  (?x)^(\n      MODULE.bazel.lock|\n      bazel/bazel_clang_tidy/.*\\.patch|\n      bazel/google_benchmark/.*\\.patch|\n      bazel/libpfm/.*\\.patch|\n      bazel/llvm_project/.*\\.patch|\n      third_party/examples/.*/carbon/.*|\n  )$\n"
  },
  {
    "path": ".prettierrc.yaml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nprintWidth: 80\nproseWrap: 'always'\nsingleQuote: true\ntabWidth: 2\ntrailingComma: 'es5'\nuseTabs: false\noverrides:\n  - files: '**/*.md'\n    options:\n      tabWidth: 4\n"
  },
  {
    "path": ".python-version",
    "content": "3.10\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"bazelbuild.vscode-bazel\",\n    \"bierner.github-markdown-preview\",\n    \"carbon-lang.carbon-vscode\",\n    \"esbenp.prettier-vscode\",\n    \"llvm-vs-code-extensions.vscode-clangd\",\n    \"ms-python.black-formatter\",\n    \"ms-python.python\"\n  ]\n}\n"
  },
  {
    "path": ".vscode/gdb_launch.json",
    "content": "{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"by-gdb\",\n      \"request\": \"launch\",\n      \"name\": \"file_test (gdb)\",\n      \"program\": \"bazel-bin/toolchain/testing/file_test\",\n      \"programArgs\": \"--file_tests=${relativeFile}\",\n      \"cwd\": \"${workspaceFolder}\",\n      \"env\": {\n        \"TEST_TARGET\": \"//toolchain/testing:file_test\",\n        \"TEST_TMPDIR\": \"/tmp\"\n      }\n    },\n    {\n      \"type\": \"by-gdb\",\n      \"request\": \"launch\",\n      \"name\": \"carbon compile (gdb)\",\n      \"program\": \"bazel-bin/toolchain/carbon\",\n      \"programArgs\": \"compile --phase=lower --dump-sem-ir --stream-errors ${relativeFile}\",\n      \"cwd\": \"${workspaceFolder}\"\n    }\n  ]\n}\n"
  },
  {
    "path": ".vscode/lldb_launch.json",
    "content": "{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"type\": \"lldb-dap\",\n      \"request\": \"launch\",\n      \"name\": \"file_test (lldb)\",\n      \"program\": \"bazel-bin/toolchain/testing/file_test\",\n      \"args\": [\"--file_tests=${relativeFile}\"],\n      \"debuggerRoot\": \"${workspaceFolder}\",\n      \"initCommands\": [\n        \"command script import external/+llvm_project+llvm-project/llvm/utils/lldbDataFormatters.py\",\n        \"command script import scripts/lldbinit.py\",\n        \"settings append target.source-map \\\".\\\" \\\"${workspaceFolder}\\\"\",\n        \"settings append target.source-map \\\"/proc/self/cwd\\\" \\\"${workspaceFolder}\\\"\",\n        \"settings set escape-non-printables false\",\n        \"settings set target.max-string-summary-length 10000\",\n        \"env TEST_TARGET=//toolchain/testing:file_test\",\n        \"env TEST_TMPDIR=/tmp\"\n      ]\n    },\n    {\n      \"type\": \"lldb-dap\",\n      \"request\": \"launch\",\n      \"name\": \"carbon compile (lldb)\",\n      \"program\": \"bazel-bin/toolchain/carbon\",\n      \"args\": [\n        \"compile\",\n        \"--phase=lower\",\n        \"--dump-sem-ir\",\n        \"--stream-errors\",\n        \"${relativeFile}\"\n      ],\n      \"debuggerRoot\": \"${workspaceFolder}\",\n      \"initCommands\": [\n        \"command script import external/+llvm_project+llvm-project/llvm/utils/lldbDataFormatters.py\",\n        \"command script import scripts/lldbinit.py\",\n        \"settings append target.source-map \\\".\\\" \\\"${workspaceFolder}\\\"\",\n        \"settings append target.source-map \\\"/proc/self/cwd\\\" \\\"${workspaceFolder}\\\"\",\n        \"settings set escape-non-printables false\",\n        \"settings set target.max-string-summary-length 10000\"\n      ]\n    }\n  ]\n}\n"
  },
  {
    "path": ".vscode/tasks.json",
    "content": "{\n  // See https://go.microsoft.com/fwlink/?LinkId=733558\n  // for the documentation about the tasks.json format\n  \"version\": \"2.0.0\",\n  \"tasks\": [\n    {\n      \"label\": \"saveAll\",\n      \"command\": \"${command:workbench.action.files.saveAll}\"\n    },\n    {\n      \"label\": \"autoupdate: toolchain tests\",\n      \"type\": \"process\",\n      \"command\": \"toolchain/autoupdate_testdata.py\",\n      \"group\": \"build\",\n      \"dependsOn\": [\"saveAll\"],\n      \"dependsOrder\": \"sequence\",\n      \"presentation\": {\n        \"echo\": false,\n        \"panel\": \"dedicated\",\n        \"showReuseMessage\": false,\n        \"clear\": true\n      },\n      \"problemMatcher\": {\n        \"owner\": \"cpp\",\n        \"fileLocation\": [\"relative\", \"${workspaceFolder}\"],\n        \"source\": \"autoupdate\",\n        \"pattern\": {\n          \"regexp\": \"^(.*):(\\\\d+):(\\\\d+):\\\\s+(warning|error):\\\\s+(.*)$\",\n          \"file\": 1,\n          \"line\": 2,\n          \"column\": 3,\n          \"severity\": 4,\n          \"message\": 5\n        }\n      }\n    }\n  ]\n}\n"
  },
  {
    "path": "BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nfilegroup(\n    name = \"clang_tidy_config\",\n    srcs = [\".clang-tidy\"],\n    visibility = [\"//visibility:public\"],\n)\n\n# `bazel run //:generate_compile_commands` to produce `compile_commands.json`.\nalias(\n    name = \"generate_compile_commands\",\n    actual = \"@wolfd_bazel_compile_commands//:generate_compile_commands\",\n)\n"
  },
  {
    "path": "CODEOWNERS",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# This file is only used for PR autoassignment. Branch protections don't enforce\n# it.\n#\n# Syntax:\n# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-syntax\n\n# Toolchain reviewers are used as a fallback.\n*                          @carbon-language/toolchain-reviewers\n\n# Key project documents should be reviewed by leads.\n/*.md                      @carbon-language/leads\n/LICENSE                   @carbon-language/leads\n/docs/project/evolution.md @carbon-language/leads\n/docs/project/goals.md     @carbon-language/leads\n/docs/project/principles/* @carbon-language/leads\n/docs/project/roadmap.md   @carbon-language/leads\n/proposals/*.md            @carbon-language/leads\n\n# Toolchain code.\n/toolchain                 @carbon-language/toolchain-reviewers\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of conduct\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Guidelines](#guidelines)\n-   [Conduct team](#conduct-team)\n    -   [Reporting conduct](#reporting-conduct)\n    -   [Filing a report](#filing-a-report)\n    -   [What happens after contacting the conduct team?](#what-happens-after-contacting-the-conduct-team)\n    -   [Appealing](#appealing)\n    -   [Special cases](#special-cases)\n-   [Enforcement action guidelines](#enforcement-action-guidelines)\n-   [Acknowledgements](#acknowledgements)\n\n<!-- tocstop -->\n\n## Guidelines\n\nThe Carbon community works to be welcoming and kind among itself and to others,\nwith a deep commitment to psychological safety, and we want to ensure that\ndoesn’t change as we grow and evolve. To that end, we have a few ground rules\nthat we ask all community members to adhere to:\n\n-   be welcoming,\n-   be friendly and patient,\n-   be considerate,\n-   be kind,\n-   be careful in the words that we choose,\n-   when we disagree, try to understand why, and\n-   recognize when progress has stopped, and take a step back.\n\nThis list isn't exhaustive. Rather, take it in the spirit in which it’s intended\n-- a guide to make it easier to communicate and participate in the community.\n\nThis code of conduct applies to all spaces managed by the Carbon project. This\nincludes chat systems, forums, emails (on lists or between members), issue\ntrackers, events, and any other spaces that the community uses for\ncommunication. It applies to all of your communication and conduct in these\nspaces, including emails, chats, things you say, slides, videos, posters, signs,\nor even t-shirts you display in these spaces.\n\nAll community members should help support our standards of acceptable behavior.\nEveryone is encouraged to speak up in response to any behavior that they deem\ninappropriate, threatening, offensive, or harmful. If you believe someone is\nviolating the code of conduct, please report it to the\n[conduct team](#conduct-team).\n\nMore detailed guidance on how to participate effectively in our community\nspaces:\n\n-   **Be welcoming.** We strive to be a community that welcomes and supports\n    people of all backgrounds and identities. This includes, but is not limited\n    to, members of any race, ethnicity, culture, national origin, color,\n    immigration status, social and economic class, educational level, sex,\n    sexual orientation, gender identity and expression, physical appearance,\n    age, size, family status, relationship status, political belief, religion or\n    lack thereof, and mental and physical ability.\n\n-   **Be friendly and patient.** We want to encourage people to participate in\n    our community in a constructive manner, so we can keep a friendly\n    atmosphere. This is especially important because many of our communication\n    tools on the Internet are low-fidelity and make it difficult to understand\n    each other. Be patient, acknowledge that we are all on a learning journey,\n    and stay supportive so that we can learn how to collaborate effectively as a\n    group.\n\n-   **Be considerate.** Your work will be used by other people, and you in turn\n    will depend on the work of others. Any decision you make will affect users\n    and colleagues, and you should take those consequences into account.\n    Remember that we’re a world-wide community, so you might not be\n    communicating in someone else’s primary language.\n\n-   **Be kind.** Not all of us will agree all the time, but disagreement is no\n    excuse for poor behavior and hurtful words. We might all experience some\n    frustration now and then, but we cannot allow that frustration to turn into\n    a personal attack. It’s important to remember that a community where people\n    feel threatened is not a productive one. Members of our community should be\n    kind when dealing with other members as well as with people outside the\n    Carbon community.\n\n-   **Be careful in the words that we choose and be kind to others.** Do not use\n    insults or put downs. Harassment and other exclusionary behaviors aren’t\n    acceptable. This includes, but is not limited to:\n\n    -   Violent threats or language directed against another person.\n    -   Discriminatory jokes and language.\n    -   Posting sexually explicit or violent material.\n    -   Posting, or threatening to post, other people’s personally identifying\n        information without their explicit permission (\"doxing\").\n    -   Personal insults, especially those using racist or sexist terms.\n    -   Unwelcome sexual attention.\n    -   Advocating for, or encouraging, any of the above behavior.\n    -   In general, if someone asks you to stop, then stop. Persisting after\n        being asked to stop is considered harassment.\n\n-   **When we disagree, we try to understand why.** Disagreements, both social\n    and technical, happen all the time, and Carbon is no exception. It is\n    important that we resolve disagreements and differing views constructively.\n    Remember that we’re different. The strength of the project comes from its\n    varied community: people from a wide range of backgrounds. Different people\n    have different perspectives on issues. Being unable to understand why\n    someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that\n    it is human to err and blaming each other doesn’t get us anywhere. Instead,\n    focus on helping to resolve issues and learning from mistakes.\n\n-   **Recognize when progress has stopped, and take a step back.** Regardless of\n    whether you're trying to resolve a disagreement or anything else, think\n    about whether you're making progress. Sometimes messaging doesn't give time\n    to think about a situation fully, and repeating positions can make people\n    defensive. Step back for a few minutes or hours to think through the issue\n    before responding again. Consider pulling in another community member to\n    give a fresh perspective. Maybe meet over VC instead. Switching approaches\n    can help resume progress.\n\nNo weapons are allowed at Carbon events. Weapons include, but are not limited\nto, explosives (including fireworks), guns, and large knives such as those used\nfor hunting or display, as well as any other item used for the purpose of\ncausing injury or harm to others.\n\nIn rare cases, violations of this code _outside_ of these spaces may affect, and\nbe detrimental to, a person’s ability to participate _within_ these spaces.\nImportant examples include, but are not limited to,\n[sexual and gender-based violence and/or harassment](https://hr.un.org/sites/hr.un.org/files/SEA%20Glossary%20%20%5BSecond%20Edition%20-%202017%5D%20-%20English_0.pdf),\n[hate crimes](https://hatecrime.osce.org/), and\n[hate speech](https://www.un.org/en/genocideprevention/documents/UN%20Strategy%20and%20Plan%20of%20Action%20on%20Hate%20Speech%2018%20June%20SYNOPSIS.pdf).\nAlthough we do not conduct proactive research, we have an obligation to respond\nto reported and, to the extent possible, corroborated concerns. Our motivations\nare not rooted in responding punitively, or holding people accountable. Instead,\nour response will be focused on how the continued participation of the person at\nissue could impact the community's safety, well-being, and inclusivity. It is\nour priority to remain a welcoming community to victims as well as groups\nsubjected to systemic marginalization or underrepresentation.\n\nIf you have questions, please feel free to ask on Discord,\n[GitHub](https://github.com/carbon-language/carbon-lang/discussions), or contact\nany member of the conduct team directly.\n\n## Conduct team\n\nThe conduct team can be emailed at conduct@carbon-lang.dev.\n\nMore details about the team, its current members and its management are on the\n[conduct team page](/docs/project/teams/conduct_team.md).\n\n### Reporting conduct\n\nIf you believe someone is violating the code of conduct, you can report it\nseveral ways, including:\n\n-   On [Discord](https://discord.gg/ZjVdShJDAs), DM ModMail. It may require\n    confirmation that you want help on the Carbon Language server. An available\n    moderator will respond.\n    -   Look for ModMail in the user list under \"Bots\", and click the name to\n        send a direct message.\n    -   Moderators can also be found and messaged similarly, but ModMail is\n        preferred.\n-   Emailing the [conduct team](#conduct-team) directly at\n    conduct@carbon-lang.dev. Bear in mind that\n    [responses may take time](#what-happens-after-contacting-the-conduct-team).\n\n**All reports will be kept confidential**, and are only used by the conduct team\nto address conduct issues and keep the Carbon community safe and inclusive.\n\nPlease send reports concerning a member of the conduct team directly to other\nmembers of the conduct team. This allows discussion of the complaint to more\neasily exclude the concerned member as a [special case](#special-cases).\n\nIf you believe anyone is in **physical danger**, please notify appropriate law\nenforcement first. If you are unsure what law enforcement agency is appropriate,\nplease include this in your report and we will attempt to notify them.\n\nIf the violation occurs at an event and requires immediate attention, you can\nalso reach out to any of the event organizers or staff. Event organizers and\nstaff will be prepared to handle the incident and be able to help. If you cannot\nfind one of the organizers, the venue staff can locate one for you. Specific\nevent information will include detailed contact information for that event. In\nperson reports will still be kept confidential exactly as above, but also feel\nfree to email the conduct team, anonymously if needed.\n\n### Filing a report\n\nReports can be as formal or informal as needed for the situation at hand. If\npossible, please include as much information as you can. If you feel\ncomfortable, please consider including:\n\n-   Your contact info, so we can get in touch with you if we need to follow up.\n-   Names -- real, nicknames, or pseudonyms -- of any individuals involved. If\n    there were other witnesses besides you, please try to include them as well.\n-   When and where the incident occurred. Please be as specific as possible.\n-   Your account of what occurred, including any private chat logs or email.\n-   Links for any public records, including community discussions.\n-   Any extra context for the incident.\n-   Whether you believe this incident is ongoing.\n-   Any other information you believe we should have.\n\n### What happens after contacting the conduct team?\n\nYou will receive a reply from the conduct team acknowledging receipt within 1\nbusiness day, and we will aim to respond much quicker than that.\n\nThe conduct team will review the incident as soon as possible and try to\ndetermine:\n\n-   What happened and who was involved.\n-   Whether this event constitutes a code of conduct violation.\n-   Whether this is an ongoing situation, or if there is a threat to anyone’s\n    physical safety.\n\nIf this is determined to be an ongoing incident or a threat to physical safety,\nthe conduct team's immediate priority will be to protect everyone involved. This\nmeans we may delay an \"official\" response until we believe that the situation\nhas ended and that everyone is physically safe.\n\nThe conduct team will try to contact other parties involved or witnessing the\nevent to gain clarity on what happened and understand any different\nperspectives.\n\nOnce the conduct team has a complete account of the events they will make a\ndecision as to how to respond. Responses may include:\n\n-   Nothing, if no violation occurred or it has already been appropriately\n    resolved.\n-   One or more [enforcement actions](#enforcement-action-guidelines).\n-   Involvement of relevant law enforcement if appropriate.\n\nIf the situation is not resolved within one week, we’ll respond to the original\nreporter with an update and explanation.\n\nOnce we’ve determined our response, we will separately contact the original\nreporter and other individuals to let them know what actions, if any, we’ll be\ntaking. We will take into account feedback from the individuals involved on the\nappropriateness of our response, but we don’t guarantee we’ll act on it.\n\nAfter any incident, the conduct team will make a report on the situation to the\nCarbon leads. The Carbon leads may choose to make a public statement about the\nincident. If that’s the case, the identities of anyone involved will remain\nconfidential unless instructed otherwise by those individuals.\n\n### Appealing\n\nOnly permanent resolutions, such as bans, or requests for public actions may be\nappealed. To appeal a decision of the conduct team, contact the\n[Carbon leads](docs/project/evolution.md#carbon-leads-1) with your appeal and\nthey will review the case.\n\nIn general, it is **not** appropriate to appeal a particular decision in public\nareas of GitHub or Discord. Doing so would involve disclosure of information\nwhich should remain confidential. Disclosing this kind of information publicly\nmay be considered a separate and, potentially, more serious violation of the\nCode of Conduct. This is not meant to limit discussion of the Code of Conduct,\nthe conduct team itself, or the appropriateness of responses in general, but\n**please** refrain from mentioning specific facts about cases without the\nexplicit permission of all parties involved.\n\n### Special cases\n\nIf a complaint is raised against a member of the conduct team or Carbon leads,\nthey will be excluded from conduct discussion and decisions, including appeals.\nThey will only be included as needed for an involved party, such as to get their\nperspective or to notify them of decisions. Such complaints may lead to a\nmember's responsibilities being revoked.\n\n## Enforcement action guidelines\n\nThe conduct team, moderators, and event organizers have the right and\nresponsibility to remove, edit, or reject comments, commits, code, wiki edits,\nissues, and other contributions that are not aligned to this Code of Conduct.\nThey will communicate reasons for moderation decisions when appropriate.\n\nThe conduct team may take additional action they deem appropriate for any\nviolation of this Code of Conduct using these guidelines based on the behavior\ninvolved:\n\n1.  **Correction**\n    -   **Behavior:** Use of inappropriate language or other minor violations of\n        the code of conduct.\n    -   **Action:** A private, written message providing clarity around the\n        nature of the violation and an explanation of why the behavior was\n        inappropriate. A public apology may be requested.\n1.  **Warning**\n    -   **Behavior:** A code of conduct violation through a single moderate\n        incident, or a series of minor violations.\n    -   **Action:** In addition to the correction action, a temporary\n        restriction forbidding interaction with the people involved for a\n        specified period of time, including unsolicited interaction with the\n        conduct team. Violating these terms may lead to a ban.\n1.  **Temporary ban**\n    -   **Behavior:** A serious violation of the code of conduct, including\n        sustained inappropriate behavior.\n    -   **Action:** In addition to the warning action, a temporary ban from use\n        of Carbon's community spaces for a specified period of time. External\n        channels, such as social media, should not be used to bypass these\n        restrictions during the temporary ban. Violating these terms may lead to\n        a permanent ban.\n1.  **Permanent ban**\n    -   **Behavior:** Demonstrating a pattern of violation of the code of\n        conduct.\n    -   **Action:** A permanent ban from use of Carbon's community spaces.\n\n## Acknowledgements\n\nThis code is based on the\n[LLVM Code of Conduct](https://llvm.org/docs/CodeOfConduct.html), the\n[Django Project Code of Conduct](https://github.com/django/code-of-conduct), the\n[Speak Up! project](http://web.archive.org/web/20141109123859/http://speakup.io/coc.html),\nand the\n[Contributor Covenant version 2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct/).\nMany thanks to all of these projects for their work helping build effective\ntools for open source communities.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Ways to contribute](#ways-to-contribute)\n    -   [Contributing to the language design](#contributing-to-the-language-design)\n        -   [Comment on proposals](#comment-on-proposals)\n        -   [Contribute design ideas to Carbon](#contribute-design-ideas-to-carbon)\n    -   [Contributing to the language implementation](#contributing-to-the-language-implementation)\n        -   [Review and comment on Pull Requests (no code)](#review-and-comment-on-pull-requests-no-code)\n        -   [Implement Carbon's design](#implement-carbons-design)\n        -   [Triage, analyze or address bugs](#triage-analyze-or-address-bugs)\n-   [How to become a contributor to Carbon](#how-to-become-a-contributor-to-carbon)\n    -   [Contributor License Agreements (CLAs)](#contributor-license-agreements-clas)\n        -   [Future CLA plans](#future-cla-plans)\n    -   [Collaboration systems](#collaboration-systems)\n        -   [Getting access](#getting-access)\n    -   [Contribution tools](#contribution-tools)\n        -   [Using AI-based contribution tools](#using-ai-based-contribution-tools)\n    -   [Contribution guidelines and standards](#contribution-guidelines-and-standards)\n        -   [Guidelines and philosophy for contributions](#guidelines-and-philosophy-for-contributions)\n        -   [How to say things](#how-to-say-things)\n            -   [Make your point concisely](#make-your-point-concisely)\n-   [Style](#style)\n    -   [Google Docs and Markdown](#google-docs-and-markdown)\n    -   [Other files](#other-files)\n-   [License](#license)\n    -   [Google Docs](#google-docs)\n    -   [Markdown](#markdown)\n    -   [Other files](#other-files-1)\n-   [Workflow](#workflow)\n-   [Acknowledgements](#acknowledgements)\n\n<!-- tocstop -->\n\n## Overview\n\nThank you for your interest in contributing to Carbon! There are many ways to\ncontribute, and we appreciate all of them. If you have questions, please feel\nfree to ask on [Discord](https://discord.gg/ZjVdShJDAs) `#contributing-help`\nchannel or [GitHub](https://github.com/carbon-language/carbon-lang/discussions).\n\nEveryone who contributes to Carbon is expected to:\n\n-   Read and follow the [Code of Conduct](CODE_OF_CONDUCT.md). We expect\n    everyone in our community to be welcoming, helpful, and respectful.\n-   Ensure you have signed the\n    [Contributor License Agreement (CLA)](https://cla.developers.google.com/).\n    We need this to cover some legal bases.\n\nWe also encourage anyone interested in contributing to check out all the\ninformation here in our contributing guide, especially the\n[guidelines and philosophy for contributions](#guidelines-and-philosophy-for-contributions)\n\n## Ways to contribute\n\n### Contributing to the language design\n\n#### Comment on proposals\n\nIf you're looking for a quick way to contribute, commenting on proposals is a\nway to provide proposal authors with a breadth of feedback. The\n[\"leads questions\" label](https://github.com/carbon-language/carbon-lang/issues?q=is%3Aissue+is%3Aopen+label%3A%22leads+question%22)\nhas questions the community is looking for a decision on. The\n[list of open proposals](https://github.com/carbon-language/carbon-lang/pulls?q=is%3Apr+is%3Aopen+label%3A%22proposal+rfc%22)\nwill have more mature proposals that are nearing a decision. For more about the\ndifference, see the [evolution process](docs/project/evolution.md).\n\nWhen giving feedback, please keep comments positive, constructive, and\n[concise](#make-your-point-concisely). Our goal is to use community discussion\nto improve proposals and assist authors.\n\n#### Contribute design ideas to Carbon\n\nIf you have ideas for Carbon, we encourage you to discuss it with the community,\nand potentially prepare a proposal for it. Ultimately, any changes or\nimprovements to Carbon will need to turn into a proposal and go through our\n[evolution process](docs/project/evolution.md).\n\nIf you do start working on a proposal, keep in mind that this requires a time\ninvestment to discuss the idea with the community, get it reviewed, and\neventually implemented. A good starting point is to read through the\n[evolution process](docs/project/evolution.md). We encourage discussing the idea\nearly, before even writing a proposal, and the process explains how to do that.\n\n### Contributing to the language implementation\n\n#### Review and comment on Pull Requests (no code)\n\nHelping with\n[pull requests](https://github.com/carbon-language/carbon-lang/pulls) review is\na good way to provide feedback, while getting acquainted with the code base.\n\n#### Implement Carbon's design\n\nThe implementation of the Carbon language design is currently focused on the\n[Carbon toolchain](/toolchain/) (see Carbon\n[toolchain issues](https://github.com/carbon-language/carbon-lang/issues?q=is%3Aissue+is%3Aopen+label%3Atoolchain))\n\n**Some issues are also marked as\n[\"good first issues\"](https://github.com/carbon-language/carbon-lang/labels/good%20first%20issue)**.\nThese are intended to be a good place to start contributing.\n\nTo pick up a \"good first issue\", check to make sure there's no in-flight pull\nrequest on the issue, and then start working on it. We don't assign issues to\nnew contributors because some people have different time constraints, and we\nwant new contributors to feel welcome to pick the issue up when it may not be\nmaking progress. Even if someone else merges a fix before you, these issues\nshould be a quick and helpful way to start learning how Carbon is built,\nbuilding towards larger contributions.\n\n#### Triage, analyze or address bugs\n\nAs Carbon's design and implementation take shape, we'll inevitably encounter\nplenty of bugs. Helping us triage, analyze, and address them is always a great\nway to get involved. See\n[open issues on GitHub](https://github.com/carbon-language/carbon-lang/issues).\n\nWhen triaging issues, we typically won't assign issues because we want to be\nconfident that contributors who have an issue assigned to them are planning for\nthe amount of time it will take, which requires familiarity. Contributors with\nwrite access are expected to have that familiarity and may assign issues to\nthemselves.\n\n## How to become a contributor to Carbon\n\n### Contributor License Agreements (CLAs)\n\nWe'd love to accept your documentation, pull requests, and comments! Before we\ncan accept them, we need you to cover some legal bases.\n\nPlease fill out either the individual or corporate CLA.\n\n-   If you are an individual contributing to spec discussions or writing\n    original source code and you're sure you own the intellectual property, then\n    you'll need to sign an\n    [individual CLA](https://code.google.com/legal/individual-cla-v1.0.html).\n-   If you work for a company that wants to allow you to contribute your work,\n    then you'll need to sign a\n    [corporate CLA](https://code.google.com/legal/corporate-cla-v1.0.html).\n\nFollow either of the two links above to access the appropriate CLA and\ninstructions for how to sign and return it. Once we receive it, we'll be able to\naccept your documents, comments and pull requests.\n\n**_NOTE_**: Only original content from you and other people who have signed the\nCLA can be accepted as Carbon contributions: this covers GitHub (including both\ncode and discussion), Google Docs, and Discord.\n\n#### Future CLA plans\n\nInitially, Carbon is bootstrapping using Google's CLA. We are planning to create\nan open source foundation and transfer all Carbon-related rights to it; our goal\nis for the foundation setup to be similar to other open source projects, such as\nLLVM or Kubernetes.\n\n### Collaboration systems\n\nWe use a few systems for collaboration which contributors should be aware of.\n\nBefore using these systems, everyone must sign the CLA. They are all governed by\nthe Code of Conduct.\n\n-   [The GitHub carbon-language organization](https://github.com/carbon-language)\n    is used for our repositories.\n-   [Discord](https://discord.gg/ZjVdShJDAs) is used for chat.\n-   [A shared Google Drive](https://drive.google.com/drive/folders/1aC5JJ5EcI8B7cgVDrLvO7WNw97F0LpS2)\n    is used for all of our Google Docs, particularly proposal drafts.\n-   [Google Calendar](https://calendar.google.com/calendar/embed?src=c_07td7k4qjq0ssb4gdl6bmbnkik%40group.calendar.google.com)\n    is used for meeting invites and project reminders. Contributors may add\n    calendar entries for meetings added to discuss details. Standard entries\n    have\n    [minutes](https://drive.google.com/drive/folders/1VssO6kn9-HeKfzPDqBDR0Sy5CUE0OnSs)\n    and include:\n    -   The weekly sync, where contributors are welcome.\n    -   Open discussions, which are unstructured meeting slots used for\n        discussing proposals, tooling, and other Carbon topics based on who\n        attends.\n\n#### Getting access\n\nOur collaboration systems are all viewable publicly, and most can be joined\nwithout particular requests. However, some require extra permissions, such as\nediting Google Docs, joining meetings, or some details of the proposal process.\n\nWhen requesting any of the following access, please provide a reason for the\naccess. All requests require a\n[signed CLA](#contributor-license-agreements-clas).\n\n-   Google Docs/Calendar access groups:\n    -   **Commenter** access:\n        [join group](https://groups.google.com/a/carbon-lang.dev/g/commenters/about)\n        -   [Google Docs](https://drive.google.com/drive/folders/1aC5JJ5EcI8B7cgVDrLvO7WNw97F0LpS2):\n            Comment on files.\n        -   [Google Calendar](https://calendar.google.com/calendar/embed?src=c_07td7k4qjq0ssb4gdl6bmbnkik%40group.calendar.google.com):\n            View event details.\n    -   **Contributor** access:\n        [join group](https://groups.google.com/a/carbon-lang.dev/g/contributors/about)\n        -   [Google Docs](https://drive.google.com/drive/folders/1aC5JJ5EcI8B7cgVDrLvO7WNw97F0LpS2):\n            Add, edit, and comment on files.\n        -   [Google Calendar](https://calendar.google.com/calendar/embed?src=c_07td7k4qjq0ssb4gdl6bmbnkik%40group.calendar.google.com):\n            View and edit event details.\n    -   After you apply to join, please let us know on\n        [#access-requests](https://discord.com/channels/655572317891461132/1006221387574292540);\n        we don't get notifications otherwise.\n-   GitHub Label/project contributor access:\n    [ask on #access-requests](https://discord.com/channels/655572317891461132/1006221387574292540)\n    -   Don't forget to mention your GitHub username.\n    -   Used by the proposal process.\n\nIf you simply want to chime in on GitHub or Discord, none of this is needed. If\nyou're interested in joining meetings, ask for commenter access. If you're\ntrying to write proposals, both types of contributor access will help.\n\n### Contribution tools\n\nPlease see our [contribution tool](/docs/project/contribution_tools.md)\ndocumentation for information on setting up a git client for Carbon development,\nas well as helpful tooling that will ease the contribution process. For example,\n[pre-commit](https://pre-commit.com) is used to simplify\n[code review](/docs/project/code_review.md).\n\n#### Using AI-based contribution tools\n\nIf you are using an AI assistant to help you contribute, or if you are an AI\nassistant yourself, please consult [GEMINI.md](/GEMINI.md) for high-density\ntechnical context and tips.\n\nAll submissions to Carbon need to follow our\n[Contributor License Agreement (CLA)](#contributor-license-agreements-clas),\nwhich covers any original work of authorship included in the submission. This\ndoesn't prohibit the use of coding assistance tools, including tool-, AI-, or\nmachine-generated code, as long as these submissions abide by the CLA's\nrequirements.\n\nAll contributions, regardless of what tools are used, are also still the\nresponsibility of the operator of these tools and subject to normal code review\nand our [guidelines and standards](#contribution-guidelines-and-standards)\nbelow. We also emphasize two additional requirements for contributors operating\nor using AI-based tools:\n\n1. **Contributions should not become extractive of the project and community**:\n   the value added should outweigh the overhead of landing the contribution. The\n   overhead of landing contributions ranges from code review, to discussions,\n   distractions from the current project priorities, or growing maintenance\n   burden without growing maintainers.\n\n2. **Each PR should be transparent about the tooling used** in proportion to how\n   much of the PR was produced by the tool and whether the tool is a standard\n   one for the project. For example, formatting with the standard tools is\n   reasonable to assume without further comment. But if a PR is largely derived\n   from running a specific Python script, regular expression, or AI-based tool\n   over the codebase, we ask that its commit message is transparent about this\n   and include a description of how the tool was used to formulate the change.\n   For PRs largely derived from AI-based tooling, we suggest following the\n   pattern established by the Fedora Project to mark commits with\n   `Assisted-by: ...`.\n\nOur policies and practices here are inspired by and aim to be roughly compatible\nwith several other open source projects:\n\n-   [Fedora Project's policy](https://docs.fedoraproject.org/en-US/council/policy/ai-contribution-policy/)\n-   [LLVM Developer Policy around AI generated code](https://llvm.org/docs/DeveloperPolicy.html#ai-generated-contributions)\n\nAs the open source community evolves and learns how best to integrate these\ntools into project and development workflows, we expect to reflect that with\nupdates and improvements here.\n\n### Contribution guidelines and standards\n\nAll documents and pull requests must be consistent with the guidelines and\nfollow the Carbon documentation and coding styles.\n\n#### Guidelines and philosophy for contributions\n\n-   For **both** documentation and code:\n\n    -   When the Carbon team accepts new documentation or features, to Carbon,\n        by default they take on the maintenance burden. This means they'll weigh\n        the benefit of each contribution against the cost of maintaining it.\n    -   The appropriate [style](#style) is applied.\n    -   The [license](#license) is present in all contributions.\n    -   [Code review](/docs/project/code_review.md) is used to improve the\n        correctness, clarity, and consistency of all contributions.\n        -   Please avoid rebasing PRs after receiving comments; it can break\n            viewing of the comments in files.\n\n-   For documentation:\n\n    -   All documentation is written for clarity and readability. Beyond fixing\n        spelling and grammar, this also means content is worded to be accessible\n        to a broad audience.\n    -   Substantive changes to Carbon follow the\n        [evolution process](docs/project/evolution.md). Pull requests are only\n        sent after the documentation changes have been accepted by the reviewing\n        team.\n    -   Typos or other minor fixes that don't change the meaning of a document\n        do not need formal review, and are often handled directly as a pull\n        request.\n\n-   For code:\n\n    -   New features should have a documented design that has been approved\n        through the [evolution process](docs/project/evolution.md). This\n        includes modifications to preexisting designs.\n    -   Bug fixes and mechanical improvements don't need this.\n    -   All new features include unit tests, as they help to (a) document and\n        validate concrete usage of the feature and its edge cases, and (b) guard\n        against future breaking changes to lower the maintenance cost.\n    -   Bug fixes also generally include unit tests, because the presence of\n        bugs usually indicates insufficient test coverage.\n    -   Unit tests must pass with the changes.\n    -   If some tests fail for unrelated reasons, we wait until they're fixed.\n        It helps to contribute a fix!\n    -   Code changes should be made with API compatibility and evolvability in\n        mind.\n    -   Keep in mind that code contribution guidelines are incomplete while we\n        start work on Carbon, and may change later.\n\n#### How to say things\n\n-   Treat others with respect.\n-   Recognize that other points of view are valid, and most decisions are about\n    choosing the best set of trade-offs or closest alignment with Carbon's goals\n    since there usually isn't a single best answer. It is important to frame\n    feedback and discussion about someone else's proposal under the assumption\n    that they too have deep experience in the area but may have come to a\n    different conclusion.\n-   Be clear when something is an opinion by using \"I\" or \"me\":\n    -   Not as helpful: \"`foo` is objectively better word to use\"\n    -   More helpful: \"I find `bar` confusing since it has this alternate\n        meaning, I think `foo` is clearer.\"\n-   It can be helpful to define your terms.\n\nWhen trying to make a point, please employ these strategies to make your\nargument _effective_ and _helpful_:\n\n-   Focus should be on explaining the basis by which others can come to a\n    conclusion. Generally this means connecting a potential solution to the use\n    cases it helps with.\n-   Be specific and concrete, using examples to demonstrate the benefits and\n    disadvantages of the different options\n    -   Minimally helpful: \"I like &lt;X>\", \"Carbon should have feature &lt;Y>\"\n    -   More helpful: \"I think Carbon should have feature &lt;Z>, it would mean\n        &lt;this example> would be written &lt;like this> instead of &lt;like\n        that>.\" (Assuming the reader will think the example is representative of\n        an important class of use cases.)\n    -   Very helpful: \"If we go with approach &lt;X>, it helps with problem\n        &lt;P> in &lt;this example> of use case &lt;A>. It doesn't help with use\n        case &lt;B>, but that can be better solved by &lt;Y>, as can be seen in\n        &lt;other example>.\"\n    -   Very helpful: \"Yes &lt;X> gives a nice answer in that case, but it has a\n        problem / I don't see how it applies in &lt;this other situation>.\"\n-   Explain the reasoning by which you can come to your conclusion\n    -   Avoid [fallacies](https://en.wikipedia.org/wiki/List_of_fallacies) like\n        [arguing from authority](https://en.wikipedia.org/wiki/Argument_from_authority)\n    -   Don't expect people to read long works to understand your point\n\nIf someone questions or argues with your point, try to directly address the\npoints being made. Try not to step backwards or switch to a more general or more\nmeta level as that can seem like you're evading the question.\n\n##### Make your point concisely\n\n-   **Asking questions is OK**: Asking questions about a particular discussion\n    is almost always OK. If you're worried the questions might be more about\n    _background_ and might be long enough to get distracting, you can always ask\n    them in some of our dedicated spaces like `#language-questions` on Discord.\n-   **Favor new and relevant information**: When sharing ideas and opinions in\n    community discussions, it is important to do so in a way that both _adds new\n    information_ in some way/shape/form, makes sure that information is\n    _relevant_ to the discussion, and avoids _repetition_. This means reviewing\n    what you write before posting a larger response, and editing it down to just\n    the points you want to make that have not already been made, and any new\n    arguments supporting those points.\n-   **Be inclusive by staying concise**: We need to be mindful that writing many\n    paragraphs of extra text is going to exclude people. Some people can be\n    excluded from consuming the conversation, either because a wall of text is\n    too intimidating to read, or they don't have the time or bandwidth to wade\n    through the extra text to find the new information being conveyed. It can\n    also drown out other contributors\n-   **Prefer upvote to repetition**: One person saying \"I don't like this\n    feature\" is useful, and that same message with 100 upvotes is extremely\n    useful, but 100 people writing separate messages saying \"I don't like this\n    feature\" is not. Emoji reactions are available in both Discord and GitHub\n    and should be used for this purpose in both.\n\nIt is also okay to do things like ask a question to get clarification about what\nsomeone has said or to solicit opinions about various options. Just be\nrespectful, and don't drown out other discussion.\n\n## Style\n\n### Google Docs and Markdown\n\nChanges to Carbon documentation follow the\n[Google developer documentation style guide](https://developers.google.com/style).\n\nMarkdown files should additionally use [Prettier](https://prettier.io) for\nformatting, which we automate with\n[pre-commit](/docs/project/contribution_tools.md#main-tools).\n\nOther style points to be aware of are:\n\n-   Whereas the Google developer documentation style guide\n    [says to use an em dash](https://developers.google.com/style/dashes)\n    (`text—text`), we are using a double-hyphen with surrounding spaces\n    (`text -- text`). We are doing this because we frequently read Markdown with\n    fixed-width fonts where em dashes are not clearly visible.\n-   Prefer the term \"developers\" when talking about people who would write\n    Carbon code. We expect the Carbon's community to include people who think of\n    themselves using many titles, including software developers, software\n    engineers, systems engineers, reliability engineers, data scientists,\n    computer scientists, programmers, and coders. We're using \"developers\" to\n    succinctly cover the variety of titles.\n\n### Other files\n\nIf you're not sure what style to use, please ask on Discord or GitHub.\n\n## License\n\nA license is required at the top of all documents and files.\n\n### Google Docs\n\nGoogle Docs all use\n[this template](https://docs.google.com/document/d/1tAwE0230PDxweVruHUVY6DSfSnrJF2LnLOWXQYqNJuI/template/preview?usp=sharing&resourcekey=0-zsrwCWP7ictbxhCuePk-fw).\nIt puts the license at the top of every page if printed.\n\n### Markdown\n\nMarkdown files always have at the top:\n\n```\n# DOC TITLE\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n```\n\nFor example, see the top of\n[CONTRIBUTING.md](https://github.com/carbon-language/carbon-lang/raw/trunk/CONTRIBUTING.md)'s\nraw content.\n\n### Other files\n\nEvery file type uses a variation on the same license text (\"Apache-2.0 WITH\nLLVM-exception\") with similar formatting. If you're not sure what text to use,\nplease ask on Discord or GitHub.\n\n## Workflow\n\nCarbon repositories all follow a common\n[pull-request workflow](docs/project/pull_request_workflow.md) for landing\nchanges. It is a trunk-based development model that emphasizes small,\nincremental changes and preserves a simple linear history.\n\n## Acknowledgements\n\nCarbon's Contributing guidelines are based on\n[TensorFlow](https://github.com/tensorflow/tensorflow/blob/master/CONTRIBUTING.md)\nand [Flutter](https://github.com/flutter/flutter/blob/master/CONTRIBUTING.md)\nguidelines. Many thanks to these communities for their help in providing a\nbasis.\n"
  },
  {
    "path": "GEMINI.md",
    "content": "# Gemini & AI assistant guide for Carbon\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis document provides high-density technical context for AI assistants (and\nhumans!) contributing to the Carbon Language project. If you are an AI\nassistant, **read this first** to avoid common pitfalls.\n\n## Table of contents\n\n-   [General instructions](#general-instructions)\n-   [Project structure](#project-structure)\n-   [Toolchain development](#toolchain-development)\n\n## General instructions\n\n-   **Communication**: Be concise, professional, and technical. Use GitHub-style\n    markdown.\n-   **Verification**: Always run relevant tests.\n-   **Tool usage**: Use web search for any research outside the immediate\n    codebase or KIs.\n\n## Project structure\n\n-   **[`common/`](common/)**: Common C++ utilities used across the project.\n-   **[`core/`](core/)**: The Carbon standard library (Core).\n-   **[`docs/`](docs/)**: Project documentation, design, and style guides.\n-   **[`examples/`](examples/)**: Example Carbon programs and code snippets.\n-   **[`proposals/`](proposals/)**: Evolution proposals.\n-   **[`testing/`](testing/)**: Testing utilities and infrastructure.\n-   **[`toolchain/`](toolchain/)**: The C++ implementation of the compiler\n    (Toolchain).\n\n## Tool usage\n\nSee the \"Tool usage\" skill for instructions on what tools to use in the\ncarbon-lang project.\n\n## Code style\n\nSee the \"Code style\" skill for instructions on formatting, style guides, and\ncode conventions to follow.\n\n## Toolchain development\n\nSee the \"Toolchain Development\" skill for instructions on architecture,\nbuilding, testing, debugging, C++ patterns, and common pitfalls.\n"
  },
  {
    "path": "LICENSE",
    "content": "==============================================================================\nThe Carbon language is under the Apache License v2.0 with LLVM Exceptions:\n==============================================================================\n\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n    1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n    2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n    3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n    4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n    5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n    6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n    7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n    8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n    9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n    END OF TERMS AND CONDITIONS\n\n    APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n    Copyright [yyyy] [name of copyright owner]\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n\n---- LLVM Exceptions to the Apache 2.0 License ----\n\nAs an exception, if, as a result of your compiling your source code, portions\nof this Software are embedded into an Object form of such source code, you\nmay redistribute such embedded portions in such Object form without complying\nwith the conditions of Sections 4(a), 4(b) and 4(d) of the License.\n\nIn addition, if you combine or link compiled forms of this Software with\nsoftware that is licensed under the GPLv2 (\"Combined Software\") and if a\ncourt of competent jurisdiction determines that the patent provision (Section\n3), the indemnity provision (Section 9) or other Section of the License\nconflicts with the conditions of the GPLv2, you may retroactively and\nprospectively choose to deem waived or otherwise exclude such Section(s) of\nthe License, but only in their entirety and only with respect to the Combined\nSoftware.\n\n==============================================================================\nSoftware from third parties included in the Carbon language:\n==============================================================================\nThe Carbon language contains third party software which is under different\nlicense terms. All such code will be identified clearly using at least one of\ntwo mechanisms:\n1) It will be in a separate directory tree with its own `LICENSE.txt` or\n   `LICENSE` file at the top containing the specific license and restrictions\n   which apply to that software, or\n2) It will contain specific license and restriction terms at the top of every\n   file.\n"
  },
  {
    "path": "MODULE.bazel",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Bazel modules.\n\n`MODULE.bazel.lock` may change locally when `bazel` is executed. This means one\nof:\n\n1.  An input is changing, typically `MODULE.bazel` or `.bazelversion`.\n    -   Running `bazel mod deps` provides a canonical update to\n        `MODULE.bazel.lock`; include the changes.\n    -   GitHub test actions may also identify platform-specific lockfile\n        updates.\n2.  The host platform hasn't yet been added to the lock file.\n    -   Platforms tested with GitHub actions are kept up-to-date. Other\n        platforms may fall out of sync due to `bazel` or dependency changes,\n        and should be updated with a PR the same way a platform is added.\n    -   Running `bazel mod deps` provides a canonical update to\n        `MODULE.bazel.lock`; create a PR with those changes in order to include\n        the host platform.\n\nFor updates, run `scripts/query_module_versions.py` to list the latest package\nversions.\n\"\"\"\n\nmodule(name = \"carbon\")\n\nbazel_dep(name = \"abseil-cpp\", version = \"20260107.1\")\nbazel_dep(name = \"bazel_skylib\", version = \"1.9.0\")\nbazel_dep(name = \"boost.unordered\", version = \"1.90.0.bcr.1\")\nbazel_dep(name = \"google_benchmark\", version = \"1.9.5\")\nbazel_dep(name = \"googletest\", version = \"1.17.0.bcr.2\")\nbazel_dep(name = \"libpfm\", version = \"4.13.0\")\nbazel_dep(name = \"re2\", version = \"2025-11-05.bcr.1\")\nbazel_dep(name = \"rules_cc\", version = \"0.2.17\")\nbazel_dep(name = \"rules_pkg\", version = \"1.2.0\")\nbazel_dep(name = \"rules_shell\", version = \"0.6.1\")\nbazel_dep(name = \"tcmalloc\", version = \"0.0.0-20250927-12f2552\")\nbazel_dep(name = \"tree-sitter-bazel\", version = \"0.26.5\")\n\nbazel_dep(name = \"wolfd_bazel_compile_commands\", version = \"0.5.2\", dev_dependency = True)\nbazel_dep(name = \"bazel_clang_tidy\", dev_dependency = True)\ngit_override(\n    module_name = \"bazel_clang_tidy\",\n    # HEAD as of 2026-01-28.\n    commit = \"c4d35e0d0b838309358e57a2efed831780f85cd0\",\n    remote = \"https://github.com/erenon/bazel_clang_tidy.git\",\n)\n\nbazel_cc_toolchain = use_extension(\n    \"//bazel/cc_toolchains:clang_configuration.bzl\",\n    \"clang_toolchain_extension\",\n)\nuse_repo(bazel_cc_toolchain, \"bazel_cc_toolchain\")\n\nregister_toolchains(\"@bazel_cc_toolchain//:all\")\n\n# TODO: Trying out `wolfd_bazel_compile_commands`, figure out if there are\n# issues. Once people have had a chance to try and check for problems, remove\n# one or the other.\nbazel_dep(name = \"hedron_compile_commands\", dev_dependency = True)\ngit_override(\n    module_name = \"hedron_compile_commands\",\n    # HEAD as of 2026-01-28.\n    commit = \"abb61a688167623088f8768cc9264798df6a9d10\",\n    remote = \"https://github.com/hedronvision/bazel-compile-commands-extractor.git\",\n)\n\n# Required for llvm-project.\nbazel_dep(name = \"platforms\", version = \"1.0.0\")\nbazel_dep(name = \"protobuf\", version = \"34.0.bcr.1\", repo_name = \"com_google_protobuf\")\nbazel_dep(name = \"zlib-ng\", version = \"2.0.7\", repo_name = \"llvm_zlib\")\nbazel_dep(name = \"zstd\", version = \"1.5.7.bcr.1\", repo_name = \"llvm_zstd\")\n\n###############################################################################\n# llvm-project\n###############################################################################\n\n# Load a repository for the raw llvm-project, pre-overlay.\nbazel_dep(name = \"llvm-raw\")\ngit_override(\n    module_name = \"llvm-raw\",\n    build_file_content = \"# empty\",\n    # We pin to specific upstream commits and try to track top-of-tree\n    # reasonably closely rather than pinning to a specific release.\n    # HEAD as of 2026-03-09.\n    commit = \"d8474abfc1e7c3856b85b088f1133ae2e90da3d0\",\n    patch_cmds = [\"echo \\\"module(name='llvm-raw')\\\" > MODULE.bazel\"],\n    patch_strip = 1,\n    patches = [\n        \"//bazel/llvm_project:0001_Patch_for_mallinfo2_when_using_Bazel_build_system.patch\",\n        \"//bazel/llvm_project:0002_Added_Bazel_build_for_compiler_rt_fuzzer.patch\",\n        \"//bazel/llvm_project:0004_Introduce_basic_sources_exporting_for_libunwind.patch\",\n        \"//bazel/llvm_project:0005_Introduce_basic_sources_exporting_for_libcxx_and_libcxxabi.patch\",\n        \"//bazel/llvm_project:0009_Introduce_starlark_exporting_compiler-rt_build_information.patch\",\n    ],\n    remote = \"https://github.com/llvm/llvm-project.git\",\n)\n\n# Apply the overlay to produce llvm-project.\nllvm_project = use_extension(\n    \"//bazel/llvm_project:llvm_project.bzl\",\n    \"llvm_project\",\n)\nuse_repo(llvm_project, \"llvm-project\")\n\n###############################################################################\n# Python\n###############################################################################\n\nbazel_dep(name = \"rules_python\", version = \"1.9.0\")\n\npython = use_extension(\"@rules_python//python/extensions:python.bzl\", \"python\")\npython.toolchain(\n    python_version = \"3.11\",\n)\nuse_repo(python, \"python_versions\")\n\n###############################################################################\n# Bazel integration testing\n###############################################################################\n\nbazel_dep(\n    name = \"rules_bazel_integration_test\",\n    version = \"0.37.1\",\n    dev_dependency = True,\n)\n\n# We test against our current Bazel version, the latest release, and the latest\n# release candidate.\nbazel_binaries = use_extension(\n    \"@rules_bazel_integration_test//:extensions.bzl\",\n    \"bazel_binaries\",\n    dev_dependency = True,\n)\nbazel_binaries.download(version_file = \"//:.bazelversion\")\nbazel_binaries.download(version = \"latest\")\nbazel_binaries.download(version = \"last_rc\")\nuse_repo(\n    bazel_binaries,\n    \"bazel_binaries\",\n    \"bazel_binaries_bazelisk\",\n    \"build_bazel_bazel_.bazelversion\",\n    \"build_bazel_bazel_last_rc\",\n    \"build_bazel_bazel_latest\",\n)\n"
  },
  {
    "path": "README.md",
    "content": "# Carbon Language: <br/> An experimental successor to C++\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<p align=\"center\">\n  <a href=\"#why-build-carbon\">Why?</a> |\n  <a href=\"#language-goals\">Goals</a> |\n  <a href=\"#project-status\">Status</a> |\n  <a href=\"#getting-started\">Getting started</a> |\n  <a href=\"#join-us\">Join us</a>\n</p>\n\n**See our [announcement video](https://youtu.be/omrY53kbVoA) from\n[CppNorth](https://cppnorth.ca/).** Note that Carbon is\n[not ready for use](#project-status).\n\n<a href=\"docs/images/snippets.md#quicksort\">\n<!--\nEdit snippet in docs/images/snippets.md and:\nhttps://drive.google.com/drive/folders/1QrBXiy_X74YsOueeC0IYlgyolWIhvusB\n-->\n<img src=\"docs/images/quicksort_snippet.svg\" align=\"right\" width=\"575\"\n     alt=\"Quicksort code in Carbon. Follow the link to read more.\">\n</a>\n\n<!--\nDon't let the text wrap too narrowly to the left of the above image.\nThe `div` reduces the vertical height. The `picture` prevents autolinking.\n-->\n<div><picture><img src=\"docs/images/bumper.png\" alt=\"\"></picture></div>\n\n**Fast and works with C++**\n\n-   Performance matching C++ using LLVM, with low-level access to bits and\n    addresses\n-   Interoperate with your existing C++ code, from inheritance to templates\n-   Fast and scalable builds that work with your existing C++ build systems\n\n**Modern and evolving**\n\n-   Solid language foundations that are easy to learn, especially if you have\n    used C++\n-   Easy, tool-based upgrades between Carbon versions\n-   Safer fundamentals, and an incremental path towards a memory-safe subset\n\n**Welcoming open-source community**\n\n-   Clear goals and priorities with robust governance\n-   Community that works to be welcoming, inclusive, and friendly\n-   Batteries-included approach: compiler, libraries, docs, tools, package\n    manager, and more\n\n## Why build Carbon?\n\nC++ remains the dominant programming language for performance-critical software,\nwith massive and growing codebases and investments. However, it is struggling to\nimprove and meet developers' needs, as outlined above, in no small part due to\naccumulating decades of technical debt. Incrementally improving C++ is\n[extremely difficult](/docs/project/difficulties_improving_cpp.md), both due to\nthe technical debt itself and challenges with its evolution process. The best\nway to address these problems is to avoid inheriting the legacy of C or C++\ndirectly, and instead start with solid language foundations like\n[modern generics system](#generics), modular code organization, and consistent,\nsimple syntax.\n\nExisting modern languages already provide an excellent developer experience: Go,\nSwift, Kotlin, Rust, and many more. **Developers that _can_ use one of these\nexisting languages _should_.** Unfortunately, the designs of these languages\npresent significant barriers to adoption and migration from C++. These barriers\nrange from changes in the idiomatic design of software to performance overhead.\n\nCarbon is fundamentally **a successor language approach**, rather than an\nattempt to incrementally evolve C++. It is designed around interoperability with\nC++ as well as large-scale adoption and migration for existing C++ codebases and\ndevelopers. A successor language for C++ requires:\n\n-   **Performance matching C++**, an essential property for our developers.\n-   **Seamless, bidirectional interoperability with C++**, such that a library\n    anywhere in an existing C++ stack can adopt Carbon without porting the rest.\n-   **A gentle learning curve** with reasonable familiarity for C++ developers.\n-   **Comparable expressivity** and support for existing software's design and\n    architecture.\n-   **Scalable migration**, with some level of source-to-source translation for\n    idiomatic C++ code.\n\nWith this approach, we can build on top of C++'s existing ecosystem, and bring\nalong existing investments, codebases, and developer populations. There are a\nfew languages that have followed this model for other ecosystems, and Carbon\naims to fill an analogous role for C++:\n\n-   JavaScript → TypeScript\n-   Java → Kotlin\n-   C++ → **_Carbon_**\n\n## Language Goals\n\nWe are designing Carbon to support:\n\n-   Performance-critical software\n-   Software and language evolution\n-   Code that is easy to read, understand, and write\n-   Practical safety and testing mechanisms\n-   Fast and scalable development\n-   Modern OS platforms, hardware architectures, and environments\n-   Interoperability with and migration from existing C++ code\n\nWhile many languages share subsets of these goals, what distinguishes Carbon is\ntheir combination.\n\nWe also have explicit _non-goals_ for Carbon, notably including:\n\n-   A stable\n    [application binary interface](https://en.wikipedia.org/wiki/Application_binary_interface)\n    (ABI) for the entire language and library\n-   Perfect backwards or forwards compatibility\n\nOur detailed [goals](/docs/project/goals.md) document fleshes out these ideas\nand provides a deeper view into our goals for the Carbon project and language.\n\n## Project status\n\nCarbon Language is currently an experimental project. We are hard at work on a\ntoolchain implementation with compiler and linker. You can try out the current\nstate at [compiler-explorer.com](http://carbon.compiler-explorer.com/).\n\nWe want to better understand whether we can build a language that meets our\nsuccessor language criteria, and whether the resulting language can gather a\ncritical mass of interest within the larger C++ industry and community.\n\nCurrently, we have fleshed out several core aspects of both Carbon the project\nand the language:\n\n-   The strategy of the Carbon Language and project.\n-   An open-source project structure, governance model, and evolution process.\n-   Critical and foundational aspects of the language design informed by our\n    experience with C++ and the most difficult challenges we anticipate. This\n    includes designs for:\n    -   Generics\n    -   Class types\n    -   Inheritance\n    -   Operator overloading\n    -   Lexical and syntactic structure\n    -   Code organization and modular structure\n-   An under-development [compiler and toolchain](/toolchain/) that will compile\n    Carbon (and eventually C++ code as well) into standard executable code. This\n    is where most of our current implementation efforts are directed.\n    -   Historically, there was also a prototype\n        [explorer](https://github.com/carbon-language/explorer) interpreter that\n        implemented an older version of the Carbon language design, but is no\n        longer under development and has been archived.\n\nIf you're interested in contributing, we're currently focused on developing the\nCarbon toolchain until it can\n[support Carbon ↔ C++ interop](/docs/project/roadmap.md#access-most-non-template-c-apis-in-carbon).\nBeyond that, we plan to continue developing the design and toolchain until we\ncan ship the\n[0.1 language](/docs/project/milestones.md#milestone-01-a-minimum-viable-product-mvp-for-evaluation)\nand support evaluating Carbon in more detail.\n\nYou can see our [full roadmap](/docs/project/roadmap.md) for more details.\n\n## Carbon and C++\n\nIf you're already a C++ developer, Carbon should have a gentle learning curve.\nIt is built out of a consistent set of language constructs that should feel\nfamiliar and be easy to read and understand.\n\nThe Carbon code here is hypothetical and meant to show the look and feel of the\nlanguage.\n\nC++ code like this:\n\n<a href=\"docs/images/snippets.md#c\">\n<!--\nEdit snippet in docs/images/snippets.md and:\nhttps://drive.google.com/drive/folders/1QrBXiy_X74YsOueeC0IYlgyolWIhvusB\n-->\n<img src=\"docs/images/cpp_snippet.svg\" width=\"600\"\n     alt=\"A snippet of C++ code. Follow the link to read it.\">\n</a>\n\ncorresponds to this Carbon code:\n\n<a href=\"docs/images/snippets.md#carbon\">\n<!--\nEdit snippet in docs/images/snippets.md and:\nhttps://drive.google.com/drive/folders/1QrBXiy_X74YsOueeC0IYlgyolWIhvusB\n-->\n<img src=\"docs/images/carbon_snippet.svg\" width=\"600\"\n     alt=\"A snippet of converted Carbon code. Follow the link to read it.\">\n</a>\n\nYou can call Carbon from C++ without overhead and the other way around. This\nmeans you migrate a single C++ library to Carbon within an application, or write\nnew Carbon on top of your existing C++ investment. For example:\n\n<a href=\"docs/images/snippets.md#mixed\">\n<!--\nEdit snippet in docs/images/snippets.md and:\nhttps://drive.google.com/drive/folders/1QrBXiy_X74YsOueeC0IYlgyolWIhvusB\n-->\n<img src=\"docs/images/mixed_snippet.svg\" width=\"600\"\n     alt=\"A snippet of mixed Carbon and C++ code. Follow the link to read it.\">\n</a>\n\nRead more about\n[C++ interop in Carbon](/docs/design/interoperability/philosophy_and_goals.md).\n\nBeyond interoperability between Carbon and C++, we're also planning to support\nmigration tools that will mechanically translate idiomatic C++ code into Carbon\ncode to help you switch an existing C++ codebase to Carbon.\n\n## Generics\n\nCarbon provides a\n**[modern generics system](/docs/design/generics/overview.md#what-are-generics)**\nwith checked definitions, while still **supporting opt-in\n[templates](/docs/design/templates.md) for seamless C++ interop**. Checked\ngenerics provide several advantages compared to C++ templates:\n\n-   **Generic definitions are fully type-checked**, removing the need to\n    instantiate to check for errors and giving greater confidence in code.\n    -   Avoids the compile-time cost of re-checking the definition for every\n        instantiation.\n    -   When using a definition-checked generic, usage error messages are\n        clearer, directly showing which requirements are not met.\n-   **Enables automatic, opt-in type erasure and dynamic dispatch** without a\n    separate implementation. This can reduce the binary size and enables\n    constructs like heterogeneous containers.\n-   **Strong, checked interfaces** mean fewer accidental dependencies on\n    implementation details and a clearer contract for consumers.\n\nWithout sacrificing these advantages, **Carbon generics support\nspecialization**, ensuring it can fully address performance-critical use cases\nof C++ templates. For more details about Carbon's generics, see their\n[design](/docs/design/generics).\n\nIn addition to easy and powerful interop with C++, Carbon templates can be\nconstrained and incrementally migrated to checked generics at a fine granularity\nand with a smooth evolutionary path.\n\n## Memory safety\n\nSafety, and especially\n[memory safety](https://en.wikipedia.org/wiki/Memory_safety), remains a key\nchallenge for C++ and something a successor language needs to address.\n\nWe plan to support a two step migration process:\n\n1. Highly automated, minimal supervision migration from C++ to a dialect of\n   Carbon designed for C++ interop and migration.\n2. Incremental refactoring of the Carbon code to adopt memory-safe designs,\n   patterns, and APIs.\n\nWe also want to address important, low-hanging fruit in the safety space\nimmediately when migrating into Carbon:\n\n-   Tracking uninitialized states better, increased enforcement of\n    initialization, and hardening against initialization bugs when needed.\n-   Designing fundamental APIs and idioms to support dynamic bounds checking.\n-   Switching from undefined behavior to erroneous behavior wherever possible,\n    and marking the remaining undefined behavior with visible `unsafe` syntax.\n-   Having a default debug build mode that has less runtime overhead while being\n    more comprehensive than existing C++ debug build modes combined with\n    [Address Sanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer).\n\nFor more details, see our [safety design](/docs/design/safety).\n\n## Getting started\n\nTo try out Carbon immediately in your browser, you can use the toolchain at:\n[carbon.compiler-explorer.com](http://carbon.compiler-explorer.com/).\n\nWe are developing a traditional toolchain for Carbon that can compile and link\nprograms. However, Carbon is still an early, experimental project, and so we\nonly have very experimental nightly releases of the Carbon toolchain available\nto download, and only on limited platforms. If you are using a recent Ubuntu\nLinux or similar (Debian, WSL, etc.), you can try these out by going to our\n[releases](https://github.com/carbon-language/carbon-lang/releases) page and\ndownload the latest nightly toolchain tar file:\n`carbon_toolchain-0.0.0-0.nightly.YYYY.MM.DD.tar.gz`. Then you can try it out:\n\n```shell\n# A variable with the nightly version from yesterday:\nVERSION=\"$(date -d yesterday +0.0.0-0.nightly.%Y.%m.%d)\"\n\n# Get the release\nwget https://github.com/carbon-language/carbon-lang/releases/download/v${VERSION}/carbon_toolchain-${VERSION}.tar.gz\n\n# Unpack the toolchain:\ntar -xvf carbon_toolchain-${VERSION}.tar.gz\n\n# Create a simple Carbon source file:\necho \"import Core library \\\"io\\\"; fn Run() { Core.Print(42); }\" > forty_two.carbon\n\n# Compile to an object file:\n./carbon_toolchain-${VERSION}/bin/carbon compile \\\n  --output=forty_two.o forty_two.carbon\n\n# Install minimal system libraries used for linking. Note that installing `gcc`\n# or `g++` for compiling C/C++ code with GCC will also be sufficient, these are\n# just the specific system libraries Carbon linking still uses.\nsudo apt install libgcc-11-dev\n\n# Link to an executable:\n./carbon_toolchain-${VERSION}/bin/carbon link \\\n  --output=forty_two forty_two.o\n\n# Run it:\n./forty_two\n```\n\nAs a reminder, the toolchain is still very early and many things don't yet work.\nPlease hold off on filing lots of bugs: we know many parts of this don't work\nyet or may not work on all systems. We expect to have releases that are much\nmore robust and reliable that you can try out when we reach our\n[0.1 milestone](/docs/project/milestones.md#milestone-01-a-minimum-viable-product-mvp-for-evaluation).\n\nIf you want to build Carbon's toolchain yourself or are thinking about\ncontributing fixes or improvements to Carbon, you'll need to install our\n[build dependencies](/docs/project/contribution_tools.md#setup-commands) (Clang,\nLLD, libc++) and check out the Carbon repository. For example, on Debian or\nUbuntu:\n\n```shell\n# Update apt.\nsudo apt update\n\n# Install tools.\nsudo apt install \\\n  clang \\\n  libc++-dev \\\n  libc++abi-dev \\\n  lld\n\n# Download Carbon's code.\n$ git clone https://github.com/carbon-language/carbon-lang\n$ cd carbon-lang\n```\n\nThen you can try out our toolchain which has a very early-stage compiler for\nCarbon:\n\n```shell\n# Build and run the toolchain's help to get documentation on the command line.\n$ ./scripts/run_bazelisk.py run //toolchain -- help\n```\n\nFor complete instructions, including installing dependencies on various\ndifferent platforms, see our\n[contribution tools documentation](/docs/project/contribution_tools.md).\n\nLearn more about the Carbon project:\n\n-   [Project goals](/docs/project/goals.md)\n-   [Language design overview](/docs/design)\n-   [Carbon Toolchain](/toolchain)\n-   [FAQ](/docs/project/faq.md)\n\n## Conference talks\n\nCarbon focused talks from the community:\n\n### 2026\n\n-   Benchmarking and optimizing the Carbon compiler, NDC {Toronto} (May 5-8)\n-   Carbon: graduating from the experiment, NDC {Toronto} (May 5-8)\n\n### 2025\n\n-   Carbon: from C++ to Memory Safety, REBASE - ICFP/SPLASH\n    ([slides](https://chandlerc.blog/slides/2025-rebase-carbon))\n-   Memory safety everywhere with both Carbon and Rust, RustConf\n    ([video](https://youtu.be/FYLuom6gg_s),\n    [slides](https://chandlerc.blog/slides/2025-rustconf-memory-safety-everywhere))\n\n### 2024\n\n-   Generic implementation strategies in Carbon and Clang, LLVM Developers'\n    Meeting ([video](https://youtu.be/j0BL52NdjAU),\n    [slides](https://chandlerc.blog/slides/2024-llvm-generic-implementation/#/))\n-   The Carbon Language: Road to 0.1, NDC {TechTown}\n    ([video](https://youtu.be/bBvLmDJrzvI),\n    [slides](https://chandlerc.blog/slides/2024-ndc-techtown-carbon-road-to-0-dot-1))\n-   How designing Carbon with C++ interop taught me about C++ variadics and\n    overloads, CppNorth ([video](https://youtu.be/8SGMy9ENGz8),\n    [slides](https://chandlerc.blog/slides/2024-cppnorth-design-stories))\n-   Generic Arity: Definition-Checked Variadics in Carbon, C++Now\n    ([video](https://youtu.be/Y_px536l_80),\n    [slides](https://docs.google.com/presentation/d/10aM1mFMN6Cd5ZkE4OfeiZtSnkVNbo33N-V0et21umww/edit))\n-   Carbon: An experiment in different tradeoffs, panel session, EuroLLVM\n    ([video](https://youtu.be/Za_KWj5RMR8),\n    [slides](https://llvm.org/devmtg/2024-04/slides/LightningTalks/Smith-Carbons-high-level-semanticIR.pdf))\n    -   [Alex Bradbury's notes](https://muxup.com/2024q2/notes-from-the-carbon-panel-session-at-eurollvm)\n-   Carbon's high-level semantic IR lightning talk, EuroLLVM\n    ([video](https://youtu.be/vIWT4RhUcyw))\n\n### 2023\n\n-   Carbon’s Successor Strategy: From C++ interop to memory safety, C++Now\n    ([video](https://youtu.be/1ZTJ9omXOQ0),\n    [slides](https://chandlerc.blog/slides/2023-cppnow-carbon-strategy/index.html#/))\n-   Definition-Checked Generics, C++Now\n    -   Part 1 ([video](https://youtu.be/FKC8WACSMP0),\n        [slides](https://chandlerc.blog/slides/2023-cppnow-generics-1/#/))\n    -   Part 2 ([video](https://youtu.be/VxQ3PwxiSzk),\n        [slides](https://chandlerc.blog/slides/2023-cppnow-generics-2/#/))\n-   Modernizing Compiler Design for Carbon’s Toolchain, C++Now\n    ([video](https://youtu.be/ZI198eFghJk),\n    [slides](https://chandlerc.blog/slides/2023-cppnow-compiler/index.html#/))\n\n### 2022\n\n-   Carbon Language: Syntax and trade-offs, Core C++\n    ([video](https://youtu.be/9Y2ivB8VaIs),\n    [slides](https://docs.google.com/presentation/d/1znvL12xCuEfcsP6tpPdrQPnh-UoPFOLnC_RVXZteYaM/edit))\n-   Carbon Language: An experimental successor to C++, CppNorth\n    ([video](https://youtu.be/omrY53kbVoA),\n    [slides](https://chandlerc.blog/slides/2022-07-19-cppnorth-keynote/#/))\n\n### Other videos\n\nWe additionally have [toolchain videos](/toolchain/docs/README.md#videos).\n\n## Join us\n\nWe'd love to have folks join us and contribute to the project. Carbon is\ncommitted to a welcoming and inclusive environment where everyone can\ncontribute.\n\n-   Most of Carbon's design discussions occur on\n    [Discord](https://discord.gg/ZjVdShJDAs).\n-   To watch for major release announcements, subscribe to our\n    [Carbon release post on GitHub](https://github.com/carbon-language/carbon-lang/discussions/1020)\n    and [star carbon-lang](https://github.com/carbon-language/carbon-lang).\n-   See our [code of conduct](CODE_OF_CONDUCT.md) and\n    [contributing guidelines](CONTRIBUTING.md) for information about the Carbon\n    development community.\n\n### Contributing\n\nYou can also directly:\n\n-   [Contribute to the language design](CONTRIBUTING.md#contributing-to-the-language-design):\n    feedback on design, new design proposal\n-   [Contribute to the language implementation](CONTRIBUTING.md#contributing-to-the-language-implementation)\n    -   [Carbon Toolchain](/toolchain/), and project infrastructure\n\nYou can **check out some\n[\"good first issues\"](https://github.com/carbon-language/carbon-lang/labels/good%20first%20issue)**,\nor join the `#contributing-help` channel on\n[Discord](https://discord.gg/ZjVdShJDAs). See our full\n[`CONTRIBUTING`](CONTRIBUTING.md) documentation for more details.\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security policy\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nIt's important to us that the Carbon Language provides a secure implementation.\nThank you for taking the time to report vulnerabilities.\n\nThe Carbon Language is still an\n[experimental project](/README.md#project-status), so please be careful if using\nit in security-sensitive environments.\n\n## Reporting a vulnerability\n\nPlease use\n<https://github.com/carbon-language/carbon-lang/security/advisories/new> to\nreport security vulnerabilities.\n\nWe use GitHub's vulnerability reporting for intake. We will respond to reports\nwithin two weeks. For valid issues we will coordinate and disclose on GitHub.\n\nIf you haven't received a response, a couple steps to take are (in order):\n\n1.  Contact individuals directly:\n    -   [Chandler Carruth](mailto:chandlerc@gmail.com)\n    -   [Richard Smith](mailto:richard@metafoo.co.uk)\n    -   [Jon Ross-Perkins](mailto:jperkins@google.com)\n2.  Reach out on\n    [#infra](https://discord.com/channels/655572317891461132/707150492370862090)\n    on Discord ([invite](https://discord.gg/ZjVdShJDAs))\n    -   This is a public forum, so say you're asking for a security contact\n        rather than talking about the security issue directly.\n"
  },
  {
    "path": "bazel/carbon_rules/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@bazel_skylib//rules:common_settings.bzl\", \"bool_flag\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\n# Flag controlling whether the target config is used for the `carbon_*` Bazel\n# rules. The default is to use the exec config as that is more correct in cases\n# where the target config is not compatible with the exec (cross compiling), and\n# for library users of Carbon likely the most efficient as it will provide an\n# optimized toolchain.\n#\n# However, for building the Carbon project itself, this will roughly double the\n# build cost by forcing a build in both target and exec config. As a consequence\n# we disable the flag in the `.bazelrc` of the project for its builds.\nbool_flag(\n    name = \"use_target_config_carbon_rules\",\n    build_setting_default = False,\n)\n\nconfig_setting(\n    name = \"use_target_config_carbon_rules_config\",\n    flag_values = {\":use_target_config_carbon_rules\": \"True\"},\n)\n"
  },
  {
    "path": "bazel/carbon_rules/defs.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Provides rules for building Carbon files using the toolchain.\"\"\"\n\nload(\"@rules_cc//cc/common:cc_info.bzl\", \"CcInfo\")\n\ndef _runtimes_path(runtimes_target):\n    path = None\n    for f in runtimes_target:\n        if f.short_path.endswith(\"clang_resource_dir/lib\"):\n            path = f.path\n            break\n\n    if not path:\n        fail(\"Could not find the `clang_resource_dir` in target {}\".format(runtimes_target.label))\n\n    return path[:-len(\"/clang_resource_dir/lib\")]\n\ndef _carbon_binary_impl(ctx):\n    toolchain_driver = ctx.executable.internal_exec_toolchain_driver\n    toolchain_data = ctx.files.internal_exec_toolchain_data\n    prebuilt_runtimes = ctx.files.internal_exec_prebuilt_runtimes\n\n    # If the exec driver isn't provided, that means we're trying to use a target\n    # config toolchain, likely to avoid build overhead of two configs.\n    if toolchain_driver == None:\n        toolchain_driver = ctx.executable.internal_target_toolchain_driver\n        toolchain_data = ctx.files.internal_target_toolchain_data\n        prebuilt_runtimes = ctx.files.internal_target_prebuilt_runtimes\n\n    # Pass any C++ flags from our dependencies onto Carbon.\n    dep_flags = []\n    dep_hdrs = []\n    dep_link_flags = []\n    dep_link_inputs = []\n    for dep in ctx.attr.deps:\n        if CcInfo in dep:\n            cc_info = dep[CcInfo]\n\n            # TODO: We should reuse the feature-based flag generation in\n            # bazel/cc_toolchains here.\n            dep_flags += [\"--clang-arg=-D{0}\".format(define) for define in cc_info.compilation_context.defines.to_list()]\n            dep_flags += [\"--clang-arg=-I{0}\".format(path) for path in cc_info.compilation_context.includes.to_list()]\n            dep_flags += [\"--clang-arg=-iquote{0}\".format(path) for path in cc_info.compilation_context.quote_includes.to_list()]\n            dep_flags += [\"--clang-arg=-isystem{0}\".format(path) for path in cc_info.compilation_context.system_includes.to_list()]\n            dep_hdrs.append(cc_info.compilation_context.headers)\n            for link_input in cc_info.linking_context.linker_inputs.to_list():\n                # TODO: `carbon link` doesn't support linker flags yet.\n                # dep_link_flags += link_input.user_link_flags\n                dep_link_inputs += link_input.additional_inputs\n                for lib in link_input.libraries:\n                    dep_link_inputs += [dep for dep in [lib.dynamic_library, lib.static_library] if dep]\n                    dep_link_inputs += lib.objects\n        if DefaultInfo in dep:\n            dep_link_inputs += dep[DefaultInfo].files.to_list()\n    dep_link_flags += [dep.path for dep in dep_link_inputs]\n\n    # Build object files for the prelude and for the binary itself.\n    # TODO: Eventually the prelude should be build as a separate `carbon_library`.\n    srcs_and_flags = [\n        (ctx.files.prelude_srcs, [\"--no-prelude-import\"]),\n        (ctx.files.srcs, dep_flags),\n    ]\n\n    objs = []\n    for (srcs, extra_flags) in srcs_and_flags:\n        for src in srcs:\n            # Build each source file. For now, we pass all sources to each compile\n            # because we don't have visibility into dependencies and have no way to\n            # specify multiple output files. Object code for each input is written\n            # into the output file in turn, so the final carbon source file\n            # specified ends up determining the contents of the object file.\n            #\n            # TODO: This is a hack; replace with something better once the toolchain\n            # supports doing so.\n            #\n            # TODO: Switch to the `prefix` based rule similar to linking when\n            # the prelude moves there.\n            out = ctx.actions.declare_file(\"_objs/{0}/{1}o\".format(\n                ctx.label.name,\n                src.short_path.removeprefix(ctx.label.package).removesuffix(src.extension),\n            ))\n            objs.append(out)\n            srcs_reordered = [s for s in srcs if s != src] + [src]\n            ctx.actions.run(\n                outputs = [out],\n                inputs = depset(direct = srcs_reordered, transitive = dep_hdrs),\n                executable = toolchain_driver,\n                tools = depset(toolchain_data),\n                arguments = [\"compile\", \"--output=\" + out.path, \"--output-last-input-only\"] +\n                            [s.path for s in srcs_reordered] + extra_flags + ctx.attr.flags,\n                mnemonic = \"CarbonCompile\",\n                progress_message = \"Compiling \" + src.short_path,\n            )\n\n    bin = ctx.actions.declare_file(ctx.label.name)\n    ctx.actions.run(\n        outputs = [bin],\n        inputs = objs + dep_link_inputs,\n        executable = toolchain_driver,\n        tools = depset(toolchain_data + prebuilt_runtimes),\n        arguments = [\"--prebuilt-runtimes=\" + _runtimes_path(prebuilt_runtimes), \"link\", \"--output=\" + bin.path] + [\"--\"] + dep_link_flags + [o.path for o in objs],\n        mnemonic = \"CarbonLink\",\n        progress_message = \"Linking \" + bin.short_path,\n    )\n    return [DefaultInfo(files = depset([bin]), executable = bin)]\n\n_carbon_binary_internal = rule(\n    implementation = _carbon_binary_impl,\n    attrs = {\n        \"deps\": attr.label_list(allow_files = True, providers = [[CcInfo]]),\n        \"flags\": attr.string_list(),\n\n        # The exec config toolchain attributes. These will be `None` when using\n        # the target config and populated when using the exec config. We have to\n        # use duplicate attributes here and below to have different `cfg`\n        # settings, as that isn't `select`-able, and we'll use `select`s when\n        # populating these.\n        \"internal_exec_prebuilt_runtimes\": attr.label(\n            cfg = \"exec\",\n        ),\n        \"internal_exec_toolchain_data\": attr.label(\n            cfg = \"exec\",\n        ),\n        \"internal_exec_toolchain_driver\": attr.label(\n            allow_single_file = True,\n            executable = True,\n            cfg = \"exec\",\n        ),\n\n        # The target config toolchain attributes. These will be 'None' when\n        # using the exec config and populated when using the target config. We\n        # have to use duplicate attributes here and below to have different\n        # `cfg` settings, as that isn't `select`-able, and we'll use `select`s\n        # when populating these.\n        \"internal_target_prebuilt_runtimes\": attr.label(\n            cfg = \"target\",\n        ),\n        \"internal_target_toolchain_data\": attr.label(\n            cfg = \"target\",\n        ),\n        \"internal_target_toolchain_driver\": attr.label(\n            allow_single_file = True,\n            executable = True,\n            cfg = \"target\",\n        ),\n        \"prelude_srcs\": attr.label_list(allow_files = [\".carbon\"]),\n        \"srcs\": attr.label_list(allow_files = [\".carbon\"]),\n        \"_cc_toolchain\": attr.label(default = \"@bazel_tools//tools/cpp:current_cc_toolchain\"),\n    },\n    executable = True,\n)\n\ndef carbon_binary(name, srcs, deps = [], flags = [], tags = []):\n    \"\"\"Compiles a Carbon binary.\n\n    Args:\n      name: The name of the build target.\n      srcs: List of Carbon source files to compile.\n      deps: List of dependencies.\n      flags: Extra flags to pass to the Carbon compile command.\n      tags: Tags to apply to the rule.\n    \"\"\"\n    _carbon_binary_internal(\n        name = name,\n        srcs = srcs,\n        prelude_srcs = [\"//core:prelude_files\"],\n        deps = deps,\n        flags = flags,\n        tags = tags,\n\n        # We synthesize two sets of attributes from mirrored `select`s here\n        # because we want to select on an internal property of these attributes\n        # but that isn't `select`-able. Instead, we have both attributes and\n        # `select` which one we use.\n        internal_exec_toolchain_driver = select({\n            \"//bazel/carbon_rules:use_target_config_carbon_rules_config\": None,\n            \"//conditions:default\": \"//toolchain/install:prefix/bin/carbon\",\n        }),\n        internal_exec_toolchain_data = select({\n            \"//bazel/carbon_rules:use_target_config_carbon_rules_config\": None,\n            \"//conditions:default\": \"//toolchain/install:install_data\",\n        }),\n        internal_exec_prebuilt_runtimes = select({\n            \"//bazel/carbon_rules:use_target_config_carbon_rules_config\": None,\n            \"//conditions:default\": \"//toolchain/driver:prebuilt_runtimes\",\n        }),\n        internal_target_toolchain_driver = select({\n            \"//bazel/carbon_rules:use_target_config_carbon_rules_config\": \"//toolchain/install:prefix/bin/carbon\",\n            \"//conditions:default\": None,\n        }),\n        internal_target_toolchain_data = select({\n            \"//bazel/carbon_rules:use_target_config_carbon_rules_config\": \"//toolchain/install:install_data\",\n            \"//conditions:default\": None,\n        }),\n        internal_target_prebuilt_runtimes = select({\n            \"//bazel/carbon_rules:use_target_config_carbon_rules_config\": \"//toolchain/driver:prebuilt_runtimes\",\n            \"//conditions:default\": None,\n        }),\n    )\n"
  },
  {
    "path": "bazel/cc_rules/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Empty; only defs.bzl is needed.\n"
  },
  {
    "path": "bazel/cc_rules/defs.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Wraps standard cc rules with the `cc_env` addition.\n\nThese should generally be used in place of `@rules_cc`.\n\"\"\"\n\nload(\n    \"@rules_cc//cc:defs.bzl\",\n    actual_cc_binary = \"cc_binary\",\n    actual_cc_library = \"cc_library\",\n    actual_cc_test = \"cc_test\",\n)\nload(\"//bazel/cc_toolchains:defs.bzl\", \"cc_env\")\n\n# Expose cc_library directly, for consistency.\ncc_library = actual_cc_library\n\ndef cc_binary(env = {}, **kwargs):\n    \"\"\"Wraps `cc_binary`, adding `cc_env`.\"\"\"\n    actual_cc_binary(\n        env = cc_env() | env,\n        **kwargs\n    )\n\ndef cc_test(env = {}, **kwargs):\n    \"\"\"Wraps `cc_binary`, adding `cc_env`.\"\"\"\n    actual_cc_test(\n        env = cc_env() | env,\n        **kwargs\n    )\n"
  },
  {
    "path": "bazel/cc_toolchains/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@bazel_skylib//lib:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\n# For use by defs.bzl.\n# Matches when asan is enabled on a macOS platform.\nselects.config_setting_group(\n    name = \"macos_asan\",\n    match_all = [\n        \":is_macos\",\n        \":macos_asan_build_modes\",\n    ],\n)\n\n# For use by defs.bzl.\n# Matches macOS platforms.\nconfig_setting(\n    name = \"is_macos\",\n    constraint_values = [\"@platforms//os:macos\"],\n)\n\n# For use by defs.bzl.\n# Matches build modes where asan is enabled.\nselects.config_setting_group(\n    name = \"macos_asan_build_modes\",\n    match_any = [\n        \":dbg\",\n        \":fastbuild\",\n    ],\n)\n\n# For use by defs.bzl.\n# Matches dbg.\nconfig_setting(\n    name = \"dbg\",\n    values = {\"compilation_mode\": \"dbg\"},\n)\n\n# For use by defs.bzl.\n# Matches fastbuild.\nconfig_setting(\n    name = \"fastbuild\",\n    values = {\"compilation_mode\": \"fastbuild\"},\n)\n\nfilegroup(\n    name = \"installed_cc_toolchain_starlark\",\n    srcs = [\n        \"cc_toolchain_actions.bzl\",\n        \"cc_toolchain_base_features.bzl\",\n        \"cc_toolchain_config_features.bzl\",\n        \"cc_toolchain_cpp_features.bzl\",\n        \"cc_toolchain_debugging.bzl\",\n        \"cc_toolchain_features.bzl\",\n        \"cc_toolchain_linking.bzl\",\n        \"cc_toolchain_modules.bzl\",\n        \"cc_toolchain_optimization.bzl\",\n        \"cc_toolchain_sanitizer_features.bzl\",\n        \"cc_toolchain_tools.bzl\",\n    ],\n)\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_actions.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Useful sets of actions for defining `cc_toolchain_config` features.\"\"\"\n\nload(\"@rules_cc//cc:action_names.bzl\", \"ACTION_NAMES\")\n\nall_c_compile_actions = [\n    ACTION_NAMES.c_compile,\n    ACTION_NAMES.assemble,\n    ACTION_NAMES.preprocess_assemble,\n]\n\nall_cpp_compile_actions = [\n    ACTION_NAMES.cpp_compile,\n    ACTION_NAMES.linkstamp_compile,\n    ACTION_NAMES.cpp_header_parsing,\n    ACTION_NAMES.cpp_module_compile,\n    ACTION_NAMES.cpp_module_codegen,\n]\n\nall_compile_actions = all_c_compile_actions + all_cpp_compile_actions\n\npreprocessor_compile_actions = [\n    ACTION_NAMES.c_compile,\n    ACTION_NAMES.cpp_compile,\n    ACTION_NAMES.linkstamp_compile,\n    ACTION_NAMES.preprocess_assemble,\n    ACTION_NAMES.cpp_header_parsing,\n    ACTION_NAMES.cpp_module_compile,\n]\n\ncodegen_compile_actions = [\n    ACTION_NAMES.c_compile,\n    ACTION_NAMES.cpp_compile,\n    ACTION_NAMES.linkstamp_compile,\n    ACTION_NAMES.assemble,\n    ACTION_NAMES.preprocess_assemble,\n    ACTION_NAMES.cpp_module_codegen,\n]\n\nall_link_actions = [\n    ACTION_NAMES.cpp_link_executable,\n    ACTION_NAMES.cpp_link_dynamic_library,\n    ACTION_NAMES.cpp_link_nodeps_dynamic_library,\n]\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_base_features.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Definitions used for the base features of a `cc_toolchain_config`.\"\"\"\n\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"feature\",\n    \"feature_set\",\n    \"flag_group\",\n    \"flag_set\",\n)\nload(\n    \":cc_toolchain_actions.bzl\",\n    \"all_compile_actions\",\n    \"all_link_actions\",\n)\n\n# Declare features that are used by Bazel to model specific build modes.\ndbg_feature = feature(name = \"dbg\")\nfastbuild_feature = feature(name = \"fastbuild\")\nhost_feature = feature(name = \"host\")\nopt_feature = feature(name = \"opt\")\n\n# Declare features that control enabling and disabling Bazel logic.\nno_legacy_features_feature = feature(name = \"no_legacy_features\")\nsupports_pic_feature = feature(name = \"supports_pic\", enabled = True)\n\nsupports_dynamic_linker_feature = feature(\n    name = \"supports_dynamic_linker\",\n    enabled = True,\n    requires = [feature_set([\"linux_target\"])],\n)\nsupports_start_end_lib_feature = feature(\n    name = \"supports_start_end_lib\",\n    enabled = True,\n    requires = [feature_set([\"linux_target\"])],\n)\n\nuser_flags_feature = feature(\n    name = \"user_flags\",\n    enabled = True,\n    flag_sets = [\n        flag_set(\n            actions = all_compile_actions,\n            flag_groups = [flag_group(\n                expand_if_available = \"user_compile_flags\",\n                flags = [\"%{user_compile_flags}\"],\n                iterate_over = \"user_compile_flags\",\n            )],\n        ),\n        flag_set(\n            actions = all_link_actions,\n            flag_groups = [flag_group(\n                expand_if_available = \"user_link_flags\",\n                flags = [\"%{user_link_flags}\"],\n                iterate_over = \"user_link_flags\",\n            )],\n        ),\n    ],\n)\n\n# TODO: It's not clear this is the right location for these flags, and it is a\n# little awkward.\noutput_flags_feature = feature(\n    name = \"output_flags\",\n    enabled = True,\n    flag_sets = [\n        flag_set(\n            actions = all_compile_actions,\n            flag_groups = [\n                # For compile actions we have a single source and so put it at\n                # the end next to the output.\n                flag_group(\n                    expand_if_available = \"source_file\",\n                    flags = [\"%{source_file}\"],\n                ),\n                flag_group(\n                    expand_if_available = \"output_file\",\n                    flags = [\"-o\", \"%{output_file}\"],\n                ),\n            ],\n        ),\n        flag_set(\n            actions = all_link_actions,\n            flag_groups = [flag_group(\n                expand_if_available = \"output_execpath\",\n                flags = [\"-o\", \"%{output_execpath}\"],\n            )],\n        ),\n    ],\n)\n\nbase_features = [\n    dbg_feature,\n    fastbuild_feature,\n    host_feature,\n    no_legacy_features_feature,\n    opt_feature,\n    supports_pic_feature,\n    supports_dynamic_linker_feature,\n    supports_start_end_lib_feature,\n]\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_carbon_project_features.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Defines `cc_toolchain_config` features specific to the Carbon project.\"\"\"\n\nload(\"@rules_cc//cc:action_names.bzl\", \"ACTION_NAMES\")\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"feature\",\n    \"feature_set\",\n    \"flag_group\",\n    \"flag_set\",\n    \"with_feature_set\",\n)\nload(\n    \":cc_toolchain_actions.bzl\",\n    \"all_compile_actions\",\n    \"preprocessor_compile_actions\",\n)\n\n# An enabled feature that requires the `fastbuild` compilation. This is used\n# to toggle general features on by default, while allowing them to be\n# directly enabled and disabled more generally as desired.\ncarbon_project_fastbuild_feature = feature(\n    name = \"enable_in_fastbuild\",\n    enabled = True,\n    requires = [feature_set([\"fastbuild\"])],\n    implies = [\n        \"asan\",\n        \"asan_min_size\",\n        \"minimal_optimization_flags\",\n        \"minimal_debug_info_flags\",\n    ],\n)\n\ndef carbon_project_features(cache_key):\n    return [carbon_project_fastbuild_feature, feature(\n        name = \"project_flags\",\n        enabled = True,\n        flag_sets = [\n            flag_set(\n                actions = all_compile_actions,\n                flag_groups = [flag_group(flags = [\n                    # Don't warn on external code as we can't\n                    # necessarily patch it easily. Note that these have\n                    # to be initial directories in the `#include` line.\n                    \"--system-header-prefix=absl/\",\n                    \"--system-header-prefix=benchmark/\",\n                    \"--system-header-prefix=boost/\",\n                    \"--system-header-prefix=clang-tools-extra/\",\n                    \"--system-header-prefix=clang/\",\n                    \"--system-header-prefix=gmock/\",\n                    \"--system-header-prefix=gtest/\",\n                    \"--system-header-prefix=libfuzzer/\",\n                    \"--system-header-prefix=llvm/\",\n                    \"--system-header-prefix=re2/\",\n                    \"--system-header-prefix=tools/cpp/\",\n                    \"--system-header-prefix=tree_sitter/\",\n                ])],\n            ),\n            flag_set(\n                actions = preprocessor_compile_actions,\n                flag_groups = [flag_group(flags = [\n                    # Pass a cache key as a `-D` flag to avoid unintended Bazel\n                    # cache hits when the underlying toolchain changes.\n                    # TODO: We should consider replacing this by causing changes\n                    # to the installed toolchain to more reliably end up as part\n                    # of the action digest.\n                    \"-DBAZEL_COMPILE_CACHE_KEY=\\\"%s\\\"\" % cache_key,\n                ])],\n            ),\n            flag_set(\n                actions = [\n                    ACTION_NAMES.c_compile,\n                    ACTION_NAMES.cpp_compile,\n                    ACTION_NAMES.cpp_header_parsing,\n                    ACTION_NAMES.cpp_module_compile,\n                ],\n                flag_groups = [flag_group(flags = [\"-DHAVE_MALLCTL\"])],\n                with_features = [with_feature_set([\"freebsd_target\"])],\n            ),\n        ],\n    )]\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_config_features.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Configuration features for other features in a `cc_toolchain_config`.\n\nThese features are designed to be used by other features in a\n`cc_toolchain_config` that need to configure their behavior in some way. This\ncan be configuration based on either the target or host of the build, and along\nmultiple dimensions of each.\n\"\"\"\n\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"feature\",\n)\n\nos_names = [\n    \"freebsd\",\n    \"linux\",\n    \"macos\",\n    \"windows\",\n]\n\ndef target_os_features(target_os):\n    if target_os not in os_names:\n        fail(\"Unsupported target OS: %s\" % target_os)\n    return [\n        feature(name = os_name + \"_target\", enabled = os_name == target_os)\n        for os_name in os_names\n    ]\n\ncpu_names = [\n    \"aarch64\",\n    \"x86_64\",\n]\n\n# Also support canonicalizing different spellings of CPUs to one of the above\n# names.\ncpu_canonical_name_map = {\n    \"aarch64\": \"aarch64\",\n    \"arm64\": \"aarch64\",\n    \"x86_64\": \"x86_64\",\n}\n\ndef target_cpu_features(target_cpu):\n    if target_cpu not in cpu_canonical_name_map:\n        fail(\"Unsupported target CPU: %s\" % target_cpu)\n    target_cpu = cpu_canonical_name_map[target_cpu]\n\n    return [\n        feature(name = cpu_name + \"_target\", enabled = cpu_name == target_cpu)\n        for cpu_name in cpu_names\n    ]\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_cpp_features.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Definitions of general C++ `cc_toolchain_config` features.\"\"\"\n\nload(\"@rules_cc//cc:action_names.bzl\", \"ACTION_NAMES\")\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"feature\",\n    \"flag_group\",\n    \"flag_set\",\n    \"with_feature_set\",\n)\nload(\n    \":cc_toolchain_actions.bzl\",\n    \"all_compile_actions\",\n    \"all_cpp_compile_actions\",\n    \"all_link_actions\",\n    \"codegen_compile_actions\",\n    \"preprocessor_compile_actions\",\n)\n\nclang_feature = feature(\n    name = \"clang\",\n    enabled = True,\n    flag_sets = [\n        flag_set(\n            actions = all_compile_actions + all_link_actions,\n            flag_groups = [\n                flag_group(flags = [\n                    \"-no-canonical-prefixes\",\n                    \"-fcolor-diagnostics\",\n                ]),\n                flag_group(\n                    expand_if_available = \"sysroot\",\n                    flags = [\"--sysroot=%{sysroot}\"],\n                ),\n            ],\n        ),\n        flag_set(\n            actions = all_compile_actions,\n            flag_groups = [\n                flag_group(flags = [\n                    # Compile actions shouldn't link anything.\n                    \"-c\",\n                ]),\n\n                # Flags controlling the production of specific outputs from\n                # compile actions.\n                flag_group(\n                    expand_if_available = \"output_assembly_file\",\n                    flags = [\"-S\"],\n                ),\n                flag_group(\n                    expand_if_available = \"output_preprocess_file\",\n                    flags = [\"-E\"],\n                ),\n                flag_group(\n                    expand_if_available = \"dependency_file\",\n                    flags = [\"-MD\", \"-MF\", \"%{dependency_file}\"],\n                ),\n                flag_group(\n                    expand_if_available = \"output_file\",\n                    flags = [\"-frandom-seed=%{output_file}\"],\n                ),\n            ],\n        ),\n        flag_set(\n            # Flags specific to compiling C++ sources.\n            actions = all_cpp_compile_actions,\n            flag_groups = [flag_group(flags = [\n                \"-std=c++20\",\n            ])],\n        ),\n        flag_set(\n            actions = codegen_compile_actions,\n            flag_groups = [flag_group(flags = [\n                \"-ffunction-sections\",\n                \"-fdata-sections\",\n            ])],\n        ),\n        flag_set(\n            actions = codegen_compile_actions,\n            flag_groups = [flag_group(\n                expand_if_available = \"pic\",\n                flags = [\"-fPIC\"],\n            )],\n        ),\n        flag_set(\n            actions = preprocessor_compile_actions,\n            flag_groups = [\n                flag_group(flags = [\n                    # Disable a warning and override builtin macros to\n                    # ensure a hermetic build.\n                    \"-Wno-builtin-macro-redefined\",\n                    \"-D__DATE__=\\\"redacted\\\"\",\n                    \"-D__TIMESTAMP__=\\\"redacted\\\"\",\n                    \"-D__TIME__=\\\"redacted\\\"\",\n                ]),\n                flag_group(\n                    flags = [\"-D%{preprocessor_defines}\"],\n                    iterate_over = \"preprocessor_defines\",\n                ),\n                flag_group(\n                    expand_if_available = \"includes\",\n                    flags = [\"-include\", \"%{includes}\"],\n                    iterate_over = \"includes\",\n                ),\n                flag_group(\n                    flags = [\"-iquote\", \"%{quote_include_paths}\"],\n                    iterate_over = \"quote_include_paths\",\n                ),\n                flag_group(\n                    flags = [\"-I%{include_paths}\"],\n                    iterate_over = \"include_paths\",\n                ),\n                flag_group(\n                    flags = [\"-isystem\", \"%{system_include_paths}\"],\n                    iterate_over = \"system_include_paths\",\n                ),\n            ],\n        ),\n        flag_set(\n            actions = [\n                ACTION_NAMES.cpp_link_dynamic_library,\n                ACTION_NAMES.cpp_link_nodeps_dynamic_library,\n            ],\n            flag_groups = [flag_group(flags = [\"-shared\"])],\n        ),\n        flag_set(\n            actions = all_link_actions,\n            flag_groups = [\n                flag_group(\n                    expand_if_available = \"strip_debug_symbols\",\n                    flags = [\"-Wl,-S\"],\n                ),\n                flag_group(\n                    expand_if_available = \"library_search_directories\",\n                    flags = [\"-L%{library_search_directories}\"],\n                    iterate_over = \"library_search_directories\",\n                ),\n                flag_group(\n                    expand_if_available =\n                        \"runtime_library_search_directories\",\n                    iterate_over = \"runtime_library_search_directories\",\n                    flags = [\n                        \"-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}\",\n                    ],\n                ),\n            ],\n        ),\n        flag_set(\n            actions = all_link_actions,\n            flag_groups = [\n                flag_group(\n                    flags = [\n                        \"-fuse-ld=lld\",\n                        # Force the C++ standard library and runtime libraries\n                        # to be statically linked. This works even with libc++\n                        # and libunwind despite the names, provided libc++ is\n                        # built with the CMake option:\n                        # - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`\n                        \"-static-libstdc++\",\n                        \"-static-libgcc\",\n                        # Link with Clang's runtime library. This is always\n                        # linked statically.\n                        \"-rtlib=compiler-rt\",\n                        # Link with pthread.\n                        \"-lpthread\",\n                    ],\n                ),\n            ],\n            with_features = [with_feature_set([\"linux_target\"])],\n        ),\n        flag_set(\n            actions = [ACTION_NAMES.cpp_link_executable],\n            flag_groups = [flag_group(\n                expand_if_available = \"force_pic\",\n                flags = [\"-pie\"],\n            )],\n            with_features = [with_feature_set([\n                \"linux_target\",\n                \"freebsd_target\",\n            ])],\n        ),\n        flag_set(\n            actions = [ACTION_NAMES.cpp_link_executable],\n            flag_groups = [flag_group(\n                expand_if_available = \"force_pic\",\n                flags = [\"-fpie\"],\n            )],\n            with_features = [with_feature_set([\"macos_target\"])],\n        ),\n    ],\n)\n\nclang_warnings_feature = feature(\n    name = \"clang_warnings\",\n    enabled = True,\n    flag_sets = [flag_set(\n        actions = all_compile_actions,\n        flag_groups = [flag_group(flags = [\n            \"-Werror\",\n            \"-Wall\",\n            \"-Wextra\",\n            \"-Wthread-safety\",\n            \"-Wself-assign\",\n            \"-Wimplicit-fallthrough\",\n            \"-Wctad-maybe-unsupported\",\n            \"-Wextra-semi\",\n            \"-Wmissing-prototypes\",\n            \"-Wzero-as-null-pointer-constant\",\n            \"-Wdelete-non-virtual-dtor\",\n\n            # TODO: Regression that warns on anonymous unions; remove depending\n            # on fix.\n            \"-Wno-missing-designated-field-initializers\",\n        ])],\n    )],\n)\n\n# Libc++ HARDENING_MODE has 4 possible values:\n# https://libcxx.llvm.org/Hardening.html#notes-for-users\n#\n# Do not enable DEBUG hardening mode, even for -c dbg, because its performance\n# impact on llvm-symbolizer is too severe -- this flag results in symbolization\n# becoming quadratic in the number of debug symbols, in practice meaning it\n# never completes.\n_libcpp_debug_flags = [\n    \"-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE\",\n]\n_libcpp_release_flags = [\n    \"-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST\",\n]\n\ndef libcxx_feature(llvm_bindir = None, clang_bindir = None):\n    \"\"\"Builds a libc++ feature.\n\n    Returns:\n        The feature for use with `cc_toolchain_config`.\n\n    Args:\n        llvm_bindir: Optional LLVM installation `bin` directory, causes the\n            feature to look for adjacent installed libraries.\n        clang_bindir: Optional Clang installation `bin` directory, causes the\n            feature to look for adjacent installed libraries if different from\n            `llvm_bindir`.\n    \"\"\"\n\n    # Explicitly add LLVM libs to the search path to preempt the\n    # detected GCC installation's library paths. Those might have a\n    # system installed libc++ and we want to find the one next to\n    # our Clang.\n    extra_link_flags = []\n    if llvm_bindir:\n        extra_link_flags.append(\"-L\" + llvm_bindir + \"/../lib\")\n    if clang_bindir and clang_bindir != llvm_bindir:\n        extra_link_flags.append(\"-L\" + clang_bindir + \"/../lib\")\n\n    return feature(\n        name = \"libcxx\",\n        enabled = True,\n        flag_sets = [\n            flag_set(\n                actions = all_cpp_compile_actions + all_link_actions,\n                flag_groups = [flag_group(flags = [\n                    \"-stdlib=libc++\",\n                ])],\n                with_features = [\n                    # libc++ is only used on non-Windows platforms.\n                    with_feature_set(not_features = [\"windows_target\"]),\n                ],\n            ),\n            flag_set(\n                actions = all_cpp_compile_actions,\n                flag_groups = [flag_group(flags = _libcpp_debug_flags)],\n                with_features = [with_feature_set(not_features = [\"opt\"])],\n            ),\n            flag_set(\n                actions = all_cpp_compile_actions,\n                flag_groups = [flag_group(flags = _libcpp_release_flags)],\n                with_features = [with_feature_set(features = [\"opt\"])],\n            ),\n            flag_set(\n                actions = all_link_actions,\n                flag_groups = [flag_group(flags = [\n                    \"-unwindlib=libunwind\",\n                ])],\n                with_features = [\n                    # libc++ is only used on non-Windows platforms.\n                    with_feature_set(not_features = [\"windows_target\"]),\n                ],\n            ),\n            flag_set(\n                actions = all_link_actions,\n                flag_groups = [flag_group(flags = extra_link_flags + [\n                    # Force linking the static libc++abi archive here. This\n                    # *should* be linked automatically, but not every release of\n                    # LLVM correctly sets the CMake flags to do so.\n                    \"-l:libc++abi.a\",\n                ])],\n                with_features = [with_feature_set([\"linux_target\"])],\n            ),\n        ],\n    )\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_debugging.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Definitions of debugging related features used in a `cc_toolchain_config`.\"\"\"\n\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"feature\",\n    \"feature_set\",\n    \"flag_group\",\n    \"flag_set\",\n)\nload(\n    \":cc_toolchain_actions.bzl\",\n    \"all_link_actions\",\n    \"codegen_compile_actions\",\n)\n\n# Handle different levels and forms of debug info emission with individual\n# features so that they can be ordered and the defaults can override the\n# minimal settings if both are enabled.\nminimal_debug_info_flags = feature(\n    name = \"minimal_debug_info_flags\",\n    implies = [\"debug_info_compression_flags\"],\n    flag_sets = [flag_set(\n        actions = codegen_compile_actions,\n        flag_groups = [flag_group(flags = [\"-gmlt\"])],\n    )],\n)\ndebug_info_flags = feature(\n    name = \"debug_info_flags\",\n    implies = [\"debug_info_compression_flags\"],\n    flag_sets = [flag_set(\n        actions = codegen_compile_actions,\n        flag_groups = [\n            flag_group(flags = [\"-g\"]),\n            flag_group(\n                expand_if_available = \"per_object_debug_info_file\",\n                flags = [\"-gsplit-dwarf\"],\n            ),\n        ],\n    )],\n)\ndebug_info_compression_flags = feature(\n    name = \"debug_info_compression_flags\",\n    flag_sets = [flag_set(\n        actions = codegen_compile_actions + all_link_actions,\n        flag_groups = [flag_group(flags = [\"-gz\"])],\n    )],\n)\n\n# Define a set of mutually exclusive debugger flags.\ndebugger_flags = feature(name = \"debugger_flags\")\nlldb_flags = feature(\n    # Use a convenient name for users to select if needed.\n    name = \"lldb_flags\",\n    # Default enable LLDB-optimized flags whenever debugging.\n    enabled = True,\n    requires = [feature_set(features = [\"debug_info_flags\"])],\n    provides = [\"debugger_flags\"],\n    flag_sets = [flag_set(\n        actions = codegen_compile_actions,\n        flag_groups = [flag_group(flags = [\n            \"-glldb\",\n            \"-gpubnames\",\n            \"-gsimple-template-names\",\n        ])],\n    )],\n)\ngdb_flags = feature(\n    # Use a convenient name for users to select if needed.\n    name = \"gdb_flags\",\n    requires = [feature_set(features = [\"debug_info_flags\"])],\n    provides = [\"debugger_flags\"],\n    flag_sets = [\n        flag_set(\n            actions = codegen_compile_actions,\n            flag_groups = [flag_group(flags = [\n                \"-ggdb\",\n                \"-ggnu-pubnames\",\n            ])],\n        ),\n        flag_set(\n            actions = all_link_actions,\n            flag_groups = [flag_group(flags = [\"-Wl,--gdb-index\"])],\n        ),\n    ],\n)\n\n# This feature can be enabled in conjunction with any optimizations to\n# ensure accurate call stacks and backtraces for profilers or errors.\npreserve_call_stacks = feature(\n    name = \"preserve_call_stacks\",\n    flag_sets = [flag_set(\n        actions = codegen_compile_actions,\n        flag_groups = [flag_group(flags = [\n            # Ensure good backtraces by preserving frame pointers and\n            # disabling tail call elimination.\n            \"-fno-omit-frame-pointer\",\n            \"-mno-omit-leaf-frame-pointer\",\n            \"-fno-optimize-sibling-calls\",\n        ])],\n    )],\n)\n\n# Enable split debug info whenever debug info is requested.\nenable_split_debug_info = feature(\n    name = \"per_object_debug_info\",\n    enabled = True,\n    # This has to be directly conditioned on requesting debug info at\n    # all, otherwise Bazel will look for an extra output file and not\n    # find one.\n    requires = [feature_set(features = [\"debug_info_flags\"])],\n)\n\n# Enable debug info whenever in the `dbg` build mode. We do this separately from\n# the `debug_info_flags` feature itself as other things may want to enable that\n# feature as well.\nenable_debug_info_in_dbg = feature(\n    name = \"enable_debug_info_in_dbg\",\n    enabled = True,\n    requires = [feature_set([\"dbg\"])],\n    implies = [\"debug_info_flags\"],\n)\n\n# Note that the order of features is significant in this list and determines the\n# relative order of flags from the features listed.\ndebugging_features = [\n    minimal_debug_info_flags,\n    debug_info_flags,\n    debug_info_compression_flags,\n    debugger_flags,\n    lldb_flags,\n    gdb_flags,\n    preserve_call_stacks,\n    enable_split_debug_info,\n    enable_debug_info_in_dbg,\n]\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_features.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Helpers to construct ordered sequences of `cc_toolchain` features.\"\"\"\n\nload(\n    \":cc_toolchain_base_features.bzl\",\n    \"base_features\",\n    \"output_flags_feature\",\n    \"user_flags_feature\",\n)\nload(\n    \":cc_toolchain_config_features.bzl\",\n    \"target_cpu_features\",\n    \"target_os_features\",\n)\nload(\n    \":cc_toolchain_cpp_features.bzl\",\n    \"clang_feature\",\n    \"clang_warnings_feature\",\n)\nload(\":cc_toolchain_debugging.bzl\", \"debugging_features\")\nload(\":cc_toolchain_linking.bzl\", \"linking_features\")\nload(\":cc_toolchain_modules.bzl\", \"modules_features\")\nload(\":cc_toolchain_optimization.bzl\", \"optimization_features\")\nload(\":cc_toolchain_sanitizer_features.bzl\", \"sanitizer_features\")\n\ndef clang_cc_toolchain_features(\n        target_os,\n        target_cpu,\n        project_features = [],\n        extra_cpp_features = []):\n    \"\"\"Builds a sequence of Clang-oriented `cc_toolchain_config` features.\n\n    Returns:\n        The list of features for calling `create_cc_toolchain_config_info`.\n\n    Args:\n        target_os: Used to select OS-specific features to include.\n        target_cpu: Used to select CPU-specific features to include.\n        project_features: Optional list of project-specific features to include.\n        extra_cpp_features: Optional list of extra C++ features to include, for\n            example `libcxx_feature` can be passed here to enable using libc++.\n    \"\"\"\n\n    # The order of the features determines the relative order of flags used.\n    features = []\n    features += target_os_features(target_os)\n    features += target_cpu_features(target_cpu)\n    features += base_features\n    features += [\n        # We always use Clang in the toolchain and enable all of its warnings.\n        clang_feature,\n        clang_warnings_feature,\n    ]\n\n    # Enable any extra baseline C++ features here where others can override\n    # their flags if needed.\n    features += extra_cpp_features\n\n    features += sanitizer_features\n    features += optimization_features\n    features += modules_features\n    features += debugging_features\n    features += linking_features\n\n    # Lastly, we add project features and the user flags so they can override\n    # anything above, and the output flags last of all for ease of debugging.\n    features += project_features\n    features += [\n        user_flags_feature,\n        output_flags_feature,\n    ]\n    return features\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_linking.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Definitions of linking related features used in a `cc_toolchain_config`.\"\"\"\n\nload(\"@rules_cc//cc:action_names.bzl\", \"ACTION_NAMES\")\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"feature\",\n    \"flag_group\",\n    \"flag_set\",\n    \"variable_with_value\",\n    \"with_feature_set\",\n)\nload(\n    \":cc_toolchain_actions.bzl\",\n    \"all_link_actions\",\n)\n\nlink_libraries_feature = feature(\n    name = \"link_libraries\",\n    enabled = True,\n    flag_sets = [\n        flag_set(\n            actions = all_link_actions,\n            flag_groups = [\n                flag_group(\n                    expand_if_available = \"linkstamp_paths\",\n                    flags = [\"%{linkstamp_paths}\"],\n                    iterate_over = \"linkstamp_paths\",\n                ),\n                flag_group(\n                    expand_if_available = \"libraries_to_link\",\n                    flag_groups = [\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"object_file_group\",\n                            ),\n                            flags = [\"-Wl,--start-lib\"],\n                        ),\n                        flag_group(\n                            expand_if_true = \"libraries_to_link.is_whole_archive\",\n                            flags = [\"-Wl,-whole-archive\"],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"object_file_group\",\n                            ),\n                            flags = [\"%{libraries_to_link.object_files}\"],\n                            iterate_over = \"libraries_to_link.object_files\",\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"object_file\",\n                            ),\n                            flags = [\"%{libraries_to_link.name}\"],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"interface_library\",\n                            ),\n                            flags = [\"%{libraries_to_link.name}\"],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"static_library\",\n                            ),\n                            flags = [\"%{libraries_to_link.name}\"],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"dynamic_library\",\n                            ),\n                            flags = [\"-l%{libraries_to_link.name}\"],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"versioned_dynamic_library\",\n                            ),\n                            flags = [\"-l:%{libraries_to_link.name}\"],\n                        ),\n                        flag_group(\n                            expand_if_true = \"libraries_to_link.is_whole_archive\",\n                            flags = [\"-Wl,-no-whole-archive\"],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"object_file_group\",\n                            ),\n                            flags = [\"-Wl,--end-lib\"],\n                        ),\n                    ],\n                    iterate_over = \"libraries_to_link\",\n                ),\n                # Note that the params file comes at the end, after the\n                # libraries to link above.\n                flag_group(\n                    expand_if_available = \"linker_param_file\",\n                    flags = [\"@%{linker_param_file}\"],\n                ),\n            ],\n            with_features = [with_feature_set(not_features = [\"macos_target\"])],\n        ),\n        flag_set(\n            actions = all_link_actions,\n            flag_groups = [\n                flag_group(\n                    expand_if_available = \"linkstamp_paths\",\n                    flags = [\"%{linkstamp_paths}\"],\n                    iterate_over = \"linkstamp_paths\",\n                ),\n                flag_group(\n                    expand_if_available = \"libraries_to_link\",\n                    flag_groups = [\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"object_file_group\",\n                            ),\n                            flags = [\"-Wl,--start-lib\"],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"object_file_group\",\n                            ),\n                            flag_groups = [\n                                flag_group(\n                                    expand_if_false = \"libraries_to_link.is_whole_archive\",\n                                    flags = [\"%{libraries_to_link.object_files}\"],\n                                ),\n                                flag_group(\n                                    expand_if_true = \"libraries_to_link.is_whole_archive\",\n                                    flags = [\"-Wl,-force_load,%{libraries_to_link.object_files}\"],\n                                ),\n                            ],\n                            iterate_over = \"libraries_to_link.object_files\",\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"object_file\",\n                            ),\n                            flag_groups = [\n                                flag_group(\n                                    expand_if_false = \"libraries_to_link.is_whole_archive\",\n                                    flags = [\"%{libraries_to_link.name}\"],\n                                ),\n                                flag_group(\n                                    expand_if_true = \"libraries_to_link.is_whole_archive\",\n                                    flags = [\"-Wl,-force_load,%{libraries_to_link.name}\"],\n                                ),\n                            ],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"interface_library\",\n                            ),\n                            flag_groups = [\n                                flag_group(\n                                    expand_if_false = \"libraries_to_link.is_whole_archive\",\n                                    flags = [\"%{libraries_to_link.name}\"],\n                                ),\n                                flag_group(\n                                    expand_if_true = \"libraries_to_link.is_whole_archive\",\n                                    flags = [\"-Wl,-force_load,%{libraries_to_link.name}\"],\n                                ),\n                            ],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"static_library\",\n                            ),\n                            flag_groups = [\n                                flag_group(\n                                    expand_if_false = \"libraries_to_link.is_whole_archive\",\n                                    flags = [\"%{libraries_to_link.name}\"],\n                                ),\n                                flag_group(\n                                    expand_if_true = \"libraries_to_link.is_whole_archive\",\n                                    flags = [\"-Wl,-force_load,%{libraries_to_link.name}\"],\n                                ),\n                            ],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"dynamic_library\",\n                            ),\n                            flags = [\"-l%{libraries_to_link.name}\"],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"versioned_dynamic_library\",\n                            ),\n                            flags = [\"-l:%{libraries_to_link.name}\"],\n                        ),\n                        flag_group(\n                            expand_if_true = \"libraries_to_link.is_whole_archive\",\n                            flag_groups = [\n                                flag_group(\n                                    expand_if_false = \"macos_flags\",\n                                    flags = [\"-Wl,-no-whole-archive\"],\n                                ),\n                            ],\n                        ),\n                        flag_group(\n                            expand_if_equal = variable_with_value(\n                                name = \"libraries_to_link.type\",\n                                value = \"object_file_group\",\n                            ),\n                            flags = [\"-Wl,--end-lib\"],\n                        ),\n                    ],\n                    iterate_over = \"libraries_to_link\",\n                ),\n                # Note that the params file comes at the end, after the\n                # libraries to link above.\n                flag_group(\n                    expand_if_available = \"linker_param_file\",\n                    flags = [\"@%{linker_param_file}\"],\n                ),\n            ],\n            with_features = [with_feature_set([\"macos_target\"])],\n        ),\n    ],\n)\n\n# Archive actions have an entirely independent set of flags and don't\n# interact with either compiler or link actions.\narchiving_feature = feature(\n    name = \"archiving\",\n    enabled = True,\n    flag_sets = [flag_set(\n        actions = [ACTION_NAMES.cpp_link_static_library],\n        flag_groups = [\n            flag_group(flags = [\"rcsD\"]),\n            flag_group(\n                expand_if_available = \"output_execpath\",\n                flags = [\"%{output_execpath}\"],\n            ),\n            flag_group(\n                expand_if_available = \"libraries_to_link\",\n                flag_groups = [\n                    flag_group(\n                        expand_if_equal = variable_with_value(\n                            name = \"libraries_to_link.type\",\n                            value = \"object_file\",\n                        ),\n                        flags = [\"%{libraries_to_link.name}\"],\n                    ),\n                    flag_group(\n                        expand_if_equal = variable_with_value(\n                            name = \"libraries_to_link.type\",\n                            value = \"object_file_group\",\n                        ),\n                        flags = [\"%{libraries_to_link.object_files}\"],\n                        iterate_over = \"libraries_to_link.object_files\",\n                    ),\n                ],\n                iterate_over = \"libraries_to_link\",\n            ),\n            flag_group(\n                expand_if_available = \"linker_param_file\",\n                flags = [\"@%{linker_param_file}\"],\n            ),\n        ],\n    )],\n)\n\n# Note that the order of features is significant in this list and determines the\n# relative order of flags from the features listed.\nlinking_features = [\n    link_libraries_feature,\n    archiving_feature,\n]\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_modules.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Definitions of C++ and Clang header modules toolchain features.\"\"\"\n\nload(\"@rules_cc//cc:action_names.bzl\", \"ACTION_NAMES\")\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"feature\",\n    \"feature_set\",\n    \"flag_group\",\n    \"flag_set\",\n)\n\nuse_module_maps = feature(\n    name = \"use_module_maps\",\n    requires = [feature_set(features = [\"module_maps\"])],\n    flag_sets = [\n        flag_set(\n            actions = [\n                ACTION_NAMES.c_compile,\n                ACTION_NAMES.cpp_compile,\n                ACTION_NAMES.cpp_header_parsing,\n                ACTION_NAMES.cpp_module_compile,\n            ],\n            flag_groups = [\n                # These flag groups are separate so they do not expand to\n                # the cross product of the variables.\n                flag_group(flags = [\"-fmodule-name=%{module_name}\"]),\n                flag_group(\n                    flags = [\"-fmodule-map-file=%{module_map_file}\"],\n                ),\n            ],\n        ),\n    ],\n)\n\n# Tell bazel we support module maps in general, so they will be generated\n# for all c/c++ rules.\n# Note: not all C++ rules support module maps; thus, do not imply this\n# feature from other features - instead, require it.\nmodule_maps = feature(\n    name = \"module_maps\",\n    enabled = True,\n    implies = [\n        # \"module_map_home_cwd\",\n        # \"module_map_without_extern_module\",\n        # \"generate_submodules\",\n    ],\n)\n\nlayering_check = feature(\n    name = \"layering_check\",\n    implies = [\"use_module_maps\"],\n    flag_sets = [flag_set(\n        actions = [\n            ACTION_NAMES.c_compile,\n            ACTION_NAMES.cpp_compile,\n            ACTION_NAMES.cpp_header_parsing,\n            ACTION_NAMES.cpp_module_compile,\n        ],\n        flag_groups = [\n            flag_group(flags = [\n                \"-fmodules-strict-decluse\",\n                \"-Wprivate-header\",\n            ]),\n            flag_group(\n                iterate_over = \"dependent_module_map_files\",\n                flags = [\"-fmodule-map-file=%{dependent_module_map_files}\"],\n            ),\n        ],\n    )],\n)\n\n# Note that the order of features is significant in this list and determines the\n# relative order of flags from the features listed.\nmodules_features = [\n    layering_check,\n    module_maps,\n    use_module_maps,\n]\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_optimization.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Definitions of optimization `cc_toolchain_config` features.\"\"\"\n\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"feature\",\n    \"feature_set\",\n    \"flag_group\",\n    \"flag_set\",\n    \"with_feature_set\",\n)\nload(\n    \":cc_toolchain_actions.bzl\",\n    \"all_compile_actions\",\n    \"all_link_actions\",\n    \"codegen_compile_actions\",\n)\n\n# Handle different levels of optimization with individual features so that\n# they can be ordered and the defaults can override the minimal settings if\n# both are enabled.\nminimal_optimization_flags = feature(\n    name = \"minimal_optimization_flags\",\n    flag_sets = [flag_set(\n        actions = codegen_compile_actions,\n        flag_groups = [flag_group(flags = [\"-O1\"])],\n    )],\n)\ndefault_optimization_flags = feature(\n    name = \"default_optimization_flags\",\n    enabled = True,\n    requires = [feature_set([\"opt\"])],\n    flag_sets = [\n        flag_set(\n            actions = all_compile_actions,\n            flag_groups = [flag_group(flags = [\"-DNDEBUG\"])],\n        ),\n        flag_set(\n            actions = codegen_compile_actions,\n            flag_groups = [flag_group(flags = [\"-O3\"])],\n        ),\n    ],\n)\n\ncpu_flags = feature(\n    name = \"aarch64_cpu_flags\",\n    enabled = True,\n    flag_sets = [\n        flag_set(\n            actions = all_compile_actions + all_link_actions,\n            flag_groups = [flag_group(flags = [\"-march=armv8.2-a\"])],\n            with_features = [with_feature_set([\"aarch64_target\"])],\n        ),\n        flag_set(\n            actions = all_compile_actions + all_link_actions,\n            flag_groups = [flag_group(flags = [\"-march=x86-64-v2\"])],\n            with_features = [with_feature_set([\"x86_64_target\"])],\n        ),\n    ],\n)\n\n# Note that the order of features is significant in this list and determines the\n# relative order of flags from the features listed.\noptimization_features = [\n    minimal_optimization_flags,\n    default_optimization_flags,\n    cpu_flags,\n]\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_sanitizer_features.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Definitions of sanitizer-related `cc_toolchain_config` features.\"\"\"\n\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"feature\",\n    \"feature_set\",\n    \"flag_group\",\n    \"flag_set\",\n    \"with_feature_set\",\n)\nload(\n    \":cc_toolchain_actions.bzl\",\n    \"all_compile_actions\",\n    \"all_link_actions\",\n)\n\nsanitizer_common_flags = feature(\n    name = \"sanitizer_common_flags\",\n    implies = [\"minimal_debug_info_flags\", \"preserve_call_stacks\"],\n    flag_sets = [flag_set(\n        actions = all_link_actions,\n        flag_groups = [flag_group(flags = [\"-static-libsan\"])],\n        with_features = [\n            with_feature_set([\"linux_target\"]),\n            with_feature_set([\"freebsd_target\"]),\n        ],\n    )],\n)\n\nasan = feature(\n    name = \"asan\",\n    implies = [\"sanitizer_common_flags\"],\n    flag_sets = [flag_set(\n        actions = all_compile_actions + all_link_actions,\n        flag_groups = [flag_group(flags = [\n            \"-fsanitize=address,undefined,nullability\",\n            \"-fsanitize-address-use-after-scope\",\n            # Outlining is almost always the right tradeoff for our\n            # sanitizer usage where we're more pressured on generated code\n            # size than runtime performance.\n            \"-fsanitize-address-outline-instrumentation\",\n            # We don't need the recovery behavior of UBSan as we expect\n            # builds to be clean. Not recovering is a bit cheaper.\n            \"-fno-sanitize-recover=undefined,nullability\",\n            # Don't embed the full path name for files. This limits the size\n            # and combined with line numbers is unlikely to result in many\n            # ambiguities.\n            \"-fsanitize-undefined-strip-path-components=-1\",\n            # Needed due to clang AST issues, such as in\n            # clang/AST/Redeclarable.h line 199.\n            \"-fno-sanitize=vptr\",\n        ])],\n    )],\n)\n\n# A feature that further reduces the generated code size of our the ASan\n# feature, but at the cost of lower quality diagnostics. This is enabled\n# along with ASan in our fastbuild configuration, but can be disabled\n# explicitly to get better error messages.\nasan_min_size = feature(\n    name = \"asan_min_size\",\n    requires = [feature_set([\"asan\"])],\n    flag_sets = [flag_set(\n        actions = all_compile_actions + all_link_actions,\n        flag_groups = [flag_group(flags = [\n            # Force two UBSan checks that have especially large code size\n            # cost to use the minimal branch to a trapping instruction model\n            # instead of the full diagnostic.\n            \"-fsanitize-trap=alignment,null\",\n        ])],\n    )],\n)\n\nfuzzer = feature(\n    name = \"fuzzer\",\n    flag_sets = [flag_set(\n        actions = all_compile_actions + all_link_actions,\n        flag_groups = [flag_group(flags = [\n            \"-fsanitize=fuzzer-no-link\",\n        ])],\n    )],\n)\n\nsanitizer_workarounds = feature(\n    name = \"sanitizer_workarounds\",\n    enabled = True,\n    requires = [feature_set([\"asan\"])],\n    flag_sets = [flag_set(\n        actions = all_compile_actions + all_link_actions,\n        flag_groups = [flag_group(flags = [\n            # Likely due to being unable to use the static-linked and up-to-date\n            # sanitizer runtimes, we have to disable this sanitizer on macOS.\n            \"-fno-sanitize=function\",\n        ])],\n        with_features = [with_feature_set([\"macos_target\"])],\n    )],\n)\n\n# Note that the order of features is significant in this list and determines the\n# relative order of flags from the features listed.\nsanitizer_features = [\n    sanitizer_common_flags,\n    asan,\n    asan_min_size,\n    fuzzer,\n\n    # Note that the workarounds must come last here to override earlier flags.\n    sanitizer_workarounds,\n]\n"
  },
  {
    "path": "bazel/cc_toolchains/cc_toolchain_tools.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Macros to produce tool-related parts of a `cc_toolchain_config`.\n\nThese macros cover both the `actions_config` array and the `tool_paths` array.\n\nThey presume an LLVM and Clang toolchain's tools, but support both a single\ninstallation and installations that split the LLVM tools and Clang tools apart.\n\"\"\"\n\nload(\"@rules_cc//cc:action_names.bzl\", \"ACTION_NAMES\")\nload(\n    \"@rules_cc//cc:cc_toolchain_config_lib.bzl\",\n    \"action_config\",\n    \"tool\",\n    \"tool_path\",\n)\nload(\n    \":cc_toolchain_actions.bzl\",\n    \"all_c_compile_actions\",\n    \"all_cpp_compile_actions\",\n    \"all_link_actions\",\n)\n\ndef llvm_tool_paths(llvm_bindir, clang_bindir = None):\n    if not clang_bindir:\n        clang_bindir = llvm_bindir\n    return [\n        tool_path(name = \"ar\", path = llvm_bindir + \"/llvm-ar\"),\n        tool_path(name = \"ld\", path = clang_bindir + \"/ld.lld\"),\n        tool_path(name = \"cpp\", path = clang_bindir + \"/clang-cpp\"),\n        tool_path(name = \"gcc\", path = clang_bindir + \"/clang++\"),\n        tool_path(name = \"dwp\", path = llvm_bindir + \"/llvm-dwp\"),\n        tool_path(name = \"gcov\", path = llvm_bindir + \"/llvm-cov\"),\n        tool_path(name = \"nm\", path = llvm_bindir + \"/llvm-nm\"),\n        tool_path(name = \"objcopy\", path = llvm_bindir + \"/llvm-objcopy\"),\n        tool_path(name = \"objdump\", path = llvm_bindir + \"/llvm-objdump\"),\n        tool_path(name = \"strip\", path = llvm_bindir + \"/llvm-strip\"),\n    ]\n\ndef llvm_action_configs(llvm_bindir, clang_bindir = None):\n    if not clang_bindir:\n        clang_bindir = llvm_bindir\n    return [\n        action_config(\n            action_name = name,\n            enabled = True,\n            tools = [tool(path = clang_bindir + \"/clang\")],\n        )\n        for name in all_c_compile_actions\n    ] + [\n        action_config(\n            action_name = name,\n            enabled = True,\n            tools = [tool(path = clang_bindir + \"/clang++\")],\n        )\n        for name in all_cpp_compile_actions\n    ] + [\n        action_config(\n            action_name = name,\n            enabled = True,\n            tools = [tool(path = clang_bindir + \"/clang++\")],\n        )\n        for name in all_link_actions\n    ] + [\n        action_config(\n            action_name = name,\n            enabled = True,\n            tools = [tool(path = llvm_bindir + \"/llvm-ar\")],\n        )\n        for name in [ACTION_NAMES.cpp_link_static_library]\n    ] + [\n        action_config(\n            action_name = name,\n            enabled = True,\n            tools = [tool(path = llvm_bindir + \"/llvm-strip\")],\n        )\n        for name in [ACTION_NAMES.strip]\n    ]\n"
  },
  {
    "path": "bazel/cc_toolchains/clang_cc_toolchain_config.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"A Starlark cc_toolchain configuration rule\"\"\"\n\nload(\"@rules_cc//cc:defs.bzl\", \"cc_toolchain\")\nload(\"@rules_cc//cc/common:cc_common.bzl\", \"cc_common\")\nload(\":cc_toolchain_carbon_project_features.bzl\", \"carbon_project_features\")\nload(\":cc_toolchain_cpp_features.bzl\", \"libcxx_feature\")\nload(\":cc_toolchain_features.bzl\", \"clang_cc_toolchain_features\")\nload(\n    \":cc_toolchain_tools.bzl\",\n    \"llvm_action_configs\",\n    \"llvm_tool_paths\",\n)\nload(\n    \":clang_detected_variables.bzl\",\n    \"clang_bindir\",\n    \"clang_include_dirs_list\",\n    \"clang_resource_dir\",\n    \"clang_version_for_cache\",\n    \"llvm_bindir\",\n    \"sysroot_dir\",\n)\n\ndef _impl(ctx):\n    # Only use a sysroot if one was found when detecting Clang.\n    sysroot = None\n    if sysroot_dir != \"None\":\n        sysroot = sysroot_dir\n\n    identifier = \"local-{0}-{1}\".format(ctx.attr.target_cpu, ctx.attr.target_os)\n    return cc_common.create_cc_toolchain_config_info(\n        ctx = ctx,\n        features = clang_cc_toolchain_features(\n            target_os = ctx.attr.target_os,\n            target_cpu = ctx.attr.target_cpu,\n            project_features = carbon_project_features(clang_version_for_cache),\n            extra_cpp_features = [libcxx_feature(llvm_bindir, clang_bindir)],\n        ),\n        action_configs = llvm_action_configs(llvm_bindir, clang_bindir),\n        cxx_builtin_include_directories = clang_include_dirs_list + [\n            # Add Clang's resource directory to the end of the builtin include\n            # directories to cover the use of sanitizer resource files by the\n            # driver.\n            clang_resource_dir + \"/share\",\n        ],\n        builtin_sysroot = sysroot,\n\n        # This configuration only supports local non-cross builds so derive\n        # everything from the target CPU selected.\n        toolchain_identifier = identifier,\n\n        # This is used to expose a \"flag\" that `config_setting` rules can use to\n        # determine if the compiler is Clang.\n        compiler = \"clang\",\n\n        # We do have to pass in our tool paths.\n        tool_paths = llvm_tool_paths(llvm_bindir, clang_bindir),\n    )\n\ncc_toolchain_config = rule(\n    implementation = _impl,\n    attrs = {\n        \"target_cpu\": attr.string(mandatory = True),\n        \"target_os\": attr.string(mandatory = True),\n    },\n    provides = [CcToolchainConfigInfo],\n)\n\ndef cc_local_toolchain_suite(name, configs):\n    \"\"\"Create a toolchain suite that uses the local Clang/LLVM install.\n\n    Args:\n        name: The name of the toolchain suite to produce.\n        configs: An array of (os, cpu) pairs to support in the toolchain.\n    \"\"\"\n\n    # An empty filegroup to use when stubbing out the toolchains.\n    native.filegroup(\n        name = name + \"_empty\",\n        srcs = [],\n    )\n\n    # Create the individual local toolchains for each CPU.\n    for (os, cpu) in configs:\n        config_name = \"{0}_{1}_{2}\".format(name, os, cpu)\n        cc_toolchain_config(\n            name = config_name + \"_config\",\n            target_os = os,\n            target_cpu = cpu,\n        )\n        cc_toolchain(\n            name = config_name + \"_tools\",\n            all_files = \":\" + name + \"_empty\",\n            ar_files = \":\" + name + \"_empty\",\n            as_files = \":\" + name + \"_empty\",\n            compiler_files = \":\" + name + \"_empty\",\n            dwp_files = \":\" + name + \"_empty\",\n            linker_files = \":\" + name + \"_empty\",\n            objcopy_files = \":\" + name + \"_empty\",\n            strip_files = \":\" + name + \"_empty\",\n            supports_param_files = 1,\n            toolchain_config = \":\" + config_name + \"_config\",\n            toolchain_identifier = config_name,\n        )\n        compatible_with = [\"@platforms//cpu:\" + cpu, \"@platforms//os:\" + os]\n        native.toolchain(\n            name = config_name,\n            exec_compatible_with = compatible_with,\n            target_compatible_with = compatible_with,\n            toolchain = config_name + \"_tools\",\n            toolchain_type = \"@bazel_tools//tools/cpp:toolchain_type\",\n        )\n"
  },
  {
    "path": "bazel/cc_toolchains/clang_configuration.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Starlark repository rules to configure Clang (and LLVM) toolchain for Bazel.\n\nThese rules should be run from the `WORKSPACE` file to substitute appropriate\nconfigured values into a `clang_detected_variables.bzl` file that can be used\nby the actual toolchain configuration.\n\"\"\"\n\ndef _run(repository_ctx, cmd):\n    \"\"\"Runs the provided `cmd`, checks for failure, and returns the result.\"\"\"\n    exec_result = repository_ctx.execute(cmd)\n    if exec_result.return_code != 0:\n        fail(\"Command failed with return code {0}: {1}\\n{2}\".format(\n            exec_result.return_code,\n            str(cmd),\n            exec_result.stderr,\n        ))\n\n    return exec_result\n\ndef _clang_version(version_output):\n    \"\"\"Returns version information, or a (None, \"unknown\") tuple if not found.\n\n    Returns both the major version number (16) and the full version number for\n    caching.\n    \"\"\"\n    clang_version = None\n    clang_version_for_cache = \"unknown\"\n\n    version_prefix = \"clang version \"\n    version_start = version_output.find(version_prefix)\n    if version_start == -1:\n        # No version\n        return (clang_version, clang_version_for_cache)\n    version_start += len(version_prefix)\n\n    # Find the newline.\n    version_newline = version_output.find(\"\\n\", version_start)\n    if version_newline == -1:\n        return (clang_version, clang_version_for_cache)\n    clang_version_for_cache = version_output[version_start:version_newline]\n\n    # Find a dot to indicate something like 'clang version 16.0.1', and grab the\n    # major version.\n    version_dot = version_output.find(\".\", version_start)\n    if version_dot != -1 and version_dot < version_newline:\n        clang_version = int(version_output[version_start:version_dot])\n\n    return (clang_version, clang_version_for_cache)\n\ndef _detect_system_clang(repository_ctx):\n    \"\"\"Detects whether the system-provided clang can be used.\n\n    Returns a tuple of (is_clang, environment).\n    \"\"\"\n\n    # If the user provides an explicit `CC` environment variable, use that as\n    # the compiler. This should point at the `clang` executable to use.\n    cc = repository_ctx.os.environ.get(\"CC\")\n    cc_path = None\n    if cc:\n        cc_path = repository_ctx.path(cc)\n        if not cc_path.exists:\n            cc_path = repository_ctx.which(cc)\n    if not cc_path:\n        cc_path = repository_ctx.which(\"clang\")\n    if not cc_path:\n        fail(\"Cannot find clang or CC (%s); either correct your path or set the CC environment variable\" % cc)\n    version_output = _run(repository_ctx, [cc_path, \"--version\"]).stdout\n    if \"clang\" not in version_output:\n        fail(\"Searching for clang or CC (%s), and found (%s), which is not a Clang compiler\" % (cc, cc_path))\n    clang_version, clang_version_for_cache = _clang_version(version_output)\n    return (cc_path.realpath, clang_version, clang_version_for_cache)\n\ndef _compute_clang_resource_dir(repository_ctx, clang):\n    \"\"\"Runs the `clang` binary to get its resource dir.\"\"\"\n    output = _run(\n        repository_ctx,\n        [clang, \"-no-canonical-prefixes\", \"--print-resource-dir\"],\n    ).stdout\n\n    # The only line printed is this path.\n    return output.splitlines()[0]\n\ndef _compute_mac_os_sysroot(repository_ctx):\n    \"\"\"Runs `xcrun` to extract the correct sysroot.\"\"\"\n    xcrun = repository_ctx.which(\"xcrun\")\n    if not xcrun:\n        fail(\"`xcrun` not found: is Xcode installed?\")\n    output = _run(repository_ctx, [xcrun, \"--show-sdk-path\"]).stdout\n    return output.splitlines()[0]\n\ndef _compute_bsd_sysroot(repository_ctx):\n    \"\"\"Look around for sysroot. Return root (/) if nothing found.\"\"\"\n\n    # Try it-just-works for CMake users.\n    default = \"/\"\n    sysroot = repository_ctx.os.environ.get(\"CMAKE_SYSROOT\", default)\n    sysroot_path = repository_ctx.path(sysroot)\n    if sysroot_path.exists:\n        return sysroot_path.realpath\n    return default\n\n# File content used when computing search paths. This additionally verifies that\n# libc++ is installed.\n_CLANG_INCLUDE_FILE_CONTENT = \"\"\"\n#if __has_include(<version>)\n#include <version>\n#endif\n#ifndef _LIBCPP_STD_VER\n#error \"No libc++ install found!\"\n#endif\n\"\"\"\n\ndef _compute_clang_cpp_include_search_paths(repository_ctx, clang, sysroot):\n    \"\"\"Runs the `clang` binary and extracts the include search paths.\n\n    Returns the resulting paths as a list of strings.\n    \"\"\"\n\n    # Create a file for Clang to use as input.\n    repository_ctx.file(\"_temp\", _CLANG_INCLUDE_FILE_CONTENT)\n    input_file = repository_ctx.path(\"_temp\")\n\n    # The only way to get this out of Clang currently is to parse the verbose\n    # output of the compiler when it is compiling C++ code.\n    cmd = [\n        clang,\n        # Avoid canonicalizing away symlinks.\n        \"-no-canonical-prefixes\",\n        # Extract verbose output.\n        \"-v\",\n        # Just parse the input, don't generate outputs.\n        \"-fsyntax-only\",\n        # Force the language to be C++.\n        \"-x\",\n        \"c++\",\n        # Use the input file.\n        input_file,\n        # Always use libc++.\n        \"-stdlib=libc++\",\n    ]\n\n    # We need to use a sysroot to correctly represent a run on macOS.\n    if repository_ctx.os.name.lower().startswith(\"mac os\"):\n        if not sysroot:\n            fail(\"Must provide a sysroot on macOS!\")\n        cmd.append(\"--sysroot=\" + sysroot)\n\n    # Note that verbose output is on stderr, not stdout!\n    output = _run(repository_ctx, cmd).stderr.splitlines()\n\n    # Return the list of directories printed for system headers. These are the\n    # only ones that Bazel needs us to manually provide. We find these by\n    # searching for a begin and end marker. We also have to strip off a leading\n    # space from each path.\n    include_begin = output.index(\"#include <...> search starts here:\") + 1\n    include_end = output.index(\"End of search list.\", include_begin)\n\n    # Suffix present on framework paths.\n    framework_suffix = \" (framework directory)\"\n    return [\n        repository_ctx.path(s.lstrip(\" \").removesuffix(framework_suffix))\n        for s in output[include_begin:include_end]\n    ]\n\ndef _configure_clang_toolchain_impl(repository_ctx):\n    # First just symlink in the untemplated parts of the toolchain repo.\n    repository_ctx.symlink(repository_ctx.attr._clang_toolchain_build, \"BUILD\")\n    repository_ctx.symlink(\n        repository_ctx.attr._clang_cc_toolchain_config,\n        \"cc_toolchain_config.bzl\",\n    )\n    for file_label in repository_ctx.attr._clang_toolchain_files:\n        repository_ctx.symlink(file_label, file_label.name)\n\n    # Find a Clang C++ compiler, and where it lives. We need to walk symlinks\n    # here as the other LLVM tools may not be symlinked into the PATH even if\n    # `clang` is. We also insist on finding the basename of `clang++` as that is\n    # important for C vs. C++ compiles.\n    (clang, clang_version, clang_version_for_cache) = _detect_system_clang(\n        repository_ctx,\n    )\n    if clang_version and clang_version < 19:\n        fail(\"Found clang {0}. \".format(clang_version) +\n             \"Carbon requires clang >=19. See \" +\n             \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/contribution_tools.md#old-llvm-versions\")\n\n    clang_cpp = clang.dirname.get_child(\"clang++\")\n\n    # Compute the various directories used by Clang.\n    resource_dir = _compute_clang_resource_dir(repository_ctx, clang_cpp)\n    sysroot_dir = None\n    if repository_ctx.os.name.lower().startswith(\"mac os\"):\n        sysroot_dir = _compute_mac_os_sysroot(repository_ctx)\n    if repository_ctx.os.name == \"freebsd\":\n        sysroot_dir = _compute_bsd_sysroot(repository_ctx)\n    include_dirs = _compute_clang_cpp_include_search_paths(\n        repository_ctx,\n        clang_cpp,\n        sysroot_dir,\n    )\n\n    # We expect that the LLVM binutils live adjacent to llvm-ar.\n    # First look for llvm-ar adjacent to clang, so that if found,\n    # it is most likely to match the same version as clang.\n    # Otherwise, try PATH.\n    ar_path = clang.dirname.get_child(\"llvm-ar\")\n    if not ar_path.exists:\n        ar_path = repository_ctx.which(\"llvm-ar\")\n        if not ar_path:\n            fail(\"`llvm-ar` not found in PATH or adjacent to clang\")\n\n    # By default Windows uses '\\' in its paths. These will be\n    # interpreted as escape characters and fail the build, thus\n    # we must manually replace the backslashes with '/'\n    if repository_ctx.os.name.lower().startswith(\"windows\"):\n        resource_dir = resource_dir.replace(\"\\\\\", \"/\")\n        include_dirs = [str(s).replace(\"\\\\\", \"/\") for s in include_dirs]\n\n    repository_ctx.template(\n        \"clang_detected_variables.bzl\",\n        repository_ctx.attr._clang_detected_variables_template,\n        substitutions = {\n            \"{CLANG_BINDIR}\": str(clang.dirname),\n            \"{CLANG_INCLUDE_DIRS_LIST}\": str(\n                [str(path) for path in include_dirs],\n            ),\n            \"{CLANG_RESOURCE_DIR}\": resource_dir,\n            \"{CLANG_VERSION_FOR_CACHE}\": clang_version_for_cache.replace('\"', \"_\").replace(\"\\\\\", \"_\"),\n            \"{CLANG_VERSION}\": str(clang_version),\n            \"{LLVM_BINDIR}\": str(ar_path.dirname),\n            \"{LLVM_SYMBOLIZER}\": str(ar_path.dirname.get_child(\"llvm-symbolizer\")),\n            \"{SYSROOT}\": str(sysroot_dir),\n        },\n        executable = False,\n    )\n\nconfigure_clang_toolchain = repository_rule(\n    implementation = _configure_clang_toolchain_impl,\n    configure = True,\n    local = True,\n    attrs = {\n        \"_clang_cc_toolchain_config\": attr.label(\n            default = Label(\n                \"//bazel/cc_toolchains:clang_cc_toolchain_config.bzl\",\n            ),\n            allow_single_file = True,\n        ),\n        \"_clang_detected_variables_template\": attr.label(\n            default = Label(\n                \"//bazel/cc_toolchains:clang_detected_variables.tpl.bzl\",\n            ),\n            allow_single_file = True,\n        ),\n        \"_clang_toolchain_build\": attr.label(\n            default = Label(\"//bazel/cc_toolchains:clang_toolchain.BUILD\"),\n            allow_single_file = True,\n        ),\n        \"_clang_toolchain_files\": attr.label_list(\n            default = [\n                Label(\"//bazel/cc_toolchains:cc_toolchain_actions.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_base_features.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_carbon_project_features.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_config_features.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_cpp_features.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_debugging.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_features.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_linking.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_modules.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_optimization.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_sanitizer_features.bzl\"),\n                Label(\"//bazel/cc_toolchains:cc_toolchain_tools.bzl\"),\n            ],\n        ),\n    },\n    environ = [\"CC\"],\n)\n\nclang_toolchain_extension = module_extension(\n    implementation = lambda ctx: configure_clang_toolchain(name = \"bazel_cc_toolchain\"),\n)\n"
  },
  {
    "path": "bazel/cc_toolchains/clang_detected_variables.tpl.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"A Starlark file exporting detected Clang configuration variables.\n\nThis file gets processed by a repository rule, substituting the\n`{VARIABLE}`s with values detected by invoking Clang.\n\"\"\"\n\nllvm_bindir = \"{LLVM_BINDIR}\"\nllvm_symbolizer = \"{LLVM_SYMBOLIZER}\"\nclang_bindir = \"{CLANG_BINDIR}\"\nclang_version = {CLANG_VERSION}\nclang_version_for_cache = \"{CLANG_VERSION_FOR_CACHE}\"\nclang_resource_dir = \"{CLANG_RESOURCE_DIR}\"\nclang_include_dirs_list = {CLANG_INCLUDE_DIRS_LIST}\nsysroot_dir = \"{SYSROOT}\"\n"
  },
  {
    "path": "bazel/cc_toolchains/clang_toolchain.BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# This file is symlinked into a configured Clang toolchain repository as the\n# root `BUILD` file for that repository.\n\nload(\":cc_toolchain_config.bzl\", \"cc_local_toolchain_suite\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncc_local_toolchain_suite(\n    name = \"bazel_cc_toolchain\",\n    configs = [\n        (\"linux\", \"aarch64\"),\n        (\"linux\", \"x86_64\"),\n        (\"freebsd\", \"x86_64\"),\n        (\"macos\", \"arm64\"),\n        (\"macos\", \"x86_64\"),\n        (\"windows\", \"x86_64\"),\n    ],\n)\n"
  },
  {
    "path": "bazel/cc_toolchains/defs.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Provides helpers for cc rules. Intended for general consumption.\"\"\"\n\nload(\"@bazel_cc_toolchain//:clang_detected_variables.bzl\", \"llvm_symbolizer\")\n\ndef cc_env():\n    \"\"\"Returns standard environment settings for a cc_binary.\n\n    In use, this looks like:\n\n    ```\n    load(\"//bazel/cc_toolchains:defs.bzl\", \"cc_env\")\n\n    cc_binary(\n      ...\n      env = cc_env(),\n    )\n    ```\n\n    We're currently setting this on a target-by-target basis, mainly because\n    it's difficult to modify default behaviors.\n    \"\"\"\n\n    # Settings which apply cross-platform.\n    # buildifier: disable=unsorted-dict-items\n    common_env = {\n        \"LLVM_SYMBOLIZER_PATH\": llvm_symbolizer,\n        # Sanitizers don't use LLVM as fallback, but sometimes ASAN may be used\n        # for UBSAN errors; we still set UBSAN in case it's directly used.\n        \"ASAN_SYMBOLIZER_PATH\": llvm_symbolizer,\n        \"UBSAN_SYMBOLIZER_PATH\": llvm_symbolizer,\n        # Default to printing traces for UBSAN.\n        \"UBSAN_OPTIONS\": \"print_stacktrace=1\",\n    }\n\n    # On macOS, there's a nano zone allocation warning when asan is enabled.\n    # This suppresses the warning in `bazel run`.\n    macos_env = {\"MallocNanoZone\": \"0\"}\n\n    return common_env | select({\n        \"//bazel/cc_toolchains:macos_asan\": macos_env,\n        \"//conditions:default\": {},\n    })\n"
  },
  {
    "path": "bazel/check_deps/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@rules_python//python:defs.bzl\", \"py_test\")\n\n# The filegroups establishing root rules for `genquery` invocations can be\n# updated by running:\n#\n# ```\n# ./bazel/check_deps/update_roots.py\n# ```\nfilegroup(\n    name = \"non_test_cc_rules\",\n    data = [\n        \"//toolchain/install:carbon_toolchain_tar_gz_rule\",\n        \"//toolchain/install:carbon_toolchain_tar_rule\",\n    ],\n    tags = [\"manual\"],\n)\n\ngenquery(\n    name = \"non_test_cc_deps.txt\",\n    expression =\n        \"kind('cc.* rule', deps(//bazel/check_deps:non_test_cc_rules))\",\n    opts = [\n        \"--notool_deps\",\n        \"--noimplicit_deps\",\n    ],\n    scope = [\":non_test_cc_rules\"],\n)\n\npy_test(\n    name = \"check_non_test_cc_deps\",\n    size = \"small\",\n    srcs = [\"check_non_test_cc_deps.py\"],\n    data = [\":non_test_cc_deps.txt\"],\n    main = \"check_non_test_cc_deps.py\",\n)\n"
  },
  {
    "path": "bazel/check_deps/check_non_test_cc_deps.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Check that non-test C++ rules only depend on Carbon and LLVM.\n\nCarbon works to ensure its user-visible libraries and binaries only depend on\ntheir code and LLVM. Among other benefits, this provides a single, simple\nlicense used for the whole project.\n\nHowever, we frequently use third-party projects and libraries where useful in\nour test code. Here, we verify that the dependencies of non-test C++ rules only\ninclude Carbon and LLVM code.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport os\nimport sys\nfrom pathlib import Path\n\nrunfiles = Path(os.environ[\"TEST_SRCDIR\"])\ndeps_path = runfiles / \"_main\" / \"bazel\" / \"check_deps\" / \"non_test_cc_deps.txt\"\ntry:\n    with deps_path.open() as deps_file:\n        deps = deps_file.read().splitlines()\nexcept FileNotFoundError:\n    sys.exit(\"ERROR: unable to find deps file: %s\" % deps_path)\n\n# This errors out on dependencies that aren't recognized, and continues on\n# allowed dependencies.\nfor dep in deps:\n    print(\"Checking dependency: \" + dep)\n    repo, _, rule = dep.partition(\"//\")\n\n    if repo == \"@@+llvm_project+llvm-project\":\n        package, _, rule = rule.partition(\":\")\n\n        # Other packages in the LLVM project shouldn't be accidentally used\n        # in Carbon. We can expand the above list if use cases emerge.\n        if package not in (\n            \"clang\",\n            \"clang-tools-extra/clangd\",\n            \"libc\",\n            \"libcxx\",\n            \"libcxxabi\",\n            \"libunwind\",\n            \"lld\",\n            \"llvm\",\n            # While this is in a `third_party` directory, its code is documented\n            # as part of LLVM and for use in compiler-rt.\n            \"third-party/siphash\",\n        ) and (\n            package == \"third-party\"\n            and rule\n            not in (\n                # LLVM wrappers for zlib-ng and zstd, which are fine as linked.\n                \"zlib\",\n                \"zstd\",\n            )\n        ):\n            sys.exit(\n                \"ERROR: unexpected dependency into the LLVM project: %s\" % dep\n            )\n\n        # Check for accidentally using the copy of GoogleTest in LLVM.\n        if rule in (\"gmock\", \"gtest\", \"gtest_main\"):\n            sys.exit(\n                \"ERROR: dependency on LLVM's GoogleTest from non-test code: %s\"\n                % dep\n            )\n\n        # The rest of LLVM, LLD, and Clang themselves are safe to depend on.\n        continue\n\n    # Carbon code is always allowed.\n    if repo == \"\" and not rule.startswith(\"third_party\"):\n        continue\n\n    # LLVM code managed in the Carbon repository is still LLVM code and OK.\n    if repo == \"\" and rule.startswith(\"third_party/llvm:\"):\n        continue\n\n    # Utility libraries provided by Bazel that are under a compatible license.\n    if repo in (\"@@rules_cc+\", \"@@bazel_tools\"):\n        continue\n\n    # These libraries have compatible licenses and are linked in without copying\n    # source, so fine for our binaries.\n    if repo in (\n        \"@@zlib-ng+\",\n        \"@@zstd+\",\n    ):\n        continue\n\n    # This should never be reached from non-test code, but these targets do\n    # exist. Specially diagnose them to try to provide a more helpful\n    # message.\n    if repo in (\n        \"@google_benchmark\",\n        \"@abseil-cpp\",\n        \"@googletest\",\n    ):\n        sys.exit(\"ERROR: dependency only allowed in test code: %s\" % dep)\n\n    # Conservatively fail if a dependency isn't explicitly allowed above.\n    sys.exit(f\"ERROR: unknown dependency on {repo}: {dep}\")\n"
  },
  {
    "path": "bazel/check_deps/update_roots.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Update the roots of the Carbon build used for dependency checking.\n\nThe dependency checking cannot use wildcard queries, so we use them here and\nthen create lists of relevant roots in the build file.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport os\nimport subprocess\nfrom pathlib import Path\n\n# Change the working directory to the repository root so that the remaining\n# operations reliably operate relative to that root.\nos.chdir(Path(__file__).parents[2])\n\nprint(\"Compute non-test C++ root targets...\")\nquery_arg = (\n    \"let non_tests = attr(\"\n    \"    testonly, 0, //...\"\n    # Exclude tree_sitter because its @platforms dependency errors in\n    # query. Note if it ends up in releases, we might want to do more,\n    # but that should also be caught by check_deps.py.\n    \"    except //utils/tree_sitter/...\"\n    # Exclude tcmalloc as an optional external library.\n    \"    except //bazel/malloc:tcmalloc_if_linux_opt\"\n    \") in kind('(cc|pkg)_.* rule', deps($non_tests))\"\n)\nnon_test_cc_roots_query = subprocess.check_output(\n    [\n        \"./scripts/run_bazel.py\",\n        \"query\",\n        \"--noshow_progress\",\n        \"--noimplicit_deps\",\n        \"--notool_deps\",\n        \"--output=minrank\",\n        query_arg,\n    ],\n    universal_newlines=True,\n)\nranked_targets = [line.split() for line in non_test_cc_roots_query.splitlines()]\nroots = [target for rank, target in ranked_targets if int(rank) == 0]\nprint(\"Found roots:\\n%s\" % \"\\n\".join(roots))\n\nprint(\"Replace non-test C++ roots in the BUILD file...\")\nbuildozer_run = subprocess.run(\n    [\n        \"./scripts/run_buildozer.py\",\n        \"remove data\",\n    ]\n    + [\"add data '%s'\" % root for root in roots]\n    + [\"//bazel/check_deps:non_test_cc_rules\"],\n)\nif buildozer_run.returncode == 3:\n    print(\"No changes needed!\")\nelse:\n    buildozer_run.check_returncode()\n    print(\"Successfully updated roots in the BUILD file!\")\n"
  },
  {
    "path": "bazel/llvm_project/0001_Patch_for_mallinfo2_when_using_Bazel_build_system.patch",
    "content": "From 80f5475adfe179739a45d42850f8c06a630bc3a0 Mon Sep 17 00:00:00 2001\nFrom: Chandler Carruth <chandlerc@gmail.com>\nDate: Fri, 17 Jun 2022 09:10:41 +0000\nSubject: [PATCH] Patch for mallinfo2 when using Bazel build system.\n\nThis detects and defines the `HAVE_MALLINFO2` macro based on the glibc\nversion to allow easy use of the Bazel build on systems with modern\nglibc installs.\n---\n llvm/lib/Support/Unix/Process.inc | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/llvm/lib/Support/Unix/Process.inc b/llvm/lib/Support/Unix/Process.inc\nindex 550b0de2e045..6d449489c450 100644\n--- a/llvm/lib/Support/Unix/Process.inc\n+++ b/llvm/lib/Support/Unix/Process.inc\n@@ -22,6 +22,13 @@\n #include <sys/resource.h>\n #include <sys/stat.h>\n #include <signal.h>\n+// When glibc is in use, detect mallinfo2 to address mallinfo deprecation\n+// warnings.\n+#if !defined(HAVE_MALLINFO2) && defined(__GLIBC_PREREQ)\n+#if __GLIBC_PREREQ(2, 33)\n+#define HAVE_MALLINFO2\n+#endif  // __GLIBC_PREREQ(2, 33)\n+#endif  // !defined(HAVE_MALLINFO2) && defined(__GLIBC_PREREQ)\n #if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)\n #include <malloc.h>\n #endif\n--\n2.48.1\n"
  },
  {
    "path": "bazel/llvm_project/0002_Added_Bazel_build_for_compiler_rt_fuzzer.patch",
    "content": "From 20d0f1fb854d9b7ce135d08575112fc58c4c7ce7 Mon Sep 17 00:00:00 2001\nFrom: jonmeow <jperkins@google.com>\nDate: Thu, 14 Sep 2023 20:31:11 +0000\nSubject: [PATCH] Add libfuzzer target to compiler-rt.\n\n---\n .../compiler-rt/BUILD.bazel                     | 17 +++++++++++++++++\n 1 file changed, 17 insertions(+)\n\ndiff --git a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel\nindex 90264449de76..115da4cb77f6 100644\n--- a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel\n+++ b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel\n@@ -57,6 +57,23 @@ cc_library(\n     ],\n )\n\n+cc_library(\n+    name = \"FuzzerMain\",\n+    srcs = glob(\n+        [\"lib/fuzzer/Fuzzer*.cpp\"],\n+    ),\n+    hdrs = glob([\n+        \"lib/fuzzer/Fuzzer*.h\",\n+        \"lib/fuzzer/Fuzzer*.def\",\n+    ]),\n+    copts = [\n+        # Not using no-sanitize=address per https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow#false-positives\n+        \"-fno-sanitize=memory,thread,undefined\",\n+        \"-fsanitize-coverage=0\",\n+    ],\n+    includes = [\"lib/fuzzer\"],\n+)\n+\n cc_library(\n     name = \"orc_rt_common_headers\",\n     hdrs = [\n--\n2.42.0\n"
  },
  {
    "path": "bazel/llvm_project/0004_Introduce_basic_sources_exporting_for_libunwind.patch",
    "content": "Commit ID: 354e38c89f28e2cc284e655a9cde707f457dc02c\nChange ID: sxspxmonsuvqzuvxvrvorlumwpwromsv\nAuthor   : Chandler Carruth <chandlerc@gmail.com> (2025-09-25 22:55:26)\nCommitter: Chandler Carruth <chandlerc@gmail.com> (2026-02-14 03:46:06)\n\n    Introduce basic sources exporting for libunwind\n\n    This exports the source files directly so that they can be used to build\n    this runtime library on demand.\n\ndiff --git a/utils/bazel/llvm-project-overlay/libunwind/BUILD.bazel b/utils/bazel/llvm-project-overlay/libunwind/BUILD.bazel\nindex c9fdc819c0..7d734c5a06 100644\n--- a/utils/bazel/llvm-project-overlay/libunwind/BUILD.bazel\n+++ b/utils/bazel/llvm-project-overlay/libunwind/BUILD.bazel\n@@ -21,3 +21,19 @@\n     ],\n     strip_include_prefix = \"include\",\n )\n+\n+filegroup(\n+    name = \"libunwind_hdrs\",\n+    srcs = glob([\"include/**/*.h\"]),\n+)\n+\n+filegroup(\n+    name = \"libunwind_srcs\",\n+    srcs = glob([\n+        \"src/*.cpp\",\n+        \"src/*.hpp\",\n+        \"src/*.c\",\n+        \"src/*.h\",\n+        \"src/*.S\",\n+    ]),\n+)\ndiff --git a/utils/bazel/llvm-project-overlay/libunwind/libunwind_library.bzl b/utils/bazel/llvm-project-overlay/libunwind/libunwind_library.bzl\nnew file mode 100644\nindex 0000000000..25675d3070\n--- /dev/null\n+++ b/utils/bazel/llvm-project-overlay/libunwind/libunwind_library.bzl\n@@ -0,0 +1,24 @@\n+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.\n+# See https://llvm.org/LICENSE.txt for license information.\n+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n+\n+\"\"\"Starlark variables and macros for building libunwind.\n+\n+Variables provide base line information for how to build libunwind source files.\n+These can be used to generate non-Bazel builds of the library.\n+\n+Macros provide a convenient way to construct Bazel `cc_library` rules for\n+libunwind.\n+\"\"\"\n+\n+# TODO: Should libunwind use `-fvisibility-inlines-hidden` and\n+# `-fvisibility=hidden`, similar to libc++?\n+libunwind_copts = [\n+    \"-D_LIBUNWIND_IS_NATIVE_ONLY\",\n+    \"-O3\",\n+    \"-fPIC\",\n+    \"-fno-exceptions\",\n+    \"-fno-rtti\",\n+    \"-funwind-tables\",\n+    \"-nostdinc++\",\n+]\n"
  },
  {
    "path": "bazel/llvm_project/0005_Introduce_basic_sources_exporting_for_libcxx_and_libcxxabi.patch",
    "content": "Commit ID: 1fd710ed69a0f47f454c386d39302ddb756a88b3\nChange ID: mstnwoqruyypnoouksnyqssllrsozpos\nBookmarks: bz-libcxx* bz-libcxx@git\nAuthor   : Chandler Carruth <chandlerc@gmail.com> (2025-09-25 22:55:26)\nCommitter: Chandler Carruth <chandlerc@gmail.com> (2026-03-08 07:41:54)\n\n    Introduce basic sources exporting for libcxx and libcxxabi\n\n    This exports the source files directly so that they can be used to build\n    a libcxx runtime library on demand. It also differentiates between\n    normal sources and textual sources.\n\ndiff --git a/utils/bazel/llvm-project-overlay/libcxx/BUILD.bazel b/utils/bazel/llvm-project-overlay/libcxx/BUILD.bazel\nnew file mode 100644\nindex 0000000000..c8b517ab56\n--- /dev/null\n+++ b/utils/bazel/llvm-project-overlay/libcxx/BUILD.bazel\n@@ -0,0 +1,139 @@\n+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.\n+# See https://llvm.org/LICENSE.txt for license information.\n+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n+\n+licenses([\"notice\"])\n+\n+package(\n+    default_visibility = [\"//visibility:public\"],\n+)\n+\n+exports_files([\n+    \"include/__config_site.in\",\n+    \"include/module.modulemap.in\",\n+    \"vendor/llvm/default_assertion_handler.in\",\n+])\n+\n+filegroup(\n+    name = \"libcxx_hdrs\",\n+    srcs = glob(\n+        [\n+            # Top level includes and those in `experimental` and `ext` sometimes\n+            # have no extension.\n+            \"include/*\",\n+            \"include/experimental/*\",\n+            \"include/ext/*\",\n+\n+            # Implementation detail headers all use `.h` extensions\n+            \"include/**/*.h\",\n+        ],\n+        exclude = [\n+            # Omit CMake and CMake-configured files that get caught by the\n+            # extension-less patterns.\n+            \"**/*.in\",\n+            \"**/CMakeLists.txt\",\n+\n+            # Omit C++03 compatibility headers as current users don't need them.\n+            \"include/__cxx03/**\",\n+        ],\n+    ),\n+)\n+\n+LIBCXX_SRCS_PSTL_LIBDISPATCH = [\n+    \"src/pstl/libdispatch.cpp\",\n+]\n+\n+filegroup(\n+    name = \"libcxx_srcs_pstl_libdispatch\",\n+    srcs = LIBCXX_SRCS_PSTL_LIBDISPATCH,\n+)\n+\n+LIBCXX_SRCS_SUPPORT_IBM_PATTERNS = [\n+    \"src/support/ibm/**/*.cpp\",\n+]\n+\n+filegroup(\n+    name = \"libcxx_srcs_support_ibm\",\n+    srcs = glob(LIBCXX_SRCS_SUPPORT_IBM_PATTERNS),\n+)\n+\n+LIBCXX_SRCS_SUPPORT_WIN32_PATTERNS = [\n+    \"src/support/win32/**/*.cpp\",\n+]\n+\n+filegroup(\n+    name = \"libcxx_srcs_support_win32\",\n+    srcs = glob(LIBCXX_SRCS_SUPPORT_WIN32_PATTERNS),\n+)\n+\n+LIBCXX_SRCS_TZDB = [\n+    \"src/experimental/chrono_exception.cpp\",\n+    \"src/experimental/time_zone.cpp\",\n+    \"src/experimental/tzdb.cpp\",\n+    \"src/experimental/tzdb_list.cpp\",\n+]\n+\n+filegroup(\n+    name = \"libcxx_srcs_tzdb\",\n+    srcs = LIBCXX_SRCS_TZDB,\n+)\n+\n+# Exclude platform-dependent patterns that are provided by per-target filegroups\n+# above.\n+LIBCXX_SRCS_TARGET_EXCLUDES = (\n+    LIBCXX_SRCS_PSTL_LIBDISPATCH +\n+    LIBCXX_SRCS_SUPPORT_IBM_PATTERNS +\n+    LIBCXX_SRCS_SUPPORT_WIN32_PATTERNS +\n+    LIBCXX_SRCS_TZDB\n+)\n+\n+filegroup(\n+    name = \"libcxx_srcs_generic\",\n+    srcs = glob(\n+        [\n+            \"src/**/*.cpp\",\n+            \"src/**/*.h\",\n+            \"src/**/*.ipp\",\n+        ],\n+        exclude = [\n+            # Build is for use with libc++abi and so don't need 'new.cpp'.\n+            \"src/new.cpp\",\n+\n+            # Build is for compiler-rt platforms so we have its int128 support.\n+            \"src/filesystem/int128_builtins.cpp\",\n+        ] + LIBCXX_SRCS_TARGET_EXCLUDES,\n+    ),\n+)\n+\n+filegroup(\n+    name = \"libcxx_linux_srcs\",\n+    srcs = [\n+        \":libcxx_srcs_generic\",\n+        \":libcxx_srcs_tzdb\",\n+    ],\n+)\n+\n+filegroup(\n+    name = \"libcxx_macos_srcs\",\n+    srcs = [\n+        \":libcxx_srcs_generic\",\n+        # TODO: Include libdispatch sources here to enable that pstl backend.\n+    ],\n+)\n+\n+filegroup(\n+    name = \"libcxx_win32_srcs\",\n+    srcs = [\n+        \":libcxx_srcs_generic\",\n+        \":libcxx_srcs_support_win32\",\n+    ],\n+)\n+\n+filegroup(\n+    name = \"libcxx_all_srcs\",\n+    srcs = [\n+        \":libcxx_linux_srcs\",\n+        \":libcxx_macos_srcs\",\n+        \":libcxx_win32_srcs\",\n+    ],\n+)\ndiff --git a/utils/bazel/llvm-project-overlay/libcxx/libcxx_library.bzl b/utils/bazel/llvm-project-overlay/libcxx/libcxx_library.bzl\nnew file mode 100644\nindex 0000000000..66f64f3610\n--- /dev/null\n+++ b/utils/bazel/llvm-project-overlay/libcxx/libcxx_library.bzl\n@@ -0,0 +1,37 @@\n+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.\n+# See https://llvm.org/LICENSE.txt for license information.\n+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n+\n+\"\"\"Starlark variables and macros for building libc++ and libc++abi.\n+\n+Variables provide base line information for how to build libc++ and libc++abi\n+source files. These can be used to generate non-Bazel builds of the library.\n+\n+TODO: Add macros that provide a convenient way to construct Bazel `cc_library`\n+rules for libc++ and libc++abi.\n+\n+TODO: Add either sufficient usage in the macros, or add a how-to example here in\n+the documentation so the use of these variables is more clear.\n+\"\"\"\n+\n+_libcxx_base_copts = [\n+    \"-std=c++26\",\n+    \"-O3\",\n+    \"-fPIC\",\n+    \"-fvisibility-inlines-hidden\",\n+    \"-fvisibility=hidden\",\n+    \"-nostdinc++\",\n+]\n+\n+_libcxx_defines = [\n+    \"-D_LIBCPP_BUILDING_LIBRARY\",\n+    \"-D_LIBCPP_REMOVE_TRANSITIVE_INCLUDES\",\n+]\n+\n+_libcxxabi_defines = [\n+    \"-DLIBCXX_BUILDING_LIBCXXABI\",\n+]\n+\n+libcxx_copts = _libcxx_base_copts + _libcxx_defines\n+libcxxabi_copts = _libcxx_base_copts + _libcxxabi_defines\n+libcxx_and_abi_copts = _libcxx_base_copts + _libcxx_defines + _libcxxabi_defines\ndiff --git a/utils/bazel/llvm-project-overlay/libcxxabi/BUILD.bazel b/utils/bazel/llvm-project-overlay/libcxxabi/BUILD.bazel\nnew file mode 100644\nindex 0000000000..2db70b54e2\n--- /dev/null\n+++ b/utils/bazel/llvm-project-overlay/libcxxabi/BUILD.bazel\n@@ -0,0 +1,30 @@\n+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.\n+# See https://llvm.org/LICENSE.txt for license information.\n+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n+\n+licenses([\"notice\"])\n+\n+package(\n+    default_visibility = [\"//visibility:public\"],\n+)\n+\n+filegroup(\n+    name = \"libcxxabi_hdrs\",\n+    srcs = glob([\"include/*.h\"]),\n+)\n+\n+filegroup(\n+    name = \"libcxxabi_srcs\",\n+    srcs = glob([\n+        \"src/**/*.cpp\",\n+        \"src/**/*.h\",\n+    ]),\n+)\n+\n+filegroup(\n+    name = \"libcxxabi_textual_srcs\",\n+    srcs = glob([\n+        \"src/**/*.def\",\n+        \"src/**/*.inc\",\n+    ]),\n+)\n"
  },
  {
    "path": "bazel/llvm_project/0009_Introduce_starlark_exporting_compiler-rt_build_information.patch",
    "content": "Commit ID: d3b82534c2546a892a27856672ed95a7db97dba3\nChange ID: zyxuvzwmzsnorloyuupuurxkppkoplnw\nAuthor   : Chandler Carruth <chandlerc@gmail.com> (2026-02-16 23:17:06)\nCommitter: Chandler Carruth <chandlerc@gmail.com> (2026-03-11 07:54:02)\n\n    Improve compiler-rt build structure and export compilation info\n\n    This first improves the structure of the compiler-rt BUILD.bazel, fixing\n    bugs and exposing more carefully arranged source files.\n\n    It also exposes compilation info for builtins and CRT files for use in\n    compiling these source files.\n\ndiff --git a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel\nindex 4ded226174..3b5b8fc787 100644\n--- a/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel\n+++ b/utils/bazel/llvm-project-overlay/compiler-rt/BUILD.bazel\n@@ -3,6 +3,7 @@\n # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n \n load(\"@rules_cc//cc:defs.bzl\", \"cc_library\")\n+load(\"compiler-rt.bzl\", \"make_filtered_builtins_srcs_groups\")\n \n package(\n     default_visibility = [\"//visibility:public\"],\n@@ -160,9 +161,15 @@\n     srcs = BUILTINS_CRTEND_SRCS,\n )\n \n+BUILTINS_EMUTLS_SRCS = [\"lib/builtins/emutls.c\"]\n+\n+filegroup(\n+    name = \"builtins_emutls_srcs\",\n+    srcs = BUILTINS_EMUTLS_SRCS,\n+)\n+\n BUILTINS_HOSTED_SRCS = [\n     \"lib/builtins/clear_cache.c\",\n-    \"lib/builtins/emutls.c\",\n     \"lib/builtins/enable_execute_stack.c\",\n     \"lib/builtins/eprintf.c\",\n ]\n@@ -224,11 +231,11 @@\n     ),\n )\n \n-BUILTNS_ATOMICS_SRCS = [\"lib/builtins/atomic.c\"]\n+BUILTINS_ATOMICS_SRCS = [\"lib/builtins/atomic.c\"]\n \n filegroup(\n     name = \"builtins_atomics_srcs\",\n-    srcs = BUILTNS_ATOMICS_SRCS + [\"lib/builtins/assembly.h\"],\n+    srcs = BUILTINS_ATOMICS_SRCS + [\"lib/builtins/assembly.h\"],\n )\n \n BUILTINS_MACOS_ATOMIC_SRCS_PATTERNS = [\n@@ -241,6 +248,28 @@\n     srcs = glob(BUILTINS_MACOS_ATOMIC_SRCS_PATTERNS),\n )\n \n+# Source files for portable components of the compiler builtins library.\n+filegroup(\n+    name = \"builtins_generic_srcs\",\n+    srcs = [\"lib/builtins/cpu_model/cpu_model.h\"] + glob(\n+        [\n+            \"lib/builtins/*.c\",\n+            \"lib/builtins/*.cpp\",\n+            \"lib/builtins/*.h\",\n+            \"lib/builtins/*.inc\",\n+        ],\n+        allow_empty = True,\n+        exclude = (\n+            BUILTINS_CRTBEGIN_SRCS +\n+            BUILTINS_CRTEND_SRCS +\n+            BUILTINS_TF_EXCLUDES +\n+            BUILTINS_TF_SRCS_PATTERNS +\n+            BUILTINS_ATOMICS_SRCS +\n+            BUILTINS_MACOS_ATOMIC_SRCS_PATTERNS\n+        ),\n+    ),\n+)\n+\n # Apple-platform specific SME source file.\n filegroup(\n     name = \"builtins_aarch64_apple_sme_srcs\",\n@@ -305,10 +334,13 @@\n \n # Source files for the AArch64 architecture-specific builtins.\n filegroup(\n-    name = \"builtins_aarch64_srcs\",\n+    name = \"builtins_unfiltered_aarch64_srcs\",\n     srcs = [\n         \"lib/builtins/cpu_model/aarch64.c\",\n         \"lib/builtins/cpu_model/aarch64.h\",\n+        \":builtins_bf16_srcs\",\n+        \":builtins_generic_srcs\",\n+        \":builtins_tf_srcs\",\n     ] + [\n         AARCH64_OUTLINE_ATOMICS_FMT.format(pat, size, model)\n         for (pat, size, model) in AARCH64_OUTLINE_ATOMICS\n@@ -328,10 +360,20 @@\n             \"lib/builtins/aarch64/lse.S\",\n             # These files are provided by SME-specific file groups above.\n             \"lib/builtins/aarch64/*sme*\",\n+            # This is only used with MinGW.\n+            \"lib/builtins/aarch64/chkstk.S\",\n+            # TODO: Remove this once we have a way of accessing `SipHash.h`.\n+            \"lib/builtins/aarch64/emupac.cpp\",\n         ],\n     ),\n )\n \n+make_filtered_builtins_srcs_groups(\n+    name = \"builtins_aarch64_srcs\",\n+    srcs = [\":builtins_unfiltered_aarch64_srcs\"],\n+    textual_name = \"builtins_aarch64_textual_srcs\",\n+)\n+\n BUILTINS_ARM_VFP_SRCS_PATTERNS = [\n     \"lib/builtins/arm/*vfp*.S\",\n     \"lib/builtins/arm/*vfp*.c\",\n@@ -348,9 +390,19 @@\n     ),\n )\n \n+BUILTINS_ARM_IMPLICIT_IT_SRCS = [\n+    \"lib/builtins/arm/mulsf3.S\",\n+    \"lib/builtins/arm/divsf3.S\",\n+]\n+\n+filegroup(\n+    name = \"builtins_arm_implicit_it_srcs\",\n+    srcs = BUILTINS_ARM_IMPLICIT_IT_SRCS,\n+)\n+\n # Source files for the ARM architecture-specific builtins.\n filegroup(\n-    name = \"builtins_arm_srcs\",\n+    name = \"builtins_arm_arch_srcs\",\n     srcs = glob(\n         [\n             \"lib/builtins/arm/*.S\",\n@@ -359,14 +411,52 @@\n             \"lib/builtins/arm/*.h\",\n         ],\n         allow_empty = True,\n-        exclude = BUILTINS_ARM_VFP_SRCS_PATTERNS,\n+        exclude = (BUILTINS_ARM_VFP_SRCS_PATTERNS +\n+                   BUILTINS_ARM_IMPLICIT_IT_SRCS) + [\n+            # This is only used with MinGW.\n+            \"lib/builtins/arm/chkstk.S\",\n+        ],\n     ),\n )\n \n-# Source files for the PPC architecture-specific builtins.\n-filegroup(\n-    name = \"builtins_ppc_srcs\",\n-    srcs = glob(\n+filegroup(\n+    name = \"builtins_unfiltered_armv7_srcs\",\n+    srcs = [\n+        \":builtins_arm_arch_srcs\",\n+        \":builtins_arm_vfp_srcs\",\n+        \":builtins_bf16_srcs\",\n+        \":builtins_generic_srcs\",\n+    ],\n+)\n+\n+make_filtered_builtins_srcs_groups(\n+    name = \"builtins_armv7_srcs\",\n+    srcs = [\":builtins_unfiltered_armv7_srcs\"],\n+    textual_name = \"builtins_armv7_textual_srcs\",\n+)\n+\n+filegroup(\n+    name = \"builtins_unfiltered_aarch32_srcs\",\n+    srcs = [\n+        \":builtins_arm_arch_srcs\",\n+        \":builtins_arm_vfp_srcs\",\n+        \":builtins_bf16_srcs\",\n+        \":builtins_generic_srcs\",\n+    ],\n+)\n+\n+make_filtered_builtins_srcs_groups(\n+    name = \"builtins_aarch32_srcs\",\n+    srcs = [\":builtins_unfiltered_aarch32_srcs\"],\n+    textual_name = \"builtins_aarch32_textual_srcs\",\n+)\n+\n+filegroup(\n+    name = \"builtins_unfiltered_ppc64_srcs\",\n+    srcs = [\n+        \":builtins_generic_srcs\",\n+        \":builtins_tf_srcs\",\n+    ] + glob(\n         [\n             \"lib/builtins/ppc/*.S\",\n             \"lib/builtins/ppc/*.c\",\n@@ -377,17 +467,64 @@\n     ),\n )\n \n-# Source files for the RISC-V architecture-specific builtins.\n-filegroup(\n-    name = \"builtins_riscv_srcs\",\n-    srcs = glob(\n-        [\n-            \"lib/builtins/riscv/*.S\",\n-            \"lib/builtins/riscv/*.c\",\n-            \"lib/builtins/riscv/*.cpp\",\n-        ],\n-        allow_empty = True,\n-    ),\n+make_filtered_builtins_srcs_groups(\n+    name = \"builtins_ppc64_srcs\",\n+    srcs = [\":builtins_unfiltered_ppc64_srcs\"],\n+    textual_name = \"builtins_ppc64_textual_srcs\",\n+)\n+\n+filegroup(\n+    name = \"builtins_unfiltered_ppc32_srcs\",\n+    srcs = [\":builtins_generic_srcs\"],\n+)\n+\n+make_filtered_builtins_srcs_groups(\n+    name = \"builtins_ppc32_srcs\",\n+    srcs = [\":builtins_unfiltered_ppc32_srcs\"],\n+    textual_name = \"builtins_ppc32_textual_srcs\",\n+)\n+\n+filegroup(\n+    name = \"builtins_unfiltered_riscv64_srcs\",\n+    srcs = [\n+        \":builtins_generic_srcs\",\n+        \":builtins_tf_srcs\",\n+    ] + glob(\n+        [\n+            \"lib/builtins/riscv/*.S\",\n+            \"lib/builtins/riscv/*.c\",\n+            \"lib/builtins/riscv/*.cpp\",\n+            \"lib/builtins/riscv/*.h\",\n+        ],\n+        allow_empty = True,\n+    ),\n+)\n+\n+make_filtered_builtins_srcs_groups(\n+    name = \"builtins_riscv64_srcs\",\n+    srcs = [\":builtins_unfiltered_riscv64_srcs\"],\n+    textual_name = \"builtins_riscv64_textual_srcs\",\n+)\n+\n+filegroup(\n+    name = \"builtins_unfiltered_riscv32_srcs\",\n+    srcs = [\n+        \":builtins_generic_srcs\",\n+    ] + glob(\n+        [\n+            \"lib/builtins/riscv/*.S\",\n+            \"lib/builtins/riscv/*.c\",\n+            \"lib/builtins/riscv/*.cpp\",\n+            \"lib/builtins/riscv/*.h\",\n+        ],\n+        allow_empty = True,\n+    ),\n+)\n+\n+make_filtered_builtins_srcs_groups(\n+    name = \"builtins_riscv32_srcs\",\n+    srcs = [\":builtins_unfiltered_riscv32_srcs\"],\n+    textual_name = \"builtins_riscv32_textual_srcs\",\n )\n \n # Source files for the x86 architecture specific builtins (both 32-bit and\n@@ -402,8 +539,14 @@\n \n # Source files for the x86-64 architecture specific builtins.\n filegroup(\n-    name = \"builtins_x86_64_srcs\",\n-    srcs = glob(\n+    name = \"builtins_unfiltered_x86_64_srcs\",\n+    srcs = [\n+        \":builtins_bf16_srcs\",\n+        \":builtins_generic_srcs\",\n+        \":builtins_tf_srcs\",\n+        \":builtins_x86_arch_srcs\",\n+        \":builtins_x86_fp80_srcs\",\n+    ] + glob(\n         [\n             \"lib/builtins/x86_64/*.S\",\n             \"lib/builtins/x86_64/*.c\",\n@@ -411,13 +554,29 @@\n             \"lib/builtins/x86_64/*.h\",\n         ],\n         allow_empty = True,\n+        exclude = [\n+            # This is a Windows-specific routine.\n+            # TODO: We should expose this as a Windows source at some point.\n+            \"lib/builtins/x86_64/chkstk.S\",\n+        ],\n     ),\n )\n \n+make_filtered_builtins_srcs_groups(\n+    name = \"builtins_x86_64_srcs\",\n+    srcs = [\":builtins_unfiltered_x86_64_srcs\"],\n+    textual_name = \"builtins_x86_64_textual_srcs\",\n+)\n+\n # Source files for the 32-bit-specific x86 architecture specific builtins.\n filegroup(\n-    name = \"builtins_i386_srcs\",\n-    srcs = glob(\n+    name = \"builtins_unfiltered_i386_srcs\",\n+    srcs = [\n+        \":builtins_bf16_srcs\",\n+        \":builtins_generic_srcs\",\n+        \":builtins_x86_arch_srcs\",\n+        \":builtins_x86_fp80_srcs\",\n+    ] + glob(\n         [\n             \"lib/builtins/i386/*.S\",\n             \"lib/builtins/i386/*.c\",\n@@ -429,28 +588,16 @@\n             # This file is used for both i386 and x86_64 and so included in the\n             # broader x86 sources.\n             \"lib/builtins/i386/fp_mode.c\",\n+            # These are Windows-specific routines.\n+            # TODO: We should expose these as Windows source at some point.\n+            \"lib/builtins/i386/chkstk.S\",\n+            \"lib/builtins/i386/chkstk2.S\",\n         ],\n     ),\n )\n \n-# Source files for portable components of the compiler builtins library.\n-filegroup(\n-    name = \"builtins_generic_srcs\",\n-    srcs = [\"lib/builtins/cpu_model/cpu_model.h\"] + glob(\n-        [\n-            \"lib/builtins/*.c\",\n-            \"lib/builtins/*.cpp\",\n-            \"lib/builtins/*.h\",\n-            \"lib/builtins/*.inc\",\n-        ],\n-        allow_empty = True,\n-        exclude = (\n-            BUILTINS_CRTBEGIN_SRCS +\n-            BUILTINS_CRTEND_SRCS +\n-            BUILTINS_TF_EXCLUDES +\n-            BUILTINS_TF_SRCS_PATTERNS +\n-            BUILTNS_ATOMICS_SRCS +\n-            BUILTINS_MACOS_ATOMIC_SRCS_PATTERNS\n-        ),\n-    ),\n+make_filtered_builtins_srcs_groups(\n+    name = \"builtins_i386_srcs\",\n+    srcs = [\":builtins_unfiltered_i386_srcs\"],\n+    textual_name = \"builtins_i386_textual_srcs\",\n )\ndiff --git a/utils/bazel/llvm-project-overlay/compiler-rt/compiler-rt.bzl b/utils/bazel/llvm-project-overlay/compiler-rt/compiler-rt.bzl\nnew file mode 100644\nindex 0000000000..e33ceb6a89\n--- /dev/null\n+++ b/utils/bazel/llvm-project-overlay/compiler-rt/compiler-rt.bzl\n@@ -0,0 +1,153 @@\n+# This file is licensed under the Apache License v2.0 with LLVM Exceptions.\n+# See https://llvm.org/LICENSE.txt for license information.\n+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n+\n+\"\"\"Starlark for building parts of compiler-rt.\n+\n+Variables provide baseline information for how to build various parts of\n+compiler-rt. These can be used to generate non-Bazel builds of the library.\n+\n+Rules and macros support building the relevant filegroups of source files.\n+\n+TODO: Add macros that provide a convenient way to construct a Bazel target for\n+the Clang resource directory with builtins and crt files.\n+\"\"\"\n+\n+_common_copts = [\n+    \"-O3\",\n+    \"-fPIC\",\n+    \"-ffreestanding\",\n+    \"-std=c11\",\n+]\n+\n+crt_copts = _common_copts + [\n+    \"-DCRT_HAS_INITFINI_ARRAY\",\n+    \"-DEH_USE_FRAME_REGISTRY\",\n+    \"-fno-lto\",\n+]\n+\n+builtins_copts = _common_copts + [\n+    \"-fno-builtin\",\n+    \"-fomit-frame-pointer\",\n+    \"-fvisibility=hidden\",\n+    \"-Wno-missing-prototypes\",\n+    \"-Wno-unused-parameter\",\n+]\n+\n+def _get_rel_path(path_str):\n+    rel_path = path_str.rpartition(\"/lib/builtins/\")[2]\n+    if rel_path == path_str:\n+        fail(\"Expected '/lib/builtins/' in path \" + path_str)\n+    return rel_path\n+\n+def _filtered_builtins_srcs_impl(ctx):\n+    \"\"\"Implementation of filter_builtins_srcs rule.\"\"\"\n+\n+    # Build a map from generic file basename to list of overriding files.\n+    overrides = {}\n+    for f in ctx.files.srcs:\n+        rel_path = _get_rel_path(f.short_path)\n+        if \"/\" in rel_path:\n+            base_file = rel_path.rpartition(\"/\")[2]\n+            if base_file.endswith(\".S\"):\n+                base_file = base_file.removesuffix(\".S\") + \".c\"\n+            overrides[base_file] = True\n+\n+    filtered_files = []\n+    for f in ctx.files.srcs:\n+        rel_path = _get_rel_path(f.short_path)\n+        if \"/\" not in rel_path:\n+            # This is a generic file. Check if it's overridden.\n+            if rel_path not in overrides:\n+                filtered_files.append(f)\n+        else:\n+            # This is an arch-specific file, include it.\n+            filtered_files.append(f)\n+\n+    # Remove any textual sources from this list.\n+    filtered_files = [\n+        f\n+        for f in filtered_files\n+        if f.extension not in [\"inc\", \"def\"]\n+    ]\n+\n+    return [DefaultInfo(files = depset(filtered_files))]\n+\n+filtered_builtins_srcs = rule(\n+    implementation = _filtered_builtins_srcs_impl,\n+    attrs = {\n+        \"srcs\": attr.label_list(\n+            mandatory = True,\n+            allow_files = True,\n+            doc = \"Input files.\",\n+        ),\n+    },\n+    doc = \"\"\"Build a filtered filegroup of non-textual srcs for builtins.\n+\n+    Accepts a filegroup whose files are in lib/builtins/, and produces a target\n+    behaving like a filegroup containing filtered files.\n+\n+    This removes any textual source files (`.inc` or `.def`) from the input.\n+\n+    It also replaces generic srcs that are overridden by architecture-specific\n+    sources. For example, given a list of sources from filegroup of the form:\n+\n+    - `.../lib/builtins/file_0.c`\n+    - `.../lib/builtins/file_1.c`\n+    - `.../lib/builtins/file_2.c`\n+    - `.../lib/builtins/arch/file_0.c`\n+    - `.../lib/builtins/arch/file_1.S`\n+\n+    It removes any source-file at the top level of lib/builtins/ (e.g.\n+    lib/builtins/file_0.c) that has a corresponding source-file in an arch\n+    directory (e.g. lib/builtins/arch/file_0.c or lib/builtins/arch/file_1.S),\n+    producing a list like:\n+\n+    - `.../lib/builtins/file_2.c`\n+    - `.../lib/builtins/arch/file_0.c`\n+    - `.../lib/builtins/arch/file_1.S`\n+\n+    This allows a target architecture to simply add a specialized file to the\n+    list of sources with the architecture prefix and have the specialized\n+    version override the generic version.\n+    \"\"\",\n+)\n+\n+def _filtered_builtins_textual_srcs_impl(ctx):\n+    \"\"\"Implementation of filter_builtins_textual_srcs rule.\"\"\"\n+\n+    filtered_files = [\n+        f\n+        for f in ctx.files.srcs\n+        if f.extension in [\"inc\", \"def\"]\n+    ]\n+\n+    return [DefaultInfo(files = depset(filtered_files))]\n+\n+filtered_builtins_textual_srcs = rule(\n+    implementation = _filtered_builtins_textual_srcs_impl,\n+    attrs = {\n+        \"srcs\": attr.label_list(\n+            mandatory = True,\n+            allow_files = True,\n+            doc = \"Input files.\",\n+        ),\n+    },\n+    doc = \"\"\"Build a filegroup of the textual srcs for builtins.\n+\n+    Textual sources are those that can't be compiled directly and aren't\n+    recognized as header files by Bazel. The extensions recognized here are\n+    `.inc` and `.def`.\n+    \"\"\",\n+)\n+\n+def make_filtered_builtins_srcs_groups(name, textual_name, srcs):\n+    \"\"\"Macro to expand both the non-textual and textual filtered srcs groups.\"\"\"\n+    filtered_builtins_srcs(\n+        name = name,\n+        srcs = srcs,\n+    )\n+    filtered_builtins_textual_srcs(\n+        name = textual_name,\n+        srcs = srcs,\n+    )\n"
  },
  {
    "path": "bazel/llvm_project/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files(glob([\n    \"*.patch\",\n]))\n"
  },
  {
    "path": "bazel/llvm_project/llvm_project.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Apply llvm_configure to produce a llvm-project repo.\"\"\"\n\nload(\"@llvm-raw//utils/bazel:configure.bzl\", \"llvm_configure\")\n\nllvm_project = module_extension(\n    implementation = lambda ctx: llvm_configure(\n        name = \"llvm-project\",\n        targets = [\n            \"AArch64\",\n            \"X86\",\n        ],\n    ),\n)\n"
  },
  {
    "path": "bazel/malloc/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@bazel_skylib//lib:selects.bzl\", \"selects\")\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_library\")\n\nconfig_setting(\n    name = \"is_linux\",\n    constraint_values = [\"@platforms//os:linux\"],\n)\n\nconfig_setting(\n    name = \"opt\",\n    values = {\"compilation_mode\": \"opt\"},\n)\n\nselects.config_setting_group(\n    name = \"linux_opt\",\n    match_all = [\n        \":is_linux\",\n        \":opt\",\n    ],\n)\n\n# A library that enables TCMalloc for optimized builds on Linux. On other\n# platforms and configurations, this falls back on the system malloc.\ncc_library(\n    name = \"tcmalloc_if_linux_opt\",\n    deps = select({\n        \":linux_opt\": [\"@tcmalloc//tcmalloc\"],\n        \"//conditions:default\": [\"@bazel_tools//tools/cpp:malloc\"],\n    }),\n)\n"
  },
  {
    "path": "bazel/manifest/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Empty; only defs.bzl is needed.\n"
  },
  {
    "path": "bazel/manifest/defs.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Rule for producing a manifest for a filegroup.\"\"\"\n\ndef _get_files(ctx):\n    files = []\n    for src in ctx.attr.srcs:\n        files.extend([f.path for f in src[DefaultInfo].files.to_list()])\n        files.extend([\n            f.path\n            for f in src[DefaultInfo].default_runfiles.files.to_list()\n        ])\n\n    if ctx.attr.strip_package_dir:\n        # Files may or may not be prefixed with the bin directory, and then\n        # may or may not be prefixed with the package directory. Strip both.\n        bin_dir = ctx.bin_dir.path + \"/\"\n        package_dir = ctx.label.package + \"/\"\n        files_stripped = [f.removeprefix(bin_dir).removeprefix(package_dir) for f in files]\n    else:\n        files_stripped = files\n\n    return files_stripped\n\ndef _manifest(ctx):\n    out = ctx.actions.declare_file(ctx.label.name)\n    files = _get_files(ctx)\n    ctx.actions.write(out, \"\\n\".join(files) + \"\\n\")\n\n    return [\n        DefaultInfo(\n            files = depset(direct = [out]),\n            runfiles = ctx.runfiles(files = [out]),\n        ),\n    ]\n\n# Produces the manifest as a series of lines.\nmanifest = rule(\n    implementation = _manifest,\n    attrs = {\n        \"srcs\": attr.label_list(allow_files = True, mandatory = True),\n        \"strip_package_dir\": attr.bool(default = False),\n    },\n)\n\ndef _manifest_as_cpp(ctx):\n    out = ctx.actions.declare_file(ctx.label.name)\n    files = _get_files(ctx)\n    lines = [\n        \"// Auto-generated by manifest_as_cpp.\",\n        \"const char* {0}[] = {{\".format(ctx.attr.var_name),\n    ]\n    lines += [\n        \"    \\\"{0}\\\",\".format(file)\n        for file in files\n    ]\n    lines += [\n        \"    nullptr,\",\n        \"};\",\n    ]\n    ctx.actions.write(out, \"\\n\".join(lines) + \"\\n\")\n\n    return [\n        DefaultInfo(\n            files = depset(direct = [out]),\n            runfiles = ctx.runfiles(files = [out]),\n        ),\n    ]\n\n# Produces the manifest as a nullptr-terminated `const char* var_name[]`.\n# Use with `extern const char* var_name[];`.\nmanifest_as_cpp = rule(\n    implementation = _manifest_as_cpp,\n    attrs = {\n        \"srcs\": attr.label_list(allow_files = True, mandatory = True),\n        \"strip_package_dir\": attr.bool(default = False),\n        \"var_name\": attr.string(mandatory = True),\n    },\n)\n"
  },
  {
    "path": "bazel/version/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@bazel_skylib//rules:common_settings.bzl\", \"bool_flag\", \"int_flag\", \"string_flag\")\nload(\"@rules_python//python:defs.bzl\", \"py_binary\")\n\npackage(default_visibility = [\"//toolchain/install:__pkg__\"])\n\npy_binary(\n    name = \"gen_tmpl\",\n    srcs = [\"gen_tmpl.py\"],\n)\n\n# Several flags are provided for customizing the exact version used for the\n# build of Carbon. Each of these is documented here, but rather than using the\n# label-based names in Bazel invocations (`bazel build --//bazel/version:flag`)\n# we suggest using the flag aliases provided in the project's `.bazelrc` and we\n# document the flags using those aliases. The aliases match the local flag names\n# here.\n#\n# For more details on the versioning scheme used by Carbon, see:\n# - https://docs.google.com/document/d/11S5VAPe5Pm_BZPlajWrqDDVr9qc7-7tS2VshqO0wWkk/edit?resourcekey=0-2YFC9Uvl4puuDnWlr2MmYw\n#   TODO: Replace with path to the markdown once this lands.\n#\n# First, we provide a flag to enable a release version: `--release`. It is\n# disabled by default, and if enabled it must be the only version flag used.\nbool_flag(\n    name = \"release\",\n    build_setting_default = False,\n)\n\n# A `--pre_release=KIND` flag where `KIND` must be one of:\n# - `rc` -- a release candidate version.\n#    Example: `--pre_release=rc --rc_number=2`\n# - `nightly -- a nightly version.\n#    Example: `--pre_release=nightly --nightly_date=2024.06.17`\n# - `dev` -- the default, a development build.\n#    Example: `--pre_release=dev`\n#\n# This flag cannot be used along with `--release`, and for all but the `dev`\n# kind must be combined with one of the below flags to specify further details\n# of the version.\nstring_flag(\n    name = \"pre_release\",\n    build_setting_default = \"dev\",\n    values = [\n        \"rc\",\n        \"nightly\",\n        \"dev\",\n    ],\n)\n\n# `--rc_number=N` sets the release candidate number to `N`. Requires\n# `--pre_release=rc`.\nint_flag(\n    name = \"rc_number\",\n    build_setting_default = -1,\n)\n\n# `--nigthly_date=YYYY.MM.DD` sets the nightly pre-release date. Requires\n# `--pre_release=nightly`. The value for this flag must be a string with the\n# exact format of `YYYY.MM.DD`.\nstring_flag(\n    name = \"nightly_date\",\n    build_setting_default = \"\",\n)\n\n# A config setting to observe the value of the `--stamp` command line flag\n# within starlark with a macro and `select`. This is a workaround suggested for\n# a Bazel issue: https://github.com/bazelbuild/bazel/issues/11164\nconfig_setting(\n    name = \"internal_stamp_flag_detect\",\n    values = {\"stamp\": \"1\"},\n    visibility = [\"//visibility:public\"],\n)\n"
  },
  {
    "path": "bazel/version/compute_version.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Compute the version string.\"\"\"\n\nload(\"@bazel_skylib//rules:common_settings.bzl\", \"BuildSettingInfo\")\nload(\"//:version_base.bzl\", \"version_base\")\n\ndef _validate_nightly_date(date):\n    date_components = date.split(\".\", 2)\n    if len(date_components) != 3:\n        fail(\"Must provide a nightly date in 'YYYY.MM.DD' format, found '{}'.\".format(date))\n    year = date_components[0]\n    if len(year) != 4 or not year.isdigit():\n        fail(\"The nightly date year was not a sequence of four digits.\")\n    month = date_components[1]\n    if len(month) != 2 or not month.isdigit():\n        fail(\"The nightly date month was not a sequence of two digits.\")\n    day = date_components[2]\n    if len(day) != 2 or not day.isdigit():\n        fail(\"The nightly date day was not a sequence of two digits.\")\n\ndef compute_version(ctx):\n    \"\"\"Compute the version string.\n\n    Args:\n        ctx: The context for a rule computing the version.\n\n    Returns:\n        The version string.\n    \"\"\"\n    version = version_base\n\n    # See if we need to append a pre-release suffix to the version.\n    #\n    # TODO: We should more fully check for erroneous combinations of flags here\n    # to help ensure users don't get surprising results.\n    if not ctx.attr._release_flag[BuildSettingInfo].value:\n        pre_release = ctx.attr._pre_release_flag[BuildSettingInfo].value\n        pre_release_numbers = {\n            \"rc\": ctx.attr._rc_number_flag[BuildSettingInfo].value,\n        }\n        if pre_release in pre_release_numbers:\n            number = pre_release_numbers[pre_release]\n            if number < 0:\n                fail(\"Must provide a non-negative {} number when building that pre-release.\".format(pre_release))\n            version += \"-{0}.{1}\".format(pre_release, number)\n        elif pre_release == \"nightly\":\n            date = ctx.attr._nightly_date_flag[BuildSettingInfo].value\n            _validate_nightly_date(date)\n            version += \"-0.nightly.{}\".format(date)\n        elif pre_release == \"dev\":\n            version += \"-0.dev\"\n        else:\n            fail(\"Invalid pre-release flag: \" + pre_release)\n\n    return version\n\nVERSION_ATTRS = {\n    \"_nightly_date_flag\": attr.label(default = \":nightly_date\"),\n    \"_pre_release_flag\": attr.label(default = \":pre_release\"),\n    \"_rc_number_flag\": attr.label(default = \":rc_number\"),\n    \"_release_flag\": attr.label(default = \":release\"),\n}\n"
  },
  {
    "path": "bazel/version/gen_tmpl.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Generate a file from a template, substituting the provided key/value pairs.\n\nThe file format should match Python's `string.Template` substitution rules:\n- `$$` for a literal `$`\n- `$identifier` for some key `identifier` to be substituted\n- `${identifier}` when adjacent text would be interpreted as part of the\n  identifier.\n\nThe keys must be strings that are valid identifiers: `[_A-Za-z][_A-Za-z0-9]*`\n\nThe values may not contain newlines or any vertical whitespace.\n\nThe initial key/value pairs are read from the command line using repeated\n`--substitute=KEY=DEFAULT-VALUE` flags.\n\nUpdated values for those keys will be read from any files provided to the\n`--status-file` flag. This flag can be given multiple times and the values will\nbe read and updated from the files in order, meaning the last file's value will\nwin. New keys are never read from these files. The file format parsed is Bazel's\n[status file format](https://bazel.build/docs/user-manual#workspace-status):\neach line is a single entry starting with a key using only characters `[_A-Z]`,\none space character, and the rest of the line is the value. To assist with using\nBazel status files, if the key parsed from the file begins with `STABLE_`, that\nprefix is removed. Any keys which are present in the substitutions provided on\nthe command line will have their value updated with the string read from the\nfile.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport argparse\nimport sys\nfrom pathlib import Path\nfrom string import Template\n\n\ndef main() -> None:\n    parser = argparse.ArgumentParser(__doc__)\n    parser.add_argument(\n        \"--template\",\n        metavar=\"FILE\",\n        type=Path,\n        required=True,\n        help=\"The template source file to use.\",\n    )\n    parser.add_argument(\n        \"--output\",\n        metavar=\"FILE\",\n        type=Path,\n        required=True,\n        help=\"The output source file to produce.\",\n    )\n    parser.add_argument(\n        \"--substitution\",\n        metavar=\"KEY=DEFAULT-VALUE\",\n        action=\"append\",\n        help=\"A substitution that should be supported and its default value.\",\n    )\n    parser.add_argument(\n        \"--status-file\",\n        metavar=\"FILE\",\n        type=Path,\n        action=\"append\",\n        default=[],\n        help=\"A file of key/value updates in Bazel's status file format.\",\n    )\n    parser.add_argument(\"-v\", \"--verbose\", action=\"store_true\")\n    args = parser.parse_args()\n\n    # Collect the supported substitutions from the command line.\n    substitutions = {}\n    for substitution_arg in args.substitution:\n        key, value = substitution_arg.split(\"=\", 1)\n        substitutions.update({key: value})\n\n    # Read either of the two status files provided to build up substitutions,\n    # with the stable file last so its values override any duplicates.\n    for status_file in args.status_file:\n        if args.verbose:\n            print(f\"Reading status file: {status_file}\", file=sys.stderr)\n        for line in status_file.open():\n            # Remove line endings.\n            line = line.rstrip(\"\\r\\n\")\n            # Exactly matches our pattern\n            key, value = line.split(\" \", 1)\n            key = key.removeprefix(\"STABLE_\")\n            if key in substitutions:\n                if args.verbose:\n                    print(f\"Parsed: '{key}': '{value}'\", file=sys.stderr)\n                substitutions.update({key: value})\n\n    if args.verbose:\n        print(f\"Reading template file: {args.template}\", file=sys.stderr)\n    with open(args.template) as template_file:\n        template = template_file.read()\n\n    result = Template(template).substitute(substitutions)\n\n    if args.verbose:\n        print(f\"Writing output file: {args.output}\", file=sys.stderr)\n    with open(args.output, mode=\"w\") as output_file:\n        output_file.write(result)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "bazel/version/rules.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Rule to expand Bazel templates with version and build information.\n\nThis rule takes a source code template and turns that into a specific source\ncode output, substituting version information and build information from Bazel's\n`stable-status.txt` and `volatile-status.txt` produced by the\n`workpsace_status_command` during the build. When stamping is disabled, the\nbuild information is replaced with constant values to provide better caching.\n\nThe template files should use Python's \"template strings\" syntax[1]. These rules\nprovide a fixed set of keys whose values will be substituted, and those keys\nwill always be substituted with something. They will have the value in the\nstable status file if present, otherwise the value in the volatile status file\nif present, otherwise the value \"unknown\". When reading keys from the status\nfiles, a prefix of `STABLE_` will be removed from the key if present.\n\n[1]: https://docs.python.org/3/library/string.html#template-strings\n\nThe substituted keys, and any guidance on values:\n- `VERSION` (the version string for Carbon)\n- `BUILD_EMBED_LABEL` (value of --embed_label)\n- `BUILD_HOST` (the name of the host machine running the build)\n- `BUILD_USER` (the name of the user running the build)\n- `GIT_COMMIT_SHA` (output of `git parse-rev --short HEAD` or `unknown`)\n- `GIT_DIRTY_SUFFIX` (`.dirty` if dirty client state or `` if unknown)\n- `BUILD_TIMESTAMP` (the time of the build in seconds since the Unix Epoch)\n- `ATTRIBUTE` (an optional attribute to apply to definitions, defaults to empty)\n\"\"\"\n\nload(\":compute_version.bzl\", \"compute_version\")\n\n_STAMP_DOC = \"\"\"\nFollows behavior of the common 'stamp' attributes on rules. Set to 1 or 0 to\nforce stamping with actual build info on or off respectively, and to -1 to\nfollow the value of the command line flag `--stamp`.\n\"\"\"\n\ndef _is_exec_config(ctx):\n    \"\"\"Detect if this is the exec configuration, previously known as \"host\".\n\n    Sadly, there is not yet a supported way to detect this so replicate the\n    hacks others currently use. Bazel issue:\n    https://github.com/bazelbuild/bazel/issues/14444\n    \"\"\"\n    return \"-exec\" in ctx.bin_dir.path or \"/host/\" in ctx.bin_dir.path\n\ndef _expand_version_build_info_impl(ctx):\n    \"\"\"Generates a file from a template, substituting version and build info.\"\"\"\n    inputs = [ctx.file.template]\n\n    # The substitutions provided and their default values.\n    substitutions = {\n        \"BUILD_EMBED_LABEL\": \"unknown\",\n        \"BUILD_HOST\": \"unknown\",\n        \"BUILD_TIMESTAMP\": \"unknown\",\n        \"BUILD_USER\": \"unknown\",\n        \"GIT_COMMIT_SHA\": \"unknown\",\n        \"GIT_DIRTY_SUFFIX\": \"\",\n        \"MAKE_WEAK\": \"0\",\n        \"VERSION\": compute_version(ctx),\n    }\n    substitutions.update(ctx.attr.substitutions)\n\n    arguments = [\n        \"--template=\" + ctx.file.template.path,\n        \"--output=\" + ctx.outputs.out.path,\n    ] + [\n        \"--substitution=\" + key + \"=\" + value\n        for key, value in substitutions.items()\n    ]\n\n    # We only want to allow stamping outside of the exec configuration.\n    if not _is_exec_config(ctx):\n        # Look at the attribute.\n        stamp = ctx.attr.stamp\n\n        # If requested, use the command line flag to select.\n        if stamp == -1:\n            # Set the default from `--stamp` / `--nostamp` command line flag,\n            # which we detect through a macro and `config_setting`, and pipe\n            # through an attribute.\n            stamp = 1 if ctx.attr.internal_stamp_flag_detect else 0\n\n        # Add the status files if stamping.\n        if stamp == 1:\n            inputs += [\n                ctx.info_file,\n                ctx.version_file,\n            ]\n            arguments += [\n                \"--status-file=\" + ctx.info_file.path,\n                \"--status-file=\" + ctx.version_file.path,\n            ]\n\n    ctx.actions.run(\n        inputs = inputs,\n        outputs = [ctx.outputs.out],\n        executable = ctx.executable._gen_tmpl_tool,\n        arguments = arguments,\n        progress_message = \"Generating templated source file: \" +\n                           ctx.outputs.out.short_path,\n    )\n\nexpand_version_build_info_internal = rule(\n    implementation = _expand_version_build_info_impl,\n    attrs = {\n        \"internal_stamp_flag_detect\": attr.bool(default = False),\n        \"out\": attr.output(mandatory = True),\n        \"stamp\": attr.int(values = [-1, 0, 1], default = -1, doc = _STAMP_DOC),\n        \"substitutions\": attr.string_dict(\n            doc = \"Extra substitutions, potentially overriding defaults.\",\n        ),\n        \"template\": attr.label(\n            allow_single_file = True,\n        ),\n        \"_gen_tmpl_tool\": attr.label(\n            default = Label(\"//bazel/version:gen_tmpl\"),\n            allow_files = True,\n            executable = True,\n            cfg = \"exec\",\n        ),\n        \"_nightly_date_flag\": attr.label(default = \":nightly_date\"),\n        \"_pre_release_flag\": attr.label(default = \":pre_release\"),\n        \"_rc_number_flag\": attr.label(default = \":rc_number\"),\n        \"_release_flag\": attr.label(default = \":release\"),\n    },\n)\n\n# We need a macro wrapping the rule so that we can inject a select that observes\n# the `--stamp` command-line value and use that when needed.\ndef expand_version_build_info(name, **kwargs):\n    expand_version_build_info_internal(\n        name = name,\n        internal_stamp_flag_detect = False if kwargs.get(\"stamp\") == 0 else select({\n            \"//bazel/version:internal_stamp_flag_detect\": True,\n            \"//conditions:default\": False,\n        }),\n        **kwargs\n    )\n"
  },
  {
    "path": "common/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@rules_shell//shell:sh_test.bzl\", \"sh_test\")\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_binary\", \"cc_library\", \"cc_test\")\nload(\"//bazel/version:rules.bzl\", \"expand_version_build_info\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncc_library(\n    name = \"array_stack\",\n    hdrs = [\"array_stack.h\"],\n    deps = [\n        \":check\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"array_stack_test\",\n    size = \"small\",\n    srcs = [\"array_stack_test.cpp\"],\n    deps = [\n        \":array_stack\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"bazel_working_dir\",\n    hdrs = [\"bazel_working_dir.h\"],\n    deps = [\n        \":check\",\n        \":filesystem\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"build_data\",\n    srcs = [\n        \"build_data.cpp\",\n        \"build_data_linkstamp.h\",\n    ],\n    hdrs = [\"build_data.h\"],\n    linkstamp = \"build_data_linkstamp.cpp\",\n    deps = [\"@llvm-project//llvm:Support\"],\n)\n\ncc_test(\n    name = \"build_data_test\",\n    size = \"small\",\n    srcs = [\"build_data_test.cpp\"],\n    deps = [\n        \":build_data\",\n        \":ostream\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"command_line\",\n    srcs = [\"command_line.cpp\"],\n    hdrs = [\"command_line.h\"],\n    deps = [\n        \":check\",\n        \":error\",\n        \":ostream\",\n        \":raw_string_ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"command_line_test\",\n    size = \"small\",\n    srcs = [\"command_line_test.cpp\"],\n    deps = [\n        \":command_line\",\n        \":error_test_helpers\",\n        \":raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"check\",\n    srcs = [\n        \"check_internal.cpp\",\n        \"check_internal.h\",\n    ],\n    hdrs = [\"check.h\"],\n    deps = [\n        \":ostream\",\n        \":template_string\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"check_test\",\n    size = \"small\",\n    srcs = [\"check_test.cpp\"],\n    deps = [\n        \":check\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"concepts\",\n    hdrs = [\"concepts.h\"],\n)\n\ncc_library(\n    name = \"emplace_by_calling\",\n    hdrs = [\"emplace_by_calling.h\"],\n)\n\ncc_test(\n    name = \"emplace_by_calling_test\",\n    srcs = [\"emplace_by_calling_test.cpp\"],\n    deps = [\n        \":emplace_by_calling\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"enum_base\",\n    hdrs = [\"enum_base.h\"],\n    deps = [\n        \"//common:ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"enum_base_test_def\",\n    testonly = 1,\n    textual_hdrs = [\"enum_base_test.def\"],\n)\n\ncc_test(\n    name = \"enum_base_test\",\n    size = \"small\",\n    srcs = [\"enum_base_test.cpp\"],\n    deps = [\n        \":enum_base\",\n        \":enum_base_test_def\",\n        \":raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"enum_mask_base\",\n    hdrs = [\"enum_mask_base.h\"],\n    deps = [\n        \":enum_base\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"enum_mask_base_test\",\n    size = \"small\",\n    srcs = [\"enum_mask_base_test.cpp\"],\n    deps = [\n        \":enum_mask_base\",\n        \":raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"error\",\n    hdrs = [\"error.h\"],\n    deps = [\n        \":check\",\n        \":ostream\",\n        \":raw_string_ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"error_test_helpers\",\n    testonly = 1,\n    hdrs = [\"error_test_helpers.h\"],\n    deps = [\n        \":error\",\n        \":ostream\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_test(\n    name = \"error_test\",\n    size = \"small\",\n    srcs = [\"error_test.cpp\"],\n    deps = [\n        \":error\",\n        \":error_test_helpers\",\n        \":raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"exe_path\",\n    srcs = [\"exe_path.cpp\"],\n    hdrs = [\"exe_path.h\"],\n    deps = [\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"exe_path_test\",\n    size = \"small\",\n    srcs = [\"exe_path_test.cpp\"],\n    deps = [\n        \":exe_path\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"filesystem\",\n    srcs = [\"filesystem.cpp\"],\n    hdrs = [\"filesystem.h\"],\n    deps = [\n        \":build_data\",\n        \":check\",\n        \":error\",\n        \":ostream\",\n        \":raw_string_ostream\",\n        \":template_string\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"filesystem_test\",\n    size = \"small\",\n    srcs = [\"filesystem_test.cpp\"],\n    deps = [\n        \":error_test_helpers\",\n        \":filesystem\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_binary(\n    name = \"filesystem_benchmark\",\n    testonly = 1,\n    srcs = [\"filesystem_benchmark.cpp\"],\n    deps = [\n        \":check\",\n        \":filesystem\",\n        \"//testing/base:benchmark_main\",\n        \"@abseil-cpp//absl/hash\",\n        \"@abseil-cpp//absl/random\",\n        \"@google_benchmark//:benchmark\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\nsh_test(\n    name = \"filesystem_benchmark_test\",\n    size = \"small\",\n    srcs = [\":filesystem_benchmark\"],\n    args = [\n        \"--benchmark_dry_run\",\n        # Restrict the sizes to 4-digit ones or smaller to keep test times low.\n        # The `$$` is repeated for Bazel escaping of `$`.\n        \"--benchmark_filter=^[^/]+(/[0-9]{1,4}(/[0-9]+)?)?/real_time$$\",\n    ],\n)\n\ncc_library(\n    name = \"find\",\n    hdrs = [\"find.h\"],\n    deps = [\n        \":check\",\n        \":ostream\",\n        \":raw_string_ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"find_test\",\n    size = \"small\",\n    srcs = [\"find_test.cpp\"],\n    deps = [\n        \":find\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"growing_range\",\n    hdrs = [\"growing_range.h\"],\n)\n\ncc_test(\n    name = \"growing_range_test\",\n    size = \"small\",\n    srcs = [\"growing_range_test.cpp\"],\n    deps = [\n        \":growing_range\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"hashing\",\n    srcs = [\"hashing.cpp\"],\n    hdrs = [\"hashing.h\"],\n    deps = [\n        \":check\",\n        \":ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"hashing_test\",\n    size = \"small\",\n    srcs = [\"hashing_test.cpp\"],\n    deps = [\n        \":hashing\",\n        \":raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_binary(\n    name = \"hashing_benchmark\",\n    testonly = 1,\n    srcs = [\"hashing_benchmark.cpp\"],\n    deps = [\n        \":check\",\n        \":hashing\",\n        \"//testing/base:benchmark_main\",\n        \"@abseil-cpp//absl/hash\",\n        \"@abseil-cpp//absl/random\",\n        \"@google_benchmark//:benchmark\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"hashtable_key_context\",\n    hdrs = [\"hashtable_key_context.h\"],\n    deps = [\n        \":hashing\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"hashtable_key_context_test\",\n    size = \"small\",\n    srcs = [\"hashtable_key_context_test.cpp\"],\n    deps = [\n        \":hashtable_key_context\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"init_llvm\",\n    srcs = [\"init_llvm.cpp\"],\n    hdrs = [\"init_llvm.h\"],\n    deps = [\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\n# Link against this to cause `:init_llvm` to pull in all LLVM targets.\n#\n# Be careful when depending on this: it pulls in several hundred megabytes of\n# LLVM binary size in -c fastbuild. This should only be depended on by a\n# `cc_binary` or `cc_test` target, never a `cc_library`.\ncc_library(\n    name = \"all_llvm_targets\",\n    srcs = [\"all_llvm_targets.cpp\"],\n    deps = [\n        \":init_llvm\",\n        \"@llvm-project//llvm:AllTargetsAsmParsers\",\n        \"@llvm-project//llvm:AllTargetsCodeGens\",\n        \"@llvm-project//llvm:Support\",\n    ],\n    alwayslink = 1,\n)\n\ncc_library(\n    name = \"latch\",\n    srcs = [\"latch.cpp\"],\n    hdrs = [\"latch.h\"],\n    deps = [\n        \":check\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"latch_test\",\n    size = \"small\",\n    srcs = [\"latch_test.cpp\"],\n    deps = [\n        \":latch\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"map\",\n    hdrs = [\"map.h\"],\n    deps = [\n        \":check\",\n        \":concepts\",\n        \":hashtable_key_context\",\n        \":raw_hashtable\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"map_test\",\n    size = \"small\",\n    srcs = [\"map_test.cpp\"],\n    deps = [\n        \":map\",\n        \":raw_hashtable_test_helpers\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_binary(\n    name = \"map_benchmark\",\n    testonly = 1,\n    srcs = [\"map_benchmark.cpp\"],\n    deps = [\n        \":map\",\n        \":raw_hashtable_benchmark_helpers\",\n        \"//testing/base:benchmark_main\",\n        \"@abseil-cpp//absl/container:flat_hash_map\",\n        \"@abseil-cpp//absl/random\",\n        \"@boost.unordered\",\n        \"@google_benchmark//:benchmark\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\nsh_test(\n    name = \"map_benchmark_test\",\n    # The benchmark allocates a large amount of memory.\n    size = \"enormous\",\n    # We configure the test to run somewhat quickly.\n    timeout = \"moderate\",\n    srcs = [\":map_benchmark\"],\n    args = [\n        \"--benchmark_dry_run\",\n        # The `$$` is repeated for Bazel escaping of `$`.\n        \"--benchmark_filter=^[^/]*/[1-9][0-9]{0,3}(/[0-9]+)?$$\",\n    ],\n)\n\ncc_library(\n    name = \"move_only\",\n    hdrs = [\"move_only.h\"],\n)\n\ncc_library(\n    name = \"ostream\",\n    hdrs = [\"ostream.h\"],\n    deps = [\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"pretty_stack_trace_function\",\n    hdrs = [\"pretty_stack_trace_function.h\"],\n    deps = [\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"raw_hashtable\",\n    srcs = [\"raw_hashtable.cpp\"],\n    hdrs = [\"raw_hashtable.h\"],\n    deps = [\n        \":check\",\n        \":concepts\",\n        \":hashing\",\n        \":hashtable_key_context\",\n        \":raw_hashtable_metadata_group\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"raw_hashtable_metadata_group\",\n    srcs = [\"raw_hashtable_metadata_group.cpp\"],\n    hdrs = [\"raw_hashtable_metadata_group.h\"],\n    deps = [\n        \":check\",\n        \":ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_binary(\n    name = \"raw_hashtable_metadata_group_benchmark\",\n    testonly = 1,\n    srcs = [\"raw_hashtable_metadata_group_benchmark.cpp\"],\n    deps = [\n        \":raw_hashtable_metadata_group\",\n        \"//testing/base:benchmark_main\",\n        \"@abseil-cpp//absl/random\",\n        \"@google_benchmark//:benchmark\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\nsh_test(\n    name = \"raw_hashtable_metadata_group_benchmark_test\",\n    size = \"small\",\n    srcs = [\"raw_hashtable_metadata_group_benchmark\"],\n    args = [\n        \"--benchmark_dry_run\",\n    ],\n)\n\ncc_library(\n    name = \"raw_hashtable_benchmark_helpers\",\n    testonly = 1,\n    srcs = [\"raw_hashtable_benchmark_helpers.cpp\"],\n    hdrs = [\"raw_hashtable_benchmark_helpers.h\"],\n    copts = [\n        \"-O2\",  # Always optimize to make testing benchmarks faster.\n    ],\n    deps = [\n        \":check\",\n        \":hashing\",\n        \":raw_hashtable\",\n        \":set\",\n        \"@abseil-cpp//absl/base:no_destructor\",\n        \"@abseil-cpp//absl/hash\",\n        \"@abseil-cpp//absl/random\",\n        \"@boost.unordered\",\n        \"@google_benchmark//:benchmark\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"raw_hashtable_test_helpers\",\n    testonly = 1,\n    hdrs = [\"raw_hashtable_test_helpers.h\"],\n    deps = [\n        \":check\",\n        \":hashing\",\n        \":hashtable_key_context\",\n        \":ostream\",\n    ],\n)\n\ncc_library(\n    name = \"raw_string_ostream\",\n    hdrs = [\"raw_string_ostream.h\"],\n    deps = [\n        \":check\",\n        \":ostream\",\n    ],\n)\n\ncc_test(\n    name = \"raw_string_ostream_test\",\n    size = \"small\",\n    srcs = [\"raw_string_ostream_test.cpp\"],\n    deps = [\n        \":raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"set\",\n    hdrs = [\"set.h\"],\n    deps = [\n        \":check\",\n        \":hashtable_key_context\",\n        \":raw_hashtable\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"set_test\",\n    size = \"small\",\n    srcs = [\"set_test.cpp\"],\n    deps = [\n        \":raw_hashtable_test_helpers\",\n        \":set\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_binary(\n    name = \"set_benchmark\",\n    testonly = 1,\n    srcs = [\"set_benchmark.cpp\"],\n    deps = [\n        \":raw_hashtable_benchmark_helpers\",\n        \":set\",\n        \"//testing/base:benchmark_main\",\n        \"@abseil-cpp//absl/container:flat_hash_set\",\n        \"@google_benchmark//:benchmark\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\nsh_test(\n    name = \"set_benchmark_test\",\n    # The benchmark allocates a large amount of memory.\n    size = \"enormous\",\n    # We configure the test to run somewhat quickly.\n    timeout = \"moderate\",\n    srcs = [\":set_benchmark\"],\n    args = [\n        \"--benchmark_dry_run\",\n        # The `$$` is repeated for Bazel escaping of `$`.\n        \"--benchmark_filter=^[^/]*/[1-9][0-9]{0,3}(/[0-9]+)?$$\",\n    ],\n)\n\ncc_library(\n    name = \"string_helpers\",\n    srcs = [\"string_helpers.cpp\"],\n    hdrs = [\"string_helpers.h\"],\n    deps = [\n        \":check\",\n        \":error\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"string_helpers_test\",\n    size = \"small\",\n    srcs = [\"string_helpers_test.cpp\"],\n    deps = [\n        \":string_helpers\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"struct_reflection\",\n    hdrs = [\"struct_reflection.h\"],\n)\n\ncc_test(\n    name = \"struct_reflection_test\",\n    size = \"small\",\n    srcs = [\"struct_reflection_test.cpp\"],\n    deps = [\n        \":struct_reflection\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"template_string\",\n    hdrs = [\"template_string.h\"],\n    deps = [\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"template_string_test\",\n    size = \"small\",\n    srcs = [\"template_string_test.cpp\"],\n    deps = [\n        \":template_string\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"type_enum\",\n    hdrs = [\"type_enum.h\"],\n    deps = [\":ostream\"],\n)\n\n# The base version source file only uses non-stamped parts of the version\n# information so we expand it once here without any stamping.\nexpand_version_build_info(\n    name = \"version_cpp_gen\",\n    out = \"version.cpp\",\n    stamp = 0,\n    template = \"version.tmpl.cpp\",\n)\n\n# Build a nostamp version of the stamp source, but mark its definitions as weak.\n# We'll include this in the library to satisfy definitions of library and test\n# users, but still allow binaries that want full build stamping to depend on the\n# stamp library below to override with strong, stamped definitions.\nexpand_version_build_info(\n    name = \"version_nostamp_cpp_gen\",\n    out = \"version_nostamp.cpp\",\n    stamp = 0,\n    substitutions = {\"MAKE_WEAK\": \"1\"},\n    template = \"version_stamp.tmpl.cpp\",\n)\n\n# Provides APIs for accessing Carbon version information.\n#\n# These provide full access to the major, minor, and patch version. It also\n# provides an API for querying version strings that may contain detailed build\n# information such as the commit SHA.\n#\n# By default, this provides the API and an *unstamped* implementations of\n# version strings. As a consequence, depending on this library doesn't introduce\n# any dependency on the commit SHA or loss of build caching.\n#\n# Targets that want full build info stamping in the data produced by these APIs\n# should additionally depend on `:version_stamp` below -- the data these APIs\n# return will be overridden in any binaries depending on that rule with the\n# fully stamped details.\ncc_library(\n    name = \"version\",\n    srcs = [\n        \"version.cpp\",\n        \"version_nostamp.cpp\",\n    ],\n    hdrs = [\"version.h\"],\n    deps = [\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\n# Generate the fully stamped sourcefile if stamping is enabled in the build.\nexpand_version_build_info(\n    name = \"version_stamp_cpp_gen\",\n    out = \"version_stamp.cpp\",\n    template = \"version_stamp.tmpl.cpp\",\n)\n\n# Depend on this library to enable fully-stamped build information in the\n# version API provided by `:version`. This doesn't provide the API, it injects\n# an override of stamped versions of the data.\n#\n# Note that depending on this will significantly reduce build caching with\n# `--stamp` builds. It should be used sparingly, typically in user-facing\n# binaries or systems that need to render a maximally detailed version string\n# with build information stamped into it.\ncc_library(\n    name = \"version_stamp\",\n    srcs = [\"version_stamp.cpp\"],\n    deps = [\n        \":version\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"vlog\",\n    hdrs = [\"vlog.h\"],\n    deps = [\n        \":ostream\",\n        \":template_string\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"vlog_test\",\n    size = \"small\",\n    srcs = [\"vlog_test.cpp\"],\n    deps = [\n        \":raw_string_ostream\",\n        \":vlog\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n"
  },
  {
    "path": "common/all_llvm_targets.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/init_llvm.h\"\n#include \"llvm/Support/TargetSelect.h\"\n\nnamespace Carbon {\n\nstatic auto InitLLVMTargets() -> void {\n  llvm::InitializeAllTargetInfos();\n  llvm::InitializeAllTargets();\n  llvm::InitializeAllTargetMCs();\n  llvm::InitializeAllAsmParsers();\n  llvm::InitializeAllAsmPrinters();\n}\n\n// On program startup, set `InitLLVM::InitializeTargets` to be our\n// initialization function so that `InitLLVM` can call it at the right moment.\nconst char InitLLVM::RegisterTargets =\n    (InitializeTargets = &InitLLVMTargets, 0);\n\n}  // namespace Carbon\n"
  },
  {
    "path": "common/array_stack.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_ARRAY_STACK_H_\n#define CARBON_COMMON_ARRAY_STACK_H_\n\n#include \"common/check.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/SmallVector.h\"\n\nnamespace Carbon {\n\n// Provides a stack of arrays. Only the array at the top of the stack can have\n// elements added.\n//\n// Example usage:\n//   // Push to start.\n//   PushArray();\n//   // Add values.\n//   AppendToTop(3);\n//   // Look at values.\n//   PeekArray();\n//   // Pop when done.\n//   PopArray();\n//\n// By using a single vector for elements, the intent is that as arrays are\n// pushed and popped, the same storage will be reused. This should yield\n// efficiencies for heap allocations. For example, in the toolchain we\n// frequently have an array per scope, and only add to the current scope's\n// array; this allows better reuse when entering and leaving scopes.\ntemplate <typename ValueT>\nclass ArrayStack {\n public:\n  // Pushes a new array onto the stack.\n  auto PushArray() -> void { array_offsets_.push_back(values_.size()); }\n\n  // Pops the top array from the stack.\n  auto PopArray() -> void {\n    auto region = array_offsets_.pop_back_val();\n    values_.truncate(region);\n  }\n\n  // Returns the top array from the stack.\n  auto PeekArray() const -> llvm::ArrayRef<ValueT> {\n    CARBON_CHECK(!array_offsets_.empty());\n    return llvm::ArrayRef(values_).slice(array_offsets_.back());\n  }\n\n  auto PeekArray() -> llvm::MutableArrayRef<ValueT> {\n    CARBON_CHECK(!array_offsets_.empty());\n    return llvm::MutableArrayRef(values_).slice(array_offsets_.back());\n  }\n\n  // Returns the array at a specific index.\n  auto PeekArrayAt(int index) const -> llvm::ArrayRef<ValueT> {\n    auto ref = llvm::ArrayRef(values_).slice(array_offsets_[index]);\n    if (index + 1 < static_cast<int>(array_offsets_.size())) {\n      ref = ref.take_front(array_offsets_[index + 1] - array_offsets_[index]);\n    }\n    return ref;\n  }\n\n  // Returns the full set of values on the stack, regardless of whether any\n  // arrays are pushed.\n  auto PeekAllValues() const -> llvm::ArrayRef<ValueT> { return values_; }\n\n  // Appends a value to the top array on the stack.\n  auto AppendToTop(const ValueT& value) -> void {\n    CARBON_CHECK(!array_offsets_.empty(),\n                 \"Must call PushArray before AppendToTop.\");\n    values_.push_back(value);\n  }\n\n  // Appends a value to the top array on the stack.\n  auto AppendToTop(ValueT&& value) -> void {\n    CARBON_CHECK(!array_offsets_.empty(),\n                 \"Must call PushArray before AppendToTop.\");\n    values_.push_back(std::move(value));\n  }\n\n  // Adds multiple values to the top array on the stack.\n  auto AppendToTop(llvm::ArrayRef<ValueT> values) -> void {\n    CARBON_CHECK(!array_offsets_.empty(),\n                 \"Must call PushArray before AppendToTop.\");\n    llvm::append_range(values_, values);\n  }\n\n  // Returns the current number of values in all arrays.\n  auto all_values_size() const -> size_t { return values_.size(); }\n\n  // Returns true if the stack has no arrays pushed.\n  auto empty() const -> bool { return array_offsets_.empty(); }\n\n private:\n  // For each pushed array, the start index in `values_`.\n  llvm::SmallVector<int32_t> array_offsets_;\n\n  // The full set of elements in all arrays.\n  llvm::SmallVector<ValueT> values_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_ARRAY_STACK_H_\n"
  },
  {
    "path": "common/array_stack_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/array_stack.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::IsEmpty;\n\nTEST(ArrayStack, Basics) {\n  ArrayStack<int> stack;\n\n  // PeekAllValues is valid when there are no arrays.\n  EXPECT_THAT(stack.PeekAllValues(), IsEmpty());\n\n  // An array starts empty.\n  stack.PushArray();\n  EXPECT_THAT(stack.PeekArray(), IsEmpty());\n  EXPECT_THAT(stack.PeekAllValues(), IsEmpty());\n\n  // Pushing a couple values works.\n  stack.AppendToTop(1);\n  stack.AppendToTop(2);\n  EXPECT_THAT(stack.PeekArray(), ElementsAre(1, 2));\n  EXPECT_THAT(stack.PeekAllValues(), ElementsAre(1, 2));\n\n  // Pushing a new array starts empty, old values are still there.\n  stack.PushArray();\n  EXPECT_THAT(stack.PeekArray(), IsEmpty());\n  EXPECT_THAT(stack.PeekAllValues(), ElementsAre(1, 2));\n\n  // The added value goes to the 2nd array.\n  stack.AppendToTop(3);\n  EXPECT_THAT(stack.PeekArray(), ElementsAre(3));\n  EXPECT_THAT(stack.PeekAllValues(), ElementsAre(1, 2, 3));\n\n  // Popping goes back to the 1st array.\n  stack.PopArray();\n  EXPECT_THAT(stack.PeekArray(), ElementsAre(1, 2));\n  EXPECT_THAT(stack.PeekAllValues(), ElementsAre(1, 2));\n\n  // Push a couple arrays, then a value on the now-3rd array.\n  stack.PushArray();\n  stack.PushArray();\n  stack.AppendToTop(4);\n  EXPECT_THAT(stack.PeekArray(), ElementsAre(4));\n  EXPECT_THAT(stack.PeekAllValues(), ElementsAre(1, 2, 4));\n\n  // Popping the 3rd array goes to the 2nd array, which is empty.\n  stack.PopArray();\n  EXPECT_THAT(stack.PeekArray(), IsEmpty());\n  EXPECT_THAT(stack.PeekAllValues(), ElementsAre(1, 2));\n\n  // Again back to the 1st array.\n  stack.PopArray();\n  EXPECT_THAT(stack.PeekArray(), ElementsAre(1, 2));\n  EXPECT_THAT(stack.PeekAllValues(), ElementsAre(1, 2));\n\n  // Go down to no arrays.\n  stack.PopArray();\n  EXPECT_THAT(stack.PeekAllValues(), IsEmpty());\n\n  // Add a new 1st array.\n  stack.PushArray();\n  stack.AppendToTop(5);\n  EXPECT_THAT(stack.PeekArray(), ElementsAre(5));\n  EXPECT_THAT(stack.PeekAllValues(), ElementsAre(5));\n}\n\nTEST(ArrayStack, AppendArray) {\n  ArrayStack<int> stack;\n\n  stack.PushArray();\n  stack.AppendToTop(llvm::ArrayRef<int>());\n  EXPECT_THAT(stack.PeekArray(), IsEmpty());\n  stack.AppendToTop({1, 2});\n  EXPECT_THAT(stack.PeekArray(), ElementsAre(1, 2));\n}\n\nTEST(ArrayStack, PeekArrayAt) {\n  ArrayStack<int> stack;\n\n  // Verify behavior with a single array.\n  stack.PushArray();\n  stack.AppendToTop(1);\n  stack.AppendToTop(2);\n\n  EXPECT_THAT(stack.PeekArrayAt(0), ElementsAre(1, 2));\n\n  // Verify behavior with a couple more arrays.\n  stack.PushArray();\n  stack.PushArray();\n  stack.AppendToTop(3);\n\n  EXPECT_THAT(stack.PeekArrayAt(0), ElementsAre(1, 2));\n  EXPECT_THAT(stack.PeekArrayAt(1), IsEmpty());\n  EXPECT_THAT(stack.PeekArrayAt(2), ElementsAre(3));\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "common/bazel_working_dir.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_BAZEL_WORKING_DIR_H_\n#define CARBON_COMMON_BAZEL_WORKING_DIR_H_\n\n#include <stdlib.h>\n\n#include <filesystem>\n#include <system_error>\n\n#include \"common/check.h\"\n#include \"common/filesystem.h\"\n\nnamespace Carbon {\n\n// Change working directory to behave as if it is where `bazel run` was invoked.\n//\n// Accepts an optional `exe_path` argument that will be adjusted to continue to\n// be valid after this adjustment.\n//\n// There is no reasonable recovery we can do if either we can't make the path\n// absolute or we can't change directory. As a consequence, this aborts if\n// either of those fail rather than propagating any error.\ninline auto SetWorkingDirForBazelRun(std::filesystem::path exe_path = {})\n    -> std::filesystem::path {\n  char* build_working_dir = getenv(\"BUILD_WORKING_DIRECTORY\");\n  if (build_working_dir == nullptr) {\n    return exe_path;\n  }\n\n  // Adjust `exe_path` before changing directory.\n  if (!exe_path.empty()) {\n    std::error_code err;\n    exe_path = std::filesystem::absolute(exe_path, err);\n    CARBON_CHECK(!err, \"Unable to make an absolute path for `{0}`: {1}\",\n                 exe_path, err.message());\n  }\n\n  auto chdir_result = Filesystem::Cwd().Chdir(build_working_dir);\n  CARBON_CHECK(chdir_result.ok(),\n               \"Unable to change working directory to `{0}`: {1}\",\n               build_working_dir, chdir_result.error());\n\n  return exe_path;\n}\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_BAZEL_WORKING_DIR_H_\n"
  },
  {
    "path": "common/build_data.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/build_data.h\"\n\nnamespace Carbon::BuildData {\n\nconst llvm::StringRef Platform = Internal::platform;\nconst bool BuildCoverageEnabled = Internal::build_coverage_enabled;\nconst llvm::StringRef TargetName = Internal::target_name;\nconst llvm::StringRef BuildTarget = Internal::build_target;\n\n}  // namespace Carbon::BuildData\n"
  },
  {
    "path": "common/build_data.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_BUILD_DATA_H_\n#define CARBON_COMMON_BUILD_DATA_H_\n\n#include \"common/build_data_linkstamp.h\"\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon::BuildData {\n\n// Build information for a binary, from bazel. Stamped values come from:\n// https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/rules/cpp/CppLinkstampCompileHelper.java\n\n// NOLINTBEGIN(readability-identifier-naming): We want to use constant-style\n// names for the public variables, but cannot use constexpr.\n\n// The platform, per https://bazel.build/extending/platforms.\nextern const llvm::StringRef Platform;\n\n// Whether coverage is enabled.\nextern const bool BuildCoverageEnabled;\n\n// The binary target, such as `//common:build_data_test`.\nextern const llvm::StringRef TargetName;\n\n// The path to the build target, such as\n// `bazel-out/k8-fastbuild/bin/common/build_data_test`.\nextern const llvm::StringRef BuildTarget;\n\n// NOLINTEND(readability-identifier-naming)\n\n}  // namespace Carbon::BuildData\n\n#endif  // CARBON_COMMON_BUILD_DATA_H_\n"
  },
  {
    "path": "common/build_data_linkstamp.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/build_data_linkstamp.h\"\n\nnamespace Carbon::BuildData::Internal {\n\nconst char platform[] = GPLATFORM;\nconst bool build_coverage_enabled = BUILD_COVERAGE_ENABLED;\nconst char target_name[] = G3_TARGET_NAME;\nconst char build_target[] = G3_BUILD_TARGET;\n\n}  // namespace Carbon::BuildData::Internal\n"
  },
  {
    "path": "common/build_data_linkstamp.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_BUILD_DATA_LINKSTAMP_H_\n#define CARBON_COMMON_BUILD_DATA_LINKSTAMP_H_\n\nnamespace Carbon::BuildData::Internal {\n\n// See build_data.h; the list of names here should match.\n//\n// Bazel will build dependencies on the `:build_data` library (which exposes\n// `build_data_linkstamp.h`) throughout the build process, but\n// `build_data_linkstamp.cpp` is compiled and linked per-binary -- essentially a\n// separate library. In essence, `build_data_linkstamp.h` is exposing values\n// that are assigned later (this has consequences like preventing `constexpr`\n// use).\n//\n// Also, when build_data_linkstamp.cpp is compiled, this doesn't receive deps,\n// so we can't use things like `llvm::StringRef` here. It should ideally be\n// purely hermetic -- not even using STL for `string_view`. As a result, we use\n// `build_data.h` as an intermediary to do a `StringRef` wrap.\nextern const char platform[];\nextern const bool build_coverage_enabled;\nextern const char target_name[];\nextern const char build_target[];\n\n}  // namespace Carbon::BuildData::Internal\n\n#endif  // CARBON_COMMON_BUILD_DATA_LINKSTAMP_H_\n"
  },
  {
    "path": "common/build_data_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/build_data.h\"\n\n#include <gmock/gmock.h>\n\n#include \"common/ostream.h\"\n\nnamespace Carbon {\nnamespace {\n\nusing ::testing::EndsWith;\nusing ::testing::HasSubstr;\n\nTEST(BuildDataTest, Values) {\n  EXPECT_FALSE(BuildData::Platform.empty());\n  // Can't really test BuildCoverageEnabled.\n\n  // This doesn't require `//`, for a bit of incremental robustness.\n  EXPECT_THAT(BuildData::TargetName, EndsWith(\"/common:build_data_test\"));\n\n  // This doesn't examine the path, for platform robustness (e.g. `.exe`).\n  EXPECT_THAT(BuildData::BuildTarget, HasSubstr(\"build_data_test\"));\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/check.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_CHECK_H_\n#define CARBON_COMMON_CHECK_H_\n\n#include \"common/check_internal.h\"\n\nnamespace Carbon {\n\n// Checks the given condition, and if it's false, prints a stack, streams the\n// error message, then exits. This should be used for unexpected errors, such as\n// a bug in the application.\n//\n// For example:\n//   CARBON_CHECK(is_valid, \"Data is not valid!\");\n//\n// The condition must be parenthesized if it contains top-level commas, for\n// example in a template argument list:\n//   CARBON_CHECK((inst.IsOneOf<Call, TupleLiteral>()),\n//                \"Unexpected inst {0}\", inst);\n#define CARBON_CHECK(condition, ...)         \\\n  CARBON_INTERNAL_CHECK_CONDITION(condition) \\\n  ? (void)0 : CARBON_INTERNAL_CHECK(condition __VA_OPT__(, ) __VA_ARGS__)\n\n// DCHECK calls CHECK in debug mode, and does nothing otherwise.\n#ifndef NDEBUG\n#define CARBON_DCHECK(condition, ...) \\\n  CARBON_CHECK(condition __VA_OPT__(, ) __VA_ARGS__)\n#else\n// When in a debug build we want to preserve as much as we can of how the\n// parameters are used, other than making them be trivially in dead code and\n// eliminated by the optimizer. As a consequence we preserve the condition but\n// prefix it with a short-circuit operator, and we still emit the (dead) call to\n// the check implementation. But we use a special implementation that reduces\n// the compile time cost.\n#define CARBON_DCHECK(condition, ...)                  \\\n  (true || CARBON_INTERNAL_CHECK_CONDITION(condition)) \\\n      ? (void)0                                        \\\n      : CARBON_INTERNAL_DEAD_DCHECK(condition __VA_OPT__(, ) __VA_ARGS__)\n#endif\n\n// This is similar to CHECK, but is unconditional. Writing\n// `CARBON_FATAL(\"message\")` is clearer than `CARBON_CHECK(false, \"message\")\n// because it avoids confusion about control flow.\n//\n// For example:\n//   CARBON_FATAL(\"Unreachable!\");\n#define CARBON_FATAL(...) CARBON_INTERNAL_FATAL(__VA_ARGS__)\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_CHECK_H_\n"
  },
  {
    "path": "common/check_internal.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/check_internal.h\"\n\n#include <cstdlib>\n#include <string>\n\n#include \"common/ostream.h\"\n#include \"llvm/Support/Signals.h\"\n\nnamespace Carbon::Internal {\n\nauto CheckFailImpl(const char* kind, const char* file, int line,\n                   const char* condition_str, llvm::StringRef extra_message)\n    -> void {\n  // Render the final check string here.\n  std::string message = llvm::formatv(\n      \"{0} failure at {1}:{2}{3}{4}{5}{6}\\n\", kind, file, line,\n      llvm::StringRef(condition_str).empty() ? \"\" : \": \", condition_str,\n      extra_message.empty() ? \"\" : \": \", extra_message);\n\n  // This macro is defined by `--config=non-fatal-checks`.\n#ifdef CARBON_NON_FATAL_CHECKS\n#ifdef NDEBUG\n#error \"--config=non-fatal-checks is incompatible with -c opt\"\n#endif\n  // TODO: It'd be nice to print the LLVM PrettyStackTrace, but LLVM doesn't\n  // expose functionality to do so.\n  llvm::sys::PrintStackTrace(llvm::errs());\n\n  llvm::errs() << message;\n#else\n  // Register another signal handler to print the message. This is because we\n  // want it at the bottom of output, after LLVM's builtin stack output, rather\n  // than the top.\n  llvm::sys::AddSignalHandler(\n      [](void* str) { llvm::errs() << reinterpret_cast<char*>(str); },\n      const_cast<char*>(message.c_str()));\n\n  // It's useful to exit the program with `std::abort()` for integration with\n  // debuggers and other tools. We also assume LLVM's exit handling is\n  // installed, which will stack trace on `std::abort()`.\n  std::abort();\n#endif\n}\n\n}  // namespace Carbon::Internal\n"
  },
  {
    "path": "common/check_internal.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_CHECK_INTERNAL_H_\n#define CARBON_COMMON_CHECK_INTERNAL_H_\n\n#include \"common/template_string.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n\nnamespace Carbon::Internal {\n\n// Evaluates a condition in a CHECK. This diagnoses if the condition evaluates\n// to the constant `true` or `false`.\n[[clang::always_inline]] constexpr bool\n// Trailing GNU function attributes are incompatible with trailing return types.\n// Filed as https://github.com/llvm/llvm-project/issues/118697\n// NOLINTNEXTLINE(modernize-use-trailing-return-type)\nCheckCondition(bool condition)\n    __attribute__((diagnose_if(condition,\n                               \"CHECK condition is always true; replace with \"\n                               \"static_assert if this is intended\",\n                               \"error\")))\n    __attribute__((diagnose_if(!condition,\n                               \"CHECK condition is always false; replace with \"\n                               \"CARBON_FATAL if this is intended\",\n                               \"error\"))) {\n  return condition;\n}\n\n// Implements the check failure message printing.\n//\n// This is out-of-line and will arrange to stop the program, print any debugging\n// information and this string. In `!NDEBUG` mode (`dbg` and `fastbuild`), check\n// failures can be made non-fatal by a build flag, so this is not `[[noreturn]]`\n// in that case.\n//\n// This API uses `const char*` C string arguments rather than `llvm::StringRef`\n// because we know that these are available as C strings and passing them that\n// way lets the code size of calling it be smaller: it only needs to materialize\n// a single pointer argument for each. The runtime cost of re-computing the size\n// should be minimal. The extra message however might not be compile-time\n// guaranteed to be a C string so we use a normal `StringRef` there.\n#ifdef NDEBUG\n[[noreturn]]\n#endif\nauto CheckFailImpl(const char* kind, const char* file, int line,\n                   const char* condition_str, llvm::StringRef extra_message)\n    -> void;\n\n// Allow converting format values; the default behaviour is to just pass them\n// through.\ntemplate <typename T>\nauto ConvertFormatValue(T&& t) -> T&& {\n  return std::forward<T>(t);\n}\n\n// Convert enums to larger integers so that byte-sized enums are not confused\n// with being chars and printed as invalid (or nul-terminating) characters.\n// Scoped enums are explicitly converted to integers so they can be printed\n// without the user writing a cast.\ntemplate <typename T>\n  requires(std::is_enum_v<std::remove_reference_t<T>>)\nauto ConvertFormatValue(T&& t) -> auto {\n  if constexpr (std::is_signed_v<\n                    std::underlying_type_t<std::remove_reference_t<T>>>) {\n    return static_cast<int64_t>(t);\n  } else {\n    return static_cast<uint64_t>(t);\n  }\n}\n\n// Prints a check failure, including rendering any user-provided message using\n// a format string.\n//\n// Most of the parameters are passed as compile-time template strings to avoid\n// runtime cost of parameter setup in optimized builds. Each of these are passed\n// along to the underlying implementation to include in the final printed\n// message.\n//\n// Any user-provided format string and values are directly passed to\n// `llvm::formatv` which handles all of the formatting of output.\ntemplate <TemplateString Kind, TemplateString File, int Line,\n          TemplateString ConditionStr, TemplateString FormatStr, typename... Ts>\n#ifdef NDEBUG\n[[noreturn]]\n#endif\n[[gnu::cold, clang::noinline]] auto CheckFail(Ts&&... values) -> void {\n  if constexpr (llvm::StringRef(FormatStr).empty()) {\n    // Skip the format string rendering if empty. Note that we don't skip it\n    // even if there are no values as we want to have consistent handling of\n    // `{}`s in the format string. This case is about when there is no message\n    // at all, just the condition.\n    CheckFailImpl(Kind.c_str(), File.c_str(), Line, ConditionStr.c_str(), \"\");\n  } else {\n    CheckFailImpl(Kind.c_str(), File.c_str(), Line, ConditionStr.c_str(),\n                  llvm::formatv(FormatStr.c_str(),\n                                ConvertFormatValue(std::forward<Ts>(values))...)\n                      .str());\n  }\n}\n\n}  // namespace Carbon::Internal\n\n// Evaluates the condition of a CHECK as a boolean value.\n//\n// This performs a contextual conversion to bool, diagnoses if the condition is\n// always true or always false, and returns its value.\n#define CARBON_INTERNAL_CHECK_CONDITION(cond) \\\n  (Carbon::Internal::CheckCondition(true && (cond)))\n\n// Implements check messages without any formatted values.\n//\n// Passes each of the provided components of the message to the template\n// parameters of the check failure printing function above, including an empty\n// string for the format string. Because there are multiple template arguments,\n// the entire call is wrapped in parentheses.\n#define CARBON_INTERNAL_CHECK_IMPL(kind, file, line, condition_str) \\\n  (Carbon::Internal::CheckFail<kind, file, line, condition_str, \"\">())\n\n// Implements check messages with a format string and potentially formatted\n// values.\n//\n// Each of the main components is passed as a template arguments, and then any\n// formatted values are passed as arguments. Because there are multiple template\n// arguments, the entire call is wrapped in parentheses.\n#define CARBON_INTERNAL_CHECK_IMPL_FORMAT(kind, file, line, condition_str,   \\\n                                          format_str, ...)                   \\\n  (Carbon::Internal::CheckFail<kind, file, line, condition_str, format_str>( \\\n      __VA_ARGS__))\n\n// Implements the failure of a check.\n//\n// Collects all the metadata about the failure to be printed, such as source\n// location and stringified condition, and passes those, any format string and\n// formatted arguments to the correct implementation macro above.\n#define CARBON_INTERNAL_CHECK(condition, ...)      \\\n  CARBON_INTERNAL_CHECK_IMPL##__VA_OPT__(_FORMAT)( \\\n      \"CHECK\", __FILE__, __LINE__, #condition __VA_OPT__(, ) __VA_ARGS__)\n\n// Implements the fatal macro.\n//\n// Similar to the check failure macro, but tags the message as a fatal one and\n// leaves the stringified condition empty.\n#define CARBON_INTERNAL_FATAL(...)                                  \\\n  (CARBON_INTERNAL_CHECK_IMPL##__VA_OPT__(_FORMAT)(                 \\\n       \"FATAL\", __FILE__, __LINE__, \"\" __VA_OPT__(, ) __VA_ARGS__), \\\n   CARBON_INTERNAL_FATAL_NORETURN_SUFFIX())\n\n#ifdef NDEBUG\n// For `DCHECK` in optimized builds we have a dead check that we want to\n// potentially \"use\" arguments, but otherwise have the minimal overhead. We\n// avoid forming interesting format strings here so that we don't have to\n// repeatedly instantiate the `Check` function above. This format string would\n// be an error if actually used.\n#define CARBON_INTERNAL_DEAD_DCHECK(condition, ...) \\\n  CARBON_INTERNAL_DEAD_DCHECK_IMPL##__VA_OPT__(_FORMAT)(__VA_ARGS__)\n\n#define CARBON_INTERNAL_DEAD_DCHECK_IMPL() \\\n  Carbon::Internal::CheckFail<\"\", \"\", 0, \"\", \"\">()\n\n#define CARBON_INTERNAL_DEAD_DCHECK_IMPL_FORMAT(format_str, ...) \\\n  Carbon::Internal::CheckFail<\"\", \"\", 0, \"\", \"\">(__VA_ARGS__)\n\n// The CheckFail function itself is noreturn in NDEBUG.\n#define CARBON_INTERNAL_FATAL_NORETURN_SUFFIX() void()\n#else\n#define CARBON_INTERNAL_FATAL_NORETURN_SUFFIX() std::abort()\n#endif\n\n#endif  // CARBON_COMMON_CHECK_INTERNAL_H_\n"
  },
  {
    "path": "common/check_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/check.h\"\n\n#include <gtest/gtest.h>\n\n#include <string>\n\nnamespace Carbon {\nnamespace {\n\n// Non-constexpr functions that always return true and false, to bypass constant\n// condition checking.\nauto AlwaysTrue() -> bool { return true; }\nauto AlwaysFalse() -> bool { return false; }\n\nTEST(CheckTest, CheckTrue) { CARBON_CHECK(AlwaysTrue()); }\n\nTEST(CheckTest, CheckFalse) {\n  ASSERT_DEATH(\n      { CARBON_CHECK(AlwaysFalse()); },\n      R\"(\nCHECK failure at common/check_test.cpp:\\d+: AlwaysFalse\\(\\)\n)\");\n}\n\nTEST(CheckTest, CheckFalseHasStackDump) {\n  ASSERT_DEATH({ CARBON_CHECK(AlwaysFalse()); }, \"\\nStack dump:\\n\");\n}\n\nTEST(CheckTest, CheckTrueCallbackNotUsed) {\n  bool called = false;\n  auto callback = [&]() {\n    called = true;\n    return \"called\";\n  };\n  CARBON_CHECK(AlwaysTrue(), \"{0}\", callback());\n  EXPECT_FALSE(called);\n}\n\nTEST(CheckTest, CheckFalseMessage) {\n  ASSERT_DEATH(\n      { CARBON_CHECK(AlwaysFalse(), \"msg\"); },\n      R\"(\nCHECK failure at common/check_test.cpp:.+: AlwaysFalse\\(\\): msg\n)\");\n}\n\nTEST(CheckTest, CheckFalseFormattedMessage) {\n  const char msg[] = \"msg\";\n  std::string str = \"str\";\n  int i = 1;\n  ASSERT_DEATH(\n      { CARBON_CHECK(AlwaysFalse(), \"{0} {1} {2} {3}\", msg, str, i, 0); },\n      R\"(\nCHECK failure at common/check_test.cpp:.+: AlwaysFalse\\(\\): msg str 1 0\n)\");\n}\n\nTEST(CheckTest, CheckOutputForms) {\n  const char msg[] = \"msg\";\n  std::string str = \"str\";\n  int i = 1;\n  CARBON_CHECK(AlwaysTrue(), \"{0} {1} {2} {3}\", msg, str, i, 0);\n}\n\nTEST(CheckTest, Fatal) {\n  ASSERT_DEATH(\n      { CARBON_FATAL(\"msg\"); },\n      \"\\nFATAL failure at common/check_test.cpp:.+: msg\\n\");\n}\n\nTEST(CheckTest, FatalHasStackDump) {\n  ASSERT_DEATH({ CARBON_FATAL(\"msg\"); }, \"\\nStack dump:\\n\");\n}\n\nauto FatalNoReturnRequired() -> int { CARBON_FATAL(\"msg\"); }\n\nTEST(ErrorTest, FatalNoReturnRequired) {\n  ASSERT_DEATH(\n      { FatalNoReturnRequired(); },\n      \"\\nFATAL failure at common/check_test.cpp:.+: msg\\n\");\n}\n\n// Detects whether `CARBON_CHECK(F())` compiles.\ntemplate <auto F>\nconcept CheckCompilesWithCondition = requires { CARBON_CHECK(F()); };\n\nTEST(CheckTest, CheckConstantCondition) {\n  EXPECT_TRUE(CheckCompilesWithCondition<[] { return AlwaysTrue(); }>);\n  EXPECT_TRUE(CheckCompilesWithCondition<[] { return AlwaysFalse(); }>);\n  EXPECT_FALSE(CheckCompilesWithCondition<[] { return true; }>);\n  EXPECT_FALSE(CheckCompilesWithCondition<[] { return false; }>);\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/command_line.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/command_line.h\"\n\n#include <array>\n#include <memory>\n#include <optional>\n#include <string>\n#include <utility>\n\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/ADT/DenseMap.h\"\n#include \"llvm/ADT/PointerIntPair.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n\n// Recursion is used for subcommands. This should be okay since recursion is\n// limited by command line architecture.\n// NOLINTBEGIN(misc-no-recursion)\n\nnamespace Carbon::CommandLine {\n\nauto operator<<(llvm::raw_ostream& output, ParseResult result)\n    -> llvm::raw_ostream& {\n  switch (result) {\n    case ParseResult::MetaSuccess:\n      return output << \"MetaSuccess\";\n    case ParseResult::Success:\n      return output << \"Success\";\n  }\n  CARBON_FATAL(\"Corrupt parse result!\");\n}\n\nauto operator<<(llvm::raw_ostream& output, ArgKind kind) -> llvm::raw_ostream& {\n  switch (kind) {\n    case ArgKind::Flag:\n      return output << \"Boolean\";\n    case ArgKind::Integer:\n      return output << \"Integer\";\n    case ArgKind::String:\n      return output << \"String\";\n    case ArgKind::OneOf:\n      return output << \"OneOf\";\n    case ArgKind::MetaActionOnly:\n      return output << \"MetaActionOnly\";\n    case ArgKind::Invalid:\n      return output << \"Invalid\";\n  }\n  CARBON_FATAL(\"Corrupt argument kind!\");\n}\n\nauto operator<<(llvm::raw_ostream& output, CommandKind kind)\n    -> llvm::raw_ostream& {\n  switch (kind) {\n    case CommandKind::Invalid:\n      return output << \"Invalid\";\n    case CommandKind::RequiresSubcommand:\n      return output << \"RequiresSubcommand\";\n    case CommandKind::Action:\n      return output << \"Action\";\n    case CommandKind::MetaAction:\n      return output << \"MetaAction\";\n  }\n  CARBON_FATAL(\"Corrupt command kind!\");\n}\n\ntemplate <typename T, typename ToPrintable>\nstatic auto PrintListOfAlternatives(llvm::raw_ostream& output,\n                                    llvm::ArrayRef<T> alternatives,\n                                    ToPrintable to_printable) -> void {\n  for (const auto& alternative : alternatives.drop_back()) {\n    output << \"`\" << to_printable(alternative)\n           << (alternatives.size() > 2 ? \"`, \" : \"` \");\n  }\n  if (alternatives.size() > 1) {\n    output << \"or \";\n  }\n  output << \"`\" << to_printable(alternatives.back()) << \"`\";\n}\n\nArg::Arg(ArgInfo info) : info(info) {}\n\nArg::~Arg() {\n  switch (kind) {\n    case Kind::Flag:\n    case Kind::Integer:\n    case Kind::String:\n    case Kind::MetaActionOnly:\n    case Kind::Invalid:\n      // Nothing to do!\n      break;\n    case Kind::OneOf:\n      value_strings.~decltype(value_strings)();\n      value_action.~ValueActionT();\n      if (has_default) {\n        default_action.~DefaultActionT();\n      }\n      break;\n  }\n}\n\nCommand::Command(CommandInfo info, Command* parent)\n    : info(info), parent(parent) {}\n\nclass MetaPrinter {\n public:\n  // `out` must not be null.\n  explicit MetaPrinter(llvm::raw_ostream* out) : out_(out) {}\n\n  // Registers this meta printer with a command through the provided builder.\n  //\n  // This adds meta subcommands or options to print both help and version\n  // information for the command.\n  auto RegisterWithCommand(const Command& command, CommandBuilder& builder)\n      -> void;\n\n  auto PrintHelp(const Command& command) const -> void;\n  auto PrintHelpForSubcommandName(const Command& command,\n                                  llvm::StringRef subcommand_name) const\n      -> void;\n  auto PrintVersion(const Command& command) const -> void;\n  auto PrintSubcommands(const Command& command) const -> void;\n\n private:\n  // The indent is calibrated to allow a short and long option after a two\n  // character indent on the prior line to be visually recognized as separate\n  // from the hanging indent.\n  //\n  // Visual guide:                               |  -x, --extract\n  //                                             |          Hanging indented.\n  static constexpr llvm::StringRef BlockIndent = \"          \";\n\n  // Width limit for parent command options in usage rendering.\n  static constexpr int MaxParentOptionUsageWidth = 8;\n\n  // Width limit for the leaf command options in usage rendering.\n  static constexpr int MaxLeafOptionUsageWidth = 16;\n\n  static constexpr CommandInfo HelpCommandInfo = {\n      .name = \"help\",\n      .help = R\"\"\"(\nPrints help information for the command, including a description, command line\nusage, and details of each subcommand and option that can be provided.\n)\"\"\",\n      .help_short = R\"\"\"(\nPrints help information.\n)\"\"\",\n  };\n  static constexpr ArgInfo HelpArgInfo = {\n      .name = \"help\",\n      .value_name = \"(full|short)\",\n      .help = R\"\"\"(\nPrints help information for the command, including a description, command line\nusage, and details of each option that can be provided.\n)\"\"\",\n      .help_short = HelpCommandInfo.help_short,\n  };\n\n  // Provide a customized description for help on a subcommand to avoid\n  // confusion with the top-level help.\n  static constexpr CommandInfo SubHelpCommandInfo = {\n      .name = \"help\",\n      .help = R\"\"\"(\nPrints help information for the subcommand, including a description, command\nline usage, and details of each further subcommand and option that can be\nprovided.\n)\"\"\",\n      .help_short = R\"\"\"(\nPrints subcommand help information.\n)\"\"\",\n  };\n  static constexpr ArgInfo SubHelpArgInfo = {\n      .name = \"help\",\n      .value_name = \"(full|short)\",\n      .help = R\"\"\"(\nPrints help information for the subcommand, including a description, command\nline usage, and details of each option that can be provided.\n)\"\"\",\n      .help_short = SubHelpCommandInfo.help_short,\n  };\n\n  static constexpr ArgInfo HelpSubcommandArgInfo = {\n      .name = \"subcommand\",\n      .help = R\"\"\"(\nWhich subcommand to print help information for.\n)\"\"\",\n  };\n\n  static constexpr CommandInfo VersionCommandInfo = {\n      .name = \"version\",\n      .help = R\"\"\"(\nPrints the version of this command.\n)\"\"\",\n  };\n  static constexpr ArgInfo VersionArgInfo = {\n      .name = \"version\",\n      .help = VersionCommandInfo.help,\n  };\n\n  // A general helper for rendering a text block.\n  auto PrintTextBlock(llvm::StringRef indent, llvm::StringRef text) const\n      -> void;\n\n  // Helpers for version and build information printing.\n  auto PrintRawVersion(const Command& command, llvm::StringRef indent) const\n      -> void;\n  auto PrintRawBuildInfo(const Command& command, llvm::StringRef indent) const\n      -> void;\n\n  // Helpers for printing components of help and usage output for arguments,\n  // including options and positional arguments.\n  auto PrintArgValueUsage(const Arg& arg) const -> void;\n  auto PrintOptionUsage(const Arg& option) const -> void;\n  auto PrintOptionShortName(const Arg& arg) const -> void;\n  auto PrintArgShortValues(const Arg& arg) const -> void;\n  auto PrintArgLongValues(const Arg& arg, llvm::StringRef indent) const -> void;\n  auto PrintArgHelp(const Arg& arg, llvm::StringRef indent) const -> void;\n\n  // Helpers for printing command usage summaries.\n  auto PrintRawUsageCommandAndOptions(\n      const Command& command,\n      int max_option_width = MaxLeafOptionUsageWidth) const -> void;\n  auto PrintRawUsage(const Command& command, llvm::StringRef indent) const\n      -> void;\n  auto PrintUsage(const Command& command) const -> void;\n\n  // Helpers to print various sections of `PrintHelp` that only occur within\n  // that output.\n  auto PrintHelpSubcommands(const Command& command) const -> void;\n  auto PrintHelpPositionalArgs(const Command& command) const -> void;\n  auto PrintHelpOptions(const Command& command) const -> void;\n\n  llvm::raw_ostream* out_;\n\n  // A flag that may be configured during command line parsing to select between\n  // long and short form help output.\n  bool short_help_ = false;\n\n  // The requested subcommand to print help information for.\n  llvm::StringRef help_subcommand_;\n};\n\nauto MetaPrinter::RegisterWithCommand(const Command& command,\n                                      CommandBuilder& builder) -> void {\n  bool is_subcommand = command.parent;\n  bool has_subcommands = !command.subcommands.empty();\n\n  // If this command has subcommands, we prefer that model for access meta\n  // actions, but still silently support using the flags. But we never want to\n  // *add* subcommands if they aren't already being used.\n  if (has_subcommands) {\n    builder.AddSubcommand(\n        is_subcommand ? SubHelpCommandInfo : HelpCommandInfo,\n        [&](CommandBuilder& sub_b) {\n          sub_b.AddStringPositionalArg(HelpSubcommandArgInfo, [&](auto& arg_b) {\n            arg_b.Set(&help_subcommand_);\n          });\n          sub_b.Meta([this, &command]() {\n            if (help_subcommand_.empty()) {\n              PrintHelp(command);\n            } else {\n              PrintHelpForSubcommandName(command, help_subcommand_);\n            }\n          });\n        });\n\n    // Only add version printing support if there is a version string\n    // configured for this command.\n    if (!command.info.version.empty()) {\n      builder.AddSubcommand(VersionCommandInfo, [&](CommandBuilder& sub_b) {\n        sub_b.Meta([this, &command]() { PrintVersion(command); });\n      });\n    }\n  }\n  builder.AddOneOfOption(\n      is_subcommand ? SubHelpArgInfo : HelpArgInfo, [&](auto& arg_b) {\n        arg_b.HelpHidden(has_subcommands);\n        arg_b.SetOneOf(\n            {\n                arg_b.OneOfValue(\"full\", false).Default(true),\n                arg_b.OneOfValue(\"short\", true),\n            },\n            &short_help_);\n        arg_b.MetaAction([this, &command]() { PrintHelp(command); });\n      });\n\n  // Only add version printing support if there is a version string configured\n  // for this command.\n  if (!command.info.version.empty()) {\n    builder.AddMetaActionOption(VersionArgInfo, [&](auto& arg_b) {\n      arg_b.HelpHidden(has_subcommands);\n      arg_b.MetaAction([this, &command]() { PrintVersion(command); });\n    });\n  }\n}\n\nauto MetaPrinter::PrintHelp(const Command& command) const -> void {\n  // TODO: begin using the short setting to customize the output.\n  (void)short_help_;\n\n  const CommandInfo& info = command.info;\n  if (!info.version.empty()) {\n    // We use the version string as a header for the command help when present.\n    PrintRawVersion(command, /*indent=*/\"\");\n    *out_ << \"\\n\";\n  }\n  if (!command.info.help.empty()) {\n    PrintTextBlock(\"\", info.help);\n    *out_ << \"\\n\";\n  }\n  if (!info.build_info.empty()) {\n    *out_ << \"Build info:\\n\";\n    PrintRawBuildInfo(command, /*indent=*/\"  \");\n    *out_ << \"\\n\";\n  }\n\n  PrintUsage(command);\n  PrintHelpSubcommands(command);\n  PrintHelpPositionalArgs(command);\n  PrintHelpOptions(command);\n\n  if (!info.help_epilogue.empty()) {\n    *out_ << \"\\n\";\n    PrintTextBlock(\"\", info.help_epilogue);\n  }\n\n  // End with a blank line for the long help to make it easier to separate from\n  // anything that follows in the shell.\n  *out_ << \"\\n\";\n}\n\nauto MetaPrinter::PrintHelpForSubcommandName(\n    const Command& command, llvm::StringRef subcommand_name) const -> void {\n  for (const auto& subcommand : command.subcommands) {\n    if (subcommand->info.name == subcommand_name) {\n      PrintHelp(*subcommand);\n      return;\n    }\n  }\n\n  // TODO: This should really be connected up so that parsing can return an\n  // Error instead of ParseResult::MetaSuccess in this case.\n  *out_ << \"error: could not find a subcommand named '\" << subcommand_name\n        << \"'\\n\";\n}\n\nauto MetaPrinter::PrintVersion(const Command& command) const -> void {\n  CARBON_CHECK(\n      !command.info.version.empty(),\n      \"Printing should not be enabled without a version string configured.\");\n  PrintRawVersion(command, /*indent=*/\"\");\n  if (!command.info.build_info.empty()) {\n    *out_ << \"\\n\";\n    // If there is build info to print, we also render that without any indent.\n    PrintRawBuildInfo(command, /*indent=*/\"\");\n  }\n}\n\nauto MetaPrinter::PrintSubcommands(const Command& command) const -> void {\n  PrintListOfAlternatives<std::unique_ptr<Command>>(\n      *out_, command.subcommands,\n      [](const std::unique_ptr<Command>& subcommand) {\n        return subcommand->info.name;\n      });\n}\n\nauto MetaPrinter::PrintRawVersion(const Command& command,\n                                  llvm::StringRef indent) const -> void {\n  // Newlines are trimmed from the version string an a closing newline added but\n  // no other formatting is performed.\n  *out_ << indent << command.info.version.trim('\\n') << \"\\n\";\n}\nauto MetaPrinter::PrintRawBuildInfo(const Command& command,\n                                    llvm::StringRef indent) const -> void {\n  // Print the build info line-by-line without any wrapping in case it\n  // contains line-oriented formatted text, but drop leading and trailing blank\n  // lines.\n  llvm::SmallVector<llvm::StringRef, 128> lines;\n  command.info.build_info.trim('\\n').split(lines, \"\\n\");\n  for (auto line : lines) {\n    *out_ << indent << line << \"\\n\";\n  }\n}\n\nauto MetaPrinter::PrintTextBlock(llvm::StringRef indent,\n                                 llvm::StringRef text) const -> void {\n  // Strip leading and trailing newlines to make it easy to use multiline raw\n  // string literals that will naturally have those.\n  text = text.trim('\\n');\n  // For empty text, print nothing at all. The caller formatting will work to\n  // handle this gracefully.\n  if (text.empty()) {\n    return;\n  }\n\n  // Remove line breaks from the text that would typically be removed when\n  // rendering it as Markdown. The goal is to preserve:\n  //\n  // - Blank lines as paragraph separators.\n  // - Line breaks after list items or other structural components in Markdown.\n  // - Fenced regions exactly as they appear.\n  //\n  // And within paragraphs (including those nested in lists), reflow the\n  // paragraph intelligently to the column width. There are TODOs below about\n  // both lists and reflowing.\n  llvm::SmallVector<llvm::StringRef, 128> input_lines;\n  text.split(input_lines, \"\\n\");\n\n  for (int i = 0, size = input_lines.size(); i < size;) {\n    if (input_lines[i].empty()) {\n      // Blank lines are preserved.\n      *out_ << \"\\n\";\n      ++i;\n      continue;\n    }\n\n    if (input_lines[i].starts_with(\"```\")) {\n      // Fenced regions are preserved verbatim.\n      llvm::StringRef fence =\n          input_lines[i].slice(0, input_lines[i].find_first_not_of(\"`\"));\n      do {\n        *out_ << indent << input_lines[i] << \"\\n\";\n        ++i;\n      } while (i < size && !input_lines[i].starts_with(fence));\n      if (i >= size) {\n        // Don't error on malformed text blocks, just print what we've got.\n        break;\n      }\n      // Including the close of the fence.\n      *out_ << indent << input_lines[i] << \"\\n\";\n      ++i;\n      continue;\n    }\n\n    if (input_lines[i].starts_with(\"    \")) {\n      // Indented code blocks ar preserved verbatim, but we don't support tabs\n      // in the indent for simplicity.\n      do {\n        *out_ << indent << input_lines[i] << \"\\n\";\n        ++i;\n      } while (i < size && input_lines[i].starts_with(\"    \"));\n      continue;\n    }\n\n    // TODO: Detect other Markdown structures, especially lists and tables.\n\n    // Otherwise, collect all of the lines until the end or the next blank line\n    // as a block of text.\n    //\n    // TODO: This is where we should re-flow.\n    llvm::StringRef space = indent;\n    do {\n      *out_ << space << input_lines[i].trim();\n      space = \" \";\n      ++i;\n    } while (i < size && !input_lines[i].empty());\n    *out_ << \"\\n\";\n  }\n}\n\nauto MetaPrinter::PrintArgValueUsage(const Arg& arg) const -> void {\n  if (!arg.info.value_name.empty()) {\n    *out_ << arg.info.value_name;\n    return;\n  }\n  if (arg.kind == Arg::Kind::OneOf) {\n    *out_ << \"(\";\n    llvm::ListSeparator sep(\"|\");\n    for (llvm::StringRef value_string : arg.value_strings) {\n      *out_ << sep << value_string;\n    }\n    *out_ << \")\";\n    return;\n  }\n  *out_ << \"...\";\n}\n\nauto MetaPrinter::PrintOptionUsage(const Arg& option) const -> void {\n  if (option.kind == Arg::Kind::Flag) {\n    *out_ << \"--\" << (option.default_flag ? \"no-\" : \"\") << option.info.name;\n    return;\n  }\n  *out_ << \"--\" << option.info.name;\n  if (option.kind != Arg::Kind::MetaActionOnly) {\n    *out_ << (option.has_default ? \"[\" : \"\") << \"=\";\n    PrintArgValueUsage(option);\n    if (option.has_default) {\n      *out_ << \"]\";\n    }\n  }\n}\n\nauto MetaPrinter::PrintOptionShortName(const Arg& arg) const -> void {\n  CARBON_CHECK(!arg.info.short_name.empty(), \"No short name to use.\");\n  *out_ << \"-\" << arg.info.short_name;\n}\n\nauto MetaPrinter::PrintArgShortValues(const Arg& arg) const -> void {\n  CARBON_CHECK(\n      arg.kind == Arg::Kind::OneOf,\n      \"Only one-of arguments have interesting value snippets to print.\");\n  llvm::ListSeparator sep;\n  for (llvm::StringRef value_string : arg.value_strings) {\n    *out_ << sep << value_string;\n  }\n}\nauto MetaPrinter::PrintArgLongValues(const Arg& arg,\n                                     llvm::StringRef indent) const -> void {\n  *out_ << indent << \"Possible values:\\n\";\n  // TODO: It would be good to add help text for each value and then print it\n  // here.\n  for (auto [i, value_string] : llvm::enumerate(arg.value_strings)) {\n    *out_ << indent << \"- \" << value_string;\n    if (arg.has_default && static_cast<int>(i) == arg.default_value_index) {\n      *out_ << \" (default)\";\n    }\n    *out_ << \"\\n\";\n  }\n}\n\nauto MetaPrinter::PrintArgHelp(const Arg& arg, llvm::StringRef indent) const\n    -> void {\n  // Print out the main help text.\n  PrintTextBlock(indent, arg.info.help);\n\n  // Then print out any help based on the values.\n  switch (arg.kind) {\n    case Arg::Kind::Integer:\n      if (arg.has_default) {\n        *out_ << \"\\n\";\n        *out_ << indent << \"Default value: \" << arg.default_integer << \"\\n\";\n      }\n      break;\n    case Arg::Kind::String:\n      if (arg.has_default) {\n        *out_ << \"\\n\";\n        *out_ << indent << \"Default value: \" << arg.default_string << \"\\n\";\n      }\n      break;\n    case Arg::Kind::OneOf:\n      *out_ << \"\\n\";\n      PrintArgLongValues(arg, indent);\n      break;\n    case Arg::Kind::Flag:\n    case Arg::Kind::MetaActionOnly:\n      // No value help.\n      break;\n    case Arg::Kind::Invalid:\n      CARBON_FATAL(\"Argument configured without any action or kind!\");\n  }\n}\n\nauto MetaPrinter::PrintRawUsageCommandAndOptions(const Command& command,\n                                                 int max_option_width) const\n    -> void {\n  // Recursively print parent usage first with a compressed width.\n  if (command.parent) {\n    PrintRawUsageCommandAndOptions(*command.parent, MaxParentOptionUsageWidth);\n    *out_ << \" \";\n  }\n\n  *out_ << command.info.name;\n\n  // Buffer the options rendering so we can limit its length.\n  RawStringOstream buffer_out;\n  MetaPrinter buffer_printer(&buffer_out);\n  bool have_short_flags = false;\n  for (const auto& arg : command.options) {\n    if (static_cast<int>(buffer_out.size()) > max_option_width) {\n      break;\n    }\n    // We can summarize positive boolean flags with a short name using a\n    // sequence of short names in a single rendered argument.\n    if (arg->kind == Arg::Kind::Flag && !arg->default_flag &&\n        !arg->info.short_name.empty()) {\n      if (!have_short_flags) {\n        have_short_flags = true;\n        buffer_out << \"-\";\n      }\n      buffer_out << arg->info.short_name;\n    }\n  }\n  llvm::StringRef space = have_short_flags ? \" \" : \"\";\n  for (const auto& option : command.options) {\n    if (static_cast<int>(buffer_out.size()) > max_option_width) {\n      break;\n    }\n    if (option->is_help_hidden || option->meta_action) {\n      // Skip hidden and options with meta actions attached.\n      continue;\n    }\n    if (option->kind == Arg::Kind::Flag && !option->default_flag &&\n        !option->info.short_name.empty()) {\n      // Handled with short names above.\n      continue;\n    }\n    buffer_out << space;\n    buffer_printer.PrintOptionUsage(*option);\n    space = \" \";\n  }\n  if (!buffer_out.empty()) {\n    if (static_cast<int>(buffer_out.size()) <= max_option_width) {\n      *out_ << \" [\" << buffer_out.TakeStr() << \"]\";\n    } else {\n      buffer_out.clear();\n      *out_ << \" [OPTIONS]\";\n    }\n  }\n}\n\nauto MetaPrinter::PrintRawUsage(const Command& command,\n                                llvm::StringRef indent) const -> void {\n  if (!command.info.usage.empty()) {\n    PrintTextBlock(indent, command.info.usage);\n    return;\n  }\n\n  if (command.kind != Command::Kind::RequiresSubcommand) {\n    // We're a valid leaf command, so synthesize a full usage line.\n    *out_ << indent;\n    PrintRawUsageCommandAndOptions(command);\n\n    if (!command.positional_args.empty()) {\n      bool open_optional = false;\n      for (auto [i, arg] : llvm::enumerate(command.positional_args)) {\n        *out_ << \" \";\n        if (i != 0 && command.positional_args[i - 1]->is_append) {\n          *out_ << \"-- \";\n        }\n        if (!arg->is_required && !open_optional) {\n          *out_ << \"[\";\n          open_optional = true;\n        }\n        *out_ << \"<\" << arg->info.name << \">\";\n        if (arg->is_append) {\n          *out_ << \"...\";\n        }\n      }\n      if (open_optional) {\n        *out_ << \"]\";\n      }\n    }\n    *out_ << \"\\n\";\n  }\n\n  // If we have subcommands, also recurse into them so each one can print their\n  // usage lines.\n  for (const auto& subcommand : command.subcommands) {\n    if (subcommand->is_help_hidden ||\n        subcommand->kind == Command::Kind::MetaAction) {\n      continue;\n    }\n    PrintRawUsage(*subcommand, indent);\n  }\n}\n\nauto MetaPrinter::PrintUsage(const Command& command) const -> void {\n  if (!command.parent) {\n    *out_ << \"Usage:\\n\";\n  } else {\n    *out_ << \"Subcommand `\" << command.info.name << \"` usage:\\n\";\n  }\n  PrintRawUsage(command, \"  \");\n}\n\nauto MetaPrinter::PrintHelpSubcommands(const Command& command) const -> void {\n  bool first_subcommand = true;\n  for (const auto& subcommand : command.subcommands) {\n    if (subcommand->is_help_hidden) {\n      continue;\n    }\n    if (first_subcommand) {\n      first_subcommand = false;\n      if (!command.parent) {\n        *out_ << \"\\nSubcommands:\";\n      } else {\n        *out_ << \"\\nSubcommand `\" << command.info.name << \"` subcommands:\";\n      }\n    }\n    *out_ << \"\\n\";\n    *out_ << \"  \" << subcommand->info.name << \"\\n\";\n    PrintTextBlock(BlockIndent, subcommand->info.help);\n  }\n}\n\nauto MetaPrinter::PrintHelpPositionalArgs(const Command& command) const\n    -> void {\n  bool first_positional_arg = true;\n  for (const auto& positional_arg : command.positional_args) {\n    if (positional_arg->is_help_hidden) {\n      continue;\n    }\n    if (first_positional_arg) {\n      first_positional_arg = false;\n      if (!command.parent) {\n        *out_ << \"\\nPositional arguments:\";\n      } else {\n        *out_ << \"\\nSubcommand `\" << command.info.name\n              << \"` positional arguments:\";\n      }\n    }\n    *out_ << \"\\n\";\n    *out_ << \"  \" << positional_arg->info.name << \"\\n\";\n    PrintArgHelp(*positional_arg, BlockIndent);\n  }\n}\n\nauto MetaPrinter::PrintHelpOptions(const Command& command) const -> void {\n  bool first_option = true;\n  for (const auto& option : command.options) {\n    if (option->is_help_hidden) {\n      continue;\n    }\n    if (first_option) {\n      first_option = false;\n      if (!command.parent && command.subcommands.empty()) {\n        // Only one command level.\n        *out_ << \"\\nOptions:\";\n      } else if (!command.parent) {\n        *out_ << \"\\nCommand options:\";\n      } else {\n        *out_ << \"\\nSubcommand `\" << command.info.name << \"` options:\";\n      }\n    }\n    *out_ << \"\\n\";\n    *out_ << \"  \";\n    if (!option->info.short_name.empty()) {\n      PrintOptionShortName(*option);\n      *out_ << \", \";\n    } else {\n      *out_ << \"    \";\n    }\n    PrintOptionUsage(*option);\n    *out_ << \"\\n\";\n    PrintArgHelp(*option, BlockIndent);\n  }\n}\n\nclass Parser {\n public:\n  // `out` must not be null.\n  explicit Parser(llvm::raw_ostream* out, CommandInfo command_info,\n                  llvm::function_ref<auto(CommandBuilder&)->void> build);\n\n  auto Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args)\n      -> ErrorOr<ParseResult>;\n\n private:\n  friend CommandBuilder;\n\n  // For the option and subcommand maps, we use somewhat large small size\n  // buffers (16) as there is no real size pressure on these and its nice to\n  // avoid heap allocation in the small cases.\n  using OptionMapT =\n      llvm::SmallDenseMap<llvm::StringRef, llvm::PointerIntPair<Arg*, 1, bool>,\n                          16>;\n  using SubcommandMapT = llvm::SmallDenseMap<llvm::StringRef, Command*, 16>;\n\n  // This table is sized to be 128 so that it can hold ASCII characters. We\n  // don't need any more than this and using a direct table indexed by the\n  // character's numeric value makes for a convenient map.\n  using ShortOptionTableT = std::array<OptionMapT::mapped_type*, 128>;\n\n  auto PopulateMaps(const Command& command) -> void;\n\n  auto SetOptionDefault(const Arg& option) -> void;\n\n  auto ParseNegatedFlag(const Arg& flag, std::optional<llvm::StringRef> value)\n      -> ErrorOr<Success>;\n  auto ParseFlag(const Arg& flag, std::optional<llvm::StringRef> value)\n      -> ErrorOr<Success>;\n  auto ParseIntegerArgValue(const Arg& arg, llvm::StringRef value)\n      -> ErrorOr<Success>;\n  auto ParseStringArgValue(const Arg& arg, llvm::StringRef value)\n      -> ErrorOr<Success>;\n  auto ParseOneOfArgValue(const Arg& arg, llvm::StringRef value)\n      -> ErrorOr<Success>;\n  auto ParseArg(const Arg& arg, bool short_spelling,\n                std::optional<llvm::StringRef> value, bool negated_name = false)\n      -> ErrorOr<Success>;\n\n  auto SplitValue(llvm::StringRef& unparsed_arg)\n      -> std::optional<llvm::StringRef>;\n  auto ParseLongOption(llvm::StringRef unparsed_arg) -> ErrorOr<Success>;\n  auto ParseShortOptionSeq(llvm::StringRef unparsed_arg) -> ErrorOr<Success>;\n  auto FinalizeParsedOptions() -> ErrorOr<Success>;\n\n  auto ParsePositionalArg(llvm::StringRef unparsed_arg) -> ErrorOr<Success>;\n  auto ParseSubcommand(llvm::StringRef unparsed_arg) -> ErrorOr<Success>;\n\n  auto ParsePositionalSuffix(llvm::ArrayRef<llvm::StringRef> unparsed_args)\n      -> ErrorOr<Success>;\n\n  auto FinalizeParse() -> ErrorOr<ParseResult>;\n\n  // When building a command, it registers arguments and potentially subcommands\n  // that are meta actions to print things to standard out, so we build a meta\n  // printer for that here.\n  MetaPrinter meta_printer_;\n\n  Command root_command_;\n\n  const Command* command_;\n\n  OptionMapT option_map_;\n  ShortOptionTableT short_option_table_;\n  SubcommandMapT subcommand_map_;\n\n  int positional_arg_index_ = 0;\n  bool appending_to_positional_arg_ = false;\n\n  ActionT arg_meta_action_;\n};\n\nauto Parser::PopulateMaps(const Command& command) -> void {\n  option_map_.clear();\n  for (const auto& option : command.options) {\n    option_map_.insert({option->info.name, {option.get(), false}});\n  }\n  short_option_table_.fill(nullptr);\n  for (auto& map_entry : option_map_) {\n    const Arg* option = map_entry.second.getPointer();\n    if (option->info.short_name.empty()) {\n      continue;\n    }\n    CARBON_CHECK(option->info.short_name.size() == 1,\n                 \"Short option names must have exactly one character.\");\n    unsigned char short_char = option->info.short_name[0];\n    CARBON_CHECK(short_char < short_option_table_.size(),\n                 \"Short option name outside of the expected range.\");\n    short_option_table_[short_char] = &map_entry.second;\n  }\n  subcommand_map_.clear();\n  for (const auto& subcommand : command.subcommands) {\n    subcommand_map_.insert({subcommand->info.name, subcommand.get()});\n  }\n}\n\nauto Parser::SetOptionDefault(const Arg& option) -> void {\n  CARBON_CHECK(option.has_default, \"No default value available!\");\n  switch (option.kind) {\n    case Arg::Kind::Flag:\n      *option.flag_storage = option.default_flag;\n      break;\n    case Arg::Kind::Integer:\n      *option.integer_storage = option.default_integer;\n      break;\n    case Arg::Kind::String:\n      *option.string_storage = option.default_string;\n      break;\n    case Arg::Kind::OneOf:\n      option.default_action(option);\n      break;\n    case Arg::Kind::MetaActionOnly:\n      CARBON_FATAL(\"Can't set a default value for a meta action!\");\n    case Arg::Kind::Invalid:\n      CARBON_FATAL(\"Option configured without any action or kind!\");\n  }\n}\n\nauto Parser::ParseNegatedFlag(const Arg& flag,\n                              std::optional<llvm::StringRef> value)\n    -> ErrorOr<Success> {\n  if (flag.kind != Arg::Kind::Flag) {\n    return Error(\n        \"cannot use a negated flag name by prefixing it with `no-` when it \"\n        \"isn't a boolean flag argument\");\n  }\n  if (value) {\n    return Error(\n        \"cannot specify a value when using a flag name prefixed with `no-` -- \"\n        \"that prefix implies a value of `false`\");\n  }\n  *flag.flag_storage = false;\n  return Success();\n}\n\nauto Parser::ParseFlag(const Arg& flag, std::optional<llvm::StringRef> value)\n    -> ErrorOr<Success> {\n  CARBON_CHECK(flag.kind == Arg::Kind::Flag, \"Incorrect kind: {0}\", flag.kind);\n  if (!value || *value == \"true\") {\n    *flag.flag_storage = true;\n  } else if (*value == \"false\") {\n    *flag.flag_storage = false;\n  } else {\n    return Error(llvm::formatv(\n        \"invalid value specified for the boolean flag `--{0}`: {1}\",\n        flag.info.name, *value));\n  }\n  return Success();\n}\n\nauto Parser::ParseIntegerArgValue(const Arg& arg, llvm::StringRef value)\n    -> ErrorOr<Success> {\n  CARBON_CHECK(arg.kind == Arg::Kind::Integer, \"Incorrect kind: {0}\", arg.kind);\n  int integer_value;\n  // Note that this method returns *true* on error!\n  if (value.getAsInteger(/*Radix=*/0, integer_value)) {\n    return Error(llvm::formatv(\n        \"cannot parse value for option `--{0}` as an integer: {1}\",\n        arg.info.name, value));\n  }\n  if (!arg.is_append) {\n    *arg.integer_storage = integer_value;\n  } else {\n    arg.integer_sequence->push_back(integer_value);\n  }\n  return Success();\n}\n\nauto Parser::ParseStringArgValue(const Arg& arg, llvm::StringRef value)\n    -> ErrorOr<Success> {\n  CARBON_CHECK(arg.kind == Arg::Kind::String, \"Incorrect kind: {0}\", arg.kind);\n  if (!arg.is_append) {\n    *arg.string_storage = value;\n  } else {\n    arg.string_sequence->push_back(value);\n  }\n  return Success();\n}\n\nauto Parser::ParseOneOfArgValue(const Arg& arg, llvm::StringRef value)\n    -> ErrorOr<Success> {\n  CARBON_CHECK(arg.kind == Arg::Kind::OneOf, \"Incorrect kind: {0}\", arg.kind);\n  if (!arg.value_action(arg, value)) {\n    RawStringOstream error;\n    error << \"option `--\" << arg.info.name << \"=\";\n    llvm::printEscapedString(value, error);\n    error << \"` has an invalid value `\";\n    llvm::printEscapedString(value, error);\n    error << \"`; valid values are: \";\n    PrintListOfAlternatives<llvm::StringRef>(\n        error, arg.value_strings, [](llvm::StringRef x) { return x; });\n    return Error(error.TakeStr());\n  }\n  return Success();\n}\n\nauto Parser::ParseArg(const Arg& arg, bool short_spelling,\n                      std::optional<llvm::StringRef> value, bool negated_name)\n    -> ErrorOr<Success> {\n  // If this argument has a meta action, replace the current meta action with\n  // it.\n  if (arg.meta_action) {\n    arg_meta_action_ = arg.meta_action;\n  }\n\n  // Boolean flags have special parsing logic.\n  if (negated_name) {\n    return ParseNegatedFlag(arg, value);\n  }\n  if (arg.kind == Arg::Kind::Flag) {\n    return ParseFlag(arg, value);\n  }\n\n  std::string name;\n  if (short_spelling) {\n    name = llvm::formatv(\"`-{0}` (short for `--{1}`)\", arg.info.short_name,\n                         arg.info.name);\n  } else {\n    name = llvm::formatv(\"`--{0}`\", arg.info.name);\n  }\n\n  if (!value) {\n    // We can't have a positional argument without a value, so we know this is\n    // an option and handle it as such.\n    if (arg.kind == Arg::Kind::MetaActionOnly) {\n      // Nothing further to do here, this is only a meta-action.\n      return Success();\n    }\n    if (!arg.has_default) {\n      return Error(llvm::formatv(\n          \"option {0} requires a value to be provided and none was\", name));\n    }\n    SetOptionDefault(arg);\n    return Success();\n  }\n\n  // There is a value to parse as part of the argument.\n  switch (arg.kind) {\n    case Arg::Kind::Integer:\n      return ParseIntegerArgValue(arg, *value);\n    case Arg::Kind::String:\n      return ParseStringArgValue(arg, *value);\n    case Arg::Kind::OneOf:\n      return ParseOneOfArgValue(arg, *value);\n    case Arg::Kind::MetaActionOnly:\n      // TODO: Improve message.\n      return Error(llvm::formatv(\n          \"option {0} cannot be used with a value, and '{1}' was provided\",\n          name, value));\n    case Arg::Kind::Flag:\n    case Arg::Kind::Invalid:\n      CARBON_FATAL(\"Invalid kind!\");\n  }\n}\n\nauto Parser::SplitValue(llvm::StringRef& unparsed_arg)\n    -> std::optional<llvm::StringRef> {\n  // Split out a value if present.\n  std::optional<llvm::StringRef> value;\n  auto index = unparsed_arg.find('=');\n  if (index != llvm::StringRef::npos) {\n    value = unparsed_arg.substr(index + 1);\n    unparsed_arg = unparsed_arg.substr(0, index);\n  }\n  return value;\n}\n\nauto Parser::ParseLongOption(llvm::StringRef unparsed_arg) -> ErrorOr<Success> {\n  CARBON_CHECK(unparsed_arg.starts_with(\"--\") && unparsed_arg.size() > 2,\n               \"Must only be called on a potential long option.\");\n\n  // Walk past the double dash.\n  unparsed_arg = unparsed_arg.drop_front(2);\n  bool negated_name = unparsed_arg.consume_front(\"no-\");\n  std::optional<llvm::StringRef> value = SplitValue(unparsed_arg);\n\n  auto option_it = option_map_.find(unparsed_arg);\n  if (option_it == option_map_.end()) {\n    // TODO: Improve error.\n    return Error(llvm::formatv(\"unknown option `--{0}{1}`\",\n                               negated_name ? \"no-\" : \"\", unparsed_arg));\n  }\n\n  // Mark this option as parsed.\n  option_it->second.setInt(true);\n\n  // Parse this specific option and any value.\n  const Arg& option = *option_it->second.getPointer();\n  return ParseArg(option, /*short_spelling=*/false, value, negated_name);\n}\n\nauto Parser::ParseShortOptionSeq(llvm::StringRef unparsed_arg)\n    -> ErrorOr<Success> {\n  CARBON_CHECK(unparsed_arg.starts_with(\"-\") && unparsed_arg.size() > 1,\n               \"Must only be called on a potential short option sequence.\");\n\n  unparsed_arg = unparsed_arg.drop_front();\n  std::optional<llvm::StringRef> value = SplitValue(unparsed_arg);\n  if (value && unparsed_arg.size() != 1) {\n    return Error(llvm::formatv(\n        \"cannot provide a value to the group of multiple short options \"\n        \"`-{0}=...`; values must be provided to a single option, using \"\n        \"either the short or long spelling\",\n        unparsed_arg));\n  }\n\n  for (unsigned char c : unparsed_arg) {\n    auto* arg_entry =\n        (c < short_option_table_.size()) ? short_option_table_[c] : nullptr;\n    if (!arg_entry) {\n      return Error(\n          llvm::formatv(\"unknown short option `-{0}`\", static_cast<char>(c)));\n    }\n    // Mark this argument as parsed.\n    arg_entry->setInt(true);\n\n    // Parse the argument, including the value if this is the last.\n    const Arg& arg = *arg_entry->getPointer();\n    CARBON_RETURN_IF_ERROR(ParseArg(arg, /*short_spelling=*/true, value));\n  }\n  return Success();\n}\n\nauto Parser::FinalizeParsedOptions() -> ErrorOr<Success> {\n  llvm::SmallVector<const Arg*> missing_options;\n  for (const auto& option_entry : option_map_) {\n    const Arg* option = option_entry.second.getPointer();\n    if (!option_entry.second.getInt()) {\n      // If the argument has a default value and isn't a meta-action, we need to\n      // act on that when it isn't passed.\n      if (option->has_default && !option->meta_action) {\n        SetOptionDefault(*option);\n      }\n      // Remember any missing required arguments, we'll diagnose those.\n      if (option->is_required) {\n        missing_options.push_back(option);\n      }\n    }\n  }\n  if (missing_options.empty()) {\n    return Success();\n  }\n\n  // Sort the missing arguments by name to provide a stable and deterministic\n  // error message. We know there can't be duplicate names because these came\n  // from a may keyed on the name, so this provides a total ordering.\n  llvm::sort(missing_options, [](const Arg* lhs, const Arg* rhs) {\n    return lhs->info.name < rhs->info.name;\n  });\n\n  RawStringOstream error;\n  error << \"required options not provided: \";\n  llvm::ListSeparator sep;\n  for (const Arg* option : missing_options) {\n    error << sep << \"--\" << option->info.name;\n  }\n\n  return Error(error.TakeStr());\n}\n\nauto Parser::ParsePositionalArg(llvm::StringRef unparsed_arg)\n    -> ErrorOr<Success> {\n  if (static_cast<size_t>(positional_arg_index_) >=\n      command_->positional_args.size()) {\n    return Error(llvm::formatv(\n        \"completed parsing all {0} configured positional arguments, and found \"\n        \"an additional positional argument: `{1}`\",\n        command_->positional_args.size(), unparsed_arg));\n  }\n\n  const Arg& arg = *command_->positional_args[positional_arg_index_];\n\n  // Mark that we'll keep appending here until a `--` marker. When already\n  // appending this is redundant but harmless.\n  appending_to_positional_arg_ = arg.is_append;\n  if (!appending_to_positional_arg_) {\n    // If we're not continuing to append to a current positional arg,\n    // increment the positional arg index to find the next argument we\n    // should use here.\n    ++positional_arg_index_;\n  }\n\n  return ParseArg(arg, /*short_spelling=*/false, unparsed_arg);\n}\n\nauto Parser::ParseSubcommand(llvm::StringRef unparsed_arg) -> ErrorOr<Success> {\n  auto subcommand_it = subcommand_map_.find(unparsed_arg);\n  if (subcommand_it == subcommand_map_.end()) {\n    RawStringOstream error;\n    error << \"invalid subcommand `\" << unparsed_arg\n          << \"`; available subcommands: \";\n    MetaPrinter(&error).PrintSubcommands(*command_);\n    return Error(error.TakeStr());\n  }\n\n  // Before we recurse into the subcommand, verify that all the required\n  // arguments for this command were in fact parsed.\n  CARBON_RETURN_IF_ERROR(FinalizeParsedOptions());\n\n  // Recurse into the subcommand, tracking the active command.\n  command_ = subcommand_it->second;\n  PopulateMaps(*command_);\n  return Success();\n}\n\nauto Parser::FinalizeParse() -> ErrorOr<ParseResult> {\n  // If an argument action is provided, we run that and consider the parse\n  // meta-successful rather than verifying required arguments were provided and\n  // the (sub)command action.\n  if (arg_meta_action_) {\n    arg_meta_action_();\n    return ParseResult::MetaSuccess;\n  }\n\n  // Verify we're not missing any arguments.\n  CARBON_RETURN_IF_ERROR(FinalizeParsedOptions());\n\n  // If we were appending to a positional argument, mark that as complete.\n  llvm::ArrayRef positional_args = command_->positional_args;\n  if (appending_to_positional_arg_) {\n    CARBON_CHECK(\n        static_cast<size_t>(positional_arg_index_) < positional_args.size(),\n        \"Appending to a positional argument with an invalid index: {0}\",\n        positional_arg_index_);\n    ++positional_arg_index_;\n  }\n\n  // See if any positional args are required and unparsed.\n  auto unparsed_positional_args = positional_args.slice(positional_arg_index_);\n  if (!unparsed_positional_args.empty()) {\n    // There are un-parsed positional arguments, make sure they aren't required.\n    const Arg& missing_arg = *unparsed_positional_args.front();\n    if (missing_arg.is_required) {\n      return Error(\n          llvm::formatv(\"not all required positional arguments were provided; \"\n                        \"first missing and required positional argument: `{0}`\",\n                        missing_arg.info.name));\n    }\n    for (const auto& arg_ptr : unparsed_positional_args) {\n      CARBON_CHECK(\n          !arg_ptr->is_required,\n          \"Cannot have required positional parameters after an optional one.\");\n    }\n  }\n\n  switch (command_->kind) {\n    case Command::Kind::Invalid:\n      CARBON_FATAL(\"Should never have a parser with an invalid command!\");\n    case Command::Kind::RequiresSubcommand: {\n      RawStringOstream error;\n      error << \"no subcommand specified; available subcommands: \";\n      MetaPrinter(&error).PrintSubcommands(*command_);\n      return Error(error.TakeStr());\n    }\n    case Command::Kind::Action:\n      // All arguments have been successfully parsed, run any action for the\n      // most specific selected command. Only the leaf command's action is run.\n      command_->action();\n      return ParseResult::Success;\n    case Command::Kind::MetaAction:\n      command_->action();\n      return ParseResult::MetaSuccess;\n  }\n}\n\nauto Parser::ParsePositionalSuffix(\n    llvm::ArrayRef<llvm::StringRef> unparsed_args) -> ErrorOr<Success> {\n  CARBON_CHECK(\n      !command_->positional_args.empty(),\n      \"Cannot do positional suffix parsing without positional arguments!\");\n  CARBON_CHECK(\n      !unparsed_args.empty() && unparsed_args.front() == \"--\",\n      \"Must be called with a suffix of arguments starting with a `--` that \"\n      \"switches to positional suffix parsing.\");\n  // Once we're in the positional suffix, we can track empty positional\n  // arguments.\n  bool empty_positional = false;\n  while (!unparsed_args.empty()) {\n    llvm::StringRef unparsed_arg = unparsed_args.consume_front();\n\n    if (unparsed_arg != \"--\") {\n      CARBON_RETURN_IF_ERROR(ParsePositionalArg(unparsed_arg));\n      empty_positional = false;\n      continue;\n    }\n\n    if (appending_to_positional_arg_ || empty_positional) {\n      ++positional_arg_index_;\n      if (static_cast<size_t>(positional_arg_index_) >=\n          command_->positional_args.size()) {\n        return Error(\n            llvm::formatv(\"completed parsing all {0} configured positional \"\n                          \"arguments, but found a subsequent `--` and have no \"\n                          \"further positional arguments to parse beyond it\",\n                          command_->positional_args.size()));\n      }\n    }\n    appending_to_positional_arg_ = false;\n    empty_positional = true;\n  }\n\n  return Success();\n}\n\nParser::Parser(llvm::raw_ostream* out, CommandInfo command_info,\n               llvm::function_ref<auto(CommandBuilder&)->void> build)\n    : meta_printer_(out), root_command_(command_info) {\n  // Run the command building lambda on a builder for the root command.\n  CommandBuilder builder(&root_command_, &meta_printer_);\n  build(builder);\n  builder.Finalize();\n  command_ = &root_command_;\n}\n\nauto Parser::Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args)\n    -> ErrorOr<ParseResult> {\n  PopulateMaps(*command_);\n\n  while (!unparsed_args.empty()) {\n    // Peak at the front for an exact `--` argument that switches to a\n    // positional suffix parsing without dropping this argument.\n    if (unparsed_args.front() == \"--\") {\n      if (command_->positional_args.empty()) {\n        return Error(\n            \"cannot meaningfully end option and subcommand arguments with a \"\n            \"`--` argument when there are no positional arguments to parse\");\n      }\n      if (static_cast<size_t>(positional_arg_index_) >=\n          command_->positional_args.size()) {\n        return Error(\n            \"switched to purely positional arguments with a `--` argument \"\n            \"despite already having parsed all positional arguments for this \"\n            \"command\");\n      }\n      CARBON_RETURN_IF_ERROR(ParsePositionalSuffix(unparsed_args));\n      // No more unparsed arguments to handle.\n      break;\n    }\n\n    // Now that we're not switching parse modes, drop the current unparsed\n    // argument and parse it.\n    llvm::StringRef unparsed_arg = unparsed_args.consume_front();\n\n    if (unparsed_arg.starts_with(\"--\")) {\n      // Note that the exact argument \"--\" has been handled above already.\n      CARBON_RETURN_IF_ERROR(ParseLongOption(unparsed_arg));\n      continue;\n    }\n\n    if (unparsed_arg.starts_with(\"-\") && unparsed_arg.size() > 1) {\n      CARBON_RETURN_IF_ERROR(ParseShortOptionSeq(unparsed_arg));\n      continue;\n    }\n\n    CARBON_CHECK(\n        command_->positional_args.empty() || command_->subcommands.empty(),\n        \"Cannot have both positional arguments and subcommands!\");\n    if (command_->positional_args.empty() && command_->subcommands.empty()) {\n      return Error(llvm::formatv(\n          \"found unexpected positional argument or subcommand: `{0}`\",\n          unparsed_arg));\n    }\n\n    if (!command_->positional_args.empty()) {\n      CARBON_RETURN_IF_ERROR(ParsePositionalArg(unparsed_arg));\n      continue;\n    }\n    CARBON_RETURN_IF_ERROR(ParseSubcommand(unparsed_arg));\n  }\n\n  return FinalizeParse();\n}\n\nauto ArgBuilder::Required(bool is_required) -> void {\n  arg_->is_required = is_required;\n}\n\nauto ArgBuilder::HelpHidden(bool is_help_hidden) -> void {\n  arg_->is_help_hidden = is_help_hidden;\n}\n\nArgBuilder::ArgBuilder(Arg* arg) : arg_(arg) {}\n\nauto FlagBuilder::Default(bool flag_value) -> void {\n  arg()->has_default = true;\n  arg()->default_flag = flag_value;\n}\n\nauto FlagBuilder::Set(bool* flag) -> void { arg()->flag_storage = flag; }\n\nauto IntegerArgBuilder::Default(int integer_value) -> void {\n  arg()->has_default = true;\n  arg()->default_integer = integer_value;\n}\n\nauto IntegerArgBuilder::Set(int* integer) -> void {\n  arg()->is_append = false;\n  arg()->integer_storage = integer;\n}\n\nauto IntegerArgBuilder::Append(llvm::SmallVectorImpl<int>* sequence) -> void {\n  arg()->is_append = true;\n  arg()->integer_sequence = sequence;\n}\n\nauto StringArgBuilder::Default(llvm::StringRef string_value) -> void {\n  arg()->has_default = true;\n  arg()->default_string = string_value;\n}\n\nauto StringArgBuilder::Set(llvm::StringRef* string) -> void {\n  arg()->is_append = false;\n  arg()->string_storage = string;\n}\n\nauto StringArgBuilder::Append(llvm::SmallVectorImpl<llvm::StringRef>* sequence)\n    -> void {\n  arg()->is_append = true;\n  arg()->string_sequence = sequence;\n}\n\nstatic auto IsValidName(llvm::StringRef name) -> bool {\n  if (name.size() <= 1) {\n    return false;\n  }\n  if (!llvm::isAlnum(name.front())) {\n    return false;\n  }\n  if (!llvm::isAlnum(name.back())) {\n    return false;\n  }\n  for (char c : name.drop_front().drop_back()) {\n    if (c != '-' && c != '_' && !llvm::isAlnum(c)) {\n      return false;\n    }\n  }\n  // We disallow names starting with \"no-\" as we will parse those for boolean\n  // flags.\n  return !name.starts_with(\"no-\");\n}\n\nauto CommandBuilder::AddFlag(const ArgInfo& info,\n                             llvm::function_ref<auto(FlagBuilder&)->void> build)\n    -> void {\n  FlagBuilder builder(AddArgImpl(info, Arg::Kind::Flag));\n  // All boolean flags have an implicit default of `false`, although it can be\n  // overridden in the build callback.\n  builder.Default(false);\n  build(builder);\n}\n\nauto CommandBuilder::AddIntegerOption(\n    const ArgInfo& info,\n    llvm::function_ref<auto(IntegerArgBuilder&)->void> build) -> void {\n  IntegerArgBuilder builder(AddArgImpl(info, Arg::Kind::Integer));\n  build(builder);\n}\n\nauto CommandBuilder::AddStringOption(\n    const ArgInfo& info,\n    llvm::function_ref<auto(StringArgBuilder&)->void> build) -> void {\n  StringArgBuilder builder(AddArgImpl(info, Arg::Kind::String));\n  build(builder);\n}\n\nauto CommandBuilder::AddOneOfOption(\n    const ArgInfo& info, llvm::function_ref<auto(OneOfArgBuilder&)->void> build)\n    -> void {\n  OneOfArgBuilder builder(AddArgImpl(info, Arg::Kind::OneOf));\n  build(builder);\n}\n\nauto CommandBuilder::AddMetaActionOption(\n    const ArgInfo& info, llvm::function_ref<auto(ArgBuilder&)->void> build)\n    -> void {\n  ArgBuilder builder(AddArgImpl(info, Arg::Kind::MetaActionOnly));\n  build(builder);\n}\n\nauto CommandBuilder::AddIntegerPositionalArg(\n    const ArgInfo& info,\n    llvm::function_ref<auto(IntegerArgBuilder&)->void> build) -> void {\n  AddPositionalArgImpl(info, Arg::Kind::Integer, [build](Arg& arg) {\n    IntegerArgBuilder builder(&arg);\n    build(builder);\n  });\n}\n\nauto CommandBuilder::AddStringPositionalArg(\n    const ArgInfo& info,\n    llvm::function_ref<auto(StringArgBuilder&)->void> build) -> void {\n  AddPositionalArgImpl(info, Arg::Kind::String, [build](Arg& arg) {\n    StringArgBuilder builder(&arg);\n    build(builder);\n  });\n}\n\nauto CommandBuilder::AddOneOfPositionalArg(\n    const ArgInfo& info, llvm::function_ref<auto(OneOfArgBuilder&)->void> build)\n    -> void {\n  AddPositionalArgImpl(info, Arg::Kind::OneOf, [build](Arg& arg) {\n    OneOfArgBuilder builder(&arg);\n    build(builder);\n  });\n}\n\nauto CommandBuilder::AddSubcommand(\n    const CommandInfo& info,\n    llvm::function_ref<auto(CommandBuilder&)->void> build) -> void {\n  CARBON_CHECK(IsValidName(info.name), \"Invalid subcommand name: {0}\",\n               info.name);\n  CARBON_CHECK(subcommand_names_.insert(info.name).second,\n               \"Added a duplicate subcommand: {0}\", info.name);\n  CARBON_CHECK(\n      command_->positional_args.empty(),\n      \"Cannot add subcommands to a command with a positional argument.\");\n\n  command_->subcommands.emplace_back(new Command(info, command_));\n  CommandBuilder builder(command_->subcommands.back().get(), meta_printer_);\n  build(builder);\n  builder.Finalize();\n}\n\nauto CommandBuilder::HelpHidden(bool is_help_hidden) -> void {\n  command_->is_help_hidden = is_help_hidden;\n}\n\nauto CommandBuilder::RequiresSubcommand() -> void {\n  CARBON_CHECK(!command_->subcommands.empty(),\n               \"Cannot require subcommands unless there are subcommands.\");\n  CARBON_CHECK(command_->positional_args.empty(),\n               \"Cannot require subcommands and have a positional argument.\");\n  CARBON_CHECK(command_->kind == Kind::Invalid,\n               \"Already established the kind of this command as: {0}\",\n               command_->kind);\n  command_->kind = Kind::RequiresSubcommand;\n}\n\nauto CommandBuilder::Do(ActionT action) -> void {\n  CARBON_CHECK(command_->kind == Kind::Invalid,\n               \"Already established the kind of this command as: {0}\",\n               command_->kind);\n  command_->kind = Kind::Action;\n  command_->action = std::move(action);\n}\n\nauto CommandBuilder::Meta(ActionT action) -> void {\n  CARBON_CHECK(command_->kind == Kind::Invalid,\n               \"Already established the kind of this command as: {0}\",\n               command_->kind);\n  command_->kind = Kind::MetaAction;\n  command_->action = std::move(action);\n}\n\nCommandBuilder::CommandBuilder(Command* command, MetaPrinter* meta_printer)\n    : command_(command), meta_printer_(meta_printer) {}\n\nauto CommandBuilder::AddArgImpl(const ArgInfo& info, Arg::Kind kind) -> Arg* {\n  CARBON_CHECK(IsValidName(info.name), \"Invalid argument name: {0}\", info.name);\n  CARBON_CHECK(arg_names_.insert(info.name).second,\n               \"Added a duplicate argument name: {0}\", info.name);\n\n  command_->options.emplace_back(new Arg(info));\n  Arg* arg = command_->options.back().get();\n  arg->kind = kind;\n  return arg;\n}\n\nauto CommandBuilder::AddPositionalArgImpl(\n    const ArgInfo& info, Arg::Kind kind,\n    llvm::function_ref<auto(Arg&)->void> build) -> void {\n  CARBON_CHECK(IsValidName(info.name), \"Invalid argument name: {0}\", info.name);\n  CARBON_CHECK(\n      command_->subcommands.empty(),\n      \"Cannot add a positional argument to a command with subcommands.\");\n\n  command_->positional_args.emplace_back(new Arg(info));\n  Arg& arg = *command_->positional_args.back();\n  arg.kind = kind;\n  build(arg);\n\n  CARBON_CHECK(!arg.is_help_hidden,\n               \"Cannot have a help-hidden positional argument.\");\n\n  if (arg.is_required && command_->positional_args.size() > 1) {\n    CARBON_CHECK((*std::prev(command_->positional_args.end(), 2))->is_required,\n                 \"A required positional argument cannot be added after an \"\n                 \"optional one.\");\n  }\n}\n\nauto CommandBuilder::Finalize() -> void {\n  meta_printer_->RegisterWithCommand(*command_, *this);\n}\n\nauto Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args,\n           llvm::raw_ostream& out, CommandInfo command_info,\n           llvm::function_ref<auto(CommandBuilder&)->void> build)\n    -> ErrorOr<ParseResult> {\n  // Build a parser, which includes building the command description provided by\n  // the user.\n  Parser parser(&out, command_info, build);\n\n  // Now parse the arguments provided using that parser.\n  return parser.Parse(unparsed_args);\n}\n\n}  // namespace Carbon::CommandLine\n\n// NOLINTEND(misc-no-recursion)\n"
  },
  {
    "path": "common/command_line.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_COMMAND_LINE_H_\n#define CARBON_COMMON_COMMAND_LINE_H_\n\n#include <memory>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/error.h\"\n#include \"common/ostream.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/DenseSet.h\"\n#include \"llvm/ADT/Sequence.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/ADT/StringRef.h\"\n\n// # Command-line argument parsing library.\n//\n// This is a collection of tools to describe both simple and reasonably complex\n// command line interfaces, and parse arguments based on those descriptions. It\n// optimizes for command line tools that will parse arguments exactly once per\n// execution, and specifically tools that make heavy use of subcommand-style\n// command line interfaces.\n//\n// ## Terminology used by this library\n//\n// _Argument_ or _arg_: One of the parsed components of the command line.\n//\n// _Option_: A _named_ argument starting with `--` to configure some aspect of\n// the tool. These often have both long spellings that start with `--` and\n// short, single character spellings that start with `-` and can be bundled with\n// other single character options.\n//\n// _Flag_: A boolean or binary option. These can only be enabled or disabled.\n//\n// _Positional argument_: An argument that is not named but is identified based\n// on the order in which it is encountered in the command line, with options\n// removed. Only a leaf command can contain positional arguments.\n//\n// _Value_: The value parameter provided to an argument. For options, this is\n// provided after an `=` and the option name. For positional arguments, the\n// value is the only thing provided. The string of the value is parsed according\n// to the kind of argument with fairly simple rules. See the argument builders\n// for more details.\n//\n// _Command_: The container of options, subcommands, and positional arguments to\n// parse and an action to take when successful.\n//\n// _Leaf command_: A command that doesn't contain subcommands. This is the only\n// kind of command that can contain positional arguments.\n//\n// _Subcommand_: A command nested within another command and identified by a\n// specific name that ends the parsing of arguments based on the parent and\n// switches to parse based on the specific subcommand's options and positional\n// arguments. A command with subcommands cannot parse positional arguments.\n//\n// _Action_: An open-ended callback, typically reflecting a specific subcommand\n// being parsed. Can either directly perform the operation or simply mark which\n// operation was selected.\n//\n// _Meta action_: An action fully handled by argument parsing such as displaying\n// help, version information, or completion.\n//\n// Example command to illustrate the different components:\n//\n//     git --no-pager clone --shared --filter=blob:none my-repo my-directory\n//\n// This command breaks down as:\n// - `git`: The top-level command.\n// - `--no-pager`: A negated flag on the top-level command (`git`).\n// - `clone`: A subcommand.\n// - `--shared`: A positive flag for the subcommand (`clone`).\n// - `--filter=blob:none`: An option named `filter` with a value `blob:none`.\n// - `my-repo`: The first positional argument to the subcommand.\n// - `my-directory`: the second positional argument to the subcommand.\n//\n// **Note:** while the example uses a `git` command to be relatively familiar\n// and well documented, this library does not support the same flag syntaxes as\n// `git` or use anything similar for its subcommand dispatch. This example is\n// just to help clarify the terminology used, and carefully chosen to only use a\n// syntax that overlaps with this library's parsed syntax.\n//\n// ## Options and flags\n//\n// The option syntax and behavior supported by this library is designed to be\n// strict and relatively simple while still supporting a wide range of expected\n// use cases:\n//\n// - All options must have a unique long name that is accessed with a `--`\n//   prefix. The name must consist of characters in the set [-a-zA-Z0-9], and it\n//   must not start with a `-` or `no-`.\n//\n// - Values are always attached using an `=` after the name. Only a few simple\n//   value formats are supported:\n//   - Arbitrary strings\n//   - Integers as parsed by `llvm::StringRef` and whose value fits in an\n//     `int`.\n//   - One of a fixed set of strings\n//\n// - Options may be parsed multiple times, and the behavior can be configured:\n//   - Each time, they can set a new value, overwriting any previous.\n//   - They can append the value to a container.\n//   - TODO: They can increment a count.\n//\n// - Options may have a default value that will be synthesized even if they do\n//   not occur in the parsed command line.\n//\n// - Flags (boolean options) have some special rules.\n//   - They may be spelled normally, and default to setting that flag to `true`.\n//   - They may also accept a value of either exactly `true` or `false` and that\n//     is the value.\n//   - They may be spelled with a `no-` prefix, such as `--no-verbose`, and that\n//     is exactly equivalent to `--verbose=false`.\n//   - For flags with a default `true` value, they are rendered in help using\n//     the `no-` prefix.\n//\n// - Options may additionally have a short name of a single character [a-zA-Z].\n//   - There is no distinction between the behavior of long and short names.\n//   - The short name can only specify the positive or `true` value for flags.\n//     There is no negative form of short names.\n//   - Short names are parsed after a single `-`, such as `-v`.\n//   - Any number of short names for boolean flags or options with default\n//     values may be grouped after `-`, such as `-xyz`: this is three options,\n//     `x`, `y`, and `z`.\n//   - Short options may include a value after an `=`, but not when grouped with\n//     other short options.\n//\n// - Options are parsed from any argument until either a subcommand switches to\n//   that subcommand's options or a `--` argument ends all option parsing to\n//   allow arguments that would be ambiguous with the option syntax.\n//\n// ## Subcommands\n//\n// Subcommands can be nested to any depth, and each subcommand gets its own\n// option space.\n//\n// ## Positional arguments\n//\n// Leaf commands (and subcommands) can accept positional arguments. These work\n// similar to options but consist *only* of the value. They have names, but the\n// name is only used in documentation and error messages. Except for the special\n// case of the exact argument `-`, positional argument values cannot start with\n// a `-` character until after option parsing is ended with a `--` argument.\n//\n// Singular positional arguments store the single value in that position.\n// Appending positional arguments append all of the values in sequence.\n//\n// Multiple positional arguments to a single command are parsed in sequence. For\n// appending positional arguments, the sequence of values appended is ended with\n// a `--` argument. For example, a command that takes two sequences of\n// positional arguments might look like:\n//\n//     my-diff-tool a.txt b.txt c.txt -- new-a.txt new-b.txt new-c.txt\n//\n// The `--` used in this way *both* ends option parsing and the positional\n// argument sequence. Note that if there are no positional arguments prior to\n// the first `--`, then it will just end option parsing. To pass an empty\n// sequence of positional arguments two `--` arguments would be required. Once\n// option parsing is ended, even a single positional argument can be skipped\n// using a `--` argument without a positional argument.\n//\n// ## Help text blocks and rendering\n//\n// At many points in this library, a block of text is specified as a string.\n// These should be written using multi-line raw string literals that start on\n// their own line such as:\n//\n// ```cpp\n//     ...\n//     .help = R\"\"\"(\n// Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod\n// tempor incididunt ut labore et dolore magna aliqua.\n// )\"\"\",\n// ```\n//\n// The code using these blocks will remove leading and trailing newlines. TODO:\n// It should also reflow all of the text in a way that tries to be roughly\n// similar to how Markdown would be reflowed when rendered:\n//\n// - Blank lines will be preserved.\n// - (TODO) A best effort to detect lists and other common Markdown constructs\n//   and preserve the newlines between those.\n// - (TODO) Fenced regions will be preserved exactly.\n//\n// The remaining blocks will have all newlines removed when there is no column\n// width information on the output stream, or will be re-flowed to the output\n// stream's column width when available.\n//\n// ## The `Args` class\n//\n// The `Args` class is not a meaningful type, it serves two purposes: to give a\n// structured name prefix to the inner types, and to allow marking many\n// components `private` and using `friend` to grant access to implementation\n// details.\n//\n// ## Roadmap / TODOs / planned future work\n//\n// - Detect column width when the stream is a terminal and re-flow text.\n// - Implement short help display mode (and enable that by default).\n// - Add help text to one-of values and render it when present.\n// - Add formatting when the stream supports it (colors, bold, etc).\n// - Improve error messages when parsing fails.\n//   - Reliably display the most appropriate usage string.\n//   - Suggest typo corrections?\n//   - Print snippet or otherwise render the failure better?\n// - Add support for responding to shell autocomplete queries.\n// - Finish adding support for setting and printing version information.\n// - Add short option counting support (`-vvv` -> `--verbose=3`).\n//\nnamespace Carbon::CommandLine {\n\n// Forward declare some implementation detail classes and classes that are\n// friended.\nstruct Arg;\nstruct Command;\nclass MetaPrinter;\nclass Parser;\nclass CommandBuilder;\n\n// The result of parsing arguments.\nenum class ParseResult : int8_t {\n  // Signifies that program arguments were successfully parsed and can be\n  // used.\n  Success,\n\n  // Signifies a successful meta operation such as displaying help text\n  // was performed. No parsed arguments are available, and the side-effects\n  // have been directly provided via the streams provided to the parser.\n  MetaSuccess,\n};\nauto operator<<(llvm::raw_ostream& output, ParseResult result)\n    -> llvm::raw_ostream&;\n\n// Actions are stored in data structures so we use an owning closure to model\n// them.\nusing ActionT = std::function<auto()->void>;\n\n// The core argument info used to render help and other descriptive\n// information. This is used for both options and positional arguments.\n// Commands use an extended version below.\nstruct ArgInfo {\n  // The name of the argument. For options, this is the long name parsed after\n  // `--`. Option names must also be unique. Conventionally, these are spelled\n  // in lower case with a single dash separating words as that tends to be\n  // especially easy to type and reasonably easy to read.\n  //\n  // For positional arguments this is only used for help text, and is often\n  // spelled with `ALL-CAPS` to make it clear that it is a placeholder name\n  // and does not appear in the actual command line.\n  llvm::StringRef name;\n\n  // Optional short name for options. This must consist of a single character\n  // in the set [a-zA-Z].\n  llvm::StringRef short_name = \"\";\n\n  // For options, it is sometimes useful to render a distinct value\n  // placeholder name to help clarify what the value should contain. These are\n  // often in `ALL-CAPS` to make it clear they are placeholders. For example,\n  // an `output` option might set this to `FILE` so it renders as\n  // `--output=FILE`.\n  llvm::StringRef value_name = \"\";\n\n  // A long-form help string that will be rendered for this argument in\n  // command help strings. It supports multiple lines and is rendered as a\n  // text block described in the `Args` top-level comment.\n  llvm::StringRef help = \"\";\n\n  // A short help string for the argument. This should be as short as\n  // possible, and always fit easily on a single line. Ideally, it can fit in\n  // a narrow column of a single line and is in the range of 40 columns wide.\n  //\n  // If not provided, the first paragraph (up to a blank line) from `help`\n  // will be used.\n  llvm::StringRef help_short = \"\";\n};\n\n// The kinds of arguments that can be parsed.\nenum class ArgKind : int8_t {\n  Invalid,\n  Flag,\n  Integer,\n  String,\n  OneOf,\n  MetaActionOnly,\n};\nauto operator<<(llvm::raw_ostream& output, ArgKind kind) -> llvm::raw_ostream&;\n\n// A builder used to configure an argument for parsing.\nclass ArgBuilder {\n public:\n  // When marked as required, if an argument is not provided explicitly in the\n  // command line the parse will produce an error.\n  auto Required(bool is_required) -> void;\n\n  // An argument can be hidden from the help output.\n  auto HelpHidden(bool is_help_hidden) -> void;\n\n  // Sets a meta-action to run when this argument is parsed. This is used to\n  // set up arguments like `--help` or `--version` that can be entirely\n  // handled during parsing and rather than produce parsed information about\n  // the command line, override that for some custom behavior.\n  template <typename T>\n  auto MetaAction(T action) -> void;\n\n protected:\n  friend class CommandBuilder;\n  // `arg` must not be null.\n  explicit ArgBuilder(Arg* arg);\n\n  auto arg() -> Arg* { return arg_; }\n\n private:\n  Arg* arg_;\n};\n\n// Customized argument builder when the value is a boolean flag.\nclass FlagBuilder : public ArgBuilder {\n public:\n  // Flags can be defaulted to true. However, flags always have *some*\n  // default, this merely customizes which value is default. If uncustomized,\n  // the default of a flag is false.\n  auto Default(bool flag_value) -> void;\n\n  // Configures the argument to store a parsed value in the provided storage.\n  //\n  // This must be called on the builder.\n  auto Set(bool* flag) -> void;\n\n private:\n  using ArgBuilder::ArgBuilder;\n};\n\n// Customized argument builder when the value is an integer.\nclass IntegerArgBuilder : public ArgBuilder {\n public:\n  // Sets a default for the argument with the provided value. There is no\n  // default for integer arguments unless this is called.\n  //\n  // For arguments that are `Set` below, this value will be stored even if the\n  // argument is never explicitly provided. For arguments that are `Append`ed\n  // below, this value will be used whenever the argument occurs without an\n  // explicit value, but unless the argument is parsed nothing will be\n  // appended.\n  auto Default(int integer_value) -> void;\n\n  // Configures the argument to store a parsed value in the provided storage.\n  // Each time the argument is parsed, it will write a new value to this\n  // storage.\n  //\n  // Exactly one of this method or `Append` below must be configured for the\n  // argument.\n  auto Set(int* integer) -> void;\n\n  // Configures the argument to append a parsed value to the provided\n  // container. Each time the argument is parsed, a new value will be\n  // appended.\n  //\n  // Exactly one of this method or `Set` above must be configured for the\n  // argument.\n  auto Append(llvm::SmallVectorImpl<int>* sequence) -> void;\n\n private:\n  using ArgBuilder::ArgBuilder;\n};\n\n// Customized argument builder when the value is a string.\nclass StringArgBuilder : public ArgBuilder {\n public:\n  // Sets a default for the argument with the provided value. There is no\n  // default for string arguments unless this is called.\n  //\n  // For arguments that are `Set` below, this value will be stored even if the\n  // argument is never explicitly provided. For arguments that are `Append`ed\n  // below, this value will be used whenever the argument occurs without an\n  // explicit value, but unless the argument is parsed nothing will be\n  // appended.\n  auto Default(llvm::StringRef string_value) -> void;\n\n  // Configures the argument to store a parsed value in the provided storage.\n  // Each time the argument is parsed, it will write a new value to this\n  // storage.\n  //\n  // Exactly one of this method or `Append` below must be configured for the\n  // argument.\n  auto Set(llvm::StringRef* string) -> void;\n\n  // Configures the argument to append a parsed value to the provided\n  // container. Each time the argument is parsed, a new value will be\n  // appended.\n  //\n  // Exactly one of this method or `Set` above must be configured for the\n  // argument.\n  auto Append(llvm::SmallVectorImpl<llvm::StringRef>* sequence) -> void;\n\n private:\n  using ArgBuilder::ArgBuilder;\n};\n\n// Customized argument builder when the value is required to be one of a fixed\n// set of possible strings, and each one maps to a specific value of some\n// type, often an enumerator.\nclass OneOfArgBuilder : public ArgBuilder {\n public:\n  // A tiny helper / builder type for describing one of the possible values\n  // that a particular argument accepts.\n  //\n  // Beyond carrying the string, type, and value for this candidate, it also\n  // allows marking the candidate as the default.\n  template <typename T>\n  class OneOfValueT {\n   public:\n    // Configure whether a candidate is the default. If not called, it is not\n    // the default. This can only be used when setting, not when appending.\n    auto Default(bool is_default) && -> OneOfValueT;\n\n   private:\n    friend OneOfArgBuilder;\n\n    explicit OneOfValueT(llvm::StringRef str, T value);\n\n    llvm::StringRef str;\n    T value;\n    bool is_default = false;\n  };\n\n  // A helper function to create an object that models one of the candidate\n  // values for this argument. It takes the string used to select this value\n  // on the command line, deduces the type of the value, and accepts the value\n  // itself that should be used when this candidate is parsed.\n  template <typename T>\n  static auto OneOfValue(llvm::StringRef string, T value) -> OneOfValueT<T>;\n\n  // Configures the argument to store a parsed value in the provided storage.\n  // Each time the argument is parsed, it will write a new value to this\n  // storage.\n  //\n  // Exactly one of this method or `AppendOneOf` below must be configured for\n  // the argument.\n  //\n  // For one-of arguments, this method also provides an array of possible\n  // values that may be used:\n  //\n  // ```cpp\n  //   arg_b.SetOneOf(\n  //       {\n  //           arg_b.OneOfValue(\"x\", 1),\n  //           arg_b.OneOfValue(\"y\", 2),\n  //           arg_b.OneOfValue(\"z\", 3).Default(true),\n  //       },\n  //       &value);\n  // ```\n  //\n  // The only value strings that will be parsed are those described in the\n  // array, and the value stored in the storage for a particular parsed value\n  // string is the one associated with it. There must be a single homogeneous\n  // type for the all of the candidate values and that type must be storable\n  // into the result storage pointee type. At most one of the array can also\n  // be marked as a default value, which will make specifying a value\n  // optional, and also will cause that value to be stored into the result\n  // even if the argument is not parsed explicitly.\n  template <typename T, typename U, size_t N>\n  auto SetOneOf(const OneOfValueT<U> (&values)[N], T* result) -> void;\n\n  // Configures the argument to append a parsed value to the provided\n  // container. Each time the argument is parsed, a new value will be\n  // appended.\n  //\n  // Exactly one of this method or `SetOneOf` above must be configured for the\n  // argument.\n  //\n  // Similar to `SetOneOf`, this must also describe the candidate value\n  // strings that can be parsed and the consequent values that are used for\n  // those strings:\n  //\n  // ```cpp\n  //   arg_b.AppendOneOf(\n  //       {\n  //           arg_b.OneOfValue(\"x\", 1),\n  //           arg_b.OneOfValue(\"y\", 2),\n  //           arg_b.OneOfValue(\"z\", 3),\n  //       },\n  //       &values);\n  // ```\n  //\n  // Instead of storing, these values are appended.\n  //\n  // However, appending one-of arguments cannot use a default. The values must\n  // always be explicitly parsed.\n  template <typename T, typename U, size_t N>\n  auto AppendOneOf(const OneOfValueT<U> (&values)[N],\n                   llvm::SmallVectorImpl<T>* sequence) -> void;\n\n private:\n  using ArgBuilder::ArgBuilder;\n\n  template <typename U, size_t N, typename MatchT, size_t... Indices>\n  auto OneOfImpl(const OneOfValueT<U> (&input_values)[N], MatchT match,\n                 std::index_sequence<Indices...> /*indices*/) -> void;\n};\n\n// The extended info for a command, including for a subcommand.\n//\n// This provides the primary descriptive information for commands used by help\n// and other diagnostic messages. For subcommands, it also provides the name\n// used to access the subcommand.\nstruct CommandInfo {\n  // The name of the command. For subcommands, this is also the argument\n  // spelling that accesses this subcommand. It must consist of characters in\n  // the set [-a-zA-Z0-9], and must not start with a `-`.\n  llvm::StringRef name;\n\n  // An optional version string that will be rendered as part of version meta\n  // action by the library. While this library does not impose a machine\n  // parsable structure, users will expect this to be extractable and parsable\n  // in practice.\n  //\n  // Subcommands with an empty version will inherit the first non-empty parent\n  // version.\n  //\n  // Whether a (possibly inherited) version string is non-empty determines\n  // whether this library provides the version-printing meta actions via a\n  // `--version` flag or, if there are subcommands, a `version` subcommand.\n  llvm::StringRef version = \"\";\n\n  // Optional build information to include when printing the version.\n  llvm::StringRef build_info = \"\";\n\n  // An optional long-form help string for the command.\n  //\n  // When accessing a command's dedicated help output, this will form the main\n  // prose output at the beginning of the help message. When listing\n  // subcommands, the subcommand's `help` string will be used to describe it\n  // in the list.\n  //\n  // The help meta actions are available regardless of whether this is\n  // provided in order to mechanically describe other aspects of the command.\n  //\n  // This field supports multiple lines and uses the text block handling\n  // described in the top-level `Args` comment.\n  llvm::StringRef help = \"\";\n\n  // An optional short help string for the command.\n  //\n  // This should be very short, at most one line and ideally fitting within a\n  // narrow column of a line. If left blank, the first paragraph of text (up\n  // to the first blank line) in the `help` string will be used.\n  llvm::StringRef help_short = \"\";\n\n  // An optional custom block of text to describe the usage of the command.\n  //\n  // The usage should just be a series of lines with possible invocations of\n  // the command summarized as briefly as possible. Ideally, each variation on\n  // a single line. The goal is to show the *structure* of different command\n  // invocations, not to be comprehensive.\n  //\n  // When omitted, the library will generate these based on the parsing logic.\n  // The generated usage is expected to be suitable for the vast majority of\n  // users, but can be customized in cases where necessary.\n  llvm::StringRef usage = \"\";\n\n  // An optional epilogue multi-line block of text appended to the help display\n  // for this command. It is only used for this command's dedicated help, but\n  // can contain extra, custom guidance that is especially useful to have at\n  // the very end of the output.\n  llvm::StringRef help_epilogue = \"\";\n};\n\n// Commands are classified based on the action they result in when run.\n//\n// Commands that require a subcommand have no action and are just a means to\n// reach the subcommand actions.\n//\n// Commands with _meta_ actions are also a separate kind from those with\n// normal actions.\nenum class CommandKind : int8_t {\n  Invalid,\n  RequiresSubcommand,\n  Action,\n  MetaAction,\n};\nauto operator<<(llvm::raw_ostream& output, CommandKind kind)\n    -> llvm::raw_ostream&;\n\n// Builder used to configure a command to parse.\n//\n// An instance of this is used to configure the top-level command, and a fresh\n// instance is provided for configuring each subcommand as well.\nclass CommandBuilder {\n public:\n  using Kind = CommandKind;\n\n  auto AddFlag(const ArgInfo& info,\n               llvm::function_ref<auto(FlagBuilder&)->void> build) -> void;\n  auto AddIntegerOption(\n      const ArgInfo& info,\n      llvm::function_ref<auto(IntegerArgBuilder&)->void> build) -> void;\n  auto AddStringOption(const ArgInfo& info,\n                       llvm::function_ref<auto(StringArgBuilder&)->void> build)\n      -> void;\n  auto AddOneOfOption(const ArgInfo& info,\n                      llvm::function_ref<auto(OneOfArgBuilder&)->void> build)\n      -> void;\n  auto AddMetaActionOption(const ArgInfo& info,\n                           llvm::function_ref<auto(ArgBuilder&)->void> build)\n      -> void;\n\n  auto AddIntegerPositionalArg(\n      const ArgInfo& info,\n      llvm::function_ref<auto(IntegerArgBuilder&)->void> build) -> void;\n  auto AddStringPositionalArg(\n      const ArgInfo& info,\n      llvm::function_ref<auto(StringArgBuilder&)->void> build) -> void;\n  auto AddOneOfPositionalArg(\n      const ArgInfo& info,\n      llvm::function_ref<auto(OneOfArgBuilder&)->void> build) -> void;\n\n  auto AddSubcommand(const CommandInfo& info,\n                     llvm::function_ref<auto(CommandBuilder&)->void> build)\n      -> void;\n\n  // Subcommands can be hidden from the help listing of their parents with\n  // this setting. Hiding a subcommand doesn't disable its own help, it just\n  // removes it from the listing.\n  auto HelpHidden(bool is_help_hidden) -> void;\n\n  // Exactly one of these three should be called to select and configure the\n  // kind of the built command.\n  auto RequiresSubcommand() -> void;\n  auto Do(ActionT action) -> void;\n  auto Meta(ActionT meta_action) -> void;\n\n private:\n  friend Parser;\n\n  // `command` and `meta_printer` must not be null.\n  explicit CommandBuilder(Command* command, MetaPrinter* meta_printer);\n\n  auto AddArgImpl(const ArgInfo& info, ArgKind kind) -> Arg*;\n  auto AddPositionalArgImpl(const ArgInfo& info, ArgKind kind,\n                            llvm::function_ref<auto(Arg&)->void> build) -> void;\n  auto Finalize() -> void;\n\n  Command* command_;\n  MetaPrinter* meta_printer_;\n\n  llvm::SmallDenseSet<llvm::StringRef> arg_names_;\n  llvm::SmallDenseSet<llvm::StringRef> subcommand_names_;\n};\n\n// Builds a description of a command and then parses the provided arguments\n// for that command.\n//\n// This is the main entry point to both build up the description of the\n// command whose arguments are being parsed and to do the parsing. Everything\n// is done in a single invocation as the common case is to build a command\n// description, parse the arguments once, and then run with that\n// configuration.\n//\n// The `out` stream is treated like `stdout` would be for a Unix-style command\n// line tool, and `errors` like `stderr`: any errors or diagnostic information\n// are printed to `errors`, but meta-actions like printing a command's help go\n// to `out`.\nauto Parse(llvm::ArrayRef<llvm::StringRef> unparsed_args,\n           llvm::raw_ostream& out, CommandInfo command_info,\n           llvm::function_ref<auto(CommandBuilder&)->void> build)\n    -> ErrorOr<ParseResult>;\n\n// Implementation details only below.\n\n// The internal representation of a parsable argument description.\nstruct Arg {\n  using Kind = ArgKind;\n  using ValueActionT =\n      std::function<auto(const Arg& arg, llvm::StringRef value_string)->bool>;\n  using DefaultActionT = std::function<auto(const Arg& arg)->void>;\n\n  explicit Arg(ArgInfo info);\n  ~Arg();\n\n  ArgInfo info;\n  Kind kind = Kind::Invalid;\n  bool has_default = false;\n  bool is_required = false;\n  bool is_append = false;\n  bool is_help_hidden = false;\n\n  // Meta action storage, only populated if this argument causes a meta action.\n  ActionT meta_action;\n\n  // Storage options depending on the kind.\n  union {\n    // Singular argument storage pointers.\n    bool* flag_storage;\n    int* integer_storage;\n    llvm::StringRef* string_storage;\n\n    // Appending argument storage pointers.\n    llvm::SmallVectorImpl<int>* integer_sequence;\n    llvm::SmallVectorImpl<llvm::StringRef>* string_sequence;\n\n    // One-of information.\n    struct {\n      llvm::SmallVector<llvm::StringRef> value_strings;\n      ValueActionT value_action;\n    };\n  };\n\n  // Default values depending on the kind.\n  union {\n    bool default_flag;\n    int default_integer;\n    llvm::StringRef default_string;\n    struct {\n      DefaultActionT default_action;\n      int default_value_index;\n    };\n  };\n};\n\n// The internal representation of a parsable command description, including its\n// options, positional arguments, and subcommands.\nstruct Command {\n  using Kind = CommandBuilder::Kind;\n\n  explicit Command(CommandInfo info, Command* parent = nullptr);\n\n  CommandInfo info;\n  Command* parent;\n  ActionT action;\n  Kind kind = Kind::Invalid;\n\n  bool is_help_hidden = false;\n\n  llvm::SmallVector<std::unique_ptr<Arg>> options;\n  llvm::SmallVector<std::unique_ptr<Arg>> positional_args;\n  llvm::SmallVector<std::unique_ptr<Command>> subcommands;\n};\n\ntemplate <typename T>\nauto ArgBuilder::MetaAction(T action) -> void {\n  CARBON_CHECK(!arg_->meta_action, \"Cannot set a meta action twice!\");\n  arg_->meta_action = std::move(action);\n}\n\ntemplate <typename T>\nauto OneOfArgBuilder::OneOfValueT<T>::Default(\n    bool is_default) && -> OneOfValueT {\n  OneOfValueT result = std::move(*this);\n  result.is_default = is_default;\n  return result;\n}\n\ntemplate <typename T>\nOneOfArgBuilder::OneOfValueT<T>::OneOfValueT(llvm::StringRef str, T value)\n    : str(str), value(std::move(value)) {}\n\ntemplate <typename T>\nauto OneOfArgBuilder::OneOfValue(llvm::StringRef str, T value)\n    -> OneOfValueT<T> {\n  return OneOfValueT<T>(str, value);\n}\n\ntemplate <typename T, typename U, size_t N>\nauto OneOfArgBuilder::SetOneOf(const OneOfValueT<U> (&values)[N], T* result)\n    -> void {\n  static_assert(N > 0, \"Must include at least one value.\");\n  arg()->is_append = false;\n  OneOfImpl(\n      values, [result](T value) { *result = value; },\n      std::make_index_sequence<N>{});\n}\n\ntemplate <typename T, typename U, size_t N>\nauto OneOfArgBuilder::AppendOneOf(const OneOfValueT<U> (&values)[N],\n                                  llvm::SmallVectorImpl<T>* sequence) -> void {\n  static_assert(N > 0, \"Must include at least one value.\");\n  arg()->is_append = true;\n  OneOfImpl(\n      values, [sequence](T value) { sequence->push_back(value); },\n      std::make_index_sequence<N>{});\n}\n\n// An implementation tool for the one-of value candidate handling. Delegating to\n// this allows us to deduce a pack of indices from the array of candidates, and\n// then use that variadic pack to operate on the array in the variadic space.\n// This includes packaging the components up separately into our storage\n// representation, as well as processing the array to find and register any\n// default.\n//\n// The representation is especially tricky because we want all of the actual\n// values and even the *type* of values to be erased. We do that by building\n// lambdas that do the type-aware operations and storing those into type-erased\n// function objects.\ntemplate <typename U, size_t N, typename MatchT, size_t... Indices>\nauto OneOfArgBuilder::OneOfImpl(const OneOfValueT<U> (&input_values)[N],\n                                MatchT match,\n                                std::index_sequence<Indices...> /*indices*/)\n    -> void {\n  std::array<U, N> values = {input_values[Indices].value...};\n\n  // Directly copy the value strings into a vector.\n  new (&arg()->value_strings) llvm::SmallVector<llvm::StringRef>(\n      std::initializer_list<llvm::StringRef>{input_values[Indices].str...});\n\n  // And build a type-erased action that maps a specific value string to a value\n  // by index.\n  new (&arg()->value_action) Arg::ValueActionT(\n      [values, match](const Arg& arg, llvm::StringRef value_string) -> bool {\n        for (auto [value, arg_value_string] :\n             llvm::zip_equal(values, arg.value_strings)) {\n          if (value_string == arg_value_string) {\n            match(value);\n            return true;\n          }\n        }\n        return false;\n      });\n\n  // Fold over all the input values to see if there is a default.\n  if ((input_values[Indices].is_default || ...)) {\n    CARBON_CHECK(!arg()->is_append, \"Can't append default.\");\n    CARBON_CHECK((input_values[Indices].is_default + ... + 0) == 1,\n                 \"Cannot default more than one value.\");\n\n    arg()->has_default = true;\n\n    // First build a lambda that configures the default using an index. We'll\n    // call this below, this lambda isn't the one that is stored.\n    auto set_default = [&](size_t index, const auto& default_value) {\n      // Now that we have the desired default index, build a lambda and store it\n      // as the default action. This lambda is stored and so it captures the\n      // necessary information explicitly and by value.\n      new (&arg()->default_action)\n          Arg::DefaultActionT([value = default_value.value,\n                               match](const Arg& /*arg*/) { match(value); });\n\n      // Also store the index itself for use when printing help.\n      arg()->default_value_index = index;\n    };\n\n    // Now we fold across the inputs and in the one case that is the default, we\n    // call the lambda. This is just a somewhat awkward way to write a loop with\n    // a condition in it over a pack.\n    ((input_values[Indices].is_default\n          ? set_default(Indices, input_values[Indices])\n          : static_cast<void>(0)),\n     ...);\n  }\n}\n\n}  // namespace Carbon::CommandLine\n\n#endif  // CARBON_COMMON_COMMAND_LINE_H_\n"
  },
  {
    "path": "common/command_line_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/command_line.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"common/error_test_helpers.h\"\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n\nnamespace Carbon::CommandLine {\nnamespace {\n\nusing ::Carbon::Testing::IsError;\nusing ::Carbon::Testing::IsSuccess;\nusing ::testing::ElementsAre;\nusing ::testing::Eq;\nusing ::testing::StrEq;\n\nconstexpr CommandInfo TestCommandInfo = {\n    .name = \"test\",\n    .help = \"A test command.\",\n    .help_epilogue = \"TODO\",\n};\n\nenum class TestEnum : int8_t {\n  Val1,\n  Val2,\n};\n\nenum class TestSubcommand : int8_t {\n  Sub1,\n  Sub2,\n};\n\nTEST(ArgParserTest, BasicCommand) {\n  bool flag = false;\n  int integer_option = -1;\n  llvm::StringRef string_option = \"\";\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args) {\n    return Parse(args, llvm::errs(), TestCommandInfo, [&](auto& b) {\n      b.AddFlag({.name = \"flag\"}, [&](auto& arg_b) { arg_b.Set(&flag); });\n      b.AddIntegerOption({.name = \"option1\"},\n                         [&](auto& arg_b) { arg_b.Set(&integer_option); });\n      b.AddStringOption({.name = \"option2\"},\n                        [&](auto& arg_b) { arg_b.Set(&string_option); });\n      b.Do([] {});\n    });\n  };\n\n  EXPECT_THAT(parse({\"--flag\", \"--option2=value\", \"--option1=42\"}),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n  EXPECT_THAT(integer_option, Eq(42));\n  EXPECT_THAT(string_option, StrEq(\"value\"));\n}\n\nTEST(ArgParserTest, BooleanFlags) {\n  bool flag = false;\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(args, s, TestCommandInfo, [&](auto& b) {\n      b.AddFlag({.name = \"flag\"}, [&](auto& arg_b) { arg_b.Set(&flag); });\n      b.Do([] {});\n    });\n  };\n\n  EXPECT_THAT(parse({\"--no-flag\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_FALSE(flag);\n\n  EXPECT_THAT(parse({\"--flag\", \"--no-flag\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_FALSE(flag);\n\n  EXPECT_THAT(parse({\"--no-flag\", \"--flag\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n\n  EXPECT_THAT(parse({\"--no-flag\", \"--flag\", \"--flag=false\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_FALSE(flag);\n\n  EXPECT_THAT(parse({\"--no-flag\", \"--flag=true\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n\n  EXPECT_THAT(parse({\"--no-flag\", \"--flag=true\", \"--no-flag\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_FALSE(flag);\n\n  RawStringOstream os;\n  EXPECT_THAT(\n      parse({\"--no-flag=true\"}, os),\n      IsError(StrEq(\"cannot specify a value when using a flag name prefixed \"\n                    \"with `no-` -- that prefix implies a value of `false`\")));\n\n  EXPECT_THAT(\n      parse({\"--no-flag=false\"}, os),\n      IsError(StrEq(\"cannot specify a value when using a flag name prefixed \"\n                    \"with `no-` -- that prefix implies a value of `false`\")));\n}\n\nTEST(ArgParserTest, ArgDefaults) {\n  bool flag = false;\n  int integer_option = -1;\n  llvm::StringRef string_option = \"\";\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(args, s, TestCommandInfo, [&](auto& b) {\n      b.AddFlag({.name = \"flag\"}, [&](auto& arg_b) {\n        arg_b.Default(true);\n        arg_b.Set(&flag);\n      });\n      b.AddIntegerOption({.name = \"option1\"}, [&](auto& arg_b) {\n        arg_b.Default(7);\n        arg_b.Set(&integer_option);\n      });\n      b.AddStringOption({.name = \"option2\"}, [&](auto& arg_b) {\n        arg_b.Default(\"default\");\n        arg_b.Set(&string_option);\n      });\n      b.Do([] {});\n    });\n  };\n\n  EXPECT_THAT(parse({}, llvm::errs()), IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n  EXPECT_THAT(integer_option, Eq(7));\n  EXPECT_THAT(string_option, StrEq(\"default\"));\n\n  EXPECT_THAT(parse({\"--option1\", \"--option2\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n  EXPECT_THAT(integer_option, Eq(7));\n  EXPECT_THAT(string_option, StrEq(\"default\"));\n\n  EXPECT_THAT(parse({\"--option1=42\", \"--option2=explicit\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n  EXPECT_THAT(integer_option, Eq(42));\n  EXPECT_THAT(string_option, StrEq(\"explicit\"));\n\n  EXPECT_THAT(\n      parse({\"--option1=42\", \"--option2=explicit\", \"--option1\", \"--option2\"},\n            llvm::errs()),\n      IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n  EXPECT_THAT(integer_option, Eq(7));\n  EXPECT_THAT(string_option, StrEq(\"default\"));\n}\n\nTEST(ArgParserTest, ShortArgs) {\n  bool flag = false;\n  bool example = false;\n  int integer_option = -1;\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(args, s, TestCommandInfo, [&](auto& b) {\n      b.AddFlag({.name = \"flag\", .short_name = \"f\"},\n                [&](auto& arg_b) { arg_b.Set(&flag); });\n      b.AddFlag({.name = \"example\", .short_name = \"x\"},\n                [&](auto& arg_b) { arg_b.Set(&example); });\n      b.AddIntegerOption({.name = \"option1\", .short_name = \"o\"},\n                         [&](auto& arg_b) {\n                           arg_b.Default(123);\n                           arg_b.Set(&integer_option);\n                         });\n      b.AddIntegerOption({.name = \"option2\", .short_name = \"z\"},\n                         [&](auto& arg_b) { arg_b.Set(&integer_option); });\n      b.Do([] {});\n    });\n  };\n\n  EXPECT_THAT(parse({\"-f\", \"-o=42\", \"-x\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n  EXPECT_TRUE(example);\n  EXPECT_THAT(integer_option, Eq(42));\n\n  flag = false;\n  example = false;\n  EXPECT_THAT(parse({\"--option1=13\", \"-xfo\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n  EXPECT_TRUE(example);\n  EXPECT_THAT(integer_option, Eq(123));\n\n  RawStringOstream os;\n\n  EXPECT_THAT(parse({\"-v\"}, os), IsError(StrEq(\"unknown short option `-v`\")));\n  EXPECT_THAT(parse({\"-xvx\"}, os), IsError(StrEq(\"unknown short option `-v`\")));\n\n  EXPECT_THAT(\n      parse({\"-xzf\"}, os),\n      IsError(StrEq(\"option `-z` (short for `--option2`) requires a value to \"\n                    \"be provided and none was\")));\n\n  EXPECT_THAT(\n      parse({\"--option2\"}, os),\n      IsError(StrEq(\n          \"option `--option2` requires a value to be provided and none was\")));\n\n  EXPECT_THAT(\n      parse({\"-xz=123\"}, os),\n      IsError(StrEq(\"cannot provide a value to the group of multiple short \"\n                    \"options `-xz=...`; values must be provided to a single \"\n                    \"option, using either the short or long spelling\")));\n}\n\nTEST(ArgParserTest, PositionalArgs) {\n  bool flag = false;\n  llvm::StringRef string_option = \"\";\n  llvm::StringRef source_string;\n  llvm::StringRef dest_string;\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(args, s, TestCommandInfo, [&](auto& b) {\n      b.AddFlag({.name = \"flag\"}, [&](auto& arg_b) { arg_b.Set(&flag); });\n      b.AddStringOption({.name = \"option\"},\n                        [&](auto& arg_b) { arg_b.Set(&string_option); });\n      b.AddStringPositionalArg({.name = \"source\"}, [&](auto& arg_b) {\n        arg_b.Set(&source_string);\n        arg_b.Required(true);\n      });\n      b.AddStringPositionalArg({.name = \"dest\"}, [&](auto& arg_b) {\n        arg_b.Set(&dest_string);\n        arg_b.Required(true);\n      });\n      b.Do([] {});\n    });\n  };\n\n  RawStringOstream os;\n  EXPECT_THAT(parse({\"--flag\", \"--option=x\"}, os),\n              IsError(StrEq(\n                  \"not all required positional arguments were provided; first \"\n                  \"missing and required positional argument: `source`\")));\n\n  EXPECT_THAT(parse({\"src\", \"--flag\", \"--option=value\", \"dst\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n  EXPECT_THAT(string_option, StrEq(\"value\"));\n  EXPECT_THAT(source_string, StrEq(\"src\"));\n  EXPECT_THAT(dest_string, StrEq(\"dst\"));\n\n  EXPECT_THAT(parse({\"src2\", \"--\", \"dst2\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(source_string, StrEq(\"src2\"));\n  EXPECT_THAT(dest_string, StrEq(\"dst2\"));\n\n  EXPECT_THAT(parse({\"-\", \"--\", \"-\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(source_string, StrEq(\"-\"));\n  EXPECT_THAT(dest_string, StrEq(\"-\"));\n}\n\nTEST(ArgParserTest, PositionalAppendArgs) {\n  bool flag = false;\n  llvm::StringRef string_option = \"\";\n  llvm::SmallVector<llvm::StringRef> source_strings;\n  llvm::SmallVector<llvm::StringRef> dest_strings;\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(args, s, TestCommandInfo, [&](auto& b) {\n      b.AddFlag({.name = \"flag\"}, [&](auto& arg_b) { arg_b.Set(&flag); });\n      b.AddStringOption({.name = \"option\"},\n                        [&](auto& arg_b) { arg_b.Set(&string_option); });\n      b.AddStringPositionalArg({.name = \"sources\"}, [&](auto& arg_b) {\n        arg_b.Append(&source_strings);\n        arg_b.Required(true);\n      });\n      b.AddStringPositionalArg({.name = \"dest\"}, [&](auto& arg_b) {\n        arg_b.Append(&dest_strings);\n        arg_b.Required(true);\n      });\n      b.Do([] {});\n    });\n  };\n\n  RawStringOstream os;\n  EXPECT_THAT(parse({\"--flag\", \"--option=x\"}, os),\n              IsError(StrEq(\n                  \"not all required positional arguments were provided; first \"\n                  \"missing and required positional argument: `sources`\")));\n\n  EXPECT_THAT(\n      parse({\"src1\", \"--flag\", \"src2\", \"--option=value\", \"--\", \"--dst--\"},\n            llvm::errs()),\n      IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(flag);\n  EXPECT_THAT(string_option, StrEq(\"value\"));\n  EXPECT_THAT(source_strings, ElementsAre(StrEq(\"src1\"), StrEq(\"src2\")));\n  EXPECT_THAT(dest_strings, ElementsAre(StrEq(\"--dst--\")));\n\n  source_strings.clear();\n  dest_strings.clear();\n  EXPECT_THAT(\n      parse({\"--\", \"--src1--\", \"--src2--\", \"--\", \"dst1\", \"dst2\"}, llvm::errs()),\n      IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(source_strings,\n              ElementsAre(StrEq(\"--src1--\"), StrEq(\"--src2--\")));\n  EXPECT_THAT(dest_strings, ElementsAre(StrEq(\"dst1\"), StrEq(\"dst2\")));\n\n  source_strings.clear();\n  dest_strings.clear();\n  EXPECT_THAT(parse({\"--\", \"--\", \"dst1\", \"dst2\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(source_strings, ElementsAre());\n  EXPECT_THAT(dest_strings, ElementsAre(StrEq(\"dst1\"), StrEq(\"dst2\")));\n}\n\nTEST(ArgParserTest, BasicSubcommands) {\n  bool flag = false;\n  llvm::StringRef option1 = \"\";\n  llvm::StringRef option2 = \"\";\n\n  TestSubcommand subcommand;\n  bool subsub_command = false;\n\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(args, s, TestCommandInfo, [&](auto& b) {\n      b.AddSubcommand({.name = \"sub1\"}, [&](auto& sub_b) {\n        sub_b.AddFlag({.name = \"flag\"}, [&](auto& arg_b) { arg_b.Set(&flag); });\n        sub_b.AddStringOption({.name = \"option\"},\n                              [&](auto& arg_b) { arg_b.Set(&option1); });\n        sub_b.Do([&] { subcommand = TestSubcommand::Sub1; });\n      });\n      b.AddSubcommand({.name = \"sub2\"}, [&](auto& sub_b) {\n        sub_b.AddStringOption({.name = \"option\"},\n                              [&](auto& arg_b) { arg_b.Set(&option1); });\n        sub_b.AddSubcommand({.name = \"subsub\"}, [&](auto& subsub_b) {\n          subsub_b.AddStringOption({.name = \"option\"},\n                                   [&](auto& arg_b) { arg_b.Set(&option2); });\n          subsub_b.Do([&] { subsub_command = true; });\n        });\n        sub_b.Do([&] { subcommand = TestSubcommand::Sub2; });\n      });\n      b.RequiresSubcommand();\n    });\n  };\n\n  RawStringOstream os;\n  EXPECT_THAT(parse({}, os),\n              IsError(StrEq(\"no subcommand specified; available subcommands: \"\n                            \"`sub1`, `sub2`, or `help`\")));\n\n  EXPECT_THAT(parse({\"--flag\"}, os), IsError(StrEq(\"unknown option `--flag`\")));\n\n  EXPECT_THAT(parse({\"sub3\"}, os),\n              IsError(StrEq(\"invalid subcommand `sub3`; available subcommands: \"\n                            \"`sub1`, `sub2`, or `help`\")));\n\n  EXPECT_THAT(parse({\"--flag\", \"sub1\"}, os),\n              IsError(StrEq(\"unknown option `--flag`\")));\n\n  EXPECT_THAT(parse({\"sub1\", \"--flag\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(subcommand, Eq(TestSubcommand::Sub1));\n  EXPECT_TRUE(flag);\n\n  EXPECT_THAT(parse({\"sub2\", \"--option=value\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(subcommand, Eq(TestSubcommand::Sub2));\n  EXPECT_THAT(option1, StrEq(\"value\"));\n\n  EXPECT_THAT(parse({\"sub2\", \"--option=abc\", \"subsub42\", \"--option=xyz\"}, os),\n              IsError(StrEq(\"invalid subcommand `subsub42`; available \"\n                            \"subcommands: `subsub` or `help`\")));\n\n  EXPECT_THAT(\n      parse({\"sub2\", \"--option=abc\", \"subsub\", \"--option=xyz\"}, llvm::errs()),\n      IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_TRUE(subsub_command);\n  EXPECT_THAT(option1, StrEq(\"abc\"));\n  EXPECT_THAT(option2, StrEq(\"xyz\"));\n}\n\nTEST(ArgParserTest, Appending) {\n  llvm::SmallVector<int> integers;\n  llvm::SmallVector<llvm::StringRef> strings;\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(args, s, TestCommandInfo, [&](auto& b) {\n      b.AddIntegerOption({.name = \"int\"},\n                         [&](auto& arg_b) { arg_b.Append(&integers); });\n      b.AddStringOption({.name = \"str\"},\n                        [&](auto& arg_b) { arg_b.Append(&strings); });\n      b.Do([] {});\n    });\n  };\n\n  EXPECT_THAT(parse({}, llvm::errs()), IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(integers, ElementsAre());\n  EXPECT_THAT(strings, ElementsAre());\n\n  EXPECT_THAT(parse({\"--int=1\", \"--int=2\", \"--int=3\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(integers, ElementsAre(Eq(1), Eq(2), Eq(3)));\n  EXPECT_THAT(strings, ElementsAre());\n\n  EXPECT_THAT(parse({\"--str=a\", \"--str=b\", \"--str=c\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(integers, ElementsAre(Eq(1), Eq(2), Eq(3)));\n  EXPECT_THAT(strings, ElementsAre(StrEq(\"a\"), StrEq(\"b\"), StrEq(\"c\")));\n\n  EXPECT_THAT(parse({\"--str=d\", \"--int=4\", \"--str=e\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(integers, ElementsAre(Eq(1), Eq(2), Eq(3), Eq(4)));\n  EXPECT_THAT(strings, ElementsAre(StrEq(\"a\"), StrEq(\"b\"), StrEq(\"c\"),\n                                   StrEq(\"d\"), StrEq(\"e\")));\n}\n\nTEST(ArgParserTest, PositionalAppending) {\n  llvm::SmallVector<llvm::StringRef> option_strings;\n  llvm::SmallVector<llvm::StringRef> strings1;\n  llvm::SmallVector<llvm::StringRef> strings2;\n  llvm::SmallVector<llvm::StringRef> strings3;\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(args, s, TestCommandInfo, [&](auto& b) {\n      b.AddStringOption({.name = \"opt\"},\n                        [&](auto& arg_b) { arg_b.Append(&option_strings); });\n      b.AddStringPositionalArg({.name = \"s1\"},\n                               [&](auto& arg_b) { arg_b.Append(&strings1); });\n      b.AddStringPositionalArg({.name = \"s2\"},\n                               [&](auto& arg_b) { arg_b.Append(&strings2); });\n      b.AddStringPositionalArg({.name = \"s3\"},\n                               [&](auto& arg_b) { arg_b.Append(&strings3); });\n      b.Do([] {});\n    });\n  };\n\n  EXPECT_THAT(parse({\"a\", \"--opt=x\", \"b\", \"--opt=y\", \"--\", \"c\", \"--opt=z\", \"d\",\n                     \"--\", \"e\", \"f\"},\n                    llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(option_strings, ElementsAre(StrEq(\"x\"), StrEq(\"y\")));\n  EXPECT_THAT(strings1, ElementsAre(StrEq(\"a\"), StrEq(\"b\")));\n  EXPECT_THAT(strings2, ElementsAre(StrEq(\"c\"), StrEq(\"--opt=z\"), StrEq(\"d\")));\n  EXPECT_THAT(strings3, ElementsAre(StrEq(\"e\"), StrEq(\"f\")));\n}\n\nstatic auto ParseOneOfOption(\n    llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s,\n    llvm::function_ref<auto(OneOfArgBuilder&)->void> build)\n    -> ErrorOr<ParseResult> {\n  return Parse(args, s, TestCommandInfo, [&](auto& b) {\n    b.AddOneOfOption({.name = \"option\"}, build);\n    b.Do([] {});\n  });\n}\n\nTEST(ArgParserTest, OneOfOption) {\n  int value = 0;\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return ParseOneOfOption(args, s, [&](auto& arg_b) {\n      arg_b.SetOneOf(\n          {\n              arg_b.OneOfValue(\"x\", 1),\n              arg_b.OneOfValue(\"y\", 2),\n              arg_b.OneOfValue(\"z\", 3),\n          },\n          &value);\n    });\n  };\n\n  EXPECT_THAT(parse({\"--option=x\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(value, Eq(1));\n\n  EXPECT_THAT(parse({\"--option=y\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(value, Eq(2));\n\n  EXPECT_THAT(parse({\"--option=z\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(value, Eq(3));\n\n  RawStringOstream os;\n\n  EXPECT_THAT(\n      parse({\"--option\"}, os),\n      IsError(StrEq(\n          \"option `--option` requires a value to be provided and none was\")));\n\n  constexpr const char* ErrorStr =\n      \"option `--option={0}` has an invalid value `{0}`; valid values are: \"\n      \"`x`, `y`, or `z`\";\n  EXPECT_THAT(parse({\"--option=a\"}, os),\n              IsError(StrEq(llvm::formatv(ErrorStr, \"a\"))));\n\n  EXPECT_THAT(parse({\"--option=\"}, os),\n              IsError(StrEq(llvm::formatv(ErrorStr, \"\"))));\n\n  EXPECT_THAT(parse({\"--option=xx\"}, os),\n              IsError(StrEq(llvm::formatv(ErrorStr, \"xx\"))));\n\n  EXPECT_THAT(parse({\"--option=\\xFF\"}, os),\n              IsError(StrEq(llvm::formatv(ErrorStr, \"\\\\FF\"))));\n\n  EXPECT_THAT(parse({llvm::StringRef(\"--option=\\0\", 10)}, os),\n              IsError(StrEq(llvm::formatv(ErrorStr, \"\\\\00\"))));\n}\n\nTEST(ArgParserTest, OneOfOptionWithTwoOptions) {\n  int value = 0;\n  RawStringOstream os;\n  EXPECT_THAT(ParseOneOfOption({\"--option=z\"}, os,\n                               [&](auto& arg_b) {\n                                 arg_b.SetOneOf(\n                                     {\n                                         arg_b.OneOfValue(\"x\", 1),\n                                         arg_b.OneOfValue(\"y\", 2),\n                                     },\n                                     &value);\n                               }),\n              IsError(StrEq(\"option `--option=z` has an invalid value `z`; \"\n                            \"valid values are: `x` or `y`\")));\n}\n\nTEST(ArgParserTest, OneOfOptionWithOneOption) {\n  int value = 0;\n  RawStringOstream os;\n  EXPECT_THAT(ParseOneOfOption({\"--option=z\"}, os,\n                               [&](auto& arg_b) {\n                                 arg_b.SetOneOf(\n                                     {\n                                         arg_b.OneOfValue(\"x\", 1),\n                                     },\n                                     &value);\n                               }),\n              IsError(StrEq(\"option `--option=z` has an invalid value `z`; \"\n                            \"valid values are: `x`\")));\n}\n\nTEST(ArgParserTest, OneOfOptionAppending) {\n  llvm::SmallVector<int> values;\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return ParseOneOfOption(args, s, [&](auto& arg_b) {\n      arg_b.AppendOneOf(\n          {\n              arg_b.OneOfValue(\"x\", 1),\n              arg_b.OneOfValue(\"y\", 2),\n              arg_b.OneOfValue(\"z\", 3),\n          },\n          &values);\n    });\n  };\n\n  EXPECT_THAT(parse({}, llvm::errs()), IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(values, ElementsAre());\n\n  EXPECT_THAT(parse({\"--option=x\", \"--option=y\", \"--option=z\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(values, ElementsAre(Eq(1), Eq(2), Eq(3)));\n\n  EXPECT_THAT(parse({\"--option=y\", \"--option=y\", \"--option=x\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(values, ElementsAre(Eq(1), Eq(2), Eq(3), Eq(2), Eq(2), Eq(1)));\n}\n\nTEST(ArgParserTest, RequiredArgs) {\n  int integer_option;\n  llvm::StringRef string_option;\n\n  TestSubcommand subcommand;\n  int integer_sub_option;\n  llvm::StringRef string_sub_option;\n  TestEnum enum_sub_option;\n\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(args, s, TestCommandInfo, [&](auto& b) {\n      b.AddIntegerOption({.name = \"opt1\"}, [&](auto& arg_b) {\n        arg_b.Required(true);\n        arg_b.Set(&integer_option);\n      });\n      b.AddStringOption({.name = \"opt2\"}, [&](auto& arg_b) {\n        arg_b.Required(true);\n        arg_b.Set(&string_option);\n      });\n      b.AddSubcommand({.name = \"sub1\"}, [&](auto& sub_b) {\n        sub_b.AddIntegerOption({.name = \"sub-opt1\"}, [&](auto& arg_b) {\n          arg_b.Required(true);\n          arg_b.Set(&integer_sub_option);\n        });\n        sub_b.AddStringOption({.name = \"sub-opt2\"}, [&](auto& arg_b) {\n          arg_b.Required(true);\n          arg_b.Set(&string_sub_option);\n        });\n        sub_b.Do([&] { subcommand = TestSubcommand::Sub1; });\n      });\n      b.AddSubcommand({.name = \"sub2\"}, [&](auto& sub_b) {\n        sub_b.AddIntegerOption({.name = \"sub-opt1\"}, [&](auto& arg_b) {\n          arg_b.Required(true);\n          arg_b.Set(&integer_sub_option);\n        });\n        sub_b.AddStringOption({.name = \"sub-opt2\"}, [&](auto& arg_b) {\n          arg_b.Required(true);\n          arg_b.Set(&string_sub_option);\n        });\n        sub_b.AddOneOfOption({.name = \"sub-opt3\"}, [&](auto& arg_b) {\n          arg_b.Required(true);\n          arg_b.SetOneOf(\n              {\n                  arg_b.OneOfValue(\"a\", TestEnum::Val1),\n                  arg_b.OneOfValue(\"b\", TestEnum::Val2),\n              },\n              &enum_sub_option);\n        });\n        sub_b.Do([&] { subcommand = TestSubcommand::Sub2; });\n      });\n      b.Do([] {});\n    });\n  };\n\n  RawStringOstream os;\n  EXPECT_THAT(parse({}, os),\n              IsError(StrEq(\"required options not provided: --opt1, --opt2\")));\n\n  EXPECT_THAT(parse({\"--opt2=xyz\"}, os),\n              IsError(StrEq(\"required options not provided: --opt1\")));\n\n  EXPECT_THAT(parse({\"--opt2=xyz\", \"--opt1=42\"}, llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(integer_option, Eq(42));\n  EXPECT_THAT(string_option, StrEq(\"xyz\"));\n\n  EXPECT_THAT(parse({\"--opt2=xyz\", \"--opt1=42\", \"sub2\"}, os),\n              IsError(StrEq(\"required options not provided: --sub-opt1, \"\n                            \"--sub-opt2, --sub-opt3\")));\n\n  EXPECT_THAT(\n      parse({\"--opt2=xyz\", \"--opt1=42\", \"sub2\", \"--sub-opt3=b\"}, os),\n      IsError(StrEq(\"required options not provided: --sub-opt1, --sub-opt2\")));\n\n  EXPECT_THAT(parse({\"--opt2=xyz\", \"--opt1=42\", \"sub2\", \"--sub-opt3=b\",\n                     \"--sub-opt1=13\"},\n                    os),\n              IsError(StrEq(\"required options not provided: --sub-opt2\")));\n\n  EXPECT_THAT(parse({\"--opt2=xyz\", \"--opt1=42\", \"sub2\", \"--sub-opt3=b\",\n                     \"--sub-opt1=13\", \"--sub-opt2=abc\"},\n                    llvm::errs()),\n              IsSuccess(Eq(ParseResult::Success)));\n  EXPECT_THAT(integer_option, Eq(42));\n  EXPECT_THAT(string_option, StrEq(\"xyz\"));\n  EXPECT_THAT(subcommand, Eq(TestSubcommand::Sub2));\n  EXPECT_THAT(integer_sub_option, Eq(13));\n  EXPECT_THAT(string_sub_option, StrEq(\"abc\"));\n  EXPECT_THAT(enum_sub_option, Eq(TestEnum::Val2));\n}\n\nTEST(ArgParserTest, HelpAndVersion) {\n  bool flag = false;\n  int storage = -1;\n  llvm::StringRef string = \"\";\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(  // Force line break.\n        args, s,\n        {\n            .name = \"test\",\n            .version = \"Test Command -- version 1.2.3\",\n            .build_info = R\"\"\"(\nBuild timestamp: )\"\"\" __TIMESTAMP__ R\"\"\"(\nBuild config: test-config-info\n)\"\"\",\n            .help = R\"\"\"(\nA test command.\n\nLots more information about the test command.\n)\"\"\",\n            .help_epilogue = R\"\"\"(\nClosing remarks.\n)\"\"\",\n        },\n        [&](auto& b) {\n          b.AddFlag(\n              {\n                  .name = \"flag\",\n                  .short_name = \"f\",\n                  .help = R\"\"\"(\nA boolean flag.\n)\"\"\",\n              },\n              [&](auto& arg_b) { arg_b.Set(&flag); });\n          b.AddFlag(\n              {\n                  .name = \"hidden_flag\",\n                  .help = R\"\"\"(\nA *hidden* boolean flag.\n)\"\"\",\n              },\n              [&](auto& arg_b) {\n                arg_b.HelpHidden(true);\n                arg_b.Set(&flag);\n              });\n          b.AddSubcommand(\n              {\n                  .name = \"edit\",\n                  .help = R\"\"\"(\nEdit the widget.\n\nThis will take the provided widgets and edit them.\n)\"\"\",\n                  .help_epilogue = R\"\"\"(\nThat's all.\n)\"\"\",\n              },\n              [&](auto& sub_b) {\n                sub_b.AddIntegerOption(\n                    {\n                        .name = \"option\",\n                        .short_name = \"o\",\n                        .help = R\"\"\"(\nAn integer option.\n)\"\"\",\n                    },\n                    [&](auto& arg_b) { arg_b.Set(&storage); });\n                sub_b.Do([] {});\n              });\n          b.AddSubcommand(\n              {\n                  .name = \"run\",\n                  .help = R\"\"\"(\nRun wombats across the screen.\n\nThis will cause several wombats to run across your screen.\n)\"\"\",\n                  .help_epilogue = R\"\"\"(\nOr it won't, who knows.\n)\"\"\",\n              },\n              [&](auto& sub_b) {\n                sub_b.AddStringOption(\n                    {\n                        .name = \"option\",\n                        .short_name = \"o\",\n                        .help = R\"\"\"(\nA string option.\n)\"\"\",\n                    },\n                    [&](auto& arg_b) { arg_b.Set(&string); });\n                sub_b.AddOneOfOption(\n                    {\n                        .name = \"one-of-option\",\n                        .help = R\"\"\"(\nA one-of option.\n)\"\"\",\n                    },\n                    [&](auto& arg_b) {\n                      arg_b.SetOneOf(\n                          {\n                              arg_b.OneOfValue(\"x\", 1),\n                              arg_b.OneOfValue(\"y\", 2),\n                              arg_b.OneOfValue(\"z\", 3),\n                          },\n                          &storage);\n                    });\n                sub_b.Do([] {});\n              });\n          b.AddSubcommand(\n              {\n                  .name = \"hidden\",\n                  .help = R\"\"\"(\nA hidden subcommand.\n)\"\"\",\n              },\n              [&](auto& sub_b) {\n                sub_b.HelpHidden(true);\n                sub_b.Do([] {});\n              });\n          b.RequiresSubcommand();\n        });\n  };\n\n  RawStringOstream os;\n\n  EXPECT_THAT(parse({\"--flag\", \"--help\"}, os),\n              IsSuccess(Eq(ParseResult::MetaSuccess)));\n  std::string help_flag_output = os.TakeStr();\n  EXPECT_THAT(help_flag_output, StrEq(llvm::StringRef(R\"\"\"(\nTest Command -- version 1.2.3\n\nA test command.\n\nLots more information about the test command.\n\nBuild info:\n  Build timestamp: )\"\"\" __TIMESTAMP__ R\"\"\"(\n  Build config: test-config-info\n\nUsage:\n  test [-f] edit [--option=...]\n  test [-f] run [OPTIONS]\n\nSubcommands:\n  edit\n          Edit the widget.\n\n          This will take the provided widgets and edit them.\n\n  run\n          Run wombats across the screen.\n\n          This will cause several wombats to run across your screen.\n\n  help\n          Prints help information for the command, including a description, command line usage, and details of each subcommand and option that can be provided.\n\n  version\n          Prints the version of this command.\n\nCommand options:\n  -f, --flag\n          A boolean flag.\n\nClosing remarks.\n\n)\"\"\")\n                                          .ltrim('\\n')));\n  EXPECT_THAT(parse({\"help\"}, os), IsSuccess(Eq(ParseResult::MetaSuccess)));\n  EXPECT_THAT(os.TakeStr(), StrEq(help_flag_output));\n\n  EXPECT_THAT(parse({\"--version\"}, os),\n              IsSuccess(Eq(ParseResult::MetaSuccess)));\n  std::string version_flag_output = os.TakeStr();\n  EXPECT_THAT(version_flag_output, StrEq(llvm::StringRef(R\"\"\"(\nTest Command -- version 1.2.3\n\nBuild timestamp: )\"\"\" __TIMESTAMP__ R\"\"\"(\nBuild config: test-config-info\n)\"\"\")\n                                             .ltrim('\\n')));\n  EXPECT_THAT(parse({\"version\"}, os), IsSuccess(Eq(ParseResult::MetaSuccess)));\n  EXPECT_THAT(os.TakeStr(), StrEq(version_flag_output));\n\n  EXPECT_THAT(parse({\"--flag\", \"edit\", \"--option=42\", \"--help\"}, os),\n              IsSuccess(Eq(ParseResult::MetaSuccess)));\n  std::string edit_help_output = os.TakeStr();\n  EXPECT_THAT(edit_help_output, StrEq(llvm::StringRef(R\"\"\"(\nEdit the widget.\n\nThis will take the provided widgets and edit them.\n\nSubcommand `edit` usage:\n  test [-f] edit [--option=...]\n\nSubcommand `edit` options:\n  -o, --option=...\n          An integer option.\n\n      --help[=(full|short)]\n          Prints help information for the subcommand, including a description, command line usage, and details of each option that can be provided.\n\n          Possible values:\n          - full (default)\n          - short\n\nThat's all.\n\n)\"\"\")\n                                          .ltrim('\\n')));\n\n  EXPECT_THAT(parse({\"help\", \"edit\"}, os),\n              IsSuccess(Eq(ParseResult::MetaSuccess)));\n  EXPECT_THAT(os.TakeStr(), StrEq(edit_help_output));\n\n  EXPECT_THAT(parse({\"--flag\", \"run\", \"--option=abc\", \"--help\"}, os),\n              IsSuccess(Eq(ParseResult::MetaSuccess)));\n  std::string run_help_output = os.TakeStr();\n  EXPECT_THAT(run_help_output, StrEq(llvm::StringRef(R\"\"\"(\nRun wombats across the screen.\n\nThis will cause several wombats to run across your screen.\n\nSubcommand `run` usage:\n  test [-f] run [OPTIONS]\n\nSubcommand `run` options:\n  -o, --option=...\n          A string option.\n\n      --one-of-option=(x|y|z)\n          A one-of option.\n\n          Possible values:\n          - x\n          - y\n          - z\n\n      --help[=(full|short)]\n          Prints help information for the subcommand, including a description, command line usage, and details of each option that can be provided.\n\n          Possible values:\n          - full (default)\n          - short\n\nOr it won't, who knows.\n\n)\"\"\")\n                                         .ltrim('\\n')));\n\n  EXPECT_THAT(parse({\"help\", \"run\"}, os),\n              IsSuccess(Eq(ParseResult::MetaSuccess)));\n  EXPECT_THAT(os.TakeStr(), StrEq(run_help_output));\n}\n\nTEST(ArgParserTest, HelpMarkdownLike) {\n  bool flag = false;\n  auto parse = [&](llvm::ArrayRef<llvm::StringRef> args, llvm::raw_ostream& s) {\n    return Parse(  // Force line break.\n        args, s, {.name = \"test\"}, [&](auto& b) {\n          b.AddFlag(\n              {\n                  .name = \"flag\",\n                  .help = R\"\"\"(\nA boolean flag.\n\n    Preformatted\n        code....\n        ........\n\nBut\n  here\n    lines\n      are\n        collapsed.\n\n```\nx\n y\n  z\n```\n)\"\"\",\n              },\n              [&](auto& arg_b) { arg_b.Set(&flag); });\n          b.Do([] {});\n        });\n  };\n\n  RawStringOstream os;\n  EXPECT_THAT(parse({\"--help\"}, os), IsSuccess(Eq(ParseResult::MetaSuccess)));\n  EXPECT_THAT(os.TakeStr(), StrEq(llvm::StringRef(R\"\"\"(\nUsage:\n  test [--flag]\n\nOptions:\n      --flag\n          A boolean flag.\n\n              Preformatted\n                  code....\n                  ........\n\n          But here lines are collapsed.\n\n          ```\n          x\n           y\n            z\n          ```\n\n      --help[=(full|short)]\n          Prints help information for the command, including a description, command line usage, and details of each option that can be provided.\n\n          Possible values:\n          - full (default)\n          - short\n\n)\"\"\")\n                                      .ltrim('\\n')));\n}\n\n}  // namespace\n}  // namespace Carbon::CommandLine\n"
  },
  {
    "path": "common/concepts.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_CONCEPTS_H_\n#define CARBON_COMMON_CONCEPTS_H_\n\n#include <concepts>\n\nnamespace Carbon {\n\n// True if `T` is the same as one of `OtherT`.\ntemplate <typename T, typename... OtherT>\nconcept SameAsOneOf = (std::same_as<T, OtherT> || ...);\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_CONCEPTS_H_\n"
  },
  {
    "path": "common/emplace_by_calling.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_EMPLACE_BY_CALLING_H_\n#define CARBON_COMMON_EMPLACE_BY_CALLING_H_\n\n#include <type_traits>\n#include <utility>\n\nnamespace Carbon {\n\n// A utility to use when calling an `emplace` function to emplace the result of\n// a function call. Expected usage is:\n//\n//   my_widget_vec.emplace_back(EmplaceByCalling([&] {\n//     return ConstructAWidget(...);\n//   }));\n//\n// In this example, the result of `ConstructAWidget` will be constructed\n// directly into the new element of `my_widget_vec`, without performing a copy\n// or move.\n//\n// Note that the type of the argument to `emplace_back` is an `EmplaceByCalling`\n// instance, not the type `DestT` stored in the container. When the `DestT`\n// instance is eventually initialized directly from the `EmplaceByCalling`, a\n// conversion function on `EmplaceByCalling` is used that converts to the type\n// `DestT` being emplaced. This `DestT` initialization does not call an\n// additional `DestT` copy or move constructor to initialize the result, and\n// instead initializes it in-place in the container's storage, per the C++17\n// guaranteed copy elision rules. Similarly, within the conversion function, the\n// result is initialized directly by calling `make_fn`, again relying on\n// guaranteed copy elision.\n//\n// Because the make function is called from the conversion function,\n// `EmplaceByCalling` should only be used in contexts where it will be used to\n// initialize a `DestT` object exactly once. This is generally true of `emplace`\n// functions. Also, because the `make_fn` callback will be called after the\n// container has made space for the new element, it should not inspect or modify\n// the container that is being emplaced into.\ntemplate <typename MakeFnT>\nclass EmplaceByCalling {\n public:\n  explicit(false) EmplaceByCalling(MakeFnT make_fn)\n      : make_fn_(std::move(make_fn)) {}\n\n  // Convert to the exact return type of the make function, by calling the make\n  // function to construct the result. No implicit conversions are permitted\n  // here, as that would mean we are not constructing the result in place.\n  template <typename DestT>\n    requires std::same_as<DestT, std::invoke_result_t<MakeFnT&&>>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  explicit(false) operator DestT() && {\n    return std::move(make_fn_)();\n  }\n\n private:\n  MakeFnT make_fn_;\n};\n\ntemplate <typename MakeFnT>\nEmplaceByCalling(MakeFnT) -> EmplaceByCalling<MakeFnT>;\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_EMPLACE_BY_CALLING_H_\n"
  },
  {
    "path": "common/emplace_by_calling_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/emplace_by_calling.h\"\n\n#include <gtest/gtest.h>\n\n#include <list>\n\nnamespace Carbon {\nnamespace {\n\nstruct NoncopyableType {\n  NoncopyableType() = default;\n  NoncopyableType(const NoncopyableType&) = delete;\n  auto operator=(const NoncopyableType&) -> NoncopyableType& = delete;\n};\n\nauto Make() -> NoncopyableType { return NoncopyableType(); }\n\nTEST(EmplaceByCalling, Noncopyable) {\n  std::list<NoncopyableType> list;\n  // This should compile.\n  list.emplace_back(EmplaceByCalling(Make));\n}\n\nTEST(EmplaceByCalling, NoncopyableInAggregate) {\n  struct Aggregate {\n    int a, b, c;\n    NoncopyableType noncopyable;\n  };\n\n  std::list<Aggregate> list;\n  // This should compile.\n  list.emplace_back(EmplaceByCalling(\n      [] { return Aggregate{.a = 1, .b = 2, .c = 3, .noncopyable = Make()}; }));\n}\n\nclass CopyCounter {\n public:\n  explicit CopyCounter(int* counter) : counter_(counter) {}\n  CopyCounter(const CopyCounter& other) : counter_(other.counter_) {\n    ++*counter_;\n  }\n\n private:\n  int* counter_;\n};\n\nTEST(EmplaceByCalling, NoCopies) {\n  std::vector<CopyCounter> vec;\n  vec.reserve(10);\n  int copies = 0;\n  for (int i = 0; i != 10; ++i) {\n    vec.emplace_back(EmplaceByCalling([&] { return CopyCounter(&copies); }));\n  }\n  EXPECT_EQ(0, copies);\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/enum_base.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_ENUM_BASE_H_\n#define CARBON_COMMON_ENUM_BASE_H_\n\n#include <compare>\n#include <type_traits>\n\n#include \"common/ostream.h\"\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon::Internal {\n\n// CRTP-style base class used to define the common pattern of Carbon enum-like\n// classes. The result is a class with named constants similar to enumerators,\n// but that are normal classes, can contain other methods, and support a `name`\n// method and printing the enums. These even work in switch statements and\n// support `case MyEnum::Name:`.\n//\n// It is specifically designed to compose with X-MACRO style `.def` files that\n// stamp out all the enumerators.\n//\n// Users must be in the `Carbon` namespace and should look like the following.\n//\n// In `my_kind.h`:\n//   ```\n//   CARBON_DEFINE_RAW_ENUM_CLASS(MyKind, uint8_t) {\n//   #define CARBON_MY_KIND(Name) CARBON_RAW_ENUM_ENUMERATOR(Name)\n//   #include \".../my_kind.def\"\n//   };\n//\n//   class MyKind : public CARBON_ENUM_BASE(MyKind) {\n//    public:\n//   #define CARBON_MY_KIND(Name) CARBON_ENUM_CONSTANT_DECL(Name)\n//   #include \".../my_kind.def\"\n//\n//     // OPTIONAL: To support converting to and from the underlying type of\n//     // the enumerator, add these lines:\n//     using EnumBase::AsInt;\n//     using EnumBase::FromInt;\n//\n//     // OPTIONAL: To expose the ability to create an instance from the raw\n//     // enumerator (for unusual use cases), add this:\n//     using EnumBase::Make;\n//\n//     // Plus, anything else you wish to include.\n//   };\n//\n//   #define CARBON_MY_KIND(Name) CARBON_ENUM_CONSTANT_DEFINITION(MyKind, Name)\n//   #include \".../my_kind.def\"\n//   ```\n//\n// In `my_kind.cpp`:\n//   ```\n//   CARBON_DEFINE_ENUM_CLASS_NAMES(MyKind) {\n//   #define CARBON_MY_KIND(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)\n//   #include \".../my_kind.def\"\n//   };\n//   ```\n//\n// The result of the above:\n// - An enum class (`RawEnumType`) defined in an `Internal` namespace with one\n//   enumerator per call to CARBON_MY_KIND(Name) in `.../my_kind.def`, with name\n//   `Name`. This won't generally be used directly, but may be needed for niche\n//   use cases such as a template argument.\n// - A type `MyKind` that extends `Carbon::Internal::EnumBase`.\n//   - `MyKind` includes all the public members of `EnumBase`, like `name` and\n//     `Print`. For example, you might call `name()` to construct an error\n//     message:\n//     ```\n//     auto ErrorMessage(MyKind k) -> std::string {\n//       return k.name() + \" not found\";\n//     }\n//     ```\n//   - `MyKind` includes all protected members of `EnumBase`, like `AsInt`,\n//     `FromInt`. They will be part of the public API of `EnumBase` if they\n//     were included in a `using` declaration.\n//   - `MyKind` includes a member `static const MyKind Name;` per call to\n//     `CARBON_MY_KIND(Name)` in `.../my_kind.def`. It will have the\n//     corresponding value from `RawEnumType`. This is the primary way to create\n//     an instance of `MyKind`. For example, it might be used like:\n//     ```\n//     ErrorMessage(MyKind::Name1);\n//     ```\n//   - `MyKind` includes an implicit conversion to the `RawEnumType`, returning\n//     the value of a private field in `EnumBase`. This is used when writing a\n//     `switch` statement, as in this example:\n//     ```\n//     auto MyFunction(MyKind k) -> void {\n//       // Implicitly converts `k` and every `case` expression to\n//       // `RawEnumType`:\n//       switch (k) {\n//         case MyKind::Name1:\n//           // ...\n//           break;\n//\n//         case MyKind::Name2:\n//           // ...\n//           break;\n//\n//         // No `default` case needed if the above cases are exhaustive.\n//         // Prefer no `default` case when possible, to get an error if\n//         // a case is skipped.\n//       }\n//     }\n//     ```\n//\ntemplate <typename DerivedT, typename EnumT, const llvm::StringLiteral Names[]>\nclass EnumBase : public Printable<DerivedT> {\n public:\n  // An alias for the raw enum type. This is an implementation detail and\n  // should rarely be used directly, only when an actual enum type is needed.\n  using RawEnumType = EnumT;\n\n  using EnumType = DerivedT;\n  using UnderlyingType = std::underlying_type_t<RawEnumType>;\n\n  // Enable conversion to the raw enum type, including in a `constexpr` context,\n  // to enable comparisons and usage in `switch` and `case`. The enum type\n  // remains an implementation detail and nothing else should be using this\n  // function.\n  //\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  explicit(false) constexpr operator RawEnumType() const { return value_; }\n\n  // Conversion to bool is deleted to prevent direct use in an `if` condition\n  // instead of comparing with another value.\n  explicit operator bool() const = delete;\n\n  // Returns the name of this value.\n  auto name() const -> llvm::StringRef { return Names[AsInt()]; }\n\n  // Prints this value using its name.\n  auto Print(llvm::raw_ostream& out) const -> void { out << name(); }\n\n  // Don't support comparison of enums by default.\n  friend auto operator<(DerivedT lhs, DerivedT rhs) -> bool = delete;\n  friend auto operator<=(DerivedT lhs, DerivedT rhs) -> bool = delete;\n  friend auto operator>(DerivedT lhs, DerivedT rhs) -> bool = delete;\n  friend auto operator>=(DerivedT lhs, DerivedT rhs) -> bool = delete;\n  friend auto operator<=>(DerivedT lhs, DerivedT rhs)\n      -> std::partial_ordering = delete;\n\n protected:\n  // The default constructor is explicitly defaulted (and constexpr) as a\n  // protected constructor to allow derived classes to be constructed but not\n  // the base itself. This should only be used in the `Make` function below.\n  constexpr EnumBase() = default;\n\n  // Create an instance from the raw enumerator. Mainly used internally, but may\n  // be exposed for unusual use cases.\n  static constexpr auto Make(RawEnumType value) -> EnumType {\n    EnumType result;\n    result.value_ = value;\n    return result;\n  }\n\n  // Convert to the underlying integer type. Derived types can choose to expose\n  // this as part of their API.\n  constexpr auto AsInt() const -> UnderlyingType {\n    return static_cast<UnderlyingType>(value_);\n  }\n\n  // Convert from the underlying integer type. Derived types can choose to\n  // expose this as part of their API.\n  static constexpr auto FromInt(UnderlyingType value) -> EnumType {\n    return Make(static_cast<RawEnumType>(value));\n  }\n\n private:\n  template <typename MaskDerivedT, typename MaskEnumT,\n            const llvm::StringLiteral MaskNames[]>\n  friend class EnumMaskBase;\n\n  RawEnumType value_;\n};\n\n}  // namespace Carbon::Internal\n\n// Use this before defining a class that derives from `EnumBase` to begin the\n// definition of the raw `enum class`. It should be followed by the body of that\n// raw enum class.\n#define CARBON_DEFINE_RAW_ENUM_CLASS(EnumClassName, UnderlyingType) \\\n  namespace Internal {                                              \\\n  struct EnumClassName##Data {                                      \\\n    static const llvm::StringLiteral Names[];                       \\\n    enum class RawEnum : UnderlyingType;                            \\\n  };                                                                \\\n  }                                                                 \\\n  enum class Internal::EnumClassName##Data::RawEnum : UnderlyingType\n\n// In the `CARBON_DEFINE_RAW_ENUM_CLASS` block, use this to generate each\n// enumerator.\n#define CARBON_RAW_ENUM_ENUMERATOR(Name) Name,\n\n// Use this to compute the `Internal::EnumBase` specialization for a Carbon enum\n// class. It both computes the name of the raw enum and ensures all the\n// namespaces are correct.\n#define CARBON_ENUM_BASE(EnumClassName)                                \\\n  ::Carbon::Internal::EnumBase<EnumClassName,                          \\\n                               Internal::EnumClassName##Data::RawEnum, \\\n                               Internal::EnumClassName##Data::Names>\n\n// Use this within the Carbon enum class body to generate named constant\n// declarations for each value.\n#define CARBON_ENUM_CONSTANT_DECL(Name) static const EnumType Name;\n\n// Use this immediately after the Carbon enum class body to define each named\n// constant.\n#define CARBON_ENUM_CONSTANT_DEFINITION(EnumClassName, Name) \\\n  inline constexpr EnumClassName EnumClassName::Name =       \\\n      EnumClassName::Make(RawEnumType::Name);\n\n// Use this in the `.cpp` file for an enum class to start the definition of the\n// constant names array for each enumerator. It is followed by the desired\n// constant initializer.\n//\n// `clang-format` has a bug with spacing around `->` returns in macros. See\n// https://bugs.llvm.org/show_bug.cgi?id=48320 for details.\n#define CARBON_DEFINE_ENUM_CLASS_NAMES(EnumClassName) \\\n  constexpr llvm::StringLiteral Internal::EnumClassName##Data::Names[] =\n\n// Use this within the names array initializer to generate a string for each\n// name.\n#define CARBON_ENUM_CLASS_NAME_STRING(Name) #Name,\n\n#endif  // CARBON_COMMON_ENUM_BASE_H_\n"
  },
  {
    "path": "common/enum_base_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/enum_base.h\"\n\n#include <gtest/gtest.h>\n\n#include \"common/raw_string_ostream.h\"\n\nnamespace Carbon {\nnamespace {\n\n// These are directly in the Carbon namespace because the defines require it.\nCARBON_DEFINE_RAW_ENUM_CLASS(TestKind, uint8_t) {\n#define CARBON_ENUM_BASE_TEST_KIND(Name) CARBON_RAW_ENUM_ENUMERATOR(Name)\n#include \"common/enum_base_test.def\"\n};\n\nclass TestKind : public CARBON_ENUM_BASE(TestKind) {\n public:\n#define CARBON_ENUM_BASE_TEST_KIND(Name) CARBON_ENUM_CONSTANT_DECL(Name)\n#include \"common/enum_base_test.def\"\n\n  using EnumBase::AsInt;\n  using EnumBase::FromInt;\n};\n\n#define CARBON_ENUM_BASE_TEST_KIND(Name) \\\n  CARBON_ENUM_CONSTANT_DEFINITION(TestKind, Name)\n#include \"common/enum_base_test.def\"\n\nCARBON_DEFINE_ENUM_CLASS_NAMES(TestKind) {\n#define CARBON_ENUM_BASE_TEST_KIND(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)\n#include \"common/enum_base_test.def\"\n};\n\nstatic_assert(sizeof(TestKind) == sizeof(uint8_t),\n              \"Class size doesn't match enum size!\");\n\nTEST(EnumBaseTest, NamesAndConstants) {\n  EXPECT_EQ(\"Beep\", TestKind::Beep.name());\n  EXPECT_EQ(\"Boop\", TestKind::Boop.name());\n  EXPECT_EQ(\"Burr\", TestKind::Burr.name());\n}\n\nTEST(EnumBaseTest, Printing) {\n  RawStringOstream stream;\n\n  TestKind kind = TestKind::Beep;\n  stream << kind << \" \" << TestKind::Beep;\n  kind = TestKind::Boop;\n  stream << \" \" << kind;\n\n  // Check the streamed results and also make sure we can stream into GoogleTest\n  // assertions.\n  EXPECT_EQ(\"Beep Beep Boop\", stream.TakeStr()) << \"Final kind: \" << kind;\n}\n\nTEST(EnumBaseTest, Switch) {\n  TestKind kind = TestKind::Boop;\n\n  switch (kind) {\n    case TestKind::Beep: {\n      FAIL() << \"Beep case selected!\";\n      break;\n    }\n    case TestKind::Boop: {\n      EXPECT_EQ(\"Boop\", kind.name());\n      break;\n    }\n    case TestKind::Burr: {\n      FAIL() << \"Burr case selected!\";\n      break;\n    }\n  }\n}\n\nTEST(EnumBaseTest, Comparison) {\n  TestKind kind = TestKind::Beep;\n\n  // Make sure all the different comparisons work, and also work with\n  // GoogleTest expectations.\n  EXPECT_EQ(TestKind::Beep, kind);\n  EXPECT_NE(TestKind::Boop, kind);\n\n  // These should also all be constexpr.\n  constexpr TestKind Kind2 = TestKind::Beep;\n  static_assert(Kind2 == TestKind::Beep);\n  static_assert(Kind2 != TestKind::Boop);\n}\n\nTEST(EnumBaseTest, IntConversion) {\n  EXPECT_EQ(0, TestKind::Beep.AsInt());\n  EXPECT_EQ(1, TestKind::Boop.AsInt());\n  EXPECT_EQ(2, TestKind::Burr.AsInt());\n\n  EXPECT_EQ(TestKind::Beep, TestKind::FromInt(0));\n  EXPECT_EQ(TestKind::Boop, TestKind::FromInt(1));\n  EXPECT_EQ(TestKind::Burr, TestKind::FromInt(2));\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/enum_base_test.def",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// Note that this is an X-macro header. It does not use `#include` guards, and\n// instead is designed to be `#include`ed after the x-macro is defined in order\n// for its inclusion to expand to the desired output.\n\n#ifndef CARBON_ENUM_BASE_TEST_KIND\n#error \"Must define the x-macro to use this file.\"\n#define CARBON_ENUM_BASE_TEST_KIND(Name)\n#endif\n\nCARBON_ENUM_BASE_TEST_KIND(Beep)\nCARBON_ENUM_BASE_TEST_KIND(Boop)\nCARBON_ENUM_BASE_TEST_KIND(Burr)\n\n#undef CARBON_ENUM_BASE_TEST_KIND\n"
  },
  {
    "path": "common/enum_mask_base.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_ENUM_MASK_BASE_H_\n#define CARBON_COMMON_ENUM_MASK_BASE_H_\n\n#include <bit>\n\n#include \"common/enum_base.h\"\n#include \"llvm/ADT/StringExtras.h\"\n\nnamespace Carbon::Internal {\n\n// CRTP-style base class similar to `EnumBase`, but supporting mask enums.\n// Enumerator values are consecutive bit shifts (1 << 0, 1 << 1, 1 << 2, 1 << 3,\n// ...).\n//\n// Users must be in the `Carbon` namespace and should look like the following.\n//\n// In `my_kind.h`:\n//   ```\n//   #define CARBON_MY_KIND(X) \\\n//       X(Enumerator1)        \\\n//       X(Enumerator2)        \\\n//       X(Enumerator3)        \\\n//       ...\n//\n//   CARBON_DEFINE_RAW_ENUM_MASK(MyKind, uint32_t) {\n//     CARBON_MY_KIND(CARBON_RAW_ENUM_MASK_ENUMERATOR)\n//   };\n//\n//   class MyKind : public CARBON_ENUM_MASK_BASE(MyKind) {\n//    public:\n//     CARBON_MY_KIND(CARBON_ENUM_MASK_CONSTANT_DECL)\n//\n//     // Plus, anything else you wish to include.\n//   };\n//\n//   #define CARBON_MY_KIND_WITH_TYPE(X) \\\n//     CARBON_ENUM_MASK_CONSTANT_DEFINITION(MyKind, X)\n//   CARBON_MY_KIND(CARBON_MY_KIND_WITH_TYPE)\n//   #undef CARBON_MY_KIND_WITH_TYPE\n//   ```\n//\n// In `my_kind.cpp`:\n//   ```\n//   CARBON_DEFINE_ENUM_MASK_NAMES(MyKind) {\n//     CARBON_MY_KIND(CARBON_ENUM_MASK_NAME_STRING)\n//   };\n//   ```\ntemplate <typename DerivedT, typename EnumT, const llvm::StringLiteral Names[]>\nclass EnumMaskBase : public EnumBase<DerivedT, EnumT, Names> {\n public:\n  // Provide a standard `None`.\n  //\n  // This uses a `&` to trigger slightly different instantiation behaviors in\n  // Clang. For context on why this is needed, see http://wg21.link/CWG2800.\n  // NOLINTNEXTLINE(readability-identifier-naming)\n  static const DerivedT& None;\n\n  // Returns true if there's a non-empty set intersection.\n  constexpr auto HasAnyOf(DerivedT other) const -> bool {\n    return !(*this & other).empty();\n  }\n\n  // Adds entries to the mask.\n  auto Add(DerivedT other) -> void { *this = *this | other; }\n\n  // Removes entries from the mask.\n  auto Remove(DerivedT other) -> void { *this = *this & ~other; }\n\n  constexpr auto empty() const -> bool { return this->AsInt() == 0; }\n\n  constexpr auto operator|(DerivedT other) const -> DerivedT {\n    return DerivedT::FromInt(this->AsInt() | other.AsInt());\n  }\n\n  constexpr auto operator&(DerivedT other) const -> DerivedT {\n    return DerivedT::FromInt(this->AsInt() & other.AsInt());\n  }\n\n  constexpr auto operator~() const -> DerivedT {\n    return DerivedT::FromInt(~this->AsInt());\n  }\n\n  // Use `Print` for mask entries. This hides `EnumBase::name`; it's not\n  // compatible with `EnumMaskBase`.\n  auto name() const -> llvm::StringRef = delete;\n\n  // Prints this value as a `|`-separated list of mask entries, or `None`.\n  //\n  // This shadows EnumBase::Print.\n  auto Print(llvm::raw_ostream& out) const -> void {\n    int value = this->AsInt();\n    if (value == 0) {\n      out << \"None\";\n      return;\n    }\n    llvm::ListSeparator sep(\"|\");\n    for (int bit = 0; value != 0; value >>= 1, ++bit) {\n      if (value & 1) {\n        out << sep << Names[bit];\n      }\n    }\n  }\n};\n\ntemplate <typename DerivedT, typename EnumT, const llvm::StringLiteral Names[]>\nconstexpr const DerivedT& EnumMaskBase<DerivedT, EnumT, Names>::None =\n    DerivedT::FromInt(0);\n\n}  // namespace Carbon::Internal\n\n// Use this before defining a class that derives from `EnumMaskBase` to begin\n// the definition of the raw `enum class`. It should be followed by the body of\n// that raw enum class.\n#define CARBON_DEFINE_RAW_ENUM_MASK(EnumMaskName, UnderlyingType)              \\\n  namespace Internal {                                                         \\\n  struct EnumMaskName##Data {                                                  \\\n    static const llvm::StringLiteral Names[];                                  \\\n    /* For bit shifts, track the initial counter value. This will increment on \\\n     * each enum entry. */                                                     \\\n    static constexpr uint64_t BitShiftCounter = __COUNTER__ + 1;               \\\n    enum class RawEnum : UnderlyingType;                                       \\\n  };                                                                           \\\n  }                                                                            \\\n  enum class Internal::EnumMaskName##Data::RawEnum : UnderlyingType\n\n// In the `CARBON_DEFINE_RAW_ENUM_MASK` block, use this to generate each\n// enumerator.\n#define CARBON_RAW_ENUM_MASK_ENUMERATOR(Name) \\\n  Name = 1 << (__COUNTER__ - BitShiftCounter),\n\n// Use this to compute the `Internal::EnumMaskBase` specialization for a Carbon\n// enum mask. It both computes the name of the raw enum and ensures all the\n// namespaces are correct.\n#define CARBON_ENUM_MASK_BASE(EnumMaskName)                               \\\n  ::Carbon::Internal::EnumMaskBase<EnumMaskName,                          \\\n                                   Internal::EnumMaskName##Data::RawEnum, \\\n                                   Internal::EnumMaskName##Data::Names>\n\n// Constants and names are declared equivalently as to `EnumBase`.\n#define CARBON_ENUM_MASK_CONSTANT_DECL(Name) CARBON_ENUM_CONSTANT_DECL(Name)\n#define CARBON_ENUM_MASK_CONSTANT_DEFINITION(EnumMaskName, Name) \\\n  CARBON_ENUM_CONSTANT_DEFINITION(EnumMaskName, Name)\n#define CARBON_DEFINE_ENUM_MASK_NAMES(EnumMaskName) \\\n  CARBON_DEFINE_ENUM_CLASS_NAMES(EnumMaskName)\n#define CARBON_ENUM_MASK_NAME_STRING(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)\n\n#endif  // CARBON_COMMON_ENUM_MASK_BASE_H_\n"
  },
  {
    "path": "common/enum_mask_base_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/enum_mask_base.h\"\n\n#include <gtest/gtest.h>\n\n#include \"common/raw_string_ostream.h\"\n\nnamespace Carbon {\nnamespace {\n\n#define CARBON_TEST_KIND(X) \\\n  X(Beep)                   \\\n  X(Boop)                   \\\n  X(Burr)\n\nCARBON_DEFINE_RAW_ENUM_MASK(TestKind, uint8_t) {\n  CARBON_TEST_KIND(CARBON_RAW_ENUM_MASK_ENUMERATOR)\n};\n\nclass TestKind : public CARBON_ENUM_MASK_BASE(TestKind) {\n public:\n  CARBON_TEST_KIND(CARBON_ENUM_MASK_CONSTANT_DECL)\n\n  using EnumMaskBase::AsInt;\n  using EnumMaskBase::FromInt;\n};\n\n#define CARBON_TEST_KIND_WITH_TYPE(X) \\\n  CARBON_ENUM_MASK_CONSTANT_DEFINITION(TestKind, X)\nCARBON_TEST_KIND(CARBON_TEST_KIND_WITH_TYPE)\n#undef CARBON_TEST_KIND_WITH_TYPE\n\nCARBON_DEFINE_ENUM_MASK_NAMES(TestKind) {\n  CARBON_TEST_KIND(CARBON_ENUM_MASK_NAME_STRING)\n};\n\nstatic_assert(sizeof(TestKind) == sizeof(uint8_t),\n              \"Class size doesn't match enum size!\");\n\nTEST(EnumMaskBaseTest, Printing) {\n  RawStringOstream stream;\n\n  TestKind kind = TestKind::Beep;\n  stream << kind;\n  EXPECT_EQ(\"Beep\", stream.TakeStr());\n\n  kind = TestKind::Boop;\n  stream << kind;\n  EXPECT_EQ(\"Boop\", stream.TakeStr());\n\n  stream << TestKind::Beep;\n  EXPECT_EQ(\"Beep\", stream.TakeStr());\n\n  stream << (TestKind::Beep | TestKind::Burr);\n  EXPECT_EQ(\"Beep|Burr\", stream.TakeStr());\n}\n\n// This just ensures it compiles, it's not validating what's printed.\nTEST(EnumMaskBaseTest, PrintToGoogletest) {\n  EXPECT_TRUE(true) << TestKind::Beep;\n}\n\nTEST(EnumMaskBaseTest, Switch) {\n  TestKind kind = TestKind::Boop;\n\n  switch (kind) {\n    case TestKind::Beep: {\n      FAIL() << \"Beep case selected!\";\n      break;\n    }\n    case TestKind::Boop: {\n      EXPECT_EQ(kind, TestKind::Boop);\n      break;\n    }\n    case TestKind::Burr: {\n      FAIL() << \"Burr case selected!\";\n      break;\n    }\n  }\n}\n\nTEST(EnumMaskBaseTest, Equality) {\n  TestKind kind = TestKind::Beep;\n\n  // Make sure all the different comparisons work, and also work with\n  // GoogleTest expectations.\n  EXPECT_EQ(TestKind::Beep, kind);\n  EXPECT_NE(TestKind::Boop, kind);\n\n  // These should also all be constexpr.\n  constexpr TestKind Kind2 = TestKind::Beep;\n  static_assert(Kind2 == TestKind::Beep);\n  static_assert(Kind2 != TestKind::Boop);\n}\n\nTEST(EnumMaskBaseTest, AddRemove) {\n  TestKind kind = TestKind::Beep;\n  EXPECT_EQ(kind, TestKind::Beep);\n  kind.Add(TestKind::Beep);\n  EXPECT_EQ(kind, TestKind::Beep);\n  kind.Add(TestKind::Burr);\n  EXPECT_EQ(kind, TestKind::Beep | TestKind::Burr);\n  kind.Remove(TestKind::Beep);\n  EXPECT_EQ(kind, TestKind::Burr);\n  kind.Remove(TestKind::Beep);\n  EXPECT_EQ(kind, TestKind::Burr);\n  kind.Remove(TestKind::Burr);\n  EXPECT_EQ(kind, TestKind::None);\n}\n\nTEST(EnumMaskBaseTest, HasAnyOf) {\n  static_assert(TestKind::Beep.HasAnyOf(TestKind::Beep));\n  static_assert(TestKind::Beep.HasAnyOf(TestKind::Beep | TestKind::Burr));\n  static_assert(!TestKind::Beep.HasAnyOf(TestKind::Burr));\n}\n\nTEST(EnumMaskBaseTest, MaskOperations) {\n  TestKind kind =\n      TestKind::Beep | (TestKind::Burr & (TestKind::Burr | TestKind::Beep));\n  EXPECT_EQ(kind, TestKind::Beep | TestKind::Burr);\n\n  // These should also all be constexpr.\n  static_assert((TestKind::Beep & TestKind::Burr) == TestKind::None);\n  static_assert((TestKind::Beep | TestKind::Burr) != TestKind::None);\n  static_assert(TestKind::Beep == ~~TestKind::Beep);\n}\n\nTEST(EnumMaskBaseTest, IntConversion) {\n  EXPECT_EQ(1, TestKind::Beep.AsInt());\n  EXPECT_EQ(2, TestKind::Boop.AsInt());\n  EXPECT_EQ(4, TestKind::Burr.AsInt());\n\n  EXPECT_EQ(TestKind::Beep, TestKind::FromInt(1));\n  EXPECT_EQ(TestKind::Boop, TestKind::FromInt(2));\n  EXPECT_EQ(TestKind::Burr, TestKind::FromInt(4));\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/error.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_ERROR_H_\n#define CARBON_COMMON_ERROR_H_\n\n#include <concepts>\n#include <functional>\n#include <string>\n#include <type_traits>\n#include <utility>\n#include <variant>\n\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/ADT/Twine.h\"\n\nnamespace Carbon {\n\n// Success values should be represented as the presence of a value in ErrorOr,\n// using `ErrorOr<Success>` and `return Success();` if no value needs to be\n// returned.\nstruct Success : public Printable<Success> {\n  auto Print(llvm::raw_ostream& out) const -> void { out << \"Success\"; }\n};\n\n// Tracks an error message.\n//\n// This is nodiscard to enforce error handling prior to destruction.\nclass [[nodiscard]] Error : public Printable<Error> {\n public:\n  // Represents an error state.\n  explicit Error(llvm::Twine message) : message_(message.str()) {\n    CARBON_CHECK(!message_.empty(), \"Errors must have a message.\");\n  }\n\n  // Move-only.\n  Error(Error&& other) noexcept = default;\n  auto operator=(Error&& other) noexcept -> Error& = default;\n\n  // Prints the error string.\n  auto Print(llvm::raw_ostream& out) const -> void { out << message(); }\n\n  // Returns the error message.\n  auto message() const -> const std::string& { return message_; }\n\n private:\n  // The error message.\n  std::string message_;\n};\n\n// A common base class that custom error types should derive from.\n//\n// This combines the ability to be printed with the ability to convert the error\n// to a string and in turn to a non-customized `Error` type by rendering into a\n// string.\n//\n// The goal is that custom error types can be used for errors that are common\n// and/or would have cost to fully render the error message to a string. A\n// custom type can then be used to allow custom, light-weight handling of errors\n// when appropriate. But to avoid these custom types being excessively viral, we\n// ensure they can be converted to normal `Error` types when needed by rendering\n// fully to a string.\ntemplate <typename ErrorT>\nclass [[nodiscard]] ErrorBase : public Printable<ErrorT> {\n public:\n  ErrorBase(const ErrorBase&) = delete;\n  auto operator=(const ErrorBase&) -> ErrorBase& = delete;\n\n  auto ToString() const -> std::string {\n    RawStringOstream os;\n    static_cast<const ErrorT*>(this)->Print(os);\n    return os.TakeStr();\n  }\n  auto ToError() const -> Error { return Error(this->ToString()); }\n\n protected:\n  ErrorBase() = default;\n  ErrorBase(ErrorBase&&) noexcept = default;\n  auto operator=(ErrorBase&&) noexcept -> ErrorBase& = default;\n};\n\n// Holds a value of type `T`, or an `ErrorT` type explaining why the value is\n// unavailable.\n//\n// The `ErrorT` type defaults to `Error` but can be customized where desired\n// with a type that derives from `ErrorBase` above. See the documentation for\n// `ErrorBase` to understand the expected contract of custom error types.\n//\n// This is nodiscard to enforce error handling prior to destruction.\ntemplate <typename T, typename ErrorT = Error>\nclass [[nodiscard]] ErrorOr {\n public:\n  using ValueT = std::remove_reference_t<T>;\n\n  // Check that the custom error type is structured the way we expect. These\n  // need to be `static_assert`s to enable forward declared error types to be\n  // used with `ErrorOr` in function signatures.\n  static_assert(!std::is_reference_v<ErrorT>);\n  static_assert(std::same_as<ErrorT, Error> ||\n                std::derived_from<ErrorT, ErrorBase<ErrorT>>);\n\n  // Constructs with an error; the error must not be Error::Success().\n  // Implicit for easy construction on returns.\n  explicit(false) ErrorOr(ErrorT err) : val_(std::move(err)) {}\n\n  // Constructs from a custom error type derived from `ErrorBase` into an\n  // `ErrorOr` for `Error` to facilitate returning errors transparently.\n  template <typename OtherErrorT>\n    requires(std::same_as<ErrorT, Error> &&\n             std::derived_from<OtherErrorT, ErrorBase<OtherErrorT>>)\n  // Implicit for easy construction on returns.\n  explicit(false) ErrorOr(OtherErrorT other_err) : val_(other_err.ToError()) {}\n\n  // Constructs with any convertible error type, necessary for return statements\n  // that are already converting to the `ErrorOr` wrapper.\n  //\n  // This supports *explicitly* conversions, not just implicit, which is\n  // important to make common patterns of returning and adjusting the error\n  // type without each error type conversion needing to be implicit.\n  template <typename OtherErrorT>\n    requires(std::constructible_from<ErrorT, OtherErrorT> &&\n             std::derived_from<OtherErrorT, ErrorBase<OtherErrorT>>)\n  // Implicit for easy construction on returns.\n  explicit(false) ErrorOr(OtherErrorT other_err)\n      : val_(std::in_place_type<ErrorT>, std::move(other_err)) {}\n\n  // Constructs with a reference.\n  // Implicit for easy construction on returns.\n  explicit(false) ErrorOr(T ref)\n    requires std::is_reference_v<T>\n      : val_(std::ref(ref)) {}\n\n  // Constructs with a value.\n  // Implicit for easy construction on returns.\n  explicit(false) ErrorOr(T val)\n    requires(!std::is_reference_v<T>)\n      : val_(std::move(val)) {}\n\n  // Returns true for success.\n  auto ok() const -> bool { return std::holds_alternative<StoredT>(val_); }\n\n  // Returns the contained error.\n  // REQUIRES: `ok()` is false.\n  auto error() const& -> const ErrorT& {\n    CARBON_CHECK(!ok());\n    return std::get<ErrorT>(val_);\n  }\n  auto error() && -> ErrorT {\n    CARBON_CHECK(!ok());\n    return std::get<ErrorT>(std::move(val_));\n  }\n\n  // Checks that `ok()` is true.\n  // REQUIRES: `ok()` is true.\n  auto Check() const -> void { CARBON_CHECK(ok(), \"{0}\", error()); }\n\n  // Returns the contained value.\n  // REQUIRES: `ok()` is true.\n  [[nodiscard]] auto operator*() & -> ValueT& {\n    Check();\n    return std::get<StoredT>(val_);\n  }\n\n  // Returns the contained value.\n  // REQUIRES: `ok()` is true.\n  [[nodiscard]] auto operator*() const& -> const ValueT& {\n    Check();\n    return std::get<StoredT>(val_);\n  }\n\n  // Returns the contained value.\n  // REQUIRES: `ok()` is true.\n  [[nodiscard]] auto operator*() && -> ValueT&& {\n    Check();\n    return std::get<StoredT>(std::move(val_));\n  }\n\n  // Returns the contained value.\n  // REQUIRES: `ok()` is true.\n  auto operator->() -> ValueT* { return &**this; }\n\n  // Returns the contained value.\n  // REQUIRES: `ok()` is true.\n  auto operator->() const -> const ValueT* { return &**this; }\n\n private:\n  using StoredT = std::conditional_t<std::is_reference_v<T>,\n                                     std::reference_wrapper<ValueT>, T>;\n\n  // Either an error message or a value.\n  std::variant<ErrorT, StoredT> val_;\n};\n\n// A helper class for accumulating error message and converting to\n// `Error` and `ErrorOr<T>`.\nclass ErrorBuilder {\n public:\n  explicit ErrorBuilder() : out_(std::make_unique<RawStringOstream>()) {}\n\n  ErrorBuilder(ErrorBuilder&&) = default;\n  auto operator=(ErrorBuilder&&) -> ErrorBuilder& = default;\n\n  // Accumulates string message to a temporary `ErrorBuilder`. After streaming,\n  // the builder must be converted to an `Error` or `ErrorOr`.\n  template <typename T>\n  auto operator<<(T&& message) && -> ErrorBuilder&& {\n    *out_ << message;\n    return std::move(*this);\n  }\n\n  // Accumulates string message for an lvalue error builder.\n  template <typename T>\n  auto operator<<(T&& message) & -> ErrorBuilder& {\n    *out_ << message;\n    return *this;\n  }\n\n  // NOLINTNEXTLINE(google-explicit-constructor): Implicit cast for returns.\n  explicit(false) operator Error() { return Error(out_->TakeStr()); }\n\n  template <typename T>\n  // NOLINTNEXTLINE(google-explicit-constructor): Implicit cast for returns.\n  explicit(false) operator ErrorOr<T>() {\n    return Error(out_->TakeStr());\n  }\n\n private:\n  std::unique_ptr<RawStringOstream> out_;\n};\n\n}  // namespace Carbon\n\n// Macro hackery to get a unique variable name.\n#define CARBON_MAKE_UNIQUE_NAME_IMPL(a, b, c) a##b##c\n#define CARBON_MAKE_UNIQUE_NAME(a, b, c) CARBON_MAKE_UNIQUE_NAME_IMPL(a, b, c)\n\n// Macro to prevent a top-level comma from being interpreted as a macro\n// argument separator.\n#define CARBON_PROTECT_COMMAS(...) __VA_ARGS__\n\n#define CARBON_RETURN_IF_ERROR_IMPL(unique_name, expr)  \\\n  if (auto unique_name = (expr); !(unique_name).ok()) { \\\n    return std::move(unique_name).error();              \\\n  }\n\n#define CARBON_RETURN_IF_ERROR(expr)                                    \\\n  CARBON_RETURN_IF_ERROR_IMPL(                                          \\\n      CARBON_MAKE_UNIQUE_NAME(_llvm_error_line, __LINE__, __COUNTER__), \\\n      CARBON_PROTECT_COMMAS(expr))\n\n#define CARBON_ASSIGN_OR_RETURN_IMPL(unique_name, var, expr) \\\n  auto unique_name = (expr);                                 \\\n  if (!(unique_name).ok()) {                                 \\\n    return std::move(unique_name).error();                   \\\n  }                                                          \\\n  var = std::move(*(unique_name));\n\n#define CARBON_ASSIGN_OR_RETURN(var, expr)                                 \\\n  CARBON_ASSIGN_OR_RETURN_IMPL(                                            \\\n      CARBON_MAKE_UNIQUE_NAME(_llvm_expected_line, __LINE__, __COUNTER__), \\\n      CARBON_PROTECT_COMMAS(var), CARBON_PROTECT_COMMAS(expr))\n\n#endif  // CARBON_COMMON_ERROR_H_\n"
  },
  {
    "path": "common/error_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/error.h\"\n\n#include <gtest/gtest.h>\n\n#include <concepts>\n#include <memory>\n\n#include \"common/error_test_helpers.h\"\n#include \"common/raw_string_ostream.h\"\n\nnamespace Carbon {\nnamespace {\n\nusing ::Carbon::Testing::IsError;\nusing ::Carbon::Testing::IsSuccess;\nusing ::testing::_;\nusing ::testing::Eq;\nusing ::testing::VariantWith;\n\nTEST(ErrorTest, Error) {\n  Error err(\"test\");\n  EXPECT_EQ(err.message(), \"test\");\n}\n\nTEST(ErrorTest, ErrorEmptyString) {\n  ASSERT_DEATH({ Error err(\"\"); }, \"CHECK failure at\");\n}\n\nauto IndirectError() -> Error { return Error(\"test\"); }\n\nTEST(ErrorTest, IndirectError) { EXPECT_EQ(IndirectError().message(), \"test\"); }\n\nTEST(ErrorTest, ErrorBuilderOperatorImplicitCast) {\n  ErrorOr<int> result = ErrorBuilder() << \"msg\";\n  EXPECT_THAT(result, IsError(\"msg\"));\n}\n\n// Make sure a custom error type can be forward declared and used with `ErrorOr`\n// until the `ErrorOr` is required to be complete itself.\nclass CustomError;\nauto TestFunction() -> ErrorOr<int, CustomError>;\n\nclass CustomError : public ErrorBase<CustomError> {\n public:\n  auto Print(llvm::raw_ostream& os) const -> void {\n    os << \"Custom test error!\";\n  }\n};\n\nauto TestFunction() -> ErrorOr<int, CustomError> { return CustomError(); }\n\nTEST(ErrorTest, UseErrorOrWithCustomError) {\n  // Uses `TestFunction` to ensure it compiles correctly with forward\n  // declarations above.\n  EXPECT_THAT(TestFunction(), IsError(\"Custom test error!\"));\n}\n\ntemplate <typename ErrorT>\nclass ErrorOrTest : public ::testing::Test {\n public:\n  auto ErrorStr() -> std::string {\n    if constexpr (std::same_as<ErrorT, Error>) {\n      return \"test error\";\n    } else if constexpr (std::same_as<ErrorT, CustomError>) {\n      return CustomError().ToString();\n    } else {\n      static_assert(false, \"Unsupported custom error type!\");\n    }\n  }\n\n  auto MakeError() -> ErrorT {\n    if constexpr (std::same_as<ErrorT, Error>) {\n      return Error(\"test error\");\n    } else if constexpr (std::same_as<ErrorT, CustomError>) {\n      return CustomError();\n    } else {\n      static_assert(false, \"Unsupported custom error type!\");\n    }\n  }\n};\n\nusing ErrorOrTestParams = ::testing::Types<Error, CustomError>;\nTYPED_TEST_SUITE(ErrorOrTest, ErrorOrTestParams);\n\nTYPED_TEST(ErrorOrTest, ErrorOr) {\n  using TestErrorOr = ErrorOr<int, TypeParam>;\n  TestErrorOr err(this->MakeError());\n\n  EXPECT_THAT(err, IsError(this->ErrorStr()));\n}\n\nTYPED_TEST(ErrorOrTest, ErrorOrValue) {\n  using TestErrorOr = ErrorOr<int, TypeParam>;\n  EXPECT_TRUE(TestErrorOr(0).ok());\n}\n\ntemplate <typename ErrorT, typename Fixture>\nauto IndirectErrorOrTest(Fixture& fixture) -> ErrorOr<int, ErrorT> {\n  return fixture.MakeError();\n}\n\nTYPED_TEST(ErrorOrTest, IndirectErrorOr) {\n  EXPECT_FALSE(IndirectErrorOrTest<TypeParam>(*this).ok());\n}\n\nstruct Val {\n  int val;\n};\n\nTYPED_TEST(ErrorOrTest, ErrorOrArrowOp) {\n  using TestErrorOr = ErrorOr<Val, TypeParam>;\n  TestErrorOr err({1});\n  EXPECT_EQ(err->val, 1);\n}\n\nTYPED_TEST(ErrorOrTest, ErrorOrReference) {\n  using TestErrorOr = ErrorOr<Val&, TypeParam>;\n  Val val = {1};\n  TestErrorOr maybe_val(val);\n  EXPECT_EQ(maybe_val->val, 1);\n}\n\ntemplate <typename ErrorT>\nauto IndirectErrorOrSuccessTest() -> ErrorOr<Success, ErrorT> {\n  return Success();\n}\n\nTYPED_TEST(ErrorOrTest, IndirectErrorOrSuccess) {\n  EXPECT_TRUE(IndirectErrorOrSuccessTest<TypeParam>().ok());\n}\n\nTYPED_TEST(ErrorOrTest, MoveValue) {\n  using TestErrorOr = ErrorOr<std::unique_ptr<int>, TypeParam>;\n\n  auto make_value = []() -> TestErrorOr { return std::make_unique<int>(42); };\n\n  std::unique_ptr<int> p = *make_value();\n  EXPECT_THAT(*p, Eq(42));\n\n  auto result = make_value();\n  std::unique_ptr<int> p2 = *std::move(result);\n  EXPECT_THAT(*p2, Eq(42));\n}\n\nTYPED_TEST(ErrorOrTest, UnprintableValue) {\n  struct X {\n    int i;\n  };\n  using TestErrorOr = ErrorOr<X, TypeParam>;\n\n  TestErrorOr value(X{.i = 42});\n  EXPECT_THAT(value, IsSuccess(_));\n\n  TestErrorOr error = this->MakeError();\n  EXPECT_THAT(error, IsError(this->ErrorStr()));\n}\n\n// Note that this is more of a test of `IsSuccess` than `ErrorOr` itself.\nTYPED_TEST(ErrorOrTest, NestedMatching) {\n  using TestErrorOr = ErrorOr<std::variant<int, float>, TypeParam>;\n\n  TestErrorOr i(42);\n  EXPECT_THAT(i, IsSuccess(VariantWith<int>(Eq(42))));\n\n  TestErrorOr f(0.42F);\n  EXPECT_THAT(f, IsSuccess(VariantWith<float>(Eq(0.42F))));\n}\n\nTYPED_TEST(ErrorOrTest, ReturnIfErrorNoError) {\n  using TestErrorOr = ErrorOr<Success, TypeParam>;\n  auto result = []() -> TestErrorOr {\n    CARBON_RETURN_IF_ERROR(TestErrorOr(Success()));\n    CARBON_RETURN_IF_ERROR(TestErrorOr(Success()));\n    return Success();\n  }();\n  EXPECT_TRUE(result.ok());\n}\n\nTYPED_TEST(ErrorOrTest, ReturnIfErrorHasError) {\n  using TestErrorOr = ErrorOr<Success, TypeParam>;\n  auto result = [this]() -> TestErrorOr {\n    CARBON_RETURN_IF_ERROR(TestErrorOr(Success()));\n    CARBON_RETURN_IF_ERROR(TestErrorOr(this->MakeError()));\n    return Success();\n  }();\n  EXPECT_THAT(result, IsError(this->ErrorStr()));\n}\n\nTYPED_TEST(ErrorOrTest, AssignOrReturnNoError) {\n  using TestErrorOr = ErrorOr<int, TypeParam>;\n  auto result = []() -> TestErrorOr {\n    CARBON_ASSIGN_OR_RETURN(int a, TestErrorOr(1));\n    CARBON_ASSIGN_OR_RETURN(const int b, TestErrorOr(2));\n    int c = 0;\n    CARBON_ASSIGN_OR_RETURN(c, TestErrorOr(3));\n    return a + b + c;\n  }();\n  EXPECT_THAT(result, IsSuccess(Eq(6)));\n}\n\nTYPED_TEST(ErrorOrTest, AssignOrReturnHasDirectError) {\n  using TestErrorOr = ErrorOr<int, TypeParam>;\n  auto result = [this]() -> TestErrorOr {\n    CARBON_RETURN_IF_ERROR(TestErrorOr(this->MakeError()));\n    return 0;\n  }();\n  EXPECT_THAT(result, IsError(this->ErrorStr()));\n}\n\nTYPED_TEST(ErrorOrTest, AssignOrReturnHasErrorInExpected) {\n  using TestErrorOr = ErrorOr<int, TypeParam>;\n  auto result = [this]() -> TestErrorOr {\n    CARBON_ASSIGN_OR_RETURN(int a, TestErrorOr(this->MakeError()));\n    return a;\n  }();\n  EXPECT_THAT(result, IsError(this->ErrorStr()));\n}\n\nclass AnotherCustomError : public ErrorBase<AnotherCustomError> {\n public:\n  auto Print(llvm::raw_ostream& os) const -> void {\n    os << \"Another custom test error!\";\n  }\n\n  explicit operator CustomError() { return CustomError(); }\n};\n\nTYPED_TEST(ErrorOrTest, AssignOrReturnNoErrorAcrossErrorTypes) {\n  using TestErrorOr = ErrorOr<int, TypeParam>;\n  auto result = []() -> ErrorOr<int> {\n    CARBON_ASSIGN_OR_RETURN(int a, TestErrorOr(1));\n    CARBON_ASSIGN_OR_RETURN(const int b, []() -> TestErrorOr {\n      CARBON_ASSIGN_OR_RETURN(int inner, (ErrorOr<int, AnotherCustomError>(2)));\n      return inner;\n    }());\n    int c = 0;\n    CARBON_ASSIGN_OR_RETURN(c, TestErrorOr(3));\n    return a + b + c;\n  }();\n  EXPECT_THAT(result, IsSuccess(Eq(6)));\n}\n\nTYPED_TEST(ErrorOrTest, AssignOrReturnErrorAcrossErrorTypes) {\n  using TestErrorOr = ErrorOr<int, TypeParam>;\n  auto result = []() -> ErrorOr<int> {\n    CARBON_ASSIGN_OR_RETURN(int a, TestErrorOr(1));\n    CARBON_ASSIGN_OR_RETURN(const int b, []() -> TestErrorOr {\n      CARBON_ASSIGN_OR_RETURN(\n          int inner, (ErrorOr<int, AnotherCustomError>(AnotherCustomError())));\n      return inner;\n    }());\n    int c = 0;\n    CARBON_ASSIGN_OR_RETURN(c, TestErrorOr(3));\n    return a + b + c;\n  }();\n\n  // When directly using the `Error` type, the explicit custom type above has\n  // its message preserved. When testing against `CustomError`, that one\n  // overrides the message.\n  if constexpr (std::same_as<TypeParam, Error>) {\n    EXPECT_THAT(result, IsError(\"Another custom test error!\"));\n  } else {\n    EXPECT_THAT(result, IsError(\"Custom test error!\"));\n  }\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/error_test_helpers.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_ERROR_TEST_HELPERS_H_\n#define CARBON_COMMON_ERROR_TEST_HELPERS_H_\n\n#include <gmock/gmock.h>\n\n#include <concepts>\n\n#include \"common/error.h\"\n#include \"common/ostream.h\"\n\nnamespace Carbon::Testing {\n\n// Matches the message for an error state of `ErrorOr<T>`. For example:\n//   EXPECT_THAT(my_result, IsError(StrEq(\"error message\")));\nclass IsError {\n public:\n  // NOLINTNEXTLINE(readability-identifier-naming)\n  using is_gtest_matcher = void;\n\n  explicit IsError(::testing::Matcher<std::string> matcher)\n      : matcher_(std::move(matcher)) {}\n\n  template <typename T, typename ErrorT>\n  auto MatchAndExplain(const ErrorOr<T, ErrorT>& result,\n                       ::testing::MatchResultListener* listener) const -> bool {\n    if (result.ok()) {\n      *listener << \"is a success\";\n      return false;\n    } else {\n      RawStringOstream os;\n      os << result.error();\n      return matcher_.MatchAndExplain(os.TakeStr(), listener);\n    }\n  }\n\n  auto DescribeTo(std::ostream* os) const -> void {\n    *os << \"is an error and matches \";\n    matcher_.DescribeTo(os);\n  }\n\n  auto DescribeNegationTo(std::ostream* os) const -> void {\n    *os << \"is a success or does not match \";\n    matcher_.DescribeTo(os);\n  }\n\n private:\n  ::testing::Matcher<std::string> matcher_;\n};\n\n// Implementation of a success matcher for a specific `T` and `ErrorT` in an\n// `ErrorOr`. Supports a nested matcher for the `T` value.\ntemplate <typename T, typename ErrorT>\nclass IsSuccessMatcherImpl\n    : public ::testing::MatcherInterface<const ErrorOr<T, ErrorT>&> {\n public:\n  explicit IsSuccessMatcherImpl(const ::testing::Matcher<T>& matcher)\n      : matcher_(matcher) {}\n\n  auto MatchAndExplain(const ErrorOr<T, ErrorT>& result,\n                       ::testing::MatchResultListener* listener) const\n      -> bool override {\n    if (result.ok()) {\n      return matcher_.MatchAndExplain(*result, listener);\n    } else {\n      *listener << \"is an error with `\" << result.error() << \"`\";\n      return false;\n    }\n  }\n\n  auto DescribeTo(std::ostream* os) const -> void override {\n    *os << \"is a success and matches \";\n    matcher_.DescribeTo(os);\n  }\n\n  auto DescribeNegationTo(std::ostream* os) const -> void override {\n    *os << \"is an error or does not match \";\n    matcher_.DescribeNegationTo(os);\n  }\n\n private:\n  ::testing::Matcher<T> matcher_;\n};\n\n// Polymorphic match implementation for GoogleTest.\n//\n// To support matching arbitrary types that `InnerMatcher` can also match, this\n// itself must match arbitrary types. This is accomplished by not being a\n// matcher itself, but by being convertible into matchers for any particular\n// `ErrorOr`.\ntemplate <typename InnerMatcher>\nclass IsSuccessMatcher {\n public:\n  explicit IsSuccessMatcher(InnerMatcher matcher)\n      : matcher_(std::move(matcher)) {}\n\n  template <typename T, typename ErrorT>\n  explicit(false)\n  // NOLINTNEXTLINE(google-explicit-constructor): Required for matcher APIs.\n  operator ::testing::Matcher<const ErrorOr<T, ErrorT>&>() const {\n    return ::testing::Matcher<const ErrorOr<T, ErrorT>&>(\n        new IsSuccessMatcherImpl<T, ErrorT>(\n            ::testing::SafeMatcherCast<T>(matcher_)));\n  }\n\n private:\n  InnerMatcher matcher_;\n};\n\n// Returns a matcher the value for a non-error state of `ErrorOr<T>`.\n//\n// For example:\n//   EXPECT_THAT(my_result, IsSuccess(Eq(3)));\ntemplate <typename InnerMatcher>\nauto IsSuccess(InnerMatcher matcher) -> IsSuccessMatcher<InnerMatcher> {\n  return IsSuccessMatcher<InnerMatcher>(matcher);\n}\n\n}  // namespace Carbon::Testing\n\nnamespace Carbon {\n\n// Supports printing `ErrorOr<T>` to `std::ostream` in tests.\ntemplate <typename T, typename ErrorT>\n  requires(std::same_as<ErrorT, Error> ||\n           std::derived_from<ErrorT, ErrorBase<ErrorT>>)\nauto operator<<(std::ostream& out, const ErrorOr<T, ErrorT>& error_or)\n    -> std::ostream& {\n  if (error_or.ok()) {\n    // Try and print the value, but only if we can find a viable `<<` overload\n    // for the value type. This should ensure that the `formatv` below can\n    // compile cleanly, and avoid erroring when using matchers on `ErrorOr` with\n    // unprintable value types.\n    if constexpr (requires(const T& value) { out << value; }) {\n      out << llvm::formatv(\"ErrorOr{{.value = `{0}`}}\", *error_or);\n    } else {\n      out << \"ErrorOr{{.value = `<unknown>`}}\";\n    }\n  } else {\n    out << llvm::formatv(\"ErrorOr{{.error = \\\"{0}\\\"}}\", error_or.error());\n  }\n  return out;\n}\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_ERROR_TEST_HELPERS_H_\n"
  },
  {
    "path": "common/exe_path.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/exe_path.h\"\n\n#include <optional>\n#include <string>\n#include <utility>\n\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/FileSystem.h\"\n#include \"llvm/Support/Program.h\"\n\nnamespace Carbon {\n\n// Returns true if a found path resolves to the actual executable path.\nstatic auto RealPathMatches(const char* found_path, llvm::StringRef exe_path)\n    -> bool {\n  char* buffer = realpath(found_path, nullptr);\n  if (!buffer) {\n    return false;\n  }\n  bool matches = exe_path == buffer;\n  free(buffer);\n  return matches;\n}\n\nauto FindExecutablePath(const char* argv0) -> std::string {\n  static int static_for_main_addr;\n  // Note this returns the canonical path, dropping symlink information that we\n  // might want. As a consequence, we use it as a last resort. However, it's\n  // also helpful to use to ensure we found the correct tool through other\n  // means.\n  std::string exe_path =\n      llvm::sys::fs::getMainExecutable(argv0, &static_for_main_addr);\n\n  llvm::StringRef argv0_ref = argv0;\n\n  // If `argv[0]` is path-like and points at the executable, use the form in\n  // `argv[0]`.\n  if (argv0_ref.contains('/') && RealPathMatches(argv0, exe_path)) {\n    return argv0_ref.str();\n  }\n\n  // If we can find `argv[0]` in `$PATH`, use the form from that.\n  //\n  // For example, `llvm-symbolizer` is subprocessed with `argv[0]` that uses\n  // this path. If `LLVM_SYMBOLIZER_PATH` is set to Carbon, but\n  // `llvm-symbolizer` in `$PATH` is a different binary, that can lead to\n  // problems -- which is why we verify the match.\n  if (llvm::ErrorOr<std::string> path = llvm::sys::findProgramByName(argv0_ref);\n      path && RealPathMatches(path->c_str(), exe_path)) {\n    return std::move(*path);\n  }\n\n  // As a fallback, use exe_path.\n  return exe_path;\n}\n\n}  // namespace Carbon\n"
  },
  {
    "path": "common/exe_path.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_EXE_PATH_H_\n#define CARBON_COMMON_EXE_PATH_H_\n\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon {\n\n// Computes the executable path for the given `argv[0]` value from `main`.\n// `argv0` is required to be null-terminated.\n//\n// A simplistic approach -- if the provided string isn't already a valid path,\n// we look it up in the PATH environment variable. Doesn't resolve any symlinks.\n// If it doesn't find a value based on `argv[0]`, returns the main executable\n// path.\nauto FindExecutablePath(const char* argv0) -> std::string;\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_EXE_PATH_H_\n"
  },
  {
    "path": "common/exe_path_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/exe_path.h\"\n\n#include <gtest/gtest.h>\n\n#include <string>\n#include <system_error>\n\n#include \"llvm/ADT/SmallString.h\"\n#include \"llvm/Support/FileSystem.h\"\n#include \"llvm/Support/Path.h\"\n\nnamespace Carbon {\nnamespace {\n\nTEST(ExePath, FailureFallback) {\n  static int static_for_main_addr;\n  std::string running_binary =\n      llvm::sys::fs::getMainExecutable(\"exe_path_test\", &static_for_main_addr);\n\n  llvm::SmallString<128> path = llvm::StringRef(getenv(\"TEST_TMPDIR\"));\n  llvm::sys::path::append(path, \"non_existant_binary\");\n  std::string exe_path = FindExecutablePath(path.c_str());\n  EXPECT_EQ(running_binary, exe_path);\n}\n\nTEST(ExePath, Symlink) {\n  static int static_for_main_addr;\n  std::string running_binary =\n      llvm::sys::fs::getMainExecutable(\"exe_path_test\", &static_for_main_addr);\n\n  llvm::SmallString<128> path = llvm::StringRef(getenv(\"TEST_TMPDIR\"));\n  llvm::sys::path::append(path, \"test_binary\");\n  std::error_code ec;\n  std::filesystem::create_symlink(running_binary, path.c_str(), ec);\n  ASSERT_TRUE(!ec) << \"Error code: \" << ec;\n\n  std::string exe_path = FindExecutablePath(path.c_str());\n  EXPECT_EQ(path, exe_path);\n}\n\nTEST(ExePath, PathLookup) {\n  // TODO: This is not likely to work well on Windows (outside of WSL). But some\n  // of that may be hidden by Bazel's test environment. Regardless, we should\n  // revisit this when we have good coverage of Windows build with something\n  // appropriate for that platform.\n  std::string exe_path = FindExecutablePath(\"bash\");\n  EXPECT_NE(exe_path, \"bash\");\n  EXPECT_TRUE(llvm::sys::fs::exists(exe_path));\n  EXPECT_TRUE(llvm::sys::fs::can_execute(exe_path));\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/filesystem.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/filesystem.h\"\n\n#include <fcntl.h>\n#include <time.h>\n#include <unistd.h>\n\n#include <chrono>\n\n#include \"common/build_data.h\"\n#include \"llvm/Support/MathExtras.h\"\n\nnamespace Carbon::Filesystem {\n\n// Render an error number from `errno` to the provided stream using the richest\n// rendering available on the platform.\nstatic auto PrintErrorNumber(llvm::raw_ostream& out, int errnum) -> void {\n#if defined(_GNU_SOURCE) && \\\n    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32))\n  // For sufficiently recent glibc versions, use GNU-specific routines to\n  // compute the error name and description.\n  llvm::StringRef name = strerrordesc_np(errnum);\n  llvm::StringRef desc = strerrorname_np(errnum);\n\n  out << llvm::formatv(\"{0}: {1}\", name, desc);\n#elif defined(__APPLE__) || defined(_GNU_SOURCE) || defined(_POSIX_SOURCE)\n  // Broadly portable fallback for Unix-like systems.\n  char buffer[4096];\n#ifdef _GNU_SOURCE\n  const char* str = strerror_r(errnum, buffer, sizeof(buffer));\n  // The GNU version doesn't report a meta-error.\n  int meta_error = 0;\n#else\n  int meta_error = strerror_r(errnum, buffer, sizeof(buffer));\n  const char* str = buffer;\n#endif\n  if (meta_error == 0) {\n    out << llvm::formatv(\"errno {0}: {1}\", errnum, llvm::StringRef(str));\n  } else {\n    out << llvm::formatv(\n        \"error number {0}; encountered meta-error number {1} while rendering \"\n        \"an error message\",\n        errnum, meta_error);\n  }\n#else\n#error TODO: Implement this for other platforms.\n#endif\n}\n\nauto FdError::Print(llvm::raw_ostream& out) const -> void {\n  // The `format_` member is a `StringLiteral` that is null terminated, so\n  // `.data()` is safe here.\n  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)\n  out << llvm::formatv(format_.data(), fd_) << \" failed: \";\n  PrintErrorNumber(out, unix_errnum());\n}\n\nauto PathError::Print(llvm::raw_ostream& out) const -> void {\n  // The `format_` member is a `StringLiteral` that is null terminated, so\n  // `.data()` is safe here.\n  // NOLINTNEXTLINE(bugprone-suspicious-stringview-data-usage)\n  out << llvm::formatv(format_.data(), path_,\n                       dir_fd_ == AT_FDCWD ? std::string(\"AT_FDCWD\")\n                                           : std::to_string(dir_fd_))\n      << \" failed: \";\n  PrintErrorNumber(out, unix_errnum());\n}\n\nauto Internal::FileRefBase::ReadFileToString()\n    -> ErrorOr<std::string, FdError> {\n  std::string result;\n\n  // Read a buffer at a time until we reach the end. We use the pipe buffer\n  // length as our max buffer size as it is likely to be small but reasonable\n  // for the OS, and in the case of pipes the same chunking in which the data\n  // will arrive.\n  //\n  // TODO: Replace this with a smaller buffer and using `resize_and_overwrite`\n  // to read into the string in-place for larger strings. Unclear if that will\n  // be any faster, but it will be much more friendly to callers with\n  // constrained stack sizes and use less memory overall.\n  std::byte buffer[PIPE_BUF];\n  CARBON_RETURN_IF_ERROR(SeekFromBeginning(0));\n  for (;;) {\n    auto read_result = ReadToBuffer(buffer);\n    if (!read_result.ok()) {\n      return std::move(read_result).error();\n    }\n    if (read_result->empty()) {\n      // EOF\n      break;\n    }\n    result.append(reinterpret_cast<const char*>(read_result->data()),\n                  read_result->size());\n  }\n\n  return result;\n}\n\nauto Internal::FileRefBase::WriteFileFromString(llvm::StringRef str)\n    -> ErrorOr<Success, FdError> {\n  CARBON_RETURN_IF_ERROR(SeekFromBeginning(0));\n  auto bytes = llvm::ArrayRef<std::byte>(\n      reinterpret_cast<const std::byte*>(str.data()), str.size());\n  while (!bytes.empty()) {\n    auto write_result = WriteFromBuffer(bytes);\n    if (!write_result.ok()) {\n      return std::move(write_result).error();\n    }\n    bytes = *write_result;\n  }\n  CARBON_RETURN_IF_ERROR(Truncate(str.size()));\n  return Success();\n}\n\n// A macOS specific sleep routine that builds on more standard utilities. This\n// is technically a portable implementation so we always compile it but only use\n// it on macOS where the more efficient direct use of `clock_nanosleep` isn't\n// available.\n[[maybe_unused]]\nstatic auto SleepMacos(Duration sleep) -> void {\n  TimePoint stop = Clock::now() + sleep;\n\n  timespec sleep_ts = Internal::DurationToTimespec(sleep);\n  for (;;) {\n    timespec rem_sleep_ts = {};\n    int result = nanosleep(&sleep_ts, &rem_sleep_ts);\n    if (result == 0) {\n      return;\n    }\n\n    // Continue sleeping if we get interrupted by a resumable signal. For\n    // everything else report it.\n    if (errno != EINTR) {\n      int errnum = errno;\n      RawStringOstream error_os;\n      PrintErrorNumber(error_os, errnum);\n      CARBON_FATAL(\"Unexpected error while sleeping: {0}\", error_os.TakeStr());\n    }\n\n    // Update to the remaining sleep time for the next attempt at sleeping.\n    sleep_ts = rem_sleep_ts;\n\n    // Also check if the clock has passed our stop time as a fallback to avoid\n    // too much clock skew.\n    if (Clock::now() > stop) {\n      return;\n    }\n  }\n}\n\nstatic auto Sleep(Duration sleep) -> void {\n  // For every platform but macOS we can sleep directly on an absolute time.\n#if __APPLE__\n  // On Apple platforms, dispatch to a specialized routine.\n  SleepMacos(sleep);\n#else\n\n  // We use `clock_gettime` instead of the filesystem `Clock` or some other\n  // `std::chrono` clock because we want to use the exact same clock that we'll\n  // use for sleeping below, and we'll need the time in a `timespec` for that\n  // call anyways. We do use a monotonic clock to try and avoid sleeps being\n  // interrupted by clock changes.\n  timespec ts = {};\n  int result = clock_gettime(CLOCK_MONOTONIC, &ts);\n  CARBON_CHECK(result == 0, \"Error getting the time: {0}\", strerror(errno));\n\n  // Now convert the timespec to a duration that we can safely do arithmetic on.\n  // Since the sleep interval is in nanoseconds it is tempting to directly do\n  // arithmetic here, but this has a subtle pitfall near the boundary between\n  // the nanosecond component and the second component.\n  //\n  // Note that our `Duration` uses `__int128` to avoid worrying about running\n  // out of precision to represent the final deadline.\n  Duration stop_time = std::chrono::seconds(ts.tv_sec);\n  stop_time += std::chrono::nanoseconds(ts.tv_nsec);\n  stop_time += sleep;\n\n  // Now convert back to timespec.\n  ts = Internal::DurationToTimespec(stop_time);\n\n  do {\n    result = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr);\n\n    // Continue sleeping if we get interrupted by a resumable signal. Because\n    // we're using a monotonic clock and an absolute deadline time we will\n    // eventually progress past that deadline.\n  } while (result != 0 && (errno == EINTR));\n\n  if (result != 0) {\n    int errnum = errno;\n    RawStringOstream error_os;\n    PrintErrorNumber(error_os, errnum);\n    CARBON_FATAL(\"Unexpected error while sleeping: {0}\", error_os.TakeStr());\n  }\n#endif\n}\n\nauto Internal::FileRefBase::TryLock(FileLock::Kind kind, Duration deadline,\n                                    Duration poll_interval)\n    -> ErrorOr<FileLock, FdError> {\n  CARBON_CHECK(poll_interval <= deadline);\n  if (deadline != Duration(0) && poll_interval == Duration(0)) {\n    // If the caller didn't provide a poll interval but did provide a deadline,\n    // pick a poll interval to roughly be 1/1000th of the deadline but at least\n    // 1 microsecond. We don't support polling faster than 1 microsecond given\n    // how expensive file locking is.\n    poll_interval =\n        std::max(Duration(std::chrono::microseconds(1)), deadline / 1000);\n  }\n  if (deadline != Duration(0)) {\n    CARBON_CHECK(\n        deadline >= std::chrono::microseconds(10),\n        \"A deadline for a file lock shorter than 10 microseconds is not \"\n        \"supported, callers can implement their own polling logic.\");\n    CARBON_CHECK(poll_interval >= std::chrono::microseconds(1),\n                 \"Polling for a file lock faster than every microsecond is not \"\n                 \"supported, callers can implement their own polling logic.\");\n  }\n  auto stop = Clock::now() + deadline;\n  for (;;) {\n    int result = flock(fd_, static_cast<int>(kind) | LOCK_NB);\n    if (result == 0) {\n      return FileLock(fd_);\n    }\n\n    // Return an error if this is something other than blocking for the lock to\n    // be available, or we didn't get a deadline for continuing to try and\n    // acquire the lock, or we've reached our deadline.\n    if (errno != EWOULDBLOCK || deadline == Duration(0) ||\n        Clock::now() >= stop) {\n      return FdError(errno, \"File::TryLock on '{0}'\", fd_);\n    }\n\n    // The caller requested attempting to wait up to a deadline to acquire the\n    // lock with a specific poll interval. Try to sleep for that poll interval\n    // before trying the lock again.\n    Sleep(poll_interval);\n  }\n}\n\nauto DirRef::AppendEntriesIf(\n    llvm::SmallVectorImpl<std::filesystem::path>& entries,\n    llvm::function_ref<auto(llvm::StringRef name)->bool> predicate)\n    -> ErrorOr<Success, FdError> {\n  CARBON_ASSIGN_OR_RETURN(Reader reader, Read());\n  for (const Entry& entry : reader) {\n    llvm::StringRef name = entry.name();\n    if (name == \".\" || name == \"..\") {\n      continue;\n    }\n    if (predicate && !predicate(name)) {\n      continue;\n    }\n    entries.push_back(name.str());\n  }\n  return Success();\n}\n\nauto DirRef::AppendEntriesIf(\n    llvm::SmallVectorImpl<std::filesystem::path>& dir_entries,\n    llvm::SmallVectorImpl<std::filesystem::path>& non_dir_entries,\n    llvm::function_ref<auto(llvm::StringRef name)->bool> predicate)\n    -> ErrorOr<Success, FdError> {\n  CARBON_ASSIGN_OR_RETURN(Reader reader, Read());\n  for (const Entry& entry : reader) {\n    llvm::StringRef name = entry.name();\n    if (name == \".\" || name == \"..\") {\n      continue;\n    }\n    if (predicate && !predicate(name)) {\n      continue;\n    }\n    std::filesystem::path name_path = name.str();\n    if (entry.is_known_dir()) {\n      dir_entries.push_back(std::move(name_path));\n      continue;\n    }\n    if (!entry.is_unknown_type()) {\n      non_dir_entries.push_back(std::move(name_path));\n      continue;\n    }\n\n    auto stat_result = Lstat(name_path);\n    if (!stat_result.ok()) {\n      return FdError(stat_result.error().unix_errnum(),\n                     \"Dir::AppendEntriesIf on '{0}' failed while stat-ing \"\n                     \"entries to determine which are directories\",\n                     dfd_);\n    }\n    if (stat_result->is_dir()) {\n      dir_entries.push_back(std::move(name_path));\n    } else {\n      non_dir_entries.push_back(std::move(name_path));\n    }\n  }\n  return Success();\n}\n\nauto DirRef::OpenDir(const std::filesystem::path& path,\n                     CreationOptions creation_options, ModeType creation_mode,\n                     OpenFlags open_flags) -> ErrorOr<Dir, PathError> {\n  // If we potentially need to create a directory, we have to do that\n  // separately as no systems support `O_CREAT | O_DIRECTORY`, even though\n  // that would be (much) nicer.\n\n  if (creation_options == CreateNew) {\n    // If we are required to be the one that created the directory, disable\n    // following the last symlink when we open that directory. The last symlink\n    // is the only one that matters for security here because it is only valid\n    // to create the last component. It is that directory component that we want\n    // to ensure has not been replaced with a symlink by an adversarial\n    // concurrent process.\n    open_flags |= OpenFlags::NoFollow;\n  }\n\n  if (creation_options != OpenExisting) {\n    CARBON_CHECK(creation_options != CreateAlways,\n                 \"Invalid `creation_options` value of `CreateAlways`: there is \"\n                 \"no support for truncating directories, and so they cannot be \"\n                 \"created in an analogous way to files if they already exist.\");\n\n    if (mkdirat(dfd_, path.c_str(), creation_mode) != 0) {\n      // Unless the error is just that the path already exists, and that is\n      // allowed for the requested creation flags, report any error here as part\n      // of opening just like we would if the error originated from `openat`\n      // with `O_CREAT`.\n      if (creation_options == CreateNew || errno != EEXIST) {\n        return PathError(errno,\n                         \"Calling `mkdirat` on '{0}' relative to '{1}' during \"\n                         \"DirRef::OpenDir\",\n                         path, dfd_);\n      }\n    }\n  }\n\n  // Open this path as a directory. Note that this has to succeed, and when we\n  // created the directory we require the last component to not be a symlink in\n  // case it was _replaced_ with a symlink while running.\n  int result_fd =\n      openat(dfd_, path.c_str(), static_cast<int>(open_flags) | O_DIRECTORY);\n  if (result_fd == -1) {\n    // No need for `EINTR` handling here as if this is a FIFO it would be an\n    // error with `O_DIRECTORY`.\n    return PathError(\n        errno,\n        \"Calling `openat` on '{0}' relative to '{1}' during DirRef::OpenDir\",\n        path, dfd_);\n  }\n  Dir result(result_fd);\n\n  // If we were required to create the directory, we also need to verify that\n  // the opened file descriptor continues to have the same permissions and the\n  // correct owner as we couldn't do the creation atomically with the open. This\n  // defends against an adversarial removal of the created directory and\n  // creation of a new directory with the same name but either with wider\n  // permissions such as all-write, or with a different owner.\n  //\n  // We don't defend against replacement with a directory of the same name, same\n  // permissions, same owner, but different group. There is no good way to do\n  // this defense given the complexity of group assignment, and there appears to\n  // be no need. Achieving such a replacement without superuser power would\n  // require a parent directory with `setgid` bit, and a group that gives the\n  // attacker access -- but such a parent directory would make *any* creation\n  // vulnerable without any need for a replacement, so we can't defend against\n  // that here. The caller has ample tools to defend against this including\n  // taking care with the parent directory and restricting the group permission\n  // bits which we *do* verify.\n  if (creation_options == CreateNew) {\n    auto stat_result = result.Stat();\n    if (!stat_result.ok()) {\n      // Manually propagate this error so we can attach it back to the opened\n      // path and relative directory.\n      return PathError(stat_result.error().unix_errnum(),\n                       \"DirRef::Stat after opening '{0}' relative to '{1}'\",\n                       path, dfd_);\n    }\n\n    // Check that the owning UID is the current effective UID.\n    if (stat_result->unix_uid() != geteuid()) {\n      // Model this as `EPERM`, which is a bit awkward, but should be fine.\n      return PathError(EPERM,\n                       \"Unexpected UID change after creating '{0}' relative to \"\n                       \"'{1}' during DirRef::OpenDir\",\n                       path, dfd_);\n    }\n\n    // Check that the permissions are a subset of the requested ones. They may\n    // have been masked down by `umask`, but if there are *new* permissions,\n    // that would be a security issue.\n    if ((stat_result->permissions() & creation_mode) !=\n        stat_result->permissions()) {\n      // Model this with `EPERM` and a custom message.\n      return PathError(EPERM,\n                       \"Unexpected permissions after creating '{0}' relative \"\n                       \"to '{1}' during DirRef::OpenDir\",\n                       path, dfd_);\n    }\n  }\n\n  return result;\n}\n\nauto DirRef::ReadFileToString(const std::filesystem::path& path)\n    -> ErrorOr<std::string, PathError> {\n  CARBON_ASSIGN_OR_RETURN(ReadFile f, OpenReadOnly(path));\n  auto result = f.ReadFileToString();\n  if (result.ok()) {\n    return *std::move(result);\n  }\n  return PathError(result.error().unix_errnum(),\n                   \"Dir::ReadFileToString on '{0}' relative to '{1}'\", path,\n                   dfd_);\n}\n\nauto DirRef::WriteFileFromString(const std::filesystem::path& path,\n                                 llvm::StringRef content,\n                                 CreationOptions creation_options)\n    -> ErrorOr<Success, PathError> {\n  CARBON_ASSIGN_OR_RETURN(WriteFile f, OpenWriteOnly(path, creation_options));\n  auto write_result = f.WriteFileFromString(content);\n  // Immediately close the file as even if there was a write error we don't want\n  // to leave the file open.\n  auto close_result = std::move(f).Close();\n\n  // Now report the first error encountered or return success.\n  if (!write_result.ok()) {\n    return PathError(\n        write_result.error().unix_errnum(),\n        \"Write error in Dir::WriteFileFromString on '{0}' relative to '{1}'\",\n        path, dfd_);\n  }\n  if (!close_result.ok()) {\n    return PathError(\n        close_result.error().unix_errnum(),\n        \"Close error in Dir::WriteFileFromString on '{0}' relative to '{1}'\",\n        path, dfd_);\n  }\n  return Success();\n}\n\nauto DirRef::CreateDirectories(const std::filesystem::path& path,\n                               ModeType creation_mode)\n    -> ErrorOr<Dir, PathError> {\n  // Avoid having to handle an empty path by immediately rejecting it as\n  // invalid.\n  if (path.empty()) {\n    return PathError(EINVAL,\n                     \"DirRef::CreateDirectories on '{0}' relative to '{1}'\",\n                     path, dfd_);\n  }\n  // Try directly opening the directory and use that if successful. This is an\n  // important hot path case of users essentially doing an \"open-always\" form of\n  // creating multiple steps of directories.\n  auto open_result = OpenDir(path, OpenExisting);\n  if (open_result.ok()) {\n    return std::move(*open_result);\n  } else if (!open_result.error().no_entity()) {\n    return std::move(open_result).error();\n  }\n\n  // Walk from the full path towards this directory (or the root) to find the\n  // first existing directory. This is faster than walking down as no file\n  // descriptors have to be allocated for any intervening directories, etc. We\n  // keep the path components that are missing as we pop them off for easy\n  // traversal back down.\n  std::optional<Dir> work_dir;\n  // Paths typically consist of relatively few components\n  // and so we can use a bit of stack and avoid allocating and moving the paths\n  // in common cases. We use `8` as an arbitrary but likely good for all of the\n  // hottest cases.\n  llvm::SmallVector<std::filesystem::path, 8> missing_components;\n  missing_components.push_back(path.filename());\n  for (std::filesystem::path parent_path = path.parent_path();\n       !parent_path.empty(); parent_path = parent_path.parent_path()) {\n    auto open_result = OpenDir(parent_path, OpenExisting);\n    if (open_result.ok()) {\n      work_dir = std::move(*open_result);\n      break;\n    }\n    missing_components.push_back(parent_path.filename());\n  }\n  CARBON_CHECK(!missing_components.empty());\n\n  // If we haven't yet opened an intermediate directory, start by creating one\n  // relative to this directory. We can't do this as part of the loop below as\n  // `this` and the newly opened directory have different types.\n  if (!work_dir) {\n    std::filesystem::path component = missing_components.pop_back_val();\n    CARBON_ASSIGN_OR_RETURN(\n        Dir component_dir,\n        OpenDir(component, CreationOptions::OpenAlways, creation_mode));\n    // Move this component into our temporary directory slot.\n    work_dir = std::move(component_dir);\n  }\n\n  // Now walk through the remaining components opening and creating each\n  // relative to the previous.\n  while (!missing_components.empty()) {\n    std::filesystem::path component = missing_components.pop_back_val();\n    CARBON_ASSIGN_OR_RETURN(\n        Dir component_dir,\n        work_dir->OpenDir(component, CreationOptions::OpenAlways,\n                          creation_mode));\n\n    // Close the current temporary directory and move the new component\n    // directory object into its place.\n    work_dir = std::move(component_dir);\n  }\n\n  CARBON_CHECK(work_dir,\n               \"Should always have created at least one directory for a \"\n               \"non-empty path!\");\n  return std::move(work_dir).value();\n}\n\nauto DirRef::Rmtree(const std::filesystem::path& path)\n    -> ErrorOr<Success, PathError> {\n  struct DirAndIterator {\n    DirRef::Reader dir;\n    ssize_t dir_entry_start;\n  };\n  llvm::SmallVector<DirAndIterator> dir_stack;\n\n  llvm::SmallVector<std::filesystem::path> dir_entries;\n  llvm::SmallVector<std::filesystem::path> unknown_entries;\n\n  dir_entries.push_back(path);\n  for (;;) {\n    // When we bottom out, we're removing the initial tree path and doing so\n    // relative to `this` directory.\n    DirRef current = dir_stack.empty() ? *this : dir_stack.back().dir;\n    ssize_t dir_entry_start =\n        dir_stack.empty() ? 0 : dir_stack.back().dir_entry_start;\n\n    // If we've finished all the child directories of the current entry in the\n    // stack, pop it off and continue.\n    if (dir_entry_start == static_cast<ssize_t>(dir_entries.size())) {\n      dir_stack.pop_back();\n      continue;\n    }\n    CARBON_CHECK(dir_entry_start < static_cast<ssize_t>(dir_entries.size()));\n\n    // Take the last entry under the current directory and try removing it.\n    const std::filesystem::path& entry_path = dir_entries.back();\n    auto rmdir_result = current.Rmdir(entry_path);\n    if (rmdir_result.ok() || rmdir_result.error().no_entity()) {\n      // Removed here or elsewhere already, so pop the entry.\n      dir_entries.pop_back();\n      if (dir_entries.empty()) {\n        // The last entry is the input path with an empty stack, so we've\n        // finished at this point.\n        CARBON_CHECK(dir_stack.empty());\n        return Success();\n      }\n      continue;\n    }\n    // If we get any error other than not-empty, just return that.\n    if (!rmdir_result.error().not_empty()) {\n      return std::move(rmdir_result).error();\n    }\n\n    // Recurse into the subdirectory since it isn't empty, opening it, getting a\n    // reader, and pushing it onto our stack.\n    CARBON_ASSIGN_OR_RETURN(Dir subdir, current.OpenDir(entry_path));\n    auto read_result = std::move(subdir).TakeAndRead();\n    if (!read_result.ok()) {\n      return PathError(\n          read_result.error().unix_errnum(),\n          \"Dir::Read on '{0}' relative to '{1}' during RmdirRecursively\",\n          entry_path, current.dfd_);\n    }\n    dir_stack.push_back(\n        {*std::move(read_result), static_cast<ssize_t>(dir_entries.size())});\n\n    // Now read the directory entries. It would be nice to be able to directly\n    // remove the files and empty directories as we find them when reading, and\n    // the POSIX spec appears to require that to work, but testing shows at\n    // least some Linux environments don't work reliably in this case and will\n    // fail to visit some entries entirely. As a consequence, we walk the entire\n    // directory and collect the entries into data structures before beginning\n    // to remove them.\n    DirRef::Reader& subdir_reader = dir_stack.back().dir;\n    for (const auto& entry : subdir_reader) {\n      llvm::StringRef name = entry.name();\n      if (name == \".\" || name == \"..\") {\n        continue;\n      }\n      if (entry.is_known_dir()) {\n        dir_entries.push_back(name.str());\n      } else {\n        // We end up here for entries known to be regular files, other kinds of\n        // non-directory entries, or when the entry kind isn't known.\n        //\n        // Unless we *know* the entry is a directory, we put it into the unknown\n        // entries. For these, we unlink them first in case they are\n        // non-directory entries and use the failure of that to move any\n        // directories that end up here to the directory entries list.\n        unknown_entries.push_back(name.str());\n      }\n    }\n\n    // We can immediately try to unlink all the unknown entries, which will\n    // include any regular files, and use an error on directories that were\n    // unknown above to switch them to the `dir_entries` list.\n    while (!unknown_entries.empty()) {\n      std::filesystem::path name = unknown_entries.pop_back_val();\n      auto unlink_result = subdir_reader.Unlink(name);\n      if (unlink_result.ok() || unlink_result.error().no_entity()) {\n        continue;\n      } else if (!unlink_result.error().is_dir()) {\n        return std::move(unlink_result).error();\n      }\n      dir_entries.push_back(std::move(name));\n    }\n\n    // We'll handle the directory entries we've queued here in the next\n    // iteration, removing them or recursing as needed.\n  }\n}\n\nauto DirRef::ReadlinkSlow(const std::filesystem::path& path)\n    -> ErrorOr<std::string, PathError> {\n  constexpr ssize_t MinBufferSize =\n#ifdef PATH_MAX\n      PATH_MAX\n#else\n      1024\n#endif\n      ;\n  // Read directly into a string to avoid allocating two large buffers.\n  std::string large_buffer;\n  // Stat the symlink to get an initial guess at the size.\n  CARBON_ASSIGN_OR_RETURN(FileStatus status, Lstat(path));\n  // We try to use the size from the `lstat` unless it is empty, in which case\n  // we try to use our minimum buffer size which is `PATH_MAX` or a constant\n  // value. We have a fallback to dynamically discover an adequate buffer size\n  // below that will handle any inaccuracy.\n  ssize_t buffer_size = status.size();\n  if (buffer_size == 0) {\n    buffer_size = MinBufferSize;\n  }\n  large_buffer.resize(status.size());\n  ssize_t result =\n      readlinkat(dfd_, path.c_str(), large_buffer.data(), large_buffer.size());\n  if (result == -1) {\n    return PathError(errno, \"Readlink on '{0}' relative to '{1}'\", path, dfd_);\n  }\n\n  // Now the really bad fallback case: if there are racing writes to the\n  // symlink, the guessed size may not have been large enough. As a last-ditch\n  // effort, begin doubling (from the next power of two >= our min buffer size)\n  // the length until it fits. We cap this at 10 MiB to prevent egregious file\n  // system contents (or some bug somewhere) from exhausting memory.\n  constexpr ssize_t MaxBufferSize = 10 << 20;\n  while (result == static_cast<ssize_t>(large_buffer.size())) {\n    int64_t next_buffer_size = std::max<ssize_t>(\n        MinBufferSize, llvm::NextPowerOf2(large_buffer.size()));\n    if (next_buffer_size > MaxBufferSize) {\n      return PathError(ENOMEM, \"Readlink on '{0}' relative to '{1}'\", path,\n                       dfd_);\n    }\n    large_buffer.resize(next_buffer_size);\n    result = readlinkat(dfd_, path.c_str(), large_buffer.data(),\n                        large_buffer.size());\n    if (result == -1) {\n      return PathError(errno, \"Readlink on '{0}' relative to '{1}'\", path,\n                       dfd_);\n    }\n  }\n\n  // Fix-up the size of the string and return it.\n  large_buffer.resize(result);\n  return large_buffer;\n}\n\nauto MakeTmpDir() -> ErrorOr<RemovingDir, Error> {\n  std::filesystem::path tmpdir_path = \"/tmp\";\n  // We use both `TEST_TMPDIR` and `TMPDIR`. The `TEST_TMPDIR` is set by Bazel\n  // and preferred to keep tests using the expected output tree rather than\n  // the system temporary directory.\n  for (const char* tmpdir_env_name : {\"TEST_TMPDIR\", \"TMPDIR\"}) {\n    const char* tmpdir_env_cstr = getenv(tmpdir_env_name);\n    if (tmpdir_env_cstr == nullptr) {\n      continue;\n    }\n    std::filesystem::path tmpdir_env = tmpdir_env_cstr;\n    tmpdir_path = std::move(tmpdir_env);\n    break;\n  }\n\n  std::filesystem::path target = BuildData::BuildTarget.str();\n  tmpdir_path /= target.filename();\n  return MakeTmpDirWithPrefix(std::move(tmpdir_path));\n}\n\nauto MakeTmpDirWithPrefix(std::filesystem::path prefix)\n    -> ErrorOr<RemovingDir, Error> {\n  std::filesystem::path tmpdir_path = std::move(prefix);\n  tmpdir_path += \".XXXXXX\";\n\n  std::string tmpdir_path_buffer = tmpdir_path.native();\n  char* result = mkdtemp(tmpdir_path_buffer.data());\n  if (result == nullptr) {\n    RawStringOstream os;\n    os << llvm::formatv(\"Calling mkdtemp on '{0}' failed: \",\n                        tmpdir_path.native());\n    PrintErrorNumber(os, errno);\n    return Error(os.TakeStr());\n  }\n  CARBON_CHECK(result == tmpdir_path_buffer.data(),\n               \"`mkdtemp` used a modified path\");\n  tmpdir_path = std::move(tmpdir_path_buffer);\n\n  // Because `mkdtemp` doesn't return an open directory atomically, open the\n  // created directory and perform safety checks similar to `OpenDir` when\n  // creating a new directory.\n  CARBON_ASSIGN_OR_RETURN(\n      Dir tmp, Cwd().OpenDir(tmpdir_path, OpenExisting, /*creation_mode=*/0,\n                             OpenFlags::NoFollow));\n  // Make sure we try to remove the directory from here on out.\n  RemovingDir result_dir(std::move(tmp), tmpdir_path);\n\n  // It's a bit awkward to report `fstat` errors as `Error`s, but we\n  // don't have much choice. The stat failing here would be very weird.\n  CARBON_ASSIGN_OR_RETURN(FileStatus stat, result_dir.Stat());\n\n  // The permissions must be exactly 0700 for a temporary directory, and the UID\n  // should be ours.\n  if (stat.permissions() != 0700 && stat.unix_uid() != geteuid()) {\n    return Error(\n        llvm::formatv(\"Found incorrect permissions or UID on tmpdir '{0}'\",\n                      tmpdir_path.native())\n            .str());\n  }\n\n  return result_dir;\n}\n\n}  // namespace Carbon::Filesystem\n"
  },
  {
    "path": "common/filesystem.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_FILESYSTEM_H_\n#define CARBON_COMMON_FILESYSTEM_H_\n\n#include <dirent.h>\n#include <fcntl.h>\n#include <sys/file.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include <chrono>\n#include <concepts>\n#include <filesystem>\n#include <iterator>\n#include <string>\n\n#include \"common/check.h\"\n#include \"common/error.h\"\n#include \"common/ostream.h\"\n#include \"common/raw_string_ostream.h\"\n#include \"common/template_string.h\"\n#include \"llvm/ADT/ScopeExit.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n\n// Provides a filesystem library for use in the Carbon project.\n//\n// This library provides an API designed to support modern Unix / Linux / POSIX\n// style filesystem operations, often called \"Unix-like\"[1] here, efficiently\n// and securely, while also carefully staying to a set of abstractions and\n// operations that can be reasonably implemented even on Windows platforms.\n//\n// TODO: Currently, there is not a Windows implementation, but this is actively\n// desired when we have testing infrastructure in place for Windows development.\n// Lacking that testing infrastructure and a full Windows port, the operations\n// here are manually compared with LLVM's filesystem library to ensure a\n// reasonable Windows implementation is possible.\n//\n// The library uses C++'s `std::filesystem::path` as its abstraction for\n// paths. This library provides two core APIs: open directories and files.\n//\n// Open directories provide relative- and absolute-path based operations to open\n// other directories or files. This allows secure creation of directories even\n// in the face of adversarial operations for example in a shared `/tmp`\n// directory. There is a `constexpr` current working directory available as\n// `Cwd()` that models normal filesystem operations with paths.\n//\n// Open files provide read, write, and other operations on the file. There are\n// separate types for read-only, write-only, and read-write files to model the\n// different APIs available.\n//\n// The APIs for both directories and files are primarily on `*Ref` types that\n// model a non-owning reference to the directory or file. These types are the\n// preferred types to use on an API boundary. Owning versions are provided that\n// ensure the file or directory is closed on destruction. Files support explicit\n// closing in order to observe any close-specific errors.\n//\n// Where APIs require flag parameters of some form, this library provides\n// enumerations that model those flags. The enumeration values are in turn\n// chosen to simplify passing these to specific native APIs. This means the\n// enumeration *values* should not be expected to be portable across platforms.\n// Customizing the values is part of the larger TODO to port the implementation\n// to Windows.\n//\n// [1]: Note that we refer to platforms as \"Unix-like\" rather than POSIX as we\n//      want to group together all the OSes where the Unix-derived APIs are the\n//      primary and expected way to interact with the filesystem, regardless of\n//      whether a POSIX conforming API happens to exist. For example, both macOS\n//      and WSL (Windows Subsystem for Linux) _are_ Unix-like as those are the\n//      primary APIs used to access files in those environments. But Windows\n//      itself _isn't_ Unix-like, even considering things like the defunct NT\n//      POSIX subsystem or modern WSL, as those aren't the primary filesystem\n//      APIs for the (non-WSL) Windows platform. This also matches the rough OS\n//      classification used in LLVM.\nnamespace Carbon::Filesystem {\n\n// The different creation options available when opening a file or directory.\n//\n// Because these are by far the most common parameters and they have unambiguous\n// names, the enumerators are also available directly within the namespace.\nenum class CreationOptions {\n  // Requires an existing file or directory.\n  OpenExisting = 0,\n\n  // Opens an existing file or directory, and create one otherwise.\n  OpenAlways = O_CREAT,\n\n  // Opens and truncates an existing file or creates a new file. Provides\n  // consistent behavior of an empty file regardless of the starting state. This\n  // cannot be used for directories as they cannot be truncated on open. This is\n  // essentially a short-cut for using `OpenAlways` and passing the\n  // `OpenFlags::Truncate` below.\n  CreateAlways = O_CREAT | O_TRUNC,\n\n  // Requires no existing file or directory and will error if one is found. Only\n  // succeeds when it creates a new file or directory.\n  CreateNew = O_CREAT | O_EXCL,\n};\nusing enum CreationOptions;\n\n// General flags to control the behavior of opening files that aren't covered by\n// other more specific flags.\n//\n// These can be combined using the `|` operator where the semantics are\n// compatible, although not all are.\nenum class OpenFlags : int {\n  None = 0,\n\n  // Open the file for appending rather than with the position at the start.\n  //\n  // An error to combine with `Truncate` or to use with `CreateAlways`.\n  Append = O_APPEND,\n\n  // Open the file and truncate its contents to be empty.\n  Truncate = O_TRUNC,\n\n  // Don't follow a symlink in the final path component being opened.\n  NoFollow = O_NOFOLLOW,\n};\ninline auto operator|(OpenFlags lhs, OpenFlags rhs) -> OpenFlags {\n  return static_cast<OpenFlags>(static_cast<int>(lhs) | static_cast<int>(rhs));\n}\ninline auto operator|=(OpenFlags& lhs, OpenFlags rhs) -> OpenFlags& {\n  lhs = lhs | rhs;\n  return lhs;\n}\n\n// Flags controlling which permissions should be checked in an `Access` call.\n//\n// These permissions can also be combined with the `|` operator, so\n// `AccessCheckFlags::Read | AccessCheckFlags::Write` checks for both read and\n// write access.\nenum class AccessCheckFlags : int {\n  Exists = F_OK,\n  Read = R_OK,\n  Write = W_OK,\n  Execute = X_OK,\n};\ninline auto operator|(AccessCheckFlags lhs, AccessCheckFlags rhs)\n    -> AccessCheckFlags {\n  return static_cast<AccessCheckFlags>(static_cast<int>(lhs) |\n                                       static_cast<int>(rhs));\n}\ninline auto operator|=(AccessCheckFlags& lhs, AccessCheckFlags rhs)\n    -> AccessCheckFlags& {\n  lhs = lhs | rhs;\n  return lhs;\n}\n\n// The underlying integer type that should be used to model the mode of a file.\n//\n// The mode is used in this API to represent both the permission bit mask and\n// special properties of a file. For example, on Unix-like systems, it combines\n// permissions with set-user-ID, set-group-ID, and sticky bits.\n//\n// The permission bits in the mode are represented using the Unix-style bit\n// pattern that facilitates octal modeling:\n// - Owner bit mask: 0700\n// - Group bit mask: 0070\n// - All bit mask:   0007\n//\n// For each, read is an octal value of `1`, write `2`, and execute `4`.\n//\n// Windows gracefully degrades to the effective permissions modeled using\n// these values.\nusing ModeType = mode_t;\n\n// Enumeration of the different file types recognized.\n//\n// In addition to the specific type values being arranged for ease of use with\n// the POSIX APIs, the underlying type of the enum is arranged to use the common\n// mode type.\nenum class FileType : ModeType {\n  // Portable file types that need to be supported across platform\n  // implementations.\n  Directory = S_IFDIR,\n  RegularFile = S_IFREG,\n  SymbolicLink = S_IFLNK,\n\n  // Non-portable Unix-like platform specific types.\n  UnixFifo = S_IFIFO,\n  UnixCharDevice = S_IFCHR,\n  UnixBlockDevice = S_IFBLK,\n  UnixSocket = S_IFSOCK,\n\n  // Mask for the Unix-like types to allow easy extraction.\n  UnixMask = S_IFMT,\n};\n\nusing Clock = std::chrono::file_clock;\nusing Duration = std::chrono::duration<__int128, std::nano>;\nusing TimePoint = std::chrono::time_point<Clock, Duration>;\n\n// Enumerates the different open access modes available.\n//\n// These are largely used to parameterize types in order to constrain which API\n// subset is available, and rarely needed directly.\nenum class OpenAccess {\n  ReadOnly = O_RDONLY,\n  WriteOnly = O_WRONLY,\n  ReadWrite = O_RDWR,\n};\n\n// Forward declarations of various types that appear in APIs.\nclass DirRef;\nclass Dir;\nclass RemovingDir;\ntemplate <OpenAccess A>\nclass FileRef;\ntemplate <OpenAccess A>\nclass File;\nclass FdError;\nclass PathError;\nnamespace Internal {\nclass FileRefBase;\n}  // namespace Internal\n\n// Returns a constant `Dir` object that models the open current working\n// directory.\n//\n// Whatever the working directory of the process is will be used as the base for\n// any relative path operations on this object. For example, on Unix-like\n// systems, `Cwd().Stat(\"some/path\")` is equivalent to `stat(\"some/path\")`.\nconsteval auto Cwd() -> Dir;\n\n// Creates a temporary directory and returns a removing directory handle to it.\n//\n// Each directory created will be unique and newly created by the call. It is\n// the caller's responsibility to clean up this directory.\nauto MakeTmpDir() -> ErrorOr<RemovingDir, Error>;\n\n// Creates a temporary directory and returns a removing directory handle to it.\n//\n// The path of the temporary directory will use the provided prefix, and will\n// not add any additional directory separators. Every component but the last in\n// the prefix path must exist and be a directory, the last directory must be\n// writable.\nauto MakeTmpDirWithPrefix(std::filesystem::path prefix)\n    -> ErrorOr<RemovingDir, Error>;\n\n// Class modeling a file (or directory) status information structure.\n//\n// This provides a largely-portable model that callers can use, as well as a few\n// APIs to access non-portable implementation details when necessary.\nclass FileStatus {\n public:\n  // The size of the file in bytes.\n  auto size() const -> int64_t { return stat_buf_.st_size; }\n\n  auto type() const -> FileType {\n    return static_cast<FileType>(stat_buf_.st_mode &\n                                 static_cast<ModeType>(FileType::UnixMask));\n  }\n\n  // Convenience predicates to test for specific values of `type()`.\n  auto is_dir() const -> bool { return type() == FileType::Directory; }\n  auto is_file() const -> bool { return type() == FileType::RegularFile; }\n  auto is_symlink() const -> bool { return type() == FileType::SymbolicLink; }\n\n  // The read, write, and execute permissions for user, group, and others. See\n  // the `ModeType` documentation for how to interpret the result.\n  auto permissions() const -> ModeType { return stat_buf_.st_mode & 0777; }\n\n  auto mtime() const -> TimePoint {\n    // Linux, FreeBSD, and OpenBSD all use `st_mtim`, but macOS uses a different\n    // spelling.\n#if __APPLE__\n    timespec ts = stat_buf_.st_mtimespec;\n#else\n    timespec ts = stat_buf_.st_mtim;\n#endif\n    TimePoint t(std::chrono::seconds(ts.tv_sec));\n    return t + std::chrono::nanoseconds(ts.tv_nsec);\n  }\n\n  // Non-portable APIs only available on Unix-like systems. See the\n  // documentation of the Unix `stat` structure fields they expose for their\n  // meaning.\n  auto unix_inode() const -> uint64_t { return stat_buf_.st_ino; }\n  auto unix_uid() const -> uid_t { return stat_buf_.st_uid; }\n\n private:\n  friend DirRef;\n  friend Internal::FileRefBase;\n\n  FileStatus() = default;\n\n  struct stat stat_buf_ = {};\n};\n\n// Models a held lock on a file or directory.\n//\n// Can model either a shared or exclusive lock with respect to the file, but the\n// held lock is unique.\n//\n// Must be released prior to the underlying file or directory being closed as it\n// contains a non-owning reference to that underlying file.\nclass FileLock {\n public:\n  enum class Kind {\n    Shared = LOCK_SH,\n    Exclusive = LOCK_EX,\n  };\n  using enum Kind;\n\n  FileLock() = default;\n  FileLock(FileLock&& arg) noexcept : fd_(std::exchange(arg.fd_, -1)) {}\n  auto operator=(FileLock&& arg) noexcept -> FileLock& {\n    Destroy();\n    fd_ = std::exchange(arg.fd_, -1);\n    return *this;\n  }\n  ~FileLock() { Destroy(); }\n\n  // Returns true if the lock is currently held.\n  auto is_locked() const -> bool { return fd_ != -1; }\n\n private:\n  friend Internal::FileRefBase;\n\n  explicit FileLock(int fd) : fd_(fd) {}\n\n  auto Destroy() -> void;\n\n  int fd_ = -1;\n};\n\n// The base class defining the core `File` API.\n//\n// While not used directly, this is the base class used to implement all of the\n// main `File` types: `ReadFileRef`, `WriteFileRef`, and `ReadWriteFileRef`.\n//\n// Objects using this type have access to an open file handle to a specific file\n// and expose operations on that open file. These operations may fail directly\n// with their `ErrorOr` return, but some errors may be deferred until the\n// underlying owning file is closed.\n//\n// The type provides reference semantics to the underlying file, but is\n// rebindable, movable, and copyable unlike a C++ language reference.\nclass Internal::FileRefBase {\n public:\n  // This object can be default constructed, but will hold an invalid file\n  // handle in that case. This is to support rebinding operations.\n  FileRefBase() = default;\n\n  // Returns true if this refers to a valid open file, and false otherwise.\n  auto is_valid() const -> bool { return fd_ != -1; }\n\n  // Reads the file status.\n  //\n  // Analogous to the Unix-like `fstat` call.\n  auto Stat() -> ErrorOr<FileStatus, FdError>;\n\n  // Updates the access and modification times for the open file.\n  //\n  // If no explicit `time_point` is provided, sets both times to the current\n  // time. If an explicit `time_point` is provided, the times are updated to\n  // that time.\n  auto UpdateTimes(std::optional<TimePoint> time_point = std::nullopt)\n      -> ErrorOr<Success, FdError>;\n\n  // Methods to seek the current file position, with various semantics for the\n  // offset.\n  auto Seek(int64_t delta) -> ErrorOr<int64_t, FdError>;\n  auto SeekFromBeginning(int64_t delta_from_beginning)\n      -> ErrorOr<int64_t, FdError>;\n  auto SeekFromEnd(int64_t delta_from_end) -> ErrorOr<int64_t, FdError>;\n\n  // Truncates or extends the size of the file to the provided size.\n  //\n  // If the new size is smaller, all bytes beyond this size will be unavailable.\n  // If the new size is larger, the file will be zero-filled to the new size.\n  // The position of reads and writes does not change.\n  auto Truncate(int64_t new_size) -> ErrorOr<Success, FdError>;\n\n  // Reads as much data as is available and fits into the provided buffer.\n  //\n  // On success, this returns a new slice from the start to the end of the\n  // successfully read bytes. These will always be located in the passed-in\n  // buffer, but not all of the buffer may be filled. A partial read does not\n  // mean that the end of the file has been reached.\n  //\n  // When a successful read with an *empty* slice is returned, that represents\n  // reaching EOF on the underlying file successfully and there is no more data\n  // to read.\n  //\n  // This method retries `EINTR` on Unix-like systems and returns\n  // other errors to the caller.\n  auto ReadToBuffer(llvm::MutableArrayRef<std::byte> buffer)\n      -> ErrorOr<llvm::MutableArrayRef<std::byte>, FdError>;\n\n  // Writes as much data as possible from the provided buffer.\n  //\n  // On success, this returns a new slice of the *unwritten* bytes still present\n  // in the buffer. An empty return represents a successful write of all bytes\n  // in the buffer. A non-empty return does not represent an error or the\n  // inability to finish writing.\n  //\n  // This method retries `EINTR` on Unix-like systems and returns\n  // other errors to the caller.\n  auto WriteFromBuffer(llvm::ArrayRef<std::byte> buffer)\n      -> ErrorOr<llvm::ArrayRef<std::byte>, FdError>;\n\n  // Returns an LLVM `raw_fd_ostream` that writes to this file.\n  //\n  // Note that this doesn't expose any write errors here, those will surface\n  // through the `raw_fd_ostream` API. The stream will also not close the file\n  // which remains owned by the owning `File` object.\n  auto WriteStream() -> llvm::raw_fd_ostream;\n\n  // Reads the file from its start until EOF into the returned string.\n  //\n  // This method will retry any recoverable errors and work to completely read\n  // the file contents from its beginning up to first encountering EOF. This\n  // will seek the file to ensure it starts at the beginning regardless of\n  // previous read or write operations.\n  //\n  // Any non-recoverable errors are returned to the caller.\n  auto ReadFileToString() -> ErrorOr<std::string, FdError>;\n\n  // Writes the provided string to the file from the start and truncating to the\n  // written size.\n  //\n  // This method will retry any recoverable errors and work to completely write\n  // the provided content into the file from its beginning, and truncate the\n  // file's size to the provided string size. Essentially, this function\n  // replaces the file contents with the string's contents.\n  //\n  // Any non-recoverable errors are returned to the caller.\n  auto WriteFileFromString(llvm::StringRef str) -> ErrorOr<Success, FdError>;\n\n  // Attempt to acquire an advisory shared lock on this directory.\n  //\n  // This is always done as a non-blocking operation, as blocking on advisory\n  // locks without a deadline can easily result in build systems essentially\n  // \"fork-bombing\" a machine. However, a `deadline` duration can be provided\n  // and this routine will block and attempt to acquire the requested lock for a\n  // bounded amount of time approximately based on that duration. Further, a\n  // `poll_interval` can be provided to control how quickly the lock will be\n  // polled during that duration. There is no scaling of the poll intervals at\n  // this layer, if a back-off heuristic is desired the caller should manage the\n  // polling themselves. The goal is to allow simple cases of spurious failures\n  // to be easily handled without unbounded blocking calls. Typically, callers\n  // should use a duration that is a reasonable upper bound on the latency to\n  // begin the locked operation and a poll interval that is a reasonably low\n  // median latency to begin the operation as 1-2 polls is expected to be\n  // common. These should not be set anywhere near the cost of acquiring a file\n  // lock, and in general file locks should only be used for expensive\n  // operations where it is worth significant delays to avoid duplicate work.\n  //\n  // If the lock cannot be acquired, the most recent lock-attempt error is\n  // returned.\n  auto TryLock(FileLock::Kind kind, Duration deadline = {},\n               Duration poll_interval = {}) -> ErrorOr<FileLock, FdError>;\n\n protected:\n  explicit FileRefBase(int fd) : fd_(fd) {}\n\n  // Note: this should only be used or made part of the public API by subclasses\n  // that provide *ownership* of the open file. It is implemented here to\n  // provide a single, non-templated implementation.\n  auto Close() && -> ErrorOr<Success, FdError>;\n\n  // Factored out code to destroy an open read-only file. This calls `Close`\n  // above but ignores any errors as there is no risk of data loss for a\n  // read-only file.\n  //\n  // Note: this is a private API that should not be made public, and should only\n  // be used by the implementation of subclass destructors. It should also only\n  // be called for subclasses with *ownership* of the file reference, and is\n  // provided here as a single non-template implementation.\n  auto ReadOnlyDestroy() -> void;\n\n  // Factored out code to destroy an open writable file. This _requires_ the\n  // file to have already been closed with an explicit `Close` call, where it\n  // can report any errors. Without that, destroying a writable file can easily\n  // result in unnoticed data loss.\n  //\n  // Note: this is a private API that should not be made public, and should only\n  // be used by the implementation of subclass destructors. It should also only\n  // be called for subclasses with *ownership* of the file reference, and is\n  // provided here as a single non-template implementation.\n  auto WriteableDestroy() -> void;\n\n  // State representing a potentially open file.\n  //\n  // On POSIX systems, this will be a file descriptor. For moved-from and\n  // default-constructed file objects this may be an invalid negative value to\n  // signal that state.\n  //\n  // TODO: This should be customized on non-POSIX systems.\n  //\n  // This member is made protected rather than private as the derived classes\n  // need direct access to it in several contexts.\n  // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)\n  int fd_ = -1;\n};\n\n// A non-owning reference to an open file.\n//\n// Instances model a reference to an open file. Generally, rather than using a\n// `WriteFile&`, code should use a `WriteFileRef`.\n//\n// A specific instance provides the subset of the file API suitable for its\n// access based on its template parameter: read, write, or both.\n//\n// The API for file references is factored into a base class\n// `Internal::FileRefBase` to avoid duplication for each access instantiation.\n// Only the methods that are constrained by access are defined here, and they\n// are defined as wrappers around methods in the base where the documentation\n// and implementation live.\ntemplate <OpenAccess A>\nclass FileRef : public Internal::FileRefBase {\n public:\n  static constexpr bool Readable =\n      A == OpenAccess::ReadOnly || A == OpenAccess::ReadWrite;\n  static constexpr bool Writeable =\n      A == OpenAccess::WriteOnly || A == OpenAccess::ReadWrite;\n\n  // This object can be default constructed, but will hold an invalid file\n  // handle in that case. This is to support rebinding operations.\n  FileRef() = default;\n\n  // Read and Write methods that delegate to the `FileRefBase` implementations,\n  // but require the relevant access. See the methods on `FileRefBase` for full\n  // documentation.\n  auto Truncate(int64_t new_size) -> ErrorOr<Success, FdError>\n    requires Writeable;\n  auto ReadToBuffer(llvm::MutableArrayRef<std::byte> buffer)\n      -> ErrorOr<llvm::MutableArrayRef<std::byte>, FdError>\n    requires Readable;\n  auto WriteFromBuffer(llvm::ArrayRef<std::byte> buffer)\n      -> ErrorOr<llvm::ArrayRef<std::byte>, FdError>\n    requires Writeable;\n  auto WriteStream() -> llvm::raw_fd_ostream\n    requires Writeable;\n  auto ReadFileToString() -> ErrorOr<std::string, FdError>\n    requires Readable;\n  auto WriteFileFromString(llvm::StringRef str) -> ErrorOr<Success, FdError>\n    requires Writeable;\n\n protected:\n  friend File<A>;\n  friend DirRef;\n\n  // Other constructors from the base are also available, but remain protected.\n  using FileRefBase::FileRefBase;\n};\n\n// Convenience type defs for the three access combinations.\nusing ReadFileRef = FileRef<OpenAccess::ReadOnly>;\nusing WriteFileRef = FileRef<OpenAccess::WriteOnly>;\nusing ReadWriteFileRef = FileRef<OpenAccess::ReadWrite>;\n\n// An owning handle to an open file.\n//\n// This extends the `FileRef` API to provide ownership of the file handle. Most\n// of the API is defined by `FileRef`.\n//\n// The file will be closed when the object is destroyed, and must close without\n// errors. If there is a chance of errors on close, and that is often where\n// errors are reported, code must use the `Close` API to directly handle them or\n// it must be correct to check-fail on them.\n//\n// This type allows intentional \"slicing\" to the `FileRef` base class as that is\n// a correct and safe conversion to pass a non-owning reference to a file to\n// another function, much like binding a reference to an owning type is\n// implicit.\ntemplate <OpenAccess A>\nclass File : public FileRef<A> {\n public:\n  static constexpr bool Readable =\n      A == OpenAccess::ReadOnly || A == OpenAccess::ReadWrite;\n  static constexpr bool Writeable =\n      A == OpenAccess::WriteOnly || A == OpenAccess::ReadWrite;\n\n  // Default constructs an invalid file.\n  //\n  // This can be destroyed or assigned safely, but no other operations are\n  // correct.\n  File() = default;\n\n  // File objects are move-only as they model ownership.\n  File(File&& arg) noexcept : FileRef<A>(std::exchange(arg.fd_, -1)) {}\n  auto operator=(File&& arg) noexcept -> File& {\n    Destroy();\n    this->fd_ = std::exchange(arg.fd_, -1);\n    return *this;\n  }\n  File(const File&) = delete;\n  auto operator=(const File&) -> File& = delete;\n  ~File() { Destroy(); }\n\n  // Closes the open file and leaves the file in a moved-from state.\n  //\n  // The signature is `auto Close() && -> ErrorOr<Success, FdError>`.\n  //\n  // This type provides ownership of the file, so expose the `Close` method to\n  // allow checked destruction and release of the file resources.\n  //\n  // If any errors are encountered during closing, returns them. Note that the\n  // file should still be considered closed, and the object is moved-from even\n  // if errors occur.\n  using Internal::FileRefBase::Close;\n\n private:\n  friend DirRef;\n\n  // Destroy the file.\n  //\n  // This dispatches to non-template code in `FileRefBase` based on whether the\n  // file is writable or readonly. The core logic is in the non-template\n  // methods.\n  auto Destroy() -> void;\n\n  explicit File(int fd) : FileRef<A>(fd) {}\n};\n\n// Convenience type defs for the three access combinations.\nusing ReadFile = File<OpenAccess::ReadOnly>;\nusing WriteFile = File<OpenAccess::WriteOnly>;\nusing ReadWriteFile = File<OpenAccess::ReadWrite>;\n\n// A non-owning reference to an open directory.\n//\n// This is the main API for accessing and opening files and other directories.\n// Conceptually, every open file or directory is relative to some other\n// directory. The symbolic current working directory object is available via the\n// `Cwd()` function. When on a Unix-like platform, this is intended to provide\n// the semantics of `openat` and related functions, including the ability to\n// write secure filesystem operations in the face of adversarial parallel\n// filesystem operations.\n//\n// Relative path parameters are always relative to this directory. Absolute path\n// parameters are also allowed and are treated as absolute paths. This parallels\n// the behavior of `/` for path concatenation where an absolute path ignores all\n// preceding components.\n//\n// Errors for directory operations retain the path parameter used in order to\n// print helpful detail when unhandled, but otherwise work to be lazy and\n// lightweight to support low-overhead expected error patterns.\n//\n// The names are designed to mirror the underlying Unix-like APIs that implement\n// them, with extensions to add clarity. However, the set of operations is\n// expected to be reasonable to implement on Windows with reasonable fidelity.\nclass DirRef {\n public:\n  class Entry;\n  class Iterator;\n  class Reader;\n\n  constexpr DirRef() = default;\n\n  // Returns true if this refers to a valid open directory, and false otherwise.\n  auto is_valid() const -> bool { return dfd_ != -1; }\n\n  // Begin reading the entries in a directory.\n  //\n  // This returns a `Reader` object that can be iterated to walk over all the\n  // entries in this directory. Note that the returned `Reader` owns a newly\n  // allocated handle to this directory, and provides the full `DirRef` API. If\n  // it isn't necessary to keep both open, the `Dir` class offers a\n  // move-qualified method `TakeAndRead` that optimizes this case.\n  //\n  // Note that it is unspecified whether added and removed files during the\n  // lifetime of the reader will be included when iterating, but otherwise\n  // concurrent mutations are well defined.\n  auto Read() -> ErrorOr<Reader, FdError>;\n\n  // Reads all of the entries in this directory into a vector.\n  //\n  // A helper function wrapping `Read` and walking the resulting reader's\n  // entries to produce a container.\n  //\n  // For details on errors, see the documentation of `Read` and `Reader`.\n  auto ReadEntries()\n      -> ErrorOr<llvm::SmallVector<std::filesystem::path>, FdError>;\n\n  // Reads the directory and appends entries to a container if they pass a\n  // predicate. The predicate can be null, which is treated as if it always\n  // returns true.\n  //\n  // For details on errors, see the documentation of `Read` and `Reader`.\n  auto AppendEntriesIf(\n      llvm::SmallVectorImpl<std::filesystem::path>& entries,\n      llvm::function_ref<auto(llvm::StringRef name)->bool> predicate = {})\n      -> ErrorOr<Success, FdError>;\n\n  // Reads the directory and appends entries to one of two containers if they\n  // pass a predicate.  The predicate can be null, which is treated as if it\n  // always returns true.\n  //\n  // Which container an entry is appended to depends on its kind -- directories\n  // go to the first and non-directories go to the second. This turns out to be\n  // a very common split with subdirectories often needing separate handling\n  // from other entries.\n  //\n  // For details on errors, see the documentation of `Read` and `Reader`. This\n  // may also `Stat` entries if necessary to determine whether they are\n  // directories.\n  auto AppendEntriesIf(\n      llvm::SmallVectorImpl<std::filesystem::path>& dir_entries,\n      llvm::SmallVectorImpl<std::filesystem::path>& non_dir_entries,\n      llvm::function_ref<auto(llvm::StringRef name)->bool> predicate = {})\n      -> ErrorOr<Success, FdError>;\n\n  // Checks that the provided path can be accessed.\n  auto Access(const std::filesystem::path& path,\n              AccessCheckFlags check = AccessCheckFlags::Exists)\n      -> ErrorOr<bool, PathError>;\n\n  // Reads the `FileStatus` for the open directory.\n  auto Stat() -> ErrorOr<FileStatus, FdError>;\n\n  // Reads the `FileStatus` for the provided path (without opening it).\n  //\n  // Like the `stat` system call on Unix-like platforms, this will follow any\n  // symlinks and provide the status of the underlying file or directory.\n  auto Stat(const std::filesystem::path& path)\n      -> ErrorOr<FileStatus, PathError>;\n\n  // Reads the `FileStatus` for the provided path (without opening it).\n  //\n  // Like the `lstat` system call on Unix-like platforms, this will *not* follow\n  // symlinks, and instead will return the status of the symlink itself.\n  auto Lstat(const std::filesystem::path& path)\n      -> ErrorOr<FileStatus, PathError>;\n\n  // Updates the access and modification times for the provided path.\n  //\n  // If no explicit `time_point` is provided, sets both times to the current\n  // time. If an explicit `time_point` is provided, the times are updated to\n  // that time.\n  auto UpdateTimes(const std::filesystem::path& path,\n                   std::optional<TimePoint> time_point = std::nullopt)\n      -> ErrorOr<Success, PathError>;\n\n  // Reads the target string of the symlink at the provided path.\n  //\n  // This does not follow the symlink, and does not require the symlink target\n  // to be valid or exist. It merely reads the textual string.\n  //\n  // Returns an error if called with a path that is not a symlink.\n  auto Readlink(const std::filesystem::path& path)\n      -> ErrorOr<std::string, PathError>;\n\n  // Opens the provided path as a read-only file.\n  //\n  // The interaction with an existing file is governed by `creation_options` and\n  // defaults to error unless opening an existing file. When creating a file,\n  // only the leaf component in the provided path can be created with this call.\n  //\n  // If creating a file, the file is created with `creation_mode` which defaults\n  // to a restrictive `0600`. The creation permission bits are also completely\n  // independent of the access provided via the opened file. For example,\n  // creating with write permissions doesn't impact whether write access is\n  // available via the returned file. And creating _without_ write permission\n  // bits is compatible with opening the file for writing.\n  //\n  // Additional flags can be provided to `flags` to control other aspects of\n  // behavior on open.\n  //\n  // This is an error if the path exists and is a directory. If the path is a\n  // symlink, it will follow the symlink.\n  auto OpenReadOnly(const std::filesystem::path& path,\n                    CreationOptions creation_options = OpenExisting,\n                    ModeType creation_mode = 0600,\n                    OpenFlags flags = OpenFlags::None)\n      -> ErrorOr<ReadFile, PathError>;\n\n  // Opens the provided path as a write-only file. Otherwise, behaves as\n  // `OpenReadOnly`.\n  auto OpenWriteOnly(const std::filesystem::path& path,\n                     CreationOptions creation_options = OpenExisting,\n                     ModeType creation_mode = 0600,\n                     OpenFlags flags = OpenFlags::None)\n      -> ErrorOr<WriteFile, PathError>;\n\n  // Opens the provided path as a read-and-write file. Otherwise, behaves as\n  // `OpenReadOnly`.\n  auto OpenReadWrite(const std::filesystem::path& path,\n                     CreationOptions creation_options = OpenExisting,\n                     ModeType creation_mode = 0600,\n                     OpenFlags flags = OpenFlags::None)\n      -> ErrorOr<ReadWriteFile, PathError>;\n\n  // Opens the provided path as a directory.\n  //\n  // Similar to `OpenReadOnly` and other file opening APIs, accepts\n  // `creation_options` to control the interaction with any existing directory.\n  // However, `CreateAlways` is not implementable for directories and an error\n  // if passed. The default permissions in the `creation_mode` are `0700` which\n  // is more suitable for directories. There are no extra flags that can be\n  // passed.\n  //\n  // As with other open routines, when creating a directory, only the leaf\n  // component can be created by the call to this routine.\n  //\n  // When creating a directory with `CreateNew`, this routine works to be safe\n  // even in the presence of adversarial, concurrent operations that attempt to\n  // replace the created directory with one that is controlled by the adversary.\n  //\n  // Specifically, for `CreateNew` we ensure that the last component is a\n  // created directory in its parent, and cannot be replaced by a symlink into\n  // an attacker-controlled directory. We further ensure it cannot have been\n  // replaced by a directory with a different owner or with wider permissions\n  // than the created directory.\n  //\n  // However, no validation is done on any prefix path components leading to the\n  // leaf component created. When securely creating directories, the initial\n  // creation should have a single component from an opened existing parent\n  // directory. Also, no validation of the owning _group_ is performed. When\n  // securely creating a directory, the caller should either ensure the parent\n  // directory does not have a malicious setgid bit set, or restrict the\n  // created mode to not give group access, or both. In general, the lack of\n  // control over the owning group motivates our choice to make the default mode\n  // permissions restrictive and not include any group access.\n  //\n  // To securely achieve a result similar to `OpenAlways` instead of\n  // `CreateNew`, callers can directly `CreateNew` and handle failures with an\n  // explicit `OpenExisting` that also blocks following symlinks with\n  // `OpenFlags::NoFollow` and performs any needed validation.\n  auto OpenDir(const std::filesystem::path& path,\n               CreationOptions creation_options = OpenExisting,\n               ModeType creation_mode = 0700, OpenFlags flags = OpenFlags::None)\n      -> ErrorOr<Dir, PathError>;\n\n  // Reads the file at the provided path to a string.\n  //\n  // This is a convenience wrapper for opening the path, reading the returned\n  // file to a string, and closing it. Errors from any step are returned.\n  auto ReadFileToString(const std::filesystem::path& path)\n      -> ErrorOr<std::string, PathError>;\n\n  // Writes the provided `content` to the provided path.\n  //\n  // This is a convenience wrapper for opening the path, creating it according\n  // to `creation_options` as necessary, writing `content` to it, and closing\n  // it. Errors from any step are returned.\n  auto WriteFileFromString(const std::filesystem::path& path,\n                           llvm::StringRef content,\n                           CreationOptions creation_options = CreateAlways)\n      -> ErrorOr<Success, PathError>;\n\n  // Renames an entry from one directory to another directory, replacing any\n  // existing entry with the target path.\n  //\n  // Note that this is *not* a general purpose move! It must be possible for\n  // this operation to be performed as a metadata-only change, and so without\n  // moving any actual data. This means it will not work across devices, mounts,\n  // or filesystems. However, these restrictions make this an *atomic* rename.\n  //\n  // The most common usage is to rename an entry within a single directory, by\n  // passing `*this` as `target_dir`.\n  auto Rename(const std::filesystem::path& path, DirRef target_dir,\n              const std::filesystem::path& target_path)\n      -> ErrorOr<Success, PathError>;\n\n  // Changes the current working directory to this directory.\n  auto Chdir() -> ErrorOr<Success, FdError>;\n\n  // Changes the current working directory to the provided path.\n  //\n  // An error if the provided path is not a directory. Does not open the\n  // provided path as a directory, but it will be available as the current\n  // working directory via `Cwd()`.\n  auto Chdir(const std::filesystem::path& path) -> ErrorOr<Success, PathError>;\n\n  // Creates a symlink at the provided path with the contents of `target`.\n  //\n  // Note that the target of a symlink is an arbitrary string and there is no\n  // error checking on whether it exists or is sensible. Also, the target string\n  // set will be up to the first null byte in `target`, regardless of its\n  // `size`. This will not overwrite an existing symlink at the provided path.\n  //\n  // Also note that the written symlink will be the null-terminated string\n  // `target.c_str()`, ignoring everything past any embedded null bytes.\n  auto Symlink(const std::filesystem::path& path, const std::string& target)\n      -> ErrorOr<Success, PathError>;\n\n  // Creates the directories in the provided path, using the permissions in\n  // `creation_mode`.\n  //\n  // This will create any missing directory components in `path`. Relative paths\n  // will be created relative to this directory, and without re-resolving its\n  // path. The leaf created directory is opened and returned.\n  //\n  // The implementation allows for concurrent creation of the same directory (or\n  // a prefix) without error or corruption and optimizes for performance of\n  // creating the requested path. As a consequence, this creation is _unsafe_ in\n  // the face of adversarial concurrent manipulation of components of the path.\n  // If you need to create directories securely, first create an initial\n  // directory securely using `OpenDir` and `CreateNew` with restricted\n  // permissions that preclude any adversarial behavior, then use this API to\n  // create tree components within that root.\n  auto CreateDirectories(const std::filesystem::path& path,\n                         ModeType creation_mode = 0700)\n      -> ErrorOr<Dir, PathError>;\n\n  // Unlink the last component of the path, removing that name from its parent\n  // directory.\n  //\n  // If this was the last link to the underlying file its contents will be\n  // removed when the last open file handle to it is closed.\n  //\n  // The path must not be a directory. If the path is a symbolic link, the link\n  // will be removed, not the target. Models the behavior of `unlinkat(2)` on\n  // Unix-like platforms.\n  auto Unlink(const std::filesystem::path& path) -> ErrorOr<Success, PathError>;\n\n  // Remove the directory entry of the last component of the path.\n  //\n  // The path must be a directory, and that directory must be empty. Models\n  // `rmdirat(2)` on Unix-like platforms.\n  auto Rmdir(const std::filesystem::path& path) -> ErrorOr<Success, PathError>;\n\n  // Remove the directory tree identified by the last component of the path.\n  //\n  // The provided path must name a directory. This removes all files and\n  // subdirectories contained within that named directory and then removes the\n  // directory itself once empty.\n  auto Rmtree(const std::filesystem::path& path) -> ErrorOr<Success, PathError>;\n\n protected:\n  constexpr explicit DirRef(int dfd) : dfd_(dfd) {}\n\n  // Slow-path fallback when unable to read the symlink target into a small\n  // stack buffer.\n  auto ReadlinkSlow(const std::filesystem::path& path)\n      -> ErrorOr<std::string, PathError>;\n\n  // Generic implementation of the various `Open*` variants using the\n  // `OpenAccess` enumerator.\n  template <OpenAccess A>\n  auto OpenImpl(const std::filesystem::path& path,\n                CreationOptions creation_options, ModeType creation_mode,\n                OpenFlags flags) -> ErrorOr<File<A>, PathError>;\n\n  // State representing an open directory.\n  //\n  // On POSIX systems, this will be a file descriptor. For moved-from and\n  // default-constructed file objects this may be an invalid negative value to\n  // signal that state.\n  //\n  // TODO: This should be customized on non-POSIX systems.\n  //\n  // The directory's file descriptor is part of the protected API.\n  // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes):\n  int dfd_ = -1;\n};\n\n// An owning handle to an open directory.\n//\n// This extends the `DirRef` API to provide ownership of the directory. Most of\n// the API is defined by `DirRef`. It additionally provides optimized move-based\n// variations on those APIs where relevant.\n//\n// The directory will be closed when the object is destroyed. Closing an open\n// directory isn't an interesting error reporting path and so no direct close\n// API is provided.\n//\n// This type allows intentional \"slicing\" to the `DirRef` base class as that is\n// a correct and safe conversion to pass a non-owning reference to a directory\n// to another function, much like binding a reference to an owning type is\n// implicit.\nclass Dir : public DirRef {\n public:\n  Dir() = default;\n\n  // Dir objects are move-only as they model ownership.\n  Dir(Dir&& arg) noexcept : DirRef(std::exchange(arg.dfd_, -1)) {}\n  auto operator=(Dir&& arg) noexcept -> Dir& {\n    Destroy();\n    dfd_ = std::exchange(arg.dfd_, -1);\n    return *this;\n  }\n  Dir(const Dir&) = delete;\n  auto operator=(const Dir&) -> Dir& = delete;\n  constexpr ~Dir();\n\n  // An optimized way to read the entries in a directory when moving from an\n  // owning `Dir` object.\n  //\n  // This avoids creating a duplicate file handle for the returned `Reader`.\n  // That `Reader` also supports the full `DirRef` API and so can often be used\n  // without retaining the original `Dir`.\n  //\n  // For more details about reading, see the documentation on `DirRef::Read`.\n  auto TakeAndRead() && -> ErrorOr<Reader, FdError>;\n\n  // Also include `DirRef`'s read API.\n  using DirRef::Read;\n\n private:\n  friend consteval auto Cwd() -> Dir;\n  friend DirRef;\n  friend RemovingDir;\n\n  explicit constexpr Dir(int dfd) : DirRef(dfd) {}\n\n  // Prevent implicit creation of a `Dir` object from a `RemovingDir` which will\n  // end up as a subclass below and represent harmful implicit slicing. Instead,\n  // require friendship and an explicit construction on an _intended_ release of\n  // the removing semantics.\n  explicit Dir(RemovingDir&& arg) noexcept;\n\n  constexpr auto Destroy() -> void;\n};\n\n// An owning handle to an open directory and its absolute path that will be\n// removed recursively when destroyed.\n//\n// This can be used to ensure removal of a directory, and also exposes the\n// absolute path of the directory.\n//\n// As removal may encounter errors, unless the desired behavior is a\n// check-failure, users should explicitly move and call `Remove` at the end of\n// lifetime and handle any resultant errors.\nclass RemovingDir : public Dir {\n public:\n  // Takes ownership of the open directory `d` and wraps it in a `RemovingDir`\n  // that will remove it on destruction using `path`. Note that for a relative\n  // `path`, the removal will re-resolve this relative to the current working\n  // directory on removal.\n  //\n  // Note that there is no way for the implementation to validate what directory\n  // `path` refers to, that is the responsibility of the caller.\n  explicit RemovingDir(Dir d, std::filesystem::path path)\n      : Dir(std::move(d)), path_(std::move(path)) {}\n\n  RemovingDir() = default;\n  RemovingDir(RemovingDir&& arg) = default;\n  auto operator=(RemovingDir&& rhs) -> RemovingDir& = default;\n  ~RemovingDir();\n\n  auto path() const [[clang::lifetimebound]] -> const std::filesystem::path& {\n    return path_;\n  }\n\n  // Releases the directory from being removed and returns just the underlying\n  // owning handle.\n  auto Release() && -> Dir { return std::move(*this); }\n\n  // Removes the directory immediately and surfaces any errors encountered.\n  auto Remove() && -> ErrorOr<Success, PathError>;\n\n private:\n  friend Dir;\n\n  std::filesystem::path path_;\n};\n\n// A named entry in a directory.\n//\n// This provides access to the scanned data when reading the entries of the\n// directory. It can only be produced by iterating over a `DirRef::Reader`.\nclass DirRef::Entry {\n public:\n  // The name of the entry.\n  //\n  // This is exposed as a null-terminated C-string as that is the most common\n  // representation.\n  auto name() const -> const char* { return dent_->d_name; }\n\n  // Test if the entry has an unknown type. In this case, all other type\n  // predicates will return false and the caller will have to directly `Lstat()`\n  // the entry to determine its type.\n  auto is_unknown_type() const -> bool { return dent_->d_type == DT_UNKNOWN; }\n\n  // Predicates to test for known entry types.\n  //\n  // Note that we don't provide an enumerator here as we don't have any reliable\n  // way to predict the set of possible values or narrow to that set. Different\n  // platforms and even different versions of the same header may change the set\n  // of types surfaced here.\n  auto is_known_dir() const -> bool { return dent_->d_type == DT_DIR; }\n  auto is_known_regular_file() const -> bool { return dent_->d_type == DT_REG; }\n  auto is_known_symlink() const -> bool { return dent_->d_type == DT_LNK; }\n\n private:\n  friend Dir::Reader;\n  friend Dir::Iterator;\n\n  Entry() = default;\n  explicit Entry(dirent* dent) : dent_(dent) {}\n\n  dirent* dent_ = nullptr;\n};\n\n// An iterator into a `DirRef::Reader`, used for walking the entries in a\n// directory.\n//\n// Most of the work of iterating a directory is done when constructing the\n// `Reader`, when constructing the beginning iterator, or when incrementing the\n// iterator.\nclass DirRef::Iterator\n    : public llvm::iterator_facade_base<Iterator, std::input_iterator_tag,\n                                        const Entry> {\n public:\n  // Default construct a general end iterator.\n  Iterator() = default;\n\n  auto operator==(const Iterator& rhs) const -> bool {\n    CARBON_DCHECK(dirp_ == nullptr || rhs.dirp_ == nullptr ||\n                  dirp_ == rhs.dirp_);\n    return entry_.dent_ == rhs.entry_.dent_;\n  }\n\n  auto operator*() const [[clang::lifetimebound]] -> const Entry& {\n    return entry_;\n  }\n  auto operator++() -> Iterator&;\n\n private:\n  friend Dir::Reader;\n\n  // Construct a begin iterator for a specific directory stream.\n  explicit Iterator(DIR* dirp) : dirp_(dirp) {\n    // Increment immediately to populate the initial entry.\n    ++*this;\n  }\n\n  DIR* dirp_ = nullptr;\n  Entry entry_;\n};\n\n// A reader for a directory.\n//\n// This class owns a handle to a directory that is set up for reading the\n// entries within the directory. Because it owns a handle to the directory, it\n// also implements the full `DirRef` API for convenience.\n//\n// Beyond the `DirRef` API, this object can be iterated as a range to visit all\n// the entries in the directory.\n//\n// Note that it is unspecified whether entries added or removed prior to being\n// visited while iterating. Iterating also cannot be re-started once begun --\n// this models an input iterable range, not even a forward iterable range.\n//\n// This type allows intentional \"slicing\" to the `DirRef` base class as that is\n// a correct and safe conversion to pass a non-owning reference to a directory\n// to another function, much like binding a reference to an owning type is\n// implicit.\nclass DirRef::Reader : public DirRef {\n public:\n  Reader() = default;\n  Reader(Reader&& arg) noexcept\n      // The directory file descriptor isn't owning, but clear it for clarity.\n      : DirRef(std::exchange(arg.dfd_, -1)),\n        dirp_(std::exchange(arg.dirp_, nullptr)) {}\n  Reader(const Reader&) = delete;\n  auto operator=(Reader&& arg) noexcept -> Reader& {\n    Destroy();\n    // The directory file descriptor isn't owning, but clear it for clarity.\n    dfd_ = std::exchange(arg.dfd_, -1);\n    dirp_ = std::exchange(arg.dirp_, nullptr);\n    return *this;\n  }\n  ~Reader() { Destroy(); }\n\n  // Compute the begin and end iterators for reading the entries of the\n  // directory.\n  auto begin() -> Iterator;\n  auto end() -> Iterator;\n\n private:\n  friend DirRef;\n  friend Dir;\n\n  explicit Reader(DIR* dirp) : DirRef(dirfd(dirp)), dirp_(dirp) {}\n  auto Destroy() -> void;\n\n  DIR* dirp_ = nullptr;\n};\n\nnamespace Internal {\n// Base class for `errno` errors.\n//\n// This is where we extract common APIs and logic for querying the specific\n// `errno`-based error.\ntemplate <typename ErrorT>\nclass ErrnoErrorBase : public ErrorBase<ErrorT> {\n public:\n  // Accessors to test for specific kinds of errors that are portably available.\n  auto already_exists() const -> bool { return errnum_ == EEXIST; }\n  auto is_dir() const -> bool { return errnum_ == EISDIR; }\n  auto no_entity() const -> bool { return errnum_ == ENOENT; }\n  auto not_dir() const -> bool { return errnum_ == ENOTDIR; }\n  auto access_denied() const -> bool { return errnum_ == EACCES; }\n  auto would_block() const -> bool { return errnum_ == EWOULDBLOCK; }\n\n  // Specific to `Rmdir` and `Rename` operations that remove a directory name,\n  // two different error values can be used.\n  auto not_empty() const -> bool {\n    return errnum_ == ENOTEMPTY || errnum_ == EEXIST;\n  }\n\n  // Accessor for the `errno` based error number. This is not a portable API,\n  // code using it will need to be ported to use a different API on Windows.\n  // TODO: Add a Windows-specific API for its low-level error information.\n  auto unix_errnum() const -> int { return errnum_; }\n\n protected:\n  // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility):\n  explicit ErrnoErrorBase(int errnum) : errnum_(errnum) {}\n\n private:\n  int errnum_;\n};\n}  // namespace Internal\n\n// Error from a file-descriptor operation.\n//\n// This is the implementation of the file-descriptor-based error type. When\n// operations on a file descriptor fail, they use this object to convey the\n// error plus the descriptor in question.\n//\n// Specific context on the exact point or nature of the operation that failed\n// can be included in the custom format string. The format string should include\n// a placeholder for the file descriptor to be substituted into. The format\n// string should describe the _operation_ that failed, once rendered it will\n// have `failed: ` and a description of the `errno`-indicated failure appended.\n//\n// For example:\n//\n//   `FdError(EPERM, \"Read of file '{0}'\", 42)`\n//\n// Will be rendered similarly to:\n//\n//   \"Read of file '42' failed: EPERM: ...\"\nclass FdError : public Internal::ErrnoErrorBase<FdError> {\n public:\n  FdError(FdError&&) noexcept = default;\n  auto operator=(FdError&&) noexcept -> FdError& = default;\n\n  // Prints this error to the provided string.\n  //\n  // Works to render the `errno` in a friendly way and includes the file\n  // descriptor for context.\n  auto Print(llvm::raw_ostream& out) const -> void;\n\n private:\n  friend FileLock;\n  friend Internal::FileRefBase;\n  friend ReadFile;\n  friend WriteFile;\n  friend ReadWriteFile;\n  friend DirRef;\n  friend Dir;\n\n  explicit FdError(int errnum, llvm::StringLiteral format, int fd)\n      : ErrnoErrorBase(errnum), fd_(fd), format_(format) {}\n\n  int fd_;\n  llvm::StringLiteral format_;\n};\n\n// Error from a path-based operation.\n//\n// This is the implementation of the path-based error type. When operations on a\n// path fail, they use this object to convey the error plus both the path and\n// relevant directory FD leading to the failure.\n//\n// Specific context on the exact point or nature of the operation that failed\n// can be included in the custom format string. The format string should include\n// placeholders for the path and the directory file descriptor to be substituted\n// into. The format string should describe the _operation_ that failed, once\n// rendered it will have `failed: ` and a description of the `errno`-indicated\n// failure appended.\n//\n// For example:\n//\n//   `PathError(EPERM, \"Open of '{0}' relative to '{1}'\", \"filename\", 42)`\n//\n// Will be rendered similarly to:\n//\n//   \"Open of 'filename' relative to '42' failed: EPERM: ...\"\nclass PathError : public Internal::ErrnoErrorBase<PathError> {\n public:\n  PathError(PathError&&) noexcept = default;\n  auto operator=(PathError&&) noexcept -> PathError& = default;\n\n  // Prints this error to the provided string.\n  //\n  // Works to render the `errno` in a friendly way and includes the path and\n  // directory file descriptor for context.\n  auto Print(llvm::raw_ostream& out) const -> void;\n\n private:\n  friend DirRef;\n  friend Dir;\n\n  explicit PathError(int errnum, llvm::StringLiteral format,\n                     std::filesystem::path path, int dir_fd)\n      : ErrnoErrorBase(errnum),\n        dir_fd_(dir_fd),\n        path_(std::move(path)),\n        format_(format) {}\n\n  int dir_fd_;\n  std::filesystem::path path_;\n  llvm::StringLiteral format_;\n};\n\n// Implementation details only below.\n\nnamespace Internal {\n\ninline auto DurationToTimespec(Duration d) -> timespec {\n  timespec ts = {};\n  ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();\n  d -= std::chrono::seconds(ts.tv_sec);\n  ts.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count();\n  return ts;\n}\n\n}  // namespace Internal\n\nconsteval auto Cwd() -> Dir { return Dir(AT_FDCWD); }\n\ninline auto FileLock::Destroy() -> void {\n  if (fd_ == -1) {\n    // Nothing to unlock.\n    return;\n  }\n\n  // We always try to unlock in a non-blocking way as there should never be a\n  // reason to block here.\n  int result = flock(fd_, LOCK_UN | LOCK_NB);\n\n  // The only realistic error is `EBADF` that would represent a programming\n  // error the type system should prevent. We conservatively check-fail if an\n  // error occurs here.\n  CARBON_CHECK(result == 0, \"{0}\",\n               FdError(errno, \"Unexpected error while _unlocking_ '{0}'\", fd_));\n}\n\ninline auto Internal::FileRefBase::Stat() -> ErrorOr<FileStatus, FdError> {\n  FileStatus status;\n  if (fstat(fd_, &status.stat_buf_) == 0) {\n    return status;\n  }\n  return FdError(errno, \"File::Stat on '{0}'\", fd_);\n}\n\ninline auto Internal::FileRefBase::UpdateTimes(\n    std::optional<TimePoint> time_point) -> ErrorOr<Success, FdError> {\n  if (!time_point) {\n    if (futimens(fd_, nullptr) == -1) {\n      return FdError(errno, \"File::UpdateTimes to now on '{0}'\", fd_);\n    }\n    return Success();\n  }\n\n  timespec times[2];\n  times[0] = Internal::DurationToTimespec(time_point->time_since_epoch());\n  times[1] = times[0];\n  if (futimens(fd_, times) == -1) {\n    return FdError(errno, \"File::UpdateTimes to a specific time on '{0}'\", fd_);\n  }\n  return Success();\n}\n\ninline auto Internal::FileRefBase::Seek(int64_t delta)\n    -> ErrorOr<int64_t, FdError> {\n  int64_t byte_offset = lseek(fd_, delta, SEEK_CUR);\n  if (byte_offset == -1) {\n    return FdError(errno, \"File::Seek on '{0}'\", fd_);\n  }\n  return byte_offset;\n}\n\ninline auto Internal::FileRefBase::SeekFromBeginning(\n    int64_t delta_from_beginning) -> ErrorOr<int64_t, FdError> {\n  int64_t byte_offset = lseek(fd_, delta_from_beginning, SEEK_SET);\n  if (byte_offset == -1) {\n    return FdError(errno, \"File::SeekTo on '{0}'\", fd_);\n  }\n  return byte_offset;\n}\n\ninline auto Internal::FileRefBase::SeekFromEnd(int64_t delta_from_end)\n    -> ErrorOr<int64_t, FdError> {\n  int64_t byte_offset = lseek(fd_, delta_from_end, SEEK_END);\n  if (byte_offset == -1) {\n    return FdError(errno, \"File::SeekFromEnd on '{0}'\", fd_);\n  }\n  return byte_offset;\n}\n\ninline auto Internal::FileRefBase::Truncate(int64_t new_size)\n    -> ErrorOr<Success, FdError> {\n  int64_t result = ftruncate(fd_, new_size);\n  if (result == -1) {\n    return FdError(errno, \"File::Truncate on '{0}'\", fd_);\n  }\n  return Success();\n}\n\ninline auto Internal::FileRefBase::ReadToBuffer(\n    llvm::MutableArrayRef<std::byte> buffer)\n    -> ErrorOr<llvm::MutableArrayRef<std::byte>, FdError> {\n  for (;;) {\n    ssize_t read_bytes = read(fd_, buffer.data(), buffer.size());\n    if (read_bytes == -1) {\n      if (errno == EINTR) {\n        continue;\n      }\n      return FdError(errno, \"File::Read on '{0}'\", fd_);\n    }\n    return buffer.slice(0, read_bytes);\n  }\n}\n\ninline auto Internal::FileRefBase::WriteFromBuffer(\n    llvm::ArrayRef<std::byte> buffer)\n    -> ErrorOr<llvm::ArrayRef<std::byte>, FdError> {\n  for (;;) {\n    ssize_t written_bytes = write(fd_, buffer.data(), buffer.size());\n    if (written_bytes == -1) {\n      if (errno == EINTR) {\n        continue;\n      }\n      return FdError(errno, \"File::Write on '{0}'\", fd_);\n    }\n    return buffer.drop_front(written_bytes);\n  }\n}\n\ninline auto Internal::FileRefBase::WriteStream() -> llvm::raw_fd_ostream {\n  return llvm::raw_fd_ostream(fd_, /*shouldClose=*/false);\n}\n\ninline auto Internal::FileRefBase::Close() && -> ErrorOr<Success, FdError> {\n  // Put the file in a moved-from state immediately as it is invalid to\n  // retry closing or use the file in any way even if the close fails.\n  int fd = std::exchange(fd_, -1);\n\n  int result = close(fd);\n  if (result == 0) {\n    return Success();\n  }\n\n  return FdError(errno, \"File::Close on '{0}'\", fd);\n}\n\ninline auto Internal::FileRefBase::ReadOnlyDestroy() -> void {\n  if (fd_ >= 0) {\n    auto result = std::move(*this).Close();\n    // Intentionally drop errors, as there is no interesting error here. There\n    // is no risk of data loss, and the least bad thing we can do is to just\n    // leak the file descriptor.\n    static_cast<void>(result);\n  }\n}\n\ninline auto Internal::FileRefBase::WriteableDestroy() -> void {\n  CARBON_CHECK(\n      fd_ == -1,\n      \"Cannot destroy an open writable file, they _must_ be destroyed by \"\n      \"calling `Close` and handling any errors to avoid data loss.\");\n}\n\ntemplate <OpenAccess A>\nauto FileRef<A>::Truncate(int64_t new_size) -> ErrorOr<Success, FdError>\n  requires Writeable\n{\n  return FileRefBase::Truncate(new_size);\n}\n\ntemplate <OpenAccess A>\nauto FileRef<A>::ReadToBuffer(llvm::MutableArrayRef<std::byte> buffer)\n    -> ErrorOr<llvm::MutableArrayRef<std::byte>, FdError>\n  requires Readable\n{\n  return FileRefBase::ReadToBuffer(buffer);\n}\n\ntemplate <OpenAccess A>\nauto FileRef<A>::ReadFileToString() -> ErrorOr<std::string, FdError>\n  requires Readable\n{\n  return FileRefBase::ReadFileToString();\n}\n\ntemplate <OpenAccess A>\nauto FileRef<A>::WriteFromBuffer(llvm::ArrayRef<std::byte> buffer)\n    -> ErrorOr<llvm::ArrayRef<std::byte>, FdError>\n  requires Writeable\n{\n  return FileRefBase::WriteFromBuffer(buffer);\n}\n\ntemplate <OpenAccess A>\nauto FileRef<A>::WriteStream() -> llvm::raw_fd_ostream\n  requires Writeable\n{\n  return FileRefBase::WriteStream();\n}\n\ntemplate <OpenAccess A>\nauto FileRef<A>::WriteFileFromString(llvm::StringRef str)\n    -> ErrorOr<Success, FdError>\n  requires Writeable\n{\n  return FileRefBase::WriteFileFromString(str);\n}\n\ntemplate <OpenAccess A>\nauto File<A>::Destroy() -> void {\n  if constexpr (Writeable) {\n    this->WriteableDestroy();\n  } else {\n    this->ReadOnlyDestroy();\n  }\n}\n\ninline auto DirRef::Read() -> ErrorOr<Reader, FdError> {\n  int dup_dfd = dup(dfd_);\n  if (dup_dfd == -1) {\n    // There are very few plausible errors here, but we can return one so it\n    // doesn't hurt to do so. While `EINTR` and `EBUSY` are mentioned in some\n    // documentation, there is no indication that for just `dup` it is useful to\n    // loop and retry.\n    return FdError(errno, \"Dir::Read on '{0}'\", dfd_);\n  }\n  return Dir(dup_dfd).TakeAndRead();\n}\n\ninline auto DirRef::ReadEntries()\n    -> ErrorOr<llvm::SmallVector<std::filesystem::path>, FdError> {\n  llvm::SmallVector<std::filesystem::path> entries;\n  CARBON_RETURN_IF_ERROR(AppendEntriesIf(entries));\n  return entries;\n}\n\ninline auto DirRef::Access(const std::filesystem::path& path,\n                           AccessCheckFlags check) -> ErrorOr<bool, PathError> {\n  if (faccessat(dfd_, path.c_str(), static_cast<int>(check), /*flags=*/0) ==\n      0) {\n    return true;\n  }\n  return PathError(errno, \"Dir::Access on '{0}' relative to '{1}'\", path, dfd_);\n}\n\ninline auto DirRef::Stat() -> ErrorOr<FileStatus, FdError> {\n  FileStatus status;\n  if (fstat(dfd_, &status.stat_buf_) == 0) {\n    return status;\n  }\n  return FdError(errno, \"Dir::Stat on '{0}': \", dfd_);\n}\n\ninline auto DirRef::Stat(const std::filesystem::path& path)\n    -> ErrorOr<FileStatus, PathError> {\n  FileStatus status;\n  if (fstatat(dfd_, path.c_str(), &status.stat_buf_, /*flags=*/0) == 0) {\n    return status;\n  }\n  return PathError(errno, \"Dir::Stat on '{0}' relative to '{1}'\", path, dfd_);\n}\n\ninline auto DirRef::Lstat(const std::filesystem::path& path)\n    -> ErrorOr<FileStatus, PathError> {\n  FileStatus status;\n  if (fstatat(dfd_, path.c_str(), &status.stat_buf_,\n              /*flags=*/AT_SYMLINK_NOFOLLOW) == 0) {\n    return status;\n  }\n  return PathError(errno, \"Dir::Lstat on '{0}' relative to '{1}'\", path, dfd_);\n}\n\ninline auto DirRef::UpdateTimes(const std::filesystem::path& path,\n                                std::optional<TimePoint> time_point)\n    -> ErrorOr<Success, PathError> {\n  if (!time_point) {\n    if (utimensat(dfd_, path.c_str(), nullptr, /*flags*/ 0) == -1) {\n      return PathError(errno,\n                       \"Dir::UpdateTimes to now on '{0}' relative to '{1}'\",\n                       path, dfd_);\n    }\n    return Success();\n  }\n\n  timespec times[2];\n  times[0] = Internal::DurationToTimespec(time_point->time_since_epoch());\n  times[1] = times[0];\n  if (utimensat(dfd_, path.c_str(), times, /*flags*/ 0) == -1) {\n    return PathError(\n        errno, \"Dir::UpdateTimes to a specific time on '{0}' relative to '{1}'\",\n        path, dfd_);\n  }\n  return Success();\n}\n\ninline auto DirRef::Readlink(const std::filesystem::path& path)\n    -> ErrorOr<std::string, PathError> {\n  // On the fast path, we read into a small stack buffer and get the whole\n  // contents.\n  constexpr ssize_t BufferSize = 256;\n  char buffer[BufferSize];\n  ssize_t read_bytes = readlinkat(dfd_, path.c_str(), buffer, BufferSize);\n  if (read_bytes == -1) {\n    return PathError(errno, \"Dir::Readlink on '{0}' relative to '{1}'\", path,\n                     dfd_);\n  }\n  if (read_bytes < BufferSize) {\n    // We got the whole contents in one shot, return it.\n    return std::string(buffer, read_bytes);\n  }\n\n  // Otherwise, fallback to an out-of-line function to handle the slow path.\n  return ReadlinkSlow(path);\n}\n\ninline auto DirRef::OpenReadOnly(const std::filesystem::path& path,\n                                 CreationOptions creation_options,\n                                 ModeType creation_mode, OpenFlags flags)\n    -> ErrorOr<ReadFile, PathError> {\n  return OpenImpl<OpenAccess::ReadOnly>(path, creation_options, creation_mode,\n                                        flags);\n}\n\ninline auto DirRef::OpenWriteOnly(const std::filesystem::path& path,\n                                  CreationOptions creation_options,\n                                  ModeType creation_mode, OpenFlags flags)\n    -> ErrorOr<WriteFile, PathError> {\n  return OpenImpl<OpenAccess::WriteOnly>(path, creation_options, creation_mode,\n                                         flags);\n}\n\ninline auto DirRef::OpenReadWrite(const std::filesystem::path& path,\n                                  CreationOptions creation_options,\n                                  ModeType creation_mode, OpenFlags flags)\n    -> ErrorOr<ReadWriteFile, PathError> {\n  return OpenImpl<OpenAccess::ReadWrite>(path, creation_options, creation_mode,\n                                         flags);\n}\n\ninline auto DirRef::Rename(const std::filesystem::path& path, DirRef target_dir,\n                           const std::filesystem::path& target_path)\n    -> ErrorOr<Success, PathError> {\n  if (renameat(dfd_, path.c_str(), target_dir.dfd_, target_path.c_str()) ==\n      -1) {\n    return PathError(errno, \"Dir::Rename on '{0}' relative to '{1}'\", path,\n                     dfd_);\n  }\n  return Success();\n}\n\ninline auto DirRef::Chdir() -> ErrorOr<Success, FdError> {\n  if (fchdir(dfd_) == -1) {\n    return FdError(errno, \"Dir::Chdir on '{0}'\", dfd_);\n  }\n  return Success();\n}\n\ninline auto DirRef::Chdir(const std::filesystem::path& path)\n    -> ErrorOr<Success, PathError> {\n  if (path.is_absolute()) {\n    if (chdir(path.c_str()) == -1) {\n      return PathError(errno, \"Dir::Chdir on '{0}' relative to '{1}'\", path,\n                       dfd_);\n    }\n    return Success();\n  }\n\n  CARBON_ASSIGN_OR_RETURN(Dir d, OpenDir(path));\n  auto result = d.Chdir();\n  if (result.ok()) {\n    return Success();\n  }\n  return PathError(result.error().unix_errnum(),\n                   \"Dir::Chdir on '{0}' relative to '{1}'\", path, dfd_);\n}\n\ninline auto DirRef::Symlink(const std::filesystem::path& path,\n                            const std::string& target)\n    -> ErrorOr<Success, PathError> {\n  if (symlinkat(target.c_str(), dfd_, path.c_str()) == -1) {\n    return PathError(errno, \"Dir::Symlink on '{0}' relative to '{1}'\", path,\n                     dfd_);\n  }\n  return Success();\n}\n\ninline auto DirRef::Unlink(const std::filesystem::path& path)\n    -> ErrorOr<Success, PathError> {\n  if (unlinkat(dfd_, path.c_str(), /*flags=*/0) == -1) {\n    return PathError(errno, \"Dir::Unlink on '{0}' relative to '{1}'\", path,\n                     dfd_);\n  }\n  return Success();\n}\n\ninline auto DirRef::Rmdir(const std::filesystem::path& path)\n    -> ErrorOr<Success, PathError> {\n  if (unlinkat(dfd_, path.c_str(), AT_REMOVEDIR) == -1) {\n    return PathError(errno, \"Dir::Rmdir on '{0}' relative to '{1}'\", path,\n                     dfd_);\n  }\n  return Success();\n}\n\ntemplate <OpenAccess A>\ninline auto DirRef::OpenImpl(const std::filesystem::path& path,\n                             CreationOptions creation_options,\n                             ModeType creation_mode, OpenFlags flags)\n    -> ErrorOr<File<A>, PathError> {\n  for (;;) {\n    int fd = openat(dfd_, path.c_str(),\n                    static_cast<int>(A) | static_cast<int>(creation_options) |\n                        static_cast<int>(flags),\n                    creation_mode);\n    if (fd == -1) {\n      // May need to retry on `EINTR` when opening FIFOs on Linux.\n      if (errno == EINTR) {\n        continue;\n      }\n      return PathError(errno, \"Dir::Open on '{0}' relative to '{1}'\", path,\n                       dfd_);\n    }\n    return File<A>(fd);\n  }\n}\n\nconstexpr Dir::~Dir() { Destroy(); }\n\ninline auto Dir::TakeAndRead() && -> ErrorOr<Reader, FdError> {\n  // Transition our file descriptor into a directory stream, clearing it in the\n  // process.\n  int dfd = std::exchange(dfd_, -1);\n  DIR* dirp = fdopendir(dfd);\n  if (dirp == nullptr) {\n    return FdError(errno, \"Dir::Read on '{0}'\", dfd);\n  }\n  return Dir::Reader(dirp);\n}\n\ninline Dir::Dir(RemovingDir&& arg) noexcept : Dir(static_cast<Dir&&>(arg)) {\n  arg.path_.clear();\n}\n\nconstexpr auto Dir::Destroy() -> void {\n  if (dfd_ != -1 && dfd_ != AT_FDCWD) {\n    auto result = close(dfd_);\n    // Closing a directory shouldn't produce errors, directly check fail on any.\n    //\n    // This is a very different case from `close` on a file producing an error.\n    // We don't actually write through the directory file descriptor, and for\n    // most platforms `closedir` (the closest thing in documentation and\n    // exclusively about directories), only provides a very few possible errors\n    // here:\n    //\n    // EBADF: This should be precluded by the types here, and so we consider\n    //        it a programming error.\n    //\n    // EINTR: Technically, a system could fail here. We have good evidence\n    //        that systems we practically support don't as there also is nothing\n    //        useful to *do* in the face of this: retrying on almost all systems\n    //        is not allowed as the file descriptor is immediately released. And\n    //        here, there is no potentially dropped data to report.\n    //\n    // If we ever discover a platform that fails here, we should adjust this\n    // code to not fail in the face of that, likely by dropping the error. If we\n    // end up supporting a platform that actually requires well-specified\n    // retries, this code should handle that. Until then, we require these to\n    // succeed so we will learn about any issues during porting to new\n    // platforms.\n    CARBON_CHECK(result == 0, \"{0}\",\n                 FdError(errno, \"Dir::Destroy on '{0}'\", dfd_));\n  }\n  dfd_ = -1;\n}\n\ninline RemovingDir::~RemovingDir() {\n  if (dfd_ != -1) {\n    auto result = std::move(*this).Remove();\n    CARBON_CHECK(result.ok(), \"{0}\", result.error());\n  }\n}\n\ninline auto RemovingDir::Remove() && -> ErrorOr<Success, PathError> {\n  CARBON_CHECK(dfd_ != -1,\n               \"Unexpected explicit remove on a `RemovingDir` with no owned \"\n               \"directory!\");\n\n  // Close the directory base object prior to removing it.\n  static_cast<Dir&>(*this) = Dir();\n  return Cwd().Rmtree(path_);\n}\n\ninline auto Dir::Iterator::operator++() -> Iterator& {\n  CARBON_CHECK(dirp_, \"Cannot increment an end-iterator\");\n\n  errno = 0;\n  entry_.dent_ = readdir(dirp_);\n  // There are no documented errors beyond an erroneous `dirp_` which would be\n  // a programming error and not due to any recoverable failure of the\n  // filesystem.\n  CARBON_CHECK(entry_.dent_ != nullptr || errno == 0,\n               \"Using a directory iterator with a non-directory, errno '{0}'\",\n               errno);\n  if (entry_.dent_ == nullptr) {\n    // Clear the directory pointer to ease debugging increments past the end.\n    dirp_ = nullptr;\n  }\n  return *this;\n}\n\ninline auto Dir::Reader::begin() -> Iterator {\n  // Reset the position of the directory stream to get the actual beginning.\n  rewinddir(dirp_);\n  return Iterator(dirp_);\n}\n\ninline auto Dir::Reader::end() -> Iterator { return Iterator(); }\n\ninline auto Dir::Reader::Destroy() -> void {\n  if (dirp_) {\n    int result = closedir(dirp_);\n    // Closing a directory shouldn't produce interesting errors, so check fail\n    // on them directly.\n    //\n    // See the detailed comment on `Dir::Destroy` for more context on closing of\n    // directories, why we check-fail, and what we should do if we discover\n    // platforms where an error needs to be handled here.\n    CARBON_CHECK(result == 0, \"{0}\",\n                 FdError(errno, \"Dir::Reader::Destroy on '{0}'\", dfd_));\n    dirp_ = nullptr;\n    dfd_ = -1;\n  }\n}\n\n}  // namespace Carbon::Filesystem\n\n#endif  // CARBON_COMMON_FILESYSTEM_H_\n"
  },
  {
    "path": "common/filesystem_benchmark.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <benchmark/benchmark.h>\n\n#include <fstream>\n#include <system_error>\n\n#include \"absl/random/random.h\"\n#include \"common/filesystem.h\"\n#include \"llvm/ADT/Sequence.h\"\n#include \"llvm/ADT/StringExtras.h\"\n\nnamespace Carbon::Filesystem {\nnamespace {\n\n// Alternative implementation strategies to allow comparing performance.\n//\n// WHen implementing benchmarks below, we try to make them templates on this\n// enum and then switch in the body between different implementations. This\n// allows us to share the framework of each benchmark but select different\n// implementations for different instantiations. The different instantiations\n// get these enumerators in their names in the output, so we keep them short.\nenum BenchmarkComparables {\n  Carbon,\n  Std,\n};\n\n// Filler text.\nconstexpr llvm::StringLiteral Text =\n    \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod \"\n    \"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim \"\n    \"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea \"\n    \"commodo consequat. Duis aute irure dolor in reprehenderit in voluptate \"\n    \"velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint \"\n    \"occaecat cupidatat non proident, sunt in culpa qui officia deserunt \"\n    \"mollit anim id est laborum.\";\n\n// Gets the filler text repeated up to a specific length.\nstatic auto GetText(int length) -> std::string {\n  std::string content;\n  content.reserve(length);\n  while (static_cast<int>(content.size()) < length) {\n    content += Text.substr(0, length - content.size());\n  }\n  CARBON_CHECK(static_cast<int>(content.size()) == length);\n  return content;\n}\n\n// We build a collection of file paths to use across different benchmarks in\n// batches to avoid looking at the same file over and over again. We can even\n// shuffle the file orders to further avoid hiding performance cost. If there\n// are specific cases where we want to measure the cached / predicted speed, we\n// can write those benchmarks against a specific file, but most often we instead\n// look at the worst case scenario for wall-clock time and use cycle counters\n// and instruction counters to measure aspects of the best case. The exact\n// number here was chosen arbitrarily to not make running benchmarks excessively\n// slow due to the large batches.\nconstexpr int NumFiles = 64;\n\n// A common set of context used in benchmarks below. A separate context object\n// works better than the benchmark fixture support in practice.\n//\n// This is a struct as there are no invariants or contracts enforced. This is\n// just a container of commonly useful data and commonly useful helper\n// functions.\nstruct BenchContext {\n  RemovingDir tmpdir;\n  absl::BitGen rng;\n  std::array<std::filesystem::path, NumFiles> file_paths;\n  std::array<std::filesystem::path, NumFiles> missing_paths;\n\n  BenchContext() : tmpdir(*MakeTmpDir()) {\n    for (int i : llvm::seq(NumFiles)) {\n      file_paths[i] = llvm::formatv(\"file_{0}\", i).str();\n      auto result = tmpdir.WriteFileFromString(file_paths[i], Text);\n      CARBON_CHECK(result.ok(), \"{0}\", result.error());\n      missing_paths[i] = llvm::formatv(\"missing_{0}\", i).str();\n    }\n    ShuffleFilePaths();\n    ShuffleMissingPaths();\n  }\n\n  auto ShuffleFilePaths() -> void {\n    std::shuffle(file_paths.begin(), file_paths.end(), rng);\n  }\n\n  auto ShuffleMissingPaths() -> void {\n    std::shuffle(missing_paths.begin(), missing_paths.end(), rng);\n  }\n\n  // Create a tree of files and directories starting from a `base` new directory\n  // in our tmp directory, and containing `entries` total entries with\n  // `entries_per_dir` in each directory. These will be a mixture of further\n  // subdirectories and files.\n  auto CreateTree(std::filesystem::path base, int entries, int entries_per_dir)\n      -> void {\n    CARBON_CHECK(entries >= 1);\n    CARBON_CHECK(entries_per_dir >= 1);\n    int num_subdirs = std::max<int>(entries_per_dir / 2, 1);\n    struct DirStackEntry {\n      Dir dir;\n      int num_entries;\n      int subdir_count;\n    };\n    llvm::SmallVector<DirStackEntry> dir_stack;\n    auto d = tmpdir.OpenDir(base, CreationOptions::CreateNew);\n    CARBON_CHECK(d.ok(), \"{0}\", d.error());\n    dir_stack.push_back({std::move(*d), entries, 0});\n\n    while (!dir_stack.empty()) {\n      auto& [dir, num_entries, subdir_count] = dir_stack.back();\n\n      // We want `num_entries` transitively in this directory, and\n      // `entries_per_dir` directly. Spread the remaining entries across\n      // `num_subdirs`.\n      int entries_per_subdir = ((num_entries - entries_per_dir) / num_subdirs);\n      CARBON_CHECK(entries_per_subdir < num_entries);\n\n      // While we'll still put entries in a subdirectory, and we still need more\n      // subdirectories in this directory, create another subdirectory, push it\n      // on the stack, and recurse to it by continuing.\n      if (entries_per_subdir >= entries_per_dir && subdir_count < num_subdirs) {\n        auto name = llvm::formatv(\"dir_{0}\", subdir_count).str();\n        auto subdir = dir.OpenDir(name, CreationOptions::CreateNew);\n        CARBON_CHECK(subdir.ok(), \"{0}\", subdir.error());\n        ++subdir_count;\n\n        // Note we have to continue after `push_back` as this will invalidate\n        // the current references.\n        dir_stack.push_back({std::move(*subdir), entries_per_subdir, 0});\n        continue;\n      }\n\n      // Otherwise, we're finished with subdirectories and just need to create\n      // direct files.\n      int num_files = entries_per_dir - subdir_count;\n      CARBON_CHECK(num_files >= 0);\n      for (int i = 0; i < num_files; ++i) {\n        auto name = llvm::formatv(\"file_{0}\", i).str();\n        auto f = dir.OpenWriteOnly(name, CreationOptions::CreateNew);\n        CARBON_CHECK(f.ok(), \"{0}\", f.error());\n        auto close_result = std::move(*f).Close();\n        CARBON_CHECK(close_result.ok(), \"{0}\", close_result.error());\n      }\n      dir_stack.pop_back();\n    }\n  }\n};\n\ntemplate <BenchmarkComparables Comp>\nauto BM_Access(benchmark::State& state) -> void {\n  BenchContext context;\n  while (state.KeepRunningBatch(NumFiles)) {\n    for (int i : llvm::seq(NumFiles)) {\n      if constexpr (Comp == Carbon) {\n        auto result = context.tmpdir.Access(context.file_paths[i]);\n        CARBON_CHECK(result.ok(), \"{0}\", result.error());\n      } else if constexpr (Comp == Std) {\n        std::error_code ec;\n        bool exists = std::filesystem::exists(\n            context.tmpdir.path() / context.file_paths[i], ec);\n        CARBON_CHECK(!ec, \"{0}\", ec.message());\n        CARBON_CHECK(exists);\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_Access<Carbon>)->UseRealTime();\nBENCHMARK(BM_Access<Std>)->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_AccessMissing(benchmark::State& state) -> void {\n  BenchContext context;\n  while (state.KeepRunningBatch(NumFiles)) {\n    for (int i : llvm::seq(NumFiles)) {\n      if constexpr (Comp == Carbon) {\n        auto result = context.tmpdir.Access(context.missing_paths[i]);\n        CARBON_CHECK(result.error().no_entity());\n      } else if constexpr (Comp == Std) {\n        std::error_code ec;\n        auto exists = std::filesystem::exists(\n            context.tmpdir.path() / context.missing_paths[i], ec);\n        CARBON_CHECK(!ec, \"{0}\", ec.message());\n        CARBON_CHECK(!exists);\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_AccessMissing<Carbon>)->UseRealTime();\nBENCHMARK(BM_AccessMissing<Std>)->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_Stat(benchmark::State& state) -> void {\n  BenchContext context;\n  while (state.KeepRunningBatch(NumFiles)) {\n    for (int i : llvm::seq(NumFiles)) {\n      if constexpr (Comp == Carbon) {\n        auto status = context.tmpdir.Stat(context.file_paths[i]);\n        CARBON_CHECK(status.ok(), \"{0}\", status.error());\n        benchmark::DoNotOptimize(status->permissions());\n      } else if constexpr (Comp == Std) {\n        std::error_code ec;\n        auto status = std::filesystem::status(\n            context.tmpdir.path() / context.file_paths[i], ec);\n        CARBON_CHECK(!ec, \"{0}\", ec.message());\n        benchmark::DoNotOptimize(status.permissions());\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_Stat<Carbon>)->UseRealTime();\nBENCHMARK(BM_Stat<Std>)->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_StatMissing(benchmark::State& state) -> void {\n  BenchContext context;\n  while (state.KeepRunningBatch(NumFiles)) {\n    for (int i : llvm::seq(NumFiles)) {\n      if constexpr (Comp == Carbon) {\n        auto status = context.tmpdir.Stat(context.missing_paths[i]);\n        CARBON_CHECK(status.error().no_entity());\n      } else if constexpr (Comp == Std) {\n        std::error_code ec;\n        auto status = std::filesystem::status(\n            context.tmpdir.path() / context.missing_paths[i], ec);\n        CARBON_CHECK(ec.value() == ENOENT, \"{0}\", ec.message());\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_StatMissing<Carbon>)->UseRealTime();\nBENCHMARK(BM_StatMissing<Std>)->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_OpenMissing(benchmark::State& state) -> void {\n  BenchContext context;\n  while (state.KeepRunningBatch(NumFiles)) {\n    for (int i : llvm::seq(NumFiles)) {\n      if constexpr (Comp == Carbon) {\n        auto f = context.tmpdir.OpenReadOnly(context.missing_paths[i]);\n        CARBON_CHECK(f.error().no_entity());\n      } else if constexpr (Comp == Std) {\n        std::ifstream f(context.tmpdir.path() / context.missing_paths[i]);\n        CARBON_CHECK(!f.is_open());\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_OpenMissing<Carbon>)->UseRealTime();\nBENCHMARK(BM_OpenMissing<Std>)->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_OpenClose(benchmark::State& state) -> void {\n  BenchContext context;\n  while (state.KeepRunningBatch(NumFiles)) {\n    for (int i : llvm::seq(NumFiles)) {\n      if constexpr (Comp == Carbon) {\n        auto f = context.tmpdir.OpenReadOnly(context.file_paths[i]);\n        CARBON_CHECK(f.ok(), \"{0}\", f.error());\n        auto close_result = std::move(*f).Close();\n        CARBON_CHECK(close_result.ok(), \"{0}\", close_result.error());\n      } else if constexpr (Comp == Std) {\n        std::ifstream f(context.tmpdir.path() / context.file_paths[i]);\n        CARBON_CHECK(f.is_open());\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_OpenClose<Carbon>)->UseRealTime();\nBENCHMARK(BM_OpenClose<Std>)->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_CreateRemove(benchmark::State& state) -> void {\n  BenchContext context;\n  while (state.KeepRunningBatch(NumFiles)) {\n    for (int i : llvm::seq(NumFiles)) {\n      if constexpr (Comp == Carbon) {\n        // Create the file by opening it.\n        auto f = context.tmpdir.OpenWriteOnly(context.missing_paths[i],\n                                              CreationOptions::CreateNew);\n        CARBON_CHECK(f.ok(), \"{0}\", f.error());\n        // Close it right away.\n        auto close_result = std::move(*f).Close();\n        CARBON_CHECK(close_result.ok(), \"{0}\", close_result.error());\n        // Remove it.\n        auto remove_result = context.tmpdir.Unlink(context.missing_paths[i]);\n        CARBON_CHECK(remove_result.ok(), \"{0}\", remove_result.error());\n      } else if constexpr (Comp == Std) {\n        auto path = context.tmpdir.path() / context.missing_paths[i];\n        // Create the file by opening it.\n        std::ofstream f(path);\n        CARBON_CHECK(f.is_open());\n        // Close it right away.\n        f.close();\n        // Remove it.\n        std::error_code ec;\n        std::filesystem::remove(path, ec);\n        CARBON_CHECK(!ec, \"{0}\", ec.message());\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_CreateRemove<Carbon>)->UseRealTime();\nBENCHMARK(BM_CreateRemove<Std>)->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_Read(benchmark::State& state) -> void {\n  BenchContext context;\n  int length = state.range(0);\n  std::string content = GetText(length);\n  for (int i : llvm::seq(NumFiles)) {\n    auto result =\n        context.tmpdir.WriteFileFromString(context.file_paths[i], content);\n    CARBON_CHECK(result.ok(), \"{0}\", result.error());\n  }\n  while (state.KeepRunningBatch(NumFiles)) {\n    // Re-shuffle the order of the files for each batch to avoid exact cache\n    // hits.\n    state.PauseTiming();\n    context.ShuffleFilePaths();\n    state.ResumeTiming();\n\n    for (int i : llvm::seq(NumFiles)) {\n      if constexpr (Comp == Carbon) {\n        auto read_result =\n            context.tmpdir.ReadFileToString(context.file_paths[i]);\n        CARBON_CHECK(read_result.ok(), \"{0}\", read_result.error());\n        benchmark::DoNotOptimize(*read_result);\n      } else if constexpr (Comp == Std) {\n        std::ifstream f(context.tmpdir.path() / context.file_paths[i],\n                        std::ios::binary);\n        CARBON_CHECK(f.is_open());\n        // This may be a somewhat surprising implementation, but benchmarking\n        // against several other ways of reading the file with `std::ifstream`\n        // all have the same or worse performance.\n        std::string read_content((std::istreambuf_iterator<char>(f)),\n                                 (std::istreambuf_iterator<char>()));\n        benchmark::DoNotOptimize(read_content);\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_Read<Carbon>)->Range(4, 1024LL * 1024)->UseRealTime();\nBENCHMARK(BM_Read<Std>)->Range(4, 1024LL * 1024)->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_Write(benchmark::State& state) -> void {\n  BenchContext context;\n  int length = state.range(0);\n  std::string content = GetText(length);\n  while (state.KeepRunningBatch(NumFiles)) {\n    // Re-shuffle the order of the files for each batch to avoid exact cache\n    // hits.\n    state.PauseTiming();\n    context.ShuffleFilePaths();\n    state.ResumeTiming();\n\n    for (int i : llvm::seq(NumFiles)) {\n      if constexpr (Comp == Carbon) {\n        auto write_result =\n            context.tmpdir.WriteFileFromString(context.file_paths[i], content);\n        CARBON_CHECK(write_result.ok(), \"{0}\", write_result.error());\n      } else if constexpr (Comp == Std) {\n        std::ofstream f(context.tmpdir.path() / context.file_paths[i],\n                        std::ios::binary | std::ios::trunc);\n        CARBON_CHECK(f.is_open());\n        f.write(content.data(), content.length());\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_Write<Carbon>)->Range(4, 1024LL * 1024)->UseRealTime();\nBENCHMARK(BM_Write<Std>)->Range(4, 1024LL * 1024)->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_Rmtree(benchmark::State& state) -> void {\n  BenchContext context;\n  int entries = state.range(0);\n  int depth = state.range(1);\n\n  // Configure our batch size based on the number of entries. Creating large\n  // numbers of entries in the filesystem can cause problems, and is also very\n  // slow. We don't need that much accuracy once the trees get large.\n  int batch_size = entries <= 1024 ? 10 : entries <= (32 * 1024) ? 5 : 1;\n\n  while (state.KeepRunningBatch(batch_size)) {\n    state.PauseTiming();\n    for (int i : llvm::seq(batch_size)) {\n      context.CreateTree(llvm::formatv(\"tree_{0}\", i).str(), entries, depth);\n    }\n    state.ResumeTiming();\n\n    for (int i : llvm::seq(batch_size)) {\n      std::string tree = llvm::formatv(\"tree_{0}\", i).str();\n      if constexpr (Comp == Carbon) {\n        auto rmdir_result = context.tmpdir.Rmtree(tree);\n        CARBON_CHECK(rmdir_result.ok(), \"{0}\", rmdir_result.error());\n      } else if constexpr (Comp == Std) {\n        std::error_code ec;\n        std::filesystem::remove_all(context.tmpdir.path() / tree, ec);\n        CARBON_CHECK(!ec, \"{0}\", ec.message());\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n  }\n}\nBENCHMARK(BM_Rmtree<Carbon>)\n    ->Ranges({{1, 256}, {1, 32}})\n    ->Ranges({{2 * 1024, 256 * 1024}, {512, 1024}})\n    ->Unit(benchmark::kMicrosecond)\n    ->UseRealTime();\nBENCHMARK(BM_Rmtree<Std>)\n    ->Ranges({{1, 256}, {1, 32}})\n    ->Ranges({{2 * 1024, 256 * 1024}, {512, 1024}})\n    ->Unit(benchmark::kMicrosecond)\n    ->UseRealTime();\n\ntemplate <BenchmarkComparables Comp>\nauto BM_CreateDirectories(benchmark::State& state) -> void {\n  BenchContext context;\n  int depth = state.range(0);\n  int existing_depth = state.range(1);\n  CARBON_CHECK(existing_depth <= depth);\n  CARBON_CHECK(depth > 0);\n\n  // Use a batch size of 10 to get avoid completely swamping the measurements\n  // with overhead from creating existing directories and cleaning up.\n  constexpr int BatchSize = 10;\n\n  // Pre-build both the paths and the existing paths. Note that we use\n  // relatively short paths here, which if anything makes the benefits of the\n  // Carbon library smaller.\n  llvm::SmallVector<std::string> paths;\n  llvm::SmallVector<std::string> existing_paths;\n  for (int i : llvm::seq(BatchSize)) {\n    RawStringOstream path;\n    llvm::ListSeparator sep(\"/\");\n    for (int j = 0; j < existing_depth; ++j) {\n      path << sep << \"exists_\" << (j == 0 ? i : j);\n    }\n    existing_paths.push_back(path.TakeStr());\n    path << existing_paths.back();\n    for (int k = existing_depth; k < depth; ++k) {\n      path << sep << \"dir_\" << (k == 0 ? i : k);\n    }\n    paths.push_back(path.TakeStr());\n  }\n\n  while (state.KeepRunningBatch(BatchSize)) {\n    state.PauseTiming();\n    for (int i : llvm::seq(BatchSize)) {\n      if (existing_depth > 0) {\n        auto result = context.tmpdir.CreateDirectories(existing_paths[i]);\n        CARBON_CHECK(result.ok(), \"{0}\", result.error());\n      }\n    }\n    state.ResumeTiming();\n\n    for (int i : llvm::seq(BatchSize)) {\n      if constexpr (Comp == Carbon) {\n        auto result = context.tmpdir.CreateDirectories(paths[i]);\n        CARBON_CHECK(result.ok(), \"Failed to create '{0}': {1}\", paths[i],\n                     result.error());\n\n        // Create a file in the provided directory. This adds some baseline\n        // overhead but matches the realistic use case and ensures that there\n        // isn't some laziness that makes just creating a directory have an\n        // unusually low cost.\n        auto f = result->OpenWriteOnly(\"test\", CreationOptions::CreateNew);\n        CARBON_CHECK(f.ok(), \"{0}\", f.error());\n        auto close_result = std::move(*f).Close();\n        CARBON_CHECK(close_result.ok(), \"{0}\", close_result.error());\n      } else if constexpr (Comp == Std) {\n        std::filesystem::path path = context.tmpdir.path() / paths[i];\n        std::error_code ec;\n        std::filesystem::create_directories(path, ec);\n        CARBON_CHECK(!ec, \"{0}\", ec.message());\n\n        // Create a file in the directory, similar to above. This has a (much)\n        // bigger effect though because the C++ APIs don't open the created\n        // directory, and so the creation cost of it can very much be hidden\n        // from the benchmark if we don't use it. This also lets us see the\n        // benefit of not needing to re-walk the path to create the file.\n        std::ofstream f(path / \"test\");\n        CARBON_CHECK(f.is_open());\n        f.close();\n      } else {\n        static_assert(false, \"Invalid benchmark comparable\");\n      }\n    }\n\n    state.PauseTiming();\n    for (int i : llvm::seq(BatchSize)) {\n      auto result = context.tmpdir.Rmtree(\n          llvm::formatv(\"{0}_{1}\", existing_depth > 0 ? \"exists\" : \"dir\", i)\n              .str());\n      CARBON_CHECK(result.ok(), \"{0}\", result.error());\n    }\n    state.ResumeTiming();\n  }\n}\nstatic auto CreateDirectoriesBenchArgs(benchmark::Benchmark* b) {\n  // The first argument is the depth of directory to create. We mostly care\n  // about reasonably small depths here. It must be >= 1 for there to be\n  // something to benchmark. The second number is the depth of pre-existing\n  // directories which can vary from 0 to equal to the depth to benchmark the\n  // case of no new directory being needed.\n  for (int i = 1; i <= 8; i *= 2) {\n    b->Args({i, 0});\n    for (int j = 1; j <= i; j *= 2) {\n      b->Args({i, j});\n    }\n  }\n}\nBENCHMARK(BM_CreateDirectories<Carbon>)\n    ->Apply(CreateDirectoriesBenchArgs)\n    ->UseRealTime();\nBENCHMARK(BM_CreateDirectories<Std>)\n    ->Apply(CreateDirectoriesBenchArgs)\n    ->UseRealTime();\n\n}  // namespace\n}  // namespace Carbon::Filesystem\n"
  },
  {
    "path": "common/filesystem_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/filesystem.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <concepts>\n#include <string>\n#include <thread>\n#include <utility>\n\n#include \"common/error_test_helpers.h\"\n\nnamespace Carbon::Filesystem {\nnamespace {\n\nusing ::testing::_;\nusing ::testing::Eq;\nusing ::testing::HasSubstr;\nusing Testing::IsError;\nusing Testing::IsSuccess;\nusing ::testing::UnorderedElementsAre;\n\nclass FilesystemTest : public ::testing::Test {\n public:\n  explicit FilesystemTest() {\n    auto result = MakeTmpDir();\n    CARBON_CHECK(result.ok(), \"{0}\", result.error());\n    dir_ = std::move(*result);\n  }\n\n  ~FilesystemTest() override {\n    auto result = std::move(dir_).Remove();\n    CARBON_CHECK(result.ok(), \"{0}\", result.error());\n  }\n\n  auto path() const -> const std::filesystem::path& { return dir_.path(); }\n\n  // The test's temp directory, deleted on destruction.\n  RemovingDir dir_;\n};\n\nTEST_F(FilesystemTest, CreateOpenCloseAndUnlink) {\n  auto unlink_result = dir_.Unlink(\"test\");\n  ASSERT_FALSE(unlink_result.ok());\n  EXPECT_TRUE(unlink_result.error().no_entity());\n#if defined(_GNU_SOURCE) && \\\n    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32))\n  EXPECT_THAT(unlink_result, IsError(HasSubstr(\"ENOENT\")));\n#endif\n  EXPECT_THAT(unlink_result, IsError(HasSubstr(\"No such file\")));\n\n  auto f = dir_.OpenWriteOnly(\"test\", CreationOptions::CreateNew);\n  ASSERT_THAT(f, IsSuccess(_));\n  auto result = (*std::move(f)).Close();\n  EXPECT_THAT(result, IsSuccess(_));\n\n  f = dir_.OpenWriteOnly(\"test\", CreationOptions::CreateNew);\n  ASSERT_FALSE(f.ok());\n  EXPECT_TRUE(f.error().already_exists());\n#if defined(_GNU_SOURCE) && \\\n    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32))\n  EXPECT_THAT(f, IsError(HasSubstr(\"EEXIST\")));\n#endif\n  EXPECT_THAT(f, IsError(HasSubstr(\"File exists\")));\n\n  f = dir_.OpenWriteOnly(\"test\");\n  ASSERT_THAT(f, IsSuccess(_));\n  result = std::move(*f).Close();\n  EXPECT_THAT(result, IsSuccess(_));\n\n  f = dir_.OpenWriteOnly(\"test\");\n  ASSERT_THAT(f, IsSuccess(_));\n  result = std::move(*f).Close();\n  EXPECT_THAT(result, IsSuccess(_));\n\n  unlink_result = dir_.Unlink(\"test\");\n  EXPECT_THAT(unlink_result, IsSuccess(_));\n\n  f = dir_.OpenWriteOnly(\"test\");\n  EXPECT_FALSE(f.ok());\n  EXPECT_TRUE(f.error().no_entity());\n#if defined(_GNU_SOURCE) && \\\n    (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 32))\n  EXPECT_THAT(f, IsError(HasSubstr(\"ENOENT\")));\n#endif\n  EXPECT_THAT(f, IsError(HasSubstr(\"No such file\")));\n\n  f = dir_.OpenWriteOnly(\"test\", CreationOptions::OpenAlways);\n  ASSERT_THAT(f, IsSuccess(_));\n  result = std::move(*f).Close();\n  EXPECT_THAT(result, IsSuccess(_));\n\n  unlink_result = dir_.Unlink(\"test\");\n  EXPECT_THAT(unlink_result, IsSuccess(_));\n}\n\nTEST_F(FilesystemTest, BasicWriteAndRead) {\n  std::string content_str = \"0123456789\";\n  {\n    auto f = dir_.OpenWriteOnly(\"test\", CreationOptions::CreateNew);\n    ASSERT_THAT(f, IsSuccess(_));\n    auto write_result = f->WriteFileFromString(content_str);\n    EXPECT_THAT(write_result, IsSuccess(_));\n    (*std::move(f)).Close().Check();\n  }\n\n  {\n    auto f = dir_.OpenReadOnly(\"test\");\n    ASSERT_THAT(f, IsSuccess(_));\n    auto read_result = f->ReadFileToString();\n    EXPECT_THAT(read_result, IsSuccess(Eq(content_str)));\n  }\n\n  auto unlink_result = dir_.Unlink(\"test\");\n  EXPECT_THAT(unlink_result, IsSuccess(_));\n}\n\nTEST_F(FilesystemTest, SeekReadAndWrite) {\n  std::string content_str = \"0123456789\";\n  // First write some initial content.\n  {\n    auto f = dir_.OpenWriteOnly(\"test\", CreationOptions::CreateNew);\n    ASSERT_THAT(f, IsSuccess(_));\n    auto write_result = f->WriteFileFromString(content_str);\n    EXPECT_THAT(write_result, IsSuccess(_));\n    (*std::move(f)).Close().Check();\n  }\n\n  // Now seek and read.\n  {\n    auto f = dir_.OpenReadOnly(\"test\");\n    ASSERT_THAT(f, IsSuccess(_));\n    auto seek_result = f->Seek(3);\n    ASSERT_THAT(seek_result, IsSuccess(Eq(3)));\n    std::array<std::byte, 4> buffer;\n    auto read_result = f->ReadToBuffer(buffer);\n    ASSERT_THAT(read_result, IsSuccess(_));\n    EXPECT_THAT(std::string(reinterpret_cast<char*>(read_result->data()),\n                            read_result->size()),\n                Eq(content_str.substr(3, read_result->size())));\n\n    // Now test that we can seek back to the beginning and read the full file.\n    auto read_file_result = f->ReadFileToString();\n    EXPECT_THAT(read_file_result, IsSuccess(Eq(content_str)));\n  }\n\n  // Now a mixture of reads, writes, an seeking.\n  {\n    auto f = dir_.OpenReadWrite(\"test\");\n    ASSERT_THAT(f, IsSuccess(_));\n    auto seek_result = f->SeekFromEnd(-6);\n    ASSERT_THAT(seek_result, IsSuccess(Eq(content_str.size() - 6)));\n    std::string new_content_str = \"abcdefg\";\n    llvm::ArrayRef<std::byte> new_content_bytes(\n        reinterpret_cast<std::byte*>(new_content_str.data()),\n        new_content_str.size());\n    for (auto write_bytes = new_content_bytes.slice(0, 4);\n         !write_bytes.empty();) {\n      auto write_result = f->WriteFromBuffer(write_bytes);\n      ASSERT_THAT(write_result, IsSuccess(_));\n      write_bytes = *write_result;\n    }\n\n    std::array<std::byte, 4> buffer;\n    auto read_result = f->ReadToBuffer(buffer);\n    ASSERT_THAT(read_result, IsSuccess(_));\n    EXPECT_THAT(std::string(reinterpret_cast<char*>(read_result->data()),\n                            read_result->size()),\n                Eq(content_str.substr(8, read_result->size())));\n\n    EXPECT_THAT(*f->ReadFileToString(), \"0123abcd89\");\n\n    // Now write the entire file, also changing its size, after a fresh seek.\n    seek_result = f->Seek(-6);\n    ASSERT_THAT(seek_result, IsSuccess(Eq(content_str.size() - 6)));\n    auto write_file_result = f->WriteFileFromString(new_content_str);\n    EXPECT_THAT(write_file_result, IsSuccess(_));\n    EXPECT_THAT(*f->ReadFileToString(), \"abcdefg\");\n    (*std::move(f)).Close().Check();\n  }\n\n  auto unlink_result = dir_.Unlink(\"test\");\n  EXPECT_THAT(unlink_result, IsSuccess(_));\n}\n\nTEST_F(FilesystemTest, CreateAndRemoveDirecotries) {\n  auto d1 = Cwd().CreateDirectories(path() / \"a\" / \"b\" / \"c\" / \"test1\");\n  ASSERT_THAT(d1, IsSuccess(_));\n  auto d2 = Cwd().CreateDirectories(path() / \"a\" / \"b\" / \"c\" / \"test2\");\n  ASSERT_THAT(d2, IsSuccess(_));\n  auto d3 = Cwd().CreateDirectories(path() / \"a\" / \"b\" / \"c\" / \"test3\");\n  ASSERT_THAT(d3, IsSuccess(_));\n  // Get a directory object to use, this shouldn't cover much new.\n  auto d4 = Cwd().CreateDirectories(path());\n  EXPECT_THAT(d4, IsSuccess(_));\n  // Single, present, relative component.\n  auto d5 = d4->CreateDirectories(\"a\");\n  EXPECT_THAT(d5, IsSuccess(_));\n  // Multiple, present, but relative components.\n  auto d6 = d5->CreateDirectories(std::filesystem::path(\"b\") / \"c\");\n  EXPECT_THAT(d6, IsSuccess(_));\n  // Single new component.\n  auto d7 = d6->CreateDirectories(\"test4\");\n  ASSERT_THAT(d7, IsSuccess(_));\n  // Two new relative components.\n  auto d8 = d6->CreateDirectories(std::filesystem::path(\"test5\") / \"d\");\n  EXPECT_THAT(d8, IsSuccess(_));\n  // Mixed relative components.\n  auto d9 = d5->CreateDirectories(std::filesystem::path(\"b\") / \"test6\");\n  EXPECT_THAT(d9, IsSuccess(_));\n\n  {\n    auto f1 = d1->OpenWriteOnly(\"file1\", CreateNew);\n    ASSERT_THAT(f1, IsSuccess(_));\n    auto f2 = d2->OpenWriteOnly(\"file2\", CreateNew);\n    ASSERT_THAT(f2, IsSuccess(_));\n    auto f3 = d3->OpenWriteOnly(\"file3\", CreateNew);\n    ASSERT_THAT(f3, IsSuccess(_));\n    auto f4 = d7->OpenWriteOnly(\"file4\", CreateNew);\n    ASSERT_THAT(f4, IsSuccess(_));\n    (*std::move(f1)).Close().Check();\n    (*std::move(f2)).Close().Check();\n    (*std::move(f3)).Close().Check();\n    (*std::move(f4)).Close().Check();\n  }\n\n  auto rm_result = Cwd().Rmtree(path() / \"a\");\n  ASSERT_THAT(rm_result, IsSuccess(_));\n}\n\nTEST_F(FilesystemTest, StatAndAccess) {\n  auto access_result = dir_.Access(\"test\");\n  ASSERT_FALSE(access_result.ok());\n  EXPECT_TRUE(access_result.error().no_entity());\n\n  // Make sure the flags and bit-or-ing them works in the boring case.\n  access_result =\n      dir_.Access(\"test\", AccessCheckFlags::Read | AccessCheckFlags::Write |\n                              AccessCheckFlags::Execute);\n  ASSERT_FALSE(access_result.ok());\n  EXPECT_TRUE(access_result.error().no_entity());\n\n  auto stat_result = dir_.Stat(\"test\");\n  ASSERT_FALSE(access_result.ok());\n  EXPECT_TRUE(access_result.error().no_entity());\n\n  // Create a file for testing, using very unusual and minimal permissions to\n  // help us test. Hopefully this isn't modified on the usual `umask` tests run\n  // under.\n  std::string content_str = \"0123456789\";\n  ModeType permissions = 0450;\n  auto f = dir_.OpenWriteOnly(\"test\", CreationOptions::CreateNew, permissions);\n  ASSERT_THAT(f, IsSuccess(_));\n  auto write_result = f->WriteFileFromString(content_str);\n  EXPECT_THAT(write_result, IsSuccess(_));\n\n  access_result = dir_.Access(\"test\");\n  EXPECT_THAT(access_result, IsSuccess(_));\n  access_result = dir_.Access(\"test\", AccessCheckFlags::Read);\n  EXPECT_THAT(access_result, IsSuccess(_));\n\n  // Neither write nor execute permission should be present though.\n  access_result = dir_.Access(\"test\", AccessCheckFlags::Write);\n  ASSERT_FALSE(access_result.ok());\n  EXPECT_TRUE(access_result.error().access_denied());\n  access_result =\n      dir_.Access(\"test\", AccessCheckFlags::Read | AccessCheckFlags::Write |\n                              AccessCheckFlags::Execute);\n  ASSERT_FALSE(access_result.ok());\n  EXPECT_TRUE(access_result.error().access_denied());\n\n  stat_result = dir_.Stat(\"test\");\n  ASSERT_THAT(stat_result, IsSuccess(_));\n  EXPECT_TRUE(stat_result->is_file());\n  EXPECT_FALSE(stat_result->is_dir());\n  EXPECT_FALSE(stat_result->is_symlink());\n  EXPECT_THAT(stat_result->size(), Eq(content_str.size()));\n  EXPECT_THAT(stat_result->permissions(), Eq(permissions));\n\n  // Directory instead of file.\n  access_result =\n      dir_.Access(\".\", AccessCheckFlags::Read | AccessCheckFlags::Write |\n                           AccessCheckFlags::Execute);\n  EXPECT_THAT(access_result, IsSuccess(_));\n\n  stat_result = dir_.Stat(\".\");\n  ASSERT_THAT(stat_result, IsSuccess(_));\n  EXPECT_FALSE(stat_result->is_file());\n  EXPECT_TRUE(stat_result->is_dir());\n  EXPECT_FALSE(stat_result->is_symlink());\n\n  // Can remove file but still stat through the file.\n  auto unlink_result = dir_.Unlink(\"test\");\n  ASSERT_THAT(unlink_result, IsSuccess(_));\n  auto file_stat_result = f->Stat();\n  ASSERT_THAT(file_stat_result, IsSuccess(_));\n  EXPECT_TRUE(file_stat_result->is_file());\n  EXPECT_FALSE(file_stat_result->is_dir());\n  EXPECT_FALSE(file_stat_result->is_symlink());\n  EXPECT_THAT(file_stat_result->size(), Eq(content_str.size()));\n  EXPECT_THAT(file_stat_result->permissions(), Eq(permissions));\n  (*std::move(f)).Close().Check();\n}\n\nTEST_F(FilesystemTest, Symlinks) {\n  auto readlink_result = dir_.Readlink(\"test\");\n  ASSERT_FALSE(readlink_result.ok());\n  EXPECT_TRUE(readlink_result.error().no_entity());\n\n  auto lstat_result = dir_.Lstat(\"test\");\n  ASSERT_FALSE(lstat_result.ok());\n  EXPECT_TRUE(lstat_result.error().no_entity());\n\n  auto symlink_result = dir_.Symlink(\"test\", \"abc\");\n  EXPECT_THAT(symlink_result, IsSuccess(_));\n\n  readlink_result = dir_.Readlink(\"test\");\n  EXPECT_THAT(readlink_result, IsSuccess(Eq(\"abc\")));\n\n  symlink_result = dir_.Symlink(\"test\", \"def\");\n  ASSERT_FALSE(symlink_result.ok());\n  EXPECT_TRUE(symlink_result.error().already_exists());\n\n  lstat_result = dir_.Lstat(\"test\");\n  ASSERT_THAT(lstat_result, IsSuccess(_));\n  EXPECT_FALSE(lstat_result->is_file());\n  EXPECT_FALSE(lstat_result->is_dir());\n  EXPECT_TRUE(lstat_result->is_symlink());\n  EXPECT_THAT(lstat_result->size(), Eq(strlen(\"abc\")));\n\n  auto unlink_result = dir_.Unlink(\"test\");\n  EXPECT_THAT(unlink_result, IsSuccess(_));\n\n  readlink_result = dir_.Readlink(\"test\");\n  ASSERT_FALSE(readlink_result.ok());\n  EXPECT_TRUE(readlink_result.error().no_entity());\n\n  // Try a symlink with null bytes for fun. This demonstrates that the symlink\n  // syscall only uses the leading C-string.\n  symlink_result = dir_.Symlink(\"test\", std::string(\"a\\0b\\0c\", 5));\n  EXPECT_THAT(symlink_result, IsSuccess(_));\n  readlink_result = dir_.Readlink(\"test\");\n  EXPECT_THAT(readlink_result, IsSuccess(Eq(\"a\")));\n}\n\nTEST_F(FilesystemTest, Chdir) {\n  auto current_result = Cwd().OpenDir(\".\");\n  ASSERT_THAT(current_result, IsSuccess(_));\n\n  auto symlink_result = dir_.Symlink(\"test\", \"abc\");\n  EXPECT_THAT(symlink_result, IsSuccess(_));\n\n  auto chdir_result = dir_.Chdir();\n  EXPECT_THAT(chdir_result, IsSuccess(_));\n  auto readlink_result = Cwd().Readlink(\"test\");\n  EXPECT_THAT(readlink_result, IsSuccess(Eq(\"abc\")));\n\n  auto chdir_path_result = dir_.Chdir(\"missing\");\n  ASSERT_FALSE(chdir_path_result.ok());\n  EXPECT_TRUE(chdir_path_result.error().no_entity());\n\n  // Dangling symlink.\n  chdir_path_result = dir_.Chdir(\"test\");\n  ASSERT_FALSE(chdir_path_result.ok());\n  EXPECT_TRUE(chdir_path_result.error().no_entity());\n\n  // Create a regular file and try to chdir to that.\n  auto f = dir_.OpenWriteOnly(\"test2\", CreationOptions::CreateNew);\n  ASSERT_THAT(f, IsSuccess(_));\n  auto write_result = f->WriteFileFromString(\"test2\");\n  EXPECT_THAT(write_result, IsSuccess(_));\n  chdir_path_result = dir_.Chdir(\"test2\");\n  ASSERT_FALSE(chdir_path_result.ok());\n  EXPECT_TRUE(chdir_path_result.error().not_dir());\n\n  auto d2_result = Cwd().OpenDir(\"test_d2\", CreationOptions::CreateNew);\n  ASSERT_THAT(d2_result, IsSuccess(_));\n  symlink_result = d2_result->Symlink(\"test2\", \"def\");\n  EXPECT_THAT(symlink_result, IsSuccess(_));\n\n  chdir_path_result = dir_.Chdir(\"test_d2\");\n  ASSERT_THAT(chdir_path_result, IsSuccess(_));\n  readlink_result = Cwd().Readlink(\"test2\");\n  EXPECT_THAT(readlink_result, IsSuccess(Eq(\"def\")));\n  readlink_result = Cwd().Readlink(\"../test\");\n  EXPECT_THAT(readlink_result, IsSuccess(Eq(\"abc\")));\n\n  chdir_result = current_result->Chdir();\n  ASSERT_THAT(chdir_result, IsSuccess(_));\n  readlink_result = Cwd().Readlink(\"test\");\n  ASSERT_FALSE(readlink_result.ok());\n  EXPECT_TRUE(readlink_result.error().no_entity());\n  (*std::move(f)).Close().Check();\n}\n\nTEST_F(FilesystemTest, WriteStream) {\n  std::string content_str = \"0123456789\";\n  auto write = dir_.OpenWriteOnly(\"test\", CreationOptions::CreateNew);\n  ASSERT_THAT(write, IsSuccess(_));\n  {\n    llvm::raw_fd_ostream os = write->WriteStream();\n    os << content_str;\n    EXPECT_FALSE(os.has_error()) << os.error();\n  }\n  (*std::move(write)).Close().Check();\n\n  EXPECT_THAT(dir_.ReadFileToString(\"test\"), IsSuccess(Eq(content_str)));\n}\n\nTEST_F(FilesystemTest, Rename) {\n  // Rename a file within a directory.\n  ASSERT_THAT(dir_.WriteFileFromString(\"file1\", \"content1\"), IsSuccess(_));\n  EXPECT_THAT(dir_.Rename(\"file1\", dir_, \"file2\"), IsSuccess(_));\n  EXPECT_THAT(dir_.ReadFileToString(\"file2\"), IsSuccess(Eq(\"content1\")));\n  auto read_missing = dir_.ReadFileToString(\"file1\");\n  EXPECT_FALSE(read_missing.ok());\n  EXPECT_TRUE(read_missing.error().no_entity());\n\n  // Rename a file between two directories.\n  auto d1 = *dir_.CreateDirectories(\"subdir1\");\n  EXPECT_THAT(dir_.Rename(\"file2\", d1, \"file1\"), IsSuccess(_));\n  EXPECT_THAT(d1.ReadFileToString(\"file1\"), IsSuccess(Eq(\"content1\")));\n  auto d2 = *dir_.CreateDirectories(\"subdir2\");\n  EXPECT_THAT(d1.Rename(\"file1\", d2, \"file1\"), IsSuccess(_));\n  EXPECT_THAT(d2.ReadFileToString(\"file1\"), IsSuccess(Eq(\"content1\")));\n  // Close the first directory.\n  d1 = Filesystem::Dir();\n  EXPECT_THAT(dir_.Rmdir(\"subdir1\"), IsSuccess(_))\n      << \"Directory should have bene empty!\";\n\n  // Rename directories.\n  ASSERT_THAT(dir_.ReadFileToString(std::filesystem::path(\"subdir2\") / \"file1\"),\n              IsSuccess(Eq(\"content1\")));\n  EXPECT_THAT(dir_.Rename(\"subdir2\", dir_, \"subdir1\"), IsSuccess(_));\n  EXPECT_THAT(dir_.ReadFileToString(std::filesystem::path(\"subdir1\") / \"file1\"),\n              IsSuccess(Eq(\"content1\")));\n\n  // The open directory `d2` should survive the rename and point at the same\n  // directory.\n  EXPECT_THAT(d2.ReadFileToString(\"file1\"), IsSuccess(Eq(\"content1\")));\n  EXPECT_THAT(d2.WriteFileFromString(\"file2\", \"content2\"), IsSuccess(_));\n  EXPECT_THAT(dir_.ReadFileToString(std::filesystem::path(\"subdir1\") / \"file2\"),\n              IsSuccess(Eq(\"content2\")));\n\n  // Rename over an existing file.\n  EXPECT_THAT(d2.Rename(\"file2\", d2, \"file1\"), IsSuccess(_));\n  EXPECT_THAT(d2.ReadFileToString(\"file1\"), IsSuccess(Eq(\"content2\")));\n\n  // Test error calls as well.\n  auto result = dir_.Rename(\"missing1\", dir_, \"missing2\");\n  EXPECT_TRUE(result.error().no_entity()) << result.error();\n  result = d2.Rename(\"file1\", dir_,\n                     std::filesystem::path(\"missing_subdir\") / \"file2\");\n  EXPECT_TRUE(result.error().no_entity()) << result.error();\n  // Note that `d2` was renamed `subdir1` above, which is why this creates\n  // infinite subdirectories.\n  result = dir_.Rename(\"subdir1\", d2, \"infinite_subdirs\");\n  EXPECT_THAT(result.error().unix_errnum(), EINVAL) << result.error();\n}\n\nTEST_F(FilesystemTest, TryLock) {\n  auto file = dir_.OpenReadWrite(\"test_file\", CreateNew);\n  ASSERT_THAT(file, IsSuccess(_));\n\n  // Acquire an exclusive lock.\n  auto lock = file->TryLock(FileLock::Exclusive);\n  ASSERT_THAT(lock, IsSuccess(_));\n  EXPECT_TRUE(lock->is_locked());\n\n  // Try to acquire a second lock from a different file object.\n  auto file2 = dir_.OpenReadOnly(\"test_file\");\n  ASSERT_THAT(file2, IsSuccess(_));\n  auto lock2 = file2->TryLock(FileLock::Exclusive);\n  ASSERT_THAT(lock2, IsError(_));\n  EXPECT_TRUE(lock2.error().would_block());\n\n  // A shared lock should also fail.\n  auto lock3 = file2->TryLock(FileLock::Shared);\n  ASSERT_THAT(lock3, IsError(_));\n  EXPECT_TRUE(lock3.error().would_block());\n\n  // Release the first lock.\n  *lock = {};\n  EXPECT_FALSE(lock->is_locked());\n\n  // Now we can acquire an exclusive lock.\n  lock2 = file2->TryLock(FileLock::Exclusive);\n  ASSERT_THAT(lock2, IsSuccess(_));\n  EXPECT_TRUE(lock2->is_locked());\n  *lock2 = {};\n\n  // Test shared locks.\n  auto shared_lock1 = file->TryLock(FileLock::Shared);\n  ASSERT_THAT(shared_lock1, IsSuccess(_));\n  EXPECT_TRUE(shared_lock1->is_locked());\n\n  auto shared_lock2 = file2->TryLock(FileLock::Shared);\n  ASSERT_THAT(shared_lock2, IsSuccess(_));\n  EXPECT_TRUE(shared_lock2->is_locked());\n\n  // An exclusive lock should fail.\n  auto file3 = dir_.OpenReadOnly(\"test_file\");\n  ASSERT_THAT(file3, IsSuccess(_));\n  auto exclusive_lock = file3->TryLock(FileLock::Exclusive);\n  ASSERT_THAT(exclusive_lock, IsError(_));\n  EXPECT_TRUE(exclusive_lock.error().would_block());\n\n  // Release locks and close files.\n  *shared_lock1 = {};\n  *shared_lock2 = {};\n  ASSERT_THAT((*std::move(file)).Close(), IsSuccess(_));\n  ASSERT_THAT((*std::move(file2)).Close(), IsSuccess(_));\n  ASSERT_THAT((*std::move(file3)).Close(), IsSuccess(_));\n}\n\nTEST_F(FilesystemTest, ReadAndAppendEntries) {\n  // Test with an empty directory.\n  {\n    auto entries = dir_.ReadEntries();\n    ASSERT_THAT(entries, IsSuccess(_));\n    EXPECT_TRUE(entries->empty());\n  }\n  {\n    llvm::SmallVector<std::filesystem::path> entries;\n    EXPECT_THAT(dir_.AppendEntriesIf(entries), IsSuccess(_));\n    EXPECT_TRUE(entries.empty());\n  }\n\n  // Create some files and directories.\n  ASSERT_THAT(dir_.WriteFileFromString(\"file1\", \"\"), IsSuccess(_));\n  ASSERT_THAT(dir_.WriteFileFromString(\"file2\", \"\"), IsSuccess(_));\n  ASSERT_THAT(dir_.WriteFileFromString(\".hidden\", \"\"), IsSuccess(_));\n  ASSERT_THAT(dir_.CreateDirectories(\"subdir1\"), IsSuccess(_));\n  ASSERT_THAT(dir_.CreateDirectories(\"subdir2\"), IsSuccess(_));\n\n  // Test ReadEntries.\n  {\n    auto entries = dir_.ReadEntries();\n    ASSERT_THAT(entries, IsSuccess(_));\n    EXPECT_THAT(*entries, UnorderedElementsAre(\".hidden\", \"file1\", \"file2\",\n                                               \"subdir1\", \"subdir2\"));\n  }\n\n  // Test AppendEntriesIf with no predicate.\n  {\n    llvm::SmallVector<std::filesystem::path> entries;\n    EXPECT_THAT(dir_.AppendEntriesIf(entries), IsSuccess(_));\n    EXPECT_THAT(entries, UnorderedElementsAre(\".hidden\", \"file1\", \"file2\",\n                                              \"subdir1\", \"subdir2\"));\n  }\n\n  // Test AppendEntriesIf with a predicate.\n  {\n    llvm::SmallVector<std::filesystem::path> entries;\n    auto result = dir_.AppendEntriesIf(\n        entries, [](llvm::StringRef name) { return name.starts_with(\"file\"); });\n    EXPECT_THAT(result, IsSuccess(_));\n    EXPECT_THAT(entries, UnorderedElementsAre(\"file1\", \"file2\"));\n  }\n\n  // Test AppendEntriesIf with directory splitting and a predicate.\n  {\n    llvm::SmallVector<std::filesystem::path> dir_entries;\n    llvm::SmallVector<std::filesystem::path> non_dir_entries;\n    auto result = dir_.AppendEntriesIf(\n        dir_entries, non_dir_entries,\n        [](llvm::StringRef name) { return !name.starts_with(\".\"); });\n    EXPECT_THAT(result, IsSuccess(_));\n    EXPECT_THAT(dir_entries, UnorderedElementsAre(\"subdir1\", \"subdir2\"));\n    EXPECT_THAT(non_dir_entries, UnorderedElementsAre(\"file1\", \"file2\"));\n  }\n}\n\nTEST_F(FilesystemTest, MtimeAndUpdateTimes) {\n  // Test UpdateTimes on a path that doesn't exist.\n  auto update_missing = dir_.UpdateTimes(\"test_file\");\n  ASSERT_THAT(update_missing, IsError(_));\n  EXPECT_TRUE(update_missing.error().no_entity());\n\n  // Create a file and get its initial modification time.\n  ASSERT_THAT(dir_.WriteFileFromString(\"test_file\", \"content\"), IsSuccess(_));\n  auto stat = dir_.Stat(\"test_file\");\n  ASSERT_THAT(stat, IsSuccess(_));\n  auto time1 = stat->mtime();\n\n  // Repeated stats have stable time.\n  stat = dir_.Stat(\"test_file\");\n  ASSERT_THAT(stat, IsSuccess(_));\n  EXPECT_THAT(stat->mtime(), Eq(time1));\n\n  // Update the timestamp to a specific time in the past.\n  auto past_time = time1 - std::chrono::seconds(120);\n  ASSERT_THAT(dir_.UpdateTimes(\"test_file\", past_time), IsSuccess(_));\n  stat = dir_.Stat(\"test_file\");\n  ASSERT_THAT(stat, IsSuccess(_));\n  EXPECT_THAT(stat->mtime(), Eq(past_time));\n\n  // Now test updating times on an open file. Should still be at `past_time`.\n  auto file = *dir_.OpenReadWrite(\"test_file\");\n  auto file_stat = file.Stat();\n  ASSERT_THAT(file_stat, IsSuccess(_));\n  EXPECT_THAT(file_stat->mtime(), Eq(past_time));\n\n  // Update the times through the file and verify those updates arrived.\n  ASSERT_THAT(file.UpdateTimes(time1), IsSuccess(_));\n  file_stat = file.Stat();\n  ASSERT_THAT(file_stat, IsSuccess(_));\n  EXPECT_THAT(file_stat->mtime(), Eq(time1));\n\n  ASSERT_THAT(std::move(file).Close(), IsSuccess(_));\n}\n\n}  // namespace\n}  // namespace Carbon::Filesystem\n"
  },
  {
    "path": "common/find.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_FIND_H_\n#define CARBON_COMMON_FIND_H_\n\n#include <concepts>\n#include <type_traits>\n\n#include \"llvm/ADT/STLExtras.h\"\n\nnamespace Carbon {\n\nnamespace Internal {\n\ntemplate <typename Range>\nusing RangePointerType = typename std::iterator_traits<decltype(std::begin(\n    std::declval<Range>()))>::pointer;\n\ntemplate <typename Range>\nusing RangeValueType = typename std::iterator_traits<decltype(std::begin(\n    std::declval<Range>()))>::value_type;\n\ntemplate <typename Range, typename Pred>\nconcept IsValidFindPredicate =\n    requires(const RangeValueType<Range>& elem, Pred pred) {\n      { pred(elem) } -> std::convertible_to<bool>;\n    };\n\ntemplate <typename A, typename B>\nconcept IsComparable = requires(const A& a, const B& b) {\n  { a == b } -> std::convertible_to<bool>;\n};\n\ntemplate <typename Range>\nconcept RangeValueHasNoneType = requires {\n  { RangeValueType<Range>::None } -> std::convertible_to<RangeValueType<Range>>;\n};\n\n}  // namespace Internal\n\n// Finds a value in the given `range` by testing the `predicate`. Returns a\n// pointer to the value from the range on success, and nullptr if nothing is\n// found.\n//\n// This is similar to `std::find_if()` but returns a pointer to the value\n// instead of an iterator that must be tested against `end()`.\ntemplate <typename Range, typename Pred>\n  requires Internal::IsValidFindPredicate<Range, Pred>\nconstexpr auto FindIfOrNull(Range&& range, Pred predicate)\n    -> Internal::RangePointerType<Range> {\n  auto it = llvm::find_if(range, predicate);\n  if (it != range.end()) {\n    return std::addressof(*it);\n  } else {\n    return nullptr;\n  }\n}\n\n// Finds a value in the given `range` by testing the `predicate` and returns a\n// copy of it. If no match is found, returns `T::None` where the input range is\n// over values of type `T`.\ntemplate <typename Range, typename Pred>\n  requires Internal::IsValidFindPredicate<Range, Pred> &&\n           Internal::RangeValueHasNoneType<Range> &&\n           std::copy_constructible<Internal::RangeValueType<Range>>\nconstexpr auto FindIfOrNone(Range&& range, Pred predicate)\n    -> Internal::RangeValueType<Range> {\n  auto it = llvm::find_if(range, predicate);\n  if (it != range.end()) {\n    return *it;\n  } else {\n    return Internal::RangeValueType<Range>::None;\n  }\n}\n\n// Finds a value in the given `range` by comparing to `query`. Returns a\n// pointer to the value from the range on success, and nullptr if nothing is\n// found.\n//\n// This is similar to `std::find_if()` but returns a pointer to the value\n// instead of an iterator that must be tested against `end()`.\ntemplate <typename Range, typename Query = Internal::RangeValueType<Range>>\n  requires Internal::IsComparable<Query, Internal::RangeValueType<Range>>\nconstexpr auto Contains(Range&& range, const Query& query) -> bool {\n  return llvm::find(range, query) != range.end();\n}\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_FIND_H_\n"
  },
  {
    "path": "common/find_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/find.h\"\n\n#include <gtest/gtest.h>\n\n#include <vector>\n\nnamespace Carbon {\nnamespace {\n\nstruct NoneType {\n  static const NoneType None;\n  int i;\n\n  friend auto operator==(NoneType, NoneType) -> bool = default;\n};\n\nconst NoneType NoneType::None = {.i = -1};\n\nTEST(FindTest, ReturnType) {\n  const std::vector<int> c;\n  std::vector<int> m;\n\n  auto pred = [](int) { return true; };\n  static_assert(std::same_as<decltype(FindIfOrNull(c, pred)), const int*>);\n  static_assert(std::same_as<decltype(FindIfOrNull(m, pred)), int*>);\n}\n\nTEST(FindTest, FindIfOrNull) {\n  auto make_pred = [](int query) {\n    return [=](int elem) { return query == elem; };\n  };\n\n  std::vector<int> empty;\n  EXPECT_EQ(FindIfOrNull(empty, make_pred(0)), nullptr);\n\n  std::vector<int> range = {1, 2};\n  EXPECT_EQ(FindIfOrNull(range, make_pred(0)), nullptr);\n  // NOLINTNEXTLINE(readability-container-data-pointer)\n  EXPECT_EQ(FindIfOrNull(range, make_pred(1)), &range[0]);\n  EXPECT_EQ(FindIfOrNull(range, make_pred(2)), &range[1]);\n  EXPECT_EQ(FindIfOrNull(range, make_pred(3)), nullptr);\n}\n\nTEST(FindTest, FindIfOrNone) {\n  auto make_pred = [](NoneType query) {\n    return [=](NoneType elem) { return query == elem; };\n  };\n\n  std::vector<NoneType> empty;\n  EXPECT_EQ(FindIfOrNone(empty, make_pred(NoneType{0})).i, -1);\n\n  std::vector<NoneType> range = {NoneType{1}, NoneType{2}};\n  EXPECT_EQ(FindIfOrNone(range, make_pred(NoneType{0})).i, -1);\n  EXPECT_EQ(FindIfOrNone(range, make_pred(NoneType{1})).i, 1);\n  EXPECT_EQ(FindIfOrNone(range, make_pred(NoneType{2})).i, 2);\n  EXPECT_EQ(FindIfOrNone(range, make_pred(NoneType{3})).i, -1);\n}\n\nTEST(FindTest, Contains) {\n  std::vector<int> empty;\n  EXPECT_EQ(Contains(empty, 0), false);\n\n  std::vector<int> range = {1, 2};\n  EXPECT_EQ(Contains(range, 0), false);\n  EXPECT_EQ(Contains(range, 1), true);\n  EXPECT_EQ(Contains(range, 2), true);\n  EXPECT_EQ(Contains(range, 3), false);\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/growing_range.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_GROWING_RANGE_H_\n#define CARBON_COMMON_GROWING_RANGE_H_\n\n#include <ranges>\n\nnamespace Carbon {\n\n// A range adaptor for a random-access container such as `std::vector` or\n// `llvm::SmallVector` that might have elements appended during the iteration.\n// This adaptor avoids invalidation issues by tracking an index instead of an\n// iterator, and by returning by value from `operator*` instead of by reference.\n//\n// This class is intended only for use as the range in a range-based for loop,\n// and as such does not provide a complete range or iterator interface. Instead,\n// it provides only the interface required by the range-based for loop.\ntemplate <typename ContainerT>\n  requires std::ranges::sized_range<ContainerT> &&\n           std::ranges::random_access_range<ContainerT>\nclass GrowingRange {\n public:\n  // An end sentinel for the range.\n  class End {};\n\n  // An iterator into a potentially-growing range. Tracks the container and the\n  // current index, and indexes the container on each dereference.\n  class Iterator {\n   public:\n    // Dereferences the iterator. These intentionally don't return by reference,\n    // to avoid handing out a reference that would be invalidated when the\n    // container grows during the traversal.\n    auto operator*() -> auto { return (*container_)[index_]; }\n    auto operator*() const -> auto { return (*container_)[index_]; }\n\n    friend auto operator!=(Iterator it, End /*end*/) -> bool {\n      return it.index_ != it.container_->size();\n    }\n\n    auto operator++() -> void { ++index_; }\n\n   private:\n    friend class GrowingRange;\n\n    explicit Iterator(const ContainerT* container)\n        : container_(container), index_(0) {}\n\n    const ContainerT* container_;\n    size_t index_;\n  };\n\n  explicit GrowingRange(const ContainerT& container) : container_(&container) {}\n\n  auto begin() const -> Iterator { return Iterator(container_); }\n  auto end() const -> End { return {}; }\n\n private:\n  const ContainerT* container_;\n};\n\ntemplate <typename ContainerT>\nGrowingRange(const ContainerT&) -> GrowingRange<ContainerT>;\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_GROWING_RANGE_H_\n"
  },
  {
    "path": "common/growing_range_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/growing_range.h\"\n\n#include <gtest/gtest.h>\n\n#include <vector>\n\nnamespace Carbon {\nnamespace {\n\nTEST(GrowingRangeTest, TestUnchanged) {\n  std::vector<int> v = {1, 2, 3, 4, 5};\n  int k = 0;\n  for (int n : GrowingRange(v)) {\n    EXPECT_EQ(n, ++k);\n  }\n}\n\nTEST(GrowingRangeTest, TestGrowWithRealloc) {\n  std::vector<int> expected = {3, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0};\n\n  std::vector<int> v;\n  v.reserve(1);\n  v.push_back(3);\n  EXPECT_LT(v.capacity(), expected.size());\n\n  int i = 0;\n  for (int n : GrowingRange(v)) {\n    // Append n copies of n - 1.\n    v.insert(v.end(), n, n - 1);\n    EXPECT_EQ(n, expected[i++]);\n  }\n}\n\nTEST(GrowingRangeTest, TestNoReference) {\n  std::vector<int> v;\n  // Use `decltype(auto)` to capture the type of the element including whether\n  // it's a reference.\n  for (decltype(auto) elem : GrowingRange(v)) {\n    // The type of `elem` should be `int`, not `int&`.\n    static_assert(std::same_as<decltype(elem), int>);\n  }\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/hashing.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/hashing.h\"\n\n#include <cstddef>\n\nnamespace Carbon {\n\nauto Hasher::HashSizedBytesLarge(llvm::ArrayRef<std::byte> bytes) -> void {\n  const std::byte* data_ptr = bytes.data();\n  const ssize_t size = bytes.size();\n  CARBON_DCHECK(size > 32);\n\n  // If we have 64 bytes or more, we're going to handle two 32-byte chunks at a\n  // time using a simplified version of the main algorithm. This is based\n  // heavily on the 64-byte and larger processing approach used by Abseil. The\n  // goal is to mix the input data using as few multiplies (or other operations)\n  // as we can and with as much [ILP][1] as we can. The ILP comes largely from\n  // creating parallel structures to the operations.\n  //\n  // [1]: https://en.wikipedia.org/wiki/Instruction-level_parallelism\n  auto mix32 = [](const std::byte* data_ptr, uint64_t buffer, uint64_t random0,\n                  uint64_t random1) {\n    uint64_t a = Read8(data_ptr);\n    uint64_t b = Read8(data_ptr + 8);\n    uint64_t c = Read8(data_ptr + 16);\n    uint64_t d = Read8(data_ptr + 24);\n    uint64_t m0 = Mix(a ^ random0, b ^ buffer);\n    uint64_t m1 = Mix(c ^ random1, d ^ buffer);\n    return (m0 ^ m1);\n  };\n\n  // Prefetch the first bytes into cache.\n  __builtin_prefetch(data_ptr, 0 /* read */, 0 /* discard after next use */);\n\n  uint64_t buffer0 = buffer ^ StaticRandomData[0];\n  uint64_t buffer1 = buffer ^ StaticRandomData[2];\n  const std::byte* tail_32b_ptr = data_ptr + (size - 32);\n  const std::byte* tail_16b_ptr = data_ptr + (size - 16);\n  const std::byte* end_ptr = data_ptr + (size - 64);\n  while (data_ptr < end_ptr) {\n    // Prefetch the next 64-bytes while we process the current 64-bytes.\n    __builtin_prefetch(data_ptr + 64, 0 /* read */,\n                       0 /* discard after next use */);\n\n    buffer0 =\n        mix32(data_ptr, buffer0, StaticRandomData[4], StaticRandomData[5]);\n    buffer1 =\n        mix32(data_ptr + 32, buffer1, StaticRandomData[6], StaticRandomData[7]);\n\n    data_ptr += 64;\n  }\n\n  // If we haven't reached our 32-byte tail pointer, consume another 32-bytes\n  // directly.\n  if (data_ptr < tail_32b_ptr) {\n    buffer0 =\n        mix32(data_ptr, buffer0, StaticRandomData[4], StaticRandomData[5]);\n    data_ptr += 32;\n  }\n\n  if (data_ptr < tail_16b_ptr) {\n    // We have more than 16-bytes in the tail so use a full 32-byte mix from the\n    // 32-byte tail pointer.\n    buffer1 =\n        mix32(tail_32b_ptr, buffer1, StaticRandomData[6], StaticRandomData[7]);\n  } else {\n    // 16-bytes or less in the tail, do something more minimal instead of a full\n    // 32-byte mix. As this only involves a single multiply, we don't decompose\n    // further even when the tail is (much) shorter.\n    buffer1 = Mix(Read8(tail_16b_ptr) ^ StaticRandomData[6],\n                  Read8(tail_16b_ptr + 8) ^ buffer1);\n  }\n\n  buffer = buffer0 ^ buffer1;\n  HashDense(size);\n}\n\n}  // namespace Carbon\n"
  },
  {
    "path": "common/hashing.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_HASHING_H_\n#define CARBON_COMMON_HASHING_H_\n\n#include <concepts>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n#include \"llvm/ADT/APFloat.h\"\n#include \"llvm/ADT/APInt.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n\n#ifdef __ARM_ACLE\n#include <arm_acle.h>\n#endif\n\nnamespace Carbon {\n\n// A 64-bit hash code produced by `Carbon::HashValue`.\n//\n// This provides methods for extracting high-quality bits from the hash code\n// quickly.\n//\n// This class can also be a hashing input when recursively hashing more complex\n// data structures.\nclass HashCode : public Printable<HashCode> {\n public:\n  HashCode() = default;\n\n  constexpr explicit HashCode(uint64_t value) : value_(value) {}\n\n  friend constexpr auto operator==(HashCode lhs, HashCode rhs) -> bool {\n    return lhs.value_ == rhs.value_;\n  }\n  friend constexpr auto operator!=(HashCode lhs, HashCode rhs) -> bool {\n    return lhs.value_ != rhs.value_;\n  }\n\n  // Extracts an index from the hash code as a `ssize_t`. This index covers the\n  // full range of that type, and may even be negative. Typical usage will\n  // involve masking this down to some positive range using a bitand with a mask\n  // computed from a power-of-two size. This routine doesn't do any masking to\n  // ensure a positive index to avoid redundant computations with the typical\n  // user of the index.\n  constexpr auto ExtractIndex() -> ssize_t;\n\n  // Extracts an index and a fixed `N`-bit tag from the hash code.\n  //\n  // This extracts these values from the position of the hash code which\n  // maximizes the entropy in the tag and the low bits of the index, as typical\n  // indices will be further masked down to fall in a smaller range.\n  //\n  // `N` must be in the range [1, 32]. The returned index will be in the range\n  // [0, 2**(64-N)).\n  template <int N>\n  constexpr auto ExtractIndexAndTag() -> std::pair<ssize_t, uint32_t>;\n\n  // Extract the full 64-bit hash code as an integer.\n  //\n  // The methods above should be preferred rather than directly manipulating\n  // this integer. This is provided primarily to enable Merkle-tree hashing or\n  // other recursive hashing where that is needed or more efficient.\n  explicit operator uint64_t() const { return value_; }\n\n  auto Print(llvm::raw_ostream& out) const -> void {\n    out << llvm::formatv(\"{0:x16}\", value_);\n  }\n\n private:\n  uint64_t value_ = 0;\n};\n\n// Computes a hash code for the provided value, incorporating the provided seed.\n//\n// The seed doesn't need to be of any particular high quality, but a zero seed\n// has bad effects in several places. Prefer the unseeded routine rather than\n// providing a zero here.\n//\n// This **not** a cryptographically secure or stable hash -- it is only designed\n// for use with in-memory hash table style data structures. Being fast and\n// effective for that use case is the guiding principle of its design.\n//\n// There is no guarantee that the values produced are stable from execution to\n// execution. For speed and quality reasons, the implementation does not\n// introduce any variance to defend against accidental dependencies. As a\n// consequence, it is strongly encouraged to use a seed that varies from\n// execution to execution to avoid depending on specific values produced.\n//\n// The algorithm used is most heavily based on [Abseil's hashing algorithm][1],\n// with some additional ideas and inspiration from the fallback hashing\n// algorithm in [Rust's AHash][2] and the [FxHash][3] function. However, there\n// are also *significant* changes introduced here.\n//\n// [1]: https://github.com/abseil/abseil-cpp/tree/master/absl/hash/internal\n// [2]: https://github.com/tkaitchuck/aHash/wiki/AHash-fallback-algorithm\n// [3]: https://docs.rs/fxhash/latest/fxhash/\n//\n// This hash algorithm does *not* defend against hash flooding. While it can be\n// viewed as \"keyed\" on the seed, it is expected to be possible to craft inputs\n// for some data types that cancel out the seed used and manufacture endlessly\n// colliding sets of keys. In general, this function works to be *fast* for hash\n// tables. If you need to defend against hash flooding, either directly use a\n// data structure with strong worst-case guarantees, or a hash table which\n// detects catastrophic collisions and falls back to such a data structure.\n//\n// This hash function is heavily optimized for *latency* over *quality*. Modern\n// hash tables designs can efficiently handle reasonable collision rates,\n// including using extra bits from the hash to avoid all efficiency coming from\n// the same low bits. Because of this, low-latency is significantly more\n// important for performance than high-quality, and this is heavily leveraged.\n// The result is that the hash codes produced *do* have significant avalanche\n// problems for small keys. The upside is that the latency for hashing integers,\n// pointers, and small byte strings (up to 32-bytes) is exceptionally low, and\n// essentially a small constant time instruction sequence.\n//\n// No exotic instruction set extensions are required, and the state used is\n// small. It does rely on being able to get the low- and high-64-bit results of\n// a 64-bit multiply efficiently.\n//\n// The function supports many typical data types such as primitives, string-ish\n// views, and types composing primitives transparently like pairs, tuples, and\n// array-ish views. It is also extensible to support user-defined types.\n//\n// The builtin support for string-like types include:\n// - `std::string_view`\n// - `std::string`\n// - `llvm::StringRef`\n// - `llvm::SmallString`\n//\n// This function supports heterogeneous lookup between all of the string-like\n// types. It also supports heterogeneous lookup between pointer types regardless\n// of pointee type and `nullptr`.\n//\n// However, these are the only heterogeneous lookup support including for the\n// builtin in, standard, and LLVM types. Notably, each different size and\n// signedness integer type may hash differently for efficiency reasons. Hash\n// tables should pick a single integer type in which to manage keys and do\n// lookups.\n//\n// To add support for your type, you need to implement a customization point --\n// a free function that can be found by ADL for your type -- called\n// `CarbonHashValue` with the following signature:\n//\n// ```cpp\n// auto CarbonHashValue(const YourType& value, uint64_t seed) -> HashCode;\n// ```\n//\n// The extension point needs to ensure that values that compare equal (including\n// any comparisons with different types that might be used with a hash table of\n// `YourType` keys) produce the same `HashCode` values.\n//\n// `HashCode` values should typically be produced using the `Hasher` helper type\n// below. See its documentation for more details about implementing these\n// customization points and how best to incorporate the value's state into a\n// `HashCode`.\n//\n// For two input values that are almost but not quite equal, the extension\n// point should maximize the probability of each bit of their resulting\n// `HashCode`s differing. More formally, `HashCode`s should exhibit an\n// [avalanche effect][4]. However, while this is desirable, it should be\n// **secondary** to low latency. The intended use case of these functions is not\n// cryptography but in-memory hashtables where the latency and overhead of\n// computing the `HashCode` is *significantly* more important than achieving a\n// particularly high quality. The goal is to have \"just enough\" avalanche\n// effect, but there is not a fixed criteria for how much is enough. That should\n// be determined through practical experimentation with a hashtable and\n// distribution of keys.\n//\n// [4]: https://en.wikipedia.org/wiki/Avalanche_effect\ntemplate <typename T>\ninline auto HashValue(const T& value, uint64_t seed) -> HashCode;\n\n// The same as the seeded version of `HashValue` but without callers needing to\n// provide a seed.\n//\n// Generally prefer the seeded version, but this is available if there is no\n// reasonable seed. In particular, this will behave better than using a seed of\n// `0`. One important use case is for recursive hashing of sub-objects where\n// appropriate or needed.\ntemplate <typename T>\ninline auto HashValue(const T& value) -> HashCode;\n\n// Object and APIs that eventually produce a hash code.\n//\n// This type is primarily used by types to implement a customization point\n// `CarbonHashValue` that will in turn be used by the `HashValue` function. See\n// the `HashValue` function for details of that extension point.\n//\n// The methods on this type can be used to incorporate data from your\n// user-defined type into its internal state which can be converted to a\n// `HashCode` at any time. These methods will only produce the same `HashCode`\n// if they are called in the exact same order with the same arguments -- there\n// are no guaranteed equivalences between calling different methods.\n//\n// Example usage:\n// ```cpp\n// auto CarbonHashValue(const MyType& value, uint64_t seed) -> HashCode {\n//   Hasher hasher(seed);\n//   hasher.HashTwo(value.x, value.y);\n//   return static_cast<HashCode>(hasher);\n// }\n// ```\n//\n// This type's API also reflects the reality that high-performance hash tables\n// are used with keys that are generally small and cheap to hash.\n//\n// To ensure this type's code is optimized effectively, it should typically be\n// used as a local variable and not passed across function boundaries\n// unnecessarily.\n//\n// The type also provides a number of static helper functions and static data\n// members that may be used by authors of `CarbonHashValue` implementations to\n// efficiently compute the inputs to the core `Hasher` methods, or even to\n// manually do some amounts of hashing in performance-tuned ways outside of the\n// methods provided.\nclass Hasher {\n public:\n  Hasher() = default;\n  explicit Hasher(uint64_t seed) : buffer(seed) {}\n\n  Hasher(Hasher&& arg) = default;\n  Hasher(const Hasher& arg) = delete;\n  auto operator=(Hasher&& rhs) -> Hasher& = default;\n\n  // Extracts the current state as a `HashCode` for use.\n  explicit operator HashCode() const { return HashCode(buffer); }\n\n  // Incorporates a variable number of objects into the `hasher`s state.\n  //\n  // The `values` here can be anything hashable, and this routine handles\n  // recursively hashing a single value as appropriate and then in turn\n  // incorporating that. However, it is optimized for relatively small numbers\n  // of values and/or small elements. A large tree structure will be better\n  // handled by a dedicated Merkle-tree decomposition rather than the ad-hoc one\n  // provided here. This routine's decomposition is mostly useful for combining\n  // N small bits of data with one recursively hashed entity.\n  //\n  // There is no guaranteed correspondence between the behavior of a single call\n  // with multiple parameters and multiple calls.\n  template <typename... Ts>\n  auto Hash(const Ts&... values) -> void;\n\n  // Incorporates an array of objects into the hasher's state.\n  //\n  // Similar to the variadic `Hash`, this will handle recursively hashing if\n  // necessary, but is optimized to avoid it when possible and is especially\n  // efficient when hashing a raw array of bytes.\n  //\n  // Note that this is especially inefficient when it must recursively hash for\n  // long arrays -- that pattern should be avoided if possible. It is usually\n  // more effective to optimize that pattern at a higher level with a dedicated\n  // hashing implementation.\n  template <typename T>\n  auto HashArray(llvm::ArrayRef<T> values) -> void;\n\n  // Incorporates an object into the hasher's state by hashing its object\n  // representation. Requires `value`'s type to have a unique object\n  // representation. This is primarily useful for builtin and primitive types.\n  //\n  // This can be directly used for simple users combining some aggregation of\n  // objects. However, when possible, prefer the variadic version below for\n  // aggregating several primitive types into a hash.\n  template <typename T>\n    requires std::has_unique_object_representations_v<T>\n  auto HashRaw(const T& value) -> void;\n\n  // Simpler and more primitive functions to incorporate state represented in\n  // `uint64_t` values into the hasher's state.\n  //\n  // These may be slightly less efficient than the `Hash` method above for a\n  // typical application code `uint64_t`, but are designed to work well even\n  // when relevant data has been packed into the `uint64_t` parameters densely.\n  auto HashDense(uint64_t data) -> void;\n  auto HashDense(uint64_t data0, uint64_t data1) -> void;\n\n  // A heavily optimized routine for incorporating a dynamically sized sequence\n  // of bytes into the hasher's state.\n  //\n  // This routine has carefully structured inline code paths for short byte\n  // sequences and a reasonably high bandwidth code path for longer sequences.\n  // The size of the byte sequence is always incorporated into the hasher's\n  // state along with the contents.\n  auto HashSizedBytes(llvm::ArrayRef<std::byte> bytes) -> void;\n\n  // Incorporate a dynamically sized sequence of bytes represented as an array\n  // of objects into the hasher's state.\n  template <typename T>\n    requires std::has_unique_object_representations_v<T>\n  auto HashSizedBytes(llvm::ArrayRef<T> data) -> void {\n    HashSizedBytes(llvm::ArrayRef<std::byte>(\n        reinterpret_cast<const std::byte*>(data.data()),\n        data.size() * sizeof(T)));\n  }\n\n  // An out-of-line, throughput-optimized routine for incorporating a\n  // dynamically sized sequence when the sequence size is guaranteed to be >32.\n  // The size is always incorporated into the state.\n  auto HashSizedBytesLarge(llvm::ArrayRef<std::byte> bytes) -> void;\n\n  // Utility functions to read data of various sizes efficiently into a\n  // 64-bit value. These pointers need-not be aligned, and can alias other\n  // objects. The representation of the read data in the `uint64_t` returned is\n  // not stable or guaranteed.\n  static auto Read1(const std::byte* data) -> uint64_t;\n  static auto Read2(const std::byte* data) -> uint64_t;\n  static auto Read4(const std::byte* data) -> uint64_t;\n  static auto Read8(const std::byte* data) -> uint64_t;\n\n  // Similar to the `ReadN` functions, but supports reading a range of different\n  // bytes provided by the size *without branching on the size*. The lack of\n  // branches is often key, and the code in these routines works to be efficient\n  // in extracting a *dynamic* size of bytes into the returned `uint64_t`. There\n  // may be overlap between different routines, because these routines are based\n  // on different implementation techniques that do have some overlap in the\n  // range of sizes they can support. Which routine is the most efficient for a\n  // size in the overlap isn't trivial, and so these primitives are provided\n  // as-is and should be selected based on the localized generated code and\n  // benchmarked performance.\n  static auto Read1To3(const std::byte* data, ssize_t size) -> uint64_t;\n  static auto Read4To8(const std::byte* data, ssize_t size) -> uint64_t;\n  static auto Read8To16(const std::byte* data, ssize_t size)\n      -> std::pair<uint64_t, uint64_t>;\n\n  // Reads the underlying object representation of a type into a 64-bit integer\n  // efficiently. Only supports types with unique object representation and at\n  // most 8-bytes large. This is typically used to read primitive types.\n  template <typename T>\n    requires std::has_unique_object_representations_v<T> && (sizeof(T) <= 8)\n  static auto ReadSmall(const T& value) -> uint64_t;\n\n  // The core of the hash algorithm is this mix function. The specific\n  // operations are not guaranteed to be stable but are described here for\n  // hashing authors to understand what to expect.\n  //\n  // Currently, this uses the same \"mix\" operation as in Abseil, AHash, and\n  // several other hashing algorithms. It takes two 64-bit integers, and\n  // multiplies them, capturing both the high 64-bit result and the low 64-bit\n  // result, and then XOR-ing those two halves together.\n  //\n  // A consequence of this operation is that a zero on either side will fail to\n  // incorporate any bits from the other side. Often, this is an acceptable rate\n  // of collision in practice. But it is worth being aware of and working to\n  // avoid common paths encountering this. For example, naively used this might\n  // cause different length all-zero byte strings to hash the same, essentially\n  // losing the length in the composition of the hash for a likely important\n  // case of byte sequence.\n  //\n  // Another consequence of the particular implementation is that it is useful\n  // to have a reasonable distribution of bits throughout both sides of the\n  // multiplication. However, it is not *necessary* as we do capture the\n  // complete 128-bit result. Where reasonable, the caller should XOR random\n  // data into operands before calling `Mix` to try and increase the\n  // distribution of bits feeding the multiply.\n  static auto Mix(uint64_t lhs, uint64_t rhs) -> uint64_t;\n\n  // An alternative to `Mix` that is significantly weaker but also lower\n  // latency. It should not be used when the input `uint64_t` is densely packed\n  // with data, but is a good option for hashing a single integer or pointer\n  // where the full 64-bits are sparsely populated and especially the high bits\n  // are often invariant between interestingly different values.\n  //\n  // This uses just the low 64-bit result of a multiply. It ensures the operand\n  // is good at diffusing bits, but inherently the high bits of the input will\n  // be (significantly) less often represented in the output. It also does some\n  // reversal to ensure the *low* bits of the result are the most useful ones.\n  static auto WeakMix(uint64_t value) -> uint64_t;\n\n  // We have a 64-byte random data pool designed to fit on a single cache line.\n  // This routine allows sampling it at byte indices, which allows getting 64 -\n  // 8 different random 64-bit results. The offset must be in the range [0, 56).\n  static auto SampleRandomData(ssize_t offset) -> uint64_t {\n    CARBON_DCHECK(offset + sizeof(uint64_t) < sizeof(StaticRandomData));\n    uint64_t data;\n    memcpy(&data,\n           reinterpret_cast<const unsigned char*>(&StaticRandomData) + offset,\n           sizeof(data));\n    return data;\n  }\n\n  // As above, but for small offsets, we can use aligned loads, which are\n  // faster. The offset must be in the range [0, 8).\n  static auto SampleAlignedRandomData(ssize_t offset) -> uint64_t {\n    CARBON_DCHECK(static_cast<size_t>(offset) <\n                  sizeof(StaticRandomData) / sizeof(uint64_t));\n    return StaticRandomData[offset];\n  }\n\n  // Random data taken from the hexadecimal digits of Pi's fractional component,\n  // written in lexical order for convenience of reading. The resulting\n  // byte-stream will be different due to little-endian integers. These can be\n  // used directly for convenience rather than calling `SampleRandomData`, but\n  // be aware that this is the underlying pool. The goal is to reuse the same\n  // single cache-line of constant data.\n  //\n  // The initializers here can be generated with the following shell script,\n  // which will generate 8 64-bit values and one more digit. The `bc` command's\n  // decimal based scaling means that without getting at least some extra hex\n  // digits rendered there will be rounding that we don't want so the script\n  // below goes on to produce one more hex digit ensuring the 8 initializers\n  // aren't rounded in any way. Using a higher scale won't cause the 8\n  // initializers here to change further.\n  //\n  // ```sh\n  // echo 'obase=16; scale=155; 4*a(1)' | env BC_LINE_LENGTH=500 bc -l \\\n  //  | cut -c 3- | tr '[:upper:]' '[:lower:]' \\\n  //  | sed -e \"s/.\\{4\\}/&'/g\" \\\n  //  | sed -e \"s/\\(.\\{4\\}'.\\{4\\}'.\\{4\\}'.\\{4\\}\\)'/0x\\1,\\n/g\"\n  // ```\n  alignas(64) static constexpr std::array<uint64_t, 8> StaticRandomData = {\n      0x243f'6a88'85a3'08d3, 0x1319'8a2e'0370'7344, 0xa409'3822'299f'31d0,\n      0x082e'fa98'ec4e'6c89, 0x4528'21e6'38d0'1377, 0xbe54'66cf'34e9'0c6c,\n      0xc0ac'29b7'c97c'50dd, 0x3f84'd5b5'b547'0917,\n  };\n\n  // We need a multiplicative hashing constant for both 64-bit multiplicative\n  // hashing fast paths and some other 128-bit folded multiplies. We use an\n  // empirically better constant compared to Knuth's, Rust's FxHash, and others\n  // we've tried. It was found by a search of uniformly distributed odd numbers\n  // and examining them for desirable properties when used as a multiplicative\n  // hash, however our search seems largely to have been lucky rather than\n  // having a highly effective set of criteria. We evaluated this constant by\n  // integrating this hash function with a hashtable and looking at the\n  // collision rates of several different but very fundamental patterns of keys:\n  // integers counting from 0, pointers allocated on the heap, and strings with\n  // character and size distributions matching C-style ASCII identifiers.\n  // Different constants found with this search worked better or less well, but\n  // fairly consistently across the different types of keys. At the end, far and\n  // away the best behaved constant we found was one of the first ones in the\n  // search and is what we use here.\n  //\n  // For reference, some other constants include one derived by diving 2^64 by\n  // Phi: 0x9e37'79b9'7f4a'7c15U -- see these sites for details:\n  // https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/\n  // https://book.huihoo.com/data-structures-and-algorithms-with-object-oriented-design-patterns-in-c++/html/page214.html\n  //\n  // Another very good constant derived by minimizing repeating bit patterns is\n  // 0xdcb2'2ca6'8cb1'34edU and its bit-reversed form. However, this constant\n  // has observed frequent issues at roughly 4k pointer keys, connected to a\n  // common hashtable seed also being a pointer. These issues appear to occur\n  // both more often and have a larger impact relative to the number of keys\n  // than the rare cases where some combinations of pointer seeds and pointer\n  // keys create minor quality issues with the constant we use.\n  static constexpr uint64_t MulConstant = 0x79d5'f9e0'de1e'8cf5U;\n\n private:\n  uint64_t buffer;\n};\n\n// A dedicated namespace for `CarbonHashValue` overloads that are not found by\n// ADL with their associated types. For example, primitive type overloads or\n// overloads for types in LLVM's libraries.\n//\n// Note that these are internal implementation details and **not** part of the\n// public API. They should not be used directly by client code.\nnamespace InternalHashDispatch {\n\ntemplate <typename T>\ninline auto CarbonHashValue(llvm::ArrayRef<T> values, uint64_t seed)\n    -> HashCode {\n  Hasher hasher(seed);\n  hasher.HashArray(values);\n  return static_cast<HashCode>(hasher);\n}\n\ninline auto CarbonHashValue(llvm::ArrayRef<std::byte> bytes, uint64_t seed)\n    -> HashCode {\n  Hasher hasher(seed);\n  hasher.HashSizedBytes(bytes);\n  return static_cast<HashCode>(hasher);\n}\n\n// Hashing implementation for `llvm::StringRef`. We forward all the other\n// string-like types that support heterogeneous lookup to this one.\ninline auto CarbonHashValue(llvm::StringRef value, uint64_t seed) -> HashCode {\n  return CarbonHashValue(\n      llvm::ArrayRef(reinterpret_cast<const std::byte*>(value.data()),\n                     value.size()),\n      seed);\n}\n\ninline auto CarbonHashValue(std::string_view value, uint64_t seed) -> HashCode {\n  return CarbonHashValue(llvm::StringRef(value.data(), value.size()), seed);\n}\n\ninline auto CarbonHashValue(const std::string& value, uint64_t seed)\n    -> HashCode {\n  return CarbonHashValue(llvm::StringRef(value.data(), value.size()), seed);\n}\n\ntemplate <unsigned Length>\ninline auto CarbonHashValue(const llvm::SmallString<Length>& value,\n                            uint64_t seed) -> HashCode {\n  return CarbonHashValue(llvm::StringRef(value.data(), value.size()), seed);\n}\n\n// Support types that are array-like by building an `llvm::ArrayRef` out of\n// them. We can't do this by accepting any type convertible to an `ArrayRef`\n// because that type supports building a synthetic array out of any single\n// element.\ntemplate <typename T>\ninline auto CarbonHashValue(const std::vector<T>& arg, uint64_t seed)\n    -> HashCode {\n  return CarbonHashValue(llvm::ArrayRef(arg), seed);\n}\ntemplate <typename T>\ninline auto CarbonHashValue(const llvm::SmallVectorImpl<T>& arg, uint64_t seed)\n    -> HashCode {\n  return CarbonHashValue(llvm::ArrayRef(arg), seed);\n}\ntemplate <typename T, size_t N>\ninline auto CarbonHashValue(const std::array<T, N>& arg, uint64_t seed)\n    -> HashCode {\n  return CarbonHashValue(llvm::ArrayRef(arg), seed);\n}\ntemplate <typename T, size_t N>\ninline auto CarbonHashValue(const T (&arg)[N], uint64_t seed) -> HashCode {\n  return CarbonHashValue(llvm::ArrayRef(arg), seed);\n}\n\ninline auto CarbonHashValue(llvm::APInt value, uint64_t seed) -> HashCode {\n  Hasher hasher(seed);\n  if (LLVM_LIKELY(value.isSingleWord())) {\n    hasher.Hash(value.getBitWidth(), value.getZExtValue());\n  } else {\n    hasher.HashRaw(value.getBitWidth());\n    hasher.HashSizedBytes(\n        llvm::ArrayRef(value.getRawData(), value.getNumWords()));\n  }\n  return static_cast<HashCode>(hasher);\n}\n\ninline auto CarbonHashValue(llvm::APFloat value, uint64_t seed) -> HashCode {\n  Hasher hasher(seed);\n  // Hashing floating point numbers is complex and depends on the specific\n  // internal semantics of `APFloat`, so delegate to the LLVM hashing framework\n  // here. We re-hash the result to mix in our seed. All of this is a bit\n  // inefficient, and we can revisit this to provide a dedicated implementation\n  // if it becomes a bottleneck.\n  using llvm::hash_value;\n  hasher.HashRaw(hash_value(value));\n  return static_cast<HashCode>(hasher);\n}\n\ntemplate <typename... Ts>\ninline auto CarbonHashValue(const std::tuple<Ts...>& value, uint64_t seed)\n    -> HashCode {\n  Hasher hasher(seed);\n  std::apply([&](const auto&... args) { hasher.Hash(args...); }, value);\n  return static_cast<HashCode>(hasher);\n}\n\ntemplate <typename T, typename U>\ninline auto CarbonHashValue(const std::pair<T, U>& value, uint64_t seed)\n    -> HashCode {\n  Hasher hasher(seed);\n  hasher.Hash(value.first, value.second);\n  return static_cast<HashCode>(hasher);\n}\n\n// Implementation detail predicate to detect if there is a `CarbonHashValue`\n// overload available for a particular type, either in this namespace or found\n// via ADL. Note that this should not be moved above any overloads.\ntemplate <typename T>\nconcept HasCarbonHashValue = requires(const T& value, uint64_t seed) {\n  { CarbonHashValue(value, seed) } -> std::same_as<HashCode>;\n};\n\n// C++ guarantees this is true for the unsigned variants, but we require it for\n// signed variants and pointers.\nstatic_assert(std::has_unique_object_representations_v<int8_t>);\nstatic_assert(std::has_unique_object_representations_v<int16_t>);\nstatic_assert(std::has_unique_object_representations_v<int32_t>);\nstatic_assert(std::has_unique_object_representations_v<int64_t>);\nstatic_assert(std::has_unique_object_representations_v<void*>);\n\n// Overloaded function to provide mappings or conversions required to types that\n// should be hashed as plain data but where can't directly examine the storage.\n//\n// For example, C++ uses `std::nullptr_t` but unfortunately doesn't make it have\n// a unique object representation. To address that, we need a function that\n// converts `nullptr` back into a `void*` that will have a unique object\n// representation. And this needs to be done by-value as we need to build a\n// temporary object to return, which requires a separate overload rather than\n// just using a type function that could be used in parallel in the predicate\n// below. Instead, we build the predicate independently of the mapping overload,\n// but together they should produce the correct result.\ntemplate <typename T>\ninline auto MapToRawDataType(const T& value) -> const T& {\n  // This overload should never be selected for `std::nullptr_t`, so\n  // static_assert to get some better compiler error messages.\n  static_assert(!std::same_as<T, std::nullptr_t>);\n  // NOLINTNEXTLINE(bugprone-return-const-ref-from-parameter)\n  return value;\n}\ninline auto MapToRawDataType(std::nullptr_t /*value*/) -> const void* {\n  return nullptr;\n}\n\n// Implementation detail predicate to detect if we can hash as a raw data type.\n// When used, it should be combined with our mapping function `MapToRawDataType`\n// to handle any necessary edge cases that don't directly work.\ntemplate <typename T>\nconcept CanHashAsRawDataType = std::same_as<T, std::nullptr_t> ||\n                               std::has_unique_object_representations_v<T>;\n\n// Implementation of the unqualified dispatch to any provided `CarbonHashValue`\n// overloads, either here, or via ADL. Note that similar to\n// `HasCarbonHashValue`, this must not be moved above any of those overloads.\ntemplate <typename T>\ninline auto DispatchImpl(const T& value, uint64_t seed) -> HashCode {\n  // If we have an explicit overload for `CarbonHashValue`, call it. This may be\n  // provided above or via ADL, and is preferred as it represents an explicit\n  // request for how the type is hashed.\n  if constexpr (HasCarbonHashValue<T>) {\n    return CarbonHashValue(value, seed);\n  } else if constexpr (CanHashAsRawDataType<T>) {\n    // There was no explicit overload to call, but the type allows us to hash it\n    // as raw data, do so.\n    Hasher hasher(seed);\n    hasher.HashRaw(MapToRawDataType(value));\n    return static_cast<HashCode>(hasher);\n  } else {\n    // We can only synthesize hashing for types that are hashable as raw data.\n    // This type isn't so fail a static assert due to the lack of an overload.\n    // We use the concept here to try and get the best diagnostics we can about\n    // candidates.\n    static_assert(HasCarbonHashValue<T>,\n                  \"Attempted to hash a type which does not have a \"\n                  \"`CarbonHashValue` overload.\");\n  }\n}\n\n}  // namespace InternalHashDispatch\n\ntemplate <typename T>\ninline auto HashValue(const T& value, uint64_t seed) -> HashCode {\n  return InternalHashDispatch::DispatchImpl(value, seed);\n}\n\ntemplate <typename T>\ninline auto HashValue(const T& value) -> HashCode {\n  // When a seed isn't provided, use the last 64-bit chunk of random data. Other\n  // chunks (especially the first) are more often XOR-ed with the seed and risk\n  // cancelling each other out and feeding a zero to a `Mix` call in a way that\n  // sharply increasing collisions.\n  return HashValue(value, Hasher::StaticRandomData[7]);\n}\n\nconstexpr auto HashCode::ExtractIndex() -> ssize_t { return value_; }\n\ntemplate <int N>\nconstexpr auto HashCode::ExtractIndexAndTag() -> std::pair<ssize_t, uint32_t> {\n  static_assert(N >= 1);\n  static_assert(N < 32);\n  return {static_cast<ssize_t>(value_ >> N),\n          static_cast<uint32_t>(value_ & ((1U << N) - 1))};\n}\n\n// Building with `-DCARBON_MCA_MARKERS` will enable `llvm-mca` annotations in\n// the source code. These can interfere with optimization, but allows analyzing\n// the generated `.s` file with the `llvm-mca` tool. Documentation for these\n// markers is here:\n// https://llvm.org/docs/CommandGuide/llvm-mca.html#using-markers-to-analyze-specific-code-blocks\n#if CARBON_MCA_MARKERS\n#define CARBON_MCA_BEGIN(NAME) \\\n  __asm volatile(\"# LLVM-MCA-BEGIN \" NAME \"\" ::: \"memory\");\n#define CARBON_MCA_END(NAME) \\\n  __asm volatile(\"# LLVM-MCA-END \" NAME \"\" ::: \"memory\");\n#else\n#define CARBON_MCA_BEGIN(NAME)\n#define CARBON_MCA_END(NAME)\n#endif\n\ninline auto Hasher::Read1(const std::byte* data) -> uint64_t {\n  uint8_t result;\n  std::memcpy(&result, data, sizeof(result));\n  return result;\n}\n\ninline auto Hasher::Read2(const std::byte* data) -> uint64_t {\n  uint16_t result;\n  std::memcpy(&result, data, sizeof(result));\n  return result;\n}\n\ninline auto Hasher::Read4(const std::byte* data) -> uint64_t {\n  uint32_t result;\n  std::memcpy(&result, data, sizeof(result));\n  return result;\n}\n\ninline auto Hasher::Read8(const std::byte* data) -> uint64_t {\n  uint64_t result;\n  std::memcpy(&result, data, sizeof(result));\n  return result;\n}\n\ninline auto Hasher::Read1To3(const std::byte* data, ssize_t size) -> uint64_t {\n  // Use carefully crafted indexing to avoid branches on the exact size while\n  // reading.\n  uint64_t byte0 = static_cast<uint8_t>(data[0]);\n  uint64_t byte1 = static_cast<uint8_t>(data[size - 1]);\n  uint64_t byte2 = static_cast<uint8_t>(data[size >> 1]);\n  return (byte0 << 8) | (byte1 << 16) | byte2;\n}\n\ninline auto Hasher::Read4To8(const std::byte* data, ssize_t size) -> uint64_t {\n  uint32_t low;\n  std::memcpy(&low, data, sizeof(low));\n  uint32_t high;\n  std::memcpy(&high, data + size - sizeof(high), sizeof(high));\n  return (static_cast<uint64_t>(low) << 32) | high;\n}\n\ninline auto Hasher::Read8To16(const std::byte* data, ssize_t size)\n    -> std::pair<uint64_t, uint64_t> {\n  uint64_t low;\n  std::memcpy(&low, data, sizeof(low));\n  uint64_t high;\n  std::memcpy(&high, data + size - sizeof(high), sizeof(high));\n  return {low, high};\n}\n\ninline auto Hasher::Mix(uint64_t lhs, uint64_t rhs) -> uint64_t {\n  // Use the C23 extended integer support that Clang provides as a general\n  // language extension.\n  using U128 = unsigned _BitInt(128);\n  U128 result = static_cast<U128>(lhs) * static_cast<U128>(rhs);\n  return static_cast<uint64_t>(result) ^ static_cast<uint64_t>(result >> 64);\n}\n\ninline auto Hasher::WeakMix(uint64_t value) -> uint64_t {\n  value *= MulConstant;\n#ifdef __ARM_ACLE\n  // Arm has a fast bit-reversal that gives us the optimal distribution.\n  value = __rbitll(value);\n#else\n  // Otherwise, assume an optimized BSWAP such as x86's. That's close enough.\n  value = __builtin_bswap64(value);\n#endif\n  return value;\n}\n\ninline auto Hasher::HashDense(uint64_t data) -> void {\n  // When hashing exactly one 64-bit entity use the Phi-derived constant as this\n  // is just multiplicative hashing. The initial buffer is mixed on input to\n  // pipeline with materializing the constant.\n  buffer = Mix(data ^ buffer, MulConstant);\n}\n\ninline auto Hasher::HashDense(uint64_t data0, uint64_t data1) -> void {\n  // When hashing two chunks of data at the same time, we XOR it with random\n  // data to avoid common inputs from having especially bad multiplicative\n  // effects. We also XOR in the starting buffer as seed or to chain. Note that\n  // we don't use *consecutive* random data 64-bit values to avoid a common\n  // compiler \"optimization\" of loading both 64-bit chunks into a 128-bit vector\n  // and doing the XOR in the vector unit. The latency of extracting the data\n  // afterward eclipses any benefit. Callers will routinely have two consecutive\n  // data values here, but using non-consecutive keys avoids any vectorization\n  // being tempting.\n  //\n  // XOR-ing both the incoming state and a random word over the second data is\n  // done to pipeline with materializing the constants and is observed to have\n  // better performance than XOR-ing after the mix.\n  //\n  // This roughly matches the mix pattern used in the larger mixing routines\n  // from Abseil, which is a more minimal form than used in other algorithms\n  // such as AHash and seems adequate for latency-optimized use cases.\n  buffer =\n      Mix(data0 ^ StaticRandomData[1], data1 ^ StaticRandomData[3] ^ buffer);\n}\n\ntemplate <typename T>\n  requires std::has_unique_object_representations_v<T> && (sizeof(T) <= 8)\ninline auto Hasher::ReadSmall(const T& value) -> uint64_t {\n  const auto* storage = reinterpret_cast<const std::byte*>(&value);\n  if constexpr (sizeof(T) == 1) {\n    return Read1(storage);\n  } else if constexpr (sizeof(T) == 2) {\n    return Read2(storage);\n  } else if constexpr (sizeof(T) == 3) {\n    return Read2(storage) | (Read1(&storage[2]) << 16);\n  } else if constexpr (sizeof(T) == 4) {\n    return Read4(storage);\n  } else if constexpr (sizeof(T) == 5) {\n    return Read4(storage) | (Read1(&storage[4]) << 32);\n  } else if constexpr (sizeof(T) == 6 || sizeof(T) == 7) {\n    // Use overlapping 4-byte reads for 6 and 7 bytes.\n    return Read4(storage) | (Read4(&storage[sizeof(T) - 4]) << 32);\n  } else if constexpr (sizeof(T) == 8) {\n    return Read8(storage);\n  } else {\n    static_assert(sizeof(T) <= 8);\n  }\n}\n\ntemplate <typename... Ts>\ninline auto Hasher::Hash(const Ts&... values) -> void {\n  if constexpr (sizeof...(Ts) == 0) {\n    buffer ^= StaticRandomData[0];\n    return;\n  }\n\n  using InternalHashDispatch::CanHashAsRawDataType;\n  using InternalHashDispatch::HasCarbonHashValue;\n  using InternalHashDispatch::MapToRawDataType;\n\n  // Special-case a single element tuple that we will hash as raw data.\n  if constexpr (sizeof...(Ts) == 1 && (... && (!HasCarbonHashValue<Ts> &&\n                                               CanHashAsRawDataType<Ts>))) {\n    HashRaw(MapToRawDataType(values)...);\n    return;\n  }\n\n  // Map each value into a uint64_t, either by hashing it using any custom hash\n  // function required, reading its data into a 64-bit value, or if large\n  // hashing it as raw data and using that hash code as the 64-bit data. This\n  // mirrors the logic in `InternalHashDispatch::DispatchImpl`, but minimizes\n  // early hashing of anything small we can just read as data. While this may be\n  // a little bit wasteful in some cases, collapsing down to a flat array of\n  // 64-bit integers is more efficient to hash.\n  auto map_value = []<typename T>(const T& value) -> uint64_t {\n    if constexpr (HasCarbonHashValue<T>) {\n      // Use the top-level `HashValue` to re-dispatch to the custom\n      // implementation with a fixed seed.\n      return static_cast<uint64_t>(HashValue(value));\n    } else if constexpr (CanHashAsRawDataType<T>) {\n      auto raw_value = MapToRawDataType(value);\n      if constexpr (sizeof(raw_value) <= 8) {\n        return ReadSmall(raw_value);\n      } else {\n        // Use the top-level `HashValue` to pick up a good fixed seed and hash\n        // this large object as raw data.\n        return static_cast<uint64_t>(HashValue(raw_value));\n      }\n    } else {\n      // We can only synthesize hashing for types that are hashable as raw data.\n      // This type isn't so fail a static assert due to the lack of an overload.\n      // We use the concept here to try and get the best diagnostics we can\n      // about candidates.\n      static_assert(HasCarbonHashValue<T>,\n                    \"Attempted to hash a type which does not have a \"\n                    \"`CarbonHashValue` overload.\");\n    }\n  };\n  const uint64_t data[] = {map_value(values)...};\n  if constexpr (sizeof...(Ts) == 2) {\n    HashDense(data[0], data[1]);\n    return;\n  }\n\n  HashRaw(data);\n}\n\ntemplate <typename T>\ninline auto Hasher::HashArray(llvm::ArrayRef<T> values) -> void {\n  using InternalHashDispatch::CanHashAsRawDataType;\n  using InternalHashDispatch::HasCarbonHashValue;\n\n  // This logic similarly mirrors `InternalHashDispatch::DispatchImpl`, but is\n  // specialized here to allow us to efficiently process the array when it\n  // *doesn't* require recursive hashing.\n  if constexpr (HasCarbonHashValue<T>) {\n    // Use a trivial loop to give consistent behavior for arrays requiring\n    // recursive hashing. This isn't terribly efficient, but if clients care\n    // they should specialize the entire hashing operation. For simple, tiny\n    // cases, this avoids an awkward functionality cliff.\n    for (const T& value : values) {\n      HashDense(static_cast<uint64_t>(HashValue(value)));\n    }\n    HashRaw(values.size());\n  } else if constexpr (std::has_unique_object_representations_v<T>) {\n    // This code is a narrow special case for `CanHashAsRawDataType` that we can\n    // further hash the underlying storage directly. We check that it is a\n    // subset.\n    static_assert(CanHashAsRawDataType<T>);\n    HashSizedBytes(values);\n  } else {\n    // We can only synthesize hashing for types that are hashable as raw data.\n    // This type isn't so fail a static assert due to the lack of an overload.\n    // We use the concept here to try and get the best diagnostics we can\n    // about candidates.\n    static_assert(HasCarbonHashValue<T>,\n                  \"Attempted to hash a type which does not have a \"\n                  \"`CarbonHashValue` overload.\");\n  }\n}\n\ntemplate <typename T>\n  requires std::has_unique_object_representations_v<T>\ninline auto Hasher::HashRaw(const T& value) -> void {\n  if constexpr (sizeof(T) <= 8) {\n    // For types size 8-bytes and smaller directly being hashed (as opposed to\n    // 8-bytes potentially bit-packed with data), we rarely expect the incoming\n    // data to fully and densely populate all 8 bytes. For these cases we have a\n    // `WeakMix` routine that is lower latency but lower quality.\n    CARBON_MCA_BEGIN(\"fixed-8b\");\n    buffer = WeakMix(buffer ^ ReadSmall(value));\n    CARBON_MCA_END(\"fixed-8b\");\n    return;\n  }\n\n  const auto* data_ptr = reinterpret_cast<const std::byte*>(&value);\n  if constexpr (8 < sizeof(T) && sizeof(T) <= 16) {\n    CARBON_MCA_BEGIN(\"fixed-16b\");\n    auto values = Read8To16(data_ptr, sizeof(T));\n    HashDense(values.first, values.second);\n    CARBON_MCA_END(\"fixed-16b\");\n    return;\n  }\n\n  if constexpr (16 < sizeof(T) && sizeof(T) <= 32) {\n    CARBON_MCA_BEGIN(\"fixed-32b\");\n    // Essentially the same technique used for dynamically sized byte sequences\n    // of this size, but we start with a fixed XOR of random data.\n    buffer ^= StaticRandomData[0];\n    uint64_t m0 = Mix(Read8(data_ptr) ^ StaticRandomData[1],\n                      Read8(data_ptr + 8) ^ buffer);\n    const std::byte* tail_16b_ptr = data_ptr + (sizeof(T) - 16);\n    uint64_t m1 = Mix(Read8(tail_16b_ptr) ^ StaticRandomData[3],\n                      Read8(tail_16b_ptr + 8) ^ buffer);\n    buffer = m0 ^ m1;\n    CARBON_MCA_END(\"fixed-32b\");\n    return;\n  }\n\n  // Hashing the size isn't relevant here, but is harmless, so fall back to a\n  // common code path.\n  HashSizedBytesLarge(llvm::ArrayRef<std::byte>(data_ptr, sizeof(T)));\n}\n\ninline auto Hasher::HashSizedBytes(llvm::ArrayRef<std::byte> bytes) -> void {\n  const std::byte* data_ptr = bytes.data();\n  const ssize_t size = bytes.size();\n\n  // First handle short sequences under 8 bytes. We distribute the branches a\n  // bit for short strings.\n  if (size <= 8) {\n    if (size >= 4) {\n      CARBON_MCA_BEGIN(\"dynamic-8b\");\n      uint64_t data = Read4To8(data_ptr, size);\n      // We optimize for latency on short strings by hashing both the data and\n      // size in a single multiply here, using the small nature of size to\n      // sample a specific sequence of bytes with well distributed bits into one\n      // side of the multiply. This results in a *statistically* weak hash\n      // function, but one with very low latency.\n      //\n      // Note that we don't drop to the `WeakMix` routine here because we want\n      // to use sampled random data to encode the size, which may not be as\n      // effective without the full 128-bit folded result.\n      buffer = Mix(data ^ buffer, SampleAlignedRandomData(size - 1));\n      CARBON_MCA_END(\"dynamic-8b\");\n      return;\n    }\n\n    // When we only have 0-3 bytes of string, we can avoid the cost of `Mix`.\n    // Instead, for empty strings we can just XOR some of our data against the\n    // existing buffer. For 1-3 byte lengths we do 3 one-byte reads adjusted to\n    // always read in-bounds without branching. Then we OR the size into the 4th\n    // byte and use `WeakMix`.\n    CARBON_MCA_BEGIN(\"dynamic-4b\");\n    if (size == 0) {\n      buffer ^= StaticRandomData[0];\n    } else {\n      uint64_t data = Read1To3(data_ptr, size) | size << 24;\n      buffer = WeakMix(data);\n    }\n    CARBON_MCA_END(\"dynamic-4b\");\n    return;\n  }\n\n  if (size <= 16) {\n    CARBON_MCA_BEGIN(\"dynamic-16b\");\n    // Similar to the above, we optimize primarily for latency here and spread\n    // the incoming data across both ends of the multiply. Note that this does\n    // have a drawback -- any time one half of the mix function becomes zero it\n    // will fail to incorporate any bits from the other half. However, there is\n    // exactly 1 in 2^64 values for each side that achieve this, and only when\n    // the size is exactly 16 -- for smaller sizes there is an overlapping byte\n    // that makes this impossible unless the seed is *also* incredibly unlucky.\n    //\n    // Because this hash function makes no attempt to defend against hash\n    // flooding, we accept this risk in order to keep the latency low. If this\n    // becomes a non-flooding problem, we can restrict the size to <16 and send\n    // the 16-byte case down the next tier of cost.\n    uint64_t size_hash = SampleRandomData(size);\n    auto data = Read8To16(data_ptr, size);\n    buffer = Mix(data.first ^ size_hash, data.second ^ buffer);\n    CARBON_MCA_END(\"dynamic-16b\");\n    return;\n  }\n\n  if (size <= 32) {\n    CARBON_MCA_BEGIN(\"dynamic-32b\");\n    // Do two mixes of overlapping 16-byte ranges in parallel to minimize\n    // latency. We also incorporate the size by sampling random data into the\n    // seed before both.\n    buffer ^= SampleRandomData(size);\n    uint64_t m0 = Mix(Read8(data_ptr) ^ StaticRandomData[1],\n                      Read8(data_ptr + 8) ^ buffer);\n\n    const std::byte* tail_16b_ptr = data_ptr + (size - 16);\n    uint64_t m1 = Mix(Read8(tail_16b_ptr) ^ StaticRandomData[3],\n                      Read8(tail_16b_ptr + 8) ^ buffer);\n    // Just an XOR mix at the end is quite weak here, but we prefer that for\n    // latency over a more robust approach. Doing another mix with the size (the\n    // way longer string hashing does) increases the latency on x86-64\n    // significantly (approx. 20%).\n    buffer = m0 ^ m1;\n    CARBON_MCA_END(\"dynamic-32b\");\n    return;\n  }\n\n  HashSizedBytesLarge(bytes);\n}\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_HASHING_H_\n"
  },
  {
    "path": "common/hashing_benchmark.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <benchmark/benchmark.h>\n\n#include <algorithm>\n#include <array>\n#include <cstddef>\n#include <numbers>\n\n#include \"absl/hash/hash.h\"\n#include \"absl/random/random.h\"\n#include \"common/hashing.h\"\n#include \"llvm/ADT/Hashing.h\"\n\nnamespace Carbon {\nnamespace {\n\n// We want the benchmark working set to fit in the L1 cache where possible so\n// that the benchmark focuses on the CPU-execution costs and not memory latency.\n// For most CPUs we're going to care about, 16k will fit easily, and 32k will\n// probably fit. But we also need to include sizes for string benchmarks. This\n// targets 8k of entropy with each object up to 8k of size for a total of 16k.\nconstexpr int EntropySize = 8 << 10;\nconstexpr int EntropyObjSize = 8 << 10;\n\n// An array of random entropy with `EntropySize` bytes plus 8k. The goal is that\n// clients can read `EntropySize` objects of up to 8k size out of this pool by\n// starting at different byte offsets.\nstatic const llvm::ArrayRef<std::byte> entropy_bytes =\n    []() -> llvm::ArrayRef<std::byte> {\n  static llvm::SmallVector<std::byte> bytes;\n  // Pad out the entropy for up to 1kb objects.\n  bytes.resize(EntropySize + EntropyObjSize);\n  absl::BitGen gen;\n  for (std::byte& b : bytes) {\n    b = static_cast<std::byte>(absl::Uniform<uint8_t>(gen));\n  }\n  return bytes;\n}();\n\n// Based on 16k of entropy above and an L1 cache size often up to 32k, keep each\n// array of sizes small at 8k or 1k 8-byte sizes.\nconstexpr int NumSizes = 1 << 10;\n\n// Selects an array of `NumSizes` sizes, witch each one in the range [0,\n// MaxSize). The sizes will be in a random order, but the sum of sizes will\n// always be the same.\ntemplate <size_t MaxSize>\nstatic const std::array<size_t, NumSizes> rand_sizes = []() {\n  std::array<size_t, NumSizes> sizes;\n  // Build an array with a deterministic set of sizes in the\n  // range [0, MaxSize), using the golden ratio to select well distributed\n  // points in that range. See https://www.youtube.com/watch?v=lOIP_Z_-0Hs for\n  // an example of why this is an effective strategy for selecting sizes in the\n  // range.\n  static_assert(NumSizes > 128);\n  constexpr size_t Scale = std::max<size_t>(1, MaxSize / std::numbers::phi);\n  for (auto [i, size] : llvm::enumerate(sizes)) {\n    size = (i * Scale) % MaxSize;\n  }\n  // Shuffle the sizes randomly so that there isn't any pattern of sizes\n  // encountered and we get relatively realistic branch prediction behavior\n  // when branching on the size. We use this approach rather than random\n  // sizes to ensure we always have the same total size of data processed.\n  std::shuffle(sizes.begin(), sizes.end(), absl::BitGen());\n  return sizes;\n}();\n\n// A small helper class to synthesize random values out of our entropy pool.\n// This is done in a way that depends on an arbitrary input (`x`) to allow us to\n// create a benchmark that measures a *dependent* chain of hashes of these\n// values.\n//\n// `T` needs to be default constructable and reasonable to synthesize an\n// instance by copying random bytes into its underlying storage.\n//\n// This helper class also accumulates the number of bytes of data generated in\n// order to let us compute throughput measurements as well as latency\n// measurements.\n//\n// This helper class has the same API as the `RandStrings` helpers below so that\n// they can all be used as type parameters to a common benchmark routine below.\ntemplate <typename T>\nstruct RandValues {\n  size_t bytes = 0;\n\n  // Get a random value. We don't need to iterate through sizes so `i` is\n  // ignored, but we use `x` to select our entropy ensuring a dependency on `x`\n  // for the benchmark.\n  auto Get(ssize_t /*i*/, uint64_t x) -> T {\n    static_assert(sizeof(T) <= EntropyObjSize);\n    bytes += sizeof(T);\n    T result;\n    // Clang Tidy complains about this `memcpy` despite this being the canonical\n    // formulation. Removing the type `T` would also remove warnings for getting\n    // the size incorrect.\n    // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)\n    memcpy(&result, &entropy_bytes[x % EntropySize], sizeof(T));\n    return result;\n  }\n};\n\n// A specialization to help with building pairs of values.\ntemplate <typename T, typename U>\nstruct RandValues<std::pair<T, U>> {\n  size_t bytes = 0;\n\n  auto Get(ssize_t /*i*/, uint64_t x) -> std::pair<T, U> {\n    static_assert(sizeof(std::pair<T, U>) <= EntropyObjSize);\n    bytes += sizeof(std::pair<T, U>);\n    T result0;\n    U result1;\n    // Clang Tidy complains about this `memcpy` despite this being the canonical\n    // formulation. Removing the type `T` would also remove warnings for getting\n    // the size incorrect.\n    // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)\n    memcpy(&result0, &entropy_bytes[x % EntropySize], sizeof(T));\n    // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)\n    memcpy(&result1, &entropy_bytes[x % EntropySize] + sizeof(T), sizeof(U));\n    return {result0, result1};\n  }\n};\n\n// A helper class similar to `RandValues`, but for building strings rather than\n// values. The string content is pulled from the entropy pool. The size can be\n// random from [0, MaxSize], or it can be fixed at `MaxSize`. But the `MaxSize`\n// cannot be larger than a single byte sequence pulled from the entropy pool\n// (`EntropyObjSize`).\ntemplate <bool RandSize, size_t MaxSize>\nstruct RandStrings {\n  size_t bytes = 0;\n\n  // Get a random string. If the sizes are random, we use `i` to select each\n  // size and require it to be in the range [0, NumSizes). Otherwise `i` is\n  // ignored. We always use `x` to select the entropy and establish a dependency\n  // on the input.\n  auto Get(ssize_t i, uint64_t x) -> llvm::StringRef {\n    static_assert(MaxSize <= EntropyObjSize);\n    size_t s = MaxSize;\n    if constexpr (RandSize) {\n      // When using random sizes, we leverage `i` which is guaranteed to range\n      // from [0, NumSizes).\n      s = rand_sizes<MaxSize>[i];\n    } else {\n      // Prevent `s` from being constant folded when we directly use `MaxSize`.\n      benchmark::DoNotOptimize(s);\n    }\n    bytes += s;\n    return llvm::StringRef(\n        reinterpret_cast<const char*>(&entropy_bytes[x % EntropySize]), s);\n  }\n};\n\nstruct HashBenchBase {\n  uint64_t seed;\n\n  HashBenchBase() {\n    // The real-world use case we care about is in a hash table where we'll mix\n    // in some seed state, likely some ASLR address. To simulate this for\n    // benchmarking, compute a seed from the address of a stack local variable.\n    volatile char key;\n    key = 42;\n    // Rinse this through a volatile variable as well so returning it isn't\n    // flagged. The whole point is to escape the address of something on the\n    // stack.\n    volatile auto key_addr = reinterpret_cast<uint64_t>(&key);\n    seed = key_addr;\n  }\n};\n\nstruct CarbonHashBench : HashBenchBase {\n  template <typename T>\n  auto operator()(const T& value) -> uint64_t {\n    return static_cast<uint64_t>(HashValue(value, seed));\n  }\n};\n\nstruct AbseilHashBench : HashBenchBase {\n  template <typename T>\n  auto operator()(const T& value) -> uint64_t {\n    // Manually seed this with an after-the-fact XOR as there isn't a seeded\n    // version. This matches what Abseil's hash tables do as well.\n    return absl::HashOf(value) ^ seed;\n  }\n};\n\nstruct LLVMHashBench : HashBenchBase {\n  template <typename T>\n  auto operator()(const T& value) -> uint64_t {\n    // Manually seed this with an after-the-fact XOR as there isn't a seeded\n    // version.\n    return llvm::hash_value(value) ^ seed;\n  }\n};\n\ntemplate <typename Values, typename Hasher>\nauto BM_LatencyHash(benchmark::State& state) -> void {\n  uint64_t x = 13;\n  Values v;\n  Hasher h;\n  // We run the benchmark in `NumSizes` batches so that when needed we always\n  // process each of the sizes and we don't randomly end up with a skewed set of\n  // sizes.\n  while (state.KeepRunningBatch(NumSizes)) {\n    for (ssize_t i = 0; i < NumSizes; ++i) {\n      benchmark::DoNotOptimize(x = h(v.Get(i, x)));\n    }\n  }\n  state.SetBytesProcessed(v.bytes);\n}\n\n// Latency benchmarks are grouped by the three different hash functions to\n// facilitate comparing their performance for a given value type or string size\n// bucket.\n#define LATENCY_VALUE_BENCHMARKS(...)                                  \\\n  BENCHMARK(BM_LatencyHash<RandValues<__VA_ARGS__>, CarbonHashBench>); \\\n  BENCHMARK(BM_LatencyHash<RandValues<__VA_ARGS__>, AbseilHashBench>); \\\n  BENCHMARK(BM_LatencyHash<RandValues<__VA_ARGS__>, LLVMHashBench>)\nLATENCY_VALUE_BENCHMARKS(uint8_t);\nLATENCY_VALUE_BENCHMARKS(uint16_t);\nLATENCY_VALUE_BENCHMARKS(std::pair<uint8_t, uint8_t>);\nLATENCY_VALUE_BENCHMARKS(uint32_t);\nLATENCY_VALUE_BENCHMARKS(std::pair<uint16_t, uint16_t>);\nLATENCY_VALUE_BENCHMARKS(uint64_t);\nLATENCY_VALUE_BENCHMARKS(int*);\nLATENCY_VALUE_BENCHMARKS(std::pair<uint32_t, uint32_t>);\nLATENCY_VALUE_BENCHMARKS(std::pair<uint64_t, uint32_t>);\nLATENCY_VALUE_BENCHMARKS(std::pair<uint32_t, uint64_t>);\nLATENCY_VALUE_BENCHMARKS(std::pair<int*, uint32_t>);\nLATENCY_VALUE_BENCHMARKS(std::pair<uint32_t, int*>);\nLATENCY_VALUE_BENCHMARKS(__uint128_t);\nLATENCY_VALUE_BENCHMARKS(std::pair<uint64_t, uint64_t>);\nLATENCY_VALUE_BENCHMARKS(std::pair<int*, int*>);\nLATENCY_VALUE_BENCHMARKS(std::pair<uint64_t, int*>);\nLATENCY_VALUE_BENCHMARKS(std::pair<int*, uint64_t>);\n\n#define LATENCY_STRING_BENCHMARKS(MaxSize)                          \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/true, MaxSize>, \\\n                           CarbonHashBench>);                       \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/true, MaxSize>, \\\n                           AbseilHashBench>);                       \\\n  BENCHMARK(                                                        \\\n      BM_LatencyHash<RandStrings</*RandSize=*/true, MaxSize>, LLVMHashBench>)\n\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/4);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/8);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/16);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/32);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/64);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/256);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/512);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/1024);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/2048);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/4096);\nLATENCY_STRING_BENCHMARKS(/*MaxSize=*/8192);\n\n// We also want to check for size-specific cliffs, particularly in small sizes\n// and sizes around implementation inflection points such as powers of two and\n// half-way points between powers of two. Because these benchmarks are looking\n// for size-related cliffs, all the runs for particular hash function are kept\n// together.\n//\n// Note: because these use a fixed size, their specific timing isn't terribly\n// informative. The branch predictor behavior on a modern CPU will be\n// significantly different in this benchmarks from any other and may distort all\n// manner of the timings. The results should really only be compared between\n// sizes for cliffs, and not directly compared with other numbers.\n#define LATENCY_STRING_SIZE_BENCHMARKS(Hash)                             \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 0>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 1>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 2>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 3>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 4>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 5>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 6>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 7>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 8>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 9>, Hash>);   \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 15>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 16>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 17>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 23>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 24>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 25>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 31>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 32>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 33>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 47>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 48>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 49>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 63>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 64>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 65>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 91>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 92>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 93>, Hash>);  \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 127>, Hash>); \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 128>, Hash>); \\\n  BENCHMARK(BM_LatencyHash<RandStrings</*RandSize=*/false, 129>, Hash>)\n\n// Because these just look for size-related cliffs in performance, we only do a\n// minimal number of benchmarks. There are a lot of sizes so this avoids wasted\n// time in benchmark runs and there isn't much value from greater comparative\n// coverage here.\nLATENCY_STRING_SIZE_BENCHMARKS(CarbonHashBench);\nLATENCY_STRING_SIZE_BENCHMARKS(AbseilHashBench);\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/hashing_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/hashing.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <concepts>\n#include <string>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/ADT/Sequence.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n#include \"llvm/Support/TypeName.h\"\n\nnamespace Carbon {\nnamespace {\n\nusing ::testing::Eq;\nusing ::testing::Le;\nusing ::testing::Ne;\n\nTEST(HashingTest, HashCodeApi) {\n  // Manually compute a few hash codes where we can exercise the underlying API.\n  HashCode empty = HashValue(\"\");\n  HashCode a = HashValue(\"a\");\n  HashCode b = HashValue(\"b\");\n  ASSERT_THAT(HashValue(\"\"), Eq(empty));\n  ASSERT_THAT(HashValue(\"a\"), Eq(a));\n  ASSERT_THAT(HashValue(\"b\"), Eq(b));\n  ASSERT_THAT(empty, Ne(a));\n  ASSERT_THAT(empty, Ne(b));\n  ASSERT_THAT(a, Ne(b));\n\n  // Exercise the methods in basic ways across a few sizes. This doesn't check\n  // much beyond stability across re-computed values, crashing, or hitting UB.\n  EXPECT_THAT(HashValue(\"a\").ExtractIndex(), Eq(a.ExtractIndex()));\n\n  EXPECT_THAT(a.ExtractIndex(), Ne(b.ExtractIndex()));\n  EXPECT_THAT(a.ExtractIndex(), Ne(empty.ExtractIndex()));\n\n  // The tag shouldn't have bits set outside the range requested.\n  EXPECT_THAT(HashValue(\"a\").ExtractIndexAndTag<1>().second & ~0b1, Eq(0));\n  EXPECT_THAT(HashValue(\"a\").ExtractIndexAndTag<2>().second & ~0b11, Eq(0));\n  EXPECT_THAT(HashValue(\"a\").ExtractIndexAndTag<3>().second & ~0b111, Eq(0));\n  EXPECT_THAT(HashValue(\"a\").ExtractIndexAndTag<4>().second & ~0b1111, Eq(0));\n\n  // Note that the index produced with a tag may be different from the index\n  // alone!\n  EXPECT_THAT(HashValue(\"a\").ExtractIndexAndTag<2>(),\n              Eq(a.ExtractIndexAndTag<2>()));\n  EXPECT_THAT(HashValue(\"a\").ExtractIndexAndTag<16>(),\n              Eq(a.ExtractIndexAndTag<16>()));\n  EXPECT_THAT(HashValue(\"a\").ExtractIndexAndTag<7>(),\n              Eq(a.ExtractIndexAndTag<7>()));\n\n  const auto [a_index, a_tag] = a.ExtractIndexAndTag<4>();\n  const auto [b_index, b_tag] = b.ExtractIndexAndTag<4>();\n  EXPECT_THAT(a_index, Ne(b_index));\n  EXPECT_THAT(a_tag, Ne(b_tag));\n}\n\nTEST(HashingTest, Integers) {\n  for (int64_t i : {0, 1, 2, 3, 42, -1, -2, -3, -13}) {\n    SCOPED_TRACE(llvm::formatv(\"Hashing: {0}\", i).str());\n    auto test_int_hash = [](auto i) {\n      using T = decltype(i);\n      SCOPED_TRACE(\n          llvm::formatv(\"Hashing type: {0}\", llvm::getTypeName<T>()).str());\n      HashCode hash = HashValue(i);\n      // Hashes should be stable within the execution.\n      EXPECT_THAT(HashValue(i), Eq(hash));\n\n      // Zero should match, and other integers shouldn't collide trivially.\n      HashCode hash_zero = HashValue(static_cast<T>(0));\n      if (i == 0) {\n        EXPECT_THAT(hash, Eq(hash_zero));\n      } else {\n        EXPECT_THAT(hash, Ne(hash_zero));\n      }\n    };\n    test_int_hash(static_cast<int8_t>(i));\n    test_int_hash(static_cast<uint8_t>(i));\n    test_int_hash(static_cast<int16_t>(i));\n    test_int_hash(static_cast<uint16_t>(i));\n    test_int_hash(static_cast<int32_t>(i));\n    test_int_hash(static_cast<uint32_t>(i));\n    // `i` is already an int64_t variable.\n    test_int_hash(i);\n    test_int_hash(static_cast<uint64_t>(i));\n  }\n}\n\nTEST(HashingTest, BasicSeeding) {\n  auto unseeded_hash = HashValue(42);\n  EXPECT_THAT(unseeded_hash, Ne(HashValue(42, 1)));\n  EXPECT_THAT(unseeded_hash, Ne(HashValue(42, 2)));\n  EXPECT_THAT(unseeded_hash, Ne(HashValue(42, 3)));\n  EXPECT_THAT(unseeded_hash,\n              Ne(HashValue(42, static_cast<uint64_t>(unseeded_hash))));\n}\n\nTEST(HashingTest, Pointers) {\n  int object1 = 42;\n  std::string object2 =\n      \"Hello World! This is a long-ish string so it ends up on the heap!\";\n\n  HashCode hash_null = HashValue(nullptr);\n  // Hashes should be stable.\n  EXPECT_THAT(HashValue(nullptr), Eq(hash_null));\n\n  // Hash other kinds of pointers without trivial collisions.\n  HashCode hash1 = HashValue(&object1);\n  HashCode hash2 = HashValue(&object2);\n  HashCode hash3 = HashValue(object2.data());\n  EXPECT_THAT(hash1, Ne(hash_null));\n  EXPECT_THAT(hash2, Ne(hash_null));\n  EXPECT_THAT(hash3, Ne(hash_null));\n  EXPECT_THAT(hash1, Ne(hash2));\n  EXPECT_THAT(hash1, Ne(hash3));\n  EXPECT_THAT(hash2, Ne(hash3));\n\n  // Hash values reflect the address and not the type.\n  EXPECT_THAT(HashValue(static_cast<void*>(nullptr)), Eq(hash_null));\n  EXPECT_THAT(HashValue(static_cast<int*>(nullptr)), Eq(hash_null));\n  EXPECT_THAT(HashValue(static_cast<std::string*>(nullptr)), Eq(hash_null));\n  EXPECT_THAT(HashValue(reinterpret_cast<void*>(&object1)), Eq(hash1));\n  EXPECT_THAT(HashValue(reinterpret_cast<int*>(&object2)), Eq(hash2));\n  EXPECT_THAT(HashValue(reinterpret_cast<std::string*>(object2.data())),\n              Eq(hash3));\n}\n\nTEST(HashingTest, PairsAndTuples) {\n  // Note that we can't compare hash codes across arity, or in general, compare\n  // hash codes for different types as the type isn't part of the hash. These\n  // hashes are targeted at use in hash tables which pick a single type that's\n  // the basis of any comparison.\n  HashCode hash_00 = HashValue(std::pair(0, 0));\n  HashCode hash_01 = HashValue(std::pair(0, 1));\n  HashCode hash_10 = HashValue(std::pair(1, 0));\n  HashCode hash_11 = HashValue(std::pair(1, 1));\n  EXPECT_THAT(hash_00, Ne(hash_01));\n  EXPECT_THAT(hash_00, Ne(hash_10));\n  EXPECT_THAT(hash_00, Ne(hash_11));\n  EXPECT_THAT(hash_01, Ne(hash_10));\n  EXPECT_THAT(hash_01, Ne(hash_11));\n  EXPECT_THAT(hash_10, Ne(hash_11));\n\n  HashCode hash_000 = HashValue(std::tuple(0, 0, 0));\n  HashCode hash_001 = HashValue(std::tuple(0, 0, 1));\n  HashCode hash_010 = HashValue(std::tuple(0, 1, 0));\n  HashCode hash_011 = HashValue(std::tuple(0, 1, 1));\n  HashCode hash_100 = HashValue(std::tuple(1, 0, 0));\n  HashCode hash_101 = HashValue(std::tuple(1, 0, 1));\n  HashCode hash_110 = HashValue(std::tuple(1, 1, 0));\n  HashCode hash_111 = HashValue(std::tuple(1, 1, 1));\n  EXPECT_THAT(hash_000, Ne(hash_001));\n  EXPECT_THAT(hash_000, Ne(hash_010));\n  EXPECT_THAT(hash_000, Ne(hash_011));\n  EXPECT_THAT(hash_000, Ne(hash_100));\n  EXPECT_THAT(hash_000, Ne(hash_101));\n  EXPECT_THAT(hash_000, Ne(hash_110));\n  EXPECT_THAT(hash_000, Ne(hash_111));\n  EXPECT_THAT(hash_001, Ne(hash_010));\n  EXPECT_THAT(hash_001, Ne(hash_011));\n  EXPECT_THAT(hash_001, Ne(hash_100));\n  EXPECT_THAT(hash_001, Ne(hash_101));\n  EXPECT_THAT(hash_001, Ne(hash_110));\n  EXPECT_THAT(hash_001, Ne(hash_111));\n  EXPECT_THAT(hash_010, Ne(hash_011));\n  EXPECT_THAT(hash_010, Ne(hash_100));\n  EXPECT_THAT(hash_010, Ne(hash_101));\n  EXPECT_THAT(hash_010, Ne(hash_110));\n  EXPECT_THAT(hash_010, Ne(hash_111));\n  EXPECT_THAT(hash_011, Ne(hash_100));\n  EXPECT_THAT(hash_011, Ne(hash_101));\n  EXPECT_THAT(hash_011, Ne(hash_110));\n  EXPECT_THAT(hash_011, Ne(hash_111));\n  EXPECT_THAT(hash_100, Ne(hash_101));\n  EXPECT_THAT(hash_100, Ne(hash_110));\n  EXPECT_THAT(hash_100, Ne(hash_111));\n  EXPECT_THAT(hash_101, Ne(hash_110));\n  EXPECT_THAT(hash_101, Ne(hash_111));\n  EXPECT_THAT(hash_110, Ne(hash_111));\n\n  // Hashing a 2-tuple and a pair should produce identical results, so pairs\n  // are compatible with code using things like variadic tuple construction.\n  EXPECT_THAT(HashValue(std::tuple(0, 0)), Eq(hash_00));\n  EXPECT_THAT(HashValue(std::tuple(0, 1)), Eq(hash_01));\n  EXPECT_THAT(HashValue(std::tuple(1, 0)), Eq(hash_10));\n  EXPECT_THAT(HashValue(std::tuple(1, 1)), Eq(hash_11));\n\n  // Integers in tuples should also work.\n  for (int i : {0, 1, 2, 3, 42, -1, -2, -3, -13}) {\n    SCOPED_TRACE(llvm::formatv(\"Hashing: ({0}, {0}, {0})\", i).str());\n    auto test_int_tuple_hash = [](auto i) {\n      using T = decltype(i);\n      SCOPED_TRACE(\n          llvm::formatv(\"Hashing integer type: {0}\", llvm::getTypeName<T>())\n              .str());\n      std::tuple v = {i, i, i};\n      HashCode hash = HashValue(v);\n\n      // Hashes should be stable within the execution.\n      EXPECT_THAT(HashValue(v), Eq(hash));\n\n      // Zero should match, and other integers shouldn't collide trivially.\n      T zero = 0;\n      std::tuple zero_tuple = {zero, zero, zero};\n      HashCode hash_zero = HashValue(zero_tuple);\n      if (i == 0) {\n        EXPECT_THAT(hash, Eq(hash_zero));\n      } else {\n        EXPECT_THAT(hash, Ne(hash_zero));\n      }\n    };\n    test_int_tuple_hash(i);\n    test_int_tuple_hash(static_cast<int8_t>(i));\n    test_int_tuple_hash(static_cast<uint8_t>(i));\n    test_int_tuple_hash(static_cast<int16_t>(i));\n    test_int_tuple_hash(static_cast<uint16_t>(i));\n    test_int_tuple_hash(static_cast<int32_t>(i));\n    test_int_tuple_hash(static_cast<uint32_t>(i));\n    test_int_tuple_hash(static_cast<int64_t>(i));\n    test_int_tuple_hash(static_cast<uint64_t>(i));\n\n    // Heterogeneous integer types should also work, but we only support\n    // comparing against hashes of tuples with the exact same type.\n    using T1 = std::tuple<int8_t, uint32_t, int16_t>;\n    using T2 = std::tuple<uint32_t, int16_t, uint64_t>;\n    if (i == 0) {\n      EXPECT_THAT(HashValue(T1{i, i, i}), Eq(HashValue(T1{0, 0, 0})));\n      EXPECT_THAT(HashValue(T2{i, i, i}), Eq(HashValue(T2{0, 0, 0})));\n    } else {\n      EXPECT_THAT(HashValue(T1{i, i, i}), Ne(HashValue(T1{0, 0, 0})));\n      EXPECT_THAT(HashValue(T2{i, i, i}), Ne(HashValue(T2{0, 0, 0})));\n    }\n  }\n\n  // Hash values of pointers in pairs and tuples reflect the address and not the\n  // type. Pairs and 2-tuples give the same hash values.\n  HashCode hash_2null = HashValue(std::pair(nullptr, nullptr));\n  EXPECT_THAT(HashValue(std::tuple(static_cast<int*>(nullptr),\n                                   static_cast<double*>(nullptr))),\n              Eq(hash_2null));\n\n  // Hash other kinds of pointers without trivial collisions.\n  int object1 = 42;\n  std::string object2 = \"Hello world!\";\n  HashCode hash_3ptr =\n      HashValue(std::tuple(&object1, &object2, object2.data()));\n  EXPECT_THAT(hash_3ptr, Ne(HashValue(std::tuple(nullptr, nullptr, nullptr))));\n\n  // Hash values reflect the address and not the type.\n  EXPECT_THAT(\n      HashValue(std::tuple(reinterpret_cast<void*>(&object1),\n                           reinterpret_cast<int*>(&object2),\n                           reinterpret_cast<std::string*>(object2.data()))),\n      Eq(hash_3ptr));\n}\n\nTEST(HashingTest, BasicStrings) {\n  llvm::SmallVector<std::pair<std::string, HashCode>> hashes;\n  for (int size : {0, 1, 2, 4, 16, 64, 256, 1024}) {\n    std::string s(size, 'a');\n    hashes.push_back({s, HashValue(s)});\n  }\n  for (const auto& [s1, hash1] : hashes) {\n    EXPECT_THAT(HashValue(s1), Eq(hash1));\n    // Also check that we get the same hashes even when using string-wrapping\n    // types.\n    EXPECT_THAT(HashValue(std::string_view(s1)), Eq(hash1));\n    EXPECT_THAT(HashValue(llvm::StringRef(s1)), Eq(hash1));\n\n    // And some basic tests that simple things don't collide.\n    for (const auto& [s2, hash2] : hashes) {\n      if (s1 != s2) {\n        EXPECT_THAT(hash1, Ne(hash2))\n            << \"Matching hashes for '\" << s1 << \"' and '\" << s2 << \"'\";\n      }\n    }\n  }\n}\n\nTEST(HashingTest, ArrayLike) {\n  int c_array[] = {1, 2, 3, 4};\n  EXPECT_THAT(HashValue(c_array), Eq(HashValue(c_array)));\n  EXPECT_THAT(HashValue(std::array{1, 2, 3, 4}), Eq(HashValue(c_array)));\n  EXPECT_THAT(HashValue(std::vector{1, 2, 3, 4}), Eq(HashValue(c_array)));\n  EXPECT_THAT(HashValue(llvm::SmallVector<int>{1, 2, 3, 4}),\n              Eq(HashValue(c_array)));\n}\n\nTEST(HashingTest, HashAPInt) {\n  // The bit width should be hashed as well as the value.\n  llvm::APInt one_64(/*numBits=*/64, /*val=*/1);\n  llvm::APInt two_64(/*numBits=*/64, /*val=*/2);\n  llvm::APInt one_128(/*numBits=*/128, /*val=*/1);\n  llvm::APInt two_128(/*numBits=*/128, /*val=*/2);\n\n  std::array array = {one_64, two_64, one_128, two_128};\n  for (int i : llvm::seq<int>(array.size())) {\n    EXPECT_THAT(HashValue(array[i]), Eq(HashValue(array[i])));\n\n    for (int j : llvm::seq<int>(i + 1, array.size())) {\n      EXPECT_THAT(HashValue(array[i]), Ne(HashValue(array[j])))\n          << \"Hashing #\" << i << \" and #\" << j;\n    }\n  }\n}\n\nTEST(HashingTest, HashAPFloat) {\n  // Hashtable equality for `APFloat` uses a bitwise comparison. This\n  // differentiates between various things that would otherwise not make sense:\n  // - Different floating point semantics\n  // - `-0.0` and `0.0`\n  //\n  // It also allows NaNs to be compared meaningfully.\n  llvm::APFloat zero_float =\n      llvm::APFloat::getZero(llvm::APFloat::IEEEsingle());\n  llvm::APFloat neg_zero_float =\n      llvm::APFloat::getZero(llvm::APFloat::IEEEsingle(), /*Negative=*/true);\n  llvm::APFloat zero_double =\n      llvm::APFloat::getZero(llvm::APFloat::IEEEdouble());\n  llvm::APFloat zero_bfloat = llvm::APFloat::getZero(llvm::APFloat::BFloat());\n  llvm::APFloat one_float = llvm::APFloat::getOne(llvm::APFloat::IEEEsingle());\n  llvm::APFloat inf_float = llvm::APFloat::getInf(llvm::APFloat::IEEEsingle());\n  llvm::APFloat nan_0_float = llvm::APFloat::getNaN(\n      llvm::APFloat::IEEEsingle(), /*Negative=*/false, /*payload=*/0);\n  llvm::APFloat nan_42_float = llvm::APFloat::getNaN(\n      llvm::APFloat::IEEEsingle(), /*Negative=*/false, /*payload=*/42);\n\n  std::array array = {zero_float, neg_zero_float, zero_double, zero_bfloat,\n                      one_float,  inf_float,      nan_42_float};\n  for (int i : llvm::seq<int>(array.size())) {\n    EXPECT_THAT(HashValue(array[i]), Eq(HashValue(array[i])));\n\n    for (int j : llvm::seq<int>(i + 1, array.size())) {\n      EXPECT_THAT(HashValue(array[i]), Ne(HashValue(array[j])))\n          << \"Hashing #\" << i << \" and #\" << j;\n    }\n  }\n\n  // Note that currently we use LLVM's hashing of `APFloat` which does *not*\n  // hash the payload of NaNs.\n  EXPECT_THAT(HashValue(nan_0_float), Eq(HashValue(nan_42_float)));\n}\n\n// A type that has hashing customization. However, it also works to be small and\n// appear to have a unique object representation. This helps ensure that when a\n// user provides custom hashing it is reliably used.\nstruct HashableType {\n  int8_t x;\n  int8_t y;\n\n  int16_t ignored = 0;\n\n  // Provide the hashing but try to craft a relatively low-ranking overload to\n  // help ensure that the hashing framework doesn't accidentally override this.\n  template <typename T>\n    requires(std::same_as<T, HashableType>)\n  friend auto CarbonHashValue(const T& value, uint64_t seed) -> HashCode {\n    Hasher hasher(seed);\n    hasher.Hash(value.x, value.y);\n    return static_cast<HashCode>(hasher);\n  }\n};\nstatic_assert(std::has_unique_object_representations_v<HashableType>);\n\nTEST(HashingTest, CustomType) {\n  HashableType a = {.x = 1, .y = 2};\n  HashableType b = {.x = 3, .y = 4};\n\n  EXPECT_THAT(HashValue(a), Eq(HashValue(a)));\n  EXPECT_THAT(HashValue(a), Ne(HashValue(b)));\n\n  // Differences in an ignored field have no impact.\n  HashableType c = {.x = 3, .y = 4, .ignored = 42};\n  EXPECT_THAT(HashValue(c), Eq(HashValue(b)));\n}\n\nTEST(HashingTest, ArrayRecursion) {\n  // Make sure we correctly recurse when hashing an array and don't try to use\n  // the object representation.\n  llvm::APInt one_64(/*numBits=*/64, /*val=*/1);\n  llvm::APInt two_64(/*numBits=*/64, /*val=*/2);\n  llvm::APInt one_128(/*numBits=*/128, /*val=*/1);\n  llvm::APInt two_128(/*numBits=*/128, /*val=*/2);\n  std::array apint_array = {one_64, two_64, one_128, two_128};\n  EXPECT_THAT(HashValue(apint_array),\n              Eq(HashValue(std::array{one_64, two_64, one_128, two_128})));\n  EXPECT_THAT(HashValue(apint_array),\n              Ne(HashValue(std::array{one_64, two_64, two_128, one_128})));\n  EXPECT_THAT(HashValue(apint_array),\n              Ne(HashValue(std::array{one_64, two_64, one_64, two_128})));\n  EXPECT_THAT(HashValue(apint_array),\n              Ne(HashValue(std::array{one_64, two_128, one_128, two_128})));\n  EXPECT_THAT(HashValue(apint_array),\n              Ne(HashValue(std::array{one_64, two_64, one_128})));\n  EXPECT_THAT(\n      HashValue(apint_array),\n      Ne(HashValue(std::array{one_64, two_64, one_128, two_128, two_128})));\n\n  // Also test for a custom type that still *looks* like plain data.\n  HashableType a = {.x = 1, .y = 2};\n  HashableType b = {.x = 3, .y = 4};\n  HashableType c = {.x = 3, .y = 4, .ignored = 42};\n  std::array custom_array = {a, b, c, a};\n  EXPECT_THAT(HashValue(custom_array), Eq(HashValue(std::array{a, b, c, a})));\n  EXPECT_THAT(HashValue(custom_array), Eq(HashValue(std::array{a, b, b, a})));\n  EXPECT_THAT(HashValue(custom_array), Ne(HashValue(std::array{a, b, c, b})));\n  EXPECT_THAT(HashValue(custom_array), Ne(HashValue(std::array{a, b, a, c})));\n  EXPECT_THAT(HashValue(custom_array), Ne(HashValue(std::array{a, b, c})));\n  EXPECT_THAT(HashValue(custom_array),\n              Ne(HashValue(std::array{a, b, c, a, a})));\n}\n\nTEST(HashingTest, TupleRecursion) {\n  // Make sure we can hash pairs and tuples which require us to recurse for each\n  // element rather than treating the whole object as raw storage.\n\n  // We can use APInt values to help test this.\n  llvm::APInt one_64(/*numBits=*/64, /*val=*/1);\n  llvm::APInt two_64(/*numBits=*/64, /*val=*/2);\n  llvm::APInt one_128(/*numBits=*/128, /*val=*/1);\n  llvm::APInt two_128(/*numBits=*/128, /*val=*/2);\n  EXPECT_THAT(HashValue(std::pair{one_64, one_128}),\n              Eq(HashValue(std::pair{one_64, one_128})));\n  EXPECT_THAT(HashValue(std::pair{one_64, one_128}),\n              Ne(HashValue(std::pair{one_64, two_64})));\n  EXPECT_THAT(HashValue(std::pair{one_64, one_128}),\n              Ne(HashValue(std::pair{one_64, one_64})));\n  EXPECT_THAT(HashValue(std::pair{one_64, one_128}),\n              Ne(HashValue(std::pair{one_128, one_64})));\n  EXPECT_THAT(HashValue(std::tuple{one_64, one_128, two_64}),\n              Eq(HashValue(std::tuple{one_64, one_128, two_64})));\n  EXPECT_THAT(HashValue(std::tuple{one_64, one_128, two_64}),\n              Ne(HashValue(std::tuple{one_64, two_64, two_64})));\n  EXPECT_THAT(HashValue(std::tuple{one_64, one_128, two_64}),\n              Ne(HashValue(std::tuple{one_64, one_64, two_64})));\n  EXPECT_THAT(HashValue(std::tuple{one_64, one_128, two_64}),\n              Ne(HashValue(std::tuple{one_64, two_64, one_128})));\n  EXPECT_THAT(HashValue(std::tuple{one_64, one_128, two_64}),\n              Ne(HashValue(std::tuple{one_64, one_128})));\n\n  // Also test for a custom type that still *looks* like plain data.\n  HashableType a = {.x = 1, .y = 2};\n  HashableType b = {.x = 3, .y = 4};\n  HashableType c = {.x = 3, .y = 4, .ignored = 42};\n  EXPECT_THAT(HashValue(std::pair{a, b}), Eq(HashValue(std::pair{a, b})));\n  EXPECT_THAT(HashValue(std::pair{a, b}), Ne(HashValue(std::pair{a, a})));\n  EXPECT_THAT(HashValue(std::pair{a, b}), Ne(HashValue(std::pair{b, a})));\n  EXPECT_THAT(HashValue(std::pair{a, b}), Eq(HashValue(std::pair{a, c})));\n  EXPECT_THAT(HashValue(std::tuple{a, b, a}),\n              Eq(HashValue(std::tuple{a, b, a})));\n  EXPECT_THAT(HashValue(std::tuple{a, b, a}),\n              Ne(HashValue(std::tuple{a, b, b})));\n  EXPECT_THAT(HashValue(std::tuple{a, b, a}),\n              Ne(HashValue(std::tuple{a, a, a})));\n  EXPECT_THAT(HashValue(std::tuple{a, b, a}),\n              Eq(HashValue(std::tuple{a, c, a})));\n}\n\n// The only significantly bad seed is zero, so pick a non-zero seed with a tiny\n// amount of entropy to make sure that none of the testing relies on the entropy\n// from this.\nconstexpr uint64_t TestSeed = 42ULL * 1024;\n\nauto ToHexBytes(llvm::StringRef s) -> std::string {\n  RawStringOstream rendered;\n  rendered << \"{\";\n  llvm::ListSeparator sep(\", \");\n  for (const char c : s) {\n    rendered << sep << llvm::formatv(\"{0:x2}\", static_cast<uint8_t>(c));\n  }\n  rendered << \"}\";\n  return rendered.TakeStr();\n}\n\ntemplate <typename T>\nstruct HashedValue {\n  HashCode hash;\n  T v;\n};\n\nusing HashedString = HashedValue<std::string>;\n\ntemplate <typename T>\nauto PrintFullWidthHex(llvm::raw_ostream& os, T value) {\n  static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 ||\n                sizeof(T) == 8);\n  // Given the nature of a format string and the good formatting, a nested\n  // conditional seems like the most readable structure.\n  // NOLINTBEGIN(readability-avoid-nested-conditional-operator)\n  os << llvm::formatv(sizeof(T) == 1   ? \"{0:x2}\"\n                      : sizeof(T) == 2 ? \"{0:x4}\"\n                      : sizeof(T) == 4 ? \"{0:x8}\"\n                                       : \"{0:x16}\",\n                      static_cast<uint64_t>(value));\n  // NOLINTEND(readability-avoid-nested-conditional-operator)\n}\n\ntemplate <typename T>\n  requires std::integral<T>\nauto operator<<(llvm::raw_ostream& os, HashedValue<T> hv)\n    -> llvm::raw_ostream& {\n  os << \"hash \" << hv.hash << \" for value \";\n  PrintFullWidthHex(os, hv.v);\n  return os;\n}\n\ntemplate <typename T, typename U>\n  requires std::integral<T> && std::integral<U>\nauto operator<<(llvm::raw_ostream& os, HashedValue<std::pair<T, U>> hv)\n    -> llvm::raw_ostream& {\n  os << \"hash \" << hv.hash << \" for pair of \";\n  PrintFullWidthHex(os, hv.v.first);\n  os << \" and \";\n  PrintFullWidthHex(os, hv.v.second);\n  return os;\n}\n\nstruct Collisions {\n  int total;\n  int median;\n  int max;\n};\n\n// Analyzes a list of hashed values to find all of the hash codes which collide\n// within a specific bit-range.\n//\n// With `BitBegin=0` and `BitEnd=64`, this is equivalent to finding full\n// collisions. But when the begin and end of the bit range are narrower than the\n// 64-bits of the hash code, it allows this function to analyze a specific\n// window of bits within the 64-bit hash code to understand how many collisions\n// emerge purely within that bit range.\n//\n// With narrow ranges (we often look at the first N and last N bits for small\n// N), collisions are common and so this function summarizes this with the total\n// number of collisions and the median number of collisions for an input value.\ntemplate <int BitBegin, int BitEnd, typename T>\nauto FindBitRangeCollisions(llvm::ArrayRef<HashedValue<T>> hashes)\n    -> Collisions {\n  static_assert(BitBegin < BitEnd);\n  constexpr int BitCount = BitEnd - BitBegin;\n  static_assert(BitCount <= 32);\n  constexpr int BitShift = BitBegin;\n  constexpr uint64_t BitMask = ((1ULL << BitCount) - 1) << BitShift;\n\n  // We collect counts of collisions in a vector. Initially, we just have a zero\n  // and all inputs map to that collision count. As we discover collisions,\n  // we'll create a dedicated counter for it and count how many inputs collide.\n  llvm::SmallVector<int> collision_counts;\n  collision_counts.push_back(0);\n  // The \"map\" for collision counts. Each input hashed value has a corresponding\n  // index stored here. That index is the index of the collision count in the\n  // container above. We resize this to fill it with zeros to start as the zero\n  // index above has a collision count of zero.\n  //\n  // The result of this is that the number of collisions for `hashes[i]` is\n  // `collision_counts[collision_map[i]]`.\n  llvm::SmallVector<int> collision_map;\n  collision_map.resize(hashes.size());\n\n  // First, we extract the bit subsequence we want to examine from each hash and\n  // store it with an index back into the hashed values (or the collision map).\n  //\n  // The result is that, `bits_and_indices[i].bits` has the hash bits of\n  // interest from `hashes[bits_and_indices[i].index]`.\n  //\n  // And because `collision_map` above uses the same indices as `hashes`,\n  // `collision_counts[collision_map[bits_and_indices[i].index]]` is the number\n  // of collisions for `bits_and_indices[i].bits`.\n  struct BitSequenceAndHashIndex {\n    // The bit subsequence of a hash input, adjusted into the low bits.\n    uint32_t bits;\n    // The index of the hash input corresponding to this bit sequence.\n    int index;\n  };\n  llvm::SmallVector<BitSequenceAndHashIndex> bits_and_indices;\n  bits_and_indices.reserve(hashes.size());\n  for (const auto& [hash, v] : hashes) {\n    CARBON_DCHECK(v == hashes[bits_and_indices.size()].v);\n    auto hash_bits = (static_cast<uint64_t>(hash) & BitMask) >> BitShift;\n    bits_and_indices.push_back(\n        {.bits = static_cast<uint32_t>(hash_bits),\n         .index = static_cast<int>(bits_and_indices.size())});\n  }\n\n  // Now we sort by the extracted bit sequence so we can efficiently scan for\n  // colliding bit patterns.\n  llvm::sort(bits_and_indices, [](const auto& lhs, const auto& rhs) {\n    return lhs.bits < rhs.bits;\n  });\n\n  // Scan the sorted bit sequences we've extracted looking for collisions. We\n  // count the total collisions, but we also track the number of individual\n  // inputs that collide with each specific bit pattern.\n  uint32_t prev_hash_bits = bits_and_indices[0].bits;\n  int prev_index = bits_and_indices[0].index;\n  bool in_collision = false;\n  int total = 0;\n  for (const auto& [hash_bits, hash_index] :\n       llvm::ArrayRef(bits_and_indices).slice(1)) {\n    // Check if we've found a new hash (and thus a new value), reset everything.\n    CARBON_CHECK(hashes[prev_index].v != hashes[hash_index].v);\n    if (hash_bits != prev_hash_bits) {\n      CARBON_CHECK(hashes[prev_index].hash != hashes[hash_index].hash);\n      prev_hash_bits = hash_bits;\n      prev_index = hash_index;\n      in_collision = false;\n      continue;\n    }\n\n    // Otherwise, we have a colliding bit sequence.\n    ++total;\n\n    // If we've already created a collision count to track this, just increment\n    // it and map this hash to it.\n    if (in_collision) {\n      ++collision_counts.back();\n      collision_map[hash_index] = collision_counts.size() - 1;\n      continue;\n    }\n\n    // If this is a new collision, create a dedicated count to track it and\n    // begin counting.\n    in_collision = true;\n    collision_map[prev_index] = collision_counts.size();\n    collision_map[hash_index] = collision_counts.size();\n    collision_counts.push_back(1);\n  }\n\n  // Sort by collision count for each hash.\n  llvm::sort(bits_and_indices, [&](const auto& lhs, const auto& rhs) {\n    return collision_counts[collision_map[lhs.index]] <\n           collision_counts[collision_map[rhs.index]];\n  });\n\n  // And compute the median and max.\n  int median = collision_counts\n      [collision_map[bits_and_indices[bits_and_indices.size() / 2].index]];\n  int max = *llvm::max_element(collision_counts);\n  CARBON_CHECK(max ==\n               collision_counts[collision_map[bits_and_indices.back().index]]);\n  return {.total = total, .median = median, .max = max};\n}\n\nauto CheckNoDuplicateValues(llvm::ArrayRef<HashedString> hashes) -> void {\n  for (int i = 0, size = hashes.size(); i < size - 1; ++i) {\n    const auto& [_, value] = hashes[i];\n    CARBON_CHECK(value != hashes[i + 1].v, \"Duplicate value: {0}\", value);\n  }\n}\n\ntemplate <int N>\nauto AllByteStringsHashedAndSorted() {\n  static_assert(N < 5, \"Can only generate all 4-byte strings or shorter.\");\n\n  llvm::SmallVector<HashedString> hashes;\n  int64_t count = 1LL << (N * 8);\n  for (int64_t i : llvm::seq(count)) {\n    uint8_t bytes[N];\n    for (int j : llvm::seq(N)) {\n      bytes[j] = (static_cast<uint64_t>(i) >> (8 * j)) & 0xff;\n    }\n    std::string s(std::begin(bytes), std::end(bytes));\n    hashes.push_back({HashValue(s, TestSeed), s});\n  }\n\n  llvm::sort(hashes, [](const HashedString& lhs, const HashedString& rhs) {\n    return static_cast<uint64_t>(lhs.hash) < static_cast<uint64_t>(rhs.hash);\n  });\n  CheckNoDuplicateValues(hashes);\n\n  return hashes;\n}\n\nauto ExpectNoHashCollisions(llvm::ArrayRef<HashedString> hashes) -> void {\n  HashCode prev_hash = hashes[0].hash;\n  llvm::StringRef prev_s = hashes[0].v;\n  for (const auto& [hash, s] : hashes.slice(1)) {\n    if (hash != prev_hash) {\n      prev_hash = hash;\n      prev_s = s;\n      continue;\n    }\n\n    FAIL() << \"Colliding hash '\" << hash << \"' of strings \"\n           << ToHexBytes(prev_s) << \" and \" << ToHexBytes(s);\n  }\n}\n\nTEST(HashingTest, Collisions1ByteSized) {\n  auto hashes_storage = AllByteStringsHashedAndSorted<1>();\n  llvm::ArrayRef hashes = hashes_storage;\n  ExpectNoHashCollisions(hashes);\n\n  auto low_32bit_collisions = FindBitRangeCollisions<0, 32>(hashes);\n  EXPECT_THAT(low_32bit_collisions.total, Eq(0));\n  auto high_32bit_collisions = FindBitRangeCollisions<32, 64>(hashes);\n  EXPECT_THAT(high_32bit_collisions.total, Eq(0));\n\n  // We expect collisions when only looking at 7-bits of the hash. However,\n  // modern hash table designs need to use either the low or high 7 bits as tags\n  // for faster searching. So we add some direct testing that the median and max\n  // collisions for any given key stay within bounds. We express the bounds in\n  // terms of the minimum expected \"perfect\" rate of collisions if uniformly\n  // distributed.\n  int min_7bit_collisions = llvm::NextPowerOf2(hashes.size() - 1) / (1 << 7);\n  auto low_7bit_collisions = FindBitRangeCollisions<0, 7>(hashes);\n  EXPECT_THAT(low_7bit_collisions.median, Le(8 * min_7bit_collisions));\n  EXPECT_THAT(low_7bit_collisions.max, Le(8 * min_7bit_collisions));\n  auto high_7bit_collisions = FindBitRangeCollisions<64 - 7, 64>(hashes);\n  EXPECT_THAT(high_7bit_collisions.median, Le(2 * min_7bit_collisions));\n  EXPECT_THAT(high_7bit_collisions.max, Le(4 * min_7bit_collisions));\n}\n\nTEST(HashingTest, Collisions2ByteSized) {\n  auto hashes_storage = AllByteStringsHashedAndSorted<2>();\n  llvm::ArrayRef hashes = hashes_storage;\n  ExpectNoHashCollisions(hashes);\n\n  auto low_32bit_collisions = FindBitRangeCollisions<0, 32>(hashes);\n  EXPECT_THAT(low_32bit_collisions.total, Eq(0));\n  auto high_32bit_collisions = FindBitRangeCollisions<32, 64>(hashes);\n  EXPECT_THAT(high_32bit_collisions.total, Eq(0));\n\n  // Similar to 1-byte keys, we do expect a certain rate of collisions here but\n  // bound the median and max.\n  int min_7bit_collisions = llvm::NextPowerOf2(hashes.size() - 1) / (1 << 7);\n  auto low_7bit_collisions = FindBitRangeCollisions<0, 7>(hashes);\n  EXPECT_THAT(low_7bit_collisions.median, Le(2 * min_7bit_collisions));\n  EXPECT_THAT(low_7bit_collisions.max, Le(2 * min_7bit_collisions));\n  auto high_7bit_collisions = FindBitRangeCollisions<64 - 7, 64>(hashes);\n  EXPECT_THAT(high_7bit_collisions.median, Le(2 * min_7bit_collisions));\n  EXPECT_THAT(high_7bit_collisions.max, Le(2 * min_7bit_collisions));\n}\n\n// Generate and hash all strings of of [BeginByteCount, EndByteCount) bytes,\n// with [BeginSetBitCount, EndSetBitCount) contiguous bits at each possible bit\n// offset set to one and all other bits set to zero.\ntemplate <int BeginByteCount, int EndByteCount, int BeginSetBitCount,\n          int EndSetBitCount>\nstruct SparseHashTestParamRanges {\n  static_assert(BeginByteCount >= 0);\n  static_assert(BeginByteCount < EndByteCount);\n  static_assert(BeginSetBitCount >= 0);\n  static_assert(BeginSetBitCount < EndSetBitCount);\n  // Note that we intentionally allow the end-set-bit-count to result in more\n  // set bits than are available -- we truncate the number of set bits to fit\n  // within the byte string.\n  static_assert(BeginSetBitCount <= BeginByteCount * 8);\n\n  struct ByteCount {\n    static constexpr int Begin = BeginByteCount;\n    static constexpr int End = EndByteCount;\n  };\n  struct SetBitCount {\n    static constexpr int Begin = BeginSetBitCount;\n    static constexpr int End = EndSetBitCount;\n  };\n};\n\ntemplate <typename ParamRanges>\nstruct SparseHashTest : ::testing::Test {\n  using ByteCount = typename ParamRanges::ByteCount;\n  using SetBitCount = typename ParamRanges::SetBitCount;\n\n  static auto GetHashedByteStrings() {\n    llvm::SmallVector<HashedString> hashes;\n    for (int byte_count :\n         llvm::seq_inclusive(ByteCount::Begin, ByteCount::End)) {\n      int bits = byte_count * 8;\n      for (int set_bit_count : llvm::seq_inclusive(\n               SetBitCount::Begin, std::min(bits, SetBitCount::End))) {\n        if (set_bit_count == 0) {\n          std::string s(byte_count, '\\0');\n          hashes.push_back({HashValue(s, TestSeed), std::move(s)});\n          continue;\n        }\n        for (int begin_set_bit : llvm::seq_inclusive(0, bits - set_bit_count)) {\n          std::string s(byte_count, '\\0');\n\n          int begin_set_bit_byte_index = begin_set_bit / 8;\n          int begin_set_bit_bit_index = begin_set_bit % 8;\n          int end_set_bit_byte_index = (begin_set_bit + set_bit_count) / 8;\n          int end_set_bit_bit_index = (begin_set_bit + set_bit_count) % 8;\n\n          // We build a begin byte and end byte. We set the begin byte, set\n          // subsequent bytes up to *and including* the end byte to all ones,\n          // and then mask the end byte. For multi-byte runs, the mask just sets\n          // the end byte and for single-byte runs the mask computes the\n          // intersecting bits.\n          //\n          // Consider a 4-set-bit count, starting at bit 2. The begin bit index\n          // is 2, and the end bit index is 6.\n          //\n          // Begin byte:  0b11111111 -(shl 2)-----> 0b11111100\n          // End byte:    0b11111111 -(shr (8-6))-> 0b00111111\n          // Masked byte:                           0b00111100\n          //\n          // Or a 10-set-bit-count starting at bit 2. The begin bit index is 2,\n          // the end byte index is (12 / 8) or 1, and the end bit index is (12 %\n          // 8) or 4.\n          //\n          // Begin byte:  0b11111111 -(shl 2)-----> 0b11111100 -> 6 bits\n          // End byte:    0b11111111 -(shr (8-4))-> 0b00001111 -> 4 bits\n          //                                                      10 total bits\n          //\n          uint8_t begin_set_bit_byte = 0xFFU << begin_set_bit_bit_index;\n          uint8_t end_set_bit_byte = 0xFFU >> (8 - end_set_bit_bit_index);\n          bool has_end_byte_bits = end_set_bit_byte != 0;\n          s[begin_set_bit_byte_index] = begin_set_bit_byte;\n          for (int i : llvm::seq(begin_set_bit_byte_index + 1,\n                                 end_set_bit_byte_index + has_end_byte_bits)) {\n            s[i] = '\\xFF';\n          }\n          // If there are no bits set in the end byte, it may be past-the-end\n          // and we can't even mask a zero byte safely.\n          if (has_end_byte_bits) {\n            s[end_set_bit_byte_index] &= end_set_bit_byte;\n          }\n          hashes.push_back({HashValue(s, TestSeed), std::move(s)});\n        }\n      }\n    }\n\n    llvm::sort(hashes, [](const HashedString& lhs, const HashedString& rhs) {\n      return static_cast<uint64_t>(lhs.hash) < static_cast<uint64_t>(rhs.hash);\n    });\n    CheckNoDuplicateValues(hashes);\n\n    return hashes;\n  }\n};\n\nusing SparseHashTestParams = ::testing::Types<\n    SparseHashTestParamRanges</*BeginByteCount=*/0, /*EndByteCount=*/256,\n                              /*BeginSetBitCount=*/0, /*EndSetBitCount=*/1>,\n    SparseHashTestParamRanges</*BeginByteCount=*/1, /*EndByteCount=*/128,\n                              /*BeginSetBitCount=*/2, /*EndSetBitCount=*/4>,\n    SparseHashTestParamRanges</*BeginByteCount=*/1, /*EndByteCount=*/64,\n                              /*BeginSetBitCount=*/4, /*EndSetBitCount=*/16>>;\nTYPED_TEST_SUITE(SparseHashTest, SparseHashTestParams);\n\nTYPED_TEST(SparseHashTest, Collisions) {\n  auto hashes_storage = this->GetHashedByteStrings();\n  llvm::ArrayRef hashes = hashes_storage;\n  ExpectNoHashCollisions(hashes);\n\n  int min_7bit_collisions = llvm::NextPowerOf2(hashes.size() - 1) / (1 << 7);\n  auto low_7bit_collisions = FindBitRangeCollisions<0, 7>(hashes);\n  EXPECT_THAT(low_7bit_collisions.median, Le(2 * min_7bit_collisions));\n  EXPECT_THAT(low_7bit_collisions.max, Le(2 * min_7bit_collisions));\n  auto high_7bit_collisions = FindBitRangeCollisions<64 - 7, 64>(hashes);\n  EXPECT_THAT(high_7bit_collisions.median, Le(2 * min_7bit_collisions));\n  EXPECT_THAT(high_7bit_collisions.max, Le(2 * min_7bit_collisions));\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/hashtable_key_context.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_HASHTABLE_KEY_CONTEXT_H_\n#define CARBON_COMMON_HASHTABLE_KEY_CONTEXT_H_\n\n#include <concepts>\n\n#include \"common/hashing.h\"\n#include \"llvm/ADT/APFloat.h\"\n#include \"llvm/ADT/APInt.h\"\n\nnamespace Carbon {\n\n// The equality comparison used by the the hashtable key contexts in this file,\n// and suitable for using in other hashtable key contexts.\n//\n// This provides a hashtable-specific extension point to implement equality\n// comparison within a hashtable key context. By default, it will use\n// `operator==` on the LHS and RHS operands. However, types can provide a\n// dedicated customization point by implementing a free function that can be\n// found by ADL for your type called `CarbonHashtableEq` with the following\n// signature:\n//\n// ```cpp\n// auto CarbonHashtableEq(const YourType& lhs, const YourType& rhs) -> bool;\n// ```\n//\n// Any such overload will be able to override the default we provide for types\n// that can compare with `==`.\n//\n// This library also provides any customization points for LLVM or standard\n// library types either lacking `operator==` or where that operator is not\n// suitable for hashtables. For example, `llvm::APInt` and `llvm::APFloat` have\n// custom equality comparisons provided through this extension point.\ntemplate <typename LeftT, typename RightT>\nauto HashtableEq(const LeftT& lhs, const RightT& rhs) -> bool;\n\n// Customizable context for keys in hashtables.\n//\n// This type or customizations matching its API are used with the data\n// structures in `map.h` and `set.h`. By providing a custom version of the\n// `KeyContext` type parameter to those data structures, users can provide\n// either stateless or stateful customization of the two core hashtable key\n// operations: hashing and comparison.\n//\n// The default for hashing uses Carbon's `hashing.h`. Customizations must still\n// return a `HashCode` as defined there, and it needs to have the same core\n// properties of hashes produced by the `hashing.h` infrastructure.\n//\n// The default for comparison is `operator==`. The `KeyEq` method is always\n// called with a key *stored in the hashtable* as the second or \"Rhs\" parameter.\n// This is to allow simplifying the set of overloads needed for heterogeneous\n// contexts: only the first, LHS, parameter needs to support different lookup\n// key types.\n//\n// Custom KeyContext types should have the the same API as the default type.\n// They can choose to use templates to support heterogeneous key types or not as\n// appropriate. The default context can also be used as a base class with only\n// one or the other APIs customized.\n//\n// An important consideration is how the key context is constructed. When the\n// key context can be default constructed, hashtable APIs trafficking in keys\n// will have overloads that provide a default constructed key context. When the\n// context is *not* default constructible, every API that accepts a key will\n// also require a context argument to be called, and that argument will be used\n// throughout that operation. The intent is to allow callers to provide stateful\n// contexts to each API where it would be needed, while managing that state\n// outside the hashtable. Often the needed state is trivially part of the\n// caller's existing state and needn't be stored separately.\n//\n// Example for a stateful, customized key context for interned strings:\n// ```cpp\n// class InternedStringIndexKeyContext {\n//  public:\n//   InternedStringIndexKeyContext(\n//       llvm::ArrayRef<llvm::StringRef> interned_strings)\n//       : interned_strings_(interned_strings) {}\n//\n//   auto HashKey(llvm::StringRef s, uint64_t seed) const -> HashCode {\n//     return HashValue(s);\n//   }\n//   auto HashKey(int index_key, uint64_t seed) const -> HashCode {\n//     return HashKey(interned_strings_[index_key]);\n//   }\n//\n//   auto KeyEq(llvm::StringRef lhs, int rhs_index) const -> bool {\n//     return lhs == interned_strings_[rhs_index];\n//   }\n//   auto KeyEq(int lhs_index, int rhs_index) const -> bool {\n//     return KeyEq(interned_strings_[lhs_index], rhs_index);\n//   }\n//\n//  private:\n//   llvm::ArrayRef<llvm::StringRef> interned_strings_;\n// };\n// ```\nstruct DefaultKeyContext {\n  template <typename AnyKeyT>\n  auto HashKey(const AnyKeyT& key, uint64_t seed) const -> HashCode;\n\n  template <typename AnyKeyT, typename TableKeyT>\n  auto KeyEq(const AnyKeyT& lhs_key, const TableKeyT& rhs_key) const -> bool;\n};\n\n// A CRTP mixin for a custom key context type that first translates keys to a\n// different type, possibly using some state.\n//\n// Derived types should publicly inherit from this mixin and define overloads of\n// the `TranslateKey` method as indicated below in its comment.\ntemplate <typename DerivedT>\nclass TranslatingKeyContext {\n public:\n  // Derived types should provide one or more overloads that hide this function\n  // and perform translation for the key types which need it.\n  //\n  // For any key type, the context will check if there exists a callable\n  // `TranslateKey` function on the derived type. If so, that function will be\n  // called and the result used for hashing or comparison. If not, the key will\n  // be used directly. The derived type doesn't need to and shouldn't provide a\n  // default no-op overload. Instead, for any types that need no translation, it\n  // should ensure no overload is viable.\n  //\n  // Note that this function should be *hidden* by the derived overloads. It is\n  // provided here to help detect typos or misspellings or cases where no\n  // overload is provided at all.\n  template <typename TranslateKeyT>\n  auto TranslateKey(const TranslateKeyT& /*key*/) const -> int {\n    // A static_assert that will fail on any actual instantiation (it can't be\n    // instantiated with a void type). We have to make this dependent as\n    // Clang-16 will fail to compile even when the definition is never\n    // instantiated otherwise.\n    static_assert(\n        std::same_as<TranslateKeyT, void>,\n        \"No `TranslateKey` overload was provided by the derived type!\");\n  }\n\n  template <typename AnyKeyT>\n  auto HashKey(const AnyKeyT& key, uint64_t seed) const -> HashCode;\n\n  template <typename AnyKeyT, typename TableKeyT>\n  auto KeyEq(const AnyKeyT& lhs_key, const TableKeyT& rhs_key) const -> bool;\n};\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// Only implementation details below this point.\n//\n////////////////////////////////////////////////////////////////////////////////\n\nnamespace InternalHashtableEqDispatch {\n\ninline auto CarbonHashtableEq(const llvm::APInt& lhs, const llvm::APInt& rhs)\n    -> bool {\n  return lhs.getBitWidth() == rhs.getBitWidth() && lhs == rhs;\n}\n\ninline auto CarbonHashtableEq(const llvm::APFloat& lhs,\n                              const llvm::APFloat& rhs) -> bool {\n  return lhs.bitwiseIsEqual(rhs);\n}\n\ntemplate <typename LeftT, typename RightT>\ninline auto CarbonHashtableEq(const LeftT& lhs, const RightT& rhs) -> bool\n  requires(requires {\n    { lhs == rhs } -> std::convertible_to<bool>;\n  })\n{\n  return lhs == rhs;\n}\n\ntemplate <typename LeftT, typename RightT>\ninline auto DispatchImpl(const LeftT& lhs, const RightT& rhs) -> bool {\n  // This unqualified call will find both the overloads in our internal\n  // namespace above and ADL-found functions within an associated namespace for\n  // either `LeftT` or `RightT`.\n  return CarbonHashtableEq(lhs, rhs);\n}\n\n}  // namespace InternalHashtableEqDispatch\n\ntemplate <typename LeftT, typename RightT>\ninline auto HashtableEq(const LeftT& lhs, const RightT& rhs) -> bool {\n  return InternalHashtableEqDispatch::DispatchImpl(lhs, rhs);\n}\n\ntemplate <typename AnyKeyT>\nauto DefaultKeyContext::HashKey(const AnyKeyT& key, uint64_t seed) const\n    -> HashCode {\n  return HashValue(key, seed);\n}\n\ntemplate <typename AnyKeyT, typename TableKeyT>\nauto DefaultKeyContext::KeyEq(const AnyKeyT& lhs_key,\n                              const TableKeyT& rhs_key) const -> bool {\n  return HashtableEq(lhs_key, rhs_key);\n}\n\ntemplate <typename DerivedT>\ntemplate <typename AnyKeyT>\nauto TranslatingKeyContext<DerivedT>::HashKey(const AnyKeyT& key,\n                                              uint64_t seed) const -> HashCode {\n  const DerivedT& self = *static_cast<const DerivedT*>(this);\n  if constexpr (requires { self.TranslateKey(key); }) {\n    return HashValue(self.TranslateKey(key), seed);\n  } else {\n    return HashValue(key, seed);\n  }\n}\n\ntemplate <typename DerivedT>\ntemplate <typename AnyKeyT, typename TableKeyT>\nauto TranslatingKeyContext<DerivedT>::KeyEq(const AnyKeyT& lhs_key,\n                                            const TableKeyT& rhs_key) const\n    -> bool {\n  const DerivedT& self = *static_cast<const DerivedT*>(this);\n  // Because we don't want to make no-op calls and potentially struggle with\n  // temporary lifetimes at runtime we have to fully expand the 4 states.\n  constexpr bool TranslateLhs = requires { self.TranslateKey(lhs_key); };\n  constexpr bool TranslateRhs = requires { self.TranslateKey(rhs_key); };\n  if constexpr (TranslateLhs && TranslateRhs) {\n    return HashtableEq(self.TranslateKey(lhs_key), self.TranslateKey(rhs_key));\n  } else if constexpr (TranslateLhs) {\n    return HashtableEq(self.TranslateKey(lhs_key), rhs_key);\n  } else if constexpr (TranslateRhs) {\n    return HashtableEq(lhs_key, self.TranslateKey(rhs_key));\n  } else {\n    return HashtableEq(lhs_key, rhs_key);\n  }\n}\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_HASHTABLE_KEY_CONTEXT_H_\n"
  },
  {
    "path": "common/hashtable_key_context_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/hashtable_key_context.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\nnamespace Carbon {\nnamespace {\n\nusing ::testing::Eq;\nusing ::testing::Ne;\n\nstruct DefaultEq {\n  int x, y;\n\n  friend auto operator==(const DefaultEq& lhs, const DefaultEq& rhs)\n      -> bool = default;\n};\n\nstruct CustomEq {\n  int x, y;\n\n  friend auto operator==(const CustomEq& lhs, const CustomEq& rhs) -> bool {\n    return lhs.x == rhs.x && lhs.y == rhs.y;\n  }\n};\n\nstruct CustomExtEq {\n  int x, y;\n\n  friend auto CarbonHashtableEq(const CustomExtEq& lhs, const CustomExtEq& rhs)\n      -> bool {\n    return lhs.x == rhs.x && lhs.y == rhs.y;\n  }\n};\n\nTEST(HashtableKeyContextTest, HashtableEq) {\n  EXPECT_TRUE(HashtableEq(0, 0));\n  EXPECT_FALSE(HashtableEq(1, 0));\n  EXPECT_FALSE(HashtableEq(0, 1));\n  EXPECT_FALSE(HashtableEq(1234, 5678));\n  EXPECT_TRUE(HashtableEq(5678, 5678));\n\n  EXPECT_TRUE(\n      HashtableEq(DefaultEq{.x = 0, .y = 0}, DefaultEq{.x = 0, .y = 0}));\n  EXPECT_FALSE(\n      HashtableEq(DefaultEq{.x = 1, .y = 2}, DefaultEq{.x = 3, .y = 4}));\n\n  EXPECT_TRUE(HashtableEq(CustomEq{.x = 0, .y = 0}, CustomEq{.x = 0, .y = 0}));\n  EXPECT_FALSE(HashtableEq(CustomEq{.x = 1, .y = 2}, CustomEq{.x = 3, .y = 4}));\n\n  EXPECT_TRUE(\n      HashtableEq(CustomExtEq{.x = 0, .y = 0}, CustomExtEq{.x = 0, .y = 0}));\n  EXPECT_FALSE(\n      HashtableEq(CustomExtEq{.x = 1, .y = 2}, CustomExtEq{.x = 3, .y = 4}));\n}\n\nTEST(HashtableKeyContextTest, HashtableEqAPInt) {\n  // Hashtable equality doesn't assert on mismatched bit width, it includes the\n  // bit width in the comparison.\n  llvm::APInt one_64(/*numBits=*/64, /*val=*/1);\n  llvm::APInt two_64(/*numBits=*/64, /*val=*/2);\n  llvm::APInt one_128(/*numBits=*/128, /*val=*/1);\n  llvm::APInt two_128(/*numBits=*/128, /*val=*/2);\n\n  EXPECT_TRUE(HashtableEq(one_64, one_64));\n  EXPECT_FALSE(HashtableEq(one_64, one_128));\n  EXPECT_TRUE(HashtableEq(two_128, two_128));\n  EXPECT_FALSE(HashtableEq(two_64, two_128));\n  EXPECT_FALSE(HashtableEq(one_64, two_64));\n  EXPECT_FALSE(HashtableEq(one_64, two_128));\n  EXPECT_FALSE(HashtableEq(one_128, two_128));\n  EXPECT_FALSE(HashtableEq(one_128, two_64));\n}\n\nTEST(HashtableKeyContextTest, HashtableEqAPFloat) {\n  // Hashtable equality for `APFloat` uses a bitwise comparison. This\n  // differentiates between various things that would otherwise not make sense:\n  // - Different floating point semantics\n  // - `-0.0` and `0.0`\n  //\n  // It also allows NaNs to be compared meaningfully.\n  llvm::APFloat zero_float =\n      llvm::APFloat::getZero(llvm::APFloat::IEEEsingle());\n  llvm::APFloat neg_zero_float =\n      llvm::APFloat::getZero(llvm::APFloat::IEEEsingle(), /*Negative=*/true);\n  llvm::APFloat zero_double =\n      llvm::APFloat::getZero(llvm::APFloat::IEEEdouble());\n  llvm::APFloat zero_bfloat = llvm::APFloat::getZero(llvm::APFloat::BFloat());\n  llvm::APFloat one_float = llvm::APFloat::getOne(llvm::APFloat::IEEEsingle());\n  llvm::APFloat inf_float = llvm::APFloat::getInf(llvm::APFloat::IEEEsingle());\n  llvm::APFloat nan_0_float = llvm::APFloat::getNaN(\n      llvm::APFloat::IEEEsingle(), /*Negative=*/false, /*payload=*/0);\n  llvm::APFloat nan_42_float = llvm::APFloat::getNaN(\n      llvm::APFloat::IEEEsingle(), /*Negative=*/false, /*payload=*/42);\n\n  // Boring cases.\n  EXPECT_TRUE(HashtableEq(zero_float, zero_float));\n  EXPECT_FALSE(HashtableEq(zero_float, one_float));\n  EXPECT_TRUE(HashtableEq(inf_float, inf_float));\n  EXPECT_FALSE(HashtableEq(inf_float, one_float));\n\n  // Confirm a case where we expect `==` to work but produce a different result.\n  ASSERT_TRUE(zero_float == neg_zero_float);\n  EXPECT_FALSE(HashtableEq(zero_float, neg_zero_float));\n\n  // Now work through less reasonable things outside of a hashtable such as\n  // mixing semantics and NaNs.\n  EXPECT_FALSE(HashtableEq(zero_float, zero_double));\n  EXPECT_FALSE(HashtableEq(zero_float, zero_bfloat));\n  EXPECT_FALSE(HashtableEq(zero_float, nan_0_float));\n  EXPECT_FALSE(HashtableEq(zero_float, nan_42_float));\n  EXPECT_FALSE(HashtableEq(nan_0_float, nan_42_float));\n}\n\nstruct CustomHash {\n  int x;\n\n  friend auto CarbonHashValue(const CustomHash& value, uint64_t seed)\n      -> HashCode {\n    return HashValue(value.x + 42, seed);\n  }\n};\n\nTEST(HashtableKeyContextTest, DefaultKeyContext) {\n  // Make sure the default context dispatches appropriately, including for\n  // interesting types. We don't cover all the cases here and use the direct\n  // tests of `HashtableEq` for that.\n  DefaultKeyContext context;\n\n  EXPECT_FALSE(context.KeyEq(1234, 5678));\n  EXPECT_TRUE(context.KeyEq(5678, 5678));\n  EXPECT_TRUE(context.KeyEq(DefaultEq{0, 0}, DefaultEq{0, 0}));\n  EXPECT_FALSE(context.KeyEq(DefaultEq{1, 2}, DefaultEq{3, 4}));\n  EXPECT_TRUE(context.KeyEq(CustomEq{0, 0}, CustomEq{0, 0}));\n  EXPECT_FALSE(context.KeyEq(CustomEq{1, 2}, CustomEq{3, 4}));\n  EXPECT_TRUE(context.KeyEq(CustomExtEq{0, 0}, CustomExtEq{0, 0}));\n  EXPECT_FALSE(context.KeyEq(CustomExtEq{1, 2}, CustomExtEq{3, 4}));\n\n  llvm::APInt one_64(/*numBits=*/64, /*val=*/1);\n  llvm::APInt one_128(/*numBits=*/128, /*val=*/1);\n  EXPECT_TRUE(HashtableEq(one_64, one_64));\n  EXPECT_FALSE(HashtableEq(one_64, one_128));\n\n  llvm::APFloat zero_float =\n      llvm::APFloat::getZero(llvm::APFloat::IEEEsingle());\n  llvm::APFloat neg_zero_float =\n      llvm::APFloat::getZero(llvm::APFloat::IEEEsingle(), /*Negative=*/true);\n  EXPECT_TRUE(HashtableEq(zero_float, zero_float));\n  EXPECT_FALSE(HashtableEq(zero_float, neg_zero_float));\n\n  // Also check hash dispatching.\n  uint64_t seed = 1234;\n  EXPECT_THAT(context.HashKey(42, seed), Eq(HashValue(42, seed)));\n  EXPECT_THAT(context.HashKey(CustomHash{.x = 1234}, seed),\n              Eq(HashValue(CustomHash{.x = 1234}, seed)));\n  EXPECT_THAT(context.HashKey(one_64, seed), Eq(HashValue(one_64, seed)));\n  EXPECT_THAT(context.HashKey(one_128, seed), Eq(HashValue(one_128, seed)));\n  EXPECT_THAT(context.HashKey(one_64, seed),\n              Ne(context.HashKey(one_128, seed)));\n  EXPECT_THAT(context.HashKey(zero_float, seed),\n              Eq(HashValue(zero_float, seed)));\n  EXPECT_THAT(context.HashKey(neg_zero_float, seed),\n              Eq(HashValue(neg_zero_float, seed)));\n  EXPECT_THAT(context.HashKey(zero_float, seed),\n              Ne(context.HashKey(neg_zero_float, seed)));\n}\n\nstruct TestTranslatingKeyContext\n    : TranslatingKeyContext<TestTranslatingKeyContext> {\n  auto TranslateKey(int index) const -> const llvm::APInt& {\n    return array[index];\n  }\n\n  llvm::ArrayRef<llvm::APInt> array;\n};\n\nTEST(HashtableKeyContextTest, TranslatingKeyContext) {\n  llvm::APInt one_64(/*numBits=*/64, /*val=*/1);\n  llvm::APInt two_64(/*numBits=*/64, /*val=*/2);\n  llvm::APInt one_128(/*numBits=*/128, /*val=*/1);\n  llvm::APInt two_128(/*numBits=*/128, /*val=*/2);\n  // An array of values, including some duplicates.\n  llvm::SmallVector<llvm::APInt> values = {one_64,  two_64, one_128,\n                                           two_128, one_64, one_64};\n\n  TestTranslatingKeyContext context = {.array = values};\n\n  uint64_t seed = 1234;\n  EXPECT_THAT(context.HashKey(0, seed), Eq(HashValue(one_64, seed)));\n  EXPECT_THAT(context.HashKey(1, seed), Eq(HashValue(two_64, seed)));\n  EXPECT_THAT(context.HashKey(2, seed), Eq(HashValue(one_128, seed)));\n  EXPECT_THAT(context.HashKey(3, seed), Eq(HashValue(two_128, seed)));\n  EXPECT_THAT(context.HashKey(4, seed), Eq(HashValue(one_64, seed)));\n  EXPECT_THAT(context.HashKey(5, seed), Eq(HashValue(one_64, seed)));\n\n  EXPECT_TRUE(context.KeyEq(one_64, 0));\n  EXPECT_TRUE(context.KeyEq(one_64, 4));\n  EXPECT_TRUE(context.KeyEq(one_64, 5));\n  EXPECT_TRUE(context.KeyEq(0, one_64));\n  EXPECT_TRUE(context.KeyEq(0, 0));\n  EXPECT_TRUE(context.KeyEq(0, 4));\n  EXPECT_TRUE(context.KeyEq(4, 5));\n  EXPECT_FALSE(context.KeyEq(one_64, 1));\n  EXPECT_FALSE(context.KeyEq(one_64, 2));\n  EXPECT_FALSE(context.KeyEq(one_64, 3));\n  EXPECT_FALSE(context.KeyEq(1, one_64));\n  EXPECT_FALSE(context.KeyEq(2, one_64));\n  EXPECT_FALSE(context.KeyEq(3, one_64));\n  EXPECT_FALSE(context.KeyEq(0, 1));\n  EXPECT_FALSE(context.KeyEq(0, 2));\n  EXPECT_FALSE(context.KeyEq(4, 3));\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/init_llvm.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/init_llvm.h\"\n\n#include \"llvm/Support/TargetSelect.h\"\n#include \"llvm/Support/raw_ostream.h\"\n\nnamespace Carbon {\n\nInitLLVM::InitLLVM(int& argc, char**& argv)\n    : init_llvm_(argc, argv),\n      // LLVM assumes that argc and argv won't change, and registers them with\n      // an `llvm::PrettyStackTraceProgram` that will crash if an argv element\n      // gets nulled out, which for example `testing::InitGoogleTest` does. So\n      // make a copy of the argv that LLVM produces in order to support\n      // mutation.\n      args_(argv, argv + argc) {\n  // `argv[argc]` is expected to be a null pointer (may reallocate `args_`).\n  args_.push_back(nullptr);\n\n  // Return our mutable copy of argv for the program to use.\n  argc = args_.size() - 1;\n  argv = args_.data();\n\n  llvm::setBugReportMsg(\n      \"Please report issues to \"\n      \"https://github.com/carbon-language/carbon-lang/issues and include the \"\n      \"crash backtrace.\\n\");\n\n  // Initialize LLVM targets if //common:all_llvm_targets was linked in.\n  if (InitializeTargets) {\n    InitializeTargets();\n  }\n\n  // Printing to stderr should flush stdout. This is most noticeable when stderr\n  // is piped to stdout.\n  llvm::errs().tie(&llvm::outs());\n}\n\nInitLLVM::InitializeTargetsFn* InitLLVM::InitializeTargets = nullptr;\n\n}  // namespace Carbon\n"
  },
  {
    "path": "common/init_llvm.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_INIT_LLVM_H_\n#define CARBON_COMMON_INIT_LLVM_H_\n\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/Support/InitLLVM.h\"\n\nnamespace Carbon {\n\n// A RAII class to handle initializing LLVM and shutting it down. An instance of\n// this class should be created in the `main` function of each Carbon binary\n// that interacts with LLVM, before `argc` and `argv` are first inspected.\nclass InitLLVM {\n public:\n  // Initializes LLVM for use by a Carbon binary. On Windows, `argc` and `argv`\n  // are updated to refer to properly-encoded UTF-8 versions of the command line\n  // arguments.\n  explicit InitLLVM(int& argc, char**& argv);\n\n  // Shuts down LLVM.\n  ~InitLLVM() = default;\n\n private:\n  using InitializeTargetsFn = auto() -> void;\n\n  llvm::InitLLVM init_llvm_;\n  llvm::SmallVector<char*> args_;\n\n  // A pointer to the LLVM target initialization function, if :all_llvm_targets\n  // is linked in. Otherwise nullptr.\n  // NOLINTNEXTLINE(readability-identifier-naming): Constant after static init.\n  static InitializeTargetsFn* InitializeTargets;\n\n  // The initializer of this static data member populates `InitializeTargets`.\n  // Defined only if :all_llvm_targets is linked in. This is a member so that\n  // it has access to `InitializeTargets`.\n  static const char RegisterTargets;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_INIT_LLVM_H_\n"
  },
  {
    "path": "common/latch.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/latch.h\"\n\n#include \"common/check.h\"\n\nnamespace Carbon {\n\nauto Latch::Inc() -> void {\n  // The increment must be _atomic_ but is _relaxed_.\n  //\n  // Increments and decrements can happen concurrently on separate threads, so\n  // we need to prevent tearing and for there to be a total ordering of stores\n  // to this atomic.\n  //\n  // However we provide no _synchronization_ of the increment with any other\n  // operations. Instead, the caller must provide some extrinsic happens-before\n  // between its call to `Inc` and its later call to `Dec`. When that call to\n  // `Dec` synchronizes-with another call to `Dec`, all relaxed stores are\n  // covered by the resulting inter-thread happens-before relationship.\n  count_.fetch_add(1, std::memory_order_relaxed);\n}\n\nauto Latch::Dec() -> bool {\n  // The decrement is both an _acquire_ and _release_ operation.\n  //\n  // All threads which decrement to a non-zero value need to synchronize-with\n  // the thread which decrements to a zero value. This means the decrements to\n  // non-zero values need to have _release_ semantics that are _acquired_ by the\n  // decrement to zero. Since there is a single decrement operation, it must be\n  // both _acquire_ and _release_.\n  //\n  // Note that this technically provides a stronger guarantee than the contract\n  // of `Dec` requires -- *all* decrements synchronize with all decrements whose\n  // value they observe, we only need that to be true of the decrement arriving\n  // at zero. This could in theory be modeled by conditional fences, but those\n  // have their own problems and we don't need to model the more precise\n  // semantics for efficiency.\n  auto previous = count_.fetch_sub(1, std::memory_order_acq_rel);\n\n  CARBON_CHECK(previous > 0);\n  if (previous == 1) {\n    // Ensure that our closure is fully destroyed here, releasing any\n    // resources, locks, or other synchronization primitives.\n    auto on_zero = std::exchange(on_zero_, [] {});\n    std::move(on_zero)();\n    return true;\n  }\n  return false;\n}\n\nauto Latch::Init(llvm::unique_function<auto()->void> on_zero) -> Handle {\n  CARBON_CHECK(count_ == 0);\n  on_zero_ = std::move(on_zero);\n  return Handle(this);\n}\n\n}  // namespace Carbon\n"
  },
  {
    "path": "common/latch.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_LATCH_H_\n#define CARBON_COMMON_LATCH_H_\n\n#include <atomic>\n\n#include \"llvm/ADT/FunctionExtras.h\"\n\nnamespace Carbon {\n\n// A synchronization primitive similar to `std::latch` to coordinate starting\n// some action once all of a set of other actions complete.\n//\n// Users initialize the latch (with `Init`), and receive a handle RAII object.\n// This handle can be copied, and the latch is satisfied when the last copy of\n// the handle returned by `Init` is destroyed.\n//\n// The latch synchronizes between every destruction of a handle and the\n// destruction of the last handle, allowing code that runs after the latch is\n// satisfied to access everything written by any thread that destroyed a handle.\n// For more details of the synchronization mechanics, see the comments on `Inc`\n// and `Dec` that implement this logic.\n//\n// This type also supports holding a closure to run when satisfied to simplify\n// patterns where that body of code is easier to express at the start of work\n// being synchronized instead of as each work item completes.\n//\n// The initialization API is separate from the constructor both for convenience\n// and to enable it to provide the initial handle. This makes it easy to build\n// constructively correct code where each work unit holds a handle until\n// finished, including the initializer of the latch, often using by-value\n// captures in a lambda that does the work.\nclass Latch {\n public:\n  class Handle;\n\n  Latch() = default;\n  Latch(const Latch&) = delete;\n  Latch(Latch&&) = delete;\n\n  // Initialize a latch and get the initial handle to it.\n  //\n  // When the last copy of the returned handle is destroyed, the latch will be\n  // satisfied.\n  //\n  // A closure may be provided which will be called when that last handle is\n  // destroyed. Note that the closure will run on whatever thread executes the\n  // last handle destruction. Typically, the closure here should _schedule_ the\n  // next step of work on some thread pool rather than performing it directly.\n  //\n  // Once this method is called, it cannot be called again until all handles are\n  // destroyed and the latch is satisfied. It can then be called again to get a\n  // fresh handle (and provide a new closure if desired).\n  auto Init(llvm::unique_function<auto()->void> on_zero = [] {}) -> Handle;\n\n private:\n  // Increments the latch's counter.\n  //\n  // This is thread-safe, and may be called concurrently on multiple threads,\n  // and may be called concurrently with `Dec`. However, the caller _must_ call\n  // `Inc` and then `Dec`, and provide some happens-before relationship between\n  // the `Inc` and `Dec`. Typically, this is done with either same-thread\n  // happens-before, or because some other synchronization event such as\n  // starting a thread or popping a task from a thread pool provides the\n  // inter-thread happens-before relationship.\n  auto Inc() -> void;\n\n  // Decrements the latch's counter, and returns true when it reaches zero.\n  //\n  // This is thread-safe, and may be called concurrently with other calls to\n  // `Dec` or `Inc`.\n  //\n  // It also ensures that all threads which call `Dec` and receive `false`\n  // synchronize-with the thread that calls `Dec` and receives `true`. As a\n  // consequence everything that happens-before the call to `Dec` has an\n  // inter-thread happens-before for any code when `Dec` returns `true`.\n  //\n  // Note that there is no guarantee of inter-thread happens-before to\n  // operations after a `Dec` call that returns `false`.\n  auto Dec() -> bool;\n\n  std::atomic<int> count_;\n  llvm::unique_function<auto()->void> on_zero_;\n};\n\n// A copyable RAII handle around a `Latch`.\n//\n// When the last copy of a handle returned by `Latch::Init` is destroyed, the\n// latch is considered satisfied. Copying is supported by incrementing the\n// count of the latch. That increment can always be performed because it starts\n// from a live handle and so the count cannot have reached zero.\n//\n// For more details, see the `Latch` class.\nclass Latch::Handle {\n public:\n  Handle(const Handle& arg) : latch_(arg.latch_) {\n    if (latch_) {\n      arg.latch_->Inc();\n    }\n  }\n  Handle(Handle&& arg) noexcept : latch_(std::exchange(arg.latch_, nullptr)) {}\n\n  ~Handle() {\n    if (latch_) {\n      latch_->Dec();\n    }\n  }\n\n  // Drops a handle explicitly, rather than waiting for it to fall out of scope.\n  //\n  // This also allows observing whether the underlying latch is satisfied.\n  // Calls to this function synchronize with all other drops or destructions of\n  // latch handles when it returns true, and only the last will return true.\n  auto Drop() && -> bool {\n    bool last = latch_->Dec();\n    latch_ = nullptr;\n    return last;\n  }\n\n private:\n  friend Latch;\n\n  // Private constructor used by `Latch::Init` to create the initial handle for\n  // a latch.\n  explicit Handle(Latch* latch) : latch_(latch) { latch_->Inc(); }\n\n  Latch* latch_ = nullptr;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_LATCH_H_\n"
  },
  {
    "path": "common/latch_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/latch.h\"\n\n#include <gtest/gtest.h>\n\n#include <chrono>\n#include <thread>\n#include <vector>\n\nnamespace Carbon {\nnamespace {\n\n// Basic test for the Latch.\nTEST(LatchTest, Basic) {\n  Latch latch;\n  Latch::Handle handle = latch.Init();\n  // Dropping a copy doesn't satisfy the latch.\n  Latch::Handle handle_copy = handle;\n  EXPECT_FALSE(std::move(handle_copy).Drop());\n  // Can create more copies even after we start dropping.\n  Latch::Handle handle_copy2 = handle;\n  EXPECT_FALSE(std::move(handle_copy2).Drop());\n  // Now drop the last handle.\n  EXPECT_TRUE(std::move(handle).Drop());\n}\n\n// Tests that the on-zero callback is called.\nTEST(LatchTest, OnZeroCallback) {\n  Latch latch;\n  bool called = false;\n  Latch::Handle handle = latch.Init([&] { called = true; });\n  Latch::Handle handle2 = handle;\n  Latch::Handle handle3 = handle;\n\n  EXPECT_FALSE(called);\n  EXPECT_FALSE(std::move(handle).Drop());\n  EXPECT_FALSE(called);\n  EXPECT_FALSE(std::move(handle2).Drop());\n  EXPECT_FALSE(called);\n  EXPECT_TRUE(std::move(handle3).Drop());\n  EXPECT_TRUE(called);\n}\n\n// Tests moving a handle.\nTEST(LatchTest, MoveHandle) {\n  Latch latch;\n  bool called = false;\n  Latch::Handle handle = latch.Init([&] { called = true; });\n  Latch::Handle handle2 = std::move(handle);\n\n  // Check that dropping the new handle satisfies the latch.\n  EXPECT_FALSE(called);\n  EXPECT_TRUE(std::move(handle2).Drop());\n  EXPECT_TRUE(called);\n}\n\n// Test that creating and destroying a handle without dropping works.\nTEST(LatchTest, Destructor) {\n  Latch latch;\n  bool called = false;\n  Latch::Handle handle = latch.Init([&] { called = true; });\n  {\n    // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)\n    Latch::Handle handle2 = handle;\n    EXPECT_FALSE(called);\n  }\n  EXPECT_FALSE(called);\n  EXPECT_TRUE(std::move(handle).Drop());\n  EXPECT_TRUE(called);\n}\n\n// Tests calling `Init` more than once.\nTEST(LatchTest, Reuse) {\n  Latch latch;\n  bool called = false;\n  Latch::Handle handle = latch.Init([&] { called = true; });\n  Latch::Handle handle2 = handle;\n\n  EXPECT_FALSE(called);\n  EXPECT_FALSE(std::move(handle).Drop());\n  EXPECT_FALSE(called);\n  EXPECT_TRUE(std::move(handle2).Drop());\n  EXPECT_TRUE(called);\n\n  // Now initialize the latch again with a new closure.\n  bool called2 = false;\n  Latch::Handle handle3 = latch.Init([&] { called2 = true; });\n  Latch::Handle handle4 = handle3;\n\n  EXPECT_FALSE(called2);\n  EXPECT_FALSE(std::move(handle3).Drop());\n  EXPECT_FALSE(called2);\n  EXPECT_TRUE(std::move(handle4).Drop());\n  EXPECT_TRUE(called2);\n}\n\n// Tests the latch with multiple threads.\nTEST(LatchTest, MultiThreaded) {\n  Latch latch;\n  std::atomic<int> counter = 0;\n  bool called = false;\n  constexpr int NumThreads = 5;\n\n  // The `on_zero` callback will be executed by the last thread to drop its\n  // handle.\n  auto handle = latch.Init([&] {\n    // Check that all threads have done their work.\n    EXPECT_EQ(counter.load(), NumThreads);\n    called = true;\n  });\n\n  std::vector<std::thread> threads;\n  threads.reserve(NumThreads);\n  for (int i = 0; i < NumThreads; ++i) {\n    threads.emplace_back([&, handle_copy = handle] {\n      // Each thread has its own copy of the handle.\n      // Simulate some work.\n      std::this_thread::sleep_for(std::chrono::milliseconds(10));\n      counter++;\n      // The handle is dropped when the thread exits.\n    });\n  }\n\n  // Drop the main thread's handle.\n  std::move(handle).Drop();\n\n  for (auto& thread : threads) {\n    thread.join();\n  }\n  EXPECT_TRUE(called);\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/map.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_MAP_H_\n#define CARBON_COMMON_MAP_H_\n\n#include <algorithm>\n#include <concepts>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/concepts.h\"\n#include \"common/hashtable_key_context.h\"\n#include \"common/raw_hashtable.h\"\n#include \"llvm/Support/Compiler.h\"\n\nnamespace Carbon {\n\n// Forward declarations to resolve cyclic references.\ntemplate <typename KeyT, typename ValueT, typename KeyContextT>\nclass MapView;\ntemplate <typename KeyT, typename ValueT, typename KeyContextT>\nclass MapBase;\ntemplate <typename KeyT, typename ValueT, ssize_t SmallSize,\n          typename KeyContextT>\nclass Map;\n\n// A read-only view type for a map from key to value.\n//\n// This view is a cheap-to-copy type that should be passed by value, but\n// provides view or read-only reference semantics to the underlying map data\n// structure.\n//\n// This should always be preferred to a `const`-ref parameter for the `MapBase`\n// or `Map` type as it provides more flexibility and a cleaner API. By default a\n// `MapView` provides no more immutability than a `const Map`: elements can't be\n// added or removed, but both keys and values can be mutated, and the user is\n// responsible for avoiding mutations that affect the key's hash value or\n// equality comparison. However, the key and value types can be\n// `const`-qualified to prevent those mutations. For example, a `MapView<K, V>`\n// can be converted to `MapView<const K, V>` to prevent mutating the keys. As\n// with any other view type, `const` on the `MapView` itself is \"shallow\": it\n// prevents rebinding the `MapView` to a different underlying map, but doesn't\n// affect mutability of the underlying map.\n//\n// A specific `KeyContextT` type can optionally be provided to configure how\n// keys will be hashed and compared. The default is `DefaultKeyContext` which is\n// stateless and will hash using `Carbon::HashValue` and compare using\n// `operator==`. Every method accepting a lookup key or operating on the keys in\n// the table will also accept an instance of this type. For stateless context\n// types, including the default, an instance will be default constructed if not\n// provided to these methods. However, stateful contexts should be constructed\n// and passed in explicitly. The context type should be small and reasonable to\n// pass by value, often a wrapper or pointer to the relevant context needed for\n// hashing and comparing keys. For more details about the key context, see\n// `hashtable_key_context.h`.\ntemplate <typename InputKeyT, typename InputValueT,\n          typename InputKeyContextT = DefaultKeyContext>\nclass MapView\n    : RawHashtable::ViewImpl<InputKeyT, InputValueT, InputKeyContextT> {\n  using ImplT =\n      RawHashtable::ViewImpl<InputKeyT, InputValueT, InputKeyContextT>;\n  using EntryT = typename ImplT::EntryT;\n\n public:\n  using KeyT = typename ImplT::KeyT;\n  using ValueT = typename ImplT::ValueT;\n  using KeyContextT = typename ImplT::KeyContextT;\n  using MetricsT = typename ImplT::MetricsT;\n\n  // This type represents the result of lookup operations. It encodes whether\n  // the lookup was a success as well as accessors for the key and value.\n  class LookupKVResult {\n   public:\n    LookupKVResult() = default;\n    explicit LookupKVResult(EntryT* entry) : entry_(entry) {}\n\n    explicit operator bool() const { return entry_ != nullptr; }\n\n    auto key() const -> KeyT& { return entry_->key(); }\n    auto value() const -> ValueT& { return entry_->value(); }\n\n   private:\n    EntryT* entry_ = nullptr;\n  };\n\n  // Enable implicit conversions that add `const`-ness to either key or value\n  // type. This is always safe to do with a view. We use a template to avoid\n  // needing all 3 versions.\n  template <typename OtherKeyT, typename OtherValueT>\n  explicit(false)\n      MapView(MapView<OtherKeyT, OtherValueT, KeyContextT> other_view)\n    requires(SameAsOneOf<KeyT, OtherKeyT, const OtherKeyT> &&\n             SameAsOneOf<ValueT, OtherValueT, const OtherValueT>)\n      : ImplT(other_view) {}\n\n  // Tests whether a key is present in the map.\n  template <typename LookupKeyT>\n  auto Contains(LookupKeyT lookup_key,\n                KeyContextT key_context = KeyContextT()) const -> bool;\n\n  // Lookup a key in the map.\n  template <typename LookupKeyT>\n  auto Lookup(LookupKeyT lookup_key,\n              KeyContextT key_context = KeyContextT()) const -> LookupKVResult;\n\n  // Lookup a key in the map and try to return a pointer to its value. Returns\n  // null on a missing key.\n  template <typename LookupKeyT>\n  auto operator[](LookupKeyT lookup_key) const -> ValueT*\n    requires(std::default_initializable<KeyContextT>);\n\n  // Run the provided callback for every key and value in the map.\n  template <typename CallbackT>\n  auto ForEach(CallbackT callback) -> void\n    requires(std::invocable<CallbackT, KeyT&, ValueT&>);\n\n  // This routine is relatively inefficient and only intended for use in\n  // benchmarking or logging of performance anomalies. The specific metrics\n  // returned have no specific guarantees beyond being informative in\n  // benchmarks.\n  auto ComputeMetrics(KeyContextT key_context = KeyContextT()) -> MetricsT {\n    return ImplT::ComputeMetricsImpl(key_context);\n  }\n\n private:\n  template <typename MapKeyT, typename MapValueT, ssize_t MinSmallSize,\n            typename KeyContextT>\n  friend class Map;\n  friend class MapBase<KeyT, ValueT, KeyContextT>;\n  friend class MapView<const KeyT, ValueT, KeyContextT>;\n  friend class MapView<KeyT, const ValueT, KeyContextT>;\n  friend class MapView<const KeyT, const ValueT, KeyContextT>;\n\n  MapView() = default;\n  explicit(false) MapView(ImplT base) : ImplT(base) {}\n  MapView(ssize_t size, RawHashtable::Storage* storage)\n      : ImplT(size, storage) {}\n};\n\n// A base class for a `Map` type that remains mutable while type-erasing the\n// `SmallSize` (SSO) template parameter.\n//\n// Note that `MapBase` has \"shallow\" const semantics: a `const MapBase<K, V>&`\n// can't be used to mutate the map data structure itself (e.g. by changing the\n// number of elements), but it can be used to mutate the keys and values it\n// contains. The user is responsible for avoiding mutations that would change\n// the hash value or equality of a key. A `MapView` with const-qualified key and\n// value types can be used to provide read-only access to the elements of a\n// `MapBase<T>`.\n//\n// A pointer or reference to this type is the preferred way to pass a mutable\n// handle to a `Map` type across API boundaries as it avoids encoding specific\n// SSO sizing information while providing a near-complete mutable API.\ntemplate <typename InputKeyT, typename InputValueT,\n          typename InputKeyContextT = DefaultKeyContext>\nclass MapBase : protected RawHashtable::BaseImpl<InputKeyT, InputValueT,\n                                                 InputKeyContextT> {\n protected:\n  using ImplT =\n      RawHashtable::BaseImpl<InputKeyT, InputValueT, InputKeyContextT>;\n  using EntryT = typename ImplT::EntryT;\n\n public:\n  using KeyT = typename ImplT::KeyT;\n  using ValueT = typename ImplT::ValueT;\n  using KeyContextT = typename ImplT::KeyContextT;\n  using ViewT = MapView<KeyT, ValueT, KeyContextT>;\n  using LookupKVResult = typename ViewT::LookupKVResult;\n  using MetricsT = typename ImplT::MetricsT;\n\n  // The result type for insertion operations both indicates whether an insert\n  // was needed (as opposed to finding an existing element), and provides access\n  // to the element's key and value.\n  class InsertKVResult {\n   public:\n    InsertKVResult() = default;\n    explicit InsertKVResult(bool inserted, EntryT& entry)\n        : entry_(&entry), inserted_(inserted) {}\n\n    auto is_inserted() const -> bool { return inserted_; }\n\n    auto key() const -> KeyT& { return entry_->key(); }\n    auto value() const -> ValueT& { return entry_->value(); }\n\n   private:\n    EntryT* entry_;\n    bool inserted_;\n  };\n\n  // Implicitly convertible to the relevant view type.\n  //\n  // NOLINTNEXTLINE(google-explicit-constructor): Designed to implicitly decay.\n  explicit(false) operator ViewT() const { return this->view_impl(); }\n\n  // We can't chain the above conversion with the conversions on `ViewT` to add\n  // const, so explicitly support adding const to produce a view here.\n  template <typename OtherKeyT, typename OtherValueT>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  explicit(false) operator MapView<OtherKeyT, OtherValueT, KeyContextT>() const\n    requires(SameAsOneOf<OtherKeyT, KeyT, const KeyT> &&\n             SameAsOneOf<OtherValueT, ValueT, const ValueT>)\n  {\n    return ViewT(*this);\n  }\n\n  // Convenience forwarder to the view type.\n  template <typename LookupKeyT>\n  auto Contains(LookupKeyT lookup_key,\n                KeyContextT key_context = KeyContextT()) const -> bool {\n    return ViewT(*this).Contains(lookup_key, key_context);\n  }\n\n  // Convenience forwarder to the view type.\n  template <typename LookupKeyT>\n  auto Lookup(LookupKeyT lookup_key,\n              KeyContextT key_context = KeyContextT()) const -> LookupKVResult {\n    return ViewT(*this).Lookup(lookup_key, key_context);\n  }\n\n  // Convenience forwarder to the view type.\n  template <typename LookupKeyT>\n  auto operator[](LookupKeyT lookup_key) const -> ValueT*\n    requires(std::default_initializable<KeyContextT>)\n  {\n    return ViewT(*this)[lookup_key];\n  }\n\n  // Convenience forwarder to the view type.\n  template <typename CallbackT>\n  auto ForEach(CallbackT callback) const -> void\n    requires(std::invocable<CallbackT, KeyT&, ValueT&>)\n  {\n    return ViewT(*this).ForEach(callback);\n  }\n\n  // Convenience forwarder to the view type.\n  auto ComputeMetrics(KeyContextT key_context = KeyContextT()) const\n      -> MetricsT {\n    return ViewT(*this).ComputeMetrics(key_context);\n  }\n\n  // Insert a key and value into the map. If the key is already present, the new\n  // value is discarded and the existing value preserved.\n  template <typename LookupKeyT>\n  auto Insert(LookupKeyT lookup_key, ValueT new_v,\n              KeyContextT key_context = KeyContextT()) -> InsertKVResult;\n\n  // Insert a key into the map and call the provided callback if necessary to\n  // produce a new value when no existing value is found.\n  //\n  // Example: `m.Insert(key, [] { return default_value; });`\n  //\n  // TODO: The `;` formatting below appears to be bugs in clang-format with\n  // concepts that should be filed upstream.\n  template <typename LookupKeyT, typename ValueCallbackT>\n  auto Insert(LookupKeyT lookup_key, ValueCallbackT value_cb,\n              KeyContextT key_context = KeyContextT()) -> InsertKVResult\n    requires(\n        !std::same_as<ValueT, ValueCallbackT> &&\n        std::convertible_to<decltype(std::declval<ValueCallbackT>()()), ValueT>)\n  ;\n\n  // Lookup a key in the map and if missing insert it and call the provided\n  // callback to in-place construct both the key and value. The lookup key is\n  // passed through to the callback so it needn't be captured and can be kept in\n  // a register argument throughout.\n  //\n  // Example:\n  // ```cpp\n  //   m.Insert(\"widget\", [](MyStringViewType lookup_key, void* key_storage,\n  //                         void* value_storage) {\n  //     new (key_storage) MyStringType(lookup_key);\n  //     new (value_storage) MyValueType(....);\n  //   });\n  // ```\n  template <typename LookupKeyT, typename InsertCallbackT>\n  auto Insert(LookupKeyT lookup_key, InsertCallbackT insert_cb,\n              KeyContextT key_context = KeyContextT()) -> InsertKVResult\n    requires(!std::same_as<ValueT, InsertCallbackT> &&\n             std::invocable<InsertCallbackT, LookupKeyT, void*, void*>);\n\n  // Replace a key's value in a map if already present or insert it if not\n  // already present. The new value is always used.\n  template <typename LookupKeyT>\n  auto Update(LookupKeyT lookup_key, ValueT new_v,\n              KeyContextT key_context = KeyContextT()) -> InsertKVResult;\n\n  // Lookup or insert a key into the map, and set it's value to the result of\n  // the `value_cb` callback. The callback is always run and its result is\n  // always used, whether the key was already in the map or not. Any existing\n  // value is replaced with the result.\n  //\n  // Example: `m.Update(key, [] { return new_value; });`\n  template <typename LookupKeyT, typename ValueCallbackT>\n  auto Update(LookupKeyT lookup_key, ValueCallbackT value_cb,\n              KeyContextT key_context = KeyContextT()) -> InsertKVResult\n    requires(\n        !std::same_as<ValueT, ValueCallbackT> &&\n        std::convertible_to<decltype(std::declval<ValueCallbackT>()()), ValueT>)\n  ;\n\n  // Lookup or insert a key into the map. If not already present and the key is\n  // inserted, the `insert_cb` is used to construct the new key and value in\n  // place. When inserting, the lookup key is passed through to the callback so\n  // it needn't be captured and can be kept in a register argument throughout.\n  // If the key was already present, the `update_cb` is called to update the\n  // existing key and value as desired.\n  //\n  // Example of counting occurrences:\n  // ```cpp\n  //   m.Update(item, /*insert_cb=*/[](MyStringViewType lookup_key,\n  //                                   void* key_storage, void* value_storage) {\n  //                    new (key_storage) MyItem(lookup_key);\n  //                    new (value_storage) Count(1);\n  //                  },\n  //                  /*update_cb=*/[](MyItem& /*key*/, Count& count) {\n  //                    ++count;\n  //                  });\n  // ```\n  template <typename LookupKeyT, typename InsertCallbackT,\n            typename UpdateCallbackT>\n  auto Update(LookupKeyT lookup_key, InsertCallbackT insert_cb,\n              UpdateCallbackT update_cb,\n              KeyContextT key_context = KeyContextT()) -> InsertKVResult\n    requires(!std::same_as<ValueT, InsertCallbackT> &&\n             std::invocable<InsertCallbackT, LookupKeyT, void*, void*> &&\n             std::invocable<UpdateCallbackT, KeyT&, ValueT&>);\n\n  // Grow the map to a specific allocation size.\n  //\n  // This will grow the map's hashtable if necessary for it to have an\n  // allocation size of `target_alloc_size` which must be a power of two. Note\n  // that this will not allow that many keys to be inserted, but a smaller\n  // number based on the maximum load factor. If a specific number of insertions\n  // need to be achieved without triggering growth, use the `GrowForInsertCount`\n  // method.\n  auto GrowToAllocSize(ssize_t target_alloc_size,\n                       KeyContextT key_context = KeyContextT()) -> void;\n\n  // Grow the map sufficiently to allow inserting the specified number of keys.\n  auto GrowForInsertCount(ssize_t count,\n                          KeyContextT key_context = KeyContextT()) -> void;\n\n  // Erase a key from the map.\n  template <typename LookupKeyT>\n  auto Erase(LookupKeyT lookup_key, KeyContextT key_context = KeyContextT())\n      -> bool;\n\n  // Clear all key/value pairs from the map but leave the underlying hashtable\n  // allocated and in place.\n  auto Clear() -> void;\n\n protected:\n  using ImplT::ImplT;\n};\n\n// A data structure mapping from key to value.\n//\n// This map also supports small size optimization (or \"SSO\"). The provided\n// `SmallSize` type parameter indicates the size of an embedded buffer for\n// storing maps small enough to fit. The default is zero, which always allocates\n// a heap buffer on construction. When non-zero, must be a multiple of the\n// `MaxGroupSize` which is currently 16. The library will check that the size is\n// valid and provide an error at compile time if not. We don't automatically\n// select the next multiple or otherwise fit the size to the constraints to make\n// it clear in the code how much memory is used by the SSO buffer.\n//\n// This data structure optimizes heavily for small key types that are cheap to\n// move and even copy. Using types with large keys or expensive to copy keys may\n// create surprising performance bottlenecks. A `std::string` key should be fine\n// with generally small strings, but if some or many strings are large heap\n// allocations the performance of hashtable routines may be unacceptably bad and\n// another data structure or key design is likely preferable.\n//\n// Note that like `MapBase`, `Map` has \"shallow\" const semantics. Note also that\n// this type should typically not appear on API boundaries; either `MapBase` or\n// `MapView` should be used instead.\ntemplate <typename InputKeyT, typename InputValueT, ssize_t SmallSize = 0,\n          typename InputKeyContextT = DefaultKeyContext>\nclass Map : public RawHashtable::TableImpl<\n                MapBase<InputKeyT, InputValueT, InputKeyContextT>, SmallSize> {\n  using BaseT = MapBase<InputKeyT, InputValueT, InputKeyContextT>;\n  using ImplT = RawHashtable::TableImpl<BaseT, SmallSize>;\n\n public:\n  using KeyT = typename BaseT::KeyT;\n  using ValueT = typename BaseT::ValueT;\n\n  Map() = default;\n  Map(const Map& arg) = default;\n  Map(Map&& arg) noexcept = default;\n  auto operator=(const Map& arg) -> Map& = default;\n  auto operator=(Map&& arg) noexcept -> Map& = default;\n\n  // Reset the entire state of the hashtable to as it was when constructed,\n  // throwing away any intervening allocations.\n  auto Reset() -> void;\n};\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto MapView<InputKeyT, InputValueT, InputKeyContextT>::Contains(\n    LookupKeyT lookup_key, KeyContextT key_context) const -> bool {\n  return this->LookupEntry(lookup_key, key_context) != nullptr;\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto MapView<InputKeyT, InputValueT, InputKeyContextT>::Lookup(\n    LookupKeyT lookup_key, KeyContextT key_context) const -> LookupKVResult {\n  return LookupKVResult(this->LookupEntry(lookup_key, key_context));\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto MapView<InputKeyT, InputValueT, InputKeyContextT>::operator[](\n    LookupKeyT lookup_key) const -> ValueT*\n  requires(std::default_initializable<KeyContextT>)\n{\n  auto result = Lookup(lookup_key, KeyContextT());\n  return result ? &result.value() : nullptr;\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename CallbackT>\nauto MapView<InputKeyT, InputValueT, InputKeyContextT>::ForEach(\n    CallbackT callback) -> void\n  requires(std::invocable<CallbackT, KeyT&, ValueT&>)\n{\n  this->ForEachEntry(\n      [callback](EntryT& entry) { callback(entry.key(), entry.value()); },\n      [](auto...) {});\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\n[[clang::always_inline]] auto\nMapBase<InputKeyT, InputValueT, InputKeyContextT>::Insert(\n    LookupKeyT lookup_key, ValueT new_v, KeyContextT key_context)\n    -> InsertKVResult {\n  return Insert(\n      lookup_key,\n      [&new_v](LookupKeyT lookup_key, void* key_storage, void* value_storage) {\n        new (key_storage) KeyT(lookup_key);\n        new (value_storage) ValueT(std::move(new_v));\n      },\n      key_context);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT, typename ValueCallbackT>\n[[clang::always_inline]] auto\nMapBase<InputKeyT, InputValueT, InputKeyContextT>::Insert(\n    LookupKeyT lookup_key, ValueCallbackT value_cb, KeyContextT key_context)\n    -> InsertKVResult\n  requires(\n      !std::same_as<ValueT, ValueCallbackT> &&\n      std::convertible_to<decltype(std::declval<ValueCallbackT>()()), ValueT>)\n{\n  return Insert(\n      lookup_key,\n      [&value_cb](LookupKeyT lookup_key, void* key_storage,\n                  void* value_storage) {\n        new (key_storage) KeyT(lookup_key);\n        new (value_storage) ValueT(value_cb());\n      },\n      key_context);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT, typename InsertCallbackT>\n[[clang::always_inline]] auto\nMapBase<InputKeyT, InputValueT, InputKeyContextT>::Insert(\n    LookupKeyT lookup_key, InsertCallbackT insert_cb, KeyContextT key_context)\n    -> InsertKVResult\n  requires(!std::same_as<ValueT, InsertCallbackT> &&\n           std::invocable<InsertCallbackT, LookupKeyT, void*, void*>)\n{\n  auto [entry, inserted] = this->InsertImpl(lookup_key, key_context);\n  CARBON_DCHECK(entry, \"Should always result in a valid index.\");\n\n  if (LLVM_LIKELY(!inserted)) {\n    return InsertKVResult(false, *entry);\n  }\n\n  insert_cb(lookup_key, static_cast<void*>(&entry->key_storage),\n            static_cast<void*>(&entry->value_storage));\n  return InsertKVResult(true, *entry);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\n[[clang::always_inline]] auto\nMapBase<InputKeyT, InputValueT, InputKeyContextT>::Update(\n    LookupKeyT lookup_key, ValueT new_v, KeyContextT key_context)\n    -> InsertKVResult {\n  return Update(\n      lookup_key,\n      [&new_v](LookupKeyT lookup_key, void* key_storage, void* value_storage) {\n        new (key_storage) KeyT(lookup_key);\n        new (value_storage) ValueT(std::move(new_v));\n      },\n      [&new_v](KeyT& /*key*/, ValueT& value) {\n        value.~ValueT();\n        new (&value) ValueT(std::move(new_v));\n      },\n      key_context);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT, typename ValueCallbackT>\n[[clang::always_inline]] auto\nMapBase<InputKeyT, InputValueT, InputKeyContextT>::Update(\n    LookupKeyT lookup_key, ValueCallbackT value_cb, KeyContextT key_context)\n    -> InsertKVResult\n  requires(\n      !std::same_as<ValueT, ValueCallbackT> &&\n      std::convertible_to<decltype(std::declval<ValueCallbackT>()()), ValueT>)\n{\n  return Update(\n      lookup_key,\n      [&value_cb](LookupKeyT lookup_key, void* key_storage,\n                  void* value_storage) {\n        new (key_storage) KeyT(lookup_key);\n        new (value_storage) ValueT(value_cb());\n      },\n      [&value_cb](KeyT& /*key*/, ValueT& value) {\n        value.~ValueT();\n        new (&value) ValueT(value_cb());\n      },\n      key_context);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT, typename InsertCallbackT,\n          typename UpdateCallbackT>\n[[clang::always_inline]] auto\nMapBase<InputKeyT, InputValueT, InputKeyContextT>::Update(\n    LookupKeyT lookup_key, InsertCallbackT insert_cb, UpdateCallbackT update_cb,\n    KeyContextT key_context) -> InsertKVResult\n  requires(!std::same_as<ValueT, InsertCallbackT> &&\n           std::invocable<InsertCallbackT, LookupKeyT, void*, void*> &&\n           std::invocable<UpdateCallbackT, KeyT&, ValueT&>)\n{\n  auto [entry, inserted] = this->InsertImpl(lookup_key, key_context);\n  CARBON_DCHECK(entry, \"Should always result in a valid index.\");\n\n  if (LLVM_LIKELY(!inserted)) {\n    update_cb(entry->key(), entry->value());\n    return InsertKVResult(false, *entry);\n  }\n\n  insert_cb(lookup_key, static_cast<void*>(&entry->key_storage),\n            static_cast<void*>(&entry->value_storage));\n  return InsertKVResult(true, *entry);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto MapBase<InputKeyT, InputValueT, InputKeyContextT>::GrowToAllocSize(\n    ssize_t target_alloc_size, KeyContextT key_context) -> void {\n  this->GrowToAllocSizeImpl(target_alloc_size, key_context);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto MapBase<InputKeyT, InputValueT, InputKeyContextT>::GrowForInsertCount(\n    ssize_t count, KeyContextT key_context) -> void {\n  this->GrowForInsertCountImpl(count, key_context);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto MapBase<InputKeyT, InputValueT, InputKeyContextT>::Erase(\n    LookupKeyT lookup_key, KeyContextT key_context) -> bool {\n  return this->EraseImpl(lookup_key, key_context);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto MapBase<InputKeyT, InputValueT, InputKeyContextT>::Clear() -> void {\n  this->ClearImpl();\n}\n\ntemplate <typename InputKeyT, typename InputValueT, ssize_t SmallSize,\n          typename InputKeyContextT>\nauto Map<InputKeyT, InputValueT, SmallSize, InputKeyContextT>::Reset() -> void {\n  this->ResetImpl();\n}\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_MAP_H_\n"
  },
  {
    "path": "common/map_benchmark.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <benchmark/benchmark.h>\n\n#include <boost/unordered/unordered_flat_map.hpp>\n#include <type_traits>\n\n#include \"absl/container/flat_hash_map.h\"\n#include \"common/map.h\"\n#include \"common/raw_hashtable_benchmark_helpers.h\"\n#include \"llvm/ADT/DenseMap.h\"\n\nnamespace Carbon {\nnamespace {\n\nusing RawHashtable::CarbonHashDI;\nusing RawHashtable::GetKeysAndHitKeys;\nusing RawHashtable::GetKeysAndMissKeys;\nusing RawHashtable::HitArgs;\nusing RawHashtable::LowZeroBitInt;\nusing RawHashtable::ReportTableMetrics;\nusing RawHashtable::SizeArgs;\nusing RawHashtable::ValueToBool;\n\n// Helpers to synthesize some value of one of the three types we use as value\n// types.\ntemplate <typename T>\nauto MakeValue() -> T {\n  if constexpr (std::is_same_v<T, llvm::StringRef>) {\n    return \"abc\";\n  } else if constexpr (std::is_pointer_v<T>) {\n    static std::remove_pointer_t<T> x;\n    return &x;\n  } else {\n    return 42;\n  }\n}\ntemplate <typename T>\nauto MakeValue2() -> T {\n  if constexpr (std::is_same_v<T, llvm::StringRef>) {\n    return \"qux\";\n  } else if constexpr (std::is_pointer_v<T>) {\n    static std::remove_pointer_t<T> y;\n    return &y;\n  } else {\n    return 7;\n  }\n}\n\ntemplate <typename MapT>\nstruct IsCarbonMapImpl : std::false_type {};\ntemplate <typename KT, typename VT, int MinSmallSize>\nstruct IsCarbonMapImpl<Map<KT, VT, MinSmallSize>> : std::true_type {};\n\ntemplate <typename MapWrapperT>\nstatic constexpr bool IsCarbonMap =\n    IsCarbonMapImpl<typename MapWrapperT::MapT>::value;\n\n// A wrapper around various map types that we specialize to implement a common\n// API used in the benchmarks for various different map data structures that\n// support different APIs. The primary template assumes a roughly\n// `std::unordered_map` API design, and types with a different API design are\n// supported through specializations.\ntemplate <typename InMapT>\nstruct MapWrapperImpl {\n  using MapT = InMapT;\n  using KeyT = typename MapT::key_type;\n  using ValueT = typename MapT::mapped_type;\n\n  MapT m;\n\n  auto BenchContains(KeyT k) -> bool { return m.find(k) != m.end(); }\n\n  auto BenchLookup(KeyT k) -> bool {\n    auto it = m.find(k);\n    if (it == m.end()) {\n      return false;\n    }\n    return ValueToBool(it->second);\n  }\n\n  auto BenchInsert(KeyT k, ValueT v) -> bool {\n    auto result = m.insert({k, v});\n    return result.second;\n  }\n\n  auto BenchUpdate(KeyT k, ValueT v) -> bool {\n    auto result = m.insert({k, v});\n    result.first->second = v;\n    return result.second;\n  }\n\n  auto BenchErase(KeyT k) -> bool { return m.erase(k) != 0; }\n};\n\n// Explicit (partial) specialization for the Carbon map type that uses its\n// different API design.\ntemplate <typename KT, typename VT, int MinSmallSize>\nstruct MapWrapperImpl<Map<KT, VT, MinSmallSize>> {\n  using MapT = Map<KT, VT, MinSmallSize>;\n  using KeyT = KT;\n  using ValueT = VT;\n\n  MapT m;\n\n  auto BenchContains(KeyT k) -> bool { return m.Contains(k); }\n\n  auto BenchLookup(KeyT k) -> bool {\n    auto result = m.Lookup(k);\n    if (!result) {\n      return false;\n    }\n    return ValueToBool(result.value());\n  }\n\n  auto BenchInsert(KeyT k, ValueT v) -> bool {\n    auto result = m.Insert(k, v);\n    return result.is_inserted();\n  }\n\n  auto BenchUpdate(KeyT k, ValueT v) -> bool {\n    auto result = m.Update(k, v);\n    return result.is_inserted();\n  }\n\n  auto BenchErase(KeyT k) -> bool { return m.Erase(k); }\n};\n\n// Provide a way to override the Carbon Map specific benchmark runs with another\n// hashtable implementation. When building, you can use one of these enum names\n// in a macro define such as `-DCARBON_MAP_BENCH_OVERRIDE=Name` in order to\n// trigger a specific override for the `Map` type benchmarks. This is used to\n// get before/after runs that compare the performance of Carbon's Map versus\n// other implementations.\nenum class MapOverride : uint8_t {\n  None,\n  Abseil,\n  Boost,\n  LLVM,\n  LLVMAndCarbonHash,\n};\n#ifndef CARBON_MAP_BENCH_OVERRIDE\n#define CARBON_MAP_BENCH_OVERRIDE None\n#endif\n\ntemplate <typename MapT, MapOverride Override>\nstruct MapWrapperOverride : MapWrapperImpl<MapT> {};\n\ntemplate <typename KeyT, typename ValueT, int MinSmallSize>\nstruct MapWrapperOverride<Map<KeyT, ValueT, MinSmallSize>, MapOverride::Abseil>\n    : MapWrapperImpl<absl::flat_hash_map<KeyT, ValueT>> {};\n\ntemplate <typename KeyT, typename ValueT, int MinSmallSize>\nstruct MapWrapperOverride<Map<KeyT, ValueT, MinSmallSize>, MapOverride::Boost>\n    : MapWrapperImpl<boost::unordered::unordered_flat_map<KeyT, ValueT>> {};\n\ntemplate <typename KeyT, typename ValueT, int MinSmallSize>\nstruct MapWrapperOverride<Map<KeyT, ValueT, MinSmallSize>, MapOverride::LLVM>\n    : MapWrapperImpl<llvm::DenseMap<KeyT, ValueT>> {};\n\ntemplate <typename KeyT, typename ValueT, int MinSmallSize>\nstruct MapWrapperOverride<Map<KeyT, ValueT, MinSmallSize>,\n                          MapOverride::LLVMAndCarbonHash>\n    : MapWrapperImpl<llvm::DenseMap<KeyT, ValueT, CarbonHashDI<KeyT>>> {};\n\ntemplate <typename MapT>\nusing MapWrapper =\n    MapWrapperOverride<MapT, MapOverride::CARBON_MAP_BENCH_OVERRIDE>;\n\ntemplate <typename MapT>\nauto ReportMetrics(const MapWrapper<MapT>& m_wrapper, benchmark::State& state)\n    -> void {\n  // Report some extra statistics about the Carbon type.\n  if constexpr (IsCarbonMap<MapWrapper<MapT>>) {\n    ReportTableMetrics(m_wrapper.m, state);\n  }\n}\n\n// NOLINTBEGIN(bugprone-macro-parentheses): Parentheses are incorrect here.\n#define MAP_BENCHMARK_ONE_OP_SIZE(NAME, APPLY, KT, VT)                         \\\n  BENCHMARK(NAME<Map<KT, VT>>)->Apply(APPLY);                                  \\\n  BENCHMARK(NAME<absl::flat_hash_map<KT, VT>>)->Apply(APPLY);                  \\\n  BENCHMARK(NAME<boost::unordered::unordered_flat_map<KT, VT>>)->Apply(APPLY); \\\n  BENCHMARK(NAME<llvm::DenseMap<KT, VT>>)->Apply(APPLY);                       \\\n  BENCHMARK(NAME<llvm::DenseMap<KT, VT, CarbonHashDI<KT>>>)->Apply(APPLY)\n// NOLINTEND(bugprone-macro-parentheses)\n\n#define MAP_BENCHMARK_ONE_OP(NAME, APPLY)                       \\\n  MAP_BENCHMARK_ONE_OP_SIZE(NAME, APPLY, int, int);             \\\n  MAP_BENCHMARK_ONE_OP_SIZE(NAME, APPLY, int*, int*);           \\\n  MAP_BENCHMARK_ONE_OP_SIZE(NAME, APPLY, int, llvm::StringRef); \\\n  MAP_BENCHMARK_ONE_OP_SIZE(NAME, APPLY, llvm::StringRef, int)\n\n// Benchmark the minimal latency of checking if a key is contained within a map,\n// when it *is* definitely in that map. Because this is only really measuring\n// the *minimal* latency, it is more similar to a throughput benchmark.\n//\n// While this is structured to observe the latency of testing for presence of a\n// key, it is important to understand the reality of what this measures. Because\n// the boolean result testing for whether a key is in a map is fundamentally\n// provided not by accessing some data, but by branching on data to a control\n// flow path which sets the boolean to `true` or `false`, the result can be\n// speculatively provided based on predicting the conditional branch without\n// waiting for the results of the comparison to become available. And because\n// this is a small operation and we arrange for all the candidate keys to be\n// present, that branch *should* be predicted extremely well. The result is that\n// this measures the un-speculated latency of testing for presence which should\n// be small or zero. Which is why this is ultimately more similar to a\n// throughput benchmark.\n//\n// Because of these measurement oddities, the specific measurements here may not\n// be very interesting for predicting real-world performance in any way, but\n// they are useful for comparing how 'cheap' the operation is across changes to\n// the data structure or between similar data structures with similar\n// properties.\ntemplate <typename MapT>\nstatic void BM_MapContainsHit(benchmark::State& state) {\n  using MapWrapperT = MapWrapper<MapT>;\n  using KT = typename MapWrapperT::KeyT;\n  using VT = typename MapWrapperT::ValueT;\n  MapWrapperT m;\n  auto [keys, lookup_keys] =\n      GetKeysAndHitKeys<KT>(state.range(0), state.range(1));\n  for (auto k : keys) {\n    m.BenchInsert(k, MakeValue<VT>());\n  }\n  ssize_t lookup_keys_size = lookup_keys.size();\n\n  while (state.KeepRunningBatch(lookup_keys_size)) {\n    for (ssize_t i = 0; i < lookup_keys_size;) {\n      // We block optimizing `i` as that has proven both more effective at\n      // blocking the loop from being optimized away and avoiding disruption of\n      // the generated code that we're benchmarking.\n      benchmark::DoNotOptimize(i);\n\n      bool result = m.BenchContains(lookup_keys[i]);\n      CARBON_DCHECK(result);\n      // We use the lookup success to step through keys, establishing a\n      // dependency between each lookup. This doesn't fully allow us to measure\n      // latency rather than throughput, as noted above.\n      i += static_cast<ssize_t>(result);\n    }\n  }\n\n  ReportMetrics(m, state);\n}\nMAP_BENCHMARK_ONE_OP(BM_MapContainsHit, HitArgs);\n\n// Similar to `BM_MapContainsHit`, while this is structured as a latency\n// benchmark, the critical path is expected to be well predicted and so it\n// should turn into something closer to a throughput benchmark.\ntemplate <typename MapT>\nstatic void BM_MapContainsMiss(benchmark::State& state) {\n  using MapWrapperT = MapWrapper<MapT>;\n  using KT = typename MapWrapperT::KeyT;\n  using VT = typename MapWrapperT::ValueT;\n  MapWrapperT m;\n  auto [keys, lookup_keys] = GetKeysAndMissKeys<KT>(state.range(0));\n  for (auto k : keys) {\n    m.BenchInsert(k, MakeValue<VT>());\n  }\n  ssize_t lookup_keys_size = lookup_keys.size();\n\n  while (state.KeepRunningBatch(lookup_keys_size)) {\n    for (ssize_t i = 0; i < lookup_keys_size;) {\n      benchmark::DoNotOptimize(i);\n\n      bool result = m.BenchContains(lookup_keys[i]);\n      CARBON_DCHECK(!result);\n      i += static_cast<ssize_t>(!result);\n    }\n  }\n\n  ReportMetrics(m, state);\n}\nMAP_BENCHMARK_ONE_OP(BM_MapContainsMiss, SizeArgs);\n\n// This is a genuine latency benchmark. We lookup a key in the hashtable and use\n// the value associated with that key in the critical path of loading the next\n// iteration's key. We still ensure the keys are always present, and so we\n// generally expect the data structure branches to be well predicted. But we\n// vary the keys aggressively to avoid any prediction artifacts from repeatedly\n// examining the same key.\n//\n// This latency can be very helpful for understanding a range of data structure\n// behaviors:\n// - Many users of hashtables are directly dependent on the latency of this\n//   operation, and this micro-benchmark will reflect the expected latency for\n//   them.\n// - Showing how latency varies across different sizes of table and different\n//   fractions of the table being accessed (and thus needing space in the\n//   cache).\n//\n// However, it remains an ultimately synthetic and unrepresentative benchmark.\n// It should primarily be used to understand the relative cost of these\n// operations between versions of the data structure or between related data\n// structures.\n//\n// We vary both the number of entries in the table and the number of distinct\n// keys used when doing lookups. As the table becomes large, the latter dictates\n// the fraction of the table that will be accessed and thus the working set size\n// of the benchmark. Querying the same small number of keys in even a large\n// table doesn't actually encounter any cache pressure, so only a few of these\n// benchmarks will show any effects of the caching subsystem.\ntemplate <typename MapT>\nstatic void BM_MapLookupHit(benchmark::State& state) {\n  using MapWrapperT = MapWrapper<MapT>;\n  using KT = typename MapWrapperT::KeyT;\n  using VT = typename MapWrapperT::ValueT;\n  MapWrapperT m;\n  auto [keys, lookup_keys] =\n      GetKeysAndHitKeys<KT>(state.range(0), state.range(1));\n  for (auto k : keys) {\n    m.BenchInsert(k, MakeValue<VT>());\n  }\n  ssize_t lookup_keys_size = lookup_keys.size();\n\n  while (state.KeepRunningBatch(lookup_keys_size)) {\n    for (ssize_t i = 0; i < lookup_keys_size;) {\n      benchmark::DoNotOptimize(i);\n\n      bool result = m.BenchLookup(lookup_keys[i]);\n      CARBON_DCHECK(result);\n      i += static_cast<ssize_t>(result);\n    }\n  }\n\n  ReportMetrics(m, state);\n}\nMAP_BENCHMARK_ONE_OP(BM_MapLookupHit, HitArgs);\n\n// We also do some minimal benchmarking with integers that have a\n// large number of low zero bits shifted into them. These present particular\n// challenges to the hashing strategy Carbon's hash tables use and so they help\n// form stress tests and benchmark to make sure the hash function quality\n// remains reasonable even under adverse conditions. We can't go past a certain\n// limit here without our hash tables becoming impossibly slow due to complete\n// collapse of the hash functions -- if we ever need to hash integers with more\n// than 32 low zero bits, we'll ask that code to use a custom hash algorithm.\n//\n// We don't benchmark these everywhere as they only provide marginal information\n// beyond the core types, and checking just this operation covers that\n// sufficiently.\nMAP_BENCHMARK_ONE_OP_SIZE(BM_MapLookupHit, HitArgs, LowZeroBitInt<12>, int);\nMAP_BENCHMARK_ONE_OP_SIZE(BM_MapLookupHit, HitArgs, LowZeroBitInt<24>, int);\nMAP_BENCHMARK_ONE_OP_SIZE(BM_MapLookupHit, HitArgs, LowZeroBitInt<32>, int);\n\n// This is an update throughput benchmark in practice. While whether the key was\n// a hit is kept in the critical path, we only use keys that are hits and so\n// expect that to be fully predicted and speculated.\n//\n// However, we expect this fairly closely matches how user code interacts with\n// an update-style API. It will have some conditional testing (even if just an\n// assert) on whether the key was a hit and otherwise continue executing. As a\n// consequence the actual update is expected to not be in a meaningful critical\n// path.\n//\n// This still provides a basic way to measure the cost of this operation,\n// especially when comparing between implementations or across different hash\n// tables.\ntemplate <typename MapT>\nstatic void BM_MapUpdateHit(benchmark::State& state) {\n  using MapWrapperT = MapWrapper<MapT>;\n  using KT = typename MapWrapperT::KeyT;\n  using VT = typename MapWrapperT::ValueT;\n  MapWrapperT m;\n  auto [keys, lookup_keys] =\n      GetKeysAndHitKeys<KT>(state.range(0), state.range(1));\n  for (auto k : keys) {\n    m.BenchInsert(k, MakeValue<VT>());\n  }\n  ssize_t lookup_keys_size = lookup_keys.size();\n\n  while (state.KeepRunningBatch(lookup_keys_size)) {\n    for (ssize_t i = 0; i < lookup_keys_size; ++i) {\n      benchmark::DoNotOptimize(i);\n\n      bool inserted = m.BenchUpdate(lookup_keys[i], MakeValue2<VT>());\n      CARBON_DCHECK(!inserted);\n    }\n  }\n\n  ReportMetrics(m, state);\n}\nMAP_BENCHMARK_ONE_OP(BM_MapUpdateHit, HitArgs);\n\n// First erase and then insert the key. The code path will always be the same\n// here and so we expect this to largely be a throughput benchmark because of\n// branch prediction and speculative execution.\n//\n// We don't expect erase followed by insertion to be a common user code\n// sequence, but we don't have a good way of benchmarking either erase or insert\n// in isolation -- each would change the size of the table and thus the next\n// iteration's benchmark. And if we try to correct the table size outside of the\n// timed region, we end up trying to exclude too fine grained of a region from\n// timers to get good measurement data.\n//\n// Our solution is to benchmark both erase and insertion back to back. We can\n// then get a good profile of the code sequence of each, and at least measure\n// the sum cost of these reliably. Careful profiling can help attribute that\n// cost between erase and insert in order to understand which of the two\n// operations is contributing most to any performance artifacts observed.\ntemplate <typename MapT>\nstatic void BM_MapEraseUpdateHit(benchmark::State& state) {\n  using MapWrapperT = MapWrapper<MapT>;\n  using KT = typename MapWrapperT::KeyT;\n  using VT = typename MapWrapperT::ValueT;\n  MapWrapperT m;\n  auto [keys, lookup_keys] =\n      GetKeysAndHitKeys<KT>(state.range(0), state.range(1));\n  for (auto k : keys) {\n    m.BenchInsert(k, MakeValue<VT>());\n  }\n  ssize_t lookup_keys_size = lookup_keys.size();\n\n  while (state.KeepRunningBatch(lookup_keys_size)) {\n    for (ssize_t i = 0; i < lookup_keys_size; ++i) {\n      benchmark::DoNotOptimize(i);\n\n      m.BenchErase(lookup_keys[i]);\n      benchmark::ClobberMemory();\n\n      bool inserted = m.BenchUpdate(lookup_keys[i], MakeValue2<VT>());\n      CARBON_DCHECK(inserted);\n    }\n  }\n}\nMAP_BENCHMARK_ONE_OP(BM_MapEraseUpdateHit, HitArgs);\n\n// NOLINTBEGIN(bugprone-macro-parentheses): Parentheses are incorrect here.\n#define MAP_BENCHMARK_OP_SEQ_SIZE(NAME, KT, VT)                  \\\n  BENCHMARK(NAME<Map<KT, VT>>)->Apply(SizeArgs);                 \\\n  BENCHMARK(NAME<absl::flat_hash_map<KT, VT>>)->Apply(SizeArgs); \\\n  BENCHMARK(NAME<boost::unordered::unordered_flat_map<KT, VT>>)  \\\n      ->Apply(SizeArgs);                                         \\\n  BENCHMARK(NAME<llvm::DenseMap<KT, VT>>)->Apply(APPLY);         \\\n  BENCHMARK(NAME<llvm::DenseMap<KT, VT, CarbonHashDI<KT>>>)->Apply(SizeArgs)\n// NOLINTEND(bugprone-macro-parentheses)\n\n#define MAP_BENCHMARK_OP_SEQ(NAME)                       \\\n  MAP_BENCHMARK_OP_SEQ_SIZE(NAME, int, int);             \\\n  MAP_BENCHMARK_OP_SEQ_SIZE(NAME, int*, int*);           \\\n  MAP_BENCHMARK_OP_SEQ_SIZE(NAME, int, llvm::StringRef); \\\n  MAP_BENCHMARK_OP_SEQ_SIZE(NAME, llvm::StringRef, int)\n\n// This is an interesting, somewhat specialized benchmark that measures the cost\n// of inserting a sequence of key/value pairs into a table with no collisions up\n// to some size and then inserting a colliding key and throwing away the table.\n//\n// This can give an idea of the cost of building up a map of a particular size,\n// but without actually using it. Or of algorithms like cycle-detection which\n// for some reason need an associative container.\n//\n// It also covers both the insert-into-an-empty-slot code path that isn't\n// covered elsewhere, and the code path for growing a table to a larger size.\n//\n// Because this benchmark operates on whole maps, we also compute the number of\n// probed keys for Carbon's set as that is both a general reflection of the\n// efficacy of the underlying hash function, and a direct factor that drives the\n// cost of these operations.\ntemplate <typename MapT>\nstatic void BM_MapInsertSeq(benchmark::State& state) {\n  using MapWrapperT = MapWrapper<MapT>;\n  using KT = typename MapWrapperT::KeyT;\n  using VT = typename MapWrapperT::ValueT;\n  constexpr ssize_t LookupKeysSize = 1 << 8;\n  auto [keys, lookup_keys] =\n      GetKeysAndHitKeys<KT>(state.range(0), LookupKeysSize);\n\n  // Note that we don't force batches that use all the lookup keys because\n  // there's no difference in cache usage by covering all the different lookup\n  // keys.\n  ssize_t i = 0;\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(i);\n\n    MapWrapperT m;\n    for (auto k : keys) {\n      bool inserted = m.BenchInsert(k, MakeValue<VT>());\n      CARBON_DCHECK(inserted, \"Must be a successful insert!\");\n    }\n\n    // Now insert a final random repeated key.\n    bool inserted = m.BenchInsert(lookup_keys[i], MakeValue2<VT>());\n    CARBON_DCHECK(!inserted, \"Must already be in the map!\");\n\n    // Rotate through the shuffled keys.\n    i = (i + static_cast<ssize_t>(!inserted)) & (LookupKeysSize - 1);\n  }\n\n  // It can be easier in some cases to think of this as a key-throughput rate of\n  // insertion rather than the latency of inserting N keys, so construct the\n  // rate counter as well.\n  state.counters[\"KeyRate\"] = benchmark::Counter(\n      keys.size(), benchmark::Counter::kIsIterationInvariantRate);\n\n  // Report some extra statistics about the Carbon type.\n  if constexpr (IsCarbonMap<MapWrapperT>) {\n    // Re-build a map outside of the timing loop to look at the statistics\n    // rather than the timing.\n    MapWrapperT m;\n    for (auto k : keys) {\n      bool inserted = m.BenchInsert(k, MakeValue<VT>());\n      CARBON_DCHECK(inserted, \"Must be a successful insert!\");\n    }\n\n    ReportMetrics(m, state);\n\n    // Uncomment this call to print out statistics about the index-collisions\n    // among these keys for debugging:\n    //\n    // RawHashtable::DumpHashStatistics(keys);\n  }\n}\nMAP_BENCHMARK_ONE_OP(BM_MapInsertSeq, SizeArgs);\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/map_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/map.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <initializer_list>\n#include <type_traits>\n#include <utility>\n#include <vector>\n\n#include \"common/raw_hashtable_test_helpers.h\"\n\n// Workaround for std::pair comparison deficiency in libc++ 16.\n#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000\nnamespace std {\ntemplate <typename T, typename U, typename V, typename W>\n  requires(convertible_to<V, T> && convertible_to<W, U>)\ninline auto operator==(\n    pair<std::reference_wrapper<T>, std::reference_wrapper<U>> lhs,\n    pair<V, W> rhs) -> bool {\n  return lhs.first == static_cast<T>(rhs.first) &&\n         lhs.second == static_cast<U>(rhs.second);\n}\n}  // namespace std\n#endif\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing RawHashtable::FixedHashKeyContext;\nusing RawHashtable::IndexKeyContext;\nusing RawHashtable::MoveOnlyTestData;\nusing RawHashtable::TestData;\nusing RawHashtable::TestKeyContext;\nusing ::testing::Pair;\nusing ::testing::UnorderedElementsAreArray;\n\ntemplate <typename MapT, typename MatcherRangeT>\nauto ExpectMapElementsAre(MapT&& m, MatcherRangeT element_matchers) -> void {\n  // Now collect the elements into a container.\n  using KeyT = typename std::remove_reference<MapT>::type::KeyT;\n  using ValueT = typename std::remove_reference<MapT>::type::ValueT;\n  std::vector<\n      std::pair<std::reference_wrapper<KeyT>, std::reference_wrapper<ValueT>>>\n      map_entries;\n  m.ForEach([&map_entries](KeyT& k, ValueT& v) {\n    map_entries.push_back({std::ref(k), std::ref(v)});\n  });\n\n  // Use the GoogleMock unordered container matcher to validate and show errors\n  // on wrong elements.\n  EXPECT_THAT(map_entries, UnorderedElementsAreArray(element_matchers));\n}\n\n// Allow directly using an initializer list.\ntemplate <typename MapT, typename MatcherT>\nauto ExpectMapElementsAre(MapT&& m,\n                          std::initializer_list<MatcherT> element_matchers)\n    -> void {\n  std::vector<MatcherT> element_matchers_storage = element_matchers;\n  ExpectMapElementsAre(m, element_matchers_storage);\n}\n\ntemplate <typename ValueCB, typename RangeT, typename... RangeTs>\nauto MakeKeyValues(ValueCB value_cb, RangeT&& range, RangeTs&&... ranges)\n    -> auto {\n  using KeyT = typename RangeT::value_type;\n  using ValueT = decltype(value_cb(std::declval<KeyT>()));\n  std::vector<std::pair<KeyT, ValueT>> elements;\n  auto add_range = [&](RangeT&& r) {\n    for (const auto&& e : r) {\n      elements.push_back({e, value_cb(e)});\n    }\n  };\n  add_range(std::forward<RangeT>(range));\n  (add_range(std::forward<RangeTs>(ranges)), ...);\n\n  return elements;\n}\n\ntemplate <typename MapT>\nclass MapTest : public ::testing::Test {};\n\ntemplate <typename MapT>\nclass MoveOnlyMapTest : public ::testing::Test {};\n\nusing Types = ::testing::Types<\n    Map<int, int>, Map<int, int, 16>, Map<int, int, 64>,\n    Map<int, int, 0, TestKeyContext>, Map<int, int, 16, TestKeyContext>,\n    Map<int, int, 64, TestKeyContext>, Map<TestData, TestData>,\n    Map<TestData, TestData, 16>, Map<TestData, TestData, 0, TestKeyContext>,\n    Map<TestData, TestData, 16, TestKeyContext>>;\nTYPED_TEST_SUITE(MapTest, Types);\n\nusing MoveOnlyTypes = ::testing::Types<\n    Map<MoveOnlyTestData, MoveOnlyTestData>,\n    Map<MoveOnlyTestData, MoveOnlyTestData, 16>,\n    Map<MoveOnlyTestData, MoveOnlyTestData, 64>,\n    Map<MoveOnlyTestData, MoveOnlyTestData, 0, TestKeyContext>,\n    Map<MoveOnlyTestData, MoveOnlyTestData, 16, TestKeyContext>>;\nTYPED_TEST_SUITE(MoveOnlyMapTest, MoveOnlyTypes);\n\nTYPED_TEST(MapTest, Basic) {\n  TypeParam m;\n\n  EXPECT_FALSE(m.Contains(42));\n  EXPECT_EQ(nullptr, m[42]);\n  EXPECT_TRUE(m.Insert(1, 100).is_inserted());\n  ASSERT_TRUE(m.Contains(1));\n  auto result = m.Lookup(1);\n  EXPECT_TRUE(result);\n  EXPECT_EQ(1, result.key());\n  EXPECT_EQ(100, result.value());\n  EXPECT_EQ(100, *m[1]);\n  // Reinsertion doesn't change the value.\n  auto i_result = m.Insert(1, 101);\n  EXPECT_FALSE(i_result.is_inserted());\n  EXPECT_EQ(100, i_result.value());\n  EXPECT_EQ(100, *m[1]);\n  // Update does change the value.\n  i_result = m.Update(1, 101);\n  EXPECT_FALSE(i_result.is_inserted());\n  EXPECT_EQ(101, i_result.value());\n  EXPECT_EQ(101, *m[1]);\n\n  // Verify all the elements.\n  ExpectMapElementsAre(m, {Pair(1, 101)});\n\n  // Fill up a bunch to ensure we trigger growth a few times.\n  for (int i : llvm::seq(2, 512)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + static_cast<int>(k == 1); },\n                       llvm::seq(1, 512)));\n  for (int i : llvm::seq(1, 512)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());\n    EXPECT_EQ(i * 100 + static_cast<int>(i == 1), *m[i]);\n    EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());\n    EXPECT_EQ(i * 100 + 1, *m[i]);\n  }\n  EXPECT_FALSE(m.Contains(513));\n\n  // Verify all the elements.\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(1, 512)));\n}\n\nTYPED_TEST(MapTest, FactoryApi) {\n  TypeParam m;\n  EXPECT_TRUE(m.Insert(1, [] { return 100; }).is_inserted());\n  ASSERT_TRUE(m.Contains(1));\n  EXPECT_EQ(100, *m[1]);\n  // Reinsertion doesn't invoke the callback.\n  EXPECT_FALSE(m.Insert(1, []() -> int {\n                  llvm_unreachable(\"Should never be called!\");\n                }).is_inserted());\n  // Update does invoke the callback.\n  auto i_result = m.Update(1, [] { return 101; });\n  EXPECT_FALSE(i_result.is_inserted());\n  EXPECT_EQ(101, i_result.value());\n  EXPECT_EQ(101, *m[1]);\n}\n\nTYPED_TEST(MapTest, Copy) {\n  using MapT = TypeParam;\n\n  MapT m;\n  // Make sure we exceed the small size for some of the map types, but not all\n  // of them, so we cover all the combinations of copying between small and\n  // large.\n  for (int i : llvm::seq(1, 24)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n\n  MapT other_m1 = m;\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));\n\n  // Add some more elements to the original.\n  for (int i : llvm::seq(24, 32)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n\n  // The first copy doesn't change.\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));\n\n  // A new copy does.\n  MapT other_m2 = m;\n  ExpectMapElementsAre(\n      other_m2, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // Copy-assign updates.\n  other_m1 = m;\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // Self-assign is a no-op.\n  other_m1 = const_cast<const MapT&>(other_m1);\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // But mutating original still doesn't change copies.\n  for (int i : llvm::seq(32, 48)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n  ExpectMapElementsAre(\n      other_m2, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n}\n\nTYPED_TEST(MapTest, Move) {\n  using MapT = TypeParam;\n\n  MapT m;\n  // Make sure we exceed the small size for some of the map types, but not all\n  // of them, so we cover all the combinations of moving between small and\n  // large.\n  for (int i : llvm::seq(1, 24)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n\n  MapT other_m1 = std::move(m);\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));\n\n  // Add some more elements.\n  for (int i : llvm::seq(24, 32)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(other_m1.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // Move back over a moved-from.\n  m = std::move(other_m1);\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // Copy over moved-from state also works.\n  other_m1 = m;\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // Now add still more elements.\n  for (int i : llvm::seq(32, 48)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(other_m1.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 48)));\n\n  // And move-assign over the copy looks like the moved-from table not the copy.\n  other_m1 = std::move(m);\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // Self-swap (which does a self-move) works and is a no-op.\n  std::swap(other_m1, other_m1);\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // Test copying of a moved-from table over a valid table and\n  // self-move-assign. The former is required to be valid, and the latter is\n  // in at least the case of self-move-assign-when-moved-from, but the result\n  // can be in any state so just do them and ensure we don't crash.\n  MapT other_m2 = other_m1;\n  // NOLINTNEXTLINE(bugprone-use-after-move): Testing required use-after-move.\n  other_m2 = m;\n  other_m1 = std::move(other_m1);\n  m = std::move(m);\n}\n\nTYPED_TEST(MoveOnlyMapTest, MoveOnlyTypes) {\n  using MapT = TypeParam;\n  static_assert(!std::is_copy_assignable_v<MapT>);\n  static_assert(!std::is_copy_constructible_v<MapT>);\n  static_assert(std::is_move_assignable_v<MapT>);\n  static_assert(std::is_move_constructible_v<MapT>);\n\n  auto make_map = [] {\n    MapT m;\n    // Make sure we exceed the small size for some of the map types, but not all\n    // of them, so we cover all the combinations of moving between small and\n    // large.\n    for (int i : llvm::seq(1, 24)) {\n      SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n      EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());\n    }\n    return m;\n  };\n\n  MapT m = make_map();\n\n  MapT other_m1 = std::move(m);\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));\n\n  // Add some more elements.\n  for (int i : llvm::seq(24, 32)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(other_m1.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(\n      other_m1, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // Move back over a moved-from.\n  m = std::move(other_m1);\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 32)));\n\n  // Now add still more elements, crossing the small size limit for all tested\n  // map types.\n  for (int i : llvm::seq(32, 72)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 72)));\n\n  // Assignment replaces the contents.\n  m = make_map();\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));\n\n  // Self-swap (which does a self-move) works and is a no-op.\n  std::swap(m, m);\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 24)));\n}\n\nTYPED_TEST(MapTest, Conversions) {\n  using MapT = TypeParam;\n  using KeyT = MapT::KeyT;\n  using ValueT = MapT::ValueT;\n  using KeyContextT = MapT::KeyContextT;\n\n  MapT m;\n\n  ASSERT_TRUE(m.Insert(1, 101).is_inserted());\n  ASSERT_TRUE(m.Insert(2, 102).is_inserted());\n  ASSERT_TRUE(m.Insert(3, 103).is_inserted());\n  ASSERT_TRUE(m.Insert(4, 104).is_inserted());\n\n  MapView<KeyT, ValueT, KeyContextT> mv = m;\n  MapView<const KeyT, ValueT, KeyContextT> cmv = m;\n  MapView<KeyT, const ValueT, KeyContextT> cmv2 = m;\n  MapView<const KeyT, const ValueT, KeyContextT> cmv3 = m;\n  EXPECT_TRUE(mv.Contains(1));\n  EXPECT_EQ(101, *mv[1]);\n  EXPECT_TRUE(cmv.Contains(2));\n  EXPECT_EQ(102, *cmv[2]);\n  EXPECT_TRUE(cmv2.Contains(3));\n  EXPECT_EQ(103, *cmv2[3]);\n  EXPECT_TRUE(cmv3.Contains(4));\n  EXPECT_EQ(104, *cmv3[4]);\n}\n\nTYPED_TEST(MapTest, GrowToAllocSize) {\n  using MapT = TypeParam;\n\n  MapT m;\n  // Grow when empty. May be a no-op for some small sizes.\n  m.GrowToAllocSize(32);\n\n  // Add some elements that will need to be propagated through subsequent\n  // growths. Also delete some.\n  ssize_t storage_bytes = m.ComputeMetrics().storage_bytes;\n  for (int i : llvm::seq(1, 24)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  for (int i : llvm::seq(1, 8)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Erase(i));\n  }\n  // No further growth triggered.\n  EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);\n\n  // No-op.\n  m.GrowToAllocSize(16);\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(8, 24)));\n  // No further growth triggered.\n  EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);\n\n  // Get a few doubling based growths, and at least one beyond the largest small\n  // size.\n  m.GrowToAllocSize(64);\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(8, 24)));\n  m.GrowToAllocSize(128);\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(8, 24)));\n  // Update the storage bytes after growth.\n  EXPECT_LT(storage_bytes, m.ComputeMetrics().storage_bytes);\n  storage_bytes = m.ComputeMetrics().storage_bytes;\n\n  // Add some more, but not enough to trigger further growth, and then grow by\n  // several more multiples of two to test handling large growth.\n  for (int i : llvm::seq(24, 48)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  for (int i : llvm::seq(8, 16)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Erase(i));\n  }\n  // No growth from insertions.\n  EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);\n\n  m.GrowToAllocSize(1024);\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(16, 48)));\n  // Storage should have grown.\n  EXPECT_LT(storage_bytes, m.ComputeMetrics().storage_bytes);\n}\n\nTYPED_TEST(MapTest, GrowForInsert) {\n  using MapT = TypeParam;\n\n  MapT m;\n  m.GrowForInsertCount(42);\n  ssize_t storage_bytes = m.ComputeMetrics().storage_bytes;\n  for (int i : llvm::seq(1, 42)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 42)));\n  EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);\n\n  // Erase many elements and grow again for another insert.\n  for (int i : llvm::seq(1, 32)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Erase(i));\n  }\n  m.GrowForInsertCount(42);\n  storage_bytes = m.ComputeMetrics().storage_bytes;\n  for (int i : llvm::seq(42, 84)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(32, 84)));\n  EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);\n\n  // Erase all the elements, then grow for a much larger insertion and insert\n  // again.\n  for (int i : llvm::seq(32, 84)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Erase(i));\n  }\n  m.GrowForInsertCount(321);\n  storage_bytes = m.ComputeMetrics().storage_bytes;\n  for (int i : llvm::seq(128, 321 + 128)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(m, MakeKeyValues([](int k) { return k * 100; },\n                                        llvm::seq(128, 321 + 128)));\n  EXPECT_EQ(storage_bytes, m.ComputeMetrics().storage_bytes);\n}\n\n// This test is largely exercising the underlying `RawHashtable` implementation\n// with complex growth, erasure, and re-growth.\nTYPED_TEST(MapTest, ComplexOpSequence) {\n  // Use a small size as well to cover more growth scenarios.\n  TypeParam m;\n\n  EXPECT_FALSE(m.Contains(42));\n  EXPECT_EQ(nullptr, m[42]);\n  EXPECT_TRUE(m.Insert(1, 100).is_inserted());\n  ASSERT_TRUE(m.Contains(1));\n  auto result = m.Lookup(1);\n  EXPECT_TRUE(result);\n  EXPECT_EQ(1, result.key());\n  EXPECT_EQ(100, result.value());\n  EXPECT_EQ(100, *m[1]);\n  // Reinsertion doesn't change the value.\n  auto i_result = m.Insert(1, 101);\n  EXPECT_FALSE(i_result.is_inserted());\n  EXPECT_EQ(100, i_result.value());\n  EXPECT_EQ(100, *m[1]);\n  // Update does change the value.\n  i_result = m.Update(1, 101);\n  EXPECT_FALSE(i_result.is_inserted());\n  EXPECT_EQ(101, i_result.value());\n  EXPECT_EQ(101, *m[1]);\n\n  // Verify all the elements.\n  ExpectMapElementsAre(m, {Pair(1, 101)});\n\n  // Fill up the small buffer but don't overflow it.\n  for (int i : llvm::seq(2, 5)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  for (int i : llvm::seq(1, 5)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Contains(i));\n    EXPECT_EQ(i * 100 + static_cast<int>(i == 1), *m[i]);\n    EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());\n    EXPECT_EQ(i * 100 + static_cast<int>(i == 1), *m[i]);\n    EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());\n    EXPECT_EQ(i * 100 + 1, *m[i]);\n  }\n  EXPECT_FALSE(m.Contains(5));\n\n  // Verify all the elements.\n  ExpectMapElementsAre(\n      m, {Pair(1, 101), Pair(2, 201), Pair(3, 301), Pair(4, 401)});\n\n  // Erase some entries from the small buffer.\n  EXPECT_FALSE(m.Erase(42));\n  EXPECT_TRUE(m.Erase(2));\n  EXPECT_EQ(101, *m[1]);\n  EXPECT_EQ(nullptr, m[2]);\n  EXPECT_EQ(301, *m[3]);\n  EXPECT_EQ(401, *m[4]);\n  EXPECT_TRUE(m.Erase(1));\n  EXPECT_EQ(nullptr, m[1]);\n  EXPECT_EQ(nullptr, m[2]);\n  EXPECT_EQ(301, *m[3]);\n  EXPECT_EQ(401, *m[4]);\n  EXPECT_TRUE(m.Erase(4));\n  EXPECT_EQ(nullptr, m[1]);\n  EXPECT_EQ(nullptr, m[2]);\n  EXPECT_EQ(301, *m[3]);\n  EXPECT_EQ(nullptr, m[4]);\n  // Fill them back in, but with a different order and going back to the\n  // original value.\n  EXPECT_TRUE(m.Insert(1, 100).is_inserted());\n  EXPECT_TRUE(m.Insert(2, 200).is_inserted());\n  EXPECT_TRUE(m.Insert(4, 400).is_inserted());\n  EXPECT_EQ(100, *m[1]);\n  EXPECT_EQ(200, *m[2]);\n  EXPECT_EQ(301, *m[3]);\n  EXPECT_EQ(400, *m[4]);\n  // Then update their values to match.\n  EXPECT_FALSE(m.Update(1, 101).is_inserted());\n  EXPECT_FALSE(m.Update(2, 201).is_inserted());\n  EXPECT_FALSE(m.Update(4, 401).is_inserted());\n\n  // Now fill up the first metadata group.\n  for (int i : llvm::seq(5, 14)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  for (int i : llvm::seq(1, 14)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Contains(i));\n    EXPECT_EQ(i * 100 + static_cast<int>(i < 5), *m[i]);\n    EXPECT_FALSE(m.Insert(i, i * 100 + 2).is_inserted());\n    EXPECT_EQ(i * 100 + static_cast<int>(i < 5), *m[i]);\n    EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());\n    EXPECT_EQ(i * 100 + 2, *m[i]);\n  }\n  EXPECT_FALSE(m.Contains(42));\n\n  // Verify all the elements by walking the entire map.\n  ExpectMapElementsAre(\n      m, {Pair(1, 102), Pair(2, 202), Pair(3, 302), Pair(4, 402), Pair(5, 502),\n          Pair(6, 602), Pair(7, 702), Pair(8, 802), Pair(9, 902),\n          Pair(10, 1002), Pair(11, 1102), Pair(12, 1202), Pair(13, 1302)});\n\n  // Now fill up several more groups.\n  for (int i : llvm::seq(14, 100)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  for (int i : llvm::seq(1, 100)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Contains(i));\n    EXPECT_EQ(i * 100 + 2 * static_cast<int>(i < 14), *m[i]);\n    EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());\n    EXPECT_EQ(i * 100 + 2 * static_cast<int>(i < 14), *m[i]);\n    EXPECT_FALSE(m.Update(i, i * 100 + 3).is_inserted());\n    EXPECT_EQ(i * 100 + 3, *m[i]);\n  }\n  EXPECT_FALSE(m.Contains(420));\n\n  // Check walking the entire container.\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 3; }, llvm::seq(1, 100)));\n\n  // Clear back to empty.\n  m.Clear();\n  EXPECT_FALSE(m.Contains(42));\n  EXPECT_EQ(nullptr, m[42]);\n\n  // Refill but with both overlapping and different values.\n  for (int i : llvm::seq(50, 150)) {\n    EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  for (int i : llvm::seq(50, 150)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Contains(i));\n    EXPECT_EQ(i * 100, *m[i]);\n    EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());\n    EXPECT_EQ(i * 100, *m[i]);\n    EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());\n    EXPECT_EQ(i * 100 + 1, *m[i]);\n  }\n  EXPECT_FALSE(m.Contains(42));\n  EXPECT_FALSE(m.Contains(420));\n\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(50, 150)));\n\n  EXPECT_FALSE(m.Erase(42));\n  EXPECT_TRUE(m.Contains(73));\n  EXPECT_TRUE(m.Erase(73));\n  EXPECT_FALSE(m.Contains(73));\n  for (int i : llvm::seq(102, 136)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Contains(i));\n    EXPECT_TRUE(m.Erase(i));\n    EXPECT_FALSE(m.Contains(i));\n  }\n  for (int i : llvm::seq(50, 150)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    if (i == 73 || (i >= 102 && i < 136)) {\n      continue;\n    }\n    ASSERT_TRUE(m.Contains(i));\n    EXPECT_EQ(i * 100 + 1, *m[i]);\n    EXPECT_FALSE(m.Insert(i, i * 100 + 2).is_inserted());\n    EXPECT_EQ(i * 100 + 1, *m[i]);\n    EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());\n    EXPECT_EQ(i * 100 + 2, *m[i]);\n  }\n  EXPECT_TRUE(m.Insert(73, 73 * 100 + 3).is_inserted());\n  EXPECT_EQ(73 * 100 + 3, *m[73]);\n\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 2 + (k == 73); },\n                       llvm::seq(50, 102), llvm::seq(136, 150)));\n\n  // Reset back to empty and small.\n  m.Reset();\n  EXPECT_FALSE(m.Contains(42));\n  EXPECT_EQ(nullptr, m[42]);\n\n  // Refill but with both overlapping and different values, now triggering\n  // growth too. Also, use update instead of insert.\n  for (int i : llvm::seq(75, 175)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Update(i, i * 100).is_inserted());\n  }\n  for (int i : llvm::seq(75, 175)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(m.Contains(i));\n    EXPECT_EQ(i * 100, *m[i]);\n    EXPECT_FALSE(m.Insert(i, i * 100 + 1).is_inserted());\n    EXPECT_EQ(i * 100, *m[i]);\n    EXPECT_FALSE(m.Update(i, i * 100 + 1).is_inserted());\n    EXPECT_EQ(i * 100 + 1, *m[i]);\n  }\n  EXPECT_FALSE(m.Contains(42));\n  EXPECT_FALSE(m.Contains(420));\n\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(75, 175)));\n\n  EXPECT_FALSE(m.Erase(42));\n  EXPECT_TRUE(m.Contains(93));\n  EXPECT_TRUE(m.Erase(93));\n  EXPECT_FALSE(m.Contains(93));\n  for (int i : llvm::seq(102, 136)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Contains(i));\n    EXPECT_TRUE(m.Erase(i));\n    EXPECT_FALSE(m.Contains(i));\n  }\n  for (int i : llvm::seq(75, 175)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    if (i == 93 || (i >= 102 && i < 136)) {\n      continue;\n    }\n    ASSERT_TRUE(m.Contains(i));\n    EXPECT_EQ(i * 100 + 1, *m[i]);\n    EXPECT_FALSE(m.Insert(i, i * 100 + 2).is_inserted());\n    EXPECT_EQ(i * 100 + 1, *m[i]);\n    EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());\n    EXPECT_EQ(i * 100 + 2, *m[i]);\n  }\n  EXPECT_TRUE(m.Insert(93, 93 * 100 + 3).is_inserted());\n  EXPECT_EQ(93 * 100 + 3, *m[93]);\n\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 2 + (k == 93); },\n                       llvm::seq(75, 102), llvm::seq(136, 175)));\n}\n\ntemplate <typename MapT>\nclass MapCollisionTest : public ::testing::Test {};\n\nusing CollisionTypes = ::testing::Types<\n    Map<int, int, 16,\n        FixedHashKeyContext<7, /*FixIndexBits*/ true, /*FixTagBits*/ false, 0>>,\n    Map<int, int, 16,\n        FixedHashKeyContext<7, /*FixIndexBits*/ false, /*FixTagBits*/ true, 0>>,\n    Map<int, int, 16,\n        FixedHashKeyContext<7, /*FixIndexBits*/ true, /*FixTagBits*/ true, 0>>,\n    Map<int, int, 16,\n        FixedHashKeyContext<7, /*FixIndexBits*/ true, /*FixTagBits*/ true,\n                            ~static_cast<uint64_t>(0)>>>;\nTYPED_TEST_SUITE(MapCollisionTest, CollisionTypes);\n\nTYPED_TEST(MapCollisionTest, Basic) {\n  TypeParam m;\n\n  // Fill the map through a couple of growth steps, verifying at each step. Note\n  // that because this is a collision test, we synthesize actively harmful\n  // hashes in terms of collisions and so this test is essentially quadratic. We\n  // need to keep it relatively small.\n  for (int i : llvm::seq(1, 256)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100).is_inserted());\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 256)));\n\n  // Erase and re-fill from the back.\n  for (int i : llvm::seq(192, 256)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Erase(i));\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100; }, llvm::seq(1, 192)));\n  for (int i : llvm::seq(192, 256)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100 + 1).is_inserted());\n  }\n  ExpectMapElementsAre(m,\n                       MakeKeyValues([](int k) { return k * 100 + (k >= 192); },\n                                     llvm::seq(1, 256)));\n\n  // Erase and re-fill from the front.\n  for (int i : llvm::seq(1, 64)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Erase(i));\n  }\n  ExpectMapElementsAre(m,\n                       MakeKeyValues([](int k) { return k * 100 + (k >= 192); },\n                                     llvm::seq(64, 256)));\n  for (int i : llvm::seq(1, 64)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100 + 1).is_inserted());\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + (k < 64) + (k >= 192); },\n                       llvm::seq(1, 256)));\n\n  // Erase and re-fill from the middle.\n  for (int i : llvm::seq(64, 192)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Erase(i));\n  }\n  ExpectMapElementsAre(m, MakeKeyValues([](int k) { return k * 100 + 1; },\n                                        llvm::seq(1, 64), llvm::seq(192, 256)));\n  for (int i : llvm::seq(64, 192)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100 + 1).is_inserted());\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(1, 256)));\n\n  // Erase and re-fill from both the back and front.\n  for (auto s : {llvm::seq(192, 256), llvm::seq(1, 64)}) {\n    for (int i : s) {\n      SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n      EXPECT_TRUE(m.Erase(i));\n    }\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(64, 192)));\n  for (auto s : {llvm::seq(192, 256), llvm::seq(1, 64)}) {\n    for (int i : s) {\n      SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n      EXPECT_TRUE(m.Insert(i, i * 100 + 2).is_inserted());\n    }\n  }\n  ExpectMapElementsAre(\n      m,\n      MakeKeyValues([](int k) { return k * 100 + 1 + (k < 64) + (k >= 192); },\n                    llvm::seq(1, 256)));\n\n  // And update the middle elements in place.\n  for (int i : llvm::seq(64, 192)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_FALSE(m.Update(i, i * 100 + 2).is_inserted());\n  }\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 2; }, llvm::seq(1, 256)));\n}\n\nTEST(MapContextTest, Basic) {\n  llvm::SmallVector<TestData> keys;\n  for (int i : llvm::seq(0, 513)) {\n    keys.push_back(i * 100000);\n  }\n  IndexKeyContext<TestData> key_context(keys);\n  Map<ssize_t, int, 0, IndexKeyContext<TestData>> m;\n\n  EXPECT_FALSE(m.Contains(42, key_context));\n  EXPECT_TRUE(m.Insert(1, 100, key_context).is_inserted());\n  ASSERT_TRUE(m.Contains(1, key_context));\n  auto result = m.Lookup(TestData(100000), key_context);\n  EXPECT_TRUE(result);\n  EXPECT_EQ(1, result.key());\n  EXPECT_EQ(100, result.value());\n  // Reinsertion doesn't change the value. Also, double check a temporary\n  // context.\n  auto i_result = m.Insert(1, 101, IndexKeyContext<TestData>(keys));\n  EXPECT_FALSE(i_result.is_inserted());\n  EXPECT_EQ(100, i_result.value());\n  // Update does change the value.\n  i_result = m.Update(1, 101, key_context);\n  EXPECT_FALSE(i_result.is_inserted());\n  EXPECT_EQ(101, i_result.value());\n\n  // Verify all the elements.\n  ExpectMapElementsAre(m, {Pair(1, 101)});\n\n  // Fill up a bunch to ensure we trigger growth a few times.\n  for (int i : llvm::seq(2, 512)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(m.Insert(i, i * 100, key_context).is_inserted());\n  }\n  // Check all the elements, including using the context.\n  for (int j : llvm::seq(1, 512)) {\n    SCOPED_TRACE(llvm::formatv(\"Assert key: {0}\", j).str());\n    ASSERT_EQ(j * 100 + static_cast<int>(j == 1),\n              m.Lookup(j, key_context).value());\n    ASSERT_EQ(j * 100 + static_cast<int>(j == 1),\n              m.Lookup(TestData(j * 100000), key_context).value());\n  }\n  for (int i : llvm::seq(1, 512)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_FALSE(m.Insert(i, i * 100 + 1, key_context).is_inserted());\n    EXPECT_EQ(i * 100 + static_cast<int>(i == 1),\n              m.Lookup(i, key_context).value());\n    EXPECT_FALSE(m.Update(i, i * 100 + 1, key_context).is_inserted());\n    EXPECT_EQ(i * 100 + 1, m.Lookup(i, key_context).value());\n  }\n  EXPECT_FALSE(m.Contains(0, key_context));\n  EXPECT_FALSE(m.Contains(512, key_context));\n\n  // Verify all the elements.\n  ExpectMapElementsAre(\n      m, MakeKeyValues([](int k) { return k * 100 + 1; }, llvm::seq(1, 512)));\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "common/move_only.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_MOVE_ONLY_H_\n#define CARBON_COMMON_MOVE_ONLY_H_\n\nnamespace Carbon {\n\n// A base class that indicates a type is move-only. Typically this can be\n// achieved by declaring the move constructor and move assignment yourself; this\n// type should be used only when doing that is not feasible, such as when\n// aggregate initialization is still desired.\n//\n// This class uses CRTP to ensure that each MoveOnly base class has a different\n// type. This is important to avoid the compiler adding extra padding to derived\n// classes to give multiple MoveOnly subobjects of the same type different\n// addresses.\ntemplate <typename Derived>\nstruct MoveOnly {\n  MoveOnly() = default;\n  MoveOnly(MoveOnly&&) noexcept = default;\n  auto operator=(MoveOnly&&) noexcept -> MoveOnly& = default;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_MOVE_ONLY_H_\n"
  },
  {
    "path": "common/ostream.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_OSTREAM_H_\n#define CARBON_COMMON_OSTREAM_H_\n\n// Libraries should include this header instead of raw_ostream.\n\n#include <concepts>\n#include <ostream>\n#include <type_traits>\n\n#include \"llvm/Support/Compiler.h\"\n#include \"llvm/Support/raw_os_ostream.h\"\n#include \"llvm/Support/raw_ostream.h\"  // IWYU pragma: export\n\nnamespace Carbon {\n\n// CRTP base class for printable types. Children (DerivedT) must implement:\n// - auto Print(llvm::raw_ostream& out) const -> void\ntemplate <typename DerivedT>\n// NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility)\nclass Printable {\n  // Provides simple printing for debuggers.\n  LLVM_DUMP_METHOD auto Dump() const -> std::string {\n    std::string buffer;\n    llvm::raw_string_ostream stream(buffer);\n    static_cast<const DerivedT*>(this)->Print(stream);\n    return buffer;\n  }\n\n  // Supports printing to llvm::raw_ostream.\n  friend auto operator<<(llvm::raw_ostream& out, const DerivedT& obj)\n      -> llvm::raw_ostream& {\n    obj.Print(out);\n    return out;\n  }\n\n  // Supports printing to std::ostream.\n  friend auto operator<<(std::ostream& out, const DerivedT& obj)\n      -> std::ostream& {\n    llvm::raw_os_ostream raw_os(out);\n    obj.Print(raw_os);\n    return out;\n  }\n\n  // Allows GoogleTest and GoogleMock to print pointers by dereferencing them.\n  // This is important to allow automatic printing of arguments of mocked\n  // APIs.\n  friend auto PrintTo(DerivedT* p, std::ostream* out) -> void {\n    *out << static_cast<const void*>(p);\n    // Also print the object if non-null.\n    if (p) {\n      *out << \" pointing to \" << *p;\n    }\n  }\n};\n\n// Helper class for printing strings with escapes.\n//\n// For example:\n//   stream << FormatEscaped(str);\n// Is equivalent to:\n//   stream.write_escaped(str);\nclass FormatEscaped : public Printable<FormatEscaped> {\n public:\n  explicit FormatEscaped(llvm::StringRef str, bool use_hex_escapes = false)\n      : str_(str), use_hex_escapes_(use_hex_escapes) {}\n\n  auto Print(llvm::raw_ostream& out) const -> void {\n    out.write_escaped(str_, use_hex_escapes_);\n  }\n\n private:\n  llvm::StringRef str_;\n  bool use_hex_escapes_;\n};\n\n// Returns the result of printing the value.\ntemplate <typename T>\n  requires std::derived_from<T, Printable<T>>\ninline auto PrintToString(const T& val) -> std::string {\n  std::string str;\n  llvm::raw_string_ostream stream(str);\n  stream << val;\n  return str;\n}\n\n}  // namespace Carbon\n\nnamespace llvm {\n\n// Injects an `operator<<` overload into the `llvm` namespace which detects LLVM\n// types with `raw_ostream` overloads and uses that to map to a `std::ostream`\n// overload. This allows LLVM types to be printed to `std::ostream` via their\n// `raw_ostream` operator overloads, which is needed both for logging and\n// testing.\n//\n// To make this overload be unusually low priority, it is designed to take even\n// the `std::ostream` parameter as a template, and SFINAE disable itself unless\n// that template parameter is derived from `std::ostream`. This ensures that an\n// *explicit* operator will be preferred when provided. Some LLVM types may have\n// this, and so we want to prioritize accordingly.\n//\n// It would be slightly cleaner for LLVM itself to provide this overload in\n// `raw_os_ostream.h` so that we wouldn't need to inject into LLVM's namespace,\n// but supporting `std::ostream` isn't a priority for LLVM so we handle it\n// locally instead.\ntemplate <typename StreamT, typename ClassT>\n  requires std::derived_from<std::decay_t<StreamT>, std::ostream> &&\n           (!std::same_as<std::decay_t<ClassT>, raw_ostream>) &&\n           requires(raw_ostream& os, const ClassT& value) { os << value; }\nauto operator<<(StreamT& standard_out, const ClassT& value) -> StreamT& {\n  raw_os_ostream(standard_out) << value;\n  return standard_out;\n}\n\n}  // namespace llvm\n\n#endif  // CARBON_COMMON_OSTREAM_H_\n"
  },
  {
    "path": "common/pretty_stack_trace_function.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_PRETTY_STACK_TRACE_FUNCTION_H_\n#define CARBON_COMMON_PRETTY_STACK_TRACE_FUNCTION_H_\n\n#include <functional>\n\n#include \"llvm/Support/PrettyStackTrace.h\"\n\nnamespace Carbon {\n\n// Calls `fn` as part of LLVM's pretty stack trace support. Implementations\n// should typically have a terminating `\\n`.\nclass PrettyStackTraceFunction : public llvm::PrettyStackTraceEntry {\n public:\n  explicit PrettyStackTraceFunction(\n      std::function<auto(llvm::raw_ostream&)->void> fn)\n      : fn_(std::move(fn)) {}\n  ~PrettyStackTraceFunction() override = default;\n\n  auto print(llvm::raw_ostream& output) const -> void override { fn_(output); }\n\n private:\n  const std::function<auto(llvm::raw_ostream&)->void> fn_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_PRETTY_STACK_TRACE_FUNCTION_H_\n"
  },
  {
    "path": "common/raw_hashtable.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/raw_hashtable.h\"\n\n#include <cstddef>\n\nnamespace Carbon::RawHashtable {\n\nvolatile std::byte global_addr_seed{1};\n\n}  // namespace Carbon::RawHashtable\n"
  },
  {
    "path": "common/raw_hashtable.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_RAW_HASHTABLE_H_\n#define CARBON_COMMON_RAW_HASHTABLE_H_\n\n#include <algorithm>\n#include <concepts>\n#include <cstddef>\n#include <cstring>\n#include <iterator>\n#include <new>\n#include <type_traits>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/concepts.h\"\n#include \"common/hashing.h\"\n#include \"common/raw_hashtable_metadata_group.h\"\n#include \"llvm/Support/Compiler.h\"\n#include \"llvm/Support/MathExtras.h\"\n\n// A namespace collecting a set of low-level utilities for building hashtable\n// data structures. These should only be used as implementation details of\n// higher-level data-structure APIs.\n//\n// The utilities here use the `hashtable_key_context.h` provided `KeyContext` to\n// support the necessary hashtable operations on keys: hashing and comparison.\n// This also serves as the customization point for hashtables built on this\n// infrastructure for those operations. See that header file for details.\n//\n// These utilities support hashtables following a *specific* API design pattern,\n// and using Small-Size Optimization, or \"SSO\", when desired. We expect there to\n// be three layers to any hashtable design:\n//\n// - A *view* type: a read-only view of the hashtable contents. This type should\n//   be a value type and is expected to be passed by-value in APIs. However, it\n//   will have `const`-reference semantics, much like a `std::string_view`. Note\n//   that the *entries* will continue to be mutable, it is only the *table* that\n//   is read-only.\n//\n// - A *base* type: a base class type of the actual hashtable, which allows\n//   almost all mutable operations but erases any specific SSO buffer size.\n//   Because this is a base of the actual hash table, it is designed to be\n//   passed as a non-`const` reference or pointer.\n//\n// - A *table* type: the actual hashtable which derives from the base type and\n//   adds any desired SSO storage buffer. Beyond the physical storage, it also\n//   allows resetting the table to its initial state & allocated size, as well\n//   as copying and moving the table.\n//\n// For complete examples of the API design, see `set.h` for a hashtable-based\n// set data structure, and `map.h` for a hashtable-based map data structure.\n//\n// The hashtable design implemented here has several key invariants and design\n// elements that are essential to all three of the types above and the\n// functionality they provide.\n//\n// - The underlying hashtable uses [open addressing], a power-of-two table size,\n//   and quadratic probing rather than closed addressing and chaining.\n//\n//   [open addressing]: https://en.wikipedia.org/wiki/Open_addressing\n//\n// - Each _slot_ in the table corresponds to a key, a value, and one byte of\n//   metadata. Each _entry_ is a key and value. The key and value for an entry\n//   are stored together.\n//\n// - The allocated storage is organized into an array of metadata bytes followed\n//   by an array of entry storage.\n//\n// - The metadata byte corresponding to each entry marks that entry is either\n//   empty, deleted, or present. When present, a 7-bit tag is also stored using\n//   another 7 bits from the hash of the entry key.\n//\n// - The storage for an entry is an internal type that should not be exposed to\n//   users, and instead only the underlying keys and values.\n//\n// - The hash addressing and probing occurs over *groups* of slots rather than\n//   individual entries. When inserting a new entry, it can be added to the\n//   group it hashes to as long it is not full, and can even replace a slot with\n//   a tombstone indicating a previously deleted entry. Only when the group is\n//   full will it look at the next group in the probe sequence. As a result,\n//   there may be entries in a group where a different group is the start of\n//   that entry's probe sequence. Also, when performing a lookup, every group in\n//   the probe sequence must be inspected for the lookup key until it is found\n//   or the group has an empty slot.\n//\n// - Groups are scanned rapidly using the one-byte metadata for each entry in\n//   the group and CPU instructions that allow comparing all of the metadata for\n//   a group in parallel. For more details on the metadata group encoding and\n//   scanning, see `raw_hashtable_metadata_group.h`.\n//\n// - `GroupSize` is a platform-specific relatively small power of two that fits\n//   in some hardware register. However, `MaxGroupSize` is provided as a\n//   portable max that is also a power of two. The table storage, whether\n//   provided by an SSO buffer or allocated, is required to be a multiple of\n//   `MaxGroupSize` to keep the requirement portable but sufficient for all\n//   platforms.\n//\n// - There is *always* an allocated table of some multiple of `MaxGroupSize`.\n//   This allows accesses to be branchless. When heap allocated, we pro-actively\n//   allocate at least a minimum heap size table. When there is a small-size\n//   optimization (SSO) buffer, that provides the initial allocation.\n//\n// - The table performs a minimal amount of bookkeeping that limits the APIs it\n//   can support:\n//    - `alloc_size` is the size of the table *allocated* (not *used*), and is\n//       always a power of 2 at least as big as `MinAllocatedSize`.\n//    - `storage` is a pointer to the storage for the `alloc_size` slots of the\n//       table, and never null.\n//    - `small_alloc_size` is the maximum `alloc_size` where the table is stored\n//       in the object itself instead of separately on the heap. In this case,\n//       `storage` points to `small_storage_`.\n//    - `growth_budget` is the number of entries that may be added before the\n//       table allocation is doubled. It is always\n//       `GrowthThresholdForAllocSize(alloc_size)` minus the number of\n//       non-empty (filled or deleted) slots. If it ever falls to 0, the table\n//       is grown to keep it greater than 0.\n//   There is also the \"moved-from\" state where the table may only be\n//   reinitialized or destroyed where the `alloc_size` is 0 and `storage` is\n//   null. Since it doesn't track the exact number of filled entries in a table,\n//   it doesn't support a container-style `size` API.\n//\n// - There is no direct iterator support because of the complexity of embedding\n//   the group-based metadata scanning into an iterator model. Instead, there is\n//   just a for-each method that is passed a lambda to observe all entries. The\n//   order of this observation is also not guaranteed.\nnamespace Carbon::RawHashtable {\n\n// Which prefetch strategies to enable can be controlled via macros to enable\n// doing experiments.\n//\n// Currently, benchmarking on both modern AMD and ARM CPUs seems to indicate\n// that the entry group prefetching is more beneficial than metadata, but that\n// benefit is degraded when enabling them both. This determined our current\n// default of no metadata prefetch but enabled entry group prefetch.\n//\n// Override these by defining them as part of the build explicitly to either `0`\n// or `1`. If left undefined, the defaults will be supplied.\n#ifndef CARBON_ENABLE_PREFETCH_METADATA\n#define CARBON_ENABLE_PREFETCH_METADATA 0\n#endif\n#ifndef CARBON_ENABLE_PREFETCH_ENTRY_GROUP\n#define CARBON_ENABLE_PREFETCH_ENTRY_GROUP 1\n#endif\n\n// If allocating storage, allocate a minimum of one cacheline of group metadata\n// or a minimum of one group, whichever is larger.\ninline constexpr ssize_t MinAllocatedSize = std::max<ssize_t>(64, MaxGroupSize);\n\n// An entry in the hashtable storage of a `KeyT` and `ValueT` object.\n//\n// Allows manual construction, destruction, and access to these values so we can\n// create arrays af the entries prior to populating them with actual keys and\n// values.\ntemplate <typename KeyT, typename ValueT>\nstruct StorageEntry {\n  static constexpr bool IsTriviallyDestructible =\n      std::is_trivially_destructible_v<KeyT> &&\n      std::is_trivially_destructible_v<ValueT>;\n\n  static constexpr bool IsTriviallyRelocatable =\n      IsTriviallyDestructible && std::is_trivially_move_constructible_v<KeyT> &&\n      std::is_trivially_move_constructible_v<ValueT>;\n\n  static constexpr bool IsCopyable =\n      IsTriviallyRelocatable || (std::is_copy_constructible_v<KeyT> &&\n                                 std::is_copy_constructible_v<ValueT>);\n\n  auto key() const -> const KeyT& {\n    // Ensure we don't need more alignment than available. Inside a method body\n    // to apply to the complete type.\n    static_assert(\n        alignof(StorageEntry) <= MinAllocatedSize,\n        \"The minimum allocated size turns into the alignment of our array of \"\n        \"storage entries as they follow the metadata byte array.\");\n\n    return *std::launder(reinterpret_cast<const KeyT*>(&key_storage));\n  }\n  auto key() -> KeyT& {\n    return const_cast<KeyT&>(const_cast<const StorageEntry*>(this)->key());\n  }\n\n  auto value() const -> const ValueT& {\n    return *std::launder(reinterpret_cast<const ValueT*>(&value_storage));\n  }\n  auto value() -> ValueT& {\n    return const_cast<ValueT&>(const_cast<const StorageEntry*>(this)->value());\n  }\n\n  // We handle destruction and move manually as we only want to expose distinct\n  // `KeyT` and `ValueT` subobjects to user code that may need to do in-place\n  // construction. As a consequence, this struct only provides the storage and\n  // we have to manually manage the construction, move, and destruction of the\n  // objects.\n  auto Destroy() -> void {\n    static_assert(!IsTriviallyDestructible,\n                  \"Should never instantiate when trivial!\");\n    key().~KeyT();\n    value().~ValueT();\n  }\n\n  auto CopyFrom(const StorageEntry& entry) -> void {\n    if constexpr (IsTriviallyRelocatable) {\n      memcpy(this, &entry, sizeof(StorageEntry));\n    } else {\n      new (&key_storage) KeyT(entry.key());\n      new (&value_storage) ValueT(entry.value());\n    }\n  }\n\n  // Move from an expiring entry and destroy that entry's key and value.\n  // Optimizes to directly use `memcpy` when correct.\n  auto MoveFrom(StorageEntry&& entry) -> void {\n    if constexpr (IsTriviallyRelocatable) {\n      memcpy(this, &entry, sizeof(StorageEntry));\n    } else {\n      new (&key_storage) KeyT(std::move(entry.key()));\n      entry.key().~KeyT();\n      new (&value_storage) ValueT(std::move(entry.value()));\n      entry.value().~ValueT();\n    }\n  }\n\n  alignas(KeyT) std::byte key_storage[sizeof(KeyT)];\n  alignas(ValueT) std::byte value_storage[sizeof(ValueT)];\n};\n\n// A specialization of the storage entry for sets without a distinct value type.\n// Somewhat duplicative with the key-value version, but C++ specialization makes\n// doing better difficult.\ntemplate <typename KeyT>\nstruct StorageEntry<KeyT, void> {\n  static constexpr bool IsTriviallyDestructible =\n      std::is_trivially_destructible_v<KeyT>;\n\n  static constexpr bool IsTriviallyRelocatable =\n      IsTriviallyDestructible && std::is_trivially_move_constructible_v<KeyT>;\n\n  static constexpr bool IsCopyable =\n      IsTriviallyRelocatable || std::is_copy_constructible_v<KeyT>;\n\n  auto key() const -> const KeyT& {\n    // Ensure we don't need more alignment than available.\n    static_assert(\n        alignof(StorageEntry) <= MinAllocatedSize,\n        \"The minimum allocated size turns into the alignment of our array of \"\n        \"storage entries as they follow the metadata byte array.\");\n\n    return *std::launder(reinterpret_cast<const KeyT*>(&key_storage));\n  }\n  auto key() -> KeyT& {\n    return const_cast<KeyT&>(const_cast<const StorageEntry*>(this)->key());\n  }\n\n  auto Destroy() -> void {\n    static_assert(!IsTriviallyDestructible,\n                  \"Should never instantiate when trivial!\");\n    key().~KeyT();\n  }\n\n  auto CopyFrom(const StorageEntry& entry) -> void\n    requires(IsCopyable)\n  {\n    if constexpr (IsTriviallyRelocatable) {\n      memcpy(this, &entry, sizeof(StorageEntry));\n    } else {\n      new (&key_storage) KeyT(entry.key());\n    }\n  }\n\n  auto MoveFrom(StorageEntry&& entry) -> void {\n    if constexpr (IsTriviallyRelocatable) {\n      memcpy(this, &entry, sizeof(StorageEntry));\n    } else {\n      new (&key_storage) KeyT(std::move(entry.key()));\n      entry.key().~KeyT();\n    }\n  }\n\n  alignas(KeyT) std::byte key_storage[sizeof(KeyT)];\n};\n\nstruct Metrics {\n  // How many keys are present in the table.\n  ssize_t key_count = 0;\n  // How many slots of the table are reserved due to deleted markers required to\n  // preserve probe sequences.\n  ssize_t deleted_count = 0;\n  // How many bytes of allocated storage are used by the table. Note, does not\n  // include the table object or any small-size buffer.\n  ssize_t storage_bytes = 0;\n\n  // How many keys have required probing beyond the initial group. These are the\n  // keys with a probe distance > 0.\n  ssize_t probed_key_count = 0;\n  // The probe distance averaged over every key. If every key is in its initial\n  // group, this will be zero as no keys will have a larger probe distance. In\n  // general, we want this to be as close to zero as possible.\n  double probe_avg_distance = 0.0;\n  // The maximum probe distance found for a single key in the table.\n  ssize_t probe_max_distance = 0;\n  // The average number of probing comparisons required to locate a specific key\n  // in the table. This is how many comparisons are required *before* the key is\n  // located, or the *failed* comparisons. We always have to do one successful\n  // comparison at the end. This successful comparison isn't counted because\n  // that focuses this metric on the overhead the table is introducing, and\n  // keeps a \"perfect\" table with an average of `0.0` here similar to the\n  // perfect average of `0.0` average probe distance.\n  double probe_avg_compares = 0.0;\n  // The maximum number of probing comparisons required to locate a specific\n  // key in the table.\n  ssize_t probe_max_compares = 0;\n};\n\n// A placeholder empty type used to model pointers to the allocated buffer of\n// storage.\n//\n// The allocated storage doesn't have a meaningful static layout -- it consists\n// of an array of metadata groups followed by an array of storage entries.\n// However, we want to be able to mark pointers to this and so use pointers to\n// this placeholder type as that signifier.\n//\n// This is a complete, empty type so that it can be used as a base class of a\n// specific concrete storage type for compile-time sized storage.\nstruct Storage {};\n\n// Forward declaration to support friending, see the definition below.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nclass BaseImpl;\n\n// Implementation helper for defining a read-only view type for a hashtable.\n//\n// A specific user-facing hashtable view type should derive privately from this\n// type, and forward the implementation of its interface to functions in this\n// type.\n//\n// The methods available to user-facing hashtable types are `protected`, and\n// where they are expected to directly map to a public API, named with an\n// `Impl`. The suffix naming ensures types don't `using` in these low-level APIs\n// but declare their own and implement them by forwarding to these APIs. We\n// don't want users to have to read these implementation details to understand\n// their container's API, so none of these methods should be `using`-ed into the\n// user facing types.\n//\n// Some of the types are just convenience aliases and aren't important to\n// surface as part of the user-facing type API for readers and so those are\n// reasonable to add via a `using`.\n//\n// Some methods are used by other parts of the raw hashtable implementation.\n// Those are kept `private` and where necessary the other components of the raw\n// hashtable implementation are friended to give access to them.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nclass ViewImpl {\n protected:\n  using KeyT = InputKeyT;\n  using ValueT = InputValueT;\n  using KeyContextT = InputKeyContextT;\n  using EntryT = StorageEntry<KeyT, ValueT>;\n  using MetricsT = Metrics;\n\n  friend class BaseImpl<KeyT, ValueT, KeyContextT>;\n  template <typename InputBaseT, ssize_t SmallSize>\n  friend class TableImpl;\n\n  // Make more-`const` types friends to enable conversions that add `const`.\n  friend class ViewImpl<const KeyT, ValueT, KeyContextT>;\n  friend class ViewImpl<KeyT, const ValueT, KeyContextT>;\n  friend class ViewImpl<const KeyT, const ValueT, KeyContextT>;\n\n  ViewImpl() = default;\n\n  // Support adding `const` to either key or value type of some other view.\n  template <typename OtherKeyT, typename OtherValueT>\n  explicit(false)\n      ViewImpl(ViewImpl<OtherKeyT, OtherValueT, KeyContextT> other_view)\n    requires(SameAsOneOf<KeyT, OtherKeyT, const OtherKeyT> &&\n             SameAsOneOf<ValueT, OtherValueT, const OtherValueT>)\n      : alloc_size_(other_view.alloc_size_), storage_(other_view.storage_) {}\n\n  // Looks up an entry in the hashtable and returns its address or null if not\n  // present.\n  template <typename LookupKeyT>\n  auto LookupEntry(LookupKeyT lookup_key, KeyContextT key_context) const\n      -> EntryT*;\n\n  // Calls `entry_callback` for each entry in the hashtable. All the entries\n  // within a specific group are visited first, and then `group_callback` is\n  // called on the group itself. The `group_callback` is typically only used by\n  // the internals of the hashtable.\n  template <typename EntryCallbackT, typename GroupCallbackT>\n  auto ForEachEntry(EntryCallbackT entry_callback,\n                    GroupCallbackT group_callback) const -> void;\n\n  // Returns a collection of informative metrics on the the current state of the\n  // table, useful for performance analysis. These include relatively slow to\n  // compute metrics requiring deep inspection of the table's state.\n  auto ComputeMetricsImpl(KeyContextT key_context) const -> MetricsT;\n\n private:\n  ViewImpl(ssize_t alloc_size, Storage* storage)\n      : alloc_size_(alloc_size), storage_(storage) {}\n\n  // Computes the offset from the metadata array to the entries array for a\n  // given size. This is trivial, but we use this routine to enforce invariants\n  // on the sizes.\n  static constexpr auto EntriesOffset(ssize_t alloc_size) -> ssize_t {\n    CARBON_DCHECK(llvm::isPowerOf2_64(alloc_size),\n                  \"Size must be a power of two for a hashed buffer!\");\n    // The size is always a power of two. We prevent any too-small sizes so it\n    // being a power of two provides the needed alignment. As a result, the\n    // offset is exactly the size. We validate this here to catch alignment bugs\n    // early.\n    CARBON_DCHECK(static_cast<uint64_t>(alloc_size) ==\n                  llvm::alignTo<alignof(EntryT)>(alloc_size));\n    return alloc_size;\n  }\n\n  // Compute the allocated table's byte size.\n  static constexpr auto AllocByteSize(ssize_t alloc_size) -> ssize_t {\n    return EntriesOffset(alloc_size) + sizeof(EntryT) * alloc_size;\n  }\n\n  auto metadata() const -> uint8_t* {\n    return reinterpret_cast<uint8_t*>(storage_);\n  }\n  auto entries() const -> EntryT* {\n    return reinterpret_cast<EntryT*>(reinterpret_cast<std::byte*>(storage_) +\n                                     EntriesOffset(alloc_size_));\n  }\n\n  // Prefetch the metadata prior to probing. This is to overlap any of the\n  // memory access latency we can with the hashing of a key or other\n  // latency-bound operation prior to probing.\n  auto PrefetchMetadata() const -> void {\n    if constexpr (CARBON_ENABLE_PREFETCH_METADATA) {\n      // Prefetch with a \"low\" temporal locality as we're primarily expecting a\n      // brief use of the metadata and then to return to application code.\n      __builtin_prefetch(metadata(), /*read*/ 0, /*low-locality*/ 1);\n    }\n  }\n\n  // Prefetch an entry. This prefetches for read as it is primarily expected to\n  // be used in the probing path, and writing afterwards isn't especially slowed\n  // down. We don't want to synthesize writes unless we *know* we're going to\n  // write.\n  static auto PrefetchEntryGroup(const EntryT* entry_group) -> void {\n    if constexpr (CARBON_ENABLE_PREFETCH_ENTRY_GROUP) {\n      // Prefetch with a \"low\" temporal locality as we're primarily expecting a\n      // brief use of the entries and then to return to application code.\n      __builtin_prefetch(entry_group, /*read*/ 0, /*low-locality*/ 1);\n    }\n  }\n\n  ssize_t alloc_size_;\n  Storage* storage_;\n};\n\n// Implementation helper for defining a read-write base type for a hashtable\n// that type-erases any SSO buffer.\n//\n// A specific user-facing hashtable base type should derive using *`protected`*\n// inheritance from this type, and forward the implementation of its interface\n// to functions in this type.\n//\n// Other than the use of `protected` inheritance, the patterns for this type,\n// and how to build user-facing hashtable base types from it, mirror those of\n// `ViewImpl`. See its documentation for more details.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nclass BaseImpl {\n protected:\n  using KeyT = InputKeyT;\n  using ValueT = InputValueT;\n  using KeyContextT = InputKeyContextT;\n  using ViewImplT = ViewImpl<KeyT, ValueT, KeyContextT>;\n  using EntryT = typename ViewImplT::EntryT;\n  using MetricsT = typename ViewImplT::MetricsT;\n\n  BaseImpl(int small_alloc_size, Storage* small_storage)\n      : small_alloc_size_(small_alloc_size) {\n    CARBON_CHECK(small_alloc_size >= 0);\n    Construct(small_storage);\n  }\n  // Only used for copying and moving, and leaves storage uninitialized.\n  BaseImpl(ssize_t alloc_size, int growth_budget, int small_alloc_size)\n      : view_impl_(alloc_size, nullptr),\n        growth_budget_(growth_budget),\n        small_alloc_size_(small_alloc_size) {}\n\n  // Destruction must be handled by the table where it can destroy entries in\n  // any small buffer, so make the base destructor protected but defaulted here.\n  ~BaseImpl() = default;\n\n  // NOLINTNEXTLINE(google-explicit-constructor): Designed to implicitly decay.\n  explicit(false) operator ViewImplT() const { return view_impl(); }\n\n  auto view_impl() const -> ViewImplT { return view_impl_; }\n\n  // Looks up the provided key in the hashtable. If found, returns a pointer to\n  // that entry and `false`.\n  //\n  // If not found, will locate an empty entry for inserting into, set the\n  // metadata for that entry, and return a pointer to the entry and `true`. When\n  // necessary, this will grow the hashtable to cause there to be sufficient\n  // empty entries.\n  template <typename LookupKeyT>\n  auto InsertImpl(LookupKeyT lookup_key, KeyContextT key_context)\n      -> std::pair<EntryT*, bool>;\n\n  // Grow the table to specific allocation size.\n  //\n  // This will grow the the table if necessary for it to have an allocation size\n  // of `target_alloc_size` which must be a power of two. Note that this will\n  // not allow that many keys to be inserted into the hashtable, but a smaller\n  // number based on the load factor. If a specific number of insertions need to\n  // be achieved without triggering growth, use the `GrowForInsertCountImpl`\n  // method.\n  auto GrowToAllocSizeImpl(ssize_t target_alloc_size, KeyContextT key_context)\n      -> void;\n\n  // Grow the table to allow inserting the specified number of keys.\n  auto GrowForInsertCountImpl(ssize_t count, KeyContextT key_context) -> void;\n\n  // Looks up the entry in the hashtable, and if found destroys the entry and\n  // returns `true`. If not found, returns `false`.\n  //\n  // Does not release any memory, just leaves a tombstone behind so this entry\n  // cannot be found and the slot can in theory be reused.\n  template <typename LookupKeyT>\n  auto EraseImpl(LookupKeyT lookup_key, KeyContextT key_context) -> bool;\n\n  // Erases all entries in the hashtable but leaves the allocated storage.\n  auto ClearImpl() -> void;\n\n private:\n  template <typename InputBaseT, ssize_t SmallSize>\n  friend class TableImpl;\n\n  static constexpr ssize_t Alignment = std::max<ssize_t>(\n      alignof(MetadataGroup), alignof(StorageEntry<KeyT, ValueT>));\n\n  // Implementation of inline small storage for the provided key type, value\n  // type, and small size. Specialized for a zero small size to be an empty\n  // struct.\n  template <ssize_t SmallSize>\n  struct SmallStorage : Storage {\n    alignas(Alignment) uint8_t metadata[SmallSize];\n    mutable StorageEntry<KeyT, ValueT> entries[SmallSize];\n  };\n  // Specialized storage with no inline buffer to avoid any extra alignment.\n  template <>\n  struct SmallStorage<0> {};\n\n  static auto Allocate(ssize_t alloc_size) -> Storage*;\n  static auto Deallocate(Storage* storage, ssize_t alloc_size) -> void;\n\n  auto growth_budget() const -> ssize_t { return growth_budget_; }\n  auto alloc_size() const -> ssize_t { return view_impl_.alloc_size_; }\n  auto alloc_size() -> ssize_t& { return view_impl_.alloc_size_; }\n  auto storage() const -> Storage* { return view_impl_.storage_; }\n  auto storage() -> Storage*& { return view_impl_.storage_; }\n  auto metadata() const -> uint8_t* { return view_impl_.metadata(); }\n  auto entries() const -> EntryT* { return view_impl_.entries(); }\n  auto small_alloc_size() const -> ssize_t {\n    return static_cast<unsigned>(small_alloc_size_);\n  }\n  auto is_small() const -> bool {\n    CARBON_DCHECK(alloc_size() >= small_alloc_size());\n    return alloc_size() == small_alloc_size();\n  }\n\n  // Wrapper to call `ViewImplT::PrefetchStorage`, see that method for details.\n  auto PrefetchStorage() const -> void { view_impl_.PrefetchMetadata(); }\n\n  auto Construct(Storage* small_storage) -> void;\n  auto Destroy() -> void;\n  auto CopySlotsFrom(const BaseImpl& arg) -> void\n    requires(EntryT::IsCopyable);\n  auto MoveFrom(BaseImpl&& arg, Storage* small_storage) -> void;\n\n  auto InsertIntoEmpty(HashCode hash) -> EntryT*;\n\n  static auto ComputeNextAllocSize(ssize_t old_alloc_size) -> ssize_t;\n  static auto GrowthThresholdForAllocSize(ssize_t alloc_size) -> ssize_t;\n\n  auto GrowToNextAllocSize(KeyContextT key_context) -> void;\n  auto GrowAndInsert(HashCode hash, KeyContextT key_context) -> EntryT*;\n\n  ViewImplT view_impl_;\n  int growth_budget_;\n  int small_alloc_size_;\n};\n\n// Implementation helper for defining a hashtable type with an SSO buffer.\n//\n// A specific user-facing hashtable should derive privately from this\n// type, and forward the implementation of its interface to functions in this\n// type. It should provide the corresponding user-facing hashtable base type as\n// the `InputBaseT` type parameter (rather than a key/value pair), and this type\n// will in turn derive from that provided base type. This allows derived-to-base\n// conversion from the user-facing hashtable type to the user-facing hashtable\n// base type. And it does so keeping the inheritance linear. The resulting\n// linear inheritance hierarchy for a `Map<K, T>` type will look like:\n//\n//   Map<K, T>\n//    ↓\n//   TableImpl<MapBase<K, T>>\n//    ↓\n//   MapBase<K, T>\n//    ↓\n//   BaseImpl<K, T>\n//\n// Other than this inheritance technique, the patterns for this type, and how to\n// build user-facing hashtable types from it, mirror those of `ViewImpl`. See\n// its documentation for more details.\ntemplate <typename InputBaseT, ssize_t SmallSize>\nclass TableImpl : public InputBaseT {\n protected:\n  using BaseT = InputBaseT;\n\n  TableImpl() : BaseT(SmallSize, small_storage()) {}\n  TableImpl(const TableImpl& arg)\n    requires(BaseT::EntryT::IsCopyable);\n  TableImpl(TableImpl&& arg) noexcept;\n  auto operator=(const TableImpl& arg) -> TableImpl&\n    requires(BaseT::EntryT::IsCopyable);\n  auto operator=(TableImpl&& arg) noexcept -> TableImpl&;\n  ~TableImpl();\n\n  // Resets the hashtable to its initial state, clearing all entries and\n  // releasing all memory. If the hashtable had an SSO buffer, that is restored\n  // as the storage. Otherwise, a minimum sized table storage is allocated.\n  auto ResetImpl() -> void;\n\n private:\n  using KeyT = BaseT::KeyT;\n  using ValueT = BaseT::ValueT;\n  using EntryT = BaseT::EntryT;\n  using SmallStorage = BaseT::template SmallStorage<SmallSize>;\n\n  auto small_storage() const -> Storage*;\n\n  auto SetUpStorage() -> void;\n\n  [[no_unique_address]] mutable SmallStorage small_storage_;\n};\n\n////////////////////////////////////////////////////////////////////////////////\n//\n// Only implementation details below this point.\n//\n////////////////////////////////////////////////////////////////////////////////\n\n// Computes a seed that provides a small amount of entropy from ASLR where\n// available with minimal cost. The priority is speed, and this computes the\n// entropy in a way that doesn't require loading from memory, merely accessing\n// entropy already available without accessing memory.\ninline auto ComputeSeed() -> uint64_t {\n  // A global variable whose address is used as a seed. This allows ASLR to\n  // introduce some variation in hashtable ordering when enabled via the code\n  // model for globals.\n  extern volatile std::byte global_addr_seed;\n\n  return reinterpret_cast<uint64_t>(&global_addr_seed);\n}\n\ninline auto ComputeProbeMaskFromSize(ssize_t size) -> size_t {\n  CARBON_DCHECK(llvm::isPowerOf2_64(size),\n                \"Size must be a power of two for a hashed buffer!\");\n  // Since `size` is a power of two, we can make sure the probes are less\n  // than `size` by making the mask `size - 1`. We also mask off the low\n  // bits so the probes are a multiple of the size of the groups of entries.\n  return (size - 1) & ~GroupMask;\n}\n\n// This class handles building a sequence of probe indices from a given\n// starting point, including both the quadratic growth and masking the index\n// to stay within the bucket array size. The starting point doesn't need to be\n// clamped to the size ahead of time (or even be positive), we will do it\n// internally.\n//\n// For reference on quadratic probing:\n// https://en.wikipedia.org/wiki/Quadratic_probing\n//\n// We compute the quadratic probe index incrementally, but we can also compute\n// it mathematically and will check that the incremental result matches our\n// mathematical expectation. We use the quadratic probing formula of:\n//\n//   p(start, step) = (start + (step + step^2) / 2) (mod size / GroupSize)\n//\n// However, we compute it incrementally and scale all the variables by the group\n// size so it can be used as an index without an additional multiplication.\nclass ProbeSequence {\n public:\n  ProbeSequence(ssize_t start, ssize_t size) {\n    mask_ = ComputeProbeMaskFromSize(size);\n    p_ = start & mask_;\n#ifndef NDEBUG\n    start_ = start & mask_;\n    size_ = size;\n#endif\n  }\n\n  auto Next() -> void {\n    step_ += GroupSize;\n    p_ = (p_ + step_) & mask_;\n#ifndef NDEBUG\n    // Verify against the quadratic formula we expect to be following by scaling\n    // everything down by `GroupSize`.\n    CARBON_DCHECK(\n        (p_ / GroupSize) ==\n            ((start_ / GroupSize +\n              (step_ / GroupSize + (step_ / GroupSize) * (step_ / GroupSize)) /\n                  2) %\n             (size_ / GroupSize)),\n        \"Index in probe sequence does not match the expected formula.\");\n    CARBON_DCHECK(step_ < size_,\n                  \"We necessarily visit all groups, so we can't have more \"\n                  \"probe steps than groups.\");\n#endif\n  }\n\n  auto index() const -> ssize_t { return p_; }\n\n private:\n  ssize_t step_ = 0;\n  size_t mask_;\n  ssize_t p_;\n#ifndef NDEBUG\n  ssize_t start_;\n  ssize_t size_;\n#endif\n};\n\n// TODO: Evaluate keeping this outlined to see if macro benchmarks observe the\n// same perf hit as micro benchmarks.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto ViewImpl<InputKeyT, InputValueT, InputKeyContextT>::LookupEntry(\n    LookupKeyT lookup_key, KeyContextT key_context) const -> EntryT* {\n  PrefetchMetadata();\n\n  ssize_t local_size = alloc_size_;\n  CARBON_DCHECK(local_size > 0);\n\n  uint8_t* local_metadata = metadata();\n  HashCode hash = key_context.HashKey(lookup_key, ComputeSeed());\n  auto [hash_index, tag] = hash.ExtractIndexAndTag<7>();\n\n  EntryT* local_entries = entries();\n\n  // Walk through groups of entries using a quadratic probe starting from\n  // `hash_index`.\n  ProbeSequence s(hash_index, local_size);\n  do {\n    ssize_t group_index = s.index();\n\n    // Load the group's metadata and prefetch the entries for this group. The\n    // prefetch here helps hide key access latency while we're matching the\n    // metadata.\n    MetadataGroup g = MetadataGroup::Load(local_metadata, group_index);\n    EntryT* group_entries = &local_entries[group_index];\n    PrefetchEntryGroup(group_entries);\n\n    // For each group, match the tag against the metadata to extract the\n    // potentially matching entries within the group.\n    auto metadata_matched_range = g.Match(tag);\n    if (LLVM_LIKELY(metadata_matched_range)) {\n      // If any entries in this group potentially match based on their metadata,\n      // walk each candidate and compare its key to see if we have definitively\n      // found a match.\n      auto byte_it = metadata_matched_range.begin();\n      auto byte_end = metadata_matched_range.end();\n      do {\n        EntryT* entry = byte_it.index_ptr(group_entries);\n        if (LLVM_LIKELY(key_context.KeyEq(lookup_key, entry->key()))) {\n          __builtin_assume(entry != nullptr);\n          return entry;\n        }\n        ++byte_it;\n      } while (LLVM_UNLIKELY(byte_it != byte_end));\n    }\n\n    // We failed to find a matching entry in this bucket, so check if there are\n    // empty slots as that indicates we're done probing -- no later probed index\n    // could have a match.\n    auto empty_byte_matched_range = g.MatchEmpty();\n    if (LLVM_LIKELY(empty_byte_matched_range)) {\n      return nullptr;\n    }\n\n    s.Next();\n\n    // We use a weird construct of an \"unlikely\" condition of `true`. The goal\n    // is to get the compiler to not prioritize the back edge of the loop for\n    // code layout, and in at least some tests this seems to be an effective\n    // construct for achieving this.\n  } while (LLVM_UNLIKELY(true));\n}\n\n// Note that we force inlining here because we expect to be called with lambdas\n// that will in turn be inlined to form the loop body. We don't want function\n// boundaries within the loop for performance, and recognizing the degree of\n// simplification from inlining these callbacks may be difficult to\n// automatically recognize.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename EntryCallbackT, typename GroupCallbackT>\n[[clang::always_inline]] auto\nViewImpl<InputKeyT, InputValueT, InputKeyContextT>::ForEachEntry(\n    EntryCallbackT entry_callback, GroupCallbackT group_callback) const\n    -> void {\n  uint8_t* local_metadata = metadata();\n  EntryT* local_entries = entries();\n\n  ssize_t local_size = alloc_size_;\n  for (ssize_t group_index = 0; group_index < local_size;\n       group_index += GroupSize) {\n    auto g = MetadataGroup::Load(local_metadata, group_index);\n    auto present_matched_range = g.MatchPresent();\n    if (!present_matched_range) {\n      continue;\n    }\n    for (ssize_t byte_index : present_matched_range) {\n      entry_callback(local_entries[group_index + byte_index]);\n    }\n\n    group_callback(&local_metadata[group_index]);\n  }\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto ViewImpl<InputKeyT, InputValueT, InputKeyContextT>::ComputeMetricsImpl(\n    KeyContextT key_context) const -> Metrics {\n  uint8_t* local_metadata = metadata();\n  EntryT* local_entries = entries();\n  ssize_t local_size = alloc_size_;\n\n  Metrics metrics;\n\n  // Compute the ones we can directly.\n  metrics.deleted_count = llvm::count(\n      llvm::ArrayRef(local_metadata, local_size), MetadataGroup::Deleted);\n  metrics.storage_bytes = AllocByteSize(local_size);\n\n  // We want to process present slots specially to collect metrics on their\n  // probing behavior.\n  for (ssize_t group_index = 0; group_index < local_size;\n       group_index += GroupSize) {\n    auto g = MetadataGroup::Load(local_metadata, group_index);\n    auto present_matched_range = g.MatchPresent();\n    for (ssize_t byte_index : present_matched_range) {\n      ++metrics.key_count;\n      ssize_t index = group_index + byte_index;\n      HashCode hash =\n          key_context.HashKey(local_entries[index].key(), ComputeSeed());\n      auto [hash_index, tag] = hash.ExtractIndexAndTag<7>();\n      ProbeSequence s(hash_index, local_size);\n      metrics.probed_key_count +=\n          static_cast<ssize_t>(s.index() != group_index);\n\n      // For each probed key, go through the probe sequence to find both the\n      // probe distance and how many comparisons are required.\n      ssize_t distance = 0;\n      ssize_t compares = 0;\n      for (; s.index() != group_index; s.Next()) {\n        auto probe_g = MetadataGroup::Load(local_metadata, s.index());\n        auto probe_matched_range = probe_g.Match(tag);\n        compares += std::distance(probe_matched_range.begin(),\n                                  probe_matched_range.end());\n        distance += 1;\n      }\n\n      auto probe_g = MetadataGroup::Load(local_metadata, s.index());\n      auto probe_matched_range = probe_g.Match(tag);\n      CARBON_CHECK(!probe_matched_range.empty());\n      for (ssize_t match_index : probe_matched_range) {\n        if (match_index >= byte_index) {\n          // Note we only count the compares that will *fail* as part of\n          // probing. The last successful compare isn't interesting, it is\n          // always needed.\n          break;\n        }\n        compares += 1;\n      }\n      metrics.probe_avg_distance += distance;\n      metrics.probe_max_distance =\n          std::max(metrics.probe_max_distance, distance);\n      metrics.probe_avg_compares += compares;\n      metrics.probe_max_compares =\n          std::max(metrics.probe_max_compares, compares);\n    }\n  }\n  if (metrics.key_count > 0) {\n    metrics.probe_avg_compares /= metrics.key_count;\n    metrics.probe_avg_distance /= metrics.key_count;\n  }\n  return metrics;\n}\n\n// TODO: Evaluate whether it is worth forcing this out-of-line given the\n// reasonable ABI boundary it forms and large volume of code necessary to\n// implement it.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::InsertImpl(\n    LookupKeyT lookup_key, KeyContextT key_context)\n    -> std::pair<EntryT*, bool> {\n  CARBON_DCHECK(alloc_size() > 0);\n  PrefetchStorage();\n\n  uint8_t* local_metadata = metadata();\n\n  HashCode hash = key_context.HashKey(lookup_key, ComputeSeed());\n  auto [hash_index, tag] = hash.ExtractIndexAndTag<7>();\n\n  // We re-purpose the empty control byte to signal no insert is needed to the\n  // caller. This is guaranteed to not be a control byte we're inserting.\n  // constexpr uint8_t NoInsertNeeded = Group::Empty;\n\n  ssize_t group_with_deleted_index;\n  MetadataGroup::MatchIndex deleted_match = {};\n\n  EntryT* local_entries = entries();\n\n  auto return_insert_at_index = [&](ssize_t index) -> std::pair<EntryT*, bool> {\n    // We'll need to insert at this index so set the control group byte to the\n    // proper value.\n    local_metadata[index] = tag | MetadataGroup::PresentMask;\n    return {&local_entries[index], true};\n  };\n\n  for (ProbeSequence s(hash_index, alloc_size());; s.Next()) {\n    ssize_t group_index = s.index();\n\n    // Load the group's metadata and prefetch the entries for this group. The\n    // prefetch here helps hide key access latency while we're matching the\n    // metadata.\n    auto g = MetadataGroup::Load(local_metadata, group_index);\n    EntryT* group_entries = &local_entries[group_index];\n    ViewImplT::PrefetchEntryGroup(group_entries);\n\n    auto control_byte_matched_range = g.Match(tag);\n    if (control_byte_matched_range) {\n      auto byte_it = control_byte_matched_range.begin();\n      auto byte_end = control_byte_matched_range.end();\n      do {\n        EntryT* entry = byte_it.index_ptr(group_entries);\n        if (LLVM_LIKELY(key_context.KeyEq(lookup_key, entry->key()))) {\n          return {entry, false};\n        }\n        ++byte_it;\n      } while (LLVM_UNLIKELY(byte_it != byte_end));\n    }\n\n    // Track the first group with a deleted entry that we could insert over.\n    if (!deleted_match) {\n      deleted_match = g.MatchDeleted();\n      group_with_deleted_index = group_index;\n    }\n\n    // We failed to find a matching entry in this bucket, so check if there are\n    // no empty slots. In that case, we'll continue probing.\n    auto empty_match = g.MatchEmpty();\n    if (!empty_match) {\n      continue;\n    }\n    // Ok, we've finished probing without finding anything and need to insert\n    // instead.\n\n    // If we found a deleted slot, we don't need the probe sequence to insert\n    // so just bail. We want to ensure building up a table is fast so we\n    // de-prioritize this a bit. In practice this doesn't have too much of an\n    // effect.\n    if (LLVM_UNLIKELY(deleted_match)) {\n      return return_insert_at_index(group_with_deleted_index +\n                                    deleted_match.index());\n    }\n\n    // We're going to need to grow by inserting into an empty slot. Check that\n    // we have the budget for that before we compute the exact index of the\n    // empty slot. Without the growth budget we'll have to completely rehash and\n    // so we can just bail here.\n    if (LLVM_UNLIKELY(growth_budget_ == 0)) {\n      return {GrowAndInsert(hash, key_context), true};\n    }\n\n    --growth_budget_;\n    CARBON_DCHECK(growth_budget() >= 0,\n                  \"Growth budget shouldn't have gone negative!\");\n    return return_insert_at_index(group_index + empty_match.index());\n  }\n\n  CARBON_FATAL(\n      \"We should never finish probing without finding the entry or an empty \"\n      \"slot.\");\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\n[[clang::noinline]] auto\nBaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowToAllocSizeImpl(\n    ssize_t target_alloc_size, KeyContextT key_context) -> void {\n  CARBON_CHECK(llvm::isPowerOf2_64(target_alloc_size));\n  if (target_alloc_size <= alloc_size()) {\n    return;\n  }\n\n  // If this is the next alloc size, we can used our optimized growth strategy.\n  if (target_alloc_size == ComputeNextAllocSize(alloc_size())) {\n    GrowToNextAllocSize(key_context);\n    return;\n  }\n\n  // Create locals for the old state of the table.\n  ssize_t old_size = alloc_size();\n  CARBON_DCHECK(old_size > 0);\n  bool old_small = is_small();\n  Storage* old_storage = storage();\n  uint8_t* old_metadata = metadata();\n  EntryT* old_entries = entries();\n\n  // Configure for the new size and allocate the new storage.\n  alloc_size() = target_alloc_size;\n  storage() = Allocate(target_alloc_size);\n  std::memset(metadata(), 0, target_alloc_size);\n  growth_budget_ = GrowthThresholdForAllocSize(target_alloc_size);\n\n  // Just re-insert all the entries. As we're more than doubling the table size,\n  // we don't bother with fancy optimizations here. Even using `memcpy` for the\n  // entries seems unlikely to be a significant win given how sparse the\n  // insertions will end up being.\n  ssize_t count = 0;\n  for (ssize_t group_index = 0; group_index < old_size;\n       group_index += GroupSize) {\n    auto g = MetadataGroup::Load(old_metadata, group_index);\n    auto present_matched_range = g.MatchPresent();\n    for (ssize_t byte_index : present_matched_range) {\n      ++count;\n      ssize_t index = group_index + byte_index;\n      HashCode hash =\n          key_context.HashKey(old_entries[index].key(), ComputeSeed());\n      EntryT* new_entry = InsertIntoEmpty(hash);\n      new_entry->MoveFrom(std::move(old_entries[index]));\n    }\n  }\n  growth_budget_ -= count;\n\n  if (!old_small) {\n    // Old isn't a small buffer, so we need to deallocate it.\n    Deallocate(old_storage, old_size);\n  }\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowForInsertCountImpl(\n    ssize_t count, KeyContextT key_context) -> void {\n  if (count < growth_budget_) {\n    // Already space for the needed growth.\n    return;\n  }\n\n  // Currently, we don't account for any tombstones marking deleted elements,\n  // and just conservatively ensure the growth will create adequate growth\n  // budget for insertions. We could make this more precise by instead walking\n  // the table and only counting present slots, as once we grow we'll be able to\n  // reclaim all of the deleted slots. But this adds complexity and it isn't\n  // clear this is necessary so we do the simpler conservative thing.\n  ssize_t used_budget =\n      GrowthThresholdForAllocSize(alloc_size()) - growth_budget_;\n  ssize_t budget_needed = used_budget + count;\n  ssize_t space_needed = budget_needed + (budget_needed / 7);\n  ssize_t target_alloc_size = llvm::NextPowerOf2(space_needed);\n  CARBON_CHECK(GrowthThresholdForAllocSize(target_alloc_size) >\n               (budget_needed));\n  GrowToAllocSizeImpl(target_alloc_size, key_context);\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::EraseImpl(\n    LookupKeyT lookup_key, KeyContextT key_context) -> bool {\n  EntryT* entry = view_impl_.LookupEntry(lookup_key, key_context);\n  if (!entry) {\n    return false;\n  }\n\n  // If there are empty slots in this group then nothing will probe past this\n  // group looking for an entry so we can simply set this slot to empty as\n  // well. However, if every slot in this group is full, it might be part of\n  // a long probe chain that we can't disrupt. In that case we mark the slot's\n  // metadata as deleted to keep probes continuing past it.\n  //\n  // If we mark the slot as empty, we'll also need to increase the growth\n  // budget.\n  uint8_t* local_metadata = metadata();\n  EntryT* local_entries = entries();\n  ssize_t index = entry - local_entries;\n  ssize_t group_index = index & ~GroupMask;\n  auto g = MetadataGroup::Load(local_metadata, group_index);\n  auto empty_matched_range = g.MatchEmpty();\n  if (empty_matched_range) {\n    local_metadata[index] = MetadataGroup::Empty;\n    ++growth_budget_;\n  } else {\n    local_metadata[index] = MetadataGroup::Deleted;\n  }\n\n  if constexpr (!EntryT::IsTriviallyDestructible) {\n    entry->Destroy();\n  }\n\n  return true;\n}\n\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::ClearImpl() -> void {\n  view_impl_.ForEachEntry(\n      [](EntryT& entry) {\n        if constexpr (!EntryT::IsTriviallyDestructible) {\n          entry.Destroy();\n        }\n      },\n      [](uint8_t* metadata_group) {\n        // Clear the group.\n        std::memset(metadata_group, 0, GroupSize);\n      });\n  growth_budget_ = GrowthThresholdForAllocSize(alloc_size());\n}\n\n// Allocates the appropriate memory layout for a table of the given\n// `alloc_size`, with space both for the metadata array and entries.\n//\n// The returned pointer *must* be deallocated by calling the below `Deallocate`\n// function with the same `alloc_size` as used here.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::Allocate(\n    ssize_t alloc_size) -> Storage* {\n  return reinterpret_cast<Storage*>(__builtin_operator_new(\n      ViewImplT::AllocByteSize(alloc_size),\n      static_cast<std::align_val_t>(Alignment), std::nothrow_t()));\n}\n\n// Deallocates a table's storage that was allocated with the `Allocate`\n// function.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::Deallocate(\n    Storage* storage, ssize_t alloc_size) -> void {\n  ssize_t allocated_size = ViewImplT::AllocByteSize(alloc_size);\n  // We don't need the size, but make sure it always compiles.\n  static_cast<void>(allocated_size);\n  __builtin_operator_delete(storage,\n#if __cpp_sized_deallocation\n                            allocated_size,\n#endif\n                            static_cast<std::align_val_t>(Alignment));\n}\n\n// Construct a table using the provided small storage if `small_alloc_size_` is\n// non-zero. If `small_alloc_size_` is zero, then `small_storage` won't be used\n// and can be null. Regardless, after this the storage pointer is non-null and\n// the size is non-zero so that we can directly begin inserting or querying the\n// table.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::Construct(\n    Storage* small_storage) -> void {\n  if (small_alloc_size_ > 0) {\n    alloc_size() = small_alloc_size_;\n    storage() = small_storage;\n  } else {\n    // Directly allocate the initial buffer so that the hashtable is never in\n    // an empty state.\n    alloc_size() = MinAllocatedSize;\n    storage() = Allocate(MinAllocatedSize);\n  }\n  std::memset(metadata(), 0, alloc_size());\n  growth_budget_ = GrowthThresholdForAllocSize(alloc_size());\n}\n\n// Destroy the current table, releasing any memory used.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::Destroy() -> void {\n  // Check for a moved-from state and don't do anything. Only a moved-from table\n  // has a zero size.\n  if (alloc_size() == 0) {\n    return;\n  }\n\n  // Destroy all the entries.\n  if constexpr (!EntryT::IsTriviallyDestructible) {\n    view_impl_.ForEachEntry([](EntryT& entry) { entry.Destroy(); },\n                            [](auto...) {});\n  }\n\n  // If small, nothing to deallocate.\n  if (is_small()) {\n    return;\n  }\n\n  // Just deallocate the storage without updating anything when destroying the\n  // object.\n  Deallocate(storage(), alloc_size());\n}\n\n// Copy all of the slots over from another table that is exactly the same\n// allocation size.\n//\n// This requires the current table to already have storage allocated and set up\n// but not initialized (or already cleared). It directly overwrites the storage\n// allocation of the table to match the incoming argument.\n//\n// Despite being used in construction, this shouldn't be called for a moved-from\n// `arg` -- in practice it is better for callers to handle this when setting up\n// storage.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::CopySlotsFrom(\n    const BaseImpl& arg) -> void\n  requires(EntryT::IsCopyable)\n{\n  CARBON_DCHECK(alloc_size() == arg.alloc_size());\n  ssize_t local_size = alloc_size();\n\n  // Preserve which slot every entry is in, including tombstones in the\n  // metadata, in order to copy into the new table's storage without rehashing\n  // all of the keys. This is especially important as we don't have an easy way\n  // to access the key context needed for rehashing here.\n  uint8_t* local_metadata = metadata();\n  EntryT* local_entries = entries();\n  const uint8_t* local_arg_metadata = arg.metadata();\n  const EntryT* local_arg_entries = arg.entries();\n  memcpy(local_metadata, local_arg_metadata, local_size);\n\n  for (ssize_t group_index = 0; group_index < local_size;\n       group_index += GroupSize) {\n    auto g = MetadataGroup::Load(local_arg_metadata, group_index);\n    for (ssize_t byte_index : g.MatchPresent()) {\n      local_entries[group_index + byte_index].CopyFrom(\n          local_arg_entries[group_index + byte_index]);\n    }\n  }\n}\n\n// Move from another table to this one.\n//\n// Note that the `small_storage` is *this* table's small storage pointer,\n// provided from the `TableImpl` to this `BaseImpl` method as an argument.\n//\n// Requires the table to have size and growth already set up but otherwise the\n// the table has not yet been initialized. Notably, storage should either not\n// yet be constructed or already destroyed. It both sets up the storage and\n// handles any moving slots needed.\n//\n// Note that because this is used in construction it needs to handle a\n// moved-from `arg`.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::MoveFrom(\n    BaseImpl&& arg, Storage* small_storage) -> void {\n  ssize_t local_size = alloc_size();\n  CARBON_DCHECK(local_size == arg.alloc_size());\n  // If `arg` is moved-from, skip the rest as the local size is all we need.\n  if (local_size == 0) {\n    return;\n  }\n\n  if (arg.is_small()) {\n    CARBON_DCHECK(local_size == small_alloc_size_);\n    this->storage() = small_storage;\n\n    // For small tables, we have to move the entries as we can't move the tables\n    // themselves. We do this preserving their slots and even tombstones to\n    // avoid rehashing.\n    uint8_t* local_metadata = this->metadata();\n    EntryT* local_entries = this->entries();\n    uint8_t* local_arg_metadata = arg.metadata();\n    EntryT* local_arg_entries = arg.entries();\n    memcpy(local_metadata, local_arg_metadata, local_size);\n    if (EntryT::IsTriviallyRelocatable) {\n      memcpy(local_entries, local_arg_entries, local_size * sizeof(EntryT));\n    } else {\n      for (ssize_t group_index = 0; group_index < local_size;\n           group_index += GroupSize) {\n        auto g = MetadataGroup::Load(local_arg_metadata, group_index);\n        for (ssize_t byte_index : g.MatchPresent()) {\n          local_entries[group_index + byte_index].MoveFrom(\n              std::move(local_arg_entries[group_index + byte_index]));\n        }\n      }\n    }\n  } else {\n    // Just point to the allocated storage.\n    storage() = arg.storage();\n  }\n\n  // Finally, put the incoming table into a moved-from state.\n  arg.alloc_size() = 0;\n  // Replace the pointer with null to ease debugging.\n  arg.storage() = nullptr;\n}\n\n// Optimized routine to insert a key into a table when that key *definitely*\n// isn't present in the table and the table *definitely* has a viable empty slot\n// (and growth space) to insert into before any deleted slots. When both of\n// these are true, typically just after growth, we can dramatically simplify the\n// insert position search.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::InsertIntoEmpty(\n    HashCode hash) -> EntryT* {\n  auto [hash_index, tag] = hash.ExtractIndexAndTag<7>();\n  uint8_t* local_metadata = metadata();\n  EntryT* local_entries = entries();\n\n  for (ProbeSequence s(hash_index, alloc_size());; s.Next()) {\n    ssize_t group_index = s.index();\n    auto g = MetadataGroup::Load(local_metadata, group_index);\n\n    if (auto empty_match = g.MatchEmpty()) {\n      ssize_t index = group_index + empty_match.index();\n      local_metadata[index] = tag | MetadataGroup::PresentMask;\n      return &local_entries[index];\n    }\n\n    // Otherwise we continue probing.\n  }\n}\n\n// Apply our doubling growth strategy and (re-)check invariants around table\n// size.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::ComputeNextAllocSize(\n    ssize_t old_alloc_size) -> ssize_t {\n  CARBON_DCHECK(llvm::isPowerOf2_64(old_alloc_size),\n                \"Expected a power of two!\");\n  ssize_t new_alloc_size;\n  bool overflow = __builtin_mul_overflow(old_alloc_size, 2, &new_alloc_size);\n  CARBON_CHECK(!overflow, \"Computing the new size overflowed `ssize_t`!\");\n  return new_alloc_size;\n}\n\n// Compute the growth threshold for a given size.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT,\n              InputKeyContextT>::GrowthThresholdForAllocSize(ssize_t alloc_size)\n    -> ssize_t {\n  // We use a 7/8ths load factor to trigger growth.\n  return alloc_size - alloc_size / 8;\n}\n\n// Optimized routine for growing to the next alloc size.\n//\n// A particularly common and important-to-optimize path is growing to the next\n// alloc size, which will always be a doubling of the allocated size. This\n// allows an important optimization -- we're adding exactly one more high bit to\n// the hash-computed index for each entry. This in turn means we can classify\n// every entry in the table into three cases:\n//\n// 1) The new high bit is zero, the entry is at the same index in the new\n//    table as the old.\n//\n// 2) The new high bit is one, the entry is at the old index plus the old\n//    size.\n//\n// 3) The entry's current index doesn't match the initial hash index because\n//    it required some amount of probing to find an empty slot.\n//\n// The design of the hash table tries to minimize how many entries fall into\n// case (3), so we expect the vast majority of entries to be in (1) or (2). This\n// lets us model growth notionally as copying the hashtable twice into the lower\n// and higher halves of the new allocation, clearing out the now-empty slots\n// (from both deleted entries and entries in the other half of the table after\n// growth), and inserting any probed elements. That model in turn is much more\n// efficient than re-inserting all of the elements as it avoids the unnecessary\n// parts of insertion and avoids interleaving random accesses for the probed\n// elements. But most importantly, for trivially relocatable types it allows us\n// to use `memcpy` rather than moving the elements individually.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\nauto BaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowToNextAllocSize(\n    KeyContextT key_context) -> void {\n  // We collect the probed elements in a small vector for re-insertion. It is\n  // tempting to reuse the already allocated storage, but doing so appears to\n  // be a (very slight) performance regression. These are relatively rare and\n  // storing them into the existing storage creates stores to the same regions\n  // of memory we're reading. Moreover, it requires moving both the key and the\n  // value twice, and doing the `memcpy` widening for relocatable types before\n  // the group walk rather than after the group walk. In practice, between the\n  // statistical rareness and using a large small size buffer here on the stack,\n  // we can handle this most efficiently with temporary, additional storage.\n  llvm::SmallVector<std::pair<ssize_t, HashCode>, 128> probed_indices;\n\n  // Create locals for the old state of the table.\n  ssize_t old_size = alloc_size();\n  CARBON_DCHECK(old_size > 0);\n\n  bool old_small = is_small();\n  Storage* old_storage = storage();\n  uint8_t* old_metadata = metadata();\n  EntryT* old_entries = entries();\n\n#ifndef NDEBUG\n  // Count how many of the old table slots will end up being empty after we grow\n  // the table. This is both the currently empty slots, but also the deleted\n  // slots because we clear them to empty and re-insert everything that had any\n  // probing.\n  ssize_t debug_empty_count =\n      llvm::count(llvm::ArrayRef(old_metadata, old_size), MetadataGroup::Empty);\n  ssize_t debug_deleted_count = llvm::count(\n      llvm::ArrayRef(old_metadata, old_size), MetadataGroup::Deleted);\n  CARBON_DCHECK(\n      debug_empty_count >= (old_size - GrowthThresholdForAllocSize(old_size)),\n      \"debug_empty_count: {0}, debug_deleted_count: {1}, size: {2}\",\n      debug_empty_count, debug_deleted_count, old_size);\n#endif\n\n  // Configure for the new size and allocate the new storage.\n  ssize_t new_size = ComputeNextAllocSize(old_size);\n  alloc_size() = new_size;\n  storage() = Allocate(new_size);\n  growth_budget_ = GrowthThresholdForAllocSize(new_size);\n\n  // Now extract the new components of the table.\n  uint8_t* new_metadata = metadata();\n  EntryT* new_entries = entries();\n\n  // Walk the metadata groups, clearing deleted to empty, duplicating the\n  // metadata for the low and high halves, and updating it based on where each\n  // entry will go in the new table. The updated metadata group is written to\n  // the new table, and for non-trivially relocatable entry types, the entry is\n  // also moved to its new location.\n  ssize_t count = 0;\n  for (ssize_t group_index = 0; group_index < old_size;\n       group_index += GroupSize) {\n    auto low_g = MetadataGroup::Load(old_metadata, group_index);\n    // Make sure to match present elements first to enable pipelining with\n    // clearing.\n    auto present_matched_range = low_g.MatchPresent();\n    low_g.ClearDeleted();\n    MetadataGroup high_g;\n    if constexpr (MetadataGroup::FastByteClear) {\n      // When we have a fast byte clear, we can update the metadata for the\n      // growth in-register and store at the end.\n      high_g = low_g;\n    } else {\n      // If we don't have a fast byte clear, we can store the metadata group\n      // eagerly here and overwrite bytes with a byte store below instead of\n      // clearing the byte in-register.\n      low_g.Store(new_metadata, group_index);\n      low_g.Store(new_metadata, group_index | old_size);\n    }\n    for (ssize_t byte_index : present_matched_range) {\n      ++count;\n      ssize_t old_index = group_index + byte_index;\n      if constexpr (!MetadataGroup::FastByteClear) {\n        CARBON_DCHECK(new_metadata[old_index] == old_metadata[old_index]);\n        CARBON_DCHECK(new_metadata[old_index | old_size] ==\n                      old_metadata[old_index]);\n      }\n      HashCode hash =\n          key_context.HashKey(old_entries[old_index].key(), ComputeSeed());\n      ssize_t old_hash_index = hash.ExtractIndexAndTag<7>().first &\n                               ComputeProbeMaskFromSize(old_size);\n      if (LLVM_UNLIKELY(old_hash_index != group_index)) {\n        probed_indices.push_back({old_index, hash});\n        if constexpr (MetadataGroup::FastByteClear) {\n          low_g.ClearByte(byte_index);\n          high_g.ClearByte(byte_index);\n        } else {\n          new_metadata[old_index] = MetadataGroup::Empty;\n          new_metadata[old_index | old_size] = MetadataGroup::Empty;\n        }\n        continue;\n      }\n      ssize_t new_index = hash.ExtractIndexAndTag<7>().first &\n                          ComputeProbeMaskFromSize(new_size);\n      CARBON_DCHECK(new_index == old_hash_index ||\n                    new_index == (old_hash_index | old_size));\n      // Toggle the newly added bit of the index to get to the other possible\n      // target index.\n      if constexpr (MetadataGroup::FastByteClear) {\n        (new_index == old_hash_index ? high_g : low_g).ClearByte(byte_index);\n        new_index += byte_index;\n      } else {\n        new_index += byte_index;\n        new_metadata[new_index ^ old_size] = MetadataGroup::Empty;\n      }\n\n      // If we need to explicitly move (and destroy) the key or value, do so\n      // here where we already know its target.\n      if constexpr (!EntryT::IsTriviallyRelocatable) {\n        new_entries[new_index].MoveFrom(std::move(old_entries[old_index]));\n      }\n    }\n    if constexpr (MetadataGroup::FastByteClear) {\n      low_g.Store(new_metadata, group_index);\n      high_g.Store(new_metadata, (group_index | old_size));\n    }\n  }\n  CARBON_DCHECK((count - static_cast<ssize_t>(probed_indices.size())) ==\n                (new_size - llvm::count(llvm::ArrayRef(new_metadata, new_size),\n                                        MetadataGroup::Empty)));\n#ifndef NDEBUG\n  CARBON_DCHECK((debug_empty_count + debug_deleted_count) ==\n                (old_size - count));\n  CARBON_DCHECK(llvm::count(llvm::ArrayRef(new_metadata, new_size),\n                            MetadataGroup::Empty) ==\n                debug_empty_count + debug_deleted_count +\n                    static_cast<ssize_t>(probed_indices.size()) + old_size);\n#endif\n\n  // If the keys or values are trivially relocatable, we do a bulk memcpy of\n  // them into place. This will copy them into both possible locations, which is\n  // fine. One will be empty and clobbered if reused or ignored. The other will\n  // be the one used. This might seem like it needs it to be valid for us to\n  // create two copies, but it doesn't. This produces the exact same storage as\n  // copying the storage into the wrong location first, and then again into the\n  // correct location. Only one is live and only one is destroyed.\n  if constexpr (EntryT::IsTriviallyRelocatable) {\n    memcpy(new_entries, old_entries, old_size * sizeof(EntryT));\n    memcpy(new_entries + old_size, old_entries, old_size * sizeof(EntryT));\n  }\n\n  // We then need to do a normal insertion for anything that was probed before\n  // growth, but we know we'll find an empty slot, so leverage that.\n  for (auto [old_index, hash] : probed_indices) {\n    EntryT* new_entry = InsertIntoEmpty(hash);\n    new_entry->MoveFrom(std::move(old_entries[old_index]));\n  }\n  CARBON_DCHECK(count ==\n                (new_size - llvm::count(llvm::ArrayRef(new_metadata, new_size),\n                                        MetadataGroup::Empty)));\n  growth_budget_ -= count;\n  CARBON_DCHECK(growth_budget_ ==\n                (GrowthThresholdForAllocSize(new_size) -\n                 (new_size - llvm::count(llvm::ArrayRef(new_metadata, new_size),\n                                         MetadataGroup::Empty))));\n  CARBON_DCHECK(growth_budget_ > 0 &&\n                \"Must still have a growth budget after rehash!\");\n\n  if (!old_small) {\n    // Old isn't a small buffer, so we need to deallocate it.\n    Deallocate(old_storage, old_size);\n  }\n}\n\n// Grow the hashtable to create space and then insert into it. Returns the\n// selected insertion entry. Never returns null. In addition to growing and\n// selecting the insertion entry, this routine updates the metadata array so\n// that this function can be directly called and the result returned from\n// `InsertImpl`.\ntemplate <typename InputKeyT, typename InputValueT, typename InputKeyContextT>\n[[clang::noinline]] auto\nBaseImpl<InputKeyT, InputValueT, InputKeyContextT>::GrowAndInsert(\n    HashCode hash, KeyContextT key_context) -> EntryT* {\n  GrowToNextAllocSize(key_context);\n\n  // And insert the lookup_key into an index in the newly grown map and return\n  // that index for use.\n  --growth_budget_;\n  return InsertIntoEmpty(hash);\n}\n\ntemplate <typename InputBaseT, ssize_t SmallSize>\nTableImpl<InputBaseT, SmallSize>::TableImpl(const TableImpl& arg)\n  requires(BaseT::EntryT::IsCopyable)\n    : BaseT(arg.alloc_size(), arg.growth_budget_, SmallSize) {\n  // Check for completely broken objects. These invariants should be true even\n  // in a moved-from state.\n  CARBON_DCHECK(arg.alloc_size() == 0 || !arg.is_small() ||\n                arg.alloc_size() == SmallSize);\n  CARBON_DCHECK(arg.small_alloc_size_ == SmallSize);\n  CARBON_DCHECK(this->small_alloc_size_ == SmallSize);\n\n  if (this->alloc_size() != 0) {\n    SetUpStorage();\n    this->CopySlotsFrom(arg);\n  }\n}\n\ntemplate <typename InputBaseT, ssize_t SmallSize>\nauto TableImpl<InputBaseT, SmallSize>::operator=(const TableImpl& arg)\n    -> TableImpl&\n  requires(BaseT::EntryT::IsCopyable)\n{\n  // Check for completely broken objects. These invariants should be true even\n  // in a moved-from state.\n  CARBON_DCHECK(arg.alloc_size() == 0 || !arg.is_small() ||\n                arg.alloc_size() == SmallSize);\n  CARBON_DCHECK(arg.small_alloc_size_ == SmallSize);\n  CARBON_DCHECK(this->small_alloc_size_ == SmallSize);\n\n  // We have to end up with an allocation size exactly equivalent to the\n  // incoming argument to avoid re-hashing every entry in the table, which isn't\n  // possible without key context.\n  if (arg.alloc_size() == this->alloc_size()) {\n    // No effective way for self-assignment to fall out of an efficient\n    // implementation so detect and bypass here. Similarly, if both are in a\n    // moved-from state, there is nothing to do.\n    if (&arg == this || this->alloc_size() == 0) {\n      return *this;\n    }\n    CARBON_DCHECK(arg.storage() != this->storage());\n    if constexpr (!EntryT::IsTriviallyDestructible) {\n      this->view_impl_.ForEachEntry([](EntryT& entry) { entry.Destroy(); },\n                                    [](auto...) {});\n    }\n  } else {\n    // The sizes don't match so destroy everything and re-setup the table\n    // storage.\n    this->Destroy();\n    this->alloc_size() = arg.alloc_size();\n    // If `arg` is moved-from, we've clear out our elements and put ourselves\n    // into a moved-from state. We're done.\n    if (this->alloc_size() == 0) {\n      return *this;\n    }\n    SetUpStorage();\n  }\n  this->growth_budget_ = arg.growth_budget_;\n  this->CopySlotsFrom(arg);\n  return *this;\n}\n\n// Puts the incoming table into a moved-from state that can be destroyed or\n// re-initialized but must not be used otherwise.\ntemplate <typename InputBaseT, ssize_t SmallSize>\nTableImpl<InputBaseT, SmallSize>::TableImpl(TableImpl&& arg) noexcept\n    : BaseT(arg.alloc_size(), arg.growth_budget_, SmallSize) {\n  // Check for completely broken objects. These invariants should be true even\n  // in a moved-from state.\n  CARBON_DCHECK(arg.alloc_size() == 0 || !arg.is_small() ||\n                arg.alloc_size() == SmallSize);\n  CARBON_DCHECK(arg.small_alloc_size_ == SmallSize);\n  CARBON_DCHECK(this->small_alloc_size_ == SmallSize);\n  this->MoveFrom(std::move(arg), small_storage());\n}\n\ntemplate <typename InputBaseT, ssize_t SmallSize>\nauto TableImpl<InputBaseT, SmallSize>::operator=(TableImpl&& arg) noexcept\n    -> TableImpl& {\n  // Check for completely broken objects. These invariants should be true even\n  // in a moved-from state.\n  CARBON_DCHECK(arg.alloc_size() == 0 || !arg.is_small() ||\n                arg.alloc_size() == SmallSize);\n  CARBON_DCHECK(arg.small_alloc_size_ == SmallSize);\n  CARBON_DCHECK(this->small_alloc_size_ == SmallSize);\n\n  // Destroy and deallocate our table.\n  this->Destroy();\n\n  // Defend against self-move by zeroing the size here before we start moving\n  // out of `arg`.\n  this->alloc_size() = 0;\n\n  // Setup to match argument and then finish the move.\n  this->alloc_size() = arg.alloc_size();\n  this->growth_budget_ = arg.growth_budget_;\n  this->MoveFrom(std::move(arg), small_storage());\n  return *this;\n}\n\ntemplate <typename InputBaseT, ssize_t SmallSize>\nTableImpl<InputBaseT, SmallSize>::~TableImpl() {\n  this->Destroy();\n}\n\n// Reset a table to its original state, including releasing any allocated\n// memory.\ntemplate <typename InputBaseT, ssize_t SmallSize>\nauto TableImpl<InputBaseT, SmallSize>::ResetImpl() -> void {\n  this->Destroy();\n\n  // Re-initialize the whole thing.\n  CARBON_DCHECK(this->small_alloc_size() == SmallSize);\n  this->Construct(small_storage());\n}\n\ntemplate <typename InputBaseT, ssize_t SmallSize>\nauto TableImpl<InputBaseT, SmallSize>::small_storage() const -> Storage* {\n  if constexpr (SmallSize > 0) {\n    // Do a bunch of validation of the small size to establish our invariants\n    // when we know we have a non-zero small size.\n    static_assert(llvm::isPowerOf2_64(SmallSize),\n                  \"SmallSize must be a power of two for a hashed buffer!\");\n    static_assert(\n        SmallSize >= MaxGroupSize,\n        \"We require all small sizes to multiples of the largest group \"\n        \"size supported to ensure it can be used portably.  \");\n    static_assert(\n        (SmallSize % MaxGroupSize) == 0,\n        \"Small size must be a multiple of the max group size supported \"\n        \"so that we can allocate a whole number of groups.\");\n    // Implied by the max asserts above.\n    static_assert(SmallSize >= GroupSize);\n    static_assert((SmallSize % GroupSize) == 0);\n\n    static_assert(SmallSize >= alignof(StorageEntry<KeyT, ValueT>),\n                  \"Requested a small size that would require padding between \"\n                  \"metadata bytes and correctly aligned key and value types. \"\n                  \"Either a larger small size or a zero small size and heap \"\n                  \"allocation are required for this key and value type.\");\n\n    static_assert(offsetof(SmallStorage, entries) == SmallSize,\n                  \"Offset to entries in small size storage doesn't match \"\n                  \"computed offset!\");\n\n    return &small_storage_;\n  } else {\n    static_assert(\n        sizeof(TableImpl) == sizeof(BaseT),\n        \"Empty small storage caused a size difference and wasted space!\");\n\n    return nullptr;\n  }\n}\n\n// Helper to set up the storage of a table when a specific size has already been\n// set up. If possible, uses any small storage, otherwise allocates.\ntemplate <typename InputBaseT, ssize_t SmallSize>\nauto TableImpl<InputBaseT, SmallSize>::SetUpStorage() -> void {\n  CARBON_DCHECK(this->small_alloc_size() == SmallSize);\n  ssize_t local_size = this->alloc_size();\n  CARBON_DCHECK(local_size != 0);\n  if (local_size == SmallSize) {\n    this->storage() = small_storage();\n  } else {\n    this->storage() = BaseT::Allocate(local_size);\n  }\n}\n\n}  // namespace Carbon::RawHashtable\n\n#endif  // CARBON_COMMON_RAW_HASHTABLE_H_\n"
  },
  {
    "path": "common/raw_hashtable_benchmark_helpers.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/raw_hashtable_benchmark_helpers.h\"\n\n#include <array>\n#include <cstddef>\n#include <forward_list>\n#include <utility>\n#include <vector>\n\nnamespace Carbon::RawHashtable {\n\n// A local shuffle implementation built on Abseil to improve performance in\n// debug builds.\ntemplate <typename T>\nstatic auto Shuffle(llvm::MutableArrayRef<T> data, absl::BitGen& gen) {\n  for (ssize_t i : llvm::seq<ssize_t>(0, data.size() - 1)) {\n    ssize_t j = absl::Uniform<ssize_t>(gen, 0, data.size() - i);\n    if (j != 0) {\n      std::swap(data[i], data[i + j]);\n    }\n  }\n}\n\nconstexpr ssize_t NumChars = 64;\nstatic_assert(llvm::isPowerOf2_64(NumChars));\n\n// For benchmarking, we use short strings in a fixed distribution with common\n// characters. Real-world strings aren't uniform across ASCII or Unicode, etc.\n// And for *micro*-benchmarking we want to focus on the map overhead with short,\n// fast keys.\nstatic auto MakeChars() -> llvm::SmallVector<char> {\n  llvm::SmallVector<char> characters;\n  characters.reserve(NumChars);\n\n  // Start with `-` and `_`, and then add `a` - `z`, `A` - `Z`, and `0` - `9`.\n  characters.push_back('-');\n  characters.push_back('_');\n  llvm::append_range(characters, llvm::seq_inclusive('a', 'z'));\n  llvm::append_range(characters, llvm::seq_inclusive('A', 'Z'));\n  llvm::append_range(characters, llvm::seq_inclusive('0', '9'));\n  CARBON_CHECK(characters.size() == NumChars,\n               \"Expected exactly {0} characters, got {1} instead!\", NumChars,\n               characters.size());\n  return characters;\n}\n\nconstexpr ssize_t NumFourCharStrs = NumChars * NumChars * NumChars * NumChars;\nstatic_assert(llvm::isPowerOf2_64(NumFourCharStrs));\n\n// Compute every 4-character string in a shuffled array. This is a little memory\n// intense -- 64 MiB -- but ends up being much cheaper by letting us reliably\n// select a unique 4-character sequence to avoid collisions.\nstatic auto MakeFourCharStrs(llvm::ArrayRef<char> characters, absl::BitGen& gen)\n    -> llvm::SmallVector<std::array<char, 4>> {\n  constexpr ssize_t NumCharsMask = NumChars - 1;\n  constexpr ssize_t NumCharsShift = llvm::ConstantLog2<NumChars>();\n  llvm::SmallVector<std::array<char, 4>> four_char_strs(\n      llvm::map_range(llvm::seq(NumFourCharStrs), [&](auto i) {\n        std::array<char, 4> str;\n        str[0] = characters[i & NumCharsMask];\n        i >>= NumCharsShift;\n        str[1] = characters[i & NumCharsMask];\n        i >>= NumCharsShift;\n        str[2] = characters[i & NumCharsMask];\n        i >>= NumCharsShift;\n        CARBON_CHECK((i & ~NumCharsMask) == 0);\n        str[3] = characters[i];\n        return str;\n      }));\n  Shuffle<std::array<char, 4>>(four_char_strs, gen);\n  return four_char_strs;\n}\n\nconstexpr ssize_t NumRandomChars = static_cast<ssize_t>(64) * 1024;\n\n// Create a pool of random characters to sample from rather than computing this\n// for every string which is very slow in debug builds. We also pad this pool\n// with the max length so we can pull the full length from the end to simplify\n// the logic when wrapping around the pool.\nstatic auto MakeRandomChars(llvm::ArrayRef<char> characters, int max_length,\n                            absl::BitGen& gen) -> llvm::SmallVector<char> {\n  return llvm::SmallVector<char>(\n      llvm::map_range(llvm::seq(NumRandomChars + max_length), [&](auto /*i*/) {\n        return characters[absl::Uniform<ssize_t>(gen, 0, NumChars)];\n      }));\n}\n\n// Make a small vector of pointers into a single allocation of raw strings. The\n// allocated memory is expected to leak and must be transitively referenced by a\n// global. Each string has `length` size (which must be >= 4), and there are\n// `key_count` keys in the result. Each key is filled from the `random_chars`\n// until the last 4 characters. The last four characters of each string will be\n// taken sequentially from `four_char_strs` from some random start position to\n// ensure no duplicate keys are produced.\nstatic auto MakeRawStrKeys(ssize_t length, ssize_t key_count,\n                           llvm::ArrayRef<std::array<char, 4>> four_char_strs,\n                           llvm::ArrayRef<char> random_chars, absl::BitGen& gen)\n    -> llvm::SmallVector<const char*> {\n  llvm::SmallVector<const char*> raw_keys;\n  CARBON_CHECK(length >= 4);\n  ssize_t prefix_length = length - 4;\n\n  // Select a random start for indexing our four character strings.\n  ssize_t four_char_index = absl::Uniform<ssize_t>(gen, 0, NumFourCharStrs);\n\n  // Select a random start for the prefix random characters.\n  ssize_t random_chars_index = absl::Uniform<ssize_t>(gen, 0, NumRandomChars);\n\n  // Do a single memory allocation for all the keys of this length to\n  // avoid an excessive number of small and fragmented allocations. This\n  // memory is intentionally leaked as the keys are global and will\n  // themselves will point into it.\n  char* key_text = new char[key_count * length];\n\n  // Reserve all the key space since we know how many we'll need.\n  raw_keys.reserve(key_count);\n  for ([[gnu::unused]] ssize_t i : llvm::seq<ssize_t>(0, key_count)) {\n    memcpy(key_text, random_chars.data() + random_chars_index, prefix_length);\n    random_chars_index += prefix_length;\n    random_chars_index &= NumRandomChars - 1;\n    // Set the last four characters with this entry in the shuffled\n    // sequence.\n    memcpy(key_text + prefix_length, four_char_strs[four_char_index].data(), 4);\n    // Step through the shuffled sequence. We start at a random position,\n    // so we need to wrap around the end.\n    ++four_char_index;\n    four_char_index &= NumFourCharStrs - 1;\n\n    // And finally save the start pointer as one of our raw keys.\n    raw_keys.push_back(key_text);\n    key_text += length;\n  }\n  return raw_keys;\n}\n\n// Build up a large collection of random and unique string keys. This is\n// actually a relatively expensive operation due to needing to build all the\n// random string text. As a consequence, the initializer of this global is\n// somewhat performance tuned to ensure benchmarks don't take an excessive\n// amount of time to run or use an excessive amount of memory.\nstatic absl::NoDestructor<llvm::SmallVector<llvm::StringRef>> raw_str_keys{[] {\n  llvm::SmallVector<llvm::StringRef> keys(MaxNumKeys);\n  absl::BitGen gen;\n\n  std::array length_buckets = {\n      4, 4, 4, 4, 5, 5, 5, 5, 7, 7, 10, 10, 15, 25, 40, 80,\n  };\n  static_assert((MaxNumKeys % length_buckets.size()) == 0);\n  CARBON_CHECK(llvm::is_sorted(length_buckets));\n\n  // For each distinct length bucket, we build a vector of raw keys.\n  std::forward_list<llvm::SmallVector<const char*>> raw_keys_storage;\n  // And a parallel array to the length buckets with the raw keys of that\n  // length.\n  std::array<llvm::SmallVector<const char*>*, length_buckets.size()>\n      raw_keys_buckets;\n\n  llvm::SmallVector<char> characters = MakeChars();\n  llvm::SmallVector<std::array<char, 4>> four_char_strs =\n      MakeFourCharStrs(characters, gen);\n  llvm::SmallVector<char> random_chars =\n      MakeRandomChars(characters, /*max_length=*/length_buckets.back(), gen);\n\n  ssize_t prev_length = -1;\n  for (auto [length_index, length] : llvm::enumerate(length_buckets)) {\n    // We can detect repetitions in length as they are sorted.\n    if (length == prev_length) {\n      raw_keys_buckets[length_index] = raw_keys_buckets[length_index - 1];\n      continue;\n    }\n    prev_length = length;\n\n    // We want to compute all the keys of this length that we'll need.\n    ssize_t key_count = (MaxNumKeys / length_buckets.size()) *\n                        llvm::count(length_buckets, length);\n\n    raw_keys_buckets[length_index] = &raw_keys_storage.emplace_front(\n        MakeRawStrKeys(length, key_count, four_char_strs, random_chars, gen));\n  }\n\n  // Now build the actual key array from our intermediate storage by\n  // round-robin extracting from the length buckets.\n  for (auto [index, key] : llvm::enumerate(keys)) {\n    ssize_t bucket = index % length_buckets.size();\n    ssize_t length = length_buckets[bucket];\n    // We pop a raw key from the list of them associated with this bucket.\n    const char* raw_key = raw_keys_buckets[bucket]->pop_back_val();\n    // And build our key from that.\n    key = llvm::StringRef(raw_key, length);\n  }\n  // Check that in fact we popped every raw key into our main keys.\n  for (const auto& raw_keys : raw_keys_storage) {\n    CARBON_CHECK(raw_keys.empty());\n  }\n  return keys;\n}()};\n\nstatic absl::NoDestructor<llvm::SmallVector<int*>> raw_ptr_keys(llvm::map_range(\n    llvm::seq(MaxNumKeys), [](int index) { return new int{index}; }));\n\nstatic absl::NoDestructor<llvm::SmallVector<int>> raw_int_keys(llvm::map_range(\n    llvm::seq(MaxNumKeys), [](int index) { return index + 1; }));\n\ntemplate <int LowZeroBits>\nstatic absl::NoDestructor<llvm::SmallVector<LowZeroBitInt<LowZeroBits>>>\n    raw_low_zero_bit_int_keys(\n        llvm::map_range(llvm::seq(MaxNumKeys), [](int index) {\n          return LowZeroBitInt<LowZeroBits>(index + 1);\n        }));\n\nnamespace {\n\n// Allow generically dispatching over the specific key types we build and\n// support.\ntemplate <typename T>\nauto GetRawKeys() -> llvm::ArrayRef<T> {\n  if constexpr (std::is_same_v<T, llvm::StringRef>) {\n    return *raw_str_keys;\n  } else if constexpr (std::is_pointer_v<T>) {\n    return *raw_ptr_keys;\n  } else if constexpr (std::is_same_v<T, LowZeroBitInt<12>>) {\n    return *raw_low_zero_bit_int_keys<12>;\n  } else if constexpr (std::is_same_v<T, LowZeroBitInt<24>>) {\n    return *raw_low_zero_bit_int_keys<24>;\n  } else if constexpr (std::is_same_v<T, LowZeroBitInt<32>>) {\n    return *raw_low_zero_bit_int_keys<32>;\n  } else {\n    return *raw_int_keys;\n  }\n}\n\ntemplate <typename T>\nstatic absl::NoDestructor<\n    std::map<std::pair<ssize_t, ssize_t>, llvm::SmallVector<T>>>\n    lookup_keys_storage;\n\n// Given a particular table keys size and lookup keys size, provide an array ref\n// to a shuffled set of lookup keys.\n//\n// Because different table sizes pull from different sub-ranges of our raw keys,\n// we need to compute a distinct set of random keys in the table to use for\n// lookups depending on the table size. And we also want to have an even\n// distribution of key *sizes* throughout the lookup keys, and so we can't\n// compute a single lookup keys array of the maximum size. Instead we need to\n// compute a distinct special set of lookup keys for each pair of table and\n// lookup size, and then shuffle that specific set into a random sequence that\n// is returned. This function memoizes this sequence for each pair of sizes.\ntemplate <typename T>\nauto GetShuffledLookupKeys(ssize_t table_keys_size, ssize_t lookup_keys_size)\n    -> llvm::ArrayRef<T> {\n  // The raw keys aren't shuffled and round-robin through the sizes. We want to\n  // keep the total size of lookup keys used exactly the same across runs. So\n  // for a given size we always take the leading sequence from the raw keys for\n  // that size, duplicating as needed to get the desired lookup sequence size,\n  // and then shuffle the keys in that sequence to end up with a random sequence\n  // of keys. We store each of these shuffled sequences in a map to avoid\n  // repeatedly computing them.\n  llvm::SmallVector<T>& lookup_keys =\n      (*lookup_keys_storage<T>)[{table_keys_size, lookup_keys_size}];\n  if (lookup_keys.empty()) {\n    auto raw_keys = GetRawKeys<T>();\n    llvm::append_range(\n        lookup_keys,\n        llvm::map_range(llvm::seq(lookup_keys_size), [&](int index) {\n          return raw_keys[index % table_keys_size];\n        }));\n    absl::BitGen gen;\n    Shuffle<T>(lookup_keys, gen);\n  }\n  CARBON_CHECK(static_cast<ssize_t>(lookup_keys.size()) == lookup_keys_size);\n\n  return lookup_keys;\n}\n\n}  // namespace\n\ntemplate <typename T>\nauto GetKeysAndMissKeys(ssize_t table_keys_size)\n    -> std::pair<llvm::ArrayRef<T>, llvm::ArrayRef<T>> {\n  CARBON_CHECK(table_keys_size <= MaxNumKeys);\n  // The raw keys aren't shuffled and round-robin through the sizes. Take the\n  // tail of this sequence and shuffle it to form a random set of miss keys with\n  // a consistent total size.\n  static absl::NoDestructor<llvm::SmallVector<T>> miss_keys{[] {\n    llvm::SmallVector<T> keys(GetRawKeys<T>().take_back(NumOtherKeys));\n    CARBON_CHECK(keys.size() == NumOtherKeys);\n    absl::BitGen gen;\n    Shuffle<T>(keys, gen);\n    return keys;\n  }()};\n\n  return {GetRawKeys<T>().slice(0, table_keys_size), *miss_keys};\n}\ntemplate auto GetKeysAndMissKeys<int>(ssize_t size)\n    -> std::pair<llvm::ArrayRef<int>, llvm::ArrayRef<int>>;\ntemplate auto GetKeysAndMissKeys<int*>(ssize_t size)\n    -> std::pair<llvm::ArrayRef<int*>, llvm::ArrayRef<int*>>;\ntemplate auto GetKeysAndMissKeys<llvm::StringRef>(ssize_t size)\n    -> std::pair<llvm::ArrayRef<llvm::StringRef>,\n                 llvm::ArrayRef<llvm::StringRef>>;\ntemplate auto GetKeysAndMissKeys<LowZeroBitInt<12>>(ssize_t size)\n    -> std::pair<llvm::ArrayRef<LowZeroBitInt<12>>,\n                 llvm::ArrayRef<LowZeroBitInt<12>>>;\ntemplate auto GetKeysAndMissKeys<LowZeroBitInt<24>>(ssize_t size)\n    -> std::pair<llvm::ArrayRef<LowZeroBitInt<24>>,\n                 llvm::ArrayRef<LowZeroBitInt<24>>>;\ntemplate auto GetKeysAndMissKeys<LowZeroBitInt<32>>(ssize_t size)\n    -> std::pair<llvm::ArrayRef<LowZeroBitInt<32>>,\n                 llvm::ArrayRef<LowZeroBitInt<32>>>;\n\ntemplate <typename T>\nauto GetKeysAndHitKeys(ssize_t table_keys_size, ssize_t lookup_keys_size)\n    -> std::pair<llvm::ArrayRef<T>, llvm::ArrayRef<T>> {\n  CARBON_CHECK(table_keys_size <= MaxNumKeys);\n  CARBON_CHECK(lookup_keys_size <= MaxNumKeys);\n  return {GetRawKeys<T>().slice(0, table_keys_size),\n          GetShuffledLookupKeys<T>(table_keys_size, lookup_keys_size)};\n}\ntemplate auto GetKeysAndHitKeys<int>(ssize_t size, ssize_t lookup_keys_size)\n    -> std::pair<llvm::ArrayRef<int>, llvm::ArrayRef<int>>;\ntemplate auto GetKeysAndHitKeys<int*>(ssize_t size, ssize_t lookup_keys_size)\n    -> std::pair<llvm::ArrayRef<int*>, llvm::ArrayRef<int*>>;\ntemplate auto GetKeysAndHitKeys<llvm::StringRef>(ssize_t size,\n                                                 ssize_t lookup_keys_size)\n    -> std::pair<llvm::ArrayRef<llvm::StringRef>,\n                 llvm::ArrayRef<llvm::StringRef>>;\ntemplate auto GetKeysAndHitKeys<LowZeroBitInt<12>>(ssize_t size,\n                                                   ssize_t lookup_keys_size)\n    -> std::pair<llvm::ArrayRef<LowZeroBitInt<12>>,\n                 llvm::ArrayRef<LowZeroBitInt<12>>>;\ntemplate auto GetKeysAndHitKeys<LowZeroBitInt<24>>(ssize_t size,\n                                                   ssize_t lookup_keys_size)\n    -> std::pair<llvm::ArrayRef<LowZeroBitInt<24>>,\n                 llvm::ArrayRef<LowZeroBitInt<24>>>;\ntemplate auto GetKeysAndHitKeys<LowZeroBitInt<32>>(ssize_t size,\n                                                   ssize_t lookup_keys_size)\n    -> std::pair<llvm::ArrayRef<LowZeroBitInt<32>>,\n                 llvm::ArrayRef<LowZeroBitInt<32>>>;\n\ntemplate <typename T>\nauto DumpHashStatistics(llvm::ArrayRef<T> keys) -> void {\n  if (keys.size() < GroupSize) {\n    return;\n  }\n\n  // The hash table load factor is 7/8ths, so we want to add 1/7th of our\n  // current size, subtract one, and pick the next power of two to get the power\n  // of two where 7/8ths is greater than or equal to the incoming key size.\n  ssize_t expected_size =\n      llvm::NextPowerOf2(keys.size() + (keys.size() / 7) - 1);\n\n  constexpr int GroupShift = llvm::ConstantLog2<GroupSize>();\n\n  size_t mask = ComputeProbeMaskFromSize(expected_size);\n  uint64_t salt = ComputeSeed();\n  auto get_hash_index = [mask, salt](auto x) -> ssize_t {\n    auto [hash_index, _] = HashValue(x, salt).template ExtractIndexAndTag<7>();\n    return (hash_index & mask) >> GroupShift;\n  };\n\n  std::vector<std::vector<int>> grouped_key_indices(expected_size >>\n                                                    GroupShift);\n  for (auto [i, k] : llvm::enumerate(keys)) {\n    ssize_t hash_index = get_hash_index(k);\n    CARBON_CHECK(hash_index < (expected_size >> GroupShift), \"{0}\", hash_index);\n    grouped_key_indices[hash_index].push_back(i);\n  }\n  ssize_t max_group_index =\n      llvm::max_element(grouped_key_indices,\n                        [](const auto& lhs, const auto& rhs) {\n                          return lhs.size() < rhs.size();\n                        }) -\n      grouped_key_indices.begin();\n\n  // If the max number of collisions on the index is less than or equal to the\n  // group size, there shouldn't be any necessary probing (outside of deletion)\n  // and so this isn't interesting, skip printing.\n  if (grouped_key_indices[max_group_index].size() <= GroupSize) {\n    return;\n  }\n\n  llvm::errs() << \"keys: \" << keys.size()\n               << \"  groups: \" << grouped_key_indices.size() << \"\\n\"\n               << \"max group index: \" << llvm::formatv(\"{0x8}\", max_group_index)\n               << \"  collisions: \"\n               << grouped_key_indices[max_group_index].size() << \"\\n\";\n\n  for (auto i : llvm::ArrayRef(grouped_key_indices[max_group_index])\n                    .take_front(2 * GroupSize)) {\n    auto k = keys[i];\n    auto hash = static_cast<uint64_t>(HashValue(k, salt));\n    llvm::errs() << \"  key: \" << k\n                 << \"  salt: \" << llvm::formatv(\"{0:x16}\", salt)\n                 << \"  hash: \" << llvm::formatv(\"{0:x16}\", hash) << \"\\n\";\n  }\n}\ntemplate auto DumpHashStatistics(llvm::ArrayRef<int> keys) -> void;\ntemplate auto DumpHashStatistics(llvm::ArrayRef<LowZeroBitInt<12>> keys)\n    -> void;\ntemplate auto DumpHashStatistics(llvm::ArrayRef<LowZeroBitInt<24>> keys)\n    -> void;\ntemplate auto DumpHashStatistics(llvm::ArrayRef<LowZeroBitInt<32>> keys)\n    -> void;\ntemplate auto DumpHashStatistics(llvm::ArrayRef<int*> keys) -> void;\ntemplate auto DumpHashStatistics(llvm::ArrayRef<llvm::StringRef> keys) -> void;\n\n}  // namespace Carbon::RawHashtable\n"
  },
  {
    "path": "common/raw_hashtable_benchmark_helpers.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_RAW_HASHTABLE_BENCHMARK_HELPERS_H_\n#define CARBON_COMMON_RAW_HASHTABLE_BENCHMARK_HELPERS_H_\n\n#include <benchmark/benchmark.h>\n#include <sys/types.h>\n\n#include <boost/unordered/unordered_flat_map.hpp>\n#include <compare>\n#include <limits>\n#include <map>\n#include <vector>\n\n#include \"absl/base/no_destructor.h\"\n#include \"absl/random/random.h\"\n#include \"common/check.h\"\n#include \"common/hashing.h\"\n#include \"common/raw_hashtable.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/Sequence.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon::RawHashtable {\n\n// We want to support benchmarking with 16M keys plus up to 256 \"other\" keys\n// (for misses). The large number of keys helps check for performance hiccups\n// with especially large tables and when missing all levels of cache.\ninline constexpr ssize_t NumOtherKeys = 1 << 8;\ninline constexpr ssize_t MaxNumKeys = (1 << 24) + NumOtherKeys;\n\n// Get an array of main keys with the given `size`, which must be less than\n// 2^24. Also get a miss keys array of `NumOtherKeys` which has no collisions\n// with the main keys.\n//\n// For a given size, this will return the same arrays. This uses unsynchronized\n// global state, and so is thread hostile and must not be called before main.\ntemplate <typename T>\nauto GetKeysAndMissKeys(ssize_t table_keys_size)\n    -> std::pair<llvm::ArrayRef<T>, llvm::ArrayRef<T>>;\n\n// Get an array of main keys with the given `size`, which must be less than\n// 2^24. Also get a hit keys array of `lookup_keys_size` all of which will occur\n// in the may keys array. If the lookup size is larger than the main size, the\n// lookup sequence will contain duplicates.\n//\n// For a given size, this will return the same arrays. This uses unsynchronized\n// global state, and so is thread hostile and must not be called before main.\ntemplate <typename T>\nauto GetKeysAndHitKeys(ssize_t table_keys_size, ssize_t lookup_keys_size)\n    -> std::pair<llvm::ArrayRef<T>, llvm::ArrayRef<T>>;\n\n// Dump statistics about hashing the given keys.\ntemplate <typename T>\nauto DumpHashStatistics(llvm::ArrayRef<T> keys) -> void;\n\n// A type that works like an `int` but shifting in the specified number of low\n// zero bits. This is only intended for testing hash tables with especially\n// difficult to hash integer values, it isn't meant to be used otherwise.\ntemplate <int LowZeroBits>\nstruct LowZeroBitInt {\n  int64_t shifted_value = 0;\n\n  explicit constexpr LowZeroBitInt() = default;\n  explicit constexpr LowZeroBitInt(int64_t value)\n      : shifted_value(value << LowZeroBits) {}\n\n  friend auto operator<<(llvm::raw_ostream& out, const LowZeroBitInt& value)\n      -> llvm::raw_ostream& {\n    return out << value.shifted_value;\n  }\n\n  constexpr auto operator==(const LowZeroBitInt& rhs) const -> bool = default;\n  constexpr auto operator<=>(const LowZeroBitInt& rhs) const\n      -> std::strong_ordering = default;\n\n  friend auto CarbonHashValue(const LowZeroBitInt& value, uint64_t seed)\n      -> HashCode {\n    return HashValue(value.shifted_value, seed);\n  }\n\n  template <typename H>\n  friend auto AbslHashValue(H h, const LowZeroBitInt& value) -> H {\n    return H::combine(std::move(h), value.shifted_value);\n  }\n\n  friend auto hash_value(const LowZeroBitInt& value) -> size_t {\n    boost::hash<int64_t> hasher;\n    return hasher(value.shifted_value);\n  }\n};\n\n// Convert values used in hashtable benchmarking to a bool. This is used to form\n// dependencies between values stored in the hashtable between benchmark\n// iterations.\ntemplate <typename T>\nauto ValueToBool(T value) -> bool {\n  if constexpr (std::is_same_v<T, llvm::StringRef>) {\n    return value.size() > 0;\n  } else if constexpr (std::is_pointer_v<T>) {\n    return value != nullptr;\n  } else {\n    // We want our keys to include `0` for integers, so use the largest value.\n    return value != std::numeric_limits<T>::max();\n  }\n}\n\ninline auto SizeArgs(benchmark::Benchmark* b) -> void {\n  // Benchmarks for \"miss\" operations only have one parameter -- the size of the\n  // table. These benchmarks use a fixed `NumOtherKeys` set of extra keys for\n  // each miss operation.\n  b->DenseRange(1, 4, 1);\n  b->Arg(8);\n  b->Arg(16);\n  b->Arg(32);\n\n  // For sizes >= 64 we first use the power of two which will have a low load\n  // factor, and then target exactly at our max load factor.\n  auto large_sizes = {64, 1 << 8, 1 << 12, 1 << 16, 1 << 20, 1 << 24};\n  for (auto s : large_sizes) {\n    b->Arg(s);\n  }\n  for (auto s : large_sizes) {\n    b->Arg(s - (s / 8));\n  }\n}\n\ninline auto HitArgs(benchmark::Benchmark* b) -> void {\n  // There are two parameters for benchmarks of \"hit\" operations. The first is\n  // the size of the hashtable itself. The second is the size of a buffer of\n  // random keys actually in the hashtable to use for the operations.\n  //\n  // For small sizes, we use a fixed `NumOtherKeys` lookup key count. This is\n  // enough to avoid patterns of queries training the branch predictor just from\n  // the keys themselves, while small enough to avoid significant L1 cache\n  // pressure.\n  b->ArgsProduct({benchmark::CreateDenseRange(1, 4, 1), {NumOtherKeys}});\n  b->Args({8, NumOtherKeys});\n  b->Args({16, NumOtherKeys});\n  b->Args({32, NumOtherKeys});\n\n  // For sizes >= 64 we first use the power of two which will have a low load\n  // factor, and then target exactly at our max load factor. Start the sizes\n  // list off with the powers of two, and the append a version of each power of\n  // two adjusted down to the load factor. We'll then build the benchmarks from\n  // these below.\n  std::vector<ssize_t> large_sizes = {64,      1 << 8,  1 << 12,\n                                      1 << 16, 1 << 20, 1 << 24};\n  for (auto i : llvm::seq<int>(0, large_sizes.size())) {\n    ssize_t s = large_sizes[i];\n    large_sizes.push_back(s - (s / 8));\n  }\n\n  for (auto s : large_sizes) {\n    b->Args({s, NumOtherKeys});\n\n    // Once the sizes are more than 4x the `NumOtherKeys` minimum lookup buffer\n    // size, also include 25% and 50% lookup buffer sizes which will\n    // increasingly exhaust the ability to keep matching entries in the cache.\n    if (s >= NumOtherKeys) {\n      b->Args({s, s / 4});\n      b->Args({s, s / 2});\n    }\n  }\n}\n\n// Provide some Dense{Map,Set}Info viable implementations for the key types\n// using Carbon's hashing framework. These let us benchmark the data structure\n// alone rather than the combination of data structure and hashing routine.\n//\n// We only provide these for benchmarking -- they are *not* necessarily suitable\n// for broader use. The Carbon hashing infrastructure has only been evaluated in\n// the context of its specific hashtable design.\ntemplate <typename T>\nstruct CarbonHashDI;\n\ntemplate <>\nstruct CarbonHashDI<int> {\n  static auto getEmptyKey() -> int { return -1; }\n  static auto getTombstoneKey() -> int { return -2; }\n  static auto getHashValue(const int val) -> unsigned {\n    return static_cast<uint64_t>(HashValue(val));\n  }\n  static auto isEqual(const int lhs, const int rhs) -> bool {\n    return lhs == rhs;\n  }\n};\n\ntemplate <int LowZeroBits>\nstruct CarbonHashDI<LowZeroBitInt<LowZeroBits>> {\n  using IntT = LowZeroBitInt<LowZeroBits>;\n  static auto getEmptyKey() -> IntT { return IntT(-1); }\n  static auto getTombstoneKey() -> IntT { return IntT(-2); }\n  static auto getHashValue(const IntT val) -> unsigned {\n    return static_cast<uint64_t>(HashValue(val));\n  }\n  static auto isEqual(const IntT lhs, const IntT rhs) -> bool {\n    return lhs == rhs;\n  }\n};\n\ntemplate <typename T>\nstruct CarbonHashDI<T*> {\n  static constexpr uintptr_t Log2MaxAlign = 12;\n\n  static auto getEmptyKey() -> T* {\n    auto val = static_cast<uintptr_t>(-1);\n    val <<= Log2MaxAlign;\n    // NOLINTNEXTLINE(performance-no-int-to-ptr): This is required by the API.\n    return reinterpret_cast<int*>(val);\n  }\n\n  static auto getTombstoneKey() -> T* {\n    auto val = static_cast<uintptr_t>(-2);\n    val <<= Log2MaxAlign;\n    // NOLINTNEXTLINE(performance-no-int-to-ptr): This is required by the API.\n    return reinterpret_cast<int*>(val);\n  }\n\n  static auto getHashValue(const T* ptr_val) -> unsigned {\n    return static_cast<uint64_t>(HashValue(ptr_val));\n  }\n\n  static auto isEqual(const T* lhs, const T* rhs) -> bool { return lhs == rhs; }\n};\n\ntemplate <>\nstruct CarbonHashDI<llvm::StringRef> {\n  static auto getEmptyKey() -> llvm::StringRef {\n    return llvm::StringRef(\n        // NOLINTNEXTLINE(performance-no-int-to-ptr): Required by the API.\n        reinterpret_cast<const char*>(~static_cast<uintptr_t>(0)), 0);\n  }\n\n  static auto getTombstoneKey() -> llvm::StringRef {\n    return llvm::StringRef(\n        // NOLINTNEXTLINE(performance-no-int-to-ptr): Required by the API.\n        reinterpret_cast<const char*>(~static_cast<uintptr_t>(1)), 0);\n  }\n  static auto getHashValue(llvm::StringRef val) -> unsigned {\n    return static_cast<uint64_t>(HashValue(val));\n  }\n  static auto isEqual(llvm::StringRef lhs, llvm::StringRef rhs) -> bool {\n    if (rhs.data() == getEmptyKey().data()) {\n      return lhs.data() == getEmptyKey().data();\n    }\n    if (rhs.data() == getTombstoneKey().data()) {\n      return lhs.data() == getTombstoneKey().data();\n    }\n    return lhs == rhs;\n  }\n};\n\ntemplate <typename TableT>\nauto ReportTableMetrics(const TableT& table, benchmark::State& state) -> void {\n  // While this count is \"iteration invariant\" (it should be exactly the same\n  // for every iteration as the set of keys is the same), we don't use that\n  // because it will scale this by the number of iterations. We want to\n  // display the metrics for this benchmark *parameter*, not what resulted\n  // from the number of iterations. That means we use the normal counter API\n  // without flags.\n  auto metrics = table.ComputeMetrics();\n  state.counters[\"P-compares\"] = metrics.probe_avg_compares;\n  state.counters[\"P-distance\"] = metrics.probe_avg_distance;\n  state.counters[\"P-fraction\"] =\n      static_cast<double>(metrics.probed_key_count) / metrics.key_count;\n  state.counters[\"Pmax-distance\"] = metrics.probe_max_distance;\n  state.counters[\"Pmax-compares\"] = metrics.probe_max_compares;\n  state.counters[\"Probed\"] = metrics.probed_key_count;\n\n  state.counters[\"Storage\"] = metrics.storage_bytes;\n\n  // Also compute how 'efficient' the storage is, 1.0 being zero bytes outside\n  // of key and value.\n  ssize_t element_size;\n  if constexpr (requires { TableT::ValueT; }) {\n    element_size =\n        sizeof(typename TableT::KeyT) + sizeof(typename TableT::ValueT);\n  } else {\n    element_size = sizeof(typename TableT::KeyT);\n  }\n  state.counters[\"Storage eff\"] =\n      static_cast<double>(metrics.key_count * element_size) /\n      metrics.storage_bytes;\n}\n\n}  // namespace Carbon::RawHashtable\n\nnamespace llvm {\n\n// Enable LLVM to hash our special stress testing integer type.\ntemplate <int LowZeroBits>\nstruct DenseMapInfo<Carbon::RawHashtable::LowZeroBitInt<LowZeroBits>> {\n  using IntT = Carbon::RawHashtable::LowZeroBitInt<LowZeroBits>;\n  static auto getEmptyKey() -> IntT { return IntT(-1); }\n  static auto getTombstoneKey() -> IntT { return IntT(-2); }\n  static auto getHashValue(const IntT val) -> unsigned {\n    return DenseMapInfo<int64_t>::getHashValue(val.shifted_value);\n  }\n  static auto isEqual(const IntT lhs, const IntT rhs) -> bool {\n    return lhs == rhs;\n  }\n};\n\n}  // namespace llvm\n\n#endif  // CARBON_COMMON_RAW_HASHTABLE_BENCHMARK_HELPERS_H_\n"
  },
  {
    "path": "common/raw_hashtable_metadata_group.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/raw_hashtable_metadata_group.h\"\n\n#include \"llvm/ADT/StringExtras.h\"\n\nnamespace Carbon::RawHashtable {\n\nauto MetadataGroup::Print(llvm::raw_ostream& out) const -> void {\n  out << \"[\";\n  llvm::ListSeparator sep;\n  for (uint8_t byte : metadata_bytes) {\n    out << sep << llvm::formatv(\"{0:x2}\", byte);\n  }\n  out << \"]\";\n}\n\n}  // namespace Carbon::RawHashtable\n"
  },
  {
    "path": "common/raw_hashtable_metadata_group.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_RAW_HASHTABLE_METADATA_GROUP_H_\n#define CARBON_COMMON_RAW_HASHTABLE_METADATA_GROUP_H_\n\n#include <cstddef>\n#include <cstring>\n#include <iterator>\n#include <type_traits>\n\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n#include \"llvm/ADT/Sequence.h\"\n#include \"llvm/ADT/bit.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n#include \"llvm/Support/MathExtras.h\"\n\n// Detect whether we can use SIMD accelerated implementations of the control\n// groups, and include the relevant platform specific APIs for the SIMD\n// implementations.\n//\n// Reference documentation for the SIMD APIs used here:\n// - https://arm-software.github.io/acle/neon_intrinsics/advsimd.html\n// - https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html\n#if defined(__SSSE3__)\n#include <x86intrin.h>\n#define CARBON_X86_SIMD_SUPPORT 1\n#elif defined(__ARM_NEON)\n#include <arm_neon.h>\n#define CARBON_NEON_SIMD_SUPPORT 1\n#endif\n\n// This namespace collects low-level utilities for implementing hashtable\n// data structures. This file only provides one of them:\n//\n// - Primitives to manage \"groups\" of hashtable entries that have densely packed\n//   control bytes we can scan rapidly as a group, often using SIMD facilities\n//   to process the entire group at once.\nnamespace Carbon::RawHashtable {\n\n// We define a constant max group size. The particular group size used in\n// practice may vary, but we want to have some upper bound used to ensure\n// memory allocation is done consistently across different architectures.\ninline constexpr ssize_t MaxGroupSize = 16;\n\n// This takes a collection of bits representing the results of looking for a\n// particular tag in this metadata group and determines the first position with\n// a match. The position is represented by either the least significant set bit\n// or the least significant non-zero byte, depending on `ByteEncoding`. When\n// represented with a non-zero byte, that byte must have at least its most\n// significant bit set, but may have other bits set to any value. Bits more\n// significant than the match may have any value provided there is at least one\n// match. Zero matches must be represented by a zero input.\n//\n// Some bits of the underlying value may be known-zero, which can optimize\n// various operations. These can be represented as a `ZeroMask`.\ntemplate <typename BitsInputT, bool ByteEncodingInput, BitsInputT ZeroMask = 0>\nclass BitIndex\n    : public Printable<BitIndex<BitsInputT, ByteEncodingInput, ZeroMask>> {\n public:\n  using BitsT = BitsInputT;\n  static constexpr bool ByteEncoding = ByteEncodingInput;\n\n  BitIndex() = default;\n  explicit BitIndex(BitsT bits) : bits_(bits) {}\n\n  friend auto operator==(BitIndex lhs, BitIndex rhs) -> bool {\n    if (lhs.empty() || rhs.empty()) {\n      return lhs.empty() == rhs.empty();\n    }\n    // For non-empty bit indices, compare the indices directly to ignore other\n    // (extraneous) parts of the incoming bits.\n    return lhs.index() == rhs.index();\n  }\n\n  auto Print(llvm::raw_ostream& out) const -> void {\n    out << llvm::formatv(\"{0:x}\", bits_);\n  }\n\n  explicit operator bool() const { return !empty(); }\n\n  // Returns true when there are no matches for the tag.\n  auto empty() const -> bool {\n    CARBON_DCHECK((bits_ & ZeroMask) == 0, \"Unexpected non-zero bits!\");\n    __builtin_assume((bits_ & ZeroMask) == 0);\n    return bits_ == 0;\n  }\n\n  // Returns the index of the first matched tag.\n  auto index() -> ssize_t {\n    CARBON_DCHECK(bits_ != 0, \"Cannot get an index from zero bits!\");\n    __builtin_assume(bits_ != 0);\n    ssize_t index = unscaled_index();\n\n    if constexpr (ByteEncoding) {\n      // Shift to scale out of the byte encoding.\n      index >>= ByteEncodingShift;\n    }\n\n    return index;\n  }\n\n  // Optimized tool to index a pointer `p` by `index()`.\n  template <typename T>\n  auto index_ptr(T* pointer) -> T* {\n    CARBON_DCHECK(bits_ != 0, \"Cannot get an index from zero bits!\");\n    __builtin_assume(bits_ != 0);\n    if constexpr (!ByteEncoding) {\n      return &pointer[unscaled_index()];\n    }\n\n    ssize_t index = unscaled_index();\n\n    // Scale the index as we counted zero *bits* and not zero *bytes*.\n    // However, we can fold that scale with the size of `T` when it is a power\n    // of two or divisible by 8.\n    CARBON_DCHECK(\n        (index & ((static_cast<size_t>(1) << ByteEncodingShift) - 1)) == 0);\n    if constexpr (sizeof(T) % 8 == 0) {\n      constexpr size_t FoldedScale = sizeof(T) / 8;\n      index *= FoldedScale;\n      return reinterpret_cast<T*>(\n          &reinterpret_cast<std::byte*>(pointer)[index]);\n    } else if constexpr (llvm::isPowerOf2_64(sizeof(T))) {\n      constexpr size_t ScaleShift = llvm::ConstantLog2<sizeof(T)>();\n      static_assert(ScaleShift <= ByteEncodingShift,\n                    \"Scaling by >=8 should be handled above!\");\n      constexpr size_t FoldedShift = ByteEncodingShift - ScaleShift;\n      index >>= FoldedShift;\n      return reinterpret_cast<T*>(\n          &reinterpret_cast<std::byte*>(pointer)[index]);\n    }\n\n    // Nothing we can fold here.\n    return &pointer[index >> ByteEncodingShift];\n  }\n\n private:\n  // When using a byte encoding, we'll need to shift any index by this amount.\n  static constexpr size_t ByteEncodingShift = 3;\n\n  auto unscaled_index() -> ssize_t {\n    if constexpr (!ByteEncoding) {\n      // Note the cast to `size_t` to force zero extending the result.\n      return static_cast<size_t>(llvm::countr_zero(bits_));\n    } else {\n      // The index is encoded in the high bit of each byte. We compute the index\n      // by counting the number of low zero bytes there are before the first\n      // byte with its high bit set. Rather that shifting the high bit to be the\n      // low bit and counting the trailing (least significant) zero bits\n      // directly, we instead byte-reverse the bits and count the *leading*\n      // (most significant) zero bits. While this may be a wash on CPUs with\n      // direct support for counting the trailing zero bits, AArch64 only\n      // supports counting the leading zero bits and requires a bit-reverse to\n      // count the trailing zero bits. Doing the byte-reverse approach\n      // essentially combines moving the high bit into the low bit and the\n      // reverse necessary for counting the zero bits. While this only removes\n      // one instruction, it is an instruction in the critical path of the\n      // hottest part of table lookup, and that critical path dependency height\n      // is few enough instructions that removing even one significantly impacts\n      // latency.\n      //\n      // We also cast to `size_t` to clearly zero-extend the result.\n      return static_cast<size_t>(llvm::countl_zero(llvm::byteswap(bits_)));\n    }\n  }\n\n  BitsT bits_ = 0;\n};\n\n// This is like `BitIndex`, but allows iterating through all of the matches.\n//\n// A key requirement for efficient iteration is that all of the matches are\n// represented with a single bit and there are no other bits set. For example,\n// with byte-encoded bit indices, exactly the high bit and no other bit of each\n// matching byte must be set. This is a stricter constraint than what `BitIndex`\n// alone would impose on any one of the matches.\ntemplate <typename BitIndexT, BitIndexT::BitsT ByteEncodingMask = 0>\nclass BitIndexRange\n    : public Printable<BitIndexRange<BitIndexT, ByteEncodingMask>> {\n public:\n  using BitsT = BitIndexT::BitsT;\n  static_assert(BitIndexT::ByteEncoding || ByteEncodingMask == 0,\n                \"Non-byte encoding must not have a byte encoding mask.\");\n\n  class Iterator\n      : public llvm::iterator_facade_base<Iterator, std::forward_iterator_tag,\n                                          ssize_t, ssize_t> {\n   public:\n    Iterator() = default;\n    explicit Iterator(BitsT bits) : bits_(bits) {}\n\n    friend auto operator==(const Iterator& lhs, const Iterator& rhs) -> bool {\n      return lhs.bits_ == rhs.bits_;\n    }\n\n    auto operator*() -> ssize_t& {\n      CARBON_DCHECK(bits_ != 0, \"Cannot get an index from zero bits!\");\n      __builtin_assume(bits_ != 0);\n      index_ = BitIndexT(bits_).index();\n      // Note that we store the index in a member so we can return a reference\n      // to it here as required to be a forward iterator.\n      return index_;\n    }\n\n    template <typename T>\n    auto index_ptr(T* pointer) -> T* {\n      return BitIndexT(bits_).index_ptr(pointer);\n    }\n\n    auto operator++() -> Iterator& {\n      CARBON_DCHECK(bits_ != 0, \"Must not increment past the end!\");\n      __builtin_assume(bits_ != 0);\n\n      if constexpr (ByteEncodingMask != 0) {\n        // Apply an increment mask to the bits first. This is used with the byte\n        // encoding when the mask isn't needed until we begin incrementing.\n        bits_ &= ByteEncodingMask;\n      }\n\n      // Clears the least significant set bit, effectively stepping to the next\n      // match.\n      bits_ &= (bits_ - 1);\n      return *this;\n    }\n\n   private:\n    ssize_t index_;\n    BitsT bits_ = 0;\n  };\n\n  BitIndexRange() = default;\n  explicit BitIndexRange(BitsT bits) : bits_(bits) {}\n\n  explicit operator bool() const { return !empty(); }\n  auto empty() const -> bool { return BitIndexT(bits_).empty(); }\n\n  auto begin() const -> Iterator { return Iterator(bits_); }\n  auto end() const -> Iterator { return Iterator(); }\n\n  friend auto operator==(BitIndexRange lhs, BitIndexRange rhs) -> bool {\n    if constexpr (ByteEncodingMask == 0) {\n      // If there is no encoding mask, we can just compare the bits directly.\n      return lhs.bits_ == rhs.bits_;\n    } else {\n      // Otherwise, compare the initial bit indices and the masked bits.\n      return BitIndexT(lhs.bits_) == BitIndexT(rhs.bits_) &&\n             (lhs.bits_ & ByteEncodingMask) == (rhs.bits_ & ByteEncodingMask);\n    }\n  }\n\n  // Define heterogeneous equality between a masked (the current type) and\n  // unmasked range. Requires a non-zero mask to avoid a redundant definition\n  // with the homogeneous equality.\n  friend auto operator==(BitIndexRange lhs, BitIndexRange<BitIndexT, 0> rhs)\n      -> bool\n    requires(ByteEncodingMask != 0)\n  {\n    // For mixed masked / unmasked comparison, we make sure the initial indices\n    // are the same and that the masked side (LHS) is the same after masking as\n    // the unmasked side (RHS).\n    return BitIndexT(lhs.bits_) == BitIndexT(rhs.bits_) &&\n           (lhs.bits_ & ByteEncodingMask) == rhs.bits_;\n  }\n\n  auto Print(llvm::raw_ostream& out) const -> void {\n    out << llvm::formatv(\"{0:x}\", bits_);\n  }\n\n  explicit operator BitsT() const { return bits_; }\n  explicit operator BitIndexT() const { return BitIndexT(bits_); }\n\n private:\n  template <typename FriendBitIndexT,\n            FriendBitIndexT::BitsT FriendByteEncodingMask>\n  friend class BitIndexRange;\n\n  BitsT bits_ = 0;\n};\n\n// A group of metadata bytes that can be manipulated together.\n//\n// The metadata bytes used Carbon's hashtable implementation are designed to\n// support being manipulating as groups, either using architecture specific SIMD\n// code sequences or using portable SIMD-in-an-integer-register code sequences.\n// These operations are unusually performance sensitive and in sometimes\n// surprising ways. The implementations here are crafted specifically to\n// optimize the particular usages in Carbon's hashtable and should not be\n// expected to be reusable in any other context.\n//\n// Throughout the functions operating on this type we try to use patterns with a\n// fallback portable implementation which can be directly used in the absence of\n// a SIMD implementation, but is also used (with the same code) to check that\n// any SIMD implementation produces the same result as the portable one. These\n// patterns help minimize un-compiled or un-tested paths through either portable\n// or SIMD code, regardless of which path is actually *used* on a particular\n// platform. To illustrate a common version of this pattern, we might have code\n// like:\n//\n// ```cpp\n// auto MetadataGroup::Operation(...) -> ... {\n//   ... portable_result;\n//   ... simd_result;\n//   if constexpr (!UseSimd || DebugSimd) {\n//     portable_result = PortableOperation(...);\n//   }\n//   if (UseSimd || DebugSimd) {\n//     simd_result = SimdOperation(...)\n//     CARBON_DCHECK(result == portable_result, \"{0}\", ...);\n//   }\n//   return UseSimd ? simd_result : portable_result;\n// }\n// ```\nclass MetadataGroup : public Printable<MetadataGroup> {\n public:\n  static constexpr ssize_t Size =\n#if CARBON_X86_SIMD_SUPPORT\n      16;\n#else\n      8;\n#endif\n  static_assert(Size >= 8);\n  static_assert(Size % 8 == 0);\n  static_assert(Size <= MaxGroupSize);\n  static_assert(MaxGroupSize % Size == 0);\n  static_assert(llvm::isPowerOf2_64(Size),\n                \"The group size must be a constant power of two so dividing by \"\n                \"it is a simple shift.\");\n  static constexpr ssize_t Mask = Size - 1;\n\n  // Each control byte can have special values. All special values have the\n  // most significant bit cleared to distinguish them from the seven hash bits\n  // stored when the control byte represents a full bucket.\n  //\n  // Otherwise, their values are chose primarily to provide efficient SIMD\n  // implementations of the common operations on an entire control group.\n  static constexpr uint8_t Empty = 0;\n  static constexpr uint8_t Deleted = 1;\n\n  static constexpr uint8_t PresentMask = 0b1000'0000;\n\n  // Whether to use a SIMD implementation. Even when we *support* a SIMD\n  // implementation, we do not always have to use it in the event that it is\n  // less efficient than the portable version.\n  static constexpr bool UseSimd =\n#if CARBON_X86_SIMD_SUPPORT\n      true;\n#else\n      false;\n#endif\n\n  // Some architectures make it much more efficient to build the match indices\n  // in a byte-encoded form rather than a bit-encoded form. This encoding\n  // changes verification and other aspects of our algorithms.\n  static constexpr bool ByteEncoding =\n#if CARBON_X86_SIMD_SUPPORT\n      false;\n#else\n      true;\n#endif\n  static_assert(!ByteEncoding || Size == 8,\n                \"We can only support byte encoding with a group size of 8.\");\n\n  // We need to indicate to users of the metadata group when they can hold a\n  // group value in a \"register\" (local variable) across clearing of individual\n  // bytes in the group efficiently. If the entire group can fit in an integer\n  // register, this works well and clients of the group should work to use the\n  // already-loaded value when clearing bytes. But when we have a larger group\n  // size, clearing the byte will typically require storing a byte to memory and\n  // re-loading the group. The usage patterns that need to clear bytes can in\n  // those cases avoid clearing a loaded group, and clear the byte directly in\n  // the larger metadata array.\n  static constexpr bool FastByteClear = Size == 8;\n\n  // Most and least significant bits set.\n  static constexpr uint64_t Msbs = 0x8080'8080'8080'8080ULL;\n  static constexpr uint64_t Lsbs = 0x0101'0101'0101'0101ULL;\n\n  using MatchIndex =\n      BitIndex<std::conditional_t<ByteEncoding, uint64_t, uint32_t>,\n               ByteEncoding,\n               /*ZeroMask=*/ByteEncoding ? 0 : (~0U << Size)>;\n\n  // Only one kind of portable matched range is needed.\n  using PortableMatchRange = BitIndexRange<MatchIndex>;\n\n  // We use specialized match range types for SIMD implementations to allow\n  // deferring the masking operation where useful. When that optimization\n  // doesn't apply, these will be the same type.\n  using SimdMatchRange =\n      BitIndexRange<MatchIndex, /*ByteEncodingMask=*/ByteEncoding ? Msbs : 0>;\n  using SimdMatchPresentRange = BitIndexRange<MatchIndex>;\n\n  // The public API range types can be either the portable or SIMD variations,\n  // selected here.\n  using MatchRange =\n      std::conditional_t<UseSimd, SimdMatchRange, PortableMatchRange>;\n  using MatchPresentRange =\n      std::conditional_t<UseSimd, SimdMatchPresentRange, PortableMatchRange>;\n\n  union {\n    uint8_t metadata_bytes[Size];\n    uint64_t metadata_ints[Size / 8];\n#if CARBON_NEON_SIMD_SUPPORT\n    uint8x8_t metadata_vec = {};\n    static_assert(sizeof(metadata_vec) == Size);\n#elif CARBON_X86_SIMD_SUPPORT\n    __m128i metadata_vec = {};\n    static_assert(sizeof(metadata_vec) == Size);\n#endif\n  };\n\n  auto Print(llvm::raw_ostream& out) const -> void;\n\n  friend auto operator==(MetadataGroup lhs, MetadataGroup rhs) -> bool {\n    return CompareEqual(lhs, rhs);\n  }\n\n  // The main API for this class. This API will switch between a portable and\n  // SIMD implementation based on what is most efficient, but in debug builds\n  // will cross check that the implementations do not diverge.\n\n  // Load and return a group of metadata bytes out of the main metadata array at\n  // a particular `index`. The index must be a multiple of `GroupSize`. This\n  // will arrange for the load to place the group into the correct structure for\n  // efficient register-based processing.\n  static auto Load(const uint8_t* metadata, ssize_t index) -> MetadataGroup;\n\n  // Store this metadata group into the main metadata array at the provided\n  // `index`. The index must be a multiple of `GroupSize`.\n  auto Store(uint8_t* metadata, ssize_t index) const -> void;\n\n  // Clear a byte of this group's metadata at the provided `byte_index` to the\n  // empty value.\n  //\n  // Note that this must only be called when `FastByteClear` is true -- in all\n  // other cases users of this class should arrange to clear individual bytes in\n  // the underlying array rather than using the group API. This is checked by a\n  // static_assert, and the function is templated so that it is not instantiated\n  // in the cases where it would not be valid.\n  template <bool IsCalled = true>\n  auto ClearByte(ssize_t byte_index) -> void;\n\n  // Clear all of this group's metadata bytes that indicate a deleted slot to\n  // the empty value.\n  auto ClearDeleted() -> void;\n\n  // Find all of the bytes of metadata in this group that are present and whose\n  // low 7 bits match the provided `tag`. The `tag` byte must have a clear high\n  // bit, only 7 bits of tag are used. Note that this means the provided tag is\n  // *not* the actual present metadata byte -- this function is responsible for\n  // mapping the tag into that form as it can do so more efficiently in some\n  // cases. A range over all of the byte indices which matched is returned.\n  auto Match(uint8_t tag) const -> MatchRange;\n\n  // Find all of the present bytes of metadata in this group. A range over all\n  // of the byte indices which are present is returned.\n  auto MatchPresent() const -> MatchPresentRange;\n\n  // Find the first byte of the metadata group that is empty and return that\n  // index. There is no order or position required for which of the bytes of\n  // metadata is considered \"first\", any model will do that makes it efficient\n  // to produce the matching index. Must return an empty match index if no bytes\n  // match the empty metadata.\n  auto MatchEmpty() const -> MatchIndex;\n\n  // Find the first byte of the metadata group that is deleted and return that\n  // index. There is no order or position required for which of the bytes of\n  // metadata is considered \"first\", any model will do that makes it efficient\n  // to produce the matching index. Must return an empty match index if no bytes\n  // match the deleted metadata.\n  auto MatchDeleted() const -> MatchIndex;\n\n private:\n  // Two classes only defined in the benchmark code are allowed to directly call\n  // the portable and SIMD implementations for benchmarking purposes.\n  friend class BenchmarkPortableMetadataGroup;\n  friend class BenchmarkSimdMetadataGroup;\n\n  // All SIMD variants that we have an implementation for should be enabled for\n  // debugging. This lets us maintain a SIMD implementation even if it is not\n  // used due to performance reasons, and easily re-enable it if the performance\n  // changes.\n  static constexpr bool DebugSimd =\n#if !defined(NDEBUG) && (CARBON_NEON_SIMD_SUPPORT || CARBON_X86_SIMD_SUPPORT)\n      true;\n#else\n      false;\n#endif\n\n  using MatchBitsT = MatchIndex::BitsT;\n\n  // A helper function to allow deducing the return type from the selected arm\n  // of a `constexpr` ternary.\n  template <bool Condition, typename LeftT, typename RightT>\n  static auto ConstexprTernary(LeftT lhs, RightT rhs) {\n    if constexpr (Condition) {\n      return lhs;\n    } else {\n      return rhs;\n    }\n  }\n\n  static auto CompareEqual(MetadataGroup lhs, MetadataGroup rhs) -> bool;\n\n  // Functions for validating the returned matches agree with what is predicted\n  // by the `byte_match` function. These either `CHECK`-fail or return true. To\n  // pass validation, the `*_bits` argument must have `0x80` for those bytes\n  // where `byte_match` returns true, and `0` for the rest.\n\n  // `VerifyIndexBits` is for functions that return `MatchIndex`, as they only\n  // promise to return accurate information up to the first match.\n  auto VerifyIndexBits(\n      MatchBitsT index_bits,\n      llvm::function_ref<auto(uint8_t byte)->bool> byte_match) const -> bool;\n  // `VerifyPortableRangeBits` is for functions that return `MatchRange`, and so\n  // it validates all the bytes of `range_bits`.\n  auto VerifyPortableRangeBits(\n      MatchBitsT range_bits,\n      llvm::function_ref<auto(uint8_t byte)->bool> byte_match) const -> bool;\n\n  // Portable implementations of each operation. These are used on platforms\n  // without SIMD support or where the portable implementation is faster than\n  // SIMD. They are heavily optimized even though they are not SIMD because we\n  // expect there to be platforms where the portable implementation can\n  // outperform SIMD. Their behavior and semantics exactly match the\n  // documentation for the un-prefixed functions.\n  //\n  // In debug builds, these also directly verify their results to help establish\n  // baseline functionality.\n  static auto PortableLoad(const uint8_t* metadata, ssize_t index)\n      -> MetadataGroup;\n  auto PortableStore(uint8_t* metadata, ssize_t index) const -> void;\n\n  auto PortableClearDeleted() -> void;\n\n  auto PortableMatch(uint8_t tag) const -> PortableMatchRange;\n  auto PortableMatchPresent() const -> PortableMatchRange;\n\n  auto PortableMatchEmpty() const -> MatchIndex;\n  auto PortableMatchDeleted() const -> MatchIndex;\n\n  static auto PortableCompareEqual(MetadataGroup lhs, MetadataGroup rhs)\n      -> bool;\n\n  // SIMD implementations of each operation. We minimize platform-specific APIs\n  // to reduce the scope of errors that can only be discovered building on one\n  // platform, so the bodies of these contain the platform specific code. Their\n  // behavior and semantics exactly match the documentation for the un-prefixed\n  // functions.\n  //\n  // These routines don't directly verify their results as we can build simpler\n  // debug checks by comparing them against the verified portable results.\n  static auto SimdLoad(const uint8_t* metadata, ssize_t index) -> MetadataGroup;\n  auto SimdStore(uint8_t* metadata, ssize_t index) const -> void;\n\n  auto SimdClearDeleted() -> void;\n\n  auto SimdMatch(uint8_t tag) const -> SimdMatchRange;\n  auto SimdMatchPresent() const -> SimdMatchPresentRange;\n\n  auto SimdMatchEmpty() const -> MatchIndex;\n  auto SimdMatchDeleted() const -> MatchIndex;\n\n  static auto SimdCompareEqual(MetadataGroup lhs, MetadataGroup rhs) -> bool;\n\n#if CARBON_X86_SIMD_SUPPORT\n  // A common routine for x86 SIMD matching that can be used for matching\n  // present, empty, and deleted bytes with equal efficiency.\n  auto X86SimdMatch(uint8_t match_byte) const -> SimdMatchRange;\n#endif\n};\n\n// Promote the size and mask to top-level constants as we'll need to operate on\n// the grouped structure outside of the metadata bytes.\ninline constexpr ssize_t GroupSize = MetadataGroup::Size;\ninline constexpr ssize_t GroupMask = MetadataGroup::Mask;\n\ninline auto MetadataGroup::Load(const uint8_t* metadata, ssize_t index)\n    -> MetadataGroup {\n  MetadataGroup portable_g;\n  if constexpr (!UseSimd || DebugSimd) {\n    portable_g = PortableLoad(metadata, index);\n    if constexpr (!UseSimd) {\n      return portable_g;\n    }\n  }\n  MetadataGroup g = SimdLoad(metadata, index);\n  CARBON_DCHECK(g == portable_g);\n  return g;\n}\n\ninline auto MetadataGroup::Store(uint8_t* metadata, ssize_t index) const\n    -> void {\n  if constexpr (!UseSimd) {\n    std::memcpy(metadata + index, &metadata_bytes, Size);\n  } else {\n    SimdStore(metadata, index);\n  }\n  CARBON_DCHECK(0 == std::memcmp(metadata + index, &metadata_bytes, Size));\n}\n\ntemplate <bool IsCalled>\ninline auto MetadataGroup::ClearByte(ssize_t byte_index) -> void {\n  static_assert(!IsCalled || FastByteClear,\n                \"Only use byte clearing when fast!\");\n  static_assert(!IsCalled || Size == 8,\n                \"The clear implementation assumes an 8-byte group.\");\n\n  metadata_ints[0] &= ~(static_cast<uint64_t>(0xff) << (byte_index * 8));\n}\n\ninline auto MetadataGroup::ClearDeleted() -> void {\n  MetadataGroup portable_g = *this;\n  MetadataGroup simd_g = *this;\n  if constexpr (!UseSimd || DebugSimd) {\n    portable_g.PortableClearDeleted();\n  }\n  if constexpr (UseSimd || DebugSimd) {\n    simd_g.SimdClearDeleted();\n    CARBON_DCHECK(\n        simd_g == portable_g,\n        \"SIMD cleared group '{0}' doesn't match portable cleared group '{1}'\",\n        simd_g, portable_g);\n  }\n  *this = UseSimd ? simd_g : portable_g;\n}\n\ninline auto MetadataGroup::Match(uint8_t tag) const -> MatchRange {\n  // The caller should provide us with the present byte hash, and not set any\n  // present bit tag on it so that this layer can manage tagging the high bit of\n  // a present byte.\n  CARBON_DCHECK((tag & PresentMask) == 0, \"{0:x}\", tag);\n\n  PortableMatchRange portable_result;\n  SimdMatchRange simd_result;\n  if constexpr (!UseSimd || DebugSimd) {\n    portable_result = PortableMatch(tag);\n  }\n  if constexpr (UseSimd || DebugSimd) {\n    simd_result = SimdMatch(tag);\n    CARBON_DCHECK(simd_result == portable_result,\n                  \"SIMD result '{0}' doesn't match portable result '{1}'\",\n                  simd_result, portable_result);\n  }\n  // Return whichever result we're using.\n  return ConstexprTernary<UseSimd>(simd_result, portable_result);\n}\n\ninline auto MetadataGroup::MatchPresent() const -> MatchPresentRange {\n  PortableMatchRange portable_result;\n  SimdMatchPresentRange simd_result;\n  if constexpr (!UseSimd || DebugSimd) {\n    portable_result = PortableMatchPresent();\n  }\n  if constexpr (UseSimd || DebugSimd) {\n    simd_result = SimdMatchPresent();\n    CARBON_DCHECK(simd_result == portable_result,\n                  \"SIMD result '{0}' doesn't match portable result '{1}'\",\n                  simd_result, portable_result);\n  }\n  // Return whichever result we're using.\n  return ConstexprTernary<UseSimd>(simd_result, portable_result);\n}\n\ninline auto MetadataGroup::MatchEmpty() const -> MatchIndex {\n  MatchIndex portable_result;\n  MatchIndex simd_result;\n  if constexpr (!UseSimd || DebugSimd) {\n    portable_result = PortableMatchEmpty();\n  }\n  if constexpr (UseSimd || DebugSimd) {\n    simd_result = SimdMatchEmpty();\n    CARBON_DCHECK(simd_result == portable_result,\n                  \"SIMD result '{0}' doesn't match portable result '{1}'\",\n                  simd_result, portable_result);\n  }\n  return UseSimd ? simd_result : portable_result;\n}\n\ninline auto MetadataGroup::MatchDeleted() const -> MatchIndex {\n  MatchIndex portable_result;\n  MatchIndex simd_result;\n  if constexpr (!UseSimd || DebugSimd) {\n    portable_result = PortableMatchDeleted();\n  }\n  if constexpr (UseSimd || DebugSimd) {\n    simd_result = SimdMatchDeleted();\n    CARBON_DCHECK(simd_result == portable_result,\n                  \"SIMD result '{0}' doesn't match portable result '{1}'\",\n                  simd_result, portable_result);\n  }\n  return UseSimd ? simd_result : portable_result;\n}\n\ninline auto MetadataGroup::CompareEqual(MetadataGroup lhs, MetadataGroup rhs)\n    -> bool {\n  bool portable_result;\n  bool simd_result;\n  if constexpr (!UseSimd || DebugSimd) {\n    portable_result = PortableCompareEqual(lhs, rhs);\n  }\n  if constexpr (UseSimd || DebugSimd) {\n    simd_result = SimdCompareEqual(lhs, rhs);\n    CARBON_DCHECK(simd_result == portable_result);\n  }\n  return UseSimd ? simd_result : portable_result;\n}\n\ninline auto MetadataGroup::VerifyIndexBits(\n    MatchBitsT index_bits,\n    llvm::function_ref<auto(uint8_t byte)->bool> byte_match) const -> bool {\n  for (ssize_t byte_index : llvm::seq<ssize_t>(0, Size)) {\n    if constexpr (!ByteEncoding) {\n      if (byte_match(metadata_bytes[byte_index])) {\n        CARBON_CHECK(((index_bits >> byte_index) & 1) == 1,\n                     \"Bit not set at matching byte index: {0}\", byte_index);\n        // Only the first match is needed, so stop scanning once found.\n        break;\n      }\n\n      CARBON_CHECK(((index_bits >> byte_index) & 1) == 0,\n                   \"Bit set at non-matching byte index: {0}\", byte_index);\n    } else {\n      // `index_bits` is byte-encoded rather than bit encoded, so extract a\n      // byte.\n      uint8_t index_byte = (index_bits >> (byte_index * 8)) & 0xFF;\n      if (byte_match(metadata_bytes[byte_index])) {\n        CARBON_CHECK(\n            (index_byte & 0x80) == 0x80,\n            \"Should have the high bit set for a matching byte, found: {0:x}\",\n            index_byte);\n        // Only the first match is needed so stop scanning once found.\n        break;\n      }\n\n      CARBON_CHECK(\n          index_byte == 0,\n          \"Should have no bits set for an unmatched byte, found: {0:x}\",\n          index_byte);\n    }\n  }\n  return true;\n}\n\ninline auto MetadataGroup::VerifyPortableRangeBits(\n    MatchBitsT range_bits,\n    llvm::function_ref<auto(uint8_t byte)->bool> byte_match) const -> bool {\n  for (ssize_t byte_index : llvm::seq<ssize_t>(0, Size)) {\n    if constexpr (!ByteEncoding) {\n      if (byte_match(metadata_bytes[byte_index])) {\n        CARBON_CHECK(((range_bits >> byte_index) & 1) == 1,\n                     \"Bit not set at matching byte index: {0}\", byte_index);\n      } else {\n        CARBON_CHECK(((range_bits >> byte_index) & 1) == 0,\n                     \"Bit set at non-matching byte index: {0}\", byte_index);\n      }\n    } else {\n      // `range_bits` is byte-encoded rather than bit encoded, so extract a\n      // byte.\n      uint8_t range_byte = (range_bits >> (byte_index * 8)) & 0xFF;\n      if (byte_match(metadata_bytes[byte_index])) {\n        CARBON_CHECK(range_byte == 0x80,\n                     \"Should just have the high bit set for a matching byte, \"\n                     \"found: {0:x}\",\n                     range_byte);\n      } else {\n        CARBON_CHECK(\n            range_byte == 0,\n            \"Should have no bits set for an unmatched byte, found: {0:x}\",\n            range_byte);\n      }\n    }\n  }\n  return true;\n}\n\ninline auto MetadataGroup::PortableLoad(const uint8_t* metadata, ssize_t index)\n    -> MetadataGroup {\n  MetadataGroup g;\n  static_assert(sizeof(g) == Size);\n  std::memcpy(&g.metadata_bytes, metadata + index, Size);\n  return g;\n}\n\ninline auto MetadataGroup::PortableStore(uint8_t* metadata, ssize_t index) const\n    -> void {\n  std::memcpy(metadata + index, &metadata_bytes, Size);\n}\n\ninline auto MetadataGroup::PortableClearDeleted() -> void {\n  for (uint64_t& metadata_int : metadata_ints) {\n    // Deleted bytes have only the least significant bits set, so to clear them\n    // we only need to clear the least significant bit. And empty bytes already\n    // have a clear least significant bit, so the only least significant bits we\n    // need to preserve are those of present bytes. The most significant bit of\n    // every present byte is set, so we take the most significant bit of each\n    // byte, shift it into the least significant bit position, and bit-or it\n    // with the compliment of `Lsbs`. This will have ones for every bit but the\n    // least significant bits, and ones for the least significant bits of every\n    // present byte.\n    metadata_int &= (~Lsbs | metadata_int >> 7);\n  }\n}\n\ninline auto MetadataGroup::PortableMatch(uint8_t tag) const -> MatchRange {\n  // The caller should provide us with the present byte hash, and not set any\n  // present bit tag on it so that this layer can manage tagging the high bit of\n  // a present byte.\n  CARBON_DCHECK((tag & PresentMask) == 0, \"{0:x}\", tag);\n\n  // Use a simple fallback approach for sizes beyond 8.\n  // TODO: Instead of a simple fallback, we should generalize the below\n  // algorithm for sizes above 8, even if to just exercise the same code on\n  // more platforms.\n  if constexpr (Size > 8) {\n    static_assert(Size <= 32, \"Sizes larger than 32 not yet supported!\");\n    uint32_t match_bits = 0;\n    uint32_t bit = 1;\n    uint8_t present_byte = tag | PresentMask;\n    for (ssize_t i : llvm::seq<ssize_t>(0, Size)) {\n      if (metadata_bytes[i] == present_byte) {\n        match_bits |= bit;\n      }\n      bit <<= 1;\n    }\n    return MatchRange(match_bits);\n  }\n\n  // This algorithm only works for matching *present* bytes. We leverage the\n  // set high bit in the present case as part of the algorithm. The whole\n  // algorithm has a critical path height of 4 operations, and does 6\n  // operations total on AArch64. The operation dependency graph is:\n  //\n  //          group | Msbs        Lsbs * match_byte + Msbs\n  //                 \\                /\n  //                 match_bits ^ broadcast\n  //                            |\n  //   group & Msbs        Msbs - match_bits\n  //          \\                /\n  //        group_Msbs & match_bits\n  //\n  // This diagram and the operation count are specific to AArch64 where we have\n  // a fused *integer* multiply-add operation.\n  //\n  // While it is superficially similar to the \"find zero bytes in a word\" bit\n  // math trick, it is different because this is designed to have no false\n  // positives and perfectly produce 0x80 for matching bytes and 0x00 for\n  // non-matching bytes. This is do-able because we constrain to only handle\n  // present matches which only require testing 7 bits and have a particular\n  // layout.\n\n  // Set the high bit of every byte to `1`. Any matching byte is a present byte\n  // and so always has this bit set as well, which means the xor below, in\n  // addition to zeroing the low 7 bits of any byte that matches the tag, also\n  // clears the high bit of every byte.\n  uint64_t match_bits = metadata_ints[0] | Msbs;\n  // Broadcast the match byte to all bytes, and mask in the present bits in the\n  // Msbs of each byte. We structure this as a multiply and an add because we\n  // know that the add cannot carry, and this way it can be lowered using\n  // combined multiply-add instructions if available.\n  uint64_t broadcast = Lsbs * tag + Msbs;\n  CARBON_DCHECK(broadcast == (Lsbs * tag | Msbs),\n                \"Unexpected carry from addition!\");\n\n  // Xor the broadcast byte pattern. This makes bytes with matches become 0, and\n  // clears the high-bits of non-matches. Note that if we are looking for a tag\n  // with the same value as `Empty` or `Deleted`, those bytes will be zero as\n  // well.\n  match_bits = match_bits ^ broadcast;\n  // Subtract each byte of `match_bits` from `0x80` bytes. After this, the high\n  // bit will be set only for those bytes that were zero.\n  match_bits = Msbs - match_bits;\n  // Zero everything but the high bits, and also zero the high bits of any bytes\n  // for \"not present\" slots in the original group. This avoids false positives\n  // for `Empty` and `Deleted` bytes in the metadata.\n  match_bits &= (metadata_ints[0] & Msbs);\n\n  // At this point, `match_bits` has the high bit set for bytes where the\n  // original group byte equals `tag` plus the high bit.\n  CARBON_DCHECK(VerifyPortableRangeBits(\n      match_bits, [&](uint8_t byte) { return byte == (tag | PresentMask); }));\n  return MatchRange(match_bits);\n}\n\ninline auto MetadataGroup::PortableMatchPresent() const -> MatchRange {\n  // Use a simple fallback approach for sizes beyond 8.\n  // TODO: Instead of a simple fallback, we should generalize the below\n  // algorithm for sizes above 8, even if to just exercise the same code on\n  // more platforms.\n  if constexpr (Size > 8) {\n    static_assert(Size <= 32, \"Sizes larger than 32 not yet supported!\");\n    uint32_t match_bits = 0;\n    uint32_t bit = 1;\n    for (ssize_t i : llvm::seq<ssize_t>(0, Size)) {\n      if (metadata_bytes[i] & PresentMask) {\n        match_bits |= bit;\n      }\n      bit <<= 1;\n    }\n    return MatchRange(match_bits);\n  }\n\n  // Want to keep the high bit of each byte, which indicates whether that byte\n  // represents a present slot.\n  uint64_t match_bits = metadata_ints[0] & Msbs;\n\n  CARBON_DCHECK(VerifyPortableRangeBits(\n      match_bits, [&](uint8_t byte) { return (byte & PresentMask) != 0; }));\n  return MatchRange(match_bits);\n}\n\ninline auto MetadataGroup::PortableMatchEmpty() const -> MatchIndex {\n  // Use a simple fallback approach for sizes beyond 8.\n  // TODO: Instead of a simple fallback, we should generalize the below\n  // algorithm for sizes above 8, even if to just exercise the same code on\n  // more platforms.\n  if constexpr (Size > 8) {\n    static_assert(Size <= 32, \"Sizes larger than 32 not yet supported!\");\n    uint32_t bit = 1;\n    for (ssize_t i : llvm::seq<ssize_t>(0, Size)) {\n      if (metadata_bytes[i] == Empty) {\n        return MatchIndex(bit);\n      }\n      bit <<= 1;\n    }\n    return MatchIndex(0);\n  }\n\n  // This sets the high bit of every byte in `match_bits` unless the\n  // corresponding metadata byte is 0. We take advantage of the fact that\n  // the metadata bytes in are non-zero only if they are either:\n  // - present: in which case the high bit of the byte will already be set; or\n  // - deleted: in which case the byte will be 1, and shifting it left by 7 will\n  //   cause the high bit to be set.\n  uint64_t match_bits = metadata_ints[0] | (metadata_ints[0] << 7);\n  // This inverts the high bits of the bytes, and clears the remaining bits.\n  match_bits = ~match_bits & Msbs;\n\n  // The high bits of the bytes of `match_bits` are set if the corresponding\n  // metadata byte is `Empty`.\n  CARBON_DCHECK(\n      VerifyIndexBits(match_bits, [](uint8_t byte) { return byte == Empty; }));\n  return MatchIndex(match_bits);\n}\n\ninline auto MetadataGroup::PortableMatchDeleted() const -> MatchIndex {\n  // Use a simple fallback approach for sizes beyond 8.\n  // TODO: Instead of a simple fallback, we should generalize the below\n  // algorithm for sizes above 8, even if to just exercise the same code on\n  // more platforms.\n  if constexpr (Size > 8) {\n    static_assert(Size <= 32, \"Sizes larger than 32 not yet supported!\");\n    uint32_t bit = 1;\n    for (ssize_t i : llvm::seq<ssize_t>(0, Size)) {\n      if (metadata_bytes[i] == Deleted) {\n        return MatchIndex(bit);\n      }\n      bit <<= 1;\n    }\n    return MatchIndex(0);\n  }\n\n  // This sets the high bit of every byte in `match_bits` unless the\n  // corresponding metadata byte is 1. We take advantage of the fact that the\n  // metadata bytes are not 1 only if they are either:\n  // - present: in which case the high bit of the byte will already be set; or\n  // - empty: in which case the byte will be 0, and in that case inverting and\n  //   shifting left by 7 will have the high bit set.\n  uint64_t match_bits = metadata_ints[0] | (~metadata_ints[0] << 7);\n  // This inverts the high bits of the bytes, and clears the remaining bits.\n  match_bits = ~match_bits & Msbs;\n\n  // The high bits of the bytes of `match_bits` are set if the corresponding\n  // metadata byte is `Deleted`.\n  CARBON_DCHECK(VerifyIndexBits(match_bits,\n                                [](uint8_t byte) { return byte == Deleted; }));\n  return MatchIndex(match_bits);\n}\n\ninline auto MetadataGroup::PortableCompareEqual(MetadataGroup lhs,\n                                                MetadataGroup rhs) -> bool {\n  return llvm::equal(lhs.metadata_bytes, rhs.metadata_bytes);\n}\n\ninline auto MetadataGroup::SimdLoad(const uint8_t* metadata, ssize_t index)\n    -> MetadataGroup {\n  MetadataGroup g;\n#if CARBON_NEON_SIMD_SUPPORT\n  g.metadata_vec = vld1_u8(metadata + index);\n#elif CARBON_X86_SIMD_SUPPORT\n  g.metadata_vec =\n      _mm_load_si128(reinterpret_cast<const __m128i*>(metadata + index));\n#else\n  static_assert(!UseSimd, \"Unimplemented SIMD operation\");\n  static_cast<void>(metadata);\n  static_cast<void>(index);\n#endif\n  return g;\n}\n\n// NOLINTNEXTLINE(readability-non-const-parameter): Mutation is in #if.\ninline auto MetadataGroup::SimdStore(uint8_t* metadata, ssize_t index) const\n    -> void {\n#if CARBON_NEON_SIMD_SUPPORT\n  vst1_u8(metadata + index, metadata_vec);\n#elif CARBON_X86_SIMD_SUPPORT\n  _mm_store_si128(reinterpret_cast<__m128i*>(metadata + index), metadata_vec);\n#else\n  static_assert(!UseSimd, \"Unimplemented SIMD operation\");\n  static_cast<void>(metadata);\n  static_cast<void>(index);\n#endif\n}\n\ninline auto MetadataGroup::SimdClearDeleted() -> void {\n#if CARBON_NEON_SIMD_SUPPORT\n  // There is no good Neon operation to implement this, so do it using integer\n  // code. This is reasonably fast, but unfortunate because it forces the group\n  // out of a SIMD register and into a general purpose register, which can have\n  // high latency.\n  metadata_ints[0] &= (~Lsbs | metadata_ints[0] >> 7);\n#elif CARBON_X86_SIMD_SUPPORT\n  // For each byte, use `metadata_vec` if the byte's high bit is set (indicating\n  // it is present), otherwise (it is empty or deleted) replace it with zero\n  // (representing empty).\n  metadata_vec =\n      _mm_blendv_epi8(_mm_setzero_si128(), metadata_vec, metadata_vec);\n#else\n  static_assert(!UseSimd && !DebugSimd, \"Unimplemented SIMD operation\");\n#endif\n}\n\ninline auto MetadataGroup::SimdMatch(uint8_t tag) const -> SimdMatchRange {\n  SimdMatchRange result;\n#if CARBON_NEON_SIMD_SUPPORT\n  // Broadcast byte we want to match to every byte in the vector.\n  auto match_byte_vec = vdup_n_u8(tag | PresentMask);\n  // Result bytes have all bits set for the bytes that match, so we have to\n  // clear everything but Msbs next.\n  auto match_byte_cmp_vec = vceq_u8(metadata_vec, match_byte_vec);\n  uint64_t match_bits = vreinterpret_u64_u8(match_byte_cmp_vec)[0];\n  // Note that the range will lazily mask to the Msbs as part of incrementing.\n  result = SimdMatchRange(match_bits);\n#elif CARBON_X86_SIMD_SUPPORT\n  result = X86SimdMatch(tag | PresentMask);\n#else\n  static_assert(!UseSimd && !DebugSimd, \"Unimplemented SIMD operation\");\n  static_cast<void>(tag);\n#endif\n  return result;\n}\n\ninline auto MetadataGroup::SimdMatchPresent() const -> SimdMatchPresentRange {\n  SimdMatchPresentRange result;\n#if CARBON_NEON_SIMD_SUPPORT\n  // Just extract the metadata directly.\n  uint64_t match_bits = vreinterpret_u64_u8(metadata_vec)[0];\n  // Even though the Neon SIMD range will do its own masking, we have to mask\n  // here so that `empty` is correct.\n  result = SimdMatchPresentRange(match_bits & Msbs);\n#elif CARBON_X86_SIMD_SUPPORT\n  // We arranged the byte vector so that present bytes have the high bit set,\n  // which this instruction extracts.\n  result = SimdMatchPresentRange(_mm_movemask_epi8(metadata_vec));\n#else\n  static_assert(!UseSimd && !DebugSimd, \"Unimplemented SIMD operation\");\n#endif\n  return result;\n}\n\ninline auto MetadataGroup::SimdMatchEmpty() const -> MatchIndex {\n  MatchIndex result;\n#if CARBON_NEON_SIMD_SUPPORT\n  // Compare all bytes with zero, as that is the empty byte value. Result will\n  // have all bits set for any input zero byte, so we zero all but the high bits\n  // below.\n  auto cmp_vec = vceqz_u8(metadata_vec);\n  uint64_t metadata_bits = vreinterpret_u64_u8(cmp_vec)[0];\n  // The matched range is likely to be tested for zero by the caller, and that\n  // test can often be folded into masking the bits with `Msbs` when we do that\n  // mask in the scalar domain rather than the SIMD domain. So we do the mask\n  // here rather than above prior to extracting the match bits.\n  result = MatchIndex(metadata_bits & Msbs);\n#elif CARBON_X86_SIMD_SUPPORT\n  // Even though we only need the first match rather than all matches, we don't\n  // have a more efficient way to compute this on x86 and so we reuse the\n  // general match infrastructure that computes all matches in a bit-encoding.\n  // We then convert it into a `MatchIndex` that just finds the first one.\n  result = static_cast<MatchIndex>(X86SimdMatch(Empty));\n#else\n  static_assert(!UseSimd && !DebugSimd, \"Unimplemented SIMD operation\");\n#endif\n  return result;\n}\n\ninline auto MetadataGroup::SimdMatchDeleted() const -> MatchIndex {\n  MatchIndex result;\n#if CARBON_NEON_SIMD_SUPPORT\n  // Broadcast the `Deleted` byte across the vector and compare the bytes of\n  // that with the metadata vector. The result will have all bits set for any\n  // input zero byte, so we zero all but the high bits below.\n  auto cmp_vec = vceq_u8(metadata_vec, vdup_n_u8(Deleted));\n  uint64_t match_bits = vreinterpret_u64_u8(cmp_vec)[0];\n  // The matched range is likely to be tested for zero by the caller, and that\n  // test can often be folded into masking the bits with `Msbs` when we do that\n  // mask in the scalar domain rather than the SIMD domain. So we do the mask\n  // here rather than above prior to extracting the match bits.\n  result = MatchIndex(match_bits & Msbs);\n#elif CARBON_X86_SIMD_SUPPORT\n  // Even though we only need the first match rather than all matches, we don't\n  // have a more efficient way to compute this on x86 and so we reuse the\n  // general match infrastructure that computes all matches in a bit-encoding.\n  // We then convert it into a `MatchIndex` that just finds the first one.\n  result = static_cast<MatchIndex>(X86SimdMatch(Deleted));\n#else\n  static_assert(!UseSimd && !DebugSimd, \"Unimplemented SIMD operation\");\n#endif\n  return result;\n}\n\ninline auto MetadataGroup::SimdCompareEqual(MetadataGroup lhs,\n                                            MetadataGroup rhs) -> bool {\n#if CARBON_NEON_SIMD_SUPPORT\n  return vreinterpret_u64_u8(vceq_u8(lhs.metadata_vec, rhs.metadata_vec))[0] ==\n         static_cast<uint64_t>(-1LL);\n#elif CARBON_X86_SIMD_SUPPORT\n  // Different x86 SIMD extensions provide different comparison functionality\n  // available.\n#if __SSE4_2__\n  // With SSE 4.2, we can directly test and branch in the SIMD domain on whether\n  // the two metadata vectors are equal.\n  return _mm_testc_si128(_mm_cmpeq_epi8(lhs.metadata_vec, rhs.metadata_vec),\n                         _mm_set1_epi8(0xff)) == 1;\n#else\n  // With older versions of SSE we have to extract the result of the comparison,\n  // much like we do when matching. That will have the usual bitmask\n  // representing equal bytes, and test for that exact bitmask in scalar code.\n  return _mm_movemask_epi8(_mm_cmpeq_epi8(lhs.metadata_vec,\n                                          rhs.metadata_vec)) == 0x0000'ffffU;\n#endif\n#else\n  static_assert(!UseSimd && !DebugSimd, \"Unimplemented SIMD operation\");\n  static_cast<void>(lhs);\n  static_cast<void>(rhs);\n  return false;\n#endif\n}\n\n#if CARBON_X86_SIMD_SUPPORT\ninline auto MetadataGroup::X86SimdMatch(uint8_t match_byte) const\n    -> MatchRange {\n  // Broadcast the byte we're matching against to all bytes in a vector, and\n  // compare those bytes with the metadata vector bytes.\n  auto match_byte_vec = _mm_set1_epi8(match_byte);\n  auto match_byte_cmp_vec = _mm_cmpeq_epi8(metadata_vec, match_byte_vec);\n  // Extract the result of each byte-wise comparison into the low bits of an\n  // integer.\n  uint32_t match_bits = _mm_movemask_epi8(match_byte_cmp_vec);\n  return MatchRange(match_bits);\n}\n#endif\n\n}  // namespace Carbon::RawHashtable\n\n#endif  // CARBON_COMMON_RAW_HASHTABLE_METADATA_GROUP_H_\n"
  },
  {
    "path": "common/raw_hashtable_metadata_group_benchmark.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <benchmark/benchmark.h>\n\n#include <algorithm>\n#include <array>\n#include <numeric>\n\n#include \"absl/random/random.h\"\n#include \"common/raw_hashtable_metadata_group.h\"\n\nnamespace Carbon::RawHashtable {\n\n// If we have any SIMD support, create dedicated benchmark utilities for the\n// portable and SIMD implementation so we can directly benchmark both.\n#if CARBON_NEON_SIMD_SUPPORT || CARBON_X86_SIMD_SUPPORT\n// Override the core API with explicit use of the portable API.\nclass BenchmarkPortableMetadataGroup : public MetadataGroup {\n public:\n  explicit BenchmarkPortableMetadataGroup(MetadataGroup g) : MetadataGroup(g) {}\n\n  static auto Load(uint8_t* metadata, ssize_t index)\n      -> BenchmarkPortableMetadataGroup {\n    return BenchmarkPortableMetadataGroup(PortableLoad(metadata, index));\n  }\n  auto Store(uint8_t* metadata, ssize_t index) const -> void {\n    PortableStore(metadata, index);\n  }\n\n  auto ClearDeleted() -> void { PortableClearDeleted(); }\n\n  auto Match(uint8_t present_byte) const -> PortableMatchRange {\n    return PortableMatch(present_byte);\n  }\n  auto MatchPresent() const -> PortableMatchRange {\n    return PortableMatchPresent();\n  }\n\n  auto MatchEmpty() const -> MatchIndex { return PortableMatchEmpty(); }\n  auto MatchDeleted() const -> MatchIndex { return PortableMatchDeleted(); }\n};\n\n// Override the core API with explicit use of the SIMD API.\nclass BenchmarkSimdMetadataGroup : public MetadataGroup {\n public:\n  explicit BenchmarkSimdMetadataGroup(MetadataGroup g) : MetadataGroup(g) {}\n\n  static auto Load(uint8_t* metadata, ssize_t index)\n      -> BenchmarkSimdMetadataGroup {\n    return BenchmarkSimdMetadataGroup(SimdLoad(metadata, index));\n  }\n  auto Store(uint8_t* metadata, ssize_t index) const -> void {\n    SimdStore(metadata, index);\n  }\n\n  auto ClearDeleted() -> void { SimdClearDeleted(); }\n\n  auto Match(uint8_t present_byte) const -> SimdMatchRange {\n    return SimdMatch(present_byte);\n  }\n  auto MatchPresent() const -> SimdMatchPresentRange {\n    return SimdMatchPresent();\n  }\n\n  auto MatchEmpty() const -> MatchIndex { return SimdMatchEmpty(); }\n  auto MatchDeleted() const -> MatchIndex { return SimdMatchDeleted(); }\n};\n#endif\n\nnamespace {\n\n// The number of metadata groups we use when benchmarking a particular scenario\n// of matching within a group.\nconstexpr ssize_t BenchSize = 256;\n\n#if CARBON_NEON_SIMD_SUPPORT || CARBON_X86_SIMD_SUPPORT\nusing PortableGroup = BenchmarkPortableMetadataGroup;\nusing SimdGroup = BenchmarkSimdMetadataGroup;\n#endif\n\nstruct BenchMetadata {\n  // The metadata for benchmarking, arranged in `BenchSize` groups, each one\n  // `GroupSize` in length. As a consequence, the size of this array will always\n  // be `BenchSize * GroupSize`.\n  llvm::MutableArrayRef<uint8_t> metadata;\n\n  // For benchmarking random matches in the metadata, each byte here is the tag\n  // that should be matched against the corresponding group of the metadata.\n  // Because this array parallels the *groups* of the metadata array, its size\n  // will be `BenchSize`. For other kinds, this is empty.\n  llvm::ArrayRef<uint8_t> bytes;\n};\n\nenum class BenchKind : uint8_t {\n  Random,\n  Empty,\n  Deleted,\n};\n\n// This routine should only be called once per `BenchKind` as the initializer of\n// a global variable below. It returns an `ArrayRef` pointing into\n// function-local static storage that provides our benchmark metadata.\n//\n// The returned array will have exactly `GroupSize` elements, each of\n// `BenchMetadata`. For the `BenchMetadata` at index `i`, there will be `i+1`\n// matches of that kind within each group of the metadata. This lets us\n// benchmark each of the possible match-counts for a group.\ntemplate <BenchKind Kind = BenchKind::Random>\nstatic auto BuildBenchMetadata() -> llvm::ArrayRef<BenchMetadata> {\n  // We build `GroupSize` elements of `BenchMetadata` below, and so we need\n  // `GroupSize` copies of each of these arrays to serve as inputs to it.\n  //\n  // The first storage is of `BenchSize` groups of metadata.\n  static uint8_t metadata_storage[GroupSize][BenchSize * GroupSize];\n  // When `Kind` is `Random`, each group above will have a *different* byte that\n  // matches in that group. This array stores those bytes for the benchmark to\n  // match against the group.\n  static uint8_t bytes_storage[GroupSize][BenchSize];\n\n  // The backing storage for the returned `ArrayRef`.\n  static BenchMetadata bm_storage[GroupSize];\n\n  absl::BitGen gen;\n  for (auto [bm_index, bm] : llvm::enumerate(bm_storage)) {\n    int match_count = bm_index + 1;\n\n    for (ssize_t g_index : llvm::seq<ssize_t>(0, BenchSize)) {\n      // Start by filling the group with random bytes.\n      llvm::MutableArrayRef group_bytes(\n          &metadata_storage[bm_index][g_index * GroupSize], GroupSize);\n      for (uint8_t& b : group_bytes) {\n        b = absl::Uniform<uint8_t>(gen) | MetadataGroup::PresentMask;\n      }\n\n      // Now we need up to `match_count` random indices into the group where\n      // we'll put a matching byte.\n      std::array<ssize_t, GroupSize> group_indices;\n      std::iota(group_indices.begin(), group_indices.end(), 0);\n      std::shuffle(group_indices.begin(), group_indices.end(), gen);\n\n      // Now cause the first match index to have the desired value.\n      ssize_t match_index = *group_indices.begin();\n      uint8_t& match_b = group_bytes[match_index];\n      switch (Kind) {\n        case BenchKind::Random: {\n          // Already a random value, but we need to  ensure it isn't one that\n          // repeats elsewhere in the group.\n          while (llvm::count(group_bytes, match_b) > 1) {\n            match_b = absl::Uniform<uint8_t>(gen) | MetadataGroup::PresentMask;\n          }\n          // Store this as the byte to search for in this group, but without the\n          // present bit to simulate where we start when using a 7-bit tag\n          // from a hash.\n          bytes_storage[bm_index][g_index] =\n              match_b & ~MetadataGroup::PresentMask;\n          break;\n        }\n        case BenchKind::Empty: {\n          match_b = MetadataGroup::Empty;\n          break;\n        }\n        case BenchKind::Deleted: {\n          match_b = MetadataGroup::Deleted;\n          break;\n        }\n      }\n\n      // Replicate the match byte in each of the other matching indices.\n      for (ssize_t m_index : llvm::ArrayRef(group_indices)\n                                 .drop_front()\n                                 .take_front(match_count - 1)) {\n        group_bytes[m_index] = match_b;\n      }\n    }\n\n    // Now that the storage is set up, record these in our struct.\n    bm.metadata = metadata_storage[bm_index];\n    if constexpr (Kind == BenchKind::Random) {\n      bm.bytes = bytes_storage[bm_index];\n    }\n  }\n  return bm_storage;\n}\n\ntemplate <BenchKind Kind>\n// NOLINTNEXTLINE(google-readability-casting): False positive clang-tidy bug.\nconst auto bench_metadata = BuildBenchMetadata<Kind>();\n\n// Benchmark that simulates the dynamic execution pattern when we match exactly\n// one entry in the group, typically then using the index of the matching byte\n// to index into an element of a group of entries. But notably, the *first*\n// match is sufficient, and we never have to find the *next* match within the\n// group.\ntemplate <BenchKind Kind, typename GroupT = MetadataGroup>\nstatic void BM_LoadMatch(benchmark::State& s) {\n  // NOLINTNEXTLINE(google-readability-casting): Same as on `bench_metadata`.\n  BenchMetadata bm = bench_metadata<Kind>[0];\n\n  // We want to make the index used by the next iteration of the benchmark have\n  // a data dependency on the result of matching. A match produces an index into\n  // the group of metadata. To consume this match in a way that is\n  // representative of how it will be used in a hashtable (indexing into an\n  // array of entries), while establishing that dependence, we keep a\n  // group-sized array of the value `1` in memory that we can index into to\n  // increment to the next step of the loop. We do have to hide the contents of\n  // the loop from the optimizer by clobbering the memory.\n  ssize_t all_ones[GroupSize];\n  for (ssize_t& n : all_ones) {\n    n = 1;\n  }\n  benchmark::ClobberMemory();\n\n  // We don't want the optimizer to peel iterations off of this loop, so hide\n  // the starting index.\n  ssize_t i = 0;\n  benchmark::DoNotOptimize(i);\n\n  // This loop looks *really* attractive to unroll to the compiler. However,\n  // that can easily overlap some of the memory operations and generally makes\n  // it harder to analyze the exact operation sequence we care about.\n#pragma clang loop unroll(disable)\n  for (auto _ : s) {\n    auto g = GroupT::Load(bm.metadata.data(), i * GroupSize);\n    typename GroupT::MatchIndex matches;\n    if constexpr (Kind == BenchKind::Empty) {\n      matches = g.MatchEmpty();\n    } else if constexpr (Kind == BenchKind::Deleted) {\n      matches = g.MatchDeleted();\n    } else {\n      static_assert(Kind == BenchKind::Random);\n      matches = static_cast<MetadataGroup::MatchIndex>(g.Match(bm.bytes[i]));\n    }\n    // Despite not being a DCHECK, this is fine for benchmarking. In an actual\n    // hashtable, we expect to have a test for empty of the match prior to using\n    // it to index an array, and that test is expected to be strongly predicted.\n    // That exactly matches how the `CARBON_CHECK` macro works, and so this\n    // serves as both a good correctness test and replication of hashtable usage\n    // of a match.\n    CARBON_CHECK(matches);\n\n    // Now do the data-dependent increment by indexing our \"all ones\" array. The\n    // index into `all_ones` is analogous to the index into a group of hashtable\n    // entries.\n    i = (i + all_ones[matches.index()]) & (BenchSize - 1);\n  }\n}\nBENCHMARK(BM_LoadMatch<BenchKind::Random>);\nBENCHMARK(BM_LoadMatch<BenchKind::Empty>);\nBENCHMARK(BM_LoadMatch<BenchKind::Deleted>);\n#if CARBON_NEON_SIMD_SUPPORT || CARBON_X86_SIMD_SUPPORT\nBENCHMARK(BM_LoadMatch<BenchKind::Random, PortableGroup>);\nBENCHMARK(BM_LoadMatch<BenchKind::Empty, PortableGroup>);\nBENCHMARK(BM_LoadMatch<BenchKind::Deleted, PortableGroup>);\nBENCHMARK(BM_LoadMatch<BenchKind::Random, SimdGroup>);\nBENCHMARK(BM_LoadMatch<BenchKind::Empty, SimdGroup>);\nBENCHMARK(BM_LoadMatch<BenchKind::Deleted, SimdGroup>);\n#endif\n\n// Benchmark that measures the speed of a match that is only found after at\n// least one miss. Because the first match doesn't work, this covers\n// incrementing to the next match, with a number of increments taken from the\n// `Step` template parameter.\ntemplate <BenchKind Kind, ssize_t Steps>\nstatic void BM_LoadMatchMissSteps(benchmark::State& s) {\n  static_assert(Steps > 0);\n  static_assert(Steps <= GroupSize);\n\n  // We pick the benchmark metadata at index `Steps - 1`, which will have\n  // `Steps` matches within each group.\n  BenchMetadata bm = bench_metadata<Kind>[Steps - 1];\n\n  // We want to make the index used by the next iteration of the benchmark have\n  // a data dependency on the result of matching. A match produces an index into\n  // the group of metadata. To consume this match in a way that is\n  // representative of how it will be used in a hashtable (indexing into an\n  // array of entries), while establishing that dependence, we keep a\n  // group-sized array of the value `1` in memory that we can index into to\n  // increment to the next step of the loop. We do have to hide the contents of\n  // the loop from the optimizer by clobbering the memory.\n  ssize_t all_ones[GroupSize];\n  for (ssize_t& n : all_ones) {\n    n = 1;\n  }\n  benchmark::ClobberMemory();\n\n  // We don't want the optimizer to peel iterations off of this loop, so hide\n  // the starting index.\n  ssize_t i = 0;\n  benchmark::DoNotOptimize(i);\n\n  // This loop looks *really* attractive to unroll to the compiler. However,\n  // that can easily overlap some of the memory operations and generally makes\n  // it harder to analyze the exact operation sequence we care about.\n#pragma clang loop unroll(disable)\n  for (auto _ : s) {\n    auto g = MetadataGroup::Load(bm.metadata.data(), i * GroupSize);\n    auto matched_range = g.Match(bm.bytes[i]);\n\n    // We don't use a `CARBON_CHECK` here as the loop below will test the range\n    // to see if the loop should be skipped, replicating the test that we also\n    // expect in hashtable usage.\n\n    // We want to simulate the code sequence a hashtable would produce when\n    // matching indices are \"misses\" in the hashtable, but only the aspects of\n    // those that reflect on the specific *match* implementation's generated\n    // code and performance. For each index in the match, we locate it in the\n    // `matched_range`, extract it as an index, and use that to index a\n    // group-sized array. We read memory from that array to increment `indices`,\n    // establishing data dependencies on each match index. This loop will run\n    // exactly `Steps` times.\n    ssize_t indices = 0;\n    for (ssize_t index : matched_range) {\n      indices += all_ones[index];\n    }\n\n    // We want to propagate the data dependencies accumulated into `indices`\n    // into the next value of `i`, and we know exactly how many increments were\n    // done in the loop, so subtract that constant and add one to arrive back at\n    // an increment of 1.\n    i = (i + (indices - Steps + 1)) & (BenchSize - 1);\n  }\n}\nBENCHMARK(BM_LoadMatchMissSteps<BenchKind::Random, 1>);\nBENCHMARK(BM_LoadMatchMissSteps<BenchKind::Random, 2>);\nBENCHMARK(BM_LoadMatchMissSteps<BenchKind::Random, 4>);\nBENCHMARK(BM_LoadMatchMissSteps<BenchKind::Random, 8>);\n#if CARBON_USE_X86_SIMD_CONTROL_GROUP\nBENCHMARK(BM_LoadMatchMissSteps<BenchKind::Random, 12>);\nBENCHMARK(BM_LoadMatchMissSteps<BenchKind::Random, 16>);\n#endif\n\n}  // namespace\n}  // namespace Carbon::RawHashtable\n"
  },
  {
    "path": "common/raw_hashtable_test_helpers.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_RAW_HASHTABLE_TEST_HELPERS_H_\n#define CARBON_COMMON_RAW_HASHTABLE_TEST_HELPERS_H_\n\n#include <compare>\n\n#include \"common/check.h\"\n#include \"common/hashing.h\"\n#include \"common/hashtable_key_context.h\"\n#include \"common/ostream.h\"\n\nnamespace Carbon::RawHashtable {\n\n// Non-trivial type for testing.\nstruct TestData : Printable<TestData> {\n  int value;\n\n  // NOLINTNEXTLINE: google-explicit-constructor\n  TestData(int v) : value(v) { CARBON_CHECK(value >= 0); }\n  ~TestData() {\n    CARBON_CHECK(value >= 0);\n    value = -1;\n  }\n  TestData(const TestData& other) : TestData(other.value) {}\n  TestData(TestData&& other) noexcept : TestData(other.value) {\n    other.value = 0;\n  }\n  auto Print(llvm::raw_ostream& out) const -> void { out << value; }\n\n  friend auto operator==(TestData lhs, TestData rhs) -> bool {\n    return lhs.value == rhs.value;\n  }\n\n  friend auto operator<=>(TestData lhs, TestData rhs) -> std::strong_ordering {\n    return lhs.value <=> rhs.value;\n  }\n\n  friend auto CarbonHashValue(TestData data, uint64_t seed) -> HashCode {\n    return Carbon::HashValue(data.value, seed);\n  }\n};\n\nstatic_assert(std::is_copy_constructible_v<TestData>);\n\n// Non-trivial type for testing.\nstruct MoveOnlyTestData : Printable<TestData> {\n  int value;\n\n  // NOLINTNEXTLINE: google-explicit-constructor\n  MoveOnlyTestData(int v) : value(v) { CARBON_CHECK(value >= 0); }\n  ~MoveOnlyTestData() {\n    CARBON_CHECK(value >= 0);\n    value = -1;\n  }\n  MoveOnlyTestData(MoveOnlyTestData&& other) noexcept\n      : MoveOnlyTestData(other.value) {\n    other.value = 0;\n  }\n  auto operator=(MoveOnlyTestData&& other) noexcept -> MoveOnlyTestData& {\n    value = other.value;\n    other.value = 0;\n    return *this;\n  }\n  auto Print(llvm::raw_ostream& out) const -> void { out << value; }\n\n  friend auto operator==(const MoveOnlyTestData& lhs,\n                         const MoveOnlyTestData& rhs) -> bool {\n    return lhs.value == rhs.value;\n  }\n\n  friend auto operator<=>(const MoveOnlyTestData& lhs,\n                          const MoveOnlyTestData& rhs) -> std::strong_ordering {\n    return lhs.value <=> rhs.value;\n  }\n\n  friend auto CarbonHashValue(const MoveOnlyTestData& data, uint64_t seed)\n      -> HashCode {\n    return Carbon::HashValue(data.value, seed);\n  }\n};\n\nstatic_assert(!std::is_copy_constructible_v<MoveOnlyTestData>);\nstatic_assert(std::is_move_constructible_v<MoveOnlyTestData>);\n\n// Test stateless key context that produces different hashes from normal.\n// Changing the hash values should result in test failures if the context ever\n// fails to be used.\nstruct TestKeyContext : DefaultKeyContext {\n  template <typename KeyT>\n  auto HashKey(const KeyT& key, uint64_t seed) const -> HashCode {\n    Hasher hash(seed);\n    // Inject some other data to the hash.\n    hash.HashRaw(42);\n    hash.HashRaw(HashValue(key));\n    return static_cast<HashCode>(hash);\n  }\n};\n\n// Hostile fixed hashing key context used for stress testing. Allows control\n// over which parts of the hash will be forced to collide, and the values they\n// are coerced to. Note that this relies on implementation details and internals\n// of `HashCode`.\ntemplate <int TagBits, bool FixIndexBits, bool FixTagBits, uint64_t FixedVal>\nstruct FixedHashKeyContext : DefaultKeyContext {\n  template <typename KeyT>\n  auto HashKey(const KeyT& key, uint64_t seed) const -> HashCode {\n    HashCode original_hash = HashValue(key, seed);\n    auto raw_hash = static_cast<uint64_t>(original_hash);\n\n    constexpr uint64_t TagMask = (1U << TagBits) - 1;\n    if (FixIndexBits) {\n      raw_hash &= TagMask;\n      raw_hash |= FixedVal << TagBits;\n      CARBON_DCHECK(HashCode(raw_hash).ExtractIndexAndTag<TagBits>().first ==\n                    (FixedVal & (~static_cast<uint64_t>(0) >> TagBits)));\n    }\n    if (FixTagBits) {\n      raw_hash &= ~TagMask;\n      raw_hash |= FixedVal & TagMask;\n      CARBON_DCHECK(HashCode(raw_hash).ExtractIndexAndTag<TagBits>().second ==\n                    (FixedVal & TagMask));\n    }\n    return HashCode(raw_hash);\n  }\n};\n\ntemplate <typename T>\nclass IndexKeyContext : public TranslatingKeyContext<IndexKeyContext<T>> {\n  using Base = TranslatingKeyContext<IndexKeyContext>;\n\n public:\n  explicit IndexKeyContext(llvm::ArrayRef<T> array) : array_(array) {}\n\n  auto TranslateKey(ssize_t index) const -> const T& { return array_[index]; }\n\n  // Override the CRTP approach when we have two indices as we can optimize that\n  // approach.\n  using Base::KeyEq;\n  auto KeyEq(ssize_t lhs_index, ssize_t rhs_index) const -> bool {\n    // No need to compare the elements, if the indices are equal, the values\n    // must be.\n    return lhs_index == rhs_index;\n  }\n\n private:\n  llvm::ArrayRef<T> array_;\n};\n\n}  // namespace Carbon::RawHashtable\n\n#endif  // CARBON_COMMON_RAW_HASHTABLE_TEST_HELPERS_H_\n"
  },
  {
    "path": "common/raw_string_ostream.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_RAW_STRING_OSTREAM_H_\n#define CARBON_COMMON_RAW_STRING_OSTREAM_H_\n\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n\nnamespace Carbon {\n\n// Implements streaming output with an underlying string. The string must always\n// be taken prior to destruction.\n//\n// Versus `llvm::raw_string_ostream`:\n// - Owns the underlying string.\n// - Supports `pwrite` for compatibility with more stream uses in tests.\nclass RawStringOstream : public llvm::raw_pwrite_stream {\n public:\n  explicit RawStringOstream() : llvm::raw_pwrite_stream(/*Unbuffered=*/true) {}\n\n  ~RawStringOstream() override {\n    CARBON_CHECK(str_.empty(), \"Expected to be emptied by TakeStr, have: {0}\",\n                 str_);\n  }\n\n  // Returns the streamed contents, clearing the stream back to empty.\n  auto TakeStr() -> std::string {\n    std::string result = std::move(str_);\n    clear();\n    return result;\n  }\n\n  // Clears the buffer, which can be helpful when destructing without\n  // necessarily calling `TakeStr()`.\n  auto clear() -> void { str_.clear(); }\n\n  auto empty() -> bool { return str_.empty(); }\n  auto size() -> size_t { return str_.size(); }\n\n private:\n  auto current_pos() const -> uint64_t override { return str_.size(); }\n\n  auto pwrite_impl(const char* ptr, size_t size, uint64_t offset)\n      -> void override {\n    str_.replace(offset, size, ptr, size);\n  }\n\n  auto write_impl(const char* ptr, size_t size) -> void override {\n    str_.append(ptr, size);\n  }\n\n  auto reserveExtraSpace(uint64_t extra_size) -> void override {\n    str_.reserve(str_.size() + extra_size);\n  }\n\n  // The actual buffer.\n  std::string str_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_RAW_STRING_OSTREAM_H_\n"
  },
  {
    "path": "common/raw_string_ostream_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/raw_string_ostream.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing ::testing::HasSubstr;\nusing ::testing::StrEq;\n\nTEST(RawStringOstreamTest, Basics) {\n  RawStringOstream os;\n\n  os << \"test 1\";\n  EXPECT_THAT(os.TakeStr(), StrEq(\"test 1\"));\n\n  os << \"test\"\n     << \" \"\n     << \"2\";\n  EXPECT_THAT(os.TakeStr(), StrEq(\"test 2\"));\n\n  os << \"test\";\n  os << \" \";\n  os << \"3\";\n  EXPECT_THAT(os.TakeStr(), StrEq(\"test 3\"));\n}\n\nTEST(RawStringOstreamTest, MultipleStreams) {\n  RawStringOstream os1;\n  RawStringOstream os2;\n\n  os1 << \"test \";\n  os2 << \"test stream 2\";\n  os1 << \"stream 1\";\n  EXPECT_THAT(os1.TakeStr(), StrEq(\"test stream 1\"));\n  EXPECT_THAT(os2.TakeStr(), StrEq(\"test stream 2\"));\n}\n\nTEST(RawStringOstreamTest, MultipleLines) {\n  RawStringOstream os;\n\n  os << \"test line 1\\n\";\n  os << \"test line 2\\n\";\n  os << \"test line 3\\n\";\n  EXPECT_THAT(os.TakeStr(), StrEq(\"test line 1\\ntest line 2\\ntest line 3\\n\"));\n}\n\nTEST(RawStringOstreamTest, Substring) {\n  RawStringOstream os;\n\n  os << \"test line 1\\n\";\n  os << \"test line 2\\n\";\n  os << \"test line 3\\n\";\n  EXPECT_THAT(os.TakeStr(), HasSubstr(\"test line 2\"));\n}\n\nTEST(RawStringOstreamTest, Pwrite) {\n  RawStringOstream os;\n  os << \"test line 1\\n\";\n  os.pwrite(\"splat\", 5, 1);\n  os << \"test line 2\\n\";\n  EXPECT_THAT(os.TakeStr(), HasSubstr(\"tsplatine 1\\ntest line 2\\n\"));\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "common/set.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_SET_H_\n#define CARBON_COMMON_SET_H_\n\n#include <concepts>\n#include <type_traits>\n\n#include \"common/check.h\"\n#include \"common/hashtable_key_context.h\"\n#include \"common/raw_hashtable.h\"\n#include \"llvm/Support/Compiler.h\"\n\nnamespace Carbon {\n\n// Forward declarations to resolve cyclic references.\ntemplate <typename KeyT, typename KeyContextT>\nclass SetView;\ntemplate <typename KeyT, typename KeyContextT>\nclass SetBase;\ntemplate <typename KeyT, ssize_t SmallSize, typename KeyContextT>\nclass Set;\n\n// A read-only view type for a set of keys.\n//\n// This view is a cheap-to-copy type that should be passed by value, but\n// provides view or read-only reference semantics to the underlying set data\n// structure.\n//\n// This should always be preferred to a `const`-ref parameter for the `SetBase`\n// or `Set` type as it provides more flexibility and a cleaner API. By default\n// a `SetView` provides no more immutability than a `const Set`: elements\n// can't be added or removed, but they can be mutated, and the user is\n// responsible for avoiding mutations that affect the hash value or equality\n// comparison. However, a `SetView<T>` can be converted to a `SetView<const T>`,\n// which prevents mutating the elements. As with any other view type, `const`\n// on the `SetView` itself is \"shallow\": it prevents rebinding the `SetView` to\n// a different underlying set, but doesn't affect mutability of the underlying\n// set.\n//\n// A specific `KeyContextT` type can optionally be provided to configure how\n// keys will be hashed and compared. The default is `DefaultKeyContext` which is\n// stateless and will hash using `Carbon::HashValue` and compare using\n// `operator==`. Every method accepting a lookup key or operating on the keys in\n// the table will also accept an instance of this type. For stateless context\n// types, including the default, an instance will be default constructed if not\n// provided to these methods. However, stateful contexts should be constructed\n// and passed in explicitly. The context type should be small and reasonable to\n// pass by value, often a wrapper or pointer to the relevant context needed for\n// hashing and comparing keys. For more details about the key context, see\n// `hashtable_key_context.h`.\ntemplate <typename InputKeyT, typename InputKeyContextT = DefaultKeyContext>\nclass SetView : RawHashtable::ViewImpl<InputKeyT, void, InputKeyContextT> {\n  using ImplT = RawHashtable::ViewImpl<InputKeyT, void, InputKeyContextT>;\n\n public:\n  using KeyT = typename ImplT::KeyT;\n  using KeyContextT = typename ImplT::KeyContextT;\n  using MetricsT = typename ImplT::MetricsT;\n\n  // This type represents the result of lookup operations. It encodes whether\n  // the lookup was a success as well as accessors for the key.\n  class LookupResult {\n   public:\n    LookupResult() = default;\n    explicit LookupResult(KeyT& key) : key_(&key) {}\n\n    explicit operator bool() const { return key_ != nullptr; }\n\n    auto key() const -> KeyT& { return *key_; }\n\n   private:\n    KeyT* key_ = nullptr;\n  };\n\n  // Enable implicit conversions that add `const`-ness to the key type.\n  explicit(false)\n      SetView(const SetView<std::remove_const_t<KeyT>, KeyContextT>& other_view)\n    requires(!std::same_as<KeyT, std::remove_const_t<KeyT>>)\n      : ImplT(other_view) {}\n\n  // Tests whether a key is present in the set.\n  template <typename LookupKeyT>\n  auto Contains(LookupKeyT lookup_key,\n                KeyContextT key_context = KeyContextT()) const -> bool;\n\n  // Lookup a key in the set.\n  template <typename LookupKeyT>\n  auto Lookup(LookupKeyT lookup_key,\n              KeyContextT key_context = KeyContextT()) const -> LookupResult;\n\n  // Run the provided callback for every key in the set.\n  template <typename CallbackT>\n  auto ForEach(CallbackT callback) const -> void\n    requires(std::invocable<CallbackT, KeyT&>);\n\n  // This routine is relatively inefficient and only intended for use in\n  // benchmarking or logging of performance anomalies. The specific metrics\n  // returned have no specific guarantees beyond being informative in\n  // benchmarks.\n  auto ComputeMetrics(KeyContextT key_context = KeyContextT()) -> MetricsT {\n    return ImplT::ComputeMetricsImpl(key_context);\n  }\n\n private:\n  template <typename SetKeyT, ssize_t SmallSize, typename KeyContextT>\n  friend class Set;\n  friend class SetBase<KeyT, KeyContextT>;\n  friend class SetView<const KeyT, KeyContextT>;\n\n  using EntryT = typename ImplT::EntryT;\n\n  SetView() = default;\n  explicit(false) SetView(ImplT base) : ImplT(base) {}\n  SetView(ssize_t size, RawHashtable::Storage* storage)\n      : ImplT(size, storage) {}\n};\n\n// A base class for a `Set` type that remains mutable while type-erasing the\n// `SmallSize` (SSO) template parameter.\n//\n// Note that `SetBase` has \"shallow\" const semantics: a `const SetBase<T>&`\n// can't be used to mutate the set data structure itself (e.g. by changing\n// the number of elements), but it can be used to mutate the `T` elements it\n// contains. The user is responsible for avoiding mutations that would change\n// the hash value or equality of an element. A `SetView<const T>` can be used\n// to provide read-only access to the elements of a `SetBase<T>`.\n//\n// A pointer or reference to this type is the preferred way to pass a mutable\n// handle to a `Set` type across API boundaries as it avoids encoding specific\n// SSO sizing information while providing a near-complete mutable API.\ntemplate <typename InputKeyT, typename InputKeyContextT>\nclass SetBase\n    : protected RawHashtable::BaseImpl<InputKeyT, void, InputKeyContextT> {\n protected:\n  using ImplT = RawHashtable::BaseImpl<InputKeyT, void, InputKeyContextT>;\n\n public:\n  using KeyT = typename ImplT::KeyT;\n  using KeyContextT = typename ImplT::KeyContextT;\n  using ViewT = SetView<KeyT, KeyContextT>;\n  using LookupResult = typename ViewT::LookupResult;\n  using MetricsT = typename ImplT::MetricsT;\n\n  // The result type for insertion operations both indicates whether an insert\n  // was needed (as opposed to the key already being in the set), and provides\n  // access to the key.\n  class InsertResult {\n   public:\n    InsertResult() = default;\n    explicit InsertResult(bool inserted, KeyT& key)\n        : key_(&key), inserted_(inserted) {}\n\n    auto is_inserted() const -> bool { return inserted_; }\n\n    auto key() const -> KeyT& { return *key_; }\n\n   private:\n    KeyT* key_;\n    bool inserted_;\n  };\n\n  // Implicitly convertible to the relevant view type.\n  //\n  // NOLINTNEXTLINE(google-explicit-constructor): Designed to implicitly decay.\n  explicit(false) operator ViewT() const { return this->view_impl(); }\n\n  // We can't chain the above conversion with the conversions on `ViewT` to add\n  // const, so explicitly support adding const to produce a view here.\n  //\n  // NOLINTNEXTLINE(google-explicit-constructor): Designed to implicitly decay.\n  explicit(false) operator SetView<const KeyT, KeyContextT>() const {\n    return ViewT(*this);\n  }\n\n  // Convenience forwarder to the view type.\n  template <typename LookupKeyT>\n  auto Contains(LookupKeyT lookup_key,\n                KeyContextT key_context = KeyContextT()) const -> bool {\n    return ViewT(*this).Contains(lookup_key, key_context);\n  }\n\n  // Convenience forwarder to the view type.\n  template <typename LookupKeyT>\n  auto Lookup(LookupKeyT lookup_key,\n              KeyContextT key_context = KeyContextT()) const -> LookupResult {\n    return ViewT(*this).Lookup(lookup_key, key_context);\n  }\n\n  // Convenience forwarder to the view type.\n  template <typename CallbackT>\n  auto ForEach(CallbackT callback) const -> void\n    requires(std::invocable<CallbackT, KeyT&>)\n  {\n    return ViewT(*this).ForEach(callback);\n  }\n\n  // Convenience forwarder to the view type.\n  auto ComputeMetrics(KeyContextT key_context = KeyContextT()) const\n      -> MetricsT {\n    return ViewT(*this).ComputeMetrics(key_context);\n  }\n\n  // Insert a key into the set. If the key is already present, no insertion is\n  // performed and that present key is available in the result. Otherwise a new\n  // key is inserted and constructed from the argument and available in the\n  // result.\n  template <typename LookupKeyT>\n  auto Insert(LookupKeyT lookup_key, KeyContextT key_context = KeyContextT())\n      -> InsertResult;\n\n  // Insert a key into the map and call the provided callback if necessary to\n  // produce a new key when no existing value is found.\n  //\n  // Example: `m.Insert(key_equivalent, [] { return real_key; });`\n  //\n  // The point of this function is when the lookup key is _different_from the\n  // stored key. However, we don't restrict it in case that blocks generic\n  // usage.\n  template <typename LookupKeyT, typename KeyCallbackT>\n  auto Insert(LookupKeyT lookup_key, KeyCallbackT key_cb,\n              KeyContextT key_context = KeyContextT()) -> InsertResult\n    requires(\n        !std::same_as<KeyT, KeyCallbackT> &&\n        std::convertible_to<decltype(std::declval<KeyCallbackT>()()), KeyT>);\n\n  // Insert a key into the set and call the provided callback to allow in-place\n  // construction of the key if not already present. The lookup key is passed\n  // through to the callback so it needn't be captured and can be kept in a\n  // register argument throughout.\n  //\n  // Example:\n  // ```cpp\n  //   m.Insert(\"widget\", [](MyStringViewType lookup_key, void* key_storage) {\n  //     new (key_storage) MyStringType(lookup_key);\n  //   });\n  // ```\n  template <typename LookupKeyT, typename InsertCallbackT>\n  auto Insert(LookupKeyT lookup_key, InsertCallbackT insert_cb,\n              KeyContextT key_context = KeyContextT()) -> InsertResult\n    requires std::invocable<InsertCallbackT, LookupKeyT, void*>;\n\n  // Grow the set to a specific allocation size.\n  //\n  // This will grow the set's hashtable if necessary for it to have an\n  // allocation size of `target_alloc_size` which must be a power of two. Note\n  // that this will not allow that many keys to be inserted, but a smaller\n  // number based on the maximum load factor. If a specific number of insertions\n  // need to be achieved without triggering growth, use the `GrowForInsertCount`\n  // method.\n  auto GrowToAllocSize(ssize_t target_alloc_size,\n                       KeyContextT key_context = KeyContextT()) -> void;\n\n  // Grow the set sufficiently to allow inserting the specified number of keys.\n  auto GrowForInsertCount(ssize_t count,\n                          KeyContextT key_context = KeyContextT()) -> void;\n\n  // Erase a key from the set.\n  template <typename LookupKeyT>\n  auto Erase(LookupKeyT lookup_key, KeyContextT key_context = KeyContextT())\n      -> bool;\n\n  // Clear all key/value pairs from the set but leave the underlying hashtable\n  // allocated and in place.\n  auto Clear() -> void;\n\n protected:\n  using ImplT::ImplT;\n};\n\n// A data structure for a set of keys.\n//\n// This set supports small size optimization (or \"SSO\"). The provided\n// `SmallSize` type parameter indicates the size of an embedded buffer for\n// storing sets small enough to fit. The default is zero, which always allocates\n// a heap buffer on construction. When non-zero, must be a multiple of the\n// `MaxGroupSize` which is currently 16. The library will check that the size is\n// valid and provide an error at compile time if not. We don't automatically\n// select the next multiple or otherwise fit the size to the constraints to make\n// it clear in the code how much memory is used by the SSO buffer.\n//\n// This data structure optimizes heavily for small key types that are cheap to\n// move and even copy. Using types with large keys or expensive to copy keys may\n// create surprising performance bottlenecks. A `std::string` key should be fine\n// with generally small strings, but if some or many strings are large heap\n// allocations the performance of hashtable routines may be unacceptably bad and\n// another data structure or key design is likely preferable.\n//\n// Note that `Set`, like `SetBase`, has \"shallow\" const semantics. Note also\n// that this type should typically not appear on API boundaries; either\n// `SetBase` or `SetView` should be used instead.\ntemplate <typename InputKeyT, ssize_t SmallSize = 0,\n          typename InputKeyContextT = DefaultKeyContext>\nclass Set : public RawHashtable::TableImpl<SetBase<InputKeyT, InputKeyContextT>,\n                                           SmallSize> {\n  using BaseT = SetBase<InputKeyT, InputKeyContextT>;\n  using ImplT = RawHashtable::TableImpl<BaseT, SmallSize>;\n\n public:\n  using KeyT = typename BaseT::KeyT;\n\n  Set() = default;\n  Set(const Set& arg) = default;\n  Set(Set&& arg) noexcept = default;\n  auto operator=(const Set& arg) -> Set& = default;\n  auto operator=(Set&& arg) noexcept -> Set& = default;\n\n  // Reset the entire state of the hashtable to as it was when constructed,\n  // throwing away any intervening allocations.\n  auto Reset() -> void;\n};\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto SetView<InputKeyT, InputKeyContextT>::Contains(\n    LookupKeyT lookup_key, KeyContextT key_context) const -> bool {\n  return this->LookupEntry(lookup_key, key_context) != nullptr;\n}\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto SetView<InputKeyT, InputKeyContextT>::Lookup(LookupKeyT lookup_key,\n                                                  KeyContextT key_context) const\n    -> LookupResult {\n  EntryT* entry = this->LookupEntry(lookup_key, key_context);\n  if (!entry) {\n    return LookupResult();\n  }\n\n  return LookupResult(entry->key());\n}\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\ntemplate <typename CallbackT>\nauto SetView<InputKeyT, InputKeyContextT>::ForEach(CallbackT callback) const\n    -> void\n  requires(std::invocable<CallbackT, KeyT&>)\n{\n  this->ForEachEntry([callback](EntryT& entry) { callback(entry.key()); },\n                     [](auto...) {});\n}\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto SetBase<InputKeyT, InputKeyContextT>::Insert(LookupKeyT lookup_key,\n                                                  KeyContextT key_context)\n    -> InsertResult {\n  return Insert(\n      lookup_key,\n      [](LookupKeyT lookup_key, void* key_storage) {\n        new (key_storage) KeyT(std::move(lookup_key));\n      },\n      key_context);\n}\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\ntemplate <typename LookupKeyT, typename KeyCallbackT>\nauto SetBase<InputKeyT, InputKeyContextT>::Insert(LookupKeyT lookup_key,\n                                                  KeyCallbackT key_cb,\n                                                  KeyContextT key_context)\n    -> InsertResult\n  requires(!std::same_as<KeyT, KeyCallbackT> &&\n           std::convertible_to<decltype(std::declval<KeyCallbackT>()()), KeyT>)\n{\n  return Insert(\n      lookup_key,\n      [&key_cb](LookupKeyT /*lookup_key*/, void* key_storage) {\n        new (key_storage) KeyT(key_cb());\n      },\n      key_context);\n}\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\ntemplate <typename LookupKeyT, typename InsertCallbackT>\nauto SetBase<InputKeyT, InputKeyContextT>::Insert(LookupKeyT lookup_key,\n                                                  InsertCallbackT insert_cb,\n                                                  KeyContextT key_context)\n    -> InsertResult\n  requires std::invocable<InsertCallbackT, LookupKeyT, void*>\n{\n  auto [entry, inserted] = this->InsertImpl(lookup_key, key_context);\n  CARBON_DCHECK(entry, \"Should always result in a valid index.\");\n\n  if (LLVM_LIKELY(!inserted)) {\n    return InsertResult(false, entry->key());\n  }\n\n  insert_cb(lookup_key, static_cast<void*>(&entry->key_storage));\n  return InsertResult(true, entry->key());\n}\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\nauto SetBase<InputKeyT, InputKeyContextT>::GrowToAllocSize(\n    ssize_t target_alloc_size, KeyContextT key_context) -> void {\n  this->GrowToAllocSizeImpl(target_alloc_size, key_context);\n}\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\nauto SetBase<InputKeyT, InputKeyContextT>::GrowForInsertCount(\n    ssize_t count, KeyContextT key_context) -> void {\n  this->GrowForInsertCountImpl(count, key_context);\n}\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\ntemplate <typename LookupKeyT>\nauto SetBase<InputKeyT, InputKeyContextT>::Erase(LookupKeyT lookup_key,\n                                                 KeyContextT key_context)\n    -> bool {\n  return this->EraseImpl(lookup_key, key_context);\n}\n\ntemplate <typename InputKeyT, typename InputKeyContextT>\nauto SetBase<InputKeyT, InputKeyContextT>::Clear() -> void {\n  this->ClearImpl();\n}\n\ntemplate <typename InputKeyT, ssize_t SmallSize, typename InputKeyContextT>\nauto Set<InputKeyT, SmallSize, InputKeyContextT>::Reset() -> void {\n  this->ResetImpl();\n}\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_SET_H_\n"
  },
  {
    "path": "common/set_benchmark.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <benchmark/benchmark.h>\n\n#include <type_traits>\n\n#include \"absl/container/flat_hash_set.h\"\n#include \"common/raw_hashtable_benchmark_helpers.h\"\n#include \"common/set.h\"\n#include \"llvm/ADT/DenseSet.h\"\n\nnamespace Carbon {\nnamespace {\n\nusing RawHashtable::CarbonHashDI;\nusing RawHashtable::GetKeysAndHitKeys;\nusing RawHashtable::GetKeysAndMissKeys;\nusing RawHashtable::HitArgs;\nusing RawHashtable::ReportTableMetrics;\nusing RawHashtable::SizeArgs;\nusing RawHashtable::ValueToBool;\n\ntemplate <typename SetT>\nstruct IsCarbonSetImpl : std::false_type {};\ntemplate <typename KT, int MinSmallSize>\nstruct IsCarbonSetImpl<Set<KT, MinSmallSize>> : std::true_type {};\n\ntemplate <typename SetT>\nstatic constexpr bool IsCarbonSet = IsCarbonSetImpl<SetT>::value;\n\n// A wrapper around various set types that we specialize to implement a common\n// API used in the benchmarks for various different map data structures that\n// support different APIs. The primary template assumes a roughly\n// `std::unordered_set` API design, and types with a different API design are\n// supported through specializations.\ntemplate <typename SetT>\nstruct SetWrapperImpl {\n  using KeyT = typename SetT::key_type;\n\n  SetT s;\n\n  auto BenchContains(KeyT k) -> bool { return s.find(k) != s.end(); }\n\n  auto BenchLookup(KeyT k) -> bool {\n    auto it = s.find(k);\n    if (it == s.end()) {\n      return false;\n    }\n    // We expect keys to always convert to `true` so directly return that here.\n    return ValueToBool(*it);\n  }\n\n  auto BenchInsert(KeyT k) -> bool {\n    auto result = s.insert(k);\n    return result.second;\n  }\n\n  auto BenchErase(KeyT k) -> bool { return s.erase(k) != 0; }\n};\n\n// Explicit (partial) specialization for the Carbon map type that uses its\n// different API design.\ntemplate <typename KT, int MinSmallSize>\nstruct SetWrapperImpl<Set<KT, MinSmallSize>> {\n  using SetT = Set<KT, MinSmallSize>;\n  using KeyT = KT;\n\n  SetT s;\n\n  auto BenchContains(KeyT k) -> bool { return s.Contains(k); }\n\n  auto BenchLookup(KeyT k) -> bool {\n    auto result = s.Lookup(k);\n    if (!result) {\n      return false;\n    }\n    return ValueToBool(result.key());\n  }\n\n  auto BenchInsert(KeyT k) -> bool {\n    auto result = s.Insert(k);\n    return result.is_inserted();\n  }\n\n  auto BenchErase(KeyT k) -> bool { return s.Erase(k); }\n};\n\n// Provide a way to override the Carbon Set specific benchmark runs with another\n// hashtable implementation. When building, you can use one of these enum names\n// in a macro define such as `-DCARBON_SET_BENCH_OVERRIDE=Name` in order to\n// trigger a specific override for the `Set` type benchmarks. This is used to\n// get before/after runs that compare the performance of Carbon's Set versus\n// other implementations.\nenum class SetOverride : uint8_t {\n  Abseil,\n  LLVM,\n  LLVMAndCarbonHash,\n};\ntemplate <typename SetT, SetOverride Override>\nstruct SetWrapperOverride : SetWrapperImpl<SetT> {};\n\ntemplate <typename KeyT, int MinSmallSize>\nstruct SetWrapperOverride<Set<KeyT, MinSmallSize>, SetOverride::Abseil>\n    : SetWrapperImpl<absl::flat_hash_set<KeyT>> {};\n\ntemplate <typename KeyT, int MinSmallSize>\nstruct SetWrapperOverride<Set<KeyT, MinSmallSize>, SetOverride::LLVM>\n    : SetWrapperImpl<llvm::DenseSet<KeyT>> {};\n\ntemplate <typename KeyT, int MinSmallSize>\nstruct SetWrapperOverride<Set<KeyT, MinSmallSize>,\n                          SetOverride::LLVMAndCarbonHash>\n    : SetWrapperImpl<llvm::DenseSet<KeyT, CarbonHashDI<KeyT>>> {};\n\n#ifndef CARBON_SET_BENCH_OVERRIDE\ntemplate <typename SetT>\nusing SetWrapper = SetWrapperImpl<SetT>;\n#else\ntemplate <typename SetT>\nusing SetWrapper =\n    SetWrapperOverride<SetT, SetOverride::CARBON_SET_BENCH_OVERRIDE>;\n#endif\n\n// NOLINTBEGIN(bugprone-macro-parentheses): Parentheses are incorrect here.\n#define MAP_BENCHMARK_ONE_OP_SIZE(NAME, APPLY, KT)        \\\n  BENCHMARK(NAME<Set<KT>>)->Apply(APPLY);                 \\\n  BENCHMARK(NAME<absl::flat_hash_set<KT>>)->Apply(APPLY); \\\n  BENCHMARK(NAME<llvm::DenseSet<KT>>)->Apply(APPLY);      \\\n  BENCHMARK(NAME<llvm::DenseSet<KT, CarbonHashDI<KT>>>)->Apply(APPLY)\n// NOLINTEND(bugprone-macro-parentheses)\n\n#define MAP_BENCHMARK_ONE_OP(NAME, APPLY)       \\\n  MAP_BENCHMARK_ONE_OP_SIZE(NAME, APPLY, int);  \\\n  MAP_BENCHMARK_ONE_OP_SIZE(NAME, APPLY, int*); \\\n  MAP_BENCHMARK_ONE_OP_SIZE(NAME, APPLY, llvm::StringRef)\n\n// Benchmark the \"latency\" of testing for a key in a set. This always tests with\n// a key that is found.\n//\n// However, because the key is always found and because the test ultimately\n// involves conditional control flow that can be predicted, we expect modern\n// CPUs to perfectly predict the control flow here and turn the measurement from\n// one iteration to the next into a throughput measurement rather than a real\n// latency measurement.\n//\n// However, this does represent a particularly common way in which a set data\n// structure is accessed. The numbers should just be carefully interpreted in\n// the context of being more a reflection of reciprocal throughput than actual\n// latency. See the `Lookup` benchmarks for a genuine latency measure with its\n// own caveats.\n//\n// However, this does still show some interesting caching effects when querying\n// large fractions of large tables, and can give a sense of the inescapable\n// magnitude of these effects even when there is a great deal of prediction and\n// speculative execution to hide memory access latency.\ntemplate <typename SetT>\nstatic void BM_SetContainsHitPtr(benchmark::State& state) {\n  using SetWrapperT = SetWrapper<SetT>;\n  using KT = typename SetWrapperT::KeyT;\n  SetWrapperT s;\n  auto [keys, lookup_keys] =\n      GetKeysAndHitKeys<KT>(state.range(0), state.range(1));\n  for (auto k : keys) {\n    s.BenchInsert(k);\n  }\n  ssize_t lookup_keys_size = lookup_keys.size();\n\n  while (state.KeepRunningBatch(lookup_keys_size)) {\n    for (ssize_t i = 0; i < lookup_keys_size;) {\n      // We block optimizing `i` as that has proven both more effective at\n      // blocking the loop from being optimized away and avoiding disruption of\n      // the generated code that we're benchmarking.\n      benchmark::DoNotOptimize(i);\n\n      bool result = s.BenchContains(lookup_keys[i]);\n      CARBON_DCHECK(result);\n      // We use the lookup success to step through keys, establishing a\n      // dependency between each lookup. This doesn't fully allow us to measure\n      // latency rather than throughput, as noted above.\n      i += static_cast<ssize_t>(result);\n    }\n  }\n}\nMAP_BENCHMARK_ONE_OP(BM_SetContainsHitPtr, HitArgs);\n\n// Benchmark the \"latency\" (but more likely the reciprocal throughput, see\n// comment above) of testing for a key in the set that is *not* present.\ntemplate <typename SetT>\nstatic void BM_SetContainsMissPtr(benchmark::State& state) {\n  using SetWrapperT = SetWrapper<SetT>;\n  using KT = typename SetWrapperT::KeyT;\n  SetWrapperT s;\n  auto [keys, lookup_keys] = GetKeysAndMissKeys<KT>(state.range(0));\n  for (auto k : keys) {\n    s.BenchInsert(k);\n  }\n  ssize_t lookup_keys_size = lookup_keys.size();\n\n  while (state.KeepRunningBatch(lookup_keys_size)) {\n    for (ssize_t i = 0; i < lookup_keys_size;) {\n      benchmark::DoNotOptimize(i);\n\n      bool result = s.BenchContains(lookup_keys[i]);\n      CARBON_DCHECK(!result);\n      i += static_cast<ssize_t>(!result);\n    }\n  }\n}\nMAP_BENCHMARK_ONE_OP(BM_SetContainsMissPtr, SizeArgs);\n\n// A somewhat contrived latency test for the lookup code path.\n//\n// While lookups into a set are often (but not always) simply used to influence\n// control flow, that style of access produces difficult to evaluate benchmark\n// results (see the comments on the `Contains` benchmarks above).\n//\n// So here we actually access the key in the set and convert that key's value to\n// a boolean on the critical path of each iteration. This lets us have a genuine\n// latency benchmark of looking up a key in the set, at the expense of being\n// somewhat contrived. That said, for usage where the key object is queried or\n// operated on in some way once looked up in the set, this will be fairly\n// representative of the latency cost from the data structure.\ntemplate <typename SetT>\nstatic void BM_SetLookupHitPtr(benchmark::State& state) {\n  using SetWrapperT = SetWrapper<SetT>;\n  using KT = typename SetWrapperT::KeyT;\n  SetWrapperT s;\n  auto [keys, lookup_keys] =\n      GetKeysAndHitKeys<KT>(state.range(0), state.range(1));\n  for (auto k : keys) {\n    s.BenchInsert(k);\n  }\n  ssize_t lookup_keys_size = lookup_keys.size();\n\n  while (state.KeepRunningBatch(lookup_keys_size)) {\n    for (ssize_t i = 0; i < lookup_keys_size;) {\n      benchmark::DoNotOptimize(i);\n\n      bool result = s.BenchLookup(lookup_keys[i]);\n      CARBON_DCHECK(result);\n      i += static_cast<ssize_t>(result);\n    }\n  }\n}\nMAP_BENCHMARK_ONE_OP(BM_SetLookupHitPtr, HitArgs);\n\n// First erase and then insert the key. The code path will always be the same\n// here and so we expect this to largely be a throughput benchmark because of\n// branch prediction and speculative execution.\n//\n// We don't expect erase followed by insertion to be a common user code\n// sequence, but we don't have a good way of benchmarking either erase or insert\n// in isolation -- each would change the size of the table and thus the next\n// iteration's benchmark. And if we try to correct the table size outside of the\n// timed region, we end up trying to exclude too fine grained of a region from\n// timers to get good measurement data.\n//\n// Our solution is to benchmark both erase and insertion back to back. We can\n// then get a good profile of the code sequence of each, and at least measure\n// the sum cost of these reliably. Careful profiling can help attribute that\n// cost between erase and insert in order to understand which of the two\n// operations is contributing most to any performance artifacts observed.\ntemplate <typename SetT>\nstatic void BM_SetEraseInsertHitPtr(benchmark::State& state) {\n  using SetWrapperT = SetWrapper<SetT>;\n  using KT = typename SetWrapperT::KeyT;\n  SetWrapperT s;\n  auto [keys, lookup_keys] =\n      GetKeysAndHitKeys<KT>(state.range(0), state.range(1));\n  for (auto k : keys) {\n    s.BenchInsert(k);\n  }\n  ssize_t lookup_keys_size = lookup_keys.size();\n\n  while (state.KeepRunningBatch(lookup_keys_size)) {\n    for (ssize_t i = 0; i < lookup_keys_size;) {\n      benchmark::DoNotOptimize(i);\n\n      s.BenchErase(lookup_keys[i]);\n      benchmark::ClobberMemory();\n\n      bool inserted = s.BenchInsert(lookup_keys[i]);\n      CARBON_DCHECK(inserted);\n      i += static_cast<ssize_t>(inserted);\n    }\n  }\n}\nMAP_BENCHMARK_ONE_OP(BM_SetEraseInsertHitPtr, HitArgs);\n\n// NOLINTBEGIN(bugprone-macro-parentheses): Parentheses are incorrect here.\n#define MAP_BENCHMARK_OP_SEQ_SIZE(NAME, KT)                  \\\n  BENCHMARK(NAME<Set<KT>>)->Apply(SizeArgs);                 \\\n  BENCHMARK(NAME<absl::flat_hash_set<KT>>)->Apply(SizeArgs); \\\n  BENCHMARK(NAME<llvm::DenseSet<KT>>)->Apply(SizeArgs);      \\\n  BENCHMARK(NAME<llvm::DenseSet<KT, CarbonHashDI<KT>>>)->Apply(SizeArgs)\n// NOLINTEND(bugprone-macro-parentheses)\n\n#define MAP_BENCHMARK_OP_SEQ(NAME)       \\\n  MAP_BENCHMARK_OP_SEQ_SIZE(NAME, int);  \\\n  MAP_BENCHMARK_OP_SEQ_SIZE(NAME, int*); \\\n  MAP_BENCHMARK_OP_SEQ_SIZE(NAME, llvm::StringRef)\n\n// This is an interesting, somewhat specialized benchmark that measures the cost\n// of inserting a sequence of keys into a set up to some size and then inserting\n// a colliding key and throwing away the set.\n//\n// This is an especially important usage pattern for sets as a large number of\n// algorithms essentially look like this, such as collision detection, cycle\n// detection, de-duplication, etc.\n//\n// It also covers both the insert-into-an-empty-slot code path that isn't\n// covered elsewhere, and the code path for growing a table to a larger size.\n//\n// This is the second most important aspect of expected set usage after testing\n// for presence. It also nicely lends itself to a single benchmark that covers\n// the total cost of this usage pattern.\n//\n// Because this benchmark operates on whole sets, we also compute the number of\n// probed keys for Carbon's set as that is both a general reflection of the\n// efficacy of the underlying hash function, and a direct factor that drives the\n// cost of these operations.\ntemplate <typename SetT>\nstatic void BM_SetInsertSeq(benchmark::State& state) {\n  using SetWrapperT = SetWrapper<SetT>;\n  using KT = typename SetWrapperT::KeyT;\n  constexpr ssize_t LookupKeysSize = 1 << 8;\n  auto [keys, lookup_keys] =\n      GetKeysAndHitKeys<KT>(state.range(0), LookupKeysSize);\n\n  // Now build a large shuffled set of keys (with duplicates) we'll use at the\n  // end.\n  ssize_t i = 0;\n  for (auto _ : state) {\n    benchmark::DoNotOptimize(i);\n\n    SetWrapperT s;\n    for (auto k : keys) {\n      bool inserted = s.BenchInsert(k);\n      CARBON_DCHECK(inserted, \"Must be a successful insert!\");\n    }\n\n    // Now insert a final random repeated key.\n    bool inserted = s.BenchInsert(lookup_keys[i]);\n    CARBON_DCHECK(!inserted, \"Must already be in the map!\");\n\n    // Rotate through the shuffled keys.\n    i = (i + static_cast<ssize_t>(!inserted)) & (LookupKeysSize - 1);\n  }\n\n  // It can be easier in some cases to think of this as a key-throughput rate of\n  // insertion rather than the latency of inserting N keys, so construct the\n  // rate counter as well.\n  state.counters[\"KeyRate\"] = benchmark::Counter(\n      keys.size(), benchmark::Counter::kIsIterationInvariantRate);\n\n  // Report some extra statistics about the Carbon type.\n  if constexpr (IsCarbonSet<SetT>) {\n    // Re-build a set outside of the timing loop to look at the statistics\n    // rather than the timing.\n    SetT s;\n    for (auto k : keys) {\n      bool inserted = s.Insert(k).is_inserted();\n      CARBON_DCHECK(inserted, \"Must be a successful insert!\");\n    }\n\n    ReportTableMetrics(s, state);\n\n    // Uncomment this call to print out statistics about the index-collisions\n    // among these keys for debugging:\n    //\n    // RawHashtable::DumpHashStatistics(raw_keys);\n  }\n}\nMAP_BENCHMARK_OP_SEQ(BM_SetInsertSeq);\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/set_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/set.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <initializer_list>\n#include <type_traits>\n#include <vector>\n\n#include \"common/raw_hashtable_test_helpers.h\"\n\nnamespace Carbon {\nnamespace {\n\nusing RawHashtable::IndexKeyContext;\nusing RawHashtable::MoveOnlyTestData;\nusing RawHashtable::TestData;\nusing ::testing::UnorderedElementsAreArray;\n\ntemplate <typename SetT, typename MatcherRangeT>\nauto ExpectSetElementsAre(SetT&& s, MatcherRangeT element_matchers) -> void {\n  // Collect the elements into a container.\n  using KeyT = typename std::remove_reference<SetT>::type::KeyT;\n  std::vector<std::reference_wrapper<KeyT>> entries;\n  s.ForEach([&entries](KeyT& k) { entries.push_back(std::ref(k)); });\n\n  // Use the GoogleMock unordered container matcher to validate and show errors\n  // on wrong elements.\n  EXPECT_THAT(entries, UnorderedElementsAreArray(element_matchers));\n}\n\n// Allow directly using an initializer list.\ntemplate <typename SetT, typename MatcherT>\nauto ExpectSetElementsAre(SetT&& s,\n                          std::initializer_list<MatcherT> element_matchers)\n    -> void {\n  std::vector<MatcherT> element_matchers_storage = element_matchers;\n  ExpectSetElementsAre(s, element_matchers_storage);\n}\n\ntemplate <typename RangeT, typename... RangeTs>\nauto MakeElements(RangeT&& range, RangeTs&&... ranges) {\n  std::vector<typename RangeT::value_type> elements;\n  auto add_range = [&elements](RangeT&& r) {\n    for (const auto&& e : r) {\n      elements.push_back(e);\n    }\n  };\n  add_range(std::forward<RangeT>(range));\n  (add_range(std::forward<RangeTs>(ranges)), ...);\n\n  return elements;\n}\n\ntemplate <typename SetT>\nclass SetTest : public ::testing::Test {};\n\ntemplate <typename SetT>\nclass MoveOnlySetTest : public ::testing::Test {};\n\nusing Types = ::testing::Types<Set<int>, Set<int, 16>, Set<int, 128>,\n                               Set<TestData>, Set<TestData, 16>>;\nTYPED_TEST_SUITE(SetTest, Types);\n\nusing MoveOnlyTypes =\n    ::testing::Types<Set<MoveOnlyTestData>, Set<MoveOnlyTestData, 16>,\n                     Set<MoveOnlyTestData, 64>>;\nTYPED_TEST_SUITE(MoveOnlySetTest, MoveOnlyTypes);\n\nTYPED_TEST(SetTest, Basic) {\n  using SetT = TypeParam;\n  SetT s;\n\n  EXPECT_FALSE(s.Contains(42));\n  EXPECT_TRUE(s.Insert(1).is_inserted());\n  EXPECT_TRUE(s.Contains(1));\n  auto result = s.Lookup(1);\n  EXPECT_TRUE(result);\n  EXPECT_EQ(1, result.key());\n  auto i_result = s.Insert(1);\n  EXPECT_FALSE(i_result.is_inserted());\n  EXPECT_TRUE(s.Contains(1));\n\n  // Verify all the elements.\n  ExpectSetElementsAre(s, {1});\n\n  // Fill up a bunch to ensure we trigger growth a few times.\n  for (int i : llvm::seq(2, 512)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(s.Insert(i).is_inserted());\n  }\n  for (int i : llvm::seq(1, 512)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(s.Contains(i));\n    EXPECT_FALSE(s.Insert(i).is_inserted());\n  }\n  EXPECT_FALSE(s.Contains(513));\n\n  // Verify all the elements.\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(1, 512)));\n}\n\nTYPED_TEST(SetTest, FactoryApi) {\n  using SetT = TypeParam;\n  SetT s;\n  EXPECT_TRUE(s.Insert(1, [](int k, void* key_storage) {\n                 return new (key_storage) int(k);\n               }).is_inserted());\n  ASSERT_TRUE(s.Contains(1));\n  // Reinsertion doesn't invoke the callback.\n  EXPECT_FALSE(s.Insert(1, [](int, void*) -> int* {\n                  llvm_unreachable(\"Should never be called!\");\n                }).is_inserted());\n}\n\nTYPED_TEST(SetTest, Copy) {\n  using SetT = TypeParam;\n\n  SetT s;\n  // Make sure we exceed the small size for some of the set types, but not all\n  // of them, so we cover all the combinations of copying between small and\n  // large.\n  for (int i : llvm::seq(1, 24)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Insert(i).is_inserted());\n  }\n\n  SetT other_s1 = s;\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 24)));\n\n  // Add some more elements to the original.\n  for (int i : llvm::seq(24, 32)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Insert(i).is_inserted());\n  }\n\n  // The first copy doesn't change.\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 24)));\n\n  // A new copy does.\n  SetT other_s2 = s;\n  ExpectSetElementsAre(other_s2, MakeElements(llvm::seq(1, 32)));\n\n  // Copy-assign updates.\n  other_s1 = s;\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 32)));\n\n  // Self-assign is a no-op.\n  other_s1 = const_cast<const SetT&>(other_s1);\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 32)));\n\n  // But mutating original still doesn't change copies.\n  for (int i : llvm::seq(32, 48)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Insert(i).is_inserted());\n  }\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 32)));\n  ExpectSetElementsAre(other_s2, MakeElements(llvm::seq(1, 32)));\n}\n\nTYPED_TEST(SetTest, Move) {\n  using SetT = TypeParam;\n\n  SetT s;\n  // Make sure we exceed the small size for some of the set types, but not all\n  // of them, so we cover all the combinations of copying between small and\n  // large.\n  for (int i : llvm::seq(1, 24)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(s.Insert(i).is_inserted());\n  }\n\n  SetT other_s1 = std::move(s);\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 24)));\n\n  // Add some more elements.\n  for (int i : llvm::seq(24, 32)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(other_s1.Insert(i).is_inserted());\n  }\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 32)));\n\n  // Move back over a moved-from.\n  s = std::move(other_s1);\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(1, 32)));\n\n  // Copy over moved-from state also works.\n  other_s1 = s;\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 32)));\n\n  // Now add still more elements.\n  for (int i : llvm::seq(32, 48)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(other_s1.Insert(i).is_inserted());\n  }\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 48)));\n\n  // Move-assign over the copy looks like the moved-from table not the copy.\n  other_s1 = std::move(s);\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 32)));\n\n  // Self-swap (which does a self-move) works and is a no-op.\n  std::swap(other_s1, other_s1);\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 32)));\n\n  // Test copying of a moved-from table over a valid table and\n  // self-move-assign. The former is required to be valid, and the latter is\n  // in at least the case of self-move-assign-when-moved-from, but the result\n  // can be in any state so just do them and ensure we don't crash.\n  SetT other_s2 = other_s1;\n  // NOLINTNEXTLINE(bugprone-use-after-move): Testing required use-after-move.\n  other_s2 = s;\n  other_s1 = std::move(other_s1);\n  s = std::move(s);\n}\n\nTYPED_TEST(MoveOnlySetTest, Move) {\n  using SetT = TypeParam;\n  static_assert(!std::is_copy_assignable_v<SetT>);\n  static_assert(!std::is_copy_constructible_v<SetT>);\n  static_assert(std::is_move_assignable_v<SetT>);\n  static_assert(std::is_move_constructible_v<SetT>);\n\n  auto make_set = [] {\n    SetT s;\n    // Make sure we exceed the small size for some of the set types, but not all\n    // of them, so we cover all the combinations of copying between small and\n    // large.\n    for (int i : llvm::seq(1, 24)) {\n      SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n      EXPECT_TRUE(s.Insert(i).is_inserted());\n    }\n    return s;\n  };\n\n  SetT s = make_set();\n\n  SetT other_s1 = std::move(s);\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 24)));\n\n  // Add some more elements.\n  for (int i : llvm::seq(24, 32)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(other_s1.Insert(i).is_inserted());\n  }\n  ExpectSetElementsAre(other_s1, MakeElements(llvm::seq(1, 32)));\n\n  // Move back over a moved-from.\n  s = std::move(other_s1);\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(1, 32)));\n\n  // Now add still more elements, crossing the small size limit for all tested\n  // map types.\n  for (int i : llvm::seq(32, 72)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Insert(i).is_inserted());\n  }\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(1, 72)));\n\n  // Assignment replaces the contents.\n  s = make_set();\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(1, 24)));\n\n  // Self-swap (which does a self-move) works and is a no-op.\n  std::swap(s, s);\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(1, 24)));\n}\n\nTYPED_TEST(SetTest, Conversions) {\n  using SetT = TypeParam;\n  using KeyT = SetT::KeyT;\n  SetT s;\n  ASSERT_TRUE(s.Insert(1).is_inserted());\n  ASSERT_TRUE(s.Insert(2).is_inserted());\n  ASSERT_TRUE(s.Insert(3).is_inserted());\n  ASSERT_TRUE(s.Insert(4).is_inserted());\n\n  SetView<KeyT> sv = s;\n  SetView<const KeyT> csv = sv;\n  SetView<const KeyT> csv2 = s;\n  EXPECT_TRUE(sv.Contains(1));\n  EXPECT_TRUE(csv.Contains(2));\n  EXPECT_TRUE(csv2.Contains(3));\n}\n\nTYPED_TEST(SetTest, GrowToAllocSize) {\n  using SetT = TypeParam;\n\n  SetT s;\n  // Grow when empty. May be a no-op for some small sizes.\n  s.GrowToAllocSize(32);\n\n  // Add some elements that will need to be propagated through subsequent\n  // growths. Also delete some.\n  ssize_t storage_bytes = s.ComputeMetrics().storage_bytes;\n  for (int i : llvm::seq(1, 24)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Insert(i).is_inserted());\n  }\n  for (int i : llvm::seq(1, 8)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Erase(i));\n  }\n  // No further growth triggered.\n  EXPECT_EQ(storage_bytes, s.ComputeMetrics().storage_bytes);\n\n  // No-op.\n  s.GrowToAllocSize(16);\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(8, 24)));\n  // No further growth triggered.\n  EXPECT_EQ(storage_bytes, s.ComputeMetrics().storage_bytes);\n\n  // Get a few doubling based growths, and at least one beyond the largest small\n  // size.\n  s.GrowToAllocSize(64);\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(8, 24)));\n  s.GrowToAllocSize(128);\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(8, 24)));\n  s.GrowToAllocSize(256);\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(8, 24)));\n  // Update the storage bytes after growth.\n  EXPECT_LT(storage_bytes, s.ComputeMetrics().storage_bytes);\n  storage_bytes = s.ComputeMetrics().storage_bytes;\n\n  // Add some more, but not enough to trigger further growth, and then grow by\n  // several more multiples of two to test handling large growth.\n  for (int i : llvm::seq(24, 48)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Insert(i).is_inserted());\n  }\n  for (int i : llvm::seq(8, 16)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Erase(i));\n  }\n  // No growth from insertions.\n  EXPECT_EQ(storage_bytes, s.ComputeMetrics().storage_bytes);\n\n  s.GrowToAllocSize(1024);\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(16, 48)));\n  // Storage should have grown.\n  EXPECT_LT(storage_bytes, s.ComputeMetrics().storage_bytes);\n}\n\nTYPED_TEST(SetTest, GrowForInsert) {\n  using SetT = TypeParam;\n\n  SetT s;\n  s.GrowForInsertCount(42);\n  ssize_t storage_bytes = s.ComputeMetrics().storage_bytes;\n  for (int i : llvm::seq(1, 42)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Insert(i).is_inserted());\n  }\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(1, 42)));\n  EXPECT_EQ(storage_bytes, s.ComputeMetrics().storage_bytes);\n\n  // Erase many elements and grow again for another insert.\n  for (int i : llvm::seq(1, 32)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Erase(i));\n  }\n  s.GrowForInsertCount(42);\n  storage_bytes = s.ComputeMetrics().storage_bytes;\n  for (int i : llvm::seq(42, 84)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Insert(i).is_inserted());\n  }\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(32, 84)));\n  EXPECT_EQ(storage_bytes, s.ComputeMetrics().storage_bytes);\n\n  // Erase all the elements, then grow for a much larger insertion and insert\n  // again.\n  for (int i : llvm::seq(32, 84)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Erase(i));\n  }\n  s.GrowForInsertCount(321);\n  storage_bytes = s.ComputeMetrics().storage_bytes;\n  for (int i : llvm::seq(128, 321 + 128)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    ASSERT_TRUE(s.Insert(i).is_inserted());\n  }\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(128, 321 + 128)));\n  EXPECT_EQ(storage_bytes, s.ComputeMetrics().storage_bytes);\n}\n\nTEST(SetContextTest, Basic) {\n  llvm::SmallVector<TestData> keys;\n  for (int i : llvm::seq(0, 513)) {\n    keys.push_back(i * 100);\n  }\n  IndexKeyContext<TestData> key_context(keys);\n  Set<ssize_t, 0, IndexKeyContext<TestData>> s;\n\n  EXPECT_FALSE(s.Contains(42, key_context));\n  EXPECT_TRUE(s.Insert(1, key_context).is_inserted());\n  EXPECT_TRUE(s.Contains(1, key_context));\n  auto result = s.Lookup(TestData(100), key_context);\n  EXPECT_TRUE(result);\n  EXPECT_EQ(1, result.key());\n  auto i_result = s.Insert(1, IndexKeyContext<TestData>(keys));\n  EXPECT_FALSE(i_result.is_inserted());\n  EXPECT_TRUE(s.Contains(1, key_context));\n  EXPECT_TRUE(\n      s.Insert(TestData(200), [] { return 2; }, key_context).is_inserted());\n  EXPECT_TRUE(s.Contains(2, key_context));\n  EXPECT_TRUE(s.Contains(TestData(200), key_context));\n\n  // Verify all the elements.\n  ExpectSetElementsAre(s, {1, 2});\n\n  // Fill up a bunch to ensure we trigger growth a few times.\n  for (int i : llvm::seq(3, 512)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(s.Insert(i, key_context).is_inserted());\n  }\n  for (int i : llvm::seq(1, 512)) {\n    SCOPED_TRACE(llvm::formatv(\"Key: {0}\", i).str());\n    EXPECT_TRUE(s.Contains(i, key_context));\n    EXPECT_FALSE(s.Insert(i, key_context).is_inserted());\n  }\n  EXPECT_FALSE(s.Contains(0, key_context));\n  EXPECT_FALSE(s.Contains(512, key_context));\n  EXPECT_FALSE(s.Contains(TestData(0), key_context));\n  EXPECT_FALSE(s.Contains(TestData(51200), key_context));\n\n  // Verify all the elements.\n  ExpectSetElementsAre(s, MakeElements(llvm::seq(1, 512)));\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/string_helpers.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/string_helpers.h\"\n\n#include <string.h>\n#include <sys/types.h>\n\n#include <algorithm>\n#include <array>\n#include <optional>\n#include <string>\n\n#include \"common/check.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/STLExtras.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/Allocator.h\"\n#include \"llvm/Support/ConvertUTF.h\"\n\nnamespace Carbon {\n\nstatic constexpr llvm::StringRef TripleQuotes = \"'''\";\nstatic constexpr llvm::StringRef HorizontalWhitespaceChars = \" \\t\";\n\n// Carbon only takes uppercase hex input.\nstatic auto FromHex(char c) -> std::optional<char> {\n  if (c >= '0' && c <= '9') {\n    return c - '0';\n  }\n  if (c >= 'A' && c <= 'F') {\n    return 10 + c - 'A';\n  }\n  return std::nullopt;\n}\n\nauto UnescapeStringLiteral(llvm::StringRef source, const int hashtag_num,\n                           bool is_block_string) -> std::optional<std::string> {\n  std::string ret;\n  ret.reserve(source.size());\n  std::string escape = \"\\\\\";\n  escape.resize(hashtag_num + 1, '#');\n  size_t i = 0;\n  while (i < source.size()) {\n    char c = source[i];\n    if (i + hashtag_num < source.size() &&\n        source.slice(i, i + hashtag_num + 1) == escape) {\n      i += hashtag_num + 1;\n      if (i == source.size()) {\n        return std::nullopt;\n      }\n      switch (source[i]) {\n        case 'n':\n          ret.push_back('\\n');\n          break;\n        case 'r':\n          ret.push_back('\\r');\n          break;\n        case 't':\n          ret.push_back('\\t');\n          break;\n        case '0':\n          if (i + 1 < source.size() && llvm::isDigit(source[i + 1])) {\n            // \\0[0-9] is reserved.\n            return std::nullopt;\n          }\n          ret.push_back('\\0');\n          break;\n        case '\"':\n          ret.push_back('\"');\n          break;\n        case '\\'':\n          ret.push_back('\\'');\n          break;\n        case '\\\\':\n          ret.push_back('\\\\');\n          break;\n        case 'x': {\n          i += 2;\n          if (i >= source.size()) {\n            return std::nullopt;\n          }\n          std::optional<char> c1 = FromHex(source[i - 1]);\n          std::optional<char> c2 = FromHex(source[i]);\n          if (c1 == std::nullopt || c2 == std::nullopt) {\n            return std::nullopt;\n          }\n          ret.push_back(16 * *c1 + *c2);\n          break;\n        }\n        case 'u': {\n          ++i;\n          if (i >= source.size() || source[i] != '{') {\n            return std::nullopt;\n          }\n          unsigned int unicode_int = 0;\n          ++i;\n          int original_i = i;\n          while (i < source.size() && source[i] != '}') {\n            std::optional<char> hex_val = FromHex(source[i]);\n            if (hex_val == std::nullopt) {\n              return std::nullopt;\n            }\n            unicode_int = unicode_int << 4;\n            unicode_int += hex_val.value();\n            ++i;\n            if (i - original_i > 8) {\n              return std::nullopt;\n            }\n          }\n          if (i >= source.size()) {\n            return std::nullopt;\n          }\n          if (i - original_i == 0) {\n            return std::nullopt;\n          }\n          char utf8_buf[4];\n          char* utf8_end = &utf8_buf[0];\n          if (!llvm::ConvertCodePointToUTF8(unicode_int, utf8_end)) {\n            return std::nullopt;\n          }\n          ret.append(utf8_buf, utf8_end - utf8_buf);\n          break;\n        }\n        case '\\n':\n          if (!is_block_string) {\n            return std::nullopt;\n          }\n          break;\n        default:\n          // Unsupported.\n          return std::nullopt;\n      }\n    } else if (c == '\\t') {\n      // Disallow non-` ` horizontal whitespace:\n      // https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/lexical_conventions/whitespace.md\n      // TODO: This doesn't handle unicode whitespace.\n      return std::nullopt;\n    } else {\n      ret.push_back(c);\n    }\n    ++i;\n  }\n  return ret;\n}\n\nauto ParseBlockStringLiteral(llvm::StringRef source, const int hashtag_num)\n    -> ErrorOr<std::string> {\n  llvm::SmallVector<llvm::StringRef> lines;\n  source.split(lines, '\\n', /*MaxSplit=*/-1, /*KeepEmpty=*/true);\n  if (lines.size() < 2) {\n    return Error(\"Too few lines\");\n  }\n\n  llvm::StringRef first = lines[0];\n  if (!first.consume_front(TripleQuotes)) {\n    return Error(\"Should start with triple quotes: \" + first);\n  }\n  first = first.rtrim(HorizontalWhitespaceChars);\n  // Remaining chars, if any, are a file type indicator.\n  if (first.find_first_of(\"\\\"#\") != llvm::StringRef::npos ||\n      first.find_first_of(HorizontalWhitespaceChars) != llvm::StringRef::npos) {\n    return Error(\"Invalid characters in file type indicator: \" + first);\n  }\n\n  llvm::StringRef last = lines[lines.size() - 1];\n  const size_t last_length = last.size();\n  last = last.ltrim(HorizontalWhitespaceChars);\n  const size_t indent = last_length - last.size();\n  if (last != TripleQuotes) {\n    return Error(\"Should end with triple quotes: \" + last);\n  }\n\n  std::string parsed;\n  for (size_t i = 1; i < lines.size() - 1; ++i) {\n    llvm::StringRef line = lines[i];\n    const size_t first_non_ws =\n        line.find_first_not_of(HorizontalWhitespaceChars);\n    if (first_non_ws == llvm::StringRef::npos) {\n      // Empty or whitespace-only line.\n      line = \"\";\n    } else {\n      if (first_non_ws < indent) {\n        return Error(\"Wrong indent for line: \" + line + \", expected \" +\n                     llvm::Twine(indent));\n      }\n      line = line.drop_front(indent).rtrim(HorizontalWhitespaceChars);\n    }\n    // Unescaping with \\n appended to handle things like \\\\<newline>.\n    llvm::SmallVector<char> buffer;\n    std::optional<std::string> unescaped =\n        UnescapeStringLiteral((line + \"\\n\").toStringRef(buffer), hashtag_num,\n                              /*is_block_string=*/true);\n    if (!unescaped.has_value()) {\n      return Error(\"Invalid escaping in \" + line);\n    }\n    // A \\<newline> string collapses into nothing.\n    if (!unescaped->empty()) {\n      parsed.append(*unescaped);\n    }\n  }\n  return parsed;\n}\n\nauto StringRefContainsPointer(llvm::StringRef ref, const char* ptr) -> bool {\n  auto le = std::less_equal<>();\n  return le(ref.begin(), ptr) && le(ptr, ref.end());\n}\n\nauto BuildCStrArgs(llvm::StringRef tool_path,\n                   llvm::ArrayRef<llvm::StringRef> args,\n                   llvm::BumpPtrAllocator& alloc)\n    -> llvm::SmallVector<const char*, 64> {\n  return BuildCStrArgs(tool_path, /*prefix_args=*/{}, args, alloc);\n}\n\nauto BuildCStrArgs(llvm::StringRef tool_path,\n                   llvm::ArrayRef<std::string> prefix_args,\n                   llvm::ArrayRef<llvm::StringRef> args,\n                   llvm::BumpPtrAllocator& alloc)\n    -> llvm::SmallVector<const char*, 64> {\n  ssize_t i = 0;\n  auto make_cstr = [&](llvm::StringRef arg) {\n    char* cstr = alloc.Allocate<char>(arg.size() + 1);\n    memcpy(cstr, arg.data(), arg.size());\n    cstr[arg.size()] = '\\0';\n    i += arg.size() + 1;\n    return cstr;\n  };\n\n  llvm::SmallVector<const char*, 64> cstr_args;\n  cstr_args.reserve(1 + prefix_args.size() + args.size());\n  cstr_args.push_back(make_cstr(tool_path));\n  for (const std::string& prefix_arg : prefix_args) {\n    cstr_args.push_back(prefix_arg.c_str());\n  }\n  for (llvm::StringRef arg : args) {\n    cstr_args.push_back(make_cstr(arg));\n  }\n\n  return cstr_args;\n}\n\n}  // namespace Carbon\n"
  },
  {
    "path": "common/string_helpers.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_STRING_HELPERS_H_\n#define CARBON_COMMON_STRING_HELPERS_H_\n\n#include <optional>\n#include <string>\n\n#include \"common/error.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/Allocator.h\"\n\nnamespace Carbon {\n\n// Note llvm StringExtras has significant functionality which is intended to be\n// complementary to this.\n\n// Unescapes Carbon escape sequences in the source string. Returns std::nullopt\n// on bad input. `is_block_string` enables escaping unique to block string\n// literals, such as \\<newline>.\nauto UnescapeStringLiteral(llvm::StringRef source, int hashtag_num = 0,\n                           bool is_block_string = false)\n    -> std::optional<std::string>;\n\n// Parses a block string literal in `source`.\nauto ParseBlockStringLiteral(llvm::StringRef source, int hashtag_num = 0)\n    -> ErrorOr<std::string>;\n\n// Returns true if the pointer is in the string ref (including equality with\n// `ref.end()`). This should be used instead of `<=` comparisons for\n// correctness.\nauto StringRefContainsPointer(llvm::StringRef ref, const char* ptr) -> bool;\n\n// Converts `tool_path` and each of the `args` into C-strings and returns the\n// results. This is intended for use with APIs that expect `argv`-like command\n// line argument lists.\n//\n// Accepts a `cstr_arg_storage` that will provide the underlying storage for\n// the C-strings, and returns a small vector of the C-string pointers. The\n// returned small vector uses a large small size to allow most common command\n// lines to avoid extra allocations and growth passes.\nauto BuildCStrArgs(llvm::StringRef tool_path,\n                   llvm::ArrayRef<llvm::StringRef> args,\n                   llvm::BumpPtrAllocator& alloc)\n    -> llvm::SmallVector<const char*, 64>;\n\n// An overload of `BuildCStrArgs` with the same core behavior as the above, but\n// with an extra series of `prefix_args` that are placed between the `tool_path`\n// and the `args` in the resulting list.\n//\n// Unlike the tool path and the main `args`, the `prefix_args` are accepted as\n// an array of `std::string`s and those string object's `c_str()` method is used\n// to get the underlying C-strings to include in the result. This is because\n// callers with prefix arguments regularly need to provide dedicated storage for\n// these arguments anyways and we can efficiently reuse that. In contrast, the\n// `args` are often pulled from an existing `llvm::StringRef` that may never\n// exist as a valid C-string and so we need to rebuild those using the storage.\nauto BuildCStrArgs(llvm::StringRef tool_path,\n                   llvm::ArrayRef<std::string> prefix_args,\n                   llvm::ArrayRef<llvm::StringRef> args,\n                   llvm::BumpPtrAllocator& alloc)\n    -> llvm::SmallVector<const char*, 64>;\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_STRING_HELPERS_H_\n"
  },
  {
    "path": "common/string_helpers_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/string_helpers.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <optional>\n#include <string>\n\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/Allocator.h\"\n\nusing ::testing::Eq;\nusing ::testing::Optional;\nusing ::testing::StrEq;\n\nnamespace Carbon {\nnamespace {\n\nTEST(UnescapeStringLiteral, Valid) {\n  EXPECT_THAT(UnescapeStringLiteral(\"test\"), Optional(Eq(\"test\")));\n  EXPECT_THAT(UnescapeStringLiteral(\"okay whitespace\"),\n              Optional(Eq(\"okay whitespace\")));\n  EXPECT_THAT(UnescapeStringLiteral(\"test\\n\"), Optional(Eq(\"test\\n\")));\n  EXPECT_THAT(UnescapeStringLiteral(\"test\\\\n\"), Optional(Eq(\"test\\n\")));\n  EXPECT_THAT(UnescapeStringLiteral(\"abc\\\\ndef\"), Optional(Eq(\"abc\\ndef\")));\n  EXPECT_THAT(UnescapeStringLiteral(\"test\\\\\\\\n\"), Optional(Eq(\"test\\\\n\")));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\xAA\"), Optional(Eq(\"\\xAA\")));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\x12\"), Optional(Eq(\"\\x12\")));\n  EXPECT_THAT(UnescapeStringLiteral(\"test\", 1), Optional(Eq(\"test\")));\n  EXPECT_THAT(UnescapeStringLiteral(\"test\\\\#n\", 1), Optional(Eq(\"test\\n\")));\n  EXPECT_THAT(UnescapeStringLiteral(\n                  \"r\\\\u{000000E9}al \\\\u{2764}\\\\u{FE0F}\\\\u{1F50A}!\\\\u{10FFFF}\"),\n              Optional(Eq(\"réal ❤️🔊!􏿿\")));\n}\n\nTEST(UnescapeStringLiteral, Invalid) {\n  // Missing char after `\\`.\n  EXPECT_THAT(UnescapeStringLiteral(\"a\\\\\"), Eq(std::nullopt));\n  // Not a supported escape.\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\e\"), Eq(std::nullopt));\n  // Needs 2 hex chars.\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\x\"), Eq(std::nullopt));\n  // Needs 2 hex chars.\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\xA\"), Eq(std::nullopt));\n  // Needs uppercase hex.\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\xaa\"), Eq(std::nullopt));\n  // Reserved.\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\00\"), Eq(std::nullopt));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\#00\", 1), Eq(std::nullopt));\n}\n\nTEST(UnescapeStringLiteral, InvalidUnicodes) {\n  // Various incomplete Unicode specifiers\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u\"), Eq(std::nullopt));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u1\"), Eq(std::nullopt));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\uz\"), Eq(std::nullopt));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u{\"), Eq(std::nullopt));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u{z\"), Eq(std::nullopt));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u{E9\"), Eq(std::nullopt));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u{E9z\"), Eq(std::nullopt));\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u{}\"), Eq(std::nullopt));\n\n  // invalid characters in unicode\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u{z}\"), Eq(std::nullopt));\n\n  // lowercase hexadecimal\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u{e9}\"), Eq(std::nullopt));\n\n  // Codepoint number too high\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u{110000}\"), Eq(std::nullopt));\n\n  // codepoint more than 8 hex digits\n  EXPECT_THAT(UnescapeStringLiteral(\"\\\\u{FF000000E9}\"), Eq(std::nullopt));\n}\n\nTEST(UnescapeStringLiteral, Nul) {\n  std::optional<std::string> str = UnescapeStringLiteral(\"a\\\\0b\");\n  ASSERT_NE(str, std::nullopt);\n  EXPECT_THAT(str->size(), Eq(3));\n  EXPECT_THAT(strlen(str->c_str()), Eq(1));\n  EXPECT_THAT((*str)[0], Eq('a'));\n  EXPECT_THAT((*str)[1], Eq('\\0'));\n  EXPECT_THAT((*str)[2], Eq('b'));\n}\n\nTEST(ParseBlockStringLiteral, FailTooFewLines) {\n  EXPECT_THAT(ParseBlockStringLiteral(\"\").error().message(),\n              Eq(\"Too few lines\"));\n}\n\nTEST(ParseBlockStringLiteral, FailNoLeadingTripleQuotes) {\n  EXPECT_THAT(ParseBlockStringLiteral(\"'a'\\n\").error().message(),\n              Eq(\"Should start with triple quotes: 'a'\"));\n}\n\nTEST(ParseBlockStringLiteral, FailInvalideFiletypeIndicator) {\n  EXPECT_THAT(ParseBlockStringLiteral(\"'''carbon file\\n\").error().message(),\n              Eq(\"Invalid characters in file type indicator: carbon file\"));\n}\n\nTEST(ParseBlockStringLiteral, FailEndingTripleQuotes) {\n  EXPECT_THAT(ParseBlockStringLiteral(\"'''\\n\").error().message(),\n              Eq(\"Should end with triple quotes: \"));\n}\n\nTEST(ParseBlockStringLiteral, FailWrongIndent) {\n  constexpr char Input[] = R\"('''\n     A block string literal\n    with wrong indent\n     ''')\";\n  EXPECT_THAT(ParseBlockStringLiteral(Input).error().message(),\n              Eq(\"Wrong indent for line:     with wrong indent, expected 5\"));\n}\n\nTEST(ParseBlockStringLiteral, FailInvalidEscaping) {\n  constexpr char Input[] = R\"('''\n     \\q\n     ''')\";\n  EXPECT_THAT(ParseBlockStringLiteral(Input).error().message(),\n              Eq(\"Invalid escaping in \\\\q\"));\n  constexpr char InputRaw[] = R\"('''\n     \\#q\n     ''')\";\n  EXPECT_THAT(ParseBlockStringLiteral(InputRaw, 1).error().message(),\n              Eq(\"Invalid escaping in \\\\#q\"));\n}\n\nTEST(ParseBlockStringLiteral, OkEmptyString) {\n  constexpr char Input[] = R\"('''\n''')\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(\"\"));\n}\n\nTEST(ParseBlockStringLiteral, OkOneLineString) {\n  constexpr char Input[] = R\"('''\n     A block string literal\n     ''')\";\n  constexpr char Expected[] = R\"(A block string literal\n)\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));\n}\n\nTEST(ParseBlockStringLiteral, OkTwoLineString) {\n  constexpr char Input[] = R\"('''\n     A block string literal\n       with indent.\n     ''')\";\n  constexpr char Expected[] = R\"(A block string literal\n  with indent.\n)\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));\n}\n\nTEST(ParseBlockStringLiteral, OkWithFileTypeIndicator) {\n  constexpr char Input[] = R\"('''carbon\n     A block string literal\n       with file type indicator.\n     ''')\";\n  constexpr char Expected[] = R\"(A block string literal\n  with file type indicator.\n)\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));\n}\n\nTEST(ParseBlockStringLiteral, OkWhitespaceAfterOpeningQuotes) {\n  constexpr char Input[] = R\"('''\n     A block string literal\n     ''')\";\n  constexpr char Expected[] = R\"(A block string literal\n)\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));\n}\n\nTEST(ParseBlockStringLiteral, OkWithEmptyLines) {\n  constexpr char Input[] = R\"('''\n     A block string literal\n\n       with\n\n       empty\n\n       lines.\n     ''')\";\n  constexpr char Expected[] = R\"(A block string literal\n\n  with\n\n  empty\n\n  lines.\n)\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));\n}\n\nTEST(ParseBlockStringLiteral, OkWithSlashNewlineEscape) {\n  constexpr char Input[] = R\"('''\n     A block string literal\\\n     ''')\";\n  constexpr char Expected[] = \"A block string literal\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));\n}\n\nTEST(ParseBlockStringLiteral, OkWithDoubleSlashNewline) {\n  constexpr char Input[] = R\"('''\n     A block string literal\\\\\n     ''')\";\n  constexpr char Expected[] = R\"(A block string literal\\\n)\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));\n}\n\nTEST(ParseBlockStringLiteral, OkWithTripleSlashNewline) {\n  constexpr char Input[] = R\"('''\n     A block string literal\\\\\\\n     ''')\";\n  constexpr char Expected[] = R\"(A block string literal\\)\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));\n}\n\nTEST(ParseBlockStringLiteral, OkMultipleSlashes) {\n  constexpr char Input[] = R\"('''\n     A block string literal\\\n     \\\n     \\\n     \\\n     ''')\";\n  constexpr char Expected[] = \"A block string literal\";\n  EXPECT_THAT(*ParseBlockStringLiteral(Input), Eq(Expected));\n}\n\nTEST(BuildCStrArgs, NoArgs) {\n  llvm::BumpPtrAllocator alloc;\n  auto result = BuildCStrArgs(\"tool\", {}, alloc);\n  ASSERT_THAT(result.size(), Eq(1));\n  EXPECT_THAT(result[0], StrEq(\"tool\"));\n}\n\nTEST(BuildCStrArgs, OneArg) {\n  llvm::BumpPtrAllocator alloc;\n  auto result = BuildCStrArgs(\"tool\", {\"arg1\"}, alloc);\n  ASSERT_THAT(result.size(), Eq(2));\n  EXPECT_THAT(result[0], StrEq(\"tool\"));\n  EXPECT_THAT(result[1], StrEq(\"arg1\"));\n}\n\nTEST(BuildCStrArgs, MultipleArgs) {\n  llvm::BumpPtrAllocator alloc;\n  auto result = BuildCStrArgs(\"tool\", {\"arg1\", \"arg2\"}, alloc);\n  ASSERT_THAT(result.size(), Eq(3));\n  EXPECT_THAT(result[0], StrEq(\"tool\"));\n  EXPECT_THAT(result[1], StrEq(\"arg1\"));\n  EXPECT_THAT(result[2], StrEq(\"arg2\"));\n}\n\nTEST(BuildCStrArgsWithPrefix, NoArgs) {\n  llvm::BumpPtrAllocator alloc;\n  auto result = BuildCStrArgs(\"tool\", {}, {}, alloc);\n  ASSERT_THAT(result.size(), Eq(1));\n  EXPECT_THAT(result[0], StrEq(\"tool\"));\n}\n\nTEST(BuildCStrArgsWithPrefix, PrefixOnly) {\n  llvm::BumpPtrAllocator alloc;\n  std::string prefix_args[] = {\"p_arg1\", \"p_arg2\"};\n  auto result = BuildCStrArgs(\"tool\", prefix_args, {}, alloc);\n  ASSERT_THAT(result.size(), Eq(3));\n  EXPECT_THAT(result[0], StrEq(\"tool\"));\n  EXPECT_THAT(result[1], Eq(prefix_args[0].c_str()));\n  EXPECT_THAT(result[2], Eq(prefix_args[1].c_str()));\n}\n\nTEST(BuildCStrArgsWithPrefix, ArgsOnly) {\n  llvm::BumpPtrAllocator alloc;\n  auto result = BuildCStrArgs(\"tool\", {}, {\"arg1\", \"arg2\"}, alloc);\n  ASSERT_THAT(result.size(), Eq(3));\n  EXPECT_THAT(result[0], StrEq(\"tool\"));\n  EXPECT_THAT(result[1], StrEq(\"arg1\"));\n  EXPECT_THAT(result[2], StrEq(\"arg2\"));\n}\n\nTEST(BuildCStrArgsWithPrefix, BothPrefixAndArgs) {\n  llvm::BumpPtrAllocator alloc;\n  std::string prefix_args[] = {\"p_arg1\", \"p_arg2\"};\n  auto result = BuildCStrArgs(\"tool\", prefix_args, {\"arg1\", \"arg2\"}, alloc);\n  ASSERT_THAT(result.size(), Eq(5));\n  EXPECT_THAT(result[0], StrEq(\"tool\"));\n  EXPECT_THAT(result[1], Eq(prefix_args[0].c_str()));\n  EXPECT_THAT(result[2], Eq(prefix_args[1].c_str()));\n  EXPECT_THAT(result[3], StrEq(\"arg1\"));\n  EXPECT_THAT(result[4], StrEq(\"arg2\"));\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/struct_reflection.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_STRUCT_REFLECTION_H_\n#define CARBON_COMMON_STRUCT_REFLECTION_H_\n\n// Reflection support for simple struct types.\n//\n// Example usage:\n//\n// ```\n// struct A { int x; std::string y; };\n//\n// A a;\n// std::tuple<int, std::string> t = StructReflection::AsTuple(a);\n// ```\n//\n// Limitations:\n//\n// - Only simple aggregate structs are supported. Types with base classes,\n//   non-public data members, constructors, or virtual functions are not\n//   supported.\n// - Structs with more than 8 fields are not supported. This limit is easy to\n//   increase if needed, but removing it entirely is hard.\n// - Structs containing a reference to the same type are not supported.\n\n#include <tuple>\n#include <type_traits>\n\nnamespace Carbon::StructReflection {\n\nnamespace Internal {\n\n// A type that can be converted to any field type within type T.\ntemplate <typename T>\nstruct AnyField {\n  template <typename FieldT>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  explicit(false) operator FieldT&() const;\n\n  template <typename FieldT>\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  explicit(false) operator FieldT&&() const;\n\n  // Don't allow conversion to T itself. This ensures we don't match against a\n  // copy or move constructor.\n  operator T&() const = delete;\n  operator T&&() const = delete;\n};\n\n// The detection mechanism below intentionally misses field initializers.\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wmissing-field-initializers\"\n\n// Detector for whether we can list-initialize T from the given list of fields.\ntemplate <typename T, typename... Fields>\nconstexpr auto CanListInitialize(decltype(T{Fields()...})* /*unused*/) -> bool {\n  return true;\n}\ntemplate <typename T, typename... Fields>\nconstexpr auto CanListInitialize(...) -> bool {\n  return false;\n}\n\n#pragma clang diagnostic pop\n\n// Simple detector to find the number of data fields in a struct. This proceeds\n// in two passes:\n//\n// 1) Add AnyField<T>s until we can initialize T from our list of initializers.\n// 2) Add more AnyField<T>s until we can't initialize any more.\ntemplate <typename T, bool AnyWorkedSoFar = false, typename... Fields>\nconstexpr auto CountFields() -> int {\n  if constexpr (CanListInitialize<T, Fields...>(nullptr)) {\n    return CountFields<T, true, Fields..., AnyField<T>>();\n  } else if constexpr (AnyWorkedSoFar) {\n    constexpr int NumFields = sizeof...(Fields) - 1;\n    static_assert(NumFields <= 8, \"Unsupported: too many fields in struct\");\n    return NumFields;\n  } else if constexpr (sizeof...(Fields) > 32) {\n    // If we go too far without finding a working initializer, something\n    // probably went wrong with our calculation. Bail out before we recurse too\n    // deeply.\n    static_assert(sizeof...(Fields) <= 32,\n                  \"Internal error, could not count fields in struct\");\n  } else {\n    return CountFields<T, false, Fields..., AnyField<T>>();\n  }\n}\n\n// Utility to access fields by index.\ntemplate <int NumFields>\nstruct FieldAccessor;\n\ntemplate <>\nstruct FieldAccessor<0> {\n  template <typename T>\n  static auto Get(T& /*value*/) -> auto {\n    return std::tuple<>();\n  }\n};\n\ntemplate <>\nstruct FieldAccessor<1> {\n  template <typename T>\n  static auto Get(T& value) -> auto {\n    auto& [field0] = value;\n    return std::tuple<decltype(field0)>(field0);\n  }\n};\n\ntemplate <>\nstruct FieldAccessor<2> {\n  template <typename T>\n  static auto Get(T& value) -> auto {\n    auto& [field0, field1] = value;\n    return std::tuple<decltype(field0), decltype(field1)>(field0, field1);\n  }\n};\n\ntemplate <>\nstruct FieldAccessor<3> {\n  template <typename T>\n  static auto Get(T& value) -> auto {\n    auto& [field0, field1, field2] = value;\n    return std::tuple<decltype(field0), decltype(field1), decltype(field2)>(\n        field0, field1, field2);\n  }\n};\n\ntemplate <>\nstruct FieldAccessor<4> {\n  template <typename T>\n  static auto Get(T& value) -> auto {\n    auto& [field0, field1, field2, field3] = value;\n    return std::tuple<decltype(field0), decltype(field1), decltype(field2),\n                      decltype(field3)>(field0, field1, field2, field3);\n  }\n};\n\ntemplate <>\nstruct FieldAccessor<5> {\n  template <typename T>\n  static auto Get(T& value) -> auto {\n    auto& [field0, field1, field2, field3, field4] = value;\n    return std::tuple<decltype(field0), decltype(field1), decltype(field2),\n                      decltype(field3), decltype(field4)>(\n        field0, field1, field2, field3, field4);\n  }\n};\n\ntemplate <>\nstruct FieldAccessor<6> {\n  template <typename T>\n  static auto Get(T& value) -> auto {\n    auto& [field0, field1, field2, field3, field4, field5] = value;\n    return std::tuple<decltype(field0), decltype(field1), decltype(field2),\n                      decltype(field3), decltype(field4), decltype(field5)>(\n        field0, field1, field2, field3, field4, field5);\n  }\n};\n\ntemplate <>\nstruct FieldAccessor<7> {\n  template <typename T>\n  static auto Get(T& value) -> auto {\n    auto& [field0, field1, field2, field3, field4, field5, field6] = value;\n    return std::tuple<decltype(field0), decltype(field1), decltype(field2),\n                      decltype(field3), decltype(field4), decltype(field5),\n                      decltype(field6)>(field0, field1, field2, field3, field4,\n                                        field5, field6);\n  }\n};\n\ntemplate <>\nstruct FieldAccessor<8> {\n  template <typename T>\n  static auto Get(T& value) -> auto {\n    auto& [field0, field1, field2, field3, field4, field5, field6, field7] =\n        value;\n    return std::tuple<decltype(field0), decltype(field1), decltype(field2),\n                      decltype(field3), decltype(field4), decltype(field5),\n                      decltype(field6), decltype(field7)>(\n        field0, field1, field2, field3, field4, field5, field6, field7);\n  }\n};\n\n}  // namespace Internal\n\n// Get the fields of the struct `T` as a tuple.\ntemplate <typename T>\nauto AsTuple(T value) -> auto {\n  // We use aggregate initialization to detect the number of fields.\n  static_assert(std::is_aggregate_v<T>, \"Only aggregates are supported\");\n  return Internal::FieldAccessor<Internal::CountFields<T>()>::Get(value);\n}\n\n}  // namespace Carbon::StructReflection\n\n#endif  // CARBON_COMMON_STRUCT_REFLECTION_H_\n"
  },
  {
    "path": "common/struct_reflection_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/struct_reflection.h\"\n\n#include <gtest/gtest.h>\n\n#include <tuple>\n\nnamespace Carbon::StructReflection {\nnamespace {\n\nstruct ZeroFields {};\n\nstruct OneField {\n  int x;\n};\n\nstruct TwoFields {\n  int x;\n  int y;\n};\n\nstruct SixFields {\n  int one;\n  int two;\n  int three;\n  int four;\n  int five;\n  int six;\n};\n\nstruct ReferenceField {\n  int& ref;\n};\n\nstruct NoDefaultConstructor {\n  explicit NoDefaultConstructor(int n) : v(n) {}\n  int v;\n};\n\nstruct OneFieldNoDefaultConstructor {\n  NoDefaultConstructor x;\n};\n\nstruct TwoFieldsNoDefaultConstructor {\n  NoDefaultConstructor x;\n  NoDefaultConstructor y;\n};\n\nTEST(StructReflectionTest, CanListInitialize) {\n  {\n    using Type = OneField;\n    using Field = Internal::AnyField<Type>;\n    static_assert(Internal::CanListInitialize<Type>(nullptr));\n    static_assert(Internal::CanListInitialize<Type, Field>(nullptr));\n    static_assert(!Internal::CanListInitialize<Type, Field, Field>(0));\n  }\n\n  {\n    using Type = OneFieldNoDefaultConstructor;\n    using Field = Internal::AnyField<Type>;\n    static_assert(!Internal::CanListInitialize<Type>(0));\n    static_assert(Internal::CanListInitialize<Type, Field>(nullptr));\n    static_assert(!Internal::CanListInitialize<Type, Field, Field>(0));\n  }\n}\n\nTEST(StructReflectionTest, CountFields) {\n  static_assert(Internal::CountFields<ZeroFields>() == 0);\n  static_assert(Internal::CountFields<OneField>() == 1);\n  static_assert(Internal::CountFields<TwoFields>() == 2);\n  static_assert(Internal::CountFields<SixFields>() == 6);\n  static_assert(Internal::CountFields<ReferenceField>() == 1);\n  static_assert(Internal::CountFields<OneFieldNoDefaultConstructor>() == 1);\n}\n\nTEST(StructReflectionTest, EmptyStruct) {\n  std::tuple<> fields = AsTuple(ZeroFields());\n  static_cast<void>(fields);\n}\n\nTEST(StructReflectionTest, OneField) {\n  std::tuple<int> fields = AsTuple(OneField{.x = 1});\n  EXPECT_EQ(std::get<0>(fields), 1);\n}\n\nTEST(StructReflectionTest, TwoFields) {\n  std::tuple<int, int> fields = AsTuple(TwoFields{.x = 1, .y = 2});\n  EXPECT_EQ(std::get<0>(fields), 1);\n  EXPECT_EQ(std::get<1>(fields), 2);\n}\n\nTEST(StructReflectionTest, SixFields) {\n  std::tuple<int, int, int, int, int, int> fields = AsTuple(SixFields{\n      .one = 1, .two = 2, .three = 3, .four = 4, .five = 5, .six = 6});\n  EXPECT_EQ(std::get<0>(fields), 1);\n  EXPECT_EQ(std::get<1>(fields), 2);\n  EXPECT_EQ(std::get<2>(fields), 3);\n  EXPECT_EQ(std::get<3>(fields), 4);\n  EXPECT_EQ(std::get<4>(fields), 5);\n  EXPECT_EQ(std::get<5>(fields), 6);\n}\n\nTEST(StructReflectionTest, NoDefaultConstructor) {\n  std::tuple<NoDefaultConstructor, NoDefaultConstructor> fields =\n      AsTuple(TwoFieldsNoDefaultConstructor{.x = NoDefaultConstructor(1),\n                                            .y = NoDefaultConstructor(2)});\n  EXPECT_EQ(std::get<0>(fields).v, 1);\n  EXPECT_EQ(std::get<1>(fields).v, 2);\n}\n\nTEST(StructReflectionTest, ReferenceField) {\n  int n = 0;\n  std::tuple<int&> fields = AsTuple(ReferenceField{.ref = n});\n  EXPECT_EQ(&std::get<0>(fields), &n);\n}\n\n}  // namespace\n}  // namespace Carbon::StructReflection\n"
  },
  {
    "path": "common/template_string.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_TEMPLATE_STRING_H_\n#define CARBON_COMMON_TEMPLATE_STRING_H_\n\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon {\n\n// Represents a compile-time string in a form suitable for use as a non-type\n// template argument.\n//\n// These arguments are required to be a \"structural type\", and so we copy the\n// string contents into a public array of `char`s. For details, see:\n// https://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter\n//\n// Designed to support implicitly deduced construction from a string literal\n// template argument. This type will implicitly convert to an `llvm::StringRef`\n// for accessing the string contents, and also provides a dedicated `c_str()`\n// method to access the string as a C string.\n//\n// Example usage:\n// ```cpp\n// template <TemplateString Str> auto F() -> void {\n//   llvm::cout() << Str;\n// }\n//\n// auto Example() -> void {\n//   F<\"string contents here\">();\n// }\n// ```\ntemplate <int N>\nstruct TemplateString {\n  // Constructs the template string from a string literal.\n  //\n  // Intentionally allows implicit conversion from string literals for use as a\n  // non-type template parameter.\n  //\n  // The closest we can get to explicitly accepting a string literal is to\n  // accept an array of `const char`s, so we additionally use Clang's constexpr\n  // `enable_if` attribute to require the array to be usable as a C string with\n  // the expected length. This checks both for null-termination and no embedded\n  // `0` bytes.\n  explicit(false) constexpr TemplateString(const char (&str)[N + 1])\n      __attribute__((\n          enable_if(__builtin_strlen(str) == N,\n                    \"character array is not null-terminated valid C string\"))) {\n    // Rely on Clang's constexpr `__builtin_memcpy` to minimize compile time\n    // overhead copying the string contents around.\n    __builtin_memcpy(storage_, str, N + 1);\n  }\n\n  // This type is designed to act as a `StringLiteral` implicitly while having\n  // the storage necessary to be used as a template parameter.\n  //\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  explicit(false) constexpr operator llvm::StringLiteral() const {\n    return llvm::StringLiteral::withInnerNUL(storage_);\n  }\n\n  // Accesses the string data directly as a compile-time C string.\n  constexpr auto c_str() const -> const char* { return storage_; }\n\n  // Note that this must be public for the type to be structural and available\n  // as a template argument, but this is not part of the public API.\n  char storage_[N + 1];\n};\n\n// Allow deducing `N` when implicitly constructing these so that we can directly\n// use a string literal in a template argument. The array needs an extra char\n// for the null terminator.\ntemplate <int M>\nTemplateString(const char (&str)[M]) -> TemplateString<M - 1>;\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_TEMPLATE_STRING_H_\n"
  },
  {
    "path": "common/template_string_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/template_string.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <type_traits>\n\nnamespace Carbon {\nnamespace {\n\nusing ::testing::StrEq;\n\ntemplate <TemplateString S>\nconstexpr auto TemplateAsStringRef() -> llvm::StringRef {\n  return S;\n}\n\ntemplate <TemplateString S>\nconstexpr auto TemplateAsStringLiteral() -> llvm::StringLiteral {\n  return S;\n}\n\ntemplate <TemplateString S>\nconstexpr auto TemplateAsCStr() -> const char* {\n  return S.c_str();\n}\n\n// An overload that will be active when it is passed a valid `TemplateString`.\n// Returns a true type to allow detection of a valid `TemplateString` argument.\ntemplate <TemplateString /*Unused*/>\nconstexpr auto IsValidTemplateString(int /*unused*/) -> std::true_type {\n  return {};\n}\n\n// A struct that can be used as a template parameter for any template argument.\nstruct AnythingAsTemplateArg {\n  // An implicit constructor that can accept any argument and discards it.\n  template <typename T>\n  // NOLINTNEXTLINE(bugprone-forwarding-reference-overload)\n  explicit(false) constexpr AnythingAsTemplateArg(T&& /*unused*/) {}\n};\n\n// An overload that will be active for any template argument. Returns a false\n// type and is used to detect when a template argument cannot correctly match a\n// `TemplateString`.\ntemplate <AnythingAsTemplateArg /*Unused*/>\nconstexpr auto IsValidTemplateString(...) -> std::false_type {\n  return {};\n}\n\n// Compile time tests with `static_assert`\nstatic_assert(TemplateAsStringRef<\"test\">().size() == 4,\n              \"Not usable in a `constexpr` context.\");\nstatic_assert(TemplateAsStringLiteral<\"test\">().size() == 4,\n              \"Not usable in a `constexpr` context.\");\nstatic_assert(__builtin_strlen(TemplateAsCStr<\"test\">()) == 4,\n              \"Not usable in a `constexpr` context.\");\n\n// The string must not contain embedded nulls.\nstatic_assert(IsValidTemplateString<\"test\">(0));\nstatic_assert(!IsValidTemplateString<\"test\\0test\">(0));\n\n// The string must be null-terminated.\nusing FourChars = char[4];\nstatic_assert(IsValidTemplateString<FourChars{'t', 'e', 's', 0}>(0));\nstatic_assert(!IsValidTemplateString<FourChars{'t', 'e', 's', 't'}>(0));\n\nTEST(TemplateStringTest, Test) {\n  EXPECT_THAT(TemplateAsStringRef<\"test\">(), StrEq(\"test\"));\n  EXPECT_THAT(TemplateAsStringLiteral<\"test\">(), StrEq(\"test\"));\n  EXPECT_THAT(TemplateAsCStr<\"test\">(), StrEq(\"test\"));\n\n  constexpr char GoodStr[5] = {'t', 'e', 's', 't', '\\0'};\n  static_assert(IsValidTemplateString<GoodStr>(0));\n  EXPECT_THAT(TemplateAsStringRef<GoodStr>(), StrEq(\"test\"));\n  EXPECT_THAT(TemplateAsStringLiteral<GoodStr>(), StrEq(\"test\"));\n\n  constexpr char BadStr[4] = {'t', 'e', 's', 't'};\n  static_assert(!IsValidTemplateString<BadStr>(0));\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "common/type_enum.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_TYPE_ENUM_H_\n#define CARBON_COMMON_TYPE_ENUM_H_\n\n#include <algorithm>\n\n#include \"common/ostream.h\"\n\nnamespace Carbon {\n\n// An enum whose values are the specified types.\ntemplate <typename... Types>\nclass TypeEnum : public Printable<TypeEnum<Types...>> {\n public:\n  using TypeTuple = std::tuple<Types...>;\n\n  static constexpr size_t NumTypes = sizeof...(Types);\n  static constexpr size_t NumValues = NumTypes + 2;\n\n  static_assert(NumValues <= 256, \"Too many types for raw enum.\");\n\n  // The underlying raw enumeration type.\n  //\n  // The enum_extensibility attribute indicates that this enum is intended to\n  // take values that do not correspond to its declared enumerators.\n  enum class [[clang::enum_extensibility(open)]] RawEnumType : uint8_t {\n    // The first sizeof...(Types) values correspond to the types.\n\n    // An explicitly invalid value.\n    Invalid = NumTypes,\n\n    // Indicates that no type should be used.\n    // TODO: This doesn't really fit the model of this type, but it's convenient\n    // for all of its users.\n    None,\n  };\n\n  // Accesses the type given an enum value.\n  template <RawEnumType K>\n    requires(K != RawEnumType::Invalid)\n  using TypeFor = __type_pack_element<static_cast<size_t>(K), Types...>;\n\n  // Workaround for Clang bug https://github.com/llvm/llvm-project/issues/85461\n  template <RawEnumType Value>\n  static constexpr auto FromRaw = TypeEnum(Value);\n\n  // Names for the `Invalid` and `None` enumeration values.\n  static constexpr const TypeEnum& Invalid = FromRaw<RawEnumType::Invalid>;\n  static constexpr const TypeEnum& None = FromRaw<RawEnumType::None>;\n\n  // Accesses the enumeration value for the type `Type`. If `AllowInvalid` is\n  // set, any unexpected type is mapped to `Invalid`, otherwise an invalid type\n  // results in a compile error.\n  //\n  // The `Self` parameter is an implementation detail to allow `ForImpl` to be\n  // defined after this template, and should not be specified.\n  template <typename Type, bool AllowInvalid = false, typename Self = TypeEnum>\n  static constexpr auto For = Self::template ForImpl<Type, AllowInvalid>();\n\n  // This bool indicates whether the specified type corresponds to a value in\n  // this enum.\n  template <typename Type>\n  static constexpr bool Contains = For<Type, true>.is_valid();\n\n  // Explicitly convert from the raw enum type.\n  explicit constexpr TypeEnum(RawEnumType value) : value_(value) {}\n\n  // Implicitly convert to the raw enum type, for use in `switch`.\n  //\n  // NOLINTNEXTLINE(google-explicit-constructor)\n  explicit(false) constexpr operator RawEnumType() const { return value_; }\n\n  // Conversion to bool is deleted to prevent direct use in an `if` condition\n  // instead of comparing with another value.\n  explicit operator bool() const = delete;\n\n  // Returns the raw enum value.\n  constexpr auto ToRaw() const -> RawEnumType { return value_; }\n\n  // Returns a value that can be used as an array index. Returned value will be\n  // < NumValues.\n  constexpr auto ToIndex() const -> size_t {\n    return static_cast<size_t>(value_);\n  }\n\n  // Returns whether this is a valid value, not `Invalid`.\n  constexpr auto is_valid() const -> bool {\n    return value_ != RawEnumType::Invalid;\n  }\n\n  auto Print(llvm::raw_ostream& out) const -> void {\n    out << \"TypeEnum(\";\n    if (value_ == RawEnumType::None) {\n      out << \"None\";\n    } else {\n      static constexpr std::array<llvm::StringLiteral, sizeof...(Types)> Names =\n          {\n              Types::Label...,\n          };\n      out << Names[static_cast<int>(value_)];\n    }\n    out << \")\";\n  }\n\n private:\n  // Translates a type to its enum value, or `Invalid`.\n  template <typename IdT, bool AllowInvalid>\n  static constexpr auto ForImpl() -> TypeEnum {\n    // A bool for each type saying whether it matches. The result is the index\n    // of the first `true` in this list. If none matches, then the result is the\n    // length of the list, which is mapped to `Invalid`.\n    constexpr bool TypeMatches[] = {std::same_as<IdT, Types>...};\n    constexpr int Index =\n        std::find(TypeMatches, TypeMatches + NumTypes, true) - TypeMatches;\n    static_assert(Index != NumTypes || AllowInvalid,\n                  \"Unexpected type passed to TypeEnum::For<...>\");\n    return TypeEnum(static_cast<RawEnumType>(Index));\n  }\n\n  RawEnumType value_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_TYPE_ENUM_H_\n"
  },
  {
    "path": "common/version.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_VERSION_H_\n#define CARBON_COMMON_VERSION_H_\n\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon {\n\nstruct Version {\n  static const int Major;\n  static const int Minor;\n  static const int Patch;\n\n  static const llvm::StringLiteral String;\n\n  // A dedicated version information string to use in the toolchain as its\n  // command line rendered version. Composed centrally so it can be composed at\n  // compile time with potentially build info stamped components.\n  static const llvm::StringLiteral ToolchainInfo;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_COMMON_VERSION_H_\n"
  },
  {
    "path": "common/version.tmpl.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/version.h\"\n\n#include <string_view>\n\nnamespace Carbon {\n\n// A simplistic string-to-integer routine that is consteval for compile-time\n// extracting specific components of the version from the string form. We use\n// `std::string_view` for its broader `constexpr` API.\nstatic consteval auto ToInt(std::string_view str) -> int {\n  int result = 0;\n  while (true) {\n    result += str.front() - '0';\n    str.remove_prefix(1);\n    if (str.empty()) {\n      break;\n    }\n    result *= 10;\n  }\n  return result;\n}\n\nstatic consteval auto MajorVersion(std::string_view str) -> int {\n  return ToInt(str.substr(0, str.find('.')));\n}\n\nstatic consteval auto MinorVersion(std::string_view str) -> int {\n  str.remove_prefix(str.find('.') + 1);\n  return ToInt(str.substr(0, str.find('.')));\n}\n\nstatic consteval auto PatchVersion(std::string_view str) -> int {\n  str.remove_prefix(str.find('.') + 1);\n  str.remove_prefix(str.find('.') + 1);\n  // Note that searching for `-` may find the end of the string if there is no\n  // pre-release component, but that produces the correct result here.\n  return ToInt(str.substr(0, str.find('-')));\n}\n\n// The major, minor, and patch versions are always provided and stable. They\n// don't depend on build stamping or introduce caching issues. Provide normal\n// strong definitions.\nconstexpr int Version::Major = MajorVersion(\"$VERSION\");\nconstexpr int Version::Minor = MinorVersion(\"$VERSION\");\nconstexpr int Version::Patch = PatchVersion(\"$VERSION\");\n\n}  // namespace Carbon\n"
  },
  {
    "path": "common/version_stamp.tmpl.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/version.h\"\n\nnamespace Carbon {\n\n#pragma clang attribute push\n// If requested, make the contents of this file weak.\n#if $MAKE_WEAK\n#pragma clang attribute(__attribute__((weak)), \\\n                        apply_to = any(function, variable))\n#endif\n\nconstexpr llvm::StringLiteral Version::String =\n    \"$VERSION+$GIT_COMMIT_SHA$GIT_DIRTY_SUFFIX\";\n\nconstexpr llvm::StringLiteral Version::ToolchainInfo = R\"\"\"(\nCarbon Language toolchain version: $VERSION+$GIT_COMMIT_SHA$GIT_DIRTY_SUFFIX\n)\"\"\";\n\n#pragma clang attribute pop\n\n}  // namespace Carbon\n"
  },
  {
    "path": "common/vlog.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_COMMON_VLOG_H_\n#define CARBON_COMMON_VLOG_H_\n\n#include \"common/ostream.h\"\n#include \"common/template_string.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n\nnamespace Carbon::Internal {\n\n// Implements verbose logging.\n//\n// This is designed to minimize the overhead in callers by being a\n// forcibly-outlined routine that takes a minimal number of parameters.\n//\n// Internally uses `llvm::formatv` to render the format string with any value\n// arguments, and streams the result to the provided stream.\ntemplate <TemplateString FormatStr, typename... Ts>\n[[clang::noinline]] auto VLogImpl(llvm::raw_ostream* stream, Ts&&... values)\n    -> void {\n  *stream << llvm::formatv(FormatStr.c_str(), std::forward<Ts>(values)...);\n}\n\n}  // namespace Carbon::Internal\n\n// Logs when verbose logging is enabled. CARBON_VLOG_TO uses a provided stream;\n// CARBON_VLOG requires a member named `vlog_stream_`.\n//\n// For example:\n//   CARBON_VLOG_TO(vlog_stream, \"Verbose message: {0}\", \"extra information\");\n//   CARBON_VLOG(\"Verbose message: {0}\", \"extra information\");\n//\n// The first argument must be a string literal format string valid for passing\n// to `llvm::formatv`. If it contains any substitutions, those should be passed\n// as subsequent arguments.\n//\n// Also supports a legacy syntax where no arguments are passed and the desired\n// logging is streamed into the call:\n//   CARBON_VLOG() << \"Legacy verbose message\";\n//\n// However, the streaming syntax has higher overhead and can inhibit inlining.\n// Code should prefer the format string form, and eventually when all code has\n// migrated the streaming interface will be removed.\n#define CARBON_VLOG_TO(Stream, FormatStr, ...)                         \\\n  __builtin_expect(Stream == nullptr, true)                            \\\n      ? (void)0                                                        \\\n      : Carbon::Internal::VLogImpl<\"\" FormatStr>(Stream __VA_OPT__(, ) \\\n                                                     __VA_ARGS__)\n\n#define CARBON_VLOG(FormatStr, ...) \\\n  CARBON_VLOG_TO(vlog_stream_, FormatStr, __VA_ARGS__)\n\n#endif  // CARBON_COMMON_VLOG_H_\n"
  },
  {
    "path": "common/vlog_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/vlog.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"common/raw_string_ostream.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing ::testing::IsEmpty;\nusing ::testing::StrEq;\n\n// Helper class with a vlog_stream_ member for CARBON_VLOG.\nclass VLogger {\n public:\n  explicit VLogger(bool enable) {\n    if (enable) {\n      vlog_stream_ = &buffer_;\n    }\n  }\n\n  auto VLog() -> void { CARBON_VLOG(\"Test\\n\"); }\n  auto VLogFormatArgs() -> void { CARBON_VLOG(\"Test {0} {1} {2}\\n\", 1, 2, 3); }\n\n  auto TakeStr() -> std::string { return buffer_.TakeStr(); }\n\n private:\n  RawStringOstream buffer_;\n\n  llvm::raw_ostream* vlog_stream_ = nullptr;\n};\n\nTEST(VLogTest, Enabled) {\n  VLogger vlog(/*enable=*/true);\n  vlog.VLog();\n  EXPECT_THAT(vlog.TakeStr(), StrEq(\"Test\\n\"));\n  vlog.VLogFormatArgs();\n  EXPECT_THAT(vlog.TakeStr(), StrEq(\"Test 1 2 3\\n\"));\n}\n\nTEST(VLogTest, Disabled) {\n  VLogger vlog(/*enable=*/false);\n  vlog.VLog();\n  EXPECT_THAT(vlog.TakeStr(), IsEmpty());\n}\n\nTEST(VLogTest, To) {\n  RawStringOstream buffer;\n  CARBON_VLOG_TO(&buffer, \"Test\");\n  EXPECT_THAT(buffer.TakeStr(), \"Test\");\n}\n\nTEST(VLogTest, ToNull) { CARBON_VLOG_TO(nullptr, \"Unused\"); }\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "core/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/manifest:defs.bzl\", \"manifest\")\n\n# Raw prelude files.\n# TODO: This includes all of Core, not just the prelude.\nfilegroup(\n    name = \"prelude_files\",\n    srcs = glob([\"**/*.carbon\"]),\n    visibility = [\"//visibility:public\"],\n)\n\n# A list of prelude inputs.\n# This is consumed by //toolchain/base:install_paths.\nmanifest(\n    name = \"prelude_manifest.txt\",\n    srcs = [\":prelude_files\"],\n    strip_package_dir = True,\n)\n\n# All files for the toolchain install.\nfilegroup(\n    name = \"prelude\",\n    srcs = [\n        \":prelude_files\",\n        \":prelude_manifest.txt\",\n    ],\n    visibility = [\"//visibility:public\"],\n)\n"
  },
  {
    "path": "core/io.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// TODO: This library is not part of the design. Either write a matching\n// proposal or remove this.\n\npackage Core library \"io\";\n\nimport library \"prelude\";\n\n// TODO: Support printing other types.\n// TODO: Consider rewriting using native support once library support exists.\nfn Print(x: i32) = \"print.int\";\nfn PrintChar(x: char) -> i32 = \"print.char\";\n\nfn PrintStr(msg: str) {\n  let size: i64 = msg.Size() as i64;\n  var i: i64 = 0;\n  while (i < size) {\n    PrintChar(msg[i]);\n    ++i;\n  }\n}\n\n// TODO: Return an `Optional(char)` instead of `i32`.\nfn ReadChar() -> i32 = \"read.char\";\n\n// TODO: Change this to a global constant once they are fully supported.\nfn EOF() -> i32 { return -1; }\n"
  },
  {
    "path": "core/prelude/copy.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/copy\";\n\n// Copying an object, which is a conversion from a value representation to an\n// initializing representation.\ninterface Copy {\n  fn Op[self: Self]() -> Self;\n}\n\nprivate fn Bool() -> type = \"bool.make_type\";\nprivate fn CharLiteral() -> type = \"char_literal.make_type\";\nprivate fn FloatLiteral() -> type = \"float_literal.make_type\";\nprivate fn IntLiteral() -> type = \"int_literal.make_type\";\n\nimpl forall [T:! Copy] const T as Copy {\n  fn Op[self: Self]() -> Self { return (self as T).(Copy.Op)() as const T; }\n}\n\nimpl Bool() as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\nimpl CharLiteral() as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\nimpl FloatLiteral() as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\nimpl IntLiteral() as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\nimpl type as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\nimpl forall [T:! type] T* as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\n// TODO: Implement tuple copy as a variadic generic impl.\nimpl () as Copy {\n  fn Op[self: Self]() -> Self = \"no_op\";\n}\n\nimpl forall [T:! Copy] (T,) as Copy {\n  fn Op[self: Self]() -> Self {\n    return (self.0.Op(),);\n  }\n}\n\nimpl forall [T:! Copy, U:! Copy] (T, U) as Copy {\n  fn Op[self: Self]() -> Self {\n    return (self.0.Op(), self.1.Op());\n  }\n}\n\nimpl forall [T:! Copy, U:! Copy, V:! Copy] (T, U, V) as Copy {\n  fn Op[self: Self]() -> Self {\n    return (self.0.Op(), self.1.Op(), self.2.Op());\n  }\n}\n"
  },
  {
    "path": "core/prelude/default.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/default\";\n\nimport library \"prelude/types/bool\";\nimport library \"prelude/types/int_literal\";\n\n// Provides the default value of an object. If implemented for a type `T`, this\n// is used to initialize declarations without an explicit initializer, such as\n// `var x: T;`, and leaves them in a fully-formed state.\ninterface Default { fn Op() -> Self; }\n\n// Indicates that a type permits unformed initialization, which leaves the\n// object in a state where calling the destructor is valid but optional, and no\n// other operations on the object except for reinitialization are permitted.\ninterface UnformedInit {\n  // TODO: This should probably be:\n  //   let StructT:! type;\n  //   fn Op() -> StructT;\n  // and should be able to initialize a subset of the fields. For now we always\n  // leave the object uninitialized when it is in an unformed state.\n  // See https://github.com/carbon-language/carbon-lang/pull/5913\n}\n\n// Implementations for some builtin types. These need to be here to satisfy the\n// orphan rule because these builtin types have no associated library of their\n// own.\nimpl bool as UnformedInit {}\nimpl forall [T:! type] T* as UnformedInit {}\nimpl forall [T:! UnformedInit, N:! IntLiteral()] array(T, N) as UnformedInit {}\n// TODO: Generalize these to apply to tuples and structs containing only\n// `UnformedInit` types.\nimpl () as UnformedInit {}\nimpl {} as UnformedInit {}\n\n// Provides a default, possibly unformed, value of an object. This should not be\n// implemented directly. Instead, implement `Default` to provide a fully-formed\n// state or (eventually) `UnformedInit` to provide an unformed state.\ninterface DefaultOrUnformed {\n  // TODO: This should return `MaybeUnformed(Self)` once that is supported.\n  fn Op() -> Self;\n}\n\nfinal impl forall [T:! Default] T as DefaultOrUnformed {\n  fn Op() -> Self {\n    return T.Op();\n  }\n}\n\nimpl forall [T:! UnformedInit] T as DefaultOrUnformed {\n  fn Op() -> Self = \"make_uninitialized\";\n}\n"
  },
  {
    "path": "core/prelude/destroy.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/destroy\";\n\n// TODO: Add `Destructor`, as in:\n// interface Destructor {\n//   private fn Op[ref self: Self]();\n// }\n\n// Destroys objects. This will invoke `Destructor` impls recursively on members;\n// it does not deallocate memory.\ninterface Destroy {\n  fn Op[ref self: Self]();\n}\n"
  },
  {
    "path": "core/prelude/iterate.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/iterate\";\n\nexport import library \"prelude/copy\";\nexport import library \"prelude/destroy\";\nexport import library \"prelude/types\";\nexport import library \"prelude/operators\";\n\ninterface Iterate {\n  // TODO: Support iterating ranges of non-copyable values.\n  let ElementType:! Copy & Destroy;\n  let CursorType:! type;\n  fn NewCursor[self: Self]() -> CursorType;\n  fn Next[self: Self](cursor: CursorType*) -> Optional(ElementType);\n}\n\nimpl forall [T:! Copy & Destroy, N:! IntLiteral()]\n    array(T, N) as Iterate\n    where .ElementType = T and .CursorType = i32 {\n  fn NewCursor[unused self: Self]() -> i32 { return 0; }\n  fn Next[self: Self](cursor: i32*) -> Optional(T) {\n    if (*cursor < N) {\n      ++*cursor;\n      return Optional(T).Some(self[*cursor - 1]);\n    } else {\n      return Optional(T).None();\n    }\n  }\n}\n"
  },
  {
    "path": "core/prelude/operators/arithmetic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/operators/arithmetic\";\n\nimport library \"prelude/types/int_literal\";\n\n// TODO: Per the design, the associated type `Result` in each of these\n// interfaces should have a default value of `Self`:\n//\n//   default let Result:! type = Self;\n\n// TODO: Per the design, for each *With interface there should also be a\n// non-With named constraint, such as:\n//\n//   constraint Add {\n//     extend require impls AddWith(Self) where .Result = Self;\n//   }\n\n// Addition: `a + b`.\ninterface AddWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Addition with assignment: `a += b`.\ninterface AddAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n// Increment: `++a`.\ninterface Inc {\n  fn Op[ref self: Self]();\n}\n\n// Negation: `-a`.\ninterface Negate {\n  let Result:! type;\n  fn Op[self: Self]() -> Result;\n}\n\n// Subtraction: `a - b`.\ninterface SubWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Subtraction with assignment: `a -= b`.\ninterface SubAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n// Decrement: `--a`.\ninterface Dec {\n  fn Op[ref self: Self]();\n}\n\n// Multiplication: `a * b`.\ninterface MulWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Multiplication with assignment: `a *= b`.\ninterface MulAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n// Division: `a / b`.\ninterface DivWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Division with assignment: `a /= b`.\ninterface DivAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n// Modulo: `a % b`.\ninterface ModWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Modulo with assignment: `a %= b`.\ninterface ModAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n\n// Operations for IntLiteral. These need to be here because IntLiteral has no\n// associated library of its own.\nimpl IntLiteral() as AddWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.sadd\";\n}\n\nimpl IntLiteral() as DivWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.sdiv\";\n}\n\nimpl IntLiteral() as ModWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.smod\";\n}\n\nimpl IntLiteral() as MulWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.smul\";\n}\n\nimpl IntLiteral() as Negate where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.snegate\";\n}\n\nimpl IntLiteral() as SubWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.ssub\";\n}\n"
  },
  {
    "path": "core/prelude/operators/as.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/operators/as\";\n\nimport library \"prelude/copy\";\n\ninterface UnsafeAs(Dest:! type) {\n  fn Convert[self: Self]() -> Dest;\n}\n\ninterface As(Dest:! type) {\n  // TODO: extend UnsafeAs(Dest);\n  fn Convert[self: Self]() -> Dest;\n}\n\ninterface ImplicitAs(Dest:! type) {\n  // TODO: extend As(Dest);\n  fn Convert[self: Self]() -> Dest;\n}\n\n// Workaround: ImplicitAs extends As.\nimpl forall [U:! type, T:! ImplicitAs(U)] T as As(U) {\n  fn Convert[self: Self]() -> U { return self.Convert(); }\n}\n\n// Workaround: As extends UnsafeAs.\nimpl forall [U:! type, T:! As(U)] T as UnsafeAs(U) {\n  fn Convert[self: Self]() -> U { return self.Convert(); }\n}\n\n// Copyable types have an identity conversion that performs a copy.\nimpl forall [T:! Copy] T as ImplicitAs(T) {\n  fn Convert[self: Self]() -> Self { return self.(Copy.Op)(); }\n}\n\n// `const` can be added and removed when converting a value.\nimpl forall [T:! type, U:! ImplicitAs(T)] U as ImplicitAs(const T) {\n  fn Convert[self: U]() -> const T { return self.Convert(); }\n}\n\nimpl forall [T:! type, U:! ImplicitAs(T)] const U as ImplicitAs(T) {\n  fn Convert[self: const U]() -> T { return (self as U).Convert(); }\n}\n\n// Pointer types can be unsafely cast to other pointer types.\n// TODO: Should `unsafe as` be able to remove `const`?\nimpl forall [T:! type, U:! type] T* as UnsafeAs(U*) {\n  fn Convert[self: T*]() -> U* = \"pointer.unsafe_convert\";\n}\n\ninterface IntFitsIn(Dest:! type) {}\n"
  },
  {
    "path": "core/prelude/operators/bitwise.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/operators/bitwise\";\n\nimport library \"prelude/types/int_literal\";\n\n// TODO: Per the design, the associated type `Result` in each of these\n// interfaces should have a default value of `Self`:\n//\n//   default let Result:! type = Self;\n\n// TODO: Per the design, for each *With interface there should also be a\n// non-With named constraint, such as:\n//\n//   constraint BitAnd {\n//     extend require impls BitAndWith(Self) where .Result = Self;\n//   }\n\n// Bit complement: `^a`.\ninterface BitComplement {\n  let Result:! type;\n  fn Op[self: Self]() -> Result;\n}\n\n// Bitwise AND: `a & b`.\ninterface BitAndWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Bitwise AND with assignment: `a &= b`.\ninterface BitAndAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n// Bitwise OR: `a | b`.\ninterface BitOrWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Bitwise OR with assignment: `a |= b`.\ninterface BitOrAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n// Bitwise XOR: `a ^ b`.\ninterface BitXorWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Bitwise XOR with assignment: `a ^= b`.\ninterface BitXorAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n// Left shift: `a << b`.\ninterface LeftShiftWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Left shift with assignment: `a <<= b`.\ninterface LeftShiftAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n// Right shift: `a >> b`.\ninterface RightShiftWith(Other:! type) {\n  let Result:! type;\n  fn Op[self: Self](other: Other) -> Result;\n}\n\n// Right shift with assignment: `a >>= b`.\ninterface RightShiftAssignWith(Other:! type) {\n  fn Op[ref self: Self](other: Other);\n}\n\n\n// Operations for IntLiteral. These need to be here because IntLiteral has no\n// associated library of its own.\nimpl IntLiteral() as BitAndWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.and\";\n}\n\nimpl IntLiteral() as BitComplement where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.complement\";\n}\n\nimpl IntLiteral() as BitOrWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.or\";\n}\n\nimpl IntLiteral() as BitXorWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.xor\";\n}\n\nimpl IntLiteral() as LeftShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.left_shift\";\n}\n\nimpl IntLiteral() as RightShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.right_shift\";\n}\n\n// Operations for `type`. These need to be here because `type` has no\n// associated library of its own.\n\n// Facet type combination.\nimpl type as BitAndWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"type.and\";\n}\n"
  },
  {
    "path": "core/prelude/operators/comparison.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/operators/comparison\";\n\nexport import library \"prelude/types/bool\";\nimport library \"prelude/types/int_literal\";\n\n// TODO: Per the design, for each *With interface there should also be a\n// non-With named constraint, such as:\n//\n//   constraint Eq {\n//     extend require impls EqWith(Self);\n//   }\n\n// Equality comparison: `a == b` and `a != b`.\ninterface EqWith(Other:! type) {\n  fn Equal[self: Self](other: Other) -> bool;\n  fn NotEqual[self: Self](other: Other) -> bool;\n}\n\n// Relational comparison: `a < b`, `a <= b`, `a > b`, `a >= b`.\ninterface OrderedWith(Other:! type) {\n  // TODO: fn Compare\n  fn Less[self: Self](other: Other) -> bool;\n  fn LessOrEquivalent[self: Self](other: Other) -> bool;\n  fn Greater[self: Self](other: Other) -> bool;\n  fn GreaterOrEquivalent[self: Self](other: Other) -> bool;\n}\n\n// Equality comparison for `bool`.\n// Note that this must be provided in this library as `bool` doesn't have any\n// associated libraries of its own.\nimpl bool as EqWith(Self) {\n  fn Equal[self: Self](other: Self) -> bool = \"bool.eq\";\n  fn NotEqual[self: Self](other: Self) -> bool = \"bool.neq\";\n}\n\n\n// Operations for IntLiteral. These need to be here because IntLiteral has no\n// associated library of its own.\nimpl IntLiteral() as EqWith(Self) {\n  fn Equal[self: Self](other: Self) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: Self) -> bool = \"int.neq\";\n}\n\nimpl IntLiteral() as OrderedWith(Self) {\n  // TODO: fn Compare\n  fn Less[self: Self](other: Self) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: Self) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: Self) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Self) -> bool = \"int.greater_eq\";\n}\n"
  },
  {
    "path": "core/prelude/operators/deref.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/operators/deref\";\n\n// TODO: Align with https://docs.carbon-lang.dev/docs/design/values.html#dereferencing-customization.\ninterface CppUnsafeDeref {\n  let Result:! type;\n  fn Op[self: Self]() -> ref Result;\n}\n"
  },
  {
    "path": "core/prelude/operators/index.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/operators/index\";\n\ninterface IndexWith(SubscriptType:! type) {\n  let ElementType:! type;\n  fn At[self: Self](subscript: SubscriptType) -> ElementType;\n}\n"
  },
  {
    "path": "core/prelude/operators.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/operators\";\n\nexport import library \"prelude/operators/arithmetic\";\nexport import library \"prelude/operators/as\";\nexport import library \"prelude/operators/bitwise\";\nexport import library \"prelude/operators/comparison\";\nexport import library \"prelude/operators/index\";\nexport import library \"prelude/operators/deref\";\n"
  },
  {
    "path": "core/prelude/types/bool.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/bool\";\n\nfn Bool() -> type = \"bool.make_type\";\n"
  },
  {
    "path": "core/prelude/types/char.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/char\";\n\nimport library \"prelude/copy\";\nimport library \"prelude/default\";\nimport library \"prelude/destroy\";\nimport library \"prelude/operators\";\nimport library \"prelude/types/uint\";\nimport library \"prelude/types/int\";\nimport library \"prelude/types/int_literal\";\n\nfn CharLiteral() -> type = \"char_literal.make_type\";\n\nclass Char {\n  adapt u8;\n}\n\nimpl Char as UnformedInit {}\n\nimpl Char as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\nimpl CharLiteral() as ImplicitAs(Char) {\n  fn Convert[self: Self]() -> Char = \"char.convert_checked\";\n}\n\n// TODO: Remove these once ImplicitAs extends As.\nimpl CharLiteral() as As(Char) {\n  fn Convert[self: Self]() -> Char = \"char.convert_checked\";\n}\n\nimpl forall [From:! IntLiteral()] UInt(From) as As(Char) {\n  fn Convert[self: Self]() -> Char = \"int.convert_char\";\n}\n"
  },
  {
    "path": "core/prelude/types/cpp/int.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/cpp/int\";\n\nimport library \"prelude/copy\";\nimport library \"prelude/default\";\nimport library \"prelude/operators\";\nimport library \"prelude/types/int\";\nimport library \"prelude/types/int_literal\";\nimport library \"prelude/types/uint\";\n\nnamespace CppCompat;\n\nclass CppCompat.Long32 {\n  adapt i32;\n}\n\nclass CppCompat.ULong32 {\n  adapt u32;\n}\n\nclass CppCompat.LongLong64 {\n  adapt i64;\n}\n\nclass CppCompat.ULongLong64 {\n  adapt u64;\n}\n\nimpl CppCompat.Long32 as UnformedInit {}\nimpl CppCompat.ULong32 as UnformedInit {}\nimpl CppCompat.LongLong64 as UnformedInit {}\nimpl CppCompat.ULongLong64 as UnformedInit {}\n\n// Copy\n\nimpl CppCompat.Long32 as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\nimpl CppCompat.ULong32 as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\nimpl CppCompat.LongLong64 as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\nimpl CppCompat.ULongLong64 as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\n// Conversions.\n\nimpl IntLiteral() as ImplicitAs(CppCompat.Long32) {\n  fn Convert[self: Self]() -> CppCompat.Long32 = \"int.convert_checked\";\n}\n\n// TODO: Remove this once `ImplicitAs` extends `As`.\nimpl IntLiteral() as As(CppCompat.Long32) {\n  fn Convert[self: Self]() -> CppCompat.Long32 = \"int.convert_checked\";\n}\n\nfinal impl CppCompat.Long32 as ImplicitAs(IntLiteral()) {\n  fn Convert[self: Self]() -> IntLiteral() = \"int.convert_checked\";\n}\n\n// TODO: ImplicitAs from Int(N) to Long32 if N < 32.\nimpl i32 as ImplicitAs(CppCompat.Long32) {\n  fn Convert[self: Self]() -> CppCompat.Long32 = \"int.convert\";\n}\n\n// TODO: Generalize ImplicitAs from Long32 to Int(N) for all N > 32.\n// N == 32 is explicitly skipped, as Long32 is considered to\n// be between i32 and i33 (details:\n// https://github.com/carbon-language/carbon-lang/issues/6275#issuecomment-3488010485).\n// This follows the rule that implicit conversions exist for all iN -> iM if\n// M > N. Otherwise, operations like i32 + Cpp.long result in i32, instead of\n// Cpp.long, which differs from the result for Cpp.long + i32 -> Cpp.long, as\n// the best match for the left operand is being selected.\nfinal impl CppCompat.Long32 as ImplicitAs(i64) {\n  fn Convert[self: Self]() -> i64 = \"int.convert\";\n}\n\nimpl IntLiteral() as ImplicitAs(CppCompat.ULong32) {\n  fn Convert[self: Self]() -> CppCompat.ULong32 = \"int.convert_checked\";\n}\n\n// TODO: Remove this once `ImplicitAs` extends `As`.\nimpl IntLiteral() as As(CppCompat.ULong32) {\n  fn Convert[self: Self]() -> CppCompat.ULong32 = \"int.convert_checked\";\n}\n\nfinal impl CppCompat.ULong32 as ImplicitAs(IntLiteral()) {\n  fn Convert[self: Self]() -> IntLiteral() = \"int.convert_checked\";\n}\n\n// TODO: ImplicitAs from UInt(N) to ULong32 if N < 32.\nimpl u32 as ImplicitAs(CppCompat.ULong32) {\n  fn Convert[self: Self]() -> CppCompat.ULong32 = \"int.convert\";\n}\n\n// TODO: ImplicitAs from ULong32 to UInt(N) if N > 32.\nfinal impl CppCompat.ULong32 as ImplicitAs(u64) {\n  fn Convert[self: Self]() -> u64 = \"int.convert\";\n}\n\nimpl IntLiteral() as ImplicitAs(CppCompat.LongLong64) {\n  fn Convert[self: Self]() -> CppCompat.LongLong64 = \"int.convert_checked\";\n}\n\n// TODO: Remove this once `ImplicitAs` extends `As`.\nimpl IntLiteral() as As(CppCompat.LongLong64) {\n  fn Convert[self: Self]() -> CppCompat.LongLong64 = \"int.convert_checked\";\n}\n\nfinal impl CppCompat.LongLong64 as ImplicitAs(IntLiteral()) {\n  fn Convert[self: Self]() -> IntLiteral() = \"int.convert_checked\";\n}\n\n// TODO: ImplicitAs from Int(N) to LongLong64 if N < 64.\nimpl i64 as ImplicitAs(CppCompat.LongLong64) {\n  fn Convert[self: Self]() -> CppCompat.LongLong64 = \"int.convert\";\n}\n\n// TODO: ImplicitAs from LongLong64 to Int(N) if N > 64.\n// N == 64 is explicitly skipped as LongLong64 is considered to\n// be between i64 and i65 (details:\n// https://github.com/carbon-language/carbon-lang/issues/6275#issuecomment-3488010485).\nfinal impl CppCompat.LongLong64 as ImplicitAs(i128) {\n  fn Convert[self: Self]() -> i128 = \"int.convert\";\n}\n\nimpl IntLiteral() as ImplicitAs(CppCompat.ULongLong64) {\n  fn Convert[self: Self]() -> CppCompat.ULongLong64 = \"int.convert_checked\";\n}\n\n// TODO: Remove this once `ImplicitAs` extends `As`.\nimpl IntLiteral() as As(CppCompat.ULongLong64) {\n  fn Convert[self: Self]() -> CppCompat.ULongLong64 = \"int.convert_checked\";\n}\n\nfinal impl CppCompat.ULongLong64 as ImplicitAs(IntLiteral()) {\n  fn Convert[self: Self]() -> IntLiteral() = \"int.convert_checked\";\n}\n\n// TODO: ImplicitAs from UInt(N) to ULongLong64 if N < 64.\nimpl u64 as ImplicitAs(CppCompat.ULongLong64) {\n  fn Convert[self: Self]() -> CppCompat.ULongLong64 = \"int.convert\";\n}\n\n// TODO: ImplicitAs from ULongLong64 to UInt(N) if N > 64.\nfinal impl CppCompat.ULongLong64 as ImplicitAs(u128) {\n  fn Convert[self: Self]() -> u128 = \"int.convert\";\n}\n\n// TODO: As from Long32 to Int(N) if N < 32.\n// TODO: As from ULong32 to UInt(N) if N < 32.\n// TODO: As from LongLong64 to Int(N) if N < 64.\n// TODO: As from ULongLong64 to UInt(N) if N < 64.\n// TODO: As from Int(N) to Long32 if N > 32.\n// TODO: As from UInt(N) to ULong32 if N > 32.\n// TODO: As from Int(N) to LongLong64 if N > 64.\n// TODO: As from UInt(N) to ULongLong64 if N > 64.\n\n// Comparisons.\n\n// - Homogeneous.\n\n// - CppCompat.T vs CppCompat.T\n\nfinal impl CppCompat.Long32 as EqWith(CppCompat.Long32) {\n  fn Equal[self: Self](other: Self) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: Self) -> bool = \"int.neq\";\n}\n\nfinal impl CppCompat.Long32 as OrderedWith(CppCompat.Long32) {\n  fn Less[self: Self](other: Self) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: Self) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: Self) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Self) -> bool = \"int.greater_eq\";\n}\n\nfinal impl CppCompat.LongLong64 as EqWith(CppCompat.LongLong64) {\n  fn Equal[self: Self](other: Self) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: Self) -> bool = \"int.neq\";\n}\n\nfinal impl CppCompat.LongLong64 as OrderedWith(CppCompat.LongLong64) {\n  fn Less[self: Self](other: Self) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: Self) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: Self) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Self) -> bool = \"int.greater_eq\";\n}\n\n// - Heterogeneous.\n\n// - CppCompat.T on left-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)] CppCompat.Long32 as EqWith(T) {\n  fn Equal[self: Self](other: Self) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: Self) -> bool = \"int.neq\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)] CppCompat.Long32 as OrderedWith(T) {\n  fn Less[self: Self](other: Self) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: Self) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: Self) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Self) -> bool = \"int.greater_eq\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as EqWith(T) {\n  fn Equal[self: Self](other: Self) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: Self) -> bool = \"int.neq\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as OrderedWith(T) {\n  fn Less[self: Self](other: Self) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: Self) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: Self) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Self) -> bool = \"int.greater_eq\";\n}\n\n// - CppCompat.T on right-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)] T as EqWith(CppCompat.Long32) {\n  fn Equal[self: CppCompat.Long32](other: CppCompat.Long32) -> bool = \"int.eq\";\n  fn NotEqual[self: CppCompat.Long32](other: CppCompat.Long32) -> bool = \"int.neq\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)] T as OrderedWith(CppCompat.Long32) {\n  fn Less[self: CppCompat.Long32](other: CppCompat.Long32) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: CppCompat.Long32](other: CppCompat.Long32) -> bool = \"int.less_eq\";\n  fn Greater[self: CppCompat.Long32](other: CppCompat.Long32) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: CppCompat.Long32](other: CppCompat.Long32) -> bool = \"int.greater_eq\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as EqWith(CppCompat.LongLong64) {\n  fn Equal[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> bool = \"int.eq\";\n  fn NotEqual[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> bool = \"int.neq\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as OrderedWith(CppCompat.LongLong64) {\n  fn Less[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> bool = \"int.less_eq\";\n  fn Greater[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> bool = \"int.greater_eq\";\n}\n\n// TODO: Comparisons for ULong32, ULongLong64.\n\n// Arithmetic.\n\n// - Homogeneous.\n\n// - CppCompat.Long32\n\nfinal impl CppCompat.Long32 as Negate where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.snegate\";\n}\n\nfinal impl CppCompat.Long32 as AddWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.sadd\";\n}\n\nfinal impl CppCompat.Long32 as SubWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.ssub\";\n}\n\nfinal impl CppCompat.Long32 as MulWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.smul\";\n}\n\nfinal impl CppCompat.Long32 as DivWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.sdiv\";\n}\n\nfinal impl CppCompat.Long32 as ModWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.smod\";\n}\n\n// - CppCompat.LongLong64\n\nfinal impl CppCompat.LongLong64 as Negate where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.snegate\";\n}\n\nfinal impl CppCompat.LongLong64 as AddWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.sadd\";\n}\n\nfinal impl CppCompat.LongLong64 as SubWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.ssub\";\n}\n\nfinal impl CppCompat.LongLong64 as MulWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.smul\";\n}\n\nfinal impl CppCompat.LongLong64 as DivWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.sdiv\";\n}\n\nfinal impl CppCompat.LongLong64 as ModWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.smod\";\n}\n\n// - Heterogeneous.\n\n// - CppCompat.Long32 on left-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as AddWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.sadd\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as SubWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.ssub\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as MulWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.smul\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as DivWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.sdiv\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as ModWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.smod\";\n}\n\n// - CppCompat.LongLong64 on left-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as AddWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.sadd\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as SubWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.ssub\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as MulWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.smul\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as DivWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.sdiv\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as ModWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.smod\";\n}\n\n// - CppCompat.Long32 on right-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as AddWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.sadd\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as SubWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.ssub\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as MulWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.smul\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as DivWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.sdiv\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as ModWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](other: CppCompat.Long32) -> CppCompat.Long32 = \"int.smod\";\n}\n\n// - CppCompat.LongLong64 on right-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as AddWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.sadd\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as SubWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.ssub\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as MulWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.smul\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as DivWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.sdiv\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as ModWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.smod\";\n}\n\n// TODO: ULong32, ULongLong64: arithmetic operators.\n\n// Bitwise operators.\n\n// - Homogeneous.\n\n// - CppCompat.Long32\n\nfinal impl CppCompat.Long32 as BitComplement where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.complement\";\n}\n\nfinal impl CppCompat.Long32 as BitAndWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.and\";\n}\n\nfinal impl CppCompat.Long32 as BitOrWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.or\";\n}\n\nfinal impl CppCompat.Long32 as BitXorWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.xor\";\n}\n\nfinal impl CppCompat.Long32 as LeftShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.left_shift\";\n}\n\nfinal impl CppCompat.Long32 as RightShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.right_shift\";\n}\n\n// - CppCompat.LongLong64\n\nfinal impl CppCompat.LongLong64 as BitComplement where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.complement\";\n}\n\nfinal impl CppCompat.LongLong64 as BitAndWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.and\";\n}\n\nfinal impl CppCompat.LongLong64 as BitOrWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.or\";\n}\n\nfinal impl CppCompat.LongLong64 as BitXorWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.xor\";\n}\n\nfinal impl CppCompat.LongLong64 as LeftShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.left_shift\";\n}\n\nfinal impl CppCompat.LongLong64 as RightShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.right_shift\";\n}\n\n// - Heterogeneous.\n\n// - CppCompat.Long32 on left-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as BitAndWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other:CppCompat.Long32) -> CppCompat.Long32 = \"int.and\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as BitOrWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other: CppCompat.Long32) -> CppCompat.Long32 = \"int.or\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as BitXorWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other: CppCompat.Long32) -> CppCompat.Long32 = \"int.xor\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as LeftShiftWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other: CppCompat.Long32) -> CppCompat.Long32 = \"int.left_shift\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    CppCompat.Long32 as RightShiftWith(T) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other: CppCompat.Long32) -> CppCompat.Long32 = \"int.right_shift\";\n}\n\n// - CppCompat.LongLong64 on left-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as BitAndWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other:CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.and\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as BitOrWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.or\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as BitXorWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.xor\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as LeftShiftWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.left_shift\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    CppCompat.LongLong64 as RightShiftWith(T) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.right_shift\";\n}\n\n// - CppCompat.Long32 on right-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as BitAndWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other: CppCompat.Long32) -> CppCompat.Long32 = \"int.and\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as BitOrWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other: CppCompat.Long32) -> CppCompat.Long32 = \"int.or\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as BitXorWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other: CppCompat.Long32) -> CppCompat.Long32 = \"int.xor\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as LeftShiftWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other: CppCompat.Long32) -> CppCompat.Long32 = \"int.left_shift\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.Long32)]\n    T as RightShiftWith(CppCompat.Long32) where .Result = CppCompat.Long32 {\n  fn Op[self: CppCompat.Long32](\n    other: CppCompat.Long32) -> CppCompat.Long32 = \"int.right_shift\";\n}\n\n// - CppCompat.LongLong64 on right-hand side.\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as BitAndWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.and\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as BitOrWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.or\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as BitXorWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.xor\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as LeftShiftWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.left_shift\";\n}\n\nimpl forall [T:! ImplicitAs(CppCompat.LongLong64)]\n    T as RightShiftWith(CppCompat.LongLong64) where .Result = CppCompat.LongLong64 {\n  fn Op[self: CppCompat.LongLong64](\n    other: CppCompat.LongLong64) -> CppCompat.LongLong64 = \"int.right_shift\";\n}\n\n// TODO: ULong32, ULongLong64: bitwise operators.\n\n// Compound assignments.\n\n// Compound arithmetic assignments.\n\n// - CppCompat.Long32\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as AddAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.sadd_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as SubAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.ssub_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as MulAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.smul_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as DivAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.sdiv_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as ModAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.smod_assign\";\n}\n\n// - CppCompat.LongLong64\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as AddAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.sadd_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as SubAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.ssub_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as MulAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.smul_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as DivAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.sdiv_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as ModAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.smod_assign\";\n}\n\n// Compound bitwise assignments.\n\n// - CppCompat.Long32\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as BitAndAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.and_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as BitOrAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.or_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as BitXorAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.xor_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as LeftShiftAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.left_shift_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.Long32)]\n\t  CppCompat.Long32 as RightShiftAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.right_shift_assign\";\n}\n\n// - CppCompat.LongLong64\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as BitAndAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.and_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as BitOrAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.or_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as BitXorAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.xor_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as LeftShiftAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.left_shift_assign\";\n}\n\nimpl forall [U:! ImplicitAs(CppCompat.LongLong64)]\n\t  CppCompat.LongLong64 as RightShiftAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.right_shift_assign\";\n}\n\n// TODO: ULong32, ULongLong64: compound assignments.\n\n// Increment and decrement.\n\n// - CppCompat.Long32\n\nimpl CppCompat.Long32 as Dec {\n  fn Op[ref self: Self]() {\n    self -= (1 as CppCompat.Long32);\n  }\n}\n\nimpl CppCompat.Long32 as Inc {\n  fn Op[ref self: Self]() {\n    self += (1 as CppCompat.Long32);\n  }\n}\n\n// - CppCompat.LongLong64\n\nimpl CppCompat.LongLong64 as Dec {\n  fn Op[ref self: Self]() {\n    self -= (1 as CppCompat.LongLong64);\n  }\n}\n\nimpl CppCompat.LongLong64 as Inc {\n  fn Op[ref self: Self]() {\n    self += (1 as CppCompat.LongLong64);\n  }\n}\n\n// TODO: Increment/decrement operations for ULong32, ULongLong64.\n"
  },
  {
    "path": "core/prelude/types/cpp/nullptr.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/cpp/nullptr\";\n\nimport library \"prelude/copy\";\nimport library \"prelude/default\";\nimport library \"prelude/destroy\";\nimport library \"prelude/operators/as\";\nimport library \"prelude/types/cpp/void\";\nimport library \"prelude/types/maybe_unformed\";\nimport library \"prelude/types/optional\";\n\nnamespace CppCompat;\n\n// C++ `std::nullptr_t` as a Carbon type.\n//\n// The C++ type `decltype(nullptr)`, also known by the library-provided alias\n// `std::nullptr_t`, is a fundamental type, not a class type, so it needs a\n// custom mapping as part of C++ interoperability.  We map it to this class\n// type. After a suitable import, this class can be named as\n// `Cpp.std.nullptr_t`. This is also the type of the constant `Cpp.nullptr`.\n//\n// This type supports implicit conversion to any optional pointer type, and\n// produces the `None` value of that type.\nclass CppCompat.NullptrT {\n  // nullptr_t has the same size and alignment as a pointer, but the\n  // corresponding pointer is always unformed.\n  // TODO: Give this type a custom empty value representation.\n  adapt MaybeUnformed(VoidBase*);\n\n  // TODO: This should be just\n  //   fn Make() -> Self = \"make_uninitialized\";\n  // but we don't yet delay processing builtin function definitions until the\n  // end of the enclosing class.\n  fn Make() -> Self {\n    fn MakeImpl() -> Self = \"make_uninitialized\";\n    return MakeImpl();\n  }\n\n  impl as Copy {\n    fn Op[unused self: Self]() -> Self {\n      return Make();\n    }\n  }\n\n  // TODO: impl as EqWith(Self)\n\n  impl forall [T:! type] as ImplicitAs(Optional(T*)) {\n    fn Convert[unused self: Self]() -> Optional(T*) {\n      return Optional(T*).None();\n    }\n  }\n}\n\nimpl CppCompat.NullptrT as UnformedInit {}\n"
  },
  {
    "path": "core/prelude/types/cpp/void.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/cpp/void\";\n\nimport library \"prelude/operators/as\";\n\nnamespace CppCompat;\n\n// C++ `void` as a Carbon type.\n//\n// This type represents a notional \"base-most\" object at the root of every\n// inheritance hierarchy. There are no objects of type `VoidType`, but any value\n// can be converted to a value of type `VoidType`.\n//\n// This type is used as the default mapping for C++ `void`, which is used in\n// most contexts in which `void` can appear: for example, as a pointee of a\n// pointer type, as the type of a typedef, or as a type template argument.\n// However, in a function signature, a `void` return type maps to `()` instead,\n// and a `(void)` parameter list maps to `()`.\n//\n// This type is also available via the alias `Cpp.void`.\nabstract class CppCompat.VoidBase {\n  adapt ();\n}\n\n// TODO: Support a conversion from a value of any type to a value of type\n// `Cpp.void` once we allow defining a conversion to a value category rather\n// than to an initializing category.\n\n// TODO: Do not allow a pointer to `const T` to convert to `Cpp.void*`.\n// #6357 allows it, and we don't have a good way to express \"non-const\" as a\n// constraint on this impl, but this conversion is not const-correct.\nimpl forall [T:! type] T* as ImplicitAs(CppCompat.VoidBase*) {\n  fn Convert[self: T*]() -> CppCompat.VoidBase* = \"pointer.unsafe_convert\";\n}\n\nimpl forall [T:! type] T* as ImplicitAs(const CppCompat.VoidBase*) {\n  fn Convert[self: T*]() -> CppCompat.VoidBase* = \"pointer.unsafe_convert\";\n}\n"
  },
  {
    "path": "core/prelude/types/float.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/float\";\n\nimport library \"prelude/copy\";\nimport library \"prelude/default\";\nimport library \"prelude/destroy\";\nimport library \"prelude/operators\";\nimport library \"prelude/types/float_literal\";\nimport library \"prelude/types/int_literal\";\n\nprivate fn MakeFloat(size: IntLiteral()) -> type = \"float.make_type\";\n\nclass Float(N:! IntLiteral()) {\n  adapt MakeFloat(N);\n}\n\nimpl forall [N:! IntLiteral()] Float(N) as UnformedInit {}\n\n// Copy.\n\nimpl forall [N:! IntLiteral()] Float(N) as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\n// Conversions.\n// TODO: Support mixed-size conversions.\n// TODO: Support int-to-float conversions.\nimpl forall [N:! IntLiteral()] FloatLiteral() as ImplicitAs(Float(N)) {\n  fn Convert[self: Self]() -> Float(N) = \"float.convert_checked\";\n}\n\n// TODO: Remove this once ImplicitAs extends As.\nimpl forall [N:! IntLiteral()] FloatLiteral() as As(Float(N)) {\n  fn Convert[self: Self]() -> Float(N) = \"float.convert_checked\";\n}\n\n// Comparisons.\n// TODO: Support mixed-type comparisons.\nfinal impl forall [N:! IntLiteral()] Float(N) as EqWith(Float(N)) {\n  fn Equal[self: Self](other: Float(N)) -> bool = \"float.eq\";\n  fn NotEqual[self: Self](other: Float(N)) -> bool = \"float.neq\";\n}\n\nfinal impl forall [N:! IntLiteral()] Float(N) as OrderedWith(Float(N)) {\n  fn Less[self: Self](other: Float(N)) -> bool = \"float.less\";\n  fn LessOrEquivalent[self: Self](other: Float(N)) -> bool = \"float.less_eq\";\n  fn Greater[self: Self](other: Float(N)) -> bool = \"float.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Float(N)) -> bool = \"float.greater_eq\";\n}\n\n// Arithmetic.\nfinal impl forall [N:! IntLiteral()]\n    Float(N) as AddWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"float.add\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Float(N) as DivWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"float.div\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Float(N) as MulWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"float.mul\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Float(N) as Negate where .Result = Self {\n  fn Op[self: Self]() -> Self = \"float.negate\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Float(N) as SubWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"float.sub\";\n}\n\n// Compound assignments.\nfinal impl forall [N:! IntLiteral()]\n    Float(N) as AddAssignWith(Self) {\n  fn Op[ref self: Self](other: Self) = \"float.add_assign\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Float(N) as DivAssignWith(Self) {\n  fn Op[ref self: Self](other: Self) = \"float.div_assign\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Float(N) as MulAssignWith(Self) {\n  fn Op[ref self: Self](other: Self) = \"float.mul_assign\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Float(N) as SubAssignWith(Self) {\n  fn Op[ref self: Self](other: Self) = \"float.sub_assign\";\n}\n"
  },
  {
    "path": "core/prelude/types/float_literal.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/float_literal\";\n\nfn FloatLiteral() -> type = \"float_literal.make_type\";\n"
  },
  {
    "path": "core/prelude/types/form.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/form\";\n\n// TODO: this should be a concrete constant, not a function.\nfn Form() -> type = \"form.make_type\";\n"
  },
  {
    "path": "core/prelude/types/int.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/int\";\n\nimport library \"prelude/copy\";\nimport library \"prelude/default\";\nimport library \"prelude/destroy\";\nimport library \"prelude/operators\";\nimport library \"prelude/types/int_literal\";\n\nprivate fn MakeInt(size: IntLiteral()) -> type = \"int.make_type_signed\";\n\nclass Int(N:! IntLiteral()) {\n  adapt MakeInt(N);\n}\n\nimpl forall [N:! IntLiteral()] Int(N) as UnformedInit {}\n\n// Copy.\n\nimpl forall [N:! IntLiteral()] Int(N) as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\n// Conversions.\n\nimpl forall [To:! IntLiteral()] IntLiteral() as ImplicitAs(Int(To)) {\n  fn Convert[self: Self]() -> Int(To) = \"int.convert_checked\";\n}\n\nfinal impl forall [From:! IntLiteral()] Int(From) as ImplicitAs(IntLiteral()) {\n  fn Convert[self: Self]() -> IntLiteral() = \"int.convert_checked\";\n}\n\n// TODO: Remove these once ImplicitAs extends As. For now we need them because\n// the forwarding impl of As in terms of ImplicitAs is not usable at compile\n// time.\nimpl forall [To:! IntLiteral()] IntLiteral() as As(Int(To)) {\n  fn Convert[self: Self]() -> Int(To) = \"int.convert_checked\";\n}\n\nfinal impl forall [From:! IntLiteral()] Int(From) as As(IntLiteral()) {\n  fn Convert[self: Self]() -> IntLiteral() = \"int.convert_checked\";\n}\n\n// Work around the inability to put a `where` clause on a generic parameter of\n// type `IntLiteral`.\n// TODO: Remove this once possible.\nprivate interface AnyInt {\n  let Width:! IntLiteral();\n  fn AsInt[self: Self]() -> Int(Width);\n}\n\nimpl forall [N:! IntLiteral()] Int(N) as AnyInt where .Width = N {\n  fn AsInt[self: Self]() -> Self { return self; }\n}\n\nimpl forall [To:! IntLiteral(), From:! AnyInt & IntFitsIn(Int(To))]\n    From as ImplicitAs(Int(To)) {\n  fn Convert[self: Self]() -> Int(To) {\n    fn Impl(src: Int(From.Width)) -> Int(To) = \"int.convert\";\n    return Impl(self.AsInt());\n  }\n}\n\nfinal impl forall [From:! IntLiteral(), To:! IntLiteral()] Int(From) as As(Int(To)) {\n  fn Convert[self: Self]() -> Int(To) = \"int.convert\";\n}\n\n// Comparisons.\n\n// - Int(N) vs Int(M).\n\nfinal impl forall [N:! IntLiteral(), M:! IntLiteral()] Int(N) as EqWith(Int(M)) {\n  fn Equal[self: Self](other: Int(M)) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: Int(M)) -> bool = \"int.neq\";\n}\n\nfinal impl forall [N:! IntLiteral(), M:! IntLiteral()] Int(N) as OrderedWith(Int(M)) {\n  // TODO: fn Compare\n  fn Less[self: Self](other: Int(M)) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: Int(M)) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: Int(M)) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Int(M)) -> bool = \"int.greater_eq\";\n}\n\n// - Int(N) on left-hand side.\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))] Int(N) as EqWith(T) {\n  fn Equal[self: Self](other: Self) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: Self) -> bool = \"int.neq\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))] Int(N) as OrderedWith(T) {\n  // TODO: fn Compare\n  fn Less[self: Self](other: Self) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: Self) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: Self) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Self) -> bool = \"int.greater_eq\";\n}\n\n// - Int(N) on right-hand side.\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))] T as EqWith(Int(N)) {\n  fn Equal[self: Int(N)](other: Int(N)) -> bool = \"int.eq\";\n  fn NotEqual[self: Int(N)](other: Int(N)) -> bool = \"int.neq\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))] T as OrderedWith(Int(N)) {\n  // TODO: fn Compare\n  fn Less[self: Int(N)](other: Int(N)) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Int(N)](other: Int(N)) -> bool = \"int.less_eq\";\n  fn Greater[self: Int(N)](other: Int(N)) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Int(N)](other: Int(N)) -> bool = \"int.greater_eq\";\n}\n\n// Arithmetic.\n\n// - Homogeneous.\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as AddWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.sadd\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as DivWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.sdiv\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as ModWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.smod\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as MulWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.smul\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as Negate where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.snegate\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as SubWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.ssub\";\n}\n\n// - Int(N) on left-hand side.\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as AddWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.sadd\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as DivWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.sdiv\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as ModWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.smod\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as MulWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.smul\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as SubWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.ssub\";\n}\n\n// - Int(N) on right-hand side.\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as AddWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.sadd\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as DivWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.sdiv\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as ModWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.smod\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as MulWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.smul\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as SubWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.ssub\";\n}\n\n// Bitwise operators.\n\n// - Homogeneous.\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as BitAndWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.and\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as BitComplement where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.complement\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as BitOrWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.or\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as BitXorWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.xor\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as LeftShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.left_shift\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    Int(N) as RightShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.right_shift\";\n}\n\n// - Int(N) on left-hand side.\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as BitAndWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.and\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as BitOrWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.or\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as BitXorWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.xor\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as LeftShiftWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.left_shift\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as RightShiftWith(U) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.right_shift\";\n}\n\n// - Int(N) on right-hand side.\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as BitAndWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.and\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as BitOrWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.or\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as BitXorWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.xor\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as LeftShiftWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.left_shift\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(Int(N))]\n    T as RightShiftWith(Int(N)) where .Result = Int(N) {\n  fn Op[self: Int(N)](other: Int(N)) -> Int(N) = \"int.right_shift\";\n}\n\n// Compound assignments.\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as AddAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.sadd_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as BitAndAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.and_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as BitOrAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.or_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as BitXorAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.xor_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as DivAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.sdiv_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as LeftShiftAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.left_shift_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as ModAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.smod_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as MulAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.smul_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as RightShiftAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.right_shift_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(Int(N))]\n    Int(N) as SubAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.ssub_assign\";\n}\n\n// Increment and decrement.\n\n// TODO: Add builtins for these to avoid emitting a call.\n\nimpl forall [N:! IntLiteral()] Int(N) as Dec {\n  fn Op[ref self: Self]() {\n    // TODO: `self -= 1;` should work, but fails because the `impl IntLiteral\n    // as ImplicitAs(Int(N))` is not final, which causes us to not attempt the\n    // conversion from `1` to `Int(N)` until runtime, when we've lost the\n    // constant value.\n    fn AsInt(n: IntLiteral()) -> Int(N) = \"int.convert_checked\";\n    self -= AsInt(1);\n  }\n}\n\nimpl forall [N:! IntLiteral()] Int(N) as Inc {\n  fn Op[ref self: Self]() {\n    fn AsInt(n: IntLiteral()) -> Int(N) = \"int.convert_checked\";\n    self += AsInt(1);\n  }\n}\n"
  },
  {
    "path": "core/prelude/types/int_literal.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/int_literal\";\n\nfn IntLiteral() -> type = \"int_literal.make_type\";\n"
  },
  {
    "path": "core/prelude/types/maybe_unformed.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/maybe_unformed\";\n\nimport library \"prelude/default\";\nimport library \"prelude/destroy\";\n\nprivate fn MakeMaybeUnformed(t: type) -> type = \"maybe_unformed.make_type\";\n\n// TODO: This should probably support non-destructible types.\nclass MaybeUnformed(T:! Destroy) {\n  adapt MakeMaybeUnformed(T);\n}\n\nimpl forall [T:! Destroy] MaybeUnformed(T) as UnformedInit {}\n"
  },
  {
    "path": "core/prelude/types/optional.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/optional\";\n\nimport library \"prelude/copy\";\nimport library \"prelude/default\";\nimport library \"prelude/destroy\";\nimport library \"prelude/operators/as\";\nimport library \"prelude/operators/bitwise\";\nimport library \"prelude/types/bool\";\nimport library \"prelude/types/maybe_unformed\";\n\n// TODO: Decide how to expose this in the public API.\nprivate interface OptionalStorage {\n  let Type:! type;\n  fn None() -> Type;\n  fn Some[self: Self]() -> Type;\n  fn Has(value: Type) -> bool;\n  fn Get(value: Type) -> Self;\n}\n\n// TODO: We don't have an approved design for an `Optional` type yet, but it's\n// used by the design for `Iterate`. The API here is a placeholder.\nclass Optional(T:! OptionalStorage) {\n  fn None() -> Self {\n    return T.None() as Self;\n  }\n  fn Some(value: T) -> Self {\n    return value.Some() as Self;\n  }\n  fn HasValue[self: Self]() -> bool {\n    return T.Has(self as T.Type);\n  }\n  fn Get[self: Self]() -> T {\n    return T.Get(self as T.Type);\n  }\n\n  // TODO: Use `private adapt` or `unsafe adapt` once available.\n  adapt T.Type;\n}\n\nimpl forall [T:! OptionalStorage & UnformedInit] Optional(T) as UnformedInit {}\n\n// Support for converting a `T` to an `Optional(U)` if `T` converts to `U`.\n// Once we have match_first, this can be rewritten more simply as:\n//\n// match_first {\n//   impl forall [T:! OptionalStorage]\n//       T as ImplicitAs(Optional(T)) {\n//     fn Convert[self: T]() -> Optional(T) {\n//       return Optional(T).Some(self);\n//     }\n//   }\n//\n//   impl forall [T:! Destroy & OptionalStorage, U:! ImplicitAs(T)]\n//       U as ImplicitAs(Optional(T)) {\n//     fn Convert[self: U]() -> Optional(T) {\n//       return Optional(T).Some(self.Convert());\n//     }\n//   }\n// }\n\nprivate interface OptionalAs(T:! OptionalStorage) {\n  fn Convert[self: Self]() -> Optional(T);\n}\n\nfinal impl forall [T:! OptionalStorage]\n    T as OptionalAs(T) {\n  fn Convert[self: Self]() -> Optional(T) {\n    return Optional(T).Some(self);\n  }\n}\n\nimpl forall [T:! Destroy & OptionalStorage, U:! ImplicitAs(T)]\n    U as OptionalAs(T) {\n  fn Convert[self: Self]() -> Optional(T) {\n    return Optional(T).Some(self.Convert());\n  }\n}\n\nimpl forall [T:! Destroy & OptionalStorage,\n             U:! Destroy & OptionalStorage & ImplicitAs(T)]\n    Optional(U) as OptionalAs(T) {\n  fn Convert[self: Self]() -> Optional(T) {\n    if (self.HasValue()) {\n      return Optional(T).Some(self.Get().Convert());\n    }\n    return Optional(T).None();\n  }\n}\n\nimpl forall [T:! OptionalStorage, U:! OptionalAs(T)]\n    U as ImplicitAs(Optional(T)) {\n  fn Convert[self: Self]() -> Optional(T) {\n    return self.Convert();\n  }\n}\n\n// By default, an `Optional(T)` is stored as a pair of a `bool` and a\n// `MaybeUnformed(T)`, with the `MaybeUnformed(T)` left uninitialized if the\n// `bool` is `false`.\n//\n// TODO: Revisit this once we have choice types implemented in the toolchain.\nprivate class DefaultOptionalStorage(T:! Copy & Destroy) {\n  var value: MaybeUnformed(T);\n  var has_value: bool;\n}\n\nprivate fn MakeUninitializedOptionalStorage(T:! Copy & Destroy)\n    -> DefaultOptionalStorage(T) = \"make_uninitialized\";\n\nimpl forall [T:! Copy & Destroy] T as OptionalStorage\n    where .Type = DefaultOptionalStorage(T) {\n  fn None() -> DefaultOptionalStorage(T) {\n    returned var me: DefaultOptionalStorage(T) =\n        MakeUninitializedOptionalStorage(T);\n    me.has_value = false;\n    return var;\n  }\n  fn Some[self: Self]() -> DefaultOptionalStorage(T) {\n    // TODO: This whole function should be just\n    //   return {.value = self, .has_value = true};\n    // but that requires that `T` implements `ImplicitAs(MaybeUnformed(T))`.\n    returned var me: DefaultOptionalStorage(T) =\n        MakeUninitializedOptionalStorage(T);\n    me.value unsafe as T = self;\n    me.has_value = true;\n    return var;\n  }\n  fn Has(value: DefaultOptionalStorage(T)) -> bool {\n    return value.has_value;\n  }\n  fn Get(value: DefaultOptionalStorage(T)) -> T {\n    return value.value unsafe as T;\n  }\n}\n\nprivate fn PointerIsNull[T:! type](value: MaybeUnformed(T*)) -> bool = \"pointer.is_null\";\n\nprivate fn MakeUninitializedOptionalPointer(T:! type)\n    -> MaybeUnformed(T*) = \"make_uninitialized\";\n\n// For pointers, we use a null pointer value as the \"None\" value. This allows\n// `Optional(T*)` to be ABI-compatible with a C++ nullable pointer.\nfinal impl forall [T:! type] T* as OptionalStorage\n    where .Type = MaybeUnformed(T*) {\n  fn None() -> MaybeUnformed(T*) = \"pointer.make_null\";\n  fn Some[self: Self]() -> MaybeUnformed(T*) {\n    returned var result: MaybeUnformed(T*) =\n        MakeUninitializedOptionalPointer(T);\n    result unsafe as T* = self;\n    return var;\n  }\n  fn Has(value: MaybeUnformed(T*)) -> bool {\n    return not PointerIsNull(value);\n  }\n  fn Get(value: MaybeUnformed(T*)) -> T* {\n    return value unsafe as T*;\n  }\n}\n"
  },
  {
    "path": "core/prelude/types/string.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/string\";\n\nimport library \"prelude/copy\";\nimport library \"prelude/default\";\nimport library \"prelude/destroy\";\nimport library \"prelude/types/char\";\nimport library \"prelude/types/uint\";\nimport library \"prelude/operators/index\";\nimport library \"prelude/types/int\";\nimport library \"prelude/operators/as\";\n\nclass String {\n  fn Size[self: Self]() -> u64 { return self.size; }\n\n  impl as Copy {\n    fn Op[self: Self]() -> Self { return {.ptr = self.ptr, .size = self.size}; }\n  }\n  // TODO: This should be an array iterator.\n  private var ptr: Char*;\n  // TODO: This should be a word-sized integer.\n  private var size: u64;\n}\n\nimpl String as UnformedInit {}\n\nimpl forall [T:! ImplicitAs(i64)] String as IndexWith(T) where .ElementType = Char {\n  fn At[self: Self](subscript: T) -> Char = \"string.at\";\n}\n"
  },
  {
    "path": "core/prelude/types/uint.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types/uint\";\n\nimport library \"prelude/copy\";\nimport library \"prelude/default\";\nimport library \"prelude/destroy\";\nimport library \"prelude/operators\";\nimport library \"prelude/types/int\";\nimport library \"prelude/types/int_literal\";\n\nprivate fn MakeUInt(size: IntLiteral()) -> type = \"int.make_type_unsigned\";\n\nclass UInt(N:! IntLiteral()) {\n  adapt MakeUInt(N);\n}\n\nimpl forall [N:! IntLiteral()] UInt(N) as UnformedInit {}\n\n// Copy.\n\nimpl forall [N:! IntLiteral()] UInt(N) as Copy {\n  fn Op[self: Self]() -> Self = \"primitive_copy\";\n}\n\n// Conversions.\n\nimpl forall [To:! IntLiteral()] IntLiteral() as ImplicitAs(UInt(To)) {\n  fn Convert[self: Self]() -> UInt(To) = \"int.convert_checked\";\n}\n\nfinal impl forall [From:! IntLiteral()] UInt(From) as ImplicitAs(IntLiteral()) {\n  fn Convert[self: Self]() -> IntLiteral() = \"int.convert_checked\";\n}\n\n// TODO: Remove these once ImplicitAs extends As. For now we need them because\n// the forwarding impl of As in terms of ImplicitAs is not usable at compile\n// time.\nimpl forall [To:! IntLiteral()] IntLiteral() as As(UInt(To)) {\n  fn Convert[self: Self]() -> UInt(To) = \"int.convert_checked\";\n}\n\nfinal impl forall [From:! IntLiteral()] UInt(From) as As(IntLiteral()) {\n  fn Convert[self: Self]() -> IntLiteral() = \"int.convert_checked\";\n}\n\n// Work around the inability to put a `where` clause on a generic parameter of\n// type `IntLiteral`.\n// TODO: Remove this once possible.\nprivate interface AnyUInt {\n  let Width:! IntLiteral();\n  fn AsUInt[self: Self]() -> UInt(Width);\n}\n\nimpl forall [N:! IntLiteral()] UInt(N) as AnyUInt where .Width = N {\n  fn AsUInt[self: Self]() -> Self { return self; }\n}\n\n// Work around the inability to constrain types other than `.Self` by reversing\n// the Self and argument type of `ImplicitAs`.\n// TODO: Remove this once possible.\nprivate interface FromUInt(From:! type) {\n  fn Convert(from: From) -> Self;\n}\n\nimpl forall [To:! IntLiteral(), From:! AnyUInt & IntFitsIn(UInt(To))]\n    UInt(To) as FromUInt(From) {\n  fn Convert(from: From) -> Self {\n    fn Impl(src: UInt(From.Width)) -> Self = \"int.convert\";\n    return Impl(from.AsUInt());\n  }\n}\n\nimpl forall [To:! IntLiteral(), From:! AnyUInt & IntFitsIn(Int(To))]\n    Int(To) as FromUInt(From) {\n  fn Convert(from: From) -> Self {\n    fn Impl(src: UInt(From.Width)) -> Self = \"int.convert\";\n    return Impl(from.AsUInt());\n  }\n}\n\nimpl forall [From:! IntLiteral(), To:! FromUInt(UInt(From))]\n    UInt(From) as ImplicitAs(To) {\n  fn Convert[self: Self]() -> To {\n    return To.Convert(self);\n  }\n}\n\nfinal impl forall [From:! IntLiteral(), To:! IntLiteral()] UInt(From) as As(UInt(To)) {\n  fn Convert[self: Self]() -> UInt(To) = \"int.convert\";\n}\n\nfinal impl forall [From:! IntLiteral(), To:! IntLiteral()] UInt(From) as As(Int(To)) {\n  fn Convert[self: Self]() -> Int(To) = \"int.convert\";\n}\n\n// Never implicit.\nimpl forall [From:! IntLiteral(), To:! IntLiteral()] Int(From) as As(UInt(To)) {\n  fn Convert[self: Self]() -> UInt(To) = \"int.convert\";\n}\n\n// Comparisons.\n\n// - UInt(N) vs UInt(M).\n\nfinal impl forall [N:! IntLiteral(), M:! IntLiteral()] UInt(N) as EqWith(UInt(M)) {\n  fn Equal[self: Self](other: UInt(M)) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: UInt(M)) -> bool = \"int.neq\";\n}\n\nfinal impl forall [N:! IntLiteral(), M:! IntLiteral()] UInt(N) as OrderedWith(UInt(M)) {\n  // TODO: fn Compare\n  fn Less[self: Self](other: UInt(M)) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: UInt(M)) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: UInt(M)) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: UInt(M)) -> bool = \"int.greater_eq\";\n}\n\n// - UInt(N) vs Int(M).\n\nfinal impl forall [N:! IntLiteral(), M:! IntLiteral()] UInt(N) as EqWith(Int(M)) {\n  fn Equal[self: Self](other: Int(M)) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: Int(M)) -> bool = \"int.neq\";\n}\n\nfinal impl forall [N:! IntLiteral(), M:! IntLiteral()] UInt(N) as OrderedWith(Int(M)) {\n  // TODO: fn Compare\n  fn Less[self: Self](other: Int(M)) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: Int(M)) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: Int(M)) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Int(M)) -> bool = \"int.greater_eq\";\n}\n\n// - Int(N) vs UInt(M).\n\nimpl forall [N:! IntLiteral(), M:! IntLiteral()] Int(N) as EqWith(UInt(M)) {\n  fn Equal[self: Self](other: UInt(M)) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: UInt(M)) -> bool = \"int.neq\";\n}\n\nimpl forall [N:! IntLiteral(), M:! IntLiteral()] Int(N) as OrderedWith(UInt(M)) {\n  // TODO: fn Compare\n  fn Less[self: Self](other: UInt(M)) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: UInt(M)) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: UInt(M)) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: UInt(M)) -> bool = \"int.greater_eq\";\n}\n\n// - UInt(N) on left-hand side.\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))] UInt(N) as EqWith(T) {\n  fn Equal[self: Self](other: Self) -> bool = \"int.eq\";\n  fn NotEqual[self: Self](other: Self) -> bool = \"int.neq\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))] UInt(N) as OrderedWith(T) {\n  // TODO: fn Compare\n  fn Less[self: Self](other: Self) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: Self](other: Self) -> bool = \"int.less_eq\";\n  fn Greater[self: Self](other: Self) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: Self](other: Self) -> bool = \"int.greater_eq\";\n}\n\n// - UInt(N) on right-hand side.\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))] T as EqWith(UInt(N)) {\n  fn Equal[self: UInt(N)](other: UInt(N)) -> bool = \"int.eq\";\n  fn NotEqual[self: UInt(N)](other: UInt(N)) -> bool = \"int.neq\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))] T as OrderedWith(UInt(N)) {\n  // TODO: fn Compare\n  fn Less[self: UInt(N)](other: UInt(N)) -> bool = \"int.less\";\n  fn LessOrEquivalent[self: UInt(N)](other: UInt(N)) -> bool = \"int.less_eq\";\n  fn Greater[self: UInt(N)](other: UInt(N)) -> bool = \"int.greater\";\n  fn GreaterOrEquivalent[self: UInt(N)](other: UInt(N)) -> bool = \"int.greater_eq\";\n}\n\n// Arithmetic.\n\n// - Homogeneous.\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as AddWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.uadd\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as DivWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.udiv\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as ModWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.umod\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as MulWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.umul\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as Negate where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.unegate\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as SubWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.usub\";\n}\n\n// - UInt(N) on left-hand side.\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as AddWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.uadd\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as DivWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.udiv\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as ModWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.umod\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as MulWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.umul\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as SubWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.usub\";\n}\n\n// - UInt(N) on right-hand side.\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as AddWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.uadd\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as DivWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.udiv\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as ModWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.umod\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as MulWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.umul\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as SubWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.usub\";\n}\n\n// Bitwise operators.\n\n// - Homogeneous.\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as BitAndWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.and\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as BitComplement where .Result = Self {\n  fn Op[self: Self]() -> Self = \"int.complement\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as BitOrWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.or\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as BitXorWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.xor\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as LeftShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.left_shift\";\n}\n\nfinal impl forall [N:! IntLiteral()]\n    UInt(N) as RightShiftWith(Self) where .Result = Self {\n  fn Op[self: Self](other: Self) -> Self = \"int.right_shift\";\n}\n\n// - UInt(N) on left-hand side.\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as BitAndWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.and\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as BitOrWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.or\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as BitXorWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.xor\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as LeftShiftWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.left_shift\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as RightShiftWith(U) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.right_shift\";\n}\n\n// - UInt(N) on right-hand side.\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as BitAndWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.and\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as BitOrWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.or\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as BitXorWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.xor\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as LeftShiftWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.left_shift\";\n}\n\nimpl forall [N:! IntLiteral(), T:! ImplicitAs(UInt(N))]\n    T as RightShiftWith(UInt(N)) where .Result = UInt(N) {\n  fn Op[self: UInt(N)](other: UInt(N)) -> UInt(N) = \"int.right_shift\";\n}\n\n// Compound assignments.\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as AddAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.uadd_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as BitAndAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.and_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as BitOrAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.or_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as BitXorAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.xor_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as DivAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.udiv_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as LeftShiftAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.left_shift_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as ModAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.umod_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as MulAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.umul_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as RightShiftAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.right_shift_assign\";\n}\n\nimpl forall [N:! IntLiteral(), U:! ImplicitAs(UInt(N))]\n    UInt(N) as SubAssignWith(U) {\n  fn Op[ref self: Self](other: Self) = \"int.usub_assign\";\n}\n\n// Increment and decrement.\n\n// TODO: Add builtins for these to avoid emitting a call.\n\nimpl forall [N:! IntLiteral()] UInt(N) as Dec {\n  fn Op[ref self: Self]() {\n    // TODO: `self -= 1;` should work, but fails because the `impl IntLiteral\n    // as ImplicitAs(Int(N))` is not final, which causes us to not attempt the\n    // conversion from `1` to `Int(N)` until runtime, when we've lost the\n    // constant value.\n    fn AsUInt(n: IntLiteral()) -> UInt(N) = \"int.convert_checked\";\n    self -= AsUInt(1);\n  }\n}\n\nimpl forall [N:! IntLiteral()] UInt(N) as Inc {\n  fn Op[ref self: Self]() {\n    fn AsUInt(n: IntLiteral()) -> UInt(N) = \"int.convert_checked\";\n    self += AsUInt(1);\n  }\n}\n"
  },
  {
    "path": "core/prelude/types.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\npackage Core library \"prelude/types\";\n\nexport import library \"prelude/types/bool\";\nexport import library \"prelude/types/char\";\nexport import library \"prelude/types/cpp/int\";\nexport import library \"prelude/types/cpp/nullptr\";\nexport import library \"prelude/types/cpp/void\";\nexport import library \"prelude/types/float\";\nexport import library \"prelude/types/float_literal\";\nexport import library \"prelude/types/int\";\nexport import library \"prelude/types/int_literal\";\nexport import library \"prelude/types/maybe_unformed\";\nexport import library \"prelude/types/optional\";\nexport import library \"prelude/types/string\";\nexport import library \"prelude/types/uint\";\n"
  },
  {
    "path": "core/prelude.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage Core library \"prelude\";\n\nexport import library \"prelude/copy\";\nexport import library \"prelude/default\";\nexport import library \"prelude/destroy\";\nexport import library \"prelude/iterate\";\nexport import library \"prelude/operators\";\nexport import library \"prelude/types\";\n"
  },
  {
    "path": "core/range.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// TODO: This library is not part of the design. Either write a matching\n// proposal or remove this.\n\npackage Core library \"range\";\n\nimport library \"prelude/destroy\";\nimport library \"prelude/iterate\";\nimport library \"prelude/operators/arithmetic\";\nimport library \"prelude/operators/as\";\nimport library \"prelude/operators/comparison\";\nimport library \"prelude/types/int\";\nimport library \"prelude/types/int_literal\";\nimport library \"prelude/types/optional\";\n\nclass IntRange(N:! IntLiteral()) {\n  fn Make(start: Int(N), end: Int(N)) -> Self {\n    return {.start = start, .end = end};\n  }\n\n  impl as Iterate where .CursorType = Int(N) and .ElementType = Int(N) {\n    fn NewCursor[self: Self]() -> Int(N) { return self.start; }\n    fn Next[self: Self](cursor: Int(N)*) -> Optional(Int(N)) {\n      var value: Int(N) = *cursor;\n      if (value < self.end) {\n        ++*cursor;\n        return Optional(Int(N)).Some(value);\n      } else {\n        return Optional(Int(N)).None();\n      }\n    }\n  }\n\n  private var start: Int(N);\n  private var end: Int(N);\n}\n\nfn Range(end: i32) -> IntRange(32) {\n  return IntRange(32).Make(0, end);\n}\n\nfn InclusiveRange(start: i32, end: i32) -> IntRange(32) {\n  return IntRange(32).Make(start, end + 1);\n}\n"
  },
  {
    "path": "docs/README.md",
    "content": "# Docs\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis directory contains current, accepted documentation underpinning Carbon.\nThese documents cover all aspects of Carbon ranging from the project down to\ndetailed designs for specific language features.\n\nIf you're trying to learn more about Carbon, we recommend starting at\n[`/README.md`](/README.md).\n\n## Design\n\nCarbon language's design and rationale are documented in the\n[`design/` directory](design/README.md). This documentation is intended to\nsupport the following audiences:\n\n-   People who wish to determine whether Carbon would be the right choice for a\n    project compared to other existing languages.\n-   People working on the evolution of the Carbon language who wish to\n    understand the rationale and motivation for existing design decisions.\n-   People working on a specification or implementation of the Carbon language\n    who need a detailed understanding of the intended design.\n-   People writing Carbon code who wish to understand why the language rules are\n    the way they are.\n\nThis is in contrast to [proposals](/proposals/README.md), which document the\nindividual decisions that led to this design (along with other changes to the\nCarbon project), including the rationale and alternatives considered.\n\n## Project\n\nThe [`project/` directory](project/README.md) contains project-related\ndocumentation for Carbon, including:\n\n-   [goals](project/goals.md), and the\n    [principles](project/principles/README.md) and [roadmap](project/roadmap.md)\n    derived from those goals,\n-   how the project works, and\n-   how to contribute.\n\n## Guides\n\nThe [`guides/` directory](guides/README.md) contains **to-be-written** end-user\ndocumentation for developers writing programs in Carbon.\n\n## Spec\n\nThe [`spec/` directory](spec/) contains the **to-be-written** formal\nspecification of the Carbon language. This is for implementers of compilers or\nother tooling. This is intended to complement the [toolchain](/toolchain/).\n"
  },
  {
    "path": "docs/design/README.md",
    "content": "# Language design\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n> **STATUS:** Up-to-date on 09-Aug-2022, including proposals up through\n> [#1382](https://github.com/carbon-language/carbon-lang/pull/1382).\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Introduction](#introduction)\n    -   [This document is provisional](#this-document-is-provisional)\n    -   [Tour of the basics](#tour-of-the-basics)\n-   [Code and comments](#code-and-comments)\n-   [Build modes](#build-modes)\n-   [Types are values](#types-are-values)\n    -   [Values usable as types](#values-usable-as-types)\n-   [Primitive types](#primitive-types)\n    -   [`bool`](#bool)\n    -   [Integer types](#integer-types)\n        -   [Integer literals](#integer-literals)\n    -   [Floating-point types](#floating-point-types)\n        -   [Floating-point literals](#floating-point-literals)\n    -   [String types](#string-types)\n        -   [String literals](#string-literals)\n-   [Values, objects, and expressions](#values-objects-and-expressions)\n    -   [Expression categories](#expression-categories)\n    -   [Expression phases](#expression-phases)\n-   [Composite types](#composite-types)\n    -   [Tuples](#tuples)\n    -   [Struct types](#struct-types)\n    -   [Pointer types](#pointer-types)\n    -   [Arrays and slices](#arrays-and-slices)\n-   [Expressions](#expressions)\n-   [Declarations, Definitions, and Scopes](#declarations-definitions-and-scopes)\n-   [Patterns](#patterns)\n    -   [Binding patterns](#binding-patterns)\n    -   [Destructuring patterns](#destructuring-patterns)\n    -   [Refutable patterns](#refutable-patterns)\n-   [Name-binding declarations](#name-binding-declarations)\n    -   [Constant `let` declarations](#constant-let-declarations)\n    -   [Variable `var` declarations](#variable-var-declarations)\n    -   [`auto`](#auto)\n    -   [Global constants and variables](#global-constants-and-variables)\n-   [Functions](#functions)\n    -   [Parameters](#parameters)\n    -   [`auto` return type](#auto-return-type)\n    -   [Blocks and statements](#blocks-and-statements)\n    -   [Control flow](#control-flow)\n        -   [`if` and `else`](#if-and-else)\n        -   [Loops](#loops)\n            -   [`while`](#while)\n            -   [`for`](#for)\n            -   [`break`](#break)\n            -   [`continue`](#continue)\n        -   [`return`](#return)\n            -   [`returned var`](#returned-var)\n        -   [`match`](#match)\n-   [User-defined types](#user-defined-types)\n    -   [Classes](#classes)\n        -   [Assignment](#assignment)\n        -   [Class functions and factory functions](#class-functions-and-factory-functions)\n        -   [Methods](#methods)\n        -   [Inheritance](#inheritance)\n        -   [Access control](#access-control)\n        -   [Destructors](#destructors)\n        -   [`const`](#const)\n        -   [Unformed state](#unformed-state)\n        -   [Move](#move)\n        -   [Mixins](#mixins)\n    -   [Choice types](#choice-types)\n-   [Names](#names)\n    -   [Files, libraries, packages](#files-libraries-packages)\n    -   [Package declaration](#package-declaration)\n    -   [Imports](#imports)\n        -   [Same-package imports](#same-package-imports)\n        -   [Cross-package imports](#cross-package-imports)\n    -   [Name visibility](#name-visibility)\n    -   [Package scope](#package-scope)\n    -   [Namespaces](#namespaces)\n    -   [Naming conventions](#naming-conventions)\n    -   [Aliases](#aliases)\n    -   [Name lookup](#name-lookup)\n        -   [Name lookup for common types](#name-lookup-for-common-types)\n-   [Generics](#generics)\n    -   [Checked and template parameters](#checked-and-template-parameters)\n    -   [Interfaces and implementations](#interfaces-and-implementations)\n    -   [Combining constraints](#combining-constraints)\n    -   [Template name lookup](#template-name-lookup)\n    -   [Associated constants](#associated-constants)\n    -   [Generic entities](#generic-entities)\n        -   [Generic Classes](#generic-classes)\n        -   [Generic choice types](#generic-choice-types)\n        -   [Generic interfaces](#generic-interfaces)\n        -   [Generic implementations](#generic-implementations)\n    -   [Other features](#other-features)\n    -   [Generic type equality and `observe` declarations](#generic-type-equality-and-observe-declarations)\n    -   [Operator overloading](#operator-overloading)\n        -   [Common type](#common-type)\n-   [Bidirectional interoperability with C and C++](#bidirectional-interoperability-with-c-and-c)\n    -   [Goals](#goals)\n    -   [Non-goals](#non-goals)\n    -   [Importing and `#include`](#importing-and-include)\n    -   [ABI and dynamic linking](#abi-and-dynamic-linking)\n    -   [Operator overloading](#operator-overloading-1)\n    -   [Templates](#templates)\n    -   [Standard types](#standard-types)\n    -   [Inheritance](#inheritance-1)\n    -   [Enums](#enums)\n-   [Unfinished tales](#unfinished-tales)\n    -   [Safety](#safety)\n    -   [Lifetime and move semantics](#lifetime-and-move-semantics)\n    -   [Metaprogramming](#metaprogramming)\n    -   [Pattern matching as function overload resolution](#pattern-matching-as-function-overload-resolution)\n    -   [Error handling](#error-handling)\n    -   [Execution abstractions](#execution-abstractions)\n        -   [Abstract machine and execution model](#abstract-machine-and-execution-model)\n        -   [Lambdas](#lambdas)\n        -   [Co-routines](#co-routines)\n        -   [Concurrency](#concurrency)\n\n<!-- tocstop -->\n\n## Introduction\n\nThis documentation describes the design of the Carbon language, and the\nrationale for that design. This documentation is an overview of the Carbon\nproject in its current state, written for the builders of Carbon and for those\ninterested in learning more about Carbon.\n\nThis document is _not_ a complete programming manual, and, nor does it provide\ndetailed and comprehensive justification for design decisions. These\ndescriptions are found in linked dedicated designs.\n\n### This document is provisional\n\nThis document includes much that is provisional or placeholder. This means that\nthe syntax used, language rules, standard library, and other aspects of the\ndesign have things that have not been decided through the Carbon process. This\npreliminary material fills in gaps until aspects of the design can be filled in.\nFeatures that are provisional have been marked as such on a best-effort basis.\n\n### Tour of the basics\n\nHere is a simple function showing some Carbon code:\n\n```carbon\nimport Core library \"io\";\nimport Math;\n\n// Returns the smallest factor of `n` > 1, and\n// whether `n` itself is prime.\nfn SmallestFactor(n: i32) -> (i32, bool) {\n  let limit: i32 = Math.Sqrt(n) as i32;\n  var i: i32 = 2;\n  while (i <= limit) {\n    let remainder: i32 = n % i;\n    if (remainder == 0) {\n      Core.Print(\"{0} is a factor of {1}\", i, n);\n      return (i, false);\n    }\n    if (i == 2) {\n      i = 3;\n    } else {\n      // Skip even numbers once we get past `2`.\n      i += 2;\n    }\n  }\n  return (n, true);\n}\n```\n\nCarbon is a language that should feel familiar to C++ and C developers. This\nexample has familiar constructs like [imports](#imports),\n[comments](#code-and-comments), [function definitions](#functions),\n[typed arguments](#binding-patterns), and [expressions](#expressions).\n[Statements](#blocks-and-statements) and\n[declarations](#declarations-definitions-and-scopes) are terminated with a `;`\nor something in curly braces `{`...`}`.\n\nA few other features that are unlike C or C++ may stand out. First,\n[declarations](#declarations-definitions-and-scopes) start with introducer\nkeywords. `fn` introduces a function declaration, and `var` introduces a\n[variable declaration](#variable-var-declarations).\n\nThe example starts with an [`import` declaration](#imports). Carbon imports are\nmore like [C++ modules](https://en.cppreference.com/w/cpp/language/modules) than\n[textual inclusion during preprocessing using `#include`](https://en.cppreference.com/w/cpp/preprocessor/include).\nThe `import` declaration imports a\n[library from a package](#files-libraries-packages). It must appear at the top\nof a Carbon source file, the first thing after the\n[optional `package` declaration](#package-declaration). Libraries can optionally\nbe split into [API and implementation files](#files-libraries-packages), like\nC++'s header and source files but without requiring a source file in any cases.\nThis declaration from the example:\n\n```carbon\nimport Math;\n```\n\nimports the default library from package `Math`. The names from this library are\naccessible as members of `Math`, like `Math.Sqrt`. The `Core.Print` function\ncomes from the `Core` package's `io` library. Unlike C++, the namespaces of\ndifferent packages are kept separate, so there are no name conflicts.\n\nCarbon [comments](#code-and-comments) must be on a line by themselves starting\nwith `//`:\n\n```carbon\n// Returns the smallest factor of `n` > 1, and\n// whether `n` itself is prime.\n...\n      // Skip even numbers once we get past `2`.\n```\n\nA [function definition](#functions) consists of:\n\n-   the `fn` keyword introducer,\n-   the function's name,\n-   a parameter list in round parens `(`...`)`,\n-   an optional `->` and return type, and\n-   a body inside curly braces `{`...`}`.\n\n```carbon\nfn SmallestFactor(n: i32) -> (i32, bool) {\n  ...\n      return (i, false);\n  ...\n  return (n, true);\n}\n```\n\nThe body of the function is an ordered sequence of\n[statements](#blocks-and-statements) and\n[declarations](#declarations-definitions-and-scopes). Function execution ends\nwhen it reaches a `return` statement or the end of the function body. `return`\nstatements can also specify an expression whose value is returned.\n\nHere `i32` refers to a signed [integer type](#integer-types), with 32 bits, and\n`bool` is the [boolean type](#bool). Carbon also has\n[floating-point types](#floating-point-types) like `f32` and `f64`, and\n[string types](#string-types).\n\nA [variable declaration](#variable-var-declarations) has three parts:\n\n-   the `var` keyword introducer,\n-   the name followed by a `:` and a type, declared the same way as a parameter\n    in a function signature, and\n-   an optional initializer.\n\n```carbon\n  var i: i32 = 2;\n```\n\nYou can modify the value of a variable with an\n[assignment statement](assignment.md):\n\n```carbon\n      i = 3;\n      ...\n      ++i;\n      ...\n      i += 2;\n```\n\n[Constants are declared](#constant-let-declarations) with the `let` keyword\nintroducer. The syntax parallels variable declarations except the initializer is\nrequired:\n\n```carbon\n  let limit: i32 = Math.Sqrt(n) as i32;\n  ...\n    let remainder: i32 = n % i;\n```\n\nThe initializer `Math.Sqrt(n) as i32` is an [expression](#expressions). It first\ncalls the `Math.Sqrt` function with `n` as the argument. Then, the `as` operator\ncasts the floating-point return value to `i32`. Lossy conversions like that must\nbe done explicitly.\n\nOther expressions include `n % i`, which applies the binary `%` modulo operator\nwith `n` and `i` as arguments, and `remainder == 0`, which applies the `==`\ncomparison operator producing a `bool` result. Expression return values are\nignored when expressions are used as statements, as in this call to the\n`Core.Print` function:\n\n```carbon\n      Core.Print(\"{0} is a factor of {1}\", i, n);\n```\n\nFunction calls consist of the name of the function followed by the\ncomma-separated argument list in round parentheses `(`...`)`.\n\nControl flow statements, including `if`, `while`, `for`, `break`, and\n`continue`, change the order that statements are executed, as they do in C++:\n\n```carbon\n  while (i <= limit) {\n    ...\n    if (remainder == 0) {\n      ...\n    }\n    if (i == 2) {\n      ...\n    } else {\n      ...\n    }\n  }\n```\n\nEvery code block in curly braces `{`...`}` defines a scope. Names are visible\nfrom their declaration until the end of innermost scope containing it. So\n`remainder` in the example is visible until the curly brace `}` that closes the\n`while`.\n\nThe example function uses a [_tuple_](#tuples), a\n[composite type](#composite-types), to return multiple values. Both tuple values\nand types are written using a comma-separated list inside parentheses. So\n`(i, false)` and `(n, true)` are tuple values, and `(i32, bool)` is their type.\n\n[Struct types](#struct-types) are similar, except their members are referenced\nby name instead of position. The example could be changed to use structs instead\nas follows:\n\n```carbon\n// Return type of `{.factor: i32, .prime: bool}` is a struct\n// with an `i32` field named `.factor`, and a `bool` field\n// named `.prime`.\nfn SmallestFactor(n: i32) -> {.factor: i32, .prime: bool} {\n  ...\n    if (remainder == 0) {\n      // Return a struct value.\n      return {.factor = i, .prime = false};\n    }\n  ...\n  // Return a struct value.\n  return {.factor = n, .prime = true};\n}\n```\n\n## Code and comments\n\nAll source code is UTF-8 encoded text. Comments, identifiers, and strings are\nallowed to have non-ASCII characters.\n\n```carbon\nvar résultat: String = \"Succès\";\n```\n\nComments start with two slashes `//` and go to the end of the line. They are\nrequired to be the only non-whitespace on the line.\n\n```carbon\n// Compute an approximation of π\n```\n\n> References:\n>\n> -   [Source files](code_and_name_organization/source_files.md)\n> -   [Lexical conventions](lexical_conventions)\n> -   Proposal\n>     [#142: Unicode source files](https://github.com/carbon-language/carbon-lang/pull/142)\n> -   Proposal\n>     [#198: Comments](https://github.com/carbon-language/carbon-lang/pull/198)\n\n## Build modes\n\nThe behavior of the Carbon compiler depends on the _build mode_:\n\n-   In a _debug build_, the priority is diagnosing problems and fast build time.\n-   In a _release build_, the priority is fastest execution time and lowest\n    memory usage.\n\n> References: [Safety design](/docs/design/safety#build-modes)\n\n## Types are values\n\nExpressions compute values in Carbon, and these values are always strongly typed\nmuch like in C++. However, an important difference from C++ is that types are\nthemselves modeled as values; specifically, compile-time-constant values of type\n`type`. This has a number of consequences:\n\n-   Names for types are in the same namespace shared with functions, variables,\n    namespaces, and so on.\n-   The grammar for writing a type is the [expression](#expressions) grammar,\n    not a separate grammar for types. As a result, Carbon doesn't use angle\n    brackets `<`...`>` in types, since `<` and `>` are used for comparison in\n    expressions.\n-   Function call syntax is used to specify parameters to a type, like\n    `HashMap(String, i64)`.\n\n> References:\n>\n> -   Proposal\n>     [#2360: Types are values of type `type`](https://github.com/carbon-language/carbon-lang/pull/2360)\n\n### Values usable as types\n\nA value used in a type position, like after a `:` in a variable declaration or\nthe return type after a `->` in a function declaration, must:\n\n-   be [a compile-time constant](#expression-phases), so the compiler can\n    evaluate it at compile time, and\n-   have a defined implicit conversion to type `type`.\n\nThe actual type used is the result of the conversion to type `type`. Of course\nthis includes values that already are of type `type`, but also allows some\nnon-type values to be used in a type position.\n\nFor example, the value `(bool, bool)` represents a [tuple](#tuples) of types,\nbut is not itself a type, since it doesn't have type `type`. It does have a\ndefined implicit conversion to type `type`, which results in the value\n`(bool, bool) as type`. This means `(bool, bool)` may be used in a type\nposition. `(bool, bool) as type` is the type of the value `(true, false)` (among\nothers), so this code is legal:\n\n```carbon\nvar b: (bool, bool) = (true, false);`\n```\n\nThere is some need to be careful here, since the declaration makes it look like\nthe type of `b` is `(bool, bool)`, when in fact it is `(bool, bool) as type`.\n`(bool, bool) as type` and `(bool, bool)` are different values since they have\ndifferent types: the first has type `type`, and the second has type\n`(type, type) as type`.\n\nIn addition to the types of [tuples](#tuples), this also comes up with\n[struct types](#struct-types) and [facets](generics/terminology.md#facet).\n\n## Primitive types\n\nPrimitive types fall into the following categories:\n\n-   the boolean type `bool`,\n-   signed and unsigned integer types,\n-   IEEE-754 floating-point types, and\n-   string types.\n\nThese are made available through the [prelude](#name-lookup-for-common-types).\n\n### `bool`\n\nThe type `bool` is a boolean type with two possible values: `true` and `false`.\nThe names `bool`, `true`, and `false` are keywords.\n[Comparison expressions](#expressions) produce `bool` values. The condition\narguments in [control-flow statements](#control-flow), like [`if`](#if-and-else)\nand [`while`](#while), and\n[`if`-`then`-`else` conditional expressions](#expressions) take `bool` values.\n\n> References:\n>\n> -   Question-for-leads issue\n>     [#750: Naming conventions for Carbon-provided features](https://github.com/carbon-language/carbon-lang/issues/750)\n> -   Proposal\n>     [#861: Naming conventions](https://github.com/carbon-language/carbon-lang/pull/861)\n\n### Integer types\n\nThe signed-integer type with bit width `N` may be written `iN`, as long as `N`\nis a positive multiple of 8. For example, `i32` is a signed 32-bit integer.\nSigned-integer\n[overflow](expressions/arithmetic.md#overflow-and-other-error-conditions) is a\nprogramming error:\n\n-   In a development build, overflow will be caught immediately when it happens\n    at runtime.\n-   In a performance build, the optimizer can assume that such conditions don't\n    occur. As a consequence, if they do, the behavior of the program is not\n    defined.\n-   In a hardened build, overflow does not result in undefined behavior.\n    Instead, either the program will be aborted, or the arithmetic will evaluate\n    to a mathematically incorrect result, such as a two's complement result or\n    zero.\n\nThe unsigned-integer types may be written `uN`, with `N` a positive multiple\nof 8. Unsigned integer types wrap around on overflow; we strongly advise that\nthey are not used except when those semantics are desired. These types are\nintended for bit manipulation or modular arithmetic as often found in\n[hashing](https://en.wikipedia.org/wiki/Hash_function),\n[cryptography](https://en.wikipedia.org/wiki/Cryptography), and\n[PRNG](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) use cases.\nValues which can never be negative, like sizes, but for which wrapping does not\nmake sense\n[should use signed integer types](/proposals/p1083.md#dont-let-unsigned-arithmetic-wrap).\n\nIdentifiers of the form `iN` and `uN` are _type literals_, resulting in the\ncorresponding type.\n\nNot all operations will be supported for all bit sizes. For example, division\nmay be limited to integers of at most 128 bits due to LLVM limitations.\n\n> **Open question:** Bit-field ([1](https://en.wikipedia.org/wiki/Bit_field),\n> [2](https://en.cppreference.com/w/cpp/language/bit_field)) support will need\n> some way to talk about non-multiple-of-eight-bit integers, even though Carbon\n> will likely not support pointers to those types.\n\n> References:\n>\n> -   [Numeric type literal expressions](expressions/literals.md#numeric-type-literals)\n> -   Question-for-leads issue\n>     [#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543)\n> -   Question-for-leads issue\n>     [#750: Naming conventions for Carbon-provided features](https://github.com/carbon-language/carbon-lang/issues/750)\n> -   Proposal\n>     [#861: Naming conventions](https://github.com/carbon-language/carbon-lang/pull/861)\n> -   Proposal\n>     [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083)\n> -   Proposal\n>     [#2015: Numeric type literal syntax](https://github.com/carbon-language/carbon-lang/pull/2015)\n\n#### Integer literals\n\nIntegers may be written in decimal, hexadecimal, octal, or binary:\n\n-   `12345` (decimal)\n-   `0x1FE` (hexadecimal)\n-   `0o755` (octal)\n-   `0b1010` (binary)\n\nUnderscores (`_`) may be used as digit separators. Numeric literals are\ncase-sensitive: `0x`, `0o`, `0b` must be lowercase, whereas hexadecimal digits\nmust be uppercase. Integer literals never contain a `.`.\n\nUnlike in C++, literals do not have a suffix to indicate their type. Instead,\nnumeric literals have a type derived from their value, and can be\n[implicitly converted](expressions/implicit_conversions.md) to any type that can\nrepresent that value.\n\n> References:\n>\n> -   [Integer literal syntax](lexical_conventions/numeric_literals.md#integer-literals)\n> -   [Numeric literal expressions](expressions/literals.md#numeric-literals)\n> -   Proposal\n>     [#143: Numeric literals](https://github.com/carbon-language/carbon-lang/pull/143)\n> -   Proposal\n>     [#144: Numeric literal semantics](https://github.com/carbon-language/carbon-lang/pull/144)\n> -   Proposal\n>     [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820)\n> -   Proposal\n>     [#1983: Weaken digit separator placement rules](https://github.com/carbon-language/carbon-lang/pull/1983)\n\n### Floating-point types\n\nFloating-point types in Carbon have IEEE-754 semantics, use the round-to-nearest\nrounding mode, and do not set any floating-point exception state. They are named\nusing _type literals_, consisting of `f` and the number of bits, which must be a\nmultiple of 8. These types will always be available:\n[`f16`](https://en.wikipedia.org/wiki/Half-precision_floating-point_format),\n[`f32`](https://en.wikipedia.org/wiki/Single-precision_floating-point_format),\nand\n[`f64`](https://en.wikipedia.org/wiki/Double-precision_floating-point_format).\nOther sizes may be available, depending on the platform, such as\n[`f80`](https://en.wikipedia.org/wiki/Extended_precision),\n[`f128`](https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format),\nor\n[`f256`](https://en.wikipedia.org/wiki/Octuple-precision_floating-point_format).\n\nCarbon also supports the\n[`BFloat16`](https://en.wikipedia.org/wiki/Bfloat16_floating-point_format)\nformat, a 16-bit truncation of a \"binary32\" IEEE-754 format floating point\nnumber.\n\n> References:\n>\n> -   [Numeric type literal expressions](expressions/literals.md#numeric-type-literals)\n> -   Question-for-leads issue\n>     [#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543)\n> -   Question-for-leads issue\n>     [#750: Naming conventions for Carbon-provided features](https://github.com/carbon-language/carbon-lang/issues/750)\n> -   Proposal\n>     [#861: Naming conventions](https://github.com/carbon-language/carbon-lang/pull/861)\n> -   Proposal\n>     [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083)\n> -   Proposal\n>     [#2015: Numeric type literal syntax](https://github.com/carbon-language/carbon-lang/pull/2015)\n\n#### Floating-point literals\n\nFloating-point types along with [user-defined types](#user-defined-types) may\ninitialized from _real-number literals_. Decimal and hexadecimal real-number\nliterals are supported:\n\n-   `123.456` (digits on both sides of the `.`)\n-   `123.456e789` (optional `+` or `-` after the `e`)\n-   `0x1.Ap123` (optional `+` or `-` after the `p`)\n\nAs with integer literals, underscores (`_`) may be used as digit separators.\nReal-number literals always have a period (`.`) and a digit on each side of the\nperiod. When a real-number literal is interpreted as a value of a floating-point\ntype, its value is the representable real number closest to the value of the\nliteral. In the case of a tie, the nearest value whose mantissa is even is\nselected.\n\n> References:\n>\n> -   [Real-number literal syntax](lexical_conventions/numeric_literals.md#real-number-literals)\n> -   [Numeric literal expressions](expressions/literals.md#numeric-literals)\n> -   Proposal\n>     [#143: Numeric literals](https://github.com/carbon-language/carbon-lang/pull/143)\n> -   Proposal\n>     [#144: Numeric literal semantics](https://github.com/carbon-language/carbon-lang/pull/144)\n> -   Proposal\n>     [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820)\n> -   Proposal\n>     [#866: Allow ties in floating literals](https://github.com/carbon-language/carbon-lang/pull/866)\n> -   Proposal\n>     [#1983: Weaken digit separator placement rules](https://github.com/carbon-language/carbon-lang/pull/1983)\n\n### String types\n\n> **Note:** This is provisional, no design for string types has been through the\n> proposal process yet.\n\nThere are two string types:\n\n-   `String` - a byte sequence treated as containing UTF-8 encoded text.\n-   `StringView` - a read-only reference to a byte sequence treated as\n    containing UTF-8 encoded text.\n\nThere is an [implicit conversion](expressions/implicit_conversions.md) from\n`String` to `StringView`.\n\n> References:\n>\n> -   Question-for-leads issue\n>     [#750: Naming conventions for Carbon-provided features](https://github.com/carbon-language/carbon-lang/issues/750)\n> -   Proposal\n>     [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820)\n> -   Proposal\n>     [#861: Naming conventions](https://github.com/carbon-language/carbon-lang/pull/861)\n\n#### String literals\n\nString literals may be written on a single line using a double quotation mark\n(`\"`) at the beginning and end of the string, as in `\"example\"`.\n\nMulti-line string literals, called _block string literals_, begin and end with\nthree single quotation marks (`'''`), and may have a file type indicator after\nthe first `'''`.\n\n```carbon\n// Block string literal:\nvar block: String = '''\n    The winds grow high; so do your stomachs, lords.\n    How irksome is this music to my heart!\n    When such strings jar, what hope of harmony?\n    I pray, my lords, let me compound this strife.\n        -- History of Henry VI, Part II, Act II, Scene 1, W. Shakespeare\n    ''';\n```\n\nThe indentation of a block string literal's terminating line is removed from all\npreceding lines.\n\nStrings may contain\n[escape sequences](lexical_conventions/string_literals.md#escape-sequences)\nintroduced with a backslash (`\\`).\n[Raw string literals](lexical_conventions/string_literals.md#raw-string-literals)\nare available for representing strings with `\\`s and `\"`s.\n\n> References:\n>\n> -   [String literals](lexical_conventions/string_literals.md)\n> -   Proposal\n>     [#199: String literals](https://github.com/carbon-language/carbon-lang/pull/199)\n\n## Values, objects, and expressions\n\nCarbon has both abstract _values_ and concrete _objects_. Carbon _values_ are\nthings like `42`, `true`, and `i32` (a type value). Carbon _objects_ have\n_storage_ where values can be read and written. Storage also allows taking the\naddress of an object in memory in Carbon.\n\n> References:\n>\n> -   [Values, variables, and pointers](values.md)\n> -   Proposal\n>     [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)\n\n### Expression categories\n\nA Carbon expression produces a value, references an object, or initializes an\nobject. Every expression has a\n[category](<https://en.wikipedia.org/wiki/Value_(computer_science)#lrvalue>),\nsimilar to [C++](https://en.cppreference.com/w/cpp/language/value_category):\n\n-   [_Value expressions_](values.md#value-expressions) produce abstract,\n    read-only _values_ that cannot be modified or have their address taken.\n-   [_Reference expressions_](values.md#reference-expressions) refer to\n    _objects_ with _storage_ where a value may be read or written and the\n    object's address can be taken.\n-   [_Initializing expressions_](values.md#initializing-expressions) which\n    require storage to be provided implicitly when evaluating the expression.\n    The expression then initializes an object in that storage. These are used to\n    model function returns, which can construct the returned value directly in\n    the caller's storage.\n\nExpressions in one category can be converted to any other category when needed.\nThe primitive conversion steps used are:\n\n-   _Value acquisition_ converts a reference expression into a value expression.\n-   _Direct initialization_ converts a value expression into an initializing\n    expression.\n-   _Copy initialization_ converts a reference expression into an initializing\n    expression.\n-   _Temporary materialization_ converts an initializing expression into a\n    reference expression.\n\n> References:\n>\n> -   [Expression categories](values.md#expression-categories)\n> -   Proposal\n>     [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)\n\n### Expression phases\n\nValue expressions are further broken down into three _expression phases_:\n\n-   A _template constant_ has a value known at compile time, and that value is\n    available during type checking, for example to use as the size of an array.\n    These include literals ([integer](#integer-literals),\n    [floating-point](#floating-point-literals), [string](#string-literals)),\n    concrete type values (like `f64` or `Optional(i32*)`), expressions in terms\n    of constants, and values of\n    [`template` parameters](#checked-and-template-parameters).\n-   A _symbolic constant_ has a value that will be known at the code generation\n    stage of compilation when\n    [monomorphization](https://en.wikipedia.org/wiki/Monomorphization) happens,\n    but is not known during type checking. This includes\n    [checked-generic parameters](#checked-and-template-parameters), and type\n    expressions with checked-generic arguments, like `Optional(T*)`.\n-   A _runtime value_ has a dynamic value only known at runtime.\n\nTemplate constants and symbolic constants are collectively called _compile-time\nconstants_ and correspond to declarations using `:!`.\n\nCarbon will automatically convert a template constant to a symbolic constant, or\nany value to a runtime value:\n\n```mermaid\ngraph TD;\n    A(template constant)-->B(symbolic constant)-->C(runtime value);\n    D(reference expression)-->C;\n```\n\nTemplate constants convert to symbolic constants and to runtime values. Symbolic\nconstants will generally convert into runtime values if an operation that\ninspects the value is performed on them. Runtime values will convert into\ntemplate or symbolic constants if constant evaluation of the runtime expression\nsucceeds.\n\n> **Note:** Conversion of runtime values to other phases is provisional.\n\n> References:\n>\n> -   Proposal\n>     [#2200: Template generics](https://github.com/carbon-language/carbon-lang/pull/2200)\n> -   Proposal\n>     [#2964: Expression phase terminology](https://github.com/carbon-language/carbon-lang/pull/2964)\n> -   Proposal\n>     [#3162: Reduce ambiguity in terminology](https://github.com/carbon-language/carbon-lang/pull/3162)\n\n## Composite types\n\n### Tuples\n\nA tuple is a fixed-size collection of values that can have different types,\nwhere each value is identified by its position in the tuple. An example use of\ntuples is to return multiple values from a function:\n\n```carbon\nfn DoubleBoth(x: i32, y: i32) -> (i32, i32) {\n  return (2 * x, 2 * y);\n}\n```\n\nBreaking this example apart:\n\n-   The return type is a tuple of two `i32` types.\n-   The expression uses tuple syntax to build a tuple of two `i32` values.\n\nBoth of these are expressions using the tuple syntax\n`(<expression>, <expression>)`. The only difference is the type of the tuple\nexpression: one is a tuple of types, the other a tuple of values. In other\nwords, a tuple type is a tuple _of_ types.\n\nThe components of a tuple are accessed positionally, so element access uses\nsubscript syntax, but the index must be a compile-time constant:\n\n```carbon\nfn DoubleTuple(x: (i32, i32)) -> (i32, i32) {\n  return (2 * x[0], 2 * x[1]);\n}\n```\n\nTuple types are\n[structural](https://en.wikipedia.org/wiki/Structural_type_system).\n\n> **Note:** This is provisional, no design for tuples has been through the\n> proposal process yet. Many of these questions were discussed in dropped\n> proposal [#111](https://github.com/carbon-language/carbon-lang/pull/111).\n\n> References: [Tuples](tuples.md)\n\n### Struct types\n\nCarbon also has\n[structural types](https://en.wikipedia.org/wiki/Structural_type_system) whose\nmembers are identified by name instead of position. These are called _structural\ndata classes_, also known as a _struct types_ or _structs_.\n\nBoth struct types and values are written inside curly braces (`{`...`}`). In\nboth cases, they have a comma-separated list of members that start with a period\n(`.`) followed by the field name.\n\n-   In a struct type, the field name is followed by a colon (`:`) and the type,\n    as in: `{.name: String, .count: i32}`.\n-   In a struct value, called a _structural data class literal_ or a _struct\n    literal_, the field name is followed by an equal sign (`=`) and the value,\n    as in `{.key = \"Joe\", .count = 3}`.\n\n> References:\n>\n> -   [Struct types](classes.md#struct-types)\n> -   Proposal\n>     [#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561)\n> -   Proposal\n>     [#981: Implicit conversions for aggregates](https://github.com/carbon-language/carbon-lang/pull/981)\n> -   Proposal\n>     [#710: Default comparison for data classes](https://github.com/carbon-language/carbon-lang/issues/710)\n\n### Pointer types\n\nThe type of pointers-to-values-of-type-`T` is written `T*`. Carbon pointers do\nnot support\n[pointer arithmetic](<https://en.wikipedia.org/wiki/Pointer_(computer_programming)>);\nthe only pointer [operations](#expressions) are:\n\n-   Dereference: given a pointer `p`, `*p` gives the value `p` points to as a\n    [reference expression](#expression-categories). `p->m` is syntactic sugar\n    for `(*p).m`.\n-   Address-of: given a [reference expression](#expression-categories) `x`, `&x`\n    returns a pointer to `x`.\n\nThere are no [null pointers](https://en.wikipedia.org/wiki/Null_pointer) in\nCarbon. To represent a pointer that may not refer to a valid object, use the\ntype `Optional(T*)`.\n\n**Future work:** Perhaps Carbon will have\n[stricter pointer provenance](https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html)\nor restrictions on casts between pointers and integers.\n\n> References:\n>\n> -   [Pointers](values.md#pointers)\n> -   Proposal\n>     [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)\n\n### Arrays and slices\n\n> **TODO:** The provisional array syntax documented here has been superseded by\n> [p4682: The Core.Array type for direct-storage immutably-sized buffers](/proposals/p4682.md).\n\nThe type of an array of holding 4 `i32` values is written `[i32; 4]`. There is\nan [implicit conversion](expressions/implicit_conversions.md) from tuples to\narrays of the same length as long as every component of the tuple may be\nimplicitly converted to the destination element type. In cases where the size of\nthe array may be deduced, it may be omitted, as in:\n\n```carbon\nvar i: i32 = 1;\n// `[i32;]` equivalent to `[i32; 3]` here.\nvar a: [i32;] = (i, i, i);\n```\n\nElements of an array may be accessed using square brackets (`[`...`]`), as in\n`a[i]`:\n\n```carbon\na[i] = 2;\nCore.Print(a[0]);\n```\n\n> **TODO:** Slices\n\n> **Note:** This is provisional, no design for arrays has been through the\n> proposal process yet.\n\n## Expressions\n\nExpressions describe some computed value. The simplest example would be a\nliteral number like `42`: an expression that computes the integer value 42.\n\nSome common expressions in Carbon include:\n\n-   Literals:\n\n    -   [boolean](#bool): `true`, `false`\n    -   [integer](#integer-literals): `42`, `-7`\n    -   [real-number](#floating-point-literals): `3.1419`, `6.022e+23`\n    -   [string](#string-literals): `\"Hello World!\"`\n    -   [tuple](#tuples): `(1, 2, 3)`\n    -   [struct](#struct-types): `{.word = \"the\", .count = 56}`\n\n-   [Names](#names) and [member access](expressions/member_access.md)\n\n-   [Operators](expressions#operators):\n\n    -   [Arithmetic](expressions/arithmetic.md): `-x`, `1 + 2`, `3 - 4`,\n        `2 * 5`, `6 / 3`, `5 % 3`\n    -   [Bitwise](expressions/bitwise.md): `2 & 3`, `2 | 4`, `3 ^ 1`, `^7`\n    -   [Bit shift](expressions/bitwise.md): `1 << 3`, `8 >> 1`\n    -   [Comparison](expressions/comparison_operators.md): `2 == 2`, `3 != 4`,\n        `5 < 6`, `7 > 6`, `8 <= 8`, `8 >= 8`\n    -   [Conversion](expressions/as_expressions.md): `2 as i32`\n    -   [Logical](expressions/logical_operators.md): `a and b`, `c or d`,\n        `not e`\n    -   [Indexing](#arrays-and-slices): `a[3]`\n    -   [Function](#functions) call: `f(4)`\n    -   [Pointer](expressions/pointer_operators.md): `*p`, `p->m`, `&x`\n    -   [Move](#move): `~x`\n\n-   [Conditionals](expressions/if.md): `if c then t else f`\n-   Parentheses: `(7 + 8) * (3 - 1)`\n\nWhen an expression appears in a context in which an expression of a specific\ntype is expected, [implicit conversions](expressions/implicit_conversions.md)\nare applied to convert the expression to the target type.\n\n> References:\n>\n> -   [Expressions](expressions/)\n> -   Proposal\n>     [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)\n> -   Proposal\n>     [#555: Operator precedence](https://github.com/carbon-language/carbon-lang/pull/555)\n> -   Proposal\n>     [#601: Operator tokens](https://github.com/carbon-language/carbon-lang/pull/601)\n> -   Proposal\n>     [#680: And, or, not](https://github.com/carbon-language/carbon-lang/pull/680)\n> -   Proposal\n>     [#702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702)\n> -   Proposal\n>     [#845: as expressions](https://github.com/carbon-language/carbon-lang/pull/845)\n> -   Proposal\n>     [#911: Conditional expressions](https://github.com/carbon-language/carbon-lang/pull/911)\n> -   Proposal\n>     [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083)\n> -   Proposal\n>     [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)\n\n## Declarations, Definitions, and Scopes\n\n_Declarations_ introduce a new [name](#names) and say what that name represents.\nFor some kinds of entities, like [functions](#functions), there are two kinds of\ndeclarations: _forward declarations_ and _definitions_. For those entities,\nthere should be exactly one definition for the name, and at most one additional\nforward declaration that introduces the name before it is defined, plus any\nnumber of declarations in a\n[`match_first` block](generics/details.md#prioritization-rule). Forward\ndeclarations can be used to separate interface from implementation, such as to\ndeclare a name in an [API file](#files-libraries-packages) that is defined in an\n[implementation file](#files-libraries-packages). Forward declarations also\nallow entities to be used before they are defined, such as to allow cyclic\nreferences. A name that has been declared but not defined is called\n_incomplete_, and in some cases there are limitations on what can be done with\nan incomplete name. Within a definition, the defined name is incomplete until\nthe end of the definition is reached, but is complete in the bodies of member\nfunctions because they are\n[parsed as if they appeared after the definition](#class-functions-and-factory-functions).\n\nA name is valid until the end of the innermost enclosing\n[_scope_](<https://en.wikipedia.org/wiki/Scope_(computer_science)>). There are a\nfew kinds of scopes:\n\n-   the outermost scope, which includes the whole file,\n-   scopes that are enclosed in curly braces (`{`...`}`), and\n-   scopes that encompass a single declaration.\n\nFor example, the names of the parameters of a [function](#functions) or\n[class](#classes) are valid until the end of the declaration. The name of the\nfunction or class itself is visible until the end of the enclosing scope.\n\n> References:\n>\n> -   [Principle: Information accumulation](/docs/project/principles/information_accumulation.md)\n> -   Proposal\n>     [#875: Principle: information accumulation](https://github.com/carbon-language/carbon-lang/pull/875)\n> -   Question-for-leads issue\n>     [#472: Open question: Calling functions defined later in the same file](https://github.com/carbon-language/carbon-lang/issues/472)\n\n## Patterns\n\n> **Note:** This is provisional, no design for patterns has been through the\n> proposal process yet.\n\nA _pattern_ says how to receive some data that is being matched against. There\nare two kinds of patterns:\n\n-   _Refutable_ patterns can fail to match based on the runtime value being\n    matched.\n-   _Irrefutable_ patterns are guaranteed to match, so long as the code\n    type-checks.\n\nIn the [introduction](#tour-of-the-basics), [function parameters](#functions),\n[variable `var` declarations](#variable-var-declarations), and\n[constant `let` declarations](#constant-let-declarations) use a \"name `:` type\"\nconstruction. That construction is an example of an irrefutable pattern, and in\nfact any irrefutable pattern may be used in those positions.\n[`match` statements](#match) can include both refutable patterns and irrefutable\npatterns.\n\n> References:\n>\n> -   [Pattern matching](pattern_matching.md)\n> -   Proposal\n>     [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)\n> -   Proposal\n>     [#2188: Pattern matching syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2188)\n\n### Binding patterns\n\nThe most common irrefutable pattern is a _binding pattern_, consisting of a new\nname, a colon (`:`), and a type. It binds the matched value of that type to that\nname. It can only match values that may be\n[implicitly converted](expressions/implicit_conversions.md) to that type. A\nunderscore (`_`) may be used instead of the name to match a value but without\nbinding any name to it.\n\nBinding patterns default to _`let` bindings_. The `var` keyword is used to make\nit a _`var` binding_.\n\n-   A `let` binding binds a name to a value, so the name can be used as a\n    [value expression](#expression-categories). This means the value cannot be\n    modified, and its address generally cannot be taken.\n-   A `var` binding creates an object with dedicated storage, and so the name\n    can be used as a [reference expression](#expression-categories) which can be\n    modified and has a stable address.\n\nA `let`-binding may be [implemented](values.md#value-expressions) as an alias\nfor the original value (like a\n[`const` reference in C++](<https://en.wikipedia.org/wiki/Reference_(C%2B%2B)>)),\nor it may be copied from the original value (if it is copyable), or it may be\nmoved from the original value (if it was a temporary). The Carbon\nimplementation's choice among these options may be indirectly observable, for\nexample through side effects of the destructor, copy, and move operations, but\nthe program's correctness must not depend on which option the Carbon\nimplementation chooses.\n\nA [compile-time binding](#checked-and-template-parameters) uses `:!` instead of\na colon (`:`) and can only match [compile-time constants](#expression-phases),\nnot run-time values. A `template` keyword before the binding selects a template\nbinding instead of a symbolic binding.\n\nThe keyword `auto` may be used in place of the type in a binding pattern, as\nlong as the type can be deduced from the type of a value in the same\ndeclaration.\n\n> References:\n>\n> -   Proposal\n>     [#3162: Reduce ambiguity in terminology](https://github.com/carbon-language/carbon-lang/pull/3162)\n\n### Destructuring patterns\n\nThere are also irrefutable _destructuring patterns_, such as _tuple\ndestructuring_. A tuple destructuring pattern looks like a tuple of patterns. It\nmay only be used to match tuple values whose components match the component\npatterns of the tuple. An example use is:\n\n```carbon\n// `Bar()` returns a tuple consisting of an\n// `i32` value and 2-tuple of `f32` values.\nfn Bar() -> (i32, (f32, f32));\n\nfn Foo() -> i64 {\n  // Pattern in `var` declaration:\n  var (p: i64, _: auto) = Bar();\n  return p;\n}\n```\n\nThe pattern used in the `var` declaration destructures the tuple value returned\nby `Bar()`. The first component pattern, `p: i64`, corresponds to the first\ncomponent of the value returned by `Bar()`, which has type `i32`. This is\nallowed since there is an implicit conversion from `i32` to `i64`. The result of\nthis conversion is assigned to the name `p`. The second component pattern,\n`_: auto`, matches the second component of the value returned by `Bar()`, which\nhas type `(f32, f32)`.\n\n### Refutable patterns\n\nAdditional kinds of patterns are allowed in [`match` statements](#match), that\nmay or may not match based on the runtime value of the `match` expression:\n\n-   An _expression pattern_ is an expression, such as `42`, whose value must be\n    equal to match.\n-   A _choice pattern_ matches one case from a choice type, as described in\n    [the choice types section](#choice-types).\n-   A _dynamic cast pattern_ is tests the dynamic type, as described in\n    [inheritance](#inheritance).\n\nSee [`match`](#match) for examples of refutable patterns.\n\n> References:\n>\n> -   [Pattern matching](pattern_matching.md)\n> -   Question-for-leads issue\n>     [#1283: how should pattern matching and implicit conversion interact?](https://github.com/carbon-language/carbon-lang/issues/1283)\n\n## Name-binding declarations\n\nThere are two kinds of name-binding declarations:\n\n-   constant declarations, introduced with `let`, and\n-   variable declarations, introduced with `var`.\n\nThere are no forward declarations of these; all name-binding declarations are\n[definitions](#declarations-definitions-and-scopes).\n\n### Constant `let` declarations\n\nA `let` declaration matches an [irrefutable pattern](#patterns) to a value. In\nthis example, the name `x` is bound to the value `42` with type `i64`:\n\n```carbon\nlet x: i64 = 42;\n```\n\nHere `x: i64` is the pattern, which is followed by an equal sign (`=`) and the\nvalue to match, `42`. The names from [binding patterns](#binding-patterns) are\nintroduced into the enclosing [scope](#declarations-definitions-and-scopes).\n\n> References:\n>\n> -   [Binding patterns and local variables with `let` and `var`](values.md#binding-patterns-and-local-variables-with-let-and-var)\n> -   Proposal\n>     [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)\n\n### Variable `var` declarations\n\nA `var` declaration is similar, except with `var` bindings, so `x` here is a\n[reference expression](#expression-categories) for an object with storage and an\naddress, and so may be modified:\n\n```carbon\nvar x: i64 = 42;\nx = 7;\n```\n\nVariables with a type that has [an unformed state](#unformed-state) do not need\nto be initialized in the variable declaration, but do need to be assigned before\nthey are used.\n\n> References:\n>\n> -   [Binding patterns and local variables with `let` and `var`](values.md#binding-patterns-and-local-variables-with-let-and-var)\n> -   Proposal\n>     [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)\n> -   Proposal\n>     [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257)\n> -   Proposal\n>     [#339: Add `var <type> <identifier> [ = <value> ];` syntax for variables](https://github.com/carbon-language/carbon-lang/pull/339)\n> -   Proposal\n>     [#618: var ordering](https://github.com/carbon-language/carbon-lang/pull/618)\n> -   Proposal\n>     [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)\n\n### `auto`\n\nIf `auto` is used as the type in a `var` or `let` declaration, the type is the\nstatic type of the initializer expression, which is required.\n\n```\nvar x: i64 = 2;\n// The type of `y` is inferred to be `i64`.\nlet y: auto = x + 3;\n// The type of `z` is inferred to be `bool`.\nvar z: auto = (y > 1);\n```\n\n> References:\n>\n> -   [Type inference](type_inference.md)\n> -   Proposal\n>     [#851: auto keyword for vars](https://github.com/carbon-language/carbon-lang/pull/851)\n\n### Global constants and variables\n\n[Constant `let` declarations](#constant-let-declarations) may occur at a global\nscope as well as local and member scopes. However, there are currently no global\nvariables.\n\n> **Note**: The semantics of global constant declarations and absence of global\n> variable declarations is currently provisional.\n>\n> We are exploring several different ideas for how to design less bug-prone\n> patterns to replace the important use cases programmers still have for global\n> variables. We may be unable to fully address them, at least for migrated code,\n> and be forced to add some limited form of global variables back. We may also\n> discover that their convenience outweighs any improvements afforded.\n\n## Functions\n\nFunctions are the core unit of behavior. For example, this is a\n[forward declaration](#declarations-definitions-and-scopes) of a function that\nadds two 64-bit integers:\n\n```carbon\nfn Add(a: i64, b: i64) -> i64;\n```\n\nBreaking this apart:\n\n-   `fn` is the keyword used to introduce a function.\n-   Its name is `Add`. This is the name added to the enclosing\n    [scope](#declarations-definitions-and-scopes).\n-   The [parameter list](#parameters) in parentheses (`(`...`)`) is a\n    comma-separated list of [irrefutable patterns](#patterns).\n-   It returns an `i64` result. Functions that return nothing omit the `->` and\n    return type.\n\nYou would call this function like `Add(1, 2)`.\n\nA function definition is a function declaration that has a body\n[block](#blocks-and-statements) instead of a semicolon:\n\n```carbon\nfn Add(a: i64, b: i64) -> i64 {\n  return a + b;\n}\n```\n\nThe names of the parameters are in scope until the end of the definition or\ndeclaration. The parameter names in a forward declaration may be omitted using\n`_`, but must match the definition if they are specified.\n\n> References:\n>\n> -   [Functions](functions.md)\n> -   Proposal\n>     [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)\n> -   Proposal\n>     [#438: Add statement syntax for function declarations](https://github.com/carbon-language/carbon-lang/pull/438)\n> -   Question-for-leads issue\n>     [#476: Optional argument names (unused arguments)](https://github.com/carbon-language/carbon-lang/issues/476)\n> -   Question-for-leads issue\n>     [#1132: How do we match forward declarations with their definitions?](https://github.com/carbon-language/carbon-lang/issues/1132)\n\n### Parameters\n\nThe bindings in the parameter list default to\n[`let` bindings](#binding-patterns), and so the parameter names are treated as\n[value expressions](#expression-categories). This is appropriate for input\nparameters. This binding will be implemented using a pointer, unless it is legal\nto copy and copying is cheaper.\n\nIf the `var` keyword is added before the binding pattern, then the arguments\nwill be copied (or moved from a temporary) to new storage, and so can be mutated\nin the function body. The copy ensures that any mutations will not be visible to\nthe caller.\n\nUse a [pointer](#pointer-types) parameter type to represent an\n[input/output parameter](<https://en.wikipedia.org/wiki/Parameter_(computer_programming)#Output_parameters>),\nallowing a function to modify a variable of the caller's. This makes the\npossibility of those modifications visible: by taking the address using `&` in\nthe caller, and dereferencing using `*` in the callee.\n\nOutputs of a function should prefer to be returned. Multiple values may be\nreturned using a [tuple](#tuples) or [struct](#struct-types) type.\n\n> References:\n>\n> -   [Binding patterns and local variables with `let` and `var`](values.md#binding-patterns-and-local-variables-with-let-and-var)\n> -   Proposal\n>     [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)\n\n### `auto` return type\n\nIf `auto` is used in place of the return type, the return type of the function\nis inferred from the function body. It is set to [common type](#common-type) of\nthe static type of arguments to the [`return` statements](#return) in the\nfunction. This is not allowed in a forward declaration.\n\n```\n// Return type is inferred to be `bool`, the type of `a > 0`.\nfn Positive(a: i64) -> auto {\n  return a > 0;\n}\n```\n\n> References:\n>\n> -   [Type inference](type_inference.md)\n> -   [Function return clause](functions.md#return-clause)\n> -   Proposal\n>     [#826: Function return type inference](https://github.com/carbon-language/carbon-lang/pull/826)\n\n### Blocks and statements\n\nA _block_ is a sequence of _statements_. A block defines a\n[scope](#declarations-definitions-and-scopes) and, like other scopes, is\nenclosed in curly braces (`{`...`}`). Each statement is terminated by a\nsemicolon or block. [Expressions](#expressions), [assignments](assignment.md),\n[`var`](#variable-var-declarations) and [`let`](#constant-let-declarations) are\nvalid statements.\n\nStatements within a block are normally executed in the order they appear in the\nsource code, except when modified by control-flow statements.\n\nThe body of a function is defined by a block, and some\n[control-flow statements](#control-flow) have their own blocks of code. These\nare nested within the enclosing scope. For example, here is a function\ndefinition with a block of statements defining the body of the function, and a\nnested block as part of a `while` statement:\n\n```carbon\nfn Foo() {\n  Bar();\n  while (Baz()) {\n    Quux();\n  }\n}\n```\n\n> References:\n>\n> -   [Blocks and statements](blocks_and_statements.md)\n> -   Proposal\n>     [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)\n> -   Proposal\n>     [#2665: Semicolons terminate statements](https://github.com/carbon-language/carbon-lang/pull/2665)\n\n### Control flow\n\nBlocks of statements are generally executed sequentially. Control-flow\nstatements give additional control over the flow of execution and which\nstatements are executed.\n\nSome control-flow statements include [blocks](#blocks-and-statements). Those\nblocks will always be within curly braces `{`...`}`.\n\n```carbon\n// Curly braces { ... } are required.\nif (condition) {\n  ExecutedWhenTrue();\n} else {\n  ExecutedWhenFalse();\n}\n```\n\nThis is unlike C++, which allows control-flow constructs to omit curly braces\naround a single statement.\n\n> References:\n>\n> -   [Control flow](control_flow/README.md)\n> -   Proposal\n>     [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)\n> -   Proposal\n>     [#623: Require braces](https://github.com/carbon-language/carbon-lang/pull/623)\n\n#### `if` and `else`\n\n`if` and `else` provide conditional execution of statements. An `if` statement\nconsists of:\n\n-   An `if` introducer followed by a condition in parentheses. If the condition\n    evaluates to `true`, the block following the condition is executed,\n    otherwise it is skipped.\n-   This may be followed by zero or more `else if` clauses, whose conditions are\n    evaluated if all prior conditions evaluate to `false`, with a block that is\n    executed if that evaluation is to `true`.\n-   A final optional `else` clause, with a block that is executed if all\n    conditions evaluate to `false`.\n\nFor example:\n\n```carbon\nif (fruit.IsYellow()) {\n  Core.Print(\"Banana!\");\n} else if (fruit.IsOrange()) {\n  Core.Print(\"Orange!\");\n} else {\n  Core.Print(\"Vegetable!\");\n}\n```\n\nThis code will:\n\n-   Print `Banana!` if `fruit.IsYellow()` is `true`.\n-   Print `Orange!` if `fruit.IsYellow()` is `false` and `fruit.IsOrange()` is\n    `true`.\n-   Print `Vegetable!` if both of the above return `false`.\n\n> References:\n>\n> -   [Control flow](control_flow/conditionals.md)\n> -   Proposal\n>     [#285: if/else](https://github.com/carbon-language/carbon-lang/pull/285)\n\n#### Loops\n\n> References: [Loops](control_flow/loops.md)\n\n##### `while`\n\n`while` statements loop for as long as the passed expression returns `true`. For\nexample, this prints `0`, `1`, `2`, then `Done!`:\n\n```carbon\nvar x: i32 = 0;\nwhile (x < 3) {\n  Core.Print(x);\n  ++x;\n}\nCore.Print(\"Done!\");\n```\n\n> References:\n>\n> -   [`while` loops](control_flow/loops.md#while)\n> -   Proposal\n>     [#340: Add C++-like `while` loops](https://github.com/carbon-language/carbon-lang/pull/340)\n\n##### `for`\n\n`for` statements support range-based looping, typically over containers. For\nexample, this prints each `String` value in `names`:\n\n```carbon\nfor (var name: String in names) {\n  Core.Print(name);\n}\n```\n\n> References:\n>\n> -   [`for` loops](control_flow/loops.md#for)\n> -   Proposal\n>     [#353: Add C++-like `for` loops](https://github.com/carbon-language/carbon-lang/pull/353)\n> -   Proposal\n>     [#1885: ranged-based `for` for user-defined types](https://github.com/carbon-language/carbon-lang/pull/1885)\n\n##### `break`\n\nThe `break` statement immediately ends a `while` or `for` loop. Execution will\ncontinue starting from the end of the loop's scope. For example, this processes\nsteps until a manual step is hit (if no manual step is hit, all steps are\nprocessed):\n\n```carbon\nfor (var step: Step in steps) {\n  if (step.IsManual()) {\n    Core.Print(\"Reached manual step!\");\n    break;\n  }\n  step.Process();\n}\n```\n\n> References:\n>\n> -   [`break`](control_flow/loops.md#break)\n> -   Proposal\n>     [#340: Add C++-like `while` loops](https://github.com/carbon-language/carbon-lang/pull/340)\n> -   Proposal\n>     [#353: Add C++-like `for` loops](https://github.com/carbon-language/carbon-lang/pull/353)\n\n##### `continue`\n\nThe `continue` statement immediately goes to the next loop of a `while` or\n`for`. In a `while`, execution continues with the `while` expression. For\nexample, this prints all non-empty lines of a file, using `continue` to skip\nempty lines:\n\n```carbon\nvar f: File = OpenFile(path);\nwhile (!f.EOF()) {\n  var line: String = f.ReadLine();\n  if (line.IsEmpty()) {\n    continue;\n  }\n  Core.Print(line);\n}\n```\n\n> References:\n>\n> -   [`continue`](control_flow/loops.md#continue)\n> -   Proposal\n>     [#340: Add C++-like `while` loops](https://github.com/carbon-language/carbon-lang/pull/340)\n> -   Proposal\n>     [#353: Add C++-like `for` loops](https://github.com/carbon-language/carbon-lang/pull/353)\n\n#### `return`\n\nThe `return` statement ends the flow of execution within a function, returning\nexecution to the caller.\n\n```carbon\n// Prints the integers 1 .. `n` and then\n// returns to the caller.\nfn PrintFirstN(n: i32) {\n  var i: i32 = 0;\n  while (true) {\n    i += 1;\n    if (i > n) {\n      // None of the rest of the function is\n      // executed after a `return`.\n      return;\n    }\n    Core.Print(i);\n  }\n}\n```\n\nIf the function returns a value to the caller, that value is provided by an\nexpression in the return statement. For example:\n\n```carbon\nfn Sign(i: i32) -> i32 {\n  if (i > 0) {\n    return 1;\n  }\n  if (i < 0) {\n    return -1;\n  }\n  return 0;\n}\n\nAssert(Sign(-3) == -1);\n```\n\n> References:\n>\n> -   [`return`](control_flow/return.md)\n> -   [`return` statements](functions.md#return-statements)\n> -   Proposal\n>     [#415: return](https://github.com/carbon-language/carbon-lang/pull/415)\n> -   Proposal\n>     [#538: return with no argument](https://github.com/carbon-language/carbon-lang/pull/538)\n\n##### `returned var`\n\nTo avoid a copy when returning a variable, add a `returned` prefix to the\nvariable's declaration and use `return var` instead of returning an expression,\nas in:\n\n```carbon\nfn MakeCircle(radius: i32) -> Circle {\n  returned var c: Circle;\n  c.radius = radius;\n  // `return c` would be invalid because `returned` is in use.\n  return var;\n}\n```\n\nThis is instead of\n[the \"named return value optimization\" of C++](https://en.wikipedia.org/wiki/Copy_elision#Return_value_optimization).\n\n> References:\n>\n> -   [`returned var`](control_flow/return.md#returned-var)\n> -   Proposal\n>     [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257)\n\n#### `match`\n\n`match` is a control flow similar to `switch` of C and C++ and mirrors similar\nconstructs in other languages, such as Swift. The `match` keyword is followed by\nan expression in parentheses, whose value is matched against the `case`\ndeclarations, each of which contains a [refutable pattern](#refutable-patterns),\nin order. The refutable pattern may optionally be followed by an `if`\nexpression, which may use the names from bindings in the pattern.\n\nThe code for the first matching `case` is executed. An optional `default` block\nmay be placed after the `case` declarations, it will be executed if none of the\n`case` declarations match.\n\nAn example `match` is:\n\n```carbon\nfn Bar() -> (i32, (f32, f32));\n\nfn Foo() -> f32 {\n  match (Bar()) {\n    case (42, (x: f32, y: f32)) => {\n      return x - y;\n    }\n    case (p: i32, (x: f32, _: f32)) if (p < 13) => {\n      return p * x;\n    }\n    case (p: i32, _: auto) if (p > 3) => {\n      return p * Pi;\n    }\n    default => {\n      return Pi;\n    }\n  }\n}\n```\n\n> References:\n>\n> -   [Pattern matching](pattern_matching.md)\n> -   Question-for-leads issue\n>     [#1283: how should pattern matching and implicit conversion interact?](https://github.com/carbon-language/carbon-lang/issues/1283)\n> -   Proposal\n>     [#2188: Pattern matching syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2188)\n\n## User-defined types\n\n### Classes\n\n_Nominal classes_, or just\n[_classes_](<https://en.wikipedia.org/wiki/Class_(computer_programming)>), are a\nway for users to define their own\n[data structures](https://en.wikipedia.org/wiki/Data_structure) or\n[record types](<https://en.wikipedia.org/wiki/Record_(computer_science)>).\n\nThis is an example of a class\n[definition](#declarations-definitions-and-scopes):\n\n```carbon\nclass Widget {\n  var x: i32;\n  var y: i32;\n  var payload: String;\n}\n```\n\nBreaking this apart:\n\n-   This defines a class named `Widget`. `Widget` is the name added to the\n    enclosing [scope](#declarations-definitions-and-scopes).\n-   The name `Widget` is followed by curly braces (`{`...`}`) containing the\n    class _body_, making this a\n    [definition](#declarations-definitions-and-scopes). A\n    [forward declaration](#declarations-definitions-and-scopes) would instead\n    have a semicolon(`;`).\n-   Those braces delimit the class'\n    [scope](#declarations-definitions-and-scopes).\n-   Fields, or\n    [instances variables](https://en.wikipedia.org/wiki/Instance_variable), are\n    defined using [`var` declarations](#variable-var-declarations). `Widget` has\n    two `i32` fields (`x` and `y`), and one `String` field (`payload`).\n\nThe order of the field declarations determines the fields' memory-layout order.\n\nClasses may have other kinds of members beyond fields declared in its scope:\n\n-   [Class functions](#class-functions-and-factory-functions)\n-   [Methods](#methods)\n-   [`alias`](#aliases)\n-   [`let`](#constant-let-declarations) to define class constants. **TODO:**\n    Another syntax to define constants associated with the class like\n    `class let` or `static let`?\n-   `class`, to define a\n    [_member class_ or _nested class_](https://en.wikipedia.org/wiki/Inner_class)\n\nWithin the scope of a class, the unqualified name `Self` can be used to refer to\nthe class itself.\n\nMembers of a class are [accessed](expressions/member_access.md) using the dot\n(`.`) notation, so given an instance `dial` of type `Widget`, `dial.payload`\nrefers to its `payload` field.\n\nBoth [structural data classes](#struct-types) and nominal classes are considered\n_class types_, but they are commonly referred to as \"structs\" and \"classes\"\nrespectively when that is not confusing. Like structs, classes refer to their\nmembers by name. Unlike structs, classes are\n[nominal types](https://en.wikipedia.org/wiki/Nominal_type_system#Nominal_typing).\n\n> References:\n>\n> -   [Classes](classes.md#nominal-class-types)\n> -   Proposal\n>     [#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722)\n> -   Proposal\n>     [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n\n#### Assignment\n\nThere is an [implicit conversions](expressions/implicit_conversions.md) defined\nbetween a [struct literal](#struct-types) and a class type with the same fields,\nin any scope that has [access](#access-control) to all of the class' fields.\nThis may be used to assign or initialize a variable with a class type, as in:\n\n```carbon\nvar sprocket: Widget = {.x = 3, .y = 4, .payload = \"Sproing\"};\nsprocket = {.x = 2, .y = 1, .payload = \"Bounce\"};\n```\n\n> References:\n>\n> -   [Classes: Assignment](classes.md#assignment)\n> -   Proposal\n>     [#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722)\n> -   Proposal\n>     [#981: Implicit conversions for aggregates](https://github.com/carbon-language/carbon-lang/pull/981)\n\n#### Class functions and factory functions\n\nClasses may also contain _class functions_. These are functions that are\naccessed as members of the type, like\n[static member functions in C++](<https://en.wikipedia.org/wiki/Method_(computer_programming)#Static_methods>),\nas opposed to [methods](#methods) that are members of instances. They are\ncommonly used to define a function that creates instances. Carbon does not have\nseparate\n[constructors](<https://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)>)\nlike C++ does.\n\n```carbon\nclass Point {\n  // Class function that instantiates `Point`.\n  // `Self` in class scope means the class currently being defined.\n  fn Origin() -> Self {\n    return {.x = 0, .y = 0};\n  }\n  var x: i32;\n  var y: i32;\n}\n```\n\nNote that if the definition of a function is provided inside the class scope,\nthe body is treated as if it was defined immediately after the outermost class\ndefinition. This means that members such as the fields will be considered\ndeclared even if their declarations are later in the source than the class\nfunction.\n\nThe [`returned var` feature](#returned-var) can be used if the address of the\ninstance being created is needed in a factory function, as in:\n\n```carbon\nclass Registered {\n  fn Make() -> Self {\n    returned var result: Self = {...};\n    StoreMyPointerSomewhere(&result);\n    return var;\n  }\n}\n```\n\nThis approach can also be used for types that can't be copied or moved.\n\n> References:\n>\n> -   [Classes: Construction](classes.md#construction)\n> -   Proposal\n>     [#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722)\n\n#### Methods\n\nClass type definitions can include methods:\n\n```carbon\nclass Point {\n  // Method defined inline\n  fn Distance[self: Self](x2: i32, y2: i32) -> f32 {\n    var dx: i32 = x2 - self.x;\n    var dy: i32 = y2 - self.y;\n    return Math.Sqrt(dx * dx + dy * dy);\n  }\n  // Mutating method declaration\n  fn Offset[ref self: Self](dx: i32, dy: i32);\n\n  var x: i32;\n  var y: i32;\n}\n\n// Out-of-line definition of method declared inline\nfn Point.Offset[ref self: Self](dx: i32, dy: i32) {\n  self.x += dx;\n  self.y += dy;\n}\n\nvar origin: Point = {.x = 0, .y = 0};\nAssert(Math.Abs(origin.Distance(3, 4) - 5.0) < 0.001);\norigin.Offset(3, 4);\nAssert(origin.Distance(3, 4) == 0.0);\n```\n\nThis defines a `Point` class type with two integer data members `x` and `y` and\ntwo methods `Distance` and `Offset`:\n\n-   Methods are defined as class functions with a `self` parameter inside square\n    brackets `[`...`]` before the regular explicit parameter list in parens\n    `(`...`)`.\n-   Methods are called using the member syntax, `origin.Distance(`...`)` and\n    `origin.Offset(`...`)`.\n-   `Distance` computes and returns the distance to another point, without\n    modifying the `Point`. This is signified using `[self: Self]` in the method\n    declaration.\n-   `origin.Offset(`...`)` _does_ modify the value of `origin`. This is\n    signified using `[ref self: Self]` in the method declaration. It may only be\n    called on [reference expressions](#expression-categories).\n-   Methods may be declared lexically inline like `Distance`, or lexically out\n    of line like `Offset`.\n\n> References:\n>\n> -   [Methods](classes.md#methods)\n> -   Proposal\n>     [#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722)\n\n#### Inheritance\n\nThe philosophy of inheritance support in Carbon is to focus on use cases where\ninheritance is a good match, and use other features for other cases. For\nexample, [mixins](#mixins) for implementation reuse and [generics](#generics)\nfor [separating interface from implementation](#interfaces-and-implementations).\nThis allows Carbon to move away from\n[multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance),\nwhich doesn't have as efficient of an implementation strategy.\n\nClasses by default are\n[_final_](<https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Non-subclassable_classes>),\nwhich means they may not be extended. A class may be declared as allowing\nextension using either the `base class` or `abstract class` introducer instead\nof `class`. An `abstract class` is a base class that may not itself be\ninstantiated.\n\n```carbon\nbase class MyBaseClass { ... }\n```\n\nEither kind of base class may be _extended_ to get a _derived class_. Derived\nclasses are final unless they are themselves declared `base` or `abstract`.\nClasses may only extend a single class. Carbon only supports single inheritance,\nand will use mixins instead of multiple inheritance.\n\n```carbon\nbase class MiddleDerived {\n  extend base: MyBaseClass;\n  ...\n}\nclass FinalDerived {\n  extend base: MiddleDerived;\n  ...\n}\n// ❌ Forbidden: class Illegal { extend base: FinalDerived; ... }\n// may not extend `FinalDerived` since not declared `base` or `abstract`.\n```\n\nA base class may define\n[virtual methods](https://en.wikipedia.org/wiki/Virtual_function). These are\nmethods whose implementation may be overridden in a derived class. By default\nmethods are _non-virtual_, the declaration of a virtual method must be prefixed\nby one of these three keywords:\n\n-   A method marked `virtual` has a definition in this class but not in any\n    base.\n-   A method marked `abstract` does not have a definition in this class, but\n    must have a definition in any non-`abstract` derived class.\n-   A method marked `impl` has a definition in this class, overriding any\n    definition in a base class.\n\nA pointer to a derived class may be cast to a pointer to one of its base\nclasses. Calling a virtual method through a pointer to a base class will use the\noverriding definition provided in the derived class. Base classes with `virtual`\nmethods may use\n[run-time type information](https://en.wikipedia.org/wiki/Run-time_type_information)\nin a match statement to dynamically test whether the dynamic type of a value is\nsome derived class, as in:\n\n```carbon\nvar base_ptr: MyBaseType* = ...;\nmatch (base_ptr) {\n  case dyn p: MiddleDerived* => { ... }\n}\n```\n\nFor purposes of construction, a derived class acts like its first field is\ncalled `base` with the type of its immediate base class.\n\n```carbon\nclass MyDerivedType {\n  extend base: MyBaseType;\n  fn Make() -> MyDerivedType {\n    return {.base = MyBaseType.Make(), .derived_field = 7};\n  }\n  var derived_field: i32;\n}\n```\n\nAbstract classes can't be instantiated, so instead they should define class\nfunctions returning `partial Self`. Those functions should be marked\n[`protected`](#access-control) so they may only be used by derived classes.\n\n```carbon\nabstract class AbstractClass {\n  protected fn Make() -> partial Self {\n    return {.field_1 = 3, .field_2 = 9};\n  }\n  // ...\n  var field_1: i32;\n  var field_2: i32;\n}\n// ❌ Error: can't instantiate abstract class\nvar abc: AbstractClass = ...;\n\nclass DerivedFromAbstract {\n  extend base: AbstractClass;\n  fn Make() -> Self {\n    // AbstractClass.Make() returns a\n    // `partial AbstractClass` that can be used as\n    // the `.base` member when constructing a value\n    // of a derived class.\n    return {.base = AbstractClass.Make(),\n            .derived_field = 42 };\n  }\n\n  var derived_field: i32;\n}\n```\n\n> References:\n>\n> -   [Classes: Inheritance](classes.md#inheritance)\n> -   Proposal\n>     [#777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777)\n> -   Proposal\n>     [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820)\n\n#### Access control\n\nClass members are by default publicly accessible. The `private` keyword prefix\ncan be added to the member's declaration to restrict it to members of the class\nor any friends. A `private virtual` or `private abstract` method may be\nimplemented in derived classes, even though it may not be called.\n\nFriends may be declared using a `friend` declaration inside the class naming an\nexisting function or type. Unlike C++, `friend` declarations may only refer to\nnames resolvable by the compiler, and don't act like forward declarations.\n\n`protected` is like `private`, but also gives access to derived classes.\n\n> References:\n>\n> -   [Access control for class members](classes.md#access-control)\n> -   Question-for-leads issue\n>     [#665: `private` vs `public` _syntax_ strategy, as well as other visibility tools like `external`/`api`/etc.](https://github.com/carbon-language/carbon-lang/issues/665)\n> -   Proposal\n>     [#777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777)\n> -   Question-for-leads issue\n>     [#971: Private interfaces in public API files](https://github.com/carbon-language/carbon-lang/issues/971)\n\n#### Destructors\n\nA destructor for a class is custom code executed when the lifetime of a value of\nthat type ends. They are defined with `fn destroy` followed by either\n`[self: Self]` or `[ref self: Self]` (as is done with [methods](#methods)) and\nthe block of code in the class definition, as in:\n\n```carbon\nclass MyClass {\n  fn destroy[self: Self]() { ... }\n}\n```\n\nor:\n\n```carbon\nclass MyClass {\n  // Can modify `self` in the body.\n  fn destroy[ref self: Self]() { ... }\n}\n```\n\nThe destructor for a class is run before the destructors of its data members.\nThe data members are destroyed in reverse order of declaration. Derived classes\nare destroyed before their base classes.\n\nA destructor in an abstract or base class may be declared `virtual` like with\n[methods](#inheritance). Destructors in classes derived from one with a virtual\ndestructor must be declared with the `impl` keyword prefix. It is illegal to\ndelete an instance of a derived class through a pointer to a base class unless\nthe base class is declared `virtual` or `impl`. To delete a pointer to a\nnon-abstract base class when it is known not to point to a value with a derived\ntype, use `UnsafeDelete`.\n\n> References:\n>\n> -   [Classes: Destructors](classes.md#destructors)\n> -   Proposal\n>     [#1154: Destructors](https://github.com/carbon-language/carbon-lang/pull/1154)\n\n#### `const`\n\nFor every type `MyClass`, there is the type `const MyClass` such that:\n\n-   The data representation is the same, so a `MyClass*` value may be implicitly\n    converted to a `(const MyClass)*`.\n-   A `const MyClass` [reference expression](#expression-categories) may\n    automatically convert to a `MyClass` value expression, the same way that a\n    `MyClass` reference expression can.\n-   If member `x` of `MyClass` has type `T`, then member `x` of `const MyClass`\n    has type `const T`.\n-   While all of the member names in `MyClass` are also member names in\n    `const MyClass`, the effective API of a `const MyClass` reference expression\n    is a subset of `MyClass`, because only `ref` methods accepting a\n    `const Self` will be valid.\n\nNote that `const` binds more tightly than postfix-`*` for forming a pointer\ntype, so `const MyClass*` is equal to `(const MyClass)*`.\n\nThis example uses the definition of `Point` from the\n[\"methods\" section](#methods):\n\n```carbon\nvar origin: Point = {.x = 0, .y = 0};\n\n// ✅ Allowed conversion from `Point*` to\n// `const Point*`:\nlet p: const Point* = &origin;\n\n// ✅ Allowed conversion of `const Point` reference expression\n// to `Point` value expression.\nlet five: f32 = p->Distance(3, 4);\n\n// ❌ Error: mutating method `Offset` excluded\n// from `const Point` API.\np->Offset(3, 4);\n\n// ❌ Error: mutating method `AssignAdd.Op`\n// excluded from `const i32` API.\np->x += 2;\n```\n\n> References:\n>\n> -   [`const`-qualified types](values.md#const-qualified-types)\n> -   Proposal\n>     [#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)\n\n#### Unformed state\n\nTypes indicate that they support unformed states by\n[implementing a particular interface](#interfaces-and-implementations),\notherwise variables of that type must be explicitly initialized when they are\ndeclared.\n\nAn unformed state for an object is one that satisfies the following properties:\n\n-   Assignment from a fully formed value is correct using the normal assignment\n    implementation for the type.\n-   Destruction must be correct using the type's normal destruction\n    implementation.\n-   Destruction must be optional. The behavior of the program must be equivalent\n    whether the destructor is run or not for an unformed object, including not\n    leaking resources.\n\nA type might have more than one in-memory representation for the unformed state,\nand those representations may be the same as valid fully formed values for that\ntype. For example, all values are legal representations of the unformed state\nfor any type with a trivial destructor like `i32`. Types may define additional\ninitialization for the [hardened build mode](#build-modes). For example, this\ncauses integers to be set to `0` when in unformed state in this mode.\n\nAny operation on an unformed object _other_ than destruction or assignment from\na fully formed value is an error, even if its in-memory representation is that\nof a valid value for that type.\n\n> References:\n>\n> -   Proposal\n>     [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257)\n\n#### Move\n\nCarbon will allow types to define if and how they are moved. This can happen\nwhen returning a value from a function or by using the _move operator_ `~x`.\nThis leaves `x` in an [unformed state](#unformed-state) and returns its old\nvalue.\n\n> **Note:** This is provisional. The move operator was discussed but not\n> proposed in accepted proposal\n> [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257).\n\n#### Mixins\n\nMixins allow reuse with different trade-offs compared to\n[inheritance](#inheritance). Mixins focus on implementation reuse, such as might\nbe done using\n[CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) or\n[multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance) in\nC++.\n\n> **TODO:** The design for mixins is still under development. The details here\n> are provisional. The mixin use case was included in accepted proposal\n> [#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561).\n\n### Choice types\n\nA _choice type_ is a [tagged union](https://en.wikipedia.org/wiki/Tagged_union),\nthat can store different types of data in a storage space that can hold the\nlargest. A choice type has a name, and a list of cases separated by commas\n(`,`). Each case has a name and an optional parameter list.\n\n```carbon\nchoice IntResult {\n  Success(value: i32),\n  Failure(error: String),\n  Cancelled\n}\n```\n\nThe value of a choice type is one of the cases, plus the values of the\nparameters to that case, if any. A value can be constructed by naming the case\nand providing values for the parameters, if any:\n\n```carbon\nfn ParseAsInt(s: String) -> IntResult {\n  var r: i32 = 0;\n  for (c: i32 in s) {\n    if (not IsDigit(c)) {\n      // Equivalent to `IntResult.Failure(...)`\n      return .Failure(\"Invalid character\");\n    }\n    // ...\n  }\n  return .Success(r);\n}\n```\n\nChoice type values may be consumed using a [`match` statement](#match):\n\n```carbon\nmatch (ParseAsInt(s)) {\n  case .Success(value: i32) => {\n    return value;\n  }\n  case .Failure(error: String) => {\n    Display(error);\n  }\n  case .Cancelled => {\n    Terminate();\n  }\n}\n```\n\nThey can also represent an\n[enumerated type](https://en.wikipedia.org/wiki/Enumerated_type), if no\nadditional data is associated with the choices, as in:\n\n```carbon\nchoice LikeABoolean { False, True }\n```\n\n> References:\n>\n> -   [Sum types](sum_types.md)\n> -   Proposal\n>     [#157: Design direction for sum types](https://github.com/carbon-language/carbon-lang/pull/157)\n> -   Proposal\n>     [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)\n\n## Names\n\nNames are introduced by [declarations](#declarations-definitions-and-scopes) and\nare valid until the end of the scope in which they appear. Code may not refer to\nnames earlier in the source than they are declared. In executable scopes such as\nfunction bodies, names declared later are not found. In declarative scopes such\nas packages, classes, and interfaces, it is an error to refer to names declared\nlater, except that inline class member function bodies are\n[parsed as if they appeared after the class](#class-functions-and-factory-functions).\n\nA name in Carbon is formed from a sequence of letters, numbers, and underscores,\nand starts with a letter. We intend to follow\n[Unicode's Annex 31](https://unicode.org/reports/tr31/) in selecting valid\nidentifier characters, but a concrete set of valid characters has not been\nselected yet.\n\n> References:\n>\n> -   [Lexical conventions](lexical_conventions)\n> -   [Principle: Information accumulation](/docs/project/principles/information_accumulation.md)\n> -   Proposal\n>     [#142: Unicode source files](https://github.com/carbon-language/carbon-lang/pull/142)\n> -   Question-for-leads issue\n>     [#472: Open question: Calling functions defined later in the same file](https://github.com/carbon-language/carbon-lang/issues/472)\n> -   Proposal\n>     [#875: Principle: information accumulation](https://github.com/carbon-language/carbon-lang/pull/875)\n\n### Files, libraries, packages\n\n-   **Files** are grouped into libraries, which are in turn grouped into\n    packages. There are two kinds of files:\n    -   API files describe the interface of a library.\n    -   Implementation files implement part of the interface of a library.\n-   **Libraries** are the granularity of code reuse through imports.\n-   **Packages** are the unit of distribution.\n\nEach library must have exactly one API file. This file includes declarations for\nall public names of the library. Definitions for those declarations must be in\nsome file in the library, either the API file or an implementation file.\n\nEvery package has its own namespace. This means libraries within a package need\nto coordinate to avoid name conflicts, but not across packages.\n\n> References:\n>\n> -   [Code and name organization](code_and_name_organization)\n> -   Proposal\n>     [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)\n\n### Package declaration\n\nFiles start with an optional package declaration, consisting of:\n\n-   optionally, the `impl` modifier keyword, indicating the file is an\n    implementation file rather than an API file,\n-   optionally, the `package` keyword followed by an identifier specifying the\n    package name,\n-   optionally, the `library` keyword followed by a string with the library\n    name, and\n-   a terminating semicolon (`;`).\n\nFor example:\n\n```carbon\n// Package name is `Geometry`.\n// Library name is \"Shapes\".\n// This file is an API file, not an implementation file.\npackage Geometry library \"Shapes\";\n```\n\nParts of this declaration may be omitted:\n\n-   If the package keyword is not specified, as in `library \"Widgets\";`, the\n    file contributes to the `Main` package. No other package may import from the\n    `Main` package, and it cannot be named explicitly.\n\n-   If the library keyword is not specified, as in `package Geometry;`, this\n    file contributes to the default library.\n\n-   If both keywords are omitted, the package declaration must be omitted\n    entirely. In this case, the file is the API file for the default library of\n    the `Main` package, which cannot have any implementation files. This library\n    is used to define the entry point for the program, and tests and smaller\n    examples may choose to reside entirely within this library. No other library\n    can import this library even from within the default package.\n\nIf the default library of the `Main` package contains a function named `Run`,\nthat function is the program entry point. Otherwise, the program's entry point\nmay be defined in another language, such as by defining a C++ `main` function.\n\n> **Note:** Valid signatures for the entry point have not yet been decided.\n\n> References:\n>\n> -   [Code and name organization](code_and_name_organization)\n> -   Proposal\n>     [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)\n> -   Proposal\n>     [#2550: Simplified package declaration for the main package](https://github.com/carbon-language/carbon-lang/pull/2550)\n\n### Imports\n\nAfter the package declaration, files may include `import` declarations. The\n`import` keyword is followed by the package name, `library` followed by the\nlibrary name, or both. If the library is omitted, the default library for that\npackage is imported.\n\nAll `import` declarations must appear before all other non-`package`\ndeclarations in the file.\n\n#### Same-package imports\n\nThe package name must be omitted when importing a library from the current\npackage.\n\n```carbon\n// Import the \"Vertex\" library from the package containing this file.\nimport library \"Vertex\";\n```\n\nThe `import library ...` syntax adds all the public top-level names within the\ngiven library to the top-level scope of the current file as\n[`private`](#name-visibility) names, and similarly for names in\n[namespaces](#namespaces).\n\nEvery implementation file automatically imports the API file for its library.\nAttempting to perform an import of the current library is invalid.\n\n```\nimpl package MyPackage library \"Widgets\";\n\n// ❌ Error, this import is performed implicitly.\nimport MyPackage library \"Widgets\";\n```\n\nThe default library for a package does not have a string name, and is instead\nnamed with the `default` keyword.\n\n```carbon\n// Import the default library from the same package.\nimport library default;\n```\n\nIt is an error to use the `import library default;` syntax in the `Main`\npackage.\n\n#### Cross-package imports\n\nWhen the package name is specified, the `import` declaration imports a library\nfrom another package.\n\n```carbon\nimpl package MyPackage;\n\n// Import the \"Vector\" library from the `LinearAlgebra` package.\nimport LinearAlgebra library \"Vector\";\n\n// Import the default library from the `ArbitraryPrecision` package.\nimport ArbitraryPrecision;\n```\n\nThe syntax `import PackageName ...` introduces the name `PackageName` as a\n[`private`](#name-visibility) name naming the given package. Importing\nadditional libraries from that package makes additional members of `PackageName`\nvisible.\n\nIt is an error to specify the name of the current package. The package name must\nbe omitted when [importing from the same package](#same-package-imports).\n\nIt is an error to specify `library default` in a package-qualified import.\nInstead, omit the `library` portion of the declaration.\n\nIt is an error to specify the package name `Main`. Libraries in the `Main`\npackage can only be imported from within that package.\n\n> References:\n>\n> -   [Code and name organization](code_and_name_organization)\n> -   Proposal\n>     [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)\n> -   Proposal\n>     [#2550: Simplified package declaration for the main package](https://github.com/carbon-language/carbon-lang/pull/2550)\n\n### Name visibility\n\nThe names visible from an imported library are determined by these rules:\n\n-   Declarations in an API file are by default _public_, which means visible to\n    any file that imports that library. This matches class members, which are\n    also [default public](#access-control).\n-   A `private` prefix on a declaration in an API file makes the name _library\n    private_. This means the name is visible in the file and all implementation\n    files for the same library.\n-   The visibility of a name is determined by its first declaration, considering\n    API files before implementation files. The `private` prefix is only allowed\n    on the first declaration.\n-   A name declared in an implementation file and not the corresponding API file\n    is _file private_, meaning visible in just that file. Its first declaration\n    must be marked with a `private` prefix. **TODO:** This needs to be finalized\n    in a proposal to resolve inconsistency between\n    [#665](https://github.com/carbon-language/carbon-lang/issues/665#issuecomment-914661914)\n    and [#1136](https://github.com/carbon-language/carbon-lang/issues/1136).\n-   Private names don't conflict with names outside the region they're private\n    to: two different libraries can have different private names `foo` without\n    conflict, but a private name conflicts with a public name in the same scope.\n\nAt most one API file in a package transitively used in a program may declare a\ngiven name public.\n\n> References:\n>\n> -   [Exporting entities from an API file](code_and_name_organization/README.md#exporting-entities-from-an-api-file)\n> -   Question-for-leads issue\n>     [#665: `private` vs `public` _syntax_ strategy, as well as other visibility tools like `external`/`api`/etc.](https://github.com/carbon-language/carbon-lang/issues/665)\n> -   Proposal\n>     [#752: api file default public](https://github.com/carbon-language/carbon-lang/pull/752)\n> -   Proposal\n>     [#931: Generic impls access (details 4)](https://github.com/carbon-language/carbon-lang/pull/931)\n> -   Question-for-leads issue\n>     [#1136: what is the top-level scope in a source file, and what names are found there?](https://github.com/carbon-language/carbon-lang/issues/1136)\n\n### Package scope\n\nThe top-level scope in a file is the scope of the package. This means:\n\n-   Within this scope (and its sub-namespaces), all visible names from the same\n    package appear. This includes names from the same file, names from the API\n    file of a library when inside an implementation file, and names from\n    imported libraries of the same package.\n-   In scopes where package members might have a name conflict with something\n    else, the syntax `package.Foo` can be used to name the `Foo` member of the\n    current package.\n\nIn this example, the names `F` and `P` are used in a scope where they could mean\ntwo different things, and\n[qualifications are needed to disambiguate](#name-lookup):\n\n```carbon\nimport P;\nfn F();\nclass C {\n  fn F();\n  class P {\n    fn H();\n  }\n  fn G() {\n    // ❌ Error: ambiguous whether `F` means\n    // `package.F` or `package.C.F`.\n    F();\n   // ✅ Allowed: fully qualified\n    package.F();\n    package.C.F();\n    // ✅ Allowed: unambiguous\n    C.F();\n    // ❌ Error: ambiguous whether `P` means\n    // `package.P` or `package.C.P`.\n    P.H();\n    // ✅ Allowed\n    package.P.H();\n    package.C.P.H();\n    C.P.H();\n  }\n}\n```\n\n> References:\n>\n> -   [Code and name organization](code_and_name_organization)\n> -   Proposal\n>     [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)\n> -   Proposal\n>     [#752: api file default public](https://github.com/carbon-language/carbon-lang/pull/752)\n> -   Question-for-leads issue\n>     [#1136: what is the top-level scope in a source file, and what names are found there?](https://github.com/carbon-language/carbon-lang/issues/1136)\n\n### Namespaces\n\nA `namespace` declaration defines a name that may be used as a prefix of names\ndeclared afterward. When defining a member of a namespace, other members of that\nnamespace are considered in scope and may be found by\n[name lookup](#name-lookup) without the namespace prefix. In this example,\npackage `P` defines some of its members inside a namespace `N`:\n\n```carbon\npackage P;\n\n// Defines namespace `N` within the current package.\nnamespace N;\n\n// Defines namespaces `M` and `M.L`.\nnamespace M.L;\n\nfn F();\n// ✅ Allowed: Declares function `G` in namespace `N`.\nprivate fn N.G();\n// ❌ Error: `Bad` hasn't been declared.\nfn Bad.H();\n\nfn J() {\n  // ❌ Error: No `package.G`\n  G();\n}\n\nfn N.K() {\n  // ✅ Allowed: Looks in both `package` and `package.N`.\n  // Finds `package.F` and `package.N.G`.\n  F();\n  G();\n}\n\n// ✅ Allowed: Declares function `R` in namespace `M.L`.\nfn M.L.R();\n// ✅ Allowed: Declares function `Q` in namespace `M`.\nfn M.Q();\n```\n\nAnother package importing `P` can refer to the public members of that namespace\nby prefixing with the package name `P` followed by the namespace:\n\n```carbon\nimport P;\n\n// ✅ Allowed: `F` is public member of `P`.\nP.F();\n// ❌ Error: `N.G` is a private member of `P`.\nP.N.G();\n// ✅ Allowed: `N.K` is public member of `P`.\nP.N.K();\n// ✅ Allowed: `M.L.R` is public member of `P`.\nP.M.L.R();\n// ✅ Allowed: `M.Q` is public member of `P`.\nP.M.Q();\n```\n\n> References:\n>\n> -   [\"Namespaces\" in \"Code and name organization\"](code_and_name_organization/README.md#namespaces)\n> -   [\"Package and namespace members\" in \"Qualified names and member access\"](expressions/member_access.md#package-and-namespace-members)\n> -   Proposal\n>     [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)\n> -   Proposal\n>     [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n> -   Question-for-leads issue\n>     [#1136: what is the top-level scope in a source file, and what names are found there?](https://github.com/carbon-language/carbon-lang/issues/1136)\n\n### Naming conventions\n\nOur naming conventions are:\n\n-   For idiomatic Carbon code:\n    -   `UpperCamelCase` will be used when the named entity cannot have a\n        dynamically varying value. For example, functions, namespaces, or\n        compile-time constant values. Note that\n        [`virtual` methods](#inheritance) are named the same way to be\n        consistent with other functions and methods.\n    -   `lower_snake_case` will be used when the named entity's value won't be\n        known until runtime, such as for variables.\n-   For Carbon-provided features:\n    -   Keywords and type literals will use `lower_snake_case`.\n    -   Other code will use the conventions for idiomatic Carbon code.\n\n> References:\n>\n> -   [Naming conventions](naming_conventions.md)\n> -   Proposal\n>     [#861: Naming conventions](https://github.com/carbon-language/carbon-lang/pull/861)\n\n### Aliases\n\n`alias` declares a name as equivalent to another name, for example:\n\n```carbon\nalias NewName = SomePackage.OldName;\n```\n\nNote that the right-hand side of the equal sign (`=`) is a name not a value, so\n`alias four = 4;` is not allowed. This allows `alias` to work with entities like\nnamespaces, which aren't values in Carbon.\n\nThis can be used during an incremental migration when changing a name. For\nexample, `alias` would allow you to have two names for a data field in a class\nwhile clients were migrated between the old name and the new name.\n\n```carbon\nclass MyClass {\n  var new_name: String;\n  alias old_name = new_name;\n}\n\nvar x: MyClass = {.new_name = \"hello\"};\nCarbon.Assert(x.old_name == \"hello\");\n```\n\nAnother use is to include a name in a public API. For example, `alias` may be\nused to include a name from an interface implementation as a member of a class\nor [named constraint](generics/details.md#named-constraints), possibly renamed:\n\n```carbon\nclass ContactInfo {\n  impl as Printable;\n  impl as ToPrinterDevice;\n  alias PrintToScreen = Printable.Print;\n  alias PrintToPrinter = ToPrinterDevice.Print;\n  ...\n}\n```\n\n> References:\n>\n> -   [Aliases](aliases.md)\n> -   [\"Aliasing\" in \"Code and name organization\"](code_and_name_organization/README.md#aliasing)\n> -   [`alias` a name from an interface impl](generics/details.md#avoiding-name-collisions)\n> -   [`alias` a name in a named constraint](generics/details.md#named-constraints)\n> -   Proposal\n>     [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)\n> -   Proposal\n>     [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n> -   Question-for-leads issue\n>     [#749: Alias syntax](https://github.com/carbon-language/carbon-lang/issues/749)\n> -   Proposal\n>     [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n\n### Name lookup\n\nThe general principle of Carbon name lookup is that we look up names in all\nrelevant scopes, and report an error if the name is found to refer to more than\none different entity. So Carbon requires disambiguation by adding qualifiers\ninstead of doing any\n[shadowing](https://en.wikipedia.org/wiki/Variable_shadowing) of names.\n[Member name lookup](expressions/member_access.md) follows a similar philosophy.\nFor an example, see [the \"package scope\" section](#package-scope).\n\nUnqualified name lookup walks the semantically-enclosing scopes, not only the\nlexically-enclosing ones. So when a lookup is performed within\n`fn MyNamespace.MyClass.MyNestedClass.MyFunction()`, we will look in\n`MyNestedClass`, `MyClass`, `MyNamespace`, and the package scope, even when the\nlexically-enclosing scope is the package scope. This means that the definition\nof a method will look for names in the class' scope even if it is written\nlexically out of line:\n\n```\nclass C {\n  fn F();\n  fn G();\n}\nfn C.G() {\n  // ✅ Allowed: resolves to `package.C.F`.\n  F();\n}\n```\n\nCarbon also rejects cases that would be invalid if all declarations in the file,\nincluding ones appearing later, were visible everywhere, not only after their\npoint of appearance:\n\n```carbon\nclass C {\n  fn F();\n  fn G();\n}\nfn C.G() {\n  F();\n}\n// Error: use of `F` in `C.G` would be ambiguous\n// if this declaration was earlier.\nfn F();\n```\n\n> References:\n>\n> -   [Name lookup](name_lookup.md)\n> -   [\"Qualified names and member access\" section of \"Expressions\"](expressions/README.md#qualified-names-and-member-access)\n> -   [Qualified names and member access](expressions/member_access.md)\n> -   [Principle: Information accumulation](/docs/project/principles/information_accumulation.md)\n> -   Proposal\n>     [#875: Principle: information accumulation](https://github.com/carbon-language/carbon-lang/pull/875)\n> -   Proposal\n>     [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n> -   Question-for-leads issue\n>     [#1136: what is the top-level scope in a source file, and what names are found there?](https://github.com/carbon-language/carbon-lang/issues/1136)\n\n#### Name lookup for common types\n\nCommon types that we expect to be used universally will be provided for every\nfile are made available as if there was a special \"prelude\" package that was\nimported automatically into every API file. Dedicated type literal syntaxes like\n`i32` and `bool` refer to types defined within this package, based on the\n[\"all APIs are library APIs\" principle](/docs/project/principles/library_apis_only.md).\n\n> **TODO:** Prelude provisionally imports the `Carbon` package which includes\n> common facilities, like `Print` and the interfaces for operator overloading.\n\n> References:\n>\n> -   [Name lookup](name_lookup.md)\n> -   [Principle: All APIs are library APIs](/docs/project/principles/library_apis_only.md)\n> -   Question-for-leads issue\n>     [#750: Naming conventions for Carbon-provided features](https://github.com/carbon-language/carbon-lang/issues/750)\n> -   Question-for-leads issue\n>     [#1058: How should interfaces for core functionality be named?](https://github.com/carbon-language/carbon-lang/issues/1058)\n> -   Proposal\n>     [#1280: Principle: All APIs are library APIs](https://github.com/carbon-language/carbon-lang/pull/1280)\n\n## Generics\n\nGenerics allow Carbon constructs like [functions](#functions) and\n[classes](#classes) to be written with compile-time parameters to generalize\nacross different values of those parameters. For example, this `Min` function\nhas a type\\* parameter `T` that can be any type that implements the `Ordered`\ninterface.\n\n```carbon\nfn Min[T:! Ordered](x: T, y: T) -> T {\n  // Can compare `x` and `y` since they have\n  // type `T` known to implement `Ordered`.\n  return if x <= y then x else y;\n}\n\nvar a: i32 = 1;\nvar b: i32 = 2;\n// `T` is deduced to be `i32`\nAssert(Min(a, b) == 1);\n// `T` is deduced to be `String`\nAssert(Min(\"abc\", \"xyz\") == \"abc\");\n```\n\nSince the `T` parameter is in the deduced parameter list in square brackets\n(`[`...`]`) before the explicit parameter list in parentheses (`(`...`)`), the\nvalue of `T` is determined from the types of the explicit arguments instead of\nbeing passed as a separate explicit argument.\n\n(\\*) Note: `T` here may be thought of as a type parameter, but its values are\nactually [facets](generics/terminology.md#facet), which are\n[values usable as types](#values-usable-as-types). The `T` in this example is\nnot itself a type.\n\n> References: **TODO:** Revisit\n>\n> -   [Generics: Overview](generics/overview.md)\n> -   Proposal\n>     [#524: Generics overview](https://github.com/carbon-language/carbon-lang/pull/524)\n> -   Proposal\n>     [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n> -   Proposal\n>     [#950: Generic details 6: remove facets](https://github.com/carbon-language/carbon-lang/pull/950)\n> -   Proposal\n>     [#2360: Types are values of type `type`](https://github.com/carbon-language/carbon-lang/pull/2360)\n\n### Checked and template parameters\n\nThe `:!` marks it as a compile-time binding pattern, and so `T` is a\ncompile-time parameter. Compile-time parameters may either be _checked_ or\n_template_, and default to checked.\n\n\"Checked\" here means that the body of `Min` is type checked when the function is\ndefined, independent of the specific values `T` is instantiated with, and name\nlookup is delegated to the constraint on `T` (`Ordered` in this case). This type\nchecking is equivalent to saying the function would pass type checking given any\ntype `T` that implements the `Ordered` interface. Subsequent calls to `Min` only\nneed to check that the deduced value of `T` implements `Ordered`.\n\nThe parameter could alternatively be declared to be a _template_ generic\nparameter by prefixing with the `template` keyword, as in `template T:! type`.\n\n```carbon\nfn Convert[template T:! type](source: T, template U:! type) -> U {\n  var converted: U = source;\n  return converted;\n}\n\nfn Foo(i: i32) -> f32 {\n  // Instantiates with the `T` implicit argument set to `i32` and the `U`\n  // explicit argument set to `f32`, then calls with the runtime value `i`.\n  return Convert(i, f32);\n}\n```\n\nA template parameter can still use a constraint. The `Min` example could have\nbeen declared as:\n\n```carbon\nfn TemplatedMin[template T:! Ordered](x: T, y: T) -> T {\n  return if x <= y then x else y;\n}\n```\n\nCarbon templates follow the same fundamental paradigm as\n[C++ templates](<https://en.wikipedia.org/wiki/Template_(C%2B%2B)>): they are\ninstantiated when called, resulting in late type checking, duck typing, and lazy\nbinding.\n\nOne difference from C++ templates, Carbon template instantiation is not\ncontrolled by the SFINAE rule of C++\n([1](https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error),\n[2](https://en.cppreference.com/w/cpp/language/sfinae)) but by explicit\nconstraints declared in the function signature and evaluated at compile-time.\n\n> **TODO:** The design for template constraints is still under development.\n\nThe [expression phase](#expression-phases) of a checked parameter is a symbolic\nconstant whereas the expression phase of a template parameter is template\nconstant. A binding pattern using `:!` is a _compile-time binding pattern_; more\nspecifically a _template binding pattern_ if it uses `template`, and a _symbolic\nbinding pattern_ if it does not.\n\nAlthough checked generics are generally preferred, templates enable translation\nof code between C++ and Carbon, and address some cases where the type checking\nrigor of checked generics is problematic.\n\n> References:\n>\n> -   [Templates](templates.md)\n> -   Proposal\n>     [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n> -   Question-for-leads issue\n>     [#949: Constrained template name lookup](https://github.com/carbon-language/carbon-lang/issues/949)\n> -   Proposal\n>     [#2138: Checked and template generic terminology](https://github.com/carbon-language/carbon-lang/pull/2138)\n> -   Proposal\n>     [#2200: Template generics](https://github.com/carbon-language/carbon-lang/pull/2200)\n\n### Interfaces and implementations\n\n_Interfaces_ specify a set of requirements that a type might satisfy. Interfaces\nact both as constraints on types a caller might supply and capabilities that may\nbe assumed of types that satisfy that constraint.\n\n```carbon\ninterface Printable {\n  // Inside an interface definition `Self` means\n  // \"the type implementing this interface\".\n  fn Print[self: Self]();\n}\n```\n\nAn interface is kind of [facet type](generics/terminology.md#facet-type), and\nthe values of this type are [facets](generics/terminology.md#facet), which are\n[values usable as types](#values-usable-as-types).\n\nIn addition to function requirements, interfaces can contain:\n\n-   [requirements that other interfaces be implemented](generics/details.md#interface-requiring-other-interfaces)\n    or\n    [interfaces that this interface extends](generics/details.md#interface-extension)\n-   [associated facets](generics/details.md#associated-facets) and other\n    [associated constants](generics/details.md#associated-constants)\n-   [interface defaults](generics/details.md#interface-defaults)\n-   [`final` interface members](generics/details.md#final-members)\n\nTypes only implement an interface if there is an explicit `impl` declaration\nthat they do. Simply having a `Print` function with the right signature is not\nsufficient.\n\n```carbon\n// Class `Text` does not implement the `Printable` interface.\nclass Text {\n  fn Print[self: Self]();\n}\n\nclass Circle {\n  var radius: f32;\n\n  // This `impl` declaration establishes that `Circle` implements\n  // `Printable`.\n  impl as Printable {\n    fn Print[self: Self]() {\n      Core.Print(\"Circle with radius: {0}\", self.radius);\n    }\n  }\n}\n```\n\nIn this case, `Print` is not a direct member of `Circle`, but:\n\n-   `Circle` may be passed to functions expecting a type that implements\n    `Printable`.\n\n    ```carbon\n    fn GenericPrint[T:! Printable](x: T) {\n      // Look up into `T` delegates to `Printable`, so this\n      // finds `Printable.Print`:\n      x.Print();\n    }\n    ```\n\n-   The members of `Printable` such as `Print` may be called using compound\n    member access syntax ([1](expressions/member_access.md),\n    [2](generics/details.md#qualified-member-names-and-compound-member-access))\n    to qualify the name of the member, as in:\n\n    ```carbon\n    fn CirclePrint(c: Circle) {\n      // Succeeds, even though `c.Print()` would not.\n      c.(Printable.Print)();\n    }\n    ```\n\nTo include the members of the interface as direct members of the type, use the\n[`extend`](generics/details.md#extend-impl) keyword, as in\n`extend impl as Printable`. This is only permitted on `impl` declarations in the\nbody of a class definition.\n\nWithout `extend`, implementations don't have to be in the same library as the\ntype definition, subject to the [orphan rule](generics/details.md#orphan-rule)\nfor [coherence](generics/terminology.md#coherence).\n\nInterfaces and implementations may be\n[forward declared](generics/details.md#forward-declarations-and-cyclic-references)\nby replacing the definition scope in curly braces (`{`...`}`) with a semicolon.\n\n> References:\n>\n> -   [Generics: Interfaces](generics/details.md#interfaces)\n> -   [Generics: Implementing interfaces](generics/details.md#implementing-interfaces)\n> -   Proposal\n>     [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n> -   Proposal\n>     [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n> -   Proposal\n>     [#624: Coherence: terminology, rationale, alternatives considered](https://github.com/carbon-language/carbon-lang/pull/624)\n> -   Proposal\n>     [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n> -   Proposal\n>     [#990: Generics details 8: interface default and final members](https://github.com/carbon-language/carbon-lang/pull/990)\n> -   Proposal\n>     [#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084)\n> -   Question-for-leads issue\n>     [#1132: How do we match forward declarations with their definitions?](https://github.com/carbon-language/carbon-lang/issues/1132)\n> -   Proposal\n>     [#2360: Types are values of type `type`](https://github.com/carbon-language/carbon-lang/pull/2360)\n> -   Proposal\n>     [#2760: Consistent `class` and `interface` syntax](https://github.com/carbon-language/carbon-lang/pull/2760)\n\n### Combining constraints\n\nA function can require type arguments to implement multiple interfaces (or other\nfacet types) by combining them using an ampersand (`&`):\n\n```carbon\nfn PrintMin[T:! Ordered & Printable](x: T, y: T) {\n  // Can compare since type `T` implements `Ordered`.\n  if (x <= y) {\n    // Can call `Print` since type `T` implements `Printable`.\n    x.Print();\n  } else {\n    y.Print();\n  }\n}\n```\n\nThe body of the function may call functions that are in either interface, except\nfor names that are members of both. In that case, use the compound member access\nsyntax ([1](expressions/member_access.md),\n[2](generics/details.md#qualified-member-names-and-compound-member-access)) to\nqualify the name of the member, as in:\n\n```carbon\nfn DrawTies[T:! Renderable & GameResult](x: T) {\n  if (x.(GameResult.Draw)()) {\n    x.(Renderable.Draw)();\n  }\n}\n```\n\n> References:\n>\n> -   [Combining interfaces by anding facet types](generics/details.md#combining-interfaces-by-anding-facet-types)\n> -   Question-for-leads issue\n>     [#531: Combine interfaces with `+` or `&`](https://github.com/carbon-language/carbon-lang/issues/531)\n> -   Proposal\n>     [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n\n### Template name lookup\n\nMember lookup into a template parameter is done in the actual value provided by\nthe caller, _in addition_ to any constraints. This means member name lookup and\ntype checking for anything [dependent](generics/terminology.md#dependent-names)\non the template parameter can't be completed until the template is instantiated\nwith a specific concrete type. When the constraint is just `type`, this gives\nsemantics similar to C++ templates.\n\n```carbon\nclass Game {\n  fn Draw[self: Self]() -> bool;\n  impl as Renderable {\n    fn Draw[self: Self]();\n  }\n}\n\nfn TemplateDraw[template T:! type](x: T) {\n  // Calls `Game.Draw` when `T` is `Game`:\n  x.Draw();\n}\n\nfn ConstrainedTemplateDraw[template T:! Renderable](x: T) {\n  // ❌ Error when `T` is `Game`: Finds both `T.Draw` and\n  // `Renderable.Draw`, and they are different.\n  x.Draw();\n}\n\nfn CheckedGenericDraw[T:! Renderable](x: T) {\n  // Always calls `Renderable.Draw`, even when `T` is `Game`:\n  x.Draw();\n}\n```\n\nThis allows a safe transition from template to checked generics. Constraints can\nbe added incrementally, with the compiler verifying that the semantics stay the\nsame. If adding the constraint would change which function gets called, an error\nis triggered, as in `ConstrainedTemplateDraw` from the example. Once all\nconstraints have been added, it is safe to remove the word `template` to switch\nto a checked parameter.\n\n> References:\n>\n> -   Proposal\n>     [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n> -   Proposal\n>     [#2200: Template generics](https://github.com/carbon-language/carbon-lang/pull/2200)\n\n### Associated constants\n\nAn associated constant is a member of an interface whose value is determined by\nthe implementation of that interface for a specific type. These values are set\nto compile-time values in implementations, and so use the\n[`:!` compile-time binding pattern syntax](#checked-and-template-parameters)\ninside a [`let` declaration](#constant-let-declarations) without an initializer.\nThis allows types in the signatures of functions in the interface to vary. For\nexample, an interface describing a\n[stack](<https://en.wikipedia.org/wiki/Stack_(abstract_data_type)>) might use an\nassociated constant to represent the type of elements stored in the stack.\n\n```\ninterface StackInterface {\n  let ElementType:! Movable;\n  fn Push[ref self: Self](value: ElementType);\n  fn Pop[ref self: Self]() -> ElementType;\n  fn IsEmpty[self: Self]() -> bool;\n}\n```\n\nThen different types implementing `StackInterface` can specify different values\nfor the `ElementType` member of the interface using a `where` clause:\n\n```carbon\nclass IntStack {\n  extend impl as StackInterface where .ElementType = i32 {\n    fn Push[ref self: Self](value: i32);\n    // ...\n  }\n}\n\nclass FruitStack {\n  extend impl as StackInterface where .ElementType = Fruit {\n    fn Push[ref self: Self](value: Fruit);\n    // ...\n  }\n}\n```\n\n> References:\n>\n> -   [Generics: Associated constants](generics/details.md#associated-constants)\n> -   Proposal\n>     [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n> -   Proposal\n>     [#1013: Generics: Set associated constants using `where` constraints](https://github.com/carbon-language/carbon-lang/pull/1013)\n\n### Generic entities\n\nMany Carbon entities, not just functions, may be made generic by adding\n[checked or template parameters](#checked-and-template-parameters).\n\n#### Generic Classes\n\nClasses may be defined with an optional explicit parameter list. All parameters\nto a class must be compile-time, and so defined with `:!`, either with or\nwithout the `template` prefix. For example, to define a stack that can hold\nvalues of any type `T`:\n\n```carbon\nclass Stack(T:! type) {\n  fn Push[ref self: Self](value: T);\n  fn Pop[ref self: Self]() -> T;\n\n  var storage: Array(T);\n}\n\nvar int_stack: Stack(i32);\n```\n\nIn this example:\n\n-   `Stack` is a type parameterized by a type `T`.\n-   `T` may be used within the definition of `Stack` anywhere a normal type\n    would be used.\n-   `Array(T)` instantiates generic type `Array` with its argument set to `T`.\n-   `Stack(i32)` instantiates `Stack` with `T` set to `i32`.\n\nThe values of type parameters are part of a type's value, and so may be deduced\nin a function call, as in this example:\n\n```carbon\nfn PeekTopOfStack[T:! type](s: Stack(T)*) -> T {\n  var top: T = s->Pop();\n  s->Push(top);\n  return top;\n}\n\n// `int_stack` has type `Stack(i32)`, so `T` is deduced to be `i32`:\nPeekTopOfStack(&int_stack);\n```\n\n> References:\n>\n> -   [Generic or parameterized types](generics/details.md#parameterized-types)\n> -   Proposal\n>     [#1146: Generic details 12: parameterized types](https://github.com/carbon-language/carbon-lang/pull/1146)\n\n#### Generic choice types\n\n[Choice types](#choice-types) may be parameterized similarly to classes:\n\n```carbon\nchoice Result(T:! type, Error:! type) {\n  Success(value: T),\n  Failure(error: Error)\n}\n```\n\n#### Generic interfaces\n\nInterfaces are always parameterized by a `Self` type, but in some cases they\nwill have additional parameters.\n\n```carbon\ninterface AddWith(U:! type);\n```\n\nInterfaces without parameters may only be implemented once for a given type, but\na type can have distinct implementations of `AddWith(i32)` and\n`AddWith(BigInt)`.\n\nParameters to an interface _determine_ which implementation is selected for a\ntype, in contrast to [associated constants](#associated-constants) which are\n_determined by_ the implementation of an interface for a type.\n\n> References:\n>\n> -   [Generic or parameterized interfaces](generics/details.md#parameterized-interfaces)\n> -   Proposal\n>     [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n\n#### Generic implementations\n\nAn `impl` declaration may be parameterized by adding `forall [`_compile-time\nparameter list_`]` after the `impl` keyword introducer, as in:\n\n```carbon\nimpl forall [T:! Printable] Vector(T) as Printable;\nimpl forall [Key:! Hashable, Value:! type]\n    HashMap(Key, Value) as Has(Key);\nimpl forall [T:! Ordered] T as PartiallyOrdered;\nimpl forall [T:! ImplicitAs(i32)] BigInt as AddWith(T);\nimpl forall [U:! type, T:! As(U)]\n    Optional(T) as As(Optional(U));\n```\n\nGeneric implementations can create a situation where multiple `impl` definitions\napply to a given type and interface query. The\n[specialization](generics/details.md#lookup-resolution-and-specialization) rules\npick which definition is selected. These rules ensure:\n\n-   Implementations have [coherence](generics/terminology.md#coherence), so the\n    same implementation is always selected for a given query.\n-   Libraries will work together as long as they pass their separate checks.\n-   A generic function can assume that some impl will be successfully selected\n    if it can see an impl that applies, even though another more-specific impl\n    may be selected.\n\nImplementations may be marked\n[`final`](generics/details.md#final-impl-declarations) to indicate that they may\nnot be specialized, subject to\n[some restrictions](generics/details.md#libraries-that-can-contain-a-final-impl).\n\n> References:\n>\n> -   [Generic or parameterized impl declarationss](generics/details.md#parameterized-impl-declarations)\n> -   Proposal\n>     [#624: Coherence: terminology, rationale, alternatives considered](https://github.com/carbon-language/carbon-lang/pull/624)\n> -   Proposal\n>     [#920: Generic parameterized impls (details 5)](https://github.com/carbon-language/carbon-lang/pull/920)\n> -   Proposal\n>     [#983: Generics details 7: final impls](https://github.com/carbon-language/carbon-lang/pull/983)\n> -   Question-for-leads issue\n>     [1192: Parameterized impl syntax](https://github.com/carbon-language/carbon-lang/issues/1192)\n> -   Proposal\n>     [#1327: Generics: `impl forall`](https://github.com/carbon-language/carbon-lang/pull/1327)\n\n### Other features\n\nCarbon generics have a number of other features, including:\n\n-   [Named constraints](generics/details.md#named-constraints) may be used to\n    disambiguate when combining two interfaces that have name conflicts. Named\n    constraints define facet types, and may be implemented and otherwise used in\n    place of an interface.\n-   [Template constraints](generics/details.md#named-constraints) are a kind of\n    named constraint that can contain structural requirements. For example, a\n    template constraint could match any type that has a function with a specific\n    name and signature without any explicit declaration that the type implements\n    the constraint. Template constraints may only be used as requirements for\n    template parameters.\n-   An [adapter type](generics/details.md#adapting-types) is a type with the\n    same data representation as an existing type, so you may cast between the\n    two types, but can implement different interfaces or implement interfaces\n    differently.\n-   Additional requirements can be placed on the associated facets of an\n    interface using\n    [`where` constraints](generics/details.md#where-constraints).\n-   [Implied constraints](generics/details.md#implied-constraints) allow some\n    constraints to be deduced and omitted from a function signature.\n-   _Planned_ [dynamic erased types](generics/details.md#runtime-type-fields)\n    can hold any value with a type implementing an interface, and allow the\n    functions in that interface to be called using\n    [dynamic dispatch](https://en.wikipedia.org/wiki/Dynamic_dispatch), for some\n    interfaces marked \"`dyn`-safe\". **Note:** Provisional.\n-   _Planned_ [variadics](generics/details.md#variadic-arguments) supports\n    variable-length parameter lists. **Note:** Provisional.\n\n> References:\n>\n> -   [Generics details](generics/details.md)\n> -   Proposal\n>     [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n> -   Proposal\n>     [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n\n> -   Proposal\n>     [#818: Constraints for generics (generics details 3)](https://github.com/carbon-language/carbon-lang/pull/818)\n\n### Generic type equality and `observe` declarations\n\nDetermining whether two types must be equal in a checked-generic context is in\ngeneral undecidable, as\n[has been shown in Swift](https://forums.swift.org/t/swift-type-checking-is-undecidable/39024).\n\nTo make compilation fast, the Carbon compiler will limit its search to a depth\nof 1, only identifying types as equal if there is an explicit declaration that\nthey are equal in the code, such as in a\n[`where` constraint](generics/details.md#where-constraints). There will be\nsituations where two types must be equal as the result of combining these facts,\nbut the compiler will return a type error since it did not realize they are\nequal due to the limit of the search. An\n[`observe`...`==` declaration](generics/details.md#observe-declarations) may be\nadded to describe how two types are equal, allowing more code to pass type\nchecking.\n\nAn `observe` declaration showing types are equal can increase the set of\ninterfaces the compiler knows that a type implements. It is also possible that\nknowing a type implements one interface implies that it implements another, from\nan\n[interface requirement](generics/details.md#interface-requiring-other-interfaces)\nor [generic implementation](#generic-implementations). An `observe`...`impls`\ndeclaration may be used to\n[observe that a type implements an interface](generics/details.md#observing-a-type-implements-an-interface).\n\n> References:\n>\n> -   [Generics: `observe` declarations](generics/details.md#observe-declarations)\n> -   [Generics: Observing a type implements an interface](generics/details.md#observing-a-type-implements-an-interface)\n> -   Proposal\n>     [#818: Constraints for generics (generics details 3)](https://github.com/carbon-language/carbon-lang/pull/818)\n> -   Proposal\n>     [#1088: Generic details 10: interface-implemented requirements](https://github.com/carbon-language/carbon-lang/pull/1088)\n\n### Operator overloading\n\nUses of an operator in an [expression](#expressions) is translated into a call\nto a method of an interface. For example, if `x` has type `T` and `y` has type\n`U`, then `x + y` is translated into a call to `x.(AddWith(U).Op)(y)`. So\noverloading of the `+` operator is accomplished by implementing interface\n`AddWith(U)` for type `T`. In order to support\n[implicit conversion](expressions/implicit_conversions.md) of the first operand\nto type `T` and the second argument to type `U`, add the `like` keyword to both\ntypes in the `impl` declaration, as in:\n\n```carbon\nimpl like T as AddWith(like U) where .Result = V {\n  // `Self` is `T` here\n  fn Op[self: Self](other: U) -> V { ... }\n}\n```\n\nWhen the operand types and result type are all the same, this is equivalent to\nimplementing the `Add` interface:\n\n```carbon\nimpl T as Add {\n  fn Op[self: Self](other: Self) -> Self { ... }\n}\n```\n\nThe interfaces that correspond to each operator are given by:\n\n-   [Arithmetic](expressions/arithmetic.md#extensibility):\n    -   `-x`: `Negate`\n    -   `x + y`: `Add` or `AddWith(U)`\n    -   `x - y`: `Sub` or `SubWith(U)`\n    -   `x * y`: `Mul` or `MulWith(U)`\n    -   `x / y`: `Div` or `DivWith(U)`\n    -   `x % y`: `Mod` or `ModWith(U)`\n-   [Bitwise and shift operators](expressions/bitwise.md#extensibility):\n    -   `^x`: `BitComplement`\n    -   `x & y`: `BitAnd` or `BitAndWith(U)`\n    -   `x | y`: `BitOr` or `BitOrWith(U)`\n    -   `x ^ y`: `BitXor` or `BitXorWith(U)`\n    -   `x << y`: `LeftShift` or `LeftShiftWith(U)`\n    -   `x >> y`: `RightShift` or `RightShiftWith(U)`\n-   Comparison:\n    -   `x == y`, `x != y` overloaded by implementing\n        [`Eq` or `EqWith(U)`](expressions/comparison_operators.md#equality)\n    -   `x < y`, `x > y`, `x <= y`, `x >= y` overloaded by implementing\n        [`Ordered` or `OrderedWith(U)`](expressions/comparison_operators.md#ordering)\n-   Conversion:\n    -   `x as U` is rewritten to use the\n        [`As(U)`](expressions/as_expressions.md#extensibility) interface\n    -   Implicit conversions use\n        [`ImplicitAs(U)`](expressions/implicit_conversions.md#extensibility)\n-   Indexing:\n    -   `x[y]` is rewritten to use the\n        [`IndexWith` or `IndirectIndexWith`](expressions/indexing.md) interface.\n-   **TODO:** Dereference: `*p`\n-   **TODO:** [Move](#move): `~x`\n-   **TODO:** Function call: `f(4)`\n\nThe\n[logical operators can not be overloaded](expressions/logical_operators.md#overloading).\n\nOperators that result in [reference expressions](#expression-categories), such\nas dereferencing `*p` and indexing `a[3]`, have interfaces that return the\naddress of the value. Carbon automatically dereferences the pointer to form the\nreference expression.\n\nOperators that can take multiple arguments, such as function calling operator\n`f(4)`, have a [variadic](generics/details.md#variadic-arguments) parameter\nlist. **TODO: Variadics are still provisional.**\n\nWhether and how a value supports other operations, such as being copied,\nswapped, or set into an [unformed state](#unformed-state), is also determined by\nimplementing corresponding interfaces for the value's type.\n\n> References:\n>\n> -   [Operator overloading](generics/details.md#operator-overloading)\n> -   Proposal\n>     [#702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702)\n> -   Proposal\n>     [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820)\n> -   Proposal\n>     [#845: as expressions](https://github.com/carbon-language/carbon-lang/pull/845)\n> -   Question-for-leads issue\n>     [#1058: How should interfaces for core functionality be named?](https://github.com/carbon-language/carbon-lang/issues/1058)\n> -   Proposal\n>     [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083)\n> -   Proposal\n>     [#1191: Bitwise operators](https://github.com/carbon-language/carbon-lang/pull/1191)\n> -   Proposal\n>     [#1178: Rework operator interfaces](https://github.com/carbon-language/carbon-lang/pull/1178)\n\n#### Common type\n\nThere are some situations where the common type for two types is needed:\n\n-   A [conditional expression like `if c then t else f`](expressions/if.md)\n    returns a value with the common type of `t` and `f`.\n-   If there are multiple parameters to a function with a type parameter, it\n    will be set to the common type of the corresponding arguments, as in:\n\n    ```carbon\n    fn F[T:! type](x: T, y: T);\n\n    // Calls `F` with `T` set to the\n    // common type of `G()` and `H()`:\n    F(G(), H());\n    ```\n\n-   The inferred return type of a function with\n    [`auto` return type](#auto-return-type) is the common type of its `return`\n    statements.\n\nThe common type is specified by implementing the `CommonTypeWith` interface:\n\n```carbon\n// Common type of `A` and `B` is `C`.\nimpl A as CommonTypeWith(B) where .Result = C { }\n```\n\nThe common type is required to be a type that both types have an\n[implicit conversion](expressions/implicit_conversions.md) to.\n\n> References:\n>\n> -   [`if` expressions](expressions/if.md#finding-a-common-type)\n> -   Proposal\n>     [#911: Conditional expressions](https://github.com/carbon-language/carbon-lang/pull/911)\n> -   Question-for-leads issue\n>     [#1077: find a way to permit impls of CommonTypeWith where the LHS and RHS type overlap](https://github.com/carbon-language/carbon-lang/issues/1077)\n\n## Bidirectional interoperability with C and C++\n\nInteroperability, or _interop_, is the ability to call C and C++ code from\nCarbon code and the other way around. This ability achieves two goals:\n\n-   Allows sharing a code and library ecosystem with C and C++.\n-   Allows incremental migration to Carbon from C and C++.\n\nCarbon's approach to interop is most similar to\n[Java/Kotlin interop](interoperability/philosophy_and_goals.md#other-interoperability-layers),\nwhere the two languages are different, but share enough of runtime model that\ndata from one side can be used from the other. For example, C++ and Carbon will\nuse the same\n[memory model](https://en.cppreference.com/w/cpp/language/memory_model).\n\nThe design for interoperability between Carbon and C++ hinges on:\n\n1.  The ability to interoperate with a wide variety of code, such as\n    classes/structs and\n    [templates](<https://en.wikipedia.org/wiki/Template_(C%2B%2B)>), not just\n    free functions.\n2.  A willingness to expose the idioms of C++ into Carbon code, and the other\n    way around, when necessary to maximize performance of the interoperability\n    layer.\n3.  The use of wrappers and generic programming, including templates, to\n    minimize or eliminate runtime overhead.\n\nThis feature will have some restrictions; only a subset of Carbon APIs will be\navailable to C++ and a subset of C++ APIs will be available to Carbon.\n\n-   To achieve simplification in Carbon, its programming model will exclude some\n    rarely used and complex features of C++. For example, there will be\n    limitations on\n    [multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance).\n-   C or C++ features that compromise the performance of code that don't use\n    that feature, like\n    [RTTI](https://en.wikipedia.org/wiki/Run-time_type_information) and\n    [exceptions](https://en.wikipedia.org/wiki/Exception_handling), are in\n    particular subject to revision in Carbon.\n\n> References:\n>\n> -   [Bidirectional interoperability with C and C++](interoperability/README.md)\n> -   Proposal\n>     [#175: C++ interoperability goals](https://github.com/carbon-language/carbon-lang/pull/175)\n\n### Goals\n\nThe [goals for interop](interoperability/philosophy_and_goals.md#goals) include:\n\n-   [Support mixing Carbon and C++ toolchains](interoperability/philosophy_and_goals.md#support-mixing-carbon-and-c-toolchains)\n-   [Compatibility with the C++ memory model](interoperability/philosophy_and_goals.md#compatibility-with-the-c-memory-model)\n-   [Minimize bridge code](interoperability/philosophy_and_goals.md#minimize-bridge-code)\n-   [Unsurprising mappings between C++ and Carbon types](interoperability/philosophy_and_goals.md#unsurprising-mappings-between-c-and-carbon-types)\n-   [Allow C++ bridge code in Carbon files](interoperability/philosophy_and_goals.md#allow-c-bridge-code-in-carbon-files)\n-   [Carbon inheritance from C++ types](interoperability/philosophy_and_goals.md#carbon-inheritance-from-c-types)\n-   [Support use of advanced C++ features](interoperability/philosophy_and_goals.md#support-use-of-advanced-c-features)\n-   [Support basic C interoperability](interoperability/philosophy_and_goals.md#support-basic-c-interoperability)\n\n> References:\n>\n> -   [Interoperability: Goals](interoperability/philosophy_and_goals.md#goals)\n\n### Non-goals\n\nThe [non-goals for interop](interoperability/philosophy_and_goals.md#non-goals)\ninclude:\n\n-   [Full parity between a Carbon-only toolchain and mixing C++/Carbon toolchains](interoperability/philosophy_and_goals.md#full-parity-between-a-carbon-only-toolchain-and-mixing-ccarbon-toolchains)\n-   [Never require bridge code](interoperability/philosophy_and_goals.md#never-require-bridge-code)\n-   [Convert all C++ types to Carbon types](interoperability/philosophy_and_goals.md#convert-all-c-types-to-carbon-types)\n-   [Support for C++ exceptions without bridge code](interoperability/philosophy_and_goals.md#support-for-c-exceptions-without-bridge-code)\n-   [Cross-language metaprogramming](interoperability/philosophy_and_goals.md#cross-language-metaprogramming)\n-   [Offer equivalent support for languages other than C++](interoperability/philosophy_and_goals.md#offer-equivalent-support-for-languages-other-than-c)\n\n> References:\n>\n> -   [Interoperability: Non-goals](interoperability/philosophy_and_goals.md#non-goals)\n\n### Importing and `#include`\n\n> **Note:** This is provisional, no design for importing C++ has been through\n> the proposal process yet.\n\nA C++ library header file may be [imported](#imports) into Carbon using an\n`import` declaration of the special `Cpp` package.\n\n```carbon\n// like `#include \"circle.h\"` in C++\nimport Cpp library \"circle.h\";\n```\n\nThis adds the names from `circle.h` into the `Cpp` namespace. If `circle.h`\ndefines some names in a `namespace shapes { ... }` scope, those will be found in\nCarbon's `Cpp.shapes` namespace.\n\nIn the other direction, Carbon packages can export a header file to be\n`#include`d from C++ files.\n\n```c++\n// like `import Geometry` in Carbon\n#include \"geometry.carbon.h\"\n```\n\nGenerally Carbon entities will be usable from C++ and C++ entities will be\nusable from Carbon. This includes types, function, and constants. Some entities,\nsuch as Carbon interfaces, won't be able to be translated directly.\n\nC and C++ macros that are defining constants will be imported as constants.\nOtherwise, C and C++ macros will be unavailable in Carbon. C and C++ `typedef`s\nwould be translated into type constants, as if declared using a\n[`let`](#constant-let-declarations).\n\nCarbon functions and types that satisfy some restrictions may be annotated as\nexported to C as well, like C++'s\n[`extern \"C\"`](https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B#Linking_C_and_C++_code)\nmarker.\n\n### ABI and dynamic linking\n\n> **Note:** This reflects goals and plans. No specific design for the\n> implementation has been through the proposal process yet.\n\nCarbon itself will not have a stable ABI for the language as a whole, and most\nlanguage features will be designed around not having any ABI stability. Instead,\nwe expect to add dedicated language features that are specifically designed to\nprovide an ABI-stable boundary between two separate parts of a Carbon program.\nThese ABI-resilient language features and API boundaries will be opt-in and\nexplicit. They may also have functionality restrictions to make them easy to\nimplement with strong ABI resilience.\n\nWhen interoperating with already compiled C++ object code or shared libraries,\nthe C++ interop may be significantly less feature rich than otherwise. This is\nan open area for us to explore, but we expect to require re-compiling C++ code\nin order to get the full ergonomic and performance benefits when interoperating\nwith Carbon. For example, recompilation lets us ensure Carbon and C++ can use\nthe same representation for key vocabulary types.\n\nHowever, we expect to have full support for the C ABI when interoperating with\nalready-compiled C object code or shared libraries. We expect Carbon's bridge\ncode functionality to cover similar use cases as C++'s\n[`extern \"C\"`](https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B#Linking_C_and_C++_code)\nmarker in order to provide full bi-directional support here. The functionality\navailable across this interop boundary will of course be restricted to what is\nexpressible in the C ABI, and types may need explicit markers to have guaranteed\nABI compatibility.\n\n> References:\n>\n> -   [Goals: Stable language and library ABI non-goal](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#stable-language-and-library-abi)\n> -   [#175: C++ interoperability goals: Support mixing Carbon and C++ toolchains](/proposals/p0175.md#support-mixing-carbon-and-c-toolchains)\n\n### Operator overloading\n\n> **Note:** This is provisional, no design for this has been through the\n> proposal process yet.\n\n[Operator overloading](#operator-overloading) is supported in Carbon, but is\ndone by [implementing an interface](#interfaces-and-implementations) instead of\ndefining a method or nonmember function as in C++.\n\nCarbon types implementing an operator overload using an interface should get the\ncorresponding operator overload in C++. So implementing `ModWith(U)` in Carbon\nfor a type effectively implements `operator%` in C++ for that type. This also\nworks in the other direction, so C++ types implementing an operator overload are\nautomatically considered to implement the corresponding Carbon interface. So\nimplementing `operator%` in C++ for a type also implements interface\n`ModWith(U)` in Carbon. However, there may be edge cases around implicit\nconversions or overload selection that don't map completely into Carbon.\n\nIn some cases, the operation might be written differently in the two languages.\nIn those cases, they are matched according to which operation has the most\nsimilar semantics rather than using the same symbols. For example, the `^x`\noperation and `BitComplement` interface in Carbon corresponds to the `~x`\noperation and `operator~` function in C++. Similarly, the `ImplicitAs(U)` Carbon\ninterface corresponds to implicit conversions in C++, which can be written in\nmultiple different ways. Other\n[C++ customization points](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html)\nlike `swap` will correspond to a Carbon interface, on a case-by-case basis.\n\nSome operators will only exist or be overridable in C++, such as logical\noperators or the comma operator. In the unlikely situation where those operators\nneed to be overridden for a Carbon type, that can be done with a nonmember C++\nfunction.\n\nCarbon interfaces with no C++ equivalent, such as\n[`CommonTypeWith(U)`](#common-type), may be implemented for C++ types\nout-of-line in Carbon code. To satisfy the\n[orphan rule](generics/details.md#orphan-rule), each C++ library will have a\ncorresponding Carbon wrapper library that must be imported instead of the C++\nlibrary if the Carbon wrapper exists. **TODO:** Perhaps it will automatically be\nimported, so a wrapper may be added without requiring changes to importers?\n\n### Templates\n\nCarbon supports both\n[checked and template generics](#checked-and-template-parameters). This provides\na migration path for C++ template code:\n\n-   C++ template -> Carbon template: This involves migrating the code from C++\n    to Carbon. If that migration is faithful, the change should be transparent\n    to callers.\n-   -> Carbon template with constraints: Constraints may be added one at a time.\n    Adding a constraint never changes the meaning of the code as long as it\n    continues to compile. Compile errors will point to types for which an\n    implementation of missing interfaces is needed. A temporary template\n    implementation of that interface can act as a bridge during the transition.\n-   -> Carbon checked generic: Once all callers work after all constraints have\n    been added, the template parameter may be switched to a checked generic.\n\nCarbon will also provide direct interop with C++ templates in many ways:\n\n-   Ability to call C++ templates and use C++ templated types from Carbon.\n-   Ability to instantiate a C++ template with a Carbon type.\n-   Ability to instantiate a Carbon generic with a C++ type.\n\nWe expect the best interop in these areas to be based on a Carbon-provided C++\ntoolchain. However, even when using Carbon's generated C++ headers for interop,\nwe will include the ability where possible to use a Carbon generic from C++ as\nif it were a C++ template.\n\n> References:\n>\n> -   Proposal\n>     [#2200: Template generics](https://github.com/carbon-language/carbon-lang/pull/2200)\n\n### Standard types\n\n> **Note:** This is provisional, no design for this has been through the\n> proposal process yet.\n\nThe Carbon integer types, like `i32` and `u64`, are considered equal to the\ncorresponding fixed-width integer types in C++, like `int32_t` and `uint64_t`,\nprovided by `<stdint.h>` or `<cstdint>`. The basic C and C++ integer types like\n`int`, `char`, and `unsigned long` are available in Carbon inside the `Cpp`\nnamespace given an `import Cpp;` declaration, with names like `Cpp.int`,\n`Cpp.char`, and `Cpp.unsigned_long`. C++ types are considered different if C++\nconsiders them different, so C++ overloads are resolved the same way. Carbon\n[conventions for implicit conversions between integer types](expressions/implicit_conversions.md#data-types)\napply here, allowing them whenever the numerical value for all inputs may be\npreserved by the conversion.\n\nOther C and C++ types are equal to Carbon types as follows:\n\n| C or C++ | Carbon         |\n| -------- | -------------- |\n| `bool`   | `bool`         |\n| `float`  | `f32`          |\n| `double` | `f64`          |\n| `T*`     | `Optional(T*)` |\n| `T[4]`   | `[T; 4]`       |\n\nFurther, C++ reference types like `T&` will be translated to `T*` in Carbon,\nwhich is Carbon's non-null pointer type.\n\nCarbon will work to have idiomatic vocabulary _view_ types for common data\nstructures, like `std::string_view` and `std::span`, map transparently between\nC++ and the Carbon equivalents. This will include data layout so that even\npointers to these types translate seamlessly, contingent on a suitable C++ ABI\nfor those types, potentially by re-compiling the C++ code with a customized ABI.\nWe will also explore how to expand coverage to similar view types in other\nlibraries.\n\nHowever, Carbon's containers will be distinct from the C++ standard library\ncontainers in order to maximize our ability to improve performance and leverage\nlanguage features like checked generics in their design and implementation.\n\nWhere possible, we will also try to provide implementations of Carbon's standard\nlibrary container _interfaces_ for the relevant C++ container types so that they\ncan be directly used with checked-generic Carbon code. This should allow\nchecked-generic code in Carbon to work seamlessly with both Carbon and C++\ncontainers without performance loss or constraining the Carbon container\nimplementations. In the other direction, Carbon containers will satisfy C++\ncontainer requirements, so templated C++ code can operate directly on Carbon\ncontainers as well.\n\n### Inheritance\n\n[Carbon has single inheritance](#inheritance) allowing C++ classes using\ninheritance to be migrated. The data representation will be consistent so that\nCarbon classes may inherit from C++ classes, and the other way around, even with\nvirtual methods.\n\nC++ [multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance)\nand [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)\nwill be migrated using a combination of Carbon features. Carbon mixins support\nimplementation reuse and Carbon interfaces allow a type to implement multiple\nAPIs. However, there may be limits on the degree of interop available with\nmultiple inheritance across the C++ <-> Carbon boundaries.\n\nCarbon dyn-safe interfaces may be exported to C++ as an\n[abstract base class](<https://en.wikipedia.org/wiki/Class_(computer_programming)#Abstract_and_concrete>).\nThe reverse operation is also possible using a proxy object implementing a C++\nabstract base class and holding a pointer to a type implementing the\ncorresponding interface.\n\n> References:\n>\n> -   Proposal\n>     [#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561)\n> -   Proposal\n>     [#777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777)\n\n### Enums\n\n> **TODO**\n\n## Unfinished tales\n\n> **Note:** Everything in this section is provisional and forward looking.\n\n### Safety\n\nCarbon's premise is that C++ users can't give up performance to get safety. Even\nif some isolated users can make that tradeoff, they share code with\nperformance-sensitive users. Any path to safety must preserve performance of C++\ntoday. This rules out garbage collection, and many other options. The only well\nunderstood mechanism of achieving safety without giving up performance is\ncompile-time safety. The leading example of how to achieve this is Rust.\n\nThe difference between Rust's approach and Carbon's is that Rust starts with\nsafety and Carbons starts with migration. Rust supports interop with C, and\nthere is ongoing work to improve the C++-interop story and develop migration\ntools. However, there is a large gap in programming models between the two\nlanguages, generally requiring a revision to the architecture. So, thus far the\ncommon pattern in the Rust community is to \"rewrite it in Rust\"\n([1](https://deprogrammaticaipsum.com/the-great-rewriting-in-rust/),\n[2](https://web.archive.org/web/20230923033736/https://unhandledexpression.com/rust/2017/07/10/why-you-should-actually-rewrite-it-in-rust.html),\n[3](https://transitiontech.ca/random/RIIR)). Carbon's approach is to focus on\nmigration from C++, including seamless interop, and then incrementally improve\nsafety.\n\nThe first impact on Carbon's design to support its safety strategy are the\nnecessary building blocks for this level of compile-time safety. We look at\nexisting languages like Rust and Swift to understand what fundamental\ncapabilities they ended up needing. The two components that stand out are:\n\n-   Expanded type system that includes more semantic information.\n-   More pervasive use of type system abstractions (typically checked generics).\n\nFor migrating C++ code, we also need the ability to add features and migrate\ncode to use those new features incrementally and over time. This requires\ndesigning the language with evolution baked in on day one. This impacts a wide\nrange of features:\n\n-   At the lowest level, a simple and extensible syntax and grammar.\n-   Tools and support for adding and removing APIs.\n-   Scalable migration strategies, including tooling support.\n\nRust shows the value of expanded semantic information in the type system such as\nprecise lifetimes. This is hard to do in C++ since it has too many kinds of\nreferences and pointers, which increases the complexity in the type system\nmultiplicatively. Carbon is attempting to compress C++'s type variations into\njust values and [pointers](#pointer-types).\n\nRust also shows the value of functions parameterized by lifetimes. Since\nlifetimes are only used to establish safety properties of the code, there is no\nreason to pay the cost of monomorphization for those parameters. So we need a\n[checked-generics system](#generics) that can reason about code before it is\ninstantiated, unlike C++ templates.\n\nIn conclusion, there are two patterns in how Carbon diverges from C++:\n\n-   Simplify and removing things to create space for new safety features. This\n    trivially requires breaking backwards compatibility.\n-   Re-engineer foundations to model and enforce safety. This is complex and\n    difficult in C++ without first simplifying the language.\n\nThis leads to Carbon's incremental path to safety:\n\n-   Keep your performance, your existing codebase, and your developers.\n-   Adopt Carbon through a scalable, tool-assisted migration from C++.\n-   Address initial, easy safety improvements starting day one.\n-   Shift the Carbon code onto an incremental path towards memory safety over\n    the next decade.\n\n> References: [Safety design](/docs/design/safety)\n\n### Lifetime and move semantics\n\n> **TODO:**\n\n### Metaprogramming\n\n> **TODO:** References need to be evolved. Needs a detailed design and a high\n> level summary provided inline.\n\nCarbon provides metaprogramming facilities that look similar to regular Carbon\ncode. These are structured, and do not offer arbitrary inclusion or\npreprocessing of source text such as C and C++ do.\n\n> References: [Metaprogramming](metaprogramming.md)\n\n### Pattern matching as function overload resolution\n\n> **TODO:** References need to be evolved. Needs a detailed design and a high\n> level summary provided inline.\n\n> References: [Pattern matching](pattern_matching.md)\n\n### Error handling\n\nFor now, Carbon does not have language features dedicated to error handling, but\nwe would consider adding some in the future. At this point, errors are\nrepresented using [choice types](#choice-types) like `Result` and `Optional`.\n\nThis is similar to the story for Rust, which started using `Result`, then added\n[`?` operator](https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator)\nfor convenience, and is now considering ([1](https://yaah.dev/try-blocks),\n[2](https://doc.rust-lang.org/beta/unstable-book/language-features/try-blocks.html))\nadding more.\n\n### Execution abstractions\n\nCarbon provides some higher-order abstractions of program execution, as well as\nthe critical underpinnings of such abstractions.\n\n#### Abstract machine and execution model\n\n> **TODO:**\n\n#### Lambdas\n\n> **TODO:** References need to be evolved. Needs a detailed design and a high\n> level summary provided inline.\n\n> References: [Lambdas](lambdas.md),\n> [Proposal #3848: Lambdas](https://github.com/carbon-language/carbon-lang/pull/3848)\n\n#### Co-routines\n\n> **TODO:**\n\n#### Concurrency\n\n> **TODO:**\n"
  },
  {
    "path": "docs/design/aliases.md",
    "content": "# Aliases\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [TODO](#todo)\n-   [Overview](#overview)\n    -   [Alternatives](#alternatives)\n\n<!-- tocstop -->\n\n## TODO\n\nThis is a skeletal design, added to support [the overview](README.md). It should\nnot be treated as accepted by the core team; rather, it is a placeholder until\nwe have more time to examine this detail. Please feel welcome to rewrite and\nupdate as appropriate.\n\n## Overview\n\nNaming is one of the things that most often requires careful management over\ntime -- things tend to get renamed and moved around.\n\nCarbon provides a fully general name aliasing facility to declare a new name as\nan alias for a value; everything is a value in Carbon. This is a fully general\nfacility because everything is a value in Carbon, including types.\n\nFor example:\n\n```\nalias MyInt = Int;\n```\n\nThis creates an alias called `MyInt` for whatever `Int` resolves to. Code\ntextually after this can refer to `MyInt`, and it will transparently refer to\n`Int`.\n\n### Alternatives\n\nThe syntax here is not at all in a good state yet. We've considered a few\nalternatives, but they all end up being confusing in some way. We need to figure\nout a good and clean syntax that can be used here.\n"
  },
  {
    "path": "docs/design/assignment.md",
    "content": "# Assignment\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Syntax](#syntax)\n-   [Simple assignment semantics](#simple-assignment-semantics)\n-   [Compound assignment semantics](#compound-assignment-semantics)\n-   [Built-in types](#built-in-types)\n-   [Tuples, structs, choice types, and data classes](#tuples-structs-choice-types-and-data-classes)\n-   [Extensibility](#extensibility)\n    -   [Simple assignment](#simple-assignment)\n    -   [Arithmetic](#arithmetic)\n    -   [Bitwise and bit-shift](#bitwise-and-bit-shift)\n    -   [Defaults](#defaults)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nValues can be assigned to variables using the `=` operator:\n\n```\nvar a: i32 = 5;\na = 6;\n```\n\nFor each binary [arithmetic](expressions/arithmetic.md) or\n[bitwise](expressions/bitwise.md) operator `$`, a corresponding compound\nassignment `$=` is provided that performs the operation in-place:\n\n```\n// Same as `a = a + 1;`\na += 1;\n// Same as `a = a << 3;`\na <<= 3;\n```\n\nIn addition, increment and decrement operators are provided:\n\n```\n// Same as `a = a + 1;`\n++a;\n// Same as `a = a - 1;`\n--a;\n```\n\nThese simple assignment, compound assignment, increment, and decrement operators\ncan only be used as complete statements, not as subexpressions of other\noperators, even when parenthesized:\n\n```\nvar n: i32;\n// Error, assignment is not permitted as a subexpression.\nif (F() and (n = GetValue()) > 5) {\n}\n```\n\nUser-defined types can define the meaning of these operations by\n[implementing an interface](#extensibility) provided as part of the Carbon\nstandard library.\n\n## Syntax\n\nThe operands of these operators can be any [expression](expressions/README.md).\nHowever, the first operand must be modifiable because it is passed to a\n`[ref self: Self]` parameter, which disallows most expression forms other than:\n\n-   The name of a `var` binding.\n-   A dereference of a pointer.\n-   Array indexing that produces a modifiable result.\n-   Member access naming a field, where the object is one of these expressions.\n\n## Simple assignment semantics\n\nA simple assignment statement is intended to exactly mirror the semantics of\ninitialization. The following two code snippets should have the same meaning if\nthey are both valid:\n\n```\n// Declare and initialize.\nvar v: T = init;\n```\n\n```\n// Declare separately from initialization.\n// Requires that `T` has an unformed state.\nvar v: T;\nv = init;\n```\n\nThis equivalence is not enforced, but when an object is in an unformed state,\nrunning the assignment function is _optional_, just like running the destructor\nis. If the assignment function is not run, the object will be directly\ninitialized from the right-hand side instead. The type is still required to\nimplement `AssignWith` for the assignment to be valid.\n\n```\nclass C { ... }\nfn F() -> C {\n  returned var c: C = {...};\n  // `&c` here is `&x` for the first call to `F()`.\n  // `&c` here can be `&y` for the second call  to `F()`.\n  return var;\n}\nfn G() {\n  var x: C = F();\n  var y: C;\n  y = F();\n}\n```\n\n## Compound assignment semantics\n\nThe syntax `a $= b;` is intended to be syntactic sugar for `a = a $ b;`, except\nas follows:\n\n-   A type might be able to provide a more efficient implementation for the\n    compound assignment form than for the uncombined form.\n-   A type might not be able to, or might not want to, provide the uncombined\n    form at all, for example because creating a new instance requires additional\n    resources that might not be available, such as a context object or an\n    allocator.\n\nThe syntactic sugar is implemented by a [default implementation](#defaults) of\n`$=` in terms of `$` and `=`.\n\nIn contrast, `++a;` and `--a;` are not simply syntactic sugar for `a = a + 1;`\nand `a = a - 1;`. Instead, we interpret these operators as meaning \"move to the\nnext value\" and \"move to the previous value\". These operations may be available\nand meaningful in cases where adding an integer is not a desirable operation,\nsuch as for an iterator into a linked list, and may not be available in cases\nwhere adding an integer is meaningful, such as for a type representing a\nrational number.\n\n## Built-in types\n\nIntegers and floating-point types, `bool`, and pointer types support simple\nassignment with `=`. The right-hand operand is implicitly converted to the type\nof the left-hand operand, and the converted value replaces the value of that\noperand.\n\nCompound assignment `$=` for integer and floating point types is\n[provided automatically](#defaults) for each supported operator `$`.\n\nFor integer types, `++n;` and `--n;` behave the same as `n += 1;` and `n -= 1;`\nrespectively. For floating-point types, these operators are not provided.\n\n## Tuples, structs, choice types, and data classes\n\n_TODO_: Describe the rules for assignment in these cases.\n\nSee leads issue\n[#686: Operation order in struct/class assignment/initialization](https://github.com/carbon-language/carbon-lang/issues/686)\n\n## Extensibility\n\nAssignment operators can be provided for user-defined types by implementing the\nfollowing families of interfaces. Implementations of these interfaces are\nprovided for built-in types as necessary to give the semantics described above.\n\n### Simple assignment\n\n```\n// Simple `=`.\ninterface AssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint Assign { extend AssignWith(Self); }\n```\n\nGiven `var x: T` and `y: U`:\n\n-   The statement `x = y;` is rewritten to `x.(AssignWith(U).Op)(y);`.\n\n### Arithmetic\n\n```\n// Compound `+=`.\ninterface AddAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint AddAssign { extend AddAssignWith(Self); }\n```\n\n```\n// Compound `-=`.\ninterface SubAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint SubAssign { extend SubAssignWith(Self); }\n```\n\n```\n// Compound `*=`.\ninterface MulAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint MulAssign { extend MulAssignWith(Self); }\n```\n\n```\n// Compound `/=`.\ninterface DivAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint DivAssign { extend DivAssignWith(Self); }\n```\n\n```\n// Compound `%=`.\ninterface ModAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint ModAssign { extend ModAssignWith(Self); }\n```\n\n```\n// Increment `++`.\ninterface Inc { fn Op[ref self: Self](); }\n// Decrement `++`.\ninterface Dec { fn Op[ref self: Self](); }\n```\n\nGiven `var x: T` and `y: U`:\n\n-   The statement `x += y;` is rewritten to `x.(AddAssignWith(U).Op)(y);`.\n-   The statement `x -= y;` is rewritten to `x.(SubAssignWith(U).Op)(y);`.\n-   The statement `x *= y;` is rewritten to `x.(MulAssignWith(U).Op)(y);`.\n-   The statement `x /= y;` is rewritten to `x.(DivAssignWith(U).Op)(y);`.\n-   The statement `x %= y;` is rewritten to `x.(ModAssignWith(U).Op)(y);`.\n-   The statement `++x;` is rewritten to `x.(Inc.Op)();`.\n-   The statement `--x;` is rewritten to `x.(Dec.Op)();`.\n\n### Bitwise and bit-shift\n\n```\n// Compound `&=`.\ninterface BitAndAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint BitAndAssign { extend BitAndAssignWith(Self); }\n```\n\n```\n// Compound `|=`.\ninterface BitOrAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint BitOrAssign { extend BitOrAssignWith(Self); }\n```\n\n```\n// Compound `^=`.\ninterface BitXorAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint BitXorAssign { extend BitXorAssignWith(Self); }\n```\n\n```\n// Compound `<<=`.\ninterface LeftShiftAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint LeftShiftAssign { extend LeftShiftAssignWith(Self); }\n```\n\n```\n// Compound `>>=`.\ninterface RightShiftAssignWith(U:! type) {\n  fn Op[ref self: Self](other: U);\n}\nconstraint RightShiftAssign { extend RightShiftAssignWith(Self); }\n```\n\nGiven `var x: T` and `y: U`:\n\n-   The statement `x &= y;` is rewritten to `x.(BitAndAssignWith(U).Op)(y);`.\n-   The statement `x |= y;` is rewritten to `x.(BitOrAssignWith(U).Op)(y);`.\n-   The statement `x ^= y;` is rewritten to `x.(BitXorAssignWith(U).Op)(y);`.\n-   The statement `x <<= y;` is rewritten to\n    `x.(LeftShiftAssignWith(U).Op)(y);`.\n-   The statement `x >>= y;` is rewritten to\n    `x.(RightShiftAssignWith(U).Op)(y)`;.\n\nImplementations of these interfaces are provided for built-in types as necessary\nto give the semantics described above.\n\n### Defaults\n\nWhen a type provides both an assignment and a binary operator `$`, so that\n`a = a $ b;` is valid, Carbon provides a default `$=` implementation so that\n`a $= b;` is valid and has the same meaning as `a = a $ b;`.\n\nThis defaulting is accomplished by a parameterized implementation of\n`OpAssignWith(U)` defined in terms of `AssignWith` and `OpWith`:\n\n```\nimpl forall [U:! type, T:! OpWith(U) where .Self impls AssignWith(.Self.Result)]\n    T as OpAssignWith(U) {\n  fn Op[ref self: Self](other: U) {\n    // Here, `$` is the operator described by `OpWith`.\n    *self = *self $ other;\n  }\n}\n```\n\nIf a more efficient form of compound assignment is possible for a type, a more\nspecific `impl` can be provided:\n\n```\nimpl like MyString as AddWith(like MyString) {\n  // Allocate new memory and perform addition.\n}\n\nimpl MyString as AddAssignWith(like MyString) {\n  // Reuse existing storage where possible.\n}\n```\n\n## Alternatives considered\n\n-   [Allow assignment as a subexpression](/proposals/p2511.md#allow-assignment-as-a-subexpression)\n-   [Allow chained assignment](/proposals/p2511.md#allow-chained-assignment)\n-   [Do not provide increment and decrement](/proposals/p2511.md#do-not-provide-increment-and-decrement)\n-   [Treat increment as syntactic sugar for adding `1`](/proposals/p2511.md#treat-increment-as-syntactic-sugar-for-adding-1)\n-   [Define `$` in terms of `$=`](/proposals/p2511.md#define--in-terms-of-)\n-   [Do not allow overloading the behavior of `=`](/proposals/p2511.md#do-not-allow-overloading-the-behavior-of-)\n-   [Treat the left hand side of `=` as a pattern](/proposals/p2511.md#treat-the-left-hand-side-of--as-a-pattern)\n-   [Different names for interfaces](/proposals/p2511.md#different-names-for-interfaces)\n\n## References\n\n-   Leads issue\n    [#451: Do we want variable-arity operators?](https://github.com/carbon-language/carbon-lang/issues/451)\n-   Proposal\n    [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257)\n-   Proposal\n    [#1083: Arithmetic](https://github.com/carbon-language/carbon-lang/pull/1083)\n-   Proposal\n    [#1178: Rework operator interfaces](https://github.com/carbon-language/carbon-lang/pull/1178)\n-   Proposal\n    [#1191: Bitwise and shift operators](https://github.com/carbon-language/carbon-lang/pull/1191)\n-   Proposal\n    [#2511: Assignment statements](https://github.com/carbon-language/carbon-lang/pull/2511)\n"
  },
  {
    "path": "docs/design/blocks_and_statements.md",
    "content": "# Blocks and statements\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [TODO](#todo)\n-   [Overview](#overview)\n\n<!-- tocstop -->\n\n## TODO\n\nThis is a skeletal design, added to support [the overview](README.md). It should\nnot be treated as accepted by the core team; rather, it is a placeholder until\nwe have more time to examine this detail. Please feel welcome to rewrite and\nupdate as appropriate.\n\n## Overview\n\nThe body or definition of a function is provided by a block of code containing\nstatements, much like in C or C++. The body of a function is also a new, nested\nscope inside the function's scope (meaning that parameter names are available).\nStatements within a block are terminated by a semicolon. Each statement can,\namong other things, be an expression. Here is a trivial example of a function\ndefinition using a block of statements:\n\n```\nfn Foo() {\n  Bar();\n  Baz();\n}\n```\n\nStatements can also themselves be a block of statements, which provide scopes\nand nesting:\n\n```\nfn Foo() {\n  Bar();\n  {\n    Baz();\n  }\n}\n```\n"
  },
  {
    "path": "docs/design/classes.md",
    "content": "# Classes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Use cases](#use-cases)\n    -   [Data classes](#data-classes)\n    -   [Encapsulated types](#encapsulated-types)\n        -   [Without inheritance](#without-inheritance)\n        -   [With inheritance and subtyping](#with-inheritance-and-subtyping)\n            -   [Polymorphic types](#polymorphic-types)\n                -   [Interface as base class](#interface-as-base-class)\n            -   [Non-polymorphic inheritance](#non-polymorphic-inheritance)\n            -   [Interop with C++ multiple inheritance](#interop-with-c-multiple-inheritance)\n    -   [Mixins](#mixins)\n-   [Background](#background)\n-   [Members](#members)\n    -   [Data members have an order](#data-members-have-an-order)\n-   [Struct types](#struct-types)\n    -   [Literals](#literals)\n    -   [Type expression](#type-expression)\n    -   [Assignment and initialization](#assignment-and-initialization)\n    -   [Operations performed field-wise](#operations-performed-field-wise)\n-   [Nominal class types](#nominal-class-types)\n    -   [Fields](#fields)\n    -   [Forward declaration](#forward-declaration)\n    -   [`Self`](#self)\n    -   [Construction](#construction)\n        -   [Assignment](#assignment)\n    -   [Member functions](#member-functions)\n        -   [Class functions](#class-functions)\n        -   [Methods](#methods)\n        -   [Deferred member function definitions](#deferred-member-function-definitions)\n        -   [Name lookup in classes](#name-lookup-in-classes)\n    -   [Nominal data classes](#nominal-data-classes)\n    -   [Member type](#member-type)\n    -   [Let](#let)\n    -   [Alias](#alias)\n    -   [Inheritance](#inheritance)\n        -   [Virtual methods](#virtual-methods)\n            -   [Virtual modifier keywords](#virtual-modifier-keywords)\n        -   [Subtyping](#subtyping)\n        -   [`Self` refers to the current type](#self-refers-to-the-current-type)\n        -   [Constructors](#constructors)\n            -   [Partial class type](#partial-class-type)\n            -   [Usage](#usage)\n        -   [Assignment with inheritance](#assignment-with-inheritance)\n    -   [Destructors](#destructors)\n    -   [Access control](#access-control)\n        -   [Private access](#private-access)\n        -   [Protected access](#protected-access)\n        -   [Friends](#friends)\n        -   [Test friendship](#test-friendship)\n        -   [Access control for construction](#access-control-for-construction)\n    -   [Operator overloading](#operator-overloading)\n-   [Future work](#future-work)\n    -   [Struct literal shortcut](#struct-literal-shortcut)\n    -   [Optional named parameters](#optional-named-parameters)\n        -   [Field defaults for struct types](#field-defaults-for-struct-types)\n        -   [Destructuring in pattern matching](#destructuring-in-pattern-matching)\n        -   [Discussion](#discussion)\n    -   [Inheritance](#inheritance-1)\n        -   [C++ abstract base classes interoperating with object-safe interfaces](#c-abstract-base-classes-interoperating-with-object-safe-interfaces)\n        -   [Overloaded methods](#overloaded-methods)\n        -   [Interop with C++ inheritance](#interop-with-c-inheritance)\n            -   [Virtual base classes](#virtual-base-classes)\n    -   [Mixins](#mixins-1)\n    -   [Memory layout](#memory-layout)\n    -   [No `static` variables](#no-static-variables)\n    -   [Computed properties](#computed-properties)\n    -   [Interfaces implemented for data classes](#interfaces-implemented-for-data-classes)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nA Carbon _class_ is a user-defined\n[record type](<https://en.wikipedia.org/wiki/Record_(computer_science)>). A\nclass has members that are referenced by their names, in contrast to a\n[Carbon tuple](tuples.md) which defines a\n[product type](https://en.wikipedia.org/wiki/Product_type) whose members are\nreferenced positionally.\n\nClasses are the primary mechanism for users to extend the Carbon type system and\nare deeply rooted in C++ and its history (C and Simula). We call them classes\nrather than other terms as that is both familiar to existing programmers and\naccurately captures their essence: they define the types of objects with\n(optional) support for methods, encapsulation, and so on.\n\nCarbon supports both named, or \"nominal\", and unnamed, anonymous, or\n\"structural\", class types. Nominal class types are all distinct, but structural\ntypes are equal if they have the same sequence of member types and names.\nStructural class literals may be used to initialize or assign values to nominal\nclass variables.\n\nA class type defines the interpretation of the bytes of a value of that type,\nincluding the size, data members, and layout. It defines the operations that may\nbe performed on those values, including what methods may be called. A class type\nmay directly have constant members. The type itself is a compile-time immutable\nconstant value.\n\n## Use cases\n\nThe use cases for classes include both cases motivated by C++ interop, and cases\nthat we expect to be included in idiomatic Carbon-only code.\n\n**This design currently only attempts to address the \"data classes\" and\n\"encapsulated types\" use cases.** Addressing the \"interface as base class\",\n\"interop with C++ multiple inheritance\" and \"mixin\" use cases is future work.\n\n### Data classes\n\nData classes are types that consist of data fields that are publicly accessible\nand directly read and manipulated by client code. They have few if any methods,\nand generally are not involved in inheritance at all.\n\nExamples include:\n\n-   a key and value pair returned from a `SortedMap` or `HashMap`\n-   a 2D point that might be used in a rendering API\n\nProperties:\n\n-   Operations like copy, move, destroy, unformed, and so on are defined\n    field-wise.\n-   Anonymous classes types and literals should match data class semantics.\n\nExpected in idiomatic Carbon-only code.\n\n**Background:** Kotlin has a dedicated concise syntax for defining\n[_data classes_](https://kotlinlang.org/docs/data-classes.html) that avoids\nboilerplate. Python has a\n[data class library](https://docs.python.org/3/library/dataclasses.html),\nproposed in [PEP 557](https://www.python.org/dev/peps/pep-0557/), that fills a\nsimilar role.\n\n### Encapsulated types\n\nThere are several categories of types that support\n[encapsulation](<https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)>).\nThis is done by making their data fields private so access and modification of\nvalues are all done through methods defined on the type.\n\n#### Without inheritance\n\nThe common case for encapsulated types are those that do not participate in\ninheritance. These types neither support being inherited from (they are\n[\"final\"](<https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Non-subclassable_classes>))\nnor do they extend other types.\n\nExamples of this use case include:\n\n-   strings, containers, iterators\n-   types with invariants such as `Date`\n-   RAII types that are movable but not copyable like C++'s `std::unique_ptr` or\n    a file handle\n-   non-movable types like `Mutex`\n\nWe expect two kinds of methods on these types: public methods defining the API\nfor accessing and manipulating values of the type, and private helper methods\nused as an implementation detail of the public methods.\n\nThese types are expected in idiomatic Carbon-only code.\n\n#### With inheritance and subtyping\n\nThe [subtyping](https://en.wikipedia.org/wiki/Subtyping) you get with\ninheritance is that you may assign the address of an object of a derived type to\na pointer to its base type. For this to work, the compiler needs implementation\nstrategies that allow operations performed through the pointer to the base type\nwork independent of which derived type it actually points to. These strategies\ninclude:\n\n-   Arranging for the data layout of derived types to start with the data layout\n    of the base type as a prefix.\n-   Putting a pointer to a table of function pointers, a\n    [_vtable_](https://en.wikipedia.org/wiki/Virtual_method_table), as the first\n    data member of the object. This allows methods to be\n    [_virtual_](https://en.wikipedia.org/wiki/Virtual_function) and have a\n    derived-type-specific implementation, an _override_, that is used even when\n    invoking the method on a pointer to a base type.\n-   Non-virtual methods implemented on a base type should be applicable to all\n    derived types. In general, derived types should not attempt to overload or\n    override non-virtual names defined in the base type.\n\nNote that these subtyping implementation strategies generally rely on\nencapsulation, but encapsulation is not a strict requirement in all cases.\n\nThis subtyping relationship also creates safety concerns, which Carbon should\nprotect against.\n[Slicing problems](https://en.wikipedia.org/wiki/Object_slicing) can arise when\nthe source or target of an assignment is a dereferenced pointer to the base\ntype. It is also incorrect to delete an object with a non-virtual destructor\nthrough a pointer to a base type.\n\n##### Polymorphic types\n\nCarbon will fully support single-inheritance type hierarchies with polymorphic\ntypes.\n\nPolymorphic types support\n[dynamic dispatch](https://en.wikipedia.org/wiki/Dynamic_dispatch) using a\n[vtable](https://en.wikipedia.org/wiki/Virtual_method_table), and data members,\nbut only single inheritance. Individual methods opt in to using dynamic\ndispatch, so types will have a mix of\n[\"virtual\"](https://en.wikipedia.org/wiki/Virtual_function) and non-virtual\nmethods. Polymorphic types support traditional\n[object-oriented single inheritance](<https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)>),\na mix of [subtyping](https://en.wikipedia.org/wiki/Subtyping) and\n[implementation and code reuse](<https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Code_reuse>).\n\nWe exclude complex multiple inheritance schemes, virtual inheritance, and so on\nfrom this use case. This is to avoid the complexity and overhead they bring,\nparticularly since the use of these features in C++ is generally discouraged.\nThe rule is that every type has at most one base type with data members for\nsubtyping purposes. Carbon will support additional base types as long as they\n[don't have data members](#interface-as-base-class) or\n[don't support subtyping](#mixins).\n\n**Background:**\n[The \"Nothing is Something\" talk by Sandi Metz](https://www.youtube.com/watch?v=OMPfEXIlTVE)\nand\n[the Composition Over Inheritance Principle](https://python-patterns.guide/gang-of-four/composition-over-inheritance/)\ndescribe design patterns to use instead of multiple inheritance to support types\nthat vary over multiple axes.\n\nIn rare cases where the complex multiple inheritance schemes of C++ are truly\nneeded, they can be effectively approximated using a combination of these\nsimpler building blocks.\n\nPolymorphic types support a number of different kinds of methods:\n\n-   They will have virtual methods:\n    -   Polymorphic types will typically include virtual destructors.\n    -   The virtual methods types may have default implementations or be\n        [_abstract_](<https://en.wikipedia.org/wiki/Method_(computer_programming)#Abstract_methods>)\n        (or\n        [_pure virtual_](https://en.wikipedia.org/wiki/Virtual_function#Abstract_classes_and_pure_virtual_functions)).\n        In the latter case, they must be implemented in any derived class that\n        can be instantiated.\n    -   Virtual methods may be\n        [_protected_](https://en.wikipedia.org/wiki/Access_modifiers) or\n        [_private_](https://stackoverflow.com/questions/2170688/private-virtual-method-in-c),\n        intended to be called by methods in the base type but implemented in the\n        descendant.\n-   They may have non-virtual public or private helper methods, like\n    [encapsulated types without inheritance](#without-inheritance). These avoid\n    the overhead of a virtual function call, and can be written when the base\n    class has sufficient data members.\n-   They may have protected helper methods, typically non-virtual, provided by\n    the base type to be called by the descendant.\n\nNote that there are two uses for protected methods: those implemented in the\nbase and called in the descendant, and the other way around.\n[\"The End Of Object Inheritance & The Beginning Of A New Modularity\" talk by Augie Fackler and Nathaniel Manista](https://www.youtube.com/watch?v=3MNVP9-hglc)\ndiscusses design patterns that split up types to reduce the number of kinds of\ncalls between base and derived types, and make sure calls only go in one\ndirection.\n\nWe expect polymorphic types in idiomatic Carbon-only code, at least for the\nmedium term. Extending this design to support polymorphic types is future work.\n\n###### Interface as base class\n\nWe distinguish the specific case of polymorphic base classes that have no data\nmembers:\n\n-   From an implementation perspective, the lack of data members removes most of\n    the problems with supporting multiple inheritance.\n-   They are about decoupling two pieces of code instead of collaborating.\n-   As a use case, they are used primarily for subtyping and much less\n    implementation reuse than other polymorphic types.\n-   This case overlaps with the\n    [interface](/docs/design/generics/terminology.md#interface) concept\n    introduced for [Carbon generics](/docs/design/generics/overview.md).\n\nRemoving support for data fields greatly simplifies supporting multiple\ninheritance. For example, it removes the need for a mechanism to figure out the\noffset of those data fields in the object. Similarly we don't need\n[C++'s virtual inheritance](https://en.wikipedia.org/wiki/Virtual_inheritance)\nto avoid duplicating those fields. Some complexities still remain, such as\npointers changing values when casting to a secondary parent type, but these seem\nmanageable given the benefits of supporting this useful case of multiple\ninheritance.\n\nWhile an interface base class is generally for providing an API that allows\ndecoupling two pieces of code, a polymorphic type is a collaboration between a\nbase and derived type to provide some functionality. This is a bit like the\ndifference between a library and a framework, where you might use many of the\nformer but only one of the latter.\n\nInterface base classes are primarily used for subtyping. The extent of\nimplementation reuse is generally limited by the lack of data members, and the\ndecoupling role they play is usually about defining an API as a set of public\npure-virtual methods. Compared to other polymorphic types, they more rarely have\nmethods with implementations (virtual or not), or have methods with restricted\naccess. The main use case is when there is a method that is implemented in terms\nof pure-virtual methods. Those pure-virtual methods may be marked as protected\nto ensure they are only called through the non-abstract API, but can still be\nimplemented in descendants.\n\nWhile it is typical for this case to be associated with single-level inheritance\nhierarchies, there are some cases where there is an interface at the root of a\ntype hierarchy and polymorphic types as interior branches of the tree. The case\nof interfaces extending or requiring other interface would also be modeled by\ndeeper inheritance hierarchies.\n\nAn interface as base class needs to either have a virtual destructor or forbid\ndeallocation.\n\nThere is significant overlap between interface base classes and\n[Carbon interfaces](generics/overview.md#interfaces). Both represent APIs as a\ncollection of method names and signatures to implement. The subset of interfaces\nthat support dynamic dispatch are called _object-safe_, following\n[Rust](https://doc.rust-lang.org/reference/items/traits.html#object-safety):\n\n-   They don't have a `Self` in the signature of a method in a contravariant\n    position like a parameter.\n-   They don't have free associated facets or other associated items used in a\n    method signature.\n\nThe restrictions on object-safe interfaces match the restrictions on base class\nmethods. The main difference is the representation in memory. A type extending a\nbase class with virtual methods includes a pointer to the table of methods in\nthe object value itself, while a type implementing an interface would store the\npointer alongside the pointer to the value in a `DynPtr(MyInterface)`. Of\ncourse, the interface option also allows the method table to be passed at\ncompile time.\n\n**Note:** This presumes that we include some concept of `final` methods in\ninterfaces to match non-virtual functions in base classes.\n\nWe expect idiomatic Carbon-only code to generally use Carbon interfaces instead\nof interface base classes. We may still support interface base classes long term\nif we determine that the ability to put the pointer to the method\nimplementations in the object value is important for users, particularly with a\nsingle parent as in the [polymorphic type case](#polymorphic-types). Extending\nthis design to support interface base classes is future work.\n\n**Background:**\n[C++ abstract base classes](https://en.wikipedia.org/wiki/Abstract_type) that\ndon't have data members and\n[Java interfaces](<https://en.wikipedia.org/wiki/Interface_(Java)>) model this\ncase.\n\n##### Non-polymorphic inheritance\n\nWhile it is not common, there are cases where C++ code uses inheritance without\ndynamic dispatch or a\n[vtable](https://en.wikipedia.org/wiki/Virtual_method_table). Instead, methods\nare never overridden, and derived types only add data and methods. There are\nsome cases where this is done in C++ but would be done differently in Carbon:\n\n-   For implementation reuse without subtyping, Carbon code should use mixins or\n    composition. Carbon won't support private inheritance.\n-   Carbon will allow data members to have size zero, so the\n    [empty-base optimization](https://en.cppreference.com/w/cpp/language/ebo) is\n    unnecessary.\n-   For cases where the derived type does not add any data members, in Carbon\n    you can potentially use adapter types instead of inheritance.\n\nHowever, there are still some cases where non-virtual inheritance makes sense.\nOne is a parameterized type where a prefix of the data is the same independent\nof the parameter. An example of this is containers with a\n[small-buffer optimization](https://akrzemi1.wordpress.com/2014/04/14/common-optimizations/#sbo),\nas described in the talk\n[CppCon 2016: Chandler Carruth \"High Performance Code 201: Hybrid Data Structures\"](https://www.youtube.com/watch?v=vElZc6zSIXM).\nBy moving the data and methods that don't depend on the buffer size to a base\nclass, we reduce the instantiation overhead for monomorphization. The base type\nis also useful for reducing instantiation for consumers of the container, as\nlong as they only need to access methods defined in the base.\n\nAnother case for non-virtual inheritance is for different node types within a\ndata structure that have some data members in common. This is done in LLVM's\nmap,\n[red-black tree](https://github.com/llvm-mirror/libcxx/blob/master/include/__tree),\nand list data structure types. In a linked list, the base type might have the\nnext and previous pointers, which is enough for a sentinel node, and there would\nalso be a derived type with the actual data member. The base type can define\noperations like \"splice\" that only operate on the pointers not the data, and\nthis is in fact enforced by the type system. Only the derived node type needs to\nbe parameterized by the element type, saving on instantiation costs as before.\n\nMany of the concerns around non-polymorphic inheritance are the same as for the\nnon-virtual methods of [polymorphic types](#polymorphic-types). Assignment and\ndestruction are examples of operations that need particular care to be sure they\nare only done on values of the correct type, rather than through a subtyping\nrelationship. This means having some extrinsic way of knowing when it is safe to\ndowncast before performing one of those operations, or performing them on\npointers that were never upcast to the base type.\n\n##### Interop with C++ multiple inheritance\n\nWhile Carbon won't support all the C++ forms of multiple inheritance, Carbon\ncode will still need to interoperate with C++ code that does. Of particular\nconcern are the `std::iostream` family of types. Most uses of those types are\nthe input and output variations or could be migrated to use those variations,\nnot the harder bidirectional cases.\n\nMuch of the complexity of this interoperation could be alleviated by adopting\nthe restriction that Carbon code can't directly access the fields of a virtual\nbase class. In the cases where such access is needed, the workaround is to\naccess them through C++ functions.\n\nWe do not expect idiomatic Carbon-only code to use multiple inheritance.\nExtending this design to support interoperating with C++ types using multiple\ninheritance is future work.\n\n### Mixins\n\nA [mixin](https://en.wikipedia.org/wiki/Mixin) is a declaration of data,\nmethods, and interface implementations that can be added to another type, called\nthe \"main type\". The methods of a mixin may also use data, methods, and\ninterface implementations provided by the main type. Mixins are designed around\nimplementation reuse rather than subtyping, and so don't need to use a vtable.\n\nA mixin might be an implementation detail of a [data class](#data-classes), or\n[encapsulated type](#encapsulated-types). A mixin might partially implement an\n[interface as base class](#interface-as-base-class).\n\n**Examples:**\n[intrusive linked list](https://www.boost.org/doc/libs/1_63_0/doc/html/intrusive.html),\nintrusive reference count\n\nIn both of these examples, the mixin needs the ability to convert between a\npointer to the mixin's data (like a \"next\" pointer or reference count) and a\npointer to the containing object with the main type.\n\nMixins are expected in idiomatic Carbon-only code. Extending this design to\nsupport mixins is future work.\n\n**Background:** Mixins are typically implemented using the\n[curiously recurring template pattern](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)\nin C++, but other languages support them directly.\n\n-   In Dart, the mixin defines an interface that the destination type ends up\n    implementing, which restores a form of subtyping. See\n    [Dart: What are mixins?](https://medium.com/flutter-community/dart-what-are-mixins-3a72344011f3).\n-   Swift is considering\n    [a proposal to add mixin support](https://github.com/Anton3/swift-evolution/blob/mixins/proposals/NNNN-mixins.md).\n\n## Background\n\nSee how other languages tackle this problem:\n\n-   [Swift](https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html)\n    -   has two different concepts: classes support\n        [inheritance](https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html)\n        and use\n        [reference counting](https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html)\n        while structs have value semantics\n    -   may have\n        [constructor functions called \"initializers\"](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html)\n        and\n        [destructors called \"deinitializers\"](https://docs.swift.org/swift-book/LanguageGuide/Deinitialization.html)\n    -   supports\n        [properties](https://docs.swift.org/swift-book/LanguageGuide/Properties.html),\n        including computed & lazy properties\n    -   methods are const by default\n        [unless marked mutating](https://docs.swift.org/swift-book/LanguageGuide/Methods.html#ID239)\n    -   supports\n        [extensions](https://docs.swift.org/swift-book/LanguageGuide/Extensions.html)\n    -   has per-field\n        [access control](https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html)\n-   [Rust](https://doc.rust-lang.org/book/ch05-01-defining-structs.html)\n    -   has no support for inheritance\n    -   has no special constructor functions, instead has literal syntax\n    -   has some convenience syntax for common cases:\n        [variable and field names matching](https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-the-field-init-shorthand-when-variables-and-fields-have-the-same-name),\n        [updating a subset of fields](https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax)\n    -   [can have unnamed fields](https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types)\n    -   [supports structs with size 0](https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields)\n-   [Zig](https://ziglang.org/documentation/0.6.0/#struct)\n    -   [explicitly mark structs as packed to manually control layout](https://ziglang.org/documentation/0.6.0/#packed-struct)\n    -   has a struct literal syntax,\n        [including for anonymous structs](https://ziglang.org/documentation/0.6.0/#Anonymous-Struct-Literals)\n    -   no special constructor functions\n    -   supports fields with undefined values\n    -   supports structs with size 0\n    -   supports generics by way of memoized compile time functions accepting\n        and returning types\n    -   [supports default field values](https://ziglang.org/documentation/0.6.0/#toc-Default-Field-Values)\n    -   [has no properties or operator overloading -- Zig does not like hidden control flow](https://ziglang.org/#Small-simple-language)\n\n## Members\n\nThe members of a class are named, and are accessed with the `.` notation. For\nexample:\n\n```\nvar p: Point2D = ...;\n// Data member access\np.x = 1;\np.y = 2;\n// Method call\nPrint(p.DistanceFromOrigin());\n```\n\n[Tuples](tuples.md) are used for cases where accessing the members positionally\nis more appropriate.\n\n### Data members have an order\n\nThe data members of a class, or _fields_, have an order that matches the order\nthey are declared in. This determines the order of those fields in memory, and\nthe order that the fields are destroyed when a value goes out of scope or is\ndeallocated.\n\n## Struct types\n\n_Structural data classes_, or _struct types_, are convenient for defining\n[data classes](#data-classes) in an ad-hoc manner. They would commonly be used:\n\n-   as the return type of a function that returns multiple values and wants\n    those values to have names so a [tuple](tuples.md) is inappropriate\n-   as an initializer for other `class` variables or values\n-   as a type parameter to a container\n\nNote that struct types are examples of _data class types_ and are still classes.\nThe [\"nominal data classes\" section](#nominal-data-classes) describes another\nway to define a data class type. Also note that there is no `struct` keyword,\n\"struct\" is just convenient shorthand terminology for a structural data class.\n\n### Literals\n\n_Structural data class literals_, or _struct literals_, are written using this\nsyntax:\n\n```\nvar kvpair: auto = {.key = \"the\", .value = 27};\n```\n\nThis produces a struct value with two fields:\n\n-   The first field is named \"`key`\" and has the value `\"the\"`. The type of the\n    field is set to the type of the value, and so is `String`.\n-   The second field is named \"`value`\" and has the value `27`. The type of the\n    field is set to the type of the value, and so is `i32`.\n\nNote: A comma `,` may optionally be included after the last field:\n\n```\nvar kvpair: auto = {.key = \"the\", .value = 27,};\n```\n\n**Open question:** To keep the literal syntax from being ambiguous with compound\nstatements, Carbon will adopt some combination of:\n\n-   looking ahead after a `{` to see if it is followed by `.name`;\n-   not allowing a struct literal at the beginning of a statement;\n-   only allowing `{` to introduce a compound statement in contexts introduced\n    by a keyword where they are required, like requiring `{ ... }` around the\n    cases of an `if...else` statement.\n\n### Type expression\n\nThe type of `kvpair` in the last example would be represented by this\nexpression:\n\n```\n{.key: String, .value: i32}\n```\n\nThis syntax is intended to parallel the literal syntax, and so uses commas (`,`)\nto separate fields instead of a semicolon (`;`) terminator. This choice also\nreflects the expected use inline in function signature declarations.\n\nStruct types may only have data members, so the type declaration is just a list\nof field names and types. The result of a struct type expression is an immutable\ncompile-time type value.\n\nNote: Like with struct literal expressions, a comma `,` may optionally be\nincluded after the last field:\n\n```\n{.key: String, .value: i32,}\n```\n\nAlso note that `{}` represents both the empty struct literal and its type.\n\n### Assignment and initialization\n\nWhen initializing or assigning a variable with a data class such as a struct\ntype to a struct value on the right hand side, the order of the fields does not\nhave to match, just the names.\n\n```\nvar different_order: {.x: i32, .y: i32} = {.y = 2, .x = 3};\nAssert(different_order.x == 3);\nAssert(different_order.y == 2);\n```\n\nInitialization and assignment occur field-by-field. The order of fields is\ndetermined by the source on the right side of the `=`, and individual operations\nare generally interleaved field-by-field. See [here](values.md#type-conversions)\nfor details about the semantics, and\n[here](pattern_matching.md#evaluation-order) for details about the order of\noperations.\n\n> **Open question:** Do we need a way for a class to require the source order to\n> match? Should that be the default, with an opt out?\n\n> **Open question:** What operations and in what order happen for assignment?\n>\n> -   Is assignment just destruction followed by initialization? Is that\n>     destruction completed for the whole object before initializing, or is it\n>     interleaved field-by-field?\n> -   Perhaps some operations are _not_ ordered with respect to each other?\n\n### Operations performed field-wise\n\nGenerally speaking, the operations that are available on a data class value,\nsuch as a value with a struct type, are dependent on those operations being\navailable for all the types of the fields.\n\nFor example, two values of the same data class type may be compared for equality\nor inequality if equality is supported for every member of the type:\n\n```\nvar p: auto = {.x = 2, .y = 3};\nAssert(p == {.x = 2, .y = 3});\nAssert(p != {.x = 2, .y = 4});\nAssert({.x = 2, .y = 4} != {.x = 5, .y = 3});\n```\n\nEquality and inequality comparisons are also allowed between different data\nclass types when:\n\n-   At least one is a struct type.\n-   They have the same set of field names, though the order may be different.\n-   Equality comparison is defined between the pairs of member types with the\n    same field names.\n\nFor example, since\n[comparison between `i32` and `u32` is defined](/proposals/p0702.md#built-in-comparisons-and-implicit-conversions),\nequality comparison between values of types `{.x: i32, .y: i32}` and\n`{.y: u32, .x: u32}` is as well. Equality and inequality comparisons compare\nfields using the field order of the left-hand operand and stop once the outcome\nof the comparison is determined. However, the comparison order and\nshort-circuiting are generally expected to affect only the performance\ncharacteristics of the comparison and not its meaning.\n\nOrdering comparisons, such as `<` and `<=`, use the order of the fields to do a\n[lexicographical comparison](https://en.wikipedia.org/wiki/Lexicographic_order).\nThe argument types must have a matching order of the field names. Otherwise, the\nrestrictions on ordering comparisons between different data class types are\nanalogous to equality comparisons:\n\n-   At least one is a struct type.\n-   Ordering comparison is defined between the pairs of member types with the\n    same field names.\n\nImplicit conversion from a struct type to a data class type is allowed when the\nset of field names is the same and implicit conversion is defined between the\npairs of member types with the same field names. So calling a function\neffectively performs an initialization of each of the function's parameters from\nthe caller's arguments, and will be valid when those initializations are all\nvalid.\n\nA data class has an unformed state if all its members do. Treatment of unformed\nstate follows proposal\n[#257](https://github.com/carbon-language/carbon-lang/pull/257).\n\nDestruction is performed field-wise in reverse order.\n\nExtending user-defined operations on the fields to an operation on an entire\ndata class is [future work](#interfaces-implemented-for-data-classes).\n\n**References:** The rules for assignment, comparison, and implicit conversion\nfor argument passing were decided in\n[question-for-leads issue #710](https://github.com/carbon-language/carbon-lang/issues/710).\n\n## Nominal class types\n\nThe declarations for nominal class types will have:\n\n-   an optional `abstract` or `base` prefix\n-   `class` introducer\n-   the name of the class\n-   `{`, an open curly brace\n-   a sequence of declarations\n-   `}`, a close curly brace\n\nDeclarations within a class should generally have the same syntax as\ndeclarations that occur in other contexts. For example, member functions are\nintroduced with `fn`.\n\n### Fields\n\nFields of a nominal class type are declared with `var`:\n\n```\nclass TextLabel {\n  var x: i32;\n  var y: i32;\n\n  var text: String = \"default\";\n}\n```\n\nNotice that this is subtly different from the meaning of `var` in other\ncontexts: it declares an\n[instance variable](https://en.wikipedia.org/wiki/Instance_variable), not just a\nvariable in the class's scope.\n\n> **Open question:** Is there a way to declare class variables (scoped to the\n> class, not an instance)?\n\nIn a field declaration, an initializer (such as `= \"default\"` above) specifies\nthe default value of the field, and will be ignored if another value is supplied\nfor that field when constructing an instance of the class. Defaults must be\nconstants whose value can be determined at compile time.\n\nThe pattern in a field declaration must be a run-time binding pattern, so the\nfull syntax is:\n\n_field-declaration_ ::= `var` _identifier_ `:` _expression_ [ `=` _expression_\n] `;`\n\n### Forward declaration\n\nTo support circular references between class types, we allow\n[forward declaration](https://en.wikipedia.org/wiki/Forward_declaration) of\ntypes. Forward declarations end with semicolon `;` after the name of the class,\ninstead of the block of declarations in curly braces `{`...`}`. A type that is\nforward declared is considered incomplete until the end of a definition with the\nsame name.\n\n```\n// Forward declaration of `GraphNode`.\nclass GraphNode;\n\nclass GraphEdge {\n  var head: GraphNode*;\n  var tail: GraphNode*;\n}\n\nclass GraphNode {\n  var edges: Vector(GraphEdge*);\n}\n// `GraphNode` is first complete here.\n```\n\n**Open question:** What is specifically allowed and forbidden with an incomplete\ntype has not yet been decided.\n\n> **TODO:** Document that qualified names can be looked up in an incomplete\n> type, as adopted in\n> [p5087: Qualified lookup into types being defined](/proposals/p5087.md).\n\n### `Self`\n\nA `class` definition may provisionally include references to its own name in\nlimited ways. These limitations arise from the type not being complete until the\nend of its definition is reached.\n\n```\nclass IntListNode {\n  var data: i32;\n  var next: IntListNode*;\n}\n```\n\nAn equivalent definition of `IntListNode`, since the `Self` keyword is an alias\nfor the current type, is:\n\n```\nclass IntListNode {\n  var data: i32;\n  var next: Self*;\n}\n```\n\n`Self` refers to the innermost type declaration:\n\n```\nclass IntList {\n  class IntListNode {\n    var data: i32;\n    // `Self` is `IntListNode`, not `IntList`.\n    var next: Self*;\n  }\n  var first: IntListNode*;\n}\n```\n\n### Construction\n\nAny function with access to all the data fields of a class can construct one by\nconverting a [struct value](#struct-types) to the class type:\n\n```\nvar tl1: TextLabel = {.x = 1, .y = 2};\nvar tl2: auto = {.x = 1, .y = 2} as TextLabel;\n\nAssert(tl1.x == tl2.x);\n\nfn ReturnsATextLabel() -> TextLabel {\n  return {.x = 1, .y = 2};\n}\nvar tl3: TextLabel = ReturnsATextLabel();\n\nfn AcceptsATextLabel(tl: TextLabel) -> i32 {\n  return tl.x + tl.y;\n}\nAssert(AcceptsATextLabel({.x = 2, .y = 4}) == 6);\n```\n\nNote that a nominal class, unlike a [struct type](#type-expression), can define\ndefault values for fields, and so may be initialized with a\n[struct value](#literals) that omits some or all of those fields.\n\n#### Assignment\n\nAssignment to a struct value is also allowed in a function with access to all\nthe data fields of a class. Assignment always overwrites all of the field\nmembers.\n\n```\nvar tl: TextLabel = {.x = 1, .y = 2};\nAssert(tl.text == \"default\");\n\n// ✅ Allowed: assigns all fields\ntl = {.x = 3, .y = 4, .text = \"new\"};\n\n// ✅ Allowed: This statement is evaluated in two steps:\n// 1. {.x = 5, .y = 6} is converted into a new TextLabel value,\n//    using default for field `text`.\n// 2. tl is assigned to a TextLabel, which has values for all\n//    fields.\ntl = {.x = 5, .y = 6};\nAssert(tl.text == \"default\");\n```\n\n**Open question:** This behavior might be surprising because there is an\nambiguity about whether to use the default value or the previous value for a\nfield. We could require all fields to be specified when assigning, and only use\nfield defaults when initializing a new value.\n\n```\n// ❌ Forbidden: should tl.text == \"default\" or \"new\"?\ntl = {.x = 5, .y = 6};\n```\n\n### Member functions\n\nMember functions can either be class functions or methods. Class functions are\nmembers of the type, while methods can only be called on instances.\n\n#### Class functions\n\nA class function is like a\n[C++ static member function](https://en.cppreference.com/w/cpp/language/static#Static_member_functions),\nand is declared like a function at file scope. The declaration can include a\ndefinition of the function body, or that definition can be provided out of line\nafter the class definition is finished. A common use is for constructor\nfunctions.\n\n```\nclass Point {\n  fn Origin() -> Self {\n    return {.x = 0, .y = 0};\n  }\n  fn CreateCentered() -> Self;\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Point.CreateCentered() -> Self {\n  return {.x = ScreenWidth() / 2, .y = ScreenHeight() / 2};\n}\n```\n\nClass functions are members of the type, and may be accessed as using dot `.`\nmember access either the type or any instance.\n\n```\nvar p1: Point = Point.Origin();\nvar p2: Point = p1.CreateCentered();\n```\n\n#### Methods\n\n[Method](<https://en.wikipedia.org/wiki/Method_(computer_programming)>)\ndeclarations are distinguished from [class function](#class-functions)\ndeclarations by having a `self` parameter in square brackets `[`...`]` before\nthe explicit parameter list in parens `(`...`)`. There is no implicit member\naccess in methods, so inside the method body members are accessed through the\n`self` parameter. Methods may be written lexically inline or after the class\ndeclaration.\n\n```carbon\nclass Circle {\n  fn Diameter[self: Self]() -> f32 {\n    return self.radius * 2;\n  }\n  fn Expand[ref self: Self](distance: f32);\n\n  var center: Point;\n  var radius: f32;\n}\n\nfn Circle.Expand[ref self: Self](distance: f32) {\n  self.radius += distance;\n}\n\nvar c: Circle = {.center = Point.Origin(), .radius = 1.5 };\nAssert(Math.Abs(c.Diameter() - 3.0) < 0.001);\nc.Expand(0.5);\nAssert(Math.Abs(c.Diameter() - 4.0) < 0.001);\n```\n\n-   Methods are called using the dot `.` member syntax, `c.Diameter()` and\n    `c.Expand(`...`)`.\n-   `Diameter` computes and returns the diameter of the circle without modifying\n    the `Circle` instance. This is signified using `[self: Self]` in the method\n    declaration.\n-   `c.Expand(`...`)` does modify the value of `c`. This is signified using\n    `[ref self: Self]` in the method declaration.\n\nThe pattern '`ref self:` _type_' means \"the argument must be a\n[reference expression](/docs/design/values.md#reference-expressions), and must\nmatch the pattern '`self:` _type_'\".\n\nIf the method declaration also includes\n[deduced compile-time parameters](/docs/design/generics/overview.md#deduced-parameters),\nthe `self` parameter must be in the same list in square brackets `[`...`]`. The\n`self` parameter may appear in any position in that list, as long as it appears\nafter any names needed to describe its type.\n\n#### Deferred member function definitions\n\nWhen defining a member function lexically inline, the body is deferred and\nprocessed as if it appeared immediately after the end of the outermost enclosing\nclass, like in C++.\n\nFor example, given a class with inline function definitions:\n\n```carbon\nclass Point {\n  fn Distance[self: Self]() -> f32 {\n    return Math.Sqrt(self.x * self.x + self.y * self.y);\n  }\n\n  fn Make(x: f32, y: f32) -> Point {\n    return {.x = x, .y = y};\n  }\n\n  var x: f32;\n  var y: f32;\n}\n```\n\nThese are all parsed as if they were defined outside the class scope:\n\n```carbon\nclass Point {\n  fn Distance[self: Self]() -> f32;\n  fn Make(x: f32, y: f32) -> Point;\n\n  var x: f32;\n  var y: f32;\n}\n\nfn Point.Distance[self: Self]() -> f32 {\n  return Math.Sqrt(self.x * self.x + self.y * self.y);\n}\n\nfn Point.Make(x: f32, y: f32) -> Point {\n  return {.x = x, .y = y};\n}\n```\n\n#### Name lookup in classes\n\n[Member access](expressions/member_access.md) is an expression; details are\ncovered there. Because function definitions are\n[deferred](#deferred-member-function-definitions), name lookup in classes works\nthe same regardless of whether a function is inline. The class body forms a\nscope for name lookup, and function definitions can perform unqualified name\nlookup within that scope.\n\nFor example:\n\n```carbon\nclass Square {\n  fn GetArea[self: Self]() -> f32 {\n    // ✅ OK: performs name lookup on `self`.\n    return self.size * self.size;\n    // ❌ Error: finds `Square.size`, but an instance is required.\n    return size * size;\n    // ❌ Error: an instance is required.\n    return Square.size * Square.size;\n    // ✅ OK: performs instance binding with `self`.\n    return self.(Square.size) * self.(Square.size);\n    // ✅ OK: uses unqualified name lookup to find `Square.size`, then performs\n    // instance binding with `self`.\n    return self.(size) * self.(size);\n  }\n\n  fn GetDoubled[self: Self]() -> Square {\n    // ✅ OK: performs name lookup on `Square` for `Create`.\n    return Square.Make(self.size);\n    // ✅ OK: performs unqualified name lookup within class scope for `Create`.\n    return Make(self.size);\n    // ✅ OK: performs name lookup on `self` for `Create`.\n    return self.Make(self.size);\n  }\n\n  fn Make(size: f32) -> Square;\n\n  var size: f32;\n}\n```\n\nThe example's name lookups refer to `Create` and `size` which are defined after\nthe example member access; this is valid because of\n[deferred member function definitions](#deferred-member-function-definitions).\n\nHowever, function signatures must still complete lookup without deferring. For\nexample:\n\n```carbon\nclass List {\n  // ❌ Error: `Iterator` has not yet been defined.\n  fn Iterate() -> Iterator;\n\n  class Iterator {\n    ...\n  }\n\n  // ✅ OK: The definition of Iterator is now available.\n  fn Iterate() -> Iterator;\n}\n```\n\nAn out-of-line function definition's parameters, return type, and body are\nevaluated as if in-scope. For example:\n\n```carbon\n// ✅ OK: The return type performs unqualified name lookup into `List` for\n// `Iterator`.\nfn List.Iterate() -> Iterator {\n  ...\n}\n```\n\n### Nominal data classes\n\nWe will mark [data classes](#data-classes) with an `impl as Data {}` line.\n\n```\nclass TextLabel {\n  var x: i32;\n  var y: i32;\n\n  var text: String;\n\n  // This line makes `TextLabel` a data class, which defines\n  // a number of operations field-wise.\n  impl as Data {}\n}\n```\n\nThe fields of data classes must all be public. That line will add\n[field-wise implementations and operations of all interfaces that a struct with the same fields would get by default](#operations-performed-field-wise).\n\nThe word `Data` here refers to an empty interface in the Carbon prologue. That\ninterface would then be part of our\n[strategy for defining how other interfaces are implemented for data classes](#interfaces-implemented-for-data-classes).\n\n**References:** Rationale for this approach is given in proposal\n[#722](/proposals/p0722.md#nominal-data-class).\n\n### Member type\n\nAdditional types may be defined in the scope of a class definition.\n\n```\nclass StringCounts {\n  class Node {\n    var key: String;\n    var count: i32;\n  }\n  var counts: Vector(Node);\n}\n```\n\nThe inner type is a member of the type, and is given the name\n`StringCounts.Node`. This case is called a _member class_ since the type is a\nclass, but other kinds of type declarations, like choice types, are allowed.\n\n### Let\n\nOther type constants can be defined using a `let` declaration:\n\n```\nclass MyClass {\n  let Pi:! f32 = 3.141592653589793;\n  let IndexType:! type = i32;\n}\n```\n\nThe `:!` indicates that this is defining a compile-time constant, and so does\nnot affect the storage of instances of that class.\n\n### Alias\n\nYou may declare aliases of the names of class members. This is to allow them to\nbe renamed in multiple steps or support alternate names.\n\n```\nclass StringPair {\n  var key: String;\n  var value: String;\n  alias first = key;\n  alias second = value;\n}\n\nvar sp1: StringPair = {.key = \"K\", .value = \"1\"};\nvar sp2: StringPair = {.first = \"K\", .second = \"2\"};\nAssert(sp1.first == sp2.key);\nAssert(&sp1.first == &sp1.key);\n```\n\n**Future work:** This needs to be connected to the broader design of aliases,\nonce that lands.\n\n### Inheritance\n\nCarbon supports\n[inheritance](<https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)>)\nusing a\n[class hierarchy](<https://en.wikipedia.org/wiki/Class_(computer_programming)#Hierarchical>),\non an opt-in basis. Classes by default are\n[_final_](<https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Non-subclassable_classes>),\nwhich means they may not be extended. To declare a class as allowing extension,\nuse either the `base class` or `abstract class` introducer:\n\n```\nbase class MyBaseClass { ... }\n```\n\nA _base class_ may be _extended_ to get a _derived class_:\n\n```\nbase class MiddleDerived {\n  extend base: MyBaseClass;\n  ...\n}\nclass FinalDerived {\n  extend base: MiddleDerived;\n  ...\n}\n// ❌ Forbidden: class Illegal { extend base: FinalDerived; ... }\n// may not extend `FinalDerived` since not declared `base` or `abstract`.\n```\n\nAn _[abstract class](https://en.wikipedia.org/wiki/Abstract_type)_ or _abstract\nbase class_ is a base class that may not be instantiated.\n\n```\nabstract class MyAbstractClass { ... }\n// ❌ Forbidden: var a: MyAbstractClass = ...;\n```\n\n**Future work:** For now, the Carbon design only supports single inheritance. In\nthe future, Carbon will support multiple inheritance with limitations on all\nbase classes except the one listed first.\n\n**Terminology:** We say `MiddleDerived` and `FinalDerived` are _derived\nclasses_, transitively extending or _derived from_ `MyBaseClass`. Similarly\n`FinalDerived` is derived from or extends `MiddleDerived`. `MiddleDerived` is\n`FinalDerived`'s _immediate base class_, and both `MiddleDerived` and\n`MyBaseClass` are base classes of `FinalDerived`. Base classes that are not\nabstract are called _extensible classes_.\n\nA derived class has all the members of the class it extends, including data\nmembers and methods, though it may not be able to access them if they were\ndeclared `private`.\n\n#### Virtual methods\n\nA base class may define\n[virtual methods](https://en.wikipedia.org/wiki/Virtual_function). These are\nmethods whose implementation may be overridden in a derived class.\n\nOnly methods defined in the scope of the class definition may be virtual, not\nany defined in\n[out-of-line interface `impl` declarations](/docs/design/generics/details.md#out-of-line-impl).\nInterface methods may be implemented using virtual methods when the\n[impl is inline](/docs/design/generics/details.md#inline-impl), and calls to\nthose methods by way of the interface will do virtual dispatch just like a\ndirect call to the method does.\n\n[Class functions](#class-functions) may not be declared virtual. Neither may\nfunctions with [compile-time parameters](/docs/design/generics/overview.md),\nwhether those are `template` or checked, explicit or deduced. Compile-time\nparameters on the enclosing scope are allowed, though, so generic classes may\nhave virtual methods.\n\n##### Virtual modifier keywords\n\nA method is declared as virtual by using a _virtual modifier keyword_ in its\ndeclaration before `fn`.\n\n```\nbase class MyBaseClass {\n  virtual fn Overridable[self: Self]() -> i32 { return 7; }\n}\n```\n\nThis matches C++, and makes it relatively easy for authors of derived classes to\nfind the functions that can be overridden.\n\nIf no keyword is specified, the default for methods is that they are\n_non-virtual_. This means:\n\n-   they can't override methods in bases of this class;\n-   they can't be overridden in derived classes; and\n-   they have an implementation in the current class, and that implementation\n    must work for all derived classes.\n\nThere are three virtual modifier keywords:\n\n-   `virtual` - This marks a method as not present in bases of this class and\n    having an implementation in this class. That implementation may be\n    overridden in derived classes.\n-   `abstract` - This marks a method that must be overridden in a derived class\n    since it has no implementation in this class. This is short for \"abstract\n    virtual\" but is called\n    [\"pure virtual\" in C++](https://en.wikipedia.org/wiki/Virtual_function#Abstract_classes_and_pure_virtual_functions).\n    Only abstract classes may have unimplemented abstract methods.\n-   `override` - This marks a method that overrides a method marked `virtual` or\n    `abstract` in the base class with an implementation specific to -- and\n    defined within -- this class. The method is still virtual and may be\n    overridden again in subsequent derived classes if this is a base class. See\n    [method overriding in Wikipedia](https://en.wikipedia.org/wiki/Method_overriding).\n    Requiring a keyword when overriding allows the compiler to diagnose when the\n    derived class accidentally uses the wrong signature or spelling and so\n    doesn't match the base class.\n\n| Keyword on<br />method in `C` | Allowed in<br />`abstract class C` | Allowed in<br />`base class C` | Allowed in<br />final `class C` | in `B` where<br />`C` extends `B`                            | in `D` where<br />`D` extends `C`                                                    |\n| ----------------------------- | ---------------------------------- | ------------------------------ | ------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------ |\n| `virtual`                     | ✅                                 | ✅                             | ❌                              | _not present_                                                | `abstract`<br />`override`<br />_not mentioned_                                      |\n| `abstract`                    | ✅                                 | ❌                             | ❌                              | _not present_<br />`virtual`<br />`abstract`<br />`override` | `abstract`<br />`override`<br />_may not be<br />mentioned if<br />`D` is not final_ |\n| `override`                    | ✅                                 | ✅                             | ✅                              | `virtual`<br />`abstract`<br />`override`                    | `abstract`<br />`override`                                                           |\n\nSince validating a method with a virtual modifier keyword involves looking for\nmethods with the same name in the base class, virtual methods must be declared\nafter the `extend base` declaration when present in a class definition. This\nsimplifies the compiler, and follows the\n[information accumulation principle](/docs/project/principles/information_accumulation.md).\n\n#### Subtyping\n\nA pointer to a base class, like `MyBaseClass*` is actually considered to be a\npointer to that type or any derived class, like `MiddleDerived` or\n`FinalDerived`. This means that a `FinalDerived*` value may be implicitly cast\nto type `MiddleDerived*` or `MyBaseClass*`.\n\nThis is accomplished by making the data layout of a type extending `MyBaseClass`\nhave `MyBaseClass` as a prefix. In addition, the first class in the inheritance\nchain with a virtual method will include a virtual pointer, or _vptr_, pointing\nto a [virtual method table](https://en.wikipedia.org/wiki/Virtual_method_table),\nor _vtable_. Any calls to virtual methods will perform\n[dynamic dispatch](https://en.wikipedia.org/wiki/Dynamic_dispatch) by calling\nthe method using the function pointer in the vtable, to get the overridden\nimplementation from the most derived class that implements the method.\n\nThis data layout is reflected in the order of declarations in a class\ndefinition. An `extend base` declaration, when present in a class definition,\nmust appear before any other declarations adding data to the class instances,\nsuch as instance variables.\n\nSince a final class may not be extended, the compiler can bypass the vtable and\nuse [static dispatch](https://en.wikipedia.org/wiki/Static_dispatch). In\ngeneral, you can use a combination of an abstract base class and a final class\ninstead of an extensible class if you need to distinguish between \"exactly a\ntype\" and \"possibly a subtype.\"\n\n```\nbase class Extensible { ... }\n\n// Can be replaced by:\n\nabstract class ExtensibleBase { ... }\nclass ExactlyExtensible {\n  extend base: ExtensibleBase;\n  ...\n}\n```\n\n#### `Self` refers to the current type\n\nNote that `Self` in a class definition means \"the current type being defined\"\nnot \"the type implementing this method.\" To implement a method in a derived\nclass that uses `Self` in the declaration in the base class, only the type of\n`self` should change:\n\n```\nbase class B1 {\n  virtual fn F[self: Self](x: Self) -> Self;\n  // Means exactly the same thing as:\n  //   virtual fn F[self: B1](x: B1) -> B1;\n}\n\nclass D1 {\n  extend base: B1;\n  // ❌ Illegal:\n  //   override fn F[self: Self](x: Self) -> Self;\n  // since that would mean the same thing as:\n  //   override fn F[self: Self](x: D1) -> D1;\n  // and `D1` is a different type than `B1`.\n\n  // ✅ Allowed: Parameter and return types\n  //  of `F` match declaration in `B1`.\n  override fn F[self: Self](x: B1) -> B1;\n  // Or: override fn F[self: D1](x: B1) -> B1;\n}\n```\n\nThe exception is when there is a [subtyping relationship](#subtyping) such that\nit would be legal for a caller using the base classes signature to actually be\ncalling the derived implementation, as in:\n\n```\nbase class B2 {\n  virtual fn Clone[self: Self]() -> Self*;\n  // Means exactly the same thing as:\n  //   virtual fn Clone[self: B2]() -> B2*;\n}\n\nclass D2 {\n  extend base: B2;\n  // ✅ Allowed\n  override fn Clone[self: Self]() -> Self*;\n  // Means the same thing as:\n  //   override fn Clone[self: D2]() -> D2*;\n  // which is allowed since `D2*` is a\n  // subtype of `B2*`.\n}\n```\n\n#### Constructors\n\nLike for classes without inheritance, constructors for a derived class are\nordinary functions that return an instance of the derived class. Generally\nconstructor functions should return the constructed value without copying, as in\nproposal\n[#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257).\nThis means either\n[creating the object in the return statement itself](/proposals/p0257.md#function-returns-and-initialization),\nor in\n[a `returned var` declaration](/proposals/p0257.md#declared-returned-variable).\nAs before, instances can be created by casting a struct value into the class\ntype, this time with a `.base` member to initialize the members of the immediate\nbase type.\n\n```\nclass MyDerivedType {\n  extend base: MyBaseType;\n  fn Make() -> MyDerivedType {\n    return {.base = MyBaseType.Make(), .derived_field = ...};\n  }\n}\n```\n\nThere are two cases that aren't well supported with this pattern:\n\n-   Users cannot create a value of an abstract class, which is necessary when it\n    has private fields or otherwise requires initialization.\n-   Users may want to reduce the chance of mistakes from calling a method on a\n    partially constructed object. Of particular concern is calling a virtual\n    method prior to forming the derived class and so it uses the base class\n    implementation.\n\nWhile expected to be relatively rarely needed, we will address both of these\nconcerns with a specialized type just used during construction of base classes,\ncalled the partial class type for the class.\n\n##### Partial class type\n\nThe partial class type for a base class type like `MyBaseType` is written\n`partial MyBaseType`.\n\n-   Only methods that take the partial class type may be called on the partial\n    class type, so methods have to opt in to being called on an object that\n    isn't fully constructed.\n-   No virtual methods may take the partial class type, so there is no way to\n    transitively call a virtual method on an object that isn't fully\n    constructed.\n-   `partial MyBaseClass` and `MyBaseClass` have the same fields in the same\n    order with the same data layout. The only difference is that\n    `partial MyBaseClass` doesn't use (look into) its hidden vptr slot. To\n    reliably catch any bugs where virtual function calls occur in this state,\n    both fast and hardened release builds will initialize the hidden vptr slot\n    to a null pointer. Debug builds will initialize it to an alternate vtable\n    whose functions will abort the program with a clear diagnostic.\n-   Since `partial MyBaseClass` has the same data layout but only uses a subset,\n    there is a subtyping relationship between these types. A `MyBaseClass` value\n    is a `partial MyBaseClass` value, but not the other way around. So you can\n    cast `MyBaseClass*` to `partial MyBaseClass*`, but the other direction is\n    not safe.\n-   When `MyBaseClass` may be instantiated, there is a conversion from\n    `partial MyBaseClass` to `MyBaseClass`. It changes the value by filling in\n    the hidden vptr slot. If `MyBaseClass` is abstract, then attempting that\n    conversion is an error.\n-   `partial MyBaseClass` is considered final. This is despite the fact that\n    from a data layout perspective, `partial MyDerivedClass` will have\n    `partial MyBaseClass` as a prefix if `MyDerivedClass` extends `MyBaseClass`.\n    The type `partial MyBaseClass` specifically means \"exactly this and no\n    more.\" This means we don't need to look at the hidden vptr slot, and we can\n    instantiate it even if it doesn't have a virtual [destructor](#destructors).\n-   The keyword `partial` is only valid for a `base` or `abstract` class. For\n    final classes, there is no need for a second type.\n\n##### Usage\n\nThe general pattern is that base classes can define constructors returning the\npartial class type.\n\n```\nbase class MyBaseClass {\n  fn Make() -> partial Self {\n    return {.base_field_1 = ..., .base_field_2 = ...};\n  }\n  // ...\n}\n```\n\nExtensible classes can be instantiated even from a partial class type value:\n\n```\nvar mbc: MyBaseClass = MyBaseClass.Make();\n```\n\nThe conversion from `partial MyBaseClass` to `MyBaseClass` only fills in the\nvptr value and can be done in place. After the conversion, all public methods\nmay be called, including virtual methods.\n\nThe partial class type is required for abstract classes, since otherwise they\nmay not be instantiated. Constructor functions for abstract classes should be\nmarked [protected](#protected-access) so they may only be accessed in derived\nclasses.\n\n```\nabstract class MyAbstractClass {\n  protected fn Make() -> partial Self {\n    return {.base_field_1 = ..., .base_field_2 = ...};\n  }\n  // ...\n}\n// ❌ Error: can't instantiate abstract class\nvar abc: MyAbstractClass = ...;\n```\n\nIf a base class wants to store a pointer to itself somewhere in the constructor\nfunction, there are two choices:\n\n-   An extensible class could use the plain type instead of the partial class\n    type.\n\n    ```\n    base class MyBaseClass {\n      fn Make() -> Self {\n        returned var result: Self = {...};\n        StoreMyPointerSomewhere(&result);\n        return var;\n      }\n    }\n    ```\n\n-   The other choice is to explicitly cast the type of its address. This pointer\n    should not be used to call any virtual method until the object is finished\n    being constructed, since the vptr will be null.\n\n    ```\n    abstract class MyAbstractClass {\n      protected fn Make() -> partial Self {\n        returned var result: partial Self = {...};\n        // Careful! Pointer to object that isn't fully constructed!\n        StoreMyPointerSomewhere(&result as Self*);\n        return var;\n      }\n    }\n    ```\n\nThe constructor for a derived class may construct values from a partial class\ntype of the class' immediate base type or the full type:\n\n```\nabstract class MyAbstractClass {\n  protected fn Make() -> partial Self { ... }\n}\n\n// Base class returns a partial type\nbase class Derived {\n  extend base: MyAbstractClass;\n  protected fn Make() -> partial Self {\n    return {.base = MyAbstractClass.Make(), .derived_field = ...};\n  }\n  ...\n}\n\nbase class MyBaseClass {\n  fn Make() -> Self { ... }\n}\n\n// Base class returns a full type\nbase class ExtensibleDerived {\n  extend base: MyBaseClass;\n  fn Make() -> Self {\n    return {.base = MyBaseClass.Make(), .derived_field = ...};\n  }\n  ...\n}\n```\n\nAnd final classes will return a type that does not use the partial class type:\n\n```\nclass FinalDerived {\n  extend base: MiddleDerived;\n  fn Make() -> Self {\n    return {.base = MiddleDerived.Make(), .derived_field = ...};\n  }\n  ...\n}\n```\n\nObserve that the vptr is only assigned twice in release builds if you use\npartial class types:\n\n-   The first class value created, by the factory function creating the base of\n    the class hierarchy, initialized the vptr field to nullptr. Every derived\n    type transitively created from that value will leave it alone.\n-   Only when the value has its most-derived class and is converted from the\n    partial class type to its final type is the vptr field set to its final\n    value.\n\nIn the case that the base class can be instantiated, tooling could optionally\nrecommend that functions returning `Self` that are used to initialize a derived\nclass be changed to return `partial Self` instead. However, the consequences of\nreturning `Self` instead of `partial Self` when the value will be used to\ninitialize a derived class are fairly minor:\n\n-   The vptr field will be assigned more than necessary.\n-   The types won't protect against calling methods on a value while it is being\n    constructed, much like the situation in C++ currently.\n\n#### Assignment with inheritance\n\nSince the assignment operator method should not be virtual, it is only safe to\nimplement it for final types. However, following the\n[maxim that Carbon should \"focus on encouraging appropriate usage of features rather than restricting misuse\"](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\nwe allow users to also implement assignment on extensible classes, even though\nit can lead to [slicing](https://en.wikipedia.org/wiki/Object_slicing).\n\n### Destructors\n\nEvery non-abstract type is _destructible_, meaning has a defined destructor\nmethod called when the lifetime of a value of that type ends, such as when a\nvariable goes out of scope. The destructor for a class may be customized using\nthe `destroy` method:\n\n```carbon\nclass MyClass {\n  fn destroy[self: Self]() { ... }\n}\n```\n\nor:\n\n```carbon\nclass MyClass {\n  // Can modify `self` in the body.\n  fn destroy[ref self: Self]() { ... }\n}\n```\n\nIf a class has no `destroy` method, it gets the default destructor, which is\nequivalent to `fn destroy[self: Self] { }`.\n\nThe destructor for a class is run before the destructors of its data members.\nThe data members are destroyed in reverse order of declaration. Derived classes\nare destroyed before their base classes, so the order of operations is:\n\n-   derived class' destructor runs,\n-   the data members of the derived class are destroyed, in reverse order of\n    declaration,\n-   the immediate base class' destructor runs,\n-   the data members of the immediate base class are destroyed, in reverse order\n    of declaration,\n-   and so on.\n\nDestructors may be declared in class scope and then defined out-of-line:\n\n```carbon\nclass MyClass {\n  fn destroy[ref self: Self]();\n}\nfn MyClass.destroy[ref self: Self]() { ... }\n```\n\nIt is illegal to delete an instance of a derived class through a pointer to one\nof its base classes unless it has a\n[virtual destructor](https://en.wikipedia.org/wiki/Virtual_function#Virtual_destructors).\nAn abstract or base class' destructor may be declared virtual using the\n`virtual` introducer, in which case any derived class destructor declaration\nmust be `override`:\n\n```carbon\nbase class MyBaseClass {\n  virtual fn destroy[ref self: Self]() { ... }\n}\n\nclass MyDerivedClass {\n  extend base: MyBaseClass;\n  override fn destroy[ref self: Self]() { ... }\n}\n```\n\nThe properties of a type, whether type is abstract, base, or final, and whether\nthe destructor is virtual or non-virtual, determines which\n[facet types](/docs/design/generics/terminology.md#facet-type) it satisfies.\n\n-   Non-abstract classes are `Concrete`. This means you can create local and\n    member variables of this type. `Concrete` types have destructors that are\n    called when the local variable goes out of scope or the containing object of\n    the member variable is destroyed.\n-   Final classes and classes with a virtual destructor are `Deletable`. These\n    may be safely deleted through a pointer.\n-   Classes that are `Concrete`, `Deletable`, or both are `Destructible`. These\n    are types that may be deleted through a pointer, but it might not be safe.\n    The concerning situation is when you have a pointer to a base class without\n    a virtual destructor. It is unsafe to delete that pointer when it is\n    actually pointing to a derived class.\n\n**Note:** The names `Deletable` and `Destructible` are\n[**placeholders**](/proposals/p1154.md#type-of-type-naming) since they do not\nconform to the decision on\n[question-for-leads issue #1058: \"How should interfaces for core functionality be named?\"](https://github.com/carbon-language/carbon-lang/issues/1058).\n\n| Class    | Destructor  | `Concrete` | `Deletable` | `Destructible` |\n| -------- | ----------- | ---------- | ----------- | -------------- |\n| abstract | non-virtual | no         | no          | no             |\n| abstract | virtual     | no         | yes         | yes            |\n| base     | non-virtual | yes        | no          | yes            |\n| base     | virtual     | yes        | yes         | yes            |\n| final    | any         | yes        | yes         | yes            |\n\nThe compiler automatically determines which of these\n[facet types](/docs/design/generics/terminology.md#facet-type) a given type\nsatisfies. It is illegal to directly implement `Concrete`, `Deletable`, or\n`Destructible`. For more about these constraints, see\n[\"destructor constraints\" in the detailed generics design](/docs/design/generics/details.md#destructor-constraints).\n\nA pointer to `Deletable` types may be passed to the `Delete` method of the\n`Allocator` [interface](/docs/design/generics/terminology.md#interface). To\ndeallocate a pointer to a base class without a virtual destructor, which may\nonly be done when it is not actually pointing to a value with a derived type,\ncall the `UnsafeDelete` method instead. Note that you may not call\n`UnsafeDelete` on abstract types without virtual destructors, it requires\n`Destructible`.\n\n```\ninterface Allocator {\n  // ...\n  fn Delete[T:! Deletable, ref self: Self](p: T*);\n  fn UnsafeDelete[T:! Destructible, ref self: Self](p: T*);\n}\n```\n\nTo pass a pointer to a base class without a virtual destructor to a\nchecked-generic function expecting a `Deletable` type, use the\n`UnsafeAllowDelete`\n[type adapter](/docs/design/generics/details.md#adapting-types).\n\n```\nclass UnsafeAllowDelete(T:! Concrete) {\n  extend adapt T;\n  impl as Deletable {}\n}\n\n// Example usage:\nfn RequiresDeletable[T:! Deletable](p: T*);\nvar x: MyExtensible;\nRequiresDeletable(&x as UnsafeAllowDelete(MyExtensible)*);\n```\n\nIf a virtual method is transitively called from inside a destructor, the\nimplementation from the current class is used, not any overrides from derived\nclasses. It will abort the execution of the program if that method is abstract\nand not implemented in the current class.\n\n**Future work:** Allow or require destructors to be declared as taking\n`partial Self` in order to prove no use of virtual methods.\n\nTypes satisfy the\n[`TrivialDestructor`](/docs/design/generics/details.md#destructor-constraints)\nfacet type if:\n\n-   the class declaration does not define a destructor or the class defines the\n    destructor with an empty body `{ }`,\n-   all data members implement `TrivialDestructor`, and\n-   all base classes implement `TrivialDestructor`.\n\nFor example, a [struct type](#struct-types) implements `TrivialDestructor` if\nall its members do.\n\n`TrivialDestructor` implies that their destructor does nothing, which may be\nused to generate optimized specializations.\n\nThere is no provision for handling failure in a destructor. All operations that\ncould potentially fail must be performed before the destructor is called.\nUnhandled failure during a destructor call will abort the program.\n\n**Future work:** Allow or require destructors to be declared as taking\n`[var self: Self]`.\n\n**Alternatives considered:**\n\n-   [Types implement destructor interface](/proposals/p1154.md#types-implement-destructor-interface)\n-   [Prevent virtual function calls in destructors](/proposals/p1154.md#prevent-virtual-function-calls-in-destructors)\n-   [Allow functions to act as destructors](/proposals/p1154.md#allow-functions-to-act-as-destructors)\n-   [Allow private destructors](/proposals/p1154.md#allow-private-destructors)\n-   [Allow multiple conditional destructors](/proposals/p1154.md#allow-multiple-conditional-destructors)\n-   [Don't distinguish safe and unsafe delete operations](/proposals/p1154.md#dont-distinguish-safe-and-unsafe-delete-operations)\n-   [Don't allow unsafe delete](/proposals/p1154.md#dont-allow-unsafe-delete)\n-   [Allow final destructors](/proposals/p1154.md#allow-final-destructors)\n\n### Access control\n\nBy default, all members of a class are fully publicly accessible. Access can be\nrestricted by adding a keyword, called an\n[access modifier](https://en.wikipedia.org/wiki/Access_modifiers), prior to the\ndeclaration. Access modifiers are how Carbon supports\n[encapsulation](#encapsulated-types).\n\nThe [access modifier](https://en.wikipedia.org/wiki/Access_modifiers) is written\nbefore any [virtual modifier keyword](#virtual-modifier-keywords).\n\n**Rationale:** Carbon makes members public by default for a few reasons:\n\n-   The readability of public members is the most important, since we expect\n    most readers to be concerned with the public API of a type.\n-   The members that are most commonly private are the data fields, which have\n    relatively less complicated definitions that suffer less from the extra\n    annotation.\n\nAdditionally, there is precedent for this approach in modern object-oriented\nlanguages such as\n[Kotlin](https://kotlinlang.org/docs/visibility-modifiers.html) and\n[Python](https://docs.python.org/3/tutorial/classes.html), both of which are\nwell regarded for their usability.\n\nKeywords controlling visibility are attached to individual declarations instead\nof C++'s approach of labels controlling the visibility for all following\ndeclarations to\n[reduce context sensitivity](/docs/project/principles/low_context_sensitivity.md).\nThis matches\n[Rust](https://doc.rust-lang.org/reference/visibility-and-privacy.html),\n[Swift](https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html),\n[Java](http://rosettacode.org/wiki/Classes#Java),\n[C#](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers),\n[Kotlin](https://kotlinlang.org/docs/visibility-modifiers.html#classes-and-interfaces),\nand [D](https://wiki.dlang.org/Access_specifiers_and_visibility).\n\n**References:** Proposal\n[#561: Basic classes](https://github.com/carbon-language/carbon-lang/pull/561)\nincluded the decision that\n[members default to publicly accessible](/proposals/p0561.md#access-control)\noriginally asked in issue\n[#665](https://github.com/carbon-language/carbon-lang/issues/665).\n\n#### Private access\n\nAs in C++, `private` means only accessible to members of the class and any\n[friends](#friends).\n\n```carbon\nclass Point {\n  fn Distance[self: Self]() -> f32;\n  // These are only accessible to members of `Point`.\n  private var x: f32;\n  private var y: f32;\n}\n```\n\nA `private virtual` or `private abstract` method may be implemented in derived\nclasses, even though it may not be called. This allows derived classes to\ncustomize the behavior of a function called by a method of the base class, while\nstill preventing the derived class from calling it. This matches the behavior of\nC++ and is more orthogonal.\n\n**Future work:** `private` will give the member internal linkage unless it needs\nto be external because it is used in an inline method or template. We may in the\nfuture\n[add a way to specify internal linkage explicitly](/proposals/p0722.md#specifying-linkage-as-part-of-the-access-modifier).\n\n**Open questions:** Using `private` to mean \"restricted to this class\" matches\nC++. Other languages support restricting to different scopes:\n\n-   Swift supports \"restrict to this module\" and \"restrict to this file\".\n-   Rust supports \"restrict to this module and any children of this module\", as\n    well as \"restrict to this crate\", \"restrict to parent module\", and \"restrict\n    to a specific ancestor module\".\n\n**Comparison to other languages:** C++, Rust, and Swift all make class members\nprivate by default. C++ offers the `struct` keyword that makes members public by\ndefault.\n\n#### Protected access\n\nProtected members may only be accessed by members of this class, members of\nderived classes, and any [friends](#friends).\n\n```\nbase class MyBaseClass {\n  protected fn HelperClassFunction(x: i32) -> i32;\n  protected fn HelperMethod[self: Self](x: i32) -> i32;\n  protected var data: i32;\n}\n\nclass MyDerivedClass {\n  extend base: MyBaseClass;\n  fn UsesProtected[ref self: Self]() {\n    // Can access protected members in derived class\n    var x: i32 = HelperClassFunction(3);\n    self.data = self.HelperMethod(x);\n  }\n}\n```\n\n#### Friends\n\nClasses may have a _friend_ declaration:\n\n```\nclass Buddy { ... }\n\nclass Pal {\n  private var x: i32;\n  friend Buddy;\n}\n```\n\nThis declares `Buddy` to be a friend of `Pal`, which means that `Buddy` can\naccess all members of this class, even the ones that are declared `private` or\n`protected`.\n\nThe `friend` keyword is followed by the name of an existing function, type, or\nparameterized family of types. Unlike C++, it won't act as a forward declaration\nof that name. The name must be resolvable by the compiler, and so may not be a\nmember of a template.\n\n#### Test friendship\n\n**Future work:** There should be a convenient way of allowing tests in the same\nlibrary as the class definition to access private members of the class. Ideally\nthis could be done without changing the class definition itself, since it\ndoesn't affect the class' public API.\n\n#### Access control for construction\n\nA function may construct a class, by casting a struct value to the class type,\nif it has access to (write) all of its fields.\n\n**Future work:** There should be a way to limit which code can construct a class\neven when it only has public fields. This will be resolved in question-for-leads\nissue [#803](https://github.com/carbon-language/carbon-lang/issues/803).\n\n### Operator overloading\n\nDevelopers may define how standard Carbon operators, such as `+` and `/`, apply\nto custom types by implementing the\n[interface](generics/terminology.md#interface) that corresponds to that operator\nfor the types of the operands. See the\n[\"operator overloading\" section](generics/details.md#operator-overloading) of\nthe [generics design](generics/overview.md). The specific interface used for a\ngiven operator may be found in the\n[expressions design](/docs/design/expressions/README.md).\n\n## Future work\n\nThis includes features that need to be designed, questions to answer, and a\ndescription of the provisional syntax in use until these decisions have been\nmade.\n\n### Struct literal shortcut\n\nWe could allow you to write `{x, y}` as a short hand for `{.x = x, .y = y}`.\n\n### Optional named parameters\n\nStructs are being considered as a possible mechanism for implementing optional\nnamed parameters. We have three main candidate approaches: allowing struct types\nto have field defaults, having dedicated support for destructuring struct values\nin pattern contexts, or having a dedicated optional named parameter syntax.\n\n#### Field defaults for struct types\n\nIf struct types could have field defaults, you could write a function\ndeclaration with all of the optional parameters in an option struct:\n\n```\nfn SortIntVector(\n    v: Vector(i32)*,\n    options: {.stable: bool = false,\n              .descending: bool = false} = {}) {\n  // Code using `options.stable` and `options.descending`.\n}\n\n// Uses defaults of `.stable` and `.descending` equal to `false`.\nSortIntVector(&v);\nSortIntVector(&v, {});\n// Sets `.stable` option to `true`.\nSortIntVector(&v, {.stable = true});\n// Sets `.descending` option to `true`.\nSortIntVector(&v, {.descending = true});\n// Sets both `.stable` and `.descending` options to `true`.\nSortIntVector(&v, {.stable = true, .descending = true});\n// Order can be different for arguments as well.\nSortIntVector(&v, {.descending = true, .stable = true});\n```\n\n#### Destructuring in pattern matching\n\nWe might instead support destructuring struct patterns with defaults:\n\n```\nfn SortIntVector(\n    v: Vector(i32)*,\n    {stable: bool = false, descending: bool = false}) {\n  // Code using `stable` and `descending`.\n}\n```\n\nThis would allow the same syntax at the call site, but avoids\n[some concerns with field defaults](https://github.com/carbon-language/carbon-lang/pull/561#discussion_r683856715)\nand allows some other use cases such as destructuring return values.\n\n#### Discussion\n\nWe might support destructuring directly:\n\n```\nvar {key: String, value: i32} = ReturnKeyValue();\n```\n\nor by way of a mechanism that converts a struct into a tuple:\n\n```\nvar (key: String, value: i32) =\n    ReturnKeyValue().extract(.key, .value);\n// or maybe:\nvar (key: String, value: i32) =\n    ReturnKeyValue()[(.key, .value)];\n```\n\nSimilarly we might support optional named parameters directly instead of by way\nof struct types.\n\nSome discussion on this topic has occurred in:\n\n-   [question-for-leads issue #505 on named parameters](https://github.com/carbon-language/carbon-lang/issues/505)\n-   labeled params brainstorming docs\n    [1](https://docs.google.com/document/d/1Ui2OEHLwa9LZ6ktc1joJqE7_N-ZHX2gBvBpaFw6DUy8/edit?usp=sharing&resourcekey=0-6bEnyc03QePVcttPRSFoew),\n    [2](https://docs.google.com/document/d/1kK_tti4DwPqa3Oh5CgA5pWSx0g3bKlZG1yREMpq9uiU/edit?usp=sharing&resourcekey=0-oFV6tXtCVu1bcHz4oCMyMQ)\n-   [\"match\" in syntax choices doc](https://docs.google.com/document/d/1EhZA3AlY9TaCMho9jz2ynFxK-6eS6BwMAkE5jNYQzEA/edit?usp=sharing&resourcekey=0-QXEoh-b4_sQG2u636gIa1A#heading=h.y566d16ivoy2)\n\n### Inheritance\n\n#### C++ abstract base classes interoperating with object-safe interfaces\n\nWe want four things so that Carbon's object-safe interfaces may interoperate\nwith C++ abstract base classes without data members, matching the\n[interface as base class use case](#interface-as-base-class):\n\n-   Ability to convert an object-safe interface (a facet type) into an\n    C++-compatible base class (a base type), maybe using\n    `AsBaseClass(MyInterface)`.\n-   Ability to convert a C++ base class without data members (a base type) into\n    an object-safe interface (a facet type), maybe using `AsInterface(MyIBC)`.\n-   Ability to convert a (thin) pointer to an abstract base class to a `DynPtr`\n    of the corresponding interface.\n-   Ability to convert `DynPtr(MyInterface)` values to a proxy type that extends\n    the corresponding base class `AsBaseType(MyInterface)`.\n\nNote that the proxy type extending `AsBaseType(MyInterface)` would be a\ndifferent type than `DynPtr(MyInterface)` since the receiver input to the\nfunction members of the vtable for the former does not match those in the\nwitness table for the latter.\n\n#### Overloaded methods\n\nWe allow a derived class to define a [class function](#class-functions) with the\nsame name as a class function in the base class. For example, we expect it to be\npretty common to have a constructor function named `Create` at all levels of the\ntype hierarchy.\n\nBeyond that, we may want some rules or restrictions about defining methods in a\nderived class with the same name as a base class method without overriding it.\nThere are some opportunities to improve on and simplify the C++ story:\n\n-   We don't want to silently hide methods in the base class because of a method\n    with the same name in a derived class. There are uses for this in C++, but\n    it also causes problems and without multiple inheritance there isn't the\n    same need in Carbon.\n-   Overload resolution should happen before virtual dispatch.\n-   For evolution purposes, you should be able to add private members to a base\n    class that have the same name as member of a derived class without affecting\n    overload resolution on instances of the derived class, in functions that\n    aren't friends of the base class.\n\n**References:** This was discussed in\n[the open discussion on 2021-07-12](https://docs.google.com/document/d/1TvHK6HWAcCtnseMpcNsLYrgdtNy9qNrv6EaY9n063ok/edit#heading=h.40jlsrcgp8mr).\n\n#### Interop with C++ inheritance\n\nThis design directly supports Carbon classes inheriting from a single C++ class.\n\n```\nclass CarbonClass {\n  extend base: Cpp.CPlusPlusClass;\n  fn Make() -> Self {\n    return {.base = Cpp.CPlusPlusClass(...), .other_fields = ...};\n  }\n  ...\n}\n```\n\nTo allow C++ classes to extend Carbon classes, there needs to be some way for\nC++ constructors to initialize their base class:\n\n-   There could be some way to export a Carbon class that identifies which\n    factory functions may be used as constructors.\n-   We could explicitly call the Carbon factory function, as in:\n\n    ```\n    // `Base` is a Carbon class which gets converted to a\n    // C++ class for interop purposes:\n    class Base {\n    public:\n        virtual ~Base() {}\n        static auto Make() -> Base;\n    };\n\n    // In C++\n    class Derived : public Base {\n    public:\n        virtual ~Derived() override {}\n        // This isn't currently a case where C++ guarantees no copy,\n        // and so it currently still requires a notional copy and\n        // there appear to be implementation challenges with\n        // removing them. This may require an extension to make work\n        // reliably without an extraneous copy of the base subobject.\n        Derived() : Base(Base::Make()) {}\n    };\n    ```\n\n    However, this doesn't work in the case where `Base` can't be instantiated,\n    or `Base` does not have a copy constructor, even though it shouldn't be\n    called due to RVO.\n\n##### Virtual base classes\n\nTODO: Ask zygoloid to fill this in.\n\nCarbon won't support declaring virtual base classes, and the C++ interop use\ncases Carbon needs to support are limited. This will allow us to simplify the\nC++ interop by allowing Carbon to delegate initialization of virtual base\nclasses to the C++ side.\n\nThis requires that we enforce two rules:\n\n-   No multiple inheritance of C++ classes with virtual bases\n-   No C++ class extending a Carbon class that extends a C++ class with a\n    virtual base\n\n### Mixins\n\nWe will need some way to declare mixins. This syntax will need a way to\ndistinguish defining versus requiring member variables. Methods may additionally\nbe given a default definition but may be overridden. Interface implementations\nmay only be partially provided by a mixin. Mixin methods will need to be able to\nconvert between pointers to the mixin type and the main type.\n\nOpen questions include whether a mixin is its own type that is a member of the\ncontaining type, and whether mixins are templated on the containing type. Mixins\nalso complicate how constructors work.\n\n### Memory layout\n\nCarbon will need some way for users to specify the memory layout of class types\nbeyond simple ordering of fields, such as controlling the packing and alignment\nfor the whole type or individual members.\n\nWe may allow members of a derived class like to put data members in the final\npadding of its base class prefix. Tail-padding reuse has both advantages and\ndisadvantages, so we may have some way for a class to explicitly mark that its\ntail padding is available for use by a derived class,\n\nAdvantages:\n\n-   Tail-padding reuse is sometimes a nice layout optimization (eg, in Clang we\n    save 8 bytes per `Expr` by reusing tail padding).\n-   No class size regressions when migrating from C++.\n-   Special case of reusing the tail padding of a class that is empty other than\n    its tail padding is very important, to the extent that we will likely need\n    to support either zero-sized types or tail-padding reuse in order to have\n    acceptable class layouts.\n\nDisadvantages:\n\n-   Cannot use `memcpy(p, q, sizeof(Base))` to copy around base class subobjects\n    if the destination is an in-lifetime, because they might overlap other\n    objects' representations.\n-   Somewhat more complex model.\n-   We need some mechanism for disabling tail-padding reuse in \"standard layout\"\n    types.\n-   We may also have to use narrowed loads for the last member of a base class\n    to avoid accidentally creating a race condition.\n\nHowever, we can still use `memcpy` and `memset` to initialize a base class\nsubobject, even if its tail padding might be reused, so long as we guarantee\nthat no other object lives in the tail padding and is initialized before the\nbase class. In C++, that happens only due to virtual base classes getting\ninitialized early and laid out at the end of the object; if we disallow virtual\nbase classes then we can guarantee that initialization order is address order,\nremoving most of the downside of tail-padding reuse.\n\n### No `static` variables\n\nAt the moment, there is no proposal to support\n[`static` member variables](https://en.wikipedia.org/wiki/Class_variable#Static_member_variables_and_static_member_functions),\nin line with avoiding global variables more generally. Carbon may need some\nsupport in this area, though, for parity with and migration from C++.\n\n### Computed properties\n\nCarbon might want to support members of a type that are accessed like a data\nmember but return a computed value like a function. This has a number of\nimplications:\n\n-   It would be a way of publicly exposing data members for\n    [encapsulated types](#encapsulated-types), allowing for rules that otherwise\n    forbid mixing public and private data members.\n-   It would provide a more graceful evolution path from a\n    [data class](#data-classes) to an [encapsulated type](#encapsulated-types).\n-   It would give an option to start with a [data class](#data-classes) instead\n    of writing all the boilerplate to create an\n    [encapsulated type](#encapsulated-types) preemptively to allow future\n    evolution.\n-   It would let you take a variable away and put a property in its place with\n    no other code changes. The number one use for this is so you can put a\n    breakpoint in the property code, then later go back to public variable once\n    you understand who was misbehaving.\n-   We should have some guidance for when to use a computed property instead of\n    a function with no arguments. One possible criteria is when it is a pure\n    function of the state of the object and executes in an amount of time\n    similar to ordinary member access.\n\nHowever, there are likely to be differences between computed properties and\nother data members, such as the ability to take the address of them. We might\nwant to support \"read only\" data members, that can be read through the public\nAPI but only modified with private access, for data members which may need to\nevolve into a computed property. There are also questions regarding how to\nsupport assigning or modifying computed properties, such as using `+=`.\n\n### Interfaces implemented for data classes\n\nWe should define a way for defining implementations of interfaces for struct\ntypes. To satisfy coherence, these implementations would have to be defined in\nthe library with the interface definition. The syntax might look like:\n\n```\ninterface ConstructWidgetFrom {\n  fn Construct(Self) -> Widget;\n}\n\nimpl {.kind: WidgetKind, .size: i32}\n    as ConstructWidgetFrom { ... }\n```\n\nIn addition, we should define a way for interfaces to define templated blanket\nimplementations for [data classes](#data-classes) more generally. These\nimplementations will typically subject to the criteria that all the data fields\nof the type must implement the interface. An example use case would be to say\nthat a data class is serializable if all of its fields were. For this we will\nneed a facet type for capturing that criteria, maybe something like\n`DataFieldsImplement(MyInterface)`. The templated implementation will need some\nway of iterating through the fields so it can perform operations fieldwise. This\nfeature should also implement the interfaces for any tuples whose fields satisfy\nthe criteria.\n\nIt is an open question how to define implementations for binary operators. For\nexample, if `i32` is comparable to `f64`, then `{.x = 3, .y = 2.72}` should be\ncomparable to `{.x = 3.14, .y = 2}`. The trick is how to declare the criteria\nthat \"`T` is comparable to `U` if they have the same field names in the same\norder, and for every field `x`, the type of `T.x` implements `ComparableTo` for\nthe type of `U.x`.\"\n\n## Alternatives considered\n\n-   [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257)\n\n    -   [Require compile-time-proven initialization](/proposals/p0257.md#require-compile-time-proven-initialization)\n    -   [C and C++ uninitialized](/proposals/p0257.md#c-and-c-uninitialized)\n    -   [Allow passing unformed objects to parameters or returning them?](/proposals/p0257.md#allow-passing-unformed-objects-to-parameters-or-returning-them)\n    -   [Allow assigning an unformed object to another unformed object?](/proposals/p0257.md#allow-assigning-an-unformed-object-to-another-unformed-object)\n    -   [Fully destructive move (Rust)](/proposals/p0257.md#fully-destructive-move-rust)\n    -   [Completely non-destructive move (C++)](/proposals/p0257.md#completely-non-destructive-move-c)\n    -   [Named return variable in place of a return type](/proposals/p0257.md#named-return-variable-in-place-of-a-return-type)\n    -   [Allow unformed members](/proposals/p0257.md#allow-unformed-members)\n\n-   [#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561)\n\n    -   [Early proposal #98](https://github.com/carbon-language/carbon-lang/pull/98)\n    -   [Interfaces implemented for anonymous data classes](/proposals/p0561.md#interfaces-implemented-for-anonymous-data-classes)\n    -   [Access control](/proposals/p0561.md#access-control)\n    -   [Introducer for structural data class types](/proposals/p0561.md#introducer-for-structural-data-class-types)\n    -   [Terminology](/proposals/p0561.md#terminology)\n\n-   [#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722)\n\n    -   [Method syntax](/proposals/p0722.md#method-syntax)\n    -   [Marking mutating methods at the call site](/proposals/p0722.md#marking-mutating-methods-at-the-call-site)\n    -   [Differences between functions and methods](/proposals/p0722.md#differences-between-functions-and-methods)\n    -   [Specifying linkage as part of the access modifier](/proposals/p0722.md#specifying-linkage-as-part-of-the-access-modifier)\n    -   [Nominal data class](/proposals/p0722.md#nominal-data-class)\n    -   [Let constants](/proposals/p0722.md#let-constants)\n\n-   [#777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777)\n\n    -   [Classes are final by default](/proposals/p0777.md#classes-are-final-by-default)\n    -   [Allow keywords to be written when they would have no effect](/proposals/p0777.md#allow-keywords-to-be-written-when-they-would-have-no-effect)\n    -   [Different virtual override keywords](/proposals/p0777.md#different-virtual-override-keywords)\n    -   [Different virtual override keyword placement](/proposals/p0777.md#different-virtual-override-keyword-placement)\n    -   [Final methods](/proposals/p0777.md#final-methods)\n    -   [Constructors](/proposals/p0777.md#constructors)\n    -   [Implicit abstract classes](/proposals/p0777.md#implicit-abstract-classes)\n    -   [No extensible objects with non-virtual destructors](/proposals/p0777.md#no-extensible-objects-with-non-virtual-destructors)\n    -   [Separate \"exact\" and \"or derived\" variations on types](/proposals/p0777.md#separate-exact-and-or-derived-variations-on-types)\n    -   [Separate \"exact\" and \"or derived\" variations on pointers](/proposals/p0777.md#separate-exact-and-or-derived-variations-on-pointers)\n\n-   [#875: Principle: Information accumulation](https://github.com/carbon-language/carbon-lang/pull/875)\n\n    -   Allow information to be used before it is provided\n        [globally](/proposals/p0875.md#strict-global-consistency),\n        [within a file](/proposals/p0875.md#context-sensitive-local-consistency),\n        or\n        [within a top-level declaration](/proposals/p0875.md#top-down-with-minimally-deferred-type-checking).\n    -   [Do not allow inline method bodies to use members before they are declared](/proposals/p0875.md#strict-top-down)\n    -   [Do not allow separate declaration and definition](/proposals/p0875.md#disallow-separate-declaration-and-definition)\n\n-   [#981: Implicit conversions for aggregates](https://github.com/carbon-language/carbon-lang/pull/981)\n\n    -   [Field order is not significant](/proposals/p0981.md#field-order-is-not-significant)\n    -   [Different field orders are incompatible](/proposals/p0981.md#different-field-orders-are-incompatible)\n    -   [Explicit instead of implicit conversions](/proposals/p0981.md#explicit-instead-of-implicit-conversions)\n\n-   [#1154: Destructors](https://github.com/carbon-language/carbon-lang/pull/1154)\n\n    -   [Types implement destructor interface](/proposals/p1154.md#types-implement-destructor-interface)\n    -   [Prevent virtual function calls in destructors](/proposals/p1154.md#prevent-virtual-function-calls-in-destructors)\n    -   [Allow functions to act as destructors](/proposals/p1154.md#allow-functions-to-act-as-destructors)\n    -   [Allow private destructors](/proposals/p1154.md#allow-private-destructors)\n    -   [Allow multiple conditional destructors](/proposals/p1154.md#allow-multiple-conditional-destructors)\n    -   [Facet type naming](/proposals/p1154.md#type-of-type-naming)\n    -   [Other approaches to extensible classes without vtables](/proposals/p1154.md#other-approaches-to-extensible-classes-without-vtables)\n\n-   [#2107: Clarify rules around `Self` and `.Self`](https://github.com/carbon-language/carbon-lang/pull/2107)\n\n    -   [`Self` not a keyword](/proposals/p2107.md#self-not-a-keyword)\n    -   [Make `Self` a member of all types](/proposals/p2107.md#make-self-a-member-of-all-types)\n    -   [`where` operator could be associative](/proposals/p2107.md#where-operator-could-be-associative)\n\n-   [#2287: Allow unqualified name lookup for class members](https://github.com/carbon-language/carbon-lang/pull/2287)\n\n    -   [No unqualified lookup when defining outside a scope](/proposals/p2287.md#no-unqualified-lookup-when-defining-outside-a-scope)\n\n-   [#2760: Consistent `class` and `interface` syntax](https://github.com/carbon-language/carbon-lang/pull/2760)\n\n    -   [Use `extends` instead of `extend`](/proposals/p2760.md#use-extends-instead-of-extend)\n    -   [List base class in class declaration](/proposals/p2760.md#list-base-class-in-class-declaration)\n\n-   [#5017: Destructor syntax](https://github.com/carbon-language/carbon-lang/pull/5017)\n\n    -   [Destructor syntax options](/proposals/p5017.md#destructor-syntax-options)\n    -   [Destructor name options](/proposals/p5017.md#destructor-name-options)\n\n-   [#6008: Replace `impl fn` with `override fn`](https://github.com/carbon-language/carbon-lang/pull/6008)\n\n## References\n\n-   [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257)\n-   [#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561)\n-   [#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722)\n-   [#777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777)\n-   [#875: Principle: Information accumulation](https://github.com/carbon-language/carbon-lang/pull/875)\n-   [#981: Implicit conversions for aggregates](https://github.com/carbon-language/carbon-lang/pull/981)\n-   [#1154: Destructors](https://github.com/carbon-language/carbon-lang/pull/1154)\n-   [#2107: Clarify rules around `Self` and `.Self`](https://github.com/carbon-language/carbon-lang/pull/2107)\n-   [#2287: Allow unqualified name lookup for class members](https://github.com/carbon-language/carbon-lang/pull/2287)\n-   [#2760: Consistent `class` and `interface` syntax](https://github.com/carbon-language/carbon-lang/pull/2760)\n-   [#5017: Destructor syntax](https://github.com/carbon-language/carbon-lang/pull/5017)\n"
  },
  {
    "path": "docs/design/code_and_name_organization/README.md",
    "content": "# Code and name organization\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Goals and philosophy](#goals-and-philosophy)\n-   [Overview](#overview)\n    -   [Small programs](#small-programs)\n    -   [Packages](#packages)\n    -   [Sizing packages and libraries](#sizing-packages-and-libraries)\n-   [Details](#details)\n    -   [Source file introduction](#source-file-introduction)\n    -   [Name paths](#name-paths)\n    -   [Packages](#packages-1)\n        -   [`package` directives](#package-directives)\n        -   [`library` directives](#library-directives)\n        -   [`Main//default`](#maindefault)\n        -   [Files and libraries](#files-and-libraries)\n        -   [Shorthand notation for libraries in packages](#shorthand-notation-for-libraries-in-packages)\n        -   [Package name conflicts](#package-name-conflicts)\n    -   [Libraries](#libraries)\n        -   [Exporting entities from an API file](#exporting-entities-from-an-api-file)\n        -   [Granularity of libraries](#granularity-of-libraries)\n        -   [Exporting namespaces](#exporting-namespaces)\n    -   [Imports](#imports)\n        -   [Imports from the current package](#imports-from-the-current-package)\n        -   [Exporting imported names](#exporting-imported-names)\n    -   [Namespaces](#namespaces)\n        -   [Redeclaring imported namespaces](#redeclaring-imported-namespaces)\n        -   [Declaring namespace members](#declaring-namespace-members)\n        -   [Aliasing](#aliasing)\n-   [Caveats](#caveats)\n    -   [Package and library name conflicts](#package-and-library-name-conflicts)\n    -   [Potential refactorings](#potential-refactorings)\n        -   [Update imports](#update-imports)\n        -   [Between API and implementation files](#between-api-and-implementation-files)\n        -   [Other refactorings](#other-refactorings)\n    -   [Preference for few child namespaces](#preference-for-few-child-namespaces)\n    -   [Redundant markers](#redundant-markers)\n-   [Open questions](#open-questions)\n    -   [Different file extensions](#different-file-extensions)\n    -   [Imports from other languages](#imports-from-other-languages)\n    -   [Imports from URLs](#imports-from-urls)\n    -   [Test file type](#test-file-type)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Goals and philosophy\n\nImportant Carbon goals for code and name organization are:\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n\n    -   Tooling support is important for Carbon, including the possibility of a\n        package manager.\n\n    -   Developer tooling, including both IDEs and refactoring tools, are\n        expected to exist and be well-supported.\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution):\n\n    -   We should support libraries adding new structs, functions or other\n        identifiers without those new identifiers being able to shadow or break\n        existing users that already have identifiers with conflicting names.\n\n    -   We should make it easy to refactor code, including moving code between\n        files. This includes refactoring both by humans and by developer\n        tooling.\n\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development):\n\n    -   It should be easy for developer tooling to parse code, without needing\n        to parse imports for context.\n\n    -   Structure should be provided for large projects to opt into features\n        which will help maintain scaling of their codebase, while not adding\n        burdens to small projects that don't need it.\n\n## Overview\n\nCarbon [source files](source_files.md) have a `.carbon` extension, such as\n`geometry.carbon`. These files are the basic unit of compilation.\n\n### Small programs\n\nFor programs that fit into a single source file, no syntax is required to\nintroduce the file. A very simple Carbon program can consist of a single file\ncontaining only a `Run` function:\n\n```\nfn Run() -> i32 {\n  return 6 * 9;\n}\n```\n\nHowever, as the program grows larger, it is desirable to split it across\nmultiple source files. To support this,\n_libraries_<sup><small>[[define](/docs/guides/glossary.md#library)]</small></sup>\ncan be written containing pieces of the program:\n\n```\nlibrary \"Colors\";\n\nchoice Color { Red, Green, Blue }\n\nfn ColorName(c: Color) -> String;\n```\n\n```\nimpl library \"Colors\";\n\nfn ColorName(c: Color) -> String {\n  match (c) {\n    case .Red => { return \"Red\"; }\n    case .Green => { return \"Green\"; }\n    case .Blue => { return \"Blue\"; }\n  }\n}\n```\n\n```\n// Make the \"Colors\" library visible here.\nimport library \"Colors\";\n\nfn Run() {\n  Print(ColorName(Color.Red));\n}\n```\n\nA library is the basic unit of _dependency_. Separating code into multiple\nlibraries can speed up the overall build while also making it clear which code\nis being reused.\n\nA library has a single API file which defines its interface, plus zero or more\nimplementation files that can provide any implementation details that were\nomitted from the API file. These files are distinguished by whether the\n`library` declaration starts with the `impl` modifier. By convention,\nimplementation files also use a file extension of `.impl.carbon`.\n\nSeparating a library into interface and implementation may help organize code as\na library grows, or to let the build system distinguish between the dependencies\nof the API itself and its underlying implementation. Implementation files allow\nfor code to be extracted out from the API file, while only being callable from\nother files within the library, including both API and implementation files.\n\nA source file that does not specify a library is implicitly within the default\nlibrary. This is the library in which a Carbon `Run` function should reside.\n\n### Packages\n\nA program usually doesn't consist of only a single collection of source files\ndeveloped by a team of people working together. In order to make it easy for\ndifferent components of a program to be independently authored, Carbon supports\n_packages_ of code.\n\nEach source file in a package begins with a declaration of which\n_package_<sup><small>[[define](/docs/guides/glossary.md#package)]</small></sup>\nit belongs in. The package is the unit of _distribution_. The package name is a\nsingle identifier, such as `Geometry`. An example API file in the `Geometry`\npackage would start with:\n\n```\npackage Geometry;\n```\n\nA tiny package may consist of a single library with a single API file. As with\nlibraries, additional implementation files can be added to the package by using\nthe `impl` keyword in the package declaration:\n\n```\nimpl package Geometry;\n```\n\nHowever, as a package adds more files, it will probably want to separate out\ninto multiple libraries. These work exactly like the libraries described above.\nIn fact, if no package is specified for a source file, it is implicitly part of\nthe `Main` package. For example, an API file adding the library `Shapes` to the\n`Geometry` package, or `Geometry//Shapes` in\n[shorthand](#shorthand-notation-for-libraries-in-packages), would start with:\n\n```\npackage Geometry library \"Shapes\";\n```\n\nThis library can be imported within the same package by using:\n\n```\nimport library \"Shapes\";\n```\n\nThis will result in the public names declared in the `\"Shapes\"` library becoming\nvisible in the importer, for example `Circle` might refer to a public type\n`Circle` declared in library `\"Shapes\"`.\n\nFrom a different package, this library can be imported by using:\n\n```\nimport Geometry library \"Shapes\";\n```\n\nUnlike in a same-package import, this import only introduces the name\n`Geometry`, as a private name for the importer to use to refer to the `Geometry`\npackage. Names declared within this package can be found as members of the name\n`Geometry`, for example `Geometry.Circle`. The `library` portion is optional in\nthis syntax, and if omitted, the default (unnamed) library is imported.\n\n```\n// Imports the source file beginning `package Geometry;`\nimport Geometry;\n```\n\nThe default library of a named package can be imported within that same package\nby using:\n\n```\nimport library default;\n```\n\nThe `Main` package can only be imported from other parts of the `Main` package,\nnever other packages. Importing `Main//default` is invalid, regardless of which\npackage is used.\n\nAs code becomes more complex, and users pull in more code, it may also be\nhelpful to add\n_namespaces_<sup><small>[[define](/docs/guides/glossary.md#namespace)]</small></sup>\nto give related entities consistently structured names. A namespace affects the\n_name\npath_<sup><small>[[define](/docs/guides/glossary.md#name-path)]</small></sup>\nused when calling code. For example, with no namespace, if a `Geometry` package\ndefines `Circle` then the name path will be `Geometry.Circle`. However, it can\nbe named `Geometry.TwoDimensional.Circle` with a `namespace`; for example:\n\n```\npackage Geometry library \"Shapes\";\nnamespace TwoDimensional;\nstruct TwoDimensional.Circle { ... };\n```\n\nThis scaling of programs into packages, libraries, and namespaces is how Carbon\nsupports both small and large codebases.\n\n### Sizing packages and libraries\n\nA different way to think of the sizing of packages and libraries is:\n\n-   A package is a GitHub repository.\n    -   Small and medium projects that fit in a single repository will typically\n        have a single package. For example, a medium-sized project like\n        [Abseil](https://github.com/abseil/abseil-cpp/tree/master/absl) could\n        still use a single `Abseil` package.\n    -   Large projects will have multiple packages. For example, Mozilla may\n        have multiple packages for Firefox and other efforts.\n-   A library is a few files that provide an interface and implementation, and\n    should remain small.\n    -   Small projects will have a single library when it's easy to maintain all\n        code in a few files.\n    -   Medium and large projects will have multiple libraries. For example,\n        [Boost Geometry's Distance](https://github.com/boostorg/geometry/blob/develop/include/boost/geometry/algorithms/detail/distance/interface.hpp)\n        interface and implementation might be its own library within `Boost`,\n        with dependencies on other libraries in `Boost` and potentially other\n        packages from Boost.\n        -   Library names could be named after the feature, such as\n            `library \"Algorithms\"`, or include part of the path to reduce the\n            chance of name collisions, such as `library \"Geometry/Algorithms\"`.\n\nPackages may choose to expose libraries that expose unions of interfaces from\nother libraries within the package. However, doing so would also provide the\ntransitive closure of build-time dependencies, and is likely to be discouraged\nin many cases.\n\n## Details\n\n### Source file introduction\n\nEvery source file will consist of, in order:\n\n1. Either a `package` directive, a `library` directive, or no introduction.\n2. A section of zero or more `import` directives.\n3. Source file body, with other code.\n\nComments and blank lines may be intermingled with these sections.\n[Metaprogramming](/docs/design/metaprogramming.md) code may also be\nintermingled, so long as the outputted code is consistent with the enforced\nordering. Other types of code must be in the source file body.\n\n### Name paths\n\n[Name paths](#name-paths) are defined above as sequences of identifiers\nseparated by dots. This syntax may be loosely expressed as a regular expression:\n\n```regex\nIDENTIFIER(\\.IDENTIFIER)*\n```\n\nName conflicts are addressed by [name lookup](/docs/design/name_lookup.md).\n\n### Packages\n\n#### `package` directives\n\nThe `package` directive's syntax may be loosely expressed as a regular\nexpression:\n\n```regex\n(impl)? package IDENTIFIER (library STRING)?;\n```\n\nFor example:\n\n```carbon\nimpl package Geometry library \"Objects/FourSides\";\n```\n\nBreaking this apart:\n\n-   The use of the `impl` keyword indicates this is an implementation files as\n    described under [libraries](#libraries). If it were omitted, this would\n    instead be an API file.\n-   The identifier after the `package` keyword, `Geometry`, is the package name\n    and will prefix both library and namespace paths.\n    -   The `package` keyword also declares a package entity matching the\n        package name. A package entity is almost identical to a namespace\n        entity, except with some package/import-specific handling. For example,\n        if the file declares `namespace TwoDimensional;` and\n        `struct TwoDimensional.Line`, the struct may be used from files in other\n        packages that import the library as `Geometry.TwoDimensional.Line`,\n        using the `Geometry` package entity created by the `package` keyword.\n    -   `Main` is invalid for use as the package name. `Main` libraries must be\n        defined by either the [`library` directive](#library-directives) or the\n        [`Main//default`](#maindefault) rule.\n-   The string after the `library` keyword sets the name of the library within\n    the package. In this example, the `Geometry//Objects/FourSides` library will\n    be used.\n    -   If the `library` portion were omitted, the file would implicitly be part\n        of the default library, which does not have a string name.\n\n#### `library` directives\n\nThe syntax for `library` directives is the same, without the `package` portion:\n\n```regex\n(impl)? library STRING;\n```\n\nFor example:\n\n```carbon\nimpl library \"PrimeGenerator\";\n```\n\nIf the `library` directive is used, the file is implicitly part of the `Main`\npackage, whose name cannot be written explicitly.\n\n#### `Main//default`\n\nIf neither a `package` directive nor a `library` directive is provided, the file\nis an API file for `Main//default`. An `impl` cannot be provided for\n`Main//default`.\n\n#### Files and libraries\n\nEvery file is in exactly one library, which is always part of a package.\n\nBecause every file is within a package, and packages act as top-level\nnamespaces, every entity in Carbon will be in a namespace, even if its namespace\npath consists of only the package name. There is no \"global\" namespace.\n\n-   Every entity in a file will be defined within the namespace described in the\n    `package` directive.\n-   Entities within a file may be defined in [child namespaces](#namespaces).\n\nFiles contributing to the `Geometry//Objects/FourSides` library must all start\nwith [`impl`] `package` `Geometry` `library` `\"Objects/FourSides\"` `;`.\n\n#### Shorthand notation for libraries in packages\n\nLibrary names may also be referred to as `PACKAGE//LIBRARY` as shorthand in\ntext. `PACKAGE//default` will refer to the name of the library used when no\n`library` argument is specified, although `PACKAGE` may also be used in\nsituations where it is unambiguous that it still refers to the default library.\n\nThe package name `Main` is always used implicitly and cannot appear as a package\nname within source code, but still appears in shorthand notation. For example,\n`Main//default` is the library that is expected to contain a Carbon `Run`\nfunction.\n\nIt's recommended that libraries use a single `/` for separators where desired,\nin order to distinguish between the `//` of the package and `/` separating\nlibrary segments. For example, `Geometry//Objects/FourSides` uses a single `/`\nto separate the `Object/FourSides` library name.\n\n#### Package name conflicts\n\nBecause an import of a package declares a namespace entity with the same name,\nconflicts with the package name are possible.\n\nFor example, this is a conflict for `DateTime`:\n\n```carbon\nimport DateTime;\n\nstruct DateTime { ... }\n```\n\nNote that [imported name conflicts](#package-and-library-name-conflicts) are\nhandled differently.\n\n### Libraries\n\nEvery Carbon library consists of one or more files. Each Carbon library has a\nprimary file that defines its API, and may optionally contain additional files\nthat are implementation.\n\n-   An API file's `package` directive does not include the `impl` modifier. For\n    example, `package Geometry library \"Shapes\";`\n    -   API filenames must have the `.carbon` extension. They must not have a\n        `.impl.carbon` extension.\n    -   API file paths will correspond to the library name.\n        -   The precise form of this correspondence is undetermined, but should\n            be expected to be similar to a \"Math/Algebra\" library being in a\n            \"Math/Algebra.carbon\" file path.\n        -   The package will not be used when considering the file path.\n-   An implementation file's `package` directive includes an `impl` modifier.\n    For example, `impl package Geometry library \"Shapes\";`.\n    -   Implementation filenames must have the `.impl.carbon` extension.\n    -   Implementation file paths need not correspond to the library name.\n    -   Implementation files implicitly import the library's API. Implementation\n        files cannot import each other. There is no facility for file or non-API\n        imports.\n\nThe difference between API and implementation will act as a form of access\ncontrol. API files must compile independently of implementation, only importing\nfrom APIs from other libraries. API files are also visible to all files and\nlibraries for import. Implementation files only see API files for import, not\nother implementation files.\n\nWhen any file imports a library's API, it should be expected that the transitive\nclosure of imported files from the primary API file will be a compilation\ndependency. The size of that transitive closure affects compilation time, so\nlibraries with complex implementations should endeavor to minimize their API\nimports.\n\nLibraries also serve as a critical unit of compilation. Dependencies between\nlibraries must be clearly marked, and the resulting dependency graph will allow\nfor separate compilation.\n\n#### Exporting entities from an API file\n\nEntities in the API file are part of the library's public API by default. They\nmay be marked as `private` to indicate they should only be visible to other\nparts of the library.\n\n```carbon\npackage Geometry library \"Shapes\";\n\n// Circle is part of the public API of the library, and will be available to\n// other libraries as Geometry.Circle.\nstruct Circle { ... }\n\n// CircleHelper is private, and so will not be available to other libraries.\nprivate fn CircleHelper(circle: Circle) { ... }\n\nnamespace Operations;\n\n// Operations.GetCircumference is part of the public API of the library, and\n// will be available to other libraries as Geometry.Operations.GetCircumference.\nfn Operations.GetCircumference(circle: Circle) { ... }\n```\n\nThis means that an API file can contain all implementation code for a library.\nHowever, separate implementation files are still desirable for a few reasons:\n\n-   It will be easier for readers to quickly scan an API-only file for API\n    documentation.\n-   Reducing the amount of code in an API file can speed up compilation,\n    especially if fewer imports are needed. This can result in transitive\n    compilation performance improvements for files using the library.\n-   From a code maintenance perspective, having smaller files can make a library\n    more maintainable.\n\nEntities in an implementation file should never have visibility keywords. If\nthey are forward declared in the API file, they use the declaration's\nvisibility; if they are only present in an implementation file, they are\nimplicitly `private`.\n\n#### Granularity of libraries\n\nThe compilation graph of Carbon will generally consist of API files depending on\neach other, and implementation files depending only on API files. Compiling a\ngiven file requires compiling the transitive closure of API files first.\nParallelization of compilation is then limited by how large that transitive\nclosure is, in terms of total volume of code rather than quantity. This also\naffects build cache invalidation.\n\nIn order to maximize opportunities to improve compilation performance, we will\nencourage granular libraries. Conceptually, we want libraries to be very small,\npossibly containing only a single class. The choice of only allowing a single\nAPI file per library should help encourage developers to write small libraries.\n\n#### Exporting namespaces\n\nA namespace declared in an API file is only exported if it contains at least one\n`public` non-namespace name. For example, given this code:\n\n```carbon\npackage Checksums library \"Sha\";\n\nnamespace Sha256;\nnamespace ImplementationDetails;\n\nprivate fn ImplementationDetails.ShaHelper(data: Bytes) -> Bytes;\nfn Sha256.HexDigest(data: Bytes) -> String { ... }\n```\n\nCalling code may look like:\n\n```carbon\npackage Caller;\n\nimport Checksums library \"Sha\";\n\nfn Process(data: Bytes) {\n  ...\n  var digest: String = Checksums.Sha256.HexDigest(data);\n  ...\n}\n```\n\nIn this example, the `Sha256` namespace is exported as part of the API\nimplicitly, but the name `Checksums.ImplementationDetails` is not available in\nthe caller.\n\n### Imports\n\n`import` directives supports reusing code from other files and libraries. The\n`import` directive's syntax may be loosely expressed as a regular expression:\n\n```regex\nimport IDENTIFIER (library NAME_PATH)?;\nimport Core (library NAME_PATH)?;\nimport library NAME_PATH;\nimport library default;\n```\n\nAn import with a package name `IDENTIFIER` declares a package entity named after\nthe imported package, and makes API entities from the imported library available\nthrough it. `Main` cannot be imported from other packages; in other words, only\n`import library NAME_PATH` syntax can be used to import from `Main`. Imports of\n`Main//default` are invalid. The keyword `Core` can be used as a package name in\nan import in order to import portions of the standard library that are not part\nof the prelude.\n\nThe full name path is a concatenation of the names of the package entity, any\nnamespace entities applied, and the final entity addressed. Child namespaces or\nentities may be [aliased](/docs/design/aliases.md) if desired.\n\nFor example, given a library:\n\n```carbon\npackage Math;\nnamespace Trigonometry;\nfn Trigonometry.Sin(...);\n```\n\nCalling code would import it and use it like:\n\n```carbon\npackage Geometry;\n\nimport Math;\n\nfn DoSomething() {\n  ...\n  Math.Trigonometry.Sin(...);\n  ...\n}\n```\n\nRepeat imports from the same package reuse the same package entity. For example,\nthis produces only one `Math` package entity:\n\n```carbon\nimport Math;\nimport Math library \"Trigonometry\";\n```\n\nNOTE: A library must never import itself. Any implementation files in a library\nautomatically import the API, so a self-import should never be required.\n\n#### Imports from the current package\n\nAn import without a package name imports the public names from the given library\nof the same package.\n\nEntities defined in the API of the current library and in imported libraries in\nthe current package may be used without mentioning the package prefix. However,\nsymbols from other packages must be imported and accessed through the package\nnamespace.\n\nFor example:\n\n```carbon\npackage Geometry;\n\n// This is required even though it's still in the Geometry package.\nimport library \"Shapes\";\n\n// Circle is visible here. The name Geometry is not declared, so\n// Geometry.Circle is invalid.\nfn GetArea(c: Circle) { ... }\n```\n\n#### Exporting imported names\n\nThe `export` keyword supports exporting names that come from imported libraries.\nThis can be used to create an API file that provides contents from multiple\nother API files.\n\n`export` can be used either as a modifier to the `import` keyword to export the\nentire imported library, or in an `export <name>` declaration to export a\nspecific entity.\n\nFor example:\n\n```\n// Exports every name from the \"Foo\" library.\nexport import library \"Foo\";\n\n// Exports just the \"Bar\" entity, which must come from an import.\nexport Bar;\n\n// Exports the \"Wiz\" entity in the \"NS\" namespace.\nexport NS.Wiz;\n```\n\nWhen `export` is used as a modifier to `import`, it is still considered to be an\n`import` directive for the\n[source file introduction](#source-file-introduction).\n\nNamespaces cannot be exported using a `export <name>` declaration. It is\npossible a form of support will be added as\n[future work](/proposals/p3938.md#namespaces).\n\nNames in other packages also cannot be exported. This covers both possible\nsyntaxes: `export import <package>` and `export <package>.<name>`. However, a\nname in another package can be aliased inside the current package, and that\nalias can be re-exported.\n\n### Namespaces\n\nNamespaces offer named paths for entities. Namespaces must be declared at file\nscope, and may be nested. Multiple libraries may contribute to the same\nnamespace. In practice, packages may have namespaces such as `Testing`\ncontaining entities that benefit from an isolated space but are present in many\nlibraries.\n\nThe `namespace` keyword's syntax may loosely be expressed as a regular\nexpression:\n\n```regex\nnamespace NAME_PATH;\n```\n\nThe `namespace` keyword declares a namespace entity. The namespace is applied to\nother entities by including it as a prefix when declaring a name. For example:\n\n```carbon\npackage Time;\n\nnamespace Timezones.Internal;\nstruct Timezones.Internal.RawData { ... }\n\nfn ParseData(data: Timezones.Internal.RawData);\n```\n\nA namespace declaration adds the first identifier in the name path as a name in\nthe file's namespace. In the above example, after declaring\n`namespace Timezones.Internal;`, `Timezones` is available as an identifier and\n`Internal` is reached through `Timezones`.\n\n#### Redeclaring imported namespaces\n\nNamespaces may exist in imported package entities, in addition to being declared\nin the current file. However, even if the namespace already exists in an\nimported library from the current package, the namespace must still be declared\nlocally in order to add symbols to it.\n\nFor example, if the `Geometry//Shapes/ThreeSides` library provides the\n`Geometry.Shapes` namespace, this code is still valid:\n\n```carbon\npackage Geometry library \"Shapes/FourSides\";\n\nimport library \"Shapes/ThreeSides\";\n\n// This does not conflict with the existence of `Geometry.Shapes` from\n// `Geometry//Shapes/ThreeSides`, even though the name path is identical.\nnamespace Shapes;\n\n// This requires the above 'namespace Shapes' declaration. It cannot use\n// `Geometry.Shapes` from `Geometry//Shapes/ThreeSides`.\nstruct Shapes.Square { ... };\n```\n\n#### Declaring namespace members\n\nNamespace members may only be declared in the same name scope which was used to\ndeclare the namespace. For example:\n\n```carbon\nnamespace NS;\n\n// ✅ Allowed: declaration is in file scope, which also declared `NS`.\nclass NS.ClassT {\n  // ❌ Error: A class body has its own name scope.\n  var NS.a: i32 = 0;\n}\n\nfn Function() {\n  // ❌ Error: A function body has its own name scope.\n  var NS.b: i32 = 1;\n}\n\n// ✅ Allowed: declaration is in file scope, which also declared `NS`.\nnamespace NS.MemberNS;\n\n// ✅ Allowed: declaration is in file scope, which also declared `NS.MemberNS`.\nclass NS.MemberNS.MemberClassT {}\n```\n\nWhen multiple names are declared by binding patterns in the same pattern, all\nnames must be in the same namespace. Because namespace members can only be\ndeclared in the same scope as the namespace, a namespace-qualified pattern\nbinding can only be used in the pattern of a `var` or `let` declaration. For\nexample:\n\n```carbon\nnamespace NS;\n\n// ✅ Allowed: `a` and `b` use the default namespace.\nvar (a: i32, b: i32) = (1, 2);\n\n// ✅ Allowed: `c` and `d` are in the same namespace.\nvar (NS.c: i32, NS.d: i32) = (3, 4);\n\n// ❌ Error: `e` and `f` are not in the same namespace.\nvar (e: i32, NS.f: i32) = (5, 6);\n```\n\nThis restriction only applies when declaring names in binding patterns, not\nother name uses in patterns.\n\n#### Aliasing\n\nCarbon's [alias keyword](/docs/design/aliases.md) will support aliasing\nnamespaces. For example, this would be valid code:\n\n```carbon\nnamespace Timezones.Internal;\nalias TI = Timezones.internal;\n\nstruct TI.RawData { ... }\nfn ParseData(data: TI.RawData);\n```\n\n## Caveats\n\n### Package and library name conflicts\n\nLibrary name conflicts should be avoidable, because it's expected that a given\npackage is maintained by a single organization. It's the responsibility of that\norganization to maintain unique library names within their package.\n\nA package name conflict occurs when two different packages use the same name,\nsuch as two packages named `Stats`. Versus libraries, package name conflicts are\nmore likely because two organizations may independently choose identical names.\nWe will encourage a unique package naming scheme, such as maintaining a name\nserver for open source packages. Conflicts can also be addressed by renaming one\nof the packages, either at the source, or as a local modification.\n\nWe do need to address the case of package names conflicting with other entity\nnames. It's possible that a preexisting entity will conflict with a new import,\nand that renaming the entity is infeasible to rename due to existing callers.\nAlternately, the entity may be using an idiomatic name that it would contradict\nnaming conventions to rename. In either case, this conflict may exist in a\nsingle file without otherwise affecting users of the API. This will be addressed\nby [name lookup](/docs/design/name_lookup.md).\n\n### Potential refactorings\n\nThese are potential refactorings that we consider important to make it easy to\nautomate.\n\n#### Update imports\n\nImports will frequently need to be updated as part of refactorings.\n\nWhen code is deleted, it should be possible to parse the remaining code, parse\nthe imports, and determine which entities in imports are referred to. Unused\nimports can then be removed.\n\nWhen code is moved, it's similar to deletion in the originating file. For the\ndestination file, the moved code should be parsed to determine which entities it\nreferred to from the originating file's imports, and these will need to be\nincluded in the destination file: either reused if already present, or added.\n\nWhen new code is added, existing imports can be checked to see if they provide\nthe symbol in question. There may also be heuristics which can be implemented to\ncheck build dependencies for where imports should be added from, such as a\ndatabase of possible entities and their libraries. However, adding references\nmay require manually adding imports.\n\n#### Between API and implementation files\n\n-   Move the definition of an entity from an API file to an implementation file,\n    while leaving a declaration behind.\n\n    -   This should be a local change that will not affect any calling code.\n    -   Inlining will be affected because the implementation won't be visible to\n        callers.\n    -   [Update imports](#update-imports).\n\n-   Split an API and implementation file.\n\n    -   This is a repeated operation of individual API moves, as noted above.\n\n-   Move the definition of an entity from an implementation file to the API\n    file.\n\n    -   This should be a local change that will not affect any calling code.\n    -   Inlining will be affected because the implementation becomes visible to\n        callers.\n    -   [Update imports](#update-imports).\n\n-   Combine an API and implementation file.\n\n    -   This is a repeated operation of individual API moves, as noted above.\n\n-   Add the `private` modifier to a declaration.\n\n    -   Search for library-external callers, and fix them first.\n\n-   Remove the `private` modifier from a declaration.\n\n    -   This should be a local change that will not affect any calling code.\n\n-   Move a `private` declaration from the API file to an implementation file.\n\n    -   The declaration must be moved to the same file as the definition of the\n        entity.\n    -   The declaration can only be used by the implementation file that now\n        contains it. Search for other callers within the library, and fix them\n        first.\n    -   [Update imports](#update-imports).\n\n-   Move a `private` declaration from an implementation file to the API file.\n\n    -   This should be a local change that will not affect any calling code.\n    -   [Update imports](#update-imports).\n\n-   Move a declaration and definition from one implementation file to another.\n\n    -   Search for any callers within the source implementation file, and either\n        move them too, or fix them first.\n    -   [Update imports](#update-imports).\n\n#### Other refactorings\n\n-   Rename a package.\n\n    -   The imports of all calling files must be updated accordingly.\n    -   All call sites must be changed, as the package name changes.\n    -   [Update imports](#update-imports).\n\n-   Move a public declaration and definition between different packages.\n\n    -   The imports of all calling files must be updated accordingly.\n    -   All call sites must be changed, as the package name changes.\n    -   [Update imports](#update-imports).\n\n-   Move a public declaration and definition between libraries in the same\n    package.\n\n    -   The imports of all calling files must be updated accordingly.\n    -   As long as the namespaces remain the same, no call sites will need to be\n        changed.\n    -   [Update imports](#update-imports).\n\n-   Rename a library.\n\n    -   This is equivalent to a repeated operation of moving a public\n        declaration and definition between libraries in the same package.\n\n-   Move a declaration and definition from one namespace to another.\n\n    -   Ensure the new namespace is declared for the declaration and definition.\n    -   Update the namespace used by call sites.\n    -   The imports of all calling files may remain the same.\n\n-   Rename a namespace.\n\n    -   This is equivalent to a repeated operation of moving a declaration and\n        definition from one namespace to another.\n\n-   Rename a file, or move a file between directories.\n\n    -   Build configuration will need to be updated.\n    -   This additionally requires the steps to rename a library, because\n        library names must correspond to the renamed paths.\n\n### Preference for few child namespaces\n\nWe expect that most code should use a package and library, but avoid specifying\nnamespaces beneath the package. The package name itself should typically be\nsufficient distinction for names.\n\nChild namespaces create longer names, which engineers will dislike typing. Based\non experience, we expect to start seeing aliasing even at name lengths around\nsix characters long. With longer names, we should expect more aliasing, which in\nturn will reduce code readability because more types will have local names.\n\nWe believe it's feasible for even large projects to collapse namespaces down to\na top level, avoiding internal tiers of namespaces.\n\nWe understand that child namespaces are sometimes helpful, and will robustly\nsupport them for that. However, we will model code organization to encourage\nfewer namespaces.\n\n### Redundant markers\n\nWe use a few possibly redundant markers for packages and libraries:\n\n-   The filename and the presence or absence of the `impl` keyword duplicate the\n    API versus implementation choice.\n-   The filename and the library name portion of the package declaration\n    duplicate the name of the library.\n-   The `import` keyword requires the full library.\n\nThese choices are made to assist human readability and tooling:\n\n-   Being explicit about imports creates the opportunity to generate build\n    dependencies from files, rather than having them maintained separately.\n-   Being explicit about API versus implementation in the filename makes it\n    easier for both humans and tooling to determine what to expect, and makes it\n    possible to check the type without reading file content.\n-   Repeating the type and library name in the file content makes\n    non-file-system-based builds possible.\n\n## Open questions\n\nThese open questions are expected to be revisited by future proposals.\n\n### Different file extensions\n\nCurrently, we're using `.carbon` and `.impl.carbon`. In the future, we may want\nto change the extension, particularly because Carbon may be renamed.\n\nThere are several other possible extensions / commands that we've considered in\ncoming to the current extension:\n\n-   `.carbon`: This is an obvious and unsurprising choice, but also quite long\n    for a file extension.\n-   `.6c`: This sounds a little like 'sexy' when read aloud.\n-   `.c6`: This seems a weird incorrect ordering of the atomic number and has a\n    bad, if obscure, Internet slang association.\n-   `.cb` or `.cbn`: These collide with several acronyms and may not be\n    especially memorable as referring to Carbon.\n-   `.crb`: This has a bad Internet slang association.\n\n### Imports from other languages\n\nCurrently, we do not support cross-language imports. In the future, we will\nlikely want to support imports from other languages, particularly for C++\ninteroperability.\n\nTo fit into the proposed `import` syntax, we are provisionally using a special\n`Cpp` package to import headers from C++ code, as in:\n\n```carbon\nimport Cpp library \"<map>\";\nimport Cpp library \"myproject/myclass.h\";\n\nfn MyCarbonCall(x: Cpp.std.map(Cpp.MyProject.MyClass));\n```\n\n### Imports from URLs\n\nCurrently, we don't support any kind of package management with imports. In the\nfuture, we may want to support tagging imports with a URL that identifies the\nrepository where that package can be found. This can be used to help drive\npackage management tooling and to support providing a non-name identity for a\npackage that is used to enable handling conflicted package names.\n\nAlthough we're not designing this right now, it could fit into the proposed\nsyntax. For example:\n\n```carbon\nimport Carbon library \"Utilities\"\n    url(\"https://github.com/carbon-language/carbon-libraries\");\n```\n\n### Test file type\n\nSimilar to API and implementation files, we may eventually want test-specific\nfiles. This should be part of a larger testing plan.\n\n## Alternatives considered\n\n-   Packages\n    -   [Name paths for package names](/proposals/p0107.md#name-paths-for-package-names)\n    -   [Referring to the package as `package`](/proposals/p0107.md#referring-to-the-package-as-package)\n    -   [Remove the `library` keyword from `package` and `import`](/proposals/p0107.md#remove-the-library-keyword-from-package-and-import)\n    -   [Rename package concept](/proposals/p0107.md#rename-package-concept)\n    -   [No association between the file system path and library/namespace](/proposals/p0107.md#no-association-between-the-file-system-path-and-librarynamespace)\n    -   [Require the use of the identifier `Main` in package declarations](/proposals/p2550.md#require-the-use-of-the-identifier-main-in-package-declarations)\n    -   [Permit the use of the identifier `Main` in package declarations](/proposals/p2550.md#permit-the-use-of-the-identifier-main-in-package-declarations)\n    -   [Make the main package be unnamed](/proposals/p2550.md#make-the-main-package-be-unnamed)\n    -   [Use a different name for the main package](/proposals/p2550.md#use-a-different-name-for-the-main-package)\n    -   [Use a different name for the entry point](/proposals/p2550.md#use-a-different-name-for-the-entry-point)\n    -   [Distinguish file scope from package scope](/proposals/p2550.md#distinguish-file-scope-from-package-scope)\n    -   [Default to an implementation file for `Main//default` instead of an API file](/proposals/p3403.md#default-to-maindefault-impl-instead-of-maindefault-api)\n-   Libraries\n    -   [Allow exporting namespaces](/proposals/p0107.md#allow-exporting-namespaces)\n    -   [Allow importing implementation files from within the same library](/proposals/p0107.md#allow-importing-implementation-files-from-within-the-same-library)\n    -   [Alternative library separators and shorthand](/proposals/p0107.md#alternative-library-separators-and-shorthand)\n        -   [Single-word libraries](/proposals/p0107.md#single-word-libraries)\n    -   [Collapse API and implementation file concepts](/proposals/p0107.md#collapse-api-and-implementation-file-concepts)\n        -   [Automatically generating the API separation](/proposals/p0107.md#automatically-generating-the-api-separation)\n    -   [Collapse file and library concepts](/proposals/p0107.md#collapse-file-and-library-concepts)\n    -   [Collapse the library concept into packages](/proposals/p0107.md#collapse-the-library-concept-into-packages)\n    -   [Collapse the package concept into libraries](/proposals/p0107.md#collapse-the-package-concept-into-libraries)\n    -   [Default API to private](/proposals/p0752.md#default-api-to-private)\n    -   [Default `impl` to public](/proposals/p0752.md#default-impl-to-public)\n    -   [Different file type labels](/proposals/p0107.md#different-file-type-labels)\n    -   [Don't default to introducing an API file](/proposals/p3927.md#mandatory-api-or-impl-as-suffix)\n    -   [Function-like syntax](/proposals/p0107.md#function-like-syntax)\n    -   [Inlining from implementation files](/proposals/p0107.md#inlining-from-implementation-files)\n    -   [Library-private access controls](/proposals/p0107.md#library-private-access-controls)\n    -   [Make keywords either optional or required in separate definitions](/proposals/p0752.md#make-keywords-either-optional-or-required-in-separate-definitions)\n    -   [Managing API versus implementation in libraries](/proposals/p0107.md#managing-api-versus-implementation-in-libraries)\n    -   [Multiple API files](/proposals/p0107.md#multiple-api-files)\n    -   [Name paths as library names](/proposals/p0107.md#name-paths-as-library-names)\n    -   [Put the `impl` modifier at the end](/proposals/p3927.md#mandatory-api-or-impl-as-suffix)\n    -   [Put the `impl` modifier before `library`](/proposals/p3927.md#put-the-impl-modifier-before-library)\n-   Imports\n    -   [Block imports](/proposals/p0107.md#block-imports)\n    -   [Block imports of libraries of a single package](/proposals/p0107.md#block-imports-of-libraries-of-a-single-package)\n    -   [Broader imports, either all names or arbitrary code](/proposals/p0107.md#broader-imports-either-all-names-or-arbitrary-code)\n    -   [Direct name imports](/proposals/p0107.md#direct-name-imports)\n    -   [Always include the package name in imports](/proposals/p2550.md#keep-the-package-name-in-imports)\n    -   Exports\n        -   [Other `export` syntax structures](/proposals/p3938.md#other-export-syntax-structures)\n        -   [Other `export name` placements](/proposals/p3938.md#other-export-name-placements)\n        -   [Re-exporting cross-package](/proposals/p3938.md#re-exporting-cross-package)\n-   Namespaces\n    -   [File-level namespaces](/proposals/p0107.md#file-level-namespaces)\n    -   [Scoped namespaces](/proposals/p0107.md#scoped-namespaces)\n    -   [Allow prefixing a tuple binding pattern with a namespace](/proposals/p3407.md#allow-prefixing-a-tuple-binding-pattern-with-a-namespace)\n    -   [Allow binding patterns to declare names in multiple namespaces](/proposals/p3407.md#allow-binding-patterns-to-declare-names-in-multiple-namespaces)\n    -   [Allow declaring names in namespaces not owned by the current scope](/proposals/p3407.md#allow-declaring-names-in-namespaces-not-owned-by-the-current-scope)\n    -   [Allow declaring namespaces in scopes other than the file scope](/proposals/p3407.md#allow-declaring-namespaces-in-scopes-other-than-the-file-scope)\n\n## References\n\n-   Proposal\n    [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)\n-   Proposal\n    [#2550: Simplified package declaration for the main package](https://github.com/carbon-language/carbon-lang/pull/2550)\n-   Proposal\n    [#3403: Change Main//default to an api file](https://github.com/carbon-language/carbon-lang/pull/3403)\n-   Proposal\n    [#3453: Clarify name bindings in namespaces.](https://github.com/carbon-language/carbon-lang/pull/3407)\n-   Proposal\n    [#3927: More consistent package syntax](https://github.com/carbon-language/carbon-lang/pull/3927)\n-   Proposal\n    [#3938: Exporting imported names](https://github.com/carbon-language/carbon-lang/pull/3938)\n"
  },
  {
    "path": "docs/design/code_and_name_organization/source_files.md",
    "content": "# Source files\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Encoding](#encoding)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nA Carbon _source file_ is a sequence of Unicode code points in Unicode\nNormalization Form C (\"NFC\"), and represents a portion of the complete text of a\nprogram.\n\nProgram text can come from a variety of sources, such as an interactive\nprogramming environment (a so-called \"Read-Evaluate-Print-Loop\" or REPL), a\ndatabase, a memory buffer of an IDE, or a command-line argument.\n\nThe canonical representation for Carbon programs is in files stored as a\nsequence of bytes in a file system on disk. Such files have a `.carbon`\nextension.\n\n## Encoding\n\nThe on-disk representation of a Carbon source file is encoded in UTF-8. Such\nfiles may begin with an optional UTF-8 BOM, that is, the byte sequence\nEF<sub>16</sub>,BB<sub>16</sub>,BF<sub>16</sub>. This prefix, if present, is\nignored.\n\nNo Unicode normalization is performed when reading an on-disk representation of\na Carbon source file, so the byte representation is required to be normalized in\nNormalization Form C. The Carbon source formatting tool will convert source\nfiles to NFC as necessary.\n\n## Alternatives considered\n\n-   [Character encoding](/proposals/p0142.md#character-encoding-1)\n-   [Byte order marks](/proposals/p0142.md#byte-order-marks)\n-   [Normalization forms](/proposals/p0142.md#normalization-forms)\n\n## References\n\n-   Proposal\n    [#142: Unicode source files](https://github.com/carbon-language/carbon-lang/pull/142)\n\n-   [Unicode](https://www.unicode.org/versions/latest/) is a universal character\n    encoding, maintained by the\n    [Unicode Consortium](https://home.unicode.org/basic-info/overview/). It is\n    the canonical encoding used for textual information interchange across all\n    modern technology.\n\n    Carbon is based on Unicode 13.0, which is currently the latest version of\n    the Unicode standard. Newer versions will be considered for adoption as they\n    are released.\n\n-   [Unicode Standard Annex #15: Unicode Normalization Forms](https://www.unicode.org/reports/tr15/tr15-50.html)\n\n-   [Wikipedia Unicode equivalence page: Normal forms](https://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms)\n"
  },
  {
    "path": "docs/design/control_flow/README.md",
    "content": "# Control flow\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Overview\n\nBlocks of statements are generally executed linearly. However, statements are\nthe primary place where this flow of execution can be controlled.\n\nCarbon's flow control statements are:\n\n-   [`if` and `else`](conditionals.md) provides conditional execution of\n    statements.\n-   Loops:\n    -   [`while`](loops.md#while) executes the loop body for as long as the loop\n        expression returns `True`.\n    -   [`for`](loops.md#for) iterates over an object, such as elements in an\n        array.\n    -   [`break`](loops.md#break) exits loops.\n    -   [`continue`](loops.md#continue) goes to the next iteration of a loop.\n-   [`return`](return.md) ends the flow of execution within a function,\n    returning it to the caller.\n"
  },
  {
    "path": "docs/design/control_flow/conditionals.md",
    "content": "# Conditionals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\n`if` and `else` provide conditional execution of statements. Syntax is:\n\n> `if (`_boolean expression_ `) {` _statements_ `}`\n>\n> [ `else if (` _boolean expression_ `) {` _statements_ `}` ] ...\n>\n> [ `else {` _statements_ `}` ]\n\nOnly one group of statements will execute:\n\n-   When the first `if`'s boolean expression evaluates to true, its associated\n    statements will execute.\n-   When earlier boolean expressions evaluate to false and an `else if`'s\n    boolean expression evaluates to true, its associated statements will\n    execute.\n    -   `... else if ...` is equivalent to `... else { if ... }`, but without\n        visible nesting of braces.\n-   When all boolean expressions evaluate to false, the `else`'s associated\n    statements will execute.\n\nWhen a boolean expression evaluates to true, no later boolean expressions will\nevaluate.\n\nNote that `else if` may be repeated.\n\nFor example:\n\n```carbon\nif (fruit.IsYellow()) {\n  Print(\"Banana!\");\n} else if (fruit.IsOrange()) {\n  Print(\"Orange!\");\n} else if (fruit.IsGreen()) {\n  Print(\"Apple!\");\n} else {\n  Print(\"Vegetable!\");\n}\nfruit.Eat();\n```\n\nThis code will:\n\n-   Evaluate `fruit.IsYellow()`:\n    -   When `True`, print `Banana!` and resume execution at `fruit.Eat()`.\n    -   When `False`, evaluate `fruit.IsOrange()`:\n        -   When `True`, print `Orange!` and resume execution at `fruit.Eat()`.\n        -   When `False`, evaluate `fruit.IsGreen()`:\n            -   When `True`, print `Apple!` and resume execution at\n                `fruit.Eat()`.\n            -   When `False`, print `Vegetable!` and resume execution at\n                `fruit.Eat()`.\n\n## Alternatives considered\n\n-   [Optional braces](/proposals/p0623.md#optional-braces)\n-   [Optional parentheses](/proposals/p0623.md#optional-parentheses)\n-   [`elif`](/proposals/p0623.md#elif)\n\n## References\n\n-   Proposal\n    [#285: `if` and `else`](https://github.com/carbon-language/carbon-lang/pull/285)\n-   Proposal\n    [#623: Require braces](https://github.com/carbon-language/carbon-lang/pull/623)\n"
  },
  {
    "path": "docs/design/control_flow/loops.md",
    "content": "# Loops\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [`while`](#while)\n    -   [`for`](#for)\n    -   [`break`](#break)\n    -   [`continue`](#continue)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon provides loops using the `while` and `for` statements. Within a loop, the\n`break` and `continue` statements can be used for flow control.\n\n## Details\n\n### `while`\n\n`while` statements loop for as long as the passed expression returns `True`.\nSyntax is:\n\n> `while (` _boolean expression_ `) {` _statements_ `}`\n\nFor example, this prints `0`, `1`, `2`, then `Done!`:\n\n```carbon\nvar x: Int = 0;\nwhile (x < 3) {\n  Print(x);\n  ++x;\n}\nPrint(\"Done!\");\n```\n\n### `for`\n\n`for` statements support range-based looping, typically over containers. Syntax\nis:\n\n> `for (` _var declaration_ `in` _expression_ `) {` _statements_ `}`\n\nFor example, this prints all names in `names`:\n\n```carbon\nfor (var name: String in names) {\n  Print(name);\n}\n```\n\n`PrintNames()` prints each `String` in the `names` `List` in iteration order.\n\nTODO: Add semantics discussion from\n[#1885: ranged-based `for` for user-defined types](https://github.com/carbon-language/carbon-lang/pull/1885).\n\n### `break`\n\nThe `break` statement immediately ends a `while` or `for` loop. Execution will\nresume at the end of the loop's scope. Syntax is:\n\n> `break;`\n\nFor example, this processes steps until a manual step is hit (if no manual step\nis hit, all steps are processed):\n\n```carbon\nfor (var step: Step in steps) {\n  if (step.IsManual()) {\n    Print(\"Reached manual step!\");\n    break;\n  }\n  step.Process();\n}\n```\n\n### `continue`\n\nThe `continue` statement immediately goes to the next loop of a `while` or\n`for`. In a `while`, execution continues with the `while` expression. Syntax is:\n\n> `continue;`\n\nFor example, this prints all non-empty lines of a file, using `continue` to skip\nempty lines:\n\n```carbon\nvar f: File = OpenFile(path);\nwhile (!f.EOF()) {\n  var line: String = f.ReadLine();\n  if (line.IsEmpty()) {\n    continue;\n  }\n  Print(line);\n}\n```\n\n## Alternatives considered\n\n-   [Non-C++ syntax](/proposals/p0340.md#non-c-syntax)\n-   [Initializing variables in the `while`](/proposals/p0340.md#initializing-variables-in-the-while)\n-   `for`:\n    -   [Include semisemi `for` loops](/proposals/p0353.md#include-semisemi-for-loops)\n    -   [Multi-variable bindings](/proposals/p0353.md#multi-variable-bindings)\n    -   [`:` versus `in`](/proposals/p0618.md#-versus-in)\n-   [Optional braces](/proposals/p0623.md#optional-braces)\n-   [Optional parentheses](/proposals/p0623.md#optional-parentheses)\n\n## References\n\n-   Proposal\n    [#340: `while`](https://github.com/carbon-language/carbon-lang/pull/340)\n-   Proposal\n    [#353: `for`](https://github.com/carbon-language/carbon-lang/pull/353)\n-   Proposal\n    [#618: `var` ordering](https://github.com/carbon-language/carbon-lang/pull/618)\n-   Proposal\n    [#623: Require braces](https://github.com/carbon-language/carbon-lang/pull/623)\n"
  },
  {
    "path": "docs/design/control_flow/return.md",
    "content": "# `return`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n    -   [Returning empty tuples](#returning-empty-tuples)\n    -   [`returned var`](#returned-var)\n    -   [`return` and initialization](#return-and-initialization)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nThe `return` statement ends the flow of execution within a\n[function](../functions.md), returning execution to the caller. Its syntax is:\n\n> `return` _[ expression ]_ `;`\n\nIf the function returns a value to the caller, that value is provided by an\nexpression in the return statement. For example:\n\n```carbon\nfn Sum(a: i32, b: i32) -> i32 {\n  return a + b;\n}\n```\n\nWhen a return type is specified, a function must _always_ `return` before\ncontrol flow can reach the end of the function body. In other words,\n`fn DoNothing() -> i32 {}` would be invalid because execution will reach the end\nof the function body without returning a value.\n\n### Returning empty tuples\n\nReturning an empty tuple `()` is special, and similar to C++'s `void` returns.\nWhen a function has no specified return type, its return type is implicitly\n`()`. `return` must not have an expression argument in this case. It also has an\nimplicit `return;` at the end of the function body. For example:\n\n```carbon\n// No return type is specified, so this returns `()` implicitly.\nfn MaybeDraw(should_draw: bool) {\n  if (!should_draw) {\n    // No expression is passed to `return`.\n    return;\n  }\n  ActuallyDraw();\n  // There is an implicit `return;` here.\n}\n```\n\nWhen `-> ()` is specified in the function signature, the return expression is\nrequired. Omitting `-> ()` is encouraged, but specifying it is supported for\ngeneralized code structures, including [templates](../templates.md). In order to\nbe consistent with other explicitly specified return types, `return;` is invalid\nin this case. For example:\n\n```carbon\n// `-> ()` defines an explicit return value.\nfn MaybeDraw(should_draw: bool) -> () {\n  if (!should_draw) {\n    // As a consequence, a return value must be passed.\n    return ();\n  }\n  ActuallyDraw();\n  // The return value must again be explicit.\n  return ();\n}\n```\n\n### `returned var`\n\n[Local variables](../values.md#binding-patterns-and-local-variables-with-let-and-var)\nmay be declared with a `returned` statement. Its syntax is:\n\n> `returned` _var statement_\n\nWhen a variable is marked as `returned`, it must be the only `returned` value\nin-scope.\n\nIf a `returned var` is returned, the specific syntax `return var;` must be used.\nReturning expressions is not allowed while a `returned var` is in scope. For\nexample:\n\n```carbon\nfn MakeCircle(radius: i32) -> Circle {\n  returned var c: Circle;\n  c.radius = radius;\n  // `return c` would be invalid because `returned` is in use.\n  return var;\n}\n```\n\nIf control flow exits the scope of a `returned` variable in any way other than\n`return var;`, the `returned var`'s lifetime ends as normal. When this occurs,\n`return` may again be used with expressions. For example:\n\n```carbon\nfn MakePointInArea(area: Area, preferred_x: i32, preferred_y: i32) -> Point {\n  if (preferred_x >= 0 && preferred_y >= 0) {\n    returned var p: Point = { .x = preferred_x, .y = preferred_y };\n    if (area.Contains(p)) {\n      return var;\n    }\n    // p's lifetime ends here when `return var;` is not reached.\n  }\n\n  return area.RandomPoint();\n}\n```\n\n### `return` and initialization\n\nConsider the following common initialization code:\n\n```carbon\nfn CreateMyObject() -> MyType {\n  return <expression>;\n}\n\nvar x: MyType = CreateMyObject();\n```\n\nThe `<expression>` in the return statement of `CreateMyObject` initializes the\nvariable `x` here. There is no copy or similar. It is equivalent to:\n\n```carbon\nvar x: MyType = <expression>;\n```\n\nThis applies recursively, similar to C++'s guaranteed copy elision.\n\nIn the case where additional statements should be run between constructing the\nreturn value and returning, the use of `returned var` allows for improved\nefficiency because the `returned var` can directly use the address of `var`\ndeclared by the caller. For example, here the `returned var vector` in\n`CreateVector` uses the storage of `my_vector` for initialization, avoiding a\ncopy:\n\n```carbon\nfn CreateVector(x: i32, y: i32) -> Vector {\n  returned var vector: Vector;\n  vector.x = x;\n  vector.y = y;\n  return var;\n}\n\nvar my_vector: Vector = CreateVector(1, 2);\n```\n\nAs a consequence, `returned var` is encouraged because it makes it easier to\navoid copies.\n\n> **TODO:** Have some discussion of RVO and NRVO as they are found in C++ here,\n> and the fact that Carbon provides the essential part of these as first-class\n> features and therefore they are never \"optimizations\" or done implicitly or\n> optionally.\n\n## Alternatives considered\n\n-   [Implicit or expression returns](/proposals/p0415.md#implicit-or-expression-returns)\n-   [Named return variable in place of a return type](/proposals/p0257.md#named-return-variable-in-place-of-a-return-type)\n-   [Retain the C++ rule](/proposals/p0538.md#retain-the-c-rule)\n-   [Fully divorce functions and procedures](/proposals/p0538.md#fully-divorce-functions-and-procedures)\n\n## References\n\n-   Proposal\n    [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257)\n-   Proposal\n    [#415: Syntax: `return`](https://github.com/carbon-language/carbon-lang/pull/415)\n-   Proposal\n    [#538: `return` with no argument](https://github.com/carbon-language/carbon-lang/pull/538)\n"
  },
  {
    "path": "docs/design/declaring_entities.md",
    "content": "# Declaring entities\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Matching redeclarations of an entity](#matching-redeclarations-of-an-entity)\n    -   [Details](#details)\n-   [`extern` and `extern library`](#extern-and-extern-library)\n    -   [Valid scopes for `extern`](#valid-scopes-for-extern)\n    -   [Effect on indirect imports](#effect-on-indirect-imports)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nEntities may have up to three declarations:\n\n-   An optional, owning forward declaration.\n    -   For example, `class MyClass;`.\n    -   This must come before the definition. The API file is considered to be\n        before the implementation file.\n-   A required, owning definition.\n    -   For example, `class MyClass { ... }`.\n    -   The definition might be the _only_ declaration.\n-   An optional, non-owning `extern library \"<owning_library>\"` declaration.\n    -   For example, `extern library \"OtherLibrary\" class MyClass;`.\n    -   It must be in a separate library from the definition.\n    -   The owning library's API file must import the `extern` declaration, and\n        must also contain a declaration.\n    -   The owning library's declarations must have the `extern` modifier\n        (without `library`).\n        -   For example, `extern class MyClass;`.\n\nFor example, a library can have a forward declaration of an entity in the API\nfile, and use the implementation file for the entity's definition. Putting the\ndefinition in an implementation file this way can reduce the dependencies for\nAPI file evaluation, improving compile time. This is commonly done with\nfunctions. For example:\n\n```\nlibrary \"MyLibrary\";\n\nfn DoSomething();\n```\n\n```\nimpl library \"MyLibrary\";\n\nfn DoSomething() {\n  ...\n}\n```\n\n## Matching redeclarations of an entity\n\nIn order to determine whether two redeclarations refer to the same entity, we\napply the rules:\n\n-   Two named declarations _declare the same entity_ if they have the same scope\n    and the same name. This includes imported declarations.\n-   When two named declarations declare the same entity, the second is said to\n    be a _redeclaration_.\n-   Two owned declarations _differ_ if they don't syntactically match.\n    -   Otherwise, if one is a non-owned `extern library` declaration,\n        declarations differ if they don't match semantically.\n-   The program is invalid if it contains two declarations of the same entity\n    that differ.\n\n```carbon\nclass A {\n  // This function will be redeclared in order to provide a definition.\n  fn F(n: i32);\n}\n\n// ✅ Valid: The declaration matches syntactically.\nfn A.F(n: i32) {}\n\n// ❌ Invalid: The parameter name differs.\nfn A.F(m: i32) {}\n\n// ❌ Invalid: The parameter type differs syntactically.\nfn A.F(n: (i32)) {}\n```\n\n### Details\n\nTODO: Figure out what details to pull from\n[#3762](https://github.com/carbon-language/carbon-lang/pull/3762) and\n[#3763](https://github.com/carbon-language/carbon-lang/pull/3763).\n\n## `extern` and `extern library`\n\nThere are two forms of the `extern` modifier:\n\n-   On an owning declaration, `extern` limits access to the definition.\n    -   The entity must be directly imported in order to use of the definition.\n    -   An `extern library` declaration is optional.\n-   On a non-owning declaration, `extern library` allows references to an entity\n    without depending on the owning library.\n    -   The library name indicates where the entity is defined.\n    -   This can be used to improve build performance, such as by splitting out\n        a declaration in order to reduce a library's dependencies.\n\nFor example, a use of both might look like:\n\n```\nlibrary \"owner\";\n\n// This `import` is required due to the `extern library`, but we also make use\n// of `MyClassFactory` below. This is a circular use of `MyClass` that we\n// couldn't split between libraries without `extern`.\nimport library \"factory\";\n\nextern class MyClass {\n  fn Make() -> MyClass* {\n    return MyClassFactory();\n  }\n\n  var val: i32 = 0;\n}\n```\n\n```\nlibrary \"factory\";\n\n// Declares `MyClass` so that `MyClassFactory` can return it.\nextern library \"owner\" class MyClass;\n\nfn MyClassFactory(val: i32) -> MyClass*;\n```\n\n```\nimpl library \"factory\";\n\n// Imports the definition of `MyClass`.\nimport library \"owner\";\n\nextern fn MyClassFactory(val: i32) -> MyClass* {\n  var c: MyClass* = new MyClass();\n  c->val = val;\n  return c;\n}\n```\n\n### Valid scopes for `extern`\n\nThe `extern` modifier is only valid on namespace-scoped entities, including in\nthe file scope. In other words, `class C { extern fn F(); }` is invalid.\n\n### Effect on indirect imports\n\nIndirect imports won't see the definition of an `extern` entity. We expect this\nto primarily affect return types of functions. If an incomplete type is\nencountered this way, it can be resolved by directly importing the definition.\nFor example:\n\n```\nlibrary \"type\";\n\n// Because this is `extern`, the definition must be directly imported.\nextern class MyType { var x: i32 }\n```\n\n```\nlibrary \"make_type\";\n\nimport library \"type\";\n\n// Here we have a function which returns the type.\nfn MakeMyType() -> MyType*;\n```\n\n```\nlibrary \"invalid_use\";\n\nimport library \"make_type\";\n\nfn InvalidUse() -> i32 {\n  // ❌ Invalid: `MyType` is incomplete because it's `extern` and not directly\n  // imported. `x` cannot be accessed.\n  return MakeMyType()->x;\n}\n```\n\n```\nlibrary \"valid_use\";\n\nimport library \"make_type\";\n\n// ✅ Valid: By directly importing the definition, we can now access `x`.\nimport library \"type\";\n\nfn ValidUse() -> i32 {\n  return MakeMyType()->x;\n}\n```\n\n## Alternatives considered\n\n-   [Other modifier keyword merging approaches](/proposals/p3762.md#other-modifier-keyword-merging-approaches)\n-   [No `extern` keyword](/proposals/p3762.md#no-extern-keyword)\n-   [Looser restrictions on declarations](/proposals/p3762.md#looser-restrictions-on-declarations)\n-   [`extern` naming](/proposals/p3762.md#extern-naming)\n-   [Default `extern` to private](/proposals/p3762.md#default-extern-to-private)\n-   [Opaque types](/proposals/p3762.md#opaque-types)\n-   [Require a library provide its own `extern` declarations](/proposals/p3762.md#require-a-library-provide-its-own-extern-declarations)\n-   [Allow cross-package `extern` declarations](/proposals/p3762.md#allow-cross-package-extern-declarations)\n-   [Use a partially or fully semantic rule](/proposals/p3763.md#use-a-partially-or-fully-semantic-rule)\n-   [Use package-wide name poisoning](/proposals/p3763.md#use-package-wide-name-poisoning)\n-   [Allow shadowing in implementation file after use in API file](/proposals/p3763.md#allow-shadowing-in-implementation-file-after-use-in-api-file)\n-   [Allow multiple non-owning declarations, remove the import requirement, or both](/proposals/p3980.md#allow-multiple-non-owning-declarations-remove-the-import-requirement-or-both)\n-   [Total number of allowed declarations (owning and non-owning)](/proposals/p3980.md#total-number-of-allowed-declarations-owning-and-non-owning)\n    -   [Do not restrict the number of forward declarations](/proposals/p3980.md#do-not-restrict-the-number-of-forward-declarations)\n    -   [Allow up to two declarations total](/proposals/p3980.md#allow-up-to-two-declarations-total)\n    -   [Allow up to four declarations total](/proposals/p3980.md#allow-up-to-four-declarations-total)\n-   [Don't require a modifier on the owning declarations](/proposals/p3980.md#dont-require-a-modifier-on-the-owning-declarations)\n-   [Only require `extern` on the first owning declaration](/proposals/p3980.md#only-require-extern-on-the-first-owning-declaration)\n-   [Separate require-direct-import from non-owning declarations](/proposals/p3980.md#separate-require-direct-import-from-non-owning-declarations)\n-   [Other `extern` syntaxes](/proposals/p3980.md#other-extern-syntaxes)\n-   [Have types with `extern` members re-export them](/proposals/p3980.md#have-types-with-extern-members-re-export-them)\n-   [Require syntactic matching for `extern library` declarations](/proposals/p3980.md#require-syntactic-matching-for-extern-library-declarations)\n\n## References\n\n-   Proposal\n    [#3762: Merging forward declarations](https://github.com/carbon-language/carbon-lang/pull/3762)\n-   Proposal\n    [#3763: Matching redeclarations](https://github.com/carbon-language/carbon-lang/pull/3763)\n-   Proposal\n    [#3980: Singular `extern` declarations](https://github.com/carbon-language/carbon-lang/pull/3980)\n"
  },
  {
    "path": "docs/design/expressions/README.md",
    "content": "# Expressions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Precedence](#precedence)\n-   [Names](#names)\n    -   [Unqualified names](#unqualified-names)\n    -   [Qualified names and member access](#qualified-names-and-member-access)\n-   [Operators](#operators)\n-   [Suffix operators](#suffix-operators)\n-   [Conversions and casts](#conversions-and-casts)\n-   [`if` expressions](#if-expressions)\n-   [Numeric type literal expressions](#numeric-type-literal-expressions)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nExpressions are the portions of Carbon syntax that produce values. Because types\nin Carbon are values, this includes anywhere that a type is specified.\n\n```\nfn Foo(a: i32*) -> i32 {\n  return *a;\n}\n```\n\nHere, the parameter type `i32*`, the return type `i32`, and the operand `*a` of\nthe `return` statement are all expressions.\n\n## Precedence\n\nExpressions are interpreted based on a partial\n[precedence ordering](https://en.wikipedia.org/wiki/Order_of_operations).\nExpression components which lack a relative ordering must be disambiguated by\nthe developer, for example by adding parentheses; otherwise, the expression will\nbe invalid due to ambiguity. Precedence orderings will only be added when it's\nreasonable to expect most developers to understand the precedence without\nparentheses.\n\nThe precedence diagram is defined thusly:\n\n```mermaid\n%%{init: {'themeVariables': {'fontFamily': 'monospace'}}}%%\ngraph BT\n    parens[\"(...)\"]\n\n    braces[\"{...}\"]\n    click braces \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/classes.md#literals\"\n\n    unqualifiedName[\"x\"]\n    click unqualifiedName \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/README.md#unqualified-names\"\n\n    top((\" \"))\n\n    suffixOps{\"x.y\n               x.(...)\n               x->y\n               x->(...)\n               x(...)\n               x[y]\"}\n    click suffixOps \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/README.md#suffix-operators\"\n\n    qualifiedType[\"const T\n                   partial T\"]\n    click pointer-type \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/type_operators.md\"\n\n    pointerType{\"T*\"}\n    click pointer-type \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/type_operators.md\"\n\n    pointer{\"*x\n             &x\"}\n    click pointer \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/pointer.md\"\n\n    negation[\"-x\"]\n    click negation \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/arithmetic.md\"\n\n    complement[\"^x\"]\n    click complement \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/bitwise.md\"\n\n    incDec[\"++x;\n            --x;\"]\n    click incDec \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/assignment.md\"\n\n    unary((\" \"))\n\n    as[\"x as T\"]\n    click as \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/implicit_conversions.md\"\n\n    multiplication>\"x * y\n                    x / y\"]\n    click multiplication \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/arithmetic.md\"\n\n    addition>\"x + y\n              x - y\"]\n    click addition \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/arithmetic.md\"\n\n    modulo[\"x % y\"]\n    click modulo \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/arithmetic.md\"\n\n    bitwise_and>\"x & y\"]\n    bitwise_or>\"x | y\"]\n    bitwise_xor>\"x ^ y\"]\n    click bitwise_and \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/bitwise.md\"\n    click bitwise_or \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/bitwise.md\"\n    click bitwise_xor \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/bitwise.md\"\n\n    shift[\"x << y\n           x >> y\"]\n    click shift \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/bitwise.md\"\n\n    binaryOps((\" \"))\n\n    where[\"T where R\"]\n\n    comparison[\"x == y\n                x != y\n                x < y\n                x <= y\n                x > y\n                x >= y\"]\n    click comparison \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/comparison_operators.md\"\n\n    not[\"not x\"]\n    click not \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/logical_operators.md\"\n\n    logicalOperand((\" \"))\n\n    and>\"x and y\"]\n    click and \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/logical_operators.md\"\n\n    or>\"x or y\"]\n    click or \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/logical_operators.md\"\n\n    logicalExpression((\" \"))\n\n    ref[\"ref x\"]\n\n    if>\"if x then y else z\"]\n    click if \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/if.md\"\n\n    insideParens[\"(...)\"]\n\n    assignment[\"x = y;\n                x $= y;\"]\n    click assignment \"https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/assignment.md\"\n\n    expressionStatement[\"x;\"]\n\n    top --> parens & braces & unqualifiedName\n\n    suffixOps --> top\n\n    qualifiedType --> suffixOps\n    pointerType --> qualifiedType\n\n    pointer --> suffixOps\n    negation & complement & incDec --> pointer\n    unary --> pointerType & negation & complement\n\n    %% Use a longer arrow here to put `not` next to other unary operators\n    not ---> suffixOps\n\n    %% `as` at the same level as `where` and comparisons\n    as -----> unary\n\n    multiplication & modulo & bitwise_and & bitwise_or & bitwise_xor & shift --> unary\n    addition --> multiplication\n    binaryOps --> addition & modulo & bitwise_and & bitwise_or & bitwise_xor & shift\n\n    where --> binaryOps\n    comparison --> binaryOps\n    logicalOperand --> comparison & not\n\n    %% This helps group `and` and `or` together\n    classDef hidden display: none;\n    HIDDEN:::hidden ~~~ logicalOperand\n\n    and & or --> logicalOperand\n    logicalExpression --> as & where & and & or\n    ref & expressionStatement --> logicalExpression\n    if ---> ref\n    insideParens & assignment --> if\n```\n\nThe diagram's attributes are:\n\n-   Each non-empty node represents a precedence group. Empty circles are used to\n    simplify the graph, and do not represent a precedence group.\n\n-   When an expression is composed from different precedence groups, the\n    interpretation is determined by the precedence edges:\n\n    -   A precedence edge A --> B means that A is lower precedence than B, so A\n        can contain B without parentheses. For example, `or --> not` means that\n        `not x or y` is treated as `(not x) or y`.\n\n    -   Precedence edges are transitive. For example, `or --> == --> as` means\n        that `or` is lower precedence than `as`.\n\n-   When a binary operator expression is composed from a single precedence\n    group, the interpretation is determined by the\n    [associativity](https://en.wikipedia.org/wiki/Operator_associativity) of the\n    precedence group:\n\n    ```mermaid\n    graph TD\n        non[\"Non-associative\"]\n        left>\"Left associative\"]\n    ```\n\n    -   For example, `+` and `-` are left-associative and in the same precedence\n        group, so `a + b + c - d` is treated as `((a + b) + c) - d`.\n\n    -   Note that in Carbon, we currently only have left-associative operators.\n        Unlike C++ and other languages, [assignment](/docs/design/assignment.md)\n        isn't a right-associative operator, it uses its own statement.\n\n-   When a unary operator expression is composed from a single precedence group,\n    it can allow unparenthesized repetition or not:\n\n    ```mermaid\n    graph TD\n        non[\"Non-repeating\"]\n        repeating{\"Repeating\"}\n    ```\n\n    This is analogous to associativity for binary operators.\n\n## Names\n\n### Unqualified names\n\nAn _unqualified name_ is a [word](../lexical_conventions/words.md) that is not a\nkeyword and is not preceded by a period (`.`).\n\n**TODO:** Name lookup rules for unqualified names.\n\n### Qualified names and member access\n\nA _qualified name_ is a word that appears immediately after a period or\nrightward arrow. Qualified names appear in the following contexts:\n\n-   [Designators](/docs/design/classes.md#literals): `.` _word_\n-   [Simple member access expressions](member_access.md): _expression_ `.`\n    _word_\n-   [Simple pointer member access expressions](member_access.md): _expression_\n    `->` _word_\n\n```\nvar x: auto = {.hello = 1, .world = 2};\n                ^^^^^       ^^^^^ qualified name\n               ^^^^^^      ^^^^^^ designator\n\nx.hello = x.world;\n  ^^^^^     ^^^^^ qualified name\n^^^^^^^   ^^^^^^^ member access expression\n\nx.hello = (&x)->world;\n                ^^^^^ qualified name\n          ^^^^^^^^^^^ pointer member access expression\n```\n\nQualified names refer to members of an entity determined by the context in which\nthe expression appears. For a member access, the entity is named by the\nexpression preceding the period. In a struct literal, the entity is the struct\ntype. For example:\n\n```\npackage Foo;\nnamespace N;\nfn N.F() {}\n\nfn G() {\n  // Same as `(Foo.N).F()`.\n  // `Foo.N` names namespace `N` in package `Foo`.\n  // `(Foo.N).F` names function `F` in namespace `N`.\n  Foo.N.F();\n}\n\n// `.n` refers to the member `n` of `{.n: i32}`.\nfn H(a: {.n: i32}) -> i32 {\n  // `a.n` is resolved to the member `{.n: i32}.n`,\n  // and names the corresponding subobject of `a`.\n  return a.n;\n}\n\nfn J() {\n  // `.n` refers to the member `n of `{.n: i32}`.\n  H({.n = 5 as i32});\n}\n```\n\nMember access expressions associate left-to-right. If the member name is more\ncomplex than a single _word_, a compound member access expression can be used,\nwith parentheses around the member name:\n\n-   _expression_ `.` `(` _expression_ `)`\n-   _expression_ `->` `(` _expression_ `)`\n\n```\ninterface I { fn F[self: Self](); }\nclass X {}\nimpl X as I { fn F[self: Self]() {} }\n\n// `x.I.F()` would mean `(x.I).F()`.\nfn Q(x: X) { x.(I.F)(); }\n```\n\nEither simple or compound member access can be part of a _pointer_ member access\nexpression when an `->` is used instead of a `.`, where _expression_ `->` _..._\nis syntactic sugar for `(` `*` _expression_ `)` `.` _..._.\n\n## Operators\n\nMost expressions are modeled as operators:\n\n| Category   | Operator                            | Syntax    | Function                                                              |\n| ---------- | ----------------------------------- | --------- | --------------------------------------------------------------------- |\n| Call       | `()` (unary)                        | `x(...)`  | Function call: the value returned by calling the function `x`.        |\n| Call       | [`[]`](indexing.md) (unary)         | `x[y]`    | Subscripting or indexing: returns the element `y` of `x`.             |\n| Pointer    | [`*`](pointer_operators.md) (unary) | `*x`      | Pointer dereference: the object pointed to by `x`.                    |\n| Pointer    | [`&`](pointer_operators.md) (unary) | `&x`      | Address-of: a pointer to the object `x`.                              |\n| Arithmetic | [`-`](arithmetic.md) (unary)        | `-x`      | The negation of `x`.                                                  |\n| Bitwise    | [`^`](bitwise.md) (unary)           | `^x`      | The bitwise complement of `x`.                                        |\n| Arithmetic | [`+`](arithmetic.md)                | `x + y`   | The sum of `x` and `y`.                                               |\n| Arithmetic | [`-`](arithmetic.md) (binary)       | `x - y`   | The difference of `x` and `y`.                                        |\n| Arithmetic | [`*`](arithmetic.md)                | `x * y`   | The product of `x` and `y`.                                           |\n| Arithmetic | [`/`](arithmetic.md)                | `x / y`   | `x` divided by `y`, or the quotient thereof.                          |\n| Arithmetic | [`%`](arithmetic.md)                | `x % y`   | `x` modulo `y`.                                                       |\n| Bitwise    | [`&`](bitwise.md)                   | `x & y`   | The bitwise AND of `x` and `y`.                                       |\n| Bitwise    | [`\\|`](bitwise.md)                  | `x \\| y`  | The bitwise OR of `x` and `y`.                                        |\n| Bitwise    | [`^`](bitwise.md) (binary)          | `x ^ y`   | The bitwise XOR of `x` and `y`.                                       |\n| Bitwise    | [`<<`](bitwise.md)                  | `x << y`  | `x` bit-shifted left `y` places.                                      |\n| Bitwise    | [`>>`](bitwise.md)                  | `x >> y`  | `x` bit-shifted right `y` places.                                     |\n| Conversion | [`as`](as_expressions.md)           | `x as T`  | Converts the value `x` to the type `T`.                               |\n| Comparison | [`==`](comparison_operators.md)     | `x == y`  | Equality: `true` if `x` is equal to `y`.                              |\n| Comparison | [`!=`](comparison_operators.md)     | `x != y`  | Inequality: `true` if `x` is not equal to `y`.                        |\n| Comparison | [`<`](comparison_operators.md)      | `x < y`   | Less than: `true` if `x` is less than `y`.                            |\n| Comparison | [`<=`](comparison_operators.md)     | `x <= y`  | Less than or equal: `true` if `x` is less than or equal to `y`.       |\n| Comparison | [`>`](comparison_operators.md)      | `x > y`   | Greater than: `true` if `x` is greater than to `y`.                   |\n| Comparison | [`>=`](comparison_operators.md)     | `x >= y`  | Greater than or equal: `true` if `x` is greater than or equal to `y`. |\n| Logical    | [`and`](logical_operators.md)       | `x and y` | A short-circuiting logical AND: `true` if both operands are `true`.   |\n| Logical    | [`or`](logical_operators.md)        | `x or y`  | A short-circuiting logical OR: `true` if either operand is `true`.    |\n| Logical    | [`not`](logical_operators.md)       | `not x`   | Logical NOT: `true` if the operand is `false`.                        |\n\nThe binary arithmetic and bitwise operators also have\n[compound assignment](/docs/design/assignment.md) forms. These are statements\nrather than expressions, and do not produce a value.\n\n## Suffix operators\n\nThese operators act like unary postfix operators for purposes of precedence:\n\n-   [Member access operators](member_access.md), like `x.y` and the\n    dereferencing variant `x->y`, only have an expression on their left-hand\n    side. The right-hand side is a name.\n-   The [compound member access operators](member_access.md), `x.(...)` and\n    `x->(...)`, have an expression as their second operand, but put that\n    expression in parentheses and so it doesn't participate in the precedence\n    considerations of its first operand.\n-   The [indexing operator](indexing.md), `x[y]`, similarly puts its second\n    operand in matching square brackets.\n-   The call operator, `x(...)`, takes a comma-separated list of arguments, but\n    again puts them in parentheses that clearly separate them for precedence\n    purposes.\n\n## Conversions and casts\n\nWhen an expression appears in a context in which an expression of a specific\ntype is expected, [implicit conversions](implicit_conversions.md) are applied to\nconvert the expression to the target type.\n\nExpressions can also be converted to a specific type using an\n[`as` expression](as_expressions.md).\n\n```\nfn Bar(n: i32);\nfn Baz(n: i64) {\n  // OK, same as Bar(n as i32)\n  Bar(n);\n}\n```\n\n## `if` expressions\n\nAn [`if` expression](if.md) chooses between two expressions.\n\n```\nfn Run(args: Span(StringView)) {\n  var file: StringView = if args.size() > 1 then args[1] else \"/dev/stdin\";\n}\n```\n\n`if` expressions are analogous to `?:` ternary expressions in C and C++.\n\n## Numeric type literal expressions\n\nCarbon's syntax provides a simple way to represent different types of integers\nand floating-point numbers. Each type is identified with a keyword-like syntax,\nprefixed with either `i`, `u`, or `f` followed by a multiple of 8, representing\nthe size in bits of the data type.\n\nThese are referred to as\n[numeric type literals](literals.md#numeric-type-literals).\n\n## Alternatives considered\n\nOther expression documents will list more alternatives; this lists alternatives\nnot noted elsewhere.\n\n-   [Total order](/proposals/p0555.md#total-order)\n-   [Different precedence for different operands](/proposals/p0555.md#different-precedence-for-different-operands)\n-   [Require less than a partial order](/proposals/p0555.md#require-less-than-a-partial-order)\n\n## References\n\nOther expression documents will list more references; this lists references not\nnoted elsewhere.\n\n-   Proposal\n    [#555: Operator precedence](https://github.com/carbon-language/carbon-lang/pull/555).\n"
  },
  {
    "path": "docs/design/expressions/arithmetic.md",
    "content": "# Arithmetic\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Precedence and associativity](#precedence-and-associativity)\n-   [Built-in types](#built-in-types)\n    -   [Integer types](#integer-types)\n        -   [Overflow and other error conditions](#overflow-and-other-error-conditions)\n    -   [Floating-point types](#floating-point-types)\n    -   [Strings](#strings)\n-   [Extensibility](#extensibility)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon provides a conventional set of arithmetic operators:\n\n```\nvar a: i32 = 5;\nvar b: i32 = 3;\n\n// -5\nvar negation: i32 = -a;\n// 8\nvar sum: i32 = a + b;\n// 2\nvar difference: i32 = a - b;\n// 15\nvar product: i32 = a * b;\n// 1\nvar quotient: i32 = a / b;\n// 2\nvar remainder: i32 = a % b;\n```\n\nThese operators have predefined meanings for some of Carbon's\n[built-in types](#built-in-types).\n\nUser-defined types can define the meaning of these operations by\n[implementing an interface](#extensibility) provided as part of the Carbon\nstandard library.\n\n## Precedence and associativity\n\n```mermaid\n%%{init: {'themeVariables': {'fontFamily': 'monospace'}}}%%\ngraph BT\n    negation[\"-x\"]\n    multiplication>\"x * y\n                    x / y\"]\n    addition>\"x + y\n              x - y\"]\n    modulo[\"x % y\"]\n\n    multiplication & modulo --> negation\n    addition --> multiplication\n```\n\n<small>[Instructions for reading this diagram.](README.md#precedence)</small>\n\nBinary `+` and `-` can be freely mixed, and are left-associative.\n\n```\n// -2, same as `((1 - 2) + 3) - 4`.\nvar n: i32 = 1 - 2 + 3 - 4;\n```\n\nBinary `*` and `/` can be freely mixed, and are left-associative.\n\n```\n// 0.375, same as `((1.0 / 2.0) * 3.0) / 4.0`.\nvar m: f32 = 1.0 / 2.0 * 3.0 / 4.0;\n```\n\nUnary `-` has higher precedence than binary `*`, `/`, and `%`. Binary `*` and\n`/` have higher precedence than binary `+` and `-`.\n\n```\n// 5, same as `(-1) + ((-2) * (-3))`.\nvar x: i32 = -1 + -2 * -3;\n// Error, parentheses required: no precedence order between `+` and `%`.\nvar y: i32 = 2 + 3 % 5;\n```\n\n## Built-in types\n\nFor binary operators, if the operands have different built-in types, they are\nconverted as follows:\n\n-   If the types are `uN` and `uM`, or they are `iN` and `iM`, the operands are\n    converted to the larger type.\n-   If one type is `iN` and the other type is `uM`, and `M` < `N`, the `uM`\n    operand is converted to `iN`.\n-   If one type is `fN` and the other type is `iM` or `uM`, and there is an\n    [implicit conversion](implicit_conversions.md#data-types) from the integer\n    type to `fN`, then the integer operand is converted to `fN`.\n\nMore broadly, if one operand is of built-in type and the other operand can be\nimplicitly converted to that type, then it is, unless that behavior is\n[overridden](#extensibility).\n\nA built-in arithmetic operation is performed if, after the above conversion\nstep, the operands have the same built-in type. The result type is that type.\nThe result type is never wider than the operands, and the conversions applied to\nthe operands are always lossless, so arithmetic between a wider unsigned integer\ntype and a narrower signed integer is not defined.\n\nAlthough the conversions are always lossless, the arithmetic may still\n[overflow](#overflow-and-other-error-conditions).\n\n### Integer types\n\nSigned and unsigned integer types support all the arithmetic operators.\n\nSigned integer arithmetic produces the usual mathematical result. Unsigned\ninteger arithmetic in `uN` wraps around modulo 2<sup>`N`</sup>.\n\nDivision truncates towards zero. The result of the `%` operator is defined by\nthe equation `a % b == a - (a / b) * b`.\n\n#### Overflow and other error conditions\n\nInteger arithmetic is subject to two classes of problems for which an operation\nhas no representable result:\n\n-   Overflow, where the resulting value is too large to be represented in the\n    type, or, for `%`, when the implied multiplication overflows.\n-   Division by zero.\n\nUnsigned integer arithmetic cannot overflow, but division by zero can still\noccur.\n\n**Note:** All arithmetic operators can overflow for signed integer types. For\nexample, given a value `v: iN` that is the least possible value for its type,\n`-v`, `v + v`, `v - 1`, `v * 2`, `v / -1`, and `v % -1` all result in overflow.\n\nSigned integer overflow and signed or unsigned integer division by zero are\nprogramming errors:\n\n-   In a development build, they will be caught immediately when they happen at\n    runtime.\n-   In a performance build, the optimizer can assume that such conditions don't\n    occur. As a consequence, if they do, the behavior of the program is not\n    defined.\n-   In a hardened build, overflow and division by zero do not result in\n    undefined behavior. On overflow and division by zero, either the program\n    will be aborted, or the arithmetic will evaluate to a mathematically\n    incorrect result, such as a two's complement result or zero. The program\n    might not in all cases be aborted immediately -- for example, multiple\n    overflow checks might be combined into one -- but no control flow or memory\n    access that depends on the value will be performed.\n\n**TODO:** Unify the description of these programming errors with those of\nbit-shift domain errors, document the behavior in a common place and link to it\nfrom here.\n\n**TODO:** In a hardened build, should we prefer to trap on overflow, give a\ntwo's complement result, or produce zero? Using zero may defeat some classes of\nexploit, but comes at a code size and performance cost.\n\n### Floating-point types\n\nFloating-point types support all the arithmetic operators other than `%`.\nFloating-point types in Carbon have IEEE 754 semantics, use the round-to-nearest\nrounding mode, and do not set any floating-point exception state.\n\nBecause floating-point arithmetic follows IEEE 754 rules: overflow results in\n±∞, and division by zero results in either ±∞ or, for 0.0 / 0.0, a quiet NaN.\n\n### Strings\n\n**TODO:** Decide whether strings are built-in types, and whether they support\n`+` for concatenation. See\n[#457](https://github.com/carbon-language/carbon-lang/issues/457).\n\n## Extensibility\n\nArithmetic operators can be provided for user-defined types by implementing the\nfollowing family of interfaces:\n\n```\n// Unary `-`.\ninterface Negate {\n  default let Result:! type = Self;\n  fn Op[self: Self]() -> Result;\n}\n```\n\n```\n// Binary `+`.\ninterface AddWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint Add {\n  extend AddWith(Self) where .Result = Self;\n}\n```\n\n```\n// Binary `-`.\ninterface SubWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint Sub {\n  extend SubWith(Self) where .Result = Self;\n}\n```\n\n```\n// Binary `*`.\ninterface MulWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint Mul {\n  extend MulWith(Self) where .Result = Self;\n}\n```\n\n```\n// Binary `/`.\ninterface DivWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint Div {\n  extend DivWith(Self) where .Result = Self;\n}\n```\n\n```\n// Binary `%`.\ninterface ModWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint Mod {\n  extend ModWith(Self) where .Result = Self;\n}\n```\n\nGiven `x: T` and `y: U`:\n\n-   The expression `-x` is rewritten to `x.(Negate.Op)()`.\n-   The expression `x + y` is rewritten to `x.(AddWith(U).Op)(y)`.\n-   The expression `x - y` is rewritten to `x.(SubWith(U).Op)(y)`.\n-   The expression `x * y` is rewritten to `x.(MulWith(U).Op)(y)`.\n-   The expression `x / y` is rewritten to `x.(DivWith(U).Op)(y)`.\n-   The expression `x % y` is rewritten to `x.(ModWith(U).Op)(y)`.\n\nImplementations of these interfaces are provided for built-in types as necessary\nto give the semantics described above.\n\n## Alternatives considered\n\n-   [Use a sufficiently wide result type to avoid overflow](/proposals/p1083.md#use-a-sufficiently-wide-result-type-to-avoid-overflow)\n-   [Guarantee that the program never proceeds with an incorrect value after overflow](/proposals/p1083.md#guarantee-that-the-program-never-proceeds-with-an-incorrect-value-after-overflow)\n-   [Guarantee that all integer arithmetic is two's complement](/proposals/p1083.md#guarantee-that-all-integer-arithmetic-is-twos-complement)\n-   [Treat overflow as an error but don't optimize on it](/proposals/p1083.md#treat-overflow-as-an-error-but-dont-optimize-on-it)\n-   [Don't let `Unsigned` arithmetic wrap](/proposals/p1083.md#dont-let-unsigned-arithmetic-wrap)\n-   [Provide separate wrapping types](/proposals/p1083.md#provide-separate-wrapping-types)\n-   [Do not provide an ordering or division for `uN`](/proposals/p1083.md#do-not-provide-an-ordering-or-division-for-un)\n-   [Give unary `-` lower precedence](/proposals/p1083.md#give-unary---lower-precedence)\n-   [Include a unary plus operator](/proposals/p1083.md#include-a-unary-plus-operator)\n-   [Floating-point modulo operator](/proposals/p1083.md#floating-point-modulo-operator)\n-   [Provide different division operators](/proposals/p1083.md#provide-different-division-operators)\n-   [Use different division and modulo semantics](/proposals/p1083.md#use-different-division-and-modulo-semantics)\n-   [Use different precedence groups for division and multiplication](/proposals/p1083.md#use-different-precedence-groups-for-division-and-multiplication)\n-   [Use the same precedence group for modulo and multiplication](/proposals/p1083.md#use-the-same-precedence-group-for-modulo-and-multiplication)\n-   [Use a different spelling for modulo](/proposals/p1083.md#use-a-different-spelling-for-modulo)\n\n## References\n\n-   Proposal\n    [#1083: Arithmetic](https://github.com/carbon-language/carbon-lang/pull/1083)\n-   Proposal\n    [#1178: Rework operator interfaces](https://github.com/carbon-language/carbon-lang/pull/1178)\n"
  },
  {
    "path": "docs/design/expressions/as_expressions.md",
    "content": "# `as` expressions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Precedence and associativity](#precedence-and-associativity)\n-   [Built-in types](#built-in-types)\n    -   [Data types](#data-types)\n    -   [Compatible types](#compatible-types)\n-   [Extensibility](#extensibility)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nAn expression of one type can be explicitly cast to another type by using an\n`as` expression:\n\n```\nvar n: i32 = Get();\nvar f: f32 = n as f32;\n```\n\nAn `as` expression can be used to perform any implicit conversion, either when\nthe context does not imply a destination type or when it is valuable to a reader\nof the code to make the conversion explicit. In addition, `as` expressions can\nperform safe conversions that nonetheless should not be performed implicitly,\nsuch as lossy conversions or conversions that lose capabilities or change the\nway a type would be interpreted.\n\nAs guidelines, an `as` conversion should be permitted when:\n\n-   The conversion is _complete_: it produces a well-defined output value for\n    each input value.\n-   The conversion is _unsurprising_: the resulting value is the expected value\n    in the destination type.\n\nFor example:\n\n-   A conversion from `fM` to `iN` is not complete, because it is not defined\n    for input values that are out of the range of the destination type, such as\n    infinities or, if `N` is too small, large finite values.\n-   A conversion from `iM` to `iN`, where `N` < `M`, is either not complete or\n    not unsurprising, because there is more than one possible expected behavior\n    for an input value that is not within the destination type, and those\n    behaviors are not substantially the same -- we could perform two's\n    complement wrapping, saturate, or produce undefined behavior analogous to\n    arithmetic overflow.\n-   A conversion from `iM` to `fN` can be unsurprising, because even though\n    there may be a choice of which way to round, the possible values are\n    substantially the same.\n\nIt is possible for user-defined types to [extend](#extensibility) the set of\nvalid explicit casts that can be performed by `as`. Such extensions are expected\nto follow these guidelines.\n\n## Precedence and associativity\n\n`as` expressions are non-associative.\n\n```\nvar b: bool = true;\n// OK\nvar n: i32 = (b as i1) as i32;\nvar m: auto = b as (bool as Hashable);\n// Error, ambiguous\nvar m: auto = b as T as U;\n```\n\n**Note:** `b as (bool as Hashable)` is valid but not useful, because\n[the second operand of `as` is implicitly converted to type `type`](#extensibility).\nThis expression therefore has the same interpretation as `b as bool`.\n\n**TODO:** We should consider making `as` expressions left-associative now that\nfacet types have been removed from the language.\n\nThe `as` operator has lower precedence than operators that visually bind\ntightly:\n\n-   prefix symbolic operators\n    -   dereference (`*a`)\n    -   negation (`-a`)\n    -   complement (`~a`)\n-   postfix symbolic operators\n    -   pointer type formation (`T*`),\n    -   function call (`a(...)`),\n    -   array indexing (`a[...]`), and\n    -   member access (`a.m`).\n\nThe `as` operator has higher precedence than assignment and comparison. It is\nunordered with respect to binary arithmetic, bitwise operators, and unary `not`.\n\n```\n// OK\nvar x: i32* as Eq;\n// OK, `x as (U*)` not `(x as U)*`.\nvar y: auto = x as U*;\n\nvar a: i32;\nvar b: i32;\n// OK, `(a as i64) < ((*x) as i64)`.\nif (a as i64 < *x as i64) {}\n// Ambiguous: `(a + b) as i64` or `a + (b as i64)`?\nvar c: i32 = a + b as i64;\n// Ambiguous: `(a as i64) + b` or `a as (i64 + b)`?\nvar d: i32 = a as i64 + b;\n\n// OK, `(-a) as f64`, not `-(a as f64)`.\n// Unfortunately, the former is undefined if `a` is `i32.MinValue()`;\n// the latter is not.\nvar u: f64 = -a as f64;\n\n// OK, `i32 as (GetType())`, not `(i32 as GetType)()`.\nvar e: i32 as GetType();\n```\n\n## Built-in types\n\n### Data types\n\nIn addition to the [implicit conversions](implicit_conversions.md#data-types),\nthe following numeric conversions are supported by `as`:\n\n-   `iN`, `uN`, or `fN` -> `fM`, for any `N` and `M`. Values that cannot be\n    exactly represented are suitably rounded to one of the two nearest\n    representable values. Very large finite values may be rounded to an\n    infinity. NaN values are converted to NaN values.\n\n-   `bool` -> `iN` or `uN`. `false` converts to `0` and `true` converts to `1`\n    (or to `-1` for `i1`).\n\nConversions from numeric types to `bool` are not supported with `as`; instead of\nusing `as bool`, such conversions can be performed with `!= 0`.\n\nLossy conversions between `iN` or `uN` and `iM` or `uM` are not supported with\n`as`, and similarly conversions from `fN` to `iM` are not supported.\n\n**Future work:** Add mechanisms to perform these conversions.\n\n### Compatible types\n\nThe following conversion is supported by `as`:\n\n-   `T` -> `U` if `T` is\n    [compatible](../generics/terminology.md#compatible-types) with `U`.\n\n**Future work:** We may need a mechanism to restrict which conversions between\nadapters are permitted and which code can perform them. Some of the conversions\npermitted by this rule may only be allowed in certain contexts.\n\n## Extensibility\n\nExplicit casts can be defined for user-defined types such as\n[classes](../classes.md) by implementing the `As` interface:\n\n```\ninterface As(Dest:! type) {\n  fn Convert[self: Self]() -> Dest;\n}\n```\n\nThe expression `x as U` is rewritten to `x.(As(U).Convert)()`.\n\n**Note:** This rewrite causes the expression `U` to be implicitly converted to\ntype `type`. The program is invalid if this conversion is not possible.\n\n## Alternatives considered\n\n-   [Allow `as` to perform some unsafe conversions](/proposals/p0845.md#allow-as-to-perform-some-unsafe-conversions)\n-   [Allow `as` to perform two's complement truncation](/proposals/p0845.md#allow-as-to-perform-twos-complement-truncation)\n-   [`as` only performs implicit conversions](/proposals/p0845.md#as-only-performs-implicit-conversions)\n-   [Integer to bool conversions](/proposals/p0845.md#integer-to-bool-conversions)\n-   [Bool to integer conversions](/proposals/p0845.md#bool-to-integer-conversions)\n\n## References\n\n-   [Implicit conversions in C++](https://en.cppreference.com/w/cpp/language/implicit_conversion)\n-   Proposal\n    [#845: `as` expressions](https://github.com/carbon-language/carbon-lang/pull/845).\n"
  },
  {
    "path": "docs/design/expressions/bitwise.md",
    "content": "# Bitwise and shift operators\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Precedence and associativity](#precedence-and-associativity)\n-   [Integer types](#integer-types)\n-   [Integer constants](#integer-constants)\n-   [Extensibility](#extensibility)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon provides a conventional set of operators for operating on bits:\n\n```\nvar a: u8 = 5;\nvar b: u8 = 3;\nvar c: i8 = -5;\n\n// 250\nvar complement: u8 = ^a;\n// 1\nvar bitwise_and: u8 = a & b;\n// 7\nvar bitwise_or: u8 = a | b;\n// 6\nvar bitwise_xor: u8 = a ^ b;\n// 40\nvar left_shift: u8 = a << b;\n// 2\nvar logical_right_shift: u8 = a >> 1;\n// -3\nvar arithmetic_right_shift: i8 = c >> 1;\n```\n\nThese operators have [predefined meanings](#integer-types) for Carbon's integer\ntypes. User-defined types can define the meaning of these operations by\n[implementing an interface](#extensibility) provided as part of the Carbon\nstandard library.\n\n## Precedence and associativity\n\n```mermaid\n%%{init: {'themeVariables': {'fontFamily': 'monospace'}}}%%\ngraph BT\n    complement[\"^x\"]\n    bitwise_and>\"x & y\"]\n    bitwise_or>\"x | y\"]\n    bitwise_xor>\"x ^ y\"]\n    shift[\"x << y\n           x >> y\"]\n    bitwise_and & bitwise_or & bitwise_xor & shift --> complement\n```\n\n<small>[Instructions for reading this diagram.](README.md#precedence)</small>\n\nParentheses are required when mixing different bitwise and bit-shift operators.\nBinary `&`, `|`, and `^` are left-associative. The bit-shift operators `<<` and\n`>>` are non-associative.\n\n```\n// ✅ Same as (1 | 2) | 4, evaluates to 7.\nvar a: i32 = 1 | 2 | 4;\n\n// ❌ Error, parentheses are required to distinguish between\n//    (3 | 5) & 6, which evaluates to 6, and\n//    3 | (5 & 6), which evaluates to 7.\nvar b: i32 = 3 | 5 & 6;\n\n// ❌ Error, parentheses are required to distinguish between\n//    (1 << 2) << 3, which evaluates to 4 << 3 == 32, and\n//    1 << (2 << 3), which evaluates to 1 << 16 == 65536.\nvar c: i32 = 1 << 2 << 3;\n\n// ❌ Error, can't repeat the `^` operator. Use `^(^4)` or simply `4`.\nvar d: i32 = ^^4;\n```\n\n## Integer types\n\nBitwise and bit-shift operators are supported for Carbon's built-in integer\ntypes, and, unless that behavior is [overridden](#extensibility), for types that\ncan be implicitly converted to integer types, as follows:\n\nFor binary bitwise operators, if one operand has an integer type and the other\noperand can be implicitly converted to that type, then it is. If both operands\nare of integer type, this results in the following conversions:\n\n-   If the types are `uN` and `uM`, or they are `iN` and `iM`, the operands are\n    converted to the larger type.\n-   If one type is `iN` and the other type is `uM`, and `M` < `N`, the `uM`\n    operand is converted to `iN`.\n\nA built-in binary bitwise `&`, `|`, or `^` operation is performed if, after the\nabove conversion step, the operands have the same integer type. The result type\nis that type, and the result value is produced by applying the relevant\noperation -- AND, OR, or XOR -- to each pair of corresponding bits in the input,\nincluding the sign bit for a signed integer type.\n\nA built-in complement operation is performed if the operand can be implicitly\nconverted to an integer type. The result type is that type, and the result value\nis produced by flipping all bits in the input, including the sign bit for a\nsigned integer type. `^a` is equivalent to `a ^ x`, where `x` is the\nall-one-bits value of the same type as `a`.\n\nA built-in bit-shift operation is performed if both operands are, or can be\nimplicitly converted to, integer types. The result type is the converted type of\nthe first operand. The result value is produced by shifting the first operand\nleft for `<<` or right for `>>` a number of positions equal to the second\noperand. Vacant positions are filled with `0` bits, except for a right shift\nwhere the first operand is of a signed type and has a negative value, in which\ncase they are filled with `1` bits.\n\nFor the purposes of bit-shifts, bits are ordered by significance, with the most\nsignificant bit being the leftmost bit and the least significant bit being the\nrightmost bit. As a consequence, in the absence of overflow a left shift is\nequivalent to a multiplication by a power of 2 and a right shift is equivalent\nto a division by a power of two, rounding downwards.\n\nThe second operand of a bit-shift is required to be between zero (inclusive) and\nthe bit-width of the first operand (exclusive); it is a programming error if the\nsecond operand is not within that range.\n\n-   In a development build, they will be caught immediately when they happen at\n    runtime.\n-   In a performance build, the optimizer may assume that this programming error\n    does not occur.\n-   In a hardened build, the result will have well the defined behavior of\n    either aborting the program or performing a shift of an unspecified number\n    of bits, which if wider than the first operand will result in `0` or `-1`.\n    In the case where the program is aborted, the program might not in all cases\n    be aborted immediately -- for example, multiple checks might be combined\n    into one -- but no control flow or memory access that depends on the value\n    will be performed.\n\n**TODO:** Unify the description of these programming errors with those of\narithmetic overflow, document the behavior in a common place and link to it from\nhere.\n\n## Integer constants\n\nThese operations can also be applied to a pair of integer constants, or to an\ninteger constant and a value of integer type, as follows:\n\n-   If any binary bitwise or bit-shift operator is applied to two integer\n    constants, or the unary `^` operator is applied to an integer constant, the\n    result is an integer constant. Integer constants are treated as having\n    infinitely many high-order bits, where all but finitely many of those bits\n    are sign bits. For example, `-1` comprises infinitely many `1` bits. Note\n    that there is no difference between an arithmetic and a logical right shift\n    on an integer constant, because every bit always has a higher-order bit to\n    shift from.\n    -   It is easy to produce extremely large numbers by left-shifting an\n        integer constant. For example, the binary representation of\n        `1 << (1 << 1000)` is thought to be substantially larger than the total\n        entropy in the observable universe. In practice, Carbon implementations\n        will set a much lower limit on the largest integer constant that they\n        support.\n-   If a binary bitwise `&`, `|`, or `^` operation is applied to an integer\n    constant and a value of an integer type to which the constant can be\n    implicitly converted, the operand that is an integer constant is implicitly\n    converted to the integer type and the computation is performed as described\n    [above](#integer-types).\n-   If the second operand of a bit-shift operator is an integer constant and the\n    first operand is not, and the second operand is between 0 (inclusive) and\n    the bit-width of the first operand (exclusive), the integer constant is\n    converted to an integer type that can hold its value and the computation is\n    performed as described above.\n\nOther operations involving integer constants are invalid. For example, a bitwise\n`&` between a `u8` and an integer constant `500` is invalid because `500`\ndoesn't fit into `u8`, and `1 << n` is invalid if `n` is an integer variable\nbecause we don't know what type to use to compute the result.\n\nNote that the unary `^` operator applied to a non-negative integer constant\nresults in a negative integer constant, and the binary `^` operator gives a\nnegative result if exactly one of the input operands was negative. For example,\n`^0 == -1` evaluates to `true`.\n\n## Extensibility\n\nBitwise and shift operators can be provided for user-defined types by\nimplementing the following family of interfaces:\n\n```\n// Unary `^`.\ninterface BitComplement {\n  default let Result:! type = Self;\n  fn Op[self: Self]() -> Result;\n}\n```\n\n```\n// Binary `&`.\ninterface BitAndWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint BitAnd {\n  extend BitAndWith(Self) where .Result = Self;\n}\n```\n\n```\n// Binary `|`.\ninterface BitOrWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint BitOr {\n  extend BitOrWith(Self) where .Result = Self;\n}\n```\n\n```\n// Binary `^`.\ninterface BitXorWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint BitXor {\n  extend BitXorWith(Self) where .Result = Self;\n}\n```\n\n```\n// Binary `<<`.\ninterface LeftShiftWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint LeftShift {\n  extend LeftShiftWith(Self) where .Result = Self;\n}\n```\n\n```\n// Binary `>>`.\ninterface RightShiftWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\nconstraint RightShift {\n  extend RightShiftWith(Self) where .Result = Self;\n}\n```\n\nGiven `x: T` and `y: U`:\n\n-   The expression `^x` is rewritten to `x.(BitComplement.Op)()`.\n-   The expression `x & y` is rewritten to `x.(BitAndWith(U).Op)(y)`.\n-   The expression `x | y` is rewritten to `x.(BitOrWith(U).Op)(y)`.\n-   The expression `x ^ y` is rewritten to `x.(BitXorWith(U).Op)(y)`.\n-   The expression `x << y` is rewritten to `x.(LeftShiftWith(U).Op)(y)`.\n-   The expression `x >> y` is rewritten to `x.(RightShiftWith(U).Op)(y)`.\n\nImplementations of these interfaces are provided for built-in types as necessary\nto give the semantics described above.\n\n## Alternatives considered\n\n-   [Use different symbols for bitwise operators](/proposals/p1191.md#use-different-symbols-for-bitwise-operators)\n-   [Provide different operators for arithmetic and logical shifts](/proposals/p1191.md#provide-different-operators-for-arithmetic-and-logical-shifts)\n-   [Provide rotate operators](/proposals/p1191.md#provide-rotate-operators)\n-   [Guarantee the behavior of large shifts](/proposals/p1191.md#guarantee-behavior-of-large-shifts)\n-   [Support shifting a constant by a variable](/proposals/p1191.md#support-shifting-a-constant-by-a-variable)\n\n## References\n\n-   Proposal\n    [#1191: bitwise and shift operators](https://github.com/carbon-language/carbon-lang/pull/1191).\n"
  },
  {
    "path": "docs/design/expressions/comparison_operators.md",
    "content": "# Comparison operators\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [Precedence](#precedence)\n    -   [Associativity](#associativity)\n    -   [Built-in comparisons and implicit conversions](#built-in-comparisons-and-implicit-conversions)\n        -   [Consistency with implicit conversions](#consistency-with-implicit-conversions)\n        -   [Comparisons with constants](#comparisons-with-constants)\n    -   [Extensibility](#extensibility)\n        -   [Equality](#equality)\n        -   [Ordering](#ordering)\n        -   [Compatibility of equality and ordering](#compatibility-of-equality-and-ordering)\n        -   [Custom result types](#custom-result-types)\n    -   [Default implementations for basic types](#default-implementations-for-basic-types)\n-   [Open questions](#open-questions)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon provides equality and relational comparison operators, each with a\nstandard mathematical meaning:\n\n| Category   | Operator | Example  | Mathematical meaning | Description                |\n| ---------- | -------- | -------- | -------------------- | -------------------------- |\n| Equality   | `==`     | `x == y` | =                    | Equality or equal to       |\n| Equality   | `!=`     | `x != y` | ≠                    | Inequality or not equal to |\n| Relational | `<`      | `x < y`  | <                    | Less than                  |\n| Relational | `<=`     | `x <= y` | ≤                    | Less than or equal to      |\n| Relational | `>`      | `x > y`  | >                    | Greater than               |\n| Relational | `>=`     | `x >= y` | ≥                    | Greater than or equal to   |\n\nComparison operators all return a `bool`; they evaluate to `true` when the\nindicated comparison is true. All comparison operators are infix binary\noperators.\n\nThese operators have predefined meanings for some of Carbon's\n[built-in types](#built-in-comparisons-and-implicit-conversions), as well as for\nsimple [\"data\" types](#default-implementations-for-basic-types) like structs and\ntuples.\n\nUser-defined types can define the meaning of these operations by\n[implementing an interface](#extensibility) provided as part of the Carbon\nstandard library.\n\n## Details\n\n### Precedence\n\nThe comparison operators are all at the same precedence level. This level is\nlower than operators used to compute (non-`bool`) values, higher than the\n[logical operators](logical_operators.md) `and` and `or`, and incomparable with\nthe precedence of `not`.\n\nFor example:\n\n```carbon\n// ✅ Valid: precedence provides order of evaluation.\nif (n + m * 3 < n * n and 3 < m and m < 6) {\n  ...\n}\n// The above is equivalent to:\nif (((n + (m * 3)) < (n * n)) and ((3 < m) and (m < 6))) {\n  ...\n}\n\n// ❌ Invalid due to ambiguity: `(not a) == b` or `not (a == b)`?\nif (not a == b) {\n  ...\n}\n// ❌ Invalid due to precedence: write `a == (not b)`.\nif (a == not b) {\n  ...\n}\n// ❌ Invalid due to precedence: write `not (f < 5.0)`.\nif (not f < 5.0) {\n  ....\n}\n```\n\n### Associativity\n\nThe comparison operators are non-associative. For example:\n\n```carbon\n// ❌ Invalid: write `3 < m and m < 6`.\nif (3 < m < 6) {\n  ...\n}\n// ❌ Invalid: write `a == b and b == c`.\nif (a == b == c) {\n  ...\n}\n// ❌ Invalid: write `(m > 1) == (n > 1)`.\nif (m > 1 == n > 1) {\n  ...\n}\n```\n\n### Built-in comparisons and implicit conversions\n\nBuilt-in comparisons are permitted in three cases:\n\n1.  When both operands are of standard Carbon integer types (`Int(n)` or\n    `Unsigned(n)`).\n2.  When both operands are of standard Carbon floating-point types (`Float(n)`).\n3.  When one operand is of floating-point type and the other is of integer type,\n    if all values of the integer type can be exactly represented in the\n    floating-point type.\n\nIn each case, the result is the mathematically-correct answer. This applies even\nwhen comparing `Int(n)` with `Unsigned(m)`.\n\nFor example:\n\n```carbon\n// ✅ Valid: Fits case #1. The value of `compared` is `true` because `a` is less\n// than `b`, even though the result of a wrapping `i32` or `u32` comparison\n// would be `false`.\nfn Compare(a: i32, b: u32) -> bool { return a < b; }\nlet compared: bool = Compare(-1, 4_000_000_000);\n\n// ❌ Invalid: Doesn't fit case #3 because `i64` values in general are not\n// exactly representable in the type `f32`.\nlet float: f32 = 1.0e18;\nlet integer: i64 = 1_000_000_000_000_000_000;\nlet eq: bool = float == integer;\n```\n\nComparisons involving integer and floating-point constants are not covered by\nthese rules and are [discussed separately](#comparisons-with-constants).\n\n#### Consistency with implicit conversions\n\nWe support the following [implicit conversions](implicit_conversions.md):\n\n-   From `Int(n)` to `Int(m)` if `m > n`.\n-   From `Unsigned(n)` to `Int(m)` or `Unsigned(m)` if `m > n`.\n-   From `Float(n)` to `Float(m)` if `m > n`.\n-   From `Int(n)` to `Float(m)` if `Float(m)` can represent all values of\n    `Int(n)`.\n\nThese rules can be summarized as: a type `T` can be converted to `U` if every\nvalue of type `T` is a value of type `U`.\n\nImplicit conversions are also supported from certain kinds of integer and\nfloating-point constants to `Int(n)` and `Float(n)` types, if the constant can\nbe represented in the type.\n\nAll built-in comparisons can be viewed as performing implicit conversions on at\nmost one of the operands in order to reach a suitable pair of identical or very\nsimilar types, and then performing a comparison on those types. The target types\nfor these implicit conversions are, for each suitable value `n`:\n\n-   `Int(n)` versus `Int(n)`\n-   `Unsigned(n)` versus `Unsigned(n)`\n-   `Int(n)` versus `Unsigned(n)`\n-   `Unsigned(n)` versus `Int(n)`\n-   `Float(n)` versus `Float(n)`\n\nThere will in general be multiple combinations of implicit conversions that will\nlead to one of the above forms, but we will arrive at the same result regardless\nof which is selected, because all comparisons are mathematically correct and all\nimplicit conversions are lossless. Implementations are expected to do whatever\nis most efficient: for example, for `u16 < i32` it is likely that the best\nchoice would be to promote the `u16` to `i32`, not `u32`.\n\nBecause we only ever convert at most one operand, we never use an intermediate\ntype that is larger than both input types. For example, both `i32` and `f32` can\nbe implicitly converted to `f64`, but we do not permit comparisons between `i32`\nand `f32` even though we could perform those comparisons in `f64`. If such\ncomparisons were permitted, the results could be surprising:\n\n```carbon\n// `i32` can exactly represent this value.\nvar integer: i32 = 2_000_000_001;\n// This value is within the representable range for `f32`, but will be rounded\n// to 2_000_000_000.0 due to the limited precision of `f32`.\nvar float: f32 = 2_000_000_001.0;\n\n// ❌ Invalid: `f32` cannot exactly represent all values of `i32`.\nif (integer == float) {\n  ...\n}\n\n// ✅ Valid: An explicit cast to `f64` on either side makes the code valid, but\n// will compare unequal because `float` was rounded to 2_000_000_000.0\n// but `integer` will convert to exactly 2_000_000_001.0.\nif (integer == float as f64) {\n  ...\n}\nif (integer as f64 == float) {\n  ...\n}\n```\n\nThe two kinds of mixed-type comparison may be\n[less efficient](/proposals/p0702.md#performance) than the other kinds due to\nthe slightly wider domain.\n\nNote that this approach diverges from C++, which would convert both operands to\na common type first, sometimes performing a lossy conversion potentially giving\nan incorrect result, sometimes converting both operands, and sometimes using a\nwider type than either of the operand types.\n\n#### Comparisons with constants\n\nWe permit the following comparisons involving constants:\n\n-   A constant can be compared with a value of any type to which it can be\n    implicitly converted.\n-   Any two constants can be compared, even if there is no type that can\n    represent both.\n\nAs described in [implicit conversions](implicit_conversions.md#data-types),\ninteger constants can be implicitly converted to any integer or floating-point\ntype that can represent their value, and floating-point constants can be\nimplicitly converted to any floating-point type that can represent their value.\n\nNote that this disallows comparisons between, for example, `i32` and an integer\nliteral that cannot be represented in `i32`. Such comparisons would always be\ntautological. This decision should be revisited if it proves problematic in\npractice, for example in templated code where the literal is sometimes in range.\n\n### Extensibility\n\nUser-defined types can extend the behavior of the comparison operators by\nimplementing interfaces. In this section, various properties are specified that\nsuch implementations \"should\" satisfy. These properties are not enforced in\ngeneral, but the standard library might detect violations of some of them in\nsome circumstances. These properties may be assumed by checked-generic code,\nresulting in unexpected behavior if they are violated.\n\n#### Equality\n\nComparison operators can be provided for user-defined types by implementing the\n`EqWith` and `OrderedWith` interfaces.\n\nThe `EqWith` interface is used to define the semantics of the `==` and `!=`\noperators for a given pair of types:\n\n```\ninterface EqWith(U:! type) {\n  fn Equal[self: Self](u: U) -> bool;\n  default fn NotEqual[self: Self](u: U) -> bool {\n    return not (self == u);\n  }\n}\nconstraint Eq {\n  extend EqWith(Self);\n}\n```\n\nGiven `x: T` and `y: U`:\n\n-   The expression `x == y` calls `x.(EqWith(U).Equal)(y)`.\n-   The expression `x != y` calls `x.(EqWith(U).NotEqual)(y)`.\n\n```\nclass Path {\n  private var drive: String;\n  private var path: String;\n  private fn CanonicalPath[self: Self]() -> String;\n\n  impl as Eq {\n    fn Equal[self: Self](other: Self) -> bool {\n      return (self.drive, self.CanonicalPath()) ==\n             (other.drive, other.CanonicalPath());\n    }\n  }\n}\n```\n\nThe `EqWith` overload is selected without considering possible implicit\nconversions. To permit implicit conversions in the operands of an `==` overload,\nthe\n[`like` operator](/docs/design/generics/details.md#like-operator-for-implicit-conversions)\ncan be used:\n\n```\nclass MyInt {\n  var value: i32;\n  fn Value[self: Self]() -> i32 { return self.value; }\n}\nimpl i32 as ImplicitAs(MyInt);\nimpl like MyInt as EqWith(like MyInt) {\n  fn Equal[self: Self](other: Self) -> bool {\n    return self.Value() == other.Value();\n  }\n}\nfn CompareBothWays(a: MyInt, b: i32, c: MyInt) -> bool {\n  // OK, calls above implementation three times.\n  return a == a and a != b and b == c;\n}\n```\n\nThe behavior of `NotEqual` can be overridden separately from the behavior of\n`Equal` to support cases like floating-point NaN values, where two values can\ncompare neither equal nor not-equal, and thus both functions would return\n`false`. However, an implementation of `EqWith` should _not_ allow both `Equal`\nand `NotEqual` to return `true` for the same pair of values. Additionally, these\noperations should have no observable side-effects.\n\n```\nimpl like MyFloat as EqWith(like MyFloat) {\n  fn Equal[self: MyFloat](other: MyFloat) -> bool {\n    if (self.IsNaN() or other.IsNaN()) {\n      return false;\n    }\n    return self.Representation() == other.Representation();\n  }\n  fn NotEqual[self: MyFloat](other: MyFloat) -> bool {\n    if (self.IsNaN() or other.IsNaN()) {\n      return false;\n    }\n    return self.Representation() != other.Representation();\n  }\n}\n```\n\nHeterogeneous comparisons must be defined both ways around:\n\n```\nimpl like MyInt as EqWith(like MyFloat);\nimpl like MyFloat as EqWith(like MyInt);\n```\n\n**TODO:** Add an adapter to the standard library to make it easy to define the\nreverse comparison.\n\n#### Ordering\n\nThe `OrderedWith` interface is used to define the semantics of the `<`, `<=`,\n`>`, and `>=` operators for a given pair of types.\n\n```\nchoice Ordering {\n  Less,\n  Equivalent,\n  Greater,\n  Incomparable\n}\ninterface OrderedWith(U:! type) {\n  fn Compare[self: Self](u: U) -> Ordering;\n  default fn Less[self: Self](u: U) -> bool {\n    return self.Compare(u) == Ordering.Less;\n  }\n  default fn LessOrEquivalent[self: Self](u: U) -> bool {\n    let c: Ordering = self.Compare(u);\n    return c == Ordering.Less or c == Ordering.Equivalent;\n  }\n  default fn Greater[self: Self](u: U) -> bool {\n    return self.Compare(u) == Ordering.Greater;\n  }\n  default fn GreaterOrEquivalent[self: Self](u: U) -> bool {\n    let c: Ordering = self.Compare(u);\n    return c == Ordering.Greater or c == Ordering.Equivalent;\n  }\n}\nconstraint Ordered {\n  extend OrderedWith(Self);\n}\n\n// Ordering.Less < Ordering.Equivalent < Ordering.Greater.\n// Ordering.Incomparable is incomparable with all three.\nimpl Ordering as Ordered;\n```\n\n**TODO:** Revise the above when we have a concrete design for enumerated types.\n\nGiven `x: T` and `y: U`:\n\n-   The expression `x < y` calls `x.(OrderedWith(U).Less)(y)`.\n-   The expression `x <= y` calls `x.(OrderedWith(U).LessOrEquivalent)(y)`.\n-   The expression `x > y` calls `x.(OrderedWith(U).Greater)(y)`.\n-   The expression `x >= y` calls `x.(OrderedWith(U).GreaterOrEquivalent)(y)`.\n\nFor example:\n\n```\nclass MyWidget {\n  var width: i32;\n  var height: i32;\n\n  fn Size[self: Self]() -> i32 { return self.width * self.height; }\n\n  // Widgets are normally ordered by size.\n  impl as Ordered {\n    fn Compare[self: Self](other: Self) -> Ordering {\n      return self.Size().(Ordered.Compare)(other.Size());\n    }\n  }\n}\nfn F(a: MyWidget, b: MyWidget) -> bool {\n  return a <= b;\n}\n```\n\nAs for `EqWith`, the\n[`like` operator](/docs/design/generics/details.md#like-operator-for-implicit-conversions)\ncan be used to permit implicit conversions when invoking a comparison, and\nheterogeneous comparisons must be defined both ways around:\n\n```\nfn ReverseOrdering(o: Ordering) -> Ordering {\n  return Ordering.Equivalent.(Ordered.Compare)(o);\n}\nimpl like MyInt as OrderedWith(like MyFloat);\nimpl like MyFloat as OrderedWith(like MyInt) {\n  fn Compare[self: Self](other: Self) -> Ordering {\n    return Reverse(other.(OrderedWith(Self).Compare)(self));\n  }\n}\n```\n\nThe default implementations of `Less`, `LessOrEquivalent`, `Greater`, and\n`GreaterOrEquivalent` can be overridden if a more efficient version can be\nimplemented. The behaviors of such overrides should follow those of the above\ndefault implementations, and the members of an `OrderedWith` implementation\nshould have no observable side-effects.\n\n`OrderedWith` implementations should be _transitive_. That is, given `V:! type`,\n`U:! OrderedWith(V)`, `T:! OrderedWith(U) & OrderedWith(V)`, `a: T`, `b: U`,\n`c: V`, then:\n\n-   If `a <= b` and `b <= c` then `a <= c`, and moreover if either `a < b` or\n    `b < c` then `a < c`.\n-   If `a >= b` and `b >= c` then `a >= c`, and moreover if either `a > b` or\n    `b > c` then `a > c`.\n-   If `a` and `b` are equivalent, then `a.Compare(c) == b.Compare(c)`.\n    Similarly, if `b` and `c` are equivalent, then\n    `a.Compare(b) == a.Compare(c)`.\n\n`OrderedWith` implementations should also be _consistent under reversal_. That\nis, given types `T` and `U` where `T impls OrderedWith(U)` and\n`U impls OrderedWith(T)`, and values `a: T` and `b: U`:\n\n-   If `a.(OrderedWith.Compare)(b)` is `Ordering.Greater`, then\n    `b.(OrderedWith.Compare)(a)` is `Ordering.Less`, and the other way around.\n-   Otherwise, `a.(OrderedWith.Compare)(b)` returns the same value as\n    `b.(OrderedWith.Compare)(a)`.\n\nThere is no expectation that an `Ordered` implementation be a total order, a\nweak order, or a partial order, and in particular the implementation for\nfloating-point types is none of these because NaN values do not compare less\nthan or equivalent to themselves.\n\n**TODO:** The standard library should provide a way to specify that an ordering\nis a weak, partial, or total ordering, and a way to request such an ordering in\na checked generic.\n\n#### Compatibility of equality and ordering\n\nThere is no requirement that a pair of types that implements `OrderedWith` also\nimplements `EqWith`. If a pair of types does implement both, however, the\nequality relation provided by `x.(EqWith.Equal)(y)` should be a refinement of\nthe equivalence relation provided by\n`x.(OrderedWith.Compare)(y) == Ordering.Equivalent`.\n\n#### Custom result types\n\n**TODO:** Support a lower-level extensibility mechanism that allows a result\ntype other than `bool`.\n\n### Default implementations for basic types\n\nIn addition to being defined for standard Carbon numeric types, equality and\nrelational comparisons are also defined for all \"data\" types:\n\n-   [Tuples](../tuples.md)\n-   [Struct types](../classes.md#struct-types)\n-   [Classes implementing an interface that identifies them as data classes](../classes.md#interfaces-implemented-for-data-classes)\n\nRelational comparisons for these types provide a lexicographical ordering. In\neach case, the comparison is only available if it is supported by all element\ntypes.\n\nBecause implicit conversions between data classes can reorder fields, the\nimplementations for data classes do not permit implicit conversions on their\narguments in general. Instead:\n\n-   Equality comparisons are permitted between any two data classes that have\n    the same _unordered set_ of field names, if each corresponding pair of\n    fields has an `EqWith` implementation. Fields are compared in the order they\n    appear in the left-hand operand.\n-   Relational comparisons are permitted between any two data classes that have\n    the same _ordered sequence_ of field names, if each corresponding pair of\n    fields has an `OrderedWith` implementation. Fields are compared in order.\n\nComparisons between tuples permit implicit conversions for either operand, but\nnot both.\n\n## Open questions\n\nThe `bool` type should be treated as a choice type, and so should support\nequality comparisons and relational comparisons if and only if choice types do\nin general. That decision is left to a future proposal.\n\n## Alternatives considered\n\n-   [Alternative symbols](/proposals/p0702.md#alternative-symbols)\n-   [Chained comparisons](/proposals/p0702.md#chained-comparisons-1)\n-   [Convert operands like C++](/proposals/p0702.md#convert-operands-like-c)\n-   [Provide a three-way comparison operator](/proposals/p0702.md#provide-a-three-way-comparison-operator)\n-   [Allow comparisons as the operand of `not`](/proposals/p0702.md#allow-comparisons-as-the-operand-of-not)\n-   [Rename `OrderedWith` to `ComparableWith`](/proposals/p1178.md#use-comparablewith-instead-of-orderedwith)\n\n## References\n\n-   Proposal\n    [#702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702)\n-   Proposal\n    [#1178: Rework operator interfaces](https://github.com/carbon-language/carbon-lang/pull/1178)\n-   Issue\n    [#710: Default comparison for data classes](https://github.com/carbon-language/carbon-lang/issues/710)\n"
  },
  {
    "path": "docs/design/expressions/if.md",
    "content": "# `if` expressions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Syntax](#syntax)\n-   [Semantics](#semantics)\n-   [Finding a common type](#finding-a-common-type)\n    -   [Symmetry](#symmetry)\n    -   [Same type](#same-type)\n    -   [Implicit conversions](#implicit-conversions)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nAn `if` expression is an expression of the form:\n\n> `if` _condition_ `then` _value1_ `else` _value2_\n\nThe _condition_ is converted to a `bool` value in the same way as the condition\nof an `if` statement.\n\n> **Note:** These conversions have not yet been decided.\n\nThe _value1_ and _value2_ are implicitly converted to their\n[common type](#finding-a-common-type), which is the type of the `if` expression.\n\n## Syntax\n\n`if` expressions have very low precedence, and cannot appear as the operand of\nany operator, except as the right-hand operand in an assignment. They can appear\nin other context where an expression is permitted, such as within parentheses,\nas the operand of a `return` statement, as an initializer, or in a\ncomma-separated list such as a function call.\n\nThe _value1_ and _value2_ expressions are arbitrary expressions, and can\nthemselves be `if` expressions. _value2_ extends as far to the right as\npossible. An `if` expression can be parenthesized if the intent is for _value2_\nto end earlier.\n\n```\n// OK, same as `if cond then (1 + 1) else (2 + (4 * 6))`\nvar a: i32 = if cond then 1 + 1 else 2 + 4 * 6;\n\n// OK\nvar b: i32 = (if cond then 1 + 1 else 2) + 4 * 6;\n```\n\nAn `if` keyword at the start of a statement is always interpreted as an\n[`if` statement](/docs/design/control_flow/conditionals.md), never as an `if`\nexpression, even if it is followed eventually by a `then` keyword.\n\n## Semantics\n\nThe converted _condition_ is evaluated. If it evaluates to `true`, then the\nconverted _value1_ is evaluated and its value is the result of the expression.\nOtherwise, the converted _value2_ is evaluated and its value is the result of\nthe expression.\n\n## Finding a common type\n\nThe common type of two types `T` and `U` is `(T as CommonType(U)).Result`, where\n`CommonType` is the `Carbon.CommonType` constraint. `CommonType` is notionally\ndefined as follows:\n\n```\nconstraint CommonType(U:! CommonTypeWith(Self)) {\n  extend CommonTypeWith(U) where .Result == U.Result;\n}\n```\n\nThe actual definition is a bit more complex than this, as described in\n[symmetry](#symmetry).\n\nThe interface `CommonTypeWith` is used to customize the behavior of\n`CommonType`:\n\n```\ninterface CommonTypeWith(U:! type) {\n  let Result:! type\n    where Self impls ImplicitAs(.Self) and\n          U impls ImplicitAs(.Self);\n}\n```\n\nThe implementation `A as CommonTypeWith(B)` specifies the type that `A` would\nlike to result from unifying `A` and `B` as its `Result`.\n\n_Note:_ It is required that both types implicitly convert to the common type.\nSome blanket `impl` declaractions for `CommonTypeWith` are provided as part of\nthe prelude. These are described in the following sections.\n\n_Note:_ The same mechanism is expected to eventually be used to compute common\ntypes in other circumstances.\n\n### Symmetry\n\nThe common type of `T` and `U` should always be the same as the common type of\n`U` and `T`. This is enforced in two steps:\n\n-   A `SymmetricCommonTypeWith` interface implicitly provides a\n    `B as CommonTypeWith(A)` implementation whenever one doesn't exist but an\n    `A as CommonTypeWith(B)` implementation exists.\n-   `CommonType` is defined in terms of `SymmetricCommonTypeWith`, and requires\n    that both `A as SymmetricCommonTypeWith(B)` and\n    `B as SymmetricCommonTypeWith(A)` produce the same type.\n\nThe interface `SymmetricCommonTypeWith` is an implementation detail of the\n`CommonType` constraint. It is defined and implemented as follows:\n\n```\ninterface SymmetricCommonTypeWith(U:! type) {\n  let Result:! type\n    where Self impls ImplicitAs(.Self) and\n          U impls ImplicitAs(.Self);\n}\nmatch_first {\n  impl forall [T:! type, U:! CommonTypeWith(T)]\n      T as SymmetricCommonTypeWith(U) where .Result = U.Result {}\n  impl forall [U:! type, T:! CommonTypeWith(U)]\n      T as SymmetricCommonTypeWith(U) where .Result = T.Result {}\n}\n```\n\nThe `SymmetricCommonTypeWith` interface is not exported, so users may not\ndeclare their own implementations of it, and only the two blanket `impl`\ndeclarations above are used. The `CommonType` constraint is then defined as\nfollows:\n\n```\nconstraint CommonType(U:! SymmetricCommonTypeWith(Self)) {\n  extend SymmetricCommonTypeWith(U) where .Result == U.Result;\n}\n```\n\nWhen computing the common type of `T` and `U`, if only one of the types provides\na `CommonTypeWith` implementation, that determines the common type. If both\ntypes provide a `CommonTypeWith` implementation and their `Result` types are the\nsame, that determines the common type. Otherwise, if both types provide\nimplementations but their `Result` types differ, there is no common type, and\nthe `CommonType` constraint is not met. For example, given:\n\n```\n// Implementation #1\nimpl forall [T:! type] MyX as CommonTypeWith(T) where .Result = MyX {}\n\n// Implementation #2\nimpl forall [T:! type] MyY as CommonTypeWith(T) where .Result = MyY {}\n```\n\n`MyX as CommonTypeWith(MyY)` will select #1, and `MyY as CommonTypeWith(MyX)`\nwill select #2, but the constraints on `MyX as CommonType(MyY)` will not be met\nbecause result types differ.\n\n### Same type\n\nIf `T` is the same type as `U`, the result is that type:\n\n```\nfinal impl forall [T:! type] T as CommonTypeWith(T) where .Result = T {}\n```\n\n_Note:_ This rule is intended to be considered more specialized than the other\nrules in this document.\n\nBecause this `impl` is declared `final`, `T.(CommonType(T)).Result` is always\nassumed to be `T`, even in contexts where `T` involves a symbolic binding and so\nthe result would normally be an unknown type whose facet type is `type`.\n\n```\nfn F[T:! Hashable](c: bool, x: T, y: T) -> HashCode {\n  // OK, type of `if` expression is `T`.\n  return (if c then x else y).Hash();\n}\n```\n\n### Implicit conversions\n\nIf `T` implicitly converts to `U`, the common type is `U`:\n\n```\nimpl forall [T:! type, U:! ImplicitAs(T)]\n    T as CommonTypeWith(U) where .Result = T {}\n```\n\n_Note:_ If an implicit conversion is possible in both directions, and no more\nspecific implementation exists, the constraints on `T as CommonType(U)` will not\nbe met because `(T as CommonTypeWith(U)).Result` and\n`(U as CommonTypeWith(T)).Result` will differ. In order to define a common type\nfor such a case, `CommonTypeWith` implementations in both directions must be\nprovided to override the blanket `impl` declarations in both directions:\n\n```\nimpl MyString as CommonTypeWith(YourString) where .Result = MyString {}\nimpl YourString as CommonTypeWith(MyString) where .Result = MyString {}\nvar my_string: MyString;\nvar your_string: YourString;\n// The type of `also_my_string` is `MyString`.\nvar also_my_string: auto = if cond then my_string else your_string;\n```\n\n## Alternatives considered\n\n-   [Provide no conditional expression](/proposals/p0911.md#no-conditional-expression)\n-   Use\n    [`cond ? expr1 : expr2`, like in C and C++](/proposals/p0911.md#use-c-syntax)\n    syntax\n-   Use [`if (cond) expr1 else expr2`](/proposals/p0911.md#no-then) syntax\n-   Use\n    [`if (cond) then expr1 else expr2`](/proposals/p0911.md#require-parentheses-around-the-condition)\n    syntax\n-   Allow\n    [`1 + if cond then expr1 else expr2`](/proposals/p0911.md#never-require-enclosing-parentheses)\n-   [Only require one `impl` to specify the common type if implicit conversions in both directions are possible](/proposals/p0911.md#implicit-conversions-in-both-directions)\n-   [Introduce special rules for lvalue conditionals](/proposals/p0911.md#support-lvalue-conditionals)\n\n## References\n\n-   Proposal\n    [#911: Conditional expressions](https://github.com/carbon-language/carbon-lang/pull/911).\n"
  },
  {
    "path": "docs/design/expressions/implicit_conversions.md",
    "content": "# Implicit conversions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Properties of implicit conversions](#properties-of-implicit-conversions)\n    -   [Lossless](#lossless)\n    -   [Semantics-preserving](#semantics-preserving)\n    -   [Examples](#examples)\n-   [Built-in types](#built-in-types)\n    -   [Data types](#data-types)\n    -   [Same type](#same-type)\n    -   [Pointer conversions](#pointer-conversions)\n    -   [Facet types](#facet-types)\n    -   [Struct, tuple, and array types](#struct-tuple-and-array-types)\n-   [Consistency with `as`](#consistency-with-as)\n-   [Extensibility](#extensibility)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nWhen an expression appears in a context in which an expression of a specific\ntype is expected, the expression is implicitly converted to that type if\npossible.\n\nFor [built-in types](#built-in-types), implicit conversions are permitted when:\n\n-   The conversion is [_lossless_](#lossless): every possible value for the\n    source expression converts to a distinct value in the target type.\n-   The conversion is [_semantics-preserving_](#semantics-preserving):\n    corresponding values in the source and destination type have the same\n    abstract meaning.\n\nThese rules aim to ensure that implicit conversions are unsurprising: the value\nthat is provided as the operand of an operation should match how that operation\ninterprets the value, because the identity and abstract meaning of the value are\npreserved by any implicit conversions that are applied.\n\nIt is possible for user-defined types to [extend](#extensibility) the set of\nvalid implicit conversions. Such extensions are expected to also follow these\nrules.\n\n## Properties of implicit conversions\n\n### Lossless\n\nWe expect implicit conversion to never lose information: if two values are\ndistinguishable before the conversion, they should generally be distinguishable\nafter the conversion. It should be possible to define a conversion in the\nopposite direction that restores the original value, but such a conversion is\nnot expected to be provided in general, and might be computationally expensive.\n\nBecause an implicit conversion is converting from a narrower type to a wider\ntype, implicit conversions do not necessarily preserve static information about\nthe source value.\n\n### Semantics-preserving\n\nWe expect implicit conversions to preserve the meaning of converted values. The\nassessment of this criterion will necessarily be subjective, because the\nmeanings of values generally live in the mind of the programmer rather than in\nthe program text. However, the semantic interpretation is expected to be\nconsistent from one conversion to another, so we can provide a test: if multiple\npaths of implicit conversions from a type `A` to a type `B` exist, and the same\nvalue of type `A` would convert to different values of type `B` along different\npaths, then at least one of those conversions must not be semantics-preserving.\n\nA semantics-preserving conversion does not necessarily preserve the meaning of\nparticular syntax when applied to the value. The same syntax may map to\ndifferent operations in the new type. For example, division may mean different\nthings in integer and floating-point types, and member access may find different\nmembers in a derived class pointer versus in a base class pointer.\n\n### Examples\n\nConversion from `i32` to `Vector(i32)` by forming a vector of N zeroes is\nlossless but not semantics-preserving.\n\nConversion from `i32` to `f32` by rounding to the nearest representable value is\nsemantics-preserving but not lossless.\n\nConversion from `String` to `StringView` is lossless, because we can compute the\n`String` value from the `StringView` value, and semantics-preserving because the\nstring value denoted is the same. Conversion in the other direction may or may\nnot be semantics-preserving depending on whether we consider the address to be a\nsalient part of a `StringView`'s value.\n\n## Built-in types\n\n### Data types\n\nThe following implicit numeric conversions are available:\n\n-   `iN` or `uN` -> `iM` if `M` > `N`\n-   `uN` -> `uM` if `M` > `N`\n-   `fN` -> `fM` if `M` > `N`\n-   `iN` or `uN` -> `fM` if every value of type `iN` or `uN` can be represented\n    in `fM`:\n    -   `i8` or `u8` -> `f16`\n    -   `i24` or `u24` (or smaller) -> `f32`\n    -   `i48` or `u48` (or smaller) -> `f64`\n    -   `i64` or `u64` (or smaller) -> `f80` (x86 only)\n    -   `i112` or `u112` (or smaller) -> `f128` (if available)\n    -   `i232` or `u232` (or smaller) -> `f256` (if available)\n\nIn each case, the numerical value is the same before and after the conversion.\nAn integer zero is translated into a floating-point positive zero.\n\nAn integer constant can be implicitly converted to any type `iM`, `uM`, or `fM`\nin which that value can be exactly represented. A floating-point constant can be\nimplicitly converted to any type `fM` in which that value is between the least\nrepresentable finite value and the greatest representable finite value\n(inclusive), and converts to the nearest representable finite value, with ties\nbroken by picking the value for which the mantissa is even.\n\nThe above conversions are also precisely those that C++ considers non-narrowing,\nexcept:\n\n-   Carbon also permits integer to floating-point conversions in more cases. The\n    most important of these is that Carbon permits `i32` to be implicitly\n    converted to `f64`. Lossy conversions, such as from `i32` to `f32`, are not\n    permitted.\n\n-   What Carbon considers to be an integer constant or floating-point constant\n    may differ from what C++ considers to be a constant expression.\n\n    **Note:** We have not yet decided what will qualify as a constant in this\n    context, but it will include at least integer and floating-point literals,\n    with optional enclosing parentheses. It is possible that such constants will\n    have singleton types; see issue\n    [#508](https://github.com/carbon-language/carbon-lang/issues/508).\n\nIn addition to the above rules, a negative integer constant `k` can be\nimplicitly converted to the type `uN` if the value `k` + 2<sup>N</sup> can be\nexactly represented, and converts to that value. Note that this conversion\nviolates the \"semantics-preserving\" test. For example, `(-1 as u8) as i32`\nproduces the value `255` whereas `-1 as i32` produces the value `-1`. However,\nthis conversion is important in order to allow bitwise operations with masks, so\nwe allow it:\n\n```\n// We allow ^0 == -1 to convert to `u32` to represent an all-ones value.\nvar a: u32 = ^0;\n// ^4 == -5 is negative, but we want to allow it to convert to u32 here.\nvar b: u32 = a & ^4;\n```\n\n### Same type\n\nThe following conversion is available for every type `T`:\n\n-   `T` -> `T`\n\n### Pointer conversions\n\nThe following pointer conversion is available:\n\n-   `T*` -> `U*` if `T` is a class derived from the class `U`.\n\nEven though we can convert `Derived*` to `Base*`, we cannot convert `Derived**`\nto `Base**` because that would allow storing a `Derived2*` into a `Derived*`:\n\n```\nabstract class Base {}\nclass Derived { extend base: Base; }\nclass Derived2 { extend base: Base; }\nvar d2: Derived2 = {};\nvar p: Derived*;\nvar q: Derived2* = &d2;\nvar r: Base** = &p;\n// Bad: would store q to p.\n*r = q;\n```\n\n### Facet types\n\nA type `T` with [facet type](../generics/terminology.md#facet-type) `TT1` can be\nimplicitly converted to the facet type `TT2` if `T`\n[satisfies the requirements](../generics/details.md#subtyping-between-facet-types)\nof `TT2`.\n\n### Struct, tuple, and array types\n\nSee [here](/docs/design/values.md#type-conversions).\n\n## Consistency with `as`\n\nAn implicit conversion of an expression `E` of type `T` to type `U`, when\npermitted, always has the same meaning as the\n[explicit cast expression `E as U`](as_expressions.md). Moreover, because such\nan implicit conversion is expected to exactly preserve the value,\n`(E as U) as T`, if valid, should be expected to result in the same value as\nproduced by `E` even if the `as T` cast cannot be performed as an implicit\nconversion.\n\n## Extensibility\n\nImplicit conversions can be defined for user-defined types such as\n[classes](../classes.md) by implementing the `ImplicitAs` interface, which\nextends\n[the `As` interface used to implement `as` expressions](as_expressions.md#extensibility):\n\n```\ninterface ImplicitAs(Dest:! type) {\n  extend As(Dest);\n  // Inherited from As(Dest):\n  // fn Convert[self: Self]() -> Dest;\n}\n```\n\nWhen attempting to implicitly convert an expression `x` to type `U`, the\nexpression is rewritten to `x.(ImplicitAs(U).Convert)()`.\n\nNote that implicit conversions are not transitive. Even if an\n`impl A as ImplicitAs(B)` and an `impl B as ImplicitAs(C)` are both provided, an\nexpression of type `A` cannot be implicitly converted to type `C`. Allowing\ntransitivity would introduce the risk of ambiguity issues as code evolves and\nwould in general require a search of a potentially unbounded set of intermediate\ntypes.\n\n## Alternatives considered\n\n-   [Provide lossy and non-semantics-preserving implicit conversions from C++](/proposals/p0820.md#c-conversions)\n-   [Provide no implicit conversions](/proposals/p0820.md#no-conversions)\n-   [Provide no extensibility](/proposals/p0820.md#no-extensibility)\n-   [Apply implicit conversions transitively](/proposals/p0820.md#transitivity)\n-   [Do not allow negative constants to convert to unsigned types](/proposals/p1191.md#converting-complements-to-unsigned-types)\n\n## References\n\n-   [Implicit conversions in C++](https://en.cppreference.com/w/cpp/language/implicit_conversion)\n-   Proposal\n    [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820).\n-   Proposal\n    [#866: Allow ties in floating literals](https://github.com/carbon-language/carbon-lang/pull/866).\n"
  },
  {
    "path": "docs/design/expressions/indexing.md",
    "content": "# Indexing\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [Examples](#examples)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon supports indexing using the conventional `a[i]` subscript syntax. When\n`a` is a\n[durable reference expression](/docs/design/values.md#durable-reference-expressions),\nthe result of subscripting is also a durable reference expression, but when `a`\nis a [value expression](/docs/design/values.md#value-expressions), the result\ncan be a durable reference expression or a value expression, depending on which\ninterface the type implements:\n\n-   If subscripting a value expression produces a value expression, as with an\n    array, the type should implement `IndexWith`.\n-   If subscripting a value expression produces a durable reference expression,\n    as with C++'s `std::span`, the type should implement `IndirectIndexWith`.\n\n`IndirectIndexWith` is a subtype of `IndexWith`, and subscript expressions are\nrewritten to method calls on `IndirectIndexWith` if the type is known to\nimplement that interface, or to method calls on `IndexWith` otherwise.\n\n`IndirectIndexWith` provides a final blanket `impl` of `IndexWith`, so a type\ncan implement at most one of those two interfaces.\n\nThe `Ref` methods of these interfaces, which are used to form durable reference\nexpressions on indexing, must return by `ref`.\n\n## Details\n\nA subscript expression has the form \"_lhs_ `[` _index_ `]`\". As in C++, this\nsyntax has the same precedence as `.`, `->`, and function calls, and associates\nleft-to-right with all of them.\n\nIts semantics are defined in terms of the following interfaces:\n\n```\ninterface IndexWith(SubscriptType:! type) {\n  let ElementType:! type;\n  fn At[bound self: Self](subscript: SubscriptType) -> val ElementType;\n  fn Ref[bound ref self: Self](subscript: SubscriptType) -> ref ElementType;\n}\n\ninterface IndirectIndexWith(SubscriptType:! type) {\n  require Self impls IndexWith(SubscriptType);\n  fn Ref[bound self: Self](subscript: SubscriptType) -> ref ElementType;\n}\n```\n\nA subscript expression where _lhs_ has type `T` and _index_ has type `I` is\nrewritten based on the expression category of _lhs_ and whether `T` is known to\nimplement `IndirectIndexWith(I)`:\n\n-   If `T` implements `IndirectIndexWith(I)`, the expression is rewritten to\n    \"`(` _lhs_ `).(IndirectIndexWith(I).Ref)(` _index_ `)`\".\n-   Otherwise, if _lhs_ is a\n    [_durable reference expression_](/docs/design/values.md#durable-reference-expressions),\n    the expression is rewritten to \"`(` _lhs_ `).(IndexWith(I).Ref)(` _index_\n    `)`\".\n-   Otherwise, the expression is rewritten to \"`(` _lhs_ `).(IndexWith(I).At)(`\n    _index_ `)`\".\n\n`IndirectIndexWith` provides a blanket `final impl` for `IndexWith`:\n\n```\nfinal impl forall\n    [SubscriptType:! type, T:! IndirectIndexWith(SubscriptType)]\n    T as IndexWith(SubscriptType) {\n  where ElementType = T.(IndirectIndexWith(SubscriptType).ElementType);\n  fn At[bound self: Self](subscript: SubscriptType) -> val ElementType {\n    return self.(IndirectIndexWith(SubscriptType).Ref)(index);\n  }\n  fn Ref[bound ref self: Self](subscript: SubscriptType) -> ref ElementType {\n    return self.(IndirectIndexWith(SubscriptType).Ref)(index);\n  }\n}\n```\n\nThus, a type that implements `IndirectIndexWith` need not, and cannot, provide\nits own definitions of `IndexWith.At` and `IndexWith.Ref`.\n\n### Examples\n\nAn array type could implement subscripting like so:\n\n```\nclass Array(template T:! type) {\n  impl as IndexWith(like i64) {\n    let ElementType:! type = T;\n    fn At[bound self: Self](subscript: i64) -> val T;\n    fn Ref[bound ref self: Self](subscript: i64) -> ref T;\n  }\n}\n```\n\nAnd a type such as `std::span` could look like this:\n\n```\nclass Span(T:! type) {\n  impl as IndirectIndexWith(like i64) {\n    let ElementType:! type = T;\n    fn Ref[bound ref self: Self](subscript: i64) -> ref T;\n  }\n}\n```\n\n## Alternatives considered\n\n-   [Different subscripting syntaxes](/proposals/p2274.md#different-subscripting-syntaxes)\n-   [Multiple indices](/proposals/p2274.md#multiple-indices)\n-   [Read-only subscripting](/proposals/p2274.md#read-only-subscripting)\n-   [Rvalue-only subscripting](/proposals/p2274.md#rvalue-only-subscripting)\n-   [Map-like subscripting](/proposals/p2274.md#map-like-subscripting)\n\n## References\n\n-   Proposal\n    [#2274: Subscript syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2274)\n-   Proposal\n    [#2006: Values, variables, and pointers](https://github.com/carbon-language/carbon-lang/pull/2006)\n"
  },
  {
    "path": "docs/design/expressions/literals.md",
    "content": "# Literal expressions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n> **STATUS:** Up-to-date on 2022-Dec-9.\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Numeric literals](#numeric-literals)\n    -   [Numeric literal syntax](#numeric-literal-syntax)\n    -   [Defined types](#defined-types)\n    -   [Implicit conversions](#implicit-conversions)\n    -   [Examples](#examples)\n    -   [Alternatives Considered](#alternatives-considered)\n-   [Numeric type literals](#numeric-type-literals)\n    -   [Meaning](#meaning)\n    -   [Usage](#usage)\n    -   [Alternatives considered](#alternatives-considered-1)\n-   [String literals](#string-literals)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Numeric literals\n\nNumeric Literals are defined on Wikipedia\n[here](<https://en.wikipedia.org/wiki/Literal_(computer_programming)>).\n\nIn Carbon, numeric literals have a type derived from their value. Two integer\nliterals have the same type if and only if they represent the same integer. Two\nreal number literals have the same type if and only if they represent the same\nreal number.\n\nThat is:\n\n-   For every integer, there is a type representing literals with that integer\n    value.\n-   For every rational number, there is a type representing literals with that\n    real value.\n-   The types for real numbers are distinct from the types for integers, even\n    for real numbers that represent integers. For example, `1 / 2` results in\n    `0`, due to integer arithmetic, whereas `1.0 / 2` results in `0.5`. This is\n    due to `1` having an integral type, while `1.0` has a real number type, even\n    though it represents the same numeric value.\n\nPrimitive operators are available between numeric literals, and produce values\nwith numeric literal types. For example, the type of `1 + 2` is the same as the\ntype of `3`.\n\nNumeric types can provide conversions to support initialization from numeric\nliterals. Because the value of the literal is carried in the type, a type-level\ndecision can be made as to whether the conversion is valid.\n\nThe integer types defined in the standard library permit conversion from integer\nliteral types whose values are representable in the integer type. The\nfloating-point types defined in the standard library permit conversion from\ninteger and rational literal types whose values are between the minimum and\nmaximum finite value representable in the floating-point type.\n\n### Numeric literal syntax\n\nNumeric literal syntax is covered in the\n[numeric literal lexical conventions](../lexical_conventions/numeric_literals.md)\ndoc. Both Integer and Real-Number syntax is defined, with decimal, hexadecimal\nand binary integer literals, and decimal and hexadecimal real number literals.\n\n### Defined types\n\nThe following types are defined in the Carbon prelude:\n\n-   `Core.BigInt`, an arbitrary-precision integer type;\n-   `Core.Rational(T:! type)`, a rational type, parameterized by a type used for\n    its numerator and denominator -- the exact constraints on `T` are not yet\n    decided;\n-   `Core.IntLiteral(N:! Core.BigInt)`, a type representing integer literals;\n    and\n-   `Core.FloatLiteral(X:! Core.Rational(Core.BigInt))`, a type representing\n    floating-point literals.\n\nAll of these types are usable during compilation. `Core.BigInt` supports the\nsame operations as [`Core.Int(N)`](#meaning). `Core.Rational(T)` supports the\nsame operations as [`Core.Float(N)`](#meaning).\n\nThe types `Core.IntLiteral(N)` and `Core.FloatLiteral(X)` also support primitive\ninteger and floating-point operations such as arithmetic and comparison, but\nthese operations are typically heterogeneous: for example, an addition between\n`Core.IntLiteral(N)` and `Core.IntLiteral(M)` produces a value of type\n`Core.IntLiteral(N + M)`.\n\n### Implicit conversions\n\n`Core.IntLiteral(N)` converts to any sufficiently large integer type, as if by:\n\n```\nimpl forall [template N:! Core.BigInt, template M:! Core.BigInt]\n    Core.IntLiteral(N) as ImplicitAs(Core.Int(M))\n    if N >= Core.Int(M).MinValue as Core.BigInt\n    and N <= Core.Int(M).MaxValue as Core.BigInt {\n  ...\n}\nimpl forall [template N:! Core.BigInt, template M:! Core.BigInt]\n    Core.IntLiteral(N) as ImplicitAs(Core.UInt(M))\n    if N >= Core.UInt(M).MinValue as Core.BigInt\n    and N <= Core.UInt(M).MaxValue as Core.BigInt {\n  ...\n}\n```\n\nThe above is for exposition purposes only; various parts of this syntax are not\nyet decided.\n\nSimilarly, `Core.IntLiteral(X)` and `Core.FloatLiteral(X)` convert to any\nsufficiently large floating-point type, and produce the nearest representable\nfloating-point value.\n\nConversions in which `X` lies exactly half-way between two values are rounded to\nthe value in which the mantissa is even, as defined in the IEEE 754 standard and\nas was decided in\n[proposal #866](https://github.com/carbon-language/carbon-lang/pull/866).\n\nConversions in which `X` is outside the range of finite values of the\nfloating-point type are rejected rather than saturating to the finite range or\nproducing an infinity.\n\n### Examples\n\n```carbon\n// This is OK: the initializer is of the integer literal type with value\n// -2147483648 despite being written as a unary `-` applied to a literal.\nvar x: i32 = -2147483648;\n\n// This initializes y to 2^60.\nvar y: i64 = 1 << 60;\n\n// This forms a rational literal whose value is one third, and converts it to\n// the nearest representable value of type `f64`.\nvar z: f64 = 1.0 / 3.0;\n\n// This is an error: 300 cannot be represented in type `i8`.\nvar c: i8 = 300;\n\nfn F[template T:! type](v: T) {\n  var x: i32 = v * 2;\n}\n\n// OK: x = 2_000_000_000.\nF(1_000_000_000);\n\n// Error: 4_000_000_000 can't be represented in type `i32`.\nF(2_000_000_000);\n\n// No storage required for the bound when it's of integer literal type.\nstruct Span(template T:! type, template BoundT:! type) {\n  var begin: T*;\n  var bound: BoundT;\n}\n\n// Returns 1, because 1.3 can implicitly convert to f32, even though conversion\n// to f64 might be a more exact match.\nfn G() -> i32 {\n  match (1.3) {\n    case _: f32 => { return 1; }\n    case _: f64 => { return 2; }\n  }\n}\n\n// Can only be called with a literal 0.\nfn PassMeZero(_: Core.IntLiteral(0));\n\n// Can only be called with integer literals in the given range.\nfn ConvertToByte[template N:! Core.BigInt](_: Core.IntLiteral(N)) -> i8\n    if N >= -128 and N <= 127 {\n  return N as i8;\n}\n\n// Given any int literal, produces a literal whose value is one higher.\nfn OneHigher(L: Core.IntLiteral(template _:! Core.BigInt)) -> auto {\n  return L + 1;\n}\n// Error: 256 can't be represented in type `i8`.\nvar v: i8 = OneHigher(255);\n```\n\n### Alternatives Considered\n\n-   [Use an ordinary integer or floating-point type for literals](/proposals/p0144.md#use-an-ordinary-integer-or-floating-point-type-for-literals)\n-   [Use same type for all literals](/proposals/p0144.md#use-same-type-for-all-literals)\n-   [Allow leading `-` in literal tokens](/proposals/p0144.md#allow-leading---in-literal-tokens)\n-   [Forbidding floating-point ties](/proposals/p0866.md#alternatives-considered)\n\n## Numeric type literals\n\nCarbon has a simple keyword-like syntax of `iN`, `uN`, and `fN` for two's\ncomplement signed integers, unsigned integers, and\n[IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) floating-point numbers,\nrespectively. Here, `N` can be a positive multiple of 8, including the common\npower-of-two sizes (for example, `N = 8, 16, 32`).\n\nExamples of this syntax include:\n\n-   `i16` - A 16-bit two's complement signed integer type\n-   `u32` - A 32-bit unsigned integer type\n-   `f64` - A 64-bit IEEE-754 binary floating-point number type\n\n### Meaning\n\nThese type literals are aliases for parameterized types defined in the `Core`\npackage that is automatically imported by the prelude:\n\n-   `iN` is an alias for `Core.Int(N)`\n-   `uN` is an alias for `Core.UInt(N)`\n-   `fN` is an alias for `Core.Float(N)`\n\n### Usage\n\n```carbon\npackage sample;\n\nfn Sum(x: i32, y: i32) -> i32 {\n  return x + y;\n}\n\nfn Run() -> i32 {\n  return Sum(4, 2);\n}\n```\n\nIn the above example, `Sum` has parameters `x` and `y`, each of which is typed\nas a 32-bit two's complement signed integer. `Main` then returns the output of\n`Sum` as a 32-bit two's complement signed integer.\n\n### Alternatives considered\n\n-   [C++ LP64 convention](/proposals/p2015.md#c-lp64-convention)\n-   [Type name with length suffix](/proposals/p2015.md#type-name-with-length-suffix)\n-   [Uppercase suffixes](/proposals/p2015.md#uppercase-suffixes)\n-   [Additional bit sizes](/proposals/p2015.md#additional-bit-sizes)\n\n## String literals\n\nString literal syntax is covered in the\n[string literal lexical conventions](../lexical_conventions/string_literals.md).\n\nNo design for string types has been through the proposal process yet.\n\n## References\n\n-   Proposal\n    [#143: Numeric literals](https://github.com/carbon-language/carbon-lang/pull/143)\n-   Proposal\n    [#144: Numeric literal semantics](https://github.com/carbon-language/carbon-lang/pull/144)\n-   Question-for-leads issue\n    [#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543)\n-   Proposal\n    [#866: Allow ties in floating literals](https://github.com/carbon-language/carbon-lang/pull/866)\n-   Proposal\n    [#2015: Numeric type literal syntax](https://github.com/carbon-language/carbon-lang/pull/2015)\n-   Question-for-leads issue\n    [#2113: Structure, scope, and naming of the prelude and syntax aliases](https://github.com/carbon-language/carbon-lang/issues/2113)\n"
  },
  {
    "path": "docs/design/expressions/logical_operators.md",
    "content": "# Logical operators\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [Precedence](#precedence)\n    -   [Associativity](#associativity)\n    -   [Conversions](#conversions)\n    -   [Overloading](#overloading)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon provides three operators to support logical operations on `bool` values:\n\n-   `and` provides a logical AND operation.\n    -   `x and y` evaluates to `true` if both operands are `true`.\n-   `or` provides a logical OR operation.\n    -   `x or y` evaluates to `true` if either operand is `true`.\n-   `not` provides a logical NOT operation.\n    -   `not x` evaluates to `true` if the operand is `false`.\n\n`and` and `or` are infix binary operators, and use\n[short-circuit evaluation](https://en.wikipedia.org/wiki/Short-circuit_evaluation).\n`not` is a prefix unary operator.\n\n## Details\n\n### Precedence\n\n`and` and `or` have very low precedence. When an expression appearing as the\ncondition of an `if` uses these operators unparenthesized, they are always the\nlowest precedence operators in that expression.\n\nThese operators permit any reasonable operator that might be used to form a\n`bool` value as a subexpression. In particular, comparison operators such as `<`\nand `==` have higher precedence than `and` and `or`. However, the precedence of\n`and` and `or` is not directly comparable with each other, so they cannot both\nbe used directly in an expression without parentheses.\n\n`not` is higher precedence than `and` and `or`, but its precedence is\nincomparable with most other operators, including comparison operators.\n\nFor example:\n\n```carbon\n// ✅ Valid: `and` is lower precedence than the `<` or `==` operators.\nif (n + m == 3 and not n < m) {\n  ...\n}\n// The above is equivalent to:\nif (((n + m) == 3) and (not (n < m))) {\n  ...\n}\n\n// ❌ Invalid: `and` and `or` precedence is incomparable.\nif (cond1 and cond2 or cond3) {\n  ...\n}\n// ✅ Valid: Parentheses avoid the precedence check.\nif (cond1 and (cond2 or cond3)) {\n  ...\n}\n\n// ❌  Invalid: `not` precedence is incomparable with `==`.\nif (not cond1 == cond2) {\n  ...\n}\n// ❌  Invalid: `not` precedence is incomparable with `==`.\nif (cond1 == not cond2) {\n  ...\n}\n// ✅ Valid: Parentheses avoid the precedence check.\nif (cond1 == (not cond2)) {\n  ...\n}\n```\n\n### Associativity\n\n`and` and `or` are left-associative. A `not` expression cannot be the operand of\nanother `not` expression; `not not b` is an error without parentheses.\n\n```\n// ✅ Valid: `and` is left-associative, and precedence is fine.\nif (not a and not b and not c) {\n  ...\n}\n// The above is equivalent to:\nif ((not a) and ((not b) and (not c))) {\n  ...\n}\n// ✅ Valid: Parentheses avoid the `not` associativity error.\nif (not (not a)) {\n  ...\n}\n\n// ❌ Invalid: `not not` associativity requires parentheses.\nif (not not a) {\n  ...\n}\n```\n\n### Conversions\n\n> TODO: This should be addressed through a standard `bool` conversion design.\n\nThe operand of `and`, `or`, or `not` is converted to a `bool` value in the same\nway as the condition of an `if` statement. In particular:\n\n-   If we decide that certain values, such as pointers or integers, should not\n    be usable as the condition of an `if` without an explicit comparison against\n    null or zero, then those values will also not be usable as the operand of\n    `and`, `or`, or `not` without an explicit comparison.\n-   If an extension point is provided to determine how to branch on the truth of\n    a value in an `if` (such as by supplying a conversion to a `bool` type),\n    that extension point will also apply to `and`, `or`, and `not`.\n\n### Overloading\n\nThe logical operators `and`, `or`, and `not` are not overloadable. As noted\nabove, any mechanism that allows types to customize how `if` treats them will\nalso customize how `and`, `or`, and `not` treats them.\n\n## Alternatives considered\n\n-   [Use punctuation spelling for all three operators](/proposals/p0680.md#use-punctuation-spelling-for-all-three-operators)\n-   [Precedence of AND versus OR](/proposals/p0680.md#precedence-of-and-versus-or)\n-   [Precedence of NOT](/proposals/p0680.md#precedence-of-not)\n-   [Punctuation form of NOT](/proposals/p0680.md#punctuation-form-of-not)\n-   [Two forms of NOT](/proposals/p0680.md#two-forms-of-not)\n-   [Repeated NOT](/proposals/p0680.md#repeated-not)\n-   [AND and OR produce the decisive value](/proposals/p0680.md#and-and-or-produce-the-decisive-value)\n\n## References\n\n-   Proposal\n    [#680: And, or, not](https://github.com/carbon-language/carbon-lang/pull/680).\n-   Proposal\n    [#702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702).\n"
  },
  {
    "path": "docs/design/expressions/member_access.md",
    "content": "# Qualified names and member access\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Member resolution](#member-resolution)\n    -   [Package and namespace members](#package-and-namespace-members)\n    -   [Types, forms, and facets](#types-forms-and-facets)\n    -   [Tuple indexing](#tuple-indexing)\n    -   [Values](#values)\n    -   [Facet binding](#facet-binding)\n        -   [Compile-time bindings](#compile-time-bindings)\n        -   [Lookup ambiguity](#lookup-ambiguity)\n-   [`impl` lookup](#impl-lookup)\n    -   [`impl` lookup for simple member access](#impl-lookup-for-simple-member-access)\n    -   [`impl` lookup for compound member access](#impl-lookup-for-compound-member-access)\n-   [Instance binding](#instance-binding)\n-   [Non-instance members](#non-instance-members)\n-   [Non-vacuous member access restriction](#non-vacuous-member-access-restriction)\n-   [Precedence and associativity](#precedence-and-associativity)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\n> **TODO:** [p3720: Member binding operators](/proposals/p3720.md) introduces an\n> additional \"member binding\" step, redefines simple member access in terms of\n> compound member access, and defines compound member access in terms of calls\n> to user-implementable interface methods. This document must be updated to\n> reflect those changes.\n\nA _qualified name_ is a [word](../lexical_conventions/words.md) that is preceded\nby a period or a rightward arrow. The name is found within a contextually\ndetermined entity:\n\n-   In a member access expression, this is the entity preceding the period.\n-   In a pointer member access expression, this is the entity pointed to by the\n    pointer preceding the rightward arrow.\n-   For a designator in a struct literal, the name is introduced as a member of\n    the struct type.\n\nA _member access expression_ allows a member of a value, type, interface,\nnamespace, and so on to be accessed by specifying a qualified name for the\nmember.\n\nA member access expression is either a _simple_ member access expression of the\nform:\n\n-   _member-access-expression_ ::= _expression_ `.` _word_\n-   _member-access-expression_ ::= _expression_ `->` _word_\n-   _member-access-expression_ ::= _expression_ `.` _integer-literal_\n-   _member-access-expression_ ::= _expression_ `->` _integer-literal_\n\nor a _compound_ member access of the form:\n\n-   _member-access-expression_ ::= _expression_ `.` `(` _expression_ `)`\n-   _member-access-expression_ ::= _expression_ `->` `(` _expression_ `)`\n\nThe _member name_ is the _word_, _integer-literal_, or the constant value of the\nparenthesized _expression_ in the member access expression. Compound member\naccesses allow specifying a qualified member name.\n\nFor example:\n\n```carbon\nnamespace Widgets;\n\ninterface Widgets.Widget {\n  fn Grow[ref self: Self](factor: f64);\n}\n\nclass Widgets.Cog {\n  var size: i32;\n  fn Make(size: i32) -> Self;\n  extend impl as Widgets.Widget;\n}\n\nfn Widgets.GrowSomeCogs() {\n  var cog1: Cog = Cog.Make(1);\n  var cog2: Cog = cog1.Make(2);\n  var cog_pointer: Cog* = &cog2;\n  let cog1_size: i32 = cog1.size;\n  cog1.Grow(1.5);\n  cog2.(Cog.Grow)(cog1_size as f64);\n  cog1.(Widget.Grow)(1.1);\n  cog2.(Widgets.Cog.(Widgets.Widget.Grow))(1.9);\n  cog_pointer->Grow(0.75);\n  cog_pointer->(Widget.Grow)(1.2);\n}\n```\n\nPointer member access expressions are those using a `->` instead of a `.` and\ntheir semantics are exactly what would result from first dereferencing the\nexpression preceding the `->` and then forming a member access expression using\na `.`. For example, a simple pointer member access expression _expression_ `->`\n_word_ becomes `(` `*` _expression_ `)` `.` _word_. More details on this syntax\nand semantics can be found in the [pointers](/docs/design/values.md#pointers)\ndesign. The rest of this document describes the semantics using `.` alone for\nsimplicity.\n\nA member access expression is processed using the following steps:\n\n-   First, the member name to the right of the `.` is\n    [resolved](#member-resolution) to a specific member entity, called `M` in\n    this document.\n-   Then, if necessary, [`impl` lookup](#impl-lookup) is performed to map from a\n    member of an interface to a member of the relevant `impl`, potentially\n    updating `M`.\n-   Then, if necessary, [instance binding](#instance-binding) is performed to\n    locate the member subobject corresponding to a field name or to build a\n    bound method object, producing the result of the member access expression.\n-   If [instance binding is not performed](#non-instance-members), the result is\n    `M`.\n\n## Member resolution\n\nThe process of _member resolution_ determines which member `M` a member access\nexpression is referring to.\n\nFor a simple member access, if the first operand is a type, form, facet,\npackage, or namespace, a search for the member name is performed in the first\noperand. Otherwise, a search for the member name is performed in the type of the\nfirst operand. In either case, the search must succeed. In the latter case, if\nthe result is an instance member, then [instance binding](#instance-binding) is\nperformed on the first operand.\n\nA search for a name within a form searches for the name in its\n[type component](/docs/design/values.md#expression-forms). Note that this means\nthat the form of an expression never affects simple member access into that\nexpression, except through its type component.\n\nFor a compound member access, the second operand is evaluated as a compile-time\nconstant to determine the member being accessed. The evaluation is required to\nsucceed and to result in a member of a type, interface, or non-type facet, or a\nvalue of an integer or integer literal type. If the result is an instance\nmember, then [instance binding](#instance-binding) is always performed on the\nfirst operand.\n\n### Package and namespace members\n\nIf the first operand is a package or namespace name, the expression must be a\nsimple member access expression. The member name must be a _word_ that names a\nmember of that package or namespace, and the result is the package or namespace\nmember with that name.\n\nAn expression that names a package or namespace can only be used as the first\noperand of a member access or as the target of an `alias` declaration.\n\n```\nnamespace MyNamespace;\nfn MyNamespace.MyFunction() {}\n\n// ✅ OK, can alias a namespace.\nalias MyNS = MyNamespace;\nfn CallMyFunction() { MyNS.MyFunction(); }\n\n// ❌ Error: a namespace is not a value.\nlet MyNS2:! auto = MyNamespace;\n\nfn CallMyFunction2() {\n  // ❌ Error: cannot perform compound member access into a namespace.\n  MyNamespace.(MyNamespace.MyFunction)();\n}\n```\n\nThe first operand may also be the keyword `package`, as in `package.Foo`, to\nname the `Foo` member of the current package. This can be used to disambiguate\nbetween different `Foo` definitions, as in:\n\n```carbon\n// This defines `package.Foo`\nclass Foo {}\nclass Bar {\n  // This defines `Bar.Foo`, or equivalently `package.Bar.Foo`.\n  class Foo {}\n  fn F() {\n    // ✅ OK, `x` has type `Foo` from the outer scope.\n    var x: package.Foo = {};\n\n    // ❌ Error: ambiguous;\n    // `Foo` could mean `package.Foo` or `Bar.Foo`.\n    var y: Foo = {};\n  }\n}\n```\n\n### Types, forms, and facets\n\nIf the first operand is a type, form, or facet, it must be a compile-time\nconstant. This disallows member access into a type except during compile-time,\nsee leads issue\n[#1293](https://github.com/carbon-language/carbon-lang/issues/1293).\n\nLike the previous case, types (including\n[facet types](/docs/design/generics/terminology.md#facet-type)) have member\nnames, and lookup searches those names. For example:\n\n-   `i32.Least` finds the member constant `Least` of the type `i32`.\n-   `Add.Op` finds the member function `Op` of the interface `Add`. Because a\n    facet type is a type, this is a special case of the previous bullet.\n\nUnlike the previous case, both simple and compound member access is allowed.\n\nNon-type facets, such as `T as Cowboy`, also have members. Specifically, the\nmembers of the `impl` or `impl`s that form the implementation of `T as Cowboy`.\nBeing part of the `impl` rather than the interface, no further\n[`impl` lookup](#impl-lookup) is needed.\n\n```carbon\ninterface Cowboy {\n  fn Draw[self: Self]();\n}\n\ninterface Renderable {\n  fn Draw[self: Self]();\n}\n\nclass Avatar {\n  extend impl Avatar as Cowboy;\n  extend impl Avatar as Renderable;\n}\n```\n\nSimple member access `(Avatar as Cowboy).Draw` finds the `Cowboy.Draw`\nimplementation for `Avatar`, ignoring `Renderable.Draw`.\n\nSimilarly, a form has members, specifically the members of the form's type\ncomponent.\n\n### Tuple indexing\n\nTuple types have member names that are *integer-literal*s, not *word*s.\n\nEach positional element of a tuple is considered to have a name that is the\ncorresponding decimal integer: `0`, `1`, and so on. The spelling of the\n_integer-literal_ is required to exactly match one of those names, and the\nresult of member resolution is an instance member that refers to the\ncorresponding element of the tuple.\n\n```\n// ✅ `a == 42`.\nlet a: i32 = (41, 42, 43).1;\n// ❌ Error: no tuple element named `0x1`.\nlet b: i32 = (1, 2, 3).0x1;\n// ❌ Error: no tuple element named `2`.\nlet c: i32 = (1, 2).2;\n\nvar t: (i32, i32, i32) = (1, 2, 3);\nlet p: (i32, i32, i32)* = &t;\n// ✅ `m == 3`.\nlet m: i32 = p->2;\n```\n\nIn a compound member access whose second operand is of integer or integer\nliteral type, the first operand is required to be of tuple type or to extend a\ntuple type, otherwise member resolution fails. The second operand is required to\nbe a non-negative template constant that is less than the number of tuple\nelements, and the result is an instance member that refers to the corresponding\npositional element of the tuple.\n\n```\n// ✅ `d == 43`.\nlet d: i32 = (41, 42, 43).(1 + 1);\n// ✅ `e == 2`.\nlet template e:! i32 = (1, 2, 3).(0x1);\n// ❌ Error: no tuple element with index 4.\nlet f: i32 = (1, 2).(2 * 2);\n\n// ✅ `n == 3`.\nlet n: i32 = p->(e);\n```\n\n### Values\n\nIf the first operand is not a type, form, package, namespace, or facet, it does\nnot have member names, and a search is performed into the type of the first\noperand instead.\n\n```carbon\ninterface Printable {\n  fn Print[self: Self]();\n}\n\nimpl i32 as Printable;\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  // Extending impl injects the name `Print` into\n  // class `Point`.\n  extend impl as Printable;\n}\n\nfn PrintPointTwice() {\n  var p: Point = {.x = 0, .y = 0};\n\n  // ✅ OK, `x` found in type of `p`, namely `Point`.\n  p.x = 1;\n  // ✅ OK, `y` found in the type `Point`.\n  p.(Point.y) = 1;\n\n  // ✅ OK, `Print` found in type of `p`, namely `Point`.\n  p.Print();\n  // ✅ OK, `Print` found in the type `Printable`, and\n  // `Printable.Print` found in the type of `p`.\n  p.(Printable.Print)();\n}\n```\n\n### Facet binding\n\nA search for members of a facet binding `T:! C` treats the facet binding as an\n[archetype](/docs/design/generics/terminology.md#archetype), and finds members\nof the facet `T` of facet type `C`.\n\nFor example:\n\n```\ninterface Printable {\n  fn Print[self: Self]();\n}\n\nfn GenericPrint[T:! Printable](a: T) {\n  // ✅ OK, type of `a` is the facet binding `T`;\n  // `Print` found in the facet `T as Printable`.\n  a.Print();\n}\n```\n\n**Note:** If lookup is performed into a type that involves a template binding,\nthe lookup will be performed both in the context of the template definition and\nin the context of the template instantiation, as described in\n[the \"compile-time bindings\" section](#compile-time-bindings). The results of\nthese lookups are [combined](#lookup-ambiguity).\n\n#### Compile-time bindings\n\nIf the value or type of the first operand depends on a checked or template\ngeneric parameter, or in fact any\n[compile-time binding](/docs/design/generics/terminology.md#bindings), the\nlookup is performed from a context where the value of that binding is unknown.\nEvaluation of an expression involving the binding may still succeed, but will\nresult in a symbolic constant involving that binding.\n\n```carbon\nclass GenericWrapper(T:! type) {\n  var field: T;\n}\nfn F[T:! type](x: GenericWrapper(T)) -> T {\n  // ✅ OK, finds `GenericWrapper(T).field`.\n  return x.field;\n}\n\ninterface Renderable {\n  fn Draw[self: Self]();\n}\nfn DrawChecked[T:! Renderable](c: T) {\n  // `Draw` resolves to `(T as Renderable).Draw` or\n  // `T.(Renderable.Draw)`.\n  c.Draw();\n}\n\nclass Cowboy { fn Draw[self: Self](); }\nimpl Cowboy as Renderable { fn Draw[self: Self](); }\n\nfn CallsDrawChecked(c: Cowboy) {\n  // ✅ Calls member of `impl Cowboy as Renderable`.\n  DrawChecked(c);\n  // In contrast to this which calls member of `Cowboy`:\n  c.Draw();\n}\n```\n\nIf the value or type depends on any template bindings, the lookup is redone from\na context where the values of those bindings are known, but where the values of\nany symbolic bindings are still unknown. The lookup results from these two\ncontexts are [combined](#lookup-ambiguity).\n\n```carbon\nfn DrawTemplate[template T:! type](c: T) {\n  // `Draw` not found in `type`, looked up in the\n  // actual deduced value of `T`.\n  c.Draw();\n}\n\nfn CallsDrawTemplate(c: Cowboy) {\n  // ✅ Calls member of `Cowboy`:\n  DrawTemplate(c);\n  // Same behavior as:\n  c.Draw();\n}\n```\n\nSince we have decided to forbid specialization of class templates, see\n[proposal #2200: Template generics](https://github.com/carbon-language/carbon-lang/pull/2200),\nthe compiler can assume the body of a templated class will be the same for all\nargument values:\n\n```carbon\nclass TemplateWrapper(template T:! type) {\n  var field: T;\n}\nfn G[template T:! type](x: TemplateWrapper(T)) -> T {\n  // ✅ Allowed, finds `TemplateWrapper(T).field`.\n  return x.field;\n}\n```\n\nIn addition, the lookup will be performed again when `T` is known. This allows\ncases where the lookup only succeeds for specific values of `T`:\n\n```carbon\nclass HasField {\n  var field: i32;\n}\nclass DerivingWrapper(template T:! type) {\n  extend base: T;\n}\nfn H[template T:! type](x: DerivingWrapper(T)) -> i32 {\n  // ✅ Allowed, but no name `field` found in template\n  // definition of `DerivingWrapper`.\n  return x.field;\n}\nfn CallH(a: DerivingWrapper(HasField),\n         b: DerivingWrapper(i32)) {\n  // ✅ Member `field` in base class found in instantiation.\n  var x: i32 = H(a);\n  // ❌ Error, no member `field` in type of `b`.\n  var y: i32 = H(b);\n}\n```\n\n**Note:** All lookups are done from a context where the values of any symbolic\nbindings that are in scope are unknown. Unlike for a template binding, the\nactual value of a symbolic binding never affects the result of member\nresolution.\n\n#### Lookup ambiguity\n\nMultiple lookups can be performed when resolving a member access expression with\na [template binding](#compile-time-bindings). We resolve this the same way as\nwhen looking in multiple interfaces that are\n[combined with `&`](/docs/design/generics/details.md#combining-interfaces-by-anding-facet-types):\n\n-   If more than one distinct member is found, after performing\n    [`impl` lookup](#impl-lookup) if necessary, the lookup is ambiguous, and the\n    program is invalid.\n-   If no members are found, the program is invalid.\n-   Otherwise, the result of combining the lookup results is the unique member\n    that was found.\n\n```carbon\ninterface Renderable {\n  fn Draw[self: Self]();\n}\n\nfn DrawTemplate2[template T:! Renderable](c: T) {\n  // Member lookup finds `(T as Renderable).Draw` and the\n  // `Draw` member of the actual deduced value of `T`, if any.\n  c.Draw();\n}\n\nclass Cowboy { fn Draw[self: Self](); }\nimpl Cowboy as Renderable { fn Draw[self: Self](); }\n\nclass Pig { }\nimpl Pig as Renderable {\n  fn Draw[self: Self]();\n}\n\nclass RoundWidget {\n  impl as Renderable {\n    fn Draw[self: Self]();\n  }\n  alias Draw = Renderable.Draw;\n}\n\nclass SquareWidget {\n  fn Draw[self: Self]() {}\n  impl as Renderable {\n    alias Draw = Self.Draw;\n  }\n}\n\nfn FlyTemplate[template T:! type](c: T) {\n  c.Fly();\n}\n\nfn Draw(c: Cowboy, p: Pig, r: RoundWidget, s: SquareWidget) {\n  // ❌ Error: ambiguous. `Cowboy.Draw` and\n  // `(Cowboy as Renderable).Draw` are different.\n  DrawTemplate2(c);\n\n  // ✅ OK, lookup in type `Pig` finds nothing, so uses\n  // lookup in facet type `Pig as Renderable`.\n  DrawTemplate2(p);\n\n  // ✅ OK, lookup in type `RoundWidget` and lookup in facet\n  // type `RoundWidget as Renderable` find the same entity.\n  DrawTemplate2(r);\n\n  // ✅ OK, lookup in type `SquareWidget` and lookup in facet\n  // type `SquareWidget as Renderable` find the same entity.\n  DrawTemplate2(s);\n\n  // ❌ Error: `Fly` method not found in `Pig` or\n  // `Pig as type`.\n  FlyTemplate(p);\n}\n```\n\n## `impl` lookup\n\n`impl` lookup maps a member of an interface to the corresponding member of the\nrelevant `impl`. It is performed when member access names an interface member,\nexcept when the member was found by a search of a facet type scope in a simple\nmember access expression.\n\n### `impl` lookup for simple member access\n\nFor a simple member access `a.b` where `b` names a member of an interface `I`:\n\n-   If the interface member was found by searching a\n    non-[facet-type](/docs/design/generics/terminology.md#facet-type) scope `T`,\n    for example a class or an adapter, then `impl` lookup is performed for\n    `T as I`.\n    -   In the case where the member was found in a base class of the class that\n        was searched, `T` is the derived class that was searched, not the base\n        class in which the name was declared.\n    -   More generally, if the member was found in something the type extends,\n        such as a facet type or mixin, `T` is the type that was initially\n        searched, not what it extended.\n-   Otherwise, `impl` lookup is not performed.\n\nThe appropriate `impl T as I` implementation is located. The program is invalid\nif no such `impl` exists. When `T` or `I` depends on a symbolic binding, a\nsuitable constraint must be specified to ensure that such an `impl` will exist.\nWhen `T` or `I` depends on a template binding, this check is deferred until the\nvalue for the template binding is known.\n\n`M` is replaced by the member of the `impl` that corresponds to `M`.\n\n[Instance binding](#instance-binding) may also apply if the member is an\ninstance member.\n\nFor example:\n\n```carbon\ninterface Addable {\n  // #1\n  fn Add[self: Self](other: Self) -> Self;\n  // #2\n  default fn Sum[Seq:! Iterable where .ValueType = Self](seq: Seq) -> Self {\n    // ...\n  }\n  alias AliasForSum = Sum;\n}\n\nclass Integer {\n  extend impl as Addable {\n    // #3\n    fn Add[self: Self](other: Self) -> Self;\n    // #4, generated from default implementation for #2.\n    // fn Sum[...](...);\n  }\n\n  alias AliasForAdd = Addable.Add;\n}\n```\n\n-   For `Integer.Sum`, member resolution resolves the name `Sum` to \\#2, which\n    is not an instance member. `impl` lookup then locates the\n    `impl Integer as Addable`, and determines that the member access refers to\n    \\#4.\n-   For `i.Add(j)` where `i: Integer`, member resolution resolves the name `Add`\n    to \\#1, which is an instance member. `impl` lookup then locates the\n    `impl Integer as Addable`, and determines that the member access refers to\n    \\#3. Finally, instance binding will be performed as described later.\n-   `Integer.AliasForAdd` finds \\#3, the `Add` member of the facet type\n    `Integer as Addable`, not \\#1, the interface member `Addable.Add`.\n-   `i.AliasForAdd`, with `i: Integer`, finds \\#3, the `Add` member of the facet\n    type `Integer as Addable`, and performs\n    [instance binding](#instance-binding) since the member is an instance\n    member.\n-   `Addable.AliasForSum` finds \\#2, the member in the interface `Addable`, and\n    does not perform `impl` lookup.\n\n**Note:** When an interface member is added to a class by an alias, `impl`\nlookup is not performed as part of handling the alias, but will happen when\nnaming the interface member as a member of the class.\n\n```carbon\ninterface Renderable {\n  // #5\n  fn Draw[self: Self]();\n}\n\nclass RoundWidget {\n  impl as Renderable {\n    // #6\n    fn Draw[self: Self]();\n  }\n  // `Draw` names #5, the member of the `Renderable` interface.\n  alias Draw = Renderable.Draw;\n}\n\nclass SquareWidget {\n  // #7\n  fn Draw[self: Self]() {}\n  impl as Renderable {\n    alias Draw = Self.Draw;\n  }\n}\n\nfn DrawWidget(r: RoundWidget, s: SquareWidget) {\n  // ✅ OK: In the inner member access, the name `Draw` resolves to the\n  // member `Draw` of `Renderable`, #5, which `impl` lookup replaces with\n  // the member `Draw` of `impl RoundWidget as Renderable`, #6.\n  // The outer member access then forms a bound member function that\n  // calls #6 on `r`, as described in \"Instance binding\".\n  r.(RoundWidget.Draw)();\n\n  // ✅ OK: In the inner member access, the name `Draw` resolves to the\n  // member `Draw` of `SquareWidget`, #7.\n  // The outer member access then forms a bound member function that\n  // calls #7 on `s`.\n  s.(SquareWidget.Draw)();\n\n  // ❌ Error: In the inner member access, the name `Draw` resolves to the\n  // member `Draw` of `SquareWidget`, #7.\n  // The outer member access fails because we can't call\n  // #7, `Draw[self: SquareWidget]()`, on a `RoundWidget` object `r`.\n  r.(SquareWidget.Draw)();\n\n  // ❌ Error: In the inner member access, the name `Draw` resolves to the\n  // member `Draw` of `Renderable`, #5, which `impl` lookup replaces with\n  // the member `Draw` of `impl RoundWidget as Renderable`, #6.\n  // The outer member access fails because we can't call\n  // #6, `Draw[self: RoundWidget]()`, on a `SquareWidget` object `s`.\n  s.(RoundWidget.Draw)();\n}\n\nbase class WidgetBase {\n  // ✅ OK, even though `WidgetBase` does not implement `Renderable`.\n  alias Draw = Renderable.Draw;\n\n  fn DrawAll[T:! Renderable](v: Vector(T)) {\n    for (var w: T in v) {\n      // ✅ OK. Unqualified lookup for `Draw` finds alias `WidgetBase.Draw`\n      // to `Renderable.Draw`, which does not perform `impl` lookup yet.\n      // Then the compound member access expression performs `impl` lookup\n      // into `impl T as Renderable`, since `T` is known to implement\n      // `Renderable`. Finally, the member function is bound to `w` as\n      // described in \"Instance binding\".\n      w.(Draw)();\n\n      // ❌ Error: `Self.Draw` performs `impl` lookup, which fails\n      // because `WidgetBase` does not implement `Renderable`.\n      w.(Self.Draw)();\n    }\n  }\n}\n\nclass TriangleWidget {\n  extend base: WidgetBase;\n  impl as Renderable;\n}\nfn DrawTriangle(t: TriangleWidget) {\n  // ✅ OK: name `Draw` resolves to `Draw` member of `WidgetBase`, which\n  // is `Renderable.Draw`. Then impl lookup replaces that with `Draw`\n  // member of `impl TriangleWidget as Renderable`.\n  t.Draw();\n}\n```\n\n### `impl` lookup for compound member access\n\nFor a compound member access `a.(b)` where `b` names a member of an interface\n`I`, `impl` lookup is performed for `T as I`, where:\n\n-   If `b` is an instance member, `T` is the type of `a`. In this case,\n    [instance binding](#instance-binding) is always performed.\n-   Otherwise, `a` is implicitly converted to `I`, and `T` is the result of\n    symbolically evaluating the converted expression. In this case,\n    [instance binding](#instance-binding) is never performed.\n\nFor example:\n\n```carbon\nfn AddTwoIntegers(a: Integer, b: Integer) -> Integer {\n  // Since `Addable.Add` is an instance member of `Addable`, `T`\n  // is set to the type of `a`, and so uses `Integer as Addable`.\n  return a.(Addable.Add)(b);\n  //      ^ impl lookup and instance binding here\n  // Impl lookup transforms this into #3:\n  //   return a.((Integer as Addable).Add)(b);\n  // which no longer requires impl lookup.\n\n  // ❌ By the same logic, in this example, `T` is set to the\n  // type of `Integer`, and so uses `type as Addable`, which\n  // isn't implemented.\n  return Integer.(Addable.Add)(...);\n}\n\nfn SumIntegers(v: Vector(Integer)) -> Integer {\n  // Since `Addable.Sum` is a  non-instance member of `Addable`,\n  // `Integer` is implicitly converted to `Addable`, and so uses\n  // `Integer as Addable`.\n  Integer.(Addable.Sum)(v);\n  //     ^ impl lookup but no instance binding here\n  // Impl lookup transforms this into #4:\n  //   ((Integer as Addable).Sum)(v);\n  // which no longer requires impl lookup.\n\n  var a: Integer;\n  // ❌ This is an error since `a` does not implicitly convert to\n  // a type.\n  a.(Addable.Sum)(v);\n}\n```\n\n## Instance binding\n\nNext, _instance binding_ may be performed. This associates an expression with a\nparticular object or value instance. For example, this is the value bound to\n`self` when calling a method.\n\nFor the simple member access syntax `x.y`, if `x` is an entity that has member\nnames, such as a namespace or a type, then `y` is looked up within `x`, and\ninstance binding is not performed. Otherwise, `y` is looked up within the type\nof `x` and instance binding is performed if an instance member is found.\n\nIf instance binding is to be performed, the result of instance binding depends\non what instance member `M` was found:\n\n-   For a field member of a struct type or tuple type, `x` is converted to a\n    struct or tuple form by\n    [form decomposition](/docs/design/values.md#category-conversions), and the\n    `.f` element of the result of that conversion becomes the result of `x.f`.\n    All other elements are [discarded](/docs/design/values.md#form-conversions).\n-   For a field member in class `C`, `x` is required to be of type `C` or of a\n    type derived from `C`. The result is the corresponding subobject within `x`.\n    If `x` is an\n    [initializing expression](/docs/design/values.md#initializing-expressions),\n    then a\n    [temporary is materialized](/docs/design/values.md#temporary-materialization)\n    for `x`. The result of `x.y` has the same\n    [expression category](/docs/design/values.md#expression-categories) as the\n    possibly materialized `x`.\n\n    ```carbon\n    class Size {\n      var width: i32;\n      var height: i32;\n    }\n\n    var dims: Size = {.width = 1, .height = 2};\n    // `dims.width` denotes the field `width` of the object `dims`.\n    Print(dims.width);\n    // `dims` is a reference expression, so `dims.height` is a\n    // reference expression.\n    dims.height = 3;\n\n    fn GetSize() -> Size;\n    // `GetSize()` returns an initializing expression, which is\n    // materialized as a temporary on member access, so\n    // `GetSize().width` is an ephemeral reference expression.\n    Print(GetSize().width);\n    ```\n\n-   For a method, the result is a _bound method_, which is a value `F` such that\n    a function call `F(args)` behaves the same as a call to `M(args)` with the\n    `self` parameter initialized by `x`.\n\n    ```carbon\n    class Blob {\n      fn Mutate[ref self: Self](n: i32);\n    }\n    fn F(p: Blob*) {\n      // ✅ OK, forms bound method `((*p).M)` and calls it.\n      // This calls `Blob.Mutate` with `self` initialized by `*p`\n      // and `n` initialized by `5`.\n      (*p).Mutate(5);\n\n      // ✅ OK, same as above.\n      let bound_m: auto = (*p).Mutate;\n      bound_m(5);\n    }\n    ```\n\nThe compound member access syntax `x.(Y)`, where `Y` names an instance member,\nalways performs instance binding. It is an error if `Y` is already bound to an\ninstance member. For example:\n\n```carbon\ninterface DebugPrint {\n  // instance member\n  fn Print[self:Self]();\n}\nimpl i32 as DebugPrint;\nimpl type as DebugPrint;\n\nfn Debug() {\n  var i: i32 = 1;\n\n  // Prints `1` using `(i32 as DebugPrint).Print` bound to `i`.\n  i.(DebugPrint.Print)();\n\n  // Prints `i32` using `(type as DebugPrint).Print` bound to `i32`.\n  i32.(DebugPrint.Print)();\n\n  // ❌ This is an error since `i32.(DebugPrint.Print)` is already\n  // bound, and may not be bound again to `i`.\n  i.(i32.(DebugPrint.Print))();\n}\n```\n\nTo get the `M` member of interface `I` for a type `T`, use `(T as I).M`, as this\ndoesn't attempt to perform instance binding on `T`, in contrast to `T.(I.M)`.\n\n## Non-instance members\n\nIf instance binding is not performed, the result is the member `M` determined by\nmember resolution and `impl` lookup. Evaluating the member access expression\nevaluates the first argument and discards the result.\n\nAn expression that names an instance member, but for which instance binding is\nnot performed, can only be used as the second operand of a compound member\naccess or as the target of an `alias` declaration.\n\n```carbon\nclass C {\n  fn StaticMethod();\n  var field: i32;\n  class Nested {}\n}\nfn CallStaticMethod(c: C) {\n  // ✅ OK, calls `C.StaticMethod`.\n  C.StaticMethod();\n\n  // ✅ OK, evaluates expression `c`, discards the result, then\n  // calls `C.StaticMethod`.\n  c.StaticMethod();\n\n  // ❌ Error: name of instance member `C.field` can only be used in\n  // a member access or alias.\n  C.field = 1;\n  // ✅ OK, instance binding is performed by outer member access,\n  // same as `c.field = 1;`\n  c.(C.field) = 1;\n\n  // ✅ OK\n  let T:! type = C.Nested;\n  // ❌ Error: value of `:!` binding is not compile-time because it\n  // refers to local variable `c`.\n  let U:! type = c.Nested;\n}\n```\n\n## Non-vacuous member access restriction\n\nThe first operand of a member access expression must be used in some way: a\ncompound member access must result in `impl` lookup, instance binding, or both.\nIn a simple member access, this always holds, because the first operand is\nalways used for lookup.\n\n```\ninterface Printable {\n  fn Print[self: Self]();\n}\nimpl i32 as Printable;\n\nfn MemberAccess(n: i32) {\n  // ✅ OK: `(i32 as Printable).Print` is the `Print` member of the\n  // `i32 as Printable` facet corresponding to the `Printable.Print`\n  // interface member.\n  // `n.((i32 as Printable).Print)` is that member function bound to `n`.\n  n.((i32 as Printable).Print)();\n\n  // ✅ Same as above, `n.(Printable.Print)` is effectively interpreted\n  // as `n.((T as Printable).Print)()`, where `T` is the type of `n`.\n  // Performs impl lookup and then instance binding.\n  n.(Printable.Print)();\n}\n\ninterface Factory {\n  fn Make() -> Self;\n}\nimpl i32 as Factory;\n\n// ✅ OK, member `Make` of interface `Factory`.\nalias X1 = Factory.Make;\n// ❌ Error, compound access without impl lookup or instance binding.\nalias X2 = Factory.(Factory.Make);\n// ✅ OK, member `Make` of `impl i32 as Factory`.\nalias X3 = (i32 as Factory).Make;\n// ❌ Error, compound access without impl lookup or instance binding.\nalias X4 = i32.((i32 as Factory).Make);\n```\n\n## Precedence and associativity\n\nMember access expressions associate left-to-right:\n\n```\nclass A {\n  class B {\n    fn F();\n  }\n}\ninterface B {\n  fn F();\n}\nimpl A as B;\n\nfn Use(a: A) {\n  // Calls member `F` of class `A.B`.\n  (a.B).F();\n  // Calls member `F` of interface `B`, as implemented by type `A`.\n  a.(B.F)();\n  // Same as `(a.B).F()`.\n  a.B.F();\n}\n```\n\nMember access has lower precedence than primary expressions, and higher\nprecedence than all other expression forms.\n\n```\n// ✅ OK, `*` has lower precedence than `.`. Same as `(A.B)*`.\nvar p: A.B*;\n// ✅ OK, `1 + (X.Y)` not `(1 + X).Y`.\nvar n: i32 = 1 + X.Y;\n```\n\n## Alternatives considered\n\n-   [Separate syntax for static versus dynamic access, such as `::` versus `.`](/proposals/p0989.md#separate-syntax-for-static-versus-dynamic-access)\n-   [Use a different lookup rule for names in templates](/proposals/p0989.md#use-a-different-lookup-rule-in-templates)\n-   [Meaning of `Type.Interface`](/proposals/p0989.md#meaning-of-typeinterface)\n\n## References\n\n-   Proposal\n    [#989: member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n-   [Question for leads: constrained template name lookup](https://github.com/carbon-language/carbon-lang/issues/949)\n-   Proposal\n    [#2360: Types are values of type `type`](https://github.com/carbon-language/carbon-lang/pull/2360)\n-   Proposal\n    [#2550: Simplified package declaration for the `Main` package](https://github.com/carbon-language/carbon-lang/pull/2550)\n"
  },
  {
    "path": "docs/design/expressions/pointer_operators.md",
    "content": "# Pointer operators\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [Precedence](#precedence)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon provides the following operators related to pointers:\n\n-   `&` as a prefix unary operator takes the address of an object, forming a\n    pointer to it.\n-   `*` as a prefix unary operator dereferences a pointer.\n\nNote that [member access expressions](member_access.md) include an `->` form\nthat implicitly performs a dereference in the same way as the `*` operator.\n\n## Details\n\nThe semantic details of pointer operators are collected in the main\n[pointers](/docs/design/values.md#pointers) design. The syntax and precedence\ndetails are covered here.\n\nThe syntax tries to remain as similar as possible to C++ pointer types as they\nare commonly written in code and are expected to be extremely common and a key\nanchor of syntactic similarity between the languages.\n\n### Precedence\n\nThese operators have high precedence. Only [member access](member_access.md)\nexpressions can be used as an unparenthesized operand to them.\n\nThe two prefix operators `&` and `*` are generally above the other unary and\nbinary operators and can appear inside them as unparenthesized operands. For the\nfull details, see the [precedence graph](README.md#precedence).\n\n## Alternatives considered\n\n-   [Alternative pointer syntaxes](/proposals/p2006.md#alternative-pointer-syntaxes)\n\n## References\n\n-   [Proposal #2006: Values, variables, and pointers](/proposals/p2006.md)\n"
  },
  {
    "path": "docs/design/expressions/type_operators.md",
    "content": "# Type operators\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [Precedence](#precedence)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon provides the following operators to transform types:\n\n-   `const` as a prefix unary operator produces a `const`-qualified type.\n-   `*` as a postfix unary operator produces a pointer _type_ to some other\n    type.\n\nThe pointer type operator is also covered as one of the\n[pointer operators](pointer_operators.md).\n\n## Details\n\nThe semantic details of both `const`-qualified types and pointer types are\nprovided as part of the [values](/docs/design/values.md) design:\n\n-   [`const`-qualified types](/docs/design/values.md#const-qualified-types)\n-   [Pointers](/docs/design/values.md#pointers)\n\nThe syntax of these operators tries to mimic the most common appearance of\n`const` types and pointer types in C++.\n\n### Precedence\n\nBecause these are type operators, they don't have many precedence relationship\nwith non-type operators.\n\n-   `const` binds more tightly than `*` and can appear unparenthesized in an\n    operand, despite being both a unary operator and having whitespace\n    separating it.\n    -   This allows the syntax of a pointer to a `const i32` to be `const i32*`,\n        which is intended to be familiar to C++ developers.\n    -   Forming a `const` pointer type requires parentheses: `const (i32*)`.\n-   All type operators bind more tightly than `as` so they can be used in its\n    type operand.\n    -   This also allows a desirable transitive precedence with `if`:\n        `if condition then T* else U*`.\n\n## Alternatives considered\n\n-   [Alternative pointer syntaxes](/proposals/p2006.md#alternative-pointer-syntaxes)\n-   [Alternative syntaxes for locals](/proposals/p2006.md#alternative-syntaxes-for-locals)\n-   [Make `const` a postfix rather than prefix operator](/proposals/p2006.md#make-const-a-postfix-rather-than-prefix-operator)\n\n## References\n\n-   [Proposal #2006: Values, variables, and pointers](/proposals/p2006.md)\n"
  },
  {
    "path": "docs/design/functions.md",
    "content": "# Functions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Function definitions](#function-definitions)\n    -   [Return clause](#return-clause)\n    -   [`return` statements](#return-statements)\n-   [Function declarations](#function-declarations)\n-   [Function calls](#function-calls)\n-   [Functions in other features](#functions-in-other-features)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\n> **TODO:** Update this document to reflect the introduction of function values,\n> function types, and the `Call` interface in\n> [p2875: Functions, function types, and function calls](/proposals/p2875.md).\n\n> **TODO:** Update this document to reflect the changes to named functions in\n> [p3848: Lambdas](/proposals/p3848.md).\n\nFunctions are the core building block for applications. Carbon's basic function\nsyntax is:\n\n-   _parameter_: _identifier_ `:` _expression_\n-   _parameter-list_: _[ parameter_ `,` _parameter_ `,` _... ]_\n-   _return-clause_: _[_ `->` _< expression |_ `auto` _> ]_\n-   _signature_: `fn` _identifier_ `(` _parameter-list_ `)` _return-clause_\n-   _function-definition_: _signature_ `{` _statements_ `}`\n-   _function-declaration_: _signature_ `;`\n-   _function-call_: _identifier_ `(` _[ expression_ `,` _expression_ `,` _...\n    ]_ `)`\n\nA function with only a signature and no body is a function declaration, or\nforward declaration. When the body is a present, it's a function definition. The\nbody introduces nested scopes which may contain local variable declarations.\n\n## Function definitions\n\nA basic function definition may look like:\n\n```carbon\nfn Add(a: i64, b: i64) -> i64 {\n  return a + b;\n}\n```\n\nThis declares a function called `Add` which accepts two `i64` parameters, the\nfirst called `a` and the second called `b`, and returns an `i64` result. It\nreturns the result of adding the two arguments.\n\nC++ might declare the same thing:\n\n```cpp\nstd::int64_t Add(std::int64_t a, std::int64_t b) {\n  return a + b;\n}\n\n// Or with trailing return type syntax:\nauto Add(std::int64_t a, std::int64_t b) -> std::int64_t {\n  return a + b;\n}\n```\n\n### Return clause\n\nThe return clause of a function specifies the return type using one of three\npossible syntaxes:\n\n-   `->` followed by an _expression_, such as `i64`, directly states the return\n    type. This expression will be evaluated at compile-time, so must be valid in\n    that context.\n    -   For example, `fn ToString(val: i64) -> String;` has a return type of\n        `String`.\n-   `->` followed by the `auto` keyword indicates that\n    [type inference](type_inference.md) should be used to determine the return\n    type.\n    -   For example, `fn Echo(val: i64) -> auto { return val; }` will have a\n        return type of `i64` through type inference.\n    -   Declarations must have a known return type, so `auto` is not valid.\n    -   The function must have precisely one `return` statement. That `return`\n        statement's expression will then be used for type inference.\n-   Omission indicates that the return type is the empty tuple, `()`.\n    -   For example, `fn Sleep(seconds: i64);` is similar to\n        `fn Sleep(seconds: i64) -> ();`.\n    -   `()` is similar to a `void` return type in C++.\n\n> **TODO:** Update this section to cover return forms, as discussed\n> [here](values.md#function-calls-and-returns).\n\n### `return` statements\n\nThe [`return` statement](control_flow/return.md) is essential to function\ncontrol flow. It ends the flow of the function and returns execution to the\ncaller.\n\nWhen the [return clause](#return-clause) is omitted, the `return` statement has\nno expression argument, and function control flow implicitly ends after the last\nstatement in the function's body as if `return;` were present.\n\nWhen the return clause is provided, including when it is `-> ()`, the `return`\nstatement must have an expression that is convertible to the return type, and a\n`return` statement must be used to end control flow of the function.\n\n> **TODO:** Update this section to cover the requirements on the form of the\n> expression.\n\n## Function declarations\n\nFunctions may be declared separate from the definition by providing only a\nsignature, with no body. This provides an API which may be called. For example:\n\n```carbon\n// Declaration:\nfn Add(a: i64, b: i64) -> i64;\n\n// Definition:\nfn Add(a: i64, b: i64) -> i64 {\n  return a + b;\n}\n```\n\nThe corresponding definition may be provided later in the same file or, when the\ndeclaration is in an\n[API file of a library](code_and_name_organization/#libraries), in an\nimplementation file of the same library. The signature of a function declaration\nmust match the corresponding definition. This includes the\n[return clause](#return-clause); even though an omitted return type has\nequivalent behavior to `-> ()`, the presence or omission must match.\n\n## Function calls\n\nFunction calls use a function's identifier to pass multiple expression arguments\ncorresponding to the function signature's parameters. For example:\n\n```carbon\nfn Add(a: i64, b: i64) -> i64 {\n  return a + b;\n}\n\nfn Run() {\n  Add(1, 2);\n}\n```\n\nHere, `Add(1, 2)` is a function call expression. `Add` refers to the function\ndefinition's identifier. The parenthesized arguments `1` and `2` are passed to\nthe `a` and `b` parameters of `Add`.\n\n## Functions in other features\n\nOther designs build upon basic function syntax to add advanced features:\n\n-   [Generic functions](generics/overview.md#generic-functions) adds support for\n    deduced parameters and compile-time parameters.\n-   [Class member functions](classes.md#member-functions) adds support for\n    methods and class functions.\n\n## Alternatives considered\n\n-   [Function keyword](/proposals/p0438.md#function-keyword)\n-   [Only allow `auto` return types if parameters are compile-time](/proposals/p0826.md#only-allow-auto-return-types-if-parameters-are-generic)\n-   [Provide alternate function syntax for concise return type inference](/proposals/p0826.md#provide-alternate-function-syntax-for-concise-return-type-inference)\n-   [Allow separate declaration and definition](/proposals/p0826.md#allow-separate-declaration-and-definition)\n\n## References\n\n-   Proposal\n    [#438: Add statement syntax for function declarations](https://github.com/carbon-language/carbon-lang/pull/438)\n-   Proposal\n    [#826: Function return type inference](https://github.com/carbon-language/carbon-lang/pull/826)\n"
  },
  {
    "path": "docs/design/generics/README.md",
    "content": "# Generics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis directory contains the collection of documents describing the generics\nfeature of Carbon:\n\n-   [Overview](overview.md) - A high-level description of the generics design,\n    with pointers to other design documents that dive deeper into individual\n    topics\n-   [Goals](goals.md) - The motivation and principles guiding the design\n    direction\n-   [Terminology](terminology.md) - A glossary establishing common terminology\n    for describing the design\n-   [Detailed design](details.md) - In-depth description\n    -   [Appendix: Coherence](appendix-coherence.md) - Describes the rationale\n        for Carbon's choice to have coherent generics, and the alternatives.\n    -   [Appendix: Rewrite constraints](appendix-rewrite-constraints.md) -\n        Describes the detailed rules governing rewrite constraints, and why\n        resolving them terminates.\n    -   [Appendix: Witness tables](appendix-witness.md) - Describes an\n        implementation strategy for checked generics, and Carbon's rationale for\n        only using it for dynamic dispatch.\n"
  },
  {
    "path": "docs/design/generics/appendix-coherence.md",
    "content": "# Carbon: alternatives to coherence\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis document explains the rationale for choosing to make\n[implementation coherence](terminology.md#coherence)\n[a goal for Carbon](goals.md#coherence), and the alternatives considered.\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Approach taken: coherence](#approach-taken-coherence)\n-   [The \"Hashtable Problem\"](#the-hashtable-problem)\n-   [Rejected alternative: no orphan rule](#rejected-alternative-no-orphan-rule)\n-   [Rejected alternative: incoherence](#rejected-alternative-incoherence)\n    -   [Incoherence means context sensitivity](#incoherence-means-context-sensitivity)\n    -   [Rejected variation: dynamic implementation binding](#rejected-variation-dynamic-implementation-binding)\n    -   [Rejected variation: manual conflict resolution](#rejected-variation-manual-conflict-resolution)\n\n<!-- tocstop -->\n\n## Approach taken: coherence\n\nThe main thing to understand is that coherence is a desirable property, but to\nget that property we need an orphan rule, and that rule has a cost. It in\nparticular limits how much control users of a type have over how that type\nimplements interfaces. There are a few main problematic use cases to consider:\n\n-   Selecting between multiple implementations of an interface for a type. For\n    example selecting the implementation of the `Comparable` interface for a\n    `Song` type to support \"by title\", \"by artist\", and \"by album\" orderings.\n-   Implementing an interface for a type when there is no relationship between\n    the libraries defining the interface and the type.\n-   When the implementation of an interface for a type relies on something that\n    can't be referenced from the file or files where the implementation is\n    allowed to be defined.\n\nThese last two cases are highlighted as concerns in Rust in\n[Rust RFC #1856: orphan rules are stricter than we would like](https://github.com/rust-lang/rfcs/issues/1856).\n\nSince Carbon is bundling interface implementations into types, for the\nconvenience and expressiveness that provides, we satisfy those use cases by\ngiving the user control over the type of a value. This means having facilities\nfor defining new [compatible types](terminology.md#compatible-types) with\ndifferent interface implementations, and casting between those types as needed.\n\n## The \"Hashtable Problem\"\n\nThe \"Hashtable problem\" is that the specific hash function used to compute the\nhash of keys in a hashtable must be the same when adding an entry, when looking\nit up, and other operations like resizing. So a hashtable type is dependent on\nboth the key type, and the key type's implementation of the `Hashable`\ninterface. If the key type can have more than one implementation of `Hashable`,\nthere needs to be some mechanism for choosing a single one to be used\nconsistently by the hashtable type, or the invariants of the type will be\nviolated.\n\nWithout the orphan rule to enforce coherence, we might have a situation like\nthis:\n\n-   Package `Container` defines a `HashSet` type.\n\n    ```\n    package Container;\n    class HashSet(Key:! Hashable) { ... }\n    ```\n\n-   A `Song` type is defined in package `SongLib`.\n-   Package `SongHashArtistAndTitle` defines an implementation of `Hashable` for\n    `SongLib.Song`.\n\n    ```\n    package SongHashArtistAndTitle;\n    import SongLib;\n    impl SongLib.Song as Hashable {\n      fn Hash[self: Self]() -> u64 { ... }\n    }\n    ```\n\n-   Package `SongUtil` uses the `Hashable` implementation from\n    `SongHashArtistAndTitle` to define a function `IsInHashSet`.\n\n    ```\n    package SongUtil;\n    import SongLib;\n    import SongHashArtistAndTitle;\n    import Containers;\n\n    fn IsInHashSet(\n        s: SongLib.Song,\n        h: Containers.HashSet(SongLib.Song)*) -> bool {\n      return h->Contains(s);\n    }\n    ```\n\n-   Package `SongHashAppleMusicURL` defines a different implementation of\n    `Hashable` for `SongLib.Song` than package `SongHashArtistAndTitle`.\n\n    ```\n    package SongHashAppleMusicURL;\n    import SongLib;\n    impl SongLib.Song as Hashable {\n      fn Hash[self: Self]() -> u64 { ... }\n    }\n    ```\n\n-   Finally, package `Trouble` imports `SongHashAppleMusicURL`, creates a hash\n    set, and then calls the `IsInHashSet` function from package `SongUtil`.\n\n    ```\n    package Trouble;\n    import SongLib;\n    import SongHashAppleMusicURL;\n    import Containers;\n    import SongUtil;\n\n    fn SomethingWeirdHappens() {\n      var unchained_melody: SongLib.Song = ...;\n      var song_set: auto = Containers.HashSet(SongLib.Song).Make();\n      song_set.Add(unchained_melody);\n      // Either this is a compile error or does something unexpected.\n      if (SongUtil.IsInHashSet(unchained_melody, &song_set)) {\n        Print(\"This is expected, but doesn't happen.\");\n      } else {\n        Print(\"This is what happens even though it is unexpected.\");\n      }\n    }\n    ```\n\nThe issue is that in package `Trouble`, the `song_set` is created in a context\nwhere `SongLib.Song` has a `Hashable` implementation from\n`SongHashAppleMusicURL`, and stores `unchained_melody` under that hash value.\nWhen we go to look up the same song in `SongUtil.IsInHashSet`, it uses the hash\nfunction from `SongHashArtistAndTitle` which returns a different hash value for\n`unchained_melody`, and so reports the song is missing.\n\n**Background:** [This post](https://gist.github.com/nikomatsakis/1421744)\ndiscusses the hashtable problem in the context of Haskell, and\n[this 2011 Rust followup](https://www.mail-archive.com/rust-dev@mozilla.org/msg01024.html)\ndiscusses how to detect problems at compile time.\n\n## Rejected alternative: no orphan rule\n\nIn Swift an implementation of an interface, or a \"protocol\" as it is called in\nSwift, can be provided in any module. As long as any module provides an\nimplementation, that implementation is\n[used globally throughout the program](https://stackoverflow.com/questions/48762971/swift-protocol-conformance-by-extension-between-frameworks).\n\nIn Swift, since some protocol implementations can come from the runtime\nenvironment provided by the operating system, multiple implementations for a\nprotocol can arise as a runtime warning. When this happens, Swift picks one\nimplementation arbitrarily.\n\nIn Carbon, we could make this a build time error. However, there would be\nnothing preventing two independent libraries from providing conflicting\nimplementations. Furthermore, the error would only be diagnosed at link time.\n\n## Rejected alternative: incoherence\n\n### Incoherence means context sensitivity\n\nThe undesirable result of incoherence is that the interpretation of source code\nchanges based on imports. In particular, imagine there is a function call that\ndepends on a type implementing an interface, and two different implementations\nare defined in two different libraries. A call to that function will be treated\ndifferently depending on which of those two libraries are imported:\n\n-   If neither is imported, it is an error.\n-   If both are imported, it is ambiguous.\n-   If only one is imported, you get totally different code executed depending\n    on which it is.\n\nFurthermore, this means that the behavior of a file can depend on an import even\nif nothing from that package is referenced explicitly. In general, Carbon is\n[avoiding this sort of context sensitivity](/docs/project/principles/low_context_sensitivity.md).\nThis context sensitivity would make moving code between files when refactoring\nmore difficult and less safe.\n\n### Rejected variation: dynamic implementation binding\n\nOne possible approach would be to bind interface implementations to a value at\nthe point it was created. In [the example above](#the-hashtable-problem), the\nimplementation of the `Hashable` interface for `Song` would be fixed for the\n`song_set` `HashSet` object based on which implementation was in scope in the\nbody of the `SomethingWeirdHappens` function.\n\nThis idea is discussed briefly in section 5.4 on separate compilation of WG21\nproposal n1848 for implementing \"Indiana\" C++0x concepts\n([1](https://citeseerx.ist.psu.edu/pdf/6e1398d22fd6a3e31aba2519d7a00a8f0d93e7e8),\nand [2](https://wg21.link/n1848)).\n\nThis has some downsides:\n\n-   It is harder to reason about. The behavior of `SongUtil.IsInHashSet` depends\n    on the dynamic behavior of the program. At the time of the call, we may have\n    no idea where the `HashSet` argument was created.\n-   An object may be created far from a call that has a particular interface\n    requirement, with no guarantee that the object was created with any\n    implementation of the interface at all. This error would only be detected at\n    runtime, not at type checking time.\n-   It requires more data space at runtime because we need to store a pointer to\n    the witness table representing the implementation with the object, since it\n    varies instead of being known statically.\n-   It is slower to execute from dynamic dispatch and the inability to inline.\n-   In some cases it may not be feasible to use dynamic dispatch. For example,\n    if the return type of an interface method involves an associated constant,\n    we might not know the calling convention of the function without knowing\n    some details about the value of that constant.\n\nAs a result, this doesn't make sense as the default behavior for Carbon based on\nits [goals](/docs/project/goals.md). That being said, this could be a feature\nadded later as opt-in behavior to either allow users to reduce code size or\nsupport use cases that require dynamic dispatch.\n\n### Rejected variation: manual conflict resolution\n\nCarbon could alternatively provide some kind of manual disambiguation syntax to\nresolve problems where they arise. The problems with this approach have been\n[considered in the context of Rust](https://github.com/Ixrec/rust-orphan-rules#whats-wrong-with-incoherence).\n\nA specific example of this approach is called\n[scoped conformance](https://forums.swift.org/t/scoped-conformances/37159),\nwhere the conflict resolution is based on limiting the visibility of\nimplementations to particular scopes. This hasn't been implemented, but it has\nthe drawbacks described above. Depending on the details of the implementation,\neither:\n\n-   there are incompatible values with types that have the same name, or\n-   it is difficult to reason about the program's behavior because it behaves\n    like\n    [dynamic implementation binding](#rejected-variation-dynamic-implementation-binding)\n    (though perhaps with a monomorphization cost instead of a runtime cost).\n\nIn addition, this can create unsoundness when combined with dynamic downcasts\nand a more complex, less predictable implementation model as\n[discussed in Swift](https://forums.swift.org/t/retroactive-conformances-dynamic-downcast-type-unsoundness/73890).\nThis approach would be particularly complex in Carbon due to supporting\n[impl specialization](terminology.md#specialization).\n"
  },
  {
    "path": "docs/design/generics/appendix-rewrite-constraints.md",
    "content": "# Carbon: Rewrite constraint details\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis document explains the rationale for choosing to make\n[implementation coherence](terminology.md#coherence)\n[a goal for Carbon](goals.md#coherence), and the alternatives considered.\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Rewrite constraints](#rewrite-constraints)\n-   [Combining constraints with `&`](#combining-constraints-with-)\n-   [Combining constraints with `and`](#combining-constraints-with-and)\n-   [Combining constraints with `extend`](#combining-constraints-with-extend)\n-   [Combining constraints with `require` and `impls`](#combining-constraints-with-require-and-impls)\n-   [Rewrite constraint resolution](#rewrite-constraint-resolution)\n-   [Precise rules and termination](#precise-rules-and-termination)\n    -   [Qualified name lookup](#qualified-name-lookup)\n    -   [Type substitution](#type-substitution)\n    -   [Examples](#examples)\n    -   [Termination](#termination)\n\n<!-- tocstop -->\n\n## Rewrite constraints\n\nRewrite constraints are [`where` clauses](details.md#where-constraints) of the\nform `.AssociatedConstant = Value`. Given `T:! A where .B = C`, references to\n`T.(A.B)` are rewritten to `C`. This appendix describes the precise rules\ngoverning them.\n\n## Combining constraints with `&`\n\nSuppose we have `X = C where .R = A` and `Y = C where .R = B`. What should\n`C & X` produce? What should `X & Y` produce?\n\n-   Combining two rewrite rules with different rewrite targets results in a\n    facet type where the associated constant is ambiguous. Given `T:! X & Y`,\n    the type expression `T.R` is ambiguous between a rewrite to `A` and a\n    rewrite to `B`. But given `T:! X & X`, `T.R` is unambiguously rewritten to\n    `A`.\n-   Combining a constraint with a rewrite rule with a constraint with no rewrite\n    rule preserves the rewrite rule, so `C & X` is the same as `X`. For example,\n    supposing that `interface Container` extends `interface Iterable`, and\n    `Iterable` has an associated constant `Element`, the constraint\n    `Container & (Iterable where .Element = i32)` is the same as the constraint\n    `(Container & Iterable) where .Element = i32` which is the same as the\n    constraint `Container where .Element = i32`.\n\nIf the rewrite for an associated constant is ambiguous, the facet type is\nrejected during [constraint resolution](#rewrite-constraint-resolution).\n\n> **Alternative considered:** We could perhaps say that `X & Y` results in a\n> facet type where the type of `R` has the union of the interface of `A` and the\n> interface of `B`, and that `C & X` similarly results in a facet type where the\n> type of `R` has the union of the interface of `A` and the interface originally\n> specified by `C`.\n\n## Combining constraints with `and`\n\nIt's possible for one `=` constraint in a `where` to refer to another. When this\nhappens, the facet type `C where A and B` is interpreted as\n`(C where A) where B`, so rewrites in `A` are applied immediately to names in\n`B`, but rewrites in `B` are not applied to names in `A` until the facet type is\n[resolved](#rewrite-constraint-resolution):\n\n```carbon\ninterface C {\n  let T:! type;\n  let U:! type;\n  let V:! type;\n}\nclass M {\n  alias Me = Self;\n}\n// ✅ Same as `C where .T = M and .U = M.Me`, which is\n// the same as `C where .T = M and .U = M`.\nfn F[A:! C where .T = M and .U = .T.Me]() {}\n// ❌ No member `Me` in `A.T:! type`.\nfn F[A:! C where .U = .T.Me and .T = M]() {}\n```\n\n## Combining constraints with `extend`\n\nWithin an interface or named constraint, `extend` can be used to extend a\nconstraint that has rewrites.\n\n```carbon\ninterface A {\n  let T:! type;\n  let U:! type;\n}\ninterface B {\n  extend A where .T = .U and .U = i32;\n}\n\nvar n: i32;\n\n// ✅ Resolved constraint on `T` is\n// `B where .(A.T) = i32 and .(A.U) = i32`.\n// `T.(A.T)` is rewritten to `i32`.\nfn F(T:! B) -> T.(A.T) { return n; }\n```\n\n## Combining constraints with `require` and `impls`\n\nWithin an interface or named constraint, the `require T impls C` and\n`require Self impls C` syntaxes do not change the type of `T` or `Self`,\nrespectively, so any `=` constraints that they specify do not result in rewrites\nbeing performed when the type `T` or `Self` is later used. Such `=` constraints\nare equivalent to `==` constraints:\n\n```carbon\ninterface A {\n  let T:! type;\n  let U:! type;\n}\nconstraint C {\n  extend A where .T = .U and .U = i32;\n}\nconstraint D {\n  extend A where .T == .U and .U == i32;\n}\ninterface B {\n  // OK, equivalent to `require Self impls D;` or\n  // `require Self impls A where .T == .U and .U == i32;`.\n  require Self impls C;\n}\n\nvar n: i32;\n\n// ❌ No implicit conversion from `i32` to `T.(A.T)`.\n// Resolved constraint on `T` is\n// `B where T.(A.T) == T.(A.U) and T.(A.U) == i32`.\n// `T.(A.T)` is single-step equal to `T.(A.U)`, and\n// `T.(A.U)` is single-step equal to `i32`, but\n// `T.(A.T)` is not single-step equal to `i32`.\nfn F(T:! B) -> T.(A.T) { return n; }\n```\n\nBecause `=` constraints are effectively treated as `==` constraints in an\n`require Self impls C` or `require T impls C` declaration in an interface or\nnamed constraint, it is an error to specify such a `=` constraint directly in\n`C`. A purely syntactic check is used to determine if an `=` is specified\ndirectly in an expression:\n\n-   An `=` constraint is specified directly in its enclosing `where` expression.\n-   If an `=` constraint is specified directly in an operand of an `&` or\n    `(`...`)`, then it is specified directly in that enclosing expression.\n\nFor example:\n\n```carbon\n// Compile-time identity function.\nfn Identity[T:! type](x:! T) -> T { return x; }\n\ninterface E {\n  // ❌ Rewrite constraint specified directly.\n  require Self impls A where .T = .U and .U = i32;\n  // ❌ Rewrite constraint specified directly.\n  require Self impls type & (A where .T = .U and .U = i32);\n  // ✅ Not specified directly, but does not result\n  // in any rewrites being performed.\n  require Self impls Identity(A where .T = .U and .U = i32);\n}\n```\n\nThe same rules apply to `where`...`impls` constraints. Note that `.T == U`\nconstraints are also not allowed in this context, because the reference to `.T`\nis rewritten to `.Self.T`, and `.Self` is ambiguous.\n\n```carbon\n// ❌ Rewrite constraint specified directly in `impls`.\nfn F[T:! A where .U impls (A where .T = i32)]();\n\n// ❌ Reference to `.T` in same-type constraint is ambiguous:\n// does this mean the outer or inner `.Self.T`?\nfn G[T:! A where .U impls (A where .T == i32)]();\n\n// ✅ Not specified directly, but does not result\n// in any rewrites being performed. Return type\n// is not rewritten to `i32`.\nfn H[T:! type where .Self impls C]() -> T.(A.U);\n\n// ✅ Return type is rewritten to `i32`.\nfn I[T:! C]() -> T.(A.U);\n```\n\n## Rewrite constraint resolution\n\nWhen a facet type is used as the declared type of a facet `T`, the constraints\nthat were specified within that facet type are _resolved_ to determine the\nconstraints that apply to `T`. This happens:\n\n-   When the constraint is used explicitly when declaring a symbolic binding,\n    like a generic parameter or associated constant, of the form\n    `T:! Constraint`.\n-   When declaring that a type implements a constraint with an `impl`\n    declaration, such as `impl T as Constraint`. Note that this does not include\n    `require` ... `impls` constraints appearing in `interface` or `constraint`\n    declarations.\n\nIn each case, the following steps are performed to resolve the facet type's\nabstract constraints into a set of constraints on `T`:\n\n-   Rewrites are performed on other rewrites in order to find a fixed point,\n    where no rewrite applies within any other rewrite. If no fixed point exists,\n    the generic parameter declaration or `impl` declaration is invalid.\n    -   Rewrites are resolved in order from left to right.\n    -   The left-most rewrite of a given associated constant is used for\n        rewriting all other rewrite constraints that refer to it.\n-   If multiple rewrites are specified for the same associated constant, they\n    are required to be identical, and duplicates are discarded. Identical is\n    taken to mean that they resolve to the same value at the time of resolution.\n-   Rewrites are performed throughout the other constraints in the facet type --\n    that is, in any `==` constraints and `impls` constraints -- and the type\n    `.Self` is replaced by `T` throughout the constraint.\n\n```carbon\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n// ✅ `.X` in `.Y = .X` is rewritten to `i32` when initially\n// forming the facet type.\n// Nothing to do during constraint resolution.\nfn InOrder[T:! I where .X = i32 and .Y = .X]() {}\n// ✅ Facet type has `.X = .Y` before constraint resolution.\n// That rewrite is resolved to `.X = i32`.\nfn Reordered[T:! I where .X = .Y and .Y = i32]() {}\n// ✅ Facet type has `.Y = .X` before constraint resolution.\n// That rewrite is resolved to `.Y = i32`.\nfn ReorderedIndirect[T:! (I where .X = i32) & (I where .Y = .X)]() {}\n// ❌ Constraint resolution fails because\n// no fixed point of rewrites exists.\nfn Cycle[T:! I where .X = .Y and .Y = .X]() {}\n```\n\nTo find a fixed point, we can perform rewrites on other rewrites, cycling\nbetween them until they don't change or until a rewrite would apply to itself.\nIn the latter case, we have found a cycle and can reject the constraint. Note\nthat it's not sufficient to expand only a single rewrite until we hit this\ncondition:\n\n```carbon\n// ❌ Constraint resolution fails because\n// no fixed point of rewrites exists.\n// If we only expand the right-hand side of `.X`,\n// we find `.Y`, then `.Y**`, then `.Y****`, and so on,\n// and never detect a cycle.\n// If we alternate between them, we find\n// `.X = .Y*`, then `.Y = .Y**`, then `.Z = .Y***`,\n// then `.X = .Y**`, then detect that the `.Y` rewrite\n// would apply to itself.\nfn IndirectCycle[T:! I where .X = .Y and .Y = .Z* and .Z = .Y*]();\n```\n\nAfter constraint resolution, no references to rewritten associated constants\nremain in the constraints on `T` and there is at most one rewrite for each\nassociated constant.\n\nThe following examples each treat the two assignments of `.X` as being\nidentical, though they are written differently:\n\n```carbon\nfn Identical(T:! I where .X = () and .X = .Y and .Y = ()) {}\n\nfn IdenticalNoCycle(T:! I where .X = () and .X = .Y and .Y = .X) {}\n\nfn IdenticalNested(T:! (I where .X = ()) where .X = .Y and .Y = ()) {}\n```\n\nThe rewrite constraints of the current facet type are all available, so both\nrewrites of `.X` can be seen to be assigning `()`. In the second example, the\nvalue of `.X` is rewritten into `.Y = .X` from the left-most rewrite of `.X`,\ngiving `.Y = ()` rather than `.Y = .Y`, so we are able to find a fixed point.\n\nBut the following does not have the rewrite of `.Y` available at the time of\nresolving the two rewrites of `.X`, so the rewrites are invalid:\n\n```carbon\nfn NotIdentical(T:! (I where .X = () and .X = .Y) where .Y = ()) {}\n```\n\nWhen combining two facet types together with `&`, the rewrite constraints are\nconcatenated together for resolution, with the rewrites from the LHS of the `&`\noperator coming first and the rewrite from the RHS coming second:\n`(I where .X = ()) & (I where .Y = ())` is resolved as\n`(I where .X = () and .Y = ())`.\n\nIf a facet type is never used to constrain a type, it is never subject to\nconstraint resolution, and it is possible for a facet type to be formed for\nwhich constraint resolution would always fail. For example:\n\n```carbon\npackage Broken;\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\nlet Bad:! auto = (I where .X = .Y) & (I where .Y = .X);\n// Bad is not used here.\n```\n\nIn such cases, the facet type `Broken.Bad` is not usable: any attempt to use\nthat facet type to constrain a type would perform constraint resolution, which\nwould always fail because it would discover a cycle between the rewrites for\n`.X` and for `.Y`. In order to ensure that such cases are diagnosed, a trial\nconstraint resolution is performed for all facet types. Note that this trial\nresolution can be skipped for facet types that are actually used, which is the\ncommon case.\n\n## Precise rules and termination\n\nThis section explains the detailed rules used to implement rewrites. There are\ntwo properties we aim to satisfy:\n\n1.  After type-checking, no symbolic references to associated constants that\n    have an associated rewrite rule remain.\n2.  Type-checking always terminates in a reasonable amount of time, ideally\n    linear in the size of the problem.\n\nRewrites are applied in two different phases of program analysis.\n\n-   During qualified name lookup and type checking for qualified member access,\n    if a rewritten member is looked up, the right-hand side's value and type are\n    used for subsequent checks.\n-   During substitution, if the symbolic name of an associated constant is\n    substituted into, and substitution into the left-hand side results in a\n    value with a rewrite for that constant, that rewrite is applied.\n\nIn each case, we always rewrite to a value that satisfies property 1 above, and\nthese two steps are the only places where we might form a symbolic reference to\nan associated cosntant, so property 1 is recursively satisfied. Moreover, we\napply only one rewrite in each of the above cases, satisfying property 2.\n\n### Qualified name lookup\n\nQualified name lookup into either a facet parameter or into an expression whose\ntype is a symbolic type `T` -- either a facet parameter or an associated facet\n-- considers names from the facet type `C` of `T`, that is, from `T`’s declared\ntype.\n\n```carbon\ninterface C {\n  let M:! i32;\n  let U:! C;\n}\nfn F[T:! C](x: T) {\n  // Value is C.M in all four of these\n  let a: i32 = x.M;\n  let b: i32 = T.M;\n  let c: i32 = x.U.M;\n  let d: i32 = T.U.M;\n}\n```\n\nWhen looking up the name `N`, if `C` is an interface `I` and `N` is the name of\nan associated constant in that interface, the result is a symbolic constant\nrepresenting \"the member `N` of `I`\". If `C` is formed by combining interfaces\nwith `&`, all such results are required to find the same associated constant,\notherwise we reject for ambiguity.\n\nIf a member of a class or interface is named in a qualified name lookup, the\ntype of the result is determined by performing a substitution. For an interface,\n`Self` is substituted for the self type, and any parameters for that class or\ninterface (and enclosing classes or interfaces, if any) are substituted into the\ndeclared type.\n\n```carbon\ninterface SelfIface {\n  fn Get[self: Self]() -> Self;\n}\nclass UsesSelf(T:! type) {\n  // Equivalent to `fn Make() -> UsesSelf(T)*;`\n  fn Make() -> Self*;\n  impl as SelfIface;\n}\n\n// ✅ `T = i32` is substituted into the type of `UsesSelf(T).Make`,\n// so the type of `UsesSelf(i32).Make` is `fn () -> UsesSelf(i32)*`.\nlet x: UsesSelf(i32)* = UsesSelf(i32).Make();\n\n// ✅ `Self = UsesSelf(i32)` is substituted into the type\n// of `SelfIface.Get`, so the type of `UsesSelf(i32).(SelfIface.Get)`\n// is `fn [self: UsesSelf(i32)]() -> UsesSelf(i32)`.\nlet y: UsesSelf(i32) = x->Get();\n```\n\nIf a facet type `C` into which lookup is performed includes a `where` clause\nsaying `.N = U`, and the result of qualified name lookup is the associated\nconstant `N`, that result is replaced by `U`, and the type of the result is the\ntype of `U`. No substitution is performed in this step, not even a `Self`\nsubstitution -- any necessary substitutions were already performed when forming\nthe facet type `C`, and we don’t consider either the declared type or value of\nthe associated constant at all for this kind of constraint. Going through an\nexample in detail:\n\n```carbon\ninterface A {\n  let T:! type;\n}\ninterface B {\n  let U:! type;\n  // More explicitly, this is of type `A where .(A.T) = Self.(B.U)`\n  let V:! A where .T = U;\n}\n// Type of W is B.\nfn F[W:! B](x: W) {\n  // The type of the expression `W` is `B`.\n  // `W.V` finds `B.V` with type `A where .(A.T) = Self.(B.U)`.\n  // We substitute `Self` = `W` giving the type of `u` as\n  // `A where .(A.T) = W.(B.U)`.\n  let u:! auto = W.V;\n  // The type of `u` is `A where .(A.T) = W.(B.U)`.\n  // Lookup for `u.T` resolves it to `u.(A.T)`.\n  // So the result of the qualified member access is `W.(B.U)`,\n  // and the type of `v` is the type of `W.(B.U)`, namely `type`.\n  // No substitution is performed in this step.\n  let v:! auto = u.T;\n}\n```\n\nThe more complex case of\n\n```carbon\nfn F2[Z:! B where .U = i32](x: Z);\n```\n\nis discussed later.\n\n### Type substitution\n\nAt various points during the type-checking of a Carbon program, we need to\nsubstitute a set of (binding, value) pairs into a symbolic constant. We saw an\nexample above: substituting `Self = W` into the type `A where .(A.T) = Self.U`\nto produce the value `A where .(A.T) = W.U`. Another important case is the\nsubstitution of inferred parameter values into the type of a function when\ntype-checking a function call:\n\n```carbon\nfn F[T:! C](x: T) -> T;\nfn G(n: i32) -> i32 {\n  // Deduces T = i32, which is substituted\n  // into the type `fn (x: T) -> T` to produce\n  // `fn (x: i32) -> i32`, giving `i32` as the type\n  // of the call expression.\n  return F(n);\n}\n```\n\nQualified name lookup is not re-done as a result of type substitution. For a\ntemplate, we imagine there’s a completely separate step that happens before type\nsubstitution, where qualified name lookup is redone based on the actual value of\ntemplate arguments; this proceeds as described in the previous section.\nOtherwise, we performed the qualified name lookup when type-checking symbolic\nexpressions, and do not do it again:\n\n```carbon\ninterface IfaceHasX {\n  let X:! type;\n}\nclass ClassHasX {\n  class X {}\n}\ninterface HasAssoc {\n  let Assoc:! IfaceHasX;\n}\n\n// Qualified name lookup finds `T.(HasAssoc.Assoc).(IfaceHasX.X)`.\nfn F(T:! HasAssoc) -> T.Assoc.X;\n\nfn G(T:! HasAssoc where .Assoc = ClassHasX) {\n  // `T.Assoc` rewritten to `ClassHasX` by qualified name lookup.\n  // Names `ClassHasX.X`.\n  var a: T.Assoc.X = {};\n  // Substitution produces `ClassHasX.(IfaceHasX.X)`,\n  // not `ClassHasX.X`.\n  var b: auto = F(T);\n}\n```\n\nDuring substitution, we might find a member access that named an opaque symbolic\nassociated constant in the original value can now be resolved to some specific\nvalue. It’s important that we perform this resolution:\n\n```carbon\ninterface A {\n  let T:! type;\n}\nclass K { fn Member(); }\nfn H[U:! A](x: U) -> U.T;\nfn J[V:! A where .T = K](y: V) {\n  // We need the interface of `H(y)` to include\n  // `K.Member` in order for this lookup to succeed.\n  H(y).Member();\n}\n```\n\nThe values being substituted into the symbolic constant are themselves already\nfully substituted and resolved, and in particular, satisfy property 1 given\nabove.\n\nSubstitution proceeds by recursively rebuilding each symbolic constant,\nbottom-up, replacing each substituted binding with its value. Doing this naively\nwill propagate values like `i32` in the `F`/`G` case earlier in this section,\nbut will not propagate rewrite constants like in the `H`/`J` case. The reason is\nthat the `.T = K` constraint is in the _type_ of the substituted value, rather\nthan in the substituted value itself: deducing `T = i32` and converting `i32` to\nthe type `C` of `T` preserves the value `i32`, but deducing `U = V` and\nconverting `V` to the type `A` of `U` discards the rewrite constraint.\n\nIn order to apply rewrites during substitution, we associate a set of rewrites\nwith each value produced by the recursive rebuilding procedure. This is somewhat\nlike having substitution track a refined facet type for the type of each value,\nbut we don’t need -- or want -- for the type to change during this process, only\nfor the rewrites to be properly applied. For a substituted binding, this set of\nrewrites is the rewrites found on the type of the corresponding value prior to\nconversion to the type of the binding. When rebuilding a member access\nexpression, if we have a rewrite corresponding to the accessed member, then the\nresulting value is the target of the rewrite, and its set of rewrites is that\nfound in the type of the target of the rewrite, if any. Because the target of\nthe rewrite is fully resolved already, we can ask for its type without\ntriggering additional work. In other cases, the rewrite set is empty; all\nnecessary rewrites were performed when type-checking the value we're\nsubstituting into.\n\nContinuing an example from [qualified name lookup](#qualified-name-lookup):\n\n```carbon\ninterface A {\n  let T:! type;\n}\ninterface B {\n  let U:! type;\n  let V:! A where .T = U;\n}\n\n// Type of the expression `Z` is `B where .(B.U) = i32`\nfn F2[Z:! B where .U = i32](x: Z) {\n  // The type of the expression `Z` is `B where .U = i32`.\n  // `Z.V` is looked up and finds the associated facet `(B.V)`.\n  // The declared type is `A where .(A.T) = Self.U`.\n  // We substitute `Self = Z` with rewrite `.U = i32`.\n  // The resulting type is `A where .(A.T) = i32`.\n  // So `u` is `Z.V` with type `A where .(A.T) = i32`.\n  let u:! auto = Z.V;\n  // The type of `u` is `A where .(A.T) = i32`.\n  // Lookup for `u.T` resolves it to `u.(A.T)`.\n  // So the result of the qualified member access is `i32`,\n  // and the type of `v` is the type of `i32`, namely `type`.\n  // No substitution is performed in this step.\n  let v:! auto = u.T;\n}\n```\n\n### Examples\n\n```carbon\ninterface Container {\n  let Element:! type;\n}\ninterface SliceableContainer {\n  extend Container;\n  let Slice:! Container where .Element = Self.(Container.Element);\n}\n// ❌ Qualified name lookup rewrites this facet type to\n// `SliceableContainer where .(Container.Element) = .Self.(Container.Element)`.\n// Constraint resolution rejects this because this rewrite forms a cycle.\nfn Bad[T:! SliceableContainer where .Element = .Slice.Element](x: T.Element) {}\n```\n\n```carbon\ninterface Helper {\n  let D:! type;\n}\ninterface Example {\n  let B:! type;\n  let C:! Helper where .D = B;\n}\n// ✅ `where .D = ...` by itself is fine.\n// `T.C.D` is rewritten to `T.B`.\nfn Allowed(T:! Example, x: T.C.D);\n// ❌ But combined with another rewrite, creates an infinite loop.\n// `.C.D` is rewritten to `.B`, resulting in `where .B = .B`,\n// which causes an error during constraint resolution.\n// Using `==` instead of `=` would make this constraint redundant,\n// rather than it being an error.\nfn Error(T:! Example where .B = .C.D, x: T.C.D);\n```\n\n```carbon\ninterface Allowed;\ninterface AllowedBase {\n  let A:! Allowed;\n}\ninterface Allowed {\n  extend AllowedBase where .A = .Self;\n}\n// ✅ The final type of `x` is `T`. It is computed as follows:\n// In `((T.A).A).A`, the inner `T.A` is rewritten to `T`,\n// resulting in `((T).A).A`, which is then rewritten to\n// `(T).A`, which is then rewritten to `T`.\nfn F(T:! Allowed, x: ((T.A).A).A);\n```\n\n```carbon\ninterface MoveYsRight;\nconstraint ForwardDeclaredConstraint(X:! MoveYsRight);\ninterface MoveYsRight {\n  let X:! MoveYsRight;\n  // Means `Y:! MoveYsRight where .X = X.Y`\n  let Y:! ForwardDeclaredConstraint(X);\n}\nconstraint ForwardDeclaredConstraint(X:! MoveYsRight) {\n  extend MoveYsRight where .X = X.Y;\n}\n// ✅ The final type of `x` is `T.X.Y.Y`. It is computed as follows:\n// The type of `T` is `MoveYsRight`.\n// The type of `T.Y` is determined as follows:\n// -   Qualified name lookup finds `MoveYsRight.Y`.\n// -   The declared type is `ForwardDeclaredConstraint(Self.X)`.\n// -   That is a named constraint, for which we perform substitution.\n//     Substituting `X = Self.X` gives the type\n//     `MoveYsRight where .X = Self.X.Y`.\n// -   Substituting `Self = T` gives the type\n//     `MoveYsRight where .X = T.X.Y`.\n// The type of `T.Y.Y` is determined as follows:\n// -   Qualified name lookup finds `MoveYsRight.Y`.\n// -   The declared type is `ForwardDeclaredConstraint(Self.X)`.\n// -   That is a named constraint, for which we perform substitution.\n//     Substituting `X = Self.X` gives the type\n//     `MoveYsRight where .X = Self.X.Y`.\n// -   Substituting `Self = T.Y` with\n//     rewrite `.X = T.X.Y` gives the type\n//     `MoveYsRight where .X = T.Y.X.Y`, but\n//     `T.Y.X` is replaced by `T.X.Y`, giving\n//     `MoveYsRight where .X = T.X.Y.Y`.\n// The type of `T.Y.Y.X` is determined as follows:\n// -   Qualified name lookup finds `MoveYsRight.X`.\n// -   The type of `T.Y.Y` says to rewrite that to `T.X.Y.Y`.\n// -   The result is `T.X.Y.Y`, of type `MoveYsRight`.\nfn F4(T:! MoveYsRight, x: T.Y.Y.X);\n```\n\n### Termination\n\nEach of the above steps performs at most one rewrite, and doesn't introduce any\nnew recursive type-checking steps, so should not introduce any new forms of\nnon-termination. Rewrite constraints thereby give us a deterministic,\nterminating type canonicalization mechanism for associated constants: in `A.B`,\nif the type of `A` specifies that `.B = C`, then `A.B` is replaced by `C`.\nEquality of types constrained in this way is transitive.\n\nHowever, some existing forms of non-termination may remain, such as template\ninstantiation triggering another template instantiation. Such cases will need to\nbe detected and handled in some way, such as by a depth limit, but doing so\ndoesn't compromise the soundness of the type system.\n"
  },
  {
    "path": "docs/design/generics/appendix-witness.md",
    "content": "# Generics appendix: Witness tables\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Terminology](#terminology)\n    -   [Witness tables](#witness-tables)\n    -   [Dynamic-dispatch witness table](#dynamic-dispatch-witness-table)\n    -   [Static-dispatch witness table](#static-dispatch-witness-table)\n-   [Limitations of witness tables](#limitations-of-witness-tables)\n    -   [Associated constants](#associated-constants)\n    -   [Blanket implementations](#blanket-implementations)\n    -   [Specialization](#specialization)\n    -   [Calling templated functions](#calling-templated-functions)\n-   [Implementing some Carbon generic features with witness tables](#implementing-some-carbon-generic-features-with-witness-tables)\n    -   [Overview](#overview-1)\n    -   [Example](#example)\n    -   [Associated facets example](#associated-facets-example)\n\n<!-- tocstop -->\n\n## Overview\n\nWitness tables are a strategy for implementing generics, specifically for\nallowing the behavior of a generic function to vary with the values of generic\nparameters. They have some nice properties:\n\n-   They can be used both for runtime and compile-time dispatch.\n-   They can support separate compilation even with compile-time dispatch.\n\nHowever, it can be a challenge to implement some features of a generic system\nwith witness tables. This leads to limitations on the generic system, additional\nruntime overhead, or both.\n\nSwift uses witness tables for both static and dynamic dispatch, accepting both\nlimitations and overhead. Carbon and Rust only use witness tables for dynamic\ndispatch, and apply limitations to control the runtime overhead when using that\nfeature. As an implementation detail, Carbon compilers might also use witness\ntables for static dispatch, for example when the code conforms to the\nlimitations of what witness tables support. However, part of the point of this\ndocument is to state the limitations and obstacles of doing that.\n\n## Terminology\n\n### Witness tables\n\n[Witness tables](https://forums.swift.org/t/where-does-the-term-witness-table-come-from/54334/4)\nare an implementation strategy where values passed to a compile-time type\nbinding are compiled into a table of required functionality. That table is then\nfilled in for a given passed-in type with references to the implementation on\nthe original type. The generic is implemented using calls into entries in the\nwitness table, which turn into calls to the original type. This doesn't\nnecessarily imply a runtime indirection: it may be a purely compile-time\nseparation of concerns. However, it insists on a full abstraction boundary\nbetween the generic user of a type and the concrete implementation.\n\nA simple way to imagine a witness table is as a struct of function pointers, one\nper method in the interface. However, in practice, it's more complex because it\nmust model things like associated facets and interfaces.\n\nWitness tables are called \"dictionary passing\" in Haskell. Outside of generics,\na [vtable](https://en.wikipedia.org/wiki/Virtual_method_table) is very similar\nto a witness table, \"witnessing\" the specific descendant of a base class.\nVtables, however, are passed as part of the object instead of separately.\n\n### Dynamic-dispatch witness table\n\nFor dynamic-dispatch witness tables, actual function pointers are formed and\nused as a dynamic, runtime indirection. As a result, the generic code **will\nnot** be duplicated for different witness tables.\n\n### Static-dispatch witness table\n\nFor static-dispatch witness tables, the implementation is required to collapse\nthe table indirections at compile time. As a result, the generic code **will**\nbe duplicated for different witness tables.\n\nStatic-dispatch may be implemented as a performance optimization for\ndynamic-dispatch that increases generated code size. The final compiled output\nmay not retain the witness table.\n\n## Limitations of witness tables\n\n### Associated constants\n\nAn interface with associated constants can use that to allow the signature of a\nfunction to vary. A similar issue arises with argument and return values\ninvolving `Self`. This adds to the cost of calling such functions, for example\nif they are not passed by pointer, then the generated code must support\narguments and return values with a size only known at runtime.\n\nFor this reason, Rust's dynamic trait dispatch system, trait objects, only works\nwith traits that are\n[\"dyn-compatible,\"](https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility)\nwhich includes a requirement that\n[all the associated types have specified values](https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md#trait-objects).\nThis reduces the expressivity of Rust traits to the subset that could be\nsupported by a C++ abstract base class.\n\nSwift instead supports types with size only known at runtime for its\n[ABI stability and dynamic linking features](https://faultlore.com/blah/swift-abi/#what-is-abi-stability-and-dynamic-linking),\nand can use that to\n[support more generic features with dynamic dispatch](https://faultlore.com/blah/swift-abi/#polymorphic-generics).\nThis comes with runtime overhead.\n\n### Blanket implementations\n\n[Blanket implementations](details.md#blanket-impl-declarations) allow you define\nan implementation of interface `Y` for any type implementing interface `X`. This\nallows a function to use the functionality of `Y` while only having a\nrequirement that `X` be implemented. This creates the problem of how to go from\na witness table for `X` to a witness table for `Y`.\n\nRust supports blanket implementations using monomorphization, but this only\nworks with static dispatch. Swift does not support blanket implementations. This\nis possibly a result of the limitations of using witness tables to implement\ngenerics.\n\n### Specialization\n\nSpecialization compounds the difficulty of the previous two issues.\n\nAn interface with an associated facet might be implemented using witness tables\nby including a reference to the associated facet's witness table in the witness\ntable for the interface. This doesn't, though, give you a witness table for\nparameterized types using the associated facet as an argument. Synthesizing\nthose witness tables is particularly tricky if the implementation is different\nfor specific types due to specialization.\n\nSimilarly, a blanket implementation can guarantee that some implementation of an\ninterface exists. Specialization means that actual implementation of that\ninterface for specific types is not the one given by the blanket implementation.\nFurthermore, that specialized implementation may be in an unrelated library.\nThey may be found anywhere in the program, not necessarily in the dependencies\nof the code that needs to use a particular witness table.\n\nAs a result, specialization is not supported by Swift, which uses witness\ntables. Specialization is being considered for Rust, and is compatible with its\nmonomorphization model used for static dispatch.\n\n### Calling templated functions\n\nCarbon's planned approach to support calling a templated function from a\nchecked-generic function, decided in\n[issue #2153](https://github.com/carbon-language/carbon-lang/issues/2153),\nrelies on monomorphization. Trying to rely on witness tables would result in\ndifferent semantics for calling the same function with the same types, depending\non which witness tables were available at the callsite.\n\n## Implementing some Carbon generic features with witness tables\n\n### Overview\n\nA possible model for generating code for a generic function is to use a\n[witness table](#witness-tables) to represent how a type implements an\ninterface:\n\n-   [Interfaces](details.md#interfaces) are types of witness tables.\n-   An [impl](details.md#implementing-interfaces) is a witness table value.\n\nWe can think of the interface as defining a struct type with a field for every\ninterface member. An implementation of that interface for a type is a value of\nthat struct type, which we call a witness or witness table. For example, the\nfunction and method members of an interface correspond to function pointer\nfields. An implementation will have function pointer values pointing to the\nfunctions defining the implementation of that interface for a given type. This\nis like a [vtable](https://en.wikipedia.org/wiki/Virtual_method_table), except\nstored separately from the object.\n\nA witness might\n[have references to other witness tables](#associated-facets-example), in order\nto support these interface features and members:\n\n-   [associated facets](details.md#associated-facets)\n-   [type parameters](details.md#parameterized-interfaces)\n-   [interface requirements](details.md#interface-requiring-other-interfaces)\n\nIt also could contain constants, to store the values of\n[associated constants](details.md#associated-constants), or the type's size.\n\n### Example\n\nFor example, this `Vector` interface:\n\n```carbon\ninterface Vector {\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: f64) -> Self;\n}\n```\n\nfrom [the generic details design](details.md#interfaces) could be thought of\ndefining a witness table type like:\n\n```\nclass Vector {\n  // `Self` is the representation type, which is only\n  // known at compile time.\n  var Self:! type;\n  // `fnty` is placeholder syntax for a \"function type\",\n  // so `Add` is a function that takes two `Self` parameters\n  // and returns a value of type `Self`.\n  var Add: fnty(a: Self, b: Self) -> Self;\n  var Scale: fnty(a: Self, v: f64) -> Self;\n}\n```\n\nThe [`impl` definition of `Vector` for `Point_Inline`](details.md#inline-impl)\nwould be a value of this type:\n\n```\nvar VectorForPoint_Inline: Vector  = {\n    .Self = Point_Inline,\n    // `lambda` is placeholder syntax for defining a\n    // function value.\n    .Add = lambda(a: Point_Inline, b: Point_Inline) -> Point_Inline {\n      return {.x = a.x + b.x, .y = a.y + b.y};\n    },\n    .Scale = lambda(a: Point_Inline, v: f64) -> Point_Inline {\n      return {.x = a.x * v, .y = a.y * v};\n    },\n};\n```\n\nSince generic arguments (where the parameter is declared using `:!`) are passed\nat compile time, the actual value of `VectorForPoint_Inline` can be used to\ngenerate the code for functions using that impl.\n\n### Associated facets example\n\nThe associated facet can be modeled by a witness table field in the interface's\nwitness table.\n\n```\ninterface Iterator {\n  fn Advance[ref self: Self]();\n}\n\ninterface Container {\n  let IteratorType:! Iterator;\n  fn Begin[ref self: Self]() -> IteratorType;\n}\n```\n\ncould be represented by:\n\n```\nclass Iterator {\n  var Self:! type;\n  var Advance: fnty(this: Self*);\n  ...\n}\nclass Container {\n  var Self:! type;\n\n  // Witness that IteratorType implements Iterator.\n  var IteratorType:! Iterator*;\n\n  // Method\n  var Begin: fnty (this: Self*) -> IteratorType->Self;\n  ...\n}\n```\n"
  },
  {
    "path": "docs/design/generics/details.md",
    "content": "# Generics: Details\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Interfaces](#interfaces)\n-   [Implementing interfaces](#implementing-interfaces)\n    -   [Inline `impl`](#inline-impl)\n    -   [`extend impl`](#extend-impl)\n    -   [Out-of-line `impl`](#out-of-line-impl)\n        -   [Defining an `impl` in another library than the type](#defining-an-impl-in-another-library-than-the-type)\n    -   [Forward `impl` declaration](#forward-impl-declaration)\n    -   [Implementing multiple interfaces](#implementing-multiple-interfaces)\n    -   [Avoiding name collisions](#avoiding-name-collisions)\n    -   [Qualified member names and compound member access](#qualified-member-names-and-compound-member-access)\n    -   [Access](#access)\n-   [Checked-generic functions](#checked-generic-functions)\n    -   [Symbolic facet bindings](#symbolic-facet-bindings)\n    -   [Return type](#return-type)\n-   [Interfaces recap](#interfaces-recap)\n-   [Facet types](#facet-types)\n-   [Named constraints](#named-constraints)\n    -   [Subtyping between facet types](#subtyping-between-facet-types)\n-   [Combining interfaces by anding facet types](#combining-interfaces-by-anding-facet-types)\n-   [Interface requiring other interfaces](#interface-requiring-other-interfaces)\n    -   [Interface extension](#interface-extension)\n        -   [`extend require` with named constraints](#extend-require-with-named-constraints)\n        -   [Diamond dependency issue](#diamond-dependency-issue)\n    -   [Use case: detecting unreachable matches](#use-case-detecting-unreachable-matches)\n-   [Adapting types](#adapting-types)\n    -   [Adapter compatibility](#adapter-compatibility)\n    -   [Extending adapter](#extending-adapter)\n    -   [Use case: Using independent libraries together](#use-case-using-independent-libraries-together)\n    -   [Use case: Defining an impl for use by other types](#use-case-defining-an-impl-for-use-by-other-types)\n    -   [Use case: Private impl](#use-case-private-impl)\n    -   [Use case: Accessing interface names](#use-case-accessing-interface-names)\n    -   [Future work: Adapter with stricter invariants](#future-work-adapter-with-stricter-invariants)\n-   [Associated constants](#associated-constants)\n    -   [Associated class functions](#associated-class-functions)\n-   [Associated facets](#associated-facets)\n-   [Parameterized interfaces](#parameterized-interfaces)\n    -   [Parameterized named constraints](#parameterized-named-constraints)\n-   [Where constraints](#where-constraints)\n    -   [Kinds of `where` constraints](#kinds-of-where-constraints)\n        -   [Recursive constraints](#recursive-constraints)\n        -   [Rewrite constraints](#rewrite-constraints)\n        -   [Same-type constraints](#same-type-constraints)\n            -   [Implementation of same-type `ImplicitAs`](#implementation-of-same-type-implicitas)\n            -   [Manual type equality](#manual-type-equality)\n            -   [Observe declarations](#observe-declarations)\n        -   [Implements constraints](#implements-constraints)\n            -   [Implied constraints](#implied-constraints)\n        -   [Combining constraints](#combining-constraints)\n    -   [Satisfying both facet types](#satisfying-both-facet-types)\n    -   [Constraints must use a designator](#constraints-must-use-a-designator)\n    -   [Referencing names in the interface being defined](#referencing-names-in-the-interface-being-defined)\n    -   [Constraint examples and use cases](#constraint-examples-and-use-cases)\n        -   [Parameterized type implements interface](#parameterized-type-implements-interface)\n        -   [Another type implements parameterized interface](#another-type-implements-parameterized-interface)\n        -   [Must be legal type argument constraints](#must-be-legal-type-argument-constraints)\n    -   [Named constraint constants](#named-constraint-constants)\n-   [Other constraints as facet types](#other-constraints-as-facet-types)\n    -   [Is a derived class](#is-a-derived-class)\n    -   [Type compatible with another type](#type-compatible-with-another-type)\n        -   [Same implementation restriction](#same-implementation-restriction)\n        -   [Example: Multiple implementations of the same interface](#example-multiple-implementations-of-the-same-interface)\n        -   [Example: Creating an impl out of other implementations](#example-creating-an-impl-out-of-other-implementations)\n    -   [Sized types and facet types](#sized-types-and-facet-types)\n    -   [Destructor constraints](#destructor-constraints)\n-   [Compile-time `let`](#compile-time-let)\n-   [Parameterized impl declarations](#parameterized-impl-declarations)\n    -   [Impl for a parameterized type](#impl-for-a-parameterized-type)\n    -   [Conditional conformance](#conditional-conformance)\n    -   [Blanket impl declarations](#blanket-impl-declarations)\n        -   [Difference between a blanket impl and a named constraint](#difference-between-a-blanket-impl-and-a-named-constraint)\n    -   [Wildcard impl declarations](#wildcard-impl-declarations)\n    -   [Combinations](#combinations)\n    -   [Lookup resolution and specialization](#lookup-resolution-and-specialization)\n        -   [Type structure of an impl declaration](#type-structure-of-an-impl-declaration)\n        -   [Orphan rule](#orphan-rule)\n        -   [Overlap rule](#overlap-rule)\n        -   [Prioritization rule](#prioritization-rule)\n        -   [Acyclic rule](#acyclic-rule)\n        -   [Termination rule](#termination-rule)\n            -   [Non-facet arguments](#non-facet-arguments)\n    -   [`final` impl declarations](#final-impl-declarations)\n        -   [Libraries that can contain a `final` impl](#libraries-that-can-contain-a-final-impl)\n    -   [Comparison to Rust](#comparison-to-rust)\n-   [Forward declarations and cyclic references](#forward-declarations-and-cyclic-references)\n    -   [Declaring interfaces and named constraints](#declaring-interfaces-and-named-constraints)\n    -   [Declaring implementations](#declaring-implementations)\n    -   [Matching and agreeing](#matching-and-agreeing)\n    -   [Declaration examples](#declaration-examples)\n    -   [Example of declaring interfaces with cyclic references](#example-of-declaring-interfaces-with-cyclic-references)\n    -   [Interfaces with parameters constrained by the same interface](#interfaces-with-parameters-constrained-by-the-same-interface)\n-   [Interface members with definitions](#interface-members-with-definitions)\n    -   [Interface defaults](#interface-defaults)\n    -   [`final` members](#final-members)\n-   [Interface requiring other interfaces revisited](#interface-requiring-other-interfaces-revisited)\n    -   [Requirements with `where` constraints](#requirements-with-where-constraints)\n-   [Observing a type implements an interface](#observing-a-type-implements-an-interface)\n    -   [Observing interface requirements](#observing-interface-requirements)\n    -   [Observing blanket impl declarations](#observing-blanket-impl-declarations)\n    -   [Observing equal to a type implementing an interface](#observing-equal-to-a-type-implementing-an-interface)\n-   [Operator overloading](#operator-overloading)\n    -   [Binary operators](#binary-operators)\n    -   [`like` operator for implicit conversions](#like-operator-for-implicit-conversions)\n-   [Parameterized types](#parameterized-types)\n    -   [Generic methods](#generic-methods)\n    -   [Conditional methods](#conditional-methods)\n    -   [Specialization](#specialization)\n-   [Future work](#future-work)\n    -   [Dynamic types](#dynamic-types)\n        -   [Runtime type parameters](#runtime-type-parameters)\n        -   [Runtime type fields](#runtime-type-fields)\n    -   [Abstract return types](#abstract-return-types)\n    -   [Evolution](#evolution)\n    -   [Testing](#testing)\n    -   [Impl with state](#impl-with-state)\n    -   [Generic associated facets and higher-ranked facets](#generic-associated-facets-and-higher-ranked-facets)\n        -   [Generic associated facets](#generic-associated-facets)\n        -   [Higher-ranked types](#higher-ranked-types)\n    -   [Field requirements](#field-requirements)\n    -   [Bridge for C++ customization points](#bridge-for-c-customization-points)\n    -   [Variadic arguments](#variadic-arguments)\n    -   [Value constraints for template parameters](#value-constraints-for-template-parameters)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nThis document goes into the details of the design of Carbon's\n[generics](terminology.md#generic-means-compile-time-parameterized), by which we\nmean generalizing some language construct with compile-time parameters. These\nparameters can be types, [facets](terminology.md#facet), or other values.\n\nImagine we want to write a function with a type (or facet) parameter. Maybe our\nfunction is `PrintToStdout` and let's say we want to operate on values that have\na type for which we have an implementation of the `ConvertibleToString`\ninterface. The `ConvertibleToString` interface has a `ToString` method returning\na string. To do this, we give the `PrintToStdout` function two parameters: one\nis the value to print, let's call that `val`, the other is the type of that\nvalue, let's call that `T`. The type of `val` is `T`, what is the type of `T`?\nWell, since we want to let `T` be any type implementing the\n`ConvertibleToString` interface, we express that in the \"interfaces are facet\ntypes\" model by saying the type of `T` is `ConvertibleToString`.\n\nSince we can figure out `T` from the type of `val`, we don't need the caller to\npass in `T` explicitly, so it can be a\n[deduced parameter](terminology.md#deduced-parameter) (also see\n[deduced parameters](overview.md#deduced-parameters) in the Generics overview\ndoc). Basically, the user passes in a value for `val`, and the type of `val`\ndetermines `T`. `T` still gets passed into the function though, and it plays an\nimportant role -- it defines the key used to look up interface implementations.\n\nThat interface implementation has the definitions of the functions declared in\nthe interface. For example, the types `i32` and `String` would have different\nimplementations of the `ToString` method of the `ConvertibleToString` interface.\n\nIn addition to function members, interfaces can include other members that\nassociate a [compile-time value](/docs/design/README.md#expression-phases) for\nany implementing type, called _associated constants_. For example, this can\nallow a container interface to include the type of iterators that are returned\nfrom and passed to various container methods.\n\nThe function expresses that the type argument is passed in statically, basically\ngenerating a separate function body for every different type passed in, by using\nthe \"compile-time parameter\" syntax `:!`. By default, this defines a\n[checked-generics parameter](#checked-generic-functions) below. In this case,\nthe interface contains enough information to\n[type and definition check](terminology.md#complete-definition-checking) the\nfunction body -- you can only call functions defined in the interface in the\nfunction body.\n\nAlternatively, the `template` keyword can be included in the signature to make\nthe type a template parameter. In this case, you could just use `type` instead\nof an interface and it will work as long as the function is only called with\ntypes that allow the definition of the function to compile.\n\nThe interface bound has other benefits:\n\n-   allows the compiler to deliver clearer error messages,\n-   documents expectations, and\n-   expresses that a type has certain semantics beyond what is captured in its\n    member function names and signatures.\n\nThe last piece of the puzzle is calling the function. For a value of type `Song`\nto be printed using the `PrintToStdout` function, `Song` needs to implement the\n`ConvertibleToString` interface. Interface implementations will usually be\ndefined either with the type or with the interface. They may also be defined\nsomewhere else as long as Carbon can be guaranteed to see the definition when\nneeded. For more on this, see\n[the implementing interfaces section](#implementing-interfaces) below.\n\nWhen the implementation of `ConvertibleToString` for `Song` is declared with\n`extend`, every member of `ConvertibleToString` is also a member of `Song`. This\nincludes members of `ConvertibleToString` that are not explicitly named in the\n`impl` definition but have defaults. Whether the type\n[extends the implementation](terminology.md#extending-an-impl) or not, you may\naccess the `ToString` function for a `Song` value `s` by a writing function call\n[using a qualified member access expression](terminology.md#qualified-member-access-expression),\nlike `s.(ConvertibleToString.ToString)()`.\n\nIf `Song` doesn't implement an interface or we would like to use a different\nimplementation of that interface, we can define another type that also has the\nsame data representation as `Song` that has whatever different interface\nimplementations we want. However, Carbon won't implicitly convert to that other\ntype, the user will have to explicitly cast to that type in order to select\nthose alternate implementations. For more on this, see\n[the adapting type section](#adapting-types) below.\n\nWe originally considered following Swift and using a witness table\nimplementation strategy for checked generics, but ultimately decided to only use\nthat for the dynamic-dispatch case. This is because of the limitations of that\nstrategy prevent some features that we considered important, as described in\n[the witness-table appendix](appendix-witness.md).\n\n## Interfaces\n\nAn [interface](terminology.md#interface), defines an API that a given type can\nimplement. For example, an interface capturing a linear-algebra vector API might\nhave two methods:\n\n```carbon\ninterface Vector {\n  // Here the `Self` keyword means\n  // \"the type implementing this interface\".\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: f64) -> Self;\n}\n```\n\nThe syntax here is to match\n[how the same members would be defined in a type](/docs/design/classes.md#methods).\nEach declaration in the interface defines an\n[associated entity](terminology.md#associated-entity). In this example, `Vector`\nhas two associated methods, `Add` and `Scale`. A type\n[implements an interface](#implementing-interfaces) by providing definitions for\nall the associated entities declared in the interface,\n\nAn interface defines a [facet type](terminology.md#facet-type), that is a type\nwhose values are [facets](terminology.md#facet). Every type implementing the\ninterface has a corresponding facet value. So if the type `Point` implements\ninterface `Vector`, the facet value `Point as Vector` has type `Vector`.\n\n## Implementing interfaces\n\nCarbon interfaces are [\"nominal\"](terminology.md#nominal-interfaces), which\nmeans that types explicitly describe how they implement interfaces. An\n[\"impl\"](terminology.md#impl-implementation-of-an-interface) defines how one\ninterface is implemented for a type, called the _implementing type_. Every\nassociated entity is given a definition. Different types satisfying `Vector` can\nhave different definitions for `Add` and `Scale`, so we say their definitions\nare _associated_ with what type is implementing `Vector`. The `impl` defines\nwhat is associated with the implementing type for that interface.\n\n### Inline `impl`\n\nAn impl may be defined inline inside the type definition:\n\n```carbon\nclass Point_Inline {\n  var x: f64;\n  var y: f64;\n  impl as Vector {\n    // In this scope, the `Self` keyword is an\n    // alias for `Point_Inline`.\n    fn Add[self: Self](b: Self) -> Self {\n      return {.x = self.x + b.x, .y = self.y + b.y};\n    }\n    fn Scale[self: Self](v: f64) -> Self {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n  }\n}\n```\n\n### `extend impl`\n\nInterfaces that are implemented inline with the `extend` keyword contribute to\nthe type's API:\n\n```carbon\nclass Point_Extend {\n  var x: f64;\n  var y: f64;\n  extend impl as Vector {\n    fn Add[self: Self](b: Self) -> Self {\n      return {.x = self.x + b.x, .y = self.y + b.y};\n    }\n    fn Scale[self: Self](v: f64) -> Self {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n  }\n}\n\nvar p1: Point_Extend = {.x = 1.0, .y = 2.0};\nvar p2: Point_Extend = {.x = 2.0, .y = 4.0};\nAssert(p1.Scale(2.0) == p2);\nAssert(p1.Add(p1) == p2);\n```\n\nWithout `extend`, those methods may only be accessed with\n[qualified member names and compound member access](#qualified-member-names-and-compound-member-access):\n\n```carbon\n// Point_Inline did not use `extend` when\n// implementing `Vector`:\nvar a: Point_Inline = {.x = 1.0, .y = 2.0};\n// `a` does *not* have `Add` and `Scale` methods:\n// ❌ Error: a.Add(a.Scale(2.0));\n```\n\nThis is consistent with the general Carbon rule that if the names of another\nentity affect a class' API, then that is mentioned with an `extend` declaration\nin the `class` definition.\n\n**Comparison with other languages:** Rust only defines implementations lexically\noutside of the `class` definition. Carbon's approach results in the property\nthat every type's API is described by declarations inside its `class` definition\nand doesn't change afterwards.\n\n**References:** Carbon's interface implementation syntax was first defined in\n[proposal #553](https://github.com/carbon-language/carbon-lang/pull/553). In\nparticular, see\n[the alternatives considered](/proposals/p0553.md#interface-implementation-syntax).\nThis syntax was changed to use `extend` in\n[proposal #2760: Consistent `class` and `interface` syntax](https://github.com/carbon-language/carbon-lang/pull/2760).\n\n### Out-of-line `impl`\n\nAn impl may also be defined after the type definition, by naming the type\nbetween `impl` and `as`:\n\n```carbon\nclass Point_OutOfLine {\n  var x: f64;\n  var y: f64;\n}\n\nimpl Point_OutOfLine as Vector {\n  // In this scope, the `Self` keyword is an\n  // alias for `Point_OutOfLine`.\n  fn Add[self: Self](b: Self) -> Self {\n    return {.x = self.x + b.x, .y = self.y + b.y};\n  }\n  fn Scale[self: Self](v: f64) -> Self {\n    return {.x = self.x * v, .y = self.y * v};\n  }\n}\n```\n\nSince `extend impl` may only be used inside the class definition, out-of-line\ndefinitions do not contribute to the class's API unless there is a corresponding\n[forward declaration in the class definition using `extend`](#forward-impl-declaration).\n\nConversely, being declared or defined lexically inside the class means that\nimplementation is available to other members defined in the class. For example,\nit would allow implementing another interface or method that requires this\ninterface to be implemented.\n\n**Open question:** Do implementations need to be defined lexically inside the\nclass to get access to private members, or is it sufficient to be defined in the\nsame library as the class?\n\n**Comparison with other languages:** Both Rust and Swift support out-of-line\nimplementation.\n[Swift's syntax](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID277)\ndoes this as an \"extension\" of the original type. In Rust, all implementations\nare out-of-line as in\n[this example](https://doc.rust-lang.org/rust-by-example/trait.html). Unlike\nSwift and Rust, we don't allow a type's API to be modified outside its\ndefinition. So in Carbon a type's API is consistent no matter what is imported,\nunlike Swift and Rust.\n\n#### Defining an `impl` in another library than the type\n\nAn out-of-line `impl` declaration is allowed to be defined in a different\nlibrary from `Point_OutOfLine`, restricted by\n[the coherence/orphan rules](#orphan-rule) that ensure that the implementation\nof an interface can't change based on imports. In particular, the `impl`\ndeclaration is allowed in the library defining the interface (`Vector` in this\ncase) in addition to the library that defines the type (`Point_OutOfLine` here).\nThis (at least partially) addresses\n[the expression problem](https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions).\n\nYou can't use `extend` outside the class definition, so an `impl` declaration in\na different library will never affect the class's API. This means that the API\nof a class such as `Point_OutOfLine` doesn't change based on what is imported.\nIt would be particularly bad if two different libraries implemented interfaces\nwith conflicting names that both affected the API of a single type. As a\nconsequence of this restriction, you can find all the names of direct members\n(those available by [simple member access](terminology.md#simple-member-access))\nof a type in the definition of that type and entities referenced in by an\n`extend` declaration in that definition. The only thing that may be in another\nlibrary is an `impl` of an interface.\n\n**Rejected alternative:** We could allow types to have different APIs in\ndifferent files based on explicit configuration in that file. For example, we\ncould support a declaration that a given interface or a given method of an\ninterface is \"in scope\" for a particular type in this file. With that\ndeclaration, the method could be called using\n[simple member access](terminology.md#simple-member-access). This avoids most\nconcerns arising from name collisions between interfaces. It has a few downsides\nthough:\n\n-   It increases variability between files, since the same type will have\n    different APIs depending on these declarations. This makes it harder to\n    copy-paste code between files.\n-   It makes reading code harder, since you have to search the file for these\n    declarations that affect name lookup.\n\n### Forward `impl` declaration\n\nAn `impl` declaration may be forward declared and then defined later. If this is\ndone using [`extend` to add to the type's API](#extend-impl), only the\ndeclaration in the class definition will use the `extend` keyword, as in this\nexample:\n\n```carbon\nclass Point_ExtendForward {\n  var x: f64;\n  var y: f64;\n  // Forward declaration in class definition using `extend`.\n  // Signals that you should look in the definition of\n  // `Vector` since those methods are included in this type.\n  extend impl as Vector;\n}\n\n// Definition outside class definition does not.\nimpl Point_ExtendForward as Vector {\n  fn Add[self: Self](b: Self) -> Self {\n    return {.x = self.x + b.x, .y = self.y + b.y};\n  }\n  fn Scale[self: Self](v: f64) -> Self {\n    return {.x = self.x * v, .y = self.y * v};\n  }\n}\n```\n\n> **TODO:** The second `impl` in this example is no longer a valid redeclaration\n> of the first after\n> [p5366: The name of an `impl` in `class` scope](/proposals/p5366.md).\n\nMore about forward declaring implementations in\n[its dedicated section](#declaring-implementations).\n\n### Implementing multiple interfaces\n\nTo implement more than one interface when defining a type, simply include an\n`impl` block or forward declaration per interface.\n\n```carbon\nclass Point_2Extend {\n  var x: f64;\n  var y: f64;\n  extend impl as Vector {\n    fn Add[self: Self](b: Self) -> Self { ... }\n    fn Scale[self: Self](v: f64) -> Self { ... }\n  }\n  extend impl as Drawable {\n    fn Draw[self: Self]() { ... }\n  }\n}\n```\n\nSince both were declared using `extend`, all the functions `Add`, `Scale`, and\n`Draw` end up a part of the API for `Point_2Extend`.\n\n**Note:** A type may implement any number of different interfaces, but may\nprovide at most one implementation of any single interface. This makes the act\nof selecting an implementation of an interface for a type unambiguous throughout\nthe whole program.\n\n**Open question:** Should we have some syntax for the case where you want both\nnames to be given the same implementation? It seems like that might be a common\ncase, but we won't really know if this is an important case until we get more\nexperience.\n\n```carbon\nclass Player {\n  var name: String;\n  extend impl as Icon {\n    fn Name[self: Self]() -> String { return self.name; }\n    // ...\n  }\n  extend impl as GameUnit {\n    // Possible syntax options for defining\n    // `GameUnit.Name` as the same as `Icon.Name`:\n    alias Name = Icon.Name;\n    fn Name[self: Self]() -> String = Icon.Name;\n    // ...\n  }\n}\n```\n\n### Avoiding name collisions\n\nTo avoid name collisions, you can't extend implementations of two interfaces\nthat have a name in common:\n\n```carbon\nclass GameBoard {\n  extend impl as Drawable {\n    fn Draw[self: Self]() { ... }\n  }\n  extend impl as EndOfGame {\n    // ❌ Error: `GameBoard` has two methods named `Draw`.\n    fn Draw[self: Self]() { ... }\n    fn Winner[self: Self](player: i32) { ... }\n  }\n}\n```\n\nTo implement two interfaces that have a name in common, omit `extend` for one or\nboth.\n\nYou might also omit `extend` when implementing an interface for a type to avoid\ncluttering the API of that type or to avoid a name collision with another member\nof that type. A syntax for reusing method implementations allows us to include\nnames from an implementation selectively:\n\n```carbon\nclass Point_ReuseMethodInImpl {\n  var x: f64;\n  var y: f64;\n  // `Add()` is a method of `Point_ReuseMethodInImpl`.\n  fn Add[self: Self](b: Self) -> Self {\n    return {.x = self.x + b.x, .y = self.y + b.y};\n  }\n  // No `extend`, so other members of `Vector` are not\n  // part of `Point_ReuseMethodInImpl`'s API.\n  impl as Vector {\n    // Syntax TBD:\n    alias Add = Point_ReuseMethodInImpl.Add;\n    fn Scale[self: Self](v: f64) -> Self {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n  }\n}\n\n// OR:\n\nclass Point_IncludeMethodFromImpl {\n  var x: f64;\n  var y: f64;\n  // No `extend`, so members of `Vector` are not\n  // part of `Point_IncludeMethodFromImpl`'s API.\n  impl as Vector {\n    fn Add[self: Self](b: Self) -> Self {\n      return {.x = self.x + b.x, .y = self.y + b.y};\n    }\n    fn Scale[self: Self](v: f64) -> Self {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n  }\n  // Include `Add` explicitly as a member.\n  alias Add = Vector.Add;\n}\n\n// OR:\n\n// This is the same as `Point_ReuseMethodInImpl`,\n// except the `impl` is out-of-line.\nclass Point_ReuseByOutOfLine {\n  var x: f64;\n  var y: f64;\n  fn Add[self: Self](b: Self) -> Self {\n    return {.x = self.x + b.x, .y = self.y + b.y};\n  }\n}\n\nimpl Point_ReuseByOutOfLine as Vector {\n  // Syntax TBD:\n  alias Add = Point_ReuseByOutOfLine.Add;\n  fn Scale[self: Self](v: f64) -> Self {\n    return {.x = self.x * v, .y = self.y * v};\n  }\n}\n```\n\n### Qualified member names and compound member access\n\n```carbon\nclass Point_NoExtend {\n  var x: f64;\n  var y: f64;\n}\n\nimpl Point_NoExtend as Vector { ... }\n```\n\nGiven a value of type `Point_NoExtend` and an interface `Vector` implemented for\nthat type, you can access the methods from that interface using a\n[qualified member access expression](terminology.md#qualified-member-access-expression)\nwhether or not the implementation is done with an\n[`extend impl` declaration](#extend-impl). The qualified member access\nexpression writes the member's _qualified name_ in the parentheses of the\n[compound member access syntax](/docs/design/expressions/member_access.md):\n\n```carbon\nvar p1: Point_NoExtend = {.x = 1.0, .y = 2.0};\nvar p2: Point_NoExtend = {.x = 2.0, .y = 4.0};\nAssert(p1.(Vector.Scale)(2.0) == p2);\nAssert(p1.(Vector.Add)(p1) == p2);\n```\n\nNote that the name in the parens is looked up in the containing scope, not in\nthe names of members of `Point_NoExtend`. So if there was another interface\n`Drawable` with method `Draw` defined in the `Plot` package also implemented for\n`Point_NoExtend`, as in:\n\n```carbon\npackage Plot;\nimport Points;\n\ninterface Drawable {\n  fn Draw[self: Self]();\n}\n\nimpl Points.Point_NoExtend as Drawable { ... }\n```\n\nYou could access `Draw` with a qualified name:\n\n```carbon\nimport Plot;\nimport Points;\n\nvar p: Points.Point_NoExtend = {.x = 1.0, .y = 2.0};\np.(Plot.Drawable.Draw)();\n```\n\n**Comparison with other languages:** This is intended to be analogous to, in\nC++, adding `ClassName::` in front of a member name to disambiguate, such as\n[names defined in both a parent and child class](https://stackoverflow.com/questions/357307/how-to-call-a-parent-class-function-from-derived-class-function).\n\n### Access\n\nAn `impl` must be visible to all code that can see both the type and the\ninterface being implemented:\n\n-   If either the type or interface is private to a single file, then since the\n    only way to define the `impl` is to use that private name, the `impl` must\n    be defined private to that file as well.\n-   Otherwise, if the type or interface is private but declared in an API file,\n    then the `impl` must be declared in the same file so the existence of that\n    `impl` is visible to all files in that library.\n-   Otherwise, the `impl` must be declared in the public API file of the\n    library, so it is visible in all places that might use it.\n\nNo access control modifiers are allowed on `impl` declarations, an `impl` is\nalways visible to the intersection of the visibility of all names used in the\ndeclaration of the `impl`.\n\n## Checked-generic functions\n\nHere is a function that can accept values of any type that has implemented the\n`Vector` interface:\n\n```carbon\nfn AddAndScaleGeneric[T:! Vector](a: T, b: T, s: f64) -> T {\n  return a.Add(b).Scale(s);\n}\nvar v: Point_Extend = AddAndScaleGeneric(a, w, 2.5);\n```\n\nHere `T` is a facet whose type is `Vector`. The `:!` syntax means that `T` is a\n_[compile-time binding](terminology.md#bindings)_. Here specifically it declares\na _symbolic binding_ since it did not use the `template` keyword to mark it as a\n_template binding_.\n\n> **References:** The `:!` syntax was accepted in\n> [proposal #676](https://github.com/carbon-language/carbon-lang/pull/676).\n\nSince this symbolic binding pattern is in a function declaration, it marks a\n_[checked](terminology.md#checked-versus-template-parameters)\n[generic parameter](terminology.md#generic-means-compile-time-parameterized)_.\nThat means its value must be known to the caller at compile-time, but we will\nonly use the information present in the signature of the function to type check\nthe body of `AddAndScaleGeneric`'s definition.\n\nNote that types may also be given compile-time parameters, see the\n[\"parameterized types\" section](#parameterized-types).\n\n### Symbolic facet bindings\n\nIn our example, `T` is a facet which may be used in type position in the rest of\nthe function. Furthermore, since it omits the keyword `template` prefix, this is\na symbolic binding. so we need to be able to typecheck the body of the function\nwithout knowing the specific value `T` from the caller.\n\nThis typechecking is done by looking at the constraint on `T`. In the example,\nthe constraint on `T` says that every value of `T` implements the `Vector`\ninterface and so has a `Vector.Add` and a `Vector.Scale` method.\n\nNames are looked up in the body of `AddAndScaleGeneric` for values of type `T`\nin `Vector`. This means that `AddAndScaleGeneric` is interpreted as equivalent\nto adding a `Vector`\n[qualification](#qualified-member-names-and-compound-member-access) to replace\nall simple member accesses of `T`:\n\n```carbon\nfn AddAndScaleGeneric[T:! Vector](a: T, b: T, s: Double) -> T {\n  return a.(Vector.Add)(b).(Vector.Scale)(s);\n}\n```\n\nWith these qualifications, the function can be type-checked for any `T`\nimplementing `Vector`. This type checking is equivalent to type checking the\nfunction with `T` set to an [archetype](terminology.md#archetype) of `Vector`.\nAn archetype is a placeholder type considered to satisfy its constraint, which\nis `Vector` in this case, and no more. It acts as the most general type\nsatisfying the interface. The effect of this is that an archetype of `Vector`\nacts like a [supertype](https://en.wikipedia.org/wiki/Subtyping) of any `T`\nimplementing `Vector`.\n\nFor name lookup purposes, an archetype is considered to\n[extend the implementation of its constraint](terminology.md#extending-an-impl).\nThe only oddity is that the archetype may have different names for members than\nspecific types `T` that don't extend the implementation of interfaces from the\nconstraint. This difference in names can also occur for supertypes in C++, for\nexample members in a derived class can hide members in the base class with the\nsame name, though it is not that common for it to come up in practice.\n\nThe behavior of calling `AddAndScaleGeneric` with a value of a specific type\nlike `Point_Extend` is to set `T` to `Point_Extend` after all the names have\nbeen qualified.\n\n```carbon\n// AddAndScaleGeneric with T = Point_Extend\nfn AddAndScaleForPoint_Extend(\n    a: Point_Extend, b: Point_Extend, s: Double)\n    -> Point_Extend {\n  return a.(Vector.Add)(b).(Vector.Scale)(s);\n}\n```\n\nThis qualification gives a consistent interpretation to the body of the function\neven when the type supplied by the caller does not\n[extend the implementation of the interface](terminology.md#extending-an-impl),\nlike `Point_NoExtend`:\n\n```carbon\n// AddAndScaleGeneric with T = Point_NoExtend\nfn AddAndScaleForPoint_NoExtend(\n    a: Point_NoExtend, b: Point_NoExtend, s: Double)\n    -> Point_NoExtend {\n  // ✅ This works even though `a.Add(b).Scale(s)` wouldn't.\n  return a.(Vector.Add)(b).(Vector.Scale)(s);\n}\n```\n\n### Return type\n\nFrom the caller's perspective, the return type is the result of substituting the\ncaller's values for the generic parameters into the return type expression. So\n`AddAndScaleGeneric` called with `Point_Extend` values returns a `Point_Extend`\nand called with `Point_NoExtend` values returns a `Point_NoExtend`. So looking\nup a member on the resulting value will look in `Point_Extend` or\n`Point_NoExtend` rather than `Vector`.\n\nThis is part of realizing\n[the goal that generic functions can be used in place of regular functions without changing the return type that callers see](goals.md#path-from-regular-functions).\nIn this example, `AddAndScaleGeneric` can be substituted for\n`AddAndScaleForPoint_Extend` and `AddAndScaleForPoint_NoExtend` without\naffecting the return types. This may require a conversion of the return value to\nthe type that the caller expects, from the erased type used inside a\nchecked-generic function.\n\nA checked-generic caller of a checked-generic function performs the same\nsubstitution process to determine the return type, but the result may be a\nsymbolic constant. In this example of calling a checked generic from another\nchecked generic,\n\n```carbon\nfn DoubleThreeTimes[U:! Vector](a: U) -> U {\n  return AddAndScaleGeneric(a, a, 2.0).Scale(2.0);\n}\n```\n\nthe return type of `AddAndScaleGeneric` is found by substituting in the `U` from\n`DoubleThreeTimes` for the `T` from `AddAndScaleGeneric` in the return type\nexpression of `AddAndScaleGeneric`. `U` is an archetype of `Vector`, and so acts\nas if it extends `Vector` and therefore has a `Scale` method.\n\nIf `U` had a more specific type, the return value would have the additional\ncapabilities of `U`. For example, given a parameterized type `GeneralPoint`\nimplementing `Vector`, and a function that takes a `GeneralPoint` and calls\n`AddAndScaleGeneric` with it:\n\n```carbon\nclass GeneralPoint(C:! Numeric) {\n  impl as Vector { ... }\n  fn Get[self: Self](i: i32) -> C;\n}\n\nfn CallWithGeneralPoint[C:! Numeric](p: GeneralPoint(C)) -> C {\n  // `AddAndScaleGeneric` returns `T` and in these calls `T` is\n  // deduced to be `GeneralPoint(C)`.\n\n  // ❌ Illegal: AddAndScaleGeneric(p, p, 2.0).Scale(2.0);\n  //    `GeneralPoint(C)` implements but does not extend `Vector`,\n  //    and so does not have a `Scale` method.\n\n  // ✅ Allowed: `GeneralPoint(C)` has a `Get` method\n  AddAndScaleGeneric(p, p, 2.0).Get(0);\n\n  // ✅ Allowed: `GeneralPoint(C)` implements `Vector`, and so has\n  //    a `Vector.Scale` method. `Vector.Scale` returns `Self`\n  //    which is `GeneralPoint(C)` again, and so has a `Get`\n  //    method.\n  return AddAndScaleGeneric(p, p, 2.0).(Vector.Scale)(2.0).Get(0);\n}\n```\n\nThe result of the call to `AddAndScaleGeneric` from `CallWithGeneralPoint` has\ntype `GeneralPoint(C)` and so has a `Get` method and a `Vector.Scale` method.\nBut, in contrast to how `DoubleThreeTimes` works, since `Vector` is implemented\nwithout `extend` the return value in this case does not directly have a `Scale`\nmethod.\n\n## Interfaces recap\n\nInterfaces have a name and a definition.\n\nThe definition of an interface consists of a set of declarations. Each\ndeclaration defines a requirement for any `impl` that is in turn a capability\nthat consumers of that `impl` can rely on. Typically those declarations also\nhave names, useful for both saying how the `impl` satisfies the requirement and\naccessing the capability.\n\nInterfaces are [\"nominal\"](terminology.md#nominal-interfaces), which means their\nname is significant. So two interfaces with the same body definition but\ndifferent names are different, just like two classes with the same definition\nbut different names are considered different types. For example, lets say we\ndefine another interface, say `LegoFish`, with the same `Add` and `Scale` method\nsignatures. Implementing `Vector` would not imply an implementation of\n`LegoFish`, because the `impl` definition explicitly refers to the name\n`Vector`.\n\nAn interface's name may be used in a few different contexts:\n\n-   to define [an `impl` for a type](#implementing-interfaces),\n-   as a namespace name in\n    [a qualified name](#qualified-member-names-and-compound-member-access), and\n-   as a [facet type](terminology.md#facet-type) for\n    [a facet binding](#symbolic-facet-bindings).\n\nWhile interfaces are examples of facet types, facet types are a more general\nconcept, for which interfaces are a building block.\n\n## Facet types\n\nA [facet type](terminology.md#facet-type) consists of a set of requirements and\na set of names. Requirements are typically a set of interfaces that a type must\nsatisfy, though other kinds of requirements are added below. The names are\naliases for qualified names in those interfaces.\n\nAn interface is one particularly simple example of a facet type. For example,\n`Vector` as a facet type has a set of requirements consisting of the single\ninterface `Vector`. Its set of names consists of `Add` and `Scale` which are\naliases for the corresponding qualified names inside `Vector` as a namespace.\n\nThe requirements determine which types may be implicitly converted to a given\nfacet type. The result of this conversion is a [facet](terminology.md#facet).\nFor example, `Point_Inline` from [the \"Inline `impl`\" section](#inline-impl)\nimplements `Vector`, so `Point_Inline` may be implicitly converted to `Vector`\nas considered as a type. The result is `Point_Inline as Vector`, which has the\nmembers of `Vector` instead of the members of `Point_Inline`. If the facet\n`Point_Inline as Vector` is used in a type position, it is implicitly converted\nback to type `type`, see\n[\"values usable as types\" in the design overview](/docs/design/README.md#values-usable-as-types).\nThis recovers the original type for the facet, so\n`(Point_Inline as Vector) as type` is `Point_Inline` again.\n\nHowever, when a facet type like `Vector` is used as the binding type of a\nsymbolic binding, as in `T:! Vector`, the\n[symbolic facet binding](#symbolic-facet-bindings) `T` is disassociated with\nwhatever facet value `T` is eventually bound to. Instead, `T` is treated as an\n[archetype](terminology.md#archetype), with the members and\n[member access](/docs/design/expressions/member_access.md) determined by the\nnames of the facet type.\n\nThis general structure of facet types holds not just for interfaces, but others\ndescribed in the rest of this document.\n\n## Named constraints\n\nIf the interfaces discussed above are the building blocks for facet types,\n[named constraints](terminology.md#named-constraints) describe how they may be\ncomposed together. Unlike interfaces which are nominal, the name of a named\nconstraint is not a part of its value. Two different named constraints with the\nsame definition are equivalent even if they have different names. This is\nbecause types don't have to explicitly specify which named constraints they\nimplement, types automatically implement any named constraints they can satisfy.\n\nA named constraint definition can contain interface requirements using `require`\n... `impls` declarations and names using `alias` declarations. Note that this\nallows us to declare the aspects of a facet type directly.\n\n```carbon\nconstraint VectorLegoFish {\n  // Interface implementation requirements\n  require impls Vector;\n  require impls LegoFish;\n  // Names\n  alias Scale = Vector.Scale;\n  alias VAdd = Vector.Add;\n  alias LFAdd = LegoFish.Add;\n}\n```\n\nA `require impls` requirement may alternatively be on a named constraint,\ninstead of an interface, to add all the requirements of another named constraint\nwithout adding any of the names:\n\n```carbon\nconstraint DrawVectorLegoFish {\n  // The same as requiring both `Vector` and `LegoFish`.\n  require impls VectorLegoFish;\n  // A regular interface requirement. No syntactic difference.\n  require impls Drawable;\n}\n```\n\nIn general, Carbon makes no syntactic distinction between the uses of named\nconstraints and interfaces, so one may be replaced with the other without\naffecting users. To accomplish this, Carbon allows a named constraint to be used\nwhenever an interface may be. This includes all of these\n[uses of interfaces](#interfaces-recap):\n\n-   A type may `impl` a named constraint to say that it implements all of the\n    requirements of the named constraint, as\n    [described below](#extend-require-with-named-constraints).\n-   A named constraint may be used as a namespace name in\n    [a qualified name](#qualified-member-names-and-compound-member-access). For\n    example, `VectorLegoFish.VAdd` refers to the same name as `Vector.Add`.\n-   A named constraint may be used as a [facet type](terminology.md#facet-type)\n    for [a facet binding](#symbolic-facet-bindings).\n\nWe don't expect developers to directly define many named constraints, but other\nconstructs we do expect them to use will be defined in terms of them. For\nexample, if `type` were not a keyword, we could define the Carbon builtin `type`\nas:\n\n```carbon\nconstraint type { }\n```\n\nThat is, `type` is the facet type with no requirements (so matches every type),\nand defines no names.\n\n```carbon\nfn Identity[T:! type](x: T*) -> T* {\n  // Can accept values of any type. But, since we know nothing about the\n  // type, we don't know about any operations on `x` inside this function.\n  return x;\n}\n\nvar i: i32 = 3;\nvar p_i: i32* = Identity(&i);\nvar s: String = \"string\";\nvar p_s: String = Identity(&s);\n```\n\nIn general, the declarations in `constraint` definition match a subset of the\ndeclarations in an `interface`. These named constraints can be used with checked\ngenerics, as opposed to templates, and only include required interfaces and\naliases to named members of those interfaces.\n\nTo declare a named constraint that includes other declarations for use with\ntemplate parameters, use the `template` keyword before `constraint`. Method,\nassociated constant, and associated function requirements may only be declared\ninside a `template constraint`. Note that a checked-generic constraint ignores\nthe names of members defined for a type, but a template constraint can depend on\nthem.\n\nThere is an analogy between declarations used in a `template constraint` and in\nan `interface` definition. If an `interface` `I` has (non-`alias`,\nnon-`require`) declarations `X`, `Y`, and `Z`, like so:\n\n```carbon\ninterface I {\n  X;\n  Y;\n  Z;\n}\n```\n\nThen a type implementing `I` would have `impl as I` with definitions for `X`,\n`Y`, and `Z`, as in:\n\n```carbon\nclass ImplementsI {\n  // ...\n  impl as I {\n    X { ... }\n    Y { ... }\n    Z { ... }\n  }\n}\n```\n\nBut a `template constraint`, `S`:\n\n```carbon\ntemplate constraint S {\n  X;\n  Y;\n  Z;\n}\n```\n\nwould match any type with definitions for `X`, `Y`, and `Z` directly:\n\n```carbon\nclass ImplementsS {\n  // ...\n  X { ... }\n  Y { ... }\n  Z { ... }\n}\n```\n\n### Subtyping between facet types\n\nThere is a subtyping relationship between facet types that allows calls of one\ngeneric function from another as long as it has a subset of the requirements.\n\nGiven a symbolic facet binding `T` with facet type `I1`, it satisfies a facet\ntype `I2` as long as the requirements of `I1` are a superset of the requirements\nof `I2`. This means a value `x: T` may be passed to functions requiring types to\nsatisfy `I2`, as in this example:\n\n```carbon\ninterface Printable { fn Print[self: Self](); }\ninterface Renderable { fn Draw[self: Self](); }\n\nconstraint PrintAndRender {\n  require impls Printable;\n  require impls Renderable;\n}\nconstraint JustPrint {\n  require impls Printable;\n}\n\nfn PrintIt[T2:! JustPrint](x2: T2) {\n  x2.(Printable.Print)();\n}\nfn PrintDrawPrint[T1:! PrintAndRender](x1: T1) {\n  // x1 implements `Printable` and `Renderable`.\n  x1.(Printable.Print)();\n  x1.(Renderable.Draw)();\n  // Can call `PrintIt` since `T1` satisfies `JustPrint` since\n  // it implements `Printable` (in addition to `Renderable`).\n  PrintIt(x1);\n}\n```\n\n## Combining interfaces by anding facet types\n\nIn order to support functions that require more than one interface to be\nimplemented, we provide a combination operator on facet types, written `&`. This\noperator gives the facet type with the union of all the requirements and the\nunion of the names.\n\n```carbon\ninterface Printable {\n  fn Print[self: Self]();\n}\ninterface Renderable {\n  fn Center[self: Self]() -> (i32, i32);\n  fn Draw[self: Self]();\n}\n\n// `Printable & Renderable` is syntactic sugar for this facet type:\nconstraint {\n  require impls Printable;\n  require impls Renderable;\n  alias Print = Printable.Print;\n  alias Center = Renderable.Center;\n  alias Draw = Renderable.Draw;\n}\n\nfn PrintThenDraw[T:! Printable & Renderable](x: T) {\n  // Can use methods of `Printable` or `Renderable` on `x` here.\n  x.Print();  // Same as `x.(Printable.Print)();`.\n  x.Draw();  // Same as `x.(Renderable.Draw)();`.\n}\n\nclass Sprite {\n  // ...\n  extend impl as Printable {\n    fn Print[self: Self]() { ... }\n  }\n  extend impl as Renderable {\n    fn Center[self: Self]() -> (i32, i32) { ... }\n    fn Draw[self: Self]() { ... }\n  }\n}\n\nvar s: Sprite = ...;\nPrintThenDraw(s);\n```\n\nIt is an error to use any names that conflict between the two interfaces.\n\n```carbon\ninterface Renderable {\n  fn Center[self: Self]() -> (i32, i32);\n  fn Draw[self: Self]();\n}\ninterface EndOfGame {\n  fn Draw[self: Self]();\n  fn Winner[self: Self](player: i32);\n}\nfn F[T:! Renderable & EndOfGame](x: T) {\n  // ❌ Error: Ambiguous, use either `(Renderable.Draw)`\n  //           or `(EndOfGame.Draw)`.\n  x.Draw();\n}\n```\n\nConflicts can be resolved at the call site using a\n[qualified member access expression](#qualified-member-names-and-compound-member-access),\nor by defining a named constraint explicitly and renaming the methods:\n\n```carbon\nconstraint RenderableAndEndOfGame {\n  require impls Renderable;\n  require impls EndOfGame;\n  alias Center = Renderable.Center;\n  alias RenderableDraw = Renderable.Draw;\n  alias TieGame = EndOfGame.Draw;\n  alias Winner = EndOfGame.Winner;\n}\n\nfn RenderTieGame[T:! RenderableAndEndOfGame](x: T) {\n  // ✅ Calls `Renderable.Draw`:\n  x.RenderableDraw();\n  // ✅ Calls `EndOfGame.Draw`:\n  x.TieGame();\n}\n```\n\nNote that `&` is associative and commutative, and so it is well defined on sets\nof interfaces, or other facet types, independent of order.\n\nNote that we do _not_ consider two facet types using the same name to mean the\nsame thing to be a conflict. For example, combining a facet type with itself\ngives itself, `MyTypeOfType & MyTypeOfType == MyTypeOfType`. Also, given two\n[interface extensions](#interface-extension) of a common base interface, the\ncombination should not conflict on any names in the common base.\n\nTo add to the requirements of a facet type without affecting the names, and so\navoid the possibility of name conflicts, names, use a\n[`where .Self impls` clause](#implements-constraints).\n\n```\n// `Printable where .Self impls Renderable` is equivalent to:\nconstraint {\n  require impls Printable;\n  require impls Renderable;\n  alias Print = Printable.Print;\n}\n```\n\nYou might use this to add requirements on interfaces used for\n[operator overloading](#operator-overloading), where merely implementing the\ninterface is enough to be able to use the operator to access the functionality.\n\nNote that the expressions `A & B` and `A where .Self impls B` have the same\nrequirements, and so you would be able to switch a function declaration between\nthem without affecting callers.\n\n**Alternatives considered:** See\n[Carbon: Access to interface methods](https://docs.google.com/document/d/17IXDdu384x1t9RimQ01bhx4-nWzs4ZEeke4eO6ImQNc/edit?resourcekey=0-Fe44R-0DhQBlw0gs2ujNJA).\n\n**Rejected alternative:** Instead of using `&` as the combining operator, we\nconsidered using `+`,\n[like Rust](https://rust-lang.github.io/rfcs/0087-trait-bounds-with-plus.html).\nThe main difference from Rust's `+` is how you\n[qualify names when there is a conflict](https://doc.rust-lang.org/rust-by-example/trait/disambiguating.html).\nSee [issue #531](https://github.com/carbon-language/carbon-lang/issues/531) for\nthe discussion.\n\n## Interface requiring other interfaces\n\nSome interfaces depend on other interfaces being implemented for the same type.\nFor example, in C++,\n[the `Container` concept](https://en.cppreference.com/w/cpp/named_req/Container#Other_requirements)\nrequires all containers to also satisfy the requirements of\n`DefaultConstructible`, `CopyConstructible`, `Eq`, and `Swappable`. This is\nalready a capability for [facet types in general](#facet-types). For consistency\nwe use the same semantics and `require` ... `impls` syntax as we do for\n[named constraints](#named-constraints):\n\n```carbon\ninterface Equatable { fn Equals[self: Self](rhs: Self) -> bool; }\n\ninterface Iterable {\n  fn Advance[ref self: Self]() -> bool;\n  require impls Equatable;\n}\n\nfn DoAdvanceAndEquals[T:! Iterable](x: T) {\n  // `x` has type `T` that implements `Iterable`, and so has `Advance`.\n  x.Advance();\n  // `Iterable` requires an implementation of `Equatable`,\n  // so `T` also implements `Equatable`.\n  x.(Equatable.Equals)(x);\n}\n\nclass Iota {\n  extend impl as Iterable { fn Advance[self: Self]() { ... } }\n  extend impl as Equatable { fn Equals[self: Self](rhs: Self) -> bool { ... } }\n}\nvar x: Iota;\nDoAdvanceAndEquals(x);\n```\n\nLike with named constraints, an interface implementation requirement doesn't by\nitself add any names to the interface, but again those can be added with `alias`\ndeclarations:\n\n```carbon\ninterface Hashable {\n  fn Hash[self: Self]() -> u64;\n  require impls Equatable;\n  alias Equals = Equatable.Equals;\n}\n\nfn DoHashAndEquals[T:! Hashable](x: T) {\n  // Now both `Hash` and `Equals` are available directly:\n  x.Hash();\n  x.Equals(x);\n}\n```\n\n**Comparison with other languages:**\n[This feature is called \"Supertraits\" in Rust](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-supertraits-to-require-one-traits-functionality-within-another-trait).\n\n**Note:** The design for this feature is continued in\n[a later section](#interface-requiring-other-interfaces-revisited).\n\n### Interface extension\n\n> **TODO:** Update this section as needed to reflect the fact that an impl of an\n> interface doesn't impl the interfaces it extends, as adopted in\n> [p5168: Forward `impl` declaration of an incomplete interface](/proposals/p5168.md).\n\nWhen implementing an interface, we allow implementing the aliased names as well.\nIn the case of `Hashable` above, this includes all the members of `Equatable`,\nobviating the need to implement `Equatable` itself:\n\n```carbon\nclass Song {\n  extend impl as Hashable {\n    fn Hash[self: Self]() -> u64 { ... }\n    fn Equals[self: Self](rhs: Self) -> bool { ... }\n  }\n}\nvar y: Song;\nDoHashAndEquals(y);\n```\n\nThis allows us to say that `Hashable`\n[\"extends\"](terminology.md#extending-an-interface) `Equatable`, with some\nbenefits:\n\n-   This allows `Equatable` to be an implementation detail of `Hashable`.\n-   This allows types implementing `Hashable` to implement all of its API in one\n    place.\n-   This reduces the boilerplate for types implementing `Hashable`.\n\nWe expect this concept to be common enough to warrant dedicated `interface`\nsyntax:\n\n> **TODO:** Update this section to reflect the new syntax adopted in\n> [p5337: Interface extension and `final impl` update](/proposals/p5337.md).\n\n```carbon\ninterface Equatable { fn Equals[self: Self](rhs: Self) -> bool; }\n\ninterface Hashable {\n  extend require impls Equatable;\n  fn Hash[self: Self]() -> u64;\n}\n// is equivalent to the definition of Hashable from before:\n// interface Hashable {\n//   require impls Equatable;\n//   alias Equals = Equatable.Equals;\n//   fn Hash[self: Self]() -> u64;\n// }\n```\n\nNo names in `Hashable` are allowed to conflict with names in `Equatable` (unless\nthose names are marked as `upcoming` or `deprecated` as in\n[evolution future work](#evolution)). Hopefully this won't be a problem in\npractice, since interface extension is a very closely coupled relationship, but\nthis may be something we will have to revisit in the future.\n\nExamples:\n\n-   The C++\n    [Boost.Graph library](https://www.boost.org/doc/libs/1_74_0/libs/graph/doc/)\n    [graph concepts](https://www.boost.org/doc/libs/1_74_0/libs/graph/doc/graph_concepts.html#fig:graph-concepts)\n    has many refining relationships between concepts.\n    [Carbon generics use case: graph library](https://docs.google.com/document/d/15Brjv8NO_96jseSesqer5HbghqSTJICJ_fTaZOH0Mg4/edit?usp=sharing&resourcekey=0-CYSbd6-xF8vYHv9m1rolEQ)\n    shows how those concepts might be translated into Carbon interfaces.\n-   The [C++ concepts](https://en.cppreference.com/w/cpp/named_req) for\n    containers, iterators, and concurrency include many requirement\n    relationships.\n-   Swift protocols, such as\n    [Collection](https://developer.apple.com/documentation/swift/collection).\n\nTo write an interface extending multiple interfaces, use multiple `extend`\ndeclarations. For example, the\n[`BinaryInteger` protocol in Swift](https://developer.apple.com/documentation/swift/binaryinteger)\ninherits from `CustomStringConvertible`, `Hashable`, `Numeric`, and `Stridable`.\nThe [`SetAlgebra` protocol](https://swiftdoc.org/v5.1/protocol/setalgebra/)\nextends `Equatable` and `ExpressibleByArrayLiteral`, which would be declared in\nCarbon:\n\n```carbon\ninterface SetAlgebra {\n  extend require impls Equatable;\n  extend require impls ExpressibleByArrayLiteral;\n}\n```\n\nWith `extend require impls I`, an interface requires an `impl` to exist for `I`\nwhen implementing the containing interface. This requires writing at least two\n`impl`s to implement the containing interface. When the two interfaces are\ntightly coupled, it's possible to have one interface gain the members of and\n_provide_ an implementation for the other interface instead, with\n`extend impl as`.\n\nJust as when used in a class, the implied `Self` between `extend impl` and `as`\nmust be omitted.\n\nWhen an interface `B` contains `extend impl as A`, implementing `B` will require\nwriting an implementation of all members of `A` inside the `impl` of `B`. And\nanything that implements `B` will implicitly also implement `A`, using the\ndefinitions from the `impl` of `B`. Here is an example:\n\n```carbon\ninterface A {\n  let T:! type;\n  fn F();\n  fn G();\n}\n\ninterface B {\n  extend impl as A;\n  fn H();\n}\n```\n\nThis is equivalent to writing `B` as:\n\n```carbon\ninterface B {\n  let T:! type;\n  fn F();\n  fn G();\n  fn H();\n}\nimpl forall [U:! B] U as A {\n  let T:! type = U.(B.T);\n  fn F() = U.(B.F);\n  fn G() = U.(B.G);\n}\n```\n\nThe implied `impl` definition can be made `final` by writing the reference to\n`A` as `extend final impl as A`.\n\nNote that this is supported only in an `interface` and not in a named\n[`constraint`](#named-constraints).\n\n**Alternative considered:** The `extend` declarations are in the body of the\n`interface` definition instead of the header so we can use\n[associated constants](terminology.md#associated-entity) also defined in the\nbody in parameters or constraints of the interface being extended.\n\n```carbon\n// A type can implement `ConvertibleTo` many times,\n// using different values of `T`.\ninterface ConvertibleTo(T:! type) { ... }\n\n// A type can only implement `PreferredConversion` once.\ninterface PreferredConversion {\n  let AssociatedFacet:! type;\n  // `extend require impls` is in the body of an `interface`\n  // definition. This allows extending an expression\n  // that uses an associated facet.\n  extend require impls ConvertibleTo(AssociatedFacet);\n}\n```\n\n#### `extend require` with named constraints\n\nThe `extend` modifier on `require` makes sense with the same meaning inside a\n[`constraint`](#named-constraints) definition, and so is also supported (unlike\n`extend impl as`).\n\n```carbon\ninterface Media {\n  fn Play[self: Self]();\n}\ninterface Job {\n  fn Run[self: Self]();\n}\n\nconstraint Combined {\n  extend require impls Media;\n  extend require impls Job;\n}\n```\n\nThis definition of `Combined` is equivalent to requiring both the `Media` and\n`Job` interfaces being implemented, and aliases their methods.\n\n```carbon\n// Equivalent\nconstraint Combined {\n  require impls Media;\n  alias Play = Media.Play;\n  require impls Job;\n  alias Run = Job.Run;\n}\n```\n\nNotice how `Combined` has aliases for all the methods in the interfaces it\nrequires. That condition is sufficient to allow a type to `impl` the named\nconstraint:\n\n```carbon\nclass Song {\n  extend impl as Combined {\n    fn Play[self: Self]() { ... }\n    fn Run[self: Self]() { ... }\n  }\n}\n```\n\nThis is equivalent to implementing the required interfaces directly:\n\n```carbon\nclass Song {\n  extend impl as Media {\n    fn Play[self: Self]() { ... }\n  }\n  extend impl as Job {\n    fn Run[self: Self]() { ... }\n  }\n}\n```\n\nThis is just like when you get an implementation of `Equatable` by implementing\n`Hashable` when `Hashable` extends `Equatable`. This provides a tool useful for\n[evolution](#evolution).\n\nConversely, an `interface` can extend a `constraint`:\n\n```carbon\ninterface MovieCodec {\n  extend require impls Combined;\n\n  fn Load[ref self: Self](filename: String);\n}\n```\n\nThis gives `MovieCodec` the same requirements and names as `Combined`, and so is\nequivalent to:\n\n```carbon\ninterface MovieCodec {\n  require impls Media;\n  alias Play = Media.Play;\n  require impls Job;\n  alias Run = Job.Run;\n\n  fn Load[ref self: Self](filename: String);\n}\n```\n\n#### Diamond dependency issue\n\n> **TODO:** Update this section to reflect the changes in\n> [p5168: Forward `impl` declaration of an incomplete interface](/proposals/p5168.md).\n\nConsider this set of interfaces, simplified from\n[this example generic graph library doc](https://docs.google.com/document/d/15Brjv8NO_96jseSesqer5HbghqSTJICJ_fTaZOH0Mg4/edit?usp=sharing&resourcekey=0-CYSbd6-xF8vYHv9m1rolEQ):\n\n```carbon\ninterface Graph {\n  fn Source[ref self: Self](e: EdgeDescriptor) -> VertexDescriptor;\n  fn Target[ref self: Self](e: EdgeDescriptor) -> VertexDescriptor;\n}\n\ninterface IncidenceGraph {\n  extend Graph;\n  fn OutEdges[ref self: Self](u: VertexDescriptor)\n    -> (EdgeIterator, EdgeIterator);\n}\n\ninterface EdgeListGraph {\n  extend Graph;\n  fn Edges[ref self: Self]() -> (EdgeIterator, EdgeIterator);\n}\n```\n\nWe need to specify what happens when a graph type implements both\n`IncidenceGraph` and `EdgeListGraph`, since both interfaces extend the `Graph`\ninterface.\n\n```carbon\nclass MyEdgeListIncidenceGraph {\n  extend impl as IncidenceGraph { ... }\n  extend impl as EdgeListGraph { ... }\n}\n```\n\nThe rule is that we need one definition of each method of `Graph`. Each method\nthough could be defined in the `impl` block of `IncidenceGraph`,\n`EdgeListGraph`, or `Graph`. These would all be valid:\n\n-   `IncidenceGraph` implements all methods of `Graph`, `EdgeListGraph`\n    implements none of them.\n\n    ```carbon\n    class MyEdgeListIncidenceGraph {\n      extend impl as IncidenceGraph {\n        fn Source[self: Self](e: EdgeDescriptor) -> VertexDescriptor { ... }\n        fn Target[self: Self](e: EdgeDescriptor) -> VertexDescriptor { ... }\n        fn OutEdges[ref self: Self](u: VertexDescriptor)\n            -> (EdgeIterator, EdgeIterator) { ... }\n      }\n      extend impl as EdgeListGraph {\n        fn Edges[ref self: Self]() -> (EdgeIterator, EdgeIterator) { ... }\n      }\n    }\n    ```\n\n-   `IncidenceGraph` and `EdgeListGraph` implement all methods of `Graph`\n    between them, but with no overlap.\n\n    ```carbon\n    class MyEdgeListIncidenceGraph {\n      extend impl as IncidenceGraph {\n        fn Source[self: Self](e: EdgeDescriptor) -> VertexDescriptor { ... }\n        fn OutEdges[ref self: Self](u: VertexDescriptor)\n            -> (EdgeIterator, EdgeIterator) { ... }\n      }\n      extend impl as EdgeListGraph {\n        fn Target[self: Self](e: EdgeDescriptor) -> VertexDescriptor { ... }\n        fn Edges[ref self: Self]() -> (EdgeIterator, EdgeIterator) { ... }\n      }\n    }\n    ```\n\n-   Explicitly implementing `Graph`.\n\n    ```carbon\n    class MyEdgeListIncidenceGraph {\n      extend impl as Graph {\n        fn Source[self: Self](e: EdgeDescriptor) -> VertexDescriptor { ... }\n        fn Target[self: Self](e: EdgeDescriptor) -> VertexDescriptor { ... }\n      }\n      extend impl as IncidenceGraph { ... }\n      extend impl as EdgeListGraph { ... }\n    }\n    ```\n\n-   Implementing `Graph` out-of-line.\n\n    ```carbon\n    class MyEdgeListIncidenceGraph {\n      extend impl as IncidenceGraph { ... }\n      extend impl as EdgeListGraph { ... }\n    }\n    impl MyEdgeListIncidenceGraph as Graph {\n      fn Source[self: Self](e: EdgeDescriptor) -> VertexDescriptor { ... }\n      fn Target[self: Self](e: EdgeDescriptor) -> VertexDescriptor { ... }\n    }\n    ```\n\nThis last point means that there are situations where we can only detect a\nmissing method definition by the end of the file. This doesn't delay other\naspects of semantic checking, which will just assume that these methods will\neventually be provided.\n\n**Open question:** We could require that the `impl` of the required interface be\ndeclared lexically in the class scope in this case. That would allow earlier\ndetection of missing definitions.\n\n### Use case: detecting unreachable matches\n\nIf interface `E` extends another interface `I`, that gives the information to\nthe compiler that the any type implementing `E` also implements `I`. This can be\nused to detect unreachable code.\n\nFor example, the [`impl` prioritization rule](#prioritization-rule) is used to\npick between `impl` declarations based on an explicit priority ordering given by\nthe developer. If the broader interface `I` is prioritized over the more\nspecific interface `E`, the compiler can conclude that the more specific\ndeclaration will never be selected and report an error. Similar situations could\nbe detected in function overloading.\n\n## Adapting types\n\nSince interfaces may only be implemented for a type once, and we limit where\nimplementations may be added to a type, there is a need to allow the user to\nswitch the type of a value to access different interface implementations. Carbon\ntherefore provides a way to create new types\n[compatible with](terminology.md#compatible-types) existing types with different\nAPIs, in particular with different interface implementations, by\n[adapting](terminology.md#adapting-a-type) them:\n\n```carbon\ninterface Printable {\n  fn Print[self: Self]();\n}\ninterface Ordered {\n  fn Less[self: Self](rhs: Self) -> bool;\n}\nclass Song {\n  extend impl as Printable { fn Print[self: Self]() { ... } }\n}\nclass SongByTitle {\n  adapt Song;\n  extend impl as Ordered {\n    fn Less[self: Self](rhs: Self) -> bool { ... }\n  }\n}\nclass FormattedSong {\n  adapt Song;\n  extend impl as Printable { fn Print[self: Self]() { ... } }\n}\nclass FormattedSongByTitle {\n  adapt Song;\n  extend impl as Printable = FormattedSong;\n  extend impl as Ordered = SongByTitle;\n}\n```\n\nThis allows developers to provide implementations of new interfaces (as in\n`SongByTitle`), provide different implementations of the same interface (as in\n`FormattedSong`), or mix and match implementations from other compatible types\n(as in `FormattedSongByTitle`). The rules are:\n\n-   You can add any declaration that you could add to a class except for\n    declarations that would change the representation of the type. This means\n    you can add methods, functions, interface implementations, and aliases, but\n    not fields, base classes, or virtual functions. The specific implementations\n    of virtual functions are part of the type representation, and so no virtual\n    functions may be overridden in an adapter either.\n-   The adapted type is compatible with the original type, and that relationship\n    is an equivalence class, so all of `Song`, `SongByTitle`, `FormattedSong`,\n    and `FormattedSongByTitle` end up compatible with each other.\n-   Since adapted types are compatible with the original type, you may\n    explicitly cast between them, but there is no implicit conversion between\n    these types.\n\nInside an adapter, the `Self` type matches the adapter. Members of the original\ntype may be accessed either by a cast:\n\n```carbon\nclass SongByTitle {\n  adapt Song;\n  extend impl as Ordered {\n    fn Less[self: Self](rhs: Self) -> bool {\n      return (self as Song).Title() < (rhs as Song).Title();\n    }\n  }\n}\n```\n\nor using a qualified member access expression:\n\n```carbon\nclass SongByTitle {\n  adapt Song;\n  extend impl as Ordered {\n    fn Less[self: Self](rhs: Self) -> bool {\n      return self.(Song.Title)() < rhs.(Song.Title)();\n    }\n  }\n}\n```\n\n**Comparison with other languages:** This matches the Rust idiom called\n\"newtype\", which is used to implement traits on types while avoiding\n[coherence](terminology.md#coherence) problems, see\n[here](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types)\nand\n[here](https://github.com/Ixrec/rust-orphan-rules#user-content-why-are-the-orphan-rules-controversial).\nRust's mechanism doesn't directly support reusing implementations, though some\nof that is provided by macros defined in libraries. Haskell has a\n[`newtype` feature](https://wiki.haskell.org/Newtype) as well. Haskell's feature\ndoesn't directly support reusing implementations either, but the most popular\ncompiler provides it as\n[an extension](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/newtype_deriving.html).\n\n### Adapter compatibility\n\nConsider a [type with a facet parameter, like a hash map](#parameterized-types):\n\n```carbon\ninterface Hashable { ... }\nclass HashMap(KeyT:! Hashable, ValueT:! type) {\n  fn Find[self: Self](key: KeyT) -> Optional(ValueT);\n  // ...\n}\n```\n\nA user of this type will provide specific values for the key and value types:\n\n```carbon\nclass Song {\n  extend impl as Hashable { ... }\n  // ...\n}\n\nvar play_count: HashMap(Song, i32) = ...;\nvar thriller_count: Optional(i32) =\n    play_count.Find(Song(\"Thriller\"));\n```\n\nSince the `KeyT` and `ValueT` are symbolic parameters, the `Find` function is a\nchecked generic, and it can only use the capabilities of `KeyT` and `ValueT`\nspecified as requirements. This allows us to evaluate when we can convert\nbetween two different arguments to a parameterized type. Consider two adapters\nof `Song` that implement `Hashable`:\n\n```carbon\nclass PlayableSong {\n  adapt Song;\n  extend impl as Hashable = Song;\n  extend impl as Media { ... }\n}\nclass SongHashedByTitle {\n  adapt Song;\n  extend impl as Hashable { ... }\n}\n```\n\n`Song` and `PlayableSong` have the same implementation of `Hashable` in addition\nto using the same data representation. This means that it is safe to convert\nbetween `HashMap(Song, i32)` and `HashMap(PlayableSong, i32)`, because the\nimplementation of all the methods will use the same implementation of the\n`Hashable` interface. Carbon permits this conversion with an explicit cast.\n\nOn the other hand, `SongHashedByTitle` has a different implementation of\n`Hashable` than `Song`. So even though `Song` and `SongHashedByTitle` are\ncompatible types, `HashMap(Song, i32)` and `HashMap(SongHashedByTitle, i32)` are\nincompatible. This is important because we know that in practice the invariants\nof a `HashMap` implementation rely on the hashing function staying the same.\n\n### Extending adapter\n\nFrequently we expect that the adapter type will want to preserve most or all of\nthe API of the original type. The two most common cases expected are adding and\nreplacing an interface implementation. Users would indicate that an adapter\nstarts from the original type's existing API by using the `extend` keyword\nbefore `adapt`:\n\n```carbon\nclass Song {\n  extend impl as Hashable { ... }\n  extend impl as Printable { ... }\n}\n\nclass SongByArtist {\n  extend adapt Song;\n\n  // Add an implementation of a new interface\n  extend impl as Ordered { ... }\n\n  // Replace an existing implementation of an interface\n  // with an alternative.\n  extend impl as Hashable { ... }\n}\n```\n\nThe resulting type `SongByArtist` would:\n\n-   implement `Ordered`, unlike `Song`,\n-   implement `Hashable`, but differently than `Song`, and\n-   implement `Printable`, inherited from `Song`.\n\nThe rule is that when looking up if `SongByArtist` implements an interface `I`\nand no implementation is found, the compiler repeats the search to see if `Song`\nimplements `I`. If that is found, it is reused if possible. The reuse will be\nsuccessful if all types that reference `Self` in the signatures of interface's\nfunctions can be cast to the corresponding type with `SongByArtist` substituted\nin for `Song`.\n\nUnlike the similar `class B { extend base: A; }` notation,\n`class B { extend adapt A; }` is permitted even if `A` is a final class. Also,\nthere is no implicit conversion from `B` to `A`, matching `adapt` without\n`extend` but unlike class extension.\n\nTo avoid or resolve name conflicts between interfaces, an `impl` may be declared\nwithout [`extend`](#extend-impl). The names in that interface may then be pulled\nin individually or renamed using `alias` declarations.\n\n```carbon\nclass SongRenderToPrintDriver {\n  extend adapt Song;\n\n  // Add a new `Print()` member function.\n  fn Print[self: Self]() { ... }\n\n  // Avoid name conflict with new `Print`\n  // function by implementing the `Printable`\n  // interface without `extend`.\n  impl as Printable = Song;\n\n  // Make the `Print` function from `Printable`\n  // available under the name `PrintToScreen`.\n  alias PrintToScreen = Printable.Print;\n}\n```\n\n### Use case: Using independent libraries together\n\nImagine we have two packages that are developed independently. Package\n`CompareLib` defines an interface `CompareLib.Comparable` and a checked-generic\nalgorithm `CompareLib.Sort` that operates on types that implement\n`CompareLib.Comparable`. Package `SongLib` defines a type `SongLib.Song`.\nNeither has a dependency on the other, so neither package defines an\nimplementation for `CompareLib.Comparable` for type `SongLib.Song`. A user that\nwants to pass a value of type `SongLib.Song` to `CompareLib.Sort` has to define\nan adapter that provides an implementation of `CompareLib.Comparable` for\n`SongLib.Song`. This adapter will probably use the\n[`extend` facility of adapters](#extending-adapter) to preserve the\n`SongLib.Song` API.\n\n```carbon\nimport CompareLib;\nimport SongLib;\n\nclass Song {\n  extend adapt SongLib.Song;\n  extend impl as CompareLib.Comparable { ... }\n}\n// Or, to keep the names from CompareLib.Comparable out of Song's API:\nclass Song {\n  extend adapt SongLib.Song;\n}\nimpl Song as CompareLib.Comparable { ... }\n// Or, equivalently:\nclass Song {\n  extend adapt SongLib.Song;\n  impl as CompareLib.Comparable { ... }\n}\n```\n\nThe caller can either convert `SongLib.Song` values to `Song` when calling\n`CompareLib.Sort` or just start with `Song` values in the first place.\n\n```carbon\nvar lib_song: SongLib.Song = ...;\nCompareLib.Sort((lib_song as Song,));\n\nvar song: Song = ...;\nCompareLib.Sort((song,));\n```\n\n### Use case: Defining an impl for use by other types\n\nLet's say we want to provide a possible implementation of an interface for use\nby types for which that implementation would be appropriate. We can do that by\ndefining an adapter implementing the interface that is parameterized on the type\nit is adapting. That impl may then be pulled in using the `impl as ... = ...;`\nsyntax.\n\nFor example, given an interface `Comparable` for deciding which value is\nsmaller:\n\n```carbon\ninterface Comparable {\n  fn Less[self: Self](rhs: Self) -> bool;\n}\n```\n\nWe might define an adapter that implements `Comparable` for types that define\nanother interface `Difference`:\n\n```carbon\ninterface Difference {\n  fn Sub[self: Self](rhs: Self) -> i32;\n}\nclass ComparableFromDifference(T:! Difference) {\n  adapt T;\n  extend impl as Comparable {\n    fn Less[self: Self](rhs: Self) -> bool {\n      return (self as T).Sub(rhs) < 0;\n    }\n  }\n}\nclass IntWrapper {\n  var x: i32;\n  impl as Difference {\n    fn Sub[self: Self](rhs: Self) -> i32 {\n      return left.x - right.x;\n    }\n  }\n  impl as Comparable = ComparableFromDifference(IntWrapper);\n}\n```\n\n**TODO:** If we support function types, we could potentially pass a function to\nuse to the adapter instead:\n\n```carbon\nclass ComparableFromDifferenceFn\n    (T:! type, Difference:! fnty(T, T)->i32) {\n  adapt T;\n  extend impl as Comparable {\n    fn Less[self: Self](rhs: Self) -> bool {\n      return Difference(self as T, rhs as T) < 0;\n    }\n  }\n}\nclass IntWrapper {\n  var x: i32;\n  fn Difference(left: Self, right: Self) {\n    return left.x - right.x;\n  }\n  impl as Comparable =\n      ComparableFromDifferenceFn(IntWrapper, Difference);\n}\n```\n\n### Use case: Private impl\n\nAdapter types can be used when a library publicly exposes a type, but only wants\nto say that type implements an interface as a private detail internal to the\nimplementation of the type. In that case, instead of implementing the interface\nfor the public type, the library can create a private adapter for that type and\nimplement the interface on that instead. Any member of the class can cast its\n`self` parameter to the adapter type when it wants to make use of the private\nimpl.\n\n```carbon\n// Public, in API file\nclass Complex64 {\n  // ...\n  fn CloserToOrigin[self: Self](them: Self) -> bool;\n}\n\n// Private\n\nclass ByReal {\n  extend adapt Complex64;\n\n  // Complex numbers are not generally comparable,\n  // but this comparison function is useful for some\n  // method implementations.\n  extend impl as Comparable {\n    fn Less[self: Self](that: Self) -> bool {\n      return self.Real() < that.Real();\n    }\n  }\n}\n\nfn Complex64.CloserToOrigin[self: Self](them: Self) -> bool {\n  var self_mag: ByReal = self * self.Conj() as ByReal;\n  var them_mag: ByReal = them * them.Conj() as ByReal;\n  return self_mag.Less(them_mag);\n}\n```\n\n### Use case: Accessing interface names\n\nConsider a case where a function will call several functions from an interface\nthat the type does not\n[extend the implementation of](terminology.md#extending-an-impl).\n\n```carbon\ninterface DrawingContext {\n  fn SetPen[self: Self](...);\n  fn SetFill[self: Self](...);\n  fn DrawRectangle[self: Self](...);\n  fn DrawLine[self: Self](...);\n  ...\n}\nimpl Window as DrawingContext { ... }\n```\n\nAn adapter can make that more convenient by making a compatible type that does\nextend the implementation of the interface. This avoids having to\n[qualify](terminology.md#qualified-member-access-expression) each call to\nmethods in the interface.\n\n```carbon\nclass DrawInWindow {\n  adapt Window;\n  extend impl as DrawingContext = Window;\n}\nfn Render(w: Window) {\n  let d: DrawInWindow = w as DrawInWindow;\n  d.SetPen(...);\n  d.SetFill(...);\n  d.DrawRectangle(...);\n  ...\n}\n```\n\n**Note:** Another way to achieve this is to use a\n[local symbolic facet constant](#compile-time-let).\n\n```carbon\nfn Render(w: Window) {\n  let DrawInWindow:! Draw = Window;\n  // Implicit conversion to `w as DrawInWindow`.\n  let d: DrawInWindow = w;\n  d.SetPen(...);\n  d.SetFill(...);\n  d.DrawRectangle(...);\n  ...\n}\n```\n\n### Future work: Adapter with stricter invariants\n\n**Future work:** Rust also uses the newtype idiom to create types with\nadditional invariants or other information encoded in the type\n([1](https://doc.rust-lang.org/rust-by-example/generics/new_types.html),\n[2](https://doc.rust-lang.org/book/ch19-04-advanced-types.html#using-the-newtype-pattern-for-type-safety-and-abstraction),\n[3](https://www.worthe-it.co.za/blog/2020-10-31-newtype-pattern-in-rust.html)).\nThis is used to record in the type system that some data has passed validation\nchecks, like `ValidDate` with the same data layout as `Date`. Or to record the\nunits associated with a value, such as `Seconds` versus `Milliseconds` or `Feet`\nversus `Meters`. We should have some way of restricting the casts between a type\nand an adapter to address this use case. One possibility would be to add the\nkeyword `private` before `adapt`, so you might write\n`extend private adapt Date;`.\n\n## Associated constants\n\n> **TODO:** Update this section to reflect the new rules and guidance on\n> associated constants in\n> [p5168: Forward `impl` declaration of an incomplete interface](/proposals/p5168.md).\n\nIn addition to associated methods, we allow other kinds of\n[associated entities](terminology.md#associated-entity). For consistency, we use\nthe same syntax to describe a compile-time constant in an interface as in a type\nwithout assigning a value. As constants, they are declared using the `let`\nintroducer. For example, a fixed-dimensional point type could have the dimension\nas an associated constant.\n\n```carbon\ninterface NSpacePoint {\n  let N:! i32;\n  // The following require: 0 <= i < N.\n  fn Get[ref self: Self](i: i32) -> f64;\n  fn Set[ref self: Self](i: i32, value: f64);\n  // Associated constants may be used in signatures:\n  fn SetAll[ref self: Self](value: Array(f64, N));\n}\n```\n\nThe pattern of an associated constant declaration must be a symbolic binding\npattern, and unlike other `let` declarations, an associated constant declaration\ncannot have an initializer unless it's\n[preceded by `default`](#interface-defaults):\n\n_associated-constant-decl_ ::= `let` _identifier_ `:!` _expression_ `;`\n_associated-constant-decl_ ::= `default` `let` _identifier_ `:!` _expression_ =\n_expression_ `;`\n\nAn implementation of an interface specifies values for associated constants with\na [`where` clause](#where-constraints). For example, implementations of\n`NSpacePoint` for different types might have different values for `N`:\n\n```carbon\nclass Point2D {\n  extend impl as NSpacePoint where .N = 2 {\n    fn Get[ref self: Self](i: i32) -> f64 { ... }\n    fn Set[ref self: Self](i: i32, value: f64) { ... }\n    fn SetAll[ref self: Self](value: Array(f64, 2)) { ... }\n  }\n}\n\nclass Point3D {\n  extend impl as NSpacePoint where .N = 3 {\n    fn Get[ref self: Self](i: i32) -> f64 { ... }\n    fn Set[ref self: Self](i: i32, value: f64) { ... }\n    fn SetAll[ref self: Self](value: Array(f64, 3)) { ... }\n  }\n}\n```\n\nMultiple assignments to associated constants may be joined using the `and`\nkeyword. The list of assignments is subject to two restrictions:\n\n-   An implementation of an interface cannot specify a value for a\n    [`final`](#final-members) associated constant.\n-   If an associated constant doesn't have a\n    [default value](#interface-defaults), every implementation must specify its\n    value.\n\nThese values may be accessed as members of the type:\n\n```carbon\nAssert(Point2D.N == 2);\nAssert(Point3D.N == 3);\n\nfn PrintPoint[PointT:! NSpacePoint](p: PointT) {\n  var i: i32 = 0\n  while (i < PointT.N) {\n    if (i > 0) { Print(\", \"); }\n    Print(p.Get(i));\n    ++i;\n  }\n}\n\nfn ExtractPoint[PointT:! NSpacePoint](\n    p: PointT,\n    dest: Array(f64, PointT.N)*) {\n  var i: i32 = 0;\n  while (i < PointT.N) {\n    (*dest)[i] = p.Get(i);\n    ++i;\n  }\n}\n```\n\n**Comparison with other languages:** This feature is also called\n[associated constants in Rust](https://doc.rust-lang.org/reference/items/associated-items.html#associated-constants).\n\n**Aside:** The use of `:!` here means these `let` declarations will only have\ncompile-time and not runtime storage associated with them.\n\n### Associated class functions\n\nTo be consistent with normal\n[class function](/docs/design/classes.md#class-functions) declaration syntax,\nassociated class functions are written using a `fn` declaration:\n\n```carbon\ninterface DeserializeFromString {\n  fn Deserialize(serialized: String) -> Self;\n}\n\nclass MySerializableType {\n  var i: i32;\n\n  extend impl as DeserializeFromString {\n    fn Deserialize(serialized: String) -> Self {\n      return {.i = StringToInt(serialized)};\n    }\n  }\n}\n\nvar x: MySerializableType = MySerializableType.Deserialize(\"3\");\n\nfn Deserialize(T:! DeserializeFromString, serialized: String) -> T {\n  return T.Deserialize(serialized);\n}\nvar y: MySerializableType = Deserialize(MySerializableType, \"4\");\n```\n\nThis is instead of declaring an associated constant using `let` with a function\ntype.\n\nTogether associated methods and associated class functions are called\n_associated functions_, much like together methods and class functions are\ncalled [member functions](/docs/design/classes.md#member-functions).\n\n> **TODO:** Document rules on where associated function implementations can be\n> declared, as adopted in\n> [p5168: Forward `impl` declaration of an incomplete interface](/proposals/p5168.md).\n\n## Associated facets\n\nAssociated facets are [associated constants](#associated-constants) that happen\nto have a [facet type](terminology.md#facet-type). These are particularly\ninteresting since they can be used in the signatures of associated methods or\nfunctions, to allow the signatures of methods to vary from implementation to\nimplementation. We already have one example of this: the `Self` type discussed\n[in the \"Interfaces\" section](#interfaces). For other cases, we can say that the\ninterface declares that each implementation will provide a facet constant under\na specified name. For example:\n\n```carbon\ninterface StackAssociatedFacet {\n  let ElementType:! type;\n  fn Push[ref self: Self](value: ElementType);\n  fn Pop[ref self: Self]() -> ElementType;\n  fn IsEmpty[ref self: Self]() -> bool;\n}\n```\n\nHere we have an interface called `StackAssociatedFacet` which defines two\nmethods, `Push` and `Pop`. The signatures of those two methods declare them as\naccepting or returning values with the type `ElementType`, which any implementer\nof `StackAssociatedFacet` must also define. For example, maybe a `DynamicArray`\n[parameterized type](#parameterized-types) implements `StackAssociatedFacet`:\n\n```carbon\nclass DynamicArray(T:! type) {\n  class IteratorType { ... }\n  fn Begin[ref self: Self]() -> IteratorType;\n  fn End[ref self: Self]() -> IteratorType;\n  fn Insert[ref self: Self](pos: IteratorType, value: T);\n  fn Remove[ref self: Self](pos: IteratorType);\n\n  // Set the associated facet `ElementType` to `T`.\n  extend impl as StackAssociatedFacet where .ElementType = T {\n    fn Push[ref self: Self](value: ElementType) {\n      self.Insert(self.End(), value);\n    }\n    fn Pop[ref self: Self]() -> ElementType {\n      var pos: IteratorType = self.End();\n      Assert(pos != self.Begin());\n      --pos;\n      returned var ret: ElementType = *pos;\n      self.Remove(pos);\n      return var;\n    }\n    fn IsEmpty[ref self: Self]() -> bool {\n      return self.Begin() == self.End();\n    }\n  }\n}\n```\n\nThe keyword `Self` can be used after the `as` in an `impl` declaration as a\nshorthand for the type being implemented, including in the `where` clause\nspecifying the values of associated facets, as in:\n\n```carbon\nimpl VeryLongTypeName as Add\n    // `Self` here means `VeryLongTypeName`\n    where .Result = Self {\n  ...\n}\n```\n\n> **Alternatives considered:** See\n> [other syntax options considered in #731 for specifying associated facets](/proposals/p0731.md#syntax-for-associated-constants).\n> In particular, it was deemed that\n> [Swift's approach of inferring an associated facet from method signatures in the impl](https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID190)\n> was unneeded complexity.\n\nThe definition of the `StackAssociatedFacet` is sufficient for writing a\nchecked-generic function that operates on anything implementing that interface,\nfor example:\n\n```carbon\nfn PeekAtTopOfStack[StackType:! StackAssociatedFacet](s: StackType*)\n    -> StackType.ElementType {\n  var top: StackType.ElementType = s->Pop();\n  s->Push(top);\n  return top;\n}\n```\n\nInside the checked-generic function `PeekAtTopOfStack`, the `ElementType`\nassociated facet member of `StackType` is an\n[archetype](terminology.md#archetype), like other\n[symbolic facet bindings](#symbolic-facet-bindings). This means\n`StackType.ElementType` has the API dictated by the declaration of `ElementType`\nin the interface `StackAssociatedFacet`.\n\nOutside the checked-generic, associated facets have the concrete facet values\ndetermined by impl lookup, rather than the erased version of that facet used\ninside a checked-generic.\n\n```carbon\nvar my_array: DynamicArray(i32) = (1, 2, 3);\n// PeekAtTopOfStack's `StackType` is set to `DynamicArray(i32)`\n// with `StackType.ElementType` set to `i32`.\nAssert(PeekAtTopOfStack(my_array) == 3);\n```\n\nThis is another part of achieving\n[the goal that generic functions can be used in place of regular functions without changing the return type that callers see](goals.md#path-from-regular-functions)\ndiscussed in the [return type section](#return-type).\n\nAssociated facets can also be implemented using a\n[member type](/docs/design/classes.md#member-type).\n\n```carbon\ninterface Container {\n  let IteratorType:! Iterator;\n  ...\n}\n\nclass DynamicArray(T:! type) {\n  ...\n  extend impl as Container {\n    class IteratorType {\n      extend impl as Iterator { ... }\n    }\n    ...\n  }\n}\n```\n\nFor context, see\n[\"Interface parameters and associated constants\" in the generics terminology document](terminology.md#interface-parameters-and-associated-constants).\n\n**Comparison with other languages:** Both\n[Rust](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types)\nand [Swift](https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID189)\nsupport these, but call them \"associated types.\"\n\n## Parameterized interfaces\n\nAssociated constants don't change the fact that a type can only implement an\ninterface at most once.\n\nIf instead you want a family of related interfaces, one per possible value of a\ntype parameter, multiple of which could be implemented for a single type, you\nwould use\n[_parameterized interfaces_](terminology.md#interface-parameters-and-associated-constants),\nalso known as _generic interfaces_. To write a parameterized version of the\nstack interface, instead of using associated constants, write a parameter list\nafter the name of the interface:\n\n```carbon\ninterface StackParameterized(ElementType:! type) {\n  fn Push[ref self: Self](value: ElementType);\n  fn Pop[ref self: Self]() -> ElementType;\n  fn IsEmpty[ref self: Self]() -> bool;\n}\n```\n\nThen `StackParameterized(Fruit)` and `StackParameterized(Veggie)` would be\nconsidered different interfaces, with distinct implementations.\n\n```carbon\nclass Produce {\n  var fruit: DynamicArray(Fruit);\n  var veggie: DynamicArray(Veggie);\n  extend impl as StackParameterized(Fruit) {\n    fn Push[ref self: Self](value: Fruit) {\n      self.fruit.Push(value);\n    }\n    fn Pop[ref self: Self]() -> Fruit {\n      return self.fruit.Pop();\n    }\n    fn IsEmpty[ref self: Self]() -> bool {\n      return self.fruit.IsEmpty();\n    }\n  }\n  extend impl as StackParameterized(Veggie) {\n    fn Push[ref self: Self](value: Veggie) {\n      self.veggie.Push(value);\n    }\n    fn Pop[ref self: Self]() -> Veggie {\n      return self.veggie.Pop();\n    }\n    fn IsEmpty[ref self: Self]() -> bool {\n      return self.veggie.IsEmpty();\n    }\n  }\n}\n```\n\nUnlike associated constants in interfaces and parameters to types, interface\nparameters can't be deduced. For example, if we were to rewrite\n[the `PeekAtTopOfStack` example in the \"associated facets\" section](#associated-facets)\nfor `StackParameterized(T)` it would generate a compile error:\n\n```carbon\n// ❌ Error: can't deduce interface parameter `T`.\nfn BrokenPeekAtTopOfStackParameterized\n    [T:! type, StackType:! StackParameterized(T)]\n    (s: StackType*) -> T { ... }\n```\n\nThis error is because the compiler can not determine if `T` should be `Fruit` or\n`Veggie` when passing in argument of type `Produce*`. Either `T` should be\nreplaced by a concrete type, like `Fruit`:\n\n```carbon\nfn PeekAtTopOfFruitStack\n    [StackType:! StackParameterized(Fruit)]\n    (s: StackType*) -> T { ... }\n\nvar produce: Produce = ...;\nvar top_fruit: Fruit =\n    PeekAtTopOfFruitStack(&produce);\n```\n\nOr the value for `T` would be passed explicitly, using `where` constraints\ndescribed [in this section](#another-type-implements-parameterized-interface):\n\n```carbon\nfn PeekAtTopOfStackParameterizedImpl\n    (T:! type, StackType:! StackParameterized(T), s: StackType*) -> T {\n  ...\n}\nfn PeekAtTopOfStackParameterized[StackType:! type]\n    (s: StackType*, T:! type where StackType impls StackParameterized(T)) -> T {\n  return PeekAtTopOfStackParameterizedImpl(T, StackType, s);\n}\n\nvar produce: Produce = ...;\nvar top_fruit: Fruit =\n    PeekAtTopOfStackParameterized(&produce, Fruit);\nvar top_veggie: Veggie =\n    PeekAtTopOfStackParameterized(&produce, Veggie);\n```\n\n> **Note:** Alternative ways of declaraing `PeekAtTopOfStackParameterized` are\n> described and discussed in\n> [#578: Value patterns as function parameters](https://github.com/carbon-language/carbon-lang/issues/578).\n\nParameterized interfaces are useful for\n[operator overloads](#operator-overloading). For example, the `EqWith(T)` and\n`OrderedWith(T)` interfaces have a parameter that allows type to be comparable\nwith multiple other types, as in:\n\n```carbon\ninterface EqWith(T:! type) {\n  fn Equal[self: Self](rhs: T) -> bool;\n  ...\n}\nclass Complex {\n  var real: f64;\n  var imag: f64;\n  // Can implement this interface more than once\n  // as long as it has different arguments.\n  extend impl as EqWith(f64) { ... }\n  // Same as: impl as EqWith(Complex) { ... }\n  extend impl as EqWith(Self) { ... }\n}\n```\n\nAll interface parameters must be marked as \"symbolic\", using the `:!` binding\npattern syntax. This reflects these two properties of these parameters:\n\n-   They must be resolved at compile-time, and so can't be passed regular\n    dynamic values.\n-   We allow either symbolic or template values to be passed in.\n\n**Future work:** We might also allow `template` bindings for interface\nparameters, once we have a use case.\n\n**Note:** Interface parameters aren't required to be facets, but that is the\nvast majority of cases. As an example, if we had an interface that allowed a\ntype to define how the tuple-member-read operator would work, the index of the\nmember could be an interface parameter:\n\n```carbon\ninterface ReadTupleMember(index:! u32) {\n  let T:! type;\n  // Returns self[index]\n  fn Get[self: Self]() -> T;\n}\n```\n\nThis requires that the index be known at compile time, but allows different\nindices to be associated with different values of `T`.\n\n**Caveat:** When implementing an interface twice for a type, the interface\nparameters are required to always be different. For example:\n\n```carbon\ninterface Map(FromType:! type, ToType:! type) {\n  fn Map[ref self: Self](needle: FromType) -> Optional(ToType);\n}\nclass Bijection(FromType:! type, ToType:! type) {\n  extend impl as Map(FromType, ToType) { ... }\n  extend impl as Map(ToType, FromType) { ... }\n}\n// ❌ Error: Bijection has two different impl definitions of\n// interface Map(String, String)\nvar oops: Bijection(String, String) = ...;\n```\n\nIn this case, it would be better to have an [adapting type](#adapting-types) to\ncontain the `impl` for the reverse map lookup, instead of implementing the `Map`\ninterface twice:\n\n```carbon\nclass Bijection(FromType:! type, ToType:! type) {\n  extend impl as Map(FromType, ToType) { ... }\n}\nclass ReverseLookup(FromType:! type, ToType:! type) {\n  adapt Bijection(FromType, ToType);\n  extend impl as Map(ToType, FromType) { ... }\n}\n```\n\n**Comparison with other languages:** Rust calls\n[traits with parameters \"generic traits\"](https://doc.rust-lang.org/reference/items/traits.html#generic-traits)\nand\n[uses them for operator overloading](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#default-generic-type-parameters-and-operator-overloading).\n\n[Rust uses the term \"type parameters\"](https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md#clearer-trait-matching)\nfor both interface facet parameters and associated facets. The difference is\nthat interface parameters are \"inputs\" since they _determine_ which `impl` to\nuse, and associated constants are \"outputs\" since they are determined _by_ the\n`impl`, but play no role in selecting the `impl`.\n\n### Parameterized named constraints\n\nCarbon also allows the [named constraint](#named-constraints) construct to\nsupport parameters. Those parameters work the same way as for interfaces.\n\n## Where constraints\n\nSo far, we have restricted a [symbolic facet binding](#symbolic-facet-bindings)\nby saying it has to implement an interface or a set of interfaces. There are a\nvariety of other constraints we would like to be able to express, such as\napplying restrictions to associated constants. This is done using the `where`\noperator that adds constraints to a [facet type](#facet-types).\n\nThe where operator can be applied to a facet type in a declaration context:\n\n```carbon\n// Constraints on generic function parameters:\nfn F[V:! D where ...](v: V) { ... }\n\n// Constraints on a class parameter:\nclass S(T:! B where ...) {\n  // Constraints on a method:\n  fn G[self: Self, V:! D where ...](v: V);\n}\n\n// Constraints on an interface parameter:\ninterface A(T:! B where ...) {\n  // Constraints on an associated facet:\n  let U:! C where ...;\n  // Constraints on an associated method:\n  fn G[self: Self, V:! D where ...](v: V);\n}\n```\n\nWe also allow you to name constraints using a `where` operator in a `let` or\n`constraint` definition. The expressions that can follow the `where` keyword are\ndescribed in the [\"kinds of `where` constraints\"](#kinds-of-where-constraints)\nsection, but generally look like boolean expressions that should evaluate to\n`true`.\n\nThe result of applying a `where` operator to a facet type is another facet type.\nNote that this expands the kinds of requirements that facet types can have from\njust interface requirements to also include the various kinds of constraints\ndiscussed later in this section. In addition, it can introduce relationships\nbetween different type variables, such as that a member of one is equal to a\nmember of another. The `where` operator is not associative, so a type expression\nusing multiple must use round parens `(`...`)` to specify grouping.\n\n> **Comparison with other languages:** Both Swift and Rust use `where` clauses\n> on declarations instead of in the expression syntax. These happen after the\n> type that is being constrained has been given a name and use that name to\n> express the constraint.\n>\n> Rust also supports\n> [directly passing in the values for associated types](https://rust-lang.github.io/rfcs/0195-associated-items.html#constraining-associated-types)\n> when using a trait as a constraint. This is helpful when specifying concrete\n> types for all associated types in a trait in order to\n> [make it object safe so it can be used to define a trait object type](https://rust-lang.github.io/rfcs/0195-associated-items.html#trait-objects).\n>\n> Rust is adding trait aliases\n> ([RFC](https://github.com/rust-lang/rfcs/blob/master/text/1733-trait-alias.md),\n> [tracking issue](https://github.com/rust-lang/rust/issues/41517)) to support\n> naming some classes of constraints.\n\n**References:** `where` constraints were added in proposal\n[#818: Constraints for generics (generics details 3)](https://github.com/carbon-language/carbon-lang/pull/818).\n\n### Kinds of `where` constraints\n\nThere are three kinds of `where` constraints, each of which uses a different\nbinary operator:\n\n-   _Rewrite constraints_: `where`...`=`...\n-   _Same-type constraints_: `where`...`==`...\n-   _Implements constraints_: `where`...`impls`...\n\nAnd there are two positions that `where` can be written:\n\n-   At the end of an `impl as` declaration, before the body of the impl.\n    ```carbon\n    impl Class as Interface where .A = i32 { ... }\n    ```\n-   Inside a type expression.\n    ```carbon\n    fn F[T: Interface where .A impls OtherInterface](t: T) { ... }\n    ```\n\nA rewrite constraint is written `where .A = B`, where `A` is the name of an\n[associated constant](#associated-constants) which is rewritten to `B`. Any use\nof `.A` thereafter is the same as using `B`, including direct access to the API\nof `B`.\n\nThe \"dot followed by the name of a member\" construct, like `.A`, is called a\n_designator_. The name of the designator is looked up in the constraint, and\nrefers to the value of that member for whatever type is to satisfy this\nconstraint.\n\n> **Concern:** Using `=` for this use case is not consistent with other `where`\n> clauses that write a boolean expression that evaluates to `true` when the\n> constraint is satisfied.\n\nA same-type constraint is written `where X == Y`, where `X` and `Y` both name\nfacets. The constraint is that `X as type` must be the same as `Y as type`. It\nwould normally only be used in the type expression position.\n\nA same-type constraint does not rewrite the type on the left-hand side to the\nright-hand side, and they are still treated as distinct types. A value of type\n`X` [would need to be cast](#satisfying-both-facet-types) to `Y` in order to use\nthe API of `Y`. So for constraint clauses that name a single facet type on the\nright-hand side, using a rewrite constraint is preferred. Note that switching\nbetween the two forms does not change which types satisfies the constraint, and\nso is a compatible change for callers.\n\nAn implements constraint is written `where T impls C`, where `T` is a facet and\n`C` is a facet type. The constraint is that `T` satisfies the requirements of\n`C`. It would normally only be used in the type expression position.\n\n**References:** The definition of rewrite and same-type constraints were in\n[proposal #2173](https://github.com/carbon-language/carbon-lang/pull/2173).\nImplements constraints switched to using the `impls` keyword in\n[proposal #2483](https://github.com/carbon-language/carbon-lang/pull/2483).\n\n**Alternatives considered:**\n\n-   [Different equality constraint operators for symbolic and constants](/proposals/p2173.md#status-quo)\n-   [Single one-step equality constraint operators that merges constraints](/proposals/p2173.md#equal-types-with-different-interfaces)\n-   [Restrict constraints to allow computable type equality](/proposals/p2173.md#restrict-constraints-to-allow-computable-type-equality)\n-   [Find a fully transitive approach to type equality](/proposals/p2173.md#find-a-fully-transitive-approach-to-type-equality)\n-   [Different syntax for rewrite constraint](/proposals/p2173.md#different-syntax-for-rewrite-constraint)\n-   [Different syntax for same-type constraint](/proposals/p2173.md#different-syntax-for-same-type-constraint)\n-   [Required ordering for rewrites](/proposals/p2173.md#required-ordering-for-rewrites)\n-   [Multi-constraint `where` clauses](/proposals/p2173.md#multi-constraint-where-clauses)\n-   [Rewrite constraints in `require` constraints](/proposals/p2173.md#rewrite-constraints-in-impl-as-constraints)\n\n#### Recursive constraints\n\nWe sometimes need to constrain a type to equal one of its associated facets. In\nthis first example, we want to represent the function `Abs` which will return\n`Self` for some but not all types, so we use an associated facet `MagnitudeType`\nto encode the return type:\n\n```carbon\ninterface HasAbs {\n  extend Numeric;\n  let MagnitudeType:! Numeric;\n  fn Abs[self: Self]() -> MagnitudeType;\n}\n```\n\nFor types representing subsets of the real numbers, such as `i32` or `f32`, the\n`MagnitudeType` will match `Self`, the type implementing an interface. For types\nrepresenting complex numbers, the types will be different. For example, the\n`Abs()` function applied to a `Complex64` value would produce a `f32` result.\nThe goal is to write a constraint to restrict to the first case.\n\nIn a second example, when you take the slice of a type implementing `Container`\nyou get a type implementing `Container` which may or may not be the same type as\nthe original container type. However, taking the slice of a slice always gives\nyou the same type, and some functions want to only operate on containers whose\nslice type is the same as the container type.\n\nTo solve this problem, we think of `Self` as an actual associated facet member\nof every interface. We can then address it using `.Self` in a `where` clause,\nlike any other associated facet member.\n\n```carbon\nfn Relu[T:! HasAbs where .MagnitudeType = .Self](x: T) {\n  // T.MagnitudeType == T so the following is allowed:\n  return (x.Abs() + x) / 2;\n}\nfn UseContainer[T:! Container where .SliceType = .Self](c: T) -> bool {\n  // T.SliceType == T so `c` and `c.Slice(...)` can be compared:\n  return c == c.Slice(...);\n}\n```\n\nNotice that in an interface definition, `Self` refers to the type implementing\nthis interface while `.Self` refers to the associated facet currently being\ndefined.\n\n```carbon\ninterface Container;\nconstraint SliceConstraint(E:! type, S:! Container);\n\ninterface Container {\n  let ElementType:! type;\n  let IteratorType:! Iterator where .ElementType = ElementType;\n\n  // `.Self` means `SliceType`.\n  let SliceType:! Container where .Self impls SliceConstraint(ElementType, .Self);\n\n  // `Self` means the type implementing `Container`.\n  fn GetSlice[ref self: Self]\n      (start: IteratorType, end: IteratorType) -> SliceType;\n}\n\nconstraint SliceConstraint(E:! type, S:! Container) {\n  extend Container where .ElementType = E and\n                         .SliceType = S;\n}\n```\n\nNote that [naming](#named-constraint-constants) a recursive constraint using the\n[`constraint` introducer](#named-constraints) approach, we can name the\nimplementing type using `Self` instead of `.Self`, since they refer to the same\ntype. Note though they are different facets with different facet types:\n\n```carbon\nconstraint RealAbs {\n  extend HasAbs where .MagnitudeType = Self;\n  // Satisfied by the same types:\n  extend HasAbs where .MagnitudeType = .Self;\n\n  // While `Self as type` is the same as `.Self as type`,\n  // they are different as facets: `Self` has type\n  // `RealAbs` and `.Self` has type `HasAbs`.\n}\n\nconstraint ContainerIsSlice {\n  extend Container where .SliceType = Self;\n  // Satisfied by the same types:\n  extend Container where .SliceType = .Self;\n\n  // `Self` has type `ContainerIsSlice` and\n  // `.Self` has type `Container`.\n}\n```\n\nThe `.Self` construct follows these rules:\n\n-   `X :!` introduces `.Self:! type`, where references to `.Self` are resolved\n    to `X`. This allows you to use `.Self` as an interface parameter as in\n    `X:! I(.Self)`.\n-   `A where` introduces `.Self:! A` and a `.Foo` _designator_ for each member\n    `Foo` of `A`.\n-   It's an error to reference `.Self` if it refers to more than one different\n    thing or isn't a facet.\n-   You get the innermost, most-specific type for `.Self` if it is introduced\n    twice in a scope. By the previous rule, it is only legal if they all refer\n    to the same facet binding.\n-   `.Self` may not be on the left side of the `=` in a rewrite constraint.\n\nSo in `X:! A where ...`, `.Self` is introduced twice, after the `:!` and the\n`where`. This is allowed since both times it means `X`. After the `:!`, `.Self`\nhas the type `type`, which gets refined to `A` after the `where`. In contrast,\nit is an error if `.Self` could mean two different things, as in:\n\n```carbon\n// ❌ Illegal: `.Self` could mean `T` or `T.A`.\nfn F[T:! InterfaceA where .A impls\n           (InterfaceB where .B = .Self)](x: T);\n```\n\nThese two meanings can be disambiguated by defining a\n[`constraint`](#named-constraints):\n\n```carbon\nconstraint InterfaceBWithSelf {\n  extend InterfaceB where .B = Self;\n}\nconstraint InterfaceBWith(U:! InterfaceA) {\n  extend InterfaceB where .B = U;\n}\n// `T.A impls InterfaceB where .B = T.A`\nfn F[T:! InterfaceA where .A impls InterfaceBWithSelf](x: T);\n// `T.A impls InterfaceB where .B = T`\nfn F[T:! InterfaceA where .A impls InterfaceBWith(.Self)](x: T);\n```\n\n#### Rewrite constraints\n\nIn a rewrite constraint, the left-hand operand of `=` must be a `.` followed by\nthe name of an associated constant. `.Self` is not permitted.\n\n```carbon\ninterface RewriteSelf {\n  // ❌ Error: `.Self` is not the name of an associated constant.\n  let Me:! type where .Self = Self;\n}\ninterface HasAssoc {\n  let Assoc:! type;\n}\ninterface RewriteSingleLevel {\n  // ✅ Uses of `A.Assoc` will be rewritten to `i32`.\n  let A:! HasAssoc where .Assoc = i32;\n}\ninterface RewriteMultiLevel {\n  // ❌ Error: Only one level of associated constant is permitted.\n  let B:! RewriteSingleLevel where .A.Assoc = i32;\n}\n```\n\nThis notation is permitted anywhere a constraint can be written, and results in\na new constraint with a different interface: the named member effectively no\nlonger names an associated constant of the constrained type, and is instead\ntreated as a rewrite rule that expands to the right-hand side of the constraint,\nwith any mentioned parameters substituted into that type.\n\n```carbon\ninterface Container {\n  let Element:! type;\n  let Slice:! Container where .Element = Element;\n  fn Add[ref self: Self](x: Element);\n}\n// `T.Slice.Element` rewritten to `T.Element`\n//     because type of `T.Slice` says `.Element = Element`.\n// `T.Element` rewritten to `i32`\n//     because type of `T` says `.Element = i32`.\nfn Add[T:! Container where .Element = i32](p: T*, y: T.Slice.Element) {\n  // ✅ Argument `y` has the same type `i32` as parameter `x` of\n  // `T.(Container.Add)`, which is also rewritten to `i32`.\n  p->Add(y);\n}\n```\n\nRewrites aren't performed on the left-hand side of such an `=`, so\n`where .A = .B and .A = C` is not rewritten to `where .A = .B and .B = C`.\nInstead, such a `where` clause is invalid when the constraint is\n[resolved](appendix-rewrite-constraints.md#rewrite-constraint-resolution) unless\neach rule for `.A` specifies the same rewrite.\n\nNote that `T:! C where .R = i32` can result in a type `T.R` whose behavior is\ndifferent from the behavior of `T.R` given `T:! C`. For example, member lookup\ninto `T.R` can find different results and operations can therefore have\ndifferent behavior. However, this does not violate\n[coherence](/proposals/p2173.md#coherence) because the facet types `C` and\n`C where .R = i32` don't differ by merely having more type information; rather,\nthey are different facet types that have an isomorphic set of values, somewhat\nlike `i32` and `u32`. An `=` constraint is not merely learning a new fact about\na type, it is requesting different behavior.\n\nThis approach has some good properties that\n[same-type constraints](#same-type-constraints) have problems with:\n\n-   [Equal types with different interfaces](/proposals/p2173.md#equal-types-with-different-interfaces):\n    When an associated facet is constrained to be a concrete type, it is\n    desirable for the associated facet to behave like that concrete type.\n-   [Type canonicalization](/proposals/p2173.md#type-canonicalization): to\n    enable efficient type equality.\n-   [Transitivity of equality of types](/proposals/p2173.md#transitivity-of-equality)\n\nThe precise rules governing rewrite constraints are described in\n[an appendix](appendix-rewrite-constraints.md).\n\n#### Same-type constraints\n\nA same-type constraint describes that two type expressions are known to evaluate\nto the same value. Unlike a [rewrite constraint](#rewrite-constraints), however,\nthe two type expressions are treated as distinct types when type-checking a\nsymbolic expression that refers to them.\n\nSame-type constraints are brought into scope, looked up, and resolved exactly as\nif there were a `SameAs(U:! type)` interface and a `T == U` impl corresponded to\n`T is SameAs(U)`, except that `==` is commutative.\n\nFurther, same-type equalities apply to type components, so that `X(A, B, C)` is\n`SameType(X(D, E, F))` if we know that `A == D`, `B == E`, and `C == F`. Stated\ndifferently, if `F` is any pure type function, `T impls SameAs(U)` implies\n`F(T) impls SameAs(F(U))`. For example, if we know that `T == i32` then we also\nhave `Vector(T)` is single-step equal to `Vector(i32)`.\n\nThis relationship is not transitive, though, so it's not possible to ask for a\nlist of types that are the same as a given type, nor to ask whether there exists\na type that is the same as a given type and has some property. But it is\npossible to ask whether two types are (non-transitively) known to be the same.\n\nIn order for same-type constraints to be useful, they must allow the two types\nto be treated as actually being the same in some context. This can be\naccomplished by the use of `==` constraints in an `impl`, such as in the\nbuilt-in implementation of `ImplicitAs`:\n\n```carbon\nfinal impl forall [T:! type, U:! type where .Self == T] T as ImplicitAs(U) {\n  fn Convert[self: Self](other: U) -> U { ... }\n}\n```\n\n> **Alternative considered:** It superficially seems like it would be convenient\n> if such implementations were made available implicitly –- for example, by\n> writing `impl forall [T:! type] T as ImplicitAs(T)` -– but in more complex\n> examples that turns out to be problematic. Consider:\n>\n> ```carbon\n> interface CommonTypeWith(U:! type) {\n>   let Result:! type;\n> }\n> final impl forall [T:! type] T as CommonTypeWith(T) where .Result = T {}\n>\n> fn F[T:! Potato, U:! Hashable where .Self == T](x: T, y: U) -> auto {\n>   // What is T.CommonTypeWith(U).Result? Is it T or U?\n>  return (if cond then x else y).Hash();\n> }\n> ```\n>\n> With this alternative, `impl` validation for `T as CommonTypeWith(U)` fails:\n> we cannot pick a common type when given two distinct type expressions, even if\n> we know they evaluate to the same type, because we would not know which API\n> the result should have.\n\n##### Implementation of same-type `ImplicitAs`\n\nIt is possible to implement the above `impl` of `ImplicitAs` directly in Carbon,\nwithout a compiler builtin, by taking advantage of the built-in conversion\nbetween `C where .A = X` and `C where .A == X`:\n\n```carbon\ninterface EqualConverter {\n  let T:! type;\n  fn Convert(t: T) -> Self;\n}\nfn EqualConvert[T:! type](t: T, U:! EqualConverter where .T = T) -> U {\n  return U.Convert(t);\n}\nimpl forall [U:! type] U as EqualConverter where .T = U {\n  fn Convert(u: U) -> U { return u; }\n}\n\nimpl forall [T:! type, U:! type where .Self == T] T as ImplicitAs(U) {\n  fn Convert[self: Self]() -> U { return EqualConvert(self, U); }\n}\n```\n\nThe transition from `(T as ImplicitAs(U)).Convert`, where we know that `U == T`,\nto `EqualConverter.Convert`, where we know that `.T = U`, allows a same-type\nconstraint to be used to perform a rewrite.\n\n##### Manual type equality\n\nA same-type constraint establishes\n[type expressions](terminology.md#type-expression) are equal, and allows\nimplicit conversions between them. However, determining whether two type\nexpressions are _transitively_ equal is in general undecidable, as\n[has been shown in Swift](https://forums.swift.org/t/swift-type-checking-is-undecidable/39024).\n\nCarbon does not combine these equalities between type expressions. This means\nthat if two type expressions are only transitively equal, the user will need to\ninclude a sequence of casts or use an\n[`observe` declaration](#observe-declarations) to convert between them.\n\nGiven this interface `Transitive` that has associated facets that are\nconstrained to all be equal, with interfaces `P`, `Q`, and `R`:\n\n```carbon\ninterface P { fn InP[self: Self](); }\ninterface Q { fn InQ[self: Self](); }\ninterface R { fn InR[self: Self](); }\n\ninterface Transitive {\n  let A:! P;\n  let B:! Q where .Self == A;\n  let C:! R where .Self == B;\n\n  fn GetA[self: Self]() -> A;\n  fn TakesC[self: Self](c: C);\n}\n```\n\nA cast to `B` is needed to call `TakesC` with a value of type `A`, so each step\nonly relies on one equality:\n\n```carbon\nfn F[T:! Transitive](t: T) {\n  // ✅ Allowed\n  t.TakesC(t.GetA() as T.B);\n\n  // ✅ Allowed\n  let b: T.B = t.GetA();\n  t.TakesC(b);\n\n  // ❌ Not allowed: t.TakesC(t.GetA());\n}\n```\n\nThe compiler may have several different `where` clauses to consider,\nparticularly when an interface has associated facets that recursively satisfy\nthe same interface, or mutual recursion between multiple interfaces. For\nexample, given these `Edge` and `Node` interfaces (similar to those defined in\n[the section on interfaces with cyclic references](#example-of-declaring-interfaces-with-cyclic-references),\nbut using `==` same-type constraints):\n\n```carbon\ninterface Edge;\ninterface Node;\n\nprivate constraint EdgeFor(NodeT:! Node);\nprivate constraint NodeFor(EdgeT:! Edge);\n\ninterface Edge {\n  let N:! NodeFor(Self);\n  fn GetN[self: Self]() -> N;\n}\ninterface Node {\n  let E:! EdgeFor(Self);\n  fn GetE[self: Self]() -> E;\n  fn AddE[ref self: Self](e: E);\n  fn NearN[self: Self](n: Self) -> bool;\n}\n\nconstraint EdgeFor(NodeT:! Node) {\n  extend Edge where .N == NodeT;\n}\nconstraint NodeFor(EdgeT:! Edge) {\n  extend Node where .E == EdgeT;\n}\n```\n\nand a function `H` taking a value with some type implementing the `Node`\ninterface, then the following would be legal statements in `H`:\n\n```carbon\nfn H[N:! Node](n: N) {\n  // ✅ Legal: argument has type `N.E`, matches parameter\n  n.AddE(n.GetE());\n\n  // ✅ Legal:\n  // - argument has type `N.E.N`\n  // - `N.E` has type `EdgeFor(Self)` where `Self`\n  //   is `N`, which means `Edge where .N == N`\n  // - so we have the constraint `N.E.N == N`\n  // - which means the argument type `N.E.N`\n  //   is equal to the parameter type `N` using a\n  //   single `==` constraint.\n  n.NearN(n.GetE().GetN());\n\n  // ✅ Legal:\n  // - type `N.E.N.E.N` may be cast to `N.E.N`\n  //   using a single `where ==` clause, either\n  //   `(N.E.N).E.N == (N).E.N` or\n  //   `N.E.(N.E.N) == N.E.(N)`\n  // - argument of type `N.E.N` may be passed to\n  //   function expecting `N`, using a single\n  //   `where ==` clause, as in the previous call.\n  n.NearN(n.GetE().GetN().GetE().GetN() as N.E.N);\n}\n```\n\nThat last call would not be legal without the cast, though.\n\n**Comparison with other languages:** Other languages such as Swift and Rust\ninstead perform automatic type equality. In practice this means that their\ncompiler can reject some legal programs based on heuristics simply to avoid\nrunning for an unbounded length of time.\n\nThe benefits of the manual approach include:\n\n-   fast compilation, since the compiler does not need to explore a potentially\n    large set of combinations of equality restrictions, supporting\n    [Carbon's goal of fast and scalable development](/docs/project/goals.md#fast-and-scalable-development);\n-   expressive and predictable semantics, since there are no limitations on how\n    complex a set of constraints can be supported; and\n-   simplicity.\n\nThe main downsides are:\n\n-   manual work for the source code author to prove to the compiler that types\n    are equal; and\n-   verbosity.\n\nWe expect that rich error messages and IDE tooling will be able to suggest\nchanges to the source code when a single equality constraint is not sufficient\nto show two type expressions are equal, but a more extensive automated search\ncan find a sequence that prove they are equal.\n\n##### Observe declarations\n\nSame-type constraints are non-transitive, just like `ImplicitAs`. The developer\ncan use an `observe` declaration to bring a new same-type constraint into scope:\n\n```carbon\nobserve A == B == C;\n```\n\nnotionally does much the same thing as\n\n```carbon\nimpl A as SameAs(C) { ... }\n```\n\nwhere the `impl` makes use of `A impls SameAs(B)` and `B impls SameAs(C)`.\n\nIn general, an `observe` declaration lists a sequence of\n[type expressions](terminology.md#type-expression) that are equal by some\nsame-type `where` constraints. These `observe` declarations may be included in\nan `interface` definition or a function body, as in:\n\n```carbon\ninterface Edge {\n  let N:! type;\n}\ninterface Node {\n  let E:! type;\n}\ninterface Graph {\n  let E:! Edge;\n  let N:! Node where .E == E and E.N == .Self;\n  observe E == N.E == E.N.E == N.E.N.E;\n  // ...\n}\n\nfn H[G: Graph](g: G) {\n  observe G.N == G.E.N == G.N.E.N == G.E.N.E.N;\n  // ...\n}\n```\n\nEvery type expression after the first must be equal to some earlier type\nexpression in the sequence by a single `where` equality constraint. In this\nexample,\n\n```carbon\nfn J[G: Graph](g: G) {\n  observe G.E.N == G.N.E.N == G.N == G.E.N.E.N;\n  // ...\n}\n```\n\nthe expression `G.E.N.E.N` is one equality away from `G.N.E.N` and so it is\nallowed. This is true even though `G.N.E.N` isn't the type expression\nimmediately prior to `G.E.N.E.N`.\n\nAfter an `observe` declaration, all of the listed type expressions are\nconsidered equal to each other using a single `where` equality. In this example,\nthe `observe` declaration in the `Transitive` interface definition provides the\nlink between associated facets `A` and `C` that allows function `F` to type\ncheck.\n\n```carbon\ninterface P { fn InP[self: Self](); }\ninterface Q { fn InQ[self: Self](); }\ninterface R { fn InR[self: Self](); }\n\ninterface Transitive {\n  let A:! P;\n  let B:! Q where .Self == A;\n  let C:! R where .Self == B;\n\n  fn GetA[self: Self]() -> A;\n  fn TakesC[self: Self](c: C);\n\n  // Without this `observe` declaration, the\n  // calls in `F` below would not be allowed.\n  observe A == B == C;\n}\n\nfn F[T:! Transitive](t: T) {\n  var a: T.A = t.GetA();\n\n  // ✅ Allowed: `T.A` values implicitly convert to\n  // `T.C` using `observe` in interface definition.\n  t.TakesC(a);\n\n  // ✅ Allowed: `T.C` extends and implements `R`.\n  (a as T.C).InR();\n}\n```\n\nOnly the current type is searched for interface implementations, so the call to\n`InR()` would be illegal without the cast. However, an\n[`observe`...`==`...`impls` declaration](#observing-equal-to-a-type-implementing-an-interface)\ncan be used to identify interfaces that must be implemented through some equal\ntype. This does not [extend](terminology.md#extending-an-impl) the API of the\ntype, that is solely determined by the definition of the type. Continuing the\nprevious example:\n\n```carbon\nfn TakesPQR[U:! P & Q & R](u: U);\n\nfn G[T:! Transitive](t: T) {\n  var a: T.A = t.GetA();\n\n  // ✅ Allowed: `T.A` implements `P` and\n  // includes its API, as if it extends `P`.\n  a.InP();\n\n  // ❌ Illegal: only the current type is\n  // searched for interface implementations.\n  a.(Q.InQ)();\n\n  // ✅ Allowed: values of type `T.A` may be cast\n  // to `T.B`, which extends and implements `Q`.\n  (a as T.B).InQ();\n\n  // ✅ Allowed: `T.A` == `T.B` that implements `Q`.\n  observe T.A == T.B impls Q;\n  a.(Q.InQ)();\n\n  // ❌ Illegal: `T.A` still does not extend `Q`.\n  a.InQ();\n\n  // ✅ Allowed: `T.A` implements `P`,\n  // `T.A` == `T.B` that implements `Q` (observe above),\n  // and `T.A` == `T.C` that implements `R`.\n  observe T.A == T.C impls R;\n  TakesPQR(a);\n}\n```\n\nSince adding an `observe`...`impls` declaration only adds non-extending\nimplementations of interfaces to symbolic facets, they may be added without\nbreaking existing code.\n\n#### Implements constraints\n\nAn _implements constraint_ is written `where T impls C`, and expresses that the\nfacet `T` must implement the requirements of facet type `C`. This is more\nflexible than using\n[`&` to add a constraint](#combining-interfaces-by-anding-facet-types) since it\ncan be applied to [associated facet](#associated-facets) members as well.\n\nIn the following example, normally the `ElementType` of a `Container` can be any\ntype. The `SortContainer` function, however, takes a pointer to a type\nsatisfying `Container` with the additional constraint that its `ElementType`\nmust satisfy the `Ordered` interface, using an `impls` constraint:\n\n```carbon\ninterface Container {\n  let ElementType:! type;\n  ...\n}\n\nfn SortContainer\n    [ContainerType:! Container where .ElementType impls Ordered]\n    (container_to_sort: ContainerType*);\n```\n\nIn contrast to a [rewrite constraint](#rewrite-constraints) or a\n[same-type constraint](#same-type-constraints), this does not say what type\n`ElementType` exactly is, just that it must satisfy the requirements of some\nfacet type.\n\nThe specific case of a clause of the form\n`where .AssociatedFacet impls AConstraint`, where the constraint is applied to a\ndirect associated facet member of the facet type being constrained (similar to\nthe restriction on [rewrite constraints](#rewrite-constraints)), gets special\ntreatment. In this case, the type of the associated facet is\n[combined](#combining-interfaces-by-anding-facet-types) with the constraint. In\nthe above example, `Container` defines `ElementType` as having type `type`, but\n`ContainerType.ElementType` has type `type & Ordered` (which is equivalent to\n`Ordered`). This is because `ContainerType` has type\n`Container where .ElementType impls Ordered`, not `Container`. This means we\nneed to be a bit careful when talking about the type of `ContainerType` when\nthere is a `where` clause modifying it.\n\n> **Future work:** We may want to use a different operator in this case, such as\n> `&=`, in place of `impls`, to reflect the change in the type. This is\n> analogous to rewrite constraints using `=` instead of `==` to visibly reflect\n> the different impact on the type.\n\nAn implements constraint can be applied to [`.Self`](#recursive-constraints), as\nin `I where .Self impls C`. This has the same requirements as `I & C`, but that\n`where` clause does not affect the API. This means that a\n[symbolic facet binding](#symbolic-facet-bindings) with that facet type, so `T`\nin `T:! I where .Self impls C`, is represented by an\n[archetype](terminology.md#archetype) that implements both `I` and `C`, but only\n[extends](terminology.md#extending-an-impl) `I`.\n\n##### Implied constraints\n\nImagine we have a checked-generic function that accepts an arbitrary\n[`HashMap` parameterized type](#parameterized-types):\n\n```carbon\nfn LookUp[KeyT:! type](hm: HashMap(KeyT, i32)*,\n                       k: KeyT) -> i32;\n\nfn PrintValueOrDefault[KeyT:! Printable,\n                       ValueT:! Printable & HasDefault]\n    (map: HashMap(KeyT, ValueT), key: KeyT);\n```\n\nThe `KeyT` in these declarations does not visibly satisfy the requirements of\n`HashMap`, which requires the type implement `Hashable` and other interfaces:\n\n```carbon\nclass HashMap(\n    KeyT:! Hashable & Eq & Movable,\n    ...) { ... }\n```\n\nIn this case, `KeyT` gets `Hashable` and so on as _implied constraints_.\nEffectively that means that these functions are automatically rewritten to add a\n`where .Self impls` constraint on `KeyT`:\n\n```carbon\nfn LookUp[\n    KeyT:! type\n        where .Self impls Hashable & Eq & Movable]\n    (hm: HashMap(KeyT, i32)*, k: KeyT) -> i32;\n\nfn PrintValueOrDefault[\n    KeyT:! Printable\n        where .Self impls Hashable & Eq & Movable,\n    ValueT:! Printable & HasDefault]\n    (map: HashMap(KeyT, ValueT), key: KeyT);\n```\n\nIn this case, Carbon will accept the definition and infer the needed constraints\non the symbolic facet parameter. This is both more concise for the author of the\ncode and follows the\n[\"don't repeat yourself\" principle](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).\nThis redundancy is undesirable since it means if the needed constraints for\n`HashMap` are changed, then the code has to be updated in more locations.\nFurther it can add noise that obscures relevant information. In practice, any\nuser of these functions will have to pass in a valid `HashMap` instance, and so\nwill have already satisfied these constraints.\n\nThis implied constraint is equivalent to the explicit constraint that each\nparameter and return type [is legal](#must-be-legal-type-argument-constraints).\n\n> **Note:** These implied constraints affect the _requirements_ of a symbolic\n> facet parameter, but not its _member names_. This way you can always look at\n> the declaration to see how name resolution works, without having to look up\n> the definitions of everything it is used as an argument to.\n\n**Limitation:** To limit readability concerns and ambiguity, this feature is\nlimited to a single signature. Consider this interface declaration:\n\n```carbon\ninterface GraphNode {\n  let Edge:! type;\n  fn EdgesFrom[self: Self]() -> HashSet(Edge);\n}\n```\n\nOne approach would be to say the use of `HashSet(Edge)` in the signature of the\n`EdgesFrom` function would imply that `Edge` satisfies the requirements of an\nargument to `HashSet`, such as being `Hashable`. Another approach would be to\nsay that the `EdgesFrom` would only be conditionally available when `Edge` does\nsatisfy the constraints on `HashSet` arguments. Instead, Carbon will reject this\ndefinition, requiring the user to include all the constraints required for the\nother declarations in the interface in the declaration of the `Edge` associated\nfacet. Similarly, a parameter to a class must be declared with all the\nconstraints needed to declare the members of the class that depend on that\nparameter.\n\n**Comparison with other languages:** Both Swift\n([1](https://www.swiftbysundell.com/tips/inferred-generic-type-constraints/),\n[2](https://github.com/apple/swift/blob/main/docs/archive/Generics.rst#constraint-inference))\nand\n[Rust](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0b2d645bd205f24a7a6e2330d652c32e)\nsupport some form of this feature as part of their type inference (and\n[the Rust community is considering expanding support](http://smallcultfollowing.com/babysteps//blog/2022/04/12/implied-bounds-and-perfect-derive/#expanded-implied-bounds)).\n\n#### Combining constraints\n\nConstraints can be combined by separating constraint clauses with the `and`\nkeyword. This example expresses a constraint that two associated facets are\nequal and satisfy an interface:\n\n```carbon\nfn EqualContainers\n    [CT1:! Container,\n     CT2:! Container where .ElementType impls HasEquality\n                       and .ElementType = CT1.ElementType]\n    (c1: CT1*, c2: CT2*) -> bool;\n```\n\n**Comparison with other languages:** Swift and Rust use commas `,` to separate\nconstraint clauses, but that only works because they place the `where` in a\ndifferent position in a declaration. In Carbon, the `where` is attached to a\ntype in a parameter list that is already using commas to separate parameters.\n\n### Satisfying both facet types\n\nIf the two facet bindings being constrained to be equal, using either a\n[rewrite constraint](#rewrite-constraints) or a\n[same-type constraint](#same-type-constraints), have been declared with\ndifferent facet types, then the actual type value they are set to will have to\nsatisfy the requirements of both facet types. For example, if\n`SortedContainer.ElementType` is declared to have a `Ordered` requirement, then\nin these declarations:\n\n```carbon\n// With `=` rewrite constraint:\nfn Contains_Rewrite\n    [SC:! SortedContainer,\n     CT:! Container where .ElementType = SC.ElementType]\n    (haystack: SC, needles: CT) -> bool;\n\n// With `==` same-type constraint:\nfn Contains_SameType\n    [SC:! SortedContainer,\n     CT:! Container where .ElementType == SC.ElementType]\n    (haystack: SC, needles: CT) -> bool;\n```\n\nthe `where` constraints in both cases mean `CT.ElementType` must satisfy\n`Ordered` as well. However, the behavior inside the body of these two inside the\nbody of the two functions is different.\n\nIn `Contains_Rewrite`, `CT.ElementType` is rewritten to `SC.ElementType` and\nuses the facet type of `SC.ElementType`.\n\nIn `Contains_SameType`, the `where` clause does not affect the API of\n`CT.ElementType`, and it would not even be considered to implement `Ordered`\nunless there is some declaration like\n`observe CT.ElementType == SC.ElementType impls Ordered`. Even then, the items\nfrom the `needles` container won't directly have a `Compare` method member.\n\nThe rule is that a same-type `where` constraint between two type variables does\nnot modify the set of member names of either type. This is in contrast to\nrewrite constraints like `where .ElementType = String` with a `=`, then\n`.ElementType` is actually set to `String` including the complete `String` API.\n\nNote that `==` constraints are symmetric, so the previous declaration of\n`Contains_SameType` is equivalent to an alternative declaration where `CT` is\ndeclared first and the `where` clause is attached to `SortedContainer`:\n\n```carbon\nfn Contains_SameType_Equivalent\n    [CT:! Container,\n     SC:! SortedContainer where .ElementType == CT.ElementType]\n    (haystack: SC, needles: CT) -> bool;\n```\n\n### Constraints must use a designator\n\nWe don't allow a `where` constraint unless it applies a restriction to the\ncurrent type. This means referring to some\n[designator](#kinds-of-where-constraints), like `.MemberName`, or\n[`.Self`](#recursive-constraints). Examples:\n\n-   `Container where .ElementType = i32`\n-   `type where Vector(.Self) impls Sortable`\n-   `Addable where i32 impls AddableWith(.Result)`\n\nConstraints that only refer to other types should be moved to the type that is\ndeclared last. So:\n\n```carbon\n// ❌ Error: `where A == B` does not use `.Self` or a designator\nfn F[A:! type, B:! type, C:! type where A == B](a: A, b: B, c: C);\n```\n\nmust be replaced by:\n\n```carbon\n// ✅ Allowed\nfn F[A:! type, B:! type where A == .Self, C:! type](a: A, b: B, c: C);\n```\n\nThis includes `where` clauses used in an `impl` declaration:\n\n```carbon\n// ❌ Error: `where T impls B` does not use `.Self` or a designator\nimpl forall [T:! type] T as A where T impls B {}\n// ✅ Allowed\nimpl forall [T:! type where .Self impls B] T as A {}\n// ✅ Allowed\nimpl forall [T:! B] T as A {}\n```\n\nThis clarifies the meaning of the `where` clause and reduces the number of\nredundant ways to express a restriction, following the\n[one-way principle](/docs/project/principles/one_way.md).\n\n**Alternative considered:** This rule was added in proposal\n[#2376](https://github.com/carbon-language/carbon-lang/pull/2376), which\n[considered whether this rule should be added](/proposals/p2376.md#alternatives-considered).\n\n### Referencing names in the interface being defined\n\nThe constraint in a `where` clause is required to only reference earlier names\nfrom this scope, as in this example:\n\n```carbon\n// ❌ Illegal: `E` references `V` declared later.\ninterface Graph {\n  let E: Edge where .V = V;\n  let V: Vert where .E = E;\n}\n\n// ✅ Allowed: Only references to earlier names.\ninterface Graph {\n  let E: Edge;\n  let V: Vert where .E = E and .Self == E.V;\n}\n```\n\n### Constraint examples and use cases\n\n-   **Set [associated constant](#associated-constants) to a constant:** For\n    example in `NSpacePoint where .N = 2`, the associated constant `N` of\n    `NSpacePoint` must be `2`. This syntax is also used to specify the values of\n    associated constants when implementing an interface for a type, as in\n    `impl MyPoint as NSpacePoint where .N = 2 {`...`}`.\n\n-   **Set an [associated facet](#associated-facets) to a specific value:**\n    Associated facets are treated like any other associated constant. So\n    `Stack where .ElementType = i32` is a facet type that restricts to types\n    that implement the `Stack` interface with integer elements, as in:\n\n    ```carbon\n    fn SumIntStack[T:! Stack where .ElementType = i32]\n        (s: T*) -> i32 {\n      var sum: i32 = 0;\n      while (!s->IsEmpty()) {\n        // s->Pop() returns a value of type\n        // `T.ElementType` which is `i32`:\n        sum += s->Pop();\n      }\n      return sum;\n    }\n    ```\n\n    Note that this is a case that can use an `==` same-type constraint instead\n    of an `=` rewrite constraint.\n\n-   **One [associated constant](#associated-constants) must equal another:** For\n    example with this definition of the interface `PointCloud`:\n\n    ```carbon\n    interface PointCloud {\n      let Dim:! i32;\n      let PointT:! NSpacePoint where .N = Dim;\n    }\n    ```\n\n    an implementation of `PointCloud` for a type `T` will have\n    `T.PointT.N == T.Dim`.\n\n-   **Equal facet bindings:**\n\n    For example, we could make the `ElementType` of an `Iterator` interface\n    equal to the `ElementType` of a `Container` interface as follows:\n\n    ```carbon\n    interface Iterator {\n      let ElementType:! type;\n      ...\n    }\n    interface Container {\n      let ElementType:! type;\n      let IteratorType:! Iterator where .ElementType = ElementType;\n      ...\n    }\n    ```\n\n    In a function signature, this may be done by referencing an earlier\n    parameter:\n\n    ```carbon\n    fn Map[CT:! Container,\n           FT:! Function where .InputType = CT.ElementType]\n          (c: CT, f: FT) -> Vector(FT.OutputType);\n    ```\n\n    In that example, `FT.InputType` is constrained to equal `CT.InputType`.\n    Given an interface with two associated facets\n\n    ```carbon\n    interface PairInterface {\n      let Left:! type;\n      let Right:! type;\n    }\n    ```\n\n    we can constrain them to be equal using\n    `PairInterface where .Left = .Right`.\n\n    Note that this is a case that can use an `==` same-type constraint instead\n    of an `=` rewrite constraint.\n\n-   **[Associated facet](#associated-facets) implements interface:** Given these\n    definitions (omitting `ElementType` for brevity):\n\n    ```carbon\n    interface IteratorInterface { ... }\n    interface ContainerInterface {\n      let IteratorType:! IteratorInterface;\n      // ...\n    }\n    interface RandomAccessIterator {\n      extend IteratorInterface;\n      // ...\n    }\n    ```\n\n    We can then define a function that only accepts types that implement\n    `ContainerInterface` where its `IteratorType` associated facet implements\n    `RandomAccessIterator`:\n\n    ```carbon\n    fn F[ContainerType:! ContainerInterface\n         where .IteratorType impls RandomAccessIterator]\n        (c: ContainerType);\n    ```\n\n#### Parameterized type implements interface\n\nThere are times when a function will pass a\n[symbolic facet parameter](#symbolic-facet-bindings) of the function as an\nargument to a [parameterized type](#parameterized-types), and the function needs\nthe result to implement a specific interface.\n\n```carbon\n// A parameterized type\nclass DynArray(T:! type) { ... }\n\ninterface Printable { fn Print[self: Self](); }\n\n// The parameterized type `DynArray` implements interface\n// `Printable` only for some arguments.\nimpl DynArray(String) as Printable { ... }\n\n// Constraint: `T` such that `DynArray(T)` implements `Printable`\nfn PrintThree\n    [T:! type where DynArray(.Self) impls Printable]\n    (a: T, b: T, c: T) {\n  // Create a `DynArray(T)` of size 3.\n  var v: auto = DynArray(T).Make(a, b, c);\n  // Known to be implemented due to the constraint on `T`.\n  v.(Printable.Print)();\n}\n\n// ✅ Allowed: `DynArray(String)` implements `Printable`.\nlet s: String = \"Ai \";\nPrintThree(s, s, s);\n// ❌ Forbidden: `DynArray(i32)` doesn't implement `Printable`.\nlet i: i32 = 3;\nPrintThree(i, i, i);\n```\n\n**Comparison with other languages:** This use case was part of the\n[Rust rationale for adding support for `where` clauses](https://rust-lang.github.io/rfcs/0135-where.html#motivation).\n\n#### Another type implements parameterized interface\n\nIn this case, we need some other type to implement an interface parameterized by\na [symbolic facet parameter](#symbolic-facet-bindings). The syntax for this case\nfollows the previous case, except now the `.Self` parameter is on the interface\nto the right of the `impls`. For example, we might need a type parameter `T` to\nsupport explicit conversion from an `i32`:\n\n```carbon\ninterface As(T:! type) {\n  fn Convert[self: Self]() -> T;\n}\n\nfn Double[T:! Mul where i32 impls As(.Self)](x: T) -> T {\n  return x * ((2 as i32) as T);\n}\n```\n\n#### Must be legal type argument constraints\n\nNow consider the case that the symbolic facet parameter is going to be used as\nan argument to a [parameterized type](#parameterized-types) in a function body,\nbut not in the signature. If the parameterized type was explicitly mentioned in\nthe signature, the [implied constraint](#implied-constraints) feature would\nensure all of its requirements were met. To say a parameterized type is allowed\nto be passed a specific argument, just write that it `impls type`, which all\ntypes do. This is a trivial case of a\n[parameterized type implements interface](#parameterized-type-implements-interface)\n`where` constraint.\n\nFor example, a function that adds its parameters to a `HashSet` to deduplicate\nthem, needs them to be `Hashable` and so on. To say \"`T` is a type where\n`HashSet(T)` is legal,\" we can write:\n\n```carbon\nfn NumDistinct[T:! type where HashSet(.Self) impls type]\n    (a: T, b: T, c: T) -> i32 {\n  var set: HashSet(T);\n  set.Add(a);\n  set.Add(b);\n  set.Add(c);\n  return set.Size();\n}\n```\n\nThis has the same advantages over repeating the constraints on `HashSet`\narguments in the type of `T` as other\n[implied constraints](#implied-constraints).\n\n### Named constraint constants\n\nA facet type with a `where` constraint, such as `C where <condition>`, can be\nnamed two different ways:\n\n-   Using `let template` as in:\n\n    ```carbon\n    let template NameOfConstraint:! auto = C where <condition>;\n    ```\n\n    or, since the type of a facet type is `type`:\n\n    ```carbon\n    let template NameOfConstraint:! type = C where <condition>;\n    ```\n\n-   Using a [named constraint](#named-constraints) with the `constraint` keyword\n    introducer:\n\n    ```carbon\n    constraint NameOfConstraint {\n      extend C where <condition>;\n    }\n    ```\n\nWhichever approach is used, the result is `NameOfConstraint` is a compile-time\nconstant that is equivalent to `C where <condition>`.\n\n## Other constraints as facet types\n\nThere are some constraints that Carbon naturally represents as named facet\ntypes. These can either be used directly to constrain a facet binding, or in a\n`where ... impls ...` [implements constraint](#implements-constraints) to\nconstrain an associated facet.\n\nThe compiler determines which types implement these interfaces, developers are\nnot permitted to explicitly implement these interfaces for their own types.\n\nThese facet types extend the requirements that facet types are allowed to\ninclude beyond [interfaces implemented](#facet-types) and\n[`where` clauses](#where-constraints).\n\n**Open question:** Are these names part of the prelude or in a standard library?\n\n### Is a derived class\n\nGiven a type `T`, `Extends(T)` is a facet type whose values are facets that are\n(transitively) [derived from](/docs/design/classes.md#inheritance) `T`. That is,\n`U:! Extends(T)` means `U` has an `extend base: T;` declaration, or there is a\nchain of `extend base` declarations connecting `T` to `U`.\n\n```carbon\nbase class BaseType { ... }\n\nfn F[T:! Extends(BaseType)](p: T*);\nfn UpCast[U:! type]\n    (p: U*, V:! type where U impls Extends(.Self)) -> V*;\nfn DownCast[X:! type](p: X*, Y:! Extends(X)) -> Y*;\n\nclass DerivedType {\n  extend base: BaseType;\n}\nvar d: DerivedType = {};\n// `T` is set to `DerivedType`\n// `DerivedType impls Extends(BaseType)`\nF(&d);\n\n// `U` is set to `DerivedType`\nlet p: BaseType* = UpCast(&d, BaseType);\n\n// `X` is set to `BaseType`\n// `Y` is set to facet `DerivedType as Extends(BaseType)`.\nAssert(DownCast(p, DerivedType) == &d);\n```\n\n**Open question:** Alternatively, we could define a new `extends` operator for\nuse in `where` clauses:\n\n```carbon\nfn F[T:! type where .Self extends BaseType](p: T*);\nfn UpCast[T:! type](p: T*, U:! type where T extends .Self) -> U*;\nfn DownCast[T:! type](p: T*, U:! type where .Self extends T) -> U*;\n```\n\n**Comparison to other languages:** In Swift, you can\n[add a required superclass to a type bound using `&`](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID282).\n\n### Type compatible with another type\n\nGiven a type `U`, define the facet type `CompatibleWith(U)` as follows:\n\n> `CompatibleWith(U)` is a facet type whose values are facets `T` such that\n> `T as type` and `U as type` are\n> [compatible types](terminology.md#compatible-types). That is values of `T` and\n> `U` as types can be cast back and forth without any change in representation\n> (for example `T` is an [adapter](#adapting-types) for `U`).\n\n`CompatibleWith` determines an equivalence relationship between types.\nSpecifically, given two types `T1` and `T2`, they are equivalent if\n`T1 impls CompatibleWith(T2)`, which is true if and only if\n`T2 impls CompatibleWith(T1)`.\n\n**Note:** Just like interface parameters, we require the user to supply `U`, it\nmay not be deduced. Specifically, this code would be illegal:\n\n```carbon\nfn Illegal[U:! type, T:! CompatibleWith(U)](x: T*) ...\n```\n\nIn general there would be multiple choices for `U` given a specific `T` here,\nand no good way of picking one. However, similar code is allowed if there is\nanother way of determining `U`:\n\n```carbon\nfn Allowed[U:! type, T:! CompatibleWith(U)](x: U*, y: T*) ...\n```\n\n#### Same implementation restriction\n\nIn some cases, we need to restrict to types that implement certain interfaces\nthe same way as the type `U`.\n\n> The values of facet type `CompatibleWith(U, C)` are facets satisfying\n> `CompatibleWith(U)` that have the same implementation of `C` as `U`.\n\nFor example, if we have a type `HashSet(T)`:\n\n```carbon\nclass HashSet(T:! Hashable) { ... }\n```\n\nThen `HashSet(T)` may be cast to `HashSet(U)` if\n`T impls CompatibleWith(U, Hashable)`. The one-parameter interpretation of\n`CompatibleWith(U)` is recovered by letting the default for the second parameter\n(`C`) be `type`.\n\n#### Example: Multiple implementations of the same interface\n\nThis allows us to represent functions that accept multiple implementations of\nthe same interface for a type.\n\n```carbon\nchoice CompareResult { Less, Equal, Greater }\ninterface Ordered {\n  fn Compare[self: Self](rhs: Self) -> CompareResult;\n}\nfn CombinedLess[T:! type](a: T, b: T,\n                          U:! CompatibleWith(T) & Ordered,\n                          V:! CompatibleWith(T) & Ordered) -> bool {\n  match ((a as U).Compare(b as U)) {\n    case .Less => { return True; }\n    case .Greater => { return False; }\n    case .Equal => {\n      return (a as V).Compare(b as V) == CompareResult.Less;\n    }\n  }\n}\n```\n\nUsed as:\n\n```carbon\nclass Song { ... }\nclass SongByArtist { adapt Song; impl as Ordered { ... } }\nclass SongByTitle { adapt Song; impl as Ordered { ... } }\nlet s1: Song = ...;\nlet s2: Song = ...;\nassert(CombinedLess(s1, s2, SongByArtist, SongByTitle) == True);\n```\n\n> **Open question:** We might generalize this to a list of implementations using\n> variadics:\n>\n> ```carbon\n> fn CombinedCompare[T:! type]\n>     (a: T, b: T, ... each CompareT:! CompatibleWith(T) & Ordered)\n>     -> CompareResult {\n>   ... block {\n>     let result: CompareResult =\n>         (a as each CompareT).Compare(b as each CompareT);\n>     if (result != CompareResult.Equal) {\n>       return result;\n>     }\n>   }\n>   return CompareResult.Equal;\n> }\n>\n> assert(CombinedCompare(s1, s2, SongByArtist, SongByTitle)\n>        == CompareResult.Less);\n> ```\n>\n> However, [variadic support](#variadic-arguments) is still future work.\n\n#### Example: Creating an impl out of other implementations\n\nAnd then to package this functionality as an implementation of `Ordered`, we\ncombine `CompatibleWith` with [type adaptation](#adapting-types) and\n[variadics](#variadic-arguments):\n\n```carbon\nclass ThenCompare(\n      T:! type,\n      ... each CompareT:! CompatibleWith(T) & Ordered) {\n  adapt T;\n  extend impl as Ordered {\n    fn Compare[self: Self](rhs: Self) -> CompareResult {\n      ... block {\n        let result: CompareResult =\n            (self as each CompareT).Compare(rhs as each CompareT);\n        if (result != CompareResult.Equal) {\n          return result;\n        }\n      }\n      return CompareResult.Equal;\n    }\n  }\n}\n\nlet template SongByArtistThenTitle:! auto =\n    ThenCompare(Song, SongByArtist, SongByTitle);\nvar s1: Song = ...;\nvar s2: SongByArtistThenTitle =\n    ({ ... } as Song) as SongByArtistThenTitle;\nassert((s1 as SongByArtistThenTitle).Compare(s2) ==\n       CompareResult.Less);\n```\n\n### Sized types and facet types\n\nWhat is the size of a type?\n\n-   It could be fully known and fixed at compile time -- this is true of\n    primitive types (`i32`, `f64`, and so on), most\n    [classes](/docs/design/classes.md), and most other concrete types.\n-   It could be known symbolically. This means that it will be known at codegen\n    time, but not at type-checking time.\n-   It could be dynamic. For example, it could be a\n    [dynamic type](#runtime-type-fields), a slice, variable-sized type (such as\n    [found in Rust](https://doc.rust-lang.org/nomicon/exotic-sizes.html#dynamically-sized-types-dsts)),\n    or you could dereference a pointer to a base class that could actually point\n    to a [derived class](/docs/design/classes.md#inheritance).\n-   It could be unknown which category the type is in. In practice this will be\n    essentially equivalent to having dynamic size.\n\nA type is called _sized_ if it is in the first two categories, and _unsized_\notherwise. Note: something with size 0 is still considered \"sized\". The facet\ntype `Sized` is defined as follows:\n\n> `Sized` is a type whose values are types `T` that are \"sized\" -- that is the\n> size of `T` is known, though possibly only symbolically\n\nKnowing a type is sized is a precondition to declaring variables of that type,\ntaking values of that type as parameters, returning values of that type, and\ndefining arrays of that type. Users will not typically need to express the\n`Sized` constraint explicitly, though, since it will usually be a dependency of\nsome other constraint the type will need such as `Movable` or `Concrete`.\n\nExample:\n\n```carbon\n// In the Carbon standard library\ninterface DefaultConstructible {\n  // Types must be sized to be default constructible.\n  require impls Sized;\n  fn Default() -> Self;\n}\n\n// Classes are \"sized\" by default.\nclass Name {\n  extend impl as DefaultConstructible {\n    fn Default() -> Self { ... }\n  }\n  ...\n}\n\nfn F[T:! type](x: T*) {  // T is unsized.\n  // ✅ Allowed: may access unsized values through a pointer.\n  var y: T* = x;\n  // ❌ Illegal: T is unsized.\n  var z: T;\n}\n\n// T is sized, but its size is only known symbolically.\nfn G[T: DefaultConstructible](x: T*) {\n  // ✅ Allowed: T is default constructible, which means sized.\n  var y: T = T.Default();\n}\n\nvar z: Name = Name.Default();;\n// ✅ Allowed: `Name` is sized and implements `DefaultConstructible`.\nG(&z);\n```\n\n**Open question:** Should the `Sized` facet type expose an associated constant\nwith the size? So you could say `T.ByteSize` in the above example to get a\nsymbolic integer value with the size of `T`. Similarly you might say\n`T.ByteStride` to get the number of bytes used for each element of an array of\n`T`.\n\n### Destructor constraints\n\nThere are four facet types related to\n[the destructors of types](/docs/design/classes.md#destructors):\n\n-   `Concrete` types may be local or member variables.\n-   `Deletable` types may be safely deallocated by pointer using the `Delete`\n    method on the `Allocator` used to allocate it.\n-   `Destructible` types have a destructor and may be deallocated by pointer\n    using the `UnsafeDelete` method on the correct `Allocator`, but it may be\n    unsafe. The concerning case is deleting a pointer to a derived class through\n    a pointer to its base class without a virtual destructor.\n-   `TrivialDestructor` types have empty destructors. This facet type may be\n    used with [specialization](#lookup-resolution-and-specialization) to unlock\n    specific optimizations.\n\n**Note:** The names `Deletable` and `Destructible` are\n[**placeholders**](/proposals/p1154.md#type-of-type-naming) since they do not\nconform to the decision on\n[question-for-leads issue #1058: \"How should interfaces for core functionality be named?\"](https://github.com/carbon-language/carbon-lang/issues/1058).\n\nThe facet types `Concrete`, `Deletable`, and `TrivialDestructor` all extend\n`Destructible`. Combinations of them may be formed using\n[the `&` operator](#combining-interfaces-by-anding-facet-types). For example, a\nchecked-generic function that both instantiates and deletes values of a type `T`\nwould require `T` implement `Concrete & Deletable`.\n\nTypes are forbidden from explicitly implementing these facet types directly.\nInstead they use\n[`destructor` declarations in their class definition](/docs/design/classes.md#destructors)\nand the compiler uses them to determine which of these facet types are\nimplemented.\n\n## Compile-time `let`\n\nA `let` statement inside a function body may be used to get the change in type\nbehavior of calling a checked-generic function without having to introduce a\nfunction call.\n\n```carbon\nfn SymbolicLet(...) {\n  ...\n  let T:! C = U;\n  X;\n  Y;\n  Z;\n}\n```\n\nThis introduces a symbolic constant `T` with type `C` and value `U`. This\nimplicitly includes an [`observe T == U;` declaration](#observe-declarations),\nwhen `T` and `U` are facets, which allows values to implicitly convert from the\nconcrete type `U` to the erased type `T`, as in:\n\n```carbon\nlet x: i32 = 7;\nlet T:! Add = i32;\n// ✅ Allowed to convert `i32` values to `T`.\nlet y: T = x;\n```\n\n> **TODO:** The implied `observe` declaration is from question-for-leads issue\n> [#996](https://github.com/carbon-language/carbon-lang/issues/996) and should\n> be approved in a proposal.\n\nThis makes the `SymbolicLet` function roughly equivalent to:\n\n```carbon\nfn SymbolicLet(...) {\n  ...\n  fn Closure(T:! C where .Self == U) {\n    X;\n    Y;\n    Z;\n  }\n  Closure(U);\n}\n```\n\nThe `where .Self == U` modifier captures the `observe` declaration introduced by\nthe `let` (at the cost of changing the type of `T`).\n\nA symbolic `let` can be used to switch to the API of `C` when `U` does not\nextend `C`, as an alternative to\n[using an adapter](#use-case-accessing-interface-names), or to simplify inlining\nof a generic function while preserving semantics.\n\nTo get a template binding instead of symbolic binding, add the `template`\nkeyword before the binding pattern, as in:\n\n```carbon\nfn TemplateLet(...) {\n  ...\n  let template T:! C = U;\n  X;\n  Y;\n  Z;\n}\n```\n\nwhich introduces a template constant `T` with type `C` and value `U`. This is\nroughly equivalent to:\n\n```carbon\nfn TemplateLet(...) {\n  ...\n  fn Closure(template T:! C) {\n    X;\n    Y;\n    Z;\n  }\n  Closure(U);\n}\n```\n\nIn this case, the `where .Self == U` modifier is superfluous.\n\n> **References:**\n>\n> -   Proposal\n>     [#950: Generics details 6: remove facets #950](https://github.com/carbon-language/carbon-lang/pull/950)\n> -   Question-for-leads issue\n>     [#996: Generic `let` with `auto`?](https://github.com/carbon-language/carbon-lang/issues/996)\n\n## Parameterized impl declarations\n\nThere are cases where an `impl` definition should apply to more than a single\ntype and interface combination. The solution is to parameterize the `impl`\ndefinition, so it applies to a family of types, interfaces, or both. This\nincludes:\n\n-   Defining an `impl` that applies to multiple arguments to a\n    [parameterized type](#parameterized-types).\n-   _Conditional conformance_ where a parameterized type implements some\n    interface if the parameter to the type satisfies some criteria, like\n    implementing the same interface.\n-   _Blanket_ `impl` declarations where an interface is implemented for all\n    types that implement another interface, or some other criteria beyond being\n    a specific type.\n-   _Wildcard_ `impl` declarations where a family of interfaces are implemented\n    for single type.\n\nThe syntax for an out-of-line parameterized `impl` declaration is:\n\n<!-- prettier-ignore-start -->\n\n<!-- The following triggers a bug in prettier where it adds an `>` -->\n\n> `impl forall [`_<parameter-bindings>_`]` _<type-expression>_ `as`\n> _<facet-type-expression> [_ `where` _<optional-rewrite-constraints> ]_ `;`\n\n<!-- prettier-ignore-end -->\n\nThis may also be called a _generic `impl` declaration_.\n\n### Impl for a parameterized type\n\nInterfaces may be implemented for a [parameterized type](#parameterized-types).\nThis can be done lexically in the class's scope:\n\n```carbon\nclass Vector(T:! type) {\n  impl as Iterable where .ElementType = T {\n    ...\n  }\n}\n```\n\nThis is equivalent to naming the implementing type between `impl` and `as`,\nthough this form is not allowed after `extend`:\n\n```carbon\nclass Vector(T:! type) {\n  impl Vector(T) as Iterable where .ElementType = T {\n    ...\n  }\n}\n```\n\nAn out-of-line `impl` declaration must declare all parameters in a `forall`\nclause:\n\n```carbon\nimpl forall [T:! type] Vector(T) as Iterable\n    where .ElementType = T {\n  ...\n}\n```\n\nThe parameter for the type can be used as an argument to the interface being\nimplemented, with or without `extend`:\n\n```carbon\nclass HashMap(KeyT:! Hashable, ValueT:! type) {\n  extend impl as Has(KeyT) { ... }\n  impl as Contains(HashSet(KeyT)) { ... }\n}\n```\n\nor out-of-line the same `forall` parameter can be passed to both:\n\n```carbon\nclass HashMap(KeyT:! Hashable, ValueT:! type) { ... }\nimpl forall [KeyT:! Hashable, ValueT:! type]\n    HashMap(KeyT, ValueT) as Has(KeyT) { ... }\nimpl forall [KeyT:! Hashable, ValueT:! type]\n    HashMap(KeyT, ValueT) as Contains(HashSet(KeyT)) { ... }\n```\n\n### Conditional conformance\n\n[Conditional conformance](terminology.md#conditional-conformance) is expressing\nthat we have an `impl` of some interface for some type, but only if some\nadditional type restrictions are met. Examples where this would be useful\ninclude being able to say that a container type, like `Vector`, implements some\ninterface when its element type satisfies the same interface:\n\n-   A container is printable if its elements are.\n-   A container could be compared to another container with the same element\n    type using a\n    [lexicographic comparison](https://en.wikipedia.org/wiki/Lexicographic_order)\n    if the element type is comparable.\n-   A container is copyable if its elements are.\n\nThis may be done by specifying a more specific implementing type to the left of\nthe `as` in the declaration:\n\n```carbon\ninterface Printable {\n  fn Print[self: Self]();\n}\nclass Vector(T:! type) { ... }\n\n// By saying \"T:! Printable\" instead of \"T:! type\" here,\n// we constrain `T` to be `Printable` for this impl.\nimpl forall [T:! Printable] Vector(T) as Printable {\n  fn Print[self: Self]() {\n    for (let a: T in self) {\n      // Can call `Print` on `a` since the constraint\n      // on `T` ensures it implements `Printable`.\n      a.Print();\n    }\n  }\n}\n```\n\nNote that no `forall` clause or type may be specified when declaring an `impl`\nwith the [`extend`](#extend-impl) keyword:\n\n```carbon\nclass Array(T:! type, template N:! i64) {\n  // ❌ Illegal: nothing allowed before `as` after `extend impl`:\n  extend impl forall [P:! Printable] Array(P, N) as Printable { ... }\n}\n```\n\n**Note:** This was changed in\n[proposal #2760](https://github.com/carbon-language/carbon-lang/pull/2760).\n\nInstead, the class can declare aliases to members of the interface. Those\naliases will only be usable when the type implements the interface.\n\n```carbon\nclass Array(T:! type, template N:! i64) {\n  alias Print = Printable.Print;\n}\nimpl forall [P:! Printable] Array(P, N) as Printable { ... }\n\nimpl String as Printable { ... }\nvar can_print: Array(String, 2) = (\"Hello \", \"world\");\n// ✅ Allowed: `can_print.Print` resolves to\n// `can_print.(Printable.Print)`, which exists as long as\n// `Array(String, 2) impls Printable`, which exists since\n// `String impls Printable`.\ncan_print.Print();\n\nvar no_print: Array(Unprintable, 2) = ...;\n// ❌ Illegal: `no_print.Print` resolves to\n// `no_print.(Printable.Print)`, but there is no\n// implementation of `Printable` for `Array(Unprintable, 2)`\n// as long as `Unprintable` doesn't implement `Printable`.\nno_print.Print();\n```\n\nIt is legal to declare or define a conditional impl lexically inside the class\nscope without `extend`, as in:\n\n```carbon\nclass Array(T:! type, template N:! i64) {\n  // ✅ Allowed: non-extending impl defined in class scope may\n  // use `forall` and may specify a type.\n  impl forall [P:! Printable] Array(P, N) as Printable { ... }\n}\n```\n\nInside the scope of this `impl` definition, both `P` and `T` refer to the same\ntype, but `P` has the facet type of `Printable` and so has a `Print` member. The\nrelationship between `T` and `P` is as if there was a\n[`where P == T` clause](#same-type-constraints).\n\n**Open question:** Need to resolve whether the `T` name can be reused, or if we\nrequire that you need to use new names, like `P`, when creating new type\nvariables.\n\n**Example:** Consider a type with two parameters, like `Pair(T, U)`. In this\nexample, the interface `Foo(T)` is only implemented when the two types are\nequal.\n\n```carbon\ninterface Foo(T:! type) { ... }\nclass Pair(T:! type, U:! type) { ... }\nimpl forall [T:! type] Pair(T, T) as Foo(T) { ... }\n```\n\nAs before, you may also define the `impl` inline, but it may not be combined\nwith the `extend` keyword:\n\n```carbon\nclass Pair(T:! type, U:! type) {\n  impl Pair(T, T) as Foo(T) { ... }\n}\n```\n\n**Clarification:** The same interface may be implemented multiple times as long\nas there is no overlap in the conditions:\n\n```carbon\nclass X(T:! type) {\n  // ✅ Allowed: `X(T).F` consistently means `X(T).(Foo.F)`\n  // even though that may have different definitions for\n  // different values of `T`.\n  alias F = Foo.F;\n}\nimpl X(i32) as Foo {\n  fn F[self: Self]() { DoOneThing(); }\n}\nimpl X(i64) as Foo {\n  fn F[self: Self]() { DoADifferentThing(); }\n}\n```\n\nThis allows a type to express that it implements an interface for a list of\ntypes, possibly with different implementations. However, in general, `X(T).F`\ncan only mean one thing, regardless of `T`.\n\n**Comparison with other languages:**\n[Swift supports conditional conformance](https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md),\nbut bans cases where there could be ambiguity from overlap.\n[Rust also supports conditional conformance](https://doc.rust-lang.org/rust-by-example/generics/where.html).\n\n### Blanket impl declarations\n\nA _blanket impl declaration_ is an `impl` declaration that could apply to more\nthan one root type, so the `impl` declaration will use a type variable for the\n`Self` type. Here are some examples where blanket impl declarations arise:\n\n-   Any type implementing `Ordered` should get an implementation of\n    `PartiallyOrdered`.\n\n    ```carbon\n    impl forall [T:! Ordered] T as PartiallyOrdered { ... }\n    ```\n\n-   `T` implements `CommonType(T)` for all `T`\n\n    ```carbon\n    impl forall [T:! type] T as CommonType(T)\n        where .Result = T { }\n    ```\n\n    This means that every type is the common type with itself.\n\nBlanket impl declarations may never be declared using [`extend`](#extend-impl)\nand must always be defined lexically [out-of-line](#out-of-line-impl).\n\n#### Difference between a blanket impl and a named constraint\n\nA blanket impl declaration can be used to say \"any type implementing\n`interface I` also implements `interface B`.\" Compare this with defining a\n`constraint C` that requires `I`. In that case, `C` will also be implemented any\ntime `I` is. There are differences though:\n\n-   There can be other implementations of `interface B` without a corresponding\n    implementation of `I`, unless `B` has a requirement on `I`. However, the\n    types implementing `C` will be the same as the types implementing `I`.\n-   More specialized implementations of `B` can override the blanket\n    implementation.\n\n### Wildcard impl declarations\n\nA _wildcard impl declaration_ is an `impl` declaration that defines how a family\nof interfaces are implemented for a single `Self` type. For example, the\n`BigInt` type might implement `AddTo(T)` for all `T` that implement\n`ImplicitAs(i32)`. The implementation would first convert `T` to `i32` and then\nadd the `i32` to the `BigInt` value.\n\n```carbon\nclass BigInt {\n  impl forall [T:! ImplicitAs(i32)] as AddTo(T) { ... }\n}\n// Or out-of-line:\nimpl forall [T:! ImplicitAs(i32)] BigInt as AddTo(T) { ... }\n```\n\nWildcard impl declarations may never be declared using [`extend`](#extend-impl),\nto avoid having the names in the interface defined for the type multiple times.\n\n### Combinations\n\nThe different kinds of parameters to an `impl` declarations may be combined. For\nexample, if `T` implements `As(U)`, then this implements `As(Optional(U))` for\n`Optional(T)`:\n\n```carbon\nimpl forall [U:! type, T:! As(U)]\n  Optional(T) as As(Optional(U)) { ... }\n```\n\nThis has a wildcard parameter `U`, and a condition on parameter `T`.\n\n### Lookup resolution and specialization\n\nAs much as possible, we want rules for where an `impl` is allowed to be defined\nand for selecting which `impl` definition to use that achieve these three goals:\n\n-   Implementations have coherence, as\n    [defined in terminology](terminology.md#coherence). This is\n    [a goal for Carbon](goals.md#coherence). More detail can be found in\n    [this appendix with the rationale and alternatives considered](appendix-coherence.md).\n-   Libraries will work together as long as they pass their separate checks.\n-   A checked-generic function can assume that some `impl` definition will be\n    successfully selected if it can see an `impl` declaration that applies, even\n    though another more specific `impl` definition may be selected.\n\nFor this to work, we need a rule that picks a single `impl` definition in the\ncase where there are multiple `impl` definitions that match a particular type\nand interface combination. This is called _specialization_ when the rule is that\nmost specific implementation is chosen, for some definition of \"specific.\"\n\n#### Type structure of an impl declaration\n\nGiven an impl declaration, find the type structure by deleting deduced\nparameters and replacing type parameters by a `?`. The type structure of this\ndeclaration:\n\n```carbon\nimpl forall [T:! ..., U:! ...] Foo(T, i32) as Bar(String, U) { ... }\n```\n\nis:\n\n```carbon\nimpl Foo(?, i32) as Bar(String, ?)\n```\n\nTo get a uniform representation across different `impl` definitions, before type\nparameters are replaced the declarations are normalized as follows:\n\n-   For `impl` declarations that are lexically inline in a class definition, the\n    type is added between the `impl` and `as` keywords if the type is left out.\n-   Pointer types `T*` are replaced with `Ptr(T)`.\n-   The `extend` keyword is removed, if present.\n-   The `forall` clause introducing type parameters is removed, if present.\n-   Any `where` clauses that are setting associated constants or types are\n    removed.\n\nThe type structure will always contain a single interface name, which is the\nname of the interface being implemented, and some number of type names. Type\nnames can be in the `Self` type to the left of the `as` keyword, or as\nparameters to other types or the interface. These names must always be defined\neither in the current library or be publicly defined in some library this\nlibrary depends on.\n\n#### Orphan rule\n\nTo achieve [coherence](terminology.md#coherence), we need to ensure that any\ngiven impl can only be defined in a library that must be imported for it to\napply. Specifically, given a specific type and specific interface, `impl`\ndeclarations that can match can only be in libraries that must have been\nimported to name that type or interface. This is achieved with the _orphan\nrule_.\n\n**Orphan rule:** Some name from the type structure of an `impl` declaration must\nbe defined in the same library as the `impl`, that is some name must be _local_.\n\nLet's say you have some interface `I(T, U(V))` being implemented for some type\n`A(B(C(D), E))`. To satisfy the orphan rule for coherence, that `impl` must be\ndefined in some library that must be imported in any code that looks up whether\nthat interface is implemented for that type. This requires that `impl` is\ndefined in the same library that defines the interface or one of the names\nneeded by the type. That is, the `impl` must be defined with one of `I`, `T`,\n`U`, `V`, `A`, `B`, `C`, `D`, or `E`. We further require anything looking up\nthis `impl` to import the _definitions_ of all of those names. Seeing a forward\ndeclaration of these names is insufficient, since you can presumably see forward\ndeclarations without seeing an `impl` with the definition. This accomplishes a\nfew goals:\n\n-   The compiler can check that there is only one definition of any `impl` that\n    is actually used, avoiding\n    [One Definition Rule (ODR)](https://en.wikipedia.org/wiki/One_Definition_Rule)\n    problems.\n-   Every attempt to use an `impl` will see the exact same `impl` definition,\n    making the interpretation and semantics of code consistent no matter its\n    context, in accordance with the\n    [low context-sensitivity principle](/docs/project/principles/low_context_sensitivity.md).\n-   Allowing the `impl` to be defined with either the interface or the type\n    partially addresses the\n    [expression problem](https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions).\n\nNote that [the rules for specialization](#lookup-resolution-and-specialization)\ndo allow there to be more than one `impl` to be defined for a type, by\nunambiguously picking one as most specific.\n\n> **References:** Implementation coherence is\n> [defined in terminology](terminology.md#coherence), and is\n> [a goal for Carbon generics](goals.md#coherence). More detail can be found in\n> [this appendix with the rationale and alternatives considered](appendix-coherence.md).\n\nOnly the implementing interface and types (self type and type parameters) in the\ntype structure are relevant here; an interface mentioned in a constraint is not\nsufficient since it\n[need not be imported](/proposals/p0920.md#orphan-rule-could-consider-interface-requirements-in-blanket-impls).\n\nSince Carbon in addition requires there be no cyclic library dependencies, we\nconclude that there is at most one library that can contain `impl` definitions\nwith a particular type structure.\n\n#### Overlap rule\n\nGiven a specific concrete type, say `Foo(bool, i32)`, and an interface, say\n`Bar(String, f32)`, the overlap rule picks, among all the matching `impl`\ndeclarations, which type structure is considered \"most specific\" to use as the\nimplementation of that type for that interface.\n\nGiven two different type structures of impl declarations matching a query, for\nexample:\n\n```carbon\nimpl Foo(?, i32) as Bar(String, ?)\nimpl Foo(?, ?) as Bar(String, f32)\n```\n\nWe pick the type structure with a non-`?` at the first difference as most\nspecific. Here we see a difference between `Foo(?, i32)` and `Foo(?, ?)`, so we\nselect the one with `Foo(?, i32)`, ignoring the fact that it has another `?`\nlater in its type structure\n\nThis rule corresponds to a depth-first traversal of the type tree to identify\nthe first difference, and then picking the most specific choice at that\ndifference.\n\n#### Prioritization rule\n\n> **TODO:** Document the changes to prioritization adopted in\n> [p5337: Interface extension and `final impl` update](/proposals/p5337.md).\n\nSince at most one library can contain `impl` definitions with a given type\nstructure, all `impl` definitions with a given type structure must be in the\nsame library. Furthermore by the [`impl` declaration access rules](#access),\nthey will be defined in the API file for the library if they could match any\nquery from outside the library. If there is more than one `impl` with that type\nstructure, they must be [defined](#implementing-interfaces) or\n[declared](#declaring-implementations) together in a prioritization block. Once\na type structure is selected for a query, the first `impl` declaration in the\nprioritization block that matches is selected.\n\n> **Open question:** How are prioritization blocks written? A block starts with\n> a keyword like `match_first` or `impl_priority` and then a sequence of impl\n> declarations inside matching curly braces `{` ... `}`.\n>\n> ```carbon\n> match_first {\n>   // If T is Foo prioritized ahead of T is Bar\n>   impl forall [T:! Foo] T as Bar { ... }\n>   impl forall [T:! Baz] T as Bar { ... }\n> }\n> ```\n\nTo increase expressivity, Carbon allows prioritization blocks to contain a mix\nof type structures, which is resolved using this rule:\n\n> The compiler first picks the `impl` declaration with the type structure most\n> favored for the query, and then picks the highest priority (earliest) matching\n> `impl` declaration in the same prioritization block.\n\n> **Alternatives considered:** We considered two other options:\n>\n> -   \"Intersection rule:\" Prioritization blocks implicitly define all non-empty\n>     intersections of contained `impl` declarations, which are then selected by\n>     their type structure.\n> -   \"Same type structure rule:\" All the `impl` declarations in a\n>     prioritization block are required to have the same type structure, at a\n>     cost in expressivity. This option was not chosen since it wouldn't support\n>     the different type structures created by the\n>     [`like` operator](#like-operator-for-implicit-conversions).\n>\n> To see the difference from the first option, consider two libraries with type\n> structures as follows:\n>\n> -   Library B has `impl (A, ?, ?, D) as I` and `impl (?, B, ?, D) as I` in the\n>     same prioritization block.\n> -   Library C has `impl (A, ?, C, ?) as I`.\n>\n> For the query `(A, B, C, D) as I`, using the intersection rule, library B is\n> considered to have the intersection impl with type structure\n> `impl (A, B, ?, D) as I` which is the most specific. If we instead just\n> considered the rules mentioned explicitly, then `impl (A, ?, C, ?) as I` from\n> library C is the most specific. The advantage of the implicit intersection\n> rule is that if library B is changed to add an impl with type structure\n> `impl (A, B, ?, D) as I`, it won't shift which library is serving that query.\n> Ultimately we decided that it was too surprising to prioritize based on the\n> implicit intersection of `impl` declarations, rather than something explicitly\n> written in the code.\n>\n> We chose between these alternatives in\n> [the open discussion on 2023-07-18](https://docs.google.com/document/d/1gnJBTfY81fZYvI_QXjwKk1uQHYBNHGqRLI2BS_cYYNQ/edit?resourcekey=0-ql1Q1WvTcDvhycf8LbA9DQ#heading=h.7jxges9ojgy3).\n> **TODO:** This decision needs to be approved in a proposal.\n\n#### Acyclic rule\n\nA cycle is when a query, such as \"does type `T` implement interface `I`?\",\nconsiders an `impl` declaration that might match, and whether that `impl`\ndeclaration matches is ultimately dependent on whether that query is true. These\nare cycles in the graph of (type, interface) pairs where there is an edge from\npair A to pair B if whether type A implements interface A determines whether\ntype B implements interface B.\n\nThe test for whether something forms a cycle needs to be precise enough, and not\nerase too much information when considering this graph, that these `impl`\ndeclarations are not considered to form cycles with themselves:\n\n```carbon\nimpl forall [T:! Printable] Optional(T) as Printable;\nimpl forall [T:! type, U:! ComparableTo(T)] U as ComparableTo(Optional(T));\n```\n\n**Example:** If `T` implements `ComparableWith(U)`, then `U` should implement\n`ComparableWith(T)`.\n\n```carbon\nimpl forall [U:! type, T:! ComparableWith(U)]\n    U as ComparableWith(T);\n```\n\nThis is a cycle where which types implement `ComparableWith` determines which\ntypes implement the same interface.\n\n**Example:** Cycles can create situations where there are multiple ways of\nselecting `impl` declarations that are inconsistent with each other. Consider an\ninterface with two blanket `impl` declarations:\n\n```carbon\nclass Y {}\nclass N {}\ninterface True {}\nimpl Y as True {}\ninterface Z(T:! type) { let Cond:! type; }\nmatch_first {\n  impl forall [T:! type, U:! Z(T) where .Cond impls True] T as Z(U)\n      where .Cond = N { }\n  impl forall [T:! type, U:! type] T as Z(U)\n      where .Cond = Y { }\n}\n```\n\nWhat is `i8.(Z(i16).Cond)`? It depends on which of the two blanket impl\ndeclarations are selected.\n\n-   An implementation of `Z(i16)` for `i8` could come from the first blanket\n    impl with `T == i8` and `U == i16` if `i16 impls Z(i8)` and\n    `(i16 as Z(i8)).Cond == Y`. This condition is satisfied if `i16` implements\n    `Z(i8)` using the second blanket impl. In this case,\n    `(i8 as Z(i16)).Cond == N`.\n-   Equally well `Z(i8)` could be implemented for `i16` using the first blanket\n    impl and `Z(i16)` for `i8` using the second. In this case,\n    `(i8 as Z(i16)).Cond == Y`.\n\nThere is no reason to prefer one of these outcomes over the other.\n\n**Example:** Further, cycles can create contradictions in the type system:\n\n```carbon\nclass A {}\nclass B {}\nclass C {}\ninterface D(T:! type) { let Cond:! type; }\nmatch_first {\n  impl forall [T:! type, U:! D(T) where .Cond = B] T as D(U)\n      where .Cond = C { }\n  impl forall [T:! type, U:! D(T) where .Cond = A] T as D(U)\n      where .Cond = B { }\n  impl forall [T:! type, U:! type] T as D(U)\n      where .Cond = A { }\n}\n```\n\nWhat is `(i8 as D(i16)).Cond`? The answer is determined by which blanket impl is\nselected to implement `D(i16)` for `i8`:\n\n-   If the third blanket impl is selected, then `(i8 as D(i16)).Cond == A`. This\n    implies that `(i16 as D(i8)).Cond == B` using the second blanket impl. If\n    that is true, though, then our first impl choice was incorrect, since the\n    first blanket impl applies and is higher priority. So\n    `(i8 as D(i16)).Cond == C`. But that means that `i16 as D(i8)` can't use the\n    second blanket impl.\n-   For the second blanket impl to be selected, so `(i8 as D(i16)).Cond == B`,\n    `(i16 as D(i8)).Cond` would have to be `A`. This happens when `i16`\n    implements `D(i8)` using the third blanket impl. However,\n    `(i8 as D(i16)).Cond == B` means that there is a higher priority\n    implementation of `D(i8).Cond` for `i16`.\n\nIn either case, we arrive at a contradiction.\n\nThe workaround for this problem is to either split an interface in the cycle in\ntwo, with a blanket implementation of one from the other, or move some of the\ncriteria into a [named constraint](#named-constraints).\n\n**Concern:** Cycles could be spread out across libraries with no dependencies\nbetween them. This means there can be problems created by a library that are\nonly detected by its users.\n\n**Open question:** Should Carbon reject cycles in the absence of a query? The\ntwo options here are:\n\n-   Combining `impl` declarations gives you an immediate error if there exists\n    queries using them that have cycles.\n-   Only when a query reveals a cyclic dependency is an error reported.\n\n**Open question:** In the second case, should we ignore cycles if they don't\naffect the result of the query? For example, the cycle might be among\nimplementations that are lower priority.\n\n#### Termination rule\n\nIt is possible to have a set of `impl` declarations where there isn't a cycle,\nbut the graph is infinite. Without some rule to prevent exhaustive exploration\nof the graph, determining whether a type implements an interface could run\nforever.\n\n**Example:** It could be that `A` implements `B`, so `A impls B` if\n`Optional(A) impls B`, if `Optional(Optional(A)) impls B`, and so on. This could\nbe the result of a single impl:\n\n```carbon\nimpl forall [A:! type where Optional(.Self) impls B] A as B { ... }\n```\n\nThis problem can also result from a chain of `impl` declarations, as in\n`A impls B` if `A* impls C`, if `Optional(A) impls B`, and so on.\n\nDetermining whether a particular set of `impl` declarations terminates is\nequivalent to the halting problem (content warning: contains many instances of\nan obscene word as part of a programming language name\n[1](https://sdleffler.github.io/RustTypeSystemTuringComplete/),\n[2](https://forums.swift.org/t/two-more-undecidable-problems-in-the-swift-type-system/64814)),\nand so is undecidable in general. Carbon adopts an approximation that guarantees\ntermination, but may mistakenly report an error when the query would terminate\nif left to run long enough. The hope is that this criteria is accurate on code\nthat occurs in practice.\n\nRule: the types in the `impl` query must never get strictly more complicated\nwhen considering the same `impl` declaration again. The way we measure the\ncomplexity of a set of types is by counting how many of each base type appears.\nA base type is the name of a type without its parameters. For example, the base\ntypes in this query `Pair(Optional(i32), bool) impls AddWith(Optional(i32))`\nare:\n\n-   `Pair`\n-   `Optional` twice\n-   `i32` twice\n-   `bool`\n-   `AddWith`\n\nA query is strictly more complicated if at least one count increases, and no\ncount decreases. So `Optional(Optional(i32))` is strictly more complicated than\n`Optional(i32)` but not strictly more complicated than `Optional(bool)`.\n\nThis rule, when combined with [the acyclic rule](#acyclic-rule) that a query\ncan't repeat exactly,\n[guarantees termination](/proposals/p2687.md#proof-of-termination).\n\nConsider the example from before,\n\n```carbon\nimpl forall [A:! type where Optional(.Self) impls B] A as B;\n```\n\nThis `impl` declaration matches the query `i32 impls B` as long as\n`Optional(i32) impls B`. That is a strictly more complicated query, though,\nsince it contains all the base types of the starting query (`i32` and `B`), plus\none more (`Optional`). As a result, an error can be given after one step, rather\nthan after hitting a large recursion limit. And that error can state explicitly\nwhat went wrong: we went from a query with no `Optional` to one with one,\nwithout anything else decreasing.\n\nNote this only triggers a failure when the same `impl` declaration is considered\nwith the strictly more complicated query. For example, if the declaration is not\nconsidered since there is a more specialized `impl` declaration that is\npreferred by the [type-structure overlap rule](#overlap-rule), as in:\n\n```\nimpl forall [A:! type where Optional(.Self) impls B] A as B;\nimpl Optional(bool) as B;\n// OK, because we never consider the first `impl`\n// declaration when looking for `Optional(bool) impls I`.\nlet U:! B = bool;\n// Error: cycle with `i32 impls B` depending on\n// `Optional(i32) impls B`, using the same `impl`\n// declaration, as before.\nlet V:! B = i32;\n```\n\n<!-- prettier-ignore-start -->\n\n<!-- The following triggers a bug in prettier where it adds an `>` -->\n\n> **Note:**\n> [Issue #2880](https://github.com/carbon-language/carbon-lang/issues/2880) is a\n> tracking bug for known issues with this \"strictly more complex\" rule for\n> `impl` termination. We are using that issue to track any code that arises in\n> practice that would terminate but is rejected by this rule.\n\n<!-- prettier-ignore-end -->\n\n> **Comparison with other languages:** Rust solves this problem by imposing a\n> recursion limit, much like C++ compilers use to terminate template recursion.\n> This goes against\n> [Carbon's goal of predictability in generics](goals.md#predictability),\n> because of the concern that increasing the number of steps needed to resolve\n> an `impl` query could cause far away code to hit the recursion limit.\n>\n> Carbon's approach is robust in the face of refactoring:\n>\n> -   It does not depend on the specifics of how an `impl` declaration is\n>     parameterized, only on the query.\n> -   It does not depend on the length of the chain of queries.\n> -   It does not depend on a measure of type-expression complexity, like depth.\n>\n> Carbon's approach also results in identifying the minimal steps in the loop,\n> which makes error messages as short and understandable as possible.\n\n> **Alternatives considered:**\n>\n>     -   [Recursion limit](/proposals/p2687.md#problem)\n>     -   [Measure complexity using type tree depth](/proposals/p2687.md#measure-complexity-using-type-tree-depth)\n>     -   [Consider each type parameter in an `impl` declaration separately](/proposals/p2687.md#consider-each-type-parameter-in-an-impl-declaration-separately)\n>     -   [Consider types in the interface being implemented as distinct](/proposals/p2687.md#consider-types-in-the-interface-being-implemented-as-distinct)\n>     -   [Require some count to decrease](/proposals/p2687.md#require-some-count-to-decrease)\n>     -   [Require non-type values to stay the same](/proposals/p2687.md#require-non-type-values-to-stay-the-same)\n\n> **References:** This algorithm is from proposal\n> [#2687: Termination algorithm for impl selection](https://github.com/carbon-language/carbon-lang/pull/2687),\n> replacing the recursion limit originally proposed in\n> [#920: Generic parameterized impls (details 5)](https://github.com/carbon-language/carbon-lang/pull/920)\n> before we came up with this algorithm.\n\n##### Non-facet arguments\n\nFor non-facet arguments we have to expand beyond base types to consider other\nkinds of keys. These other keys are in a separate namespace from base types.\n\n-   Values with an integral type use the name of the type as the key and the\n    absolute value as a count. This means integer arguments are considered more\n    complicated if they increase in absolute value. For example, if the values\n    `2` and `-3` are used as arguments to parameters with type `i32`, then the\n    `i32` key will have count `5`.\n-   Every option of a choice type is its own key, counting how many times a\n    value using that option occurs. Any parameters to the option are recorded as\n    separate keys. For example, the `Optional(i32)` value of `.Some(7)` is\n    recorded as keys `.Some` (with a count of `1`) and `i32` (with a count of\n    `7`).\n-   Yet another namespace of keys is used to track counts of variadic arguments,\n    under the base type. This is to defend against having a variadic type `V`\n    that takes any number of `i32` arguments, with an infinite set of distinct\n    instantiations: `V(0)`, `V(0, 0)`, `V(0, 0, 0)`, ...\n    -   A `tuple` key in this namespace is used to track the total number of\n        components of tuple values. The values of those elements will be tracked\n        using their own keys.\n\nNon-facet argument values not covered by these cases are deleted from the query\nentirely for purposes of the termination algorithm. This requires that two\nqueries that only differ by non-facet arguments are considered identical and\ntherefore are rejected by the acyclic rule. Otherwise, we could construct an\ninfinite family of non-facet argument values that could be used to avoid\ntermination.\n\n### `final` impl declarations\n\nThere are cases where knowing that a parameterized impl won't be specialized is\nparticularly valuable. This could let the compiler know the return type of a\ncall to a generic function, such as using an operator:\n\n```carbon\n// Interface defining the behavior of the prefix-* operator\ninterface Deref {\n  let Result:! type;\n  fn Op[self: Self]() -> Result;\n}\n\n// Types implementing `Deref`\nclass Ptr(T:! type) {\n  ...\n  impl as Deref where .Result = T {\n    fn Op[self: Self]() -> Result { ... }\n  }\n}\nclass Optional(T:! type) {\n  ...\n  impl as Deref where .Result = T {\n    fn Op[self: Self]() -> Result { ... }\n  }\n}\n\nfn F[T:! type](x: T) {\n  // uses Ptr(T) and Optional(T) in implementation\n}\n```\n\nThe concern is the possibility of specializing `Optional(T) as Deref` or\n`Ptr(T) as Deref` for a more specific `T` means that the compiler can't assume\nanything about the return type of `Deref.Op` calls. This means `F` would in\npractice have to add a constraint, which is both verbose and exposes what should\nbe implementation details:\n\n```carbon\nfn F[T:! type where Optional(T).(Deref.Result) == .Self\n                and Ptr(T).(Deref.Result) == .Self](x: T) {\n  // uses Ptr(T) and Optional(T) in implementation\n}\n```\n\nTo mark an impl as not able to be specialized, prefix it with the keyword\n`final`:\n\n```carbon\nclass Ptr(T:! type) {\n  ...\n  // Note: added `final`\n  final impl as Deref where .Result = T {\n    fn Op[self: Self]() -> Result { ... }\n  }\n}\nclass Optional(T:! type) {\n  ...\n  // Note: added `final`\n  final impl as Deref where .Result = T {\n    fn Op[self: Self]() -> Result { ... }\n  }\n}\n\n// ❌ Illegal: impl Ptr(i32) as Deref { ... }\n// ❌ Illegal: impl Optional(i32) as Deref { ... }\n```\n\n> **TODO:** Update the following passage to reflect the relaxed overlap rule\n> adopted in\n> [p5337: Interface extension and `final impl` update](/proposals/p5337.md).\n\nThis prevents any higher-priority impl that overlaps a final impl from being\ndefined unless it agrees with the `final` impl on the overlap. Overlap is\ncomputed between two non-`template` `impl` declaration by\n[unifying](<https://en.wikipedia.org/wiki/Unification_(computer_science)>) the\ncorresponding parts. For example, the intersection of these two declarations\n\n```carbon\nfinal impl forall [T:! type]\n    T as CommonTypeWith(T)\n    where .Result = T {}\n\nimpl forall [V:! type, U:! CommonTypeWith(V)]\n    Vec(U) as CommonTypeWith(Vec(V))\n    where .Result = Vec(U.Result) {}\n```\n\nis found by unifying `T` with `Vec(U)` and `CommonTypeWith(T)` with\n`CommonTypeWith(Vec(V))`. In this case, the intersection is when `T == Vec(U)`\nand `U == V`. For templated `impl` declarations, overlap and agreement is\ndelayed until the template is instantiated with concrete types.\n\nSince we do not require the compiler to compare the definitions of functions,\nagreement is only possible for interfaces without any function members.\n\nIf the Carbon compiler sees a matching `final` impl, it can assume it won't be\nspecialized so it can use the assignments of the associated constants in that\nimpl definition.\n\n```carbon\nfn F[T:! type](x: T) {\n  var p: Ptr(T) = ...;\n  // *p has type `T`\n  var o: Optional(T) = ...;\n  // *o has type `T`\n}\n```\n\n> **Alternatives considered:**\n>\n> -   [Allow interfaces with member functions to compare equal](/proposals/p2868.md#allow-interfaces-with-member-functions-to-compare-equal)\n> -   Mark associated constants as `final` instead of an `impl` declaration, in\n>     proposals\n>     [#983](/proposals/p0983.md#final-associated-constants-instead-of-final-impls)\n>     and\n>     [#2868](/proposals/p2868.md#mark-associated-constants-as-final-instead-of-an-impl-declaration)\n> -   [Prioritize a `final impl` over a more specific `impl` on the overlap](/proposals/p2868.md#prioritize-a-final-impl-over-a-more-specific-impl-on-the-overlap)\n\n#### Libraries that can contain a `final` impl\n\nTo prevent the possibility of two unrelated libraries defining conflicting\n`impl` declarations, Carbon restricts which libraries may declare an impl as\n`final` to only:\n\n-   the library declaring the impl's interface and\n-   the library declaring the root of the `Self` type.\n\nThis means:\n\n-   A blanket impl with type structure `impl ? as MyInterface(...)` may only be\n    defined in the same library as `MyInterface`.\n-   An impl with type structure `impl MyType(...) as MyInterface(...)` may be\n    defined in the library with `MyType` or `MyInterface`.\n\nThese restrictions ensure that the Carbon compiler can locally check that no\nhigher-priority impl is defined superseding a `final` impl.\n\n-   An impl with type structure `impl MyType(...) as MyInterface(...)` defined\n    in the library with `MyType` must import the library defining `MyInterface`,\n    and so will be able to see any final blanket impl declarations.\n-   A blanket impl with type structure\n    `impl ? as MyInterface(...ParameterType(...)...)` may be defined in the\n    library with `ParameterType`, but that library must import the library\n    defining `MyInterface`, and so will be able to see any `final` blanket impl\n    declarations that might overlap. A final impl with type structure\n    `impl MyType(...) as MyInterface(...)` would be given priority over any\n    overlapping blanket impl defined in the `ParameterType` library.\n-   An impl with type structure\n    `impl MyType(...ParameterType(...)...) as MyInterface(...)` may be defined\n    in the library with `ParameterType`, but that library must import the\n    libraries defining `MyType` and `MyInterface`, and so will be able to see\n    any `final` `impl` declarations that might overlap.\n\n### Comparison to Rust\n\nRust has been designing a specialization feature, but it has not been completed.\nLuckily, Rust team members have done a lot of blogging during their design\nprocess, so Carbon can benefit from the work they have done. However, getting\nspecialization to work for Rust is complicated by the need to maintain\ncompatibility with existing Rust code. This motivates a number of Rust rules\nwhere Carbon can be simpler. As a result there are both similarities and\ndifferences between the Carbon design and Rust plans:\n\n-   A Rust `impl` defaults to not being able to be specialized, with a `default`\n    keyword used to opt-in to allowing specialization, reflecting the existing\n    code base developed without specialization. Carbon `impl` declarations\n    default to allowing specialization, with restrictions on which may be\n    declared `final`.\n-   Since a Rust impl is not specializable by default, generic functions can\n    assume that if a matching blanket impl declaration is found, the associated\n    constants from that impl will be used. In Carbon, if a checked-generic\n    function requires an associated constant to have a particular value, the\n    function commonly will need to state that using an explicit constraint.\n-   Carbon will not have the \"fundamental\" attribute used by Rust on types or\n    traits, as described in\n    [Rust RFC 1023: \"Rebalancing Coherence\"](https://rust-lang.github.io/rfcs/1023-rebalancing-coherence.html).\n-   Carbon will not use \"covering\" rules, as described in\n    [Rust RFC 2451: \"Re-Rebalancing Coherence\"](https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html)\n    and\n    [Little Orphan Impls: The covered rule](http://smallcultfollowing.com/babysteps/blog/2015/01/14/little-orphan-impls/#the-covered-rule).\n-   Like Rust, Carbon does use ordering, favoring the `Self` type and then the\n    parameters to the interface in left-to-right order, see\n    [Rust RFC 1023: \"Rebalancing Coherence\"](https://rust-lang.github.io/rfcs/1023-rebalancing-coherence.html)\n    and\n    [Little Orphan Impls: The ordered rule](http://smallcultfollowing.com/babysteps/blog/2015/01/14/little-orphan-impls/#the-ordered-rule),\n    but the specifics are different.\n-   Carbon is not planning to support any inheritance of implementation between\n    `impl` definitions. This is more important to Rust since Rust does not\n    support class inheritance for implementation reuse. Rust has considered\n    multiple approaches here, see\n    [Aaron Turon: \"Specialize to Reuse\"](http://aturon.github.io/tech/2015/09/18/reuse/)\n    and\n    [Supporting blanket impls in specialization](http://smallcultfollowing.com/babysteps/blog/2016/10/24/supporting-blanket-impls-in-specialization/).\n-   [Supporting blanket impls in specialization](http://smallcultfollowing.com/babysteps/blog/2016/10/24/supporting-blanket-impls-in-specialization/)\n    proposes a specialization rule for Rust that considers type structure before\n    other constraints, as in Carbon, though the details differ.\n-   Rust has more orphan restrictions to avoid there being cases where it is\n    ambiguous which impl should be selected. Carbon instead has picked a total\n    ordering on type structures, picking one as higher priority even without one\n    being more specific in the sense of only applying to a subset of types.\n\n## Forward declarations and cyclic references\n\n> **TODO:** Update this section to distinguish between _defined_ and _complete_,\n> as adopted in\n> [p5087: Qualified lookup into types being defined](/proposals/p5087.md).\n\nInterfaces, named constraints, and their implementations may be forward declared\nand then later defined. This is needed to allow cyclic references, for example\nwhen declaring the edges and nodes of a graph. It is also a tool that may be\nused to make code more readable.\n\nThe [interface](#interfaces), [named constraint](#named-constraints), and\n[implementation](#implementing-interfaces) sections describe the syntax for\ntheir _definition_, which consists of a declaration followed by a body contained\nin curly braces `{` ... `}`. A _forward declaration_ is a declaration followed\nby a semicolon `;`. A forward declaration is a promise that the entity being\ndeclared will be defined later. Between the first declaration of an entity,\nwhich may be in a forward declaration or the first part of a definition, and the\nend of the definition the interface or implementation is called _incomplete_.\nThere are additional restrictions on how the name of an incomplete entity may be\nused.\n\n### Declaring interfaces and named constraints\n\n> **TODO:** Update this section to reflect the additional things you can do with\n> a defined but incomplete type, as adoped in\n> [p5087: Qualified lookup into types being defined](/proposals/p5087.md).\n\nThe declaration for an interface or named constraint consists of:\n\n-   an optional access-control keyword like `private`,\n-   the keyword introducer `interface`, `constraint`, or `template constraint`,\n-   the name of the interface or constraint, and\n-   the parameter list, if any.\n\nThe name of an interface or constraint can not be used until its first\ndeclaration is complete. In particular, it is illegal to use the name of the\ninterface in its parameter list. There is a\n[workaround](#interfaces-with-parameters-constrained-by-the-same-interface) for\nthe use cases when this would come up.\n\nAn expression forming a constraint, such as `C & D`, is incomplete if any of the\ninterfaces or constraints used in the expression are incomplete.\n\nAn interface or named constraint may be forward declared subject to these rules:\n\n-   The definition must be in the same file as the declaration.\n-   Only the first declaration may have an access-control keyword.\n-   An incomplete interface or named constraint may be used as constraints in\n    declarations of types, functions, interfaces, or named constraints. This\n    includes a `require` declaration inside an interface or named constraint,\n    but excludes specifying the values for associated constants because that\n    would involve name lookup into the incomplete constraint.\n-   An attempt to define the body of a generic function using an incomplete\n    interface or named constraint in its signature is illegal.\n-   An attempt to call a generic function using an incomplete interface or named\n    constraint in its signature is illegal.\n-   Any name lookup into an incomplete interface or named constraint is an\n    error. For example, it is illegal to attempt to access a member of an\n    interface using `MyInterface.MemberName` or constrain a member using a\n    [`where` clause](#where-constraints).\n\nIf `C` is the name of an incomplete interface or named constraint, then it can\nbe used in the following contexts:\n\n-   ✅ `T:! C`\n-   ✅ `C & D`\n    -   There may be conflicts between `C` and `D` making this invalid that will\n        only be discovered once they are both complete.\n-   ✅ `interface `...` { require` ... `impls C; }` or\n    `constraint `...` { require` ... `impls C; }`\n    -   Nothing implied by implementing `C` will be visible until `C` is\n        complete.\n-   ✅ `T:! C` ... `T impls C`\n-   ✅ `T:! A & C` ... `T impls C`\n    -   This includes constructs requiring `T impls C` such as `T as C` or\n        `U:! C = T`.\n-   ✅ `impl `...` as C;`\n    -   Checking that all associated constants of `C` are correctly assigned\n        values will be delayed until `C` is complete.\n\nAn incomplete `C` cannot be used in the following contexts:\n\n-   ❌ `T:! C` ... `T.X`\n-   ❌ `T:! C where `...\n-   ❌ `class `...` { extend impl as C; }`\n    -   The names of `C` are added to the class, and so those names need to be\n        known.\n-   ❌ `T:! C` ... `T impls A` where `A` is an interface or named constraint\n    different from `C`\n    -   Need to see the definition of `C` to see if it implies `A`.\n-   ❌ `impl` ... `as C {` ... `}`\n\n> **Future work:** It is currently undecided whether an interface needs to be\n> complete to be extended, as in:\n>\n> ```carbon\n> interface I { extend C; }\n> ```\n>\n> There are three different approaches being considered:\n>\n> -   If we detect name collisions between the members of the interface `I` and\n>     `C` when the interface `I` is defined, then we need `C` to be complete.\n> -   If we instead only generate errors on ambiguous use of members with the\n>     same name, as we do with `A & B`, then we don't need to require `C` to be\n>     complete.\n> -   Another option, being discussed in\n>     [#2745](https://github.com/carbon-language/carbon-lang/issues/2745), is\n>     that names in interface `I` shadow the names in any interface being\n>     extended, then `C` would not be required to be complete.\n\n### Declaring implementations\n\n> **TODO:** Update this section to reflect the new rules adopted in\n> [p5168: Forward `impl` declaration of an incomplete interface](/proposals/p5168.md).\n\nThe declaration of an interface implementation consists of:\n\n-   optional modifier keyword `final`,\n-   the keyword introducer `impl`,\n-   an optional `forall` followed by a deduced parameter list in square brackets\n    `[`...`]`,\n-   an optional type, including an optional\n    [argument list](#parameterized-types),\n-   the keyword `as`, and\n-   a [facet type](#facet-types), including an optional\n    [argument list](#parameterized-interfaces) and\n    [`where` clause](#where-constraints) assigning\n    [associated constants](#associated-constants) including\n    [associated facets](#associated-facets).\n\n> **TODO:** Document the redeclaration syntax `impl C.(as I)` adopted in\n> [p5366: The name of an `impl` in `class` scope](/proposals/p5366.md).\n\n**Note:** The type before the `as` is required except in class scope, where it\ndefaults to `Self` as described in the\n[matching and agreeing section](#matching-and-agreeing).\n\n**Note:** The `extend` keyword, when present, is not part of the `impl`\ndeclaration. It precedes the `impl` declaration in class scope. When the\n`extend` keyword is present, the `forall` and type clauses before the `as`\nkeyword must be omitted.\n\nAn implementation of an interface for a type may be forward declared, subject to\nthese rules:\n\n-   The definition must be in the same library as the declaration. They must\n    either be in the same file, or the declaration can be in the API file and\n    the definition in an impl file. **Future work:** Carbon may require\n    [parameterized `impl` definitions](#parameterized-impl-declarations) to be\n    in the API file, to support separate compilation.\n-   If there is both a forward declaration and a definition, only the first\n    declaration must specify the assignment of associated constants with a\n    `where` clause. Later declarations may omit the `where` clause by writing\n    `where _` instead.\n-   You can't forward declare an implementation of an incomplete interface. This\n    allows the assignment of associated constants in the `impl` declaration to\n    be verified with the declaration. An `impl` forward declaration may be for\n    any declared type, whether it is incomplete or defined.\n-   Every [extending implementation](#extend-impl) must be declared (or defined)\n    inside the scope of the class definition. It may also be declared before the\n    class definition or defined afterwards. Note that the class itself is\n    incomplete in the scope of the class definition, but member function bodies\n    defined inline are processed\n    [as if they appeared immediately after the end of the outermost enclosing class](/docs/project/principles/information_accumulation.md#exceptions).\n-   For [coherence](terminology.md#coherence), we require that any `impl`\n    declaration that matches an impl lookup query in the same file, must be\n    declared before the query. This can be done with a definition or a forward\n    declaration. This matches the\n    [information accumulation principle](/docs/project/principles/information_accumulation.md).\n\n### Matching and agreeing\n\n> **TODO:** Update this section to reflect the new terminology and rules adopted\n> in [p3763: Matching redeclarations](/proposals/p3763.md), and the new rules\n> adopted in\n> [p5168: Forward `impl` declaration of an incomplete interface](/proposals/p5168.md).\n\nCarbon needs to determine if two declarations match in order to say which\ndefinition a forward declaration corresponds to and to verify that nothing is\ndefined twice. Declarations that match must also agree, meaning they are\nconsistent with each other.\n\nInterface and named constraint declarations match if their names are the same\nafter name and alias resolution. To agree:\n\n-   The introducer keyword or keywords much be the same.\n-   The types and order of parameters in the parameter list, if any, must match.\n    The parameter names may be omitted, but if they are included in both\n    declarations, they must match.\n-   Types agree if they correspond to the same expression tree, after name and\n    alias resolution and canonicalization of parentheses. Note that no other\n    evaluation of expressions is performed.\n\nInterface implementation declarations match if the type and interface\nexpressions match along with\n[the `forall` clause](#parameterized-impl-declarations), if any:\n\n-   If the type part is omitted, it is rewritten to `Self` in the context of the\n    declaration.\n-   `Self` is rewritten to its meaning in the scope it is used. In a class\n    scope, this should match the type name and\n    [optional parameter expression](#parameterized-types) after `class`. So in\n    `class MyClass { ... }`, `Self` is rewritten to `MyClass`. In\n    `class Vector(T:! Movable) { ... }`, `Self` is rewritten to\n    `forall [T:! Movable] Vector(T)`.\n-   Types match if they have the same name after name and alias resolution and\n    the same parameters, or are the same type parameter.\n-   Interfaces match if they have the same name after name and alias resolution\n    and the same parameters. Note that a named constraint that is equivalent to\n    an interface, as in `constraint Equivalent { extend MyInterface; }`, is not\n    considered to match.\n\n> **TODO:** Document the matching rules for the redeclaration syntax\n> `impl C.(as I)` adopted in\n> [p5366: The name of an `impl` in `class` scope](/proposals/p5366.md).\n\nFor implementations to agree:\n\n-   The presence of the modifier keyword `final` before `impl` must match\n    between a forward declaration and definition.\n-   If either declaration includes a `where` clause, they must both include one.\n    If neither uses `where _`, they must match in that they produce the\n    associated constants with the same values considered separately.\n\n### Declaration examples\n\n```carbon\n// Forward declaration of interfaces\ninterface Interface1;\ninterface Interface2;\ninterface Interface3;\ninterface Interface4;\ninterface Interface5;\ninterface Interface6;\n\n// Forward declaration of class type\nclass MyClass;\n\n// ❌ Illegal: Can't declare implementation of incomplete\n//             interface.\n// impl MyClass as Interface1;\n\n// Definition of interfaces that were previously declared\ninterface Interface1 {\n  let T1:! type;\n}\ninterface Interface2 {\n  let T2:! type;\n}\ninterface Interface3 {\n  let T3:! type;\n}\ninterface Interface4 {\n  let T4:! type;\n}\n\n// Out-of-line forward declarations\nimpl MyClass as Interface1 where .T1 = i32;\nimpl MyClass as Interface2 where .T2 = bool;\nimpl MyClass as Interface3 where .T3 = f32;\nimpl MyClass as Interface4 where .T4 = String;\n\ninterface Interface5 {\n  let T5:! type;\n}\ninterface Interface6 {\n  let T6:! type;\n}\n\n// Definition of the previously declared class type\nclass MyClass {\n  // Inline definition of previously declared impl.\n  // Note: no need to repeat assignments to associated\n  // constants.\n  impl as Interface1 where _ { }\n\n  // Inline extending definition of previously declared\n  // impl.\n  // Note: `extend` only appears on the declaration in\n  // class scope\n  // Note: allowed even though `MyClass` is incomplete.\n  // Note: allowed but not required to repeat `where`\n  // clause.\n  extend impl as Interface3 where .T3 = f32 { }\n\n  // Extending redeclaration of previously declared\n  // impl. Every extending implementation must be\n  // declared in the class definition.\n  extend impl as Interface4 where _;\n\n  // Inline forward declaration of implementation.\n  impl MyClass as Interface5 where .T5 = u64;\n  // or: impl as Interface5 where .T5 = u64;\n\n  // Forward declaration of extending implementation.\n  extend impl as Interface6 where .T6 = u8;\n  // *Not*:\n  //   extend impl MyClass as Interface6 where .T6 = u8;\n  // No optional type after `extend impl`, it must be\n  // followed immediately by `as`\n}\n\n// It would be legal to move the following definitions\n// from the API file to the implementation file for\n// this library.\n\n// Definitions of previously declared implementations.\nimpl MyClass as Interface2 where _ { }\nimpl MyClass as Interface5 where _ { }\n\n// Definition of previously declared extending\n// implementations.\nimpl MyClass as Interface4 where _ { }\nimpl MyClass as Interface6 where _ { }\n```\n\n### Example of declaring interfaces with cyclic references\n\nIn this example, `Node` has an `EdgeT` associated facet that is constrained to\nimplement `Edge`, and `Edge` has a `NodeT` associated facet that is constrained\nto implement `Node`. Furthermore, the `NodeT` of an `EdgeT` is the original\ntype, and the other way around. This is accomplished by naming and then forward\ndeclaring the constraints that can't be stated directly:\n\n```carbon\n// Forward declare interfaces used in\n// parameter lists of constraints.\ninterface Edge;\ninterface Node;\n\n// Forward declare named constraints used in\n// interface definitions.\nprivate constraint EdgeFor(N:! Node);\nprivate constraint NodeFor(E:! Edge);\n\n// Define interfaces using named constraints.\ninterface Edge {\n  let NodeT:! NodeFor(Self);\n  fn Head[self: Self]() -> NodeT;\n}\ninterface Node {\n  let EdgeT:! EdgeFor(Self);\n  fn Edges[self: Self]() -> DynArray(EdgeT);\n}\n\n// Now that the interfaces are defined, can\n// refer to members of the interface, so it is\n// now legal to define the named constraints.\nconstraint EdgeFor(N:! Node) {\n  extend Edge where .NodeT = N;\n}\nconstraint NodeFor(E:! Edge) {\n  extend Node where .EdgeT = E;\n}\n```\n\n> **Future work:** This approach has limitations. For example the compiler only\n> knows `EdgeT` is convertible to `type` in the body of the `interface Node`\n> definition, which may not be enough to satisfy the requirements to be an\n> argument to `DynArray`. If this proves to be a problem, we may decided to\n> expand what can be done with incomplete interfaces and types to allow the\n> above to be written without the additional private constraints:\n>\n> ```carbon\n> interface Node;\n>\n> interface Edge {\n>   let NodeT:! Node where .EdgeT = Self;\n>   fn Head[self: Self]() -> NodeT;\n> }\n>\n> interface Node {\n>   let EdgeT:! Movable & Edge where .NodeT = Self;\n>   fn Edges[self: Self]() -> DynArray(EdgeT);\n> }\n> ```\n\n### Interfaces with parameters constrained by the same interface\n\nTo work around\n[the restriction about not being able to name an interface in its parameter list](#declaring-interfaces-and-named-constraints),\ninstead include that requirement in the body of the interface.\n\n```carbon\n// Want to require that `T` satisfies `CommonType(Self)`,\n// but that can't be done in the parameter list.\ninterface CommonType(T:! type) {\n  let Result:! type;\n  // Instead add the requirement inside the definition.\n  require T impls CommonType(Self);\n}\n```\n\nNote however that `CommonType` is still incomplete inside its definition, so no\nconstraints on members of `CommonType` are allowed, and that this\n`require T impls` declaration\n[must involve `Self`](#interface-requiring-other-interfaces-revisited).\n\n```carbon\ninterface CommonType(T:! type) {\n  let Result:! type;\n  // ❌ Illegal: `CommonType` is incomplete\n  require T impls CommonType(Self) where .Result == Result;\n}\n```\n\nInstead, a forward-declared named constraint can be used in place of the\nconstraint that can only be defined later. This is\n[the same strategy used to work around cyclic references](#example-of-declaring-interfaces-with-cyclic-references).\n\n```carbon\nprivate constraint CommonTypeResult(T:! type, R:! type);\n\ninterface CommonType(T:! type) {\n  let Result:! type;\n  // ✅ Allowed: `CommonTypeResult` is incomplete, but\n  //             no members are accessed.\n  require T impls CommonTypeResult(Self, Result);\n}\n\nconstraint CommonTypeResult(T:! type, R:! type) {\n  extend CommonType(T) where .Result == R;\n}\n```\n\n## Interface members with definitions\n\nInterfaces may provide definitions for members, such as a function body for an\nassociated function or method or a value for an associated constant. If these\ndefinitions may be overridden in implementations, they are called \"defaults\" and\nprefixed with the `default` keyword. Otherwise they are called \"final members\"\nand prefixed with the `final` keyword.\n\n### Interface defaults\n\nAn interface may provide a default implementation of methods in terms of other\nmethods in the interface.\n\n```carbon\ninterface Vector {\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: f64) -> Self;\n  // Default definition of `Invert` calls `Scale`.\n  default fn Invert[self: Self]() -> Self {\n    return self.Scale(-1.0);\n  }\n}\n```\n\nA default function or method may also be defined out of line, later in the same\nfile as the interface definition:\n\n```carbon\ninterface Vector {\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: f64) -> Self;\n  default fn Invert[self: Self]() -> Self;\n}\n// `Vector` is considered complete at this point,\n// even though `Vector.Invert` is still incomplete.\nfn Vector.Invert[self: Self]() -> Self {\n  return self.Scale(-1.0);\n}\n```\n\nAn impl of that interface for a type may omit a definition of `Invert` to use\nthe default, or provide a definition to override the default.\n\nInterface defaults are helpful for [evolution](#evolution), as well as reducing\nboilerplate. Defaults address the gap between the minimum necessary for a type\nto provide the desired functionality of an interface and the breadth of API that\ndevelopers desire. As an example, in Rust the\n[iterator trait](https://doc.rust-lang.org/std/iter/trait.Iterator.html) only\nhas one required method but dozens of \"provided methods\" with defaults.\n\nDefaults may also be provided for associated constants, such as associated\nfacets, and interface parameters, using the `= <default value>` syntax.\n\n```carbon\ninterface Add(Right:! type = Self) {\n  default let Result:! type = Self;\n  fn DoAdd[self: Self](right: Right) -> Result;\n}\n\nimpl String as Add() {\n  // Right == Result == Self == String\n  fn DoAdd[self: Self](right: Self) -> Self;\n}\n```\n\nNote that `Self` is a legal default value for an associated facet or facet\nparameter. In this case the value of those names is not determined until `Self`\nis, so `Add()` is equivalent to the constraint:\n\n```carbon\n// Equivalent to Add()\nconstraint AddDefault {\n  extend Add(Self);\n}\n```\n\nNote also that the parenthesis are required after `Add`, even when all\nparameters are left as their default values.\n\nMore generally, default expressions may reference other associated constants or\n`Self` as parameters to type constructors. For example:\n\n```carbon\ninterface Iterator {\n  let Element:! type;\n  default let Pointer:! type = Element*;\n}\n```\n\nCarbon does **not** support providing a default implementation of a required\ninterface.\n\n```carbon\ninterface TotalOrder {\n  fn TotalLess[self: Self](right: Self) -> bool;\n  // ❌ Illegal: May not provide definition\n  //             for required interface.\n  require impls PartialOrder {\n    fn PartialLess[self: Self](right: Self) -> bool {\n      return self.TotalLess(right);\n    }\n  }\n}\n```\n\nThe workaround for this restriction is to use a\n[blanket impl declaration](#blanket-impl-declarations) instead:\n\n```carbon\ninterface TotalOrder {\n  fn TotalLess[self: Self](right: Self) -> bool;\n  // No `require` declaration, since implementers of\n  // `TotalOrder` don't need to also implement\n  // `PartialOrder`, since an implementation is provided.\n}\n\n// Any type that implements `TotalOrder` also has at\n// least this implementation of `PartialOrder`:\nimpl forall [T:! TotalOrder] T as PartialOrder {\n  fn PartialLess[self: Self](right: Self) -> bool {\n    return self.TotalLess(right);\n  }\n}\n```\n\nNote that by the [orphan rule](#orphan-rule), this blanket impl must be defined\nin the same library as `PartialOrder`.\n\n**Comparison with other languages:** Rust supports specifying defaults for\n[methods](https://doc.rust-lang.org/book/ch10-02-traits.html#default-implementations),\n[interface parameters](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#default-generic-type-parameters-and-operator-overloading),\nand\n[associated constants](https://doc.rust-lang.org/reference/items/associated-items.html#associated-constants-examples).\nRust has found them valuable.\n\n### `final` members\n\nAs an alternative to providing a definition of an interface member as a default,\nmembers marked with the `final` keyword will not allow that definition to be\noverridden in `impl` definitions.\n\n```carbon\ninterface TotalOrder {\n  fn TotalLess[self: Self](right: Self) -> bool;\n  final fn TotalGreater[self: Self](right: Self) -> bool {\n    return right.TotalLess(self);\n  }\n}\n\nclass String {\n  extend impl as TotalOrder {\n    fn TotalLess[self: Self](right: Self) -> bool { ... }\n    // ❌ Illegal: May not provide definition of final\n    //             method `TotalGreater`.\n    fn TotalGreater[self: Self](right: Self) -> bool { ... }\n  }\n}\n\ninterface Add(T:! type = Self) {\n  // `AddWith` *always* equals `T`\n  final let AddWith:! type = T;\n  // Has a *default* of `Self`\n  default let Result:! type = Self;\n  fn DoAdd[self: Self](right: AddWith) -> Result;\n}\n```\n\nFinal members may also be defined out-of-line:\n\n```carbon\ninterface TotalOrder {\n  fn TotalLess[self: Self](right: Self) -> bool;\n  final fn TotalGreater[self: Self](right: Self) -> bool;\n}\n// `TotalOrder` is considered complete at this point, even\n// though `TotalOrder.TotalGreater` is not yet defined.\nfn TotalOrder.TotalGreater[self: Self](right: Self) -> bool {\n return right.TotalLess(self);\n}\n```\n\nThere are a few reasons for this feature:\n\n-   When overriding would be inappropriate.\n-   Matching the functionality of non-virtual methods in base classes, so\n    interfaces can be a replacement for inheritance.\n-   Potentially reduce dynamic dispatch when using the interface in a\n    [`DynPtr`](#dynamic-types).\n\nNote that this applies to associated entities, not interface parameters.\n\n## Interface requiring other interfaces revisited\n\nRecall that an\n[interface can require another interface be implemented for the type](#interface-requiring-other-interfaces),\nas in:\n\n```carbon\ninterface Iterable {\n  require impls Equatable;\n  // ...\n}\n```\n\nThis states that the type implementing the interface `Iterable`, which in this\ncontext is called `Self`, must also implement the interface `Equatable`. As is\ndone with [conditional conformance](#conditional-conformance), we allow another\ntype to be specified between `require` and `impls` to say some type other than\n`Self` must implement an interface. For example,\n\n```carbon\ninterface IntLike {\n  require i32 impls As(Self);\n  // ...\n}\n```\n\nsays that if `Self` implements `IntLike`, then `i32` must implement `As(Self)`.\nSimilarly,\n\n```carbon\ninterface CommonTypeWith(T:! type) {\n  require T impls CommonTypeWith(Self);\n  // ...\n}\n```\n\nsays that if `Self` implements `CommonTypeWith(T)`, then `T` must implement\n`CommonTypeWith(Self)`.\n\nA `require <type> impls <facet type>` constraint in an `interface`, or\n`constraint`, definition must still use `Self` as either the type, or as a\nparameter to the [type](#parameterized-types) or an\n[interface](#parameterized-interfaces) in the facet type. In particular, it\nrequires `Self` be part of the type structure of any `impl` that could satisfy\nthat `require`. If the `<type>` is omitted entirely, it will be implied to be\n`Self`. For example:\n\n-   ✅ Allowed: `require impls Equatable`\n-   ✅ Allowed: `require Self impls Equatable`\n-   ✅ Allowed: `require Vector(Self) impls Equatable`\n-   ✅ Allowed: `require i32 impls CommonTypeWith(Self)`\n-   ✅ Allowed: `require impls CommonTypeWith(Self)`\n-   ✅ Allowed: `require Self impls CommonTypeWith(Self)`\n-   ❌ Error: `require i32 impls Equatable`\n-   ❌ Error: `require i32 impls Equatable where .Result = Self`\n-   ❌ Error: `require T impls Equatable` when `T` is some parameter to the\n    interface\n\nThis restriction allows the Carbon compiler to know where to look for facts\nabout a type. If `require i32 impls Equatable` could appear in any `interface`\ndefinition, that implies having to search all of them when considering what\ninterfaces `i32` implements. This would create a\n[coherence](terminology.md#coherence) problem, since then the set of facts true\nfor a type would depend on which interfaces have been imported.\n\nWhen implementing an interface with an `require`...`impls` requirement, that\nrequirement must be satisfied by an implementation in an imported library, an\nimplementation somewhere in the same file, or a constraint in the impl\ndeclaration. Implementing the requiring interface is a promise that the\nrequirement will be implemented. This is like a\n[forward declaration of an impl](#declaring-implementations) except that the\ndefinition can be broader instead of being required to match exactly.\n\n```carbon\n// `Iterable` requires `Equatable`, so there must be some\n// impl of `Equatable` for `Vector(i32)` in this file.\nimpl Vector(i32) as Iterable { ... }\n\nfn RequiresEquatable[T:! Equatable](x: T) { ... }\nfn ProcessVector(v: Vector(i32)) {\n  // ✅ Allowed since `Vector(i32)` is known to\n  // implement `Equatable`.\n  RequiresEquatable(v);\n}\n\n// Satisfies the requirement that `Vector(i32)` must\n// implement `Equatable` since `i32 impls Equatable`.\nimpl forall [T:! Equatable] Vector(T) as Equatable { ... }\n```\n\nIn some cases, the interface's requirement can be trivially satisfied by the\nimplementation itself, as in:\n\n```carbon\nimpl forall [T:! type] T as CommonTypeWith(T) { ... }\n```\n\nHere is an example where the requirement of interface `Iterable` that the type\nimplements interface `Equatable` is satisfied by a constraint in the `impl`\ndeclaration:\n\n```carbon\nclass Foo(T:! type) {}\n// This is allowed because we know that an `impl Foo(T) as Equatable`\n// will exist for all types `T` for which this impl is used, even\n// though there's neither an imported impl nor an impl in this file.\nimpl forall [T:! type where Foo(T) impls Equatable]\n    Foo(T) as Iterable {}\n```\n\nThis might be used to provide an implementation of `Equatable` for types that\nalready satisfy the requirement of implementing `Iterable`:\n\n```carbon\nclass Bar {}\nimpl Foo(Bar) as Equatable {}\n// Gives `Foo(Bar) impls Iterable` using the blanket impl of\n// `Iterable` for `Foo(T)`.\n```\n\n### Requirements with `where` constraints\n\nAn interface implementation requirement with a `where` clause is harder to\nsatisfy. Consider an interface `B` that has a requirement that interface `A` is\nalso implemented.\n\n```carbon\ninterface A(T:! type) {\n  let Result:! type;\n}\ninterface B(T:! type) {\n  require impls A(T) where .Result == i32;\n}\n```\n\nAn implementation of `B` for a set of types can only be valid if there is a\nvisible implementation of `A` with the same `T` parameter for those types with\nthe `.Result` associated facet set to `i32`. That is\n[not sufficient](/proposals/p1088.md#less-strict-about-requirements-with-where-clauses),\nthough, unless the implementation of `A` can't be specialized, either because it\nis [marked `final`](#final-impl-declarations) or is not\n[parameterized](#parameterized-impl-declarations). Implementations in other\nlibraries can't make `A` be implemented for fewer types, but can cause `.Result`\nto have a different assignment.\n\n## Observing a type implements an interface\n\nAn [`observe` declaration](#observe-declarations) can be used to show that two\ntypes are equal so code can pass type checking without explicitly writing casts,\nand without requiring the compiler to do a unbounded search that may not\nterminate. An `observe` declaration can also be used to show that a type\nimplements an interface, in cases where the compiler will not work this out for\nitself.\n\n### Observing interface requirements\n\nOne situation where this occurs is when there is a chain of\n[interfaces requiring other interfaces](#interface-requiring-other-interfaces-revisited).\nDuring the `impl` validation done during type checking, Carbon will only\nconsider the interfaces that are direct requirements of the interfaces the type\nis known to implement. An `observe`...`impls` declaration can be used to add an\ninterface that is a direct requirement to the set of interfaces whose direct\nrequirements will be considered for that type. This allows a developer to\nprovide a proof that there is a sequence of requirements that demonstrate that a\ntype implements an interface, as in this example:\n\n```carbon\ninterface A { }\ninterface B { require impls A; }\ninterface C { require impls B; }\ninterface D { require impls C; }\n\nfn RequiresA[T:! A](x: T);\nfn RequiresC[T:! C](x: T);\nfn RequiresD[T:! D](x: T) {\n  // ✅ Allowed: `D` directly requires `C` to be implemented.\n  RequiresC(x);\n\n  // ❌ Illegal: No direct connection between `D` and `A`.\n  // RequiresA(x);\n\n  // `T impls D` and `D` directly requires `C` to be\n  // implemented.\n  observe T impls C;\n\n  // `T impls C` and `C` directly requires `B` to be\n  // implemented.\n  observe T impls B;\n\n  // ✅ Allowed: `T impls B` and `B` directly requires\n  //             `A` to be implemented.\n  RequiresA(x);\n}\n```\n\nNote that `observe` statements do not affect which impl is selected during code\ngeneration. For [coherence](terminology.md#coherence), the impl used for a\n(type, interface) pair must always be the same, independent of context. The\n[termination rule](#termination-rule) governs when compilation may fail when the\ncompiler can't determine the `impl` definition to select.\n\n### Observing blanket impl declarations\n\nAn `observe`...`impls` declaration can also be used to observe that a type\nimplements an interface because there is a\n[blanket impl declaration](#blanket-impl-declarations) in terms of requirements\na type is already known to satisfy. Without an `observe` declaration, Carbon\nwill only use blanket impl declarations that are directly satisfied.\n\n```carbon\ninterface A { }\ninterface B { }\ninterface C { }\ninterface D { }\n\nimpl forall [T:! A] T as B { }\nimpl forall [T:! B] T as C { }\nimpl forall [T:! C] T as D { }\n\nfn RequiresD[T:! D](x: T);\nfn RequiresB[T:! B](x: T);\n\nfn RequiresA[T:! A](x: T) {\n  // ✅ Allowed: There is a blanket implementation\n  //             of `B` for types implementing `A`.\n  RequiresB(x);\n\n  // ❌ Illegal: No implementation of `D` for type\n  //             `T` implementing `A`\n  // RequiresD(x);\n\n  // There is a blanket implementation of `B` for\n  // types implementing `A`.\n  observe T impls B;\n\n  // There is a blanket implementation of `C` for\n  // types implementing `B`.\n  observe T impls C;\n\n  // ✅ Allowed: There is a blanket implementation\n  //             of `D` for types implementing `C`.\n  RequiresD(x);\n}\n```\n\nIn the case of an error, a quality Carbon implementation will do a deeper search\nfor chains of requirements and blanket impl declarations and suggest `observe`\ndeclarations that would make the code compile if any solution is found.\n\n### Observing equal to a type implementing an interface\n\nThe [`observe`...`==` form](#observe-declarations) can be combined with the\n`observe`...`impls` form to show that a type implements an interface because it\nis equal to another type that is known to implement that interface.\n\n```carbon\ninterface I {\n  fn F();\n}\n\nfn G(T:! I, U:! type where .Self == T) {\n  // ❌ Illegal: No implementation of `I` for `U`.\n  U.(I.F)();\n\n  // ✅ Allowed: Implementation of `I` for `U`\n  //             through `T`.\n  observe U == T impls I;\n  U.(I.F)();\n\n  // ❌ Illegal: `U` does not extend `I`.\n  U.F();\n}\n```\n\nMultiple `==` clauses are allowed in an `observe` declaration, so you may write\n`observe A == B == C impls I;`.\n\n## Operator overloading\n\nOperations are overloaded for a type by implementing an interface specific to\nthat interface for that type. For example, types implement\n[the `Negate` interface](/docs/design/expressions/arithmetic.md#extensibility)\nto overload the unary `-` operator:\n\n```carbon\n// Unary `-`.\ninterface Negate {\n  default let Result:! type = Self;\n  fn Op[self: Self]() -> Result;\n}\n```\n\nExpressions using operators are rewritten into calls to these interface methods.\nFor example, `-x` would be rewritten to `x.(Negate.Op)()`.\n\nThe interfaces and rewrites used for a given operator may be found in the\n[expressions design](/docs/design/expressions/README.md).\n[Question-for-leads issue #1058](https://github.com/carbon-language/carbon-lang/issues/1058)\ndefines the naming scheme for these interfaces, which was implemented in\n[proposal #1178](https://github.com/carbon-language/carbon-lang/pull/1178).\n\n### Binary operators\n\nBinary operators will have an interface that is\n[parameterized](#parameterized-interfaces) based on the second operand. For\nexample, to say a type may be converted to another type using an `as`\nexpression, implement the\n[`As` interface](/docs/design/expressions/as_expressions.md#extensibility):\n\n```carbon\ninterface As(Dest:! type) {\n  fn Convert[self: Self]() -> Dest;\n}\n```\n\nThe expression `x as U` is rewritten to `x.(As(U).Convert)()`. Note that the\nparameterization of the interface means it can be implemented multiple times to\nsupport multiple operand types.\n\nUnlike `as`, for most binary operators the interface's argument will be the\n_type_ of the right-hand operand instead of its _value_. Consider\n[the interface for a binary operator like `*`](/docs/design/expressions/arithmetic.md#extensibility):\n\n```carbon\n// Binary `*`.\ninterface MulWith(U:! type) {\n  default let Result:! type = Self;\n  fn Op[self: Self](other: U) -> Result;\n}\n```\n\nA use of binary `*` in source code will be rewritten to use this interface:\n\n```carbon\nvar left: Meters = ...;\nvar right: f64 = ...;\nvar result: auto = left * right;\n// Equivalent to:\nvar equivalent: left.(MulWith(f64).Result)\n    = left.(MulWith(f64).Op)(right);\n```\n\nNote that if the types of the two operands are different, then swapping the\norder of the operands will result in a different implementation being selected.\nIt is up to the developer to make those consistent when that is appropriate. The\nstandard library will provide [adapters](#adapting-types) for defining the\nsecond implementation from the first, as in:\n\n```carbon\ninterface OrderedWith(U:! type) {\n  fn Compare[self: Self](u: U) -> Ordering;\n  // ...\n}\n\nclass ReverseComparison(T:! type, U:! OrderedWith(T)) {\n  adapt T;\n  extend impl as OrderedWith(U) {\n    fn Compare[self: Self](u: U) -> Ordering {\n      match (u.Compare(self)) {\n        case .Less         => return .Greater;\n        case .Equivalent   => return .Equivalent;\n        case .Greater      => return .Less;\n        case .Incomparable => return .Incomparable;\n      }\n    }\n  }\n}\n\nimpl SongByTitle as OrderedWith(SongTitle) { ... }\nimpl SongTitle as OrderedWith(SongByTitle)\n    = ReverseComparison(SongTitle, SongByTitle);\n```\n\nIn some cases the reverse operation may not be defined. For example, a library\nmight support subtracting a vector from a point, but not the other way around.\n\nFurther note that even if the reverse implementation exists,\n[the `impl` prioritization rule](#prioritization-rule) might not pick it. For\nexample, if we have two types that support comparison with anything implementing\nan interface that the other implements:\n\n```carbon\ninterface IntLike {\n  fn AsInt[self: Self]() -> i64;\n}\n\nclass EvenInt { ... }\nimpl EvenInt as IntLike;\nimpl EvenInt as OrderedWith(EvenInt);\n// Allow `EvenInt` to be compared with anything that\n// implements `IntLike`, in either order.\nimpl forall [T:! IntLike] EvenInt as OrderedWith(T);\nimpl forall [T:! IntLike] T as OrderedWith(EvenInt);\n\nclass PositiveInt { ... }\nimpl PositiveInt as IntLike;\nimpl PositiveInt as OrderedWith(PositiveInt);\n// Allow `PositiveInt` to be compared with anything that\n// implements `IntLike`, in either order.\nimpl forall [T:! IntLike] PositiveInt as OrderedWith(T);\nimpl forall [T:! IntLike] T as OrderedWith(PositiveInt);\n```\n\nThen the compiler will favor selecting the implementation based on the type of\nthe left-hand operand:\n\n```carbon\nvar even: EvenInt = ...;\nvar positive: PositiveInt = ...;\n// Uses `EvenInt as OrderedWith(T)` impl\nif (even < positive) { ... }\n// Uses `PositiveInt as OrderedWith(T)` impl\nif (positive > even) { ... }\n```\n\n### `like` operator for implicit conversions\n\nBecause the type of the operands is directly used to select the operator\ninterface implementation, there are no automatic implicit conversions, unlike\nwith function or method calls. Given both a method and an interface\nimplementation for multiplying by a value of type `f64`:\n\n```carbon\nclass Meters {\n  fn Scale[self: Self](s: f64) -> Self;\n}\n// \"Implementation One\"\nimpl Meters as MulWith(f64)\n    where .Result = Meters {\n  fn Op[self: Self](other: f64) -> Result {\n    return self.Scale(other);\n  }\n}\n```\n\nthe method will work with any argument that can be implicitly converted to `f64`\nbut the operator overload will only work with values that have the specific type\nof `f64`:\n\n```carbon\nvar height: Meters = ...;\nvar scale: f32 = 1.25;\n// ✅ Allowed: `scale` implicitly converted\n//             from `f32` to `f64`.\nvar allowed: Meters = height.Scale(scale);\n// ❌ Illegal: `Meters` doesn't implement\n//             `MulWith(f32)`.\nvar illegal: Meters = height * scale;\n```\n\nThe workaround is to define a parameterized implementation that performs the\nconversion. The implementation is for types that implement the\n[`ImplicitAs` interface](/docs/design/expressions/implicit_conversions.md#extensibility).\n\n```carbon\n// \"Implementation Two\"\nimpl forall [T:! ImplicitAs(f64)]\n    Meters as MulWith(T) where .Result = Meters {\n  fn Op[self: Self](other: T) -> Result {\n    // Carbon will implicitly convert `other` from type\n    // `T` to `f64` to perform this call.\n    return self.((Meters as MulWith(f64)).Op)(other);\n  }\n}\n// ✅ Allowed: uses `Meters as MulWith(T)` impl\n//             with `T == f32` since `f32 impls ImplicitAs(f64)`.\nvar now_allowed: Meters = height * scale;\n```\n\nObserve that the [prioritization rule](#prioritization-rule) will still prefer\nthe unparameterized impl when there is an exact match.\n\nTo reduce the boilerplate needed to support these implicit conversions when\ndefining operator overloads, Carbon has the `like` operator. This operator can\nonly be used in the type or facet type part of an `impl` declaration, as part of\na forward declaration or definition, in a place of a type.\n\n```carbon\n// Notice `f64` has been replaced by `like f64`\n// compared to \"implementation one\" above.\nimpl Meters as MulWith(like f64)\n    where .Result = Meters {\n  fn Op[self: Self](other: f64) -> Result {\n    return self.Scale(other);\n  }\n}\n```\n\nThis `impl` definition actually defines two implementations. The first is the\nsame as this definition with `like f64` replaced by `f64`, giving something\nequivalent to \"implementation one\". The second implementation replaces the\n`like f64` with a parameter that ranges over types that can be implicitly\nconverted to `f64`, equivalent to \"implementation two\".\n\n> **Note:** We have decided to change the following in\n> [a discussion on 2023-07-13](https://docs.google.com/document/d/1gnJBTfY81fZYvI_QXjwKk1uQHYBNHGqRLI2BS_cYYNQ/edit?resourcekey=0-ql1Q1WvTcDvhycf8LbA9DQ#heading=h.rs7m0kytcl4t).\n> The new approach is to have one parameterized implementation replacing all of\n> the `like` expressions on the left of the `as`, and another replacing all of\n> the `like` expressions on the right of the `as`. However, in\n> [a discussion on 2023-07-20](https://docs.google.com/document/d/1gnJBTfY81fZYvI_QXjwKk1uQHYBNHGqRLI2BS_cYYNQ/edit?resourcekey=0-ql1Q1WvTcDvhycf8LbA9DQ#heading=h.msdqbemd6axi),\n> we decided that this change would not affect how we handle nested `like`\n> expressions: `like Vector(like i32)` is still `like Vector(i32)` plus\n> `Vector(like i32)`. These changes have not yet gone through the proposal\n> process, and we may decide to reject nested `like` until we have a\n> demonstrated need.\n\nIn general, each `like` adds one additional parameterized implementation. There\nis always the impl defined with all of the `like` expressions replaced by their\narguments with the definition supplied in the source code. In addition, for each\n`like` expression, there is an automatic `impl` definition with it replaced by a\nnew parameter. These additional automatic implementations will delegate to the\nmain `impl` definition, which will trigger implicit conversions according to\n[Carbon's ordinary implicit conversion rules](/docs/design/expressions/implicit_conversions.md).\nIn this example, there are two uses of `like`, producing three implementations\n\n```carbon\nimpl like Meters as MulWith(like f64)\n    where .Result = Meters {\n  fn Op[self: Self](other: f64) -> Result {\n    return self.Scale(other);\n  }\n}\n```\n\nis equivalent to \"implementation one\", \"implementation two\", and:\n\n```carbon\nimpl forall [T:! ImplicitAs(Meters)]\n    T as MulWith(f64) where .Result = Meters {\n  fn Op[self: Self](other: f64) -> Result {\n    // Will implicitly convert `self` to `Meters` in\n    // order to match the signature of this `Op` method.\n    return self.((Meters as MulWith(f64)).Op)(other);\n  }\n}\n```\n\n`like` may be used in `impl` forward declarations in a way analogous to `impl`\ndefinitions.\n\n```carbon\nimpl like Meters as MulWith(like f64)\n    where .Result = Meters;\n}\n```\n\nis equivalent to:\n\n```carbon\n// All `like`s removed. Same as the declaration part of\n// \"implementation one\", without the body of the definition.\nimpl Meters as MulWith(f64) where .Result = Meters;\n\n// First `like` replaced with a wildcard.\nimpl forall [T:! ImplicitAs(Meters)]\n    T as MulWith(f64) where .Result = Meters;\n\n// Second `like` replaced with a wildcard. Same as the\n// declaration part of \"implementation two\", without the\n// body of the definition.\nimpl forall [T:! ImplicitAs(f64)]\n    Meters as MulWith(T) where .Result = Meters;\n```\n\nIn addition, the generated `impl` definition for a `like` is implicitly injected\nat the end of the (unique) source file in which the `impl` is defined. That is,\nit is injected in the API file if the `impl` definition is in an API file, and\nin the sole impl file with the `impl` definition otherwise.\n\nIf one `impl` declaration uses `like`, other declarations must use `like` in the\nsame way to match.\n\nThe `like` operator may be nested, as in:\n\n```carbon\nimpl like Vector(like String) as Printable;\n```\n\nWhich will generate implementations with declarations:\n\n```carbon\nimpl Vector(String) as Printable;\nimpl forall [T:! ImplicitAs(Vector(String))] T as Printable;\nimpl forall [T:! ImplicitAs(String)] Vector(T) as Printable;\n```\n\nThe generated implementations must be legal or the `like` is illegal. For\nexample, it must be legal to have those `impl` definitions in this library by\nthe [orphan rule](#orphan-rule). In addition, the generated `impl` definitions\nmust only require implicit conversions that are guaranteed to exist. For\nexample, there existing an implicit conversion from `T` to `String` does not\nimply that there is one from `Vector(T)` to `Vector(String)`, so the following\nuse of `like` is illegal:\n\n```carbon\n// ❌ Illegal: Can't convert a value with type\n//             `Vector(T:! ImplicitAs(String))`\n//             to `Vector(String)` for `self`\n//             parameter of `Printable.Print`.\nimpl Vector(like String) as Printable;\n```\n\nSince the additional implementation definitions are generated eagerly, these\nerrors will be reported in the file with the first declaration.\n\nThe argument to `like` must either not mention any type parameters, or those\nparameters must be able to be determined due to being repeated outside of the\n`like` expression.\n\n```carbon\n// ✅ Allowed: no parameters\nimpl like Meters as Printable;\n\n// ❌ Illegal: No other way to determine `T`\nimpl forall [T:! IntLike] like T as Printable;\n\n// ❌ Illegal: `T` being used in a `where` clause\n//             is insufficient.\nimpl forall [T:! IntLike] like T\n    as MulWith(i64) where .Result = T;\n\n// ❌ Illegal: `like` can't be used in a `where`\n//             clause.\nimpl Meters as MulWith(f64)\n    where .Result = like Meters;\n\n// ✅ Allowed: `T` can be determined by another\n//             part of the query.\nimpl forall [T:! IntLike] like T\n    as MulWith(T) where .Result = T;\nimpl forall [T:! IntLike] T\n    as MulWith(like T) where .Result = T;\n\n// ✅ Allowed: Only one `like` used at a time, so this\n//             is equivalent to the above two examples.\nimpl forall [T:! IntLike] like T\n    as MulWith(like T) where .Result = T;\n```\n\n## Parameterized types\n\nGeneric types may be defined by giving them compile-time parameters. Those\nparameters may be used to specify types in the declarations of its members, such\nas data fields, member functions, and even interfaces being implemented. For\nexample, a container type might be parameterized by a facet describing the type\nof its elements:\n\n```carbon\nclass HashMap(\n    KeyT:! Hashable & Eq & Movable,\n    ValueT:! Movable) {\n  // `Self` is `HashMap(KeyT, ValueT)`.\n\n  // Class parameters may be used in function signatures.\n  fn Insert[ref self: Self](k: KeyT, v: ValueT);\n\n  // Class parameters may be used in field types.\n  private var buckets: DynArray((KeyT, ValueT));\n\n  // Class parameters may be used in interfaces implemented.\n  extend impl as Container where .ElementType = (KeyT, ValueT);\n  impl as OrderedWith(HashMap(KeyT, ValueT));\n}\n```\n\nNote that, unlike functions, every parameter to a type must be a compile-time\nbinding, either symbolic using `:!` or template using `template`...`:!`, not\nruntime, with a plain `:`.\n\nTwo types are the same if they have the same name and the same arguments, after\napplying aliases and [rewrite constraints](#rewrite-constraints). Carbon's\n[manual type equality](#manual-type-equality) approach means that the compiler\nmay not always be able to tell when two\n[type expressions](terminology.md#type-expression) are equal without help from\nthe user, in the form of [`observe` declarations](#observe-declarations). This\nmeans Carbon will not in general be able to determine when types are unequal.\n\nUnlike an [interface's parameters](#parameterized-interfaces), a type's\nparameters may be [deduced](terminology.md#deduced-parameter), as in:\n\n```carbon\nfn ContainsKey[KeyT:! Movable, ValueT:! Movable]\n    (haystack: HashMap(KeyT, ValueT), needle: KeyT)\n    -> bool { ... }\nfn MyMapContains(s: String) {\n  var map: HashMap(String, i32) = ((\"foo\", 3), (\"bar\", 5));\n  // ✅ Deduces `KeyT` = `String as Movable` from the types of both arguments.\n  // Deduces `ValueT` = `i32 as Movable` from the type of the first argument.\n  return ContainsKey(map, s);\n}\n```\n\nNote that restrictions on the type's parameters from the type's declaration can\nbe [implied constraints](#implied-constraints) on the function's parameters. In\nthe above example, the `KeyT` parameter to `ContainsKey` gets `Hashable & Eq`\nimplied constraints from the declaration of the corresponding parameter to\n`HashMap`.\n\n> **Future work:** We may want to support optional deduced parameters in square\n> brackets `[`...`]` before the explicit parameters in round parens `(`...`)`.\n\n> **References:** This feature is from\n> [proposal #1146: Generic details 12: parameterized types](https://github.com/carbon-language/carbon-lang/pull/1146).\n\n### Generic methods\n\nA generic type may have methods with additional compile-time parameters. For\nexample, this `Set(T)` type may be compared to anything implementing the\n`Container` interface as long as the element types match:\n\n```carbon\nclass Set(T:! Ordered) {\n  fn Less[U:! Container with .ElementType = T, self: Self](u: U) -> bool;\n  // ...\n}\n```\n\nThe `Less` method is parameterized both by the `T` parameter to the `Set` type\nand its own `U` parameter deduced from the type of its first argument.\n\n### Conditional methods\n\nA method could be defined conditionally for a generic type by using a more\nspecific type in place of `Self` in the method declaration. For example, this is\nhow to define a dynamically sized array type that only has a `Sort` method if\nits elements implement the `Ordered` interface:\n\n```carbon\nclass DynArray(T:! type) {\n  // `DynArray(T)` has a `Sort()` method if `T impls Ordered`.\n  fn Sort[C:! Ordered, ref self: DynArray(C)]();\n}\n```\n\n**Comparison with other languages:** In\n[Rust](https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods)\nthis feature is part of conditional conformance. Swift supports conditional\nmethods using\n[conditional extensions](https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID553)\nor\n[contextual where clauses](https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID628).\n\n### Specialization\n\n[Specialization](terminology.md#checked-generic-specialization) is used to\nimprove performance in specific cases when a general strategy would be\ninefficient. For example, you might use\n[binary search](https://en.wikipedia.org/wiki/Binary_search_algorithm) for\ncontainers that support random access and keep their contents in sorted order\nbut [linear search](https://en.wikipedia.org/wiki/Linear_search) in other cases.\nTypes, like functions, may not be specialized directly in Carbon. This effect\ncan be achieved, however, through delegation.\n\nFor example, imagine we have a parameterized class `Optional(T)` that has a\ndefault storage strategy that works for all `T`, but for some types we have a\nmore efficient approach. For pointers we can use a\n[null value](https://en.wikipedia.org/wiki/Null_pointer) to represent \"no\npointer\", and for booleans we can support `True`, `False`, and `None` in a\nsingle byte. Clients of the optional library may want to add additional\nspecializations for their own types. We make an interface that represents \"the\nstorage of `Optional(T)` for type `T`,\" written here as `OptionalStorage`:\n\n```carbon\ninterface OptionalStorage {\n  let Storage:! type;\n  fn MakeNone() -> Storage;\n  fn Make(x: Self) -> Storage;\n  fn IsNone(x: Storage) -> bool;\n  fn Unwrap(x: Storage) -> Self;\n}\n```\n\nThe default implementation of this interface is provided by a\n[blanket implementation](#blanket-impl-declarations):\n\n```carbon\n// Default blanket implementation\nimpl forall [T:! Movable] T as OptionalStorage\n    where .Storage = (bool, T) {\n  ...\n}\n```\n\nThis implementation can then be\n[specialized](#lookup-resolution-and-specialization) for more specific type\npatterns:\n\n```carbon\n// Specialization for pointers, using nullptr == None\nfinal impl forall [T:! type] T* as OptionalStorage\n    where .Storage = Array(Byte, sizeof(T*)) {\n  ...\n}\n// Specialization for type `bool`.\nfinal impl bool as OptionalStorage\n    where .Storage = Byte {\n  ...\n}\n```\n\nFurther, libraries can implement `OptionalStorage` for their own types, assuming\nthe interface is not marked `private`. Then the implementation of `Optional(T)`\ncan delegate to `OptionalStorage` for anything that can vary with `T`:\n\n```carbon\nclass Optional(T:! Movable) {\n  fn None() -> Self {\n    return {.storage = T.(OptionalStorage.MakeNone)()};\n  }\n  fn Some(x: T) -> Self {\n    return {.storage = T.(OptionalStorage.Make)(x)};\n  }\n  ...\n  private var storage: T.(OptionalStorage.Storage);\n}\n```\n\nNote that the constraint on `T` is just `Movable`, not\n`Movable & OptionalStorage`, since the `Movable` requirement is\n[sufficient to guarantee](#lookup-resolution-and-specialization) that some\nimplementation of `OptionalStorage` exists for `T`. Carbon does not require\ncallers of `Optional`, even checked-generic callers, to specify that the\nargument type implements `OptionalStorage`:\n\n```carbon\n// ✅ Allowed: `T` just needs to be `Movable` to form `Optional(T)`.\n//             A `T:! OptionalStorage` constraint is not required.\nfn First[T:! Movable & Eq](v: Vector(T)) -> Optional(T);\n```\n\nAdding `OptionalStorage` to the constraints on the parameter to `Optional` would\nobscure what types can be used as arguments. `OptionalStorage` is an\nimplementation detail of `Optional` and need not appear in its public API.\n\nIn this example, a `let` is used to avoid repeating `OptionalStorage` in the\ndefinition of `Optional`, since it has no name conflicts with the members of\n`Movable`:\n\n```carbon\nclass Optional(T:! Movable) {\n  private let U:! Movable & OptionalStorage = T;\n  fn None() -> Self {\n    return {.storage = U.MakeNone()};\n  }\n  fn Some(x: T) -> Self {\n    return {.storage = U.Make(x)};\n  }\n  ...\n  private var storage: U.Storage;\n}\n```\n\n> **Alternative considered:** Direct support for specialization of types was\n> considered in [proposal #1146](/proposals/p1146.md#alternatives-considered).\n\n## Future work\n\n### Dynamic types\n\nChecked-generics provide enough structure to support runtime dispatch for values\nwith types that vary at runtime, without giving up type safety. Both Rust and\nSwift have demonstrated the value of this feature.\n\n#### Runtime type parameters\n\nThis feature is about allowing a function's type parameter to be passed in as a\ndynamic (non-compile-time) parameter. All values of that type would still be\nrequired to have the same type.\n\n#### Runtime type fields\n\nInstead of passing in a single type parameter to a function, we could store a\ntype per value. This changes the data layout of the value, and so is a somewhat\nmore invasive change. It also means that when a function operates on multiple\nvalues they could have different real types.\n\n### Abstract return types\n\nThis lets you return an anonymous type implementing an interface from a\nfunction. In Rust this is the\n[`impl Trait` return type](https://rust-lang.github.io/rfcs/1522-conservative-impl-trait.html).\n\nIn Swift, there are discussions about implementing this feature under the name\n\"reverse generics\" or \"opaque result types\":\n[1](https://forums.swift.org/t/improving-the-ui-of-generics/22814#heading--reverse-generics),\n[2](https://forums.swift.org/t/reverse-generics-and-opaque-result-types/21608),\n[3](https://forums.swift.org/t/se-0244-opaque-result-types/21252),\n[4](https://forums.swift.org/t/se-0244-opaque-result-types-reopened/22942),\nSwift is considering spelling this `<V: Collection> V` or `some Collection`.\n\n### Evolution\n\nThere are a collection of use cases for making different changes to interfaces\nthat are already in use. These should be addressed either by describing how they\ncan be accomplished with existing generics features, or by adding features.\n\nIn addition, evolution from (C++ or Carbon) templates to checked generics needs\nto be supported and made safe.\n\n### Testing\n\nThe idea is that you would write tests alongside an interface that validate the\nexpected behavior of any type implementing that interface.\n\n### Impl with state\n\nA feature we might consider where an `impl` itself can have state.\n\n### Generic associated facets and higher-ranked facets\n\nThis would be some way to express the requirement that there is a way to go from\na type to an implementation of an interface parameterized by that type.\n\n#### Generic associated facets\n\nGeneric associated facets are about when this is a requirement of an interface.\nThese are also called\n\"[associated type constructors](https://smallcultfollowing.com/babysteps/blog/2016/11/02/associated-type-constructors-part-1-basic-concepts-and-introduction/).\"\n\nRust has\n[stabilized this feature](https://github.com/rust-lang/rust/pull/96709).\n\n#### Higher-ranked types\n\nHigher-ranked types are used to represent this requirement in a function\nsignature. They can be\n[emulated using generic associated facets](https://smallcultfollowing.com/babysteps//blog/2016/11/03/associated-type-constructors-part-2-family-traits/).\n\n### Field requirements\n\nWe might want to allow interfaces to express the requirement that any\nimplementing type has a particular field. This would be to match the\nexpressivity of inheritance, which can express \"all subtypes start with this\nlist of fields.\"\n\n### Bridge for C++ customization points\n\nSee details in [the goals document](goals.md#bridge-for-c-customization-points).\n\n### Variadic arguments\n\nSome facility for allowing a function to take a variable number of arguments,\nwith the [definition checked](terminology.md#complete-definition-checking)\nindependent of calls. Open\n[proposal #2240](https://github.com/carbon-language/carbon-lang/pull/2240) is\nadding this feature.\n\n### Value constraints for template parameters\n\nWe have planned support for predicates that constrain the value of non-facet\ntemplate parameters. For example, we might support a predicate that constrains\nan integer to live inside a specified range. See\n[question-for-leads issue #2153: Checked generics calling templates](https://github.com/carbon-language/carbon-lang/issues/2153)\nand\n[future work in proposal #2200: Template generics](/proposals/p2200.md#predicates-constraints-on-values).\n\n## References\n\n-   [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n-   [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n-   [#818: Constraints for generics (generics details 3)](https://github.com/carbon-language/carbon-lang/pull/818)\n-   [#931: Generic impls access (details 4)](https://github.com/carbon-language/carbon-lang/pull/931)\n-   [#920: Generic parameterized impls (details 5)](https://github.com/carbon-language/carbon-lang/pull/920)\n-   [#950: Generic details 6: remove facets](https://github.com/carbon-language/carbon-lang/pull/950)\n-   [#983: Generic details 7: final impls](https://github.com/carbon-language/carbon-lang/pull/983)\n-   [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n-   [#990: Generics details 8: interface default and final members](https://github.com/carbon-language/carbon-lang/pull/990)\n-   [#1013: Generics: Set associated constants using `where` constraints](https://github.com/carbon-language/carbon-lang/pull/1013)\n-   [#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084)\n-   [#1088: Generic details 10: interface-implemented requirements](https://github.com/carbon-language/carbon-lang/pull/1088)\n-   [#1144: Generic details 11: operator overloading](https://github.com/carbon-language/carbon-lang/pull/1144)\n-   [#1146: Generic details 12: parameterized types](https://github.com/carbon-language/carbon-lang/pull/1146)\n-   [#1327: Generics: `impl forall`](https://github.com/carbon-language/carbon-lang/pull/1327)\n-   [#2107: Clarify rules around `Self` and `.Self`](https://github.com/carbon-language/carbon-lang/pull/2107)\n-   [#2138: Checked and template generic terminology](https://github.com/carbon-language/carbon-lang/pull/2138)\n-   [Issue #2153: Checked generics calling templates](https://github.com/carbon-language/carbon-lang/issues/2153)\n-   [#2173: Associated constant assignment versus equality](https://github.com/carbon-language/carbon-lang/pull/2173)\n-   [#2200: Template generics](https://github.com/carbon-language/carbon-lang/pull/2200)\n-   [#2347: What can be done with an incomplete interface](https://github.com/carbon-language/carbon-lang/pull/2347)\n-   [#2360: Types are values of type `type`](https://github.com/carbon-language/carbon-lang/pull/2360)\n-   [#2376: Constraints must use `Self`](https://github.com/carbon-language/carbon-lang/pull/2376)\n-   [#2483: Replace keyword `is` with `impls`](https://github.com/carbon-language/carbon-lang/pull/2483)\n-   [#2687: Termination algorithm for impl selection](https://github.com/carbon-language/carbon-lang/pull/2687)\n-   [#2760: Consistent `class` and `interface` syntax](https://github.com/carbon-language/carbon-lang/pull/2760)\n-   [#2964: Expression phase terminology](https://github.com/carbon-language/carbon-lang/pull/2964)\n-   [#3162: Reduce ambiguity in terminology](https://github.com/carbon-language/carbon-lang/pull/3162)\n"
  },
  {
    "path": "docs/design/generics/goals.md",
    "content": "# Generics: Goals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Purpose of this document](#purpose-of-this-document)\n-   [Background](#background)\n    -   [Compile-time parameters](#compile-time-parameters)\n    -   [Interfaces](#interfaces)\n-   [Templates](#templates)\n-   [Checked-generic goals](#checked-generic-goals)\n    -   [Use cases](#use-cases)\n        -   [Generic programming](#generic-programming)\n        -   [Upgrade path from C++ abstract interfaces](#upgrade-path-from-c-abstract-interfaces)\n        -   [Dependency injection](#dependency-injection)\n        -   [Checked generics instead of open overloading and ADL](#checked-generics-instead-of-open-overloading-and-adl)\n    -   [Performance](#performance)\n    -   [Better compiler experience](#better-compiler-experience)\n    -   [Encapsulation](#encapsulation)\n    -   [Predictability](#predictability)\n    -   [Dispatch control](#dispatch-control)\n    -   [Upgrade path from templates](#upgrade-path-from-templates)\n    -   [Path from regular functions](#path-from-regular-functions)\n    -   [Coherence](#coherence)\n    -   [No novel name lookup](#no-novel-name-lookup)\n    -   [Learn from others](#learn-from-others)\n    -   [Interfaces are nominal](#interfaces-are-nominal)\n    -   [Interop and evolution](#interop-and-evolution)\n    -   [Bridge for C++ customization points](#bridge-for-c-customization-points)\n-   [What we are not doing with checked generics](#what-we-are-not-doing-with-checked-generics)\n    -   [Not the full flexibility of templates](#not-the-full-flexibility-of-templates)\n    -   [Checked generics will be checked when defined](#checked-generics-will-be-checked-when-defined)\n    -   [Implementation strategy](#implementation-strategy)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Purpose of this document\n\nThis document attempts to clarify our goals for the design of the generics\nfeature for Carbon. While these are not strict requirements, they represent the\nyardstick by which we evaluate design decisions. We do expect to achieve most of\nthese goals, though some of these goals are somewhat aspirational or\nforward-looking.\n\n## Background\n\nCarbon will support both\n[checked and template generics](terminology.md#checked-versus-template-parameters)\nto support generic programming by way of\n[compile-time parameterization of language constructs](terminology.md#generic-means-compile-time-parameterized).\n\nCarbon's checked generics will feature\n[early type checking](terminology.md#early-versus-late-type-checking) and\n[complete definition checking](terminology.md#complete-definition-checking).\n\nCarbon's [template generics](#templates), in contrast, will more closely follow\nthe\n[compile-time duck typing](https://en.wikipedia.org/wiki/Duck_typing#Templates_or_generic_types)\napproach of C++ templates.\n\n### Compile-time parameters\n\nGeneric functions and generic types will all take some compile-time parameters,\nwhich will frequently be types, and in some cases will be\n[deduced](terminology.md#deduced-parameter) from the types of the values of\nexplicit parameters.\n\nIf a compile-time parameter is a type, the generic function's signature can\nspecify constraints that the caller's type must satisfy. For example, a\nresizable array type (like C++'s `std::vector`) might have a compile-time type\nparameter with the constraint that the type must be movable and have a static\nsize. A sort function might apply to any array whose elements are comparable and\nmovable.\n\nA constraint might involve multiple compile-time parameters. For example, a\nmerge function might apply to two arbitrary containers so long as their elements\nhave the same type.\n\n### Interfaces\n\nWe need some way to express the constraints on a compile-time type parameter. In\nCarbon we express these \"type constraints\" by saying we restrict to types that\nimplement specific [_interfaces_](terminology.md#interface). Interfaces describe\nan API a type could implement; for example, it might specify a set of functions,\nincluding names and signatures. A type implementing an interface may be passed\nas a compile-time type argument to a function that has that interface as a\nrequirement of its compile-time type parameter. Then, the functions defined in\nthe interface may be called in the body of the function. Further, interfaces\nhave names that allow them to be reused.\n\nSimilar compile-time and run-time constructs may be found in other programming\nlanguages:\n\n-   [Rust's traits](https://doc.rust-lang.org/book/ch10-02-traits.html)\n-   [Swift's protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html)\n-   [Java interfaces](<https://en.wikipedia.org/wiki/Interface_(Java)>)\n-   [C++ concepts](<https://en.wikipedia.org/wiki/Concepts_(C%2B%2B)>)\n    (compile-time only)\n-   [Abstract base classes](<https://en.wikipedia.org/wiki/Class_(computer_programming)#Abstract_and_concrete>)\n    in C++, etc. (run-time only)\n-   [Go interfaces](https://gobyexample.com/interfaces)\n\nIn addition to specifying the methods available on a type, we may in the future\nexpand the role of interfaces to allow other type constraints, such as on size,\nprefix of the data layout, specified method implementations, tests that must\npass, etc. This might be part of making interfaces as expressive as classes, as\npart of a strategy to migrate to a future version of Carbon that uses interfaces\ninstead of, rather than in addition to, standard inheritance-and-classes\nobject-oriented language support. For the moment, everything beyond specifying\nthe _methods_ available is out of scope.\n\n## Templates\n\nThe entire idea of statically typed languages is that coding against specific\ntypes and interfaces is a better model and experience. Unfortunately, templates\ndon't provide many of those benefits to programmers until it's too late, when\nusers are consuming the API. Templates also come with high overhead, such as\n[template error messages](#better-compiler-experience).\n\nWe want Carbon code to move towards more rigorously type-checked constructs.\nHowever, existing C++ code is full of unrestricted usage of compile-time\nduck-typed templates. They are incredibly convenient to write and so likely will\ncontinue to exist for a long time.\n\nCarbon will have direct support for templates in addition to checked generics.\nCarbon's template system will be similar to C++ templates with some specific\nchanges:\n\n-   It may have some limitations to be more compatible with checked generics,\n    much like how we\n    [restrict overloading](#checked-generics-instead-of-open-overloading-and-adl).\n-   We likely will have a different method of selecting between different\n    template instantiations, since\n    [SFINAE](https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error)\n    makes it difficult to deliver high quality compiler diagnostics.\n\nOther aspects of Carbon will reduce the number of situations where errors will\nonly be detected after the template is\n[instantiated](terminology.md#instantiation):\n\n-   Carbon's grammar won't require type information to disambiguate parsing, and\n    so definitions may be parsed without knowing the values of template\n    arguments.\n-   Carbon's name resolution is more restricted. Every package has its own\n    namespace, and there will be no\n    [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl).\n\n## Checked-generic goals\n\nOur goal for checked generics support in Carbon is to get most of the expressive\nbenefits of C++ templates and open overloading with fewer downsides.\nAdditionally, we want to support some dynamic dispatch use cases; for example,\nin cases that inheritance struggles with.\n\n### Use cases\n\nTo clarify the expressive range we are aiming for, here are some specific use\ncases we expect Carbon checked generics to cover.\n\n#### Generic programming\n\nWe in particular want to support\n[generic programming](https://en.wikipedia.org/wiki/Generic_programming),\nincluding:\n\n-   Containers: arrays, maps, lists, and more complicated data structures like\n    trees and graphs\n-   Algorithms: sort, search\n-   Wrappers: optional, variant, expected/result, smart pointers\n-   Parameterized numeric types: `std::complex<T>`\n-   Configurable and parametric APIs: the storage-customized `std::chrono` APIs\n-   [Policy-based design](https://en.wikipedia.org/wiki/Modern_C%2B%2B_Design#Policy-based_design)\n\nThese would generally involve static, compile-time type arguments, and so would\ngenerally be used with [static dispatch](#dispatch-control).\n\n#### Upgrade path from C++ abstract interfaces\n\nInterfaces in C++ are often represented by abstract base classes. Checked\ngenerics should offer an alternative that does not rely on inheritance. This\nmeans looser coupling and none of the problems of multiple inheritance. Some\npeople, such as\n[Sean Parent](https://sean-parent.stlab.cc/papers-and-presentations/#better-code-runtime-polymorphism),\nadvocate for runtime polymorphism patterns in C++ that avoid inheritance because\nit can cause runtime performance, correctness, and code maintenance problems in\nsome situations. Those patterns require a lot of boilerplate and complexity in\nC++. It would be nice if those patterns were simpler to express with Carbon\nchecked generics. More generally, Carbon checked generics will provide an\nalternative for those situations inheritance doesn't handle as well. As a\nspecific example, we would like Carbon checked generics to supplant the need to\nsupport multiple inheritance in Carbon.\n\nThis is a case that would use [dynamic dispatch](#dispatch-control).\n\n#### Dependency injection\n\nTypes which only support subclassing for test stubs and mocks, as in\n[\"dependency injection\"](https://en.wikipedia.org/wiki/Dependency_injection),\nshould be able to easily migrate to checked generics. This extends outside the\nrealm of testing, allowing general configuration of how dependencies can be\nsatisfied. For example, checked generics might be used to configure how a\nlibrary writes logs.\n\nThis would allow you to avoid the runtime overhead of virtual functions, using\n[static dispatch](#dispatch-control) without the\n[poor build experience of templates](#better-compiler-experience).\n\n#### Checked generics instead of open overloading and ADL\n\nOne name lookup problem we would like to avoid is caused by open overloading.\nOverloading is where you provide multiple implementations of a function with the\nsame name, and the implementation used in a specific context is determined by\nthe argument types. Open overloading is overloading where the overload set is\nnot restricted to a single file or library. This works with\n[Argument-dependent lookup](https://en.wikipedia.org/wiki/Argument-dependent_name_lookup),\nor [ADL](https://en.cppreference.com/w/cpp/language/adl), a mechanism for\nenabling open overloading without having to reopen the namespace where the\nfunction was originally defined. Together these enable\n[C++ customization points](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html).\n\nThis is commonly used to provide a type-specific implementation of some\noperation, but doesn't provide any enforcement of consistency across the\ndifferent overloads. It makes the meaning of code dependent on which overloads\nare imported, and is at odds with being able to type check a function's\ndefinition before instantiation.\n\nOur goal is to address this use case, known more generally as\n[the expression problem](https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions),\nwith a checked-generics mechanism that does enforce consistency so that type\nchecking is possible without seeing all implementations. This will be Carbon's\nreplacement for open overloading. This is encapsulated in Carbon's\n[\"one static open extension mechanism\" principle](/docs/project/principles/static_open_extension.md).\nAs a consequence, Carbon checked generics will need to be able to support\noperator overloading.\n\nA specific example is the absolute value function `Abs`. We would like to write\n`Abs(x)` for a variety of types. For some types `T`, such as `Int32` or\n`Float64`, the return type will be the same `T`. For other types, such as\n`Complex64` or `Quaternion`, the return type will be different. Checked generic\nfunctions that call `Abs` will need a way to specify whether they only operate\non `T` such that `Abs` has signature `T -> T`.\n\nThis does create an issue when interoperating with C++ code using open\noverloading, which will\n[need to be addressed](#bridge-for-c-customization-points).\n\n### Performance\n\nFor any real-world C++ template, there shall be an idiomatic reformulation in\nCarbon checked generics that has equal or better performance.\n[Performance is the top priority for Carbon](/docs/project/goals.md#performance-critical-software),\nand we expect to use checked generics pervasively, and so they can't compromise\nthat goal in release builds.\n\n**Nice to have:** There are cases where we should aim to do better than C++\ntemplates. For example, the additional structure of checked generics should make\nit easier to reduce generated code duplication, reducing code size and cache\nmisses.\n\n### Better compiler experience\n\nCompared to C++ templates, we expect to reduce build times, particularly in\ndevelopment builds. We also expect the compiler to be able to report clearer\nerrors, and report them earlier in the build process.\n\nOne source of improvement is that the bodies of checked generic functions and\ntypes can be type checked once when they are defined, instead of every time they\nare used. This is both a reduction in the total work done, and how errors can be\nreported earlier. On use, the errors can be a lot clearer since they will be of\nthe form \"argument did not satisfy function's contract as stated in its\nsignature\" instead of \"substitution failed at this line of the function's\nimplementation.\"\n\n**Nice to have:** In development builds, we will have the option of using\n[dynamic dispatch](#dispatch-control) to reduce build times. We may also be able\nto reduce the amount of redundant compilation work even with the\n[static strategy](#dispatch-control) by identifying instantiations with the same\narguments or identical implementations and only generating code for them once.\n\n### Encapsulation\n\nWith a template, the implementation is part of the interface and types are only\nchecked when the function is called and the template is instantiated.\n\nA checked-generic function is type checked when it is defined, and type checking\ncan't use any information that is only known when the function is instantiated\nsuch as the exact argument types. Furthermore, calls to a checked-generic\nfunction may be type checked using only its declaration, not its body.\n\n### Predictability\n\nA general property of checked generics is they are more predictable than\ntemplates. They make clear when a type satisfies the requirements of a function;\nthey have a documented contract. Further, that contract is enforced by the\ncompiler, not sensitive to implementation details in the function body. This\neases evolution by reducing (but not eliminating) the impact of\n[Hyrum's law](https://www.hyrumslaw.com/).\n\n**Nice to have:** We also want well-defined boundaries between what is legal and\nnot. This is \"will my code be accepted by the compiler\" predictability. We would\nprefer to avoid algorithms in the compiler with the form \"run for up to N steps\nand report an error if it isn't resolved by then.\" For example, C++ compilers\nwill typically have a template recursion limit. With checked generics, these\nproblems arise due to trying to reason whether something is legal in all\npossible instantiations, rather than with specific, concrete types.\n\nSome of this is likely unavoidable or too costly to avoid, as most existing\nchecked generics systems\n[have undecidable aspects to their type system](https://web.archive.org/web/20231223005655/https://3fx.ch/typing-is-hard.html),\nincluding [Rust](https://sdleffler.github.io/RustTypeSystemTuringComplete/) and\nSwift ([1](https://forums.swift.org/t/swift-type-checking-is-undecidable/39024),\n[2](https://forums.swift.org/t/termination-checking-for-type-substitution/64504),\n[3](https://forums.swift.org/t/two-more-undecidable-problems-in-the-swift-type-system/64814),\n[4](https://forums.swift.org/t/brainf-in-the-swift-type-system/68301)). We fully\nexpect there to be metaprogramming facilities in Carbon that will be able to\nexecute arbitrary Turing machines, with infinite loops and undecidable stopping\ncriteria. We don't see this as a problem though, just like we don't worry about\ntrying to make the compiler reliably prevent you from writing programs that\ndon't terminate.\n\nWe _would_ like to distinguish \"the executed steps are present in the program's\nsource\" from \"the compiler has to search for a proof that the code is legal.\" In\nthe former case, the compiler can surface a problem to the user by pointing to\nlines of code in a trace of execution. The user could employ traditional\ndebugging techniques to refine their understanding until they can determine a\nfix. What we want to avoid is the latter case, since it has bad properties:\n\n-   Error messages end up in the form: \"this was too complicated to figure out,\n    I eventually gave up.\"\n-   Little in the way of actionable feedback on how to fix problems.\n-   Not much the user can do to debug problems.\n-   If the compiler is currently right at a limit for figuring something out, it\n    is easy to imagine a change to a distant dependency can cause it to suddenly\n    stop compiling.\n\nIf we can't find acceptable restrictions to make problems efficiently decidable,\nthe next best solution is to require the proof to be in the source instead of\nderived by the compiler. If authoring the proof is too painful for the user, the\nwe should invest in putting the proof search into IDEs or other tooling.\n\n### Dispatch control\n\nEnable simple user control of whether to use dynamic or static dispatch.\n\n**Implementation strategy:** There are two strategies for generating code for\nchecked-generic functions:\n\n-   Static strategy: Like template parameters, the values for checked parameters\n    must be statically known at the callsite, or known to be a compile-time\n    parameter to the calling function. This can generate separate, specialized\n    versions of each combination of checked and template arguments, in order to\n    optimize for those types or values.\n-   Dynamic strategy: This is when the compiler generates a single version of\n    the function that uses runtime dispatch to get something semantically\n    equivalent to separate instantiation, but likely with different size, build\n    time, and performance characteristics.\n\nBy default, we expect the implementation strategy to be controlled by the\ncompiler, and not semantically visible to the user. For example, the compiler\nmight use the static strategy for release builds and the dynamic strategy for\ndevelopment. Or it might choose between them on a more granular level based on\ncode analysis, specific features used in the code, or profiling -- maybe some\nspecific specializations are needed for performance, but others would just be\ncode bloat.\n\nWe require that all checked generic functions can be compiled using the static\nspecialization strategy. For example, the values for checked parameters must be\nstatically known at the callsite. Other limitations are\n[listed below](#implementation-strategy).\n\n**Nice to have:** It is desirable that the majority of functions with checked\nparameters also support the dynamic strategy. Specific features may prevent the\ncompiler from using the dynamic strategy, but they should ideally be relatively\nrare, and easy to identify. Language features should avoid making it observable\nwhether function code generated once or many times. For example, you should not\nbe able to take the address of a function with checked parameters, or determine\nif a function was instantiated more than once using function-local static\nvariables.\n\nThere are a few obstacles to supporting dynamic dispatch efficiently, which may\nlimit the extent it is used automatically by implementations. For example, the\nfollowing features would benefit substantially from guaranteed monomorphization:\n\n-   Field packing in class layout. For example, packing a `bool` into the lower\n    bits of a pointer, or packing bit-fields with checked-parameter widths.\n-   Allocating local variables in stack storage. Without monomorphization, we\n    would need to perform dynamic memory allocation -- whether on the stack or\n    the heap -- for local variables whose sizes depend on checked parameters.\n-   Passing parameters to functions. We cannot pass values of types in\n    registers.\n-   Finding [specialized](terminology.md#specialization) implementations of\n    interfaces beyond those clearly needed from the function signature.\n\nWhile it is possible to address these with dynamic dispatch, handling some of\nthem might have far-reaching and surprising performance implications. We don't\nwant to compromise our goal for predictable performance.\n\nWe will allow the user to explicitly opt-in to using the dynamic strategy in\nspecific cases. This could be just to control binary size in cases the user\nknows are not performance sensitive, or it could be to get the additional\ncapability of operating on values with dynamic types. We may need to restrict\nthis in various ways to maintain efficiency, like Rust does with object-safe\ntraits.\n\nWe also anticipate that the user may want to force the compiler to use the\nstatic strategy in specific cases. This might be to keep runtime performance\nacceptable even when running a development or debug build.\n\n### Upgrade path from templates\n\nWe want there to be a natural, incremental upgrade path from templated code to\nchecked-generic code. The first step of migrating C++ template code would be to\nfirst convert it to a [Carbon template](#templates). The problem is then how to\nconvert templates to checked generics within Carbon. This gives us these\nsub-goals:\n\n-   Users should be able to convert a single template parameter to be checked at\n    a time. A hybrid function with both template and checked parameters has all\n    the limitations of a template function: it can't be completely definition\n    checked, it can't use the dynamic strategy, etc. Even so, there are still\n    benefits from enforcing the function's declared contract for those\n    parameters that have been converted.\n-   Converting from a template parameter to a checked parameter should be safe.\n    It should either work or fail to compile, never silently change semantics.\n-   We should minimize the effort to convert functions and types from templated\n    to checked. Ideally it should just require specifying the type constraints,\n    affecting just the signature of the function, not its body.\n-   **Nice to have:** It should be legal to call templated code from\n    checked-generic code when it would have the same semantics as if called from\n    non-generic code, and an error otherwise. This is to allow more templated\n    functions to be converted to checked generics, instead of requiring them to\n    be converted specifically in bottom-up order.\n-   **Nice to have:** Provide a way to migrate from a template to a checked\n    generic without immediately updating all of the types used with the\n    template. For example, if the checked-generic code requires types to\n    implement a new interface, one possible solution would use the original\n    template code to provide an implementation for that interface for any type\n    that structurally has the methods used by the original template.\n\n### Path from regular functions\n\nReplacing a regular, non-parameterized function with a checked-generic function\nshould not affect existing callers of the function. There may be some\ndifferences, such as when taking the address of the function, but ordinary calls\nshould not see any difference. In particular, the return type of a\nchecked-generic function should match, without any type erasure or additional\nnamed members.\n\n### Coherence\n\nWe want the generics system to have the\n[_coherence_ property](terminology.md#coherence), so that the implementation of\nan interface for a type is well defined. Since a checked-generic function only\ndepends on interface implementations, they will always behave consistently on a\ngiven type, independent of context. For more on this, see\n[this description of what coherence is and why Rust enforces it](https://github.com/Ixrec/rust-orphan-rules#what-is-coherence).\n\nCoherence greatly simplifies the language design, since it reduces the need for\ncomplicated rules to picking an implementation when there are many candidates.\nIt also has a number of benefits for users:\n\n-   It removes a way packages can conflict with each other.\n-   It makes the behavior of code more consistent and predictable.\n-   It means there is no need to provide a disambiguation mechanism.\n    Disambiguation is particularly problematic since the ambiguous call is often\n    in generic code rather than code you control.\n-   A consistent definition of a type is useful for instantiating a C++ or\n    Carbon template on that type.\n\nThe main downside of coherence is that there are some capabilities we would like\nfor interfaces that are in tension with having an orphan rule limiting where\nimplementations may be defined. For example, we would like to address\n[the expression problem](https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions#another-clojure-solution-using-protocols).\nWe can get some of the way there by allowing the implementation of an interface\nfor a type to be defined with either the interface or the type. But some use\ncases remain:\n\n-   They should be some way of selecting between multiple implementations of an\n    interface for a given type. For example, a _Song_ might support multiple\n    orderings, such as by title or by artist. These would be represented by\n    having multiple implementations of a _Ordered_ interface.\n-   In order to allow libraries to be composed, there must be some way of saying\n    a type implements an interface that is in another package that the authors\n    of the type were unaware of. This is especially important since the library\n    a type is defined in may not be able to see the interface definition without\n    creating a dependency cycle or layering violation.\n\nWe should have some mechanism for addressing these use cases. There are multiple\napproaches that could work:\n\n-   Interface implementations could be external to types and are passed in to\n    checked-generic functions separately.\n-   There could be some way to create multiple types that are compatible with a\n    given value that you can switch between using casts to select different\n    interface implementations. This is the approach used by Rust\n    ([1](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-the-newtype-pattern-to-implement-external-traits-on-external-types),\n    [2](https://github.com/Ixrec/rust-orphan-rules#user-content-why-are-the-orphan-rules-controversial)).\n\nAlternatives to coherence are discussed in [an appendix](appendix-coherence.md).\n\n### No novel name lookup\n\nWe want to avoid adding rules for name lookup that are specific to generics.\nThis is in contrast to Rust which has different lookup rules inside its traits.\nInstead, we should structure generics in a way that reuses existing name lookup\nfacilities of the language.\n\n**Nice to have:** One application of this that would be nice to have is if the\nnames of a type's members were all determined by a type's definition. So if `x`\nhas type `T`, then if you write `x.y` you should be able to look up `y` in the\ndefinition of `T`. This might need to be somewhat indirect in some cases. For\nexample, if `T` inherits from `U`, the name `y` might come from `U` and not be\nmentioned in the definition of `T` directly. We may have similar mechanisms\nwhere `T` gets methods that have default implementations in interfaces it\nimplements, as long as the names of those interfaces are explicitly mentioned in\nthe definition of `T`.\n\n### Learn from others\n\nMany languages have implemented checked-generics systems, and we should learn\nfrom those experiences. We should copy what works and makes sense in the context\nof Carbon, and change decisions that led to undesirable compromises. We are\ntaking the strongest guidance from Rust and Swift, which have similar goals and\nsignificant experience with the implementation and usability of checked\ngenerics. They both use nominal interfaces, were designed with checked generics\nfrom the start, and produce native code. Contrast with Go which uses structural\ninterfaces, or Java which targets a virtual machine that predated its generics\nfeature.\n\nFor example, Rust has found that supporting defaults for interface methods is a\nvaluable feature. It is useful for [evolution](#interop-and-evolution),\nimplementation reuse, and for bridging the gap between the minimal functionality\na type wants to implement and the rich API that users want to consume\n([example](https://doc.rust-lang.org/std/iter/trait.Iterator.html)).\n\nWe still have the flexibility to make simplifications that Rust cannot because\nthey need to maintain compatibility. We could remove the concept of\n`fundamental` and explicit control over which methods may be specialized. These\nare complicated and\n[impose coherence restrictions](http://aturon.github.io/tech/2017/02/06/specialization-and-coherence/).\n\n### Interfaces are nominal\n\nInterfaces can either be [structural](terminology.md#structural-interfaces), as\nin Go, or [nominal](terminology.md#nominal-interfaces), as in Rust and Swift.\nStructural interfaces match any type that has the required methods, whereas\nnominal interfaces only match if there is an explicit declaration stating that\nthe interface is implemented for that specific type. Carbon will support nominal\ninterfaces, allowing them to designate _semantics_ beyond the basic structure of\nthe methods.\n\nThis means that interfaces implicitly specify the intended semantics and\ninvariants of and between those functions. Unlike the function signatures, this\ncontract is between the implementers and the consumers of interfaces and is not\nenforced by Carbon itself. For example, a `Draw` method would mean different\nthings when it is part of a `GameResult` interface versus an `Image2D`\ninterface, even if those methods happen to have the same signature.\n\n### Interop and evolution\n\n[Evolution is a high priority for Carbon](/docs/project/goals.md#software-and-language-evolution),\nand so will need mechanisms to support evolution when using checked generics.\nNew additions to an interface might:\n\n-   need default implementations\n-   be marked \"upcoming\" to allow for a period of transition\n-   replace other APIs that need to be marked \"deprecated\"\n\nExperience with C++ concepts has shown that interfaces are\n[hard to evolve](https://www.youtube.com/watch?v=v_yzLe-wnfk) without these\nkinds of supporting language mechanisms. Otherwise changes to interfaces need to\nmade simultaneously with updates to types that implement the interface or\nfunctions that consume it.\n\nAnother way of supporting evolution is to allow one interface to be\nsubstitutable for another. For example, a feature that lets you use an\nimplementation of `Interface1` for a type to automatically get an implementation\nof `Interface2`, as well as the other way around, would help transitioning\nbetween those two interfaces.\n\nEvolution in particular means that the set of names in an interface can change,\nand so two interfaces that don't start with name conflicts can develop them.\n\nTo handle name conflicts, interfaces should be separate, isolated namespaces. We\nshould provide mechanisms to allow one type to implement two interfaces that\naccidentally use the same name for different things, and for functions to use\ninterfaces with name conflicts together on a single type. Contrast this with\nSwift, where a type can only supply one associated type of a given name even\nwhen implementing multiple protocols. Similarly a function in Swift with a given\nname and signature can only have a single implementation for a type.\n\nNote this is possible since [interfaces are nominal](#interfaces-are-nominal).\nThe place where types specify that they implement an interface is also the\nvehicle for unambiguously designating which function implementation goes with\nwhat interface.\n\n### Bridge for C++ customization points\n\nThere will need to be some bridge for C++ extension points that currently rely\non open overloading or\n[ADL](https://en.wikipedia.org/wiki/Argument-dependent_name_lookup). For\nexample, we need some way for C++\n[customization points](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html)\nlike `swap` to work on Carbon types. We might define `CPlusPlus.ADL.swap` as a\nCarbon interface to be that bridge. Carbon types could implement that interface\nto work from C++, and Carbon functions could use that interface to invoke `swap`\non C++ types.\n\nSimilarly, we will want some way to implement Carbon interfaces for C++ types.\nFor example, we might have a template implementation of an `AddWith` interface\nfor any C++ type that implements `operator+`.\n\n## What we are not doing with checked generics\n\nWhat are we **not** doing with checked generics, particularly things that some\nother languages do?\n\n### Not the full flexibility of templates\n\nChecked generics don't need to provide full flexibility of C++ templates:\n\n-   [Carbon templates](#templates) will cover those cases that don't fit inside\n    checked generics, such as code that relies on compile-time duck typing.\n-   We won't allow a specialization of some interface for some particular type\n    to actually expose a _different_ interface, with different methods or\n    different types in method signatures. This would break modular type\n    checking.\n-   [Template metaprogramming](https://en.wikipedia.org/wiki/Template_metaprogramming)\n    will not be supported by Carbon checked generics. We expect to address those\n    use cases with metaprogramming or [templates](#templates) in Carbon.\n-   [Expression templates](https://en.wikipedia.org/wiki/Expression_templates)\n    are out of scope. It may be possible to express this approach in Carbon's\n    checked-generics system, but they won't drive any accommodation in the\n    checked-generics design.\n\n### Checked generics will be checked when defined\n\nC++ compilers must defer full type checking of templates until they are\ninstantiated by the user. Carbon will not defer type checking of checked-generic\ndefinitions.\n\n### Implementation strategy\n\nWe want all generic Carbon code to support [static dispatch](#dispatch-control).\nThis means we won't support unbounded type families. Unbounded type families are\nwhen recursion creates an infinite collection of types, such as in\n[this example from Swift](https://forums.swift.org/t/ergonomics-generic-types-conforming-in-more-than-one-way/34589/71)\nor:\n\n```carbon\nfn Sort[T:! Ordered](list: List(T)) -> List(T) {\n  if (list.size() == 1) return list;\n  var chunks: List(List(T)) = FormChunks(list, sqrt(list.size()));\n  chunks = chunks.ApplyToEach(Sort);\n  chunks = Sort(chunks);\n  return MergeSortedListOfSortedLists(chunks);\n}\n```\n\nThis, given an implementation of `Ordered` for any list with elements that are\nthemselves `Ordered`, would recursively call itself to produce a set of types\nwithout bound. That is, calling `Sort` on a `List(Int)` would internally call\n`Sort` on a `List(List(Int))` and so on recursively without any static limit.\n\nWe won't require all checked-generic Carbon code to support dynamic dispatch,\nbut we would like it to be an implementation option for the compiler in the\nmajority of cases.\n\nLastly, runtime specialization is out of scope as an implementation strategy.\nThat is, some language runtimes JIT a specialization when it is first needed,\nbut it is not a goal for Carbon to support such an implementation strategy.\n\n## References\n\nProposals:\n\n-   [#24: Generics goals](https://github.com/carbon-language/carbon-lang/pull/24)\n-   [#950: Generic details 6: remove facets](https://github.com/carbon-language/carbon-lang/pull/950)\n-   [#2138: Checked and template generic terminology](https://github.com/carbon-language/carbon-lang/pull/2138)\n"
  },
  {
    "path": "docs/design/generics/overview.md",
    "content": "# Generics: Overview\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis document is a high-level description of Carbon's generics design, with\npointers to other design documents that dive deeper into individual topics.\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Goals](#goals)\n-   [Summary](#summary)\n-   [What are generics?](#what-are-generics)\n    -   [Interfaces](#interfaces)\n        -   [Defining interfaces](#defining-interfaces)\n        -   [Contrast with templates](#contrast-with-templates)\n    -   [Implementing interfaces](#implementing-interfaces)\n        -   [Accessing members of interfaces](#accessing-members-of-interfaces)\n    -   [Facet types](#facet-types)\n    -   [Generic functions](#generic-functions)\n        -   [Deduced parameters](#deduced-parameters)\n        -   [Facet parameters](#facet-parameters)\n    -   [Requiring or extending another interface](#requiring-or-extending-another-interface)\n    -   [Combining interfaces](#combining-interfaces)\n        -   [Named constraints](#named-constraints)\n        -   [Type erasure](#type-erasure)\n    -   [Adapting types](#adapting-types)\n    -   [Interface inputs and outputs](#interface-inputs-and-outputs)\n        -   [Associated constants](#associated-constants)\n        -   [Parameterized interfaces](#parameterized-interfaces)\n    -   [Constraints](#constraints)\n    -   [Parameterized impl declarations](#parameterized-impl-declarations)\n    -   [Operator overloading](#operator-overloading)\n-   [Future work](#future-work)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Goals\n\nCarbon [generics](terminology.md#generic-means-compile-time-parameterized)\nsupports generalizing code to apply to more situations by adding compile-time\nparameters, allowing\n[generic programming](https://en.wikipedia.org/wiki/Generic_programming). Carbon\nsupports both\n[checked and template](terminology.md#checked-versus-template-parameters)\ngenerics.\n\nTemplate generics provide a similar model to C++ templates, to help with interop\nand migration. They can be more convenient to write, and support some use cases,\nlike [metaprogramming](https://en.wikipedia.org/wiki/Metaprogramming), that are\ndifficult with checked generics.\n\nChecked generics are an alternative that has advantages including:\n\n-   Function calls and bodies are checked independently against the function\n    signatures.\n-   Clearer and earlier error messages.\n-   Fast builds, particularly development builds.\n-   Support for both static and dynamic dispatch.\n\nChecked generics do have some restrictions, but are expected to be more\nappropriate at public API boundaries than templates.\n\nFor more detail, see [the detailed discussion of generics goals](goals.md) and\n[generics terminology](terminology.md).\n\n## Summary\n\nSummary of how Carbon generics work:\n\n-   _Generics_ are compile-time parameterized functions, types, and other\n    language constructs. Those parameters allow a single definition to apply\n    more generally. They are used to avoid writing specialized, near-duplicate\n    code for similar situations.\n-   The definition of a _checked_ generic is typechecked once, without having to\n    know the specific argument values of the generic parameters it is\n    instantiated with. Typechecking the definition of a checked generic requires\n    a precise contract specifying the requirements on the argument values.\n-   For parameters that will be used as types, those requirements are written\n    using _interfaces_. Interfaces have a name and describe methods, functions,\n    and other entities for types to implement.\n-   Types must explicitly _implement_ interfaces to indicate that they support\n    their functionality. A given type may implement an interface at most once.\n-   Implementations may be declared inline in the body of a class definition or\n    out-of-line.\n-   Types may _extend_ an implementation declared inline, in which case you can\n    directly call the interface's methods on those types.\n-   Out-of-line implementations may be defined in the library defining the\n    interface as an alternative to the type, or\n    [the library defining a type argument](#parameterized-impl-declarations).\n-   Interfaces may be used as the type of a generic parameter. Interfaces are\n    _facet types_, whose values are the subset of all types that implement the\n    interface. Facet types in general specify the capabilities and requirements\n    of the type. The value of a interface is called a _facet_. Facets are not\n    types, but are usable as types.\n-   With a template generic, the concrete argument value used by the caller is\n    used for name lookup and typechecking. With checked generics, that is all\n    done with the declared restrictions expressed as the types of bindings in\n    the declaration. Inside the body of a checked generic with a facet\n    parameter, the API of the facet is just the names defined by the facet type.\n-   _Deduced parameters_ are parameters whose values are determined by the types\n    of the explicit arguments. Generic facet parameters are typically deduced.\n-   A function with a generic parameter can have the same function body as an\n    unparameterized one. Functions can freely mix checked, template, and regular\n    parameters.\n-   Interfaces can require other interfaces be implemented.\n-   Interfaces can [extend](terminology.md#extending-an-interface) required\n    interfaces.\n-   The `&` operation on facet types allows you conveniently combine interfaces.\n    It gives you all the names that don't conflict.\n-   You may also declare a new facet type directly using\n    [\"named constraints\"](terminology.md#named-constraints). Named constraints\n    can express requirements that multiple interfaces be implemented, and give\n    you control over how name conflicts are handled.\n-   Alternatively, you may resolve name conflicts by using a qualified member\n    access expression to directly call a function from a specific interface\n    using a qualified name.\n\n## What are generics?\n\nGenerics are a mechanism for writing parameterized code that applies generally\ninstead of making near-duplicates for very similar situations, much like C++\ntemplates. For example, instead of having one function per type-you-can-sort:\n\n```\nfn SortInt32Vector(a: Vector(i32)*) { ... }\nfn SortStringVector(a: Vector(String)*) { ... }\n...\n```\n\nYou might have one generic function that could sort any array with comparable\nelements:\n\n```\nfn SortVector(T:! Comparable, a: Vector(T)*) { ... }\n```\n\nThe syntax above adds a `!` to indicate that the parameter named `T` is\ncompile-time. By default compile-time parameters are _checked_, the `template`\nkeyword may be added to make it a _template generic_.\n\nGiven an `i32` vector `iv`, `SortVector(i32, &iv)` is equivalent to\n`SortInt32Vector(&iv)`. Similarly for a `String` vector `sv`,\n`SortVector(String, &sv)` is equivalent to `SortStringVector(&sv)`. Thus, we can\nsort any vector containing comparable elements using this single `SortVector`\nfunction.\n\nThis ability to generalize makes `SortVector` a _generic_.\n\n### Interfaces\n\nThe `SortVector` function requires a definition of `Comparable`, with the goal\nthat the compiler can perform checking. This has two pieces:\n\n-   definition checking: completely type check a checked-generic definition\n    without information from calls;\n-   encapsulation: completely type check a call to a generic with information\n    only from the function's signature, and not from its body. For Rust, this is\n    called\n    \"[Rust's Golden Rule](https://steveklabnik.com/writing/rusts-golden-rule).\"\n\nIn this example, `Comparable` is an _interface_.\n\nInterfaces describe all the requirements needed for the type `T`. Given that the\ncompiler knows `T` satisfies those requirements, it can type check the body of\nthe `SortVector` function. This includes checking that the `Comparable`\nrequirement covers all of the uses of `T` inside the function.\n\nLater, when the compiler comes across a call to `SortVector`, it can type check\nagainst the requirements expressed in the function's signature. Using only the\ntypes at the call site, the compiler can check that the member elements of the\npassed-in array satisfy the function's requirements. There is no need to look at\nthe body of the `SortVector` function, since we separately checked that those\nrequirements were sufficient.\n\n#### Defining interfaces\n\nInterfaces, then, have a name and describe methods, functions, and other\nentities for types to implement.\n\nExample:\n\n```\ninterface Comparable {\n  // `Less` is an associated method.\n  fn Less[self: Self](rhs: Self) -> bool;\n}\n```\n\nFunctions and methods may be given a default implementation by prefixing the\ndeclaration with `default` and putting the function body in curly braces\n`{`...`}` in place of the terminating `;` of the function declaration. To\nprevent that implementation from being overridden, use `final` instead of\n`default`.\n\nInterfaces describe functionality, but not data; no variables may be declared in\nan interface.\n\n#### Contrast with templates\n\nContrast these checked generics with a Carbon or C++ template, where the\ncompiler may be able to do some checking given a function definition, but more\nchecking of the definition is required after seeing the call sites once all the\n[instantiations](terminology.md#instantiation) are known.\n\nNote: [Generics terminology](terminology.md) goes into more detail about the\n[differences between checked and template generic parameters](terminology.md#checked-versus-template-parameters).\n\n### Implementing interfaces\n\nInterfaces themselves only describe functionality by way of method descriptions.\nA type needs to _implement_ an interface to indicate that it supports its\nfunctionality. A given type may implement an interface at most once.\n\nConsider this interface:\n\n```\ninterface Printable {\n  fn Print[self: Self]();\n}\n```\n\nThe `interface` keyword is used to define a\n[_nominal interface_](terminology.md#nominal-interfaces). That means that types\nneed to explicitly implement them, using an `impl` block, such as here:\n\n```\nclass Song {\n  // ...\n\n  // Implementing `Printable` for `Song` inside the definition of `Song`\n  // with the keyword `extend` means all names of `Printable`, such\n  // as `F`, are included as a part of the `Song` API.\n  extend impl as Printable {\n    // Could use `Self` in place of `Song` here.\n    fn Print[self: Song]() { ... }\n  }\n}\n\n// Implement `Comparable` for `Song` without changing the API of `Song`\n// using an `impl` declaration without `extend`. This may be defined in\n// either the library defining `Song` or `Comparable`.\nimpl Song as Comparable {\n  // Could use either `Self` or `Song` here.\n  fn Less[self: Self](rhs: Self) -> bool { ... }\n}\n```\n\nImplementations may be defined within the class definition itself or\nout-of-line. Implementations may optionally start with the `extend` keyword to\nsay the members of the interface are also members of the class, which may only\nbe used in a class scope. Out-of-line implementations may be defined in the\nlibrary defining the class, the interface, or\n[a type argument](#parameterized-impl-declarations).\n\n#### Accessing members of interfaces\n\nMethods from an interface that a class extends may be called with the\n[simple member access syntax](terminology.md#simple-member-access). Methods of\nall implemented interfaces may be called with a\n[qualified member access expression](terminology.md#qualified-member-access-expression),\nwhether the class extends them or not.\n\n```\nvar song: Song;\n// `song.Print()` is allowed, unlike `song.Play()`.\nsong.Print();\n// `Less` is defined in `Comparable`, which `Song`\n// does not extend the implementation of.\nsong.(Comparable.Less)(song);\n// Can also call `Print` using a qualified member\n// access expression, using the compound member access\n// syntax with the qualified name `Printable.Print`:\nsong.(Printable.Print)();\n```\n\n### Facet types\n\nTo type check a function, the compiler needs to be able to verify that uses of a\nvalue match the capabilities of the value's type. In `SortVector`, the parameter\n`T` is a type, but that type is a checked-generic, or _symbolic_, parameter.\nThat means that the specific type value assigned to `T` is not known when type\nchecking the `SortVector` function. Instead it is the constraints on `T` that\nlet the compiler know what operations may be performed on values of type `T`.\nThose constraints are represented by the type of `T`, a\n[**_facet type_**](terminology.md#facet-type).\n\nIn general, a facet type describes the capabilities of a type, while a type\ndefines specific implementations of those capabilities. An interface, like\n`Comparable`, may be used as a facet type. In that case, the constraint on the\ntype is that it must implement the interface `Comparable`.\n\nA facet type also defines a set of names and a mapping to corresponding\nqualified names. Those names are used for\n[simple member lookup](terminology.md#simple-member-access) in scopes where the\nvalue of the type is not known, such as when the type is a generic parameter.\n\nYou may combine interfaces into new facet types using\n[the `&` operator](#combining-interfaces) or\n[named constraints](#named-constraints).\n\n### Generic functions\n\nWe want to be able to call generic functions just like ordinary functions, and\nwrite generic function bodies like ordinary functions. There are only a few\ndifferences, like that you can't take the address of generic functions.\n\n#### Deduced parameters\n\nThis `SortVector` function is explicitly providing type information that is\nalready included in the type of the second argument. To eliminate the argument\nat the call site, use a _deduced parameter_.\n\n```\nfn SortVectorDeduced[T:! Comparable](a: Vector(T)*) { ... }\n```\n\nThe `T` parameter is defined in square brackets before the explicit parameter\nlist in parenthesis to indicate it should be deduced. This means you may call\nthe function without the type argument, just like the ordinary functions\n`SortInt32Vector` or `SortStringVector`:\n\n```\nSortVectorDeduced(&anIntVector);\n// or\nSortVectorDeduced(&aStringVector);\n```\n\nand the compiler deduces that the `T` argument should be set to `i32` or\n`String` from the type of the argument.\n\nDeduced arguments are always determined from the call and its explicit\narguments. There is no syntax for specifying deduced arguments directly at the\ncall site.\n\n```\n// ERROR: can't determine `U` from explicit parameters\nfn Illegal[T:! type, U:! type](x: T) -> U { ... }\n```\n\n#### Facet parameters\n\nA function with a facet parameter can have the same function body as an\nunparameterized one.\n\n```\nfn PrintIt[T:! Printable](p: T*) {\n  p->Print();\n}\n\nfn PrintIt(p: Song*) {\n  p->Print();\n}\n```\n\nInside the function body, you can treat the facet parameter just like any other\ntype. There is no need to refer to or access generic parameters differently\nbecause they are defined as generic, as long as you only refer to the names\ndefined by [facet type](#facet-types) for the facet parameter.\n\nYou may also refer to any of the methods of interfaces required by the facet\ntype using a\n[qualified member access expression](#accessing-members-of-interfaces).\n\nA function can have a mix of checked, template, and regular parameters. Each\nkind of parameter is defined using a different syntax: a checked parameter is\nuses a symbolic binding pattern, a template parameter uses a template binding\npattern, and a regular parameter uses a runtime binding pattern. Likewise, it's\nallowed to pass a symbolic or template constant value to a checked or regular\nparameter. _We have decided to support passing a symbolic constant to a template\nparameter, see\n[leads issue #2153: Checked generics calling templates](https://github.com/carbon-language/carbon-lang/issues/2153),\nbut incorporating it into the design is future work._\n\n### Requiring or extending another interface\n\nInterfaces can require other interfaces be implemented:\n\n```\ninterface Equatable {\n  fn IsEqual[self: Self](rhs: Self) -> bool;\n}\n\n// `Iterable` requires that `Equatable` is implemented.\ninterface Iterable {\n  require Self impls Equatable;\n  fn Advance[ref self: Self]();\n}\n```\n\nThe `extend` keyword is used to [extend](terminology.md#extending-an-interface)\nanother interface. If interface `Derived` extends interface `Base`, `Base`'s\ninterface is both required and all its methods are included in `Derived`'s\ninterface.\n\n```\n// `Hashable` extends `Equatable`.\ninterface Hashable {\n  extend Equatable;\n  fn Hash[self: Self]() -> u64;\n}\n// `Hashable` is equivalent to:\ninterface Hashable {\n  require Self impls Equatable;\n  alias IsEqual = Equatable.IsEqual;\n  fn Hash[self: Self]() -> u64;\n}\n```\n\nA type may implement the base interface implicitly by implementing all the\nmethods in the implementation of the derived interface.\n\n```\nclass Key {\n  // ...\n  extend impl as Hashable {\n    fn IsEqual[self: Key](rhs: Key) -> bool { ... }\n    fn Hash[self: Key]() -> u64 { ... }\n  }\n  // No need to separately implement `Equatable`.\n}\nvar k: Key = ...;\nk.Hash();\nk.IsEqual(k);\n```\n\n### Combining interfaces\n\nThe `&` operation on facet types allows you conveniently combine interfaces. It\ngives you all the names that don't conflict.\n\n```\ninterface Renderable {\n  fn GetCenter[self: Self]() -> (i32, i32);\n  // Draw the object to the screen\n  fn Draw[self: Self]();\n}\ninterface EndOfGame {\n  fn SetWinner[ref self: Self](player: i32);\n  // Indicate the game was a draw\n  fn Draw[ref self: Self]();\n}\n\nfn F[T:! Renderable & EndOfGame](game_state: T*) -> (i32, i32) {\n  game_state->SetWinner(1);\n  return game_state->Center();\n}\n```\n\nNames with conflicts can be accessed using a\n[qualified member access expression](#accessing-members-of-interfaces).\n\n```\nfn BothDraws[T:! Renderable & EndOfGame](game_state: T*) {\n  game_state->(Renderable.Draw)();\n  game_state->(GameState.Draw)();\n}\n```\n\n#### Named constraints\n\nYou may also declare a new facet type directly using\n[\"named constraints\"](terminology.md#named-constraints). Named constraints can\nexpress requirements that multiple interfaces be implemented, and give you\ncontrol over how name conflicts are handled. Named constraints have other\napplications and capabilities not covered here.\n\n```\nconstraint Combined {\n  require Self impls Renderable;\n  require Self impls EndOfGame;\n  alias Draw_Renderable = Renderable.Draw;\n  alias Draw_EndOfGame = EndOfGame.Draw;\n  alias SetWinner = EndOfGame.SetWinner;\n}\n\nfn CallItAll[T:! Combined](game_state: T*, int winner) {\n  if (winner > 0) {\n    game_state->SetWinner(winner);\n  } else {\n    game_state->Draw_EndOfGame();\n  }\n  game_state->Draw_Renderable();\n  // Can still use a qualified member access expression\n  // for names not defined in the named constraint.\n  return game_state->(Renderable.Center)();\n}\n```\n\n#### Type erasure\n\nInside a generic function, the API of a facet argument is\n[erased](terminology.md#type-erasure) except for the names defined in the facet\ntype. An equivalent model is to say an [archetype](terminology.md#archetype) is\nused for type checking and name lookup when the actual type is not known in that\nscope. The archetype has members dictated by the facet type.\n\nFor example: If there were a class `CDCover` defined this way:\n\n```\nclass CDCover  {\n  extend impl as Printable {\n    ...\n  }\n}\n```\n\nit can be passed to this `PrintIt` function:\n\n```\nfn PrintIt[T:! Printable](p: T*) {\n  p->Print();\n}\n```\n\nInside `PrintIt`, `T` is an archetype with the API of `Printable`. A call to\n`PrintIt` with a value of type `CDCover` erases everything except the members or\n`Printable`. This includes the type connection to `CDCover`, so it is illegal to\ncast from `T` to `CDCover`.\n\n### Adapting types\n\nCarbon has a mechanism called [adapting types](terminology.md#adapting-a-type)\nto create new types that are [compatible](terminology.md#compatible-types) with\nexisting types but with different interface implementations. This could be used\nto add or replace implementations, or define implementations for reuse.\n\nIn this example, we have multiple ways of sorting a collection of `Song` values.\n\n```\nclass Song { ... }\n\nclass SongByArtist {\n  extend adapt Song;\n  extend impl as Comparable { ... }\n}\n\nclass SongByTitle {\n  extend adapt Song;\n  extend impl as Comparable { ... }\n}\n```\n\nValues of type `Song` may be cast to `SongByArtist` or `SongByTitle` to get a\nspecific sort order.\n\n### Interface inputs and outputs\n\n[Associated constants and interface parameters](terminology.md#interface-parameters-and-associated-constants)\nallow function signatures to vary with the implementing type. The biggest\ndifference between these is that associated constants (\"outputs\") may be deduced\nfrom a type, and types can implement the same interface multiple times with\ndifferent interface parameters (\"inputs\").\n\n#### Associated constants\n\nExpect parts of function signatures that vary in an interface to be associated\nconstants by default. Since associated constants may be deduced, they are more\nconvenient to use. Imagine a `Stack` interface. Different types implementing\n`Stack` will have different element types:\n\n```\ninterface Stack {\n  let ElementType:! Movable;\n  fn Push[ref self: Self](value: ElementType);\n  fn Pop[ref self: Self]() -> ElementType;\n  fn IsEmpty[ref self: Self]() -> bool;\n}\n```\n\n`ElementType` is an associated constant of the interface `Stack`. Types that\nimplement `Stack` give `ElementType` a specific value that is some type (really,\nfacet) implementing `Movable`. Functions that accept a type implementing `Stack`\ncan deduce the `ElementType` from the stack type.\n\n```\n// ✅ This is allowed, since the type of the stack will determine\n// `ElementType`.\nfn PeekAtTopOfStack[StackType:! Stack](s: StackType*)\n    -> StackType.ElementType;\n```\n\n#### Parameterized interfaces\n\nParameterized interfaces are commonly associated with overloaded operators.\nImagine an interface for determining if two values are equivalent that allows\nthose types to be different. An element in a hash map might have type\n`Pair(String, i64)` that implements both `Equatable(String)` and\n`Equatable(Pair(String, i64))`.\n\n```\ninterface Equatable(T:! type) {\n  fn IsEqual[self: Self](compare_to: T) -> bool;\n}\n```\n\n`T` is a parameter to interface `Equatable`. A type can implement `Equatable`\nmultiple times as long as each time it is with a different value of the `T`\nparameter. Functions may accept types implementing `Equatable(i32)` or\n`Equatable(f32)`. Functions can't accept types implementing `Equatable(T)` in\ngeneral, unless some other parameter determines `T`.\n\n```\n// ✅ This is allowed, since the value of `T` is determined by the\n// `v` parameter.\nfn FindInVector[T:! type, U:! Equatable(T)](v: Vector(T), needle: U)\n    -> Optional(i32);\n\n// ❌ This is forbidden. Since `U` could implement `Equatable`\n// multiple times, there is no way to determine the value for `T`.\n// Contrast with `PeekAtTopOfStack` in the associated constant\n// example.\nfn CompileError[T:! type, U:! Equatable(T)](x: U) -> T;\n```\n\n### Constraints\n\nFacet types can be further constrained using a `where` clause:\n\n```\nfn FindFirstPrime[T:! Container where .Element = i32]\n    (c: T, i: i32) -> Optional(i32) {\n  // The elements of `c` have type `T.Element`, which is `i32`.\n  ...\n}\n\nfn PrintContainer[T:! Container where .Element impls Printable](c: T) {\n  // The type of the elements of `c` is not known, but we do know\n  // that type satisfies the `Printable` interface.\n  ...\n}\n```\n\nConstraints limit the types that the generic function can operate on, but\nincrease the knowledge that may be used in the body of the function to operate\non values of those types.\n\nConstraints are also used when implementing an interface to specify the values\nof associated constants.\n\n```\nclass Vector(T:! Movable) {\n  extend impl as Stack where .ElementType = T { ... }\n}\n```\n\n### Parameterized impl declarations\n\nImplementations can be parameterized to apply to multiple types. Those\nparameters can have constraints to restrict when the implementation applies.\nWhen multiple implementations apply, there is a rule to pick which one is\nconsidered the most specific:\n\n-   All parameters in each `impl` declaration are replaced with question marks\n    `?`. This is called the type structure of the `impl` declaration.\n-   Given two type structures, find the first difference when read from\n    left-to-right. The one with a `?` is less specific, the one with a concrete\n    type name in that position is more specific.\n-   If there is more than one `impl` declaration with the most specific type\n    structure, pick the one listed first in the priority ordering.\n\nTo ensure [coherence](goals.md#coherence), an `impl` may only be declared in a\nlibrary defining some name from its type structure. If a library defines\nmultiple implementations with the same type structure, they must be listed in\npriority order in a prioritization block.\n\n### Operator overloading\n\nTo overload an operator, implement the corresponding interface from the standard\nlibrary. For example, to define how the unary `-` operator behaves for a type,\nimplement the `Negatable` interface for that type. The interfaces and rewrites\nused for a given operator may be found in the\n[expressions design](/docs/design/expressions/README.md).\n\nAs a convenience, there is a shortcut for defining an implementation that\nsupports any type implicitly convertible to a specified type, using `like`:\n\n```\n// Support multiplying values of type `Distance` with\n// values of type `f64` or any type implicitly\n// convertible to `f64`.\nimpl Distance as MultipliableWith(like f64) ...\n```\n\n## Future work\n\n-   Functions should have a way to accept types that vary at runtime.\n-   You should have the ability to mark entities as `upcoming` or `deprecated`\n    to support evolution.\n-   There should be a way to define generic associated and higher-ranked/kinded\n    types.\n\n## References\n\n-   [#524: Generics overview](https://github.com/carbon-language/carbon-lang/pull/524)\n-   [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n-   [#818: Constraints for generics (generics details 3)](https://github.com/carbon-language/carbon-lang/pull/818)\n-   [#920: Generic parameterized impls (details 5)](https://github.com/carbon-language/carbon-lang/pull/920)\n-   [#950: Generic details 6: remove facets](https://github.com/carbon-language/carbon-lang/pull/950)\n-   [#1013: Generics: Set associated constants using `where` constraints](https://github.com/carbon-language/carbon-lang/pull/1013)\n-   [#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084)\n"
  },
  {
    "path": "docs/design/generics/terminology.md",
    "content": "# Generics: Terminology\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Generic means compile-time parameterized](#generic-means-compile-time-parameterized)\n-   [Checked versus template parameters](#checked-versus-template-parameters)\n    -   [Polymorphism](#polymorphism)\n        -   [Parametric polymorphism](#parametric-polymorphism)\n        -   [Compile-time duck typing](#compile-time-duck-typing)\n        -   [Ad-hoc polymorphism](#ad-hoc-polymorphism)\n    -   [Constrained genericity](#constrained-genericity)\n    -   [Dependent names](#dependent-names)\n    -   [Definition checking](#definition-checking)\n        -   [Complete definition checking](#complete-definition-checking)\n        -   [Early versus late type checking](#early-versus-late-type-checking)\n-   [Bindings](#bindings)\n-   [Types and `type`](#types-and-type)\n-   [Facet type](#facet-type)\n-   [Facet](#facet)\n-   [Type expression](#type-expression)\n-   [Facet binding](#facet-binding)\n-   [Deduced parameter](#deduced-parameter)\n-   [Interface](#interface)\n    -   [Structural interfaces](#structural-interfaces)\n    -   [Nominal interfaces](#nominal-interfaces)\n    -   [Named constraints](#named-constraints)\n-   [Associated entity](#associated-entity)\n-   [Impl: Implementation of an interface](#impl-implementation-of-an-interface)\n    -   [Extending an impl](#extending-an-impl)\n-   [Member access](#member-access)\n    -   [Simple member access](#simple-member-access)\n    -   [Qualified member access expression](#qualified-member-access-expression)\n-   [Compatible types](#compatible-types)\n-   [Subtyping and casting](#subtyping-and-casting)\n-   [Coherence](#coherence)\n-   [Adapting a type](#adapting-a-type)\n-   [Type erasure](#type-erasure)\n-   [Archetype](#archetype)\n-   [Extending an interface](#extending-an-interface)\n-   [Dynamic-dispatch witness table](#dynamic-dispatch-witness-table)\n-   [Instantiation](#instantiation)\n-   [Specialization](#specialization)\n    -   [Template specialization](#template-specialization)\n    -   [Checked-generic specialization](#checked-generic-specialization)\n-   [Conditional conformance](#conditional-conformance)\n-   [Interface parameters and associated constants](#interface-parameters-and-associated-constants)\n-   [Type constraints](#type-constraints)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Generic means compile-time parameterized\n\nGenerally speaking, when we talk about _generics_, either\n[checked or template](#checked-versus-template-parameters), we are talking about\ngeneralizing some language construct by adding a _compile-time parameter_, also\ncalled a _generic parameter_, to it. So:\n\n-   a _generic function_ is a function with at least one compile-time parameter,\n    which could be an explicit argument to the function or\n    [deduced](#deduced-parameter);\n-   a _generic type_ is a type with a compile-time parameter, for example a\n    container type parameterized by the type of the contained elements;\n-   a _generic interface_ is an [interface](#interface) with\n    [a compile-time parameter](#interface-parameters-and-associated-constants).\n\nThis parameter broadens the scope of the language construct on an axis defined\nby that parameter, for example it could define a family of functions instead of\na single one.\n\nNote that different languages allow different things to be parameterized; for\nexample, Rust supports\n[generic associated types](https://rust-lang.github.io/rfcs/1598-generic_associated_types.html).\n\n## Checked versus template parameters\n\nWhen we distinguish between checked and template generics in Carbon, it is on a\nparameter by parameter basis. A single function can take a mix of regular,\nchecked, and template parameters.\n\n-   **Regular parameters**, or \"dynamic parameters\", are designated using the\n    \"\\<name>`:` \\<type>\" syntax (or \"\\<value>\").\n-   **Checked parameters** are designated using `:!` between the name and the\n    type (so it is \"\\<name>`:!` \\<type>\").\n-   **Template parameters** are designated using \"`template` \\<name>`:!`\n    \\<type>\".\n\nThe syntax for checked and template parameters was decided in\n[questions-for-leads issue #565](https://github.com/carbon-language/carbon-lang/issues/565).\n\nExpected difference between checked and template parameters:\n\n<table>\n  <tr>\n   <td><strong>Checked</strong>\n   </td>\n   <td><strong>Template</strong>\n   </td>\n  </tr>\n  <tr>\n   <td>bounded parametric polymorphism\n   </td>\n   <td>compile-time duck typing and ad-hoc polymorphism\n   </td>\n  </tr>\n  <tr>\n   <td>constrained genericity\n   </td>\n   <td>optional constraints\n   </td>\n  </tr>\n  <tr>\n   <td>name lookup resolved for definitions in isolation (\"early\")\n   </td>\n   <td>name lookup can use information from arguments (name lookup may be \"late\")\n   </td>\n  </tr>\n  <tr>\n   <td>sound to typecheck definitions in isolation (\"early\")\n   </td>\n   <td>complete type checking may require information from calls (may be \"late\")\n   </td>\n  </tr>\n  <tr>\n   <td>supports separate type checking; may also support separate compilation\n   </td>\n   <td>separate compilation only to the extent that C++ supports it\n   </td>\n  </tr>\n  <tr>\n   <td>allowed but not required to be implemented using dynamic dispatch\n   </td>\n   <td>does not support implementation by way of dynamic dispatch, just static by way of <a href=\"#instantiation\">instantiation</a>\n   </td>\n  </tr>\n  <tr>\n   <td>monomorphization is an optional optimization that cannot render the program invalid\n   </td>\n   <td>monomorphization is mandatory and can fail, resulting in the program being invalid\n   </td>\n  </tr>\n</table>\n\n### Polymorphism\n\nGenerics provide different forms of\n[polymorphism](<https://en.wikipedia.org/wiki/Polymorphism_(computer_science)>)\nthan object-oriented programming with inheritance. That uses\n[subtype polymorphism](https://en.wikipedia.org/wiki/Subtyping) where different\ndescendants, or \"subtypes\", of a base class can provide different\nimplementations of a method, subject to some compatibility restrictions on the\nsignature.\n\n#### Parametric polymorphism\n\nParametric polymorphism\n([Wikipedia](https://en.wikipedia.org/wiki/Parametric_polymorphism)) is when a\nfunction or a data type can be written generically so that it can handle values\n_identically_ without depending on their type.\n[Bounded parametric polymorphism](https://en.wikipedia.org/wiki/Parametric_polymorphism#Bounded_parametric_polymorphism)\nis where the allowed types are restricted to satisfy some constraints. Within\nthe set of allowed types, different types are treated uniformly.\n\n#### Compile-time duck typing\n\nDuck typing ([Wikipedia](https://en.wikipedia.org/wiki/Duck_typing)) is when the\nlegal types for arguments are determined implicitly by the usage of the values\nof those types in the body of the function. Compile-time duck typing is when the\nusages in the body of the function are checked at compile-time, along all code\npaths. Contrast this with ordinary duck typing in a dynamic language such as\nPython where type errors are only diagnosed at runtime when a usage is reached\ndynamically.\n\n#### Ad-hoc polymorphism\n\nAd-hoc polymorphism\n([Wikipedia](https://en.wikipedia.org/wiki/Ad_hoc_polymorphism)), also known as\n\"overloading\", is when a single function name has multiple implementations for\nhandling different argument types. There is no enforcement of any consistency\nbetween the implementations. For example, the return type of each overload can\nbe arbitrary, rather than being the result of some consistent rule being applied\nto the argument types.\n\nTemplates work with ad-hoc polymorphism in two ways:\n\n-   A function with template parameters can be\n    [specialized](#template-specialization) in\n    [C++](https://en.cppreference.com/w/cpp/language/template_specialization) as\n    a form of ad-hoc polymorphism.\n-   A function with template parameters can call overloaded functions since it\n    will only resolve that call after the types are known.\n\nIn Carbon, we expect there to be a compile error if overloading of some name\nprevents a checked-generic function from being typechecked from its definition\nalone. For example, let's say we have some overloaded function called `F` that\nhas two overloads:\n\n```\nfn F[template T:! type](x: T*) -> T;\nfn F(x: Int) -> bool;\n```\n\nA checked generic function `G` can call `F` with a type like `T*` that cannot\npossibly call the `F(Int)` overload for `F`, and so it can consistently\ndetermine the return type of `F`. But `G` can't call `F` with an argument that\ncould match either overload.\n\n**Note:** It is undecided what to do in the situation where `F` is overloaded,\nbut the signatures are consistent and so callers could still typecheck calls to\n`F`. This still poses problems for the dynamic strategy for compiling generics,\nin a similar way to impl specialization.\n\n### Constrained genericity\n\nWe will allow some way of specifying constraints as part of a function (or type\nor other parameterized language construct). These constraints are a limit on\nwhat callers are allowed to pass in. The distinction between constrained and\nunconstrained genericity is whether the body of the function is limited to just\nthose operations that are guaranteed by the constraints.\n\nWith templates using unconstrained genericity, you may perform any operation in\nthe body of the function, and they will be checked against the specific types\nused in calls. You can still have constraints, but they are optional in that\nthey could be removed and the function would still have the same capabilities.\nConstraints only affect the caller, which will use them to resolve overloaded\ncalls to the template and provide clearer error messages.\n\nWith checked generics using constrained genericity, the function body can be\nchecked against the signature at the time of definition. Note that it is still\nperfectly permissible to have no constraints on a type; that just means that you\ncan only perform operations that work for all types (such as manipulate pointers\nto values of that type) in the body of the function.\n\n### Dependent names\n\nA name is said to be _dependent_ if it depends on some checked or template\nparameter. Note: this matches\n[the use of the term \"dependent\" in C++](https://www.google.com/search?q=c%2B%2B+dependent+name),\nnot as in [dependent types](https://en.wikipedia.org/wiki/Dependent_type).\n\n### Definition checking\n\nDefinition checking is the process of semantically checking the definition of\nparameterized code for correctness _independently_ of any particular argument\nvalues. It includes type checking and other semantic checks. It is possible,\neven with templates, to check semantics of expressions that are not\n[dependent](#dependent-names) on any template parameter in the definition.\nAdding constraints to template parameters and/or switching them to be checked\nallows the compiler to increase how much of the definition can be checked. Any\nremaining checks are delayed until [instantiation](#instantiation), which can\nfail.\n\n#### Complete definition checking\n\nComplete definition checking is when the definition can be _fully_ semantically\nchecked, including type checking. It is an especially useful property because it\nenables _separate_ semantic checking of the definition, a prerequisite to\nseparate compilation. It also is a requirement for implementation strategies\nthat don’t instantiate the implementation (for example,\n[type erasure](#type-erasure) or\n[dynamic-dispatch witness tables](#dynamic-dispatch-witness-table)).\n\n#### Early versus late type checking\n\nEarly type checking is where expressions and statements are type checked when\nthe definition of the function body is compiled, as part of definition checking.\nThis occurs for regular and checked-generic values.\n\nLate type checking is where expressions and statements may only be fully\ntypechecked once calling information is known. Late type checking delays\ncomplete definition checking. This occurs for\n[template-dependent](#dependent-names) values.\n\n## Bindings\n\n_Binding patterns_ associate a name with a type and a value. This is used to\ndeclare function parameters, in `let` and `var` declarations, as well as to\ndeclare [compile-time parameters](#generic-means-compile-time-parameterized) for\nclasses, interfaces, and so on. There are three kinds of binding patterns,\ncorresponding to\n[the three expression phases](/docs/design/README.md#expression-phases):\n\n-   A _runtime binding pattern_ binds to a dynamic value at runtime, and is\n    written using a `:`, as in `x: i32`.\n-   A _symbolic binding pattern_ binds to a compile-time value that is not known\n    when type checking, and is used to declare\n    [checked generic](#checked-versus-template-parameters) parameters. These\n    binding use `:!`, as in `T:! type`.\n-   A _template binding pattern_ binds to a compile-time value that is known\n    when type checking, and is used to declare\n    [template](#checked-versus-template-parameters) parameters. These bindings\n    use the keyword `template` in addition to `:!`, as in `template T:! type`.\n\nThe last two binding patterns, which are about binding a compile-time value, are\ncalled _compile-time binding patterns_, and correspond to those binding patterns\nthat use `:!`.\n\nThe name being declared, which is the identifier to the left of the `:` or `:!`,\nis called a _binding_, or more specifically a _runtime binding_, _compile-time\nbinding_, _symbolic binding_, or _template binding_. The expression to the right\ndefining the type of the binding pattern is called the _binding type\nexpression_, a kind of [type expression](#type-expression). For example, in\n`T:! Hashable`, `T` is the binding (a symbolic binding in this case), and\n`Hashable` is the binding type expression.\n\n## Types and `type`\n\nA _type_ is a value of type `type`. Conversely, `type` is the type of all types.\n\nExpressions in type position, for example a [binding type expression](#bindings)\nor the return type of a function, are implicitly cast to type `type`. This means\nthat it is legal to put a value that is not a type where a type is expected, as\nlong as it has an implicit conversion to `type` that may be performed at compile\ntime.\n\n## Facet type\n\nA _facet type_ is a [type](#types-and-type) whose values are some subset of the\nvalues of `type`, determined by a set of [type constraints](#type-constraints):\n\n-   [Interfaces](#interface) and [named constraints](#named-constraints) are\n    facet types whose constraints are that the interface or named constraint is\n    satisfied by the type.\n-   The values produced by `&` operations between facet types and by `where`\n    expressions are facet types, whose set of constraints are determined by the\n    `&` or `where` expression.\n-   `type` is a facet type whose set of constraints is empty.\n\nA facet type is the type used when declaring some type parameter. It foremost\ndetermines which types are legal arguments for that type parameter. For template\nparameters, that is all a facet type does. For checked parameters, it also\ndetermines the API that is available in the body of the definition of the\n[generic function, class, or other entity](#generic-means-compile-time-parameterized).\n\n## Facet\n\nA _facet_ is a value of a [facet type](#facet-type). For example,\n`i32 as Hashable` is a facet, and `Hashable` is a facet type. Note that all\ntypes are facets, since [`type`](#types-and-type) is considered a facet type.\nNot all facets are types, though: `i32 as Hashable` is of type `Hashable` not\n`type`, so it is a facet that is not a type. However, in places where a type is\nexpected, for example in a [binding type expression](#bindings) or after the\n`->` in a function declaration, there is an automatic implicit conversion to\n`type`. This means that a facet may be used in those positions. For example, the\nfacet `i32 as Hashable` will implicitly convert to `(i32 as Hashable) as type`,\nwhich is `i32`, in those contexts.\n\n## Type expression\n\nA _type expression_ is an expression that can be used as a type. In some cases,\nwhat is written in the source code is a value, like a [facet](#facet) or tuple\nof types, that is not a type but has an implicit conversion to `type`. In those\ncases, we are concerned with the type value after the implicit conversion.\n\n## Facet binding\n\nWe use the term _facet binding_ to refer to the name introduced by a\n[compile-time binding pattern](#bindings) (using `:!` with or without the\n`template` modifier) where the declared type is a [facet type](#facet-type). In\nthe binding pattern `T:! Hashable`, `T` is a facet binding, and the value of `T`\nis a [facet](#facet).\n\n## Deduced parameter\n\nA deduced parameter is listed in the optional `[` `]` section right after the\nfunction name in a function signature:\n\n`fn` \\<name> `[` \\<deduced parameters> `](` \\<explicit parameters> `) ->`\n\\<return type>\n\nDeduced arguments are determined as a result of pattern matching the explicit\nargument values (usually the types of those values) to the explicit parameters.\n\nSee more [here](overview.md#deduced-parameters).\n\n## Interface\n\nAn interface is an API constraint used in a function signature to provide\nencapsulation. Encapsulation here means that callers of the function only need\nto know about the interface requirements to call the function, not anything\nabout the implementation of the function body, and the compiler can check the\nfunction body without knowing anything more about the caller. Callers of the\nfunction provide a value that has an implementation of the API and the body of\nthe function may then use that API. In the case of a checked generic, the\nfunction may _only_ use that API.\n\n### Structural interfaces\n\nA \"structural\" interface is one where we say a type satisfies the interface as\nlong as it has members with a specific list of names, and for each name it must\nhave some type or signature. A type can satisfy a structural interface without\never naming that interface, just by virtue of having members with the right\nform.\n\n### Nominal interfaces\n\nA \"nominal\" interface is one where we say a type can only satisfy an interface\nif there is some explicit statement saying so, for example by defining an\n[impl](#impl-implementation-of-an-interface). This allows \"satisfies the\ninterface\" to have additional semantic meaning beyond what is directly checkable\nby the compiler. For example, knowing whether the `Draw` function means \"render\nan image to the screen\" or \"take a card from the top of a deck of cards\"; or\nthat a `+` operator is commutative (and not, say, string concatenation).\n\nWe use the \"structural\" versus \"nominal\" terminology as a generalization of the\nsame terms being used in a\n[subtyping context](https://en.wikipedia.org/wiki/Subtyping#Subtyping_schemes).\n\n### Named constraints\n\nNamed constraints are \"structural\" in the sense that they match a type based on\nmeeting some criteria rather than an explicit statement in the type's\ndefinition. The criteria for a named constraint, however, are less focused on\nthe type's API and instead might include a set of nominal interfaces that the\ntype must implement and constraints on the\n[associated entities](#associated-entity) and\n[interface parameters](#interface-parameters-and-associated-constants).\n\n## Associated entity\n\nAn _associated entity_ is a requirement in an interface that a type's\nimplementation of the interface must satisfy by having a matching definition. A\nrequirement that the type define a value for a member constant is called an\n_associated constant_. If the type of the associated constant is a\n[facet type](#facet-type), then it is called an _associated [facet](#facet)_,\nwhich corresponds to what is called an \"associated type\" in other languages\n([Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/generics/#Associated-Types),\n[Rust](https://doc.rust-lang.org/reference/items/associated-items.html#associated-types)).\nSimilarly, an interface can have _associated function_, _associated method_, or\n_associated class function_.\n\nDifferent types can satisfy an interface with different definitions for a given\nmember. These definitions are _associated_ with what type is implementing the\ninterface. An [impl](#impl-implementation-of-an-interface) defines what is\nassociated with the type for that interface.\n\nRust uses the term\n[\"associated item\"](https://doc.rust-lang.org/reference/items/associated-items.html)\ninstead of associated entity.\n\n## Impl: Implementation of an interface\n\nAn _impl_ is an implementation of an interface for a specific type, called the\n_implementing type_. It is the place where the function bodies are defined,\nvalues for associated constants, etc. are given. Implementations are needed for\n[nominal interfaces](#nominal-interfaces);\n[structural interfaces](#structural-interfaces) and\n[named constraints](#named-constraints) define conformance implicitly instead of\nby requiring an impl to be defined. In can still make sense to explicitly\nimplement a named constraint as a way to implement all of the interfaces it\nrequires.\n\n### Extending an impl\n\nA type that _extends_ the implementation of an interface has all the named\nmembers of the interface as named members of the type. This means that the\nmembers of the interface are available by way of both\n[simple member access and qualified member access expressions](#member-access).\n\nIf a type implements an interface without extending, the members of the\ninterface may only be accessed using\n[qualified member access expressions](#qualified-member-access-expression).\n\n## Member access\n\nThere are two different kinds of member access: _simple_ and _compound_. See the\n[member access design document](/docs/design/expressions/member_access.md) for\nthe details. The application to generics combines compound member access with\nqualified names, which we call a _qualified member access expression_.\n\n### Simple member access\n\nSimple member access has the from `object.member`, where `member` is a word\nnaming a member of `object`. This form may be used to access members of\ninterfaces when the type of `object`\n[extends the implementation](#extending-an-impl) of that interface.\n\nIf `String` extends its implementation of `Printable`, then `s1.Print()` calls\nthe `Print` method of `Printable` using simple member access. In this case, the\nname `Print` is used without qualifying it with the name of the interface it is\na member of since it is recognized as a member of the type itself as well.\n\n### Qualified member access expression\n\nCompound member access has the form `object.(expression)`, where `expression` is\nresolved in the containing scope. A compound member access where the member\nexpression is a simple member access expression, as in `a.(context.b)`, is\ncalled a _qualified member access expression_. The member expression `context.b`\nmay be the _qualified member name_ of an interface member, that consists of the\nname of the interface, possibly qualified with a package or namespace name, a\ndot `.` and the name of the member.\n\nFor example, if the `Comparable` interface has a `Less` member method, then the\nqualified name of that member is `Comparable.Less`. So if `String` implements\n`Comparable`, and `s1` and `s2` are variables of type `String`, then the `Less`\nmethod may be called using the qualified member name by writing the qualified\nmember access expression `s1.(Comparable.Less)(s2)`.\n\nThis form may be used to access any member of an interface implemented for a\ntype, whether or not it [extends the implementation](#extending-an-impl).\n\n## Compatible types\n\nTwo types are compatible if they have the same notional set of values and\nrepresent those values in the same way, even if they expose different APIs. The\nrepresentation of a type describes how the values of that type are represented\nas a sequence of bits in memory. The set of values of a type includes properties\nthat the compiler can't directly see, such as invariants that the type\nmaintains.\n\nWe can't just say two types are compatible based on structural reasons. Instead,\nwe have specific constructs that create compatible types from existing types in\nways that encourage preserving the programmer's intended semantics and\ninvariants, such as implementing the API of the new type by calling (public)\nmethods of the original API, instead of accessing any private implementation\ndetails.\n\n## Subtyping and casting\n\nBoth subtyping and casting are different names for changing the type of a value\nto a compatible type.\n\n[Subtyping](https://en.wikipedia.org/wiki/Subtyping) is a relationship between\ntwo types where you can safely operate on a value of one type using a variable\nof another. For example, using C++'s object-oriented features, you can operate\non a value of a derived class using a pointer to the base class. In most cases,\nyou can pass a more specific type to a function that can handle a more general\ntype. Return types work the opposite way, a function can return a more specific\ntype to a caller prepared to handle a more general type. This determines how\nfunction signatures can change from base class to derived class, see\n[covariance and contravariance in Wikipedia](<https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)>).\n\nIn a generics context, we are specifically interested in the subtyping\nrelationships between [facet types](#facet-type). In particular, a facet type\nencompasses a set of [type constraints](#type-constraints), and you can convert\na type from a more-restrictive facet type to another facet type whose\nconstraints are implied by the first. C++ concepts terminology uses the term\n[\"subsumes\"](https://en.cppreference.com/w/cpp/language/constraints#Partial_ordering_of_constraints)\nto talk about this partial ordering of constraints, but we avoid that term since\nit is at odds with the use of the term in\n[object-oriented subtyping terminology](https://en.wikipedia.org/wiki/Subtyping#Subsumption).\n\nNote that subtyping is a bit like\n[coercion](https://en.wikipedia.org/wiki/Type_conversion), except we want to\nmake it clear that the data representation of the value is not changing, just\nits type as reflected in the API available to manipulate the value.\n\nCasting is indicated explicitly by way of some syntax in the source code. You\nmight use a cast to switch between [type adaptations](#adapting-a-type), or to\nbe explicit where an implicit conversion would otherwise occur. For now, we are\nsaying \"`x as y`\" is the provisional syntax in Carbon for casting the value `x`\nto the type `y`. Note that outside of generics, the term \"casting\" includes any\nexplicit type change, including those that change the data representation.\n\nIn contexts where an expression of one type is provided and a different type is\nrequired, an [implicit conversion](../expressions/implicit_conversions.md) is\nperformed if it is considered safe to do so. Such an implicit conversion, if\npermitted, always has the same meaning as an explicit cast.\n\n## Coherence\n\nA generics or interface system has the _implementation coherence_ property, or\nsimply _coherence_, if there is a single answer to the question \"what is the\nimplementation of this interface for this type, if any?\" independent of context,\nsuch as the libraries imported into a given file. Coherence is\n[a goal of Carbon checked generics](goals.md#coherence).\n\nThis is enforced using two kinds of rules:\n\n-   An _orphan rule_ is a restriction on which files may declare a particular\n    implementation. This is to ensure that the implementation is imported any\n    time it could be used. For example, if neither the type nor the interface is\n    parameterized, the orphan rule requires that the implementation must be in\n    the same library as the interface or type. The rule is we don't allow an\n    _orphan_ implementation that is not with either of its parents (parent type\n    or parent interface).\n-   An _overlap rule_ is a way to _consistently_ select a single implementation\n    when multiple implementations apply. In Carbon, overlap is resolved by\n    picking a single implementation using a rule that picks the one that is\n    considered most specialized. In Rust, by contrast, the\n    [overlap rule or overlap check](https://rust-lang.github.io/chalk/book/clauses/coherence.html#chalk-overlap-check)\n    instead produces an error if two implementations apply at once.\n\nThe rationale for Carbon choosing coherence and alternatives considered may be\nfound in [this appendix](appendix-coherence.md)\n\n## Adapting a type\n\nA type can be adapted by creating a new type that is\n[compatible](#compatible-types) with an existing type, but has a different API.\nIn particular, the new type might implement different interfaces or provide\ndifferent implementations of the same interfaces.\n\nUnlike extending a type (as with C++ class inheritance), you are not allowed to\nadd new data fields onto the end of the representation -- you may only change\nthe API. This means that it is safe to [cast](#subtyping-and-casting) a value\nbetween those two types without any dynamic checks or danger of\n[object slicing](https://en.wikipedia.org/wiki/Object_slicing).\n\nThis is called \"newtype\" in Rust, and is used for capturing additional\ninformation in types to improve type safety by moving some checking to compile\ntime ([1](https://doc.rust-lang.org/rust-by-example/generics/new_types.html),\n[2](https://doc.rust-lang.org/book/ch19-04-advanced-types.html#using-the-newtype-pattern-for-type-safety-and-abstraction),\n[3](https://www.worthe-it.co.za/blog/2020-10-31-newtype-pattern-in-rust.html))\nand as a workaround for\n[Rust's orphan rules for coherence](https://github.com/Ixrec/rust-orphan-rules#why-are-the-orphan-rules-controversial).\n\n## Type erasure\n\n\"Type erasure\" is where a type's API is replaced by a subset. Everything outside\nof the preserved subset is said to have been \"erased\". This can happen in a\nvariety of contexts including both checked generics and runtime polymorphism.\nFor checked generics, type erasure restricts a type to just the API required by\nthe constraints on that type stated in the signature of the function.\n\nAn example of type erasure in runtime polymorphism in C++ is casting from a\npointer of a derived type to a pointer to an abstract base type. Only the API of\nthe base type is available on the result, even though the implementation of\nthose methods still come from the derived type.\n\nThe term \"type erasure\" can also refer to\n[the specific strategy used by Java to implement generics](https://en.wikipedia.org/wiki/Generics_in_Java).\nwhich includes erasing the identity of type parameters. This is not the meaning\nof \"type erasure\" used in Carbon.\n\n## Archetype\n\nA placeholder type is used when type checking a function in place of a generic\ntype parameter. This allows type checking when the specific type to be used is\nnot known at type-checking time. The type satisfies just its constraint and no\nmore, so it acts as the most general type satisfying the interface. In this way\nthe archetype is the supertype of all types satisfying the interface.\n\nIn addition to satisfying all the requirements of its constraint, the archetype\nalso has the member names of its constraint. Effectively it is considered to\n[extend the implementation of the constraint](#extending-an-impl).\n\n## Extending an interface\n\nAn interface can be extended by defining an interface that includes the full API\nof another interface, plus some additional API. Types implementing the extended\ninterface should automatically be considered to have implemented the narrower\ninterface.\n\n## Dynamic-dispatch witness table\n\nDynamic-dispatch\n[witness tables](https://forums.swift.org/t/where-does-the-term-witness-table-come-from/54334/4)\nare an implementation strategy that uses a table accessed at runtime to allow\nbehavior of a function to vary. This allows a function to work with any type\nimplementing a facet type (such as an interface). For example, the witness table\nmight contain pointers to the implementations of the functions of the interface.\nThis can be done to reduce the size of generated code, at the expense of\nadditional indirection at runtime.\n\nIt can also allow a function to dynamically dispatch when the runtime type of a\nvalue is not known. This is the implementation strategy for\n[boxed protocol types in Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/opaquetypes/#Boxed-Protocol-Types)\nand\n[trait objects in Rust](https://doc.rust-lang.org/book/ch17-02-trait-objects.html).\nNote that this often comes with limitations, since for example it is much more\ndifficult to support when the associated constants of the interface are not\nknown.\n\nTypically a reference to the witness table will be passed separately from the\nobject, unlike a\n[virtual method table](https://en.wikipedia.org/wiki/Virtual_method_table),\nwhich otherwise is very similar to a witness table, \"witnessing\" the specific\ndescendant of a base class.\n\nCarbon's approach to using witness tables is detailed in an\n[appendix](appendix-witness.md).\n\n## Instantiation\n\nInstantiation is the implementation strategy for templates in both C++ and\nCarbon. Instantiation explicitly creates a copy of the template code and\nreplaces the template components with the concrete type and its implementation\noperations. It allows duck typing and lazy binding. Instantiation implies\ntemplate code **will** be duplicated.\n\nUnlike static-dispatch witness tables (as in Swift) and\n[monomorphization (as in Rust)](https://doc.rust-lang.org/book/ch10-01-syntax.html#performance-of-code-using-generics),\nthis is done **before** type checking completes. Only when the template is used\nwith a concrete type is the template fully type checked, and it type checks\nagainst the actual concrete type after substituting it into the template. This\nmeans that different instantiations may interpret the same construct in\ndifferent ways, and that templates can include constructs that are not valid for\nsome possible instantiations. However, it also means that some errors in the\ntemplate implementation may not produce errors until the instantiation occurs,\nand other errors may only happen for **some** instantiations.\n\n## Specialization\n\n### Template specialization\n\nSpecialization in C++ is essentially overloading, or\n[ad-hoc polymorphism](#ad-hoc-polymorphism), in the context of a template. The\ntemplate is overloaded to have a different definition for some subset of the\npossible template argument values. For example, the C++ type `std::vector<T>`\nmight have a specialization `std::vector<T*>` that is implemented in terms of\n`std::vector<void*>` to reduce code size. In C++, even the interface of a\ntemplated type can be changed in a specialization, as happens for\n`std::vector<bool>`.\n\n### Checked-generic specialization\n\nSpecialization of checked generics, or types used by checked generics, is\nrestricted to changing the implementation _without_ affecting the interface.\nThis restriction is needed to preserve the ability to perform type checking of\ngeneric definitions that reference a type that can be specialized, without\nstatically knowing which specialization will be used.\n\n## Conditional conformance\n\nConditional conformance is when you have a parameterized type that has one API\nthat it always supports, but satisfies additional interfaces under some\nconditions on the type argument. For example: `Array(T)` might implement\n`Comparable` if `T` itself implements `Comparable`, using lexicographical order.\n\n## Interface parameters and associated constants\n\n_Interface parameters_ and [associated constants](#associated-entity) are both\nways of allowing the types in function signatures in an interface to vary. For\nexample, different\n[stacks](<https://en.wikipedia.org/wiki/Stack_(abstract_data_type)>) will have\ndifferent element types. That element type would be used as the parameter type\nof the `Push` function and the return type of the `Pop` function. As\n[in Rust](https://rust-lang.github.io/rfcs/0195-associated-items.html#clearer-trait-matching),\nwe can distinguish these by whether they are input parameters or output\nparameters:\n\n-   An interface parameter is a parameter or input to the interface. That means\n    they must be specified before an implementation of the interface may be\n    determined.\n-   In contrast, associated constants are outputs. This means that they are\n    determined by the implementation, and need not be specified in a\n    [type constraint](#type-constraints).\n\nFunctions using an interface as a constraint need not specify the value of its\nassociated constants.\n\n```\n// Stack using associated facets\ninterface Stack {\n  let ElementType:! type;\n  fn Push[ref self: Self](value: ElementType);\n  fn Pop[ref self: Self]() -> ElementType;\n}\n\n// Works on any type implementing `Stack`. Return type\n// is determined by the type's implementation of `Stack`.\nfn PeekAtTopOfStack[T:! Stack](s: T*) -> T.ElementType {\n  let ret: T.ElementType = s->Pop();\n  s->Push(ret);\n  return ret;\n}\n\nclass Fruit;\nclass FruitStack {\n  // Implement `Stack` for `FruitStack`\n  // with `ElementType` set to `Fruit`.\n  extend impl as Stack where .ElementType == Fruit { ... }\n}\n```\n\nAssociated constants are particularly called for when the implementation of the\ninterface determines the value, not the caller. For example, the iterator type\nfor a container is specific to the container and not something you would expect\na user of the interface to specify.\n\nIf you have an interface with parameters, a type can have multiple matching\n`impl` declarations for different combinations of argument values. As a result,\ninterface parameters may not be deduced in a function call. However, if the\ninterface parameters are specified, a type can only have a single implementation\nof the given interface. This unique implementation choice determines the values\nof associated constants.\n\nFor example, we might have an interface that says how to perform addition with\nanother type:\n\n```\ninterface AddWith(T:! type) {\n  let ResultType:! type;\n  fn Add[self: Self](rhs: T) -> ResultType;\n}\n```\n\nAn `i32` value might support addition with `i32`, `u16`, and `f64` values.\n\n```\nimpl i32 as AddWith(i32) where .ResultType = i32 { ... }\nimpl i32 as AddWith(u16) where .ResultType = i32 { ... }\nimpl i32 as AddWith(f64) where .ResultType = f64 { ... }\n```\n\nTo write a generic function requiring a parameter to be `AddWith`, there needs\nto be some way to determine the type to add to:\n\n```\n// ✅ This is allowed, since the value of `T` is determined by the\n// `y` parameter.\nfn DoAdd[T:! type, U:! AddWith(T)](x: U, y: T) -> U.ResultType {\n  return x.Add(y);\n}\n\n// ❌ This is forbidden, can't uniquely determine `T`.\nfn CompileError[T:! type, U:! AddWith(T)](x: U) -> T;\n```\n\nOnce the interface parameters can be determined, that determines the values for\nassociated constants, such as `ResultType` in the example. As always, calls with\ntypes for which no implementation exists will be rejected at the call site:\n\n```\n// ❌ This is forbidden, no implementation of `AddWith(Orange)`\n// for `Apple`.\nDoAdd(apple, orange);\n```\n\nThe type of an interface parameters and associated constants is commonly a\n[facet type](#facet-type), but not always. For example, an interface parameter\nthat specifies an array bound might have an integer type.\n\n## Type constraints\n\nType constraints restrict which types are legal for a\n[facet binding](#facet-binding), like a facet parameter or associated facet.\nThey help define semantics under which they should be called, and prevent\nincorrect calls.\n\nIn general there are a number of different type relationships we would like to\nexpress, for example:\n\n-   This function accepts two containers. The container types may be different,\n    but the element types need to match.\n-   For this container interface we have associated facets for iterators and\n    elements. The iterator type's element type needs to match the container's\n    element type.\n-   An interface may define an associated facet that needs to be constrained to\n    implement some interfaces.\n-   This type must be [compatible](#compatible-types) with another type. You\n    might use this to define alternate implementations of a single interfaces,\n    such as sorting order, for a single type.\n\nNote that type constraints can be a restriction on one facet parameter or\nassociated facet, or can define a relationship between multiple facets.\n\n## References\n\n-   [#447: Generics terminology](https://github.com/carbon-language/carbon-lang/pull/447)\n-   [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n-   [#950: Generic details 6: remove facets](https://github.com/carbon-language/carbon-lang/pull/950)\n-   [#1013: Generics: Set associated constants using where constraints](https://github.com/carbon-language/carbon-lang/pull/1013)\n-   [#2138: Checked and template generic terminology](https://github.com/carbon-language/carbon-lang/pull/2138)\n-   [#2360: Types are values of type `type`](https://github.com/carbon-language/carbon-lang/pull/2360)\n-   [#2760: Consistent `class` and `interface` syntax](https://github.com/carbon-language/carbon-lang/pull/2760)\n"
  },
  {
    "path": "docs/design/interoperability/README.md",
    "content": "# Bidirectional interoperability with C and C++\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Philosophy and goals](#philosophy-and-goals)\n-   [Overview](#overview)\n-   [C++ interoperability model: introduction and principles](#c-interoperability-model-introduction-and-principles)\n    -   [The successor language mandate](#the-successor-language-mandate)\n    -   [The C++ interop type](#the-c-interop-type)\n-   [Importing C++ APIs into Carbon](#importing-c-apis-into-carbon)\n    -   [Importing C++ libraries (header-based)](#importing-c-libraries-header-based)\n    -   [TODO: Importing C++ code (inline)](#todo-importing-c-code-inline)\n    -   [Accessing built-in C++ entities (file-less)](#accessing-built-in-c-entities-file-less)\n    -   [The `Cpp` package](#the-cpp-package)\n    -   [TODO: Importing C++ macros](#todo-importing-c-macros)\n-   [Calling C++ code from Carbon](#calling-c-code-from-carbon)\n    -   [Function call syntax and semantics](#function-call-syntax-and-semantics)\n    -   [TODO: Overload resolution](#todo-overload-resolution)\n    -   [TODO: Constructors](#todo-constructors)\n    -   [TODO: Struct literals](#todo-struct-literals)\n-   [TODO: Accessing C++ classes, structs, and members](#todo-accessing-c-classes-structs-and-members)\n-   [TODO: Accessing global variables](#todo-accessing-global-variables)\n-   [TODO: Bi-directional type mapping: primitives and core types](#todo-bi-directional-type-mapping-primitives-and-core-types)\n-   [TODO: Advanced type mapping: pointers, references, and `const`](#todo-advanced-type-mapping-pointers-references-and-const)\n-   [TODO: Bi-directional type mapping: standard library types](#todo-bi-directional-type-mapping-standard-library-types)\n-   [TODO: The operator interoperability model](#todo-the-operator-interoperability-model)\n\n<!-- tocstop -->\n\n## Philosophy and goals\n\nThe C++ interoperability layer of Carbon allows a subset of C++ APIs to be\naccessed from Carbon code, and similarly a subset of Carbon APIs to be accessed\nfrom C++ code. This requires expressing one language as a subset of the other.\nBridge code may be needed to map some APIs into the relevant subset, but the\nconstraints on expressivity should be loose enough to keep the amount of such\nbridge code sustainable.\n\nThe [interoperability philosophy and goals](philosophy_and_goals.md) provide\nmore detail.\n\n## Overview\n\nCarbon's bidirectional interoperability with C++ is\n[a cornerstone of its design](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code),\nenabling a gradual transition from existing C++ codebases. The goal is not just\na foreign function interface (FFI), but a seamless, high-fidelity integration\nthat supports advanced C++ features, from templates to class hierarchies.\n\nC++ APIs are imported into Carbon using an `import Cpp` directive, which makes\nC++ declarations available within a dedicated `Cpp` package in Carbon. This\nprevents name collisions and makes the origin of symbols explicit. Carbon code\ncan then call C++ functions, instantiate C++ classes, and use C++ types, while\nrespecting C++'s semantics, including its complex overload resolution rules and\npreserving the nominal distinctions between C++ types like `long` and\n`long long`, or `T*` and `T&`, which is critical for correct overload resolution\nand template instantiation.\n\nSimilarly, Carbon APIs can be designed to be callable from C++. The\ninteroperability layer is designed to be zero-cost, avoiding unnecessary\nallocations or copies when calling between the two languages.\n\n## C++ interoperability model: introduction and principles\n\n### The successor language mandate\n\nThe design of Carbon's C++ interoperability is governed by its foundational\ngoal: [to be a successor language](/README.md), not merely a language with a\nforeign function interface (FFI). This mandate dictates a design that moves\nbeyond the C-style FFI adopted by most modern languages and instead provides\nseamless, bidirectional interoperability. The objective is to support deep\nintegration with existing C++ code, encompassing its most complex features, from\ninheritance to templates.\n\nThis goal has profound implications for the Carbon compiler and language\nsemantics. It requires that C++ is not treated as a foreign entity. Instead,\nCarbon's semantic model must be _co-designed_ to understand, map, and interact\nwith C++'s semantic constructs—including templates, class hierarchies, and\ncomplex overload resolution—with high fidelity. The interoperability layer must,\ntherefore, operate at the semantic analysis level, not just at the linking (ABI)\nlevel. This document specifies the design of this semantic contract.\n\n### The C++ interop type\n\nA core mechanism in this design is the C++ interop type. This concept defines\nthe \"trigger\" that activates C++-specific semantic rules within the Carbon\ncompiler. Any operation involving a type that is designated as a C++ interop\ntype could invoke the specialized interoperability logic, such as C++ overload\nresolution or operator overload resolution that involves both Carbon and C++\noperator overloads.\n\nA type is considered a C++ interop type if its definition involves an imported\nC++ type in any of the following ways:\n\n1.  A C++ imported type (for example, `Cpp.Widget`).\n2.  A pointer to a C++ interop type (for example, `Cpp.Widget*`).\n3.  A Carbon generic type parameterized with a C++ interop type (for example,\n    `MyCarbonVector(Cpp.Widget)`).\n\nMore generally, a C++ interop type is any type for which Carbon's\n[orphan rule](https://docs.carbon-lang.dev/docs/design/generics/details.html#orphan-rule)\nwould allow an impl to be provided by a library in `package Cpp`.\n\nThis \"pervasive\" model of C++-awareness is a fundamental design choice. The C++\nsemantics are not confined to a specific `unsafe` or `extern \"C++\"` block; they\naffect any Carbon type that composes them. For example, when the Carbon compiler\ninstantiates a _Carbon_ generic type like `MyCarbonVector(Cpp.Widget)`, its type\nsystem must be aware that the `Cpp.Widget` parameter carries C++-specific rules.\nThis mandates that Carbon's own generic system, struct layout logic, overload\nresolution and operator lookup must query the type system for the presence of a\nC++ interop type. If present, Carbon must consider C++ rules when operating over\nC++ interop types. This design prioritizes the goal of a seamless and intuitive\nuser experience.\n\n## Importing C++ APIs into Carbon\n\n### Importing C++ libraries (header-based)\n\nThe primary mechanism for importing existing, user-defined C++ code is through\nheader file inclusion. Carbon must be able to parse and analyze C++ header files\nto make their declarations available within Carbon.\n\n**Syntax:** The syntax for this operation is `import Cpp library \"header_name\"`.\nThis syntax is used for both standard library headers and user-defined headers:\n\n-   **Standard Library:**\n\n    ```carbon\n    import Cpp library \"<cstdio>\";\n    ```\n\n    This import makes entities like `putchar` available.\n\n-   **C++ User-Defined Header:**\n    ```carbon\n    import Cpp library \"circle.h\";\n    ```\n    This import makes user-defined declarations and definitions available.\n\n### TODO: Importing C++ code (inline)\n\n### Accessing built-in C++ entities (file-less)\n\nSome C++ entities, particularly built-in primitive types, are not defined in any\nheader file. They are \"intrinsic\" to the C++ language. These entities are\navailable in Carbon without an explicit `import` declaration.\n\n### The `Cpp` package\n\nA critical design choice for managing C++ imports is the mandatory use of a\ncontaining package, `Cpp`. All imported C++ named entities (functions, types,\nnamespaces) are contained in the `Cpp` package.\n\n-   **Functions:** `Cpp.putchar(...)`\n-   **Classes/Types:** `Cpp.Circle`, `Cpp.Point`\n-   **Constructors:** `Cpp.Circle.Circle()`\n\nThe `Cpp.` prefix makes the _origin_ of every symbol explicit and unambiguous.\nIt ensures that C++ entities cannot collide with Carbon code.\n\n### TODO: Importing C++ macros\n\n## Calling C++ code from Carbon\n\n### Function call syntax and semantics\n\nOnce imported, C++ functions are invoked using standard Carbon function call\nsyntax, prefixed with the `Cpp` name. The Carbon compiler is responsible for\nmapping the Carbon arguments to the types expected by the C++ function's\nsignature.\n\nThis often requires explicit casting on the Carbon side, using the `as` keyword,\nto satisfy the C++ function's parameter types.\n\n**Example:** The following example imports `cstdio` and calls the C function\n`putchar`. The Carbon `Core.Char` variable `n` must be cast first to `u8` and\nthen to `i32` to match the `int` parameter expected by `putchar`.\n\n```carbon\nimport Cpp library \"<cstdio>\";\n\nfn Run() {\n  let hello: array(Core.Char, 6) = ('H', 'e', 'l', 'l', 'o', '!');\n  for (n: Core.Char in hello) {\n    // Carbon 'as' casting is used to match the C++ signature\n    Cpp.putchar((n as u8) as i32);\n  }\n}\n```\n\n### TODO: Overload resolution\n\n### TODO: Constructors\n\n### TODO: Struct literals\n\n## TODO: Accessing C++ classes, structs, and members\n\n## TODO: Accessing global variables\n\n## TODO: Bi-directional type mapping: primitives and core types\n\n## TODO: Advanced type mapping: pointers, references, and `const`\n\n## TODO: Bi-directional type mapping: standard library types\n\n## TODO: The operator interoperability model\n"
  },
  {
    "path": "docs/design/interoperability/philosophy_and_goals.md",
    "content": "# Interoperability philosophy and goals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n    -   [Other interoperability layers](#other-interoperability-layers)\n-   [Philosophy](#philosophy)\n-   [Language goal influences](#language-goal-influences)\n    -   [Performance-critical software](#performance-critical-software)\n    -   [Software and language evolution](#software-and-language-evolution)\n    -   [Code that is easy to read, understand, and write](#code-that-is-easy-to-read-understand-and-write)\n    -   [Practical safety guarantees and testing mechanisms](#practical-safety-guarantees-and-testing-mechanisms)\n    -   [Fast and scalable development](#fast-and-scalable-development)\n    -   [Modern OS platforms, hardware architectures, and environments](#modern-os-platforms-hardware-architectures-and-environments)\n    -   [Interoperability with and migration from existing C++ code](#interoperability-with-and-migration-from-existing-c-code)\n-   [Goals](#goals)\n    -   [Support mixing Carbon and C++ toolchains](#support-mixing-carbon-and-c-toolchains)\n    -   [Compatibility with the C++ memory model](#compatibility-with-the-c-memory-model)\n    -   [Minimize bridge code](#minimize-bridge-code)\n    -   [Unsurprising mappings between C++ and Carbon types](#unsurprising-mappings-between-c-and-carbon-types)\n    -   [Allow C++ bridge code in Carbon files](#allow-c-bridge-code-in-carbon-files)\n    -   [Carbon inheritance from C++ types](#carbon-inheritance-from-c-types)\n    -   [Support use of advanced C++ features](#support-use-of-advanced-c-features)\n    -   [Support basic C interoperability](#support-basic-c-interoperability)\n-   [Non-goals](#non-goals)\n    -   [Full parity between a Carbon-only toolchain and mixing C++/Carbon toolchains](#full-parity-between-a-carbon-only-toolchain-and-mixing-ccarbon-toolchains)\n    -   [Never require bridge code](#never-require-bridge-code)\n    -   [Convert all C++ types to Carbon types](#convert-all-c-types-to-carbon-types)\n    -   [Support for C++ exceptions without bridge code](#support-for-c-exceptions-without-bridge-code)\n    -   [Cross-language metaprogramming](#cross-language-metaprogramming)\n    -   [Offer equivalent support for languages other than C++](#offer-equivalent-support-for-languages-other-than-c)\n-   [Open questions to be resolved later](#open-questions-to-be-resolved-later)\n    -   [Carbon type inheritance from non-pure interface C++ types](#carbon-type-inheritance-from-non-pure-interface-c-types)\n    -   [CRTP support](#crtp-support)\n    -   [Object lifetimes](#object-lifetimes)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Background\n\nInteroperability with and migration from C++ are a\n[language goal](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\nHowever, performance and evolution are\n[_higher_ priorities](/docs/project/goals.md#language-goals-and-priorities).\nThis interaction of priorities is important to understanding Carbon's\ninteroperability goals and trade-offs.\n\n### Other interoperability layers\n\nOther language interoperability layers that may offer useful examples are:\n\n-   [Java/Kotlin](https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html)\n    should be a comparable interoperability story. The languages are different,\n    but share an underlying runtime. This may be closest to the model we desire\n    for Carbon.\n\n-   [JavaScript/TypeScript](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html)\n    is similar to C/C++, where one language is essentially a subset of the\n    other, allowing high interoperability. This is an interesting reference\n    point, but we are looking at a different approach with a clearer boundary.\n\n-   [C++/Java](https://en.wikipedia.org/wiki/Java_Native_Interface) is an\n    example of requiring specialized code for the bridge layer, making\n    interoperability more burden on developers. The burden of the approach may\n    be considered to correspond to the difference in language memory models and\n    other language design choices. Regardless, the result can be considered\n    higher maintenance for developers than we want for Carbon.\n\n-   [C++/Go](https://golang.org/cmd/cgo/) is similar to C++/Java. However, Go\n    notably allows C++ bridge code to exist in the .go files, which can ease\n    maintenance of the bridge layer, and is desirable for Carbon.\n\n## Philosophy\n\nThe C++ interoperability layer of Carbon allows a subset of C++ APIs to be\naccessed from Carbon code, and similarly a subset of Carbon APIs to be accessed\nfrom C++ code. This requires expressing one language as a subset of the other.\nBridge code may be needed to map some APIs into the relevant subset, but the\nconstraints on expressivity should be loose enough to keep the amount of such\nbridge code sustainable.\n\nThe design for interoperability between Carbon and C++ hinges on:\n\n1.  The ability to interoperate with a wide variety of code, such as\n    classes/structs and templates, not just free functions.\n2.  A willingness to expose the idioms of C++ into Carbon code, and the other\n    way around, when necessary to maximize performance of the interoperability\n    layer.\n3.  The use of wrappers and generic programming, including templates, to\n    minimize or eliminate runtime overhead.\n\nThese things come together when looking at how custom data structures in C++ are\nexposed into Carbon, and the other way around. In both languages, it is\nreasonable and even common to have customized low-level data structures, such as\nassociative containers. For example, there are numerous data structures for\nmapping from a key to a value that might be best for a particular use case,\nincluding hash tables, linked hash tables, sorted vectors, and btrees. Even for\na given data structure, there may be slow but meaningful evolution in\nimplementations strategies.\n\nThe result is that it will often be reasonable to directly expose a C++ data\nstructure to Carbon without converting it to a \"native\" or \"idiomatic\" Carbon\ndata structure. Although interfaces may differ, a trivial adapter wrapper should\nbe sufficient. Many Carbon data structures should also be able to support\nmultiple implementations with C++ data structures being one such implementation,\nallowing for idiomatic use of C++ hidden behind Carbon.\n\nThe reverse is also true. C++ code will often not care, or can be refactored to\nnot care, what specific data structure is used. Carbon data structures can be\nexposed as yet another implementation in C++, and wrapped to match C++ idioms\nand even templates.\n\nFor example, a C++ class template like `std::vector<T>` should be usable without\nwrapper code or runtime overhead, and passing a Carbon type as `T`. The\nresulting type should be equally usable from either C++ or Carbon code. It\nshould also be easy to wrap `std::vector<T>` with a Carbon interface for\ntransparent use in idiomatic Carbon code.\n\n## Language goal influences\n\n### Performance-critical software\n\nInteroperability with C++ will be frequently used in Carbon, whether it's C++\ndevelopers trying out Carbon, incrementally migrating a large C++ codebase, or\ncontinuing to use a C++ library long-term. In all cases, it must be possible to\nwrite interoperable code with zero overhead; copies must not be required.\n\n### Software and language evolution\n\nInteroperability will require the addition of features to Carbon which exist\nprimarily to support interoperability use cases. However, these features must\nnot unduly impinge the overall evolution of Carbon. In particular, only a subset\nof Carbon features will support interoperability with C++. To do otherwise would\nrestrict Carbon's feature set.\n\n### Code that is easy to read, understand, and write\n\nInteroperability-related Carbon code will likely be more difficult to read than\nother, more idiomatic Carbon code. This is okay: aiming to make Carbon code\nreadable doesn't mean that it needs to _all_ be trivial to read. At the same\ntime, the extra costs that interoperability exerts on Carbon developers should\nbe minimized.\n\n### Practical safety guarantees and testing mechanisms\n\nSafety is important to maintain around interoperability code, and mitigations\nshould be provided where possible. However, safety guarantees will be focused on\nnative Carbon code. C++ code will not benefit from the same set of safety\nmechanisms that Carbon offers, so Carbon code calling into C++ will accept\nhigher safety risks.\n\n### Fast and scalable development\n\nThe interoperability layer will likely have tooling limitations similar to C++.\nFor example, Carbon aims to compile quickly. However, C++ interoperability\nhinges on compiling C++ code, which is relatively slow. Carbon libraries that\nuse interoperability will see bottlenecks from C++ compile time. Improving C++\nis outside the scope of Carbon.\n\n### Modern OS platforms, hardware architectures, and environments\n\nInteroperability will apply to the intersection of environments supported by\nboth Carbon and C++. Pragmatically, Carbon will likely be the limiting factor\nhere.\n\n### Interoperability with and migration from existing C++ code\n\nCarbon's language goal for interoperability will focus on C++17 compatibility.\nThe language design must be mindful of the prioritization; trade-offs harming\nother goals may still be made so long as they offer greater benefits for\ninteroperability and Carbon as a whole.\n\nAlthough the below interoperability-specific goals will focus on\ninteroperability, it's also important to consider how migration would be\naffected. If interoperability requires complex work, particularly to avoid\nperformance impacts, it could impair the ability to incrementally migrate C++\ncodebases to Carbon.\n\n## Goals\n\n### Support mixing Carbon and C++ toolchains\n\nThe Carbon toolchain will support compiling C++ code. It will contain a\ncustomized C++ compiler that enables some more advanced interoperability\nfeatures, such as calling Carbon templates from C++.\n\nMixing toolchains will also be supported in both directions:\n\n-   C++ libraries compiled by a non-Carbon toolchain will be usable from Carbon,\n    so long as they are ABI-compatible with Carbon's C++ toolchain.\n\n-   The Carbon toolchain will support, as an option, generating a C++ header and\n    object file from a Carbon library, with an ABI that's suitable for use with\n    non-Carbon toolchains.\n\nMixing toolchains restricts functionality to what's feasible with the C++ ABI.\nFor example, developers should expect that Carbon templates will be callable\nfrom C++ when using the Carbon toolchain, and will not be available when mixing\ntoolchains because it would require a substantially different and more complex\ninteroperability implementation. This degraded interoperability should still be\nsufficient for most developers, albeit with the potential of more bridge code.\n\nAny C++ interoperability code that works when mixing toolchains must work when\nusing the native Carbon toolchain. The mixed toolchain support must not have\nsemantic divergence. The converse is not true, and the native Carbon toolchain\nmay have additional language support and optimizations.\n\n### Compatibility with the C++ memory model\n\nIt must be straightforward for any Carbon interoperability code to be compatible\nwith the C++ memory model. This does not mean that Carbon must exclusively use\nthe C++ memory model, only that it must be supported.\n\n### Minimize bridge code\n\nThe majority of simple C++ functions and types should be usable from Carbon\nwithout any custom bridge code and without any runtime overhead. That is, Carbon\ncode should be able to call most C++ code without any code changes to add\nsupport for interoperability, even if that code was built with a non-Carbon\ntoolchain. This includes instantiating Carbon templates or generics using C++\ntypes.\n\nIn the other direction, Carbon may need some minimal markup to expose functions\nand types to C++. This should help avoid requiring Carbon to generate\nC++-compatible endpoints unconditionally, which could have compile and linking\noverheads that may in many cases be unnecessary. Also, it should help produce\nerrors that indicate when a function or type may require additional changes to\nmake compatible with C++.\n\nCarbon's priority developers should be able to easily reuse the mature ecosystem\nof C++ libraries provided by third-parties. A third-party library's language\nchoice should not be a barrier to Carbon adoption.\n\nEven for first-party libraries, migration of C++ codebases to Carbon will often\nbe incremental due to human costs of executing and verifying source migrations.\nMinimizing the amount of bridge code required should be expected to simplify\nsuch migrations.\n\n### Unsurprising mappings between C++ and Carbon types\n\nCarbon will provide unsurprising mappings for common types.\n\n**Primitive types** will have mappings with zero overhead conversions. They are\nfrequently used, making it important that interoperability code be able to use\nthem seamlessly.\n\nThe storage and representation will need to be equivalent in both languages. For\nexample, if a C++ `__int64` maps to Carbon's `Int64`, the memory layout of both\ntypes must be identical.\n\nSemantics need to be similar, but edge-case behaviors don't need to be\nidentical, allowing Carbon flexibility to evolve. For example, where C++ would\nhave modulo wrapping on integers, Carbon could instead have trapping behavior on\nthe default-mapped primitive types.\n\nCarbon may have versions of these types with no C++ mapping, such as `Int256`.\n\n**Non-owning vocabulary types**, such as pointers and references, will have\ntransparent, automatic translation between C++ and Carbon non-owning vocabulary\ntypes with zero overhead.\n\n**Other vocabulary types** will typically have reasonable, but potentially\nnon-zero overhead, conversions available to map into Carbon vocabulary types.\nCode using these may choose whether to pay the overhead to convert. They may\nalso use the C++ type directly from Carbon code, and the other way around.\n\n**Incomplete types** must have a mapping with similar semantics, similar to\nprimitive types.\n\n### Allow C++ bridge code in Carbon files\n\nCarbon files should support inline bridge code written in C++. Where bridge code\nis necessary, this will allow for maintenance of it directly alongside the code\nthat uses it.\n\n### Carbon inheritance from C++ types\n\nCarbon will support inheritance from C++ types for interoperability, although\nthe syntax constructs may look different from C++ inheritance. This is\nconsidered necessary to address cases where a C++ library API expects users to\ninherit from a given C++ type.\n\nThis might be restricted to pure interface types; see\n[the open question](#carbon-type-inheritance-from-non-pure-interface-c-types).\n\n### Support use of advanced C++ features\n\nThere should be support for most idiomatic usage of advanced C++ features. A few\nexamples are templates, overload sets,\n[attributes](https://en.cppreference.com/w/cpp/language/attributes) and\n[ADL](https://en.wikipedia.org/wiki/Argument-dependent_name_lookup).\n\nAlthough these features can be considered \"advanced\", their use is widespread\nthroughout C++ code, including STL. Support for such features is key to\nsupporting migration from C++ features.\n\n### Support basic C interoperability\n\nC interoperability support must be sufficient for Carbon code to call popular\nAPIs that are written in C. The ability of C to call Carbon will be more\nrestricted, limited to where it echoes C++ interoperability support. Basic C\ninteroperability will include functions, primitive types, and structs that only\ncontain member variables.\n\nFeatures where interoperability will rely on more advanced C++-specific\nfeatures, such as templates, inheritance, and class functions, need not be\nsupported for C. These would require a C-specific interoperability model that\nwill not be included.\n\n## Non-goals\n\n### Full parity between a Carbon-only toolchain and mixing C++/Carbon toolchains\n\nMaking mixed C++/Carbon toolchain support equivalent to Carbon-only toolchain\nsupport affects all interoperability features. Mixed toolchains will have\ndegraded support because full parity would be too expensive.\n\nThe feature of calling Carbon templates from C++ code is key when analyzing this\noption. Template instantiation during compilation is pervasive in C++.\n\nWith a Carbon toolchain compiling both Carbon and C++ code, the C++ compiler\n_can_ be modified to handle Carbon templates differently. Carbon templates can\nbe handled by exposing the Carbon compiler's AST to the C++ compiler directly,\nas a compiler extension. While this approach is still complex and may not always\nwork, it should offer substantial value and ability to migrate C++ code to\nCarbon without requiring parallel maintenance of implementations in C++.\n\nWith a mixed toolchain, the C++ compiler _cannot_ be modified to handle Carbon\ntemplates differently. The only way to support template instantiation would be\nby having Carbon templates converted into equivalent C++ templates in C++\nheaders; in other words, template support would require source-to-source\ntranslation. Supporting Carbon to C++ code translations would be a complex and\nhigh cost feature to achieve full parity for mixed toolchains. Requiring bridge\ncode for mixed toolchains is the likely solution to avoid this cost.\n\nNote that this issue differs when considering interoperability for Carbon code\ninstantiating C++ templates. The C++ templates must be in C++ headers for reuse,\nwhich in turn must compile with the Carbon toolchain to reuse the built C++\ncode, regardless of whether a separate C++ toolchain is in use. This may also be\nconsidered a constraint on mixed toolchain interoperability, but it's simpler to\naddress and less likely to burden developers.\n\nTo summarize, developers should expect that while _most_ features will work\nequivalently for mixed toolchains, there will never be full parity.\n\n### Never require bridge code\n\nCorner cases of C++ will not receive equal support to common cases: the\ncomplexity of supporting any given construct must be balanced by the real world\nneed for that support. For example:\n\n-   Long-term, we expect interoperability will target all of C++, including new\n    features as they are added, standardized, implemented, and adopted across\n    the industry. The priority of _individual_ features will reflect how widely\n    they are used in practice and how any gap impacts users trying to adopt\n    Carbon. Exhaustive, high-quality support of the long-tail or corner cases of\n    C++ features should not be assumed.\n\n-   Support will be focused on idiomatic code, interfaces, and patterns used in\n    widespread open source libraries or by other key constituencies. C++ code\n    will have edge cases where the benefits of limiting Carbon's maintenance\n    costs by avoiding complex interoperability outweighs the value of avoiding\n    bridge code.\n\n-   Support for low-level C ABIs may be focused on modern 64-bit ABIs, including\n    Linux, POSIX, and a small subset of Windows' calling conventions.\n\n### Convert all C++ types to Carbon types\n\nNon-zero overhead conversions should only be _supported_, never _required_, in\norder to offer reliable, unsurprising performance behaviors. This does not mean\nthat conversions will _always_ be supported, as support is a cost-benefit\ndecision for specific type mappings. For example, consider conversions between\n`std::vector<T>` and an equivalent, idiomatic Carbon type:\n\n-   Making conversions zero-overhead would require the Carbon type to mirror the\n    memory layout and implementation semantics of `std::vector<T>`. However,\n    doing so would constrain the evolution of the Carbon type to match C++.\n    Although some constraints are accepted for most primitive types, it would\n    pose a major burden on Carbon's evolution to constrain Carbon's types to\n    match C++ vocabulary type implementations.\n\n-   These conversions may not always be present, but `std::vector<T>` is a\n    frequently used type. As a result, it can be expected that there will be\n    functions supporting a copy-based conversion to the idiomatic Carbon type.\n\n-   An interface which can hide the difference between whether `std::vector<T>`\n    or the equivalent, idiomatic Carbon type is in use may also be offered for\n    common types.\n\n-   It will still be normal to handle C++ types in Carbon code without\n    conversions. Developers should be given the choice of when to convert.\n\n### Support for C++ exceptions without bridge code\n\nCarbon may not provide seamless interoperability support for C++ exceptions. For\nexample, translating C++ exceptions to or from Carbon errors might require\nannotations or bridge code, and those translations may have some performance\noverhead or lose information. Furthermore, if Carbon code calls a C++ function\nwithout suitable annotations or bridging, and that function exits with an\nexception, the program might terminate.\n\n### Cross-language metaprogramming\n\nCarbon's metaprogramming design will be more restrictive than C++'s preprocessor\nmacros. Although interoperability should handle simple cases, such as\n`#define STDIN_FILENO 0`, complex metaprogramming libraries may require a deep\nability to understand code rewrites. It should be reasonable to have these\ninstead rewritten to use Carbon's metaprogramming model.\n\n### Offer equivalent support for languages other than C++\n\nLong-term, it should be anticipated that Carbon will add interoperability with\nnon-C++ languages. However, interoperability discussions will be focused on C++\nin order to support the\n[language goal](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\nAlthough we should work to consider extensibility when building interoperability\nfacilities, C++ should be expected to have more robust support.\n\nMany languages do offer interoperability layers with C. Carbon's\n[C interoperability](#support-basic-c-interoperability) will likely offer a\ndegree of multi-language interoperability using C as an intermediary.\n\n## Open questions to be resolved later\n\n### Carbon type inheritance from non-pure interface C++ types\n\nSome C++ APIs will expect that consumers use classes that inherit from a type\nprovided by the API. It's desirable to have Carbon support, in some way,\ninheritance from API types in order to use these APIs.\n\nIt may be sufficient to require the parent type be a pure interface, and that\nAPIs with either use bridge code or switch implementations. That will be\ndetermined later.\n\n### CRTP support\n\nAlthough\n[CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) is a\ncommon technique in C++, interoperability support may require substantial work.\nLibraries based on use of CRTP may require bridge code or a rewrite for Carbon\ninteroperability.\n\nMore analysis should be done on the cost-benefit of supporting CRTP before\nmaking a support decision.\n\n### Object lifetimes\n\nCarbon may have a different object lifetime design than C++. For example, Carbon\nmay choose different rules for determining the lifetime of temporaries. This\ncould affect idiomatic use of C++ APIs, turning code that would be safe in C++\ninto unsafe Carbon code, requiring developers to learn new coding patterns.\n\nMore analysis should be done on object lifetimes and potential Carbon designs\nfor it before deciding how to treat object lifetimes in the scope of\ninteroperability.\n\n## References\n\n-   Proposal\n    [#175: C++ interoperability goals](https://github.com/carbon-language/carbon-lang/pull/175)\n"
  },
  {
    "path": "docs/design/lambdas.md",
    "content": "# Lambdas\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Syntax Overview](#syntax-overview)\n    -   [Return type](#return-type)\n        -   [Return expression](#return-expression)\n        -   [Explicit return type](#explicit-return-type)\n        -   [No return](#no-return)\n    -   [Implicit parameters in square brackets](#implicit-parameters-in-square-brackets)\n    -   [Parameters](#parameters)\n    -   [Syntax defined](#syntax-defined)\n-   [Positional parameters](#positional-parameters)\n    -   [Positional parameter restrictions](#positional-parameter-restrictions)\n-   [Captures](#captures)\n    -   [Capture modes](#capture-modes)\n    -   [Default capture mode](#default-capture-mode)\n-   [Function fields in lambdas](#function-fields-in-lambdas)\n-   [Copy semantics](#copy-semantics)\n-   [Self and recursion](#self-and-recursion)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Syntax Overview\n\nOne goal of Carbon's lambda syntax is to have continuity between lambdas and\nfunction declarations. Below are some example declarations:\n\nImplicit return types:\n\n```carbon\n// In a variable:\nlet lambda: auto = fn => T.Make();\n// Equivalent in C++23:\n// const auto lambda = [] { return T::Make(); };\n\n// As an argument to a function call:\nFoo(10, 20, fn => T.Make());\n// Equivalent in C++23:\n// Foo(10, 20, [] { return T::Make(); });\n```\n\nExplicit return types:\n\n```carbon\n// In a variable:\nlet lambda: auto = fn -> T { return T.Make(); };\n// Equivalent in C++23:\n// const auto lambda = [] -> T { return T::Make(); };\n\n// As an argument to a function call:\nPushBack(my_list, fn -> T { return T.Make() });\n// Equivalent in C++23:\n// PushBack(my_list, [] { return T::Make(); });\n```\n\n### Return type\n\nThere are three options for how a lambda expresses its return type, parallel to\n[how function declarations express returns](functions.md#return-clause): using a\nreturn expression, using an explicit return type, or having no return.\n\n#### Return expression\n\nA return expression is introduced with a double arrow (`=>`) followed by an\nexpression describing the function's return value. In this case, the return type\nis determined by the type of the expression, as if the return type was `auto`.\n\n```carbon\n// In a variable:\nlet lambda: auto = fn => T.Make();\n// Equivalent in C++23:\n// const auto lambda = [] { return T::Make(); };\n\n// As an argument to a function call:\nFoo(fn => T.Make());\n// Equivalent in C++23:\n// Foo([] { return T::Make(); });\n```\n\n#### Explicit return type\n\nAn explicit return type is introduced with a single arrow (`->`), followed by\nthe return type, and finally the body of the lambda with a sequence of\nstatements enclosed in curly braces (`{`...`}`).\n\n```carbon\n// In a variable:\nlet lambda: auto = fn -> T { return T.Make(); };\n// Equivalent in C++23:\n// const auto lambda = [] -> T { return T::Make(); };\n\n// As an argument to a function call:\nFoo(fn -> T { return T.Make(); });\n// Equivalent in C++23:\n// Foo([] -> T { return T::Make(); });\n```\n\n#### No return\n\nLambdas that don't return anything end with a body of statements in curly braces\n(`{`...`}`).\n\n```carbon\n// In a variable:\nlet lambda: auto = fn { Print(T.Make()); };\n// Equivalent in C++23:\n// const auto lambda = [] -> void { Print(T::Make()); };\n\n// As an argument to a function call:\nFoo(fn { Print(T.Make()); });\n// Equivalent in C++23:\n// Foo([] -> void { Print(T::Make()); });\n```\n\n### Implicit parameters in square brackets\n\nLambdas support [captures](#captures), [fields](#function-fields-in-lambdas) and\ndeduced parameters in the square brackets.\n\n```carbon\nfn Foo(x: i32) {\n  // In a variable:\n  let lambda: auto = fn [var x, var y: i32 = 0] { Print(++x, ++y); };\n  // Equivalent in C++23:\n  // const auto lambda = [x, y = int32_t{0}] mutable -> void { Print(++x, ++y); };\n\n  // As an argument to a function call:\n  Foo(fn [var x, var y: i32 = 0] { Print(++x, ++y); });\n  // Equivalent in C++23:\n  // Foo([x, y = int32_t{0}] mutable -> void { Print(++x, ++y); });\n}\n```\n\n### Parameters\n\nLambdas also support so-called [\"positional parameters\"](#positional-parameters)\nthat are defined at their point of use using a dollar sign and a non-negative\ninteger. They are implicitly of type `auto`.\n\n```carbon\nfn Foo() {\n  let lambda: auto = fn { Print($0); };\n  // Equivalent in C++23:\n  // auto lambda = [](auto _0, auto...) -> void { Print(_0); };\n  // Equivalent in Swift:\n  // let lambda = { Print($0) };\n}\n```\n\nOf course, lambdas can also have named parameters, but a single lambda can't\nhave both named and positional parameters.\n\n```carbon\nfn Foo() {\n  // In a variable:\n  let lambda: auto = fn (v: auto) { Print(v); };\n  // Equivalent in C++23:\n  // const auto lambda = [](v: auto) -> void { Print(v); };\n\n  // As an argument to a function call:\n  Foo(fn (v: auto) { Print(v); });\n  // Equivalent in C++23:\n  // Foo([](v: auto) { Print(v); });\n}\n```\n\nAnd in additional the option between positional and named parameters, deduced\nparameters are always permitted.\n\n```carbon\nfn Foo() {\n  let lambda: auto = fn [T:! Printable](t: T) { Print(t); };\n}\n```\n\n### Syntax defined\n\nLambda expressions have one of the following syntactic forms (where items in\nsquare brackets are optional and independent):\n\n`fn`\\[_implicit-parameters_\\] \\[_tuple-pattern_\\] `=>` _expression_\n\n`fn` \\[_implicit-parameters_\\] \\[_tuple-pattern_\\] \\[`->` _return-type_\\] `{`\n_statements_ `}`\n\nThe first form is a shorthand for the second: \"`=>` _expression_\" is equivalent\nto \"`-> auto { return` _expression_ `; }`\".\n\n_implicit-parameters_ consists of square brackets enclosing a optional default\ncapture mode and any number of explicit captures, function fields, and deduced\nparameters, all separated by commas. The default capture mode (if any) must come\nfirst; the other items can appear in any order. If _implicit-parameters_ is\nomitted, it is equivalent to `[]`.\n\nFunction definitions are distinguished from lambdas by the presence of a name\nafter the `fn` keyword.\n\nThe presence of _tuple-pattern_ determines whether the function body uses named\nor positional parameters.\n\nThe presence of \"`->` _return-type_\" determines whether the function body can\n(and must) return a value.\n\nTo understand how the syntax between lambdas and function declarations is\nreasonably \"continuous\", refer to this table of syntactic positions and the\nfollowing code examples.\n\n| Syntactic Position |                         Syntax Allowed in Given Position (optional, unless otherwise stated)                         |\n| :----------------: | :------------------------------------------------------------------------------------------------------------------: |\n|         A1         |                Required Returned Expression ([positional parameters](#positional-parameters) allowed)                |\n|         A2         |              Required Returned Expression ([positional parameters](#positional-parameters) disallowed)               |\n|         B          |                                    [Default capture mode](#default-capture-mode)                                     |\n|         C          | Explicit [Captures](#captures), [Function fields](#function-fields-in-lambdas) and Deduced Parameters (in any order) |\n|         D          |                                                 Explicit Parameters                                                  |\n|         E1         |            Body of Statements (no return value) ([positional parameters](#positional-parameters) allowed)            |\n|         E2         |           Body of Statements (with return value) ([positional parameters](#positional-parameters) allowed)           |\n|         E3         |          Body of Statements (no return value) ([positional parameters](#positional-parameters) disallowed)           |\n|         E4         |         Body of Statements (with return value) ([positional parameters](#positional-parameters) disallowed)          |\n|         F          |                                                 Required Return Type                                                 |\n\n```carbon\n// Lambdas (all the following are in an expression context and are\n// themselves expressions)\n\nfn => A1\n\nfn [B, C] => A1\n\nfn (D) => A2\n\nfn [B, C](D) => A2\n\nfn { E1; }\n\nfn -> F { E2; }\n\nfn [B, C] { E1; }\n\nfn [B, C] -> F { E2; }\n\nfn (D) { E3; }\n\nfn (D) -> F { E4; }\n\nfn [B, C](D) { E3; }\n\nfn [B, C](D) -> F { E4; }\n```\n\n## Positional parameters\n\nPositional parameters, denoted by a dollar sign followed by a non-negative\ninteger (for example, $3), are auto-typed parameters defined within the lambda's\nbody.\n\n```carbon\nlet lambda: auto = fn => $0\n```\n\nThey can be used in any lambda declaration that lacks an explicit parameter list\n(parentheses). They are variadic by design, meaning an unbounded number of\narguments can be passed to any function that lacks an explicit parameter list.\nOnly the parameters that are named in the body will be read from, meaning the\nhighest named parameter denotes the minimum number of arguments required by the\nfunction. The lambda body is free to omit lower-numbered parameters (ex:\n`fn { Print($10); }`).\n\nThis syntax was inpsired by Swift's\n[Shorthand Argument Names](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/#Shorthand-Argument-Names).\n\n```carbon\n// A lambda that takes two positional parameters being used as a comparator\nSort(my_list, fn => $0.val < $1.val);\n// In Swift: { $0.val < $1.val }\n```\n\n### Positional parameter restrictions\n\nLambdas with positional parameters have the restriction that they can only be\nused in a context where there is exactly one enclosing function or lambda that\nhas no explicit parameter list. For example:\n\n```carbon\nfn Foo1 {\n  // ❌ Invalid: Foo1 is already using positional parameters\n  let lambda: auto = fn => $0 < $1\n}\n\nfn Foo2 {\n  my_list.Sort(\n    // ❌ Invalid: Foo2 is already using positional parameters\n    fn => $0 < $1\n  );\n}\n\nfn Foo3() {\n  my_list.Sort(\n    // ✅ Valid: Foo3 has explicit parameters\n    fn => $0 < $1\n  );\n}\n\nfn Foo4() {\n  let lambda: auto = fn -> bool {\n    // ❌ Invalid: Outer lambda is already using positional parameters\n    return (fn => $0 < $1)($0, $1);\n  };\n}\n\nfn Foo5() {\n  let lambda: auto = fn (x: i32, y: i32) -> bool {\n    // ✅ Valid: Outer lambda has explicit parameters\n    return (fn => $0 < $1)(x, y);\n  };\n}\n```\n\n## Captures\n\nCaptures in Carbon mirror the non-init captures of C++. A capture declaration\nconsists of a capture mode (for `var` captures) followed by the name of a\nbinding from the enclosing scope, and makes that identifier available in the\ninner function body. The lifetime of a capture is the lifetime of the function\nin which it exists. For example...\n\n```carbon\nfn Foo() {\n  let handle: Handle = Handle.Get();\n  var thread: Thread = Thread.Make(fn [var handle] { handle.Process(); });\n  thread.Join();\n}\n```\n\n```carbon\nfn Foo() {\n  let handle: Handle = Handle.Get();\n  fn MyThread[handle]() { handle.Process(); }\n  var thread: Thread = Thread.Make(MyThread);\n  thread.Join();\n}\n```\n\n### Capture modes\n\nLambdas can capture variables from their surrounding scope using `let` or `var`,\njust like regular bindings.\n\nCapture modes can be used as\n[default capture mode specifiers](#default-capture-mode) or for explicit\ncaptures as shown in the example code below.\n\n```carbon\nfn Example() {\n  var a: i32 = 0;\n  var b: i32 = 0;\n\nlet lambda: auto = fn [a, var b] {\n  // ❌ Invalid: by-value captures are immutable (default `let`)\n  a += 1;\n  // ✅ Valid: `b` is a mutable copy (captured with `var`)\n  b += 1;\n};\n\n  lambda();\n}\n```\n\n```carbon\nfn Example {\n  fn Invalid() -> auto {\n    var s: String = \"Hello world\";\n    return fn [s]() => s;\n  }\n\n  // ❌ Invalid: returned lambda references `s` which is no longer alive\n  // when the lambda is invoked.\n  Print(Invalid()());\n}\n```\n\nNote: If a function object F has mutable state, either because it has a\nby-object capture or because it has a by-object function field, then a call to F\nshould require the callee to be a reference expression rather than a value\nexpression. We need a mutable handle to the function in order to be able to\nmutate its mutable state.\n\n### Default capture mode\n\nBy default, there is no capturing in lambdas. The lack of any square brackets is\nthe same as an empty pair of square brackets. Users can opt into capturing\nbehavior. This is done either by way of individual explicit captures, or more\nsuccinctly by way of a default capture mode. The default capture mode roughly\nmirrors the syntax `[=]` and `[&]` capture modes from C++ by being the first\nthing to appear in the square brackets.\n\n```carbon\nfn Foo1() {\n  let handle: Handle = Handle.Get();\n  fn MyThread[var]() {\n    // `handle` is captured by-object due to the default capture\n    // mode specifier of `var`\n    handle.Process();\n  }\n  var thread: Thread = Thread.Make(MyThread);\n  thread.Join();\n}\n\nfn Foo2() {\n  let handle: Handle = Handle.Get();\n  fn MyThread[let]() {\n    // `handle` is captured by-value due to the default capture\n    // mode specifier of `let`\n    handle.Process();\n  }\n  var thread: Thread = Thread.Make(MyThread);\n  thread.Join();\n}\n```\n\n## Function fields in lambdas\n\nFunction fields in lambdas mirror the behavior of init captures in C++. A\nfunction field definition consists of an irrefutable pattern, `=`, and an\ninitializer. It matches the pattern with the initializer when the lambda\ndefinition is evaluated. The bindings in the pattern have the same lifetime as\nthe function, and their scope extends to the end of the function body.\n\n```carbon\nfn Foo() {\n  var h1: Handle = Handle.Get();\n  var h2: Handle = Handle.Get();\n  var thread: Thread = Thread.Make(fn [a: auto = h1, var b: auto = h2] {\n    a.Process();\n    b.Process();\n  });\n  thread.Join();\n}\n```\n\n## Copy semantics\n\nTo mirror the behavior of C++, lambdas will be as copyable as their contained\nfunction fields and function captures. This means that, if a function holds a\nby-object function field, if the type of the field is copyable, so too is the\nfunction that contains it. This also applies to captures.\n\nThe other case is by-value function fields. Since C++ const references, when\nmade into fields of a class, prevent the class from being copied assigned, so\ntoo should by-value function fields prevent the function in which it is\ncontained from being copied assigned.\n\n## Self and recursion\n\nTo mirror C++'s use of capturing `this`, `self` should always come from the\nouter scope as a capture. `self: Self` is never permitted on lambdas.\n\n```carbon\n// ❌ Not allowed\nlet lambda: auto = fn [self: Self] { self.F(); };\n\n// ✅ Captures `self` from outer scope\nlet lambda: auto = fn [self] { self.F(); };\n```\n\nNote: Following\n[#3720](https://github.com/carbon-language/carbon-lang/pull/3720), an expression\nof the form `x.(F)`, where `F` is a function with a `self` or `ref self`\nparameter, produces a callable that holds the value of `x`, and does not hold\nthe value of `F`. As a consequence, we can't support combining captures and\nfunction fields with a `self` parameter.\n\n## Alternatives considered\n\n-   [Terse vs Elaborated](/proposals/p3848.md#alternative-considered-terse-vs-elaborated)\n-   [Sigil](/proposals/p3848.md#alternative-considered-sigil)\n-   [Additional Positional Parameter Restriction](/proposals/p3848.md#alternative-considered-additional-positional-parameter-restriction)\n-   [Recursive Self](/proposals/p3848.md#alternative-considered-recursive-self)\n"
  },
  {
    "path": "docs/design/lexical_conventions/README.md",
    "content": "# Lexical conventions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Lexical elements](#lexical-elements)\n\n<!-- tocstop -->\n\n## Lexical elements\n\nThe first stage of processing a\n[source file](/docs/design/code_and_name_organization/source_files.md) is the\ndivision of the source file into lexical elements.\n\nA _lexical element_ is one of the following:\n\n-   a maximal sequence of [whitespace](whitespace.md) characters\n-   a [word](words.md)\n-   a literal:\n\n    -   a [numeric literal](numeric_literals.md)\n    -   a [string literal](string_literals.md)\n\n-   a [comment](comments.md)\n-   a [symbolic token](symbolic_tokens.md)\n\nThe sequence of lexical elements is formed by repeatedly removing the longest\ninitial sequence of characters that forms a valid lexical element, with the\nfollowing exception:\n\n-   When a numeric literal immediately follows a `.` or `->` token, with no\n    intervening whitespace, a real literal is never formed. Instead, the token\n    will end no later than the next `.` character. For example, `tuple.1.2` is\n    five tokens, `tuple` `.` `1` `.` `2`, not three tokens, `tuple` `.` `1.2`.\n    However, `tuple . 1.2` is lexed as three tokens.\n"
  },
  {
    "path": "docs/design/lexical_conventions/comments.md",
    "content": "# Comments\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nA comment is a lexical element beginning with the characters `//` and running to\nthe end of the line. We have no mechanism for physical line continuation, so a\ntrailing `\\` does not extend a comment to subsequent lines.\n\n## Details\n\nIn the comments after the `//` a whitespace character is required to make the\ncomment valid. Newline is a whitespace character, so a line containing only `//`\nis a valid comment. The end of the file also constitutes whitespace.\n\nAll comments are removed prior to formation of tokens.\n\nExample:\n\n```\n// This is a comment and is ignored. \\\nThis is not a comment.\n\nvar Int: x; // error, trailing comments not allowed\n```\n\nCurrently no support for block comments is provided. Commenting out larger\nregions of human-readable text or code is accomplished by commenting out every\nline in the region.\n\n## Alternatives considered\n\n-   [Intra-line comments](/proposals/p0198.md#intra-line-comments)\n-   [Multi-line text comments](/proposals/p0198.md#multi-line-text-comments)\n-   [Block comments](/proposals/p0198.md#block-comments-2)\n-   [Documentation comments](/proposals/p0198.md#documentation-comments)\n-   [Code folding comments](/proposals/p0198.md#code-folding-comments)\n\n## References\n\n-   Proposal\n    [#198: Comments](https://github.com/carbon-language/carbon-lang/pull/198)\n"
  },
  {
    "path": "docs/design/lexical_conventions/numeric_literals.md",
    "content": "# Numeric literals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [Integer literals](#integer-literals)\n    -   [Real-number literals](#real-number-literals)\n    -   [Digit separators](#digit-separators)\n-   [Divergence from other languages](#divergence-from-other-languages)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nThe following syntaxes are supported:\n\n-   [Integer literals](#integer-literals)\n    -   `12345` (decimal)\n    -   `0x1FE` (hexadecimal)\n    -   `0o755` (octal)\n    -   `0b1010` (binary)\n-   [Real-number literals](#real-number-literals)\n    -   `123.456` (digits on both sides of the `.`)\n    -   `123.456e789` (optional `+` or `-` after the `e`)\n    -   `0x1.2p123` (optional `+` or `-` after the `p`)\n-   [Digit separators](#digit-separators) (`_`)\n\nNote that real-number literals always contain a `.` with digits on both sides,\nand integer literals never contain a `.`.\n\nLiterals are case-sensitive. Unlike in C++, literals do not have a suffix to\nindicate their type.\n\n## Details\n\n### Integer literals\n\nDecimal integers are written as a non-zero decimal digit followed by zero or\nmore additional decimal digits, or as a single `0`.\n\nIntegers in other bases are written as a `0` followed by a base specifier\ncharacter, followed by a sequence of one or more digits in the corresponding\nbase. The available base specifiers and corresponding bases are:\n\n| Base specifier | Base | Digits                   |\n| -------------- | ---- | ------------------------ |\n| `b`            | 2    | `0` and `1`              |\n| `o`            | 8    | `0` ... `7`              |\n| `x`            | 16   | `0` ... `9`, `A` ... `F` |\n\nThe above table is case-sensitive. For example, `0b1`, `0o7`, and `0x1A` are\nvalid, and `0B1`, `0O7`, `0X1A`, and `0x1a` are invalid.\n\nA zero at the start of a literal can never be followed by another digit: either\nthe literal is `0`, the `0` begins a base specifier, or the next character is a\ndecimal point (see below). The `0o` prefix is used for octal literals; a C-style\n`0755` octal is invalid in Carbon.\n\n### Real-number literals\n\nReal numbers are written as a decimal or hexadecimal integer followed by a\nperiod (`.`) followed by a sequence of one or more decimal or hexadecimal\ndigits, respectively. A digit is required on each side of the period. `0.` and\n`.3` are both lexed as two separate tokens: `0.(Util.Abs)()` and `tuple.3` both\ntreat the period as member or element access, not as a radix point.\n\nTo support tuple indexing, a real number literal is never formed immediately\nfollowing a `.` token with no intervening whitespace. Instead, the result is an\ninteger literal.\n\nA real number can be followed by an exponent character, an optional `+` or `-`\n(defaulting to `+` if absent), and a character sequence matching the grammar of\na decimal integer with some value _N_. For a decimal real number, the exponent\ncharacter is `e`, and the effect is to multiply the given value by\n10<sup>&plusmn;_N_</sup>. For a hexadecimal real number, the exponent character\nis `p`, and the effect is to multiply the given value by\n2<sup>&plusmn;_N_</sup>. The exponent suffix is optional for both decimal and\nhexadecimal real numbers.\n\nNote that a decimal integer followed by `e` is not a real-number literal. For\nexample, `3e10` is not a valid literal.\n\nWhen a real-number literal is interpreted as a value of a real-number type, its\nvalue is the representable real number closest to the value of the literal. In\nthe case of a tie, the nearest value whose mantissa is even is selected.\n\nThe decimal real number syntax allows for any decimal fraction to be expressed\n-- that is, any number of the form _a_ x 10<sup>-_b_</sup>, where _a_ is an\ninteger and _b_ is a non-negative integer. Because the decimal fractions are\ndense in the reals and the set of values of the real-number type is assumed to\nbe discrete, every value of the real-number type can be expressed as a real\nnumber literal. However, for certain applications, directly expressing the\nintended real-number representation may be more convenient than producing a\ndecimal equivalent that is known to convert to the intended value. Hexadecimal\nreal-number literals are provided in order to permit values of binary floating\nor fixed point real-number types to be expressed directly.\n\n### Digit separators\n\nA digit separator (`_`) may occur between any two digits within a literal. For\nexample:\n\n-   Decimal integers: `1_23_456_7890`\n-   Hexadecimal integers: `0x7_F_FF_FFFF`\n-   Octal literals: `0o7_55`\n-   Binary literals: `0b1_000_101_11`\n-   Real-number literals: `2_147.48_3648e12_345` or `0x1_00CA.FE_F00Dp+2_4`\n\n## Divergence from other languages\n\nThe design provides a syntax that is deliberately close to that used both by C++\nand many other languages, so it should feel familiar to developers. However, it\nselects a reasonably minimal subset of the syntaxes. This minimal approach\nprovides benefits directly in line with the goal that Carbon code should be\n[easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n\n-   Reduces unnecessary choices for programmers.\n-   Simplifies the syntax rules of the language.\n-   Improves consistency of written Carbon code.\n\nThat said, it still provides sufficient variations to address important use\ncases for the goal of not leaving room for a lower level language:\n\n-   Hexadecimal, octal, and binary integer literals.\n-   Scientific notation floating point literals.\n-   Hexadecimal (scientific) floating point literals.\n\n## Alternatives considered\n\n-   [Integer bases](/proposals/p0143.md#integer-bases)\n    -   [Octal literals](/proposals/p0143.md#octal-literals)\n    -   [Decimal literals](/proposals/p0143.md#decimal-literals)\n    -   [Case sensitivity](/proposals/p0143.md#case-sensitivity)\n-   [Real number syntax](/proposals/p0143.md#real-number-syntax)\n    -   [Disallow ties](/proposals/p0866.md)\n-   [Digit separator syntax](/proposals/p0143.md#digit-separator-syntax)\n    -   [3-digit decimal groupings](/proposals/p1983.md#3-digit-decimal-groupings)\n    -   [2-digit or 4-digit hexadecimal digit groupings](/proposals/p1983.md#2-digit-or-4-digit-hexadecimal-digit-groupings)\n    -   [Disallow digit separators in fractions](/proposals/p1983.md#disallow-digit-separators-in-fractions)\n-   [No octal literals](/proposals/p6910.md#no-octal-literals)\n\n## References\n\n-   Proposal\n    [#143: Numeric literals](https://github.com/carbon-language/carbon-lang/pull/143)\n-   Proposal\n    [#866: Allow ties in floating literals](https://github.com/carbon-language/carbon-lang/pull/866)\n-   Proposal\n    [#1983: Weaken digit separator placement rules](https://github.com/carbon-language/carbon-lang/pull/1983)\n-   Proposal\n    [#6910: Support octal literals](https://github.com/carbon-language/carbon-lang/pull/6910)\n"
  },
  {
    "path": "docs/design/lexical_conventions/string_literals.md",
    "content": "# String literals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [Simple and block string literals](#simple-and-block-string-literals)\n        -   [Escape sequences](#escape-sequences)\n    -   [Raw string literals](#raw-string-literals)\n    -   [Encoding](#encoding)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon supports both simple literals that are single-line using one double\nquotation mark (`\"`) and block literals that are multi-line using three single\nquotation marks (`'''`). A block string literal may have a file type indicator\nafter the first `'''`; this does not affect the string itself, but may assist\nother tooling. For example:\n\n```carbon\n// Simple string literal:\nvar simple: String = \"example\";\n\n// Block string literal:\nvar block: String = '''\n    The winds grow high; so do your stomachs, lords.\n    How irksome is this music to my heart!\n    When such strings jar, what hope of harmony?\n    I pray, my lords, let me compound this strife.\n        -- History of Henry VI, Part II, Act II, Scene 1, W. Shakespeare\n    ''';\n\n// Block string literal with file type indicator:\nvar code_block: String = '''cpp\n    #include <iostream>\n    int main() {\n        std::cout << \"Hello world!\";\n        return 0;\n    }\n    '''\n```\n\nThe indentation of a block string literal's terminating line is removed from all\npreceding lines. As a consequence, in the above `code_block` example, only\n`std::cout` and `return` are indented in the resulting string, and by 4 spaces\neach.\n\nEscape sequences introduced by a backslash (`\\`) and are used to express special\ncharacter or code unit sequences, such as `\\n` for a newline character. Raw\nstring literals are additionally delimited with one or more `#`; these require\nan equal number of hash symbols (`#`) after the `\\` to indicate an escape\nsequence. Raw string literals are used to more easily write literal `\\`s in\nstrings. Both simple and block string literals have raw forms. For example:\n\n```carbon\n// Raw simple string literal with newline escape sequence:\nvar newline: String = \"line one\\nline two\";\n\n// Raw simple string literal with literal `\\n`, not a newline:\nvar raw: String = #\"line one\\nstill line one\"#;\n\n// Raw simple string literal with newline escape sequence:\nvar raw_newline: String = #\"line one\\#nline two\"#;\n```\n\n## Details\n\n### Simple and block string literals\n\nA _simple string literal_ is formed of a sequence of:\n\n-   Characters other than `\\` and `\"`.\n    -   Only space characters (U+0020) are valid whitespace in a string literal.\n    -   Other [horizontal whitespace](whitespace.md), including tabs, are\n        disallowed but parse as part of the string for error recovery purposes.\n    -   Vertical whitespace will not parse as part of a simple string literal.\n-   [Escape sequences](#escape-sequences).\n    -   Each escape sequence is replaced with the corresponding character\n        sequence or code unit sequence.\n    -   Similarly to invalid whitespace, invalid escape sequences such as `\\z`\n        parse as part of the string.\n\nThis sequence is enclosed in `\"`s. For example, this is a simple string literal:\n\n```carbon\nvar String: lucius = \"The strings, my lord, are false.\";\n```\n\nAdjacent string literals are disallowed, like the following:\n\n```carbon\n// The three adjacent simple string literals `\"\"`, `\"abc\"` and `\"\"` are invalid.\nvar String: block = \"\"\"abc\"\"\";\n```\n\nString literals starting with triple double quotation marks `\"\"\"` are adjacent\nstring literals. It is important to reject and diagnose them.\n\nA _block string_ literal starts with `'''`. Characters on the same line\nfollowing the `'''` are an optional file type indicator. The literal ends at the\nnext instance of three single quotation marks whose first `'` is not part of a\n`\\'` escape sequence. The closing `'''` shall be the first non-whitespace\ncharacters on that line. The lines between the opening line and the closing line\n(exclusive) are _content lines_. The content lines shall not contain `\\`\ncharacters that do not form part of an escape sequence.\n\nThe _indentation_ of a block string literal is the sequence of horizontal\nwhitespace preceding the closing `'''`. Each non-empty content line shall begin\nwith the indentation of the string literal. The content of the literal is formed\nas follows:\n\n-   The indentation of the closing line is removed from each non-empty content\n    line.\n-   All trailing whitespace on each line, including the line terminator, is\n    replaced with a single line feed (U+000A) character.\n-   The resulting lines are concatenated.\n-   Each [escape sequence](#escape-sequences) is replaced with the corresponding\n    character sequence or code unit sequence.\n\nA content line is considered empty if it contains only whitespace characters.\n\n```carbon\n// All block string literals contain a trailing newline by default.\nvar String: newline_example = '''\n  This is a block string literal. Its first character is 'T' and its last character is\n  a newline. It contains another newline character between 'is' and 'a'.\n  ''';\n\n// Newlines can be suppressed using the escape character '\\'\nvar String: suppressed_newlines = '''\n  This is another block string literal. The newline character here \\\n  is suppressed, along with the trailing newline here.\\\n  ''';\n\n// This block string literal is invalid because the ''' after 'closing' terminates\n// the literal, but is not at the start of the line.\nvar String: invalid = '''\n  error: closing ''' is not on its own line.\n  ''';\n```\n\nA _file type indicator_ is any sequence of non-whitespace characters other than\n`'` or `#`. The file type indicator has no semantic meaning to the Carbon\ncompiler, but some file type indicators are understood by the language tooling\n(for example, syntax highlighter, code formatter) as indicating the structure of\nthe string literal's content.\n\n```carbon\n// This is a block string literal. Its first two characters are spaces, and its\n// last character is a line feed. It has a file type of 'c++'.\nvar String: starts_with_whitespace = '''c++\n    int x = 1; // This line starts with two spaces.\n    int y = 2; // This line starts with two spaces.\n  ''';\n```\n\nThe file type indicator might contain semantic information beyond the file type\nitself, such as instructions to the code formatter to disable formatting for the\ncode block.\n\n**Open question:** There is no concrete set of recognized file type indicators.\nIt would be useful to informally specify a set of well-known indicators, so that\ntools have a common understanding of what those indicators mean, perhaps in a\nbest practices guide.\n\n#### Escape sequences\n\nWithin a string literal, the following escape sequences are recognized:\n\n| Escape        | Meaning                                                  |\n| ------------- | -------------------------------------------------------- |\n| `\\t`          | U+0009 CHARACTER TABULATION                              |\n| `\\n`          | U+000A LINE FEED                                         |\n| `\\r`          | U+000D CARRIAGE RETURN                                   |\n| `\\\"`          | U+0022 QUOTATION MARK (`\"`)                              |\n| `\\'`          | U+0027 APOSTROPHE (`'`)                                  |\n| `\\\\`          | U+005C REVERSE SOLIDUS (`\\`)                             |\n| `\\0`          | Code unit with value 0                                   |\n| `\\0D`         | Invalid, reserved for evolution                          |\n| `\\xHH`        | Code unit with value HH<sub>16</sub>                     |\n| `\\u{HHHH...}` | Unicode code point U+HHHH...                             |\n| `\\<newline>`  | No string literal content produced (block literals only) |\n\nHex characters (`H`) must be uppercase (`\\xAA`, not `\\xaa`).\n\nThis includes all C++ escape sequences except:\n\n-   `\\?`, which was historically used to escape trigraphs in string literals,\n    and no longer serves any purpose.\n-   `\\ooo` octal escapes, which are removed because Carbon does not support\n    octal literals; `\\0` is retained as a special case, which is expected to be\n    important for C interoperability.\n-   `\\uABCD`, which is replaced by `\\u{ABCD}`.\n-   `\\U0010FFFF`, which is replaced by `\\u{10FFFF}`.\n-   `\\a` (bell), `\\b` (backspace), `\\v` (vertical tab), and `\\f` (form feed).\n    `\\a` and `\\b` are obsolescent, and `\\f` and `\\v` are largely obsolete. These\n    characters can be expressed with `\\x07`, `\\x08`, `\\x0B`, and `\\x0C`\n    respectively if needed.\n\nNote that this is the same set of escape sequences supported by\n[Swift](https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#ID295)\nand [Rust](https://doc.rust-lang.org/reference/tokens.html), except that, unlike\nin Swift, support for `\\xHH` is provided.\n\nWhile octal escape sequences are expected to remain not permitted (even though\n`\\0D` is reserved), the decision to not support `\\1`..`\\7` or more generally\n`\\DDDD` is _experimental_.\n\nIn the above table, `H` represents an arbitrary hexadecimal character, `0`-`9`\nor `A`-`F` (case-sensitive). Unlike in C++, but like in Python, `\\x` expects\nexactly two hexadecimal digits. As in JavaScript, Rust, and Swift, Unicode code\npoints can be expressed by number using `\\u{10FFFF}` notation. This accepts\nbetween 1 and 8 hexadecimal characters. Any numeric code point in the ranges\n0<sub>16</sub>-D7FF<sub>16</sub> or E000<sub>16</sub>-10FFFF<sub>16</sub> can be\nexpressed this way.\n\n_Open question:_ Some programming languages (notably Python) support a\n`\\N{unicode character name}` syntax. We could add such an escape sequence.\nFuture proposals considering adding such support should pay attention to work\ndone by C++'s Unicode study group in this area.\n\nThe escape sequence `\\0` shall not be followed by a decimal digit. In cases\nwhere a null byte should be followed by a decimal digit, `\\x00` can be used\ninstead: `\"foo\\x00123\"`. The intent is to preserve the possibility of permitting\ndecimal escape sequences in the future.\n\nA backslash followed by a line feed character is an escape sequence that\nproduces no string contents. This escape sequence is _experimental_, and can\nonly appear in block string literals. This escape sequence is processed after\ntrailing whitespace is replaced by a line feed character, so a `\\` followed by\nhorizontal whitespace followed by a line terminator removes the whitespace up to\nand including the line terminator. Unlike in Rust, but like in Swift, leading\nwhitespace on the line after an escaped newline is not removed, other than\nwhitespace that matches the indentation of the terminating `'''`.\n\nA character sequence starting with a backslash that doesn't match any known\nescape sequence is invalid. Whitespace characters other than space and, for\nblock string literals, new line optionally preceded by carriage return are\ndisallowed. All other characters (including non-printable characters) are\npreserved verbatim. Because all Carbon source files are required to be valid\nsequences of Unicode characters, code unit sequences that are not valid UTF-8\ncan only be produced by `\\x` escape sequences.\n\nThe decision to disallow raw tab characters in string literals is\n_experimental_.\n\n```carbon\nvar String: fret = \"I would 'twere something that would fret the string,\\n\" +\n                   \"The master-cord on's \\u{2764}\\u{FE0F}!\";\n\n// This string contains two characters (prior to encoding in UTF-8):\n// U+1F3F9 (BOW AND ARROW) followed by U+0032 (DIGIT TWO)\nvar String: password = \"\\u{1F3F9}2\";\n\n// This string contains no newline characters.\nvar String: type_mismatch = '''\n  Shall I compare thee to a summer's day? Thou art \\\n  more lovely and more temperate.\\\n  ''';\n\nvar String: trailing_whitespace = '''\n  This line ends in a space followed by a newline. \\n\\\n      This line starts with four spaces.\n  ''';\n```\n\n### Raw string literals\n\nIn order to allow strings whose contents include `\\`s and `\"`s, the delimiters\nof string literals can be customized by prefixing the opening delimiter with _N_\n`#` characters. A closing delimiter for such a string is only recognized if it\nis followed by _N_ `#` characters, and similarly, escape sequences in such\nstring literals are recognized only if the `\\` is also followed by _N_ `#`\ncharacters. A `\\`, `\"`, or `'''` not followed by _N_ `#` characters has no\nspecial meaning.\n\n| Opening delimiter | Escape sequence introducer    | Closing delimiter |\n| ----------------- | ----------------------------- | ----------------- |\n| `\"` / `'''`       | `\\` (for example, `\\n`)       | `\"` / `'''`       |\n| `#\"` / `#'''`     | `\\#` (for example, `\\#n`)     | `\"#` / `'''#`     |\n| `##\"` / `##'''`   | `\\##` (for example, `\\##n`)   | `\"##` / `'''##`   |\n| `###\"` / `###'''` | `\\###` (for example, `\\###n`) | `\"###` / `'''###` |\n| ...               | ...                           | ...               |\n\nFor example:\n\n```carbon\nvar String: x = #'''\n  This is the content of the string. The 'T' is the first character\n  of the string.\n  ''' <-- This is not the end of the string.\n  '''#;\n  // But the preceding line does end the string.\n// OK, final character is \\\nvar String: y = #\"Hello\\\"#;\nvar String: z = ##\"Raw strings #\"nesting\"#\"##;\nvar String: w = #\"Tab is expressed as \\t. Example: '\\#t'\"#;\n```\n\n### Encoding\n\nA string literal results in a sequence of 8-bit bytes. Like Carbon source files,\nstring literals are encoded in UTF-8. There is no guarantee that the string is\nvalid UTF-8, however, because arbitrary byte sequences can be inserted by way of\n`\\xHH` escape sequences.\n\nThis is _experimental_, and should be revisited if we find sufficient motivation\nfor directly expressing string literals in other encodings. Similarly, as\nlibrary support for a string type evolves, we should consider including string\nliteral syntax (perhaps as the default) that guarantees the string content is a\nvalid UTF-8 encoding, so that valid UTF-8 can be distinguished from an arbitrary\nstring in the type system. In such string literals, we should consider rejecting\n`\\xHH` escapes in which HH is greater than 7F<sub>16</sub>, as in Rust.\n\n## Alternatives considered\n\n-   [Block string literals](/proposals/p0199.md#block-string-literals)\n    -   [Leading whitespace removal](/proposals/p0199.md#leading-whitespace-removal)\n    -   [Terminating newline](/proposals/p0199.md#terminating-newline)\n-   [Escape sequences](/proposals/p0199.md#escape-sequences-1)\n    -   Unicode escape sequences:\n        -   [Allow zero digits](/proposals/p2040.md#allow-zero-digits)\n        -   [Allow any number of hexadecimal characters](/proposals/p2040.md#allow-any-number-of-hexadecimal-characters)\n        -   [Limiting to 6 digits versus 8](/proposals/p2040.md#limiting-to-6-digits-versus-8)\n-   [Raw string literals](/proposals/p0199.md#raw-string-literals-1)\n    -   [Trailing whitespace](/proposals/p0199.md#trailing-whitespace)\n    -   [Line separators](/proposals/p0199.md#line-separators)\n-   [Internal whitespace](/proposals/p0199.md#internal-whitespace)\n-   [Different restrictions for file type indicators](https://github.com/carbon-language/carbon-lang/issues/2140)\n\n## References\n\n-   Proposal\n    [#199: String literals](https://github.com/carbon-language/carbon-lang/pull/199)\n-   Proposal\n    [#2040: Unicode escape code length](https://github.com/carbon-language/carbon-lang/pull/2040)\n"
  },
  {
    "path": "docs/design/lexical_conventions/symbolic_tokens.md",
    "content": "# Symbolic Tokens\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [Symbolic token list](#symbolic-token-list)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nA _symbolic token_ is one of a fixed set of\n[tokens](https://en.wikipedia.org/wiki/Lexical_analysis#Token) that consist of\ncharacters that are not valid in identifiers. That is, they are tokens\nconsisting of symbols, not letters or numbers. Operators are one use of symbolic\ntokens, but they are also used in patterns `:`, declarations (`->` to indicate\nreturn type, `,` to separate parameters), statements (`;`, `=`, and so on), and\nother places (`,` to separate function call arguments).\n\nCarbon has a fixed set of symbolic tokens, defined by the language\nspecification. Developers cannot define new symbolic tokens in their own code.\n\nSymbolic tokens are lexed using a \"max munch\" rule: at each lexing step, the\nlongest symbolic token defined by the language specification that appears\nstarting at the current input position is lexed, if any.\n\nWhen a symbolic token is used as an operator, the surrounding whitespace must\nfollow certain rules:\n\n-   There can be no whitespace between a unary operator and its operand.\n-   The whitespace around a binary operator must be consistent: either there is\n    whitespace on both sides or on neither side.\n-   If there is whitespace on neither side of a binary operator, the token\n    before the operator must be an identifier, a literal, or any kind of closing\n    bracket (for example, `)`, `]`, or `}`), and the token after the operator\n    must be an identifier, a literal, or any kind of opening bracket (for\n    example, `(`, `[`, or `{`).\n\nThese rules enable us to use a token like `*` as a prefix, infix, and postfix\noperator, without creating ambiguity.\n\n## Details\n\n### Symbolic token list\n\nThe following is the initial list of symbolic tokens recognized in a Carbon\nsource file:\n\n| Symbolic Tokens | Explanation                                                                                                  |\n| --------------- | ------------------------------------------------------------------------------------------------------------ |\n| `+`             | Addition                                                                                                     |\n| `-`             | Subtraction and negation                                                                                     |\n| `*`             | Indirection, multiplication, and forming pointer types                                                       |\n| `/`             | Division                                                                                                     |\n| `%`             | Modulus                                                                                                      |\n| `^`             | Complementing and Bitwise XOR                                                                                |\n| `&`             | Address-of and Bitwise AND                                                                                   |\n| `\\|`            | Bitwise OR                                                                                                   |\n| `<<`            | Arithmetic and Logical Left-shift                                                                            |\n| `>>`            | Arithmetic and Logical Right-shift                                                                           |\n| `=`             | Assignment and initialization                                                                                |\n| `++`            | Increment                                                                                                    |\n| `--`            | Decrement                                                                                                    |\n| `+=`            | Add-and-assign                                                                                               |\n| `-=`            | Subtract-and-assign                                                                                          |\n| `*=`            | Multiply-and-assign                                                                                          |\n| `/=`            | Divide-and-assign                                                                                            |\n| `%=`            | Modulus-and-assign                                                                                           |\n| `&=`            | Bitwise-AND-and-assign                                                                                       |\n| `\\|=`           | Bitwise-OR-and-assign                                                                                        |\n| `^=`            | Bitwise-XOR-and-assign                                                                                       |\n| `<<=`           | Left-shift-and-assign                                                                                        |\n| `>>=`           | Right-shift-and-assign                                                                                       |\n| `==`            | Equality or equal to                                                                                         |\n| `!=`            | Inequality or not equal to                                                                                   |\n| `>`             | Greater than                                                                                                 |\n| `>=`            | Greater than or equal to                                                                                     |\n| `<`             | Less than                                                                                                    |\n| `<=`            | Less than or equal to                                                                                        |\n| `->`            | Return type and indirect member access                                                                       |\n| `=>`            | Match syntax                                                                                                 |\n| `[` and `]`     | Subscript and deduced parameter lists                                                                        |\n| `(` and `)`     | Function call, function declaration, and tuple literals                                                      |\n| `{` and `}`     | Struct literals, blocks of control flow statements, and the bodies of definitions (classes, functions, etc.) |\n| `,`             | Separate tuple and struct elements                                                                           |\n| `.`             | Member access                                                                                                |\n| `:`             | Name binding patterns                                                                                        |\n| `:!`            | Compile-time binding patterns                                                                                |\n| `;`             | Statement separator                                                                                          |\n\n## Alternatives considered\n\n[Alternatives from proposal #601](/proposals/p0601.md#alternatives-considered):\n\n-   lex the longest sequence of symbolic characters rather than lexing only the\n    longest known operator\n-   support an extensible operator set\n-   different whitespace restrictions or no whitespace restrictions\n\n## References\n\n-   Proposal\n    [#162: Basic Syntax](https://github.com/carbon-language/carbon-lang/pull/162)\n-   Proposal\n    [#339: Add `var <type> <identifier> [ = <value> ];` syntax for variables](https://github.com/carbon-language/carbon-lang/pull/339)\n-   Proposal\n    [#438: Add statement syntax for function declarations](https://github.com/carbon-language/carbon-lang/pull/438)\n-   Proposal\n    [#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561)\n-   Proposal\n    [#601: Operator tokens](https://github.com/carbon-language/carbon-lang/pull/601)\n-   Proposal\n    [#676: `:!` generic syntax](https://github.com/carbon-language/carbon-lang/pull/676)\n-   Proposal\n    [#702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702)\n-   Proposal\n    [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n-   Proposal\n    [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083)\n-   Proposal\n    [#1191: Bitwise operators](https://github.com/carbon-language/carbon-lang/pull/1191)\n-   Proposal\n    [#2188: Pattern matching syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2188)\n-   Proposal\n    [#2274: Subscript syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2274)\n-   Proposal\n    [#2511: Assignment statements](https://github.com/carbon-language/carbon-lang/pull/2511)\n-   Proposal\n    [#2665: Semicolons terminate statements](https://github.com/carbon-language/carbon-lang/pull/2665)\n"
  },
  {
    "path": "docs/design/lexical_conventions/whitespace.md",
    "content": "# Whitespace\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nThe exact lexical form of Carbon whitespace has not yet been settled. However,\nCarbon will follow lexical conventions for whitespace based on\n[Unicode Annex #31](https://unicode.org/reports/tr31/). TODO: Update this once\nthe precise rules are decided; see the\n[Unicode source files](/proposals/p0142.md#characters-in-identifiers-and-whitespace)\nproposal.\n\nUnicode Annex #31 suggests selecting whitespace characters based on the\ncharacters with Unicode property `Pattern_White_Space`, which is currently these\n11 characters:\n\n-   Horizontal whitespace:\n    -   U+0009 CHARACTER TABULATION (horizontal tab)\n    -   U+0020 SPACE\n    -   U+200E LEFT-TO-RIGHT MARK\n    -   U+200F RIGHT-TO-LEFT MARK\n-   Vertical whitespace:\n    -   U+000A LINE FEED (traditional newline)\n    -   U+000B LINE TABULATION (vertical tab)\n    -   U+000C FORM FEED (page break)\n    -   U+000D CARRIAGE RETURN\n    -   U+0085 NEXT LINE (Unicode newline)\n    -   U+2028 LINE SEPARATOR\n    -   U+2029 PARAGRAPH SEPARATOR\n\nThe quantity and kind of whitespace separating tokens is ignored except where\notherwise specified.\n\n## References\n\n-   Proposal\n    [#142: Unicode source files](https://github.com/carbon-language/carbon-lang/pull/142)\n"
  },
  {
    "path": "docs/design/lexical_conventions/words.md",
    "content": "# Words\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Keywords](#keywords)\n    -   [Type literals](#type-literals)\n    -   [Identifiers](#identifiers)\n    -   [Raw identifiers](#raw-identifiers)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nA _word_ is a lexical element formed from a sequence of letters or letter-like\ncharacters, such as `fn` or `Foo` or `Int`, optionally preceded by `r#`.\n\nThe exact lexical form of words has not yet been settled. However, Carbon will\nfollow lexical conventions for identifiers based on\n[Unicode Annex #31](https://unicode.org/reports/tr31/). TODO: Update this once\nthe precise rules are decided; see the\n[Unicode source files](/proposals/p0142.md#characters-in-identifiers-and-whitespace)\nproposal.\n\nCarbon source files, including comments and string literals, are required to be\nin Unicode Normalization Form C (NFC).\n\n## Keywords\n\n<!--\nKeep in sync:\n- utils/textmate/Syntaxes/carbom.tmLanguage.json\n- utils/tree_sitter/queries/highlights.scm\n-->\n\nThe following words are interpreted as keywords:\n\n-   `abstract`\n-   `adapt`\n-   `alias`\n-   `and`\n-   `as`\n-   `auto`\n-   `base`\n-   `break`\n-   `Core`\n-   `case`\n-   `choice`\n-   `class`\n-   `constraint`\n-   `continue`\n-   `default`\n-   `destroy`\n-   `else`\n-   `export`\n-   `extend`\n-   `final`\n-   `fn`\n-   `for`\n-   `forall`\n-   `friend`\n-   `if`\n-   `impl`\n-   `impls`\n-   `import`\n-   `in`\n-   `interface`\n-   `let`\n-   `library`\n-   `like`\n-   `match`\n-   `namespace`\n-   `not`\n-   `observe`\n-   `or`\n-   `override`\n-   `package`\n-   `partial`\n-   `private`\n-   `protected`\n-   `ref`\n-   `require`\n-   `return`\n-   `returned`\n-   `Self`\n-   `self`\n-   `template`\n-   `then`\n-   `type`\n-   `var`\n-   `virtual`\n-   `where`\n-   `while`\n\n### Type literals\n\nA word starting with `i`, `u`, or `f`, followed by a decimal integer, is a\n[_numeric type literal_](/docs/design/expressions/literals.md#numeric-type-literals).\n\n### Identifiers\n\nA word is interpreted as an _identifier_ if it is neither a keyword nor a type\nliteral.\n\n### Raw identifiers\n\nA _raw identifier_ is a word starting with `r#`. A raw identifier is equivalent\nto the word following the `r#` prefix, except that it is always interpreted as\nan identifier, even if it would otherwise be a keyword or type literal.\n\nRaw identifiers can be used to specify identifiers which have the same spelling\nas keywords; for example, `r#impl`. This can be useful when interoperating with\nC++ code that uses identifiers that are keywords in Carbon, and when migrating\nbetween versions of Carbon.\n\nThe word doesn't need to be a keyword, in order to support forwards\ncompatibility when a keyword is planned to be added. If `word` is an identifier,\nthen `word` and `r#word` have the same meaning.\n\n## Alternatives considered\n\nOverview:\n\n-   [Character encoding: We could restrict words to ASCII.](/proposals/p0142.md#character-encoding-1)\n-   [Normalization form alternatives considered](/proposals/p0142.md#normalization-forms)\n\nType literals:\n\n-   [Use C++ type keywords with LP64 convention](/proposals/p2015.md#c-lp64-convention)\n-   [Use full type name with length suffix](/proposals/p2015.md#type-name-with-length-suffix)\n-   [Use uppercase for type names](/proposals/p2015.md#uppercase-suffixes)\n-   [Support additional bit widths](/proposals/p2015.md#additional-bit-sizes)\n\nRaw identifiers:\n\n-   [Other raw identifier syntaxes](/proposals/p3797.md#other-raw-identifier-syntaxes)\n-   [Restrict raw identifier syntax to current and future keywords](/proposals/p3797.md#restrict-raw-identifier-syntax-to-current-and-future-keywords)\n-   [Don't require syntax for references to raw identifiers](/proposals/p3797.md#dont-require-syntax-for-references-to-raw-identifiers)\n-   [Don't provide raw identifier syntax](/proposals/p3797.md#dont-provide-raw-identifier-syntax)\n\n## References\n\n-   Proposal\n    [#142: Unicode source files](https://github.com/carbon-language/carbon-lang/pull/142)\n-   Proposal\n    [#2015: Numeric type literal syntax](https://github.com/carbon-language/carbon-lang/pull/2015)\n-   Proposal\n    [#3797: Raw identifier syntax](https://github.com/carbon-language/carbon-lang/pull/3797)\n"
  },
  {
    "path": "docs/design/metaprogramming.md",
    "content": "# Metaprogramming\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [TODO](#todo)\n-   [Overview](#overview)\n\n<!-- tocstop -->\n\n## TODO\n\nThis is a skeletal design, added to support [the overview](README.md). It should\nnot be treated as accepted by the core team; rather, it is a placeholder until\nwe have more time to examine this detail. Please feel welcome to rewrite and\nupdate as appropriate.\n\nSee [proposal PR 89](https://github.com/carbon-language/carbon-lang/pull/89) for\ncontext -- that proposal may replace this.\n\n## Overview\n\nCarbon provides metaprogramming facilities that look similar to regular Carbon\ncode. These are structured, and do not offer inclusion or arbitrary\npreprocessing of source text such as C and C++ do.\n"
  },
  {
    "path": "docs/design/name_lookup.md",
    "content": "# Name lookup\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [TODO](#todo)\n-   [Overview](#overview)\n    -   [Unqualified name lookup](#unqualified-name-lookup)\n        -   [Alternatives](#alternatives)\n    -   [Name lookup for common, standard types](#name-lookup-for-common-standard-types)\n-   [Open questions](#open-questions)\n    -   [Shadowing](#shadowing)\n\n<!-- tocstop -->\n\n## TODO\n\nThis is a skeletal design, added to support [the overview](README.md). It should\nnot be treated as accepted by the core team; rather, it is a placeholder until\nwe have more time to examine this detail. Please feel welcome to rewrite and\nupdate as appropriate.\n\n## Overview\n\nNames are always introduced into some scope which defines where they can be\nreferenced. Many of these scopes are themselves named. Carbon has a special\nfacility for introducing a dedicated named scope just like C++, but we traverse\nnested names in a uniform way with `.`-separated names:\n\n```\nnamespace Foo {\n  namespace Bar {\n    alias ??? MyInt = Int;\n  }\n}\n\nfn F(x: Foo.Bar.MyInt);\n```\n\nCarbon packages are also namespaces so to get to an imported name from the\n`Abseil` package you would write `Abseil.Foo`. The \"top-level\" file scope is\nthat of the Carbon package containing the file, meaning that there is no\n\"global\" scope. Dedicated namespaces can be reopened within a package, but there\nis no way to reopen a package without being a library and file _within_ that\npackage.\n\nNote that libraries (unlike packages) do **not** introduce a scope, they share\nthe scope of their package. This is based on the observation that in practice, a\nfairly coarse scoping tends to work best, with some degree of global registry to\nestablish a unique package name.\n\n### Unqualified name lookup\n\nUnqualified name lookup in Carbon will always find a file-local result, other\nthan the implicit \"prelude\" of importing and aliasing the fundamentals of the\nstandard library. There will be an explicit mention of the name in the file that\ndeclares the name in the current or enclosing scope, which must also precede the\nreference.\n\n#### Alternatives\n\nThis implies that other names within your own package but not declared within\nthe file must be found by way of the package name. It isn't clear if this is the\ndesirable end state. We need to consider alternatives where names from the same\nlibrary or any library in the same package are made immediately visible within\nthe package scope for unqualified name lookup.\n\n### Name lookup for common, standard types\n\nThe Carbon standard library is in the `Core` package. A subset of this package,\ncalled the \"prelude\", is implicitly imported in every file, so the package name\n`Core` is always available.\n\nSome keywords and type literals, such as `bool` and `i32`, are aliases for\nentities in the prelude. Similarly, some of the Carbon language syntax, such as\noperators and `for` loops, is defined in terms of interfaces in the prelude.\n\n## Open questions\n\n### Shadowing\n\nWe can probably disallow the use of shadowed unqualified names, but the actual\ndesign for such needs to be thought through.\n"
  },
  {
    "path": "docs/design/naming_conventions.md",
    "content": "# Naming conventions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Details](#details)\n    -   [Constants](#constants)\n    -   [Carbon-provided item naming](#carbon-provided-item-naming)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nOur naming conventions are:\n\n-   For idiomatic Carbon code:\n    -   `UpperCamelCase` will be used when the named entity cannot have a\n        dynamically varying value. For example, functions, namespaces, or\n        compile-time constant values.\n    -   `lower_snake_case` will be used when the named entity's value won't be\n        known until runtime, such as for variables.\n-   For Carbon-provided features:\n    -   Keywords and type literals will use `lower_snake_case`.\n    -   Other code will use the guidelines for idiomatic Carbon code.\n\nIn other words:\n\n| Item                      | Convention         | Explanation                                                                                |\n| ------------------------- | ------------------ | ------------------------------------------------------------------------------------------ |\n| Packages                  | `UpperCamelCase`   | Used for compile-time lookup.                                                              |\n| Types                     | `UpperCamelCase`   | Resolved at compile-time.                                                                  |\n| Functions                 | `UpperCamelCase`   | Resolved at compile-time.                                                                  |\n| Methods                   | `UpperCamelCase`   | Methods, including virtual methods, are equivalent to functions.                           |\n| Compile-time parameters   | `UpperCamelCase`   | May vary based on inputs, but are ultimately resolved at compile-time.                     |\n| Compile-time constants    | `UpperCamelCase`   | Resolved at compile-time. See [constants](#constants) for more remarks.                    |\n| Variables                 | `lower_snake_case` | May be reassigned and thus require runtime information.                                    |\n| Member variables          | `lower_snake_case` | Behave like variables.                                                                     |\n| Keywords                  | `lower_snake_case` | Special, and developers can be expected to be comfortable with this casing cross-language. |\n| Type literals             | `lower_snake_case` | Equivalent to keywords.                                                                    |\n| Boolean type and literals | `lower_snake_case` | Equivalent to keywords.                                                                    |\n| Other Carbon types        | `UpperCamelCase`   | Behave like normal types.                                                                  |\n| `Self` and `Base`         | `UpperCamelCase`   | These are similar to type members on a class.                                              |\n\nWe only use `UpperCamelCase` and `lower_snake_case` in naming conventions in\norder to minimize the variation in rules.\n\n## Details\n\n### Constants\n\nConsider the following code:\n\n```carbon\npackage Example;\n\nlet CompileTimeConstant: i32 = 7;\n\nfn RuntimeFunction(runtime_constant: i32);\n```\n\nIn this example, `CompileTimeConstant` has a singular value (`7`) which is known\nat compile-time. As such, it uses `UpperCamelCase`.\n\nOn the other hand, `runtime_constant` may be constant within the function body,\nbut it is assigned at runtime when `RuntimeFunction` is called. Its value is\nonly known in a given runtime invocation of `RuntimeFunction`. As such, it uses\n`lower_snake_case`.\n\n### Carbon-provided item naming\n\nCarbon-provided items are split into a few categories:\n\n-   Keywords; for example, `for`, `fn`, and `var`.\n-   Type literals; for example, `i<digits>`, `u<digits>`, and `f<digits>`.\n-   Boolean type and literals; for example, `bool`, `true`, and `false`.\n    -   The separate categorization of booleans should not be taken as a rule\n        that only booleans would use lowercase; it's just the only example right\n        now.\n-   `Self` and `Base`.\n-   Other Carbon types; for example, `Int`, `UInt`, and `String`.\n\nNote that while other Carbon types currently use `UpperCamelCase`, that should\nnot be inferred to mean that future Carbon types will do the same. The leads\nwill make decisions on future naming.\n\n## Alternatives considered\n\n-   [Other naming conventions](/proposals/p0861.md#other-naming-conventions)\n-   [Other conventions for naming Carbon types](/proposals/p0861.md#other-conventions-for-naming-carbon-types)\n\n## References\n\n-   Proposal\n    [#861: Naming conventions](https://github.com/carbon-language/carbon-lang/pull/861)\n"
  },
  {
    "path": "docs/design/pattern_matching.md",
    "content": "# Pattern matching\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Pattern Syntax and Semantics](#pattern-syntax-and-semantics)\n    -   [Expression patterns](#expression-patterns)\n        -   [Alternatives considered](#alternatives-considered)\n    -   [Binding patterns](#binding-patterns)\n        -   [Name binding patterns](#name-binding-patterns)\n        -   [Anonymous bindings](#anonymous-bindings)\n            -   [Alternatives considered](#alternatives-considered-1)\n        -   [`auto` and type deduction](#auto-and-type-deduction)\n        -   [Alternatives considered](#alternatives-considered-2)\n    -   [`var`](#var)\n        -   [Alternatives considered](#alternatives-considered-3)\n    -   [`unused`](#unused)\n    -   [Tuple patterns](#tuple-patterns)\n    -   [Struct patterns](#struct-patterns)\n        -   [Alternatives considered](#alternatives-considered-4)\n    -   [Alternative patterns](#alternative-patterns)\n    -   [Templates](#templates)\n    -   [Refutability, overlap, usefulness, and exhaustiveness](#refutability-overlap-usefulness-and-exhaustiveness)\n        -   [Alternatives considered](#alternatives-considered-5)\n-   [Pattern usage](#pattern-usage)\n    -   [Pattern match control flow](#pattern-match-control-flow)\n        -   [Alternatives considered](#alternatives-considered-6)\n        -   [Guards](#guards)\n    -   [Pattern matching in local variables](#pattern-matching-in-local-variables)\n-   [Evaluation order](#evaluation-order)\n    -   [Alternatives considered](#alternatives-considered-7)\n-   [Open questions](#open-questions)\n    -   [Slice or array nested value pattern matching](#slice-or-array-nested-value-pattern-matching)\n    -   [Pattern matching as function overload resolution](#pattern-matching-as-function-overload-resolution)\n-   [Alternatives considered](#alternatives-considered-8)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nA _pattern_ is an expression-like syntax that describes the structure of some\nvalue. The pattern may contain unknowns, so it can potentially match multiple\nvalues, and those unknowns may have names, in which case they are called\n_binding patterns_. When a pattern is executed by giving it a value called the\n_scrutinee_, it determines whether the scrutinee matches the pattern, and if so,\ndetermines the values of the bindings.\n\nA _full pattern_ is a complete input to a pattern matching operation, that is a\npattern that is not a subpattern of another pattern. If it's preceded by a\ndeduced parameter list or followed by a return type expression, those are part\nof the full pattern as well.\n\n## Pattern Syntax and Semantics\n\nAll expressions are patterns, but they may be either tuple patterns, struct\npatterns, or expression patterns, as described below. A pattern that is not an\nexpression, because it contains pattern-specific syntax such as a binding\npattern, is a _proper pattern_. Many expression forms, such as arbitrary\nfunction calls, are not permitted as proper patterns, so cannot contain binding\npatterns.\n\n```carbon\nfn F(n: i32) -> i32 { return n; }\n\nmatch (F(42)) {\n  // ❌ Error: binding can't appear in a function call.\n  case (F(n: i32)) => {}\n}\n```\n\n### Expression patterns\n\nAn expression is a pattern.\n\n-   _expression-pattern_ ::= _expression_\n-   _pattern_ ::= _expression-pattern_\n\nThe scrutinee is compared with the expression using the `==` operator:\n_expression_ `==` _scrutinee_.\n\n```carbon\nfn F(n: i32) {\n  match (n) {\n    // ✅ Results in an `n == 5` comparison.\n    // OK despite `n` and `5` having different types.\n    case 5 => {}\n  }\n}\n```\n\nAs depicted here, _expression-pattern_ is ambiguous with _tuple-pattern_,\n_struct-pattern_, and _alternative-pattern_. In the case of _tuple-pattern_ and\n_struct-pattern_, the ambiguity is resolved in their favor, meaning that a tuple\nor struct literal in a pattern context is not interpreted as an expression\npattern, but as a tuple or struct pattern whose elements are expression\npatterns. For example:\n\n```carbon\nmatch (0, 1, 2) {\n  case (F(), 0, G()) => ...\n}\n```\n\nHere `(F(), 0, G())` is not an expression, but three separate expressions in a\ntuple pattern. As a result, this code will call `F()` but not `G()`, because the\nmismatch between the middle tuple elements will cause pattern matching to fail\nbefore reaching `G()`. Other than this short-circuiting behavior, a tuple\npattern of expression patterns behaves the same as if it were a single\nexpression pattern.\n\nThe resolution of the _alternative-pattern_ ambiguity is not specified, because\n_alternative-pattern_ is specified to behave the same way an expression pattern\nwould, in the cases where they overlap.\n\n#### Alternatives considered\n\n-   [Introducer syntax for expression patterns](/proposals/p2188.md#introducer-syntax-for-expression-patterns)\n\n### Binding patterns\n\n#### Name binding patterns\n\nA name binding pattern is a pattern.\n\n-   _binding-pattern_ ::= `ref`? (_identifier_ | `self`) `:` _expression_\n-   _binding-pattern_ ::= `template`? _identifier_ `:!` _expression_\n-   _pattern_ ::= _binding-pattern_\n\nA name binding pattern declares a _binding_ with a name specified by the\n_identifier_, which can be used as an expression. If the binding pattern is\nprefixed with `ref` or enclosed by a `var` pattern, it is a _reference binding\npattern_, and otherwise it is a _value binding pattern_. A binding pattern\nenclosed by a `var` pattern cannot have a `ref` prefix, because it would be\nredundant.\n\nA _variable binding pattern_ is a special kind of reference binding pattern,\nwhich is the immediate subpattern of its enclosing `var` pattern.\n\n> **TODO:** Specify the conditions under which a binding can be moved. This is\n> expected to be the only difference between variable binding patterns and other\n> reference binding patterns.\n\nIf the pattern syntax uses `:` it is a _runtime binding pattern_. If it uses\n`:!`, it is a _compile-time binding pattern_, and it cannot appear inside a\n`var` pattern. A compile-time binding pattern is either a _symbolic binding\npattern_ or a _template binding pattern_, depending on whether it is prefixed\nwith `template`.\n\nThe binding declared by a binding pattern has a\n[primitive form](values.md#expression-forms) with the following components:\n\n-   The type is _expression_.\n-   The category is \"value\" if the pattern is a value binding pattern, \"durable\n    entire reference\" if it's a variable binding pattern, or \"durable non-entire\n    reference\" if it's a non-variable reference binding pattern.\n-   The phase is \"runtime\", \"symbolic\", or \"template\" depending on whether the\n    pattern is a runtime, symbolic, or template binding pattern.\n\nDuring pattern matching, the scrutinee is implicitly converted as needed to have\nthe same form, and the binding is _bound_ to (and consumes) the result of these\nconversions. This makes a runtime or template binding a kind of reusable alias\nfor the converted scrutinee expression, with the same form and value. Symbolic\nbindings are more complex: the binding will have the same type, category, and\nphase as the converted scrutinee expression, but its constant value is an opaque\nsymbol introduced by the binding, which the type system knows to be equal to the\nconverted scrutinee expression.\n\nNote that there is no way to implicitly convert to a durable reference\nexpression from any other category, so the scrutinee of a reference binding\npattern must already be a durable reference. `var` pattern matching ensures that\nthis is the case for the bindings nested inside it, but for `ref` binding\npatterns the user-provided scrutinee must meet this requirement itself.\n\n```carbon\nfn F() -> i32 {\n  match (5) {\n    // ✅ `5` is implicitly converted to `i32`.\n    case n: i32 => {\n      // The binding `n` has the value `5 as i32`,\n      // which is the value returned.\n      return n;\n    }\n  }\n}\n```\n\nWhen `self` is used instead of an identifier, the pattern must appear in the\nimplicit parameter list of a method (as discussed [here](classes.md#methods)).\nDuring pattern matching in a method call, the parameter pattern containing\n`self` is matched with the object that the method was invoked on. In all other\nrespects, the `self` pattern behaves just like an ordinary binding pattern,\nintroducing a binding named `self` into scope, just as if `self` were an\nidentifier rather than a keyword.\n\n#### Anonymous bindings\n\nA syntax like a binding but with `_` in place of an identifier is an anonymous\nbinding. It does not participate in name lookup (so there can be multiple such\npatterns in the same scope), and in all other respects it behaves as if it were\nwrapped in an [`unused` pattern](#unused).\n\n-   _binding-pattern_ ::= `_` `:` _expression_\n-   _binding-pattern_ ::= `template`? `_` `:!` _expression_\n\n```carbon\nfn F(n: i32) {\n  match (n) {\n    // ✅ Matches and discards the value of `n`.\n    case _: i32 => {}\n    // ❌ Error: unreachable.\n    default => {}\n  }\n}\n```\n\nAs specified in [#1084](/proposals/p1084.md), function redeclarations may\nreplace binding names with `_`s but may not use different names.\n\n```carbon\nfn G(n: i32);\nfn H(n: i32);\nfn J(n: i32);\n\n// ✅ Does not use `n`.\nfn G(_: i32) {}\n// ❌ Error: name of parameter does not match declaration.\nfn H(m: i32) {}\n```\n\n##### Alternatives considered\n\n-   [Commented names](/proposals/p2022.md#commented-names)\n-   [Only short form support with `_`](/proposals/p2022.md#only-short-form-support-with-_)\n-   [Named identifiers prefixed with `_`](/proposals/p2022.md#named-identifiers-prefixed-with-_)\n-   [Anonymous, named identifiers](/proposals/p2022.md#anonymous-named-identifiers)\n-   [Attributes](/proposals/p2022.md#attributes)\n\n#### `auto` and type deduction\n\nThe `auto` keyword is a placeholder for a unique deduced type.\n\n-   _expression_ ::= `auto`\n\n```carbon\nfn F(n: i32) {\n  var v: auto = SomeComplicatedExpression(n);\n  // Equivalent to:\n  var w: T = SomeComplicatedExpression(n);\n  // ... where `T` is the type of the initializer.\n}\n```\n\nThe `auto` keyword is only permitted in specific contexts. Currently these are:\n\n-   As the return type of a function.\n-   As the type of a binding.\n\nIt is anticipated that `auto` may be permitted in more contexts in the future,\nfor example as a placeholder argument in a parameterized type that appears in a\ncontext where `auto` is allowed, such as `Vector(auto)` or `auto*`.\n\nWhen the type of a binding requires type deduction, the type is deduced against\nthe type of the scrutinee and deduced values are substituted back into the type\nbefore pattern matching is performed.\n\n```carbon\nfn G[T:! Type](p: T*);\nclass X { impl as ImplicitAs(i32*); }\n// ✅ Deduces `T = i32` then implicitly and\n// trivially converts `p` to `i32*`.\nfn H1(p: i32*) { G(p); }\n// ❌ Error, can't deduce `T*` from `X`.\nfn H2(p: X) { G(p); }\n```\n\nThe above is only an illustration; the behavior of type deduction is not yet\nspecified.\n\n#### Alternatives considered\n\n-   [Shorthand for `auto`](/proposals/p2188.md#shorthand-for-auto)\n\n### `var`\n\nA `var` prefix indicates that a pattern provides mutable storage for the\nscrutinee.\n\n-   _pattern_ ::= `var` _pattern_\n\nThe scrutinee is expected to have the same type as the resolved type of the\nnested _pattern_, and it is expected to be a runtime-phase ephemeral entire\nreference expression, which therefore refers to a newly-allocated temporary\nobject. The scrutinee expression is converted as needed to satisfy those\nexpectations, and the `var` pattern takes ownership of the referenced object,\npromotes it to a _durable_ entire reference expression, and matches the nested\n_pattern_ with it.\n\nThe lifetime of the allocated object extends to the end of scope of the `var`\npattern (that is the scope that any bindings declared within it would have).\n\n```carbon\nfn F(p: i32*);\nfn G() {\n  match ((1, 2)) {\n    // `n` is a mutable `i32`.\n    case (var n: i32, 1) => { F(&n); }\n    // `n` and `m` are the elements of a mutable `(i32, i32)`.\n    case var (n: i32, m: i32) => { F(if n then &n else &m); }\n  }\n}\n```\n\nA `var` pattern cannot be nested within another `var` pattern. The declaration\nsyntax `var` _pattern_ `=` _expresson_ `;` is equivalent to `let` `var`\n_pattern_ `=` _expression_ `;`.\n\n#### Alternatives considered\n\n-   [Treat all bindings under `var` as variable bindings](/proposals/p5164.md#treat-all-bindings-under-var-as-variable-bindings)\n-   [Make `var` a binding pattern modifier](/proposals/p5164.md#make-var-a-binding-pattern-modifier)\n-   [Initialize storage once pattern matching succeeds](/proposals/p5164.md#initialize-storage-once-pattern-matching-succeeds)\n\n### `unused`\n\nWhen a name introduced by a binding is not used, a warning is issued. It is\npossible to avoid the warning while keeping a name, by using an `unused` marker.\n\nAn `unused` marker indicates that all names in a pattern are visible for name\nlookup but uses are invalid. This includes situations when they cause ambiguous\nname lookup errors. If attempted to be used, a compiler error will be shown to\nthe user, instructing them to either remove the `unused` qualifier or remove the\nuse.\n\n-   _proper-pattern_ ::= `unused` _proper-pattern_\n\nAn `unused` marker can be applied to any pattern and it will apply to all name\nbindings in a pattern. Nesting `unused` markers is an error. When an `unused`\nmarker applies only to anonymous bindings `_` and is thus redundant, a warning\nis produced. `var` and `unused` may appear in any order in a pattern.\n\nAs specified in [#3763](/proposals/p3763.md), `unused` markers may only appear\non definitions, not on non-defining declarations. Function redeclarations that\nare also definitions may have difference due to `unused` markers, but they may\nnot have different names.\n\n```carbon\nfn J(n: i32);\n\n// ✅ Does not use `n`.\nfn J(unused n: i32) { ... };\n\nfn G() {\n  match ((1, 2)) {\n    // `x` is unused\n    case (var n: i32, unused x: i32) => { F(&n); }\n    // `n` and `m` are both unused\n    case unused (n: i32, m: i32) => { J(42); }\n  }\n}\n```\n\n### Tuple patterns\n\nA tuple of patterns can be used as a pattern.\n\n-   _tuple-pattern_ ::= `(` [_pattern_ `,` [_pattern_ [`,` _pattern_]\\* `,`? ] ]\n    `)`\n-   _pattern_ ::= _tuple-pattern_\n\nThe scrutinee is required to be of tuple type, with the same arity as the number\nof nested _patterns_. It is converted to a tuple form by\n[form decomposition](values.md#form-conversions), and then each nested _pattern_\nis matched against the corresponding element of the converted scrutinee's\n[result](values.md#expression-forms). The tuple pattern matches if all of these\nsub-matches succeed.\n\n### Struct patterns\n\nA struct can be matched with a struct pattern.\n\n-   _struct-pattern_ ::= `{` [_field-pattern_ [`,` _field-pattern_ ]\\* ] `}`\n-   _struct-pattern_ ::= `{` [_field-pattern_ `,`]+ `_` `}`\n-   _field-pattern_ ::= _designator_ `=` _pattern_\n-   _field-pattern_ ::= _binding-pattern_\n-   _pattern_ ::= _struct-pattern_\n\nA struct pattern resembles a struct literal, except that the initializers can be\npatterns.\n\n```carbon\nmatch ({.a = 1, .b = 2}) {\n  // Struct literal as a pattern.\n  case {.b = 2, .a = 1} => {}\n  // Proper struct pattern.\n  case {.b = n: i32, .a = m: i32} => {}\n}\n```\n\nThe scrutinee is required to be of struct type, and every field name in the\npattern must be a field name in the scrutinee. It is converted to a struct form\nby [form decomposition](values.md#form-conversions) and then each\n_field-pattern_ is matched with the same-named element of the converted\nscrutinee's [result](values.md#expression-forms). If the scrutinee result has\nany field names not present in the pattern, those sub-results are\n[discarded](values.md#form-conversions) in lexical order if the pattern has a\ntrailing `_` (as in `{.a = 1, _}`), or diagnosed as an error if it does not. The\nstruct pattern matches if all of these sub-matches succeed.\n\nIn the case where a field will be bound to an identifier with the same name, a\nshorthand syntax is available: `a: T` is synonymous with `.a = a: T`.\n\n```carbon\nmatch ({.a = 1, .b = 2}) {\n  case {a: i32, b: i32} => { return a + b; }\n}\n```\n\nLikewise, `ref a: T` is synonymous with `.a = ref a: T`, and `var a: T` is\nsynonymous with `.a = var a: T`.\n\nIf some fields should be ignored when matching, a trailing `, _` can be added to\nspecify this:\n\n```carbon\nmatch ({.a = 1, .b = 2}) {\n  case {.a = 1, _} => { return 1; }\n  case {b: i32, _} => { return b; }\n}\n```\n\nThis is valid even if all fields are actually named in the pattern.\n\n#### Alternatives considered\n\n-   [Struct pattern syntax](/proposals/p2188.md#struct-pattern-syntax)\n\n### Alternative patterns\n\nAn alternative pattern is used to match one alternative of a choice type.\n\n-   _alternative-pattern_ ::= _callee-expression_ _tuple-pattern_?\n-   _alternative-pattern_ ::= _designator_ _tuple-pattern_? \\_ _pattern_ ::=\n    _alternative-pattern_\n\nHere, _callee-expression_ is syntactically an expression that is valid as the\ncallee in a function call expression, and an alternative pattern is\nsyntactically a function call expression whose argument list may contain proper\npatterns.\n\nSemantically, if the argument list contains no proper patterns, it behaves like\nan expression pattern. Otherwise, if a _callee-expression_ is provided, it is\nrequired to name a choice type alternative that has a parameter list, and the\nscrutinee is implicitly converted to that choice type. Otherwise, the scrutinee\nis required to be of some choice type, and the designator is looked up in that\ntype and is required to name an alternative with a parameter list if and only if\na _tuple-pattern_ is specified.\n\nThe pattern matches if the active alternative in the scrutinee is the specified\nalternative, and the arguments of the alternative match the given tuple pattern\n(if any).\n\n```carbon\nchoice Optional(T:! Type) {\n  None,\n  Some(T)\n}\n\nmatch (Optional(i32).None) {\n  // ✅ `.None` resolved to `Optional(i32).None`.\n  case .None => {}\n  // ✅ `.Some` resolved to `Optional(i32).Some`.\n  case .Some(n: i32) => { Print(\"{0}\", n); }\n  // ❌ Error, no such alternative exists.\n  case .Other => {}\n}\n\nclass X {\n  impl as ImplicitAs(Optional(i32));\n}\n\nmatch ({} as X) {\n  // ✅ OK, but expression pattern.\n  case Optional(i32).None => {}\n  // ✅ OK, implicitly converts to `Optional(i32)`.\n  case Optional(i32).Some(n: i32) => { Print(\"{0}\", n); }\n}\n```\n\nNote that a pattern of the form `Optional(T).None` is an expression pattern and\nis compared using `==`.\n\n### Templates\n\nAny checking of the type of the scrutinee against the type of the pattern that\ncannot be performed because the type of the scrutinee involves a template\nparameter is deferred until the template parameter's value is known. During\ninstantiation, patterns that are not meaningful due to a type error are instead\ntreated as not matching. This includes cases where an `==` fails because of a\nmissing `EqWith` implementation.\n\n```carbon\nfn TypeName[template T:! Type](x: T) -> String {\n  match (x) {\n    // ✅ OK, the type of `x` is a template parameter.\n    case _: i32 => { return \"int\"; }\n    case _: bool => { return \"bool\"; }\n    case _: auto* => { return \"pointer\"; }\n    default => { return \"unknown\"; }\n  }\n}\n```\n\nCases where the match is invalid for reasons not involving the template\nparameter are rejected when type-checking the template:\n\n```carbon\nfn MeaninglessMatch[template T:! Type](x: T*) {\n  match (*x) {\n    // ✅ OK, `T` could be a tuple.\n    case (_: auto, _: auto) => {}\n    default => {}\n  }\n  match (x->y) {\n    // ✅ OK, `T.y` could be a tuple.\n    case (_: auto, _: auto) => {}\n    default => {}\n  }\n  match (x) {\n    // ❌ Error, tuple pattern cannot match value of non-tuple type `T*`.\n    case (_: auto, _: auto) => {}\n    default => {}\n  }\n}\n```\n\n### Refutability, overlap, usefulness, and exhaustiveness\n\nSome definitions:\n\n-   A pattern _P_ is _useful_ in the context of a set of patterns _C_ if there\n    exists a value that _P_ can match that no pattern in _C_ matches.\n-   A set of patterns _C_ is _exhaustive_ if it matches all possible values.\n    Equivalently, _C_ is exhaustive if the pattern `_: auto` is not useful in\n    the context of _C_.\n-   A pattern _P_ is _refutable_ if there are values that it does not match,\n    that is, if the pattern `_: auto` is useful in the context of {_P_}.\n    Equivalently, the pattern _P_ is _refutable_ if the set of patterns {_P_} is\n    not exhaustive.\n-   A set of patterns _C_ is _overlapping_ if there exists any value that is\n    matched by more than one pattern in _C_.\n\nFor the purpose of these terms, expression patterns that match a constant tuple,\nstruct, or choice value are treated as if they were tuple, struct, or\nalternative patterns, respectively, and `bool` is treated like a choice type.\nAny expression patterns that remain after applying this rule are considered to\nmatch a single value from an infinite set of values so that a set of expression\npatterns is never exhaustive:\n\n```carbon\nfn IsEven(n: u8) -> bool {\n  // Not considered exhaustive.\n  match (n) {\n    case 0 => { return true; }\n    case 1 => { return false; }\n    ...\n    case 255 => { return false; }\n  }\n  // Code here is considered to be reachable.\n}\n```\n\n```carbon\nfn IsTrue(b: bool) -> bool {\n  // Considered exhaustive.\n  match (b) {\n    case false => { return false; }\n    case true => { return true; }\n  }\n  // Code here is considered to be unreachable.\n}\n```\n\nWhen determining whether a pattern is useful, no attempt is made to determine\nthe value of any guards, and instead a worst-case assumption is made: a guard on\nthat pattern is assumed to evaluate to true and a guard on any pattern in the\ncontext set is assumed to evaluate to false.\n\nWe will diagnose the following situations:\n\n-   A pattern is not useful in the context of prior patterns. In a `match`\n    statement, this happens if a pattern or `default` cannot match because all\n    cases it could cover are handled by prior cases or a prior `default`. For\n    example:\n\n    ```carbon\n    choice Optional(T:! Type) {\n      None,\n      Some(T)\n    }\n    fn F(a: Optional(i32), b: Optional(i32)) {\n      match ((a, b)) {\n        case (.Some(a: i32), _: auto) => {}\n        // ✅ OK, but only matches values of the form `(None, Some)`,\n        // because `(Some, Some)` is matched by the previous pattern.\n        case (_: auto, .Some(b: i32)) => {}\n        // ✅ OK, matches all remaining values.\n        case (.None, .None) => {}\n        // ❌ Error, this pattern never matches.\n        case (_: auto, _: auto) => {}\n      }\n    }\n    ```\n\n-   A pattern match is not exhaustive and the program doesn't explicitly say\n    what to do when no pattern matches. For example:\n\n    -   If the patterns in a `match` are not exhaustive and no `default` is\n        provided.\n\n        ```carbon\n        fn F(n: i32) -> i32 {\n          // ❌ Error, this `match` is not exhaustive.\n          match (n) {\n            case 0 => { return 2; }\n            case 1 => { return 3; }\n            case 2 => { return 5; }\n            case 3 => { return 7; }\n            case 4 => { return 11; }\n          }\n        }\n        ```\n\n    -   If a refutable pattern appears in a context where only one pattern can\n        be specified, such as a `let` or `var` declaration, and there is no\n        fallback behavior. This currently includes all pattern matching contexts\n        other than `match` statements, but the `var`/`let`-`else` feature in\n        [#1871](https://github.com/carbon-language/carbon-lang/pull/1871) would\n        introduce a second context permitting refutable matches, and overloaded\n        functions might introduce a third context.\n\n        ```carbon\n        fn F(n: i32) {\n          // ❌ Error, refutable expression pattern `5` used in context\n          // requiring an irrefutable pattern.\n          var 5 = n;\n        }\n        // ❌ Error, refutable expression pattern `5` used in context\n        // requiring an irrefutable pattern.\n        fn G(n: i32, 5);\n        ```\n\n-   When a set of patterns have no ordering or tie-breaker, it is an error for\n    them to overlap unless there is a unique best match for any value that\n    matches more than one pattern. However, this situation does not apply to any\n    current language rule:\n\n    -   For `match` statements, patterns are matched top-down, so overlap is\n        permitted.\n    -   We do not yet have an approved design for overloaded functions, but it\n        is anticipated that declaration order will be used in that case too.\n    -   For a set of `impl`s that match a given `impl` lookup, argument\n        deduction is used rather than pattern matching, but `impl`s with the\n        same type structure are an error unless a `match_first` declaration is\n        used to order the `impl`s.\n\n#### Alternatives considered\n\n-   [Treat expression patterns as exhaustive if they cover all possible values](/proposals/p2188.md#treat-expression-patterns-as-exhaustive-if-they-cover-all-possible-values)\n-   [Allow non-exhaustive `match` statements](/proposals/p2188.md#allow-non-exhaustive-match-statements)\n\n## Pattern usage\n\n### Pattern match control flow\n\n`match` is a skeletal design, added to support [the overview](README.md). Aside\nfrom [guards](#guards), it should not be treated as accepted by the core team;\nrather, it is a placeholder until we have more time to examine this detail.\nPlease feel welcome to rewrite and update as appropriate.\n\nThe most powerful form and easiest to explain form of pattern matching is a\ndedicated control flow construct that subsumes the `switch` of C and C++ into\nsomething much more powerful, `match`. This is not a novel construct, and is\nwidely used in existing languages (Swift and Rust among others) and is currently\nunder active investigation for C++. Carbon's `match` can be used as follows:\n\n```carbon\nfn Bar() -> (i32, (f32, f32));\nfn Foo() -> f32 {\n  match (Bar()) {\n    case (42, (x: f32, y: f32)) => {\n      return x - y;\n    }\n    case (p: i32, (x: f32, _: f32)) if (p < 13) => {\n      return p * x;\n    }\n    case (p: i32, _: auto) if (p > 3) => {\n      return p * Pi;\n    }\n    default => {\n      return Pi;\n    }\n  }\n}\n```\n\nThere is a lot going on here. First, let's break down the core structure of a\n`match` statement. It accepts a value that will be inspected, here the result of\nthe call to `Bar()`. It then will find the _first_ `case` that matches this\nvalue, and execute that block. If none match, then it executes the default\nblock.\n\nEach `case` contains a pattern. The first part is a value pattern\n(`(p: i32, _: auto)` for example) optionally followed by an `if` and boolean\npredicate. The value pattern has to match, and then the predicate has to\nevaluate to `true` for the overall pattern to match. Value patterns can be\ncomposed of the following:\n\n-   An expression (`42` for example), whose value must be equal to match.\n-   An identifier to bind the value to, followed by a colon (`:`) and a type\n    (`i32` for example). An underscore (`_`) may be used instead of the\n    identifier to discard the value once matched.\n-   A tuple destructuring pattern containing a tuple of value patterns\n    (`(x: f32, y: f32)`) which match against tuples and tuple-like values by\n    recursively matching on their elements.\n-   An unwrapping pattern containing a nested value pattern which matches\n    against a variant or variant-like value by unwrapping it.\n\nIn order to match a value, whatever is specified in the pattern must match.\nUsing `auto` for a type will always match, making `_: auto` the wildcard\npattern.\n\nIf the scrutinee expression's [form](values.md#expression-forms) contains any\nprimitive forms with category \"initializing\", they are converted to ephemeral\nnon-entire reference expressions by\n[materialization](values.md#temporary-materialization) before pattern matching\nbegins, so that the result can be reused by multiple `case`s. However, the\nobjects created by `var` patterns are not reused by multiple `case`s:\n\n```carbon\nclass X {\n  destructor { Print(\"Destroyed!\"); }\n}\nfn F(x: X) {\n  match ((x, 1 as i32)) {\n    // Prints \"Destroyed!\" here, because `y` is initialized before we reach the\n    // expression pattern `0` and determine that this case doesn't match,\n    // so it must be destroyed.\n    case (var y: X, 0) => {}\n    case (var z: X, 1) => {\n      // Prints \"Destroyed!\" again at the end of the block here, when `z` goes\n      // out of scope.\n    }\n  }\n}\n```\n\n#### Alternatives considered\n\n-   [Allow variable binding patterns to alias across `case`s](/proposals/p5164.md#allow-variable-binding-patterns-to-alias-across-cases)\n\n#### Guards\n\nWe allow `case`s within a `match` statement to have _guards_. These are not part\nof pattern syntax, but instead are specific to `case` syntax:\n\n-   _case_ ::= `case` _pattern_ [`if` _expression_]? `=>` _block_\n\nA guard indicates that a `case` only matches if some predicate holds. The\nbindings in the pattern are in scope in the guard:\n\n```carbon\nmatch (x) {\n  case (m: i32, n: i32) if m + n < 5 => { return m - n; }\n}\n```\n\nFor consistency, this facility is also available for `default` clauses, so that\n`default` remains equivalent to `case _: auto`.\n\n### Pattern matching in local variables\n\nValue patterns may be used when declaring local variables to conveniently\ndestructure them and do other type manipulations. However, the patterns must\nmatch at compile time, so they can't use an `if` clause.\n\n```carbon\nfn Bar() -> (i32, (f32, f32));\nfn Foo() -> i32 {\n  var (p: i32, _: auto) = Bar();\n  return p;\n}\n```\n\nThis extracts the first value from the result of calling `Bar()` and binds it to\na local variable named `p` which is then returned.\n\n## Evaluation order\n\nA pattern matching operation's potentially-observable side effects are a series\nof calls to functions that might be user-defined. This includes function calls\nand operators in the scrutinee and in expression patterns, and also type\nconversions and category conversions. Note that category conversions on tuple\nand struct types, and type conversions between tuple and struct types, are not\nmodeled as function calls, but are broken down into function calls on their\nelements. Note also that for function and operator calls in expressions, we are\nonly considering top-level calls, that is calls that aren't inputs to other\ncalls within the expression, because the entire sub-expression of a top-level\ncall acts as a single unit for purposes of evaluation ordering.\n\nFor example, suppose `A` is implicitly convertible to a `C` and `B` is\nimplicitly convertible to `D`, but both conversions are value expressions\n(rather than initializing expressions), and consider the following code:\n\n```\nfn MakeA() -> A;\nfn MakeB() -> B;\n\nvar cd: (C, D) = (MakeA(), MakeB());\n```\n\nEvaluation of the last line involves 6 function calls:\n\n1. Call `MakeA`.\n2. Call `A.(Core.ImplicitAsPrimitive(C)).Convert`, to convert the `A` object to\n   a `C` value, as part of type conversion.\n3. Call `A.(Core.Copy).Op` to copy the `C` value into the storage for `cd.0`, as\n   part of category conversion.\n4. Call `MakeB`.\n5. Call `B.(Core.ImplicitAsPrimitive(D)).Convert`.\n6. Call `B.(Core.Copy).Op`.\n\n> **Note:** These `Core` interfaces haven't been specified yet, and their\n> details may change.\n\nTo define the evaluation order of these calls, we have to consider the\ndependencies between them, which we'll model as a DAG, with function calls as\nnodes, and edges representing data dependencies. It will also be useful to\ninclude leaf patterns (that is, patterns that have no subpatterns) as nodes in\nthe graph; they don't have side effects as such, so they aren't part of the\nevaluation order, but they do constrain the evaluation order.\n\n```mermaid\n%%{init: {'themeVariables': {'fontFamily': 'monospace'}}}%%\nflowchart BT\n  2[\"A.(Core.ImplicitAsPrimitive(C))\"]-->1[/\"MakeA\"\\]\n  3[\"A.(Core.Copy)\"]-->2\n  5[\"B.(Core.ImplicitAsPrimitive(D))\"]-->4[/\"MakeB\"\\]\n  6[\"B.(Core.Copy)\"]-->5\n  7[\\\"cd: (C, D)\"/]-->3\n  7-->6\n```\n\nThis DAG will always have a few key properties:\n\n-   The sources are the primitive patterns. Only the sources can have multiple\n    out-edges.\n-   The sinks are function calls in the scrutinee expression, and in expression\n    patterns. Only scrutinee expression sinks can have multiple in-edges.\n-   The interior nodes always have one edge in and one edge out, forming a set\n    of paths that connect a source to a sink.\n-   The paths to calls in expression patterns are trivial: they consist of a\n    single edge from an expression pattern source to a function call sink.\n    Furthermore, a given source or sink has at most one such edge.\n-   Each path to the scrutinee connects a type in the pattern to a type in the\n    scrutinee, and together the paths uniquely cover the entire pattern and\n    scrutinee types. Furthermore, they are minimal, in the sense that unless the\n    path is a single edge, its source and sink types won't both be tuple or\n    struct types.\n\n> **Future work:** this design needs to be reconciled with the design for\n> [user-defined sum types](sum_types.md#user-defined-sum-types), because\n> `Match.Op` can violate this topology. This should probably be folded into a\n> broader redesign of sum type customization, which we expect to be necessary\n> for other reasons.\n\nThe order of evaluation is determined by a depth-first postorder traversal of\nthe this DAG: while visiting a node, we recursively visit all its children, and\na call occurs when we finish visiting the corresponding node (revisiting a node\nis a no-op). By eagerly consuming the result of each function call as soon as\npossible, this minimizes the number of simultaneously-live temporaries, which\nenables more efficient code generation.\n\nWhen visiting a pattern, we visit its out-paths in the scrutinee type's\nleft-to-right source code order (recall that each path is associated with a\nunique part of the scrutinee type). An edge to an expression pattern call, if\nany, is visited last. The patterns themselves are visited in their own\nleft-to-right source code order. So, returning to our earlier example, the 6\nfunction calls will be evaluated in the order we listed them.\n\nIn some cases, visiting the patterns in their own order may lead to visiting the\ntypes within a scrutinee call out of order, but if it would lead to visiting the\nscrutinee calls themselves out of order, the program is ill-formed. For example:\n\n```carbon\n// ❌ Error: visiting `.c: C` first leads to evaluating `MakeA()` before\n// `MakeB()`\nvar {c: C, d: D} = {.d = MakeB(), .c = MakeA()};\n\n// ✅ OK: only one pattern, and we use scrutinee order to visit its children.\nvar cd: {.c: C, .d: D} = {.d = MakeB(), .c = MakeA()};\n\n// ✅ OK: only one scrutinee call, so it can't be out of order.\nfn MakeAB() -> {.d: B, .c: A};\nvar {c: C, d: D} = MakeAB();\n```\n\nAs a result, the overall evaluation order is always consistent with the written\norder of the patterns, and with the written order of the scrutinee expressions.\nWithin those constraints, the order of the scrutinee types acts as a\ntie-breaker. Note in particular that this means the fields of a struct-type\nbinding are not necessarily initialized in declaration order.\n\nNote that generally speaking, pattern-match evaluation stops as soon as it's\nknown that the match will fail, in which case only a prefix of the full\nevaluation order will be evaluated.\n\n### Alternatives considered\n\n-   [Breadth-first evaluation order](/proposals/p5545.md#breadth-first-evaluation-order)\n-   [Depth-first evaluation with a different \"horizontal\" order](/proposals/p5545.md#depth-first-evaluation-with-a-different-horizontal-order)\n\n## Open questions\n\n### Slice or array nested value pattern matching\n\nAn open question is how to effectively fit a \"slice\" or \"array\" pattern into\nnested value pattern matching, or whether we shouldn't do so.\n\n### Pattern matching as function overload resolution\n\nNeed to flesh out specific details of how overload selection leverages the\npattern matching machinery, what (if any) restrictions are imposed, etc.\n\n## Alternatives considered\n\n-   [Type pattern matching](/proposals/p2188.md#type-pattern-matching)\n-   [Allow guards on arbitrary patterns](/proposals/p2188.md#allow-guards-on-arbitrary-patterns)\n\n## References\n\n-   Proposal\n    [#2022: Unused Pattern Bindings (Unused Function Parameters)](https://github.com/carbon-language/carbon-lang/pull/2022)\n-   Proposal\n    [#2188: Pattern matching syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2188)\n"
  },
  {
    "path": "docs/design/safety/README.md",
    "content": "# Safety\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Safe and unsafe code](#safe-and-unsafe-code)\n-   [Safety modes](#safety-modes)\n-   [Memory safety model](#memory-safety-model)\n    -   [Data races versus unsynchronized temporal safety](#data-races-versus-unsynchronized-temporal-safety)\n-   [Safe library ecosystem](#safe-library-ecosystem)\n-   [Build modes](#build-modes)\n-   [Constraints](#constraints)\n    -   [Probabilistic techniques likely cannot stop attacks](#probabilistic-techniques-likely-cannot-stop-attacks)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nOne of Carbon's core goals is [practical safety]. This is referring to _[code\nsafety]_\nas opposed to the larger space of [systems safety]. The largest aspect of code safety\nat the language level is [memory safety], but this also applies to other aspects\nof code safety such as avoiding undefined behavior in other forms.\n\n[practical safety]:\n    /docs/project/goals.md#practical-safety-and-testing-mechanisms\n[code safety]:\n    /docs/design/safety/terminology.md#code-software-or-program-safety\n[systems safety]: /docs/design/safety/terminology.md#safety\n[memory safety]: /docs/design/safety/terminology.md#memory-safety\n\nHowever, Carbon also has a goal of fine grained, smooth interop-with and\nmigration-from existing C++ code, and C++ is a fundamentally unsafe language. It\nhas pervasive sources of undefined behavior and minimal memory safety\nguarantees. Our safety strategy has to address how C++ code fits into it, and\nprovide an incremental path from where the code is at today towards increasing\nlevels of safety.\n\nUltimately, Carbon will both provide a [memory-safe language], _and_ provide a language\nthat is a target for mechanical migration from C++ and optimizes even further for\ninterop with unsafe C++ with minimal friction.\n\n[memory-safe language]: /docs/design/safety/terminology.md#memory-safe-language\n\n## Safe and unsafe code\n\nCarbon will have both _safe_ and _unsafe_ code. Safe code provides limits on the\npotential behavior of the program even in the face of bugs in order to prevent\n[safety bugs] from becoming [vulnerabilities]. Unsafe code is any code or operation\nwhich lacks limits or guarantees on behavior, and as a consequence may have undefined\nbehavior or be a safety bug.\n\n[safety bugs]: /docs/design/safety/terminology.md#safety-bugs\n[vulnerabilities]:\n    /docs/design/safety/terminology.md#vulnerability-or-security-vulnerability\n\nAll things being equal, safe code constructs are preferable to unsafe\nconstructs, but many unsafe constructs are necessary. Where unsafe constructs\nare needed, Carbon follows three principles to incorporate them into the\nlanguage:\n\n-   The unsafe capabilities provided should be semantically narrow: only the\n    minimal unsafe operation to achieve the desired result.\n-   The unsafe code should be syntactically narrow and separable from\n    surrounding safe code.\n-   There should be a reasonable way of including the keyword `unsafe` in\n    whatever syntax is used so that this keyword can be used as a common\n    annotation in audits and review.\n\nThe result is that we don't model large regions or sections of Carbon code as\n\"unsafe\" or have a parallel \"unsafe\" variant language. We instead focus on the\nnarrow and specific unsafe operations and constructs.\n\nNote that when we're talking about the narrow semantics of an unsafe capability,\nthese are the semantics of the specific unsafe operation. For example, an unsafe\ntype conversion shouldn't also allow unsafe out-of-lifetime access. This is\nseparate from the _soundness_ implications of an unsafe operation, which may not\nbe as easily narrowed.\n\n> **Future work**: More fully expand on the soundness principles and model for\n> safe Carbon code. This is an interesting and important area of the design that\n> isn't currently fleshed out in detail.\n\n## Safety modes\n\nThe _safety mode_ of Carbon governs the extent to which unsafe code must include\nthe local `unsafe` keyword in its syntax to delineate it from safe code.\n\n_Strict Carbon_ is the mode in which all unsafe code is marked with the `unsafe`\nkeyword. This mode is designed to satisfy the requirements of a [memory\nsafe language].\n\n_Permissive Carbon_ is a mode optimized for interop with C++ and automated\nmigration from C++. In this mode, some unsafe code does not require an `unsafe`\nkeyword: specific aspects of C++ interop or pervasive patterns that occur when\nmigrating from C++. However, not _all_ unsafe code will omit the keyword, the\npermissive mode is designed to be minimal in the unsafe code allowed.\n\nModes can be configured on an individual file as part of the package\ndeclaration, or an a function body as part of the function definition. More\noptions such as regions of declarations or regions of statements can be explored\nin the future based on demand in practice when working with mixed-strictness\ncode. More fine grained than statements is not expected given that the same core\nexpressivity is available at that finer granularity through explicitly marking\n`unsafe` operations.\n\n> **Future work**: Define the exact syntax for package declaration and function\n> definition control of strictness. The syntax for enabling the permissive mode\n> must include the `unsafe` keyword as it is standing in place of more granular\n> use of the `unsafe` keywords and needs to still be discovered when auditing\n> for safety.\n\n> **Future work**: Define how to mark `import`s of permissive libraries in\n> various contexts, balancing ergonomic burden against the potential for\n> surprising amounts of unsafety in dependencies.\n\n## Memory safety model\n\nCarbon will use a hybrid of different techniques to achieve memory safety in its\nsafe code, largely broken down by the categories of memory safety:\n\n-   [Type safety]: compile-time enforcement, the same as other statically typed languages\n    with generic type systems.\n-   [Initialization safety]: hybrid of run-time and compile-time enforcement.\n-   [Spatial safety]: run-time enforcement.\n-   [Temporal safety]: compile-time enforcement through its type system.\n-   [Data-race safety]: compile-time enforcement through its type system.\n\n[type safety]: /docs/design/safety/terminology.md#type-safety\n[initialization safety]:\n    /docs/design/safety/terminology.md#initialization-safety\n[spatial safety]: /docs/design/safety/terminology.md#spatial-safety\n[temporal safety]: /docs/design/safety/terminology.md#temporal-safety\n[data-race safety]: /docs/design/safety/terminology.md#data-race-safety\n\n**At this high level, this means Carbon's memory safety model will largely match\nRust's.** The only minor deviation at this level from Rust is the use of\nrun-time enforcement for initialization, where Carbon will more heavily leverage\nrun-time techniques such as automatic initialization and dynamic \"optional\"\nsemantics to improve the ergonomics in Carbon.\n\nHowever, Carbon and Rust will have substantial differences in the _details_ of\nhow they approach both temporal and data-race safety.\n\n### Data races versus unsynchronized temporal safety\n\nCarbon has the option of distinguishing between two similar but importantly\ndifferent classes of bugs: data races and unsynchronized temporal safety\nviolations. Specifically, there is no evidence from security teams that there is\nany significant volume of vulnerabilities that involve a data race bug but don't\nalso involve a temporal memory safety violation. For example, despite both Go\nand non-strict-concurrency Swift only providing temporal safety, the rate of\nmemory safety vulnerabilities in software written in both matches the expected\nlow rate for memory-safe languages. As a consequence, Carbon has some\nflexibility while still being a [memory-safe language] according to our definition:\n\n-   Carbon might choose to _not_ prevent data race bugs that are not\n    _themselves_ also temporal safety bugs, even though the data race may lead\n    to corruption and cause the program to later violate various other forms of\n    memory safety. So far, evidence has not shown this to be as significant and\n    prevalent source of _vulnerabilities_ as other forms of memory safety bugs.\n-   However, Carbon _must_ detect and prevent cases where a lack of\n    synchronization directly allows temporal safety bugs, such as use after\n    free.\n\nDespite having this flexibility, preventing data race bugs remains _highly\nvaluable_ for correctness, debugging, and achieving [fearless concurrency]. If Carbon\ncan, it should work to prevent data races as well.\n\n[fearless concurrency]: https://doc.rust-lang.org/book/ch16-00-concurrency.html\n\n## Safe library ecosystem\n\nCarbon will need access to memory-safe library ecosystems, both for\ngeneral-purpose, multi-platform functionality and for platform-specific\nfunctionality. Currently, the industry is currently investing a massive amount\nof effort to build out a sufficient ecosystem of general, multi-platform\nsoftware using Rust, and it is critical that Carbon does not impede, slow down,\nor require duplicating that ecosystem. Similarly, if any other cross-platform\nlibrary ecosystems emerge in any viable memory-safe languages given our\nperformance constraints, we should work to reuse them and avoid duplication.\n\n**Carbon's strategy for safe and generally reusable cross-platform libraries is\nto leverage Rust libraries through interop.** This is a major motivating reason\nfor seamless and safe Rust interop. The Carbon project will work to avoid\ncreating duplication between the growing Rust library ecosystem and any future\nCarbon library ecosystem. Carbon's ecosystem will be focused instead on\nlibraries and functionality that would either be missing or only available in\nC++.\n\nPlatform-specific functionality is typically developed in that platform's native\nlanguage, whether that is Swift for Apple platforms or Kotlin for Android.\nAgain, the goal of Carbon should be to avoid duplicating functionality, and\ninstead to prioritize high quality interop with the existing platform libraries\nin the relevant languages on those platforms.\n\n## Build modes\n\nWhere Carbon's safety mode governs the language rules applied to unsafe code,\nCarbon's build modes will change the _behavior_ of unsafe code.\n\nThere are two primary build modes:\n\n-   **Release**: the primary build mode for programs in production, focuses on\n    giving the best possible performance with a practical baseline of safety.\n-   **Debug**: the primary build mode during development, focuses on\n    high-quality developer experience.\n\nThe release build will include a baseline of hardening necessary to uphold the\nrun-time enforcement components of our\n[memory safety model](#memory-safety-model) above. This means, for example, that\nbounds checking is enabled in the release build. There is [evidence] that the\ncost of these hardening steps is low. Following the specific guidance of our top\npriority for [performance _control_], Carbon will provide ways to write unsafe code\nthat disables the run-time enforcement, enabling the control of any overhead incurred.\n\n[evidence]: https://chandlerc.blog/posts/2024/11/story-time-bounds-checking/\n[performance control]: /docs/project/goals.md#performance-critical-software\n\nThe debug build will change the actual behavior of both safe and unsafe code\nwith detectable bugs or detectable undefined or erroneous behavior to have\n[fail-stop] behavior and provide detailed diagnostics to enable better\ndebugging. This mode will at least provide similar bug [detection] capabilities\nto [AddressSanitizer] and [MemorySanitizer].\n\n[fail-stop]: /docs/design/safety/terminology.md#fail-stop\n[detection]: /docs/design/safety/terminology.md#detecting\n[AddressSanitizer]: https://clang.llvm.org/docs/AddressSanitizer.html\n[MemorySanitizer]: https://clang.llvm.org/docs/MemorySanitizer.html\n\nCarbon will also have additional build modes to provide specific, narrow\ncapabilities that cannot be reasonably combined into either of the above build\nmodes. Each of these is expected to be an extension of either the debug or\nrelease build for that specific purpose. For example:\n\n-   Debug + [ThreadSanitizer]: detection of [data-races][data-race safety].\n-   Release + specialized [hardening]: some users can afford significant\n    run-time overhead in order to use additional hardening. Carbon will have\n    several specialized build modes in this space. Hardening techniques in this\n    space include [Control-Flow Integrity (CFI)][cfi] and hardware-accelerated\n    address sanitizing ([HWASAN]).\n\n[ThreadSanitizer]: https://clang.llvm.org/docs/ThreadSanitizer.html\n[hardening]: /docs/design/safety/terminology.md#hardening\n[cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html\n[hwasan]:\n    https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html\n\nCarbon will provide a way to disable the default hardening in release builds,\nbut not in a supported way. Its use is expected to be strictly for benchmarking\npurposes.\n\n## Constraints\n\n### Probabilistic techniques likely cannot stop attacks\n\nIt's expected that non-cryptographic probabilistic techniques that can be\napplied at the language level are attackable through a variety of techniques:\n\n-   The attacker might be able to attack repeatedly until it gets through.\n-   The attacker may be able to determine when the attack would be detected and\n    only run the attack when it would not be.\n-   The attacker might be able control the test condition to make detection much\n    less likely or avoid detection completely. For example, if detection is\n    based on the last 4 bits of a memory address, an attacker may be able to\n    generate memory allocations, viewing the address and only attacking when\n    there's a collision.\n\nHardware vulnerabilities may make these attacks easier than they might otherwise\nappear. Future hardware vulnerabilities are difficult to predict. In general, we\ndo not expect non-cryptographic probabilistic techniques to be an effective\napproach to achieving safety.\n\nWhile _cryptographic_ probabilistic techniques can, and typically do, work\ncarefully to not be subject to these weaknesses, they face a very different\nchallenge. The overhead of a cryptographically secure hash is generally\nprohibitive for use in language level constructs. Further, some of the defenses\nagainst hardware vulnerabilities and improvements further exacerbate these\noverheads. However, when these can be applied usefully such as with [PKeys],\nthey are robust.\n\n[PKeys]: https://docs.kernel.org/core-api/protection-keys.html\n\n## References\n\n-   Proposal\n    [#196: Language-level safety strategy](https://github.com/carbon-language/carbon-lang/pull/196).\n-   Proposal\n    [#5914: Updating Carbon's safety strategy](https://github.com/carbon-language/carbon-lang/pull/5914).\n"
  },
  {
    "path": "docs/design/safety/terminology.md",
    "content": "# Safety: Terminology\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Core Terminology](#core-terminology)\n    -   [_Hazard_](#hazard)\n    -   [_Bug_ or _defect_](#bug-or-defect)\n        -   [_Active bug_](#active-bug)\n        -   [_Latent bug_](#latent-bug)\n    -   [_Safety_](#safety)\n    -   [_Code_, _software_, or _program safety_](#code-software-or-program-safety)\n    -   [_Safety bugs_](#safety-bugs)\n    -   [_Initial bug_](#initial-bug)\n    -   [_Fail-stop_](#fail-stop)\n-   [Vulnerability Terminology](#vulnerability-terminology)\n    -   [_Vulnerability_ or _security vulnerability_](#vulnerability-or-security-vulnerability)\n    -   [_Vulnerability defense_](#vulnerability-defense)\n        -   [_Detecting_](#detecting)\n        -   [_Mitigating_](#mitigating)\n        -   [_Preventing_ vulnerabilities](#preventing-vulnerabilities)\n        -   [_Ensuring_ correctness](#ensuring-correctness)\n        -   [_Hardening_](#hardening)\n-   [Memory Safety Specifics](#memory-safety-specifics)\n    -   [_Memory safety_](#memory-safety)\n        -   [_Temporal safety_](#temporal-safety)\n        -   [_Spatial safety_](#spatial-safety)\n        -   [_Type safety_](#type-safety)\n        -   [_Initialization safety_](#initialization-safety)\n        -   [_Data-race safety_](#data-race-safety)\n    -   [_Memory safety bug_](#memory-safety-bug)\n    -   [_Memory-safe platform_ or _environment_](#memory-safe-platform-or-environment)\n    -   [_Memory-safe language_](#memory-safe-language)\n\n<!-- tocstop -->\n\n## Core Terminology\n\n### _Hazard_\n\nUnsafe coding construct that may lead to a bug or vulnerability. For example,\nindexing an array with a user-supplied and unvalidated index is a hazard.\n\n### _Bug_ or _defect_\n\nReachable program behavior contrary to the author's intent.\n\n#### _Active bug_\n\nBuggy behavior that is actively occurring for users of the program.\n\n#### _Latent bug_\n\nBuggy behavior that does not currently occur for users, but is reachable.\nBehaviors that are reachable, and so _can_ happen, but don't happen today in\npractice _are always still bugs_!\n\n### _Safety_\n\nAbsent a qualifier or narrow context, refers to _[system safety]_, and _[safety\nengineering]_.\nAlways a property of a system or product as a whole, including human factors,\netc.\n\n[system safety]: https://en.wikipedia.org/wiki/System_safety\n[safety engineering]: https://en.wikipedia.org/wiki/Safety_engineering\n\n### _Code_, _software_, or _program safety_\n\nInvariants or limits on program behavior in the face of bugs.\n\n-   Very narrow and specific meaning.\n-   Often necessary but not sufficient for system safety.\n\nThis is a specific subset of [safety](#safety) concerns, and the ones we are\nmost often focused on with programming language and library design.\n\n### _Safety bugs_\n\nBugs where some aspect of program behavior has insufficient (often none)\ninvariants or limits.\n\nFor example, _undefined behavior_ definitionally has no invariant or limit, and\nreaching it is always a safety bug.\n\n### _Initial bug_\n\nThe first behavior contrary to the author's intent, distinct from subsequent\ndeviations.\n\n### _Fail-stop_\n\nThe behavior of immediately terminating the program, minimizing any further\nbusiness logic. This is in contrast to any form of \"correct\" program\ntermination, continuing execution, or unwinding.\n\n## Vulnerability Terminology\n\n### _Vulnerability_ or _security vulnerability_\n\nA bug that creates the possibility for a malicious actor to subvert a program's\nintended behavior in a way that violates a security policy (for example,\nconfidentiality, integrity, availability). Vulnerabilities are often exploitable\nmanifestations of underlying bugs.\n\n### _Vulnerability defense_\n\nThe set of strategies and techniques employed to reduce the risks posed by\nvulnerabilities arising from bugs. These strategies operate at different levels\nand have varying degrees of effectiveness.\n\n#### _Detecting_\n\nWhile still leaving the code vulnerable, a defense that attempts to recognize\nand potentially track when a specific bug has occurred dynamically. Requires\n_some_ invariant or limit, but very minimal.\n\n#### _Mitigating_\n\nMaking a vulnerability significantly more expensive, difficult, or improbable to\nbe exploited.\n\n#### _Preventing_ vulnerabilities\n\nMaking it impossible for a bug to be exploited as a vulnerability without\nresolving the underlying bug -- the program still doesn't behave as intended, it\njust cannot be exploited. Often this is done by defining behavior to\n[fail-stop](#fail-stop).\n\n#### _Ensuring_ correctness\n\nEnsures that if the program compiles successfully, it behaves as intended. This\ntypically prevents a bug being written and compiled into a program in the first\nplace. For example, statically typed languages typically ensure that the types\nused in the program are correct.\n\n#### _Hardening_\n\nCombinations of mitigation, prevention, and ensured correctness to reduce the\npractical risk of vulnerabilities due to bugs.\n\n## Memory Safety Specifics\n\n### _Memory safety_\n\nHaving well-defined and predictable behavior regarding memory access, even in\nthe face of bugs. Memory safety encompasses several key aspects:\n\n#### _Temporal safety_\n\nMemory accesses occur only within the valid lifetime of the intended memory\nobject.\n\n#### _Spatial safety_\n\nMemory accesses remain within the intended bounds of memory regions.\n\n#### _Type safety_\n\nMemory is accessed and interpreted according to its intended type, preventing\ntype confusion.\n\n#### _Initialization safety_\n\nMemory is properly initialized before being read, avoiding the use of\nuninitialized data.\n\n#### _Data-race safety_\n\nMemory writes are synchronized with reads or writes on other threads.\n\n### _Memory safety bug_\n\nA safety bug that violates memory safety.\n\n### _Memory-safe platform_ or _environment_\n\nA computing platform or execution environment that provides mechanisms to\nprevent memory safety bugs in programs running on it from becoming\nvulnerabilities. This is a _systems_ path to achieving memory safety by\nproviding the well-defined and predictable behavior by way of the execution\nenvironment. For example, a strongly sandboxed WebAssembly runtime environment\ncan allow a program that is itself unsafe to be executed safely\n\n### _Memory-safe language_\n\nA programming language with sufficient defenses against memory safety bugs for\nthem to not be a significant source of security vulnerabilities. This requires\n_preventing_ vulnerabilities or _ensuring_ correctness; mitigation is not\nsufficient to provide an adequate level of memory safety.\n\nWe identify several key requirements for a language to be memory-safe:\n\n-   The default mode or subset of the language must provide guaranteed spatial,\n    temporal, type, and initialization memory safety.\n-   Any unsafe subset must only be needed and only be used in rare, exceptional\n    cases. Any use of the unsafe subset must also be well delineated and\n    auditable.\n-   Currently, security evidence doesn't _require_ providing guaranteed\n    data-race safety for\n    [data-race bugs that are not _also_ temporal memory safety bugs](/docs/design/safety#data-races-versus-unsynchronized-temporal-safety).\n    However, the temporal memory safety guarantee must still hold.\n"
  },
  {
    "path": "docs/design/sum_types.md",
    "content": "# Sum types\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [`choice` declarations](#choice-declarations)\n-   [User-defined sum types](#user-defined-sum-types)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nIn Carbon, a _sum type_ is a type whose values are grouped into several distinct\nnamed cases, called _alternatives_. A value of a sum type notionally consists of\na _discriminator_ tag that identifies which alternative is present, together\nwith that alternative's value if it has one. Sum types are typically handled\nwith pattern matching.\n\n## `choice` declarations\n\nThe `choice` keyword is used to declare a sum type by specifying its interface,\nleaving the implementation to the compiler. A `choice` declaration consists of\nthe `choice` keyword followed by the name of the type, and then a list of\nalternatives inside curly braces. An alternative declaration consists of the\nalternative name, optionally followed by a parameter list in parentheses. If\npresent, the parameter list has the same syntax as in a\n[function declaration](README.md#functions). For example:\n\n```carbon\nchoice OptionalI32 {\n  Some(value: i32),\n  None\n}\n```\n\nThis declares a sum type named `OptionalI32` with two alternatives: `Some`,\nwhich holds a single `i32` value (the parameter name `value` has no effect other\nthan documentation), and `None`, which is empty. Choice types can also be\nparameterized, [like class types](generics/details.md#parameterized-types):\n\n```carbon\nchoice Optional(T:! type) {\n  Some(value: T),\n  None\n}\n```\n\nA value of a function-like alternative is specified by \"calling\" it like a\nfunction, and a value of an empty alternative like `None` is specified by naming\nit:\n\n```carbon\nvar my_opt: Optional(i32) = Optional(i32).None;\nmy_opt = Optional(i32).Some(42);\n```\n\nThe value of a choice type can be inspected using a `match` statement:\n\n```carbon\nmatch (my_opt) {\n  case .Some(the_value: i32) => {\n    Print(the_value);\n  }\n  case .None => {\n    Print(\"None\");\n  }\n}\n```\n\n## User-defined sum types\n\n`choice` declarations are a convenience shorthand for common use cases, but they\nhave limited flexibility. There is no way to control the representation of a\n`choice` type, or define methods or other members for it (although you can\nextend it to implement interfaces, using an\n[out-of-line `impl`](generics/details.md#out-of-line-impl) or\n[adapter](generics/overview.md#adapting-types)). However, a `class` type can be\nextended to behave like a sum type. This is much more verbose than a `choice`\ndeclaration, but gives the author full control over the representation and class\nmembers.\n\nThe ability to create instances of the sum type can be straightforwardly\nemulated with factory functions and static constants, and the internal storage\nlayout will presumably involve untagged unions or some other low-level storage\nprimitive which hasn't been designed yet, but the key to defining a sum type's\ninterface is enabling it to support pattern matching. To do that, the sum type\nhas to specify two things:\n\n-   The set of all possible alternatives, including their names and parameter\n    types, so that the compiler can typecheck the `match` body, identify any\n    unreachable `case`s, and determine whether any `case`s are missing.\n-   The algorithm that, given a value of the sum type, determines which\n    alternative is present, and specifies the values of its parameters.\n\nIt does so by implementing the `Match` interface, which is defined as follows:\n\n```carbon\ninterface Match {\n  interface BaseContinuation {\n    let ReturnType:! type;\n  }\n\n  let template Continuation:! type;\n  fn Op[self: Self, C:! Continuation](continuation: C*)\n    -> C.(BaseContinuation.ReturnType);\n}\n```\n\n`Continuation` must itself be an interface that extends\n`Match.BaseContinuation`, and its definition specifies the set of possible\nalternatives: each alternative is represented as a method of that interface.\nWhen compiling a proper pattern (or set of patterns that includes a proper\npattern, as with the cases of a `match`) whose type is a sum type, the compiler\ngenerates an implementation of `Continuation` and passes it to `Match.Op`. The\nsum type's implementation of `Match.Op` is responsible for determining which\nalternative is present and what its parameters are, and calling the\ncorresponding method of `continuation` with those parameters. The `Match.Op`\nimplementation is required to call exactly one such method exactly once before\nreturning. The compiler populates the `Continuation` method bodies with whatever\ncode should be executed when the corresponding alternatives match.\n\n**TODO:** if Carbon has explicit support for tail calls, we should probably\nrequire that `Match.Op` invoke the continuation as a tail call.\n\nFor example, here's how `Optional` can be defined as a class:\n\n```carbon\nclass Optional(T:! type) {\n  // Factory functions\n  fn Some(value: T) -> Self;\n  let None:! Self;\n\n  private var has_value: bool;\n  private var value: T;\n\n  impl as Match {\n    interface Continuation {\n      extend Match.BaseContinuation;\n      fn Some[ref self: Self](value: T) -> ReturnType;\n      fn None[ref self: Self]() -> ReturnType;\n    }\n\n    fn Op[self: Self, C:! Continuation](continuation: C*) -> C.ReturnType {\n      if (self.has_value) {\n        return continuation->Some(self.value);\n      } else {\n        return continuation->None();\n      }\n    }\n  }\n\n  // Operations like destruction, copying, assignment, and comparison are\n  // omitted for brevity.\n}\n```\n\nAnd here's how the compiler-generated implementation of\n`Optional.(Match.Continuation)` for the `match` statement shown earlier might\nlook, if it were written in Carbon:\n\n```carbon\nclass __MatchStatementImpl {\n  extend impl as Optional.(Match.Continuation) where .ReturnType = () {\n    fn Some(the_value: i32) {\n      Print(the_value);\n    }\n    fn None() {\n      Print(\"None\");\n    }\n  }\n}\n\nmy_opt.(Match.Op)({} as __MatchStatementImpl);\n```\n\n(The name `__MatchStatementImpl` is a placeholder for illustration purposes; the\nactual generated class will be anonymous.)\n\nThe mechanism described above for proper patterns may also be used for\nexpression patterns if they have the form of an alternative pattern. An\nexpression pattern of type `T` has the form of an alternative pattern if `T`\nimplements `Match`, and the expression consists of an optional expression that\nnames `T`, followed by a designator that names a method of\n`T.(Match.Continuation)`, optionally followed by a tuple expression. If an\nexpression pattern has that form, it may be matched using the mechanism above,\nas if it were a proper pattern, rather than by evaluating the expression and\ncomparing it to the scrutinee using `==`. Both possible implementations must be\nwell-formed (and this is enforced by the compiler), but it is unspecified which\nimplementation is used to generate code.\n\nAs a result, it is **strongly** recommended that user-defined sum types ensure\nthat for every alternative there is a factory function or constant member with\nthe same name and parameter list, such that pattern-matching on the result will\ncorrectly reproduce the arguments to the factory function. For example, the\ndefinition of `Optional` above satisfies this requirement, because for any\nregular type `T`, the expression `Optional(T).None` evaluates to a value that\nmatches the pattern `Optional(T).None` (under both possible matching\nmechanisms), and for any `x` of type `T`, the expression `Optional(T).Some(x)`\nevaluates to a value that matches the pattern `Optional(T).Some(y: T)` and binds\n`y` to a value that's equal to `x`. Expression patterns involving a sum type\nthat doesn't meet this requirement will fail to compile, or have behavior that\nobservably changes depending on the compiler's implementation choices.\n\nAnother corollary of this rule is that if an alternative takes no arguments, its\npattern syntax is the same as its expression syntax. For example,\n`case Optional(i32).None() => ...` is not well-formed, because\n`Optional(i32).None()` has the form of an alternative pattern, but the\nimplementation in terms of `==` is not well-formed because\n`Optional(i32).None()` is not a well-formed expression. If we had defined\n`Optional.None` as a factory function instead of a constant,\n`case Optional(i32).None() => ...` would be well-formed but\n`case Optional(i32).None => ...` would not be.\n\nNote that the compiler-generated continuation method bodies are not required to\ncontain the code in the `case` body (or whatever code is in the scope of the\npattern). For example, they might only store the parameter values and then\nreturn an index that identifies the `case` body to be executed.\n\n## Alternatives considered\n\n-   [Providing `choice` types only](/proposals/p0157.md#choice-types-only), with\n    no support for user-defined sum types.\n-   [Indexing alternatives by type](/proposals/p0157.md#indexing-by-type)\n    instead of by name.\n-   Implementing user-defined sum types in terms of\n    [`choice` type proxies](/proposals/p0157.md#pattern-matching-proxies) rather\n    than callbacks.\n-   Implementing user-defined sum types in terms of invertible\n    [pattern functions](/proposals/p0157.md#pattern-functions).\n\n## References\n\n-   Proposal\n    [#157: Design direction for sum types](https://github.com/carbon-language/carbon-lang/pull/157)\n"
  },
  {
    "path": "docs/design/templates.md",
    "content": "# Templates\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [TODO](#todo)\n-   [Overview](#overview)\n    -   [Types with template parameters](#types-with-template-parameters)\n    -   [Functions with template parameters](#functions-with-template-parameters)\n    -   [Overloading](#overloading)\n    -   [Constraining templates with interfaces](#constraining-templates-with-interfaces)\n\n<!-- tocstop -->\n\n## TODO\n\nThis is a skeletal design, added to support [the overview](README.md). It should\nnot be treated as accepted by the core team; rather, it is a placeholder until\nwe have more time to examine this detail. Please feel welcome to rewrite and\nupdate as appropriate.\n\n## Overview\n\nCarbon templates follow the same fundamental paradigm as C++ templates: they are\ninstantiated, resulting in late type checking, duck typing, and lazy binding.\nThey both enable interoperability between Carbon and C++ and address some\n(hopefully limited) use cases where the type checking rigor imposed by generics\nisn't helpful.\n\n### Types with template parameters\n\nWhen parameterizing a user-defined type, the parameters can be marked as\ntemplate parameters. The resulting type-function will instantiate the\nparameterized definition with the provided arguments to produce a complete type\nwhen used. Note that only the parameters marked as having this template behavior\nare subject to full instantiation -- other parameters will be type checked and\nbound early to the extent possible. For example:\n\n```\nclass Stack(template T:! type) {\n  var storage: Array(T);\n\n  fn Push[ref self: Self](value: T);\n  fn Pop[ref self: Self]() -> T;\n}\n```\n\nThis both defines a parameterized type (`Stack`) and uses one (`Array`). Within\nthe definition of the type, the template type parameter `T` can be used in all\nof the places a normal type would be used, and it will only by type checked on\ninstantiation.\n\n### Functions with template parameters\n\nBoth deduced and explicit function parameters in Carbon can be marked as\ntemplate parameters. When called, the arguments to these parameters trigger\ninstantiation of the function definition, fully type checking and resolving that\ndefinition after substituting in the provided (or computed if deduced)\narguments. The runtime call then passes the remaining arguments to the resulting\ncomplete definition.\n\n```\nfn Convert[template T:! type](source: T, template U:! type) -> U {\n  var converted: U = source;\n  return converted;\n}\n\nfn Foo(i: i32) -> f32 {\n  // Instantiates with the `T` deduced argument set to `i32` and the `U`\n  // explicit argument set to `f32`, then calls with the runtime value `i`.\n  return Convert(i, f32);\n}\n```\n\nHere we deduce one type parameter and explicitly pass another. It is not\npossible to explicitly pass a deduced type parameter, instead the call site\nshould cast or convert the argument to control the deduction. The explicit type\nis passed after a runtime parameter. While this makes that type unavailable to\nthe declaration of _that_ runtime parameter, it still is a template parameter\nand available to use as a type even within the remaining parts of the function\ndeclaration.\n\n### Overloading\n\nAn important feature of templates in C++ is the ability to customize how they\nend up specialized for specific types. Because template parameters (whether as\ntype parameters or function parameters) are pattern matched, we expect to\nleverage pattern matching techniques to provide \"better match\" definitions that\nare selected analogously to specializations in C++ templates. When expressed\nthrough pattern matching, this may enable things beyond just template parameter\nspecialization, but that is an area that we want to explore cautiously.\n\n### Constraining templates with interfaces\n\nBecause we consider only specific _parameters_ to be templated and they could be\nindividually migrated to a constrained interface using the\n[checked-generics system](README.md#generics), constraining templates themselves\nmay be less critical. Instead, we expect parameterized types and functions may\nuse a mixture of checked and template generic parameters based on where they are\nconstrained.\n\nHowever, if there are still use cases, we would like to explore applying the\ninterface constraints of the checked-generics system directly to template\nparameters rather than create a new constraint system.\n"
  },
  {
    "path": "docs/design/tuples.md",
    "content": "# Tuples\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Element access](#element-access)\n-   [Conversion](#conversion)\n    -   [Empty tuples](#empty-tuples)\n    -   [Trailing commas and single-element tuples](#trailing-commas-and-single-element-tuples)\n    -   [Tuple of types and tuple types](#tuple-of-types-and-tuple-types)\n    -   [Operations performed field-wise](#operations-performed-field-wise)\n    -   [Pattern matching](#pattern-matching)\n-   [Open questions](#open-questions)\n    -   [Tuple slicing](#tuple-slicing)\n    -   [Slicing ranges](#slicing-ranges)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\nThe primary composite type involves simple aggregation of other types as a\ntuple, called a \"product type\" in formal type theory:\n\n```\nfn DoubleBoth(x: i32, y: i32) -> (i32, i32) {\n  return (2 * x, 2 * y);\n}\n```\n\nThis function returns a tuple of two integers represented by the type\n`(i32, i32)`. The expression to return it uses a special tuple syntax to build a\ntuple within an expression: `(<expression>, <expression>)`. This is actually the\nsame syntax in both cases. The return type is a tuple expression, and the first\nand second elements are expressions referring to the `i32` type. The only\ndifference is the type of these expressions. Both are tuples, but one is a tuple\nof types.\n\n## Element access\n\nElement access uses a syntax similar to field access, with an element index\ninstead of a field name:\n\n```\nfn Sum(x: i32, y: i32) -> i32 {\n  var t: (i32, i32) = (x, y);\n  return t.0 + t.1;\n}\n```\n\nA parenthesized template constant expression can also be used to index a tuple:\n\n```\nfn Choose(template N:! i32) -> i32 {\n  return (1, 2, 3).(N % 3);\n}\n```\n\n## Conversion\n\nA tuple type `Source` can be converted to a tuple type `Dest` if they have the\nsame number of elements, and each element type of `Source` is convertible to the\ncorresponding element type of `Dest`, and the conversion is implicit if all of\nthe element type conversions are implicit. See\n[here](values.md#type-conversions) for full details.\n\n### Empty tuples\n\n`()` is the empty tuple. This is used in other parts of the design, such as\n[functions](functions.md), where a type with a single value is needed.\n\n### Trailing commas and single-element tuples\n\nThe final element in a tuple literal may be followed by a trailing comma, such\nas `(1, 2,)`. This trailing comma is optional in tuples with two or more\nelements, and mandatory in a tuple with a single element: `(x,)` is a one-tuple,\nwhereas `(x)` is a parenthesized single expression.\n\n### Tuple of types and tuple types\n\nA tuple of types can be used in contexts where a type is needed. This is made\npossible by a built-in implicit conversion: a tuple can be implicitly converted\nto type `type` if all of its elements can be converted to type `type`, and the\nresult of the conversion is the corresponding tuple type.\n\nFor example, `(i32, i32)` is a value of type `(type, type)`, which is not a type\nbut can be implicitly converted to a type. `(i32, i32) as type` can be used to\nexplicitly refer to the corresponding tuple type, which is the type of\nexpressions such as `(1 as i32, 2 as i32)`. However, this is rarely necessary,\nas contexts requiring a type will implicitly convert their operand to a type:\n\n```carbon\n// OK, both (i32, i32) values are implicitly converted to `type`.\nfn F(x: (i32, i32)) -> (i32, i32);\n```\n\n### Operations performed field-wise\n\nLike some other aggregate data types like\n[struct types](classes.md#struct-types), there are some operations are defined\nfor tuples field-wise:\n\n-   initialization\n-   assignment\n-   equality and inequality comparison\n-   ordered comparison\n-   implicit conversion for argument passing\n-   destruction\n\nFor binary operations, the two tuples must have the same number of components\nand the operation must be defined for the corresponding component types of the\ntwo tuples.\n\n### Pattern matching\n\nTuple values can be matched using a\n[tuple pattern](/docs/design/pattern_matching.md#tuple-patterns), which is\nwritten as a tuple of element patterns:\n\n```carbon\nlet tup: (i32, i32, i32) = (1, 2, 3);\nmatch (tup) {\n  case (a: i32, 2, var c: i32) => {\n    c = a;\n    return c + 1;\n  }\n}\n```\n\n## Open questions\n\n### Tuple slicing\n\nTuples could support multiple indices and slicing to restructure tuple elements:\n\n```\nfn Baz(x: i32, y: i32, z: i32) -> (i32, i32) {\n  var t1: (i32, i32, i32) = (x, y, z);\n  var t2: (i32, i32, i32) = t1.((2, 1, 0));\n  return t2.(0 .. 2);\n}\n```\n\nThis code would first reverse the tuple, and then extract a slice using a\nhalf-open range of indices.\n\n### Slicing ranges\n\nThe intent of `0 .. 2` is to be syntax for forming a sequence of indices based\non the half-open range [0, 2). There are a bunch of questions we'll need to\nanswer here:\n\n-   Is this valid anywhere? Only some places?\n-   What _is_ the sequence?\n    -   If it is a tuple of indices, maybe that solves the above issue, and\n        unlike function call indexing with multiple indices is different from\n        indexing with a tuple of indexes.\n-   Do we need syntax for a closed range (`...` perhaps, unclear if that ends up\n    _aligned_ or in _conflict_ with other likely uses of `...` in pattern\n    matching)?\n-   All of these syntaxes are also very close to `0.2`, is that similarity of\n    syntax OK?\n    -   Do we want to require the `..` to be surrounded by whitespace to\n        minimize that collision?\n\n## Alternatives considered\n\n-   [Indexing with square brackets](/proposals/p3646.md#square-bracket-notation)\n-   [Indexing from the end of a tuple](/proposals/p3646.md#negative-indexing-from-the-end-of-the-tuple)\n-   [Restrict indexes to decimal integers](/proposals/p3646.md#decimal-indexing-restriction)\n-   [Alternatives to trailing commas](/proposals/p3646.md#trailing-commas)\n\n## References\n\n-   Proposal\n    [#2188: Pattern matching syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2188)\n-   Proposal\n    [#2360: Types are values of type `type`](https://github.com/carbon-language/carbon-lang/pull/2360)\n-   Proposal\n    [#3646: Tuples and tuple indexing](https://github.com/carbon-language/carbon-lang/pull/3646)\n-   Leads issue\n    [#710](https://github.com/carbon-language/carbon-lang/issues/710)\n    established rules for assignment, comparison, and implicit conversion\n-   Leads issue\n    [#2191: one-tuples and one-tuple syntax](https://github.com/carbon-language/carbon-lang/issues/2191)\n"
  },
  {
    "path": "docs/design/type_inference.md",
    "content": "# Type inference\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Open questions](#open-questions)\n    -   [Inferring a variable type from literals](#inferring-a-variable-type-from-literals)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Overview\n\n[Type inference](https://en.wikipedia.org/wiki/Type_inference) occurs in Carbon\nwhen the `auto` keyword is used. This may occur in\n[variable declarations](values.md#binding-patterns-and-local-variables-with-let-and-var)\nor [function declarations](functions.md).\n\nAt present, type inference is very simple: given the expression which generates\nthe value to be used for type inference, the inferred type is the precise type\nof that expression. For example, the inferred type for `auto` in\n`fn Foo(x: i64) -> auto { return x; }` is `i64`.\n\nType inference is currently supported for [function return types](functions.md)\nand\n[declared variable types](values.md#binding-patterns-and-local-variables-with-let-and-var).\n\n## Open questions\n\n### Inferring a variable type from literals\n\nUsing the type on the right side for `var y: auto = 1` currently results in a\nconstant `IntLiteral(1)` value, whereas most languages would suggest a variable\ninteger type, such as `i64`. Carbon might also make it an error. Although type\ninference currently only addresses `auto` for variables and function return\ntypes, this is something that will be considered as part of type inference in\ngeneral, because it also affects checked generics, templates, lambdas, and\nreturn types.\n\n## Alternatives considered\n\n-   [Use `_` instead of `auto`](/proposals/p0851.md#use-_-instead-of-auto)\n\n## References\n\n-   Proposal\n    [#851: auto keyword for vars](https://github.com/carbon-language/carbon-lang/pull/851)\n"
  },
  {
    "path": "docs/design/values.md",
    "content": "# Values, variables, and pointers\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Values, objects, and expressions](#values-objects-and-expressions)\n    -   [Expression categories](#expression-categories)\n        -   [Value acquisition](#value-acquisition)\n        -   [Direct initialization](#direct-initialization)\n        -   [Copy initialization](#copy-initialization)\n        -   [Temporary materialization](#temporary-materialization)\n-   [Binding patterns and local variables with `let` and `var`](#binding-patterns-and-local-variables-with-let-and-var)\n    -   [Local variables](#local-variables)\n    -   [Consuming function parameters](#consuming-function-parameters)\n-   [Reference expressions](#reference-expressions)\n    -   [Entire reference expressions](#entire-reference-expressions)\n    -   [Durable reference expressions](#durable-reference-expressions)\n    -   [Ephemeral reference expressions](#ephemeral-reference-expressions)\n-   [Value expressions](#value-expressions)\n    -   [Comparison to C++ parameters](#comparison-to-c-parameters)\n    -   [Polymorphic types](#polymorphic-types)\n    -   [Interop with C++ `const &` and `const` methods](#interop-with-c-const--and-const-methods)\n    -   [Escape hatches for value addresses in Carbon](#escape-hatches-for-value-addresses-in-carbon)\n-   [Initializing expressions](#initializing-expressions)\n    -   [Function calls and returns](#function-calls-and-returns)\n        -   [Deferred initialization from values and references](#deferred-initialization-from-values-and-references)\n        -   [Declared `returned` variable](#declared-returned-variable)\n-   [Expression forms](#expression-forms)\n    -   [Initializing results](#initializing-results)\n    -   [Form conversions](#form-conversions)\n        -   [Type conversions](#type-conversions)\n        -   [Category conversions](#category-conversions)\n-   [Pointers](#pointers)\n    -   [Reference types](#reference-types)\n    -   [Pointer syntax](#pointer-syntax)\n    -   [Dereferencing customization](#dereferencing-customization)\n-   [`const`-qualified types](#const-qualified-types)\n-   [Lifetime overloading](#lifetime-overloading)\n-   [Value representation and customization](#value-representation-and-customization)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Values, objects, and expressions\n\nCarbon has both abstract _values_ and concrete _objects_. Carbon _values_ are\nthings like `42`, `true`, and `i32` (a type value). Carbon _objects_ have\n_storage_ where values can be read and written. Storage also allows taking the\naddress of an object in memory in Carbon.\n\nBoth objects and values can be nested within each other. For example\n`(true, true)` is both a value and also contains two sub-values. When a\ntwo-tuple is stored somewhere, it is both a tuple-typed object and contains two\nsubobjects.\n\nThese terms are important components in the describing the semantics of Carbon\ncode, but they aren't sufficient. We also need to explicitly and precisely talk\nabout the Carbon _expressions_ that produce or reference values and objects.\nCategorizing the expressions themselves allows us to be more precise and\narticulate important differences not captured without looking at the expression\nitself.\n\n### Expression categories\n\nThere are three primary expression categories in Carbon:\n\n-   [_Value expressions_](#value-expressions) produce abstract, read-only\n    _values_ that cannot be modified or have their address taken.\n-   [_Reference expressions_](#reference-expressions) refer to _objects_ with\n    _storage_ where a value may be read or written and the object's address can\n    be taken.\n-   [_Initializing expressions_](#initializing-expressions) require a result\n    location to be provided implicitly when evaluating the expression. The\n    expression then initializes an object in that location. These are used to\n    model function returns, which can construct the returned value directly in\n    the caller's storage.\n\nExpressions in one category can be implicitly converted to any other primary\ncategory when needed. The primitive conversion steps used are:\n\n-   [_Value acquisition_](#value-acquisition) forms a value expression from the\n    current value of the object referenced by a reference expression.\n-   [_Direct initialization_](#direct-initialization) converts a value\n    expression into an initializing expression.\n-   [_Copy initialization_](#copy-initialization) converts a reference\n    expression into an initializing expression.\n-   [_Temporary materialization_](#temporary-materialization) converts an\n    initializing expression into a reference expression.\n\nThese conversion steps combine to provide the transitive conversion table:\n\n|               From: | value                     | reference | initializing          |\n| ------------------: | ------------------------- | --------- | --------------------- |\n|        to **value** | ==                        | acquire   | materialize + acquire |\n|    to **reference** | direct init + materialize | ==        | materialize           |\n| to **initializing** | direct init               | copy init | ==                    |\n\nReference expressions are divided into 2x2 sub-categories: they can be either\n[_ephemeral_](#ephemeral-reference-expressions) or\n[_durable_](#durable-reference-expressions), and either _entire_ or\n_non-entire_.\n\nEphemeral reference expressions are formed through temporary materialization,\nand have restrictions on how they are used. In contrast, durable reference\nexpressions refer to storage that outlives the expression, and typically has a\ndeclared name. Entire reference expressions can only refer to complete objects,\nwhereas non-entire reference expressions can refer to both complete objects and\nsub-objects (such as class fields and base class sub-objects). As a consequence,\nonly entire reference expressions can be destructively moved.\n\n> **Future work:** This means that pointer-dereference expressions are\n> non-entire, but we will presumably want to be able to destructively move from\n> them. We need to figure out how to support that without violating the\n> invariant that a live object has live fields.\n\nValue acquisition and copy initialization can be applied to any reference\nexpression, but materialization only produces ephemeral entire reference\nexpressions. An entire reference expression can be implicitly converted to\nnon-entire; this has no run-time effect because it merely discards static\nobject-completeness information. Non-entire reference expressions can only be\nconverted to entire reference expressions by round-tripping through\ncopy-initialization and materialization. Non-durable-reference expressions\ncannot be implicitly converted to durable reference expressions at all.\n\n> **TODO:** Determine how these reference sub-categories relate to memory-safety\n> properties like uniqueness, and make sure their names are aligned with\n> memory-safety terminology.\n\n#### Value acquisition\n\nWe call forming a value expression from a reference expression _value\nacquisition_. This forms a value expression that will evaluate to the value of\nthe object in the referenced storage of the reference expression. It may do this\nby eagerly reading that value into a machine register, lazily reading that value\non-demand into a machine register, or in some other way modeling that abstract\nvalue.\n\nSee the [value expressions](#value-expressions) section for more details on the\nsemantics of value expressions.\n\n#### Direct initialization\n\nThis is the first way we have of initializing storage of an object. There may\nnot be storage for the source of this initialization, as the value expression\nused for the initialization may be in a machine register or simply be abstractly\nmodeled like a source literal. A canonical example here is zeroing an object.\n\n#### Copy initialization\n\nThis initializes storage for an object based on some other object which already\nhas initialized storage. A classic example here are types which can be copied\ntrivially and where this is implemented as a `memcpy` of their underlying bytes.\n\n#### Temporary materialization\n\nWe use temporary materialization when we need to initialize an object by way of\nstorage, but weren't provided dedicated storage and can simply acquire the\nresult as a value afterward.\n\n> **Open question:** The lifetimes of temporaries is not yet specified.\n\n## Binding patterns and local variables with `let` and `var`\n\nA [_value binding pattern_](/docs/design/README.md#binding-patterns) introduces\na name that is a [_value expression_](#value-expressions) and is called a _value\nbinding_. This is the desired default for many pattern contexts, especially\nfunction parameters. Values are a good model for \"input\" function parameters\nwhich are the dominant and default style of function parameters:\n\n```carbon\nfn Sum(x: i32, y: i32) -> i32 {\n  // `x` and `y` are value expressions here. We can use their value, but not\n  // modify them or take their address.\n  return x + y;\n}\n```\n\nValue bindings require the matched expression to be a _value expression_,\nconverting it into one as necessary.\n\nA _variable pattern_ is introduced with the `var` keyword. The matched\nexpression must be an ephemeral entire reference expression (which typically\nrequires the matched expression to be materialized); the `var` pattern takes\nownership of the newly-allocated temporary storage it refers to, which extends\nits lifetime to the end of the enclosing scope. The subpattern is then matched\nagainst a _durable_ entire reference expression to the object in that storage.\n\n> **Open question:** This implies that `var field: T = F().field;` doesn't\n> perform any copies or moves on `T`. This, in turn, implies that the storage\n> for `field` must be laid out as part of a complete `typeof(F())` object\n> layout, which is initialized by the call to `F()`. All other members of that\n> layout are immediately destroyed, and their storage is theoretically reusable\n> after that point, but it's unclear if this is the right default, or how to\n> enable user code to override that default when it's the wrong tradeoff.\n\nA _reference binding pattern_ is a binding pattern that is nested under a `var`\npattern. It introduces a name called a _reference binding_ that is a\n[durable reference expression](#durable-reference-expressions) to an object\nwithin the variable pattern's storage.\n\n```carbon\nfn MutateThing(ptr: i64*);\n\nfn Example() {\n  // `1` starts as a value expression, which is what a value binding expects.\n  let x: i64 = 1;\n\n  // `2` also starts as a value expression, but the variable pattern requires it\n  // to be converted to an ephemeral entire reference expression by using the\n  // value `2` to initialize temporary storage, which the variable pattern\n  // takes ownership of. The reference binding pattern is then bound to a\n  // durable reference to the newly-initialized object.\n  var y: i64 = 2;\n\n  // Allowed to take the address and mutate `y` as it is a durable reference\n  // expression.\n  MutateThing(&y);\n\n  // ❌ This would be an error though due to trying to take the address of the\n  // value expression `x`.\n  MutateThing(&x);\n}\n```\n\n### Local variables\n\nA local binding pattern can be introduced with either the `let` or `var`\nkeyword. The `let` introducer begins a value pattern which works the same as the\ndefault patterns in other contexts. The `var` introducer immediately begins a\nvariable pattern.\n\n-   `let` _identifier_`:` _( expression |_ `auto` _)_ `=` _value_`;`\n-   `var` _identifier_`:` _( expression |_ `auto` _) [_ `=` _value ]_`;`\n\nThese are just simple examples of binding patterns used directly in local\ndeclarations. Local `let` and `var` declarations build on Carbon's general\n[pattern matching](/docs/design/pattern_matching.md) design. `var` declarations\nimplicitly start off within a `var` pattern. `let` declarations introduce\npatterns that bind values by default, the same as function parameters and most\nother pattern contexts.\n\nThe general pattern matching model also allows nesting `var` sub-patterns within\na larger pattern that defaults to matching values. For example, we can combine\nthe two local declarations above into one destructuring declaration with an\ninner `var` pattern here:\n\n```carbon\nfn DestructuringExample() {\n  // Both `1` and `2` start as value expressions. The `x` binding directly\n  // matches `1`. For `2`, the variable pattern requires it to be converted to\n  // an ephemeral entire reference expression by using the value `2` to\n  // initialize temporary storage, which the variable pattern takes ownership\n  // of. The reference binding `y` is then bound to a durable reference to the\n  // newly-initialized object.\n  let (x: i64, var y: i64) = (1, 2);\n\n  // Just like above, we can take the address and mutate `y`:\n  MutateThing(&y);\n\n  // ❌ And this remains an error:\n  MutateThing(&x);\n}\n```\n\nIf `auto` is used in place of the type for a local binding pattern,\n[type inference](type_inference.md) is used to automatically determine the\nvariable's type.\n\nThese local bindings introduce names scoped to the code block in which they\noccur, which will typically be marked by an open brace (`{`) and close brace\n(`}`).\n\n### Consuming function parameters\n\nJust as part of a `let` declaration can use a `var` prefix to become a variable\npattern and bind names that will form reference expressions to the variable's\nstorage, so can function parameters:\n\n```carbon\nfn Consume(var x: SomeData) {\n  // We can mutate and use variable that `x` refers to here.\n}\n```\n\nThis allows us to model an important special case of function inputs -- those\nthat are _consumed_ by the function, either through local processing or being\nmoved into some persistent storage. Marking these in the pattern and thus\nsignature of the function changes the expression category required for arguments\nin the caller. These arguments are required to be _ephemeral entire reference\nexpressions_, potentially being converted into such an expression if necessary,\nwhose storage will be dedicated-to and owned-by the function parameter.\n\nThis pattern serves the same purpose as C++'s pass-by-value when used with types\nthat have non-trivial resources attached to pass ownership into the function and\nconsume the resource. But rather than that being the seeming _default_, Carbon\nmakes this a use case that requires a special marking on the declaration.\n\n## Reference expressions\n\n_Reference expressions_ refer to _objects_ with _storage_ where a value may be\nread or written and the object's address can be taken.\n\nReference expressions can be either _durable_ or _ephemeral_. These refine the\n_lifetime_ of the underlying storage and provide safety restrictions reflecting\nthat lifetime. Reference expressions can also be either _entire_ or\n_non-entire_, depending on whether the referenced object is known to be complete\n(rather than a sub-object of another object).\n\n### Entire reference expressions\n\nAn _entire reference expression_ is one that is statically known to refer to a\ncomplete object. Other references are _non-entire_. Durable and ephemeral\nreference expressions can both be either entire or non-entire (although\nnon-entire ephemeral references are rare). Unless otherwise specified, an\nexpression or operation that produces a reference produces a non-entire\nreference.\n\nNote that a non-entire reference expression still _might_ refer to a complete\nobject; the language rules just don't _guarantee_ that is does. As a result, an\nentire reference can be implicitly converted to a non-entire reference (with the\nsame durability), because this merely discards the knowledge that the object is\ncomplete. By the same token, there is no context that requires a non-entire\nreference; only contexts that accept both, that accept only entire references,\nor that don't accept references at all.\n\nCurrently, the only context that requires an entire reference is the scrutinee\nof a `var` pattern, which is required to be an entire ephemeral reference (and\nis [converted](#category-conversions) to that category if necessary).\n\n> **Note:** This extends the lifetime of the reference, so it must be possible\n> to determine _which_ temporary an ephemeral entire reference refers to, so\n> that the implementation knows which lifetime to extend. Under the current\n> language rules, this can be done statically.\n\n> **Open question:** Should we extend the language in ways that would force that\n> determination to be dynamic? For example, should we allow\n> `if c then r1 else r2` to be an entire ephemeral reference expression if `r1`\n> and `r2` are? As a more extreme example, should we support functions that take\n> and return entire ephemeral references?\n\nThere are several kinds of expressions that produce entire references. For\nexample:\n\n-   The name of an object introduced with a\n    [variable binding pattern](pattern_matching.md#name-binding-patterns) (in\n    other words, a name that was declared with `var <name> : <type>`) is a\n    durable entire reference.\n-   a member access expression `x.member` or `x.(member)` is an entire reference\n    if `x` is an initializing or entire ephemeral reference expression with a\n    struct or tuple type.\n-   The result of materialization is an entire ephemeral reference.\n-   When a [tuple pattern](pattern_matching.md#tuple-patterns) or\n    [struct pattern](pattern_matching.md#struct-patterns) is matched with an\n    ephemeral entire reference scrutinee, that scrutinee is destructured into\n    ephemeral entire references to its elements, which are then matched with the\n    corresponding subpatterns.\n\n### Durable reference expressions\n\n_Durable reference expressions_ are those where the object's storage outlives\nthe full expression and the address could be meaningfully propagated out of it\nas well.\n\nThere are several contexts where durable reference expressions are required. For\nexample:\n\n-   [Assignment statements](/docs/design/assignment.md) require the\n    left-hand-side of the `=` to be a durable reference. This stronger\n    requirement is enforced before the expression is rewritten to dispatch into\n    the `Carbon.Assign.Op` interface method.\n-   [Address-of expressions](#pointer-syntax) require their operand to be a\n    durable reference and compute the address of the referenced object.\n-   [`ref` binding patterns](pattern_matching.md#name-binding-patterns) require\n    their scrutinee to be a durable reference.\n-   If a function's [return form](#function-calls-and-returns) contains `ref`\n    tags, `return` statements require the corresponding parts of the operand to\n    be durable reference expressions.\n\nThere are also several kinds of expressions that produce durable references. For\nexample:\n\n-   Names of objects introduced with a\n    [reference binding](#binding-patterns-and-local-variables-with-let-and-var):\n    `x`\n-   Dereferenced [pointers](#pointers): `*p`\n-   Names of subobjects through member access to some other durable reference\n    expression: `x.member` or `p->member`\n-   [Indexing](/docs/design/expressions/indexing.md) into a type similar to\n    C++'s `std::span` that implements `IndirectIndexWith`, or indexing into any\n    type with a durable reference expression such as `local_array[i]`.\n-   Calls to functions whose [return forms](#function-calls-and-returns) contain\n    `ref`.\n\nDurable reference expressions can only be produced _directly_ by one of these\nexpressions. They are never produced by converting one of the other expression\ncategories into a reference expression.\n\n### Ephemeral reference expressions\n\nWe call the reference expressions formed through\n[temporary materialization](#temporary-materialization) _ephemeral reference\nexpressions_. They still refer to an object with storage, but it may be storage\nthat will not outlive the full expression, and so it can't be used where a\ndurable reference is expected.\n\n> **Future work:** The current design does not support mutating ephemeral\n> references (or initializing expressions): assigning to an ephemeral reference\n> is disallowed directly, and invoking mutating methods is disallowed because\n> the `ref self` parameter can only bind to a durable reference. In C++ it's\n> unusual but not rare to intentionally mutate a temporary, such as in a\n> builder-style method chain (for example `MakeFoo().SetBar().AddBaz()`), so\n> Carbon will need to provide some interop and migration target for that kind of\n> code.\n\nThere is one context that requires an ephemeral reference expression in Carbon:\nthe scrutinee of a\n[`var` pattern](#binding-patterns-and-local-variables-with-let-and-var) (which\nalso requires the reference to be entire).\n\nThere are only a few ways to produce an ephemeral reference expression. Most\nnotably:\n\n-   The result of materialization is an entire ephemeral reference.\n-   A member access expression `x.member` or `x.(member)` is an ephemeral\n    reference if `x` is an initializing or ephemeral reference.\n-   When a [tuple pattern](pattern_matching.md#tuple-patterns) or\n    [struct pattern](pattern_matching.md#struct-patterns) is matched with an\n    initializing or ephemeral reference scrutinee, that scrutinee is\n    destructured into ephemeral references to its elements, which are then\n    matched with the corresponding subpatterns.\n\n## Value expressions\n\nA value cannot be mutated, cannot have its address taken, and may not have\nstorage at all or a stable address of storage. Values are abstract constructs\nlike function input parameters and constants. They can be formed in two ways --\na literal expression like `42`, or by reading the value of some stored object.\n\nA core goal of values in Carbon is to provide a single model that can get both\nthe efficiency of passing by value when working with small types such as those\nthat fit into a machine register, but also the efficiency of minimal copies when\nworking with types where a copy would require extra allocations or other costly\nresources. This directly helps programmers by providing a simpler model to\nselect the mechanism of passing function inputs. But it is also important to\nenable generic code that needs a single type model that will have consistently\ngood performance.\n\nWhen forming a value expression from a reference expression, Carbon\n[acquires](#value-acquisition) the value of the referenced object. This allows\nimmediately reading from the object's storage into a machine register or a copy\nif desired, but does not require that. The read of the underlying object can\nalso be deferred until the value expression itself is used. Once an object is\nbound to a value expression in this way, any mutation to the object or its\nstorage ends the lifetime of the value binding, and makes any use of the value\nexpression an error.\n\n> Note: this is _not_ intended to ever become \"undefined behavior\", but instead\n> just \"erroneous\". We want to be able to detect and report such code as having\n> a bug, but do not want unbounded UB and are not aware of important\n> optimizations that this would inhibit.\n>\n> _Open issue:_ We need a common definition of erroneous behavior that we can\n> use here (and elsewhere). Once we have that, we should cite it here.\n\n> Note: this restriction is also **experimental** -- we may want to strengthen\n> or weaken it based on experience, especially with C++ interop and a more\n> complete memory safety story.\n\nEven with these restrictions, we expect to make values in Carbon useful in\nroughly the same places as `const &`s in C++, but with added efficiency in the\ncase where the values can usefully be kept in machine registers. We also\nspecifically encourage a mental model of a `const &` with extra efficiency.\n\nThe actual _representation_ of a value when bound, especially across function\nboundaries, is [customizable](#value-representation-and-customization) by the\ntype. The defaults are based around preserving the baseline efficiency of C++'s\n`const &`, but potentially reading the value when that would be both correct and\nreliably more efficient, such as into a machine register.\n\n### Comparison to C++ parameters\n\nWhile these are called \"values\" in Carbon, they are not related to \"by-value\"\nparameters as they exist in C++. The semantics of C++'s by-value parameters are\ndefined to create a new local copy of the argument, although it may move into\nthis copy.\n\nCarbon's values are much closer to a `const &` in C++ with extra restrictions\nsuch as allowing copies under \"as-if\" and preventing taking the address.\nCombined, these restrictions allow implementation strategies such as in-register\nparameters.\n\n### Polymorphic types\n\nValue expressions and value bindings can be used with\n[polymorphic types](/docs/design/classes.md#inheritance), for example:\n\n```carbon\nbase class MyBase { ... }\n\nfn UseBase(b: MyBase) { ... }\n\nclass Derived {\n  extend base: MyBase;\n  ...\n}\n\nfn PassDerived() {\n  var d: Derived = ...;\n  // Allowed to pass `d` here:\n  UseBase(d);\n}\n```\n\nThis is still allowed to create a copy or to move, but it must not _slice_. Even\nif a copy is created, it must be a `Derived` object, even though this may limit\nthe available implementation strategies.\n\n> **Future work:** The interaction between a\n> [custom value representation](#value-representation-and-customization) and a\n> value expression used with a polymorphic type needs to be fully captured.\n> Either it needs to restrict to a `const ref` style representation (to prevent\n> slicing) or it needs to have a model for the semantics when a different value\n> representation is used.\n\n### Interop with C++ `const &` and `const` methods\n\nWhile value expressions cannot have their address taken in Carbon, they should\nbe interoperable with C++ `const &`s and C++ `const`-qualified methods. This\nwill in-effect \"pin\" some object (potentially a copy or temporary) into memory\nand allow C++ to take its address. Without supporting this, values would likely\ncreate an untenable interop ergonomic barrier. However, this does create some\nadditional constraints on value expressions and a way that their addresses can\nescape unexpectedly.\n\nDespite interop requiring an address to implement, C++ allows `const &`\nparameters to bind to temporary objects where that address doesn't have much\nmeaning and might not be valid once the called function returns. As a\nconsequence, we don't expect C++ interfaces using a `const &` to misbehave in\npractice.\n\n> **Future work:** when a type customizes its\n> [value representation](#value-representation-and-customization), as currently\n> specified this will break the use of `const &` C++ APIs with such a value. We\n> should extend the rules around value representation customization to require\n> that either the representation type can be converted to (a copy) of the\n> customized type, or implements an interop-specific interface to compute a\n> `const` pointer to the original object used to form the representation object.\n> This will allow custom representations to either create copies for interop or\n> retain a pointer to the original object and expose that for interop as\n> desired.\n\nAnother risk is exposing Carbon's value expressions to `const &` parameters in\nthis way, as C++ allows casting away `const`. However, in the absence of\n`mutable` members, casting away `const` does not make it safe to _mutate_\nthrough a `const &` parameter (or a `const`-qualified method). C++ allows\n`const &` parameters and `const` member functions to access objects that are\n_declared_ `const`. These objects cannot be mutated, even if `const` is removed,\nexactly the same as Carbon value expressions. In fact, these kinds of mutations\n[break in real implementations](https://cpp.compiler-explorer.com/z/KMhTondaK).\nThe result is that Carbon's value expressions will work similarly to\n`const`-declared objects in C++, and will interop with C++ code similarly well.\n\n### Escape hatches for value addresses in Carbon\n\n**Open question:** It may be necessary to provide some amount of escape hatch\nfor taking the address of values. The\n[C++ interop](#interop-with-c-const--and-const-methods) above already takes\ntheir address functionally. Currently, this is the extent of an escape hatch to\nthe restrictions on values.\n\nIf a further escape hatch is needed, this kind of fundamental weakening of the\nsemantic model would be a good case for some syntactic marker like Rust's\n`unsafe`, although rather than a region, it would seem better to tie it directly\nto the operation in question. For example:\n\n```carbon\nclass S {\n  fn ValueMemberFunction[self: Self]();\n  fn RefMemberFunction[ref self: const Self]();\n}\n\nfn F(s_value: S) {\n  // This is fine.\n  s_value.ValueMemberFunction();\n\n  // This requires an unsafe marker in the syntax.\n  s_value.unsafe RefMemberFunction();\n}\n```\n\nThe specific tradeoff here is covered in a proposal\n[alternative](/proposals/p2006.md#value-expression-escape-hatches).\n\n## Initializing expressions\n\nStorage in Carbon is initialized using _initializing expressions_. Their\nevaluation takes a _result location_ as an implicit input, and produces an\ninitialized object at that location, although that object may still be\n_unformed_.\n\n**Future work:** More details on initialization and unformed objects should be\nadded to the design from the proposal\n[#257](https://github.com/carbon-language/carbon-lang/pull/257), see\n[#1993](https://github.com/carbon-language/carbon-lang/issues/1993). When added,\nit should be linked from here for the details on the initialization semantics\nspecifically.\n\nThe simplest form of initializing expressions are value or durable reference\nexpressions that are converted into an initializing expression. Value\nexpressions are written directly into the storage to form a new object.\nReference expressions have the object they refer to copied into a new object in\nthe provided storage.\n\n**Future work:** The design should be expanded to fully cover how copying is\nmanaged and linked to from here.\n\nThere are no syntactic contexts in Carbon that always require an initializing\nexpression, and no expression syntax that always produces an initializing\nexpression. By default, function call expressions are initializing expressions,\nand correspondingly the operand of `return` is required to be an initializing\nexpression, but this default can be overridden by the\n[function signature](#function-calls-and-returns).\n\nInitializing expressions can also be created implicitly, when attempting to\nconvert an expression into an ephemeral entire reference expression\n(particularly to match a `var` pattern): the expression is first converted to an\ninitializing expression if necessary, and then temporary storage is materialized\nto act as its output, and as the referent of the resulting ephemeral reference\nexpression.\n\n### Function calls and returns\n\nThe [result](#expression-forms) of a function call can have an almost arbitrary\nform. The return clause of a function signature consists of `->` followed by a\n_return form_, an expression-like syntax that specifies not only the type but\nalso the form of the function call's result. `return` expressions in the\nfunction body are expected to have that form, and are converted to it if\nnecessary. When a function is declared without a return clause, it behaves from\nthe caller's point of view as if the return clause were `-> ()`, but `return`\nstatements in the function body don't take operands (and can be omitted at the\nend of the function).\n\nIn the common case, the return form is a type expression, in which case calls\nare modeled directly as initializing expressions -- they require storage as an\ninput and when evaluated cause that storage to be initialized with an object.\nThis means that when a function call is used to initialize some variable pattern\nas here:\n\n```carbon\nfn CreateMyObject() -> MyType {\n  return <return-expression>;\n}\n\nvar x: MyType = CreateMyObject();\n```\n\nThe `<return-expression>` in the `return` statement actually initializes the\nstorage provided for `x`. There is no \"copy\" or other step.\n\nIn the body of such a function, all `return` statement expressions are required\nto be initializing expressions and in fact initialize the storage provided to\nthe function's call expression. This in turn causes the property to hold\n_transitively_ across an arbitrary number of function calls and returns. The\nstorage is forwarded at each stage and initialized exactly once.\n\nMore generally, the syntax and semantics of a return form are as follows:\n\n-   _return-clause_ ::= `->` _return-form_\n-   _return-form_ ::= _nesting-return-form_ | _auto-return-form_\n-   _nesting-return-form_ ::= _expression-return-form_ | _proper-return-form_\n\nReturn forms can usually be nested, but syntaxes involving `auto` can only occur\nat top level. We further divide nesting return forms into expressions and\n\"proper\" return forms, but this is just a technical means of avoiding formal\nambiguity in the grammar; it has no greater significance.\n\n-   _category-tag_ ::= `val` | `ref` | `var`\n\nThese tags are used to specify \"value\", \"non-entire durable reference\", or\n\"initializing\" expression category (respectively). Note that there is no way to\nexpress an entire or ephemeral reference category in a return form.\n\n-   _auto-return-form_ ::= _category-tag_? `auto`\n\nThis denotes a primitive form with runtime phase and deduced type. The category\nis determined by _category-tag_ if present, or \"initializing\" otherwise.\n\n-   _proper-return-form_ ::= _category-tag_ _expression_\n\nThis denotes a primitive form with runtime phase, category _category-tag_, and\ntype \"_expression_ `as type`\".\n\n-   _expression-return-form_ ::= _expression_\n\nAn expression with no _category-tag_ is equivalent to \"`var` _expression_\".\n\n-   _proper-return-form_ ::= `(` [_expression-return-form_ `,`]\\* _proper-return-form_\n    [`,` _nesting-return-form_]\\* `,`? `)`\n\nA tuple literal of return forms denotes a tuple form whose sub-forms are\nspecified by the comma-separated elements. To avoid formal ambiguity, this\ngrammar rule requires at least one of the sub-forms to be proper.\n\n-   _expression-field-form_ ::= _designator_ `:` _expression-return-form_\n-   _proper-field-form_ ::= _designator_ `:` _proper-return-form_\n-   _field-form_ ::= _field-decl_\n-   _field-form_ ::= _proper-field-form_\n-   _proper-return-form_ ::= `{` [_expression-field-form_ `,`]\\* _proper-field-form_\n    [`,` _field-form_]\\* `}`\n\nA struct literal of return forms denotes a struct form whose field names and\ntheir forms are specified by the comma-separated field forms. To avoid formal\nambiguity, this grammar rule requires at least one of the field forms to be\nproper.\n\n> **Open question:** Should there be a way to specify symbolic or template phase\n> in return forms?\n\n#### Deferred initialization from values and references\n\nTODO: This section needs to be updated to reflect the addition of `-> val`\nreturns in [proposal #5434](/proposals/p5434.md). This section could be replaced\nby a statement that initializing returns may be replaced by value returns when\nthat is safe and correct, moving much of this content into a description of how\nvalue returns works.\n\nCarbon also makes the evaluation of function calls and return statements tightly\nlinked in order to enable more efficiency improvements. It allows the actual\ninitialization performed by the `return` statement with its expression to be\ndeferred from within the body of the function to the caller initializer\nexpression if it can simply propagate a value or reference expression to the\ncaller that is guaranteed to be alive and available to the caller.\n\nConsider the following code:\n\n```carbon\nfn SelectSecond(first: Point, second: Point, third: Point) -> Point {\n  return second;\n}\n\nfn UsePoint(p: Point);\n\nfn F(p1: Point, p2: Point) {\n  UsePoint(SelectSecond(p2, p1, p2));\n}\n```\n\nThe call to `SelectSecond` must provide storage for a `Point` that can be\ninitialized. However, Carbon allows an implementation of the actual\n`SelectSecond` function to not initialize this storage when it reaches\n`return second`. The expression `second` is a name bound to the call's argument\nvalue expression, and that value expression is necessarily valid in the caller.\nCarbon in this case allows the implementation to merely communicate that the\nreturned expression is a name bound to a specific value expression argument to\nthe call, and the caller _if necessary_ should initialize the temporary storage.\nThis in turn allows the caller `F` to recognize that the value expression\nargument (`p1`) is already valid to pass as the argument to `UsePoint` without\ninitializing the temporary storage from it and reading it back out of that\nstorage.\n\nNone of this impacts the type system and so an implementation can freely select\nspecific strategies here based on concrete types without harming generic code.\nEven if generics were to be implemented without monomorphization, for example\ndynamic dispatch of object-safe interfaces, there is a conservatively correct\nstrategy that will work for any type.\n\nThis freedom mirrors that of [input values](#value-expressions) where might be\nimplemented as either a reference or a copy without breaking genericity. Here\ntoo, many small types will not need to be lazy and simply eagerly initialize the\ntemporary which is implemented as an actual machine register. But for large\ntypes or ones with associated allocated storage, this can reliably avoid\nextraneous memory allocations and other costs.\n\nNote that this flexibility doesn't avoid the call expression materializing\ntemporary storage and providing it to the function. Whether the function needs\nthis storage is an implementation detail. It simply allows deferring an\nimportant case of initializing that storage from a value or reference expression\nalready available in the caller to the caller so that it can identify cases\nwhere that initialization is not necessary.\n\n**References:** This addresses an issue-for-leads about\n[reducing the potential copies incurred by returns](https://github.com/carbon-language/carbon-lang/issues/828).\n\n#### Declared `returned` variable\n\nThe model of initialization of returns also facilitates the use of\n[`returned var` declarations](control_flow/return.md#returned-var). These\ndirectly observe the storage provided for initialization of a function's return.\n\n## Expression forms\n\nWe typically treat the category and type of an expression as independent\nproperties. However, in some cases we need to deal with them as an integrated\nwhole. The _form_ of an expression captures all of the information about it that\nis visible to the type system, while abstracting away all other information\nabout it. Thus, forms are a generalization of types: what we conventionally call\n\"types\" are really the types of objects and values, whereas forms are the types\nof expressions and patterns.\n\nA _primitive form_ currently consists of a type, an expression category, an\nexpression phase, and optionally a constant value (which is present if and only\nif the expression phase is not \"runtime\"). When dealing with primitive forms,\nwhich is the common case, we can treat each of those properties as independent.\nFor convenience, in this section we will use the notation `<T, C, P, V>` to\nrepresent a primitive form with type `T`, category `C`, phase `P` and value `V`,\nbut this is not Carbon syntax.\n\nOther forms are called _composite forms_, and there are two kinds:\n\nA _tuple form_ can be thought of as a tuple of forms, just as a tuple type can\nbe thought of as a tuple of types. The form of a tuple literal is a tuple form,\nwhose elements are the forms of the literal elements.\n\n> **TODO:** Extend this to support variadic forms.\n\nA _struct form_ can be thought of as a struct whose fields are forms, just as a\nstruct type can be thought of as a struct whose fields are types. The form of a\nstruct literal is a struct form with the same field names, whose values are the\nforms of the corresponding fields of the struct literal.\n\nThe _type component_ of a form is defined as follows:\n\n-   The type component of a primitive form `<T, C, P, V>` is `T`.\n-   The type component of a tuple form is a tuple of the type components of its\n    elements.\n-   The type component of a struct form is a struct whose field names are the\n    field names of the struct form and whose field types are the type components\n    of the corresponding elements.\n\nThe _category component_ and _phase component_ of a form are defined likewise.\nThe category component of a struct form is called a _struct category_, and the\ncategory component of a tuple form is called a _tuple category_.\n\nThe type of an expression is the type component of the expression's form.\n\nEvaluating an expression produces a _result_. It can be defined recursively in\nterms of the expression's form:\n\n-   The result of an initializing expression is an\n    [initializing result](#initializing-results).\n-   The result of a value expression is a value.\n-   The result of a reference expression is a reference of the same kind.\n-   The result of an expression with tuple form is a tuple of results.\n-   The result of an expression with struct form is a struct of results.\n\nAn expression and its result always have the same form.\n\nThe code that accesses the result of an expression is said to _consume_ that\nresult, and every primitive-form result is consumed exactly once (except in\ncertain narrow contexts where the result is known not to be initializing). If a\nresult isn't explicitly accessed, such as when the expression is used as a\nstatement, it is said to be _discarded_, which consumes it in the absence of an\nexplicit consumer. Discarding an initializing result materializes and then\nimmediately destroys it. Discarding an entire ephemeral reference destroys the\nobject it refers to. Discarding a value or any other kind of reference is a\nno-op.\n\n### Initializing results\n\nAs discussed earlier, evaluation of an initializing expression takes as an input\nthe result location that it initializes, which is implicitly provided by the\ncontext in which the evaluation takes place. In some cases, the context may\nobtain the location from its own context, and so on. For example:\n\n```carbon\nclass C {\n  private var i: i32;\n\n  fn Make() -> C {\n    return {.i = 0};\n  }\n}\n\nfn F() -> C {\n  return C.Make();\n}\n\nfn G() {\n  var c: C = F();\n}\n```\n\nBy default, a function call is an initializing expression, and a `return`\nstatement initializes the call's result location (which is passed as a hidden\noutput parameter). So when the declaration of `c` is evaluated, its storage is\nimplicitly passed into `F()` as an output parameter, which is initialized by the\n`return` statement inside `F`. When that `return` statement is evaluated to\ninitialize the result location, it likewise implicitly passes the storage into\n`C.Make()` as an output parameter, which is initialized by the `return`\nstatement inside `C.Make`. Finally, that `return` statement initializes the\nresult location (which is still the location of `c`'s storage) by\n[direct initialization](#direct-initialization) from the value expression\n`{.i = 0}`.\n\nNotice that the implicit storage parameter propagates \"backwards\", into an\nexpression from the code that uses its result. In order to simplify the\ndescription of the language, we usually won't explicitly discuss the result\nlocations of initializing expressions, or how they're propagated. Instead, this\npropagation is encapsulated inside the _initializing result_, which is the\nnotional result of an initializing expression.\n\nWhenever an initializing result is consumed, that implicitly means that the\nconsumer passes a result location into the evaluation of the initializing\nexpression. The source of that location depends on the consumer:\n\n-   If the consumer is a temporary materialization conversion, the result\n    location is newly-allocated temporary storage (which the consumer may\n    subsequently lifetime-extend to durable storage).\n-   If the consumer is a `return` statement, and the initializing result\n    corresponds to an initializing sub-form of the function's return form, the\n    result location is the implicit output parameter corresponding to that\n    initializing sub-form.\n\n### Form conversions\n\nA conversion between forms can be broken down into up to three steps: type\nconversion, category conversion, and phase conversion. These convert the form to\na particular target type, category, and phase component (respectively). These\nsteps aren't fully orthogonal: type conversions can change the category and\nphase components as a byproduct, and category conversions can change the phase\ncomponent. However, category conversions can't change the type component, and\nphase conversions can't change either of the other two, so converting the type,\nthen category, then phase, ensures that we converge on the desired result.\n\nAny of these steps may be omitted, depending on whether the context imposes\nrequirements on the corresponding component. Most commonly, an operand position\nrequires its operand to have a primitive form with a particular category,\nusually with a particular type, and sometimes with a particular phase.\n\nPhase conversions cannot change the form structure; they can only apply\nprimitive phase conversions to primitive sub-forms. Type and category\nconversions are more complex, and are covered in the next two sections.\n\nNote that these rules will implicitly convert between primitive and composite\nforms in both directions (except that a composite containing references cannot\nbe converted to a primitive form). As a result, although the difference between\nprimitive and composite forms is observable by way of overloading, it can't\nreliably carry any higher-level meaning, and should be used only as an\noptimization tool.\n\nNote that this section describes the _logical structure_ of form conversions. As\nsuch, it primarily describes them \"breadth-first\", as a sequence of operations\nthat each applies to the whole expression by recursively operating on its parts.\nHowever, the _physical execution_ of these conversions is actually depth-first,\napplying as many operations as possible to a minimal subexpression before moving\non to the next one. The details of that process are described\n[here](pattern_matching.md#evaluation-order).\n\n#### Type conversions\n\nSee [here](expressions/implicit_conversions.md) for overall information about\ntype conversions. Conversions involving struct, tuple, and array types are\ndescribed here because of their unique interactions with expression forms.\n\n> **TODO:** A forthcoming proposal is expected to update the type conversion\n> interfaces to permit user-defined conversions to depend on the form of the\n> input, and customize the form of the output. Once that is done, these \"built\n> in\" conversions should be presented as implementations of those interfaces,\n> possibly with some \"magic\" for things like introspecting on struct field\n> names.\n\nEach of the conversions described in this section is explicit if and only if it\ninvokes another explicit type conversion. Otherwise, it is implicit.\n\nA type conversion of a primitive-form expression to a\n[compatible type](generics/terminology.md#compatible-types) just re-interprets\nthe expression's result with a new type, so it requires no run-time work, and\nhas the same category as the input expression.\n\nA result `source` that has a struct type can be converted to a struct type\n`Dest` if they have the same set of field names:\n\n-   If the type of `source` is `Dest`, return `source`.\n-   If `source` is a struct result, for each field name `F` in `Dest`,\n    type-convert `source.F` to `Dest.F`. Return a struct result where each field\n    `F` is set to the result of the corresponding conversion.\n-   If `source` is a primitive result, convert it to a struct result by\n    [form decomposition](#category-conversions), and then type-convert the\n    result to `Dest` and return the result.\n\nNote that the sub-conversions invoked here are not necessarily defined; if so,\nthe conversion itself is not defined.\n\nThere is a conversion to a class type `Dest` from a result `source` that has a\nstruct type, if there is a conversion from `source` to a struct type that has\nthe same field names as `Dest` (including a `.base` field if `Dest` is a derived\nclass), with the same types, in the same order. The conversion type-converts\n`source` to that struct type, category-converts that to an initializing\nexpression of the struct type, and then reinterprets it as an initializing\nexpression of `Dest` (which is layout-compatible with the struct type by\nconstruction).\n\nNote that some fields of an object may be initialized directly by the evaluation\nof the source expression, while others may be initialized by the conversions\ndescribed here. The conversions initialize fields in their declaration order,\nbut the evaluation of the source expression always happens before any of the\nconversions, and happens in the source expression's lexical order, so the fields\nof an object are not necessarily initialized in declaration order.\n\nConversions between tuple types are defined in the same way, treating tuples as\nstructs that have fields named `.0`, `.1`, etc, in numerical order.\n\nThere is a conversion to `array(T, N)` from any expression with a tuple form of\nexactly `N` elements, whose type components are convertible to `T`. The\nconversion is an initializing expression, which type-converts each source\nelement to `T`, and initializes the corresponding array element from the result\nof that conversion.\n\n#### Category conversions\n\n_Form composition_ converts an expression of composite form with consistent\ncategory to a primitive form as follows (where `min` as applied to phases uses\nthe ordering \"runtime\" < \"symbolic\" < \"template\"):\n\n-   An expression of tuple form\n    `(<T1, C, P1, V1>, <T2, C, P2, V2>, ... <TN, C, PN, VN>)` can be converted\n    to a primitive form\n    `<(T1, T2, ..., TN), C, min(P1, P2, ..., PN), (V1, V2, ... VN)>`.\n-   An expression of struct form\n    `{.a = <Ta, C, Pa, Va>, .b = <Tb, C, Pb, Vb>, ... .z = <Tz, C, Pz, Vz>}` can\n    be converted to a primitive form\n    `<{.a = Ta, .b = Tb, ... .z = Tz}, C, min(Pa, Pb, ... Pz), {.a = Va, .b = Vb, ... .z = Vz}>`.\n\nWhen `C` is \"value\", composition forms a value representation of the aggregate\nfrom value representations of the elements. When `C` is \"initializing\", it\ntransforms initializing expressions for each element into a single initializing\nexpression that initializes the whole aggregate. `C` cannot be a reference\ncategory, because an aggregate of references to independent objects can't be\nreplaced by a reference to a single aggregate object in a single step.\n\n_Form decomposition_ is the inverse of form composition. It converts a\nprimitive-form expression to a composite form as follows:\n\n-   An expression with primitive form `<(T0, T1, ..., TN), C, P, V>` can be\n    converted to a tuple form\n    `(<T0, CC, P, V.0>, <T1, CC, P, V.1>, ... <TN, CC, P, V.N>)`.\n-   An expression with primitive form\n    `<{.a = Ta, .b = Tb, ... .z = Tz}, C, P, V>` can be converted to a struct\n    form\n    `{.a = <Ta, CC, P, V.a>, .b = <Tb, CC, P, V.b>, ... .z = <Tz, CC, P, V.z>}`.\n\nThe category `CC` of the resulting sub-forms is the same as `C`, with two\nexceptions:\n\n-   If `C` is \"durable entire reference\", `CC` will be \"durable non-entire\n    reference\", because the sub-forms don't refer to complete objects. This\n    doesn't apply to ephemeral entire references, because in that case form\n    decomposition implicitly ends the lifetime of the original aggregate,\n    promoting its elements to complete objects with independent lifetimes.\n-   If `C` is \"initializing\", the original expression is materialized before it\n    is decomposed, so `CC` will be \"ephemeral entire reference\".\n\nBy convention, form decomposition is a no-op when applied to an expression with\nstruct or tuple form.\n\n_Category conversion_ converts an expression to have a given category component\nwithout changing its type. The conversion works by combining form composition\nand decomposition with primitive category conversions, and is defined\nrecursively:\n\n-   If the target category component is a tuple, the source form must have a\n    tuple type with the same arity. Convert the source to a tuple form by form\n    decomposition, and then category-convert each source sub-form to the\n    corresponding target sub-category.\n-   If the target category component is a struct, the source form must have a\n    struct type with the same set of field names in the same order. Convert the\n    source to a struct form by form decomposition, and then category-convert\n    each source sub-form to the corresponding target sub-category.\n-   If the target category is a primitive category `C`:\n    -   If the source form is primitive, convert to `C` by applying primitive\n        category conversions.\n    -   If the source form is composite and `C` is a reference category,\n        category-convert the source form to \"initializing\", and then convert the\n        result to `C` by applying primitive category conversions.\n    -   If the source form is composite and `C` is not a reference category,\n        category-convert each source sub-form to `C`, and then convert the\n        aggregate result of these conversions to `C` by form composition.\n\n## Pointers\n\nPointers in Carbon are the primary mechanism for _indirect access_ to storage\ncontaining some value. Dereferencing a pointer is one of the primary ways to\nform a [_durable reference expression_](#durable-reference-expressions).\n\nCarbon pointers are heavily restricted compared to C++ pointers -- they cannot\nbe null and they cannot be indexed or have pointer arithmetic performed on them.\nIn some ways, this makes them more similar to references in C++, but they retain\nthe essential aspect of a pointer that they syntactically distinguish between\nthe point*er* and the point*ee*.\n\nCarbon will still have mechanisms to achieve the equivalent behaviors as C++\npointers. Optional pointers are expected to serve nullable use cases. Slice or\nview style types are expected to provide access to indexable regions. And even\nraw pointer arithmetic is expected to be provided at some point, but through\nspecialized constructs given the specialized nature of these operations.\n\n**Future work:** Add explicit designs for these use cases and link to them here.\n\n### Reference types\n\nTODO: This section needs to be updated to reflect\n[proposal #5434](/proposals/p5434.md).\n\nUnlike C++, Carbon does not currently have reference types. The only form of\nindirect access are pointers. There are a few aspects to this decision that need\nto be separated carefully from each other as the motivations and considerations\nare different.\n\nFirst, Carbon has only a single fundamental construct for indirection because\nthis gives it a single point that needs extension and configuration if and when\nwe want to add more powerful controls to the indirect type system such as\nlifetime annotations or other safety or optimization mechanisms. The designs\nattempts to identify a single, core indirection tool and then layer other\nrelated use cases on top. This is motivated by keeping the language scalable as\nit evolves and reducing the huge explosion of complexity that C++ sees due to\nhaving a large space here. For example, when there are N > 1 ways to express\nindirection equivalently and APIs want to accept any one of them across M\ndifferent parameters they can end up with N \\* M combinations.\n\nSecond, with pointers, Carbon's indirection mechanism retains the ability to\nrefer distinctly to the point*er* and the point*ee* when needed. This ends up\ncritical for supporting rebinding and so without this property more permutations\nof indirection would likely emerge.\n\nThird, Carbon doesn't provide a straightforward way to avoid the syntactic\ndistinction between indirect access and direct access.\n\nFor a full discussion of the tradeoffs of these design decisions, see the\nalternatives considered section of [P2006]:\n\n-   [References in addition to pointers](/proposals/p2006.md#references-in-addition-to-pointers)\n-   [Syntax-free or automatic dereferencing](/proposals/p2006.md#syntax-free-or-automatic-dereferencing)\n-   [Exclusively using references](/proposals/p2006.md#exclusively-using-references)\n\n### Pointer syntax\n\nThe type of a pointer to a type `T` is written with a postfix `*` as in `T*`.\nDereferencing a pointer is a [_reference expression_] and is written with a prefix\n`*` as in `*p`:\n\n```carbon\nvar i: i32 = 42;\nvar p: i32* = &i;\n\n// Form a reference expression `*p` and assign `13` to the referenced storage.\n*p = 13;\n```\n\nThis syntax is chosen specifically to remain as similar as possible to C++\npointer types as they are commonly written in code and are expected to be\nextremely common and a key anchor of syntactic similarity between the languages.\nThe different alternatives and tradeoffs for this syntax issue were discussed\nextensively in [#523] and are summarized in the\n[proposal](/proposals/p2006.md#alternative-pointer-syntaxes).\n\n[#523]: https://github.com/carbon-language/carbon-lang/issues/523\n\nCarbon also supports an infix `->` operation, much like C++. However, Carbon\ndirectly defines this as an exact rewrite to `*` and `.` so that `p->member`\nbecomes `(*p).member` for example. This means there is no overloaded or\ncustomizable `->` operator in Carbon the way there is in C++. Instead,\ncustomizing the behavior of `*p` in turn customizes the behavior of `p->`.\n\n**Future work:** As [#523] discusses, one of the primary challenges of the C++\nsyntax is the composition of a prefix dereference operation and other postfix or\ninfix operations, especially when chained together such as a classic C++\nfrustrations of mixes of dereference and indexing: `(*(*p)[42])[13]`. Where\nthese compositions are sufficiently common to create ergonomic problems, the\nplan is to introduce custom syntax analogous to `->` that rewrites down to the\ngrouped dereference. However, nothing beyond `->` itself is currently provided.\nExtending this, including the exact design and scope of extension desired, is a\nfuture work area.\n\n### Dereferencing customization\n\nCarbon should support user-defined pointer-like types such as _smart pointers_\nusing a similar pattern as operator overloading or other expression syntax. That\nis, it should rewrite the expression into a member function call on an\ninterface. Types can then implement this interface to expose pointer-like\n_user-defined dereference_ syntax.\n\nThe interface might look like:\n\n```carbon\ninterface Pointer {\n  let ValueT:! Type;\n  fn Dereference[self: Self]() -> ValueT*;\n}\n```\n\nHere is an example using a hypothetical `TaggedPtr` that carries some extra\ninteger tag next to the pointer it emulates:\n\n```carbon\nclass TaggedPtr(T:! Type) {\n  var tag: Int32;\n  var ptr: T*;\n}\nexternal impl [T:! Type] TaggedPtr(T) as Pointer {\n  let ValueT:! T;\n  fn Dereference[self: Self]() -> T* { return self.ptr; }\n}\n\nfn Test(arg: TaggedPtr(T), dest: TaggedPtr(TaggedPtr(T))) {\n  **dest = *arg;\n  *dest = arg;\n}\n```\n\nThere is one tricky aspect of this. The function in the interface which\nimplements a pointer-like dereference must return a raw pointer which the\nlanguage then actually dereferences to form a reference expression similar to\nthat formed by `var` declarations. This interface is implemented for normal\npointers as a no-op:\n\n```carbon\nimpl [T:! Type] T* as Pointer {\n  let ValueT:! Type = T;\n  fn Dereference[self: Self]() -> T* { return self; }\n}\n```\n\nDereference expressions such as `*x` are syntactically rewritten to use this\ninterface to get a raw pointer and then that raw pointer is dereferenced. If we\nimagine this language level dereference to form a reference expression as a\nunary `deref` operator, then `(*x)` becomes\n`(deref (x.(Pointer.Dereference)()))`.\n\nCarbon will also use a simple syntactic rewrite for implementing `x->Method()`\nas `(*x).Method()` without separate or different customization.\n\n## `const`-qualified types\n\nCarbon provides the ability to qualify a type `T` with the keyword `const` to\nget a `const`-qualified type: `const T`. This is exclusively an API-subsetting\nfeature in Carbon -- for more fundamentally \"immutable\" use cases, value\nexpressions and bindings should be used instead. Pointers to `const`-qualified\ntypes in Carbon provide access to an object with an API subset that can help\nmodel important requirements like ensuring usage is exclusively by way of a\n_thread-safe_ interface subset of an otherwise _thread-compatible_ type.\n\nNote that `const T` is a type qualification and is generally orthogonal to\nexpression categories or what form of pattern is used, including for object\nparameters. Notionally, it can occur both with `ref` and value object\nparameters. However, on value patterns, it is redundant as there is no\nmeaningful distinction between a value expression of type `T` and type\n`const T`. For example, given a type and methods:\n\n```carbon\nclass X {\n  fn Method[self: Self]();\n  fn ConstMethod[self: const Self]();\n  fn RefMethod[ref self: Self]();\n  fn RefConstMethod[ref self: const Self]();\n}\n```\n\nThe methods can be called on different kinds of expressions according to the\nfollowing table:\n\n| Expression category: | `let x: X` <br/> (value) | `let x: const X` <br/> (const value) | `var x: X` <br/> (reference) | `var x: const X` <br/> (const reference) |\n| -------------------: | ------------------------ | ------------------------------------ | ---------------------------- | ---------------------------------------- |\n|        `x.Method();` | ✅                       | ✅                                   | ✅                           | ✅                                       |\n|   `x.ConstMethod();` | ✅                       | ✅                                   | ✅                           | ✅                                       |\n|     `x.RefMethod();` | ❌                       | ❌                                   | ✅                           | ❌                                       |\n| `x.RefConstMethod()` | ❌                       | ❌                                   | ✅                           | ✅                                       |\n\nThe `const T` type has the same representation as `T` with the same field names,\nbut all of its field types are also `const`-qualified. Other than fields, all\nother members `T` are also members of `const T`, and impl lookup ignores the\n`const` qualification. There is an implicit conversion from `T` to `const T`,\nbut not the reverse. Conversion of reference expressions to value expressions is\ndefined in terms of `const T` reference expressions to `T` value expressions.\n\nIt is expected that `const T` will largely occur as part of a\n[pointer](#pointers), as the express purpose is to form reference expressions.\nThe precedence rules are even designed for this common case, `const T*` means\n`(const T)*`, or a pointer-to-const. Carbon will support conversions between\npointers to `const`-qualified types that follow the same rules as used in C++ to\navoid inadvertent loss of `const`-qualification.\n\nThe syntax details of `const` are also covered in the\n[type operators](/docs/design/expressions/type_operators.md) documentation.\n\n## Lifetime overloading\n\nOne potential use case that is not obviously or fully addressed by these designs\nin Carbon is overloading function calls by observing the lifetime of arguments.\nThe use case here would be selecting different implementation strategies for the\nsame function or operation based on whether an argument lifetime happens to be\nending and viable to move-from.\n\nCarbon currently intentionally leaves this use case unaddressed. There is a\nfundamental scaling problem in this style of overloading: it creates a\ncombinatorial explosion of possible overloads similar to other permutations of\nindirection models. Consider a function with N parameters that would benefit\nfrom lifetime overloading. If each parameter benefits _independently_ from the\nothers, as is commonly the case, we would need 2<sup>N</sup> overloads to\nexpress all the possibilities.\n\nCarbon will initially see if code can be designed without this facility. Some of\nthe tools needed to avoid it are suggested above such as the\n[consuming](#consuming-function-parameters) input pattern. But it is possible\nthat more will be needed in practice. It would be good to identify the specific\nand realistic Carbon code patterns that cannot be expressed with the tools in\nthis proposal in order to motivate a minimal extension. Some candidates based on\nfunctionality already proposed here or for [classes](/docs/design/classes.md):\n\n-   Allow overloading between `ref self` and `self` in methods. This is among\n    the most appealing as it _doesn't_ have the combinatorial explosion. But it\n    is also very limited as it only applies to the implicit object parameter.\n-   Allow overloading between `var` and non-`var` parameters.\n-   Allow overloading between `ref` and non-`ref` parameters in general.\n\nPerhaps more options will emerge as well. Again, the goal isn't to completely\npreclude pursuing this direction, but instead to try to ensure it is only\npursued based on a real and concrete need, and the minimal extension is adopted.\n\n## Value representation and customization\n\nThe representation of a value expression is especially important because it\nforms the calling convention used for the vast majority of function parameters\n-- function inputs. Given this importance, it's important that it is predictable\nand customizable by the value's type. Similarly, while Carbon code must be\ncorrect with either a copy or a reference-based implementation, we want which\nimplementation strategy is used to be a predictable and customizable property of\nthe type of a value.\n\nA type can optionally control its value representation using a custom syntax\nsimilar to customizing its [destructor](/docs/design/classes.md#destructors).\nThis syntax sets the representation to some type uses a keyword `value_rep` and\ncan appear where a member declaration would be valid within the type:\n\n```carbon\nclass SomeType {\n  value_rep = RepresentationType;\n}\n```\n\n**Open question:** The syntax for this is just placeholder, using a placeholder\nkeyword. It isn't final at all and likely will need to change to read well.\n\nThe provided representation type must be one of the following:\n\n-   `const Self` -- this forces the use of a _copy_ of the object.\n-   `const ref` -- this forces the use of a [_pointer_](#pointers) to the\n    original object, but with the `const` API subset.\n-   A custom type that is not `Self`, `const Self`, or a pointer to either.\n\nIf the representation is `const Self` or `const ref`, then the type fields will\nbe accessible as [_value expressions_](#value-expressions) using the normal\nmember access syntax for value expressions of a type. These will be implemented\nby either accessing a copy of the object in the non-pointer case or a pointer to\nthe original object in the pointer case. A representation of `const Self`\nrequires copying to be valid for the type. This provides the builtin\nfunctionality but allows explicitly controlling which representation should be\nused.\n\nIf no customization is provided, the implementation will select one based on a\nset of heuristics. Some examples:\n\n-   Non-copyable types and polymorphic types would use a `const ref`.\n-   Small objects that are trivially copied in a machine register would use\n    `const Self`.\n\nWhen a custom type is provided, it must not be `Self`, `const Self`, or a\npointer to either. The type provided will be used on function call boundaries\nand as the implementation representation for value bindings and other value\nexpressions referencing an object of the type. A specifier of `value_rep = T;`\nwill require that the type containing that specifier satisfies the constraint\n`impls ReferenceImplicitAs where .T = T` using the following interface:\n\n```carbon\ninterface ReferenceImplicitAs {\n  let T:! type;\n  fn Convert[ref self: const Self]() -> T;\n}\n```\n\nConverting a reference expression into a value expression for such a type calls\nthis customization point to form a representation object from the original\nreference expression.\n\nWhen using a custom representation type in this way, no fields are accessible\nthrough a value expression. Instead, only methods can be called using member\naccess, as they simply bind the value expression to the `self` parameter.\nHowever, one important method can be called -- `.(ImplicitAs(T).Convert)()`.\nThis implicitly converting a value expression for the type into its custom\nrepresentation type. The customization of the representation above and\n`impls ReferenceImplicitAs where .T = T` causes the class to have a builtin\n`impl as ImplicitAs(T)` which converts to the representation type as a no-op,\nexposing the object created by calling `ReferenceImplicitAs.Convert` on the\noriginal reference expression, and preserved as a representation of the value\nexpression.\n\nHere is a more complete example of code using these features:\n\n```carbon\nclass StringView {\n  private var data_ptr: Char*;\n  private var size: i64;\n\n  fn Make(data_ptr: Char*, size: i64) -> StringView {\n    return {.data_ptr = data_ptr, .size = size};\n  }\n\n  // A typical readonly view of a string API...\n  fn ExampleMethod[self: Self]() { ... }\n}\n\nclass String {\n  // Customize the value representation to be `StringView`.\n  value_rep = StringView;\n\n  private var data_ptr: Char*;\n  private var size: i64;\n\n  private var capacity: i64;\n\n  impl as ReferenceImplicitAs where .T = StringView {\n    fn Op[ref self: const Self]() -> StringView {\n      // Because this is called on the String object prior to it becoming\n      // a value, we can access an SSO buffer or other interior pointers\n      // of `self`.\n      return StringView.Make(self.data_ptr, self.size);\n    }\n  }\n\n  // We can directly declare methods that take `self` as a `StringView` which\n  // will cause the caller to implicitly convert value expressions to\n  // `StringView` prior to calling.\n  fn ExampleMethod[self: StringView]() { self.ExampleMethod(); }\n\n  // Or we can use a value binding for `self` much like normal, but the\n  // implementation will be constrained because of the custom value rep.\n  fn ExampleMethod2[self: String]() {\n    // Error due to custom value rep:\n    self.data_ptr;\n\n    // Fine, this uses the builtin `ImplicitAs(StringView)`.\n    (self as StringView).ExampleMethod();\n  }\n\n  // Note that even though the `Self` type is `const` qualified here, this\n  // cannot be called on a `String` value! That would require us to convert to a\n  // `StringView` that does not track the extra data member.\n  fn Capacity[ref self: const Self]() -> i64 {\n    return self.capacity;\n  }\n}\n```\n\nIt is important to note that the _representation_ type of a value expression is\njust its representation and does not impact the name lookup or type. Name lookup\nand `impl` search occur for the same type regardless of the expression category.\nBut once a particular method or function is selected, an implicit conversion can\noccur from the original type to the representation type as part of the parameter\nor receiver type. In fact, this conversion is the _only_ operation that can\noccur for a value whose type has a customized value representation.\n\nThe example above also demonstrates the fundamental tradeoff made by customizing\nthe value representation of a type in this way. While it provides a great deal\nof control, it may result in some surprising limitations. Above, a method that\nis classically available on a C++ `const std::string&` like querying the\ncapacity cannot be implemented with the customized value representation because\nit loses access to this additional state. Carbon allows type authors to make an\nexplicit choice about whether they want to work with a restricted API and\nleverage a custom value representation or not.\n\n**Open question:** Beyond the specific syntax used where we currently have a\nplaceholder `value_rep = T;`, we need to explore exactly what the best\nrelationship is with the customization point. For example, should this syntax\nimmediately forward declare `impl as ReferenceImplicitAs where .T = T`, thereby\nallowing an out-of-line definition of the `Convert` method and `... where _` to\npick up the associated constant from the syntax. Alternatively, the syntactic\nmarker might be integrated into the `impl` declaration for `ReferenceImplicitAs`\nitself.\n\n## Alternatives considered\n\n-   [No `var` introducer keyword](/proposals/p0339.md#no-var-introducer-keyword)\n-   [Name of the `var` statement introducer](/proposals/p0339.md#name-of-the-var-statement-introducer)\n-   [Colon between type and identifier](/proposals/p0339.md#colon-between-type-and-identifier)\n-   [Type elision](/proposals/p0339.md#type-elision)\n-   [Type ordering](/proposals/p0618.md#type-ordering)\n-   [Elide the type instead of using `auto`](/proposals/p0851.md#elide-the-type-instead-of-using-auto)\n-   [Value expression escape hatches](/proposals/p2006.md#value-expression-escape-hatches)\n-   [References in addition to pointers](/proposals/p2006.md#references-in-addition-to-pointers)\n-   [Syntax-free or automatic dereferencing](/proposals/p2006.md#syntax-free-or-automatic-dereferencing)\n-   [Exclusively using references](/proposals/p2006.md#exclusively-using-references)\n-   [Alternative pointer syntaxes](/proposals/p2006.md#alternative-pointer-syntaxes)\n-   [Alternative syntaxes for locals](/proposals/p2006.md#alternative-syntaxes-for-locals)\n-   [Mixed expression categories](/proposals/p5545.md#mixed-expression-categories)\n-   [Don't implicitly convert to less-primitive forms](/proposals/p5545.md#dont-implicitly-convert-to-less-primitive-forms)\n\n## References\n\n-   [Proposal #257: Initialization of memory and values][p0257]\n-   [Proposal #339: `var` statement][p0339]\n-   [Proposal #618: `var` ordering][p0618]\n-   [Proposal #851: auto keyword for vars][p0851]\n-   [Proposal #2006: Values, variables, and pointers][p2006]\n-   [Proposal #5545: Expression form basics][p5545]\n\n[p0257]: /proposals/p0257.md\n[p0339]: /proposals/p0339.md\n[p0618]: /proposals/p0618.md\n[p0851]: /proposals/p0851.md\n[p2006]: /proposals/p2006.md\n[p5545]: /proposals/p5545.md\n"
  },
  {
    "path": "docs/design/variadics.md",
    "content": "# Variadics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Basics](#basics)\n    -   [Overview](#overview)\n    -   [Packs and each-names](#packs-and-each-names)\n    -   [Pack expansions](#pack-expansions)\n        -   [Pack expansion expressions and statements](#pack-expansion-expressions-and-statements)\n        -   [Pack expansion patterns](#pack-expansion-patterns)\n    -   [Additional examples](#additional-examples)\n-   [Execution Semantics](#execution-semantics)\n    -   [Expressions and statements](#expressions-and-statements)\n    -   [Pattern matching](#pattern-matching)\n-   [Typechecking](#typechecking)\n    -   [Tuples, packs, segments, and shapes](#tuples-packs-segments-and-shapes)\n    -   [Iterative typechecking of pack expansions](#iterative-typechecking-of-pack-expansions)\n    -   [Typechecking patterns](#typechecking-patterns)\n    -   [Typechecking pattern matches](#typechecking-pattern-matches)\n-   [Appendix: Type system formalism](#appendix-type-system-formalism)\n    -   [Explicit deduced arities](#explicit-deduced-arities)\n    -   [Typing and shaping rules](#typing-and-shaping-rules)\n    -   [Reduction rules](#reduction-rules)\n    -   [Equivalence, equality, and convertibility](#equivalence-equality-and-convertibility)\n    -   [Pattern match typechecking algorithm](#pattern-match-typechecking-algorithm)\n        -   [Canonicalization algorithm](#canonicalization-algorithm)\n-   [Alternatives considered](#alternatives-considered)\n-   [References](#references)\n\n<!-- tocstop -->\n\n## Basics\n\n### Overview\n\nA \"pack expansion\" is a syntactic unit beginning with `...`, which is a kind of\ncompile-time loop over sequences called \"packs\". Packs are initialized and\nreferred to using \"each-names\", which are marked with the `each` keyword at the\npoint of declaration and the point of use.\n\nThe syntax and behavior of a pack expansion depends on its context, and in some\ncases on a keyword following the `...`:\n\n-   In a tuple literal expression (such as a function call argument list), `...`\n    iteratively evaluates its operand expression, and treats the values as\n    successive elements of the tuple.\n-   `...and` and `...or` iteratively evaluate a boolean expression, combining\n    the values using `and` and `or`. Normal short-circuiting behavior for the\n    resulting `and` and `or` operators applies at runtime.\n-   In a statement context, `...` iteratively executes a statement.\n-   In a tuple literal pattern (such as a function parameter list), `...`\n    iteratively matches the elements of the scrutinee tuple. In conjunction with\n    pack bindings, this enables functions to take an arbitrary number of\n    arguments.\n\nThis example illustrates many of the key concepts:\n\n```carbon\n// Takes an arbitrary number of vectors with arbitrary element types, and\n// returns a vector of tuples where the i'th element of the vector is\n// a tuple of the i'th elements of the input vectors.\nfn Zip[... each ElementType:! type]\n      (... each vector: Vector(each ElementType))\n      -> Vector((... each ElementType)) {\n  ... var each iter: auto = each vector.Begin();\n  var result: Vector((... each ElementType));\n  while (...and each iter != each vector.End()) {\n    result.push_back((... each iter));\n    ... each iter++;\n  }\n  return result;\n}\n```\n\n### Packs and each-names\n\nA _pack_ is a sequence of a fixed number of values called \"elements\", which may\nbe of different types. Packs are very similar to tuple values in many ways, but\nthey are not first-class values -- in particular, no run-time expression\nevaluates to a pack. The _arity_ of a pack is a compile-time value representing\nthe number of values in the sequence.\n\nAn _each-name_ consists of the keyword `each` followed by the name of a pack,\nand can only occur inside a pack expansion. On the Nth iteration of the pack\nexpansion, an each-name refers to the Nth element of the named pack. As a\nresult, a binding pattern with an each-name, such as `each ElementType:! type`,\nacts as a declaration of all the elements of the named pack, and thereby\nimplicitly acts as a declaration of the pack itself.\n\nNote that `each` is part of the name syntax, not an expression operator, so it\nbinds more tightly than any expression syntax. For example, the loop condition\n`...and each iter != each vector.End()` in the implementation of `Zip` is\nequivalent to `...and (each iter) != (each vector).End()`.\n\n### Pack expansions\n\nA _pack expansion_ is an instance of one of the following syntactic forms:\n\n-   A statement of the form \"`...` _statement_\".\n-   A tuple expression element of the form \"`...` _expression_\", with the same\n    precedence as `,`.\n-   A tuple pattern element of the form \"`...` _pattern_\", with the same\n    precedence as `,`.\n-   An implicit parameter list element of the form \"`...` _pattern_\", with the\n    same precedence as `,`.\n-   An expression of the form \"`...` `and` _expression_\" or \"`...` `or`\n    _expression_\", with the same precedence as `and` and `or`.\n\nThe statement, expression, or pattern following the `...` (and the `and`/`or`,\nif present) is called the _body_ of the expansion.\n\nThe `...` token can also occur in a tuple expression element of the form \"`...`\n`expand` _expression_\", with the same precedence as `,`. However, that syntax is\nnot considered a pack expansion, and has its own semantics: _expression_ must\nhave a tuple type, and \"`...` `expand` _expression_\" evaluates _expression_ and\ntreats its elements as elements of the enclosing tuple literal. This is\nespecially useful for using non-literal tuple values as function call arguments:\n\n```carbon\nfn F(x: i32, y: String);\nfn MakeArgs() -> (i32, String);\n\nF(...expand MakeArgs());\n```\n\n`...and`, `...or`, and `...expand` can be trivially distinguished with one token\nof lookahead, and the other meanings of `...` can be distinguished from each\nother by the context they appear in. As a corollary, if the nearest enclosing\ndelimiters around a `...` are parentheses, they will be interpreted as forming a\ntuple rather than as grouping. Thus, expressions like `(... each ElementType)`\nin the above example are tuple literals, even though they don't contain commas.\n\nBy convention, `...` is always followed by whitespace, except that `...and`,\n`...or`, and `...expand` are written with no whitespace between the two tokens.\nThis serves to emphasize that the keyword is not part of the expansion body, but\nrather a modifier on the syntax and semantics of `...`.\n\nAll each-names in a given expansion must refer to packs with the same arity,\nwhich we will also refer to as the arity of the expansion. If an expansion\ncontains no each-names, it must be a pattern, or an expression in the type\nposition of a binding pattern, and its arity is deduced from the scrutinee.\n\nA pack expansion or `...expand` expression cannot contain another pack expansion\nor `...expand` expression.\n\nAn each-name cannot be used in the same pack expansion that declares it. In most\nif not all cases, an each-name that violates this rule can be changed to an\nordinary name, because each-names are only necessary when you need to transfer a\npack from one pack expansion to another.\n\n#### Pack expansion expressions and statements\n\nA pack expansion expression or statement can be thought of as a kind of loop\nthat executes at compile time (specifically, monomorphization time), where the\nexpansion body is implicitly parameterized by an integer value called the _pack\nindex_, which ranges from 0 to one less than the arity of the expansion. The\npack index is implicitly used as an index into the packs referred to by\neach-names. This is easiest to see with statement pack expansions. For example,\nif `a`, `x`, and `y` are packs with arity 3, then\n`... each a += each x * each y;` is roughly equivalent to\n\n```carbon\na[:0:] += x[:0:] * y[:0:];\na[:1:] += x[:1:] * y[:1:];\na[:2:] += x[:2:] * y[:2:];\n```\n\nHere we are using `[:N:]` as a hypothetical pack indexing operator for purposes\nof illustration; packs cannot actually be indexed in Carbon code.\n\n> **Future work:** We're open to eventually adding indexing of variadics, but\n> that remains future work and will need its own proposal.\n\n`...and` and `...or` behave like chains of the corresponding boolean operator,\nso `...and F(each x, each y)` behaves like\n`true and F(x[:0:], y[:0:]) and F(x[:1:], y[:1:]) and F(x[:2:], y[:2:])`. They\ncan also be interpreted as looping constructs, although the rewrite is less\nstraightforward because Carbon doesn't have a way to write a loop in an\nexpression context. An expression like `...and F(each x, each y)` can be thought\nof as evaluating to the value of `result` after executing the following code\nfragment:\n\n```\nvar result: bool = true;\nfor (let i:! i32 in (0, 1, 2)) {\n  result = result && F(x[:i:], y[:i:]);\n  if (result == false) { break; }\n}\n```\n\n`...` in a tuple literal behaves like a series of comma-separated tuple\nelements, so `(... F(each x, each y))` is equivalent to\n`(F(x[:0:], y[:0:]), F(x[:1:], y[:1:]), F(x[:2:], y[:2:]))`. This can't be\nexpressed as a loop in Carbon code, but it is still fundamentally iterative.\n\n#### Pack expansion patterns\n\nA pack expansion pattern \"`...` _subpattern_\" appears as part of a tuple pattern\n(or an implicit parameter list), and matches a sequence of tuple elements if\neach element matches _subpattern_. For example, in the signature of `Zip` shown\nearlier, the parameter list consists of a single pack expansion pattern\n`... each vector: Vector(each ElementType)`, and so the entire argument list\nwill be matched against the binding pattern\n`each vector: Vector(each ElementType)`.\n\nSince _subpattern_ will be matched against multiple scrutinees (or none) in a\nsingle pattern-matching operation, a binding pattern within a pack expansion\npattern must declare an each-name (such as `each vector` in the `Zip` example),\nand the Nth iteration of the pack expansion will initialize the Nth element of\nthe named pack from the Nth scrutinee. The binding pattern's type expression may\ncontain an each-name (such as `each ElementType` in the `Zip` example), but if\nso, it must be a deduced parameter of the enclosing pattern.\n\n> **Future work:** That restriction can probably be relaxed, but we currently\n> don't have motivating use cases to constrain the design.\n\n### Additional examples\n\n```carbon\n// Computes the sum of its arguments, which are i64s\nfn SumInts(... each param: i64) -> i64 {\n  var sum: i64 = 0;\n  ... sum += each param;\n  return sum;\n}\n```\n\n```carbon\n// Concatenates its arguments, which are all convertible to String\nfn StrCat[... each T:! ConvertibleToString](... each param: each T) -> String {\n  var len: i64 = 0;\n  ... len += each param.Length();\n  var result: String = \"\";\n  result.Reserve(len);\n  ... result.Append(each param.ToString());\n  return result;\n}\n```\n\n```carbon\n// Returns the minimum of its arguments, which must all have the same type T.\nfn Min[T:! Comparable & Value](first: T, ... each next: T) -> T {\n  var result: T = first;\n  ... if (each next < result) {\n    result = each next;\n  }\n  return result;\n}\n```\n\n```carbon\n// Invokes f, with the tuple `args` as its arguments.\nfn Apply[... each T:! type, F:! CallableWith(... each T)]\n    (f: F, args: (... each T)) -> auto {\n  return f(...expand args);\n}\n```\n\n```carbon\n// Toy example of mixing variadic and non-variadic parameters.\n// Takes an i64, any number of f64s, and then another i64.\nfn MiddleVariadic(first: i64, ... each middle: f64, last: i64);\n```\n\n```carbon\n// Toy example of using the result of variadic type deduction.\nfn TupleConcat[... each T1: type, ... each T2: type](\n    t1: (... each T1), t2: (... each T2)) -> (... each T1, ... each T2) {\n  return (...expand t1, ...expand t2);\n}\n```\n\n## Execution Semantics\n\n### Expressions and statements\n\nIn all of the following, N is the arity of the pack expansion being discussed,\nand `$I` is a notional variable representing the pack index. These semantics are\nimplemented at monomorphization time, so the value of N is a known integer\nconstant. Although the value of `$I` can vary during execution, it is\nnevertheless treated as a constant.\n\nA statement of the form \"`...` _statement_\" is evaluated by executing\n_statement_ N times, with `$I` ranging from 0 to N - 1.\n\nAn expression of the form \"`...and` _expression_\" is evaluated as follows: a\nnotional `bool` variable `$R` is initialized to `true`, and then \"`$R = $R and`\n_expression_\" is executed up to N times, with `$I` ranging from 0 to N - 1. If\nat any point `$R` becomes false, this iteration is terminated early. The final\nvalue of `$R` is the value of the expression.\n\nAn expression of the form \"`...or` _expression_\" is evaluated the same way, but\nwith `or` in place of `and`, and `true` and `false` transposed.\n\nA tuple expression element of the form \"`...` _expression_\" evaluates to a\nsequence of N values, where the k'th value is the value of _operand_ where `$I`\nis equal to k - 1.\n\nAn each-name evaluates to the `$I`th value of the pack it refers to (indexed\nfrom zero).\n\n### Pattern matching\n\nThe semantics of pack expansion patterns are chosen to follow the general\nprinciple that pattern matching is the inverse of expression evaluation, so for\nexample if the pattern `(... each x: auto)` matches some scrutinee value `s`,\nthe expression `(... each x)` should be equal to `s`. These semantics are\nimplemented at monomorphization time, so all types are known constants, and all\nall arities are known.\n\nA tuple pattern can contain no more than one subpattern of the form \"`...`\n_operand_\". When such a subpattern is present, the N elements of the pattern\nbefore the `...` expansion are matched with the first N elements of the\nscrutinee, and the M elements of the pattern after the `...` expansion are\nmatched with the last M elements of the scrutinee. If the scrutinee does not\nhave at least N + M elements, the pattern does not match.\n\nThe remaining elements of the scrutinee are iteratively matched against\n_operand_, in order. In each iteration, `$I` is equal to the index of the\nscrutinee element being matched, minus N.\n\nOn the Nth iteration, a binding pattern binds the Nth element of the named pack\nto the Nth scrutinee value.\n\n## Typechecking\n\n### Tuples, packs, segments, and shapes\n\nIn order to discuss the underlying type system for variadics, we will need to\nintroduce some pseudo-syntax to represent values and expressions that occur in\nthe type system, but cannot be expressed directly in user code. We will use\nnon-ASCII glyphs such as `«»‖⟬⟭` for that pseudo-syntax, to distinguish it from\nvalid Carbon syntax.\n\nIn the context of variadics, we will say that a tuple literal consists of a\ncomma-separated sequence of _segments_, and reserve the term \"elements\" for the\ncomponents of a tuple literal after pack expansion. For example, the expression\n`(... each foo)` may evaluate to a tuple value with any number of elements, but\nthe expression itself has exactly one segment.\n\nEach segment has a type, which expresses (potentially symbolically) both the\ntypes of the elements of the segment and the arity of the segment. The type of a\ntuple literal is a tuple literal of the types of its segments. For example,\nsuppose we are trying to find the type of `z` in this code:\n\n```carbon\nfn F[... each T:! type]((... each x: Optional(each T)), (... each y: i32)) {\n  let z: auto = (0 as f32, ... each x, ... each y);\n}\n```\n\nWe proceed by finding the type of each segment. The type of `0 as f32` is `f32`,\nby the usual non-variadic typing rules. The type of `... each x` is\n`... Optional(each T)`, because `Optional(each T)` is the declared type of\n`each x`, and the type of a pack expansion is a pack expansion of the type of\nits body.\n\nThe type of `... each y` is more complicated. Conceptually, it consists of some\nnumber of repetitions of `i32`. We don't know exactly how many repetitions,\nbecause it's implicitly specified by the caller: it's the arity of the second\nargument tuple. Effectively, that arity acts as a hidden deduced parameter of\n`F`.\n\nSo to represent this type, we need two new pseudo-syntaxes:\n\n-   `‖each X‖` refers to the deduced arity of the pack expansion that contains\n    the declaration of `each X`.\n-   `«E; N»` evaluates to `N` repetitions of `E`. This is called a _arity\n    coercion_, because it coerces the expression `E` to have arity `N`. `E` must\n    not contain any pack expansions, each-names, or pack literals (see below).\n\nCombining the two, the type of `... each y` is `... «i32; ‖each y‖»`. Thus, the\ntype of `z` is `(f32, ... Optional(each T), ... «i32; ‖each y‖»)`.\n\nNow, consider a modified version of that example:\n\n```carbon\nfn F[... each T:! type]((... each x: Optional(each T)), (... each y: i32)) {\n  let (... each z: auto) = (0 as f32, ... each x, ... each y);\n}\n```\n\n`each z` is a pack, but it has the same elements as the tuple `z` in our earlier\nexample, so we represent its type in the same way, as a sequence of segments:\n`⟬f32, Optional(each T), «i32; ‖each y‖»⟭`. The `⟬⟭` delimiters make this a\n_pack literal_ rather than a tuple literal. Notice one subtle difference: the\nsegments of a pack literal do not contain `...`. In effect, every segment of a\npack literal acts as a separate loop body. As with the tuple literal syntax, the\npack literal pseudo-syntax can also be used in patterns.\n\nThe _shape_ of a pack literal is a tuple of the arities of its segments, so the\nshape of `⟬f32, Optional(each T), «i32; ‖each y‖»⟭` is\n`(1, ‖each T‖, ‖each y‖)`. Other expressions and patterns also have shapes. In\nparticular, the shape of an arity coercion `«E; A»` is `(A,)`, the shape of\n`each X` is `(‖each X‖,)`, and the shape of an expression that does not contain\npack literals, shape coercions, or each-names is `(1,)`. The arity of an\nexpression is the sum of the elements of its shape. See the\n[appendix](#typing-and-shaping-rules) for the full rules for determining the\nshape of an expression.\n\nIf a pack literal is part of some enclosing expression that doesn't contain\n`...`, it can be _expanded_, which moves the outer expression inside the pack\nliteral. For example, `... Optional(⟬each X, Y⟭)` is equivalent to\n`... ⟬Optional(each X), Optional(Y)⟭`. Similarly, an arity coercion can be\nexpanded so long as the parent node is not `...`, a pattern, or a pack literal.\nSee the [appendix](#reduction-rules) for the full rules governing this\noperation. _Fully expanding_ an expression or pattern that does not contain a\npack expansion means repeatedly expanding any pack literals and arity coercions\nwithin it, until they cannot be expanded any further.\n\nThe _scalar components_ of a fully-expanded expression `E` are a set, defined as\nfollows:\n\n-   If `E` is a pack literal, its scalar components are the union of the scalar\n    components of the segments.\n-   If `E` is an arity coercion `«F; S»`, the only scalar component of `E` is\n    `F`.\n-   Otherwise, the only scalar component of `E` is `E`.\n\nThe scalar components of any other expression that does not contain `...` are\nthe scalar components of its fully expanded form.\n\nBy construction, a segment of a pack literal never has more than one scalar\ncomponent. Also by construction, a scalar component cannot contain a pack\nliteral, pack expansion, or arity coercion, but it can contain each-names, so we\ncan operate on it using the ordinary rules of non-variadic expressions so long\nas we treat the names as opaque.\n\n### Iterative typechecking of pack expansions\n\nSince the execution semantics of an expansion are defined in terms of a notional\nrewritten form where we simultaneously iterate over each-names, in principle we\ncan typecheck the expansion by typechecking the rewritten form. However, the\nrewritten form usually would not typecheck as ordinary Carbon code, because the\neach-names can have different types on different iterations. Furthermore, the\ndifference in types can propagate through expressions: if `each x` and `each y`\ncan have different types on different iterations, then so can `each x * each y`.\nIn effect, we have to typecheck the loop body separately for each iteration.\n\nHowever, at typechecking time we usually don't even know how many iterations\nthere will be, much less what type an each-name will have on any particular\niteration, because the types of the each-names are packs, which are sequences of\nsegments, not sequences of elements. To solve that problem, we require that the\ntypes of all each-names in a pack expansion must have the same shape. This\nenables us to typecheck the pack expansion by simultaneously iterating over\nsegments instead of input elements.\n\nAs a result, the type of an expression or pattern within a pack expansion is a\nsequence of segments, or in other words a _pack_, representing the types it\ntakes on over the course of the iteration. Note, however, that even though such\nan expression has a pack type, it does not evaluate to a pack value. Rather, it\nevaluates to a sequence of non-pack values over the course of the pack expansion\nloop, and its pack type summarizes the types of that sequence.\n\nWithin a given iteration, typechecking follows the usual rules of non-variadic\ntypechecking, except that when we need the type of an each-name, we use the\nscalar component of the current segment of its type. As noted above, we can\noperate on a scalar component using the ordinary rules of non-variadic\ntypechecking.\n\nOnce the body of a pack expansion has been typechecked, typechecking the\nexpansion itself is relatively straightforward:\n\n-   A statement pack expansion requires no further typechecking, because\n    statements don't have types.\n-   An `...and` or `...or` expression has type `bool`, and every segment of the\n    operand's type pack must have a type that's convertible to `bool`.\n-   For a `...` tuple element expression or pattern, the segments of the\n    operand's type pack become segments of the type of the enclosing tuple.\n\n> **TODO:** Discuss typechecking `...expand`.\n\n### Typechecking patterns\n\nA pack expansion pattern has _fixed arity_ if it contains at least one usage of\nan each-name that is not a parameter of the enclosing\n[full pattern](pattern_matching.md). Otherwise it has _deduced arity_. A tuple\npattern can have at most one segment with deduced arity. For example:\n\n```carbon\nclass C(... each T:! type) {\n  fn F[... each U:! type](... each t: each T, ... each u: each U);\n}\n```\n\nIn the signature of `F`, `... each t: each T` has fixed arity, since the arity\nis determined by the arguments passed to `C`, before the call to `F`. On the\nother hand, `... each u: each U` has deduced arity, because the arity of\n`each U` is determined by the arguments passed to `F`.\n\nAfter typechecking a full pattern, we attempt to merge as many tuple segments as\npossible, in order to simplify the subsequent pattern matching. For example,\nconsider the following function declaration:\n\n```carbon\nfn Min[T:! type](first: T, ... each next: T) -> T;\n```\n\nDuring typechecking, we rewrite that function signature so that it only has one\nparameter:\n\n```carbon\nfn Min[T:! type](... each args: «T; ‖each next‖+1») -> T;\n```\n\n(We represent the arity as `‖each next‖+1` to capture the fact that `each args`\nmust match at least one element.)\n\nWhen the pattern is heterogeneous, the merging process may be more complex. For\nexample:\n\n```carbon\nfn ZipAtLeastOne[First:! type, ... each Next:! type]\n    (first: Vector(First), ... each next: Vector(each Next))\n    -> Vector((First, ... each Next));\n```\n\nDuring typechecking, we transform that function signature to the following form:\n\n```carbon\nfn ZipAtLeastOne[... ⟬First, each Next⟭:! «type; ‖each next‖+1»]\n    (... each __args: Vector(⟬First, each Next⟭))\n    -> Vector((... ⟬First, each Next⟭));\n```\n\nWe can then rewrite that by replacing the pack of names `⟬First, each Next⟭`\nwith an invented name `each __Args`, so that the function has only one\nparameter:\n\n```carbon\nfn ZipAtLeastOne[... each __Args:! «type; ‖each next‖+1»]\n    (... each __args: Vector(each __Args))\n    -> Vector((... each __Args));\n```\n\nWe can replace a name pack with an invented each-name only if all of the\nfollowing conditions hold:\n\n-   The name pack doesn't use any name more than once. For example, we can't\n    apply this rewrite to `⟬X, each Y, X⟭`.\n-   The name pack contains exactly one each-name. For example, we can't apply\n    this rewrite to `⟬X, Y⟭`.\n-   The replacement removes all usages of the constituent names, including their\n    declarations. For example, we can't apply this rewrite to `⟬X, each Y⟭` in\n    this code, because the resulting signature would have return type `X` but no\n    declaration of `X`:\n    ```carbon\n    fn F[... ⟬X, each Y⟭:! «type; ‖each next‖+1»]\n        (... each __args: each ⟬X, each Y⟭) -> X;\n    ```\n-   The pack expansions being rewritten do not contain any pack literals other\n    than the name pack being replaced. For example, we can't apply this rewrite\n    to `⟬X, each Y⟭` in this code, because the pack expansion in the deduced\n    parameter list also contains the pack literal `⟬I, each type⟭`:\n    ```carbon\n    fn F[... ⟬X, each Y⟭:! ⟬I, each type⟭](... each __args: each ⟬X, each Y⟭);\n    ```\n    Notice that as a corollary of this rule, all the names in the name pack must\n    have the same type.\n\nSee the [appendix](#pattern-match-typechecking-algorithm) for a more formal\ndiscussion of the rewriting process.\n\n### Typechecking pattern matches\n\nTo typecheck a pattern match between a tuple pattern and a tuple scrutinee, we\ntry to split and merge the segments of the scrutinee type so that it has the\nsame number of segments as the pattern type, and corresponding segments have the\nsame arity. For example, consider this call to `ZipAtLeastOne` (as defined in\nthe previous section):\n\n```carbon\nfn F[... each T:! type](... each t: Vector(each T), u: Vector(i32)) {\n  ZipAtLeastOne(... each t, u);\n}\n```\n\nThe pattern type is `(... Vector(⟬First, each Next⟭))`, so we need to rewrite\nthe scrutinee type `(... Vector(each T), Vector(i32))` to have a single tuple\nsegment with an arity that matches `‖each Next‖+1`. We can do that by merging\nthe scrutinee segments to obtain `(... ⟬Vector(each T), Vector(i32)⟭)`. This has\na single segment with arity `‖each T‖+1`, which can match `‖each Next‖+1`\nbecause the deduced arity `‖each Next‖` behaves as a deduced parameter of the\npattern, so they match by deducing `‖each Next‖ == ‖each T‖`.\n\nWhen merging segments of the scrutinee, we don't attempt to form name packs and\nreplace them with invented names, but we also don't need to: we don't require a\nmerged scrutinee segments to have a single scalar component.\n\nThe search for this rewrite processes each pattern segment to the left of the\nsegment with deduced arity, in order from left to right. For each pattern\nsegment, it greedily merges unmatched scrutinee segments from left to right\nuntil their cumulative shape is greater than or equal to the shape of the\npattern segment, and then splits off a scrutinee segment on the right if\nnecessary to make the shapes exactly match. Pattern segments to the right of the\nsegment with deduced arity are processed the same way, but with left and right\nreversed, so that segments are always processed from the outside in.\n\nSee the [appendix](#appendix-type-system-formalism) for the rewrite rules that\ngovern merging and splitting.\n\nOnce we have the pattern and scrutinee segments in one-to-one correspondence, we\ncheck each scalar component of the scrutinee type against the scalar component\nof the corresponding pattern type segment (by construction, the pattern type\nsegment has only one scalar component). Since we are checking scalar components\nagainst scalar components, this proceeds according to the usual rules of\nnon-variadic typechecking.\n\n> **TODO:** Extend this approach to fall back to a complementary approach, where\n> the pattern and scrutinee trade roles: we maximally merge the scrutinee tuple,\n> while requiring each segment to have a single scalar component, and then\n> merge/split the pattern tuple to match it, without requiring pattern tuple\n> segments to have a single scalar component. This isn't quite symmetric with\n> the current approach, because when processing the scrutinee we can't merge\n> deduced parameters (scrutinees don't have any), but we can invent new `let`\n> bindings.\n\n## Appendix: Type system formalism\n\nA _pack literal_ is a comma-separated sequence of segments, enclosed in `⟬⟭`\ndelimiters. A pack literal can appear in an expression, pattern, or name\ncontext, and every segment must be valid in the context where the pack literal\nappears (for example, the segments of a pack literal in a name context must all\nbe names). Pack literals cannot be nested, and cannot appear outside a pack\nexpansion.\n\n### Explicit deduced arities\n\nIn this formalism, deduced arities are explicit rather than implicit, so Carbon\ncode must be desugared into this formalism as follows:\n\nFor each pack expansion pattern, we introduce a binding pattern `__N:! Arity` as\na deduced parameter of the enclosing full pattern, where `__N` is a name chosen\nto avoid collisions. Then, for each binding pattern of the form `each X: T`\nwithin that expansion, if `T` does not contain an each-name, the binding pattern\nis rewritten as `each X: «T; __N»`. If this does not introduce any usages of\n`__N`, we remove its declaration.\n\n`Arity` is a compiler-internal type which represents non-negative integers. The\nonly operation it supports is `+`, with non-negative integer literals and other\n`Arity`s. `Arity` is used only during type checking, so `+` has no run-time\nsemantics, and its only symbolic semantics are that it is commutative and\nassociative.\n\n### Typing and shaping rules\n\nThe shape of an AST node within a pack expansion is determined as follows:\n\n-   The shape of an arity coercion is the value of the expression after the `;`.\n-   The shape of a pack literal is the concatenation of the arities of its\n    segments.\n-   The shape of an each-name expression is the shape of the binding pattern\n    that declared the name.\n-   If a binding pattern's name and type components have the same number of\n    segments, and each name segment is an each-name if and only if the\n    corresponding type segment's shape is not 1, then the shape of the binding\n    pattern is the shape of the type expression. Otherwise, the binding pattern\n    is ill-shaped.\n-   For any other AST node:\n    -   If all the node's children have shape 1, its shape is 1.\n    -   If there is some shape `S` such that all of the node's children have\n        shape either 1 or `S`, its shape is `S`.\n    -   Otherwise, the node is ill-shaped.\n\n> **TODO:** The \"well-shaped\" rules as stated are slightly too restrictive. For\n> example, `⟬each X, Y⟭: «Z; N+1»` is well-shaped, and `(⟬each X, Y⟭, «Z; N+1»)`\n> is well-shaped if the shape of `each X` is `N`.\n\nThe type of an expression or pattern can be computed as follows:\n\n-   The type of `each x: auto` is `each __X`, a newly-invented deduced parameter\n    of the enclosing full pattern, which behaves as if it was declared as\n    `... each __X:! type`.\n-   The type of an each-name expression is the type expression of the binding\n    pattern that declared it.\n-   The type of an arity coercion `«E; S»` is `«T; S»`, where `T` is the type of\n    `E`.\n-   The type of a pack literal is a pack literal consisting of the concatenated\n    types of its segments. This concatenation flattens any nested pack literals\n    (for example `⟬A, ⟬B, C⟭⟭` becomes `⟬A, B, C⟭`)\n-   The type of a pack expansion expression or pattern is `...B`, where `B` is\n    the type of its body.\n-   The type of a tuple literal is a tuple literal consisting of the types of\n    its segments.\n-   If an expression or pattern `E` contains a pack literal or arity coercion\n    that is not inside a pack expansion, the type of `E` is the type of the\n    fully expanded form of `E`.\n\n> **TODO:** address `...expand`, `...and` and `...or`.\n\n### Reduction rules\n\nUnless otherwise specified, all expressions in these rules must be free of side\neffects. Note that every reduction rule is also an equivalence: the utterance\nbefore the reduction is equivalent to the utterance after, so these rules can\nsometimes be run in reverse (particularly during deduction).\n\nUtterances that are reduced by these rules must be well-shaped (and the reduced\nform will likewise be well-shaped), but need not be well-typed. This enables us\nto apply these reductions while determining whether an utterance is well-typed,\nas in the case of typing an expression or pattern that contains a pack literal\nor arity coercion, above.\n\n_Singular pack removal:_ if `E` is a pack segment, `⟬E⟭` reduces to `E`.\n\n_Singular expansion removal:_ `...E` reduces to `E`, if the shape of `E` is\n`(1,)`.\n\n_Pack expansion splitting:_ If `E` is a segment and `S` is a sequence of\nsegments, `...⟬E, S⟭` reduces to `...E, ...⟬S⟭`.\n\n_Pack expanding:_ If `F` is a function, `X` is an utterance that does not\ncontain pack literals, each-names, or arity coercions, and `⟬P1, P2⟭` and\n`⟬Q1, Q2⟭` both have the shape `(S1, S2)`, then\n`F(⟬P1, P2⟭, X, ⟬Q1, Q2⟭, «Y; S1+S2»)` reduces to\n`⟬F(P1, X, Q1, «Y; S1»), F(P2, X, Q2, «Y; S2»)⟭`. This rule generalizes in\nseveral dimensions:\n\n-   `F` can have any number of arity coercion and other non-pack-literal\n    arguments, and any positive number of pack literal arguments, and they can\n    be in any order.\n-   The pack literal arguments can have any number of segments (but the\n    well-shapedness requirement means they must have the same number of\n    segments).\n-   `F()` can be any expression syntax other than `...`, not just a function\n    call. For example, this rule implies that `⟬X1, X2⟭ * ⟬Y1, Y2⟭` reduces to\n    `⟬X1 * Y1, X2 * Y2⟭`, where the `*` operator plays the role of `F`.\n-   `F()` can also a be a pattern syntax. For example, this rule implies that\n    `(⟬x1: X1, x2: X2⟭, ⟬y1: Y1, y2: Y2⟭)` reduces to\n    `⟬(x1: X1, y1: Y1), (x2: X2, y2: Y2)⟭`, where the tuple pattern syntax\n    `( , )` plays the role of `F`.\n-   When binding pattern syntax takes the role of `F`, the name part of the\n    binding pattern must be a name pack. For example, `⟬x1, x2⟭: ⟬X1, X2⟭`\n    reduces to `⟬x1: X1, x2: X2⟭`, but `each x: ⟬X1, X2⟭` cannot be reduced by\n    this rule.\n\n_Coercion expanding:_ If `F` is a function, `S` is a shape, and `Y` is an\nexpression that does not contain pack literals or arity coercions,\n`F(«X; S», Y, «Z; S»)` reduces to `«F(X, Y, Z); S»`. As with pack expanding,\nthis rule generalizes:\n\n-   `F` can have any number of non-arity-coercion arguments, and any positive\n    number of arity coercion arguments, and they can be in any order.\n-   `F()` can be any expression syntax other than `...` or pack literal\n    formation, not just a function call. Unlike pack expanding, coercion\n    expanding does not apply if `F` is a pattern syntax.\n\n_Coercion removal:_ `«E; 1»` reduces to `E`.\n\n_Tuple indexing:_ Let `I` be an integer template constant, let `X` be a tuple\nsegment, and let `Ys` be a sequence of tuple segments.\n\n-   If the arity `A` of `X` is less than `I+1`, then `(X, Ys).(I)` reduces to\n    `(Ys).(I-A)`.\n-   Otherwise:\n    -   If `X` is not a pack expansion, then `(X, Ys).(I)` reduces to `X`.\n    -   If `X` is of the form `...⟬«E; S»⟭`, then `(X, Ys).(I)` reduces to `E`.\n\n### Equivalence, equality, and convertibility\n\n_Pack renaming:_ Let `Ns` be a sequence of names, let `⟬Ns⟭: «T; N»` be a name\nbinding pattern (which may be a symbolic or template binding as well as a\nruntime binding), and let `__A` be an identifier that does not collide with any\nname that's visible where `⟬Ns⟭` is visible. We can rewrite all occurrences of\n`⟬Ns⟭` to `each __A` in the scope of the binding pattern (including the pattern\nitself) if all of the following conditions hold:\n\n-   `Ns` contains at least one each-name.\n-   No name in `Ns` is used in the scope outside of `Ns`.\n-   No name occurs more than once in `Ns`.\n-   No other pack literals occur in the same pack expansion as an occurrence of\n    `⟬Ns⟭`.\n\n_Expansion convertibility:_ `...T` is convertible to `...U` if the arity of `U`\nequals the arity of `T`, and the scalar components of `T` are each convertible\nto all scalar components of `U`.\n\n_Shape equality:_ Let `(S1s)`, `(S2s)`, `(S3s)`, and `(S4s)` be shapes.\n`(S1s, S2s)` equals `(S3s, S4s)` if `(S1s)` equals `(S3s)` and `(S2s)` equals\n`(S4s)`.\n\n### Pattern match typechecking algorithm\n\nA full pattern is in _normal form_ if it contains no pack literals, and every\narity coercion is fully expanded. For example,\n`[__N:! Arity](... each x: Vector(«i32; __N»))` is not in normal form, but\n`[__N:! Arity](... each x: «Vector(i32); __N»)` is. Note that all user-written\nfull patterns are in normal form. Note also that by construction, this means\nthat the type of the body of every pack expansion has a single scalar component.\nThe _canonical form_ of a full pattern is the unique normal form (if any) that\nis \"maximally merged\", meaning that every tuple pattern and tuple literal has\nthe smallest number of segments. For example, the canonical form of\n`[__N:! Arity](... each x: «i32; __N», y: i32)` is\n`[__N:! Arity](... each __args: «i32; __N+1»)`.\n\n> **TODO:** Specify algorithm for converting a full pattern to canonical form,\n> or establishing that there is no such form. See next section for a start.\n\nIf a function with type `F` is called with argument type `A`, we typecheck the\ncall by converting `F` to canonical form, and then checking whether `A` is\nconvertible to the parameter type by applying the deduction rules in the\nprevious sections. If that succeeds, we apply the resulting binding map to the\nfunction return type to obtain the type of the call expression.\n\n> **TODO:** Specify the algorithm more precisely. In particular, discuss how to\n> rewrite `A` as needed to make the shapes line up, but don't rewrite `F` after\n> canonicalization.\n\nTypechecking for pattern match operations other than function calls is defined\nin terms of typechecking a function call: We check a scrutinee type `S` against\na pattern `P` by checking `__F(S,)` against a hypothetical function signature\n`fn __F(P,)->();`.\n\n> **Future work:** Extend this approach to support merging the argument list as\n> well as the parameter list.\n\n#### Canonicalization algorithm\n\nThe canonical form can be found by starting with a normal form, and\nincrementally merging an adjacent singular parameter type into the variadic\nparameter type.\n\nFor example, consider the following function:\n\n```carbon\nfn F[First:! type, Second:! type, ... each Next:! type]\n    (first: Vector(First), second: Vector(Second),\n     ... each next: Vector(each Next)) -> (First, Second, ... each Next);\n```\n\nFirst, we desugar the implicit arity:\n\n```carbon\nfn F[__N:! Arity, First:! type, Second:! type, ... each Next:! «type; __N»]\n    (first: Vector(First), second: Vector(Second),\n     ... each next: Vector(each Next)) -> (First, Second, ... each Next);\n```\n\nThen we attempt to merge `Second` with `each Next` as follows (note that for\nbrevity, some of the steps presented here actually contain multiple independent\nreductions):\n\n```carbon\n// Singular pack removal (in reverse)\nfn F[__N:! Arity, First:! type, Second:! type, ... ⟬each Next:! «type; __N»⟭]\n    (first: Vector(First), second: Vector(Second),\n     ... each next: Vector(⟬each Next⟭)) -> (First, Second, ... ⟬each Next⟭);\n// Pack expanding\nfn F[__N:! Arity, First:! type, Second:! type, ... ⟬each Next:! «type; __N»⟭]\n    (first: Vector(First), second: Vector(Second),\n     ... each next: ⟬Vector(each Next)⟭) -> (First, Second, ... ⟬each Next⟭);\n// Pack expanding\nfn F[__N:! Arity, First:! type, Second:! type, ... ⟬each Next:! «type; __N»⟭]\n    (first: Vector(First), second: Vector(Second),\n     ... ⟬each next: Vector(each Next)⟭) -> (First, Second, ... ⟬each Next⟭);\n// Pack expansion splitting (in reverse)\nfn F[__N:! Arity, First:! type, ... ⟬Second:! type, each Next:! «type; __N»⟭]\n    (first: Vector(First), ... ⟬second: Vector(Second),\n                                each next: Vector(each Next)⟭)\n    -> (First, ... ⟬Second, each Next⟭);\n// Pack expanding (in reverse)\nfn F[__N:! Arity, First:! type, ... ⟬Second, each Next⟭:! «type; __N+1»]\n    (first: Vector(First), ... ⟬second, each next⟭: ⟬Vector(Second), Vector(each Next)⟭)\n    -> (First, ... ⟬Second, each Next⟭);\n// Pack expanding (in reverse)\nfn F[__N:! Arity, First:! type, ... ⟬Second, each Next⟭:! «type; __N+1»]\n    (first: Vector(First), ... ⟬second, each next⟭: Vector(⟬Second, each Next⟭))\n    -> (First, ... ⟬Second, each Next⟭);\n// Pack renaming\nfn F[__N:! Arity, First:! type, ... each __A:! «type; __N+1»]\n    (first: Vector(First), ... each __a: Vector(each __A))\n    -> (First, ... each __A);\n```\n\nThis brings us back to a normal form, while reducing the number of tuple\nsegments. We can now repeat that process to merge the remaining parameter type:\n\n```carbon\nfn F[__N:! Arity, First:! type, ... ⟬each __A:! «type; __N+1»⟭]\n    (first: Vector(First), ... each __a: Vector(⟬each __A⟭))\n    -> (First, ... ⟬each __A⟭);\n// Pack expanding\nfn F[__N:! Arity, First:! type, ... ⟬each __A:! «type; __N+1»⟭]\n    (first: Vector(First), ... each __a: ⟬Vector(each __A)⟭)\n    -> (First, ... ⟬each __A⟭);\n// Pack expanding\nfn F[__N:! Arity, First:! type, ... ⟬each __A:! «type; __N+1»⟭]\n    (first: Vector(First), ... ⟬each __a: Vector(each __A)⟭)\n    -> (First, ... ⟬each __A⟭);\n// Pack expansion splitting (in reverse)\nfn F[__N:! Arity, ... ⟬First:! type, each __A:! «type; __N+1»⟭]\n    (... ⟬first: Vector(First), each __a: Vector(each __A)⟭)\n    -> (... ⟬First, each __A⟭);\n// Pack expanding (in reverse)\nfn F[__N:! Arity, ... ⟬First, each __A⟭:! «type; __N+2»⟭]\n    (... ⟬first, each __a⟭: ⟬Vector(First), Vector(each __A)⟭)\n    -> (... ⟬First, each __A⟭);\n// Pack expanding (in reverse)\nfn F[__N:! Arity, ... ⟬First, each __A⟭:! «type; __N+2»⟭]\n    (... ⟬first, each __a⟭: Vector(⟬First, each __A⟭))\n    -> (... ⟬First, each __A⟭);\n// Pack renaming\nfn F[__N:! Arity, ... __B:! «type; __N+2»⟭]\n    (... __b: Vector(__B))\n    -> (... __B);\n```\n\nHere again, this is a normal form, and there is demonstrably no way to perform\nany further merging, so this must be the canonical form.\n\n> **TODO:** define the algorithm in more general terms, and discuss ways that\n> merging can fail.\n\n## Alternatives considered\n\n-   [Member packs](/proposals/p2240.md#member-packs)\n-   [Single semantic model for pack expansions](/proposals/p2240.md#single-semantic-model-for-pack-expansions)\n-   [Generalize `expand`](/proposals/p2240.md#generalize-expand)\n-   [Omit `expand`](/proposals/p2240.md#omit-expand)\n-   [Support expanding arrays](/proposals/p2240.md#support-expanding-arrays)\n-   [Omit each-names](/proposals/p2240.md#omit-each-names)\n    -   [Disallow pack-type bindings](/proposals/p2240.md#disallow-pack-type-bindings)\n-   [Fold expressions](/proposals/p2240.md#fold-expressions)\n-   [Allow multiple pack expansions in a tuple pattern](/proposals/p2240.md#allow-multiple-pack-expansions-in-a-tuple-pattern)\n-   [Allow nested pack expansions](/proposals/p2240.md#allow-nested-pack-expansions)\n-   [Use postfix instead of prefix `...`](/proposals/p2240.md#use-postfix-instead-of-prefix-)\n-   [Avoid context-sensitity in pack expansions](/proposals/p2240.md#avoid-context-sensitity-in-pack-expansions)\n    -   [Fold-like syntax](/proposals/p2240.md#fold-like-syntax)\n    -   [Variadic blocks](/proposals/p2240.md#variadic-blocks)\n    -   [Keyword syntax](/proposals/p2240.md#keyword-syntax)\n-   [Require parentheses around `each`](/proposals/p2240.md#require-parentheses-around-each)\n-   [Fused expansion tokens](/proposals/p2240.md#fused-expansion-tokens)\n-   [No parameter merging](/proposals/p2240.md#no-parameter-merging)\n-   [Exhaustive function call typechecking](/proposals/p2240.md#exhaustive-function-call-typechecking)\n\n## References\n\n-   Proposal\n    [#2240: Variadics](https://github.com/carbon-language/carbon-lang/pull/2240)\n"
  },
  {
    "path": "docs/guides/README.md",
    "content": "# Guides\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis directory contains end-user documentation on how to use Carbon, focused on\npeople trying to use and write code in Carbon.\n\n-   [Glossary](glossary.md)\n"
  },
  {
    "path": "docs/guides/glossary.md",
    "content": "# Glossary\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## entity\n\nAn _entity_ is a named item with an associated name path, such as a function,\ntype, interface, or namespace. For example, in `fn GetTime()`, `GetTime` refers\nto an entity which is a function.\n\n## identifier\n\nAn _identifier_ is the token which names an entity, and is also used in code to\nrefer to the entity. For example, in `fn GetTime()`, `GetTime` is the identifier\nfor the function.\n\n## library\n\nA _library_ is a group of files that form an importable API and its\nimplementation. Carbon encourages small libraries, bundled into larger packages.\nFor example, given `package Geometry library Shapes;`, `Shapes` is a library in\nthe `Geometry` package.\n\n## name path\n\nA _name path_ is the dot-separated identifier list that indicates a relative or\nfull path of a name. For example, given `fn GetArea(var Geometry.Circle: x)`,\n`Geometry.Circle` is a name path. `GetArea` is also a name path, albeit with\nonly one identifier needed.\n\n## namespace\n\nA _namespace_ is an entity that contains entities, and may be nested. For\nexample, given a name path of `Geometry.Circle`, `Geometry` is a namespace\ncontaining `Circle`.\n\n## package\n\nA _package_ is a group of libraries in Carbon, and is the standard unit for\ndistribution. The package name also serves as the root namespace for all name\npaths in its libraries. The package name should be a single, globally-unique\nidentifier. For example, given `package Geometry;` in a file, `Geometry` is the\npackage and root namespace.\n"
  },
  {
    "path": "docs/images/snippets.md",
    "content": "# Front page snippets for Carbon\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!--\n{% raw %}\nHides `{{` from jekyll's liquid parsing. Note endraw at the bottom.\n-->\n\n## Images\n\nImages are managed in\n[Google Drive](https://drive.google.com/drive/folders/1QrBXiy_X74YsOueeC0IYlgyolWIhvusB).\n\n## Quicksort\n\nA sample of quicksort in Carbon.\n\n```cpp\npackage Sorting;\n\nfn Partition[T:! Comparable & Movable](s: Slice(T))\n     -> i64 {\n  var i: i64 = -1;\n\n  for (e: T in s) {\n    if (e <= s.Last()) {\n      ++i;\n      Swap(&s[i], &e);\n    }\n  }\n  return i;\n}\n\nfn QuickSort[T:! Comparable & Movable](s: Slice(T)) {\n  if (s.Size() <= 1) {\n    return;\n  }\n  let p: i64 = Partition(s);\n  QuickSort(s[:p - 1]);\n  QuickSort(s[p + 1:]);\n}\n```\n\n## Carbon and C++\n\n### C++\n\n```cpp\n// C++:\n#include <numbers>\n#include <print>\n#include <span>\n#include <stdfloat>\n#include <vector>\n// or: import std;\n\nstruct Circle {\n  std::float32_t r;\n};\n\nvoid PrintTotalArea(std::span<Circle> circles) {\n  std::float32_t area = 0;\n  for (const Circle& c : circles) {\n    area += std::numbers::pi * c.r * c.r;\n  }\n  std::print(\"Total area: {}\\n\", area);\n}\n\nauto main() -> int {\n  std::vector<Circle> circles = {{.r = 1.0}, {.r = 2.0}};\n  // Implicitly converts `vector` to `span`.\n  PrintTotalArea(circles);\n  return 0;\n}\n```\n\n### Carbon\n\n```cpp\n// Carbon:\npackage Geometry;\nimport Math;\n\nclass Circle {\n  var r: f32;\n}\n\nfn PrintTotalArea(circles: [Circle]) {\n  var area: f32 = 0;\n  for (c: Circle in circles) {\n    area += Math.Pi * c.r * c.r;\n  }\n  Print(\"Total area: {0}\", area);\n}\n\nfn Run() -> i32 {\n  // A dynamically sized array, like `std::vector`.\n  var circles: array [Circle] = ({.r = 1.0}, {.r = 2.0});\n  // Implicitly constructs a slice from the array.\n  PrintTotalArea(circles);\n  return 0;\n}\n```\n\n### Mixed\n\n```cpp\n// C++ code used in both Carbon and C++:\n#include <stdfloat>\n\nstruct Circle {\n  std::float32_t r;\n};\n\n// Carbon exposing a function for C++:\npackage Geometry;\nimport Cpp library \"circle.h\";\nimport Math;\n\nfn PrintTotalArea(circles: [Cpp.Circle]) {\n  var area: f32 = 0;\n  for (c: Cpp.Circle in circles) {\n    area += Math.Pi * c.r * c.r;\n  }\n  Print(\"Total area: {0}\", area);\n}\n\n// C++ calling Carbon:\n#include <vector>\n#include \"circle.h\"\n#include \"geometry.carbon.h\"\n\nauto main() -> int {\n  std::vector<Circle> circles = {{1.0}, {2.0}};\n  // A Carbon slice supports implicit construction\n  // from `std::vector`, similar to `std::span`.\n  Geometry::PrintTotalArea(circles);\n  return 0;\n}\n```\n\n<!--\n{% endraw %}\n-->\n"
  },
  {
    "path": "docs/project/README.md",
    "content": "# Project\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis directory contains project-related documentation for Carbon. Information\nabout how the project works, goals, and community information belong here.\n\n-   [Goals](goals.md), and [principles](principles/README.md) derived from those\n    goals\n-   [Roadmap](roadmap.md) and the [process](roadmap_process.md) for updating it\n-   Carbon's process for [evolution and governance](evolution.md)\n-   [Groups](groups.md) used for contacting key contributors and determining\n    access\n-   Contributing to Carbon:\n    -   [Tools used when contributing to Carbon](contribution_tools.md)\n    -   Style guides for [language design](design_style_guide.md) and\n        [C++ code](cpp_style_guide.md)\n    -   How Carbon does [code review](code_review.md)\n    -   [Trunk-based pull-request GitHub workflow](pull_request_workflow.md)\n        used by Carbon\n"
  },
  {
    "path": "docs/project/code_review.md",
    "content": "# Code review\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [High level goals of code review](#high-level-goals-of-code-review)\n-   [What requires review?](#what-requires-review)\n-   [Who should review?](#who-should-review)\n-   [GitHub pull request mechanics](#github-pull-request-mechanics)\n-   [Code author guide](#code-author-guide)\n    -   [Write good change descriptions](#write-good-change-descriptions)\n        -   [First line](#first-line)\n        -   [Body](#body)\n        -   [Pull request labels](#pull-request-labels)\n    -   [Make small changes](#make-small-changes)\n    -   [Responding to review comments](#responding-to-review-comments)\n        -   [Responding to questions or confusion](#responding-to-questions-or-confusion)\n        -   [Understand the feedback in the comments](#understand-the-feedback-in-the-comments)\n    -   [Fixing conflicts with trunk](#fixing-conflicts-with-trunk)\n-   [Code reviewer guide](#code-reviewer-guide)\n    -   [How quickly should you respond to a review request?](#how-quickly-should-you-respond-to-a-review-request)\n    -   [What should be covered by a review?](#what-should-be-covered-by-a-review)\n    -   [Writing review comments](#writing-review-comments)\n    -   [Approving the change](#approving-the-change)\n    -   [Pausing reviews and reassigning PRs](#pausing-reviews-and-reassigning-prs)\n-   [Merging pull requests](#merging-pull-requests)\n    -   [Merge commit descriptions](#merge-commit-descriptions)\n-   [Resolving an impasse or conflict](#resolving-an-impasse-or-conflict)\n-   [Escalation](#escalation)\n\n<!-- tocstop -->\n\n## High level goals of code review\n\nCode review serves several goals in the Carbon project. It directly improves the\ncorrectness, clarity, and consistency of contributions, including both code and\ndocumentation. These improvements range from the high-level functionality down\nthrough the design and implementation details. It also promotes team ownership\nand spreads knowledge across the team.\n\nMore detailed discussions can be found in chapter 9 \"Code Review\" of the book\n_[Software Engineering at Google](https://www.amazon.com/Software-Engineering-Google-Lessons-Programming/dp/1492082791)_\nand chapter 21 \"Collaborative Construction\" in\n_[Code Complete: A Practical Handbook of Software Construction](https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/)_.\nHowever, these details aren't essential to understanding code review and how it\nworks in the Carbon project. All of the important details are provided in the\nproject documentation.\n\n## What requires review?\n\nEvery change to Carbon's repositories requires code review. Even formal\n[evolution decisions](evolution.md) which have been approved should have their\nspecific changes to the repository reviewed.\n\nMany changes to Carbon repositories may _only_ require code review. Typically,\nthese include bug fixes, and development or documentation improvements clearly\nin line with accepted designs. It may in some rare cases extend to exploring\nexperimental or prototype directions whose design is under active consideration.\n\nThe term \"code review\" in the Carbon project is not only about \"code\". We expect\nchanges to any file to be reviewed, including documentation and any other\nmaterial stored in the repository.\n\n## Who should review?\n\nEveryone should feel free to review Carbon changes. Even providing small or\npartial review can be a good way to start contributing to Carbon. Contributors\nwith specific domain expertise or familiarity should also try to provide review\non changes touching relevant parts of the project.\n\nAdditionally, at least one developer with commit access must review each change.\nIn Carbon, developers will focus on particular areas, loosely broken down as:\n\n-   [Carbon leads](groups.md#carbon-leads): [proposals](/proposals/) and other\n    important project documents, including the [Main README](/README.md),\n    [Code of Conduct](/CODE_OF_CONDUCT.md), [license](/LICENSE), and\n    [goals](goals.md).\n\n-   [Implementation team](groups.md#implementation-team): general changes.\n\n    -   We split out auto-assignment by explorer, toolchain, and other files\n        (including documentation).\n\n[Auto-assignment](/CODEOWNERS) will help find owners, but won't always be\nperfect -- developers may take a PR they weren't auto-assigned in order to help\nreview go quickly. Contributors can also request multiple reviewers, but it can\nbe daunting to get feedback from a large number of reviewers, so we suggest\nkeeping the number of reviewers reasonably small.\n\nAny reviews that explicitly request changes should be addressed, either with the\nchanges or an explanation of why not, before a pull request is merged. Further,\nany owners who have requested changes should explicitly confirm they're happy\nwith the resolution before the change is merged.\n\nWhen a team gives an affirm decision on an [evolution proposal](evolution.md),\neach team member should explicitly note any of their comments on the pull\nrequest that, while not blocking the _decision_, still need to be resolved as\npart of code review prior to it being merged. These might, for example, be\ntrivial or minor wording tweaks or improvements. Otherwise, the decision is\nassumed to mean the prior review comments from members of that team are\naddressed; the author is free to merge once the pull request is approved,\npossibly with a code review separate from the proposal's review.\n\n## GitHub pull request mechanics\n\nCarbon uses GitHub pull requests for code review, and we recommend some\nmechanical best practices to most effectively navigate them.\n\n-   Be aware that the main thread of pull request doesn't support threaded\n    discussions or \"resolving\" a comment.\n    -   If either of those would be useful, you'll probably want to comment on a\n        file.\n    -   You can quote comments in the main conversation thread in a reply by\n        clicking the three-dot menu on the original comment and selecting \"Quote\n        reply\".\n-   If you will want to comment on files, don't comment in the pull request\n    conversation.\n    -   Always go to the `Files Changed` tab.\n    -   Make any in-file comments needed, but add them to a pending review\n        rather than sending them directly.\n    -   Finish the review and add any top-level review comments there.\n-   Don't mark reviews as requesting changes. Sometimes reviewers get busy and\n    somebody else approves; the \"request changes\" feature still blocks merges\n    until the original requester approves, which can slow reviews down.\n-   Don't reply to in-file comment threads in the conversation view, or with\n    direct single reply comments.\n    -   Add all replies to in-file comment threads using the `Files Changed` tab\n        and by adding each reply to a new review, and posting them as a batch\n        when done.\n    -   You can get to the appropriate `Files Changed` tab by clicking on the\n        change listed in the conversation view with the incoming set of in-file\n        comments.\n    -   This flow ensures an explicit update in the overall pull request that\n        can help both the author and other reviewers note that new replies have\n        arrived.\n-   Don't reply to an in-file comment and then mark it as resolved. No one will\n    see your reply as the thread will be hidden immediately when marked as\n    resolved.\n    -   Generally, the person who started the comment thread should mark it as\n        resolved when their comments are sufficiently addressed. If another\n        reviewer is also on the thread and should also agree, just state that\n        you're happy and the last reviewer can mark it resolved.\n    -   Trivially resolved threads can just be marked as \"resolved\" without\n        further update. Examples: a suggested change that has been successfully\n        applied, or a thread where the relevant reviewers have clearly indicated\n        they're happy.\n\n## Code author guide\n\nThe goal of an author should be to ensure their change improves the overall\ncode, repository, and/or project. Within the context of code review, the goal is\nto get a reviewer to validate that the change succeeds at this goal. That\ninvolves finding an effective reviewer given the particular nature of the\nchange, helping them understand the change fully, and addressing any feedback\nthey provide.\n\n### Write good change descriptions\n\nThe change description in the pull request is the first thing your reviewers\nwill see. This sets the context for the entire review, and is very important.\n\n#### First line\n\nThe first line of a commit, or the subject of the pull request, should be a\nshort summary of specifically what is being done by that change. It should be a\ncomplete sentence, written as though it was an order. Try to keep it short,\nfocused, and to the point.\n\n#### Body\n\nThe description body may need to explain several important aspects of the change\nto provide context for the reviewer when it isn't obvious from the change\nitself:\n\n-   The problem being solved by the change.\n-   Why the approach taken is the best one.\n-   Any issues, concerns, or shortcomings of the approach.\n-   Any alternatives considered or attempted.\n-   Relevant supporting data such as examples or benchmarks.\n\nTry to anticipate what information the reviewer of your change will need to have\nin order to be effective. Also consider what information someone else will need\na year in the future when doing archaeology on the codebase and they come across\nyour change without any context.\n\n#### Pull request labels\n\nGitHub labels are used on PRs, such as\n[toolchain](https://github.com/carbon-language/carbon-lang/labels/toolchain).\nThese are automatically added based on affected directories.\n\nWe do not put labels in PR descriptions; for example, we would write\n`Implements type deduction` instead of `[feature] Type deduction`, or\n`Fix crash in function imports` instead of `[bug] Crash in function imports`.\n\nGiven the current size and state of Carbon, we believe the `[feature]`-style PR\nlabeling would add too much process for their benefit. Additionally, in contrast\nwith LLVM's\n[`[NFC]` label policies](https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access),\nCarbon changes are always reviewed prior to commit.\n\n### Make small changes\n\nSmall changes have many benefits:\n\n-   Faster review.\n-   More thorough review.\n-   Easier to merge.\n-   Easier to revert if needed.\n\nThe ideal size of a change is as small as possible while it remains\nself-contained. It should address only _one thing_. Often, this results in a\nchange only addressing _part_ of a feature rather than the whole thing at once.\nThis makes work more incremental, letting the reviewer understand it piece by\npiece. It can also make it much easier to critically evaluate whether each part\nof a feature is adequately tested by showing it in isolation.\n\nThat said, a change should not be so small that its implications cannot easily\nbe understood. It is fine to provide the reviewer context or a framework of a\nseries of changes so they understand the big picture, but that will only go so\nfar. It is still possible to shrink a change so much that it becomes nonsensical\nin isolation. For example, a change without appropriate tests is not\nself-contained.\n\n### Responding to review comments\n\nMany comments have easy and simple responses. The easiest is **\"Done\"**. When\nthe comment is a concrete suggestion that makes sense and you implement it, you\ncan simply let the reviewer know their suggestion has been incorporated. If the\n_way_ you implemented the suggestion might need clarification, add that as well.\nFor example, consider mentioning tweaks to the suggestion or when the suggestion\nwas applied in more places.\n\nWhen a suggestion from the reviewer is explicitly optional, you may also have a\nsimple response that you're not going to make the change. This is totally fine\n-- if it weren't, the reviewer shouldn't have listed it as optional -- but it\nmay be helpful to explain your reasoning to the reviewer so they understand\nbetter why the optional suggestion didn't make sense to you.\n\nSometimes comments, even optional ones, center around slight differences or\npreferences around the code. Consider that the reviewer may be a good proxy for\nfuture readers. If the suggestion is essentially equivalent to your original\ncode, consider adopting it as it may make the code easier to read for others.\nBut if you feel the current choice is _better_, even if only slightly, stand up\nfor yourself and keep it. The reviewer can always push for a change and justify\nit if needed.\n\nFor non-optional comments, this section provides several suggestions on how best\nto make progress. If none of these work, you may need to\n[resolve an impasse or conflict](#resolving-an-impasse-or-conflict).\n\nIn response to suggestions, update the files in the pull request in new commits.\nRebasing, squashing, or force-pushing commits can break GitHub's comment\nassociations, and it makes it harder to determine what's changed since the last\nreview. With regular pushes, GitHub can show individual deltas, giving\nadditional flexibility to the reviewer. We squash pull requests when we merge\nthem, so the end result is the same.\n\nIt is good to reply to every comment so that the reviewer knows you saw them.\nBest practice is to send the reply to all of the comments at once, after the\nfiles in the pull request have been updated. If there are a lot of replies, it\ncan be helpful to include a message saying whether the pull request is now ready\nfor another round of review, or press the \"Re-request review\" button to the\nright of the reviewer's name:\n![The re-request review button on GitHub](https://user-images.githubusercontent.com/711534/189789784-fcf18d1b-137b-48ba-959a-0d05cee36c2d.png)\n\n#### Responding to questions or confusion\n\nSome comments in code review will be questions or confusion as the reviewer\ntries to understand the code in question or why a particular approach was used.\nDon't assume that questions are a request for a change. Reviewers should be\nexplicit if they think a change is needed rather than merely asking questions.\nYou should assume a question or confusion is something which only needs to be\nclarified.\n\nHowever, when responding to a question or confusion, consider making changes to\nimprove clarity in addition to responding within the review, such as by adding\ncomments or changing code structure. The reviewer may not be the last person to\nneed more clarity, and you should use their comments as a signal for\nimprovement. Once done, the review response should typically focus on verifying\nthat the clarifications made in the code are sufficient for the reviewer.\n\n#### Understand the feedback in the comments\n\nAt times, review comments may be confusing or frustrating for you. While this is\nsomething we always want reviewers to minimize, it will still happen at some\ntimes and to some degree. It helps to remember that the goal of the review is to\nensure the change results in the project improving over time.\n\nIf the review comment doesn't make sense, ask the reviewer to help you\nunderstand the feedback better. If it isn't constructive or doesn't seem to\nprovide any meaningful path forward, ask the reviewer to provide this. Making\ncomments both clear and constructive are part of the reviewers'\nresponsibilities.\n\nOnce there is a clear and effectively communicated comment that you understand,\nit may still feel wrong or like it is unnecessarily blocking your progress. It\nis important to try to step back in this situation and, no matter how certain\nyou are, genuinely consider whether there is valuable feedback. You should be\nasking yourself whether the reviewer might be correct, potentially in an\nunexpected or surprising way. If you can't decide this definitively, you may\nneed to work to get a deeper understanding.\n\nIf you are confident that the reviewer's comment is incorrect, that is _OK_. The\nreviewer is also only human and is certain to make mistakes and miss things. The\nresponse needs to try to explain what it is that leads you to be confident in\nyour assessment. Lay out the information you have and how you are reasoning\nabout the issue to arrive at the conclusion. Try not to make assumptions about\nwhat the reviewer knows or why they made the comment. Instead, focus on\nsurfacing explicitly your perspective on the issue.\n\nThese parts of a review will often be a discussion and may need to iterate a few\ntimes. That isn't intrinsically bad, but try to make sure that it doesn't result\nin reiterating positions or repeating things. Make sure the discussion is\n_progressing_ towards deeper understanding and recognize when you reach an\nimpasse or conflict and shift strategy to\n[resolve that](#resolving-an-impasse-or-conflict). It is also useful to avoid\nlong delays between these iterations. Consider discussing over Discord chat or\nscheduling a quick video chat on the specific issue. This can avoid multi-hour\n-- or multi-day -- round trips.\n\n### Fixing conflicts with trunk\n\nIf a PR has conflicts with trunk, those conflicts must be resolved before the PR\ncan be merged. If the PR is already in review, prefer to wait until review is\nmostly done before fixing the conflicts. Conflicts should be fixed by way of a\nmerge commit rather than rebasing.\n\n## Code reviewer guide\n\nThe specific goal for a particular review should always be to ensure that the\noverall health of the code, repository, and/or project improves over time. This\nrequires that contributions _make progress_ -- otherwise, nothing can improve.\nHowever, the review should ensure that quality of changes does not cause the\nhealth of the project to decrease over time.\n\nThe primary responsibility for ensuring that code review remains constructive,\nproductive, and helpful resides in the _reviewer_. As a reviewer, you are in a\nposition of power and asked to critique the authors hard work. With this power\ncomes responsibility for conducting the review well.\n\n### How quickly should you respond to a review request?\n\nTry to respond to code review requests as soon as you can without interrupting a\nfocused task. At the latest, the next day you are working on the project. Note\nthat the review isn't expected to necessarily be complete after a single review.\nIt is more valuable to give reasonably quick but partial feedback than to delay\nfeedback in order to complete it. If leaving partial feedback, make it clear to\nthe author which parts are covered and which you haven't gotten to yet.\n\nLarge changes are especially important to give incremental feedback on in order\nto do so in a timely fashion. One of the first things to consider with large\nchanges is whether it can be split apart into smaller changes that are easier to\nreview promptly.\n\nThis timeliness guidance doesn't apply to the higher-level\n[evolution process](evolution.md) reviews. Evaluating those proposals will often\nrequire a larger time investment and have their own timelines spelled out in the\nprocess. Here, we are talking about simply reviewing changes themselves\northogonally to any evolutionary discussion and evaluation.\n\n### What should be covered by a review?\n\nThings to consider and evaluate when reviewing changes:\n\n-   Is the code well designed?\n    -   Is the resulting functionality, including its interface, good for the\n        users of the code?\n    -   Does the resulting design facilitate long-term maintenance?\n    -   Can the code be simplified? Is there unnecessary complexity?\n    -   Are things being implemented that aren't yet needed and only _might_ be\n        needed in the future?\n-   Is the code free of bugs and well tested?\n    -   Is memory safely managed?\n    -   Is any parallel or concurrent programming done safely?\n    -   Do unit tests cover relevant behaviors and edge cases?\n    -   Do any integration tests need to be extended or added?\n    -   Do any fuzz tests need to be extended or added?\n    -   Are any tests well designed to be both thorough but also maintainable\n        over time?\n-   Is the code easy to read?\n    -   Are the names used in the code clear?\n    -   Are all important or non-obvious aspects of the code well commented? Do\n        the comments focus on _why_ instead of _what_?\n    -   Is there appropriate high level documentation for the change?\n    -   Does the change adhere to all relevant style guides?\n    -   Is the change consistent with other parts of the project?\n\n### Writing review comments\n\nThese are general guidelines for writing effective code review comments:\n\n-   **Be kind.** Detailed review, especially in an open source project, can be\n    stressful and difficult for the author. As a reviewer, part of the job is to\n    ensure the review experience ends up positive and constructive for the\n    author.\n-   **Stay constructive.** Focus your comments on suggesting specific ways to\n    improve the change. If you need to explain why an improvement is necessary,\n    focus on objective ways the improvement helps and avoid both subjective\n    assessments and anchoring on problems with the current state.\n-   **Explain why.** It is important for the author to understand not merely the\n    mechanical suggested change but what motivates it and why it matters. This\n    may help clear up misunderstandings, help the suggestion be understood and\n    applied more effectively, and allow internalizing improvements for future\n    contributions.\n-   **Provide a path forward.** The author needs to understand what they will\n    need to do to respond to your comments. For example, always provide\n    alternatives when commenting that the current approach won't work.\n\nKeep in mind that the goal is to improve the overall health of the code,\nrepository, and/or project over time. Sometimes, there will be pushback on\nreview comments. Consider carefully if the author is correct -- they may be\ncloser to the technical issues than you are and may have important insight. Also\nconsider whether the suggestion is necessary to achieve the overall goal. If the\nsuggestion isn't critical to make the change an overall improvement, it may be\nfine for it to move forward as-is.\n\nAs with all communication in the Carbon project, it is critical that your\ncomments are not unkind, unwelcoming, angry, ad-hominem attacks, or otherwise\nviolating our community's [code of conduct](/CODE_OF_CONDUCT.md).\n\n### Approving the change\n\nBe explicit and unambiguous at the end of your review. Select \"Approve\" when\nsubmitting the review to mark this in GitHub. You can always include a message,\noften \"LGTM\" or \"Looks Good To Me\" is often used. If you don't feel like you're\nin a position to approve the change and are simply helping out with review\nfeedback, make that explicit as well. You should set the review to a \"Comment\"\nin GitHub, but also state this explicitly in the message since this is the\ndefault and doesn't indicate that your feedback _is_ addressed. For example, say\nthat \"my comments are addressed, but leaving the final review to others\" to\nclearly indicate that you're happy but are deferring the decision to others. If\nyou are an owner and deferring to someone else, it is essential to suggest\nspecific other reviewers. Otherwise, we risk all the owners assuming another is\ngoing to approve the change.\n\nAn important technique to make progress, especially with different working hours\nand timezones, is to approve changes even with outstanding comments. For\nexample, if the comments you have are straightforward and have unambiguous fixes\nor suggested edits, you should give an LGTM with those comments addressed. The\nauthor can always come back to you if they have questions, and we can always\nrevert changes if the resolution for some reason diverges wildly from your\nexpectations.\n\n### Pausing reviews and reassigning PRs\n\nWhen temporarily unavailable to review, for example due to a vacation, reviewers\ncan either mark themselves as\n[busy in GitHub](https://docs.github.com/en/account-and-profile/tutorials/personalize-your-profile#setting-a-status),\nor ask an admin to stop assignment (using\n[\"Never assign to certain team members\"](https://docs.github.com/en/organizations/organizing-members-into-teams/managing-code-review-settings-for-your-team#configuring-auto-assignment)).\n\nA PR's reviewer can also be changed to a team, such as\n`carbon-language/toolchain-reviewers`, and it should be automatically\nreassigned. This can be done by anyone, not just a reviewer.\n\n## Merging pull requests\n\nPull requests are ready to be merged when reviewers have indicated they're happy\n(for example, \"LGTM\" or \"Looks good to me\") or have approved the pull request.\nWhile all merges require at least one approval, a reviewer might approve before\nothers are finished reviewing; all reviewers should be given time to comment to\nensure there's a consensus.\n\nEither the author or reviewer may merge and resolve conflicts. The author may\nindicate they want to merge by informing the reviewer and adding the\n`DO NOT MERGE` label. The reviewer is encouraged to coordinate with the author\nabout merge timing if there are concerns about breaks. In either case, the\ndeveloper doing the merge is expected to be available to help address\npost-commit issues, whether through a fix-forward or a rollback.\n\n### Merge commit descriptions\n\nWhen squashing and merging, GitHub tries to generate a description, but it's\nrecommended to use the first comment on the pull request review for the squashed\ncommit description. Authors should keep it up-to-date so that reviewers can\nmerge when the change is ready. Reviewers shouldn't edit or rewrite this message\nthemselves, and instead ask the author make those changes (possibly with\nsuggestions) just like other parts of the code review. It's important that the\ncommit message is one the author is comfortable with when merged.\n\nWhen suggested edits have been merged into a pull request, GitHub will append a\n`Co-authored-by:` line to its default proposed commit message for each reviewer\nwho suggested edits that were applied. These lines should be retained and\nappended to the message from the initial comment.\n\n## Resolving an impasse or conflict\n\nAt some point, a review may reach an impasse or a genuine conflict. While our\ngoal is always to resolve these by building consensus in review, it may not be\npossible. Both the author and any reviewers should be careful to recognize when\nthis point arrives and address it directly. Continuing the review is unlikely to\nbe productive and has a high risk of becoming acrimonious or worse.\n\nThere are two techniques to use to resolve these situations that should be tried\nearly on:\n\n1. Bring another person into the review to help address the specific issue.\n   Typically they should at least be an owner, and may usefully be a\n   [Carbon lead](groups.md#carbon-leads).\n\n2. Ask the specific question in a broader forum, such as Discord, in order to\n   get a broad set of perspectives on a particular area or issue.\n\nThe goal of these steps isn't to override the author or the reviewer, but to get\nmore perspectives and voices involved. Often this will clarify the issue and its\ntrade-offs, and provide a simple resolution that all parties are happy with.\nHowever, in some cases, the underlying conflict isn't actually addressed. While\nthere is a desire to generally bias towards the direction of the owners during\nreviews, reviews should _not_ turn into a voting process. The reason for\nproceeding in a specific direction should always be explained sufficiently that\nall parties on the review are satisfied by the explanation and don't feel the\nneed to escalate.\n\nFundamentally, both reviewers and the author need to agree on the direction to\nmove forward. If reaching that agreement proves impossible, the review should be\n[escalated](#escalation). If you feel like an escalation is needed in a review,\nbe explicit and clear in requesting it. There is nothing bad about going through\nthis process, but it should only occur when needed and so it helps to be very\nclear.\n\nOnce the impasse or conflict is addressed, it is _essential_ to commit to that\ndirection. It can be especially difficult for the author to accept a direction\nthat they initially disagree with and make changes to their code as a result. An\nessential skill is the ability to\n[disagree and commit](https://en.wikipedia.org/wiki/Disagree_and_commit).\n\n## Escalation\n\nAt the explicit request of any [Carbon lead](evolution.md#carbon-leads-1) or to\nresolve any fundamental impasse in a review, the change should move to a formal\n[proposal](evolution.md#proposals). Ultimately, the Carbon project\n[governance](evolution.md#governance-structure) structure is always available as\nan escalation path.\n\nBefore escalating an impasse or conflict in code review, try asking another\nreviewer to help resolve the issue or bridge any communication gaps. Consider\nscheduling a quick video chat to discuss and better understand each other’s\nconcerns and position.\n\nNote that the formal evolution process is heavyweight and relatively slow. The\nexpectation is that this is rarely used and only to resolve serious and severe\ndisagreements. If this becomes a more common problem, lighter weight processes\nmay be needed to help ensure a reasonable rate of progress.\n"
  },
  {
    "path": "docs/project/commit_access.md",
    "content": "# Commit access\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Getting access](#getting-access)\n-   [Removing access](#removing-access)\n\n<!-- tocstop -->\n\n## Overview\n\nFirst and foremost, commit access is **not required** for contributing to\nCarbon! Anyone can send a pull request with a change to Carbon. Very few parts\nof our process require commit access, and most development activity is exactly\nthe same for folks with or without. This is an important feature of our GitHub\nworkflow for us, and one we plan to keep.\n\nThe main thing commit access allows is for developers to merge PRs into the main\n[carbon-lang repository](https://github.com/carbon-language/carbon-lang/). They\nstill need review, and often a reviewer with commit access handles the merge. It\nalso gives the ability to [approve and merge changes](code_review.md).\n\nGetting commit access can help ease the development process; for contributors\nwho don't feel comfortable doing reviews, it can still ease the review process\nfor their own PRs. It allows authors to automatically get GitHub Action results\nand merge their own PRs, including after resolving conflicts or fixing trivial\nPR comments post-approval.\n\nDevelopers with commit access are expected to make reasonable choices about when\nto approve or merge PRs for others. Generally, the change either needs to be\ntrivially understood without context on the code in question (such as a cleanup\nor typo fix), or the developer should have some context on the code in question.\nIf in doubt, feel free to review but leave approving or merging for someone\nelse.\n\nSimilarly, developers with commit access are expected to make reasonable choices\nabout what changes to make to their own PRs without asking for another round of\nreview prior to merge, even after approval. And again, if in doubt, ask for\nreview.\n\n## Getting access\n\nContributors can request commit access based on their commit history. We want to\nmake sure that developers with commit access are reasonably familiar with the\nstyle and structure of the codebase. Access will typically be granted when\ndevelopers have contributed several PRs and are expecting to continue making\nmore.\n\nAfter a few non-trivial PRs are merged, contributors can ask a reviewer to\nnominate them for commit access if they plan to keep contributing. Reviewers can\nalso directly suggest and nominate someone. Nominations need to be approved by\nat least one lead.\n\nWhen approved, an invitation will be sent to join the\n[Commit access team](https://github.com/orgs/carbon-language/teams/commit-access)\non GitHub. The invitation should cause a notification from GitHub, but it's also\npossible to go to the\n[invitation link](https://github.com/orgs/carbon-language/invitation) directly.\nAccess is granted when the invitation is accepted.\n\n## Removing access\n\nWe'll periodically remove commit access from contributors who have been idle for\nover 6 months. We'll use a combination of sources to determine what \"idle\"\nmeans, including whether a developer has been either sending or reviewing PRs.\nDevelopers can ask for commit access to be restored if they plan to start\ncontributing again or come back from a break. Any relevant past contributions\nwill still apply and allow it to be restored trivially.\n\nFor example, for `jonmeow`, GitHub searches (defaulting to PRs for convenience,\nbut other types are included):\n\n-   [repository:carbon-language/carbon-lang author:jonmeow](https://github.com/search?q=repository%3Acarbon-language%2Fcarbon-lang+author%3Ajonmeow&type=pullrequests)\n-   [repository:carbon-language/carbon-lang commenter:jonmeow](https://github.com/search?q=repository%3Acarbon-language%2Fcarbon-lang+commenter%3Ajonmeow&type=pullrequests)\n"
  },
  {
    "path": "docs/project/contribution_tools.md",
    "content": "# Contribution tools\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThe Carbon language project has a number of tools used to assist in preparing\ncontributions.\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Setup commands](#setup-commands)\n    -   [Debian or Ubuntu](#debian-or-ubuntu)\n        -   [Installing Bazelisk](#installing-bazelisk)\n        -   [Old `clang` versions](#old-clang-versions)\n    -   [macOS](#macos)\n-   [Tools](#tools)\n    -   [Main tools](#main-tools)\n        -   [Running pre-commit](#running-pre-commit)\n    -   [Optional tools](#optional-tools)\n        -   [Jujutsu (`jj`)](#jujutsu-jj)\n        -   [AI assistants](#ai-assistants)\n    -   [Manually building Clang and LLVM (not recommended)](#manually-building-clang-and-llvm-not-recommended)\n-   [Troubleshooting build issues](#troubleshooting-build-issues)\n    -   [`bazel clean`](#bazel-clean)\n    -   [Old LLVM versions](#old-llvm-versions)\n    -   [Debugging](#debugging)\n    -   [Asking for help](#asking-for-help)\n\n<!-- tocstop -->\n\n## Setup commands\n\nThese commands should help set up a development environment on your machine.\n\n<!-- google-doc-style-ignore -->\n<!-- Need to retain \"repo\" in \"gh repo clone\". -->\n\n### Debian or Ubuntu\n\n```shell\n# Update apt.\nsudo apt update\n\n# Check that the `clang` version is at least 19, our minimum version. That needs\n# the number of the `:` in the output to be over 19. For example, `1:19.0-1`.\napt-cache show clang | grep 'Version:'\n\n# Install tools.\nsudo apt install \\\n  clang \\\n  gh \\\n  libc++-dev \\\n  libc++abi-dev \\\n  lld \\\n  lldb \\\n  python3 \\\n  pipx\n\n# Install pre-commit.\npipx install pre-commit\n\n# Set up git.\n# If you don't already have a fork:\ngh repo fork --clone carbon-language/carbon-lang\ncd carbon-lang\npre-commit install\n\n# Run tests.\n./scripts/run_bazelisk.py test //...:all\n```\n\n#### Installing Bazelisk\n\nAlthough the `run_bazelisk` script can make it easy to get started, if you're\nfrequently building Carbon, it can be a bit much to type. Consider either\naliasing `bazel` to the `run_bazelisk.py` script, or\n[downloading a bazelisk release](https://github.com/bazelbuild/bazelisk), adding\nit to your `$PATH`, and aliasing `bazel` to it.\n\n#### Old `clang` versions\n\nIf the version of `clang` is earlier than 19, you may still have version 19\navailable. You can use the following install instead:\n\n```shell\n# Install explicitly versioned Clang tools.\nsudo apt install \\\n  clang-19 \\\n  libc++-19-dev \\\n  libc++abi-19-dev \\\n  lld-19 \\\n  lldb-19\n\n# In your Carbon checkout, tell Bazel where to find `clang`. You can also\n# export this path as the `CC` environment variable, or add it directly to\n# your `PATH`.\necho \"build --repo_env=CC=$(readlink -f $(which clang-19))\" >> user.bazelrc\n```\n\nAnd if it's not available directly from the distribution, you can install Clang\ntools on Debian/Ubuntu from <https://apt.llvm.org>.\n\n> NOTE: Most LLVM 19+ installs should build Carbon. If you're having issues, see\n> [troubleshooting build issues](#troubleshooting-build-issues).\n\n### macOS\n\n```shell\n# Install Homebrew.\n/bin/bash -c \"$(curl -fsSL \\\n  https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"\n\n# IMPORTANT: Make sure `brew` is added to the PATH!\n\n# Install Homebrew tools.\nbrew install \\\n  bazelisk \\\n  gh \\\n  llvm \\\n  python@3.10 \\\n  pre-commit\n\n# IMPORTANT: Make sure `llvm` is added to the PATH! It's separate from `brew`.\n\n# Set up git.\ngh repo fork --clone carbon-language/carbon-lang\ncd carbon-lang\npre-commit install\n\n# Run tests. Note homebrew makes `bazel` an alias to `bazelisk`.\nbazel test //...:all\n```\n\n> NOTE: On macOS, you should end up adding rc file lines similar to:\n>\n> ```\n> # For `brew`, `gh`, and other tools:\n> export PATH=\"${HOME}/.brew/bin:${PATH}\"\n> # For `llvm`:\n> export PATH=\"$(brew --prefix llvm)/bin:${PATH}\"\n> ```\n\n<!-- google-doc-style-resume -->\n\n## Tools\n\n### Main tools\n\nThese tools are essential for work on Carbon.\n\n-   Package managers\n    -   `apt` (for Debian or Ubuntu)\n        -   To upgrade versions of `apt` packages, it will be necessary to\n            periodically run `sudo apt update && sudo apt upgrade`.\n    -   [Homebrew](https://brew.sh/) (for macOS)\n        -   To upgrade versions of `brew` packages, it will be necessary to\n            periodically run `brew upgrade`.\n    -   [Python](https://python.org)\n        -   Carbon requires Python 3.10 or newer.\n        -   To upgrade versions of pip-installed packages, it will be necessary\n            to periodically run `pipx list --outdated`, then\n            `pipx install -U <package>` to upgrade desired packages.\n        -   When upgrading, version dependencies may mean packages _should_ be\n            outdated, and not be upgraded.\n-   Main tools\n    -   [Bazel](https://www.bazel.build/)\n        -   [Bazelisk](https://docs.bazel.build/versions/master/install-bazelisk.html):\n            Downloads and runs the [configured Bazel version](/.bazelversion).\n    -   [Clang](https://clang.llvm.org/) and [LLVM](https://llvm.org/)\n        -   NOTE: Most LLVM 19+ installs should build Carbon. If you're having\n            issues, see\n            [troubleshooting build issues](#troubleshooting-build-issues).\n    -   [gh CLI](https://github.com/cli/cli): Helps with GitHub.\n    -   [pre-commit](https://pre-commit.com): Validates and cleans up git\n        commits.\n    -   `autoupdate_testdata.py`: Updates expected output for tests.\n        -   Usage: `./toolchain/autoupdate_testdata.py [files...]`\n        -   This is essential when changes affect compiler output (diagnostics,\n            SemIR, etc.).\n\n#### Running pre-commit\n\n[pre-commit](https://pre-commit.com) is typically set up using\n`pre-commit install`. When set up in this mode, it will check for issues when\n`git commit` is run. A typical commit workflow looks like:\n\n1.  `git commit` to try committing files. This automatically executes\n    `pre-commit run`, which may fail and leave files modified for cleanup.\n2.  `git add .` to add the automatically modifications done by `pre-commit`.\n3.  `git commit` again.\n\nYou can also use `pre-commit run` to check pending changes without `git commit`,\nor `pre-commit run -a` to run on all files in the repository.\n\n> NOTE: Some developers prefer to run `pre-commit` on `git push` instead of\n> `git commit` because they want to commit files as originally authored instead\n> of with pre-commit modifications. To switch, run\n> `pre-commit uninstall && pre-commit install -t pre-push`.\n\n### Optional tools\n\nThese tools aren't necessary to contribute to Carbon, but can be worth\nconsidering if they fit your workflow.\n\n-   [GitHub Desktop](https://desktop.github.com/): A UI for managing GitHub\n    repositories.\n-   `rs-git-fsmonitor` and Watchman: Helps make `git` run faster on large\n    repositories.\n    -   **WARNING**: Bugs in `rs-git-fsmonitor` and/or Watchman can result in\n        `pre-commit` deleting files. If you see files being deleted, disable\n        `rs-git-fsmonitor` with `git config --unset core.fsmonitor`.\n-   [vim-prettier](https://github.com/prettier/vim-prettier): A vim integration\n    for [Prettier](https://prettier.io/), which we use for formatting.\n-   [Visual Studio Code](https://code.visualstudio.com/): A code editor.\n    -   We provide [recommended extensions](/.vscode/extensions.json) to assist\n        Carbon development. Some settings changes must be made separately:\n        -   Python › Formatting: Provider: `black`\n    -   **WARNING:** Visual Studio Code modifies the `PATH` environment\n        variable, particularly in the terminals it creates. The `PATH`\n        difference can cause `bazel` to detect different startup options,\n        discarding its build cache. As a consequence, it's recommended to use\n        **either** normal terminals **or** Visual Studio Code to run `bazel`,\n        not both in combination. Visual Studio Code can still be used for other\n        purposes, such as editing files, without interfering with `bazel`.\n    -   We also provide recommended setups for debugging in VS Code with either\n        [LLDB](/toolchain/docs/debugging.md#debugging-with-lldb) or\n        [GDB]((/toolchain/docs/debugging.md#debugging-with-gdb)\n-   [clangd](https://clangd.llvm.org/installation): An LSP server implementation\n    for C/C++.\n\n    -   To ensure that `clangd` reports accurate diagnostics. It needs a\n        generated file called `compile_commands.json`. This can be generated by\n        invoking the command below:\n\n        ```\n        ./scripts/create_compdb.py\n        ```\n\n        -   **NOTE**: This assumes you have `python` 3 installed on your system.\n\n-   [`uv`](https://docs.astral.sh/uv/): A fast Python package manager.\n    -   Notably, `uv` supports automatic management of even complex Python\n        dependencies for scripts: https://docs.astral.sh/uv/guides/scripts/\n    -   Installation: https://docs.astral.sh/uv/getting-started/installation/\n\n#### Jujutsu (`jj`)\n\n[Jujutsu](https://github.com/jj-vcs/jj) is a Git-compatible version control\nsystem that can be used instead of or alongside Git. See the\n[documentation for using Jujutsu with GitHub](https://jj-vcs.github.io/jj/latest/github/)\nfor more information.\n\nIf you use `jj`, you may find the following configuration snippets (added to\n`~/.config/jj/config.toml`) helpful for your workflow:\n\n```toml\n[aliases]\n# Clean up untracked or abandoned commits.\nabandon-untagged = [\"abandon\", \"all() & ~ancestors(@ | bookmarks() | remote_bookmarks())\"]\n\n[ui]\n# Use Git-style conflict markers, which VS Code can provide merge support for.\nconflict-marker-style = \"git\"\n\n[ui.diff]\n# Produce Git-compatible diff format.\nformat = \"git\"\n\n[remotes.origin]\n# Automatically track all remote bookmarks.\nauto-track-bookmarks = \"*\"\n\n[templates]\n# Automatically add a trailer to commits to indicate that they were AI-assisted.\ncommit_trailers = '''\n\"Assisted-by: My AI Tool\"'''\n```\n\n#### AI assistants\n\nWhen using AI assistants and reviewing terminal commands, some commands which\nmay be helpful and reasonably safe to allowlist (assuming prefix-based\nallowlisting) are:\n\n```\n# Carbon development commands.\nbazelisk build\nbazelisk test\nbazelisk run //toolchain/testing:file_test --\nclang-format\npre-commit run\n./toolchain/autoupdate_testdata.py\n\n# Shell commands. Note that these allow reading arbitrary files on your local\n# file system.\ncat\ngrep\nhead\nls\n\n# VCS commands.\ngit diff\ngit log\ngit show\ngit status\n```\n\n### Manually building Clang and LLVM (not recommended)\n\nWe primarily test against [apt.llvm.org](https://apt.llvm.org) and Homebrew\ninstallations. However, you can build and install LLVM yourself if you feel more\ncomfortable with it. The essential CMake options to pass in order for this to\nwork reliably include:\n\n```\n-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra;lld;lldb\n-DLLVM_ENABLE_RUNTIMES=compiler-rt;libcxx;libcxxabi;libunwind\n-DRUNTIMES_CMAKE_ARGS=-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF;-DCMAKE_POSITION_INDEPENDENT_CODE=ON;-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON;-DLIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY=OFF;-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON;-DLIBCXX_USE_COMPILER_RT=ON;-DLIBCXXABI_USE_COMPILER_RT=ON;-DLIBCXXABI_USE_LLVM_UNWINDER=ON\n-DLLDB_ENABLE_PYTHON=ON\n```\n\n## Troubleshooting build issues\n\n### `bazel clean`\n\nChanges to packages installed on your system may not be noticed by `bazel`. This\nincludes things such as changing LLVM versions, or installing libc++. Running\n`bazel clean` should force cached state to be rebuilt.\n\n### Old LLVM versions\n\nMany build issues result from the particular options `clang` and `llvm` have\nbeen built with, particularly when it comes to system-installed versions. If you\nrun `clang --version`, you should see at least version 19. If you see an older\nversion, please update, or use the special `clang-19` instructions above.\n\nSystem installs of macOS typically won't work, for example being an old LLVM\nversion or missing llvm-ar; [setup commands](#setup-commands) includes LLVM from\nHomebrew for this reason.\n\nRun [`bazel clean`](#bazel-clean) when changing the installed LLVM version.\n\n### Debugging\n\nSee the [toolchain documentation](/toolchain/docs/debugging.md) for guidance on\nhow to debug problems with the toolchain itself.\n\n### Asking for help\n\nIf you're having trouble resolving issues, please ask on\n[#build-help](https://discord.com/channels/655572317891461132/824137170032787467),\nproviding the output of the following diagnostic commands:\n\n```shell\necho $CC\nwhich clang\nwhich clang-19\nclang --version\ngrep llvm_bindir $(bazel info workspace)/bazel-execroot/external/+clang_toolchain_extension+bazel_cc_toolchain/clang_detected_variables.bzl\n\n# If on macOS:\nbrew --prefix llvm\n```\n\nThese commands will help diagnose potential build issues by showing which\ntooling is in use.\n"
  },
  {
    "path": "docs/project/cpp_style_guide.md",
    "content": "# C++ style guide\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n-   [Baseline](#baseline)\n-   [Carbon-local guidance](#carbon-local-guidance)\n    -   [General naming rules](#general-naming-rules)\n    -   [File names](#file-names)\n    -   [Syntax and formatting](#syntax-and-formatting)\n        -   [Line comments](#line-comments)\n        -   [Initialization](#initialization)\n        -   [Passing addresses](#passing-addresses)\n    -   [Naming variable types and the use of `auto`](#naming-variable-types-and-the-use-of-auto)\n    -   [Copyable and movable types](#copyable-and-movable-types)\n    -   [Static and global variables](#static-and-global-variables)\n    -   [Foundational libraries and data types](#foundational-libraries-and-data-types)\n    -   [Iterative algorithms](#iterative-algorithms)\n-   [Suggested `.clang-format` contents](#suggested-clang-format-contents)\n\n<!-- tocstop -->\n\n## Background\n\nC++ code in the Carbon project should use a consistent and well documented style\nguide. Where possible, this should be enacted and enforced with tooling to avoid\ntoil both for authors of C++ code in the Carbon project and for code reviewers.\n\nHowever, we are not in the business of innovating significantly in the space of\nwriting clean and maintainable C++ code, and so we work primarily to reuse\nexisting best practices and guidelines.\n\n## Baseline\n\nThe baseline style guidance is the\n[Google C++ style guide](https://google.github.io/styleguide/cppguide.html).\n\n## Carbon-local guidance\n\nWe provide some local guidance beyond the baseline. These are typically motived\neither by specific value provided to the project, or to give simpler and more\nstrict guidance for Carbon's narrow use of C++.\n\n### General naming rules\n\nCarbon's C++ code tries to match the proposed Carbon naming convention as\nclosely as is reasonable in C++ in order to better understand and familiarize\nourselves with the practice of using this convention. It happens that this is\nfairly similar to the naming convention in the Google style guide and largely\nserves to simplify it.\n\n-   Known, compile-time constants use `UpperCamelCase`, referencing Proper\n    Nouns.\n    -   This includes namespaces, type names, functions, member functions\n        (except as noted below), template parameters, `constexpr` variables,\n        enumerators, etc.\n    -   Note that virtual member functions should be named with\n        `UpperCamelCase`. The distinction between a virtual function and a\n        non-virtual function should be invisible, especially at the call site,\n        as that is an internal implementation detail. We want to be able to\n        freely change that without updating the name.\n-   Member functions may use `snake_case` names if they do nothing besides\n    return a reference to a data member (or assign a value to a data member, in\n    the case of `set_` methods), **or** if their behavior (including\n    performance) would be unsurprising to a caller who assumes they are\n    implemented that way.\n-   All other names use `snake_case`, including function parameters, and\n    non-constant local and member variables.\n    -   Private member variables should have a trailing `_`.\n-   For acronyms and initialisms, we generally follow the\n    [capitalization style](https://google.github.io/styleguide/cppguide.html#General_Naming_Rules)\n    (`Api` instead of `API`).\n    -   The exceptions are `LLVM` and `IR`, which we capitalize.\n-   For abbreviations, there is a list of\n    [common toolchain abbreviations](/toolchain/docs/idioms.md#abbreviations-used-in-the-code-aka-carbon-abbreviation-decoder-ring).\n\n### File names\n\n-   Always use `snake_case` for files, directories, and build system rules.\n    Avoid `-`s in these as well.\n-   Use `.cpp` for source files, which is the most common open source extension\n    and matches other places where \"C++\" is written without punctuation.\n\n### Syntax and formatting\n\nThese are minor issues where any of the options would be fine and we simply need\nto pick a consistent option. Where possible,\n[`clang-format`](#suggested-clang-format-contents) should be used to enforce\nthese.\n\n-   Always use trailing return type syntax for functions and methods, including\n    `-> void`, for consistency with Carbon syntax.\n-   Place the pointer `*` adjacent to the type: `TypeName* variable_name`.\n-   Only declare one variable at a time (declaring multiple variables requires\n    confusing repetition of part of the type).\n-   Write `const` before the type when at the outer level: `const int N = 42;`.\n-   Use the `using`-based type alias syntax instead of `typedef`.\n-   Don't use `using` to support unqualified lookup on `std` types; for example,\n    `using std::vector;`. This also applies to other short namespaces,\n    particularly `llvm` and `clang`.\n    -   Writing `std::` gives clearer diagnostics and avoids any possible\n        ambiguity, particularly for ADL.\n    -   An exception is made for functions like `std::swap` that are\n        intentionally called using ADL. This pattern should be written as\n        `{ using std::swap; swap(thing1, thing2); }`.\n-   Always mark constructors `explicit` unless there's a specific reason to\n    support implicit or `{}` initialization.\n-   Always use braces for conditional, `switch`, and loop statements, even when\n    the body is a single statement.\n    -   Within a `switch` statement, use braces after a `case` label when\n        necessary to create a scope for a variable.\n    -   Always break the line immediately after an open brace except for empty\n        loop bodies.\n-   For\n    [internal linkage](https://google.github.io/styleguide/cppguide.html#Internal_Linkage)\n    of definitions of functions and variables, prefer `static` over anonymous\n    namespaces. `static` minimizes the context necessary to notice the internal\n    linkage of a definition.\n    -   Anonymous namespaces are still necessary for classes and enums.\n    -   Tests are an exception and should typically be wrapped in an anonymous\n        namespace under the namespace of the code under test, to keep everything\n        internal.\n-   For\n    [Access Control](https://google.github.io/styleguide/cppguide.html#Access_Control),\n    specifically for test fixtures in `.cpp` files, we use `public` instead of\n    `protected`. This is motivated by the\n    `misc-non-private-member-variables-in-classes` tidy check.\n\n#### Line comments\n\nOnly use line comments (with `//`, not `/* ... */`), on a line by themselves,\nexcept for\n[argument name comments](https://clang.llvm.org/extra/clang-tidy/checks/bugprone/argument-comment.html),\n[closing namespace comments](https://google.github.io/styleguide/cppguide.html#Namespaces),\nand similar structural comments. In particular, don't append comments about a\nline of code to the end of its line:\n\n```\nint bad = 42;  // Don't comment here.\n\n// Instead comment here.\nint good = 42;\n\n// Closing namespace comments are structural, and both okay and expected.\n}  // namespace MyNamespace\n```\n\nThis dogfoods our planned commenting syntax for Carbon. It also provides a\nsingle, consistent placement rule. It also provides more resilience against\nautomated refactorings. Those changes often make code longer, which forces ever\nmore difficult formatting decisions, and can easily spread one line across\nmultiple lines, leaving it impossible to know where to place the comment.\nComments on their own line preceding such code, while still imprecise, are at\nleast less confusing over the course of such refactorings.\n\n#### Initialization\n\nInitialization syntax has guidelines based on what compiles. See also\n[Abseil's tip #88](https://abseil.io/tips/88#best-practices-for-initialization),\nalthough these guidelines differ slightly.\n\n-   Use assignment syntax (`=`) when initializing directly with the intended\n    value (or with a braced initializer directly specifying that value).\n-   Prefer braced initialization for aggregate initialization, such as structs,\n    pairs, and initializer lists.\n    -   Use designated initializers (`{.a = 1}`) when possible for structs, but\n        not for pairs or tuples. Prefer to only include the typename when\n        required to compile (`WizType{.a = 1}`). This is analogous to how\n        structs and tuples would be written in Carbon code.\n    -   Avoid braced initialization for types that define a constructor, except\n        as an initializer list (`llvm::SmallVector<int> v = {0, 1};`),\n        `std::pair`, or `std::tuple`. Never use it with `auto`\n        (`auto a = {0, 1}`).\n-   Prefer parenthesized initialization (`FooType foo(10);`) in most other\n    cases.\n-   Braced initialization without `=` (`BarType bar{10}`) should be treated as a\n    fallback, preferred only when other constructor syntax doesn't compile.\n\n#### Passing addresses\n\nWhen passing an object's address as an argument, use a reference unless one of\nthe following cases applies:\n\n-   If the parameter is optional, use a pointer and document that it may be\n    null.\n-   If it is captured and must outlive the call expression itself, use a pointer\n    and document that it must not be null (unless it is also optional).\n\n    -   When storing an object's address as a non-owned member, prefer storing a\n        pointer. For example:\n\n        ```cpp\n        class Bar {\n          public:\n            // `foo` must not be null.\n            explicit Bar(Foo* foo) : foo_(foo) {}\n          private:\n            Foo* foo_;\n        };\n        ```\n\n### Naming variable types and the use of `auto`\n\nWe generally use `auto` for most local variables when a type can be inferred,\nexcept for primitive types such as `bool` and `int`. It is not required to use\n`auto`, and shorter type names such as `SemIR::InstId` are sometimes named even\nthough they could be inferred. Naming the type can be helpful in cases where the\ntype would be obscure and can not be explained with the variable name. Function\nparameters generally name the type of each parameter, though lambdas may use\n`auto` if it's helpful.\n\nWhen naming variables, we typically suffix `_id` for ID types. When needed, we\ncan also resolve ambiguity by referring to the full type name in the variable\nname; for example, if there's a `ClassId`, `InstId`, and `TypeId` for the same\nclass entity, we might call these `class_id`, `class_inst_id`, and\n`class_type_id`. Similarly, we might call an `Inst` `class_inst`.\n\n### Copyable and movable types\n\n-   Types should have value semantics and support both move and copy where\n    possible.\n-   Types that cannot be copied should still be movable where possible.\n-   If supported, moving should be as efficient as possible.\n\n### Static and global variables\n\n-   Global and static variables, whether at file, class, or function scope,\n    should be declared `constexpr`.\n\n### Foundational libraries and data types\n\n-   In the toolchain, prefer LLVM libraries and data structures to standard C++\n    ones.\n    -   These are optimized significantly for performance, especially when used\n        without exception handling or safety requirements, and when used in\n        patterns that tend to occur while building compilers.\n    -   They also minimize the vocabulary type friction when using actual LLVM\n        and Clang APIs.\n-   Do not add other third-party library dependencies to any code that might\n    conceivably be used as part of the compiler or runtime.\n    -   Compilers and runtime libraries have unique constraints on their\n        licensing. For simplicity, we want all transitive dependencies of these\n        layers to be under the LLVM license that the Carbon project as a whole\n        uses (as well as LLVM itself).\n\n### Iterative algorithms\n\nWe choose iterative over recursive algorithms, and use clang-tidy to help\nenforce this. We expect Carbon to be used in codebases which stress test the\ncompiler, for example due to complex interactions of APIs or simply due to\nrepetitive code structures from code generators.\n\nOther solutions that make recursion work better have been considered, but we\nprefer iteration for its performance and robustness. For example, Clang launches\nthreads when it gets close to a stack limit; that has performance overhead and\nrelies on developers correctly identifying recursion which may have limits.\n\n## Suggested `.clang-format` contents\n\nSee this repository's [`.clang-format` file](/.clang-format).\n"
  },
  {
    "path": "docs/project/design_style_guide.md",
    "content": "# Language design style guide\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n-   [General](#general)\n-   [Linking](#linking)\n-   [Document structure](#document-structure)\n    -   [Overview and detailed design](#overview-and-detailed-design)\n    -   [Alternatives considered](#alternatives-considered)\n    -   [References](#references)\n\n<!-- tocstop -->\n\n## Background\n\nThe [language design](/docs/design) documentation in the Carbon project should\nuse a consistent style and tone, and should read as if it were written by a\nsingle author. This document describes structural, stylistic, and formatting\nconventions for the language design, where they have been established.\n\n## General\n\nThe language design documentation follows the\n[style conventions](/CONTRIBUTING.md#google-docs-and-markdown) for Carbon\ndocumentation.\n\n## Linking\n\n-   Links to issues and to complete proposals should use the text `#nnnn`, where\n    `nnnn` is the issue number, optionally followed by the proposal title, and\n    should link to the issue or pull request on GitHub. For example,\n    `[#123: widget painting](https://github.com/carbon-language/carbon-lang/pull/123)`.\n-   Links to specific sections of a proposal should link to the repository copy\n    of the proposal file, using the section title or other appropriate link\n    text. For example,\n    `[Painting details](/proposals/p0123.md#painting-details)`\n\n## Document structure\n\nDocuments within the language design should usually be divided into the\nfollowing sections, with suitable level-two (`##`) headings:\n\n-   **Table of contents** (auto-generated)\n-   **TODO** (optional)\n-   **Overview**\n-   Zero or more detailed design sections\n-   **Alternatives considered**\n-   **References**\n\n### Overview and detailed design\n\nThe overview should describe the high-level concepts of this area of the design,\nfollowing BLUF principles. Where the overview does not fully cover the detailed\ndesign, additional sections can be added as needed to more completely describe\nthe design.\n\nThe aim of these sections is to describe the design choices that have been made,\nhow those choices fit into the overall design of Carbon, the rationale for those\nchoices, and how and why those choices differ from other languages to which\nCarbon is likely to be compared, particularly C++, Rust, and Swift.\n\n### Alternatives considered\n\nThis section should provide bullet points briefly describing alternative designs\nthat were considered, along with references to the proposals in which those\ndesigns were discussed. For example:\n\n```md\n-   [Paint widgets from bottom to top](/proposals/p0123.md#alternatives-considered).\n```\n\n### References\n\nThis section should provide bullet points linking to the following:\n\n-   External documents providing background on the topic or additional useful\n    information.\n-   Each proposal that contributed to the design described in this document.\n\nFor example:\n\n```md\n-   [Wikipedia example page](https://en.wikipedia.org/wiki/Wikipedia:Example)\n-   Proposal\n    [#123: widget painting](https://github.com/carbon-language/carbon-lang/pull/123).\n```\n\nLinks to related parts of the design should be included inline, where relevant,\nnot in the references section.\n"
  },
  {
    "path": "docs/project/difficulties_improving_cpp.md",
    "content": "# Difficulties improving C++\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nC++ is the dominant programming language for the performance critical software\nour goals prioritize. The most direct way to deliver a modern and excellent\ndeveloper experience for those use cases and developers would be to improve C++.\n\nImproving C++ to deliver the kind of experience developers expect from a\nprogramming language today is difficult in part because **C++ has decades of\ntechnical debt** accumulated in the design of the language. It inherited the\nlegacy of C, including\n[textual preprocessing and inclusion](https://clang.llvm.org/docs/Modules.html#problems-with-the-current-model).\nAt the time, this was essential to C++'s success by giving it instant and high\nquality access to a large C ecosystem. However, over time this has resulted in\nsignificant technical debt ranging from\n[integer promotion rules](https://shafik.github.io/c++/2021/12/30/usual_arithmetic_confusions.html)\nto complex syntax with\n\"[the most vexing parse](https://en.wikipedia.org/wiki/Most_vexing_parse)\".\n\n**C++ has also prioritized backwards compatibility** including both syntax and\n[ABI](https://en.wikipedia.org/wiki/Application_binary_interface). This is\nheavily motivated by preserving its access to existing C and C++ ecosystems, and\nforms one of the foundations of common Linux package management approaches. A\nconsequence is that rather than changing or replacing language designs to\nsimplify and improve the language, features have overwhelmingly been added over\ntime. This both creates technical debt due to complicated feature interaction,\nand fails to benefit from on cleanup opportunities in the form of replacing or\nremoving legacy features.\n\nCarbon is exploring significant backwards incompatible changes. It doesn't\ninherit the legacy of C or C++ directly, and instead is starting with solid\nfoundations, like a modern generics system, modular code organization, and\nconsistent, simple syntax. Then, it builds a simplified and improved language\naround those foundational components that remains both interoperable with and\nmigratable from C++, while giving up transparent backwards compatibility. This\nis fundamentally **a successor language approach**, rather than an attempt to\nincrementally evolve C++ to achieve these improvements.\n\nAnother challenge to improving C++ in these ways is the current evolution\nprocess and direction. A key example of this is the committee's struggle to\nconverge on a clear set of high-level and long-term goals and priorities aligned\nwith [ours](https://wg21.link/p2137). When [pushed](https://wg21.link/p1863) to\naddress\n[the technical debt caused by not breaking the ABI](https://wg21.link/p2028),\n**C++'s process\n[did not reach any definitive conclusion](https://cor3ntin.github.io/posts/abi/#abi-discussions-in-prague)**.\nThis both failed to meaningfully change C++'s direction and priorities towards\nimprovements rather than backwards compatibility, and demonstrates how the\nprocess can fail to make directional decisions.\n\nBeyond C++'s evolution direction, the mechanics of the process also make\nimproving C++ difficult. **C++'s process is oriented around standardization\nrather than design**: it uses a multiyear waterfall committee process. Access to\nthe committee and standard is restricted and expensive, attendance is necessary\nto have a voice, and decisions are made by live votes of those present. The\ncommittee structure is designed to ensure representation of nations and\ncompanies, rather than building an inclusive and welcoming team and community of\nexperts and people actively contributing to the language.\n\nCarbon has a more accessible and efficient [evolution process](evolution.md)\nbuilt on open-source principles, processes, and tools. Throughout the project,\nwe explicitly and clearly lay out our [goals and priorities](goals.md) and how\nthose directly shape our decisions. We also have a clear\n[governance structure](evolution.md#governance-structure) that can make\ndecisions rapidly when needed. The open-source model enables the Carbon project\nto expand its scope beyond just the language. We will build a holistic\ncollection of tools that provide a rich developer experience, ranging from the\ncompiler and standard library to IDE tools and more. **We will even try to close\na huge gap in the C++ ecosystem with a built-in package manager.**\n\nCarbon is particularly focused on a specific set of [goals](goals.md). These\nwill not align with every user of C++, but have significant interest across a\nwide range of users that are capable and motivated to evolve and modernize their\ncodebase. Given the difficulties posed by C++'s technical debt, sustained\npriority of backwards compatibility, and evolution process, we wanted to explore\nan alternative approach to achieve these goals -- through a\nbackwards-incompatible successor language, designed with robust support for\ninteroperability with and migration from C++. We hope other efforts to\nincrementally improve C++ continue, and would love to share ideas where we can.\n"
  },
  {
    "path": "docs/project/evolution.md",
    "content": "# Evolution and governance\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Proposals](#proposals)\n    -   [Life of a proposal](#life-of-a-proposal)\n    -   [Proposal roles](#proposal-roles)\n        -   [Proposal authors](#proposal-authors)\n        -   [Community](#community)\n        -   [Active contributors](#active-contributors)\n        -   [Carbon leads](#carbon-leads)\n    -   [When to write a proposal](#when-to-write-a-proposal)\n    -   [Proposal PRs](#proposal-prs)\n        -   [What goes in the proposal document](#what-goes-in-the-proposal-document)\n        -   [Open questions](#open-questions)\n    -   [Review and RFC on proposal PRs](#review-and-rfc-on-proposal-prs)\n    -   [Blocking issues](#blocking-issues)\n        -   [Discussion on blocking issues](#discussion-on-blocking-issues)\n-   [Governance structure](#governance-structure)\n    -   [Carbon leads](#carbon-leads-1)\n        -   [Subteams](#subteams)\n    -   [Painter](#painter)\n    -   [Adding and removing governance members](#adding-and-removing-governance-members)\n-   [Acknowledgements](#acknowledgements)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon's evolution process uses [proposals](#proposals) to evaluate and approve\n[significant changes](#when-to-write-a-proposal) to the project or language.\nThis process is designed to:\n\n-   Ensure these kinds of changes can receive feedback from the entire\n    community.\n-   Resolve questions and decide direction efficiently.\n-   Create a clear log of the rationale for why the project and language have\n    evolved in particular directions.\n\nWhen there are questions, concerns, or issues with a proposal that need to be\nresolved, Carbon uses its [governance](#governance-structure) system of\n[Carbon leads](#carbon-leads-1) to decide how to move forward. Leads are\nfundamentally responsible for encouraging Carbon's ongoing and healthy evolution\nand so also take on the critical steps of the evolution process for proposals.\n\n## Proposals\n\nThese are primarily structured as GitHub pull requests that use a somewhat more\nformal document structure and process to ensure changes to the project or\nlanguage are well explained, justified, and reviewed by the community.\n\n### Life of a proposal\n\n-   Proposals consist of a PR (pull request) in GitHub that adds a document to\n    the [`proposals/` directory](/proposals/) following\n    [the template](/proposals/scripts/template.md).\n\n-   Proposal PRs start in draft mode. When proposal PRs are ready, click on\n    [\"Ready for review\"](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review).\n    This will:\n\n    -   Route the proposal to a Carbon lead for review.\n\n    -   Send the proposal as a broad RFC to the community.\n\n    -   Add the \"proposal rfc\" label for tracking.\n\n-   Contributors are encouraged to react with a _thumbs-up_ to proposal PRs if\n    they are generally interested and supportive of the high-level direction\n    based on title and summary. Similarly, other reactions are encouraged to\n    help surface contributor's sentiment.\n\n-   We use GitHub issues to discuss and track _blocking issues_ with proposals,\n    such as open questions or alternative approaches that may need further\n    consideration. These are assigned to carbon-leads to decide.\n\n-   A [Carbon lead](#carbon-leads-1) will be assigned to a proposal PR. They are\n    responsible for the basic review (or delegating that) as well as ultimately\n    approving the PR.\n\n-   The assigned lead should ensure that there is a reasonable degree of\n    consensus among the contributors outside of the identified blocking issues.\n    Contributors should have a reasonable chance to raise concerns, and where\n    needed they should become blocking issues. Community consensus isn't\n    intended to be perfect, and is ultimately a judgment call by the lead. When\n    things are missed or mistakes are made here, we should just revert or\n    fix-forward as usual.\n\n-   Once a reasonable degree of community consensus is reached and the assigned\n    lead finishes code review, the lead should\n    [approve](/docs/project/code_review.md#approving-the-change) the PR. Any\n    outstanding high-level concerns should be handled with blocking issues.\n\n-   Optionally, the assigned lead can file a blocking issue for a one-week final\n    comment period when they approve. This is rarely needed, and only when it is\n    both useful and important for the proposal to give extra time for community\n    comments.\n\n-   The leads are responsible for resolving any blocking issues for a proposal\n    PR, including the one-week comment period where resolving it indicates\n    comments arrived which require the proposal to undergo further review.\n\n-   The proposal PR can be merged once the assigned lead approves, all blocking\n    issues have been decided, and any related decisions are incorporated.\n\n-   If the leads choose to defer or reject the proposal, the reviewing lead\n    should explain why and close the PR.\n\n### Proposal roles\n\nIt is also useful to see what the process looks like for different roles within\nthe community. These perspectives are also the most critical to keep simple and\neasily understood.\n\n#### Proposal authors\n\nFor proposal authors, this should feel like a code review, with some broken out\nissues for longer discussion:\n\n-   Create a proposal document and draft PR following\n    [the template](/proposals/scripts/template.md).\n\n    -   [new_proposal.py](/proposals/scripts/new_proposal.py) helps create\n        templated PRs.\n\n    -   If you have open questions, filing [blocking issues](#blocking-issues)\n        while preparing the PR can help resolve them quickly.\n\n-   When ready, click on\n    [\"Ready for review\"](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review)\n    in GitHub. This will:\n\n    -   Route the proposal to a Carbon lead for review.\n\n    -   Send the proposal as a broad RFC to the community.\n\n    -   Add the \"proposal rfc\" label for tracking.\n\n-   Address comments where you can and they make sense.\n\n-   If you don't see an obvious way to address comments, that's OK.\n\n    -   It's great to engage a bit with the commenter to clarify their comment\n        or why you don't see an obvious way to address it, just like you would\n        [in code review](/docs/project/code_review.md#responding-to-review-comments).\n\n    -   If the commenter feels this is important, they can move it to a blocking\n        issue for a longer discussion and resolution from the leads.\n\n    -   You don't need to try to resolve everything yourself.\n\n-   Incorporate any changes needed based on the resolution of blocking issues.\n    Once the leads have provided a resolution, it's important to make progress\n    with that direction.\n\n-   When you both have\n    [approval](/docs/project/code_review.md#approving-the-change) from the\n    assigned lead and the last blocking issue is addressed, merge!\n\n    -   If you end up making significant changes when incorporating resolved\n        issues after the approval from the assigned lead, circle back for a\n        fresh approval before merging, just like you would with code review.\n\n#### Community\n\n-   We use the\n    [\"proposal rfc\" label](https://github.com/carbon-language/carbon-lang/pulls?q=is%3Apr+is%3Aopen+label%3A%22proposal+rfc%22)\n    to track proposals that are in RFC.\n\n    -   Anyone that is interested can participate once a proposal is ready for\n        review and in RFC.\n\n    -   It's OK to only comment when particularly interested in a proposal, or\n        when asked by one of the leads to help ensure thorough review. Not\n        everyone needs to participate heavily in every RFC.\n\n    -   PRs that are in \"draft\" status in GitHub are considered\n        works-in-progress. Check with the author before spending time reviewing\n        these, and generally avoid distracting the author with comments unless\n        they ask for them. The proposal may be actively undergoing edits.\n\n-   Read the proposal and leave comments to try to help make the proposal an\n    improvement for Carbon.\n\n    -   Note that progress and improvement are more important than perfection\n        here!\n\n-   Try to make comments on proposals\n    [constructive](/docs/project/code_review.md#writing-review-comments).\n    Suggest how the proposal could be better if at all possible.\n\n-   If there is an open question or a critical blocking issue that needs to get\n    resolved, move it to its own issue that the PR depends on, and focus the\n    discussion there.\n\n    -   The issue should focus on surfacing the important aspects of the\n        tradeoff represented by the issue or open question, not on advocacy.\n\n#### Active contributors\n\nEveryone actively contributing to the evolution of Carbon should try to\nregularly:\n\n-   Give a thumbs-up or other reaction on any interesting PRs out for RFC to\n    help surface the community's sentiment around the high level idea or\n    direction. Don't worry about \"approving\" or the detailed text of the\n    proposal here.\n\n-   If interested and time permitting, dive into some RFCs and provide\n    [community feedback](#community).\n\n#### Carbon leads\n\n[Carbon leads](#carbon-leads-1) are responsible for making decisions rapidly and\nensuring proposal PRs land:\n\n-   Rapidly resolve all blocking issues raised across any proposals.\n\n-   When assigned a specific proposal PR:\n\n    -   Make sure it gets both constructive general comments and good code\n        review.\n\n    -   Ideally, you should directly participate in the code review, but it's\n        fine to ask others to help. However, ultimately you have to review and\n        approve the PR.\n\n    -   Escalate any blocking issues without a resolution that are slowing down\n        the proposal to the other leads.\n\n    -   Evaluate whether the community has had a reasonable chance to raise\n        concerns and there is sufficient consensus to move forward given the\n        decisions on the blocking issues. This doesn't need to be perfect\n        though. Here too, we prioritize progress over perfection. We can revert\n        or fix-forward mistakes whenever necessary, especially for low-risk\n        changes. In rare cases, an extended final comment period can be used\n        when warranted for a proposal.\n\n    -   Once ready, approve and help the author merge the proposal.\n\n### When to write a proposal\n\nAny substantive change to Carbon -- whether the language, project,\ninfrastructure, or otherwise -- should be done through an evolution proposal.\nThe meaning of \"substantive\" is subjective, but will generally include:\n\n-   Any semantic or syntactic language change that isn't fixing a bug.\n-   Major changes to project infrastructure, including additions and removals.\n-   Rolling back an accepted proposal, even if never executed.\n\nChanges which generally will not require a proposal are:\n\n-   Fixing typos or bugs that don't change the meaning or intent.\n-   Rephrasing or refactoring documentation for easier reading.\n-   Minor infrastructure updates, improvements, setting changes, tweaks.\n\nIf you're not sure whether to write a proposal, please err on the side of\nwriting a proposal. A team can always ask for a change to be made directly if\nthey believe it doesn't need review. Conversely, a reviewer might also ask that\na pull request instead go through the full evolution process.\n\n### Proposal PRs\n\nA proposal PR should use the `proposal` label, have a descriptive title, and\neasily understood initial summary comment. Authors and leads are encouraged to\nedit both as necessary to ensure they give the best high-level understanding of\nthe proposal possible.\n\nA proposal PR will include a \"P-numbered\" _proposal document_,\n`proposals/pNNNN.md`, where `NNNN` is the pull request number. This file should\nbe based on the [proposal template file](/proposals/scripts/template.md).\n\nWhen writing a proposal, try to keep it brief and focused to maximize the\ncommunity's engagement in it. Beyond the above structure, try to use\n[Inverted Pyramid](<https://en.wikipedia.org/wiki/Inverted_pyramid_(journalism)>)\nor [BLUF](<https://en.wikipedia.org/wiki/BLUF_(communication)>) writing style to\nhelp readers rapidly skim the material.\n\n#### What goes in the proposal document\n\nThe purpose of the proposal document is to present the case for deciding to\nadopt the proposal. Any information that feeds into making that decision, and\nthat should not be maintained as part of our living design documentation,\nbelongs in the proposal document. This includes background material to introduce\nthe problem, comparisons to any alternative designs that were considered and any\nother current proposals in the same area, records of informal polls taken to\ndetermine community preferences, and rationale for the decision based on the\nproject's goals.\n\nThe proposal PR can contain related changes to the Carbon project, such as\nupdates to the design documentation. Those changes form part of the proposal,\nand need not be additionally described in the proposal document beyond a mention\nin the \"Proposal\" section that such changes exist. For example:\n\n```md\n## Proposal\n\nSee the proposed changes to the design documents.\n```\n\nReaders of proposals are expected to consult the PR or the git commit that\nmerged the PR in order to understand the proposed changes.\n\nThe author of a proposal is not required to include changes to the design\ndocumentation as part of a proposal, and it may in some cases be preferable to\ndecouple the proposal process from updating the design. When accepted, the\nproposal would then be implemented through a series of future PRs to the rest of\nthe project. If the proposal PR defers any documentation changes in this way,\nthe proposal document should describe what is being proposed in enough detail to\nvalidate that those future PRs properly implement the proposed direction, and\nthe proposal PR should add \"TODO\" comments in the places where significant\nfuture changes will be needed (including adding new placeholder documents if\nneeded), with links back to the proposal document. These comments should be kept\nclose to the passages that need to be changed. This is intended to ensure that\nreaders of the design documentation know when what they're reading is out of\ndate, and can easily find out what has changed. For example:\n\n```md\n> **TODO:** Document the redeclaration syntax `impl C.(as I)` adopted in\n> [p5366](/proposals/p5366.md).\n```\n\nSee the `docs/design` changes in\n[#5606: Keep design documents current](https://github.com/carbon-language/carbon-lang/pull/5606)\nfor additional examples of adding those comments. As with other parts of the\nproposal, these comments should be included in the initial PR, and updated as\nneeded during the review.\n\nAs an exception, proposals that will have a widespread, pervasive effect on the\ndesign documents (such as proposals to replace widely-used vocabulary) usually\nshouldn't make those changes as part of the proposal, so that changes during the\nreview aren't an excessive burden on the proposal author. Such proposals usually\nshouldn't apply \"TODO\" comments either, because pervasive \"TODO\" comments are\nmore likely to be disruptive than helpful to the reader. Instead, the proposal\nauthor should file a GitHub issue to track the need for documentation updates,\nand include a link to it in the proposal document, and then follow up with pull\nrequests to make the changes after the proposal is approved by the leads.\n\n#### Open questions\n\nFeel free to factor out open questions in a proposal to issues that you assign\nto the leads to resolve. You can even do this before sending the proposal for\nreview. Even after it's resolved, an open question issue can be reopened if new\ninformation comes up during the RFC.\n\nWhen opening issues, label them as\n[leads questions](https://github.com/carbon-language/carbon-lang/issues?q=is%3Aissue+is%3Aopen+label%3A%22leads+question%22).\nCarbon leads use this to locate and prioritize the issue for resolution.\n\n### Review and RFC on proposal PRs\n\nWhen a proposal PR is assigned to the\n[carbon-leads GitHub group](https://github.com/orgs/carbon-language/teams/carbon-leads),\none of them will be assigned the PR. They are responsible for helping land that\nproposal, or explaining why the project won't move forward in that direction.\nThe assigned lead is also ultimately responsible for the code review on the PR.\nProposals sent for review are also sent as an RFC to the entire community.\n\nAll active Carbon contributors are strongly encouraged to regularly skim the\ntitle and summary comment of proposals under RFC that are interesting to them.\nThey should use GitHub reactions, including at least a thumbs-up, to show their\ninterest and enthusiasm about the proposal, and help encourage the author.\nWriting proposals is _extremely hard work_, and we need to clearly show both\ninterest in the proposed direction of Carbon and appreciation for the work put\ninto the proposal. This is not about _approving_ the proposal, or any of its\ndetails. It is completely fine and coherent to both give a thumbs-up to a\nproposal _and_ provide a serious, blocking issue that needs to be resolved.\n\n_Anyone_ in the community is welcome to participate in the RFC in detail if\ninterested. However, not everyone needs to participate in every RFC. If a\nproposal is already getting actively and thoroughly reviewed, feel free to focus\nyour time on other proposals with fewer commenters. Even if there are issues or\nproblems discovered later, we can always fix them with follow-up proposals.\n\nBoth code review and high-level design comments are welcome. If an open question\ncomes up or a high-level blocking issue is uncovered, feel free to move it to\nits own GitHub issue and assign it to the leads to resolve. That issue is also a\ngood place to focus discussion on that specific topic rather than the main PR.\n\nThe assigned lead should approve proposals once the following criteria are met:\n\n-   It looks good from a code review perspective.\n\n-   At least three thumbs-up reactions showing general community interest.\n\n-   The community has had a sufficient opportunity to review the proposed\n    change, given its scope and complexity.\n\n-   Any remaining blocking issues are reasonably likely to resolve in a way that\n    allows the proposal to move forward. It is fine if some are not fully\n    decided, but a lead shouldn't approve a proposal that's unlikely to move\n    forward.\n\nThe last two criteria are fundamentally judgement calls for the lead to make,\nand we don't try to formulate a rigid or fixed bar for them. If resolving the\nblocking issues requires significant changes, the author should also get a fresh\napproval from the assigned lead after those changes, just like they would with\ncode review.\n\nThe assigned lead may also request a final comment period for the community when\napproving. This signals to the community that the proposal is likely to be\nmerged once the blocking issues are resolved, and any remaining concerns need to\nbe surfaced. The goal is to help uncover concerns that were hidden until it was\nclear that the proposal is likely to move forward. However, requesting a final\ncomment period is not the default; the assigned lead should only do this when\nthere is some reason to expect further community comment is especially important\nto solicit. Common cases to consider are contentious, complex, or dramatic\nchanges to the language or project. Ultimately, whether this is important is a\njudgement call for the lead. This will be modeled by filing a blocking issue\nthat resolves in one week when approving. This issue will also explain the\nmotivation for requesting a final comment period.\n\n### Blocking issues\n\nWe use blocking GitHub issues to track open questions or other discussions that\nthe leads are asked to resolve. Any time a blocking issue is filed, that issue\nforms both the primary discussion thread and where the leads signal how it is\nresolved. We use issues both to track that there is a specific resolution\nexpected and that there may be dependencies.\n\nWe label blocking issues as\n[leads questions](https://github.com/carbon-language/carbon-lang/issues?q=is%3Aissue+is%3Aopen+label%3A%22leads+question%22).\n\nThese issues can be created at any time and by any one. Issues can be created\nwhile the proposal is being drafted in order to help inform specific content\nthat should go into the proposal. It is even fine to create an issue first, even\nbefore a proposal exists, as an open question about whether to produce a\nparticular proposal, or what a proposal that is being planned should say. For\nissues which don't (yet) have a specific proposal PR associated with them, at\nsome point the leads may ask that a proposal be created to help collect in a\nmore cohesive place a written overview of the issue and related information, but\nthis process need not be strictly or rigidly bound to having proposal text.\n\nAvoid using issues for things that are just requests or suggestions on a\nproposal PR. If in doubt, start off with a simple comment on the PR and see if\nthere is any disagreement -- everyone may already be aligned and agree. When a\ncomment does seem worth turning into an issue, don't worry about that as the\nauthor or the commenter. Getting the leads to resolve disagreement isn't a bad\nthing for anyone involved. This should be seen as a friendly way to move the\ndiscussion out to its own forum where it'll get resolved, and focus the PR on\nimproving the proposal and getting it ready to merge.\n\nWhen an issue is created from a discussion on a PR, and after the discussion on\nthe _issue_ all the original parties come to a happy agreement, it's totally OK\nto close the issue and move back to the code review in the PR. Anyone who would\nprefer the leads to still chime in can re-open the issue and the leads will\nfollow up, even if it's only to get confirmation that everyone _did_ end up\nhappy with the resolution. At the end of the day, while it's fine to resolve an\nissue that _everyone_ actually ended up agreeing about (maybe once some\nconfusion is addressed), ultimately the leads are responsible for resolving\nthese issues and there is no pressure on anyone else to do so.\n\n#### Discussion on blocking issues\n\nDiscussion on these issues, especially contentious ones, should endeavor to\nfocus on surfacing information and highlighting the nature of the tradeoff\nimplied by the decisions available. This is in contrast to focusing on advocacy\nor persuasion. The goal of the issues shouldn't be to persuade or convince the\nleads to make a specific decision, but to give the leads the information they\nneed to make the best decision for Carbon.\n\nIt's fine that some people have a specific belief of which decision would be\nbest; however, framing their contributions to the discussion as surfacing the\ninformation that underpins that belief will make the discussion more\nconstructive, welcoming, and effective. Overall, everyone should strive to focus\non data-based arguments to the extent they can, minimizing their use of appeals\nto emotion or excessive rhetoric.\n\nNone of this should preclude gathering information like polls of opinion among\ngroups, or signaling agreement. Where community members stand and how many agree\nwith that stance on any issue _is_ information, and useful to surface.\n\n## Governance structure\n\n### Carbon leads\n\nCarbon leads are responsible for reviewing proposals and\n[setting Carbon's roadmap](roadmap_process.md) and managing evolution. This team\nshould broadly understand both the users of Carbon and the project itself in\norder to factor different needs, concerns, and pressures into a\n[consensus decision-making process](https://en.wikipedia.org/wiki/Consensus_decision-making).\n\nWhile leads may approve proposals individually, they should decide on issues\nraised to them using\n[blocking consensus](https://en.wikipedia.org/wiki/Consensus_decision-making#Blocking)\nwith a quorum of two.\n\nCarbon's current leads are:\n\n-   [chandlerc](https://github.com/chandlerc)\n-   [KateGregory](https://github.com/KateGregory)\n-   [zygoloid](https://github.com/zygoloid)\n\n#### Subteams\n\nAs Carbon grows, the leads may decide to form subteams that provide leadership\nfor specific areas. These subteams are expected to largely organize in a similar\nfashion to the Carbon leads, with a more narrow focus and scope. Subteam\ndecisions may be escalated to the Carbon leads.\n\n### Painter\n\nWhenever possible, we want Carbon to make syntax and other decisions based on\nunderstanding its users, data, and the underlying goals of the language.\nHowever, there will be times when those don't provide a clear cut rationale for\nany particular decision -- all of the options are fine/good and someone simply\nneeds to choose which color to paint the bikeshed. The goal of the painter role\nis to have a simple way to quickly decide these points.\n\nLeads and teams may defer a decision to the painter if there is a consensus that\nit is merely a bikeshed in need of paint. They may also open an issue to revisit\nthe color with data and/or user studies of some kind. This allows progress to be\nunblocked while also ensuring we return to issues later and attempt to find more\ndefinite rationale.\n\nThe painter is a single person in order to keep decisions around taste or\naesthetics reasonably consistent.\n\nThe current painter is:\n\n-   [chandlerc](https://github.com/chandlerc)\n\n### Adding and removing governance members\n\nAny member of Carbon governance may step down or be replaced when they are no\nlonger able to contribute effectively. The Carbon leads can nominate and decide\non adding, removing, or replacing members using the usual evolution processes.\n\n## Acknowledgements\n\nOur governance and evolution process is influenced by the\n[Rust](https://github.com/rust-lang/rfcs),\n[Swift](https://swift.org/contributing/), and C++ processes. Many thanks to\nthese communities for providing a basis.\n"
  },
  {
    "path": "docs/project/faq.md",
    "content": "# Project FAQ\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [What is Carbon?](#what-is-carbon)\n-   [What is Carbon's status?](#what-is-carbons-status)\n    -   [How soon can we use Carbon?](#how-soon-can-we-use-carbon)\n    -   [Why make Carbon public while it's still an experiment?](#why-make-carbon-public-while-its-still-an-experiment)\n    -   [How complete is Carbon's design?](#how-complete-is-carbons-design)\n    -   [How many people are involved in Carbon?](#how-many-people-are-involved-in-carbon)\n    -   [Is there a demo?](#is-there-a-demo)\n    -   [Where should I ask questions about Carbon Language?](#where-should-i-ask-questions-about-carbon-language)\n    -   [Why isn't there a Carbon Language logo?](#why-isnt-there-a-carbon-language-logo)\n-   [Why build Carbon?](#why-build-carbon)\n    -   [Why is performance critical?](#why-is-performance-critical)\n    -   [What level of C++ interoperability is expected?](#what-level-of-c-interoperability-is-expected)\n    -   [What would migrating C++ code to Carbon look like?](#what-would-migrating-c-code-to-carbon-look-like)\n-   [What alternatives did you consider? Why did they not work?](#what-alternatives-did-you-consider-why-did-they-not-work)\n    -   [Why not improve C++?](#why-not-improve-c)\n    -   [Why not fork C++?](#why-not-fork-c)\n    -   [Why not Rust?](#why-not-rust)\n        -   [If you can use Rust, ignore Carbon](#if-you-can-use-rust-ignore-carbon)\n        -   [Why is adopting Rust difficult for C++ codebases?](#why-is-adopting-rust-difficult-for-c-codebases)\n    -   [Why not a garbage collected language, like Java, Kotlin, or Go?](#why-not-a-garbage-collected-language-like-java-kotlin-or-go)\n-   [How were specific feature designs chosen?](#how-were-specific-feature-designs-chosen)\n    -   [Why aren't `<` and `>` used as delimiters?](#why-arent--and--used-as-delimiters)\n    -   [Why do variable declarations have to start with `var` or `let`?](#why-do-variable-declarations-have-to-start-with-var-or-let)\n    -   [Why do variable declarations have to have types?](#why-do-variable-declarations-have-to-have-types)\n-   [How will Carbon work?](#how-will-carbon-work)\n    -   [What compiler infrastructure is Carbon using?](#what-compiler-infrastructure-is-carbon-using)\n    -   [How will Carbon's bidirectional C++ interoperability work?](#how-will-carbons-bidirectional-c-interoperability-work)\n    -   [How do Carbon generics differ from templates?](#how-do-carbon-generics-differ-from-templates)\n    -   [What is Carbon's memory model?](#what-is-carbons-memory-model)\n    -   [How will Carbon achieve memory safety?](#how-will-carbon-achieve-memory-safety)\n    -   [How will language version upgrades work?](#how-will-language-version-upgrades-work)\n-   [How will the Carbon _project_ work?](#how-will-the-carbon-project-work)\n    -   [Where does development occur?](#where-does-development-occur)\n    -   [How does Carbon make decisions?](#how-does-carbon-make-decisions)\n    -   [What happens when a decision was wrong?](#what-happens-when-a-decision-was-wrong)\n    -   [What license does Carbon use?](#what-license-does-carbon-use)\n    -   [Why make Carbon open source?](#why-make-carbon-open-source)\n    -   [Why does Carbon have a CLA?](#why-does-carbon-have-a-cla)\n    -   [Who pays for Carbon's infrastructure?](#who-pays-for-carbons-infrastructure)\n-   [How can I contribute to Carbon?](#how-can-i-contribute-to-carbon)\n    -   [What are the prerequisites for contributing to Carbon Language's design and tools?](#what-are-the-prerequisites-for-contributing-to-carbon-languages-design-and-tools)\n    -   [When do we revisit decisions or reopen discussions?](#when-do-we-revisit-decisions-or-reopen-discussions)\n    -   [What can I do if I disagree with a design decision?](#what-can-i-do-if-i-disagree-with-a-design-decision)\n    -   [How can I best say \"I like X\" or \"I don't like X\"?](#how-can-i-best-say-i-like-x-or-i-dont-like-x)\n\n<!-- tocstop -->\n\n## What is Carbon?\n\nThe [Carbon Language](/README.md) is an experimental successor to C++. It is an\neffort to explore a possible future direction for the C++ language given the\n[difficulties improving C++](difficulties_improving_cpp.md).\n\n## What is Carbon's status?\n\n[Carbon is still an experiment.](/README.md#project-status) There remain\nsignificant open questions that we need to answer before the project can\nconsider becoming a production effort. For now, we're focused on exploring this\ndirection and gaining information to begin answering these questions.\n\n-   [Project status](/README.md#project-status)\n-   [Roadmap](roadmap.md)\n\n### How soon can we use Carbon?\n\nCarbon is still years away — even if the experiment succeeds, it's unlikely that\nit will be ready for serious or production use in the next few years. Everything\nhere is part of a long-term investigation.\n\n### Why make Carbon public while it's still an experiment?\n\nOne of the critical questions we need to answer as part of this experiment is\nwhether the direction we're exploring with Carbon has both broad and significant\ninterest for the industry at large. We feel like this is best answered by\ndeveloping the language openly, publicly, and with broad participation.\n\n### How complete is Carbon's design?\n\nKey design questions for the initial\n[0.1 language design](milestones.md#milestone-01-a-minimum-viable-product-mvp-for-evaluation)\nhave been resolved, and we are actively working on toolchain implementation. See\nour [roadmap](roadmap.md) for an overview of current work.\n\nReferences:\n\n-   [Carbon design overview](/docs/design/README.md)\n-   [Roadmap](roadmap.md)\n\n### How many people are involved in Carbon?\n\nPrior to going public, Carbon has had a couple dozen people involved.\n[GitHub Insights](https://github.com/carbon-language/carbon-lang/pulse/monthly)\nprovides activity metrics.\n\n### Is there a demo?\n\nYes! See the [getting started](/README.md#getting-started) tip for current\nadvice.\n\n### Where should I ask questions about Carbon Language?\n\nPlease ask questions and hold discussions either by using\n[GitHub Discussions](https://github.com/carbon-language/carbon-lang/discussions)\nor\n[#language-questions on Discord](https://discord.com/channels/655572317891461132/998959756045713438).\n\nGitHub Issues should be reserved for missing features, bugs, and anything else\nthat is fixable by way of a Pull Request.\n\n### Why isn't there a Carbon Language logo?\n\nEstablishing a Carbon Language logo isn't a priority right now. Remember that\nthis project is an _experiment_, and so we think it's best to concentrate\nefforts on ensuring that the language succeeds at its goals instead.\n\nWe have a few drafts in the works, but it requires a fair amount of work to get\nright, and getting it wrong is costly, so we won't be adding one in the near\nfuture. Don't suggest logos, because we need to be careful about how we create\none.\n\n## Why build Carbon?\n\nSee the [project README](/README.md#why-build-carbon) for an overview of the\nmotivation for Carbon. This section dives into specific questions in that space.\n\n### Why is performance critical?\n\nPerformance is critical for many users today. A few reasons are:\n\n-   **Cost savings**: Organizations with large-scale compute needs\n    [care about software performance](https://www.microsoft.com/en-us/research/publication/theres-plenty-of-room-at-the-top/)\n    because it reduces hardware needs.\n-   **Reliable latency**: Environments with specific latency needs or\n    [concerns with bounding tail latency](https://research.google/pubs/pub40801/)\n    need to be able to control and improve their latency.\n-   **Resource constraints**: Many systems have constrained CPU or memory\n    resources that require precise control over resource usage and performance.\n\n### What level of C++ interoperability is expected?\n\nCarbon code will be able to call C++, and the other way around, without\noverhead. You will be able to migrate a single library to Carbon within a C++\napplication, or write new Carbon on top of your existing C++ investment.\n\nWhile Carbon's interoperability may not cover every last case, most C++ style\nguides (such as the C++ Core Guidelines or Google C++ Style Guide) steer\ndevelopers away from complex C++ code that's more likely to cause issues, and we\nexpect the vast majority of code to interoperate well.\n\nFor example, considering a pure C++ application:\n\n<a href=\"/docs/images/snippets.md#c\">\n<!--\nEdit snippet in /docs/images/snippets.md and:\nhttps://drive.google.com/drive/folders/1QrBXiy_X74YsOueeC0IYlgyolWIhvusB\n-->\n<img src=\"/docs/images/cpp_snippet.svg\" width=\"600\"\n     alt=\"A snippet of C++ code. Follow the link to read it.\">\n</a>\n\nIt's possible to migrate a single function to Carbon:\n\n<a href=\"/docs/images/snippets.md#mixed\">\n<!--\nEdit snippet in /docs/images/snippets.md and:\nhttps://drive.google.com/drive/folders/1QrBXiy_X74YsOueeC0IYlgyolWIhvusB\n-->\n<img src=\"/docs/images/mixed_snippet.svg\" width=\"600\"\n     alt=\"A snippet of mixed Carbon and C++ code. Follow the link to read it.\">\n</a>\n\nReferences:\n\n-   [Interoperability philosophy and goals](/docs/design/interoperability/philosophy_and_goals.md)\n-   [How will Carbon's bidirectional C++ interoperability work?](#how-will-carbons-bidirectional-c-interoperability-work)\n\n### What would migrating C++ code to Carbon look like?\n\nMigration support is a\n[key long-term goal for Carbon](goals.md#interoperability-with-and-migration-from-existing-c-code).\n\nIf a migration occurs, we anticipate:\n\n-   Migration tools that automatically translate C++ libraries to Carbon at the\n    file or library level with minimal human assistance.\n-   Bidirectional C++ interoperability that allows teams to migrate libraries in\n    any order they choose without performance concerns or maintaining\n    interoperability wrappers.\n-   Test-driven verification that migrations are correct.\n\n## What alternatives did you consider? Why did they not work?\n\n### Why not improve C++?\n\nA lot of effort has been invested into improving C++, but\n[C++ is difficult to improve](difficulties_improving_cpp.md).\n\nFor example, although [P2137](https://wg21.link/p2137r0) was not accepted, it\nformed the basis for [Carbon's goals](goals.md).\n\n### Why not fork C++?\n\nWhile we would like to see C++ improve, we don't think that forking C++ is the\nright path to achieving that goal. A fork could create confusion about what code\nworks with standard C++. We believe a _successor_ programming language is a\nbetter approach because it gives more freedom for Carbon's design while\nretaining the existing C++ ecosystem investments.\n\n### Why not Rust?\n\n#### If you can use Rust, ignore Carbon\n\nIf you want to use Rust, and it is technically and economically viable for your\nproject, you should use Rust. In fact, if you can use Rust or any other\nestablished programming language, you should. Carbon is for organizations and\nprojects that heavily depend on C++; for example, projects that have a lot of\nC++ code or use many third-party C++ libraries.\n\nWe believe that Rust is an excellent choice for writing software within the pure\nRust ecosystem. Software written in Rust has properties that neither C++ nor\nCarbon have. When you need to call other languages from Rust, RPCs are a good\noption. Rust is also good for using APIs implemented in a different language\nin-process, when the cost of maintaining the FFI boundary is reasonable.\n\nWhen the foreign language API is large, constantly changes, uses advanced C++\nfeatures, or\n[makes architectural choices that are incompatible with safe Rust](#why-is-adopting-rust-difficult-for-c-codebases),\nmaintaining a C++/Rust FFI may not be economically viable today (but it is an\narea of active research: [cxx](https://crates.io/crates/cxx),\n[autocxx](https://crates.io/crates/autocxx),\n[Crubit](https://github.com/google/crubit/blob/main/docs/design/design.md)).\n\nThe Carbon community is looking for a language that existing, large, monolithic\nC++ codebases can incrementally adopt and have a prospect of migrating away from\nC++ completely. We would be very happy if Rust could be this language. However,\nwe are not certain that:\n\n-   Idiomatic, safe Rust can seamlessly integrate into an existing C++ codebase,\n    similarly to how TypeScript code can be added to a large existing JavaScript\n    codebase.\n-   Developers can incrementally migrate existing C++ code to Rust, just like\n    they can migrate JavaScript to TypeScript one file at a time, while keeping\n    the project working.\n\nSee\n[Carbon's goals](goals.md#interoperability-with-and-migration-from-existing-c-code)\nfor an in-depth discussion of Carbon's vision for C++/Carbon interop and\nmigration.\n\n#### Why is adopting Rust difficult for C++ codebases?\n\nLarge existing C++ codebases almost certainly made architectural choices that\nare incompatible with safe Rust. Specifically:\n\n-   Seamless interop where existing, unmodified **C++ APIs are made callable\n    from safe Rust** requires the C++ code to follow borrow checking rules at\n    the API boundary.\n    -   To reduce the amount of Rust-side compile-time checking that makes\n        interop difficult, C++ APIs can be exposed to Rust with pointers instead\n        of references. However, that forces users to write _unsafe_ Rust, which\n        can be even more tricky to write than C++ because it has new kinds of UB\n        compared to C++; for example,\n        [stacked borrows violations](https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md).\n-   Seamless interop where **safe Rust APIs are made callable from C++**\n    requires C++ users to follow Rust borrow checking rules.\n-   **Incremental migration of C++ to safe Rust** means that C++ code gets\n    converted to Rust without major changes to the architecture, data\n    structures, or APIs. However Rust imposes stricter rules than C++,\n    disallowing some design choices that were valid in C++. Therefore, the\n    original C++ code must follow Rust rules before attempting a conversion.\n    -   Original C++ code must be structured in such a way that the resulting\n        Rust code passes borrow checking. C++ APIs and data structures are not\n        designed with this in mind.\n    -   Migrating C++ to _unsafe_ Rust would still require the code to follow\n        Rust's\n        [reference exclusivity](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references)\n        and stacked borrows rules.\n\n### Why not a garbage collected language, like Java, Kotlin, or Go?\n\nIf you can use one of these languages, you absolutely should.\n\nGarbage collection provides dramatically simpler memory management for\ndevelopers, but at the expense of performance. The performance cost can range\nfrom direct runtime overhead to significant complexity and loss of _control_\nover performance. This trade-off makes sense for many applications, and we\nactively encourage using these languages in those cases. However, we need a\nsolution for C++ use-cases that require its full performance, low-level control,\nand access to hardware.\n\n## How were specific feature designs chosen?\n\nThroughout the design, we include 'Alternatives considered' and 'References'\nsections which can be used to research the decision process for a particular\ndesign.\n\n### Why aren't `<` and `>` used as delimiters?\n\n[One of our goals for Carbon](goals.md#fast-and-scalable-development) is that it\nshould support parsing without contextual or semantic information, and\nexperience with C++ has shown that using `<` as both a binary operator and an\nopening delimiter makes that goal difficult to achieve.\n\nFor example, in C++, the expression `a<b>(c)` could parse as either a function\ncall with a template argument `b` and an ordinary argument `c`, or as a chained\ncomparison `(a < b) > (c)`. In order to resolve the ambiguity, the compiler has\nto perform name lookup on `a` to determine whether there's a function named `a`\nin scope.\n\nIt's also worth noting that Carbon\n[doesn't use _any_ kind of brackets](/docs/design/README.md#checked-and-template-parameters)\nto mark template- or checked-generic parameters, so if Carbon had angle\nbrackets, they would mean something different than they do in C++, which could\ncause confusion. We do use square brackets to mark _deduced_ parameters, as in:\n\n```\nfn Sort[T:! Comparable](a: Vector(T)*)\n```\n\nBut deduced parameters aren't the same thing as template parameters. In\nparticular, deduced parameters are never mentioned at the callsite, so those\nsquare brackets are never part of the expression syntax.\n\nSee [Proposal #676: `:!` generic syntax](/proposals/p0676.md) for more\nbackground on how and why we chose our current compile-time parameter syntax.\n\n### Why do variable declarations have to start with `var` or `let`?\n\nIn Carbon, a declaration of a single variable looks like this:\n\n```\nvar the_answer: i32 = 42;\n```\n\nBut this is just the most common case. The syntax between `var` and `=` can be\nany [irrefutable pattern](/docs/design/README.md#patterns), not just a single\nvariable binding. For example:\n\n```\nvar ((x: i32, _: i32), y: auto) = ((1, 2), (3, 4));\n```\n\nThis code is valid, and initializes `x` to `1` and `y` to `(3, 4)`. In the\nfuture, we will probably also support destructuring structs in a similar way,\nand many other kinds of patterns are possible.\n\nNow consider how that example would look if the `var` token were not required:\n\n```\n((x: i32, _: i32), y: auto) = ((1, 2), (3, 4));\n```\n\nWith this example, the parser would need to look four tokens ahead to determine\nthat it's parsing a variable declaration rather than an expression. With more\ndeeply-nested patterns, it would have to look ahead farther. Avoiding this sort\nof unbounded lookahead is an important part of our\n[fast and scalable development](goals.md#fast-and-scalable-development) goal.\n\n### Why do variable declarations have to have types?\n\nAs discussed above, Carbon variable declarations are actually doing a form of\npattern matching. In a declaration like this:\n\n```\nvar the_answer: i32 = 42;\n```\n\n`the_answer: i32` is an example of a _binding pattern_, which matches any value\nof the appropriate type, and binds the given name to it. The `: i32` can't be\nomitted, because `the_answer` on its own is an expression, and any Carbon\nexpression is also a valid pattern, which matches if the value being matched is\nequal to the value of the expression. So `var the_answer = 42;` would try to\nmatch `42` with the value of the expression `the_answer`, which requires a\nvariable named `the_answer` to already exist.\n\nThe pattern matching proposal details alternative\n[shorthand for `auto`](/proposals/p2188.md#shorthand-for-auto) and the tradeoffs\nthat were considered.\n\nReferences:\n\n-   [Pattern matching design](/docs/design/pattern_matching.md)\n\n## How will Carbon work?\n\n### What compiler infrastructure is Carbon using?\n\nCarbon is being built using LLVM, and is expected to have Clang dependencies for\n[interoperability](#how-will-carbons-bidirectional-c-interoperability-work).\n\n### How will Carbon's bidirectional C++ interoperability work?\n\nThe Carbon toolchain will compile both Carbon and C++ code together, in order to\nmake the interoperability\n[seamless](#what-level-of-c-interoperability-is-expected).\n\nFor example, for `import Cpp library \"<vector>\"`, Carbon will:\n\n-   Call into Clang to load the AST of the `vector` header file.\n-   Analyze the AST for public APIs, which will be turned into names that can be\n    accessed from Carbon; for example, `std::vector` is `Cpp.std.vector` in\n    Carbon.\n-   Use Clang to instantiate the `Cpp.std.vector` template when parameterized\n    references occur in Carbon code.\n    -   In other words, C++ templates will be instantiated using standard C++\n        mechanisms, and the instantiated versions are called by Carbon code.\n\nSome code, such as `#define` preprocessor macros, will not work as well. C++\nallows arbitrary content in a `#define`, and that can be difficult to translate.\nAs a consequence, this is likely to be a limitation of interoperability and left\nto migration.\n\n### How do Carbon generics differ from templates?\n\nCarbon's\n[generic programming](https://en.wikipedia.org/wiki/Generic_programming) support\nwill handle both templates (matching C++) and checked generics (common in other\nlanguages: Rust, Swift, Go, Kotlin, Java, and so on).\n\nThe key difference between the two is that template arguments can only finish\ntype-checking _during_ instantiation, whereas checked generics specify an\ninterface with which arguments can finish type-checking _without_ instantiation.\nThis has a couple of important benefits:\n\n-   Type-checking errors for checked generics happen earlier, making it easier\n    for the compiler to produce helpful diagnostics.\n-   Checked-generic functions can generate less compiled output, allowing\n    compilation with many uses to be faster.\n    -   For comparison, template instantiations are a major factor for C++\n        compilation latency.\n\nAlthough Carbon will prefer checked generics over templates, templates are\nprovided for migration of C++ code.\n\nReferences:\n\n-   [Generics: Goals: Better compiler experience](/docs/design/generics/goals.md#better-compiler-experience)\n-   [Generics: Terminology: Checked versus template parameters](/docs/design/generics/terminology.md#checked-versus-template-parameters)\n\n### What is Carbon's memory model?\n\nCarbon will match C++'s memory model closely in order to maintain zero-overhead\ninteroperability. There may be some changes made as part of supporting memory\nsafety, but performance and interoperability will constrain flexibility in this\nspace.\n\n### How will Carbon achieve memory safety?\n\nSee our [safety design](/docs/design/safety).\n\n### How will language version upgrades work?\n\nCarbon will provide tooling to assist upgrades of code in response to language\nsyntax changes, similar to\n[C++ to Carbon migration tooling](#what-would-migrating-c-code-to-carbon-look-like).\nFor example, if a new keyword `except` is added in Carbon 1.1, an upgrade tool\nmight be provided that would accept Carbon 1.0 code and replace `except`\nidentifier uses with `r#except` raw identifiers\n([like Rust provides](https://doc.rust-lang.org/rust-by-example/compatibility/raw_identifiers.html)),\nautomatically fixing the conflict.\n\nWhile Carbon remains in early development, upgrade tooling is not ready. It is\ninstead a consideration for declaring Carbon\n[ready for use](#how-soon-can-we-use-carbon).\n\nThis upgrade approach stands in comparison to enforcing\n[backwards or forwards compatibility](goals.md#backwards-or-forwards-compatibility).\n\n## How will the Carbon _project_ work?\n\n### Where does development occur?\n\nCarbon is using GitHub for its repository and code reviews. Most non-review\ndiscussion occurs on our [Discord server](https://discord.gg/ZjVdShJDAs).\n\nIf you're interested in contributing, you can find more information in our\n[Contributing file](/CONTRIBUTING.md).\n\n### How does Carbon make decisions?\n\nAny interested developer may [propose and discuss changes](evolution.md) to\nCarbon. The [Carbon leads](groups.md#carbon-leads) are responsible for reviewing\nproposals and surrounding discussion, then making decisions based on the\ndiscussion. As Carbon grows, we expect to add feature teams to distribute\nresponsibility.\n\nThe intent of this setup is that Carbon remains a community-driven project,\navoiding situations where any single organization controls Carbon's direction.\n\nReferences:\n\n-   [Contributing](/CONTRIBUTING.md)\n-   [Evolution process](evolution.md)\n\n### What happens when a decision was wrong?\n\nCarbon's [evolution process](evolution.md) is iterative: when we make poor\ndecisions, we'll work to fix them. If we realize a mistake quickly, it may make\nsense to just roll back the decision. Otherwise, a fix will need to follow the\nnormal evolution process, with a proposal explaining why the decision was wrong\nand proposing a better path forward.\n\n### What license does Carbon use?\n\nCarbon is under the [Apache License v2.0 with LLVM Exceptions](/LICENSE). We\nwant Carbon to be available under a permissive open source license. As a\nprogramming language with compiler and runtime library considerations, our\nproject has the same core needs as the LLVM project for its license and we build\non their work to address these by combining the\n[Apache License](https://spdx.org/licenses/Apache-2.0.html) with the\n[LLVM Exceptions](https://spdx.org/licenses/LLVM-exception.html).\n\n### Why make Carbon open source?\n\nWe believe it is important for a programming language like Carbon, if it is\nsuccessful, to be developed by and for a broad community. We feel that the open\nsource model is the most effective and successful approach for doing this. We're\nclosely modeled on LLVM and other similar open source projects, and want to\nfollow their good examples. We've structured the project to be attractive for\nindustry players big and small to participate in, but also to be resilient and\nindependent long-term.\n\nThe open source model, particularly as followed by Apache and LLVM, also\nprovides a strong foundation for handling hard problems like intellectual\nproperty and licensing with a broad and diverse group of contributors.\n\n### Why does Carbon have a CLA?\n\nCarbon [uses a CLA](/CONTRIBUTING.md#contributor-license-agreements-clas)\n(Contributor License Agreement) in case we need to fix issues with the license\nstructure in the future, something which has proven to be important in other\nprojects.\n\nAny changes to the license of Carbon would be made very carefully and subject to\nthe exact same decision making process as any other change to the overall\nproject direction.\n\nInitially, Carbon is bootstrapping using Google's CLA. We are planning to create\nan open source foundation and transfer all Carbon-related rights to it; our goal\nis for the foundation setup to be similar to other open source projects, such as\nLLVM or Kubernetes.\n\n### Who pays for Carbon's infrastructure?\n\nCarbon is currently bootstrapping infrastructure with the help of Google. As\nsoon as a foundation is ready to oversee infrastructure, such as\n[continuous integration](https://en.wikipedia.org/wiki/Continuous_integration)\nand the CLA, we plan to transfer them so they are run by the community.\n\n## How can I contribute to Carbon?\n\nThere are many ways to contribute, and we appreciate all of them. Begin by\nreading the project's [Contributing](/CONTRIBUTING.md) page to learn more about\nhow you can contribute.\n\n### What are the prerequisites for contributing to Carbon Language's design and tools?\n\n**[Carbon Language isn't ready for use](#how-soon-can-we-use-carbon). This\nsection is for people wishing to participate in designing and implementing the\nlanguage.**\n\nCarbon is being designed to migrate C++ codebases and to look familiar to C++\nprogrammers. As such, familiarity with C++ is very important. Carbon is also\ntrying to learn from other programming languages, so having broad experience\nwith other programming languages will be helpful to see tradeoffs in design\ndecisions.\n\nThe Carbon toolchain is being implemented in C++, and we also use Python and\nStarlark. As we're building off of the LLVM project, familiarity with Clang and\nother parts of LLVM will be advantageous, but not required.\n\nOur [contribution tools](contribution_tools.md) page documents specific tools we\nuse when building.\n\n### When do we revisit decisions or reopen discussions?\n\nOnce a decision is made through the [evolution process](evolution.md) the\ncommunity should treat it as _firmly_ decided. This doesn't mean that the\ndecision is _definitely_ right or set in stone, it just means we'd like the\ncommunity to focus time and energy on other issues in the name of progress.\n\nSometimes, it will be appropriate to revisit a decision; for example, when there\nis new information introduced, a new community joins Carbon, or there is an\norder of magnitude growth in the community. These cases are handled as new\nproposals through the [evolution process](evolution.md).\n\nFor example, we have done this with digit separators: we missed important\n_domain_ conventions and had overly restricted where separators are allowed,\n[an issue was filed with the new information](https://github.com/carbon-language/carbon-lang/issues/1485),\nand we're fixing the choice.\n\nSee also the related questions\n[What happens when a decision was wrong?](#what-happens-when-a-decision-was-wrong),\n[How does Carbon make decisions?](#how-does-carbon-make-decisions), and\n[What can I do if I disagree with a design decision?](#what-can-i-do-if-i-disagree-with-a-design-decision).\n\n### What can I do if I disagree with a design decision?\n\nWe invite you to give us constructive feedback. Some of Carbon's design\ndecisions are made with the _expectation_ of receiving community feedback. We\nunderstand that many decisions won't be universally popular, but we'd still like\nto understand the community's reaction to Carbon.\n\nWe encourage you to investigate why Carbon came to be the way it is. Designs\nwill include links to the proposals and important alternatives considered that\nled to them, typically linked at the bottom. Read through and understand the\ncontext and rationale behind the decisions you are concerned about. You may find\nthat your concerns were already thoroughly discussed. If not, you will be in a\nbetter place to present your thoughts in a convincing way.\n\nChanging decisions that have come out of the [evolution process](evolution.md)\ninvolves a formal process. See\n[When do we revisit decisions or reopen discussions?](#when-do-we-revisit-decisions-or-reopen-discussions).\nFor these issues in particular, please be aware that other community members may\nchoose to not actively engage in detailed discussions, especially if the\ndiscussion seems to be revisiting points made in the past.\n\nIf after reading this answer you are not sure how to proceed please feel free to\nask (see\n[Where should I ask questions?](#where-should-i-ask-questions-about-carbon-language)).\n\n### How can I best say \"I like X\" or \"I don't like X\"?\n\nBoth Discord and GitHub Discussions allow you to give an emoji \"reaction\" to\nindividual posts. If you'd like to amplify what has already been said, please\nuse these instead of posting messages that re-state substantially the same\nthing. These make conversations easier to follow and understand general\nsentiment in discussions involving many people.\n"
  },
  {
    "path": "docs/project/goals.md",
    "content": "# Goals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Project goals](#project-goals)\n    -   [Community and culture](#community-and-culture)\n    -   [Language tools and ecosystem](#language-tools-and-ecosystem)\n-   [Language goals and priorities](#language-goals-and-priorities)\n    -   [Performance-critical software](#performance-critical-software)\n    -   [Software and language evolution](#software-and-language-evolution)\n    -   [Code that is easy to read, understand, and write](#code-that-is-easy-to-read-understand-and-write)\n    -   [Practical safety and testing mechanisms](#practical-safety-and-testing-mechanisms)\n    -   [Fast and scalable development](#fast-and-scalable-development)\n    -   [Modern OS platforms, hardware architectures, and environments](#modern-os-platforms-hardware-architectures-and-environments)\n    -   [Interoperability with and migration from existing C++ code](#interoperability-with-and-migration-from-existing-c-code)\n-   [Non-goals](#non-goals)\n    -   [Stable language and library ABI](#stable-language-and-library-abi)\n    -   [Backwards or forwards compatibility](#backwards-or-forwards-compatibility)\n    -   [Legacy compiled libraries without source code or ability to rebuild](#legacy-compiled-libraries-without-source-code-or-ability-to-rebuild)\n    -   [Support for existing compilation and linking models](#support-for-existing-compilation-and-linking-models)\n    -   [Idiomatic migration of non-modern, non-idiomatic C++ code](#idiomatic-migration-of-non-modern-non-idiomatic-c-code)\n-   [Prioritization beyond goals](#prioritization-beyond-goals)\n-   [Acknowledgements](#acknowledgements)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon is an experiment to explore a possible, distant future for the C++\nprogramming language designed around a specific set of goals, priorities, and\nuse cases.\n\nA programming language is a tool, and different tools are good for different\npurposes. We think there is great value in priorities that differentiate Carbon\nfrom other programming languages. Stating Carbon’s priorities clearly and\nexplicitly shapes the design of Carbon, and helps the entire community\neffectively evaluate and use the language.\n\nCarbon's language goals have historically been best addressed by C++, and there\nare large ecosystems and codebases written using C++ to these ends. Carbon\nshould be attractive and easy for C++ developers to try out and incrementally\nadopt, even in individual libraries both using and used from C++ code. We expect\nthis depends on having high-performance bidirectional interoperability with C++,\nexcellent migration tooling, and an easy ramp-up for experienced C++ software\ndevelopers.\n\n[Principles](principles/README.md) are provided to clarify these goals.\nPrinciples do not supersede goals and priorities.\n\n## Project goals\n\n### Community and culture\n\nCarbon has an overarching goal of promoting a healthy and vibrant community with\nan inclusive, welcoming, and pragmatic culture. While this may not directly\naffect Carbon's design, it affects how Carbon's design occurs. We cannot build a\ngood language without a good community. As the saying goes,\n[\"culture eats strategy for breakfast\"](https://techcrunch.com/2014/04/12/culture-eats-strategy-for-breakfast/).\nCarbon's community, including both maintainers and users, needs to last for\nyears and be capable of scaling up. It needs to support people working on Carbon\nacross a wide range of companies as their full time job, but also people\ncontributing in small fractions of their time, or as students, teachers, or as a\nhobby. There are several key ingredients to achieving this.\n\n**The community and project needs a code of conduct.** We want Carbon's\ncommunity to be welcoming and respectful, with a deep commitment to\npsychological safety. We need consistent expectations for how every community\nmember should behave, regardless of their position in the community. These\nexpectations around conduct and behavior need to be clearly articulated both to\nset expectations for people joining, and to help remind and anchor us on\nconsistent standards. It is also important that we hold ourselves accountable to\nthese expectations and have real and meaningful mechanisms to moderate the\ncommunity. When behavior steps outside of our expectations, we need tools,\nprocesses, and policies for how we will recognize and correct it.\n\n**An open, inclusive process for Carbon changes.** The community needs to be\nable to effectively engage in the direction and evolution of the project and\nlanguage, while keeping the process efficient and effective. That means we need\nan open, inclusive process where everyone feels comfortable participating.\nCommunity members should understand how and why decisions are made, and have the\nability to both influence them before they occur and give feedback afterward. We\nwant to use this process to also ensure we stick to our language priorities and\nhave clear rationales for all of our technical designs and decisions.\n\n**Being inclusive is different from including everyone.** We want to avoid\nexcluding or marginalizing members of the community. However, we expect to\ninevitably make choices that benefit some Carbon community members more than\nothers. We will provide justification for these decisions, but achieving\nCarbon's goals -- including that of a healthy community -- will be the guiding\nrule.\n\n### Language tools and ecosystem\n\nProgramming languages do not succeed in a vacuum. The Carbon project cannot\nmerely _design_ a language in order to succeed, it must tackle the full\necosystem of tooling that makes developers effective using the language. This\nincludes not only a compiler and standard library, but also a broad range of\nother tools that enable developers to be more effective, efficient, or\nproductive.\n\n**We will provide a reference implementation.** This helps the language have a\nstrong and consistent experience for developers and a clear onboarding process.\nIt also enables us to carefully consider implementation considerations\nthroughout the design of the language. However, we do _not_ want this to be seen\nas a replacement for a formal specification at any point.\n\n**Carbon will have a formal specification.** Fully specifying the language\nenables other implementations and allows us to clearly document the expected\nbehavior of the reference implementation. This does not mean the specification\ndefines what is \"correct\"; instead, the specification and reference\nimplementation should complement each other. Any divergence is a bug that _must_\nbe resolved, and the specification and reference should always converge. Carbon\nshould not have designs or specifications which do not match the practical\nimplementation, even if that means updating designs to reflect implementation\nrealities. Having the specification will enable better analysis of the language\nas a whole and the production of other partial or full implementations which\nmatch the behavior of the reference implementation.\n\n**Approachable, developer-facing documentation.** Developers shouldn't be\nexpected to read through the specification to ramp up with Carbon. User guides\nand other documentation will be provided to make it easy to learn how to use\nCarbon.\n\n**Compelling adoption tooling.** We want to provide a compelling suite of tools\nout-of-the-box in order to encourage adoption of Carbon at scale where it can\naugment existing C++ codebases. For example, we expect a C++ -> Carbon code\ntranslator will be important.\n\n**Tooling for updating code when Carbon evolves.** As Carbon evolves over time,\nwe expect to provide tooling to help automate and scale migrating existing\nCarbon code to the new version. The goal is to enable more rapid evolution of\nthe language without the churn tax and version skew becoming unsustainable.\n\n**Developer tooling.** We need developers to be productive while reading and\nwriting Carbon code. We expect to provide a broad suite of development oriented\ntools ranging from formatting and refactoring tools to\n[LSP](https://langserver.org/) implementations and editor integrations. We also\nplan to provide machine readable forms of many parts of the language, such as a\ngrammar, to ensure consistency between tools and enable the development of tools\nby others.\n\n**Infrastructure to enable package management and other library ecosystem\nsupport.** The goal is to support what the ecosystem needs, regardless of the\nexact form this ends up taking.\n\n## Language goals and priorities\n\nWe are designing Carbon to support:\n\n-   Performance-critical software\n-   Software and language evolution\n-   Code that is easy to read, understand, and write\n-   Practical safety and testing mechanisms\n-   Fast and scalable development\n-   Modern OS platforms, hardware architectures, and environments\n-   Interoperability with and migration from existing C++ code\n\nMany languages share subsets of these goals, but what distinguishes Carbon is\ntheir combination. Where it is necessary to make tradeoffs between these goals,\nwe intend to prioritize them in this order.\n\nEach goal is broad, and has several facets to consider when making decisions.\nBelow, we discuss all of these goals in more detail to give a deeper\nunderstanding of both the nature and motivation of these goals.\n\n### Performance-critical software\n\nAll software consumes resources: time, memory, compute, power, binary size, and\nso on. In many cases, raw resource usage is not the biggest concern. Instead,\nalgorithmic efficiency or business logic dominates these concerns. However,\nthere exists software where its rate of resource consumption -- its performance\n-- is critical to its successful operation. Another way to think about when\nperformance is critical: would a performance regression be considered a bug?\nWould it even be noticed?\n\nOur goal is to support software where its performance with respect to some set\nof resource constraints is critical to its successful operation. This\noverarching goal can be decomposed into a few specific aspects.\n\n**Provide the developer control over every aspect of performance.** When faced\nwith some performance problem, the developer should always have tools within\nCarbon to address it. This does not mean that the developer is necessarily\nconcerned with ultimate performance at every moment, but in the most constrained\nscenarios they must be able to \"open up the hood\" without switching to another\nlanguage.\n\n**Idiomatic code should be fast.** Developers should not regularly be required\nto choose between performance and readability. Although performance tuning may\nin rare cases require complex or surprising code, Carbon's design should ensure\nregular, idiomatic code usually results in high performance.\n\n**Code should perform predictably.** The reader and writer of code should be\nable to easily understand its expected performance, given sufficient background\nknowledge of the environment in which it will run. This need not be precise, but\ninstead can use heuristics and guidelines to avoid surprise. The key priority is\nthat performance, whether good or bad, is unsurprising to developers. Even\npleasant surprises, when too frequent, can become a problem due to establishing\nbrittle baseline performance that cannot be reliably sustained.\n\n**No need for a lower level language.** Developers should not need to leave the\nrules and structure of Carbon, whether to gain control over performance problems\nor to gain access to hardware facilities.\n\n### Software and language evolution\n\nTitus Winters writes in \"Non-Atomic Refactoring and Software Sustainability\":\n\n> What is the difference between programming and software engineering? These are\n> nebulous concepts and thus there are many possible answers, but my favorite\n> definition is this: Software engineering is programming integrated over time.\n> All of the hard parts of engineering come from dealing with time:\n> compatibility over time, dealing with changes to underlying infrastructure and\n> dependencies, and working with legacy code or data. Fundamentally, it is a\n> different task to produce a programming solution to a problem (that solves the\n> current [instance] of the problem) versus an engineering solution (that solves\n> current instances, future instances that we can predict, and - through\n> flexibility - allows updates to solve future instances we may not be able to\n> predict).\n\nCarbon will prioritize being a \"software engineering\" language, in the above\nsense. We specifically are interested in dealing with the time-oriented aspects\nof software built in this language. We need to be prepared for substantive\nchanges in priority over the next decade, on par with the changes experienced in\nthe 2010s: 10x scaling of software organizations, mobile, cloud, diversification\nof platforms and architectures, and so on.\n\n**Support maintaining and evolving software written in Carbon for decades.** The\nlife expectancy of some software will be long and the software will not be\nstatic or unchanging in that time. Mistakes will be made and need to be\ncorrected. New functionality will be introduced and old functionality retired\nand removed. The design of Carbon must support and ease every step of this\nprocess. This ranges from emphasizing testing and continuous integration to\ntooling and the ability to make non-atomic changes. It also includes constraints\non the design of Carbon itself: we should avoid, or at least minimize, language\nfeatures that encourage unchangeable constructs. For example, any feature with a\ncontract that cannot be strengthened or weakened without breaking the expected\nusage patterns is inherently hostile to refactoring. Analogously, features or\nconventions that require simultaneously updating all users of an API when\nextending it are inherently hostile towards long-term maintenance of software.\n\n**Support maintaining and evolving the language itself for decades.** We will\nnot get the design of most language features correct on our first, second, or\n73rd try. As a consequence, there must be a built-in plan and ability to move\nCarbon forward at a reasonable pace and with a reasonable cost. Simultaneously,\nan evolving language must not leave software behind to languish, but bring\nsoftware forward. This requirement should not imply compatibility, but instead\nsome migratability, likely tool-assisted.\n\n**Be mindful of legacy.** Globally, there may be as many as 50 billion lines of\nC++ code. Any evolution of Carbon that fails to account for human\ninvestment/training and legacy code, representing significant capital, is doomed\nfrom the start. Note that our priority is restricted to legacy source code; we\ndo not prioritize full support of legacy object code. While that still leaves\nmany options open, such as dedicated and potentially slower features, it does\nlimit the degree to which legacy use cases beyond source code should shape the\nCarbon design.\n\n### Code that is easy to read, understand, and write\n\nWhile this is perhaps the least unique among programming languages of the goals\nwe list here, we feel it is important to state it, explain all of what we mean\nby it, and fit it into our prioritization scheme.\n\nSoftware has inherent complexity that burdens developers, especially at scale\nand over time. Carbon will strive to minimize that burden for reading,\nunderstanding, and writing code. The behavior of code should be easily\nunderstood, especially by those unfamiliar with the software system. Consider\ndevelopers attempting to diagnose a serious outage under time pressure -- every\nsecond spent trying to understand the _language_ is one not spent understanding\nthe _problem_.\n\nWhile the source code of our software may be read far more often by machines,\nhumans are the most expensive readers and writers of software. As a consequence,\nwe need to optimize for human reading, understanding, and writing of software,\nin that order.\n\n**Excellent ergonomics.** Human capabilities and limitations in the domains of\nperception, memory, reasoning, and decision-making affect interactions between\nhumans and systems. Ergonomic language design takes human factors into account\nto increase productivity and comfort, and reduce errors and fatigue, making\nCarbon more suitable for humans to use. We can also say that ergonomic designs\nare accessible to humans. \"Readability\" is a related, but a more focused\nconcept, connected to only the process of reading code. \"Ergonomics\" covers all\nactivities where humans interact with Carbon: reading, writing, designing,\ndiscussing, reviewing, and refactoring code, as well as learning and teaching\nCarbon. A few examples:\n\n-   Carbon should not use symbols that are difficult to type, see, or\n    differentiate from similar symbols in commonly used contexts.\n-   Syntax should be easily parsed and scanned by any human in any development\n    environment, not just a machine or a human aided by semantic hints from an\n    IDE.\n-   Code with similar behavior should use similar syntax, and code with\n    different behavior should use different syntax. Behavior in this context\n    should include both the functionality and performance of the code. This is\n    part of conceptual integrity.\n-   Explicitness must be balanced against conciseness, as verbosity and ceremony\n    add cognitive overhead for the reader, while explicitness reduces the amount\n    of outside context the reader must have or assume.\n-   Common yet complex tasks, such as parallel code, should be well-supported in\n    ways that are easy to reason about.\n-   Ordinary tasks should not require extraordinary care, because humans cannot\n    consistently avoid making mistakes for an extended amount of time.\n\n**Support tooling at every layer of the development experience, including\nIDEs.** The design and implementation of Carbon should make it easy to create\nsuch tools and make them effective. Carbon should avoid syntax and textual\nstructures that are difficult to recognize and mechanically change without\nlosing meaning.\n\n**Support software outside of the primary use cases well.** There are\nsurprisingly high costs for developers to switch languages. Even when the\nprimary goal is to support performance-critical software, other kinds of\nsoftware should not be penalized unnecessarily.\n\n> \"The right tool for the job is often the tool you are already using -- adding\n> new tools has a higher cost than many people appreciate.\"\n>\n> -- [John Carmack](https://twitter.com/id_aa_carmack/status/989951283900514304)\n\n**Focus on encouraging appropriate usage of features rather than restricting\nmisuse.** Adding arbitrary restrictions to prevent misuse of otherwise general\nfeatures of the language can create problems when they end up interfering with\nunexpected or rare but still appropriate usages. Instead, Carbon should focus on\nenabling appropriate and effective usage of features, and creating incentives\naround those. What seems initially like a \"misuse\" of a feature may be critical\nfor some rare or future use case. Put differently, we will not always be able to\nprevent developers from misusing features or writing unnecessarily complex code,\nand that is okay. We should instead focus on helping reduce the rate that this\noccurs accidentally, and enabling tooling and diagnostics that warn about\ndangerous or surprising patterns.\n\n**The behavior and semantics of code should be clearly and simply specified\nwhenever possible.** Leaving behavior undefined for some cases of invalid,\nbuggy, or non-portable code may be necessary, but it comes at a very high cost\nand should be avoided. Every case where behavior is left undefined should be\nclearly spelled out with a strong rationale for this tradeoff. The code patterns\nwithout defined behavior should be teachable and understandable by developers.\nFinally, there must be mechanisms available to detect undefined behavior, at\nbest statically, and at worst dynamically with high probability and at minimal\ncost.\n\n**Adhere to the principle of least surprise.** Defaults should match typical\nusage patterns. Implicit features should be unsurprising and expected, while\nexplicit syntax should inform the reader about any behavior which might\notherwise be surprising. The core concepts of implicit versus explicit syntax\nare well articulated in\n[the Rust community](https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html#implicit-vs-explicit),\nalthough we may come to different conclusions regarding the principles.\n\n**Design features to be simple to implement.** Syntax, structure, and language\nfeatures should be chosen while keeping the implementation complexity\nmanageable. Simplicity of implementation reduces bugs, and will in most cases\nmake the features easier to understand. It's also often the best way to ensure\npredictable performance, although supporting peak performance may require\noptions for more complex implementation behavior.\n\n### Practical safety and testing mechanisms\n\nOur goal is to add as much language-level safety and security to Carbon as\npossible, using a hybrid strategy to balance other goals. We will do as many\nsafety checks as we can at compile time. We will also provide dynamic runtime\nchecking and a strong testing methodology ranging from unit tests through\nintegration and system tests all the way to coverage-directed fuzz testing. We\nhave specific criteria that are important for this strategy to be successful:\n\n**Make unsafe or risky aspects of Carbon code explicit and syntactically\nvisible.** This will allow the software to use the precise flexibility needed\nand to minimize its exposure, while still aiding the reader. It can also help\nthe reader more by indicating the specific nature of risk faced by a given\nconstruct. More simply, safe things shouldn't look like unsafe things and unsafe\nthings should be easily recognized when reading code.\n\n**Common patterns of unsafe or risky code must support static checking.**\nWaiting until a dynamic check is too late to prevent the most common errors. A\ncanonical example here are\n[thread-safety annotations](https://clang.llvm.org/docs/ThreadSafetyAnalysis.html)\nfor basic mutex lock management to allow static checking. This handles the\ncommon patterns, and we use dynamic checks, such as TSan and deadlock detection,\nto handle edge cases.\n\n**All unsafe or risky operations and interfaces must support some dynamic\nchecking.** Developers need some way to test and verify that their code using\nany such interface is in fact correct. Uncheckable unsafety removes any ability\nfor the developer to gain confidence. This means we need to design features with\nunsafe or risky aspects with dynamic checking in mind. A concrete example of\nthis can be seen in facilities that allow indexing into an array: such\nfacilities should be designed to have the bounds of the array available to\nimplement bounds checking when desirable.\n\n### Fast and scalable development\n\nSoftware development iteration has a critical \"edit, test, debug\" cycle.\nDevelopers will use IDEs, editors, compilers, and other tools that need\ndifferent levels of parsing. For small projects, raw parsing speed is essential;\nfor large software systems, scalability of parsing is also necessary.\n\n**Syntax should parse with bounded, small look-ahead.** Syntax that requires\nunbounded look-ahead or fully general backtracking adds significant complexity\nto parsing and makes it harder to provide high quality error messages. The\nresult is both slower iteration and more iterations, a multiplicative negative\nimpact on productivity. Humans aren't immune either; they can be confused by\nconstructs that appear to mean one thing but actually mean another. Instead, we\nshould design for syntax that is fast to parse, with easy and reliable error\nmessages.\n\n**No semantic or contextual information used when parsing.** The more context,\nand especially the more _semantic_ context, required for merely parsing code,\nthe fewer options available to improve the performance of tools and compilation.\nCross-file context has an especially damaging effect on the potential\ndistributed build graph options. Without these options, we will again be unable\nto provide fast developer iteration as the codebase scales up.\n\n**Support separate compilation, including parallel and distributed strategies.**\nIteration requires frequent rebuilds of software as part of the edit/test/debug\ncycle of development. The language design should enable low-latency build\nstrategies, particularly when relatively little has changed. This minimally\nrequires separate compilation of source files, and potentially other incremental\nbuild strategies. Separate compilation also enables better scalability options\nfor build systems of large software.\n\n### Modern OS platforms, hardware architectures, and environments\n\nCarbon must have strong support for all of the major, modern OS platforms, the\nhardware architectures they run on, and the environments in which their software\nruns. Carbon must also continue supporting these over time, even as which ones\nare major or modern evolve and change.\n\n**Provide _native_ support for the programming models of those platforms and\nenvironments.** This goes beyond enabling compile-time translations from one\nabstraction to several implementations. While enabling high-level\nsynchronization primitives like mutexes and futures is good, the underlying\natomic operations provided by the hardware must also be directly available.\nSimilarly, lowering parallel constructs into a specific implementation, such as\nSIMD or SPMD, is good but insufficient. Multiple parallel implementations must\nbe directly addressable in Carbon. The need for native support repeats across\nthe landscape of OS platform, hardware, and environment distinctions; for\nexample, concurrency versus parallelism, and desktop versus mobile.\n\n**Conversely, Carbon cannot prioritize support for historical platforms.** To\nuse a hockey metaphor, we should not skate to where the puck is, much less where\nthe puck was twenty years ago. We have existing systems to support those\nplatforms where necessary. Instead, Carbon should be forward-leaning in its\nplatform support. As these platforms evolve over time, Carbon will have to\nevolve as well to continue to effectively prioritize the modern and major\nplatforms.\n\nFor examples, please see Carbon's\n[success criteria](principles/success_criteria.md#modern-os-platforms-hardware-architectures-and-environments).\n\n### Interoperability with and migration from existing C++ code\n\nWe want developers working within existing C++ ecosystems to easily start using\nCarbon, without starting from scratch. Adopting Carbon should not require\ncomplete rewrites, new programming models, or building an entire new\nstack/ecosystem. This means integrating into the existing C++ ecosystem by\nsupporting incremental migration from C++ to Carbon, which in turn requires\nhigh-quality interoperability with existing C++ code.\n\nWe must be able to move existing _large_ C++ codebases -- some with hundreds of\nmillions of lines of code and tens of thousands of active developers -- onto\nCarbon. C++ developers must also successfully switch to Carbon development. Any\nmigration of this scale will take years, will need to be incremental, and some\nlibraries -- particularly third-party -- may remain in C and C++. It must be\npossible to migrate a C++ library to Carbon without simultaneously migrating all\nof the libraries it depends on or all of the libraries that depend on it.\n\nWe believe incremental migrations require:\n\n**Familiarity for experienced C++ developers with a gentle learning curve.** We\nneed a feasible plan for retraining a C++ workforce to become proficient in\nCarbon. If long and significant study is required to be minimally proficient,\nmeaning able to read, superficially understand, and do limited debugging or\nmodifications, then the inertia of C++ will inevitably win. Further, we need a\ngentle and easily traversed learning curve to basic productivity in order for\nthe transition to not become a chore or otherwise unsustainable for teams and\nindividuals.\n\n**Expressivity comparable to C++.** If an algorithm or data structure or system\narchitecture can naturally be written in C++, it should also be possible to\nwrite it naturally in Carbon.\n\n**Automated source-to-source migration of large segments of large-scale\nidiomatic C++ code bases with high fidelity.** We will prioritize having very\n[low human interaction](principles/success_criteria.md#migration-tooling) to\nachieve high fidelity migration results. We do not require all C++ code to be\nmigratable in this fashion, and the resulting Carbon may be non-idiomatic. We\ncan add reasonable constraints here if those constraints are already well\nestablished best practices for C++ development, including design patterns,\ntesting coverage, or usage of sanitizers. Over many years, as Carbon evolves and\ncodebases have had time to migrate, the results of the tooling may also drift\nfurther from idiomatic Carbon and have less desirable results.\n\n**Support for bi-directional interoperability with existing C++ code.** We need\nCarbon code to be able to call into C and C++ libraries with both reasonable API\nclarity and high performance. We will also need some ability to implement C++\ninterfaces with business logic in Carbon, although this direction can tolerate\nslightly more constraints both in supported features and performance overhead.\nIn all cases, the particular performance overhead imposed by moving between C++\nand Carbon will need to be easily exposed and understood by developers. While a\ngiven piece of code only needs to be migrated once, we expect interoperability\nto be invoked continuously to support migrated code and will thus remain\nimportant for most developers.\n\n## Non-goals\n\nThere are common or expected goals of many programming languages that we\nexplicitly call out as non-goals for Carbon. That doesn't make these things bad\nin any way, but reflects the fact that they do not provide meaningful value to\nus and come with serious costs and/or risks.\n\n### Stable language and library ABI\n\nWe would prefer to provide better, dedicated mechanisms to decompose software\nsubsystems in ways that scale over time rather than providing a stable ABI\nacross the Carbon language and libraries. Our experience is that providing broad\nABI-level stability for high-level constructs is a significant and permanent\nburden on their design. It becomes an impediment to evolution, which is one of\nour stated goals.\n\nThis doesn't preclude having low-level language features or tools to create\nspecific and curated stable ABIs, or even serializable protocols. Using any such\nfacilities will also cause developers to explicitly state where they are relying\non ABI and isolating it in source from code which does not need that stability.\nHowever, these facilities would only expose a restricted set of language\nfeatures to avoid coupling the high-level language to particular stabilized\ninterfaces. There is a wide range of such facilities that should be explored,\nfrom serialization-based systems like\n[protobufs](https://developers.google.com/protocol-buffers) or\n[pickling in Python](https://docs.python.org/3/library/pickle.html), to other\napproaches like\n[COM](https://docs.microsoft.com/en-us/windows/win32/com/com-objects-and-interfaces)\nor Swift's [\"resilience\"](https://swift.org/blog/library-evolution/) model. The\nspecific approach should be designed around the goals outlined above in order to\nfit the Carbon language.\n\n### Backwards or forwards compatibility\n\nOur goals are focused on _migration_ from one version of Carbon to the next\nrather than _compatibility_ between them. This is rooted in our experience with\nevolving software over time more generally and a\n[live-at-head model](https://abseil.io/blog/20171004-cppcon-plenary). Any\ntransition, whether based on backward compatibility or a migration plan, will\nrequire some manual intervention despite our best efforts, due to\n[Hyrum's Law](http://www.hyrumslaw.com), and so we should acknowledge that\nupgrades require active migrations.\n\n### Legacy compiled libraries without source code or ability to rebuild\n\nWe consider it a non-goal to support legacy code for which the source code is no\nlonger available, though we do sympathize with such use cases and would like the\ntooling mentioned above to allow easier bridging between ABIs in these cases.\nSimilarly, plugin ABIs aren’t our particular concern, yet we’re interested in\nseeing tooling which can help bridge between programs and plugins which use\ndifferent ABIs.\n\n### Support for existing compilation and linking models\n\nWhile it is essential to have interoperability with C++, we are willing to\nchange the compilation and linking model of C++ itself to enable this if\nnecessary. Compilation models and linking models should be designed to suit the\nneeds of Carbon and its use cases, tools, and environments, not what happens to\nhave been implemented thus far in compilers and linkers.\n\nAs a concrete example, Carbon will not support platforms that cannot update\ntheir compiler and linker alongside the language.\n\n### Idiomatic migration of non-modern, non-idiomatic C++ code\n\nWhile large-scale, tool-assisted migration of C++ code to Carbon is an explicit\ngoal, handling all C++ code with this is expressly not a goal. There is likely a\ngreat deal of C++ code that works merely by chance or has serious flaws that\nprevent us from understanding the developer's intent. While we may be able to\nprovide a minimally \"correct\" migration to very unfriendly code, mechanically\nreproducing exact C++ semantics even if bizarre, even this is not guaranteed and\nimproving on it is not a goal. Migration support will prioritize code that\nadheres to reasonable C++ best practices, such as avoiding undefined behavior,\nmaintaining good test coverage, and validating tests with sanitizers.\n\n## Prioritization beyond goals\n\nThe features, tools, and other efforts of Carbon should be prioritized based on\na clearly articulated rationale. This may be based on this document's\noverarching goals and priorities, or if those don't offer enough clarity, we\nwill fall back on rationale such as a required implementation order or a\ncost-benefit analysis.\n\n**Cost-benefit will drive many choices.** We expect to measure both cost,\nincluding complexity, and benefit using the impact on the project and language\nas a whole. Benefit accumulates over time, which means providing incremental\nsolutions earlier will typically increase the total benefit. It is also\nreasonable for the rationale of a decision to factor in both effort already\ninvested, and effort ready to commit to the feature. This should not overwhelm\nany fundamental cost-benefit analysis. However, given two equally impactful\nfeatures, we should focus on the solution that is moving the fastest.\n\n**Domain-motivated libraries and features are an example.** For these, the cost\nfunction will typically be the effort required to specify and implement the\nfeature. The benefit will stem from the number of users and how much utility the\nfeature provides. We don't expect to have concrete numbers for these, but we\nexpect prioritization decisions between features to be expressed using this\nframework.\n\n## Acknowledgements\n\nCarbon's goals are heavily based on\n[\"Goals and priorities for C++\"](https://wg21.link/p2137). Many thanks to the\nauthors and contributors for helping us formulate our goals and priorities.\n"
  },
  {
    "path": "docs/project/groups.md",
    "content": "# Groups\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n    -   [Linked entities](#linked-entities)\n-   [Carbon leads](#carbon-leads)\n-   [Conduct team](#conduct-team)\n    -   [Moderators](#moderators)\n-   [Admins](#admins)\n-   [Implementation team](#implementation-team)\n-   [Security](#security)\n-   [Access groups](#access-groups)\n    -   [GitHub commit access](#github-commit-access)\n    -   [GitHub label and review access](#github-label-and-review-access)\n    -   [Google Drive access](#google-drive-access)\n\n<!-- tocstop -->\n\n## Overview\n\nThese are groups used by the Carbon Language project, listed here for central\ntracking. Membership will typically be managed by a team owner or admin; see\neach group's summary for information on how to join.\n\nNote that some links are admin or member restricted. We're providing public\nlinks where possible.\n\n### Linked entities\n\nGroups are defined by their linked entities in Carbon's various forums:\n\n-   [GitHub teams](https://github.com/orgs/carbon-language/teams): Used\n    primarily for GitHub ACLs.\n    -   [GitHub organization members](https://github.com/orgs/carbon-language/people):\n        This should only contain people in teams.\n-   Discord roles: Used to identify team members on Discord, and for ACLs.\n-   [Google groups](https://admin.google.com/ac/groups): Used for a mix of\n    contact lists and ACLs.\n\n## Carbon leads\n\nSee [governance structure](evolution.md#governance-structure) for team\ninformation.\n\n-   GitHub teams: [Leads](https://github.com/orgs/carbon-language/teams/leads)\n-   Discord roles: lead\n-   Google groups: None\n\n## Conduct team\n\nSee [Conduct team](teams/conduct_team.md) for information.\n\n-   GitHub teams: None\n-   Discord roles: None\n-   Google groups:\n    [conduct@carbon-lang.dev](https://groups.google.com/a/carbon-lang.dev/g/conduct/about)\n    Used as a contact list.\n\n### Moderators\n\nSee [moderators](moderators.md) for information.\n\n-   GitHub teams:\n    [Moderators](https://github.com/orgs/carbon-language/teams/moderators)\n-   Discord roles: moderator, senior-moderator\n-   Google groups:\n    [moderators](https://groups.google.com/a/carbon-lang.dev/g/moderators/about):\n    Used for Google Drive ACLs.\n\n## Admins\n\nMaintains infrastructure. Membership changes are handled on an as-needed basis\nby leads.\n\nNote that while various groups exist, the way admins are actually configured\ngoes a little beyond this.\n\n-   Github teams: [Admins](https://github.com/orgs/carbon-language/teams/admins)\n    -   Canonically, the\n        [role:owner](https://github.com/orgs/carbon-language/people?query=role%3Aowner)\n        search.\n-   Discord roles: admin\n-   Google groups:\n    [admins](https://groups.google.com/a/carbon-lang.dev/g/conduct/about): Used\n    for `carbon-lang.dev` security settings.\n\n## Implementation team\n\nThis team is responsible for development of Carbon's primary, reference\nimplementation and toolchain. It also oversees other related implementation work\nwithin the Carbon project, from tooling of the language spec to test suites.\nThere may be some overlap with [admins](#admins) -- any issue can be resolved by\nescalating to the [Carbon leads](#carbon-leads). Notably, this team is _not_\nresponsible for the _design_ of the language itself, only for its\nimplementation.\n\n-   GitHub teams: None\n-   Discord role: implementation-team\n-   Google groups: None\n\n## Security\n\nReceives GitHub security reports. Membership changes are handled on an as-needed\nbasis by leads.\n\n-   GitHub teams:\n    [Security](https://github.com/orgs/carbon-language/teams/security)\n-   Discord roles: None\n-   Google groups: None\n\n## Access groups\n\nThese groups are defined by the access they grant. They are not directly tied to\nany of the above community groups.\n\n### GitHub commit access\n\nDevelopers who can merge and approve changes on GitHub. See\n[commit access](commit_access.md) for information.\n\n-   GitHub teams:\n    [Commit access](https://github.com/orgs/carbon-language/teams/commit-access)\n-   Discord roles: None\n-   Google groups: None\n\n### GitHub label and review access\n\nDevelopers who can label and assign PRs and issues on GitHub, particularly\nproposals. See [CONTRIBUTING.md](/CONTRIBUTING.md#getting-access) for more\ninformation.\n\n-   GitHub teams:\n    [Label and review access](https://github.com/orgs/carbon-language/teams/label-and-review-access)\n-   Discord roles: None\n-   Google groups: None\n\n### Google Drive access\n\nFor Google Drive and the contained documents, we have separate groups for\ncommenting and contributing (modify and create). See\n[CONTRIBUTING.md](/CONTRIBUTING.md#getting-access) for more information.\n\n-   GitHub teams: None\n-   Discord roles: None\n-   Google groups:\n    [commenters](https://groups.google.com/a/carbon-lang.dev/g/commenters/about)\n    and\n    [contributors](https://groups.google.com/a/carbon-lang.dev/g/contributors/about):\n    Used for Google Drive ACLs.\n"
  },
  {
    "path": "docs/project/milestones.md",
    "content": "# Milestones\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Milestone 0.1: a minimum viable product (MVP) for evaluation](#milestone-01-a-minimum-viable-product-mvp-for-evaluation)\n    -   [Goals](#goals)\n    -   [Language features](#language-features)\n        -   [Code organization and structuring](#code-organization-and-structuring)\n        -   [Type system](#type-system)\n        -   [Functions, statements, expressions, ...](#functions-statements-expressions-)\n        -   [Standard library components](#standard-library-components)\n    -   [Project features](#project-features)\n-   [Milestone 0.2: feature complete product for evaluation](#milestone-02-feature-complete-product-for-evaluation)\n    -   [Features explicitly deferred until at least 0.2](#features-explicitly-deferred-until-at-least-02)\n        -   [Why are coroutines and async in this milestone?](#why-are-coroutines-and-async-in-this-milestone)\n-   [Milestone 1.0: no longer an experiment, usable in production](#milestone-10-no-longer-an-experiment-usable-in-production)\n    -   [Features explicitly deferred beyond 0.2](#features-explicitly-deferred-beyond-02)\n\n<!-- tocstop -->\n\n## Overview\n\nAs Carbon progresses, we want to have some common long-term milestones that we\norient our work around. The annual [roadmap](roadmap.md) provides a specific and\nimmediate set of priorities for the year, but we want successive years to point\nin a coherent direction with meaningful end goals. Milestones should typically\nbe long-term, spanning more than a year, and have some functional motivation.\n\nWe also assign version numbers to our initial milestones to make them easy to\nrefer to and incorporate into various versioning schemes.\n\n## Milestone 0.1: a minimum viable product (MVP) for evaluation\n\nThe first milestone is also the most concrete -- it is the MVP for C++ users and\ndevelopers to begin evaluating Carbon seriously. We want to keep this milestone\nas minimal as we can while still enabling a sufficient initial round of\nevaluation.\n\n### Goals\n\nFrom the perspective of outcomes, our goals for the 0.1 language are centered\naround what we expect evaluations to be able to include:\n\n-   Evaluators have a clear idea of the long-term evolution strategy of Carbon\n    and how it addresses different use cases and requirements.\n-   Language design components are documented, cohesive, and understandable by\n    evaluators without placeholders.\n    -   The components and language features must include the foundational core\n        of the language. These features must also be sufficient to translate\n        existing C++ code\n        ([except coroutines](#why-are-coroutines-and-async-in-this-milestone))\n        into obvious and unsurprising Carbon code.\n    -   Also in-scope are additional features that impact API design or need\n        early feedback, but only if they are low cost to both the design and\n        implementation.\n    -   Example language components include: lexical structure, expressions,\n        statements, conditions, loops, user-defined types, and their\n        dependencies.\n    -   Example library components include: integer types, floating point types,\n        strings, arrays, ranges, pointers, optionals, variants, heap allocation,\n        and their dependencies.\n    -   Where these build on top of other language or library designs, those are\n        transitively in-scope.\n-   Design for both Carbon use of C++ and C++ use of Carbon, including all major\n    C++ language features except for coroutines, is documented, cohesive, and\n    understandable by evaluators without placeholders.\n-   Evaluators can build and run tests of most C++ interoperability, including\n    both real-world C++ code that can be built with the latest release of Clang\n    and test Carbon code.\n    -   Gaps from the design need to be ones that don't undermine evaluation\n        confidence.\n-   Evaluators can effectively stress-test build speed and scaling with Carbon.\n-   Evaluators can build some key benchmarks that include C++ interoperation in\n    the critical path and get representative performance results.\n    -   This can in turn be a still smaller subset of all aspects of C++\n        interoperability based around what impacts interesting benchmarks.\n-   Both strategy and design for memory safety allow evaluators to be confident\n    in safe Carbon having strong memory safety protections, and being\n    incrementally adoptable starting from existing C++ codebases.\n\n### Language features\n\nThese are focused on the core _necessary_ features for us to reach a successful\n0.1 language that can address our goals. Some of these features are required\ndirectly by the above goals, others are required due to dependencies or\ninteractions with the directly required features. However, we don't try to cover\nall of the features in full granularity here. There will be many minor\ncomponents that are necessary for these to hold together but are not directly\naddressed. In general, unless something is explicitly described as partial or\nhaving exceptions, everything covered by that entry should be expected in the\n0.1 language.\n\nAnother important point is that this doesn't commit Carbon to any _particular_\ndesign for any of these bullet points. Instead, it just means that the Carbon\ndesign must have _something_ that addresses each of these bullet points. That\nmight be to add the named design to Carbon, but it equally might be a clear\nstatement that Carbon will _not_ include this design but use some other language\nfeatures to address its use cases and when rewriting C++ code using that feature\ninto Carbon.\n\n#### Code organization and structuring\n\n-   Packages\n-   Libraries\n-   Implementation files\n-   Importing\n-   Namespaces\n\n#### Type system\n\n-   User-defined types\n    -   C++ interop: importing C++ types into Carbon, exporting Carbon types\n        into C++\n    -   Single inheritance\n        -   Virtual dispatch\n        -   C++ interop:\n            -   Bi-directional inheritance between C++ and Carbon\n            -   Type hierarchy roots in both C++ and Carbon\n            -   Mappings of inheritance features: abstract, final, virtual\n    -   Operator overloading\n        -   C++ interop:\n            -   Synthesizing Carbon overloads for imported C++ types\n            -   Exporting Carbon overloads into C++\n    -   Sum types (discriminated unions)\n    -   Unions (un-discriminated)\n        -   C++ interop: mapping to and from C++ unions.\n-   Generics\n    -   Both generic functions and types\n    -   Checked generics\n        -   Definition-checked variadics\n    -   Integrated templates\n        -   Including template-style structural conformance to nominal\n            constraints, both modeling the members (like interfaces) and\n            arbitrary predicates (like C++20 expression validity predicates)\n    -   C++ interop:\n        -   Importing C++ templates, instantiating on Carbon types\n        -   Exporting Carbon templates, instantiating on C++ types\n        -   Exporting Carbon checked generics (as templates), instantiating on\n            C++ types\n        -   Mapping C++20 concepts into named predicates, and named predicates\n            into C++20 concepts\n\n#### Functions, statements, expressions, ...\n\n-   Functions\n    -   Separate declaration and definition\n    -   Function overloading\n    -   C++ interop:\n        -   Importing C++ functions and methods and calling them from Carbon\n        -   Exporting Carbon functions and methods and calling them from C++\n        -   Importing C++ overload sets into Carbon overload sets where the\n            model (closed overloading) fits\n        -   Importing C++ open-overload-sets-as-extension-points (`swap`, etc)\n            into synthetic Carbon interfaces for common cases (likely based on\n            heuristics)\n-   Control flow statements\n    -   Conditions\n    -   Loops\n        -   Range-based loops\n        -   Good equivalents for a range of existing C/C++ looping constructs\n    -   Matching\n        -   Good equivalents for C/C++ uses of `switch`\n        -   Working with sum-types, especially for C++ `std::variant` and\n            `std::optional` interop\n        -   Both positive (`if let` in Rust) and negative (`let else` in Rust)\n            combined match control flow and variable declaration\n-   C++ interop: support for C++'s threading and atomic primitives, memory\n    model, and synchronization tools\n-   Error handling\n    -   Any dedicated error handling control flow constructs\n    -   C++ interop:\n        -   Mechanisms to configure how exception handling should or shouldn't\n            be integrated into C++ interop sufficient to address both\n            `-fno-except` C++ dialects and standard C++ dialects\n        -   Calling C++ functions which throw exceptions from Carbon and\n            automatically using Carbon's error handling\n        -   Export Carbon error handling using some reasonably ergonomic mapping\n            into C++ -- `std::expected`, something roughly compatible with\n            `std::expected`, C++ exceptions, etc.\n\n#### Standard library components\n\nNote: we expect to _heavily_ leverage the C++ standard library by way of interop\nfor the vast majority of what is needed in Carbon initially. As a consequence,\nthis is a surprisingly more minimal area than the language features.\n\n-   Language and syntax support library components\n    -   Fundamental types (`bool`, `iN`, `fN`)\n    -   Any parts of tuple or array types needed in the library\n    -   Pointer types\n    -   Interfaces powering language syntax (operators, conversions, etc.)\n-   Types with important language support\n    -   String and related types used with string literals\n    -   Optional\n    -   Slices\n-   C++ interop:\n    -   Transparent mapping between Carbon fundamental types and C++ equivalents\n    -   Transparent mapping between Carbon and C++ _non-owning_ string-related\n        types\n    -   Transparent mapping between Carbon and C++ _non-owning_ contiguous\n        container types\n        -   Includes starting from an owning container and forming the\n            non-owning view and then transparently mapping that between\n            languages.\n    -   Transparent mapping between Carbon and C++ iteration abstractions\n\n### Project features\n\nThere are a few important components of the overarching Carbon project that need\nto be completed as part of 0.1 beyond _language_ features:\n\n-   A functioning Carbon toolchain:\n    -   Supports drop-in usage as a Clang C++ toolchain with the most common\n        Make- and CMake-derived build systems.\n    -   Implements most of the [features](#language-features) above, including\n        C++ interop, and any remaining gaps don't undermine the ability to\n        evaluate the remaining features or the confidence in the overall\n        evaluation.\n    -   Installs on Windows, macOS, and Linux, and builds working programs for\n        those platforms.\n-   Build system integration for CMake, and documentation for integrating with\n    Make or similar build systems.\n-   Detailed safety strategy for Carbon\n    -   Will include specific expectations for how unsafe C++ code and unsafe\n        Carbon code will interact with safe Carbon code.\n    -   Also includes any tradeoffs or prioritization across different kinds or\n        levels of safety.\n-   Detailed and concrete design for safe Carbon\n    -   Must at least include ways in which most modern C++ is safe: type and\n        initialization safety.\n    -   Must also include spatial, temporal, and mutation safety.\n    -   Will include an analysis of how this impacts _safe_ Rust interop.\n    -   Does _not_ include having a complete implementation in 0.1.\n-   Basic documentation for evaluators from getting started to FAQs.\n\n## Milestone 0.2: feature complete product for evaluation\n\nThe second milestone already concretely in mind is reaching a level of\nfeature-completeness. The completeness metric here is based around the features\nnecessary to credibly address the _existing_ needs of C++ users and developers\ninterested in moving to Carbon, and so will be heavily driven by either features\nalready in use in C++ or necessary features to make moving off of C++ a viable\ntradeoff. Ultimately, we need this milestone to be sufficiently feature complete\nthat _users can complete their evaluation of Carbon_. The language will continue\nto evolve and grow features beyond this, but at this point there shouldn't be\nany feature gaps that are problematic for the initial target audience coming\nfrom C++, and we should be able to finalize the Carbon _experiment_ with this\nfeature set.\n\nThat said, this is about as concrete as we can get for a milestone that remains\nyears in the future. The full scope of requirements for this milestone will be\ndefined as we complete 0.1 and begin getting feedback on it. Currently, we just\ncall out specific features that we are actively deferring until at least 0.2 but\nwithout being listed somewhere could cause confusion.\n\n### Features explicitly deferred until at least 0.2\n\n-   Memory safety\n-   Coroutines, async, generators, etc.\n-   Comprehensive story for handling effects, and how functions can be generic\n    across effects\n-   Carbon-native threading\n-   Long tail of metaprogramming features\n-   Mixins\n-   Properties\n-   Inline assembly\n-   SIMD\n-   Some ability to define an API that communicates & shares data across\n    language versions, build configurations, and other FFI or ABI boundaries.\n-   Necessary parts of the standard library\n\n#### Why are coroutines and async in this milestone?\n\nSpecifically, why not address them earlier in 0.1? Or if they can be deferred\nwhy not defer them further?\n\nCoroutines and async programming are large and complex topics to introduce into\nthe language. From watching C++, Rust, Swift, Kotlin, and many other languages\nworking in this space, we have a strong belief that trying to add these to the\n0.1 language would _significantly_ increase the amount of work and likely delay\nwhen we reach that milestone. Also, given the recency of coroutines being added\nto C++, we expect evaluators to be able to reason about their absence and still\naccomplish most of the evaluation of Carbon without issue.\n\nHowever, we also expect that as coroutines start to be widely adopted in C++,\nthey will become an essential feature of the language that would be extremely\ndifficult to give up when moving to Carbon. So we expect coroutines to be a\nnecessary feature for us to effectively decide that the Carbon experiment is a\nsuccess and begin planning large-scale adoption and migration.\n\n## Milestone 1.0: no longer an experiment, usable in production\n\nEven less concrete is the milestone that marks Carbon no longer being an\nexperiment, but if successful, a usable language. Currently this is\nspeculatively called 1.0 but even that is highly subject to change as we\napproach. Again, we simply call out features here that we _do_ expect to have in\na 1.0 milestone, but want to explicitly defer beyond the 0.2 milestone.\n\n### Features explicitly deferred beyond 0.2\n\n-   Robust language evolution strategy and plan, specifically addressing:\n    -   The need to make on-going changes to the language to address feedback\n        and a changing landscape.\n    -   The cost on users of churn and change over time and how to manage that\n        cost.\n    -   A mechanism to address users who need true, durable stability over long\n        time horizons.\n-   Package management strategy and plan, and any early groundwork needed.\n-   Developer experience is high enough quality to enable initial production\n    users.\n    -   Includes compiler error messages and basic developer tooling.\n-   Everything we've learned we need as part of the evaluation of 0.1 and 0.2\n"
  },
  {
    "path": "docs/project/moderators.md",
    "content": "# Moderators\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Overview\n\nModeration is primarily focused on Carbon's Discord and GitHub, but generally\napplies to the [collaboration systems](/CONTRIBUTING.md#collaboration-systems).\nModerators are empowered to improve community discussion and enforce the\n[Code of Conduct](/CODE_OF_CONDUCT.md). Conduct decisions are ultimately the\ndomain of the [Conduct team](/CODE_OF_CONDUCT.md#conduct-team), although\nmoderators will often act in order to protect the community.\n\nAll moderators will have the \"moderator\" role on Discord. Some moderators are\n_senior moderators_, and will have extra privileges to help address harmful\nconduct. Senior moderators will have the \"senior-moderator\" role on Discord.\n\n## Becoming a moderator\n\nTODO: Need to figure out right process for asking. (that is, how?)\n\nThe Conduct team reviews new moderators. Community members will be considered\nmainly based on their history in Carbon Language community spaces (Discord,\nGitHub, etc.), although applicants may also note history in other communities.\n\nPrior to being granted moderation privileges, new moderators will need to attend\na workshop in order to help orient them with the Carbon Language community's\nvalues and moderator expectations.\n\n## Promotion to senior moderator\n\nThe Conduct team reviews promotions to senior moderator. Moderators will be\nconsidered for promotion to senior moderators when:\n\n-   They have demonstrated that they will be active moderators.\n-   They are making decisions consistent with the\n    [Code of Conduct](/CODE_OF_CONDUCT.md).\n-   Senior moderators are taking actions which require senior moderator\n    privileges at the moderator's request.\n\n## Moderation powers\n\nThere is a moderation playbook for moderators with instructions on how to use\nthese powers. This enumerates specific actions a moderator may take.\n\n-   **Discord**\n\n    -   **Timeout user** (all): Prevent a user from sending messages on the\n        Discord server for up to a week.\n\n    -   **Delete message** (senior): Delete a message owned by another user.\n\n    -   **Kick user** (senior): Temporarily remove a user from the Discord\n        server. Note that users can rejoin the server, and so banning is\n        typically preferred.\n\n    -   **Ban user** (senior): Permanently remove a user from the Discord\n        server.\n\n    -   **Slow-mode** (senior): Limit the rate of discussion on a channel.\n\n        -   Slow-mode is tied to the ability to generically edit channels.\n            Moderators are generally expected to use the channel edit power\n            judiciously, preferring to leave channel edits for admins.\n\n-   **GitHub**\n\n    -   **Convert issue to discussion** (all): Moves an issue to a discussion.\n        This is mainly organizational.\n\n    -   **Hide message** (all): Collapses a message so that its text is not\n        immediately visible, reducing distractions. Recommended for moderators\n        when a particular message is unproductive. Users can still view the\n        original content.\n\n        -   This cannot be done with the first message in a conversation.\n\n    -   **Lock conversation** (senior): Prevent more discussion on a topic.\n\n    -   **Edit message** (senior): Edits content of a message. Users can still\n        view the original content.\n\n    -   **Edit title** (senior): Edits the title of a thread.\n\n    -   **Delete message** (senior): Removes a single message from a\n        conversation. Hiding or editing messages is preferred.\n\n        -   This cannot be done to the first message in a conversation.\n\n    -   **Delete conversation** (senior): Deletes a full GitHub conversation.\n        Hiding or editing messages is preferred.\n\n    -   **Block user** (senior): Blocks a user from all repositories.\n\n    -   Note: We use custom roles which have\n        [limited access options](https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/managing-custom-repository-roles-for-an-organization)\n        versus what\n        [base permissions](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-roles-for-an-organization)\n        allow.\n\n-   **Google Docs**\n\n    -   There are limited powers for moderators on Google Docs, but access to\n        Google Docs is already restricted. At present, the right action is to\n        respond or comment on an issue as needed, and report to the Conduct team\n        if further steps are necessary.\n"
  },
  {
    "path": "docs/project/principles/README.md",
    "content": "# Principles\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nSome language [goals](../goals.md) will have widely-applicable, high-impact, and\nsometimes non-obvious corollaries. We collect concrete language design\nprinciples in this directory as a way to document and clarify these. Principles\nclarify, but do not supersede, goals and priorities. Principles should be used\nas a tool in making decisions, and to clarify to contributors how decisions are\nexpected to be made.\n\nA key difference between a principle and the design of a language feature is\nthat a principle should inform multiple designs, whereas a feature's design is\ntypically more focused on achieving a specific goal or set of goals. The\nprinciple can help achieve consistency across those multiple designs.\n\nNote that these principles seek to establish both the approaches the project\nwants to pursue, as well as those we want to exclude.\n\n-   [Errors are values](error_handling.md)\n-   [Information accumulation](information_accumulation.md)\n-   [Low context-sensitivity](low_context_sensitivity.md)\n-   [Prefer providing only one way to do a given thing](one_way.md)\n-   [One static open extension mechanism](static_open_extension.md)\n-   [Success criteria](success_criteria.md)\n"
  },
  {
    "path": "docs/project/principles/error_handling.md",
    "content": "# Principle: Errors are values\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n-   [Principle](#principle)\n-   [Applications of these principles](#applications-of-these-principles)\n\n<!-- tocstop -->\n\n## Background\n\nMost nontrivial programs contain functions that can _fail_, meaning that even if\nall their preconditions are met, they may not be able to perform their primary\nbehavior. For example, a function that reads data from a remote server may fail\nif the server is unreachable, and a function that parses a string to return an\ninteger may fail if the input string is not a properly-formatted integer.\n\nIn many cases, the function author wants these failures to be _recoverable_,\nmeaning that a direct or transitive caller can respond to the failure in some\nway that enables the program to continue running.\n\n## Principle\n\nA Carbon function that needs to report recoverable failures should return a sum\ntype whose alternatives represent the success case and failure cases, such as\n`Optional(T)`, `Result(T, Error)`, or `bool`. The function's successful return\nvalue, and any metadata about the failure, should be embedded in the\nalternatives of the sum type, rather than reported by way of output parameters\nor other side channels. Carbon's design will prioritize making this form of\nerror handling efficient and ergonomic.\n\n## Applications of these principles\n\nCarbon errors, unlike exceptions in C++ and similar languages, will not be\npropagated implicitly. Instead, Carbon will very likely need to provide some\nexplicit but syntactically lightweight means of propagating errors, such as\nRust's `?` operator, so that error-propagation boilerplate doesn't make it hard\nfor readers to follow the logic of the success path.\n\nCarbon will not have a special syntax for specifying what kind of errors a\nfunction can emit, such as `noexcept` or\n[dynamic exception specifications](https://en.cppreference.com/w/cpp/language/except_spec)\nin C++, or `throws` in Java, because that information will be embedded in the\nfunction's return type. Similarly, Carbon errors will be statically typed,\nbecause Carbon return values are statically typed.\n"
  },
  {
    "path": "docs/project/principles/information_accumulation.md",
    "content": "# Principle: Information accumulation\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n-   [Principle](#principle)\n-   [Applications of this principle](#applications-of-this-principle)\n-   [Exceptions](#exceptions)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Background\n\nThere are many different sources of information in a program, and a tool or a\nhuman interpreting code will not in general have full information, but will\nstill want to draw conclusions about the code.\n\nDifferent languages take different approaches to this problem. For example:\n\n-   In C, information is accumulated linearly in each source file independently,\n    and only information from earlier in the same file is available. A program\n    can observe that information is incomplete at one point and complete at\n    another.\n-   In C++, the behavior is largely similar to C, except:\n    -   Within certain contexts in a class, information from later in the class\n        definition is available.\n    -   With C++20 modules, information from other source files can be made\n        available.\n    -   It is easier to observe -- perhaps even accidentally -- that information\n        is accumulated incrementally.\n-   In Rust, all information from the entire crate is available everywhere\n    within that crate, with exceptions for constructs like proc macros that can\n    see the state of the program being incrementally built.\n-   In Swift, all information from the entire source file is available within\n    that source file.\n\n## Principle\n\nIn Carbon, information is accumulated incrementally within each source file.\nCarbon programs are invalid if they would have a different meaning if more\ninformation were available.\n\nCarbon source files can be interpreted top-down, without referring to\ninformation that appears substantially later in a file. Source files are\nexpected to be organized into a topological order where that makes sense, with\nforward declarations used to introduce names before they are first referenced\nwhen necessary.\n\nIf a program attempts to use information that has not yet been provided, the\nprogram is invalid. There are multiple options for how this can be reported:\n\n-   The program can be rejected as soon as it tries to use information that\n    might not be known yet.\n-   For the case where the information can only be provided in the same source\n    file, an assumption about the information can be made at the point where it\n    is needed, and the program can be rejected only if that assumption turns out\n    to be incorrect.\n\nDisallowing programs from changing meaning in the context of more information\nensures that the program is interpreted consistently or is rejected. This is\nespecially important to the coherence of generics and templates.\n\n## Applications of this principle\n\n-   As in C++, and unlike in Rust and Swift, name lookup only finds names\n    declared earlier.\n-   Classes are incomplete until the end of their definition. Unlike in C++, any\n    attempt to observe a property of an incomplete class that is not known until\n    the class is complete renders the program invalid.\n-   When an `impl` needs to be resolved, only those `impl` declarations that\n    appear earlier are considered. However, if a later `impl` declaration would\n    change the result of any earlier `impl` lookup, the program is invalid.\n\n## Exceptions\n\nBecause a class is not complete until its definition has been fully parsed,\napplying this rule would make it impossible to define most member functions\nwithin the class definition. In order to still provide the convenience of\ndefining class member functions inline, such member function bodies are deferred\nand processed as if they appeared immediately after the end of the outermost\nenclosing class, like in C++.\n\n## Alternatives considered\n\n-   Allow information to be used before it is provided\n    [globally](/proposals/p0875.md#strict-global-consistency),\n    [within a file](/proposals/p0875.md#context-sensitive-local-consistency), or\n    [within a top-level declaration](/proposals/p0875.md#top-down-with-minimally-deferred-type-checking).\n-   [Do not allow inline method bodies to use members before they are declared](/proposals/p0875.md#strict-top-down)\n-   [Do not allow separate declaration and definition](/proposals/p0875.md#disallow-separate-declaration-and-definition)\n"
  },
  {
    "path": "docs/project/principles/library_apis_only.md",
    "content": "# Principle: All APIs are library APIs\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n-   [Principle](#principle)\n-   [Applications of this principle](#applications-of-this-principle)\n-   [Exceptions](#exceptions)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Background\n\nEvery major modern programming language comes with a standard library, which\nconsists of APIs that are not part of the core language, but instead are written\nin the language (although their implementations may not be). However, different\nlanguages draw the boundary between language and library in different places.\nFor example, Go's `map` type is built into the core language, whereas the C++\nequivalent, `std::unordered_map`, is part of the standard library. In Swift,\neven fundamental types like integers and pointers are part of the standard\nlibrary; there are no truly \"built in\" types.\n\nThese decisions can have important consequences for the design of the language.\nFor example, many important features of C++, such as move semantics, variadics,\nand coroutines, were motivated largely by their anticipated uses in a small set\nof standard library types. In a language with a different design philosophy,\nthose types could have been built into the core language. This would probably\nhave substantially simplified the language, and made those types available\nfaster. However, that would have come at the cost of less flexibility for users\noutside the common case.\n\n## Principle\n\nIn Carbon, every public function is declared in some Carbon API file, and every\npublic `interface`, `impl`, and first-class type is defined in some Carbon API\nfile. In some cases, the bodies of public functions will not be defined as\nCarbon code, or will be defined as hybrid Carbon code using intrinsics that\naren't available to ordinary Carbon code. However, we will try to minimize those\nsituations.\n\nThus, even \"built-in\" APIs can be used like user-defined APIs, by importing the\nappropriate library and using qualified names from that library, relying on the\nordinary semantic rules for Carbon APIs.\n\n## Applications of this principle\n\nWe expect Carbon to have a special \"prelude\" library that is implicitly imported\nby all Carbon source files, and there might be a special name lookup rule to\nallow the names in the prelude to be used unqualified. However, in accordance\nwith this principle, they will remain available to ordinary qualified name\nlookup as well.\n\nAccording to the resolutions of\n[#543](https://github.com/carbon-language/carbon-lang/issues/543) and\n[#750](https://github.com/carbon-language/carbon-lang/issues/750), Carbon will\nhave a substantial number of type keywords, such as `i32`, `f64`, and `bool`.\nHowever, these keywords will all be aliases for ordinary type names, such as\n`Carbon.Int(32)`, `Carbon.Float(64)`, and `Carbon.Bool`. Furthermore, all\narithmetic and logical operators will be overloadable, so that those types can\nbe defined as class types. The member function bodies for these types will be\nprobably not be implemented in Carbon, but this principle applies only to\nfunction declarations, not function definitions.\n\nSimilarly, a pointer type such as `Foo*` will be an alias for some library class\ntype, for example `Carbon.Ptr(Foo)`. As a result, Carbon will support\noverloading pointer operations like `->` and unary `*`.\n\nAll Carbon operations that use function-style syntax, such as `sizeof()` and\n`decltype()` in C++, will be standard library functions. As above, in some cases\nwe may choose to alias those functions with keywords, and the function bodies\nmay not be defined in Carbon.\n\n## Exceptions\n\nThis principle applies to types only if they are _first-class_, meaning that\nthey can be the types of run-time variables, function parameters, and return\nvalues. Carbon's type system will probably also include some types whose usage\nis more restricted, and this principle will not apply to them. Most importantly,\nfunction types might not be first-class types, in which case they need not be\nlibrary types.\n\nSome types (such as tuples, structs, and certain integer types) will have\nbuilt-in literal syntaxes for creating values of those types. Furthermore, in\nsome cases (such as tuples and structs) the type's literal syntax will also be\nusable as a pattern syntax. The logic for performing those operations is\narguably part of those types' public API, but will not be part of those types'\nclass definitions.\n\n## Alternatives considered\n\n-   [Built-in primitive types](/proposals/p1280.md#built-in-primitive-types)\n"
  },
  {
    "path": "docs/project/principles/low_context_sensitivity.md",
    "content": "# Principle: Low context-sensitivity\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Principle](#principle)\n    -   [Mitigations of context-sensitive costs](#mitigations-of-context-sensitive-costs)\n        -   [Visual aids](#visual-aids)\n        -   [Contextual _validity_ rather than _meaning_](#contextual-validity-rather-than-meaning)\n        -   [Reduced cost of mistakes](#reduced-cost-of-mistakes)\n            -   [Compiler-checked context](#compiler-checked-context)\n-   [Applications of the principle](#applications-of-the-principle)\n    -   [Imports and namespaces](#imports-and-namespaces)\n    -   [Name shadowing](#name-shadowing)\n    -   [Flow-sensitive typing](#flow-sensitive-typing)\n    -   [Coherence of names and generics](#coherence-of-names-and-generics)\n    -   [Performance](#performance)\n\n<!-- tocstop -->\n\n## Principle\n\nCarbon should favor designs and mechanisms that are not sensitive to context.\nInstead, we should favor constructs that are not ambiguous so that they don't\nneed context for disambiguation. This is in service to the goal that\n[Carbon code is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nIn particular, this is about prioritizing reading and understanding over\nwriting. We should be willing to trade off conciseness, which still benefits\nreading as well as writing, for a sufficiently impactful reduction in the amount\nof context needed to read and understand code.\n\nContext can be expensive in different ways, for example:\n\n-   It can be _large_: it might require looking through a lot of lines of code\n    to find all of the relevant contextual information.\n-   It can be _distant_: the further away from the current declaration or\n    definition, the more expensive it is to find contextual information. This\n    can scale from a separate definition in the same file, to a separate file,\n    or even to a separate package.\n-   It can be _unpredictable_: it might require careful searching of large\n    bodies of code to locate the contextual information if its location cannot\n    be predicted.\n-   It can be _subtle_: the contextual clues might be easily missed or mistaken.\n\nCode that isn't context sensitive is easier to copy or move between contexts,\nlike files or functions. It is code that needs fewer changes when it is\nrefactored, in support of\n[software evolution](/docs/project/goals.md#software-and-language-evolution).\n\nIn general, we should start with more restrictive constructs that limit\nambiguity and see if we can make them work. If we find those restrictions are\nburdensome, we will then have more information to inform the next step. Ideally\nwe would address those use cases with simple tools that solve multiple problems.\nThe goal is to make a bunch of orthogonal mechanisms, each of which are easily\nunderstood and act in unsurprising ways.\n\nIf that next step is to loosen restrictions, that is generally easier to do\nwhile maintaining compatibility with existing code than adding new restrictions.\n\n### Mitigations of context-sensitive costs\n\nThere are several ways that the potential costs of context-sensitive code can be\nmitigated. These techniques can and should be leveraged to help minimize and\nmitigate the contextual costs of Carbon features, and in some cases may provide\na path to a feature that would otherwise be prohibitively costly.\n\n#### Visual aids\n\nA direct way to reduce contextual costs is through lexical and syntactic\nstructures that form visual aids. These can both reinforce what the context is\nand aid the reader in the expensive aspect of navigating the context. For\nexample, representing contexts with indentation, or IDE highlighting of matching\nparentheses and braces. These visual hints make it easier for developers to\nnotice contextual elements.\n\n#### Contextual _validity_ rather than _meaning_\n\nWhen the context only affects the _validity_ of code, but not its meaning, the\ncosts are significantly reduced. In that case, understanding the meaning or\nbehavior of the code doesn't require context, and a developer can easily rely on\nthe compiler to check the validity. A simple example of this is contextually\nvalid syntax, which is relatively common and inexpensive. However, reusing the\nsame syntax with different contexts _with different meanings_ shifts the\ncontextual information from simple validity to impacting the meaning of code.\n\n#### Reduced cost of mistakes\n\nAnother mitigation for the costs of context-sensitive code is when the cost of a\nmistake due to the context is low. Some simple examples:\n\n-   Context-sensitivity in comments is less expensive in general than in code.\n-   In places where the general meaning is clear, developers can safely and\n    reliably work with that general understanding, and the context only provides\n    a minor refinement.\n\n##### Compiler-checked context\n\nAnother way the costs of mistakes can be reduced is when the compiler can\nreliably detect them. This is the fundamental idea behind statically\ntype-checked languages: the compiler enforcement reduces the contextual cost of\nknowing what the types are. How early and effectively the compiler can detect\nthe mistakes also plays a role in reducing this cost, which is part of the value\nproposition for\n[definition-checked](/docs/design/generics/terminology.md#definition-checking)\ngenerics.\n\nAn example of this situation in Rust is that the same syntax is used for a move\nand a copy of the value in a variable. Those cases are distinguished by whether\nthe type implements a specific trait, which may not be readily ascertained. The\ncompiler verifies that the code never uses a variable that is no longer valid\ndue to having been moved from, which is expected to catch the problems that\ncould arise from this difference. Otherwise the semantic difference between a\nmove and a copy is considered in Rust to be low-enough stakes for there to be no\nneed to signal that difference in the code.\n\nHowever, the reasoning that makes this example a good design on balance for Rust\ndoesn't necessarily apply to Carbon. The compiler is checking to prevent\n_errors_, but it can't reliably check for unpredictable _performance_. Given\nCarbon's priorities, that might make this level of contextual information still\ntoo expensive.\n\nMore background on this area of Rust specifically is presented in\n[their blog post on language ergonomics](https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html).\n\n## Applications of the principle\n\nThere are many parts of Carbon that could potentially be analyzed through this\nlens, and we can't enumerate them all here. This section focuses on several\nexamples to help illustrate how the principle is likely to be relevant to\nCarbon. They focus on either cases that showcase the principle in effect or\ncases which make challenging tradeoffs of the costs in the principle.\n\n### Imports and namespaces\n\nThere are several parts of the way\n[imports](/docs/design/code_and_name_organization/#imports) and\n[namespaces](/docs/design/code_and_name_organization/#namespaces) are designed\nin Carbon that reflect applications of this principle:\n\n-   Adding an import or reordering imports should never change behavior of\n    existing code. This means the reader doesn't have to look through all the\n    imports to understand how code behaves. This is also important for tooling,\n    which should not have to worry about unwanted side effects when adding or\n    sorting imports.\n\n-   Carbon doesn't provide an analogy to C++'s\n    [`using namespace`](https://en.cppreference.com/w/cpp/language/namespace#Using-directives)\n    or a\n    [\"wildcard imports\" mechanisms](/proposals/p0107.md#broader-imports-either-all-names-or-arbitrary-code)\n    that merge the names from one namespace into another. Either would introduce\n    ambiguity in where a name is coming from, making the code more\n    context-sensitive.\n\n-   Carbon doesn't support large blocks of code\n    [inside a namespace declaration](/proposals/p0107.md#scoped-namespaces),\n    where the reader would have to search for the beginning of the block to see\n    what namespace applies.\n\n### Name shadowing\n\nWe should limit how names can be reused with shadowing rules, so the meaning of\na name doesn't change in surprising ways between scopes. Further, if you find a\nmatching declaration you don't have to keep searching to see if there is another\nthat hides the one you found. This both expands the context you have to\nconsider, and is an opportunity to make a mistake identifying the correct\ncontext, potentially leading to misunderstanding of the code.\n\n### Flow-sensitive typing\n\nThis principle is an argument against\n[flow-sensitive typing](https://en.wikipedia.org/wiki/Flow-sensitive_typing),\nwhere the type of a name can change depending on control flow. For example,\n[Midori used this for optional types](http://joeduffyblog.com/2016/02/07/the-error-model/#the-syntax).\nIf we were to support this in Carbon, you could unwrap an optional value by\ntesting it against `None`.\n\n```\nvar x: Optional(Int) = ...;\nif (x != None) {\n  // x has type Int.\n  PrintInt(x);\n}\n// x is back to type Optional(Int).\n```\n\nThis can be taken farther, this example has `x` taking on three different types:\n\n```\nvar x: Optional(Optional(Int)) = ...;\nif (x != None) {\n  // x has type Optional(Int).\n  if (x != None) {\n    // x has type Int.\n    PrintInt(x);\n  }\n  // x has type Optional(Int).\n}\n// x has type Optional(Optional(Int)).\n```\n\nThe concern here is that the context is very subtle. The type of `x` is affected\nby otherwise ordinary-looking `if` statements and closing braces (`}`).\n\nWhile we might not want to completely eliminate the possibility of\nflow-sensitive typing in Carbon, it would have to overcome a large hurdle. We\nwould only want a flow-sensitive feature if it delivered sufficiently large\nusability, consistency, or expressivity gains.\n\n### Coherence of names and generics\n\nCarbon [packages](/docs/design/code_and_name_organization/#packages) are\ndesigned to ensure all declared names belong to exactly one package and the\ncompiler can enforce Carbon's equivalent\n[one-definition rule (ODR)](https://en.wikipedia.org/wiki/One_Definition_Rule).\nThis avoids an issue in C++ where the ODR is not reliably checked by the\ncompiler, which can leave the correctness of programs dependent on both distant\nand subtle contextual information.\n\nSimilarly, Carbon generics should have\n[coherence, like Rust](https://github.com/Ixrec/rust-orphan-rules#what-is-coherence),\nwhere types have a single implementation of an interface. And this should be\nenforced by the compiler, using rules like\n[Rust's orphan rules](https://github.com/Ixrec/rust-orphan-rules#what-are-the-orphan-rules).\n\n### Performance\n\nSince\n[Carbon's number one goal is performance](/docs/project/goals.md#performance-critical-software),\nit is important that the performance characteristics of code be predictable and\nreadily determined by readers. This argues that those characteristics should not\ndepend on expensive context. For example, Carbon should not provide a\n`dynamic_cast` facility with the same capabilities of C++'s where distant\naspects of the inheritance structure can cause surprising performance\ndifferences. Similarly, Carbon should try to ensure normal looking method calls\nand data member access don't have the surprising performance costs caused by\nvirtual inheritance in C++.\n\nMore generally, Carbon should avoid features with hidden costs, particularly\nwhen they scale based on subtle aspects of the context where those features are\nused.\n"
  },
  {
    "path": "docs/project/principles/namespace_cleanliness.md",
    "content": "# Principle: Namespace cleanliness\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n-   [Principle](#principle)\n-   [Applications of this principle](#applications-of-this-principle)\n-   [Exceptions](#exceptions)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Background\n\nNames and entities in a program can come from multiple sources -- from a local\ndeclaration, from an import, from the standard library, or from the prelude.\nNames can be imported from Carbon code or imported or derived from code written\nin another language such as C++ or an interface description language such as\nthat of Protobuf, MIDL, or CORBA. Names can be selected for use in a program\nthat language designers later decide they want to use as keywords. And in order\nto use a library, it is sometimes necessary to redeclare the same name that that\nlibrary chose.\n\nThis puts a lot of pressure on the language to support a free choice of naming\nfor entities. Different languages make different choices in this space:\n\n-   Many languages have a set of keywords that are not usable as identifiers,\n    with no workaround. If this set collides with a name needed by user code,\n    the user is left to solve this problem, often by rewriting the identifier in\n    some way (`klass` or `class_`), which sometimes conflicts with the general\n    naming convention used by the code. And conversely, suboptimal choices are\n    made for new language keywords to avoid causing problems for existing code.\n-   C and C++ reserve a family of identifiers, such as those beginning with an\n    underscore and a capital letter. However, it's not clear which audiences the\n    reserved identifiers are for, and this leads to collisions between standard\n    library vendors and compiler authors, as well as between implementation\n    extensions and language extensions.\n    -   MSVC provides a `__identifier(keyword)` extension that allows using a\n        keyword as an identifier. This extension is also implemented by Clang in\n        `-fms-extensions` mode.\n    -   GCC provides an `__asm__(symbol)` extension that allows a specific\n        symbol to be assigned to an object or function, which provides ABI\n        compatibility but not source compatibility with code that uses a keyword\n        as a symbol name. This extension is also implemented by Clang.\n-   Python reserves some identifiers but still allows them to be freely\n    overwritten (such as `bool`) and reserves some identifiers but rejects\n    assignment to them (such as `True`).\n-   Rust provides a raw identifier syntax to allow most identifiers with\n    reserved meaning to be used by a program, but\n    [not all](https://internals.rust-lang.org/t/raw-identifiers-dont-work-for-all-identifiers/9094):\n    `self`, `Self`, `super`, `extern`, and `crate` cannot be used as raw\n    identifiers. Rust also predeclares a large number of library names in every\n    file, but allows them to be shadowed by user declarations with the same\n    name.\n-   Swift provides a raw identifier syntax using backticks: `` `class` ``, and\n    is\n    [considering](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0451-escaped-identifiers.md)\n    extending this to allow arbitrary non-word-shaped character sequences\n    between the `` ` ``s.\n\nCarbon provides\n[raw identifier syntax](/docs/design/lexical_conventions/words.md#raw-identifiers),\nfor example `r#for`, to allow using keywords as identifiers. Carbon also intends\nto have strict shadowing rules that may make predeclared identifiers that are\n_not_ keywords difficult or impossible to redeclare and use in inner scopes.\n\n## Principle\n\nIn Carbon, the language does not encroach on the developer's namespace. There\nare no predeclared or reserved identifiers. In cases where the language gives\nspecial meaning to a word or to word-shaped syntax such as `i32`, that special\nmeaning can always be undone with raw identifier syntax, `r#`.\n\nConversely, when adding language keywords, we will not select an inferior\nkeyword merely to avoid the risk of breaking existing programs. We will still\ntake into account how often it is desirable to use the word as an identifier,\nincluding in domain-specific contexts, because that is a factor in whether it\nwould make a good keyword, and will manage the rollout of new keywords to make\nit straightforward to migrate existing uses to `r#` or a different name.\n\n## Applications of this principle\n\n-   Words like `final` and `base` that only have special meaning in a few\n    contexts, and could otherwise be made available as identifiers, are keywords\n    in Carbon. `{.base = ...}` and `{.r#base = ...}` specify different member\n    names.\n-   Words like `self` that are declared by the developer but nonetheless have\n    special language-recognized meaning are keywords in Carbon. `[self:! Self]`\n    introduces a self parameter; `[r#self:! Self]` introduces a deduced\n    parameter.\n-   Words like `Self` that are implicitly declared by the language in some\n    contexts are keywords, even though we could treat them as user-declared\n    identifiers that are merely implicitly declared in some cases.\n-   Words like `i32` that are treated as type literals rather than keywords can\n    be used as identifiers with raw identifier syntax `r#i32`.\n-   There are no predeclared identifiers imported from the prelude. If an entity\n    is important enough to be available by default, we should add a keyword, and\n    allow the name of the entity to be used for other purposes with `r#`.\n-   The predeclared package name `Core` is a keyword. A package named `r#Core`\n    is an unrelated package, and `Core.foo` always refers to members of the\n    predeclared `Core` package.\n\n## Exceptions\n\nFor now, we reserve the package names `Main` and `Cpp`. These names aren't\npredeclared in any scope, and the name `Main` is not even usable from within\nsource files to refer to the main package. However, there is currently no way to\navoid collisions between the package name `Cpp` and a top-level entity named\n`Cpp` if they are both used in the same source file.\n\n## Alternatives considered\n\n-   [Have both predeclared identifiers and keywords](/proposals/p4864.md#have-both-predeclared-identifiers-and-keywords)\n-   [Reserve words with a certain spelling](/proposals/p4864.md#reserve-words-with-a-certain-spelling)\n"
  },
  {
    "path": "docs/project/principles/one_way.md",
    "content": "# Principle: Prefer providing only one way to do a given thing\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n-   [Principle](#principle)\n-   [Applications of this principle](#applications-of-this-principle)\n-   [Caveats](#caveats)\n    -   [Specialized syntax](#specialized-syntax)\n    -   [Non-obvious alternatives](#non-obvious-alternatives)\n    -   [In evolution](#in-evolution)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Background\n\nIt's common in programming languages to provide multiple, similar ways of doing\nthe same thing. Sometimes this reflects the legacy of a language, and\ndifficulties in evolving in ways that would require changes to\ndeveloper-authored code, thereby retaining backwards compatibility. Other times\nit reflects a desire to provide both verbose and concise versions of the same\nsyntax. We are concerned with both forms.\n\nWe also are cautious about creating alternatives that may give rise to a\n[paradox of choice](https://en.wikipedia.org/wiki/The_Paradox_of_Choice),\nwherein options are similar enough that developers actively spend time analyzing\ntrade-offs, and the time spent that way outweighs the potential benefits of a\ncorrect choice.\n\nWhere multiple, similar implementation options exist, it can sometimes give rise\nto style guidelines to indicate a preferential choice; sometimes because one\noption is objectively better, but sometimes because making a choice is better\nthan not making one. Even with a style guide, developers may diverge in style by\naccident or intent, choosing different coding patterns simply because either\noption works. It can also become an issue as developers move between an\norganization that they need to learn a new style guide, and relearn habits.\n\nA couple examples of this in other languages are:\n\n-   In Perl,\n    [\"There is more than one way to do it.\"](https://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it)\n-   In Python,\n    [\"There should be one -- and preferably only one -- obvious way to do it.\"](https://www.python.org/dev/peps/pep-0020/)\n\n## Principle\n\nIn Carbon, we will prefer providing only one way to do a given thing. That is,\ngiven a syntax scenario where multiple design options are available, we will\ntend to provide _one_ option rather than providing several and letting users\nchoose. This echoes Python's principle.\n\nMinimizing choices serves several goals:\n\n-   [Language tools](/docs/project/goals.md#language-tools-and-ecosystem) should\n    be easier to write and maintain with the lower language complexity implied\n    by less duplication of functionality.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    processes should find it easier to both consider existing syntax and avoid\n    creation of new syntax conflicts.\n-   [Understandability of code](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    should be promoted if developers have less syntax they need to understand.\n    This can be expected to improve code quality and productivity so long as the\n    resulting code structures aren't overly complicated.\n\nBy minimizing the overlap of language features, we hope to make work easier for\nboth Carbon's maintainers and developers.\n\n## Applications of this principle\n\nWe can observe the application of this principle by comparing several language\nfeatures to C++. There, improving understandability is frequently the primary\nmotivation:\n\n-   Where C++ allows logical operators to be written with either symbols (for\n    example, `&&`) or text (for example, `and`), Carbon will only support one\n    form (in this case, [text](/proposals/p0680.md)).\n-   Where C++ allows hexadecimal numeric literals to be either lowercase\n    (`0xaa`) or uppercase (`0xAA`), and with `x` optionally uppercase as well,\n    Carbon will only allow the [`0xAA` casing](/proposals/p0143.md).\n-   Where C++ provides both `struct` and `class` with the only difference is\n    access control defaults, Carbon will only provide one (`class`, albeit with\n    default public visibility diverging from C++).\n\nHowever, sometimes language tools are the primary motivation. For example, where\nC++ allows braces to be omitted for single-statement control flow blocks, Carbon\nwill [require braces](/proposals/p0623.md). This offers a syntax simplification\nthat should allow for better error detection.\n\n## Caveats\n\n### Specialized syntax\n\nSometimes overlap will occur because a specialized syntax offers particular\nbenefits, typically as a matter of convenience for either a common use-case or a\nparticularly complex and important use-case. Some examples of why and where this\noccurs are:\n\n-   For [performance](/docs/project/goals.md#performance-critical-software), it\n    may at times be necessary to provide a specialized syntax that better\n    supports optimization than a generic syntax.\n-   For\n    [understandability of code](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\n    there may be times that a particular use-case is common enough that\n    simplifying its syntax provides substantial benefit.\n    -   For example, `for (var x: auto in list)` could typically be written with\n        as a `while` loop, but range-based for loops are considered to improve\n        understandability. However, C++'s `for (;;)` syntax is sufficiently\n        close to `while` that we expect to use `while` to address the\n        corresponding use-cases.\n-   For\n    [migration and interoperability](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code),\n    it may be pragmatic to provide both an ideal way of doing things for new\n    Carbon code, and a separate approach that is more C++-compatible for\n    migration.\n    -   For example, consider generics and templates: generics are considered to\n        be the preferred form for new code, but templates are considered a\n        necessity for migration of C++ code. This is not an evolution situation\n        because we do not anticipate ever removing templates.\n\n### Non-obvious alternatives\n\nEchoing Python, there may be non-obvious alternative ways of doing a given\nthing, such as using `while (condition) { DoSomething(); break; }` in place of\n`if (condition) { DoSomething(); }`. As a more complex example, lambdas could be\nimplemented using other code constructs; this would require significantly more\ncode and hinder understandability.\n\nThis kind of overlap may exist, but will hopefully be considered sufficiently\nnon-idiomatic that examples won't be common in code. If a choice would not\nlikely be based mainly on coding styles, it's likely sufficiently distinct that\nthis principle won't apply.\n\n### In evolution\n\nFor [evolution](/docs/project/goals.md#software-and-language-evolution), it will\noften be necessary to temporarily provide an \"old\" and \"new\" way of doing things\nsimultaneously.\n\nFor example, if renaming a language feature, it may be appropriate to provide\nthe same functionality under two identifiers. However, one should be marked as\ndeprecated and eventually removed. We should be cautious of adding new,\noverlapping features without a plan to remove the corresponding legacy version.\n\n## Alternatives considered\n\n-   [Provide multiple ways of doing a given thing](/proposals/p0829.md#provide-multiple-ways-of-doing-a-given-thing)\n"
  },
  {
    "path": "docs/project/principles/progressive_disclosure.md",
    "content": "# Principle: Progressive disclosure\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n-   [Principle](#principle)\n-   [Applications of this principle](#applications-of-this-principle)\n\n<!-- tocstop -->\n\n## Background\n\n[Progressive disclosure](https://en.wikipedia.org/wiki/Progressive_disclosure)\nis a UX design pattern which defers revealing information and advanced/\nspecial-case controls to the user until they are relevant to the current task,\nin order to make the system easier to learn and use. Although the term\noriginates in GUI design, it can be applied to language design as well. In\nparticular, it's one of\n[Swift's core design principles](https://www.youtube.com/watch?v=CRtyWqwLM3M&t=369s).\n\n## Principle\n\nIn Carbon, we will prefer designs that support progressive disclosure, in the\nsense defined\n[here](https://www.douggregor.net/posts/swift-for-cxx-practitioners-extensions/#:~:text=By%20default%2C%20any%20code,understanding%20of%20the%20language):\n\n> ... the idea that one can ignore certain aspects of the language when starting\n> out, and then learn about them only at the time when you need them, without\n> invalidating any of your prior understanding of the language.\n\n## Applications of this principle\n\nTypes such as `i32` are designed to follow progressive disclosure: they are\nactually class types defined in the prelude library that support arithmetic\noperations by implementing certain customization interfaces. However,\nprogrammers can learn to use them by thinking of them as primitive types like\ntheir C counterparts, without needing to understand the arithmetic operator\ninterfaces, interface implementation in general, libraries, the prelude, or even\nclass types. Subsequently learning those concepts doesn't invalidate that\noriginal mental model, but rather shows how that model is built out of more\nfundamental pieces.\n"
  },
  {
    "path": "docs/project/principles/safety_strategy.md",
    "content": "# Safety strategy\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n    -   [What \"safety\" means in Carbon](#what-safety-means-in-carbon)\n    -   [Safety guarantees versus hardening](#safety-guarantees-versus-hardening)\n-   [Philosophy](#philosophy)\n-   [Principles](#principles)\n-   [Details](#details)\n    -   [Incremental work when safety requires work](#incremental-work-when-safety-requires-work)\n    -   [Using build modes to manage safety checks](#using-build-modes-to-manage-safety-checks)\n        -   [Debug](#debug)\n        -   [Performance](#performance)\n        -   [Hardened](#hardened)\n    -   [Managing bugs without compile-time safety](#managing-bugs-without-compile-time-safety)\n-   [Caveats](#caveats)\n    -   [Probabilistic techniques likely cannot stop attacks](#probabilistic-techniques-likely-cannot-stop-attacks)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Guaranteed memory safety programming models](#guaranteed-memory-safety-programming-models)\n        -   [Guaranteed compile-time memory safety using borrow checking](#guaranteed-compile-time-memory-safety-using-borrow-checking)\n        -   [Guaranteed run-time memory safety using reference counting](#guaranteed-run-time-memory-safety-using-reference-counting)\n        -   [Guaranteed run-time memory safety using garbage collection](#guaranteed-run-time-memory-safety-using-garbage-collection)\n    -   [Build mode names](#build-mode-names)\n    -   [Performance versus safety in the hardened build mode](#performance-versus-safety-in-the-hardened-build-mode)\n    -   [Add more build modes](#add-more-build-modes)\n\n<!-- tocstop -->\n\n## Background\n\nCarbon's goal is to provide\n[practical safety and testing mechanisms](../goals.md#practical-safety-and-testing-mechanisms).\n\n### What \"safety\" means in Carbon\n\nSafety is protection from software bugs, whether the protection is required by\nthe language or merely an implementation option. Application-specific logic\nerrors can be prevented by testing, but can lead to security vulnerabilities in\nproduction. Safety categories will be referred to using names based on the type\nof\n[security vulnerability](<https://en.wikipedia.org/wiki/Vulnerability_(computing)#Software_vulnerabilities>)\nthey protect against.\n\nA key subset of safety categories Carbon should address are:\n\n-   [**Memory safety**](https://en.wikipedia.org/wiki/Memory_safety) protects\n    against invalid memory accesses. Carbon uses\n    [two main subcategories](https://onlinelibrary.wiley.com/doi/full/10.1002/spe.2105)\n    for memory safety:\n\n    -   _Spatial_ memory safety protects against accessing an address that's out\n        of bounds for the source. This includes array boundaries, as well as\n        dereferencing invalid pointers such as uninitialized pointers, `NULL` in\n        C++, or manufactured pointer addresses.\n\n    -   _Temporal_ memory safety protects against accessing an address that has\n        been deallocated. This includes use-after-free for heap and\n        use-after-return for stack addresses.\n\n-   [**Type safety**](https://en.wikipedia.org/wiki/Type_safety) protects\n    against accessing valid memory with an incorrect type, also known as \"type\n    confusion\".\n\n-   [**Data race safety**](https://en.wikipedia.org/wiki/Race_condition#Data_race)\n    protects against racing memory access: when a thread accesses (read or\n    write) a memory location concurrently with a different writing thread and\n    without synchronizing.\n\n### Safety guarantees versus hardening\n\nIn providing safety, the underlying goal is to prevent attacks from turning a\n_logic error_ into a _security vulnerability_. The three ways of doing this can\nbe thought of in terms of how they prevent attacks:\n\n-   **Safety guarantees** prevent bugs. They offer a strong requirement that a\n    particular security vulnerability cannot exist. Compile-time safety checks\n    are always a safety guarantee, but safety guarantees may also be done at\n    runtime. For example:\n\n    -   At compile-time, range-based for loops offer a spatial safety guarantee\n        that out-of-bounds issues cannot exist in the absence of concurrent\n        modification of the sequence.\n\n    -   At runtime, garbage collected languages offer a temporal safety\n        guarantee because objects cannot be freed while they're still\n        accessible.\n\n-   **Error detection** checks for common logic errors at runtime. For example:\n\n    -   An array lookup function might offer spatial memory error detection by\n        verifying that the passed index is in-bounds.\n\n    -   A program can implement reference counting to detect a temporal memory\n        error by checking whether any references remain when memory is freed.\n\n-   **Safety hardening** mitigates bugs, typically by minimizing the feasibility\n    of an attack. For example:\n\n    -   [Control Flow Integrity (CFI)](https://en.wikipedia.org/wiki/Control-flow_integrity)\n        monitors for behavior which can subvert the program's control flow. In\n        [Clang](http://clang.llvm.org/docs/ControlFlowIntegrity.html), it is\n        optimized for use in release builds. Typically CFI analysis will only\n        detect a subset of attacks because it can't track each possible code\n        path separately. It should still reduce the feasibility of both spatial\n        memory, temporal memory, and type attacks.\n\n    -   [Memory tagging](https://llvm.org/devmtg/2018-10/slides/Serebryany-Stepanov-Tsyrklevich-Memory-Tagging-Slides-LLVM-2018.pdf)\n        makes each attempt at an invalid read or write operation have a high\n        probability of trapping, while still not detecting the underlying bug in\n        every case. Realistic attacks require many such operations, so memory\n        tagging may stop attacks in some environments. Alternatively, the trap\n        might be asynchronous, leaving only a tiny window of time prior to the\n        attack being detected and program terminated. These are probabilistic\n        hardening and reduces the feasibility of both spatial and temporal\n        memory attacks.\n\nUnder both error detection and safety hardening, even if a safety is protected,\nthe underlying bugs will still exist and will need to be fixed. For example,\nprogram termination could be used for a denial-of-service attack.\n\n## Philosophy\n\nCarbon's\n[practical safety and testing mechanisms](../goals.md#practical-safety-and-testing-mechanisms)\nwill emphasize guaranteed safety where feasible without creating barriers to\nCarbon's [other goals](../goals.md), particularly performance and\ninteroperability. This limits Carbon's options for guaranteed safety, and as a\nresult there will be more reliance upon error detection and safety hardening.\nThe language's design should incentivize safe programming, although it will not\nbe required.\n\nWhen writing code, Carbon developers should expect to receive safety without\nneeding to add safety annotations. Carbon will have optional safety annotations\nfor purposes such as optimizing safety checks or providing information that\nimproves coverage of safety checks.\n\nCarbon will favor compile-time safety checks because catching issues early will\nmake applications more reliable. Runtime checks, either error detection or\nsafety hardening, will be enabled where safety cannot be proven at compile-time.\n\nThere will be three high-level use cases or directions that Carbon addresses\nthrough different build modes that prioritize safety checks differently:\n\n-   A [debug](#debug) oriented build mode that prioritizes detecting bugs and\n    reporting errors helpfully.\n-   A [performance](#performance) oriented build mode that skips any dynamic\n    safety checks to reduce overhead.\n-   A [hardened](#hardened) oriented build mode that prioritizes ensuring\n    sufficient safety to prevent security vulnerabilities, although it may not\n    allow detecting all of the bugs.\n\nThese high level build modes may be tuned, either to select specific nuanced\napproach for achieving the high level goal, or to configure orthogonal\nconstraints such as whether to prioritize binary size or execution speed.\nHowever, there is a strong desire to avoid requiring more fundamental build\nmodes to achieve the necessary coverage of detecting bugs and shipping software.\nThese build modes are also not expected to be interchangeable or compatible with\neach other within a single executable -- they must be a global selection.\n\nAlthough expensive safety checks could be provided through additional build\nmodes, Carbon will favor safety checks that can be combined into these three\nbuild modes rather than adding more.\n\nOver time, safety should [evolve](../goals.md#software-and-language-evolution)\nusing a hybrid compile-time and runtime safety approach to eventually provide a\nsimilar level of safety to a language that puts more emphasis on guaranteed\nsafety, such as\n[Rust](#guaranteed-compile-time-memory-safety-using-borrow-checking). However,\nwhile Carbon may _encourage_ developers to modify code in support of more\nefficient safety checks, it will remain important to improve the safety of code\nfor developers who cannot invest into safety-specific code modifications.\n\n## Principles\n\n-   Safety must be\n    [easy to ramp-up with](../goals.md#code-that-is-easy-to-read-understand-and-write),\n    even if it means new developers don't receive the full safety that Carbon\n    can offer.\n\n    -   Developers should benefit from Carbon's safety without needing to learn\n        and apply Carbon-specific design patterns. Some safety should be enabled\n        by default, without safety-specific work, although some safety will\n        require work to opt in. Developers concerned with performance should\n        only need to disable safety in rare edge-cases.\n\n    -   Where there is a choice between safety approaches, the safe option\n        should be incentivized by making it equally easy or easier to use. If\n        there is a default, it should be the safe option. It should be\n        identifiable when the unsafe option is used. Incentives will prioritize,\n        in order:\n\n        1.  Guaranteed safety.\n        2.  Error detection.\n        3.  Safety hardening.\n        4.  Unsafe and unmitigated code.\n\n    -   Language design choices should favor more efficient implementations of\n        safety checks. They should also allow favor automation of testing and\n        fuzzing.\n\n-   Safety in Carbon must work with\n    [interoperable or migrated C++ code](../goals.md#interoperability-with-and-migration-from-existing-c-code),\n    so that C++ developers can readily take advantage of Carbon's improvements.\n\n    -   Safety mechanisms will ideally be designed to apply to automatically\n        migrated C++ code. Providing immediate safety improvements to Carbon\n        adopters will help motivate adoption.\n\n    -   In the other direction, safety mechanisms must not force manual\n        rewriting of C++ code in order to migrate, either by creating design\n        incompatibilities or performance degradations. Automated migration of\n        C++ code to Carbon must work for most developers, even if it forces\n        Carbon's safety design to take a different approach.\n\n    -   Carbon's safety should degrade gracefully when Carbon code calls C++\n        code, although this may require use of the Carbon toolchain to compile\n        the C++ code. Applications should be expected to use interoperability.\n        Although some safety features will be Carbon-specific, safety should not\n        stop at the language boundary.\n\n-   The rules for determining whether code will pass compile-time safety\n    checking should be articulable, documented, and easy to understand.\n\n    -   Compile-time safety checks should not change significantly across\n        different build modes. The purpose of the build modes is to determine\n        code generation.\n\n-   Each build mode will prioritize performance and safety differently:\n\n    -   The [debug build mode](#debug) will produce development-focused binaries\n        that prioritize fast iteration on code with safety checks that assist in\n        identification and debugging of errors.\n\n    -   The [performance build mode](#performance) will produce release-focused\n        binaries that prioritize performance over safety.\n\n    -   The [hardened build mode](#hardened) will produce release-focused\n        binaries that prioritize safety that is resistant to attacks at the cost\n        of performance.\n\n-   Safety checks should try to be identical across build modes.\n\n    -   There will be differences, typically due to performance overhead and\n        detection rate trade-offs of safety check algorithms.\n\n-   The number of build modes will be limited, and should be expected to remain\n    at the named three.\n\n    -   Most developers will use two build modes in their work: debug for\n        development, and either performance or hardened for releases.\n\n    -   It's important to focus on checks that are cheap enough to run as part\n        of normal development. Users are not expected to want to run additional\n        development build modes for additional sanitizers.\n\n    -   Limiting the number of build modes simplifies support for both Carbon\n        maintainers, who can focus on a more limited set of configurations, and\n        Carbon developers, who can easily choose which is better for their\n        use-case.\n\n-   Each distinct safety-related build mode (debug, performance, and hardened)\n    cannot be combined with others in the same binary.\n\n    -   Cross-binary interfaces will exist in Carbon, and will need to be used\n        by developers interested in combining libraries built under different\n        build modes.\n\n-   Although runtime safety checks should prevent logic errors from turning into\n    security vulnerabilities, the underlying logic errors will still be bugs.\n    For example, some safety checks would result in application termination;\n    this prevents execution of unexpected code and still needs to be fixed.\n\n-   Developers need a strong testing methodology to engineer correct software.\n    Carbon will encourage testing and then leverage it with the checking build\n    modes to find and fix bugs and vulnerabilities.\n\n## Details\n\n### Incremental work when safety requires work\n\nCarbon is prioritizing usability of the language, particularly minimizing\nretraining of C++ developers and easing migration of C++ codebases, over the\nkind of provable safety that some other languages pursue, particularly Rust.\n\nA key motivation of Carbon is to move C++ developers to a better, safer\nlanguage. However, if Carbon requires manually rewriting or redesigning C++ code\nin order to maintain performance, it creates additional pressure on C++\ndevelopers to learn and spend time on safety. Safety will often not be the top\npriority for developers; as a result, Carbon must be thoughtful about how and\nwhen it forces developers to think about safety.\n\nRelying on multiple build modes to provide safety should fit into normal\ndevelopment workflows. Carbon can also have features to enable additional\nsafety, so long as developers can start using Carbon in their applications\n_without_ learning new paradigms.\n\nWhere possible, safety checks shouldn't require work on the part of Carbon\ndevelopers. A safety check that requires no code edits or can be handled by\nautomated migration may be opt-out, as there is negligible cost to developers.\nOne which requires local code changes should be opt-in because costs will scale\nwith codebase size. Safety check approaches which would require substantial\nredesign by developers will be disfavored based on adoption cost, even if the\nalternative is a less-comprehensive approach.\n\n### Using build modes to manage safety checks\n\nCarbon will likely start in a state where most safety checks are done at\nruntime. However, runtime detection of safety violations remains expensive. In\norder to make as many safety checks as possible available to developers, Carbon\nwill adopt a strategy based on three build modes that target key use-cases.\n\n#### Debug\n\nThe debug build mode targets developers who are iterating on code and running\ntests. It will emphasize detection and debuggability, especially for safety\nissues.\n\nIt needs to perform well enough to be run frequently by developers, but will\nmake performance sacrifices to catch more safety issues. This mode should have\nruntime checks for the most common safety issues, but it can make trade-offs\nthat improve performance in exchange for less frequent, but still reliable,\ndetection. Developers should do most of their testing in this build mode.\n\nThe debug build mode will place a premium on the debuggability of safety\nviolations. Where safety checks rely on hardening instead of guaranteed safety,\nviolations should be detected with a high probability per single occurrence of\nthe bug. Detected bugs will be accompanied by a detailed diagnostic report to\nease classification and root cause identification.\n\n#### Performance\n\nThe performance build mode targets the typical application that wants high\nperformance from Carbon code, where performance considers processing time,\nmemory, and disk space. Trade-offs will be made that maximize the performance.\n\nOnly safety techniques that don't measurably impact application hot path\nperformance will be enabled by default. This is a very high bar, but is crucial\nfor meeting Carbon's performance goals, as well as allowing migration of\nexisting C++ systems which may not have been designed with Carbon's safety\nsemantics in mind.\n\n#### Hardened\n\nThe hardened build mode targets applications where developers want strong safety\nagainst attacks in exchange for worse performance. It will work to prevent\nattacks in ways that\n[attackers cannot work around](#probabilistic-techniques-likely-cannot-stop-attacks),\neven if it means using techniques that create significant performance costs.\n\n### Managing bugs without compile-time safety\n\nCarbon's reliance on runtime checks will allow developers to manage their\nsecurity risk. Developers will still need to reliably find and fix the\ninevitable bugs, including both safety violations and regular business logic\nbugs. The cornerstone of managing bugs will be strong testing methodologies,\nwith built-in support from Carbon.\n\nStrong testing is more than good test coverage. It means a combination of:\n\n-   Ensuring unsafe or risky operations and interfaces can easily be recognized\n    by developers.\n\n-   Using static analysis tools to detect common bugs, and ensuring they're\n    integrated into build and code review workflows. These could be viewed as\n    static testing of code.\n\n-   Writing good test coverage, including unit, integration, and system tests.\n\n-   Implementing coverage-directed fuzz testing to discover bugs outside of\n    manually authored test coverage, especially for interfaces handling\n    untrusted data. Fuzz testing is a robust way to catch bugs when APIs may be\n    used in ways developers don't consider.\n\n-   Running continuous integration, including automatic and continuous running\n    of these tests. The checked development build mode should be validated, as\n    well as any additional build modes necessary to cover different forms of\n    behavior checking.\n\n-   Easing automated testing and fuzzing through language features. For example,\n    if the language encourages value types and pure functions of some sort, they\n    can be automatically fuzzed.\n\nThese practices are necessary for reliable, large-scale software engineering.\nMaintaining correctness of business logic over time requires continuous and\nthorough testing. Without it, such software systems cannot be changed and\nevolved over time reliably. Carbon will reuse these practices in conjunction\nwith checking build modes to mitigate the limitations of Carbon's safety\nguarantees without imposing overhead on production systems.\n\nWhen a developer chooses to use Carbon, adhering to this kind of testing\nmethodology is essential for maintaining safety. As a consequence, Carbon's\necosystem, including the language, tools, and libraries, will need to directly\nwork to remove barriers and encourage the development of these methodologies.\n\nThe reliance on testing may make Carbon a poor choice in some environments; in\nenvironments where such testing rigor is infeasible, a language with a greater\ndegree of static checking may be better suited.\n\n## Caveats\n\n### Probabilistic techniques likely cannot stop attacks\n\nIt's expected that probabilistic techniques that can be applied at the language\nlevel are attackable through a variety of techniques:\n\n-   The attacker might be able to attack repeatedly until it gets through.\n-   The attacker may be able to determine when the attack would be detected and\n    only run the attack when it would not be.\n-   The attacker might be able control the test condition to make detection much\n    less likely or avoid detection completely. For example, if detection is\n    based on the last 4 bits of a memory address, an attacker may be able to\n    generate memory allocations, viewing the address and only attacking when\n    there's a collision.\n\nHardware vulnerabilities may make these attacks easier than they might otherwise\nappear. Future hardware vulnerabilities are difficult to predict.\n\nNote this statement focuses on what can be applied to the language level. Using\na secure hash algorithm, such as SHA256, may be used to offer probabilistic\ndefense in other situations. However, the overhead of a secure hash algorithm's\ncalculation is significant in the context of most things that Carbon may do at\nthe language level.\n\nCombining these issues, although it may seem like a probabilistic safety check\ncould be proven to reliably detect attackers, it's likely infeasible to do so.\nFor the various build modes, this means:\n\n-   The debug build mode will not typically be accessible to attackers, so where\n    a probabilistic technique provides a better developer experience, it will be\n    preferred.\n-   The performance build mode will often avoid safety checks in order to reach\n    peak performance. As a consequence, even the weak protection of a\n    probabilistic safety check may be used in order to provide _some_\n    protection.\n-   The hardened build mode will prefer non-probabilistic techniques that\n    _cannot_ be attacked.\n\n## Alternatives considered\n\n### Guaranteed memory safety programming models\n\nMultiple approaches that would offer guaranteed memory safety have been\nconsidered, mainly based on other languages which offer related approaches.\nCarbon will likely rely more on error detection and hardening because of what\nthe models would mean for Carbon's performance and C++ migration language goals.\n\n#### Guaranteed compile-time memory safety using borrow checking\n\nRust offers a good example of an approach for compile-time safety based on\nborrow checking, which provides guaranteed safety. For code which can't\nimplement borrow checking, runtime safety using reference counting is available\nand provides reliable error detection. This approach still allows for\n[`unsafe` blocks](https://doc.rust-lang.org/rust-by-example/unsafe.html), as\nwell as types that offer runtime safety while wrapping `unsafe` interfaces.\n\nCarbon could use a similar approach for guaranteed safety by default.\n\nAdvantages:\n\n-   Guaranteed safety, including against data races, is provided for the\n    binaries.\n    -   The emphasis on compile-time safety limits the scope of the runtime\n        memory safety costs.\n    -   With Rust, there is early evidence that there's a significant impact in\n        reducing bugs generally.\n-   Imitating Rust's techniques would allow building on the huge work of the\n    Rust community, reducing the risks of implementing similar in Carbon.\n-   Careful use of narrow `unsafe` escape hatches can be effectively\n    encapsulated behind otherwise safe APIs.\n\nDisadvantages:\n\n-   Rust's approach to compile-time safety requires use of\n    [design patterns and idioms](https://github.com/rust-unofficial/patterns)\n    that are substantially different from C++.\n    -   Conversion of C++ code to Rust results in either rewrites of code, or\n        use of runtime safety checks that impair performance.\n    -   Requires fully modeling lifetime and exclusivity in the type system.\n    -   Data structures must be redesigned to avoid sharing mutable state.\n    -   Increases complexity of node and pointer based data structures, such as\n        linked lists.\n-   Imitating Rust's techniques may prove insufficient for achieving Carbon's\n    [compiler performance goals](../goals.md#fast-and-scalable-development).\n    Rust compilation performance suggests its borrow checking performance is\n    slow, although it's difficult to determine how significant this is or\n    whether it could be improved.\n    -   The Rust compiler\n        [is slow](https://pingcap.com/blog/rust-compilation-model-calamity),\n        although\n        [much has been done to improve it](https://blog.mozilla.org/nnethercote/2020/09/08/how-to-speed-up-the-rust-compiler-one-last-time/).\n    -   Details of type checking, particularly requiring parsing of function\n        bodies to type check signatures, as well as wide use of\n        [monomorphization](https://doc.rust-lang.org/book/ch10-01-syntax.html)\n        are likely significant contributors to Rust compilation performance.\n    -   LLVM codegen is also a significant cost for Rust compilation\n        performance.\n    -   With\n        [Fuchsia](https://fuchsia.dev/fuchsia-src/development/languages/rust) as\n        an example, in December 2020, borrow checking and type checking combined\n        account for around 10% of Rust compile CPU time, or 25% of end-to-end\n        compile time. The current cost of borrow checking is obscured both\n        because of the combination with type checking, and because Fuchsia\n        disables some compiler parallelization due to build system\n        incompatibility.\n-   The complexity of using Rust's compile-time safety may incentivize\n    unnecessary runtime checking of safety properties. For example, using\n    [`RefCell`](https://doc.rust-lang.org/std/cell/struct.RefCell.html) or\n    [`Rc`](https://doc.rust-lang.org/std/rc/struct.Rc.html) to avoid changing\n    designs to fit compile-time safety models.\n-   Some of the most essential safety tools that ease the ergonomic burden of\n    the Rust-style lifetime model (`Rc`) introduce _semantic_ differences that\n    cannot then be eliminated in a context where performance is the dominant\n    priority.\n\nIt's possible to modify the Rust model several ways in order to reduce the\nburden on C++ developers:\n\n-   Don't offer safety guarantees for data races, eliminating `RefCell`.\n    -   This would likely not avoid the need for `Rc` or `Arc`, and wouldn't\n        substantially reduce the complexity.\n-   Require manual destruction of `Rc`, allowing safety checks to be disabled in\n    the performance build mode to eliminate overhead.\n    -   This still requires redesigning C++ code to take advantage of `Rc`.\n    -   The possibility of incorrect manual destruction means that the safety\n        issue is being turned into a bug, which means it is hardening and no\n        longer a safety guarantee.\n    -   Carbon can provide equivalent hardening through techniques such as\n        [MarkUs](https://www.cl.cam.ac.uk/~tmj32/papers/docs/ainsworth20-sp.pdf),\n        which does not require redesigning C++ code.\n\nOverall, Carbon is making a compromise around safety in order to give a path for\nC++ to evolve. C++ developers must be comfortable migrating their codebases, and\nable to do so in a largely automated manner. In order to achieve automated\nmigration, Carbon cannot require fundamental redesigns of migrated C++ code.\nWhile a migration tool could in theory mark all migrated code as `unsafe`,\nCarbon should use a safety strategy that degrades gracefully and offers\nimprovements for C++ code, whether migrated or not.\n\nThat does not mean Carbon will never adopt guaranteed safety by default, only\nthat performance and migration of C++ code takes priority, and any design will\nneed to be considered in the context of other goals. It should still be possible\nto adopt guaranteed safety later, although it will require identifying a\nmigration path.\n\n#### Guaranteed run-time memory safety using reference counting\n\n[Reference counting](https://en.wikipedia.org/wiki/Reference_counting) is a\ncommon memory safety model, with Swift as a popular example.\n\nAdvantages:\n\n-   Simple model for safety, particularly as compared with Rust.\n-   Safe for all of the most common and important classes of memory safety bugs.\n\nDisadvantages:\n\n-   Safety based on reference counting introduces significant performance costs,\n    and tools for controlling these costs are difficult.\n    -   Safety based on garbage collection has less direct performance overhead,\n        but has a greater unpredictability of performance.\n-   Significant design differences versus C++ still result, as the distinction\n    between value types and \"class types\" becomes extremely important.\n    -   Class types are held by a reference counted pointer and are thus\n        lifetime safe.\n\nIn order to mitigate the performance overhead, Swift does have a proposal to add\nan option for unique ownership, although the specifics are not designed yet. The\nunique ownership approach is expected to require unowned and unsafe access, so\nit would not considered to improve the safety trade-offs.\n\nSwift was designated by Apple as the replacement for Objective-C. The safety\nversus performance trade-offs that it makes fit Apple's priorities. Carbon's\nperformance goals should lead to different trade-off decisions with a higher\npriority on peak performance, which effectively rules out broad use of reference\ncounting.\n\n#### Guaranteed run-time memory safety using garbage collection\n\n[Garbage collection](<https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)>)\nis a common memory safety model, with Java as a popular example.\n\nAdvantages:\n\n-   This approach is among the most robust and well studied models, with decades\n    of practical usage and analysis for security properties.\n-   Extremely suitable for efficient implementation on top of a virtual machine,\n    such as the JVM.\n\nDisadvantages:\n\n-   Extremely high complexity to fully understand the implications of complex\n    cases like data races.\n-   Performance overhead is significant in terms of what Carbon would like to\n    consider.\n    -   Garbage collection remains a difficult performance problem, even for the\n        JVM and its extensive optimizations.\n    -   The complexity of the implementation makes it difficult to _predict_\n        performance; for example, Java applications experience latency spikes\n        when garbage collection runs.\n\nJava is a good choice for many applications, but Carbon is working to focus on a\nset of performance priorities that would be difficult to achieve with a garbage\ncollector.\n\n### Build mode names\n\nThe build mode concepts are difficult to name. Other names that were evaluated,\nand are ultimately similar, are:\n\n-   \"Debug\" is a common term for the intended use of this build mode. Also,\n    tooling including Visual Studio frequently uses the debug term for\n    describing similar.\n\n    -   \"Development\" was also considered, but this term is less specific and\n        would be better for describing all non-release builds together. For\n        example, a \"fast build\" mode might be added that disables safety checks\n        to improve iteration time, like might be controlled by way of C++'s\n        `NDEBUG` option.\n\n-   \"Performance\" aligns with the phrasing of the language performance goal.\n\n    -   \"Optimized\" implies that other modes would not be fully optimized, but\n        hardened should be optimized.\n\n    -   \"Fast\" would suggest that speed is the only aspect of performance being\n        optimizing for, but \"performance\" also optimizes for memory usage and\n        binary size.\n\n-   \"Hardened\" is the choice for succinctly describing the additional safety\n    measures that will be taken, and is a well-known term in the safety space.\n    It could be incorrectly inferred that \"performance\" has no hardening, but\n    the preference is to clearly indicate the priority of the \"hardened\" build\n    mode.\n\n    -   \"Safe\" implies something closer to guaranteed safety. However, safety\n        bugs should be expected to result in program termination, which can\n        still be used in other attacks, such as Denial-of-Service.\n\n    -   \"Mitigated\" is an overloaded term, and it may not be succinctly clear\n        that it's about security mitigations.\n\n-   Some terms which were considered and don't fit well into the above groups\n    are:\n\n    -   \"Release\" is avoided because both \"performance\" and \"hardened\" could be\n        considered to be \"release\" build modes.\n\nThe names \"performance\" and \"hardened\" may lead to misinterpretations, with some\ndevelopers who should use \"hardened\" using \"performance\" because they are\nworried about giving up too much performance, and the other way around. The\nterms try to balance the utility of well-known terminology with the succinctness\nof a short phrase for build modes, and that limits the expressivity. Some\nconfusion is expected, and documentation as well as real-world experience (for\nexample, a developer who cares about latency benchmarking both builds) should be\nexpected to help mitigate mix-ups.\n\n### Performance versus safety in the hardened build mode\n\nThe performance cost of safety techniques are expected to be non-linear with\nrespect to detection rates. For example, a particular vulnerability such as heap\nuse-after-free may be detectable with 99% accuracy at 20% performance cost, but\n100% accuracy at 50% performance cost. At present, build modes should be\nexpected to evaluate such a scenario as:\n\n-   The debug build mode would choose the 99% accurate approach.\n    -   Detecting safety issues is valuable for debugging.\n    -   The probabilistic detection rate won't meaningfully affect accuracy of\n        tests.\n    -   The lower performance cost improves developer velocity.\n-   The performance build mode would decline detection.\n    -   Safety checks with a measurable performance cost should be declined.\n-   The hardened build mode would choose the 100% accurate approach.\n    -   Safety must be non-probabilistic in order to reliably prevent attacks.\n    -   Significant performance hits are acceptable.\n    -   This means the hardened build mode may be slower than the debug build\n        mode.\n\nIn order to achieve better performance, the hardened build mode could make\ntrade-offs closer to the debug build mode. Rather than relying on\nnon-probabilistic techniques, it could instead offer a probability-based chance\nof detecting a given attack.\n\nAdvantages:\n\n-   Probabilistic safety should come at lower performance cost (including CPU,\n    memory, and disk space).\n    -   This will sometimes be significant, and as a result of multiple checks,\n        could result in the hardened build mode being 50% slower than the\n        performance build mode instead of being 200% slower.\n\nDisadvantages:\n\n-   [Probabilistic techniques likely cannot stop attacks](#probabilistic-techniques-likely-cannot-stop-attacks).\n    -   Attackers may be able to repeat attacks until they succeed.\n    -   The variables upon which the probability is based, such as memory\n        addresses, may be manipulable by the attacker. As a consequence, a\n        determined attacker may be able to manipulate probabilities and not even\n        be detected.\n\nAlthough performance is\n[Carbon's top goal](../goals.md#language-goals-and-priorities), the hardened\nbuild mode exists to satisfy developers and environments that value safety more\nthan performance. The hardened build mode will rely on non-probabilistic safety\nat significant performance cost because other approaches will be insufficient to\nguard against determined attackers.\n\n### Add more build modes\n\nMore build modes could be added to this principle, or the principle could\nencourage the idea that specific designs may add more.\n\nTo explain why three build modes:\n\n-   The concept of debug and release (sometimes called opt) are common. For\n    example, in\n    [Visual Studio](https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-debug-and-release-configurations?view=vs-2019).\n    In Carbon, this could be considered to translate to the \"debug\" and\n    \"performance\" build modes by default.\n\n-   The hardened build mode is added in order to emphasize security. Although\n    hardened could be implemented as a set of options passed to the standard\n    release build mode, the preference is to focus on it as an important\n    feature.\n\nAn example of why another build mode may be needed is\n[ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html), which is\nnoted as having 5-15x slowdown and 5-10x memory overhead. This is infeasible for\nnormal use, but could be useful for some users in a separate build mode. A\ntrade-off that's possible for Carbon is instead using an approach similar to\n[KCSAN](https://github.com/google/ktsan/wiki/KCSAN) which offers relatively\ninexpensive but lower-probability race detection.\n\nAlthough options to these build modes may be supported to customize deployments,\nthe preference is to focus on a small set and make them behave well. For\nexample, if a separate build mode is added for ThreadSanitizer, it should be\nconsidered a temporary solution until it can be merged into the debug build\nmode.\n\nAdvantages:\n\n-   Grants more flexibility for using build modes as a solution to problems.\n    -   With safety checks, this would allow providing safety checks that are\n        high overhead but also high detection rate as separate build modes.\n    -   With other systems, there could be non-safety performance versus\n        behavior trade-offs.\n\nDisadvantages:\n\n-   Having standard modes simplifies validation of interactions between various\n    safety checks.\n    -   Safety is the only reason that's been considered for adding build modes.\n-   As more build modes are added, the chance of developers being confused and\n    choosing the wrong build mode for their application increases.\n\nAny long-term additions to the set of build modes will need to update this\nprinciple, raising the visibility and requiring more consideration of such an\naddition. If build modes are added for non-safety-related reasons, this may lead\nto moving build modes out of the safety strategy.\n\n**Experiment**: This can be considered an experiment. Carbon may eventually add\nmore than the initial three build modes, although the reluctance to add more is\nlikely to remain.\n"
  },
  {
    "path": "docs/project/principles/static_open_extension.md",
    "content": "# Principle: One static open extension mechanism\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Background](#background)\n-   [Principle](#principle)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Background\n\nIn C++, a single function may be overloaded with definitions in multiple files.\nThe [ADL](https://en.wikipedia.org/wiki/Argument-dependent_name_lookup) name\nlookup rule even allows an unqualified call to resolve to functions defined in\ndifferent namespaces. These rules are used to define extension points with\nstatic dispatch for operator overloading and functions like\n[`swap`](https://www.cplusplus.com/reference/algorithm/swap/).\n\nNothing in C++ restricts the signatures of function overloads. This means that\nif overloading is used as an extension point to define an operation for a\nvariety of types, there is no way to type check generic code that tries to\ninvoke that operation over those types.\n\nFurther, in C++, all non-member functions can be found in this way, if they are\ndeclared in the same namespace as a type that could be associated with an\nargument list in a call. There is no straightforward opt-out mechanism in a\nfunction declaration, and while there are opt-out mechanisms at call sites, they\nare rarely used. As a consequence, many non-member functions with the same name\ncan form part of an overload set, even if they provide unrelated functionality,\nand there is no indication in the code of which functions in different\nnamespaces are intended to expose the same capability.\n\n## Principle\n\nIn Carbon, [`interface`s](/docs/design/generics/overview.md) are the only static\nopen extension mechanism.\n\nEach type may define its own implementation of each interface. Generic code can\nbe written that works with any type implementing the interface. That code can be\ntype checked independent of which type the generic code is instantiated with by\nusing the fact that the interface specifies the signatures of the calls.\n\nTo keep the language simple, this is the only static open extension mechanism in\nCarbon. This means that function overloading is limited in Carbon to only\nsignatures defined together in the same library. It also means that to\ninteroperate with C++, the operators and `swap` need to have corresponding\ninterfaces on the Carbon side.\n\nThe main advantage of interfaces as an open extension mechanism over open\noverloading is allowing generics to be type checked separately. In addition,\nthey are less [context sensitive](low_context_sensitivity.md). Generics are\n[coherent](/docs/design/generics/terminology.md#coherence), while open function\noverloading can resolve names differently depending on what is imported. Closed\noverloading in Carbon also simplifies what gets exported to C++ from Carbon.\nInterface implementations express intent by being explicit, in contrast to how\nadding a function to a cross-file overload set can be accidental.\n\nInterfaces provide an way to group functions together, and express the\nconstraint that all of the functions in the group are implemented. Consider a\nrandom-access iterator, which has a number of methods. If a C++ template\nfunction only accesses some of those methods which happens to match the subset\ndefined for a type, the code will work temporarily but fail later when the code\nis changed to use a different subset.\n\nThis helps achieve the Carbon Goal of\n[code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n\n## Alternatives considered\n\nAnother approach to operator overloading is to use methods with a specific name.\nIn C++ these start with the\n[`operator` keyword](https://en.cppreference.com/w/cpp/language/operators).\n[Python uses method with names starting and ending with double underscores](https://docs.python.org/3/reference/datamodel.html#special-method-names).\nInterfaces are more flexible about where implementations may be defined. For\nexample, with special method names, `+` on a `Vector(T)` class could only be\ndefined as part of the `Vector(T)` definition. With interfaces, additionally `+`\nfor `Vector(MyType)` could be implemented with `MyType`. C++ provides this\nflexibility by also permitting non-method operator overloads, but this brings\nwith it the cost of selecting a best-matching operator from a potentially very\nlarge open overload set.\n"
  },
  {
    "path": "docs/project/principles/success_criteria.md",
    "content": "# Principle: Success criteria\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Principle](#principle)\n-   [Applications of these principles](#applications-of-these-principles)\n    -   [Modern OS platforms, hardware architectures, and environments](#modern-os-platforms-hardware-architectures-and-environments)\n        -   [OS platforms](#os-platforms)\n        -   [Hardware architectures](#hardware-architectures)\n        -   [Historical platforms](#historical-platforms)\n    -   [Interoperability with and migration from existing C++ code](#interoperability-with-and-migration-from-existing-c-code)\n        -   [Migration tooling](#migration-tooling)\n\n<!-- tocstop -->\n\n## Principle\n\nCarbon's goals set a high-level path for where Carbon should head. However,\ngiven priorities, it's not always clear how specific features or details may end\nup being evaluated.\n\nCarbon's success criteria are specific, measurable, key results that we expect\nto use to see how Carbon is doing against its goals. Success criteria will be\nconsidered as part of Carbon's [roadmap process](../roadmap_process.md), missing\nthem will be considered significant, and extra scrutiny will be applied on\nproposals that would require diminishing them. These success criteria are not\nexhaustive, but they are a bar that we aim to _exceed_.\n\n## Applications of these principles\n\n> TODO: Add more metrics for various goals.\n\n### Modern OS platforms, hardware architectures, and environments\n\n> References:\n> [goal](../goals.md#modern-os-platforms-hardware-architectures-and-environments)\n\nThis should not be considered an exhaustive list of important platforms.\n\n#### OS platforms\n\nOur priority OS platforms are modern versions of:\n\n-   Linux, including common distributions, Android and ChromeOS\n-   FreeBSD\n-   Windows\n-   macOS and iOS\n-   Fuchsia\n-   WebAssembly\n-   Bare metal\n\n#### Hardware architectures\n\nWe expect to prioritize 64-bit little endian hardware, including:\n\n-   x86-64\n-   AArch64, also known as ARM 64-bit\n-   PPC64LE, also known as Power ISA, 64-bit, Little Endian\n-   RV64I, also known as RISC-V 64-bit\n\nWe believe Carbon should strive to support some GPUs, other restricted\ncomputational hardware and environments, and embedded environments. While this\nshould absolutely include future and emerging hardware and platforms, those\nshouldn't disproportionately shape the fundamental library and language design\nwhile they remain relatively new and rapidly evolving.\n\n#### Historical platforms\n\nExample historical platforms that we will not prioritize support for are:\n\n-   Byte sizes other than 8 bits, or non-power-of-two word sizes.\n-   Source code encodings other than UTF-8.\n-   Big- or mixed-endian, at least for computation; accessing encoded data\n    remains useful.\n-   Non-2's-complement integer formats.\n-   Non-IEEE 754 binary floating point format and semantics for default single-\n    and double-precision floating point types.\n-   Source code in file systems that don’t support file extensions or nested\n    directories.\n\n### Interoperability with and migration from existing C++ code\n\n> References:\n> [goal](../goals.md#interoperability-with-and-migration-from-existing-c-code)\n\n#### Migration tooling\n\nMigrations must be mostly automatic. To that end, given an arbitrary large\ncodebase following best practices, we aim to have less than 2% of files require\nhuman interaction.\n\nThis criterion includes:\n\n-   Addressing performance bugs unique to Carbon, introduced by migration\n    tooling.\n-   Converting complex code which migration tooling does not handle.\n\nThis criterion does not include:\n\n-   Cleaning up coding style to idiomatic Carbon.\n    -   For example, heavy use of C++ preprocessor macros may result in expanded\n        code where there is no equivalent Carbon metaprogramming construct.\n"
  },
  {
    "path": "docs/project/pull_request_workflow.md",
    "content": "# Trunk-based pull-request GitHub workflow\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Trunk based development](#trunk-based-development)\n    -   [Green tests](#green-tests)\n-   [Always use pull requests (with review) rather than pushing directly](#always-use-pull-requests-with-review-rather-than-pushing-directly)\n-   [Small, incremental changes](#small-incremental-changes)\n-   [Linear history](#linear-history)\n-   [Merging a pull request](#merging-a-pull-request)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon repositories follow a few basic principles:\n\n-   Development directly on the `trunk` branch and\n    [revert to green](#green-tests).\n-   Always use pull requests, rather than pushing directly.\n-   Changes should be small, incremental, and review-optimized.\n-   Preserve linear history by\n    [squashing](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-request-merges#squash-and-merge-your-pull-request-commits)\n    pull requests rather than using unsquashed merge commits.\n\nThese principles try to optimize for several different uses or activities with\nversion control:\n\n-   Continuous integration and bisection to identify failures and revert to\n    green.\n-   Code review both at the time of commit and follow-up review after commit.\n-   Understanding how things evolve over time, which can manifest in different\n    ways:\n    -   When were things introduced?\n    -   How does the main branch and project evolve over time?\n    -   How was a bug or surprising thing introduced?\n\nNote that this document focuses on the mechanical workflow and branch\nmanagement. Details of the code review process are in their own\n[document](code_review.md).\n\n## Trunk based development\n\nWe work in a simple\n[trunk-based development](https://trunkbaseddevelopment.com/) model. This means\nall development activity takes place on a single common `trunk` branch in the\nrepository (our default branch). We focus on\n[small, incremental changes](#small-incremental-changes) rather than feature\nbranches or the \"scaled\" variations of this workflow.\n\n### Green tests\n\nThe `trunk` branch should always stay \"green\". That means that if tests fail or\nif we discover bugs or errors, we revert to a \"green\" state by default, where\nthe failure or bug is no longer present. Fixing forward is fine if that will be\ncomparably fast and efficient. The goal isn't to dogmatically avoid fixing\nforward, but to prioritize getting back to green quickly. We hope to eventually\ntool this through automatic continuous-integration powered submit queues, but\neven those can fail and the principle remains.\n\n## Always use pull requests (with review) rather than pushing directly\n\nWe want to ensure that changes to Carbon are always reviewed, and the simplest\nway to do this is to consistently follow a pull request workflow. Even if the\nchange seems trivial, still go through a pull request -- it'll likely be trivial\nto review. Always wait for someone else to review your pull request rather than\njust merging it, even if you have permission to do so.\n\nOur GitHub repositories are configured to require pull requests and review\nbefore they are merged, so this rule is enforced automatically.\n\n## Small, incremental changes\n\nDeveloping in small, incremental changes improves code review time, continuous\nintegration, and bisection. This means we typically squash pull requests into a\nsingle commit when landing. We use two fundamental guides for deciding how to\nsplit up pull requests:\n\n1. Ensure that each pull request builds and passes any tests cleanly when you\n   request review and when it lands. This will ensure bisection and continuous\n   integration can effectively process them.\n\n2. Without violating the first point, try to get each pull request to be \"just\n   right\": not too big, not too small. You don't want to separate a pattern of\n   tightly related changes into separate requests when they're easier to review\n   as a set or batch, and you don't want to bundle unrelated changes together.\n   Typically you should try to keep the pull request as small as you can without\n   breaking apart tightly coupled changes. However, listen to your code reviewer\n   if they ask to split things up or combine them.\n\nWhile the default is to squash pull requests into a single commit, _during_ the\nreview you typically want to leave the development history undisturbed until the\nend so that comments on any particular increment aren't lost. We typically use\nthe GitHub squash-and-merge functionality to land things.\n\n## Linear history\n\nWe want the history of the `trunk` branch of each repository to be as simple and\neasy to understand as possible. While Git has strong support for managing\ncomplex history and merge patterns, we find understanding and reasoning about\nthe history -- especially for humans -- to be at least somewhat simplified by\nsticking to a linear progression. As a consequence, pull requests are squashed\nwhen merging them.\n\n## Merging a pull request\n\nOnce approved, and even if all checks have not finished running yet, a pull\nrequest can be added to a\n[merge queue](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue#about-merge-queues).\nWhen queued, and after all pull request checks pass, this will automatically\ncreate a squashed version of the commits in a temporary branch on top of `trunk`\nand any previously queued merge. Checks run on this commit help to ensure that\nthe `trunk` stays \"green\" in presence of conflicting merges.\n\nAfter the merge queue checks pass, the `trunk` branch pointer is updated to\ninclude the now merged changeset. The resulting commit title and description\nwill match exactly those of the pull request, so it is important to set those\nappropriately before merging. Co-authors are preserved by this operation. If a\nfailure happens at any point, the merge fails, with both `trunk` and the pull\nrequest branch kept in their original state.\n"
  },
  {
    "path": "docs/project/roadmap.md",
    "content": "# Roadmap\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Objectives for 2025: demo of C++ interop and design of memory safety](#objectives-for-2025-demo-of-c-interop-and-design-of-memory-safety)\n-   [Key results in 2025](#key-results-in-2025)\n    -   [Access most non-template C++ APIs in Carbon](#access-most-non-template-c-apis-in-carbon)\n    -   [Access non-generic Carbon APIs in C++](#access-non-generic-carbon-apis-in-c)\n    -   [Detailed safety strategy update, including expected tradeoffs and prioritization](#detailed-safety-strategy-update-including-expected-tradeoffs-and-prioritization)\n    -   [Design for compile-time temporal and mutation memory safety](#design-for-compile-time-temporal-and-mutation-memory-safety)\n    -   [Give talks at 2-3 conferences about Carbon topics, expanding our audience](#give-talks-at-2-3-conferences-about-carbon-topics-expanding-our-audience)\n-   [Beyond 2025](#beyond-2025)\n    -   [Potential 2026 goals: ship a working 0.1 language for evaluation](#potential-2026-goals-ship-a-working-01-language-for-evaluation)\n    -   [Potential 2027-2028 goals: finish 0.2 language, stop experimenting](#potential-2027-2028-goals-finish-02-language-stop-experimenting)\n    -   [Potential goals _beyond_ 2028: ship 1.0 language & organization](#potential-goals-beyond-2028-ship-10-language--organization)\n\n<!-- tocstop -->\n\n## Objectives for 2025: demo of C++ interop and design of memory safety\n\nWe have two areas of focus for 2025:\n\n1. Get a major chunk of our C++ interop working to the point where we can\n   demonstrate it in realistic scenarios.\n2. Build a concrete and specific design for memory safety in Carbon.\n\nWe will scope the first one to non-template C++ APIs, and prioritize accessing\nC++ APIs from Carbon. This still will require major progress on the\nimplementation of all the relevant Carbon features, and even design in some\ncases.\n\nThe second is focused on moving from a vague direction of \"we will have a memory\nsafe dialect of Carbon that is a reasonable default\", to a specific and concrete\ndesign. We want to be able to illustrate exactly what it will look like to\nmigrate existing unsafe C++ to Carbon (possibly at large scale), and then begin\nincrementally adopting and integrating memory safety into that otherwise unsafe\nCarbon codebase.\n\nAchieving these should dramatically reduce the risk around Carbon, especially in\nenvironments where memory safety is increasingly a necessary part of any future\nsoftware development plans. They will also move the project much closer to our\n0.1 milestone.\n\n## Key results in 2025\n\n### Access most non-template C++ APIs in Carbon\n\nBeyond excluding templates, this excludes coroutines, and any aspects that\nrequire accessing Carbon types in C++ such as templates with Carbon types as\ntemplate arguments.\n\nThis result includes both the implementation in the toolchain and the underlying\ndesign underpinning this implementation. It also includes implementation and\ndesign work on necessary Carbon language features that underpin the interop\nprovided.\n\n### Access non-generic Carbon APIs in C++\n\nThis excludes generics to make the scope more tractable, but this remains a bit\nof a stretch goal for 2025, and how much progress we make will depend on how\nmany unexpected difficulties we encounter getting the other direction to work,\nand any other delays.\n\n### Detailed safety strategy update, including expected tradeoffs and prioritization\n\nWe haven't been focused on the safe side of Carbon for several years and will\nneed to refresh our safety strategy to reflect the current plan, as well as\nexpanding and making it more detailed to support building our initial memory\nsafety design.\n\n### Design for compile-time temporal and mutation memory safety\n\nWe expect our memory safety story for temporal memory safety to at the highest\nlevel follow the direction of Rust, using the type system to ensure compile-time\nguarantees of safety without the runtime overhead of garbage collection or\nreference counting. We want our design here to cover both temporal and mutation\nsafety. While the exact level of safety and the tradeoffs we're willing to\naccept will be part of updating our safety strategy, at a fundamental level we\nneed to fully address the security requirements on memory safety, much like\nother modern languages including Swift, Kotlin, Go, or Rust. A significantly\nlower security bar won't be acceptable for the expected users of safe Carbon.\n\n### Give talks at 2-3 conferences about Carbon topics, expanding our audience\n\nBeyond continuing to share details about Carbon with the open source and C++\ncommunities, we also want to expand our audience reach in 2025. We want to give\ntalks at a conference in the Asia/Pacific region, and at a conference in the\nbroader open source world beyond LLVM and C++ specific conferences.\n\n## Beyond 2025\n\nLonger term goals are hard to pin down and always subject to change, but we want\nto give an idea of what kinds of things are expected at a high level further out\nin order to illustrate how the goals and priorities we have in 2025 feed into\nsubsequent years.\n\n### Potential 2026 goals: ship a working [0.1 language] for evaluation\n\n[0.1 language]:\n    /docs/project/milestones.md#milestone-01-a-minimum-viable-product-mvp-for-evaluation\n\nBecause we are adding a design for memory safety to our 0.1 milestone, we are\nalso expecting to push it out by at least a year. Shipping 0.1 in 2026 will be a\nvery ambitious goal and may not be possible, but the end of 2026 is now the\n_soonest_ that 0.1 could realistically be ready to ship.\n\nWe expect that once we reach this milestone the community will be able to start\nrealistically evaluating Carbon as a C++ successor language. Of course, this\nevaluation will take some time.\n\n### Potential 2027-2028 goals: finish [0.2 language], stop experimenting\n\n[0.2 language]:\n    /docs/project/milestones.md#milestone-02-feature-complete-product-for-evaluation\n\nOnce Carbon is moving quickly and getting public feedback, we should be able to\nconclude the experiment. We should know if this is the right direction for\nmoving C++ forward for a large enough portion of the industry and community, and\nwhether the value proposition of this direction outweighs the cost.\n\nHowever, there will still be a lot of work left to make Carbon into a production\nquality language, even if the experiment concludes successfully.\n\nSome concrete goals that might show up in this time frame:\n\n-   Self-hosting toolchain, including sufficient Carbon standard library\n    support.\n-   Expand design of standard library to include, at least directionally,\n    critical and complex areas. For example: concurrency/parallelism and\n    networking/IO.\n-   Migration tooling sufficient to use with real-world libraries and systems.\n    This might be used to help with self-hosting Carbon, as well as by initial\n    early adopters evaluating Carbon.\n-   Create a foundation or similar organization to manage the Carbon project,\n    separate from any corporate entities that fund work on Carbon.\n\n### Potential goals _beyond_ 2028: ship [1.0 language] & organization\n\n[1.0 language]:\n    /docs/project/milestones.md#milestone-10-no-longer-an-experiment-usable-in-production\n\nA major milestone will be the first version of a production language. We also\nplan to finish transferring all governance of Carbon to an independent open\nsource organization at that point. However, we won't know what a more realistic\nor clear schedule for these milestones will be until we get closer.\n\nGoals in this time frame will expand to encompass the broader ecosystem of the\nlanguage:\n\n-   End-to-end developer tooling and experience.\n-   Teaching and training material.\n-   Package management.\n-   Etc.\n"
  },
  {
    "path": "docs/project/roadmap_process.md",
    "content": "# Roadmap process\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nCarbon has an annual roadmap to align and focus the work of the teams and\ncommunity. Teams will need to defer work on Carbon that may be good and make\nsense but doesn't align with the current focus and plan of the project.\n\nThe core team will draft proposed roadmaps each year, going through the standard\nproposal review process. Objectives and key results will be based on\n[goals](goals.md), [success criteria](principles/success_criteria.md), and\ntactical features.\n\nIt is expected that the core team will provide a draft decision and enter\ndecision review first thing at the beginning of the year, concluding in an\naccepted plan of record for the overarching direction of the project for that\nyear. Subteams may optionally follow a similar practice as needed for their area\nof Carbon.\n\nThis roadmap is not strictly binding and does not need to cover everything that\nwill happen. However, it can and should be used by teams to defer some proposals\nas needed to focus on proposals aligned with the current roadmap.\n\nThe roadmap is also subject to change, just as any other document, with a fresh\nproposal. The core team should critically evaluate the direction and any new\ninformation on a quarterly basis during the initial phase of the project and\nadjust the roadmap as needed to stay focused on the most important things.\n"
  },
  {
    "path": "docs/project/teams/conduct_team.md",
    "content": "# Conduct Team\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis team owns and drives the project's Code of Conduct, questions, concerns,\nand conduct reports. This page is for the _team_, see our actual\n[Code of Conduct](/CODE_OF_CONDUCT.md) for the code and reporting details.\n\n## Contact and current team members\n\nThe Conduct Team can be reached by emailing conduct@carbon-lang.dev -- this can\nbe used for questions, concerns, or reports of specific conduct issues.\n\nThe current members of this list are:\n\n-   Allison Poppe (@acpoppe on Discord and GitHub)\n-   Céline Dedaj (@celineausberlin on Discord and GitHub)\n-   Christopher Di Bella (@cjdb.work on Discord, @cjdb on GitHub)\n-   Lexi Bromfield (@lexinadia on Discord and @lexi-nadia on GitHub)\n\nFor more details on reporting conduct to the team, please see the\n[reporting conduct](/CODE_OF_CONDUCT.md#reporting-conduct) documentation.\n\n## Team structure and updates\n\nThe Conduct Team's goal is to have at least 5 trained conduct team members to\ndeal with conduct-related escalations on behalf of and for the Carbon community.\nThere should always be at least 3 conduct team members available to respond\npromptly, even factoring in vacations, getting sick, or other normal\ndisruptions.\n\nThe Conduct Team is responsible for recruiting new members as needed to achieve\nthese goals, and when trained and ready, the team will directly update this\ndocumentation and add them to the respective infrastructure.\n\nThe Conduct Team is typically recruited from among our active moderators -- if\nyou are interested, reaching out to any of the moderators about helping with\nmoderation is a good first step.\n"
  },
  {
    "path": "docs/project/transparency_reports.md",
    "content": "# Conduct and moderation transparency reports\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Overview\n\nCarbon regularly publishes transparency reports that cover conduct issues that\nhave come up in our spaces as well as the moderation and other actions taken in\nresponse. We prioritize keeping the Carbon community\n[welcoming and inclusive](/docs/project/goals.md#community-and-culture) and\nbelieve this kind of transparency is essential to sustaining that.\n\n## Cadence and publishing\n\nWe publish a report quarterly in a GitHub discussion thread in the\n[transparency reports](https://github.com/carbon-language/carbon-lang/discussions/categories/transparency-reports)\ntopic. We use the following template for each of these reports.\n\nWe may publish outside of the quarterly cycle if needed for an urgent response.\n\n## Template\n\nThe Carbon community works to be welcoming and kind among itself and to others,\nwith a deep commitment to psychological safety, and we want to ensure that\ndoesn’t change as we grow and evolve. To that end, we have a few ground rules\nthat we ask all community members to adhere to:\n\n-   be welcoming,\n-   be friendly and patient,\n-   be considerate,\n-   be kind,\n-   be careful in the words that we choose,\n-   when we disagree, try to understand why, and\n-   recognize when progress has stopped, and take a step back.\n\nThe following summary is intended to help the community understand what kinds of\nCode of Conduct (CoC) incidents were brought to our attention lately, and how we\ndealt with them.\n\nPublishing such transparency reports in the future will help us track progress\nand hold ourselves accountable to high standards of community culture.\n\n### Summary\n\n_[overview with overall number of interventions and mention of major community\nrelated events during that period]_\n\nPlease note that some incidents may have escaped our attention. Please help us\nkeep our spaces welcoming and fostering a spirit of collaboration, and report\nany situation that may require our intervention:\nhttps://github.com/carbon-language/carbon-lang/blob/trunk/CODE_OF_CONDUCT.md\n\n### Our interventions from _[YYYY-MM-DD (start date)]_ through _[YYYY-MM-DD (end date)]_\n\n_[mention of preventive measures if applicable]_\n\nThese are the conduct incidents that were brought to our attention during the\nlast documentation period with the relevant sections of the Carbon community\nCode of Conduct when this report was published:\n\n-   > _[Quote1 from the Code of Conduct related to the following interventions]_\n\n    _[Number of related incidents, and corresponding moderation interventions]_\n\n-   > _[Quote2 from the Code of Conduct related to the following interventions]_\n\n    _[Number of related incidents, and corresponding moderation interventions]_\n\n-   > _[Quote3 from the Code of Conduct related to the following interventions]_\n\n    _[Number of related incidents, and corresponding moderation interventions]_\n\n### Closing observations\n\nThank you all for helping us keep such a fantastic Carbon community,\n\n-- The Carbon Language community moderation team, together with the Carbon\nleads.\n"
  },
  {
    "path": "docs/project/versioning.md",
    "content": "# Toolchain and language versioning\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/4105)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Overview](#overview)\n-   [Major version increments](#major-version-increments)\n    -   [Breaking changes](#breaking-changes)\n    -   [Exclusions to what constitutes a breaking change](#exclusions-to-what-constitutes-a-breaking-change)\n-   [Minor version increments](#minor-version-increments)\n-   [Patch version increments](#patch-version-increments)\n    -   [Examples:](#examples)\n-   [Pre-release versions](#pre-release-versions)\n    -   [Release qualification pre-releases: `MAJOR.MINOR.PATCH-rc.N`](#release-qualification-pre-releases-majorminorpatch-rcn)\n    -   [Incremental development versions: `MAJOR.MINOR.PATCH-0.{nightly,dev}.N`](#incremental-development-versions-majorminorpatch-0nightlydevn)\n        -   [Nightly pre-release versions](#nightly-pre-release-versions)\n        -   [Development pre-release versions](#development-pre-release-versions)\n-   [Relevant proposal](#relevant-proposal)\n\n<!-- tocstop -->\n\n## Overview\n\nCarbon uses a single versioning scheme across both the language itself and\ntoolchain, including the standard library, compiler, linker, and all development\ntools released by the main Carbon project.\n\nThe scheme conforms to and is closely based on Semantic Versioning\n(https://semver.org/ -- version 2.0.0):\n\n-   Carbon versions: `MAJOR.MINOR.PATCH`\n-   Releases with backwards incompatible changes, including a deprecation that\n    might trigger a build-breaking warning, increment `MAJOR` after reaching the\n    `1.0` milestone, and increment `MINOR` before then.\n-   Releases with only backwards compatible changes are not expected to happen.\n-   Releases containing only bug fixes increment `PATCH`.\n-   Pre-release suffixes:\n    -   `MAJOR.MINOR.PATCH-rc.N`: The N-th potentially viable candidate for a\n        release.\n    -   `MAJOR.MINOR.PATCH-0.nightly.YYYY.MM.DD`: A nightly incremental\n        development build on a particular day during development of that\n        version.\n    -   `MAJOR.MINOR.PATCH-0.dev`: An interactive, incremental development build\n        on a particular day by some developer during development of that\n        version.\n\nSee the sections below for the details of each aspect of these versions.\n\n## Major version increments\n\nAligned with SemVer, the major version must increment for any _breaking change_\nto the language or any part of the toolchain.\n\nThe first increment from 0 to 1 is expected to be based on achieving a desired\nmilestone of feature completeness and quality to declare the language to have\nreached a stable version.\n\nSubsequent increments are expected to be done with a time-based release\nstrategy. Features (or breaking changes) ready to ship will do so, and others\nwill wait for the next major release. The exact cadence used is future work and\nshould be determined based on discussions with Carbon's users in the ramp up to\nand after reaching the 1.0 milestone.\n\nHowever, just because we increment the major version for a major release and\n_can_ make breaking changes doesn't mean we _will_ or _should_. Breaking\nlanguage changes are extraordinarily expensive for users due to the inherent\nscale of churn they impose. It is tempting to try to make non-breaking releases\ninstead, but our experience with C++ language, compiler, and standard library\nupdates is that truly making no breaking changes is extremely difficult and\noverly constraining. We expect most releases, especially in the early phases of\nthe language to involve _some_ amount of breaking change and will simply work to\nmake these as cheap to upgrade through and minimal as we can.\n\nAt some future point, it is possible that Carbon will become so stable that it\nmakes sense to consider using minor version increments for some releases. If and\nwhen this happens, we should revisit our versioning and release policies to\nestablish a predictable and unsurprising structure.\n\n### Breaking changes\n\nBeyond traditional breaking API changes in either standard library APIs or tool\nAPIs, Carbon also includes breaking changes in the language or toolchain.\nLanguage and toolchain breaking changes are any that cause correct, functioning,\nand non-reflective code to become invalid, rejected, incorrect, or silently\nchange behavior.\n\n### Exclusions to what constitutes a breaking change\n\nCarbon excludes \"reflective code\" which is in some way detecting the Carbon\nversion, or the presence or absence of features and as a consequence can be\n\"broken\" by detecting changes that are correctly designed to otherwise be\nnon-breaking. We don't want adding features to be considered a breaking change\nand so exclude code that specifically detects such additions.\n\nCarbon also excludes breaking changes to incorrect code unless it was accepted\nand functioning in some useful, and typically widespread, way despite its bugs.\n\n## Minor version increments\n\nCurrently, Carbon plans to primarily use the minor version increments with a 0\nmajor version to track our progress towards our 1.0 milestone of a feature\ncomplete initial language. As a consequence we have defined 0.1 and 0.2\nmilestones and may define more steps as needed.\n\nBeyond this and in a post-1.0 language world, we expect most significant\nfeatures to also accompany some small and manageable breaking changes from\ndeprecations. We may choose to revisit this in the future, but our current plan\nis not to make minor version releases post-1.0 and instead focus on our\ncommitment to making those updates both easy and scalable for language users.\n\n## Patch version increments\n\nThe patch version will increment when the change is fundamentally a bug fix to a\npreviously released version. We expect the vast majority of these to be strictly\nbackwards compatible bug fixes.\n\nPatch releases are expected to be driven by demand, and not necessarily present\nif unnecessary. However, the exact schedule and process will be determined as\npart of getting ready for the 1.0 milestone. Before that milestone we don't\ncommit to any particular process or cadence for patch releases as no release\nbefore that point should be considered stable.\n\nNote that we still consider restoring the _intended_ \"public API\" of a release\nto be a bug fix. When these bug fixes theoretically break new code in a way that\nwould typically require a major version increment, they may be made with merely\na patch version increment when they are in fact restoring our intended behavior\nfor that release. However, we take the SemVer guarantees very seriously as these\nfixes can still be disruptive and so we work to hold a high bar for them:\n\n-   They must be in some way fixing a _regressions_ for users from a previous\n    release, not merely a missing feature.\n    -   Can even be a regression in the overall cohesion or reliability of the\n        language or tools, which a bug in a new feature might erode.\n    -   Key is that we motivate any patch fix through the lens of a regression\n        fix and stabilization rather than fixing forward.\n-   The scope of disruption from the fix is demonstrably small, due to some\n    combination of:\n    -   The short time duration of the release containing the regression.\n    -   The narrow scope of code constructs potentially impacted.\n-   The impact of the regression is large and cannot be easily worked around,\n    for example:\n    -   Undermining a core priority of the Carbon Language for a significant set\n        of users.\n    -   Making the engineering cost of adopting the release uneconomical for any\n        significant body of users.\n\n### Examples:\n\n-   We add a new feature that includes a bug which creates unsoundness and\n    allows incorrect code to be compiled that will crash or exhibit UB when\n    executed.\n    -   While this is a new feature and not a bug in an existing feature, it\n        would be a _serious_ regression to the reliability of the language as a\n        whole and the ability of users to reason about the correctness of\n        programs.\n    -   This would be a good candidate for a patch release to address unless it\n        is found very late (months) after the release _and_ the only ways to\n        address would have similarly bad effects on code written since the\n        initial release.\n    -   Even that level of user disruption could potentially be overcome if for\n        example the bug led to security vulnerabilities.\n-   We add a narrowly used new feature that includes a bug where some code\n    patterns that _should_ work with the feature are rejected at compile time or\n    crash reliably.\n    -   Unlikely this is worth a patch release to make an invasive change given\n        the narrow use case.\n    -   A good candidate to introduce a warning or error on using the feature in\n        the way that might lead to a crash, and possibly on using the feature at\n        all.\n-   We add a compiler opt-in feature behind a flag that doesn't work reliably.\n    -   Good candidate to have the flag disabled or trigger a warning message.\n    -   Not a good candidate to try to fix the feature forward.\n-   We add a compiler opt-out feature that doesn't work reliably.\n    -   What to do likely depends on the scope of users impacted. If _very_ few\n        users impacted, possibly just document how to opt-out.\n    -   If enough are impacted to be a nuisance and a regression in experience\n        in general, likely worth attempting a patch release that narrowly fixes\n        or mitigates the issue.\n\n## Pre-release versions\n\nBeyond the major, minor, and patch versions of an actual release, SemVer\nprovides a foundation for pre-release version management. However, it is a very\nopen-ended foundation with a wide range of possibilities and no particular\nsemantic model provided. Some of this is to support the wide variety of\ndifferent needs across different projects. It also reflects the fundamentally\nless crisp and well defined criteria needed for pre-releases.\n\nThat said, Carbon should try to have a small and well articulated scheme of\npre-release versions to help communicate what these releases do and don't\nconstitute and how they should be interpreted. These are selected to provide a\nframework that allows pre-release versions to order in a reasonably cohesive way\nwhen compared using SemVer.\n\nIn descending order, Carbon pre-releases may use:\n\n-   `MAJOR.MINOR.PATCH-rc.N`\n-   `MAJOR.MINOR.PATCH-0.nightly.YYYY.MM.DD`\n-   `MAJOR.MINOR.PATCH-0.dev`\n\nWe expand on each of these below to provide criteria and details.\n\n### Release qualification pre-releases: `MAJOR.MINOR.PATCH-rc.N`\n\nWe create release candidate or \"rc\" pre-releases when we believe that version to\nbe complete and ready to release and want to collect feedback. There should not\nbe interesting or significant gaps, even known ones, from the intended release.\nThe expectation should always be that unless some feedback arrives to the\ncontrary, the release candidate could simply become the release.\n\nFor each pre-release category, we always suffix with a sequential count `N` of\nthe pre-releases at that version. We must start with a `.0` in order to have\nsubsequent iterations of the same version and category of pre-release to sort\nafter the first.\n\n### Incremental development versions: `MAJOR.MINOR.PATCH-0.{nightly,dev}.N`\n\nThese are versions that are not in any way associated with the actual expected\nrelease, but are periodically produced as an incremental tracking of development\nprogress. Because they are not expected to be part of qualifying a specific\nrelease, they're not defined by any particular criteria of completeness or\nreadiness. In practice, these will occur at every stage between one release and\nthe next.\n\n#### Nightly pre-release versions\n\nThese are automated incremental development versions built each night when the\nautomated testing passes. There is _no_ attempt to provide any higher quality\nbar or refinement than whatever was in the tree at the time the automation runs,\nand whatever automated tests are present pass.\n\nIt is important to emphasize that the primary use case of these pre-release\nversions is not to evaluate a potential release but for the developers and\ncontributors to Carbon itself to track incremental development progress. That\ndevelopment-oriented goal drives how they are built and what they do and don't\nprovide.\n\nMechanically, we prefix the `nightly` pre-release version component with a `0`\ncomponent to ensure these versions sort before any and all release qualification\npre-release versions. We also add a date-derived suffix to provide a rough\nchronological ordering of nightly builds with otherwise identical versions.\n\n#### Development pre-release versions\n\nDuring development, interactive builds of Carbon need to be versioned in an\nunambiguous way, and we do that with the `dev` pre-release version. Much like\nnightly versions, these are only produced as artifacts of development activities\nand are never part of any actual release process. These versions are further not\nbuilt expected to be automated or necessarily repeatable. They may contain\nin-flight edits and all manner of other variations.\n\nMechanically, we prefix the `dev` pre-release version component with `0` in the\nsame way as `nightly` is prefixed to ensure effective ordering. We don't add any\nadditional information to keep the mechanics of development builds simple -- for\nexample, there is no easy way to extract the date of the build. The exact\ntimestamp of the build may be available but doesn't participate for simplicity\nand minimizing cache impact.\n\n## Relevant proposal\n\n-   [Proposal p4105](/proposals/p4105.md)\n"
  },
  {
    "path": "docs/spec/README.md",
    "content": "# Spec\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nEventually, this will be the home of a formal specification for the Carbon\nLanguage. We are committed to having a specification that is sufficiently\ndetailed to allow independent implementations of the language. While we plan to\nhave a reference implementation, we think having a specification as well is an\nimportant tool to ensure that the behavior of the language is well understood\nand holds together.\n\nThe work-in-progress specification is available here:\n\n-   [Language specification](lang)\n-   [Library specification](lib)\n"
  },
  {
    "path": "docs/spec/lang/README.md",
    "content": "# Carbon language specification\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Program structure\n\n1.  A _program_ is a collection of one or more linkage units that are\n    [linked](#linkage) together.\n\n2.  A _Carbon linkage unit_ is the result of [translating](#translation) a\n    source file. A _foreign linkage unit_ is an artifact produced by a\n    translation process for some other programming language. A linkage unit is\n    either a Carbon linkage unit or a foreign linkage unit.\n\n3.  A _source file_ is a sequence of Unicode code points.\n\n    > Note: Source files are typically stored on disk in files with a `.carbon`\n    > file extension, encoded in UTF-8.\n\n## Conformance\n\n1.  A program is _valid_ if it contains no constructs that violate \"shall\"\n    constraints in this specification. Otherwise, the program is _invalid_.\n\n2.  An implementation is _conforming_ if it accepts all valid programs, it\n    rejects all invalid programs for which a diagnostic is required, and the\n    [execution](execution.md) semantics of all accepted programs is as specified\n    in this specification.\n\n## Translation\n\n1.  Translation of a source file into a Carbon linkage unit proceeds as follows:\n\n    -   [Lexical analysis](lex.md) decomposes the sequence of code points into a\n        sequence of lexical elements.\n    -   Whitespace and text comments are discarded, leaving a sequence of\n        [tokens](lex.md).\n    -   The tokens are [parsed](parsing.md) into an abstract syntax tree.\n    -   [Unqualified names are bound](names.md) to declarations in the abstract\n        syntax tree.\n    -   A translated form of each imported [library](libs.md) is located and\n        loaded.\n    -   [Semantic analysis](semantics.md) is performed: types are determined and\n        semantic checks are performed for all non-template-dependent constructs\n        in the abstract syntax tree, constant expressions are evaluated, and\n        templates are instantiated and semantically analyzed.\n\n2.  > Note: After semantic analysis, an implementation may optionally\n    > monomorphize generics by a process similar to template instantiation.\n\n3.  The resulting linkage unit comprises all entities in the translated source\n    file that are either [external](#linkage) or are reachable from an external\n    entity.\n\n    > Note: A linkage unit can include non-monomorphized generics, but never\n    > includes templates. Constant evaluation can eliminate references to\n    > entities.\n\n## Linkage\n\n1.  Two declarations declare the same entity if both declarations are in the\n    same library and the same [scope](names.md#scopes) and declare the same\n    [name](names.md).\n\n    TODO: Linkage rules for foreign entities. TODO: Ability to declare\n    file-local entities.\n\n2.  All declarations of an entity shall use the same type.\n\n3.  Every entity that is reachable from a linkage unit in a program shall be\n    defined by a linkage unit in the program; no diagnostic is required unless\n    an entity that can be referenced during the [execution](execution.md) of the\n    program is not defined.\n\n4.  There shall not be more than one definition of an entity in a program.\n"
  },
  {
    "path": "docs/spec/lang/execution.md",
    "content": "# Execution\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Entry points\n\nTODO: Entry points (Carbon and foreign). `fn Run()`.\n\n## Object model\n\n## Sequential execution\n\n## Threads and data races\n"
  },
  {
    "path": "docs/spec/lang/lex.md",
    "content": "# Lexical analysis\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nTODO\n\n## Lexical elements\n\n1.  The sequence of Unicode code points in a source file is partitioned into\n    contiguous subsequences called _lexical elements_. Formation of lexical\n    elements begins with the first code point in the source file and proceeds in\n    code point order.\n\n2.  At each step, the longest valid lexical element that can be formed from a\n    prefix of the remaining code points is formed, even if this would result in\n    a failure to form a later lexical element. Repeating this process shall\n    convert the entire source file into lexical elements.\n\n3.  Valid lexical elements are:\n\n    TODO: Add a list of lexical elements once we've decided on them.\n"
  },
  {
    "path": "docs/spec/lang/libs.md",
    "content": "# Libraries and packages\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nTODO\n"
  },
  {
    "path": "docs/spec/lang/names.md",
    "content": "# Names\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nTODO\n\n## Names\n\n1.  A _name_ is an [identifier](lex.md). Two names are the same if they comprise\n    the same sequence of Unicode code points.\n\n    TODO: Normalization?\n\n## Scopes\n\n1.  A _scope_ is one of:\n\n    -   The top level in a source file.\n    -   A pattern scope.\n    -   A block scope.\n    -   A type definition.\n\n2.  Every construct that declares a name _binds_ the name to the declared entity\n    within the innermost enclosing scope.\n\n## Unqualified name lookup\n\n1.  Unqualified name lookup associates a name with an entity. The associated\n    entity is the entity to which the name is bound in the innermost enclosing\n    scope in which the name is bound.\n"
  },
  {
    "path": "docs/spec/lang/parsing.md",
    "content": "# Parsing\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nTODO\n"
  },
  {
    "path": "docs/spec/lang/semantics.md",
    "content": "# Semantic analysis\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nTODO\n"
  },
  {
    "path": "docs/spec/lib/README.md",
    "content": "# Carbon standard library specification\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nTODO\n"
  },
  {
    "path": "examples/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@bazel_binaries//:defs.bzl\", \"bazel_binaries\")\nload(\n    \"@rules_bazel_integration_test//bazel_integration_test:defs.bzl\",\n    \"bazel_integration_tests\",\n    \"integration_test_utils\",\n)\nload(\"@rules_python//python:defs.bzl\", \"py_binary\")\nload(\"//bazel/carbon_rules:defs.bzl\", \"carbon_binary\")\n\ncarbon_binary(\n    name = \"sieve\",\n    srcs = [\"sieve.carbon\"],\n)\n\ncarbon_binary(\n    name = \"hello_world\",\n    srcs = [\"hello_world.carbon\"],\n)\n\npy_binary(\n    name = \"bazel_test_runner\",\n    testonly = True,\n    srcs = [\"bazel_test_runner.py\"],\n    data = [\"//toolchain/install:install_data\"],\n    deps = [\n        \"@bazel_tools//tools/python/runfiles\",\n        \"@rules_bazel_integration_test//bazel_integration_test/py:test_base\",\n    ],\n)\n\nbazel_example_files = [\n    \"bazel/BUILD\",\n    \"bazel/MODULE.bazel\",\n    \"bazel/example_lib.h\",\n    \"bazel/example_lib.cpp\",\n    \"bazel/example.cpp\",\n]\n\nbazel_integration_tests(\n    name = \"bazel_min_test\",\n    bazel_binaries = bazel_binaries,\n    bazel_versions = bazel_binaries.versions.all,\n    # Override the default tags which assume a much more expensive test.\n    tags = [],\n    test_runner = \":bazel_test_runner\",\n    workspace_files = bazel_example_files,\n    workspace_path = \"bazel\",\n)\n\nbazel_integration_tests(\n    name = \"bazel_full_test\",\n    bazel_binaries = bazel_binaries,\n    bazel_versions = bazel_binaries.versions.all,\n    env = {\"CARBON_BAZEL_TEST_FULL\": \"\"},\n    # Override the default tags -- while running these manually is good as the\n    # full tests are very expensive, there isn't a reason to run them\n    # _exclusively_ as well.\n    tags = [\"manual\"],\n    test_runner = \":bazel_test_runner\",\n    workspace_files = bazel_example_files,\n    workspace_path = \"bazel\",\n)\n\n# Convenience test suites with a simple names to run all the different\n# configured Bazel versions of tests.\ntest_suite(\n    name = \"bazel_min_tests\",\n    tests = integration_test_utils.bazel_integration_test_names(\n        \"bazel_min_test\",\n        bazel_binaries.versions.all,\n    ),\n)\n\ntest_suite(\n    name = \"bazel_full_tests\",\n    # Full tests are too expensive to run by default.\n    tags = [\"manual\"],\n    tests = integration_test_utils.bazel_integration_test_names(\n        \"bazel_full_test\",\n        bazel_binaries.versions.all,\n    ),\n)\n"
  },
  {
    "path": "examples/advent2024/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/carbon_rules:defs.bzl\", \"carbon_binary\")\n\nutils = [\n    \"io_utils.carbon\",\n    \"sort.carbon\",\n]\n\n# A list of examples that should be excluded because they don't build any more.\n# For example, to exclude day3_part2, use:\n# excluded = [\"day3_part2.carbon\"]\nexcluded = []\n\n# Produce a binary `dayX_partY` for each matching `.carbon` file. Each binary\n# depends on `dayX_partY.carbon` and `dayX_common.carbon`.\n[\n    carbon_binary(\n        name = carbon_file.removesuffix(\".carbon\"),\n        srcs = [\n            carbon_file,\n            carbon_file.rsplit(\"_\", 1)[0] + \"_common.carbon\",\n        ] + utils,\n    )\n    for carbon_file in glob([\"day*_part*.carbon\"])\n    if carbon_file not in excluded\n]\n"
  },
  {
    "path": "examples/advent2024/README.md",
    "content": "# Advent of Code 2024\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis directory contains sample solutions written in Carbon for\n[Advent of Code 2024](https://adventofcode.com/2024/).\n\nThe Carbon toolchain is in a very early state, so these samples frequently need\nto work around missing functionality and are not reflective of expected Carbon\nstyle and idioms. Instead, the purpose of these examples are to test the current\nstate of the toolchain against larger code examples than those that are present\nin the toolchain's own tests, to find bugs in the toolchain, and to drive\nfeature development in the toolchain by presenting somewhat realistic testcases.\n\nIf one of these examples stops building after a change to the toolchain, please:\n\n-   Make sure that the build break is an expected consequence of the change.\n-   Update the `BUILD` file to exclude that example.\n-   File an issue and assign it to @zygoloid.\n"
  },
  {
    "path": "examples/advent2024/day10_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/10\n\nlibrary \"day10_common\";\n\nimport Core library \"io\";\nimport Core library \"range\";\nimport library \"io_utils\";\n\nclass Terrain {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Terrain {\n    returned var me: Terrain;\n    for (y: i32 in Core.Range(43)) {\n      for (x: i32 in Core.Range(43)) {\n        me.height[x][y] = ReadChar() - '0';\n      }\n      SkipNewline();\n    }\n    return var;\n  }\n\n  var height: array(array(i32, 43), 43);\n}\n"
  },
  {
    "path": "examples/advent2024/day10_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/10\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day10_common\";\nimport library \"io_utils\";\n\n// TODO: Add this to the prelude.\nfn PopCount(n: u256) -> i32 {\n  var bit: u256 = 1;\n  var total: i32 = 0;\n  while (bit != 0) {\n    if (n & bit != 0) {\n      ++total;\n    }\n    bit <<= 1;\n  }\n  return total;\n}\n\nclass Reachable {\n  impl as Core.UnformedInit {}\n\n  fn Make(terrain: Terrain) -> Reachable {\n    returned var me: Reachable;\n    var next: u256 = 1;\n    for (y: i32 in Core.Range(43)) {\n      for (x: i32 in Core.Range(43)) {\n        if (terrain.height[x][y] == 0) {\n          me.trailheads[x][y] = next;\n          next <<= 1;\n        }\n      }\n    }\n    return var;\n  }\n\n  fn AddLevel[ref self: Self](terrain: Terrain, level: i32) {\n    let adj: array((i32, i32), 4) = ((-1, 0), (0, -1), (1, 0), (0, 1));\n    for (y: i32 in Core.Range(43)) {\n      for (x: i32 in Core.Range(43)) {\n        if (terrain.height[x][y] == level) {\n          var reach: u256 = 0;\n          var i: i32 = 0;\n          while (i < 4) {\n            let adj_x: i32 = x + adj[i].0;\n            let adj_y: i32 = y + adj[i].1;\n            if (adj_x >= 0 and adj_x < 43 and\n                adj_y >= 0 and adj_y < 43 and\n                terrain.height[adj_x][adj_y] == level - 1) {\n              reach = reach | self.trailheads[adj_x][adj_y];\n            }\n            ++i;\n          }\n          self.trailheads[x][y] = reach;\n        }\n      }\n    }\n  }\n\n  fn Count[self: Self](terrain: Terrain, level: i32) -> i32 {\n    var total: i32 = 0;\n    for (y: i32 in Core.Range(43)) {\n      for (x: i32 in Core.Range(43)) {\n        if (terrain.height[x][y] == level) {\n          total += PopCount(self.trailheads[x][y]);\n        }\n      }\n    }\n    return total;\n  }\n\n  var trailheads: array(array(u256, 43), 43);\n}\n\nfn Run() {\n  var terrain: Terrain = Terrain.Read();\n  var reachable: Reachable = Reachable.Make(terrain);\n  for (i: i32 in Core.InclusiveRange(1, 9)) {\n    reachable.AddLevel(terrain, i);\n  }\n  Core.Print(reachable.Count(terrain, 9));\n}\n"
  },
  {
    "path": "examples/advent2024/day10_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/10\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day10_common\";\nimport library \"io_utils\";\n\nclass PathsToTop {\n  impl as Core.UnformedInit {}\n\n  fn Make(terrain: Terrain) -> PathsToTop {\n    returned var me: PathsToTop;\n    for (y: i32 in Core.Range(43)) {\n      for (x: i32 in Core.Range(43)) {\n        // TODO: We shouldn't need an explicit cast here.\n        me.paths[x][y] =\n          if terrain.height[x][y] == 9 then 1 as i64 else 0;\n      }\n    }\n    return var;\n  }\n\n  fn AddLevel[ref self: Self](terrain: Terrain, level: i32) -> i64 {\n    var total: i64 = 0;\n    let adj: array((i32, i32), 4) = ((-1, 0), (0, -1), (1, 0), (0, 1));\n    for (y: i32 in Core.Range(43)) {\n      for (x: i32 in Core.Range(43)) {\n        if (terrain.height[x][y] == level) {\n          var paths: i64 = 0;\n          // TODO: for ((adj_x: i32, adj_y: i32) in adj) {\n          for (i: i32 in Core.Range(4)) {\n            let adj_x: i32 = x + adj[i].0;\n            let adj_y: i32 = y + adj[i].1;\n            if (adj_x >= 0 and adj_x < 43 and\n                adj_y >= 0 and adj_y < 43 and\n                terrain.height[adj_x][adj_y] == level + 1) {\n              paths += self.paths[adj_x][adj_y];\n            }\n          }\n          self.paths[x][y] = paths;\n          total += paths;\n        }\n      }\n    }\n    return total;\n  }\n\n  var paths: array(array(i64, 43), 43);\n}\n\nfn Run() {\n  var terrain: Terrain = Terrain.Read();\n  var paths: PathsToTop = PathsToTop.Make(terrain);\n  var total: i64;\n  for (i: i32 in Core.InclusiveRange(0, 8)) {\n    total = paths.AddLevel(terrain, 8 - i);\n  }\n  PrintInt(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day11_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/11\n\nlibrary \"day11_common\";\n\nimport Core library \"io\";\nimport library \"io_utils\";\n\nfn Next(n: i64) -> (i64, i64) {\n  if (n == 0) { return (1, -1); }\n  var pow10: i64 = 10;\n  var pow100: i64 = 1;\n  while (n / pow100 >= 100) {\n    pow100 *= 100;\n    pow10 *= 10;\n  }\n  if (n / pow100 >= 10) {\n    return (n / pow10, n % pow10);\n  }\n  return (n * 2024, -1);\n}\n\nfn Count(n: i64, depth: i32) -> i32 {\n  if (n == -1) { return 0; }\n  if (depth == 0) { return 1; }\n  let next: (i64, i64) = Next(n);\n  return Count(next.0, depth - 1) + Count(next.1, depth - 1);\n}\n"
  },
  {
    "path": "examples/advent2024/day11_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/11\n\nimport Core library \"io\";\n\nimport library \"day11_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var n: i64;\n  var total: i32 = 0;\n  while (ReadInt(ref n)) {\n    total += Count(n, 25);\n    SkipSpaces();\n  }\n  Core.Print(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day11_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/11\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day11_common\";\nimport library \"io_utils\";\n\nclass Digits {\n  impl as Core.UnformedInit {}\n\n  fn Make() -> Digits {\n    returned var me: Digits;\n    for (digit: i32 in Core.Range(10)) {\n      for (depth: i32 in Core.Range(75)) {\n        me.count[digit][depth] = 0;\n      }\n    }\n    return var;\n  }\n\n  fn Print[self: Self](max_depth: i32) {\n    for (digit: i32 in Core.Range(10)) {\n      Core.PrintChar(((digit + 0x30) as u8) as char);\n      Core.PrintChar(':');\n      for (depth: i32 in Core.Range(max_depth)) {\n        Core.PrintChar(' ');\n        PrintIntNoNewline(self.count[digit][depth]);\n      }\n      Core.PrintChar('\\n');\n    }\n    Core.PrintChar('\\n');\n  }\n\n  var count: array(array(i64, 75), 10);\n}\n\nfn ReduceToDigits(n: i64, depth: i32, multiplicity: i64, digits: Digits*) -> i64 {\n  if (n == -1) { return 0; }\n  if (depth == 0) { return multiplicity; }\n  if (n < 10) {\n    let count: i64* = &digits->count[n as i32][depth - 1];\n    *count += multiplicity;\n    return 0;\n  }\n  let next: (i64, i64) = Next(n);\n  return ReduceToDigits(next.0, depth - 1, multiplicity, digits) +\n         ReduceToDigits(next.1, depth - 1, multiplicity, digits);\n}\n\nfn Run() {\n  let max_depth: i32 = 75;\n  var total: i64 = 0;\n  var digits: Digits = Digits.Make();\n\n  var n: i64;\n  while (ReadInt(ref n)) {\n    total += ReduceToDigits(n, max_depth, 1, &digits);\n    // PrintInt(total);\n    // digits.Print(max_depth - 1);\n    SkipSpaces();\n  }\n\n  var depth: i32 = max_depth - 1;\n  while (depth >= 0) {\n    // PrintInt(total);\n    // digits.Print(depth);\n    for (digit: i32 in Core.Range(10)) {\n      let m: i64 = digits.count[digit][depth];\n      if (m > 0) {\n        let next: (i64, i64) = Next(digit as i64);\n        total += ReduceToDigits(next.0, depth, m, &digits) +\n                 ReduceToDigits(next.1, depth, m, &digits);\n      }\n    }\n    --depth;\n  }\n\n  PrintInt(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day12_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/12\n\nlibrary \"day12_common\";\n\nimport Core library \"io\";\nimport Core library \"range\";\nimport library \"io_utils\";\n\nclass Map {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Map {\n    returned var me: Self;\n    for (y: i32 in Core.Range(140)) {\n      for (x: i32 in Core.Range(140)) {\n        me.kind[x][y] = ReadChar() as i32;\n      }\n      SkipNewline();\n    }\n    return var;\n  }\n\n  fn At[self: Self](x: i32, y: i32) -> i32 {\n    return if x < 0 or x >= 140 or y < 0 or y >= 140\n           then -1\n           else self.kind[x][y];\n  }\n\n  var kind: array(array(i32, 140), 140);\n}\n\nclass DisjointSetForest {\n  impl as Core.UnformedInit {}\n\n  fn Make() -> DisjointSetForest {\n    returned var me: Self;\n    for (i: i32 in Core.Range(140 * 140)) {\n      me.nodes[i].next = i;\n      me.nodes[i].weight = 1;\n      me.nodes[i].unions = 0;\n    }\n    return var;\n  }\n\n  fn Lookup[ref self: Self](a: i32) -> i32 {\n    let next: i32 = self.nodes[a].next;\n    if (next == a) {\n      return next;\n    }\n    let resolved: i32 = self.Lookup(next);\n    self.nodes[a].next = resolved;\n    return resolved;\n  }\n\n  fn Unions[self: Self](canon_a: i32) -> i32 {\n    return self.nodes[canon_a].unions;\n  }\n\n  fn Weight[self: Self](canon_a: i32) -> i32 {\n    return self.nodes[canon_a].weight;\n  }\n\n  fn Union[ref self: Self](a: i32, b: i32) {\n    let canon_b: i32 = self.Lookup(b);\n    self.Set(a, canon_b);\n    ++self.nodes[canon_b].unions;\n  }\n\n  private fn Set[ref self: Self](a: i32, canon_b: i32) {\n    let next: i32 = self.nodes[a].next;\n    self.nodes[a].next = canon_b;\n    if (next == a) {\n      if (a != canon_b) {\n        self.nodes[canon_b].weight += self.nodes[a].weight;\n        self.nodes[canon_b].unions += self.nodes[a].unions;\n      }\n    } else {\n      self.Set(next, canon_b);\n    }\n  }\n\n  // TODO: Consider adding ranked choice.\n  // TODO: Make this generic in the payload data.\n  var nodes: array({.next: i32, .weight: i32, .unions: i32}, 140 * 140);\n}\n\nfn MakeRegions(map: Map) -> DisjointSetForest {\n  returned var forest: DisjointSetForest =\n    DisjointSetForest.Make();\n\n  for (x: i32 in Core.Range(140)) {\n    for (y: i32 in Core.Range(140)) {\n      for (a: i32 in Core.Range(2)) {\n        // TODO: Crashes toolchain:\n        // let adj: (i32, i32) = if a == 0 then (x - 1, y) else (x, y - 1);\n        // if (map.At(adj.0, adj.1) == map.At(x, y)) {\n        //   forest.Union(y * 140 + x, adj.1 * 140 + adj.0);\n        // }\n        let adj_x: i32 = if a == 0 then x - 1 else x;\n        let adj_y: i32 = if a == 0 then y else y - 1;\n        if (map.At(adj_x, adj_y) == map.At(x, y)) {\n          forest.Union(y * 140 + x, adj_y * 140 + adj_x);\n        }\n      }\n    }\n  }\n\n  return var;\n}\n"
  },
  {
    "path": "examples/advent2024/day12_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/12\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day12_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var map: Map = Map.Read();\n  var regions: DisjointSetForest = MakeRegions(map);\n\n  var total: i32 = 0;\n\n  for (i: i32 in Core.Range(140 * 140)) {\n    if (regions.Lookup(i) == i) {\n      let area: i32 = regions.Weight(i);\n      let internal_edges: i32 = regions.Unions(i);\n      let perimeter: i32 = area * 4 - internal_edges * 2;\n      total += area * perimeter;\n    }\n  }\n\n  Core.Print(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day12_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/12\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day12_common\";\nimport library \"io_utils\";\n\nfn CountExtensions(map: Map, regions: DisjointSetForest*) -> array(i32, 140 * 140) {\n  returned var extensions: array(i32, 140 * 140);\n  for (i: i32 in Core.Range(140 * 140)) {\n    extensions[i] = 0;\n  }\n\n  var ext: array({.same: (i32, i32), .adj: (i32, i32)}, 4) = (\n    {.same = (-1, 0), .adj = (0, -1)},\n    {.same = (-1, 0), .adj = (0, 1)},\n    {.same = (0, -1), .adj = (-1, 0)},\n    {.same = (0, -1), .adj = (1, 0)},\n  );\n\n  for (x: i32 in Core.Range(140)) {\n    for (y: i32 in Core.Range(140)) {\n      let kind: i32 = map.At(x, y);\n      for (e: i32 in Core.Range(4)) {\n        if (map.At(x + ext[e].same.0, y + ext[e].same.1) == kind and\n            map.At(x + ext[e].adj.0, y + ext[e].adj.1) != kind and\n            map.At(x + ext[e].same.0 + ext[e].adj.0,\n                   y + ext[e].same.1 + ext[e].adj.1) != kind) {\n          ++extensions[regions->Lookup(y * 140 + x)];\n        }\n      }\n    }\n  }\n  return var;\n}\n\nfn Run() {\n  var map: Map = Map.Read();\n  var regions: DisjointSetForest = MakeRegions(map);\n  var ext: array(i32, 140 * 140) = CountExtensions(map, &regions);\n\n  var total: i32 = 0;\n\n  for (i: i32 in Core.Range(140 * 140)) {\n    if (regions.Lookup(i) == i) {\n      let area: i32 = regions.Weight(i);\n      let internal_edges: i32 = regions.Unions(i);\n      let extensions: i32 = ext[i];\n      let perimeter: i32 = area * 4 - internal_edges * 2 - extensions;\n      total += area * perimeter;\n    }\n  }\n\n  Core.Print(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day13_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/13\n\nlibrary \"day13_common\";\n\nimport Core library \"io\";\nimport library \"io_utils\";\n\n// Returns m and n so that am + bn = gcd.\nfn Euclid(a: i64, b: i64) -> {.m: i64, .n: i64, .gcd: i64} {\n  if (a < b) {\n    let reverse: {.m: i64, .n: i64, .gcd: i64} = Euclid(b, a);\n    return {.m = reverse.n, .n = reverse.m, .gcd = reverse.gcd};\n  }\n  if (b == 0) {\n    return {.m = 1, .n = 0, .gcd = a};\n  }\n  let next: {.m: i64, .n: i64, .gcd: i64} = Euclid(b, a % b);\n  return {.m = next.n, .n = next.m - next.n * (a / b), .gcd = next.gcd};\n}\n\nclass Machine {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Machine {\n    returned var me: Machine;\n    // \"Button A: X+\"\n    SkipNChars(12);\n    ReadInt(ref me.a.0);\n    // \", Y+\"\n    SkipNChars(4);\n    ReadInt(ref me.a.1);\n    // \"\\nButton B: X+\"\n    SkipNChars(13);\n    ReadInt(ref me.b.0);\n    // \", Y+\"\n    SkipNChars(4);\n    ReadInt(ref me.b.1);\n    // \"\\nPrize: X=\"\n    SkipNChars(10);\n    ReadInt(ref me.prize.0);\n    // \", Y=\"\n    SkipNChars(4);\n    ReadInt(ref me.prize.1);\n    SkipNewline();\n    return var;\n  }\n\n  var a: (i64, i64);\n  var b: (i64, i64);\n  var prize: (i64, i64);\n}\n\n// Set of solutions to 'm a + n b = c'.\nclass BezoutSolutionSet {\n  fn Make(a: i64, b: i64, c: i64) -> BezoutSolutionSet {\n    var e: {.m: i64, .n: i64, .gcd: i64} = Euclid(a, b);\n    if (c % e.gcd != 0) {\n      // Impossible.\n      return {.m0 = -1, .n0 = -1, .m_step = -1, .n_step = -1};\n    }\n\n    // Find an initial solution. Note that m and n might be negative.\n    let num_gcds: i64 = c / e.gcd;\n    e.m *= num_gcds;\n    e.n *= num_gcds;\n\n    // Pick the smallest positive m we can.\n    let a_over_gcd: i64 = a / e.gcd;\n    let b_over_gcd: i64 = b / e.gcd;\n    var adj: i64 = 0;\n    // This is e.m / b rounded towards -inf.\n    // TODO: Should there be a way of expressing this directly?\n    if (e.m < 0) {\n      adj = (e.m - b_over_gcd + 1) / b_over_gcd;\n    } else {\n      adj = e.m / b_over_gcd;\n    }\n    e.m -= adj * b_over_gcd;\n    e.n += adj * a_over_gcd;\n    return {.m0 = e.m, .n0 = e.n,\n            .m_step = b_over_gcd, .n_step = -a_over_gcd};\n  }\n\n  fn Valid[self: Self]() -> bool {\n    return self.m_step >= 0;\n  }\n\n  fn Solution[self: Self](k: i64) -> (i64, i64) {\n    return (self.m0 + k * self.m_step, self.n0 + k * self.n_step);\n  }\n\n  // m_k * a + n_k * b == c, where:\n  //   m_k = m0 + k * m_step\n  //   n_k = n0 * k * n_step\n  // m0 is the minimum non-negative m value, and n_step is negative.\n  var m0: i64;\n  var n0: i64;\n  var m_step: i64;\n  var n_step: i64;\n}\n\n// Given two sets of points s and t, find the intersection in the first quadrant\n// with the minimum x coordinate. Returns the intersection point, or (-1, -1) if\n// there is no intersection.\nfn FirstIntersection(s: BezoutSolutionSet, t: BezoutSolutionSet) -> (i64, i64) {\n  if (not s.Valid() or not t.Valid()) {\n    // One of the sets is empty.\n    return (-1, -1);\n  }\n\n  // Easy case: lines meet at a point. This happens unless the lines are\n  // parallel.\n  let d: i64 = s.m_step * t.n_step - t.m_step * s.n_step;\n  if (d != 0) {\n    let u: i64 = (t.m0 - s.m0) * t.n_step - (t.n0 - s.n0) * t.m_step;\n    if (u % d != 0) {\n      // Lines don't meet at an integer point.\n      return (-1, -1);\n    }\n    let j: i64 = u / d;\n    if (j < 0 or s.n0 + j * s.n_step < 0) {\n      // Lines don't meet in first quadrant.\n      return (-1, -1);\n    }\n    return s.Solution(j);\n  }\n\n  // Hard case: lines are parallel. We also get here if either \"line\" is a\n  // point, but that doesn't happen in this exercise. We know all integer points\n  // on the line are solutions, so the first intersection is the greater of the\n  // first point in s and the first point in t, if that point is on both lines.\n  if (s.m0 < t.m0) {\n    // (t.m0, t.n0) is the solution if it's in s.\n    if ((t.m0 - s.m0) % s.m_step == 0 and\n        (t.n0 - s.n0) % s.n_step == 0) {\n      return (t.m0, t.n0);\n    }\n  } else {\n    // (s.m0, s.n0) is the solution if it's in t.\n    if ((s.m0 - t.m0) % t.m_step == 0 and\n        (s.n0 - t.n0) % t.n_step == 0) {\n      return (s.m0, s.n0);\n    }\n  }\n  return (-1, -1);\n}\n\nfn CostIfPossible(m: Machine) -> i64 {\n  let x: BezoutSolutionSet = BezoutSolutionSet.Make(m.a.0, m.b.0, m.prize.0);\n  let y: BezoutSolutionSet = BezoutSolutionSet.Make(m.a.1, m.b.1, m.prize.1);\n  let ab: (i64, i64) = FirstIntersection(x, y);\n  if (ab.0 == -1) { return 0; }\n  return ab.0 * 3 + ab.1;\n}\n"
  },
  {
    "path": "examples/advent2024/day13_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/13\n\nimport Core library \"io\";\n\nimport library \"day13_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var total_cost: i64 = 0;\n  while (true) {\n    var m: Machine = Machine.Read();\n    total_cost += CostIfPossible(m);\n    if (not SkipNewline()) {\n      break;\n    }\n  }\n  PrintInt(total_cost);\n}\n"
  },
  {
    "path": "examples/advent2024/day13_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/13\n\nimport Core library \"io\";\n\nimport library \"day13_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var total_cost: i64 = 0;\n  while (true) {\n    var m: Machine = Machine.Read();\n    m.prize.0 += 10_000_000_000_000;\n    m.prize.1 += 10_000_000_000_000;\n    total_cost += CostIfPossible(m);\n    if (not SkipNewline()) {\n      break;\n    }\n  }\n  PrintInt(total_cost);\n}\n"
  },
  {
    "path": "examples/advent2024/day14_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/14\n\nlibrary \"day14_common\";\n\nimport Core library \"io\";\nimport library \"io_utils\";\n\nfn ReadXY(xy: (i32, i32)*) -> bool {\n  return ReadInt(ref xy->0) and ConsumeChar(',') and ReadInt(ref xy->1);\n}\n\nfn SkipString(s: str) -> bool {\n  return SkipNChars(s.Size() as i32);\n}\n\nfn Mod(a: i32, d: i32) -> i32 {\n  let rem: i32 = a % d;\n  return if rem < 0 then rem + d else rem;\n}\n\nclass Robot {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Robot {\n    returned var me: Robot;\n    SkipString(\"p=\");\n    ReadXY(&me.p);\n    SkipString(\" v=\");\n    ReadXY(&me.v);\n    SkipNewline();\n    return var;\n  }\n\n  fn Pos[self: Self](t: i32) -> (i32, i32) {\n    return (Mod((self.p.0 + self.v.0 * Mod(t, 101)), 101),\n            Mod((self.p.1 + self.v.1 * Mod(t, 103)), 103));\n  }\n\n  impl as Core.Copy {\n    fn Op[self: Self]() -> Self {\n      return {.p = self.p, .v = self.v};\n    }\n  }\n\n  var p: (i32, i32);\n  var v: (i32, i32);\n}\n"
  },
  {
    "path": "examples/advent2024/day14_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/14\n\nimport Core library \"io\";\n\nimport library \"day14_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var q: array(array(i32, 3), 3) = ((0,0,0), (0,0,0), (0,0,0));\n  while (PeekChar() != CharOrEOF.EOF()) {\n    var r: Robot = Robot.Read();\n    let xy: (i32, i32) = r.Pos(100);\n    ++q[if xy.0 < 50 then 0 else if xy.0 > 50 then 2 else 1]\n       [if xy.1 < 51 then 0 else if xy.1 > 51 then 2 else 1];\n  }\n  Core.Print(q[0][0] * q[0][2] * q[2][0] * q[2][2]);\n}\n"
  },
  {
    "path": "examples/advent2024/day14_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/14\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day14_common\";\nimport library \"io_utils\";\n\n// Returns m and n so that am + bn = gcd.\nfn Euclid(a: i32, b: i32) -> {.m: i32, .n: i32, .gcd: i32} {\n  if (a < b) {\n    let reverse: {.m: i32, .n: i32, .gcd: i32} = Euclid(b, a);\n    return {.m = reverse.n, .n = reverse.m, .gcd = reverse.gcd};\n  }\n  if (b == 0) {\n    return {.m = 1, .n = 0, .gcd = a};\n  }\n  let next: {.m: i32, .n: i32, .gcd: i32} = Euclid(b, a % b);\n  return {.m = next.n, .n = next.m - next.n * (a / b), .gcd = next.gcd};\n}\n\n// Uses Chinese remainder theorem to find the least positive x that solves\n//   x = a mod p\n//   x = b mod q\n// modulo pq / gcd(p,q), if one exists (if a = b mod gcd(p,q)).\nfn CRT(a: i32, b: i32, p: i32, q: i32) -> i32 {\n  let e: {.m: i32, .n: i32, .gcd: i32} = Euclid(p, q);\n  let x: i32 = a * (q / e.gcd) * e.n + b * (p / e.gcd) * e.m;\n  return Mod(x, p * (q / e.gcd));\n}\n\nfn PrintState(r: array(Robot, 500), t: i32) {\n  var display: array(array(char, 101), 103);\n\n  for (y: i32 in Core.Range(103)) {\n    for (x: i32 in Core.Range(101)) {\n      display[y][x] = '.';\n    }\n  }\n\n  for (ri: Robot in r) {\n    let xy: (i32, i32) = ri.Pos(t);\n    display[xy.1][xy.0] = '#';\n  }\n\n  for (y: i32 in Core.Range(103)) {\n    for (x: i32 in Core.Range(101)) {\n      Core.PrintChar(display[y][x]);\n    }\n    Core.PrintChar('\\n');\n  }\n}\n\nfn Run() {\n  var r: array(Robot, 500);\n  for (i: i32 in Core.Range(500)) {\n    r[i] = Robot.Read();\n  }\n\n  let first_match_x: i32 = 28;\n  let first_match_y: i32 = 84;\n\n  var t: i32 = CRT(first_match_x, first_match_y, 101, 103);\n  Core.Print(t);\n  PrintState(r, t);\n}\n"
  },
  {
    "path": "examples/advent2024/day15_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/15\n\nlibrary \"day15_common\";\n\nimport Core library \"io\";\nimport library \"io_utils\";\n\n// TODO: Use a choice type.\nclass Square {\n  adapt char;\n\n  impl as Core.Copy {\n    fn Op[self: Self]() -> Self {\n      return (self as char).(Core.Copy.Op)() as Self;\n    }\n  }\n  impl as Core.EqWith(Square) {\n    fn Equal[self: Self](other: Self) -> bool {\n      // TODO: Use a `char` comparison when it's supported.\n      return (self as u8) == (other as u8);\n    }\n    fn NotEqual[self: Self](other: Self) -> bool {\n      // TODO: Use a `char` comparison when it's supported.\n      return (self as u8) != (other as u8);\n    }\n  }\n\n  fn Make(c: CharOrEOF) -> Square {\n    // TODO: Use `match`.\n    if (c == '#') { return ('#' as char) as Square; }\n    if (c == 'O') { return ('O' as char) as Square; }\n    if (c == '.') { return ('.' as char) as Square; }\n    if (c == '@') { return ('@' as char) as Square; }\n    return ('!' as char) as Square;\n  }\n}\n\nlet Wall: Square = ('#' as char) as Square;\nlet Box: Square = ('O' as char) as Square;\nlet Empty: Square = ('.' as char) as Square;\nlet Robot: Square = ('@' as char) as Square;\n\nclass Grid {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Grid {\n    returned var me: Grid;\n    var y: i32 = 0;\n    while (y < 50) {\n      var x: i32 = 0;\n      while (x < 50) {\n        me.data[x][y] = Square.Make(ReadChar());\n        if (me.data[x][y] == Robot) {\n          me.robot = (x, y);\n        }\n        ++x;\n      }\n      SkipNewline();\n      ++y;\n    }\n    return var;\n  }\n\n  fn Move[ref self: Self](d: (i32, i32)) {\n    var distance: i32 = 1;\n    while (self.data[self.robot.0 + distance * d.0][self.robot.1 + distance * d.1] == Box) {\n      ++distance;\n    }\n    if (self.data[self.robot.0 + distance * d.0][self.robot.1 + distance * d.1] == Empty) {\n      self.data[self.robot.0][self.robot.1] = Empty;\n      self.data[self.robot.0 + distance * d.0][self.robot.1 + distance * d.1] = Box;\n      self.data[self.robot.0 + d.0][self.robot.1 + d.1] = Robot;\n      self.robot.0 += d.0;\n      self.robot.1 += d.1;\n    }\n  }\n\n  fn Print[self: Self]() {\n    var y: i32 = 0;\n    while (y < 50) {\n      var x: i32 = 0;\n      while (x < 50) {\n        Core.PrintChar(self.data[x][y] as char);\n        ++x;\n      }\n      Core.PrintChar('\\n');\n      ++y;\n    }\n    Core.PrintChar('\\n');\n  }\n\n  fn Signature[self: Self]() -> i32 {\n    var s: i32 = 0;\n    var y: i32 = 0;\n    while (y < 50) {\n      var x: i32 = 0;\n      while (x < 50) {\n        if (self.data[x][y] == Box) {\n          s += y * 100 + x;\n        }\n        ++x;\n      }\n      ++y;\n    }\n    return s;\n  }\n\n  var data: array(array(Square, 50), 50);\n  var robot: (i32, i32);\n}\n\nfn ReadAndExecuteActions(ref g: Grid) {\n  while (true) {\n    var m: CharOrEOF = ReadChar();\n    // To watch the progress, uncomment the following:\n    // g.Print();\n    // Core.PrintChar(((m as i32) as u8) as char);\n    // Core.PrintChar('\\n');\n    // TODO: Use `match` once it's available.\n    if (m == '^') {\n      g.Move((0, -1));\n    } else if (m == '<') {\n      g.Move((-1, 0));\n    } else if (m == '>') {\n      g.Move((1, 0));\n    } else if (m == 'v') {\n      g.Move((0, 1));\n    } else if (m == CharOrEOF.EOF()) {\n      return;\n    }\n  }\n}\n"
  },
  {
    "path": "examples/advent2024/day15_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/15\n\nimport Core library \"io\";\n\nimport library \"day15_common\";\n\nfn Run() {\n  var g: Grid = Grid.Read();\n  ReadAndExecuteActions(ref g);\n  Core.Print(g.Signature());\n}\n"
  },
  {
    "path": "examples/advent2024/day1_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/1\n\nlibrary \"day1_common\";\n\nimport Core library \"range\";\n\nimport library \"io_utils\";\n\n// Read a sequence of lines each containing a pair of numbers into two arrays.\n// Returns the number of lines read.\nfn ReadInputs[N:! Core.IntLiteral()](ref a: array(i32, N), ref b: array(i32, N)) -> i32 {\n  for (i: i32 in Core.Range(N)) {\n    var av: i32;\n    var bv: i32;\n    if (ReadInt(ref av) and SkipSpaces() and ReadInt(ref bv) and SkipNewline()) {\n      a[i] = av;\n      b[i] = bv;\n    } else {\n      return i;\n    }\n  }\n  return N;\n}\n"
  },
  {
    "path": "examples/advent2024/day1_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/1\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day1_common\";\nimport library \"sort\";\n\nfn Abs(n: i32) -> i32 { return if n < 0 then -n else n; }\n\nfn Run() {\n  var a: array(i32, 1000);\n  var b: array(i32, 1000);\n  let n: i32 = ReadInputs(ref a, ref b);\n  Quicksort(ref a, 0, n);\n  Quicksort(ref b, 0, n);\n\n  var difference: i32 = 0;\n  for (i: i32 in Core.Range(n)) {\n    difference += Abs(a[i] - b[i]);\n  }\n  Core.Print(difference);\n}\n"
  },
  {
    "path": "examples/advent2024/day1_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/1\n\nimport Core library \"io\";\n\nimport library \"day1_common\";\nimport library \"sort\";\n\nfn Run() {\n  var a: array(i32, 1000);\n  var b: array(i32, 1000);\n  let n: i32 = ReadInputs(ref a, ref b);\n  Quicksort(ref a, 0, n);\n  Quicksort(ref b, 0, n);\n\n  var i: i32 = 0;\n  var j: i32 = 0;\n  var similarity: i32 = 0;\n  while (i < n and j < n) {\n    if (a[i] < b[j]) {\n      ++i;\n    } else {\n      if (a[i] == b[j]) {\n        similarity += b[j];\n      }\n      ++j;\n    }\n  }\n  Core.Print(similarity);\n}\n"
  },
  {
    "path": "examples/advent2024/day2_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/2\n\nlibrary \"day2_common\";\n\nfn Abs(n: i32) -> i32 {\n  return if n < 0 then -n else n;\n}\n\nfn IsSafeDelta(from: i32, to: i32) -> bool {\n  return from != to and Abs(from - to) <= 3;\n}\n"
  },
  {
    "path": "examples/advent2024/day2_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/2\n\nimport Core library \"io\";\n\nimport library \"day2_common\";\nimport library \"io_utils\";\n\nclass ReportState {\n  fn Make() -> ReportState {\n    return {.levels_so_far = 0, .previous = 0,\n            .increasing = false, .safe_so_far = true};\n  }\n\n  fn Add[ref self: Self](level: i32) {\n    ++self.levels_so_far;\n    if (self.levels_so_far >= 2) {\n      if (not IsSafeDelta(self.previous, level)) {\n        // Difference is zero or too large.\n        self.safe_so_far = false;\n      }\n\n      var is_increase: bool = level > self.previous;\n      if (self.levels_so_far == 2) {\n        self.increasing = is_increase;\n      } else if (is_increase != self.increasing) {\n        // Not monotone.\n        self.safe_so_far = false;\n      }\n    }\n    self.previous = level;\n  }\n\n  var levels_so_far: i32;\n  var previous: i32;\n  var increasing: bool;\n  var safe_so_far: bool;\n}\n\nfn ReadReport() -> ReportState {\n  returned var report: ReportState = ReportState.Make();\n  var n: i32;\n  while (ReadInt(ref n)) {\n    report.Add(n);\n    SkipSpaces();\n  }\n  return var;\n}\n\nfn Run() {\n  var safe_reports: i32 = 0;\n  while (true) {\n    var report: ReportState = ReadReport();\n    if (report.levels_so_far == 0) {\n      break;\n    }\n    if (report.safe_so_far) {\n      ++safe_reports;\n    }\n    SkipNewline();\n  }\n  Core.Print(safe_reports);\n}\n"
  },
  {
    "path": "examples/advent2024/day2_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/2\n\nimport Core library \"io\";\n\nimport library \"day2_common\";\nimport library \"io_utils\";\n\n// A three-element sliding window of recent levels.\nclass Window {\n  fn Make() -> Window { return {.data = (0,0,0), .size = 0}; }\n  fn Add[ref self: Self](n: i32) {\n    self.data[2] = self.data[1];\n    self.data[1] = self.data[0];\n    self.data[0] = n;\n    ++self.size;\n  }\n\n  var data: array(i32, 3);\n  var size: i32;\n}\n\n// Determines whether a transition from `from` to `to` is safe.\nfn IsSafe(from: i32, to: i32, want_increase: bool) -> bool {\n  var is_increase: bool = to > from;\n  return IsSafeDelta(from, to) and is_increase == want_increase;\n}\n\nclass ReportState {\n  fn Make(increasing: bool) -> ReportState {\n    return {.increasing = increasing, .bad_edges = 0,\n            .removable_single_bad_edge = false,\n            .removable_double_bad_edge = false};\n  }\n\n  fn OnAdd[ref self: Self](window: Window) {\n    if (window.size < 2) {\n      return;\n    }\n\n    // We label the three most recent levels as `a b c`, with `c` the most\n    // recent. We might not have an `a`.\n    let b: i32 = window.data[1];\n    let c: i32 = window.data[0];\n\n    // Keep a count of the unsafe edges.\n    let b_to_c: bool = IsSafe(window.data[1], window.data[0], self.increasing);\n    if (not b_to_c) {\n      ++self.bad_edges;\n\n      // We have a removable single bad edge if the first edge is unsafe.\n      if (window.size == 2) {\n        self.removable_single_bad_edge = true;\n      }\n    }\n\n    if (window.size >= 3) {\n      let a: i32 = window.data[2];\n      if (IsSafe(a, c, self.increasing)) {\n        let lhs: bool = IsSafe(a, b, self.increasing);\n        let rhs: bool = b_to_c;\n        if (not lhs and not rhs) {\n          // If a->b and b->c are both unsafe, but a->c is safe,\n          // then we have a removable double bad edge.\n          self.removable_double_bad_edge = true;\n        } else if (not lhs or not rhs) {\n          // If a->b or b->c is unsafe but a->c is safe, then we have a\n          // removable single bad edge.\n          self.removable_single_bad_edge = true;\n        }\n      }\n    }\n  }\n\n  fn OnFinish[ref self: Self](window: Window) {\n    if (window.size >= 2 and\n        not IsSafe(window.data[1], window.data[0], self.increasing)) {\n      // We have a removable single bad edge if the last edge is unsafe.\n      self.removable_single_bad_edge = true;\n    }\n  }\n\n  fn IsSafeWithRemoval[self: Self]() -> bool {\n    return self.bad_edges == 0 or\n           (self.bad_edges == 1 and self.removable_single_bad_edge) or\n           (self.bad_edges == 2 and self.removable_double_bad_edge);\n  }\n\n  var increasing: bool;\n  var bad_edges: i32;\n  var removable_single_bad_edge: bool;\n  var removable_double_bad_edge: bool;\n}\n\nfn ReadAndCheckReport() -> bool {\n  var window: Window = Window.Make();\n  var increasing: ReportState = ReportState.Make(true);\n  var decreasing: ReportState = ReportState.Make(false);\n  var n: i32;\n  while (ReadInt(ref n)) {\n    window.Add(n);\n    increasing.OnAdd(window);\n    decreasing.OnAdd(window);\n    SkipSpaces();\n  }\n  increasing.OnFinish(window);\n  decreasing.OnFinish(window);\n  return window.size > 0 and\n         (increasing.IsSafeWithRemoval() or decreasing.IsSafeWithRemoval());\n}\n\nfn Run() {\n  var safe_reports: i32 = 0;\n  while (true) {\n    if (ReadAndCheckReport()) {\n      ++safe_reports;\n    }\n    if (not SkipNewline()) {\n      break;\n    }\n  }\n  Core.Print(safe_reports);\n}\n"
  },
  {
    "path": "examples/advent2024/day3_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/3\n\nlibrary \"day3_common\";\n\nimport library \"io_utils\";\n\n// Reads \"mul(a,b)\", and returns (true, a, b).\n// On error, stops before the first invalid character and returns (false, 0, 0).\n// TODO: -> Optional((i32, i32))\nfn ReadMul() -> (bool, i32, i32) {\n  var a: i32;\n  var b: i32;\n  if (ConsumeChar('m') and ConsumeChar('u') and ConsumeChar('l') and\n      ConsumeChar('(') and ReadInt(ref a) and ConsumeChar(',') and\n      ReadInt(ref b) and ConsumeChar(')')) {\n    return (true, a, b);\n  }\n  return (false, 0, 0);\n}\n\n// Reads \"do()\" or \"don't()\", and returns (true, was_do).\n// On error, stops before the first invalid character and returns (false, false).\nfn ReadDoOrDont() -> (bool, bool) {\n  // \"do\"\n  if (not ConsumeChar('d') or not ConsumeChar('o')) {\n    return (false, false);\n  }\n\n  var do: bool = true;\n  // \"n't\"\n  if (ConsumeChar('n')) {\n    if (not ConsumeChar('\\'') or not ConsumeChar('t')) {\n      return (false, false);\n    }\n    do = false;\n  }\n\n  // \"()\"\n  if (not ConsumeChar('(') or not ConsumeChar(')')) {\n    return (false, false);\n  }\n  return (true, do);\n}\n"
  },
  {
    "path": "examples/advent2024/day3_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/3\n\nimport Core library \"io\";\n\nimport library \"day3_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var total: i32 = 0;\n  while (PeekChar() != CharOrEOF.EOF()) {\n    if (PeekChar() == 'm') {\n      // TODO: Use `if let` when available.\n      let result: (bool, i32, i32) = ReadMul();\n      if (result.0) {\n        total += result.1 * result.2;\n      }\n    } else {\n      ReadChar();\n    }\n  }\n  Core.Print(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day3_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/3\n\nimport Core library \"io\";\n\nimport library \"day3_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var total: i32 = 0;\n  var enabled: bool = true;\n  while (PeekChar() != CharOrEOF.EOF()) {\n    if (PeekChar() == 'm') {\n      // TODO: Use `if let` when available.\n      let result: (bool, i32, i32) = ReadMul();\n      if (result.0 and enabled) {\n        total += result.1 * result.2;\n      }\n    } else if (PeekChar() == 'd') {\n      // TODO: Use `if let` when available.\n      let result: (bool, bool) = ReadDoOrDont();\n      if (result.0) {\n        enabled = result.1;\n      }\n    } else {\n      ReadChar();\n    }\n  }\n  Core.Print(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day4_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/4\n\nlibrary \"day4_common\";\n\nimport library \"io_utils\";\n\nclass Wordsearch {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Wordsearch {\n    returned var s: Wordsearch;\n    // TODO: Use for loops once they're implemented.\n    var y: i32 = 0;\n    while (y < 140) {\n      var x: i32 = 0;\n      while (x < 140) {\n        // TODO: Assert on failure.\n        s.grid[x][y] = ReadChar() as i32;\n        ++x;\n      }\n      // TODO: Assert on failure.\n      SkipNewline();\n      ++y;\n    }\n    return var;\n  }\n\n  fn At[self: Self](x: i32, y: i32) -> i32 {\n    return if x < 0 or x >= 140 or y < 0 or y >= 140 then -1 else self.grid[x][y];\n  }\n\n  // TODO: Make this generic in the length of the search query.\n  fn Check4[self: Self](xmas: array(i32, 4), x: i32, y: i32, dx: i32, dy: i32) -> bool {\n    var i: i32 = 0;\n    while (i < 4) {\n      if (self.At(x + i * dx, y + i * dy) != xmas[i]) {\n        return false;\n      }\n      ++i;\n    }\n    return true;\n  }\n\n  fn Check3[self: Self](mas: array(i32, 3), x: i32, y: i32, dx: i32, dy: i32) -> bool {\n    var i: i32 = 0;\n    while (i < 3) {\n      if (self.At(x + i * dx, y + i * dy) != mas[i]) {\n        return false;\n      }\n      ++i;\n    }\n    return true;\n  }\n\n  var grid: array(array(i32, 140), 140);\n}\n"
  },
  {
    "path": "examples/advent2024/day4_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/4\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day4_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var search: Wordsearch = Wordsearch.Read();\n  var xmas: array(i32, 4) = (0x58, 0x4D, 0x41, 0x53);\n  var found: i32 = 0;\n\n  for (y: i32 in Core.Range(140)) {\n    for (x: i32 in Core.Range(140)) {\n      for (dy: i32 in Core.InclusiveRange(-1, 1)) {\n        for (dx: i32 in Core.InclusiveRange(-1, 1)) {\n          if (search.Check4(xmas, x, y, dx, dy)) {\n            ++found;\n          }\n        }\n      }\n    }\n  }\n  Core.Print(found);\n}\n"
  },
  {
    "path": "examples/advent2024/day4_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/4\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day4_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var search: Wordsearch = Wordsearch.Read();\n  var mas: array(i32, 3) = (0x4D, 0x41, 0x53);\n  var found: i32 = 0;\n\n  for (y: i32 in Core.InclusiveRange(1, 138)) {\n    for (x: i32 in Core.InclusiveRange(1, 138)) {\n      if ((search.Check3(mas, x - 1, y - 1, 1, 1) or\n           search.Check3(mas, x + 1, y + 1, -1, -1)) and\n          (search.Check3(mas, x - 1, y + 1, 1, -1) or\n           search.Check3(mas, x + 1, y - 1, -1, 1))) {\n        ++found;\n      }\n    }\n  }\n  Core.Print(found);\n}\n"
  },
  {
    "path": "examples/advent2024/day5_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/5\n\nlibrary \"day5_common\";\n\nimport Core library \"range\";\n\nimport library \"io_utils\";\n\nfn PageMask(page: i32) -> Core.UInt(100) {\n  // TODO: return (1 as Core.UInt(100)) << page;\n  return (1 as Core.UInt(100)) << (page as Core.UInt(100));\n}\n\nclass Rules {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Rules {\n    returned var rules: Rules;\n    for (i: i32 in Core.Range(100)) {\n      rules.disallowed_before[i] = 0;\n    }\n\n    var a: i32;\n    var b: i32;\n    while (ReadInt(ref a) and ConsumeChar('|') and ReadInt(ref b)) {\n      rules.disallowed_before[a] |= PageMask(b);\n      SkipNewline();\n    }\n    return var;\n  }\n\n  fn IsValidOrder[self: Self](a: i32, b: i32) -> bool {\n    return self.disallowed_before[b] & PageMask(a) == 0;\n  }\n\n  var disallowed_before: array(Core.UInt(100), 100);\n};\n\nclass PageList {\n  impl as Core.UnformedInit {}\n\n  fn Empty() -> PageList {\n    returned var me: PageList;\n    me.num_pages = 0;\n    return var;\n  }\n\n  fn Read() -> PageList {\n    returned var me: PageList = Empty();\n\n    var page: i32;\n    if (not ReadInt(ref page)) {\n      return var;\n    }\n    me.Add(page);\n    while (ConsumeChar(',')) {\n      ReadInt(ref page);\n      me.Add(page);\n    }\n    SkipNewline();\n    return var;\n  }\n\n  fn Add[ref self: Self](page: i32) {\n    self.pages[self.num_pages] = page;\n    ++self.num_pages;\n  }\n\n  fn FollowsRules[self: Self](rules: Rules) -> bool {\n    var seen: Core.UInt(100) = 0;\n    for (i: i32 in Core.Range(self.num_pages)) {\n      let page: i32 = self.pages[i];\n      if (seen & rules.disallowed_before[page] != 0) {\n        return false;\n      }\n      seen |= PageMask(page);\n    }\n    return true;\n  }\n\n  fn IsPossibleFirstPage[self: Self](rules: Rules, page: i32) -> bool {\n    for (i: i32 in Core.Range(self.num_pages)) {\n      if (not rules.IsValidOrder(page, self.pages[i])) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  fn ExtractPossibleFirstPage[ref self: Self](rules: Rules) -> i32 {\n    for (i: i32 in Core.Range(self.num_pages)) {\n      var page: i32 = self.pages[i];\n      if (self.IsPossibleFirstPage(rules, page)) {\n        self.pages[i] = self.pages[self.num_pages - 1];\n        --self.num_pages;\n        return page;\n      }\n    }\n    // TODO: Assert.\n    return 0;\n  }\n\n  fn MiddlePage[self: Self]() -> i32 {\n    return self.pages[self.num_pages / 2];\n  }\n\n  var pages: array(i32, 24);\n  var num_pages: i32;\n};\n"
  },
  {
    "path": "examples/advent2024/day5_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/5\n\nimport Core library \"io\";\n\nimport library \"day5_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var rules: Rules = Rules.Read();\n  SkipNewline();\n  var total: i32 = 0;\n  while (true) {\n    var page_list: PageList = PageList.Read();\n    if (page_list.num_pages == 0) {\n      break;\n    }\n    if (page_list.FollowsRules(rules)) {\n      total += page_list.MiddlePage();\n    }\n  }\n  Core.Print(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day5_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/5\n\nimport Core library \"io\";\n\nimport library \"day5_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var rules: Rules = Rules.Read();\n  SkipNewline();\n  var total: i32 = 0;\n  while (true) {\n    var page_list: PageList = PageList.Read();\n    if (page_list.num_pages == 0) {\n      break;\n    }\n    if (page_list.FollowsRules(rules)) {\n      continue;\n    }\n    var new_page_list: PageList = PageList.Empty();\n    while (page_list.num_pages != 0) {\n      new_page_list.Add(page_list.ExtractPossibleFirstPage(rules));\n    }\n    total += new_page_list.MiddlePage();\n  }\n  Core.Print(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day6_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/6\n\nlibrary \"day6_common\";\n\nimport Core library \"io\";\nimport library \"io_utils\";\n\n// TODO: Use a choice type.\nfn Empty() -> i8 { return 0; }\nfn Visited() -> i8 { return 1; }\nfn Wall() -> i8 { return 2; }\n\nclass Maze {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Maze {\n    returned var me: Maze;\n\n    var y: i32 = 0;\n    while (y < 130) {\n      var x: i32 = 0;\n      while (x < 130) {\n        var cell: i32 = Core.ReadChar();\n        if (cell == 0x23) {\n          me.data[x][y] = Wall();\n        } else if (cell == 0x5E) {\n          // TODO: Handle other starting directions?\n          me.data[x][y] = Visited();\n          me.loc = (x, y);\n          me.dir = (0, -1);\n        } else {\n          me.data[x][y] = Empty();\n        }\n        ++x;\n      }\n      SkipNewline();\n      ++y;\n    }\n    return var;\n  }\n\n  fn Copy[self: Self]() -> Maze {\n    returned var copy: Maze;\n    var y: i32 = 0;\n    while (y < 130) {\n      var x: i32 = 0;\n      while (x < 130) {\n        copy.data[x][y] = self.data[x][y];\n        ++x;\n      }\n      ++y;\n    }\n    copy.loc = self.loc;\n    copy.dir = self.dir;\n    return var;\n  }\n\n  fn Step[ref self: Self]() -> bool {\n    let x: i32 = self.loc.0 + self.dir.0;\n    let y: i32 = self.loc.1 + self.dir.1;\n    if (x < 0 or x >= 130 or y < 0 or y >= 130) {\n      return false;\n    }\n    if (self.data[x][y] == Wall()) {\n      // TODO: Should this work?\n      // self.dir = (-self.dir.1, self.dir.0);\n      let d: (i32, i32) = self.dir;\n      self.dir = (-d.1, d.0);\n    } else {\n      self.loc = (x, y);\n      self.data[x][y] = Visited();\n    }\n    return true;\n  }\n\n  fn AddObstacle[ref self: Self]() -> bool {\n    let x: i32 = self.loc.0 + self.dir.0;\n    let y: i32 = self.loc.1 + self.dir.1;\n    if (x < 0 or x >= 130 or y < 0 or y >= 130) {\n      return false;\n    }\n    if (self.data[x][y] != Empty()) {\n      return false;\n    }\n    self.data[x][y] = Wall();\n    return true;\n  }\n\n  fn CountVisited[self: Self]() -> i32 {\n    var total: i32 = 0;\n    var y: i32 = 0;\n    while (y < 130) {\n      var x: i32 = 0;\n      while (x < 130) {\n        if (self.data[x][y] == Visited()) {\n          ++total;\n        }\n        ++x;\n      }\n      ++y;\n    }\n    return total;\n  }\n\n  var data: array(array(i8, 130), 130);\n  var loc: (i32, i32);\n  var dir: (i32, i32);\n}\n"
  },
  {
    "path": "examples/advent2024/day6_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/6\n\nimport Core library \"io\";\n\nimport library \"day6_common\";\n\nfn Run() {\n  var maze: Maze = Maze.Read();\n  while (maze.Step()) {\n  }\n  Core.Print(maze.CountVisited());\n}\n"
  },
  {
    "path": "examples/advent2024/day6_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/6\n\nimport Core library \"io\";\n\nimport library \"day6_common\";\n\nclass LoopDetector {\n  fn Make() -> LoopDetector {\n    return {.last = ((-1, -1), (-1, -1)), .steps = 1, .next_steps = 1};\n  }\n\n  fn Check[ref self: Self](next: ((i32, i32), (i32, i32))) -> bool {\n    // TODO: if (next == self.last) {\n    if (next.0.0 == self.last.0.0 and next.0.1 == self.last.0.1 and\n        next.1.0 == self.last.1.0 and next.1.1 == self.last.1.1) {\n      return true;\n    }\n    --self.steps;\n    if (self.steps == 0) {\n      self.steps = self.next_steps;\n      self.next_steps <<= 1;\n      self.last = next;\n    }\n    return false;\n  }\n\n  var last: ((i32, i32), (i32, i32));\n  var steps: i32;\n  var next_steps: i32;\n}\n\nfn AddingObstacleMakesALoop(position: Maze) -> bool {\n  var maze: Maze = position.Copy();\n  var loop: LoopDetector = LoopDetector.Make();\n  if (not maze.AddObstacle()) {\n    return false;\n  }\n  while (maze.Step()) {\n    if (loop.Check((maze.loc, maze.dir))) {\n      return true;\n    }\n  }\n  return false;\n}\n\nfn Run() {\n  var maze: Maze = Maze.Read();\n  var loops: i32 = 0;\n  while (true) {\n    if (AddingObstacleMakesALoop(maze)) {\n      ++loops;\n    }\n    if (not maze.Step()) {\n      break;\n    }\n  }\n  Core.Print(loops);\n}\n"
  },
  {
    "path": "examples/advent2024/day7_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/7\n\nlibrary \"day7_common\";\n\nimport Core library \"io\";\nimport library \"io_utils\";\n\nfn Concat(a_val: i64, b_val: i64) -> i64 {\n  var a: i64 = a_val;\n  var b: i64 = b_val;\n  if (b == 0) {\n    return a * 10;\n  }\n  while (b != 0) {\n    a *= 10;\n    b /= 10;\n  }\n  return a + b_val;\n}\n\nclass Equation {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Equation {\n    returned var me: Equation;\n    me.num_operands = 0;\n    ReadInt(ref me.result);\n    ConsumeChar(':');\n    while (ConsumeChar(' ')) {\n      ReadInt(ref me.operands[me.num_operands]);\n      ++me.num_operands;\n    }\n    while (SkipNewline()) {}\n    return var;\n  }\n\n  fn SolveFrom[self: Self](start: i32, value: i64, concat: bool) -> bool {\n    if (value > self.result) {\n      return false;\n    }\n    if (start == self.num_operands) {\n      return value == self.result;\n    }\n    return self.SolveFrom(start + 1, value + self.operands[start], concat) or\n           self.SolveFrom(start + 1, value * self.operands[start], concat) or\n           (concat and self.SolveFrom(start + 1, Concat(value, self.operands[start]), true));\n  }\n\n  fn Solve[self: Self](concat: bool) -> bool {\n    return self.SolveFrom(1, self.operands[0], concat);\n  }\n\n  var operands: array(i64, 16);\n  var num_operands: i32;\n  var result: i64;\n}\n"
  },
  {
    "path": "examples/advent2024/day7_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/7\n\nimport Core library \"io\";\n\nimport library \"day7_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var total: i64 = 0;\n  while (PeekChar() != CharOrEOF.EOF()) {\n    var eq: Equation = Equation.Read();\n    if (eq.Solve(false)) {\n      total += eq.result;\n    }\n  }\n  PrintInt(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day7_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/7\n\nimport Core library \"io\";\n\nimport library \"day7_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var total: i64 = 0;\n  while (PeekChar() != CharOrEOF.EOF()) {\n    var eq: Equation = Equation.Read();\n    if (eq.Solve(true)) {\n      total += eq.result;\n    }\n  }\n  PrintInt(total);\n}\n"
  },
  {
    "path": "examples/advent2024/day8_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/8\n\nlibrary \"day8_common\";\n\nimport Core library \"io\";\nimport Core library \"range\";\nimport library \"io_utils\";\n\nclass Grid {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> Grid {\n    returned var me: Grid;\n    for (y: i32 in Core.Range(50)) {\n      for (x: i32 in Core.Range(50)) {\n        me.data[x][y] = ReadChar() as i32;\n      }\n      SkipNewline();\n    }\n    return var;\n  }\n\n  var data: array(array(i32, 50), 50);\n}\n"
  },
  {
    "path": "examples/advent2024/day8_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/8\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day8_common\";\nimport library \"io_utils\";\n\nfn IsAntinode(grid: Grid, ox: i32, oy: i32) -> bool {\n  for (ay: i32 in Core.Range(50)) {\n    let by: i32 = ay * 2 - oy;\n    if (by >= 0 and by < 50) {\n      for (ax: i32 in Core.Range(50)) {\n        let bx: i32 = ax * 2 - ox;\n        if (bx >= 0 and bx < 50 and (ax != bx or ay != by)) {\n          if (grid.data[ax][ay] != 0x2E and\n              grid.data[ax][ay] == grid.data[bx][by]) {\n            return true;\n          }\n        }\n      }\n    }\n  }\n  return false;\n}\n\nfn CountAntinodes(grid: Grid) -> i32 {\n  var count: i32 = 0;\n  for (y: i32 in Core.Range(50)) {\n    for (x: i32 in Core.Range(50)) {\n      if (IsAntinode(grid, x, y)) {\n        ++count;\n      }\n    }\n  }\n  return count;\n}\n\nfn Run() {\n  Core.Print(CountAntinodes(Grid.Read()));\n}\n"
  },
  {
    "path": "examples/advent2024/day8_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/8\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nimport library \"day8_common\";\nimport library \"io_utils\";\n\nfn MarkAndCount(marks: array(array(bool, 50), 50)*, x: i32, y: i32) -> i32 {\n  if (not (*marks)[x][y]) {\n    (*marks)[x][y] = true;\n    return 1;\n  }\n  return 0;\n}\n\nfn MarkAndCountAntinodesFor(grid: Grid, marks: array(array(bool, 50), 50)*, ax: i32, ay: i32) -> i32 {\n  var count: i32 = 0;\n  for (by: i32 in Core.Range(50)) {\n    for (bx: i32 in Core.Range(50)) {\n      let dx: i32 = bx - ax;\n      let dy: i32 = by - ay;\n      if (grid.data[bx][by] != grid.data[ax][ay] or (dx == 0 and dy == 0)) {\n        continue;\n      }\n\n      var x: i32 = bx;\n      var y: i32 = by;\n      while (x >= 0 and x < 50 and y >= 0 and y < 50) {\n        count += MarkAndCount(marks, x, y);\n        x += dx;\n        y += dy;\n      }\n    }\n  }\n  return count;\n}\n\nfn MarkAndCountAntinodes(grid: Grid, marks: array(array(bool, 50), 50)*) -> i32 {\n  var count: i32 = 0;\n  for (y: i32 in Core.Range(50)) {\n    for (x: i32 in Core.Range(50)) {\n      if (grid.data[x][y] != 0x2E) {\n        count += MarkAndCountAntinodesFor(grid, marks, x, y);\n      }\n    }\n  }\n  return count;\n}\n\nfn Run() {\n  var marks: array(array(bool, 50), 50);\n  for (y: i32 in Core.Range(50)) {\n    for (x: i32 in Core.Range(50)) {\n      marks[x][y] = false;\n    }\n  }\n\n  Core.Print(MarkAndCountAntinodes(Grid.Read(), &marks));\n}\n"
  },
  {
    "path": "examples/advent2024/day9_common.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/9\n\nlibrary \"day9_common\";\n\nimport Core library \"io\";\nimport Core library \"range\";\nimport library \"io_utils\";\n\nclass SectorList {\n  impl as Core.UnformedInit {}\n\n  fn Read() -> SectorList {\n    returned var me: SectorList;\n    me.size = 0;\n    var sector: i32 = 0;\n    var used: bool = true;\n    // TODO: An assignment expression would be useful here.\n    var c: CharOrEOF = ReadChar();\n    while (c != CharOrEOF.EOF() and c != '\\n') {\n      let v: i32 = if used then sector else -1;\n      for (_: i32 in Core.Range(c - '0')) {\n        me.data[me.size] = v;\n        ++me.size;\n      }\n      if (used) {\n        ++sector;\n      }\n      used = not used;\n      c = ReadChar();\n    }\n    return var;\n  }\n\n  fn DefragBlocks[ref self: Self]() {\n    var i: i32 = 0;\n    var j: i32 = self.size - 1;\n    while (j > i) {\n      if (self.data[i] != -1) {\n        ++i;\n      } else if (self.data[j] == -1) {\n        --j;\n      } else {\n        self.data[i] = self.data[j];\n        ++i;\n        --j;\n      }\n    }\n    self.size = j;\n  }\n\n  fn HasSpace[ref self: Self](start: i32, size: i32) -> bool {\n    for (i: i32 in Core.InclusiveRange(start, start + size - 1)) {\n      if (self.data[i] != -1) {\n        return false;\n      }\n    }\n    return true;\n  }\n\n  fn Fill[ref self: Self](start: i32, size: i32, sector: i32) {\n    for (i: i32 in Core.InclusiveRange(start, start + size - 1)) {\n      self.data[i] = sector;\n    }\n  }\n\n  fn DefragFiles[ref self: Self]() {\n    var j: i32 = self.size - 1;\n    while (j >= 0) {\n      // Skip empty sectors.\n      while (j >= 0 and self.data[j] == -1) {\n        --j;\n      }\n\n      // Find the file size and sector and delete the file.\n      let last: i32 = j;\n      let sector: i32 = self.data[last];\n      while (j >= 0 and self.data[j] == sector) {\n        self.data[j] = -1;\n        --j;\n      }\n      let first: i32 = j + 1;\n      let size: i32 = last - first + 1;\n\n      // Find the first available space for the file.\n      var i: i32 = 0;\n      while (not self.HasSpace(i, size)) {\n        ++i;\n        if (i + size > first) {\n          // If it doesn't fit to the left of its old position, put it back\n          // where it was.\n          i = first;\n        }\n      }\n\n      // Insert it.\n      self.Fill(i, size, sector);\n    }\n  }\n\n  fn Checksum[self: Self]() -> i64 {\n    var total: i64 = 0;\n    for (i: i32 in Core.Range(self.size)) {\n      if (self.data[i] != -1) {\n        total = total + ((i * self.data[i]) as i64);\n      }\n    }\n    return total;\n  }\n\n  var data: array(i32, 200000);\n  var size: i32;\n}\n"
  },
  {
    "path": "examples/advent2024/day9_part1.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/9\n\nimport Core library \"io\";\n\nimport library \"day9_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var list: SectorList = SectorList.Read();\n  list.DefragBlocks();\n  PrintInt(list.Checksum());\n}\n"
  },
  {
    "path": "examples/advent2024/day9_part2.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// https://adventofcode.com/2024/day/9\n\nimport Core library \"io\";\n\nimport library \"day9_common\";\nimport library \"io_utils\";\n\nfn Run() {\n  var list: SectorList = SectorList.Read();\n  list.DefragFiles();\n  PrintInt(list.Checksum());\n}\n"
  },
  {
    "path": "examples/advent2024/io_utils.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nlibrary \"io_utils\";\n\nimport Core library \"io\";\nimport Core library \"range\";\n\nclass EOFType {}\n\nclass CharOrEOF {\n  adapt i32;\n\n  fn EOF() -> Self;\n}\n\nimpl CharOrEOF as Core.Copy {\n  fn Op[self: Self]() -> Self {\n    return (self as i32).(Core.Copy.Op)() as Self;\n  }\n}\n\nfn CharOrEOF.EOF() -> Self {\n  // Ordering between `CharOrEOF` and `char` treats EOF as less than all `char`\n  // values.\n  return (-1 as i32) as CharOrEOF;\n}\n\nimpl forall [U:! Core.ImplicitAs(char)] U as Core.ImplicitAs(CharOrEOF) {\n  fn Convert[self: char]() -> CharOrEOF {\n    return ((self as u8) as i32) as CharOrEOF;\n  }\n}\n\nimpl forall [U:! Core.ImplicitAs(CharOrEOF)]\n    CharOrEOF as Core.EqWith(U) {\n  fn Equal[self: Self](other: CharOrEOF) -> bool {\n    return (self as i32) == (other as i32);\n  }\n  fn NotEqual[self: Self](other: CharOrEOF) -> bool {\n    return (self as i32) != (other as i32);\n  }\n}\n\nimpl forall [U:! Core.ImplicitAs(CharOrEOF)]\n    CharOrEOF as Core.OrderedWith(U) {\n  fn Less[self: Self](other: CharOrEOF) -> bool {\n    return (self as i32) < (other as i32);\n  }\n  fn LessOrEquivalent[self: Self](other: CharOrEOF) -> bool {\n    return (self as i32) <= (other as i32);\n  }\n  fn Greater[self: Self](other: CharOrEOF) -> bool {\n    return (self as i32) > (other as i32);\n  }\n  fn GreaterOrEquivalent[self: Self](other: CharOrEOF) -> bool {\n    return (self as i32) >= (other as i32);\n  }\n}\n\nimpl forall [U:! Core.ImplicitAs(char)]\n    CharOrEOF as Core.SubWith(U) where .Result = i32 {\n  fn Op[self: Self](other: char) -> i32 {\n    return (self as i32) - ((other as u8) as i32);\n  }\n}\n\nvar unread_char: Core.Optional(CharOrEOF)\n  = Core.Optional(CharOrEOF).None();\n\nfn ReadChar() -> CharOrEOF {\n  if (unread_char.HasValue()) {\n    var result: CharOrEOF = unread_char.Get();\n    unread_char = Core.Optional(CharOrEOF).None();\n    return result;\n  }\n\n  var value: i32 = Core.ReadChar();\n  if (value == Core.EOF()) {\n    return CharOrEOF.EOF();\n  } else {\n    return value as CharOrEOF;\n  }\n}\n\nfn UnreadChar(c: CharOrEOF) {\n  // TODO: assert(unread_char == 0);\n  // TODO: unread_char = c;\n  unread_char = Core.Optional(CharOrEOF).Some(c);\n}\n\nfn PeekChar() -> CharOrEOF {\n  var next: CharOrEOF = ReadChar();\n  UnreadChar(next);\n  return next;\n}\n\nfn ConsumeChar(c: char) -> bool {\n  var next: CharOrEOF = ReadChar();\n  if (next != c) {\n    UnreadChar(next);\n    return false;\n  }\n  return true;\n}\n\nfn ReadInt[N:! Core.IntLiteral()](ref p: Core.Int(N)) -> bool {\n  var read_any_digits: bool = false;\n  let negative: bool = ConsumeChar('-');\n  // TODO: `p = 0;` crashes the toolchain, see\n  // https://github.com/carbon-language/carbon-lang/issues/6500.\n  p = (0 as i32) as Core.Int(N);\n\n  while (true) {\n    var c: CharOrEOF = ReadChar();\n    if (c < '0' or c > '9') {\n      UnreadChar(c);\n      break;\n    }\n    // TODO: Check for overflow.\n    // TODO: p *= 10; crashes the toolchain.\n    p *= (10 as i32) as Core.Int(N);\n    p += (c - '0') as Core.Int(N);\n    read_any_digits = true;\n  }\n  if (negative) {\n    p = -p;\n    if (not read_any_digits) {\n      UnreadChar('-');\n    }\n  }\n  return read_any_digits;\n}\n\nfn PrintIntNoNewline[N:! Core.IntLiteral()](n_val: Core.Int(N)) {\n  // TODO: var pow10: Core.Int(N) = 1; crashes the toolchain.\n  var pow10: Core.Int(N) = (1 as i32) as Core.Int(N);\n  var n: Core.Int(N) = n_val;\n  // TODO: let ten: Core.Int(N) = 10;\n  let ten: Core.Int(N) = (10 as i32) as Core.Int(N);\n  while (n / ten >= pow10) {\n    pow10 = pow10 * ten;\n  }\n  // TODO: while (pow10 != 0) {\n  while (pow10 != ((0 as i32) as Core.Int(N))) {\n    let d: Core.Int(N) = n / pow10;\n    // TODO: Core.PrintChar('0' + d);\n    Core.PrintChar(((d as u8) + (('0' as char) as u8)) as char);\n    n = n % pow10;\n    pow10 = pow10 / ten;\n  }\n}\n\nfn PrintInt[N:! Core.IntLiteral()](n_val: Core.Int(N)) {\n  PrintIntNoNewline(n_val);\n  Core.PrintChar('\\n');\n}\n\nfn SkipSpaces() -> bool {\n  var skipped_any_spaces: bool = false;\n  while (ConsumeChar(' ')) {\n    skipped_any_spaces = true;\n  }\n  return skipped_any_spaces;\n}\n\nfn SkipNewline() -> bool {\n  // Optional carriage return.\n  ConsumeChar('\\r');\n  // Newline.\n  // TODO: Unread the CR if it was present?\n  return ConsumeChar('\\n');\n}\n\nfn SkipNChars(n: i32) -> bool {\n  for (_: i32 in Core.Range(n)) {\n    if (ReadChar() == CharOrEOF.EOF()) {\n      return false;\n    }\n  }\n  return true;\n}\n"
  },
  {
    "path": "examples/advent2024/sort.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nlibrary \"sort\";\n\ninterface Ordered {\n  // extend require impls Core.OrderedWith(Self);\n  fn Less[self: Self](other: Self) -> bool;\n  fn LessOrEquivalent[self: Self](other: Self) -> bool;\n  fn Greater[self: Self](other: Self) -> bool;\n  fn GreaterOrEquivalent[self: Self](other: Self) -> bool;\n}\n\nimpl i32 as Ordered {\n  fn Less[self: Self](other: Self) -> bool { return self < other; }\n  fn LessOrEquivalent[self: Self](other: Self) -> bool { return self <= other; }\n  fn Greater[self: Self](other: Self) -> bool { return self > other; }\n  fn GreaterOrEquivalent[self: Self](other: Self) -> bool { return self >= other; }\n}\n\nfn Swap[T:! Core.Copy & Core.Destroy](ref from: T, ref to: T) {\n  var tmp: T = from;\n  from = to;\n  to = tmp;\n}\n\nfn Partition\n    [T:! Core.Copy & Core.Destroy & Ordered, N:! Core.IntLiteral()]\n    (ref a: array(T, N), from_in: i32, to_in: i32) -> i32 {\n  var pivot_index: i32 = from_in;\n  let pivot: T = a[pivot_index];\n  var from: i32 = from_in + 1;\n  var to: i32 = to_in;\n  while (from < to) {\n    // TODO: if (a[from] <= pivot) {\n    if (a[from].(Ordered.LessOrEquivalent)(pivot)) {\n      ++from;\n    // TODO: } else if ((*p)[to - 1] > pivot) {\n    } else if (a[to - 1].(Ordered.Greater)(pivot)) {\n      --to;\n    } else {\n      // Element at `from` is > pivot, and\n      // element at `to - 1` is <= pivot.\n      Swap(ref a[from], ref a[to - 1]);\n      ++from;\n      --to;\n    }\n  }\n  Swap(ref a[pivot_index], ref a[from - 1]);\n  return from - 1;\n}\n\nfn Quicksort\n    [T:! Core.Copy & Core.Destroy & Ordered, N:! Core.IntLiteral()]\n    (ref a: array(T, N), from: i32, to: i32) {\n  if (from + 1 >= to) { return; }\n  var pivot: i32 = Partition(ref a, from, to);\n  Quicksort(ref a, from, pivot);\n  Quicksort(ref a, pivot + 1, to);\n}\n"
  },
  {
    "path": "examples/bazel/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n#\n# Note that this is not a BUILD file that is part of the larger Carbon project, and\n# is not built by running `bazel build //examples/bazel/...`. This is its own\n# _distinct_ example Bazel project rooted at `examples/bazel`. You will need to\n# `cd` into this directory to interact with it.\n#\n# For more details about how to manually interact with this example, please see\n# the adjacent `MODULES.bazel` file.\n\nload(\"@rules_cc//cc:defs.bzl\", \"cc_binary\", \"cc_library\")\n\ncc_library(\n    name = \"example_lib\",\n    srcs = [\n        \"example_lib.cpp\",\n        \"example_lib.h\",\n    ],\n    # We force static linking here so we can test compilation without performing\n    # a full link that is more expensive with runtimes on demand.\n    linkstatic = 1,\n)\n\ncc_binary(\n    name = \"example\",\n    srcs = [\"example.cpp\"],\n    deps = [\":example_lib\"],\n)\n"
  },
  {
    "path": "examples/bazel/MODULE.bazel",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Example Bazel module that builds C++ with the Carbon toolchain.\n\nNote that this is at the root of an example Bazel project, not part of the\nlarger Carbon Bazel project. To interact with this example, you'll want to\n`cd examples/bazel` so that you can operate Bazel entirely within this example\n(sub-)project.\n\nOnce interacting with this subdirectory's project, you can use this and build\nwith the Carbon toolchain in a few different ways:\n\n1) Override the module with a local installation on the command line:\n   `bazel build --override_module=carbon_toolchain=/path/to/carbon_toolchain/installation/lib/carbon`\n\n2) Encode a local override into this file:\n   ```\n   local_path_override(\n       module_name = \"carbon_toolchain\",\n       path = \"/path/to/carbon_toolchain/installation/lib/carbon\",\n   )\n   ```\n\n3) Encode a archive override into this file:\n   ```\n   version = \"0.0.0-0.nightly.YYYY.MM.DD\"\n   archive_override(\n       module_name = \"carbon_toolchain\",\n       strip_prefix = \"carbon_toolchain-{0}/lib/carbon\".format(version),\n       urls = [\"https://github.com/carbon-language/carbon-lang/releases/download/v{0}/carbon_toolchain-{0}.tar.gz\".format(version)],\n   )\n   ```\n\n   Note: Initially, Bazel will warn about the lack of an `integrity` field,\n   and will print the value it found by downloading the archive which you can\n   verify on GitHub before encoding.\n\nYou can use the provided script `update_module_to_nightly.py` to generate and\nadd an `archive_override` of the current nightly release, including integrity\nfrom GitHub.\n\nOnce the Carbon toolchain has established releases in the Bazel central\nregistry, this file will work with an updated version out of the box.\n\"\"\"\n\nmodule(name = \"example\")\n\nbazel_dep(name = \"rules_cc\", version = \"0.2.14\")\n\n# Declare the `carbon_toolchain` module. This is needed even if it will be\n# overridden with a local path or archive.\nbazel_dep(name = \"carbon_toolchain\", version = \"0.0.0\")\n\nregister_toolchains(\"@carbon_toolchain//:all\")\n"
  },
  {
    "path": "examples/bazel/example.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <stdlib.h>\n\n#include \"example_lib.h\"\n\nauto main() -> int {\n  HelloWorld();\n  return EXIT_SUCCESS;\n}\n"
  },
  {
    "path": "examples/bazel/example_lib.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"example_lib.h\"\n\n#include <iostream>\n\nauto HelloWorld() -> void { std::cout << \"Hello World!\\n\"; }\n"
  },
  {
    "path": "examples/bazel/example_lib.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_EXAMPLES_BAZEL_EXAMPLE_LIB_H_\n#define CARBON_EXAMPLES_BAZEL_EXAMPLE_LIB_H_\n\nauto HelloWorld() -> void;\n\n#endif  // CARBON_EXAMPLES_BAZEL_EXAMPLE_LIB_H_\n"
  },
  {
    "path": "examples/bazel/update_module_to_nightly.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Updates example module file to use the nightly toolchain release.\n\nThis script computes the most recent nightly Carbon toolchain release, and\nupdates the example module file with an `archive_override` pointing at it.\n\nUsage:\n  # Within the `examples/bazel` directory:\n  ./update_module_to_nightly.py\n\nFor more details about using the Carbon toolchain with Bazel, see the\ndocumentation in `examples/bazel/MODULE.bazel`.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport re\nimport os\nimport sys\nimport base64\nimport urllib.request\nimport urllib.error\nimport json\n\nMODULE_NAME = \"carbon_toolchain\"\nMODULE_FILENAME = \"MODULE.bazel\"\nDEP_PATTERN = re.compile(\n    rf'^bazel_dep\\s*\\(\\s*name\\s*=\\s*\"{MODULE_NAME}\".*?\\)',\n    re.DOTALL | re.MULTILINE,\n)\nOVERRIDE_PATTERN = re.compile(\n    rf'^archive_override\\s*\\(\\s*module_name\\s*=\\s*\"{MODULE_NAME}\".*?\\)',\n    re.DOTALL | re.MULTILINE,\n)\n\n# The nightly build starts at 2am UTC, and we give it up to 4 hours to complete.\nBUFFER_HOURS = 6\n\nRELEASES_URL = (\n    \"https://github.com/carbon-language/carbon-lang/releases/download\"\n)\nRELEASES_API_URL = (\n    \"https://api.github.com/repos/carbon-language/carbon-lang/releases\"\n)\nAPI_HEADERS = {\n    \"Accept\": \"application/vnd.github+json\",\n    \"X-GitHub-Api-Version\": \"2022-11-28\",\n    # GitHub API requires a User-Agent, urllib doesn't send one by default\n    \"User-Agent\": \"python-urllib\",\n}\n\n\ndef log(msg: str) -> None:\n    print(f\"[update_module_to_nightly] {msg}\", file=sys.stderr)\n\n\ndef get_latest_version() -> str:\n    # Use the 'releases' list endpoint, NOT 'releases/latest'. Using the\n    # `latest` endpoint only works for full releases, not pre-releases. Carbon's\n    # nightly releases are classified as pre-releases so we have to get the full\n    # list and simply take the first one. That does mean we only need the first\n    # page of results.\n    url = f\"{RELEASES_API_URL}?per_page=1\"\n    req = urllib.request.Request(url, headers=API_HEADERS)\n    try:\n        with urllib.request.urlopen(req) as response:\n            data = json.load(response)\n            if not data:\n                log(\"Error: no releases found for this repository.\")\n                sys.exit(1)\n\n            # The API returns a list sorted by creation date (newest first).\n            latest_release = data[0]\n\n    except urllib.error.HTTPError as e:\n        log(f\"Error: HTTP error {e.code} fetching latest release: {e.reason}\")\n        # It's often useful to print the body for GitHub API errors (e.g. rate\n        # limit exceeded)\n        log(e.read().decode(\"utf-8\"))\n        sys.exit(1)\n\n    # The release tag starts with `v` followed by the version.\n    latest_version = str(latest_release[\"tag_name\"])\n    if not latest_version.startswith(\"v\"):\n        log(f\"Error: malformed release tag name: {latest_version}\")\n        sys.exit(1)\n\n    return latest_version[1:]\n\n\ndef get_digest(version: str, filename: str) -> str:\n    url = f\"{RELEASES_API_URL}/tags/v{version}\"\n    req = urllib.request.Request(url, headers=API_HEADERS)\n    try:\n        with urllib.request.urlopen(req) as response:\n            release_data = json.load(response)\n    except urllib.error.HTTPError as e:\n        log(f\"Error: unable to find `v{version}`: {e.code}: {e.reason}\")\n        sys.exit(1)\n\n    assets = release_data.get(\"assets\", [])\n    for asset in assets:\n        name = str(asset.get(\"name\"))\n        if name != filename:\n            continue\n\n        digest = str(asset.get(\"digest\"))\n        if not digest.startswith(\"sha256:\"):\n            log(f\"Error: found invalid digest for `{filename}`: `{digest}`\")\n            sys.exit(1)\n\n        # Re-encode from the GitHub format to Bazel.\n        digest = (\n            \"sha256-\"\n            + base64.b64encode(bytes.fromhex(digest[len(\"sha256:\") :])).decode()\n        )\n        return digest\n\n    log(f\"Error: unable to find a digest for `{filename}`\")\n    sys.exit(1)\n\n\ndef generate_override(version: str) -> str:\n    basename = f\"carbon_toolchain-{version}\"\n    digest = get_digest(version, f\"{basename}.tar.gz\")\n    return (\n        f\"archive_override(\\n\"\n        f'    module_name = \"{MODULE_NAME}\",\\n'\n        f'    integrity = \"{digest}\",\\n'\n        f'    strip_prefix = \"{basename}/lib/carbon\",\\n'\n        f'    urls = [\"{RELEASES_URL}/v{version}/{basename}.tar.gz\"],\\n'\n        f\")\"\n    )\n\n\ndef main() -> None:\n    if not os.path.exists(MODULE_FILENAME):\n        log(f\"Error: `{MODULE_FILENAME}` not found in current directory.\")\n        sys.exit(1)\n\n    with open(MODULE_FILENAME, \"r\") as f:\n        content = f.read()\n\n    # 1. Verification (Check if dependency exists)\n    dep_match = DEP_PATTERN.search(content)\n    if not dep_match:\n        log(\n            f\"Error: `bazel_dep` for `{MODULE_NAME}` not found in \"\n            f\"`{MODULE_FILENAME}`.\"\n        )\n        sys.exit(1)\n\n    version = get_latest_version()\n    new_block = generate_override(version)\n\n    new_content, count = OVERRIDE_PATTERN.subn(new_block, content)\n    if count > 0:\n        log(\"Existing override found, replacing with a fresh one\")\n    else:\n        log(\"No existing override found, inserting one\")\n        new_content = (\n            content[: dep_match.end()]\n            + \"\\n\\n\"\n            + new_block\n            + content[dep_match.end() :]\n        )\n\n    with open(MODULE_FILENAME, \"w\") as f:\n        f.write(new_content)\n\n    log(f\"Successfully updated `{MODULE_FILENAME}` to version `{version}`\")\n\n\nif __name__ == \"__main__\":\n    try:\n        main()\n    except KeyboardInterrupt:\n        sys.exit(1)\n"
  },
  {
    "path": "examples/bazel_test_runner.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Checks various LLVM tool symlinks behave as expected.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport os\nimport sys\nimport time\nimport unittest\nfrom bazel_tools.tools.python.runfiles import runfiles\nfrom bazel_integration_test.py import test_base\n\n\nclass BazelExampleTest(test_base.TestBase):\n    def setUp(self) -> None:\n        test_base.TestBase.setUp(self)\n        self.runfiles = runfiles.Create()\n        self.install_module = self.runfiles.Rlocation(\n            \"carbon/toolchain/install/prefix/lib/carbon\"\n        )\n        self.startup_flags = [\n            \"--ignore_all_rc_files\",\n            \"--batch\",\n        ]\n        self.flags = [\n            f\"--override_module=carbon_toolchain={self.install_module}\"\n        ]\n\n    def _run_bazel(self, command: list[str]) -> str:\n        \"\"\"Runs bazel with retry logic for transient errors.\"\"\"\n        for attempt in range(5):\n            exit_code, stdout, stderr = self.RunBazel(\n                self.startup_flags + command + self.flags\n            )\n\n            # Several error codes are reliably permanent, break immediately.\n            # `1`  -- The build failed.\n            # `2`  -- Command line or environment problem.\n            # `3`  -- Tests failed or timed out, we don't retry at this layer\n            #         on execution timeout.\n            # `4`  -- Test command but no tests found.\n            # `8`  -- Explicitly interrupted build.\n            #\n            # Note that `36` is documented as \"likely permanent\", but we retry\n            # it as most of our transient failures actually produce that error\n            # code.\n            perm_error = (1, 2, 3, 4, 8)\n            if exit_code in perm_error:\n                break\n\n            for line in stderr:\n                print(line, file=sys.stderr)\n\n            if exit_code == 0:\n                return stdout\n\n            # Retry transient errors with a brief delay.\n            print(f\"Attempt {attempt + 1} failed with exit code {exit_code}\")\n            time.sleep(attempt)\n        self.AssertExitCode(exit_code, 0, stderr)\n\n    def test_compile_lib(self) -> None:\n        # TODO: Can remove this in favor of always running `test_run` if we can\n        # make linking a binary sufficiently efficient.\n        self._run_bazel([\"build\", \"//:example_lib\"])\n\n    @unittest.skipUnless(\n        \"CARBON_BAZEL_TEST_FULL\" in os.environ,\n        \"Skipping expensive test step for minimal testing\",\n    )\n    def test_run(self) -> None:\n        stdout = self._run_bazel([\"run\", \"//:example\"])\n        self.assertEqual(stdout, [\"Hello World!\"])\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "examples/hello_world.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nimport Core library \"io\";\n\nfn Run() {\n  Core.PrintStr(\"Hello world!\\n\");\n}\n"
  },
  {
    "path": "examples/interop/cpp/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/carbon_rules:defs.bzl\", \"carbon_binary\")\n\ncarbon_binary(\n    name = \"hello_world\",\n    srcs = [\"hello_world.carbon\"],\n)\n\ncarbon_binary(\n    name = \"socket\",\n    srcs = [\"socket.carbon\"],\n)\n"
  },
  {
    "path": "examples/interop/cpp/hello_world.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nimport Cpp library \"<cstdio>\";\nimport Cpp library \"<iostream>\";\nimport Cpp library \"<string_view>\";\nimport Cpp library \"<unistd.h>\";\n\n// Demonstrate passing `char`s to a C++ function.\nfn HelloPutchar() {\n  let message: array(char, 13) =\n      ('H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\\n');\n  for (c: char in message) {\n    // TODO: u8 should probably have an implicit cast to i32.\n    Cpp.putchar((c as u8) as i32);\n  }\n\n  // TODO: Use a loop over a string literal instead. Requires IndexWith support\n  // for str.\n  //\n  // let message: str = \"Hello world!\\n\";\n  // for (c: char in message) {\n  //   Cpp.putchar((c as u8) as i32);\n  // }\n}\n\n// Demonstrate passing a null-terminated string to a C++ function.\nfn HelloStdio() {\n  // TODO: There should be a better way to interact with functions that expect a\n  // null-terminated string.\n  Cpp.puts(Cpp.std.data(\"Hello world!\\0\"));\n\n  // TODO: Requires variadic function support.\n  // Cpp.printf(\"Hello world!\\n\\0\");\n}\n\n// Demonstrate passing a string as a void pointer to a C++ function.\nfn HelloWrite() {\n  let s: str = \"Hello world!\\n\";\n  Cpp.write(1, Cpp.std.data(s), Cpp.std.size(s));\n}\n\nfn HelloIostreams() {\n  Cpp.std.cout << \"Hello world!\\n\";\n}\n\nfn Run() {\n  HelloPutchar();\n  HelloStdio();\n  HelloWrite();\n  HelloIostreams();\n}\n"
  },
  {
    "path": "examples/interop/cpp/socket.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nimport Core library \"io\";\nimport Cpp library \"<arpa/inet.h>\";\nimport Cpp library \"<netinet/in.h>\";\nimport Cpp library \"<stdio.h>\";\nimport Cpp library \"<string_view>\";\nimport Cpp library \"<sys/socket.h>\";\nimport Cpp library \"<unistd.h>\";\n\nimport Cpp inline '''\n#define SOCKADDR_IN_SIZE sizeof(struct sockaddr_in6)\n\n// Work around htons being a macro, not a function, on MacOS.\n// TODO: This should not be necessary once we can import function-like macros.\ninline unsigned short htons_wrap(unsigned short n) {\n  return htons(n);\n}\n''';\n\nfn Perror(s: str) {\n  // TODO: Should we allow passing a string literal to a `const char*`\n  // parameter?\n  Cpp.perror(Cpp.std.data(s));\n}\n\n// Basic example of using POSIX networking functions via interop.\n//\n// Opens a socket listening on port 8081, waits for a single connection, then\n// reads a single chunk of up to 256 bytes from it and echoes it to the\n// terminal.\nfn Run() -> i32 {\n  // TODO: `Cpp.SOCK_STREAM as i32` should probably be allowed.\n  // TODO: Should this be an implicit conversion?\n  let server_fd: i32 = Cpp.socket(Cpp.AF_INET6, (Cpp.SOCK_STREAM as u32) as i32, 0);\n  if (server_fd == -1) {\n    Perror(\"socket failed\");\n    return 1;\n  }\n\n  // TODO: This initialization should zero-initialize the struct.\n  // TODO: We should be able to use simply `= ()` or `= {}` to get the same effect.\n  var address: Cpp.sockaddr_in6 = Cpp.sockaddr_in6.sockaddr_in6();\n  Cpp.memset(&address, 0, Cpp.SOCKADDR_IN_SIZE);\n  // TODO: Should this be valid without a cast? `AF_INET6` is defined to an\n  // integer literal in glibc at least, but we import it as an `i32`.\n  address.sin6_family = Cpp.AF_INET6 as Cpp.sa_family_t;\n  // TODO: This leads to a link error referring to `in6addr_any.1`.\n  // address.sin6_addr = Cpp.in6addr_any;\n  let port: u16 = 8081;\n  address.sin6_port = Cpp.htons_wrap(port);\n\n  let address_ptr: Cpp.sockaddr* = &address unsafe as Cpp.sockaddr*;\n  // TODO: Should have an implicit conversion from\n  // T* to Optional(const T*).\n  // TODO: Should expose `sizeof` somehow.\n  let bind_result: i32 = Cpp.bind(\n      server_fd, address_ptr as const Cpp.sockaddr*, Cpp.SOCKADDR_IN_SIZE as u32\n  );\n\n  if (bind_result == -1) {\n      Perror(\"bind failed\");\n      return 1;\n  }\n\n  if (Cpp.listen(server_fd, 1) == -1) {\n    Perror(\"listen failed\");\n    return 1;\n  }\n\n  // TODO: Add a better `Core.Print`.\n  Core.PrintStr(\"Server is listening on port \");\n  Core.Print(port as i32);\n\n  var addr_len: Cpp.socklen_t = 0;\n  let socket_fd: i32 = Cpp.accept(\n      server_fd,\n      address_ptr,\n      &addr_len\n  );\n\n  if (socket_fd == -1) {\n      Perror(\"accept failed\");\n      return 1;\n  }\n\n  Core.PrintStr(\"Connection accepted!\\n\");\n\n  var buffer: array(char, 256);\n  let len: Cpp.ssize_t = Cpp.read(socket_fd, &buffer[0], 256);\n  if (len < 0) {\n    Perror(\"read failed\");\n    return 1;\n  }\n\n  Cpp.write(1, &buffer[0], len as Cpp.size_t);\n\n  Cpp.close(socket_fd);\n  Cpp.close(server_fd);\n\n  return 0;\n}\n"
  },
  {
    "path": "examples/re2_playground/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/carbon_rules:defs.bzl\", \"carbon_binary\")\n\ncarbon_binary(\n    name = \"re2_playground\",\n    srcs = [\"re2_playground.carbon\"],\n    flags = [\"--clang-arg=-std=c++20\"],\n    tags = [\"manual\"],\n    deps = [\n        \"@llvm-project//llvm:LineEditor\",\n        \"@re2\",\n    ],\n)\n"
  },
  {
    "path": "examples/re2_playground/re2_playground.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nimport Cpp library \"llvm/LineEditor/LineEditor.h\";\nimport Cpp library \"llvm/Support/raw_ostream.h\";\nimport Cpp library \"re2/re2.h\";\n\nimport Cpp inline \"using OptionalString = std::optional<std::string>;\";\nimport Cpp inline \"std::string_view AsStringView(const std::string &s) { return s; }\";\n\nimport Core library \"io\";\n\nclass RE2 {\n  extend adapt Cpp.re2.RE2;\n  fn Make(re: str) -> Self {\n    return RE2(re) as Self;\n  }\n  fn Match[self: Self](text: str) -> bool {\n    return FullMatch(text, self as Cpp.re2.RE2);\n  }\n}\n\nimpl str as Core.ImplicitAs(Cpp.llvm.StringRef) {\n  fn Convert[self: Self]() -> Cpp.llvm.StringRef {\n    return Cpp.llvm.StringRef.StringRef(self);\n  }\n}\n\nfn Print(var s: str) {\n  *Cpp.llvm.outs() << s;\n}\n\nfn Run() -> i32 {\n  var editor: Cpp.llvm.LineEditor = Cpp.llvm.LineEditor.LineEditor(\"re2_playground\");\n  editor.setPrompt(Cpp.std.string.basic_string(\"re2> \"));\n\n  Print('''\n    Usage:\n      /regex/        -- sets the current regular expression to regex\n      anything else  -- matches the entered text against the specified regex\n    ''');\n\n  var re: RE2 = RE2.Make(\"^a*$\");\n  while (true) {\n    var line: Cpp.OptionalString = editor.readLine();\n    if (not line.has_value()) {\n      break;\n    }\n    if (line.value()->starts_with(\"/\") and line.value()->ends_with(\"/\")) {\n      re = RE2.Make(Cpp.AsStringView(line.value()->substr(1, line.value()->size() - 2)));\n      continue;\n    }\n    if (re.Match(Cpp.AsStringView(*line.value()))) {\n      Print(\"Match\\n\");\n    } else {\n      Print(\"No match\\n\");\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "examples/sieve.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nimport Core library \"io\";\nimport Core library \"range\";\n\n// Compute and return the number of primes less than 1000.\n\nclass Sieve {\n  impl as Core.UnformedInit {}\n\n  fn Make() -> Sieve {\n    returned var s: Sieve;\n    for (n: i32 in Core.Range(1000)) {\n      s.is_prime[n] = true;\n    }\n    return var;\n  }\n\n  fn MarkMultiplesNotPrime[ref self: Self](p: i32) {\n    var n: i32 = p * 2;\n    while (n < 1000) {\n      self.is_prime[n] = false;\n      n += p;\n    }\n  }\n\n  var is_prime: array(bool, 1000);\n}\n\nfn Run() -> i32 {\n  var s: Sieve = Sieve.Make();\n\n  var number_of_primes: i32 = 0;\n  for (n: i32 in Core.InclusiveRange(2, 999)) {\n    if (s.is_prime[n]) {\n      ++number_of_primes;\n      Core.Print(n);\n      s.MarkMultiplesNotPrime(n);\n    }\n  }\n\n  return number_of_primes;\n}\n"
  },
  {
    "path": "github_tools/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@py_deps//:requirements.bzl\", \"requirement\")\nload(\"@rules_python//python:defs.bzl\", \"py_binary\", \"py_library\", \"py_test\")\nload(\"@rules_python//python:pip.bzl\", \"compile_pip_requirements\")\n\npy_library(\n    name = \"github_helpers\",\n    srcs = [\"github_helpers.py\"],\n    deps = [requirement(\"gql\")],\n)\n\ncompile_pip_requirements(\n    name = \"requirements\",\n    src = \"requirements.in\",\n    requirements_txt = \"requirements.txt\",\n)\n\npy_test(\n    name = \"github_helpers_test\",\n    size = \"small\",\n    srcs = [\"github_helpers_test.py\"],\n    deps = [\":github_helpers\"],\n)\n\npy_binary(\n    name = \"pr_comments\",\n    srcs = [\"pr_comments.py\"],\n    deps = [\"github_helpers\"],\n)\n\npy_test(\n    name = \"pr_comments_test\",\n    size = \"small\",\n    srcs = [\"pr_comments_test.py\"],\n    deps = [\":pr_comments\"],\n)\n"
  },
  {
    "path": "github_tools/MODULE.bazel",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Bazel modules.\n\nThis is set up as a separate bazel repo from the main Carbon directory in order\nto split up the pip dependency, which makes MODULE.bazel.lock\nplatform-dependent. We don't commit the MODULE.bazel.lock for github_tools\nbecause it's low-value, and would shift the platform dependence costs.\n\"\"\"\n\nmodule(name = \"github_tools\")\n\nbazel_dep(name = \"rules_python\", version = \"0.27.1\")\n\npython = use_extension(\"@rules_python//python/extensions:python.bzl\", \"python\")\npython.toolchain(\n    python_version = \"3.11\",\n)\nuse_repo(python, \"python_versions\")\n\n# Create a central repo that knows about the pip dependencies.\npip = use_extension(\"@rules_python//python/extensions:pip.bzl\", \"pip\")\npip.parse(\n    hub_name = \"py_deps\",\n    python_version = \"3.11\",\n    requirements_lock = \"//:requirements.txt\",\n)\nuse_repo(pip, \"py_deps\")\n"
  },
  {
    "path": "github_tools/README.md",
    "content": "# GitHub\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nScripts for use with GitHub.\n\nSee individual scripts for more details.\n"
  },
  {
    "path": "github_tools/WORKSPACE",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nworkspace(name = \"github_tools\")\n"
  },
  {
    "path": "github_tools/__init__.py",
    "content": ""
  },
  {
    "path": "github_tools/github_helpers.py",
    "content": "\"\"\"GitHub GraphQL helpers.\n\nhttps://developer.github.com/v4/explorer/ is very useful for building queries.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport argparse\nfrom collections.abc import Generator\nimport os\nfrom typing import Optional\n\n# https://pypi.org/project/gql/\nimport gql  # type: ignore\nimport gql.transport.requests  # type: ignore\n\n_ENV_TOKEN = \"GITHUB_ACCESS_TOKEN\"\n\n# Query elements for pagination.\nPAGINATION = \"\"\"pageInfo {\n  hasNextPage\n  endCursor\n}\ntotalCount\"\"\"\n\n\ndef add_access_token_arg(\n    parser: argparse.ArgumentParser, permissions: str\n) -> None:\n    \"\"\"Adds a flag to set the access token.\"\"\"\n    access_token = os.environ.get(_ENV_TOKEN, default=None)\n    parser.add_argument(\n        \"--access-token\",\n        metavar=\"ACCESS_TOKEN\",\n        default=access_token,\n        required=not access_token,\n        help=\"The access token for use with GitHub. May also be specified in \"\n        \"the environment as %s. The access token should have permissions: %s\"\n        % (_ENV_TOKEN, permissions),\n    )\n\n\nclass Client:\n    \"\"\"A GitHub GraphQL client.\"\"\"\n\n    def __init__(self, parsed_args: argparse.Namespace):\n        \"\"\"Connects to GitHub.\"\"\"\n        transport = gql.transport.requests.RequestsHTTPTransport(\n            url=\"https://api.github.com/graphql\",\n            headers={\"Authorization\": \"bearer %s\" % parsed_args.access_token},\n        )\n        self._client = gql.Client(transport=transport)\n\n    def execute(self, query: str) -> dict:\n        \"\"\"Runs a query.\"\"\"\n        return self._client.execute(gql.gql(query))  # type: ignore\n\n    def execute_and_paginate(\n        self,\n        query: str,\n        path: tuple[str, ...],\n        first_page: Optional[dict] = None,\n    ) -> Generator[dict, None, None]:\n        \"\"\"Runs a query with pagination.\n\n        Arguments:\n          query: The GraphQL query template, which must have both 'cursor' and\n            'pagination' fields to fill in. The cursor should be part of the\n            location query (with 'first'), and the pagination should be at the\n            same level as nodes.\n          path: A list of strings indicating the path to the nodes in the\n            result.\n          first_page: An optional object for the first page of results, which\n            will otherwise automatically be collected. This exists for callers\n            to optimize by collecting other data with the first page.\n        \"\"\"\n        format = {\"cursor\": \"\", \"pagination\": PAGINATION}\n        count = 0\n        exp_count = None\n        while True:\n            if first_page:\n                result = first_page\n                first_page = None\n            else:\n                result = self.execute(query % format)\n            # Follow the path to the nodes being paginated.\n            node_parent = result\n            for entry in path:\n                node_parent = node_parent[entry]\n            # Store the total count of responses.\n            if not exp_count:\n                exp_count = node_parent[\"totalCount\"]\n            # Yield each node individually.\n            for node in node_parent[\"nodes\"]:\n                yield node\n                count += 1\n            # Check for pagination, verifying the total count on exit.\n            page_info = node_parent[\"pageInfo\"]\n            if not page_info[\"hasNextPage\"]:\n                assert exp_count == count, \"exp %d != actual %d at path %s\" % (\n                    exp_count,\n                    count,\n                    path,\n                )\n                return\n            format[\"cursor\"] = ' after: \"%s\"' % page_info[\"endCursor\"]\n"
  },
  {
    "path": "github_tools/github_helpers_test.py",
    "content": "\"\"\"Tests for github_helpers.py.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport unittest\nfrom unittest import mock\n\nimport github_helpers\n\n_TEST_QUERY = \"\"\"\nquery {\n  top(login: \"foo\") {\n    child(first: 100%(cursor)s) {\n      nodes {\n        login\n      }\n      %(pagination)s\n    }\n  }\n}\n\"\"\"\n\n_TEST_QUERY_PATH = (\"top\", \"child\")\n\n_EXP_QUERY_FIRST_PAGE = \"\"\"\nquery {\n  top(login: \"foo\") {\n    child(first: 100) {\n      nodes {\n        login\n      }\n      pageInfo {\n  hasNextPage\n  endCursor\n}\ntotalCount\n    }\n  }\n}\n\"\"\"\n\n_EXP_QUERY_SECOND_PAGE = \"\"\"\nquery {\n  top(login: \"foo\") {\n    child(first: 100 after: \"CURSOR\") {\n      nodes {\n        login\n      }\n      pageInfo {\n  hasNextPage\n  endCursor\n}\ntotalCount\n    }\n  }\n}\n\"\"\"\n\n\nclass TestGithubHelpers(unittest.TestCase):\n    def setUp(self):\n        patcher = mock.patch.object(\n            github_helpers.Client, \"__init__\", lambda self, parsed_args: None\n        )\n        self.addCleanup(patcher.stop)\n        patcher.start()\n        self.client = github_helpers.Client(None)\n\n    @staticmethod\n    def mock_result(nodes, total_count=None, has_next_page=False):\n        if total_count is None:\n            total_count = len(nodes)\n        end_cursor = None\n        if has_next_page:\n            end_cursor = \"CURSOR\"\n        return {\n            \"top\": {\n                \"child\": {\n                    \"nodes\": nodes,\n                    \"pageInfo\": {\n                        \"hasNextPage\": has_next_page,\n                        \"endCursor\": end_cursor,\n                    },\n                    \"totalCount\": total_count,\n                }\n            }\n        }\n\n    def test_execute_and_paginate_empty(self):\n        self.client.execute = mock.MagicMock(return_value=self.mock_result([]))\n        self.assertEqual(\n            list(\n                self.client.execute_and_paginate(_TEST_QUERY, _TEST_QUERY_PATH)\n            ),\n            [],\n        )\n        self.client.execute.assert_called_once_with(_EXP_QUERY_FIRST_PAGE)\n\n    def test_execute_and_paginate_one_page(self):\n        self.client.execute = mock.MagicMock(\n            return_value=self.mock_result([\"foo\", \"bar\", \"baz\"])\n        )\n        self.assertEqual(\n            list(\n                self.client.execute_and_paginate(_TEST_QUERY, _TEST_QUERY_PATH)\n            ),\n            [\"foo\", \"bar\", \"baz\"],\n        )\n        self.client.execute.assert_called_once_with(_EXP_QUERY_FIRST_PAGE)\n\n    def test_execute_and_paginate_one_page_count_mismatch(self):\n        self.client.execute = mock.MagicMock(\n            return_value=self.mock_result([\"foo\"], total_count=2),\n        )\n        self.assertRaises(\n            AssertionError,\n            list,\n            self.client.execute_and_paginate(_TEST_QUERY, _TEST_QUERY_PATH),\n        )\n        self.client.execute.assert_called_once_with(_EXP_QUERY_FIRST_PAGE)\n\n    def test_execute_and_paginate_two_page(self):\n        def paging(query):\n            if query == _EXP_QUERY_FIRST_PAGE:\n                return self.mock_result(\n                    [\"foo\", \"bar\"], total_count=3, has_next_page=True\n                )\n            elif query == _EXP_QUERY_SECOND_PAGE:\n                return self.mock_result([\"baz\"], total_count=\"unused\")\n            else:\n                raise ValueError(\"Bad query: %s\" % query)\n\n        self.client.execute = mock.MagicMock(side_effect=paging)\n        self.assertEqual(\n            list(\n                self.client.execute_and_paginate(_TEST_QUERY, _TEST_QUERY_PATH)\n            ),\n            [\"foo\", \"bar\", \"baz\"],\n        )\n        self.assertEqual(self.client.execute.call_count, 2)\n\n    def test_execute_and_paginate_first_page_done(self):\n        self.client.execute = mock.MagicMock()\n        self.assertEqual(\n            list(\n                self.client.execute_and_paginate(\n                    _TEST_QUERY,\n                    _TEST_QUERY_PATH,\n                    first_page=self.mock_result([\"foo\"]),\n                )\n            ),\n            [\"foo\"],\n        )\n        self.assertEqual(self.client.execute.call_count, 0)\n\n    def test_execute_and_paginate_first_page_continue(self):\n        self.client.execute = mock.MagicMock(\n            return_value=self.mock_result([\"bar\"], total_count=\"unused\")\n        )\n        self.assertEqual(\n            list(\n                self.client.execute_and_paginate(\n                    _TEST_QUERY,\n                    _TEST_QUERY_PATH,\n                    first_page=self.mock_result(\n                        [\"foo\"], total_count=2, has_next_page=True\n                    ),\n                )\n            ),\n            [\"foo\", \"bar\"],\n        )\n        self.client.execute.assert_called_once_with(_EXP_QUERY_SECOND_PAGE)\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "github_tools/pr_comments.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Figure out comments on a GitHub PR.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport argparse\nimport datetime\nimport hashlib\nimport os\nimport importlib.util\nimport textwrap\nfrom typing import Any, Callable, Optional\n\n# Do some extra work to support direct runs.\ntry:\n    from github_tools import github_helpers\nexcept ImportError:\n    github_helpers_spec = importlib.util.spec_from_file_location(\n        \"github_helpers\",\n        os.path.join(os.path.dirname(__file__), \"github_helpers.py\"),\n    )\n    assert github_helpers_spec is not None\n    github_helpers = importlib.util.module_from_spec(github_helpers_spec)\n    github_helpers_spec.loader.exec_module(github_helpers)  # type: ignore\n\n\n# The main query, into which other queries are composed.\n_QUERY = \"\"\"\n{\n  repository(owner: \"carbon-language\", name: \"%(repo)s\") {\n    pullRequest(number: %(pr_num)d) {\n      author {\n        login\n      }\n      createdAt\n      title\n\n      %(comments)s\n      %(reviews)s\n      %(review_threads)s\n    }\n  }\n}\n\"\"\"\n\n# Queries for comments on the PR. These are direct, non-review comments on the\n# PR.\n_QUERY_COMMENTS = \"\"\"\n      comments(first: 100%(cursor)s) {\n        nodes {\n          author {\n            login\n          }\n          body\n          createdAt\n          url\n        }\n        %(pagination)s\n      }\n\"\"\"\n\n# Queries for reviews on the PR, which have a non-empty body if a review has\n# a summary comment.\n_QUERY_REVIEWS = \"\"\"\n      reviews(first: 100%(cursor)s) {\n        nodes {\n          author {\n            login\n          }\n          body\n          createdAt\n          url\n        }\n        %(pagination)s\n      }\n\"\"\"\n\n# Queries for review threads on the PR.\n_QUERY_REVIEW_THREADS = \"\"\"\n      reviewThreads(first: 100%(cursor)s) {\n        nodes {\n          comments(first: 100) {\n            nodes {\n              author {\n                login\n              }\n              body\n              createdAt\n              originalPosition\n              originalCommit {\n                abbreviatedOid\n              }\n              path\n            }\n          }\n          isResolved\n          resolvedBy {\n            createdAt\n            login\n          }\n        }\n        %(pagination)s\n      }\n\"\"\"\n\n\nclass _Comment:\n    \"\"\"A comment, either on a review thread or top-level on the PR.\"\"\"\n\n    def __init__(self, author: str, timestamp: str, body: str):\n        self.author = author\n        self.timestamp = datetime.datetime.strptime(\n            timestamp, \"%Y-%m-%dT%H:%M:%SZ\"\n        )\n        self.body = body\n\n    @staticmethod\n    def from_raw_comment(raw_comment: dict) -> \"_Comment\":\n        \"\"\"Creates the comment from a raw comment dict.\"\"\"\n        return _Comment(\n            raw_comment[\"author\"][\"login\"],\n            raw_comment[\"createdAt\"],\n            raw_comment[\"body\"],\n        )\n\n    @staticmethod\n    def _rewrap(content: str) -> str:\n        \"\"\"Rewraps a comment to fit in 80 columns with an indent.\"\"\"\n        lines = []\n        for line in content.split(\"\\n\"):\n            lines.extend(\n                [\n                    x\n                    for x in textwrap.wrap(\n                        line,\n                        width=80,\n                        initial_indent=\" \" * 4,\n                        subsequent_indent=\" \" * 4,\n                    )\n                ]\n            )\n        return \"\\n\".join(lines)\n\n    def format(self, long: bool) -> str:\n        \"\"\"Formats the comment.\"\"\"\n        if long:\n            return \"%s%s at %s:\\n%s\" % (\n                \" \" * 2,\n                self.author,\n                self.timestamp.strftime(\"%Y-%m-%d %H:%M\"),\n                self._rewrap(self.body),\n            )\n        else:\n            # Compact newlines down into pilcrows, leaving a space after.\n            body = self.body.replace(\"\\r\", \"\").replace(\"\\n\", \"¶ \")\n            while \"¶ ¶\" in body:\n                body = body.replace(\"¶ ¶\", \"¶¶\")\n            line = \"%s%s: %s\" % (\" \" * 2, self.author, body)\n            return line if len(line) <= 80 else line[:77] + \"...\"\n\n\nclass _PRComment(_Comment):\n    \"\"\"A comment on the top-level PR.\"\"\"\n\n    def __init__(self, raw_comment: dict):\n        super().__init__(\n            raw_comment[\"author\"][\"login\"],\n            raw_comment[\"createdAt\"],\n            raw_comment[\"body\"],\n        )\n        self.url = raw_comment[\"url\"]\n\n    def __lt__(self, other: \"_PRComment\") -> bool:\n        return self.timestamp < other.timestamp\n\n    def format(self, long: bool) -> str:\n        return \"%s\\n%s\" % (self.url, super().format(long))\n\n\nclass _Thread:\n    \"\"\"A review thread on a line of code.\"\"\"\n\n    def __init__(self, parsed_args: argparse.Namespace, thread: dict):\n        self.is_resolved: bool = thread[\"isResolved\"]\n\n        comments = thread[\"comments\"][\"nodes\"]\n        first_comment = comments[0]\n        self.line: int = first_comment[\"originalPosition\"]\n        self.path: str = first_comment[\"path\"]\n\n        # Link to the comment in the commit; GitHub features work better there\n        # than in the conversation view. The diff_url allows viewing changes\n        # since the comment, although the comment won't be visible there.\n        template = (\n            \"https://github.com/carbon-language/%(repo)s/pull/%(pr_num)s/\"\n            \"files/%(oid)s%(head)s#diff-%(path_md5)s%(line_side)s%(line)s\"\n        )\n        # GitHub uses an md5 of the file's path for the link.\n        path_md5 = hashlib.md5()\n        path_md5.update(bytearray(self.path, \"utf-8\"))\n        format_dict = {\n            \"head\": \"\",\n            \"line_side\": \"R\",\n            \"line\": self.line,\n            \"oid\": first_comment[\"originalCommit\"][\"abbreviatedOid\"],\n            \"path_md5\": path_md5.hexdigest(),\n            \"pr_num\": parsed_args.pr_num,\n            \"repo\": parsed_args.repo,\n        }\n        self.url: str = template % format_dict\n        format_dict[\"head\"] = \"..HEAD\"\n        format_dict[\"line_side\"] = \"L\"\n        self.diff_url: str = template % format_dict\n\n        self.comments = [\n            _Comment.from_raw_comment(comment)\n            for comment in thread[\"comments\"][\"nodes\"]\n        ]\n        if self.is_resolved:\n            self.comments.append(\n                _Comment(\n                    thread[\"resolvedBy\"][\"login\"],\n                    thread[\"resolvedBy\"][\"createdAt\"],\n                    \"<resolved>\",\n                )\n            )\n\n    def __lt__(self, other: \"_Thread\") -> bool:\n        \"\"\"Sort threads by line then timestamp.\"\"\"\n        if self.line != other.line:\n            return bool(self.line < other.line)\n        return self.comments[0].timestamp < other.comments[0].timestamp\n\n    def format(self, long: bool) -> str:\n        \"\"\"Formats the review thread with comments.\"\"\"\n        lines = [\n            \"%s\\n  - line %d; %s\"\n            % (\n                self.url,\n                self.line,\n                (\"resolved\" if self.is_resolved else \"unresolved\"),\n            )\n        ]\n        if self.diff_url:\n            lines.append(\"  - diff: %s\" % self.diff_url)\n        for comment in self.comments:\n            lines.append(comment.format(long))\n        return \"\\n\".join(lines)\n\n    def has_comment_from(self, comments_from: str) -> bool:\n        \"\"\"Returns true if comments has a comment from comments_from.\"\"\"\n        for comment in self.comments:\n            if comment.author == comments_from:\n                return True\n        return False\n\n\ndef _parse_args(args: Optional[list[str]] = None) -> argparse.Namespace:\n    \"\"\"Parses command-line arguments and flags.\"\"\"\n    parser = argparse.ArgumentParser(description=\"Lists comments on a PR.\")\n    parser.add_argument(\n        \"pr_num\",\n        metavar=\"PR#\",\n        type=int,\n        help=\"The pull request to fetch comments from.\",\n    )\n    github_helpers.add_access_token_arg(parser, \"repo\")\n    parser.add_argument(\n        \"--comments-after\",\n        metavar=\"LOGIN\",\n        help=\"Only print threads where the final comment is not from the given \"\n        \"user. For example, use when looking for threads that you still need \"\n        \"to respond to.\",\n    )\n    parser.add_argument(\n        \"--comments-from\",\n        metavar=\"LOGIN\",\n        help=\"Only print threads with comments from the given user. For \"\n        \"example, use when looking for threads that you've commented on.\",\n    )\n    parser.add_argument(\n        \"--include-resolved\",\n        action=\"store_true\",\n        help=\"Whether to include resolved review threads. By default, only \"\n        \"unresolved threads will be shown.\",\n    )\n    parser.add_argument(\n        \"--repo\",\n        choices=[\"carbon-lang\"],\n        default=\"carbon-lang\",\n        help=\"The Carbon repo to query. Defaults to %(default)s.\",\n    )\n    parser.add_argument(\n        \"--long\",\n        action=\"store_true\",\n        help=\"Prints long output, with the full comment.\",\n    )\n    return parser.parse_args(args=args)\n\n\ndef _query(\n    parsed_args: argparse.Namespace, field_name: Optional[str] = None\n) -> str:\n    \"\"\"Returns a query for the passed field_name, or all by default.\"\"\"\n    print(\".\", end=\"\", flush=True)\n    format = {\n        \"pr_num\": parsed_args.pr_num,\n        \"repo\": parsed_args.repo,\n        \"comments\": \"\",\n        \"review_threads\": \"\",\n        \"reviews\": \"\",\n    }\n    if field_name:\n        # Use a cursor for pagination of the field.\n        if field_name == \"comments\":\n            format[\"comments\"] = _QUERY_COMMENTS\n        elif field_name == \"reviewThreads\":\n            format[\"review_threads\"] = _QUERY_REVIEW_THREADS\n        elif field_name == \"reviews\":\n            format[\"reviews\"] = _QUERY_REVIEWS\n        else:\n            raise ValueError(\"Unexpected field_name: %s\" % field_name)\n    else:\n        # Fetch the first page of all fields.\n        subformat = {\"cursor\": \"\", \"pagination\": github_helpers.PAGINATION}\n        format[\"comments\"] = _QUERY_COMMENTS % subformat\n        format[\"review_threads\"] = _QUERY_REVIEW_THREADS % subformat\n        format[\"reviews\"] = _QUERY_REVIEWS % subformat\n    return _QUERY % format\n\n\ndef _accumulate_pr_comment(\n    parsed_args: argparse.Namespace,\n    comments: list[_PRComment],\n    raw_comment: dict,\n) -> None:\n    \"\"\"Collects top-level comments and reviews.\"\"\"\n    # Elide reviews that have no top-level comment body.\n    if raw_comment[\"body\"]:\n        comments.append(_PRComment(raw_comment))\n\n\ndef _accumulate_thread(\n    parsed_args: argparse.Namespace,\n    threads_by_path: dict[str, list[_Thread]],\n    raw_thread: dict,\n) -> None:\n    \"\"\"Adds threads to threads_by_path for later sorting.\"\"\"\n    thread = _Thread(parsed_args, raw_thread)\n\n    # Optionally skip resolved threads.\n    if not parsed_args.include_resolved and thread.is_resolved:\n        return\n\n    # Optionally skip threads where the given user isn't the last commenter.\n    if (\n        parsed_args.comments_after\n        and thread.comments[-1].author == parsed_args.comments_after\n    ):\n        return\n\n    # Optionally skip threads where the given user hasn't commented.\n    if parsed_args.comments_from and not thread.has_comment_from(\n        parsed_args.comments_from\n    ):\n        return\n\n    if thread.path not in threads_by_path:\n        threads_by_path[thread.path] = []\n    threads_by_path[thread.path].append(thread)\n\n\ndef _paginate(\n    field_name: str,\n    accumulator: Callable[[argparse.Namespace, Any, dict], None],\n    parsed_args: argparse.Namespace,\n    client: github_helpers.Client,\n    main_result: dict,\n    output: Any,\n) -> None:\n    \"\"\"Paginates through the given field_name, accumulating results.\"\"\"\n    query = _query(parsed_args, field_name=field_name)\n    path = (\"repository\", \"pullRequest\", field_name)\n    for node in client.execute_and_paginate(\n        query, path, first_page=main_result\n    ):\n        accumulator(parsed_args, output, node)\n\n\ndef _fetch_comments(\n    parsed_args: argparse.Namespace,\n) -> tuple[list[_PRComment], dict[str, list[_Thread]]]:\n    \"\"\"Fetches comments and review threads from GitHub.\"\"\"\n    # Each _query call will print a '.' for progress.\n    print(\n        \"Loading https://github.com/carbon-language/%s/pull/%d ...\"\n        % (parsed_args.repo, parsed_args.pr_num),\n        end=\"\",\n        flush=True,\n    )\n\n    client = github_helpers.Client(parsed_args)\n\n    # Get the initial set of review threads, and print the PR summary.\n    main_result = client.execute(_query(parsed_args))\n    pull_request = main_result[\"repository\"][\"pullRequest\"]\n\n    # Paginate comments, reviews, and review threads.\n    comments: list[_PRComment] = []\n    _paginate(\n        \"comments\",\n        _accumulate_pr_comment,\n        parsed_args,\n        client,\n        main_result,\n        comments,\n    )\n    # Combine reviews into comments for interleaving.\n    _paginate(\n        \"reviews\",\n        _accumulate_pr_comment,\n        parsed_args,\n        client,\n        main_result,\n        comments,\n    )\n    threads_by_path: dict[str, list[_Thread]] = {}\n    _paginate(\n        \"reviewThreads\",\n        _accumulate_thread,\n        parsed_args,\n        client,\n        main_result,\n        threads_by_path,\n    )\n\n    # Now that loading is done (no more progress indicators), print the header.\n    print()\n    pr_desc = _Comment(\n        pull_request[\"author\"][\"login\"],\n        pull_request[\"createdAt\"],\n        pull_request[\"title\"],\n    )\n    print(pr_desc.format(parsed_args.long))\n    return comments, threads_by_path\n\n\ndef main() -> None:\n    parsed_args = _parse_args()\n    comments, threads_by_path = _fetch_comments(parsed_args)\n\n    for comment in sorted(comments):\n        print()\n        print(comment.format(parsed_args.long))\n\n    for path, threads in sorted(threads_by_path.items()):\n        # Print a header for each path.\n        print()\n        print(\"=\" * 80)\n        print(path)\n        print(\"=\" * 80)\n\n        for thread in sorted(threads):\n            print()\n            print(thread.format(parsed_args.long))\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "github_tools/pr_comments_test.py",
    "content": "\"\"\"Tests for pr_comments.py.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport os\nimport unittest\nfrom unittest import mock\n\nimport github_helpers\nimport pr_comments\n\n\nclass TestPRComments(unittest.TestCase):\n    def setUp(self):\n        # Stub out the access token.\n        os.environ[github_helpers._ENV_TOKEN] = \"unused\"\n\n    def test_format_comment_short(self):\n        created_at = \"2001-02-03T04:05:06Z\"\n        self.assertEqual(\n            pr_comments._Comment(\"author\", created_at, \"brief\").format(False),\n            \"  author: brief\",\n        )\n        self.assertEqual(\n            pr_comments._Comment(\"author\", created_at, \"brief\\nwrap\").format(\n                False\n            ),\n            \"  author: brief¶ wrap\",\n        )\n        self.assertEqual(\n            pr_comments._Comment(\n                \"author\", created_at, \"brief\\n\\n\\nwrap\"\n            ).format(False),\n            \"  author: brief¶¶¶ wrap\",\n        )\n        self.assertEqual(\n            pr_comments._Comment(\n                \"author\",\n                created_at,\n                \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed \"\n                \"do eiusmo\",\n            ).format(False),\n            \"  author: Lorem ipsum dolor sit amet, consectetur adipiscing \"\n            \"elit, sed do eiusmo\",\n        )\n        self.assertEqual(\n            pr_comments._Comment(\n                \"author\",\n                created_at,\n                \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed \"\n                \"do eiusmod\",\n            ).format(False),\n            \"  author: Lorem ipsum dolor sit amet, consectetur adipiscing \"\n            \"elit, sed do eiu...\",\n        )\n\n    def test_format_comment_long(self):\n        created_at = \"2001-02-03T04:05:06Z\"\n        self.assertEqual(\n            pr_comments._Comment(\"author\", created_at, \"brief\").format(True),\n            \"  author at 2001-02-03 04:05:\\n    brief\",\n        )\n        self.assertEqual(\n            pr_comments._Comment(\"author\", created_at, \"brief\\nwrap\").format(\n                True\n            ),\n            \"  author at 2001-02-03 04:05:\\n    brief\\n    wrap\",\n        )\n\n        body = (\n            \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed \"\n            \"do eiusmod tempor incididunt ut labore et dolore magna \"\n            \"aliqua.\\n\"\n            \"Ut enim ad minim veniam,\"\n        )\n        self.assertEqual(\n            pr_comments._Comment(\"author\", created_at, body).format(True),\n            \"  author at 2001-02-03 04:05:\\n\"\n            \"    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed \"\n            \"do eiusmod\\n\"\n            \"    tempor incididunt ut labore et dolore magna aliqua.\\n\"\n            \"    Ut enim ad minim veniam,\",\n        )\n\n    @staticmethod\n    def fake_thread(**kwargs):\n        with mock.patch.dict(os.environ, {}):\n            parsed_args = pr_comments._parse_args([\"83\"])\n        return pr_comments._Thread(\n            parsed_args, TestPRComments.fake_thread_dict(**kwargs)\n        )\n\n    @staticmethod\n    def fake_thread_dict(\n        is_resolved=False,\n        path=\"foo.md\",\n        line=3,\n        created_at=\"2001-02-03T04:05:06Z\",\n    ):\n        thread_dict = {\n            \"isResolved\": is_resolved,\n            \"comments\": {\n                \"nodes\": [\n                    {\n                        \"author\": {\"login\": \"author\"},\n                        \"body\": \"comment\",\n                        \"createdAt\": created_at,\n                        \"originalCommit\": {\"abbreviatedOid\": \"abcdef\"},\n                        \"originalPosition\": line,\n                        \"path\": path,\n                        \"url\": \"http://xyz\",\n                    },\n                    {\n                        \"author\": {\"login\": \"other\"},\n                        \"body\": \"reply\",\n                        \"createdAt\": \"2001-02-03T04:15:16Z\",\n                    },\n                ],\n            },\n        }\n        if is_resolved:\n            thread_dict[\"resolvedBy\"] = {\n                \"login\": \"resolver\",\n                \"createdAt\": \"2001-02-03T04:25:26Z\",\n            }\n        return thread_dict\n\n    def test_thread_format(self):\n        self.assertEqual(\n            self.fake_thread().format(False),\n            \"https://github.com/carbon-language/carbon-lang/pull/83/\"\n            \"files/abcdef#diff-d8ca3b3d314d8209367af0eea2373b6fR3\\n\"\n            \"  - line 3; unresolved\\n\"\n            \"  - diff: https://github.com/carbon-language/carbon-lang/pull/83/\"\n            \"files/abcdef..HEAD#diff-d8ca3b3d314d8209367af0eea2373b6fL3\\n\"\n            \"  author: comment\\n\"\n            \"  other: reply\",\n        )\n        self.assertEqual(\n            self.fake_thread().format(True),\n            \"https://github.com/carbon-language/carbon-lang/pull/83/files/\"\n            \"abcdef#diff-d8ca3b3d314d8209367af0eea2373b6fR3\\n\"\n            \"  - line 3; unresolved\\n\"\n            \"  - diff: https://github.com/carbon-language/carbon-lang/pull/83/\"\n            \"files/abcdef..HEAD#diff-d8ca3b3d314d8209367af0eea2373b6fL3\\n\"\n            \"  author at 2001-02-03 04:05:\\n\"\n            \"    comment\\n\"\n            \"  other at 2001-02-03 04:15:\\n\"\n            \"    reply\",\n        )\n\n        self.assertEqual(\n            self.fake_thread(is_resolved=True).format(False),\n            \"https://github.com/carbon-language/carbon-lang/pull/83/\"\n            \"files/abcdef#diff-d8ca3b3d314d8209367af0eea2373b6fR3\\n\"\n            \"  - line 3; resolved\\n\"\n            \"  - diff: https://github.com/carbon-language/carbon-lang/pull/83/\"\n            \"files/abcdef..HEAD#diff-d8ca3b3d314d8209367af0eea2373b6fL3\\n\"\n            \"  author: comment\\n\"\n            \"  other: reply\\n\"\n            \"  resolver: <resolved>\",\n        )\n        self.assertEqual(\n            self.fake_thread(is_resolved=True).format(True),\n            \"https://github.com/carbon-language/carbon-lang/pull/83/\"\n            \"files/abcdef#diff-d8ca3b3d314d8209367af0eea2373b6fR3\\n\"\n            \"  - line 3; resolved\\n\"\n            \"  - diff: https://github.com/carbon-language/carbon-lang/pull/83/\"\n            \"files/abcdef..HEAD#diff-d8ca3b3d314d8209367af0eea2373b6fL3\\n\"\n            \"  author at 2001-02-03 04:05:\\n\"\n            \"    comment\\n\"\n            \"  other at 2001-02-03 04:15:\\n\"\n            \"    reply\\n\"\n            \"  resolver at 2001-02-03 04:25:\\n\"\n            \"    <resolved>\",\n        )\n\n    def test_thread_lt(self):\n        thread1 = self.fake_thread(line=2)\n        thread2 = self.fake_thread()\n        thread3 = self.fake_thread(created_at=\"2002-02-03T04:05:06Z\")\n\n        self.assertTrue(thread1 < thread2)\n        self.assertFalse(thread2 < thread1)\n\n        self.assertFalse(thread2 < thread2)\n\n        self.assertTrue(thread2 < thread3)\n        self.assertFalse(thread3 < thread2)\n\n    def test_accumulate_thread(self):\n        with mock.patch.dict(os.environ, {}):\n            parsed_args = pr_comments._parse_args([\"83\"])\n        threads_by_path = {}\n        review_threads = [\n            self.fake_thread_dict(line=2),\n            self.fake_thread_dict(line=4),\n            self.fake_thread_dict(path=\"other.md\"),\n            self.fake_thread_dict(),\n        ]\n        for thread in review_threads:\n            pr_comments._accumulate_thread(\n                parsed_args,\n                threads_by_path,\n                thread,\n            )\n        self.assertEqual(sorted(threads_by_path.keys()), [\"foo.md\", \"other.md\"])\n        threads = sorted(threads_by_path[\"foo.md\"])\n        self.assertEqual(len(threads), 3)\n        self.assertEqual(threads[0].line, 2)\n        self.assertEqual(threads[1].line, 3)\n        self.assertEqual(threads[2].line, 4)\n        self.assertEqual(len(threads_by_path[\"other.md\"]), 1)\n\n    @staticmethod\n    def fake_pr_comment(**kwargs):\n        return pr_comments._PRComment(\n            TestPRComments.fake_pr_comment_dict(**kwargs)\n        )\n\n    @staticmethod\n    def fake_pr_comment_dict(\n        body=\"comment\",\n        created_at=\"2001-02-03T04:05:06Z\",\n    ):\n        pr_comment_dict = {\n            \"author\": {\"login\": \"author\"},\n            \"body\": body,\n            \"createdAt\": created_at,\n            \"url\": \"http://xyz\",\n        }\n        return pr_comment_dict\n\n    def test_pr_comment_format(self):\n        self.assertEqual(\n            self.fake_pr_comment().format(False),\n            \"http://xyz\\n  author: comment\",\n        )\n        self.assertEqual(\n            self.fake_pr_comment().format(True),\n            \"http://xyz\\n  author at 2001-02-03 04:05:\\n    comment\",\n        )\n\n    def test_pr_comment_lt(self):\n        pr_comment1 = self.fake_pr_comment()\n        pr_comment2 = self.fake_pr_comment(created_at=\"2002-02-03T04:05:06Z\")\n\n        self.assertTrue(pr_comment1 < pr_comment2)\n        self.assertFalse(pr_comment2 < pr_comment1)\n\n        self.assertFalse(pr_comment2 < pr_comment2)\n\n    def test_accumulate_pr_comment(self):\n        with mock.patch.dict(os.environ, {}):\n            parsed_args = pr_comments._parse_args([\"83\"])\n        raw_comments = [\n            self.fake_pr_comment_dict(body=\"x\"),\n            self.fake_pr_comment_dict(body=\"\"),\n            self.fake_pr_comment_dict(\n                body=\"y\", created_at=\"2000-02-03T04:05:06Z\"\n            ),\n            self.fake_pr_comment_dict(\n                body=\"z\", created_at=\"2002-02-03T04:05:06Z\"\n            ),\n        ]\n        comments = []\n        for raw_comment in raw_comments:\n            pr_comments._accumulate_pr_comment(\n                parsed_args, comments, raw_comment\n            )\n        comments.sort()\n        self.assertEqual(len(comments), 3)\n        self.assertEqual(comments[0].body, \"y\")\n        self.assertEqual(comments[1].body, \"x\")\n        self.assertEqual(comments[2].body, \"z\")\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "github_tools/requirements.in",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n# Python dependencies, consumed by /WORKSPACE.\ngql >= 2.0.0, < 3.0.0\n"
  },
  {
    "path": "github_tools/requirements.txt",
    "content": "#\n# This file is autogenerated by pip-compile with Python 3.11\n# by the following command:\n#\n#    bazel run //:requirements.update\n#\ncertifi==2024.7.4 \\\n    --hash=sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b \\\n    --hash=sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90\n    # via requests\ncharset-normalizer==3.3.2 \\\n    --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \\\n    --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \\\n    --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \\\n    --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \\\n    --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \\\n    --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \\\n    --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \\\n    --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \\\n    --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \\\n    --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \\\n    --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \\\n    --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \\\n    --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \\\n    --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \\\n    --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \\\n    --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \\\n    --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \\\n    --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \\\n    --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \\\n    --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \\\n    --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \\\n    --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \\\n    --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \\\n    --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \\\n    --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \\\n    --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \\\n    --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \\\n    --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \\\n    --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \\\n    --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \\\n    --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \\\n    --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \\\n    --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \\\n    --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \\\n    --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \\\n    --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \\\n    --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \\\n    --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \\\n    --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \\\n    --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \\\n    --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \\\n    --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \\\n    --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \\\n    --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \\\n    --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \\\n    --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \\\n    --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \\\n    --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \\\n    --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \\\n    --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \\\n    --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \\\n    --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \\\n    --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \\\n    --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \\\n    --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \\\n    --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \\\n    --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \\\n    --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \\\n    --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \\\n    --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \\\n    --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \\\n    --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \\\n    --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \\\n    --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \\\n    --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \\\n    --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \\\n    --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \\\n    --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \\\n    --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \\\n    --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \\\n    --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \\\n    --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \\\n    --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \\\n    --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \\\n    --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \\\n    --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \\\n    --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \\\n    --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \\\n    --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \\\n    --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \\\n    --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \\\n    --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \\\n    --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \\\n    --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \\\n    --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \\\n    --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \\\n    --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \\\n    --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \\\n    --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \\\n    --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561\n    # via requests\ngql==2.0.0 \\\n    --hash=sha256:35032ddd4bfe6b8f3169f806b022168932385d751eacc5c5f7122e0b3f4d6b88 \\\n    --hash=sha256:fe8d3a08047f77362ddfcfddba7cae377da2dd66f5e61c59820419c9283d4fb5\n    # via -r requirements.in\ngraphql-core==2.3.2 \\\n    --hash=sha256:44c9bac4514e5e30c5a595fac8e3c76c1975cae14db215e8174c7fe995825bad \\\n    --hash=sha256:aac46a9ac524c9855910c14c48fc5d60474def7f99fd10245e76608eba7af746\n    # via gql\nidna==3.7 \\\n    --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \\\n    --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0\n    # via requests\npromise==2.3 \\\n    --hash=sha256:dfd18337c523ba4b6a58801c164c1904a9d4d1b1747c7d5dbf45b693a49d93d0\n    # via\n    #   gql\n    #   graphql-core\nrequests==2.32.4 \\\n    --hash=sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c \\\n    --hash=sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422\n    # via gql\nrx==1.6.3 \\\n    --hash=sha256:ca71b65d0fc0603a3b5cfaa9e33f5ba81e4aae10a58491133595088d7734b2da\n    # via graphql-core\nsix==1.16.0 \\\n    --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \\\n    --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254\n    # via\n    #   gql\n    #   graphql-core\n    #   promise\nurllib3==2.6.3 \\\n    --hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \\\n    --hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4\n    # via requests\n"
  },
  {
    "path": "proposals/README.md",
    "content": "# Proposals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Proposal lists\n\n-   [All proposals](https://github.com/carbon-language/carbon-lang/pulls?q=is%3Apr+label%3Aproposal)\n-   [Accepted proposals](https://github.com/carbon-language/carbon-lang/pulls?q=is%3Apr+label%3A%22proposal%22+is%3Amerged)\n\n## Directory structure\n\nThis directory contains accepted proposals for the carbon-lang repository. For\ninformation about declined/deferred proposals, please view the proposal's\noriginal pull request.\n\nFor accepted proposals, where `####` is the corresponding proposal's pull\nrequest:\n\n-   `p####.md` will contain the main proposal text.\n-   `p####` may be present as an optional subdirectory for related files (for\n    example, images).\n"
  },
  {
    "path": "proposals/__init__.py",
    "content": ""
  },
  {
    "path": "proposals/p0024.md",
    "content": "# Generics goals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/24)\n\n## Problem\n\nThe \"generics\" feature of Carbon is a large design effort that needs to be\nbroken up into manageable steps. The first thing we need is a high-level goals\ndocument:\n\n-   to make sure we agree on the approach we are taking,\n-   to clearly communicate expectations to contributors for future steps,\n-   to encourage us to solve problems in the design in a consistent way,\n-   to provide a yardstick for measuring different alternatives under\n    consideration.\n\n## Background\n\nThe question of what a generics feature would look like in Carbon has been an\nongoing discussion, with many alternative proposals. Of course there have been a\nnumber of use cases that we want to address with this feature, but over the\ncourse of this process we have discovered a number of desirable properties we\nwould like to achieve with any solution.\n\n## Proposal\n\nSee the [generics goals document](/docs/design/generics/goals.md).\n\n## Rationale\n\nThe goals here well reflect Carbon's goals as applied to the specifics of the\ngenerics feature.\n"
  },
  {
    "path": "proposals/p0029.md",
    "content": "# Linear, rebase, and pull-request GitHub workflow\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/29)\n\n## Problem\n\nThere are a variety of workflows that can be effectively used with both Git\nversion control and GitHub. We should have a common and consistent workflow\nacross as much of Carbon as possible. While some specific areas may end up\nneeding specialized flows to suit their needs, these should be the exceptions\nand can be handled on a case-by-case basis when they arise.\n\n## Background\n\n-   Chapter 16 \"Version Control and Branch Management\" in the SWE book\n    (_[Software Engineering at Google](https://www.amazon.com/Software-Engineering-Google-Lessons-Programming/dp/1492082791)_)\n-   [Trunk Based Development](https://trunkbaseddevelopment.com/)\n-   GitHub documentation on\n    \"[pull requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)\"\n    -   [Configuration of their merges](https://help.github.com/en/github/administering-a-repository/configuring-pull-request-merges)\n    -   [Protected branches](https://help.github.com/en/github/administering-a-repository/about-protected-branches)\n\n## Proposal\n\nCarbon repositories should all follow a common\n[workflow](/docs/project/pull_request_workflow.md) for managing and landing\nchanges. The document outlines the specifics of the proposed workflow as well as\nthe core motivation.\n\n### Rename the default git branch to `trunk`\n\nThis achieves two goals:\n\n1. Replaces the term `master`. This term, while only used in isolation in Git,\n   [was used](https://mail.gnome.org/archives/desktop-devel-list/2019-May/msg00066.html)\n   in immediately preceding and related systems as part of extremely problematic\n   \"master/slave\" terminology. That background associates the term with\n   unacceptable historical and cultural meanings. The intent of those using or\n   adopting the term isn't relevant to this association. The less overtly\n   problematic term being isolated from the rest doesn't erase its history, and\n   doesn't completely avoid painful associations.\n\n2. It directly anchors and reinforces contributors on the trunk-based workflow.\n\n### Longer discussion of linear history\n\nWhile Git can effectively bisect through complex history graphs, this is\nsignificantly harder than bisecting across linear history. Especially for any\npart of Carbon involving code, we expect bisection to be a pervasive tool and we\ncan make it simpler and more effective by forcing a linear history.\n\nA linear history also makes it much easier to ask questions about whether a\nparticular change has landed yet, or when a bug was introduced. For some people,\nreleases are more simply understood as branching from a specific snapshot of the\nlinear history. While tools like `git log` can provide similar functionality, it\nis less trivially understood.\n\nContinuous integration is simplified for many of the same reasons as bisection:\nthe set of potential deltas is reduced to a linear sequence. Reverting to green\nbecomes easier to understand, and testing each incremental commit has a single\nobvious interpretation.\n\nRequiring linear history also incentivises incremental development that is\ncommitted early to the main branch. This, in essence, ensures a single source of\ntruth model even with the distributed version control system. Because\nworks-in-progress are required to be rebased, they tend to merge early and often\nrather than forming long-lived development branches. This helps reduce the total\nmerge resolution and testing costs as a project scales. For more details about\nthe advantages of using a single source of truth, see the full text of the\n\"Version Control and Branch Management\" chapter in the SWE book.\n\nOne concern with linear history when rebasing a sequence of changes and merging\nthem is that the pull request associated with that sequence might not be obvious\nfrom the main branch commit log. However, there is enough information in the\nrepository to establish the relationship, and GitHub's UI surfaces the pull\nrequest on each commit in the series.\n\n## Alternatives considered\n\n### LLVM model\n\nLLVM allows directly pushing/submitting to their \"trunk\" with post-commit\nreview. LLVM enforces linear history for day-to-day development. Merge commits\nare allowed for rare events like contributing a new subproject.\n\nAdvantages:\n\n-   Still has linear history.\n-   Incentivizes squashing for continuous integration and bisection.\n-   Very low overhead for fixing trivial mistakes.\n\nDisadvantages:\n\n-   Creates extremely bad incentives around code review.\n    -   Lots of patches don't get pre-commit review, even if they would benefit\n        from it.\n    -   Very experienced contributors are much better at avoiding pre-commit\n        review, so are rarely blocked waiting on review.\n    -   Leads to the most experienced members of the community not doing enough\n        code reviews, or being timely enough in code reviews.\n    -   Lots of patches submitted with post-commit review are never reviewed in\n        practice unless they break something.\n-   UI and basic support for code reviews entirely focused on pull requests.\n\n### Fork and merge model\n\nClassically, Git and GitHub support merging entire complex graphs of\ndevelopment.\n\nAdvantages:\n\n-   Mostly supported by pull requests, so still able to use much of that\n    functionality.\n-   Supports a model in which contributors do not communicate and can each\n    develop a local, decentralized fork while still achieving overall\n    reconciliation.\n-   Can model much more complex history of code evolution faithfully in the\n    tooling.\n    -   Most of the time these aren't so complex that they create problems for\n        humans.\n\nDisadvantages:\n\n-   History is harder for humans to understand and reason about in complex\n    cases.\n-   Bisection and continuous integration are more complex.\n    -   May create difficulty for continuous integration against mainline,\n        because unclear what \"order\" they should be applied / explored. While\n        there are technical approaches to address this, they don't seem to\n        eliminate the complexity, merely provide a clear set of mechanics for\n        handling it.\n-   Reduces incentives to land small, incremental changes by allowing\n    non-linearity to reduce the effort required for large and/or complex merges.\n-   Makes review of the main branch's history harder due to non-linearity.\n\n### Fork and merge, but branches can only have linear history\n\nImagine a fork and merge model, but PRs can only have linear history. That is,\nbranching and merging within a PR, or merging `trunk` into PR is not allowed. In\nthis model, the only merge commits are merges of PRs into `trunk`. PRs\nthemselves don’t contain merge commits.\n\nAdvantages:\n\n-   Mostly supported by GitHub pull requests, so still able to use much of that\n    functionality.\n-   Restricts non-linearity of history. The only non-linearity that is left is\n    merge commits on the trunk branch. PRs themselves can’t contain merge\n    commits.\n\nDisadvantages:\n\n-   Requires a custom presubmit on GitHub that checks linearity of a PR.\n-   The disadvantages of the fork and merge strategy regarding the complexity of\n    history remain, but to a smaller degree, since non-linearity is restricted.\n\n## Rationale\n\n-   Easy to follow single source of truth will help foster an open and inclusive\n    community.\n-   Review requirements and focus on small, incremental changes match well\n    established engineering practices for ensuring the project and codebase\n    scale up both in size and time dimensions.\n-   Linear history seems easier for humans to reason about.\n"
  },
  {
    "path": "proposals/p0042.md",
    "content": "# Create code review guidelines\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/42)\n\n## Problem\n\nCarbon should ensure that all checked-in changes to the repository are properly\ncode reviewed, and that the process for code review is effective across a number\nof dimensions:\n\n-   Ensure high quality of code, documentation, and other artifacts. We consider\n    these all \"code reviews\" regardless of whether the final artefact is \"code\"\n    in a technical sense.\n-   Encourage broad participation and contribution to the community through code\n    reviews.\n-   Ensure code reviews are inclusive, respectful, and welcoming.\n-   Have clear, discoverable, and mechanically enforced (where possible) rules\n    for who _can_, who _should_, and who _must_ review any particular change.\n\n## Background\n\nGeneral code review:\n\n-   Chapter 9 \"Code Review\" in\n    _[Software Engineering at Google](https://www.amazon.com/Software-Engineering-Google-Lessons-Programming/dp/1492082791)_\n-   Chapter 21 \"Collaborative Construction\" in\n    _[Code Complete: A Practical Handbook of Software Construction](https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670/)_\n-   [Respectful Code Reviews (Chromium)](https://chromium.googlesource.com/chromium/src/+/master/docs/cr_respect.md)\n-   [Compassionate--Yet Candid--Code Reviews (video)](https://youtu.be/Ea8EiIPZvh0)\n-   [The Standard of Code Review](https://google.github.io/eng-practices/review/reviewer/standard.html)\n-   [How We Do Code Review](https://devblogs.microsoft.com/appcenter/how-the-visual-studio-mobile-center-team-does-code-review/)\n-   [Code Reviewing in the Trenches: Understanding Challenges, Best Practices and Tool Needs](https://www.microsoft.com/en-us/research/wp-content/uploads/2016/05/MS-Code-Review-Tech-Report-MSR-TR-2016-27.pdf)\n-   [The Importance of Code Reviews](https://www.sitepoint.com/the-importance-of-code-reviews/)\n-   [10 Reasons Why Code Reviews Make Better Code and Better Teams](https://simpleprogrammer.com/why-code-reviews-make-better-code-teams/)\n-   [Wikipedia article on code review](https://en.wikipedia.org/wiki/Code_review)\n-   [Expectations, Outcomes, and Challenges of Modern Code Review](https://sback.it/publications/icse2013.pdf)\n\nSpecific GitHub tooling:\n\n-   [About code owners](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners)\n-   [Reviewing changes in pull requests](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/reviewing-changes-in-pull-requests)\n\n## Proposal\n\nAdd a [code review guide](/docs/project/code_review.md) to the project, and\nreference it from our contributing guide and pull request workflow\ndocumentation.\n\nAlso create initial `CODEOWNERS` files in both this repository and the toolchain\nrepository based on current review activity and team roles. These are really\nonly suggested as an initial guess and should likely be iterated frequently as\nmore people join and begin contributing. The `carbon-lang` repository file is\nincluded directly, and carbon-language/carbon-toolchain#1 updates the\n`carbon-toolchain` repository.\n\n## Alternatives considered\n\n### Post-commit review\n\nSome projects, such as LLVM, use _post-commit_ review for some changes. This has\nboth advantages and disadvantages.\n\nAdvantages:\n\n-   Enables sustaining velocity in the face of high latency in code review.\n    -   Little need to rebase or resolve merge conflicts due to immediately\n        landing patches even while under review.\n    -   Cross-developer dependencies don't create challenges.\n-   Optimizes commit velocity amongst a small group of developers with extensive\n    experience working together and minimal review comments on others' code.\n\nDisadvantages:\n\n-   Does not meaningfully scale beyond small group of developers with\n    preexisting shared understanding of desired form of code.\n    -   Relies on relative infrequency of needing code review comments.\n    -   Developers largely need to be well aligned and reliably writing code\n        others would already approve.\n-   Disincentivizes code review relative to writing code.\n    -   This effect is strong enough to create a significant fraction of commits\n        that simply see no review in the LLVM community.\n-   Creates significant barriers for new contributors.\n    -   In practice, existing contributors are much more likely to be able to\n        accurately create post-commit review passing changes than new\n        contributors.\n    -   Because of this, new contributors will have a very difficult time\n        joining the community.\n    -   This has specifically been cited by people joining the LLVM community.\n\n### Skipping review when no functionality is changed (NFC commits)\n\nAnother practice popular in the LLVM community is to skip pre-commit review for\nchanges for which \"no functionality changes\" or NFC commits. Common examples are\nreformatting or basic code cleanup. The idea is that these are exceedingly lower\nrisk compared changes to functionality.\n\nAdvantages:\n\n-   Can avoid waiting for a review on trivial cleanups and refactorings.\n    -   May be especially useful as they tend to be merge conflict prone and\n        likely to be lead-ups to changes sent out for review.\n    -   The advantage is lessened when using stacked reviews to parallelize\n        them.\n-   Avoid spending reviewer time on more trivial changes.\n    -   Unclear how much time this is as NFC changes are typically relatively\n        fast to review due to their nature. Deciding \"did it change behavior?\"\n        is easier than deciding \"given that it changes behavior, is the change\n        good?\".\n\nDisadvantages:\n\n-   No concrete and objective rubric for whether or not a change is NFC, and\n    whether it perhaps is significant enough to still warrant review.\n    -   Debating this adds a new cost to the entire process.\n    -   In some cases, deciding whether a change is NFC roughly requires a code\n        review, making it pointless to skip the code review.\n    -   A specific utility of code review is to discover when something\n        _unexpected_ happens. The fact that the author _believes_ a change is\n        NFC doesn't address this utility as the unexpected thing may be the\n        functionality changed.\n-   Loses the knowledge sharing benefit of code review for cleanups and\n    refactorings.\n    -   Especially unfortunate as these are exactly the kinds of changes often\n        recommend for people starting to get familiar with a project.\n-   Fails to ensure consistency or ease of understanding of the code.\n    -   Despite not changing functionality, a change may decrease how easily\n        understood the code is or may move it to be inconsistent with the wider\n        codebase.\n    -   Avoiding these two things are some of the primary goals of code review.\n\n## Rationale\n\nThis proposal contains the right goals for the code review process in light of\nour project goals, and the proposal is well-tailored to achieve them.\nSpecifically:\n\n-   Ensure high quality of code, documentation, and other artifacts. We consider\n    these all \"code reviews\" regardless of whether the final artifact is \"code\"\n    in a technical sense.\n-   Encourage broad participation and contribution to the community through code\n    reviews.\n-   Ensure code reviews are inclusive, respectful, and welcoming.\n-   Have clear, discoverable, and mechanically enforced (where possible) rules\n    for who can, who should, and who must review any particular change.\n\nWe want pre-commit rather than post-commit review, and we want all changes to go\nthrough review. These guidelines are consistent with standard code review best\npractice, including what’s described in the cited sources.\n"
  },
  {
    "path": "proposals/p0044.md",
    "content": "# Proposal tracking\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/44)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Overview](#overview)\n    -   [Open question: Do we use a Google Docs-centric or GitHub Markdown-centric flow?](#open-question-do-we-use-a-google-docs-centric-or-github-markdown-centric-flow)\n        -   [Option: Google Docs-centric flow](#option-google-docs-centric-flow)\n            -   [Overview](#overview-1)\n            -   [Flow summary](#flow-summary)\n            -   [Advantages/Disadvantages](#advantagesdisadvantages)\n        -   [Option: GitHub Markdown-centric flow](#option-github-markdown-centric-flow)\n            -   [Overview](#overview-2)\n            -   [Flow summary](#flow-summary-1)\n            -   [Advantages/Disadvantages](#advantagesdisadvantages-1)\n-   [Details](#details)\n    -   [Carbon language shared drive](#carbon-language-shared-drive)\n        -   [Main shared drive](#main-shared-drive)\n        -   [Proposals (shared folder)](#proposals-shared-folder)\n        -   [Proposal Archive (folder in shared drive)](#proposal-archive-folder-in-shared-drive)\n    -   [Google Docs proposal ACLs](#google-docs-proposal-acls)\n-   [Markdown-specific questions](#markdown-specific-questions)\n    -   [Open question: Where should proposals be stored in GitHub?](#open-question-where-should-proposals-be-stored-in-github)\n        -   [Option: Proposal archive GitHub repository (carbon-proposals)](#option-proposal-archive-github-repository-carbon-proposals)\n        -   [Option: Store proposals in the repository they affect](#option-store-proposals-in-the-repository-they-affect)\n    -   [Open question: Should we push comments to focus on GitHub?](#open-question-should-we-push-comments-to-focus-on-github)\n        -   [Common principles](#common-principles)\n        -   [Option: Push high-level comments to Discourse Forums](#option-push-high-level-comments-to-discourse-forums)\n        -   [Option: Push high-level comments to GitHub](#option-push-high-level-comments-to-github)\n        -   [Option: Give no guidance, see what happens](#option-give-no-guidance-see-what-happens)\n    -   [Open question: Should there be a tracking issue?](#open-question-should-there-be-a-tracking-issue)\n        -   [Common principles](#common-principles-1)\n        -   [Option: Tracking issue for all proposals](#option-tracking-issue-for-all-proposals)\n        -   [Option: Don't require tracking issues](#option-dont-require-tracking-issues)\n    -   [Open question: Should declined/deferred proposals be committed?](#open-question-should-declineddeferred-proposals-be-committed)\n        -   [Common principles](#common-principles-2)\n        -   [Option: Do not commit declined/deferred proposals](#option-do-not-commit-declineddeferred-proposals)\n        -   [Option: Commit declined/deferred proposals](#option-commit-declineddeferred-proposals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use a shared drive for everything](#use-a-shared-drive-for-everything)\n-   [Appendix](#appendix)\n    -   [General concern about multiple Markdown flavors](#general-concern-about-multiple-markdown-flavors)\n    -   [Google Docs vs GitHub comment flow comparison](#google-docs-vs-github-comment-flow-comparison)\n        -   [Comment clustering](#comment-clustering)\n        -   [Basic comments](#basic-comments)\n        -   [Suggesting edits](#suggesting-edits)\n    -   [Google Docs add-ons](#google-docs-add-ons)\n        -   [Docs to Markdown](#docs-to-markdown)\n        -   [Code blocks](#code-blocks)\n        -   [Advanced Find & Replace](#advanced-find--replace)\n    -   [Markdown editing](#markdown-editing)\n        -   [StackEdit](#stackedit)\n    -   [GitHub Markdown syntax highlighting](#github-markdown-syntax-highlighting)\n-   [Rationale](#rationale)\n    -   [Rationale for using a GitHub markdown-centric flow](#rationale-for-using-a-github-markdown-centric-flow)\n    -   [Rationale for not requiring tracking issues](#rationale-for-not-requiring-tracking-issues)\n    -   [Rationale for not committing proposals that are declined or deferred](#rationale-for-not-committing-proposals-that-are-declined-or-deferred)\n    -   [Rationale for committing a proposal to the repository it affects](#rationale-for-committing-a-proposal-to-the-repository-it-affects)\n    -   [Rationale for pushing high-level comments to GitHub](#rationale-for-pushing-high-level-comments-to-github)\n    -   [Open questions](#open-questions)\n        -   [Do we use a Google Docs-centric or GitHub Markdown-centric flow?](#do-we-use-a-google-docs-centric-or-github-markdown-centric-flow)\n        -   [Where should proposals be stored in GitHub?](#where-should-proposals-be-stored-in-github)\n        -   [Should we push comments to focus on GitHub?](#should-we-push-comments-to-focus-on-github)\n        -   [Should there be a tracking issue?](#should-there-be-a-tracking-issue)\n        -   [Should declined/deferred proposals be committed?](#should-declineddeferred-proposals-be-committed)\n\n<!-- tocstop -->\n\n## Problem\n\nHow should we:\n\n-   Draft proposals?\n-   Store under review proposals?\n-   Archive proposals?\n\nEach of these is a distinct, important step. We may be able to use the same\nstorage for multiple steps.\n\n## Background\n\nOne thing that is _not_ under question is that we will have accepted proposals\nin Markdown. This is critical, as we are essentially only delaying when a\nproposal goes to Markdown.\n\nThe evolution process expects that community contributors will author proposals\nfor review by the core team. Things to consider are:\n\n-   How easy is it for an author to write a proposal?\n    -   What if there are multiple contributors to a proposal?\n-   How easy is it to comment on a proposal?\n    -   What about small typo fixes?\n-   How do we prevent unwanted edits during the comment process?\n-   How much work does it take to convert a proposal into a final doc edit?\n-   How do we prevent edits after a decision is complete?\n\nIn any situation, it's necessary that proposals be clearly contributed to Carbon\n(even if in a draft phase, even if never accepted), and have an appropriate\nlicense attached.\n\nAlthough the evolution document currently makes statements about how to manage\nproposals, changes in approval from this doc may affect the evolution process.\nExplicit wording changes aren't outlined here because they are assumed to be\npart of executing this proposal rather than the substance of this proposal.\n\nFor reference, a version of this proposal is also available in GitHub (broken\nlink:\n`https://github.com/carbon-language/carbon-proposals/blob/d1946fab824742b4857fa74ffc1b9fe9af37375d/proposals/p0001.md`).\n\n## Proposal\n\n### Overview\n\nThis proposal presents two possible flows: one Google Docs-centric, one\nMarkdown-centric. This is an open question.\n\nIn either case, it's assumed that we will want a Carbon language shared drive\nfor any Google Docs we may create, and a Proposal archive GitHub repository.\n\n### Open question: Do we use a Google Docs-centric or GitHub Markdown-centric flow?\n\n**Decision:** GitHub Markdown-centric flow\n\nAll documents will end up in Markdown. Some members of the core team have a\nstated preference for reviewing proposals in Google Docs, and some have a\npreference for Markdown. No other clear options exist. This would yield two\npossible flows:\n\n#### Option: Google Docs-centric flow\n\n##### Overview\n\n-   Draft proposals: Google Docs\n-   Under review proposals: Google Docs\n-   Archive proposals: Google Docs + PDF\n-   Final format: Markdown\n\n##### Flow summary\n\nFor reviewing a proposal:\n\n-   Authors create a Google Doc in the Proposals shared folder.\n    -   Authors may want to trim down edit access, leaving only comment access.\n-   When ready for review, the authors share the Google Doc on Discourse Forums.\n    -   Community comments on the Google Doc.\n-   To move for a decision, ownership is transferred to a review manager.\n    -   The review manager trims down all access to comment access.\n-   When a decision is reached, the review manager updates the doc and moves it\n    to the Proposal Archive folder in the Carbon language shared drive.\n-   A PDF is saved to the carbon-proposals GitHub repository.\n-   The author converts any long-term documentation portions of the doc to\n    Markdown.\n\nIf the proposal needs to be checked later to figure out why a decision was made:\n\n-   Pragmatically, the PDF should have the same viewable content as the Google\n    Doc, and so can be used.\n-   The Google Doc's comments will be a mess to read, and so should likely be\n    treated as inaccessible later.\n-   The edit history of a Google Doc is only visible to users with edit access.\n    Since most people will have comment-only or view-only access to reviewed\n    docs, we should treat edit history as not accessible.\n\n##### Advantages/Disadvantages\n\nAdvantages:\n\n-   Supports collaborative editing.\n-   Commenting in Docs is a slightly better UI, even though the commenting\n    workflows are equivalent.\n-   Images can easily be embedded in the Google Doc, without needing separate\n    files.\n\nNeutral:\n\n-   Has an easier [suggested edit workflow](#suggesting-edits) than GitHub.\n    -   For commenters, this may be a pro because they can see their suggested\n        edit as they make it.\n    -   For the author, this is a mixed bag:\n        -   When a suggestion is for multiple, fragmented edits, it's harder to\n            read.\n            -   for example, \"foo ~~bar ~~baaz bang~~wiz ~~bing\" -> \"foo baaz\n                bangbing\"\n        -   It's easier to accept changes.\n        -   It's harder to comment on changes, as the change is still visible\n            and hiding the original state of the doc.\n            -   This is especially true when trying to respond to comments by\n                others on a suggested edit, as you can't _both_ have a\n                discussion _and_ apply/reject the edit.\n        -   It's harder to make alternative edits and/or reject changes, as it\n            effectively resolves the comment thread and hinders further\n            discussion.\n    -   For other readers, this is likely a con: it's harder to read the\n        original state of the doc that's been suggested on, and it's not clear\n        how the author will respond.\n\nDisadvantages:\n\n-   Documents will go through at least three different file formats (Docs, PDF,\n    Markdown).\n    -   Docs->Markdown conversion has limited tooling support.\n    -   Comment history will be lost on conversions.\n    -   Using different formats for proposals and documentation/specification\n        creates additional work when pulling text into a proposal to suggest\n        modifications, and when applying those modifications.\n    -   Any differences between the text in different formats will be difficult\n        to notice, particularly if the author makes a change when converting\n        long-term documentation from Docs to Markdown.\n-   Difficult to manage access control on files.\n    -   Docs does not provide access to version history (desirable) without\n        granting full edit access (undesirable).\n    -   Shared drives combine permissions for adding files to a folder and\n        editing files. Permissions can also only be _added_, not _removed_, from\n        individual docs. As a result, contributors who can create new proposals\n        will also receive the ability to edit all proposals.\n    -   Docs will not automatically mirror permissions if we use two different\n        sharing systems (shared drive and shared folder).\n-   Difficult to archive documents as read-only.\n    -   If we set archived documents to be view-only, users won't be able to\n        read comments. At that point, the PDF version that we plan to commit to\n        the Proposal archive GitHub repository is sufficient, and we could\n        delete the proposal.\n    -   If we set archived documents to allow commenting, then users can comment\n        on and add suggested edits to archived documents. Only review managers\n        could close suggested edits. This could confuse the history of the doc,\n        and stop archives from looking read-only.\n    -   In any case, archived documents would not be editable, and so revision\n        history could not be seen.\n-   Managing comments over time is infeasible.\n    -   It's infeasible to point people to old comment threads, to suggest they\n        read and engage if they disagree with the original request.\n    -   Even identifying _whether_ a comment led to a particular change is\n        infeasible.\n    -   Comments vanish if the text they're on is removed.\n    -   There is no way to quickly check for unresponded comments: instead,\n        authors will need to repeatedly crawl the doc. This is exacerbated by\n        process advice that the commenter be left to decide whether to resolve\n        comments, or slow-to-respond commenters.\n-   No support for seeing deltas.\n    -   Only editors can see the delta. However, it should be expected that only\n        the author is an editor.\n    -   Even if deltas were accessible, Docs delta support requires extra work\n        on the part of a doc editor to set up markers in the version history.\n-   Restricted support for extensibility.\n    -   Proposals frequently have duplicated/boilerplate text that the authors\n        may need to rewrite in bulk, for example when renaming something. Google\n        Docs has built-in regex search. However, regex replace with capture\n        groups isn't directly supported, so users would need to learn and use\n        Google Apps Script to do the replacement.\n    -   When URLs need to be replaced, Google Docs has _no_ support. Authors\n        must audit every URL.\n-   No low-friction support for formatted code blocks and inline code snippets.\n    -   [Extensions exist](#google-docs-add-ons); we'll probably want to\n        recommend a specific extension to the community.\n-   Intra-document links break frequently, just from moving headers.\n    -   It's also difficult to determine when an intra-document link is broken.\n        There doesn't seem to be support (built-in or add-on) for identifying\n        issues.\n    -   It's also not supported to search through links, so even if the author\n        knows what they're breaking, they won't be able to find it.\n-   Google Docs comment syntax is essentially text-only.\n    -   Syntax can interfere with \"\\*\" insertion in code snippets due to bolding\n        confusion.\n-   May enhance Google-centric views of Carbon.\n    -   Swift and Rust use Markdown-centric flows.\n-   Some companies may block Google Docs, because it's a file transfer service.\n    -   It's unclear how prevalent this would be. GitHub may also be blocked\n        under similar security rules, but it's a requirement for participation\n        whereas Google Docs is avoidable.\n    -   Ref:\n        [[1]](https://community.cisco.com/t5/web-security/blocking-google-docs/td-p/3376518),\n        [[2]](https://www.reddit.com/r/sysadmin/comments/2kwyhk/block_google_docs/),\n        [[3]](https://mybroadband.co.za/forum/threads/google-drive-blocked-at-work-work-around.809132/)\n-   Some individuals may refuse to use Google Docs over privacy (or other)\n    concerns.\n    -   We've considered creating a GSuite domain for Carbon contributor\n        accounts to help address this. However, it may not address everyone's\n        concerns.\n\n#### Option: GitHub Markdown-centric flow\n\n##### Overview\n\n-   Draft proposals: Markdown, possibly in Google Docs (but not required)\n-   Under review proposals: Markdown with review comments by way of GitHub\n-   Archive proposals: Markdown\n-   Final format: Markdown\n\n##### Flow summary\n\nFor reviewing a proposal:\n\n-   Authors prepare a markdown doc using their favored tooling.\n    -   This could be [a WYSIWYG markdown editor](#markdown-editing), or Google\n        docs for collaboration.\n-   Authors create a pull request with the markdown doc, to the carbon-proposals\n    GitHub repository.\n    -   Community comments on the pull request.\n-   To move for a decision, no special action is taken.\n-   When a decision is reached, the review manager ensures the markdown doc is\n    updated appropriately and approves the pull request.\n\nIf the proposal needs to be checked later to figure out why a decision was made:\n\n-   The committed markdown represents the final state of the proposal.\n-   The pull request may be viewed to read through comments, even after it is\n    merged.\n-   The pull request will have edit history publicly visible.\n    -   GitHub has a nice renderer for markdown diffs.\n\n##### Advantages/Disadvantages\n\nAdvantages:\n\n-   No need to convert file formats.\n    -   Markdown reviews can be committed directly, putting all history in one\n        place.\n    -   When dealing with a proposal that results in separate long-term\n        documentation, any differences between proposal text and long-term text\n        will be relatively easy to see in a diff.\n-   Access control is straightforward, determined by location.\n-   Referring to older comments is feasible.\n    -   There may be some cases where comments disappear in certain situations,\n        but these problems should be avoidable.\n-   The archival copy of a document will include an easy link to comment\n    history.\n-   Easy to see Markdown-formatted deltas in GitHub.\n-   The style of all documents can be updated centrally by changing a style\n    sheet.\n-   Multiple comments may be sent together in a review.\n    -   Comments may also be sent individually as in Docs.\n-   GitHub comment syntax supports Markdown, allowing code in comments.\n-   Multi-author editing is possible by using a shared GitHub branch as a\n    source.\n    -   This may still be less convenient than Google Docs flows, but\n        multi-author proposals could still use Google Docs to collaborate on the\n        Markdown.\n\nNeutral:\n\n-   Has a more difficult [suggested edit workflow](#suggesting-edits) than\n    Google Docs.\n    -   For commenters, this may be a con, as it takes a little more work to add\n        a suggested edit. This may still lead to fewer suggested edits.\n    -   For the author, this is a mixed bag:\n        -   Whereas Google Docs may often see multiple, fragmented edits for the\n            same sentence, commenters would be more likely to suggest them\n            together (a pro).\n        -   It's seamless to comment on changes, as it follows the normal\n            comment flow.\n        -   It's seamless to make alternative edits and/or reject changes.\n        -   The author may need to do extra reformatting/word wrapping after\n            accepting a Markdown change, which Docs would handle internally.\n    -   For other readers, this is likely a pro: the current state of the doc\n        remains visible.\n\nDisadvantages:\n\n-   GitHub comments on pull requests can be difficult to find in certain\n    situations.\n    -   Comments can disappear when a pull request is rebased and force-pushed.\n    -   Comments generally don't get tracked across revisions to a pull request.\n    -   If we disallow force-pushes on pull requests, they are probably okay\n        most of the time.\n-   Can't comment on the rendered Markdown, only the raw Markdown.\n-   Images need to be stored separately from the main Markdown file.\n    -   Final documentation may or may not need the images; they may only be\n        added to explain the proposal. that is, this may be extra work without\n        later benefit.\n\n## Details\n\n### Carbon language shared drive\n\n#### Main shared drive\n\nA shared drive will be used as a nexus for any Google Docs materials. This\nmainly offers a central point for contributors to locate materials, as most will\nnot be able to modify contents.\n\nA shared drive should be assumed to be present, regardless of whether we choose\na Google Docs-centric flow: if we allow/encourage the use of Google Docs for\ncollaborative editing in a Markdown-centric flow, we should still provide\nstorage.\n\nAccess controls:\n\n-   Managers: a minimal set (chandlerc + review managers?) to prevent accidental\n    edits.\n    -   _Not_ the entire core team, in order to discourage the core team from\n        using privileges not accessible to the rest of the community (including\n        sub-teams).\n-   Content managers: the review manager group, so that they can archive\n    proposals.\n-   Contributors: none - does not provide sufficiently distinct access from\n    content managers.\n-   Commenters: full community\n-   Viewers: none\n\n#### Proposals (shared folder)\n\nCommunity members need to be able to add proposals to the shared folder. This\nwill be available as a shortcut from the main shared drive.\n\nIn shared folders, edit access to the folder allows adding/moving/removing\nfiles, but doesn't grant control over the actual _file_, which is still owned by\nthe individual creator. Unlike shared drives, proposal authors can remove edit\naccess from individual files.\n\nAccess controls:\n\n-   Owner: chandlerc\n-   Editors: full community\n-   Commenters/viewers: none (non-public)\n\n#### Proposal Archive (folder in shared drive)\n\nThe archive will be used to store reviewed proposals. This will mainly make\ncomments on proposals available for future reference.\n\nTo allow viewing comments, comment access _must_ be granted: Google Docs\ncomments are not visible to users with view-only access. At the same time, this\nmeans contributors will still be able to comment on archived docs: this should\nbe discouraged.\n\nAccess controls:\n\n-   Inherited from Carbon language shared drive.\n\n### Google Docs proposal ACLs\n\nIn this setup, pending proposals go into the Proposals shared folder, where\nthey'll still have their own ACLs.\n\nNote that, in the Markdown-centric flow, this is generally not relevant: using\nGoogle Docs is optional and may often be skipped.\n\nAccess controls:\n\n-   Owner: proposal author (transferred to review manager, for proposals going\n    to decision)\n-   Editors: any collaborators\n-   Commenters: community\n-   Viewers: none\n\n## Markdown-specific questions\n\n### Open question: Where should proposals be stored in GitHub?\n\n**Decision**: Store proposals in the repository they affect\n\n#### Option: Proposal archive GitHub repository (carbon-proposals)\n\nIn this approach, the review managers are presumed to be responsible for commits\nto the proposal archive.\n\nAccess controls:\n\n-   Commit privileges: review managers\n\nAdvantages:\n\n-   Easy to find pending proposals; just look at the carbon-proposals issue\n    tracker.\n-   All proposals will be uniquely numbered.\n-   No need for a proposal label: everything's a proposal.\n\nDisadvantages:\n\n-   Proposals affect other repositories; may miss opportunities to combine\n    changes.\n-   Harder to filter for proposals that are relevant to a specific repository.\n\n#### Option: Store proposals in the repository they affect\n\nIn this approach, we would store proposals in the same repository as they\naffect. for example, a proposal about the spec would be stored in carbon-lang,\nwhile a proposal specific to the compiler would be in carbon-toolchains. If a\nproposal affected multiple repositories, we'd probably choose a single primary\nrepository for the proposal.\n\nSpecific to a GitHub Markdown-centric flow, we could additionally allow the\nproposal's pull request to include the specific proposed changes to\ndocumentation where appropriate, allowing for the author to avoid duplicating\ntext in the proposal itself.\n\nWe would likely still want a proposal document with a summary at a minimum, even\nfor small proposals. The summary can link to the pull request for details,\ncreating additional breadcrumbs for reading the full (with additional document\nedits) proposal.\n\nRejected proposals should commit _only_ the proposal document. A link to the\npull request in the proposal document should make it easier to research\nrejections. Alternatively, rejected proposals could have their pull request\nabandoned, but that would leave only the tracking issue as a breadcrumb for\nhistory.\n\nAccess controls:\n\n-   Commit privileges: normal repository access, possibly with review managers\n    getting broad access in order to finalize proposals.\n\nAdvantages:\n\n-   Makes it easier to demonstrate the actual changes a proposal suggests\n    making.\n-   Reduces possible redundant work by the author of making changes in two\n    places (the proposal, and affected documents).\n-   Keeps discussion about the _proposal_ and discussion about the _proposed\n    changes_ on a single review thread, for most cases.\n-   Makes it easy to find most/all proposals relevant to a given repository.\n\nDisadvantages:\n\n-   Proposals would need to be tracked separately per-repository.\n    -   This could also end up being a pro if we get a bunch of different\n        repositories, as it may become easier to find relevant proposals for a\n        given repository. It's only really a con for as long as we have few\n        repositories (which may last long-term, as having many repositories may\n        lead to other scaling problems).\n-   Access controls are part of the parent repository, and so will be less\n    restricted than if we had a separate proposals repository.\n-   Proposals won't be uniquely numbered.\n    -   We'll need to refer to proposals with the repository, for example,\n        `carbon-lang/456`.\n-   Need to make sure we have a proposal label, to separate from non-proposal\n    traffic.\n\n### Open question: Should we push comments to focus on GitHub?\n\n**Decision**: Push high-level comments to GitHub\n\n#### Common principles\n\n-   Proposals will be declared on Discourse Forums at important stages; for\n    example, asking for input on ideas, RFC, decisions, etc.\n-   Some discussion is expected to occur on the GitHub PR.\n\n#### Option: Push high-level comments to Discourse Forums\n\nWe could push for high-level comments to be added on the same thread as the\nDiscourse Forums RFC.\n\nAdvantages:\n\n-   Discourse Forums offer better interfaces for pure, non-code-comment\n    discussion.\n-   Email notifications are easier to parse with less threading, more use of\n    quotes, and \"In Reply To\" automation.\n-   More familiar for people familiar with mixed Discourse/GitHub workflows.\n    -   Both Rust and Swift use Discourse, and are closer to this option.\n    -   May also be better for people used to using email lists to discuss\n        proposed changes.\n\nDisadvantages:\n\n-   Leads contributors to two different places for comments - some high-level\n    discussion will inevitably be in GitHub.\n-   Contributors must read both Discourse Forums and GitHub to get context.\n\n#### Option: Push high-level comments to GitHub\n\nWe could push for high-level comments to be added to the proposal PR, with other\ndiscussion.\n\nAdvantages:\n\n-   The GitHub PR becomes a single hub for conversation.\n-   More familiar for people familiar with GitHub-only workflows.\n\nDisadvantages:\n\n-   Discourse Forum topics cannot have \"create\" without \"reply\" permissions, so\n    some high-level discussion will inevitably be in Discourse Forums.\n    -   We could address this by only allowing moderators to post RFCs, but that\n        may be overly exclusive.\n-   Email notifications include only the lines of code affected, not what is\n    being replied to. This will generally make it infeasible to get context from\n    emails.\n-   Comment threads sometimes make it unclear what's being replied to. for\n    example, (broken link:\n    `https://github.com/carbon-language/carbon-proposals/pull/5#discussion_r423401993`)\n    and (broken link:\n    `https://github.com/carbon-language/carbon-proposals/pull/5/files/a51ff951561accfb4aee403d7add6e8e69009ce1#r423401993`)\n    are equivalent, but the replied-to-comment is only visible in the file view.\n    -   This may be particularly visible as an issue if high-level discussions\n        are often not line-specific.\n-   Not clear what to do about resolving high-level discussion comment threads.\n    -   If comment threads are resolved, it's harder to read them, discouraging\n        third-party comment.\n    -   If comment threads are not resolved, they may create a bunch of noise.\n        As noted above, GitHub manages the file view better than the discussion\n        view.\n    -   Mixed solutions will leave it to the author to choose the balance of\n        issues.\n\n#### Option: Give no guidance, see what happens\n\nRather than trying to guide high-level discussion to a particular medium, we\ncould offer no guidance.\n\nAdvantages:\n\n-   Less policies, more freedom.\n    -   Discover what happens, switch back and forth over time based on\n        individual contributor preferences.\n\nDisadvantages:\n\n-   Advantages of a primary hub are discarded. Disadvantages of multiple hubs\n    should be assumed to remain.\n\n### Open question: Should there be a tracking issue?\n\n**Decision**: Don't require tracking issues\n\n#### Common principles\n\n-   Discourse Forum topics are minimally used to announce when a decision is\n    going to RFC, going to decision, and the decision once made.\n-   The proposal's PR may be used for discussion of the proposal.\n\n#### Option: Tracking issue for all proposals\n\nIn a workflow where there's always a tracking issue:\n\n1.  Create the tracking issue, for example #123.\n2.  Create the PR, for example #456, naming the proposal p0123.md after the\n    tracking issue.\n    1. Use GitHub features to link #123 and #456.\n3.  Update the status in p0123.md and labels of #123 when progressing a\n    proposal.\n4.  When a decision is made, create a new PR, for example #789, containing the\n    decision p0123-decision.md.\n    1. This does not replace the Discourse Forum topic announcing a decision.\n    2. Use GitHub features to link #123 and #789.\n    3. Comments on the decision may go on the decision PR, similar to the\n       proposal PR discussion.\n5.  Declined/deferred proposals may be committed or not; it doesn't matter.\n\nAdvantages:\n\n-   Easy to find the full decision in p0123-decision.md.\n-   The PR to create the decision is clearly visible in the associated tracking\n    issue.\n\nDisadvantages:\n\n-   The tracking issue separates more state.\n\n#### Option: Don't require tracking issues\n\nIn a workflow where there's no need for a tracking issue (although contributors\nmay create them for bucketing work, they are non-essential):\n\n1.  Create the PR, for example #456, naming the proposal p0456.md.\n2.  Update the labels of #456 when progressing a proposal.\n    1. Don't bother putting the status in p0456.md: people should rely on the PR\n       labels since it's in the same place.\n3.  When a decision is made, add it as a comment to #456.\n    1. This does not replace the Discourse Forum topic announcing a decision.\n    2. Comments on the decision should go in Discourse Forums.\n    3. The author is asked to link to the decision in p0456.md before the commit\n       is approved.\n4.  If declined/deferred proposals are committed, it would be best to add a\n    status in p0456.md before committing.\n\nAdvantages:\n\n-   Lighter weight process: no tracking issue, and no need to update status in\n    p0456.md.\n\nDisadvantages:\n\n-   Harder to store the decision in a way that clearly links it to the original\n    proposal.\n    -   In particular, finding discussion about the decision is hard to resolve.\n        Neither below ideas clearly improve on this, so preference to keep\n        everything in Discourse Forum topic.\n    -   Could in theory have the full decision in p0456.md. Pro is it's easy to\n        find, con is it makes it look more like the author's writing the\n        decision.\n    -   Could keep storing p0456-decision.md. Pro is it's easy to find, con is\n        the lack of association with #456 and extra file+PR. Not clear that\n        storage offers enough independent value to justify.\n-   Restricts where discussion about a decision should occur.\n\n### Open question: Should declined/deferred proposals be committed?\n\n**Decision**: Do not commit declined/deferred proposals\n\n#### Common principles\n\n-   Accepted proposals are always committed.\n-   We may (or may not) commit decisions for any committed proposal (accepted or\n    otherwise).\n    -   See notes in the above open question.\n\n#### Option: Do not commit declined/deferred proposals\n\nUnder this approach, declined/deferred proposals are never committed. Instead,\nthe PR is abandoned and we at most save a link to it.\n\nNote that GitHub does (at least to some extent) retain closed PRs, even those\ncoming from a fork.\n\nAdvantages:\n\n-   The proposals directory remains a list of only accepted proposals.\n-   No need to spend effort saving declined/deferred proposals.\n\n\\\nDisadvantages:\n\n-   Lose an easy way to check declined/deferred proposals for history.\n    -   More reliance on searching forums for history.\n\n#### Option: Commit declined/deferred proposals\n\nUnder this approach, declined/deferred proposals are committed.\n\nAdvantages:\n\n-   Easy to skim through declined/deferred proposals.\n\nDisadvantages:\n\n-   Finding accepted proposals may become more difficult.\n    -   Could put declined/deferred proposals in a different directory.\n-   Requires a little more effort in order to save declined/deferred proposals.\n\n## Alternatives considered\n\n### Use a shared drive for everything\n\nInstead of adding a shared folder for proposals, we could instead use a shared\ndrive for everything. However, this puts us in a bad situation for taking in new\nproposals. We would need to choose between:\n\n-   Allowing **all** community member edit access to **all** proposals.\n-   Requiring authors ask a review manager to create a blank proposal for them\n    to edit.\n\nNeither of these feel like great situations - they are either overly-broad or\noverly-restrictive sharing, neither approximating what we actually would want,\nwhich is for anybody in the community to easily create proposals.\n\n## Appendix\n\n### General concern about multiple Markdown flavors\n\nDifferent markdown implementations have subtly different rendering rules for the\nsame input. for example, per\n[CommonMark Spec](https://spec.commonmark.org/0.29/#), table syntax is not\nspecified, although\n[GitHub uses a table extension](https://guides.github.com/features/mastering-markdown/).\nHowever, we do plan on using GitHub consistently; this only stands to confuse\nusers of other Markdown systems.\n\nChoosing the Google Docs-centric flow does not eliminate this issue, since\nproposals will be archived in Markdown either way.\n\n### Google Docs vs GitHub comment flow comparison\n\n#### Comment clustering\n\nGoogle Docs only allows sending comments individually.\n\nGitHub supports either sending comments individually or clustering multiple\ncomments together, as in a review.\n\n#### Basic comments\n\n[Google Docs](https://support.google.com/docs/answer/65129?co=GENIE.Platform%3DDesktop&hl=en):\n\n1. Follow the link to the doc\n2. Select text to comment on\n3. Click on \"+\" to add a comment (or use keyboard shortcut)\n4. Enter text\n5. Click \"Comment\"\n\n[GitHub](https://help.github.com/en/enterprise/2.14/user/articles/commenting-on-a-pull-request):\n\n1. Follow the link to a pull request\n2. Click on \"+\" next to line to comment on\n3. Enter text\n4. Click \"Add single comment\"\n\n#### Suggesting edits\n\n[Google Docs](https://support.google.com/docs/answer/6033474?co=GENIE.Platform%3DDesktop&hl=en):\n\n1. Follow the link to the doc\n2. Select text to suggest edit on\n3. Type suggested edit\n\n[GitHub](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/commenting-on-a-pull-request):\n\n1. Follow the link to a pull request\n2. Click on \"+\" next to line to comment on\n3. Optionally select multiple lines\n4. Click on the left-most button\n5. Edit quoted text\n6. Click \"Add single comment\"\n\n### Google Docs add-ons\n\n#### Docs to Markdown\n\nhttps://gsuite.google.com/marketplace/app/docs_to_markdown/700168918607\n\nThis plugin actually looks pretty good, and may actually work better than\nGoogle's internal-only equivalent. I'm not seeing obvious downsides.\n\nAdvantages:\n\n-   Provides easy conversion of Google Docs to Markdown.\n\nDisadvantages:\n\n-   ?\n\n#### Code blocks\n\nhttps://gsuite.google.com/marketplace/app/code_blocks/100740430168\n\nThis is another code formatting tool, but doesn't seem to work as well as\nGoogle's internal-only equivalent. Google's internal-only equivalent happens to\ndo some syntax highlighting, whereas Code blocks does none.\n\nAdvantages:\n\n-   Public code formatting.\n-   Works with \"Docs to Markdown\" plugin to get ```-block escaping.\n\nDisadvantages:\n\n-   Mediocre syntax highlighting for Carbon.\n-   No inline `foo` highlighting, unlike Google's internal-only equivalent.\n-   Different highlighting from that in the eventual Markdown document.\n\n#### Advanced Find & Replace\n\nhttps://gsuite.google.com/marketplace/app/advanced_find_replace/11210842879\n\nAdvanced Find & Replace offers more advanced functionality than the built-in\nfeatures, particularly around URL and regexp support.\n\nAdvantages:\n\n-   Offers improved functionality around key Google Docs friction problems.\n\nDisadvantages:\n\n-   2 of 5 stars: we should not expect quality.\n-   \\$6 purchase price may turn off contributors.\n-   Requires permissions that are banned by Google internally.\n\n### Markdown editing\n\nThere are multiple markdown editing tools.\n\n#### StackEdit\n\nhttps://stackedit.io/\n\nStackEdit may look good on the surface, but we may effectively be restricted to\nusing it as a WYSIWYG markdown editor, not for collaboration. For that, it's\nsimply one option amongst many, and not necessarily the best.\n\nAdvantages:\n\n-   Provides preview when editing Markdown files.\n-   Provides application-specific comment support.\n\nDisadvantages:\n\n-   Cannot use shared Google workspaces with Google corp accounts, due to\n    security restrictions. Will likely cause issues for others, too.\n-   Google Docs only works as passive storage.\n    -   StackEdit docs aren't Google Docs, comments aren't Google Docs comments.\n\n### GitHub Markdown syntax highlighting\n\nGitHub's syntax highlighter\n[allows adding third-party extensions](https://github.com/github/linguist/blob/master/CONTRIBUTING.md#adding-an-extension-to-a-language),\nbut requires them to have significant use.\n\nNote we can't take advantage of this until Carbon is public. We may be able to\nfind a language with sufficiently similar syntax to\n[override the language](https://github.com/github/linguist/#overrides) and get\nreasonable highlighting.\n\n## Rationale\n\nDuring the decision process, several of the individual rationales were\ninfluenced by the idea that one could view the proposal process in one of two\nways:\n\n1.  A PR-centric model. The review team is trying to achieve consensus around a\n    PR as a whole. The PR may (and often will) implement the proposed changes.\n    The proposal as essentially a description of the changes.\n\n2.  A proposal-centric model. The review team is trying to achieve consensus\n    around a proposal. The PR may show a preview of the implementation, but it\n    is purely informative.\n\nIf one favors a PR-centric model, this steers one away from committing proposals\nthat are not accepted, towards committing proposals to the affected repository,\netc. In general, the PR-centric model was favored.\n\n### Rationale for using a GitHub markdown-centric flow\n\n-   The GitHub markdown-centric flow makes the on-ramp as smooth as possible for\n    external contributors.\n    -   This positions the project to maximize the ease of engaging with and\n        gaining contributions from the wider industry.\n-   The final documents must be in markdown form, so it is best if contributors\n    have the option to stay in markdown for the whole process. This is\n    significantly less complex than something that converts between formats:\n\n    -   Less to learn\n    -   Fewer steps in the process\n    -   No outdated versions in the old format left behind\n\n-   The technical flow seems on balance better than the Google Docs-based\n    workflow. The proposal does a really good job explaining advantages and\n    disadvantages. In summary, the Google Docs-centric workflow has a lot of\n    disadvantages that make it difficult to work with proposals over the long\n    term.\n\n### Rationale for not requiring tracking issues\n\nThere were several members who had no strong preference on this issue. The\nconsensus was that until there is a compelling reason to require tracking\nissues, the process is more light-weight without them.\n\n### Rationale for not committing proposals that are declined or deferred\n\n-   This approach seems simpler.\n-   When a proposal PR includes the changes put forth in the proposal\n    (PR-centric model), the declined PR might need to be considerably\n    changed--and might lose context--in order to be committed.\n-   The community will put a lot of work into developing, discussing, and making\n    a decision on a proposal. There may be valuable insight in rejected\n    proposals, so it makes sense to archive them. However, as noted, committing\n    the PR will not always be possible with reasonable effort if not working in\n    a proposal-centric model, as the proposal text may not stand on its own.\n-   While we may discover issues with this approach, it is better to try this\n    way, see if any issues can be rectified, and propose changes as necessary.\n\n### Rationale for committing a proposal to the repository it affects\n\n-   This keeps the proposal close to the repository, and therefore, the\n    community, that it affects.\n-   It facilitates autonomy of (future) review teams responsible for a\n    particular aspect of Carbon. For example, a reference implementation team\n    responsible for the carbon-toolchain repository.\n-   It simplifies the common case and makes it easier to find how each\n    repository evolves over time.\n\n### Rationale for pushing high-level comments to GitHub\n\nWhile opinions were not as strong, reasons given for preferring comments in\nGitHub:\n\n-   This flow will maximize the alignment with “normal” GitHub development flow.\n    -   This both improves pulling external/new people into the flow, and will\n        reduce the number of flows they need to learn/remember/tool for.\n-   We will get ecosystem benefits as this flow continues to be optimized by\n    GitHub and those using it.\n\n### Open questions\n\n#### Do we use a Google Docs-centric or GitHub Markdown-centric flow?\n\n**Decision:** Use GitHub Markdown-centric flow.\n\n#### Where should proposals be stored in GitHub?\n\n**Decision:** Store proposals in the repository they affect.\n\n#### Should we push comments to focus on GitHub?\n\n**Decision:** Push high-level comments to GitHub, rather than focusing these\ndiscussions in Discourse.\n\n#### Should there be a tracking issue?\n\n**Decision:** Don't require tracking issues.\n\n#### Should declined/deferred proposals be committed?\n\n**Decision:** Do not commit declined/deferred proposals.\n"
  },
  {
    "path": "proposals/p0051.md",
    "content": "# Goals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/51)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Including success criteria](#including-success-criteria)\n-   [Alternatives](#alternatives)\n    -   [Change priority of interoperability and migration](#change-priority-of-interoperability-and-migration)\n    -   [Address project goals differently](#address-project-goals-differently)\n        -   [Status quo](#status-quo)\n        -   [Completely remove the community priority from this document](#completely-remove-the-community-priority-from-this-document)\n        -   [Add project goals to the priority list](#add-project-goals-to-the-priority-list)\n        -   [Merge project goals and language goals](#merge-project-goals-and-language-goals)\n-   [Rationale](#rationale)\n    -   [Open questions](#open-questions)\n\n<!-- tocstop -->\n\n## Problem\n\nWe want to have clear goals for the Carbon project, to both establish and\ndocument where we expect Carbon to be headed. These are aspirational goals, and\nwe will try our best to achieve all of them. The documented goals should make it\neasier for potential users to determine whether Carbon is an appropriate fit for\nthem.\n\n## Background\n\nCarbon's goals are heavily based on\n[\"Goals and priorities for C++\"](https://docs.google.com/document/d/1jrpGk6Sa0bt1u1tSuZtPnVI3inr7A4c0iJC9V2I6zUA/edit).\nMany thanks to the authors and contributors for helping us formulate our goals\nand priorities.\n\nThis proposal was drafted in\n[Docs](https://docs.google.com/document/d/1MJvVIDXQrhIj6hZ7NwMDbDch9XLO2VaYrGq29E57meU/edit).\n\n## Proposal\n\nThe proposed goals are encapsulated in\n[the goals changes](/docs/project/goals.md).\n\n### Including success criteria\n\nThe goals are currently a series of rough goals, with no specific metrics to\nmeasure them by. We've discussed adding metrics, and decided not to include them\nin the goals; the expectation is that they'll be added separately as a\nprinciple.\n\nThis proposal includes\n[success criteria](/docs/project/principles/success_criteria.md) covering:\n\n-   Platforms\n-   Migration tooling\n\nIt should be expected that more will be added in the future.\n\n## Alternatives\n\n### Change priority of interoperability and migration\n\nRight now, interoperability/migration is priority #7, indicating that when\ntrade-offs are necessary, interoperability is likely to suffer. At least some\nparties believe it should be somewhere in the top 3 priorities, perhaps #1.\nOverall, we believe a consensus can be formed around keeping\ninteroperability/migration as #7, so long as there are clear minimum\nexpectations for interoperability.\n\nPart of the priority conflict may be an interpretation that there will only\nrarely be compromises between goals, irrespective of the priority of\ninteroperability. For example, considering the readability of C++\ninteroperability syntax, it could be viewed in two ways:\n\n1. An edge-case syntax that can be avoided in most code, thus not significantly\n   affecting the readability goal.\n2. A readability issue that risks making _all_ code less readable, representing\n   the interoperability goal as subverting the readability goal, in which case\n   either interoperability must be higher priority than readability, or we must\n   have no interoperability.\n\nWhile the proposers prefer the first interpretation, the second all-or-nothing\ninterpretation may be what's leading to the desire of treating interoperability\nas a higher priority.\n\nOverall, we would present the advantages and disadvantages as:\n\nAdvantages:\n\n-   There is a consensus that interoperability is critical. Making it the top\n    goal emphasizes that.\n\nDisadvantages:\n\n-   While interoperability is critical, the same is true of other goals; this\n    isn't enough to determine priority.\n-   There are trade-offs between goals where there is already a consensus that\n    interoperability will be diminished in favor of other goals, and there\n    aren't as many clear cases in the other direction.\n    -   Taken to extremes, making interoperability and migration a higher\n        priority than evolution would suggest that Carbon should start with C++\n        and incrementally evolve from that base. We have observed areas where\n        C++ has had trouble evolving, and Carbon would risk getting stuck on\n        similar local maxima in order to avoid breaking existing code.\n\nFor example of where trade-offs may be seen right now:\n\n-   Carbon's set of primitive types won't match C++'s list; we currently expect\n    multiple C++ types to map to single Carbon types. This could be considered a\n    conflict with multiple priorities:\n    -   #2: Carbon's leaning for fewer types should make evolution of the\n        language easier.\n    -   #3: Carbon code will be easier to read and understand with fewer types.\n-   When considering `Int` vs `int`, Carbon's plans do not mirror C++. This\n    could be considered a conflict with multiple priorities:\n    -   #1: Carbon's primary types, such as `Int`, should be allowed to replace\n        C++-specified overflow behaviors with alternatives that are higher\n        performance.\n    -   #3: Avoiding platform-specific types should make it easier to understand\n        how could will function on various platforms.\n    -   #4: Carbon's plan for `Int` trapping where C++ would overflow should\n        make code safety easier.\n-   We expect platform support priorities to differ between C/C++ and Carbon.\n    This is a conflict with Carbon's #6 priority, which focuses support on\n    modern over legacy platforms.\n-   C++'s preprocessor macros will be replaced by metaprogramming in Carbon.\n    It's not clear what migration of code using macros will look like, but some\n    will likely be expanded by automation. This could be considered a conflict\n    with multiple priorities:\n    -   #2: Structured metaprogramming should make it easier to evolve software.\n    -   #3: Metaprogramming should be easier to read than preprocessor macros.\n-   Templates have been argued as only being added for\n    interoperability/migration, and that we could only have generics without\n    that goal. This is not considered a conflict between goal priorities.\n    -   This could be considered a conflict with priority #3, because templates\n        are hard to read and understand. However, templates don't constrain\n        other parts of the language. While they may have readability or other\n        problems, they aren't core or required in the way that other elements\n        are, including primitive types.\n\n### Address project goals differently\n\nA concern was raised that, while the \"Governance and evolution\" doc calls for\nall decisions to be justified by goals, there was no clear goal to justify the\nexistence of things like a code of conduct. Similarly, if performance is the\nhighest priority, then one might decide that retaining a performance expert may\ntake priority over addressing their bad behavior.\n\nTo address this issue, project goals were added. They are not explicitly part of\nthe numeric priority list. However, while we expect a ranking of language goals\nin order to weigh tradeoffs in the language design, we see project goals as\northogonal to language design.\n\n#### Status quo\n\nThe project goals could be addressed as-is in the proposal.\n\n#### Completely remove the community priority from this document\n\nWe could completely remove the project goals from this document.\n\nAdvantages:\n\n-   Allows this to be the \"language goals\" document.\n\nDisadvantages:\n\n-   Creates additional documents that need to be understood to parse language\n    goals.\n-   Makes for less clear prioritization of community, increasing ambiguity on\n    how community vs language design conflicts can be resolved.\n\n#### Add project goals to the priority list\n\nWe could make the project goals part of the priority list.\n\nAdvantages:\n\n-   Makes the ordering unambiguous.\n\nDisadvantages:\n\n-   Makes what's currently a numerated list of language design goals less\n    design-focused.\n-   Prevents saying trivial things like \"performance is our top priority\".\n    -   Unless community isn't the top priority, re-creating the conflict risk\n        that led to the creating of these project goals.\n\n#### Merge project goals and language goals\n\nOriginally, we only had one goals and priorities section. We could re-merge\nproject goals and language goals.\n\nAdvantages:\n\n-   Makes the document shorter and more concise.\n-   Tooling can already be considered a priority under \"Code that is easy to\n    read, understand, and write\", and is explicitly mentioned as part of that\n    goal.\n\nDisadvantages:\n\n-   Previous setup raised objections over why the community goal wasn't part of\n    the priority list.\n\n## Rationale\n\nA concrete set of goals is essential to ensure that contributors to the Carbon\nproject are working in the same direction, and as a guide for what constitutes\nprogress in every aspect of the project. It is important to have a coherent,\nagreed-upon vision and direction for a programming language, as a social\ncontract between people who work on it and people who use it. The goals listed\nhave been iterated on for many months by many parties.\n\nThese goals reflect not only the kind of community and language that the core\nteam would like to build, but also the kind of community and language that a\nlarge population of C++ users have been asking for from C++ itself. As a\nconsequence, this particular set of goals seems like an important direction in\nwhich to experiment with a candidate future for C++ itself. By doing so, it will\naddress a specific group of C++ users.\n\nWhile there may be some uncertainty about resolving conflicts between goals,\nparticularly migratability and C++ interoperability, the core team feels that\nthey are generally in alignment in this regard. The priority among goals can be\nrevised as needed based on the experience of using it in practice.\n\n### Open questions\n\nThere were no open questions. GitHub issue\n[106](https://github.com/carbon-language/carbon-lang/issues/106) contains points\nto be considered and, if necessary, resolved in a subsequent proposal.\n"
  },
  {
    "path": "proposals/p0063.md",
    "content": "# Criteria for Carbon to go public\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/63)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Alternatives considered](#alternatives-considered)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Problem\n\nCarbon is currently private, and should have a clear plan for going public.\n\n## Background\n\nSome of this is explained to people when they're asked if they'd like to\ncontribute to Carbon; the purpose of this proposal is to provide documentation.\n\n## Proposal\n\nSee /docs/project/going_public.md.\n\n## Alternatives considered\n\nWe have also considered going public immediately. We believe the noted criteria\nare important to address before proceeding.\n\n## Rationale\n\n\"An open, inclusive process for Carbon changes\" requires us to make the decision\nto go public in a clear and unsurprising way, with criteria that are written\ndown.\n\nGoing public too early introduces risks to the long-term evolution and\nmaintenance of the language by increasing the costs of the community members\ndeveloping it.\n\nEnsuring that Carbon meets its functional goals, especially that of\ninteroperability and migration, will inherently require large scale\nexperimentation that is infeasible to do without becoming public at some point.\n\nThe core team is aligned on the core policy decisions, which are:\n\n-   The decision to go public will go through the usual proposal process.\n-   The structure of the proposal gives the things that we are looking for prior\n    to going public.\n-   We expect to delay announcing to the extent we can.\n-   We do not expect that to be so late that everything is done and we are ready\n    to ship. That is, we are not going to wait until version 1.0 is ready.\n    -   We don't expect this to be so late that Carbon is no longer an\n        experiment.\n\nChanges to the text and wording that align with these items should be submitted\nas code reviews. The core team members chandlerc and zygloid will both approve\neach code review.\n\nAn example change that would be covered by a code review: there will be no\nautomatic going public just because the criteria are met -- it will be a\ndecision of the core team.\n"
  },
  {
    "path": "proposals/p0074.md",
    "content": "# Change comment/decision timelines in proposal process\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/74)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Open Question/Bikeshed](#open-questionbikeshed)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Alternative 1](#alternative-1)\n    -   [Alternative 2](#alternative-2)\n-   [Rationale](#rationale)\n    -   [Open questions](#open-questions)\n        -   [Do we want to add the proposal to the core team meeting agenda when the deadline for comments is announced, or when the deadline is reached?](#do-we-want-to-add-the-proposal-to-the-core-team-meeting-agenda-when-the-deadline-for-comments-is-announced-or-when-the-deadline-is-reached)\n\n<!-- tocstop -->\n\n## Problem\n\nIn the existing approval process, the deadline for a decision is set to be at\nleast a week after the comment period. The request for final comments currently\nasks that remaining comments be provided within a day, essentially setting a\nsoft deadline for the end of the comment period unless issues arise. As such,\nthe end of the comment period--which is where most of the decision work usually\ntakes place--is not known very far in advance. This makes it difficult for core\nteam members to prioritize work to get proposals fully reviewed by the end of\nthe comment period.\n\n## Background\n\nPeople tend to prioritize work based on deadlines. In the current proposal\napproval process, the deadline for final comments is not known until the day\nbefore they are due (if not extended). Ideally, we want the core team to have\nall issues with a proposal raised and addressed to the extent possible prior to\nentering the decision phase. As such, the work of the core team is front-loaded\nto the comment phase, and the decision is usually delivered shortly after the\nend of the comment phase and well before the decision deadline. While the\ncomment period usually begins long before the final request for comments is\nissued, there are often multiple outstanding proposals (as well as non-Carbon\nwork) competing for the attention of the core team.\n\n## Proposal\n\nAnnounce the end of the comment period further in advance, while reducing the\ninterval between the end of the comment period and the decision meeting.\n\nThe advanced notification will allow team members to more easily prioritize\ntheir review work. It also reflects the importance of getting issues surfaced\nduring the review period rather than the decision period.\n\n## Details\n\n-   A deadline for final comments will be published at least 7 calendar days (or\n    4 working days, if longer) in advance (instead of the current 1 day). On or\n    before the deadline date, the deadline may be extended if the review manager\n    determines that there is still productive discussion going on.\n    -   At the time the comment period deadline is announced, the proposal will\n        be added to the agenda of the next core team meeting following the\n        comment period deadline.\n-   There must be a minimum of four working days between the end of the comment\n    period and the day of the meeting.\n    -   If the deadline for comments is extended, the agenda item will be moved,\n        if necessary, by the review manager.\n\n### Open Question/Bikeshed\n\nDo we want to add the proposal to the core team meeting agenda when the deadline\nfor comments is announced, or when the deadline is reached? The advantage of the\nlatter is that no adjustments need to be made if the deadline is extended. The\nadvantage of the former is that it gives people an idea of whether a core team\nmeeting can be canceled further in advance.\n\n## Alternatives considered\n\n### Alternative 1\n\nLeaving the approval process as it is.\n\n### Alternative 2\n\nReducing the amount of time between the end of the comment period and the\ndecision meeting.\n\nThis option was not chosen because the shorter period could result in more\nmeetings, as the deciders would have less time to get their decisions in. It has\nthe potential to reduce the velocity of decisions if it results in decisions\nhappening later than they would with an earlier meeting date (decision\ndeadline).\n\n## Rationale\n\n-   This directly supports our community goals: not everybody is in a position\n    to respond to events with less than a day of latency, so longer lead times\n    before deadlines will help enable them to participate.\n    -   Longer lead time makes it more likely that we'll get substantive\n        comments.\n-   The answer to the open question doesn't strongly matter, and there is a\n    preference for leaving it to the review managers' discretion rather than\n    having the core team decide.\n\n### Open questions\n\n#### Do we want to add the proposal to the core team meeting agenda when the deadline for comments is announced, or when the deadline is reached?\n\nThe core team is okay with available options, and treating this as a bikeshed\nthat can be resolved by review managers as part of doc changes.\n"
  },
  {
    "path": "proposals/p0083.md",
    "content": "# In-progress design overview\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/83)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Goals](#goals)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Single-file design overview](#single-file-design-overview)\n    -   [No in-progress design overview](#no-in-progress-design-overview)\n    -   [No overview of designs](#no-overview-of-designs)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Problem\n\nWe need some vaguely consistent shared understanding of the language design as a\nwhole. The goal is merely consistency in discussions, in-progress syntax, and\ngeneral approach. It in no way needs reliably to reflect the end state, either\ndesired or realized. Instead, it should evolve as each area matures and becomes\nconcrete, while providing an overarching overview that connects the language\ntogether, and the consistent background that we all can refer back to during\ndiscussions.\n\n## Goals\n\nThis is intended to offer a reasonable starting point for:\n\n-   Example code.\n-   Conceptualizing Carbon at a high level.\n-   Reasonable, but not necessarily final, approaches to features in README.md.\n    -   If any idea is obviously bad, we can clean it up here.\n\nThis proposal is not intended to achieve:\n\n-   A whole language design.\n    -   This is way too much work for a single proposal; this is a skeletal\n        framework only.\n    -   As we work on feature-specific designs, we may decide to use other\n        approaches. That's fine: we only need somewhere to start.\n    -   The summaries in README.md may be expected to change over time.\n-   Feature-specific files aren't intended to be well-written or comprehensive.\n    They are a quick jot of prior thoughts.\n    -   We want to avoid getting stuck on language details that we should\n        consider more carefully regardless. If you're passionate about a\n        feature, please feel free to start a new proposal for it.\n    -   Each and every aspect of the suggested overview should be subject to\n        careful examination and justification before it becomes a settled plan\n        of record.\n\n## Background\n\nMany of the ideas here stem from discussions between several of the initial\npeople working on Carbon over several years. That doesn't make them good, but\nmay give some context on where they came from. They are also heavily informed by\nthe experience several of us have both working on the Clang C++ frontend and\nseveral C++ codebases including those of LLVM and Clang themselves.\n\n## Proposal\n\nSee [the language design overview document](/docs/design/README.md).\n\n## Alternatives considered\n\n### Single-file design overview\n\nWe also considered putting the full design overview in one file, as in\n[PR 22](https://github.com/carbon-language/carbon-lang/pull/22). This is versus\nthe hierarchy proposed here.\n\nAdvantages:\n\n-   All proposed changes are in one place.\n-   Easier for people to skim rationale and considered changes.\n\nDisadvantages:\n\n-   Encourages more single-file designs.\n    -   A principle of the multi-file approach is that complex features may have\n        subdirectories with their own README.md and files for sub-features,\n        similar to the relationship between this design overview and features.\n    -   Single-file designs may be harder to evolve long-term, as the volume of\n        information contained impedes reading.\n\n### No in-progress design overview\n\nThe primary alternative is to avoid even having a draft or in-progress design of\nthis form until each constituent component is more thoroughly conceived and\nconsidered.\n\nAdvantages:\n\n-   Avoids anchoring design on approaches that haven't yet been fully explored.\n    -   Avoids getting stuck on discussing details where a proposal isn't\n        fleshed out.\n\nDisadvantages:\n\n-   The lack of an overview can lead to significant confusion and\n    inconsistencies in discussion, hindering fleshing out details.\n    -   An overview offers basic shaping of the language as a whole, even as it\n        evolves.\n\nThe compromise chosen is to have the in-progress design and simply work to\nresist both anchoring and distraction stemming from it. We want to get the\nbenefits we can here while minimizing the cost.\n\n### No overview of designs\n\nThe overview will result in content duplication from individual designs. At the\ntime of this proposal, this may be significant because individual designs are\nnot fleshed out, and should thus duplication should be expected to reduce over\ntime. However, it should be expected to remain as the duplication is fundamental\nto having an overview.\n\nThis duplication could be addressed by removing the overview. Instead,\ndesign/README.md could be restricted to listing existing designs, with no\nadditional content.\n\nThe proposed approach assumes that the proposed overviews offer significant\nvalue for ramp-up.\n\nAdvantages:\n\n-   Eliminates content duplication.\n-   A simple index is easier to maintain long-term, with less to become stale.\n    -   It could be fully automated.\n\nDisadvantages:\n\n-   No quick way to get a high-level understanding.\n    -   The overview is the only step before \"reading every design\".\n    -   For example, we summarize common control flow keywords, so that readers\n        don't need to identify which documents they come from and what exists.\n-   Harder to show relationships between various features.\n    -   While examples can show how designs relate, it may not be as obvious\n        from a simple link, even when reading the associated design.\n    -   For example, lexical conventions come up as references for three\n        otherwise distinct sections. If we had a simple index of files, we\n        should expect users to need to read individual designs to understand\n        relationships.\n    -   For example, we explain in brief the relationships between categories of\n        types.\n    -   There's disagreement about whether the text of README.md offers any\n        utility:\n        [comment thread](https://github.com/carbon-language/carbon-lang/pull/83/files/25437de9e61b3a15e8ddde67b6297f1795922355..97da855dbe6023930e02473af46abea03af991e7#r444487049)\n\n## Rationale\n\nThis proposal provides some much-needed context for a lot of our discussions and\ndeliberations about Carbon. Having a skeleton in place for the language design\nis an important step forward. We can't make language design decisions in a\nvacuum -- we need a \"blurry outline\" of the big picture before we can start\nfilling in the details of any particular area. We need to establish a common\nframe of reference regarding the overall shape of the language, so that we can\nparallelize the in-depth design work.\n\nThat means that, by necessity, this proposal suggests lots of concrete design\ndecisions that have not yet had sufficient analysis for us to affirm them. There\nis a shared understanding that we are not committing to any of those decisions,\nonly to the broad picture painted by the combination of those decisions, and\nthat all such decisions need to be revisited by another proposal before we\nconsider them to be agreed on. There is a substantial risk of anchoring how we\nthink about Carbon -- we’ll just have to do our best to avoid taking this doc as\na given when evaluating subsequent proposals. Those proposals must justify a\ndirection that agrees with this doc as much as one that does not agree with it.\n\nThis doc sets the stage for increasingly incremental steps towards a complete\ndesign. Establishing a structure for the design is especially helpful as it will\nshow how things do or do not connect across the language.\n\nAdopting this largely work-in-progress overview in order to see the structure of\nthings, while still needing to resolve the specifics in each area, will directly\nhelp reinforce our goal of language evolution over time. This will help us learn\nhow to effectively iterate, and how to compensate and overcome the risks of\nanchoring, change aversion, and other challenges.\n"
  },
  {
    "path": "proposals/p0107.md",
    "content": "# Code and name organization\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/107)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n    -   [Out-of-scope issues](#out-of-scope-issues)\n-   [Open questions for the decision](#open-questions-for-the-decision)\n    -   [Should we switch to a library-oriented structure that's package-agnostic?](#should-we-switch-to-a-library-oriented-structure-thats-package-agnostic)\n    -   [Should there be a tight association between file paths and packages/libraries?](#should-there-be-a-tight-association-between-file-paths-and-packageslibraries)\n-   [Justification](#justification)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Packages](#packages)\n        -   [Name paths for package names](#name-paths-for-package-names)\n        -   [Referring to the package as `package`](#referring-to-the-package-as-package)\n        -   [Remove the `library` keyword from `package` and `import`](#remove-the-library-keyword-from-package-and-import)\n        -   [Rename package concept](#rename-package-concept)\n        -   [No association between the file system path and library/namespace](#no-association-between-the-file-system-path-and-librarynamespace)\n    -   [Libraries](#libraries)\n        -   [Allow exporting namespaces](#allow-exporting-namespaces)\n        -   [Allow importing implementation files from within the same library](#allow-importing-implementation-files-from-within-the-same-library)\n        -   [Alternative library separators and shorthand](#alternative-library-separators-and-shorthand)\n            -   [Single-word libraries](#single-word-libraries)\n        -   [Collapse API and implementation file concepts](#collapse-api-and-implementation-file-concepts)\n            -   [Automatically generating the API separation](#automatically-generating-the-api-separation)\n        -   [Collapse file and library concepts](#collapse-file-and-library-concepts)\n        -   [Collapse the library concept into packages](#collapse-the-library-concept-into-packages)\n        -   [Collapse the package concept into libraries](#collapse-the-package-concept-into-libraries)\n        -   [Different file type labels](#different-file-type-labels)\n        -   [Function-like syntax](#function-like-syntax)\n        -   [Inlining from implementation files](#inlining-from-implementation-files)\n        -   [Library-private access controls](#library-private-access-controls)\n        -   [Managing API versus implementation in libraries](#managing-api-versus-implementation-in-libraries)\n        -   [Multiple API files](#multiple-api-files)\n        -   [Name paths as library names](#name-paths-as-library-names)\n    -   [Imports](#imports)\n        -   [Block imports](#block-imports)\n        -   [Block imports of libraries of a single package](#block-imports-of-libraries-of-a-single-package)\n        -   [Broader imports, either all names or arbitrary code](#broader-imports-either-all-names-or-arbitrary-code)\n        -   [Direct name imports](#direct-name-imports)\n        -   [Optional package names](#optional-package-names)\n    -   [Namespaces](#namespaces)\n        -   [File-level namespaces](#file-level-namespaces)\n        -   [Scoped namespaces](#scoped-namespaces)\n-   [Rationale](#rationale)\n    -   [Open questions](#open-questions)\n        -   [Should we switch to a library-oriented structure that's package-agnostic?](#should-we-switch-to-a-library-oriented-structure-thats-package-agnostic-1)\n        -   [Should there be a tight association between file paths and packages/libraries?](#should-there-be-a-tight-association-between-file-paths-and-packageslibraries-1)\n\n<!-- tocstop -->\n\n## Problem\n\nHow do developers store code for the compiler, and access it for reuse?\n\n## Proposal\n\nAdopt an approach with tiered files, libraries, packages and namespaces in the\ndesign.\n\n### Out-of-scope issues\n\nRelated issues that are out-of-scope for this proposal are:\n\n-   Access control: while there is some implicit access control from interface\n    vs implementation considerations for libraries, they are more about\n    addressing circular dependencies in code.\n\n-   Aliasing implementation: while the `alias` keyword is critical to how easy\n    or difficult refactoring is, it should be designed on its own.\n\n-   Compilation details: this proposal sets up a framework that should enable\n    well-designed compilation, but does not set about to design how compilation\n    will work.\n\n-   File-private identifiers: Something similar to C++ `static` functions may\n    exist. However, that will be addressed separately.\n\n-   Incremental migration and unused imports: incrementally migrating a\n    declaration from one library to another might require an intermediate state\n    where callers import both libraries, with consequent issues. However, it may\n    also not require such. Whether it does, or whether tooling needs to be added\n    to support the specific intermediary state of transitional, unused imports,\n    is out of scope.\n\n-   Name lookup, including addressing conflicting names between imports and\n    names in the current file: the name lookup design is likely to address this\n    better, including offering syntax that could refer to it if needed.\n\n    -   After discussion, we believe we do not need to support package renaming.\n        However, that final decision should be based on name lookup addressing\n        the issue, as implications need to be considered more deeply.\n\n-   Package management: while we want to choose syntax that won't impose\n    barriers on building package management into Carbon, we should not make\n    assumptions about how package management should work.\n\n-   Prelude package, or fundamentals: while we've discussed how to handle name\n    lookup for things like `Int32`, this proposal mainly lays out a framework\n    where options for addressing that are possible.\n\nThis proposal should not be interpreted as addressing these issues. A separate\ndiscussion of these issues will remain necessary.\n\n## Open questions for the decision\n\nExtended open question comparisons may be found in\n[the examples doc](https://docs.google.com/document/d/1J8GX9uw5AxBz5Q22MLHJOfzLq4WJqKL-q1VwnKGHG-k/edit#)\nin addition to the `code_and_organization.md` alternatives section.\n\n### Should we switch to a library-oriented structure that's package-agnostic?\n\n**Decision:** No.\n\nRight now, the `package` syntax is very package-oriented. We could instead\neliminate package semantics from code and organization, relying only on\nlibraries and removing the link to distribution. This is the\n[collapse the package concept into libraries](#collapse-the-package-concept-into-libraries)\nalternative.\n\nDoes the core team agree with the approach to packages and libraries? If not,\ndoes the alternative capture what the core team wants to be turned into the\nproposal, or is some other approach preferred?\n\n### Should there be a tight association between file paths and packages/libraries?\n\n**Decision:** Make paths correspond to libraries for API files, not impl files.\nKeep `package`.\n\nRight now, the `package` syntax requires the package's own name be repeated\nthrough code. This touches on a couple alternatives:\n\n-   Strict association between the file system path and library/namespace\n-   [Referring to the package as `package`](#referring-to-the-package-as-package)\n\nThe end result of taking both alternatives would be that:\n\n-   The `package` and `library` would no longer need to be specified on the\n    first line.\n    -   The `import` would still need a `library`.\n-   The `package` keyword would always be used to refer to the current package.\n    -   Referring to the current package by name would be disallowed, to allow\n        for easier renames of conflicting package names.\n\n## Justification\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution):\n\n    -   The syntax and interactions between `package` and `import` should enable\n        moving code between files and libraries with fewer modifications to\n        callers, easing maintenance of large codebases.\n\n        -   In C++ terms, `#include` updates are avoidable when moving code\n            around.\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n\n    -   By setting up imports so that each name in a file is unique and refers\n        to the source package, we make the meaning of symbols clear and easier\n        to understand.\n\n    -   The proposed `namespace` syntax additionally makes it clear when the\n        package's default namespace is not being used.\n\n        -   This is in contrast to C++ namespaces, where the entire body of code\n            above the line of code in question may be used to start a namespace.\n\n    -   Clearly marking interfaces will make it easier for both client code and\n        IDE tab completion to more easily determine which APIs can be used from\n        a given library.\n\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development):\n\n    -   The structure of libraries and imports should help enable separate\n        compilation, particularly improving performance for large codebases.\n\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):\n\n    -   The syntax of `import` should enable extending imports for use in\n        interoperability code.\n\n## Alternatives considered\n\n### Packages\n\n#### Name paths for package names\n\nRight now, we only allow a single identifier for the package name. We could\nallow a full name path without changing syntax.\n\nAdvantages:\n\n-   Allow greater flexibility and hierarchy for related packages, such as\n    `Database.Client` and `Database.Server`.\n-   Would allow using GitHub repository names as package names. For example,\n    `carbon-language/carbon-toolchain` could become\n    `carbon_language.carbon_toolchain`.\n\nDisadvantages:\n\n-   Multiple identifiers is more complex.\n-   Other languages with similar distribution packages don't have a hierarchy,\n    and so it may be unnecessary for us.\n    -   In other languages that use packages for distribution, they apply\n        similar restrictions. For example,\n        [Node.JS/NPM](https://www.npmjs.com/), [Python PyPi](https://pypi.org/),\n        or [Rust Crates](https://crates.io/).\n    -   In [Rust Crates](https://crates.io/), we can observe an example\n        `winapi-build` and `winapi-util`.\n-   We can build a custom system for reserving package names in Carbon.\n\nAt present, we are choosing to use single-identifier package names because of\nthe lack of clear advantage towards a more complex name path.\n\n#### Referring to the package as `package`\n\nRight now, we plan to refer to the package containing the current file by name.\nWhat's important in the below example is the use of `Math.Stats`:\n\n```carbon\npackage Math library \"Stats\" api;\napi struct Stats { ... }\nstruct Quantiles {\n  fn Stats();\n  fn Build() {\n    ...\n    var Math.Stats: b;\n    ...\n  }\n}\n```\n\nWe could instead use `package` as an identifier within the file to refer to the\npackage, giving `package.Stats`.\n\nIt's important to consider how this behaves for `impl` files, which expect an\nimplicit import of the API. In other words, for `impl` files, this can be\ncompared to an implicit `import Math;` versus an implicit\n`import Math as package;`. However, there may also be _explicit_ imports from\nthe package, such as `import Math library \"Trigonometry\";`, which may or may not\nbe referable to using `package`, depending on the precise option used.\n\nAdvantages:\n\n-   Gives a stable name to refer to the current library's package.\n    -   This reduces the amount of work necessary if the current library's\n        package is renamed, although imports and library consumers may still\n        need to be updated. If the library can also refer to the package by the\n        package name, even with imports from other libraries within the package,\n        work may not be significantly reduced.\n-   The same syntax can be used to refer to entities with the same name as the\n    package.\n    -   For example, in a\n        [package named `DateTime`](https://docs.python.org/3/library/datetime.html#datetime-objects),\n        `package.DateTime` is unambiguous, whereas `DateTime.DateTime` could be\n        confusing.\n\nDisadvantages:\n\n-   We are likely to want a more fine-grained, file-level approach proposed by\n    [name lookup](/docs/design/name_lookup.md).\n-   Allows package owners to name their packages things that they rarely type,\n    but that importers end up typing frequently.\n    -   The existence of a short `package` keyword shifts the balance for long\n        package names by placing less burden on the package owner.\n-   Reuses the `package` keyword with a significantly different meaning,\n    changing from a prefix for the required declaration at the top of the file,\n    to an identifier within the file.\n    -   We don't need to have a special way to refer to the package to\n        disambiguate duplicate names. In other words, there is likely to be\n        other syntax for referring to an entity `DateTime` in the package\n        `DateTime`.\n    -   Renaming to a `library` keyword has been suggested to address concerns\n        with `package`. Given that `library` is an argument to `package`, it\n        does not significantly change the con.\n-   Creates inconsistencies as compared to imports from other packages, such as\n    `package Math; import Geometry;`, and imports from the current package, such\n    as `package Math; import Math library \"Stats\";`.\n    -   Option 1: Require `package` to be used to refer to all imports from\n        `Math`, including the current file. This gives consistent treatment for\n        the `Math` package, but not for other imports. In other words,\n        developers will always write `package.Stats` from within `Math`, and\n        `Math.Stats` will only be written in _other_ packages.\n    -   Option 2: Require `package` be used for the current library's entities,\n        but not other imports. This gives consistent treatment for imports, but\n        not for the `Math` package as a whole. In other words, developers will\n        only write `package.Stats` when referring to the current library,\n        whether in `api` or `impl` files. `Math.Stats` will be used elsewhere,\n        including from within the `Math` package.\n    -   Option 3: Allow either `package` or the full package name to refer to\n        the current package. This allows code to say either `package` or `Math`,\n        with no enforcement for consistency. In other words, both\n        `package.Stats` and `Math.Stats` are valid within the `Math` package.\n\nBecause name lookup can be expected to address the underlying issue differently,\nwe will not add a feature to support name lookup. We also don't want package\nowners to name their packages things that even _they_ find difficult to type. As\npart of pushing library authors to consider how their package will be used, we\nrequire them to specify the package by name where desired.\n\n#### Remove the `library` keyword from `package` and `import`\n\nRight now, we have syntax such as:\n\n```carbon\npackage Math library \"Median\" api;\npackage Math library \"Median\" namespace Stats api;\nimport Math library \"Median\";\n```\n\nWe could remove `library`, resulting in:\n\n```carbon\npackage Math.Median api;\npackage Math.Median namespace Math.Stats api;\nimport Math.Median;\n```\n\nAdvantages:\n\n-   Reduces redundant syntax in library declarations.\n    -   We expect libraries to be common, so this may add up.\n\nDisadvantages:\n\n-   Reduces explicitness of package vs library concepts.\n-   Creates redundancy of the package name in the namespace declaration.\n    -   Instead of `package Math.Median namespace Math.Stats`, could instead use\n        `Stats`, or `this.Stats` to elide the package name.\n-   Potentially confuses the library names, such as `Math.Median`, with\n    namespace names, such as `Math.Stats`.\n-   Either obfuscates or makes it difficult to put multiple libraries in the\n    top-level namespace.\n    -   This is important because we are interested in encouraging such\n        behavior.\n    -   For example, if `package Math.Median api;` uses the `Math` namespace,\n        the presence of `Median` with the same namespace syntax obfuscates the\n        actual namespace.\n    -   For example, if `package Math.Median namespace Math api` is necessary to\n        use the `Math` namespace, requiring the `namespace` keyword makes it\n        difficult to put multiple libraries in the top-level namespace.\n\nAs part of avoiding confusion between libraries and namespaces, we are declining\nthis alternative.\n\n#### Rename package concept\n\nIn other languages, a \"package\" is equivalent to what we call the name path\nhere, which includes the `namespace`. We may want to rename the `package`\nkeyword to avoid conflicts in meaning.\n\nAlternative names could be 'bundle', 'universe', or something similar to Rust's\n'crates'; perhaps 'compound' or 'molecule'.\n\nAdvantages:\n\n-   Avoids conflicts in meaning with other languages.\n    -   [Java](https://www.oracle.com/java/technologies/glossary.html), similar\n        to a namespace path.\n    -   [Go](https://golang.org/doc/effective_go.html#package-names), similar to\n        a namespace path.\n\nDisadvantages:\n\n-   The meaning of `package` also overlaps a fair amount, and we would lose that\n    context.\n    -   [Package management systems](https://en.wikipedia.org/wiki/List_of_software_package_management_systems)\n        in general.\n    -   [NPM/Node.js](https://www.npmjs.com/), as a distributable unit.\n    -   [Python](https://packaging.python.org/tutorials/installing-packages/),\n        as a distributable unit.\n    -   [Rust](https://doc.rust-lang.org/book/ch07-01-packages-and-crates.html),\n        as a collection of crates.\n    -   [Swift](https://developer.apple.com/documentation/packagedescription),\n        as a distributable unit.\n\n#### No association between the file system path and library/namespace\n\nSeveral languages create a strict association between the method for pulling in\nan API and the path to the file that provides it. For example:\n\n-   In C++, `#include` refers to specific files without any abstraction.\n    -   For example, `#include \"PATH/TO/FILE.h\"` means there's a file\n        `PATH/TO/FILE.h`.\n-   In Java, `package` and `import` both reflect file system structure.\n    -   For example, `import PATH.TO.FILE;` means there's a file\n        `PATH/TO/FILE.java`.\n-   In Python, `import` requires matching file system structure.\n    -   For example, `import PATH.TO.FILE` means there's a file\n        `PATH/TO/FILE.py`.\n-   In TypeScript, `import` refers to specific files.\n    -   For example, `import {...} from 'PATH/TO/FILE';` means there's a file\n        `PATH/TO/FILE.ts`.\n\nFor contrast:\n\n-   In Go, `package` uses an arbitrary name.\n    -   For example, `import \"PATH/TO/NAME\"` means there is a directory\n        `PATH/TO` that contains one or more files starting with `package NAME`.\n\nIn Carbon, we are using a strict association to say that\n`import PACKAGE library \"PATH/TO/LIBRARY\"` means there is a file\n`PATH/TO/LIBRARY.carbon` under some package root.\n\nAdvantages:\n\n-   The strict association makes it harder to move names between files without\n    updating callers.\n-   If there were a strict association of paths, it would also need to handle\n    file system-dependent casing behaviors.\n    -   For example, on Windows, `project.carbon` and `Project.carbon` are\n        conflicting filenames. This is exacerbated by paths, wherein a file\n        `config` and a directory `Config/` would conflict, even though this\n        would be a valid structure on Unix-based filesystems.\n\nDisadvantages:\n\n-   A strict association between file system path and import path makes it\n    easier to find source files. This is used by some languages for compilation.\n-   Allows getting rid of the `package` keyword by inferring related information\n    from the file system path.\n\nWe are choosing to have some association between the file system path and\nlibrary for API files to make it easier to find a library's files. We are not\ngetting rid of the `package` keyword because we don't want to become dependent\non file system structures, particularly as it would increase the complexity of\ndistributed builds.\n\n### Libraries\n\n#### Allow exporting namespaces\n\nWe propose to not allow exporting namespaces as part of library APIs. We could\neither allow or require exporting namespaces. For example:\n\n```carbon\npackage Checksums;\n\napi namespace Sha256;\n```\n\nWhile this approach would mainly be syntactic, a more pragmatic use of this\nwould be in refactoring. It implies that an aliased namespace could be marked as\nan `api`. For example, the below could be used to share an import's full\ncontents:\n\n```carbon\npackage Translator library \"Interface\" api;\n\nimport Translator library \"Functions\" as TranslatorFunctions;\n\napi alias Functions = TranslatorFunctions;\n```\n\nAdvantages:\n\n-   Avoids any inconsistency in how entities are handled.\n-   Reinforces whether a namespace may contain `api` entities.\n-   Enables new kinds of refactorings.\n\nDisadvantages:\n\n-   Creates extra syntax for users to remember, and possibly forget, when\n    declaring `api` entities.\n    -   Makes it possible to have a namespace marked as `api` that doesn't\n        contain any `api` entities.\n-   Allowing aliasing of entire imports makes it ambiguous which entities are\n    being passed on through the namespace.\n    -   This may impair refactoring.\n    -   This can be considered related to\n        [broader imports, either all names or arbitrary code](#broader-imports-either-all-names-or-arbitrary-code).\n\nThis alternative is declined because it's not sufficiently clear it'll be\nhelpful, versus impairment of refactoring.\n\n#### Allow importing implementation files from within the same library\n\nThe current proposal is that implementation files in a library implicitly import\ntheir API, and that they cannot import other implementation files in the same\nlibrary.\n\nWe could instead allow importing implementation files from within the same\nlibrary. There are two ways this could be done:\n\n-   We could add a syntax for importing symbols from other files in the same\n    library. This would make it easy to identify a directed acyclic graph\n    between files in the library. For example:\n\n    ```carbon\n    package Geometry;\n\n    import file(\"point.6c\");\n    ```\n\n-   We could automatically detect when symbols from elsewhere in the library are\n    referenced, given an import of the same library. For example:\n\n    ```carbon\n    package Geometry;\n\n    import this;\n    ```\n\nAdvantages:\n\n-   Allows more separation of implementation between files within a library.\n\nDisadvantages:\n\n-   Neither approach is quite clean:\n    -   Using filenames creates a common case where filenames _must_ be used,\n        breaking away from name paths.\n    -   Detecting where symbols exist may cause separate parsing, compilation\n        debugging, and compilation parallelism problems.\n-   Libraries are supposed to be small, and we've chosen to only allow one API\n    file per library to promote that concept. Encouraging implementation files\n    to be inter-dependent appears to support a more complex library design\n    again, and may be better addressed through inter-library ACLs.\n-   Loses some of the ease-of-use that some other languages have around imports,\n    such as Go.\n-   Part of the argument towards `api` and `impl`, particularly with a single\n    `api`, has been to mirror C++ `.h` and `.cc`. Wherein a `.cc` `#include`-ing\n    other `.cc` files is undesirable, allowing a `impl` to import another `impl`\n    could be considered similarly.\n\nThe problems with these approaches, and encouragement towards small libraries,\nis how we reach the current approach of only importing APIs, and automatically.\n\n#### Alternative library separators and shorthand\n\nExamples are using `/` to separator significant terms in library names, and `//`\nto separate the package name in shorthand. For example,\n`package Time library \"Timezones/Internal\";` with shorthand\n`Time//Timezones/Internal`.\n\nNote that, because the library is an arbitrary string and shorthand is not a\nlanguage semantic, this won't affect much. However, users should be expected to\ntreat examples as best practice.\n\nWe could instead use `.` for library names and `/` for packages, such as\n`Time/Timezones.Internal`.\n\nAdvantages:\n\n-   Clearer distinction between the package and library, increasing readability.\n-   We have chosen not to\n    [enforce file system paths](#should-there-be-a-tight-association-between-file-paths-and-packageslibraries)\n    in order to ease refactoring, and encouraging a mental model where they may\n    match could confuse users.\n\nDisadvantages:\n\n-   Uses multiple separators, so people need to type different characters.\n-   There is a preference for thinking of libraries like file system paths, even\n    if they don't actually correspond.\n\nPeople like `/`, so we're going with `/`.\n\n##### Single-word libraries\n\nWe could stick to single word libraries in examples, such as replacing\n`library \"Algorithms/Distance\"` with `library \"Distance\"`.\n\nAdvantages:\n\n-   Encourages short library names.\n\nDisadvantages:\n\n-   Users are likely to end up doing some hierarchy, and we should address it.\n    -   Consistency will improve code understandability.\n\nWe might list this as a best practice, and have Carbon only expose libraries\nfollowing it. However, some hierarchy from users can be expected, and so it's\nworthwhile to include a couple examples to nudge users towards consistency.\n\n#### Collapse API and implementation file concepts\n\nWe could remove the distinction between API and implementation files.\n\nAdvantages:\n\n-   Removing the distinction between API and implementation would be a language\n    simplification.\n-   Developers will not need to consider build performance impacts of how they\n    are distributing code between files.\n\nDisadvantages:\n\n-   Serializes compilation across dependencies.\n    -   May be exacerbated because developers won't be aware of when they are\n        adding a dependency that affects imports.\n    -   In large codebases, it's been necessary to abstract out API from\n        implementation in languages that similarly consolidate files, such as\n        Java. However, the lack of language-level support constrains potential\n        benefit and increases friction for a split.\n-   Whereas an `api`/`impl` hierarchy gives a structure for compilation, if\n    there are multiple files we will likely need to provide a different\n    structure, perhaps explicit file imports, to indicate intra-library\n    compilation dependencies.\n    -   We could also effectively concatenate and compile a library together,\n        reducing build parallelism options differently.\n-   Makes it harder for users to determine what the API is, as they must read\n    all the files.\n\nRequiring users to manage the `api`/`impl` split allows us to speed up\ncompilation for large codebases. This is important for large codebases, and\nshouldn't directly affect small codebases that choose to only use `api` files.\n\n##### Automatically generating the API separation\n\nWe could try to address the problems with collapsing API and implementation\nfiles by automatically generating an API file from the input files for a\nlibrary.\n\nFor example, it may preprocess files to split out an API, reducing the number of\nimports propagated for _actual_ APIs. For example:\n\n1. Extract `api` declarations within the `api` file.\n2. Remove all implementation bodies.\n3. Add only the imports that are referenced.\n\nEven under the proposed model, compilation will do some of this work as an\noptimization. However, determining which imports are referenced requires\ncompilation of all imports that _may_ be referenced. When multiple libraries are\nimported from a single package, it will be ambiguous which imports are used\nuntil all have been compiled. This will cause serialization of compilation that\ncan be avoided by having a developer split out the `impl`, either manually or\nwith developer tooling.\n\nThe `impl` files may make it easier to read code, but they will also allow for\nbetter parallelism than `api` files alone can. This does not mean the compiler\nwill or will not add optimizations -- it only means that we cannot wholly rely\non optimizations by the compiler.\n\nAutomatically generating the API separation would only partly mitigate the\nserialization of compilation caused by collapsing file and library concepts.\nMost of the build performance impact would still be felt by large codebases, and\nso the mitigation does not significantly improve\n[the alternative](#collapse-api-and-implementation-file-concepts).\n\n#### Collapse file and library concepts\n\nWe could collapse the file and library concepts. What this implies is:\n\n-   [Collapse API and implementation file concepts](#collapse-api-and-implementation-file-concepts).\n    -   As described there, this approach significantly reduces the ability to\n        separate compilation.\n-   Only support having one file per library.\n    -   The file would need to contain both API and implementation together.\n\nThis has similar advantages and disadvantages to\n[collapse API and implementation file concepts](#collapse-api-and-implementation-file-concepts).\nDifferences follow.\n\nAdvantages:\n\n-   Offers a uniformity of language usage.\n    -   Otherwise, some developers will use only `api` files, while others will\n        always use `impl` files.\n-   The structure of putting API and implementation in a single file mimics\n    other modern languages, such as Java.\n-   Simplifies IDEs and refactoring tools.\n    -   Otherwise, these systems will need to understand the potential for\n        separation of interface from implementation between multiple files.\n    -   For example, see\n        [potential refactorings](/docs/design/code_and_name_organization/README.md#potential-refactorings).\n\nDisadvantages:\n\n-   Avoids the need to establish a hierarchy between files in a library, at the\n    cost of reducing build parallelism options further.\n-   While both API and implementation is in the same file, it can be difficult\n    to visually identify the API when it's mixed with a lengthy implementation.\n\nAs with\n[collapse API and implementation file concepts](#collapse-api-and-implementation-file-concepts),\nwe consider the split to be important for large codebases. The additional\nadvantages of a single-file restriction do not outweigh the disadvantages\nsurrounding build performance.\n\n#### Collapse the library concept into packages\n\nWe could only have packages, with no libraries. Some other languages do this;\nfor example, in Node.JS, a package is often similar in size to what we currently\ncall a library.\n\nIf packages became larger, that would lead to compile-time bottlenecks. Thus, if\nCarbon allowed large packages without library separation, we would undermine our\ngoals for fast compilation. Even if we combined the concepts, we should expect\nit's by turning the \"package with many small libraries\" concept into \"many small\npackages\".\n\nAdvantages:\n\n-   Simplification of organizational hierarchy.\n    -   Less complexity for users to think about on imports.\n\nDisadvantages:\n\n-   Coming up with short, unique package names may become an issue, leading to\n    longer package names that overlap with the intent of libraries.\n    -   These longer package names would need to be used to refer to contained\n        entities in code, affecting brevity of Carbon code. The alternative\n        would be to expect users to always rename packages on import; some\n        organizations anecdotally see equivalent happen for C++ once names get\n        longer than six characters.\n    -   For example, [boost](https://github.com/boostorg) could use\n        per-repository packages like `BoostGeometry` and child libraries like\n        `algorithms-distance` under the proposed approach. Under the alternative\n        approach, it would use either a monolithic package that could create\n        compile-time bottlenecks, or packages like\n        `BoostGeometryAlgorithmsDistance` for uniqueness.\n-   While a package manager will need a way to specify cross-package version\n    compatibility, encouraging a high number of packages puts more weight and\n    maintenance cost on the configuration.\n    -   We expect libraries to be versioned at the package-level.\n\nWe prefer to keep the library separation to enable better hierarchy for large\ncodebases, plus encouraging small units of compilation. It's still possible for\npeople to create small Carbon packages, without breaking it into multiple\nlibraries.\n\n#### Collapse the package concept into libraries\n\nVersus\n[collapse the library concept into packages](#collapse-the-library-concept-into-packages),\nwe could have libraries without packages. Under this model, we still have\nlibraries of similar granularity as what's proposed. However, there is no\npackage grouping to them: there are only libraries which happen to share a\nnamespace.\n\nReferences to imports from other top-level namespaces would need to be prefixed\nwith a '`.`' in order to make it clear which symbols were from imports.\n\nFor example, suppose `Boost` is a large system that cannot be distributed to\nusers in a single package. As a result, `Random` functionality is in its own\ndistribution package, with multiple libraries contained. The difference between\napproaches looks like:\n\n-   `package` vs `library`:\n    -   Trivial:\n        -   Proposal: `package BoostRandom;`\n        -   Alternative: `library \"Boost/Random\" namespace Boost;`\n    -   Multi-layer library:\n        -   Proposal: `package BoostRandom library \"Uniform\";`\n        -   Alternative: `library \"Boost/Random.Uniform\" namespace Boost;`\n    -   Specifying namespaces:\n        -   Proposal: `package BoostRandom namespace Distributions;`\n        -   Alternative:\n            `library \"Boost/Random.Uniform\" namespace Boost.Random.Distributions;`\n    -   Combined:\n        -   Proposal:\n            `package BoostRandom library \"Uniform\" namespace Distributions;`\n        -   Alternative:\n            `library \"Boost/Random.Uniform\" namespace Boost.Random.Distributions;`\n-   `import` changes:\n    -   Trivial:\n        -   Proposal: `import BoostRandom;`\n        -   Alternative: `import \"Boost/Random\";`\n    -   Multi-layer library:\n        -   Proposal: `import BoostRandom library \"Uniform\";`\n        -   Alternative: `import \"Boost/Random.Uniform\";`\n    -   Namespaces have no effect on `import` under both approaches.\n-   Changes to use an imported entity:\n    -   Proposal: `BoostRandom.UniformDistribution`\n    -   Alternative:\n        -   If the code is in the `Boost.Random` namespace: `Uniform`\n        -   If the code is in the `Boost` package but a different namespace:\n            `Random.Uniform`\n        -   If the code is outside the `Boost` package: `.Boost.Random.Uniform`\n\nWe assume that the compiler will enforce that the root namespace must either\nmatch or be a prefix of the library name, followed by a `/` separator. For\nexample, `Boost` in the namespace `Boost.Random.Uniform` must either match a\n`library \"Boost\"` or prefix as `library \"Boost/...\"`; `library \"BoostRandom\"`\ndoes not match because it's missing the `/` separator.\n\nThere are several approaches which might remove this duplication, but each has\nbeen declined due to flaws:\n\n-   We could have `library \"Boost/Random.Uniform\";` imply `namespace Boost`.\n    However, we want name paths to use things listed as identifiers in files. We\n    specifically do not want to use strings to generate identifiers in order to\n    support understandability of code.\n-   We could alternately have `namespace Boost;` syntax imply\n    `library \"Boost\" namespace Boost;`.\n    -   This approach only helps with single-library namespaces. While this\n        would be common enough that a special syntax would help some developers,\n        we are likely to encourage multiple libraries per namespace as part of\n        best practices. We would then expect that the quantity of libraries in\n        multi-library namespaces would dominate cost-benefit, leaving this to\n        address only an edge-case of duplication issues.\n    -   This would create an ambiguity between the file-level `namespace` and\n        other `namespace` keyword use. We could then rename the `namespace`\n        argument for `library` to something like `file-namespace`.\n    -   It may be confusing as to what `namespace Boost.Random;` does. It may\n        create `library \"Boost/Random\"` because `library \"Boost.Random\"` would\n        not be legal, but the change in characters may in turn lead to developer\n        confusion.\n        -   We could change the library specification to use `.` instead of `/`\n            as a separator, but that may lead to broader confusion about the\n            difference between libraries and namespaces.\n\nAdvantages:\n\n-   Avoids introducing the \"package\" concept to code and name organization.\n    -   Retains the key property that library and namespace names have a prefix\n        that is intended to be globally unique.\n    -   Avoids coupling package management to namespace structure. For example,\n        it would permit a library collection like Boost to be split into\n        multiple repositories and multiple distribution packages, while\n        retaining a single top-level namespace.\n-   The library and namespace are pushed to be more orthogonal concepts than\n    packages and namespaces.\n    -   Although some commonality must still be compiler-enforced.\n-   For the common case where packages have multiple libraries, removing the\n    need to specify both a package and library collapses two keywords into one\n    for both `import` and `package`.\n-   It makes it easier to draw on C++ intuitions, because all the concepts have\n    strong counterparts in C++.\n-   The prefix `.` on imported name paths can help increase readability by\n    making it clear they're from imports, so long as those imports aren't from\n    the current top-level namespace.\n-   Making the `.` optional for imports from the current top-level namespace\n    eliminates the boilerplate character when calling within the same library.\n\nDisadvantages:\n\n-   The use of a leading `.` to mark absolute paths may conflict with other\n    important uses, such as designated initializers and named parameters.\n-   Declines an opportunity to align code and name organization with package\n    distribution.\n    -   Alignment means that if a developer sees\n        `package BoostRandom library \"Uniform\";`, they know installing a package\n        `BoostRandom` will give them the library. Declining this means that\n        users seeing `library \"Boost/Random.Uniform\"`, they will still need to\n        do research as to what package contains `Boost/Random.Uniform` to figure\n        out how to install it because that package may not be named `Boost`.\n    -   Package distribution is a\n        [project goal](/docs/project/goals.md#language-tools-and-ecosystem), and\n        cannot be avoided indefinitely.\n    -   This also means multiple packages may contribute to the same top-level\n        namespace, which would prevent things like tab-completion in IDEs from\n        producing cache optimizations based on the knowledge that modified\n        packages cannot add to a given top-level namespace. For example, the\n        ability to load less may improve performance:\n        -   As proposed, a package `BoostRandom` only adds to a namespace of the\n            same name. If a user is editing libraries in a package\n            `BoostCustom`, then `BoostRandom` may be treated as unmodifiable. An\n            IDE could optimize cache invalidation of `BoostRandom` at the\n            package level. As a result, if a user types `BoostRandom.` and\n            requests a tab completion, the system need only ensure that\n            libraries from the `BoostRandom.` package are loaded for an accurate\n            result.\n        -   Under this alternative, a library `Boost.Random` similarly adds to\n            the namespace `Boost`. However, if a user is editing libraries, the\n            IDE needs to support them adding to both `Boost` and `MyProject`\n            simultaneously. As a result, if a user types `Boost.` and requests a\n            tab completion, the system must have all libraries from all packages\n            loaded for an accurate result.\n        -   Although many features can be restricted to _current_ imports, some\n            features, such as\n            [auto-imports](https://www.jetbrains.com/help/idea/creating-and-optimizing-imports.html),\n            examine _possible_ imports. Large codebases may have a\n            memory-constrained quantity of possible imports.\n-   The string prefix enforcement between `library` and `namespace` forces\n    duplication between both, which would otherwise be handled by `package`.\n-   For the common case of packages with a matching namespace name, increases\n    verbosity by requiring the `namespace` keyword.\n-   The prefix `.` on imported name paths will be repeated frequently through\n    code, increasing overall verbosity, versus the package approach which only\n    affects import verbosity.\n-   Making the `.` optional for imports from the current top-level namespace\n    hides whether an API comes from the current library or an import.\n\nWe are declining this approach because we desire package separation, and because\nof concerns that this will lead to an overall increase in verbosity due to the\n[preference for few child namespaces](/docs/design/code_and_name_organization/README.md#preference-for-few-child-namespaces),\nwhereas this alternative benefits when `namespace` is specified more often.\n\n#### Different file type labels\n\nWe're using `api` and `impl` for file types, and have `test` as an open\nquestion.\n\nWe've considered using `interface` instead of `api`, but that introduces a\nterminology collision with interfaces in the type system.\n\nWe've considered dropping `api` from naming, but that creates a definition from\nabsence of a keyword. It also would be more unusual if both `impl` and `test`\nmust be required, that `api` would be excluded. We prefer the more explicit\nname.\n\nWe could spell out `impl` as `implementation`, but are choosing the abbreviation\nfor ease of typing. We also don't think it's an unclear abbreviation.\n\nWe expect `impl` to be used for implementations of `interface`. This isn't quite\nas bad as if we used `interface` instead of `api` because of the `api` export\nsyntax on entities, such as `api fn DoSomething()`, which could create\nambiguities as `interface fn DoSomething()`. It may still confuse people to see\nan `interface impl` in an `api` file. However, we're touching on related\nconcepts and don't see a great alternative.\n\n#### Function-like syntax\n\nWe could consider more function-like syntax for `import`, and possibly also\n`package`.\n\nFor example, instead of:\n\n```carbon\nimport Math library \"Stats\";\nimport Algebra as A;\n```\n\nWe could do:\n\n```carbon\nimport(\"Math\", \"Stats\").Math;\nalias A = import(\"Algebra\").Algebra;\n```\n\nOr some related variation.\n\nAdvantages:\n\n-   Allows straightforward reuse of `alias` for language consistency.\n-   Easier to add more optional arguments, which we expect to need for\n    [interoperability](/docs/design/code_and_name_organization/README.md#imports-from-other-languages)\n    and\n    [URLs](/docs/design/code_and_name_organization/README.md#imports-from-urls).\n-   Avoids defining keywords for optional fields, such as `library`.\n    -   Interoperability and package management may add more fields long-term.\n\nDisadvantages:\n\n-   It's unusual for a function-like syntax to produce identifiers for name\n    lookup.\n    -   This could be addressed by _requiring_ alias, but that becomes verbose.\n    -   There's a desire to explicitly note the identifier being imported some\n        way, as with `.Math` and `.Algebra` above. However, this complicates the\n        resulting syntax.\n\nThe preference is for keywords.\n\n#### Inlining from implementation files\n\nAn implicit reason for keeping code in an `api` file is that it makes it\nstraightforward to inline code from there into callers.\n\nWe could explicitly encourage inlining from `impl` files as well, making the\nlocation of code unimportant during compilation. Alternately, we could add an\n`inline` file type which explicitly supports separation of inline code from the\n`api` file.\n\nAdvantages:\n\n-   Allows moving code out of the main API file for easier reading.\n\nDisadvantages:\n\n-   Requires compilation of `impl` files to determine what can be inlined from\n    the `api` file, leading to the transitive closure dependency problems which\n    `impl` files are intended to avoid.\n\nWe expect to only support inlining from `api` files in order to avoid confusion\nabout dependency problems.\n\n#### Library-private access controls\n\nWe currently have no special syntax for library-private APIs. However,\nnon-exported APIs are essentially library-private, and may be in the `api` file.\nIt's been suggested that we could either provide a special syntax or a new file\ntype, such as `shared_impl`, to support library-private APIs.\n\nAdvantages:\n\n-   Allows for better separation of library-private APIs.\n\nDisadvantages:\n\n-   Increases language complexity.\n-   Dependencies are still an issue for library-private APIs.\n    -   If used from the `api` file, the dependencies are still in the\n        transitive closure of client libraries, and any separation may confuse\n        users about the downsides of the extra dependencies.\n    -   If only used from `impl` files, then they could be in the `impl` file if\n        there's only one, or shared from a separate library.\n-   Generalized access controls may provide overlapping functionality.\n\nAt this point in time, we prefer not to provide specialized access controls for\nlibrary-private APIs.\n\n#### Managing API versus implementation in libraries\n\nAt present, we plan to have `api` versus `impl` as a file type, and also\n`.carbon` versus `.impl.carbon` as the file extension. We chose to use both\ntogether, rather than one or the other, because we expect some parties to\nstrongly want file content to be sufficient for compilation, while others will\nwant file extensions to be meaningful for the syntax split.\n\nInstead of the file type split, we could drift further and instead have APIs in\nany file in a library, using the same kind of\n[API markup](/docs/design/code_and_name_organization/README.md#exporting-entities-from-an-api-file).\n\nAdvantages:\n\n-   May help users who have issues with cyclical code references.\n-   Improves compiler inlining of implementations, because the compiler can\n    decide how much to actually put in the generated API.\n\nDisadvantages:\n\n-   While allowing users to spread a library across multiple files can be\n    considered an advantage, we see the single API file as a way to pressure\n    users towards smaller libraries, which we prefer.\n-   May be slower to compile because each file must be parsed once to determine\n    APIs.\n-   For users that want to see _only_ APIs in a file, they would need to use\n    tooling to generate the API file.\n    -   Auto-generated documentation may help solve this problem.\n\n#### Multiple API files\n\nThe proposal also presently suggests a single API file. Under an explicit API\nfile approach, we could still allow multiple API files.\n\nAdvantages:\n\n-   More flexibility when writing APIs; could otherwise end up with one gigantic\n    API file.\n\nDisadvantages:\n\n-   Encourages larger libraries by making it easier to provide large APIs.\n-   Removes some of the advantages of having an API file as a \"single place\" to\n    look, suggesting more towards the markup approach.\n-   Not clear if API files should be allowed to depend on each other, as they\n    were intended to help resolve cyclical dependency issues.\n\nWe particularly want to discourage large libraries, and so we're likely to\nretain the single API file limit.\n\n#### Name paths as library names\n\nWe're proposing strings for library names. We've discussed also using name paths\n(`My.Library`) and also restricting to single identifiers (`Library`).\n\nAdvantages:\n\n-   Shares the form between packages (identifiers) and namespaces (name paths).\n-   Enforces a constrained set of names for libraries for cross-package\n    consistency of naming.\n\nDisadvantages:\n\n-   Indicates that a library may be referred to in code, when only the package\n    and namespace are used for name paths of entities.\n-   The constrained set of names may also get in the way for some packages that\n    can make use of more flexibility in naming.\n\nWe've decided to use strings primarily because we want to draw the distinction\nthat a library is not something that's used when referring to an entity in code.\n\n### Imports\n\n#### Block imports\n\nRather than requiring an `import` keyword per line, we could support block\nimports, as can be found in languages like Go.\n\nIn other words, instead of:\n\n```carbon\nimport Math;\nimport Geometry;\n```\n\nWe could have:\n\n```carbon\nimports {\n  Math,\n  Geometry,\n}\n```\n\nAdvantages:\n\n-   Allows repeated imports with less typing.\n\nDisadvantages:\n\n-   Makes it harder to find files importing a package or library using tools\n    like `grep`.\n\nOne concern has been that a mix of `import` and `imports` syntax would be\nconfusing to users: we should only allow one.\n\nThis alternative has been declined because retyping `import` statements is\nlow-cost, and `grep` is useful.\n\n#### Block imports of libraries of a single package\n\nWe could allow block imports of libraries from the same package. For example:\n\n```carbon\nimport Containers libraries({\n  \"FlatHashMap\",\n  \"FlatHashSet\",\n})\n```\n\nThe result of this `api alias` allowing `Containers.HashSet()` to work\nregardless of whether `HashSet` is in `\"HashContainers\"` or `\"Internal\"` may be\nclearer if both `import Containers` statements were a combined\n`import Containers libraries({\"HashContainers\", \"Internal\"});`.\n\nThe advantages/disadvantages are similar to [block imports](#block-imports).\nAdditional advantages/disadvantages are:\n\nAdvantages:\n\n-   If we limit to one import per library, then any `alias` of the package\n    `Containers` is easier to understand as affecting all libraries.\n\nDisadvantages:\n\n-   If we allow both `library` and `libraries` syntax, it's two was of doing the\n    same thing.\n    -   Can be addressed by _always_ requiring `libraries`, removing `library`,\n        but that diverges from `package`'s `library` syntax.\n\nThis alternative has been declined for similar reasons to block imports; the\nadditional advantages/disadvantages don't substantially shift the cost-benefit\nargument.\n\n#### Broader imports, either all names or arbitrary code\n\nCarbon imports require specifying individual names to import. We could support\nbroader imports, for example by pulling in all names from a library. In C++, the\n`#include` preprocessor directive even supports inclusion of arbitrary code. For\nexample:\n\n```carbon\nimport Geometry library \"Shapes\" names *;\n\n// Triangle was imported as part of \"*\".\nfn Draw(var Triangle: x) { ... }\n```\n\nAdvantages:\n\n-   Reduces boilerplate code specifying individual names.\n\nDisadvantages:\n\n-   Loses out on parser benefits of knowing which identifiers are being\n    imported.\n-   Increases the risk of adding new features to APIs, as they may immediately\n    get imported by a user and conflict with a preexisting name, breaking code.\n-   As the number of imports increases, it can become difficult to tell which\n    import a particular symbol comes from, or how imports are being used.\n-   Arbitrary code inclusion can result in unexpected code execution, a way to\n    create obfuscated code and a potential security risk.\n\nWe particularly value the parser benefits of knowing which identifiers are being\nimported, and so we require individual names for imports.\n\n#### Direct name imports\n\nWe could allow direct imports of names from libraries. For example, under the\ncurrent setup we might see:\n\n```carbon\nimport Math library \"Stats\";\nalias Median = Stats.Median;\nalias Mean = Stats.Mean;\n```\n\nWe could simplify this syntax by augmenting `import`:\n\n```carbon\nimport Math library \"Stats\" name Median;\nimport Math library \"Stats\" name Mean;\n```\n\nOr more succinctly with block imports of names:\n\n```carbon\nimport Math library \"Stats\" names {\n  Median,\n  Mean,\n}\n```\n\nAdvantages:\n\n-   Avoids an additional `alias` step.\n\nDisadvantages:\n\n-   With a single name, this isn't a significant improvement in syntax.\n-   With multiple names, this runs into similar issues as\n    [block imports](#block-imports).\n\n#### Optional package names\n\nWe could allow a short syntax for imports from the current library. For example,\nthis code imports `Geometry.Shapes`:\n\n```carbon\npackage Geometry library \"Operations\" api;\n\nimport library \"Shapes\";\n```\n\nAdvantages:\n\n-   Reduces typing.\n\nDisadvantages:\n\n-   Makes it harder to find files importing a package or library using tools\n    like `grep`.\n-   Creates two syntaxes for importing libraries from the current package.\n    -   If we instead disallow `import Geometry library \"Shapes\"` from within\n        `Geometry`, then we end up with a different inconsistency.\n\nOverall, consistent with the decision to disallow\n[block imports](#block-imports), we are choosing to require the package name.\n\n### Namespaces\n\n#### File-level namespaces\n\nWe are providing entity-level namespaces. This is likely necessary to support\nmigrating C++ code, at a minimum. It's been discussed whether we should _also_\nsupport file-level namespaces.\n\nFor example, this is the current syntax for defining `Geometry.Shapes.Circle`:\n\n```carbon\npackage Geometry library \"Shapes\" api;\n\nnamespace Shapes;\nstruct Shapes.Circle;\n```\n\nThis is the proposed alternative syntax for defining `Geometry.Shapes.Circle`,\nand would put all entities in the file under the `Shapes` namespace:\n\n```carbon\npackage Geometry library \"Shapes\" namespace Shapes api;\n\nstruct Circle;\n```\n\nAdvantages:\n\n-   Reduces repetitive syntax in the file when every entity should be in the\n    same, child namespace.\n    -   Large libraries and packages are more likely to be self-referential, and\n        may pay a disproportionate ergonomics tax that others wouldn't see.\n    -   Although library authors could also avoid this repetitive syntax by\n        omitting the namespace, that may in turn lead to more name collisions\n        for large packages.\n    -   Note that syntax can already be reduced with a shorter namespace alias,\n        but the redundancy cannot be _eliminated_.\n-   Reduces the temptation of aliasing in order to reduce verbosity, wherein\n    it's generally agreed that aliasing creates inconsistent names which hinder\n    readability.\n    -   Users are known to alias long names, where \"long\" may be considered\n        anything over six characters.\n    -   This is a risk for any package that uses namespaces, as importers may\n        also need to address it.\n\nDisadvantages:\n\n-   Encourages longer namespace names, as they won't need to be retyped.\n-   Increases complexity of the `package` keyword.\n-   Creates two ways of defining namespaces, and reuses the `namespace` keyword\n    in multiple different ways.\n    -   We generally prefer to provide one canonical way of doing things.\n    -   Does not add functionality which cannot be achieved with entity-level\n        namespaces. However, the converse is not true: entity-level control\n        allows a single file to put entities into multiple namespaces.\n-   Creates a divergence between code as written by the library maintainer and\n    code as called.\n    -   Calling code would need to specify the namespace, even if aliased to a\n        shorter name. Library code gets to omit this, essentially getting a free\n        alias.\n\nWe are choosing not to provide this for now because we want to provide the\nminimum necessary support, and then see if it works out. It may be added later,\nbut it's easier to add features than to remove them.\n\n#### Scoped namespaces\n\nInstead of including additional namespace information per-name, we could have\nscoped namespaces, similar to C++. For example:\n\n```carbon\nnamespace absl {\n  namespace numbers_internal {\n    fn SafeStrto32Base(...) { ... }\n  }\n\n  fn SimpleAtoi(...) {\n    ...\n    return numbers_internal.SafeStrto32Base(...);\n    ...\n  }\n}\n```\n\nAdvantages:\n\n-   Makes it easy to write many things in the same namespace.\n\nDisadvantages:\n\n-   It's not clear which namespace an identifier is in without scanning to the\n    start of the file.\n-   It can be hard to find the end of a namespace. For examples addressing this,\n    end-of-namespace comments are called for by both the\n    [Google](https://google.github.io/styleguide/cppguide.html#Namespaces) and\n    [Boost](https://github.com/boostorg/geometry/wiki/Guidelines-for-Developers)\n    style guides.\n    -   Carbon may disallow the same-line-as-code comment style used for this.\n        Even if not, if we acknowledge it's a problem, we should address it\n        structurally for\n        [readability](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n    -   This is less of a problem for other scopes, such as functions, because\n        they can often be broken apart until they fit on a single screen.\n\nThere are other ways to address the con, such as adding syntax to indicate the\nend of a namespace, similar to block comments. For example:\n\n```carbon\n{ namespace absl\n  { namespace numbers_internal\n    fn SafeStrto32Base(...) { ... }\n  } namespace numbers_internal\n\n  fn SimpleAtoi(...) {\n    ...\n    return numbers_internal.SafeStrto32Base(...);\n    ...\n  }\n} namespace absl\n```\n\nWhile we could consider such alternative approaches, we believe the proposed\ncontextless namespace approach is better, as it reduces information that\ndevelopers will need to remember when reading/writing code.\n\n## Rationale\n\nThis proposal provides an organizational structure that seems both workable and\naligns well with Carbon's goals:\n\n-   Distinct and required top-level namespace -- \"package\"s from the proposal --\n    both matches software best practices for long-term evolution, and avoids\n    complex and user-confusing corner cases.\n-   Providing a fine-grained import structure as provided by the \"library\"\n    concept supports scalable build system implementations while ensuring\n    explicit dependencies.\n-   The structured namespace facilities provide a clear mechanism to migrate\n    existing hierarchical naming structures in C++ code.\n\n### Open questions\n\n#### Should we switch to a library-oriented structure that's package-agnostic?\n\n-   **Decision:** No.\n-   **Rationale:** While this would simplify the overall set of constructs\n    needed, removing the concept of a global namespace remained desirable and\n    would require re-introducing much of the complexity around top-level\n    namespaces. Overall, the simplification trade-off didn't seem significantly\n    better.\n\n#### Should there be a tight association between file paths and packages/libraries?\n\n-   **Decision:** Yes, for the API files in libraries. Specifically, the library\n    name should still be written in the source, but it should be checked to\n    match -- after some platform-specific translation -- against the path.\n-   **Note:** Sufficient restrictions to result in a portable and simple\n    translation on different filesystems should be imposed, but the Core team\n    was happy for these restrictions to be developed as part of implementation\n    work.\n-   **Rationale:** This will improve usability and readability for users by\n    making it obvious how to find the files that are being imported. Similarly,\n    this will improve tooling by increasing the ease with which tools can find\n    imported APIs.\n"
  },
  {
    "path": "proposals/p0113.md",
    "content": "# Add a C++ style guide\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/113)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Different variations on the baseline of the Google C++ style guide](#different-variations-on-the-baseline-of-the-google-c-style-guide)\n        -   [Use exceptions](#use-exceptions)\n        -   [Format functions with one-per-line arguments and parameters](#format-functions-with-one-per-line-arguments-and-parameters)\n        -   [Place `*` and `&` with the variable in pointer declarations](#place--and--with-the-variable-in-pointer-declarations)\n        -   [Place `const` after the type](#place-const-after-the-type)\n    -   [Use the LLVM coding standards](#use-the-llvm-coding-standards)\n-   [Rationale](#rationale-1)\n\n<!-- tocstop -->\n\n## Problem\n\nWhen writing C++ code for Carbon, we want to keep all of our code consistent,\neasy to learn, and help avoid spending undue code review time arguing about the\nsame core style and idiomatic issues.\n\n## Background\n\n-   [C++ Coding Standards](https://dl.acm.org/doi/book/10.5555/1036281)\n-   [C++ Core Guidelines](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)\n-   [Chromium C++ style guide](https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md)\n-   [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)\n-   [Joint Strike Fighter Air Vehicle C++ Coding Standards](https://stroustrup.com/JSF-AV-rules.pdf)\n-   [LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html)\n-   [Mozilla C++ Style Guide](https://firefox-source-docs.mozilla.org/code-quality/coding-style/coding_style_cpp.html)\n-   [Programming style](https://en.wikipedia.org/wiki/Programming_style)\n-   [The Elements of Programming Style](https://dl.acm.org/doi/book/10.5555/578130)\n-   [WebKit Code Style Guidelines](https://webkit.org/code-style-guidelines/)\n\n## Proposal\n\nI propose to use the Google C++ style guide as a baseline, and then make\nminimal, focused additions and adjustments to it to suit the needs of Carbon.\n\n## Details\n\nThe Google C++ style guide is widely used even outside of Google. Both Mozilla\nand Chromium use it as their base style guide. It is both comprehensive and\nspecific, providing a strong foundation with wide coverage.\n\nHowever, there are a small number of places that seem worth adjusting. I propose\nto use the Google style guide as a baseline and then have a minimal, and focused\nlist of changes and clarifications.\n\nThe most expensive cases are those where we _actively diverge_ from this\nbaseline. Doing this outside of mechanical formatting issues would require\ncareful thought and justification that seems likely to have a higher cost than\nthe benefit. I propose focusing only on specific places where there is a direct\n_benefit_ to Carbon by diverging. The only place where I suggest this is the\nnaming convention. The convention suggested by Google's style guide is more\ncomplex than necessary, in part due to its desire to not invalidate a large\nhistorical codebase. That is not a concern for Carbon, and there is a specific\nadvantage: using and learning how the proposed naming convention for Carbon\nitself works in practice. Thus, the [proposal](/docs/project/cpp_style_guide.md)\nis to replace the naming conventions suggested by the Google style guide with\nthose suggested for Carbon.\n\nThe remaining suggested modifications simply consist of selecting one of several\nallowed options in order to increase consistency and modernness. Many of the\ncases allowing multiple options only exist to retain consistency with an\nexisting code base that isn't a factor for Carbon. I suggest we take advantage\nof this to have a more consistent and modern style. See the proposed\n[section](/docs/project/cpp_style_guide.md#carbon-local-guidance) for details.\n\n### Rationale\n\nSome aspects of this proposal warrant specific rationale.\n\n## Alternatives considered\n\n### Different variations on the baseline of the Google C++ style guide\n\n#### Use exceptions\n\nAdvantages:\n\n-   Better aligned with standard C++, Boost, and some other C++ communities.\n\nDisadvantages:\n\n-   Significant performance problems, especially of data structures that need to\n    provide strong exception safety guarantees.\n-   LLVM does not use exceptions and is not exception safe.\n\n#### Format functions with one-per-line arguments and parameters\n\nNote: this is likely a bikeshed that we should not invest significant time\ndebating.\n\nAdvantages:\n\n-   Simpler for editors and authors of code to get correct.\n-   Minimizes diffs during refactorings.\n-   Regular horizontal rhythm (independent of name lengths) and no hard-to-spot\n    additional parameters on the right, which for some subset of readers\n    improves readability.\n\nDisadvantages:\n\n-   A non-trivial change from Google's style guide.\n-   Readability problems caused by bin packing of function parameters and\n    arguments are typically better solved by factoring (either into variables or\n    option structs) than a formatting change. We should not have interfaces that\n    are hard to read due to their number of parameters.\n-   Increases vertical space of code, which for some subset of readers is\n    expensive, and for them may outweigh any benefit of the regular horizontal\n    rhythm.\n\n#### Place `*` and `&` with the variable in pointer declarations\n\nNote: this is likely a bikeshed that we should not invest significant time\ndebating.\n\nAdvantages:\n\n-   This spacing matches the language grammar more closely than the alternative\n    spacing.\n-   Declaration syntax parallels the usage syntax. Given `int *p;`, the type of\n    `*p` is `int`.\n-   Enables coherent declaration of multiple variables in a single declaration.\n    -   However, even with this formatting these declarations are hard to read\n        and should not be used.\n\nDisadvantages:\n\n-   Many people think of the declaration structure as `<type> <identifier>;` and\n    the `*` is part of the type.\n    -   However, that intuitive understanding doesn't generalize to a few\n        different constructs in C++. For example: arrays and function pointers.\n\n#### Place `const` after the type\n\nNote: this is likely a bikeshed that we should not invest significant time\ndebating.\n\nAdvantages:\n\n-   Makes multiple layers of `const` alternating with pointers or references\n    more obviously readable.\n    -   However, using type aliases to avoid multiple layers of `const` often\n        provides even better readability.\n\nDisadvantages:\n\n-   For declarations without any pointer in the type, `const <type> <id>;` is\n    much more conventional.\n    -   And most declarations are of this form.\n\n### Use the LLVM coding standards\n\nCarbon will end up heavily using LLVM and Clang for its reference\nimplementation. This will both involve interfacing with those APIs and heavily\nusing libraries from those projects. We could adopt the LLVM coding standards to\ngain consistency with those APIs.\n\nAdvantages:\n\n-   Consistent coding style between Carbon code and any LLVM or Clang APIs used.\n-   If it eventually becomes desirable to contribute Carbon's reference\n    implementation to the LLVM project, it would avoid updating the code to\n    adhere to the relevant coding standards.\n\nDisadvantages:\n\n-   The LLVM coding standards are neither precise nor specific on a number of\n    points. They leave a large number of issues to the judgement of code\n    reviewers to stay consistent with the LLVM codebase. This isn't practical\n    for Carbon nor is it an efficient policy.\n    -   LLVM and Clang don't _consistently_ follow the standards either, making\n        it impossible to have complete consistency with them.\n-   Contributing the reference implementation to LLVM seems unlikely and\n    necessarily at least a year away which minimizes any concerns around style\n    matching.\n-   LLVM has not yet adopted C++17 due to existing users who still need C++14.\n    However, Carbon has no such need to constrain its version of C++ and can\n    effectively adopt and use more modern C++ versions.\n\n## Rationale\n\nA common, established style guide will allow us to focus on the more important\naspects of coding and code review. Once we're familiar with the rules, their\nconsistent application will result in a more readable codebase, and rules that\ncan largely be automated by clang-format will result in a more efficient\ndevelopment process.\n\nThis particular ruleset attempts to align with our expected lexical rules for\nthe Carbon language (for example, comment syntax and capitalization rules),\nwhich will also mean that we can use a largely consistent style between the\naspects of the toolchain implemented in C++ and the aspects implemented in\nCarbon.\n"
  },
  {
    "path": "proposals/p0120.md",
    "content": "# Add idiomatic code performance and developer-facing docs to goals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/120)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Justification](#justification)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use a principle to address performance of idiomatic code](#use-a-principle-to-address-performance-of-idiomatic-code)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Problem\n\n[Issue #106](https://github.com/carbon-language/carbon-lang/issues/106) raises a\nfew small issues with the goals doc as approved. Some are small, but in\nparticular I'll emphasize the question:\n\n> Do we want to say anything about \"reasonably fast by default\" or \"favors\n> constructs that can be compiled to efficient code\" or something like that?\n\nI think this is something that we clearly want for performance, and should be\nlaid out.\n\nAdditionally, while considering justification for changes in\n[PR 80](https://github.com/carbon-language/carbon-lang/pull/80), I noted there\nis no explicit goal to provide developer-facing documentation. I believe this is\nan intended part of the community goals, and could be inferred from current\necosystem text, but may be better if explicit.\n\n## Proposal\n\nAdd paragraphs to address performance of idiomatic code and developer-facing\ndocumentation, as well as making other small fixes.\n\n## Justification\n\nPerformance of idiomatic code:\n\nUnder \"Performance-critical software\", we establish that it should be possible\nto write high-performance code with Carbon. However, if taken strictly, we could\nbe saying something like \"it's okay if idiomatic code is predictably slow, as\nlong as developers have tools to 'open up the hood'.\" That is not the intent,\nand so addressing the case of routine code performance offers the reassurance\nthat Carbon will prioritize performance consistently, regardless of whether\nperformance tuning is done.\n\nDeveloper-facing documentation:\n\n\"Language tools and ecosystem\" addresses the specification and tooling\nexplicitly. However, developer-facing documentation is also part of the\necosystem, and part of supporting ramp-up training by new Carbon developers.\nSuch documentation should be an explicit project priority.\n\nOther changes are incremental improvements to the goal text, and mainly\npresented in this change for consistency of review.\n\n## Alternatives considered\n\n### Use a principle to address performance of idiomatic code\n\nA principle is another way of addressing non-obvious conclusions based on goals.\nHowever, performance of idiomatic code seems quick to state, and not worth\nsplitting off to a separate doc. I believe the cost-benefit favors keeping it in\nthe goals doc.\n\n## Rationale\n\nThis addresses a number of rough edges and small missing pieces in the original\nproposal, providing useful clarification. This follow up is expected as part of\nthe launch and iterate process we use to keep our velocity up.\n\nUser-facing documentation and speed-by-default should be first-order priorities\nfor Carbon.\n"
  },
  {
    "path": "proposals/p0140.md",
    "content": "# Create initial rough framework for specification\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/140)\n\n## Table of contents\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Conventions](#conventions)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Maintain the specification in a different language.](#maintain-the-specification-in-a-different-language)\n\n<!-- tocstop -->\n\n## Problem\n\nWe need a rough layout for our specification so that we can start adding details\nto it once they're decided.\n\n## Proposal\n\nSplit the specification into a language and a library section. In the language\nsection, use one file per broad area of functionality. Divide the language up\nbased on the intended layering of the language design.\n\nFor now, maintain the specification sources in Markdown.\n\n## Details\n\nProposed top-level structure of the `spec/` directory as of this pull request:\n\n-   `README.md` Introduction to the specification\n-   `lang`\n    -   `README.md` Language specification overview and basics\n    -   `execution.md` Execution semantics\n    -   `lex.md` Lexical analysis\n    -   `libs.md` Libraries and packages\n    -   `names.md` Names and name binding / lookup\n    -   `parsing.md` Parsing\n    -   `semantics.md` Semantic analysis\n-   `lib`\n    -   `README.md` Library specification overview and basics\n\nThis is only a starting point; the structure should be expected to change and\ngrow as the specification is filled out. Most of the proposed files are empty or\nnearly-empty placeholders.\n\n### Conventions\n\nAll paragraphs within the specification are numbered so that they can be\nreferenced more easily.\n\nDefined terms are introduced in italics.\n\nHyperlinks between sections of the specification are used liberally.\n\n## Alternatives considered\n\n### Maintain the specification in a different language.\n\nAdvantages:\n\n-   An alternative language may provide better support for custom typesetting,\n    representing grammars, linking to definitions, and so on.\n\nDisadvantages:\n\n-   Using a different language would add complexity and inconsistency to our\n    documentation.\n-   There is unlikely to be any existing documentation language that is\n    well-suited to our needs without significant customization.\n-   Conversion from a more sophisticated language is likely to be more complex\n    than converting from Markdown.\n\nConversion of Markdown to another language at a later point (either manually or\nusing a tool like Sphinx) is expected to remain a relatively low-cost option,\ndue to the relative simplicity of Markdown-formatted documents.\n"
  },
  {
    "path": "proposals/p0142.md",
    "content": "# Unicode source files\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/142)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Character encoding](#character-encoding)\n    -   [Source files](#source-files)\n    -   [Normalization](#normalization)\n    -   [Characters in identifiers and whitespace](#characters-in-identifiers-and-whitespace)\n        -   [Homoglyphs](#homoglyphs)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Character encoding](#character-encoding-1)\n    -   [Byte order marks](#byte-order-marks)\n    -   [Normalization forms](#normalization-forms)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Problem\n\nPortable use and maintenance of Carbon source files requires a common\nunderstanding of how they are encoded on disk. Further, the decision as to what\ncharacters are valid in names and what constitutes whitespace are a complex area\nin which we do not expect to have local expertise.\n\n## Background\n\n[Unicode](https://www.unicode.org/versions/latest/) is a universal character\nencoding, maintained by the\n[Unicode Consortium](https://home.unicode.org/basic-info/overview/). It is the\ncanonical encoding used for textual information interchange across all modern\ntechnology.\n\nThe [Unicode Standard Annex 31](https://www.unicode.org/reports/tr31/), \"Unicode\nIdentifier and Pattern Syntax\", provides recommendations for the use of Unicode\nin the definitions of general-purpose identifiers.\n\n## Proposal\n\nCarbon programs are represented as a sequence of Unicode code points. Carbon\nsource files are encoded in UTF-8.\n\nCarbon will follow lexical conventions for identifiers and whitespace based on\nUnicode Annex 31.\n\n## Details\n\n### Character encoding\n\nBefore being divided into tokens, a program starts as a sequence of Unicode code\npoints -- integer values between 0 and 10FFFF<sub>16</sub> -- whose meaning as\ncharacters or non-characters is defined by the Unicode standard.\n\nCarbon is based on Unicode 13.0, which is currently the latest version of the\nUnicode standard. Newer versions should be considered for adoption as they are\nreleased.\n\n### Source files\n\nProgram text can come from a variety of sources, such as an interactive\nprogramming environment (a so-called \"Read-Evaluate-Print-Loop\" or REPL), a\ndatabase, a memory buffer of an IDE, or a command-line argument.\n\nThe canonical representation for Carbon programs is in files stored as a\nsequence of bytes in a file system on disk, and such files are expected to be\nencoded in UTF-8. Such files may begin with an optional UTF-8 BOM, that is, the\nbyte sequence EF<sub>16</sub>,BB<sub>16</sub>,BF<sub>16</sub>. This prefix, if\npresent, is ignored.\n\nRegardless of how program text is concretely stored, the first step in\nprocessing any such text is to convert it to a sequence of Unicode code points\n-- although such conversion may be purely notional. The result of this\nconversion is a Carbon _source file_. Depending on the needs of the language, we\nmay require each such source file to have an associated filename, even if the\nsource file does not originate in anything resembling a file system.\n\n### Normalization\n\nBackground:\n\n-   [wikipedia article on Unicode normal forms](https://en.wikipedia.org/wiki/Unicode_equivalence#Normal_forms)\n-   [Unicode Standard Annex #15: Unicode Normalization Forms](https://www.unicode.org/reports/tr15/tr15-50.html)\n\nCarbon source files, including comments and string literals, are required to be\nin Unicode Normalization Form C (\"NFC\"). The Carbon source formatting tool will\nconvert source files to NFC as necessary to satisfy this constraint.\n\nThe choice to require NFC is really four choices:\n\n1. Equivalence classes: we use a canonical normalization form rather than a\n   compatibility normalization form or no normalization form at all.\n\n    - If we use no normalization, invisibly-different ways of representing the\n      same glyph, such as with pre-combined diacritics versus with diacritics\n      expressed as separate combining characters, or with combining characters\n      in a different order, would be considered different characters.\n    - If we use a canonical normalization form, all ways of encoding diacritics\n      are considered to form the same character, but ligatures such as `ﬃ` are\n      considered distinct from the character sequence that they decompose into.\n    - If we use a compatibility normalization form, ligatures are considered\n      equivalent to the character sequence that they decompose into.\n\n    For a fixed-width font, a canonical normalization form is most likely to\n    consider characters to be the same if they look the same. Unicode annexes\n    [UAX#15](https://www.unicode.org/reports/tr15/tr15-18.html#Programming%20Language%20Identifiers)\n    and\n    [UAX#31](https://www.unicode.org/reports/tr31/tr31-33.html#normalization_and_case)\n    both recommend the use of Normalization Form C for case-sensitive\n    identifiers in programming languages.\n\n    See also the discussion of [homoglyphs](#homoglyphs) below.\n\n2. Composition: we use a composed normalization form rather than a decomposed\n   normalization form. For example, `ō` is encoded as U+014D (LATIN SMALL LETTER\n   O WITH MACRON) in a composed form and as U+006F (LATIN SMALL LETTER O),\n   U+0304 (COMBINING MACRON) in a decomposed form. The composed form results in\n   smaller representations whenever the two differ, but the decomposed form is a\n   little easier for algorithmic processing (for example, typo correction and\n   homoglyph detection).\n\n3. We require source files to be in our chosen form, rather than converting to\n   that form as necessary.\n\n4. We require that the entire contents of the file be normalized, rather than\n   restricting our attention to only identifiers, or only identifiers and string\n   literals.\n\n### Characters in identifiers and whitespace\n\nWe will largely follow [Unicode Annex 31](https://www.unicode.org/reports/tr31/)\nin our selection of identifier and whitespace characters. This Annex does not\nprovide specific rules on lexical syntax, instead providing a framework that\npermits a selection of choices of concrete rules.\n\nThe framework provided by Annex 31 includes suggested sets of characters that\nmay appear in identifier, including uppercase and lowercase ASCII letters, along\nwith reasonable extensions to many non-ASCII letters, with some characters\nrestricted to not appear as the first character. For example, this list includes\nU+30EA (KATAKANA LETTER RI), but not U+2603 (SNOWMAN), both of which are\npermitted in identifiers in C++20. Similarly, it indicates which characters\nshould be classified as whitespace, including all the ASCII whitespace\ncharacters plus some non-ASCII whitespace characters. It also supports\nlanguage-specific \"profiles\" to alter these baseline character sets for the\nneeds of a particular language -- for example, to permit underscores in\nidentifiers, or to include non-breaking spaces as whitespace characters.\n\nThis proposal does not specify concrete choices for lexical rules, nor that we\nwill not deviate from conformance to Annex 31 in any concrete area. We may find\ncases where we wish to take a different direction than that of the Annex.\nHowever, we should use Annex 31 as a basis for our decisions, and should expect\nstrong justification for deviations from it.\n\nNote that this aligns with the current direction for C++, as described in WG21\npaper [P1949R6](http://wg21.link/P1949R6).\n\n#### Homoglyphs\n\nThe sets of identifier characters suggested by Annex 31's `ID_Start` /\n`XID_Start` / `ID_Continue` / `XID_Continue` characters include many pairs of\nhomoglyphs and near-homoglyphs -- characters that would be interpreted\ndifferently but may render identically or very similarly. This problem would\nalso be present if we restricted the character set to ASCII -- for example,\n`kBa11Offset` and `kBall0ffset` may be very hard to distinguish in some fonts --\nbut there are many more ways to introduce such problems with the broader\nidentifier character set suggested by Annex 31.\n\nOne way to handle this problem would be by adding a restriction to name lookup:\nif a lookup for a name is performed in a scope and that lookup would have found\nnothing, but there is a confusable identifier, as defined by\n[UAX#39](http://www.unicode.org/reports/tr39/#Confusable_Detection), in the same\nscope, the program is ill-formed. However, this idea is only provided as weak\nguidance to future proposals and to demonstrate that UAX#31's approach is\ncompatible with at least one possible solution for the homoglyph problem. The\nconcrete rules for handling homoglyphs are considered out of scope for this\nproposal.\n\n## Alternatives considered\n\nThere are a number of different design choices we could make, as divergences\nfrom the above proposal. Those choices, along with the arguments that led to\nchoosing the proposed design rather than each alternative, are presented below.\n\n### Character encoding\n\nWe could restrict programs to ASCII.\n\nPro:\n\n-   Reduced implementation complexity.\n-   Avoids all problems relating to normalization, homoglyphs, text\n    directionality, and so on.\n-   We have no intention of using non-ASCII characters in the language syntax or\n    in any library name.\n-   Provides assurance that all names in libraries can reliably be typed by all\n    developers -- we already require that keywords, and thus all ASCII letters,\n    can be typed.\n\nCon:\n\n-   An overarching goal of the Carbon project is to provide a language that is\n    inclusive and welcoming. A language that does not permit names and comments\n    in programs to be expressed in the developer's native language will not meet\n    that goal for at least some of our developers.\n-   Quoted strings will be substantially less readable if non-ASCII printable\n    characters are required to be written as escape sequences.\n\n### Byte order marks\n\nWe could disallow byte order marks.\n\nPro:\n\n-   Marginal implementation simplicity.\n\nCon:\n\n-   Several major editors, particularly on the Windows platform, insert UTF-8\n    BOMs and use them to identify file encoding.\n\n### Normalization forms\n\nWe could require a different normalization form.\n\nPro:\n\n-   Some environments might more naturally produce a different normalization\n    form.\n-   Normalization Form D is more uniform, in that characters are always\n    maximally decomposed into combining characters; in NFC, characters may or\n    may not be decomposed depending on whether a composed form is available.\n    -   NFD may be more suitable for certain uses such as typo correction,\n        homoglyph detection, or code completion.\n\nCon:\n\n-   The C++ standard and community is moving towards using NFC:\n\n    -   WG21 is in the process of adopting a NFC requirement for C++\n        identifiers.\n    -   GCC warns on C++ identifiers that aren't in NFC.\n\n    As a consequence, we should expect that the tooling and development\n    environments that C++ developers are using will provide good support for\n    authoring NFC-encoded source files.\n\n-   The W3C recommends using NFC for all content, so code samples distributed on\n    webpages may be canonicalized into NFC by some web authoring tools.\n\n-   NFC produces smaller encodings than NFD in all cases where they differ.\n\nWe could require no normalization form and compare identifiers by code point\nsequence.\n\nPro:\n\n-   This is the rule in use in C++20 and before.\n\nCon:\n\n-   This is not the rule planned for the near future of C++.\n-   Different representations of the same character may result in different\n    identifiers, in a way that is likely to be invisible in most programming\n    environments.\n\nWe could require no normalization form, and normalize the source code ourselves:\n\nPro:\n\n-   We would treat source text identically regardless of the normalization form.\n-   Developers would not be responsible for ensuring that their editing\n    environment produces and preserves the proper normalization form.\n\nCon:\n\n-   There is substantially more implementation cost involved in normalizing\n    identifiers than in detecting whether they are in normal form. While this\n    proposal would require the implementation complexity of converting into NFC\n    in the formatting tool, it would not require the conversion cost to be paid\n    during compilation.\n\n    A high-quality implementation may choose to accept this cost anyway, in\n    order to better recover from errors. Moreover, it is possible to\n    [detect NFC on a fast path](http://unicode.org/reports/tr15/#NFC_QC_Optimization)\n    and do the conversion only when necessary. However, if non-canonical source\n    is formally valid, there are more stringent performance constraints on such\n    conversion than if it is only done for error recovery.\n\n-   Tools such as `grep` do not perform normalization themselves, and so would\n    be unreliable when applied to a codebase with inconsistent normalization.\n-   GCC already diagnoses identifiers that are not in NFC, and WG21 is in the\n    process of adopting an\n    [NFC requirement for C++ identifiers](http://wg21.link/P1949R6), so\n    development environments should be expected to increasingly accommodate\n    production of text in NFC.\n-   The byte representation of a source file may be unstable if different\n    editing environments make different normalization choices, creating problems\n    for revision control systems, patch files, and the like.\n-   Normalizing the contents of string literals, rather than using their\n    contents unaltered, will introduce a risk of user surprise.\n\nWe could require only identifiers, or only identifiers and comments, to be\nnormalized, rather than the entire input file.\n\nPro:\n\n-   This would provide more freedom in comments to use arbitrary text.\n-   String literals could contain intentionally non-normalized text in order to\n    represent non-normalized strings.\n\nCon:\n\n-   Within string literals, this would result in invisible semantic differences:\n    strings that render identically can have different meanings.\n-   The semantics of the program could vary if its sources are normalized, which\n    an editing environment might do invisibly and automatically.\n-   If an editing environment were to automatically normalize text, it would\n    introduce spurious diffs into changes.\n-   We would need to be careful to ensure that no string or comment delimiter\n    ends with a code point sequence that is a prefix of a decomposition of\n    another code point, otherwise different normalizations of the same source\n    file could tokenize differently.\n\n## Rationale\n\nWe need to specify the source file encoding in order to move on to higher-level\nlexical issues, and the proposal generally gives sound rationales for the\nspecific choices it makes. UTF-8 and Unicode Annex 31 are non-controversial\nchoices for a new language in 2020. The proposal provides a good rationale for\nrequiring NFC.\n\nWe support treating homoglyphs and confusability as out of scope. We favor of\naccepting of a wide range of scripts to start, in order to be welcoming to as\nwide a community as possible, assuming that underhanded code concerns can be\nadequately addressed outside of the compiler proper.\n"
  },
  {
    "path": "proposals/p0143.md",
    "content": "# Numeric literals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/143)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Integer literals](#integer-literals)\n    -   [Real number literals](#real-number-literals)\n        -   [Ties](#ties)\n    -   [Digit separators](#digit-separators)\n        -   [Open question: digit separator placement](#open-question-digit-separator-placement)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Integer bases](#integer-bases)\n        -   [Octal literals](#octal-literals)\n        -   [Decimal literals](#decimal-literals)\n        -   [Case sensitivity](#case-sensitivity)\n    -   [Real number syntax](#real-number-syntax)\n    -   [Digit separator syntax](#digit-separator-syntax)\n-   [Rationale](#rationale)\n    -   [Painter rationale](#painter-rationale)\n    -   [Open questions](#open-questions)\n\n<!-- tocstop -->\n\n## Problem\n\nThis proposal specifies lexical rules for numeric constants in Carbon.\n\n## Background\n\nWe wish to cover literals for two categories of types:\n\n-   Integer types, that can represent some (typically contiguous) subset of the\n    integers, ℤ.\n-   Real number types, that can represent some\n    [discrete](https://en.wikipedia.org/wiki/Isolated_point) subset of the real\n    numbers, ℝ. (Typically only rational numbers can be represented, but that\n    doesn't matter for our purposes.)\n\nReal number types may include additional values (infinities and NaN values). We\ndo not provide a notation to express such values.\n\nIn C++, the following syntaxes are used:\n\n-   Integer literals\n    -   `12345` (decimal)\n    -   `0x1FE` (hexadecimal)\n    -   `0123` (octal)\n    -   `0b1010` (binary)\n-   Real number literals\n    -   Decimal\n        -   `123.`\n        -   `.123`\n        -   `123.456`\n        -   `123.e456` (= 123 \\* 10<sup>456</sup>)\n        -   `.123e456`\n        -   `123.456e789`\n        -   `123e456` (no decimal point)\n        -   Any of the above with a `+` or `-` after `e`.\n    -   Hexadecimal\n        -   `0x123.p456` (= 123<sub>16</sub> \\* 2<sup>456</sup>)\n        -   `0x.123p456`\n        -   `0x123.456p789`\n        -   `0x123p456` (no hexadecimal point)\n        -   Any of the above with a `+` or `-` after `p`.\n-   Digit separators (`'`) may appear between any two digits\n-   An optional suffix defines the type\n    -   `U` (`unsigned`) and `L` (`long`) or `LL` (`long long`) for integers\n        (order-independent, but `LUL` disallowed)\n    -   `F` (`float`) or `L` (`long double`) for real numbers\n-   User-defined literals may have custom suffixes, starting with `_` for\n    non-standard-library literals.\n\nC++ numeric literals are case-insensitive, except in the suffix of a\nuser-defined literal. Negative numbers are formed by applying a unary `-`\noperator to a non-negative literal.\n\nThe type of a literal in C++ depends primarily on its syntax and its suffix.\nHowever, for integer literals, the type also depends on the value; the language\nrules attempt to pick a type large enough to fit the value. An `unsigned` type\nis always used if a `U` suffix is present, is never used for a decimal literal\nwithout a `U` suffix, and otherwise may or may not be used depending on whether\nthe value happens to fit into an unsigned type but not into a signed type of the\nsame width.\n\nOther languages use somewhat different rules, but the broad lexical structure\nabove -- an optional prefix for the base, a value, an optional exponent, and an\noptional suffix -- is common across a large number of languages.\n\n## Proposal\n\nWe allow these syntaxes:\n\n-   Integer literals\n    -   `12345` (decimal)\n    -   `0x1FE` (hexadecimal)\n    -   `0b1010` (binary)\n-   Real number literals\n    -   `123.456` (digits on both sides of the `.`)\n    -   `123.456e789` (optional `+` or `-` after the `e`)\n    -   `0x1.2p123` (optional `+` or `-` after the `p`)\n-   Digit separators (`_`) may be used, but only in conventional locations\n\nNote that real number literals always contain a `.` with digits on both sides,\nand integer literals never contain a `.`.\n\nLiterals are case-sensitive.\n\nNo support is proposed for literals with type suffixes, but without prejudice:\nthis proposal proposes neither the inclusion nor the absence of such literals.\n\n## Details\n\n### Integer literals\n\nDecimal integers are written as a non-zero decimal digit followed by zero or\nmore additional decimal digits, or as a single `0`.\n\nIntegers in other bases are written as a `0` followed by a base specifier\ncharacter, followed by a sequence of digits in the corresponding base. The\navailable base specifiers and corresponding bases are:\n\n| Base specifier | Base | Digits                   |\n| -------------- | ---- | ------------------------ |\n| `b`            | 2    | `0` and `1`              |\n| `x`            | 16   | `0` ... `9`, `A` ... `F` |\n\nThe above table is case-sensitive. For example, `0b1` and `0x1A` are valid, and\n`0B1`, `0X1A`, and `0x1a` are invalid.\n\nA zero at the start of a literal can never be followed by another digit: either\nthe literal is `0`, the `0` begins a base specifier, or the next character is a\ndecimal point (see below).\n\n### Real number literals\n\nReal numbers are written as a decimal or hexadecimal integer followed by a\nperiod (`.`) followed by a sequence of one or more decimal or hexadecimal\ndigits, respectively. A digit is required on each side of the period. `0.` and\n`.3` are both invalid.\n\nA real number can be followed by an exponent character, an optional `+` or `-`\n(defaulting to `+` if absent), and a character sequence matching the grammar of\na decimal integer with some value _N_. For a decimal real number, the exponent\ncharacter is `e`, and the effect is to multiply the given value by\n10<sup>&plusmn;_N_</sup>. For a hexadecimal real number, the exponent character\nis `p`, and the effect is to multiply the given value by\n2<sup>&plusmn;_N_</sup>. The exponent suffix is optional for both decimal and\nhexadecimal real numbers.\n\nNote that a decimal integer followed by `e` is not a real number literal. For\nexample, `3e10` is not a valid literal.\n\nWhen a real number literal is interpreted as a value of a real number type, its\nvalue is the representable real number closest to the value of the literal. In\nthe case of a [tie](#ties), the conversion to the real number type is invalid.\n\nThe decimal real number syntax allows for any decimal fraction to be expressed\n-- that is, any number of the form _a_ x 10<sup>-_b_</sup>, where _a_ is an\ninteger and _b_ is a non-negative integer. Because the decimal fractions are\ndense in the reals and the set of values of the real number type is assumed to\nbe discrete, every value of the real number type can be expressed as a real\nnumber literal. However, for certain applications, directly expressing the\nintended real number representation may be more convenient than producing a\ndecimal equivalent that is known to convert to the intended value. Hexadecimal\nreal number literals are provided in order to permit values of binary floating\nor fixed point real number types to be expressed directly.\n\n#### Ties\n\nAs described above, a real number literal that lies exactly between two\nrepresentable values for its target type is invalid. Such ties are extremely\nunlikely to occur by accident: for example, when interpreting a literal as\n`Float64`, `1.` would need to be followed by exactly 53 decimal digits (followed\nby zero or more `0`s) to land exactly half-way between two representable values,\nand the probability of `1.` followed by a random 53-digit sequence resulting in\nsuch a tie is one in 5<sup>53</sup>, or about\n0.000000000000000000000000000000000009%. For `Float32`, it's about\n0.000000000000001%, and even for a typical `Float16` implementation with 10\nfractional bits, it's around 0.00001%.\n\nTies are much easier to express as hexadecimal floating-point literals: for\nexample, `0x1.0000_0000_0000_08p+0` is exactly half way between `1.0` and the\nsmallest `Float64` value greater than `1.0`, which is `0x1.0000_0000_0000_1p+0`.\n\nWhether written in decimal or hexadecimal, a tie provides very strong evidence\nthat the developer intended to express a precise floating-point value, and\nprovided one bit too much precision (or one bit too little, depending on whether\nthey expected some rounding to occur), so rejecting the literal seems like a\nbetter option than accepting it and making an arbitrary choice between the two\npossible values.\n\n### Digit separators\n\nIf digit separators (`_`) are included in literals, they must meet the\nrespective condition:\n\n-   For decimal integers, the digit separators shall occur every three digits\n    starting from the right. For example, `2_147_483_648`.\n-   For hexadecimal integers, the digit separators shall occur every four digits\n    starting from the right. For example, `0x7FFF_FFFF`.\n-   For real number literals, digit separators can appear in the decimal and\n    hexadecimal integer portions (prior to the period and after the optional `e`\n    or mandatory `p`) as described in the previous bullets. For example,\n    `2_147.483648e12_345` or `0x1_00CA.FEF00Dp+24`\n-   For binary literals, digit separators can appear between any two digits. For\n    example, `0b1_000_101_11`.\n\n#### Open question: digit separator placement\n\n**2020-09-15: core team meeting selected Alternative 0**\n\nAs an alternative to the rule proposed above, we could consider different\nrestrictions on where digit separators can appear:\n\n**Alternative 0:** as presented above.\n\n**Alternative 1:** allow any digit groupings (for example, `123_4567_89`).\n\nPro:\n\n-   Simpler, more flexible rule, that may allow some groupings that are\n    conventional in a specific domain. For example, `var Date: d = 01_12_1983;`,\n    or `var Int64: time_in_microseconds = 123456_000000;`.\n-   Culturally agnostic. For example, the Indian convention for digit separators\n    would group the last three digits, and then every two digits before that\n    (1,23,45,678 could be written `1_23_45_678`).\n\nCon:\n\n-   Less self-checking that numeric literals are interpreted the way that the\n    author intends.\n\n**Alternative 2:** as above, but additionally require binary digits to be\ngrouped in 4s.\n\nPro:\n\n-   More enforcement that digit grouping is conventional.\n\nCon:\n\n-   No clear, established rule for how to group binary digits. In some cases, 8\n    digit groups may be more conventional.\n-   When used to express literals involving bit-fields, arbitrary grouping may\n    be desirable. For example:\n\n    ```carbon\n    var Float32: flt_max =\n      BitCast(Float32, 0b0_11111110_11111111111111111111111);\n    ```\n\n**Alternative 3:** allow any regular grouping.\n\nPro:\n\n-   Can be applied uniformly to all bases.\n\nCon:\n\n-   Provides no assistance for decimal numbers with a single digit separator.\n-   Does not allow binary literals to express an intent to initialize irregular\n    bit-fields.\n\n## Alternatives considered\n\nThere are a number of different design choices we could make, as divergences\nfrom the above proposal. Those choices, along with the arguments that led to\nchoosing the proposed design rather than each alternative, are presented below.\n\n### Integer bases\n\n#### Octal literals\n\nNo support is proposed for octal literals. In practice, their appearance in C\nand C++ code in a sample corpus consisted of (in decreasing order of commonality\nand excluding `0` literals):\n\n-   file permissions,\n-   cases where decimal was clearly intended (`CivilDay(2020, 04, 01)`), and\n-   (in _distant_ third place) anything else.\n\nThe number of intentional uses of octal literals, other than in file\npermissions, was negligible. We considered the following alternatives:\n\n**Baseline:** This proposal suggests that we do not support octal literals.\nOctal literals are rare and mostly obsolescent. File permissions can be\nsupported in some other way.\n\n**Alternative 1:** Follow C and C++, and use `0` as the base prefix for octal.\n\nPro:\n\n-   More similar to C++ and other languages.\n\nCon:\n\n-   Subtle and error-prone rule: for example, left-padding with zeroes for\n    alignment changes the meaning of literals.\n\n**Alternative 2:** Use `0o` as the base prefix for octal.\n\nPro:\n\n-   Unlikely to be misinterpreted as decimal.\n-   Follows several other languages (for example, Python).\n\nCon:\n\n-   Additional language complexity.\n\nIf we decide we want to introduce octal literals at a later date, use of\nalternative 2 is suggested.\n\n#### Decimal literals\n\n**We could permit leading `0`s in decimal integers (and in floating-point\nnumbers).**\n\nPro:\n\n-   We would allow leading `0`s to be used to align columns of numbers.\n\nCon:\n\n-   The same literal could be valid but have a different value in C++ and\n    Carbon.\n\n**We could add an (optional) base specifier `0d` for decimal integers.**\n\nPro:\n\n-   Uniform treatment of all bases. Left-padding with `0` could be achieved by\n    using `0d000123`.\n\nCon:\n\n-   No evidence of need for this functionality.\n\n**We could permit an `e` in decimal literals to express large powers of 10.**\n\nPro:\n\n-   Many uses of (eg) `1e6` in our sample C++ corpus intend to form an integer\n    literal instead of a floating-point literal.\n\nCon:\n\n-   Would violate the expectations of many C++ programmers used to `e`\n    indicating a floating-point constant.\n\nWe suggest that this syntax is not added at this point. However, it should be\nreconsidered at a later date, once developers are used the requirement that real\nliterals always contain a period.\n\n#### Case sensitivity\n\n**We could make base specifiers case-insensitive.**\n\nPro:\n\n-   More similar to C++.\n\nCon:\n\n-   `0B1` is easily mistaken for `081`\n-   `0B1` can be confused with `0xB1`\n-   `0O17` is easily mistaken for `0017`\n-   Allowing more than one way to write literals will lead to style divergence.\n\n**We could make the digit sequence in hexadecimal integers case-insensitive.**\n\nPro:\n\n-   More similar to C++.\n-   Some developers will be more comfortable writing hexadecimal digits in\n    lowercase. Some tools, such as `md5`, will print lowercase.\n\nCon:\n\n-   Allowing more than one way to write literals will lead to style divergence.\n-   Lowercase hexadecimal digits are less visually distinct from the `x` base\n    specifier (for example, the digit sequence is more visually distinct in\n    `0xAC` than in `0xac`).\n\n**We could require the digit sequence in hexadecimal integers to be written\nusing lowercase letters `a`..`f`.**\n\nPro:\n\n-   Some developers will be more comfortable writing hexadecimal digits in\n    lowercase. Some tools, such as `md5`, will print lowercase.\n-   `B` and `D` are more likely to be confused with `8` and `0` than `b` and `d`\n    are.\n\nCon:\n\n-   Some developers will be more comfortable writing hexadecimal digits in\n    uppercase. Some tools will print uppercase.\n-   Lowercase hexadecimal digits are less visually distinct from the `x` base\n    specifier (for example, the digit sequence is more visually distinct in\n    `0xAC` than in `0xac`).\n\n### Real number syntax\n\n**We could allow real numbers with no digits on one side of the period (`3.` or\n`.5`).**\n\nPro:\n\n-   More similar to C++.\n-   Allows numbers to be expressed more tersely.\n\nCon:\n\n-   Gives meaning to `tup.0` syntax that may be useful for indexing tuples.\n-   Gives meaning to `0.ToString()` syntax that may be useful for performing\n    member access on literals.\n-   May harm readability by making the difference between an integer literal and\n    a real number literal less significant.\n-   Allowing more than one way to write literals will lead to style divergence.\n\nSee also the section on\n[floating-point literals](https://google.github.io/styleguide/cppguide.html#Floating_Literals)\nin the Google style guide, which argues for the same rule.\n\n**We could allow a real number with no `e` or `p` to omit a period (`1e100`).**\n\nPro:\n\n-   More similar to C++.\n-   Allows numbers to be expressed more tersely.\n\nCon:\n\n-   Assuming that such numbers are integers rather than real numbers is a common\n    error in C++.\n\n**We could allow the `e` or `p` to be written in uppercase.**\n\nPro:\n\n-   More similar to C++.\n-   Most calculators use `E`, to avoid confusion with the constant `e`.\n\nCon:\n\n-   Allowing more than one way to write literals will lead to style divergence.\n-   `E` may be confused with a hexadecimal digit.\n\n**We could require a `p` in a hexadecimal real number literal.**\n\nPro:\n\n-   More similar to C++.\n-   When explicitly writing a bit-pattern for a floating-point type, it's\n    reasonable to always include the exponent value.\n\nCon:\n\n-   Less consistent.\n-   Makes hexadecimal floating-point values even more expert-only.\n\n**We could arbitrarily pick one of the two values when a real number is exactly\nhalf-way between two representable values.**\n\nPro:\n\n-   More similar to C++.\n-   Would accept more cases, and it's likely that either of the two possible\n    values would be acceptable in practice.\n\nCon:\n\n-   Would either need to specify which option is chosen or, following C++,\n    accept that programs using such literals have non-portable semantics.\n-   Numbers specified to the exact level of precision required to form a tie are\n    a strong signal that the programmer intended to specify a particular value.\n\n### Digit separator syntax\n\n**2020-09-15: core team meeting chose to forward digit separator to painter**\n\n**2020-10-05: painter selected Alternative 2: `_` as digit separator**\n\nThere are various different characters we could attempt to use as a digit\nseparator. The options we considered are:\n\n**Alternative 0:** `'` as a digit separator.\n\nPro:\n\n-   Follows C++ syntax.\n-   Used in several (mostly European) writing conventions.\n\nCon:\n\n-   `'` is also likely to be used to introduce character literals.\n\n**Alternative 1:** `,` as a digit separator.\n\nPro:\n\n-   More similar to how numbers are written in English text and many other\n    cultures.\n\nCon:\n\n-   Commas are expected to widely be used in Carbon programs for other purposes,\n    where there may be digits on both sides of the comma. For example, there\n    could be readability problems if `f(1, 234)` called `f` with two arguments\n    but `f(1,234)` called `f` with a single argument.\n-   Comma is interpreted as a decimal point in the conventions of many cultures.\n-   Unprecedented in common programming languages.\n\n**Alternative 2:** `_` as a digit separator.\n\nPro:\n\n-   Follows convention of C#, Java, JavaScript, Python, D, Ruby, Rust, Swift,\n    ...\n-   Culturally agnostic, because it doesn't match any common human writing\n    convention.\n\nCon:\n\n-   Underscore is not used as a digit grouping separator in any common human\n    writing convention.\n\n**Alternative 3:** whitespace as a digit separator.\n\nPro:\n\n-   Used and understood by many cultures.\n-   Never interpreted as a decimal point instead of a grouping separator.\n-   Also usable to the right of a decimal point.\n\nCon:\n\n-   Omitted separators in lists of numbers may result in distinct numbers being\n    spliced together. For example, `f(1, 23, 4 567)` may be interpreted as three\n    separate numerical arguments instead of four arguments with a missing comma.\n-   Unprecedented in other programming languages.\n\n**Alternative 4:** `.` as digit separator, `,` as decimal point.\n\nPro:\n\n-   More familiar to cultures that write numbers this way.\n\nCon:\n\n-   As with `,` as a digit separator, `,` as a decimal point is problematic.\n-   This usage is unfamiliar and would be surprising to programmers; programmers\n    from cultures where `,` is the decimal point in regular writing are likely\n    already accustomed to using `.` as the decimal point in programming\n    environments, and the converse is not true.\n\n**Alternative 5:** No digit separator syntax.\n\nPro:\n\n-   Simpler language rules.\n-   More consistent source syntax, as there is no choice as to whether to use\n    digit separators or not.\n\nCon:\n\n-   Harms the readability of long literals.\n\n## Rationale\n\nThe proposal provides a syntax that is sufficiently close to that used both by\nC++ and many other languages to be very familiar. However, it selects a\nreasonably minimal subset of the syntaxes. This minimal approach provides\nbenefits directly in line with both the simplicity and readability goals of\nCarbon:\n\n-   Reduces unnecessary choices for programmers.\n-   Simplifies the syntax rules of the language.\n-   Improves consistency of written Carbon code.\n\nThat said, it still provides sufficient variations to address important use\ncases for the goal of not leaving room for a lower level language:\n\n-   Hexadecimal and binary integer literals.\n-   Scientific notation floating point literals.\n-   Hexadecimal (scientific) floating point literals.\n\n### Painter rationale\n\nThe primary aesthetic benefit of `'` to the painter is consistency with C++.\nHowever, its rare usage in C++ at this point reduces this advantage to a very\nsmall one, while there is broad convergence amongst other languages around `_`.\nThe choice here has no risk of significant meaning or building up patterns of\nreading for users that might be disrupted by the change, and so it seems\nreasonable to simply converge with other languages to end up in the less\nsurprising and more conventional syntax space.\n\n### Open questions\n\nPlacement restrictions of digit separators:\n\n-   The core team had consensus for the proposed restricted placement rules.\n\nUse `_` or `'` as the digit separator character:\n\n-   The core team deferred this decision to the painter.\n-   The painter selected `_`.\n"
  },
  {
    "path": "proposals/p0144.md",
    "content": "# Numeric literal semantics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/144)\n\n## Table of contents\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Prelude support](#prelude-support)\n    -   [Implicit conversions](#implicit-conversions)\n    -   [Examples](#examples)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use an ordinary integer or floating-point type for literals](#use-an-ordinary-integer-or-floating-point-type-for-literals)\n    -   [Use same type for all literals](#use-same-type-for-all-literals)\n    -   [Allow leading `-` in literal tokens](#allow-leading---in-literal-tokens)\n\n<!-- tocstop -->\n\n## Problem\n\nWhen a numeric literal appears in a program, we need to understand its\nsemantics:\n\n-   What type does it have?\n-   What value is produced by operations on it?\n-   When can it validly be used to initialize an object?\n\n## Background\n\nIn C++, numeric literals have either an integral type or a floating-point type.\nC++ provides permission for implementations to add extended integral types, but\nin practice (for bad reasons relating to `intmax_t`) implementations do not do\nso, so there are a small finite set of types that any given numeric literal\nmight have:\n\n-   `int`, `long`, `long long`, or `unsigned` versions of these\n-   `float`, `double`, or `long double`\n\nThe choice of type is determined solely by the literal.\n\nThe C++ approach is error-prone and problematic:\n\n-   Lossy conversions from literals in initializers are permitted.\n-   Lossy operations on literals are permitted; for example, on a typical\n    implementation, `1 << 60` has value `0` because `1` is a 32-bit type.\n-   Attempting to naturally express some values has undefined behavior; for\n    example, `int x = -2147483648;` typically results in undefined behavior even\n    when -2147483648 is a valid `int` value.\n-   Integer literals with value 0 have special semantics that are lost when the\n    integer is passed to a function: \"perfect\" forwarding doesn't work for such\n    literals.\n-   The built-in types are privileged: only the types listed above have\n    literals. There is no syntax for a 64-bit integer literal, only for (for\n    example) a `long int` literal, which may or may not 64 bits wide.\n-   The type of a literal can be unpredictable in portable code, as it can\n    depend on which type a particular value happens to fit into.\n\n## Proposal\n\nNumeric literals have a type derived from their value, and can be converted to\nany type that can represent that value.\n\nSimple operations such as arithmetic that involve only literals also produce\nvalues of literal types.\n\n## Details\n\nNumeric literals have a type derived from their value. Two integer literals have\nthe same type if and only if they represent the same integer. Two real number\nliterals have the same type if and only if they represent the same real number.\n\nThat is:\n\n-   For every integer, there is a type representing literals with that integer\n    value.\n-   For every rational number, there is a type representing literals with that\n    real value.\n-   The types for real numbers are distinct from the types for integers, even\n    for real numbers that represent integers. `var x: i32 = 1.0;` is invalid.\n\nPrimitive operators are available between numeric literals, and produce values\nwith numeric literal types. For example, the type of `1 + 2` is the same as the\ntype of `3`.\n\nNumeric types can provide conversions to support initialization from numeric\nliterals. Because the value of the literal is carried in the type, a type-level\ndecision can be made as to whether the conversion is valid.\n\nThe integer types defined in the standard library permit conversion from integer\nliteral types whose values are representable in the integer type. The\nfloating-point types defined in the Carbon library permit conversion from\ninteger and rational literal types whose values are between the minimum and\nmaximum finite value representable in the floating-point type.\n\n### Prelude support\n\nThe following types are defined in the Carbon prelude:\n\n-   An arbitrary-precision integer type.\n\n    ```\n    class BigInt;\n    ```\n\n-   A rational type, parameterized by a type used for its numerator and\n    denominator.\n\n    ```\n    class Rational(T:! Type);\n    ```\n\n    The exact constraints on `T` are not yet decided.\n\n-   A type representing integer literals.\n\n    ```\n    class IntLiteral(N:! BigInt);\n    ```\n\n-   A type representing floating-point literals.\n\n    ```\n    class FloatLiteral(X:! Rational(BigInt));\n    ```\n\nAll of these types are usable during compilation. `BigInt` supports the same\noperations as `Int(n)`. `Rational(T)` supports the same operations as\n`Float(n)`.\n\nThe types `IntLiteral(n)` and `FloatLiteral(x)` also support primitive integer\nand floating-point operations such as arithmetic and comparison, but these\noperations are typically heterogeneous: for example, an addition between\n`IntLiteral(n)` and `IntLiteral(m)` produces a value of type\n`IntLiteral(n + m)`.\n\n### Implicit conversions\n\n`IntLiteral(n)` converts to any sufficiently large integer type, as if by:\n\n```\nimpl [template N:! BigInt, template M:! BigInt]\n    IntLiteral(N) as ImplicitAs(Int(M))\n    if N >= Int(M).MinValue as BigInt and N <= Int(M).MaxValue as BigInt {\n  ...\n}\nimpl [template N:! BigInt, template M:! BigInt]\n    IntLiteral(N) as ImplicitAs(Unsigned(M))\n    if N >= Int(M).MinValue as BigInt and N <= Int(M).MaxValue as BigInt {\n  ...\n}\n```\n\nThe above is for exposition purposes only; various parts of this syntax are not\nyet decided.\n\nSimilarly, `IntLiteral(x)` and `FloatLiteral(x)` convert to any sufficiently\nlarge floating-point type, and produce the nearest representable floating-point\nvalue. Conversions in which `x` lies exactly half-way between two values are\nrejected, as\n[previously decided](/docs/design/lexical_conventions/numeric_literals.md).\nConversions in which `x` is outside the range of finite values of the\nfloating-point type are also rejected, rather than saturating to the finite\nrange or producing an infinity.\n\n### Examples\n\n```carbon\n// This is OK: the initializer is of the integer literal type with value\n// -2147483648 despite being written as a unary `-` applied to a literal.\nvar x: i32 = -2147483648;\n\n// This initializes y to 2^60.\nvar y: i64 = 1 << 60;\n\n// This forms a rational literal whose value is one third, and converts it to\n// the nearest representable value of type `f64`.\nvar z: f64 = 1.0 / 3.0;\n\n// This is an error: 300 cannot be represented in type `i8`.\nvar c: i8 = 300;\n\nfn f[template T:! Type](v: T) {\n  var x: i32 = v * 2;\n}\n\n// OK: x = 2_000_000_000.\nf(1_000_000_000);\n\n// Error: 4_000_000_000 can't be represented in type `i32`.\nf(2_000_000_000);\n\n// No storage required for the bound when it's of integer literal type.\nstruct Span(template T:! Type, template BoundT:! Type) {\n  var begin: T*;\n  var bound: BoundT;\n}\n\n// Returns 1, because 1.3 can implicitly convert to f32, even though conversion\n// to f64 might be a more exact match.\nfn G() -> i32 {\n  match (1.3) {\n    case _: f32 => { return 1; }\n    case _: f64 => { return 2; }\n  }\n}\n\n// Can only be called with a literal 0.\nfn PassMeZero(_: IntLiteral(0));\n\n// Can only be called with integer literals in the given range.\nfn ConvertToByte[template N:! BigInt](_: IntLiteral(N)) -> i8\n    if N >= -128 and N <= 127 {\n  return N as i8;\n}\n\n// Given any int literal, produces a literal whose value is one higher.\nfn OneHigher(L: IntLiteral(template _:! BigInt)) -> auto {\n  return L + 1;\n}\n// Error: 256 can't be represented in type `i8`.\nvar v: i8 = OneHigher(255);\n```\n\n## Alternatives considered\n\n### Use an ordinary integer or floating-point type for literals\n\nWe could decide on a fixed-width type based on the form of the literal, for\nexample using a type suffix with some rules to determine what type to pick for\nunsuffixed literals.\n\nAdvantages:\n\n-   This follows what C++ does.\n-   Can determine the type of a floating-point number without requiring\n    contextual information.\n\nDisadvantages:\n\n-   Surprising behavior when applying an operator to a literal would result in\n    overflow. Even if we diagnose this, a diagnostic that `-2147483648` is\n    invalid because it overflows is surprising.\n-   Creates additional literal syntax that users will need to understand.\n-   May select types that don't match the programmer's expectations.\n-   Whatever types we pick are privileged.\n\n### Use same type for all literals\n\nWe could give literals a single, arbitrary-precision type (say, `Integer` for\ninteger literals and `Rational` for real literals).\n\nAdvantages:\n\n-   Only introduces two new types, not an unbounded parameterized family of\n    types.\n-   Writing a function that takes any integer literal can be done with more\n    obvious syntax and less syntactic overhead. Instead of:\n    ```\n    fn OneHigher(L: IntLiteral(template _:! BigInt));\n    ```\n    we could write\n    ```\n    fn OneHigher(template L:! Integer);\n    ```\n    However, with this proposal, a function taking any integer expression that\n    can be evaluated to a constant can be written as\n    ```\n    fn F(template N:! BigInt);\n    ```\n    and such a function would accept all integer literals, as well as\n    non-literal constants.\n\nDisadvantages:\n\n-   Our mechanism for specifying the behavior of operations such as arithmetic\n    is based on interface implementations, which are looked up by type.\n    Supporting `impl` selection based on values would introduce substantial\n    complexity.\n-   If we introduce an arbitrary-precision integer type, it would be\n    inconsistent to support it only during compilation. However, if we allow its\n    use at runtime, programs may use it accidentally, with an invisible\n    performance cost. For example, `var x: auto = 123;` would result in `x`\n    having an infinite-precision type, possibly involving invisible dynamic\n    allocation.\n    -   Under this proposal, the type of `x` is a type that can only represent\n        the value `123`; as such, `x` is effectively immutable. The\n        arbitrary-precision integer type introduced in this proposal can only be\n        used explicitly by programs naming it.\n\n### Allow leading `-` in literal tokens\n\nWe could treat a leading `-` character as part of a numeric literal token, so\nthat -- for example -- `-123` would be a single `-123` token rather than a unary\nnegation applied to a literal `123`.\n\nAdvantages:\n\n-   This would narrowly solve the problem that `INT_MIN` cannot be written\n    directly, without any of the other implications of this proposal.\n\nDisadvantages:\n\n-   Makes the behavior of unary `-` less uniform.\n-   Prevents the introduction of infix or postfix operators that bind more\n    tightly than unary `-`, such as an infix exponentiation operator: `-2**2`\n    may be expected to evaluate to -4, not to +4.\n"
  },
  {
    "path": "proposals/p0149.md",
    "content": "# Change documentation style guide\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/149)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Common deviations](#common-deviations)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Google developer documentation style guide](#google-developer-documentation-style-guide)\n    -   [Microsoft writing style guide](#microsoft-writing-style-guide)\n    -   [Word lists](#word-lists)\n-   [Alternatives considered](#alternatives-considered)\n-   [Rationale](#rationale)\n    -   [Painter rationale](#painter-rationale)\n    -   [Open questions](#open-questions)\n        -   [Which style guide?](#which-style-guide)\n\n<!-- tocstop -->\n\n## Problem\n\nThere's disagreement with the current Google developer documentation style\nguide. We should make sure the core team has a consensus on the style guide\nchosen.\n\n## Background\n\nThe status quo is that we use the Google style guide, per\n[CONTRIBUTING.md](/CONTRIBUTING.md#style). There's basic support for a style\nguide in order to avoid protracted debate about formatting and to maintain basic\nconsistency.\n\nKey desires for a style guide are:\n\n-   Actively maintained.\n-   Freely available for contributors.\n\n### Common deviations\n\nCONTRIBUTING.md notes a couple deviations from the Google style guide. These may\nbe assumed to apply regardless of the style guide, as the relevant styles are\ncommon to Microsoft's style guide.\n\n## Proposal\n\nA style guide should be chosen. The only candidates found are:\n\n-   Google developer documentation style guide\n-   Microsoft writing style guide\n\nThis may be done with or without additional modifications, such as the em-dash\nexception in CONTRIBUTING.md.\n\n**Open question**: Which style guide?\n\n**Decision**: Google style guide\n\n## Details\n\nA few key items are highlighted from both style guides for comparison.\n\n### Google developer documentation style guide\n\nhttps://developers.google.com/style\n\n-   **Dates and times**:\n    [January 19, 2017 or 2017-04-15 3:45 PM](https://developers.google.com/style/dates-times).\n-   **Lists**:\n    [nuanced guidance for punctuation](https://developers.google.com/style/lists).\n-   **Non-English words**: mostly covered through the word list and\n    [abbreviations](https://developers.google.com/style/abbreviations).\n-   **Punctuation**:\n    -   Commas: [Oxford](https://developers.google.com/style/commas).\n    -   Parentheses:\n        [use judiciously](https://developers.google.com/style/parentheses).\n    -   Semicolons:\n        [use judiciously](https://developers.google.com/style/semicolons).\n-   **Word list**:\n    -   Letter links, such as\n        [i](https://developers.google.com/style/word-list#letter-i).\n    -   Easy to skim comments on words.\n\n### Microsoft writing style guide\n\nhttps://docs.microsoft.com/en-us/style-guide/welcome/\n\n-   **Dates and times**:\n    [February 16, 2016, 3:45 PM](https://docs.microsoft.com/en-us/style-guide/global-communications/time-place#dates).\n    [Only use digits for dates in locale-customized UIs](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/term-collections/date-time-terms).\n-   **Lists**:\n    [use a period if any item is a complete sentence](https://docs.microsoft.com/en-us/style-guide/scannable-content/lists).\n-   **Non-English words**:\n    [avoid](https://docs.microsoft.com/en-us/style-guide/word-choice/use-us-spelling-avoid-non-english-words).\n-   **Punctuation**:\n    -   Commas:\n        [Oxford](https://docs.microsoft.com/en-us/style-guide/punctuation/commas).\n    -   Parentheses:\n        [no guidance, sentence-length parenthetical examples](https://docs.microsoft.com/en-us/style-guide/punctuation/formatting-punctuation).\n    -   Semicolons:\n        [avoid](https://docs.microsoft.com/en-us/style-guide/punctuation/semicolons).\n-   **Word list**:\n    -   Letter links and individual word links, such as\n        [illegal](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/i/illegal).\n    -   No way to skim comments on words; each needs to be read individually.\n\n### Word lists\n\n> NOTE: Due to the noted lack of support for skimming Microsoft's word list, it\n> may be that Microsoft has other noteworthy guidance for terms that Google\n> doesn't.\n\n<!-- google-doc-style-ignore -->\n\nabove\n\n: Google: Use preceding.\n\n: Microsoft: \"Use previous, preceding, or earlier.\"\n\nand so on\n\n: Google: See etc.\n\n: Microsoft: \"Use such as or like.\"\n\nbelow\n\n: Google: Use following.\n\n: Microsoft: \"Use a link, or use later or the following.\"\n\nblacklist\n\n: Google: Use blocklist.\n\n: Microsoft: \"Use block list instead. Note that block list is two words.\"\n\ncons\n\n: Google: Use disadvantages.\n\n: Microsoft: No guidance.\n\nCLI\n\n: Google: Use command-line tool.\n\n: Microsoft: No guidance.\n\nclient\n\n: Google: Short for \"client app\", say \"library\" for \"client library\".\n\n: Microsoft: Use customer to refer to people.\n\ne.g.\n\n: Google: Use for example or such as. Too many people mix up e.g. and i.e.\n\n: Microsoft: \"Use for example, such as, or like, as appropriate.\"\n\netc.\n\n: Google: Avoid if possible, but use instead of and so on.\n\n: Microsoft: \"Use such as or like followed by an example or two.\"\n\nfilename, file name\n\n: Google: one word.\n\n: Microsoft: two words.\n\nfile name extension, extension\n\n: Google: No guidance, but \"filename extension\" is used in the guide.\n\n: Microsoft: Use instead of file extension.\n\nflag\n\n: Google: Use option.\n\n: Microsoft: No guidance.\n\nfor instance\n\n: Google: Use for example or such as.\n\n: Microsoft: No guidance.\n\ni.e.\n\n: Google: Use that is.\n\n: Microsoft: Use that is.\n\nillegal\n\n: Google: No guidance.\n\n: Microsoft: \"Don't use to mean invalid or not valid.\"\n\njust\n\n: Google: Don't use.\n\n: Microsoft: No guidance.\n\nmaster/slave\n\n: Google: Use master with caution. Don't use slave. Multiple alternatives given.\n\n: Microsoft: Don't use master/slave. Multiple alternatives given.\n\nnative\n\n: Google: Avoid and use more precise terms when possible, such as \"built-in\".\n\n: Microsoft: Only guidance is for native language. \"Don't use to refer to a\ncomputer system's machine language. Use machine language or host language\ninstead.\"\n\npros\n\n: Google: Use advantages.\n\n: Microsoft: No guidance.\n\nquick\n\n: Google: Avoid.\n\n: Microsoft: No guidance.\n\nregex\n\n: Google: Use regular expression.\n\n: Microsoft: No guidance.\n\nrepo\n\n: Google: Use repository.\n\n: Microsoft: No guidance.\n\nshould\n\n: Google: Avoid because it's ambiguous.\n\n: Microsoft: \"Before using should or must, consider other ways to discuss\nrecommendations or requirements.\"\n\nsimple, simply\n\n: Google: Avoid; \"what might be simple for you might not be simple for others.\"\n\n: Microsoft: Only guidance is for simply; nothing for simple. \"Don't use to mean\nthat something is easy to do.\"\n\ntl;dr\n\n: Google: Use to summarize.\n\n: Microsoft: No guidance.\n\ntraditional\n\n: Google: Avoid.\n\n: Microsoft: No guidance.\n\nvia\n\n: Google: Don't use.\n\n: Microsoft: No explicit guidance, but might be considered to fall under\nnon-English words.\n\nvice versa\n\n: Google: Use other way around or conversely.\n\n: Microsoft: No explicit guidance, but might be considered to fall under\nnon-English words.\n\nvs.\n\n: Google: Use versus.\n\n: Microsoft: Use versus.\n\n<!-- google-doc-style-resume -->\n\n## Alternatives considered\n\nVarious offline resources like the Chicago Manual of Style may be helpful to\nsome, but require a subscription or physical copy, and so are less useful as\ncanonical resources for contributors.\n\n## Rationale\n\nThe core team reached consensus that there should be a style guide, but did not\nhave a strong preference between the Google style guide and the Microsoft style\nguide. One advantage of the Microsoft style guide is that it is less\nGoogle-centric, which could contribute somewhat to our community goal. Given the\nlevel of experience of the core team members with these style guides, it is not\nclear that a well-informed decision could be made. As such, the core team\ndecided to leave the decision of the specific style guide up to the Painter.\n\n### Painter rationale\n\nGiven the lack of a high level reason to pick one over the other, the painter\nlooked at the available tooling for linting against the two options and spoke\nwith people who have written substantial developer documentation against both\nstyle guides. There was no persuasive reason to change from the Google\ndocumentation style guide at this time. Specific ambiguities or problems with\nthat style guide should instead be addressed, if necessary at all, with\nCarbon-specific local rule.\n\n### Open questions\n\n#### Which style guide?\n\nThe core team decided to let the Painter choose the style guide to be used. The\npainter selected to continue using the Google documentation markdown style\nguide.\n"
  },
  {
    "path": "proposals/p0157.md",
    "content": "# Design direction for sum types\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/157)\n\n## Table of contents\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Shareable storage](#shareable-storage)\n-   [User-defined pattern matching](#user-defined-pattern-matching)\n-   [\"Bare\" designator syntax](#bare-designator-syntax)\n    -   [Alternatives considered](#alternatives-considered)\n        -   [Placeholder keywords](#placeholder-keywords)\n        -   [Designator types](#designator-types)\n-   [Distinguishing pattern and expression semantics](#distinguishing-pattern-and-expression-semantics)\n    -   [Alternatives considered](#alternatives-considered-1)\n        -   [Separate syntaxes](#separate-syntaxes)\n        -   [Disambiguation by fixed priority](#disambiguation-by-fixed-priority)\n        -   [Disambiguation based on pattern content](#disambiguation-based-on-pattern-content)\n-   [Choice types](#choice-types)\n    -   [Alternatives considered](#alternatives-considered-2)\n        -   [Different spelling for `choice`](#different-spelling-for-choice)\n-   [Alternatives considered](#alternatives-considered-3)\n    -   [`choice` types only](#choice-types-only)\n    -   [Indexing by type](#indexing-by-type)\n    -   [Pattern matching proxies](#pattern-matching-proxies)\n    -   [Pattern functions](#pattern-functions)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Problem\n\nMany important programming use cases involve values that are most naturally\nrepresented as having one of several alternative forms (called _alternatives_\nfor short). For example,\n\n-   Optional values, which are pervasive in computing, take the form of either\n    values of some underlying type, or a special \"not present\" value.\n-   Functions that cannot throw exceptions often use a return type that can\n    represent either a successfully computed result, or some description of how\n    the computation failed.\n-   Nodes of a parse tree often take different forms depending on the grammar\n    production that generated them. For example, a node of a parse tree for\n    simple arithmetic expressions might represent either a sum or product\n    expression with two child nodes representing the operands, or a\n    parenthesized expression with a single child node representing the contents\n    of the parentheses.\n-   The error codes returned by APIs like POSIX have a fixed set of named\n    values.\n\nWhat unites these use cases is that the set of alternatives is fixed by the API,\nit is possible for user code to determine which alternative is present, and\nthere is little or nothing you can usefully do with such a value without first\nmaking that determination.\n\nCarbon needs to support defining and working with types representing such\nvalues. Following Carbon's principles, these types need to be easy to define,\nunderstand, and use, and they need to be safe -- in ordinary usage, the type\nsystem should ensure that user code cannot accidentally access the wrong\nalternative. These types should be writeable as well as readable, and writing\nshould be type-safe and efficient. In particular, it should be possible to\nmutate a single sub-field of an alternative, without having to overwrite the\nentire alternative, and without a risk of accidentally doing so when that\nalternative is not present.\n\nFurthermore, it needs to be possible for type owners to customize the\nrepresentations of these types. For example:\n\n-   Most sum types need a \"discriminator\" field to indicate which alternative is\n    present, but since it typically has very few possible values, it can often\n    be packed into padding, or even the low-order bits of a pointer.\n-   Other sum types avoid an explicit discriminator, and instead reserve certain\n    values to indicate separate alternatives. For example, a typical C-style\n    pointer can be thought of as an optional type, with a special null value\n    indicating that no pointer is present, because the platform guarantees that\n    the null byte pattern is never the representation of a valid pointer.\n\nIt must be possible to implement such customizations without changing the type's\nAPI, and hence without altering the static safety guarantees for users of the\ntype.\n\n## Background\n\nThe terminology in this space is quite fragmented and inconsistent. This\nproposal will use the term _sum types_ to refer to types of the kind described\nin the problem statement. Note that \"sum type\" is not being proposed as a\nspecific Carbon feature, or even as a precisely defined term of art; it is\nmerely an informal way for this proposal to refer to its motivating use cases,\nin much the same way that a structs proposal might refer to \"value types\".\n\nCarbon as currently envisioned is already capable of approximating support for\nsum types. In particular, [pattern matching](/docs/design/pattern_matching.md)\ngives us a natural way to express querying which alternative is active, and then\nperforming computations on that active alternative, which as discussed above is\nthe primary way of interacting with a sum type. For example, a value-or-error\ntype `Result(T, Error)` could be implemented like so:\n\n```\n// Result(T, Error) holds either a successfully-computed value of type T,\n// or metadata about a failure during that computation, or a singleton\n// \"cancelled\" state indicating that the computation successfully complied with\n// a request to halt before completion.\nstruct Result(Type:$$ T, Type:$$ Error) {\n  // 0 if this represents a value, 1 if this represents an error, 2 if this\n  // represents the cancelled state.\n  var Int: discriminator;\n  var T: value;\n  var Error: error;\n\n  fn Success(T: value) -> Result(T, Error) {\n    return (.discriminator = 0, .value = value, .error = Error());\n  }\n\n  fn Failure(Error: error) -> Result(T, Error) {\n    return (.discriminator = 1, .value = T(), .error = error);\n  }\n\n  var Result(T, Error):$$ Cancelled =\n    (.discriminator = 2, .value = T(), .error = Error());\n}\n```\n\nA typical usage might look like:\n\n```\nfn ParseAsInt(String: s) -> Result(Int, String) {\n  var Int: result = 0;\n  var auto: it = s.begin();\n  while (it != s.end()) {\n    if (*it < '0' || *it > '9') {\n      return Result(Int, String).Failure(\"String contains non-digit\");\n    }\n    result += *it - '0';\n    result *= 10;\n  }\n  return Result(Int, String).Success(result);\n}\n\nfn GetIntFromUser() -> Int {\n  while(True) {\n    var String: s = UserPrompt(\"Please enter a number\");\n    match (ParseAsInt(s)) {\n      case (.discriminator = 0, .value = Int: value, .error = String: _) => {\n        return value;\n      }\n      case (.discriminator = 1, .value = Int: _, .error = String: error) => {\n        Display(error);\n      }\n      case .Cancelled => {\n        // We didn't request cancellation, so something is very wrong.\n        Terminate();\n      }\n      default => {\n        // Can't happen, because the above cases are exhaustive.\n        Assert(False);\n      }\n    }\n  }\n}\n```\n\nHowever, this code has several functional deficiencies:\n\n-   `.value` and `.error` must both be live throughout the `Result`'s lifetime,\n    even when they are not meaningful. Consequently, `Success` must populate\n    `.error` with a default-constructed dummy value (and so it won't work if\n    `Error` is not default-constructible), `Failure` must do the same for\n    `.value`, and `Cancelled` must do the same for both. Furthermore, `Result`\n    is bloated by the fact that the two fields must have separately-allocated\n    storage, even though at most one at a time actually stores any data.\n-   The implementation details of `Result` are not encapsulated. This makes the\n    `Result` API unsafe: nothing prevents client code from accessing `.value`\n    even when `.discriminator` is not 0. This also makes the patterns extremely\n    verbose.\n-   `.discriminator` should never have any value other than 0, 1, or 2, but the\n    compiler can't enforce that property when `Result`s are created, or exploit\n    it when `Result`s are used. So, for example, the `match` must have a\n    `default` case in order for the compiler and other tools to consider it\n    exhaustive, even though that default case should never be entered.\n\nIt also has a couple of ergonomic problems:\n\n-   The definition of `Result` is largely boilerplate. Conceptually, the only\n    information needed to specify this type is the names and parameter types of\n    the two factory functions, the name of the static member `Cancelled`, plus\n    the fact that every possible value of `Result` is uniquely described by the\n    name and parameter values of a call to one of those two functions, or else\n    equal to `Cancelled`. Given that information, the compiler could easily\n    generate the rest of the struct definition. This generated implementation\n    may not always be as efficient as a hand-coded one could be, but in a lot of\n    cases that may not matter.\n-   The `return` statements in `ParseAsInt` are quite verbose, due to the need\n    to explicitly qualify the function calls with `Result(Int, String)`. In\n    fact, developers might prefer to avoid having a function call at all,\n    especially in the success case, and instead rely on implicit conversions to\n    write something like `return result;`.\n\n## Proposal\n\nTo summarize, the previous section identified several missing features in\nCarbon, which together would enable Carbon to support efficient and ergonomic\nsum types:\n\n-   There's no way to manually control the lifetimes of subobjects, or enable\n    them to share storage.\n-   There's no way for pattern matching to operate through an encapsulation\n    boundary.\n-   There's no way for a type to specify that a given set of patterns is\n    exhaustive.\n-   There's no concise way to define a sum type based on the form of its\n    alternatives.\n-   There's no way to return a specific alternative without restating the return\n    type of the function.\n\nI propose supporting sum types by introducing several language features to\nsupply the missing functionality identified above. These features are largely\nseparable, although there are some dependencies between them, so their detailed\ndesign will be addressed in future proposals, and the details discussed here\nshould be considered provisional. This proposal merely establishes the overall\ndesign direction for sum types, in the same way that [#83](p0083.md) established\nthe overall design direction for the language as a whole.\n\nTo support manual lifetime control and storage sharing, I propose introducing at\nleast one and preferably both of the following:\n\n-   A `Storage` type, which represents a fixed-size buffer of untyped memory and\n    provides operations for creating and destroying objects within it.\n-   A typed `union` facility, such as the one described in proposal\n    [0139](https://github.com/carbon-language/carbon-lang/pull/139).\n\nTo support encapsulation in pattern matching, I propose introducing a\n`Matchable` interface, which a type can implement in order to specify how it\nbehaves in pattern matching, including what (if anything) constitutes an\nexhaustive set of patterns for that type.\n\nTo allow users to concisely specify a sum type when they don't need to\nmicro-optimize the implementation details, I propose a `choice` syntax that\nspecifies a sum type purely in terms of its alternatives, which acts as a sugar\nsyntax for those lower-level features.\n\nTo avoid redundant boilerplate in functions that return sum types, I propose\nallowing statements of the form `return .X;` and `return .F();`, which are\ninterpreted as if the function's return type appeared immediately prior to the\n`.` character.\n\nCumulatively, these features will allow `Status` to be defined so that the usage\nportions of the above example can be rewritten as follows:\n\n```\nfn ParseAsInt(String: s) -> Result(Int, String) {\n  var Int: result = 0;\n  var auto: it = s.begin();\n  while (it != s.end()) {\n    if (*it < '0' || *it > '9') {\n      return .Failure(\"String contains non-digit\");\n    }\n    result += *it - '0';\n    result *= 10;\n  }\n  return .Success(result);\n}\n\nfn GetIntFromUser() -> Int {\n  while(True) {\n    var String: s = UserPrompt(\"Please enter a number\");\n    match (ParseAsInt(s)) {\n      case .Success(var Int: value) => {\n        return value;\n      }\n      case .Failure(var String: error) => {\n        Display(error);\n      }\n      case .Cancelled => {\n        // We didn't request cancellation, so something is very wrong.\n        Terminate();\n      }\n    }\n  }\n}\n```\n\n> **Open question:** How will user-defined sum types (and pattern matching in\n> general) support name bindings that allow you to mutate the underlying object?\n\n## Shareable storage\n\nThis approach to sum types imposes relatively few requirements on the language\nfeatures used to implement shareable storage (meaning, storage that can be\ninhabited by different objects at different times), and so this proposal doesn't\ndescribe them in much detail. The primary options are typed unions along the\nlines of proposal\n[0139](https://github.com/carbon-language/carbon-lang/pull/139), and untyped\nbyte buffers along the lines described below. Typed unions are somewhat safer\nand more readable, but less general. For example, they can't support use cases\nlike implementing a small-object-optimized version of\n[`std::any`](https://en.cppreference.com/w/cpp/utility/any), because the set of\npossible types is not known in advance.\n\nThis proposal takes the position that Carbon must have at least one of these two\nfeatures. Whether it should have only untyped byte buffers, only typed unions,\nor both, is left as an **open question**, because the answer is orthogonal to\nthe overall design direction that is the focus of this proposal. Consequently, I\nwill not further discuss the tradeoffs between the two features. This proposal's\nexamples focus on untyped byte buffers because they are simpler to describe, and\naren't already covered by another proposal.\n\nRegardless of the form that shareable storage takes, it won't be able to\nintrinsically keep track of whether it currently holds any objects, or the types\nor offsets of those objects, because that would require it to maintain\nadditional hidden storage, and a major goal of this design is to give the\ndeveloper explicit control of the object representation. Consequently, it is not\nsafe to copy, move, assign to, or destroy shareable storage unless it is known\nnot to be inhabited by an object.\n\nThis means that in the general case, the compiler will not be able to generate\nsafe default implementations for any special member functions of types that have\nshareable storage members.\n\nFor purposes of illustration in this proposal, I will treat\n`Storage(SizeT size, SizeT align)` as a library template representing an untyped\nbuffer of `size` bytes, aligned to `align`. It provides `Create`, `Read`, and\n`Destroy` methods which create, access, and destroy an object of a specified\ntype within the buffer.\n\nUsing `Storage`, we can redefine `Status` as follows:\n\n```\nstruct Result(Type:$$ T, Type:$$ Error) {\n  var Int: discriminator;\n\n  var Storage(Max(Sizeof(T), Sizeof(Error)),\n              Max(Alignof(T), Alignof(Error))): storage;\n\n  fn Success(T: value) -> Self {\n    Self result = (.discriminator = 0);\n    result.storage->Create(T, value);\n    return result;\n  }\n\n  fn Failure(Error: error) -> Self {\n    Self result = (.discriminator = 1);\n    result.storage->Create(Error, error);\n    return result;\n  }\n\n  var Self:$$ Cancelled = (.discriminator = 2);\n\n  // Copy, move, assign, destroy, and similar operations need to be defined\n  // explicitly, but are omitted for brevity.\n}\n```\n\n## User-defined pattern matching\n\nAs seen in the example above, we want to allow pattern-matching on `Status` to\nlook like this:\n\n```\nmatch (ParseAsInt(s)) {\n  case .Success(var Int: value) => {\n    return value;\n  }\n  case .Failure(var String: error) => {\n    Display(error);\n  }\n  case .Cancelled => {\n    // We didn't request cancellation, so something is very wrong.\n    Terminate();\n  }\n}\n```\n\nFor this to work, `Status` needs to specify two things:\n\n-   The set of all possible alternatives, including their names and parameter\n    types, so that the compiler can typecheck the `match` body, identify any\n    unreachable `case`s, and determine whether any `case`s are missing.\n-   The algorithm that, given a `Status` object, determines which alternative is\n    present, and specifies the values of its parameters.\n\nHere's how `Status` can do that under this proposal:\n\n```\nstruct Result(Type:$$ T, Type:$$ Error) {\n  var Int: discriminator;\n\n  var Storage(Max(Sizeof(T), Sizeof(Error)),\n              Max(Alignof(T), Alignof(Error))): storage;\n\n  interface MatchContinuation {\n    var Type:$$ ReturnType;\n    fn Success(T: value) -> ReturnType;\n    fn Failure(Error: error) -> ReturnType;\n    fn Cancelled() -> ReturnType;\n  }\n\n  impl Matchable(MatchContinuation) {\n    method (Ptr(Self): this) Match[MatchContinuation:$ Continuation](\n        Ptr(Continuation): continuation) -> Continuation.ReturnType {\n      match (discriminator) {\n        case 0 => {\n          return continuation->Success(this->storage.Read(T));\n        }\n        case 1 => {\n          return continuation->Failure(this->storage.Read(Error));\n        }\n        case 2 => {\n          return continuation->Cancelled();\n        }\n        default => {\n          Assert(false);\n        }\n      }\n    }\n  }\n\n  // Success() and Failure() factory functions, and the Cancelled static\n  // constant, are defined as above.\n\n  // Copy, move, assign, destroy, and similar operations need to be defined\n  // explicitly, but are omitted for brevity.\n}\n```\n\nIn this code, `Result` makes itself available for use in pattern matching by\ndeclaring that it implements the `Matchable` interface. `Matchable` takes an\ninterface argument, `MatchContinuation` in this case, which specifies the set of\npossible alternatives by declaring a method for each one. I'll call that\nargument the _continuation interface_, for reasons that are about to become\nclear.\n\nThe `Match` method of the `Matchable` interface. This method takes two\nparameters: the value being matched against, and an instance of the continuation\ninterface, which the compiler generates from the `match` expression being\nevaluated, with method bodies that correspond to the bodies of the corresponding\n`case`s. Once `Match` has determined which alternative is present, and the\nvalues of its parameters, it invokes the corresponding method of the\ncontinuation object. `Match` is required to invoke exactly one continuation\nmethod, and to do so exactly once.\n\nThis proposal assumes that Carbon will have support for defining and\nimplementing generic interfaces, including interfaces that take interface\nparameters, and uses `interface`, `impl`, `method` etc. as **placeholder**\nsyntax. It can probably be revised to work if interfaces can't be parameterized\nthat way, or if we don't have a feature like this at all, but it might be\nsomewhat more awkward.\n\nNotice that the names `Success`, `Failure`, and `Cancelled` are defined twice,\nonce as factory functions of `Result` and once as methods of\n`MatchContinuation`, with the same parameter types in each case. The two\neffectively act as inverses of each other: the factory functions compute a\n`Result` from their parameters, and the methods are used to report the parameter\nvalues that compute a given `Result`. This mirroring between expression and\npattern syntax is ultimately a design choice by the type author; there is no\nlanguage-level requirement that the alternatives correspond to the factory\nfunctions.\n\nThis approach can be extended to support non-sum patterns as well. For example,\na type that wants to match a tuple-shaped pattern like `(Int: i, String: s)`\ncould define a continuation interface like\n\n```\ninterface MatchContinuation {\n  fn operator()(Int: i, String: s);\n}\n```\n\nA type's continuation interface can also include a function named\n`operator default`, which implements the `default` case of the `match`.\nConsequently, any `match` on that type will be required to have a `default`\ncase. This is valuable because it protects the type author's ability to add new\nalternatives in the future, without causing build failures in client code.\n\n> **Open question:** Can `Match` actually invoke `operator default`? It might\n> sometimes be useful to define a type that can't be matched exhaustively, and\n> the mere possibility that the `default` case could actually run might help\n> encourage client code to implement it robustly, rather than blindly providing\n> something like `Assert(False)`. However, if there's a language-level guarantee\n> that the `default` case is unreachable if all other alternatives are handled,\n> then we can allow code in the same library as the type to omit the `default`\n> case. That's desirable because code in the same library doesn't pose an\n> evolutionary risk, and it's often valuable to have a build-time guarantee that\n> code within the type's own API explicitly handles every case.\n\nNote that `Match`'s continuation parameter type must be generic rather than\ntemplated (`:$` rather than `:$$`). Template specialization is driven by the\nconcrete values of the template arguments, but the type of the continuation\nparameter may depend on code generation details that aren't yet known when\ntemplate specialization takes place. By the same token, we won't support\noverloading `Match`, because overload resolution is likewise driven by the\nconcrete types of the function arguments, which may not be known at that point.\n\n## \"Bare\" designator syntax\n\nA _designator_ is a token consisting of `.` followed by an identifier. The\ncanonical use case for designators is member access, as in `foo.bar`, where the\ndesignator applies to the preceding expression. However, we expect Carbon will\nalso have some use cases for \"bare\" designators, where there is no preceding\nexpression. In particular, we expect to use bare designators to initialize named\ntuple fields, as in `(.my_int = 42, .my_str = \"Foo\")`, which produces a tuple\nwith fields named `my_int` and `my_str`.\n\nI propose to also permit using bare designators to refer to the alternatives of\na sum type, in cases where the sum type is clear from context. In particular, I\npropose that in statements of the form `return R.Alt;` or\n`return R.Alt(<args>);`, where `R` is the function return type, the `R` can be\nomitted. Similarly, I propose that patterns of the form `S.Alt` or\n`S.Alt(<subpatterns>)`, where `S` is the type being matched against, the `S` can\nbe omitted. Note that both of these shorthands are allowed only at top level,\nnot as subexpressions or subpatterns.\n\n> **Open question:** Can we also permit these shorthands to be nested? This\n> would be more consistent and less surprising, but could create ambiguity with\n> the use of bare designators in tuple initialization: does `case (.Foo, .Bar)`\n> match a tuple of two fields named `Foo` and `Bar`, or does it match a tuple of\n> two positional fields, of sum types that respectively have `.Foo` and `.Bar`\n> as alternatives? Furthermore, allowing such nested usages may conflict with\n> the\n> [proposed principle](https://github.com/carbon-language/carbon-lang/pull/103)\n> that type information should propagate only from an expression to its\n> enclosing context, and not vice-versa.\n>\n> The issue of type propagation is particularly acute if we want to allow\n> nesting of alternatives, such as `case .Foo(.Bar(_))`. The problem there is\n> that we are relying on the type of `Foo`'s parameter to tell us the type of\n> the argument expression `.Bar(_)`, but if `Foo` is overloaded, we can't\n> determine the type of the parameter until the overload is resolved, and to do\n> that we first need to know the type of the argument expression. And even if\n> `Foo` is not currently overloaded, an overload might be added in the future\n> (at least if the sum type has an `operator default`). Adding overloads is a\n> canonical example of the kind of software evolution that Carbon is intended to\n> allow, so the validity of this code can't depend on whether or not `Foo` is\n> overloaded.\n\n### Alternatives considered\n\n#### Placeholder keywords\n\nRather than allowing code to omit the type altogether, we could allow code to\nreplace the type with a placeholder keyword, for example `case auto.Foo`. This\nwould avoid the ambiguity with tuple initialization, but would still mean that\ntype information is propagating into the expression from its surrounding context\nrather than vice-versa (which also means that `auto` may not be an appropriate\nspelling). Furthermore, this could wind up feeling fairly boilerplate-heavy,\neven if the keyword is very short.\n\n#### Designator types\n\nWe could treat each bare designator as essentially defining its own type, which\nmay then implicitly convert to a suitable sum type. For example, we could think\nof `.Some(42)` as having a type `DesignatedTuple(\"Some\", (Int))`, and\n`Optional(Int)` would define an implicit conversion from that type. This would\nensure that type information does not propagate into the expression from the\ncontext, but would not resolve the ambiguity with tuple initialization.\nFurthermore, this would mean that the names of bare designators do not need to\nbe declared before they are used, and in fact can't be meaningfully declared at\nall.\n\nThis could have very surprising consequences. For example, a typo in a line of\ncode like `var auto: x = .Sone(42);` cannot be diagnosed at that line. Instead,\nthe problem can't be diagnosed until `x` is used, and even then it will show up\nas an overload resolution error rather than a name lookup error. This is\nparticularly problematic because it is much harder to provide useful, actionable\ndiagnostics for overload resolution failure than for name lookup failure.\nRelatedly, in the case of bare designators, IDEs would not be able to implement\ntab-completion using Carbon's name lookup rules, but would effectively have to\ninvent their own ad hoc name lookup rules.\n\nNote that this approach would work well with the \"Indexing by type\" alternative\ndiscussed below, with instances of `DesignatedTuple` (or whatever we call it)\nacting as tagged wrapper types.\n\n## Distinguishing pattern and expression semantics\n\nAs discussed above, we expect a well-behaved sum type to define factory\nfunctions that correspond to each of the alternatives in its continuation\ninterface. This creates some potential ambiguity about whether a given use of an\nalternative name refers to the factory function or the continuation interface.\nFor example, consider the following code:\n\n```\nvar Result(Int, String): r = ...;\nmatch (r) {\n  case Result(Int, String).Value(0) => ...\n```\n\nThis could potentially be interpreted two ways:\n\n-   `Result(Int, String).Value(0)` is evaluated as an ordinary function call,\n    and the result is compared with `r` to see if they match, presumably using\n    the `==` operator.\n-   The whole `match` expression is evaluated by invoking\n    `Result(Int, String)`'s implementation of `Matchable`, with a continuation\n    object whose `.Value(Int)` method compares the `Int` parameter with 0.\n\nThis can also be thought of as a name lookup problem: is `.Value` looked up in\n`Result(Int, String)`, or in `Result(Int, String)`'s implementation of\n`Matchable`?\n\nI propose to leave this choice unspecified, so that the compiler may validly\ngenerate code either way. This gives the compiler more freedom to optimize, and\nperhaps more importantly, it helps discourage sum type authors from\nintentionally making its factory function behavior inconsistent with its pattern\nmatching behavior. By extension, I propose treating the shorthand syntax\n`case .Value(0)` the same way.\n\n### Alternatives considered\n\n#### Separate syntaxes\n\nWe could instead avoid the ambiguity by providing separate syntaxes for the two\nsemantics. The more straightforward version of this would be to say that\n`Result(Int, String).Value(0)` is always interpreted as an ordinary function\ncall, and patterns like `Result(Int, String).Value(Int: i)` are ill-formed\nbecause they cannot be interpreted as function calls. However, this would\nrequire us to have a syntax for matching alternatives that is disjoint from the\nsyntax for constructing alternatives. This would be at odds with existing\npractice in languages like Rust, Swift, Haskell, and ML, all of which use the\nsame syntax for constructing and matching alternatives.\n\nNote that it is tempting to use bare designators as the syntax for matching\nalternatives, so that `Result(Int, String).Value(0)` is an expression, but\n`.Value(0)` is a pattern. However, that is unlikely to be sufficient on its own,\nbecause bare designators rely on type information that may not always be\navailable, especially in nested patterns. Hence, in order for this approach to\nwork, we would need to introduce a separate syntax for specifying the type of a\nbare designator, such as `.Value(0) as Result(Int, String)`.\n\nAlternatively, we could say that code in a pattern-matching context is always\ninterpreted as a pattern, even if it could otherwise be interpreted as an\nexpression. We would then need to introduce a pattern operator for explicitly\nevaluating a subpattern as an expression, such as\n`is Result(Int, String).Value(0)` or `== Result(Int, String).Value(0)`. However,\nthis would impose an educational and cognitive burden on users: FAQ entries like\n\"What's the difference between `case .Foo` and `case is .Foo`\" and \"How do I\nchoose between `case .Foo` and `case is .Foo`\" seem inevitable, and would\nrequire fairly nuanced answers. It would also add syntactic noise to the use\ncases that correspond to C++ `switch` statements, where all of the cases are\nfixed values.\n\n#### Disambiguation by fixed priority\n\nWe could instead specify that, when `Result(Int, String).Value(0)` appears in a\ncontext where a pattern is expected, the name `.Value` is looked up as both an\nordinary function call and as a use of the `Matchable` interface, and specify\none of the two as the \"winner\" in the case where both lookups succeed. This is\neffectively a variant of the previous option, except that some usages that would\nbe build errors under that approach would be saved by the fallback\ninterpretation here. In particular, it would still require us to introduce a\nsecond syntax for the case where the programmer wants the lower-priority of the\ntwo behaviors. Thus, it would carry largely the same drawbacks as the previous\noption, with the additional drawback that there wouldn't be a consistent\ncorrespondence between syntax and semantics.\n\n#### Disambiguation based on pattern content\n\nWe could instead specify that `Result(Int, String).Value(0)` is always\ninterpreted as an ordinary function call, but patterns like\n`Result(Int, String).Value(Int: i)` are evaluated using the `Matchable`\ninterface, because no other implementation is possible. However, this would mean\nthat the name-lookup behavior of a function call depends on code that can be\narbitrarily deeply nested within it, which seems likely to be hostile to both\nprogrammers and tools.\n\n## Choice types\n\nTo allow users to define sum types without micromanaging the implementation\ndetails, I propose introducing `choice` as a convenient syntax for defining a\nsum type by specifying only the declarations of the set of alternatives. From\nthat information, the compiler generates an appropriate object representation,\nand synthesizes definitions for the alternatives and special member functions.\n\nOur manual implementation of `Result` above doesn't really benefit from having\ndirect control of the object representation, and doesn't seem to have any\nadditional API surfaces, so it's well-suited to being defined as a choice type\ninstead:\n\n```\nchoice Result(Type:$$ T, Type:$$ Error) {\n  Success(T: value),\n  Failure(Error: error),\n  Cancelled\n}\n```\n\nThe body of a `choice` type definition consists of a comma-separated list of\nalternatives. These have the same syntax as a function declaration, but with\n`fn` and the return type omitted. If there are no arguments, the parentheses may\nalso be omitted, as with `Cancelled`. `default` may also be included in the\nlist, with the same meaning as `operator default` in a continuation interface:\nit means that pattern-matching operations on this type must be prepared to\nhandle alternatives other than those explicitly listed.\n\nThe choice type will have a static factory function corresponding to each of the\nalternatives with parentheses, and a static data member corresponding to each\nalternative with no parentheses. The choice type will also implement the\n`Matchable` interface, and its continuation interface will have a method\ncorresponding to each alternative.\n\nIn short, this definition of `Result` as a choice type will have the same\nsemantics as the earlier definition of it as a struct. It will probably also\nhave the same implementation, with a discriminator field and a storage buffer\nlarge enough to hold the argument values of the alternatives. Any alternative\nparameter types that are incomplete (or have unknown size for any other reason)\nwill be represented using owning pointers; among other things, this will allow\nusers to define recursive choice types. The implementation will be hidden, of\ncourse, and the compiler may be able to generate better code, but we will design\nthis feature to support at least that baseline implementation strategy.\n\nOne consequence is that although the alternatives of a choice type can be\noverloaded (as in the `Variant` example below), they cannot be templates. More\nprecisely, the parameter types of a pattern function must be fixed without\nknowing the values of any of the arguments. To see why, consider a choice type\nlike the following, which attempts to emulate `std::any`:\n\n```\nchoice Any {\n  Value[Type:$$ T](T: value)\n}\n```\n\nThe problem is that since `T` could be any type, and a single `Any` object could\nhold values of different types throughout its lifetime, `Any` can't be\nimplemented using a storage buffer within the `Any` object. Instead, the storage\nbuffer for the `T` object would have to be allocated on the heap, but then the\ncompiler would need to decide whether to apply a small buffer optimization, and\nif so what size threshold to use, etc. Allowing choice types to be implemented\nin terms of heap allocation would make their performance far less predictable,\ncontrary to Carbon's performance goals, and would have little offsetting\nbenefit: these sorts of types appear to be rare, and when needed they should be\nimplemented in library code, where the performance tradeoffs are explicit and\nunder programmer control.\n\nIt may be possible to relax this restriction when and if we have a design for\nsupporting non-fixed-size types, although it's worth noting that even that would\nnot give us a way for `Any` to support assignment.\n\nCarbon will probably have some mechanism for allowing a struct to have\ncompiler-generated default implementations of operations such as copy, move,\nassignment, hashing, and equality comparison, so long as the struct's members\nsupport those operations. Assuming that mechanism exists, choice types will\nsupport it as well, with the parameter types of the pattern functions taking the\nplace of the member types. However, there are a couple of special cases:\n\n-   choice types cannot be default constructible, unless we provide a separate\n    mechanism for specifying which alternative is the default.\n-   choice types can be assignable, regardless of whether the parameter types\n    are assignable, because assigning to a choice type always destroys the\n    existing alternative, rather than assigning to it.\n\nA future proposal for this mechanism will need to consider whether to require an\nexplicit opt-in to generate these operations.\n\n**Open question:** Should `choice` provide a way to directly access the\ndiscriminator? Correspondingly, should it provide a way to specify the\ndiscriminator type, and which discriminator values correspond to which\nalternatives? These features would enable choice types to support all the same\nuse cases as C++ `enum`s, and permit zero-overhead conversion between the two at\nlanguage boundaries.\n\n### Alternatives considered\n\n#### Different spelling for `choice`\n\nThe Rust and Swift counterparts of `choice` are spelled `enum`. I have avoided\nthis because these types are not really \"enumerated types\" in the sense of all\nvalues being explicitly enumerated in the code. I chose the spelling `choice`\nbecause \"choice type\" is one of the only available synonyms for \"sum type\" that\ndoesn't have any potentially-misleading associations.\n\n## Alternatives considered\n\n### `choice` types only\n\nRather than layering `choice` types on top of lower level features, we could\nmake them a primitive language feature, and simply not provide a way for user\ncode to customize the representation of sum types. However, this would mean that\nusers who encounter performance problems with the compiler-generated code for a\n`choice` type would have no way to address those problems without rewriting all\ncode that uses that type. This would be contrary to Carbon's performance and\nevolvability goals. Furthermore, the rewritten code would probably be\nsubstantially less readable, and less safe, because it wouldn't be able to use\npattern matching.\n\n### Indexing by type\n\nRather than requiring each alternative to have a distinct name (or at least a\ndistinct function signature), we could pursue a design that requires each\nalternative to have a distinct type. With this approach, which I'll call\n\"type-indexed\" as opposed to \"name-indexed\", Carbon sum types would much more\nclosely resemble C++'s `std::variant`, rather than Swift and Rust's `enum` or\nthe sum types of various functional programming languages.\n\nEither approach can be emulated in terms of the other. For example, we don't yet\nhave enough of a design for variadics to give an example of a Carbon counterpart\nfor `std::variant<Ts...>`, but a variant with exactly three alternative types\ncould be written like so:\n\n```\nchoice Variant(Type:$$ T1, Type:$$ T2, Type:$$ T3) {\n  Value(T1: value),\n  Value(T2: value),\n  Value(T3: value)\n}\n```\n\nConversely a type-indexed type like `std::variant` can model a name-indexed type\nlike `Result(T,E)` by introducing a wrapper type for each name, leading to\nsomething like `std::variant<Value<T>, Error<E>, Cancelled>` (note that\n`std::variant<T,E>` would not work, because `T` and `E` can be the same type).\nIn either case, emulating the other model introduces some syntactic overhead:\nwith name-indexing, `Variant`'s factory functions must be given a name (`Value`)\neven though it doesn't really convey any information, and emulating\n`Result(T,E)` in terms of type-indexing requires separately defining the tagged\nwrapper templates `Value` and `Error`.\n\nThe distinction between these two models of sum types seems analogous the\ndistinction between the tuple and struct models of product types. Tuples and\ntype-indexed sum types treat the data structurally, in terms of types and\npositional indices, but structs and name-indexed sum types require the\ncomponents of the data to have names, which contributes to both readability and\ntype-safety by attaching higher-level semantics to the data.\n\nIt is possible that both models of sum types could coexist in Carbon, just as\nstructs and tuples do. However, that seems unlikely to be a good idea: the\ncoexistence of tuples and structs is necessitated by the fact that it is quite\ndifficult to emulate either of them in terms of the other in a type-safe way,\nbut as we've seen, it's fairly straightforward to emulate either model of sum\ntypes in terms of the other.\n\nUse cases that work best with type-indexing appear to be quite rare, just as use\ncases for tuples appear to be quite rare compared to use cases for structs.\nConsequently, if Carbon has only one form of sum types, it should probably be\nthe name-indexed form, as proposed here.\n\n> **Open question:** Should Carbon have a native syntax for pattern matching on\n> the dynamic type of an object? If so, should types like `Variant` be able to\n> use it, instead of having the `.Value` boilerplate in every pattern? Should\n> this mechanism be aware of subtype relationships (so that a subtype pattern is\n> a better match than a supertype pattern)? If so, how are those subtype\n> relationships defined?\n\n### Pattern matching proxies\n\nAs a variant of the previous approach, we could allow types to specify their\npattern-matching behavior in terms of a proxy type that Carbon \"natively\" knows\nhow to pattern-match against. In the case of a sum type, this proxy would be a\n`choice` type, which means that `choice` needs to be a fundamental part of the\nlanguage, rather than syntactic sugar for a sum type struct. Returning once more\nto the `Result` example:\n\n```\nstruct Result(Type:$$ T, Type:$$ Error) {\n  // Data members, factories, and special members same as above\n\n  choice Choice {\n    Success(T: value),\n    Failure(Error: error),\n    Cancelled\n  }\n\n  fn operator match(Ptr(Self): this) -> Choice {\n    match (discriminator) {\n      case 0 => {\n        return .Success(this->storage.Read(T));\n      }\n      case 1 => {\n        return .Failure(this->storage.Read(Error));\n      }\n      case 2 => {\n        return .Cancelled;\n      }\n      default => {\n        Assert(False);\n      }\n    }\n  }\n}\n```\n\nThis approach has several advantages:\n\n-   It's somewhat simpler, because it uses return values instead of\n    continuation-passing.\n-   It will be easier for the compiler to reason about, because of that\n    simplicity and the somewhat narrower API surface. This may lead to better\n    compiler performance, and better generated code.\n-   It could generalize more easily to allow things like user-defined types that\n    can match list patterns (if Carbon has those).\n\nHowever, it also has several drawbacks:\n\n-   It forces us to treat `choice` as a fundamental part of the language: in\n    order to implement a sum type, you have to work with an object type whose\n    layout and implementation is inherently opaque. This would be a substantial\n    departure from C++, and it's difficult to foresee the consequences of that.\n    Possibly the closest analogy in C++ is virtual calls, and especially virtual\n    base classes, where fundamental operations like `->` and pointer casts can\n    involve nontrivial generated code, and some aspects of object layout are\n    required to be hidden from the user. However, Carbon seems to be moving away\n    from C++ in precisely those ways.\n-   Although both approaches carry a risk of confusion due to duplicate names,\n    the risk is somewhat greater here: a naive reader might think that, for\n    example, `.Success` in the body of `operator match` refers to `Self.Success`\n    rather than `Self.Choice.Success`. Relatedly, there's some risk that the\n    author may omit the leading `.`, and thereby invoke `Self.Success` instead\n    of `Self.Choice.Success`. This will probably fail to build, but the errors\n    may be confusing.\n-   It has less expressive power, because there's no straightforward way for the\n    library type to specify code that should run after pattern matching is\n    complete. For example, the callback approach could allow `Match` to create a\n    mutable local variable, pass it to the callback by pointer/reference, and\n    then write the (possibly modified) contents of the variable back into the\n    sum type object.\n-   Extending this approach to support in-place mutation during pattern matching\n    is likely to require Carbon to support reference _types_, whereas the\n    primary proposal would probably only require reference _patterns_, which are\n    substantially less problematic. This is a consequence of using a return type\n    rather than a set of callback parameters (which are patterns) to define the\n    type's pattern matching interface.\n\nI very tentatively recommend the callback approach rather than this one,\nprimarily because of the last point above: the Carbon type system is likely to\nbe dramatically simplified if there are no reference types, but I think the\nproxy approach will make reference types all but unavoidable.\n\n### Pattern functions\n\nRather than require user types to define both the pattern-matching logic and the\nfactory functions, with the expectation that they will be inverses of each\nother, we could instead enable them to define the set of alternatives as factory\nfunctions that the compiler can invert automatically. This approach, like the\nprimary proposal, would consist of several parts.\n\nA _pattern function_ is a function that can be invoked as part of a pattern,\neven with arguments that contain placeholders. Pattern functions use the\nintroducer `pattern` instead of `fn`, and can only contain the sort of code that\ncould appear directly in a pattern. This lets us define reusable pattern\nsyntaxes that can do things like encapsulate hidden implementation details of\nthe object they're matching.\n\nNext, we would introduce the concept of an `alternatives` block, which groups\ntogether a set of factory functions and designates them as a set of\nalternatives. They are required to be both exhaustive and unambiguous, meaning\nthat for any possible value of the type, it must be possible to obtain it as the\nreturn value of exactly one of the alternatives. Alternatives that take no\narguments, which represent singleton states such as `Cancelled`, can instead be\nwritten as static constants. An `alternatives` block can be marked `closed`,\nwhich plays the same role as omitting `operator default` in the primary\nproposal: it indicates that client code need not be prepared to accept\nalternatives other than the ones currently present.\n\nAs with the primary proposal, `Storage` is used to represent a span of memory\nthat the user can create objects within. However, with this approach we also\nneed it to support initialization from a `ToStorage` factory function, because\npattern functions can't contain procedural code. Note that for the same reason,\n`ToStorage` will probably need to be a language intrinsic, or implemented in\nterms of one.\n\nUsing these features, the `Result(T, Error)` example can be written as follows:\n\n```\nstruct Result(Type:$$ T, Type:$$ Error) {\n  var Int: discriminator;\n\n  var Storage(Max(Sizeof(T), Sizeof(Error)),\n              Max(Alignof(T), Alignof(Error))): storage;\n\n  closed alternatives {\n    pattern Success(T: value) -> Self {\n      return (.discriminator = 0, .storage = ToStorage(value));\n    }\n\n    pattern Failure(Error: error) -> Self {\n      return (.discriminator = 1, .storage = ToStorage(error));\n    }\n\n    var Self:$$ Cancelled = (.discriminator = 2);\n  }\n}\n```\n\nNotice that with this approach, we do not need to define the special member\nfunctions of `Result` manually. The compiler can infer appropriate definitions\nin the same way that it infers how to invert these functions during pattern\nmatching.\n\nAs with the primary proposal, `choice` would be available as syntactic sugar,\nbut its syntax would mirror the syntax of an `alternatives` block:\n\n```\nclosed choice Result(Type:$$ T, Type:$$ Error) {\n  pattern Success(T: value) -> Self;\n  pattern Failure(Error: error) -> Self;\n  var Self:$$ Cancelled;\n}\n```\n\nThis ensures that a sum type's API is defined using essentially the same syntax,\nregardless of how the type author chooses to implement it.\n\nThis approach is described in much more detail in an\n[earlier draft](https://github.com/carbon-language/carbon-lang/blob/4dbd31d71e02895892f97a211df4b5fff8cae5c3/proposals/p0157.md)\nof this document, where it was the primary proposal. It has a number of\nadvantages over the primary proposal:\n\n-   Manually-defined sum types could probably be implemented with dramatically\n    less code, because both the special member functions and the code that\n    implements pattern matching can be generated automatically. This would not\n    only make these types less tedious to implement, it would probably also\n    reduce the risk of bugs, and avoid readability problems arising from the\n    duplication of names between factory functions and continuation interface\n    methods.\n-   Programmers would be able to define functions that encapsulate complex\n    pattern-matching logic behind simple interfaces.\n-   Pattern matching would not require the special overload resolution rules\n    that are needed to translate a pattern-matching operation into a `Match`\n    call.\n-   User-defined sum types would default to being open, whereas they default to\n    being closed under the primary proposal. This is probably a better default,\n    because an open sum type can always be closed, but a closed sum type can't\n    be opened (much less extended with new alternatives) without the risk of\n    breaking user code.\n\nHowever, this approach also carries some substantial drawbacks:\n\n-   Types can't use the full power of the Carbon language when defining their\n    pattern-matching behavior, or the corresponding factory functions. Instead,\n    they are restricted to a very narrow subset of the language that is valid in\n    both patterns and procedural code. This forces us to introduce intrinsics\n    like `ToStorage` to make that subset even minimally usable, and creates a\n    substantial risk that some user-defined sum types just won't be able to\n    support pattern matching.\n-   The language rules are substantially more complicated and harder to explain,\n    because we need to define the language subset that is usable in pattern\n    functions, and define both \"forward\" and \"reverse\" semantics for it.\n    Relatedly, it means that during pattern matching, there will be no\n    straightforward correspondence between the Carbon code and the generated\n    assembly, which could substantially complicate things like debugging.\n-   Carbon's pattern language can't allow you to write _underconstrained_\n    patterns, which are patterns where the values of all bindings aren't\n    sufficient to uniquely determine the state of the object being matched. This\n    rules out things like the `|` pattern operator, and even prevents us from\n    using pattern matching with types that have non-salient state, like the\n    capacity of a `std::vector`.\n\nThese issues, especially the overall complexity of this approach, leads me to\nrecommend against adopting it.\n\n## Rationale\n\nThis proposal gives us solid ground on which to continue developing features\nthat rely on sum types and pattern matching thereof. The approach taken seems\nplausible, and while there's a good chance that we will revise it significantly\nbefore we finish our first pass over the complete Carbon design (for example, by\nswitching to pattern matching proxies or by supporting mutation of matched\nelements), we don't think it will anchor us too much on this one particular\ndirection.\n\nWith regard to Carbon's goals:\n\n-   Performance: while the approach taken herein potentially has some\n    performance cost for a common operation that is likely to appear in\n    performance-critical code (requiring an indirect call and the generation of\n    continuations for user-defined pattern matching), such cost should be\n    practically removable by inlining. We'll need to take care to ensure this\n    abstraction penalty is reliably removed in common cases, but this seems\n    sufficiently feasible to be worth attempting.\n-   Evolution: software evolution is supported by allowing user-defined pattern\n    matching to specify (by way of the presence/absence of operator default)\n    whether the set of patterns is intended to be extended in the future.\n-   Ergonomics: custom pattern matching for user-defined types promotes language\n    consistency and removes boilerplate\n\nNote: At the decision meeting, it was stated that geoffromer will update the\nproposal to add a rationale to address austern's questions about the layered\napproach.\n"
  },
  {
    "path": "proposals/p0162.md",
    "content": "# Basic Syntax\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/162)\n\n## Table of contents\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Expressions and Patterns](#expressions-and-patterns)\n    -   [Statements](#statements)\n    -   [Declarations](#declarations)\n    -   [Precedence and Associativity](#precedence-and-associativity)\n    -   [Abstract Syntax](#abstract-syntax)\n        -   [Abstract Syntax for Expressions](#abstract-syntax-for-expressions)\n        -   [Abstract Syntax for Statements](#abstract-syntax-for-statements)\n        -   [Abstract Syntax for Declarations](#abstract-syntax-for-declarations)\n-   [Alternatives considered](#alternatives-considered)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Problem\n\nThe purpose of this proposal is to establish some basic syntactic elements of\nthe Carbon language and make sure that the grammar is unambiguous and can be\nparsed by an LALR parser such as `yacc` or `bison`. The grammar presented here\nhas indeed been checked by `bison`. The language features in this basic grammar\ninclude control flow by way of `if` and `while`, functions, simple structures,\nchoice, pattern matching, and a sample of operators on Booleans and integers.\nThe main syntactic categories are `declaration`, `statement`, and `expression`.\nEstablishing these syntactic categories should help the other proposals choose\nsyntax that is compatible with the rest of the language.\n\n## Background\n\nThe grammar proposed here is based on the following proposals:\n\n-   [Carbon language overview](https://github.com/carbon-language/carbon-lang/tree/trunk/docs/design)\n-   pattern matching\n    [#87](https://github.com/carbon-language/carbon-lang/pull/87),\n-   structs [#98](https://github.com/carbon-language/carbon-lang/pull/98),\n-   tuples [#111](https://github.com/carbon-language/carbon-lang/pull/111),\n-   sum types [#157](https://github.com/carbon-language/carbon-lang/pull/157),\n    and\n-   metaprogramming\n    [#89](https://github.com/carbon-language/carbon-lang/pull/89).\n\n## Proposal\n\nWe summarize the four main syntactic categories here and define the grammar in\nthe next section.\n\n-   `declaration` includes function, structure, and choice definitions.\n\n-   `statement` includes local variable definitions, assignment, blocks, `if`,\n    `while`, `match`, `break`, `continue`, and `return`.\n\n-   `expression` includes function calls, arithmetic, literals, and other\n    syntaxes that evaluate to a value. In Carbon, a type is a kind of value, and\n    Carbon makes no syntactic distinction between type-valued expressions and\n    other kinds of expressions, so the `expression` nonterminal is used in\n    positions where a type is expected.\n\n-   `pattern` for the patterns in a `match` statement, for the left-hand side of\n    a variable definition, and for describing the parameters of a function. The\n    grammar treats patterns and expressions identically, but the type system\n    will only allow pattern variables (`expression ':' identifier`) in patterns\n    and not in value or type-producing expressions. Having the separate\n    non-terminals for `pattern` and `expression` helps to document this\n    distinction.\n\nThe proposal also specifies the abstract syntax.\n\nWhen this proposal is accepted, the accompanying `flex`, `bison`, and C++ files\nthat define the grammar and implement the parser actions will be placed in the\n`executable_semantics` directory of the `carbon-lang` repository.\n\nIn the near future there will be proposals regarding the semantic analysis (aka.\ntype checking) and specification of runtime behavior for this subset of Carbon\nwith the plan to add the accompanying executable forms of those specifications\nto the `executable_semantics` directory.\n\nLooking towards growing the Carbon language, the intent is for other proposals\nto add to this grammar by modifying the `flex` and `bison` files and the\nabstract syntax definitions in the `executable_semantics` directory.\n\n## Details\n\n### Expressions and Patterns\n\nThe following grammar defines the concrete syntax for expressions. Below we\ncomment on a few aspects of the grammar.\n\n```Bison\npattern:\n  expression\n;\nexpression:\n  identifier\n| expression designator\n| expression '[' expression ']'\n| expression ':' identifier\n| integer_literal\n| \"true\"\n| \"false\"\n| tuple\n| expression \"==\" expression\n| expression '+' expression\n| expression '-' expression\n| expression \"and\" expression\n| expression \"or\" expression\n| \"not\" expression\n| '-' expression\n| expression tuple\n| \"auto\"\n| \"fnty\" tuple return_type\n;\ndesignator:\n  '.' identifier\n;\ntuple:\n  '(' field_list ')'\n;\nfield_list:\n  /* empty */\n| field\n| field ',' field_list\n;\nfield:\n  pattern\n| designator '=' pattern\n;\nreturn_type:\n  /* empty */\n| \"->\" expression\n;\n```\n\nThe grammar rule\n\n```Bison\nexpression:  expression ':' identifier\n```\n\nis for pattern variables. For example, in a variable definition such as\n\n    var Int: x = 0;\n\nthe `Int: x` is parsed with the grammar rule for pattern variables. In the\nright-hand side of the above grammar rule, the `expression` to the left of the\n`:` must evaluate to a type at compile time.\n\nThe grammar rule\n\n```Bison\nexpression:  \"fnty\" tuple return_type\n```\n\nis for function types. They are meant to play the role that function pointers\nplay in C and that `std::function` plays in C++.\n\nRegarding the grammar rule for the return type of a function:\n\n```Bison\nreturn_type:  \"->\" expression\n```\n\nthe `expression` is expected to evaluate to a type at compile-time.\n\nThe grammar rule\n\n```Bison\ntuple:  '(' field_list ')'\n```\n\nis primarily for constructing a tuple, but it is also used for creating tuple\ntypes and tuple patterns, depending on the context in which the expression\noccurs.\n\nRegarding the grammar rules for `designator` and for a named argument\n\n```Bison\ndesignator: '.' identifier\nfield: designator '=' pattern\n```\n\nThe period enables the addition of new keywords to Carbon without colliding with\nfield names. The period also aids integrated development environments with\nauto-completion. The issue is that without the period, when the programmer is\ntyping the identifier (and not yet typed the `=`), the IDE doesn't know whether\nthe identifier is for a positional argument, in which case it is a variable\noccurrence, or whether the identifier is a field name.\n\n### Statements\n\nThe following grammar defines the concrete syntax for statements.\n\n```Bison\nstatement:\n  \"var\" pattern '=' expression ';'\n| expression '=' expression ';'\n| expression ';'\n| \"if\" '(' expression ')' statement \"else\" statement\n| \"while\" '(' expression ')' statement\n| \"break\" ';'\n| \"continue\" ';'\n| \"return\" expression ';'\n| '{' statement_list '}'\n| \"match\" '(' expression ')' '{' clause_list '}'\n;\nstatement_list:\n  /* empty */\n| statement statement_list\n;\nclause_list:\n  /* empty */\n| clause clause_list\n;\nclause:\n  \"case\" pattern \"=>\" statement\n| \"default\" \"=>\" statement\n;\n```\n\n### Declarations\n\nThe following grammar defines the concrete syntax for declarations.\n\n```Bison\ndeclaration:\n  \"fn\" identifier tuple return_type '{' statement_list '}'\n| \"fn\" identifier tuple \"=>\" expression ';'\n| \"fn\" identifier tuple return_type ';'\n| \"struct\" identifier '{' member_list '}'\n| \"choice\" identifier '{' alternative_list '}'\n;\nmember:\n  \"var\" expression ':' identifier ';'\n;\nmember_list:\n  /* empty */\n| member member_list\n;\nalternative:\n  identifier tuple ';'\n;\nalternative_list:\n  /* empty */\n| alternative alternative_list\n;\ndeclaration_list:\n  /* empty */\n| declaration declaration_list\n;\n```\n\nIn the grammar rule for function definitions\n\n```Bison\ndeclaration:  \"fn\" identifier tuple return_type '{' statement_list '}'\n```\n\nthe `tuple` is used as a pattern to describe the parameters of the function. The\ngrammar for function definitions does not currently include\n[implicit parameters](/docs/design/generics/terminology.md#deduced-parameter),\nbut the intent is to add them to the grammar in the future.\n\nIn the rule for field declarations\n\n```Bison\nmember:  \"var\" expression ':' identifier ';'\n```\n\nthe `expression` must evaluate to a type at compile time. The same is true for\nthe `tuple` in the grammar rule for an alternative:\n\n    alternative:  identifier tuple ';'\n\n### Precedence and Associativity\n\nThe following precedence and associativity specification is meant to approximate\nthe definitions in the operators and precedence proposal\n[#168](https://github.com/carbon-language/carbon-lang/pull/168) to the extent\nthat is possible in a `yacc`/`bison` generated parser. The ordering is from\nlowest to highest precedence, with operators on the same line having equal\nprecedence. Proposal 168 differs in that the operator groups are partially\nordered instead of being totally ordered.\n\n    nonassoc '{' '}'\n    nonassoc ':' ','\n    left \"or\" \"and\"\n    nonassoc \"==\" \"not\"\n    left '+' '-'\n    left '.' \"->\"\n    nonassoc '(' ')' '[' ']'\n\n### Abstract Syntax\n\nThe output of parsing is an abstract syntax tree. There are many ways to define\nabstract syntax. Here we simply use C-style `struct` definitions. The definition\nof the abstract syntax is important because it is used in the specification of\nthe semantic analysis and the specification of runtime behavior.\n\n#### Abstract Syntax for Expressions\n\n```c++\nenum ExpressionKind { Variable, PatternVariable, Int, Bool,\n                      PrimitiveOp, Call, Tuple, Index, GetField,\n                      IntT, BoolT, TypeT, FunctionT, AutoT };\nenum Operator { Neg, Add, Sub, Not, And, Or, Eq };\n\nstruct Expression {\n  ExpressionKind tag;\n  union {\n    struct { string* name; } variable;\n    struct { Expression* aggregate; string* field; } get_field;\n    struct { Expression* aggregate; Expression* offset; } index;\n    struct { string* name; Expression* type; } pattern_variable;\n    int integer;\n    bool boolean;\n    struct { vector<pair<string,Expression*> >* fields; } tuple;\n    struct {\n      Operator operator_;\n      vector<Expression*>* arguments;\n    } primitive_op;\n    struct { Expression* function; Expression* argument; } call;\n    struct { Expression* parameter; Expression* return_type;} function_type;\n  } u;\n};\n```\n\nThe correspondence between most of the grammar rules and the abstract syntax is\nstraightforward. However, the parsing of the `field_list` deserves some\nexplanation. The fields can be labeled with the grammar rule:\n\n```Bison\nfield:  designator '=' pattern\n```\n\nor unlabeled, with the rule\n\n```Bison\nfield: pattern\n```\n\nThe unlabeled fields are given numbers (represented as strings) for field\nlabels, starting with 0 and going up from left to right.\n\nRegarding the rule for tuples:\n\n```Bison\ntuple:  '(' field_list ')'\n```\n\nif the field list only has a single unlabeled item without a trailing comma,\nthen the parse result for that item is returned. Otherwise a `tuple` AST node is\ncreated containing the parse results for the fields.\n\nIn the following grammar rules, if the parse result for `tuple` is not a tuple\n(because the field list was a single unlabeled item without a trailing comma),\nthen a tuple is wrapped around the expression to ensure that it is a tuple.\n\n```Bison\nexpression: expression tuple\nexpression: \"fnty\" tuple return_type\nfunction_definition:\n  \"fn\" identifier tuple return_type '{' statement_list '}'\n| \"fn\" identifier tuple DBLARROW expression ';'\n| \"fn\" identifier tuple return_type ';'\nalternative: identifier tuple ';'\n```\n\n#### Abstract Syntax for Statements\n\n```c++\nenum StatementKind { ExpressionStatement, Assign, VariableDefinition,\n                     If,  Return, Sequence, Block, While, Break, Continue,\n                     Match };\n\nstruct Statement {\n  StatementKind tag;\n  union {\n    Expression* exp;\n    struct { Expression* lhs; Expression* rhs; } assign;\n    struct { Expression* pat; Expression* init; } variable_definition;\n    struct { Expression* cond; Statement* then_; Statement* else_; } if_stmt;\n    Expression* return_stmt;\n    struct { Statement* stmt; Statement* next; } sequence;\n    struct { Statement* stmt; } block;\n    struct { Expression* cond; Statement* body; } while_stmt;\n    struct {\n      Expression* exp;\n      list< pair<Expression*,Statement*> >* clauses;\n    } match_stmt;\n  } u;\n};\n```\n\n#### Abstract Syntax for Declarations\n\n```c++\nstruct FunctionDefinition {\n  string name;\n  Expression* param_pattern;\n  Expression* return_type;\n  Statement* body;\n};\n\nenum MemberKind { FieldMember };\n\nstruct Member {\n  MemberKind tag;\n  union {\n    struct { string* name; Expression* type; } field;\n  } u;\n};\n\nstruct StructDefinition {\n  string* name;\n  list<Member*>* members;\n};\n\nenum DeclarationKind { FunctionDeclaration, StructDeclaration,\n                       ChoiceDeclaration };\n\nstruct Declaration {\n  DeclarationKind tag;\n  union {\n    struct FunctionDefinition* fun_def;\n    struct StructDefinition* struct_def;\n    struct {\n      string* name;\n      list<pair<string, Expression*> >* alts;\n    } choice_def;\n  } u;\n};\n```\n\n## Alternatives considered\n\nExpressions, type expressions, and patterns could instead be defined using\ncompletely disjoint grammar productions, but that would require adding more\nkeywords or symbols to avoid ambiguity and there would be a fair amount of\nrepetition in grammar productions.\n\nThe proposal does not include declarations for uninitialized variables, leaving\nthat to a later proposal.\n\nIn this proposal, assignment is a statement. It could instead be an expression\nas it is in C and C++. The arguments against assignment-as-an-expression\ninclude 1) it complicates reasoning about the ordering of side-effects and 2) it\ncan cause confusion between `=` and `==`\n[(SEI CERT C Coding Standard)](https://wiki.sei.cmu.edu/confluence/display/c/EXP45-C.+Do+not+perform+assignments+in+selection+statements)\n[Visual Studio Warning](https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-4-c4706?view=vs-2019).\n\nThe syntax for variable initialization uses `=`, which is the same token used in\nassignment. An alternative would be to use a different syntax such as `:=` to\nbetter signal the semantic differences between initialization and assignment.\nThe author does not have a preference on this choice. The `:=` alternative does\nnot introduce any complications regarding ambiguity despite the other uses of\n`:` in the grammar.\n\nInside a `choice`, an `alternative` could instead begin with a keyword such as\n`alt`, `fn`, or `var`, as discussed in the proposal for sum types\n[#157](https://github.com/carbon-language/carbon-lang/pull/157). The author does\nnot have a preference in this regard.\n\nThe precedence for `and` and `or` are equal, following the suggestion of\nproposal [#168](https://github.com/carbon-language/carbon-lang/pull/168),\nwhereas in C++ `&&` has higher precedence than `||`.\n\nThe parameters of a function are described using the syntax of a pattern. There\ncould instead be separate syntax that is special to function parameters, as\nthere is in C++.\n\nThere are open questions regarding the design of function types, so we could\nalternatively postpone the specification of the syntax for function types. The\nchoice to include them is based on the idea that Carbon will need something that\nfills the roles of `std::function` and C-style function pointers. Also, the\nfeatures were selected for the basic syntax proposal in a way that aimed to make\nthe proposal complete in the sense that each value-oriented feature (functions,\ntuples, structures) comes with syntax for 1) creating values, 2) using values,\nand 3) a type for classifying values.\n\nThe parameters of a function type are described using the syntax for type\nexpression. There could instead be separate syntax that is special to the\nparameters of a function type, as there is in C++.\n\nThe keyword for introducing a function type is `fnty`, which is an arbitrary\nchoice. Other alternatives include `fn_type` and `fn`. The `fn` alternative\nwould conflict with future plans to use `fn` for lambda expressions. Some\ndislike of `fn_type` was voiced, which motivated the choice of `fnty`. It would\nbe nice to do without a keyword, but as the grammar currently stands, that\nintroduce ambiguity.\n\nThe `pattern` non-terminal is defined in terms of `expression`. It could instead\nbe the other way around, defining `expression` in terms of `pattern`.\n\nRegarding tuples and tuple types, this proposal follows\n[#111](https://github.com/carbon-language/carbon-lang/pull/111) in that there is\nnot a distinct syntax for tuple types. Instead, the intent is that when a tuple\nof types results from an expression in a context that expects a type, the type\nsystem will convert the tuple to a tuple type. An alternative approach has been\ndiscussed in which tuple types have a distinct syntax, such as\n`Tuple(Int, Bool)`.\n\n## Rationale\n\nUsing code to validate our specification is a really promising direction, and\nthis proposal seems like a good starting point. A reference implementation\nthat's simple enough to be part of the design iteration process should help us\nmove faster, by quickly uncovering the places where our specifications are\nambiguous, syntactically or semantically unsound, or don't give the behavior we\nexpect. In other words, it will help us keep ourselves honest, even at the\nproposal stage, which will help us avoid wasting time and effort implementing\ndesigns that turn out to be unworkable.\n\nThis can be considered as sort of a counterpart to\n[In-progress design overview #83](p0083.md), in that the design specifics are\nbeing approved in order to bootstrap the specification process. We aren't\nnecessarily adopting the specific syntax and semantics expressed by this\nproposal, and those choices will need to be presented and justified from scratch\nby future proposals.\n\nThis decision is deferring the implementation to code review. The specific\ntooling used to implement the syntax checker, such as Bison, is a detail which\nmay be changed, now or later, without requiring a proposal for core team review.\n"
  },
  {
    "path": "proposals/p0175.md",
    "content": "# C++ interoperability goals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/175)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Philosophy](#philosophy)\n    -   [Language goal influences](#language-goal-influences)\n        -   [Performance-critical software](#performance-critical-software)\n        -   [Software and language evolution](#software-and-language-evolution)\n        -   [Code that is easy to read, understand, and write](#code-that-is-easy-to-read-understand-and-write)\n        -   [Practical safety guarantees and testing mechanisms](#practical-safety-guarantees-and-testing-mechanisms)\n        -   [Fast and scalable development](#fast-and-scalable-development)\n        -   [Modern OS platforms, hardware architectures, and environments](#modern-os-platforms-hardware-architectures-and-environments)\n        -   [Interoperability with and migration from existing C++ code](#interoperability-with-and-migration-from-existing-c-code)\n    -   [Goals](#goals)\n        -   [Support mixing Carbon and C++ toolchains](#support-mixing-carbon-and-c-toolchains)\n        -   [Compatibility with the C++ memory model](#compatibility-with-the-c-memory-model)\n        -   [Minimize bridge code](#minimize-bridge-code)\n        -   [Unsurprising mappings between C++ and Carbon types](#unsurprising-mappings-between-c-and-carbon-types)\n        -   [Allow C++ bridge code in Carbon files](#allow-c-bridge-code-in-carbon-files)\n        -   [Carbon inheritance from C++ types](#carbon-inheritance-from-c-types)\n        -   [Support use of advanced C++ features](#support-use-of-advanced-c-features)\n        -   [Support basic C interoperability](#support-basic-c-interoperability)\n    -   [Non-goals](#non-goals)\n        -   [Full parity between a Carbon-only toolchain and mixing C++/Carbon toolchains](#full-parity-between-a-carbon-only-toolchain-and-mixing-ccarbon-toolchains)\n        -   [Never require bridge code](#never-require-bridge-code)\n        -   [Convert all C++ types to Carbon types](#convert-all-c-types-to-carbon-types)\n        -   [Support for C++ exceptions without bridge code](#support-for-c-exceptions-without-bridge-code)\n        -   [Cross-language metaprogramming](#cross-language-metaprogramming)\n-   [Open questions to be resolved later](#open-questions-to-be-resolved-later)\n    -   [Carbon type inheritance from non-pure interface C++ types](#carbon-type-inheritance-from-non-pure-interface-c-types)\n    -   [CRTP support](#crtp-support)\n    -   [Object lifetimes](#object-lifetimes)\n-   [Rationale](#rationale)\n    -   [Open questions](#open-questions)\n\n<!-- tocstop -->\n\n## Problem\n\n[Carbon's goals](/docs/project/goals.md) include \"Interoperability with and\nmigration from existing C++ code\". This proposal aims to provide additional\ndetail to that goal, beyond what makes sense to have in the main goals document.\n\n## Background\n\nInteroperability and migration are key to Carbon. However, performance and\nevolution are _higher_ priorities. This proposal aims to outline at what this\ninteraction of priorities should end up looking like in Carbon, as well as\nindicating a couple trade-offs that will occur.\n\nOther language interoperability layers that may offer useful examples are:\n\n-   [Java/Kotlin](https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html)\n    should be a comparable interoperability story. The languages are different,\n    but share an underlying runtime. This may be closest to the model we desire\n    for Carbon.\n\n-   [JavaScript/TypeScript](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html)\n    is similar to C/C++, where one language is essentially a subset of the\n    other, allowing high interoperability. This is an interesting reference\n    point, but we are looking at a different approach with a clearer boundary.\n\n-   [C++/Java](https://en.wikipedia.org/wiki/Java_Native_Interface) is an\n    example of requiring specialized code for the bridge layer, making\n    interoperability more burden on developers. The burden of the approach may\n    be considered to correspond to the difference in language memory models and\n    other language design choices. Regardless, the result can be considered\n    higher maintenance for developers than we want for Carbon.\n\n-   [C++/Go](https://golang.org/cmd/cgo/) is similar to C++/Java. However, Go\n    notably allows C++ bridge code to exist in the .go files, which can ease\n    maintenance of the bridge layer, and is desirable for Carbon.\n\n## Proposal\n\n### Philosophy\n\nThe C++ interoperability layer of Carbon is the section wherein a specific,\nrestricted set of C++ APIs can be expressed in a way that's callable from\nCarbon, and similar for calling Carbon from C++. This requires expressing one\nlanguage as a subset of the other. Our goal is that the constraint of\nexpressivity is loose enough that the resulting amount of bridge code is\nsustainable.\n\nThe design for interoperability between Carbon and C++ hinges on:\n\n1.  The ability to interoperate with a wide variety of code, such as\n    classes/structs and templates, not just free functions.\n2.  A willingness to expose the idioms of C++ into Carbon code, and the other\n    way around, when necessary to maximize performance of the interoperability\n    layer.\n3.  The use of wrappers and generic programming, including templates, to\n    minimize or eliminate runtime overhead.\n\nThese things come together when looking at how custom data structures in C++ are\nexposed into Carbon, and the other way around. In both languages, it is\nreasonable and even common to have customized low-level data structures, such as\nassociative containers. For example, there are numerous data structures for\nmapping from a key to a value that might be best for a particular use case,\nincluding hash tables, linked hash tables, sorted vectors, and btrees. Even for\na given data structure, there may be slow but meaningful evolution in\nimplementations strategies.\n\nThe result is that it will often be reasonable to directly expose a C++ data\nstructure to Carbon without converting it to a \"native\" or \"idiomatic\" Carbon\ndata structure. Although interfaces may differ, a trivial adapter wrapper should\nbe sufficient. Many Carbon data structures should also be able to support\nmultiple implementations with C++ data structures being one such implementation,\nallowing for idiomatic use of C++ hidden behind Carbon.\n\nThe reverse is also true. C++ code will often not care, or can be refactored to\nnot care, what specific data structure is used. Carbon data structures can be\nexposed as yet another implementation in C++, and wrapped to match C++ idioms\nand even templates.\n\nFor example, a C++ class template like `std::vector<T>` should be usable without\nwrapper code or runtime overhead, and passing a Carbon type as `T`. The\nresulting type should be equally usable from either C++ or Carbon code. It\nshould also be easy to wrap `std::vector<T>` with a Carbon interface for\ntransparent use in idiomatic Carbon code.\n\n### Language goal influences\n\n#### Performance-critical software\n\nInteroperability with C++ will be frequently used in Carbon, whether it's C++\ndevelopers trying out Carbon, incrementally migrating a large C++ codebase, or\ncontinuing to use a C++ library long-term. In all cases, it must be possible to\nwrite interoperable code with zero overhead; copies must not be required.\n\n#### Software and language evolution\n\nInteroperability will require the addition of features to Carbon which exist\nprimarily to support interoperability use cases. However, these features must\nnot unduly impinge the overall evolution of Carbon. In particular, only a subset\nof Carbon features will support interoperability with C++. To do otherwise would\nrestrict Carbon's feature set.\n\n#### Code that is easy to read, understand, and write\n\nInteroperability-related Carbon code will likely be more difficult to read than\nother, more idiomatic Carbon code. This is okay: aiming to make Carbon code\nreadable doesn't mean that it needs to _all_ be trivial to read. At the same\ntime, the extra costs that interoperability exerts on Carbon developers should\nbe minimized.\n\n#### Practical safety guarantees and testing mechanisms\n\nSafety is important to maintain around interoperability code, and mitigations\nshould be provided where possible. However, safety guarantees will be focused on\nnative Carbon code. C++ code will not benefit from the same set of safety\nmechanisms that Carbon offers, so Carbon code calling into C++ will accept\nhigher safety risks.\n\n#### Fast and scalable development\n\nThe interoperability layer will likely have tooling limitations similar to C++.\nFor example, Carbon aims to compile quickly. However, C++ interoperability\nhinges on compiling C++ code, which is relatively slow. Carbon libraries that\nuse interoperability will see bottlenecks from C++ compile time. Improving C++\nis outside the scope of Carbon.\n\n#### Modern OS platforms, hardware architectures, and environments\n\nInteroperability will apply to the intersection of environments supported by\nboth Carbon and C++. Pragmatically, Carbon will likely be the limiting factor\nhere.\n\n#### Interoperability with and migration from existing C++ code\n\nCarbon's language goal for interoperability will focus on C++17 compatibility.\nThe language design must be mindful of the prioritization; trade-offs harming\nother goals may still be made so long as they offer greater benefits for\ninteroperability and Carbon as a whole.\n\nAlthough the below interoperability-specific goals will focus on\ninteroperability, it's also important to consider how migration would be\naffected. If interoperability requires complex work, particularly to avoid\nperformance impacts, it could impair the ability to incrementally migrate C++\ncodebases to Carbon.\n\n### Goals\n\n#### Support mixing Carbon and C++ toolchains\n\nThe Carbon toolchain will support compiling C++ code. It will contain a\ncustomized C++ compiler that enables some more advanced interoperability\nfeatures, such as calling Carbon templates from C++.\n\nMixing toolchains will also be supported in both directions:\n\n-   C++ libraries compiled by a non-Carbon toolchain will be usable from Carbon,\n    so long as they are ABI-compatible with Carbon's C++ toolchain.\n\n-   The Carbon toolchain will support, as an option, generating a C++ header and\n    object file from a Carbon library, with an ABI that's suitable for use with\n    non-Carbon toolchains.\n\nMixing toolchains restricts functionality to what's feasible with the C++ ABI.\nFor example, developers should expect that Carbon templates will be callable\nfrom C++ when using the Carbon toolchain, and will not be available when mixing\ntoolchains because it would require a substantially different and more complex\ninteroperability implementation. This degraded interoperability should still be\nsufficient for most developers, albeit with the potential of more bridge code.\n\nAny C++ interoperability code that works when mixing toolchains must work when\nusing the native Carbon toolchain. The mixed toolchain support must not have\nsemantic divergence. The converse is not true, and the native Carbon toolchain\nmay have additional language support and optimizations.\n\n#### Compatibility with the C++ memory model\n\nIt must be straightforward for any Carbon interoperability code to be compatible\nwith the C++ memory model. This does not mean that Carbon must exclusively use\nthe C++ memory model, only that it must be supported.\n\n#### Minimize bridge code\n\nThe majority of simple C++ functions and types should be usable from Carbon\nwithout any custom bridge code and without any runtime overhead. That is, Carbon\ncode should be able to call most C++ code without any code changes to add\nsupport for interoperability, even if that code was built with a non-Carbon\ntoolchain. This includes instantiating Carbon templates or generics using C++\ntypes.\n\nIn the other direction, Carbon may need some minimal markup to expose functions\nand types to C++. This should help avoid requiring Carbon to generate\nC++-compatible endpoints unconditionally, which could have compile and linking\noverheads that may in many cases be unnecessary. Also, it should help produce\nerrors that indicate when a function or type may require additional changes to\nmake compatible with C++.\n\nOur priority is that Carbon developers should be able to easily reuse the mature\necosystem of C++ libraries provided by third-parties. A third-party library's\nlanguage choice should not be a barrier to Carbon adoption.\n\nEven for first-party libraries, migration of C++ codebases to Carbon will often\nbe incremental due to human costs of executing and verifying source migrations.\nMinimizing the amount of bridge code required should be expected to simplify\nsuch migrations.\n\n#### Unsurprising mappings between C++ and Carbon types\n\nCarbon will provide unsurprising mappings for common types.\n\n**Primitive types** will have mappings with zero overhead conversions. They are\nfrequently used, making it important that interoperability code be able to use\nthem seamlessly.\n\nThe storage and representation will need to be equivalent in both languages. For\nexample, if a C++ `__int64` maps to Carbon's `Int64`, the memory layout of both\ntypes must be identical.\n\nSemantics need to be similar, but edge-case behaviors don't need to be\nidentical, allowing Carbon flexibility to evolve. For example, where C++ would\nhave modulo wrapping on integers, Carbon could instead have trapping behavior on\nthe default-mapped primitive types.\n\nCarbon may have versions of these types with no C++ mapping, such as `Int256`.\n\n**Non-owning vocabulary types**, such as pointers and references, will have\ntransparent, automatic translation between C++ and Carbon non-owning vocabulary\ntypes with zero overhead.\n\n**Other vocabulary types** will typically have reasonable, but potentially\nnon-zero overhead, conversions available to map into Carbon vocabulary types.\nCode using these may choose whether to pay the overhead to convert. They may\nalso use the C++ type directly from Carbon code, and the other way around.\n\n**Incomplete types** must have a mapping with similar semantics, similar to\nprimitive types.\n\n#### Allow C++ bridge code in Carbon files\n\nCarbon files should support inline bridge code written in C++. Where bridge code\nis necessary, this will allow for maintenance of it directly alongside the code\nthat uses it.\n\n#### Carbon inheritance from C++ types\n\nCarbon will support inheritance from C++ types for interoperability, although\nthe syntax constructs may look different from C++ inheritance. This is\nconsidered necessary to address cases where a C++ library API expects users to\ninherit from a given C++ type.\n\nThis might be restricted to pure interface types; see\n[the open question](#carbon-type-inheritance-from-non-pure-interface-c-types).\n\n#### Support use of advanced C++ features\n\nThere should be support for most idiomatic usage of advanced C++ features. A few\nexamples are templates, overload sets,\n[attributes](https://en.cppreference.com/w/cpp/language/attributes) and\n[ADL](https://en.wikipedia.org/wiki/Argument-dependent_name_lookup).\n\nAlthough these features can be considered \"advanced\", their use is widespread\nthroughout C++ code, including STL. Support for such features is key to\nsupporting migration from C++ features.\n\n#### Support basic C interoperability\n\nC interoperability support must be sufficient for Carbon code to call popular\nAPIs that are written in C. The ability of C to call Carbon will be more\nrestricted, limited to where it echoes C++ interoperability support. Basic C\ninteroperability will include functions, primitive types, and structs that only\ncontain member variables.\n\nFeatures where interoperability will rely on more advanced C++-specific\nfeatures, such as templates, inheritance, and class functions, need not be\nsupported for C. These would require a C-specific interoperability model that\nwill not be included.\n\n### Non-goals\n\n#### Full parity between a Carbon-only toolchain and mixing C++/Carbon toolchains\n\nMaking mixed C++/Carbon toolchain support equivalent to Carbon-only toolchain\nsupport affects all interoperability features. Mixed toolchains will have\ndegraded support because full parity would be too expensive.\n\nThe feature of calling Carbon templates from C++ code is key when analyzing this\noption. Template instantiation during compilation is pervasive in C++.\n\nWith a Carbon toolchain compiling both Carbon and C++ code, the C++ compiler\n_can_ be modified to handle Carbon templates differently. Carbon templates can\nbe handled by exposing the Carbon compiler's AST to the C++ compiler directly,\nas a compiler extension. While this approach is still complex and may not always\nwork, it should offer substantial value and ability to migrate C++ code to\nCarbon without requiring parallel maintenance of implementations in C++.\n\nWith a mixed toolchain, the C++ compiler _cannot_ be modified to handle Carbon\ntemplates differently. The only way to support template instantiation would be\nby having Carbon templates converted into equivalent C++ templates in C++\nheaders; in other words, template support would require source-to-source\ntranslation. Supporting Carbon to C++ code translations would be a complex and\nhigh cost feature to achieve full parity for mixed toolchains. Requiring bridge\ncode for mixed toolchains is the likely solution to avoid this cost.\n\nNote that this issue differs when considering interoperability for Carbon code\ninstantiating C++ templates. The C++ templates must be in C++ headers for reuse,\nwhich in turn must compile with the Carbon toolchain to reuse the built C++\ncode, regardless of whether a separate C++ toolchain is in use. This may also be\nconsidered a constraint on mixed toolchain interoperability, but it's simpler to\naddress and less likely to burden developers.\n\nTo summarize, developers should expect that while _most_ features will work\nequivalently for mixed toolchains, there will never be full parity.\n\n#### Never require bridge code\n\nCorner cases of C++ will not receive equal support to common cases: the\ncomplexity of supporting any given construct must be balanced by the real world\nneed for that support. For example:\n\n-   Interoperability will target C++17. Any interoperability support for future\n    versions of C++, including features such as C++20 modules, will be based on\n    a cost-benefit analysis. Exhaustive support should not be assumed.\n\n-   Support will be focused on idiomatic code, interfaces, and patterns used in\n    widespread open source libraries or by other key constituencies. C++ code\n    will have edge cases where the benefits of limiting Carbon's maintenance\n    costs by avoiding complex interoperability outweighs the value of avoiding\n    bridge code.\n\n-   Support for low-level C ABIs may be focused on modern 64-bit ABIs, including\n    Linux, POSIX, and a small subset of Windows' calling conventions.\n\n#### Convert all C++ types to Carbon types\n\nNon-zero overhead conversions should only be _supported_, never _required_, in\norder to offer reliable, unsurprising performance behaviors. This does not mean\nthat conversions will _always_ be supported, as support is a cost-benefit\ndecision for specific type mappings. For example, consider conversions between\n`std::vector<T>` and an equivalent, idiomatic Carbon type:\n\n-   Making conversions zero-overhead would require the Carbon type to mirror the\n    memory layout and implementation semantics of `std::vector<T>`. However,\n    doing so would constrain the evolution of the Carbon type to match C++.\n    Although some constraints are accepted for most primitive types, it would\n    pose a major burden on Carbon's evolution to constrain Carbon's types to\n    match C++ vocabulary type implementations.\n\n-   These conversions may not always be present, but `std::vector<T>` is a\n    frequently used type. As a result, it can be expected that there will be\n    functions supporting a copy-based conversion to the idiomatic Carbon type.\n\n-   An interface which can hide the difference between whether `std::vector<T>`\n    or the equivalent, idiomatic Carbon type is in use may also be offered for\n    common types.\n\n-   It will still be normal to handle C++ types in Carbon code without\n    conversions. Developers should be given the choice of when to convert.\n\n#### Support for C++ exceptions without bridge code\n\nCarbon may not provide seamless interoperability support for C++ exceptions. For\nexample, translating C++ exceptions to or from Carbon errors might require\nannotations or bridge code, and those translations may have some performance\noverhead or lose information. Furthermore, if Carbon code calls a C++ function\nwithout suitable annotations or bridging, and that function exits with an\nexception, the program might terminate.\n\n#### Cross-language metaprogramming\n\nCarbon's metaprogramming design will be more restrictive than C++'s preprocessor\nmacros. Although interoperability should handle simple cases, such as\n`#define STDIN_FILENO 0`, complex metaprogramming libraries may require a deep\nability to understand code rewrites. It should be reasonable to have these\ninstead rewritten to use Carbon's metaprogramming model.\n\n## Open questions to be resolved later\n\n### Carbon type inheritance from non-pure interface C++ types\n\nSome C++ APIs will expect that consumers use classes that inherit from a type\nprovided by the API. It's desirable to have Carbon support, in some way,\ninheritance from API types in order to use these APIs.\n\nIt may be sufficient to require the parent type be a pure interface, and that\nAPIs with either use bridge code or switch implementations. That will be\ndetermined later.\n\n### CRTP support\n\nAlthough\n[CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) is a\ncommon technique in C++, interoperability support may require substantial work.\nLibraries based on use of CRTP may require bridge code or a rewrite for Carbon\ninteroperability.\n\nMore analysis should be done on the cost-benefit of supporting CRTP before\nmaking a support decision.\n\n### Object lifetimes\n\nCarbon may have a different object lifetime design than C++. For example, Carbon\nmay choose different rules for determining the lifetime of temporaries. This\ncould affect idiomatic use of C++ APIs, turning code that would be safe in C++\ninto unsafe Carbon code, requiring developers to learn new coding patterns.\n\nMore analysis should be done on object lifetimes and potential Carbon designs\nfor it before deciding how to treat object lifetimes in the scope of\ninteroperability.\n\n## Rationale\n\nThe core team agrees with the mapping of the proposed interoperability goals to\nthe overall Carbon goals as rationale.\n\nEmbedding of C++ bridge code inside Carbon code is inspired in part by\nexperience with CUDA and SYCL, where users provided feedback that these were\npreferred over alternatives such as OpenCL due to the ability to embed bridge\ncode and device kernels in the same source file as host C++ code. It also\nmatches the approach of bridging between C++ and C where bridge code is often\nembedded as `extern \"C\"` within C++ source files.\n\nThe non-goals seem appropriately motivated by the non-interoperability\npriorities, without undermining the effectiveness of the interoperability as a\nwhole.\n\nWe agree with ensuring some level of C interoperability in order to effectively\ninteroperate with both some parts of the C++ ecosystem that rely on the C ABI as\nwell as all other languages which target C-based interoperability.\n\n### Open questions\n\nAll open questions in the document are intended to be answered later after we\nhave more experience.\n"
  },
  {
    "path": "proposals/p0179.md",
    "content": "# Create a toolchain team.\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/179)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Scope](#scope)\n-   [Rationale](#rationale)\n    -   [Open questions](#open-questions)\n        -   [Should the name of the team be \"toolchain team\" or \"implementation team\"?](#should-the-name-of-the-team-be-toolchain-team-or-implementation-team)\n\n<!-- tocstop -->\n\n## Problem\n\nThe development of a toolchain for Carbon needs a team of people to oversee it.\nThis will primarily involve code reviews and ensuring the quality of the end\ntoolchain, and includes significant work around compile time efficiency as well\nas developing a cohesive set of libraries for use in developer tools and other\ncontexts.\n\n## Background\n\nThis is largely a technical team that can fluidly evolve over time as people\nhave time and energy to commit to developing the toolchain's codebase itself.\n\n## Proposal\n\nCreate a team from initial volunteers and evolve it over time based on who ends\nup contributing. Notably, contributions can be to the design, documentation, and\ncode _review_ in addition to code or patches themselves.\n\n### Scope\n\nBeyond the traditional components of a language toolchain, this team should also\ncover any needed code review and oversight for other implementation efforts\nwithin the Carbon project, such as supporting tools and test suites related to\nthe language itself.\n\nThere may be some overlap between this _language_ infrastructure and the\n_project_ infrastructure covered by the\n[admins](/docs/project/groups.md#admins). This proposal doesn't suggest a hard\ndelineation between these, and if in doubt or there is disagreement, it should\nbe escalated to the [core team](/docs/project/groups.md) rather than spending\ntoo much time defining precisely disjoint scopes.\n\n## Rationale\n\nCarbon's goals include providing a reference implementation and tooling.\nDelivering this complex software requires a dedicated team, vision, leadership,\nand a degree of autonomy.\n\n### Open questions\n\n#### Should the name of the team be \"toolchain team\" or \"implementation team\"?\n\nSome core team members expressed a preference for \"implementation team\", none\nexpressed a preference for \"toolchain team\", all were fine either way. As\ngribozavr noted, and everyone at the review meeting agreed, the team should be\nfree to choose its own name.\n"
  },
  {
    "path": "proposals/p0196.md",
    "content": "# Language-level safety strategy\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/196)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Open question: probabilistic checks in the hardened build mode](#open-question-probabilistic-checks-in-the-hardened-build-mode)\n-   [Rationale](#rationale)\n    -   [Open questions](#open-questions)\n        -   [Does the core team believe that we should put a cap on how much performance should be sacrificed for safety, putting more emphasis on probabilistic methods that would allow more attacks through?](#does-the-core-team-believe-that-we-should-put-a-cap-on-how-much-performance-should-be-sacrificed-for-safety-putting-more-emphasis-on-probabilistic-methods-that-would-allow-more-attacks-through)\n\n<!-- tocstop -->\n\n## Problem\n\nCarbon needs to have a clear and consistent strategy for approaching the\nproblems of language-level safety. These problems have been persistent and\ngrowing sources of both bugs and security vulnerabilities in C and C++ software.\nFailure to effectively and carefully address safety concerns is likely to\nundermine any hope of Carbon being a successful path forward for today's C++\nusers.\n\n## Background\n\n-   [Fearless Security: Memory Safety](https://hacks.mozilla.org/2019/01/fearless-security-memory-safety/)\n-   [A proactive approach to more secure code](https://msrc-blog.microsoft.com/2019/07/16/a-proactive-approach-to-more-secure-code/)\n-   [Chromium memory safety](https://www.chromium.org/Home/chromium-security/memory-safety)\n-   [MemSafe](https://doi.org/10.1002/spe.2105)\n    -   Notably introduces the terms \"_spatial_\" and \"_temporal_\" safety.\n\n## Proposal\n\nWe propose a safety strategy for Carbon that aims for incrementally increasing\nthe compile-time proven safety while allowing for dynamic checks to cover what\nremains. It also prioritizes dynamic safety checks that are amenable to being\noptimized away or being manually disabled for performance-critical use cases\nwhere the added dynamic protections are not a viable trade-off.\n\n## Open question: probabilistic checks in the hardened build mode\n\nThis proposal explicitly discourages probabilistic checks in the hardened build\nmode because they won't reliably prevent security attacks. Does the core team\nbelieve that we should put a cap on how much performance should be sacrificed\nfor safety, putting more emphasis on probabilistic methods that would allow more\nattacks through?\n\nFor example,\n[heap use-after-free detection](https://docs.google.com/document/d/14-_JAMoMBIVgKOUi3iZIRMHJlAyT23kqSVR8wxJPk9M/edit)\nwith 100% accuracy is expected to be a significant expense for hardened builds.\nMarkUs is estimated to cost 10-50% CPU and 25% RAM in order to catch 100% of\nissues. For comparison, MTE is estimated to cost 0-20% CPU and 3-6% RAM in order\nto catch 93% of issues.\n\nThe CPU and RAM cost of MarkUs is significant, even by comparison with other\ntechniques, and costs will add up as more safety is added. 93% is a reasonably\nhigh detection rate for an performance-efficient, probabilistic technique. Would\nthe core team expect to use MTE instead MarkUs in hardened builds?\n\n## Rationale\n\nMost of Carbon's goals can be addressed in a somewhat piecemeal fashion. For\nexample, there's probably no need for our designs for generics and for sum types\nto coordinate how they address performance or readability. Safety, on the other\nhand, is much more cross-cutting, and so it's important for us to approach it\nconsistently across the whole language. This proposal gives us a common\nvocabulary for discussing safety, establishes some well-motivated common\nprinciples, and provides an overall strategy based on those principles, all of\nwhich will be essential to achieving that consistency.\n\nThis proposal gives a solid basis for thinking about safety in future proposals.\nThe pragmatic choice to focus on the security aspects of safety seems\nwell-aligned with Carbon's goals. In particular, a more idealistic approach to\nsafety, in which every language construct has bounded behavior, would be likely\nto result in safety being prioritized over performance. By instead considering\nsafety largely from the perspective of security vulnerabilities, and accepting\nthat there will be cases where the pragmatic choice is hardening rather than\nstatic or dynamic checks, we can focus on delivering practical safety without\nbeing overly distracted from other goals.\n\nIt is critical that Carbon use build modes to enable writing\nperformance-optimized code (much like C++ today) that can still be built and\ndeployed at reasonable engineering cost with strong guarantees around memory\nsafety for the purposes of security. We think this proposal provides that\nfoundation.\n\nNote: The decision by the core team included a request to clarify the wording on\nbuild modes as described in chandlerc's post (broken link:\n`https://forums.carbon-lang.dev/t/request-for-decision-language-level-safety-strategy/196/6`)\non the decision thread.\n\n### Open questions\n\n#### Does the core team believe that we should put a cap on how much performance should be sacrificed for safety, putting more emphasis on probabilistic methods that would allow more attacks through?\n\nThere is no cap at this point. Where possible, static checking should be used.\nIn practice, there will be some who will not use the safest option until the\ncost gets low enough.\n"
  },
  {
    "path": "proposals/p0198.md",
    "content": "# Comments\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/198)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n    -   [Use cases](#use-cases)\n-   [Background](#background)\n    -   [Line comments](#line-comments)\n    -   [Block comments](#block-comments)\n    -   [`#if 0`](#if-0)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Overview](#overview)\n    -   [Block comments](#block-comments-1)\n        -   [Block comments rationale](#block-comments-rationale)\n    -   [Reserved comments](#reserved-comments)\n        -   [Reserved comments rationale](#reserved-comments-rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Intra-line comments](#intra-line-comments)\n    -   [Multi-line text comments](#multi-line-text-comments)\n    -   [Block comments](#block-comments-2)\n    -   [Documentation comments](#documentation-comments)\n    -   [Code folding comments](#code-folding-comments)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Problem\n\nThis proposal provides a suggested concrete lexical syntax for comments.\n\n### Use cases\n\nComments serve a variety of purposes in existing programming languages. The\nprimary use cases are:\n\n-   _Documentation_: human-readable commentary explaining to users and future\n    maintainers of an API what function it performs and how to use it. Such\n    comments are typically attached to function declarations, class definitions,\n    public member declarations, at file scope, and similar levels of granularity\n    in an API.\n\n    ```\n    /// A container for a collection of connected widgets.\n    class WidgetAssembly {\n      /// Improve the appearance of the assembly if possible.\n      void decorate(bool repaint_all = false);\n\n      // ...\n    };\n    ```\n\n-   _Implementation comments_: human-readable commentary explaining intent and\n    mechanism to future readers or maintainers of code, or summarizing the\n    behavior of code to avoid readers or maintainers needing to read it in\n    detail. Such comments are typically used when such details may not be\n    readily apparent from the code itself or may require non-trivial work to\n    infer, and tend to be short.\n\n    ```\n    void WidgetAssembly::decorate(bool repaint_all) {\n      // ...\n\n      // Paint all the widgets that have been changed since last time.\n      for (auto &w : widgets) {\n        if (repaint_all || w.modified > last_foo)\n          w.paint();\n      }\n      last_decorate = now();\n\n      // ...\n    }\n    ```\n\n-   _Syntactic disambiguation comments_: comments that contain code or\n    pseudocode intended to allow the human reader to more easily parse the code\n    in the same way that the compiler does.\n\n    ```\n    void WidgetAssembly::decorate(bool repaint_all /*= false*/) {\n    // ...\n\n    /*static*/ std::unique_ptr<WidgetAssembly> WidgetAssembly::make() {\n    // ...\n\n    assembly.decorate(/*repaint_all=*/true);\n    // ...\n\n    }  // end namespace WidgetLibrary\n    ```\n\n-   _Disabled code_: comments that contain regions of code that have been\n    disabled, because the code is incomplete or incorrect, or in order to\n    isolate a problem while debugging, or as reference material for a change in\n    progress. It is often considered bad practice to check such comments into\n    version control.\n\n## Background\n\nIn C++, there are three different ways in which comments are expressed in\npractice:\n\n### Line comments\n\nSingle-line comments (and sometimes multiline comments) are expressed in C++\nusing `// ...`:\n\n```\n// The next line declares a variable.\nint n; // This is a comment about 'n'.\n```\n\n(These are sometimes called \"BCPL comments\".)\n\n-   Can appear anywhere (at the start of a line or after tokens).\n-   Can contain any text (other than newline).\n-   End at the end of the logical line.\n-   Can be continued by ending the comment with `\\` (or `??/` in C++14 and\n    earlier).\n-   Unambiguous with non-comment syntax.\n-   \"Nest\" in that `//` within `//` has no effect.\n-   Do not nest with other kinds of comment.\n\nThis comment syntax is often used to express documentation (sometimes with a\nDoxygen-style `///` introducer) and implementation comments.\n\n### Block comments\n\nComments within lines (or sometimes multiline comments) are expressed in C++\nusing `/*...*/`:\n\n```\nf(/*size*/5, /*initial value*/1);\n```\n\n-   Can appear anywhere (at the start of a line or after tokens).\n-   Can contain any text (other than `*/`).\n-   End at the `*/` delimiter (which might be separated by a `\\` line\n    continuation).\n-   Ambiguous with non-comment syntax: `int a=1, *b=&a, c=a/*b;` though this is\n    not a problem in practice.\n-   Do not nest -- the first `*/` ends the comment.\n\nThis comment syntax is often used to express syntactic disambiguation comments,\nand is sometimes used for disabled code. Some coding styles also use this\ncomment style for longer documentation comments (sometimes with a Doxygen-style\n`/**` introducer).\n\n### `#if 0`\n\nBlocks of code are often commented out in C++ programs using `#if 0`:\n\n```\n#if 0\nint n;\n#endif\n```\n\n-   Can appear only at the start of a logical line.\n-   Can only contain sequences of preprocessing tokens (including invalid tokens\n    such as `'`, but not including unterminated multiline string literals).\n-   End at the matching `#endif` delimiter.\n-   Unambiguous with any other syntax.\n-   Nest properly, and can have other kinds of comments nested within.\n\nThis syntax is generally only used for disabled code.\n\n## Proposal\n\nWe provide only one kind of comment, which starts with `//` and runs to the end\nof the line. No code is permitted prior to a comment on the same line, and the\n`//` introducing the comment is required to be followed by whitespace.\n\nThis comment syntax is intended to support implementation comments and\n(_experimentally_) disabled code. The documentation use case is\n[not covered](#documentation-comments), with the intent that a separate\n(non-comment) facility is explored for this use case. The syntactic\ndisambiguation use case is not covered, with the intent that the language syntax\nis designed in a way that avoids this use case.\n\n## Details\n\n### Overview\n\nA _comment_ is a lexical element beginning with the characters `//` and running\nto the end of the line. We have no mechanism for physical line continuation, so\na trailing `\\` does not extend a comment to subsequent lines.\n\n> _Experimental:_ There can be no text other than horizontal whitespace before\n> the `//` characters introducing a comment. Either all of a line is a comment,\n> or none of it.\n\nThe character after the `//` is required to be a whitespace character. Newline\nis a whitespace character, so a line containing only `//` is a valid comment.\nThe end of the file also constitutes whitespace.\n\nAll comments are removed prior to formation of tokens.\n\nExample:\n\n```carbon\n// This is a comment and is ignored. \\\nThis is not a comment.\n\nvar Int: x; // error, trailing comments not allowed\n```\n\n### Block comments\n\n> _Experimental:_ No support for block comments is provided. Commenting out\n> larger regions of human-readable text or code is accomplished by commenting\n> out every line in the region.\n\n#### Block comments rationale\n\nThere is little value in supporting block comments for the implementation\ncomments use case. We expect such comments to typically be short, and in\nexisting C++ codebases with long implementation comments, it is typical for line\ncomments rather than block comments to be used. Therefore, as we consider the\ndocumentation use case to be out of scope, and intend for the syntactic\ndisambiguation use case to be solved by language syntax, the sole purpose of\nblock comments would be for disabled code. Block comments could provide more\nergonomic support for intra-line disabled code and multiline blocks of disabled\ncode.\n\nExisting block comment syntaxes are not a great fit for the use case of\ndisabling code. The `/* ... */` block comment syntax does not nest in C++, and\ncannot be used to reliably comment out a block of code because it can be\nterminated by a `*/` appearing in a `//` comment or in a string literal. The\n`#if 0 ... #endif` syntax would not be a good fit in Carbon as we do not intend\nto have a preprocessor in general, and requires the text in between to consist\nof a mostly-valid token sequence, disallowing certain forms of incomplete code.\n\nWe should be reluctant to invent something new: it is hard to justify the cost\nof introducing a novel syntax for the transient and rare use case of disabling\ncode. And similarly, we should be reluctant to use existing syntax with novel\nsemantics, such as a `/* ... */` comment that tokenizes its contents, to avoid\nsurprise to C++ developers.\n\nThe disabled code use cases can be addressed with line comments, by commenting\nout each line in the intended region, and reflowing or duplicating lines when\ndisabling code within a line. That may be cumbersome, but it's unclear whether\nthat burden is sufficient to warrant introducing another form of comment into\nthe language. By providing no such form of comments, we aim to discover if the\nresulting friction warrants a language addition.\n\n### Reserved comments\n\nComments in which the `//` characters are not followed by whitespace are\nreserved for future extension. Anticipated possible extensions are block\ncomments, documentation comments, and code folding region markers.\n\n#### Reserved comments rationale\n\nWe anticipate the possibility of adding additional kinds of comment in the\nfuture. Reserving syntactic space in comment syntax, in a way that is easy for\nprograms to avoid, allows us to add such additional kinds of comment as a\nnon-breaking change.\n\n## Alternatives considered\n\n### Intra-line comments\n\nWe could include a feature similar to C-style block comments, as a way to\nprovide comments that attach to some element of the program smaller than a line.\nIn C++ code, such comments are frequently used to annotate function parameter\nnames and similar syntactic disambiguation use cases:\n\n```\nrender(/*use_world_coords=*/true, /*draw_frame=*/false);\n```\n\nWe expect these use cases to be addressed by extensions to Carbon's grammar,\nsuch as by adding named parameters or annotation syntax, to allow such\nutterances to be expressed as code rather than as comments, so they are\nmeaningful to both the Carbon programmer and the Carbon language tools.\n\nWe could permit trailing comments on a line that contains other content. Such\ncomments are most frequently used in our sample C++ corpus to describe the\nmeaning of an entity, label, or close brace on the same line:\n\n```\nnamespace N {\nint n; // number of hats\nenum Mode {\n  mode1, // first mode\n  mode2 // second mode\n};\n} // end namespace N\n```\n\nIn all cases but the last, we expect it to be reasonable to move the comment to\nbefore the declaration. The case of the \"end namespace\" comment is another\ninstance of the syntactic disambiguation use case, which we expect to be\naddressed by grammar changes. In general, we should avoid any syntax that would\nneed disambiguation comments, either by promoting those comments to the language\ngrammar or by altering the syntax until the comment is unnecessary, such as by\nnot providing a delimited scope syntax for describing the contents of large\nscopes such as namespaces and packages. For example:\n\n```carbon\n// This declares the namespace N but does not open a scope.\nnamespace N;\n\n// This declares a member of namespace N.\n@\"Number of hats.\"\nvar Int: N.n;\n\nenum N.Mode {\n  @\"First mode.\"\n  mode1;\n  @\"Second mode.\"\n  mode2;\n}\n```\n\nIntra-line comments present a challenge for code formatting tools, which would\nneed to understand what part of the program syntax the comment \"attaches to\" in\norder properly reflow the comment with the code. This concern is mitigated, but\nnot fully eliminated, by requiring comments to always be on their own line. We\ncould restrict text comments to appear in only certain syntactic locations to\nfully resolve this concern, but doing so would remove the flexibility to insert\ncomments in arbitrary places:\n\n```\nmatch (x) {\n  case .Foo(1, 2,\n            // This might be 3 or 4 depending on the size of the Foo.\n            Int: n) => { ... }\n}\n```\n\nWe could allow intra-line comments and still retain some idea of what the\ncomment syntactically attaches to by using a directionality marker in the\ncomment:\n\n```\nmatch (x) {\n  case .Foo(1, 2, //> either 3 or 4 >// Int: n) => { ... }\n  case .Foo(2, Int: n //< either 3 or 4 <//, 5) => { ... }\n}\n```\n\nEven with an understanding of how comments attach, line wrapping such comments\nis a complex challenge. For example, formatting in a situation with aligned\ntrailing comments across multiple lines requires special handling:\n\n```\nvar Int: quality = 3;   // The quality of the widget. It should always\n                        // be between 1 and 9.\nvar Int: blueness = 72; // The blueness of the widget, as a percentage.\n```\n\nHere, a tool that renames `blueness` to `blue_percent` may need to reflow the\ncomment following `quality` as well as the comment following `blueness`.\nMoreover, if the last line becomes too long, keeping the comment on the same\nline as the variable may become untenable, requiring a more substantive\nrewriting:\n\n```\n// The blueness of the widget, as a percentage.\nvar Int: blue_percent = Floor(ComputeBluenessRatio() * 100);\n```\n\nThe decision to not support trailing and intra-line comments is **experimental**\nand should be revisited if we find there is a need for such comments in the\ncontext of the complete language design.\n\n### Multi-line text comments\n\nNo support is provided for multi-line text comments. Instead, the intent is that\nsuch comments are expressed by prepending each line with the same `// ` comment\nmarker.\n\nRequiring each line to repeat the comment marker will improve readability, by\nremoving a source of non-local state, and removes a needless source of stylistic\nvariability. The resulting style of comment is common in other languages and\nwell-supported by editors. Even in C and C++ code that uses `/* ... */` to\ncomment out a block of human-readable text, it is common to include a `*` at the\nstart of each comment continuation line.\n\n### Block comments\n\nWe considered various different options for block comments. Our primary goal was\nto permit commenting out a large body of Carbon code, which may or may not be\nwell-formed (including code that contains a block comment, meaning that such\ncomments would need to nest). Alternatives considered included:\n\n-   Fully line-oriented block comments, which would remove lines without regard\n    for whether they are nested within a string literal, with the novel feature\n    of allowing some of the contents of a block string literal to be commented\n    out. This alternative has the disadvantage that it would result in\n    surprising behavior inside string literals containing Carbon code.\n-   Fully lexed block comments, in which a token sequence between the opening\n    and closing comment marker is produced and discarded, with the lexing rules\n    relaxed somewhat to avoid rejecting ill-formed code. This would be analogous\n    to C and C++'s `#if 0` ... `#endif`. This alternative has the disadvantage\n    that it would be unable to cope with incomplete code fragments, such as an\n    unterminated block string literal. It would also be somewhat inefficient to\n    process compared to non-lexing syntaxes, but that's likely to be largely\n    irrelevant given that block comments are expected to be transient.\n-   A hybrid approach, with `//\\{` and `//\\}` delimiters that are invalid in\n    non-raw string literals, and with an indentation requirement for raw string\n    literals only. This alternative has the disadvantage of introducing\n    additional complexity into the lexical rules by treating different kinds of\n    string literals differently.\n-   Use of `/*` and `*/` as comment markers. This alternative has the\n    disadvantage that it risks confusion by using similar syntax to C and C++\n    but with divergent semantics.\n\nHowever, given the limited use cases for such comments and a desire to minimize\nour inventiveness, we are not pursuing any of these options in this proposal.\n\n### Documentation comments\n\nWe could add a distinct comment syntax for documentation comments, perhaps\ntreating documentation comments as producing real tokens rather than being\nstripped out by the lexer. However, during discussion, there was significant\nsupport for using a syntax that does not resemble a comment for representing\ndocumentation. For example, we could introduce an attribute syntax, such as\nusing `@ <expression>` as a prefix to a declaration to attach attributes. Then a\nstring literal attribute can be treated as documentation:\n\n```carbon\n@\"Get the size of the thing.\"\nfn GetThingSize() -> Int;\n\n@\"\"\"\nRate the quality of the widget.\n\nReturns a quality factor between 0.0 and 1.0.\n\"\"\"\nfn RateQuality(\n  @\"The widget to rate.\"\n  Widget: w,\n  @\"A widget quality database.\"\n  QualityDB: db) -> Float;\n```\n\nThis use case will be explored by a future proposal.\n\n### Code folding comments\n\nSome code editors are able to \"fold\" regions of a source file in order to ease\nnavigation. In some cases, these fold regions can be customized by the use of\ncomment lines. For example, in VS Code, this is accomplished with comments\ncontaining `#region` and `#endregion`:\n\n```\n// #region Functions F and G\nfn f() { ... }\nfn g() { ... }\n// #endregion\n```\n\nSupporting such markers as normal text within line comments requires no\nadditional effort. However, we could consider introducing a specific Carbon\nsyntax for region comments, in order to encourage a common representation across\ncode editors. Such support is not covered by this proposal, but could be handled\nby a new form of comment.\n\n## Rationale\n\n-   Some comment syntax is necessary to support software evolution, readable and\n    understandable code, and many other goals of Carbon.\n-   A single, simple, and consistent comment style supports Carbon's goal of\n    easy to read and understand code, and fast development tools.\n-   The experiment of restricting comments to be the only non-whitespace text on\n    a line supports Carbon's goal of software evolution.\n-   The careful open lexical space left supports Carbon's goal of language\n    evolution.\n-   The use of `//` as the primary syntax marking comments supports\n    interoperability with C++-trained programmers and codebases by avoiding\n    unnecessary and unhelpful churn of comment syntax.\n"
  },
  {
    "path": "proposals/p0199.md",
    "content": "# String literals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/199)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Existing practice](#existing-practice)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Non-raw string literals](#non-raw-string-literals)\n        -   [Escape sequences](#escape-sequences)\n    -   [Raw string literals](#raw-string-literals)\n    -   [Encoding](#encoding)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Block string literals](#block-string-literals)\n        -   [Leading whitespace removal](#leading-whitespace-removal)\n        -   [Terminating newline](#terminating-newline)\n    -   [Escape sequences](#escape-sequences-1)\n    -   [Raw string literals](#raw-string-literals-1)\n        -   [Trailing whitespace](#trailing-whitespace)\n        -   [Line separators](#line-separators)\n    -   [Internal whitespace](#internal-whitespace)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Problem\n\nThis proposal specifies lexical rules for constant strings in Carbon.\n\n## Background\n\nWe wish to provide a syntax for writing literals containing human-readable text.\n\nNote that \"human-readable text\" here should be understood broadly: such text may\nbe subject to further processing, and may in some cases be intended to be\ninterpreted by a computer rather than by a human (such as a regular expression,\nprogram source code, or a C++ mangled name), but broadly represents a sequence\nof characters rather than arbitrary binary data.\n\nSuch text is typically represented in an _encoding_, which is a bidirectional\nmapping between a sequence of characters in text and a sequence of bounded\ninteger values known as _code units_, suitable for storage, transmission, and\nprocessing. For example, the Russian word углерод (carbon) is encoded in the\nUTF-8 encoding as D1<sub>16</sub>83<sub>16 </sub>D0<sub>16</sub>B3<sub>16\n</sub>D0<sub>16</sub>BB<sub>16</sub> D0<sub>16</sub>B5<sub>16</sub>\nD1<sub>16</sub>80<sub>16</sub> D0<sub>16</sub>BE<sub>16</sub>\nD0<sub>16</sub>B4<sub>16</sub>.\n\n### Existing practice\n\nSee\n[Comparison of programming languages (strings) on Wikipedia](https://en.wikipedia.org/wiki/Comparison_of_programming_languages_%28strings%29).\n\nSimple string literals are specified in most programming languages as text\ndelimited by double-quote characters, `\"like this\"`. Such string literals\nusually are restricted to begin and end on the same source line. Three\nadditional features are commonly seen:\n\n-   Escape sequences, which permit string literals to include characters that\n    are difficult to type, are ambiguous for the reader, or that would be\n    problematic in some way (such as whitespace characters, characters that are\n    invisible, and characters that change how other characters are rendered),\n    and also to include arbitrary code units. One common convention is to use\n    `\\` to introduce an escape sequence, where, for example:\n\n    -   `\\n` represents a newline character,\n    -   `\\u1234` represents the Unicode character U+1234,\n    -   `\\xAB` represents the code unit AB<sub>16</sub>,\n    -   `\\\"` represents a single `\"` character and does not terminate the string\n        literal,\n    -   `\\\\` represents a single `\\` character,\n\n    and so on.\n\n    The set of single-letter escape sequences has a lot of commonality between\n    languages, with some variation between older and newer languages:\n\n    -   C++ and Python allow `\\a`, `\\b`, `\\f`, `\\n`, `\\r`, `\\t`, `\\v` for bell,\n        backspace, form feed, new line, carriage return, tab, and vertical tab,\n        respectively.\n    -   JavaScript drops support for `\\a`.\n    -   Java additionally drops support for `\\v`.\n    -   Rust and Swift additionally drop support for `\\b` and `\\f`, leaving only\n        `\\n`, `\\r`, and `\\t`.\n\n    The rules for numeric escape sequences differ between kinds of escape\n    sequence and between languages. The rules in C++, JavaScript, Python, Rust,\n    and Swift are as follows:\n\n    -   `\\123` is interpreted as a octal code unit value, and up to three octal\n        digits are consumed. In JavaScript and C++, values greater than\n        377<sub>8</sub> (255<sub>10</sub>) are invalid (assuming an 8-bit\n        character type). In Python, values greater than 377<sub>8</sub> are\n        interpreted modulo 256. Rust and Swift do not allow octal escapes in\n        general, but do allow `\\0` as a special case.\n    -   `\\xAB` is interpreted as a hexadecimal code unit value. In C++, any\n        nonzero number of hexadecimal digits can follow as part of the escape\n        sequence. In Python, JavaScript, and Rust, exactly two digits are\n        required. In Rust, the value must be less than or equal to\n        7F<sub>16</sub> except for `b`-prefixed strings (byte array literals).\n        Swift does not support this form of escape sequence.\n    -   `\\uABCD` is interpreted as a hexadecimal code point value. In C++,\n        Python, and JavaScript, exactly four hexadecimal digits can follow, but\n        JavaScript allows any nonzero number of digits to be specified using\n        `\\u{ABCDE}` notation. Rust and Swift support only the `\\u{ABCDE}`\n        notation.\n    -   `\\U0010FFFD` is interpreted as a hexadecimal code point value in C++ and\n        Python, but not in JavaScript, Rust, or Swift, and permits exactly eight\n        hexadecimal digits.\n\n-   Raw string literals, in which escape sequences are not recognized. These are\n    often used in situations where escape sequences are undesirable, but in\n    which the escape character or regular string terminator is used frequently.\n    Such literals are useful when embedding one machine-readable language in\n    another, when those languages share some escaping conventions. Such\n    functionality may also provide a way to customize the string delimiters.\n\n    -   In Python, raw string literals have an `r` prefix: `r\"li\\ngo\"` is a six\n        character string whose third character is `\\`.\n    -   In C++, raw string literals have an `r` prefix, along with a custom\n        delimiter (which may be empty): `r\"DELIM(li\\ngo)DELIM\"` is a six\n        character string (plus a nul terminator).\n    -   In Rust, raw string literals have an `r` prefix and any matching number\n        of `#` characters enclose the string contents: the third character of\n        `r\"lo\\ng\"` is `\\`, and the second character of `r#\" \" \"#` is `\"`.\n    -   In Swift, raw string literals are a generalization of regular string\n        literals: literals are introduced by any number, _N_, of `#` characters\n        followed by a `\"`, terminated by `\"` followed by _N_ `#` characters, and\n        escape sequences are introduced by a `\\` followed by _N_ `#` characters:\n        `#\" \" # \\n \\#n \\#\\# \"#` has the same contents as the C++ string literal\n        `\" \\\" # \\\\n \\n \\\\# \"`.\n    -   In Java, raw string literals are delimited by a sequence of one or more\n        backticks instead of double quotes: the fourth character of\n        <code>\\`\\`foo\\`\\bar\\`\\`</code> is a backtick and the fifth is a\n        backslash.\n\n-   Multiline string literals provide a mechanism for a string to easily span\n    more than one line of source text.\n\n    -   In C++, Rust, and Java, raw string literals are used to represent\n        multiline string literals.\n    -   In Python, different delimiters (`\"\"\"` or, in Python, `'''` instead of\n        `\"` or `'`) are used to represent multiline string literals, and plain\n        `\"` and `\"\"` can thereby appear in the string contents, but these\n        literals otherwise behave the same as regular string literals.\n    -   In Swift, different delimiters are used (`\"\"\"` instead of `\"`), but\n        unlike in Python, the string content cannot be on the same line as the\n        delimiters, and the resulting mandatory leading and trailing newlines\n        are not included in the string. Internal newlines can be removed by\n        preceding them with backslashes.\n    -   In JavaScript, backtick-delimited strings can contain newlines; this\n        syntax also allows string interpolation as described below.\n\nIn addition, some languages, primarily scripting languages, also provide a\nmechanism for string interpolation, wherein a string value is formed by\nincluding the formatted values of some variables in a given format string. For\nexample, `\"Hello, $planet.\"` might produce a string value including the\nformatted value of the variable named `planet`. Such interpolation facilities\nare outside the scope of this proposal.\n\n## Proposal\n\n-   Single-line string literals are delimited by `\"`s: `\"hello\"`\n\n-   Multi-line string literals are introduced by a `\"\"\"` followed by a newline\n    and terminated by a line beginning with a `\"\"\"`. The indentation of the\n    terminating line is removed from all preceding lines:\n\n    ```carbon\n    var String: henry_vi = \"\"\"\n      The winds grow high; so do your stomachs, lords.\n      How irksome is this music to my heart!\n      When such strings jar, what hope of harmony?\n      I pray, my lords, let me compound this strife.\n          -- History of Henry VI, Part II, Act II, Scene 1, W. Shakespeare\n      \"\"\";\n    ```\n\n    Only the final line of this string literal begins with whitespace. The\n    opening newline is not part of the string's contents, but the trailing\n    newline is; the first character of this example string is `T` and the last\n    character is a newline.\n\n-   The opening `\"\"\"` of a multi-line string literal can be followed by a _file\n    type indicator_, to assist tooling in understanding the intent of the\n    string. This indicator has no effect on the meaning of the program.\n\n    ```carbon\n    var String: cpp_snippet = \"\"\"c++\n      #include <iostream>\n\n      int main() {\n        std::cout << \"hello world\" << std::endl;\n      }\n      \"\"\";\n    ```\n\n-   Escape sequences are introduced with a `\\` character; the most common C and\n    C++ escape sequences are supported: `\"hello\\nworld\"`. Octal escapes\n    (`\\177`), `\\a`, `\\b`, `\\f` and `\\v` are removed. `\\uNNNN` and `\\U00NNNNNN`\n    are replaced by `\\u{NNNNNN}`. An escape sequence `\\<newline>` is permitted\n    in multi-line string literals, and results in no string contents.\n\n-   Raw string literals are supported, for both the single and multi-line case,\n    following the Swift convention: they are introduced by prefixing the opening\n    delimiter with one or more `#`s, and suffixing the closing delimiter with a\n    matching number of `#`s: `#\"foo\\s*bar\"#` or `#\"foo\"bar\"#`. Escape sequences\n    can be introduced in a raw string literal by inserting a matching number of\n    `#`s after the `\\` character: `#\"foo\\#nbar\"#` contains a newline character.\n\n-   Unlike in C and C++, adjacent string literals are not implicitly\n    concatenated.\n\n## Details\n\n### Non-raw string literals\n\nA _simple string literal_ is formed of a sequence of\n\n-   characters other than backslashes, double quotation marks, and vertical\n    whitespace\n-   [escape sequences](#escape-sequences)\n\nenclosed in double quotation marks (`\"`). Each escape sequence is replaced with\nthe corresponding character sequence or code unit sequence.\n\n```carbon\nvar String: lucius = \"The strings, my lord, are false.\";\n```\n\nA _block string literal_ starts with three double quotation marks, followed by\nan optional file type indicator, followed by a newline, and ends at the next\ninstance of three double quotation marks whose first `\"` is not part of a `\\\"`\nescape sequence. The closing `\"\"\"` shall be the first non-whitespace characters\non that line. The lines between the opening line and the closing line\n(exclusive) are _content lines_. The content lines shall not contain `\\`\ncharacters that do not form part of an escape sequence.\n\nThe _indentation_ of a block string literal is the sequence of horizontal\nwhitespace preceding the closing `\"\"\"`. Each non-empty content line shall begin\nwith the indentation of the string literal. The content of the literal is formed\nas follows:\n\n-   The indentation of the closing line is removed from each non-empty content\n    line.\n-   All trailing whitespace on each line, including the line terminator, is\n    replaced with a single line feed (U+000A) character.\n-   The resulting lines are concatenated.\n-   Each [escape sequence](#escape-sequences) is replaced with the corresponding\n    character sequence or code unit sequence.\n\nA content line is considered empty if it contains only whitespace characters.\n\n```carbon\nvar String: w = \"\"\"\n  This is a string literal. Its first character is 'T' and its last character is\n  a newline character. It contains another newline between 'is' and 'a'.\n  \"\"\";\n\n// This string literal is invalid because the \"\"\" after 'closing' terminates\n// the literal, but is not at the start of the line.\nvar String: invalid = \"\"\"\n  error: closing \"\"\" is not on its own line.\n  \"\"\";\n```\n\nA _file type indicator_ is any sequence of non-whitespace characters other than\n`\"` or `#`. The file type indicator has no semantic meaning to the Carbon\ncompiler, but some file type indicators are understood by the language tooling\n(for example, syntax highlighter, code formatter) as indicating the structure of\nthe string literal's content.\n\n```carbon\n// This is a block string literal. Its first two characters are spaces, and its\n// last character is a line feed. It has a file type of 'c++'.\nvar String: starts_with_whitespace = \"\"\"c++\n    int x = 1; // This line starts with two spaces.\n    int y = 2; // This line starts with two spaces.\n  \"\"\";\n```\n\nThe file type indicator might contain semantic information beyond the file type\nitself, such as instructions to the code formatter to disable formatting for the\ncode block.\n\n**Open question:** This proposal does not suggest any concrete set of recognized\nfile type indicators. It would be useful to informally specify a set of\nwell-known indicators, so that tools have a common understanding of what those\nindicators mean, perhaps in a best practices guide.\n\n#### Escape sequences\n\nWithin a string literal, the following escape sequences are recognized:\n\n| Escape        | Meaning                                                  |\n| ------------- | -------------------------------------------------------- |\n| `\\t`          | U+0009 CHARACTER TABULATION                              |\n| `\\n`          | U+000A LINE FEED                                         |\n| `\\r`          | U+000D CARRIAGE RETURN                                   |\n| `\\\"`          | U+0022 QUOTATION MARK (`\"`)                              |\n| `\\'`          | U+0027 APOSTROPHE (`'`)                                  |\n| `\\\\`          | U+005C REVERSE SOLIDUS (`\\`)                             |\n| `\\0`          | Code unit with value 0                                   |\n| `\\xHH`        | Code unit with value HH<sub>16</sub>                     |\n| `\\u{HHHH...}` | Unicode code point U+HHHH...                             |\n| `\\<newline>`  | No string literal content produced (block literals only) |\n\nThis includes all C++ escape sequences except:\n\n-   `\\?`, which was historically used to escape trigraphs in string literals,\n    and no longer serves any purpose.\n-   `\\ooo` octal escapes, which are removed because Carbon does not support\n    octal literals; `\\0` is retained as a special case, which is expected to be\n    important for C interoperability.\n-   `\\uABCD`, which is replaced by `\\u{ABCD}`.\n-   `\\U0010FFFF`, which is replaced by `\\u{10FFFF}`.\n-   `\\a` (bell), `\\b` (backspace), `\\v` (vertical tab), and `\\f` (form feed).\n    `\\a` and `\\b` are obsolescent, and `\\f` and `\\v` are largely obsolete. These\n    characters can be expressed with `\\x07`, `\\x08`, `\\x0B`, and `\\x0C`\n    respectively if needed.\n\nNote that this is the same set of escape sequences supported by\n[Swift](https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#ID295)\nand [Rust](https://doc.rust-lang.org/reference/tokens.html), except that, unlike\nin Swift, support for `\\xHH` is provided.\n\nWhile this proposal takes a firm stance on not permitting octal escape\nsequences, the decision to not allow `\\1`..`\\7`, and more generally to not treat\n`\\DDDD` as a decimal escape sequence, is _experimental_.\n\nIn the above table, `H` represents an arbitrary hexadecimal character, `0`-`9`\nor `A`-`F` (case-sensitive). Unlike in C++, but like in Python, `\\x` expects\nexactly two hexadecimal digits. As in JavaScript, Rust, and Swift, Unicode code\npoints can be expressed by number using `\\u{10FFFF}` notation, which accepts any\nnumber of hexadecimal characters. Any numeric code point in the ranges\n0<sub>16</sub>-D7FF<sub>16</sub> or E000<sub>16</sub>-10FFFF<sub>16</sub> can be\nexpressed this way.\n\n_Open question:_ Some programming languages (notably Python) support a\n`\\N{unicode character name}` syntax. We could add such an escape sequence, but\nthis proposal does not include one. Future proposals considering adding such\nsupport should pay attention to work done by C++'s Unicode study group in this\narea.\n\nThe escape sequence `\\0` shall not be followed by a decimal digit. In cases\nwhere a null byte should be followed by a decimal digit, `\\x00` can be used\ninstead: `\"foo\\x00123\"`. The intent is to preserve the possibility of permitting\ndecimal escape sequences in the future.\n\nA backslash followed by a line feed character is an escape sequence that\nproduces no string contents. This escape sequence is _experimental_, and can\nonly appear in multi-line string literals. This escape sequence is processed\nafter trailing whitespace is replaced by a line feed character, so a `\\`\nfollowed by horizontal whitespace followed by a line terminator removes the\nwhitespace up to and including the line terminator. Unlike in Rust, but like in\nSwift, leading whitespace on the line after an escaped newline is not removed,\nother than whitespace that matches the indentation of the terminating `\"\"\"`.\n\nA character sequence starting with a backslash that doesn't match any known\nescape sequence is invalid. Whitespace characters other than space and, for\nblock string literals, new line optionally preceded by carriage return are\ndisallowed. All other characters (including non-printable characters) are\npreserved verbatim. Because all Carbon source files are required to be valid\nsequences of Unicode characters, code unit sequences that are not valid UTF-8\ncan only be produced by `\\x` escape sequences.\n\nThe choice to disallow raw tab characters in string literals is _experimental_.\n\n```carbon\nvar String: fret = \"I would 'twere something that would fret the string,\\n\" +\n                   \"The master-cord on's \\u{2764}\\u{FE0F}!\";\n\n// This string contains two characters (prior to encoding in UTF-8):\n// U+1F3F9 (BOW AND ARROW) followed by U+0032 (DIGIT TWO)\nvar String: password = \"\\u{1F3F9}2\";\n\n// This string contains no newline characters.\nvar String: type_mismatch = \"\"\"\n  Shall I compare thee to a summer's day? Thou art \\\n  more lovely and more temperate.\\\n  \"\"\";\n\nvar String: trailing_whitespace = \"\"\"\n  This line ends in a space followed by a newline. \\n\\\n      This line starts with four spaces.\n  \"\"\";\n```\n\n### Raw string literals\n\nIn order to allow strings whose contents include backslashes and double quotes,\nthe delimiters of string literals can be customized by prefixing the opening\ndelimiter with _N_ `#` characters. A closing delimiter for such a string is only\nrecognized if it is followed by _N_ `#` characters, and similarly, escape\nsequences in such string literals are recognized only if the `\\` is also\nfollowed by _N_ `#` characters. A `\\`, `\"`, or `\"\"\"` not followed by _N_ `#`\ncharacters has no special meaning.\n\n| Opening delimiter | Escape sequence introducer    | Closing delimiter |\n| ----------------- | ----------------------------- | ----------------- |\n| `\"` / `\"\"\"`       | `\\` (for example, `\\n`)       | `\"` / `\"\"\"`       |\n| `#\"` / `#\"\"\"`     | `\\#` (for example, `\\#n`)     | `\"#` / `\"\"\"#`     |\n| `##\"` / `##\"\"\"`   | `\\##` (for example, `\\##n`)   | `\"##` / `\"\"\"##`   |\n| `###\"` / `###\"\"\"` | `\\###` (for example, `\\###n`) | `\"###` / `\"\"\"###` |\n| ...               | ...                           | ...               |\n\nFor example:\n\n```carbon\nvar String: x = #\"\"\"\n  This is the content of the string. The 'T' is the first character\n  of the string.\n  \"\"\" <-- This is not the end of the string.\n  \"\"\"#;\n  // But the preceding line does end the string.\n// OK, final character is \\\nvar String: y = #\"Hello\\\"#;\nvar String: z = ##\"Raw strings #\"nesting\"#\"##;\nvar String: w = #\"Tab is expressed as \\t. Example: '\\#t'\"#;\n```\n\nNote that both a single-line raw string literal and a multi-line raw string\nliteral can begin with `#\"\"\"`. These cases can be distinguished by the presence\nor absence of additional `\"`s later in the same line:\n\n-   In a single-line raw string literal, there must be a `\"` and one or more\n    `#`s later in the same line terminating the string.\n-   In a multi-line raw string literal, the rest of the line is a file type\n    indicator, which can contain neither `\"` nor `#`.\n\n```carbon\n// This string is a single-line raw string literal.\n// The contents of this string start and end with exactly two \"s.\nvar String: ambig1 = #\"\"\"This is a raw string literal starting with \"\"\"#;\n\n// This string is a block raw string literal with file-type 'This',\n// whose contents start with \"is a \".\nvar String: ambig2 = #\"\"\"This\n  is a block string literal with file type 'This', first character 'i',\n  and last character 'X': X\\#\n  \"\"\"#;\n\n// This is a single-line raw string literal, equivalent to \"\\\"\".\nvar String: ambig3 = #\"\"\"#;\n```\n\n### Encoding\n\nA string literal results in a sequence of 8-bit bytes. Like Carbon source files,\nstring literals are encoded in UTF-8. This proposal includes no mechanism to\nrequest that any other encoding is used. The expectation is that if another\nencoding is needed, the string literal can be transcoded from UTF-8 during\ncompilation. There is no guarantee that the string is valid UTF-8, however,\nbecause arbitrary byte sequences can be inserted by way of `\\xHH` escape\nsequences.\n\nThis decision is _experimental_, and should be revisited if we find sufficient\nmotivation for directly expressing string literals in other encodings.\nSimilarly, as library support for a string type evolves, we should consider\nincluding string literal syntax (perhaps as the default) that guarantees the\nstring content is a valid UTF-8 encoding, so that valid UTF-8 can be\ndistinguished from an arbitrary string in the type system. In such string\nliterals, we should consider rejecting `\\xHH` escapes in which HH is greater\nthan 7F<sub>16</sub>, as in Rust.\n\n## Alternatives considered\n\n### Block string literals\n\nWe could avoid including a block string literal in general, and instead\nconstruct multi-line strings by string concatenation, with either C-style\njuxtaposition or with an explicit concatenation operator. But doing so would be\nmore verbose and would make the expression of the source code be further from\nthe programmer's intent.\n\nWe could use raw string literals to provide block string literal syntax, as C++\ndoes. However, this couples two orthogonal choices: whether escape sequences\nshould be recognized and whether the string is intended to span multiple lines.\nIn C++ code, the inability to use escape sequences in multi-line string literals\nsometimes awkward. For example:\n\n```c++\nstd::string make_rule = \"%s: %s\\n\\t$(CC) -c -o $@ $< $(CFLAGS)\\n\\n\"\n                        \"main:\\n\\t$(CC) %s -o %s\\n\";\n```\n\ncan be written under this proposal as\n\n```carbon\nvar String: make_rule = \"\"\"make\n  %s: %s\n  \\t$(CC) -c -o $@ $< $(CFLAGS)\n\n  main:\n  \\t$(CC) %s -o %s\n  \"\"\";\n```\n\nimproving readability while still making the semantically-meaningful presence of\ntabs visible even in editors / code browsers that do not distinguish tabs from\nspaces.\n\n#### Leading whitespace removal\n\nBlock string literals could use explicit characters in the body to indicate the\namount of leading whitespace to be removed:\n\n```carbon\nvar String: x = \"\"\"\n  |  starts with two spaces.\n  \"\"\";\n```\n\nThis would allow the correct indentation to be determined as soon as the first\nline after the opening `\"\"\"` is seen. However, this adds lexical complexity, and\nharms the ability to copy-paste string contents into other contexts.\n\n#### Terminating newline\n\nWe could choose to exclude the trailing newline (like in Swift). Informal\nsurveys suggest that expectations for whether to include or exclude the trailing\nnewline vary.\n\nThe intended use case for block string literals is to represent multi-line\nstrings. When forming a single larger string from concatenation of multi-line\nstring literals, including the trailing newline but not the leading newline --\nor, more generally, including a newline at the end of each line in the string --\nprovides the best alignment between the source-level syntax and the result. For\nexample:\n\n```carbon\nfn Run() {\n  print(\"\"\"c++\n    class X {\n    public:\n      X() {}\n\n    \"\"\");\n  for (var String: decl in GetMemberDecls()) {\n    print decl;\n  }\n  print(\"\"\"c++\n\n    private:\n    \"\"\");\n  print(GetFields());\n  print(\"\"\"c++\n    };\n    \"\"\");\n}\n```\n\nAs is, the output printed by this example can be visualized by ignoring all\nlines other than those between the `\"\"\"`s. If we excluded the trailing newline,\nadditional blank lines would be required at the end of each string literal,\nharming the readability of the example.\n\n### Escape sequences\n\nWe could support octal escape sequences, as many C family languages do. However,\nthey are considered antiquated in C++ code, and supporting them would be\ninconsistent with our decision to not support octal numeric literals. A quick\ninformal poll suggests that many C++ programmers do not realize that `\\123` is\nan octal escape sequence, not a decimal one.\n\nWe could support `\\123` as a decimal escape sequence. However, doing so may lead\nto surprise when migrating C++ code to Carbon. This possibility should be\nrevisited once Carbon matures and we have a better idea of how the migration\nprocess is expected to proceed.\n\nWe could allow arbitrary-length `\\x` escape sequences, as C++ does, and include\nsome explicit mechanism to terminate such a sequence. For example, we could\ntreat `\\<whitespace>` for an arbitrary whitespace character in the same way we\ntreat `\\<newline>`, and use `\"\\xAB\\ C\"` to terminate an escape sequence\nprematurely. However, this is unnecessarily inventive, and the Python approach\nof requiring exactly two hexadecimal characters after `\\x` is adequate, assuming\nwe do not intend to support string literal element types other than 8-bit bytes.\nIf we do find we want to support wider element types in future (for example, if\nwe want to add a UTF-16 or UTF-32 string literal), `\\x{ABCD}` can be used.\n\nWe could permit `\\<newline>` even in non-block string literals to allow them to\nbe line-wrapped, but there seems to be little benefit to doing so, as a block\nstring literal can always be used instead.\n\nWe could adopt Python's `\\N{unicode character name}` syntax. But there is no\npressing need to add such a syntax imminently, and concerns have been raised\nboth over the exact ways in which characters are named and over compatibility\nwith upcoming C++ language extensions in this area, so this syntax is not being\nproposed at this time.\n\nWe could allow an `\\e` escape sequence for the U+001C ESCAPE character. This\ncharacter is a common extension in C and C++ compilers, and appears to primarily\nbe used to hardcode ANSI terminal escape sequences, such as\n`\"\\e[32mgreen text\\e[0m\"`. This proposal doesn't explicitly reject this idea.\nHowever, if we consider adopting such an extension in the future, we should\nconsider whether a library facility for simple terminal operations would be a\nmore valuable addition than this escape sequence.\n\nWe could retain the `\\uNNNN` escape sequence to give a terser notation for the\ncommon case of a Unicode code point that is most naturally written as four\nhexadecimal digits -- that is, all code points in the Basic Multilingual Plane.\nThis is the approach taken by JavaScript. However, following Swift and Rust in\npermitting only `\\u{NNNN}` is simpler and avoids redundancy. We expect explicit\n`\\u` escapes to be rare: we expect regular, printable Unicode characters that\nare normalized in NFC to be written directly in the source file, rather than\nspelled with `\\u` escapes. Explicit `\\u` escapes would be useful where the code\npoint value is important -- for example, in test data -- or where special\ncharacters such as directionality markers or non-normalized characters are\ndesired, but for such uses, the longer `\\u{NNNN}` form seems adequate.\n\n### Raw string literals\n\nThe approach to raw string literals in this proposal is based on Swift's raw\nstrings facility.\n\nWe could use a different mechanism other than a sequence of `#`s to support\nnesting raw string literals. For example, we could adopt something like C++'s\nsemi-arbitrary delimiters `R\"foo(string contents)foo\"`. However, this level of\ncustomizability seems unwarranted: raw string literals are unlikely to nest more\nthan one or two levels deep, so using `#\"...\"#`, `##\"...\"##`, `###\"...\"###` for\nsuccessive nesting levels seems unproblematic, and removes the need for the\nprogrammer to make an arbitrary choice.\n\nWe could use a delimiter other than `#` to demarcate raw string literals. At\nthis stage in Carbon's development, we don't know exactly which characters will\nbe useful in operators, but it seems reasonable to assume a mostly C++-like\noperator set, which gives us a variety of characters that cannot appear\nimmediately before a string literal: at least `@` `#` `$` `)` `]` `}` `\\` `.`\nall appear likely to be available. Of these, `\\` is likely to be problematic due\nto its use in escape sequences, closing brackets followed by string literals\nmight one day be useful in some grammar constructs, and `.` seems a little too\nclose to resembling designator. That leaves `@`, `#`, and `$`, and multiple\nexisting languages have used `#` for this purpose.\n\nWe could disallow use of _N_ `#`s as a delimiter if a lower value of _N_ would\nwork. However, this would make the language brittle under maintenance: removing\nthe last nested string literal from a quoted block of code would require\nchanging the delimiters.\n\nWe could use Rust-style raw strings, which add a leading `r`, permit zero `#`s\nto be used in raw strings, and do not provide a facility for escape sequences in\nraw strings. There are several reasons to prefer Swift-style raw strings:\n\n-   Swift raw strings are not a distinct language feature; rather, they are a\n    generalization of non-raw strings -- non-raw strings are simply the case\n    where the number of `#` characters in the delimiters and escape sequence\n    introducer is zero.\n-   Permitting escape sequences even in raw strings means that there is no loss\n    of functionality when using a raw string, and code changes under maintenance\n    that would require use of a facility only available by way of an escape\n    sequence (such as inclusion of trailing whitespace in a block string\n    literal) do not force a reversion to a non-raw string literal.\n\nThere are also several reasons to prefer the Rust-style approach:\n\n-   In the most common case, a Rust raw string will be one character shorter.\n-   Less lexical space is used: Swift-style raw strings remove the possibility\n    of using `#` as a prefix operator, whereas the leading `r` in Rust-style raw\n    strings does not.\n-   Certain character sequences are hard to express in Swift-style raw strings.\n    Specifically, string literals such as `\"\\\\################\"` cannot readily\n    be expressed as a raw string. Such string literals are extremely rare, but\n    not nonexistent, in one large sample C++ corpus.\n\nIf the final issue is concerning, we have a path to address it, by specifying\nthat `\\` followed by <i>N</i>+1 or more `#`s is left alone, just like `\\`\nfollowed by <i>N</i>-1 or fewer `#`s is left alone. Formally, this can be\naccomplished by defining `\\#` as an escape sequence that expands to itself, that\nis, to a backslash followed by <i>N</i>+1 `#` characters.\n\n#### Trailing whitespace\n\nWe could preserve trailing whitespace in at least raw block string literals, and\nperhaps in all block string literals. However, this would mean that visually\nidentical programs could have different meanings, and even that transformations\nperformed automatically on save by some editors (removing trailing whitespace)\ncould change the meaning of a program. It might also mean that raw string\nliterals are no longer a generalization of non-raw string literals.\n\nUnder this proposal, trailing whitespace can be included in a block string\nliteral by following it with `\\n\\`:\n\n```\nvar String: authors = \"\"\"markdown\n  *Authors*:  \\n\\\n  Me <me@example.com>  \\n\\\n  Someone Else <them@example.com>\n\n\"\"\";\n```\n\nIn a single-`#` raw string literal, the same can be accomplished with the\nmore-verbose terminator `\\#n\\#`, and so on.\n\n#### Line separators\n\nRaw block string literals could preserve the form of vertical whitespace used to\nterminate each line. This would allow uncommon forms of vertical whitespace (for\nexample, vertical tab and form feed) to be included in raw string literals, but\nwould create a risk that the meaning of a program would be different when the\nsource code is checked out on an operating system that uses line feed as a line\nterminator versus when the source code is checked out on an operating system\nthat uses a different line terminator (such as carriage return followed by line\nfeed). This would also mean that raw string literals are no longer a\ngeneralization of non-raw string literals.\n\n### Internal whitespace\n\nWe could allow raw tab characters in string literals. However, raw tab\ncharacters harm the readability of the program, and we would like to encourage\nthe use of `\\t` escapes instead in situations where they are available, even if\nthis means that the more verbose form `\\#t` needs to be used in raw string\nliterals.\n\n## Rationale\n\nThis proposal supports the goal of making Carbon code\n[easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\nby ensuring that essentially every kind of string content can be represented in\na Carbon string literal, in a way that is natural, toolable, and easy to read:\n\n-   Multi-line strings are supported by multi-line string literals, and the\n    rules for stripping leading indentation enhance readability by allowing\n    those literals to avoid visually disrupting the indentation structure of the\n    code.\n-   Strings that make extensive use of `\\` and `\"` are supported by raw string\n    literals.\n-   Treating raw versus ordinary and single-line versus multi-line as orthogonal\n    allows Carbon to support all 4 combinations while keeping the language\n    simple.\n-   The handling of `\\#` within raw string literals makes it possible to use\n    escape sequences within raw string literals when necessary, for example to\n    embed arbitrary byte values or Unicode data. This ensures that the\n    programmer is never prevented from using a raw string literal, or forced to\n    assemble a single logical string by concatenating ordinary and raw literals\n    (with the negligible and fixable exception of strings like\n    `\"\\\\################\"`, as noted in the proposal).\n-   \"File type indicators\" make it easier for tooling to understand the contents\n    of literals, in order to provide features such as syntax highlighting,\n    automated formatting, and potentially even certain kinds of static analysis,\n    for code that's embedded in string literals.\n-   Support for non-Unicode strings by way of `\\x` ensures \"support for software\n    outside the primary use case\".\n-   Avoids unnecessary invention, following Rust and particularly Swift.\n"
  },
  {
    "path": "proposals/p0253.md",
    "content": "# 2021 Roadmap\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/253)\n\n## Objective for 2021: speed up Carbon development\n\nThe main objective of the Carbon project in 2021 is to speed up the development\nof the project, even while it remains both an experiment and private. This will\nrequire improving at least two dimensions:\n\n-   Increase the investment by existing individuals and organizations.\n-   Increase the breadth of different individuals and organizations investing in\n    Carbon.\n\nWe expect to make progress on this objective in 2021 primarily by making\nCarbon's design more concrete and with a more specific and easily understood\nvalue proposition. As a result, our key results are primarily around specific\nartifacts that we think will help support the scaling up of Carbon development\nefforts.\n\nWe also need to identify key missing participants and onboard them\nthroughout 2021.\n\n## Key results in 2021\n\nThere are several milestones that we believe are on the critical path to\nsuccessfully achieving our main goal for the year, and point to concrete areas\nof focus for the project.\n\n### Broaden core team representation so no organization is >50%\n\nOur goal is that no single organization makes up >50% of the core team to ensure\nthat we are including as broad and representative a set of perspectives in the\nevolution of Carbon as possible.\n\n### Example ports of C++ libraries to Carbon (100% of [woff2](https://github.com/google/woff2), 99% of [RE2](https://github.com/google/re2))\n\nThe first part of this result is that all of the woff2 library is ported to\nCarbon in a way that exports the same C++ API. There should be no gaps in this\nport given that woff2 has a very simple C++ API and uses few C++ language\nfeatures.\n\nRE2 is a larger library using significantly more language features. For that\npart of the result, fewer than 1% of its C++ lines of code should be missing a\nsemantically meaningful port into Carbon code.\n\nAn important nuance of this goal is that it doesn't include building a complete\nCarbon standard library beyond the most basic necessary types. The intent is to\nexercise and show the interoperability layers of Carbon by reusing the C++\nstandard library in many cases and exporting a compatible C++ API to both woff2\nand RE2's current API.\n\nWhile this key result isn't directly tied to the main objective, we believe it\nrepresents a critical milestone for being able to achieve this objective. It\nboth measures our progress solidifying Carbon's design and demonstrating the\nvalue proposition of Carbon.\n\nNote that both woff2 and RE2 libraries are chosen somewhat arbitrarily and could\neasily be replaced with a different, more effective libraries to achieve the\nfundamental result of demonstrating a compelling body of cohesive design and the\noverarching value proposition.\n\n#### Language design covers the syntax and semantics of the example port code.\n\nWe should have a clear understanding of the syntax and semantics used by these\nexample ports. While this should include accepted proposals, it doesn't\nnecessarily require either formal specification or implementation.\n\n### Demo implementation of core features with working examples\n\nA core set of Carbon features should be implemented sufficiently to build\nworking examples of those features and run them successfully. These features\ncould include:\n\n-   User-defined types, functions, namespaces, packages, and importing.\n-   Basic generic functions and types using interfaces.\n-   Initial/simple implementation of safety checking including at least bounds\n    checking, simple lifetime checking, and simple initialization checking.\n-   Sum types sufficient for optional-types to model nullable pointers.\n-   Pattern matching sufficient for basic function overloading on types and\n    arity, as well as unwrapping of optional types for guard statements.\n\nStretch goals if we can hit the above:\n\n-   Instantiating a basic C++ template through interop layer for use within\n    Carbon.\n\nThe demo implementation should also provide demos outside of specific language\nfeatures including:\n\n-   Basic benchmarking of the different phases of compilation (lexing, parsing,\n    etc).\n-   A basic REPL command line.\n\nStretch goals if we can hit the above:\n\n-   Automatic code formatter on top of the implementation infrastructure.\n-   A [compiler explorer](https://compiler-explorer.com/) fork with REPL\n    integrated.\n\nBenchmarking at this stage isn't expected to include extensive optimization.\nInstead, it should focus on letting us track large/high-level impact on\ndifferent phases as they are developed or features are added. They may also help\nillustrate initial high-level performance characteristics of the implementation,\nbut the long term focus should be on end-to-end user metrics.\n\nAutomatic code formatting could be achieved many ways, but it seems useful to\nensure the language and implementation both support use cases like formatting.\n\n### Executable semantic specification for core features with test cases\n\nThis should include both a human readable rendering of the formal semantics as\nwell as an execution environment to run test cases through those semantics. The\ncore features which should be covered by these semantics are:\n\n-   User-defined types, functions, namespaces, packages, and importing.\n-   Basic generic functions and types using interfaces.\n-   Sum types sufficient for optional-types to model nullable pointers.\n\nThis is intentionally a subset of the features covered by the demo\nimplementation. The intent is to reflect that _completing_ coverage of the\nfeatures in the specification is a slightly lower priority, and instead we\nshould rapidly spike out as complete of a demo as possible and come back to the\nsemantics if possible.\n\n## Beyond 2021\n\nLonger term goals are hard to pin down and always subject to change, but we want\nto give an idea of what kinds of things are expected at a high level further out\nin order to illustrate how the goals and priorities we have in 2021 feed into\nsubsequent years.\n\n### Potential 2022 goals: finish 0.1 language, make it public\n\nWe expect that at some point in 2022 we will need to shift the experiment to be\npublic. This will allow us to significantly expand both those directly involved\nand contributing to Carbon but also those able to evaluate and give us feedback.\n\nWe don't expect Carbon to shift away from an experiment until after it becomes\npublic and after we have been able to collect and incorporate a reasonable\namount of feedback from the broader industry and community.\n\nWe'll also need to start broadening our scope:\n\n-   Expand the standard library to at least cover everything needed for self\n    hosting.\n-   Develop initial C++ to Carbon migration tooling.\n\n### Potential 2023 goals: finish 0.2 language, stop experimenting\n\nOnce Carbon is moving quickly and getting public feedback, we should be able to\nconclude the experiment. We should know if this is the right direction for\nmoving C++ forward for a large enough portion of the industry and community, and\nwhether the value proposition of this direction outweighs the cost.\n\nHowever, there will still be a _lot_ of work to make Carbon into a production\nquality language, even if the experiment concludes successfully.\n\nSome concrete goals that might show up in this time frame:\n\n-   Self-hosting toolchain, including sufficient Carbon standard library\n    support.\n-   Expand design of standard library to include, at least directionally,\n    critical and complex areas. For example: concurrency/parallelism and\n    networking/IO.\n-   Migration tooling sufficient to use with real-world libraries and systems.\n    This might be used to help with self-hosting Carbon, as well as by initial\n    early adopters evaluating Carbon.\n\n### Potential 2024-2025 goals: _ship_ 1.0 language & organization\n\nA major milestone will be the first version of a production language. We should\nalso have finished transferring all governance of Carbon to an independent open\nsource organization at that point. However, we won't know what a more realistic\nor clear schedule for these milestones will be until we get closer.\n\nAnother important aspect of our goals in this time frame is expanding them to\nencompass the broader ecosystem of the language:\n\n-   End-to-end developer tooling and experience.\n-   Teaching and training material.\n-   Package management.\n-   Etc.\n\n## Rationale\n\nBy its nature, we're not sure a planning document like this can directly advance\nCarbon's goals, but we think this roadmap does a good job of keeping us focused\non the work that will help us generate concrete evidence as to whether Carbon is\nlikely to successfully achieve those goals (and help us figure out how to\ncourse-correct if it's not). Increasing the representation of non-Googlers on\nthe core team is an important indicator (as well as enabler) of building an\n\"open and inclusive community\", not to mention of having a broad enough user\nbase to succeed, and the example ports, demo implementation, and executable\nsemantics will help us concretely evaluate how well Carbon is meeting all of its\nlanguage goals.\n\nIn addition, as the proposal argues, concrete evidence that Carbon can succeed\nwill indirectly help Carbon make faster progress, by motivating further\ninvestment in the project. Some aspects of the roadmap will also help accelerate\nCarbon's development in more direct ways. In particular, the executable\nsemantics implementation should enable Carbon contributors to rapidly prototype\npotential new features, which will help us identify and solve more problems at\nan earlier stage, and have higher confidence in the proposals we adopt.\n\nWhile rapid progress is not an explicit goal of the Carbon project, Carbon can't\nmeet any of its other goals until it exists in a usable form, and the longer it\ntakes to reach that point, the less likely it is to reach it at all.\n"
  },
  {
    "path": "proposals/p0257.md",
    "content": "# Initialization of memory and variables\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/257)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Unformed objects](#unformed-objects)\n        -   [Representation](#representation)\n        -   [Address-of and escape](#address-of-and-escape)\n        -   [Types with an unformed state](#types-with-an-unformed-state)\n        -   [Raw storage and padding](#raw-storage-and-padding)\n    -   [Necessary initialization](#necessary-initialization)\n    -   [Optional features for unformed states](#optional-features-for-unformed-states)\n        -   [Hardening initialization](#hardening-initialization)\n        -   [Queryable unformed state](#queryable-unformed-state)\n    -   [Function returns and initialization](#function-returns-and-initialization)\n        -   [Declared `returned` variable](#declared-returned-variable)\n    -   [Constructors and initializing aggregate objects](#constructors-and-initializing-aggregate-objects)\n        -   [No unformed members](#no-unformed-members)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Require compile-time-proven initialization](#require-compile-time-proven-initialization)\n        -   [Trivially required initialization, with no escape hatch](#trivially-required-initialization-with-no-escape-hatch)\n        -   [Initialize on all branches prior to use (Rust, C#, TypeScript)](#initialize-on-all-branches-prior-to-use-rust-c-typescript)\n        -   [Definitive initialization (Swift)](#definitive-initialization-swift)\n    -   [C and C++ uninitialized](#c-and-c-uninitialized)\n    -   [Allow passing unformed objects to parameters or returning them?](#allow-passing-unformed-objects-to-parameters-or-returning-them)\n    -   [Allow assigning an unformed object to another unformed object?](#allow-assigning-an-unformed-object-to-another-unformed-object)\n    -   [Fully destructive move (Rust)](#fully-destructive-move-rust)\n    -   [Completely non-destructive move (C++)](#completely-non-destructive-move-c)\n    -   [Named return variable in place of a return type](#named-return-variable-in-place-of-a-return-type)\n    -   [Allow unformed members](#allow-unformed-members)\n        -   [Summary of advantages and disadvantages](#summary-of-advantages-and-disadvantages)\n\n<!-- tocstop -->\n\n## Problem\n\nHow should Carbon handle uninitialized memory and variables? There are a number\nof goals we would like to satisfy in this space:\n\n-   Minimize the overhead (in optimized builds) of unnecessary initialization.\n-   Detect and diagnose bugs in code where variables are used without being\n    initialized first at lower cost than a separate and unscalable build mode\n    (MSan for C++).\n-   Avoid the ergonomic, readability, and at times correctness issues when\n    forced to initialize all variables at the point of declaration, even if\n    there is no intentional value to yet use.\n-   Minimize the security risk posed by accidental access of uninitialized\n    memory.\n-   Avoid unnecessary overhead for dynamic tracking of whether a variable is\n    initialized.\n-   Avoid unnecessarily running destructors for variables when they haven't yet\n    been initialized or used.\n-   Allow most types similar ergonomics and behaviors as a simple machine\n    integer type.\n-   Offer similar behavior regardless of storage location (stack, heap,\n    thread-local-storage, static / global storage).\n-   Leave a path to add more strict safety rules in the future, such as\n    requiring explicit marking when the address of an uninitialized variable\n    escapes.\n\nPart of our goal is also to support code patterns such as:\n\n```\n  // At block scope of some function...\n  var temporary: Int;\n  while (...) {\n    // ... code not using `temporary` ...\n\n    temporary = ...;\n    // ... code using `temporary` ...\n  }\n```\n\nThat is, we also don't want to force a _syntactic_ distinction when an\nassignment occurs to an already initialized variable. That would end up with\nfundamentally similar ergonomic (and potentially performance) overheads as\nforcing initialization as part of declaration. Throughout this document, the\nterm \"assignment\" should instead be understood as the operation that can be used\nin this construct.\n\nThese problems are also tightly related to the problems of _moved-from_\nsemantics. These semantics might range from completely non-destructive (as in\nC++) to completely destructive (as in Rust). A compelling solution for the\nvariable initialization challenges can also provide a compelling approach for\nmoved-from semantics that represents a middle ground between the two extremes\nseen in C++ and Rust. For example, we propose that the following should hold\nequally for moved-from objects and objects without an explicit initializer:\n\n-   The object must not be used in any way other than assignment or destruction.\n    -   Note that this refers to the _object_. Taking the address is fine, but\n        the restrictions here on how the object is used apply equally to any\n        uses through a pointer to the object.\n-   It must be possible to transition it to a valid, normal object through\n    assignment.\n-   It should be allowed to destroy them.\n-   It should not be necessary to destroy them.\n\n## Background\n\n-   [Definitive assignment or definitive initialization](https://en.wikipedia.org/wiki/Definite_assignment_analysis)\n    (used by Swift, Java, and so on)\n-   [Rust checked uninitialized data](https://doc.rust-lang.org/nomicon/checked-uninit.html)\n-   [Elements of Programming](http://elementsofprogramming.com/eop_bluelinks.pdf)\n-   [P2025 - Guaranteed copy elision for named return objects](http://wg21.link/p2025)\n\n## Proposal\n\nWe propose two fundamental concepts:\n\n1. An _unformed state_ for objects.\n2. Raw, uninitialized storage.\n\nThe first of these is a new concept and is discussed in detail below. However,\nuninitialized storage in Carbon should work in the same way as an uninitialized\narray of `unsigned char` or `std::byte` in C++. This is intended primarily to\nserve the needs of custom data structures such as C++'s `std::vector` or\nwhatever Carbon ends up with as an `Optional(T)` type. With such raw storage,\ninitialization and destruction of any objects within the storage must be managed\nmanually and externally and the language won't provide any automatic mechanisms.\nThe detailed syntax for working with raw storage in this manner is left to a\nsubsequent proposal.\n\n### Unformed objects\n\nAn _unformed_ state is a state of an _object_. We both classify _objects_ based\non whether they are in an unformed state or a fully formed state, as well as\nclassify _types_ which support unformed states at all versus types that require\nobjects to always be in a fully formed state.\n\nAn unformed state for an object is one that satisfies the following properties:\n\n-   Assignment from a fully formed value is correct using the normal assignment\n    implementation for the type.\n-   Destruction must be correct using the type's normal destruction\n    implementation.\n-   Destruction must be optional. The behavior of the program must be equivalent\n    whether the destructor is run or not for an unformed object, including not\n    leaking resources.\n\nAny operation on an unformed object _other_ than destruction or assignment to a\nfully formed value is an **error**, including:\n\n-   Comparisons with other objects.\n-   Passing an unformed object to a function or returning it.\n-   Initializing or assigning _with_ an unformed object, including all forms of\n    self assignment or self swap:\n\n    ```\n    var unformed_x: Int;\n\n    // Each line mentioning `unformed_x` below is an error:\n    var a: Int = unformed_x;\n    var b: Int = 42;\n    b = unformed_x;\n    var unformed_c: Int;\n    unformed_c = unformed_x;\n    unformed_x = unformed_x;\n\n    // If we imagine a move operation similar to C++'s `std::move` spelled `~`\n    // and a function `Swap` similar to C++'s `std::swap` but using pointers,\n    // these too are errors:\n    unformed_x = ~unformed_x;\n    Swap(&unformed_x, &unformed_x);\n    ```\n\nThese errors should be diagnosed as early as possible in a debug build and at\nleast at runtime. In a performance build, it may lead to undefined behavior, but\nin a hardened build we have a strong mitigation that restores safety by defining\nthe behavior using a maximally safe representation.\n\nWhen a variable is declared without initialization, such as:\n\n```\nvar x: Int;\n```\n\nThe variable is implicitly initialized to its type's unformed state and\nrepresents an unformed object.\n\nIt is invalid to declare a variable without explicit initialization unless its\ntype implements the interface to specify how to do that initialization. For\ntypes that do not support initializing the variable to an unformed state, the\nprogrammer must either explicitly initialize it to a valid and fully formed\nstate for the type, or must change the type to something like an `Optional(T)`\nthat introduces an unformed state (and the dynamic tracking necessary to\nimplement it) alongside raw storage for the underlying object.\n\n#### Representation\n\nThe unformed state can have the same representation as valid and fully formed\nstates for the object (for example, an empty `Optional(T)`). While there is a\nsemantic difference (any operation _other_ than assignment and destruction is an\nerror for an unformed object), there is no problem reusing a representation\nwhich is also used for fully formed and valid objects provided it satisfies all\nthree of the above constraints. The semantic restrictions remain even in this\ncase. Using the hypothetical `Optional(T)` API, we could imagine:\n\n```\nvar formed: Optional(T) = .Empty;\n// This is of course fine.\nif (formed.empty()) { ... }\n\nvar unformed: Optional(T);\n// This would be an error even though `unformed` might have identical\n// in-memory representation or bit-pattern to `formed`:\nif (unformed.empty()) { ... }\n```\n\n#### Address-of and escape\n\nIt is allowed to take the address of an unformed object and escape it to another\nfunction. This function may even be responsible for assigning a fully formed\nobject to that location.\n\n```\nfn AssignIntTo(x: Int, destination: Int*) {\n  *destination = x;\n}\n\nfn Example() {\n  var y: Int;\n  // `y` is unformed here.\n  AssignIntTo(42, &y);\n  // `y` is fully formed and usable.\n}\n```\n\nThis in turn is part of why it is important that the destructor is _allowed_ to\nbe run on an unformed object. This gives us a conservatively correct way to\nimplement code where it may be impossible to know whether the object has been\ninitialized to a fully formed object, and similarly code where it is impossible\nto know whether the object has been moved-from. Consider some `HashMap`\ncontainer with allocated memory where the destructor _must_ be run to release\nthe memory:\n\n```\nfn MaybeInitializes(map: HashMap*);\nfn MaybeMovesFrom(map: HashMap*);\n\nfn Example() {\n  var map: HashMap;\n  MaybeInitializes(&map);\n  if (...) {\n    // Don't know if we need to destroy `map`. But conservatively we can run the\n    // destructor unconditionally.\n    return;\n  }\n\n  // Unconditionally assign a particular value to our map.\n  map = ...;\n  MaybeMovesFrom(&map);\n\n  // `map` could be unformed (due to being moved from) or still fully formed.\n  // Run the destructor unconditionally to be safe.\n  return;\n}\n```\n\n#### Types with an unformed state\n\nThe intent is that most types have an unformed state, as it will let types \"be\nlike the `int`s\" -- we design it to closely match how machine integers actually\nbehave in modern optimizing compilers: when left \"uninitialized\" they can be\nsafely _assigned_ or _destroyed_. But running the destructor is _optional_.\n\nTypes can opt into this semantic model and define an explicit operation to\ncreate a type in the unformed state by implementing an interface. Because this\nwill be defined semantically by the existence of an implementation of the\nrelevant interface, and operationally by providing code to produce an unformed\nobject, there is no specific bit pattern or representation encoded for the\nunformed state. The interface should provide a default implementation for types\nwhere all members have an implementation which recurses member-wise.\n\nIt is reasonable to wonder if types where the default implementation is valid\nimplicitly implement the interface, or should it require an explicit opt-in?\nInitially we suggest this should be explicit. There may grow to be a set of\ninterfaces which should be implicitly implemented due to their prevalence, but\nit seems better to be conservative at first and approach that systematically.\n\nNote that this state is similar but more restrictive than the _partially formed\nstate_ from Elements of Programming (EoP) in section 1.5.\n\n#### Raw storage and padding\n\nRaw storage and padding bytes are treated like they always consist of unformed\nbytes. We propose not allowing sub-byte raw storage or padding.\n\nPadding bytes have specific practical considerations. It is fine for operations\nthat work across all bytes of raw storage, such as C-style routines like\n`memset` and `memcpy`, to write to padding bytes. But doing so has no observable\neffect, and even if they notionally set padding bytes to a known value, the\npadding bytes continue to behave as if they are unformed bytes.\n\nCopying _from_ padding bytes is significantly more difficult because it risks\nopening up the possibility of copying unformed objects more generally. That has\nsignificant downsides and we are proposing it is\n[not allowed](#allow-assigning-an-unformed-object-to-another-unformed-object).\nInstead, there will need to be a low-level language facility that specifically\nhandles copying storage with padding bytes. Such a facility would have to either\nexclude the padding bytes from the copy, or provide a strong guarantee that they\nare only ever _directly_ copied into other padding bytes without any\nintermediate steps.\n\n### Necessary initialization\n\nSome types will not provide an unformed state. Variables of such types must be\ninitialized when declared:\n\n```\nstruct NecessaryInit {\n  var m: Mutex;\n\n  // Potentially other members without a meaningful unformed state.\n}\n\n// This line would be an error:\nvar error_no_init: NecessaryInit;\n```\n\nFor these types, the programmer must either explicitly initialize it to a valid\nand fully formed state for the type, or must change the type to something like\nan `Optional(T)` that introduces an unformed state (and the dynamic tracking\nnecessary to implement it) alongside raw storage for the underlying object:\n\n```\n// This is fine, it contains the boolean necessary to track initialization.\nvar ok: Optional(NecessaryInit);\n```\n\n### Optional features for unformed states\n\nThere are two _optional_ aspects of unformed states that types may elect to\nexplicitly specify (again by implementing interfaces, here by specializing the\nimplementation rather than relying on the default fallback).\n\n#### Hardening initialization\n\nFirst, types may customize how to further initialize an object that is in the\nunformed state to most effectively harden it against erroneous usage. For\nexample, the unformed state of an `Int` is trivial -- it can simply be left\nuninitialized. However, it can be hardened against bugs by setting it to zero.\nUser defined types have the option of specifying a specific routine to do\nsimilar hardening initialization. The entire storage, including any padding\nbytes, for all types will be at least be zeroed as part of hardening\ninitialization. This routine simply allows a user defined type to specifically\ncustomize the hardening initialization of some parts or members of the object to\nvalues other than zero.\n\n#### Queryable unformed state\n\nThe second optional aspect is implementing a test for whether an object is\nunformed. This test cannot be run by user code -- doing so would be a bug due to\nreferencing an unformed object. However, for types where the unformed state is\nintrinsically distinct from any other state, they can expose the ability to\nquery this. That allows debug builds of Carbon to verify objects are fully\nformed prior to use without external tracking state. Types which do not\nimplement this functionality will still get partial checking in debug builds\nthrough external state, but may lose dynamic enforcement across ABI boundaries\nwhere this extra state cannot be propagated. These are also the boundaries\nacross which the hardening will be done to ensure bugs across those boundaries\ncannot become security vulnerabilities in the hardened build configuration.\n\n### Function returns and initialization\n\nThis proposal also has implications for returning values from functions,\nespecially as it relates to how Carbon can provide similar functionality to\nguaranteed return value optimization (RVO) and named return value optimization\n(NRVO) in more principled ways than C++ does. While these facilities should\nallow Carbon to not require tricks like NRVO and the dangers that come with\nthem, the primary motivation is to increase the expressivity of \"normal\"\nfunction returns in order to address complex use cases in object\n[construction](#constructors-and-initializing-aggregate-objects).\n\nConsider the following common initialization code:\n\n```\nfn CreateMyObject() -> MyType {\n  return <return-expression>;\n}\n\nvar x: MyType = CreateMyObject();\n```\n\nWe propose that the `<return-expression>` in the `return` statement of\n`CreateMyObject` _initializes_ the variable `x` here. There is no copy, etc. It\nis precisely the same as:\n\n```\nvar x: MyType = <return-expression>;\n```\n\nWe also propose this applies _recursively_. This matches how C++ has evolved\nwith \"guaranteed copy elision\".\n\nHowever, while most C++ implementations provide a \"named return value\"\noptimization that applies the performance benefits of this to returning a named\nvariable, it has proven extremely difficult to _automatically_ provide\n\"guaranteed copy elision\" when returning a named variable. The determining\nfactors for whether it can be safely applied change significantly based on\noptimization levels and numerous other implementation details. The result has\nbeen repeated requests from users and proposals to provide an explicit syntax\nfor marking a named variable as being returned and then both _guaranteeing_ the\ncopy elision takes place, and requiring that all returns are of the variable and\ncompatible with that elision.\n\nWhile these proposals have hit issues in C++ due to compatibility concerns and\ncomplexity in C++ itself, those won't apply to Carbon. We suggest that Carbon\nshould provide a direct mechanism for this with a named return variable which\nobeys the same initialization rules as any other variable.\n\nAn important aspect of any approach to named return variables is that, much like\nwith normal return values, there is no copy when initializing. This means that\nthe address of `result` in the examples below of `CreateMyObject2` and\n`CreateMyObject3` are the same as the address of `y` during the evaluation of\n`y`'s initialization expression. Only one variable is created. It is first\ninitialized to an unformed state on entry to `CreateMyObject2` and assigned to a\nfully formed value internally.\n\n#### Declared `returned` variable\n\nWe propose to allow a specific variable within the function body to be declared\nas `returned` from the function. Assuming that `MyType` has an unformed state,\nthe alternative to the above syntax would be:\n\n```\nfn CreateMyObject2() -> MyType {\n  returned var result: MyType;\n  // Any code we want here.\n\n  result = CreateMyObject();\n\n  // Must explicitly use the variable return syntax rather than returning an expression.\n  return var;\n}\n```\n\nAnd we can initialize the return variable to remove the unformed requirement:\n\n```\nfn CreateMyObject3() -> MyType {\n  // Any code we want here.\n\n  returned var result: MyType = CreateMyObject();\n\n  // Potentially more code...\n  return var;\n}\n```\n\n**Minor syntax variations (not proposed):**\n\n-   Just use `return;` rather than `return var;` for the actual control flow\n    return.\n    -   The ceremony here is intended to distinguish from the case of a function\n        that doesn't have a return value at all, but it could be removed.\n-   Require `return <name>;` where `<name>` is constrained to match the declared\n    variable name.\n    -   One concern with this is that the `<name>` here is not an expression --\n        it isn't evaluated or anything and must be just a name. Worse, there\n        might not _be_ a single name.\n    -   However, if there were good syntax, it might help with scoping.\n-   Maybe better syntax than `returned var` and `return var`, open to follow-up\n    proposals to tweak the exact syntax of both sides of this.\n\nWe expect subsequent proposals to generalize this facility to non-`var`\ndeclarations where there is a reasonable and clear semantic. However, it should\nbe noted that for `var`-style declarations in particular where the address of\nthe object can be taken, the entire declared object must be marked as `returned`\n-- it cannot be a component of the pattern alone.\n\nWe also propose a set of rules to use for the types in the pattern, and to what\ndegree they must match the return type: whatever type would be the _allocated_\ntype of the variable declaration must match the return type. For declarations\nthat produce storage such as `var`, the entire allocated object based on the\npattern must match the return type. If this is generalized to non-allocating\npatterns, it would be fine to use any pattern that can match the return type.\n\nThe initializer expression must initialize the declared return type, and then\nany pattern match is done.\n\nControl flow presents some challenging questions for this design. Consider code\nwith the following structure:\n\n```\nfn ReturnEitherOr(...) -> MyType {\n  // ...\n  if (...) {\n    returned var result1: MyType = ...;\n    // ...\n    return var;\n  } else if (...) {\n    returned var result2: MyType = ...;\n    // ...\n  } else {\n    returned var result3: MyType = ...;\n    // ...\n  }\n  // ...\n  return var;\n}\n```\n\nIt seems like at least `result1` should be valid. What about `result2` and\n`result3`?\n\nMore complex control flow patterns grow the complexity this presents. For\nexample:\n\n```\nfn ReturnVarWithControlFlow() -> Point {\n  if ... {\n    // Is this allowed?\n    returned var p1: Point = ...;\n\n    if ... {\n      // This seems fine to return `p1`.\n      return var;\n    }\n  }\n  if ... {\n    // But this would have to be an error...\n    return var;\n  }\n\n  // And what happens here?\n  returned var p2: Point = ...;\n\n  for ... {\n    // Or here?\n    returned var p3: Point = ...;\n\n    // Even though we might actually return...\n    if ... {\n      return var;\n    }\n  }\n  // Definitely no way to know what happens here between p1, p2, and p3.\n  return var;\n}\n```\n\nWe propose a set of restrictions to give simple and understandable behavior\nwhich remains reasonably expressive.\n\n1. Once a `returned var` is in scope, another `returned var` cannot be declared.\n2. Any `return` with a `returned var` in scope must be `return var;` and returns\n   the declared `returned var`.\n3. If control flow exits the scope of a `returned var` in any way other than a\n   `return var;`, it ends the lifetime of the declared `returned var` exactly\n   like it would end the lifetime of a `var` declaration.\n4. There must be a `returned var` declaration in scope when the function does a\n   `return var;`.\n\nA consequence of these rules allows code like:\n\n```\nfn MaybeReturnedVar() -> Point {\n  {\n    returned var p: Point = ...;\n    if ... {\n      return var;\n    }\n  }\n\n  return MakeMeAPoint();\n}\n```\n\n### Constructors and initializing aggregate objects\n\nConstructors of user defined aggregate types can present specific problems with\ninitialization because they intrinsically operate on types prior to all of their\ninvariants being established and when a valid value may not (yet) exist for\nsubobjects such as members. These problems are discussed in detail in the blog\npost\n[\"Perils of Constructors\"](https://matklad.github.io/2019/07/16/perils-of-constructors.html).\nA primary goal in trying to solve these problems is being able to separate the\nphase of initializing members (or other kinds of subobjects) prior to the outer\nobject existing and establishing any necessary invariants without creating holes\nin the type system soundness. An interconnected problem is correctly running\ndestructors (in order to release any acquired resources) in the event of errors\n_during_ construction.\n\nThe behavior of function returns provides interesting build blocks to write code\nthat addresses these problems. They provide a natural set of tools to build two\nphases of a constructor: code that executes before a valid object exists and\ncode that executes afterward. It even gives a clear demarcation between these\nphases. Adding `returned` variable declarations provide an important building\nblock for solving these problems.\n\n```\nstruct Point {\n  var x: Int;\n  var y: Int;\n}\n\nfn PointConstructorPreObjectPhase() -> Point {\n  // Code that runs prior to an object existing.\n  // Just assembles inputs needed to initialize the members.\n  return (<x-expression>, <y-expression>);\n}\n\nfn ComplexTwoPhasePointConstructor() -> Point {\n  // Code that runs prior to an object existing.\n  var x_init: Int = ...;\n  var y_init: Int = ...;\n\n  returned var p: Point = (x_init, y_init);\n  // `p` is now fully formed, and its destructor *must* run.\n\n  // More code that uses p can go here.\n  return var;\n}\n```\n\n#### No unformed members\n\nThis proposal suggests disallowing unformed members -- objects must be\ncompletely formed or completely unformed. Allowing mixing of formed and unformed\nmembers in an object introduces significant complexity into the language without\nadvantages, and the code patterns that result scale poorly to real world\nexamples. For details on what it would look like to allow these and how this\ngoes wrong, see the [alternative section](#allow-unformed-members)\n\nNote that inheritance opens a set of closely related but also importantly\ndifferent concerns as members here and this proposal doesn't take any position\none way or another there. If and when there is a proposal for how inheritance\nshould work in Carbon, it should address this question.\n\n## Rationale based on Carbon's goals\n\nThis model is designed to give significant control to users of Carbon for\nmaximizing performance around variable initialization, which matches the primary\ngoal of Carbon for performance-critical software. It then tries to provide as\nmany ergonomic and safety tools as possible to support the goals of easy to read\nand understand code and providing practical safety. Leaving space for future\nevolution toward stricter checking of potentially unsafe code aligns with the\ngoal for language evolution.\n\n## Alternatives considered\n\n### Require compile-time-proven initialization\n\nA primary alternative to the approach of unformed objects for initialization is\nto simply require initializing all variables at compile time. This can take a\nfew forms across the spectrum of compile time analysis complexity.\n\n#### Trivially required initialization, with no escape hatch\n\nThe simplest approach is to require initialization at the point of declaration\nor allocation for any variable or memory. An essential property to this approach\nremaining simple is that it have _no_ escape hatch. Once such an escape hatch\nexists, all of the semantic questions of this proposal need to be answered.\n\nAdvantages:\n\n-   No need to specify or support the complexity of objects that have been\n    declared but not fully initialized in the language.\n-   Simple, easy to teach, easy to implement.\n\nDisadvantages:\n\n-   Will result in initialization with nonsensical values that if used remain a\n    bug. We won't have any realistic way to detect these bugs.\n-   Imposes a non-trivial performance cost in some cases and for some users\n    without providing any effective mechanisms to address this overhead.\n\n#### Initialize on all branches prior to use (Rust, C#, TypeScript)\n\nUse a simple rule such as requiring initialization before use along all\nbranches.\n\nAdvantages:\n\n-   Still avoids much of the language level complexity of unformed objects.\n-   Very simple to implement.\n-   Reasonably teachable.\n-   Avoids trivially redundant initializations.\n\nDisadvantages:\n\n-   Has significant expressivity limits past which initialization is forced.\n    -   When this happens, the disadvantages of always requiring initialization\n        repeat. While it is expected to happen less often, it still happens.\n    -   Adding an unsafe escape hatch that avoids initialization even in this\n        case returns to the same fundamental complexity and model as is proposed\n        here.\n-   Would still need a semantic model for moved from objects which would\n    introduce some amount of additional complexity.\n\n#### Definitive initialization (Swift)\n\nWe could do significantly more complete analysis of the dataflow of the program\nto prove that initialization occurs prior to use.\n\nAdvantages:\n\n-   Still avoids much of the language level complexity of unformed objects.\n\nDisadvantages:\n\n-   Some implementation complexity to achieve strong dataflow analysis.\n-   Significant complexity to teach -- it can be difficult to understand or\n    explain why the data flow analysis fails in edge cases.\n-   Can result in brittleness where changes to one part of code confuse the\n    dataflow analysis needed by another part of code.\n-   There still exist rare cases where the analysis fails, and a nonsensical\n    initialization may be required and the disadvantages of those return (both\n    bug detection and performance).\n    -   The rate at which this occurs scale inversely proportional to the\n        complexity of the data flow analysis and the teachability.\n-   Would still need a semantic model for moved from objects which would\n    introduce some amount of additional complexity.\n\n### C and C++ uninitialized\n\nWe could pursue the same approach as C and C++ here. However, this path has\nproven to have severe problems. It has inevitably resulted in prevalent bugs and\nsecurity vulnerabilities due to programmer errors, And having uninitialized\nvariables in the language makes teaching the debug build to catch these bugs\nextremely difficult and potentially impossible. We essentially will need\ndevelopers to heavily use an MSan-like mode (either by integrating it with the\ndebug build or having a separate one) in order to cope with the bugs caused by\nuninitialized memory. This is the only thing that has allowed coping with C and\nC++ semantics here and even it is not very effective.\n\nIf MSan remains a separate tool that needs propagation and origin tracking\n([details](https://research.google.com/pubs/archive/43308.pdf)), the cost and\nthe barrier to entry will remain very high: MSan is currently the least used and\nthe least portable of the sanitizers; it is widely used only in two Google’s\necosystems, only on one OS, where it is maintained with a considerable effort.\n\nIf we end up having uninitialized memory, we should aim at having MSan-like\nchecking be part of the normal debug build, which means no or very limited\npropagation. Any form of propagation will require optional original tracking,\nwhich is doable, but will mean extra CPU/RAM overhead for meaningful\ndiagnostics.\n\nEven without propagation, MSan-like checking requires bit-to-bit shadow that\nwould incur a 2x RAM overhead in the debug build. Byte-to-bit shadow, which is\n&lt; 12% RAM overhead, is prone to racy false positives and false negatives\nunless a) instrumentation uses expensive bit-wise atomics or b) the language\ndefines data races on 8-byte granularity. Adding this restriction on data races\nwould diverge from C++ and further complicate porting code and interoperability.\n\n### Allow passing unformed objects to parameters or returning them?\n\nThis proposal suggests **not** allowing code to pass unformed objects to other\nfunctions as arguments or to return them. They can still be escaped to another\nfunction by passing the address.\n\nAdvantages of allowing this:\n\n-   Would accept more code that can be written in C++ today and doesn't directly\n    exhibit a bug. For example, unused arguments or return values in C++ could\n    be left uninitialized, but in Carbon they would need to use an optional type\n    instead.\n\nDisadvantages of allowing this:\n\n-   Makes checking for errors in debug builds both more expensive and less\n    helpful by potentially moving the error to a separate function rather than\n    the one most likely containing any bug.\n    -   We have anecdotal evidence that indicates producing an error at the\n        function boundary would be preferable to delaying the error. This\n        evidence is a result of MSan delaying any such errors, while UBSan\n        eagerly errors at the function boundary for a few types (`bool`s and\n        `enum`s). Particularly for `bool` parameters the early errors from UBSan\n        have essentially always been correctly diagnosed and bugs. The early\n        errors from UBSan are also significantly easier to understand.\n    -   Implementing interprocedural checking either requires a more expensive\n        ABI or using more expensive shadow-memory checks which would otherwise\n        be unnecessary.\n-   Equivalent functionality can be achieved safely using an optional type, or\n    unsafely by passing the address. The only cases where passing the address\n    would be less efficient than what C++ allows are likely to be amenable to\n    compiler optimization to remove the overhead.\n\n### Allow assigning an unformed object to another unformed object?\n\nThis proposal suggests **not** allowing assigning an unformed object to another\nunformed object.\n\n-   We should try _not_ allowing this at first.\n    -   This will be enforced the same way as any other use of an unformed\n        object: at compile time when locally detectable, at runtime when\n        sufficient runtime tracking is enabled.\n-   If we find we must allow this in some cases, we should start by allowing it\n    only using specially named operations.\n-   If either can be made to work, they are significantly easier to check for\n    bugs.\n\nAdvantages of allowing this:\n\n-   Avoids some surprise for users.\n    -   It seems like it should work for integers.\n    -   They may not know when the incoming object is actually unformed\n        resulting in an error far away from the root cause.\n    -   Only some surprise is avoided given that we still can't assign unformed\n        objects to fully-formed objects -- doing so would open up the\n        possibility of unformed subobjects.\n-   Makes some idiomatic patterns in C++ either invalid or inefficient. Consider\n    the typical C++ implementation of a `swap` function:\n\n    ```c++\n    template <typename T>\n    void swap(T& lhs, T& rhs) {\n      T tmp = std::move(lhs);\n      lhs = std::move(rhs);\n      rhs = std::move(tmp);\n    }\n    ```\n\n    If this function is called with `lhs` and `rhs` referring _to the same\n    object_, then the first move into a temporary leaves the object in an\n    unformed state, and the second assignment will assign that unformed object.\n    Whatever Carbon code ends up replicating patterns like this will require one\n    of two options:\n\n    1.  Check for `lhs` and `rhs` referring to the same object, adding a branch\n        and its overhead to the code.\n    2.  Require that it is never called with `lhs` and `rhs` referring to the\n        same object, pushing the cost onto the caller.\n\n    We would largely expect (2) to be the dominant choice in Carbon due to\n    performance concerns. However, if the ergonomic burden of (2) becomes\n    significant, we may revisit this rule to carve out enough of a facility for\n    self swap specifically. That might either be the narrow specially-named\n    operation mentioned above, or attempt to special case self-assignment in\n    some way.\n\n    -   We could consider narrowly allowing _only_ self-move-assignment or\n        self-swap of unformed objects to lessen the impact of precluding the\n        move-assignment and swap of unformed objects generally. However, that\n        carries surprising complexity cost for the language specification and\n        creates very subtle rules.\n\n        At a minimum, types with an unformed state would need to implement move\n        assignment in a way that would be correct even when performing a\n        self-move of an unformed object.\n\n        On top of that, the simplest solution would be to allow _any_ self move\n        assignment of an unformed object. However, that would require any move\n        assignment that _might_ be a self-move to be implemented in a checked or\n        sanitized build with a branch to detect that case and not error. To\n        lower this overhead of checked builds, we would need to add\n        language-level swap operation of some form and only exempt _that_ from\n        checking. This would reduce the overhead, but would now make it\n        impossible to even test the self move assignment that would still be\n        required to work in non-checked builds.\n\n-   May be important to enable specific code patterns if we allow member access.\n\nDisadvantages of allowing this:\n\n-   Will require the core propagation logic and origin tracking that is a source\n    of large complexity and cost in MSan to detect bugs.\n    -   However, object granularity and lack of arithmetic makes this still\n        somewhat less severe than what MSan deals with.\n    -   Only a concern for detection, hardening is easily accomplished\n        regardless.\n-   Can only possibly support combined debug build mode if restricted to a\n    special/designated operation rather than arbitrary assignment.\n    -   Origin tracking will still be required and have significant cost.\n\n### Fully destructive move (Rust)\n\nRust has truly destructive moves -- the object is gone after being moved from,\nand no destructor ever runs past that point. This is possible because the type\nsystem models when a variable declared in one function can be moved-from by\nanother function. It is incompatible with allowing move-from through a pointer\nto a non-local object.\n\nAdvantages:\n\n-   Precise, safe, and efficient lifetime management.\n-   Perfect detection of use-after-move bugs.\n\nDisadvantages:\n\n-   Doesn't compose with pointers and C++ idioms which involve moving out of\n    non-local objects through a pointer.\n    -   Would require redesigning systems to model the lifetime in the type\n        system.\n\n### Completely non-destructive move (C++)\n\nC++ moves are never destructive. The result is that moves simply do not impact\nthe _lifetime_ of the moved-from object, only its state.\n\nAdvantages:\n\n-   Perfect match for C++ semantics and idioms, including interoperability and\n    migrated code and systems.\n\nDisadvantages:\n\n-   Pervasive user expectation that destroying a moved-from object is a no-op,\n    but nothing in the language helps enforce this pattern.\n-   Allows types to provide meaningful semantics for use-after-move.\n    -   Rarely used, resulting in strong user expectations that this isn't\n        allowed but special cases where it is allowed.\n    -   Complicates generic code having to handle both patterns.\n    -   Significantly reduces the effectiveness of use-after-move bug detection.\n-   Introduces difficulty in optimizing away no-op destruction post move.\n    -   Some cases requires complex rules around ABIs and calling conventions.\n    -   Other cases require expensive optimization techniques (inlining and\n        memory analysis) that can fail in some circumstances.\n\n### Named return variable in place of a return type\n\nAn alternative approach to\n[declaring `returned` variables](#declared-returned-variable) is to extend the\nsyntax for the return type such that it can declare a named variable that holds\nthe return value. For example, provided that `MyType` has an unformed state:\n\n```\nfn CreateMyObject2() -> var result: MyType {\n  // `result` here is an unformed object.\n  // so we can assign to it here:\n  result = CreateMyObject();\n\n  // Because there is a named return variable, we cannot\n  // have an expression in the return statement.\n  return;\n}\n```\n\nWe could also explicitly initialize the return variable, which eliminates the\nrequirement that its type has an unformed state:\n\n```\nfn CreateMyObject3() -> var result: MyType = CreateMyObject2() {\n  // any code we want\n  return;\n}\n\nvar y: MyType = CreateMyObject3();\n```\n\n**Minor syntax variations:**\n\n-   Possible to use different arrow symbols (such as `=>` instead of `->`) to\n    differentiate different kinds of returns.\n    -   However, we don't recommend this given the subtlety of the visual\n        difference.\n-   Potentially require `return <name>;` where `<name>` must exactly match the\n    return variable's name to make it clear what is being returned.\n    -   One concern with this is that `<name>` can't really be an expression in\n        general, it needs to _just_ be a name. This may be a bit surprising.\n    -   Also complicated as there is no need to have a single name for the\n        variable: it might be `var (result: MyType, Error: error)` for example,\n        and it becomes unclear what to put in the `return`.\n\n**Advantages:**\n\n-   The primary advantage of this approach is that it avoids any and all\n    challenging lifetime questions or restrictions on where the `returned`\n    variable can be declared or what control flow must follow.\n-   It is also slightly less expressive which if sufficient seems desirable.\n\n**Disadvantages:**\n\n-   The syntax space of the return type is very crowded already, and this would\n    add more complexity there rather than fitting in cleanly with existing\n    declaration spaces within the body of the function.\n-   Likely to be an implementation detail and valid to use on a function with a\n    normal return _type_ in its forward declaration. This isn't obvious when\n    placed in the declaration position, and it might well be unnecessarily added\n    to forward declarations just because of its position.\n-   Removes the ability to _both_ specify a specific return type and a pattern\n    for binding parts of that object to names. Instead, the type must be\n    inferred from the pattern.\n    -   This ended up feeling like a deep and fundamental problem where we would\n        lose important expressivity to disambiguate the return type from\n        patterns. For example, when the return type is some form of sum type or\n        variant, the pattern space is both especially attractive to use and\n        fundamentally fails to express enough information to capture the type.\n\n### Allow unformed members\n\nRegardless of which specific strategy, using the proposed `return` facilities\nfor constructing aggregate objects still presents some ergonomic difficulties\nfor large objects with many members, or members that are expensive/impossible to\nmove if we don't have the `returned var` facility. To further ease initializing\nmembers, we could allow access to unformed members of an unformed object.\nSuperficially, this remains safe -- we aren't allowing access to uninitialized\nstorage, and the only access allowed is what is always allowed for unformed\nobjects: assignment (and destruction). However, making this work with\ndestructors adds some complexity to rules around unformed objects.\n\nDisallowing access to unformed members provides a simple rule for the semantics\nrequired of the destructor: it must be valid and correct to run on an unformed\nobject or a _fully_ formed object. Destructors always have to be valid for fully\nformed objects, so the only addition is the unformed state being a no-op.\n\nHowever, for the same reasons it might be necessary to run the destructor on an\nunformed object, if we allow assigning to a _member_ of an unformed object the\ndestructor may also need to be run with this mixed state where some members are\nunformed and others are fully formed:\n\n```\nstruct Point {\n  var x: Int;\n  var y: Int;\n}\n\nfn AssignToX(x: Int, p: Point*) {\n  p->x = x;\n}\n\nfn Example() {\n  var p: Point;\n  if (...) {\n    // Allowed to call the destructor of `p`, sees a fully unformed `Point`.\n    return;\n  }\n  AssignToX(42, &p);\n  if (...) {\n    // If `AssignToX` is in another file, don't know if `p` is fully unformed,\n    // a mixture of `x` fully formed and `y` unformed, or `p` is fully formed.\n    // The last case can only be handled by running the destructor of `p`\n    // so that's what we have to do here, and it must handle all the other\n    // cases as well.\n    return;\n  }\n  p->y = 13;\n  // ...\n}\n```\n\nThe added requirement for destructors of types that support an unformed state is\nthat if they are called for an unformed object of that type, they must run the\ndestructors for any members that might themselves be fully formed.\n\n-   For private members, the type itself controls which members might be\n    assigned fully formed values and the destructor run. The type's destructor\n    merely needs to agree with the constructors and/or factories of the type to\n    destroy any members that might have been assigned values.\n-   For public members, the type's destructor must destroy _all_ members as it\n    cannot know which ones might have been assigned a value.\n\nBecause of these inherent restrictions around private members, types can ensure\nany necessary relationship between its private data members hold in order for\nthe destructor to work. See the detailed example below for how this might work\nin practice.\n\nDespite these added requirements to the destructor, it isn't exempt from the\nrules governing unformed objects when accessing its members: any that are in\nfact unformed when the type's destructor runs are only allowed to be assigned to\nor destroyed.\n\nLastly, we need some syntax other than assignment for marking when the members\nhave reached a state where the entire object is fully formed. This document uses\na hypothetical `?reify?` statement that is intended to be placeholder syntax\nonly. Just like an assignment to an unformed object, after this point it is\nfully formed and follows those rules. Our example becomes:\n\n```\nfn EvenSimplerPointConstructor() -> var p: Point {\n  // p is unformed and no members are referenced.\n  // Destruction is completely optional.\n  p.x = ...;\n  // p.x may now be fully formed. Either p must be destroyed,\n  // or p.x must be destroyed.\n  p.y = ...;\n  // Now either p must be destroyed, or both p.x and p.y must be\n  // destroyed.\n\n  ?reify? p;\n  // Now p must be destroyed, and is a fully formed object.\n\n  // ...\n\n  return;\n}\n```\n\nBefore the `?reify?` operation, the compiler can either track the members which\nare assigned fully formed values and run their destructors, or it can elect to\nrun the entire object's destructor if, for example, the entire object escapes\nand it becomes impossible to track which members have been assigned fully formed\nvalues. But once the object has the `?reify?` operation performed, its\ndestructor _must_ be run as it is now itself a fully formed object.\n\nNow that we have all the components of this tool, let's consider a container\nlike `std::vector` using a hypothetical syntax for defining a type, its\nimplementation of the necessary initialization, its destructor, and a factory\nfunction. This example specifically tries to illustrate how, for private\nmembers, the function doing construction and the destructor can work together to\nensure at any point of destruction, the necessary state and invariants hold.\n\n```\nstruct MyContainer(T: Type) {\n  private var size: Int;\n  private var capacity: Int;\n  private var data: Optional(T*);\n\n  // ... public API ...\n\n  impl NecessaryInit {\n    // Not necessarily suggesting this specific API.\n    // Just *some* API we pick for doing the necessary init.\n    // This API assumes that all members with an unformed state\n    // have their implementation called already, all we need to do is\n    // adjust to *specific* values anything that is necessary for this\n    // type.\n    fn Init(this: Self*) {\n      this->data = Optional(T*).Empty;\n    }\n  }\n\n  fn Create(count: Int, T: value) -> Optional(MyContainer(T)) {\n    var container: MyContainer(T);\n    // Set the capacity first so it is available for deallocation.\n    container.capacity = count;\n    // And clear the size so we don't need a special case.\n    container.size = 0;\n\n    // Next set the data to the allocated buffer. If the allocation fails,\n    // this routine should just return null.\n    container.data = AllocateRawStorage(count, T);\n    if (container.data == null) {\n      // Might destroy `container` here.\n      return .Empty;\n    }\n\n    // Some loop syntax over [0, count).\n    for (i: Int = 0 ..< count) {\n      if (not CopyThatMightFail(value, &container.data[i])) {\n        // Might destroy `container` here.\n        return .Empty;\n      }\n      // Increment size as we go to track how many objects\n      // need to be destroyed if the next one fails.\n      ++container.size;\n    }\n\n    ?reify? container;\n\n    // Maybe we make this implicit... somehow make it move...\n    return .Some(container);\n  }\n\n  // However we end up naming this...\n  fn Destructor(this: Self*) {\n    if (this->data.IsEmpty()) {\n      // If the buffer isn't allocated, nothing to do.\n      return;\n    }\n    // Destroy any successfully created object. The `Create`\n    // function ensures that `size` is valid for use here.\n    for (i: Int = 0 ..< this->size) {\n      // However we spell in-place destroy...\n      this->data[i].Destructor();\n    }\n    // Deallocate the buffer. Here as well the `Create`\n    // function ensures that `capacity` is available for a\n    // non-null data pointer.\n    Deallocate(this->data, this->capacity);\n  }\n}\n```\n\nThis kind of type creates a close contract between construction and destruction\nto simplify both routines by ensuring that the necessary members are valid any\ntime the destructor would need them to continue executing correctly.\n\nWhile this provides a very flexible and convenient set of tools for\nconstruction, it comes at a fairly high cost. There is no way for the language\nto _enforce_ any contract between the construction and destruction. I don't see\nany way to provide compile time checking that one or the other doesn't make a\nmistake. We can verify it dynamically, but at fairly high cost. It also adds\nnon-trivial complexity. Given that this is merely an ergonomic improvement as\nopposed to an expressivity improvement, it isn't at all clear that we should\npursue this until we have clear evidence that the ergonomic need is sufficiently\nlarge.\n\nIn fact, for this kind of realistic example, the `returned` variable approach\nappears to be significantly _more_ ergonomic as well as simpler, undermining the\npurpose of pursing this direction:\n\n```\nstruct MyContainer(T: Type) {\n  private var size: Int;\n  private var capacity: Int;\n  private var data: Optional(T*);\n\n  // ... public API ...\n\n  impl NecessaryInit {\n    // Not necessarily suggesting this specific API.\n    // Just *some* API we pick for doing the necessary init.\n    // This API assumes that all members with an unformed state\n    // have their implementation called already, all we need to do is\n    // adjust to *specific* values anything that is necessary for this\n    // type.\n    fn Init(this: Self*) {\n      this->data = Optional(T*).Empty;\n    }\n  }\n\n  // Private helper factored out of the destructor.\n  fn DestroyElements(data: T*, count: Int) {\n    for (i: Int = 0 ..< count) {\n      data[i].Destructor();\n    }\n  }\n\n  fn Create(count: Int, T: value) -> Optional(MyContainer(T)) {\n    // Try to allocate the storage.\n    var data: UniquePtr(T) = AllocateRawStorage(count, T);\n    if (data == null) {\n      return .Empty;\n    }\n\n    // Some loop syntax over [0, count).\n    for (i: Int = 0 ..< count) {\n      if (not CopyThatMightFail(value, &container.data[i])) {\n        // Here we have to destroy the copies that succeeded.\n        // But we can easily share the logic with the destructor.\n        DestroyElements(data, i);\n        return .Empty;\n      }\n    }\n\n    // Now we can just initialize the object and all invariants\n    // hold for its destructor.\n    returned var Optional(MyContainer(T)): result =\n        .Some((count, count, data.Release()));\n\n    return result;\n  }\n\n  // However we end up naming this...\n  fn Destructor(this: Self*) {\n    if (this->data.IsEmpty()) {\n      // If the buffer isn't allocated, nothing to do.\n      return;\n    }\n    // The above check is the only thing needed, and it is only needed\n    // to support an unformed state. Once we get here, everything holds.\n    DestroyElements(this->data, this->size);\n    Deallocate(this->data, this->capacity);\n  }\n\n}\n```\n\nWith this approach, the necessary steps in the `Create` function are all _local_\nconstraints, and changes to the destructor can't break their assumptions. There\nis no significant added complexity in practice due to needing to form the entire\nobject at a single point. Normal techniques for factoring common logic are\neasily used to address what little added logic is needed.\n\n#### Summary of advantages and disadvantages\n\nAdvantages:\n\n-   Allows incrementally assigning meaningful members to an object.\n-   Simplifies some initialization patterns for objects with large numbers of\n    members.\n\nDisadvantages:\n\n-   The simplifications don't scale up to more realistic scenarios. There, they\n    are eclipsed by the added complexity forced onto the destructor of any such\n    type.\n-   The design patterns that simplify the organization of the construction and\n    destruction logic for these kinds of types are likely to remove the need for\n    the feature, so it seems better to keep the language simpler.\n"
  },
  {
    "path": "proposals/p0285.md",
    "content": "# if/else\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/285)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Executable semantics form](#executable-semantics-form)\n-   [Caveats](#caveats)\n    -   [C++ as baseline](#c-as-baseline)\n    -   [if/else in expressions](#ifelse-in-expressions)\n    -   [Indentation](#indentation)\n    -   [Ambiguous else](#ambiguous-else)\n-   [Alternatives considered](#alternatives-considered)\n    -   [No parentheses](#no-parentheses)\n    -   [Require braces](#require-braces)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Problem\n\n`if`/`else` is noted in the [language overview](/docs/design/README.md), but is\nprovisional. Control flow is important, and `if`/`else` is basic; the form is\nsimilar in many languages, even if details may change.\n\n## Background\n\n`if`/`else` is a common\n[conditional](<https://en.wikipedia.org/wiki/Conditional_(computer_programming)>),\nseen in\n[many languages](<https://en.wikipedia.org/wiki/Conditional_(computer_programming)#Choice_system_cross_reference>).\nA few syntaxes that are likely to influence `if`/`else` are:\n\n-   C++\n\n    ```c++\n    if (x) {\n      printf(\"x is true\");\n    } else if (y) {\n      printf(\"y is true\");\n    } else {\n      printf(\"Neither was true\");\n    }\n    ```\n\n-   Python\n\n    ```python\n    if x:\n      print(\"x is true\");\n    elif y:\n      print(\"y is true\");\n    else:\n      print(\"Neither was true\");\n    ```\n\n-   Swift\n\n    ```swift\n    if x {\n      print(\"x is true\")\n    } else if y {\n      print(\"y is true\")\n    } else {\n      print(\"Neither was true\")\n    }\n    ```\n\n-   Rust -- versus other cases where `if` is a statement, Rust makes `if` an\n    expression, allowing:\n\n    ```rust\n    let x = if y {\n        1\n    } else {\n        0\n    };\n    ```\n\n## Proposal\n\nWe should make `if`/`else` syntax consistent with C and C++, rather than\nadopting the syntax of another language.\n\n## Details\n\n`if`/`else` is a statement. The syntax looks like:\n\n`if` `(`_boolean expression_`)` `{` _statements evaluated when true_ `}` [\n`else` `{` _statements evaluated when false_ `}` ]\n\nThe braces are optional, but must be paired (`{ ... }`) if present. When there\nare no braces, only one statement is allowed.\n\n### Executable semantics form\n\n```bison\nstatement:\n  \"if\" '(' expression ')' statement optional_else\n| /* preexisting statements elided */\n;\n\noptional_else:\n  /* empty */\n| \"else\" statement\n;\n```\n\n## Caveats\n\n### C++ as baseline\n\nThis baseline syntax is based on C++, following the migration sub-goal\n[Familiarity for experienced C++ developers with a gentle learning curve](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\nTo the extent that this proposal anchors on a particular approach, it aims to\nanchor on C++'s existing syntax, consistent with that sub-goal.\n\nAlternatives will generally reflect breaking consistency with C++ syntax. While\nmost proposals may consider alternatives more, this proposal suggests a\nthreshold of only accepting alternatives that skew from C++ syntax if they are\nclearly better; the priority in this proposal is to _avoid debate_ and produce a\ntrivial proposal. Where an alternative would trigger debate, it should be\nexamined by an advocate in a separate proposal.\n\n### if/else in expressions\n\nThis proposal covers `if`/`else` as a statement. A Rust-like form of `if`/`else`\nas an expression could be supported, but is not part of this proposal because\nit's more complex.\n\n### Indentation\n\nIt may be desirable to require meaningful indentation of the body of an\n`if`/`else`, in particular to help catch errors when there are no braces.\n\nFor example, this could be a compiler error due to inconsistent indentation of\nthe `do_parse` assignment:\n\n```carbon\nif (missing_data)\n  Print(\"Missing data!\");\n  do_parse = false;\nif (do_parse)\n  ParseData();\n```\n\nThis is _not_ part of this proposal.\n\n### Ambiguous else\n\nIt may be desirable to reject cases where an `else` is ambiguous. For example,\nthis could be a compiler error due to the ambiguous `else`:\n\n```carbon\nif (a) if (b) f(); else g();\n```\n\nThis is _not_ part of this proposal. This proposal takes C++ syntax as a\nbaseline, so an `else` binds to the innermost enclosing `if` that doesn't\nalready have an `else`.\n\nThis desire might also be addressed by choosing to require consistent\nindentation and disallowing multiple `if`s on the same line.\n\n## Alternatives considered\n\nSee [C++ as baseline](#c-as-baseline) for an explanation of how alternatives are\nevaluated in this proposal.\n\n### No parentheses\n\nParentheses could be optional (essentially not part of `if`/`else`, but addable\nas part of the expression), instead of required (as proposed).\n\nAdvantages:\n\n-   Removing parentheses gives developers less to type.\n    -   Consistent with several other languages, including Swift and Rust.\n\nDisadvantages:\n\n-   Requiring parentheses is consistent with C++, and will be intuitive for C++\n    developers, from both a writability and readability perspective.\n-   Parentheses help avoid ambiguities.\n    -   The Swift and Rust model is ambiguous if it's ever possible for an\n        expression to optionally be followed by braces. That is possible in\n        Rust, at least, where `Type{...}` is a valid expression. As a result,\n        Rust rejects `if Type{.value = true}.value { thing1 } else { thing2 }`\n        because it misinterprets the braces.\n-   Parentheses allow making the braces optional without any risk of ambiguity.\n-   Parentheses allow introducing syntactic variants in the future without\n    ambiguity.\n    -   For example, C++'s `if constexpr (...)` wouldn't have been possible if\n        the parentheses were optional.\n\nThe benefits of this are debatable, and it should be examined by an advocate in\na focused proposal. For now, we should match C++'s decision.\n\n### Require braces\n\nBraces could be required, instead of optional (as proposed).\n\nAdvantages:\n\n-   Braces avoid syntax ambiguities.\n    -   For example, `if (x) if (y) { ... } else { ... }` has\n        difficult-to-understand binding of `else`.\n-   Braces avoid errors when adding statements.\n\n    -   For example, if:\n\n        ```carbon\n        if (x)\n          do_parse = false;\n        ```\n\n        has a statement added:\n\n        ```carbon\n        if (missing_data)\n          Print(\"Missing data!\");\n          do_parse = false;\n        ```\n\nDisadvantages:\n\n-   Inconsistent with C++.\n\nThe benefits of this are debatable, and it should be examined by an advocate in\na focused proposal. For now, we should match C++'s decision.\n\n## Rationale\n\nThis proposal focuses on an uncontroversial piece that we are going to carry\nfrom C++, as a baseline for future Carbon evolution. It serves our migration\ngoals (especially \"Familiarity for experienced C++ developers with a gentle\nlearning curve\") by avoiding unnecessary deviation from C++, and instead\nfocusing on subsetting the C++ feature. While we expect this feature to evolve\nsomewhat, the changes we're likely to want can easily be applied incrementally,\nand this is a fine starting point that anchors us on favoring syntax familiar to\nC++ developers.\n"
  },
  {
    "path": "proposals/p0301.md",
    "content": "# Principle: Errors are values\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/301)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Decouple errors from return values](#decouple-errors-from-return-values)\n    -   [Implicit error propagation](#implicit-error-propagation)\n\n<!-- tocstop -->\n\n## Problem\n\nCarbon needs a coherent, consistent approach to handling and propagating errors.\n\n## Background\n\nThe handling and propagation of errors is a pervasive concern in almost every\nnontrivial codebase, and every language provides some form of support for it.\nWhether that takes the form of direct language support for errors, or emerges as\na special case of more general-purpose language features, it always has a\npowerful effect on the performance, safety, and ergonomics of the language.\nConsequently, Carbon's ability to meet its goals will be strongly influenced by\nhow it supports errors.\n\n## Proposal\n\nI propose establishing as a design principle that Carbon's error handling will\nbe based on return values, and specifically return values of sum types, rather\nthan exceptions or other non-return side channels.\n\n## Alternatives considered\n\n### Decouple errors from return values\n\nRather than representing errors using function return values, we could convey\nerrors by way of a separate \"channel\", as in Swift. This would require a\nseparate syntax for indicating whether a function can raise errors, and unless\nwe want to follow Swift in making errors dynamically typed, that syntax would\nalso need to indicate the type of those errors. We would additionally need a\nseparate syntax for stopping error propagation and resuming normal control flow,\nsuch as Swift's `do`/`catch`, because the error \"channel\" is invisible to\nordinary code.\n\nThis approach may have some performance advantages, because the compiler always\nstatically knows whether a given object represents an error or a successful\nreturn value, although it's not clear how significant that advantage will be in\nCarbon. It would also make it easier to explore different implementation\nstrategies, such as table-driven stack unwinding, that generate very different\ncode for propagating errors than for handling ordinary return values.\n\nThis approach will make it harder for Carbon code to interoperate with C++ code\nthat uses error returns, and harder to migrate such code to Carbon. It might be\nan easier migration/interoperation target for C++ code that uses exceptions, but\nthat's less certain, because this approach still differs from C++ exceptions in\nfairly important ways, such as the fact that typing is static and propagation is\nexplicit. By the same token, this approach is somewhat less likely to feel\nfamiliar to C++ programmers.\n\nI recommend against this approach for the present, because the need for\nsomething like `do`/`catch` makes it more complex to design, and because the\npotential advantages, particularly with respect to performance, are speculative.\nIt seems better to start with the simpler approach, and let subsequent design\nchanges be driven by concrete experience with whatever problems it has.\n\n### Implicit error propagation\n\nAs an extension of the previous option, we could treat errors as a separate\nchannel from return values, and allow them to propagate across stack frames\nimplicitly, without an explicit `?` or `try` at the callsite. This is basically\nhow C++ exceptions work, so this would ease migration and interoperation with\nC++ code that uses them. However, this entails a readability tradeoff:\nerror-propagating code can be distracting boilerplate, but it can also be a\nvital signal about what the code actually does, depending on the needs of the\nreader.\n\nI recommend against this approach for the present. Instead, we should\ninvestigate ways to make explicit error propagation as syntactically lightweight\nas possible, in order to address the second kind of reader use case, while\nminimizing the burden on the first.\n"
  },
  {
    "path": "proposals/p0339.md",
    "content": "# `var` statement\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/339)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n    -   [Constants](#constants)\n-   [Background](#background)\n    -   [Terminology](#terminology)\n    -   [Out of scope features](#out-of-scope-features)\n    -   [Language comparison](#language-comparison)\n-   [Proposal](#proposal)\n    -   [Executable semantics form](#executable-semantics-form)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Caveats](#caveats)\n    -   [`var` name may change](#var-name-may-change)\n        -   [Changing to `let mut`](#changing-to-let-mut)\n    -   [Multiple identifiers in one statement](#multiple-identifiers-in-one-statement)\n    -   [Update provisional pattern matching syntax](#update-provisional-pattern-matching-syntax)\n    -   [Update provisional `$` syntax](#update-provisional--syntax)\n-   [Alternatives considered](#alternatives-considered)\n    -   [No `var` introducer keyword](#no-var-introducer-keyword)\n    -   [Name of the `var` statement introducer](#name-of-the-var-statement-introducer)\n    -   [Colon between type and identifier](#colon-between-type-and-identifier)\n        -   [Syntax ambiguity](#syntax-ambiguity)\n        -   [Confusion with other languages and alternatives](#confusion-with-other-languages-and-alternatives)\n        -   [Use in pattern matching](#use-in-pattern-matching)\n        -   [Advantages and disadvantages](#advantages-and-disadvantages)\n        -   [Conclusion](#conclusion)\n    -   [Type after identifier](#type-after-identifier)\n        -   [Ordering as a way to quickly answer questions](#ordering-as-a-way-to-quickly-answer-questions)\n        -   [Syntax popularity](#syntax-popularity)\n    -   [Type elision](#type-elision)\n        -   [Advantages and disadvantages](#advantages-and-disadvantages-1)\n        -   [Conclusion](#conclusion-1)\n\n<!-- tocstop -->\n\n## Problem\n\nThe `var` statement is noted in the\n[language overview](https://github.com/carbon-language/carbon-lang/tree/trunk/docs/design#ifelse),\nbut is provisional — no justification has been provided. Variable declarations\nare fundamental, and it should be clear to what degree the current syntax is\nadopted.\n\nIt's expected that after the adoption of this proposal, `var` syntax will still\nnot be finalized: the [proposal](#proposal) is an experiment.\n\n### Constants\n\nAlthough constants are naturally related to variables, this proposal does not\ninclude any syntax for constants. This is expected to be revisited later.\n\n## Background\n\n### Terminology\n\nIn this proposal, \"variable\" is defined as an identifier referring to a mutable\nvalue.\n\n### Out of scope features\n\nQuestions have come up about:\n\n-   The type system\n-   Type checking\n-   Scoping\n\nAll of these are important features. However, in the interest of small\nproposals, they are out of scope of this proposal.\n\n### Language comparison\n\nVariables are standard in many languages. Some various forms to consider are:\n\n-   C++:\n\n    ```c++\n    int x;\n    int y = 0;\n    bool a = true, *b = nullptr, c;\n    ```\n\n-   Python:\n\n    ```python\n    x = None\n    y = 0\n    z: int = 7  # Added by PEP 526.\n    ```\n\n-   Swift:\n\n    ```swift\n    var x = 0\n    var y: Int = 0\n    var z: Int\n    ```\n\n-   TypeScript\n\n    ```ts\n    let y: Number = 0;\n    var x = 0;  # Legacy from JavaScript.\n    ```\n\n-   Rust\n\n    ```rust\n    let mut x = 0;\n    let mut y: i32 = 0;\n    let mut z: i32;\n    ```\n\n-   Go\n\n    ```go\n    var x = 0\n    y := 0\n    var z int\n    var a, b = true, false\n    ```\n\n-   Visual Basic\n\n    ```vb\n    Dim x As Integer = 3\n    ```\n\n## Proposal\n\nCarbon should adopt `var <type> <identifier> [ = <value> ];` syntax for variable\nstatements.\n\nConsiderations for this syntax are:\n\n-   **Type and identifier ordering:** The ordering of `<type>` before\n    `<identifier>` reflects the typical C++ ordering syntax.\n    -   Some C++ syntax can put type information after the identifier, such as\n        `int x[6];`. Carbon should be expected to place that as part of the\n        type.\n-   **`var` introducer keyword:** The use of `var` makes it clearer for readers\n    to skim and see where variables are being declared. It also reduces\n    complexity and potential ambiguity in language parsing.\n-   **One variable:** In C++, multiple variables can be declared in a single\n    statement. An equivalent Carbon syntax may end up looking like\n    `var (Int x, String y) = (0, \"foo\");`, so limiting to one declaration is not\n    fundamentally restrictive. However, by breaking with C++ and requiring the\n    full type to be specified with each identifier, we achieve two important\n    things:\n    -   It's clear what the full type is, preventing difficult-to-read\n        statements with a mix of stack variables, pointers, and similar.\n    -   As the language grows, a function returning a tuple may be assigned to\n        distinctly named and typed variables.\n\n**Experiment:** The ordering of type and identifier will be researched. For more\ninformation, see the [alternative](#type-after-identifier).\n\n### Executable semantics form\n\nExample bison syntax for executable semantics is:\n\n```bison\nstatement:\n  \"var\" expression identifier optional_assignment;\n| /* preexisting statements elided */\n;\n\noptional_assignment:\n  /* empty */\n| \"=\" expression\n;\n```\n\n## Rationale based on Carbon's goals\n\nCarbon needs variables in order to be writable by developers. That functionality\nneeds a syntax.\n\nRelevant goals are:\n\n-   [3. Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n\n    -   Adding a keyword makes it easy for developers to visually identify\n        functions.\n\n-   [5. Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development):\n\n    -   The addition of a keyword should make parsing easy.\n\n-   [7. Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):\n\n    -   Keeping syntax close to C++ will make it easier for developers to\n        transition.\n\n## Caveats\n\n### `var` name may change\n\nThe name `var` could still change. However, it's used with similar meaning in\nother languages including Swift, Go, and TypeScript, and so it's reasonable to\nexpect it will not.\n\n#### Changing to `let mut`\n\nThe idea that `var` may change includes the possibility that `var` may become\nsomething like `let mut` in Rust. However, this is not assumed by this proposal:\n\n-   This proposal [omits constant syntax](#constants).\n-   It would need to be considered whether the syntax tax of `let mut`\n    appropriately\n    [focuses on encouraging appropriate usage of features rather than restricting misuse](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)).\n-   Lower verbosity syntax for variables is more\n    [consistent with C++](p0285.md#c-as-baseline), even if constants are made\n    less verbose by way of `let`.\n\n### Multiple identifiers in one statement\n\nAlthough `var (Int x, String y) = (0, \"foo\");` syntax is mentioned, this\nproposal is not intended to propose such a syntax. It's noted primarily to\nexplain the likely path, that this does not _rule out_ abbreviated syntax such\nas that. That should probably be covered as part of tuples.\n\n### Update provisional pattern matching syntax\n\nPattern matching syntax in [the overview](/docs/design/README.md) uses syntax\nsimilar to `Int: x`. As part of removing the\n[colon between type and identifier](#colon-between-type-and-identifier) from the\nprovisional `var` syntax, that syntax should be changed to remove the `:`.\nDetails should be resolved as part of the eventual pattern matching proposal,\nbut if changes are needed to add a separator, the `var` syntax should be updated\nto remain consistent. The precise form of that implementation will be part of\nnormal Carbon evolution.\n\nFor example, replacing `fn Sum(Int: a, Int: b) -> Int;` with\n`fn Sum(Int a, Int b) -> Int;` and\n`case (Int: p, (Float: x, Float: _)) if (p < 13) => {` with\n`case (Int p, (Float x, Float _)) if (p < 13) => {`.\n\n### Update provisional `$` syntax\n\nVariables using `Type:$` and similar should drop the `:`, as in `Type$`.\n\n## Alternatives considered\n\nNoted alternatives are key differences from C++ variable declaration syntax.\n\n### No `var` introducer keyword\n\nThe intent of the `var` statement is to improve readability and parsability, and\nit's related to `fn` for functions. Although code is more succinct without\nintroducers, the noted benefits are expected to be significant. Most other\nmodern languages use similar introducers, and so this break from C++ is adopting\na different norm.\n\n### Name of the `var` statement introducer\n\n`var` is used with a similar meaning in several other languages, including\nSwift, Go, and JavaScript. `let` is used by TypeScript. `let mut` is used by\nRust, with `let` used for constants (this use of `let` alone is consistent with\nother languages). In general `var` appears to be a more common choice.\n\n### Colon between type and identifier\n\nThe use of a colon (`:`) between the type and identifier is intended to reduce\npotential parsing ambiguity, and to make reading code easier. As proposed, there\nis no colon between the type and identifier.\n\n#### Syntax ambiguity\n\nUsing a colon or other separator could make it easier to avoid certain kinds of\nambiguities. For example, suppose we decided to use a postfix `*` operator to\nform pointer types, as in C++. In such a setup, we could have code like the\nfollowing:\n\n```carbon\nvar T * x = 3;\nvar T * x = 3 y;\n```\n\nIn the first statement, `*` is a unary operator and so `T*` is the type and `x`\nis the identifier. However, in the second statement, `*` is a binary operator\nand so `T * x = 3` is the type, and `y` is the identifier; the resulting\ncompiler errors may be confusing to users. Furthermore, the place of `3` could\nbe taken by an arbitrarily complex expression; this could cause resolving the\nambiguity between unary and binary `*` to require unbounded look-ahead,\nadversely impacting\n[code compilation time goals](/docs/project/goals.md#fast-and-scalable-development).\n\nConsider instead the code:\n\n```carbon\nvar T *: x = 3;\nvar T * x = 3: y;\n```\n\nThe colon makes it unambiguous whether the `*` in each case is unary or binary\nwith only one token of look-ahead. More importantly, this syntax immediately\ncalls the reader's attention to the fact that the second declaration has a\nhighly unusual type.\n\nThere are other ways of resolving ambiguities like this. For example, we could\navoid allowing the same operator to have both postfix and infix forms, or we\ncould distinguish them by the presence or absence of whitespace. However, even\nif we avoid _formal_ ambiguity by such means, a separator like `:` may be useful\nfor reducing _visual_ ambiguity for human readers.\n\n#### Confusion with other languages and alternatives\n\nOne of the disadvantages of `:` is that with `var Int: x`, ordering is\ninconsistent with other languages using `:`, such as Rust and Swift, which would\nsay `var x: Int`.\n\nIt may be worth considering other syntax options. A few to consider are:\n\n```carbon\nvar(Int) x;\nvar Int# x;\nvar Int @x;\nvar Int -> x;\n```\n\nThese aren't part of the proposed syntax mainly because it's not clear any would\ngain as much support as `:`. However, this is an opportunity to make suggestions\nand see if there's a good compromise.\n\n#### Use in pattern matching\n\nThe\n[old draft pattern matching proposal](https://github.com/carbon-language/carbon-lang/pull/87)\nused `:` as a separator. In pattern matching, the `:` may be particularly\nimportant to distinguish between value matching and type name matching. However,\nthe pattern matching proposal should examine these choices and alternatives\nbefore we reach a conclusion that `:` is necessary for pattern matching. Per\n[syntax ambiguity](#syntax-ambiguity), it is expected that `:` has some\nadvantages, but may not turn out to make a compiler difference due to prevailing\nconstraints on type expression syntax.\n\nThis proposal suggests we\n[update provisional pattern matching syntax](#update-provisional-pattern-matching-syntax)\nto match the proposed `var` syntax.\n\n#### Advantages and disadvantages\n\nAdvantages:\n\n-   Reduces syntax ambiguity.\n    -   This should improve readability and parsability.\n    -   It should make it easier to debug issues during development.\n\nDisadvantages:\n\n-   Deviates from the common syntax used by most languages with the type before\n    the identifier, including C, C++, Java, and C#.\n    -   Changing from C++ is especially significant because of Carbon's goals\n        for interoperability and migration which will mean an especially large\n        portion of Carbon developers will be actively reading both Carbon and\n        C++ code.\n-   Other notable languages that us `:` in variable statements, including Swift,\n    put the type after the identifier.\n    -   It may be worth considering\n        [alternatives to `:`](#confusion-with-other-languages-and-alternatives).\n    -   If the alternative of [type after identifier](#type-after-identifier) is\n        adopted, it's likely a `:` separator will be adopted.\n\n#### Conclusion\n\nRight now the proposal is to not have anything between the type and identifier\nin order to avoid cross-language ambiguity, and to retain syntax that is closer\nto C++. However, the ultimate decision may hinge on type and identifier\nordering, as well as related future evolution.\n\n### Type after identifier\n\nThere are many languages that put the type after the identifier. A common format\nused by Swift and Rust is `var x: Int`.\n\nIt's worth considering the sentence-like readings:\n\n-   `var x Int` (or `var x: Int`) may be read as \"declare x as an int\" or \"make\n    a variable x and give it int storage\".\n-   `var Int x` may be read as \"declare an int called x\" or \"make a variable\n    with int storage called x\".\n\nThese readings might be of similar quality, and are presented to offer different\nperspectives on how to read the possible statement orderings.\n\n#### Ordering as a way to quickly answer questions\n\nOrdering is essentially a question of pairing identifiers and types. This can be\ncast as asking which question developers consider more important when reading\ncode:\n\n1. What is the type of variable `x`?\n2. What is the identifier of the `Int` variable?\n\nWe assert the first question is the more important one: developers will see an\nidentifier in later code, and want to know its type. However, how do we\ndetermine which order is better for this purpose?\n\nUnfortunately, little research has been done on this. All we're aware of right\nnow is a study from an unpublished undergraduate project from Germany. The study\nwas done in Java with 50 students. Its data indicates that it's faster to answer\nquestion 1 if the type comes first, and faster to answer question 2 if the\nidentifier comes first. We do not want to make decisions based on the study\nbecause it isn't published, studied a small group, and doesn't directly compare\npossible `var` syntaxes; however, it still influences our thoughts.\n\n#### Syntax popularity\n\nWhen considering what to use for now, we can consider the popularity of various\nlanguages. The top 10 on several sources (with percentages noted by sources that\nhave them) are:\n\n| TIOBE        | Pct | GitHut     | Pct | PYPL        | Pct | Octoverse  |\n| ------------ | --: | ---------- | --: | ----------- | --: | ---------- |\n| C            | 16% | JavaScript | 19% | Python      | 30% | JavaScript |\n| Java         | 11% | Python     | 16% | Java        | 17% | Python     |\n| Python       | 11% | Java       | 11% | JavaScript  |  8% | Java       |\n| C++          |  7% | Go         |  8% | C#          |  7% | TypeScript |\n| C#           |  4% | C++        |  7% | C and C++   |  7% | C#         |\n| Visual Basic |  4% | Ruby       |  7% | PHP         |  6% | PHP        |\n| JavaScript   |  2% | TypeScript |  7% | R           |  4% | C++        |\n| PHP          |  2% | PHP        |  6% | Objective-C |  4% | C          |\n| SQL          |  2% | C#         |  4% | Swift       |  2% | Shell      |\n| Assembly     |  2% | C          |  3% | TypeScript  |  2% | Ruby       |\n\nSources:\n\n-   [TIOBE](https://www.tiobe.com/tiobe-index/) as of 2021-02\n-   [GitHut](https://madnight.github.io/githut/) as of 2020 Q4\n-   [PYPL](https://pypl.github.io/PYPL.html) as of 2021-02\n-   [Octoverse](https://octoverse.github.com/) as of 2020-10\n\nFor these languages:\n\n-   C, C++, C#, Objective-C, and Java put the identifier after the type.\n    -   These use `<type> <identifier>`, with no keyword.\n-   Python, Go, TypeScript, Visual Basic, SQL, and Swift put the type after the\n    identifier.\n    -   Python uses `<identifier>: <type>`, with no keyword. This was added in\n        [Python 3.6](https://www.python.org/dev/peps/pep-0526/), and reflects\n        language evolution.\n    -   Go uses `var <identifier> <type>`, with no colon.\n    -   TypeScript and Swift use `var <identifier>: <type>`.\n    -   Visual Basic uses `Dim <identifier> as <type>`.\n    -   SQL uses `DECLARE @<identifier> AS <type>`, where `AS` is optional.\n-   JavaScript, R, Ruby, PHP, Shell, and Assembly language do not specify types\n    in the same ways as other languages.\n\n### Type elision\n\nFirst, with Carbon it's been discussed to require use of `auto` (or a similar\nexplicit syntax marker) instead of allowing developers to elide the type\nentirely from a `var` statement. In other words, while `var Int x = 0;` is\nvalid, and `var auto x = 0;` is equivalent, there is no form such as\n`var x = 0;` which removes the type entirely.\n\nMost languages that write `var x: Int` also allow eliding the type when\nassigning a value. For example, Go allows `x := 0` and Swift allows\n`var x = 0;`. As a result, there is no need for an `auto` keyword.\n\nThis would be more surprising with `var Int x` syntax because removing the `Int`\nnow places the identifier immediately after `var`, where the type normally is.\nThis may be subtly confusing to developers. However, if `auto` is required for\nexplicitness, the issue is moot.\n\nRetaining `auto` does not eliminate the need to consider type elision as part of\nadvantages and disadvantages: if the type is put after the identifier and\n`var x: auto` syntax is used, it now becomes an inconsistency with other\nlanguages. This inconsistency would be a Carbon innovation that may confuse\ndevelopers, leading to long-term pressure to remove `auto` for consistency with\nsimilar languages, and thus a disadvantage.\n\n#### Advantages and disadvantages\n\nAdvantages:\n\n-   Consistent with languages that put a `:` in the type declaration.\n    -   Notable languages using `x: Int` syntax include Swift, Rust, Kotlin and\n        TypeScript. Go is similar but does not include `:`.\n    -   Swift puts\n        [argument labels](https://docs.swift.org/swift-book/LanguageGuide/Functions.html#ID166)\n        before variable declaration. Keeping the identifier first allows\n        consistency with Swift's argument label syntax while also keeping names\n        adjacent.\n-   More opportunity to unify a concept of putting the identifier immediately\n    after the keyword.\n    -   `fn`, `import`, and `package` will all have the identifier immediately\n        after the keyword, with non-identifier content following.\n        -   It's expected that a typical function declaration will look like\n            `fn Foo(Int bar)`, with `var` only added when a storage for a copy\n            is _required_. Thus, this advantage is primarily about the function\n            identifier `Foo`, not parameter identifiers.\n    -   Other cases, such as `alias`, are likely flexible and could follow `var`\n        in concept by putting the resulting name at the end. That is,\n        `alias To = From;` for consistency with `var x: Int;` versus\n        `alias From as To;` similar to `var Int x;` ordering.\n\nDisadvantages:\n\n-   If Carbon doesn't support [type elision](#type-elision), it creates an\n    inconsistency with other notable languages using `x: Int` syntax.\n    -   It may be worth considering\n        [alternatives to `:`](#confusion-with-other-languages-and-alternatives).\n-   The ordering of `x: Int` is inconsistent with C++ variable syntax.\n    -   Negatively affects\n        [Familiarity for experienced C++ developers with a gentle learning curve](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\n    -   It is consistent with other parts of C++ syntax, particularly\n        `using To = From;`, although not `typedef From To;`.\n-   Early signs are that putting the identifier first makes it slower for\n    developers to answer the question, \"what is the type of variable `x`?\"\n    -   This indicates worse readability in spite of the sentence ordering, the\n        essential part of\n        [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n-   Popular languages tend to use `int x` syntax, including C, Java, C++, and\n    C#. Other notable languages include Groovy and Dart.\n\n#### Conclusion\n\nWe should conduct a larger study on the topic of type and identifier ordering\nand syntax. Until then, we should adopt C++-like syntax. This meets the\nmigration sub-goal\n\n[Familiarity for experienced C++ developers with a gentle learning curve](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code),\nand allows applying the higher-priority goal\n[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\nif supporting evidence is found.\n\n**Experiment**: The ordering of type and identifier will be researched.\n"
  },
  {
    "path": "proposals/p0340.md",
    "content": "# while loops\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/340)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Executable semantics form](#executable-semantics-form)\n-   [Caveats](#caveats)\n    -   [C++ as baseline](#c-as-baseline)\n    -   [`do`/`while`](#dowhile)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Non-C++ syntax](#non-c-syntax)\n    -   [Initializing variables in the `while`](#initializing-variables-in-the-while)\n\n<!-- tocstop -->\n\n## Problem\n\n`while` is noted in the [language overview](/docs/design/README.md#while), but\nis provisional. Control flow is important, and `while` is basic; the form is\nsimilar in many languages, even if details may change.\n\n## Background\n\n-   C++: A couple example languages following C++'s syntax closely are Java and\n    TypeScript.\n\n    ```c++\n    while (x) {\n      DoSomething();\n    }\n\n    do {\n      DoSomethingElse();\n    } while (y);\n    ```\n\n-   Python: Python does not provide `do`/`while`. However, the `else` syntax for\n    having code execute if the condition is _never_ true may be of interest.\n\n    ```python\n    while x:\n      DoSomething()\n\n    while True:\n      DoSomethingElse()\n      if not y:\n        break\n\n    while z:\n      print(\"z is true\")\n    else:\n      print(\"z was never true\")\n    ```\n\n-   Swift: Swift uses `repeat` instead of `do`.\n\n    ```swift\n    while x {\n      DoSomething()\n    }\n\n    repeat {\n      DoSomethingElse()\n    } while y\n    ```\n\n-   Rust: Rust provides only a basic `while` loop, relying on the condition-less\n    `loop` to achieve `do`/`while`-like behavior.\n\n    ```rust\n    while x {\n      DoSomething();\n    }\n\n    loop {\n      DoSomethingElse();\n      if (!y) { break; }\n    }\n    ```\n\n-   Go: Go has no `while` loops, only `for` loops. However, a `for` can be\n    written similar to a `while`.\n\n    ```go\n    for x {\n      DoSomething()\n    }\n\n    for {\n      DoSomethingElse();\n      if !y { break; }\n    }\n    ```\n\n## Proposal\n\nCarbon should adopt `while` loop syntax consistent with C and C++. In\nparticular, it should adopt these three kinds of statements:\n\n-   `while`: declares that we're doing a loop, containing the condition.\n-   `continue`: continues with the next loop iteration, starting with the loop\n    condition.\n-   `break`: breaks out of the loop, without testing the loop condition.\n\n## Details\n\nLoop syntax looks like:\n\n-   `while (` _boolean expression_ `) {` _statements_ `}`\n\nWhile will evaluate the loop condition before each pass of the loop, only\ncontinuing if the loop condition is true. When the loop condition evaluates to\nfalse, the loop completes.\n\nSimilar to the\n[`if`/`else` proposal](https://github.com/carbon-language/carbon-lang/pull/285),\nthe braces are optional and must be paired (`{ ... }`) if present. When there\nare no braces, only one statement is allowed.\n\n`continue` will continue with the next loop iteration directly, skipping any\nother statements in the loop body. The next loop iteration behaves as normal,\nstarting with the condition being tested.\n\n`break` exits the loop immediately, without testing the condition.\n\nAll of this is consistent with C and C++ behavior.\n\n### Executable semantics form\n\n```\n%token WHILE\n%token CONTINUE\n%token BREAK\n\nstatement:\n  WHILE '(' expression ')' statement\n| CONTINUE ';'\n| BREAK ';'\n| /* preexisting statements elided */\n;\n```\n\nNote that `continue` and `break` should only be valid in a loop context.\n\n## Caveats\n\n### C++ as baseline\n\nThis baseline syntax is based on C++, following the migration sub-goal\n[Familiarity for experienced C++ developers with a gentle learning curve](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\nTo the extent that this proposal anchors on a particular approach, it aims to\nanchor on C++'s existing syntax, consistent with that sub-goal.\n\nAlternatives will generally reflect breaking consistency with C++ syntax. While\nmost proposals may consider alternatives more, this proposal suggests a\nthreshold of only accepting alternatives that skew from C++ syntax if they are\nclearly better; the priority in this proposal is to _avoid debate_ and produce a\ntrivial proposal. Where an alternative would trigger debate, it should be\nexamined by an advocate in a separate proposal.\n\n### `do`/`while`\n\n`do`/`while` is omitted from this proposal because of disagreement about whether\nit should be included in Carbon. It's better to have `do`/`while` considered\nseparately as a result, in order to separate review of the non-contentious\n`while`.\n\n## Rationale based on Carbon's goals\n\nRelevant goals are:\n\n-   [3. Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n\n    -   `while` loops are easy to read and very helpful.\n\n-   [7. Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):\n\n    -   Keeping syntax close to C++ will make it easier for developers to\n        transition.\n\n## Alternatives considered\n\nBoth alternatives from the\n[`if`/`else` proposal](https://github.com/carbon-language/carbon-lang/pull/285)\napply to `while` as well: we could remove parentheses, require braces, or both.\nThe conclusions mirror here in order to avoid a divergence in syntax.\n\nAdditional alternatives follow.\n\n### Non-C++ syntax\n\nVarious non-C++ features that came up and are not suggested by this proposal\nbecause they aren't in C++ are:\n\n-   `else` on `while`, as in Python.\n-   A `loop` statement with `while(true)` behavior, as in Rust.\n-   Labeled break and continue statements, as in Java or TypeScript.\n\nThese may be added later, but they are not part of the\n[C++ baseline](#c-as-baseline), and have not received much consideration beyond\nthat adopting the proposed syntax would not significantly impair adoption of\nsuch features.\n\n### Initializing variables in the `while`\n\nThis proposal does not offer a way to initialize variables in the `while`.\n\nFor comparison, C++ does allow declaring a variable in the condition, such as:\n\n```c++\nwhile (optional<T> next = get_next()) { ... }\n```\n\nIn addition,\n[Selections statements with initializer](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r1.html)\ncould be inferred to suggest a corresponding `while (init; cond)` syntax.\n\nNeither of these is suggested in this proposal because we are likely to consider\na _different_ route of allowing declaration of a variable in expressions. For\nexample, the following would be legal not because `while` would use a\n`condition` semantic that allows variable declarations as a form, but because it\nuses `expression` semantics and `var` would be part of `expression` semantics:\n\n```carbon\nwhile (var optional<T> next = get_next()) { ... }\n```\n\nIn particular, this would also allow more flexible usage addressing more complex\nuse-cases that C++ does not, such as:\n\n```carbon\nwhile ((var status_code c = bar()) != SUCCESS) { ... }`\n```\n\nThis breaks slightly from the [C++ baseline](#c-as-baseline) by offering a\nsubset of C++ functionality. However, we can choose to add related functionality\nlater if `expression` semantics end up not including `var`. Temporarily omitting\n`condition` functionality avoids having to reconcile it later if we pursue the\n`expression` route, and it is not crucial to `while` loop functionality.\n"
  },
  {
    "path": "proposals/p0353.md",
    "content": "# `for` loops\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/353)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [C++](#c)\n    -   [Java](#java)\n    -   [TypeScript and JavaScript](#typescript-and-javascript)\n    -   [Python, Swift, and Rust](#python-swift-and-rust)\n    -   [Go](#go)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Range inputs](#range-inputs)\n    -   [Executable semantics form](#executable-semantics-form)\n-   [Caveats](#caveats)\n    -   [C++ as baseline](#c-as-baseline)\n    -   [Semisemi support](#semisemi-support)\n    -   [Range literals](#range-literals)\n    -   [Enumerating containers](#enumerating-containers)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Include semisemi `for` loops](#include-semisemi-for-loops)\n    -   [Writing `in` instead of `:`](#writing-in-instead-of-)\n    -   [Multi-variable bindings](#multi-variable-bindings)\n\n<!-- tocstop -->\n\n## Problem\n\nControl flow is documented at\n[language overview](/docs/design/README.md#control-flow). `for` loops are common\nin C++, and Carbon should consider providing some form of it.\n\n## Background\n\n### C++\n\nThere are two forms of `for` loops in C++:\n\n-   **Semisemi** (semicolon, semicolon): `for (int i = 0; i < list.size(); ++i)`\n-   **Range-based**: `for (auto x : list)`\n\nSemisemi `for` loops have been around for a long time, and are in C. Range-based\n`for` loops were added in C++11.\n\nFor example, here is a basic semisemi:\n\n```c++\nfor (int i = 0; i < list.size(); ++i) {\n  printf(\"List at %d: %s\\n\", i, list[i].name);\n}\n```\n\nAn equivalent semisemi using iterators and the comma operator may look like:\n\n```c++\nint i = 0;\nfor (auto it = list.begin(); it != list.end(); ++it, ++i) {\n  printf(\"List at %d: %s\\n\", i, it->name);\n}\n```\n\nRange-based syntax can be simpler, but can also make it more difficult if there\nare multiple pieces of interesting information:\n\n```c++\nint i = 0;\nfor (const auto& x : list) {\n  printf(\"List at %d: %s\\n\", i, x.name);\n  ++i;\n}\n```\n\n### Java\n\nJava provides equivalent syntax to C++. Although Java doesn't have a comma\noperator, it does provide for comma-separated statements in the first and third\nsections of semisemi for loops.\n\n### TypeScript and JavaScript\n\nBoth TypeScript and JavaScript offer three kinds of for loops:\n\n-   Semisemi, mirroring C++.\n-   `for (x of list)`, mirroring range-based for loops.\n-   `for (x in list)`, returning indices.\n\nFor example, here is an `in` loop:\n\n```javascript\nfor (i in list) {\n    console.log('List at ' + i + ': ' + list[i].name);\n}\n```\n\n### Python, Swift, and Rust\n\nPython, Swift, and Rust all only support range-based for loops, using\n`for x in list` syntax.\n\n### Go\n\nGo uses `for` as its primary looping construct. It has:\n\n-   Semisemi, mirroring C++.\n-   `for i < list.size()` condition-only loops, mirroring C++ `while` loops.\n-   `for {` infinite loops.\n\n## Proposal\n\nCarbon should adopt C++-style range-based `for` loops syntax. Semisemi `for`\nloops should be addressed through a different mechanism.\n\nRelated keywords are:\n\n-   `for`\n-   `continue`: continues with the next loop iteration.\n-   `break`: breaks out of the loop.\n\n## Details\n\nFor loop syntax looks like: `for (` `var` _type_ _variable_ `:` _expression_\n`) {` _statements_ `}`\n\nSimilar to the\n[if/else proposal](https://github.com/carbon-language/carbon-lang/pull/285), the\nbraces are optional and must be paired (`{ ... }`) if present. When there are no\nbraces, only one statement is allowed.\n\n`continue` will continue with the next loop iteration directly, skipping any\nother statements in the loop body.\n\n`break` exits the loop immediately.\n\nAll of this is consistent with C and C++ behavior.\n\n### Range inputs\n\nThe syntax for inputs is not being defined in this proposal. However, we can\nstill establish critical things to support:\n\n-   Interoperable C++ objects that work with C++'s range-based `for` loops, such\n    as containers with iterators.\n-   Carbon arrays and other containers.\n-   Range literals. These are not proposed, but for an example seen in other\n    languages, `0..2` may indicate the set of integers [0, 2).\n\n### Executable semantics form\n\n```bison\n%token FOR\n\nstatement:\n  FOR \"(\" pattern \":\" expression \")\" statement\n| /* preexisting statements elided */\n;\n```\n\nThe `continue` and `break` statements are intended to be added as part of the\n[while proposal](https://github.com/carbon-language/carbon-lang/pull/340).\n\n## Caveats\n\n### C++ as baseline\n\nThis baseline syntax is based on C++, following the migration sub-goal\n[Familiarity for experienced C++ developers with a gentle learning curve](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\nTo the extent that this proposal anchors on a particular approach, it aims to\nanchor on C++'s existing syntax, consistent with that sub-goal.\n\nAlternatives will generally reflect breaking consistency with C++ syntax. While\nmost proposals may consider alternatives more, this proposal suggests a\nthreshold of only accepting alternatives that skew from C++ syntax if they are\nclearly better; the priority in this proposal is to _avoid debate_ and produce a\ntrivial proposal. Where an alternative would trigger debate, it should be\nexamined by an advocate in a separate proposal.\n\n### Semisemi support\n\nCarbon will not provide semisemi support. This decision will be contingent upon\na better alternative loop structure which is not currently provided by `while`\nor `for` syntax. If Carbon doesn't evolve a better solution, semisemi support\nwill be added later.\n\nFor details, see [the alternative](#include-semisemi-for-loops).\n\n### Range literals\n\nRange literals are important to the ergonomics of range-based `for` loops, and\nshould be added. However, they should be examined separately as part of limiting\nthe scope of this proposal.\n\n### Enumerating containers\n\nSeveral languages have the concept of providing an index with the object in a\nrange-based for loop:\n\n-   Python does `for i, item in enumerate(items)`, with a global function.\n-   Go does `for i, item := range items`, with a keyword.\n-   Swift does `for (i, item) in items.enumerated()`, having removed a\n    `enumerate()` global function.\n-   Rust does `for (i, item) in items.enumerate()`.\n\nAn equivalent pattern for Carbon should be examined separately as part of\nlimiting the scope of this proposal.\n\n## Rationale based on Carbon's goals\n\nRelevant goals are:\n\n-   [3. Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n\n    -   Range-based `for` loops are easy to read and very helpful.\n    -   Semisemi `for` syntax is complex and can be error prone for cases where\n        range-based loops work. Avoiding it, even by providing equivalent syntax\n        with a different loop structure, should discourage its use and direct\n        engineers towards better options. The alternative syntax should also be\n        easier to understand than semisemi syntax, otherwise we should just keep\n        semisemi syntax.\n\n-   [7. Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):\n\n    -   Keeping syntax close to C++ will make it easier for developers to\n        transition.\n\n## Alternatives considered\n\nBoth alternatives from the\n[`if`/`else` proposal](https://github.com/carbon-language/carbon-lang/pull/285)\napply to `while` as well: we could remove parentheses, require braces, or both.\nThe conclusions mirror here in order to avoid a divergence in syntax.\n\nAdditional alternatives follow.\n\n### Include semisemi `for` loops\n\nWe could include semisemi for loops for greater consistency with C++.\n\nThis is in part important because switching from a semisemi `for` loop to a\n`while` loop is not always straightforward due to how `for` evaluates the third\nsection of the semisemi. The inter-loop evaluation of the third section is\nimportant given how it interacts with `continue`. In particular, consider the\nloops:\n\n```c++\nfor (int i = 0; i < 3; ++i) {\n  if (i == 1) continue;\n  printf(\"%d\\n\", i);\n}\n\nint j = 0;\nwhile (j < 3) {\n  if (j == 1) continue;\n  printf(\"%d\\n\", j);\n  ++j;\n}\n\nint k = 0;\nwhile (k < 3) {\n  ++k;\n  if (k == 1) continue;\n  printf(\"%d\\n\", k);\n}\n\nint l = 0;\nwhile (l < 3) {\n  if (l == 1) {\n    ++l;\n    continue;\n  }\n  printf(\"%d\\n\", l);\n  ++l;\n}\n```\n\nTo explain the differences between these loops:\n\n-   The first loop will print 0 and 2.\n-   The second loop will print 0, then loop infinitely because the increment is\n    never reached.\n-   The third loop will only print 2 because the increment happens too early.\n-   Only the fourth loop is equivalent to the first loop, and it duplicates the\n    increment.\n\nThere is no easy place to put the increment in a `while` loop.\n\nAdvantages:\n\n-   We need a plan for\n    [migrating both developers and code from C++](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    semisemis `for` loops, and providing them in Carbon is the easiest solution.\n    -   Semisemis remain common in C++ code.\n-   Semisemis are much more flexible than range-based `for` loops.\n    -   `while` loops do not offer a sufficient alternative.\n\nDisadvantages:\n\n-   Semisemi loops can be error prone, such as `for (int i = 0; i < 3; --i)`.\n    -   Syntax such as `for (int x : range(0, 3))` leaves less room for\n        developer mistakes.\n    -   Removing semisemi syntax will likely improve\n        [understandability of Carbon code](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\n        a language goal.\n-   If we add semisemi loops, it would be very difficult to get rid of them.\n    -   Code using them should be expected to accumulate quickly, from both\n        migrated code and developers familiar with C++ idioms.\n\nIf we want to remove `for` loops, we should avoid adding them. We do need to\nensure that developers are _happy_ with the replacement, although that should be\nachievable through providing strong range support, including range literals.\n\nA story for migrating developers and code is still required. For developers, it\nwould be ideal if we could have a compiler error that detects semisemi loops and\nadvises the preferred Carbon constructs. For both developers and code, we need a\nsuitable loop syntax that is easy to use in cases that remain hard to write in\n`while` or range-based `for` loops. This will depend on a separate proposal, but\nthere's at least presently interest in this direction.\n\n### Writing `in` instead of `:`\n\nRange-based for loops could write `in` instead of `:`, such as:\n\n```carbon\nfor (x in list) {\n  ...\n}\n```\n\nAn argument for switching _now_, instead of using\n[C++ as a baseline](#c-as-baseline), would be that `var` syntax has been\ndiscussed as using a `:`, and avoiding `:` in range-based for loops may reduce\nsyntax ambiguity risks. However, the\n[current `var` proposal](https://github.com/carbon-language/carbon-lang/pull/339)\ndoes not use a `:`, and so this risk is only a potential future concern: it's\ntoo early to require further evaluation.\n\nBecause the benefits of this alternative are debatable and would diverge from\nC++, adopting `in` would run contrary to\n[using C++ as a baseline](#c-as-baseline). Any divergence should be justified\nand reviewed as a separate proposal.\n\n### Multi-variable bindings\n\nC++ allows `for (auto [x, y] : range_of_pairs)` which is not explicitly part of\nthe syntax here. Carbon is likely to support this through tuples, so adding\nspecial `for` syntax for this would likely be redundant.\n"
  },
  {
    "path": "proposals/p0415.md",
    "content": "# Syntax: `return`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/415)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Deferred questions](#deferred-questions)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Implicit or expression returns](#implicit-or-expression-returns)\n\n<!-- tocstop -->\n\n## Problem\n\nCarbon has functions. We should write down how those functions indicate their\ncode should stop running and, if applicable, what result should be provided back\nto their caller.\n\n## Background\n\nThe Carbon overview [contains](/docs/design/README.md#return) a \"skeletal\ndesign\" for `return`.\n\nCarbon aims for\n[_familiarity for experienced C++ developers with a gentle learning curve_](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\nC++ returns from functions with a `return` statement, which is documented well\n[here](https://en.cppreference.com/w/cpp/language/return).\n\n## Proposal\n\nCarbon will have a `return` statement that is unsurprising to C++ programmers.\n\nEach of these is a valid Carbon function:\n\n```\n// A function that returns no value\nfn NoReturn() {\n  // This function intentionally left blank\n}\n\n\n// A function that returns no value in a different way\nfn ReturnNoValue() {\n  // Usually no expression in a function with no return value.\n  return;\n}\n\n\n// A function that returns a value\nfn ReturnFive() -> Int {\n  // Must include an expression \"convertible\" to `Int`.\n  // The (lack of) definition for \"convertible\" is addressed later.\n  return 5;\n}\n```\n\n## Details\n\nWe define a `return` statement in Carbon. It can occur any place a statement is\nallowed. It takes one optional expression, the _return value_. Functions may\ncontain multiple `return` statements.\n\nA function that returns `Void` may have `return` statements. Most will have no\nreturn value, though some may provide a `Void`-type expression, for example the\nresult of another `Void`-returning function.\n\n> This last affordance is provided to avoid making `Void` a special case in\n> templating.\n\nFunctions returning `Void` are also defined to end with an implicit `return`\nstatement.\n\n> This implicit `return` is intended to make it easier for later designs to\n> refer to \"the (now always present) `return` statement\" rather than the less\n> well-defined \"the point the function returns\".\n\nA function that returns anything other than `Void` must have at least one\n`return` statement. All `return` statements in the function must provide an\nexpression \"convertible\" to the function's return type. If a control flow path\nreaches the end of the function without executing a `return` statement, it is a\ncompile error.\n\n### Deferred questions\n\nThis proposal is limited to the syntax and simple static semantics of the\n`return` statement.\n\nSome questions about the full validity and meaning of a `return` statement in\ncontext are left unresolved, in the expectation they will be addressed when\nadjacent parts of the language are specified.\n\nThose include:\n\n-   **What does \"convertible\" mean?**\n\n    When a function returns a value, we say the `return` statement takes an\n    expression \"convertible\" to the function's return type. As a coarse\n    approximation, this may mean \"assignable to a variable of the function's\n    return type\", but there are likely to be subtleties. We assume this question\n    will be addressed as the type system develops.\n\n-   **What optimizations are encouraged or guaranteed for return values?**\n\n    C++ has\n    [copy elision](https://en.cppreference.com/w/cpp/language/copy_elision) and\n    it's a good bet Carbon will too. But first we need to decide what copying\n    means.\n\n-   **What code, if any, runs between `return` and _returning_?**\n\n    Carbon is likely to have approaches for deterministic cleanup that trigger\n    when a function's code stops executing -- analogues to C++ destructors,\n    Golang deferred functions, or Java's `finally` blocks. Once we know what\n    they are and how we intend them to work, we can determine how to slot them\n    in next to `return`.\n\n## Alternatives considered\n\n### Implicit or expression returns\n\nSome C-family languages allow an unadorned expression in the right context to\nserve as a return value.\n\nIn Rust, for example, function bodies are\n[block expressions](https://doc.rust-lang.org/reference/expressions/block-expr.html),\nwhich may have an expression as their final clause and which take the value of\nthat expression.\n\nThis Rust function returns `5`:\n\n```rust\nfn return_five() -> i32 {\n    perhaps_unrelated_action();\n    5\n}\n```\n\nRust still has a `return` statement, so this is entirely an ergonomic feature.\n\nWe can choose to add a similar feature to Carbon in the future as long as we can\nunambiguously discern expressions and statements in parsing.\n"
  },
  {
    "path": "proposals/p0426.md",
    "content": "# Governance & evolution revamp\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/426)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n    -   [Governance](#governance)\n    -   [Evolution process](#evolution-process)\n    -   [Specific changes to members](#specific-changes-to-members)\n-   [Evolution process details](#evolution-process-details)\n    -   [Proposal PRs](#proposal-prs)\n    -   [Review and RFC on proposal PRs](#review-and-rfc-on-proposal-prs)\n    -   [Open questions or blocking issues with proposal PRs](#open-questions-or-blocking-issues-with-proposal-prs)\n-   [Rationale for the proposal based Carbon's goals](#rationale-for-the-proposal-based-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Status-quo](#status-quo)\n    -   [Retain a large (8+ people) core team, change role and process](#retain-a-large-8-people-core-team-change-role-and-process)\n    -   [Retain consistent use of fixed duration comment periods](#retain-consistent-use-of-fixed-duration-comment-periods)\n\n<!-- tocstop -->\n\n## Problem\n\nToday's governance and evolution process are not meeting the current needs of\nthe Carbon project in a few ways:\n\n-   Expensive both in effort expended and in wall clock latency to make\n    decisions, at a time when both resources are in short supply on the Carbon\n    project.\n    -   This won't allow Carbon to achieve its goals given the time available.\n    -   These costs are not proportional. The high constant overhead places a\n        relatively higher cost on simple, uncontroversial proposals.\n-   Proposal authors get a disproportionately large amount of feedback\n    (exacerbating the costs for them of pushing the proposal forward) and a\n    disproportionate amount of _negative_ feedback.\n    -   Because there are always many more core team members than authors, even\n        with the best intentions of all involved there will inevitably be an\n        amplification of even accidental negative or unconstructive feedback.\n-   Doesn't allow for specific intermediate questions to come up and be resolved\n    at a smaller granularity than \"a proposal\".\n    -   Sometimes, this results in paying the full overhead of a proposal to\n        merely answer an intermediate question.\n    -   Other times this has resulted in a near combinatorial explosion of\n        complexity in the proposal due to a collection of intersecting open\n        questions rather than serializing them eagerly and simplifying\n        accordingly.\n-   The mechanisms used for the evolution process spread elements of the\n    discussion across a number of different tools and \"inboxes\". While each of\n    these has specific features lacking in the others, the spread carries with\n    it high cost, especially for new community members.\n\nAn orthogonal problem that is worth solving while here is to update the set of\npeople providing governance for Carbon. This is not a pressing problem, but the\nset should grow to reflect the many new and active members of the project.\n\n## Proposal\n\nThis proposal makes significant changes to both the governance model and\nevolution process. Rather than describing the delta, it focuses on the newly\nproposed model and process.\n\n### Governance\n\nThe primary governance model for Carbon shifts to be handled directly by the\narbiters from the prior system. There remain three of them, and they make\ndecisions by blocking consensus with a quorum of two. The group is renamed to\nthe \"Carbon Leads\". They may in the future create other similarly small groups\nof leads and delegate specific domains or decisions.\n\nThe core team, as well as other teams, are replaced with a directory of experts.\nThis is an informal list of experts with different backgrounds, experience,\nexpertise, and interest. It is indexed by these different areas and focuses on\nbreadth. People listed should be actively interested in Carbon, invested in its\nsuccess, and available to engage on their relevant topic area. The intent is to\nboth surface different interested parties, and provide resources for\ncontributors to Carbon for advice, information, or insight on specific areas.\n\n### Evolution process\n\nAn overview of the new evolution process, but note that details are saved for\nthe detailed section below:\n\n-   Proposals consist of a PR (pull request) in GitHub that adds a new document\n    to the `proposals/` directory of the project, using a similar template to\n    our current one.\n-   Sending a _proposal_ PR for review also signifies a RFC (request for\n    comment) from the entire community.\n-   One of the three leads should be added as the _assigned_ reviewer.\n-   Contributors should react with a _thumbs-up_ to the proposal PR if they are\n    generally interested and supportive of the high level direction based on\n    title and summary.\n-   Comments during the RFC that represent a _blocking concern_ are moved to\n    their own GitHub issue, and assigned to the leads to decide.\n-   The assigned lead should ensure that at least three contributors (possibly\n    including the lead) are generally supportive and react with thumbs-up. If a\n    proposal doesn't have these thumbs-up, the leads together need to decide\n    whether to move forward, and if so provide those thumbs-up.\n-   If the lead chooses to defer or reject the proposal, they should explain why\n    and close the PR.\n-   Once the thumbs-up are present and the assigned lead finishes code review,\n    the lead should [approve](/docs/project/code_review.md#approving-the-change)\n    the PR. Any outstanding high-level concerns should be handled with blocking\n    issues.\n-   Optionally, the assigned lead can file a blocking issue for a one week final\n    comment period when they approve if it is both useful and important for the\n    proposal.\n-   The proposal PR can be submitted once the assigned lead approves, all\n    blocking issues have been decided, and any related decisions are\n    incorporated.\n\nIt is also useful to see what the process looks like for different roles within\nthe community. These perspectives are also the most critical to keep simple and\neasily understood.\n\n**Proposal author:** this should feel like a code review, with some broken out\nissues for longer discussion:\n\n-   Create a proposal document and PR following the template, potentially using\n    a script.\n-   When ready, send this for review to the leads GitHub team to get an assigned\n    reviewer.\n    -   This will also send the proposal as a broad RFC to the community.\n-   Address comments where you can and they make sense.\n-   If you don't see an obvious way to address comments, that's OK.\n    -   It's great to engage a bit with the commenter just like you would in\n        code review to clarify their comment or why you don't see an obvious way\n        to address it.\n    -   If the commenter feels this is important, they can move it to a blocking\n        issue for a longer discussion and resolution from the leads.\n    -   You don't need to try to resolve everything yourself.\n-   Incorporate any changes needed based on the resolution of blocking issues.\n    Once the leads have provided a resolution, it's important to make progress\n    with that direction.\n-   When you both have an\n    [LGTM](/docs/project/code_review.md#approving-the-change) from the assigned\n    lead and the last blocking issue is addressed, submit!\n    -   If you end up making significant changes when incorporating resolved\n        issues after the LGTM from the assigned lead, circle back for a fresh\n        LGTM before landing, just like you would with code review.\n\n**Community:** anyone that is interested can participate in the RFC:\n\n-   It's OK to only do this when particularly interested in a proposal, or when\n    asked by one of the leads to help ensure thorough review. Not everyone needs\n    to participate heavily in every RFC.\n-   Once a proposal is sent for review and RFC, read it and leave comments to\n    try to help make the proposal an improvement for Carbon.\n    -   Note that progress and improvement are more important than perfection\n        here!\n-   Try to make comments on proposals constructive. Suggest how the proposal\n    could be better if at all possible.\n-   If there is an open question or a critical blocking issue that needs to get\n    resolved, move it to its own issue that the PR depends on, and focus the\n    discussion there.\n    -   The issue should focus on surfacing the important aspects of the\n        tradeoff represented by the issue or open question, not on advocacy.\n\n**Active contributors:** everyone actively contributing to the evolution of\nCarbon should try to regularly:\n\n-   Give a thumbs-up or other reaction on any interesting PRs out for RFC to\n    help surface general enthusiasm for the high level idea / direction. Don't\n    worry about \"approving\" or the details here.\n-   If interested and time permitting, dive into some RFCs with community\n    feedback.\n\n**Carbon Leads:** responsible for making decisions rapidly and ensuring proposal\nPRs land:\n\n-   Rapidly resolve all blocking issues raised across any proposals.\n-   When assigned a specific proposal PR:\n    -   Make sure it gets both constructive general comments and good code\n        review.\n    -   Ideally, you should directly participate in the code review at least,\n        but it's fine to ask others to help. However, ultimately you have to\n        give an LGTM.\n    -   Escalate any blocking issues without a resolution that are slowing down\n        the proposal to the other leads.\n    -   Evaluate whether an extended final comment period is important for the\n        community given the nature of the proposal.\n\n### Specific changes to members\n\nThis proposal asks Kate Gregory to join the leads, replacing Titus Winters who\ndoesn't currently have the bandwidth to participate as actively. Given the shift\nto the leads handling a more direct share of the evolution process, it seems\nprudent to make this change at the same time.\n\nNo specific composition of the experts directory is proposed here. Instead, it\nis suggested to collaboratively build that with interested parties adding\nthemselves and helping structure the domains / areas to be covered. Those\nchanges shouldn't require any formal proposal, and can simply be approved by any\none of the leads.\n\n## Evolution process details\n\n### Proposal PRs\n\nA proposal PR should use the `proposal` label, have a descriptive title, and\neasily understood initial summary comment. Authors and leads are encouraged to\nedit both as necessary to ensure they give the best high-level understanding of\nthe proposal possible. The proposals should then use the template markdown file\nto describe itself fully. This template will have an additional section to\ncontain the rationale for the proposal being accepted.\n\nThe purpose of the rationale section will match the prior process's rationale:\nit must explain how the proposal furthers the goals for Carbon. It is important\nthat proposals stay aligned with Carbon's goals, and where they need to change\nover time we change the goals themselves rather than inventing new rationale\nincrementally. While the author of the proposal should suggest an initial\nrationale, the reviewers and leads can also help improve this to make sure it\ncaptures the basis on which the proposal is accepted. Authors shouldn't stress\nabout getting the rationale right out of the box, this is among the easiest\nparts to improve with help from the community.\n\nProposal PRs can also include changes to the rest of the Carbon project as part\nof the PR, in subsequent PRs that are referenced for context, or they can be\nstand-alone changes that are implemented through a series of future PRs to the\nrest of the project. All of these options are fine.\n\nThere won't be a separate \"decision\" file for proposals as the rationale will be\nincorporated, and the decision will be marked by closing the PR. Existing\nproposals should be updated to merge their decisions into the document so that\nwe have a simpler layout of the proposals tree and can have simple and easy\ntooling around it.\n\nPRs that are in \"draft\" status in GitHub are considered works-in-progress\n(rather than prior `WIP` label). Check with the author before spending time\nreviewing these, and generally avoid distracting the author with comments unless\nthey ask for them. The proposal may be actively undergoing edits.\n\nFeel free to factor out open questions in a proposal to issues that you assign\nto the leads to resolve. You can even do this before sending the proposal for\nreview. Even after resolved, an open question issue can be reopened if new\ninformation comes up during the RFC.\n\n### Review and RFC on proposal PRs\n\nWhen a proposal PR is sent for review by the leads, one of them will be assigned\nthe PR and is responsible for helping land that proposal, or explaining why the\nproject won't move forward in that direction. The assigned lead is also\nultimately responsible for the code review on the PR. Proposals sent for review\nare also sent as an RFC to the entire community.\n\nAll active Carbon contributors are strongly encouraged to regularly skim the\ntitle and summary comment of proposals under RFC that are interesting to them.\nThey should use GitHub reactions, including at least a thumbs-up, to show their\ninterest and enthusiasm about the proposal, and help encourage the author.\nWriting proposals is _extremely hard work_, and we need to clearly show both\ninterest in the proposed direction of Carbon and appreciation for the work put\ninto the proposal. This is not about _approving_ the proposal, or any of its\ndetails. It is completely fine and coherent to both give a thumbs-up to a\nproposal _and_ provide a serious, blocking issue that needs to be resolved.\n\n_Anyone_ in the community, of course including active contributors, is\nencouraged to participate in the RFC in detail if interested. However, not\neveryone needs to participate in every RFC. If a proposal is already getting\nactively and thoroughly reviewed, feel free to focus your time on other\nproposals with fewer comments. Even if there are issues or problems discovered\nlater, we can always fix them with follow-up proposals.\n\nBoth code review and high-level design comments are welcome. If an open question\ncomes up or a high level blocking issue is uncovered, feel free to move it to\nits own issue and assign it to the leads to resolve. That issue is also a good\nplace to focus discussion on that specific topic rather than the main PR.\n\nThe assigned lead should provide an LGTM on proposals once the following\ncriteria are met:\n\n-   It looks good from a code review perspective.\n-   At least three thumbs-up reactions showing general community interest.\n-   The community has had a sufficient opportunity to review the proposed\n    change, given its scope and complexity.\n-   Any remaining blocking issues are reasonably likely to resolve in a way that\n    allows the proposal to move forward. It is fine if some are not fully\n    decided, but a lead shouldn't provide an LGTM for a proposal unlikely to\n    move forward.\n\nThe last two criteria are fundamentally judgement calls for the lead to make,\nand we don't try to formulate a rigid or fixed bar for them. If resolving the\nblocking issues requires significant changes, the author should also get a fresh\nLGTM from the assigned lead after those changes, just like they would with code\nreview.\n\nThe assigned lead may also request a final comment period for the community when\ngiving an LGTM. This signals to the community that the proposal is likely to\nmove forward once the blocking issues are resolved, and any remaining concerns\nneed to be surfaced. The goal is to help uncover concerns that were hidden until\nit was clear that the proposal is likely to move forward. However, this is not\nthe default. The assigned lead should only do this when there is some reason to\nexpect further community comment is especially important to solicit. Common\ncases to consider are contentious, complex, or dramatic changes to the language\nor project. Ultimately, whether this is important is a judgement call for the\nlead. This will be modeled by filing a blocking issue that resolves in one week\nwhen giving the LGTM. This issue will also explain the motivation for requesting\na final comment period.\n\n### Open questions or blocking issues with proposal PRs\n\nAny time an open question or a blocking issue is filed for the leads to resolve,\nthat issue forms both the primary discussion thread and where the leads signal\nhow it is resolved. We use issues both to track that there is a specific\nresolution expected and that there may be dependencies.\n\nThese issues can be created at any time and by any one. Issues can be created\nwhile the proposal is a WIP or draft in order to help inform specific content\nthat should go into the proposal. It is even fine to create an issue first, even\nbefore a proposal exists, as an open question about whether to produce a\nparticular proposal, or what a proposal that is being planned should say. For\nissues which don't (yet) have a specific proposal PR associated with them, at\nsome point the leads may ask that a proposal be created to help collect in a\nmore cohesive place a written overview of the issue and related information, but\nthis process need not be strictly or rigidly bound to having proposal text.\n\nDiscussion on these issues, especially contentious ones, should endeavor to\nfocus on surfacing information and highlighting the nature of the tradeoff\nimplied by the decisions available. This is in contrast to focusing on advocacy\nor persuasion. The goal of the issues shouldn't be to persuade or convince the\nleads to make a specific decision, but to give the leads the information they\nneed to make the best decision for Carbon. It is of course fine that some people\nhave a specific belief of which decision would be best. However, by framing\ntheir contributions to the discussion as surfacing the information that\nunderpins that belief the discussion is more likely to be constructive,\nwelcoming, and effective. Overall, everyone should strive to minimize their use\nof [rhetoric](https://en.wikipedia.org/wiki/Rhetoric) or other\n[persuasive methods](https://en.wikipedia.org/wiki/Persuasion#List_of_methods)\nto the extent they can. However, none of this should preclude gathering\ninformation like polls of opinion among groups, or signaling agreement. Where\ncommunity members stand and how many agree with that stance on any issue _is_\ninformation, and useful to surface.\n\nAvoid using issues for things that are just requests or suggestions on a\nproposal PR. If in doubt, start off with a simple comment on the PR and see if\nthere is any disagreement -- everyone may already be aligned and agree. When a\ncomment does seem worth turning into an issue, don't worry about that as the\nauthor or the commenter. Getting the leads to resolving a disagreement isn't a\nbad thing for anyone involved. This should be seen as a friendly way to move the\ndiscussion with more disagreement out to its own forum where it'll get resolved,\nand focus the PR on improving the proposal and getting it ready to land.\n\nWhen an issue is created from a discussion on a PR, and after the discussion on\nthe _issue_ all the original parties actually come to a happy agreement, it's\ntotally ok to just close the issue and move back to the code review in the PR.\nAnyone who would prefer the leads to still chime in can just re-open the issue\nand the leads will follow up, even if its just to get confirmation that everyone\n_did_ end up happy with the resolution. At the end of the day, while it's fine\nto resolve an issue that _everyone_ actually ended up agreeing about (maybe once\nsome confusion is addressed), ultimately the leads are responsible for resolving\nthese issues and there is no pressure on anyone else to do so.\n\n## Rationale for the proposal based Carbon's goals\n\nOur goals document identifies that \"[t]he community needs to be able to\neffectively engage in the direction and evolution of the project and language,\nwhile keeping the process efficient and effective. That means we need an open,\ninclusive process where everyone feels comfortable participating. Community\nmembers should understand how and why decisions are made, and have the ability\nto both influence them before they occur and give feedback afterward.\"\n\nOur prior process, in a well-intentioned effort to ensure we have scope for\ncommunity engagement, is not as efficient and effective as we would like, and\nthat lack of efficiency ironically has a negative impact on community engagement\nthat outweighs the benefits. The proposed process removes several artificial\ndelays from our process and enables much earlier feedback and decision-making as\npart of proposal development, ideally without introducing a negative impact on\nany of the other aspects of this goal.\n\n## Alternatives considered\n\n### Status-quo\n\nWe could simply not make a change here.\n\nAdvantages:\n\n-   No need to make a change.\n\nDisadvantages:\n\n-   Does not solve any of the problems.\n\n### Retain a large (8+ people) core team, change role and process\n\nWe could attempt to solve the problems cited while keeping the larger core team\nstructure. This would largely involve carefully changing the role that members\nof the core team fill when making decisions, and the process used to make those\ndecisions.\n\nAdvantages:\n\n-   Less dramatic change to the governance structure\n-   Retains a leadership group that can have some realistic breadth across the\n    community\n\nDisadvantages:\n\n-   Extremely difficult to formulate a role that both serves a purpose and\n    addresses the cited problems.\n-   Every idea for both process and role that seemed to potentially help the\n    problems listed also ended up heavily leaning on the arbiters and thus\n    reducing the utility of the role.\n-   Continues to require forming and sustaining the core team.\n-   Would inherently result in slower progress.\n\n### Retain consistent use of fixed duration comment periods\n\nThese were added based on the repeated failure modes seen in other language\ncommunities where members of the community didn't feel they had sufficient\nopportunity to participate in discussions. We could retain them with the new\nprocess.\n\nAdvantages:\n\n-   Defends against failure modes seen in other language evolution processes.\n-   Ensures a predictable amount of time for the community to comment.\n\nDisadvantages:\n\n-   Would dramatically slow the rate of progress.\n-   Reduces the ability of proposal authors to fully feel satisfied and rewarded\n    for their effort by separating all of their work from any of the benefits\n    being accrued.\n    -   This kind of delay decreases human feelings of satisfaction with work,\n        which in turn disincentives people making proposals and seeing them\n        through to completion.\n-   Unclear whether the failure modes observed in other language evolution\n    processes will actually occur for Carbon.\n    -   Many other aspects of the projects and communities are sufficiently\n        different to make the prediction difficult.\n    -   Initially, the size of the project alone makes these concerns a\n        non-issue.\n-   Makes it too easy to delay commenting until the end of the period.\n    -   This in turn can cause comments to be rushed to avoid the period\n        expiring.\n"
  },
  {
    "path": "proposals/p0438.md",
    "content": "# Functions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/438)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [C++ syntax](#c-syntax)\n    -   [Other languages](#other-languages)\n    -   [Forward declarations](#forward-declarations)\n-   [Proposal](#proposal)\n    -   [Functions](#functions-1)\n    -   [Forward declarations](#forward-declarations-1)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Open questions](#open-questions)\n    -   [Calling functions defined later in the same file](#calling-functions-defined-later-in-the-same-file)\n    -   [Optional argument names](#optional-argument-names)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Function keyword](#function-keyword)\n        -   [Type](#type)\n        -   [`-` (dash)](#--dash)\n        -   [`def`](#def)\n        -   [`fn`](#fn)\n        -   [`fun`](#fun)\n        -   [`func`](#func)\n        -   [`function`](#function)\n    -   [Conclusion](#conclusion)\n\n<!-- tocstop -->\n\n## Problem\n\nWe currently have\n[placeholder guidance on functions](/docs/design/functions.md). The intent of\nthis proposal is to establish agreement on the basics, providing a baseline for\nfuture evolution.\n\n## Background\n\n### C++ syntax\n\nC++ syntax for function declarations comes in two forms:\n\n```cpp\nstd::int64_t Sum(std::int64_t a, std::int64_t b) {\n  return a + b;\n}\n\n// Or with trailing return type syntax:\nauto Sum(std::int64_t a, std::int64_t b) -> std::int64_t {\n  return a + b;\n}\n```\n\nBodies are always wrapped by braces.\n\n### Other languages\n\nTo summarize keyword use from other languages:\n\n-   Type: C# and Java\n-   `-`: Objective-C\n-   `def`: Python and Ruby\n-   `fn`: Rust\n-   `fun`: Kotlin\n-   `func`: Go and Swift\n-   `function`: JavaScript, MatLab, PHP, R, and TypeScript\n\nFor exhaustive function examples:\n\n-   C#\n\n    ```csharp\n    int Sum(int a, int b) {\n      return a + b;\n    }\n    ```\n\n-   Go\n\n    ```go\n    func add(a int, b int) int {\n      return a + b\n    }\n    ```\n\n-   Java\n\n    ```java\n    Int Sum(Int a, Int b) {\n      return a + b;\n    }\n    ```\n\n-   JavaScript\n\n    ```javascript\n    function Sum(a, b) {\n        return a + b;\n    }\n    ```\n\n-   Kotlin\n\n    ```kotlin\n    fun add(a: Int, b: Int): Int {\n      return a + b\n    }\n    ```\n\n-   Matlab\n\n    ```matlab\n    function s = sum(a,b)\n      s = a+b;\n    end\n    ```\n\n-   Objective-C\n\n    ```objc\n    - (int)sum:(int)a\n               (int)b {\n      return a + b;\n    }\n    ```\n\n-   PHP\n\n    ```php\n    function sum(int $a, int $b) {\n      return $a + $b;\n    }\n    ```\n\n-   Python\n\n    ```python\n    def sum(a, b):\n      return a + b\n\n    def sum(a: int, b: int) -> int:\n      return a + b\n    ```\n\n-   R\n\n    ```r\n    sum <- function(a, b) {\n      a + b\n    }\n    ```\n\n-   Ruby\n\n    ```ruby\n    def sum(a, b)\n      return a + b\n    end\n    ```\n\n-   Rust\n\n    ```rust\n    fn sum(a: i64, b: i64) -> i64 {\n      a + b\n    }\n    ```\n\n-   Swift\n\n    ```swift\n    func sum(a: Int, b: Int) -> Int {\n      return a + b\n    }\n    ```\n\n-   TypeScript\n\n    ```typescript\n    function sum(a: number, b: number): number {\n        return a + b;\n    }\n    ```\n\n### Forward declarations\n\n[Forward declarations](https://en.wikipedia.org/wiki/Forward_declaration) of\nfunctions are largely unique to C++. Objective-C also has this. However, most\nother languages being discussed do not.\n\n## Proposal\n\n### Functions\n\nFunction declarations and definitions should look like:\n\n`fn` _function name_ `(` _type identifier \\[_ `,` _type identifier ]..._ `)` _[_\n`->` _return type_ _] [_ `{` _body_ `}` _|_ `;` _]_\n\nArguments should be comma-separated and imitate\n[`var` syntax](https://github.com/carbon-language/carbon-lang/pull/339),\nalthough `var` itself is not used.\n\nFor example:\n\n```carbon\nfn Sum(Int a, Int b) -> Int {\n  <body>\n}\n\nfn UnusedArgument(Int _) -> Int {\n  <body>\n}\n```\n\nThe return type may optionally be omitted if `()`. For example, these two\nfunction declarations both return `()`:\n\n```carbon\nfn Print(String s) -> ();\nfn Print(String s);\n```\n\n### Forward declarations\n\nForward declarations will be supported in order to support separation of API and\nimplementation, as explained in\n[code and name organization](https://github.com/carbon-language/carbon-lang/tree/trunk/docs/design/code_and_name_organization).\nFor example:\n\n```carbon\npackage Math api;\n\nfn Sum(Int a, Int b) -> Int;\n```\n\nForward declarations will experimentally _only_ be allowed in `api` files, and\n_only_ when the definition is in the library's `impl` file. The intent is to\nminimize use, consistent with most other languages that have no forward\ndeclaration support at all.\n\n## Rationale based on Carbon's goals\n\nCarbon needs functions in order to be writable by developers. That functionality\nneeds a syntax.\n\nRelevant goals are:\n\n-   [3. Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n\n    -   Adding a keyword makes it easy for developers to visually identify\n        functions.\n    -   Trailing return syntax should be easier to understand than C++'s older\n        preceding return syntax. Only allowing one avoids requiring developers\n        to recognize and choose between equivalent syntaxes.\n\n-   [5. Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development):\n    The addition of a keyword should make parsing easy.\n\n-   [7. Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):\n    Keeping syntax close to C++ will make it easier for developers to\n    transition.\n\n## Open questions\n\n### Calling functions defined later in the same file\n\nC++ supports forward declaring functions in a `.cpp` file, and this may be\nuseful for handling interdependencies between functions. In Carbon, we should\ninstead aim to allow having a function able to call a function defined later in\nthe same file without requiring a forward declaration.\n\nAdvantages:\n\n-   Minimize accidents with forward declarations not matching implementation.\n-   Fewer forward declarations for developers to find while reading.\n\nDisadvantages:\n\n-   Shifts burden onto how code is parsed and executed.\n\nWe'll need to evaluate how this works. There is tracked by\n[#472](https://github.com/carbon-language/carbon-lang/issues/472). This does not\nneed to block this proposal, as we can allow it later if that's the decision; it\nmay also be helpful to give more time to consider how name lookup should work.\n\n### Optional argument names\n\nArgument names are required under this proposal. It's likely that developers\nwill want a way to indicate unused arguments. This is tracked by\n[#476](https://github.com/carbon-language/carbon-lang/issues/476).\n\n## Alternatives considered\n\n### Function keyword\n\nWe may have anchored on `fn` without much consideration. A key piece of this\nproposal is to suggest reconsidering the choice, even if we end up with the\nsame.\n\n#### Type\n\nAdvantages:\n\n-   Echoes C++, C#, and Java.\n-   Simpler to write; a type will often be present for the return regardless.\n\nDisadvantages:\n\n-   Makes function syntax more difficult to parse.\n    -   In C++, it's notable that functions with a trailing return still start\n        with `auto` to indicate a \"type\".\n\nThere's a consensus that _some_ keyword should be used in order to simplify\nparsing, so this option is not expected to receive much support.\n\n#### `-` (dash)\n\nAdvantages:\n\n-   Echoes Objective-C instance method syntax.\n    -   Class methods use `+` and we could echo that too.\n-   This is the most succinct option.\n\nDisadvantages:\n\n-   Easy to miss, and hard to read as a result.\n-   Might be ambiguous with the `-` operator.\n\nAlthough this alternative is mentioned, it is not expected to receive much\nsupport due to its readability problem.\n\n#### `def`\n\nAdvantages:\n\n-   Echoes Python and Ruby.\n\nDisadvantages:\n\n-   `def` is presumably short for \"define\", which may not be as obvious as a\n    \"function\" derivative.\n\n#### `fn`\n\nAdvantages:\n\n-   Echoes Rust.\n-   The shortest \"function\" derivative.\n    -   Likely comes from the [fn key](https://en.wikipedia.org/wiki/Fn_key).\n\nDisadvantages:\n\n-   Abbreviation by removing letters in the middle of a word is\n    [disallowed by Carbon's C++ style](https://google.github.io/styleguide/cppguide.html#General_Naming_Rules).\n    -   Even though the abbreviation is in Wikipedia, it is not associated with\n        [functions in programming](https://en.wikipedia.org/wiki/Subroutine).\n    -   Would likely be the only keyword abbreviated this way.\n\n#### `fun`\n\nAdvantages:\n\n-   Echoes Kotlin.\n-   Could be used with `var` as a push towards three letter abbreviations.\n    -   Not clear there are other examples of three letter abbreviations.\n    -   `let` may be used in a similar way, although it's not an abbreviation.\n\nDisadvantages:\n\n-   \"fun\" is a common English word and may be a mildly confusing choice as a\n    result.\n-   When wrapping function definitions, the function name and wrapped types\n    would end up on the same column when indenting by 4 spaces. These use the\n    same casing, so it may make it slower to understand code.\n\n    -   For example:\n\n        ```carbon\n        fun Print(\n            String message) {\n          ...\n        }\n        // Similar confusion if the body of the function is indented 4 spaces.\n        fun Print(String message) {\n            SomeFunctionCall();\n            ...\n        }\n        ```\n\n    -   This is also true for `var`, but wrapping arguments is expected to be\n        more common for functions, and the casing more likely to match.\n\n#### `func`\n\nAdvantages:\n\n-   Echoes Go and Swift.\n\nDisadvantages:\n\n-   The longest abbreviated form of \"function\".\n\n#### `function`\n\nAdvantages:\n\n-   Echoes JavaScript, MatLab, PHP, R, and TypeScript.\n-   Clear meaning without any abbreviation.\n\nDisadvantages:\n\n-   The longest \"function\" derivative.\n\n### Conclusion\n\n`fn` and `func` are the favored options:\n\n-   Desire to abbreviate \"function\":\n    -   `fn` is clearly shorter than `func`. Both are shorter than \"function\".\n-   Consistency with other abbreviations:\n    -   We are using abbreviations like `var`, and something like `mut` or\n        `const` seems likely. `ptr` is possible.\n        -   `func` is consistent with abbreviation by removing letters at the\n            end.\n        -   `fn` is more consistent with abbreviations like `ptr` that remove\n            letters in the middle, but a three letter abbreviation like `fcn`\n            would be more consistent.\n    -   We are using\n        [Google C++ style](https://google.github.io/styleguide/cppguide.html#General_Naming_Rules)\n        as a base, which explicitly discourages abbreviating by deleting letters\n        within a word.\n        -   `fn` deletes letters in the middle of \"function\", `func` does not.\n-   Familiarity for developers:\n    -   `func` is used by Go and Swift, both of which are common languages.\n        -   [`func`](https://www.google.com/search?q=func) is very searchable.\n    -   `fn` is only used by Rust, which by most measures has less adoption than\n        either Go or Swift at present. However, it is used in\n        [Hungarian notation](https://docs.microsoft.com/en-us/windows/win32/stg/coding-style-conventions),\n        so some C++ developers will be familiar with `fn` for function pointers.\n        -   It's also used for the\n            [Fn key](https://en.wikipedia.org/wiki/Fn_key), although assumptions\n            about the meaning of \"Fn\" as abbreviation for \"function\" versus\n            \"F-number key\" (as in F5) may mislead some developers.\n        -   [`fn`](https://www.google.com/search?q=fn) is difficult to search\n            for.\n-   Pronunciation:\n    -   Both may be pronounced as \"function\", but may also be pronounced by\n        their abbreviation.\n    -   `func` could be as \"funk\", defined as a music genre or state of\n        depression.\n    -   `fn` could be as:\n        -   \"eff en\", which has no direct meaning but could be misheard as\n            \"effing\", or profanity. However, it's not clear that this potential\n            mishearing is a pragmatic issue.\n        -   \"fun\", defined as enjoyment.\n\nNote that both are argued here as reasonable solutions that would satisfy many.\nThis was asked on\n[#463](https://github.com/carbon-language/carbon-lang/issues/463). We are using\n`fn`.\n"
  },
  {
    "path": "proposals/p0444.md",
    "content": "# GitHub Discussions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/444)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Keep using Discourse Forums](#keep-using-discourse-forums)\n    -   [Try to maintain history](#try-to-maintain-history)\n        -   [Caveats](#caveats)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n\n<!-- tocstop -->\n\n## Problem\n\nRight now we run our own Discourse Forums (broken link:\n`https://forums.carbon-lang.dev/`).\n[GitHub Discussions](https://docs.github.com/en/discussions) was recently\nreleased, and should be evaluated for appropriateness as a replacement.\n\n## Background\n\n[GitHub Discussions](https://docs.github.com/en/discussions) is a new forum\nsolution offered by GitHub. Although it was initially only for public\nrepositories, as of March, it is\n[available to private repositories](https://github.blog/2021-03-09-github-discussions-now-available-for-private-repositories/).\n\nDevelopers can\n[preview in carbon-lang](https://github.com/carbon-language/carbon-lang/discussions).\n\nDiscourse Forums (broken link: `https://forums.carbon-lang.dev/`) are currently\nused by Carbon. These run on a Google Cloud instance owned by Carbon team.\n\n## Proposal\n\nWe should shut down the Discourse Forums and adapt GitHub Discussions to our\nneeds. GitHub Discussions categories and documentation should be updated\naccordingly, alongside evolution process changes.\n\nDiscourse Forums should be frozen and eventually shut down once we are confident\nin the switch. History can manually copied from the frozen instance as needed,\nand discarded otherwise.\n\n## Alternatives considered\n\n### Keep using Discourse Forums\n\nAdvantages:\n\n-   Discourse's UI is better in some places:\n    -   Easy drag-and-click UI for quoting.\n    -   Easy to navigate to the original post of a quote.\n    -   Less noisy notifications because it's separate from other discussion,\n        such as issues and PRs.\n        -   However, notifications will all be in one place.\n    -   Preview is visible while writing, whereas GitHub uses a tab.\n    -   More advanced search support.\n-   Discourse Forums has categories and subcategories.\n    -   GitHub Discussions only has categories.\n-   Discourse Forums has controllable settings for many things.\n    -   GitHub Discussions offers fewer options, although simplicity is\n        sometimes better.\n-   Keeps existing history.\n-   [Swift](https://forums.swift.org/) and [Rust](https://users.rust-lang.org/)\n    are prominent examples also using Discourse.\n-   Avoids handing more control to GitHub.\n\nDisadvantages:\n\n-   GitHub's UI is better in some places:\n    -   Responses to responses are threaded in-place, which may be appreciated\n        by some.\n    -   Links to issues and PRs will work more seamlessly, with tooltips.\n    -   Discourse Forums has nuisance warnings about similar posts and @-ing to\n        many people in a group, which cannot be disabled. These get in the way\n        of frequent posters.\n    -   When copying links, Discourse Forums' URL updates made it easy to\n        accidentally link to a specific post; GitHub makes that require a\n        deliberate action.\n    -   There is direct support for filing issues based on discussions.\n    -   Supports voting on posts and sorting by vote, for more types of\n        discussions, particularly Q&A.\n-   Discourse Forums is a now unnecessary split in communication mechanisms.\n    -   GitHub is the only possible direction of consolidation: we already use\n        GitHub for issues and PR discussion, and moving that to Discourse is\n        infeasible.\n-   Running Discourse Forums ourselves requires significant maintenance, and\n    [still has configuration issues](https://github.com/carbon-language/carbon-lang/issues/356).\n\n### Try to maintain history\n\nWe've deliberately not put much into Discourse Forums, and GitHub issues are\nalready a focus of discussion. There's not enough history to justify significant\ninvestment into making a copy.\n\n#### Caveats\n\nThe contributor wiki (broken link:\n`https://forums.carbon-lang.dev/t/contributor-directory-wiki/134/2`) can be\nmoved to [GitHub's wiki](https://github.com/carbon-language/carbon-lang/wiki).\n\n## Rationale based on Carbon's goals\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture):\n\n    -   GitHub Discussions offers a way to consolidate tools and make community\n        forums easier to find.\n"
  },
  {
    "path": "proposals/p0447.md",
    "content": "# Generics terminology\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/447)\n\n## Problem\n\nTo talk about generics as a programming language feature, you need a lot of\nspecialized terminology. We need to agree on the words we are using and their\nmeaning before we can meaningfully talk about the design of the feature itself.\n\nThere a number of problems a glossary solves:\n\n-   Not everyone knows every term, so having a single place to look them up will\n    improve the ease of understanding, ease of contributing, and accessibility\n    of the project.\n-   There may not be widespread agreement on the meaning of some terms. In\n    particular, individual programming languages tend to assign very specific\n    meanings to terms used within their ecosystem.\n-   Some terms may be used in multiple ways, but we only use the term with one\n    specific meaning.\n-   Some terms are our invention and we need to introduce them.\n\n## Proposal\n\nSee the [generics terminology document](../docs/design/generics/terminology.md).\n\n## Rationale\n\nThis gives a common vocabulary for discussing the design of the generics\nfeature.\n"
  },
  {
    "path": "proposals/p0524.md",
    "content": "# Generics overview\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/524)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Problem\n\nWe want to Carbon to have a high quality generics feature that achieves the\ngoals set out in [#24](https://github.com/carbon-language/carbon-lang/pull/24).\nThis is too big a feature to land in a single proposal. This proposal specifies\nthe feature at the level of an overview description. This overview document is\nintended to act as a starting point for people interested in the generics\nfeature by providing:\n\n-   a high-level description of the generics feature, and\n-   pointers to documents that go deeper into individual topics.\n\n## Background\n\nThis is a follow on to these previous generics proposals:\n\n-   [Generics goals #24](https://github.com/carbon-language/carbon-lang/pull/24)\n-   [Generics terminology #447](https://github.com/carbon-language/carbon-lang/pull/447)\n\nThe content for this proposal was extracted from a larger\n[Generics combined draft proposal](https://github.com/carbon-language/carbon-lang/pull/36).\n\n## Proposal\n\nThis is a proposal to add\n[this overview document](/docs/design/generics/overview.md).\n\n## Rationale based on Carbon's goals\n\nMuch of this rationale was captured in the\n[Generics goals proposal](https://github.com/carbon-language/carbon-lang/pull/24).\n\n## Alternatives considered\n\nAlternatives considered will be in a future proposal. Some of them can be seen\nin a rough form in\n[#36](https://github.com/carbon-language/carbon-lang/pull/36).\n"
  },
  {
    "path": "proposals/p0538.md",
    "content": "# `return` with no argument\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/538)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n    -   [Use cases](#use-cases)\n    -   [What's wrong with the C++ rule?](#whats-wrong-with-the-c-rule)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Relation to upcoming proposals](#relation-to-upcoming-proposals)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Retain the C++ rule](#retain-the-c-rule)\n    -   [Fully divorce functions and procedures](#fully-divorce-functions-and-procedures)\n\n<!-- tocstop -->\n\n## Problem\n\n### Use cases\n\nWe wish to support the following use cases:\n\n-   Functions that return values. This should be supported for any type for\n    which a value can be formed, and such support should be uniform and\n    independent of whether the return type is `()`. A return value must always\n    be produced.\n-   Functions that do not return a value (\"procedures\"). In such functions, we\n    do not need or want to be able to return a value. No return value is needed,\n    so if control flow reaches the end of a procedure, it should return to its\n    caller.\n-   Functions with parameterized return types, that may be either of the above,\n    depending on the parameterization. For example, a call wrapper might be\n    parameterized by the type of its callee, and might return the same type that\n    its callee returns, or a type computed based on that type.\n\n### What's wrong with the C++ rule?\n\nC++ treats `void` as a special case in a number of ways. We want to minimize the\nimpact of this special-case treatment for the corresponding Carbon types. One\nway that this special treatment is visible in C++ is that functions with the\nreturn type `void` obey different rules: the operand of `return` becomes\noptional (but is still permitted), and reaching the end of the function becomes\nequivalent to `return;`. In a function template, this can even happen invisibly,\nwith some instantiations having an implicit `return;` and others not.\n\nThis interferes with the ability to reason about programs. Consider:\n\n```\ntemplate<typename T> auto f() {\n  if (T::cond())\n    return T::run();\n}\n```\n\nHere, it is possible for control flow to reach the end of the function. However,\na compiler can't warn on this without false positives, because it's possible\nthat `T::run()` has type `void`, in which case this function has an implicit\n`return;` added before its `}`, and indeed, it might be the case that `T::run()`\nalways has return type `void` for any `T` where `T::cond()` returns `false`.\n\n## Background\n\nSee the following issues:\n\n-   [Proposal: function declaration syntax](https://github.com/carbon-language/carbon-lang/pull/438)\n-   [Proposal: `return` statements](https://github.com/carbon-language/carbon-lang/pull/415)\n-   [Leads question: what is the relationship between `Void` and `()`?](https://github.com/carbon-language/carbon-lang/issues/443)\n-   [Leads question: should we allow `return;` in functions with a `Void` return type?](https://github.com/carbon-language/carbon-lang/issues/518)\n\n## Proposal\n\nInstead of applying special-case rules based on whether the return type of a\nfunction is `()`, we apply special-case rules based on whether a return type is\nprovided.\n\n## Details\n\nA function with no declared return type is a _procedure_. The return type of a\nprocedure is implicitly `()`, and a procedure always returns the value `()` if\nand when it returns. Inside a procedure, `return` must have no argument, and if\ncontrol flow reaches the end of a procedure, the behavior is as if `return;` is\nexecuted.\n\n```\n// F is a procedure.\nfn F() {\n  if (cond) {\n    return;\n  }\n  if (cond2) {\n    // Error: cannot return a value from a procedure.\n    return F();\n  }\n\n  // Implicitly `return;` here.\n}\n```\n\nA function with a declared return type is treated uniformly regardless of\nwhether that return type happens to be `()`. Every `return` statement must\nreturn a value. There is no implicit `return` at the end of the function, and\ninstead a compile error is produced if control flow can reach the end of the\nfunction, even if the return type is `()` -- or any other unit type.\n\n```\nfn G() -> () {\n  if (cond) {\n    // OK, F() returns ().\n    return F();\n  }\n  if (cond2) {\n    // Error: return without value in value-returning function.\n    return;\n  }\n\n  // Error: control flow can reach end of value-returning function.\n}\n```\n\nFrom the caller's perspective, there is no difference between a function\ndeclared as\n\n```\nfn DoTheThing() -> ();\n```\n\nand a function declared as\n\n```\nfn DoTheThing();\n```\n\nAs a result, the choice to include or omit the `-> ()` in the definition is an\nimplementation detail, and the syntax used in a forward declaration is not\nrequired to match that used in a definition. The use of `-> ()` in idiomatic\nCarbon code is expected to be rare, but it is permitted for uniformity, and in\ncase there is a reason to desire the value-returning-function rules or to\nemphasize to the reader that `()` is the return type or similar.\n\n### Relation to upcoming proposals\n\nIssue [#510](https://github.com/carbon-language/carbon-lang/issues/510) asks\nwhether we should support named return variables:\n\n```\nfn F() -> var ReturnType: x {\n  // initialize x\n  return;\n}\n```\n\nIf we do, functions using that syntax should follow the rules for procedures in\nthis proposal, including the implicit `return;` if control reaches the end of\nthe function. In particular,\n\n```\nfn F() { ... }\n```\n\nwould be exactly equivalent to\n\n```\nfn F() -> var (): _ = () { ... }\n```\n\n## Rationale based on Carbon's goals\n\n-   **Software and language evolution**\n    -   This proposal may decrease the number of places in which the return type\n        of a procedure is used, by discouraging the use of\n        `return Procedure();`. This in turn may make it easier to change a\n        return type from `()` to something else, but this proposal by itself is\n        insufficient to ensure that is always possible.\n-   **Code that is easy to read, understand, and write**\n    -   The conceptual integrity of the Carbon language is improved by making\n        the same syntax result in the same semantics, regardless of whether a\n        type happens to be `()` or not, and symmetrically by using different\n        syntax for different semantics.\n    -   The readability of Carbon code is improved and a source of surprise is\n        eliminated by removing the possibility of `return F();` being mixed with\n        `return;` in the same function.\n-   **Practical safety guarantees and testing mechanisms**\n    -   By making the presence or absence of an implicit `return` in a function\n        be determined based on syntax alone, we permit checks for missing\n        `return` statements to be provided in the definition of a template or\n        generic, without needing to know the arguments. This is important for\n        generics in particular, because we do not want monomorphization to be\n        able to fail and because we do not in general guarantee that\n        monomorphization will be performed.\n-   **Fast and scalable development**\n    -   The correct syntax for a `return` statement can be detected while\n        parsing, using only syntactic information rather than contextual,\n        semantic information. In practice, we will likely parse both kinds of\n        `return` statement in all functions and check the return type from a\n        context that has the semantic information, but the ability to do these\n        checks syntactically may be useful for simple tools and editor\n        integration.\n-   **Interoperability with and migration from existing C++ code**\n    -   This proposal rejects some constructs that would be valid in C++:\n        ```\n        return F();\n        ```\n        in a function with `void` return type would no longer be valid in a\n        corresponding Carbon function with no specified return type, and would\n        need to be translated into\n        ```\n        F();\n        return;\n        ```\n        (possibly with braces added). However, the fact that this construct is\n        valid in C++ is surprising to many, and the constructs that would be\n        idiomatic in C++ are still valid under these rules.\n\n## Alternatives considered\n\n### Retain the C++ rule\n\nThe advantages of this approach compared to maintaining the C++ rule are\ndiscussed above. The advantage of maintaining the C++ rule would be that Carbon\nis more closely aligned with C++. However, the removed functionality --\nspecifically, the ability to return an expression of type `void` from a `void`\nreturning function -- is still available, albeit with a more verbose syntax, and\nthe existence of that functionality in C++ is a source of surprise to C++\nprogrammers.\n\n### Fully divorce functions and procedures\n\nWe could treat the choice of function with `()` return type versus procedure as\nbeing part of the interface rather than being an implementation detail.\n\n```\n// F is a procedure.\nfn F();\n// F is a function returning ().\nfn G() -> ();\n\n// ...\n\n// Error, procedure redeclared as a function.\nfn F() -> () {\n  return ();\n}\n\n// Error, function redeclared as a procedure.\nfn G() {\n}\n```\n\nThen, we could disallow any use of a procedure call in a context that depends on\nits return value, treating a procedure call as a statement rather than as an\nexpression that can be used as a subexpression or an operand of an operator.\n\n```\nfn Func() -> ();\nfn Proc();\n// OK, x is of type ().\nauto x = Func();\n// Error, Proc is a procedure.\nauto y = Proc();\n```\n\nAdvantages:\n\n-   Removes all special treatment of `()` in this context. Procedures no longer\n    need to say that their return type is implicitly `()` nor that they\n    implicitly return `()`.\n-   Adding a return type to a procedure -- converting it to a function -- would\n    be a non-breaking change.\n    -   But we don't have evidence that this is a common problem.\n-   Prevents a source of programming error where a returned `()` value is stored\n    and used.\n    -   But it's not clear that this would be a frequent error, and it would\n        likely be caught in other ways due to the limited API of `()`.\n\nDisadvantages:\n\n-   Having distinct notions of function versus procedure would be a surprise for\n    those coming from C++.\n-   Supporting `auto x = F();` regardless of whether `F` is a function or\n    procedure may be important for generic code.\n-   When migrating C++ code to Carbon, this makes the choice of function versus\n    procedure load-bearing, as there may be uses that depend on a return value\n    existing, for example in templates.\n"
  },
  {
    "path": "proposals/p0540.md",
    "content": "# Remove `Void`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/540)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Problem\n\nThe `Void` type as\n[currently specified](https://github.com/carbon-language/carbon-lang/blob/4bf396b8f6e7f5289c170c5ad9dda64c5c680d4a/docs/design/README.md#primitive-types)\nis redundant with `()`, the type of a tuple with no elements.\n\n## Background\n\n[Issue 443](https://github.com/carbon-language/carbon-lang/issues/443) contains\nfurther discussion of the problem, and possible solutions. The consensus of the\nCarbon leads was that `Void` should be removed.\n\n## Proposal\n\nRemove `Void` from the Carbon design.\n\n## Rationale based on Carbon's goals\n\nEliminating `Void` will make Carbon code\n[easier to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nThe main advantage of `Void` is that it is recognizable and familiar to C++\nprogrammers. However, we haven't yet found any use cases where using `Void`\nresults in clearer code, even to programmers transitioning from C++. In\nparticular, omitting a function's return type is more concise and at least as\nclear as explicitly specifying `-> Void`. In most other use cases, the\nappearance of familiarity is more likely to mislead than to clarify: most other\nuse cases for C++ `void`, such as using `void*` to mean \"pointer to anything\",\nwill not work with Carbon's `Void`, and most other use cases for Carbon's\n`Void`, such as using it as the type of a variable, would not work with C++'s\n`void`,\n\n## Alternatives considered\n\n-   Define `Void` as an alias for `()`. This is workable, but forces users to\n    understand both spellings, and make a style choice between them.\n-   Define `Void` as a distinct type from `()` with the same semantics. This\n    forces users to know \"which kind of nothing\" to use in any given context\n-   Define `Void` as a distinct type from `()`, with more C++-like semantics.\n    This would reproduce the problems of C++'s `void`, for no clear benefit.\n-   Eliminate `()`. This would needlessly complicate programming with tuples,\n    especially in variadic settings.\n\nSee [issue 443](https://github.com/carbon-language/carbon-lang/issues/443) for\ndetails.\n"
  },
  {
    "path": "proposals/p0553.md",
    "content": "# Generics details part 1\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/553)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Interface implementation syntax](#interface-implementation-syntax)\n        -   [`for` instead of `as` in external `impl`](#for-instead-of-as-in-external-impl)\n        -   [No `as` for inline `impl`](#no-as-for-inline-impl)\n        -   [No `external` for external `impl`](#no-external-for-external-impl)\n        -   [Out-of-line impl](#out-of-line-impl)\n        -   [`extend` blocks](#extend-blocks)\n    -   [Others](#others)\n\n<!-- tocstop -->\n\n## Problem\n\nWe want to Carbon to have a high quality generics feature that achieves the\ngoals set out in [#24](https://github.com/carbon-language/carbon-lang/pull/24).\nThis is too big to land in a single proposal. This proposal goes into the\ndetails of the core of the feature, and provides an outline covering future\nwork. It covers:\n\n-   interfaces\n-   implementing interfaces for types\n-   resolving name conflicts\n-   facet types\n-   type-types as the way of describing type variables\n-   structural interfaces\n-   combining interfaces\n-   interface requirements and extension\n-   type compatibility\n\n## Background\n\nThis is a follow on to these previous generics proposals:\n\n-   [Generics goals #24](https://github.com/carbon-language/carbon-lang/pull/24)\n-   [Generics terminology #447](https://github.com/carbon-language/carbon-lang/pull/447)\n-   [Generics overview #524](https://github.com/carbon-language/carbon-lang/pull/524)\n\nThe content for this proposal was extracted from a larger\n[Generics combined draft proposal](https://github.com/carbon-language/carbon-lang/pull/36).\n\n## Proposal\n\nThis is a proposal to add\n[this detailed design document](/docs/design/generics/details.md).\n\n## Rationale based on Carbon's goals\n\nMuch of this rationale was captured in the\n[Generics goals proposal](https://github.com/carbon-language/carbon-lang/pull/24).\n\n## Alternatives considered\n\n### Interface implementation syntax\n\nThe interface implementation syntax was decided in\n[question-for-leads issue #575](https://github.com/carbon-language/carbon-lang/issues/575).\n\n```\nstruct Song {\n  // data and methods ...\n  impl as Printable {\n    method (me: Self) Print() { ... }\n  }\n}\nexternal impl Song as Comparable { ... }\n```\n\nThis proposal includes additional discussion and additional alternatives.\n\n#### `for` instead of `as` in external `impl`\n\nIn this option, the interface name comes before the type name.\n\n```\nstruct Song { ... }\nexternal impl Comparable for Song { ... }\n```\n\nAdvantage:\n\n-   This ordering used by Rust.\n\nDisadvantages:\n\n-   We prefer the type name before the interface name (using `as`), since having\n    the type first and outer is consistent with those implemented in `struct`\n    declarations. It also seems more natural to express the parameters to the\n    interface in terms of the parameters and associated items of the type than\n    the other way around.\n-   The `Song as Comparable` phrase is the name of the facet type that is being\n    implemented.\n\n#### No `as` for inline `impl`\n\n```\nstruct Song {\n  // data and methods ...\n  impl Printable {\n    method (me: Self) Print() { ... }\n  }\n}\n```\n\nAdvantage:\n\n-   More concise, so less to read and write.\n\nDisadvantage:\n\n-   Less consistent with the `external impl` syntax.\n-   Less consistent with the planned inline conditional impl syntax.\n\n#### No `external` for external `impl`\n\n```\nstruct Song { ... }\nimpl Song as Comparable { ... }\n```\n\nAdvantage:\n\n-   More concise, so less to read and write.\n\nDisadvantages:\n\n-   Less explicit that the methods of this impl definition are not contributing\n    to unqualified API of the type.\n-   This kind of implementation is naturally referred to as \"external\",\n    especially when contrasting with \"inline impl\".\n\n#### Out-of-line impl\n\nWe considered an out-of-line syntax for declaring and defining interface `impl`\nblocks, to be consistent with the `external impl` declarations. For example:\n\n```\nstruct Song { ... }\nimpl Printable for Song { ... }\nexternal impl Comparable for Song { ... }\n```\n\nThe main advantage of this syntax was that it was uniform across many cases,\nincluding\n[conditional conformance](/docs/design/generics/details.md#conditional-conformance).\nIt wasn't ideal across a number of dimensions though.\n\n-   It repeated the type name which was redundant and verbose\n-   It could affect the API of the type outside of the type definition.\n\n#### `extend` blocks\n\nInstead of the `external impl` statement, we considered putting all external\nimplementations in an `expand` block.\n\n```\nstruct Song {\n  impl Printable { ... }\n}\nexpand Song {\n  impl Comparable { ... }\n}\n```\n\nAdvantages:\n\n-   This option is most similar to the\n    [approach used by Swift](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID277).\n-   Easier to copy-paste an `impl` between a `struct` definition and an `expand`\n    block.\n\nThe `expand` approach had some disadvantages:\n\n-   Implementations were indented more than the `external impl` approach.\n-   Extra ceremony in the case of only implementing one type for an interface.\n    This case is expected to be common since external implementations will most\n    often be defined with the interface.\n-   When implementing multiple interfaces in a single `expand` block, the name\n    of the type being expanded could be far from the `impl` declaration and hard\n    to find.\n\nWe originally used `extend` instead of `expand` but that collided with using\n`extends` for interface extension and derived classes.\n\n### Others\n\nOther alternatives considered will be in a future proposal. Some of them can be\nseen in a rough form in\n[#36](https://github.com/carbon-language/carbon-lang/pull/36).\n"
  },
  {
    "path": "proposals/p0555/figures.py",
    "content": "#! /usr/bin/env python\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nfmt = \"svg\"\n\n\ndef escape(s):\n    return (\n        s.replace(\"&\", \"&amp;\")\n        .replace(\"<\", \"&lt;\")\n        .replace(\">\", \"&gt;\")\n        .replace(\"[\", \"&#91;\")\n        .replace(\"]\", \"&#93;\")\n    )\n\n\ndef tablejoin(items, separator):\n    data = (\"<td>%s</td>\" % separator).join(\n        \"<td>%s</td>\" % item for item in items\n    )\n    return '<table border=\"0\"><tr>%s</tr></table>' % data\n\n\ndef code(s):\n    # FIXME: GraphViz's handling of font metrics appears to be pretty broken.\n    # Add a little extra width to each character with a non-code-font space to\n    # compensate.\n    codefont = \"\".join(\n        (\n            '<font face=\"SFMono-Regular,Consolasl,Liberation Mono,'\n            + 'Menlo,monospace\" point-size=\"10.2\">%s</font> '\n        )\n        % escape(part)\n        for part in s\n    )\n    return (\n        '<table border=\"0\" bgcolor=\"#f2f3f3\"><tr><td>%s</td></tr></table>'\n        % codefont\n    )\n\n\ndef math(s):\n    # Render math in italics but otherwise unchanged.\n    return \"<i>%s</i>\" % s\n\n\ndef raw(s):\n    return s\n\n\nLtR = ' shape=\"rarrow\"'\nRtL = ' shape=\"larrow\"'\nNonAssoc = \"\"\n\nout = None\nnum = 0\n\n\ndef group(ops, assoc=NonAssoc, style=code):\n    global num\n    num = num + 1\n    name = \"op%d\" % num\n    print(\n        \"  %s [label=<%s>%s]\"\n        % (\n            name,\n            tablejoin((style(op) for op in ops), \", \"),\n            assoc,\n        ),\n        file=out,\n    )\n    return name\n\n\ndef edge(a, b):\n    print(\"  %s -> %s\" % (a, b), file=out)\n\n\ndef combine(name, items):\n    if len(items) <= 1:\n        return items\n    print(\"  %s [label=<<i>%s</i>> shape=ellipse]\" % (name, name), file=out)\n    res = name\n    for i in items:\n        edge(i, name)\n    return [res]\n\n\ndef graph(f):\n    import subprocess\n\n    outfile = open(f.__name__ + \".\" + fmt, \"w\")\n    process = subprocess.Popen(\n        [\"dot\", \"-T\" + fmt],\n        stdin=subprocess.PIPE,\n        stdout=outfile,\n        encoding=\"utf8\",\n        # [\"cat\"], stdin=subprocess.PIPE, stdout=outfile, encoding='utf8'\n    )\n    global out\n    out = process.stdin\n    # print >>out, '  node [shape=\"rectangle\" style=\"rounded\" fontname=\"Arial\"]'\n    print(\n        \"\"\"\ndigraph {\n  layout = dot\n  rankdir = TB\n  rank = \"min\"\n  node [shape=\"none\" fontsize=\"12\" height=\"0\"\n        fontname=\"BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif\"]\n  edge [dir=\"none\"]\n  \"\"\".strip(),\n        file=out,\n    )\n    f()\n    print(\"}\", file=out)\n    process.communicate()\n    return f\n\n\n@graph\ndef example():\n    term = group([\"(...)\"], NonAssoc)\n    mul = group([\"a * b\"], LtR)\n    add = group([\"a + b\"], LtR)\n    shl = group([\"a << b\"], NonAssoc)\n    compare = group([\"a == b\"], NonAssoc)\n\n    edge(term, mul)\n    edge(mul, add)\n    edge(term, shl)\n    edge(add, compare)\n    edge(shl, compare)\n"
  },
  {
    "path": "proposals/p0555/yacc-parser/Makefile",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nexample: example.l example.y\n\tflex example.l\n\tbison example.y --defines\n\tclang example.tab.c lex.yy.c -o example\n\nclean:\n\trm -f example.tab.c example.tab.h lex.yy.c example\n"
  },
  {
    "path": "proposals/p0555/yacc-parser/example.l",
    "content": "/*\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n*/\n\n%option noyywrap\n%{\n#include <stdio.h>\n#define YY_DECL int yylex()\n#include \"example.tab.h\"\n%}\n\n%%\n\n[0-9]+ { yylval = atoi(yytext); return INT; }\n\"*\" { return '*'; }\n\"+\" { return '+'; }\n\"<<\" { return LSH; }\n\"==\" { return EQEQ; }\n\"(\" { return '('; }\n\")\" { return ')'; }\n\";\" { return ';'; }\n\n%%\n"
  },
  {
    "path": "proposals/p0555/yacc-parser/example.y",
    "content": "/*\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n*/\n\n%{\n#include <stdio.h>\n\nextern int yylex();\nextern int yyparse();\nextern FILE* yyin;\n\nvoid yyerror(const char *s) { fprintf(stderr, \"%s\\n\", s); }\nint main() { while (yyparse()) {} }\n%}\n\n%define api.value.type {int}\n%token INT LSH EQEQ\n\n%%\n\ninterpreter:\n  %empty\n| interpreter expression ';' { printf(\"%d\\n\", $2); }\n\nexpression: compare_expression | compare_operand;\n\ncompare_expression: compare_lhs EQEQ compare_operand { $$ = ($1 == $3); };\ncompare_lhs: compare_expression | compare_operand;\ncompare_operand: add_expression | multiply_expression | shift_expression | primary_expression;\n\nadd_expression: add_lhs '+' add_operand { $$ = ($1 + $3); };\nadd_lhs: add_expression | add_operand;\nadd_operand: multiply_expression | multiply_operand;\n\nmultiply_expression: multiply_lhs '*' multiply_operand { $$ = ($1 * $3); };\nmultiply_lhs: multiply_expression | multiply_operand;\nmultiply_operand: primary_expression;\n\nshift_expression: shift_lhs LSH shift_operand { $$ = ($1 << $3); };\nshift_lhs: shift_expression | shift_operand;\nshift_operand: primary_expression;\n\nprimary_expression: INT | '(' expression ')' { $$ = $2; };\n\n%%\n"
  },
  {
    "path": "proposals/p0555.md",
    "content": "# Operator precedence\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/555)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Notational convention](#notational-convention)\n    -   [When to add precedence edges](#when-to-add-precedence-edges)\n    -   [Parsing with a partial precedence order](#parsing-with-a-partial-precedence-order)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Total order](#total-order)\n    -   [Different precedence for different operands](#different-precedence-for-different-operands)\n    -   [Require less than a partial order](#require-less-than-a-partial-order)\n\n<!-- tocstop -->\n\n## Problem\n\nMost expression-oriented languages use a strict hierarchy of precedence levels.\nThat approach is error-prone, as it assigns meaning to programs that developers\nmay either not understand or may misunderstand.\n\n## Background\n\nGiven an expression, we need to be able to infer its structure: what are the\noperands of each of the operators? This may be ambiguous in the absence of rules\nthat determine which operator is preferred, such as in the expression\n`a $ b ^ c`: is this `(a $ b) ^ c` or `a $ (b ^ c)`?\n\nStarting with a sequence of operators and non-operator terms, we can completely\ndetermine the structure of an expression by determining which operator in our\nsequence will be the root of the parse tree, splitting the expression at that\npoint, and recursively determining the structure of each subexpression. The\noperator that forms the root of the parse tree is said to have the lowest\nprecedence in the expression.\n\nTraditionally, this is accomplished by assigning a precedence level to each\noperator and devising a total ordering over precedence levels. For example, we\ncould assign a higher precedence level to an infix `*` operator than an infix\n`+` operator. With that choice of precedence levels, an infix `*` operator would\nbind tighter than an infix `+` operator, regardless of the order in which they\nappear.\n\nThis approach is well-understood, but is problematic. For example, in C++,\nexpressions such as `a & b << c * 3` are valid, but the meaning of such an\nexpression is unlikely to be readily apparent to many developers. Worse, for\ncases such as `a & 3 == 3`, there is a clear intended meaning, namely\n`(a & 3) == 3`, but the actual meaning is something else -- in this case,\n`a & (3 == 3)`.\n\nBecause the precedence rules are not widely known and are sometimes quite\nsurprising, parentheses are used as a matter of course for certain kinds of C++\nexpressions. However, the absence of such parentheses is not diagnosed in all\ncases, even by many linting tools, and forgetting those parentheses can lead to\nsubtle bugs.\n\n## Proposal\n\nDo not have a total ordering of precedence levels. Instead, define a partial\nordering of precedence levels. Expressions using operators that lack relative\norderings must be disambiguated by the developer, for example by adding\nparentheses; when a program's meaning depends on an undefined relative ordering\nof two operators, it will be rejected due to ambiguity.\n\nThe default behavior for any new operator is for it to be unordered with respect\nto all other operators, thereby requiring parentheses when combining that\noperator with any other operator. Precedence rules should be added only if it is\nreasonable to expect most or all developers who regularly use Carbon to reliably\nremember the precedence rule.\n\n## Details\n\n### Notational convention\n\nFor pedagogical purposes, our documentation will use\n[Hasse diagrams](https://en.wikipedia.org/wiki/Hasse_diagram) to represent\noperator precedence partial orders, where operators with lower precedence are\nconsidered less than (and therefore depicted lower than and connected to)\noperators with higher precedence. In our diagrams, an enclosing arrow will be\nused to show associativity within precedence groups, if there is any, with a\nleft-to-right arrow meaning a left-associative operator.\n\nFor example:\n\n<div align=\"center\">\n<img src=\"p0555/example.svg\" alt=\"Example operator precedence diagram\">\n</div>\n\n... would depict a higher-precedence `*` operator and a lower-precedence `+`\noperator, both of which are left-associative, and a non-associative `<<`\noperator. The `==` operator is lower precedence than all of those operators, and\nparentheses are higher precedence than all of those operators.\n\nWith those precedence rules:\n\n-   `a + b * c` would be parsed as `a + (b * c)`, because `+` has lower\n    precedence than `*`.\n-   `a + b << c` would be an error, requiring parentheses, because the\n    precedence levels of `+` and `<<` are unordered.\n\nA [python script](p0555/figures.py) to generate these diagrams is included with\nthis proposal.\n\n### When to add precedence edges\n\nGiven a program whose meaning is ambiguous to a reader, it is preferable to\nreject the program rather than to arbitrarily pick a meaning. For Carbon's\noperators, we should only add an ordering between two operators if there is a\nlogical reason for that ordering, not merely to provide _some_ answer. **Goal:\nfor every combination of operators, either it should be reasonable to expect\nmost or all developers who regularly use Carbon to reliably remember the\nprecedence, or there should not be a precedence rule.**\n\nAs an example, consider the expression `a * b ^ c`, where `*` is assumed to be a\nmultiplication operator and `^` is assumed to be a bitwise XOR operation. We\nshould reject this expression because there is no logical reason to perform\neither operator first and it would be unreasonable to expect Carbon developers\nto remember an arbitrary tie-breaker between the two options.\n\nThis still leaves open the question of how high a bar of knowledge we put on our\ndevelopers (what is reasonable for us to expect?). We can use experience from\nC++ to direct this decision: just as many developers who regularly use C++ do\nnot remember the relative precedence of `&&` vs `||`, and `&` vs `|`, and `&` vs\n`<<`, and so on, we shouldn't expect them to remember similar precedence rules\nin Carbon. If we are in doubt, omitting a precedence rule and waiting for\nreal-world experience should be preferred.\n\n### Parsing with a partial precedence order\n\nA traditional, totally-ordered precedence scheme can be implemented by an\n[operator precedence parser](https://en.wikipedia.org/wiki/Operator-precedence_parser):\n\n-   Keep track of the current left-hand-side operand and an ambient precedence\n    level. The ambient precedence level is the precedence of the operator whose\n    operand is being parsed, or a placeholder \"lowest\" precedence level when\n    parsing an expression that is not the operand of an operator.\n-   When a new operator is encountered, its precedence is compared to the\n    ambient precedence level:\n    -   If its precedence is higher than the ambient precedence level, then\n        recurse (\"shift\") with that as the new ambient precedence level to form\n        the right-hand side of the new operator. After forming the right-hand\n        side, build an operator expression from the current left-hand side\n        operand and the right-hand side operand; that is the new current\n        left-hand side.\n    -   If its precedence is equal to the ambient precedence level, then use the\n        associativity of that precedence level to determine what to do:\n        -   If the operator is left-associative, build an operator expression.\n        -   If the operator is right-associative, recurse.\n        -   If the operator is non-associative, produce an error.\n    -   If its precedence is lower than the ambient precedence level, return the\n        expression formed so far; it's the complete operand to an earlier\n        operator.\n\nThis is, for example, the strategy\n[currently used in Clang](https://github.com/llvm/llvm-project/blob/5f0903e9bec97e67bf34d887bcbe9d05790de934/clang/lib/Parse/ParseExpr.cpp#L396).\n\nThe above algorithm is only suited to parsing in the case where precedence\nlevels are totally ordered, because it does not say what to do if the new\nprecedence is not comparable with the ambient precedence. However, the algorithm\ncan easily be adapted to also parse with a partial precedence order by adding\none more case:\n\n-   If the precedence level of the new operator is not comparable with the\n    ambient precedence level, produce an ambiguity error.\n\nThe key observation here is that, if we ever see `... a * b ^ c ...`, where `*`\nand `^` have incomparable precedence, no later tokens can ever resolve the\nambiguity, so we can diagnose it immediately. Sketch proof: If there were a\nvalid parse tree for this expression, one of `*` and `^` must end up as an\nancestor of the other. But in a valid parse tree, along the path from one\noperator to the other, precedences monotonically increase, so by transitivity of\nthe precedence partial ordering, the ancestor operator has lower precedence than\nthe descendent operator.\n\nAn operator precedence parser with a partial ordering of precedence levels\n[has been implemented](https://github.com/carbon-language/carbon-lang/commit/b8afadb3c6af5e68192d585232fee759180ea1e3)\nas a proof-of-concept in the Carbon toolchain.\n\nOperator precedence partial ordering can also be implemented in yacc / bison\nparser generators by using a variant of the\n[precedence climbing method](https://en.wikipedia.org/wiki/Operator-precedence_parser#Precedence_climbing_method).\nFor example, here is a yacc grammar for the Hasse diagram shown above:\n\n```\nexpression: compare_expression | compare_operand;\n\ncompare_expression: compare_lhs EQEQ compare_operand { $$ = ($1 == $3); };\ncompare_lhs: compare_expression | compare_operand;\ncompare_operand: add_expression | multiply_expression | shift_expression | primary_expression;\n\nadd_expression: add_lhs '+' add_operand { $$ = ($1 + $3); };\nadd_lhs: add_expression | add_operand;\nadd_operand: multiply_expression | multiply_operand;\n\nmultiply_expression: multiply_lhs '*' multiply_operand { $$ = ($1 * $3); };\nmultiply_lhs: multiply_expression | multiply_operand;\nmultiply_operand: primary_expression;\n\nshift_expression: shift_lhs LSH shift_operand { $$ = ($1 << $3); };\nshift_lhs: shift_expression | shift_operand;\nshift_operand: primary_expression;\n\nprimary_expression: INT | '(' expression ')' { $$ = $2; };\n```\n\nNote that some care must be taken to avoid grammar ambiguities. Under the\nprecedence climbing method, a `primary_expression` would be a\n`shift_expression`, a `multiply_expression`, and an `add_expression`, and\ntherefore interpreting a `primary_expression` as an `expression` would be\nambiguous: we could take either the `shift_expression` path or the\n`multiply_expression` path through the grammar. The above formulation avoids\nthis ambiguity by excluding `primary_expression` from `add_expression` and\n`shift_expression`, and instead listing it as a distinct production for\n`compare_operand`. A yacc grammar such as the above can be produced\nsystematically for any precedence partial ordering.\n\nA complete example of a yacc parser with operator precedence partial ordering is\navailable [alongside this proposal](p0555/yacc-parser).\n\n## Rationale based on Carbon's goals\n\n-   Software and language evolution\n\n    -   The advice to not supply an operator precedence relationship if in doubt\n        is based on the idea that it's easier to add a precedence rule as an\n        evolutionary step than to remove one.\n\n-   Code that is easy to read, understand, and write\n\n    -   This proposal aims to support this goal by ensuring that the operator\n        expressions that are used in programs are readily understood by\n        practitioners, by making unreadable constructs invalid.\n\n## Alternatives considered\n\n### Total order\n\nWe could provide a total order over operator precedence. This proposal is not\nstrictly in conflict with doing so, if every ordering relationship is justified,\nbut in practice we expect there to be pairs of operators for which there is no\nobvious precedence relationship.\n\nFor:\n\n-   This is established practice across most languages.\n\nAgainst:\n\n-   This practice is a common source of bugs in the case where an arbitrary or\n    bad choice is made.\n\n### Different precedence for different operands\n\nWe could provide different precedence relationships for the left and right sides\nof infix operators. For example, we could allow multiplication on the left of a\n`<<` operator but not on the right. This is precedented in C++: the `?` in a\n`?:` allows a comma operator on its right but not on its left.\n\nFor:\n\n-   This may allow some additional cases that would be clear and unsurprising.\n\nAgainst:\n\n-   The resulting rules would be more challenging to learn, and it seems likely\n    that they would fail the test that most developers who regularly use Carbon\n    know the rules.\n\nThis proposal is not incompatible with adopting such a direction in future if we\nfind motivation to do so.\n\n### Require less than a partial order\n\nWe could require something weaker than a partial ordering of precedence levels.\nThis proposal assumes the following two points are useful for human\ncomprehension of operator precedence:\n\n-   The lowest-precedence operator does not depend on the relative order of\n    operators in the expression (except as a tie-breaker when there are multiple\n    operators with the same precedence, where the associativity of the operator\n    is considered).\n-   If an `^` expression can appear indirectly (but unparenthesized) within an\n    `$` expression, then an `^` expression can appear directly within an `$`\n    expression.\n-   If the lowest-precedence operator in `a $ b ^ c` is `$`, and the\n    lowest-precedence operator in `b ^ c # d` is `^`, then the lowest-precedence\n    operator in `a $ b ^ c # d` is `$`.\n\nThese assumptions lead to the conclusion that operator precedence should form a\npartial order over equivalence classes of operators. However, these assumptions\ncould be wrong.\n\nIf we find motivation to select rules that violate the above assumptions, we\nshould reconsider the approach of using a partial precedence ordering, but no\nmotivating case is currently known.\n"
  },
  {
    "path": "proposals/p0561.md",
    "content": "# Basic classes: use cases, struct literals, struct types, and future work\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/561)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Earlier proposal](#earlier-proposal)\n    -   [Interfaces implemented for anonymous data classes](#interfaces-implemented-for-anonymous-data-classes)\n    -   [Access control](#access-control)\n    -   [Introducer for structural data class types](#introducer-for-structural-data-class-types)\n    -   [Terminology](#terminology)\n\n<!-- tocstop -->\n\n## Problem\n\nWe need to say how you define new types in Carbon. This proposal is specifically\nabout [record types](<https://en.wikipedia.org/wiki/Record_(computer_science)>).\nThe proposal is not intended to be a complete story for record types, but enough\nto get agreement on direction. It primarily focuses on:\n\n-   use cases including: data classes, encapsulated types with virtual and\n    non-virtual methods and optional single inheritance, interfaces as base\n    classes that support multiple inheritance, and mixins for code reuse;\n-   anonymous structural data types for record literals used to initialize class\n    values and ad-hoc parameter and return types with named components; and\n-   future work, including the provisional syntax in use for features that have\n    not been decided.\n\n## Background\n\nThis is a replacement for earlier proposal\n[#98](https://github.com/carbon-language/carbon-lang/pull/98).\n\n## Proposal\n\nThis proposal adds an initial design for record types called \"classes\",\nincluding _structural data classes_ called _struct types_ as well as struct\nliterals. The design is replacing the skeletal design for what were called\n\"struct\" types with a [new document on classes](/docs/design/classes.md).\n\n## Rationale based on Carbon's goals\n\nThis particular proposal is focusing on\n[the Carbon goal](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\nthat code is \"easy to read, understand, and write.\" Future proposals will\naddress other aspects of the class type design such as performance.\n\n## Alternatives considered\n\n### Earlier proposal\n\nThere was an earlier proposal\n[#98](https://github.com/carbon-language/carbon-lang/pull/98), that made a\nnumber of different choices, including:\n\n-   Tuples were given named components instead of having separate struct\n    literals.\n-   No form of multiple inheritance was proposed.\n-   Operators were define using methods like C++ instead of by implementing\n    interfaces like Rust.\n-   Constructors had a special form like C++ instead of being regular functions\n    like Rust.\n-   Tuples and classes were both considered example of record types.\n-   Members of classes could be individually left uninitialized.\n-   Coverage of nominal types, inheritance, etc. were considered in much more\n    detail.\n\n### Interfaces implemented for anonymous data classes\n\nWhether we would support implementing interfaces for specific anonymous data\nclasses was\n[discussed on Discord](https://discord.com/channels/655572317891461132/709488742942900284/867471671089561643).\n[The conclusion](https://discord.com/channels/655572317891461132/709488742942900284/867516894029938710)\nwas \"yes\", reasoning that we would support that for the same reason as a number\nof other cases such as tuple and pointer types.\n[A specific use case](https://discord.com/channels/655572317891461132/709488742942900284/867517209026756630)\nwould be implementing interface\n\n```\ninterface ConstructWidgetFrom { fn Construct(Self) -> Widget; }\n```\n\nfor type `{.kind: WidgetKind, .size: Int}`.\n\n### Access control\n\n[Issue #665](https://github.com/carbon-language/carbon-lang/issues/665) decided\nthat by default members of a class would be publicly accessible. There were a\nfew reasons:\n\n-   The readability of public members is the most important, since we expect\n    most readers to be concerned with the public API of a type.\n-   The members that are most commonly private are the data fields, which have\n    relatively less complicated definitions that suffer less from the extra\n    annotation.\n\nAdditionally, there is precedent for this approach in modern object-oriented\nlanguages such as\n[Kotlin](https://kotlinlang.org/docs/visibility-modifiers.html) and\n[Python](https://docs.python.org/3/tutorial/classes.html), both of which are\nwell regarded for their usability.\n\nIt further decided that members would be given more restricted access using a\nlocal annotation on the declaration itself rather than a block or region\napproach such as used in C++. This is primarily motivated by a desire to reduce\ncontext sensitivity, following\n[the principle](/docs/project/principles/low_context_sensitivity.md) introduced\nin [#646](https://github.com/carbon-language/carbon-lang/pull/646). It helps\nreaders to more easily determine the accessibility of a member in large classes,\nsay when they have jumped to a specific definition in their IDE.\n\n### Introducer for structural data class types\n\n[Issue #653](https://github.com/carbon-language/carbon-lang/issues/653)\ndiscussed whether structural data class types should have an introducer to\ndistinguish them from structural data class literals. Ultimately we decided no\nintroducer was needed:\n\n-   Outside of `{}`, types could be distinguished from literal values by the\n    presence of a `:` after the first field name.\n-   This creates a sort of consistency: introducers are frequently used when\n    introducing new names, as in `fn`, `var`, `interface`, and so on. Struct\n    type declarations don't introduce new names so they don't require an\n    introducer.\n-   It avoids having a different introducer for things that are still treated as\n    classes for many purposes. This means we won't have to frequently say\n    \"struct or class\" in documentation.\n-   We do want to use these type expressions in contexts that will benefit from\n    being more concise, such as inside function and variable declarations.\n\nThis does cause an issue that `{}` is both an empty struct literal and empty\nstruct type. However, we've already accepted that complexity with tuples, so\nthis choice is more consistent. If we find that we need an introducer for tuple\ntypes to distinguish the empty tuple from its type, we expect to find that we\nhave the same problem with empty struct literals, and the other way around. We\nare explicitly to choosing to accept the risk that this won't work out in order\nto have a more concise syntax in case it does.\n\n### Terminology\n\nDo literals have \"class\" type or are they some other kind of type?\n[Issue #651](https://github.com/carbon-language/carbon-lang/issues/651) decided\nthat all of these types were different kinds of classes:\n\n-   Literals like `{.a = 2}` are \"structural data class literals\" or \"struct\n    literals\" for short. Here \"structural\" means that two types are considered\n    equal if their fields match. They are not \"nominal\" since they don't have a\n    name to use for type equality.\n-   The types of those literals like `{.a: i64}` would be \"structural data\n    classes\" or \"struct types\" for short.\n-   There would also be \"nominal data classes\" that are declared with a syntax\n    more similar to other nominal classes.\n\nWe preferred to refer to all of these as class types, rather than have to\nfrequently refer to \"struct or class types\", adding additional words to name\nmore specific subsets, like \"data classes\". In contrast, tuple types are not\nconsidered classes, but classes and tuples together form _product types_.\n\nThe term \"class\" was chosen over \"struct\" since they generally support\nobject-oriented features like encapsulation, inheritance, and dynamic dispatch,\nand how C++ programmers generally refer to their record types. These were\nconsidered more significant than the C++ distinction that classes default to\nprivate access control. Since we plan to use a different syntax in Carbon to\nspecify access restrictions, the different default seemed straightforward to\nteach.\n"
  },
  {
    "path": "proposals/p0601.md",
    "content": "# Operator tokens\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/601)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Two kinds of operator tokens](#two-kinds-of-operator-tokens)\n    -   [Symbolic token list](#symbolic-token-list)\n    -   [Whitespace](#whitespace)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Problem\n\nCarbon needs a set of tokens to represent operators.\n\n## Background\n\nSome languages have a fixed set of operator tokens. For example:\n\n-   [C++ operators](https://eel.is/c++draft/lex.operators)\n    -   The keyword operators `and`, `or`, etc. are lexical synonyms for\n        corresponding symbolic operators `&&`, `||`, etc.\n-   [Rust operators](https://doc.rust-lang.org/book/appendix-02-operators.html)\n\nOther languages have extensible rules for defining operators, including the\nfacility for a developer to define operators that aren't part of the base\nlanguage. For example:\n\n-   [Swift operator rules](https://docs.swift.org/swift-book/ReferenceManual/LexicalStructure.html#ID418)\n-   [Haskell operator rules](https://www.haskell.org/onlinereport/haskell2010/haskellch2.html#dx7-18008)\n\nOperators tokens can be formed by various rules, for example:\n\n-   At each lexing step, form the longest known operator token possible from the\n    remaining character sequence. For example, in C++, `a += b` is 3 tokens and\n    `a =+ b` is four tokens, because there are `+`, `=`, and `+=` operators, but\n    there is no `=+` operator. This approach is sometimes known as \"max munch\".\n-   At each lexing step, treat the longest sequence of operator-like characters\n    possible as an operator. The program is invalid if there is no such\n    operator. For example, in a C++-like language using this approach, `a =+ b`\n    would be invalid instead of meaning `a = (+b)`.\n-   Use semantic information to determine how to split a sequence of operator\n    characters into one or more operators, for example based on the types of the\n    operands.\n\n## Proposal\n\nCarbon has a fixed set of tokens that represent operators, defined by the\nlanguage specification. Developers cannot define new tokens to represent new\noperators; there may be facilities to overload operators, but that is outside\nthe scope of this proposal. There are two kinds of tokens that represent\noperators:\n\n-   _Symbolic tokens_ consist of one or more symbol characters. In particular,\n    such a token contains no characters that are valid in identifiers, no quote\n    characters, and no whitespace.\n-   _Keywords_ follow the lexical rules for words.\n\nSymbolic tokens are lexed using a \"max munch\" rule: at each lexing step, the\nlongest symbolic token defined by the language specification that appears\nstarting at the current input position is lexed, if any.\n\nNot all uses of symbolic tokens within the Carbon grammar will be as operators.\nFor example, we will have `(` and `)` tokens that serve to delimit various\ngrammar productions, and we may not want to consider `.` to be an operator,\nbecause its right \"operand\" is not an expression.\n\nWhen a symbolic token is used as an operator, we use the presence or absence of\nwhitespace around the symbolic token to determine its fixity, in the same way we\nexpect a human reader to recognize them. For example, we want `a* - 4` to treat\nthe `*` as a unary operator and the `-` as a binary operator, while `a * -4`\nresults in the reverse. This largely requires whitespace on only one side of a\nunary operator and on both sides of a binary operator. However, we'd also like\nto support binary operators where a lack of whitespace reflects precedence such\nas`2*x*x + 3*x + 1` where doing so is straightforward. The rules we use to\nachieve this are:\n\n-   There can be no whitespace between a unary operator and its operand.\n-   The whitespace around a binary operator must be consistent: either there is\n    whitespace on both sides or on neither side.\n-   If there is whitespace on neither side of a binary operator, the token\n    before the operator must be an identifier, a literal, or any kind of closing\n    bracket (for example, `)`, `]`, or `}`), and the token after the operator\n    must be an identifier, a literal, or any kind of opening bracket (for\n    example, `(`, `[`, or `{`).\n\nThis proposal includes an initial set of symbolic tokens covering only the\ngrammar productions that have been approved so far. This list should be extended\nby proposals that use additional symbolic tokens.\n\n## Details\n\n### Two kinds of operator tokens\n\nTwo kinds of operator tokens are proposed. These two kinds are intended for\ndifferent uses, not as alternate spellings of the same functionality:\n\n-   Symbolic tokens are intended to be used for widely-recognized operators,\n    such as the mathematical operators `+`, `*`, `<`, and so on.\n    -   Symbolic tokens used as operators would generally be expected to also be\n        meaningful for some user-defined types, and should be candidates for\n        being made overloadable once we support operator overloading.\n-   Keywords are intended to be used for cases such as the following:\n    -   Operators that perform flow control, such as `and`, `or`, `throw`,\n        `yield`, and operators closely connected to these, such as `not`. It is\n        important that these stand out from other operators as they have action\n        that goes beyond evaluating their operands and computing a value.\n    -   Operators that are rare and that we do not want to spend our finite\n        symbolic token budget on, such as perhaps xor or bit rotate.\n    -   Operators with very low precedence, and perhaps certain operators with\n        very high precedence.\n    -   Special-purpose operators for which there is no conventional established\n        symbol and for which we do not want to invent one, such as `as`.\n\nThe example operators in this section are included only to motivate the two\nkinds of operator token; those specific operators are not proposed as part of\nthis proposal.\n\n### Symbolic token list\n\nThe following is the initial list of symbolic tokens recognized in a Carbon\nsource file:\n\n|     |      |      |     |     |     |\n| --- | ---- | ---- | --- | --- | --- |\n| `(` | `)`  | `{`  | `}` | `[` | `]` |\n| `,` | `.`  | `;`  | `:` | `*` | `&` |\n| `=` | `->` | `=>` |     |     |     |\n\nThis list is expected to grow over time as more symbolic tokens are required by\nlanguage proposals.\n\n### Whitespace\n\nWe wish to support the use of the same symbolic token as a prefix operator, an\ninfix operator, and a postfix operator, in some cases. In particular, we have\n[decided in #523](https://github.com/carbon-language/carbon-lang/issues/523)\nthat the `*` operator should support all three uses; this operator will be\nintroduced in a future proposal. In order to support such usage, we want a rule\nthat allows us to simply and unambiguously parse operators that might have all\nthree fixities.\n\nFor example, given the expression `a * - b`, there are two possible parses:\n\n-   As `a * (- b)`, multiplying `a` by the negation of `b`.\n-   As `(a *) - b`, subtracting `b` from the pointer type `a *`.\n\nOur chosen rule to distinguish such cases is to consider the presence or absence\nof whitespace, as we think this strikes a good balance between simplicity and\nexpressiveness for the programmer and simplicity and good support for error\nrecovery in the implementation. `a * -b` uses the first interpretation, `a* - b`\nuses the second interpretation, and other combinations (`a*-b`, `a *- b`,\n`a* -b`, `a * - b`, `a*- b`, `a *-b`) are rejected as errors.\n\nIn general, we require whitespace to be present or absent around the operator to\nindicate its fixity, as this is a cue that a human reader would use to\nunderstand the code: binary operators have whitespace on both sides, and unary\noperators lack whitespace between the operator and its operand. We also make\nallowance for omitting the whitespace around a binary operator in cases where it\naids readability to do so, such as in expressions like `2*x*x + 3*x + 1`: for an\noperator with whitespace on neither side, if the token immediately before the\noperator indicates it is the end of an operand, and the token immediately after\nthe operator indicates it is the beginning of an operand, the operator is\ntreated as binary.\n\nWe define the set of tokens that constitutes the beginning or end of an operand\nas:\n\n-   Identifiers, as in `x*x + y*y`.\n-   Literals, as in `3*x + 4*y` or `\"foo\"+s`.\n-   Brackets of any kind, facing away from the operator, as in `f()*(n + 3)` or\n    `args[3]*{.real=4, .imag=1}`.\n\nFor error recovery purposes, this rule functions best if no expression context\ncan be preceded by a token that looks like the end of an operand and no\nexpression context can be followed by a token that looks like the start of an\noperand. One known exception to this is in function definitions:\n\n```\nfn F(p: Int *) -> Int * { return p; }\n```\n\nBoth occurrences of `Int *` here are erroneous. The first is easy to detect and\ndiagnose, but the second is more challenging, if `{...}` is a valid expression\nform. We expect to be able to easily distinguish between code blocks starting\nwith `{` and expressions starting with `{` for all cases other than `{}`.\nHowever, the code block `{}` is not a reasonable body for a function with a\nreturn type, so we expect errors involving a combination of misplaced whitespace\nand `{}` to be rare, and we should be able to recover well from the remaining\ncases.\n\nFrom the perspective of token formation, the whitespace rule means that there\nare four _variants_ of each symbolic token:\n\n-   A symbolic token with whitespace on both sides is a _binary_ variant of the\n    token.\n-   A symbolic token with whitespace on neither side, where the preceding token\n    is an identifier, literal, or closing bracket, and the following token is an\n    identifier, literal, or `(`, is also a _binary_ variant of the token.\n-   A symbolic token with whitespace on neither side that does not satisfy the\n    preceding rule is a _unary_ variant of the token.\n-   A symbolic token with whitespace on the left side only is a _prefix_ variant\n    of the token.\n-   A symbolic token with whitespace on the right side only is a _postfix_\n    variant of the token.\n\nWhen used in non-operator contexts, any variant of a symbolic token is\nacceptable. When used in operator contexts, only a binary variant of a token can\nbe used as a binary operator, only a prefix or unary variant of a token can be\nused as a prefix operator, and only a postfix or unary variant of a token can be\nused as a postfix operator.\n\nThis whitespace rule has been\n[implemented in the Carbon toolchain](https://github.com/carbon-language/carbon-lang/pull/576)\nfor all operators by tracking the presence or absence of trailing whitespace as\npart of a token, and\n[in executable semantics](https://github.com/carbon-language/carbon-lang/commit/04d3a885ae01a779aadb19f51ec7a5a12ffe295c)\nfor the `*` operator by forming four different token variants as described\nabove.\n\nThe choice to disallow whitespace between a unary operator and its operand is\n_experimental_.\n\n## Rationale based on Carbon's goals\n\n-   Software and language evolution\n\n    -   By not allowing user-defined operators, we reduce the possibility that\n        operators added to the language later will conflict with existing uses\n        in programs. Due to the use of a max munch rule, we might add an\n        operator that causes existing code to be interpreted differently, but\n        such problems will be easy to detect and resolve, because we know the\n        operator set in advance.\n\n-   Code that is easy to read, understand, and write\n\n    -   The fixed operator set means that developers don't need to understand an\n        unbounded and extensible number of operators and precedence rules. The\n        fixed operator set encourages functionality that does not correspond to\n        a well-known operator symbol to be exposed by way of a named operation\n        instead of a symbol, improving readability among developers not familiar\n        with a codebase.\n    -   Requiring whitespace to be used consistently around operators reduces\n        the possibility for confusing formatting.\n    -   Permitting whitespace on either both sides of a binary operator or on\n        neither side allows expressions such as `2*x*x + 3*x + 1` to use the\n        absence of whitespace to improve readability. Because the language\n        officially sanctions both choices, the formatting tool can be expected\n        to preserve the user's choice.\n    -   The choice to lex the longest known symbolic token rather than the\n        longest sequence of symbolic characters makes it easier to write\n        expressions involving a series of prefix or postfix operators, such as\n        `x = -*p;`.\n\n-   Interoperability with and migration from existing C++ code\n\n    -   The fixed operator set makes a mapping between Carbon operators and C++\n        operators easier, by avoiding any desire to map arbitrary user-defined\n        Carbon operators into a C++ form.\n    -   The choice of a fixed operator set and a \"max munch\" rule will be\n        familiar to C++ developers, as it is the same approach taken by C++.\n    -   The whitespace rule permits the `*` operator to be used for all of\n        multiplication, dereference, and pointer type formation, as in C++,\n        while still permitting Carbon to treat type expressions as expressions.\n\n## Alternatives considered\n\nWe could lex the longest sequence of symbolic characters rather than lexing only\nthe longest known operator.\n\nAdvantages:\n\n-   Adding new operators could be done without any change to the lexing rules.\n-   If unknown operators are rejected, adding new operators would carry no risk\n    of changing the meaning of existing valid code.\n\nDisadvantages:\n\n-   Sequences of prefix or postfix operators would require parentheses or\n    whitespace. For example, `Int**` would lex as `Int` followed by a single\n    `**` token, and `**p` would lex as a single `**` token followed by `p`, if\n    there is no `**` operator. While we could define `**`, `***`, and so on as\n    operators, doing so would add complexity and inconsistency to the language\n    rules.\n\nWe could support an extensible operator set, giving the developer the option to\nadd new operators.\n\nAdvantages:\n\n-   This would increase expressivity, especially for embedded domain-specific\n    languages.\n\nDisadvantages:\n\n-   This would harm readability, at least for those unfamiliar with the code\n    using the operators.\n-   This could harm our ability to evolve the language, by admitting the\n    possibility of a custom operator colliding with a newly-introduced standard\n    operator, although this risk could be reduced by providing a separate\n    lexical syntax for custom operators.\n-   We would need to either lex the longest sequence of symbolic characters we\n    can, which has the same disadvantage discussed for that approach above, or\n    use a more sophisticated rule to determine how to split operators -- perhaps\n    based on what operator overloads are in scope -- increasing complexity.\n\nWe could apply different whitespace restrictions or no whitespace restrictions.\nSee [#520](https://github.com/carbon-language/carbon-lang/issues/520) for\ndiscussion of the alternatives and the leads decision.\n\nWe could require whitespace around a binary operator followed by `[` or `{`. In\nparticular, for examples such as:\n\n```\nfn F() -> Int*{ return Null; }\nvar n: Int = pointer_to_array^[i];\n```\n\n... this would allow us to form a unary operator instead of a binary operator,\nwhich is likely to be more in line with the developer's expectations.\n\nAdvantages:\n\n-   Room to add a postfix `^` dereference operator, or similarly any other\n    postfix operator producing an array, without creating surprises for pointers\n    to arrays.\n-   Allows the whitespace before the `{` of a function body to be consistently\n    omitted if desired.\n\nDisadvantages:\n\n-   The rule would be more complex, and would be asymmetric: we must allow\n    closing square brackets before unspaced binary operators to permit things\n    like `arr[i]*3`.\n-   Would interact badly with expression forms that begin with a `[` or `{`, for\n    example `Time.Now()+{.seconds = 3}` or `names+[\"Lrrr\"]`.\n"
  },
  {
    "path": "proposals/p0618.md",
    "content": "# var ordering\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/618)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Type ordering](#type-ordering)\n        -   [`<type>: <name>`](#type-name)\n        -   [`<type> <name>`](#type-name-1)\n        -   [`<name>: <type>`](#name-type)\n    -   [`:` versus `in`](#-versus-in)\n\n<!-- tocstop -->\n\n## Problem\n\nAs stated by on\n[Re-evaluate core variable & parameter identifier/type order (including a default for parameters) #542](https://github.com/carbon-language/carbon-lang/issues/542):\n\n> Somewhat condensed, bullet-point-y background for this question:\n>\n> -   We've been using first `Type: variable` and then `Type variable` syntax in\n>     variables, parameters, and other declarations.\n> -   This was primarily based on a _lack of compelling data_ to select a better\n>     syntax, with trying to stay similar to C++ as a fallback.\n> -   It was _specifically_ intended to be revisited. The expected trigger for\n>     this was some form of broader user data (surveys at least of decent #s of\n>     developers, or potentially real user studies).\n> -   However, we have gained specific new information as we've filled out a\n>     great deal of the surrounding syntax. We have also gotten some data on\n>     parsing challenges (although perhaps surmountable challenges) of\n>     `Type variable`.\n> -   We also don't have a short/definite timeline to start getting useful data.\n> -   The leads should re-evaluate the core variable syntax based on the new\n>     information we have, but _without_ trying to wait for data.\n>     -   We can always re-evaluate again if and when data arrives and indicates\n>         any need for it.\n> -   The leads should do this ASAP and make a decision so that we can focus our\n>     energy, reduce frustrating discussions, and have consistent syntax in\n>     examples and proposals.\n\n## Background\n\nBackground may be found in the related\n[#542](https://github.com/carbon-language/carbon-lang/issues/542) and\n[Docs](https://docs.google.com/document/d/1EhZA3AlY9TaCMho9jz2ynFxK-6eS6BwMAkE5jNYQzEA/edit?usp=sharing&resourcekey=0-QXEoh-b4_sQG2u636gIa1A).\n\n## Proposal\n\nTwo changes:\n\n-   Switch to `<name>: <type>`, replacing `<type>: <name>`.\n-   Use `in` instead of `:` in range-based for loops.\n\nNote these changes were largely implemented by\n[#563](https://github.com/carbon-language/carbon-lang/pull/563).\n\n## Rationale based on Carbon's goals\n\nBoth of these changes are done for consistency with other modern languages,\nparticularly Swift and Rust. The switch from `:` to `in` is for ease of\nunderstanding and parsing.\n\n## Alternatives considered\n\n### Type ordering\n\nAlternatives are pulled from\n[Docs](https://docs.google.com/document/d/1EhZA3AlY9TaCMho9jz2ynFxK-6eS6BwMAkE5jNYQzEA/edit?usp=sharing&resourcekey=0-QXEoh-b4_sQG2u636gIa1A).\n\n#### `<type>: <name>`\n\n`var String: message = \"Hello world\";`\n\nAdvantages:\n\n-   Roughly matches the order of C, C++, C#, D and Java, except with extra `var`\n    and `:`.\n-   Type at the beginning puts most important information up front.\n-   Name followed by default matches assignment statements.\n\nDisadvantages:\n\n-   Existing languages that use a `:` put the name before and the type after\n    ([universally](http://rosettacode.org/wiki/Variables)).\n-   Beyond simple inconsistency, the overlap of `:` in this syntax with\n    different order will add confusion for people working/familiar with multiple\n    languages.\n-   Does not end up having a syntax that is consistent with using colons for\n    marking labelled parameters and arguments, such as how Swift does.\n    -   We currently do not plan to use a colon syntax for labelled parameters\n        and arguments, regardless of the decision here.\n\nOpinions vary:\n\n-   Not friendly to optionally dropping the `type:` to represent auto type\n    deduction.\n\n#### `<type> <name>`\n\n`var String message = \"Hello world\";`\n\nAdvantages\n\n-   Matches C, C++, C#, D and Java the closest.\n\nDisadvantages:\n\n-   Creates parse ambiguity, particularly when we start adding syntax to the\n    name to indicate that a parameter is labeled, etc.\n\nCurrently hard to see how we can make this work, since it isn't compatible with\nother choices, detailed in\n[Docs](https://docs.google.com/document/d/1EhZA3AlY9TaCMho9jz2ynFxK-6eS6BwMAkE5jNYQzEA/edit?usp=sharing&resourcekey=0-QXEoh-b4_sQG2u636gIa1A).\n\n#### `<name>: <type>`\n\n`var message: String = \"Hello world\";`\n\nAdvantages:\n\n-   Matches [Swift](http://rosettacode.org/wiki/Variables#Swift),\n    [Rust](https://doc.rust-lang.org/stable/rust-by-example/primitives.html),\n    [Kotlin](http://rosettacode.org/wiki/Variables#Kotlin),\n    [Python3](https://docs.python.org/3/library/typing.html), and many smaller\n    languages ([Ada](http://rosettacode.org/wiki/Variables#Ada),\n    [Pascal languages like Delphi](http://rosettacode.org/wiki/Variables#Delphi)\n    and [Modula-3](http://rosettacode.org/wiki/Variables#Modula-3),\n    [Eiffel](http://rosettacode.org/wiki/Variables#Eiffel),\n    [Nim](https://nim-lang.org/docs/tut1.html#the-var-statement),\n    [Pony](http://rosettacode.org/wiki/Variables#Pony),\n    [Zig](https://ziglang.org/documentation/0.7.1/#Variables)).\n-   Names will line up better with method names in a `struct` definition.\n\nDisadvantages:\n\n-   Name separated from initializer; default doesn't match assignment\n    statements.\n-   Further from the simplistic appearance of common C and C++ variable\n    declarations.\n\nOpinions vary:\n\n-   Existing languages typically make the \"`: type`\" part optional when an\n    \"`= value`\" clause is present.\n\n### `:` versus `in`\n\nThe `:` operator for range-based for loops becomes harder to read, and more\nlikely to cause ambiguity, when `:` is also used for `var`. That is,\n`for (var i: Int : list)` is just harder to understand than\n`for (var i: Int in list)`. `in` is a favorable choice for its use in other\nlanguages.\n"
  },
  {
    "path": "proposals/p0623.md",
    "content": "# Require braces\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/623)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Consistency](#consistency)\n    -   [C++ style rules](#c-style-rules)\n    -   [`goto fail`](#goto-fail)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Optional braces](#optional-braces)\n    -   [Optional parentheses](#optional-parentheses)\n    -   [`elif`](#elif)\n\n<!-- tocstop -->\n\n## Problem\n\nIn C++, braces are often optional, such as in:\n\n```\nfor (Shape x : shapes)\n  Draw(x);\n```\n\nCarbon adopted this design choice by default in proposals\n[#285](/proposals/p0285.md), [#340](/proposals/p0340.md), and\n[#353](/proposals/p0353.md). But should we keep it?\n\n## Background\n\n### Consistency\n\nWe were adopting the C++ syntax primarily for easy consistency with C++. For\nother languages:\n\n-   Some modern languages require braces, including Go, Rust, and Swift. Note\n    some which require braces make parentheses optional.\n-   Kotlin is an example modern language which does not require braces.\n-   Older languages tend to make braces optional, including Java, JavaScript,\n    and C#.\n\n### C++ style rules\n\nThere is a\n[CERT rule](https://wiki.sei.cmu.edu/confluence/display/c/EXP19-C.+Use+braces+for+the+body+of+an+if%2C+for%2C+or+while+statement)\nfor when to use braces.\n\n### `goto fail`\n\nApple had an infamous `goto fail` bug:\n\n-   https://www.imperialviolet.org/2014/02/22/applebug.html\n-   https://dwheeler.com/essays/apple-goto-fail.html\n\n## Proposal\n\nCarbon should require braces when they might otherwise be optional. We should\ncontinue to require parentheses. This currently comes up in `if`/`else`,\n`while`, and `for`.\n\nWe will allow `else if` as a special structure for repeated `if` statements due\nto their frequency. For example, `if (...) { ... } else if (...) { ... }`\nbehaves identically to `if (...) { ... } else { if (...) { ... } }`.\n\n## Rationale based on Carbon's goals\n\n-   **Software and language evolution**: Reducing parsing ambiguity of curly\n    braces is important for expanding the syntactic options for Carbon.\n\n-   **Code that is easy to read, understand, and write**: We have a preference\n    to give only one way to do things, and optional braces are inconsistent with\n    that. It's also easier to understand and parse code that uses braces, and\n    defends against the possibility of `goto fail`-style bugs, whether\n    accidental or malicious.\n\n-   **Interoperability with and migration from existing C++ code**: While C++\n    does make braces optional in related situations, we believe this isn't\n    fundamental to migration or familiarity for C++ developers, so this goal is\n    not meaningfully impacted by this change.\n\n## Alternatives considered\n\n### Optional braces\n\nWe could instead keep braces optional, such as:\n\n```carbon\nif (x)\n  return y;\n```\n\nAdvantages:\n\n-   Consistent with C++.\n-   Allows for greater brevity in code, such as `if (!success) return error;`.\n\nDisadvantages:\n\n-   Gives two ways of doing the same thing.\n    -   Style guides will make choices, creating more contextual coding style.\n    -   Some community members opined that requiring braces was the only\n        solution which is both appealing and easy to automate formatting for.\n        -   A contrary opinion is that single-line if statements without braces\n            are more appealing, and not significantly more difficult to\n            automate.\n-   More complex and harder to parse.\n\n    -   Nested `if` statements can have unclear `else` bindings. For example:\n\n        ```carbon\n        if (x)\n        if (y)\n          DoIfY();\n        else\n          DoIfNotY();\n        else\n          DoIfNotX();\n        ```\n\n    -   If Carbon were to reuse `if` and `else` keywords for a ternary operator,\n        that could omit braces in order to avoid ambiguity. For example,\n        `int x = if y then 3 else 7;`.\n\n-   Developers are known to make mistakes adding statements to conditionals\n    missing braces, keeping consistent indentation, and missing the incorrect\n    behavior due to cognitive load. For example:\n\n    ```carbon\n    if (x)\n      return y;\n    ```\n\n    ->\n\n    ```carbon\n    if (x)\n      print(\"Returning y\");\n      return y;\n    ```\n\n    -   Developers commonly want to add debugging statements to conditionals,\n        and missing braces can lead to these kinds of errors.\n    -   It's possible that, over time, adding braces to add debug statements\n        then removing the debug statements without removing statements will lead\n        to braces remaining when braces are optional.\n        -   This can be addressed by style guides and automated formatting that\n            inserts or removes braces as appropriate, cleaning up after\n            temporary edits.\n        -   Some people feel the churn of adding braces and later removing them\n            is a significant toil that can be avoided by always adding them,\n            such as [here](https://wiki.c2.com/?AlwaysUseBracesOnIfThen).\n    -   It can more easily lead to bugs like `goto fail;`.\n        -   However, as the blog post points out, one can have incorrect\n            indentation with braces too.\n\n### Optional parentheses\n\nLanguages which make braces required can make parentheses optional, or even\ndisallow them, such as:\n\n```carbon\nif x {\n  return y;\n}\n```\n\nAdvantages:\n\n-   Exchanges verbosity in syntax, requiring `{}` but removing `()`.\n    -   Particularly useful in that many conditionals have `{}` regardless of\n        optionality, but all conditionals could in theory remove `()`.\n-   Cross-language consistency with languages that require `{}`.\n\nDisadvantages:\n\n-   Visual inconsistency with C++.\n-   Parentheses make parsing less likely to encounter ambiguity.\n-   Optional parentheses lead to two ways of doing the same thing, although\n    disallowing them entirely could address this.\n\n### `elif`\n\nWe could make `else if` a single token, such as `elseif` or `elif`.\n\nAdvantages:\n\n-   Can parse as a single token.\n\nDisadvantages:\n\n-   Visual inconsistency with C++.\n    -   `else if` also appears in some languages that require braces, such as\n        Go, Rust, and Swift.\n"
  },
  {
    "path": "proposals/p0646.md",
    "content": "# Low context-sensitivity principle\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/646)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n\n<!-- tocstop -->\n\n## Problem\n\nCarbon needs a consistent policy on how willing we are to make syntax dependent\non context.\n\n## Background\n\nRust has\n[a statement of their ergonomic principles](https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html)\nthat talks about their approach to context dependence.\n\n## Proposal\n\nWe propose adding\n(`docs/project/principles/low_context_sensitivity.md`)[/docs/project/principles/low_context_sensitivity.md],\nwhich has the details.\n\n## Rationale based on Carbon's goals\n\nThis proposal supports the goal of making Carbon code\n[easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\nparticularly prioritizing \"read and understand\" over \"write\".\n\nIt supports\n[software evolution](/docs/project/goals.md#software-and-language-evolution) by\nallowing code to be moved or refactored with fewer changes.\n\nFurther it supports developing\n[performance-critical software](/docs/project/goals.md#performance-critical-software)\nin Carbon by making performance predictable.\n"
  },
  {
    "path": "proposals/p0676.md",
    "content": "# `:!` generic syntax\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/676)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Default based on context](#default-based-on-context)\n        -   [Square brackets](#square-brackets)\n    -   [Other spellings that were considered](#other-spellings-that-were-considered)\n    -   [`Template` as a type-of-type](#template-as-a-type-of-type)\n-   [Alternatives not considered](#alternatives-not-considered)\n\n<!-- tocstop -->\n\n## Problem\n\nCarbon design docs provisionally used `:$` to mark generic parameters. Since\nthen, [issue #565](https://github.com/carbon-language/carbon-lang/issues/565)\ndecided to use `:!` more permanently. This proposal is to implement that\ndecision.\n\n## Background\n\nMost popular languages put generic parameters inside angle brackets (`<`...`>`),\nas can be seen on rosettacode.org:\n[1](http://rosettacode.org/wiki/Generic_swap),\n[2](http://rosettacode.org/wiki/Constrained_genericity).\n\n## Proposal\n\nGeneric parameters will be marked using `:!` instead of `:` in the parameter\nlist. They are listed with the regular parameters if they are to be specified\nexplicitly by callers.\n\n```\nfn Zero(T:! ConvertFrom(Int)) -> T;\n\nvar zf: Float32 = Zero(Float32);\n```\n\nIf they are instead deduced from the (types of) the regular parameters, they are\nlisted in square brackets (`[`...`]`) before the parameter list in round parens\n(`(`...`)`).\n\n```\nfn Swap[T:! Movable](a: T*, b: T*);\n\nvar i: Int = 1;\nvar j: Int = 2;\nSwap(&i, &j);\n```\n\nTemplate parameters use both a `template` keyword before the parameter and `:!`\nin place of `:`.\n\n```\nfn FieldNames(template T:! Type) -> String;\n\nAssert(FieldNames(struct {.x: Int, .y: Int}) == \"x, y\");\n```\n\nFor both generic and template parameters, the `!` means \"compile time.\" There is\nsome precedent for this meaning; Rust uses `!` to mark macro calls, that is\ncalls that happen at compile time.\n\n## Rationale based on Carbon's goals\n\nWe are attempting to choose a syntax that advances Carbon's goal of having\n[code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nThis option was chosen since it has the advantage of being very simple and not\nrelying on any context, in accordance with the\n[#646: low-context-sensitivity principle](https://github.com/carbon-language/carbon-lang/pull/646).\n\nFor ease of parsing, we've been trying to avoid using angle brackets (`<`...`>`)\noutside of declarations. This is primarily a concern for parameterized types\nthat can appear in expressions alongside comparison operators (`<` and `>`).\n\nThe choice to mark template parameters with a keyword was to make it very\nvisible when that powerful and dangerous feature was being used. We also liked\nthe similarities to how a `template` keyword also introduces a C++ template\ndeclaration.\n\nThe choice to use the specific symbols `:!` over `:$` or other possibilities was\njust a matter of taste.\n\n## Alternatives considered\n\nThere were a few other options considered to designate generics in\n[issue #565](https://github.com/carbon-language/carbon-lang/issues/565).\n\nNote that we at first considered the possibility that type parameters might\naccidentally be declared as dynamic if that was the default. We eventually\ndecided that we could forbid dynamic type parameters for now, and revisit this\nproblem if and when we decided to add a dynamic type parameter feature.\n\n### Default based on context\n\nIn a given syntactic context, one option is going to be more common than others:\n\n-   Regular explicit parameters would most commonly be dynamic.\n-   Deduced parameters would most commonly be generic.\n-   Parameters to interfaces and types would most commonly be generic.\n\nWe considered making `x: T` be generic or dynamic based on this context. In\ncases where this default was not what was intended, there would be a keyword\n(`dynamic`, `generic`, or `template`) to explicitly pick.\n\nThere were a few variations about whether to treat parameters used in types\ndifferently. This had the downside of being harder to discern at a glance.\n\nThe main benefits of this approach were:\n\n-   It handled dynamic type parameters being allowed but uncommon more\n    gracefully.\n-   Users could use `:` and it would generally do the right thing.\n-   Keywords are generally easier to find in search engines, and more\n    self-explanatory.\n-   Template parameters in particular were highlighted, a property shared with\n    the approach recommended by this proposal.\n\nThe main objections to this approach was that it was context-sensitive and there\nwas a lack of syntactic consistency in the context. That is, there were two\nkinds of context, generic and dynamic, and two kinds of brackets, square and\nparens, but sometimes the parens would be generic and sometimes not.\n\n#### Square brackets\n\nUsing `[`...`]` for generics creates the opposite problem of the brackets being\ninconsistent with the deduced or explicit distinction.\n\n```\n// `T` is an explicit generic parameter to `Vector`\nclass Vector[T: Type] { ... }\n// `T` and `DestT` are generic parameters, with `T` deduced and\n// `DestT` explicit.\nfn CastAVector[T: Type](v: Vector[T], generic DestT: Type) -> Vector[DestT];\n```\n\n### Other spellings that were considered\n\nThere were a number of other options considered. None of them were compelling,\nthough this mostly came down to taste.\n\n```\nclass Vector(<T: Type>) { ... }\nfn CastAVector<T: Type>(v: Vector(T), <DestT: CastFrom(T)>) -> Vector(DestT);\nvar from: Vector(i32) = ...;\nvar to: Vector(i64) = CastAVector(from, i64);\n```\n\n-   not trivial to parse, but doable\n-   too much punctuation\n-   nice that `<`...`>` is associated with generics, but with enough differences\n    to be concerning\n\n```\nfn CastAVector[T: Type](v: Vector(T), [DestT: Type]) -> Vector(DestT);\nclass Vector([T: Type]) { ... }\nvar from: Vector(i32) = ...;\nvar to: Vector(i64) = CastAVector(from, i64);\n```\n\n-   There was no reason to prefer this over the previous option, since `<`...`>`\n    is more associated with generics than `[`...`]`.\n\nOther different spellings of the `:!` position that came up during brainstorming\nbut were not found to be compelling included:\n\n-   `<id>: Type`\n-   `id:# Type`\n-   `id:<> Type`\n-   `id: <Type>`\n-   `generic id: Type`\n\n### `Template` as a type-of-type\n\nWe talked about the alternative of using a keyword like `Auto` or `Template` as\na type-of-type to indicate that a parameter was a template.\n\n```\nfn FieldNames(T: Template) -> String;\n```\n\nThis would be able to be combined with other type-of-types using the `&`\noperator to constrain the allowed types, as in `Container & Template`. The idea\nis that `Auto` or `Template` would act like an interface that contained any\ncalls used by the function that were not in any other interface constraint for\nthat parameter.\n\nIt had two downsides:\n\n-   This approach only worked for type parameters. We would need something else\n    for non-type template parameters.\n-   It didn't seem like you would want to be able to hide an `& Auto` or\n    `& Template` clause by declaring it in a constant:\n\n    ```\n    let CT = Container & Template;\n    fn SurpriseIHaveATemplateParam[T: CT](c: T);\n    ```\n\nThat suggests that the `Auto` or `Template` keyword would not act like other\ntype-of-type expressions and would need special treatment.\n\n## Alternatives not considered\n\nWe never really broke out of the idea that `[`...`]` were for deduced\nparameters. As a result we didn't really consider options where type expressions\nused square brackets for generic parameters, as in `Vector[Int]`, even though\nthat addresses the parsing problems of angle brackets. For example, if we were\nto revisit this decision, we might use three kinds of brackets for the three\ndifferent cases:\n\n-   `<`...`>` for deduced and generic parameters\n-   `[`...`]` for explicit and generic parameters\n-   `(`...`)` for explicit and dynamic parameters\n\nCode would most commonly use square brackets both when declaring and using a\nparameterized type or an interface. Parens would be required for functions, with\ngeneric parameters typically specified using angle brackets.\n\n```\nclass Vector[T: Type] { ... }\nfn CastAVector<T: Type>[DestT: CastFrom[T]](v: Vector[T]) -> Vector[DestT];\nvar from: Vector[i32] = ...;\nvar to: Vector[i64] = CastAVector[i64](from);\n```\n\nOne concern is that use of square brackets will be in the same contexts as\n`[`...`]` will be used for indexing. Another concern is that there is\n[some motivation](http://open-std.org/JTC1/SC22/WG21/docs/papers/2019/p1045r1.html)\nfor putting generic and template parameters together with regular parameters in\nthe `(`...`)` parameter list\n\n[Go ultimately did decided to use square brackets for generics](https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md).\nThis is even though Go also uses square brackets for slices and indexing.\n"
  },
  {
    "path": "proposals/p0680.md",
    "content": "# And, or, not\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/680)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Usage in existing languages](#usage-in-existing-languages)\n    -   [Known issues with punctuation operators](#known-issues-with-punctuation-operators)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Precedence](#precedence)\n    -   [Associativity](#associativity)\n    -   [Conversions](#conversions)\n    -   [Overloading](#overloading)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use punctuation spelling for all three operators](#use-punctuation-spelling-for-all-three-operators)\n    -   [Precedence of AND versus OR](#precedence-of-and-versus-or)\n    -   [Precedence of NOT](#precedence-of-not)\n    -   [Punctuation form of NOT](#punctuation-form-of-not)\n    -   [Two forms of NOT](#two-forms-of-not)\n    -   [Repeated NOT](#repeated-not)\n    -   [AND and OR produce the decisive value](#and-and-or-produce-the-decisive-value)\n\n<!-- tocstop -->\n\n## Problem\n\nLogical AND, OR, and NOT are important building blocks for working with Boolean\nvalues. Carbon should support them.\n\n## Background\n\n### Usage in existing languages\n\nMost mainstream programming languages use one (or both) of two syntaxes for\nthese operators:\n\n-   `&&`, `||`, and `!`. The `&&` and `||` operators were\n    [first used by C](https://www.bell-labs.com/usr/dmr/www/chist.html) to\n    distinguish short-circuiting behavior from that of regular operators. They\n    are now seen in C, C++, C#, Swift, Rust, Haskell, and many more languages.\n    `&&` and `||` invariably short-circuit.\n-   `and`, `or`, and `not`. These are often used by languages with more emphasis\n    on readability and scripting, such as Python, Pascal, Nim, SQL, and various\n    variants of BASIC. In Python, the `and` and `or` operators short-circuit; in\n    Pascal and Visual Basic, they do not, but variants of them do:\n\n    -   `and then` and `or else` in Pascal short-circuit.\n    -   `AndAlso` and `OrElse` in Visual Basic short-circuit.\n\n    C++ recognizes `and`, `or`, and `not` as keywords and treats them as lexical\n    synonyms for `&&`, `||`, and `!`. C provides an `<iso646.h>` standard header\n    that exposes `and`, `or`, and `not` as macros expanding to `&&`, `||`, and\n    `!`.\n\nPerl, Ruby, and Raku permit both syntaxes, giving the punctuation forms higher\nprecedence and the keyword forms lower precedence. Both forms short-circuit.\nRaku also provides `andthen` and `orelse`, but these differ from `and` and `or`\nin what value is produced on short-circuiting, not in whether they\nshort-circuit.\n\nZig provides `and`, `or`, and `!`.\n\n### Known issues with punctuation operators\n\nThe use of `&&` and `||` for short-circuiting logical operators is a common\nsource of error due to the potential for confusion with the bitwise `&` and `|`\noperators. See:\n\n-   [CERT rule EXP46-C: Do not use a bitwise operator with a Boolean-like operand](https://wiki.sei.cmu.edu/confluence/display/c/EXP46-C.+Do+not+use+a+bitwise+operator+with+a+Boolean-like+operand)\n-   ChromiumOS bug prevents login due to `&&` / `&` typo\n    ([news coverage](https://www.theregister.com/2021/07/23/chromebork_bug_google/)).\n\nWe have anecdotal evidence that the `!` operator is hard to see for some\naudiences in some contexts, particularly when adjacent to similar characters:\nparentheses, `I`, `l`, `1`.\n\n## Proposal\n\nCarbon will provide three operators to support logical operations on Boolean\nvalues.\n\n-   `and` provides a short-circuiting logical AND operation.\n-   `or` provides a short-circuiting logical OR operation.\n-   `not` provides a logical NOT operation.\n\nNote that these operators are valid alternative spellings in C++; PR\n[#682](https://github.com/carbon-language/carbon-lang/pull/682) provides a\ndemonstration of what this proposal would look like if applied to the C++ code\nin the Carbon project.\n\n## Details\n\n`and` and `or` are infix binary operators. `not` is a prefix unary operator.\n\n### Precedence\n\n`and`, `or`, and `not` have very low precedence. When an expression appearing as\nthe condition of an `if` uses these operators unparenthesized, they are always\nthe lowest precedence operators in that expression.\n\nThese operators permit any reasonable operator that might be used to form a\nboolean value as a subexpression. In particular, comparison operators such as\n`<` and `==` have higher precedence than all logical operators.\n\nA `not` operator can be used within `and` and `or`, but `and` cannot be used\ndirectly within `or` without parentheses, nor the other way around.\n\nFor example:\n\n```\nif (n + m == 3 and not n < m) {\n```\n\ncan be fully parenthesized as\n\n```\nif (((n + m) == 3) and (not (n < m))) {\n```\n\nand\n\n```\nif (cond1 == not cond2) {\n// ...\nif (cond1 and cond2 or cond3) {\n```\n\nare both errors, requiring parentheses.\n\n### Associativity\n\n`and` and `or` are left-associative. A `not` expression cannot be the operand of\nanother `not` expression -- `not not b` is an error without parentheses.\n\n```\n// OK\nif (not a and not b and not c) { ... }\nif (not (not a)) { ... }\n\n// Error\nif (not a or not b and not c) { ... }\nif (not not a) { ... }\n```\n\n### Conversions\n\nThe operand of `and`, `or`, or `not` is converted to a Boolean value in the same\nway as the condition of an `if` expression. In particular:\n\n-   If we decide that certain values, such as pointers or integers, should not\n    be usable as the condition of an `if` without an explicit comparison against\n    null or zero, then those values will also not be usable as the operand of\n    `and`, `or`, or `not` without an explicit comparison.\n-   If an extension point is provided to determine how to branch on the truth of\n    a value in an `if` (such as by supplying a conversion to a Boolean type),\n    that extension point will also apply to `and`, `or`, and `not`.\n\n### Overloading\n\nThe logical operators `and`, `or`, and `not` are not overloadable. As noted\nabove, any mechanism that allows types to customize how `if` treats them will\nalso customize how `and`, `or`, and `not` treats them.\n\n## Rationale based on Carbon's goals\n\n-   _Code that is easy to read, understand, and write:_\n\n    -   The choice of `and` and `or` improves readability by avoiding the\n        potential for visual confusion between `&&` and `&`.\n    -   The choice of `not` improves readability by avoiding the use of a small\n        and easy-to-miss punctuation character for logical negation.\n    -   Having no precedence rule between `and` and `or` avoids readability\n        problems with expressions involving both operators, by requiring the use\n        of parentheses.\n    -   The use of a keyword rather than punctuation for these operators helps\n        emphasize that they are not regular operators but instead have\n        control-flow semantics.\n    -   Using the same precedence for `not` as for `and` and `or` allows\n        conditions to quickly be visually scanned and for the overall structure\n        and its nested conditions to be identified.\n\n-   _Interoperability with and migration from existing C++ code:_\n    -   The use of the operators `and`, `or`, and `not`, which are keywords with\n        the same meaning in C++, avoids problems with a Carbon keyword colliding\n        with a valid C++ identifier and allows early adoption of the Carbon\n        syntax in C++ codebases.\n    -   While these operators are overloadable in C++, `&&` and `||` are nearly\n        the least-overloaded operators, and `!` is generally only overloaded as\n        a roundabout way of converting to `bool`. There is no known need for\n        Carbon code to call overloaded C++ `operator&&`, `operator||`, or\n        `operator!`, nor for Carbon code to provide such operators to C++. We\n        will need a mechanism for `if`, `and`, `or`, and `not` to invoke\n        (possibly-`explicit`) `operator bool` defined in C++, but that's outside\n        the scope of this proposal.\n\n## Alternatives considered\n\n### Use punctuation spelling for all three operators\n\nWe could follow the convention established by C and spell these operators as\n`&&`, `||`, and `!`.\n\nAdvantage:\n\n-   This would improve familiarity for people comfortable with this operator\n    set.\n\nDisadvantages:\n\n-   The use of keywords rather than punctuation gives a hint that `and` and `or`\n    are not merely performing a computation -- they also affect control flow.\n-   The `!` operator is known to be hard to see for some readers.\n-   If we also support `&` and `|` operators, there is a known risk of confusion\n    between `&&` and `&` and between `||` and `|`.\n-   If we want to change the precedence rules, using a different syntax can\n    serve as a reminder that these operators do not behave like the `&&`, `||`,\n    and `!` operators.\n-   `&&`, `||`, and `!` are likely to be harder to type than `and`, `or`, and\n    `not` on at least most English keyboard layouts, due to requiring the use of\n    the Shift key and reaching outside the letter keys.\n\n### Precedence of AND versus OR\n\nMost languages give their AND operator higher precedence than their OR operator:\n\n```c++\nif (a && b || c && d) { ... }\n// ... means ...\nif ((a && b) || (c && d)) { ... }\n```\n\nThis makes sense when viewed the right way: `&&` is the multiplication of\nBoolean algebra and `||` is the addition, and multiplication usually binds\ntighter than addition.\n\nWe could do the same. However, this precedence rule is not reliably known by a\nsignificant fraction of developers despite having been present across many\nlanguages for decades, leading to common recommendations to enable compiler\nwarnings for the first form in the above example, suggesting to rewrite it as\nthe second form. This therefore fails the test from proposal\n[#555: when to add precedence edges](/proposals/p0555.md#when-to-add-precedence-edges).\n\n### Precedence of NOT\n\nWe could give the `not` operator high precedence, mirroring the behavior in C++.\nIn this proposal, the `not` operator has the same precedence rules as `and` and\n`or`, which may be inconvenient for some uses. For example:\n\n```\nvar x: Bool = cond1 == not cond2;\n```\n\nis invalid in this proposal and requires parentheses, and\n\n```\nvar y: Bool = not cond1 == cond2;\n```\n\nis equivalent to\n\n```\nvar y: Bool = cond1 != cond2;\n```\n\nwhich may not be what the developer intended.\n\nHowever, giving `not` higher precedence would result in a more complex rule and\nwould break the symmetry between `and`, `or`, and `not`.\n\n### Punctuation form of NOT\n\nWe could use the spelling `!` for the NOT operator instead of `not`.\n\nThe syntax of the `not` operator may be harder to read than a `!` operator for\nsome uses. For example, when its operand is parenthesized, because it contains a\nnested `and` or `or`:\n\n```\nif (not (thing1 and thing2) or\n    not (thing3 and thing4)) {\n```\n\nAlso, the spelling of the `!=` operator is harder to justify if there is no `!`\noperator.\n\nHowever:\n\n-   Changing the syntax would break the symmetry between `and`, `or`, and `not`.\n-   Python uses this set of keywords and has a `!=` operator, and that doesn't\n    appear to cause confusion in practice.\n-   `not` may be easier to read than `!` in some uses, and easier to pick out of\n    surrounding context.\n-   `!` is being used to indicate early substitution in generics, so avoiding\n    its use here may avoid overloading the same syntax for multiple purposes.\n-   A function-like `not (...)` may better conform to reader expectations than a\n    `!(...)` expression.\n\n### Two forms of NOT\n\nWe could combine the two previous alternatives, and introduce both a\nlow-precedence `not` operator and a high-precedence `!` operator.\n\nThis would allow us to provide both a convenient `!` operator for use in\nsubexpressions and a consistent `not` keyword that looks and behaves like `and`\nand `or`.\n\nHowever, including both operators would either lead to one of the forms being\nunused or to the extra developer burden of style rules suggesting when to use\neach. Also, it may be surprising to provide a `!` operator but not `&&` and `||`\noperators.\n\n### Repeated NOT\n\nWe could permit the syntax `not not x` as an idiom for converting `x` to a\nBoolean type. However, we hope that a clearer syntax for that will be available,\nsuch as perhaps `x as Bool`. In the presence of such syntax, `not not x` would\nbe an anti-pattern, and may indicate a bug due to an unintentionally repeated\n`not` operator. Per\n[#555: when to add precedence edges](/proposals/p0555.md#when-to-add-precedence-edges),\nwhen in doubt, we omit the precedence rule and wait for real-world experience.\n\n### AND and OR produce the decisive value\n\nWe could make the AND and OR operator produce the (unconverted) value that\ndetermined the result, rather than producing a Boolean value. For example, given\nnullable pointers `p` and `q`, and assuming that we can test a pointer value for\nnonnullness with `if (p)`, we could treat `p or q` as producing `p` if `p` is\nnonnull and `q` otherwise.\n\nThis is the approach taken by several scripting languages, notably Python, Perl,\nand Raku. It is also the approach taken by `std::conjunction` and\n`std::disjunction` in C++.\n\nAdvantages:\n\n-   Provides a syntactic method to compute the first \"truthy\" or last \"falsy\"\n    value in a list.\n\nDisadvantages:\n\n-   The resulting code may be harder to read and understand, especially when the\n    value is passed onto a function call.\n-   Requires all conditions in a chained conditional to have a common type, or\n    the use of a fallback rule in the case where there is no common type.\n-   When combined with type deduction, an unexpected type will often be deduced;\n    for example, `var x: auto = p and q;` may deduce `x` as having pointer type\n    instead of Boolean type.\n"
  },
  {
    "path": "proposals/p0702.md",
    "content": "# Comparison operators\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/702)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Terminology](#terminology)\n    -   [Usage in existing languages](#usage-in-existing-languages)\n    -   [Three-way comparisons](#three-way-comparisons)\n    -   [Chained comparisons](#chained-comparisons)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Precedence](#precedence)\n    -   [Associativity](#associativity)\n    -   [Built-in comparisons and implicit conversions](#built-in-comparisons-and-implicit-conversions)\n        -   [Consistency with implicit conversions](#consistency-with-implicit-conversions)\n        -   [Comparisons with constants](#comparisons-with-constants)\n        -   [Performance](#performance)\n    -   [Overloading](#overloading)\n    -   [Default implementations for basic types](#default-implementations-for-basic-types)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Alternative symbols](#alternative-symbols)\n    -   [Chained comparisons](#chained-comparisons-1)\n    -   [Convert operands like C++](#convert-operands-like-c)\n    -   [Provide a three-way comparison operator](#provide-a-three-way-comparison-operator)\n    -   [Allow comparisons as the operand of `not`](#allow-comparisons-as-the-operand-of-not)\n\n<!-- tocstop -->\n\n## Problem\n\nWe need to be able to compare values for equality, and to compare ordered values\nfor relative ordering.\n\n## Background\n\n### Terminology\n\nWe refer to tests that check whether two values are the same or different as\n_equality_ comparisons, and to tests that determine the relative ordering of two\nvalues as _relational_ comparisons.\n\n### Usage in existing languages\n\nThere is near-universal convention on the use of the following symbols for\nrelational operators:\n\n-   `<`, `<=`, `>`, and `>=` perform ordered comparisons (less than, less than\n    or equal to, greater than, greater than or equal to).\n\nThere are rare exceptions in somewhat esoteric languages: some languages use `≤`\nand `≥`, but these are not straightforward to type for many potential Carbon\ndevelopers.\n\nFor equality operators, there is some divergence but still a very strong trend:\n\n-   C-family languages, Rust, Swift, Kotlin, Zig, Nim, Ruby, etc. use `==` for\n    equality comparison and `!=` for inequality comparison.\n-   Some languages, such as ALGOL, APL, BASIC, and PL/I, use `=` as equality\n    comparison, with some using a different symbol (such as `:=` or `<-`) for\n    assignment and others distinguishing assignment from equality comparison\n    based on context.\n-   Haskell and Fortran use `==` for \"equal to\" and `/=` for \"not equal to\". The\n    latter is intended to resemble a ≠ symbol.\n-   Some languages, such as Pascal and BASIC, use `<>` for inequality\n    comparison. Python 2 permits this as a synonym for `!=`.\n-   Perl uses `eq` and `ne` for string comparisons; some shells and UNIX `test`\n    use `-eq` and `-ne` for integer comparisons.\n\nSome languages support multiple different kinds of equality comparison, such as\nboth a value comparison (typically `==`) and an object identity comparison\n(typically `===` or `is`). Some languages that freely convert between numbers\nand strings have different operators to perform a string comparison versus a\nnumeric comparison. Fortran has custom `.eqv.` and `.neqv.` for equality\ncomparisons of Boolean values.\n\nSome languages have synonyms for equality operators. For example, Fortran allows\n`.eq.`, `.ne.`, `.gt.`, and so on, as synonyms for `==`, `/=`, `>`, and so on.\nThis appears to be historical: FORTRAN 77 had only the dotted forms of these\noperators.\n\n### Three-way comparisons\n\nC++ has three-way comparisons, written using the `<=>` operator. These provide a\nuseful mechanism to allow overloading the behavior of relational comparisons\nwithout defining four separate operator overloads for relational comparisons.\n\nSimilarly, Python provides a `__cmp__` special method that can be used to\nimplement all equality and relational comparisons.\n\n### Chained comparisons\n\nPython permits comparisons to be chained: that is, `a < b <= c` is interpreted\nas `a < b and b <= c`, except that `b` is evaluated only once. In most C-family\nlanguages, that expression is instead interpreted as `(a < b) <= c`, which\ncomputes the value of `a < b`, maps `false` to `0` and `true` to `1`, then\ncompares the result to `c`.\n\n## Proposal\n\nCarbon will provide the following operators:\n\n-   Equality comparison operators: `==` and `!=`.\n-   Relational comparison operators: `<`, `<=`, `>`, `>=`.\n\nEach has the obvious mathematical meaning, where `==` means =, `!=` means ≠,\n`<=` means ≤, and `>=` means ≥.\n\nThere will be no three-way comparison operator symbol. The interface used to\nsupport overloading comparison operators will provide a named function to\nperform three-way comparisons.\n\nChained comparisons are an error: a comparison expression cannot appear as an\nunparenthesized operand of another comparison operator.\n\nFor built-in types, we will follow these rules:\n\n-   Behave consistently with implicit conversions: if an operation is valid\n    between built-in types `T` and `U`, then it is valid between built-in types\n    that implicitly convert to `T` and `U`.\n-   Never invent an intermediate type that is larger than both operand types.\n-   A comparison produces either a mathematically correct answer or a\n    compilation error.\n\nThe first two rules are expected to also apply for other built-in operators,\nsuch as arithmetic. The third rule is specific to comparisons.\n\nOne consequence of the first rule is that we do not convert operands in a way\nthat might lose information. This is generally also implied by the third rule.\n\n## Details\n\nAll six operators are infix binary operators. For standard Carbon types, they\nproduce a `Bool` value.\n\n### Precedence\n\nThe comparison operators are all at the same precedence level. This level is\nlower than operators used to compute (non-Boolean) values, higher than the\nlogical operators `and` and `or`, and incomparable with the precedence of `not`.\n\nFor example, this is OK:\n\n```\nif (n + m * 3 < n * n and 3 < m and m < 6) {}\n```\n\n... but these are errors:\n\n```\n// Error, ambiguous: `(not a) == b` or `not (a == b)`?\nif (not a == b) {}\n// Error, requires parentheses: `a == (not b)`.\nif (a == not b) {}\n// Error, requires parentheses: `not (f < 5.0)`.\nif (not f < 5.0) {}\n```\n\n### Associativity\n\nThe comparison operators are non-associative. For example:\n\n```\n// Error, need `3 < m and m < 6`.\nif (3 < m < 6) {}\n// Error, need `a == b and b == c`.\nif (a == b == c) {}\n// Error, need `(m > 1) == (n > 1)`.\nif (m > 1 == n > 1) {}\n```\n\n### Built-in comparisons and implicit conversions\n\nBuilt-in comparisons are permitted:\n\n-   when both operands are of standard Carbon integer types (`Int(n)` or\n    `Unsigned(n)`), or\n-   when both operands are of standard Carbon floating-point types (`Float(n)`),\n    or\n-   when one operand is of floating-point type and the other is of integer type,\n    if all values of the integer type can be exactly represented in the\n    floating-point type\n\nIn each case, the result is the mathematically-correct answer. This applies even\nwhen comparing `Int(n)` with `Unsigned(m)`.\n\nFor example:\n\n```\n// The value of `v` is True, because `a` is less than `b`, even though the\n// result of either an `i32` comparison or a `u32` comparison would be False.\nfn f(a: i32, b: u32) -> Bool { return a < b; }\nlet v: Bool = f(-1, 4_000_000_000);\n\n// This does not compile, because `i64` values in general (and 10^18 in\n// particular) are not exactly representable in the type `f32`.\nlet f: f32 = 1.0e18;\nlet n: i64 = 1_000_000_000_000_000_000;\nlet w: Bool = f == n;\n```\n\nComparisons involving integer and floating-point constants are not covered by\nthese rules and are [discussed separately](#comparisons-with-constants).\n\n#### Consistency with implicit conversions\n\nAs specified in [#820](https://github.com/carbon-language/carbon-lang/pull/820),\nwe support the following implicit conversions:\n\n-   from `Int(n)` to `Int(m)` if `m > n`,\n-   from `Unsigned(n)` to `Int(m)` or `Unsigned(m)` if `m > n`,\n-   from `Float(n)` to `Float(m)` if `m > n`, and\n-   from `Int(n)` to `Float(m)` if `Float(m)` can represent all values of\n    `Int(n)`.\n\nThese rules can be summarized as: a type `T` can be converted to `U` if every\nvalue of type `T` is a value of type `U`.\n\nAdditionally [#820](https://github.com/carbon-language/carbon-lang/pull/820)\npermits conversions from certain kinds of integer and floating-point constants\nto `Int(n)` and `Float(n)` types if the constant can be represented in the type.\n\nAll built-in comparisons can be viewed as performing implicit conversions on at\nmost one of the operands in order to reach a suitable pair of identical or very\nsimilar types, and then performing a comparison on those types. The target types\nfor these implicit conversions are, for each suitable value `n`:\n\n-   `Int(n)` vs `Int(n)`\n-   `Unsigned(n)` vs `Unsigned(n)`\n-   `Int(n)` vs `Unsigned(n)`\n-   `Unsigned(n)` vs `Int(n)`\n-   `Float(n)` vs `Float(n)`\n\nThere will in general be multiple combinations of implicit conversions that will\nlead to one of the above forms, but we will arrive at the same result regardless\nof which is selected, because all comparisons are mathematically correct and all\nimplicit conversions are lossless. Implementations are expected to do whatever\nis most efficient: for example, for `u16 < i32` it is likely that the best\nchoice would be to promote the `u16` to `i32`, not `u32`.\n\nBecause we only ever convert at most one operand, we never use an intermediate\ntype that is larger than both input types. For example, both `i32` and `f32` can\nbe implicitly converted to `f64`, but we do not permit comparisons between `i32`\nand `f32` even though we could perform those comparisons in `f64`. If such\ncomparisons were permitted, the results could be surprising:\n\n```\n// OK, i32 can exactly represent this value.\nvar n: i32 = 2_000_000_001;\n// OK, this value is within the representable range for f32.\nvar f: f32 = 2_000_000_001.0;\n// This comparison could compare unequal, because f32 cannot exactly represent\n// the value 2,000,000,001.\nif (n == f) { ... }\n// OK with explicit cast, but may still compare unequal.\nif (n == f as f64) { ... }\nif (n as f64 == f) { ... }\n```\n\nThe two kinds of mixed-type comparison may be [less efficient](#performance)\nthan the other kinds due to the slightly wider domain.\n\nNote that this approach diverges from C++, which would convert both operands to\na common type first, sometimes performing a lossy conversion potentially giving\nan incorrect result, sometimes converting both operands, and sometimes using a\nwider type than either of the operand types.\n\n#### Comparisons with constants\n\nAs described in [#820](https://github.com/carbon-language/carbon-lang/pull/820),\ninteger constants can be implicitly converted to any integer or floating-point\ntype that can represent their value, and floating-point constants can be\nimplicitly converted to any floating-point type that can represent their value.\nWe permit the following comparisons involving constants:\n\n-   A constant can be compared with a value of any type to which it can be\n    implicitly converted.\n-   Any two constants can be compared, even if there is no type that can\n    represent both.\n\nNote that this disallows comparisons between, for example, `i32` and an integer\nliteral that cannot be represented in `i32`. Such comparisons would always be\ntautological. This decision should be revisited if it proves problematic in\npractice, for example in templated code where the literal is sometimes in range.\n\n#### Performance\n\nThe choice to give correct results for signed/unsigned comparisons has a\nperformance impact in practice, because it exposes operations that some\nprocessors do not currently directly support.\n[Sample microbenchmarks](https://quick-bench.com/q/1_xA8G_jXci_yeOKt0WgCc6eGN4)\nfor implementations of several operations show the following performance on\nx86_64:\n\n| Operation   | Mathematical comparison time | C++ comparison time | Ratio |\n| ----------- | ---------------------------- | ------------------- | ----- |\n| `i64 < u64` | 1636                         | 798                 | 2.0x  |\n| `u64 < i64` | 1956                         | 798                 | 2.5x  |\n\nThe execution times here are computed as operation time minus no-op time.\n\nThe mixed-type operations typically have 2-2.5x the execution time of the\nsame-type operations. However, this is a predictable performance change, and can\nbe controlled by the developer by converting the operands to a suitable type\nprior to the conversion if a faster same-type comparison is preferred over a\ncorrect mixed-type comparison.\n\nThe above comparison attempts to demonstrate a worst-case difference. In many\ncases, better code can be generated for the mixed-type comparison. For example,\nwhen\n[branching on the result of the comparison](https://quick-bench.com/q/mXJiHK3_RcCH4fgB88phQscLu88),\nthe difference is significantly reduced:\n\n| Operation   | Mathematical comparison time | C++ comparison time | Ratio |\n| ----------- | ---------------------------- | ------------------- | ----- |\n| `i64 < u64` | 996                          | 991                 | 1.0x  |\n| `u64 < i64` | 1973                         | 997                 | 2.0x  |\n\n### Overloading\n\nSeparate interfaces will be provided to permit overloading equality and\nrelational comparisons. The exact design of those interfaces is left to a future\nproposal. As non-binding design guidance for such a proposal:\n\n-   The interface for equality comparisons should primarily provide the ability\n    to override the behavior of `==`. The `!=` operator can optionally also be\n    overridden, with a default implementation that returns `not (a == b)`.\n    Overriding `!=` separately from `==` is expected to be used to support\n    floating-point NaN comparisons and for C++ interoperability.\n-   The interface for relational comparisons should primarily provide the\n    ability to specify a three-way comparison operator. The individual\n    relational comparison operators can optionally be overridden separately,\n    with a default implementation in terms of the three-way comparison operator.\n    This facility is expected to be used primarily to support C++\n    interoperability.\n-   Overloaded comparison operators may wish to produce a type other than\n    `Bool`, for uses such as a vector comparison producing a vector of `Bool`\n    values. We should decide whether we wish to support such uses.\n\n### Default implementations for basic types\n\nIn addition to being defined for standard Carbon numeric types, equality and\nrelational comparisons are also defined for all \"data\" types:\n\n-   Tuples.\n-   Structs (structural data classes).\n-   Classes implementing an interface that identifies them as data classes.\n\nRelational comparisons for these types provide a lexicographical ordering. This\nproposal defers to\n[#710](https://github.com/carbon-language/carbon-lang/issues/710) for details on\ncomparison support for classes.\n\nIn each case, the comparison is only available if it is supported by all element\ntypes.\n\nThe `Bool` type should be treated as a choice type, and so should support\nequality comparisons and relational comparisons if and only if choice types do\nin general. That decision is left to a future proposal.\n\n## Rationale based on Carbon's goals\n\n-   _Performance-critical software:_\n\n    -   The use of a three-way comparison as the central primitive for\n        overloading relational comparisons provides predictable, composable\n        performance for comparing hierarchical data structures.\n    -   The performance of mixed comparisons may be slower than in C++, but this\n        is because it's performing a different operation. This performance\n        change is predictable, and can be controlled by the programmer by\n        performing suitable non-value-preserving casts to a common type prior to\n        the comparison.\n\n-   _Code that is easy to read, understand, and write:_\n\n    -   The chosen precedence and associativity rules aim to avoid bugs and\n        ensure the code does what it appears to do, requiring parentheses in\n        cases where the intent is unclear.\n    -   The choice to not perform lossy conversions on operands of a comparison\n        operator removes a source of bugs caused by unintended lossy\n        conversions.\n\n-   _Interoperability with and migration from existing C++ code:_\n\n    -   The use of the chosen operator symbols exactly matches C++, reducing\n        friction for developers and code moving between the two languages, and\n        for interoperability.\n\n## Alternatives considered\n\n### Alternative symbols\n\nWe could use `/=` instead of `!=` for not-equal comparisons.\n\nAdvantages:\n\n-   Avoids overloading `!` for both \"not equals\" and template/generic use in\n    `:!` bindings.\n-   There is no other usage of `!` meaning \"not\" in the language because we use\n    a `not` operator.\n\nDisadvantages:\n\n-   Unfamiliar to C++ programmers.\n-   `a /= b` would likely be expected to mean an `a = a / b` compound\n    assignment.\n-   Breaks consistency with Python, which uses `not` for logical negation and\n    `!=` for inequality comparison.\n\nWe could use `=/=` instead of `!=` for not-equal comparisons.\n\nAdvantages:\n\n-   As above; also `=/=` looks like an `==` with a line through the middle.\n\nDisadvantages:\n\n-   This would be inventive and unlike all other languages. As above, breaks\n    consistency with Python.\n-   This would make `=/=` one character longer, and harder to type on US-ASCII\n    keyboards because the keys are distant but likely to be typed with the same\n    finger.\n\n### Chained comparisons\n\nWe could support Python-like chained comparisons.\n\nAdvantages:\n\n-   Small ergonomic improvement for range comparisons.\n-   Middle operand is evaluated only once.\n\nDisadvantages:\n\n-   Using the middle expression as an argument to two different functions may\n    create problems, as the value will need to be stored somewhere, potentially\n    changing the semantics of the operator expression as we can no longer move\n    from the operand.\n-   Both short-circuiting behavior and non-short-circuiting behavior will be\n    surprising and unintuitive to some. The short-circuiting option will\n    introduce control flow without a keyword to announce it, which goes against\n    our design decision to use a keyword for `and` and `or` to announce the\n    control flow. The non-short-circuiting option will evaluate subexpressions\n    unnecessarily, which creates a tension with our performance goal.\n-   Experienced C++ developers may expect a different behavior, such as\n    `a < b == cmp` comparing the result of `a < b` against the Boolean value\n    `cmp`.\n\nSee also the ongoing discussion in\n[#451](https://github.com/carbon-language/carbon-lang/issues/451).\n\n### Convert operands like C++\n\nWe could convert the operands of comparison operators in a way that's equivalent\nto C++'s behavior.\n\nAdvantages:\n\n-   May ease migration from C++.\n-   May allow programmers to reuse some intuition, for example when comparing\n    floating-point values against integer values.\n-   Allows more efficient machine code to be generated for source code that\n    takes no special care about the types of comparison operands.\n-   Improves performance predictability for C++ developers unfamiliar with\n    Carbon's rules.\n\nDisadvantages:\n\n-   Produces incorrect results.\n-   Does not provide a simple syntax for correct mixed-type comparisons.\n\n### Provide a three-way comparison operator\n\nWe could provide a symbol for three-way comparisons, such as C++20's `<=>`.\n\nAdvantages:\n\n-   The use of a symbol rather than a named member of an interface for this\n    functionality may ease migration from C++20.\n\nDisadvantages:\n\n-   Reserves a symbol for an operation that should not be used directly except\n    in special circumstances, and that will produce a nuanced type even when\n    comparing standard Carbon types such as `f32`.\n\n### Allow comparisons as the operand of `not`\n\nWe could permit comparisons to appear as the immediate operand of `not` without\nparentheses.\n\nAdvantages:\n\n-   Provides an easier syntax for floating-point comparisons where the desired\n    result for a NaN operand is `True` rather than `False`: `not f < 5.0`.\n\nDisadvantages:\n\n-   Introduces ambiguity when comparing Boolean values: `not cond1 == cond2`\n    might intend to compare `not cond1` to `cond2` rather than comparing\n    `cond1 != cond2`.\n"
  },
  {
    "path": "proposals/p0720.md",
    "content": "# Property naming in C++\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/720)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Style](#style)\n    -   [Properties](#properties)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Disallow \"setters\"](#disallow-setters)\n    -   [Disallow mutable accessors](#disallow-mutable-accessors)\n    -   [Looser restrictions on property method performance](#looser-restrictions-on-property-method-performance)\n    -   [Require trailing `_` only for property data members](#require-trailing-_-only-for-property-data-members)\n\n<!-- tocstop -->\n\n## Problem\n\nThis proposal aims to address two problems:\n\n-   Our current C++ style rules are prone to name conflicts, particularly\n    between types and accessors.\n-   There is preliminary interest in Carbon providing \"properties\" as a language\n    feature. It would be useful to be able to experiment with the style and API\n    effects of such a feature in our C++ code.\n\n## Background\n\n### Style\n\nOur C++ style rules currently require all functions (including accessors) and\nall types to have `CamelCase` names. However, this creates a nontrivial risk of\nname collisions. To take two examples:\n\n-   The base class\n    [`Carbon::Pattern`](https://github.com/carbon-language/carbon-lang/blob/ebd6c7afa91a1a02961b72d619fba630d8fbfbff/executable_semantics/ast/pattern.h#L25)\n    defines a `Kind` enum, which identifies the concrete type of a `Pattern`\n    object, as part of its support for\n    [LLVM-style RTTI](https://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html). It\n    also needs to provide an accessor that exposes the `Kind` of a `Pattern`\n    object, so that client code can `switch` on it rather than using virtual\n    dispatch. The most natural name for that accessor would be `Kind`, but C++\n    doesn't allow us to use the same name for both a type and a function in the\n    same scope. Instead, the accessor is called `Tag`, but that's an entirely\n    ad-hoc solution: there happened to be a synonymous term available, so we\n    arbitrarily chose one for the type and the other for the function.\n-   The class\n    [`Carbon::ExpressionPattern`](https://github.com/carbon-language/carbon-lang/blob/ebd6c7afa91a1a02961b72d619fba630d8fbfbff/executable_semantics/ast/pattern.h#L181)\n    adapts an `Expression` to behave as a `Pattern`. The underlying `Expression`\n    is exposed by an accessor, which is named `Expression`. That function name\n    shadows the type name within the class, so the type must instead be referred\n    to by its fully-qualified name `Carbon::Expression`.\n\nAs these examples illustrate, there are occasional situations where the best\nname for an accessor is the same word (or words) as the name of its return type,\nbecause in context, that type fully describes what the accessor returns. Since\nour style rules require those words to be turned into identifiers in the same\nway (`CamelCase` rather than `snake_case`), this results in shadowing, or an\noutright name collision.\n\n### Properties\n\nSome programming languages allow classes to define\n[property members](<https://en.wikipedia.org/wiki/Property_(programming)>),\nwhich are accessed using data member syntax, but allow the type to implement\nthose accesses using procedural code. Properties can thus offer the clarity and\nconvenience of public data members, while retaining many of the advantages of\nprivate data with \"getters\" and \"setters\".\n\nHowever, the fact that properties can be implemented using arbitrary procedural\ncode means that they are capable of behaving in ways that would be very\nsurprising to a user who thinks of them as ordinary data members, such as\nperforming large amounts of computation, blocking on I/O, or causing observable\nside effects when the property is being read. Usage of properties therefore\ninvolves a style tradeoff between expressive power and user surprise.\n\nProperties are a popular feature of several of Carbon's peer languages, so we\nare likely to eventually explore the possibility of adding them to Carbon. When\nwe do, it may be useful to have some experience with the style tradeoffs that\nproperties create.\n\n## Proposal\n\nI propose to allow C++ classes in the Carbon project to provide methods that are\nnamed like properties, so long as they behave like properties. I also propose to\nrequire data members to have a trailing `_`. See the changes to\n`cpp_style_guide.md` for further specifics.\n\n## Rationale based on Carbon's goals\n\nAvoiding the name conflicts will incrementally advance our \"Language tools and\necosystem\" goals by making those tools somewhat easier to implement.\n\nEarly experimentation with properties in C++ could help us design Carbon\nproperties to better address several of Carbon's goals, especially \"code that is\neasy to read, understand, and write\".\n\n## Alternatives considered\n\n### Disallow \"setters\"\n\nWe could narrow the style rule to disallow `set_` methods.\n\nAdvantages:\n\n-   This minimizes the likely syntactic divergence from Carbon properties,\n    because reading a Carbon property will probably look very much like an\n    accessor call, minus the `()`, but assigning to a Carbon property will\n    probably look like an assignment, not a `set_` method call.\n\nDisadvantages:\n\n-   This would lead to inconsistencies where a `foo_bar()` accessor is paired\n    with a `SetFooBar()` setter.\n-   This would prevent us from gaining experience that could shed light on the\n    design of mutable properties in Carbon.\n\n### Disallow mutable accessors\n\nWe could narrow the style rule to disallow property accessors that provide\nnon-const access to the property.\n\nAdvantages:\n\n-   It would be a more narrow feature to allow in our C++ code.\n-   Carbon doesn't yet have a property design and we don't know the extent or\n    mechanisms it might use for mutable access.\n-   In C++, mutable accessors directly expose the underlying storage, removing\n    most abstraction opportunities.\n\nDisadvantages:\n\n-   This would prevent us from resolving name collisions in cases that involve\n    in-place mutation, and lead to inconsistencies where a `foo_bar()` const\n    accessor is paired with a `FooBar()` (or perhaps `MutableFooBar()`)\n    non-const accessor.\n-   This would prevent us from gaining experience that could shed light on the\n    design of mutable properties in Carbon.\n\n### Looser restrictions on property method performance\n\nWe could allow methods to use property-like naming, even if their performance is\nsubstantially worse than the cost of accessing a data member, so long as the\noverall performance of the code calling the method is likely to be comparable.\n\nFor example, this could permit property methods to return strings by value, even\nthough that requires linear time in the length of the string, because the\nsubsequent usage of the string will very likely be linear time as well, in which\ncase there is no overall asymptotic slowdown.\n\nAdvantages:\n\n-   It would allow us to define methods that behave like \"computed properties\"\n    for types like strings that are not fixed-size, but that are typically\n    treated as single values rather than collections.\n\nDisadvantages:\n\n-   It would be a substantially more subjective rule, since it involves\n    guesswork about what usages are likely.\n-   It would carry a greater risk of user surprise.\n\n### Require trailing `_` only for property data members\n\nIt's necessary to have trailing `_`s (or some equivalent convention) on data\nmembers that provide storage for properties, because otherwise their names would\ncollide with the names of member accessors. However, we could continue to forbid\na trailing `_` on all other data members.\n\nAdvantages:\n\n-   This would be a more minimal change to our existing style, and in particular\n    it would avoid putting any existing code out of compliance with the style\n    guide.\n\nDisadvantages:\n\n-   It might be harder to predict and internalize which data members have a\n    trailing `_`.\n-   The trailing `_` can provide readability benefits even for non-property\n    members, by explicitly marking member accesses in a way that distinguishes\n    them from local variable accesses.\n"
  },
  {
    "path": "proposals/p0722.md",
    "content": "# Nominal classes and methods\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/722)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Method syntax](#method-syntax)\n        -   [Rationale](#rationale)\n            -   [Full receiver type](#full-receiver-type)\n            -   [Method names line up](#method-names-line-up)\n            -   [Receiver in square brackets](#receiver-in-square-brackets)\n            -   [Receiver parameter is named `me`](#receiver-parameter-is-named-me)\n            -   [Keyword to indicate pass by address](#keyword-to-indicate-pass-by-address)\n    -   [Marking mutating methods at the call site](#marking-mutating-methods-at-the-call-site)\n    -   [Differences between functions and methods](#differences-between-functions-and-methods)\n    -   [Specifying linkage as part of the access modifier](#specifying-linkage-as-part-of-the-access-modifier)\n    -   [Nominal data class](#nominal-data-class)\n    -   [Let constants](#let-constants)\n\n<!-- tocstop -->\n\n## Problem\n\nWe need facilities for defining new nominal\n[record types](<https://en.wikipedia.org/wiki/Record_(computer_science)>) in\nCarbon. They will need to support object-oriented features such as methods.\n\n## Background\n\nThis is a follow up to\n[#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561)\nwhich laid a foundation.\n\n## Proposal\n\nThe proposal is to update [docs/design/classes.md](/docs/design/classes.md) as\ndescribed in [this PR](https://github.com/carbon-language/carbon-lang/pull/701).\n\n## Rationale based on Carbon's goals\n\nThis particular proposal is focusing on\n[the Carbon goal](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\nthat code is \"easy to read, understand, and write.\" Future proposals will\naddress other aspects of the class type design such as performance.\n\n## Alternatives considered\n\n### Method syntax\n\nThe proposed method syntax was decided in question-for-leads issue\n[#494: Method syntax](https://github.com/carbon-language/carbon-lang/issues/494).\n\nA wide variety of alternatives were considered:\n\n-   Using a different introducer such as `method` to distinguish methods from\n    functions.\n-   Putting a pattern to match the receiver before the method name.\n-   Omitting either the receiver name or the receiver type.\n-   Allowing the user to specify the receiver name instead of using a parameter\n    named `me` to indicate it is a method.\n-   Using syntax between `fn` and the method name to indicate that it is a\n    method, and whether the method takes a value or the address of the receiver.\n-   Using a keyword to indicate that the first parameter is the receiver, as in\n    [C++'s \"Deducing `this`\" proposal](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r6.html).\n-   Using a delimiter in the parameter list after the receiver type, but the\n    main choice of `;` seemed pretty subtle.\n-   Putting the receiver pattern in a separate set of brackets. This could be an\n    additional set of parens `(`...`)` before the explicit parameter list. Or\n    the deduced parameters could be put in angle brackets `<`...`>` and the\n    receiver in square brackets `[`...`]`.\n\nExamples:\n\n```\nmethod (this: Self*) Set(n: Int);\nfn [Me*].Set(n: Int);\nfn ->Set(n: Int);\nfn& Set(n: Int);\nfn &Set(s: Self*, n: Int);\nfn Set(this self: Self*, n: Int);\nfn Set[this self: Self*](n: Int);\nfn Set(self: Self*; n: Int);\nfn Set(self: Self*)(n: Int);\n```\n\nNote: These examples are written using the parameter syntax decided in\n[issue #542](https://github.com/carbon-language/carbon-lang/issues/542), though\nthat does not match the syntax used in the discussion at the time.\n\n#### Rationale\n\n##### Full receiver type\n\nWe wanted the option to specify the type of the receiver. In C++, the type of\nthis is controlled by way of special syntax, such as putting a `const` keyword\nat the end of the method declaration. We wanted to treat the receiver type more\nconsistently with other parameter types, like is being considered in\n[C++'s \"Deducing `this`\" proposal](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r6.html).\nThat proposal also showed the value of including the entire type, rather than\njust part such as whether the parameter would be passed by value or address. We\nalready plan to use this feature to conditionally include methods based on\nwhether parameters to the type satisfy additional constraints. In this example,\n`FixedArray(T, N)` has a `Print()` method if `T` is `Printable`:\n\n```\nclass FixedArray(T:! Type, N:! Int) {\n  // ...\n  fn Print[me: FixedArray(P:! Printable, N)]() { ... }\n}\n```\n\nWe did consider the option of making the type of the receiver optional. This is\nnot what we decided to try first, but is an idea we would consider in the\nfuture.\n\n##### Method names line up\n\nUsing the same introducer `fn` as functions, as decided in\n[issue #463](https://github.com/carbon-language/carbon-lang/issues/463), along\nwith the method name immediately afterwards means that function and method names\nline up in the same column visually.\n\n```\nstruct IntContainer {\n  // Non-methods for building instances\n  fn MakeFromInts ... -> IntContainer;\n  fn MakeRepeating ... -> IntContainer;\n\n  // Methods\n  fn Size ... -> Int;\n  fn First ... -> Int;\n\n  fn Clear ...;\n  fn Append ...;\n}\n```\n\nThis is to ease scanning and to put the most important information up front.\n\nWe also considered using another 2-character introducer that would distinguish\nmethods from associated functions, like `me`, but it did not garner much\nsupport. The name `me` was not evocative enough of \"method\", and people\ngenerally preferred matching other function declarations. We also considered\nusing different introducers to communicate whether the receiver was passed by\nvalue or by address, for example `ro` for \"read-only\" and `rw` for \"read-write\".\n\n##### Receiver in square brackets\n\nPutting the receiver pattern inside the explicit parameter list, as is done in\nPython, would lead to an unfortunate mismatch between the arguments listed at\nthe call and the function declaration. That motivated putting the receiver\npattern inside square brackets (`[`...`]`) with deduced parameters. There were\nconcerns, however, that this parameter did not act like deduced parameters.\n\n##### Receiver parameter is named `me`\n\nHaving the receiver name be fixed is helpful for consistency. This benefits\nreaders, and simplifies copying or moving code between functions. A fixed\nreceiver name also allows us to identify the receiver pattern in the function\ndeclaration, and identify it as a method instead of an ordinary function\nassociated with the type, like\n[static methods in C++](<https://en.wikipedia.org/wiki/Static_(keyword)#Static_method>).\n\nFinally, we wanted the bodies of methods to access members of the object using\nan explicit member access. This means we need the name used to access members to\nbe short, and so we chose the name `me`.\n\n##### Keyword to indicate pass by address\n\nWe considered using just whether the receiver type was a pointer type to\nindicate whether the receiver was passed by address, but we preferred type\ninformation to flow in one direction. Otherwise this would cause a problem if we\nwant to allow _deduction_ of the object parameter type. This deduction can't be\nused to select between pointer and not pointer.\n\nWe also considered supporting reference types that could bind to lvalues without\nexplicitly taking the address of the object, but references would have added a\nlot of complexity to the type system and we believed that they are not otherwise\nnecessary.\n\nWe decided to adopt an approach where the parameter declaration can contain a\nmarker for matching an argument's\n[value category](https://en.cppreference.com/w/cpp/language/value_category)\nseparately from its type. This marker would be present for methods that mutate\nthe object, and so requires that the receiver be an lvalue to match the pattern.\nThe marker means \"first take the address of the argument and then match the rest\nof the pattern.\" We considered a few different possible ways to write this:\n\n```\nfn Set[&me: Self*](n: Int);\nfn Set[*(me: Self*)](n: Int);\nfn Set[ref me: Self*](n: Int);\n```\n\nWe eventually settled on using a keyword `addr`.\n\n```\nfn Set[addr me: Self*](n: Int);\n```\n\nThis doesn't use up a symbol, makes it easier to find in search engines, and\nallows us to add more keywords in the future for other calling conventions, such\nas `inout`. We may even find that those other keywords have preferable semantics\nso we may eventually drop `addr`.\n\nThis keyword approach also is consistent with how we are marking template\nparameters with the `template` keyword, as decided in\n[issue #565 on generic syntax](https://github.com/carbon-language/carbon-lang/issues/565).\n\n### Marking mutating methods at the call site\n\nWe considered making it visible at the call site when the receiver was passed by\naddress, with the address-of operator `&`.\n\n```\n(&x).Set(4);\n```\n\nThis would in effect make the mutating methods be methods on the pointer type\nrather than the class type.\n\n### Differences between functions and methods\n\nQuestion-for-leads issue\n[#494: Method syntax](https://github.com/carbon-language/carbon-lang/issues/494)\nalso considered what would be different between functions and methods:\n\n-   Methods use a different calling syntax: `x.F(n)`.\n-   Methods distinguish between taking the receiver (`x`) by value or by\n    pointer, without changing the call syntax.\n-   Methods have to be declared in the body of the class.\n-   Methods and associated functions both have access to private members of the\n    class.\n-   Only methods can opt in to using dynamic dispatch.\n-   The receiver parameter to a method varies covariantly in inheritance unlike\n    other parameter types.\n\n### Specifying linkage as part of the access modifier\n\nWe considered various access modifiers such as `internal` or `private.internal`\nthat would enforce internal linkage in addition to restricted visibility. We\ndecided to postpone such considerations for the time being.\n\nEven if we _do_ need explicit controls here, we did not feel the need to\nfront-load that complexity right now and with relatively less time or experience\nto evaluate the tradeoffs. If and when linkage becomes a visible issue and\nimportant to discuss, we can add it. Until then, we can see how much mileage we\ncan get out of purely implementation techniques.\n\n### Nominal data class\n\nWe needed some way of opting a nominal class into the fieldwise behavior of a\ndata class. [In Kotlin](https://kotlinlang.org/docs/data-classes.html), you\nprecede the `class` declaration with a `data` keyword. Carbon already has a way\nof marking types as having specific semantic properties, implementing\ninterfaces. This leverages the support for interfaces in the language to be able\nto express things like \"here is a blanket implementation of an interface for all\ndata classes\" in a consistent way.\n\nWe chose the name `Data` rather than `DataClass` for the interface since tuples\nimplicitly implement the interface and were \"product types\" rather than\n\"classes\".\n\n### Let constants\n\nWe wanted a consistent interpretation for `let` declarations in classes and\nfunction bodies. Experience from C++ `const int` variables, where we try\nconstant-evaluation and then give the program different semantics based on\nwhether such evaluation happened to work, suggested we wanted to instead require\n`:!` in all places where a value that's usable during compilation is introduced.\n"
  },
  {
    "path": "proposals/p0731.md",
    "content": "# Generics details 2: adapters, associated types, parameterized interfaces\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/731)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [`adaptor` instead of `adapter`](#adaptor-instead-of-adapter)\n    -   [Syntax for associated constants](#syntax-for-associated-constants)\n        -   [Omitting types](#omitting-types)\n        -   [Inferring associated types from method signatures](#inferring-associated-types-from-method-signatures)\n    -   [Value patterns](#value-patterns)\n    -   [Deduced interface parameters](#deduced-interface-parameters)\n        -   [Rationale for the rejection](#rationale-for-the-rejection)\n            -   [Impl lookup rules with deducible interface parameters](#impl-lookup-rules-with-deducible-interface-parameters)\n    -   [Only associated types, no interface parameters](#only-associated-types-no-interface-parameters)\n    -   [Others](#others)\n\n<!-- tocstop -->\n\n## Problem\n\nWe want to Carbon to have a high quality generics feature that achieves the\ngoals set out in [#24](https://github.com/carbon-language/carbon-lang/pull/24).\nThis is too big to land in a single proposal. This proposal continues\n[#553](https://github.com/carbon-language/carbon-lang/pull/553) defining the\ndetails of:\n\n-   adapters\n-   associated types and other constants\n-   parameterized interfaces\n\n## Background\n\nThis is a follow on to these previous generics proposals:\n\n-   [#24: Generics goals](https://github.com/carbon-language/carbon-lang/pull/24)\n-   [#447: Generics terminology](https://github.com/carbon-language/carbon-lang/pull/447)\n-   [#524: Generics overview](https://github.com/carbon-language/carbon-lang/pull/524)\n-   [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n\nThe content for this proposal was extracted from a larger\n[Generics combined draft proposal](https://github.com/carbon-language/carbon-lang/pull/36).\n\n## Proposal\n\nThis is a proposal to add multiple sections to\n[this design document on generics details](/docs/design/generics/details.md).\n\n## Rationale based on Carbon's goals\n\nMuch of this rationale was captured in the\n[Generics goals proposal](https://github.com/carbon-language/carbon-lang/pull/24).\n\n## Alternatives considered\n\n### `adaptor` instead of `adapter`\n\nWe considered replacing the `adapter` keyword with the alternate spelling of\n\"adaptor\". Both spellings can be used for the intended meaning, but the \"-er\"\nspelling is more common in English text and in code. The final deciding factor\nwas that the\n[GoF Design Patterns book](https://en.wikipedia.org/wiki/Design_Patterns) spells\nthe [\"adapter pattern\"](https://en.wikipedia.org/wiki/Adapter_pattern) with the\n[\"-er\" spelling](https://springframework.guru/gang-of-four-design-patterns/adapter-pattern/).\n\n### Syntax for associated constants\n\nIssue\n[#739: Associated type syntax](https://github.com/carbon-language/carbon-lang/issues/739)\ndecided that the syntax for assigning a value to an associated constant, such as\nan associated type.\n\nThe decision was to use `let` with `:!` to express that these are compile-time\nvalues, matching the use in classes described in proposal\n[#772](p0722.md#let-constants).\n\n```\ninterface Stack {\n  let ElementType:! Type;\n  fn Push[addr me: Self*](value: ElementType);\n  ...\n}\n\nclass DynamicArray(T:! Type) {\n  ...\n  impl as Stack {\n    let ElementType:! Type = T;\n    fn Push[addr me: Self*](value: ElementType);\n    ...\n  }\n}\n```\n\nOne advantage was this opened the door for a type to satisfy the associated\ntypes of two interfaces with the same name with a single `let` declaration using\nconstraints satisfying the requirements of both interfaces.\n\nThis type can be replaced with `auto`, to have it determined automatically.\n\n```\nclass DynamicArray(T:! Type) {\n  ...\n  impl as Stack {\n    let ElementType:! auto = T;\n    fn Push[addr me: Self*](value: ElementType);\n    ...\n  }\n}\n```\n\nThis would avoid needing to change the `impl` when the constraints in the\ninterface changed as long as the value to the right of the `=` satisfied the new\nconstraints. Otherwise if the constraints are being weakened, first functions\nrelying on the capabilities being removed would have to change, then they would\nbe changed in the interface, and finally the implementations for types. If the\nconstraints are being strengthened, the implementations for types would have to\nchange first followed by the interface.\n\n#### Omitting types\n\nWe also considered omitting the type in the `impl`, always using the type\ndeclared in the interface.\n\n```\nclass DynamicArray(T:! Type) {\n  ...\n  impl as Stack {\n    let ElementType = T;\n    fn Push[addr me: Self*](value: ElementType);\n    ...\n  }\n}\n```\n\nThis would provide the advantage of reducing the number of changes when changing\nthe constraint specified in the interface. If the constraints were being\nweakened, then functions that used the capability that was being removed would\nbreak or need to be modified. If the constraints were being strengthened, then\nonly type implementations that didn't satisfy the new constraints would break or\nneed to be modified.\n\nThe biggest difference from the selected option is when adding a constraint. In\nthat case the selected option would have more churn, because all implementations\nwould be updated even if they already satisfied the new constraint. This comes\nwith the advantage of making it easier _incrementally enforce_ greater\nconstraints.\n\nOn the whole, it seems like both could be made to work. You could explicitly\nspecify constraints with this option by using an alias to a normal\n`let ..:! TypeOfType` declaration that has extra constraints. Conversely, you\ncan specify `auto` as the constraints in the selected option.\n\nBut on balance, it seemed better to try putting the explicit constraints into\nthe implementations so that we have more tools to incrementally roll out changes\nto interface constraints even though those rollouts will as a consequence be\nmore noisy in some cases. If experience shows that this is a really bad\ntradeoff, we should revisit it.\n\n#### Inferring associated types from method signatures\n\nThe last option considered is used by Swift.\n[Swift allows the value of an associated type to be omitted when it can be determined from the method signatures in the implementation](https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID190).\nFor the above example, this would mean figuring out `ElementType == T` from\ncontext:\n\n```\nclass DynamicArray(T:! Type) {\n  ...\n  impl as Stack {\n    // Not needed: let ElementType:! Type = T;\n    fn Push[addr me: Self*](value: T);\n    ...\n  }\n}\n```\n\nOne benefit is that it allows an interface to evolve by adding an associated\ntype, without having to then modify all implementations of that interface.\n\nOne concern is this might be a little more complicated in the presence of method\noverloads with\n[default implementations](/docs/design/generics/details.md#interface-defaults),\nsince it might not be clear how they should match up, as in this example:\n\n```\ninterface Has2OverloadsWithDefaults {\n  let T:! StackAssociatedType;\n  fn F[me: Self](x: DynamicArray(T), y: T) { ... }\n  fn F[me: Self](x: T, y: T.ElementType) { ... }\n}\n\nclass S {\n  impl as Has2OverloadsWithDefaults {\n     // Unclear if T == DynamicArray(Int) or\n     // T == DynamicArray(DynamicArray(Int)).\n     fn F[me: Self](\n         x: DynamicArray(DynamicArray(Int)),\n         y: DynamicArray(Int)) { ... }\n  }\n}\n```\n\nNot to say this can't be resolved, but it does add complexity.\n[Swift considered](https://github.com/apple/swift/blob/main/docs/GenericsManifesto.md#associated-type-inference)\nremoving this feature because it was the one thing in Swift that required global\ntype inference, which they otherwise avoided. They\n[ultimately decided to keep the feature](https://github.com/apple/swift-evolution/blob/main/proposals/0108-remove-assoctype-inference.md).\n\nThis option was only very briefly discussed and not preferred because:\n\n-   It came with complexity of inference.\n-   It seemed unnecessary.\n\n### Value patterns\n\nWe considered an alternative to the `type_of` approach from\n[the parameterized interfaces section](/docs/design/generics/details.md#parameterized-interfaces)\nfor binding `T` to a type mentioned later in the parameter list. We could\ninstead allow functions to have value patterns without a `:`, as in:\n\n```\nfn PeekAtTopOfStackParameterized\n    [T:! Type, StackType:! StackParameterized(T)]\n    (s: StackType*, T) -> T { ... }\n```\n\nHowever, we don't want to allow value patterns more generally so we can reject\ndeclarations like `fn F(Int)` when users almost certainly meant `fn F(i: Int)`.\n\n### Deduced interface parameters\n\nThe Carbon team considered and then rejected the idea that we would have two\nkinds of interface parameters. \"Multi\" parameters would work as described in the\n[detailed design document](/docs/design/generics/details.md#parameterized-interfaces).\n\"Deducible\" type parameters would only allow one implementation of an interface,\nnot one per interface & type parameter combination. These deducible type\nparameters could be inferred like\n[associated types](/docs/design/generics/details.md#associated-facets) are. For\nexample, we could make a `Stack` interface that took a deducible `ElementType`\nparameter. You would only be able to implement that interface once for a type,\nwhich would allow you to infer the `ElementType` parameter like so:\n\n```\nfn PeekAtTopOfStack[ElementType:! Type, StackType:! Stack(ElementType)]\n    (s: StackType*) -> ElementType { ... }\n```\n\nThis can result in more concise code for interfaces where you generally need to\ntalk about some parameter anytime you use that interface. For example,\n`NTuple(N, type)` is much shorter without having to specify names with the\narguments.\n\n#### Rationale for the rejection\n\n-   Having only one type of parameter simplifies the language.\n-   Multi parameters express something we need, while deducible parameters can\n    always be changed to associated types.\n-   One implementation per interface & type parameter combination is more\n    consistent with other parameterized constructs in Carbon. For example,\n    parameterized types `Foo(A)` and `Foo(B)` are distinct, unconnected types.\n-   It would be hard to give clear guidance on when to use associated types\n    versus deducible type parameters, since which is best for a particular use\n    is more of a subtle judgement call.\n-   Deducible parameters in structural interfaces require additional rules to\n    ensure they can be deduced unambiguously.\n\nIn addition, deducible interface parameters would complicate the lookup rules\nfor impls.\n\n##### Impl lookup rules with deducible interface parameters\n\nInterface implementation is Carbon's only language construct that allows open\nextension, and this sort of open extension is needed to address the \"expression\nproblem\" in programming language design. However, we need to limit which\nlibraries can implement an interface for a type so we can be guaranteed to see\nthe implementation when we try and use it.\n\nSo the question becomes: can we allow an implementation of a parameterized\ninterface `I(T)` for a type `A` to be in the same library as `T`, or can it only\nbe provided with `I` or `A`? The answer is \"yes\" if `T` is \"multi\" and \"no\" if\n`T` is deducible.\n\nThe problem with defining the implementation with a deducible `T` is that it\nwould allow users to violate\n[coherence](/docs/design/generics/goals.md#coherence). Consider this collection\nof libraries, where there are implementations for an interface `I(T)` for a type\n`A`, and those implementations are in the libraries defining the type parameter:\n\n```\npackage X library \"I and A\" api;\n\ninterface I(Type:$ T) { ... }\n\nstruct A { ... }\n```\n\n```\npackage Y library \"T1\" api;\n\nimport X library \"I and A\";\n\nstruct T1 { ... }\n\n// Type `X.A` has an implementation for `X.I(T)` for `T == Y.T1`.\nimpl X.I(T1) for X.A { ... }\n```\n\n```\npackage Z library \"T2\" api;\n\nimport X library \"I and A\";\n\nstruct T2 { ... }\n\n// Type `X.A` has an implementation for `X.I(T)` for `T == Z.T2`.\nimpl X.I(T2) for X.A { ... }\n```\n\n```\npackage Main api;\n\nimport X library \"I and A\";\n// Consider what happens if we include different combinations\n// of the following two statements:\n// import Y library \"T1\";\n// import Z library \"T2\";\n\n// Function `F` is called with value `a` with type `U`,\n// where `U` implements interface `X.I(T)` for some type `T`.\nfn F[Type:$ T, X.I(T):$ U](U:$ a) { ... }\n\nfn Main() {\n  var X.A: a = X.A.Init();\n  F(a);\n}\n```\n\n(In the example, each library is in a different package, but the packages are\nnot the important part here.)\n\nThe `F(a)` call triggers a lookup for implementations of the interface `X.I(T)`\nfor some `T`. There exists such implementations in both libraries `Y.T1` and\n`Z.T2` for different values of `T`. This has a number of sad consequences:\n\n-   \"Import what you use\" is hard to measure: libraries `Y.T1` and `Z.T2` are\n    important and used even though `Y` and `Z` are not mentioned outside the\n    `import` statement.\n-   The call `F(a)` has different interpretations depending on what libraries\n    are imported:\n    -   If neither is imported, it is an error.\n    -   If both are imported, it is ambiguous.\n    -   If only one is imported, you get totally different code executed\n        depending on which it is.\n-   We have no way of enforcing a \"one implementation per interface\" rule that\n    would prevent the call to `F` from being ambiguous.\n\nBasically, there is nothing guaranteeing that we import libraries defining the\ntypes that are used as interface parameters if we allow the interface parameters\nto be deduced.\n\n### Only associated types, no interface parameters\n\nThis is what Swift does, but doesn't allow us to use interfaces to express\noperator overloads. For example, a vector should be able to be added to either a\nvector or a point. So we follow Rust, which has trait parameters in addition to\nassociated types and uses them to define the behavior of operators.\n\n### Others\n\nOther alternatives considered will be in a future proposal. Some of them can be\nseen in a rough form in\n[#36](https://github.com/carbon-language/carbon-lang/pull/36).\n"
  },
  {
    "path": "proposals/p0752.md",
    "content": "# `api` file default-`public`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/752)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Default `api` to private](#default-api-to-private)\n    -   [Default `impl` to public](#default-impl-to-public)\n    -   [Make keywords either optional or required in separate definitions](#make-keywords-either-optional-or-required-in-separate-definitions)\n\n<!-- tocstop -->\n\n## Problem\n\nQuestion for leads\n[#665: private vs public _syntax_ strategy, as well as other visibility tools like external/api/etc.](https://github.com/carbon-language/carbon-lang/issues/665)\ndecided that methods on classes should default to public. Should `api` echo the\nsimilar strategy?\n\n## Background\n\n-   In C++, `struct` members default public, while `class` members default\n    `public`.\n-   In proposal\n    [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107),\n    an `api` keyword was used to indicate public APIs within an `api` file.\n-   In [#665](https://github.com/carbon-language/carbon-lang/issues/665), it was\n    decided that Carbon class members should default `public`.\n    -   This issue was reopened to discuss alternatives in this proposal.\n\n## Proposal\n\nAPIs in the `api` file should default public, without need for an additional\n`api` keyword. `private` may be specified to designate APIs that are internal to\nthe library, and only visible to `impl` files.\n\nNothing is necessary within `impl` files, and APIs there will be private unless\nforward declared in the `api` file.\n\n## Rationale based on Carbon's goals\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n    It will be easier for developers to understand code if APIs have\n    semantically similar behavior when comparing the visibility of class methods\n    to other code, and the library to other packages.\n\n## Alternatives considered\n\n### Default `api` to private\n\nDefault private is what was implied by `api`, and was the previous state.\n\nAdvantages:\n\n-   Decreases the likelihood that developers will accidentally expose APIs,\n    because it's an explicit choice.\n-   Can move functions between `api` and `impl` without visibility changing.\n\nDisadvantages:\n\n-   The `api` file's primary purpose is to expose APIs, and so it may be more\n    natural for developers to assume things there are public.\n-   Inconsistent with \"default public\" behavior on classes.\n\nWe are switching to default public in `api` files for consistency with class\nbehaviors.\n\n### Default `impl` to public\n\nNoting that we default `api` to public, we could similarly default `impl` to\npublic.\n\nAdvantages:\n\n-   Can move functions between `api` and `impl` without visibility changing.\n\nDisadvantages:\n\n-   Everything in an `impl` file must be private unless it's a separate\n    definition of an `api` declaration. As a consequence, everything declared in\n    the `impl` file would need to be explicitly `private`.\n\nIn order to avoid the toil of explicitly declaring everything in the `impl` as\n`private`, `impl` will be `private` by default. As a consequence of being the\ndefault behavior, no `private` should be specified, just as `public` is not\nallowed in `api` files.\n\nNote the visibility behavior can be described as making declarations the most\nvisible possible for its context, which in `api` files is `public`, and in\n`impl` is `private`.\n\n### Make keywords either optional or required in separate definitions\n\nWhen a prior declaration exists, keywords are _disallowed_ in separate\ndefinitions. We could instead allow keywords, making them either optional or\nrequired. This would allow developers to determine visibility when reading a\ndefinition.\n\nThe downside of this is that optional keywords can be confusing. For example:\n\n-   `api` file:\n\n    ```\n    class Foo {\n      private fn Bar();\n      private fn Wiz();\n    };\n    ```\n\n-   `impl` file:\n\n    ```\n    fn Foo.Bar() { ...impl... }\n    private fn Foo.Wiz() { ...impl... }\n    fn Baz() { ...impl... }\n    ```\n\nIn an \"optional\" setup, the above is valid code. However, the lack of a\n`private` keyword on `Foo.Bar` may lead a developer to conclude that it's public\nwithout checking the `api` file (particularly because `Foo.Wiz` is explicitly\nprivate), when it's actually private. This is an accident that could also occur\non refactoring; for example, removing the keyword on the `impl` version of\n`Foo.Wiz` would be valid but does not make it public.\n\nA response may be to make keywords required to match, so that reading the `impl`\nfile would have a compiled guarantee of correctness, avoiding confusion.\nHowever, consider a similar example:\n\n-   `api` file:\n\n    ```\n    class Foo {\n      fn Bar();\n      private fn Wiz();\n    };\n    ```\n\n-   `impl` file:\n\n    ```\n    fn Foo.Bar() { ...impl... }\n    private fn Foo.Wiz() { ...impl... }\n    fn Baz() { ...impl... }\n    ```\n\nIn this example, `Foo.Bar` is public, and that may lead developers to conclude\nthat `Baz` is public. This could be corrected by requiring `private` on `Baz`,\nbut we are hesitant to do that per\n[Default `impl` to public](#default-impl-to-public).\n\nThere is still some risk of confusion if the forward declaration and separate\ndefinition are both in the `api` file. For example:\n\n```\nprivate fn PrintLeaves(Node node);\n\nfn PrintNode(Node node) {\n  Print(node.value);\n  PrintLeaves(node);\n);\n\nfn PrintLeaves(Node node) {\n  for (Node leaf : node.leaves) {\n    PrintNode(leaf);\n  }\n}\n```\n\nIn this, a reader may read the `PrintLeaves` definition and incorrectly conclude\nthat it is implicitly `public` because (a) it has no keywords and (b) it is in\nthe `api` file. This will be addressed as part of\n[Open question: Calling functions defined later in the same file #472](https://github.com/carbon-language/carbon-lang/issues/472#issuecomment-915407683).\n\nOverall, the decision to _disallow_ keywords on separate definitions means that\n`impl` files shouldn't have any visibility keywords at the file scope (they will\non classes), which is considered a writability improvement while keeping the\n`api` as the single source of truth for `public` entities, addressing\nreadability.\n"
  },
  {
    "path": "proposals/p0777.md",
    "content": "# Inheritance\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/777)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Classes are final by default](#classes-are-final-by-default)\n    -   [Allow keywords to be written when they would have no effect](#allow-keywords-to-be-written-when-they-would-have-no-effect)\n        -   [Allow `final class`](#allow-final-class)\n        -   [Allow `partial FinalClass`](#allow-partial-finalclass)\n    -   [Different virtual override keywords](#different-virtual-override-keywords)\n    -   [Different virtual override keyword placement](#different-virtual-override-keyword-placement)\n    -   [Final methods](#final-methods)\n    -   [Constructors](#constructors)\n        -   [Different keyword than `partial`](#different-keyword-than-partial)\n        -   [Partial facet for extensible classes](#partial-facet-for-extensible-classes)\n        -   [Derived constructors set base fields](#derived-constructors-set-base-fields)\n        -   [No partial facet](#no-partial-facet)\n        -   [Only mixins and interfaces](#only-mixins-and-interfaces)\n        -   [Swift approach](#swift-approach)\n        -   [C# approach](#c-approach)\n        -   [Construct function](#construct-function)\n    -   [Implicit abstract classes](#implicit-abstract-classes)\n    -   [No extensible objects with non-virtual destructors](#no-extensible-objects-with-non-virtual-destructors)\n    -   [Separate \"exact\" and \"or derived\" variations on types](#separate-exact-and-or-derived-variations-on-types)\n    -   [Separate \"exact\" and \"or derived\" variations on pointers](#separate-exact-and-or-derived-variations-on-pointers)\n\n<!-- tocstop -->\n\n## Problem\n\nWe would like to address the use cases for inheritance described in proposal\n[#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561),\nincluding providing a migration path for C++ types and programmers currently\nusing inheritance.\n\n## Background\n\nThis is a follow up to these previous proposals defining classes:\n\n-   [#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561)\n-   [#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722)\n\n## Proposal\n\nThe proposal is to update [docs/design/classes.md](/docs/design/classes.md) as\ndescribed in [this PR](https://github.com/carbon-language/carbon-lang/pull/777).\n\n## Rationale based on Carbon's goals\n\nThis particular proposal is focusing on these Carbon goals:\n\n-   [That code is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\n    particularly addressing mechanisms for writing object-oriented code familiar\n    to C++ programmers. We have attempted to include support for most C++ usage\n    patterns, rather than a lot of safety restrictions following the maxim that\n    Carbon should \"focus on encouraging appropriate usage of features rather\n    than restricting misuse\".\n-   [That Carbon supports writing performance-critical software](/docs/project/goals.md#performance-critical-software).\n    This includes removing cruft from the produced binaries by limiting support\n    for multiple and virtual inheritance, avoiding redundantly setting the vptr\n    when constructing objects, and making classes final by default.\n-   [That Carbon has practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms).\n    This proposal addresses safety concerns with non-virtual destructors by\n    making the unsafe case syntactically visible, and providing the tools for\n    safer alternative approaches by using\n    [final classes](<https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Non-subclassable_classes>).\n\n## Alternatives considered\n\n### Classes are final by default\n\nThis is a divergence from C++, but has a number of benefits:\n\n-   Classes are not in general safe for derivation unless they are explicitly\n    designed to be. One example is that a class `X` may assume that any value of\n    type `X*` should be treated as a pointer to exactly that type.\n-   Final classes are easier to evolve, since there are no concerns that a newly\n    added name will conflict with one in a derived class.\n-   It is only safe to delete a pointer to a class that is final or has a\n    virtual destructor. Making classes final by default means we can provide\n    good ergonomics without sacrificing safety.\n-   We want to encourage users to use composition or interfaces instead of\n    inheritance unless they consciously decide that is the right solution for\n    their use case.\n-   Labelling a class that supports inheritance as a `base class` puts\n    information about the class important to readers up front, rather than\n    leaving them wondering whether the class supports inheritance or just\n    accidentally used the default.\n-   The compiler can easily diagnose that a class is mistakenly final when you\n    attempt to extend it. It is much more difficult to determine that a class is\n    mistakenly a base.\n-   We expect there are some performance and code size benefits.\n\n### Allow keywords to be written when they would have no effect\n\nIn both of these cases, we decided it was better that there was only one way to\nwrite the code, than allow a keyword to be written in a situation where it only\nacted as a comment without changing the meaning of the code.\n\n#### Allow `final class`\n\nWe considered allowing `final class` as a synonym for `class` without a `base`\nprefix, but we didn't feel it would provide benefit justifying the additional\ncomplexity.\n\n#### Allow `partial FinalClass`\n\nWe considered allowing `partial` to be used for all constructor functions. For a\nfinal class, `partial FinalClass` would be an alias for `FinalClass`. FIXME\n**Answer: No**\n\n### Different virtual override keywords\n\nInstead of `virtual` we considered `base`. This would create a parallel\nstructure between `abstract` and `base` classes on one hand, and `abstract` and\n`base` methods on the other. However, we felt like this was an important case to\nmaintain continuity with C++.\n\nInstead of `abstract` we considered:\n\n-   `virtual` ... `= 0`\n-   `required`\n-   `pure virtual`\n-   `virtual` ... `pure`\n\nWe didn't like using a suffix like `= 0` or `= pure`, since it is in place of an\nimplementation but we wouldn't put it out of line like an implementation. We\ndidn't like `= 0` despite it being consistent with C++ because it didn't reflect\nthe meaning in the way a keyword could, and keywords are easier to look up in\nsearch engines. We might reconsider `required` if we decide that we want to use\nthat keyword in other places, such as in a mixin. In the end, we went with\n`abstract` since it is used in other languages, such as Java, and could stand on\nits own without having to be paired with `virtual`.\n\nInstead of `impl` we considered using `override` as done in C++, with the\ndifference that the keyword would be mandatory in Carbon. There were a few\nconcerns with using `override`:\n\n-   It doesn't match the case where the base class doesn't have an\n    implementation to override because it is abstract or pure virtual.\n-   Concern about confusion between overriding and overloading.\n\nThe choice of `impl` is intended to draw a parallel with implementing\ninterfaces.\n\nIf we went with `override`, we might change the other keywords to match, using\n`must_override` instead of `abstract` and `overridable` instead of `virtual`. We\nmight consider switching to `overridable` if we decide that is a keyword we\nwould use in other contexts that allow overriding without using runtime dispatch\nusing a virtual table, for example interfaces or mixins.\n\n### Different virtual override keyword placement\n\nWe considered putting the virtual override keyword after the function's\nsignature:\n\n```\nbase class MyBaseClass {\n  fn Overridable[me: Self]() -> i32 virtual { return 7; }\n}\n```\n\nRationale for putting the keyword to the right:\n\n-   This is less salient information than the name and signature of the\n    function, particularly for callers of the API.\n-   This choice allows the function names to line up vertically.\n-   This keyword is about the implementation. For example, it says whether there\n    is an implementation of this method in this class at all.\n\nUnless you are extending the class, callers would not notice replacing a virtual\nfunction with a non-virtual function calling a private virtual function.\n\nThe concern was that while this choice makes the API easier to read for users\ncalling methods on the base class, it makes it significantly harder to read for\nusers extending the base class. And extending the base class was a common enough\nand important enough use case that this change was not worth also trading off\nfamiliarity from C++.\n\n**Reference:** This was decided in issue\n[#754: Placement of the word virtual](https://github.com/carbon-language/carbon-lang/issues/754).\n\n### Final methods\n\nWe considered allowing `final` to be used as a virtual override keyword, to mark\n[non-overridable methods](<https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Non-overridable_methods>).\nThis is something we might change in the future, based on demonstrated need, but\nfor now we didn't see the use cases for it occurring in practice that would\njustify its addition to the language. This was based on a few reasons.\n\n-   Even though this exists in C++ code, it can be dropped without changing\n    meaning.\n-   We expect you can get similar performance benefits from profile guided\n    optimizations and devirtualization.\n-   We imagined that we might use this keyword in the future with a different\n    meaning, such as \"no shadow\".\n-   We saw little harm in omitting this for now, even if we decide to add it in\n    later if and when we see that it would be useful for Carbon programmers.\n\nNote that if we were to add final methods, they would be allowed to be\nimplemented in the partial facet type of a base class.\n\n### Constructors\n\n[Perils of Constructors](https://matklad.github.io/2019/07/16/perils-of-constructors.html)\ngives a great overview of the challenges with constructors. It expresses the\nadvantages of the factory function approach used by Rust, but observes that\nthere are some difficulties making it work with inheritance and placement.\nProposal\n[#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257/files)\naddresses the placement component of construction, and this proposal extends\nthat approach to work with inheritance using the `partial` facet. This approach\nhas some benefits:\n\n-   Simplicity by not having constructors with different rules from other\n    functions.\n-   No initializer list\n    [shadow world](https://gbracha.blogspot.com/2014/09/a-domain-of-shadows.html).\n-   No distinction between constructors and other factory functions.\n-   No need for rules and syntax for\n    [delegating](https://docs.microsoft.com/en-us/cpp/cpp/delegating-constructors?view=msvc-160)\n    or\n    [convenience](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID217)\n    constructors.\n-   No need to have special handling of errors.\n-   Ability to write code in a derived constructor before calling its base\n    constructor.\n-   No static analysis of code, potentially with control flow, to ensure that\n    all fields are initialized.\n\nWe considered several alternatives, particularly in issue\n[#741: Constructing an object of a derived type](https://github.com/carbon-language/carbon-lang/issues/741).\n\n#### Different keyword than `partial`\n\nIn issue [#741](https://github.com/carbon-language/carbon-lang/issues/741), we\nconsidered other keywords instead of `partial` to designate the facet of the\ntype for construction.\n\n-   `base`: Intended to indicate a\n    [base class subobject](https://en.cppreference.com/w/cpp/language/derived_class),\n    but was confusing with other uses of the word \"base\" to mean \"the base class\n    of a type.\"\n-   `as_base`: Intended to address the confusion around using `base` by adding a\n    preposition that indicates this isn't the \"base of the type.\" However, it\n    introduces confusion with the `as` operator used to cast.\n-   `bare`: Too far from the intended meaning.\n-   `impl`: This keyword is already being used for other things that are too\n    different from this use.\n-   `novirt`: Describes something about the effect of this keyword, but not why\n    you are using it.\n-   `exact`: Intended to suggest this is the is a use of the exact type, not a\n    possibly derived type. This, like `novirt`, was too focused on the effect of\n    the keyword and wasn't suggestive enough of why it was being used. Also this\n    didn't capture why this keyword would allow you to instantiate an abstract\n    base class.\n-   `ctor`, `construct`, `constructor`: These were the wrong part of speech. The\n    type is not the constructor, the function returning this type is.\n-   `under_construction`: Too long.\n\nFor the construction-related options, there were also concerns that we might\nalso use this type during destruction of an object.\n\n#### Partial facet for extensible classes\n\nIn issue [#741](https://github.com/carbon-language/carbon-lang/issues/741), we\nconsidered recommending using the `partial` facet in constructors of extensible\nclasses more strongly than the current proposal. Ultimately we decided it wasn't\nnecessary:\n\n-   The behavior was more consistent with C++.\n-   The consequences of not using `partial` are small enough, matching C++\n    instead of a possible improvement.\n-   The rule for when to use `partial` was too subtle and hard to explain.\n-   Ending up with a `partial` type because you declared a variable with type\n    `auto` seemed like a bad user experience.\n-   Writing both a `protected` constructor returning a `partial` type for\n    descendants and a public constructor returning the full type improved the\n    ergonomics for using the class but seemed like painful boilerplate for\n    authors of the class.\n\n#### Derived constructors set base fields\n\nIn issue [#741](https://github.com/carbon-language/carbon-lang/issues/741), we\nconsidered making the constructor of a derived class explicitly set the fields\nof the base class without delegating to the base constructor, avoiding the\nproblem of trying to instantiate a base class that might be abstract.\n\nIt had some clear disadvantages including:\n\n-   There would be no way to make members of a base class private, particularly\n    their names.\n-   It wasn't clear how to interoperate with C++.\n\n#### No partial facet\n\nIn issue [#741](https://github.com/carbon-language/carbon-lang/issues/741), we\nconsidered allowing instantiating abstract base classes so they could be used to\ninitialize derived classes, but this was a safety regression from C++.\n\n#### Only mixins and interfaces\n\nIn issue [#741](https://github.com/carbon-language/carbon-lang/issues/741), we\nconsidered splitting inheritance into separate mechanisms for subtyping and\nimplementation reuse. Interfaces would represent APIs for subtyping purposes and\nimplementations would be defined in mixins. This was a major divergence from C++\nand would likely cause problems for both programmers and interoperation.\n\n#### Swift approach\n\n[Swift initialization](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html)\nrequires the user to define a special `init` method that initializes the fields\nof the object before calling any methods on it. For a\n[derived class](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID216),\nthis is then followed by a call to the base's `init` method. After that is done,\nthere is a\n[second phase of initialization](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html#ID220)\nthat can operate on an object that at least has all fields initialized. This\nmeans method calls are allowed, even though it is possible that not all\ninvariants of the class have been established for the object.\n\n```\nclass MyClass extends BaseClass {\n  fn init(...) {\n    me.derived_field = ...;\n    super.init(base_arguments);\n    phase_2_after_fields_are_set();\n  }\n}\n```\n\nThis approach has some nice properties, for example it supports calling virtual\nmethods in the base class' `init` method and getting the derived implementation.\nHowever it has some disadvantages for our purposes:\n\n-   Relies on potentially fragile static analysis of the code to determine that\n    all fields are initialized.\n-   Init methods have a number of restrictions, such as no method calls in the\n    first phase, to avoid potentially unsafe use of a partially initialized\n    value. So init methods are not ordinary method calls even though they\n    superficially look quite similar.\n-   Unclear what destructors to run if there is a failure partway through\n    construction.\n-   Would not interoperate well with C++, since derived fields are initialized\n    before base fields. This also means that the initial value for derived\n    fields can't be set using the values of the base fields set in the base's\n    init method.\n\n#### C# approach\n\n[C# Constructors](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/constructors)\nhave names that match their class, and the constructor of a derived class starts\nwith a call to the base class' constructor using this `: base(...)` syntax\nbetween the parameter list and function body:\n\n```\nclass MyClass extends BaseClass {\n  fn MyClass(...) : base(base_arguments) {\n    me.derived_field = ...;\n    phase_2_after_fields_are_set();\n  }\n}\n```\n\nAlternatively, a constructor can delegate to another constructor using\n`: this(...)` syntax instead.\n\nDisadvantages for our purposes:\n\n-   Doesn't allow you to write code before calling the base class' constructor.\n-   Constructors have a special syntax and are not ordinary functions. However\n    those differences would be familiar to C++ programmers.\n-   Relies on potentially fragile static analysis of the code to determine that\n    all fields are initialized and that it is safe to call methods.\n-   Unclear what destructors to run if there is a failure partway through\n    construction.\n\n#### Construct function\n\nWe rejected prior Carbon proposal\n[#98](https://github.com/carbon-language/carbon-lang/pull/98), where the user's\ninitialization function called a compiler-provided function to create the object\nonce the base constructor arguments and derived field values were known.\n\n```\nclass MyClass extends BaseClass {\n  fn operator create(...) -> Self {\n    ...\n    returned var result: Self =\n        construct(base_arguments, {.derived_field = ...});\n    phase_2_after_fields_are_set();\n    return result;\n  }\n}\n```\n\nThis avoids giving a name to the object being constructed until its fields have\nbeen initialized, without relying on static analysis, making it clearer what\ndestructors should run in the case of failure, though the current proposal is\nstill clearer.\n\nDisadvantages for our purposes:\n\n-   Complexity when initializing fields that depended on the address of the\n    object being constructed.\n-   Constructors are special, not ordinary functions.\n\nNote that this prevents using the values assigned to the fields in the base's\nconstructor to determine the initial values for the derived fields. We could\naddress this concern by splitting the special `construct` function into two\npieces:\n\n```\nclass MyClass extends BaseClass {\n  fn operator create(...) -> Self* {\n    ...\n    var parent: BaseClass* = create_base(base_arguments);\n    // Can determine the values for derived fields here.\n    var result: Self* = construct(parent, {.derived_field = ...});\n    phase_2_after_fields_are_set();\n    return result;\n  }\n}\n```\n\nThis adds some complexity, but interoperates better with C++.\n\n### Implicit abstract classes\n\nWe considered following C++'s approach of making classes abstract based on\nhaving any pure virtual methods. This leads to awkward workarounds where you\nmight mark a class' destructor as pure virtual even though it is still\nimplemented. We decided to use a different introducer for abstract classes since\nthis is very important for readers, helping them determine the role of the class\nand whether this is the class they are looking for.\n\nWe thought that if you were to change a class to being abstract, you would\nlikely also update its description and rename it at the same time, since that\nwas such an important change to the interface of the class.\n\n### No extensible objects with non-virtual destructors\n\nWe considered forbidding constructing extensible objects with non-virtual\ndestructors. This was to avoid getting into a state where a type could be used\nas a local variable but not allocated on the heap. It was also identified as an\nadvanced use case that didn't need to be as convenient to write, and so the\noverhead of using both a final and an abstract type in place of an extensible\ntype might be more acceptable and would give much more clarity to what a given\ntype represented.\n\nHowever, this was a noticeable divergence from C++ where extensible objects are\nthe default. We decided that consistency with both C++ and extensible classes\nwith virtual methods was more valuable. The error when deleting a base class\nwith a non-virtual destructor would be very clear and offer useful alternatives:\nmaking the destructor virtual, making a final class, or using `unsafe_delete`.\nThis matched the idea that\n[Carbon should \"focus on encouraging appropriate usage of features rather than restricting misuse\"](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n\nThis topic was discussed in issue\n[#652: Extensible classes with or without vtables](https://github.com/carbon-language/carbon-lang/issues/652)\nand\n[on Discord](https://discord.com/channels/655572317891461132/708431657849585705/880471907407888404).\n\n### Separate \"exact\" and \"or derived\" variations on types\n\nIssue [#652](https://github.com/carbon-language/carbon-lang/issues/652)\nconsidered many variations on ways to have two different types for values\ndepending on whether they represented a value with an exact type, or a value\nthat could be a derived type. We ultimately decided that asking users to use\nboth types would be too much cognitive overhead, and would be a usability\nregression from C++.\n\n### Separate \"exact\" and \"or derived\" variations on pointers\n\nIssue [#652](https://github.com/carbon-language/carbon-lang/issues/652)\nconsidered instead having two kinds of pointers. One would point to a value of a\nspecific known type, and the other would point to a value of some derived type.\nThis has two disadvantages compared to having the variations be on the types of\nthe values.\n\n-   The distinction between pointer types is meaningless for non-extensible\n    types.\n-   We still need the distinction for value types to give the right type to the\n    result of dereferencing the pointer.\n"
  },
  {
    "path": "proposals/p0818/regular_equivalence_classes.md",
    "content": "# Regular equivalence classes\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n## Problem\n\nFor generics, users will define _interfaces_ that describe types. These\ninterfaces may have associated types (see\n[Swift](https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID189),\n[Rust](https://doc.rust-lang.org/rust-by-example/generics/assoc_items/types.html)):\n\n```\ninterface Container {\n  let Elt:! Type;\n  let Slice:! Container;\n  let Subseq:! Container;\n}\n```\n\nThe next step is to express constraints between these associated types.\n\n-   `Container.Slice.Elt == Container.Elt`\n-   `Container.Slice.Slice == Container.Slice`\n-   `Container.Subseq.Elt == Container.Elt`\n-   `Container.Subseq.Slice == Container.Slice`\n-   `Container.Subseq.Subseq == Container.Subseq`\n\nLanguages commonly express these constraints using `where` clauses, as in\n[Swift](https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID557) and\n[Rust](https://doc.rust-lang.org/rust-by-example/generics/where.html), that\ndirectly represent these constraints as equations.\n\n```\ninterface Container {\n  let Elt:! Type;\n  let Slice:! Container where .Elt == Elt\n                          and .Slice == Slice;\n  let Subseq:! Container where .Elt == Elt\n                           and .Slice == Slice\n                           and .Subseq == Subseq;\n}\n```\n\nThese relations give us a semi-group, where in general deciding whether two\nsequences are equivalent is undecidable, see\n[Swift type checking is undecidable - Discussion - Swift Forums](https://forums.swift.org/t/swift-type-checking-is-undecidable/39024).\n\nIf you allow the full undecidable set of `where` clauses, there are some\nunpleasant options:\n\n-   Possibly the compiler won't realize that two expressions are equal even\n    though they should be.\n-   Possibly the compiler will reject some interface declarations as \"too\n    complicated\", due to \"running for too many steps\", based on some arbitrary\n    threshold.\n\nFurthermore, the algorithms are expensive and perform extensive searches.\n\n### Goal\n\nThe goal is to identify some restrictions such that:\n\n-   We have a terminating algorithm to decide if a set of constraints meets the\n    restrictions.\n-   For constraints that meet the restrictions we have a terminating algorithm\n    for deciding which expressions are equal.\n-   Expected use cases satisfy the restrictions.\n\nThe expected cases are things of these forms:\n\n-   `X == Y`\n-   `X == Y.Z`\n-   `X == X.Y`\n-   `X == Y.X`\n-   and _some_ combinations and variations\n\nFor ease of exposition, I'm going to assume that all associated types are\nrepresented by single letters, and omit the dots `.` between them.\n\n## Idea\n\nObserve that the equivalence class of words you can rewrite to in these expected\ncases are described by a regular expression:\n\n-   `X` can be rewritten to `(X|Y)` using the rewrite `X == Y`\n-   `X` can be rewritten to `XY*` using the rewrite `X == XY`\n-   `X` can be rewritten to `Y*X` using the rewrite `X == YX`\n\nThese regular expressions can be used instead of the rewrite rules: anything\nmatching the regular expression can be rewritten to anything else matched by the\nsame regular expression. This means we can take any sequence of letters, replace\nanything that matches the regular expression by the regular expression itself,\nand get a regular expression that matches the original sequence of letters. We\ncan even get a shortest/smallest representative of the class by dropping all the\nthings with a `*` and picking the shortest/smallest between alternatives\nseparated by a `|`.\n\n### Question\n\nGiven a set of rewrite equations, is there a terminating algorithm that either:\n\n-   gives a finite set of regular expressions (or finite automata) that\n    describes their equivalence classes, or\n-   rejects the rewrites.\n\nWe would be willing to reject cases where there are more equivalence classes\nthan rewrite rules. An example of this would be the rewrite rules `A == XY` and\n`B == YZ` have equivalence classes `A|XY`, `B|YZ`, `XYZ|AZ|XB`.\n\n## Problem\n\nIn particular, we've identified two operations for combining two finite automata\ndepending on how they overlap:\n\n-   **Containment operation:** If we have automatas `X` and `Y`, where `Y`\n    completely matches a subsequence matched by `X`, then we need to extend `X`\n    to include all the rewrites offered by `Y`. For example, if `X` is `AB*` and\n    `Y` is `(B|C)`, then we can extend `X` to `A(B|C)*`.\n-   **Union operation:** If we have automatas `X` and `Y`, and there is a string\n    `ABC` such that `X` matches the prefix `AB` and `Y` matches the suffix `BC`,\n    then we need to make sure there is a rule for matching `ABC`.\n\nEven though it is straightforward to translate a single rewrite rule into a\nregular expression that matches at least some portion of the equivalence class,\nto match the entire equivalence classes we need to apply these two operations in\nways that can run into difficulties.\n\nOne concern is that an individual regular expression might not cover the entire\nequivalence for a rewrite rule. We may need to apply the union and containment\noperations to combine the automata _with itself_. For example, we may convert\nthe rewrite rule `AB == BA` into the regular expression `AB|BA`, but this\ndoesn't completely describe the set of equivalence classes that this rule\ncreates, since it triggers the union operation twice to add `AAB|ABA|BAA` and\n`ABB|BAB|BBA`. These would also trigger the union operation, and so on\nindefinitely, so the rewrite rule `AB == BA` does not have a finite set of\nregular equivalence classes. Similarly the rule `A == BCB` has an infinite\nfamily of equivalence classes: `BCB|A`, `BCBCB|ACB|BCA`,\n`BCBCBCB|ACBCB|ACA|BCACB|BCBCA`, ...\n\nThe other concern is that even in the case that each rule by itself can be\nfaithfully translated into a regular expression that captures the equivalence\nclasses of the rewrite, attempts to combine multiple rules using the two\noperations might never reach a fixed point.\n\nIn both cases, we are looking for criteria that we can use to decide if the\napplication of the operations will terminate. If it would not terminate, then we\nneed to report an error to the user instead of applying those two operations\nendlessly.\n\n## Examples\n\n### Regular single rules\n\n-   Anything where there are no shared letters between the two sides, and no\n    side has a prefix matching a suffix\n    -   `A == B` => `A|B`\n    -   `A == BC` => `A|BC`\n    -   `A == BBC` => `A|BBC`\n    -   `A == BCC` => `A|BCC`\n-   `A == AB` => `AB*`\n-   `A == BA` => `B*A`\n-   `A == AA` => `AA*` or `A*A` or `A+`\n-   `A == ABC` => `A(BC)*`\n-   `A == ABB` => `A(BB)*`\n-   `A == AAA` => `A(AA)*`\n-   `A == BCA` => `(BC)*A`\n-   `A == BBA` => `(BB)*A`\n-   `A == ACA` => `A(CA)*` or `(AC)*A`\n\n### Regular combinations\n\n-   `A==AB` + `A==AC` => `AB*` + `AC*` => `A(B|C)*`\n-   `A==AB` + `B==BC` => `AB*` + `BC*` => `A(B|C)*`, `BC*` with relation\n    `A(B|C)* BC* == A(B|C)*`; Note: `A == AB == ABC == AC`\n-   `A==AB` + `C==CB` => `AB*`, `CB*`, no relations\n-   `A==AB` + `A==CA` => `AB*` + `C*A` => `C*AB*`\n-   `A==AB` + `C==BC` => `AB*` + `B*C` => `AB*`, `B*C`, where if you have `AB*C`\n    it doesn't matter how you split the `B`s between `AB*` and `B*C`.\n-   `A==AB` + `B==AB` => `AB*` + `A*B` => `(A|B)+`\n-   `A==AB` + `B==CB` => `AB*` + `C*B` => `A(C*B)*`, `C*B` with `A(C*B)* C*B` ->\n    `A(C*B)*`\n-   `A==AB` + `B==CB` + `C==CD` => `AB*` + `C*B` + `CD*` => `A((CD*)*B)*`,\n    `(CD*)*B`, `CD*`\n-   `A==ABC` + `D==CB` => `A(BC)*` + `(CB|D)` => `A(BD*C)*`, `A(BD*C)*BD*`,\n    `(CB|D)`\n-   `A==ABBBBB` + `A==ABBBBBBBB` (or `A==AB^5` + `A==AB^8`)=> `A(BBBBB)*` +\n    `A(BBBBBBBB)*` => `AB*`, since `A=AB^8=AB^16=AB^11=AB^6=AB`\n\n### Not regular\n\n-   `AB == BA`, has equivalence classes: `AB|BA`, `AAB|ABA|BAA`, `ABB|BAB|BBA`,\n    ...\n-   Similarly: `AB==C` + `C==BA`\n-   `ABC == CBA`, has equivalence classes: `ABC|CBA`, `ABABC|ABCBA|CBABA`,\n    `ABCBC|CBABC|CBCBA`, ...\n-   `A == BAB`, involves back references or counting the number of `B`s:\n    `A|BAB|BBABB|BBBABBB|`...\n-   `A == BAC`, involves matching the number of `B`s to `C`s:\n    `A|BAC|BBACC|BBBACCC|`...\n-   `A == BCB`, has equivalence classes: `BCB|A`, `BCBCB|ACB|BCA`,\n    `BCBCBCB|ACBCB|ACA|BCACB|BCBCA`, ...\n-   `A == BB`, has equivalence classes: `A|BB`, `BBB|AB|BA`, `(A|BB)(A|BB)|BAB`,\n    ...\n-   `A == BBB`, has equivalence classes: `A|BBB`, `BBBB|AB|BA`,\n    `BBBBB|ABB|BAB|BBA`, ...\n-   `AA == BB`, has equivalence classes: `AA|BB`, `AAA|ABB|BBA`, `BAA|BBB|AAB`,\n    ...\n-   `AB == AA`, has equivalence classes: `A(A|B)`, `A(A|B)(A|B)`,\n    `A(A|B)(A|B)(A|B)`, ...\n-   `AB == BB`, similarly\n-   `AB == BC`, has equivalence classes: `(AB|BC)`, `(AAB|ABC|BCC)`, ...,\n    `A`^i`BC`^(N-i)\n-   `A == AAB` and `A == BAA`\n\n## References\n\nSee these notes from discussions:\n\n-   [Regular equivalence classes 2021-09-23](https://docs.google.com/document/d/1iyL7ZDfWT6ZmDSz6Fp8MrLcl5nOQc4ItQbeL3QlVXYU/edit#)\n-   [Carbon minutes (rolling): Open discussions: 2021-09-27](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#heading=h.qh4b1gy7o5el)\n-   [Carbon minutes (rolling): Open discussions: 2021-09-28](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#heading=h.9a1r39mla9ho)\n-   [Regular equivalence classes 2 2021-10-01](https://docs.google.com/document/d/1xGDRSV6q534-CoDZnzuZJmzhty2yPki2ZfDDPLSHYek/edit#)\n"
  },
  {
    "path": "proposals/p0818.md",
    "content": "# Constraints for generics (generics details 3)\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/818)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Alternatives to `where` clauses modifying type-of-types](#alternatives-to-where-clauses-modifying-type-of-types)\n    -   [Different keyword than `where`](#different-keyword-than-where)\n    -   [Inline constraints instead of `.Self`](#inline-constraints-instead-of-self)\n    -   [Self reference instead of `.Self`](#self-reference-instead-of-self)\n    -   [Implied constraints across declarations](#implied-constraints-across-declarations)\n    -   [No implied constraints](#no-implied-constraints)\n    -   [Type inequality constraints](#type-inequality-constraints)\n    -   [`where .Self is ...` could act like an external impl](#where-self-is--could-act-like-an-external-impl)\n        -   [Other syntax for external impl](#other-syntax-for-external-impl)\n    -   [Other syntax for must be legal type constraints](#other-syntax-for-must-be-legal-type-constraints)\n    -   [Using only `==` instead of also `=`](#using-only--instead-of-also-)\n    -   [Automatic type equality](#automatic-type-equality)\n        -   [Restricted equality constraints](#restricted-equality-constraints)\n        -   [No explicit restrictions](#no-explicit-restrictions)\n\n<!-- tocstop -->\n\n## Problem\n\nWe want Carbon to have a high quality generics feature that achieves the goals\nset out in [#24](https://github.com/carbon-language/carbon-lang/pull/24). This\nis too big to land in a single proposal. This proposal continues\n[#553](https://github.com/carbon-language/carbon-lang/pull/553) defining the\ndetails of:\n\n-   adapters\n-   associated types and other constants\n-   parameterized interfaces\n\n## Background\n\nThis is a follow on to these previous generics proposals:\n\n-   [#24: Generics goals](https://github.com/carbon-language/carbon-lang/pull/24)\n-   [#447: Generics terminology](https://github.com/carbon-language/carbon-lang/pull/447)\n-   [#524: Generics overview](https://github.com/carbon-language/carbon-lang/pull/524)\n-   [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n-   [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n\nSome of the content for this proposal was extracted from a larger\n[Generics combined draft proposal](https://github.com/carbon-language/carbon-lang/pull/36).\n\n## Proposal\n\nThis is a proposal to add two sections to\n[this design document on generics details](/docs/design/generics/details.md).\n\n## Rationale based on Carbon's goals\n\nMuch of this rationale for generics was captured in the\n[Generics goals proposal](https://github.com/carbon-language/carbon-lang/pull/24).\nThe specific decisions for this constraint design were motivated by:\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   The manual generic type equality approach being proposed could be\n        extended to automatically observe more types as being equal without\n        breaking existing code.\n    -   Adding or growing an `observe` statement has been designed to be\n        non-breaking since they can't introduce name conflicts, only make more\n        code legal.\n    -   This constraint system is expressive and does not have artificial limits\n        that would be needed to support automatic type equality.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Attaching `where` clauses to type-of-types addresses more use cases than\n        attaching them to declarations, allowing the design to be smaller, see\n        [#780](https://github.com/carbon-language/carbon-lang/issues/780).\n    -   The manual generic type equality approach is very simple and easy to\n        understand how it works. It unfortunately is a bit more verbose, leading\n        to more to read and write.\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n    -   The manual generic type equality approach does much less work at compile\n        time than the automatic approach. The extra work would only be done to\n        produce an error message that includes the changes to the source needed\n        to avoid repeating that work. In effect, the source code holds a cache\n        of the facts needed to compile it.\n\n## Alternatives considered\n\n### Alternatives to `where` clauses modifying type-of-types\n\nIssue\n[#780: How to write constraints](https://github.com/carbon-language/carbon-lang/issues/780)\nconsidered other forms that constraints could be written.\n\nOne alternative is to place `where` clauses on declarations instead of types.\n\n```\nfn F[W:! Type, V:! D & E](v:V) -> W\n    where V.X == W, V.Y == W, V.Z = i32;\n```\n\nThe constraints are written after the names of types are complete, and so\nconstraints are naturally written in terms of those names. This is a common\napproach used by several languages including Swift and Rust, and so is likely\nfamiliar to a significant fraction of our users. The downside of this approach\nis it doesn't let you put constraints on types that never get a names, such as\nin\n[\"protocols as types\" or \"existential types\" in Swift](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID275)\nand \"trait objects\" in Rust\n([1](https://doc.rust-lang.org/book/ch17-02-trait-objects.html),\n[2](https://doc.rust-lang.org/reference/types/trait-object.html)). This is a\nproblem in practice, since those are cases where constraints are needed, since\nfor type safety any associated types need to be constrained to be a specific\nconcrete type. This motivated Rust to add another syntax just for specifying\nspecific concrete types for associated types in the argument passing style. It\nis also motivation for Swift to consider a feature they call\n[\"generalized existentials\"](https://github.com/apple/swift/blob/main/docs/GenericsManifesto.md#generalized-existentials),\nthat is very similar to this proposal.\n\nAnother alternative is to generalize the argument passing approach Rust allows\nto handle more kinds of constraints.\n\n```\nfn F[W:! Type, V:! D{.X = W} & E{.Y = W, .Z = i32}](v: V) -> W;\n```\n\nThis would treat constraints on interface parameters and associated types in a\nmore uniform way, but doesn't handle the full breadth of constraints we would\nlike to express. We at some point believed that this framing of the constraints\nmade it harder to express undecidable type equality problems and easier to\nenforce restrictions that would make the constraints decidable, but we\neventually discovered that this formulation had the essentially the same\ndifficulties.\n\nWe considered a variation of argument passing that we called \"whole expression\nconstraint intersections.\"\n\n```\nfn F[W:! Type, V:! D & E & {.X = W, .Y = W, .Z = i32}](v: V) -> W;\n```\n\nThis variation made it easy to set associated types from two interfaces with the\nsame name to the same value, but introduced concerns that it would stop `&` from\nbeing associative and commutative. It was not chosen because it had the same\ndownsides as the argument passing approach.\n\n### Different keyword than `where`\n\nWe considered other keywords for introducing constraints, such as:\n\n-   `requires`, like\n    [C++](https://en.cppreference.com/w/cpp/language/constraints)\n-   `with`\n-   `if`, like [D](http://rosettacode.org/wiki/Constrained_genericity#D)\n-   `when`, like [F#](http://rosettacode.org/wiki/Constrained_genericity#F.23).\n\nThe most common choice across popular languages is `where`, including:\n\n-   [C#](http://rosettacode.org/wiki/Constrained_genericity#C.23)\n-   [Haskell](http://rosettacode.org/wiki/Constrained_genericity#Haskell)\n-   [Rust](https://doc.rust-lang.org/rust-by-example/generics/where.html)\n-   Swift\n    ([1](https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID553),\n    [2](https://docs.swift.org/swift-book/LanguageGuide/Generics.html#ID557))\n\nWhile C++ is particularly important to our target userbase, Carbon's constraints\nwork more similarly to languages with generics like Rust and Swift.\n\n### Inline constraints instead of `.Self`\n\nWe considered the possibility of using\n[named constraints](/docs/design/generics/details.md#named-constraints) instead\nof `.Self` for\n[recursive constraints](/docs/design/generics/details.md#recursive-constraints).\nThis comes under consideration since `.Self` outside the named constraint is the\nsame as `Self` inside. However, you can't always avoid using `.Self`, since\nnaming the constraint before using it doesn't allow you to define this\n`Container` interface:\n\n```\ninterface Container {\n  ...\n  let SliceType:! Container where .SliceType == .Self;\n  ...\n}\n```\n\nThe problem that arises is to avoid using `.Self`, we would need to define the\nnamed constraint using `Container` before `Container` is defined:\n\n```\nconstraint ContainerIsSlice {\n  // Error: forward reference\n  extends Container where Container.SliceType == Self;\n}\n\ninterface Container {\n  ...\n  let SliceType:! ContainerIsSlice;\n  ...\n}\n```\n\nTo work around this problem, we could allow the named constraint to be defined\ninline in the `Container` definition:\n\n```\ninterface Container {\n  ...\n  constraint ContainerIsSlice {\n    extends Container where Container.SliceType == Self;\n  }\n  let SliceType:! ContainerIsSlice;\n  ...\n}\n```\n\nThis alternative seems too cumbersome.\n\n### Self reference instead of `.Self`\n\nAnother alternative instead of using `.Self` for\n[recursive constraints](/docs/design/generics/details.md#recursive-constraints),\nis to use the name of the type being declared inside the type declaration, as in\n`T:! HasAbs(.MagnitudeType = T)`. This had two downsides:\n\n-   Using the name of the type before it is finished being defined created\n    questions about what that name meant. Using the reserved token sequence\n    `.Self` instead makes it clearer that it obeys different rules than other\n    identifier references. For example, that we don't allow members to be\n    accessed.\n-   It doesn't address use cases where we are defining a type-of-type that isn't\n    associated with a type that has a name.\n\n### Implied constraints across declarations\n\nIf constraints on an associated type could be implied by any declaration in the\ninterface, readers and the type checker would be required to scan the entire\ninterface definition and perform many type declaration lookups to understand the\nconstraints on that associated type. This is particularly important when those\nconstraints can be obscured in recursive references to the same interface:\n\n```\ninterface I {\n  let A:! Type;\n  let B:! Type;\n  let C:! Type;\n  let D:! Type;\n  let E:! Type;\n  let SwapType:! I where .A == B and .B == A and .C == C\n                     and .D == D and .E == E;\n  let CycleType:! I where .A == B and .B == C and .C == D\n                      and .D == E and .E == A;\n  fn LookUp(hm: HashMap(D, E)*) -> E;\n  fn Foo(x: Bar(A, B));\n}\n```\n\nThis applies equally to parameters:\n\n```\ninterface I(A:! Type, B:! Type, C:! Type, D:! Type, E:! Type) {\n  let SwapType:! I(B, A, C, D, E);\n  let CycleType:! I(B, C, D, E, A);\n  fn LookUp(hm: HashMap(D, E)*) -> E;\n  fn Foo(x: Bar(A, B));\n}\n```\n\nAll of the type arguments to `I` must actually implement `Hashable`, since\n[an adjacent swap and a cycle generate the full symmetry group on 5 elements](https://www.mathcounterexamples.net/generating-the-symmetric-group-with-a-transposition-and-a-maximal-length-cycle/)).\nAnd additional restrictions on those types would depend on the definition of\n`Bar`. For example, this definition\n\n```\nclass Bar(A:! Type, B:! ComparableWith(A)) { ... }\n```\n\nwould imply that all the type arguments to `I` would have to be comparable with\neach other. This propagation problem means that allowing constraints to be\nimplied in this context is substantial, and potentially unbounded, work for the\ncompiler and human readers.\n\nFrom this we conclude that we need the initial declaration part of an\n`interface`, type definition, or associated type declaration to include a\ncomplete description of all needed constraints.\n\nIt is possible that this reasoning will apply more generally, but we will wait\nuntil we implement type checking to see what restrictions we actually need. For\nexample, we might need to restate \"parameterized type implements interface\"\nconstraints when it is on an associated type in a referenced interface, as in:\n\n```\ninterface HasConstraint {\n  let T:! Type where Vector(.Self) is Printable;\n}\n\ninterface RestatesConstraint {\n  // This works, since it restates the constraint on\n  // `HasConstraint.T` that `U` is equal to.\n  let U:! Type where Vector(.Self) is Printable;\n  // This doesn't work:\n  // ❌ let U:! Type;\n\n  let V:! HasConstraint where .T == U;\n}\n```\n\n### No implied constraints\n\nIssue [#809](https://github.com/carbon-language/carbon-lang/issues/809)\nconsidered whether Carbon would support implied constraints. The conclusion was\nthat implied constraints was an important ergonomic improvement. The framing as\na rewrite to a `where` restriction that did not affect the generic type\nparameter's unqualified API seemed like something that could be explained to\nusers. Potential problems where a specialization of a generic type might allow\nthat type to be instantiated for types that don't satisfy the normal constraints\nwill be considered in the future along with the specialization feature.\n\nWe also considered the alternative where the user would need to explicitly opt\nin to this behavior by adding `& auto` or `& implied_requirements` to their type\nconstraint, as in:\n\n```\nfn LookUp[KeyType:! Type & auto](hm: HashMap(KeyType, i32)*,\n                                 k: KeyType) -> i32;\n\nfn PrintValueOrDefault[KeyType:! Printable & auto,\n                       ValueT:! Printable & HasDefault]\n    (map: HashMap(KeyType, ValueT), key: KeyT);\n```\n\nThe feeling was that implied constraints were natural enough that they didn't\nneed to be signaled by additional marking, with the accompanying ergonomic and\nbrevity loss.\n\n### Type inequality constraints\n\nYou might want an inequality type constraint, for example, to control overload\nresolution:\n\n```\nfn F[T:! Type](x: T) -> T { return x; }\nfn F(x: Bool) -> String {\n  if (x) return \"True\"; else return \"False\";\n}\n\nfn G[T:! Type where .Self != Bool](x: T) -> T {\n  // We need T != Bool for this to type check.\n  return F(x);\n}\n```\n\nThere are some problems with supporting this feature, however.\n[Negative reasoning in general has been a source of difficulties in the implementation of Rust's type system](http://aturon.github.io/tech/2017/04/24/negative-chalk/).\nThis is a type of constraint that is more difficult to use since it would have\nto be repeated by any generic caller, since nothing else can generically\nestablish two types are different.\n\nOur manual type equality approach will not be able to detect situations where\nthe two sides of the inequality in fact have to be equal due to a sequence of\nequality constraints. In those situations, no type will be ever be able to\nsatisfy the inequality constraint.\n\nWe may be able to overcome these difficulties, but we don't expect this feature\nis required since neither Rust nor Swift support it.\n\n### `where .Self is ...` could act like an external impl\n\nWe considered making `T:! A where .Self is B` mean something different than\n`T:! A & B`. In particular, in the former case we considered whether `B` might\nbe considered to be implemented externally for `T`. The advantage of this\nalternative is it gives a convenient way of not polluting the members of `T`\nwith the members of `B`, however it wasn't clear how common that use case would\nbe. Furthermore, it introduced an inconsistency with other associated types. For\nexample:\n\n-   `T:! Container where .ElementType = i32` means that `T.ElementType` has type\n    `i32`.\n-   Following that, given `T:! Container where .ElementType is Printable` and\n    `x: T`, we expect that `x.Front().Print()` to be legal.\n-   To be consistent with the last point, it seems like given\n    `T:! Container where .Self is Printable` and `x: T`, then `x.Print()` should\n    be legal as well.\n\nThis matches Rust, where `T: Container` is considered a synonym for\n`T where T is Container`.\n\n[See the Discord discussion](https://discord.com/channels/655572317891461132/708431657849585705/895794334723637258).\n\n#### Other syntax for external impl\n\nIn a\n[follow up Discord discussion](https://discord.com/channels/655572317891461132/708431657849585705/902728293080530954),\nwe considered allowing developers to write `where .Foo as Bar is Type` to mean\n\"`.Foo` implements interface `Bar` externally.\" We would consider this feature\nin the future once we saw a demonstrated need.\n\n### Other syntax for must be legal type constraints\n\nInstead of `where HashSet(.Self) is Type` to say `.Self` must satisfy the\nconstraints on being an argument to `HashSet`, we considered other syntaxes like\n`where HashSet(.Self) legal` and `where HashSet(.Self)`. The current choice is\nintended to be consistent with the syntax for \"Parameterized type implements\ninterface\" and how implied constraints ensure that parameters to types\nautomatically are given their needed constraints.\n\n### Using only `==` instead of also `=`\n\nOriginally this proposal only used `==` for both setting an associated type to a\nspecific concrete type and saying it was equal to another type variable. The two\ncases affected the type differently. In the specific concrete type case, the\noriginal type-of-type for the associated type doesn't affect the API, you just\nget the API of the type. When equating two type variables, though, the\nunqualified member names are unaffected. The only change was some interfaces may\nbe implemented externally.\n\nIn\n[this Discord discussion](https://discord.com/channels/655572317891461132/708431657849585705/902713789735116821),\nwe decided it might be clearer to use two different operators to reflect the\ndifferent effect. The compiler or a tool can easily correct cases where the\ndeveloper used the wrong one. However, using `=` comes with the downside that it\ndoesn't follow the pattern of other constraints of looking like a boolean\nexpression returning `true` when the constraint is satisfied. We would consider\na different pair of operators here to address this point, perhaps `~` for type\nvariables and `==` for concrete type case.\n\n### Automatic type equality\n\nOther languages, such as Swift and Rust, don't require `observe` declarations or\ncasting for the compiler to recognize two types as transitively equal. The\nproblem is that there is no way to know how many equality constraints need to be\nconsidered before being able to conclude whether two type expressions are equal.\nIn fact, the equality relations form a semi-group, where in general deciding\nwhether two sequences are equivalent is undecidable, see\n[Swift type checking is undecidable - Discussion - Swift Forums](https://forums.swift.org/t/swift-type-checking-is-undecidable/39024).\n\n#### Restricted equality constraints\n\nOne possible approach to this problem is to apply limitations to the equality\nconstraints developers are allowed to express. The goal is to identify some\nrestrictions such that:\n\n-   We have a terminating algorithm to decide if a set of constraints meets the\n    restrictions.\n-   For constraints that meet the restrictions we have a terminating algorithm\n    for deciding which expressions are equal.\n-   Expected use cases satisfy the restrictions.\n\nThe expected cases are things of these forms:\n\n-   `X == Y`\n-   `X == Y.Z`\n-   `X == X.Y`\n-   `X == Y.X`\n-   and _some_ combinations and variations\n\nFor example, here are some interfaces that have been translated to Carbon syntax\nfrom Swift standard library protocols:\n\n```\ninterface IteratorProtocol {\n  let Element:! Type;\n}\n\ninterface Sequence {\n  let Element:! Type;\n  let Iterator:! IteratorProtocol\n    where .Element == Element;\n}\n\ninterface Collection {\n  extends Sequence;\n  let Index:! Type;\n  let SubSequence:! Collection\n    where .Element == Element\n      and .SubSequence == SubSequence\n      and .Index == Index;\n  let Indices:! Collection\n    where .Element == Index\n      and .Index == Index\n      and .SubSequence == Indices;\n}\n```\n\nOne approach we considered is\n[regular equivalence classes](p0818/regular_equivalence_classes.md), however we\nhave not yet been able to figure out how to ensure the algorithm terminates.\nThis is an approach we would like to reconsider if we find solutions to this\nproblem once can share this problem more widely.\n\nOther approaches we considered worked in simple cases but had requirements that\ncould not be validated, since for example they were equivalent to solving the\nsame word problem that makes transitive equality undecidable in general.\n\n#### No explicit restrictions\n\nIf you allow the full undecidable set of `where` clauses, there are some\nunpleasant options:\n\n-   Possibly the compiler won't realize that two expressions are equal even\n    though they should be.\n-   Possibly the compiler will reject some interface declarations as \"too\n    complicated\", due to \"running for too many steps\", based on some arbitrary\n    threshold.\n\nEither way, the compiler will have to perform a lot more work at compile time,\nslowing down builds. There is also a danger that composition of things that\nseparately work or incremental evolution of working code could end up over a\ncomplexity or search depth threshold. In effect, there are still restrictions on\nwhat combinations of equality constraints are allowed, it is just that those\nrestrictions are implicit in the specifics of the algorithm chosen and execution\nlimits used.\n\nOne approach that has been suggested by\n[Slava Pestov](https://forums.swift.org/u/Slava_Pestov) in the context of Swift,\nis to\n[formalize type equality as a term rewriting system](https://forums.swift.org/t/formalizing-swift-generics-as-a-term-rewriting-system/45175).\nThen the equality constraints in an interface or function declaration can be\ncompleted by running the Knuth-Bendix completion algorithm\n([1](https://en.wikipedia.org/wiki/Knuth%E2%80%93Bendix_completion_algorithm#Description_of_the_algorithm_for_finitely_presented_monoids),\n[2](https://academic.oup.com/comjnl/article/34/1/2/427931)) for some limited\nnumber of steps. If the algorithm completes successfully, type expressions may\nthen be efficiently canonicalized. However the algorithm can fail, or fail to\nterminate before hitting the threshold number of steps, in which case the source\ncode would have to be rejected. See\n[this example implementation](https://gist.github.com/slavapestov/75dbec34f9eba5fb4a4a00b1ee520d0b).\n"
  },
  {
    "path": "proposals/p0820.md",
    "content": "# Implicit conversions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/820)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [C++ conversions](#c-conversions)\n        -   [Array-to-pointer conversions](#array-to-pointer-conversions)\n        -   [Function-to-pointer conversions](#function-to-pointer-conversions)\n        -   [Qualification conversions](#qualification-conversions)\n        -   [Integral promotions](#integral-promotions)\n        -   [Floating-point promotions](#floating-point-promotions)\n        -   [Integral conversions](#integral-conversions)\n        -   [Floating-point conversions](#floating-point-conversions)\n        -   [Pointer conversions](#pointer-conversions)\n        -   [Pointer-to-member conversions](#pointer-to-member-conversions)\n        -   [Function pointer conversions](#function-pointer-conversions)\n        -   [Boolean conversions](#boolean-conversions)\n    -   [No conversions](#no-conversions)\n    -   [No extensibility](#no-extensibility)\n    -   [Transitivity](#transitivity)\n\n<!-- tocstop -->\n\n## Problem\n\nFrequently, an expression provided as input to an operation has a type that does\nnot exactly match the expected type. To improve the language ergonomics, we do\nnot want to require explicit conversions in all such cases. However, there is\nstrong evidence from C++ that allowing certain kinds of implicit conversion is\ndangerous and harmful in practice. We need to find a reasonable balance.\n\n## Background\n\nC++ permits many kinds of implicit conversion, some of which are generally\nconsidered good, and others are sometimes harmful. For example:\n\n-   `int` implicitly converts to `long`. This is useful and seldom harmful.\n-   `long` implicitly converts to `int` and to `unsigned int`. This can result\n    in data loss.\n-   `int*` implicitly converts to `bool`. This can be useful in some contexts,\n    such as `if (p)`, but surprising and harmful in others.\n\nSee also\n[implicit conversions in C++](https://en.cppreference.com/w/cpp/language/implicit_conversion).\n\n## Proposal\n\nSee changes to design.\n\n## Rationale based on Carbon's goals\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Disallowing implicit conversions that lose information reduces the risk\n        that existing code will be reinterpreted in a harmful way as libraries\n        in use evolve.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Permitting a limited, safe set of implicit conversions reduces the\n        boilerplate work necessary to write code.\n    -   Generics rely on performing implicit conversions between different\n        type-of-types for deduced type parameters. Applying the same rules\n        consistently for all expressions makes the language simpler.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Providing some of the same implicit conversions as C++ reduces the need\n        to add explicit casts when migrating. However, explicit casts will still\n        be required when the C++ code was performing an operation that we don't\n        consider safe.\n    -   Support for implicit conversions provides a path to expose converting\n        constructors and conversion functions defined in C++ code to Carbon.\n\n## Alternatives considered\n\n### C++ conversions\n\nWe could permit more of the conversions that C++ does. This section considers\neach kind of implicit conversion in C++ and provides a description of the\ndeviation and a rationale.\n\n#### Array-to-pointer conversions\n\nArray types have not yet been designed yet, so this is out of scope for now.\n\nOne possible design would be for pointers to not support arithmetic, and for\narrays to provide \"array iterators\" that do supply such arithmetic. In this\ndesign, an implicit conversion from arrays to array iterators would likely be\nsurprising.\n\n#### Function-to-pointer conversions\n\nFunction pointer types have not been designed yet, and might not exist in the\nsame form as in C++, so this is out of scope for now.\n\nOne possible design would be to have no function pointer types, and instead\nmodel functions as values of a unique type that implements a certain `Callable`\ninterface. Then a function pointer could be modeled as a type-erased generic\nimplementing `Callable`. In this model, there would be an implicit conversion\nfrom a function value to such a type-erased generic value.\n\n#### Qualification conversions\n\nSo far, Carbon has no notion of cv-qualification. However, these conversions\nwould likely be covered by the permission to convert from `T*` to `U*` if `T` is\na subtype of `U`.\n\n#### Integral promotions\n\nCarbon disallows implicit conversion from `bool` to integral types. We could\npermit such implicit conversions.\n\nAdvantages:\n\n-   Improves C++ compatibility.\n-   Permits constructs to count how many of a set of predicates were true:\n    `if (cond1 + cond2 + cond3 >= 2)`.\n\nDisadvantages:\n\n-   Treating truth values as the integers 0 and 1 results in code that is harder\n    to read and understand.\n-   This conversion can result in unexpected overloads being called, when a\n    `bool` argument is passed to a parameter of some other type.\n\n#### Floating-point promotions\n\nThis conversion is permitted.\n\n#### Integral conversions\n\nThese conversions are only permitted when they are known to preserve the\noriginal value. These are the conversions that are considered non-narrowing in\nC++.\n\nWe could permit narrowing integer conversions.\n\nAdvantages:\n\n-   Improves C++ compatibility.\n-   Allows implicitly undoing implicit widening in constructs such as\n    `char n; char c = '0' + n;` where C++ promotes `'0' + n` to `int`.\n    -   However, Carbon is unlikely to implicitly widen to `i32` here.\n\nDisadvantages:\n\n-   Introduces the potential for implicit data loss.\n\n#### Floating-point conversions\n\nCarbon disallows implicit conversion from a more-precise floating-point type to\na less-precise floating-point type, such as from `f64` to `f32`. We could permit\nthese implicit conversions.\n\nAdvantages:\n\n-   Improves C++ compatibility.\n-   Allows implicitly undoing implicit widening in constructs such as\n    `float a, b; float c = a + b;` where C++ promotes `a + b` to `double`.\n    -   However, Carbon might not implicitly widen to `f64` here.\n\nDisadvantages:\n\n-   Introduces the potential for implicit loss of precision.\n-   Introduces the risk that a low-precision operation might be selected when\n    given higher-precision operands.\n\n#### Pointer conversions\n\nCarbon permits the equivalent conversions, except for the conversion from\n`nullptr` to pointer type. We anticipate that Carbon pointers will not be\nnullable by default.\n\nOnce nullable pointers are designed, we would expect an expression representing\nthe null state would be implicitly convertible to the nullable pointer type.\n\n#### Pointer-to-member conversions\n\nCarbon does not yet have pointer-to-member types. This is out of scope for now.\n\n#### Function pointer conversions\n\nCarbon does not yet have function pointer types. This is out of scope for now.\n\n#### Boolean conversions\n\nAn implicit conversion from arithmetic types and pointer types to `bool` is not\nprovided. Pointer types are expected to not be nullable by default, so that part\nis out of scope for now.\n\nWe could permit implicit conversion from arithmetic types to `bool`.\n\nAdvantages:\n\n-   Improves C++ compatibility and familiarity to C++ programmers.\n\nDisadvantages:\n\n-   Harms type safety by permitting an implicit lossy conversion.\n    -   Invites bugs where the wrong overload is selected, where an argument of\n        arithmetic type is passed to a `bool` parameter.\n-   Harms the mental model of `bool` being a choice type rather than an integer\n    type.\n-   Allowing an implicit conversion would permit this kind of conversion\n    everywhere, whereas it is likely only desirable in a select few places, such\n    as where C++ performs a \"contextual conversion to `bool`\".\n\n### No conversions\n\nWe could permit no implicit conversions at all, or restrict the set of\nconversions from those proposed.\n\nAdvantages:\n\n-   Code might be easier to understand, because all conversions would be fully\n    explicit.\n\nDisadvantages:\n\n-   Code is likely to be harder to read and harder to write due to casts being\n    inserted frequently.\n-   Creates tension for generics, where implicit conversions between\n    type-of-types are a central part of the model.\n\n### No extensibility\n\nWe could provide only built-in conversions and no user-defined implicit\nconversions.\n\nAdvantages:\n\n-   Ensures that programmers don't add irresponsible implicit conversions.\n\nDisadvantages:\n\n-   Creates an artificial distinction between built-in and user-defined types.\n-   Creates problems for interoperation with C++ and migration from C++, because\n    certain forms of user-defined implicit conversion are common in C++ code.\n-   Disallows useful functionality without sufficient justification.\n\n### Transitivity\n\nWe could apply implicit conversions transitively. If an implicit conversion from\n`A` to `B` is provided and an implicit conversion from `B` to `C` is provided,\nwe could try to infer an implicit conversion from `A` to `C`.\n\nThis leads to practical problems, as there would be an unbounded search space\nfor intermediate `B` types. For example:\n\n```\nimpl [T:! Constraint1] A as ImplicitAs(T);\nimpl [T:! Constraint2] T as ImplicitAs(B);\nlet x: A = ...;\nlet y: B = x as B;\n```\n\nThere is a potentially unbounded space of types to search here (anything that\nsatisfies both `Constraint1` and `Constraint2` at once. Similarly:\n\n```\nclass X(N: i32, M: i1) {}\nimpl [template N:! i32] X(N, 0) as ImplicitAs(X(N+1, 0));\nimpl [template N:! i32] X(N, 0) as ImplicitAs(X(N+1, 1));\nimpl [template N:! i32] X(N, 1) as ImplicitAs(X(N+1, 1));\nlet z: auto = ({} as X(0, 0)) as X(100, 0);\n```\n\nThis could lead to a very long implicit conversion sequence (which will\npresumably need exponential runtime to find).\n\nWe could support partial transitivity, for only unparameterized intermediate\ntypes, by ignoring all blanket impls. But that would be arbitrary, and we can\nprovide better results by first matching the overall source and destination\ntypes and then asking them what intermediate type we should be converting to,\nwhich is supported by this proposal. For example, for `Optional`:\n\n```\nimpl [T:! Type, U:! ImplicitAs(T)] U as ImplicitAs(Optional(T)) {\n  fn Convert[me: T]() -> Optional(T) { return ...; }\n}\n```\n"
  },
  {
    "path": "proposals/p0826.md",
    "content": "# Function return type inference\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/826)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Lambdas](#lambdas)\n    -   [`auto` keyword](#auto-keyword)\n    -   [`const` qualification](#const-qualification)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Explicit return required](#explicit-return-required)\n    -   [Executable semantics changes](#executable-semantics-changes)\n    -   [Disallow direct recursion](#disallow-direct-recursion)\n        -   [Indirect recursion](#indirect-recursion)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Open questions](#open-questions)\n    -   [Multiple returns](#multiple-returns)\n    -   [`const` qualification](#const-qualification-1)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Only allow `auto` return types if parameters are generic](#only-allow-auto-return-types-if-parameters-are-generic)\n    -   [Provide alternate function syntax for concise return type inference](#provide-alternate-function-syntax-for-concise-return-type-inference)\n    -   [Allow separate declaration and definition](#allow-separate-declaration-and-definition)\n\n<!-- tocstop -->\n\n## Problem\n\nShould there be a shorter way of declaring a function? This embodies two\nquestions:\n\n-   Should there be a way for a declarer to ask that the return type of a\n    function be inferred from returned values?\n-   Should there be an alternate function syntax that provides briefer function\n    declarations for simple cases of return type inference?\n\n## Background\n\nUnder\n[Proposal #438: Add statement syntax for function declarations](https://github.com/carbon-language/carbon-lang/pull/438),\nthe syntax approved was:\n\n> `fn` _identifier_ `(` _args_ `)` _[_ `->` _expression ]_ `{` _statements_ `}`\n\nExecutable semantics currently supports the syntax:\n\n> `fn` _identifier_ `(` _args_ `) =>` _expression_\n\nIn C++, there is similar automatic type inference for return types, although the\nuse of `=>` reflects syntax tentatively discussed for matching use.\n\n### Lambdas\n\nLambdas are also under discussion for Carbon: however, a different syntax is\nlikely to arise. This proposal does not try to address lambda syntax, although\nit is possible that a decision on lambda syntax may lead to an alternate syntax\nfor declaring functions in order to maintain syntax parity.\n\n### `auto` keyword\n\nThis is the first proposal to formally include a use of `auto`; although\n[`var` statement #339](p0339.md) mentions it in an alternative, the proposal did\nnot explicitly propose the keyword. However, the `var x: auto` use-case is\nexpected in Carbon, and so uses of `auto` here can be considered in that\ncontext.\n\nNote the `auto` keyword name and behavior can generally be considered consistent\nwith C++.\n\n### `const` qualification\n\nC++ initially used the matching return type for lambdas. However, it switched to\nits `auto` variable rules, which are defined in terms of template argument\ndeduction and discard `const` qualifiers. This yields subtle behavioral\ndifferences.\n\nNote that `const` is not yet defined in Carbon.\n\n## Proposal\n\nSupport automatic type inference in Carbon with a new `auto` keyword, as in:\n\n> `fn` _identifier_ `(` _args_ `) -> auto {` _statements_ `}`\n\nFor now, only one return statement is allowed: we will avoid defining rules for\nhandling differing return types.\n\nSeparate declarations and definitions are not supported with `auto` return types\nbecause the declaration must have a known return type.\n\n## Details\n\n### Explicit return required\n\nFunctions using `-> auto` must return an expression; using the implicit return\nor `return;` is invalid. This is consistent with the\n[design for returning empty tuples](/docs/design/control_flow/return.md#returning-empty-tuples).\n\n### Executable semantics changes\n\nExecutable semantics will remove the `=>` function syntax.\n\nIn practice, this means the current executable semantics syntax:\n\n```\nfn Add(x: i32, y: i32) => x + y;\n```\n\nBecomes:\n\n```\nfn Add(x: i32, y: i32) -> auto { return x + y; }\n```\n\n### Disallow direct recursion\n\nDirect recursive calls can create complexities in inferring the return type. For\nexample:\n\n```\n// In the return statement.\nfn Factorial(x: i32) -> auto {\n    return (if x == 1 then x else x * Factorial(x - 1));\n}\n\n// Before the return statement, but affecting the return type.\nfn Factorial(x: i32) -> auto {\n    var x: auto = (if x == 1 then x else x * Factorial(x - 1));\n    return x;\n}\n```\n\nAs a consequence, direct recursion is rejected: that is, a function with an\n`auto` return type may not call itself.\n\n#### Indirect recursion\n\nIndirect recursion will typically look like:\n\n```\nfn ExplicitReturn() -> i32;\nfn AutoReturn() -> auto { return ExplicitReturn(); }\nfn ExplicitReturn() -> i32 { return AutoReturn(); }\n```\n\nThis is valid because the return type of `AutoReturn()` can be calculated to be\n`i32` from the forward declaration of `ExplicitReturn`.\n\nDue to how name lookup works, there is no risk of indirect recursion causing\nproblems for typing:\n\n-   A similar separate declaration of an `auto` return is\n    [disallowed](#proposal).\n-   Without a separate declaration, name lookup would fail. That is, the below\n    has a name lookup error at `return B();`:\n\n    ```\n    fn A() -> auto { return B(); }\n    fn B() -> auto { return A(); }\n    ```\n\nAs a consequence, no specific rules about indirect recursion are needed, unlike\ndirect recursion.\n\n## Rationale based on Carbon's goals\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n\n    -   We are avoiding providing an alternative function syntax in order to\n        provide users less syntax they'll need to understand.\n    -   As a practical measure, there are likely to be cases in generic code\n        that are more feasible to write.\n\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n\n    -   The intent is to have `auto` as a return type work similarly to C++'s\n        type inference, in order to ease migration.\n\n## Open questions\n\n### Multiple returns\n\nIt's likely that we should support `auto` on functions with multiple returns.\nThis proposal declines to address that use-case because of the complexities\nwhich arise when return types may differ. Instead, the use-case is left for\nfuture proposals to handle.\n\n### `const` qualification\n\nAs noted in background, [`const` qualification](#const-qualification) has seen\nchanges in C++. While we should work to choose a story that can remain\nlong-term, this will likely be revisited when rules around deduction for\ntemplates are addressed.\n\n## Alternatives considered\n\n### Only allow `auto` return types if parameters are generic\n\n`auto` return types are likely to be a negative impact to readability, because a\nreader must read the function body in order to determine the return type. We\ncould detect whether parameters used in determining an `auto` return type are\ngeneric, and only allow `auto` to be used when they are.\n\nAdvantages:\n\n-   Limits the readability impact of `auto`.\n    -   `auto` could not be used where the return type is clearly deterministic,\n        and thus easy to write. In these cases, readers would never need to look\n        at the function body to determine the return.\n    -   `auto` could be used where the return type may be difficult to easily\n        write as a consequence of potential generic parameters.\n\nDisadvantages:\n\n-   Increases the rule set around use of `auto` in return types.\n-   Breaks C++ compatibility.\n\nThe decision to allow `auto` in more cases is primarily for C++ compatibility.\n\n### Provide alternate function syntax for concise return type inference\n\nExecutable semantics currently demonstrates an alternate function syntax with:\n\n```\nfn Add(x: i32, y: i32) => x + y;\n```\n\nThis is a more concise syntax that builds upon return type inference. We could\nkeep that, or come up with some other syntax.\n\nAdvantages:\n\n-   For short functions, provides a more succinct manner of defining the\n    function.\n-   `=>` use echoes tentative matching syntax.\n\nDisadvantages:\n\n-   Creates an additional syntax which can be used for equivalent behavior.\n-   Overlaps with lambda use-cases, but lambdas will likely end up looking\n    different; that is, we should not assume the syntax will converge.\n    -   We may in particular take a more sharply divergent syntax for lambdas,\n        in order to allow for significant brevity in typing, which may not make\n        sense to support for function declarations.\n-   Limits use of `=>` for other purposes.\n    -   To the extent that `=>` might primarily be replacing `-> auto`, assuming\n        Carbon adopted Rust-style\n        [block expression returns](https://doc.rust-lang.org/reference/expressions/block-expr.html),\n        this offers limited value for the additional token use.\n\nThis proposal suggests not adding an inference-focused alternate function syntax\nat this time; while consistent with tentative matching syntax, the split from\nfunction syntax is significant. The\n[one way principle](/docs/project/principles/one_way.md) applies here.\n\nIf an alternate function syntax is added, it should be done in tandem with a\nlambda proposal in order to ensure consistency in syntax.\n\n### Allow separate declaration and definition\n\nThe return type must be possible to determine from the declaration. As a\nconsequence, the declaration and definition of a function returning `auto`\ncannot be significantly separated: a caller must be able to see the definition.\nThus, although a separate declaration would be insufficient for a call, we could\nallow using `auto` with a separate declaration and definition when the caller\ncan see _both_.\n\nThis example would be valid because `CallAdd` can see the `Add` definition:\n\n```\nfn Add(x: i32, y: i32) -> auto;\n\nfn Add(x: i32, y: i32) -> auto { return x + y; }\n\nfn CallAdd() -> i32 { return Add(1, 2); }\n```\n\nHowever, the following example would be invalid because `CallAdd` can only see\nthe `Add` declaration (even though the definition may be in the same file), and\nit would need the definition to determine the return type:\n\n```\nfn Add(x: i32, y: i32) -> auto;\n\nfn CallAdd() -> i32 { return Add(1, 2); }\n\nfn Add(x: i32, y: i32) -> auto { return x + y; }\n```\n\nAdvantages:\n\n-   Separating the declaration and definition could be used in files to cluster\n    brief declarations, then put definitions below.\n    -   A particularly common use-case of this might be in class declarations,\n        where a user might want to offer a declaration and define it out of line\n        where it doesn't interrupt the class's API.\n    -   It may be preferred to only use `auto` return types with short\n        functions, which limits this advantage as a short function could easily\n        be inlined.\n\nDisadvantages:\n\n-   Cannot be used to break call cycles, which is the usual use of separate\n    declarations and definitions.\n    -   A separate declaration still cannot be called until after the definition\n        is provided.\n    -   This may be particularly confusing to humans.\n\nThe decision is to not support separate declarations and definitions with `auto`\nreturn types due to the limited utility.\n"
  },
  {
    "path": "proposals/p0829.md",
    "content": "# One way principle\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/829)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Provide multiple ways of doing a given thing](#provide-multiple-ways-of-doing-a-given-thing)\n\n<!-- tocstop -->\n\n## Problem\n\nWe have repeatedly run into cases where we could offer equivalent functionality\nmultiple ways.\n\n## Proposal\n\nAdd a principle noting the preference is to only provide one way of doing\nthings.\n\n## Alternatives considered\n\n### Provide multiple ways of doing a given thing\n\nCarbon could focus on providing a lower bar for overlapping functionality,\nencouraging overlapping syntax. This could be considered as similar to Perl's\n[\"There is more than one way to do it.\"](https://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it).\nOverlapping syntax should still receive some scrutiny, but use-cases with small\nmarginal benefits might be considered sufficient to create divergent syntax.\n\nFor example:\n\n-   For matching C++ legacy:\n    -   We might include `for (;;)`.\n    -   We might re-add support for optional braces on `if` and similar.\n    -   We might support `class` and `struct` with their C++-equivalent default\n        visibility rules.\n    -   We might support both `and` and `&&`, `0xa` and `0XA`, etc.\n-   We might make `;` optional, as there's precedent in modern languages to do\n    so.\n-   Both templates and generics might be embraced with feature parity such that\n    both should be good solutions for generic programming problems, as much as\n    possible.\n\nIt's worth noting Perl also has a related motto of \"There is more than one way\nto do it, but sometimes consistency is not a bad thing either.\" It's best to\navoid interpreting this alternative to the extreme: for example, this is not\nencouraging providing all of `extensible`, `extendable`, and `extendible` as\nequivalent keywords, as that is divergence with very minimal benefit\n(particularly `extendable` versus `extendible`).\n\nAdvantages:\n\n-   More likely that developers will find syntax that they like.\n-   Can make it easier to migrate code because we can actively support a\n    C++-like dialect in addition to a more Carbon-centric dialect.\n\nDisadvantages:\n\n-   Developers would either accept personal styles, or create more style guides.\n    -   Either can be considered a language dialect, whether at the personal or\n        organizational level.\n-   Increases the difficulty of building syntax parsing and typo correction in\n    the language, as there are more options that need to be corrected between,\n    multiple of which may be valid in a given context.\n\nWe are declining this alternative because we value the language simplicity\nprovided by minimizing overlap of features.\n"
  },
  {
    "path": "proposals/p0845.md",
    "content": "# `as` expressions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/845)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Future work](#future-work)\n    -   [Provide a mechanism for unsafe conversions](#provide-a-mechanism-for-unsafe-conversions)\n        -   [Casting operator for conversions with domain restrictions](#casting-operator-for-conversions-with-domain-restrictions)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Allow `as` to perform some unsafe conversions](#allow-as-to-perform-some-unsafe-conversions)\n    -   [Allow `as` to perform two's complement truncation](#allow-as-to-perform-twos-complement-truncation)\n    -   [`as` only performs implicit conversions](#as-only-performs-implicit-conversions)\n    -   [Integer to bool conversions](#integer-to-bool-conversions)\n    -   [Bool to integer conversions](#bool-to-integer-conversions)\n\n<!-- tocstop -->\n\n## Problem\n\nWe would like to provide a notation for the following operations:\n\n-   Requesting a type conversion in order to select an operation to perform, or\n    to resolve an ambiguity between possible operations:\n    ```\n    fn Ratio(a: i32, b: i32) -> f64 {\n      // Note that a / b would invoke a different / operation.\n      return a / (b as f64);\n    }\n    ```\n-   Specifying the type that an expression will have or will be converted into,\n    for documentation purposes.\n    ```\n    class Thing {\n      var id: i32;\n    }\n    fn PrintThing(t: Thing) {\n      // 'as i32' reminds the reader what type we're printing.\n      Print(t.id as i32);\n    }\n    ```\n-   Specifying the type that an expression is expected to have, potentially\n    after implicit conversions, as a form of static assertion.\n    ```\n    fn Munge() {\n      // I expect this expression to produce a Widget but I'm getting compiler\n      // errors and I'd like to narrow down why.\n      F(Some().Complex().Expression() as Widget);\n    }\n    ```\n\nIn general, the developer wants to specify that an expression should be\nconsidered to produce a value of a particular type, and that type might be more\ngeneral than the type of the expression, the same as the type of the expression,\nor perhaps might represent a different way of viewing the value.\n\nThe first of the above problems is especially important in Carbon due to the use\nof facet types for generics. Explicit conversions of types to interfaces will be\nnecessary in order to select the meaning of operations, because the same member\nname on different facet types for the same underlying type will in general have\ndifferent meanings.\n\nFor this proposal, the following are out of scope:\n\n-   Requesting a type conversion that changes the value, such as by truncation.\n-   Converting a value to a narrower type or determining whether such a\n    conversion is possible -- `try_as` or `as?` operations.\n\n## Background\n\nC++ provides a collection of different kinds of casts and conversions from an\nexpression `x` to a type `T`:\n\n-   Copy-initialization: `T v = x;`\n-   Direct-initialization: `T v(x);`\n-   Named casts:\n    -   `static_cast<T>(x)`\n    -   `const_cast<T>(x)`\n    -   `reinterpret_cast<T>(x)`\n    -   `dynamic_cast<T>(x)`\n-   C-style casts: `T(x)` or equivalently `(T)x`\n    -   These can do anything that `static_cast`, `const_cast`, and\n        `reinterpret_cast` can do, but ignore access control on base classes.\n-   List-initialization: `T{x}`\n    -   This can do anything that implicit conversion can do, and can also\n        initialize a single -- real or notional -- subobject of `T`.\n    -   Narrowing conversions are disallowed.\n\nThese conversions are all different, and each of them has some surprising or\nunsafe behavior.\n\nSwift provides four forms of type casting operation:\n\n-   `x as T` performs a conversion from subtype to supertype.\n    -   `pattern as T` in a pattern matching context converts a pattern that\n        matches a subtype to a pattern that matches a supertype, by performing a\n        runtime type test. This effectively results in a checked supertype to\n        subtype conversion.\n-   `x as! T` performs a conversion from supertype to subtype, with the\n    assumption that the value inhabits the subtype.\n-   `x as? T` performs a conversion from supertype to subtype, producing an\n    `Optional`.\n-   `T(x)` and similar construction expressions are used to convert between\n    types without a subtyping relationship, such as between integer and\n    floating-point types.\n\nIn Swift, `x as T` is always unsurprising and safe.\n\nRust provides the following:\n\n-   `x as T` performs a conversion to type `T`.\n    -   When there is no corresponding value, some specified value is produced:\n        this conversion will perform 2's complement truncation on integers and\n        will saturate when converting large floating-point values to integers.\n    -   Conversions between distinct pointer types, and between pointers and\n        integers, are permitted. Rust treats accesses through pointers as\n        unsafe, but not pointer arithmetic or casting.\n\nThis cast can perform some conversions with surprising results, such as integer\ntruncation. It can also have surprising performance implications, because it\ndefines the behavior of converting an out-of-range value -- for example, when\nconverting from floating-point to integer -- in ways that aren't supported\nacross all modern targets.\n\nHaskell and Scala support type ascription notation, `x : T`. This has also been\nproposed for Rust. This notation constrains the type checker to find a type for\nthe expression `x` that is consistent with `T`, and is used:\n\n-   for documentation purposes,\n-   to guide the type checker to select a particular meaning of the code in the\n    presence of ambiguity, and\n-   as a diagnostic tool when attempting to understand type inference failures.\n\n## Proposal\n\nCarbon provides a binary `as` operator.\n\n`x as T` performs an unsurprising and safe conversion from `x` to type `T`.\n\n-   This can be used to perform any implicit conversion explicitly. As in Swift,\n    this can therefore be used to convert from subtype to supertype.\n-   This can also be used to perform an unsurprising and safe conversion that\n    cannot be performed implicitly because it's lossy, such as from `i32` to\n    `f32`.\n\nThis operator does not perform conversions with domain restrictions, such as\nconverting from `f32` to `i64`, where sufficiently large values can't be\nconverted. It does not perform operations in which there are multiple different\nreasonable interpretations, such as converting from `i64` to `i32`, where a\ntwo's complement truncation might sometimes be reasonable but where the intent\nis more likely that it is an error to convert a value that does not fit into an\n`i32`.\n\nSee changes to the design for details.\n\n## Rationale based on Carbon's goals\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Providing only unsurprising built-in `as` conversions, and encouraging\n        user-defined types to do the same, makes code easier to understand.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   Syntactically distinguishing between always-safe `as` conversions and\n        potentially-unsafe conversions being performed by other syntax makes it\n        clearer which code should be the subject of more scrutiny when reasoning\n        about safety.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   The `As` interface provides the same functionality as single-argument\n        `explicit` constructors and `explicit` conversion functions in C++, and\n        can be used to expose those operations for interoperability purposes and\n        as a replacement for those operations during migration.\n\n## Future work\n\n### Provide a mechanism for unsafe conversions\n\nWe need to provide additional conversions beyond those proposed for `as`. In\nparticular, to supply the same set of conversions as C++, we would need at least\nthe following conversions that don't match the rules for `as`:\n\nConversions with a domain restriction:\n\n-   Conversions from pointer-to-supertype to pointer-to-subtype.\n-   Conversions from floating-point to integer types that assume the input is\n    in-range.\n-   (Not in C++.) Conversions between any two integer types that assume the\n    input is in-range.\n\nConversions that modify some values:\n\n-   Truncating conversions between any two integer types.\n\nConversions that reinterpret values:\n\n-   Conversions between arbitrary pointer types.\n-   Conversions between integers and pointers.\n-   Bit-casts between arbitrary, sufficiently-trivial types of the same size.\n\nSpecial cases:\n\n-   Some analogue of `dynamic_cast`.\n-   Some analogue of `const_cast`.\n\nWe will need to decide which of these we wish to provide -- in particular,\ndepending on our plans for mutability and RTTI, `const_cast` and `dynamic_cast`\nmay or may not be appropriate.\n\nFor the operations we do supply, we could provide either named functions or\ndedicated language syntax. While this proposal suggests that the `as` operator\nshould not be the appropriate language syntax for the above cases, that decision\nshould be revisited once we have more information from examining the\nalternatives.\n\n#### Casting operator for conversions with domain restrictions\n\nWe could provide an additional casting operator, such as `assume_as` or\n`unsafe_as`, to model conversions that have a domain restriction, such as\n`i64 -> i32` or `f32 -> i64` or `Base*` -> `Derived*`.\n\nAdvantage:\n\n-   Provides additional important but unsafe functionality.\n-   Gives this functionality the appearance of being a central language feature.\n-   Separates safe conversions from unsafe ones.\n\nDisadvantage:\n\n-   Increases complexity.\n-   The connection between these conversions may not be obvious, and the kind\n    and amount of unsafety in practice differs substantially between them.\n\nIf we don't follow this direction, we will need to provide these operations by\nanother mechanism, such as named function calls.\n\n## Alternatives considered\n\n### Allow `as` to perform some unsafe conversions\n\nWe could provide a single type-casting operator that can perform some\nconversions that have a domain restriction, treating values out of range as\nprogramming errors.\n\nOne particularly appealing option would be to permit `as` to convert freely\nbetween integer and floating-point types, but not permit it to convert from\nsupertype to subtype.\n\nAdvantage:\n\n-   Developers many not want to be reminded about the possibility of overflow in\n    conversions to integer types.\n-   This would make `as` more consistent with arithmetic operations, which will\n    likely have no overt indication that they're unsafe in the presence of\n    integer overflow.\n-   If we don't do this, then code mixing differently-sized types will need to\n    use a syntactic notation other than `as`, even if all conversions remain\n    in-bounds. If such code is common, as it is in C++ (for example, when mixing\n    `int` and `size_t`), developers may become accustomed to using that \"assume\n    in range\" notation and not consider it to be a warning sign, thereby eroding\n    the advantage of using a distinct notation.\n\nDisadvantage:\n\n-   If we allow this conversion, there would be no clear foundation for which\n    conversions can be performed by `as` and which cannot in general.\n-   An `as` expression would be less suitable for selecting which operation to\n    perform if it can be unsafe.\n-   Under maintenance, every usage of `as` would need additional scrutiny\n    because it's not in general a safe operation.\n-   This risks being surprising to developers coming from C and C++ where\n    integer type conversions are always safe.\n\nThe choice to not provide these operations with `as` is experimental, and should\nbe revisited when we have more information about the design of integer types and\ntheir behavior.\n\n### Allow `as` to perform two's complement truncation\n\nWe could allow `as` to convert between any two integer types, performing a two's\ncomplement conversion between these types.\n\nAdvantage:\n\n-   Familiar to developers from C++ and various other systems programming\n    languages.\n\nDisadvantage:\n\n-   Makes `as` conversions have behavior that diverges from the behavior of\n    arithmetic, where we expect at least signed overflow to be considered a\n    programming error rather than being guaranteed to wrap around.\n-   Introducing a common and easy notation for conversion with wraparound means\n    that this notation will also be used in the -- likely much more common --\n    case of wanting to truncate a value that is already known to be in-bounds.\n    Compared to having distinct notation for these two operations:\n    -   This removes the ability to distinguish between programming errors due\n        to overflow and intentional wraparound by using the same syntax for\n        both, both for readers of the code and for automated checks in debugging\n        builds.\n    -   This removes the ability to optimize on the basis of knowing that a\n        value is expected to be in-bounds when performing a narrowing\n        conversion.\n\nThe choice to not provide these operations with `as` is experimental, and should\nbe revisited when we have more information about the design of integer types and\ntheir behavior.\n\n### `as` only performs implicit conversions\n\nWe could limit `as` to performing only implicit conversions. This would mean\nthat `as` cannot perform lossy conversions.\n\nAdvantage:\n\n-   One fewer set of rules for developers to be aware of.\n\nDisadvantage:\n\n-   Converting between integer and floating-point types is common, and providing\n    built-in syntax for it seems valuable.\n\n### Integer to bool conversions\n\nWe could allow a conversion of integer types (and perhaps even floating-point\ntypes) to `bool`, converting non-zero values to `true` and converting zeroes to\n`false`.\n\nAdvantage:\n\n-   This treatment of non-zero values as being \"truthy\" and zero values as being\n    \"falsy\" is familiar to developers of various other languages.\n-   Uniform treatment of types that can be notionally converted to a Boolean\n    value may be useful in templates and generics in some cases.\n\nDisadvantage:\n\n-   The lossy treatment of all non-zero values as being \"truthy\" is somewhat\n    arbitrary and can be confusing.\n-   An `as bool` conversion is less clear to a reader than a `!= 0` test.\n-   An `as bool` conversion is more verbose than a `!= 0` test.\n\n### Bool to integer conversions\n\nWe could disallow conversions from `bool` to `iN` types.\n\nAdvantage:\n\n-   More clearly demarcates the intended semantics of `bool` as a truth value\n    rather than as a number.\n-   Avoids making a choice as to whether `true` should map to 1 (zero-extension)\n    or -1 (sign-extension).\n    -   But there is a strong established convention of using 1.\n-   Such conversions are a known source of bugs, especially when performed\n    implicitly. `as` conversions will likely be fairly common and routine in\n    Carbon code due to their use in generics. As such, they may be written\n    without much thought and not given much scrutiny in code review.\n    ```\n    var found: bool = false;\n    var total_found: i32 = 0;\n    for (var (key: i32, value: i32) in list) {\n      if (key == expected) {\n        found = true;\n        total_found += value;\n      }\n    }\n    // Include an explicit `as i64` to emphasize that we're widening the\n    // total at this point.\n    // Bug: meant to pass `total_found` not `found` here.\n    add_to_total(found as i64);\n    ```\n\nDisadvantage:\n\n-   Removes a sometimes-useful operation for which there isn't a similarly terse\n    alternative expression form.\n    -   But we could add a member function `b.AsBit()` if we wanted.\n-   Does not expose the intended connection between the `bool` type and bits.\n\nWe could disallow conversion from `bool` to `i1`.\n\nAdvantage:\n\n-   Avoids a surprising behavior where this conversion converts `true` to -1\n    whereas all others convert `true` to 1.\n\nDisadvantage:\n\n-   Results in non-uniform treatment of conversion from `bool`, and an awkward\n    special case that may get in the way of generics.\n-   A conversion from `bool` that produces -1 for a `true` value is useful when\n    producing a mask, for example in `(b as i1) as u32`.\n"
  },
  {
    "path": "proposals/p0851.md",
    "content": "# Variable type inference\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/851)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Variable type inference in other languages](#variable-type-inference-in-other-languages)\n        -   [Carbon equivalents](#carbon-equivalents)\n    -   [Pattern matching](#pattern-matching)\n        -   [Carbon equivalents](#carbon-equivalents-1)\n    -   [Pattern matching on `if`](#pattern-matching-on-if)\n-   [Proposal](#proposal)\n-   [Open questions](#open-questions)\n    -   [Inferring a variable type from literals](#inferring-a-variable-type-from-literals)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Elide the type instead of using `auto`](#elide-the-type-instead-of-using-auto)\n    -   [Use `_` instead of `auto`](#use-_-instead-of-auto)\n\n<!-- tocstop -->\n\n## Problem\n\nInferring variable types is a common, and desirable, use-case. In C++, the use\nof `auto` for this purpose is prevalent. We desire this enough for Carbon that\nwe already make prevalent use in example code.\n\n## Background\n\nAlthough [#826: Function return type inference](p0826.md) introduced the `auto`\nkeyword for `fn`, the use type inference in `var` should be expected to be more\nprevalent.\n\nIn C++, `auto` can be used in variables as in:\n\n```cpp\nauto x = DoSomething();\n```\n\nIn Carbon, we're already using `auto` extensively in examples in a similar\nfashion. However, it's notable that in C++ the use of `auto` replaces the actual\ntype, and is likely there as a matter of backwards compatibility.\n\n### Variable type inference in other languages\n\n[#618: var ordering](p0618.md) chose the ordering of var based on other\nlanguages. Most of these also provide inferred variable types.\n\nWhere the `<identifier>: <type>` syntax matches, here are a few example inferred\ntypes:\n\n-   [Kotlin](https://kotlinlang.org/docs/basic-syntax.html#variables):\n    `var x = 5`\n-   [Python](https://docs.python.org/3/tutorial/introduction.html): `x = 5`\n-   [Rust](https://doc.rust-lang.org/std/keyword.mut.html): `let mut x = 5;`\n-   [Swift](https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html):\n    `var x = 5`\n\nAda appears to\n[require](https://learn.adacore.com/courses/intro-to-ada/chapters/strongly_typed_language.html#what-is-a-type)\na variable type in declarations.\n\nFor different syntax, [Go](https://tour.golang.org/basics/14) switches from\n`var x int = 5` to `x := 5`, using the `:=` to trigger type inference.\n\n#### Carbon equivalents\n\nIn Carbon, we have generally discussed:\n\n```carbon\nvar x: auto = 5;\n```\n\nHowever, given precedent from other languages, we could omit this:\n\n```carbon\nvar x = 5;\n```\n\n### Pattern matching\n\nAs we consider variable type inference, we need to consider how pattern matching\nwould be affected.\n\n[Swift's patterns](https://docs.swift.org/swift-book/ReferenceManual/Patterns.html)\nsupport:\n\n-   Value-binding patterns, as in:\n\n    ```swift\n    switch point {\n      case let (x, y):\n        ...\n    }\n    ```\n\n-   Expression patterns, as in:\n\n    ```swift\n    switch point {\n      case (0, 0):\n        ...\n      case (x, y):\n        ...\n    }\n    ```\n\n-   **Combining** the above, as in:\n\n    ```swift\n    switch point {\n      case (x, let y):\n        ...\n    }\n    ```\n\n#### Carbon equivalents\n\nWith Carbon, we have generally discussed:\n\n-   Value-binding patterns, as in:\n\n    ```carbon\n    match (point) {\n      case (x: auto, y: auto):\n        ...\n    }\n    ```\n\n-   Expression patterns, as in:\n\n    ```carbon\n    match (point) {\n      case (0, 0):\n        ...\n      case (x, y):\n        ...\n    }\n    ```\n\n-   **Combining** the above, as in:\n\n    ```carbon\n    match (point) {\n      case (x, y: auto):\n        ...\n    }\n    ```\n\nHowever, it may be possible to mirror Swift's syntax more closely; for example:\n\n-   Value-binding patterns, as in:\n\n    ```carbon\n    match (point) {\n      case let (x, y):\n        ...\n    }\n    ```\n\n-   Expression patterns, as in:\n\n    ```carbon\n    match (point) {\n      case (0, 0):\n        ...\n      case (x, y):\n        ...\n    }\n    ```\n\n-   **Combining** the above, as in:\n\n    ```carbon\n    match (point) {\n      case (x, let y):\n        ...\n    }\n    ```\n\nIn the above, this presumes to allow `let` inside a tuple in order to indicate\nthe variable-binding for one member of a tuple.\n\n### Pattern matching on `if`\n\nIn Carbon, it's been suggested that `if` could support testing pattern matching\nwhen there's only one case, for example with `auto`:\n\n```carbon\nmatch (point) {\n  case (x, y: auto):\n    // Pattern match succeeded, `y` is initialized.\n  default:\n    // Pattern match failed.\n}\n\n=>\n\nif ((x, y: auto) = point) {\n  // Pattern match succeeded, `y` is initialized.\n} else {\n  // Pattern match failed.\n}\n```\n\nA `let` approach may still look like:\n\n```carbon\nmatch (point) {\n  case (x, let y):\n    // Pattern match succeeded, `y` is initialized.\n  default:\n    // Pattern match failed.\n}\n\n=>\n\nif ((x, let y) = point) {\n  // Pattern match succeeded, `y` is initialized.\n} else {\n  // Pattern match failed.\n}\n```\n\nSome caveats should be considered for pattern matching tests inside `if`:\n\n-   There is syntax overlap with C++, which allows code such as:\n\n    ```cpp\n    if (Derived* derived = dynamic_cast<Derived*>(base)) {\n      // dynamic_cast succeeded, `derived` is initialized.\n    } else {\n      // dynamic_cast failed.\n    }\n    ```\n\n-   Syntax is similar to `match` itself; it may be worth considering whether the\n    feature is\n    [sufficiently distinct and valuable](/docs/project/principles/one_way.md) to\n    support.\n\n## Proposal\n\nCarbon should offer variable type inference using `auto` in place of the type,\nas in:\n\n```carbon\nvar x: auto = DoSomething();\n```\n\nAt present, variable type inference will simply use the type on the right side.\nIn particular, this means that in the case of `var y: auto = 1`, the type of `y`\nis `IntLiteral(1)` rather than `i64` or similar. This\n[may change](#inferring-a-variable-type-from-literals), but is the simplest\nanswer for now.\n\n## Open questions\n\n### Inferring a variable type from literals\n\nUsing the type on the right side for `var y: auto = 1` currently results in a\nconstant `IntLiteral` value, whereas most languages would suggest a variable\ninteger value. This is something that will be considered as part of type\ninference in general, because it also affects generics, templates, lambdas, and\nreturn types.\n\n## Rationale based on Carbon's goals\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Frequently code will have the type on the line, as in\n        `var x: auto = CreateGeneric[Type](args)`. Avoiding repetition of the\n        type will reduce the amount of code that must be read, and should allow\n        readers to comprehend more quickly.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   The intent is to have `auto` work similarly to C++'s type inference, in\n        order to ease migration.\n\n## Alternatives considered\n\n### Elide the type instead of using `auto`\n\nAs discussed in background,\n[other languages allow eliding the type](#variable-type-inference-in-other-languages).\nCarbon could do similar, allowing:\n\n```carbon\nvar y = 1;\n```\n\nAdvantages:\n\n-   Forms a cross-language syntax consistency with languages that put the type\n    on the right side of the identifier.\n    -   This is particularly strong with Kotlin and Swift, because they also use\n        `var`.\n-   Use of `auto` is currently unique to C++; Carbon will be extending its use.\n\nDisadvantages:\n\n-   Type inference becomes the _lack_ of a type, rather than the presence of\n    something different.\n-   C++'s syntax legacy may have needed `auto` in order to provide type\n    inference, where Carbon does not.\n-   Removes syntactic distinction between binding of a new name and reference to\n    an existing name, [particularly for pattern matching](#pattern-matching).\n    Reintroducing this distinction would likely require additional syntax, such\n    as Swift's nested `let`.\n\nWe expect there will be long-term pushback over the cross-language\ninconsistency, particularly as the `var <identifier>: auto` syntax form will be\nunique to Carbon. However, there's a strong desire not to have the lack of a\ntype mean the type will be inferred.\n\n### Use `_` instead of `auto`\n\nWe have discussed using `_` as a placeholder to indicate that an identifier\nwould be unused, as in:\n\n```carbon\nfn IgnoreArgs(_: i32) {\n  // Code that doesn't need the argument.\n}\n```\n\nWe could use `_` instead of `auto`, leading to:\n\n```carbon\nvar x: _ = 1;\n```\n\nHowever, removing `auto` entirely would also require using `_` when inferring\nfunction return types. For example:\n\n```carbon\nfn InferReturnType() -> _ {\n  return 3;\n}\n```\n\nAdvantages:\n\n-   Reduces the number of keywords in Carbon.\n-   Less to type.\n    -   The incremental convenience may ameliorate the decision to require a\n        keyword for type inference.\n\nDisadvantages:\n\n-   There's a feeling that `_` means \"discard\", which doesn't match the\n    semantics of inferring a return type, since the type is not discarded.\n-   There may be some ambiguities in handling, such as `var c: (_, _) = (a, b)`.\n-   The reduction of typing is unlikely to address arguments that the keyword is\n    not technically required.\n\nThe sense of \"discard\" versus \"infer\" semantics is why we are using `auto`.\n"
  },
  {
    "path": "proposals/p0861.md",
    "content": "# Naming conventions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/861)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Cross-language precedent](#cross-language-precedent)\n    -   [Carbon artifacts](#carbon-artifacts)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Constants](#constants)\n    -   [Carbon-provided item naming](#carbon-provided-item-naming)\n-   [Open questions](#open-questions)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Other naming conventions](#other-naming-conventions)\n    -   [Other conventions for naming Carbon types](#other-conventions-for-naming-carbon-types)\n\n<!-- tocstop -->\n\n## Problem\n\nThe goal of this proposal is to establish naming conventions for:\n\n-   Idiomatic Carbon code.\n-   Carbon-provided features, including:\n    -   Keywords, such as `fn` or `for`.\n    -   Type literals, such as `i32`.\n    -   Types, such as `bool` or `String`.\n\nThe reason for resolving this through proposal is to ensure we're headed in a\nreasonably consistent path as we write early documentation and example code.\n\n## Background\n\n### Cross-language precedent\n\nNaming conventions are an issue frequently addressed by style guides. A few\nexamples of language-provided guidelines are:\n\n-   [Effective Go](https://golang.org/doc/effective_go#names)\n-   [Python's PEP 8](https://www.python.org/dev/peps/pep-0008/#naming-conventions)\n    -   Note PEP 8 offers a list of\n        [naming styles](https://www.python.org/dev/peps/pep-0008/#descriptive-naming-styles).\n-   [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/naming.html)\n-   [Swift's API Design Guidelines](https://swift.org/documentation/api-design-guidelines/#general-conventions)\n\n### Carbon artifacts\n\nRelated issues:\n\n-   Issue\n    [#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543)\n    covers numeric type literal naming.\n-   Issue\n    [#750: Naming conventions for Carbon-provided features](https://github.com/carbon-language/carbon-lang/issues/750)\n    was used for initial naming convention discussion.\n\nRelated proposals:\n\n-   Proposal\n    [#720: Property naming in C++](https://github.com/carbon-language/carbon-lang/pull/720)\n    covers nuances of property naming.\n\n## Proposal\n\nOnly `UpperCamelCase` and `lower_snake_case` conventions will be used, in order\nto minimize the variation in rules.\n\n-   For idiomatic Carbon code:\n    -   `UpperCamelCase` will be used when the named entity cannot have a\n        dynamically varying value. For example, functions, namespaces, or\n        compile-time constant values.\n    -   `lower_snake_case` will be used when the named entity's value won't be\n        known until runtime, such as for variables.\n-   For Carbon-provided features:\n    -   Keywords and type literals will use `lower_snake_case`.\n    -   Other code will use the guidelines for idiomatic Carbon code.\n\nIn other words:\n\n| Item                      | Convention         | Explanation                                                                                |\n| ------------------------- | ------------------ | ------------------------------------------------------------------------------------------ |\n| Packages                  | `UpperCamelCase`   | Used for compile-time lookup.                                                              |\n| Types                     | `UpperCamelCase`   | Resolved at compile-time.                                                                  |\n| Functions                 | `UpperCamelCase`   | Resolved at compile-time.                                                                  |\n| Methods                   | `UpperCamelCase`   | Methods, including virtual methods, are equivalent to functions.                           |\n| Generic parameters        | `UpperCamelCase`   | May vary based on inputs, but are ultimately resolved at compile-time.                     |\n| Compile-time constants    | `UpperCamelCase`   | Resolved at compile-time. See [constants](#constants) for more remarks.                    |\n| Variables                 | `lower_snake_case` | May be reassigned and thus require runtime information.                                    |\n| Member variables          | `lower_snake_case` | Behave like variables.                                                                     |\n| Keywords                  | `lower_snake_case` | Special, and developers can be expected to be comfortable with this casing cross-language. |\n| Type literals             | `lower_snake_case` | Equivalent to keywords.                                                                    |\n| Boolean type and literals | `lower_snake_case` | Equivalent to keywords.                                                                    |\n| Other Carbon types        | `UpperCamelCase`   | Behave like normal types.                                                                  |\n| `Self` and `Base`         | `UpperCamelCase`   | These are similar to type members on a class.                                              |\n\n## Details\n\n### Constants\n\nSupposing `let` might be used to designate a constant, consider the following\ncode:\n\n```carbon\npackage Example;\n\nlet CompileTimeConstant: i32 = 7;\n\nfn RuntimeFunction(runtime_constant: i32);\n```\n\nIn this example, `CompileTimeConstant` has a singular value (`7`) which is known\nat compile-time. As such, it uses `UpperCamelCase`.\n\nOn the other hand, `runtime_constant` may be constant within the function body,\nbut it is assigned at runtime when `RuntimeFunction` is called. Its value is\nonly known in a given runtime invocation of `RuntimeFunction`. As such, it uses\n`lower_snake_case`.\n\n### Carbon-provided item naming\n\nCarbon-provided items are split into a few categories:\n\n-   Keywords; for example, `for`, `fn`, and `var`\n-   Type literals; for example, `i<digits>`, `u<digits>`, and `f<digits>`\n-   Boolean type and literals; for example, `bool`, `true`, and `false`\n    -   The separate categorization of booleans should not be taken as a rule\n        that only booleans would use lowercase; it's just the only example right\n        now.\n-   `Self` and `Base`\n-   Other Carbon types; for example, `Int`, `UInt`, and `String`\n\nNote that while other Carbon types currently use `UpperCamelCase`, that should\nnot be inferred to mean that future Carbon types will do the same. The leads\nwill make decisions on future naming.\n\n## Open questions\n\n## Rationale based on Carbon's goals\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   The intent is that limiting to `UpperCamelCase` and `lower_snake_case`\n        will offer developers a limited number of style rules to learn.\n    -   There is a desire to maintain good ergonomics for developers.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   There is a general desire to maintain naming consistency with C++, and\n        this can be seen with keywords such as `for` as well as booleans.\n\n## Alternatives considered\n\n### Other naming conventions\n\nA couple naming conventions that were discussed briefly are:\n\n-   `lowerCamelCase` names came up, but are hard to distinguish from\n    `lower_snake_case` for single-word identifiers. By contrast,\n    `UpperCamelCase` and `lower_snake_case` are distinct, whether a single word\n    or multiple.\n-   `ALL_CAPS_SNAKE_CASE` is used in C++ code, such as for macros and\n    compile-time constants. With Carbon, we hope the language is simple enough\n    that the readability benefit of an additional naming convention wouldn't\n    outweigh the cost of giving developers more naming conventions to learn.\n\n### Other conventions for naming Carbon types\n\nIn detail, individual naming decisions that had alternative patterns or options\ndiscussed were:\n\n-   Type literals use `lower_snake_case` as described in issue\n    [#543: pick names for fixed-size integer types](https://github.com/carbon-language/carbon-lang/issues/543).\n    -   `i8` is more ergonomic than `Int8` for brevity.\n    -   `i32` and `i64` maintain the same length as C++'s `int`.\n    -   We don't want to use `I32` because `I32` can be hard to visually\n        distinguish with `132` or `l32`, even though it may help screen readers.\n-   Booleans use `bool`, `true`, and `false` mainly because there's a desire not\n    to skew from C++.\n    -   While leads are okay with some things being shadowed, such as `Self` and\n        `Base`, there is a desire not to allow shadowing of booleans.\n-   `Self` and `Base` are `UpperCamelCase` because leads want them to look more\n    like normal types.\n    -   They may be implemented as a hybrid approach, using something similar to\n        lookup in classes so they aren't quite keywords, but somewhat similar to\n        keywords because leads may want to reject them as identifiers in\n        non-class contexts.\n-   `String` and potentially other names follow idiomatic naming conventions.\n    -   Note that, in this case, divergence from C++ is accepted.\n\nTaking that into consideration, and that we are likely to keep\n`lower_snake_case` for keywords and type literals in particular, a couple\noptions discussed would have mainly affect `self`, `base`, and `string`:\n\n-   Anything language-provided without needing an `import` is always\n    `lower_snake_case`.\n    -   `i32`, `bool`, `true`, `self`, `base`, `string.is_empty()`\n-   As above, but prelude class members follow standard naming conventions.\n    -   `i32`, `bool`, `true`, `self`, `base`, `string.IsEmpty()`\n\nThe understanding is that the difference between `bool` being treated similarly\nto a keyword and `Self` being treated similarly to a type (both regardless of\nimplementation) is somewhat arbitrary. The decision not to use\n`lower_snake_case` consistently depends mainly on the leaning of the leads, that\n`self` and `base` felt like they shouldn't strictly be treated as keywords, and\n`string` felt like the point where users should expect something more like an\nidiomatic class. Future borderline cases may need to be decided by leads whether\nthey should be treated as more keyword-like or type-like.\n"
  },
  {
    "path": "proposals/p0866.md",
    "content": "# Allow ties in floating literals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/866)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Problem\n\nProposal [#143](https://github.com/carbon-language/carbon-lang/pull/143)\nsuggested that we do not allow ties in floating-point literals. That is, given a\nliteral whose value lies exactly half way between two representable values, we\nshould reject rather than arbitrarily picking one of the two possibilities.\n\nHowever, the [statistical argument](p0143.md#ties) presented in that proposal\nmisses an important fact: the distribution of the values that are exactly half\nway between representable values includes several values of the form A x\n10<sup>B</sup>, where A and B are small integers.\n\nFor example, the current rule rejects this very reasonable looking code:\n\n```\nvar v: f32 = 9.0e9;\n```\n\n... because 9 x 10<sup>9</sup> lies exactly half way between the nearest two\nrepresentable values of type `f32`, namely 8999999488 and 9000000512. Similar\nexamples exist for larger floating point types:\n\n```\n// Error, half way between two exactly representable values.\nvar w: f64 = 5.0e22;\n```\n\nWe would also reject an attempted workaround such as:\n\n```\nvar v: f32 = 5 * 1.0e22;\n```\n\n... because the literal arithmetic would be performed exactly, resulting in the\nsame tie. A workaround such as\n\n```\nvar v1: f32 = 5.0e22 + 1.0;\nvar v2: f32 = 5.0e22 - 1.0;\n```\n\n... to request rounding upwards and downwards, respectively, would work.\nHowever, these seem cumbersome and burden the Carbon developer with\nfloating-point minutiae about which they very likely do not care.\n\n## Background\n\nFor background on the ties-to-even rounding rule, see\n[this Wikipedia article](https://en.wikipedia.org/wiki/Rounding#Round_half_to_even).\nThe ties-to-even rule is the default rounding mode specified by ISO 60559 /\nIEEE 754.\n\n## Proposal\n\nInstead of rejecting exact ties, we use the default IEEE floating point rounding\nmode: we round to even.\n\n## Details\n\nSee design changes.\n\n## Rationale based on Carbon's goals\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   This improves the ease of both reading and writing floating-point\n        literals that would result in ties.\n    -   This improves the language consistency, by performing the same rounding\n        when converting literals as is performed by default when converting\n        runtime values.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   It is unlikely that making an arbitrary but consistent rounding choice\n        will harm safety or program correctness.\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n-   [Modern OS platforms, hardware architectures, and environments](/docs/project/goals.md#modern-os-platforms-hardware-architectures-and-environments)\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   This rule, likely because it is the IEEE default rounding mode, already\n        appears to be used by major C++ compilers such as Clang, GCC, MSVC, and\n        ICC.\n\n## Alternatives considered\n\nWe could round to even only for decimal floating-point literals, and still use\nthe rule that ties are rejected for hexadecimal floating point. In the latter\ncase, a tie means that too many digits were specified, and the trailing digits\nwere exactly `80000...`.\n\nHowever, because we support arithmetic on literals, forming other literals, this\nwould mean that whether a literal was originally written in hexadecimal would\nform part of its value and thereby part of its type. There would also be\nproblems with literals produced by arithmetic. The complexity involved here far\noutweighs any perceived benefit of diagnosing mistyped literals.\n"
  },
  {
    "path": "proposals/p0875.md",
    "content": "# Principle: information accumulation\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/875)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Single-pass \"splat\" compilation](#single-pass-splat-compilation)\n    -   [Global consistency](#global-consistency)\n    -   [The C++ compromise](#the-c-compromise)\n    -   [Separate declarations and definitions](#separate-declarations-and-definitions)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Goals](#goals)\n    -   [Choice of alternative](#choice-of-alternative)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Separate declaration and definition](#separate-declaration-and-definition)\n        -   [Allow separate declaration and definition](#allow-separate-declaration-and-definition)\n            -   [Analysis](#analysis)\n        -   [Disallow separate declaration and definition](#disallow-separate-declaration-and-definition)\n            -   [Analysis](#analysis-1)\n    -   [Information flow](#information-flow)\n        -   [Strict top-down](#strict-top-down)\n            -   [Analysis](#analysis-2)\n        -   [Strict global consistency](#strict-global-consistency)\n            -   [Block-scope exception](#block-scope-exception)\n            -   [Analysis](#analysis-3)\n        -   [Top-down with minimally deferred type checking](#top-down-with-minimally-deferred-type-checking)\n            -   [Analysis](#analysis-4)\n        -   [Top-down with deferred method bodies](#top-down-with-deferred-method-bodies)\n            -   [Analysis](#analysis-5)\n        -   [Context-sensitive local consistency](#context-sensitive-local-consistency)\n            -   [Analysis](#analysis-6)\n\n<!-- tocstop -->\n\n## Problem\n\nWe should have consistent rules describing what information about a program is\nvisible where.\n\n## Background\n\nInformation in a source file is provided incrementally, with each source\nutterance providing a small piece of the overall picture. Different languages\nhave different rules for which information is available where.\n\n### Single-pass \"splat\" compilation\n\nIn C and other languages of a similar age, single-pass compilation was highly\ndesirable, due to resource limits and performance concerns. In these languages:\n\n-   Information is accumulated top-down, and can only be used lexically after it\n    appears.\n-   Most information can be discarded soon after it is provided: function bodies\n    don't need to be kept around once they've been converted to the output\n    format, and no information on local variable or parameter names needs to\n    persist past the end of the variable's scope. However, the types of globals\n    and the contents of type definitions must be retained.\n-   The behavior of an entity can be different at different places in the same\n    source file. An early use may fail if it depends on information that's\n    provided later, and in some cases a later use may fail when an earlier use\n    succeeded because the use is invalid in a way that was not visible at the\n    point of an earlier use.\n\n### Global consistency\n\nIn more modern languages such as C#, Rust, Java, and Swift, there is no lexical\ninformation ordering. In these languages:\n\n-   Information is effectively accumulated and processed in separate passes.\n-   The language design and implementation ensure that the behavior of an entity\n    is the same everywhere: both before its definition, after its definition,\n    within its definition, and in any other source file in which it was made\n    visible.\n-   Dependency cycles between program properties are carefully avoided by the\n    language designers.\n\n### The C++ compromise\n\nIn C++, a hybrid approach is taken. There is a C-like lexical information\nordering rule, but this rule is subverted within classes by -- effectively --\nreordering certain parts of a class that appear within the class definition so\nthat they are processed after the class definition. This primarily applies to\nthe bodies of member functions. Here:\n\n-   Information is mostly accumulated top-down, and is accumulated fully\n    top-down after the reordering step.\n-   The behavior of a class is the same within member function bodies that are\n    defined inside the class as it is within member function bodies defined\n    lexically after the class.\n-   The language designers need to ensure that the bounds of the member function\n    bodies and similar constructs can be determined without parsing them, so\n    that the late-parsed portions can be separated from the early-parsed\n    portions. In C++, this was not done successfully, and there are constructs\n    for which this determination is very hard or impossible.\n\n### Separate declarations and definitions\n\nSomewhat separate from the direction of information flow is the ability to\nseparate the information about an entity into multiple distinct regions of\nsource files. In C and C++, entities can be separately declared and defined. As\na consequence, these languages need rules to determine whether two declarations\ndeclare the same entity.\n\nIn C++, especially for templated declarations, these rules can be incredibly\ncomplex, and even now, more than 30 years after the introduction of templates in\nC++, [basic questions are not fully answered](https://wg21.link/cwg2), and\nimplementations disagree about which declarations declare the same entity in\nfairly simple examples.\n\nOne key benefit of this separation is in reduction of _physical dependencies_:\nin order to validate a usage of an entity, we need only see a source file\ncontaining a declaration of that entity, and need never consider the source file\ncontaining its definition. This both reduces the number of steps required for an\nincremental rebuild and reduces the input information and processing required\nfor each individual step.\n\nThe ability to break physical dependencies is limited to the cases where\ninformation can actually be hidden from the users of the entity. For example, if\nthe user actually needs a function body, either because they will evaluate a\ncall to the function during compilation or because they will inline it prior to\nlinking, it cannot be physically isolated from the user of that information. As\na consequence, in C++, a programmer must carefully manage which information they\nput in the source files that are exposed to client code and which information is\nkept separate.\n\nAnother key benefit is that the exported interface of a source file can become\nmore readable, by presenting an interface that contains only the facts that are\nsalient to a user and not the implementation details.\n\n## Proposal\n\nCarbon will use a\n[top-down approach with deferred method bodies](#top-down-with-deferred-method-bodies),\nwith [forward declarations](#allow-separate-declaration-and-definition).\n\nIn any case where the [strict global consistency](#strict-global-consistency)\nmodel with the [block-scope exception](#block-scope-exception) would consider\nthe program to be invalid or would assign it a different meaning, the program is\ninvalid.\n\nPut another way: we accept exactly the cases where those two models both accept\nand give the same result, and reject all other cases.\n\n## Details\n\nEach entity has only one meaning and only one set of properties; that meaning\nand those properties do not depend on which source file you are within or where\nin that source file you are. However, not all information will be available\neverywhere, and it is an error to attempt to use information that is not\navailable -- either because it's in a different source file and not exported or\nnot imported, or because it appears later in the same source file.\n\nFor example, a full definition of a class `Widget` may be available in some\nparts of the program, with only a forward declaration available in other parts\nof the program. In this case, any attempt to use `Widget` where only a forward\ndeclaration is available will always either result in the program being invalid\nor doing the same thing that would happen if the full information were\navailable. This is a stronger guarantee than is provided by C++'s One Definition\nRule, which guarantees that every use sees an equivalent definition or no\ndefinition, but does not guarantee that every use has the same behavior -- in\nC++ a function could do one thing if `Widget` is defined and a different thing\nif `Widget` is only forward declared, and that will not be possible in Carbon.\n\nName lookup only provides earlier-declared names. However, the bodies of class\nmember functions that are defined inside the class are reordered to be\nseparately defined after the class, so all class member names are declared\nbefore the class body is seen. Unlike in C++, classes are either incomplete or\ncomplete, with no intermediate state. Any attempt to perform name lookup into an\nincomplete class is an error, even if the name being looked up has already been\ndeclared.\n\n```\nclass A {\n  fn F() {\n    // OK: A and B are complete class types here.\n    var b: A.B;\n  }\n\n  class B {}\n\n  // Error: cannot look up B within incomplete class A.\n  var p: A.B*;\n}\n```\n\nForward declarations are permitted in order to allow separation of interface and\nimplementation whenever the developer wishes to do so, and introduce names early\nin order to break cycles or when the developer does not wish to define entities\nin topological order. All declarations of an entity are required to be part of\nthe same library, but can be in different source files. If a point within a\nsource file can only see a declaration of an entity and not its definition, some\nuses of that entity will be invalid that would be valid if the definition were\nvisible. For example, without a class definition, we may be unable to create\ninstances of the class, and without a function definition, we may be unable to\nuse the function to compute a compile-time constant.\n\n### Goals\n\nFor this proposal, we have the following goals as refinements of the overall\nCarbon goals:\n\n-   _Comprehensibility._ Our rules should be understandable, and should minimize\n    surprise and gotchas. Our behavior should be self-consistent, and\n    explainable in only a few sentences.\n-   _Ergonomics._ It should be easy to express common developer desires, without\n    a lot of boilerplate or repetitive code.\n-   _Readability._ Code written using our rules should be as straightforward as\n    possible for Carbon developers to read and reason about.\n-   _Efficient and simple compilation._ It should be relatively straightforward\n    to implement our semantic rules. Implementation heroics shouldn't be\n    required, and the number of special cases required should be minimized.\n-   _Diagnosability._ An implementation should be able to explain coding errors\n    in ways that are easy to understand and are well-correlated with the error\n    and its remedy. Diagnostics should appear in an order and style that guides\n    the developer through logical steps to fix their mistakes.\n-   _Toolability._ Relatively simple tools should be able to understand simpler\n    properties of Carbon code. It should ideally be possible to identify which\n    names can be used in a particular context and what those names mean without\n    full processing. It should ideally be possible to gather useful and mostly\n    complete information about a potentially-invalid source file that is\n    currently being edited, for which it may be desirable to assume there is a\n    \"hole\" in the source file at the cursor position that will be filled by\n    unknown code.\n\n### Choice of alternative\n\nWe have a large space of options here, all of which have both benefits and\ndrawbacks. The rationale for our choice is as follows:\n\nThe first consideration is whether to provide a\n[globally consistent view](#strict-global-consistency) of code. Providing such a\nview would require us to find a compatible build process that can scale to large\nprojects; see the [detailed analysis](#analysis-3) for details. Moreover, this\nis likely to be a choice that is relatively hard to evolve away from. A\nnon-scalable build process would be an existential threat to the Carbon language\nunder its stated goals, so we set this option aside. This should be revisited if\na complete design for a scalable build process with a globally-consistent\nsemantic model is proposed.\n\nOnce we step away from strict global consistency, there will be cases where the\nmeaning of an entity differs in different parts of the program. In order for\nprograms to behave consistently and predictably, especially in the presence of\ntemplates and generics, we do not want to allow the same operation to have two\nor more different behaviors depending on which information is available. So we\nchoose to make programs invalid if they would make use of information that is\nnot available.\n\nEven though we have chosen not to provide a globally consistent view, we could\nstill choose to provide a consistent view throughout a package, library, or\nsource file, such as in the\n[context-sensitive local consistency](#context-sensitive-local-consistency)\nmodel. However, again for build performance reasons, we want to avoid\npackage-at-a-time or even library-at-a-time compilation, and would like a\nfile-at-a-time compilation strategy. The cost of having different views in\ndifferent files is substantially reduced given that we have already chosen to\nhave different views at least in different packages. So we allow the known\ninformation about an entity to vary between source files, even in the same\nlibrary.\n\nThis implies that we at least need forward declarations for entities that are\ndeclared in an `api` file for a library and defined in an `impl` file. However,\nthis leaves the question of what happens within a single source file: do\nentities need to be manually written in dependency order, or is the\nimplementation expected to use information that appears after its point of\ndeclaration? Neither option guarantees that an entity will behave consistently\nwherever it's used, because we already gave up that guarantee for entities\nvisible across source files, and we need to cope with the resulting risk of\nincoherence anyway.\n\nThe simplest option for implementation, and the one most similar to C++, would\nthen be to accumulate information top-down. This is also the choice that is most\nconsistent with the cross-source-file behavior: moving a prefix of a source file\ninto a separate, imported file should generally preserve the validity of the\nprogram. Further, this choice gives us the most opportunity for future language\nevolution, as it is the most restrictive option, and hence it is\nforward-compatible with the other rules under consideration, as well as\nsupporting paths for evolution that require a top-down view, such as some\napproaches to metaprogramming.\n\nThis choice implies that we need forward declarations, both for declarations in\ndifferent source files from their definitions and to resolve cycles or cases\nwhere the developer cannot or does not wish to write code in topological order.\nAllowing separate declaration and definition may also be valuable to allow the\ncode author to hide implementation details from readers of the interface, and\npresent a condensed catalog or table of contents for the library. This is also\nan important aspect in providing a language that is familiar to C++ developers.\nSo we choose to\n[allow separate declaration and definition](#allow-separate-declaration-and-definition)\nin general.\n\nGiven the above decisions, class member functions could not be meaningfully\ndefined inline under a strict top-down rule, because the class would not yet be\ncomplete. We make an ergonomic affordance of reordering the bodies of such\nfunctions as if they appear after the class definition. This also improves\nconsistency with C++, which has a similar rule.\n\n## Rationale based on Carbon's goals\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   See \"Toolability\" goal.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Ensuring that the program interpretation is consistent with an\n        interpretation with full information makes it easier to evolve code, as\n        changing the amount of visible information -- for example, by reordering\n        code or by adding or removing imports -- cannot change the meaning of a\n        program from one valid meaning to another.\n    -   Selecting a rule that disallows information from flowing backwards keeps\n        open more language evolution paths:\n        -   We could allow more information to flow backwards.\n        -   We could expose metaprogramming constructs that can inspect the\n            state of a partial source file without creating inconsistency in our\n            model.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   See \"Readability\", \"Ergonomics\", and \"Comprehensibility\" gaols.\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n    -   See \"Efficient and simple compilation\" and \"Diagnosability\" goals.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   The chosen rule is mostly the same as the corresponding rule in C++,\n        both in accumulating information top-down and in treating inline method\n        bodies as a special case. This should keep migration simple and improve\n        familiarity for experienced C++ developers.\n\nIt should be noted that the decision between the model presented here and the\nleading alternative, which was\n[context-sensitive local consistency](#context-sensitive-local-consistency), was\nvery close, and came down to minor details. For each of our goals, neither\nalternative had a significant advantage. The similarity to C++ and evolvability\nof the alternative in this proposal were ultimately the deciding factors.\n\n## Alternatives considered\n\nBelow, various alternatives are presented and rated according to the\n[goals](#goals) for this proposal.\n\nGenerally we need to pick a rule for allowing or disallowing separate\ndeclaration and definition, and a rule for information flow. These choices are\nnot independent: some information flow rules require separate declaration and\ndefinition.\n\n### Separate declaration and definition\n\n#### Allow separate declaration and definition\n\nWe could allow two or more declarations of each entity, with at most one\ndeclaration providing a definition and the other declarations merely introducing\nthe existence of the entity and its basic properties:\n\n```\n// Forward declaration.\nfn F();\n// ...\n// Another forward declaration of the same function.\nfn F();\n// One and only definition.\nfn F() {}\n// Yet another forward declaration.\nfn F();\n```\n\nThis could be done in either a free-for-all fashion as in the above example,\nwhere any number of declarations is permitted, or in a more restricted fashion,\nwhere there can be at most one declaration introducing an entity, and, if that\ndeclaration is not a definition, at most one separate implementation providing\nthe definition. In this case, the separate definition could contain a syntactic\nmarker indicating that a prior declaration should exist:\n\n```\n// Forward declaration.\nfn F();\n// ...\n// Separate definition, with `impl` marker to indicate that this is just an\n// implementation of an entity that was already declared.\nimpl fn F() {}\n```\n\n##### Analysis\n\n_Comprehensibility:_ In general, determining whether two declarations declare\nthe same entity may not be straightforward, particularly for a redeclaration of\nan overloaded function. We have some options, but they all have challenges for\ncomprehensibility or ergonomics of the rule:\n\n-   We could require token-for-token identical declarations, but this may result\n    in ergonomic problems -- developers may wish to leave out information in an\n    interface that isn't relevant for consumers of that interface, or spell the\n    same type or parameter name differently in an implementation.\n-   We could allow the declarations to differ so long as they have the same\n    meaning. However, there may be cases, as there are in C++, where it's\n    unclear whether two declarations are \"sufficiently similar\" so as to declare\n    the same entity.\n-   We could require all overloads of a function to be declared together in a\n    group, perhaps with some dedicated syntax, and then match up redeclarations\n    based on position in the group rather than signature. Such an approach is\n    likely to lead to developers, especially those familiar with the C++ rule,\n    being surprised. It will likely also interact poorly with cases where some\n    but not all of the overloads are defined in their first declaration and the\n    rest are defined separately, or where it is desirable for different\n    overloads to be defined in different implementation files.\n\n_Ergonomics:_ Any case where the declaration and definition are separated\nresults in repetitive code. However, this repetition may serve a purpose to the\nextent that it's presenting an API description or acting as a compilation\nbarrier.\n\n_Readability:_ Readability of code may be substantially improved by separating a\ndeclaration of an API from its definition, and permitting an API user to read,\nin a small localized portion of a source file, only the information they care\nabout, without regard for implementation details.\n\n_Efficient and simple compilation:_ Allowing multiple declarations of an entity\nintroduces some implementation complexity, as the implementation must look up,\nvalidate, and link together multiple declarations of the same entity. If\nredeclarations are permitted across source files -- such as between the\ninterface and implementation of an API, or between multiple implementation files\n-- then this may also require some stable mechanism for identifying the\ndeclaration, such as a name mangling scheme. This may be especially complex in\nthe case of overloaded function templates, which might differ in arbitrary\nCarbon expressions appearing in the function's declaration. This complexity\ncould be greatly reduced if we require all overloads to be declared together --\nat least in the same source file -- as we can then identify them by name and\nindex.\n\nThis approach supports physical separation of implementation from interface,\npotentially leading to build time wins through reduced recompilation and through\nreducing the amount of information fed into each compilation step.\n\n_Diagnosability:_ Identifying errors where a redeclaration doesn't exactly match\na prior declaration is not completely straightforward. This is especially the\ncase when function overloads can be added by the same syntax with which a\ndefinition of a prior declaration would be introduced. Even if declarations and\ndefinitions use a different syntax, diagnosing a mismatch between a definition\nof an overloaded function and a prior set of declarations requires some amount\nof fuzzy matching to infer which one was probably intended.\n\n_Toolability:_ Supporting separate declarations and definitions will present the\nsame kinds of complexity for non-compiler tools as for compilers. Tools will\nneed to be able to reason about multiple declarations providing distinct\ninformation about an entity and the effect of that on how the entity can be used\nat different source locations.\n\n#### Disallow separate declaration and definition\n\nWe could require each entity to be declared in exactly one place, and reject any\ncases where the same entity is declared more than once.\n\n##### Analysis\n\n_Comprehensibility:_ This rule is easy to explain and easy to reason about.\n\n_Ergonomics:_ Minimizes the work required by the developer to implement new\nfunctionality and maintain existing functionality. Reduces the chance that a\nchange in one place will be forgotten in another.\n\n_Readability:_ Each entity has only one declaration, giving a single canonical\nlocation to include documentation, and no question as to where information about\nthe entity might be found. This will likely improve the navigability of source\ncode and the ease with which all the information about an entity can be\ngathered, and reduce the chance that information in the declaration or\ndefinition will be incomplete or that they will be inconsistent with each other.\n\nHowever, there would be no ability to present a function or class as source code\nwithout also including implementation details. Such implementation details\ncannot be physically separated from the API as presented to clients. The ability\nto read and understand an interface will depend more heavily on tools that can\nhide implementation details, such as documentation generators and IDEs with\noutlining, and implementation techniques such as using `interface`s to present\nthe API of a class separate from its implementation.\n\nFor developers familiar with C++ in particular, the absence of the ability to\nseparate declaration from definition may create friction, due to the familiarity\nof that feature and having their thinking about code layout shaped around it.\nGiven that Carbon aims to be familiar to those coming from C++, an absence of\nforward declarations will work against that goal to some extent, although\nempirical evidence suggests that the extent to which this is an issue varies\nwidely between existing C++ developers.\n\n_Efficient and simple compilation:_ This approach leads to a simpler compilation\nstrategy. However, in the absence of forward declarations, every compilation\nreferring to an entity needs to have a build dependency on the full definition\nof that entity, meaning there is no physical separation between the APIs of\nentities and their definitions. This would impose a potentially-significant\nbuild time cost due to increased recompilations when the definition of an entity\nchanges.\n\nThere are possibilities to reduce this build time cost. For example, instead of\neach declaration identifying whether it is public or private to a library, we\ncould add a third visibility level to say that the declaration but not the\ndefinition is public, and use a stripping tool as part of the build process to\navoid dependencies on non-public definitions from cascading into unnecessary\nrebuilds.\n\nThis approach is also unlikely to be acceptable from an ergonomic standpoint\nunless declarations within a source file are visible throughout at least the\nentire library containing that file, although this is strictly an independent\nchoice. Making definitions from a source file visible throughout its library\nwould presumably require a library-at-a-time build strategy, which is also\nexpected to introduce build time costs due to changes to a library requiring\nmore code in that library to be recompiled. This cost could be reduced by using\na reactive compilation model, recompiling only the portions of a library that\nare affected by a code change, at some complexity cost.\n\n_Diagnosability:_ Because each entity can only be declared once, there is no\nsignificant challenge in diagnosing redeclaration issues. However, there is\nstill some work required to diagnose conflicts between similar or functionally\nidentical function overloads.\n\n_Toolability:_ Having a unique source location for each entity allows for\nsomewhat simpler tooling. For example, there is no need to distinguish between\n\"jump to declaration\" and \"jump to definition\", or to decide which declaration\nshould be consulted to find documentation comments, parameter names, and so on.\n\n### Information flow\n\n#### Strict top-down\n\nCarbon could accumulate information top-down. We could require that each program\nutterance is type-checked and fully validated before any later code is\nconsidered.\n\nIn order to support this and still permit cyclic references between entities, we\nwould need to\n[allow separate declaration and definition](#allow-separate-declaration-and-definition).\n\n##### Analysis\n\n_Comprehensibility:_ This rule is simple to explain, and has no special cases.\nHowever, the inability to look at information from later in the source file is\nlikely to result in gotchas:\n\n```\nclass Base {\n  var n: i32;\n}\nclass Derived extends Base {\n  // Returns me.(Base.n), not me.(Derived.n), because the latter has not\n  // been declared yet.\n  fn Get[me: Self]() -> i32 { return me.n; }\n  var n: i32;\n}\n```\n\nIt might be possible to require a diagnostic in such cases, when we find a\ndeclaration that would change the meaning of prior code if it had appeared\nearlier, but that would result in implementation complexity, and the fact that\nsuch cases are rejected would still be a surprise.\n\n_Ergonomics:_ The developer is required to topologically sort their source files\nin dependency order, manually breaking cycles with forward declarations. Common\nrefactoring tasks such as reorganizing code may require effort or tooling\nassistance in order to preserve a topological order.\n\nDevelopers could adapt to this ruleset by beginning each source file with a\ncollection of forward declarations. This would mitigate the need to produce a\ntopological ordering, except within those forward declarations themselves, and\nother declarations required to provide those forward declarations. For example,\na forward declaration of a class member will likely only be possible within a\nclass definition, and the order in which that class definition is given can be\nrelevant to the validity of other class definitions. However, our experience\nwith C++ indicates that this will not be done, and instead an ad-hoc and\nundisciplined combination of a topological sort and occasional forward\ndeclarations will be used. Indeed, including these additional forward\ndeclarations would increase the maintenance burden and introduce an additional\nopportunity for errors due to mismatches between declaration and definition.\n\n_Readability:_ Developers wishing to understand code have the advantage that\nthey need only consider prior code, and there is no possibility that a later\nsource utterance could change the meaning of the code they're reading. However,\nit is rare to read code top-down, so the effect of this advantage may be modest.\n\nThis advantage leads to a significant disadvantage: the behaviour of an entity\ncan be different at different places within a source file. For example, a type\ncan be incomplete in one place and complete in another, or can fail to implement\nan interface when inspected early and then found to implement that interface\nlater. This can lead to very subtle incoherent behavior.\n\nIn practice, the topological ordering constraint tends to lead to good locality\nof information: helpers for particular functionality are often located near to\nthe functionality. However, this is not a universal advantage, and the\ntopological constraint sometimes leads to internal helpers being ordered\nimmediately before their first use instead of in a more logical position near\ncorrelated functionality.\n\n_Efficient and simple compilation:_ This rule is mostly simple and efficient to\nimplement, and even allows single-pass processing of source files.\n\n_Diagnosability:_ Because information is provided top-down, diagnostics can also\nbe provided top-down and in every case the diagnostic will be caused by an error\nat the given location or earlier. Fixing errors should require little or no\nbacktracking by the developer.\n\nHowever, an implementation that strictly confines its processing to top-down\norder and produces diagnostics eagerly cannot deliver diagnostics that react\nintelligently to contextual cues that appear after the point of the diagnostic.\nThis approach diminishes the ability for an implementation to pinpoint the cause\nof the error and describe it in a developer-oriented fashion.\n\n_Toolability:_ Limiting information flow to top-down means that tools such as\ncode completion tools need only consider context prior to the cursor, and they\ncan be confident that if all the code prior to the cursor is valid that it can\nbe type-checked and suitable completions offered.\n\nHowever, in the case where the user wants to refer to a later-declared entity,\nsuch tools would not be able to use this strategy. They would need to parse as\nif there were not a top-down rule in order to find such later-declared entities,\nand would likely additionally need the ability to add forward declarations or to\nreorder declarations in order to satisfy the ordering requirement.\n\n#### Strict global consistency\n\nCarbon could follow an approach of requiring the behavior of every entity to be\nglobally consistent. In this approach, the behavior of every entity would be as\nif the entire program could be consulted to determine facts about that entity.\n\nIn practice, to make this work, we would need to limit where those facts can be\ndeclared. For example, we limit implementations of interfaces to appear only in\nsource files that must already be in use wherever the question \"does this type\nimplement that interface?\" can be asked.\n\nIn addition, we need to reject at least the case where some property of the\nprogram recursively depends upon itself:\n\n```\nstruct X {\n  var a: Array(sizeof(X), i8);\n}\n```\n\nIn order to give globally consistent semantics to, for example, a package name,\nwe would likely need to process all source files comprising a package at the\nsame time. This is likely to encourage packages to be small, whereas we have\ndesigned package support on the assumption that the scope of a package matches\nthat of a complete source code repository.\n\nThis alternative can be considered either with or without the ability to\nseparate declarations from definitions. If we permit separate declaration and\ndefinition, we would likely require declarations of the same entity to appear in\nthe same library; however, that limitation is desirable regardless of which\nstrategy we choose.\n\n##### Block-scope exception\n\nApplying this rule to local name lookup in block scope does result in some\nsurprises. For example, C# uses this approach, and combined with its\ndisallowance of shadowing of local variables, this\n[confuses some developers](https://stackoverflow.com/questions/1196941/variable-scope-confusion-in-c-sharp).\nAs a variant of this alternative, it would be reasonable and in line with likely\nprogrammer expectations to not apply this rule to names in block scope. We call\nthis the _block-scope exception_.\n\nFor example:\n\n```\nvar m: i32 = 1;\nfn F(b: bool) -> i32 {\n  if (b) {\n    var n: i32 = 2;\n    // With the block-scope exception:\n    // * `n` is unambiguously the variable declared on the line above, and\n    // * `m` is unambiguously the global.\n    //\n    // Without the block-scope exception:\n    // * depending on the rules we choose for shadowing, `n` might name the\n    //   variable above, might be ambiguous, or might be invalid because it\n    //   shadows the variable `n` declared below, and\n    // * `m` would name the local variable declared below.\n    return n + m;\n  }\n  var n: i32 = 3;\n  var m: i32 = 4;\n  return n * m;\n}\n```\n\n##### Analysis\n\n_Comprehensibility:_ This rule is simple to explain, and has no special cases,\nother than perhaps the block scope variant. The disallowance of semantic cycles\nis likely to be unsurprising as it is a logical necessity in any rule.\n\n_Ergonomics:_ The developer can organize or arrange their code in any way they\ndesire. There is never a requirement to forward-declare or repeat an interface\ndeclaration. Refactoring and code reorganization do not require any non-obvious\nchanges, because the same code means the same thing regardless of how it is\nlocated relative to other code.\n\n_Readability:_ Reasoning about code is simple in this model, as such reasoning\nis largely not context-sensitivity. Instead of questioning \"what does this do\nhere?\" we can instead consider \"what does this do?\". Some context sensitivity\nmay remain, for example due to access and name bindings differing in different\ncontexts.\n\nHowever, to developers accustomed to a top-down semantic model, the ability to\ndefer giving key information about an entity -- or even declaring it at all --\nuntil long after it is first used may hinder readability in some circumstances,\nparticularly when reading code top-down.\n\n_Efficient and simple compilation:_ This model forces the compilation process to\noperate in multiple stages rather than as a single pass.\n\nSome form of cycle detection is necessary if cycles are possible. However, such\na mechanism is likely to be necessary for template instantiation too, so this is\nlikely not a novel requirement for Carbon.\n\nForcing all files within a package to be compiled together in order to provide\nconsistent semantics for the package name may place an undesirable scalability\nbarrier on the build system. This will also tend to push up build latency,\nespecially for incremental builds, by decreasing the granule size of\ncompilation. It may increase the scope of recompilations due to additional\nphysical dependencies unless we implement a mechanism to detect whether a\nlibrary has changed in an \"important\" way.\n\nWe do not have an existence proof of an efficient build strategy for a\nCarbon-like language that follows this model. For example, Rust has known build\nscalability issues, as does Java for large projects unless a tool like\n[ijar](https://github.com/bazelbuild/bazel/tree/master/third_party/ijar) is used\nto automatically create something resembling a C++ header file from a source\nfile. There is a significant risk that such an automated tool would be very hard\nto create for Carbon: because the definitions of classes and functions can be\nexposed in various ways through compile-time function evaluation, templates, and\nmetaprogramming, it seems challenging to put any useful bound on which entities\ncan be stripped without restricting the capabilities of client code.\n\n_Diagnosability:_ The implementation is likely to have more contextual\ninformation when providing diagnostics, improving their quality. However, the\ndiagnostics may appear in a confusing order: if an early declaration needs\ninformation from a later declaration in order to type-check, diagnostics\nassociated with that later declaration may be produced first, or may be\ninterleaved with diagnostics for the earlier declaration, leading to the\nprogrammer potentially revisiting the same code multiple times during a\ncompile-edit cycle.\n\n_Toolability:_ This model requires tools to consider the whole file as context,\nbecause code may refer to entities that are only introduced later. For an IDE\nscenario, where the cursor represents a location where an arbitrary chunk of\ncode may be missing, this presents a challenge of determining how to\nresynchronize the input in order to determine how to interpret the portion of\nthe source file following the cursor.\n\nSophisticated tooling for a top-down model may wish to inspect the trailing\nportion of the file anyway, in order to provide a better developer experience,\nbut this complexity would be forced upon tools with this model.\n\n#### Top-down with minimally deferred type checking\n\nWe could follow a top-down approach generally, but defer type-checking some or\nall top-level entities until we reach the end of that entity. For example, we\nwould check an entire class as a single unit, following the same principles as\nin the globally-consistent rule, but using only information provided prior to\nthe end of the class definition. This would allow class members to use other\nmembers that have not yet been declared, while not permitting a function\ndefinition preceding the class definition to use such members.\n\nFollowing C++'s lead, we would apply this to at least classes and interfaces,\nbut perhaps to nothing else. We may still want to apply the top-down rule to\nfunction definitions appearing within a class or interface, as the C# behavior\nthat the scope of a local variable extends backwards before its declaration may\nbe surprising.\n\n##### Analysis\n\nThis approach generally has the properties as\n[strict top-down](#strict-top-down), except as follows:\n\n_Comprehensibility:_ Slightly reduced due to additional special-casing of\ntop-level declarations. Gotchas would be rarer, but may not be fully eliminated.\nFor example:\n\n```\nimport X;\n// G from package X, not G from class X below.\nfn F() { X.G(); }\nclass X {\n  fn G() {}\n}\nclass Y {\n  // G from class X below, not G from package X.\n  fn F() { X.G(); }\n  class X {\n    fn G() {}\n  }\n}\n```\n\n_Ergonomics:_ Improved within classes, as members can now be named everywhere\nwithin the class.\n\n_Readability:_ The ability to read and understand code may be somewhat harmed,\nas the rules for behavior across top-level declarations aren't the same as the\nrules for behavior within a top-level declaration. It may be especially jarring\nthat code that is valid within a class definition is not valid at the top level:\n\n```\nclass A {\n  // OK\n  var b: B;\n  class B {}\n}\n\n// Error, I have not heard of B.\nvar b: B;\nclass B {}\n```\n\nHowever, the behavior of an entity no longer differs at different points within\nthe same declaration of that entity, so the ability to reason about the behavior\nof an entity is somewhat improved compared to the strict top-down approach. For\nentities without a separate declaration and definition, the behavior of those\nentities is the same everywhere.\n\n_Efficient and simple compilation:_ This has the same complications as the\nstrict global consistency approach, except that it does not apply to contexts\nthat span multiple files, so it doesn't have the build time disadvantages of\nrequiring all source files in a library to be built together.\n\n_Diagnosability:_ Diagnostics should be encountered by the implementation in the\ntop-down order of the top-level declaration containing the error, but may in\nprinciple appear in any order within that top-level declaration, if there are\nforward references that require later code to be analyzed before earlier code\nis.\n\nDiagnostics can be caused by errors appearing both before and after the location\nreported, but not arbitrarily far after: later top-level declarations cannot\naffect an earlier diagnostic.\n\n_Toolability:_ Tools that want to correctly model Carbon semantics would be\nrequired to deal with incomplete source code in the vicinity of the cursor. This\nis probably the hardest kind of incomplete source code to handle, as the region\nof \"damaged\" code is most likely to be relevant context. In practice, this is\nlikely to present the same difficulties as tooling in the\n[strict global consistency](#strict-global-consistency) model.\n\n#### Top-down with deferred method bodies\n\n**This is the proposed approach.**\n\nWe could follow a top-down approach generally, but defer all processing of\nbodies of class member functions until we have finished processing the class, at\nwhich point we would process those member function bodies in the order they\nappeared within the class. For example, we would reinterpret:\n\n```carbon\nclass A {\n  fn F[me: Self]() -> i32 { return me.n; }\n  fn Make() -> A { return {.n = 5}; }\n  var n: i32;\n}\n```\n\nexactly as if it were written with the member function bodies out of line:\n\n```carbon\nclass A {\n  fn F[me: Self]() -> i32;\n  fn Make() -> A;\n  var n: i32;\n}\nfn A.F[me: Self]() -> i32 { return me.n; }\nfn A.Make() -> A { return {.n = 5}; }\n```\n\nThe [strict top-down](#strict-top-down) would be applied to this rewritten form\nof the program.\n\nAs in C++, member functions of nested classes would be deferred until the\noutermost class is complete. This deferral would apply only to the bodies of\nmember functions, unlike in C++ where it also applies to default arguments,\ndefault member initializers, and exception specifications, and unlike\n[top-down with minimally deferred type checking](#top-down-with-minimally-deferred-type-checking),\nwhere it also applies to member function signatures and the declarations and\ndefinitions of non-function members.\n\n##### Analysis\n\nThis approach generally has the properties as\n[strict top-down](#strict-top-down), except as follows:\n\n_Comprehensibility:_ Slightly reduced due to additional special-casing of class\nmember functions, but these rules are well-aligned with the rules from C++,\nwhich do not seem to suffer from major comprehensibility problems in this area.\n\n_Ergonomics:_ Improved within classes, as members can now be named within member\nfunction bodies.\n\n_Readability:_ The ability to read and understand code may be somewhat harmed,\nas the rules for behavior within a member function body are different from the\nrules everywhere else in the language. However, the very similar rule in C++ is\nnot known to cause readability problems, so no major concerns are anticipated.\n\n_Efficient and simple compilation:_ The complexity of this approach is not\nsubstantially greater than the simple top-down approach. Processing of member\nfunction bodies must be deferred, but this can be done either by storing and\nreplaying the tokens, or by forming a parse tree but deferring the semantic\nanalysis and type-checking until the end of the class.\n\n_Diagnosability:_ Diagnostics for errors in member functions may appear after\ndiagnostics for later code in the same class.\n\nDevelopers may be confused by diagnostics claiming that a class member function\nbody is not available yet and referring to a point in the program text that\nlexically follows the member function definition. It is likely possible to\nspecial-case such diagnostics to explain the nature of the problem.\n\n_Toolability:_ Tools that want to parse incomplete Carbon code would need to\ncope with member function bodies containing errors. For the most part, skipping\na brace-balanced function body should be straightforward, but tools will also\nneed to consider whether they attempt to detect and recover from mismatched\nbraces within member functions.\n\n#### Context-sensitive local consistency\n\nWe could use different behaviors in different contexts, as follows:\n\n-   For contexts that are fundamentally ordered, such as function bodies, a\n    top-down rule is used.\n-   For contexts that are defined across multiple source files, such as packages\n    and namespaces, we guarantee consistent behavior within each source file,\n    but the behavior may be inconsistent across source files: different source\n    files may see different sets of names within a package or namespace,\n    depending on what they have imported.\n-   For contexts that are defined within a single source file, such as a class\n    or an interface, we guarantee globally consistent behavior.\n\nCompared to the [strict global consistency](#strict-global-consistency) model,\nthis would not guarantee that the contents of a package or namespace are the\nsame everywhere: you only see the names that you declare or import into a\npackage or namespace. Also, a top-down rule is used within function bodies, as\nthat likely better matches programmer expectations.\n\nCompared to the\n[top-down with minimally deferred type checking](#top-down-with-minimally-deferred-type-checking)\nand\n[top-down with deferred method bodies](#top-down-with-deferred-method-bodies)\nmodels, this would not require forward declarations for namespace and package\nmembers that are declared or defined later in the same source file.\n\n##### Analysis\n\n_Comprehensibility:_ This model is probably a little easier to understand than\nthe minimally-deferred type-checking model, because there is no difference\nbetween top-level declarations and nested declarations.\n\nBecause the behavior of every entity is consistent within a file, and every name\nlookup is consistent within a scope -- other than the top-down behavior within\nfunction scopes -- there are fewer opportunities for surprises than in the\ntop-down approaches, and nearly as few as in the strict global consistency\nmodel.\n\n_Ergonomics:_ As with the strict global consistency model, code can be organized\nas the developer desires, and refactoring doesn't have any surprises due to\ndisrupting a topological order.\n\n_Readability:_ As with the strict global consistency model, readability is\nimproved by not being context-sensitive. However, it is file-sensitive, and a\ndifferent set of imports may lead to different behavior.\n\nSimilarly, as with the strict global consistency model, developers accustomed to\nthe top-down model may find it harder to understand code in which a name can be\nreferenced before it is declared.\n\n_Efficient and simple compilation:_ This model has the same general costs as the\ntop-down with minimal deferred type-checking model. The implementation needs to\nbe able to separate parsing from type-checking, and type-check lazily in order\nto handle forward references. However, more state needs to be accumulated before\ntype-checking can begin.\n\nThis model supports separate compilation of source files, as no attempt is made\nto ensure consistency across source files, only within a source file.\n\n_Diagnosability:_ The compilation process will be split up into multiple phases,\nand it is likely that diagnostics from one phase will precede those from\nanother. For example, a parsing error for a later construct may precede a type\nerror for an earlier one.\n\nIf an earlier phase fails, it may not be feasible to diagnose later phases. For\nexample, if parsing encounters an unrecoverable failure, type errors for the\nsuccessfully-parsed portion cannot be generated, because they may depend on\nconstructs appearing later in the same source file. However, this may also mean\nthat better diagnostics are produced for cases such as a missing `}`, where the\nsyntactic error will precede or prevent diagnostics for semantic errors caused\nby the misinterpretation of the program resulting from that missing `}`.\n\nWithin a particular phase of processing, diagnostics will generally be produced\nin a topological order, and the processing can be arranged such that they are\nproduced in top-down order except where a forward reference requires that a\nlater declaration is checked earlier.\n\n_Toolability:_ Largely the same as the strict global consistency model, except\nthat tools only need to use the current source file as context. Also largely the\nsame as the top-down with minimally deferred type checking model.\n"
  },
  {
    "path": "proposals/p0911.md",
    "content": "# Conditional expressions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/911)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Chaining](#chaining)\n    -   [Precedence and ambiguity](#precedence-and-ambiguity)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [No conditional expression](#no-conditional-expression)\n    -   [Use C syntax](#use-c-syntax)\n    -   [No `then`](#no-then)\n    -   [Require parentheses around the condition](#require-parentheses-around-the-condition)\n    -   [Never require enclosing parentheses](#never-require-enclosing-parentheses)\n    -   [Variable-precedence `if`](#variable-precedence-if)\n    -   [Implicit conversions in both directions](#implicit-conversions-in-both-directions)\n    -   [Support lvalue conditionals](#support-lvalue-conditionals)\n-   [Future work](#future-work)\n    -   [Too many user-facing interfaces](#too-many-user-facing-interfaces)\n    -   [Incompatible `CommonType` implementations diagnosed late](#incompatible-commontype-implementations-diagnosed-late)\n    -   [`impl` ordering depends on operand order](#impl-ordering-depends-on-operand-order)\n\n<!-- tocstop -->\n\n## Problem\n\nPrograms need to be able to select between multiple different paths of execution\nand multiple different values. In a rich expression language, developers expect\nto be able to do this within a subexpression of some overall expression.\n\n## Background\n\nC-family languages provide a `cond ? value1 : value2` operator.\n\n-   This operator has confusing syntax, because both `cond` and `value2` are\n    undelimited, and it's often unclear to developers how much of the adjacent\n    expressions are part of the conditional expression. For example:\n    ```\n    int n = has_thing1 && cond ? has_thing2 : has_thing3 && has_thing4;\n    ```\n    is parsed as\n    ```\n    int n = (has_thing1 && cond) ? has_thing2 : (has_thing3 && has_thing4);\n    ```\n    Also, `value1` and `value2` are parsed with different rules:\n    ```\n    cond ? f(), g() : h(), i();\n    ```\n    is parsed as\n    ```\n    (cond ? f(), g() : h()), i();\n    ```\n-   In C++, this operator has confusing semantics, due to having a complicated\n    set of rules governing how the target type is determined.\n-   Despite the complications of the rules, the result type of `?:` is not\n    customizable. Instead, C++ invented a `std::common_type` trait that models\n    what the result of `?:` should have been.\n\nRust allows most statements to be used as expressions, with `if` statements\nbeing an important case of this: `Use(if cond { v1 } else { v2 })`.\n\n-   This has a number of behaviors that would be surprising to developers coming\n    from C++ and C, such as a final `;` in a `{...}` making a semantic\n    difference.\n-   The expression semantics leak into the statement semantics. For example,\n    Rust rejects:\n\n    ```\n    fn f() {}\n    fn g() -> i32 {}\n\n    fn main() {\n      if true { f() } else { g() };\n      return;\n    }\n    ```\n\n    ... because the two arms of the `if` don't have the same type.\n\n-   We have already\n    [decided](https://github.com/carbon-language/carbon-lang/issues/430) that we\n    do not want Carbon to treat statements such as `if` as being expressions\n    without some kind of syntactic distinction.\n\n## Proposal\n\nProvide a conditional expression with the syntax:\n\n> ```\n> if cond then value1 else value2\n> ```\n\n`then` is a new keyword introduced for this purpose.\n\n## Details\n\n### Chaining\n\nThis syntax can be chained like `if` statements:\n\n```\nPrint(if guess < value\n      then \"Too low!\"\n      else if guess > value\n      then \"Too high!\"\n      else \"Correct!\")\n```\n\nUnlike with `if` statements, this doesn't require a special rule.\n\n### Precedence and ambiguity\n\nAn `if` expression can be used as a top-level expression, or within parentheses\nor a comma-separated list such as a function call. They have low precedence, so\ncannot be used as the operand of any operator, with the exception of assignment\n(if assignment is treated as an operator), but they can appear in other contexts\nwhere an arbitrary expression is permitted, for example as the operand of\n`return`, the initializer of a variable, or even as the condition of another\n`if` expression or `if` statement.\n\n```\n// Error, can't use `if` here.\nvar v: i32 = 1 * if cond then 2 else 3 + 4;\n```\n\n`value2` extends as far to the right as possible:\n\n```\nvar v: i32 = if cond then 2 else 3 + 4;\n```\n\nis the same as\n\n```\nvar v: i32 = if cond then 2 else (3 + 4);\n```\n\nnot\n\n```\nvar v: i32 = (if cond then 2 else 3) + 4;\n```\n\nThe intent is that an `if` expression is used to produce a value, not only for\nits side-effects. If only the side-effects are desired, an `if` statement should\nbe used instead. Because `value2` extends as far to the right as possible, if an\n`if` expression appeared at the start of a statement, its value could never be\nused:\n\n```\nif cond then value1 else value2;\n```\n\nFor this reason and to avoid the need for lookahead or disambiguation, an `if`\nkeyword appearing at the start of a statement is always interpreted as beginning\nan `if` statement and never as beginning an `if` expression.\n\n## Rationale based on Carbon's goals\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   The `if ... then ... else` syntax should be easier to format\n        automatically in an unsurprising way than a `?:` syntax because it is\n        clear that the `then` and `else` keywords should be wrapped to the start\n        of a new line when wrapping the overall conditional expression.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Including such an expression is expected to improve ergonomics.\n    -   An explicit delimiter for the start of the condition expression makes it\n        easier to read, correctly write, and understand the precedence of\n        conditional expressions.\n    -   Making the `value2` portion as long as possible gives a simple rule that\n        it seems feasible for every Carbon developer to remember. This rule is\n        expected to be unsurprising both due to using the same rule for `value1`\n        and `value2`, and because it means that `if` consistently behaves like a\n        very low precedence prefix operator.\n    -   The use of an explicit `if` keyword for flow control makes the\n        distinction between flow control and linear computation clearer.\n    -   The readability of a multi-line `if` expression is improved by having a\n        `then` and `else` keyword of the same length\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Migration is improved by providing an operator set that largely matches\n        the C++ operator set.\n\n## Alternatives considered\n\n### No conditional expression\n\nWe could provide no conditional expression, and instead ask people to use a\ndifferent mechanism to achieve this functionality. Some options include:\n\n-   Use of an `if` statement:\n    ```\n    var v: Result;\n    if (cond) {\n      v = value1;\n    } else {\n      v = value2;\n    }\n    Use(v);\n    ```\n-   A function call syntax:\n    ```\n    Use(cond.Select(value1, value2));\n    ```\n    or, with short-circuiting and lambdas:\n    ```\n    Use(cond.LazySelect($(value1), $(value2)));\n    ```\n-   An `if` statement in a lambda:\n    ```\n    Use(${ if (cond) { return value1; } else { return value2; } });\n    ```\n\nThe above assumes a placeholder `$(...)` syntax for a single-expression lambda,\nand a `${...}` syntax for a lambda with statements as its body.\n\nAdvantages:\n\n-   No new dedicated syntax.\n\nDisadvantages:\n\n-   Conditional expressions are commonly used, commonly desired, and Carbon\n    developers -- especially those coming from C++ and C -- will be disappointed\n    by their absence.\n-   Readability and ergonomics will be harmed by making this common operation\n    more verbose, even if an idiom is established.\n\n### Use C syntax\n\nWe could use the C `cond ? value1 : value2` syntax.\n\nAdvantages:\n\n-   Familiar to developers coming from C++ and C.\n\nDisadvantages:\n\n-   These operators have serious precedence problems in C++ and C. We could\n    address those by making more cases ambiguous, at the cost of harming\n    familiarity and requiring parentheses in more cases.\n-   The `:` token is already in use in name binding; using it as part of a\n    conditional expression would be confusing.\n-   The `?` token is likely to be desirable for use in optional unwrapping and\n    error handling.\n\n### No `then`\n\nWe could use\n\n> ```\n> if (cond) value1 else value2\n> ```\n\ninstead of\n\n> ```\n> if cond then value1 else value2\n> ```\n\nNote that we cannot avoid parentheses in this formulation without risking\nsyntactic ambiguities.\n\nAdvantages:\n\n-   Looks more like an `if` statement, albeit one with unbraced operands.\n-   Slightly shorter.\n-   Better line-wrapping for chained `if` expressions:\n    ```\n    Print(if (guess < value)\n            \"Too low!\"\n          else if (guess > value)\n            \"Too high!\"\n          else\n            \"Correct!\")\n    ```\n    may be more readable than\n    ```\n    Print(if guess < value\n          then \"Too low!\"\n          else if guess > value\n          then \"Too high!\"\n          else \"Correct!\")\n    ```\n    or\n    ```\n    Print(if guess < value\n            then \"Too low!\"\n            else if guess > value\n              then \"Too high!\"\n              else \"Correct!\")\n    ```\n\nDisadvantages:\n\n-   Potentially worse line wrapping. The `else` would presumably be wrapped onto\n    a line by itself, wasting vertical space, whereas `then` and `else` when\n    paired can both comfortably precede their values on the same line; consider\n    ```\n    F(if (cond)\n        value1\n      else\n        value2)\n    ```\n    occupies more space than\n    ```\n    F(if cond\n      then value1\n      else value2)\n    ```\n-   May create confusion between `if` statements and `if` expressions by\n    resembling an `if` statement but not matching the semantics.\n-   May cause evolutionary problems due to syntactic conflict if we ever make\n    the braces or parentheses in `if` statements optional.\n-   Requires parentheses, and hence additional presses of \"Shift\" on US\n    keyboards, making it slightly harder to type.\n\n### Require parentheses around the condition\n\nWe could use:\n\n> ```\n> if (cond) then value1 else value2\n> ```\n\nHowever, it's not clear that there is value in requiring both parentheses and a\nnew keyword. It also seems jarring that this so closely resembles an `if`\nstatement but adds a `then` keyword that the `if` statement lacks.\n\n### Never require enclosing parentheses\n\nWe could allow an `if` expression to appear anywhere a parenthesized expression\ncan appear, and retain the rule that `value2` extends as far to the right as\npossible.\n\nAdvantages:\n\n-   Removes extra ceremony from a construct that is already more verbose than\n    the corresponding `?:` construct in C++.\n-   The requirement to include parentheses may be irritating in cases where\n    there is no other possible interpretation, such as\n    `1 + (if cond then 2 else 3)`.\n\nDisadvantages:\n\n-   Visually ambiguous where `value2` ends in some cases, and violates\n    precedence rules.\n-   Hard for a simple yacc/bison parser to handle, due to ambiguity of `if` at\n    the start of a statement and ambiguity when parsing `value2`.\n\n### Variable-precedence `if`\n\nWe could allow an `if` expression to appear anywhere a parenthesized expression\ncan appear, and parse the `value1` and `value2` as if they appeared in place of\nthe `if` expression:\n\n```carbon\nvar n: i32 = 1 + if cond then 2 * 3 else 4 * 5 + 6;\n// ... is interpreted as ...\nvar n: i32 = (1 + (if cond then (2 * 3) else (4 * 5))) + 6;\n\n// Error: expected `else` but found `+ 4`.\nvar m: i32 = 1 + if cond then 2 * 3 + 4 else 5 + 6;\n```\n\nAdvantages:\n\n-   Same as previous option.\n\nDisadvantages:\n\n-   Confusing to readers, because it's not clear locally where the expression\n    after `else` ends, and discovering this requires looking backwards to before\n    the `if`.\n-   Hard for a simple yacc/bison parser to handle, due to needing at least one\n    production for an `if` statement for each precedence level. Also, those\n    productions will result in grammar ambiguities that will need to be\n    resolved.\n\n### Implicit conversions in both directions\n\nSuppose we have two types where implicit conversions in both directions are\npossible:\n\n```carbon\nclass A {}\nclass B {}\nimpl A as ImplicitAs(B) { ... }\nimpl B as ImplicitAs(A) { ... }\n```\n\nBy default, an expression `if cond then {} as A else {} as B` would be\nambiguous. If the author of `A` or `B` wishes to change this behavior:\n\n-   If the common type should be `A`, then `impl A as CommonTypeWith(B)` must be\n    provided specifying the common type is `A`.\n-   If the common type should be `B`, then `impl B as CommonTypeWith(A)` must be\n    provided specifying the common type is `B`.\n-   If the common type should be something else, then both `impl`s need to be\n    provided:\n    ```\n    impl A as CommonTypeWith(B) { let Result:! Type = C; }\n    impl B as CommonTypeWith(A) { let Result:! Type = C; }\n    ```\n\nWe could change the rules so instead, in any of the above cases, implementing\neither `A as CommonTypeWith(B)` or `B as CommonTypeWith(A)` would suffice.\n\nAdvantages:\n\n-   Simplifies the user experience in this case.\n\nDisadvantages:\n\n-   Introduces non-uniformity: the blanket `impl` of `CommonTypeWith` in terms\n    of `ImplicitAs` would get this special treatment, but other blanket `impl`s\n    would not.\n-   Introduces complexity, which might not be fully hidden from users. At\n    minimum, we would need to explain that `ImplicitAs` is treated specially\n    here.\n-   The case in which two `impl`s are required is a corner case. It's somewhat\n    uncommon for implicit conversions to be possible in both directions between\n    two types. In those cases, it's more uncommon for there to be a clear best\n    \"common type\". And even then, most of the time the common type will be one\n    of the two types being unified.\n\nFrom a more abstract perspective: the process of finding a common type involves\nasking each type to implicitly convert to the destination type that it thinks is\nbest, and then failing if both sides didn't convert to the same type. If `A`\nimplicitly converts to `B` and the other way around, then both sides of this\nprocess should be overridden in order to get both types to implicitly convert to\n`C` instead.\n\n### Support lvalue conditionals\n\nCarbon doesn't formally have a notion of lvalue or rvalue yet; this notion is\nexpected to be added by\n[#821: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/821).\nIn any case, we certainly intend to distinguish between expressions that\nrepresent values and expressions that represent locations where values could\nappear. We therefore need to decide whether a conditional expression can ever be\nin the latter category. For example:\n\n```carbon\nvar a: String;\nvar b: String;\nvar c: bool;\n// Valid?\n(if c then a else b) = \"Hello\";\n```\n\nWe could permit this, as C++ does. For example, we could say:\n\n> If both _value1_ and _value2_ are lvalues then\n> `if cond then value1 else value2` is rewritten to\n> `*(if cond then &value1 else &value2)` if those pointer types have a common\n> type.\n\nThe other reason we might want to consider this alternative is performance. In\nC++, this code avoids making a `std::string` copy:\n\n```c++\nstd::string a;\nstd::string b;\nstd::string c;\nbool cond;\n// ...\nbool equal = c == (cond ? a : b);\n```\n\n... by treating the conditional expression as an lvalue of type `std::string`\nrather than as a prvalue. However, in Carbon, following #821, we would expect\nthat the equivalent of a prvalue of type `std::string` would not necessarily\nimply that a copy is made. Rather, Carbon's equivalent of prvalues would\nrepresent either a set of instructions to initialize a value (as in C++), or the\nlocation of some existing value that we are temporarily \"borrowing\".\n\nWith that in mind:\n\nAdvantages:\n\n-   More similar to C++.\n-   Permits certain operations that have an obvious intended meaning, such as\n    assignment to a conditional.\n\nDisadvantages:\n\n-   Modification through an lvalue conditional is seldom used in C++, indicating\n    that this is not an important feature. The other benefits of a conditional\n    producing an lvalue are expected to be obtained by #821.\n-   Mutable inputs to operations (\"out parameters\") in Carbon are expected to be\n    expressed as pointers under #821, so there will be a `&` somewhere anyway;\n    given the choice between an lvalue conditional:\n    ```\n    F(&(if cond then a else b));\n    ```\n    and an rvalue-only conditional:\n    ```\n    F(if cond then &a else &b);\n    ```\n    the latter option would likely be preferred even if the former were\n    available.\n-   This would create an inconsistency in behavior, which would be particularly\n    visible in a generic when determining what constraints are necessary to\n    type-check an `if` expression -- the constraints would depend not only on\n    operand types, but also on value category, and may result in a hard to\n    express constraint such as \"either `T*` and `U*` have a common type or `T`\n    and `U` have a common type\".\n-   Certain kinds of lvalue conditional expression have turned out to be hard to\n    implement in C++, such as a conditional involving bit-field lvalues. We can\n    entirely avoid that class of implementation problems by treating conditional\n    expressions as rvalues.\n\nThis should be revisited if the direction in #821 changes substantially from the\nassumptions described above.\n\n## Future work\n\nThere are some known issues with the way that the extensibility mechanism works\nin this proposal. It is hoped that extensions to Carbon's generics mechanism\nwill provide simple ways to resolve these issues. This design should be\nrevisited once those mechanisms are available.\n\n### Too many user-facing interfaces\n\nWe provide both `CommonTypeWith`, as an extension point, and `CommonType`, as a\nconstraint. It would be preferable to provide only a single name that functions\nboth as the extension point and as a constraint, but we don't have a good way to\nautomatically make `impl`s symmetric and avoid `impl` cycles if we use only one\ninterface.\n\n### Incompatible `CommonType` implementations diagnosed late\n\nExample:\n\n```\nclass A {}\nclass B {}\n\nimpl A as CommonTypeWith(B) where .Result = A {}\nimpl B as CommonTypeWith(A) where .Result = B {}\n\nfn F(a: A, b: B) -> auto { return if true then a else b; }\n```\n\nThe definition of function `F` is rejected, because `A` and `B` have no\n(consistent) common type. It would be preferable to reject the `impl`\ndefinitions.\n\n### `impl` ordering depends on operand order\n\nExample:\n\n```\nclass A(T:! Type) {}\nclass B(T:! Type) {}\n\ninterface Fungible {}\nimpl A(T:! Type) as Fungible {}\nimpl B(T:! Type) as Fungible {}\n\n// #1\nimpl A(T:! Type) as CommonTypeWith(U:! Fungible) where .Result = A(T) {}\n// #2\nimpl B(T:! Type) as CommonTypeWith(A(T)) where .Result = T {}\n\nfn F(a: A(i32), b: B(i32)) -> auto { return if true then a else b; }\n```\n\nHere, reversed #2 is a better match than #1, because it matches both `A(?)` and\n`B(?)`, so #2 should be consider the best-matching `impl`. However, we never\ncompare reversed #2 against non-reversed #1. Instead, we look for:\n\n1.  `impl A(i32) as SymmetricCommonTypeWith(B(i32))`, which selects #1 as being\n    better than the blanket `impl` that reverses operand order.\n2.  `impl B(i32) as SymmetricCommonTypeWith(A(i32))`, which selects #2 as being\n    better than the blanket `impl` that reverses operand order.\n\nSo we decide that the `if` in `F` is ambiguous, even though there is a unique\nbest `CommonTypeWith` match. If either #1 or #2 is written with the operand\norder reversed, then `F` would be accepted.\n"
  },
  {
    "path": "proposals/p0920.md",
    "content": "# Generic blanket impls (details 5)\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/920)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Different syntax](#different-syntax)\n        -   [Inconsistent syntax](#inconsistent-syntax)\n        -   [Members defined out-of-line](#members-defined-out-of-line)\n        -   [Context sensitivity](#context-sensitivity)\n    -   [Orphan rule could consider interface requirements in blanket impls](#orphan-rule-could-consider-interface-requirements-in-blanket-impls)\n    -   [Child trumps parent rule](#child-trumps-parent-rule)\n    -   [Impls could limit specialization](#impls-could-limit-specialization)\n    -   [Libraries for orphan impls](#libraries-for-orphan-impls)\n    -   [Different traversal order for overlap rule](#different-traversal-order-for-overlap-rule)\n    -   [Intersection rule in addition to prioritization](#intersection-rule-in-addition-to-prioritization)\n    -   [Name lookup into conditional impls](#name-lookup-into-conditional-impls)\n    -   [Automatic implicit conversions](#automatic-implicit-conversions)\n\n<!-- tocstop -->\n\n## Problem\n\nThere are cases where an impl definition should apply to more than a single type\nand interface combination. The solution is to parameterize the impl definition,\nso it applies to a family of types, interfaces, or both. This includes:\n\n-   Declaring an impl for a parameterized type, which may be external or\n    declared out-of-line.\n-   \"Conditional conformance\" where a parameterized type implements some\n    interface if the parameter to the type satisfies some criteria, like\n    implementing the same interface.\n-   \"Blanket\" impls where an interface is implemented for all types that\n    implement another interface, or some other criteria beyond being a specific\n    type.\n-   \"Wildcard\" impls where a family of interfaces are implemented for single\n    type.\n\nIn addition to a syntax for defining parameterized impls, we need rules for\ncoherence:\n\n-   Orphan rules ensure that an impl is imported in any code that might use it.\n-   Overlap rules pick a specific impl when more than one impl declaration\n    matches a specific query about whether a type implements an interface.\n\n## Background\n\nRust supports parameterized impls, but has not stabilized the specialization\nfeature that resolves multiple impls applying.\n\n## Proposal\n\nThis is a proposal to add\n[a \"parameterized impls\" section to the generics design details](/docs/design/generics/details.md#parameterized-impl-declarations).\n\n## Rationale based on Carbon's goals\n\nMuch of this rationale for generics was captured in the\n[Generics goals proposal](https://github.com/carbon-language/carbon-lang/pull/24).\nThis proposal is particularly concerned with achieving the goal of making\ngenerics [coherent](/docs/design/generics/goals.md#coherence).\n\n## Alternatives considered\n\n### Different syntax\n\nThis conditional interface implementation syntax was decided in\n[issue #575](https://github.com/carbon-language/carbon-lang/issues/575), and\nclarified in\n[a Discord discussion in #syntax](https://discord.com/channels/655572317891461132/709488742942900284/903036676371259432).\nA large part of what was decided in that issue is the syntax used for\nnon-parameterized impls, and incorporated into the Carbon generics design in\n[proposal #553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553).\n\n#### Inconsistent syntax\n\nOur primary concern with the syntax for parameterized impls was that it be\nconsistent with non-parameterized impls, and consistent between lexically inline\nand out-of-line definitions. Consistency was the basis for rejecting a number of\nconditional conformance options:\n\n-   The `extend` syntax inline in a class definition to establish a more\n    specific `Self` type for conditional conformance choice was eliminated along\n    with [the `extend` syntax for external impls](p0553.md#extend-blocks).\n-   Consistency excluded using deduced arguments in square brackets after the\n    `impl` keyword, and an `if` or `where` clause to add constraints:\n\n    ```\n    class FixedArray(T:! Type, N:! Int) {\n      impl as [U:! Printable] Printable if T == U {\n        // Here `T` and `U` have the same value and so you can freely\n        // cast between them. The difference is that you can call the\n        // `Print` method on values of type `U`.\n      }\n    }\n\n    class Pair(T:! Type, U:! Type) {\n      impl as Foo(T) if T == U {\n        // Can cast between `Pair(T, U)` and `Pair(T, T)` since `T == U`.\n      }\n    }\n    ```\n\n    This was too different from how those same impls would be declared\n    out-of-line.\n\n-   Another approach that was too different between inline and out-of-line, is\n    to use pattern matching instead of boolean conditions. This might look like:\n\n    ```\n    class FixedArray(T:! Type, N:! Int) {\n      @if let P:! Printable = T {\n        impl as Printable { ... }\n      }\n    }\n\n    interface Foo(T:! Type) { ... }\n    class Pair(T:! Type, U:! Type) {\n      @if let Pair(T, T) = Self {\n        impl as Foo(T) { ... }\n      }\n    }\n    ```\n\n#### Members defined out-of-line\n\nWe rejected options that declared unqualified member names outside of the scope\ndefining the class. This would have allowed us to consistently use an\nout-of-line syntax, but starting with something other than `external` when it\naffected the names in the class.\n\n#### Context sensitivity\n\nWe rejected options for conditional conformance where the meaning of names\ndeclared in the class scope would have a more specific meaning in an inner\nscope. This would be much like how a language with\n[flow-sensitive typing](https://en.wikipedia.org/wiki/Flow-sensitive_typing)\nmight affect the types in an inner scope as part of control flow. For example, a\n`where` clause on an `impl` declaration might add constraints to a class\nparameter only inside the scope of the `impl` it was applied to:\n\n```\nclass FixedArray(T:! Type, N:! Int) {\n  impl as Printable where T is Printable {\n    // Inside this scope, `T` has type `Printable` instead of `Type`.\n  }\n}\n```\n\nThese options were rejected based on the\n[low-context-sensitivity principle](/docs/project/principles/low_context_sensitivity.md).\n\n### Orphan rule could consider interface requirements in blanket impls\n\nThe orphan rule states that a rule like\n\n```\nimpl [T:! Interface1] T as Interface2 { ... }\n```\n\ncan only live in the library that defines `Interface2`, not the library that\ndefines `Interface1`. To see that the alternative is not coherent, consider this\nexample where we have three libraries, with one a common library imported by the\nother two:\n\n-   Library `Common`\n\n    ```\n    interface ICommon { ... }\n    class S { ... }\n    ```\n\n-   Library `A`:\n\n    ```\n    import Common\n    interface IA { ... }\n    // Local interface only used as a constraint\n    impl [T:! IA] T as ICommon { ... }\n    // Fine: implementation of a local interface\n    impl S as IA { ... }\n    ```\n\n-   Library `B`:\n\n    ```\n    import Common\n    interface IB { ... }\n    // Local interface only used as a constraint\n    impl [T:! IB] T as ICommon { ... }\n    // Fine: implementation of a local interface\n    impl S as IB { ... }\n    ```\n\nInside another library that imports the `Common` library:\n\n-   Does `S` implement `ICommon`? If you just import `ICommon`, no\n    implementations are visible\n-   Does the answer change if you import libraries `A` or `B`?\n-   Which implementation of `ICommon` should `S` use if you import both?\n\nWe avoid these problems by requiring the use of a local type or interface\n**outside** of constraints.\n\n### Child trumps parent rule\n\n[Rust has considered a \"child trumps parent\" rule](http://aturon.github.io/tech/2017/02/06/specialization-and-coherence/).\nThis rule would say that a library `Child` importing library `Parent` is enough\nto prioritize `impl` definitions in `Child` over `Parent` when they would\notherwise overlap without one matching a strict subset of the other. The goal\nwould be to resolve overlaps in a way that is both easy to understand and more\noften matches what implementations users actually want prioritized.\n\nOne caveat of this rule is that a simple interpretation is not transitive. If we\ndefine three impls in three different libraries, with these type structures:\n\n-   `impl (A, ?, ?) as I`\n-   `impl (?, B, ?) as I`\n-   `impl (?, ?, C) as I`\n\nthen the type structure rule would prioritize `A` over `B` over `C`. If the\nlibrary with `C` had a dependency on the one with `A`, though, then `C` would\nhave priority over `A`, and we would not be able to decide which impl to use for\n`(A, B, C)`.\n\nThe fix is to change the rule to be \"Child trumps parent on their intersection\".\nWith that rule, it would be as if there was another implementation defined on\nthe intersection of `(A, ?, ?)` and `(?, ?, C)`, that is it would match\n`(A, ?, C)`, that had the highest priority and delegated to the `(?, ?, C)` impl\nfor the definition of the body.\n\nWithout some child trumps parent rule: If I define a new type, then all impl\nlookup for interfaces implemented by that type as `Self` will consider impl from\nmy library first, at the time I define it until some other library adds an impl\nof that type as `Self`. However, adding the \"child trumps parent on their\nintersection\" rule removes this property.\n\nThis is something we would consider in the future once we have more experience.\nNote that this rule has not yet been implemented in Rust, so we don't know how\nit works out in practice.\n\n### Impls could limit specialization\n\nThis would allow greater reasoning in generic functions, requiring less\nspecification. For example, there may be a blanket implementation of\n`PartiallyOrdered` provided for types that implement `Ordered`. If that blanket\nimplementation could not be specialized, a generic function could rely on the\nimplementations of the two interfaces being consistent with each other.\n\nThis feature has been left for a future proposal. Note this feature needs to be\nlimited to those cases where the implementation that limits specialization will\nbe guaranteed to be a dependency of all implementations that are prioritized as\nmore specific.\n\n### Libraries for orphan impls\n\nThe [orphan rule](/docs/design/generics/details.md#orphan-rule) means that there\nmay be no library that can define an impl with a particular type structure. Rust\nhas encountered this problem already, see\n[Rust RFC #1856: \"Orphan rules are stricter than we would like\"](https://github.com/rust-lang/rfcs/issues/1856).\nCarbon does not currently address this problem, but we would consider future\nchanges that do as long as coherence was maintained. For example, we'd consider\na mechanism that allowed libraries to be defined that must be imported, either\nimplicitly or explicitly, depending on whether specific other libraries are\nimported or linked into the project.\n\n### Different traversal order for overlap rule\n\nThe [overlap rule](/docs/design/generics/details.md#overlap-rule) uses a\ndepth-first traversal of the type tree to identify the first difference between\ntwo different type structures. We could also do another order, such as\nbreadth-first, but this order is both simple and reflects some experience from\nthe Rust community that the `Self` type is particularly important to prioritize.\n\n### Intersection rule in addition to prioritization\n\nAnother approach for\n[selecting between impls with the same type structure](/docs/design/generics/details.md#prioritization-rule)\nis to require that there is an impl matching the intersection of any two impls\nwith the same type structure, and then prioritize by containment. This approach\nis being considered for Rust, see\n[Baby Steps: \"Intersection Impls\"](http://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/)\nand\n[Aaron Turon: \"Specialization, coherence, and API evolution](http://aturon.github.io/tech/2017/02/06/specialization-and-coherence/).\nInstead of requiring that impls with the same type structure are always in the\nsame prioritization block, that requirement could be only when the intersection\nisn't defined. The advantage of the prioritization block is that it can express\neverything that intersection impls can express, and generally can do so without\nhaving to write an exponential number of impl declarations. Prioritization\nblocks do require you to write all the impls together in a block, though, so we\nmight want to support the option of allowing developers to explicitly write out\nintersections instead. This might be convenient in cases where the intersection\nis defined anyway, such as when there is already strict subset relationship\nbetween the impls.\n\n### Name lookup into conditional impls\n\nWe considered the possibility that name lookup would fail to find the members of\nthat impl when a conditional impl's condition does not apply. This would allow\n\n```\nclass X(T:! Type) {\n  impl X(i32) as Foo {\n    fn F[me: Self]();\n  }\n  impl X(i64) as Bar {\n    fn F[me: Self](n: i64);\n  }\n}\n```\n\nwhere `X(T).F` means different things for different `T`, which could be an\nunpleasant surprise. This seemed against the Carbon philosophy of making the\ncode behave consistently and predictably, and didn't have a motivating use case.\n\n### Automatic implicit conversions\n\nWe considered adding two features to support operator overloading use cases,\nwhere the language would select the interface parameter using the type of the\nsecond argument without considering implicit conversions. The intent of these\nfeatures was to, for example, make it convenient to support addition with\nanything that implicitly converted to `i32` by implementing addition with just\n`i32`.\n\nOne feature was to support implementing an interface using a function with a\ndifferent signature, as long as the compiler could automatically generate a\nwrapper that bridged the two signatures using implicit conversions. This raised\nconcerns about accidentally implementing interfaces with functions that had the\nwrong signature, evolution problems when new overloads were introduced, and\nsurprises and confusing errors from a single function considered to have two\ndifferent signatures.\n\nThe other feature was to allow a wildcard implementation as long as it could be\nimplemented using functions that did not vary with the wildcard parameter, by\nimplicitly converting to a common type. This introduced concerns about what to\ndo with other members of the interface, particularly those with defaults.\nPerhaps we would allow functions as long as the interface parameters could be\ndeduced from the types of the arguments? Perhaps we would require explicit\nqualification to call functions where the interface parameter couldn't be\ndeduced? In particular we were worried about evolution, and allowing users to\nadd functions to an interface as long as they had defaults.\n\nThese problems were discussed in\n[2021-12-08 open discussion](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.njnqpdcjp5h0).\nWe concluded that we will later find other mechanisms to support this use case.\n"
  },
  {
    "path": "proposals/p0931.md",
    "content": "# Generic impls access (details 4)\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/931)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Private impls for public types](#private-impls-for-public-types)\n    -   [Private interfaces in public API files](#private-interfaces-in-public-api-files)\n\n<!-- tocstop -->\n\n## Problem\n\nShould a type be able to declare an `impl` to be private, like it can for its\ndata and methods? There are some use cases for this feature, but those use cases\ngenerally could also be addressed by implementing the interface on a private\nadapter type instead.\n\n## Background\n\nPrivate impls have been considered but not implemented for Swift in the\n[scoped conformances pitch](https://forums.swift.org/t/scoped-conformances/37159).\n\n## Proposal\n\nThis is a proposal to add to\n[this design document on generics details](/docs/design/generics/details.md).\nThe additions are:\n\n-   to say impls do not allow access control modifiers and are always as public\n    as the names used in the signature of the impl; and\n-   to document how to use private adapter types instead.\n\n## Rationale based on Carbon's goals\n\nWe decided to make generics coherent as part of accepting proposal\n[#24: generics goals](https://github.com/carbon-language/carbon-lang/pull/24).\nThis approach is consistent with broader Carbon goals that Carbon have\n[code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nIn particular, we favor making code\n[less context sensitive](/docs/project/principles/low_context_sensitivity.md).\n\n## Alternatives considered\n\n### Private impls for public types\n\nWe considered supporting private impls for public types. This was motivated by\nusing the conversion of a `struct` type to a `class` type to construct class\nvalues. In the case that the class had private data members, we wanted to\nrestrict that conversion so it was only available in the bodies of class members\nor friends of the class. We considered achieving that goal by saying that the\nimplementation of the conversion would be private in that case. Allowing impls\nto generally be private, though, led to a number of coherence concerns that the\nsame code would behave differently in different files. Our solution was to\naddress these conversions using a different approach that only addressed the\nconversion use case:\n\n-   Users could not implement `struct` to `class` conversions themselves.\n-   The compiler would generate `struct` to `class` conversions for constructing\n    class values itself.\n-   Those conversion impls will always be as visible as the class type, and will\n    still be selected using the same rules as other impls.\n-   When one of these compiler-generated conversion impls is selected, the\n    compiler would perform an access control check to see if it was allowed.\n\nWe believe that other use cases for restricting access to an impl are better\naccomplished by using a private adapter type than supporting private impls.\n\n### Private interfaces in public API files\n\nA private interface may only be implemented by a single library, which gives the\nlibrary full control. We considered and rejected the idea that developers could\nput that interface declaration in an API file to allow it to be referenced in\nnamed constraints available to users. All impls for that interface would also\nhave to be declared in the API file, unless they were for a private type\ndeclared in that library.\n\nThis would allow you to express things like:\n\n-   A named constraint that is satisfied for any type **not** implementing\n    interface `Foo`:\n\n    ```\n    class TrueType {}\n    class FalseType {}\n    private interface NotFooImpl {\n      let IsFoo:! Type;\n    }\n    impl [T:! Foo] T as NotFooImpl {\n      let IsFoo:! Type = TrueType;\n    }\n    impl [T:! Type] T as NotFooImpl {\n      let IsFoo:! Type = FalseType;\n    }\n    constraint NotFoo {\n      extends NotFooImpl where .IsFoo == FalseType;\n    }\n    ```\n\n-   A named constraint that ensures `CommonType` is implemented symmetrically:\n\n    ```\n    // For users to implement for types\n    interface CommonTypeWith(U:! Type) {\n      let Result:! Type where ...;\n    }\n\n    // internal library detail\n    private interface AutoCommonTypeWith(U:! Type) {\n      let Result:! Type where ...;\n    }\n\n    // To use as the requirement for parameters\n    constraint CommonType(U:! AutoCommonTypeWith(Self)) {\n      extends AutoCommonTypeWith(U) where .Result == U.Result;\n    }\n\n    match_first {\n      impl [T:! Type, U:! ManualCommonTypeWith(T)]\n          T as AutoCommonTypeWith(U) {\n        let Result:! auto = U.Result;\n      }\n      impl [T:! Type, U:! ManualCommonTypeWith(T)]\n          U as AutoCommonTypeWith(T) {\n        let Result:! auto = U.Result;\n      }\n    }\n    ```\n\nThis feature is something we might consider adding in the future.\n"
  },
  {
    "path": "proposals/p0950.md",
    "content": "# Generics details 6: remove facets\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/950)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Status quo: name lookup only in the type-of-type](#status-quo-name-lookup-only-in-the-type-of-type)\n    -   [Status quo: facet types](#status-quo-facet-types)\n    -   [Name lookup in type and type-of-type](#name-lookup-in-type-and-type-of-type)\n    -   [No generic 'let'](#no-generic-let)\n    -   [Generic 'let' erases connection to original type](#generic-let-erases-connection-to-original-type)\n\n<!-- tocstop -->\n\n## Problem\n\nThere were some concerns about facet types leaking out of generic code in return\ntypes. Some initial fixes for this were done in\n[PR #900](https://github.com/carbon-language/carbon-lang/pull/900), but there\nremain concerns, for example when associated types are involved.\n\nIn particular, given an interface method with return type using an associated\ntype, as in:\n\n```\ninterface Deref {\n  let Result:! Type;\n  fn DoDeref[me: Self]() -> Result;\n}\n\nclass IntHandle {\n  impl Deref {\n    let Result:! Type = i32;\n    fn DoDeref[me: Self]() -> Result { ... }\n  }\n}\n```\n\nSince `Result` has type `Type`, we had the problem that `IntHandle.DoDeref`\nwould have to return `i32 as Type`, instead of the desired `i32`.\n\nWe also think we can simplify the model by eliminating the facet type concept\nand syntax.\n\n## Proposal\n\nThis proposal removes facet types, introduces archetypes in their place,\nclarifies how associated types work outside of a generic function, and specifies\nhow a generic `let` statement in a function body works.\n\n## Details\n\nThe details of this proposal are in the changes to these generics design\ndocuments:\n\n-   [Overview](/docs/design/generics/overview.md)\n-   [Goals](/docs/design/generics/goals.md)\n-   [Terminology](/docs/design/generics/terminology.md)\n-   [Details](/docs/design/generics/details.md)\n\n## Rationale based on Carbon's goals\n\nThis proposal\n[adds a goal](/docs/design/generics/goals.md#path-from-regular-functions) about\nminimizing the differences between a regular function and one with a generic\nparameter from the perspective of the caller. This is to support the\n[software and language evolution](/docs/project/goals.md#software-and-language-evolution)\ngoal by reducing the amount of changes needed to source code when generalizing a\nfunction.\n\nThis change is also a simplification to the programming model, removing a\nconcept that developers have to learn and reducing the number of types a program\ndeals with. This is in support of the\n[code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\ngoal.\n\n## Alternatives considered\n\nThis design was the conclusion of a number of discussions and proposals:\n\n-   [#typesystem discussion in Discord on Nov 2](https://discord.com/channels/655572317891461132/708431657849585705/905248525028323368)\n-   Nov 3, 2021 document by `zygoloid` titled\n    [Member lookup in generic and non-generic contexts](https://docs.google.com/document/d/1-vw39x5YARpUZ0uD2xmKepLEKG7_u122CUJ67hNz3hk/edit#)\n-   Nov 4, 2021 document by `josh11b` and `mconst` titled\n    [Carbon: facets exposed from generics](https://docs.google.com/document/d/1C1eIzd6JY0ooE1rDjW1vx7e3i7sgGugCA9bPMRhwWM0/edit#)\n-   [Open discussion on 2021-11-08](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.ec285oam2okw)\n-   [Open discussion 2021-11-11](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.8vuatm82d1mk)\n\nThe main alternatives we evaluated are summarized below.\n\n### Status quo: name lookup only in the type-of-type\n\nThe main problem with the status quo is that we would look up names in the\ntype-of-type whether or not the type value was known. This meant that there was\nno way to have a type variable that didn't alter the API of the type it held,\neven when the value of that variable was known at compile time. It also created\nproblems putting a particular facet type into an associated type, as was desired\nwhen computing the `CommonType` of two facets of the same type, since the\ntype-of-type of the associated type would overwrite the facet. This last concern\nwas raised in this\n[#typesystem discussion in Discord on Nov 2](https://discord.com/channels/655572317891461132/708431657849585705/905248525028323368).\n\n### Status quo: facet types\n\nFacet types as a user-visible type expression `MyType as MyConstraint` have a\nfew downsides:\n\n-   Facet types introduce extra types for the user to concern themselves with.\n-   Facet types introduce extra types for instantiation purposes.\n-   We don't want the possibility of facet types leaking outside of generic\n    code.\n\nArchetypes have replaced using facet types to type check a function with a\ngeneric parameter. Generic `let` and adapter types address trying to repeatedly\naccess methods from an interface implemented externally.\n\nWe considered making the other changes in this proposal with a different way of\nforming a facet type than `MyType as MyConstraint`\n[in this document](https://docs.google.com/document/d/1C1eIzd6JY0ooE1rDjW1vx7e3i7sgGugCA9bPMRhwWM0/edit#).\nUltimately we all agreed that we did not want to instantiate templates called\nwith a generic type with a facet type, and the removal of facet types simplifies\nthe design.\n\n### Name lookup in type and type-of-type\n\n[`zygoloid` proposed](https://docs.google.com/document/d/1-vw39x5YARpUZ0uD2xmKepLEKG7_u122CUJ67hNz3hk/edit#)\na solution of looking up names in both the type and the type-of-type, resolving\nconflicts in the same way `&` would between two type-of-types. This has the nice\nproperty of using the type information when it is available, but still allowing\nthe type-of-type to affect name lookup. This made the code inside and outside a\ngeneric consistent as long as there were no name conflicts. The downside is that\nthis still involved types potentially changing when you added a generic\nparameterization, even though the changes were smaller, and didn't have the\nsimplification advantages of removing facet types entirely.\n\nWe did like the idea from\n[that proposal](https://docs.google.com/document/d/1-vw39x5YARpUZ0uD2xmKepLEKG7_u122CUJ67hNz3hk/edit#)\nthat we would perform look up in the type when it was a constant, since that\naddressed the main problem we were trying to address.\n\n### No generic 'let'\n\nGeneric `let` has two main use cases: manual monomorphizing a generic and making\nrepeated calls to members of an interface implemented externally more\nconvenient. The former may be performed by using qualified member names, and the\nlatter by an adapter type, so this feature is not strictly needed.\n\nHowever, `chandlerc` believes including generic `let` is more consistent, for\nexample with the use of generic `let` to declare associated types in interfaces\nand implementations. It make replicating the change in type behavior of calling\na generic function much more straightforward, without having to introduce a\nfunction call or rewriting all of the member accesses to add qualification.\n\nRemoving generic `let` is a simplification we would consider in the future.\n\n### Generic 'let' erases connection to original type\n\nWe considered the idea that a generic `let` would fully erase type identity,\n[on discord as \"option A\"](https://discord.com/channels/655572317891461132/708431657849585705/908834806551445554).\nThis didn't have any clear advantages other than making a generic `let` in a\nfunction body be more similar to a generic function parameter. Erasing the type\nidentity would have made generic `let` much harder to use, though, without any\nclear ways to get values of the new type. The option we chose is more similar to\ngeneric `let` used to declare an associated type.\n"
  },
  {
    "path": "proposals/p0981.md",
    "content": "# Implicit conversions for aggregates\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/981)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Field order is not significant](#field-order-is-not-significant)\n    -   [Different field orders are incompatible](#different-field-orders-are-incompatible)\n    -   [Explicit instead of implicit conversions](#explicit-instead-of-implicit-conversions)\n\n<!-- tocstop -->\n\n## Problem\n\nWhat operations are supported by default between two data classes with the same\nfields in different orders? What implicit conversions are allowed between\naggregates, such as arrays, tuples, and data classes?\n\n## Background\n\n-   Comparison operators more generally were added to Carbon in\n    [proposal #702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702)\n-   An initial take on these questions was originally in proposal\n    [proposal #561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561)\n    but postponed until we had agreement on the right approach.\n-   The discussion that eventually reached an agreement took place in\n    [question-for-leads issue #710: Default comparison for data classes](https://github.com/carbon-language/carbon-lang/issues/710)\n\n## Proposal\n\nWe propose that we should permissively allow operations between data classes and\nother aggregates with different field orders and types where we can. Field order\nin data classes is salient, but mostly determines the order that operations are\nperformed. The only case where different field orders will forbid an operation\nis with ordering comparisons, where the field order determines the answer\nreturned, not just the order of execution.\n\n## Details\n\nChanges have been made to:\n\n-   [docs/design/classes.md](/docs/design/classes.md),\n-   [docs/design/tuples.md](/docs/design/tuples.md).\n\nThese changes are intended to apply to all aggregate types, including arrays.\n\n## Rationale based on Carbon's goals\n\nThis proposal advances Carbon's goals:\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution):\n    This proposal allows changes to field order and type to be made\n    incrementally.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n    This proposal provides useful and expected facilities for data classes and\n    other aggregate types by default.\n\n## Alternatives considered\n\nAlternatives were considered in:\n\n-   [question-for-leads issue #710: Default comparison for data classes](https://github.com/carbon-language/carbon-lang/issues/710)\n-   [open discussion on 2021-11-29](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.6komy889g3hc)\n\n### Field order is not significant\n\nWe considered not making field order significant in struct types, making them\ninto unordered collections of named fields. This view is consistent with order\nnot being significant in initializers in prior class proposal\n[#561](https://github.com/carbon-language/carbon-lang/pull/561). This had a\nnumber of consequences:\n\n-   Users would not have control over the order of operations performed\n    field-by-field, such as comparisons, unless they use a nominal class type\n    and implement those operations explicitly.\n-   Order comparison operators, like `<` and `<=`, would not be supported. We\n    considered defining an unspecified-but-fixed ordering, for use in things\n    like binary search, accessed in some other way than the ordinary comparison\n    operators.\n\nUltimately, we decided that field order was a salient property of struct types,\nat least determining the layout of the data in memory, and we should use it to\ndetermine the order of operations and how to compare lexicographically.\n\n**Reference:** See\n[this comment by `geoffromer` on #710](https://github.com/carbon-language/carbon-lang/issues/710#issuecomment-893866801).\n\n### Different field orders are incompatible\n\nRather than picking the left-hand argument's field order when the orders were\ndifferent, we considered requiring the field order to match when performing all\ncomparisons, including equality comparisons. An explicit conversion to a common\ntype would be required to perform a comparison when the field orders did not\nmatch.\n\nThe current proposal is more convenient for users, and has the property that\nexecuting `a = b` results in the condition `a == b` being true, even when `a`\nand `b` have different field orders. We also believed that operations like\nassignment between structs with different field orders would be more efficiently\nimplemented using field-by-field assignment rather than a conversion to the\nleft-hand type followed by assignment, and so it was natural to support the\nformer directly.\n\n### Explicit instead of implicit conversions\n\nWe expected a lot of code trying to pass values between functions using\ndifferent field orders would use destructuring instead of direct conversion. As\na result, we thought it might be safer to require explicit conversions to avoid\nsilently converting, say, 10,000 `i8` values to `i64`.\n\nHowever, there were some important use cases for performing the conversion\nimplicitly, such as `(1, 1)` converting to an `(i8, i8)` value. We did not want\nrules that distinguish this case from other implicit conversions, for\nsimplicity. Similarly, we wanted the set of conversions to be consistent across\naggregate types, including tuples, arrays, and data classes. We can amend these\nrules in the future to address cases that are surprising to users in practice.\n\n**Reference:** See\n[this comment by `chandlerc` on #710](https://github.com/carbon-language/carbon-lang/issues/710#issuecomment-983579560).\n"
  },
  {
    "path": "proposals/p0983.md",
    "content": "# Generics details 7: final impls\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/983)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [No `final`, all parameterized impls may be specialized](#no-final-all-parameterized-impls-may-be-specialized)\n    -   [`final` associated constants instead of `final` impls](#final-associated-constants-instead-of-final-impls)\n\n<!-- tocstop -->\n\n## Problem\n\nAllowing an impl to be specialized can lead to higher performance if there are\nparameter values for which a more optimized version can be written. However, not\nall impls will be specialized and there are some benefits when that is known:\n\n-   The values of associated types can be assumed to come from the impl. In many\n    cases this means leaking fewer implementation details into the signature of\n    a function using generics.\n-   The bodies of functions from the impl could be inlined into the caller even\n    when using a more dynamic implementation strategy rather than\n    monomorphization.\n\nHowever, not all impls can opt-out of specialization, since this can create\nincompatibilities between unrelated libraries. For example, consider two\nlibraries that both import parameterized type `TA` and interface `I`:\n\n-   Library `LB` that defines type `TB` can define an impl with type structure\n    `impl TA(TB, ?) as I`.\n-   Library `LC` that defines type `TC` can define an impl with type structure\n    `impl TA(?, TC) as I`.\n\nBoth of these are allowed under\n[Carbon's current orphan rules](/docs/design/generics/details.md#orphan-rule). A\nlibrary `LD` that imports both `LB` and `LC` could then query for the\nimplementation of `I` by `TA(TB, TC)` and would use the definition from library\n`LB`, which would be a conflict if library `LC` marked its impl definition as\nnot specializable.\n\n## Background\n\nRust currently does not support specialization, so for backwards compatibility\nimpls are final by default in Rust's specialization proposal.\n\n## Proposal\n\nWe propose that impls can be declared `final`, but only in libraries that must\nbe imported by any file that would otherwise be able to define a higher-priority\nimpl.\n\n## Details\n\nDetails are in\n[the added `final` impl section to the generics details design document](/docs/design/generics/details.md#final-impl-declarations).\n\n## Rationale based on Carbon's goals\n\nThis proposal supports the following of Carbon's goals:\n\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software):\n    the ability to inline functions defined in `final` impls will in some cases\n    improve performance.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution):\n    reducing how much implementation details are exposed in a generic function's\n    signature allows that function to evolve.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n    reducing the list of requirements in a generic function signature is an\n    improvement to both readability and writability. Furthermore, `final` impls\n    are a tool for making code more predictable. For example, making the\n    dereferencing impl for pointers final means it always does the same thing\n    and produces a value of the expected type.\n\n## Alternatives considered\n\n### No `final`, all parameterized impls may be specialized\n\nIn addition to the [problems listed above](#problem), we ran into problems in\nproposal [#911](https://github.com/carbon-language/carbon-lang/pull/911) trying\nto use the `CommonType` interface to define the type of a conditional\nexpression, `if <condition> then <true-result> else <false-result>`. The idea is\nthat `CommonType` implementations would specify how to combine the types of the\n`<true-result>` and `<false-result>` expressions using an associated type. In\ngeneric code, however, there was nothing to guarantee that there wouldn't be a\nspecialization that would change the result. As a result, nothing could be\nconcluded about the common type if either expression was generic. If at least\nthe common type of two equal types was guaranteed, then you could use an\nexplicit cast to make sure the types were as expected. Some method of limiting\nspecialization was needed.\n\nWe considered other approaches, such as using the fact that the compiler could\nsee all implementations of private interfaces, but that didn't address other use\ncases. For example, we don't want users to be able to customize dereferencing\npointers for their types so that dereferencing pointers behaves predictably in\ngeneric and regular code.\n\n### `final` associated constants instead of `final` impls\n\nWe considered allowing developers to mark individual items in an impl as `final`\ninstead. This gave developers more control, but we didn't have examples where\nthat extra control was needed. It also introduced a number of complexities and\nconcerns.\n\nThe value for a `final let` could be an expression dependent on other associated\nconstants which could be `final` or not. Checking that a refining impl adheres\nto that constraint is possible, but subtle and possibly tricky to diagnose\nmistakes clearly.\n\nIf an impl matches a subset of an impl with a `final let`, how should the\nnarrower impl comply with the restriction from the broader?\n\n```\ninterface A {\n  let T:! type;\n}\n\nimpl [U:! Type] Vector(U) as A {\n  final let T:! Type = i32;\n}\n\nimpl Vector(f32) as A {\n  // T has to be `i32` because of the `final let`\n  // from the previous impl. What needs to be\n  // written here?\n}\n```\n\nWe considered two different approaches, neither of which was satisfying:\n\n-   **Restate approach:** It could restate the `let` with a consistent value.\n    This does not give any indication that the `let` value is constrained, and\n    what impl is introducing that constraint, leading to spooky action at a\n    distance. It was unclear to us whether the restated `let` should use `final`\n    as well, or maybe some other keyword?\n-   **Inheritance approach:** We could have a concept of inheriting from an\n    impl, and require that any impl refining an impl with `final` members must\n    inherit those values rather than declaring them. Inheritance between impls\n    might be a useful feature in its own right, but requires there be some way\n    to name the impl being inherited from.\n\nConsider two overlapping impls that both use `final let`. The compiler would\nneed to validate that they are consistent on their overlap, a source of\ncomplexity for the user. An impl that overlaps both would have to be consistent\nwith both, but would not be able to inherit from both, a problem with using the\ninheritance approach.\n\nUltimately we decided that this approach had a lot of complexity, concerns, and\nedge cases and we could postpone trying to solve these problems until such time\nas we determined there was a need for the greater expressivity of being able to\nmark individual items as `final`. This discussion occurred in:\n\n-   [Document examining an extended example using specialization](https://docs.google.com/document/d/1w-kRC338Jc1ibTu7Vf0pOlGKdrpumfz63bzUIxEj9jY/edit)\n-   [2021-11-29 open discussion](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.6komy889g3hc)\n-   [Carbon's #typesystem channel on Discord](https://discord.com/channels/655572317891461132/708431657849585705/910681126236987495)\n"
  },
  {
    "path": "proposals/p0989.md",
    "content": "# Member access expressions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/989)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Separate syntax for static versus dynamic access](#separate-syntax-for-static-versus-dynamic-access)\n    -   [Use a different lookup rule in templates](#use-a-different-lookup-rule-in-templates)\n    -   [Meaning of `Type.Interface`](#meaning-of-typeinterface)\n\n<!-- tocstop -->\n\n## Problem\n\nWe need syntaxes for a number of closely-related operations:\n\n-   Given an expression denoting a package, namespace, class, interface, or\n    similar, and the name of one of its members, form an expression denoting the\n    member. In C++ and Rust, this is spelled `Container::MemberName`. In many\n    other languages, it is spelled `Container.MemberName`.\n\n-   Given an expression denoting an object and a name of one of its fields, form\n    an expression denoting the corresponding subobject. This is commonly written\n    as `object.field`, with very little deviation across languages.\n\n-   Given an expression denoting an object and a name of one of its methods,\n    form an expression that calls the function on the object. This is commonly\n    written as `object.function(args)`.\n\n-   Given an expression denoting a type, and an expression denoting a member of\n    an interface, form an expression denoting the corresponding member in the\n    `impl` of that interface for that type.\n\nFurther, we need rules describing how the lookup for the member name is\nperformed, and how this lookup behaves in generics and in templates in cases\nwhere the member name depends on the type or value of the first operand.\n\n## Background\n\nC++ and Rust distinguish between the first use case and the rest. Other\nlanguages, such as Swift and C#, do not, and model all of these use cases as\nsome generalized form of member access, where the member might be a namespace\nmember, an interface member, an instance member, or similar.\n\nSee also:\n\n-   [Exploration of member lookup in generic and non-generic contexts](https://docs.google.com/document/d/1-vw39x5YARpUZ0uD2xmKepLEKG7_u122CUJ67hNz3hk/edit)\n-   [Question for leads: constrained template name lookup](https://github.com/carbon-language/carbon-lang/issues/949)\n\n## Proposal\n\nAll these operations are performed using `.`:\n\n```carbon\nfn F() {\n  // Can perform lookup inside the package or namespace.\n  var x: Package.Namespace.Class;\n  // Can perform lookup inside the type of the value.\n  x.some_field = x.SomeFunction(1, 2, 3);\n}\n```\n\nWhen the type of the left-hand operand is a generic type parameter, lookup is\nperformed in its type-of-type instead. Effectively, a generic type parameter\nbehaves as an archetype:\n\n```carbon\ninterface Hashable {\n  let HashValue:! Type;\n  fn Hash[me: Self]() -> HashValue;\n  fn HashInto[me: Self](s: HashState);\n}\nfn G[T:! Hashable](x: T) {\n  // Can perform lookup inside the type-of-type if the type is\n  // a generic type parameter.\n  x.Hash();\n}\n```\n\nWhen the type of the left-hand operand is a template parameter, the lookup is\nperformed both in the actual type corresponding to that template parameter and\nin the archetype, as described above. If a result is found in only one lookup,\nor the same result is found in both lookups, that result is used. Otherwise, the\nmember access is invalid.\n\n```carbon\nclass Potato {\n  fn Mash[me: Self]();\n  fn Hash[me: Self]();\n  alias HashValue = Hashable.HashValue;\n}\nexternal impl Potato as Hashable where .HashValue = u32 {\n  // ...\n}\nfn H[template T:! Hashable](x: T, s: HashState) {\n  // When called with T == Potato:\n  // ❌ Ambiguous, could be `Potato.Hash` or `Hashable.Hash`.\n  x.Hash();\n  // ✅ OK, found only in `Potato`.\n  x.Mash();\n  // ✅ OK, found only in `Hashable`.\n  x.HashInto(s);\n\n  // ✅ OK, same `HashValue` found in both `Potato` and `Hashable`;\n  // `Hashable.Hash` unambiguously names the interface member.\n  var v: T.HashValue = x.(Hashable.Hash)();\n\n  // ✅ OK, unambiguously names the type member.\n  x.(Potato.Hash)();\n}\n```\n\n## Details\n\nSee\n[the changes to the design](https://github.com/carbon-language/carbon-lang/pull/989/files).\n\n## Rationale based on Carbon's goals\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Rejecting cases in a template where a generic interpretation and an\n        interpretation with specific types would lead to different meanings\n        supports incremental migration towards generics by way of a template,\n        where the compiler will help you find places that would change meaning.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Using a single, familiar `container.member` notation for all the member\n        access use cases minimizes the complexity of this portion of the\n        language syntax.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   The behavior of templates is aligned with that in C++, simplifying both\n        comprehension for C++ developers and migration of C++ code.\n\n## Alternatives considered\n\n### Separate syntax for static versus dynamic access\n\nWe could follow C++ and Rust, and use `::` for static lookup, reserving `.` for\ninstance binding:\n\n```\nvar x: Package::Namespace::Class;\nClass::Function();\nx.field = x.Function();\nx.(Interface::Method)();\n```\n\nAdvantages:\n\n-   Visually separates operations that readers may think of as being distinct: a\n    `::` path statically identifies an object whereas a `.` path dynamically\n    identifies a subobject or forms a bound method.\n-   Improves familiarity for those coming from C++.\n-   Removes most of the need for parenthesized member access: `a.(b.c)` would\n    generally become `a.b::c`, like in C++.\n\nDisadvantages:\n\n-   Adds a new token and a new operation.\n-   Swift, C#, and Java do not distinguish these operations syntactically, and\n    we have no evidence that this lack of syntactic distinction creates problems\n    for them in practice.\n-   Likely to result in complexity and inconsistency for operations falling\n    between the two options. For example, in C++:\n    ```\n    struct A {\n      static void F();\n      enum { e };\n    };\n    enum class B { e };\n    void G(A a, B b) {\n      a.F(); // OK, but static dispatch, like A::F().\n      a.e;   // OK, but static dispatch, like A::e.\n      b.e;   // Error.\n    }\n    ```\n-   Does not provide an obvious syntax for `impl` lookup.\n    `Type::Interface::method` would be ambiguous and `Type.Interface::method`\n    would be inconsistent with using `::` for static lookup, so we would likely\n    end up with `Type::(Interface::method)` syntax or similar.\n-   May create the suggestion that `.`s imply a performance-relevant operation\n    and `::`s do not. This will typically not be the case, as `.`s will\n    typically result in, at worst, a constant offset. However, `impl` lookup,\n    which may be performed by either a `.` or a `::`, may require a memory\n    access in cases where dynamic dispatch is in use.\n\n### Use a different lookup rule in templates\n\nSee\n[question for leads: constrained template name lookup](https://github.com/carbon-language/carbon-lang/issues/949)\nfor more in-depth discussion and leads decision.\n\nGiven a situation where the same name can be found in both a type and a\nconstraint when instantiating a template, and resolves to two different things,\nwe could use various different rules to pick the outcome:\n\n```\nclass Potato {\n  fn Bake[me: Self]();\n  fn Hash[me: Self]();\n}\ninterface Hashable {\n  fn Hash[me: Self]() -> HashState;\n  fn HashInto[me: Self](s: HashState);\n}\nexternal impl Potato as Hashable;\n\nfn MakePotatoHash[template T:! Hashable](x: T, s: HashState) {\n  x.Bake();\n  x.Hash();\n  x.HashInto(s);\n}\n```\n\nWe considered the following options:\n\n| Option                | Type only: `x.Bake()` | Both: `x.Hash()` | Constraint only: `x.HashInto(s)` |\n| --------------------- | --------------------- | ---------------- | -------------------------------- |\n| Type                  | -> Type               | -> Type          | ❌ Rejected                      |\n| Type over constraint  | -> Type               | -> Type          | -> Constraint                    |\n| Type minus conflicts  | -> Type               | -> Type          | ❌ Rejected                      |\n| Union minus conflicts | -> Type               | ❌ Rejected      | -> Constraint                    |\n| Constraint over type  | -> Type               | -> Constraint    | -> Constraint                    |\n| Constraint            | ❌ Rejected           | -> Constraint    | -> Constraint                    |\n\nOf these rules:\n\n-   \"Type\" and \"type over constraint\" mean the constraints in a constrained\n    template do not guide the meaning of the program, which creates a surprising\n    discontinuity when migrating from templates to generics.\n-   \"Type minus conflicts\" does not present a valuable improvement over \"union\n    minus conflicts\".\n-   \"Union minus conflicts\" makes the type-only case behave like a non-template,\n    and the constraint-only case behave like a generic. This means that explicit\n    qualification is necessary for all qualified names in a template if it wants\n    to defend against ambiguity from newly-added names, whereas all the earlier\n    options require qualification only for names intended to be found in the\n    constraint, and all the later options require qualification for names\n    intended to be found in the type. However, most of the other rules require\n    explicit qualification in the same cases to defend against names being\n    _removed_.\n-   \"Constraint over type\" means there is potential for a discontinuity in\n    behavior depending on whether we're able to symbolically resolve the type or\n    not: if semantic analysis can determine a type symbolically, you get the\n    behavior from the constraint, and if not, you get the behavior from the\n    type. This may lead to surprising and hard-to-understand program behavior.\n-   \"Constraint\" means that a constrained template behaves essentially the same\n    as a generic, which harms the ability to use constrained templates as an\n    incremental, evolutionary stepping stone from non-constrained templates into\n    generics.\n\nNo rule provides ideal behavior. The most significant disadvantage of the chosen\nrule, \"union minus conflicts\", is that it requires explicit qualification with\neither the type or the constraint in a fully-robust template. However, the other\nleading contender, \"constraint over type\", also requires qualification of all\nnames to prevent silent changes in behavior if a constraint is changed, and\n\"union minus conflict\" seems preferable to \"constraint over type\" in other ways.\n\n### Meaning of `Type.Interface`\n\nIn this proposal, `impl` lookup is performed when a member of an interface\nappears on the right of a `.`. We could also consider applying `impl` lookup\nwhen the name of an interface appears on the right of a `.`. Under that\nalternative, `Class.(Interface)` would be a name for the `impl`, that is, for\n`impl Class as Interface`.\n\nBecause we have previously decided we don't want facet types, such a name would\nbe restricted to only appear in the same places where package and namespace\nnames can appear: on the left of a `.` or the right of an `alias`.\n\nFor example:\n\n```\ninterface MyInterface {\n  fn F();\n  fn G[me: Self]();\n}\nclass MyClass {\n  alias InterfaceAlias = MyInterface;\n  impl as MyInterface {\n    fn F();\n    fn G[me: Self]();\n  }\n}\n\nfn G(x: MyClass) {\n  // OK with this proposal and the alternative.\n  MyClass.(MyInterface.F)();\n  // Error with this proposal, OK with the alternative.\n  MyClass.(MyInterface).F();\n\n  // Names the interface with this proposal.\n  // Names the `impl` with the alternative.\n  alias AnotherInterfaceAlias = MyClass.InterfaceAlias;\n\n  // Error with this proposal, OK with the alternative.\n  MyClass.InterfaceAlias.F();\n  // OK with this proposal, error with the alternative.\n  MyClass.(MyClass.InterfaceAlias.F)();\n\n  // Error under this proposal, OK with the alternative.\n  x.MyInterface.F();\n  // Error under both this proposal.\n  // Also error under the alternative, unless we introduce\n  // a notion of a \"bound `impl`\" so that `x.MyInterface`\n  // remembers its receiver object.\n  x.MyInterface.G();\n  // OK under this proposal and the alternative.\n  x.(MyInterface.G)();\n}\n```\n\nAdvantages:\n\n-   Gives a way to name an `impl`.\n\nDisadvantages:\n\n-   It's not clear that we need a way to name an `impl`.\n-   Presents a barrier to supporting member interfaces, because\n    `MyClass.MemberInterface` would name the `impl MemberInterface as MyClass`,\n    not the interface itself.\n-   Reintroduces facet types, without the ability to use them as a type. Having\n    a way of naming an `impl` may lead to confusion over whether they are\n    first-class entities.\n-   Would either surprisingly reject constructs like `x.MyInterface.G()` or\n    require additional complexity in the form of a \"bound `impl`\" value. The\n    value of such a type would presumably be equivalent to a facet type.\n\nAs a variant of this alternative, we could disallow `Type.Interface` for now, in\norder to reserve syntactic space for a future decision. However, it's not clear\nthat the cost of evolution nor the likelihood of such a change is sufficiently\nhigh to warrant including such a rule.\n"
  },
  {
    "path": "proposals/p0990.md",
    "content": "# Generics details 8: interface default and final members\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/990)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Defaulting to less specialized impls](#defaulting-to-less-specialized-impls)\n    -   [Allow default implementations of required interfaces](#allow-default-implementations-of-required-interfaces)\n    -   [Don't support `final`](#dont-support-final)\n\n<!-- tocstop -->\n\n## Problem\n\nRust has found that allowing interfaces to define default values for its\nassociated entities is valuable:\n\n-   Helps with evolution by reducing the changes needed to add new members to an\n    interface.\n-   Reduces boilerplate when some value is more common than others.\n-   Addresses the gap between the minimum necessary for a type to provide the\n    desired functionality of an interface and the breadth of API that user's\n    desire.\n\nCarbon would benefit in the same ways.\n\n## Background\n\nRust supports specifying defaults for\n[methods](https://doc.rust-lang.org/book/ch10-02-traits.html#default-implementations),\n[interface parameters](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#default-generic-type-parameters-and-operator-overloading),\nand\n[associated constants](https://doc.rust-lang.org/reference/items/associated-items.html#associated-constants-examples).\n\n## Proposal\n\nThis proposal defines both how defaults for interface members are specified in\nCarbon code as well as final interface members in the\n[generics details design doc](/docs/design/generics/details.md#interface-defaults).\n\n## Rationale based on Carbon's goals\n\nThis proposal advances these goals of Carbon:\n\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software):\n    Final members of interfaces can avoid some dynamic dispatch overhead.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution):\n    Defaults simplify adding new members to an interface without having to\n    simultaneously update all impls of that interface.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n    Defaults both reduce boilerplate, making code easier to read and write.\n    Marking interface members as `final` makes the code more predictable to\n    users of that member.\n\n## Alternatives considered\n\n### Defaulting to less specialized impls\n\nRust has observed\n([1](https://rust-lang.github.io/rfcs/1210-impl-specialization.html#default-impls),\n[2](http://aturon.github.io/tech/2015/09/18/reuse/)) that interface defaults\ncould be generalized into a feature for reusing definitions between impls. This\nwould involve allowing more specific implementations to be incomplete and reuse\nmore general implementations for anything unspecified.\n\nHowever,\n[they also observed](http://smallcultfollowing.com/babysteps/blog/2016/09/29/distinguishing-reuse-from-override/):\n\n> [To be sound,] if an impl A wants to reuse some items from impl B, then impl A\n> must apply to a subset of impl B's types. ... This implies we will have to\n> separate the concept of \"when you can reuse\" (which requires subset of types)\n> from \"when you can override\" (which can be more general).\n\nThis is a source of complexity that we don't want in Carbon. If we do eventually\nsupport inheritance of implementation between impls in Carbon, it will do this\nby explicitly identifying the impl being reused instead of having it be\ndetermined by their specialization relationship.\n\n### Allow default implementations of required interfaces\n\nHere are the reasons we considered for not allowing interfaces to provide\ndefault implementations of interfaces they require:\n\n-   This feature would lead to incoherence unless types implementing\n    `TotalOrder` also must explicitly implement `PartialOrder`, possibly with an\n    empty definition. The problem arises since querying whether `PartialOrder`\n    is implemented for a type does not require that an implementation of\n    `TotalOrder` be visible.\n-   It would be unclear how to resolve the ambiguity of which default to use\n    when two different interfaces provide different defaults for a common\n    interface requirement.\n-   It would be ambiguous whether the required interface should be external or\n    [internal](/docs/design/generics/terminology.md#extending-an-interface)\n    unless `PartialOrder` is implemented explicitly.\n-   There would be a lot of overlap between default impls and blanket impls.\n    Eliminating default impls keeps the language smaller and simpler.\n\nThe rules for blanket impls already provide resolution of the questions about\ncoherence and priority and make it clear that the provided definition of the\nrequired interface will be external.\n\n### Don't support `final`\n\nThere are a few reasons to support `final` on associated entities in the\ninterface:\n\n-   Clarity of intent when default methods are just to provide an expanded API\n    for the convenience of callers, reducing the uncertainty about what code is\n    called.\n-   Matches the functionality available to base classes in C++, namely\n    non-virtual functions.\n-   Could reduce the amount of dynamic dispatch needed when using an interface\n    in a `DynPtr`.\n\nThe main counter-argument is that you could achieve something similar using a\n`final` impl:\n\n```\ninterface I {\n  fn F();\n  final fn CallF() { F(); }\n}\n```\n\ncould be replaced by:\n\n```\ninterface IImpl {\n  fn F();\n}\ninterface I {\n  extends IImpl;\n  fn CallF();\n}\nfinal impl (T:! IImpl) as I {\n  fn CallF() { F(); }\n}\n```\n\nThis is both verbose and a bit awkward to use since you would need to\n`impl as IImpl` but use `I` in constraints.\n"
  },
  {
    "path": "proposals/p0998.md",
    "content": "# Principle: One static open extension mechanism\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/998)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Problem\n\nThere are a few ways of approaching open extension, such as defining how\noperators are overload for every type. For Carbon, with its\n[focus on performance](/docs/project/goals.md#performance-critical-software), we\nare particularly interested in those that support static dispatch, to avoid the\nruntime overhead of dynamic dispatch. The three main options are:\n\n-   Open function overloading, where new overloads for a given name can be\n    defined broadly, as is done in C++.\n-   Interfaces, as is done in\n    [Rust](https://doc.rust-lang.org/rust-by-example/trait/ops.html).\n-   Special method names, as are used in\n    [C++](https://en.cppreference.com/w/cpp/language/operators) and\n    [Python](https://docs.python.org/3/reference/datamodel.html#special-method-names).\n\nWe would prefer to use a single mechanism, if possible, for simplicity.\n\n## Proposal\n\nProposal is to use interfaces as the single open extension mechanism.\n\n## Details\n\nDetails are in the added principle doc:\n[docs/project/principles/static_open_extension.md](/docs/project/principles/static_open_extension.md).\n\n## Rationale based on Carbon's goals\n\nThis proposal is pursuing Carbon's goal of having\n[code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n\n## Alternatives considered\n\nEarly arguments for this approach were put forth in\n[this document](https://docs.google.com/document/d/1uvX_hmw5DVs1SFjnehUUizGnI6C099vqIGfUhfCwBIo/edit#).\n"
  },
  {
    "path": "proposals/p1013.md",
    "content": "# Generics: Set associated constants using `where` constraints\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1013)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Status quo](#status-quo)\n    -   [`with` and `,` instead of `where` and `and`](#with-and--instead-of-where-and-and)\n-   [Future work](#future-work)\n\n<!-- tocstop -->\n\n## Problem\n\nThere are a variety of contexts that currently use the keyword `let`:\n\n-   declaring associated constants or types in an interface,\n-   defining associated constants or types in an implementation,\n-   defining local constant in a function body, and\n-   defining class constants.\n\nIn all but the implementation case, the semantics are generally similar to the\nsemantics of passing a value into a function, with some erasing of the specific\nvalue passed and using the type to determine how the name can legally be used.\nHowever,\n[proposal #950](https://github.com/carbon-language/carbon-lang/pull/950) has\nchanged the `let` in an implementation to use the value specified, not its type,\ncreating an inconsistency with the other uses of `let`.\n\nFurthermore, we have come to the realization that we still want to specify the\nvalues of associated constants and types for an implementation even in an API\nfile where we only want to make a forward declaration. This makes that\ninformation available to clients that only look at the API file, who need to\nknow those values for type checking, but otherwise don't need to see the full\ndefinition of the implementation. This suggests that those assignments should be\ndeclared outside of definition block's curly braces `{`...`}`.\n\nLastly, there is a bit of redundancy in Carbon since `where` clauses are also a\nway of specifying the values of associated constants and types in other Carbon\ncontexts.\n\n## Background\n\nThe `let` syntax for setting an associated type in an interface implementation\nwas originally decided in issue\n[#739: Associated type syntax](https://github.com/carbon-language/carbon-lang/issues/739)\nand implemented in proposal\n[#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731).\n\nProposal\n[#950: Generics details 6: remove facets](https://github.com/carbon-language/carbon-lang/pull/950)\nmade two relevant changes:\n\n-   The type part of a `let` in an `impl` block is no longer \"load bearing\": the\n    only legal types are `auto` and whatever was in the corresponding interface.\n    In particular, the `let` in an `impl` block does not erase.\n-   There is now a defined meaning for a generic `let` statement in a function\n    body that can erase depending on the type specified.\n\nCombined with the `let` in an interface giving you an erased type, or archetype,\nthis has made the meaning of `let` in an `impl` block inconsistent with other\nplaces using `let`.\n\n## Proposal\n\nThe suggested change is to use a `where` clause as part of an `impl` declaration\nto specify associated constants and types instead of `let` declarations inside\nof the `impl` definition. In effect, it removes `let` declarations from `impl`\nblocks in exchange for allowing an `impl` declaration to implement a constraint\nexpression instead of a simple interface or named constraint.\n\nThis proposal updates the following design docs on the generics feature to\nreflect this change:\n\n-   [docs/design/generics/overview.md](/docs/design/generics/overview.md)\n-   [docs/design/generics/terminology.md](/docs/design/generics/terminology.md)\n-   [docs/design/generics/details.md](/docs/design/generics/details.md)\n\n## Rationale based on Carbon's goals\n\nAs a simplification, this proposal advances the goal of having Carbon\n[code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nIn particular, having a simple specification and be simple to implement.\n\nThis is an example of\n[the \"prefer providing only one way to do a given thing\" principle](/docs/project/principles/one_way.md),\nby switching to a single way of specifying associated constants and values.\n\n## Alternatives considered\n\n### Status quo\n\nThe main alternative considered was the status quo. We did have two concerns\nwith this proposal, however we felt that this behavior would not be surprising\nto developers in practice.\n\n**Concern:** Due to interface defaults, it is possible for copy-pasting the\ntype-of-type expression from an `impl` block in a `class` into a constraint in a\nfunction signature to give a constraint that is weaker than what that impl block\nactually delivers.\n\n**Concern:** Because a specialization of an `impl` can change the values of\nassociated constants, a type might not actually satisfy a constraint that it\nappears to implement when that constraint specifies the values of associated\nconstants. In this example:\n\n```\ninterface Bar {\n  let X:! Type;\n}\nclass Foo(T:! Type) {\n  impl as Bar where .X = T { ... }\n}\n```\n\nit appears that `Foo(T)` satisfies the constraint that `Bar where .X = T`, but\nthere could be specializations that set `.X` to different values for some\nspecific values of `T`.\n\n### `with` and `,` instead of `where` and `and`\n\nInstead of matching the syntax used when specifying constraints, we could have\nused a different syntax to highlight that this is assigning instead of\nconstraining. The suggestion that came up in discussion was using `with` instead\nof `where` and a comma `,` instead of `and` to join multiple clauses.\n\nWe decided that it would not be good to have two syntaxes that were very similar\nbut different, and that there was some benefit to be able to copy-paste between\nthe constraint context and the implementation context.\n\n## Future work\n\nThis proposal will allow us to support declaring that a type implements an\ninterface inside an API file separate from the definition of the `impl`, even\nfor internal `impl`s. However, that feature is waiting on resolution of\n[#472: Open question: Calling functions defined later in the same file](https://github.com/carbon-language/carbon-lang/issues/472)\nand proposal\n[#875: Principle: information accumulation](https://github.com/carbon-language/carbon-lang/pull/875).\n\nIf and when we do add support declaration of impls without definition, we will\nneed to answer the question: do you have to repeat `where` constraints from a\nforward declaration of an impl when it is later defined?\n\n```\nclass Vector(T:! Type) {\n  impl as Container where .Element = T and .Iter = VectIter(T);\n}\n\n// Probably okay:\nfn Vector(T:! Type).(Container.Begin)[me: Self]() ...\n\n// Maybe okay:\nclass Vector(T:! Type) {\n  // Not repeating constraints on .Element and .Iter above:\n  impl as Container {\n    fn Begin[me: Self]() ...\n  }\n}\n```\n"
  },
  {
    "path": "proposals/p1025.md",
    "content": "# Roadmap for 2022\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1025)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Retrospective on 2021](#retrospective-on-2021)\n    -   [Broaden core team representation so no organization is >50%](#broaden-core-team-representation-so-no-organization-is-50)\n    -   [Example ports of C++ libraries to Carbon (100% of woff2, 99% of RE2)](#example-ports-of-c-libraries-to-carbon-100-of-woff2-99-of-re2)\n    -   [Demo implementation of core features with working examples](#demo-implementation-of-core-features-with-working-examples)\n    -   [Executable semantic specification for core features with test cases](#executable-semantic-specification-for-core-features-with-test-cases)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Problem\n\nIt's (past) time to update our roadmap for 2022, following Carbon's annual\n[roadmap process](/docs/project/roadmap_process.md).\n\n## Background\n\nCarbon has an annual roadmap to align and focus the work of the teams and\ncommunity. For 2021, our main objective was to speed up the development of the\nCarbon project while it remains a private experiment, by:\n\n-   Increasing the investment by existing individuals and organizations.\n-   Increasing the breadth of different individuals and organizations investing\n    in Carbon.\n\n## Proposal\n\nWe have two primary goals for 2022:\n\n-   Shift the experiment to being public.\n-   Reach the point where the core language design is substantially complete.\n\nSee the\n[updated roadmap](https://github.com/carbon-language/carbon-lang/pull/1025/files)\nfor more details.\n\n## Retrospective on 2021\n\nAs we plan for 2022, we should look at how well we did at achieving our\n[objectives for 2021 and their key results](https://github.com/carbon-language/carbon-lang/blob/9523ac97bf5c3b7e52fa14299c1391c62dd907f5/docs/project/roadmap.md).\n\n### Broaden core team representation so no organization is >50%\n\n> Our goal is that no single organization makes up >50% of the core team to\n> ensure that we are including as broad and representative a set of perspectives\n> in the evolution of Carbon as possible.\n\nIn 2021, we dissolved the core team, and introduced a set of three leads. Two of\nthose leads represent the same organization. The leads now have more\norganizational diversity than the core team did at the start of 2021, so this is\na partial success. (And, vacuously, no organization makes up any part of the\ncore team any more!)\n\nIn the wider Carbon community, most active participants and nearly all proposals\nare still from a single organization, but we are seeing significant and\nincreasing contribution outside that organization.\n\nThe spirit of this goal has been retained for 2022, but it has been reformulated\nto better fit our current organization and governance model, and somewhat\nreduced in scope. Instead of looking for <50% of the Carbon leadership from any\none organization, we're now looking for <50% of active participants from any one\norganization. In future years, we hope to also reach the point where <50% of the\nCarbon leads are from any one organization, but that doesn't seem like a\nrealistic goal for 2022.\n\n### Example ports of C++ libraries to Carbon (100% of woff2, 99% of RE2)\n\nWe did not make much progress on this goal in 2021, in part because we made less\nprogress on the Carbon language design in 2021 than anticipated. It remains\nimportant that we do this work, for the same reasons as in 2021: it both\nmeasures our progress solidifying Carbon's design and demonstrating the value\nproposition of Carbon.\n\nFor 2022, as we move towards going public and completing the language design,\nour expectations for these ports become higher, and we now aim to not only\nprovide the ported example code but also to have a sufficiently complete\nexecutable semantics implementation that parts of it can be demonstrated to work\ncorrectly.\n\n### Demo implementation of core features with working examples\n\n> A core set of Carbon features should be implemented sufficiently to build\n> working examples of those features and run them successfully.\n\nThe toolchain supports parsing for many basic features, such as functions,\nvariables, operators, and so on, but no type-checking or code generation.\n\n> Basic benchmarking of the different phases of compilation (lexing, parsing,\n> etc).\n\nWe have some benchmarks accompanying the toolchain, but the coverage here is\nincomplete.\n\nThis takes us some of the way to our intended outcome, but there's a lot more to\ndo.\n\n### Executable semantic specification for core features with test cases\n\n> This should include both a human readable rendering of the formal semantics as\n> well as an execution environment to run test cases through those semantics.\n> [...]\n\nIn the 2021 roadmap, we prioritized completing the demo toolchain implementation\nover work on executable semantics. We did not end up following that ethos\nthroughout 2021, and the outcome is that most of the implementation work was\nperformed in executable semantics rather than in the toolchain. It would not be\nunfair to say that executable semantics has ended up as a better model of a demo\nCarbon implementation than the toolchain.\n\nNonetheless, we made great progress here. Executable semantics supports a broad\nsubset of the currently approved Carbon feature set, and some things beyond that\nfeature set. What is less clear is whether our experiment of having a clear and\nprecise formal specification expressed as an implementation that favors clarity\nof exposition over all else is successful.\n\n## Rationale based on Carbon's goals\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   A roadmap is an important tool for setting community expectations and\n        direction.\n    -   Going public is fundamental to the open community we aim to have.\n    -   Broadening participation is an essential factor in building a diverse\n        and welcoming community.\n\n## Alternatives considered\n"
  },
  {
    "path": "proposals/p1083.md",
    "content": "# Arithmetic expressions\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1083)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Symbols](#symbols)\n    -   [Semantics](#semantics)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n    -   [Choice of operator symbols](#choice-of-operator-symbols)\n    -   [Signed integer semantics](#signed-integer-semantics)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use a sufficiently wide result type to avoid overflow](#use-a-sufficiently-wide-result-type-to-avoid-overflow)\n    -   [Guarantee that the program never proceeds with an incorrect value after overflow](#guarantee-that-the-program-never-proceeds-with-an-incorrect-value-after-overflow)\n    -   [Guarantee that all integer arithmetic is two's complement](#guarantee-that-all-integer-arithmetic-is-twos-complement)\n    -   [Treat overflow as an error but don't optimize on it](#treat-overflow-as-an-error-but-dont-optimize-on-it)\n    -   [Don't let `Unsigned` arithmetic wrap](#dont-let-unsigned-arithmetic-wrap)\n    -   [Provide separate wrapping types](#provide-separate-wrapping-types)\n    -   [Do not provide an ordering or division for `uN`](#do-not-provide-an-ordering-or-division-for-un)\n    -   [Give unary `-` lower precedence](#give-unary---lower-precedence)\n    -   [Include a unary plus operator](#include-a-unary-plus-operator)\n    -   [Floating-point modulo operator](#floating-point-modulo-operator)\n    -   [Provide different division operators](#provide-different-division-operators)\n    -   [Use different division and modulo semantics](#use-different-division-and-modulo-semantics)\n    -   [Use different precedence groups for division and multiplication](#use-different-precedence-groups-for-division-and-multiplication)\n    -   [Use the same precedence group for modulo and multiplication](#use-the-same-precedence-group-for-modulo-and-multiplication)\n    -   [Use a different spelling for modulo](#use-a-different-spelling-for-modulo)\n-   [Future work](#future-work)\n    -   [Provide separate wrapping operators](#provide-separate-wrapping-operators)\n    -   [Provide separate operations to detect overflow](#provide-separate-operations-to-detect-overflow)\n\n<!-- tocstop -->\n\n## Problem\n\nCarbon needs a set of arithmetic operators in order to perform basic\ncalculations on various kinds of built-in and user-defined numbers and\nnumber-like values: integers, real numbers, complex numbers, vectors, matrices,\nand so on.\n\n## Background\n\n### Symbols\n\nConventions for arithmetic operators have a very long tradition. The following\nsymbols have common meaning across C, C++, Java, JavaScript, Rust, Swift, and\nmany other languages:\n\n-   `+` and `-` mean addition and subtraction, as in mathematics. Unary `-`\n    forms a negated value -- an additive inverse. Sometimes, unary `+` is\n    permitted, as a no-op.\n-   `*` means multiplication, diverging from the use of '×', '⋅', or simply\n    juxtaposition in normal mathematical notation. However, this symbol does\n    have some visual similarity to '×'.\n-   `/` means division, diverging from the use of '÷', fraction notation, or an\n    exponent of -1 in mathematics. However, this symbol does somewhat visually\n    resemble fractional notation that has \"fallen over\" to the left.\n-   `%` means remainder, diverging from the use of the word \"mod\" in\n    mathematics, and, perhaps confusingly, resembling the '÷' division operator\n    from mathematics.\n\n### Semantics\n\nEfficient integer types often have finite bounds on the numbers they can\nrepresent, and we expect Carbon's to be no different. This presents a problem\nfor operations that might produce values outside those bounds: what should the\nbehavior of a primitive arithmetic operation be if the result cannot be\nrepresented? Moreover, some operations, such as division by zero, have no\nmathematically-defined result.\n\nDifferent languages take different approaches to this problem.\n\n-   In C and C++, signed integer overflow and division by zero -- including\n    floating-point division by zero -- have undefined behavior, meaning that\n    there are no constraints on the behavior of a program that performs such a\n    calculation.\n-   In [Rust](https://rust-lang.github.io/rfcs/0560-integer-overflow.html),\n    these conditions are classified as being errors, which, depending on various\n    factors, will either panic or give a two's complement result. Rust also\n    provides a `Wrapping<T>` type, where `T` is a signed or unsigned integer\n    type, that provides arithmetic with guaranteed two's complement wrapping\n    semantics.\n-   In Swift, overflow triggers a runtime fatal error. Arithmetic operators can\n    be prefixed with `&`, such as `big_num &* other_big_num`, to request two's\n    complement wrapping behavior instead.\n-   In Java, integer arithmetic has two's complement wrapping behavior. Division\n    by zero throws an exception.\n-   In JavaScript, all arithmetic is (at least notionally) performed in IEEE 754\n    double-precision floating-point, so all operations have defined results,\n    although some integer operations may produce non-integer results, such as\n    infinities or NaNs, and some produce incorrect integer results. For example,\n    in JavaScript, `100000001 * 100000001` evaluates to `10000000200000000` not\n    to `10000000200000001`.\n-   In LLVM, the result of overflow is a poison value, which results in\n    undefined behavior only when it is observed, for example by a branch, and\n    otherwise propagates to dependent values. This permits speculative execution\n    of arithmetic that might overflow.\n\n## Proposal\n\nCarbon will provide the five usual binary arithmetic operators -- `+`, `-`, `*`,\n`/`, and `%` -- with their usual semantics. A unary minus `-` operator will also\nbe provided, but no unary plus `+` operator.\n\n| Notation | Meaning            |\n| -------- | ------------------ |\n| `-a`     | Negation           |\n| `a + b`  | Addition           |\n| `a - b`  | Subtraction        |\n| `a * b`  | Multiplication     |\n| `a / b`  | Division           |\n| `a % b`  | Modulo / remainder |\n\nThese operators follow the same precedence rules as in C-family languages --\nmultiplicative operators bind tighter than additive operators, and negation\nbinds tighter than multiplicative operators. Unlike in other C-family languages,\nno precedence is defined between `%` and other binary operators, so\n`a + b % c * d` is an error, and does not mean `a + (b % c) * d` as it would in\nC++.\n\nUnlike in C++, lossy conversions are never performed. Instead, built-in\narithmetic is not permitted unless one of the operand types can represent all\nthe values of the other operand. The calculation is performed in that operand\ntype; there is no implicit widening to Carbon's equivalent of `int`.\n\nUnsigned integer types `uN` model arithmetic modulo 2<sup>`N`</sup>, and we\nstrongly advise that they are not used except when those semantics are desired,\nsuch as in random number generation, cryptography, hashing, and similar domains.\n\nFor signed integer types `iN`, it is a programming error if overflow occurs. We\nguarantee that in development build modes such errors will result in a runtime\ntrap, and that in hardened build modes the result will either be a trap or the\ntwo's complement value.\n\nInitially, no support will be provided for wrapping signed integer arithmetic,\nnor for non-wrapping unsigned integer arithmetic. This can be added by a future\nproposal if we find there is sufficient demand for either.\n\nFloating-point types use IEEE 754 semantics, with round-to-nearest rounding\nmode, no signaling NaNs, and no floating-point exceptions.\n\nThis proposal takes no position on whether the `+` operator is supported on\nstrings to perform concatenation.\n\nSee the changes to the design for more details; the rest of this proposal will\nfocus on the rationale and alternatives.\n\n## Rationale based on Carbon's goals\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   Treating overflow as a programming error empowers static and dynamic\n        analysis tools to distinguish arithmetic bugs from intentional\n        wraparound.\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software)\n    -   Allowing the optimizer to assume that signed integer overflow does not\n        occur in performance build modes allows certain important loop\n        optimizations to fire that would otherwise be incorrect.\n    -   Avoiding extending into larger types when performing arithmetic on small\n        operands aids in the ability to vectorize.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Each subexpression of an arithmetic expression is given a specific type,\n        rather than being computed in a type of sufficient width for any\n        possible value, in order to make it simple to factor out subexpressions.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Using the same operators as other languages, with largely the same\n        semantics as C++, should aid readability and writability especially for\n        those with less Carbon-specific knowledge.\n    -   Performing built-in arithmetic in the larger operand type and refusing\n        cases where a lossy conversion would be performed in C++ reduces the\n        scope for confusion and surprises.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   Treating signed integer overflow as an error condition, and having it\n        produce a runtime error in some build modes, will assist with certain\n        forms of testing and with analysis of program behavior. For example,\n        fuzz testing can be used to locate overflow bugs, with confidence that\n        any overflow detected is unintentional.\n-   [Modern OS platforms, hardware architectures, and environments](/docs/project/goals.md#modern-os-platforms-hardware-architectures-and-environments)\n    -   The choice of division and modulo semantics aims to provide fast\n        execution and small code size on modern hardware architectures.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Using the same operator set as C++ may aid migration of C++ developers\n        and make code using interop between Carbon and C++ easier to follow.\n    -   Making similar choices for the behavior of signed and unsigned types\n        will make a correct but unidiomatic conversion of C++ into Carbon\n        easier; however, in idiomatic Carbon, signed types are expected to be\n        used more frequently.\n\n### Choice of operator symbols\n\nWe want Carbon to provide a close analogue of standard mathematical expression\nnotation, with some unsurprising set of operators. While accessibility to\nbeginners is important, the most important audience for which the operators set\nshould be unsurprising is programmers with C++ or Rust experience. The choice of\n`+`, `-`, `*`, `/`, and `%` is ubiquitous among programming languages, and any\nsignificant change to this symbol set for the benefit of programming novices\nwith a mathematical background would be a detriment to those with a background\nin other programming languages.\n\nTherefore we choose the conventional symbol set.\n\n### Signed integer semantics\n\nCarbon prioritizes fast and predictable performance above all other factors.\nAllowing an optimizer to assume that certain forms of arithmetic do not result\nin overflow can improve program performance and allow the generation of smaller\ncode. Moreover, while in general we only want to provide the means for accessing\nthe fastest possible implementation of an operation, we expect integer\narithmetic to be so ubiquitous that it's important that the most efficient\noption be the default option.\n\nAt the same time, it's important that Carbon code can be used in safety-critical\nscenarios where unbounded undefined behavior on integer arithmetic is\nproblematic, so in a hardened build mode, we provide stronger guarantees.\n\n## Alternatives considered\n\n### Use a sufficiently wide result type to avoid overflow\n\nWe could define that integer operators always produce a sufficiently wide result\ntype such that overflow never occurs, and defer all overflow handling --\nchecking for out-of-bounds values, wrapping around, or a programmer assertion\nthat overflow simply doesn't happen -- until the end of the computation or some\nexplicit step.\n\nFor example:\n\n```\nfn F(a: i32, b: i32, c: i32) {\n  // a * b is computed in i63,\n  // ... + c is computed in i64.\n  // =! is an assertion that the value is in-range.\n  let d: i32 =! a * b + c;\n\n  // Same, but =% says to wrap around.\n  let e: i32 =% a * b + c;\n\n  // If the value doesn't fit in the specified type, pattern-matching fails.\n  let f: i32 = a * b + c else { return; }\n}\n```\n\nWe could put a limit on how large an intermediate type can be, and reject if it\nwould require a larger intermediate operand than the largest we can efficiently\nsupport.\n\nThis approach seems quite promising, but close inspection finds a number of\nnon-trivial issues.\n\nAdvantages:\n\n-   No implicit undefined behavior or incorrect results on overflow.\n-   Forces developer to think about the possibility of overflow and write down\n    what they intend to happen.\n-   If the final assignment is `=%` or `=!`, all intermediate arithmetic other\n    than division and remainder can be done in the result type, avoiding the\n    need for wide computations.\n\nDisadvantages:\n\n-   This approach is novel and it's unknown whether developers would accept its\n    ergonomic burden.\n-   Decreases the uniformity of the model. While we can generalize `=!` to mean\n    \"assign assuming the RHS fits into the LHS\", there doesn't seem to be any\n    good generalization of `=%` to other situations and types.\n-   The largest type for which we can truly efficiently perform arithmetic is\n    `i64` / `u64`. While 128-bit arithmetic is typically available on our target\n    architectures, use of it will often be less efficient and may increase\n    register pressure. Calculations as simple as `(a + b) / c` may be rejected\n    if the operands are already in the largest efficient type.\n-   Operations such as negation and division can increase the width of the\n    operand: `-i32.Min` and `i32.Min / -1` don't fit in `i32`. The following\n    approaches to this problem were considered:\n    -   Remove the `Min` value from `iN` types, so the negative and positive\n        range are identical. However, this would severely violate programmer\n        expectations, for example in some important bit-manipulation cases.\n    -   Give integer types a range of values rather than simply a bit-width. For\n        example, we can say that negation on `i32` produces a type that can\n        represent [-2<sup>31</sup>+1, 2<sup>31</sup>], which still fits in 32 bits.\n        However, this would add significant complexity to the type system, and with\n        this approach, division would still increase the bit width: for example,\n        `a / b`, where `a` and `b` are `iN`s, has 2<sup>`N`</sup>+1 distinct possible\n        values. This is especially surprising because integer division is usually\n        expected to make a number smaller!\n-   Refactoring code becomes more challenging, as the appropriate intermediate\n    type must be determined. Mitigating this, the type system would inform the\n    programmer when they make a mistake.\n-   The `!` and `%` annotations become quite viral: they would be needed not\n    only in initialization and assignment, but likely also in `case`, `return`,\n    and other initialization contexts not using `=`. As an alternative, the\n    annotation could be put on the outermost arithmetic operator, but that is\n    likely to be syntactically awkward, especially in unparenthesized\n    expressions such as `a + b +% c`.\n-   It will likely become idiomatic in many communities to either always use `%`\n    or always use `!`.\n    -   Always using `!` means that the developers see no benefit compared to\n        the behavior as proposed here, and nonetheless pay an ergonomic cost.\n    -   Always using `%` means that we lose any ability to distinguish between\n        intentional wraparound and overflow, making a class of bugs that would\n        otherwise be easily detectible be undetectable without making the\n        program behavior correct.\n-   Division by zero is still not handled.\n\n### Guarantee that the program never proceeds with an incorrect value after overflow\n\nWe could say that overflow errors always result in program termination, possibly\nwith the permission for the compiler to give the mathematically correct result\ninstead if it so chooses.\n\nThis would result in slower and larger code being generated in a lot of cases.\nSome optimizations would still be possible if the optimizer could ensure that it\nonly increased the set of cases for which the correct result is given, but\ncurrent optimizers are not well-suited to perform that task.\n\nGiven Carbon's emphasis on performance, this approach is rejected without\nprejudice until we have a demonstration that no important performance metric is\nharmed by it.\n\n### Guarantee that all integer arithmetic is two's complement\n\nInstead of making overflow a programming error, we could define it as two's\ncomplement. This is, for example, the approach taken by Java.\n\nThe major problem with this approach is that it makes erroneous wrapping and\nintentional wrapping indistinguishable. This would make finding such bugs much\nharder for readers of the code, and all but impossible for static and dynamic\nanalysis tools. Making overflow issues programming errors allows problems to be\ncaught earlier and more reliably.\n\n### Treat overflow as an error but don't optimize on it\n\nWe could follow Rust and say that overflow is an error, but that we promise\nwe'll either catch it or give two's complement semantics. This approach is\ncurrently rejected for the same reason we reject\n[guaranteeing we catch all cases where we can't give a correct result](#guarantee-that-the-program-never-proceeds-with-an-incorrect-value-after-overflow).\n\n### Don't let `Unsigned` arithmetic wrap\n\nWe could treat `Unsigned(N)` like `Integer(N)`, and make it an error by default\nif it overflows. However, this doesn't seem like a great fit for the problem\ndomain.\n\nThere are, broadly speaking, two different classes of use cases we want to\nsupport:\n\n-   Cases where the developer wants a number. They might have some expectation\n    of the range of the number -- eg, non-negative, or strictly positive, or\n    between -1 and 100 -- or they might just want a number and not have explicit\n    bounds. We expect `iN` to be used for all such cases, and do not want to\n    treat the non-negative cases as a distinct and special type.\n-   Cases where the developer wants the ring ℤ/2<sup>n</sup>ℤ of integers modulo\n    2<sup>n</sup>, for example in cryptography, hashing, or random number\n    generation.\n\nThe second class is certainly rarer than the first, but contains many important\nuse cases.\n\nThe typical arguments for using an unsigned type for the first class of use\ncases are:\n\n-   Better expression of developer intent. It is generally preferable to make\n    invalid states unrepresentable, and if negative numbers are invalid, then\n    unsigned types are better suited than signed types. However, supporting this\n    use case with the same types used to support the wrapping use cases results\n    in a situation where one side or the other has to make compromises. The\n    alternative would be to have three different kinds of type: signed,\n    unsigned, and modulo. But in that setup, it's not clear that the value added\n    by unsigned types is worthwhile. Also, it's common to want to take the\n    difference of such unsigned quantities, and it's generally preferable for\n    such subtractions to produce a negative result rather than a subtle bug.\n    Moreover, while a restriction to non-negative values is common, supporting\n    only the case of a range restriction to [0, 2<sup>N</sup>-1], but not any other\n    range, does not do a good job of addressing the general desire to capture intent\n    and to make invalid states unrepresentable.\n-   Ability to reduce storage size. Spending a sign bit every time a number is\n    stored, even when it's known to be non-negative is wasteful. This is an\n    important concern, and one we should address, but it's thought to be better\n    to address this by annotating a field with a description of how it should be\n    packed -- such as in a bit-field -- rather than by changing the type of the\n    data and possibly the behavior of operations on it.\n\nAdditionally, providing unsigned types for which overflow is an error introduces\na much larger risk of that error state being inadvertently reached than for\nsigned types, because calculations typically involve numbers that are close to\nzero, which is far from overflowing in signed types but near to overflowing in\nunsigned types. For example, a calculation such as `a - b + c` may be known to\nalways produce a non-negative result, and the developer may be tempted to use\nnon-negative non-wrapping types for `a`, `b`, and `c`, but doing so introduces\nthe risk that the intermediate `a - b` calculation is negative. By contrast,\noverflow would only occur in a signed calculation if the numbers involved were\nvery large.\n\n### Provide separate wrapping types\n\nWe could provide distinct types for wrapping versus non-wrapping use cases,\nindependent of the choice of signedness. This approach is being followed by\nRust.\n\nAdvantages:\n\n-   Avoids coupling two decisions that are logically independent.\n-   Allows developer intent to be expressed more explicitly, in the case where\n    the intent is a non-negative but non-wrapping integer.\n\nDisadvantages:\n\n-   Twice as many kinds of integer types, likely meaning twice as many `impl`s\n    need to be defined for each operation, twice as many overloads in each\n    overload set, and so on.\n-   The presence of unsigned types for which overflow is an error has a greater\n    risk of inadvertent overflow, as described in the previous section.\n-   Less familiar to those coming from C++.\n\n### Do not provide an ordering or division for `uN`\n\nFor arithmetic purposes, we treat `uN` as the integers modulo 2<sup>N</sup>.\nThere is no single canonical total order for that ring, and because\nmultiplication by even numbers loses information by discarding the high-order\nbit, not all non-zero numbers have\n[multiplicative inverses](https://en.wikipedia.org/wiki/Modular_multiplicative_inverse),\nand so division is not well-defined. We could be more mathematically pure by\nrefusing to implement `<` and friends for `uN`, and similarly refusing to\nsupport `/`.\n\nHowever, the `uN` types exist as much for pragmatic purposes as for mathematical\nones. Making the choice to treat all `uN` values as non-negative is somewhat\narbitrary, but is both unsurprising to those coming from C++ and useful for the\ncases where some ordering is desired.\n\n### Give unary `-` lower precedence\n\nIn this proposal, `- a * b` is interpreted as `(-a) * b`. We could instead\ninterpret it as `- (a * b)`.\n\nAdvantages:\n\n-   Can be argued as better following mathematical convention.\n\nDisadvantages:\n\n-   Unfamiliar to people coming from most other programming languages, including\n    C++.\n-   If we followed our normal precedence partial ordering rule, this would mean\n    that `a * -b` is invalid, because `*` has higher precedence than `-`.\n\nComparison to other languages:\n\n-   C and C++ give all unary operators (including unary `-` and unary `+`)\n    higher precedence than any binary operator.\n-   Go, Rust, and Swift give unary `-` higher precedence than multiplication.\n-   Python binds unary `-` more tightly than multiplication but less tightly\n    than exponentiation, so `- a * b` is `(- a) * b` but `- a ** b` is\n    `- (a ** b)`.\n-   Haskell gives unary `-` the same precedence as binary `-` and rejects\n    `a * - b`.\n\n### Include a unary plus operator\n\nC and C++ include a unary `+` operator. In principle, this operator permits\nlists of numbers to be written with an operator attached to each:\n\n```cpp\nint arr[] = {\n  -100,\n  -50,\n  +20,\n  +400\n};\n```\n\n... but in practice this use case is rare at best, and unary `+` in C++ is\ninstead mainly used to coerce operands to prvalues of built-in types. For\nexample, `auto *p = +[]{ /*...*/ };` might be used to create a function pointer\n(`auto` deduction would fail without the unary `+` operator), and\n`min(+Class::static_member, x)` might be used to force `Class::static_member` to\nbe loaded, to avoid requiring the static member to be defined.\n\nSuch usage of `+` is a design wart that we need not replicate. If we want a\nmechanism to decay an operand, we can pick a better name for it than `+`.\n\n### Floating-point modulo operator\n\nIt would be possible and sometimes useful to support the `%` operator for\nfloating-point types.\n\nAdvantages:\n\n-   When desired, `f1 % f2` would be a more concise notation than a call to an\n    `fmod` function (however it is named).\n\nDisadvantages:\n\n-   Uses of this operation would likely be rare and unfamiliar enough that\n    people would assume an integer operation is being performed when they see\n    the operator.\n-   This operation is not available in hardware in many modern architectures,\n    and providing it as a built-in operator may create a false impression of its\n    implementation as a non-trivial library function.\n-   We lack sufficient evidence of utility to propose it at this time.\n\n### Provide different division operators\n\nWe could follow Python3 and provide an `/` operator for integers that produces a\nfloating-point (or perhaps rational) type. This would be mathematically clean:\nignoring overflow and precision loss, all standard properties for division would\nbe maintained. Or we could follow Haskell and refuse to provide an `/` operator\nbetween integers on the basis that such division is not mathematically defined\nfor that type. Or we could provide a division operator that produces a pair of\ndividend and modulo, or an `Optional(Int)` that is absent whenever the division\nis inexact. In each case, functionality not available through operators could be\nprovided with named functions instead.\n\nAll of these options are likely to be surprising to programmers coming from C++,\nto a level that outweighs the perceived benefit.\n\n### Use different division and modulo semantics\n\nThere are multiple somewhat-reasonable ways to define division operations for\nsigned integers (whether we provide those operations as operators or library\nfunctions). Assuming operator notation for now, and that we define modulo as\n`a % b == a - a / b * b`, the following options all have merit:\n\n<!-- prettier-ignore -->\n| Property                             | Round towards zero (truncating division) | Round towards negative infinity (floor division) | Round based on sign of divisor\\[1] (Euclidean division) |\n| ------------------------------------ | -------- | -------- | --------- |\n| `(-a) / b ==`<br>` a / (-b)`         | :+1: Yes | :+1: Yes | No        |\n| `(-a) / b ==`<br>` -(a / b)`         | :+1: Yes | No       | :+1: Yes  |\n| `a / (-b)  ==`<br>` -(a / b)`        | :+1: Yes | No       | No        |\n| `(a + k * b) / b`<br>` == a / b + k` | No       | :+1: Yes | :+1: Yes  |\n| Sign of `a % b`                      | Same as `a` | :+1: Same as `b` | :+1: Never negative |\n| x86 instruction?                     | :+1: Yes: `cqo` (or similar) + `idiv` | First option + fixup:<br> `s * (a / (s * b))` where `s` is `sign(a) * sign(b)`[2] | First option + fixup:<br>`a / b - (a % b < 0)` |\n| LLVM IR + optimization support       | :+1: Yes | No       | No        |\n| Use in existing languages            | C, C++, Rust, Swift <br> `quotRem` in Haskell | `//` and `%` in Python <br> `/` in Python 2 only <br> `divMod` in Haskell | None? |\n\nThe cells marked :+1: suggest generally desirable properties. For further\nreading, see\n[this Microsoft Research paper](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf).\n\nOur options here are as follows:\n\n-   Pick one of the two interpretations as the meaning of `/`, and (optionally)\n    pick one of the above interpretations as the meaning of `%`); perhaps\n    provide the others as library functions or as additional operators.\n-   Do not provide any of these operators for integers and provide only named\n    functions.\n\nNote that we are not required to provide a `%` that is consistent with our\nchosen `/` operator. (We could pick truncate-towards-zero for `/` and\ntruncate-towards-negative-infinity for `%`, for example.) There is\nlong-established tradition here, but it's unclear to what extent practicing\nprogrammers really care about the relationship between `/` and `%`.\n\nIt is likely that most Carbon code that performs division and modulo between\nsigned integer types does not actually care about what happens when either\noperand is negative. Therefore, following our goals of supporting\nhigh-performance code and current CPU architectures, we will choose to implement\n`/` and `%` as division with truncation towards zero. The other variants can be\nprovided by a library function, if at all.\n\n[1]: That is: for positive divisors, round towards negative infinity; for\nnegative divisors, round towards positive infinity.\n\n[2]: Here, `sign(a)` is 1 if `a >= 0` and is -1 if `a < 0`.\n\n### Use different precedence groups for division and multiplication\n\nUnder this proposal, division and multiplication are in the same precedence\ngroup, and are left-associative: `a * b / c * d` is `((a * b) / c) / d`, and not\n`(a * b) / (c * d)` or some other grouping.\n\nIt's not feasible to provide a different interpretation here due to the risk of\nconfusing developers migrating from other languages. However, we could reject\nsuch expressions and require explicit parentheses.\n\nWhile the value of accepting code such as this is relatively low, the fact that\nboth existing programming languages and common mathematical education treat\nmultiplication and division as the same, left-associative, precedence group\nmeans that it's unlikely to be a significant burden to expect Carbon developers\nto remember this precedence rule.\n\n### Use the same precedence group for modulo and multiplication\n\nIn most languages with the set of arithmetic operators discussed in this\nproposal, `%` is considered a multiplicative operator, and so a sequence of `*`,\n`/`, and `%` operators is processed left-to-right. In some sense this is\nreasonable: `%` is notionally performing a division, after all. Moreover, in a\ncode search, I was unable to find evidence that it's common for precedence\nerrors with `%` to be checked in to source control, and C++ compilers don't have\nwarnings for mixing `%` with `+` without parentheses.\n\nGiving `%` and `/` the same precedence also allows some kinds of code to be\nwritten symmetrically:\n\n```c++\nchar two_digit_number[] = {\n  '0' + m / 10,\n  '0' + m % 10,\n  0\n};\nchar four_digit_number[] = {\n  '0' + n / 1000,\n  '0' + n / 100 % 10,\n  '0' + n / 10 % 10,\n  '0' + n % 10,\n  0\n};\n```\n\nWith minimal parentheses, that example would be written as follows under this\nproposal:\n\n```carbon\nvar two_digit_number: Array(Char, 3) = (\n  '0' + m / 10,\n  '0' + (m % 10),\n  0\n);\nvar four_digit_number: Array(Char, 5) = (\n  '0' + n / 1000,\n  '0' + ((n / 100) % 10),\n  '0' + ((n / 10) % 10),\n  '0' + (n % 10),\n  0\n);\n```\n\nWe could use the same precedence rule as other languages, and permit examples\nsimilar to the above to be written without any parentheses.\n\nHowever, our [rule for precedence](p0555.md#when-to-add-precedence-edges) is:\n\n> For every combination of operators, either it should be reasonable to expect\n> most or all developers who regularly use Carbon to reliably remember the\n> precedence, or there should not be a precedence rule.\n\nIt is not clear that a precedence rule that gives a defined meaning to, for\nexample, `a + b % c + d` would satisfy this rule. Moreover, in mathematics, the\n\"mod\" operator generally binds very loosely: in 'n = m + 1 (mod 5)', the '(mod\n5)' applies to the entire equality, certainly not to the '1'.\n\nTherefore, we do not give modulo higher precedence than addition, and require\nparentheses when mixing the two. This decision should be revisited if it is a\nsignificant source of friction in practice.\n\n### Use a different spelling for modulo\n\nWe could use a different spelling for the modulo operation. For example, we\ncould spell it as `mod`.\n\nAdvantages:\n\n-   The percent sign has no relation to modulo or remainder. The only known\n    justification for this particular choice of symbol is that it resembles the\n    '÷' symbol; however, that symbol means division, not remainder.\n-   Would free up the `%` symbol for other uses that may be more prevalent than\n    modulo. However, we would need to be cautious when adding any alternative\n    uses to avoid confusion for people who expect `%` to mean modulo.\n\nDisadvantages:\n\n-   This would be unfamiliar to developers coming from C++ and other languages\n    with similar operator sets.\n-   There is no other common established symbol for this operation. Using a\n    keyword such as `mod` would break our loose convention of using keywords for\n    non-overloadable operators and operator symbols for overloadable operators.\n    Using a function would substantially increase the verbosity of certain kinds\n    of code.\n\n## Future work\n\n### Provide separate wrapping operators\n\nWe could provide distinct operators with wrapping semantics for types where\noverflow is normally a programming error. For example, Swift provides\n[overflow operators](https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37)\n`&+`, `&-`, and `&*` for this purpose.\n\nThis proposal takes no position on whether this would be useful. However, given\nthat in this proposal, unsigned types already have wrapping semantics, the\npressure to provide operators for signed types with those semantics is somewhat\nreduced.\n\n### Provide separate operations to detect overflow\n\nIt would be useful to provide a way to perform an arithmetic operation if\npossible, and to provide a separate codepath to handle the case where the\narithmetic would have overflowed. For example, we could imagine the Carbon\nstandard library providing a facility such as:\n\n```\nfn AddWithOverflow[N:! BigInt](a: Integer(N), b: Integer(N)) -> Optional(Integer(N));\n```\n\nWhile this would undoubtedly be useful, this proposal provides no facility for\nthis operation.\n"
  },
  {
    "path": "proposals/p1084.md",
    "content": "# Generics details 9: forward declarations\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1084)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [No `default` keyword on interface members](#no-default-keyword-on-interface-members)\n    -   [Declaring an implementation of an incomplete interface](#declaring-an-implementation-of-an-incomplete-interface)\n    -   [Allow definition of private interfaces in separate impl file](#allow-definition-of-private-interfaces-in-separate-impl-file)\n    -   [No implementations for incomplete types](#no-implementations-for-incomplete-types)\n    -   [No forward declaration of named constraints](#no-forward-declaration-of-named-constraints)\n    -   [Repeating `private` in both declaration and definition](#repeating-private-in-both-declaration-and-definition)\n    -   [Allow function bodies using incomplete interfaces](#allow-function-bodies-using-incomplete-interfaces)\n    -   [Don't require parameter names to match](#dont-require-parameter-names-to-match)\n    -   [Allow deduced parameters to vary](#allow-deduced-parameters-to-vary)\n\n<!-- tocstop -->\n\n## Problem\n\nDevelopers want to organize their code for readability and convenience. For\nexample, they may want to present the public API of their type in a concise way.\nThat includes the ability to say a type implements an interface without\nrepeating the full contents of that interface.\n\nThe Carbon compiler can give better diagnostics if it can assume every\nidentifier it encounters refers to some earlier declaration in the file.\nHowever, sometimes multiple entities will reference each other in a cycle so no\none entity can be defined first.\n\n## Background\n\nWe have decided to tackle these problems in a manner similar to C++ by\nsupporting forward declarations:\n\n-   [issue #472: Open question: Calling functions defined later in the same file](https://github.com/carbon-language/carbon-lang/issues/472)\n-   [proposal #875: Principle: information accumulation](https://github.com/carbon-language/carbon-lang/pull/875).\n\nUse of the `default` keyword in `interface` definitions to allow defaulted\nmembers to be defined out-of-line was originally proposed in\n[withdrawn proposal #1034](https://github.com/carbon-language/carbon-lang/pull/1034).\n\nThis proposal implements the decisions in\n[issue #1132: How do we match forward declarations with their definitions?](https://github.com/carbon-language/carbon-lang/issues/1132)\nas they apply to generic interfaces, implementations, and so on.\n\n## Proposal\n\nThis proposal makes changes to these sections of the\n[generics details design document](/docs/design/generics/details.md):\n\n-   [Forward declarations and cyclic references](/docs/design/generics/details.md#forward-declarations-and-cyclic-references)\n    section added\n-   [Interface members with definitions](/docs/design/generics/details.md#interface-members-with-definitions)\n    section added to\n\n## Rationale based on Carbon's goals\n\nForward declarations are intended to advance these goals:\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem),\n    by making Carbon easier to interpret by tooling in a single top-down pass.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\n    by allowing developers to separate declaration from definition when\n    organizing the presentation of their code, and imposing constraints that\n    allow readers to interpret the code with less skipping around.\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n    from potential build performance improvements that come from allowing an\n    `impl` to be defined in the `impl` file instead of the `api` file.\n\nThe rationale behind using forward declarations are covered in more detail in:\n\n-   [issue #472: Open question: Calling functions defined later in the same file](https://github.com/carbon-language/carbon-lang/issues/472)\n-   [proposal #875: Principle: information accumulation](https://github.com/carbon-language/carbon-lang/pull/875).\n\n## Alternatives considered\n\n### No `default` keyword on interface members\n\nWithout the `default` keyword, default definitions would always have to be\ninline. We discussed this in\n[the #syntax channel on Discord](https://discord.com/channels/655572317891461132/709488742942900284/941408009689641010)\nwhich eventually led to the\n[question-for-leads issue #1082: Use `default` keyword in interface defaults?](https://github.com/carbon-language/carbon-lang/issues/1082).\n\nThe conclusion was that we did want to support forward declarations of default\ninterface members. To make it so that users would have a single place to look to\nsee whether the member had a definition even when it might be out of line, we\ndecided to use a `default` keyword as a prefix of the declaration. We considered\nputting the keyword at the end of the declaration, but we decided it was more\nreadable if it wasn't next to the return type. It was also more consistent with\n`final`, an alternative to `default`, which also now supports forward\ndeclaration.\n\n### Declaring an implementation of an incomplete interface\n\nWe did not have any use cases for forward declaring an impl of an incomplete\ninterface, and so we took the conservative position of forbidding that. We could\nadd this feature in the future if use cases were found, but clearly we can't\nhave impl definitions until the interface is defined.\n\n### Allow definition of private interfaces in separate impl file\n\nThis proposal requires the definition of an interface to be in the same file as\nany declaration of it. We\n[anticipate](https://github.com/carbon-language/carbon-lang/pull/1084#discussion_r824214281)\nthe possibility that we will find a use case for declaring a private interface\nin an API file that is defined in the corresponding impl file. An example where\nthis may arise is if the constraint is only used when defining private members\nof an exported class. We would be willing to change if we see demand for this in\nthe future.\n\n### No implementations for incomplete types\n\nFor simplicity, generally Carbon entities should either be \"incomplete\" or\n\"defined\" and never \"partially defined\". However, the set of interfaces\nimplemented for a type is by necessity only ever partially known by the nature\nof being the\n[one static open extension mechanism](https://github.com/carbon-language/carbon-lang/pull/998)\nin Carbon. As a result, we felt there was more leeway for implementing\ninterfaces for incomplete types. This happens incidentally when implementing the\ninterface inline in the scope of a class definition. We also wanted to allow it\nin the case where there was only a forward declaration of the type in an API\nfile.\n\n### No forward declaration of named constraints\n\nWe considered omitting the ability to forward declare named constraints, but we\ndiscovered that ability made declaring interfaces with cyclic dependencies\neasier and cleaner. Without this feature,\n[the graph example of cyclic references](/docs/design/generics/details.md#example-of-declaring-interfaces-with-cyclic-references)\nlooked like this instead:\n\n```\n// Forward declaration of interface\ninterface EdgeInterface;\n\n// Definition that only uses the declaration of\n// `EdgeInterface`, not its definition.\ninterface NodeBootstrap {\n  let EdgeType:! EdgeInterface;\n  fn Edges[me: Self]() -> Vector(EdgeType);\n}\n\n// Now can define `EdgeInterface` in terms of\n// `NodeBootstrap`.\ninterface EdgeInterface {\n  let NodeType:! NodeBootstrap where .EdgeType == Self;\n  fn Head[me: Self]() -> NodeType;\n}\n\n// Make `NodeInterface` a named constraint defined in\n// terms of `NodeBootstrap`, adding in constraints that\n// couldn't be written until `EdgeInterface` was defined.\nconstraint NodeInterface {\n  extends NodeBootstrap where .EdgeType.NodeType == Self;\n}\n```\n\nWe did not like how the definition of `NodeInterface` was split into two pieces,\nmaking it harder to understand what it contained.\n\nThis question was discussed in\n[the #generics channel on Discord](https://discord.com/channels/655572317891461132/941071822756143115/951288264315265114).\n\n### Repeating `private` in both declaration and definition\n\nWe considered repeating the access-control keyword `private` as a prefix of all\n`impl` declarations and definitions. The\n[current rule](/docs/design/generics/details.md#declaring-interfaces-and-named-constraints)\nonly marks the first declaration or definition, which is consistent with\n[the policy of not repeating access-control keywords stated in an API file in an impl file](/docs/design/code_and_name_organization#exporting-entities-from-an-api-file).\n\nThis was discussed in\n[the #syntax channel on Discord](https://discord.com/channels/655572317891461132/709488742942900284/951520959544823868),\nbut this decision should be considered provisional since it was not considered\ndeeply. We would be open to revisiting this decision in the future, once we had\nsome experience with it.\n\n### Allow function bodies using incomplete interfaces\n\nWe\n[considered](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#heading=h.oqmpxtubjmkm)\nallowing a function definition to use an incomplete interface. One concern was\nwhether the criteria for when the function body depended on something in the\ninterface's definition would be too subtle for developers to reason about. We\neventually concluded that, unless using a monomorphization compilation strategy,\nefficient code generation for a generic function would need to use the\ninterface's definition. For example, an interface that represented a single\nfunction call might use a function pointer instead of a witness table. This same\nargument led to the requirement that the interface's definition be visible at\ncall sites as well.\n\n### Don't require parameter names to match\n\nWe decided to diverge from C++ in requiring parameter names to match between\ndeclarations for a few reasons:\n\n-   wanting to avoid the confusion that we've experienced when they don't match,\n    noting that common C++ lint tools ask to make them match;\n-   wanting reflection to return a single parameter name for a parameter; and\n-   wanting the parameter names to be consistent with the single docstring we\n    expect to associate with a function.\n\nThis was discussed in\n[open discussion on 2022-03-14](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#heading=h.oqmpxtubjmkm)\nand\n[question-for-leads issue #1132](https://github.com/carbon-language/carbon-lang/issues/1132).\n\n### Allow deduced parameters to vary\n\nWe decided to apply\n[the same matching requirements for other parameter names](#dont-require-parameter-names-to-match)\nto deduced parameters for consistency. We may in the future allow some rewrites\nbetween equivalent expressions, such as between `Vector(T:! Type)` and\n`[T:! Type] Vector(T)`, but for now we are starting with the more restrictive\nrule. This was discussed in\n[open discussion on 2022-03-24](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#heading=h.w4zgqvarhnbn)\nand in\n[#syntax channel on Discord](https://discord.com/channels/655572317891461132/709488742942900284/953798170750615622).\n"
  },
  {
    "path": "proposals/p1088.md",
    "content": "# Generic details 10: interface-implemented requirements\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1088)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Less strict about requirements with `where` clauses](#less-strict-about-requirements-with-where-clauses)\n    -   [Don't require `observe...is` declarations](#dont-require-observeis-declarations)\n\n<!-- tocstop -->\n\n## Problem\n\nThis proposal is to add the capability for an interface to require other types\nto be implemented, not just the `Self` type. The interface-implemented\nrequirement feature also has some concerns:\n\n-   If the interface requirement has a `where` clause, there are\n    [concerns](#less-strict-about-requirements-with-where-clauses) about being\n    able to locally check whether impls satisfy that requirement.\n-   A function trying to make use of the fact that a type implements an\n    interface due to an interface requirement, or a blanket impl, may require\n    the compiler perform a search that we don't know will be bounded.\n\n## Background\n\nThe first version of interface-implemented requirements for interfaces was\nintroduced in proposal\n[#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553).\n\n## Proposal\n\nThis proposal adds two sections to the\n[generics details design document](/docs/design/generics/details.md):\n\n-   [Interface requiring other interfaces revisited](/docs/design/generics/details.md#interface-requiring-other-interfaces-revisited)\n-   [Observing a type implements an interface](/docs/design/generics/details.md#observing-a-type-implements-an-interface)\n\n## Rationale based on Carbon's goals\n\nThis proposal advances these goals of Carbon:\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem):\n    The motivation for this expressive power of interface requirements comes\n    from discussions about how to achieve symmetric behavior with interfaces\n    like `CommonTypeWith` from\n    [proposal #911: Conditional expressions](https://github.com/carbon-language/carbon-lang/pull/911).\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development):\n    The requirement that the source provide the proof of any facts that would\n    require a recursive search using `observe` declarations means that the\n    expense of that search is avoided except in the case where there is a\n    compiler error. If the search is successful, the results of the search can\n    be copied into the source, and afterward the search need not be repeated.\n\n## Alternatives considered\n\n### Less strict about requirements with `where` clauses\n\nWe could allow\n[requirements with `where` constraints](/docs/design/generics/details.md#requirements-with-where-constraints)\nto be satisfied by implementations that could be specialized, as long as the\nconstraints were still satisfied. Unfortunately, this is not a condition that\ncan be checked locally. Continuing the example from that section, consider four\npackages\n\n-   A package defining the two interfaces\n\n    ```\n    package Interfaces api;\n    interface A(T:! Type) {\n      let Result:! Type;\n    }\n    interface B(T:! Type) {\n      impl as A(T) where .Result == i32;\n    }\n    ```\n\n-   A package defining a type that is used as a parameter to interfaces `A` and\n    `B` in blanket impls:\n\n    ```\n    package Param api;\n    import Interfaces;\n    class P {}\n    external impl [T:! Type] T as Interfaces.A(P) where .Result = i32 { }\n    // Question:Is this blanket impl of `Interfaces.A(P)` sufficient\n    // to allow us to make this blanket impl of `Interfaces.B(P)`?\n    external impl [T:! Type] T as Interfaces.B(P) { }\n    ```\n\n-   A package defining a type that implements the interface `A` with a wildcard\n    impl:\n\n    ```\n    package Class api;\n    import Interfaces;\n    class C {}\n    external impl [T:! Type] C as Interfaces.A(T) where .Result = bool { }\n    ```\n\n-   And a package that tries to use the above packages together:\n\n    ```\n    package Main;\n    import Interfaces;\n    import Param;\n    import Class;\n\n    fn F[V:! Interfaces.B(Param.P)](x: V);\n    fn Run() {\n      var c: Class.C = {};\n      // Does Class.C implement Interfaces.B(Param.P)?\n      F(c);\n    }\n    ```\n\nPackage `Param` has an implementation of `Interfaces.B(Param.P)` for any `T`,\nwhich should include `T == Class.C`. The requirement in `Interfaces.B` in this\ncase is that `T == Class.C` must implement `Interfaces.A(Param.P)`, which it\ndoes, and `Class.C.(Interfaces.A(Param.P).Result)` must be `i32`. This would\nhold using the blanket implementation defined in `Param`, but the wildcard impl\ndefined in package `Class` has higher priority and sets the associated type\n`.Result` to `bool` instead.\n\nThe conclusion is that this problem would only be detected during\nmonomorphization, and could cause independent libraries to be incompatible with\neach other even when they work separately. These were significant enough\ndownsides that we wanted to see if we could live with the restrictions that\nallowed local checking first. We don't know if developers will want to declare\ntheir parameterized implementations `final` in this situation anyway, even with\n[the limitations on `final`](/docs/design/generics/details.md#libraries-that-can-contain-a-final-impl).\n\nThis problem was discussed in\n[the #generics channel on Discord](https://discord.com/channels/655572317891461132/941071822756143115/941089885475962940).\n\n### Don't require `observe...is` declarations\n\nWe could require the Carbon compiler to do a search to discover all interfaces\nthat are transitively implied from knowing that a type implements a set of\ninterfaces. However, we don't have a good way of bounding the depth of that\nsearch.\n\nIn fact, this search combined with conditional conformance makes the question\n\"is this interface implemented for this type\" undecidable\n[in Rust](https://sdleffler.github.io/RustTypeSystemTuringComplete/). Note: it\nis possible that\n[the acyclic rule](/docs/design/generics/details.md#acyclic-rule) would avoid\nthis problem in Carbon for blanket impls, but it doesn't apply to interface\nrequirements.\n\nThis problem was observed in\n[a discussion in #typesystem on Discord](https://discord.com/channels/655572317891461132/708431657849585705/938167784565792848).\n"
  },
  {
    "path": "proposals/p1144.md",
    "content": "# Generic details 11: operator overloading\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1144)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Weak impls instead of adapters for reverse implementations](#weak-impls-instead-of-adapters-for-reverse-implementations)\n    -   [Default impls instead of adapters for reverse implementations](#default-impls-instead-of-adapters-for-reverse-implementations)\n    -   [Allow an impl declaration with `like` to match one without](#allow-an-impl-declaration-with-like-to-match-one-without)\n    -   [Where are the impl definitions from `like` generated?](#where-are-the-impl-definitions-from-like-generated)\n    -   [Support marking interfaces or their members as `external`](#support-marking-interfaces-or-their-members-as-external)\n\n<!-- tocstop -->\n\n## Problem\n\nC++ supports\n[operator overloading](https://en.wikipedia.org/wiki/Operator_overloading), and\nwe would like Carbon to as well. This proposal is about the general problem, not\nthe specifics application to any particular operator.\n\nThis proposal does not attempt to define a mechanism by which we can ensure that\n`a < b` has the same value as `b > a`.\n\n## Background\n\nThe generics feature is the\n[single static open extension mechanism](/docs/project/principles/static_open_extension.md)\nin Carbon, and so will be what we use operator overloading. We have already\nstarted specifying the ability to extend or customize the behavior of operators\nby implementing interfaces, as in these proposals:\n\n-   [#820: Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820)\n-   [#845: as expressions](https://github.com/carbon-language/carbon-lang/pull/845)\n-   [#911: Conditional expressions](https://github.com/carbon-language/carbon-lang/pull/911)\n-   [#1083: Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083)\n\nProposal\n[#702: Comparison operators](https://github.com/carbon-language/carbon-lang/pull/702)\nspecified\n[using interfaces for overloading the comparison operators](p0702.md#overloading),\nbut did not pin down specifically what those interfaces are.\n\n## Proposal\n\nThis proposal adds an\n[\"Operator overloading\" section](/docs/design/generics/details.md#operator-overloading)\nto the [detailed design of generics](/docs/design/generics/details.md).\n\n## Rationale based on Carbon's goals\n\nThis proposal advances Carbon's goals:\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\n    by making common constructs more concise, and allowing the syntax to more\n    closely mirror notation used math or the application domain.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution),\n    since this allows standard types to implement operators using the same\n    mechanisms that user types do, this allows changes between what is built-in\n    versus provided in a library without user-visible impact.\n\n## Alternatives considered\n\nThe current proposal requires the user to define a reverse implementation, and\nrecommends using an adapter to do that more conveniently. We also considered\napproaches that would provide the reverse implementation more automatically.\n\n### Weak impls instead of adapters for reverse implementations\n\nWe proposed\n[weak impls](https://github.com/carbon-language/carbon-lang/pull/1027) as a way\nof defining blanket impls for the reverse impl that did not introduce\n[cycles](/docs/design/generics/details.md#acyclic-rule). We rejected that\napproach due to giving the reverse implementation the wrong priority. This meant\nthat there were many situations where `a < b` and `b > a` would give different\nanswers.\n\n### Default impls instead of adapters for reverse implementations\n\nWe then proposed\n[default impls](https://github.com/carbon-language/carbon-lang/pull/1034) as a\nway to define reverse implementations. These were rejected because they had a\nlot of overlap with blanket impls, making it difficult to describe when to use\none over the other, and because they introduced a lot of complexity without\nfully solving the priority problem. Most of the complexity was from the criteria\nfor determining whether the default implementation would be used. As\n[noted](/docs/design/generics/details.md#binary-operators), the current proposal\nstill has some priority issues, but this way the relevant impls are visible in\nthe source which will hopefully make it clearer why it happens.\n\nThe capability provided by default impls -- the ability to conveniently give\nimplementations of other interfaces -- may prove useful enough that we would\nreconsider this decision in the future.\n\n### Allow an impl declaration with `like` to match one without\n\nWe considered allowing an impl declared with `like` to match the equivalent\nimpls without `like`. The main concern was there would not be a canonical form\nwithout `like`, particularly of how the newly introduced parameter would be\nwritten. We thought we might say that the `like` declaration, since it omits a\nspelling of the parameter, is allowed to match any spelling of the parameter.\nHowever, there would still be a question of whether to use a deduced parameter,\nas in `[T:! ImplicitAs(i64)] Vector(T)` or not as in\n`Vector(T:! ImplicitAs(i64))`. We also considered the canonical form of\n`Vector(_:! ImplicitAs(i64))` without naming the parameter. In the end, we\ndecided to start with a restrictive approach with the knowledge that we could\nchange once we gained experience.\n\nThe main use case for allowing declarations in a different form, which may\nmotivate changes in the future, is to prioritize the different implementations\ngenerated by the `like` shortcut separately in `match_first` blocks.\n\nThis was discussed in\n[open discussion on 2022-03-24](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#).\n\n### Where are the impl definitions from `like` generated?\n\nWe considered whether the additional impl definitions would be generated with\nthe first declaration of an impl using `like` or with its definition. We\nultimately decided on the former approach for two reasons:\n\n-   The generated impl definitions are parameterized even if the explicit\n    definition is not, and parameterized impl definitions may need to be in the\n    API file to allow separate compilation.\n-   This will make the code doing implicit conversions visible to callers,\n    allowing it to be inlined, matching how the caller does implicit conversions\n    for method calls.\n\nThis was discussed in\n[the #generics channel on Discord](https://discord.com/channels/655572317891461132/941071822756143115/962059164014739526).\n\n### Support marking interfaces or their members as `external`\n\nWe\n[discussed on 2022-03-28](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#heading=h.sk06n1ggoa3o)\nthe idea that operator interfaces might be marked `external`. This would either\nmean that types would only be able to implement them using `external impl` or\nthat even if they were implemented internally, they would not add the names of\nthe interface members to the type. Alternatively, individual members might be\nmarked `external` to indicate that their names are not added to implementing\ntypes, which might also be useful for making changes to an interface in a\ncompatible way.\n\nWe were not sure if this feature was needed, so we left this as future work.\n"
  },
  {
    "path": "proposals/p1146.md",
    "content": "# Generic details 12: parameterized types\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1146)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Problem\n\nMost aspects of generic parameterization are the same between functions and\ntypes, but there are a few things specific to types. In particular:\n\n-   the declaration of a type can contain a greater variety of members, and\n-   types have identity which affects type comparisons, deduced parameters, and\n    implied constraints.\n\nWe also want a\n[generic specialization](/docs/design/generics/terminology.md#checked-generic-specialization)\nstory that works well for types, without giving up the ability to type check\nusers of a type without knowing which specializations apply.\n\n## Background\n\nC++ supports specialization, including partial specialization, for templated\ntypes and functions.\n\n## Proposal\n\nThis proposal adds a\n[\"parameterized types\" section](/docs/design/generics/details.md#parameterized-types)\nto the [detailed design of generics](/docs/design/generics/details.md). Of note,\nit proposes not to support specialization of types or functions since those use\ncases can be handled by delegating to interfaces, which already support\nspecialization.\n\n## Rationale based on Carbon's goals\n\nSpecialization is important for allowing code to be generic without sacrificing\n[performance](/docs/project/goals.md#performance-critical-software). Since there\nis already a way to support specialization use cases without adding direct\nsupport for specializing types, this proposal follows the Carbon principle to\n[prefer providing only one way to do a given thing](/docs/project/principles/one_way.md).\nBy avoiding another way of customizing behavior for specific types, it makes\ninterfaces the\n[single static open extension mechanism](/docs/project/principles/static_open_extension.md).\nThis proposal maintains consistency between generic parameterization of types\nand functions, in support of\n[code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n\n## Alternatives considered\n\nWe considered supporting specialization for types directly. To support type\nchecking in a generic context, the API of the type needs to be defined\nindependent of which specialization is selected. This would have introduced\ncomplexity into the language:\n\n-   Would the API of the type be represented by an `interface`?\n-   Would the type's API be explicitly declared or inferred from the type\n    declaration by some process, at the risk of including details that are not\n    necessarily stable?\n-   How would public data members be handled, since interfaces (currently) don't\n    support them?\n-   How would we support non-monomorphizing generic strategies? With the current\n    proposal, the layout of a parameterized type is known unless it uses an\n    associated type.\n\nThe main disadvantage of the proposed approach is that the author of the type\nneeds to define the ways that the type can be customized. We will need to see if\nthis ends up being a problem in practice. It may turn out to be a benefit, by\ngiving more information about the implementation of a class to readers.\n"
  },
  {
    "path": "proposals/p1154.md",
    "content": "# Destructors\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1154)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Types implement destructor interface](#types-implement-destructor-interface)\n    -   [Prevent virtual function calls in destructors](#prevent-virtual-function-calls-in-destructors)\n    -   [Allow functions to act as destructors](#allow-functions-to-act-as-destructors)\n    -   [Allow private destructors](#allow-private-destructors)\n    -   [Allow multiple conditional destructors](#allow-multiple-conditional-destructors)\n        -   [Allow direct implementation of `TrivialDestructor`](#allow-direct-implementation-of-trivialdestructor)\n    -   [Type-of-type naming](#type-of-type-naming)\n    -   [Other approaches to extensible classes without vtables](#other-approaches-to-extensible-classes-without-vtables)\n        -   [Don't distinguish safe and unsafe delete operations](#dont-distinguish-safe-and-unsafe-delete-operations)\n        -   [Don't allow unsafe delete](#dont-allow-unsafe-delete)\n        -   [Allow final destructors](#allow-final-destructors)\n\n<!-- tocstop -->\n\n## Problem\n\nC++ code supports defining custom\n[destructors](<https://en.wikipedia.org/wiki/Destructor_(computer_programming)>)\nfor user-defined types, and C++ developers will expect to use that tool. Carbon\nshould support destructors, but should make some changes to protect against\ndeleting a value with a derived type through a pointer to the base class when\nthe base class destructor is not virtual. We also need some mechanism to allow\ngeneric code to identify types that are safe to destroy, or have trivial\ndestructors and don't need to be explicitly destroyed.\n\n## Background\n\nDestructors may only be customized for nominal classes, which were introduced in\nproposal [#722](https://github.com/carbon-language/carbon-lang/pull/722).\nDestructors interact with inheritance, which was introduced in proposal\n[#777](https://github.com/carbon-language/carbon-lang/pull/777).\n\nDestructors were discussed in open discussion on these dates:\n\n-   [2021-07-12](https://docs.google.com/document/d/14vAcURDKeH6LZ_TQCMRGpNJrXSZCACQqDy29YH19XGo/edit#heading=h.40jlsrcgp8mr)\n-   [2021-08-30](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.4dobu6v1cdam)\n-   [2021-10-04](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.a0rffns9r10n)\n    discussed not all types being destructible, and that some types are\n    `TriviallyDestructible`\n-   [2021-10-18](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.uz59mgk5ezch)\n-   [2022-03-24](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#heading=h.cy8m79pgct1v)\n\nAs part of\n[proposal 777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777),\nwe decided to support extensible classes, that is non-abstract base classes,\n[including with non-virtual destructors](p0777.md#no-extensible-objects-with-non-virtual-destructors).\n[\"Extensible classes\" Google doc](https://docs.google.com/document/d/1gbQJN_IMJBnquOUUd2orbHLlAIqZ4pL0Vt7h34DkQjg/edit?resourcekey=0-0lkEvh0umUU206ASFlWc7A#)\nfrom that time considered options for making deleting extensible classes safer.\n\n## Proposal\n\nThis proposal adds two sections to the design:\n\n-   [\"Destructors\"](/docs/design/classes.md#destructors) to the\n    [classes design](/docs/design/classes.md), and\n-   [\"Destructor constraint\"](/docs/design/generics/details.md#destructor-constraints)\n    to the [detailed generics design](/docs/design/generics/details.md).\n\n## Rationale based on Carbon's goals\n\nDestructors advance these goals:\n\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms),\n    since destructors are about making sure clean-up actions are performed by\n    doing them automatically, which is helpful for avoiding safety-related bugs.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code),\n    since destructors are relied upon in C++.\n\n## Alternatives considered\n\n### Types implement destructor interface\n\nWe considered letting developers implement a destructor interface, as is done in\n[Rust](https://doc.rust-lang.org/std/ops/trait.Drop.html). This would be more\nconsistent with the other customization points for classes, but had some\ndownsides that we ultimately decided were too large:\n\n-   Destructors are relatively common, and implementing an interface involves\n    more boilerplate than writing a destructor in C++, so we wanted a concise\n    syntax.\n-   Destructors need access to the private members of a class, so generally\n    would have to be part of the class.\n-   We didn't have any use cases where an author of a type used as a type\n    argument to a class should be able to override the destructor for the class,\n    so users would have to mark destructors as `final` or risk surprises.\n-   Abstract classes without virtual destructors may have code that should run\n    when the type is destroyed, but don't implement any destructor\n    type-of-types.\n-   More generally, we wanted the compiler to enforce that the correct\n    type-of-types were implemented.\n\nThis was considered in the open discussions on\n[2021-08-30](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.4dobu6v1cdam)\nand\n[2021-10-18](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.uz59mgk5ezch).\nWe decided to go with the proposed approach in\n[the open discussion on 2022-03-24](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#heading=h.cy8m79pgct1v).\n\n### Prevent virtual function calls in destructors\n\nWe considered disallowing virtual calls to be made while executing the\ndestructor. This would avoid having to assign to the vtable pointer between each\nlevel of the class hierarchy's destructor calls. This seemed like an avoidable\nexpense since you can't call a derived method implementation from a destructor\nanyway.\n\nWe observed that this assignment, which happens in C++, is unsynchronized and\ncould cause race conditions when there was synchronization inside a destructor.\nIn Carbon, we expect to mitigate that somewhat by doing the assignment at the\nend of the destructor instead of the beginning, which is safe since we won't\nhave multiple inheritance. This means that at least the most derived class'\ndestructor can acquire locks before any unsynchronized writes occur.\n\nWe didn't decide to include this approach in this proposal, since we felt like\nit would likely be too burdensome to prevent calling member functions from a\ndestructor unless the developer did some extra work to mark all functions it\ntransitively calls. We would consider this as a potential future extension. As\nnoted in the design, this could be achieved by using the `partial` type.\n\nThis was considered in the open discussions on\n[2021-08-30](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.4dobu6v1cdam)\nand\n[2021-10-18](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.uz59mgk5ezch).\n\n### Allow functions to act as destructors\n\n[We considered, on 2021-08-30](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.4dobu6v1cdam),\nhow we might support returning a value, for example a failure, from a\ndestructor. This would require that the destructor be called explicitly, rather\nthan implicitly as part of a `Allocator.Delete()` call or a variable leaving\nscope. This led to a design where you could have \"named destructors\" that were\nordinary methods except that they consumed their `me` parameter, as is possible\nin Rust. As a result, the `me` parameter would be marked with a keyword like\n`destroy` or `consume`, like:\n\n```\nclass MyClass {\n  fn MyDestroyer[destroy me: Self](x: i32) -> bool;\n}\n```\n\nWe would need some way to make the ending of the lifetime visible in the caller,\nperhaps:\n\n```\nvar c: MyClass = ...;\n// `~c` indicates lifetime of `c` is ending.\nvar b: bool = (~c).MyDestroyer(3);\n```\n\nThere were questions about how this would interact with unformed state.\n\nWe decided to keep this idea in mind, but there is not a pressing need for this\nfeature now since this doesn't mirror a capability of C++. We might reconsider\nas part of error handling strategy, or a desire to model resources that can be\nconsumed.\n\n### Allow private destructors\n\nC++ allows destructors to be marked `private`, which has some use cases such as\ncontrolling deletes of a reference-counted value. This introduces\n[context-sensitivity](/docs/project/principles/low_context_sensitivity.md). It\nis particularly concerning if whether a type implements a constraint depends on\nwhich function is the enclosing scope.\n\nThis was considered in the\n[open discussion on 2021-08-30](https://docs.google.com/document/d/1YhwNKLxQsWf8NPVaRm9PvgPmSM3PIK_KlD1gpNuUfwY/edit#heading=h.4dobu6v1cdam).\n\n### Allow multiple conditional destructors\n\nA parameterized type might want to specialize a destructor based on properties\nof the parameter. For example, it might do something more efficient if its\nparameter is a `TriviallyDestructible` type. An approach consistent with\n[conditional methods](/docs/design/generics/details.md#conditional-methods) and\nthe [prioritization rule](/docs/design/generics/details.md#prioritization-rule)\nwould be to write something like:\n\n```\nclass Vector(T:! Movable) {\n  // Prioritize using `match_first`\n  match_first {\n    // Express conditions by using a\n    // specific `Self` type.\n    destructor [U:! TriviallyDestructible,\n                me: Vector(U)];\n    // If first doesn't apply:\n    destructor [me: Self];\n  }\n}\n```\n\n#### Allow direct implementation of `TrivialDestructor`\n\nFor the specific case where the developer wants to specialize the destructor to\nbe trivial under certain circumstances, we could allow the developer to directly\nimplement `TrivialDestructor`. That implementation would include the criteria\nwhen the trivial destructor should be used. For example, we might express that\n`Optional` has a trivial destructor when its argument does by writing:\n\n```\nclass Optional(T:! Concrete) {\n  var value: Storage(T);\n  var holds_value: bool;\n\n  // It's perfectly safe, I assure you\n  impl [U:! TrivialDestructor] Optional(U) as TrivialDestructor {}\n\n  destructor [me: Self] { if (me.holds_value) value.Destroy(); }\n}\n```\n\n### Type-of-type naming\n\nWe considered other names for the type-of-types introduced in this proposal.\n\nThe name `Deletable` is inconsistent with\n[the decision on #1058](https://github.com/carbon-language/carbon-lang/issues/1058),\nso we considered alternatives like `Delete`, `CanDelete`, `DeleteInterface`,\n`DeleteConstraint`, or `SafeToDelete`. We agreed that it should match whatever\nterm was used in the allocation interface, and finalizing that was out of scope\nfor this proposal. So we left it at `Deletable` for now, with the understanding\nthat this was only a placeholder and not the final name.\n\nInstead of `Destructible`, which is inconsistent with\n[the decision on #1058](https://github.com/carbon-language/carbon-lang/issues/1058),\nwe considered:\n\n-   `DestructorConstraint`: a bit too long\n-   `HasDestructor`: means something slightly different\n-   `CanDestroy`: also inconsistent with\n    [the decision on #1058](https://github.com/carbon-language/carbon-lang/issues/1058)\n\nWe ultimately decided that the best name is likely `Unsafe` followed by the name\nwe chose in place of `Deletable`, and would wait until that is decided.\n\nOriginally `TrivialDestructor` was spelled `TriviallyDestructible`, but the word\n\"destructor\" was more aligned with the `destructor` keyword being used in\ndeclarations. We also considered replacing \"trivial\" with something like \"no-op\"\nor \"empty\" to emphasize that the destructor does literally nothing and can be\ncompletely omitted, but decided to stay consistent with C++ for now.\n\nInstead of `Concrete`, we also considered `Instantiable`, but this choice is\nboth more concise and more clearly the opposite of \"abstract.\"\n\n### Other approaches to extensible classes without vtables\n\nThere were a few alternatives we considered that were specifically concerned\nabout how to handle the unsafe case of deleting a pointer to a base class that\ndoes not have a virtual destructor, but may be pointing to a derived value. We\n[decided to allow this case](p0777.md#no-extensible-objects-with-non-virtual-destructors)\nas part of\n[proposal 777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777).\nWe decided to go with the proposed approach in\n[the open discussion on 2022-03-24](https://docs.google.com/document/d/1UelNaT_j61G8rYp6qQZ-biRddTuGcxJtqXxrVbjB9rA/edit#heading=h.cy8m79pgct1v).\n\n#### Don't distinguish safe and unsafe delete operations\n\nWe could, like C++, have a single operation that includes both the safe and\nunsafe cases. We decided we would like to try the safer option to see if it is\nviable or if it causes problems with interoperation with C++. We expect that\nmigrated C++ code can fall-back to using `UnsafeDelete` if using `Delete` is too\nburdensome.\n\nThis option was considered in the\n[\"Option: C++ DWIM model\" section of \"Extensible classes\" doc](https://docs.google.com/document/d/1gbQJN_IMJBnquOUUd2orbHLlAIqZ4pL0Vt7h34DkQjg/edit?resourcekey=0-0lkEvh0umUU206ASFlWc7A#heading=h.d2ybn2szry11).\n\n#### Don't allow unsafe delete\n\nFor even more safety, we considered preventing deletion of extensible classes\nwithout virtual destructors entirely. However, extensible classes without\nvirtual destructors were not that rare in C++ code we examined. It did not seem\nlikely this would provide enough C++ interop, and there were concerns that C++\ndevelopers would generally want to have an escape hatch for performing\noperations that they could prove to themselves were safe even if the compiler\ncould not.\n\nThis option was considered in the\n[\"Option: Like C++ but forbid unsafe\" section of \"Extensible classes\" doc](https://docs.google.com/document/d/1gbQJN_IMJBnquOUUd2orbHLlAIqZ4pL0Vt7h34DkQjg/edit?resourcekey=0-0lkEvh0umUU206ASFlWc7A#heading=h.718ogac3yb9l).\n\n#### Allow final destructors\n\nOne option we\n[considered early on](https://docs.google.com/document/d/14vAcURDKeH6LZ_TQCMRGpNJrXSZCACQqDy29YH19XGo/edit#heading=h.40jlsrcgp8mr)\nfor extensible classes with non-virtual destructors, was to require the same\nthing we do from non-virtual methods. That is, require that the implementation\nin the base class is appropriate for derived classes. We ultimately decided on a\ndifferent approach, but we could still provide that as an option. You would\ndeclare the destructor as `final`, and that would impose the necessary\nrestrictions on any derived class:\n\n-   No custom destructor code.\n-   Either no added data members, or, if we are willing to support unsized\n    deletes, no added data members with non-trivial destructors.\n\nBase classes with `final` destructors would be `Deletable`, like base classes\nwith `virtual` destructors. This would be a safe option without the overhead of\nincluding a vtable in your object, but fairly restrictive in its applicability.\n\n[We decided](https://discord.com/channels/655572317891461132/708431657849585705/958595054707023964)\nis viable but not pressing since this isn't a feature present in C++, and we\nwould wait and see if this would fill a common need.\n"
  },
  {
    "path": "proposals/p1178.md",
    "content": "# Rework operator interfaces\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1178)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use `ComparableWith` instead of `OrderedWith`](#use-comparablewith-instead-of-orderedwith)\n\n<!-- tocstop -->\n\n## Problem\n\nOur operator interface names need to be updated to match the decision in\n[#1058](https://github.com/carbon-language/carbon-lang/issues/1058). Further, we\nare missing a description of the interfaces used to overload comparison\noperators, and the rules are not up to date with the decision in\n[#710](https://github.com/carbon-language/carbon-lang/issues/710).\n\n## Background\n\nSee the two leads issues for background and discussion of options.\n\n## Proposal\n\nSee changes to the design.\n\n## Details\n\nBeyond establishing names for interfaces, this proposal also establishes:\n\n-   We will have high-level interfaces for equality and relational comparison.\n    The equality interface provides both `==` and `!=`. The relational\n    comparison interface provides all of `<`, `<=`, `>`, and `>=`.\n-   Following the convention established for arithmetic operators, we provide\n    both a heterogeneous comparison interface and a homogeneous constraint. For\n    example, `T is EqWith(T)` is equivalent to `T is Eq`.\n-   The high-level interfaces always return `bool`.\n-   The high-level interfaces have expected semantics associated with them.\n\nIt is intended that we also provide low-level interfaces, to directly control\nindividual operators and to allow a result type other than `bool`. These are not\nincluded in this proposal, as it's not yet clear how they should be specified,\nand it's more important to get the high-level interfaces decided at this point.\n\n## Rationale\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   High-level semantics allow tools to reason about the intended meaning of\n        Carbon code. For example, a tool could statically or dynamically\n        determine that an implementation of `Ordered` doesn't satisfy the\n        expected rules and produce a warning.\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software)\n    -   We expect `==` and ordering to be customized separately, in order to\n        avoid cases where a suboptimal `==` is constructed in terms of an\n        ordering. See\n        [C++ committee paper P1190R0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1190r0.html)\n        for details on the problem.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Combining all comparison operators of the same kind -- equality or\n        relational -- into a single interface makes it both easier to implement\n        them and easier to write a generic constraint for them. This approach is\n        also expected to be easy to teach, with the low-level interfaces only\n        explained to a more advanced audience.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   While there are rules for the comparison interfaces, violating those\n        rules does not result in immediate unbounded undefined behavior.\n        However, implementations should still attempt to detect violations of\n        these rules and report them where that is feasible.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   The intent to provide a low-level interface for individual operators is\n        directly motivated by the desire to provide strong interoperability with\n        operators defined in C++. While this functionality is not part of this\n        proposal, it's expected to follow once the interactions with generics\n        are worked out.\n\n## Alternatives considered\n\n### Use `ComparableWith` instead of `OrderedWith`\n\nWe could use the term \"comparable\" for relational comparisons instead of\n\"ordered\". There is existing practice for both: for example, Rust and Haskell\nuse `Ord`, and Swift uses `Comparable`.\n\nThe main argument for using \"ordered\" instead of \"comparable\" is that `==` and\n`!=` are also a form of comparison but aren't part of `OrderedWith`, and the\nword \"ordered\" distinguishes relational comparison from equality comparison.\n"
  },
  {
    "path": "proposals/p1190.md",
    "content": "# Reviewer-merged PRs\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1190)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Never merge PRs from developers with merge access](#never-merge-prs-from-developers-with-merge-access)\n    -   [Grant all potential contributors merge access](#grant-all-potential-contributors-merge-access)\n    -   [Allow reviewers to clean up pull request descriptions](#allow-reviewers-to-clean-up-pull-request-descriptions)\n    -   [Only have authors resolve merge conflicts](#only-have-authors-resolve-merge-conflicts)\n    -   [Implement a two-person rule for source code changes](#implement-a-two-person-rule-for-source-code-changes)\n\n<!-- tocstop -->\n\n## Problem\n\nWe've been having authors merged PRs, but that's not going to work when we get\ncontributors who don't have merge access. We need a solution.\n\n## Background\n\nIt's been mentioned that LLVM favors having authors merge due to the risks of\nbreaking build bots. The LLVM community's leaning is to favor author merges so\nthat the author can decide whether to try rolling back or fixing forward.\n\nAt present Carbon has essentially been using a\n[shared repository model](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/about-collaborative-development-models#shared-repository-model)\nwhere authors merge their own PRs, but that's difficult to extend to a fully\npublic setup. The\n[fork and pull model](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/about-collaborative-development-models#fork-and-pull-model)\nis the other main git collaboration model, and is popular with open source\nprojects.\n\n## Proposal\n\nEncourage reviewers to merge when they feel okay doing so. Let reviewers make\nthat choice. Let authors say they'll merge themselves.\n\nThis is a\n[fork and pull model](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/about-collaborative-development-models#fork-and-pull-model)\nwhich encourages reviewer merges.\n\n## Details\n\nSee changes to [code review](/docs/project/code_review.md).\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   Defines a process for accepting contributions from developers who don't\n        have merge access.\n\n## Alternatives considered\n\n### Never merge PRs from developers with merge access\n\nWe could tell reviewers to never merge PRs from developers with merge access.\nThis is also a\n[fork and pull model](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/about-collaborative-development-models#fork-and-pull-model),\nbut minimizing reviewer merges.\n\nAdvantages:\n\n-   While this proposal suggest authors could opt out from having the reviewer\n    merge, minimizing reviewer merges avoids a gray area when an author forgets\n    or the reviewer misses it (even if enforced, the author might do it wrong).\n\nDisadvantages:\n\n-   Relies on the reviewer figuring out whether the author has merge access,\n    which they may forget to do. The most likely consequence is that outside\n    contributors will need to ping to get PRs merged.\n-   Makes reviewer merges less common. This in turn can make them less\n    consistently done well due to unfamiliarity.\n    -   Contributors without merge access would be following a different\n        process, and as a consequence it increases the chance that a new\n        contributor would be first to discover a problem, which in turn can\n        discourage contributions.\n\nIn the future, build bots may cause more issues, and we may lean more in this\ndirection. It could also be that we end up here through standard practice of\ncoordinating with the reviewer is concerned the author may need to fix a break\npost-commit. However, it doesn't seem necessary to make it a hard rule at\npresent.\n\n### Grant all potential contributors merge access\n\nWe could grant the public merge access; in other words, continue with a\n[shared repository model](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/about-collaborative-development-models#shared-repository-model),\nbut fully public instead of private. This way, reviewers would not need to\nconsider access.\n\nAdvantages:\n\n-   Authors can always merge, removing the burden on reviewers.\n\nDisadvantages:\n\n-   Relies on approvals heavily for code security, which constrains decisions\n    [regarding whether to keep CODEOWNERS](https://github.com/carbon-language/carbon-lang/issues/413).\n-   This kind of setup is likely atypical for GitHub projects, and so may be\n    more surprising than alternatives.\n-   Harder for reviewers to discern between frequent contributors and new\n    contributors.\n    -   GitHub has an option,\n        [\"Dismiss stale pull request approvals when new commits\"](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule):\n        we would likely want to enable it to reduce the weight on reviewers,\n        although it means reviewers would need to approve again for any change\n        (likely including merge commits).\n-   May create issues when a novice contributor breaks something.\n    -   There must not be an expectation that novice contributors should\n        understand processes, unless demonstrating an understanding becomes a\n        prerequisite for review.\n\n### Allow reviewers to clean up pull request descriptions\n\nWe could allow reviewers to clean up pull request descriptions, rather than\nasking the author to.\n\nAdvantages:\n\n-   Decreases the number of review round-trips.\n\nDisadvantages:\n\n-   May lead to PR descriptions not being in the authors voice, frustrating\n    authors.\n\nThe preference is to let authors control pull request descriptions.\n\n### Only have authors resolve merge conflicts\n\nWe could only have authors resolve merge conflicts, instead of having reviewers\ndo it.\n\nAdvantages:\n\n-   Lowers the chance of an incorrect merge, because authors are likely to\n    better understand the conflict.\n-   Lets ambiguous resolves be handled with the author's voice.\n    -   If a bad resolve introduces a bug, it's the author's fault, rather than\n        being the reviewer's fault but _attributed_ to the author.\n\nDisadvantages:\n\n-   Increases the number of review round-trips.\n    -   Pull requests by authors lacking merge access would have an extra\n        round-trip, because the author would resolve conflicts then the reviewer\n        would merge the pull request. In a worst case this may bounce back and\n        forth due to new conflicts being added before the reviewer merged.\n\nThe preference is to minimize review round-trips. However, this could still be a\nreal-world outcome if reviewers generally only merge when there are no\noutstanding merge conflicts.\n\n### Implement a two-person rule for source code changes\n\nWe could implement a\n[two-person rule](https://en.wikipedia.org/wiki/Two-man_rule) for source code\nchanges, where both an author _and_ reviewer must see the merged code. GitHub\nsupports this with\n[\"Dismiss stale pull request approvals when new commits are pushed\"](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule),\nalthough we may also need to require 2 approvers per pull request.\n\nAdvantages:\n\n-   Gives stronger code security, eliminating situations where either the author\n    or reviewer could merge unreviewed changes.\n\nDisadvantages:\n\n-   Increases the number of review round-trips.\n    -   Right now, reviewers can approve with minor comments (\"fix typo\").\n        Fixing those would require a new commit, which in turn would require\n        fresh approval.\n    -   Truly preventing this issue may require setting 2 approvers per pull\n        request, so that a reviewer couldn't push a commit to the pull request\n        then approve and merge. Requiring 2 approvers also increases review\n        overhead.\n\nThe preference is to minimize review round-trips.\n"
  },
  {
    "path": "proposals/p1191.md",
    "content": "# Bitwise and shift operators\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1191)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Overflow in shift operators](#overflow-in-shift-operators)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use different symbols for bitwise operators](#use-different-symbols-for-bitwise-operators)\n        -   [Use a multi-character spelling](#use-a-multi-character-spelling)\n        -   [Don't provide an xor operator](#dont-provide-an-xor-operator)\n        -   [Use `~`, or some other symbol, for complement](#use--or-some-other-symbol-for-complement)\n    -   [Provide different operators for arithmetic and logical shifts](#provide-different-operators-for-arithmetic-and-logical-shifts)\n    -   [Provide rotate operators](#provide-rotate-operators)\n    -   [Guarantee behavior of large shifts](#guarantee-behavior-of-large-shifts)\n    -   [Support shifting a constant by a variable](#support-shifting-a-constant-by-a-variable)\n    -   [Converting complements to unsigned types](#converting-complements-to-unsigned-types)\n\n<!-- tocstop -->\n\n## Problem\n\nCarbon needs operations for working with bit representations of values.\n\n## Background\n\nC++ provides four bitwise operations for Boolean algebra: complement (`~`), and\n(`&`), or (`|`), and xor (`^`). These are all useful in bit-manipulation code\n(although `^` is used substantially less than the others). In addition, C++\nprovides two bit-shift operators `<<` and `>>` that can perform three different\noperations: left shift, arithmetic right shift, and logical right shift. The\nmeaning of `>>` is determined by the signedness of the first operand.\n\nC and Swift use the same set of operators as C++. Rust uses most of the same\noperators, but uses `!` instead of `~` for complement, unifying it with the\nlogical not operator, which is spelled `not` in Carbon and as `!` in Rust and\nC++. Go uses most of the same operators as C++, but uses unary prefix `^`\ninstead of `~` for complement, mirroring binary `^` for xor.\n\nIn addition to the operators provided by C and C++, bit-rotate operators are\npresent in some languages, and a short notation for them may be convenient.\nFinally, there are other non-degenerate binary Boolean operations with no common\noperator symbol:\n\n-   The \"implies\" operator (equivalent to `~a | b`).\n-   The \"implied by\" operator (equivalent to `a | ~b`).\n-   The complement of each of the other operators (NAND, NOR, XNOR, \"does not\n    imply\", \"is not implied by\").\n\n### Overflow in shift operators\n\nThe behavior of shift operators in C++ had a turbulent past. The behavior of\nshift operators has always been undefined if the right operand is out of range\n-- not between zero inclusive and the bit-width of the left operator exclusive\n-- but other restrictions have varied:\n\n-   Unsigned left shift has never had any restrictions on the first operand.\n-   For signed left shift:\n    -   In C++98, the result was fully unspecified.\n    -   In C++11, the result was specified only if the first operand was\n        non-negative and the result fit into the destination type -- that is, if\n        no 1 bit is shifted into the sign bit.\n    -   In C++14, the result was specified only if the first operand was\n        non-negative and the result fit into the unsigned type corresponding to\n        the destination type -- that is, if no 1 bit is shifted out of the sign\n        bit.\n    -   In C++20 onwards, there are no restrictions beyond a range restriction\n        on the right operand, and the result is otherwise always specified, even\n        if the left operand is negative.\n-   Unsigned right shift has never had any restrictions on the first operand.\n-   For signed right shift:\n    -   In C++17 and earlier, if the left operand is negative, the result is\n        implementation-defined.\n    -   In C++20 onwards, the result is always specified, even if the left\n        operand is negative.\n\nThere is a clear trend towards defining more cases, following two's complement\nrules.\n\n## Proposal\n\nUse the same operator set as C++, but replace `~` with unary prefix `^`.\n\nDefine the behavior for all cases of `<<` and `>>` except where the right\noperand is either negative or is greater than or equal to the bit-width of the\nleft operand.\n\n## Details\n\nSee changes to the design, and in particular\n[the new section on bitwise and shift operators](/docs/design/expressions/bitwise.md).\n\n## Rationale\n\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software)\n    -   Bit operations are important low-level primitives. Providing operators\n        for them is important in order to allow low-level high-performance code\n        to be written elegantly in Carbon.\n    -   By not defining semantics for `<<` and `>>` when the right-hand operand\n        is out of range, we can directly use hardware instructions for these\n        operations whose behavior in these cases vary between architectures.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Using operator notation rather than function call notation for bitwise\n        operators improves readability in code making heavy use of these\n        operations.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   Carbon follows C++ in treating `<<` and `>>` as programming errors when\n        the right hand operand is out of range, but Carbon guarantees that such\n        errors will not directly result in unbounded misbehavior in hardened\n        builds.\n-   [Modern OS platforms, hardware architectures, and environments](/docs/project/goals.md#modern-os-platforms-hardware-architectures-and-environments)\n    -   All hardware architectures we care to support are natively two's\n        complement architectures, and that assumption allows us to define the\n        semantics of shift operators in the way that makes the most sense for\n        such architectures.\n    -   Our bitwise operations make no assumptions about the endianness of the\n        hardware architecture, although the shift operators make the most sense\n        on a little-endian or big-endian architecture, which are the only\n        endiannesses we expect to see in modern hardware platforms.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   The same set of operators is provided as in C++, making it easy for\n        programmers and programs to migrate, with the exception that the `~`\n        operator is mechanically replaced with `^`. This change is expected to\n        be easy for programmers to accommodate, especially given that Rust's\n        choice to replace `~` with `!` does not seem to be a source of sustained\n        complaints.\n    -   The extensibility support reflects the full scope of operator\n        overloading in C++, permitting separate overloading of each of the\n        bitwise operators with custom return types. This should allow smooth\n        interoperability with C++ overloaded operators.\n\n## Alternatives considered\n\n### Use different symbols for bitwise operators\n\nThe operator syntax for bitwise operators was decided in\n[#545](https://github.com/carbon-language/carbon-lang/issues/545). Some of the\nspecific alternatives considered are discussed below.\n\n#### Use a multi-character spelling\n\nWe considered using various multi-character spellings for the bitwise and, or,\nxor, and complement operators:\n\n-   `&:`, `|:`, `^:`, `~:`\n-   `.&.`, `.|.`, `.^.`, `.~.`\n-   `.*.`, `.+.`, `.!=.`, `.!.`\n-   `/\\`, `\\/`, `(+)`, `-|`\n-   `bitand`, `bitor`, `bitxor`, `compl`\n\nThe advantage of switching to such a set of operators is that this would free up\nthe single-character `&`, `|`, `^`, and `~` tokens for other uses that may occur\nmore frequently in Carbon programs. We have some candidate uses for these\noperators already:\n\n-   `&` is used for combining interfaces and as a unary address-of operator.\n-   `|` may be useful for sum types, for alternatives in patterns, or as another\n    kind of bracket as in\n    [Ruby's lambda notation](https://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html#iter).\n-   `~` may be useful as a destructive move notation.\n-   `^` may be useful as a postfix pointer dereference operator.\n\nOther motivations for switching to a different set of spellings include:\n\n-   There are some concerns that `<` and `<<` are visually similar, analogous to\n    `&` and `&&`.\n-   Carbon has moved away from `&&` and other punctuation based _logical_\n    operators and towards keywords like `and`. Bitwise operators could similarly\n    switch to keywords like `bitand`.\n\nHowever, moving substantially away from the C++ operator set comes with a set of\nconcerns:\n\n-   There are strong established expectations and intuitions about these\n    operators and their spellings among C++ practitioners.\n-   In some of the code that uses these operators, they are used a lot, and a\n    more cumbersome operator may consequently cause an outsized detriment on\n    readability.\n-   These operations are used particularly in the area of low-level,\n    high-performance code, which is an area for which we want Carbon to be\n    especially appealing. Using short operators for these operations\n    demonstrates our commitment to providing good support for such code.\n-   Even if we didn't use these operators as bit operators, we would still want\n    to exercise caution when using them for some other purpose to avoid\n    surprising C++ developers.\n-   While some visual similarity exists such as between `<` and `<<`, the\n    contexts in which these operators are used are sufficiently different to\n    avoid any serious concerns.\n-   The primary motivation of using `and` instead of `&&` doesn't apply for\n    bitwise operators: the _logical_ operator represents _control flow_.\n    Separating logical and bitwise \"and\" operations more visibly seems\n    especially important because of this control flow semantic difference.\n    Without any control flow and with the keywords being significantly longer\n    for bitwise operations, the above considerations were the dominant ones that\n    led us to stick with familiar `&` and `|` spellings.\n\n#### Don't provide an xor operator\n\nWe considered omitting the `^` operator, providing this functionality in some\nother way, such as a named function or an `xor` keyword, while keeping the `&`\nand `|` symbols for bitwise operations. We could take a similar approach for the\ncomplement operation, such as by using a `compl` keyword. The primary motivation\nwas to avoid spending two precious operator characters on relatively uncommon\noperations. However, we did not want to apply the same change to `&` and `|`,\nand it seemed important to maintain consistency between the three binary bitwise\noperators from C++.\n\nUsing `^` for both operations provides some of the benefits here, allowing us to\nreclaim `~`, without introducing the inconsistency that would result from using\nkeywords.\n\n#### Use `~`, or some other symbol, for complement\n\nWe could follow C++ and use `~` as the complement operator. However, using `~`\nfor this purpose spends a precious operator character on a relatively uncommon\noperation, and `~` is often visually confusible with `-`, creating the potential\nfor readability problems. Also, in C++, `~` is overloaded to also refer to\ndestruction, and we may want to use the same notation for destruction or\ndestructive move semantics in Carbon.\n\nWe found `^` to be a satisfying alternative with a good rationale and mnemonic:\n`^` is a bit-flipping operator -- `a ^ b` flips the bits in `a` that are\nspecified in `b` -- and complement is an operator that flips _all_ the bits.\n`^a` is equivalent to `a ^ n`, where `n` is the all-one-bits value in the type\nof `a`.\n\nWe also considered using `!` for complement, like Rust does. Unlike in Rust,\nthis would not be a generalization of `!` on `bool`, because we use `not` for\n`bool` negation, and repurposing `!` in this way compared to C++ seemed\nconfusing.\n\n### Provide different operators for arithmetic and logical shifts\n\nWe could provide different operators for arithmetic right shift and logical\nright shift. This might allow programmers to better express their intent.\nHowever, it seems unnecessary, as using the type of the left operand is a\nstrategy that doesn't appear to have caused significant problems in practice in\nthe languages that have followed it.\n\nBasing the kind of shift on the signedness of the left operand also follows from\nviewing a negative number as having an infinite number of leading 1 bits, which\nis the underlying mathematical model behind the two's complement representation.\n\n### Provide rotate operators\n\nWe could provide bitwise rotation operators. However, there doesn't seem to be a\nsufficient need to justify adding another operator symbol for this purpose.\n\n### Guarantee behavior of large shifts\n\nLogically, the behavior of shifts is meaningful for all values of the second\noperand:\n\n-   A shift by an amount greater than or equal to the bit-width of the first\n    operand will shift out all of the original bits, producing a result where\n    all value bits are the same.\n-   A shift in one direction by a negative amount is treated as a shift in the\n    opposite direction by the negation of that amount.\n\nPut another way, we can view the bits of the first operand as an N-bit window\ninto an infinite sequence of bits, with infinitely many leading sign bits (all\nzeroes for an unsigned value) and infinitely many trailing zero bits after a\nnotional binary point, and a shift moves that window around. Or equivalently, a\nshift is always a multiplication by 2<sup>N</sup> followed by rounding and\nwrapping.\n\nWe could provide the correct result for all shifts, regardless of the magnitude\nof the second operand. This is the approach taken by Python, except that Python\nrejects negative shift counts. The primary reason we do not do this is lack of\nhardware support. For example, x86 does not have an instruction to perform this\noperation. Rather, x86 provides shift instructions that mask off all bits of the\nsecond operand except for the bottom 5 or 6, meaning that a left shift of a\n64-bit operand by 64 will return the operand unchanged rather than producing\nzero.\n\nWe could instead provide x86-like behavior, guaranteeing to consider only the\nlowest `N` bits of the second operand when the first operand is an `iN` or `uN`.\nThis is the approach taken by Java for its 32-bit `int` type and 64-bit `long`\ntype, where the second operand is taken modulo 32 or 64, respectively, and in\nJavaScript, where operands of bitwise and bit-shift operators are treated as\n32-bit integers and the second operand of a shift is taken modulo 32. This\napproach would provide an operation that can be implemented by a single\ninstruction on x86 platforms when `N` is 32 or 64, and for all smaller types and\nfor all other platforms the operation can be implemented with two instructions:\na mask and a shift. For larger types, single-instruction support may not be\navailable, but nonetheless the performance will be close to optimal, requiring\nat most one additional mask. There is still some performance cost in some cases,\nbut the primary reason we do not do this is the same reason we choose to not\ndefine signed integer overflow: this masked result is unlikely to be the value\nthat the developer actually wanted.\n\nInstead of the above options, Carbon treats a second operand that is not in the\ninterval [0, N) as a programming error, just like signed integer overflow:\n\n-   Debugging builds can detect and report this error without the risk of false\n    positives.\n-   Performance builds can optimize on the basis that this situation will not\n    occur, and can in particular use the dedicated x86 instructions that ignore\n    the high order bits of the second operand.\n-   Optimized builds guarantee that either the programming error results in\n    program termination or that _some_ value is produced, and moreover that said\n    value is the result of applying _some_ mathematical shift to the input. For\n    example, it's valid for an `i32` shift to be implemented by an x86 64-bit\n    shift that will produce 0 if the second operand is in [32, 63) but that will\n    treat a second operand of, say, 64 or -64 the same as 0.\n\n### Support shifting a constant by a variable\n\nWe considered various ways to support\n\n```\nvar a: i32 = ...;\nvar b: i32 = 1 << a;\nvar c: i32 = 1234 >> a;\n```\n\nwith no explicit type specified for the first operand of a bit-shift operator.\nWe considered the following options:\n\n-   Use the type of the second operand as the result type. This would be\n    surprising, because the type of the second operand doesn't otherwise\n    influence the result type of a built-in bit-shift operator.\n-   Use some suitable integer type that can fit the first operand. However, this\n    is unlikely to do the right thing for a left-shift, and will frequently pick\n    either a type that's too large, resulting in the program being rejected due\n    to narrowing, or a type that's too small, resulting in a program that has\n    undefined behavior due to the second operand being too large. We could apply\n    this approach only for right shifts, but it was deemed too inconsistent to\n    use different rules for left and right shifts.\n-   We could find a way to defer picking the type in which the operation is\n    performed until later. For example, we could treat `1 << a` as a value of a\n    new type that carries its left-hand operand as a type parameter and its\n    right-hand operand as runtime state, and allow that type to be converted in\n    the same way as its integer constant. However, this would introduce\n    substantial complexity: reasonable and expected uses such as\n    ```\n    var mask: u32 = (1 << a) - 1;\n    ```\n    would require a second new type for a shifted value plus an offset, and\n    general support would require a facility analogous to\n    [expression templates](https://en.wikipedia.org/wiki/Expression_templates).\n    Further, this facility would allow implicit conversions that notionally\n    overflow, such as would happen in the above example when `a` is greater\n    than 32.\n\nIn the absence of a good approach, we disallow such conversions for now. The\nabove example can be written as:\n\n```\nvar a: i32 = ...;\nvar b: i32 = (1 as i32) << a;\nvar c: i32 = (1234 as i32) >> a;\n```\n\n### Converting complements to unsigned types\n\nWe view an integer constant has having infinitely many high-order sign bits\nfollowed by some number of lower-order value bits. As a consequence, the\ncomplement of a positive integer constant is negative. As a result, some\nimportant forms of initialization use a negative integer constant initializer\nfor an unsigned type:\n\n```\n// Initializer here is the integer value -8.\nvar mask: u32 = ^7;\n```\n\nWe considered some options for handling this:\n\n-   We could allow negative integer constants to convert to unsigned types if\n    doing so only discards sign bits. This violates the \"semantics-preserving\"\n    rule for implicit conversions.\n-   We could change our model of integer constants to distinguish between\n    \"masks\" -- numbers with infinitely many 1 bits preceding the value bits that\n    are nonetheless not considered to be negative. This was considered to\n    introduce too much complexity.\n-   We could allow conversions to unsigned types from signed types and negative\n    constants in general, or at least in cases where the signed operand is no\n    wider than the unsigned type, and perform wrapping. The latter option seems\n    plausible, but we don't have sufficient motivation for it, and were worried\n    about a risk of bugs from allowing an implicit conversion at runtime that\n    converts a negative value to an unsigned type.\n-   We could reject such initializations, with an explicit conversion required\n    to convert such values to unsigned types. This seems to present unacceptable\n    ergonomics for code performing bit-manipulation.\n\nOn balance, our preferred option was to permit implicit conversions from\nnegative literals to unsigned types so long as we only discard sign bits.\n"
  },
  {
    "path": "proposals/p1270.md",
    "content": "# Update and expand `README` content and motivation for Carbon\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1270)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Avoid discussion of motivations](#avoid-discussion-of-motivations)\n    -   [Avoid summarizing key language design areas](#avoid-summarizing-key-language-design-areas)\n    -   [Avoid discussing the difficulty of directly and incrementally improving C++](#avoid-discussing-the-difficulty-of-directly-and-incrementally-improving-c)\n\n<!-- tocstop -->\n\n## Problem\n\nFeedback from folks outside of the immediate team working on Carbon surfaced\nboth some problems with the exact phrasing of our main README content, but more\nimportantly some major _gaps_ in our overall documentation. Specifically, we\nfailed to really explain our motivations for building Carbon and why this\napproach might make sense.\n\nGiven the significance of the new content and the importance of these specific\ntopics, this level of change seems important to go through the proposal process.\n\n## Background\n\nWe've been trying to polish and improve the positioning and explanation of\nCarbon to help understand whether it makes sense to shift the project towards\nbeing a _public_ experiment instead of private one.\n\n## Proposal\n\nThis PR includes a significant update to the [`README`](/README.md) content, as\nwell as adding [a new document](/docs/project/difficulties_improving_cpp.md) to\nexplain the difficulties with incrementally improving C++.\n\nIt also tweaks the wording of our goals to try to further reduce confusion.\n\n## Details\n\nSee the pull request for the detailed change.\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   We should document clearly our motivations to ensure that aspect of the\n        project remains transparent and clear.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Understanding the _motivations_ of the Carbon project will be important\n        for future language evolution efforts.\n\n## Alternatives considered\n\n### Avoid discussion of motivations\n\nWe could instead choose to avoid discussion of the project's motivations. This\nhas largely been the status-quo prior to this change.\n\nAdvantages:\n\n-   Less text.\n-   Fewer opportunities for a misunderstanding to develop.\n\nDisadvantages:\n\n-   Fails to be transparent. We _do_ have motivations, and we can't\n    realistically pretend otherwise.\n-   Because we all _do_ have motivations, failing to write them down will\n    largely result in an inconsistent and lower-quality presentation of them in\n    informal discussions and forums.\n\n### Avoid summarizing key language design areas\n\nThis proposal suggests some brief summaries around both\n[generics](/README.md#generics) and [memory safety](/README.md#memory-safety).\nWe could instead skip these or only have a brief mention of these.\n\nAdvantages:\n\n-   Less text.\n-   May be inaccurate and will run the risk of drifting out of date.\n    -   This was a larger concern previously when for example generics was\n        undergoing more active development.\n\nDisadvantages:\n\n-   Fails to give people an easily consumed entry into some of the really\n    exciting aspects of the language design.\n-   Memory safety at least will likely be an immediate question for readers\n    where we can front-load a well considered answer.\n\n### Avoid discussing the difficulty of directly and incrementally improving C++\n\nPreviously we didn't go into details about the difficulties with incrementally\nimproving C++ itself that are an essential component of the motivation for\nCarbon. We could stay with that approach.\n\nAdvantages:\n\n-   Less text.\n-   A very contentious subject that will have many divergent, well-reasoned, and\n    strongly held positions.\n-   Prior attempts to articulate this have ended up being easily misunderstood\n    or implying significantly more than was intended in a way that actually\n    reduced alignment between different readers rather than building alignment\n    and shared understanding.\n\nDisadvantages:\n\n-   Despite the _difficulty_ of articulating this, it remains _important_. We\n    shouldn't avoid doing the work here merely because it is difficult.\n-   Omitting the discussion of these difficulties runs a risk of seeming\n    disingenuous -- the premise of the Carbon project makes it clear that there\n    is a significant motivation here.\n-   Overcoming the difficulty of articulating these difficulties well and in an\n    understandable form will significantly strengthen the Carbon project's\n    overall motivation and how it can engage with the broader industry.\n"
  },
  {
    "path": "proposals/p1280.md",
    "content": "# Principle: All APIs are library APIs\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1280)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Built-in primitive types](#built-in-primitive-types)\n\n<!-- tocstop -->\n\n## Problem\n\nWe need a clear and consistent \"division of labor\" between the core language and\nthe standard library.\n\n## Background\n\nSee\n[the principle doc](/docs/project/principles/library_apis_only.md#background).\n\nSee also [#57](https://github.com/carbon-language/carbon-lang/pull/57), a\nprevious iteration of a similar idea.\n\n## Proposal\n\nIn Carbon, every public function will be declared in some Carbon `api` file, and\nevery public `interface`, `impl`, and first-class type will be defined in some\nCarbon `api` file. In some cases, the bodies of public functions will not be\ndefined as Carbon code, or will be defined as hybrid Carbon code using\nintrinsics that aren't available to ordinary Carbon code. However, we will try\nto minimize those situations.\n\nThus, even \"built-in\" APIs can be used like user-defined APIs, by importing the\nappropriate library and using qualified names from that library, relying on the\nordinary semantic rules for Carbon APIs.\n\n## Details\n\nSee [the principle doc](/docs/project/principles/library_apis_only.md).\n\n## Rationale\n\nThis principle facilitates\n[software evolution](/docs/project/goals.md#software-and-language-evolution), by\nhelping to ensure that code written in terms of a Carbon-provided type can be\nmigrated to use a suitable user-defined type instead. It also facilitates\nevolution of the language itself, by enabling more of that evolution to take\nplace in library code, which doesn't require compiler expertise.\n\nThis principle helps make Carbon code\n[easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\nbecause user-defined APIs can match the ergonomics of language-defined APIs, and\nthe syntax, language rules, and core concepts are consistent between the two.\n\nThis principle indirectly helps Carbon support\n[performance-critical software](/docs/project/goals.md#performance-critical-software):\nby using Carbon's API abstraction mechanisms for even the most fundamental\ntypes, we ensure that those mechanisms do not impose any performance overhead.\n\n## Alternatives considered\n\n### Built-in primitive types\n\nWe could follow the general outline of C++, where arithmetic and pointer types\nare built-in. However, that would substantially erode the advantages outlined\nabove. We expect Carbon to have multiple kinds of pointers (for example, to\nrepresent different kinds of ownership), and multiple kinds of arithmetic types\n(for example, to handle overflow in different ways). They can't all be built-in,\nso putting even the common-case types in the library helps ensure that Carbon\nhas enough expressive power for the uncommon-case library types.\n"
  },
  {
    "path": "proposals/p1327.md",
    "content": "# Generics: `impl forall`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1327)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Problem\n\nWe have an ambiguity in the grammar between declaring a parameterized impl and\nan impl for an array type.\n\n```\n// Parameterized impl\nexternal impl [T:! Printable] Vector(T) as Printable { ... }\n// Impl for an array type\nexternal impl [i32; 5] as Printable { ... }\n```\n\nWhen the parser sees `impl [`, it doesn't know which kind of impl declaration it\nis parsing without more lookahead than we plan to support. For the same reason,\nthese declarations are easy for humans to confuse.\n\n## Background\n\nParameterized impls introduced in\n[#920: Generic parameterized impls (details 5)](https://github.com/carbon-language/carbon-lang/pull/920).\n\nArray syntax has not been finalized, but the leading contender is `[i32; 5]`,\nsimilar to\n[Rust](https://doc.rust-lang.org/rust-by-example/primitives/array.html). This is\nwhat is currently provisionally implemented in Explorer. Some other contenders\nalso start with `[` and have the same problem.\n\nThis problem was discussed and resolved in question-for-leads issue\n[#1192: Parameterized impl syntax](https://github.com/carbon-language/carbon-lang/issues/1192).\n\n## Proposal\n\nThis proposal implements the decision in\n[#1192](https://github.com/carbon-language/carbon-lang/issues/1192) to write\nparameterized impls using this syntax:\n\n> `impl forall [`_generic parameters_`]` _type_ `as` _constraint_ ...\n\nand to remove the option to includes bindings in the _type_ `as` _constraint_\npart of the declaration.\n\nThis PR includes the changes to\n[the generics details design doc](/docs/design/generics/details.md).\n\n## Rationale\n\nThis decision favored approaches that did not require more lookahead. This is to\nsimplify compiler and tool development and to make it easier for humans to read\nthe code, in support of these goals:\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\n    particularly \"Excellent ergonomics\", \"Support tooling at every layer of the\n    development experience, including IDEs\", and \"Design features to be simple\n    to implement.\"\n\n## Alternatives considered\n\n@zygoloid listed some options for addressing this problem\n[in the #syntax channel on Discord](https://discord.com/channels/655572317891461132/709488742942900284/963191891334168628):\n\n> Summary of options for implicit parameters / arrays ambiguity discussed so\n> far:\n>\n> 1. Just make it work as-is: `impl [a; b]` parses as an array type,\n>    `impl [a, b]` parses as an implicit parameter. Theoretically this is\n>    unambiguous given that a `;` is required inside the `[`...`]` in the former\n>    and disallowed in the latter. Concerns: it's likely to be visually\n>    ambiguous.\n> 2. Add mandatory parentheses: `impl [T:! Type] (Vector(T) as Container)`.\n>    Concerns: it's hard to avoid requiring them in cases that don't start with\n>    a `[` if we want an unambiguous grammar. Requiring them always would impose\n>    a small ergonomic hit.\n> 3. Add an introducer keyword for implicit parameters:\n>    `impl where [T:! Type] Vector(T) as Container`. Unambiguous. Concerns:\n>    still some visual ambiguity due to reuse of `[`...`]`, concern over whether\n>    we'd uniformly use this syntax (`fn F where [T:! Type](x: T)`) or have\n>    non-uniform syntax for implicit parameters.\n> 4. Use a different syntax for array types in general:\n>    `impl Array(T) as Container` or `impl Array[N] as Container`. Concerns: may\n>    want a first-class syntax here, especially if (per @geoffromer 's variadics\n>    work, we want some special behavior for a deduced bound), and there's a\n>    strong convention to use `[`...`]` for this. The latter syntax is messy\n>    because of our types-as-expressions approach, but we could imagine\n>    providing a `impl Type as Indexable where .Result = Type` to construct\n>    array types. `T[]` might be a special case of some kind.\n> 5. Use a different syntax for implicit parameters in general:\n>    `impl<T:! Type> Vector(T) as Container`. Concerns: we don't have many\n>    delimiter options unless we start using multi-character delimiters; `()`,\n>    `[]`, and `{}` are all used for types, leaving `<>` as the only remaining\n>    bracket. Use of `<>` as brackets as a long history but not a good one. ...\n> 6. Remove the implicit parameter list from impls and force them to be\n>    introduced where they're first used: `impl Vector(T:! Type) as Container`.\n>    Concerns: harms readability in some cases, eg\n>    `impl Optional(T:! As(U:! Type)) as As(Optional(U))` versus\n>    `impl [U:! Type, T:! As(U)] Optional(T) as As(Optional(U))`.\n> 7. Move the implicit parameter list before the impl keyword, perhaps with an\n>    introducer: `generic [T:! Type] impl Vector(T) as Container`. Concerns:\n>    increases verbosity; would be inconsistent if we put everything but me\n>    there, and surprising if we put me there. Also not clear what a good\n>    keyword is, given that the existence of deduced parameters isn't the same\n>    as an entity being generic.\n\nUltimately we adopted approach 3, but changed to the new keyword `forall` to\navoid overloading the meaning of a keyword used for something else.\n"
  },
  {
    "path": "proposals/p1344.md",
    "content": "# Remove LLVM from the repository, and clean up history.\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1344)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Implementation](#implementation)\n    -   [Patching LLVM](#patching-llvm)\n    -   [Updating forks and clones](#updating-forks-and-clones)\n        -   [Archive your existing fork and clones](#archive-your-existing-fork-and-clones)\n        -   [Create a fresh fork and clone](#create-a-fresh-fork-and-clone)\n        -   [Porting in-progress branches from your archived clone](#porting-in-progress-branches-from-your-archived-clone)\n        -   [Updating pending PRs](#updating-pending-prs)\n    -   [Review comments may be disrupted](#review-comments-may-be-disrupted)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Do nothing](#do-nothing)\n    -   [Don't rewrite the repository history.](#dont-rewrite-the-repository-history)\n    -   [Go back to submodules](#go-back-to-submodules)\n    -   [Rename the repository, and create a new one](#rename-the-repository-and-create-a-new-one)\n    -   [Manually extract and archive some review comments](#manually-extract-and-archive-some-review-comments)\n\n<!-- tocstop -->\n\n## Problem\n\nWe have tried both Git submodules and subtrees to manage accessing the LLVM\nsource code as part of Carbon. We have had significant issues with both of these\nover time.\n\nGit submodules are well supported in general, but make the repository\nsignificantly less user-friendly. There are a number of common operations, not\nleast the initial clone of the repository, that are made frustratingly more\ncomplex in the presence of a submodule. In some cases (switching branches), it\ncan even cause hard to diagnose errors for users. It also doesn't directly help\nwith carrying local patches. Because of all of these, we switched to subtrees.\n\nGit subtrees in some ways work much better once set up as they are simply a\nnormal directory for most users. They also make it especially easy to make and\ncarry local patches. However, setting up the subtree and updating the subtree\nare bug prone and interact very poorly with GitHub's pull request workflow. The\nresult is that updating LLVM is currently both very difficult and error prone.\n\nAnother fundamental problem subtrees expose is that the LLVM repository is\n_huge_. It includes large and complex projects that Carbon is unlikely to ever\nuse, and it doesn't make sense for us to start our repository off with all of\nthat history and space if we can avoid it. Including LLVM causes things like\n`git status` or cloning the repository to be dramatically more expensive without\nsignificant benefit.\n\n## Proposal\n\nWe should switch to using Bazel to download a snapshot of LLVM during the build,\nand do a destructive history re-write to the Carbon repository to completely\nremove LLVM from it. All of the building against LLVM will continue to work\nseamlessly. However, the repository will become tiny and fast to work with, and\nthe snapshot download is significantly cheaper than cloning or working with the\nfull-history of LLVM.\n\nThe only way to capture the benefit here is to do a destructive update to the\nrepository's history. This is unfortunate, but essential to do as soon as\npossible and before we shift to be public. Despite the cost of making this\nchange, the cost of _not_ making it will grow without bound for the life of the\nproject.\n\n**Important:** This _will_ require a manual update of some kind for every fork\nand clone. The steps to update them are provided below.\n\n## Details\n\n### Implementation\n\n<!-- google-doc-style-ignore -->\n\nThis will be accomplished using the\n[`git-filter-repo` tool](https://github.com/newren/git-filter-repo). This makes\nit very easy to prune any trees from the history, replaying the history left and\nresulting in a clean and clear result.\n\n<!-- google-doc-style-resume -->\n\nWe will remove three other trees while here that are no longer used:\n\n-   `src/jekyll/`\n-   `src/firebase/`\n-   `website/`\n\nOnce we're taking a history break, we should capture the value we can and have a\nminimal history of the repository we are actually using. The largest of these is\n`src/jekyll` (988kb even packed), but it seems cleanest to remove the three\ntogether.\n\n### Patching LLVM\n\nWe still need to support patching LLVM. Initially, we will start with a simple\napproach of applying a collection of patch files from the Carbon repository to\nthe LLVM snapshot. This is especially convenient while Carbon's repositories are\nnot public. Eventually, we can switch to having a fork of LLVM that we snapshot\nand developing any needed patches there. Having a more robust long-term solution\nis expected to be important if larger scale development is needed on Clang when\nbuilding interoperability support.\n\n<!-- google-doc-style-ignore -->\n\nDeveloping patches is also very easy when using Bazel. You can pass\n`--override_repository=llvm-project=<directory>`\n([docs](https://bazel.build/reference/command-line-reference#flag--override_repository))\nto have Bazel use a local checkout of LLVM (with any patches you are testing)\nrather than downloading it. If doing significant development, this can be added\nto your `user.bazelrc` file to consistently use your development area.\n\n<!-- google-doc-style-resume -->\n\n### Updating forks and clones\n\nIf you have a fork and any clones of the repository with work that you want to\nsave, we suggest the following process:\n\n#### Archive your existing fork and clones\n\n1.  Go to the archived repository: (broken link:\n    `https://github.com/carbon-language/archived-carbon-lang`)\n\n2.  Fork this archived repository just like you normally would (into your\n    _personal_ space). It is important to fork the `carbon-language` hosted\n    archived repository so you pick up the ACLs. You should **not** create your\n    own personal repository.\n\n3.  Update any clones to use these archived remotes to avoid accidentally trying\n    to interact with the new repository. Example commands assuming the remote\n    `origin` points to your fork and `upstream` points to the main repository.\n    You may also need to adjust from the SSH-style URLs to HTTPS ones to match:\n\n    ```\n    git remote set-url upstream git@github.com:carbon-language/archived-carbon-lang.git git@github.com:carbon-language/carbon-lang.git\n    git remote set-url origin git@github.com:$USER/archived-carbon-lang.git git@github.com:$USER/carbon-lang.git\n    ```\n\n4.  For each clone, mirror everything into the new `origin` (your fork):\n\n    ```\n    git push --mirror origin\n    ```\n\n    If you have multiple clones with different but overlapping branches, this\n    may require some extra steps to avoid collisions when doing the mirror push.\n\nAt this point, your clones should all point to an archival fork and should be\nable to function \"normally\" cleanly. The goal here is just archival and making\nsure you don't lose anything.\n\n#### Create a fresh fork and clone\n\nDelete your existing fork of `carbon-lang` (_not_ `archived-carbon-lang`):\n\n1.  Go to your fork's settings page:\n    `https://github.com/$USER/carbon-lang/settings`. Be certain this is your\n    _fork_ and not the `carbon-language` organization.\n2.  Scroll to the bottom, and click `Delete this repository`.\n\nOnce deleted, create a fresh fork from the now-filtered main repository:\nhttps://github.com/carbon-language/carbon-lang/fork\n\nClone this fork and you're ready to go with the new repository structure.\n\n#### Porting in-progress branches from your archived clone\n\nFor any branch in your archive clones that you want to import, there are two\napproaches.\n\nThe simplest way is to extract the branch as a patch file and apply it in the\nnew repository:\n\n```\n# If your old clone is in the `archived-carbon-lang` directory and your new\n# clone is in `carbon-lang`, both of them on the `trunk` branch:\ncd archived-carbon-lang\ngit switch $BRANCH\ngit diff upstream/trunk... > ../$BRANCH.patch\ncd ../carbon-lang\ngit switch -c $BRANCH\npatch -p1 < ../$BRANCH.patch\ngit commit\n```\n\nThis will just flatten the branch into a single commit in the new clone.\n\nIf you want to preserve the commit history, you can do that using\n`git format-patch`. Some points to remember here:\n\n-   Make sure you've rebased the branch into a clean series of commits on top of\n    the latest trunk in the archived repository.\n-   Use `git format-patch` to get a series of patches in a directory. See its\n    help for detailed usage.\n-   Use `git am` to apply the series of patches in your new clone under some\n    branch. Again, see its help for detailed usage.\n\n#### Updating pending PRs\n\nThe pending PRs should end up closed automatically when you delete your fork\nabove. If not, the simplest approach is to close them and just create a new PR.\nIn-flight discussion comment threads will be awkward, but there isn't much else\nto do. Rename the proposal document if needed.\n\nWe will explore whether we can re-open PRs with a fresh forced push from the\nfresh fork, but aren't confident in this working. It also isn't necessary, and\nwe only have 12 PRs open at the moment.\n\n### Review comments may be disrupted\n\nWhen we edit the repository, some PR comments (especially pending PRs that are\nupdated to follow a freshly created fork) may lose their association with the\nline of code they were made against, and it is possible we may be unable to find\nsome comments. This will at most apply to inline comments within the code of\nPRs, but that is the common case for PRs. We expect most of these to still be\nsomewhat visible in the conversation view of the pull request, but they may be\nhard to find due to no longer being attached to a line.\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   This will make it even easier and smoother for folks to clone, build,\n        and even contribute.\n    -   It will make clones significantly cheaper, especially those not building\n        code but just working on documentation.\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   Preserving the ability to build with LLVM and develop patches will be\n        important as we expand the set of language tools and ecosystem being\n        developed.\n\n## Alternatives considered\n\n### Do nothing\n\nWe could simply continue using the moderately broken Git subtree approach.\n\nAdvantages:\n\n-   No need to change our approach.\n-   No destructive operation on the repository requiring everyone to update.\n\nDisadvantages:\n\n-   Every update of LLVM remains difficult, manual, and error prone.\n    -   We're currently carrying an LLVM patch, and it's easy to lose (and has\n        been lost) in updates.\n-   Will continually hit bugs in Git subtree as it seems both brittle and not a\n    priority. We will have to struggle to understand and fix or work around\n    them.\n-   The repository remains massive, slow, and contains significant LLVM code\n    that we will never use.\n-   If we ever have users that wish to import the Carbon repository into some\n    other environment, they will have to pay the cost of LLVM or remove it\n    somehow. It may even cause them to have two copies of LLVM.\n\nWe think this problem is worth solving.\n\n### Don't rewrite the repository history.\n\nWe could fix this without rewriting history. If we choose not to rewrite history\nnow, it should be noted that the cost of rewriting history only grows and so we\nshould expect to _never_ rewrite history.\n\nAdvantages:\n\n-   No need for manual steps to update forks, clones, in-flight patches, etc.\n-   Commit hashes remain stable.\n-   All code review comment information associated with commit hashes will be\n    retained.\n\nDisadvantages:\n\n-   We pay the cost of having imported LLVM forever. Even if this cost is\n    incrementally small (some amount of repository space when cloning with\n    history), it is a cost we will never stop paying.\n\nWhile the immediate costs are high, the unbounded time frame for which we will\npay for leaving LLVM in the history means that will eventually be the dominant\ncost and we should just rewrite history, and the sooner the better.\n\n### Go back to submodules\n\nRather than switching to use Bazel downloaded snapshots, we could go back to\nusing Git submodules. The original motivation to move away from submodules was\nneeding to carry a local patch. Submodules and the proposed direction have the\nsame options there, and our approach is discussed above.\n\nAdvantages:\n\n-   Somewhat more of a Git-native approach.\n-   Would avoid needing to invent another approach if we add a non-Bazel build\n    system.\n\nDisadvantages:\n\n-   Much of the cloning cost and other Git command costs we see with subtrees\n    would still be present.\n-   It makes working with the Git repository even more tricky to get right.\n-   While less esoteric than subtrees, it still exposes a less polished surface\n    of Git that we will have to cope with.\n-   Most notably, this will re-introduce the stumbling block of users first\n    encountering Carbon not having a seamless experience.\n\nWe think we should try something simpler here, even if a bit less of a\nnative-Git solution. It is also especially important for us to optimize the\ninitial new contributor flow, and the Bazel approach is expected to be more\nseamless.\n\n### Rename the repository, and create a new one\n\nRather than editing the repository in place, this would move it aside and create\na new one with the edited history.\n\nAdvantages:\n\n-   Some disruptive aspects of the in-place history edit would be avoided,\n    specifically parts of PRs that are associated with commit hashes would\n    likely continue working due to the commit hashes being preserved.\n\nDisadvantages:\n\n-   For most cases, this would be equally disruptive -- forks and clones would\n    have the same update needed as they reference the repository by name.\n-   We would either need to build a system to carefully re-create the exact\n    issue numbering and PR numbering, which may not even be possible, or we\n    would need to allow all issue numbers and PR numbers to churn.\n    -   The PR numbers churning is especially disruptive as the commit log\n        references them to connect commits to the code review that led to the\n        commit. They are also the basis of the proposal numbers.\n    -   There isn't likely a way to move the PRs back to the main repository, so\n        browsing the historical code reviews would become problematic.\n\nThis seems to largely trade off preservation of some of the comment history\nwithin PRs for preserving the location, numbers, and links of all PRs and\nissues. That doesn't seem like the right tradeoff.\n\n### Manually extract and archive some review comments\n\nWe could attempt to extract and archive review comments in case they are lost or\nmade hard to find by the change.\n\nAdvantages:\n\n-   Defense in depth against any information loss here.\n\nDisadvantages:\n\n-   Would be a decent amount of work to get this right.\n-   May not lose much information here. We think the comments will still be in\n    the conversation view, but maybe hard to find.\n-   Unclear whether any of these will actually have value, especially extracted\n    and out of context from the review where they were made.\n-   Serious concerns about arbitrarily scraping and moving comments other folks\n    authored outside of the system (GitHub) that they authored them within.\n\nOverall, while there is some risk here, we don't think it is too high and the\ncost of trying to mitigate this seems unreasonable given the relatively small\ntotal amount of data at issue here.\n"
  },
  {
    "path": "proposals/p1360.md",
    "content": "# Change raw string literal syntax: `[#]\\*\"` represents single-line string and `[#]\\*'''` represents block string\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1360)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [The current implementation](#the-current-implementation)\n    -   [Using `\"\"\"` to start block string literals](#using--to-start-block-string-literals)\n    -   [Non-quote marker after the open quote](#non-quote-marker-after-the-open-quote)\n    -   [Use different quotes to allow `#'\"'#`](#use-different-quotes-to-allow-)\n\n<!-- tocstop -->\n\n## Problem\n\nUnder current design of string literals, users may make assumptions that a\nstarting `[#]*\"\"\"` represents a block string and misunderstand the syntax.\n\n## Background\n\nThe design of\n[string literals](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/lexical_conventions/string_literals.md)\nspecifies a block string literal to start with `[#]*\"\"\"`. Users may take for\ngranted the other way around, where any string literal starting with `[#]*\"\"\"`\nis a block string literal. This does not hold true, however. Two counter-cases\nare `\"\"\"abc\"\"\"` represents three tokens `\"\"`, `\"abc\"` and `\"\"`, and `#\"\"\"#`\nwhich is equivalent to `\"\\\"\"`. Neither is a block string literal and may be\nvisually confusing.\n\n## Proposal\n\nInterpret `[#]*\"` as the start of single-line string literals, and `[#]*'''` as\nthe start of block string literals. Disallow adjacent string literals like\n`\"\"\"abc\"\"\"`.\n\n## Details\n\nUsers can easily distinguish single-line string literals from block string\nliterals with the proposed change. Confusion on `\"\"\"abc\"\"\"` will be eliminated\nbecause adjacent string literals are invalid in the proposal. On the other hand,\n`#\"\"\"#` will be clear to the user of representing `\"\\\"\"`, as `\"\"\"` does not\nrepresent a block string literal any more. More details can be found\n[here](/docs/design/lexical_conventions/string_literals.md).\n\n## Rationale\n\nThis principle helps make Carbon code\n[easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\nbecause it avoids confusion on the type of certain string literals.\n\n## Alternatives considered\n\n### The current implementation\n\nIn addition to the confusion described above, the\n[current implementation](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/lexical_conventions/string_literals.md)\ncomplicates the lexing. When the lexer sees `[#]+\"\"\"`, it temporarily accepts\nsyntax of both string types because the type of the string is undecided.\nSpecifically, it accepts vertical whitespaces even if they are not allowed in\nsingle-line strings. The type of the string won't be decided until the lexer\nsees a closing `\"#` or a new line. In case of a closing `\"#` where the string is\nsingle-line, the lexer will look back on the scanned characters for vertical\nwhitespaces to decide if the single-line string is valid.\n\n### Using `\"\"\"` to start block string literals\n\nThis approach loses some convenience in using raw string literals while\naddressing the problem. For example, as discussed in\n[issue #1359](https://github.com/carbon-language/carbon-lang/issues/1359),\n`#\"\"\"#` is a natural way to write a string of `\"`.\n\n### Non-quote marker after the open quote\n\nAlthough something similar to C++ style like `\"(` solves the problem, the syntax\nbecomes complicated and hurts readability. In addition, `\"(\")\"` is no simpler\nthan `\"\\\"\"` or `#\"\"\"#`.\n\n### Use different quotes to allow `#'\"'#`\n\nWhen disallowing adjacent string literals, we can additionally allow `[#]+'` on\nsingle-line string literals. Another option is to use `[#]+'` for single-line\nstring literals and `[#]+\"` for block string literals. In general, `#'\"'#` is\nvisually confusing with character `'\"'` and hurts readability.\n"
  },
  {
    "path": "proposals/p1363.md",
    "content": "# Make the Carbon experiment public\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1363)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Why go public now?](#why-go-public-now)\n    -   [Planned process for going public](#planned-process-for-going-public)\n        -   [Public site and communications plan](#public-site-and-communications-plan)\n        -   [Plan for ACLs once public](#plan-for-acls-once-public)\n    -   [Risks and mitigations](#risks-and-mitigations)\n        -   [Too many cooks in the kitchen](#too-many-cooks-in-the-kitchen)\n        -   [Community management overload](#community-management-overload)\n        -   [Added distraction or confusion to the C++ evolution process](#added-distraction-or-confusion-to-the-c-evolution-process)\n        -   [Added distractions from existing new programming languages.](#added-distractions-from-existing-new-programming-languages)\n        -   [Friction with existing LLVM and Clang communities](#friction-with-existing-llvm-and-clang-communities)\n        -   [Labeled as vaporware](#labeled-as-vaporware)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Delay going public until we have working interop demonstrated](#delay-going-public-until-we-have-working-interop-demonstrated)\n    -   [Delay going public until Carbon is a compelling option for C++ developers to adopt](#delay-going-public-until-carbon-is-a-compelling-option-for-c-developers-to-adopt)\n\n<!-- tocstop -->\n\n## Problem\n\nOpen, transparent, and public development is often the best way to build a\ndeveloper community. Long-term evolution of Carbon behind closed doors does not\nalign with our core principles.\n\nWhile early exploration with a limited group of participants has been effective\nat bootstrapping, a primary goal for the Carbon experiment is to establish\nwhether there will be **broad industry interest and participation** in this\ndirection. We expect this kind of interest and participation to ultimately\nresult in widespread adoption if the technical components of the experiment\nsucceed. We both want to see how the industry reacts to Carbon and think that\nreaction will be much more positive if the industry can actively participate and\nhelp shape the language.\n\n## Background\n\nHistorically, Carbon has followed a \"quiet\" development model. While developed\non GitHub using an open source process, the project was not publicly visible or\ndiscussed outside the invited set of early participants.\n\nCarbon developed an initial set of criteria that we expected to signal the\ncorrect time for the project to become public:\n\n-   Broader field experience required\n-   Sustained interest from multiple organizations and individuals\n-   A prototype implementation\n-   A demonstration of potential\n-   Learning material\n-   Prepared for broader contributions and feedback\n-   Prepared for a launch event\n\nSee the removed `going_public.md` document in this\n[proposal](https://github.com/carbon-language/carbon-lang/pull/1363) for the\nfull historical criteria and analysis.\n\n## Proposal\n\nWe should make the Carbon experiment public as soon as reasonably possible,\nspecifically at the upcoming [C++ North](https://cppnorth.ca) conference.\n\nMany of the criteria outlined previously have not yet been met, and this\nproposal specifically suggests shifting Carbon to be public without waiting for\nthem. Instead, we should make Carbon public largely as it is today. We should be\nopen and transparent about the current status. We should frame this as making a\n_nascent_ project public in order to _build it in the open_, rather than\nsuggesting it is \"done\" or \"ready\" even for evaluation.\n\n### Why go public now?\n\nThere is no perfect time to shift the project public, it is a tradeoff. The\nearlier we move the project to be public, the earlier we can gain more broad\nfeedback and participation from the industry. However, it comes at the cost of\nintroducing people to the project at an earlier stage with less material to help\nthem get started. We believe Carbon has crossed the point where this tradeoff\nsuggests sooner would be overall better for the project than later.\n\n**The Carbon experiment has accomplished what it can** to explore industry\ninterest and participation with limited and targeted outreach to experts. We\nhave built the critical community and design process and framework to support an\nopen technical discussion. We have also developed the key language design ideas\nsufficiently to show what Carbon would look like clearly and unambiguously. To\nbroaden or deepen the feedback, we will need frank and public discussion with\nwider groups of users and stakeholders. We will need to iterate with a larger\ncommunity and a broader set of stakeholders.\n\n**The needs of the C++ community remain unmet, and they are eager** and asking\nfor exactly Carbon's approach. The technical approach of Carbon directly\naddresses concrete and current requests from influential C++ developers. These\nneeds are specifically not met by C or C++ as they exist or by Rust or other\noptions, and we have a strategic opportunity to help drive a solution in this\nspace.\n\nA recent example on Twitter:\n\n> Speaking as a C/C++ developer, when I write in C/C++, I am doing so due to\n> ecosystem/practical/legacy code constraints I have no control over, which\n> means that being given a superior choice makes no difference to me because I\n> didn't get a chance to choose C/C++ to start with\n>\n> -- [@mcclure111](https://twitter.com/mcclure111/status/1484987221136580610)\n\nA recent HackerNews discussion directly suggested essentially the direction we\nare exploring:\n\n> The permanent-ABI compatibility decision was effectively the death-knell for\n> C++. Can't improve the standard library performance, making it effectively\n> useless for the real world. Can't correct mistakes - the language and library\n> warts grow and grow as the years pass by, making it impossible for beginners\n> to pick up and learn the language.\n>\n> -- [lenkite](https://news.ycombinator.com/item?id=31227269)\n\nLast but not least, **the Carbon experiment will accelerate thinking about more\ndramatic ways to improve C++ across the industry**.\n\n### Planned process for going public\n\nOur planned process is anchored around a few key principles:\n\n-   Replicate LLVM's open-source approach and strategy. This has proven broadly\n    successful over many years.\n-   Use existing events and spaces where possible to engage with the C++\n    community and industry.\n-   Emphasize that it's an experiment, not a finished product.\n-   Leverage existing C++ ecosystems rather than creating new ecosystems from\n    scratch.\n\nWe expect three phases to move things to be public:\n\n-   Get technical components ready: demo, documentation, etc.\n-   Do an incremental \"road show\" with experts, organizations, and WG21 in weeks\n    leading up to an official public announcement to seed early awareness.\n-   Announce and make everything public at C++North.\n\nDuring the second phase, we plan to engage with the following individuals and\ngroups:\n\n-   Industry partners already active in C++ evolution.\n-   Influential experts, especially those actively driving C++ evolution and\n    prominently writing blog posts or speaking on C++.\n-   Community organizations like #include <C++> and Boost.\n\nOur intent is to invite large portions of these groups to join community spaces\nto help engage and establish the community culture.\n\nThe third phase will be oriented around a keynote at CppNorth:\n\n-   Introduce the audience to the motivation for Carbon and its goals.\n-   Explain the project, community, and process.\n-   Walk through the core language design so far, and touch on exciting future\n    efforts.\n-   Provide an extended Q&A to help kick off active discussions, ideally with as\n    many of the current Carbon contributors on stage as possible.\n-   Will open the GitHub project _read_ ACLs either right before or during the\n    talk so that the audience can explore during the Q&A and afterward.\n-   Will open the _contribution_ ACLs and Discord Chat at the _end_ so that the\n    maximum team bandwidth is available to engage with folks as they begin\n    discussing.\n\n#### Public site and communications plan\n\n-   Planning to use a GitHub project and GitHub hosted markdown documentation.\n-   Work with existing C++ community blogs to post information about the project\n    after announcement.\n\nWe are specifically not planning on a website, blog, or other more \"official\"\npresence. This should anchor on Carbon being an experiment and attracting\ncontributors and participants rather than users.\n\n#### Plan for ACLs once public\n\nGitHub will move to the normal for a public repository:\n\n-   Anyone can create PRs, issues, discussions. This will be fully public.\n-   A fairly small number of committers (initially the current set) can merge\n    PRs.\n\nDiscord will be fully public, using the community features to gate entry on CoC\nand CLA.\n\nThe shared Google drive and docs:\n\n-   Make viewable publicly.\n-   Use the existing group (carbon-lang-contributors@googlegroups.com) to\n    provide comment and edit access.\n-   New contributors will need to request to join the group to begin\n    contributing in this space, but only to avoid spam. This will be a very\n    low-risk and trivially handed out access.\n\nMeetings and calendar:\n\n-   As currently, the meeting links would be posted to Discord and anyone there\n    can click through and join.\n-   The shared calendar and weekly meeting can also be directly made available\n    to the same group as the drive.\n-   In the future, we can explore enabling live-streaming from the weekly\n    meeting and providing a fully public live stream link for those interested.\n\n### Risks and mitigations\n\nMaking Carbon public does raise some significant risks that we need to be aware\nof and work to mitigate.\n\n#### Too many cooks in the kitchen\n\n-   While opening up to the public, we may get a huge influx of feedback and\n    even contributions.\n-   This can quickly turn into a situation of too many folks all trying to drive\n    Carbon forward in their own direction.\n\nPlanned mitigations:\n\n-   We're hoping that many of the critical parts of the language design we've\n    prioritized have enough maturity to show a reasonably focused direction that\n    folks should focus on to be useful.\n    -   We will likely work to avoid immediately reconsidering directions that\n        are already well under way to stay focused, capturing any feedback and\n        marking it as deferred for a time to revisit.\n-   Critical aspects of the language design that are still green fields, we're\n    hoping to clearly document as being intentionally deferred in part just to\n    reduce the level of churn.\n    -   However, we can and should carefully watch for sustained contributors\n        who are looking for an area to drive. _That_ needs to be identified and\n        enabled. We just want to make sure it can be a focused effort.\n-   We should make an extra effort to use the more formal process of raising\n    questions for the Carbon Leads to direct the incoming flow. That process is\n    set up in a way that should enable it to queue and process things without\n    ending up in total chaos.\n-   Where possible, teams working on Carbon should start making contingency\n    plans to pull in more resources if needed to sustain the engagement.\n\n#### Community management overload\n\n-   We may have a sudden influx of community members, with all of them trying to\n    figure out how to collaborate and communicate effectively. This may even\n    include publicity and other factors.\n-   Responding to and engaging with this will be both time consuming, and\n    difficult.\n-   It will be tempting for the Carbon Leads to attempt to drive these\n    responses, in turn starving other parts of the project.\n\nPlanned mitigations:\n\n-   Provide early access to a growing set of people, especially those interested\n    and effective and helping with community and communication.\n-   Contract with a dedicated community engagement specialist.\n    -   Work with them to recruit moderation teams and other scalable groups to\n        tackle these issues.\n-   Leverage moderation scaling tools across our communication platforms to keep\n    the technical work focused and moving.\n\n#### Added distraction or confusion to the C++ evolution process\n\n-   Carbon is a very different direction from the continued C++ evolution in\n    WG21.\n-   Bringing the C++ community into Carbon and getting them engaged and\n    participating will at least reduce the available resources for WG21 in the\n    C++ community.\n-   The existence, and especially any excitement around such a different\n    approach may distract from important work that still needs to get done in\n    WG21.\n\nPlanned mitigations:\n\n-   Carbon's documentation and all of our public communication should include a\n    key message: **If C++ fully meets your needs today, you should keep using\n    it.** Carbon is _only_ exploring a direction to address specific concerns\n    and problems some users have with C++ today. For other users whose needs are\n    fully met, they should stay focused on the thing that exists and works\n    today: C++.\n-   Carbon is building on top of the C++ ecosystem, and we need to be very clear\n    that means it is important to not distract from critical work that needs to\n    happen there. We should be active and vocal in supporting folks who are\n    continuing to drive WG21 forward.\n-   We need to be extremely explicit and clear at every stage that Carbon is\n    still an experiment that may not work out.\n    -   We do not want critical work that needs to happen for C++ and WG21 to\n        stay healthy to be diverted towards Carbon.\n-   We plan to engage with committee members actively so they can learn as much\n    as possible from the Carbon experiment and incorporate any and all of our\n    ideas into C++ where they see a path to do so.\n\n#### Added distractions from existing new programming languages.\n\n-   Another programming language in the world might dilute some of the efforts\n    going towards new and exciting but existing languages, especially ones with\n    similar performance goals such as Rust.\n-   It may also distract users who are unsure of which language to use.\n\nPlanned mitigations:\n\n-   Throughout Carbon's documentation and any public communication, we will take\n    a specific stance to avoid and minimize this effect:\n    -   **If you can use an existing language like Go, Kotlin, or Rust, do so.**\n        This experiment is exploring an option for when existing languages\n        _don't_ work, particularly due to needing to interoperate with a large\n        body of C++ code.\n-   We should be careful in the tone whenever discussing existing languages or\n    comparing with them, to approach them positively. We should be actively\n    supporting other languages, and our focus should be trying to fill a _gap_\n    in that ecosystem rather than directly competing.\n\n#### Friction with existing LLVM and Clang communities\n\nWhile somewhat unlikely, we don't want to create unnecessary friction with the\nLLVM and especially the Clang community, as they have heavily invested in a C++\ncompiler and tooling stack and supporting the C++ language.\n\nPlanned mitigations:\n\n-   Need to carefully emphasize that we are build on top of the tremendous work\n    done by the LLVM and Clang communities.\n    -   LLVM is a critical part of our ability to make a high-performance\n        implementation and have no performance overhead when interoperating with\n        C++ by using a shared compilation environment.\n    -   Clang is the key to our C++ interoperability implementation plans --\n        without a production quality frontend with broad cross-platform support\n        it would be impossible to achieve the level of interop we need between\n        C++ and Carbon.\n    -   Many of the insights that have led to Carbon's design come from\n        experimentation with Clang and C++ extensions, as well as our experience\n        working on the LLVM and Clang codebases themselves.\n-   We will clearly and publicly drive improvements to LLVM and Clang upstream\n    when needed for Carbon rather than carrying local patches for long\n    durations.\n-   We will also actively engage members of the LLVM community in the Carbon\n    experiment and ensure they are able to participate where interested.\n-   Lastly, all Carbon code uses the same license as LLVM so that any of it can\n    be immediately merged into LLVM if useful to the broader project or\n    community.\n\n#### Labeled as vaporware\n\n-   We are intentionally moving public while Carbon is still very nascent.\n-   Many parts of the language still need to be built.\n-   We are front-loading design work heavily, which means we have designed\n    significantly more than is implemented.\n\nPlanned mitigations:\n\n-   Our communication around Carbon will be focused around _building_ the Carbon\n    experiment to emphasize both that it is _not_ yet even a complete\n    experiment, and that our goal is to get help shaping it rather than suggest\n    it is ready for evaluation.\n-   We also plan to have clear roadmaps and other artifacts that help give a\n    realistic and credible story around the path from where Carbon is to being a\n    more complete experiment.\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   Becoming a fully open project has always been a goal for the project.\n    -   Moving public will substantially broaden the feedback we get,\n        strengthening our community and directly furthering our goal of being an\n        welcoming and inclusive community.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   We need to ensure we can actively engage with users of different C++\n        codebases to effectively build a compelling interoperability and\n        migration story. This kind of broad engagement is only possible with a\n        public project.\n\n## Alternatives considered\n\n### Delay going public until we have working interop demonstrated\n\nAn appealing time to go public would be when we have a toolchain that implements\nthe core language design _and_ provides a demonstration of the banner feature of\nCarbon -- C++ interop -- working effectively. If we made this our top priority,\nwe expect we could complete this in the order of a year.\n\nAdvantages:\n\n-   Make the project much more \"real\" when people first learn of it, and avoid\n    the perception of it being vaporware.\n-   Avoids spending significant time and effort engaging with a large community\n    and industry when the project is new and small. That effort could be\n    directed at furthering the design and implementation.\n\nDisadvantages:\n\n-   It would be difficult or impossible to expand the group working on Carbon\n    significantly, which will at some point limit the rate at which we can\n    execute on the project.\n-   We would be have significantly less broad input on the design of Carbon\n    itself and especially of its C++ interop, risking that the design would not\n    actually address the needs of the broader industry.\n-   We wouldn't be able to build Carbon in the open and develop trust of the\n    community and industry.\n-   We wouldn't be able to involve the broader community and industry in the\n    design and development of Carbon, which might lessen both interest and\n    enthusiasm.\n-   We won't start to understand how broadly the industry is interested in the\n    Carbon direction until significantly more effort has been invested.\n\nThe desire to build Carbon in the open, develop strong trust with the community,\nand understand the breadth of industry interest outweigh the costs and risks of\nmaking Carbon public earlier.\n\n### Delay going public until Carbon is a compelling option for C++ developers to adopt\n\nWe could delay still further and build Carbon into a compelling and ready-to-use\nprogramming language before going public.\n\nAdvantages:\n\n-   This would in some ways be the most _efficient_ strategy, as it would keep\n    everyone working on Carbon focused without distraction.\n-   We would have the best possible first impression on developers by having a\n    largely complete and high quality language ready to go.\n\nDisadvantages:\n\n-   We still wouldn't know whether the experiment was a success -- both\n    developers and the industry at large might not be interested in Carbon. The\n    result is that this would have the maximum sunk cost at the point where we\n    begin to learn about the industry interest.\n-   It is unlikely we could sustain the effort required to reach this point\n    without any incremental milestones.\n-   We would likely have very little trust from the community due the prolonged\n    secrecy.\n-   Given the timeline, it is very likely that Carbon would leak and lose some\n    of the advantages.\n-   This would maximize the risk of some aspect of Carbon being designed in a\n    way that doesn't meet the larger industry needs due to a lack of feedback.\n    It also maximizes the cost of correcting this once discovered.\n\nThis has never been seen as a realistic approach for Carbon, and that doesn't\nseem to have changed. While it does have some advantages, the tradeoff seems\nsharply wrong for the needs of the Carbon project.\n"
  },
  {
    "path": "proposals/p1367.md",
    "content": "# Remove CODEOWNERS\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1367)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Current CODEOWNERS](#current-codeowners)\n    -   [CODEOWNERS issues](#codeowners-issues)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Group access controls](#group-access-controls)\n    -   [rm CODEOWNERS](#rm-codeowners)\n    -   [Auto-assignment](#auto-assignment)\n    -   [Stacked PRs](#stacked-prs)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Fine-grained CODEOWNERS](#fine-grained-codeowners)\n    -   [Broaden CODEOWNERS](#broaden-codeowners)\n\n<!-- tocstop -->\n\n## Problem\n\nWe want to restrict who can merge files, in particular to ensure reviews are\ndone.\n\nCurrently we use CODEOWNERS for this purpose. However, CODEOWNERS can lead to\nreview bottlenecks, creating possibly unnecessary hindrances to development, as\ndiscussed in the background.\n\n## Background\n\n### Current CODEOWNERS\n\nWe currently use, in brief:\n\n```CODEOWNERS\n*                   @carbon-language/implementation-team\n/*                  @carbon-language/implementation-team\n/*.md               @carbon-language/carbon-leads @carbon-language/implementation-team\n/docs/              @carbon-language/carbon-leads @carbon-language/implementation-team\n/proposals/         @carbon-language/carbon-leads\n/LICENSE            @carbon-language/carbon-leads\nCODEOWNERS          @carbon-language/carbon-leads\n```\n\n### CODEOWNERS issues\n\n[Issue #413: Consider removing CODEOWNERS -- at least for now](https://github.com/carbon-language/carbon-lang/issues/413)\nwas used to discuss this issue. This can lead to a few issues:\n\n-   CODEOWNERS defaults to assignment to the group, which can lead to a \"tragedy\n    of the commons\" situation where everybody expects someone else to review.\n    -   In assigning to the group, CODEOWNERS also makes for noisy PR\n        notifications.\n    -   Note both of these issues can be addressed with\n        [GitHub review settings](https://docs.github.com/en/organizations/organizing-members-into-teams/managing-code-review-settings-for-your-team).\n-   CODEOWNERS doesn't accurately handle the difference between a \"major\" change\n    and a \"minor\" change.\n    -   For example, a new proposal should only be approved by carbon-leads,\n        while a typo fix to a proposal would be fine for anyone to approve.\n    -   Decisions to make minor proposal edits more common, as in\n        [Issue #1009: Should doc edits maintain proposal links?](https://github.com/carbon-language/carbon-lang/issues/1009),\n        exacerbate this issue.\n\n## Proposal\n\nRemove CODEOWNERS, and instead use commit access to gate PRs.\n\n## Details\n\n### Group access controls\n\n-   Base: read (unchanged)\n    -   Should be the standard public permission.\n-   Contributors: \"contributor\" (previously write)\n    -   The \"Contributors\" group should be easy to get access to. On top of\n        read, this should include the ability to add/remove labels and projects\n        (may require some work to get right).\n    -   Versus \"triage\", \"triage\" seems to have powers including deleting\n        conversations, etc, that may not make sense for this group.\n-   Implementation team: write (unchanged)\n    -   For people expected to be reviewing commits.\n-   Moderators: triage\n    -   Includes\n        [separate GitHub moderation permissions](https://docs.github.com/en/communities/moderating-comments-and-conversations).\n-   Leads: maintain (unchanged)\n-   Admin team: admin (unchanged)\n\nFor people who have access, settings are at:\n\n-   [Organization repository roles](https://github.com/organizations/carbon-language/settings/roles)\n-   [Organization moderators](https://github.com/organizations/carbon-language/settings/moderators)\n-   [Repository collaborators and teams](https://github.com/carbon-language/carbon-lang/settings/access)\n\n### rm CODEOWNERS\n\nThis should only be done after group access controls are updated. Once done,\ngroup access controls are the last word on who can commit PRs.\n\n### Auto-assignment\n\nThis PR\n[introduces auto-assignment](https://github.com/carbon-language/carbon-lang/pull/1367/files#diff-5e5db53c34ec04ba9da95c70d5c797f1be9f390f7e2bf18ca3149cbd99c277df)\nin order to ensure PRs aren't lost. It provides categories of assignment, and a\nfallback for other PRs that don't have explicit assignment.\n\n### Stacked PRs\n\nAdvice for stacked PRs is no longer \"just ask an admin\"; it is \"commit access\nrequired\". This is because removing CODEOWNERS removes boundary between merge\naccess _to a feature branch_ and merge access _to trunk_.\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   The intent is to make it easier to get PRs reviewed and reduce\n        bottlenecks.\n\n## Alternatives considered\n\n### Fine-grained CODEOWNERS\n\nWe could keep the [current fine-grained CODEOWNERS](#current-codeowners). In\nthis setup, we would try to have specific directories owned by specific teams.\n\nWe've ended up on this path so far so that we have some mechanical enforcement\nof who's reviewing. We may need to change up the groups a little, but a\nreasonable long-term expectation would be something like a docs team, an\nexplorer team, a toolchain team, etc, with each owning their own files. For\nexample, /docs is owned only by the docs team, and there are people in the docs\nteam who aren't in other teams (and the other way around).\n\nAs previously mentioned, if we were using this option, we may want to change\n[GitHub review settings](https://docs.github.com/en/organizations/organizing-members-into-teams/managing-code-review-settings-for-your-team)\nin order to fix email/assignment.\n\nAdvantages:\n\n-   Relies on built-in GitHub CODEOWNERS featureset, intended for this purpose.\n    -   Can use built-in features for review assignment.\n-   Works with current stacked PR advice.\n\nDisadvantages:\n\n-   Retains team-specific bottlenecks: if none of a directory's owners are\n    available, other contributors cannot step in.\n    -   This could also be considered to be an advantage by some.\n-   GitHub's built-in features for review assignment are not as feature-rich as\n    some custom tooling.\n\nIt's mainly because of the relative inflexibility of CODEOWNERS that we aren't\ndoing this.\n\n### Broaden CODEOWNERS\n\nWe could broaden the CODEOWNERS to something basic, like a single group owning\neverything. Reviews in a particular area become best practice, not mechanically\nenforced.\n\nAdvantages:\n\n-   Simple to understand.\n    -   Avoids custom tooling.\n\nDisadvantages:\n\n-   We expect multiple subprojects within the carbon-lang repository, and this\n    approach would make it difficult to determine when to review a PR.\n    -   A large group means GitHub's built-in auto-assignment would assign to\n        arbitrary CODEOWNERS.\n    -   The [notification issues](#codeowners-issues) couldn't be addressed.\n\nThis option is likely worse for our purposes than\n[fine-grained CODEOWNERS](#fine-grained-codeowners).\n"
  },
  {
    "path": "proposals/p1382.md",
    "content": "# Rename `me` -> `self`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1382)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Don't change anything](#dont-change-anything)\n    -   [`this`](#this)\n\n<!-- tocstop -->\n\n## Problem\n\nWe've tried the `fn MethodName[me: Self]()` syntax for a while, and from our\nexperience the brevity of `me` is not worth doing something novel in this space.\nWe have found that `me` doesn't read well in practice.\n\n## Background\n\nThe current method syntax, including these choices, was decided in\nquestions-for-leads issue\n[#494: Method syntax](https://github.com/carbon-language/carbon-lang/issues/494)\nand implemented in proposal\n[#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722).\n\nLooking at other languages that use reserved word for the receiver value:\n\n| When       | Language   | Receiver when<br />accessing members | Receiver value | Receiver type |\n| ---------- | ---------- | ------------------------------------ | -------------- | ------------- |\n| 1983       | C++        | implicit                             | `this`         | ---           |\n| 1991       | Python     | explicit                             | `self`         | ---           |\n| 1995       | Java       | implicit                             | `this`         | ---           |\n| 1995       | JavaScript | explicit                             | `this`         | ---           |\n| 2000       | C#         | implicit                             | `this`         | ---           |\n| 2009       | Go         | explicit                             | (see below)    | ---           |\n| 2010       | Rust       | explicit                             | `self`         | `Self`        |\n| 2011       | Kotlin     | implicit                             | `this`         | ---           |\n| 2012       | TypeScript | explicit                             | `this`         | `this`        |\n| 2014       | Swift      | implicit                             | `self`         | `Self`        |\n| previously | Carbon     | explicit                             | `me`           | `Self`        |\n| proposed   | Carbon     | explicit                             | `self`         | `Self`        |\n\nIn detail:\n\n-   C++ uses\n    [`this` for address of the receiver value](https://en.cppreference.com/w/cpp/language/this).\n    C++23 includes\n    [an explicit `this` facility](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html).\n    Examples in the proposal frequently use `self` as the name of the parameter,\n    and `Self` as its type.\n-   Swift uses\n    [`self` for the receiver value](https://docs.swift.org/swift-book/LanguageGuide/Methods.html#ID238).\n    and\n    [`Self` for its type](https://docs.swift.org/swift-book/ReferenceManual/Types.html#ID610).\n-   Rust uses\n    [`self` for the receiver value](https://doc.rust-lang.org/std/keyword.self.html)\n    and\n    [`Self` for its type](https://doc.rust-lang.org/rust-by-example/fn/methods.html).\n-   C# uses\n    [`this` for a reference to the receiver value](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/this).\n-   Python as a convention uses `self` for the receiver value, but it's almost\n    universally followed.\n-   Go conventionally uses an abbreviation of the type name.\n\nSome history about the use of `self` in programming languages is documented in\n[this StackOverflow answer](https://stackoverflow.com/a/1080192/624900),\nincluding that `self` is also used in Smalltalk, Modula-3, Delphi/Object Pascal,\nand Objective-C.\n\n## Proposal\n\nUse `self` instead of `me` to be consistent with Swift and Rust.\n\n## Rationale\n\nThis is consistent with Carbon's goal to make\n[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\nby choosing a keyword for this role that is less surprising to users.\n\n## Alternatives considered\n\n### Don't change anything\n\nWe could stay with the status quo, which has the benefit that `me` is shorter\nthan `self`. There are two considerations:\n\n-   For accessing members of the current object, the chart in\n    [the background section](#background) shows plenty of precedent for\n    requiring a 4 character explicit keyword.\n-   We would also like to reduce ceremony when declaring the signature of a\n    method. For this concern, both `me: Self` and `addr me: Self*` are already\n    longer than what other languages use in practice. It would probably be\n    better to solve this problem with a shortcut approach like Rust\n    ([1](https://doc.rust-lang.org/book/ch05-03-method-syntax.html),\n    [2](https://doc.rust-lang.org/rust-by-example/fn/methods.html)), where\n    `&self` is short for `self: &Self` and `&mut self` is short for\n    `self: &mut Self`.\n\n### `this`\n\nWe could also switch to `this`, primarily to benefit\n[C++ users](https://en.cppreference.com/w/cpp/language/this). This had a few\ndisadvantages:\n\n-   We are worried that it frequently not being a pointer would be surprising to\n    those C++ users.\n-   As noted in [the background section](#background), C++23 code using explicit\n    this frequently uses the name `self`.\n-   We view it as an advantage to use the same spelling for the variable `self`\n    as for the type `Self`, and while `this` might make an acceptable name for\n    the object parameter, `Self` is much more strongly established as the name\n    for the current class, for example in PL research, and there is no precedent\n    for a type named `This`.\n"
  },
  {
    "path": "proposals/p1885.md",
    "content": "# `for` statement and user types\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1885)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Other languages](#other-languages)\n        -   [C++](#c)\n        -   [Python](#python)\n        -   [Rust](#rust)\n        -   [Typescript](#typescript)\n        -   [Go](#go)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [`for` with immutable values](#for-with-immutable-values)\n        -   [`Iterate` interface](#iterate-interface)\n        -   [`let` by default](#let-by-default)\n        -   [Lifetime of rvalues on right-hand side of `:`](#lifetime-of-rvalues-on-right-hand-side-of-)\n    -   [Use cases](#use-cases)\n        -   [Mutable and immutable elements](#mutable-and-immutable-elements)\n        -   [Random access containers](#random-access-containers)\n        -   [Maps, hash maps, and other containers](#maps-hash-maps-and-other-containers)\n        -   [R-value containers](#r-value-containers)\n        -   [Synthetic data](#synthetic-data)\n        -   [Large containers](#large-containers)\n        -   [Filtering, transforming, and reversing](#filtering-transforming-and-reversing)\n        -   [Interoperability with C++ types and containers](#interoperability-with-c-types-and-containers)\n-   [Future work](#future-work)\n    -   [`for` with mutable values](#for-with-mutable-values)\n    -   [Speculative mixin usage](#speculative-mixin-usage)\n        -   [Mutable values](#mutable-values)\n        -   [Alternative views](#alternative-views)\n    -   [Large elements and Optional](#large-elements-and-optional)\n    -   [C++ interoperability](#c-interoperability)\n        -   [Iterating over C++ types in Carbon](#iterating-over-c-types-in-carbon)\n        -   [Iterating over Carbon types in C++](#iterating-over-carbon-types-in-c)\n    -   [Inversion of control](#inversion-of-control)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Atomic methods for `Iterate`](#atomic-methods-for-iterate)\n    -   [Using an iterator instead of a cursor](#using-an-iterator-instead-of-a-cursor)\n    -   [Support getter for both `T` and `T*` with `Iterate`](#support-getter-for-both-t-and-t-with-iterate)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposes an interface that can be implemented by user types to support\nrange-based iteration with `for`.\n\n## Problem\n\nThe current `for` proposal does not define a way for types to support\nrange-based `for` loops.\n\nExamples of use cases for `for` loops include iterating over:\n\n-   Mutable and immutable elements\n-   Random access containers\n-   Maps, hash maps, and complex containers\n-   R-value containers\n-   Synthetic data\n-   Large containers, and large elements\n-   Filtering, transforming, and reversing\n-   Interoperability with C++ types and containers\n\nThe goals for the solution includes:\n\n-   Easy to support for user types, with minimal requirements\n-   Simple and clear usage\n-   Minimal performance overhead\n\n## Background\n\nThe original proposal of `for` loops were discussed in\n[p0353](/proposals/p0353.md), and the basic design documented in\n[control_flow/loops#for](/docs/design/control_flow/loops.md#for).\n\nThe resulting syntax was:\n\n> `for (` _var declaration_ `in` _expression_ `) {` _statements_ `}`\n\nWe now need a way to allow supporting this syntax for user and library container\ntypes.\n\n### Other languages\n\nThis section highlights some examples of how iterators and range-based for\nuser-defined types is addressed in different languages.\n\n#### C++\n\nC++ requires either `.begin()`/`.end()` methods, or\n`begin(<container>)`/`end(<container>)` to be supported for\n[range-based `for`](https://en.cppreference.com/w/cpp/language/range-for).\n\n#### Python\n\nPython requires 2 dunder methods, `__iter__` on the container and `__next__` on\nthe iterator, to be usable with a `for <element> in <container>:` construct.\n\n[Generator functions](https://peps.python.org/pep-0255/) act like iterators.\nThey are executed until the next `yield` statement, whose argument is returned\nas the next value to the `for` loop. Iteration ends when the function returns.\n\n```python\ndef generate_fibonacci():\n  yield 0;\n  n1, n2 = 0, 1;\n  while True:\n    n1, n2 = n2, n1+n2;\n    yield n1;\n\nfor n in generate():\n  print(n);\n```\n\n#### Rust\n\nRust supports iterating over a container with\n[for](https://doc.rust-lang.org/rust-by-example/flow_control/for.html) using\n\n-   ranges `for n in 1..100`\n-   iterators `for element in container.iter()` or `.iter_mut()`\n\nThe `Iterator` type can be used with custom types using the\n[following syntax](https://doc.rust-lang.org/rust-by-example/trait/iter.html)\n(though specific):\n\n```rust\nstruct Fibonacci {\n    curr: u32,\n    next: u32,\n}\n\nimpl Iterator for Fibonacci {\n    type Item = u32;\n    fn next(&mut self) -> Option<Self::Item> {\n        // calculate and yield value\n        [...]\n    }\n}\n\nfor i in fibonacci().take(4) {\n    ...\n}\n```\n\n#### Typescript\n\nTypescript uses the\n[`.iterator` property](https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html#iterables),\nalong with\n[two forms](https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html#forof-statements)\nof range-based for loops: `for..in` and `for..of`.\n\n```ts\nlet pets = new Set(['Cat', 'Dog', 'Hamster']);\npets['species'] = 'mammals';\nfor (let pet in pets) {\n    console.log(pet); // \"species\"\n}\nfor (let pet of pets) {\n    console.log(pet); // \"Cat\", \"Dog\", \"Hamster\"\n}\n```\n\nUsing the `.iterator` property, Typescript allow to lazily generate data easily\nusing functions, classes, or objects:\n\n```ts\nconst reverse = (arr) => ({\n    [Symbol.iterator]() {\n        let i = arr.length;\n        return {\n            next: () => ({\n                value: arr[--i],\n                done: i < 0,\n            }),\n        };\n    },\n});\n```\n\n#### Go\n\nGo does not officially support customizing `for` for user types.\n\n## Proposal\n\nProvide interfaces that can be implemented by user types to enable support for\nranged-for loops.\n\nWe propose:\n\n-   A new `Iterate` interface to support for loops\n-   Using a cursor-based approach\n-   Making the `for` loop value `let` by default, that is, non-reassignable\n\nBelow is a high-level example of this concept:\n\n```carbon\n// Add support for `for`\nclass MyRange {\n  impl as Iterate where .ElementType = i32 and .CursorType = i32 {\n    // Implement `Iterate`\n  }\n}\n// Usage\nlet my_range: MyRange = {...};\nfor (item: auto in my_range) {\n  // Do something with `item`\n}\n```\n\n## Details\n\n### `for` with immutable values\n\n#### `Iterate` interface\n\nThis proposal exposes a new `Iterate`. This interface:\n\n-   Relies on a cursor-based approach: minimize implementation effort for\n    developers, could support R-values.\n-   Expects an `ElementType` and `CursorType`.\n-   Combines \"advance\", \"get\", and \"bounds check\" into a single `Next(cursor)`\n    method that returns an optional value.\n\nThe `Iterate` interface is:\n\n```carbon\ninterface Iterate {\n  let ElementType:! type;\n  let CursorType:! type;\n  fn NewCursor[self: Self]() -> CursorType;\n  fn Next[self: Self](cursor: CursorType*) -> Optional(ElementType);\n}\n```\n\nA naive Carbon implementation of the for loop could be:\n\n```carbon\nvar cursor: range.(Iterate.CursorType) = range.(Iterate.NewCursor)();\nvar iter: Optional(range.(Iterate.ElementType)) = range.(Iterate.Next)(&cursor);\n\n// A. Possible implementation\nwhile (iter.HasValue()) {\n  ExecuteForBlock(iter.Get());\n  iter = container.(Iterate.Next)(&cursor);\n}\n\n// B. Possible alternative depending on the API for Optional(T):\nwhile (true) {\n  match (iter) {\n    case .None => { break; }\n    case .Some(let value: range.(Iterate.ElementType)) => {\n      ExecuteForBlock(value);\n      iter = container.(Iterate.Next)(&cursor);\n    }\n  }\n}\n```\n\nThe cursor tracks progression, and the `Next` method advances the cursor and\nreturns an `Optional` value. An empty `Optional` indicates that we have reached\nthe end.\n\nBelow is a sample implementation of that interface for a user type.\n\n```carbon\nclass MyIntContainer {\n  var data: ...\n  fn Size[self: Self]() -> i32 {\n      return 4;\n  }\n  impl as Iterate where .ElementType = i32 and .CursorType = i32 {\n    fn NewCursor[self: Self]() -> i32 { return 0; }\n    fn Next[self: Self](cursor: i32*) -> Optional(i32) {\n      // Advance and return value, or return empty\n      if (*cursor < self.Size()) {\n        let index: i32 = *cursor;\n        *cursor = index + 1;\n        return Optional(i32).Create(self.data[index]);\n      } else {\n        return Optional(i32).CreateEmpty();\n      }\n    }\n  }\n}\n```\n\nWhich can be used as follow:\n\n```carbon\nfn Main() -> i32 {\n  var container: MyIntContainer = {.data = (1, 2, 3, 4)};\n  // Implicit `let` value declaration\n  for (value: i32 in container) {\n    Print(\"{0}\", value);\n  }\n  return 0;\n}\n```\n\n#### `let` by default\n\nTo keep usage simple and non-surprising, we propose defaulting variable\ndeclarations to `let` declarations. This is consistent with function parameters\nand scrutinees for\n[pattern matching](https://github.com/carbon-language/carbon-lang/pull/2188),\nwhich are immutable by default.\n\n```carbon\n// Implicitly `let item: T`\nfor (item: T in my_range) {\n  // `item` cannot be reassigned\n}\n```\n\nThis default can be overridden by adding the `var` keyword:\n\n```carbon\nfor (var item: T in my_range) {\n  // `item` can be modified, but this will not modify `my_range`\n  // because it is a copy of the element with its own storage\n}\n```\n\n#### Lifetime of rvalues on right-hand side of `:`\n\nIt will be important to ensure that temporary entities on the right-hand side of\n`:` are alive during the execution of the `for` loop to prevent invalid memory\naccess (Note: this was only recently addressed for C++ by\n[P2644](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2644r0.pdf)).\nThis applies to Carbon and C++ interoperability.\n\n```carbon\n// Example using a temporary range, with `GetElements()` returning an object that implements `Iterate`\nfor (item: T in bucket.GetElements()) {\n  // We need to make sure the object is alive for the duration of the `for` loop\n}\n```\n\n### Use cases\n\nThis section covers the use cases highlighted in the introduction, and usage\nwith the proposed design.\n\n#### Mutable and immutable elements\n\nThis proposal covers strictly immutable elements, and proposes defaulting\nelement declaration to `let`, to minimize surprises and clarify the intent.\nMutable elements are mentioned in the [Future work](#future-work) section.\n\n#### Random access containers\n\nFor random access containers, the cursor would represent a numerical index,\nincremented within `Next()`.\n\n#### Maps, hash maps, and other containers\n\nBecause the cursor type is defined by the developer, and opaque to the user, it\ncould be a hashmap index, a string, or pointer to a node, without changing the\nusage for users.\n\nThe `ElementType` can be a tuple, such as a `(key, value)` for maps, or a single\nvalue. See [Future work][#future-work] for other examples.\n\n#### R-value containers\n\nR-values are likely to be limited in terms of addressing and mutation. The\nimpact is undefined until the\n[corresponding design](https://github.com/carbon-language/carbon-lang/pull/2006)\nis finalized.\n\nThe cursor approach used for `Iterate` has the slight advantage of not requiring\npointers (and addressing) for some container types. This may be beneficial as a\nfirst iteration, until the dependent design is updated, at which point we will\nhave to define how to handle this special case.\n\n#### Synthetic data\n\n`Next()` can be trivially implemented to return a single computed value\non-demand based on the cursor, without the need for storage. If the sequence is\ninfinite, `Next()` will never return an empty `Optional`, and the `for` loop\nwill continue until interrupted by the user.\n\n```carbon\nclass SquaredSequence {\n  impl as Iterate where .ElementType = i32 and .CursorType = i32 {\n    fn NewCursor[self: Self]() -> i32 { return -1; }\n    fn Next[self: Self](cursor: i32*) -> Optional(i32) {\n      // Advance and return computed value\n      *cursor = *cursor + 1;\n      return Optional(i32).Create((*cursor) * (*cursor));\n    }\n  }\n}\n```\n\n#### Large containers\n\nThe proposal does not present any limitation regarding large collections. The\ncursor can be adapted to the collection size, and no copy of the container\nshould occur both for immutable collections, and future mutable elements.\n\n#### Filtering, transforming, and reversing\n\nProvided the traversal order is the same, generic filters and transformers are\nsupported by implementing a proxy `Iterate` interface, internally or externally.\n\nThis example illustrates a simple proxy interface.\n\n```carbon\nclass BasicFilter(T:! Iterate) {\n  var seq: T*;\n  var value: T.ElementType;\n  impl as Iterate where .ElementType = T.ElementType and .CursorType = T.CursorType {\n    fn NewCursor[self: Self]() -> T.ElementType { return self.seq->NewCursor(); }\n    fn Next[self: Self](cursor: T.CursorType*) -> Optional(T.ElementType) {\n      var res: auto = self.seq->Next(cursor);\n      while (res.has_value() && res.get() == value) {\n        res = self.seq->Next(cursor);\n      }\n      return res;\n    }\n  }\n}\n\nfn Main() -> i32 {\n  let container: MyIntContainer = MyIntContainer.Create(0,1,0,2,3,0);\n  let no_zeros: BasicFilter(MyIntContainer) =\n      { .seq = &container, .value = 0 };\n  // Prints \"123\"\n  for (v: i32 in no_zeros) {\n    Print(\"{0}\", v);\n  }\n  return 0;\n}\n```\n\nOn the other hand, changing how the collection is traversed (for example\nreverse), requires internal knowledge about the data layout, and a custom\nimplementation. One approach for containers that support reverse iteration would\nbe to implement a different interface with a `Prev()` method. A proxy could be\nexposed to make it usable with `for` directly.\n\nBelow is an example of what such an interface could look like:\n\n```carbon\ninterface IterateBidirectional;\nclass ReverseProxy(T:! IterateBidirectional);\ninterface IterateBidirectional {\n  extends Iterate;\n  fn NewEndCursor[self: Self]() -> CursorType;\n  fn Prev[self: Self](cursor: CursorType*) -> Optional(ElementType);\n  final fn Reversed[self: Self]() -> ReverseProxy(Self);\n}\nclass ReverseProxy(T:! IterateBidirectional) {\n  var container: T;\n  impl as Iterate where .ElementType = T.ElementType and .CursorType = T.CursorType {\n    fn NewCursor[self: Self]() -> CursorType {\n      return self.container.NewEndCursor();\n    }\n    fn Next[self: Self](cursor: CursorType*) -> Optional(ElementType) {\n      return self.container.Prev(cursor);\n    }\n  }\n}\n\nfn IterateBidirectional.Reversed[self: Self]() -> ReverseProxy(Self) {\n  return {.container = self};\n}\n\n/// Usage\nclass MyContainer {\n  fn Create(...) { ... }\n  impl as Iterate ... { ... }\n  impl as IterateBidirectional ... { ... }\n}\nvar container: MyContainer = MyContainer.Create(...);\nfor (v: container.(Iterate.ElementType) in container.Reversed()) {...}\n```\n\n#### Interoperability with C++ types and containers\n\nThe cursor approach deviates from the C++ iterator approach, requiring some\nadaptation.\n\nGiven the current state of the design, C++ interoperability is yet to be\ndefined, and suggestions have been highlighted in the\n[Future work](#future-work) section.\n\n## Future work\n\n### `for` with mutable values\n\nSupporting mutable values could be achieved using a second interface that\nprovides a proxy or view for the data, exposing an `Iterate` interface with\n`ElementType*`\n\n```carbon\n// Object implementing `MutableIterate` returned by a function\nfor (p: T* in my_range.AddrRange()) {}\n```\n\nThe example `MutableIterate` interface below acts as a proxy for the collection,\nand implements our `Iterate` interface.\n\n```carbon\ninterface MutableIterate {\n  impl as Iterate;\n  alias ElementType = Iterate.ElementType;\n  let ProxyType:! Iterate where .ElementType = ElementType*\n      and .CursorType is ImplicitAs((Self as Iterate).CursorType);\n  fn AddrRange[addr self: Self*]() -> ProxyType;\n}\n\nclass MyIntContainer {\n  //...\n  impl as Iterate ...\n  external impl as MutateIterate where .ProxyType = Self {\n    ...\n  }\n}\n```\n\n### Speculative mixin usage\n\nMixins are currently in early design stages. This section highlights possible\nuses speculating on the final design. Some may include:\n\n-   Improved semantics for views compared to getter methods: no direct side\n    effect from using the view\n-   Facilitate code reuse, compared to reimplementing an interface\n-   Direct access to `self`, limiting needs for pointers and address resolution\n\n#### Mutable values\n\nNamed mixins, used as programmable members, could expose a view with mutable\nvalues:\n\n```carbon\n// Using a named mixin to expose mutable values\nfor (p: my_range.(Iterate.ElementType)* in my_range.mutable) {}\n```\n\nUsed in this way, this clarifies that this a view of the data, like an\nattribute, with no direct side effects, when compared to a method.\n\n#### Alternative views\n\nSimilarly, mixins could allow supporting other views into the container.\n\nFor example, maps could expose a view with \"key\" and \"value\" only, in addition\nto the default (key, value) tuple.\n\n```carbon\n// Using a named mixin to expose mutable values\nfor (k: my_dict.(Iterate.CursorType) in my_dict.keys) {}\n```\n\nAnd \"reversed\" view could also be used for reverse iteration:\n\n```carbon\n// Reversing\nfor (v: my_dict.(Iterate.ElementType) in my_dict.reversed) {}\n```\n\n### Large elements and Optional\n\nLarge elements would have a negative impact if the `Optional` cannot leverage\nunused bit patterns within the type, nor present a view instead of a copy.\n\nIf this proves difficult, we can let implementers of the container choose\nwhether to expose values or pointers to values. When electing to \"pointers to\nvalues\", an adapter can be provided to support transforming the range of\npointers into a range a values. This choice allows supporting either iteration\nover container r-values (`ElementType = T`), or efficient iteration\n(`ElementType = T*`), but not both. While acceptable as an intermediate\nsolution, a better alternative will be needed in the future.\n\n```carbon\nadapter IterateByValue(T:! Iterate where .CursorType impls Deref) for T {\n  impl as Iterate\n      where .CursorType = T.CursorType\n        and .ElementType = T.CursorType.(Deref.Result) {\n        ...\n  }\n}\n\n// Used like:\nvar frames: NetworkFramesContainerByPtr = ...\nfor (i: NetworkFrame in frames as IterateByValue(NetworkFramesContainerByPtr))\n{\n  ...\n}\n```\n\nAlternatively, we can allow the binding in the `for` loop to be an `addr`\npattern, implemented by calling into a separate interface on the container. This\nputs the choice of using values or pointers to values in the hands of the `for`\nloop author. While this deviates from the ergonomics of `let` (where the\ncompiler can choose to copy or alias the value depending on what is more\nefficient), this option would provide parity with C++ `for` loops (where the\nauthor chooses between value and reference).\n\n### C++ interoperability\n\n#### Iterating over C++ types in Carbon\n\nFor reference, range-based `for` loops in C++ requires:\n\n-   `begin()` and `end()` methods or free functions, and\n-   the type returned supports pre-increment `++`, indirection `*`, and\n    inequality `!=` operations\n\nSee [range-based for statement](https://eel.is/c++draft/stmt.iter#stmt.ranged)\nfor more details.\n\nA limitation of the approach proposed in this document is the need for\nadaptation to interoperate with the C++ iterator model. The adapter would be a\nCarbon type that satisfies the Cursor interface, implemented in terms of a C++\niterator.\n\n-   `NewCursor` providing the \"start iterator\" returned by `begin()`\n-   `Next` doing the \"increment, bounds check, and returning value\"\n\nTwo different approaches are identified:\n\n-   One is to have a templated `impl` of `Iterate`, for anything with the right\n    method signatures (`begin`, `end`, and so on)\n-   Another is a templated adapter that implements `Iterate` when requested\n\n```carbon\n// Template impl approach\ntemplate constraint CppIterator { ... }\ntemplate constraint CppContainer {\n  // Speculative\n  for_unique IteratorType: CppIterator;\n  fn begin() -> IteratorType;\n  fn end() -> IteratorType;\n}\nexternal impl forall [template T:! CppContainer] T as Iterate\n    where .CursorType = T.(CppContainer.IteratorType)\n      and .ElementType = .CursorType.ElementType {\n  fn NewCursor[self: Self]() -> CursorType {\n    return self.(CppContainer.begin)();\n  }\n  fn Next[self: Self](cursor: CursorType*) -> Optional(ElementType) {\n    if (*cursor == self.(CppContainer.end)()) {\n      return Optional(ElementType).MakeEmpty();\n    }\n    let value: ElementType = **cursor;\n    ++*cursor;\n    return Optional(ElementType).MakeValue(value);\n  }\n}\n// Used like:\nvar v: Cpp.std.vector(i32) = ...\nfor (i: i32 in v) { ... }\n```\n\n```carbon\n// Adapter approach\nadapter CppIterate(template T:! type) for T {\n  impl as Iterate\n      // Speculative syntax. Alternatively, a cursor type parameter\n      // would avoid the need for deduction.\n      where .CursorType = typeof(T.begin())\n        and .ElementType = .CursorType.(Deref.Result) {\n    fn NewCursor[self: Self]() -> CursorType {\n      return self.begin();\n    }\n    fn Next[self: Self](cursor: CursorType*) -> Optional(ElementType) {\n      if (*cursor == self.end()) {\n        return Optional(ElementType).MakeEmpty();\n      }\n      let value: ElementType = **cursor;\n      ++*cursor;\n      return Optional(ElementType).MakeValue(value);\n    }\n  }\n}\n// Used like:\nvar v: Cpp.std.vector(i32) = ...\nfor (i: i32 in v as CppIterate(Cpp.std.vector(i32))) { ... }\n```\n\nThese two options could allow interoperability with a compatible C++ type,\neither implicitly (template approach) or explicitly (adapter approach).\n\n#### Iterating over Carbon types in C++\n\nThere need to be `begin()` and `end()` methods or free functions accessible to\nC++ for any Carbon type that implements the `Iterate` interface, in addition to\noverloads of the `*`, `++`, and `!=` operators for the types returned.\n\nThe `Iterate` interface does not expose a way to have a cursor nor an iterator\nto the past-last element. An option would be to have `end()` return a predefined\ninvalid value, to satisfy iterator comparison when `Next()` returns an empty\n`Optional`.\n\nBelow is sample implementation to iterate on a Carbon `Iterate`. Note that we\nneed to copy and cache the last value, to allow for `*it` to be called. This\nputs a requirement on `ElementType` to be copyable for this interoperability to\nbe usable.\n\n```cpp\nnamespace Carbon {\n// A C++ input iterator for any type that implements the Carbon `Iterate` interface.\ntemplate <typename Iterate>\nclass IterateIterator {\n public:\n  // Returns an \"Invalid\" iterator representing `end()`\n  static auto Invalid(const Iterate& container) -> IterateIterator<Iterate> {\n    return IterateIterator<Iterate>(container, std::nullopt);\n  }\n\n  IterateIterator(const Iterate& container,\n                  std::optional<typename Iterate::CursorType> cursor)\n      : container_(&container), cursor_(cursor) {\n    if (cursor_) {\n      next();\n    }\n  }\n  IterateIterator(const IterateIterator& other)\n      : container_(other.container_), cursor_(other.cursor_),\n      value_(other) {}\n\n  auto operator*() const -> const typename Iterate::ElementType& {\n    assert(cursor_);\n    return value_;\n  }\n  auto operator++() -> IterateIterator<Iterate>& {\n    next();\n    return *this;\n  }\n  auto operator==(const IterateIterator<Iterate>& rhs) -> bool {\n    return container_ == rhs.container_ && cursor_ == rhs.cursor_;\n  }\n  auto operator!=(const IterateIterator<Iterate>& rhs) -> bool {\n    return !(*this == rhs);\n  }\n\n private:\n  void next() {\n    assert(cursor_);\n    if (const auto v = container_->Next(*cursor_); v) {\n      value_ = *std::move(v);\n    } else {\n      cursor_ = std::nullopt;\n    }\n  }\n\n  const Iterate* container_;\n  std::optional<typename Iterate::CursorType> cursor_;\n  typename Iterate::ElementType value_;\n};\n\n// The C++ side of a custom Carbon type implementing\n// `Iterate` with CursorType `C`, and ElementType `T`\n// could have `begin()` and `end()` methods defined as:\nclass MyIterateType {\n  // [...]\n  auto begin() -> IterateIterator<Iterate<C, T>> {\n    return IterateIterator<Iterate<C, T>>(*this, NewCursor());\n  }\n  auto end() -> IterateIterator<Iterate<C, T>> {\n    return IterateIterator<Iterate<C, T>>::Invalid(*this);\n  }\n};\n}  // namespace Carbon\n\n// Usage:\nCarbon::MyIterateType container;\nfor (auto s : container) { /*...*/ }\n```\n\n### Inversion of control\n\nUsing an `Optional` has downsides, discussed in the\n[\"alternatives considered\"](#alternatives-considered) section. A possible\napproach would be to invert the control of the `for` loop, by having the\ncontainer call in the `for` block for each value, passing the value as argument.\nThis would work similarly to [Python generator functions](#python).\n\nThis has the following advantages:\n\n-   Removes the need for an `Optional`, and the associated overheads, copies,\n    and unwrapping.\n-   No boundary checks needed at the `for` level\n-   Compatible with R-value containers\n\nLimitations:\n\n-   The context needed by the `for` body will needs to be available or provided\n-   No optimizer known to the team can reliably produce efficient code for this\n    construct.\n\n## Rationale\n\nThis proposal offers a first step to support a needed way to iterate using a\n`for` loop. More specifically:\n\n-   Requires a single interface to be implemented with a combined `Next` method,\n    uses cursors instead of their more complex iterator counterpart, and defines\n    loop values as `let` by default to be less error prone\n    ([Code that is easy to read, understand, and write](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)).\n-   Makes use of\n    [Library APIs only](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/principles/library_apis_only.md).\n\n## Alternatives considered\n\n### Atomic methods for `Iterate`\n\nAn option was to define methods such as `Get`, `Advance`, `IsAtEnd` on\n`Iterate`, instead of a unique `Next` methods. While being more atomic, the\nconcern is that these individual methods will all need to be called separately\nwhile iterating, while a single call to `Next` performs these three operations\ntogether, providing more opportunities for optimization.\n\nUsing a single operation to return an optional is also consistent with Rust’s\napproach.\n\nThe combined `Next` method forces us to return an `Optional`, which has\ndownsides:\n\n-   potential performance overhead to wrapping and unwrapping,\n-   storage overhead for `Optional` itself, and\n-   may require additional copying of the value wrapped.\n\nThose may be mitigated by leveraging unused bit patterns, passing a view of the\nvalue, or [inverting control](#inversion-of-control).\n\n### Using an iterator instead of a cursor\n\nThe iterator approach was considered but proved to have key limitations that a\ncursor approach does not have:\n\n-   It requires implementing 2 interfaces instead of 1, and is more complex due\n    to having the iteration logic separated from the container itself\n-   More difficult to harden or troubleshoot, compared to a cursor that allows\n    bounds checking in debug & hardened build modes\n-   Can pose problems with ranges that consumes their input (See Barry Revzin’s\n    \"take(5)\" presentation from C++Now 2023), when compared to a combined\n    `Next()` approach.\n-   Higher overhead\n-   Proves to be difficult to support for R-values\n\nOn the other hand, the cursor approach deviates more from C++ than iterator, and\nmay require some more effort for C++ interoperability.\n\n### Support getter for both `T` and `T*` with `Iterate`\n\nBecause some collections will be read-only, we want to separate mutable and\nimmutable interfaces. A single interface would force developers to implement or\nstub the mutable portion of the interface, even if it is not applicable.\n"
  },
  {
    "path": "proposals/p1891.md",
    "content": "# Are We Explorer Yet?\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1891)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [AreWeYet](#areweyet)\n    -   [Carbon Explorer Status Brainstorm](#carbon-explorer-status-brainstorm)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Are We Explorer Yet?](#are-we-explorer-yet-1)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Abstract\n\nIt is currently difficult to see the status of Carbon explorer and where effort\nis needed. We propose creating a AreWeYet-styled dashboard to address this.\n\n## Problem\n\nWhile the Carbon project has many published documents, it can be a challenge to\nget a high-level picture of work that has been done and work that remains to be\ndone. This can make it difficult to both track its progress and identify\ncontribution areas that will have the biggest impact. Left unchecked, this can\nlead to the team equivalent of micro-optimization where resources are deployed\nin a way that isn’t consistent with high-level goals.\n\n## Background\n\n### AreWeYet\n\nMozilla, a non-profit behind many Open Source projects, has created and utilized\nwhat is known as the AreWeYet meme as an approach to solve the aforementioned\nproblem. In this approach, a highly structured dashboard is built that\nsuccinctly states a goal, what its status is, and links to issues or other means\nto track subgoals.\n\nOne example is [“Are We XBL Still?”](https://bgrins.github.io/xbl-analysis/))\nwhich tracks a project to remove all XBL bindings from Firefox. The general\nformat is a question, “Are we X still?”, followed by a list of items that, when\ncomplete, means the answer to the question becomes yes. Other examples can be\nfound on Mozilla’s [Areweyet page](https://wiki.mozilla.org/Areweyet).\n\nThe success of this methodology has led to other projects, such as Rust,\nadopting it.\n\n### Carbon Explorer Status Brainstorm\n\nA portion of the June 29th, 2022 Carbon weekly sync was used as a brainstorming\nsession to identify both work that has been accomplished and work that remains\nfor the Carbon explorer tool. While a comprehensive snapshot in time, there\nwasn’t an explicit agreement on how to utilize this document or keep it updated\ngoing forward. This proposal is the logical next step in this work.\n\n## Proposal\n\nWe propose creating and utilizing an AreWeYet for the explorer project. The\nmethodology has already been successful elsewhere and we already have the data\ncollected for the explorer project. Although this proposal narrowly targets\nCarbon explorer, experience with this methodology may indicate value for its use\nelsewhere.\n\n## Details\n\nIn summary, we propose the creation of a new page on the carbon-lang Wiki called\n“Are We Explorer Yet?”, population of this page with results of the explorer\nstatus brainstorm, and the creation of issues for parts that are not complete.\n\nThe following section will be used as the basis for the “Are We Explorer Yet?”\npage. Items that are specifically out of scope for this AreWeYet are C++ interop\n(likely never a target for explorer), metaprogramming, parallel programming, and\ncoroutines. The last three are likely substantial enough to merit their own\nAreWeYet pages.\n\n### Are We Explorer Yet?\n\n-   ❌ Structured programming\n    -   ✅ While loops\n    -   ✅ Variable declarations\n    -   ❌ Variable initialization tracking\n    -   ❌ Returned var\n    -   ❌ Variadics\n-   ❌ User defined types\n    -   ✅ structs\n    -   ✅ classes\n    -   ❌ choice\n-   ✅ Alias system\n-   ❌ OO programming\n    -   ❌ Inheritance\n    -   ❌ Parameterized class methods w/ inheritance\n    -   ❌ Destructors\n    -   ✅ Methods\n    -   ✅ Static functions / Class functions\n-   ❌ Generic programming\n    -   ✅ Generic classes\n    -   ❌ Generic methods\n    -   ✅ Generic functions\n    -   ✅ Interfaces\n    -   ✅ Generic Interfaces\n    -   ✅ Impls\n    -   ✅ Generic Impls\n    -   ❌ Impl specialization\n    -   ❌ Templates\n-   ❌ Operator overloading\n    -   ✅ ==\n    -   ❌ /=\n    -   ❌ Other operators\n    -   ❌ Constraints\n    -   ✅ Implicit “as”\n-   ❌ Error handling\n-   ✅ Prelude\n    -   ✅ Print function\n-   ❌ Types\n    -   ✅ i32\n    -   ❌ Other integral types\n    -   ❌ Integral types as library types instead of native\n    -   ✅ Tuples\n    -   ✅ Pointer\n    -   ✅ Functions\n    -   ✅ Bool\n    -   ✅ String\n    -   ❌ Floating point types\n    -   ❌ Raw string literals\n-   ❌ Code organization\n    -   ❌ Mixins\n    -   ❌ Imports\n    -   ❌ Separate packages\n    -   ❌ Modules\n    -   ❌ Namespaces\n\n## Alternatives considered\n\nThe default alternative is status quo where carbon explorer progress isn’t being\ntracked from a high-level. Due to the problems outlined in the problems section,\nthis seems like an undesirable option.\n\nAnother alternative is to use github issue tags and come up with a custom search\nto see the outstanding issues. This has the benefit of being fully automated. On\nthe other hand, it would be difficult to get a hierarchical view which is useful\nto being able to grasp the big picture.\n"
  },
  {
    "path": "proposals/p1964.md",
    "content": "# Character literals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1964)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Types](#types)\n    -   [Operations](#operations)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [No distinct character types](#no-distinct-character-types)\n    -   [No distinct character literal](#no-distinct-character-literal)\n    -   [Supporting prefix declarations](#supporting-prefix-declarations)\n    -   [Allowing numeric escape sequences](#allowing-numeric-escape-sequences)\n    -   [Supporting formulations of grapheme clusters and non-code-point code-units](#supporting-formulations-of-grapheme-clusters-and-non-code-point-code-units)\n-   [Future Work](#future-work)\n    -   [UTF code unit types proposal](#utf-code-unit-types-proposal)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal specifies lexical rules for constant characters in Carbon:\n\nPut character literals in single quotes, like `'a'`. Character literals work\nlike numeric literals:\n\n-   Every different literal value has its own type.\n-   The literal itself doesn't have a bit width as a consequence. Instead,\n    variables use explicitly sized character types and character literals can be\n    converted to these types when representable.\n-   A character literal must contain exactly one code point.\n\nFollows the plan from open design idea\n[#1934: Character Literals](https://github.com/carbon-language/carbon-lang/issues/1934).\n\n## Problem\n\nCarbon currently has no lexical syntax for character literals, and only provides\nstring literals and numeric literals. We wish to provide a distinct lexical\nsyntax for character literals versus string literals.\n\nThe advantage of having an explicit character type fundamentally comes down to\ncharacters being represented as integers whereas strings are represented as\nbuffers. This will allow characters to have different operations, and be more\nfamiliar to use. For example:\n\n```\nif (c >= 'A' and c <= 'Z') {\n    c += 'a' - 'A';\n}\n```\n\nThe example above shows how we would be able to use operations similar to\nintegers. Being able to use the comparison operations and supporting arithmetic\noperations provides an intuitive approach to using characters. This allows us to\nremove unnecessary logic of type conversion and other control flow logic, that\nis needed to work with a single element string. See [Rationale](#rationale) for\nmore examples showing more appropriate use of characters over using strings.\n\n## Background\n\nCharacter Literals by definition is a type of literal in programming for the\nrepresentation of a single character's value within the source code of a\ncomputer program. Character literals between languages have some minor nuances\nbut are fundamentally designed for the same purpose. Languages that have a\ndedicated character data type generally include character literals, for example\nC++, Java, Swift to name a few. Whereas other languages that lack distinct\ncharacter type, like Python use strings of length one to serve the same purpose\na character data type. For more information see\n[Character Literals Wiki](https://en.wikipedia.org/wiki/Character_literal),\n[Character Literals DBpedia](https://dbpedia.org/page/Character_literal)\n\n## Proposal\n\nPut character literals in single quotes, like `'a'`. Character literals work\nlike numeric literals:\n\n-   Every different literal value has its own type.\n-   The literal itself doesn't have a bit width as a consequence. Instead,\n    variables use explicitly sized character types and character literals can be\n    converted to these types when representable. Follows the plan from #1934.\n-   A character literal will model single Unicode code points that have a single\n    concrete numerical representation. We will not be supporting other\n    formulations like code unit sequences or grapheme clusters as these will be\n    modeled with normal string literals.\n\n## Details\n\n-   A character literal is a sequence enclosed with single quotes delimiter ('),\n    of UTF-8 code units that must be a valid encoding. This matches\n    [the UTF-8 encoding of Carbon source files](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0142.md#character-encoding).\n-   A character literal must encode exactly one code point.\n-   It supports addition and subtraction, [as described below](#operations).\n-   Character literals will support the relevant subset of the backslash (`\\`)\n    escape sequences in string literals, including `\\t`, `\\n`, `\\r`, `\\\"`, `\\'`,\n    `\\\\`, `\\0`, and `\\u{HHHH...}`. See\n    [String Literals: Escape sequence](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0199.md#escape-sequences).\n    -   Escape sequences which would result in non-UTF-8 encodings or more than\n        one code point are not included.\n    -   The escape of an embedded newline is also excluded as it isn't expected\n        to be relevant for character literals.\n\nWe will not support:\n\n-   character literals that don't contain exactly one Unicode code point;\n-   multi-line literals;\n-   \"raw\" literals (using #'x'#);\n-   `\\x` escape sequences;\n-   character literals with a single quote (`'`) or back-slash (`\\`), except as\n    part of an escape sequence;\n-   empty character literals (`''`);\n-   a backslash followed by an (unescaped) newline;\n-   ASCII control codes (0...31), including whitespace characters other than\n    word space (tab, line feed, carriage return, form feed, and vertical tab),\n    except when specified with an escape sequence.\n\n### Types\n\nFor the time being, Carbon will support three character types: `Char8`,\n`Char16`, and `Char32`. These types are capable of representing both code units\nand code points. It’s important to note that the support for different\nUTF-encoding code unit types will be addressed in a separate proposal. Please\nrefer to the [UTF code unit types proposal](#utf-code-unit-types-proposal)for\nmore information on that topic.\n\nIn Carbon, the type `CharN` represents a character, where `N` corresponds to the\nbit size of the character type (`8`, `16`, or `32`). We will only allow\ncharacter literals that map directly to a complete value of a code point. Here\nare examples of character literals for each specific type:\n\n-   `Char8`: The character literal consists of a single Unicode code point that\n    can be represented within 8 bits. For example:\n\n`let allowed: Char8 = ‘a’ `\n\nIn this example, the character literal `’a’` corresponds to the Unicode code\npoint `97`, which is within the valid range of `Char8` since `97` is less than\nor equal to `0x7F`.\n\n-   `Char16`: The character literal represents a Unicode code point that can be\n    represented within 16 bits. Here’s an example:\n\n`let smiley: Char16 = ‘\\u{1F600}’`\n\nThe character literal `’\\u{1F600}’` represents the smiley face emoji, which has\nthe Unicode code point `128512`. Since `128512` can be represented within 16\nbits, it can be assigned to a variable of type `Char16`.\n\n-   `Char32`: This character type allows the representation of Unicode code\n    points within 32 bits. Here’s an example:\n\n`let musicalNote: Char32 = ‘🎵’`\n\nIn this case, the character literal `’🎵’` corresponds to the musical note emoji\nwith the Unicode code point `127925`. Since `127925` falls within the range that\ncan be represented by `Char32`, it can be assigned to a variable of type\n`Char32`.\n\nBy restricting character literals to those that can be directly mapped to code\npoints within the specific character types, we ensure accurate representation\nand compatibility with the chosen character encoding scheme.\n\n### Operations\n\nCharacter literals representing a single code point support the following\noperators:\n\n-   Comparison: `<`, `>`, `<=`, `>=` `==`\n-   Plus: `+`. This doesn't concatenate, but allows numerically adjusting the\n    value:\n    -   Only one operand may be a character literal, the other must be an\n        integer literal.\n    -   The result is the character literal whose numeric value is the sum of\n        numeric value of the operands. If that sum is not a valid Unicode code\n        point, it is an error.\n-   Subtract: `-`. This will subtract the value of the two characters, or a\n    character followed by an integer literal:\n    -   If the `-` is used between two character literals, the result will be an\n        integer constant. For example, `'z' - 'a'` is equivalent to `25`.\n    -   If the `-` is used between a character literal followed by a integer\n        literal, this will produce a character constant. For example `'z' - 4`\n        is equivalent to `'v'`.\n    -   If the `-` is used between a integer literal followed by a character\n        literal `100 - 'a'`, this will be rejected unless the integer is cast to\n        a character.\n\nThere is intentionally no implicit conversion from character literals to integer\ntypes, but explicit conversions are permitted between character literals and\ninteger types. Carbon will separate the integer types from character types\nentirely.\n\n## Rationale\n\nThis proposal supports the goal of making Carbon code\n[easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nAdding support for a specific character literal supports clean, readable,\nconcise use and is a much more familiar concept that will make it easier to\nadopt Carbon coming from other languages. Have a distinct character literal will\nalso allow us support useful operations designed to manipulate the literal's\nvalue. When working with an explicit character type we can use operators that\nhave unique behavior, for example say we wanted to advance a character to the\nnext literal. In other languages the `+` operator is often used for\nconcatenation, so using a `String` will produce a type error: `\"a\" + 1`. However\nwith a character literal, we can support operations for these use cases:\n\n```\nvar b: u8;\n\nb = 'a' + 1;\nb + 1 == 'c';\n```\n\nSee [Operations](#operations) and\n[No Distinct Character Literal](#no-distinct-character-literal) for more\ninformation.\n\nFurther, this design follows other standards set in place by previous proposals.\nFor example following the\n[String Literals: Escaping Sequence](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0199.md#escape-sequences-1)\nand representing characters as integers with the behaviour inline with\n[Integer Literals](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0143.md).\n\nThis also supports our goal for\n[Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\nby ensuring that every kind of character literal that exists in C++ can be\nrepresented in a Carbon character literal. This is done in a way that is natural\nto adopt, understand, easy to read by having explicit character types mapped to\nthe C++ character types and the correct associated encoding.\n\nFinally, the choice to use Unicode and UTF-8 by default reflects the Carbon goal\nto prioritize\n[modern OS platforms, hardware architectures, and environments](/docs/project/goals.md#modern-os-platforms-hardware-architectures-and-environments).\nThis reflects the\n[growing adoption of UTF-8](https://en.wikipedia.org/wiki/UTF-8#Adoption).\n\n## Alternatives considered\n\n### No distinct character types\n\nUnlike C++, Carbon will separate the integer and the character types. We\nconsidered using `u8`, `u16`, and `u32` instead of `Char8`, `Char16`, and\n`Char32` to reduce the number of different types users needed to be aware of and\nconvert between. We decided against it because it came with a number of\ndisadvantages:\n\n-   `u8`, `u16`, and `u32` have the wrong arithmetic semantics: we don't want\n    wrapping, and many `uN` operations, like multiplication, division, and\n    shift, are not meaningful on code units. There may be rare cases where you\n    want to use those operations, such as if you're implementing a conversion to\n    or from code units. But in those rare cases it would be reasonable for the\n    user to convert to an integer type to perform that operation and convert\n    back when done.\n-   Some operations want to be able to tell the difference between values that\n    are intended to be UTF-8 instead of having no specified encoding.\n-   Some operations want to be able to know that they've been given text rather\n    than random bytes of data. For example, `Print(0x41 as u8)` would be\n    expected to print `\"65\"` while `Print('\\u{41}')` and `Print(0x41 as Char8)`\n    would be expected to print `\"A\"`.\n-   It's useful for developers to document the intended meaning of a value, and\n    using a distinct type is one way to do that.\n\nSee [UTF code unit types proposal](#utf-code-unit-types-proposal) for more\ninformation about UTF encoding types for a future proposal.\n\n### No distinct character literal\n\nIn principle, a character literal can be represented by reusing string literals\nsimilar to how Python handles character literals, however this would prevent\nperforming operations on characters as integers. For example, the `+` operator\non strings is used for concatenation, but `+` on a character would change its\nvalue.\n\n```\n// `digit` must be in the range 0..9.\nfn DigitToChar(digit: i32) -> Char8 {\n  return '0' + digit;\n}\n```\n\nFurthermore, many properties of Unicode characters are defined on ranges of code\npoints, motivating supporting comparison operators on code points.\n\n```\nfn IsDingBatCodePoint(c: Char32) -> bool {\n  return c >= '\\u{2700}' and c <= '\\u{27BF}';\n}\n```\n\n### Supporting prefix declarations\n\nNo support is proposed for prefix declarations like `u`, `U`, or `L`. In\npractice they are used to specify the character literal types and their encoding\nin languages like C and C++. There are a several benefits to omitting prefix\ndeclarations; improved readablitly, simplifying how a character's type is\ndetermined, and how we are encoding character literals. When declaring a\ncharacter literal, the type is based on the contents of the character so that\n`var c: u8 = 'a'` is a valid character that can be converted to `u8`, in order\nto support prefix declarations we would need to extend our type system to have\nother explicit type checks like in C++; a UTF-16 `u'`, UTF-32 `U'`, and wide\ncharacters `L'`. This would be more familiar for individuals coming to Carbon\nfrom a C++ background, and simplify our approach for C++ Interoperability. At\nthe cost of diverge from existing standards, for example\n[Proposal 142](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0142.md#character-encoding)\nstates all of Carbon source code should be UTF-8 encoded. Prefix declarations\nwould detract the readability of the character literals and increase the\ncomplexity of character literal [Types](#types).\n\n### Allowing numeric escape sequences\n\nThis proposal does not support numeric escape sequences using `\\x`. This\nsimplifies the design of character types and literals, making them only\nrepresent code points and not code units. However this does come with the\ndisadvantage of less consistency of character literals with string literals,\nsince they now accept different escape sequences. We don't want to remove\nnumeric escape sequence from string literals, so we can support string use cases\nlike representing invalid encodings.\n\nThis approach has the additional concern that if character literals don't\nsupport numeric escape sequences, developers may choose to use numeric literals\ninstead, at a cost of type-safety and readability. For example, it isn't clear\nin `var first_digit: Char8 = 0;` whether `0` is supposed to be a `NUL` character\nor the encoding of the `'0'` character (48). We addressed this concern, and type\nsafety concerns about distinguishing numbers and characters, by making the\ninteger to character conversions explicit.\n\n### Supporting formulations of grapheme clusters and non-code-point code-units\n\nRather than explicitly limiting characters literals to a more integer-like\nrepresentation of a single Unicode code point, we could represent characters\nliteral formulations of grapheme clusters and non-code-point code units. What\nhumans tend to think of as a \"character\" corresponds to a \"grapheme cluster.\"\nThe encoding of a grapheme cluster can be arbitrarily long and complex, which\nwould sacrifice the ability to perform integer operations. If we wanted to add\nsupport for other character formulations, we would need to use separate\nspellings to represent a small set of operations that are today expressed with\ninteger-based math on C++'s character literals. This includes things like\nconverting an integer between 0 and 9 into the corresponding digit character, or\ncomputing the difference between two digits/two other characters. For these\nreasons, we have decided to start out by representing character literals as\nsingle Unicode code points following a more integer-like model. However this\ntopic should be revisited if we find that there is a significant need for the\nadditional functionality and attendant complexity for these other character\nformulations.\n\n## Future Work\n\n### UTF code unit types proposal\n\nThere have been several ideas and discussions around how we would like to handle\nUTF code units. This section will hopefully provide some guidance for a future\nproposal when the topic is revisited for how we would like to build out\nencoding/decoding for character literals.\n\nWe will have the types `Char8`, `Char16`, and `Char32` representing code units\nin UTF-8, UTF-16, and UTF-32, but we will not support all code units, but only\nthose which map directly to the complete value of a code point. However,\ncharacter literals will use their own types distinct from these:\n\n-   We will support value preserving implicit conversions from character\n    literals to code point or code unit types. In particular, a character\n    literal converts to a `Char8` UTF-8 code unit if it is less than or equal to\n    0x7F, and `Char16` UTF-16 code unit if it is less than or equal to 0xFFFF.\n-   Conversions from string or character literals to a non-value-preserving\n    encoding must be explicit.\n-   Conversions from string literals to Unicode strings are implicit, even\n    though the numeric values of the encoding may change.\n\nWe can see whether the particular literal is represented in the variable's type\nby only looking at the types.\n\n```\nlet allowed: Char8 = 'a';\n```\n\nThe above is allowed because the type of `'a'` is the character literal\nconsisting of the single Unicode code point 97, which can be converted to\n`Char8` since 97 is less than or equal to 0x7F.\n\n```\nlet error1: Char8 = '😃';\nlet error2: Char8 = 'AB';\n```\n\nHowever these should produce errors. The type of `'😃'` is the character literal\nconsisting of the single Unicode code point `0x1F603`, which is greater than\n0x7F. The type of `'AB'` is a character literal that is a sequence of two\nUnicode code points, which has no conversion to a type that only handles a\nsingle UTF-8 code unit.\n\nAll of `'\\n'`, and `'\\u{A}'` represent the same character and so have the same\ntype. However, explicitly converting this character literal to another character\nset might result in a character with a different value, but that still\nrepresents the newline character.\n"
  },
  {
    "path": "proposals/p1983.md",
    "content": "# Weaken digit separator placement rules\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/1983)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [3-digit decimal groupings](#3-digit-decimal-groupings)\n    -   [2-digit or 4-digit hexadecimal digit groupings](#2-digit-or-4-digit-hexadecimal-digit-groupings)\n    -   [Disallow digit separators in fractions](#disallow-digit-separators-in-fractions)\n\n<!-- tocstop -->\n\n## Abstract\n\n[Proposal #143: Numeric literals](/proposals/p0143.md) added digit separators\nwith strict rules for placement. It missed some use-cases. In order to address\nthis, remove placement rules for numeric literals.\n\n## Problem\n\nDigit separator placement rules are too strict:\n\n-   For integers, while the original proposal mentioned Indian digit groupings,\n    Chinese, Japanese, and Korean cultures use 4-digit groupings. This oversight\n    is likely due to the description on\n    [wikipedia](https://en.wikipedia.org/wiki/Decimal_separator#Digit_grouping):\n    \"but the delimiter commonly separates every three digits\".\n-   There are microformats where different placement rules may be desirable. See\n    [alternatives](#alternatives-considered) for more specific examples.\n\n## Background\n\n[Proposal #143: Numeric literals](/proposals/p0143.md) added digit separators\nwith strict rules for placement:\n\n-   For decimal integers, the digit separators shall occur every three digits\n    starting from the right. For example, `2_147_483_648`.\n-   For hexadecimal integers, the digit separators shall occur every four digits\n    starting from the right. For example, `0x7FFF_FFFF`.\n-   For real number literals, digit separators can appear in the decimal and\n    hexadecimal integer portions (prior to the period and after the optional `e`\n    or mandatory `p`) as described in the previous bullets. For example,\n    `2_147.483648e12_345` or `0x1_00CA.FEF00Dp+24`\n-   For binary literals, digit separators can appear between any two digits. For\n    example, `0b1_000_101_11`.\n\nThis was asked on\n[Issue #1485: Reconsider digit separators](https://github.com/carbon-language/carbon-lang/issues/1485),\nwhere a proposal was requested.\n\n## Proposal\n\nSwitch to simple rules: a single digit separator can appear between any two\ndigits. For example:\n\n-   Decimal literals: `1_2_3`\n-   Hexadecimal literals: `0xA_B_C`\n-   Real literals: `1_2.3_4e5_6`\n-   Binary literals are unaffected.\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   Removing restrictions on decimal literals provides flexibility for\n        developers who don't use 3-digit groupings.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   This allows for mistakes in groupings, which is undesirable. However,\n        it's useful for microformats to be able to provide their own particular\n        groupings.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Reduces migration hurdles for C++ code by providing a rule that's more\n        consistent with the C++ rule.\n\n## Alternatives considered\n\n### 3-digit decimal groupings\n\nFor decimal separators, we could enforce 3-digit groupings if digit separators\nare used at all.\n\nAdvantages:\n\n-   More enforcement of digit groupings can prevent bugs and misreadings\n    resulting from accidentally incorrect groupings.\n\nDisadvantages:\n\n-   Indian, Chinese, Japanese, and Korean digit grouping conventions don't fit\n    under this rule.\n    -   These are worth considering similar to how Carbon allows\n        [Unicode identifiers](/docs/design/lexical_conventions/words.md):\n        although keywords are in English, we can be more flexible for both\n        identifiers and literals.\n-   Microformats could also pose issues. For example, microseconds (`1_00000`),\n    dates (`01_12_1983`), credit cards (`1234_5678_9012_3456`), or identity\n    numbers such as US social security numbers (`123_45_6789`).\n    -   Since the original proposal, more cases have been raised.\n\nNote that any regular grouping rule can present similar issues for Indian digit\ngrouping conventions.\n\n[Proposal #143: Numeric literals](/proposals/p0143.md) chose 3-digit decimal\ngroupings.\n\nGiven there are overall advantages to not enforcing regular digit conventions,\nincluding for hex digits, it seems unnecessary to conform to the currently\nestablished decimal conventions. While this removes the enforcement, the\nresulting accidents are considered a reasonable risk.\n\nIn theory a code linter could be told to prefer certain formats with options to\nchange behavior, although that may remain too low benefit to implement.\n\n### 2-digit or 4-digit hexadecimal digit groupings\n\nHexadecimal digit groupings could be enforced along two axes:\n\n-   Every 2 (`F_FF`) or 4 (`F_FFFF`) characters, corresponding to one or two\n    bytes respectively.\n-   Regular or irregular placement. For example, if a digit separator is placed\n    every byte (every other digit), we could require regular placement every\n    byte as in `FF_FF_FF_FF`, or irregular as in `FF_FFFFF_FF` which skips one\n    placement.\n\n[Proposal #143: Numeric literals](/proposals/p0143.md) chose 4-digit with\nregular placement.\n\nAdvantages:\n\n-   More enforcement of digit groupings can prevent bugs and misreadings\n    resulting from accidentally incorrect groupings.\n\nDisadvantages:\n\n-   Again, microformats become an issue.\n    -   As noted in background, MAC addresses are typically in byte pairs\n        (`00_B0_D0_63_C2_26`) and UUIDs have particular groupings\n        (`123E4567_E89B_12D3_A456_426614174000`).\n-   If all of the other literal formats (decimal, real, and binary) allow\n    arbitrary digit separator placement, enforcing placement in hexadecimal\n    numbers would be an outlier.\n\nWhile it may be that enforcing 2 character (one byte) groupings with irregular\nplacement would prevent sufficient errors versus the developer inconvenience\nrisks, it risks becoming an outlier and for only very loose enforcement.\n\nSimilar to the preceding conclusion, leaving these issues to code linters may be\nbest.\n\n### Disallow digit separators in fractions\n\n[Proposal #143: Numeric literals](/proposals/p0143.md) appears to disallow digit\nseparators in fractions. That is, in `1.2345`, `1.23_45` is disallowed. This\nproposal changes that.\n\nAdvantages:\n\n-   Reduces the chance of confusion resulting from mistaking a `.` for another\n    `_` separator, as in `1_234_567.890_123_456`.\n\nDisadvantages:\n\n-   While sometimes commas aren't written for digit separators, it's notable\n    that SI advice is to use digit spacing instead\n    ([Digit spacing, rule #16](https://physics.nist.gov/cuu/Units/checklist.html)).\n    As a consequence, it's likely common to want some kind of digit separator\n    after the decimal point.\n-   Would create an inconsistency in placement rules.\n\nWe'll allow digit separators in fractions.\n"
  },
  {
    "path": "proposals/p2006.md",
    "content": "# Values, variables, pointers, and references\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2006)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n    -   [Conceptual integrity between local variables and parameters](#conceptual-integrity-between-local-variables-and-parameters)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Values, objects, and expressions](#values-objects-and-expressions)\n    -   [Patterns, `var`, `let`, and local variables](#patterns-var-let-and-local-variables)\n    -   [Pointers, dereferencing, and references](#pointers-dereferencing-and-references)\n    -   [Indexing](#indexing)\n    -   [`const`-qualified types](#const-qualified-types)\n    -   [Interop with `const &` and `const` methods](#interop-with-const--and-const-methods)\n    -   [Customization](#customization)\n-   [Rationale](#rationale)\n    -   [Contrasting the rationale for pointers with `goto`](#contrasting-the-rationale-for-pointers-with-goto)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Value expression escape hatches](#value-expression-escape-hatches)\n    -   [References in addition to pointers](#references-in-addition-to-pointers)\n    -   [Syntax-free or automatic dereferencing](#syntax-free-or-automatic-dereferencing)\n        -   [Syntax-free address-of](#syntax-free-address-of)\n    -   [Exclusively using references](#exclusively-using-references)\n    -   [Alternative pointer syntaxes](#alternative-pointer-syntaxes)\n        -   [Pointer type alternative syntaxes](#pointer-type-alternative-syntaxes)\n        -   [Pointer dereference syntax alternatives](#pointer-dereference-syntax-alternatives)\n        -   [Pointer syntax conclusion](#pointer-syntax-conclusion)\n    -   [Alternative syntaxes for locals](#alternative-syntaxes-for-locals)\n    -   [Make `const` a postfix rather than prefix operator](#make-const-a-postfix-rather-than-prefix-operator)\n-   [Appendix: background, context, and use cases from C++](#appendix-background-context-and-use-cases-from-c)\n    -   [`const` references versus `const` itself](#const-references-versus-const-itself)\n    -   [Pointers](#pointers)\n    -   [References](#references)\n        -   [Special but critical case of `const T&`](#special-but-critical-case-of-const-t)\n        -   [R-value references and forwarding references](#r-value-references-and-forwarding-references)\n        -   [Mutable operands to user-defined operators](#mutable-operands-to-user-defined-operators)\n        -   [User-defined dereference and indexed access syntax](#user-defined-dereference-and-indexed-access-syntax)\n        -   [Member and subobject accessors](#member-and-subobject-accessors)\n        -   [Non-null pointers](#non-null-pointers)\n        -   [Syntax-free dereference](#syntax-free-dereference)\n\n<!-- tocstop -->\n\n## Abstract\n\nIntroduce a concrete design for how Carbon values, objects, storage, variables,\nand pointers will work. This includes fleshing out the design for:\n\n-   The expression categories used in Carbon to represent values and objects,\n    how they interact, and terminology that anchors on their expression nature.\n-   An expression category model for readonly, abstract values that can\n    efficiently support input to functions.\n-   A customization system for value expression representations, especially as\n    seen on function boundaries in the calling convention.\n-   An expression category model for references instead of a type system model.\n-   How patterns match different expression categories.\n-   How initialization works in conjunction with function returns.\n-   Specific pointer syntax, semantics, and library customization mechanisms.\n-   A `const` type qualifier for use when the value expression category system\n    is too abstracted from the underlying objects in storage.\n\n## Problem\n\nCarbon needs a design for how values, variables, objects, pointers, and\nreferences work within the language. These designs are heavily interdependent\nand so they are presented together here. The design also needs to provide a\ncompelling solution for a wide range of use cases in the language:\n\n-   Easy to use, and use correctly, function input and in/out parameters.\n-   Clear separation of read-only use cases like function inputs from mutable\n    use cases.\n-   Local names bound both to fixed values and mutable variables.\n-   Indirect (and mutable) access to objects (by way of pointers or references).\n-   Extensible models for dereferencing and indexing.\n-   A delineated method subset which forms the API for read-only or input\n    objects.\n-   A delineated method subset which forms the APIs for indirect access to\n    shared objects in thread-compatible ways.\n-   Interoperation between function input parameters and C++ `const &`\n    parameters.\n-   Complex type designs which expose both interior pointers and exterior\n    pointers transparently for extended dereferencing or indexing.\n\n### Conceptual integrity between local variables and parameters\n\nAn additional challenge that this design attempts to address is retaining the\nconceptual integrity between local variables and parameters. Two of the most\nfundamental refactorings in software engineering are _inlining_ and _outlining_\nof regions of code. These operations introduce or collapse one of the most basic\nabstraction boundaries in the language: functions. These refactorings translate\nbetween local variables and parameters in both directions. In order to ensure\nthese translations are unsurprising and don't face significant expressive gaps\nor behavioral differences, it is important to have strong semantic consistency\nbetween local variables and function parameters. While there are some places\nthat these need to differ, there should be a strong overlap of the core\nfacilities, design, and behavior.\n\n## Background\n\nMuch of this is informed by the experience of working with increasingly complex\n\"value categories\" (actually categorizing expressions) and parameter passing in\nC++ and how the language arrived there. Some background references on this area\nof C++ and the problems encountered:\n\n-   https://en.cppreference.com/w/cpp/language/value_category\n-   http://wg21.link/basic.lval\n-   https://www.scs.stanford.edu/~dm/blog/decltype.html\n-   https://medium.com/@barryrevzin/value-categories-in-c-17-f56ae54bccbe\n-   http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-conventional\n-   https://www.youtube.com/watch?v=Tz5drzXREW0\n\nI've also written up a detailed walk-through of the different use cases and\nconsiderations that touch on the space of values, references, function inputs,\nand more across C++ in an\n[appendix](#appendix-background-context-and-use-cases-from-c).\n\nLeads questions which informed the design proposed here:\n\n-   [What syntax should we use for pointer types? (#523)][#523]\n\nIt also builds on the design of the proposal [\"Initialization of memory and\nvariables\"][p0257] ([#257]), implementing part of [#1993].\n\n[#257]: https://github.com/carbon-language/carbon-lang/pull/257\n[#523]: https://github.com/carbon-language/carbon-lang/issues/523\n[#1993]: https://github.com/carbon-language/carbon-lang/issues/1993\n[p0257]: /proposals/p0257.md\n\n## Proposal\n\nThis section provides a condensed overview of the proposal. The details are\ncovered in the updated content in the design, and each section links into the\nrelevant content there. While this overview both duplicates and summarizes\ncontent, it isn't intending anything different from the updates to the design\ncontent, and the design content should be considered authoritative as it will\nalso continue to be maintained going forward.\n\n### Values, objects, and expressions\n\nCarbon has both abstract _values_ and concrete _objects_. Carbon _values_ are\nthings like `42`, `true`, and `i32` (a type value). Carbon _objects_ have\n_storage_ where values can be read and written. Storage also allows taking the\naddress of an object in memory in Carbon.\n\nBoth objects and values can be nested within each other. For example\n`(true, true)` is both a value and also contains two sub-values. When a\ntwo-tuple is stored somewhere, it is both a tuple-typed object and contains two\nsubobjects.\n\n> Details:\n> [Values, objects, and expressions](/docs/design/values.md#values-objects-and-expressions)\n\nExpressions are categorized in a way that explains how they produce values or\nrefer to objects:\n\n-   [_Value expressions_](/docs/design/values.md#value-expressions) produce\n    abstract, read-only _values_ that cannot be modified or have their address\n    taken.\n-   [_Reference expressions_](/docs/design/values.md#reference-expressions)\n    refer to _objects_ with _storage_ where a value may be read or written and\n    the object's address can be taken.\n    -   [_Durable reference expressions_](/docs/design/values.md#durable-reference-expressions)\n        are reference expressions which cannot refer to _temporary_ storage, but\n        must refer to some storage that outlives the full expression.\n    -   [_Ephemeral reference expressions_](/docs/design/values.md#ephemeral-reference-expressions)\n        are reference expressions which _can_ refer to temporary storage.\n-   [_Initializing expressions_](/docs/design/values.md#initializing-expressions)\n    which require storage to be provided implicitly when evaluating the\n    expression. The expression then initializes an object in that storage. These\n    are used to model function returns, which can construct the returned value\n    directly in the caller's storage.\n\n> Details: [Expression categories](/docs/design/values.md#expression-categories)\n\n### Patterns, `var`, `let`, and local variables\n\nPatterns are by default _value patterns_ and match _value expressions_, but can\nbe introduced with the `var` keyword to create a _variable pattern_ that has\n_storage_ and matches _initializing expressions_. Names bound in value patterns\nbecome value expressions, and names bound in a variable pattern become _durable\nreference expressions_ referring to an object in that pattern's storage.\n\nLocal patterns can be introduced with `let` to get the default behavior of a\nreadonly pattern, or they can be directly introduced with `var` to form a\nvariable pattern and declare mutable local variables.\n\n> Details:\n> [Binding patterns and local variables with `let` and `var`](/docs/design/values.md#binding-patterns-and-local-variables-with-let-and-var)\n\n### Pointers, dereferencing, and references\n\nPointers in Carbon are the primary mechanism for _indirect access_ to storage\ncontaining some object. Dereferencing a pointer forms a\n[_durable reference expression_](/docs/design/values.md#durable-reference-expressions)\nto the object.\n\nCarbon pointers are heavily restricted compared to C++ pointers -- they cannot\nbe null and they cannot be indexed or have pointer arithmetic performed on them.\nCarbon will have dedicated mechanisms that still provide this functionality, but\nthose are future work.\n\n> Details: [Pointers](/docs/design/values.md#pointers)\n\nThe syntax for working with pointers is similar to C++:\n\n```carbon\nvar i: i32 = 42;\nvar p: i32* = &i;\n\n// Form a reference expression `*p` and assign `13` to the referenced storage.\n*p = 13;\n```\n\n> Details:\n>\n> -   [Pointer syntax](/docs/design/values.md#pointer-syntax)\n> -   [Pointer operators](/docs/design/expressions/pointer_operators.md)\n\nCarbon doesn't have reference types, just reference expressions. API designs in\nC++ that use references (outside of a few common cases like `const &` function\nparameters) will typically use pointers in Carbon. The goal is to simplify and\nfocus the type system on a primary model of indirect access to an object.\n\n> Details: [Reference types](/docs/design/values.md#reference-types)\n\n### Indexing\n\nCarbon supports indexing that both accesses directly contained storage like an\narray and indirect storage like C++'s `std::span`. As a result, the exact\ninterfaces used for indexing reflect the expression category of the indexed\noperand and the specific interface its type implements. This proposal just\nupdates and refines this design with the new terminology.\n\n> Details: [Indexing](/docs/design/expressions/indexing.md)\n\n### `const`-qualified types\n\nCarbon provides the ability to qualify a type `T` with the keyword `const` to\nget a `const`-qualified type: `const T`. This is exclusively an API-subsetting\nfeature in Carbon -- for more fundamentally \"immutable\" use cases, value\nexpressions and bindings should be used instead. Pointers to `const`-qualified\ntypes in Carbon provide a way to reference an object with an API subset that can\nhelp model important requirements like ensuring usage is exclusively by way of a\n_thread-safe_ interface subset of an otherwise _thread-compatible_ type.\n\n> Details:\n> [`const`-qualified types](/docs/design/values.md#const-qualified-types)\n\n### Interop with `const &` and `const` methods\n\nCarbon makes value expressions interoperable with `const &` function parameters.\nThere are two dangers of this approach:\n\n-   Those constructs in C++ _do_ allow the address to be taken, so Carbon will\n    synthesize an object and address for value expressions for the duration of\n    the C++ call as needed. C++ code already cannot rely on the address of\n    `const &` parameters continuing to exist once the call completes.\n-   C++ also allows casting away `const`. However, this doesn't allow a method\n    to safely _mutate_ a `const &` parameter, except its `mutable` members.\n\nIn both cases, correct C++ code should already respect the limitations Carbon\nneeds for this interop. The same applies to the implicit `this` parameter of\n`const` methods in C++.\n\n> Details:\n> [Interop with C++ `const &` and `const` methods](/docs/design/values.md#interop-with-c-const--and-const-methods)\n\n### Customization\n\nCarbon will provide a way to customize the implementation representation of a\nvalue expression by nominating some other type to act as its representation.\nThis will be indicated through an explicit syntactic marker in the class\ndefinition, and will require the type to `impl` a customization interface\n`ReferenceImplicitAs` to provide the needed functionality. The result will be to\nform this custom type when forming a value expression from a reference\nexpression, and will restrict the operations on such a value expression to\nimplicitly converting to the nominated type.\n\n> Details:\n> [Value representation and customization](/docs/design/values.md#value-representation-and-customization)\n\nCarbon will also allow customizing the behavior of a dereference operation on a\ntype to allow building \"smart pointers\" or other pointer-like types in the\nlibrary. This will be done in a similar fashion to overloading other operators,\nwhere the overloaded operation returns some other pointer that is then\ndereferenced to form a reference expression.\n\n> Details:\n> [Dereferencing customization](/docs/design/values.md#dereferencing-customization)\n\n## Rationale\n\n-   Pointers are a fundamental components of all modern computer hardware --\n    they are abstractly random-access machines -- and being able to directly\n    model and manipulate this is necessary for\n    [performance-critical software](/docs/project/goals.md#performance-critical-software).\n-   Simplifying the type system by avoiding both pointers and references is\n    expected to make\n    [code easier to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n-   Creating space in both the syntax and type system to introduce ownership and\n    lifetime information is important to be able to address long term\n    [safety](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    needs.\n-   Pointers are expected to be deeply familiar to C++ programmers and easily\n    [interoperate with C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\n\n### Contrasting the rationale for pointers with `goto`\n\nThere is an understandable concern about Carbon deeply incorporating pointers\ninto its design -- pointers in C and C++ have been the root of systematic\nsecurity and correctness bugs. There is an amazing wealth of \"gotchas\" tied to\npointers that it can seem unreasonable to build Carbon on top of these\nfoundations. By analogy, the `goto` control-flow construct is similarly\nconsidered _deeply_ problematic and there is a wealth of literature in computer\nscience and programming language design on how and why to build languages on top\nof structured control flow instead. It would be very concerning to build `goto`\ninto the fundamental design of Carbon as an integral and pervasive component of\nits control flow. However, there are two important distinctions between pointers\nand `goto`.\n\nFirst, C and C++ pointers are _very_ different from Carbon pointers, and their\nrightly earned reputation as a source of bugs and confusion stems precisely from\nthese differences:\n\n-   C pointers can be null, the [\"billion dollar mistake\"][null-mistake],\n    Carbon's cannot be. Carbon requires null-ness to be explicitly modeled in\n    the type system and dealt with prior to dereference.\n-   C pointers can be indexed even when not pointing to an array. Carbon's\n    pointers are to singular objects. Carbon handles indexing with a separate\n    construct and types to distinguish arrays where indexing is semantically\n    meaningful from the cases where it is not.\n-   C pointers support deeply surprising indexing patterns such as `3[pointer]`.\n    Carbon restricts to unsurprising indexing.\n-   C pointers don't enforce lifetime or any other memory safety properties.\n    While Carbon does not yet support these deeper protections, tackling memory\n    safety is an explicit plan of Carbon's and may yet result in changes to the\n    pointer type to reflect the safety risks posed by them.\n\n[null-mistake]:\n    https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/\n\nWhile these are described in terms of C's pointers, C++ inherits these without\nmeaningful improvement from C. The core point here is that while Carbon is\nbuilding pointers into its foundations, it is building in the least problematic\nand most useful aspect of pointers and leaving almost all of the legacy and risk\nbehind. That is a critical part of what makes pointers viable in Carbon.\n\nThe second important contrast with `goto` is the lack of a comprehensive\nalternative to pointers. Structured control flow has been thoroughly studied and\nshown to address the practical needs of expressing control flow. As a\nconsequence, we have _good_ tools to replace `goto` within languages, and we\nshould use them. In contrast, Carbon programs are still expected to map onto\n[von Neumann architecture](https://en.wikipedia.org/wiki/Von_Neumann_architecture)\nmachines and need to model the fundamental construct of a pointer to data. We\nhave no comprehensive alternative to solve all of the practical needs\nsurrounding indirect access to data on such an architecture.\n\nSo despite including pointers as one of the building blocks of Carbon, we don't\nneed for `goto` to be the surfaced and visible building block of Carbon's\ncontrol flow. Even if we decide to support some limited forms of `goto` to\nhandle edge cases where structured constructs end up suboptimal, we can still\nbuild the foundations in a structured way without impairing the use of Carbon to\nwork with the low-level hardware effectively.\n\n## Alternatives considered\n\n### Value expression escape hatches\n\nWe could provide escape hatches for value expressions that (unsafely) take the\naddress or even perform mutations through a value expression. This would more\neasily match patterns like `const_cast` in C++. However, there seem to be\neffective ways of rewriting the code to avoid this need so this proposal\nsuggests not adding these escape hatches now. We will instead provide a more\nlimited escape exclusively for\n[interop](#interop-with-const--and-const-methods). We can add more later if\nexperience proves this is an important pattern to support without the\ncontortions of manually creating a local copy (or changing to pointers).\n\n### References in addition to pointers\n\nThe primary and most obvious alternative to the design proposed here is the one\nused by C++: have _references_ in addition to pointers in the type system. This\ninitially allows zero-syntax modeling of L-values, which can in turn address\nmany use cases here much as they do in C++. Similarly, adding different kinds of\nreferences can allow modeling more complex situations such as different lifetime\nsemantics.\n\nHowever, this approach has two fundamental downsides. First, it would add\noverall complexity to the language as references don't form a superset of the\nfunctionality provided by pointers -- there is still no way to distinguish\nbetween the reference and the referenced object. This results in confusion where\nreferences are understood to be syntactic sugar over a pointer, but cannot be\ntreated as such in several contexts.\n\nSecond, this added complexity would reside exactly in the position of the type\nsystem where additional safety complexity may be needed. We would like to leave\nthis area (pointers and references to non-local objects) as simple and minimal\nas possible to ease the introduction of important safety features going forward\nin Carbon.\n\n### Syntax-free or automatic dereferencing\n\nOne way to make pointers behave very nearly the same as references without\nadding complexity to the type system is to automatically dereference them in the\nrelevant contexts. This can, if done carefully, preserve the ability to\ndistinguish between the pointer and the pointed-to object while still enabling\npointers to be seamlessly used without syntactic overhead as L-values.\n\nThis proposal does not currently provide a way to dereference with zero syntax,\neven on function interface boundaries. The presence of a clear level of\nindirection can be an important distinction for readability. It helps surface\nthat an object that may appear local to the caller is in fact escaped and\nreferenced externally to some degree. However, it can also harm readability by\nforcing code that doesn't _need_ to look different to do so anyway. In the worst\ncase, this can potentially interfere with being generic. Currently, Carbon\nprioritizes making the distinction here visible.\n\nReasonable judgement calls about which direction to prefer may differ, but\nCarbon's principle of\n[preferring lower context sensitivity](/docs/project/principles/low_context_sensitivity.md)\nleans (slightly) toward explicit dereferencing instead. That is the current\nproposed direction.\n\nIt may prove desirable in the future to provide an ergonomic aid to reduce\ndereferencing syntax within function bodies, but this proposal suggests\ndeferring that in order to better understand the extent and importance of that\nuse case. If and when it is considered, a direction based around a way to bind a\nname to a reference expression in a pattern appears to be a promising technique.\nAlternatively, there are various languages with implicit- or\nautomatic-dereference designs that might be considered in the future such as\nRust.\n\n#### Syntax-free address-of\n\nA closely related concern to syntax-free dereference is syntax-free address-of.\nHere, Carbon supports one very narrow form of this: implicitly taking the\naddress of the implicit object parameter of member functions. Currently that is\nthe only place with such an implicit affordance. It is designed to be\nsyntactically sound to extend to other parameters, but currently that is not\nplanned as we don't yet have enough experience to motivate it and it may prove\nsurprising.\n\n### Exclusively using references\n\nWhile framed differently, this is essentially equivalent to automatic\ndereferencing of pointers. The key is that it does not add both options to the\ntype system but addresses the syntactic differences separately and uses\ndifferent operations to distinguish between the reference and the referenced\nobject when necessary.\n\nThe same core arguments against automatic dereferencing applies equally to this\nalternative -- this would remove the explicit visual marker for where non-local\nmemory is accessed and potentially mutated.\n\n### Alternative pointer syntaxes\n\nThe syntax both for declaring a pointer type and dereferencing a pointer has\nbeen extensively discussed in the leads question [#523].\n\n[#523]: https://github.com/carbon-language/carbon-lang/issues/523\n\nThe primary sources of concern over a C++-based syntax:\n\n1.  A prefix dereference operator composes poorly with postfix and infix\n    operations.\n\n    -   This is highlighted by the use of `->` for member access due to the poor\n        composition with `.`: `(*pointer).member`.\n\n2.  Even without replicating the [\"inside out\"][inside-out] C/C++ challenges, we\n    would end up with a prefix, postfix, and infix operator `*`.\n\n[inside-out]:\n    https://faculty.cs.niu.edu/~mcmahon/CS241/Notes/reading_declarations.html\n\nThe second issue was resolved in [#520], giving us at least the flexibility to\nconsider `*` both for dereference and pointer type, but we still considered\nnumerous alternatives given the first concerns. These were discussed in detail\nin a [document][pointer-syntax-doc] but the key syntax alternatives are\nextracted with modern syntax below.\n\n[pointer-syntax-doc]:\n    https://docs.google.com/document/d/1gsP74fLykZBCWZKQua9VP0GnQcADCkn5-TIC1JbUvdA/edit?resourcekey=0-8MsUybUvHDCuejrzadrbMg\n\n#### Pointer type alternative syntaxes\n\n**Postfix `*`:**\n\n```\nvar p: i32* = &i;\n```\n\nAdvantages:\n\n-   Most familiar to C/C++ programmers\n    -   Doesn't collide with prefix `*` for dereference so can have that\n        familiarity as well.\n\nDisadvantages:\n\n-   Requires the [#520] logic to resolve parsing ambiguities.\n-   Visually, `*` is used for both pointers and multiplication.\n-   Interacts poorly with prefix array type syntaxes.\n-   Looks like a C++ pointer but likely has different semantics.\n\n**Prefix `*`:**\n\n```\nvar p: *i32 = &i;\n```\n\nAdvantages:\n\n-   Used by Rust, Go, Zig,\n    [Jai](https://github.com/BSVino/JaiPrimer/blob/master/JaiPrimer.md#memory-management).\n-   Go in particular has good success transitioning C/C++ programmers to this\n    syntax.\n-   Allows reading types left-to-right.\n\nDisadvantages:\n\n-   \"Pointer to T\" and \"Dereference T\" would not be distinguished grammatically,\n    could particularly be a problem in template code\n-   `*` used for both pointers and multiplication\n-   Uncanny valley -- it is very close to C++'s syntax but not quite the same.\n\n**Prefix `&`:**\n\n```\nvar p: &i32 = &i;\n```\n\nAdvantages:\n\n-   \"Type of a pointer is a pointer to the type\"\n-   Allows reading types left-to-right.\n\nDisadvantages:\n\n-   Visual ambiguity:\n\n    ```\n    let X:! type = i32;\n    // Can't actually write this, but there is a visual collision between\n    // whether this is the address of `X` or pointer-to-`i32`.\n    var y: auto = &X;\n    ```\n\n**Prefix `^`:**\n\n```\nvar p: ^i32 = &i;\n```\n\nAdvantages:\n\n-   Used by the Pascal family of languages like\n    [Delphi](http://rosettacode.org/wiki/Pointers_and_references#Delphi), and a\n    few others like\n    [BBC_BASIC](http://rosettacode.org/wiki/Pointers_and_references#BBC_BASIC)\n-   `^` looks pointy\n-   `^` operator is not heavily used otherwise (as a binary op it could be\n    bit-xor or raise-to-power).\n-   Allows reading types left-to-right.\n\n**`Ptr(T)`:**\n\n```\nvar p: Ptr(i32) = &i;\n```\n\nAdvantages:\n\n-   It is simple and unambiguous.\n-   Better supports a variety of pointer types.\n-   Allows reading types left-to-right.\n\nDisadvantages:\n\n-   Ends up making common code verbose.\n-   Not widely used in other languages.\n\n#### Pointer dereference syntax alternatives\n\n**Prefix `*`:**\n\n```\n*p = *p * *p + (*q)[3] + r->x;\n```\n\nAdvantages:\n\n-   Matches C/C++, and will be familiar to our initial users.\n-   When _not_ composed with other operations, prefix may be easier to recognize\n    visually than postfix.\n\nDisadvantages:\n\n-   `*` is used for both pointers and multiplication.\n-   Need parens or operator `->` to resolve precedence issues when composing\n    with postfix and infix operations, which is common.\n\n**Postfix `^`:**\n\n```\np^ = p^ * p^ + q^[3] + r^.x;\n```\n\nAdvantages:\n\n-   Generally fewer precedence issues.\n-   No need for `->` operator.\n-   Used by Pascal family of languages.\n\nDisadvantages:\n\n-   Not familiar to C/C++ users.\n-   Potential conflict with `^` as xor or exponentiation.\n-   Non-ergonomic: would be very frequently typed, but also a stretching motion\n    for typing.\n\n**Postfix `[]`:**\n\n```\np[] = p[] * p[] + q[][3] + r[].x;\n```\n\nAdvantages:\n\n-   Generally fewer precedence issues.\n-   No need for `->` operator.\n-   Used by Swift.\n\nDisadvantages:\n\n-   Two characters is a bit heavier visually.\n-   Possibly confusing given that plain pointers are used for non-array\n    pointees.\n\nMaybe should pair this with prefix `[]` to make pointer types? Would also need\nto distinguish slice types and maybe dynamically-sized-array types.\n\n#### Pointer syntax conclusion\n\nUltimately, the decision in [#523] was to keep Carbon's syntax familiar to\nC++'s. The challenges that presents and advantages of changes weren't sufficient\nto overcome the advantage of familiarity and for the specific challenges we have\neffective solutions.\n\n### Alternative syntaxes for locals\n\nSeveral other options for declaring locals were considered, but none ended up\noutweighing the proposed option on balance.\n\n-   `let` and `let mut`, based on the Rust names\n    -   While nicely non-inventive, there was both concern that `mut` didn't as\n        effectively communicate the requirement of storage and concern around\n        not being as obviously or unambiguously a good default with `let`. Put\n        differently, the `mut` keyword feels more fitting in its use with\n        mutable borrows than as a declaration introducer the way it would work\n        in Carbon.\n    -   There was a desire, for locals especially, to have both cases be\n        similarly easy to spell. While mutation being visible does seem helpful,\n        this specific approach seemed to go too far into being a tax.\n-   `val` and `var`\n    -   Appealing to use `val` instead of `let` given that these form value\n        expression bindings. These are also likely to be taught and discussed as\n        \"local values\" which would align well with the `val` introducer.\n    -   Not completely inventive, used in Kotlin for example. But rare, overall.\n    -   However, _very_ visually similar to `var` which makes code harder to\n        read at a glance.\n    -   Also difficult when speaking or listening to pronounce or hear the\n        distinction.\n-   `const` and `var`\n    -   Some familiarity for C++ developers given the use of `const` there.\n    -   `const` is used by other languages in a similar way to Carbon's `let`.\n    -   However, very concerned about reusing `const` but having it mean\n        something fairly different from C++ as a declaration introducer. For\n        example, nesting a `var` pattern within `const` might be especially\n        surprising.\n\nUltimately, the overwhelming most popular introducer for immutable local values\nacross popular languages that have such a distinction is `let`. Using that makes\nCarbon unsurprising in the world of programming languages which is a good thing.\nUsing `var` to help signify the allocation of storage and given it also having\nwidespread usage across popular languages.\n\n### Make `const` a postfix rather than prefix operator\n\nUsing a prefix operator for `const` and a postfix operator for `*` causes them\nto require parentheses for complex nesting. We could avoid that by using a\npostfix `const` and this would also allow more combinations in Carbon to be\nvalid in C++ with the same meaning as Carbon such as `T* const`.\n\nThis direction isn't pursued because:\n\n-   We expect pointers-to-`const` to be significantly more common in code than\n    `const`-pointers-to-non-`const`, even more-so than is already the case in\n    C++. And for `pointers-to-const`, we lean towards matching more widespread\n    convention of `const T*` rather than `T const*`.\n    -   We are aware that some developers have a stylistic preference for \"East\n        `const`\" which would write `T const*` in C++. However, that preference\n        and advocacy for this style hasn't yet caused it to become more\n        widespread or widely adopted style.\n-   We don't expect the parenthesized form of `const (T*)` to be _confusing_ to\n    C++ developers even though C++ doesn't allow this approach to forming a\n    `const`-pointer-to-non-`const`.\n\nThis alternative was only lightly considered and can be revisited if we get\nevidence that motivates a change here.\n\n## Appendix: background, context, and use cases from C++\n\nThis appendix provides an examination of C++'s fundamental facilities in the\nspace involving `const` qualification, references (including R-value\nreferences), and pointers. Beyond the expression categorization needed to\nprovide a complete model for the language, these use cases help inform the space\nthat should be covered by the proposed design.\n\n### `const` references versus `const` itself\n\nC++ provides overlapping but importantly separable semantic models which\ninteract with `const` references.\n\n1. An _immutable view_ of a value\n2. A _thread-safe interface_ of a [thread-compatible type][]\n\n[thread-compatible type]:\n    https://abseil.io/blog/20180531-regular-types#:~:text=restrictions%20or%20both,No%20concurrent%20call\n\nSome examples of the immutable view use case are provided below. These include\n`const` reference parameters and locals, as well as `const` declared local and\nstatic objects.\n\n```cpp\nvoid SomeFunction(const int &id) {\n  // Here `id` is an immutable view of some value provided by the caller.\n}\n\nvoid OtherFunction(...) {\n  // ...\n\n  const int &other_id = <some-runtime-expression>;\n\n  // Cannot mutate `other_id` here either, it is just a view of the result of\n  // `<some-runtime-expression>` above. But we can pass it along to another\n  // function accepting an immutable view:\n  SomeFunction(other_id);\n\n  // We can also pass ephemeral values:\n  SomeFunction(other_id + 2);\n\n  // Or values that may be backed by read-only memory:\n  static const int fixed_id = 42; SomeFunction(fixed_id);\n}\n```\n\nThe _immutable view_ `id` in `SomeFunction` can be thought of as requiring that\nthe semantics of the program be exactly the same whether it is implemented in\nterms of a view of the initializing expression or a copy of that value, perhaps\nin a register.\n\nThe implications of the semantic equivalence help illustrate the requirements:\n\n-   The input value must not change while the view is visible, or else a copy\n    would hide those changes.\n-   The view must not be used to mutate the value, or those mutations would be\n    lost if made to a copy.\n-   The identity of the object must not be relevant, or else inspection of its\n    address would reveal whether a copy was used.\n\nPut differently, these restrictions make a copy valid under the\n[as-if rule](https://en.cppreference.com/w/cpp/language/as_if).\n\nThe _thread-safe interface_ use case is the more prevalent use of `const` in\nAPIs. It is most commonly seen with code that looks like:\n\n```cpp\nclass MyThreadCompatibleType {\n public:\n  // ...\n\n  int Size() const { return size; }\n\n private:\n  int size;\n\n  // ...\n};\n\nvoid SomeFunction(const MyThreadCompatibleType *thing) {\n  // ....\n\n  // Users can expect calls to `Size` here to be correct even if running on\n  // multiple threads with a shared `thing`.\n  int thing_size = thing->Size();\n\n  // ...\n}\n```\n\nThe first can seem like a subset of the second, but this isn't really true.\nThere are cases where `const` works for the first use case but doesn't work well\nfor thread-safety:\n\n```cpp\nvoid SomeFunction(...) {\n  // ...\n\n  // We never want to release or re-allocate `data` and `const` makes sure that\n  // doesn't happen. But the actual data is completely mutable!\n  const std::unique_ptr<BigData> data = ComputeBigData();\n\n  // ...\n}\n```\n\nThese two use cases can also lead to tension between shallow const and deep\nconst:\n\n-   Immutability use cases will tend towards shallow(-er) const, like pointers.\n-   Thread safety use cases will tend towards deep(-er) const.\n\n### Pointers\n\nThe core of C++'s indirect access to an object stored somewhere else comes from\nC and its lineage of explicit pointer types. These create an unambiguous\nseparate layer between the pointer object and the pointee object, and introduce\ndereference syntax (both the unary `*` operator and the `->` operator).\n\nC++ makes an important extension to this model to represent _smart pointers_ by\nallowing the dereference operators to be overloaded. This can be seen across a\nwide range of APIs such as `std::unique_ptr`, `std::shared_ptr`,\n`std::weak_ptr`, etc. These user-defined types preserve a fundamental property\nof C++ pointers: the separation between the pointer object and the pointee\nobject.\n\nThe distinction between pointer and pointee is made syntactically explicit in\nC++ both when _dereferencing_ a pointer, and when _forming_ the pointer or\ntaking an object's address. These two sides can be best illustrated when\npointers are used for function parameters. The caller code must explicitly take\nthe address of an object to pass it to the function, and the callee code must\nexplicitly dereference the pointer to access the caller-provided object.\n\n### References\n\nC++ provides for indirection _without_ the syntactic separation of pointers:\nreferences. Because a reference provides no syntactic distinction between the\nreference and the referenced object--that is their point!--it is impossible to\nrefer to the reference itself in C++. This creates a number of restrictions on\ntheir design:\n\n-   They _must_ be initialized when declared\n-   They cannot be rebound or unbound.\n-   Their address cannot be taken.\n\nReferences were introduced originally to enable operator overloading, but have\nbeen extended repeatedly and as a consequence fill a wide range of use cases.\nSeparating these and understanding them is essential to forming a cohesive\nproposal for Carbon -- that is the focus of the rest of our analysis of\nreferences here.\n\n#### Special but critical case of `const T&`\n\nAs mentioned above, one form of reference in C++ has unique properties:\n`const T&` for some type `T`, or a _`const` reference_. The primary use for\nthese is also the one that motivates its unique properties: a zero-copy way to\nprovide an input function parameter without requiring the syntactic distinction\nin the caller and callee needed when using a pointer. The intent is to safely\nemulate passing by-value without the cost of copying. Provided the usage is\nimmutable, this emulation can safely be done with a reference and so a `const`\nreference fits the bill here.\n\nHowever, to make zero-copy, pass-by-value to work in practice, it must be\npossible to pass a _temporary_ object. That works well with by-value parameters\nafter all. To make this work, C++ allows a `const` reference to bind to a\ntemporary. However, the rules for parameters and locals are the same in C++ and\nso this would create serious lifetime bugs. This is fixed in C++ by applying\n_lifetime extension_ to the temporary. The result is that `const` references are\nquite different from other references, but they are also quite useful: they are\nthe primary tool used to fill the _immutable view_ use case of `const`.\n\nOne significant disadvantage of `const` references is that they are observably\nstill references. When used in function parameters, they cannot be implemented\nwith in-register parameters, etc. This complicates the selection of readonly\ninput parameter type for functions, as both using a `const` reference and a\nby-value parameter force a particular form of overhead. Similarly, range based\n`for` loops in C++ have to choose between a reference or value type when each\nwould be preferable in different situations.\n\n#### R-value references and forwarding references\n\nAnother special set of use cases for references are R-value and forwarding\nreferences. These are used to capture _lifetime_ information in the type system\nin addition to binding a reference. By doing so, they can allow overload\nresolution to select C++'s _move semantics_ when appropriate for operations.\n\nThe primary use case for move semantics in function boundaries was to model\n_consuming input_ parameters. Because move semantics were being added to an\nexisting language and ecosystem that had evolved exclusively using copies,\nmodeling consumption by moving into a by-value parameter would have forced an\neager and potentially expensive copy in many cases. Adding R-value reference\nparameters and overloading on them allowed code to gracefully degrade in the\nabsence of move semantics -- their internal implementation could minimally copy\nanything non-movable. These overloads also helped reduce the total number of\nmoves by avoiding moving first into the parameter and then out of the parameter.\nThis kind of micro-optimization of moves was seen as important because some\ninteresting data structures, especially in the face of exception safety\nguarantees, either implemented moves as copies or in ways that required\nnon-trivial work like memory allocation.\n\nUsing R-value references and overloading also provided a minor benefit to C++:\nthe lowest-level mechanics of move semantics such as move construction and\nassignment easily fit into the function overloading model that already existed\nfor these special member functions.\n\nThese special member functions are just a special case of a more general pattern\nenabled by R-value references: designing interfaces that use _lifetime\noverloading_ to _detect_ whether a move would be possible and change\nimplementation strategy based on how they are called. Both the move constructor\nand the move-assignment operator in C++ work on this principle. However, other\nuse cases for this design pattern are so far rare. For example, Google's C++\nstyle\n[forbids](https://google.github.io/styleguide/cppguide.html#Rvalue_references)\nR-value references outside of an enumerated set of use cases, which has been\nextended incrementally based on demonstrated need, and has now been stable for\nsome time. While overloading on lifetime is one of the allowed use cases, that\nexemption was added almost four years after the initial exemption of move\nconstructors and move assignment operators.\n\n#### Mutable operands to user-defined operators\n\nC++ user-defined operators have their operands directly passed as parameters.\nWhen these operators require _mutable operands_, references are used to avoid\nthe syntactic overhead and potential semantic confusion of taking their address\nexplicitly. This use case stems from the combined design decisions of having\noperators that mutate their operands in-place and requiring the operand\nexpression to be directly passed as a normal function parameter.\n\n#### User-defined dereference and indexed access syntax\n\nC++ also allows user-defined operators that model dereference (or indirecting in\nthe C++ standard) and indexed access (`*` and `[]`). Because these operators\nspecifically model forming an L-value and because the return of the operator\ndefinition is directly used as the expression, it is necessary to return a\nreference to the already-dereferenced object. Returning a pointer would break\ngenericity with builtin pointers and arrays in addition to adding a very\nsignificant syntactic overhead.\n\n#### Member and subobject accessors\n\nAnother common use of references is in returns from member functions to provide\naccess to a member or subobject, whether const or mutable. This particular use\ncase is worth calling out specially as it has an interesting property: this is\noften not a fully indirect access. Instead, it is often simply selecting a\nparticular member, field, or other subobject of the data structure. As a\nconsequence, making subsequent access transparent seems especially desirable.\n\nHowever, it is worth noting that this particular use case is also an especially\ncommon source of lifetime bugs. A classic and pervasive example can be seen when\ncalling such a method on a temporary object. The returned reference is almost\nimmediately invalid.\n\n#### Non-null pointers\n\nA common reason for using mutable references outside of what has already been\ndescribed is to represent _non-null pointers_ with enforcement in the type\nsystem. Because the canonical pointer types in C++ are allowed to be null,\nsystems that forbid a null in the type system use references to induce any null\nchecks to be as early as possible. This causes a\n\"[shift left](https://en.wikipedia.org/wiki/Shift-left_testing)\" of handling\nnull pointers, both moving the error closer to its cause logically and\nincreasing the chance of moving earlier in the development process by making it\na static property enforced at compile time.\n\nReferences are imperfectly suited to modeling non-null pointers because they are\nmissing many of the fundamental properties of pointers such as being able to\nrebind them, being able to take their address, etc. Also, references cannot be\nsafely made `const` in the same places that pointers can because that might\nunintentionally change their semantics by allowing temporaries or extending\nlifetimes.\n\n#### Syntax-free dereference\n\nBeyond serving as a non-null pointer, the other broad use case for references is\nto remove the syntactic overhead of taking an address and dereferencing\npointers. In other words, they provide a way to have _syntax-free dereferences_.\nOutside of function parameters, removing this distinction may provide a\ngenericity benefit, as it allows using the same syntax as would be used with\nnon-references. In theory code could simply use pointers everywhere, but this\nwould add syntactic overhead compared to local variables and references. For\nimmutable accesses, the syntactic overhead seems unnecessary and unhelpful.\nHowever, having distinct syntax for _mutable_ iteration, container access, and\nso on often makes code more readable.\n\nThere are several cases that have come up in the design of common data\nstructures where the use of distinct syntaxes immutable and mutable operations\nprovides clear benefit: copy-on-write containers where the costs are\ndramatically different, and associative containers which need to distinguish\nbetween looking up an element and inserting an element. This tension should be\nreflected in how we design _indexed access syntax_.\n\nUsing mutable references for parameters to reduce syntactic overhead also\ndoesn't seem particularly compelling. For passing parameters, the caller syntax\nseems to provide significant benefit to readability. When using _non-local_\nobjects in expressions, the fact that there is a genuine indirection into memory\nseems to also have high value to readability. These syntactic differences do\nmake inline code and outlined code look different, but that reflects a behavior\ndifference in this case.\n"
  },
  {
    "path": "proposals/p2015.md",
    "content": "# Numeric type literal syntax\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2015)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Non-goals](#non-goals)\n-   [Details](#details)\n    -   [Syntax](#syntax)\n    -   [Usage](#usage)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [C++ LP64 convention](#c-lp64-convention)\n    -   [Type name with length suffix](#type-name-with-length-suffix)\n    -   [Uppercase suffixes](#uppercase-suffixes)\n    -   [Additional bit sizes](#additional-bit-sizes)\n\n<!-- tocstop -->\n\n## Problem\n\nWe want to establish a syntax for fixed-size scalar number types. These types\ninclude the two's complement signed integer, the unsigned integer, and the\nfloating-point number.\n\nAs these types are pervasive throughout the language, our goal here is to align\non a terse, convenient, yet understandable, and ergonomic syntax to the author.\n\n## Background\n\nFor developer convenience, names are given to number types that map to native\nmachine register widths. These sizes typically include 8-bit, 16-bit, 32-bit,\n64-bit, and, more recently, 128-bit widths.\n\nFor example, in [C++11+](https://en.cppreference.com/w/cpp/types/integer),\ninteger types such as `int8_t` (8-bit two's complement signed integer type) and\n`uint16_t` (16-bit unsigned integer type) exist, among similar types for 32- and\n64-bit values. Correspondingly, you have the `i8` and `u16`\n([among others](https://doc.rust-lang.org/book/ch03-02-data-types.html#scalar-types))\nscalar integer types in Rust. And in Swift, the `Int8` and `UInt16`\n([among others](https://developer.apple.com/documentation/swift/uint8)) integer\nvalue types.\n\nIn each case, the intent is to provide a clear and pragmatic syntax.\n\nAdditional discussion around this proposal's background can be found in\n[#543](https://github.com/carbon-language/carbon-lang/issues/543).\n\n## Proposal\n\nWe introduce a simple keyword-like syntax of `iN`, `uN`, and `fN` for two's\ncomplement integers, unsigned integers, and floating-point numbers,\nrespectively. Where `N` can be a positive multiple of 8, including the common\npower-of-two sizes (for example, `N = 8, 16, 32`). We think of these as \"type\nliterals\" just like `7` is a \"numeric literal.\" This structure follows the\nsuccessful precedent set by Rust and LLVM development communities and\npotentially saves 40% or more on characters required compared to other options\nsuch as `IntN` (for example, `i16` versus `Int16`). While bit sizes greater than\n128-bits will be well-supported, some operations like division will not be\navailable on these large sizes.\n\n### Non-goals\n\n-   This does not address any considerations around the `bool` type\n-   This does not provide a formal plan for the shape or mapping of the\n    underlying types\n    ([#767 comments](https://github.com/carbon-language/carbon-lang/issues/767#issuecomment-1214153375))\n-   This does not prescribe an official grammar for parsing these types\n-   This proposal does not address other, non-multiple of 8 bit sizes, such as\n    those used in a bit field\n\n## Details\n\n### Syntax\n\nThe syntax for a two's complement signed integer, the unsigned integer, and the\nfloating-point number corresponds to a lowercase 'i', 'u', or 'f' character,\nrespectively, indicating the type followed by a numeric value specifying the\nwidth.\n\nAs a regular expression, this can be illustrated as:\n\n```re\n([iuf])([1-9][0-9]*)\n```\n\nCapture group 1 indicates either an 'i' for a two's complement signed integer\ntype, a 'u' for an unsigned integer type, or an 'f' for an\n[IEEE-754](https://en.wikipedia.org/wiki/IEEE_754) binary floating-point number\ntype. Capture group 2 specifies the width in bits. Note that this bit width is\nrestricted to a multiple of 8.\n\nExamples of this syntax include:\n\n-   `i16` - A 16-bit two's complement signed integer type\n-   `u32` - A 32-bit unsigned integer type\n-   `f64` - A 64-bit IEEE-754 binary floating-point number type\n\n### Usage\n\n```carbon\npackage sample api;\n\nfn Sum(x: i32, y: i32) -> i32 {\n  return x + y;\n}\n\nfn Main() -> i32 {\n  return Sum(4, 2);\n}\n```\n\nIn the above example, `Sum` has parameters `x` and `y`, each of which is typed\nas a 32-bit two's complement signed integer. `Main` then returns the output of\n`Sum` as a 32-bit two's complement signed integer.\n\n## Rationale\n\nFollowing Carbon's goal to facilitate\n[\"Code that is easy to read, understand, and write\"](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\nan explicit goal is to provide excellent ergonomics.\n\nHighlighting relevant aspects of this from the project goals:\n\n-   _Carbon should not use symbols that are difficult to type, see, or\n    differentiate from similar symbols in commonly used contexts._\n-   _Syntax should be easily parsed and scanned by any human in any development\n    environment, not just a machine or a human aided by semantic hints from an\n    IDE._\n-   _Explicitness must be balanced against conciseness, as verbosity and\n    ceremony add cognitive overhead for the reader, while explicitness reduces\n    the amount of outside context the reader must have or assume._\n\nThe type system syntax must also complement Carbon's target for\n[\"Performance-critical software\"](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#performance-critical-software)\n\nSpecifically, there should be \"No need for a lower level language.\"\n\n-   _Developers should not need to leave the rules and structure of Carbon,\n    whether to gain control over performance problems or to gain access to\n    hardware facilities._\n\n## Alternatives considered\n\nAs discussed in\n[#543](https://github.com/carbon-language/carbon-lang/issues/543), four other\noptions were considered:\n\n### C++ LP64 convention\n\nWhere `char` is the 8-bit type, `short` is the 16-bit type, `int` is the 32-bit\ntype, `long` is the 64-bit type.\n\nAdvantages:\n\n-   The type name indicates its use to the reader\n-   There is an existing precedent of this pattern in many programming\n    languages, including C++\n-   In the case of a typo, potentially better compiler checks versus an\n    abbreviated form (for example, `i332`)\n\nDisadvantages:\n\n-   The type names themselves, as compared to the actual width and potentially\n    use often can be arbitrary and confusing\n-   The names themselves can be longer than the other syntax options\n-   Some common C++ implementations use other models, which may create confusion\n    when interoperating with C++ code. For example, Windows uses the LLP64\n    model, where `long` is a 32-bit type, so Carbon code and C++ on Windows\n    would have different and incompatible definitions for `long`.\n\n### Type name with length suffix\n\nComplete type name with a length-specifying suffix - `int8`, `int16`, `int32`,\n`int64`, `uint32`, `float64`.\n\nAdvantages:\n\n-   Are more explicit than an abbreviated version\n-   Stand out against similar variable names, for example, `i8` versus `i = 8`)\n\nDisadvantages:\n\n-   Contain additional verbosity for potentially a non-significant amount of\n    clarity\n-   There are precedents from other communities (for example, Rust) that\n    indicate authors enjoy a more compact syntax\n\n### Uppercase suffixes\n\nThe suffix can be upper - `Int8`, `UInt8`, `Float16`; `I8`, `U8`, `F16`.\n\nAdvantages:\n\n-   May help screen readers distinguish the type\n\nDisadvantages:\n\n-   Can be visually similar to other values, for example, `I8` versus `l8`\n    (second is a lowercase L)\n\n### Additional bit sizes\n\nSupport for additional bit sizes such as all bit sizes or common powers of two.\n\nAdvantages:\n\n-   Adds flexibility and convenience for further use cases such as bit fields\n\nDisadvantages:\n\n-   May increase chances of typos without strong compiler guards, for example,\n    `i32` versus `i22` versus `i23`\n-   Variables such as `i1` and `i2` already exist in C++ code in practice\n    ([example1](https://github.com/google/googletest/blob/main/googlemock/include/gmock/gmock-matchers.h#L878),\n    [example2](https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+/HEAD/absl/container/btree_test.cc#2772),\n    [example3](https://sourcegraph.com/search?q=context:global+lang:c%2B%2B+%5Ei1%24+type:symbol&patternType=regexp&case=yes))\n-   Adds complexity through additional size rules, for example, we can't support\n    pointers to arbitrary bits\n-   Adds confusion in syntactical overlap, for example, `i1`, `il`, `i18`, and\n    `i18n`\n"
  },
  {
    "path": "proposals/p2022.md",
    "content": "# Unused Pattern Bindings (Unused Function Parameters)\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2022)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [The behavior of `unused` name bindings](#the-behavior-of-unused-name-bindings)\n    -   [Examples](#examples)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Commented names](#commented-names)\n    -   [Only short form support with `_`](#only-short-form-support-with-_)\n    -   [Named identifiers prefixed with `_`](#named-identifiers-prefixed-with-_)\n    -   [Anonymous, named identifiers](#anonymous-named-identifiers)\n    -   [Attributes](#attributes)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal specifies how unused pattern bindings are written in the Carbon\nprogramming language. This is a more general problem statement of \"how do users\nspecify unused function parameters\" as function parameter declarations are a\nmore specific form of pattern.\n\nRelated issue:\n[#1996](https://github.com/carbon-language/carbon-lang/issues/1996).\n\n## Problem\n\n\"How does a user of Carbon declare an unused pattern binding?\"\n\nGiven that function parameters are a specific type of pattern binding, a more\nspecific question that will have the same answer is \"How does a user of Carbon\ndeclare an unused function parameter?\"\n\nBindings that can be specified as unused makes code explicit and unambiguous.\nAuthors of code can clearly state that a value is not intended to be used. Tools\nsuch as compilers or linters can explicitly handle a parameter that is specified\nas unused, but later used, or a parameter that is unused despite not being\nspecified as unused.\n\n## Background\n\nSee\n[the overall design](https://github.com/carbon-language/carbon-lang/blob/09e4417431b77c05ceb2a98dd38833276514a1ff/docs/design/README.md#binding-patterns)\nfor the current state of things with regards to name bindings and the underscore\ncharacter, `_`.\n\nSee\n[issue #476: Optional argument names (unused arguments)](https://github.com/carbon-language/carbon-lang/issues/476)\nfor the previous conversation on this topic.\n\nNote: These are not exhaustive lists and not intended to be thoroughly\ninvestigated, rather a brief overview of some prior art.\n\nC and C++ style guides, linters, and other tools have addressed unused function\nparameters specifically with varying levels of clarity for readers.\n\n-   [Standard C++ Foundation's guidelines on unused parameters](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-unused)\n-   [Google's C++ style guide recommendations on unused parameters](https://google.github.io/styleguide/cppguide.html#Function_Declarations_and_Definitions)\n-   [C++ `maybe_unused` attribute](https://en.cppreference.com/w/cpp/language/attributes/maybe_unused)\n-   [GCC C `unused` attribute](https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html#index-g_t_0040code_007bunused_007d-attribute_002e-2640)\n\nMore generally, various languages use the underscore character (`_`) to signal\nan unused binding or pattern.\n\n-   [Rust `_` Patterns](https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#ignoring-values-in-a-pattern)\n-   [Golang Blank Identifiers](https://go.dev/ref/spec#Blank_identifier)\n-   [PyLint allows parameters starting with `_`, `ignored_`, or `unused_` to be unused](https://pylint.pycqa.org/en/latest/user_guide/configuration/all-options.html#ignored-argument-names)\n-   [Scala Wildcard Patterns](https://www.scala-lang.org/files/archive/spec/2.11/10-pattern-matching.html#variable-patterns)\n-   [Crystal `_` Cases](https://crystal-lang.org/reference/1.5/syntax_and_semantics/case.html#underscore-allowed)\n\n## Proposal\n\nUsers can explicitly declare a value in a pattern as unused in two forms:\n\n-   `_: i32` : Using the underscore token, `_`, in place of a name.\n\n-   `unused size: i32` : Using the leading `unused` keyword followed by the\n    name.\n\n## Details\n\nIntroducing two syntaxes satisfies the desire to have a terse way to discard\nvalues, but still provides authors with a more verbose, explicit syntax that\npreserves the name.\n\nBoth approaches are unambiguous -- to human readers and authors as well as\nprogrammatic interpretations. The inclusion of an explicit `unused` keyword\nallows authors to preserve the name of a value for documentation purposes, while\nstill explicitly marking the value as discarded in an interpretable way to\nhumans and programs alike.\n\nThe `unused` keyword would be a new keyword in Carbon. This keyword would only\nbe valid when preceding a name in a pattern binding and the keyword would\ntightly bind to the following name, disallowing specifying an entire sub-pattern\nas `unused`.\n\n### The behavior of `unused` name bindings\n\nNames that are qualified with the `unused` keyword are visible for name lookup\nbut uses are invalid, including when they cause ambiguous name lookup errors. If\nattempted to be used, a compiler error will be shown to the user, instructing\nthem to either remove the `unused` qualifier or remove the use.\n\nThe inverse, where a name is not qualified by the `unused` qualifier, but never\nused, will cause the compiler to emit a warning diagnostic, informing the user\nthat a given name was not used and suggesting to either remove the binding or\nmark it as unused.\n\n### Examples\n\nExamples with an unused function parameter\n\n```carbon\n// Function declaration (may be in API file)\nfn Sum(x: List(i32), size: i32) -> i32;\n\n// Implementation that doesn't use the size parameter\nfn Sum(x: List(i32), _: i32) -> i32 { ... }\n// or:\nfn Sum(x: List(i32), unused size: i32) -> i32 { ... }\n```\n\nExamples with an unused variable\n\n```carbon\nfn Bar() -> (i32, i32);\nfn Foo() -> i32 {\n  var (x: i32, _: i32) = Bar();\n  // or:\n  var (x: i32, unused y: i32) = Bar();\n\n  return x;\n}\n```\n\nExamples with an unused case binding\n\n```carbon\nfn Bar() -> (i32, i32);\nfn Foo() -> i32 {\n  match (Bar()) {\n    case (42, y: i32) => {\n      return y;\n    }\n    case (x: i32, _: i32) => {\n      return x;\n    }\n    // or:\n    case (x: i32, unused y: i32) => {\n      return x;\n    }\n  }\n}\n```\n\n## Rationale\n\n-   This proposal supports the Carbon goal of having\n    [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Carbon should not use symbols that are difficult to type, see, or\n        differentiate from similar symbols in commonly used contexts.\n    -   Syntax should be easily parsed and scanned by any human in any\n        development environment, not just a machine or a human aided by semantic\n        hints from an IDE.\n    -   Explicitness must be balanced against conciseness, as verbosity and\n        ceremony add cognitive overhead for the reader, while explicitness\n        reduces the amount of outside context the reader must have or assume.\n\nThis proposal uses the underscore, `_`, character to denote an unused value, a\nmeaning used across various other programming languages. A lone underscore\ncharacter only has a single meaning in Carbon and will be unambiguous across\ncontexts.\n\nBoth syntaxes are easily read by humans, either by seeing the `_` character\nalone, or by introducing a keyword that allows code to read naturally such as\n`unused size : i32`.\n\nThe inclusion of two syntaxes allows authors to decide when they will favor\nconciseness or explicitness.\n\n## Alternatives considered\n\n### Commented names\n\nC++ allows function parameters to be unnamed, allowing function declarations\nsuch as\n\n```\nint Foo(int) { ... }\nint Foo(int /*unused_name*/) { ... }\n```\n\nAdvantages:\n\n-   Consistency with C++\n\nDisadvantages:\n\n-   Carbon does not intend to support `/* */` comments, so this option is\n    effectively a non-starter\n\n### Only short form support with `_`\n\nCarbon could provide only a single way to discard a value with the underscore,\n`_`, token\n\n```\n// Function declaration (may be in API file)\nfn Sum(x: List(i32), size: i32) -> i32;\n\n// Implementation that doesn't use the size parameter\nfn Sum(x: List(i32), _: i32) -> i32 { ... }\n```\n\nAdvantages:\n\n-   A smaller language, one less keyword, and a single way to write code\n\nDisadvantages:\n\n-   Less expressiveness, less documentation through names\n\n### Named identifiers prefixed with `_`\n\nCarbon could treat identifiers prefixed with `_` as unused identifiers and\ndiscard their names.\n\n```\n// Function declaration (may be in API file)\nfn Sum(x: List(i32), size: i32) -> i32;\n\n// Implementation that doesn't use the size parameter\nfn Sum(x: List(i32), _size: i32) -> i32 { ... }\n```\n\nAdvantages:\n\n-   Reuse of the underscore character in both short and long form bindings\n-   Functionally similar to commented names in C++\n\nDisadvantages:\n\n-   Tying the semantics of a name being unused to the particular spelling of the\n    identifier (starting with a `_` character), even while it remains an\n    identifier seems more subtle and indirect than necessary.\n    -   We shouldn't use identifier spellings as a side-channel for semantic\n        information.\n    -   Semantics, including used versus unused, should be conveyed in an\n        orthogonal manner to the name rather than tying them together.\n-   Would require the name to change when shifting between being used or unused,\n    which could undermine some of its utility such as remaining for annotations,\n    metaprogramming, or diagnostics.\n\n### Anonymous, named identifiers\n\nA potential syntax for naming unused bindings while retaining the underscore,\n`_`, token is an optional name suffix following the underscore token.\n\n```\n// Function declaration (may be in API file)\nfn Sum(x: List(i32), size: i32) -> i32;\n\n// Implementation that doesn't use the size parameter\nfn Sum(x: List(i32), _ size: i32) -> i32 { ... }\n```\n\nAdvantages:\n\n-   Reuse of the underscore token in both short and long form bindings\n\nDisadvantages:\n\n-   The underscore token, while consistent, may be less human readable than a\n    dedicated keyword such as `unused`\n\n### Attributes\n\nWhile attributes aren't designed yet, there's a possibility that in the future,\nthe Carbon language will have some mechanism to attach metadata to parts of\nsource code to inform readers, compilers, and other tools. Its conceivable that\nthere could be an `unused` attribute which could be use to implement similar\nsemantics as the proposed `unused` keyword.\n\nAdvantages:\n\n-   Opens the inspection and subsequent actions taken to whatever ecosystem and\n    programmatic support is introduced by attributes.\n-   Solves a specific problem with a generic approach\n    -   Removes the introduction of a new keyword\n\nDisadvantages:\n\n-   Given the current proposal where `unused` bindings specify unambiguous,\n    absolute behavior for the compiler's handling of names, similar to the\n    `private` keyword, using attributes as the transport for this semantic\n    information is indirect.\n\nGiven that attributes are not designed and may go in a number of unknown\ndirections, it might be worth revisiting this option once attributes are fully\ndesigned.\n"
  },
  {
    "path": "proposals/p2040.md",
    "content": "# Unicode escape code length\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2040)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Allow zero digits](#allow-zero-digits)\n    -   [Allow any number of hexadecimal characters](#allow-any-number-of-hexadecimal-characters)\n    -   [Limiting to 6 digits versus 8](#limiting-to-6-digits-versus-8)\n\n<!-- tocstop -->\n\n## Abstract\n\nThe `\\u{HHHH...}` can be an arbitrary length, potentially including `\\u{}`.\nRestrict to 1 to 8 characters.\n\n## Problem\n\n[Proposal #199: String literals](https://github.com/carbon-language/carbon-lang/pull/199)\nsays \"any number of hexadecimal characters\" is valid for `\\u{HHHH}`. This is\nundesirable, because it means `\\u{000 ... 000E9}` is a valid escape sequence,\nfor any number of `0` characters. Additionally, it's not clear if `\\u{}` is\nmeant to be valid.\n\n## Background\n\n[Proposal #199: String literals](https://github.com/carbon-language/carbon-lang/pull/199)\nsays:\n\n> As in JavaScript, Rust, and Swift, Unicode code points can be expressed by\n> number using `\\u{10FFFF}` notation, which accepts any number of hexadecimal\n> characters. Any numeric code point in the ranges\n> 0<sub>16</sub>-D7FF<sub>16</sub> or E000<sub>16</sub>-10FFFF<sub>16</sub> can\n> be expressed this way.\n\nWhen it comes to the number of digits, the languages differ:\n\n-   In [JavaScript](https://262.ecma-international.org/13.0/#prod-CodePoint),\n    between 1 and 6 digits are supported, and it must be less than or equal to\n    `10FFFF`.\n-   In [Rust](https://doc.rust-lang.org/reference/tokens.html), between 1 and 6\n    digits are supported.\n-   In\n    [Swift](https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html),\n    between 1 and 8 digits are supported.\n\nUnicode's codespace is 0 to [`10FFFF`](https://unicode.org/glossary/#codespace).\n\n## Proposal\n\nThe `\\u{H...}` syntax is only valid for 1 to 8 unicode characters.\n\n## Rationale\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   This restriction does not affect the ability to write valid Unicode.\n        Instead, it restricts the ability to write confusing or invalid unicode,\n        which should make it easier to detect errors.\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n    -   Simplifies tooling by reducing the number of syntaxes that need to be\n        supported, and allowing early failure on obviously invalid inputs.\n\n## Alternatives considered\n\n### Allow zero digits\n\nWe could allow `\\u{}` as a version of `\\u{0}`. However, as shorthand, it doesn't\nsave much and `\\x00` is both equal length and clearer.\n\nRather than allowing this syntax, we prefer to disallow it for consistency with\nother languages.\n\n### Allow any number of hexadecimal characters\n\nWe could allow any number of digits in the `\\u` escape. However, this has the\nconsequence of requiring parsing of escapes of completely arbitrary length.\n\nThis creates unnecessary complexity in the parser because we need to consider\nwhat happens if the result is greater than 32 bits, significantly larger than\nunicode's current `10FFFF` limit. One way to do this would be to store the\nresult in a 32-bit integer and keep parsing until the value goes above `10FFFF`,\nthen error as invalid if that's exceeded. This would allow an arbitrary number\nof leading `0`'s to correctly parse.\n\nIt should make it easier to write a simple parser if we instead limit the number\nof digits to a reasonable amount.\n\n### Limiting to 6 digits versus 8\n\nA limit of 6 digits offers a reasonable limit as the minimum needed to represent\nUnicode's codespace. A limit of 8 digits offers a reasonable limit as a standard\n4-byte value, and roughly matches UTF-32.\n\nWhile it seems a weak advantage, this proposal leans towards 8.\n"
  },
  {
    "path": "proposals/p2107.md",
    "content": "# Clarify rules around `Self` and `.Self`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2107)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [`Self` not a keyword](#self-not-a-keyword)\n    -   [Make `Self` a member of all types](#make-self-a-member-of-all-types)\n    -   [`where` operator could be associative](#where-operator-could-be-associative)\n\n<!-- tocstop -->\n\n## Abstract\n\nA number of smaller changes grouped together in one proposal:\n\n-   Make `Self` a keyword.\n-   Clarify that `Self` refers to the current type in a base class and in impl\n    declarations.\n-   Clarify when `.Self` is legal, and what type it has.\n-   Also specify that `where` is not an associative operator.\n\n## Problem\n\nThere were a number of gaps found in the design when @zygoloid went to implement\nthese features in\n[the explorer codebase](https://github.com/carbon-language/carbon-lang/tree/76c68153a2cf5b35249be3e9b8097238f3dc1ee1/explorer),\nfor example\n[#1311: Basic support for `.Self` within `:!` bindings and `where` expressions](https://github.com/carbon-language/carbon-lang/pull/1311).\n\n## Background\n\n`Self` was introduced for interfaces and implementations in\n[#524: Generics overview](https://github.com/carbon-language/carbon-lang/pull/524)\nand\n[#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553).\n`Self` was introduced for class types and methods in\n[#494: Method syntax](https://github.com/carbon-language/carbon-lang/issues/494)\nand\n[#722: Nominal classes and methods](https://github.com/carbon-language/carbon-lang/pull/722).\n\nConstraints using `where` and `.Self` were introduced in\n[#818: Constraints for generics (generics details 3)](https://github.com/carbon-language/carbon-lang/pull/818).\nThe use of `where` to set associated types was introduced in\n[#1013: Generics: Set associated constants using `where` constraints](https://github.com/carbon-language/carbon-lang/pull/1013).\n\nThe type of `.Self` and where it would be introduced grammatically was discussed\n[#generics channel on Discord on 2022-06-07](https://discord.com/channels/655572317891461132/708431657849585705/1013904969335836732).\n\n## Proposal\n\nThis proposal implements a number of changes and clarifications about the use of\n`Self` and `.Self` with generics:\n\n-   `Self` is now a keyword, and may not be used as an identifier even in\n    contexts where `Self` has no meaning. If `Self` is used in a C++ API, Carbon\n    will use the same mechanism for interop as other Carbon keywords.\n-   Clarify that `Self` always refers to the current type, even for virtual\n    functions implemented in a derived class, not the type implementing the\n    method.\n-   `Self` in an `impl` declaration may be used after the `as` to refer to the\n    type being implemented. This could be the type named before `as` when\n    specified, otherwise it is the enclosing type.\n-   Clarify that `.Self` is legal after `:!` and `where`, as long as it only\n    refers to a single type variable.\n-   Specify the type of `.Self` as `Type` after `:!`, or `MyConstraint` after\n    `MyConstraint where`.\n\nIn addition, this proposal specifies that `where` is not an associative\noperator.\n\n## Details\n\n`Self` was added as a keyword to\n[`docs/design/lexical_conventions/words.md`](/docs/design/lexical_conventions/words.md).\nThe other rules were added to\n[`docs/design/classes.md`](/docs/design/classes.md) and\n[`docs/design/generics/details.md`](/docs/design/generics/details.md).\n\n## Rationale\n\nThis proposal fills in gaps with an aim to make things consistent and simplify\nby having fewer rules where possible. For example, the rule saying that it is an\nerror if `.Self` could mean two different things is consistent with other name\nlookup rules, such as those from\n[#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\nand\n[#2070: Always `==` not `=` in `where` clauses](https://github.com/carbon-language/carbon-lang/pull/2070).\nSimplicity benefits Carbon's\n[language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\nand consistency leads to\n[code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n\n## Alternatives considered\n\n### `Self` not a keyword\n\nAn alternative considered was forbidding identifiers to be equal to `Self`. The\nbig concern with that approach is that we would need some other way to\ninteroperate with C++ code, particularly classes, that had a `Self` member. If\nwe were adding `Self` to the language later as part of evolution, we would make\nit a keyword. That would allow us to use the same evolution strategy as other\nkeywords -- we would automatically update the code to change existing uses of\n`Self` to the raw identifier syntax.\n\nNote that at this time\n[no raw identifier syntax has been approved](https://github.com/carbon-language/carbon-lang/pull/93),\nbut Rust uses a `r#` prefix. If Carbon used the same syntax, existing uses of\n`Self` would be changed to `r#Self`, and so `r#Self` should still be a legal\nidentifier.\n\n### Make `Self` a member of all types\n\nWe considered making `Self` a member of all types. From this uses of `Self` and\n`.Self` would follow naturally. It would have other consequences as well:\n\n-   `T.Self == T` for all types `T`.\n-   `x.Self`, where `x` is a non-type value with type `T`, would be `T`. This is\n    because under the normal member-access rules, since `Self` is not a member\n    of `x`, it would look in `T` and find `T.Self`.\n\nThis raised the question of whether `Self` is a member of type-of-types like\n`Type`. That would seem to introduce an ambiguity for `i32.Self`. Furthermore,\nusing `x.Self` to get the type of `x` seemed tricky, it would be better to have\nsomething that used the word \"type\" to do that.\n\nSince [`Self` is a keyword](#self-not-a-keyword), we don't need to make it\nfollow the normal member-access rules. So we instead only define what it means\nin places where we have a use case.\n\nThis was discussed\n[on 2022-08-29 in the #typesystem channel in Discord](https://discord.com/channels/655572317891461132/708431657849585705/1013904969335836732).\n\n### `where` operator could be associative\n\nWe considered making the `where` operator associative, since an expression like\n\n```\nInterface1 where .AssocType1 is Interface2 where .AssocType2 == i32\n```\n\nwould more usefully be interpreted as:\n\n```\nInterface1 where .AssocType1 is (Interface2 where .AssocType2 == i32)\n```\n\nthan the alternative. However, this is expected to be a rare case and so it\nseemed much friendlier to humans to require parentheses or a separate named\nconstraint declaration. This way they can easily visually disambiguate how it is\ninterpreted without having to remember a rule that won't commonly be relevant.\n\nThis was discussed in\n[the #syntax channel on Discord on 2022-05-27](https://discord.com/channels/655572317891461132/709488742942900284/979869282903130153)\nand\n[the weekly sync meeting on 2022-06-01](https://docs.google.com/document/d/1dwS2sJ8tsN3LwxqmZSv9OvqutYhP71dK9Dmr1IXQFTs/edit?resourcekey=0-NxBWgL9h05yD2GOR3wUisg#heading=h.qarzfirrcrgf).\n"
  },
  {
    "path": "proposals/p2138.md",
    "content": "# Checked and template generic terminology\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2138)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Status quo: \"generic\" means \"checked\"](#status-quo-generic-means-checked)\n    -   [Use the name \"templates\" instead of \"template generics\"](#use-the-name-templates-instead-of-template-generics)\n    -   [Use the name \"unchecked generics\" instead of \"template generics\"](#use-the-name-unchecked-generics-instead-of-template-generics)\n\n<!-- tocstop -->\n\n## Abstract\n\nChange terminology from \"generics\" and \"templates\" to \"checked generics\" and\n\"template generics\". Afterwards, \"generics\" will be an umbrella term that\ninclude templates.\n\n## Problem\n\nThe C++ community does \"generic programming\" using templates in C++, and so\nthinks of templates as a mechanism for implementing generics. In Carbon,\ntemplates and other generic features are more similar than they are different,\nso it is worthwhile to have an easy way to talk about things that apply to both.\n\n## Proposal\n\nChange terminology from \"generics\" and \"templates\" to \"checked generics\" and\n\"template generics\". Afterwards, \"generics\" will be an umbrella term that\ninclude templates.\n\nSimilarly, for parameters, use \"checked generic parameter\" and \"template generic\nparameter\", with the umbrella term \"generic parameter\" describing both kinds.\nThe word \"generic\" can be omitted from these terms if it's clear from context,\nwhich will usually be the case for template parameters.\n\nSome existing design docs give examples of the difference before and after this\nproposal:\n\n-   The [generics overview](/docs/design/generics/overview.md), for example,\n    currently demonstrates the current approach of using \"generics\" and\n    \"templates\".\n-   The\n    [generics section of the design overview](/docs/design/README.md#generics)\n    demonstrates the use of the proposed new terminology.\n\n## Rationale\n\nUsing the terminology expected by the community supports these goals:\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    since our documentation governing the interpretation of that code will be\n    more easily understood and with greater accuracy.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    since there will be a smaller terminology gap between Carbon and C++.\n\n## Alternatives considered\n\n### Status quo: \"generic\" means \"checked\"\n\nUse \"generic\" for checked generics, \"template\" for template generics, and\n\"template or generic\" when we mean both.\n\nAdvantages:\n\n-   The terms \"generic\" and \"template\" are more concise than \"checked generic\"\n    and \"template generic\".\n-   The term \"template\" is more familiar than \"template generic\" to people\n    coming from C++.\n\nDisadvantages:\n\n-   Does not provide a unifying term for templates and generics, leading to our\n    needing to talk about both in various places, given that they are very\n    similar concepts in Carbon.\n-   Does not acknowledge that templates are used for generic programming and as\n    such are a kind of generic.\n-   Carbon's template generics aren't exactly the same as C++'s templates, so\n    this may give the wrong intuition for people coming from C++ in some cases.\n\n### Use the name \"templates\" instead of \"template generics\"\n\nUse \"checked generic\" for checked generics, \"template\" for template generics,\nand \"generic\" when we mean both.\n\nAdvantages:\n\n-   More concise term than in this proposal.\n-   More familiar to people coming from C++.\n-   People will likely use this term anyway rather than saying \"template\n    generics\".\n\nDisadvantages:\n\n-   Does not parallel the term \"checked generics\".\n-   Loses the implication that a template generic is a kind of generic.\n-   Carbon's template generics aren't exactly the same as C++'s templates, so\n    this may give the wrong intuition for people coming from C++ in some cases.\n\n### Use the name \"unchecked generics\" instead of \"template generics\"\n\nUse \"checked generic\" for checked generics, \"unchecked generic\" for template\ngenerics, and \"generic\" when we mean both.\n\nAdvantages:\n\n-   Creates a better parallel between \"checked generics\" and \"unchecked\n    generics\".\n-   Describes the semantics rather than the implementation strategy, especially\n    given that templating / monomorphization is also the implementation strategy\n    we intend to use for unchecked generics.\n\nDisadvantages:\n\n-   Unfamiliar to people coming from C++.\n-   Would either need to rename the `template` keyword or pick new non-keyword\n    syntax for it, or have a mismatch between keywords and terminology.\n-   Template generics still involve checking, it just can't complete until later\n    when the argument values are known.\n\nThis was suggested in\n[#1443](https://github.com/carbon-language/carbon-lang/pull/1443).\n"
  },
  {
    "path": "proposals/p2173.md",
    "content": "# Associated constant assignment versus equality\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2173)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n    -   [Equal types with different interfaces](#equal-types-with-different-interfaces)\n    -   [Type canonicalization](#type-canonicalization)\n    -   [Transitivity of equality](#transitivity-of-equality)\n    -   [Coherence](#coherence)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Rewrite constraints](#rewrite-constraints)\n    -   [Combining constraints with `&`](#combining-constraints-with-)\n    -   [Combining constraints with `and`](#combining-constraints-with-and)\n    -   [Combining constraints with `extends`](#combining-constraints-with-extends)\n    -   [Combining constraints with `impl as` and `is`](#combining-constraints-with-impl-as-and-is)\n    -   [Constraint resolution](#constraint-resolution)\n    -   [Precise rules and termination](#precise-rules-and-termination)\n        -   [Qualified name lookup](#qualified-name-lookup)\n        -   [Type substitution](#type-substitution)\n        -   [Examples](#examples)\n        -   [Termination](#termination)\n    -   [Same type constraints](#same-type-constraints)\n        -   [Implementation of same-type `ImplicitAs`](#implementation-of-same-type-implicitas)\n    -   [Observe declarations](#observe-declarations)\n    -   [Implementing an interface](#implementing-an-interface)\n    -   [Ergonomics](#ergonomics)\n    -   [Implementation experience](#implementation-experience)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Status quo](#status-quo)\n    -   [Restrict constraints to allow computable type equality](#restrict-constraints-to-allow-computable-type-equality)\n    -   [Find a fully transitive approach to type equality](#find-a-fully-transitive-approach-to-type-equality)\n    -   [Different syntax for rewrite constraint](#different-syntax-for-rewrite-constraint)\n    -   [Different syntax for same-type constraint](#different-syntax-for-same-type-constraint)\n    -   [Required ordering for rewrites](#required-ordering-for-rewrites)\n    -   [Multi-constraint `where` clauses](#multi-constraint-where-clauses)\n    -   [Rewrite constraints in `impl as` constraints](#rewrite-constraints-in-impl-as-constraints)\n\n<!-- tocstop -->\n\n## Abstract\n\nSplit the `where A == B` constraint in two: `where .A = B` produces a new\nconstraint from an old one, where the value of `.A` in the new constraint is\nknown and eagerly rewritten to `B`, and `where A == B`, which does not cause `A`\nand `B` to be considered as identical by language rules but does permit implicit\n(no-op) conversion between them.\n\nThis aims to provide an efficiently-computable and human-understandable type\nequality rule, with type canonicalization and therefore transitive type\nequality, without sacrificing too much in the way of ergonomics and without\nsacrificing determinism, while still providing the full power of a general type\nconstraint system in a less ergonomic form.\n\n## Problem\n\n### Equal types with different interfaces\n\nWhen an associated type is constrained to be a concrete type, it is desirable\nfor the associated type to behave like that concrete type:\n\n```\ninterface Hashable {\n  fn Hash[me: Self]() -> u128;\n}\ninterface X {\n  let R:! Hashable;\n  fn Make() -> R;\n}\nfn F[T:! X where .R == i32](x: T) -> i32 {\n  return T.Make() + 1;\n}\n```\n\nHere, we want to be able to use the result of `F.Make()` in all regards like an\n`i32`. Assuming an `i32.Abs` function exists, and `i32` implements `Hashable`\nexternally, it is more desirable for `F.Make().Abs()` to work than it is for\n`F.Make().Hash()` to work.\n\nWe are\n[currently aiming to address this](https://github.com/carbon-language/carbon-lang/pull/2070)\nby saying that when two type expressions are constrained to be equal, a value\nwhose type is either of those type expressions provides the (disjoint) union of\ntheir interfaces. This leads to a surprise:\n\n```\nfn G[T:! X where .R == i32](x: T) -> u128 {\n  let n: i32 = 1;\n  let m: i64 = 2;\n  return n.Hash() ^ m.Hash();\n}\n```\n\nHere, the call to `n.Hash()` is valid but the call to `m.Hash()` is invalid,\nbecause the type `i32` of `n` is constrained to be equal to `T.R` which is of\ntype `Hashable`, but the type `i64` is not constrained in that way and does not\nimplement `Hashable` internally.\n\nThis suggests that there might be two different behaviors that we want when\nadding a constraint: either we are changing the interface, or not. This is\nanalogous to internal versus external implementation of an interface.\n\n### Type canonicalization\n\nThere are a variety of contexts in which types are compared for equality. In\nsome of those contexts, it might be acceptable to perform a search and a\ncomputation, and it might be acceptable to have false negatives. For example,\nwhen analyzing an argument being passed to a function in a generic, it might be\nOK to say \"we can't prove that the argument has a type that is equal to (or\nconvertible to) the type of the parameter\", so long as the developer has some\nway to demonstrate that the types are the same if that is indeed the case.\n\nHowever, not all comparisons of generic types have that property. As an extreme\nand hopefully avoidable example, suppose a C++-like linkage model is used, with\nname mangling. We may need to determine whether two type expressions are equal\nat link time, by reducing them both to strings that are guaranteed to be\nidentical if the types are equal and non-identical otherwise. This requires some\nform of type canonicalization: reducing all equal type expressions to some\ncommon representation where we can faithfully perform equality comparisons.\n\nEven if the semantics of Carbon don't require canonicalization, it is still a\nvery useful property for implementation purposes. For example, if type\ncanonicalization is possible to perform efficiently, building a data structure\nmapping from a type to some value becomes much simpler, and if the\nrepresentation of a type expression carries its canonical form then type\nequality comparisons can be done in constant time.\n\n### Transitivity of equality\n\nFor ergonomic purposes, it is valuable for the notion of type expression\nequality to be transitive: if type A is known to be the same as type B, and type\nB is known to be the same as type C, then shouldn't we be able to use an A where\na C is required? See\n[#1369](https://github.com/carbon-language/carbon-lang/issues/1369) for an\nexplanation of why this is important.\n\nHowever, if we permit arbitrary constraints and have a transitive equality rule,\nthen type equality is isomorphic to the\n[word problem for finitely-presented monoids](https://en.wikipedia.org/wiki/Word_problem_for_groups),\nwhich is undecidable, and certainly not computable, in general.\n\nTherefore we must impose a restriction somewhere: either not all constraints are\npermissible, or we do not have transitivity, or we impose some other constraint\non the language to avoid the hard cases. Some languages merely impose some kind\nof depth limit on their search for a proof of equality.\n\nNote that if we can perform type canonicalization, then type equality is\nnecessarily transitive: if all equal _pairs_ of types canonicalize to the same\nrepresentation, then _all_ equal types canonicalize to the same representation\ntransitively.\n\n### Coherence\n\nIn order to avoid surprises in the language behavior, we want Carbon to have the\nproperty that learning more about the type of a value should not cause the\nbehavior of an expression to change from one valid behavior to another valid\nbehavior.\n\nIt's important to distinguish here between learning more about a type, such as\nlearning that it implements a particular interface – for example, from an added\nimport – and changing the type, such as by writing a different expression after\na `:` or `:!`. Changing the type of a value is expected to be able to change the\nbehavior of an expression using that value.\n\n## Background\n\nThere has been a lot of work in this space. Some previous relevant proposals:\n\n-   [#731: generics details 2](https://github.com/carbon-language/carbon-lang/pull/731)\n    introduced associated types, with the intent that a mechanism to constrain\n    their value would be provided in a later proposal.\n-   [#818: generics details 3](https://github.com/carbon-language/carbon-lang/pull/818)\n    introduced `where` constraints for generics, with an open question for\n    whether and how we might restrict constraints in order to give a decidable\n    type equality rule.\n    -   #818 represents the status quo of approved proposals. It has both `=`\n        and `==` where constraints, which are similar to, but somewhat different\n        from, those in this proposal.\n    -   `=` constraints require a concrete type on their right-hand side. The\n        left-hand side is not restricted. The facet type of the left-hand side\n        type is changed to match the right-hand side.\n    -   `==` constraints do not affect the facet type of either operand.\n    -   As an answer to the question of how to produce a decidable type equality\n        rule, both kinds of constraints are applied automatically, but only at a\n        depth of one constraint. Neither form is transitive but both can be\n        transitively extended using `observe` declarations.\n-   [#2070: always `==` not `=` in `where` clauses](https://github.com/carbon-language/carbon-lang/pull/2070)\n    describes an attempt to unify the syntax and semantics of `=` and `==`\n    constraints, under which we would always merge the facet types of the\n    operands. That proposal has not yet been accepted, and this proposal intends\n    to supersede it.\n\n## Proposal\n\nReplace the semantics of the existing `where A == B` and `where A = B`\nconstraints and restrict the syntax of `where A = B` as follows:\n\n-   `where .A = T` specifies a _rewrite_ constraint. The left-hand side is\n    required to name an associated constant. If that associated constant `.A` is\n    named as a member of a type declared with this constraint, it is rewritten\n    to `T`. This means that the interface of the type changes, and the behavior\n    is in all respects as if `T` had been specified directly.\n-   `where X == Y` specifies a _same-type_ constraint. This is treated much like\n    `where X is SameAs(Y)`. Here, `SameAs` is a hypothetical constraint that is\n    reflexive (`T is SameAs(T)` for all `T`), commutative (`T is SameAs(U)` if\n    and only if `U is SameAs(T)`), and not implementable by the developer.\n    Moreover, if `F` is any pure type function, `T is SameAs(U)` implies\n    `F(T) is SameAs(F(U)`). `observe` statements can be used to form transitive\n    `SameAs` relations. Same-type constraints are not used automatically by the\n    language rules for any purpose, but a blanket `ImplicitAs` impl permits\n    conversions between types that are known to be the same:\n    ```\n    impl forall [T:! type, U:! type where .Self == T] T as ImplicitAs(U);\n    ```\n\nA type implements `C where .A = T` if and only if it implements\n`C where .A == T`, assuming both constraints are valid – the inhabitants of\nthese two facet types are the same, but they are different facet types and\nprovide different interfaces for corresponding type values.\n\n## Details\n\n### Rewrite constraints\n\nIn a rewrite constraint, the left-hand operand of `=` must be a `.` followed by\nthe name of an associated constant. `.Self` is not permitted.\n\n```\ninterface RewriteSelf {\n  // ❌ Error: `.Self` is not the name of an associated constant.\n  let Me:! type where .Self = Self;\n}\ninterface HasAssoc {\n  let Assoc:! type;\n}\ninterface RewriteSingleLevel {\n  // ✅ Uses of `A.Assoc` will be rewritten to `i32`.\n  let A:! HasAssoc where .Assoc = i32;\n}\ninterface RewriteMultiLevel {\n  // ❌ Error: Only one level of associated constant is permitted.\n  let B:! RewriteSingleLevel where .A.Assoc = i32;\n}\n```\n\nThis notation is permitted anywhere a constraint can be written, and results in\na new constraint with a different interface: the named member effectively no\nlonger names an associated constant of the constrained type, and is instead\ntreated as a rewrite rule that expands to the right-hand side of the constraint,\nwith any mentioned parameters substituted into that type.\n\n```\ninterface Container {\n  let Element:! type;\n  let Slice:! Container where .Element = Element;\n  fn Add[addr me: Self*](x: Element);\n}\n// `T.Slice.Element` rewritten to `T.Element`\n//     because type of `T.Slice` says `.Element = Element`.\n// `T.Element` rewritten to `i32`\n//     because type of `T` says `.Element = i32`.\nfn Add[T:! Container where .Element = i32](p: T*, y: T.Slice.Element) {\n  // ✅ Argument `y` has the same type `i32` as parameter `x` of\n  // `T.(Container.Add)`, which is also rewritten to `i32`.\n  p->Add(y);\n}\n```\n\nRewrites aren't performed on the left-hand side of such an `=`, so\n`where .A = .B and .A = C` is not rewritten to `where .A = .B and .B = C`.\nInstead, such a `where` clause is invalid when the constraint is\n[resolved](#constraint-resolution) unless each rule for `.A` specifies the same\nrewrite.\n\nNote that `T:! C where .R = i32` can result in a type `T.R` whose behavior is\ndifferent from the behavior of `T.R` given `T:! C`. For example, member lookup\ninto `T.R` can find different results and operations can therefore have\ndifferent behavior. However, this does not violate coherence because the facet\ntypes `C` and `C where .R = i32` don't differ by merely having more type\ninformation; rather, they are different facet types that have an isomorphic set\nof values, somewhat like `i32` and `u32`. An `=` constraint is not merely\nlearning a new fact about a type, it is requesting different behavior.\n\n### Combining constraints with `&`\n\nSuppose we have `X = C where .R = A` and `Y = C where .R = B`. What should\n`C & X` produce? What should `X & Y` produce?\n\nWe could perhaps say that `X & Y` results in a facet type where the type of `R`\nhas the union of the interface of `A` and the interface of `B`, and that `C & X`\nsimilarly results in a facet type where the type of `R` has the union of the\ninterface of `A` and the interface originally specified by `C`. However, this\nproposal suggests a simpler rule:\n\n-   Combining two rewrite rules with different rewrite targets results in a\n    facet type where the associated constant is ambiguous. Given `T:! X & Y`,\n    the type expression `T.R` is ambiguous between a rewrite to `A` and a\n    rewrite to `B`. But given `T:! X & X`, `T.R` is unambiguously rewritten to\n    `A`.\n-   Combining a constraint with a rewrite rule with a constraint with no rewrite\n    rule preserves the rewrite rule. For example, supposing that\n    `interface Container` extends `interface Iterable`, and `Iterable` has an\n    associated constant `Element`, the constraint\n    `Container & (Iterable where .Element = i32)` is the same as the constraint\n    `(Container & Iterable) where .Element = i32` which is the same as the\n    constraint `Container where .Element = i32`.\n\nIf the rewrite for an associated constant is ambiguous, the facet type is\nrejected during [constraint resolution](#constraint-resolution).\n\n### Combining constraints with `and`\n\nIt's possible for one `=` constraint in a `where` to refer to another. When this\nhappens, the facet type `C where A and B` is interpreted as\n`(C where A) where B`, so rewrites in `A` are applied immediately to names in\n`B`, but rewrites in `B` are not applied to names in `A` until the facet type is\n[resolved](#constraint-resolution):\n\n```\ninterface C {\n  let T:! type;\n  let U:! type;\n  let V:! type;\n}\nclass M {\n  alias Me = Self;\n}\n// ✅ Same as `C where .T = M and .U = M.Me`, which is\n// the same as `C where .T = M and .U = M`.\nfn F[A:! C where .T = M and .U = .T.Me]() {}\n// ❌ No member `Me` in `A.T:! type`.\nfn F[A:! C where .U = .T.Me and .T = M]() {}\n```\n\n### Combining constraints with `extends`\n\nWithin an interface or named constraint, `extends` can be used to extend a\nconstraint that has rewrites.\n\n```\ninterface A {\n  let T:! type;\n  let U:! type;\n}\ninterface B {\n  extends A where .T = .U and .U = i32;\n}\n\nvar n: i32;\n\n// ✅ Resolved constraint on `T` is\n// `B where .(A.T) = i32 and .(A.U) = i32`.\n// `T.(A.T)` is rewritten to `i32`.\nfn F(T:! B) -> T.(A.T) { return n; }\n```\n\n### Combining constraints with `impl as` and `is`\n\nWithin an interface or named constraint, the `impl T as C` syntax does not\npermit `=` constraints to be specified directly. However, such constraints can\nbe specified indirectly, for example if `C` is a named constraint that contains\nrewrites. Because these constraints don't change the type of `T`, rewrite\nconstraints in this context will never result in a rewrite being performed, and\ninstead are equivalent to `==` constraints.\n\n```\ninterface A {\n  let T:! type;\n  let U:! type;\n}\nconstraint C {\n  extends A where .T = .U and .U = i32;\n}\nconstraint D {\n  extends A where .T == .U and .U == i32;\n}\ninterface B {\n  // OK, equivalent to `impl as D;` or\n  // `impl as A where .T == .U and .U == i32;`.\n  impl as C;\n}\n\nvar n: i32;\n\n// ❌ No implicit conversion from `i32` to `T.(A.T)`.\n// Resolved constraint on `T` is\n// `B where T.(A.T) == T.(A.U) and T.(A.U) = i32`.\n// `T.(A.T)` is single-step equal to `T.(A.U)`, and\n// `T.(A.U)` is single-step equal to `i32`, but\n// `T.(A.T)` is not single-step equal to `i32`.\nfn F(T:! B) -> T.(A.T) { return n; }\n```\n\nA purely syntactic check is used to determine if an `=` is specified directly in\nan expression:\n\n-   An `=` constraint is specified directly in its enclosing `where` expression.\n-   If an `=` constraint is specified directly in an operand of an `&` or\n    `(`...`)`, then it is specified directly in that enclosing expression.\n\nIn an `impl as C` or `impl T as C` declaration in an interface or named\nconstraint, `C` is not allowed to directly specify any `=` constraints:\n\n```\n// Compile-time identity function.\nfn Identity[T:! type](x:! T) -> T { return x; }\n\ninterface E {\n  // ❌ Rewrite constraint specified directly.\n  impl as A where .T = .U and .U = i32;\n  // ❌ Rewrite constraint specified directly.\n  impl as type & (A where .T = .U and .U = i32);\n  // ✅ Not specified directly, but does not result\n  // in any rewrites being performed.\n  impl as Identity(A where .T = .U and .U = i32);\n}\n```\n\nThe same rules apply to `is` constraints. Note that `.T == U` constraints are\nalso not allowed in this context, because the reference to `.T` is rewritten to\n`.Self.T`, and `.Self` is ambiguous.\n\n```\n// ❌ Rewrite constraint specified directly in `is`.\nfn F[T:! A where .U is (A where .T = i32)]();\n\n// ❌ Reference to `.T` in same-type constraint is ambiguous:\n// does this mean the outer or inner `.Self.T`?\nfn G[T:! A where .U is (A where .T == i32)]();\n\n// ✅ Not specified directly, but does not result\n// in any rewrites being performed. Return type\n// is not rewritten to `i32`.\nfn H[T:! type where .Self is C]() -> T.(A.U);\n\n// ✅ Return type is rewritten to `i32`.\nfn I[T:! C]() -> T.(A.U);\n```\n\n### Constraint resolution\n\nWhen a facet type is used as the declared type of a type `T`, the constraints\nthat were specified within that facet type are _resolved_ to determine the\nconstraints that apply to `T`. This happens:\n\n-   When the constraint is used explicitly, when declaring a generic parameter\n    or associated constant of the form `T:! Constraint`.\n-   When declaring that a type implements a constraint with an `impl`\n    declaration, such as `impl T as Constraint`. Note that this does not include\n    `impl ... as` constraints appearing in `interface` or `constraint`\n    declarations.\n\nIn each case, the following steps are performed to resolve the facet type's\nabstract constraints into a set of constraints on `T`:\n\n-   If multiple rewrites are specified for the same associated constant, they\n    are required to be identical, and duplicates are discarded.\n-   Rewrites are performed on other rewrites in order to find a fixed point,\n    where no rewrite applies within any other rewrite. If no fixed point exists,\n    the generic parameter declaration or `impl` declaration is invalid.\n-   Rewrites are performed throughout the other constraints in the facet type --\n    that is, in any `==` constraints and `is` constraints -- and the type\n    `.Self` is replaced by `T` throughout the constraint.\n\n```\n// ✅ `.T` in `.U = .T` is rewritten to `i32` when initially\n// forming the facet type.\n// Nothing to do during constraint resolution.\nfn InOrder[A:! C where .T = i32 and .U = .T]() {}\n// ✅ Facet type has `.T = .U` before constraint resolution.\n// That rewrite is resolved to `.T = i32`.\nfn Reordered[A:! C where .T = .U and .U = i32]() {}\n// ✅ Facet type has `.U = .T` before constraint resolution.\n// That rewrite is resolved to `.U = i32`.\nfn ReorderedIndirect[A:! (C where .T = i32) & (C where .U = .T)]() {}\n// ❌ Constraint resolution fails because\n// no fixed point of rewrites exists.\nfn Cycle[A:! C where .T = .U and .U = .T]() {}\n```\n\nTo find a fixed point, we can perform rewrites on other rewrites, cycling\nbetween them until they don't change or until a rewrite would apply to itself.\nIn the latter case, we have found a cycle and can reject the constraint. Note\nthat it's not sufficient to expand only a single rewrite until we hit this\ncondition:\n\n```\n// ❌ Constraint resolution fails because\n// no fixed point of rewrites exists.\n// If we only expand the right-hand side of `.T`,\n// we find `.U`, then `.U*`, then `.U**`, and so on,\n// and never detect a cycle.\n// If we alternate between them, we find\n// `.T = .U*`, then `.U = .U**`, then `.V = .U***`,\n// then `.T = .U**`, then detect that the `.U` rewrite\n// would apply to itself.\nfn IndirectCycle[A:! C where .T = .U and .U = .V* and .V = .U*]();\n```\n\nAfter constraint resolution, no references to rewritten associated constants\nremain in the constraints on `T`.\n\nIf a facet type is never used to constrain a type, it is never subject to\nconstraint resolution, and it is possible for a facet type to be formed for\nwhich constraint resolution would always fail. For example:\n\n```\npackage Broken api;\n\ninterface X {\n  let T:! type;\n  let U:! type;\n}\nlet Bad:! auto = (X where .T = .U) & (X where .U = .T);\n// Bad is not used here.\n```\n\nIn such cases, the facet type `Broken.Bad` is not usable: any attempt to use\nthat facet type to constrain a type would perform constraint resolution, which\nwould always fail because it would discover a cycle between the rewrites for\n`.T` and for `.U`. In order to ensure that such cases are diagnosed, a trial\nconstraint resolution is performed for all facet types. Note that this trial\nresolution can be skipped for facet types that are actually used, which is the\ncommon case.\n\n### Precise rules and termination\n\nThis section explains the detailed rules used to implement rewrites. There are\ntwo properties we aim to satisfy:\n\n1.  After type-checking, no symbolic references to associated constants that\n    have an associated rewrite rule remain.\n2.  Type-checking always terminates in a reasonable amount of time, ideally\n    linear in the size of the problem.\n\nRewrites are applied in two different phases of program analysis.\n\n-   During qualified name lookup and type checking for qualified member access,\n    if a rewritten member is looked up, the right-hand side's value and type are\n    used for subsequent checks.\n-   During substitution, if the symbolic name of an associated constant is\n    substituted into, and substitution into the left-hand side results in a\n    value with a rewrite for that constant, that rewrite is applied.\n\nIn each case, we always rewrite to a value that satisfies property 1 above, and\nthese two steps are the only places where we might form a symbolic reference to\nan associated cosntant, so property 1 is recursively satisfied. Moreover, we\napply only one rewrite in each of the above cases, satisfying property 2.\n\n#### Qualified name lookup\n\nQualified name lookup into either a type parameter or into an expression whose\ntype is a symbolic type `T` -- either a type parameter or an associated type --\nconsiders names from the facet type `C` of `T`, that is, from `T`’s declared\ntype.\n\n```\ninterface C {\n  let M:! i32;\n  let U:! C;\n}\nfn F[T:! C](x: T) {\n  // Value is C.M in all four of these\n  let a: i32 = x.M;\n  let b: i32 = T.M;\n  let c: i32 = x.U.M;\n  let d: i32 = T.U.M;\n}\n```\n\nWhen looking up the name `N`, if `C` is an interface `I` and `N` is the name of\nan associated constant in that interface, the result is a symbolic value\nrepresenting \"the member `N` of `I`\". If `C` is formed by combining interfaces\nwith `&`, all such results are required to find the same associated constant,\notherwise we reject for ambiguity.\n\nIf a member of a class or interface is named in a qualified name lookup, the\ntype of the result is determined by performing a substitution. For an interface,\n`Self` is substituted for the self type, and any parameters for that class or\ninterface (and enclosing classes or interfaces, if any) are substituted into the\ndeclared type.\n\n```\ninterface SelfIface {\n  fn Get[me: Self]() -> Self;\n}\nclass UsesSelf(T:! type) {\n  // Equivalent to `fn Make() -> UsesSelf(T)*;`\n  fn Make() -> Self*;\n  impl as SelfIface;\n}\n\n// ✅ `T = i32` is substituted into the type of `UsesSelf(T).Make`,\n// so the type of `UsesSelf(i32).Make` is `fn () -> UsesSelf(i32)*`.\nlet x: UsesSelf(i32)* = UsesSelf(i32).Make();\n\n// ✅ `Self = UsesSelf(i32)` is substituted into the type\n// of `SelfIface.Get`, so the type of `UsesSelf(i32).(SelfIface.Get)`\n// is `fn [me: UsesSelf(i32)]() -> UsesSelf(i32)`.\nlet y: UsesSelf(i32) = x->Get();\n```\n\nNone of this is new in this proposal. This proposal adds the rule:\n\nIf a facet type `C` into which lookup is performed includes a `where` clause\nsaying `.N = U`, and the result of qualified name lookup is the associated\nconstant `N`, that result is replaced by `U`, and the type of the result is the\ntype of `U`. No substitution is performed in this step, not even a `Self`\nsubstitution -- any necessary substitutions were already performed when forming\nthe facet type `C`, and we don’t consider either the declared type or value of\nthe associated constant at all for this kind of constraint. Going through an\nexample in detail:\n\n```\ninterface A {\n  let T:! type;\n}\ninterface B {\n  let U:! type;\n  // More explicitly, this is of type `A where .(A.T) = Self.(B.U)`\n  let V:! A where .T = U;\n}\n// Type of T is B.\nfn F[T:! B](x: T) {\n  // The type of the expression `T` is `B`.\n  // `T.V` finds `B.V` with type `A where .(A.T) = Self.(B.U)`.\n  // We substitute `Self` = `T` giving the type of `u` as\n  // `A where .(A.T) = T.(B.U)`.\n  let u:! auto = T.V;\n  // The type of `u` is `A where .(A.T) = T.(B.U)`.\n  // Lookup for `u.T` resolves it to `u.(A.T)`.\n  // So the result of the qualified member access is `T.(B.U)`,\n  // and the type of `v` is the type of `T.(B.U)`, namely `type`.\n  // No substitution is performed in this step.\n  let v:! auto = u.T;\n}\n```\n\nThe more complex case of\n\n```\nfn F2[T:! B where .U = i32](x: T);\n```\n\nis discussed later.\n\n#### Type substitution\n\nAt various points during the type-checking of a Carbon program, we need to\nsubstitute a set of (binding, value) pairs into a symbolic value. We saw an\nexample above: substituting `Self = T` into the type `A where .(A.T) = Self.U`\nto produce the value `A where .(A.T) = T.U`. Another important case is the\nsubstitution of inferred parameter values into the type of a function when\ntype-checking a function call:\n\n```\nfn F[T:! C](x: T) -> T;\nfn G(n: i32) -> i32 {\n  // Deduces T = i32, which is substituted\n  // into the type `fn (x: T) -> T` to produce\n  // `fn (x: i32) -> i32`, giving `i32` as the type\n  // of the call expression.\n  return F(n);\n}\n```\n\nQualified name lookup is not re-done as a result of type substitution. For a\ntemplate, we imagine there’s a completely separate step that happens before type\nsubstitution, where qualified name lookup is redone based on the actual value of\ntemplate arguments; this proceeds as described in the previous section.\nOtherwise, we performed the qualified name lookup when type-checking the\ngeneric, and do not do it again:\n\n```\ninterface IfaceHasX {\n  let X:! type;\n}\nclass ClassHasX {\n  class X {}\n}\ninterface HasAssoc {\n  let Assoc:! IfaceHasX;\n}\n\n// Qualified name lookup finds `T.(HasAssoc.Assoc).(IfaceHasX.X)`.\nfn F(T:! HasAssoc) -> T.Assoc.X;\n\nfn G(T:! HasAssoc where .Assoc = ClassHasX) {\n  // `T.Assoc` rewritten to `ClassHasX` by qualified name lookup.\n  // Names `ClassHasX.X`.\n  var a: T.Assoc.X = {};\n  // Substitution produces `ClassHasX.(IfaceHasX.X)`,\n  // not `ClassHasX.X`.\n  var b: auto = F(T);\n}\n```\n\nDuring substitution, we might find a member access that named an opaque symbolic\nassociated constant in the original value can now be resolved to some specific\nvalue. It’s important that we perform this resolution:\n\n```\ninterface A {\n  let T:! type;\n}\nclass K { fn Member(); }\nfn H[U:! A](x: U) -> U.T;\nfn J[V:! A where .T = K](y: V) {\n  // We need the interface of `H(y)` to include\n  // `K.Member` in order for this lookup to succeed.\n  H(y).Member();\n}\n```\n\nThe values being substituted into the symbolic value are themselves already\nfully substituted and resolved, and in particular, satisfy property 1 given\nabove.\n\nSubstitution proceeds by recursively rebuilding each symbolic value, bottom-up,\nreplacing each substituted binding with its value. Doing this naively will\npropagate values like `i32` in the `F`/`G` case earlier in this section, but\nwill not propagate rewrite constants like in the `H`/`J` case. The reason is\nthat the `.T = K` constraint is in the _type_ of the substituted value, rather\nthan in the substituted value itself: deducing `T = i32` and converting `i32` to\nthe type `C` of `T` preserves the value `i32`, but deducing `U = V` and\nconverting `V` to the type `A` of `U` discards the rewrite constraint.\n\nIn order to apply rewrites during substitution, we associate a set of rewrites\nwith each value produced by the recursive rebuilding procedure. This is somewhat\nlike having substitution track a refined facet type for the type of each value,\nbut we don’t need -- or want -- for the type to change during this process, only\nfor the rewrites to be properly applied. For a substituted binding, this set of\nrewrites is the rewrites found on the type of the corresponding value prior to\nconversion to the type of the binding. When rebuilding a member access\nexpression, if we have a rewrite corresponding to the accessed member, then the\nresulting value is the target of the rewrite, and its set of rewrites is that\nfound in the type of the target of the rewrite, if any. Because the target of\nthe rewrite is fully resolved already, we can ask for its type without\ntriggering additional work. In other cases, the rewrite set is empty; all\nnecessary rewrites were performed when type-checking the value we're\nsubstituting into.\n\nContinuing an example from [qualified name lookup](#qualified-name-lookup):\n\n```\ninterface A {\n  let T:! type;\n}\ninterface B {\n  let U:! type;\n  let V:! A where .T = U;\n}\n\n// Type of the expression `T` is `B where .(B.U) = i32`\nfn F2[T:! B where .U = i32](x: T) {\n  // The type of the expression `T` is `B where .U = i32`.\n  // `T.V` is looked up and finds the associated type `(B.V)`.\n  // The declared type is `A where .(A.T) = Self.U`.\n  // We substitute `Self = T` with rewrite `.U = i32`.\n  // The resulting type is `A where .(A.T) = i32`.\n  // So `u` is `T.V` with type `A where .(A.T) = i32`.\n  let u:! auto = T.V;\n  // The type of `u` is `A where .(A.T) = i32`.\n  // Lookup for `u.T` resolves it to `u.(A.T)`.\n  // So the result of the qualified member access is `i32`,\n  // and the type of `v` is the type of `i32`, namely `type`.\n  // No substitution is performed in this step.\n  let v:! auto = u.T;\n}\n```\n\n#### Examples\n\n```\ninterface Container {\n  let Element:! type;\n}\ninterface SliceableContainer {\n  extends Container;\n  let Slice:! Container where .Element = Self.(Container.Element);\n}\n// ❌ Qualified name lookup rewrites this facet type to\n// `SliceableContainer where .(Container.Element) = .Self.(Container.Element)`.\n// Constraint resolution rejects this because this rewrite forms a cycle.\nfn Bad[T:! SliceableContainer where .Element = .Slice.Element](x: T.Element) {}\n```\n\n```\ninterface Helper {\n  let D:! type;\n}\ninterface Example {\n  let B:! type;\n  let C:! Helper where .D = B;\n}\n// ✅ `where .D = ...` by itself is fine.\n// `T.C.D` is rewritten to `T.B`.\nfn Allowed(T:! Example, x: T.C.D);\n// ❌ But combined with another rewrite, creates an infinite loop.\n// `.C.D` is rewritten to `.B`, resulting in `where .B = .B`,\n// which causes an error during constraint resolution.\n// Using `==` instead of `=` would make this constraint redundant,\n// rather than it being an error.\nfn Error(T:! Example where .B = .C.D, x: T.C.D);\n```\n\n```\ninterface Allowed;\ninterface AllowedBase {\n  let A:! Allowed;\n}\ninterface Allowed {\n  extends AllowedBase where .A = .Self;\n}\n// ✅ The final type of `x` is `T`. It is computed as follows:\n// In `((T.A).A).A`, the inner `T.A` is rewritten to `T`,\n// resulting in `((T).A).A`, which is then rewritten to\n// `(T).A`, which is then rewritten to `T`.\nfn F(T:! Allowed, x: ((T.A).A).A);\n```\n\n```\ninterface MoveYsRight;\nconstraint ForwardDeclaredConstraint(X:! MoveYsRight);\ninterface MoveYsRight {\n  let X:! MoveYsRight;\n  // Means `Y:! MoveYsRight where .X = X.Y`\n  let Y:! ForwardDeclaredConstraint(X);\n}\nconstraint ForwardDeclaredConstraint(X:! MoveYsRight) {\n  extends MoveYsRight where .X = X.Y;\n}\n// ✅ The final type of `x` is `T.X.Y.Y`. It is computed as follows:\n// The type of `T` is `MoveYsRight`.\n// The type of `T.Y` is determined as follows:\n// -   Qualified name lookup finds `MoveYsRight.Y`.\n// -   The declared type is `ForwardDeclaredConstraint(Self.X)`.\n// -   That is a named constraint, for which we perform substitution.\n//     Substituting `X = Self.X` gives the type\n//     `MoveYsRight where .X = Self.X.Y`.\n// -   Substituting `Self = T` gives the type\n//     `MoveYsRight where .X = T.X.Y`.\n// The type of `T.Y.Y` is determined as follows:\n// -   Qualified name lookup finds `MoveYsRight.Y`.\n// -   The declared type is `ForwardDeclaredConstraint(Self.X)`.\n// -   That is a named constraint, for which we perform substitution.\n//     Substituting `X = Self.X` gives the type\n//     `MoveYsRight where .X = Self.X.Y`.\n// -   Substituting `Self = T.Y` with\n//     rewrite `.X = T.X.Y` gives the type\n//     `MoveYsRight where .X = T.Y.X.Y`, but\n//     `T.Y.X` is replaced by `T.X.Y`, giving\n//     `MoveYsRight where .X = T.X.Y.Y`.\n// The type of `T.Y.Y.X` is determined as follows:\n// -   Qualified name lookup finds `MoveYsRight.X`.\n// -   The type of `T.Y.Y` says to rewrite that to `T.X.Y.Y`.\n// -   The result is `T.X.Y.Y`, of type `MoveYsRight`.\nfn F4(T:! MoveYsRight, x: T.Y.Y.X);\n```\n\n#### Termination\n\nEach of the above steps performs at most one rewrite, and doesn't introduce any\nnew recursive type-checking steps, so should not introduce any new forms of\nnon-termination. Rewrite constraints thereby give us a deterministic,\nterminating type canonicalization mechanism for associated constants: in `A.B`,\nif the type of `A` specifies that `.B = C`, then `A.B` is replaced by `C`.\nEquality of types constrained in this way is transitive.\n\nHowever, some existing forms of non-termination may remain, such as template\ninstantiation triggering another template instantiation. Such cases will need to\nbe detected and handled in some way, such as by a depth limit, but doing so\ndoesn't compromise the soundness of the type system.\n\n### Same type constraints\n\nA same-type constraint describes that two type expressions are known to evaluate\nto the same value. Unlike a rewrite constraint, however, the two type\nexpressions are treated as distinct types when type-checking a generic that\nrefers to them.\n\nSame-type constraints are brought into scope, looked up, and resolved exactly as\nif there were a `SameAs(U:! type)` interface and a `T == U` impl corresponded to\n`T is SameAs(U)`, except that `==` is commutative. As such, it's not possible to\nask for a list of types that are the same as a given type, nor to ask whether\nthere exists a type that is the same as a given type and has some property. But\nit is possible to ask whether two types are (non-transitively) the same.\n\nIn order for same-type constraints to be useful, they must allow the two types\nto be treated as actually being the same in some context. This can be\naccomplished by the use of `==` constraints in an `impl`, such as in the\nbuilt-in implementation of `ImplicitAs`:\n\n```\nfinal impl forall [T:! type, U:! type where .Self == T] T as ImplicitAs(U) {\n  fn Convert[me: Self](other: U) -> U { ... }\n}\n```\n\nIt superficially seems like it would be convenient if such implementations were\nmade available implicitly – for example, by writing\n`impl forall [T:! type] T as ImplicitAs(T)` – but in more complex examples that\nturns out to be problematic. Consider:\n\n```\ninterface CommonTypeWith(U:! type) {\n  let Result:! type;\n}\nfinal impl forall [T:! type] T as CommonTypeWith(T) where .Result = T {}\n\nfn F[T:! Potato, U:! Hashable where .Self == T](x: T, y: U) -> auto {\n  // What is T.CommonTypeWith(U).Result? Is it T or U?\n  return (if cond then x else y).Hash();\n}\n```\n\nWith this proposal, `impl` validation for `T as CommonTypeWith(U)` fails: we\ncannot pick a common type when given two distinct type expressions, even if we\nknow they evaluate to the same type, because we would not know which API the\nresult should have.\n\n#### Implementation of same-type `ImplicitAs`\n\nIt is possible to implement the above `impl` of `ImplicitAs` directly in Carbon,\nwithout a compiler builtin, by taking advantage of the built-in conversion\nbetween `C where .A = X` and `C where .A == X`:\n\n```\ninterface EqualConverter {\n  let T:! type;\n  fn Convert(t: T) -> Self;\n}\nfn EqualConvert[T:! type](t: T, U:! EqualConverter where .T = T) -> U {\n  return U.Convert(t);\n}\nimpl forall [U:! type] U as EqualConverter where .T = U {\n  fn Convert(u: U) -> U { return u; }\n}\n\nimpl forall [T:! type, U:! type where .Self == T] T as ImplicitAs(U) {\n  fn Convert[self: Self]() -> U { return EqualConvert(self, U); }\n}\n```\n\nThe transition from `(T as ImplicitAs(U)).Convert`, where we know that `U == T`,\nto `EqualConverter.Convert`, where we know that `.T = U`, allows a same-type\nconstraint to be used to perform a rewrite.\n\nThis implementation is in use in Carbon Explorer.\n\n### Observe declarations\n\nSame-type constraints are non-transitive, just like other constraints such as\n`ImplicitAs`. The developer can use an `observe` declaration to bring a new\nsame-type constraint into scope:\n\n```\nobserve A == B == C;\n```\n\nnotionally does much the same thing as\n\n```\nimpl A as SameAs(C) { ... }\n```\n\nwhere the `impl` makes use of `A is SameAs(B)` and `B is SameAs(C)`.\n\n### Implementing an interface\n\nWhen implementing an interface, the `=` syntax must be used, and each associated\nconstant without a default must be explicitly assigned-to:\n\n```\nimpl IntVec as Container where .Element = i32 { ... }\n```\n\nnot\n\n```\nimpl IntVec as Container where .Element == i32 { ... }\n```\n\nThe latter would be treated as\n\n```\nimpl IntVec as Container where IntVec.Element is SameAs(i32) { ... }\n```\n\n... which only checks the value of `Element` rather than specifying it.\n\nAs in other contexts, `Self.Element` is rewritten to `i32` within the context of\nthe `impl`.\n\n### Ergonomics\n\nThis proposal can be viewed as dividing type constraints into two categories:\n\n-   Ergonomic, but quite restricted, constraints using `=`.\n-   Non-ergonomic, but fully general, constraints using `==`.\n\nIn order for this to be an effective and ergonomic strategy, we require both\nthat the difference between these two kinds of constraints are readily\nunderstood by developers, and that the more-ergonomic `=` constraints cover\nsufficiently many scenarios that the developer seldom needs to write code to\nrequest a conversion between types that are known to be the same.\n\nIdeally, we hope that `=` constraints will cover all real situations, and `==`\nconstraints will never need to be written, outside of the one `ImplicitAs`\nimplementation described above. If this turns out to be true in practice, we\nshould consider removing `==` syntax from the language. However, this will not\nremove `==` semantics, both because of the behavior of `ImplicitAs` and because\n`impl T as C where .A = B` constraints in an interface or named constraint give\nrise to `==` semantics.\n\n### Implementation experience\n\nThis proposal has been mostly implemented in Carbon Explorer, and appears to\nbehave as expected. However, Explorer does not yet support forward declarations\nof interfaces and constraints, which means that some of the more interesting\ncases can't be tested.\n\n## Rationale\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   This rule is easy to implement, and even a naive implementation should\n        be efficient.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   The status quo causes coincidentally equal types to have the same\n        interface. Under this proposal, the interface of a type is not affected\n        by coincidental equality, only by intentional assignment to an\n        associated type.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Using `=` rather than `==` in `impl`s is easier to read and write.\n    -   The interface available on a type is more predictable in this proposal\n        than in the status quo ante, making code easier to understand.\n\n## Alternatives considered\n\n### Status quo\n\nThe [Problem](#problem) section describes some concerns with the status quo\napproach. This proposal aims to address those concerns.\n\n### Restrict constraints to allow computable type equality\n\nWe could somehow restrict which constraints can be specified, in order to ensure\nthat our type equality rule is efficiently computable, perhaps even in a way\nthat permits a deterministic computation of a canonical type. The exact details\nof how we would do this have not been worked out, but this might lead to a\ncoherent rule that has transitive type equality. However, this would not solve\nthe \"equal types with different interfaces\" problem.\n\n### Find a fully transitive approach to type equality\n\nThis proposal makes type equality transitive, but still has non-transitive\n\"same-type\" constraints describing types that are known to always eventual be\nthe same after substitution, but which are not treated as the same type value\nwhile type-checking a generic. This proposal also imposes a directionality on\nrewrites, a restriction to only rewrite at a depth of exactly one associated\nconstant, and a restriction that only one value can be specified as equal to a\ngiven associated constant. We could seek a type equality rule that would avoid\nhaving two different kinds of equality and would avoid some or all of the\nrestrictions placed on rewrite constraints.\n\nOne candidate approach is to accept that the full generality of the equality\nproblem is\n[hard](https://link.springer.com/content/pdf/10.1007/3-540-17220-3_7.pdf), but\nattempt to solve it anyway. Because of the close correspondence between Turing\nmachines and string rewriting systems, this results in a type system with no\nupper bound on its runtime. We consider this unacceptable for Carbon, but it is\nthe approach taken by some other modern languages:\n\n-   Swift has an\n    [undecidable type system](https://forums.swift.org/t/swift-type-checking-is-undecidable/39024)\n    due to this, and handles the problem by placing a limit on the complexity of\n    cases they will accept, but that seems unsuited to Carbon's goals, as the\n    rule cannot be readily understood by a developer nor effectively worked\n    around.\n-   Rust also has an\n    [undecidable type system](https://sdleffler.github.io/RustTypeSystemTuringComplete/)\n    (content warning: contains many instances of an obscene word as part of a\n    programming language name) for the same reason, and similarly has a\n    recursion limit.\n\nSee also\n[Typing is Hard](https://web.archive.org/web/20231223005655/https://3fx.ch/typing-is-hard.html),\nwhich lists similar information for a variety of other languages. Note that most\nlanguages listed have an undecidable type system.\n\nAnother candidate approach is to find a way to reduce the inputs to the\ntype-checking step as a set of non-quantified equalities. The resulting system\nof equalities can then be\n[solved efficiently](https://dl.acm.org/doi/pdf/10.1145/322186.322198) to\ndetermine whether two types are known to be the same. This approach appears\nsufficient to cope with locally declared constraints, but when constraints\nappear within interfaces, they can give rise to an infinite family of\nequalities, and picking any finite subset risks the result being non-transitive\nin general, if a different subset of equalities might be considered in a\ndifferent type-checking context.\n\n### Different syntax for rewrite constraint\n\nWe could use a different syntax, such as `~>`, for rewrite constraints. This\nwould have the advantage of not using assignment for an operation that's not\nalways doing something that developers will think of as assignment. It also\navoids hard-to read code in cases where a binding has an initializer:\n\n```\n// This proposal.\nlet T:! Add where .Result = i32 = i32;\n// Alternative syntax.\nlet T:! Add where .Result ~> i32 = i32;\n```\n\nHowever, it seems valuable to use only a single syntax for specifying these\nconstraints, and equality is the appropriate mental model most of the time.\nMoreover, in an `impl` declaration, we really are assigning to the associated\nconstant in the sense of setting a value, rather than merely constraining a\nvalue.\n\nThis decision should be revisited if a superior syntax that avoids the above\nvisual ambiguity is suggested.\n\n### Different syntax for same-type constraint\n\nWe considered various options for the spelling of a same-type constraint:\n\n-   `where A == B`\n-   `where A ~ B`\n-   some other operator symbol\n-   `where A is SameType(B)`, or some other constraint name\n\nThe advantage of `==` is that it has a lot of desirable implications: it's\nfamiliar, symmetric, and connotes the left and right operand being the same.\nHowever, it also might be taken as suggesting that the `==` overloaded operator\nis used to determine equality. A different spelling would also indicate that\nthis is an unusual constraint, and would be easier to search for. Concerns were\nalso raised that `==` might suggest transitivity if taken to mean \"same value\"\nrather than something like the Carbon `==` binary operator, and the transitivity\nof `==` constraints is not automatic.\n\nThe `~` operator is currently not in use as a binary operator. However, that\nmakes it quite valuable syntactic real estate, and it may see little use in this\ncontext in practice. A longer operator could be used, but any choice other than\n`==` will present an unfamiliarity barrier, and longer operators will be harder\nto remember.\n\nA named constraint is appealing, but this operator does not behave like a named\nconstraint in that it is automatically symmetrized, not implementable, and\nespecially in its interactions with `observe` declarations. It is unclear how\n`observe` declarations would be written with a named `SameType` constraint:\n\n```\n// Maybe something like this special-case and verbose syntax?\nobserve A is SameType(B) and B is SameType(C) => A is SameType(C);\n```\n\nThe fundamental connection between same-type constraints and `observe` suggests\nthat dedicated syntax is justified.\n\nFor now, we use `==`, despite it having a different meaning in the context of a\nconstraint than in expression contexts. This is analogous to how `=` and `and`\nhave different meanings in this context from in expressions, so the behavior\ndivergence is at least consistent. It's also not clear at this stage how much\nusage same-type constraints will have, compared to rewrite constraints, so it's\nhard to judge the other arguments in favor of and against other operators. It\nwould be reasonable to revisit this decision when we have more usage\ninformation.\n\n### Required ordering for rewrites\n\nWe considered a rule where a rewrite would need to be specified in a constraint\nbefore the associated constant is used. For example:\n\n```\ninterface C {\n  let T:! type;\n  let U:! type;\n}\n// Could reject, `.U` referenced before rewrite is defined.\nfn G[A:! C where .T = .U and .U = i32]() {}\n```\n\nThis would remove the need to perform constraint resolution. Instead, we could\napply rewrites as we form the constraint, and constraints formed in this way\nwould always satisfy the property that they don't refer to associated constants\nthat have a rewrite.\n\nIt may also be less surprising to use this rule. Because Carbon uses top-down\nprocessing for type-checking in general, it may be unexpected that a rewrite\nrule would rewrite an earlier occurrence of its rewrite target, even though this\nhappens in practice at a later point in time, during constraint resolution.\n\nHowever, such an approach would not give a satisfactory outcome for cases such\nas:\n\n```\nconstraint X {\n  extends C where .T = .U;\n}\nconstraint Y {\n  extends C where .U = i32;\n}\n// Desired behavior is that `.T` and `.U` both rewrite to `i32`.\nfn G[A:! X & Y]() -> A.T { return 0; }\n```\n\nPerforming earlier-appearing rewrites in later constraints and additionally\nperforming a constraint resolution step to apply rewrites throughout the\nconstraint seems to give better outcomes for the examples we considered.\n\n### Multi-constraint `where` clauses\n\nInstead of treating `A where B and C` as `(A where B) where C`, we could model\nit as `(A where B) & (A where C)`.\n\nSpecifically, given\n\n```\ninterface C {\n  let T:! type;\n  let U:! type;\n}\n```\n\nthis would treat `C where .T = A and .U = B` as\n`(C where .T = A) & (C where .U = B)`, where the type of `.Self` would be `C` in\nboth clauses, with both constraints applied \"simultaneously\" to `C`. This would\nmean that the order of clauses doesn’t matter.\n\nHowever, if we do this, then neither right-hand side is rewritten by name\nlookup, and thus we would reject cases such as\n`C where .T = i32 and .U = .T.(Add.Result)`. This case seems reasonable, and we\nwould prefer to accept it.\n\nTherefore, the rule we select is that, as soon as a rewrite is declared, it is\nin scope, and later references to that associated constant refer to the\nrewritten value with its rewritten type. We still reject cases like\n`C where .U = .T.(Add.Result) and .T = i32`, because we do not know that\n`T is Add` from the declared type of `C.T`.\n\nThe same rule applies to `is` constraints: we accept\n`C where .T is Add and .U = .T.(Add.Result)`, but reject\n`C where .U = .T.(Add.Result) and .T is Add`.\n\n### Rewrite constraints in `impl as` constraints\n\nA rewrite constraint can appear indirectly in an `impl as` constraint in an\ninterface or named constraint:\n\n```\ninterface A {\n  let T:! type;\n}\nconstraint AInt {\n  extends A where .T = i32;\n}\ninterface B {\n  // Or, `impl as A where .T = i32;`\n  impl as AInt;\n}\n```\n\nWhen this happens, the rewrite constraint does not result in rewrites being\nperformed when the associated constant is mentioned in a member access into that\ninterface or named constraint:\n\n```\n// Return type is not rewritten to `i32`,\n// but there is still a same-type constraint.\nfn F(T:! B) -> T.(A.T) {\n  // OK, `i32` implicitly converts to `T.(A.T)`.\n  return 0 as i32;\n}\n```\n\nThis may be surprising: `B` says that its `.(A.T)` has a rewrite to `i32`, but\nthat rewrite is not performed. In contrast, rewrites in an `extends` constraint\ndo become part of the enclosing interface or named constraint.\n\n```\ninterface C {\n  extends AInt;\n}\n// Return type is rewritten to `i32`.\nfn G(T:! C) -> T.T;\n```\n\nSomething similar happens with `impl T as` constraints. The following two\ninterfaces `A1` and `A2` are not equivalent:\n\n```\ninterface A1 {\n  let X:! Add where .Result = i32;\n}\nconstraint AddToi32 {\n  extends Add where .Result = i32;\n}\ninterface A2 {\n  let X:! Add;\n  impl X as AddToi32;\n}\n```\n\nIn the former case, references to `A.X.Result` are rewritten to `i32`, and in\nthe latter case, they are not, because the rewrite is not part of the type of\n`X`.\n\nThe general principle here is that rewrites are part of the declared type of a\nname, and can't be changed after the fact by another declaration. For the\n`impl T as` case, this behavior is also a necessary part of the termination\nargument. If rewrites from `impl T as` constraints were used, it would be\npossible to form a rewrite cycle:\n\n```\ninterface C { let X:! type; }\ninterface A {\n  let U:! C;\n  let T:! C;\n}\ninterface B1 {\n  extends A;\n  impl T as C where .X = U.X;\n}\ninterface B2 {\n  extends A;\n  impl U as C where .X = T.X;\n}\n// `V.T.X` ~> `V.U.X` ~> `V.T.X` ~> ...\nfn F(V:! B1 & B2) -> V.T.X;\n```\n\nWe could allow the specific case of `impl as` (not `impl T as`) to introduce\nrewrites. The advantage of this change is that this behavior may be less\nsurprising in some cases. However, this would mean that an `impl as` sometimes\nchanges the interface of the enclosing constraint, and behaves inconsistently\nfrom an `impl T as` constraint, so this proposal does not adopt that behavior.\n\nWe could allow `impl T as` to introduce rewrites for `T` in general, but we\nwould need to find some way to fix the resulting holes in the termination\nargument.\n\nTo minimize the scope of confusion, we currently disallow rewrites from\nappearing _syntactically_ within an `impl as` or `impl T as` constraint. We\ncould allow these constructs. However, a `.T = V` constraint would be equivalent\nto a `.T == V` constraint, and the latter more clearly expresses the resulting\nsemantics, so disallowing the misleading form seems preferable.\n"
  },
  {
    "path": "proposals/p2187.md",
    "content": "# Update sum types design\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2187)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Keep the continuation interface as a parameter](#keep-the-continuation-interface-as-a-parameter)\n    -   [Require the continuation to execute the whole `case` body](#require-the-continuation-to-execute-the-whole-case-body)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal updates the design of [#157](p0157.md) to reflect subsequent\nevolution of the language.\n\n## Problem\n\nSome aspects of the design of #157 have become inconsistent with the rest of the\nlanguage, or can be made more precise in light of subsequent language\ndevelopment.\n\n## Proposal\n\n-   Make the continuation interface an associated type rather than an interface\n    parameter.\n-   For patterns that can be matched using either `Match` or `==`, require both\n    implementations to be well-formed.\n-   Use `name: Type` order instead of `Type: name` order in alternative\n    declarations.\n-   Use current syntax and semantics for generics and class types.\n-   Rename `Matchable.Match` to `Match.Op`, following the resolution of\n    [#1058](https://github.com/carbon-language/carbon-lang/issues/1058).\n\n## Alternatives considered\n\n### Keep the continuation interface as a parameter\n\nMaking the continuation interface a parameter of `Match` could in principle\nallow a single type to support pattern matching in multiple ways, by\nimplementing `Match` for multiple continuation interfaces. However, that would\nrequire something like overload resolution on interfaces, to choose the\nimplementation of `Match(C)` on the sum type for which `C` best matches the\ncontinuation constructed by the compiler. No such overloading mechanism is\nplanned, and we don't have sufficiently compelling use cases to motivate it.\n\n### Require the continuation to execute the whole `case` body\n\nWe will probably want to support in-place mutation of alternative parameters\n(for example so you can call a mutable method on the value stored in an\n`Optional(Foo)`), and we might even want to extend that to cases where the\nunderlying parameter isn't represented as an lvalue of that type, but has to be\nunpacked by `Match.Op`. The only way I see to make that work is to have\n`Match.Op` unpack the parameter to a local lvalue, pass it to the continuation,\nand then pack the possibly-mutated value back into the sum object after the\ncontinuation returns. That would mean the compiler has to execute the case body\ninside the continuation, not after `Match.Op` returns.\n\nHowever, that's fairly speculative, and wouldn't apply to the read-only cases\nthat we currently support, so we need not preemptively constrain the compiler\nhere.\n"
  },
  {
    "path": "proposals/p2188.md",
    "content": "# Pattern matching syntax and semantics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2188)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Expressions versus proper patterns](#expressions-versus-proper-patterns)\n    -   [Expression patterns](#expression-patterns)\n    -   [Bindings](#bindings)\n        -   [Name bindings](#name-bindings)\n        -   [Wildcard](#wildcard)\n        -   [Generic bindings](#generic-bindings)\n        -   [`auto` and type deduction](#auto-and-type-deduction)\n    -   [`var`](#var)\n    -   [Tuple patterns](#tuple-patterns)\n    -   [Struct patterns](#struct-patterns)\n    -   [Alternative patterns](#alternative-patterns)\n    -   [Templates](#templates)\n    -   [Guards](#guards)\n    -   [Refutability, overlap, usefulness, and exhaustiveness](#refutability-overlap-usefulness-and-exhaustiveness)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Shorthand for `auto`](#shorthand-for-auto)\n    -   [Struct pattern syntax](#struct-pattern-syntax)\n    -   [Type pattern matching](#type-pattern-matching)\n    -   [Introducer syntax for expression patterns](#introducer-syntax-for-expression-patterns)\n    -   [Allow guards on arbitrary patterns](#allow-guards-on-arbitrary-patterns)\n    -   [Treat expression patterns as exhaustive if they cover all possible values](#treat-expression-patterns-as-exhaustive-if-they-cover-all-possible-values)\n    -   [Allow non-exhaustive `match` statements](#allow-non-exhaustive-match-statements)\n-   [Future work](#future-work)\n    -   [Or patterns](#or-patterns)\n    -   [As patterns](#as-patterns)\n    -   [Matching classes by dynamic type](#matching-classes-by-dynamic-type)\n    -   [User-defined pattern matching](#user-defined-pattern-matching)\n    -   [Matching classes with struct patterns](#matching-classes-with-struct-patterns)\n    -   [Matching by reference](#matching-by-reference)\n    -   [Type deduction](#type-deduction)\n    -   [Match expressions](#match-expressions)\n-   [Examples](#examples)\n    -   [Examples from P0095R1](#examples-from-p0095r1)\n        -   [Figure 1. Declaration of a command data structure](#figure-1-declaration-of-a-command-data-structure)\n        -   [Figure 2. Implementation of an output operator](#figure-2-implementation-of-an-output-operator)\n        -   [Figure 3. Switching an enum](#figure-3-switching-an-enum)\n        -   [Figure 4. Expression datatype](#figure-4-expression-datatype)\n        -   [Figure 5. `struct` inspection](#figure-5-struct-inspection)\n    -   [Example from P1371R5: Red-black tree rebalancing](#example-from-p1371r5-red-black-tree-rebalancing)\n        -   [With P1371R5 pattern matching](#with-p1371r5-pattern-matching)\n        -   [With this proposal](#with-this-proposal)\n        -   [With this proposal plus #2187](#with-this-proposal-plus-2187)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis paper proposes concrete syntax and semantic choices for Carbon patterns.\n\n## Problem\n\nCarbon uses patterns wherever a value should be given a name, decomposed, or\nmatched against: in function parameters, variable declarations, `match`\nstatement `case`s, `for` statement loop variables, and so on. Simplified forms\nof patterns, required to be just a simple name binding, appear in additional\ncontexts, such as fields in classes and implicit parameter lists. While we have\nsyntax specified for some of these constructs, we do not have an approved\nproposal describing the syntax or semantics of patterns.\n\n## Background\n\nSee [pattern matching](https://en.wikipedia.org/wiki/Pattern_matching) on\nwikipedia for a broad overview of the subject.\n\nWe refer to the value being matched by a pattern as the _scrutinee_.\n\n## Proposal\n\nPatterns in Carbon are a generalization of the expression grammar. Compared to\nexpressions, patterns add:\n\n-   Bindings, of the form `name: type`, which give a name for the scrutinee.\n-   `var` _pattern_, which creates a separate object to hold the value of the\n    scrutinee, and causes any nested bindings to be mutable lvalues instead of\n    immutable rvalues.\n-   Additional syntax to make matching against structs more convenient.\n\n## Details\n\n### Expressions versus proper patterns\n\nExpressions are patterns, as described below. A pattern that is not an\nexpression, because it contains pattern-specific syntax such as a binding, is a\n_proper pattern_. Many expression forms, such as arbitrary function calls, are\nnot permitted as proper patterns, so cannot contain bindings.\n\n-   _pattern_ ::= _proper-pattern_\n\n```\nfn F(n: i32) -> i32 { return n; }\n\nmatch (F(42)) {\n  // ❌ Error: binding can't appear in a function call.\n  case (F(n: i32)) => {}\n}\n```\n\n### Expression patterns\n\nAn expression is a pattern.\n\n-   _pattern_ ::= _expression_\n\nThe pattern is compared with the expression using the `==` operator: _pattern_\n`==` _scrutinee_.\n\n```\nfn F(n: i32) {\n  match (n) {\n    // ✅ Results in an `n == 5` comparison.\n    // OK despite `n` and `5` having different types.\n    case 5 => {}\n  }\n}\n```\n\nAny `==` operations performed by a pattern match occur in lexical order, but for\nrepeated matches against the same _pattern_, later comparisons may be skipped by\nreusing the result from an earlier comparison:\n\n```\nclass ChattyIntMatcher {\n  external impl as EqWith(i32) {\n    fn Eq[me: ChattyIntMatcher](other: i32) {\n      Print(\"Matching {0}\", other);\n      return other == 1;\n    }\n  }\n}\n\nfn F() {\n  // Prints `Matching 1` then `Matching 2`,\n  // may or may not then print `Matching 1` again.\n  match ((1, 2)) {\n    case ({} as ChattyIntMatcher, 0) => {}\n    case (1, {} as ChattyIntMatcher) => {}\n    case ({} as ChattyIntMatcher, 2) => {}\n  }\n}\n```\n\n### Bindings\n\n#### Name bindings\n\nA name binding is a pattern.\n\n-   _binding-pattern_ ::= `unused`? _identifier_ `:` _expression_\n-   _proper-pattern_ ::= _binding-pattern_\n\nThe type of the _identifier_ is specified by the _expression_. The scrutinee is\nimplicitly converted to that type if necessary.\n\n```\nfn F() -> i32 {\n  match (5) (\n    // ✅ `5` is implicitly converted to `i32`.\n    // Returns `5 as i32`.\n    case n: i32 => { return n; }\n  }\n}\n```\n\nWhen a new object needs to be created for the binding, the lifetime of the bound\nvalue matches the scope of the binding.\n\n```\nclass NoisyDestructor {\n  fn Make() -> Self { return {}; }\n  external impl i32 as ImplicitAs(NoisyDestructor) {\n    fn Convert[me: i32]() -> Self { return Make(); }\n  }\n  destructor {\n    Print(\"Destroyed!\");\n  }\n}\n\nfn G() {\n  // Does not print \"Destroyed!\".\n  let n: NoisyDestructor = NoisyDestructor.Make();\n  Print(\"Body of G\");\n  // Prints \"Destroyed!\" here.\n}\n\nfn H(n: i32) {\n  // Does not print \"Destroyed!\".\n  let (v: NoisyDestructor, w: i32) = (n, n);\n  Print(\"Body of H\");\n  // Prints \"Destroyed!\" here.\n}\n```\n\nAs specified in\n[#2022](/proposals/p2022.md#the-behavior-of-unused-name-bindings), the `unused`\nkeyword indicates that the binding is intended to not be used.\n\n#### Wildcard\n\nA syntax like a binding but with `_` in place of an identifier can be used to\nignore part of a value.\n\n-   _binding-pattern_ ::= `_` `:` _expression_\n\nSee [#2022](/proposals/p2022.md) for details.\n\nThe behavior is similar to that of an `unused` binding with a unique name.\n\n```\nfn F(n: i32) {\n  match (n) {\n    // ✅ Matches and discards the value of `n`.\n    case _: i32 => {}\n    // ❌ Error: unreachable.\n    default => {}\n  }\n}\n```\n\nAs specified in [#1084](/proposals/p1084.md), function redeclarations may\nreplace named bindings with wildcards but may not use different names.\n\n```\nfn G(n: i32);\nfn H(n: i32);\nfn J(n: i32);\n\n// ✅ Does not use `n`.\nfn G(_: i32) {}\n// ❌ Error: name of parameter does not match declaration.\nfn H(m: i32) {}\n// ✅ Does not use `n`.\nfn J(unused n: i32);\n```\n\n#### Generic bindings\n\nA `:!` can be used in place of `:` for a binding that is usable at compile time.\n\n-   _generic-pattern_ ::= `unused`? `template`? _identifier_ `:!` _expression_\n-   _generic-pattern_ ::= `template`? `_` `:!` _expression_\n-   _proper-pattern_ ::= _generic-pattern_\n\n```\n// ✅ `F` takes a generic type parameter `T` and a parameter `x` of type `T`.\nfn F(T:! Type, x: T) {\n  var v: T = x;\n}\n```\n\nThe `template` keyword indicates the binding is introducing a template\nparameter, so name lookups into the parameter should be deferred until its value\nis known.\n\n#### `auto` and type deduction\n\nThe `auto` keyword is a placeholder for a unique deduced type.\n\n-   _expression_ ::= `auto`\n\n```\nfn F(n: i32) {\n  var v: auto = SomeComplicatedExpression(n);\n  // Equivalent to:\n  var w: T = SomeComplicatedExpression(n);\n  // ... where `T` is the type of the initializer.\n}\n```\n\nThe `auto` keyword is only permitted in specific contexts. Currently these are:\n\n-   As the return type of a function.\n-   As the type of a binding.\n\nIt is anticipated that `auto` may be permitted in more contexts in the future,\nfor example as a generic argument in a parameterized type that appears in a\ncontext where `auto` is allowed, such as `Vector(auto)` or `auto*`.\n\nWhen the type of a binding requires type deduction, the type is deduced against\nthe type of the scrutinee and deduced values are substituted back into the type\nbefore pattern matching is performed.\n\n```\nfn G[T:! Type](p: T*);\nclass X { external impl as ImplicitAs(i32*); }\n// ✅ Deduces `T = i32` then implicitly and\n// trivially converts `p` to `i32*`.\nfn H1(p: i32*) { G(p); }\n// ❌ Error, can't deduce `T*` from `X`.\nfn H2(p: X) { G(p); }\n```\n\nThe above is only an illustration; the behavior of type deduction is not\nspecified in this proposal.\n\n### `var`\n\nA `var` prefix indicates that a pattern provides mutable storage for the\nscrutinee.\n\n-   _proper-pattern_ ::= `var` _proper-pattern_\n\nA `var` pattern matches when its nested pattern matches. The type of the storage\nis the resolved type of the nested _pattern_. Any bindings within the nested\npattern refer to portions of the corresponding storage rather than to the\nscrutinee.\n\n```\nfn F(p: i32*);\nfn G() {\n  match ((1, 2)) {\n    // `n` is a mutable `i32`.\n    case (var n: i32, 1) => { F(&n); }\n    // `n` and `m` are the elements of a mutable `(i32, i32)`.\n    case var (n: i32, m: i32) => { F(if n then &n else &m); }\n  }\n}\n```\n\nPattern matching precedes the initialization of the storage for any `var`\npatterns. An introduced variable is only initialized if the complete pattern\nmatches.\n\n```\nclass X {\n  destructor { Print(\"Destroyed!\"); }\n}\nfn F(x: X) {\n  match ((x, 1 as i32)) {\n    case (var y: X, 0) => {}\n    case (var z: X, 1) => {}\n    // Prints \"Destroyed!\" only once, when `z` is destroyed.\n  }\n}\n```\n\nA `var` pattern cannot be nested within another `var` pattern. The declaration\nsyntax `var` _pattern_ `=` _expresson_ `;` is equivalent to `let` `var`\n_pattern_ `=` _expression_ `;`.\n\n### Tuple patterns\n\nA tuple of patterns can be used as a pattern.\n\n-   _tuple-pattern_ ::= `(` [_expression_ `,`]\\* _proper-pattern_ [`,`\n    _pattern_]\\*\n    `,`? `)`\n-   _proper-pattern_ ::= _tuple-pattern_\n\nA _tuple-pattern_ containing no commas is treated as grouping parens: the\ncontained _proper-pattern_ is matched directly against the scrutinee. Otherwise,\nthe behavior is as follows.\n\nA tuple pattern is matched left-to-right. The scrutinee is required to be of\ntuple type.\n\nNote that a tuple pattern must contain at least one _proper-pattern_. Otherwise,\nit is a tuple-valued expression. However, a tuple pattern and a corresponding\ntuple-valued expression are matched in the same way because `==` for a tuple\ncompares fields left-to-right.\n\n### Struct patterns\n\nA struct can be matched with a struct pattern.\n\n-   _proper-pattern_ ::= `{` [_field-init_ `,`]\\* _proper-field-pattern_ [`,`\n    _field-pattern_]\\*\n    `}`\n-   _proper-pattern_ ::= `{` [_field-pattern_ `,`]+ `_` `}`\n-   _field-init_ ::= _designator_ `=` _expression_\n-   _proper-field-pattern_ ::= _designator_ `=` _proper-pattern_\n-   _proper-field-pattern_ ::= _binding-pattern_\n-   _field-pattern_ ::= _field-init_\n-   _field-pattern_ ::= _proper-field-pattern_\n\nA struct pattern resembles a struct literal, with at least one field initialized\nwith a proper pattern:\n\n```\nmatch ({.a = 1, .b = 2}) {\n  // Struct literal as an expression pattern.\n  case {.b = 2, .a = 1} => {}\n  // Struct pattern.\n  case {.b = n: i32, .a = m: i32} => {}\n}\n```\n\nThe scrutinee is required to be of struct type, and to have the same set of\nfield names as the pattern. The pattern is matched left-to-right, meaning that\nmatching is performed in the field order specified in the pattern, not in the\nfield order of the scrutinee. This is consistent with the behavior of matching\nagainst a struct-valued expression, where the expression pattern becomes the\nleft operand of the `==` and so determines the order in which `==` comparisons\nfor fields are performed.\n\nIn the case where a field will be bound to an identifier with the same name, a\nshorthand syntax is available: `a: T` is synonymous with `.a = a: T`.\n\n```\nmatch ({.a = 1, .b = 2}) {\n  case {a: i32, b: i32} => { return a + b; }\n}\n```\n\nIf some fields should be ignored when matching, a trailing `, _` can be added to\nspecify this:\n\n```\nmatch ({.a = 1, .b = 2}) {\n  case {.a = 1, _} => { return 1; }\n  case {b: i32, _} => { return b; }\n}\n```\n\nThis is valid even if all fields are actually named in the pattern.\n\n### Alternative patterns\n\nAn alternative pattern is used to match one alternative of a choice type.\n\n-   _proper-pattern_ ::= _callee-expression_ _tuple-pattern_\n-   _proper-pattern_ ::= _designator_ _tuple-pattern_?\n\nHere, _callee-expression_ is syntactically an expression that is valid as the\ncallee in a function call expression, and an alternative pattern is\nsyntactically a function call expression whose argument list contains at least\none _proper-pattern_.\n\nIf a _callee-expression_ is provided, it is required to name a choice type\nalternative that has a parameter list, and the scrutinee is implicitly converted\nto that choice type. Otherwise, the scrutinee is required to be of some choice\ntype, and the designator is looked up in that type and is required to name an\nalternative with a parameter list if and only if a _tuple-pattern_ is specified.\n\nThe pattern matches if the active alternative in the scrutinee is the specified\nalternative, and the arguments of the alternative match the given tuple pattern\n(if any).\n\n```\nchoice Optional(T:! Type) {\n  None,\n  Some(T)\n}\n\nmatch (Optional(i32).None) {\n  // ✅ `.None` resolved to `Optional(i32).None`.\n  case .None => {}\n  // ✅ `.Some` resolved to `Optional(i32).Some`.\n  case .Some(n: i32) => { Print(\"{0}\", n); }\n  // ❌ Error, no such alternative exists.\n  case .Other => {}\n}\n\nclass X {\n  external impl as ImplicitAs(Optional(i32));\n}\n\nmatch ({} as X) {\n  // ✅ OK, but expression pattern.\n  case Optional(i32).None => {}\n  // ✅ OK, implicitly converts to `Optional(i32)`.\n  case Optional(i32).Some(n: i32) => { Print(\"{0}\", n); }\n}\n```\n\nNote that a pattern of the form `Optional(T).None` is an expression pattern and\nis compared using `==`.\n\n### Templates\n\nAny checking of the type of the scrutinee against the type of the pattern that\ncannot be performed because the type of the scrutinee involves a template\nparameter is deferred until the template parameter's value is known. During\ninstantiation, patterns that are not meaningful due to a type error are instead\ntreated as not matching. This includes cases where an `==` fails because of a\nmissing `EqWith` implementation.\n\n```\nfn TypeName[template T:! Type](x: T) -> String {\n  match (x) {\n    // ✅ OK, the type of `x` is a template parameter.\n    case _: i32 => { return \"int\"; }\n    case _: bool => { return \"bool\"; }\n    case _: auto* => { return \"pointer\"; }\n    default => { return \"unknown\"; }\n  }\n}\n```\n\nCases where the match is invalid for reasons not involving the template\nparameter are rejected when type-checking the template:\n\n```\nfn MeaninglessMatch[template T:! Type](x: T*) {\n  match (*x) {\n    // ✅ OK, `T` could be a tuple.\n    case (_: auto, _: auto) => {}\n    default => {}\n  }\n  match (x->y) {\n    // ✅ OK, `T.y` could be a tuple.\n    case (_: auto, _: auto) => {}\n    default => {}\n  }\n  match (x) {\n    // ❌ Error, tuple pattern cannot match value of non-tuple type `T*`.\n    case (_: auto, _: auto) => {}\n    default => {}\n  }\n}\n```\n\n### Guards\n\nWe allow `case`s within a `match` statement to have _guards_. These are not part\nof pattern syntax, but instead are specific to `case` syntax:\n\n-   _case_ ::= `case` _pattern_ [`if` _expression_]? `=>` _block_\n\nA guard indicates that a `case` only matches if some predicate holds. The\nbindings in the pattern are in scope in the guard:\n\n```\nmatch (x) {\n  case (m: i32, n: i32) if m + n < 5 => { return m - n; }\n}\n```\n\nFor consistency, this facility is also available for `default` clauses, so that\n`default` remains equivalent to `case _: auto`.\n\n### Refutability, overlap, usefulness, and exhaustiveness\n\nSome definitions:\n\n-   A pattern _P_ is _useful_ in the context of a set of patterns _C_ if there\n    exists a value that _P_ can match that no pattern in _C_ matches.\n-   A set of patterns _C_ is _exhaustive_ if it matches all possible values.\n    Equivalently, _C_ is exhaustive if the pattern `_: auto` is not useful in\n    the context of _C_.\n-   A pattern _P_ is _refutable_ if there are values that it does not match,\n    that is, if the pattern `_: auto` is useful in the context of {_P_}.\n    Equivalently, the pattern _P_ is _refutable_ if the set of patterns {_P_} is\n    not exhaustive.\n-   A set of patterns _C_ is _overlapping_ if there exists any value that is\n    matched by more than one pattern in _C_.\n\nFor the purpose of these terms, expression patterns that match a constant tuple,\nstruct, or choice value are treated as if they were tuple, struct, or\nalternative patterns, respectively, and `bool` is treated like a choice type.\nAny expression patterns that remain after applying this rule are considered to\nmatch a single value from an infinite set of values so that a set of expression\npatterns is never exhaustive:\n\n```\nfn IsEven(n: u8) -> bool {\n  // Not considered exhaustive.\n  match (n) {\n    case 0 => { return true; }\n    case 1 => { return false; }\n    ...\n    case 255 => { return false; }\n  }\n  // Code here is considered to be reachable.\n}\n```\n\n```\nfn IsTrue(b: bool) -> bool {\n  // Considered exhaustive.\n  match (b) {\n    case false => { return false; }\n    case true => { return true; }\n  }\n  // Code here is considered to be unreachable.\n}\n```\n\nWhen determining whether a pattern is useful, no attempt is made to determine\nthe value of any guards, and instead a worst-case assumption is made: a guard on\nthat pattern is assumed to evaluate to true and a guard on any pattern in the\ncontext set is assumed to evaluate to false.\n\nWe will diagnose the following situations:\n\n-   A pattern is not useful in the context of prior patterns. In a `match`\n    statement, this happens if a pattern or `default` cannot match because all\n    cases it could cover are handled by prior cases or a prior `default`. For\n    example:\n\n    ```\n    choice Optional(T:! Type) {\n      None,\n      Some(T)\n    }\n    fn F(a: Optional(i32), b: Optional(i32)) {\n      match ((a, b)) {\n        case (.Some(a: i32), _: auto) => {}\n        // ✅ OK, but only matches values of the form `(None, Some)`,\n        // because `(Some, Some)` is matched by the previous pattern.\n        case (_: auto, .Some(b: i32)) => {}\n        // ✅ OK, matches all remaining values.\n        case (.None, .None) => {}\n        // ❌ Error, this pattern never matches.\n        case (_: auto, _: auto) => {}\n      }\n    }\n    ```\n\n-   A pattern match is not exhaustive and the program doesn't explicitly say\n    what to do when no pattern matches. For example:\n\n    -   If the patterns in a `match` are not exhaustive and no `default` is\n        provided.\n\n        ```\n        fn F(n: i32) -> i32 {\n          // ❌ Error, this `match` is not exhaustive.\n          match (n) {\n            case 0 => { return 2; }\n            case 1 => { return 3; }\n            case 2 => { return 5; }\n            case 3 => { return 7; }\n            case 4 => { return 11; }\n          }\n        }\n        ```\n\n    -   If a refutable pattern appears in a context where only one pattern can\n        be specified, such as a `let` or `var` declaration, and there is no\n        fallback behavior. This currently includes all pattern matching contexts\n        other than `match` statements, but the `var`/`let`-`else` feature in\n        [#1871](https://github.com/carbon-language/carbon-lang/pull/1871) would\n        introduce a second context permitting refutable matches, and overloaded\n        functions might introduce a third context.\n\n        ```\n        fn F(n: i32) {\n          // ❌ Error, refutable expression pattern `5` used in context\n          // requiring an irrefutable pattern.\n          var 5 = n;\n        }\n        // ❌ Error, refutable expression pattern `5` used in context\n        // requiring an irrefutable pattern.\n        fn G(n: i32, 5);\n        ```\n\n-   When a set of patterns have no ordering or tie-breaker, it is an error for\n    them to overlap unless there is a unique best match for any value that\n    matches more than one pattern. However, this situation does not apply to any\n    current language rule:\n\n    -   For `match` statements, patterns are matched top-down, so overlap is\n        permitted.\n    -   We do not yet have an approved design for overloaded functions, but it\n        is anticipated that declaration order will be used in that case too.\n    -   For a set of `impl`s that match a given `impl` lookup, argument\n        deduction is used rather than pattern matching, but `impl`s with the\n        same type structure are an error unless a `match_first` declaration is\n        used to order the `impl`s. (This is a pre-existing rule and is unchanged\n        by this proposal.)\n\n## Rationale\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   The `, _` syntax for struct patterns enables a style where adding a\n        struct member is not a breaking change.\n    -   The requirement that matches be exhaustive makes it easier to add new\n        cases to a choice type, by requiring the compiler to detect places where\n        the new value is not handled.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Pattern syntax makes it easier to match complex values.\n    -   Modeling pattern syntax after expressions eases the burden of learning a\n        new sub-language for pattern-matching: patterns are an extension of\n        expressions, and expressions are a special case of patterns.\n    -   Requiring exhaustiveness for matches makes control flow easier to\n        understand as there is never a value for which the `match` skips all\n        cases.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   The rules for matching a templated value can be used to replace\n        `if constexpr` in many cases.\n\n## Alternatives considered\n\n### Shorthand for `auto`\n\nWe could provide a shorter syntax for `name: auto`.\n[Proposal #851](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0851.md#elide-the-type-instead-of-using-auto)\nconsidered the following shorthands and decided against using them:\n\n```\nvar n: _ = init;\nvar n = init;\n```\n\nA novel suggestion that avoids some of the disadvantages of those syntaxes would\nbe to use:\n\n```\nvar n:= init;\n```\n\nAdvantages:\n\n-   Shorter syntax for variables with a deduced type.\n-   Potentially allows removal of the `auto` keyword.\n\nDisadvantages:\n\n-   Appears to introduce a `:=` syntax, but that only arises in cases where an\n    initializer immediately follows the name.\n    -   Cases such as `var (a:, b:) = my_pair;` would either be invalid or would\n        not use the `:=` syntax.\n    -   If we accept such cases, there is a risk of grammar ambiguities.\n    -   If we reject such cases, we may still want to keep `auto` around for\n        them, creating inconsistency.\n-   Not a complete replacement for `auto` if we want to also allow things like\n    `v: Vector(auto)`. C++ doesn't allow the equivalent syntax currently, but it\n    was part of the Concepts TS and seems likely to return at some point.\n-   No syntactic difference between accidentally omitting a type entirely and\n    requesting type deduction. However, the mistake of omitting a type but\n    retaining the `:` seems unlikely, and the `:` followed by the absence of a\n    type is a signal that something is happening, so this seems to be less of a\n    concern than for the `var n = init;` syntax.\n\nSee discussion topics\n[1](https://github.com/carbon-language/carbon-lang/discussions/1495) and\n[2](https://github.com/carbon-language/carbon-lang/discussions/1988).\n\n### Struct pattern syntax\n\nWe could omit the `, _` syntax. This would simplify struct patterns, but at the\ncost of removing a feature that can be useful for reducing verbosity and making\nlibrary evolution easier.\n\nWe could always allow a struct pattern to match a struct with more fields,\nwithout requiring a `, _` suffix. This would aid evolution by reducing the cases\nwhere adding a field to a struct can be a breaking change, but such cases would\nstill exist. Further, this would make matches against a struct-valued expression\ninconsistent with matches against a struct pattern.\n\nWe could use a different syntax instead of `, _`. Other options that were\nexplicitly considered:\n\n-   `, ...` seems visually evocative of \"and more stuff\", but risks conflicting\n    with variadic syntax or at least being confusing when used in a variadic\n    context, given that variadics are expected to claim `...` for pack\n    expansion.\n-   `, ._` suggests matching a field without specifying a name, but might create\n    an impression of matching just one field, and three low punctuation\n    characters in a row seems to be pushing the limits of readability.\n\nOn balance, `, _` harmonizes well with the use of `_` to introduce a wildcard,\nwithout being too visually confusing given that the other use of `_` has a\nfollowing `:`.\n\nWe could remove the `{field: type}` shorthand and require\n`{.field = field: type}`. This may avoid encouraging reusing the field name even\nwhen it is not appropriate, and would remove some syntactic sugar that's not\nformally necessary. However, we expect this to be a common case whose ergonomics\nare important.\n\nWe could use a different syntax for `{field: type}` that is less divergent from\nother struct syntaxes:\n\n-   `{.field: type}` seems like a contender, but doesn't work because that is\n    already recognized as a struct type literal. Also, the use of normal binding\n    syntax means that every locally-introduced name is always introduced by\n    `name: type` where `name` is not preceded by `.`.\n-   `{.=field: type}` might be a reasonable mnemonic shorthand for\n    `{.field = field: type}`, but looks a little surprising. This is probably\n    the best choice if concerns are found with `{field: type}` syntax.\n\n### Type pattern matching\n\nWe could treat type deduction as a form of pattern matching. For example, we\ncould allow\n\n```\nfn F(a: Vector(T:! Type)) -> T { return a[0]; }\nfn G() -> i32 {\n  let v: Vector(i32) = (1, 2, 3);\n  // Deduces `T = i32`.\n  return F(v);\n}\n```\n\nwhere the value of `T` is determined by pattern-matching `Vector(T:! Type)`\nagainst the supplied type `Vector(i32)` of `v`. And symmetrically:\n\n```\nfn H[m: i32, n: i32](k: i32, (m, n)) { return m + n; }\nfn I() {\n  // Deduces `m = 2`, `n = 3`.\n  H(1, (2, 3));\n}\n```\n\nThis would ensure consistency between pattern matching and deduction,\npotentially reducing the number of rules that Carbon developers need to learn.\n\nWe find that use of pattern-matching in type position can harm readability. For\nexample, the first of these two examples may be easier to read due to having\nless nesting:\n\n```\nfn F[T:! Type](x: T);\nfn F(x: (T:! Type));\n```\n\nHaving distinct syntax for type-level matching and value-level matching helps\nguide the reader to the correct interpretation, even though the underlying\nmatching process is expected to be similar or identical. As a result, we keep\ntype deduction syntax and pattern matching syntax separate for now:\n\n-   In pattern matching, bindings and wildcards are introduced by nested `:` /\n    `:!` patterns, and the right-hand side of a binding pattern is never a\n    proper pattern.\n-   In type deduction, deduced values are specified separately and an expression\n    written in terms of those bindings describes the type.\n\nThere are some contexts where there is no syntactic location for introducing\ndeduced values, such as in `case` labels. For syntactic consistency, such cases\nshould be addressed by adding `forall` syntax, if there is motivation to support\ndeduction:\n\n```\nmatch (templated_value) {\n  case forall [template T:! Type] (p: T*) => { heap.Delete(p); }\n}\n```\n\n### Introducer syntax for expression patterns\n\nWe could have some separate introducer syntax to distinguish expression patterns\nfrom other kinds of patterns:\n\n```\nmatch ((a, b)) {\n  case is (1, 2) => {}\n  case (is 3, n: i32) => {}\n  case (m: i32, is 4) => {}\n}\n```\n\nThis would reduce the chance of confusion in cases where an expression and a\nsimilar-looking pattern are treated differently:\n\n```\nclass TupleLike {\n  external impl as (i32, i32);\n}\nfn MatchTupleLike(t: TupleLike) {\n  match (t) {\n    // ✅ OK, expression pattern;\n    // `t` implicitly converted to `(i32, i32)` by\n    // built-in `impl EqWith` for tuples.\n    case (1, 2) => {}\n    // ❌ Error, `t` is not a tuple.\n    case (n: i32, 3) => {}\n  }\n}\n```\n\nThis would also permit the same, or overlapping, syntax to be used in\nexpressions and patterns with different meanings, for example:\n\n```\nfn F() {\n  // Here, `[...]` is an array type.\n  var array: [i32; 5];\n  match (&array) {\n    // Here, `[...]` could introduce deduced parameters.\n    case [T:! Type] x: T* => {}\n  }\n}\n```\n\nSimilarly, if we added a `&PATT` pattern to match the address of a value, a\nconstruct like `&n` would be ambiguous without in introducer:\n\n```\nvar n: i32 = 5;\nfn MatchPointerOrPointee(p: i32*) {\n  match (p) {\n    case is &n => {\n      Print(\"given pointer to n\");\n    }\n    // Here, the pattern `&PATT` could match the address of\n    // a value that matches `PATT`.\n    case &(is n) => {\n      Print(\"given pointer to i32 whose value equals the value of n\");\n    }\n    case &(m: i32) => {\n      Print(\"given pointer to value {0}\", m);\n    }\n  }\n}\n```\n\nSuch an introducer would also denote the portions of a pattern that are\nevaluated at runtime rather than at compile time, benefitting Carbon's goals of\nreadability and of predictable performance, and would also add syntactic\nseparation between the parts of a pattern that have full exhaustiveness checking\nand the parts that do not.\n\nHowever, this would also introduce additional ceremony for the common case where\npart of a pattern is a specific value. This could be mitigated by permitting\ncertain kinds of value as patterns without an introducer, such as numeric\nliterals and `true` and `false`, at the cost of introducing more complexity and\nmore confusion over which cases require `is` and which do not.\n\nWe have also not identified a good choice for the introducer syntax, should we\npursue this direction. `is` is not an ideal choice, because elsewhere in Carbon\nsyntax, it is a relation between a value and its type, so `is T` may be misread\nas matching values whose type is `T`. `==` _expression_ has been suggested, but\nthat would imply the opposite operand order of that in this proposal --\n_scrutinee_ `==` _expression_ rather than _expression_ `==` _scrutinee_ -- which\nwould compare struct fields in a surprising order that diverges from the order\nof comparison for a struct pattern. A prefix `==` may also be visually\nsurprising.\n\nFor now, we do not add such an introducer, but this decision is expected to be\nrevisited by a future proposal.\n\nSee:\n\n-   [2022-09-16 Discord discussion in #syntax](https://discord.com/channels/655572317891461132/709488742942900284/1020559500597538886)\n-   [2022-12-05 open discussion](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#bookmark=id.utvzosvvfg80)\n\n### Allow guards on arbitrary patterns\n\nWe could treat guards as part of pattern syntax instead of as part of `case`\nsyntax. However, since guards make a pattern refutable, this wouldn't allow them\nanywhere other than in `case`s in the current language design. It would allow\nthem to be nested within cases:\n\n```\nmatch (x) {\n  case (n: i32 if n > 5, \"some string\") => { ... }\n}\n```\n\nSuch nesting might allow an expensive later check to be avoided. For example, in\nthe above case we can avoid an `==` comparison on a string if a cheaper\ncomparison of `n > 5` fails. However, this would introduce complexity into the\ngrammar, and it's not clear that this feature would add sufficient value to\njustify that complexity.\n\nAn additional concern is that if we add `let`...`else` syntax, this would\npresumably permit things like:\n\n```\nlet n: i32 if n > 5 = 20 else { return 0; };\n```\n\n... where it would be easy to misparse the `if ... else` as being a single\nconstruct, where the intended parse would be:\n\n```\nlet ((n: i32) if n > 5) = 20 else { return 0; };\n```\n\nSee also a\n[related Discord discussion](https://discord.com/channels/655572317891461132/748959784815951963/981691016040030279).\n\n### Treat expression patterns as exhaustive if they cover all possible values\n\nWe could do more work to treat a set of expression patterns as being exhaustive,\nif each pattern has a constant value and between those constant values, all\npossible values of the type are covered. The advantage of this would be that we\nimprove the precision of our language rules.\n\nThis change in rules has some disadvantages and problems:\n\n-   It would add some complexity to the rules and to implementations in order to\n    track whether all possible values have been created.\n-   For even the simplest types where this would apply, such as `i8`, it seems\n    unlikely that a `match` covering all possible values would be written, due\n    to the large number of patterns required.\n-   In many cases, the value being matched will carry an invariant so that\n    matching a subset of the representable values would match all meaningful\n    values. We would still have imprecise rules in those cases.\n-   Expression patterns are matched with `==`, and for an arbitrary `==` it is\n    not computable in general to tell whether a given set of values is\n    exhaustive, so we would only be able to apply this in some subset of cases.\n\nThis restriction is straightforward to work around by adding a final unreachable\n`default`, or by replacing the final value match with a `default` or `_`.\n\n### Allow non-exhaustive `match` statements\n\nWe could permit `match` statements that are not exhaustive, and execute none of\nthe case blocks if none of the patterns match. This is a very common choice in\nthe design of such language features. However, it is also a common source of\nerrors, for example when matching a sum type and an alternative is missed. By\nmaking this a language rule, we ensure that developers can rely on such mistakes\nbeing caught.\n\nThere is an easy syntactic way to disable this check, by adding an explicit\n`default => {}` case. If we made the opposite choice, we would not automatically\nhave an easy way to request that the check be performed. We could add syntax to\nrequest it, but such syntax would likely be forgotten and the default behavior\nwould be that errors are silently permitted. This seems sufficient to outweigh\nthe potential ergonomic cost of requiring the `default => {}` case to be written\nexplicitly.\n\nAnother motivation for requiring exhaustiveness is that it simplifies other\nlanguage rules. For example, when determining whether control flow can reach the\nend of a function with a declared return type, a separate exhaustiveness\nanalysis is not necesasry.\n\nOne concern with exhaustiveness checking is that it will cause the addition of\nan alternative to a choice type to be a breaking change by default. However,\nthis is also one of the main advantages, and the design of choice types is\nintended to eventually provide a mechanism to specify that a choice type is\nextensible, which if used would mean that a set of patterns for that choice type\nwould only be considered exhaustive if it includes a wildcard pattern.\n\n## Future work\n\n### Or patterns\n\nWe could provide \"or patterns\", allowing matching of one pattern or another with\nthe same handler:\n\n```\nmatch (x) {\n  case (m: i32, 0) | (0, m: i32) => { return m; }\n}\n```\n\nSee the\n[red-black tree rebalancing example](#example-from-p1371r5-red-black-tree-rebalancing)\nfor a real-world example where this would result in a simplification.\n\n### As patterns\n\nWe could provide\n[\"as-patterns\"](https://en.wikibooks.org/wiki/Haskell/Pattern_matching#As-patterns)\nas a convenient way to give a name to a value while still matching parts of that\nvalue. Following Haskell, we could use:\n\n-   _pattern_ ::= _identifier_ `@` _pattern_\n\nFor example:\n\n```\nmatch (x) {\n  // `s` names the first element of the tuple.\n  case (s@{.a = n: i32, .b = 12}, 4) if n > 1 => { return s; }\n}\n```\n\n### Matching classes by dynamic type\n\nWe could provide a way to match polymorphic class objects based on their dynamic\ntype. This might be the default when matching a polymorphic class, or might\nrequire opt-in. The behavior in this proposal is that only the static type of\nthe operand is considered.\n\nFor example, we could default to matching the static type, and allow a `dyn`\n_pattern_ syntax for matching a pointer to a polymorphic class type, meaning\nthat we match the dynamic type rather than the static type of the pointer:\n\n```\nabstract class Base { virtual fn F[me: Self](); }\nclass Derived1 extends Base {}\nclass Derived2 extends Base {}\n\nfn PrintType(b: Base*) {\n  match (b) {\n    // `case d1: Derived*` would be invalid here,\n    // because it could never match.\n    case dyn d1: Derived1* => { Print(\"Derived1\"); }\n    case dyn d2: Derived2* => { Print(\"Derived2\"); }\n    default => { Print(\"Unknown derived class\"); }\n  }\n}\n\nfn PrintTemplateType[template T:! Type](p: T*) {\n  match (p) {\n    // OK, dispatch is based on the static type.\n    case b: Base* => { Print(\"Base\"); }\n    case d1: Derived1* => { Print(\"Derived1\"); }\n    case d2: Derived2* => { Print(\"Derived2\"); }\n    default => { Print(\"Unknown class\"); }\n  }\n}\n```\n\nHowever, at this time we do not have a design for a checked down-cast, so it's\nnot clear how this matching operation would fit into the design of classes,\neither syntactically or semantically.\n\n### User-defined pattern matching\n\nWe plan to provide a mechanism for allowing a user-defined type to specify how\nit can be matched by patterns. See [proposal #157](/proposals/p0157.md) for\ndetails.\n\n### Matching classes with struct patterns\n\nWe could allow a class to be matched by a struct pattern that matches its\nfields. This would make sense especially for data classes, and would be\nconsistent with the behavior of `==` in the case where a struct is implicitly\nconvertible to the class type. However, without a design for user-defined\npattern matching and matching on dynamic type, there is a significant risk that\nthis would conflict with the rules there, so it is deferred for now.\n\n### Matching by reference\n\nWhen the scrutinee is an lvalue, it is sometimes desirable to form a mutable\nbinding to it. For example, see the\n[`struct` inspection example](#figure-5-struct-inspection) below. We currently\nsupport this only for the `me` binding in a method, using the `addr` keyword,\nbut could allow this more generally.\n\n```carbon\nfn takeDamage(p: player*) {\n  match (*p) {\n    case {.hitpoints = 0, .lives = 0, _} => { gameOver(); }\n    case {.hitpoints = addr hp: i32*, .lives = addr l: i32*, _} if *hp == 0 => {\n      *hp = 10;\n      --*l;\n    }\n    case {.hitpoints = addr hp: i32*, _} if *hp <= 3 => {\n      --*hp;\n      messageAlmostDead();\n    }\n    case {.hitpoints = addr hp: i32*, _} => {\n      --*hp;\n    }\n  }\n}\n```\n\nWork in this area will need to consider whether we can provide this feature\nergonomically without introducing reference-like behavior.\n\n### Type deduction\n\nThis proposal does not cover type deduction, instead considering it to be a\nseparate topic from pattern matching syntax, even though the semantic behavior\nof the two may be quite similar or identical.\n\nWe will need a proposal to explore type deduction and describe its functioning.\n\n### Match expressions\n\nAs demonstrated in the [switching an enum](#figure-3-switching-an-enum) example\nbelow, it would be valuable to have an expression `match` syntax in addition to\nthe statement `match` syntax. We could follow the same approach as for `if`\nstatements, and say that a `match` that appears at the start of a statement is a\nstatement `match` and any other `match` is an expression `match`.\n\nAs candidate syntax, braced `case` bodies could be replaced by an expression\nfollowed by a comma. For example:\n\n```\nlet opengl_color: Vec3 = match (c) {\n  case .red    => Vec3.Make(1.0, 0.0, 0.0),\n  case .yellow => Vec3.Make(1.0, 1.0, 0.0),\n  case .green  => Vec3.Make(0.0, 1.0, 0.0),\n  case .blue   => Vec3.Make(0.0, 0.0, 1.0)\n};\n```\n\n## Examples\n\nThese examples are translations of examples in WG21 paper\n[P0095R1](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0095r1.html)\nand\n[P1371R3](https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2020/p1371r3.pdf),\nwith permission from the author of those examples, David Sankel. Thank you,\nDavid!\n\n### Examples from P0095R1\n\n#### Figure 1. Declaration of a command data structure\n\n<table>\n<tr><th>C++</th><th>P0095R1</th><th>This proposal</th></tr>\n<tr markdown=\"block\"><td>\n\n```c++\nstruct set_score {\n  std::size_t value;\n};\n\nstruct fire_missile {};\n\nstruct fire_laser {\n  unsigned intensity;\n};\n\nstruct rotate {\n  double amount;\n};\n\nstruct command {\n  std::variant<\n    set_score,\n    fire_missile,\n    fire_laser,\n    rotate > value;\n};\n```\n\n</td><td>\n\n```c++\nlvariant command {\n  std::size_t set_score;\n  std::monostate fire_missile;\n  unsigned fire_laser;\n  double rotate;\n};\n```\n\n</td><td>\n\n```carbon\nchoice command {\n  set_score(u64),\n  fire_missile,\n  fire_laser(u32),\n  rotate(f64)\n}\n```\n\n</td></tr>\n</table>\n\n#### Figure 2. Implementation of an output operator\n\n<table>\n<tr><th>C++</th><th>P0095R1</th><th>This proposal</th></tr>\n<tr markdown=\"block\"><td>\n\n```c++\nnamespace {\nstruct Output {\n  std::ostream& operator()(std::ostream& stream, const set_score& ss) const {\n    return stream << \"Set the score to \" << ss.value << \".\\n\";\n  }\n  std::ostream& operator()(std::ostream& stream, const fire_missile&) const {\n    return stream << \"Fire a missile.\\n\";\n  }\n  std::ostream& operator()(std::ostream& stream, const fire_laser& fl) const {\n    return stream << \"Fire a laser with \" << fl.intensity << \" intensity.\\n\";\n  }\n  std::ostream& operator()(std::ostream& stream, const rotate& r) const {\n    return stream << \"Rotate by \" << r.degrees << \" degrees.\\n\"\n  }\n};\n}\n\nstd::ostream& operator<<(std::ostream& stream, const command& cmd) {\n  return std::visit(std::bind(Output(), std::ref(stream), std::placeholders::_1),\n                    cmd.value);\n}\n```\n\n</td><td>\n\n```c++\nstd::ostream& operator<<(std::ostream& stream, const command& cmd) {\n  return inspect(cmd) {\n    set_score value =>\n      stream << \"Set the score to \" << value << \".\\n\"\n    fire_missile _ =>\n      stream << \"Fire a missile.\\n\"\n    fire_laser intensity =>\n      stream << \"Fire a laser with \" << intensity << \" intensity.\\n\"\n    rotate degrees =>\n      stream << \"Rotate by \" << degrees << \" degrees.\\n\"\n  }\n}\n```\n\n</td><td>\n\n```carbon\nimpl command as Printable {\n  fn Print[me: Self](stream: Cpp.std.ostream*) {\n    match (me) {\n      case .set_score(value: u64) => {\n        stream->Print(\"Set the score to {0}.\\n\", value);\n      }\n      case .fire_missile => {\n        stream->Print(\"Fire a missile.\\n\");\n      }\n      case .fire_laser(intensity: u32) => {\n        stream->Print(\"Fire a laser with {0} intensity.\\n\", intensity);\n      }\n      case .rotate(degrees: f64) => {\n        stream->Print(\"Rotate by {0} degrees.\\n\", degrees);\n      }\n    }\n  }\n}\n```\n\n</td></tr>\n</table>\n\n#### Figure 3. Switching an enum\n\n<table>\n<tr><th>C++</th><th>P0095R1</th><th>This proposal</th></tr>\n<tr markdown=\"block\"><td colspan=2>\n\n```c++\nenum color { red, yellow, green, blue };\n```\n\n</td><td>\n\n```carbon\nchoice color { red, yellow, green, blue }\n```\n\n</td></tr>\n<tr markdown=\"block\"><td>\n\n```c++\nconst Vec3 opengl_color = [&c] {\n  switch(c) {\n    case red:\n      return Vec3(1.0, 0.0, 0.0);\n      break;\n    case yellow:\n      return Vec3(1.0, 1.0, 0.0);\n      break;\n    case green:\n      return Vec3(0.0, 1.0, 0.0);\n      break;\n    case blue:\n      return Vec3(0.0, 0.0, 1.0);\n      break;\n    default:\n      std::abort();\n  }();\n```\n\n</td><td>\n\n```c++\nconst Vec3 opengl_color =\n  inspect(c) {\n    red    => Vec3(1.0, 0.0, 0.0)\n    yellow => Vec3(1.0, 1.0, 0.0)\n    green  => Vec3(0.0, 1.0, 0.0)\n    blue   => Vec3(0.0, 0.0, 1.0)\n  };\n```\n\n</td><td>\n\n```carbon\n// Carbon has neither expression-match nor lambdas yet,\n// so this can't easily be done in line.\nfn GetOpenGLColor(c: color) -> Vec3 {\n  match (c) {\n    case .red    => { return Vec3.Make(1.0, 0.0, 0.0); }\n    case .yellow => { return Vec3.Make(1.0, 1.0, 0.0); }\n    case .green  => { return Vec3.Make(0.0, 1.0, 0.0); }\n    case .blue   => { return Vec3.Make(0.0, 0.0, 1.0); }\n  }\n}\nlet opengl_color: Vec3 = GetOpenGLColor(c);\n```\n\n</td></tr>\n</table>\n\n#### Figure 4. Expression datatype\n\n<table>\n<tr><th>C++</th><th>P0095R1</th><th>This proposal</th></tr>\n<tr markdown=\"block\"><td>\n\n```c++\nstruct expression;\n\nstruct sum_expression {\n  std::unique_ptr<expression> left_hand_side;\n  std::unique_ptr<expression> right_hand_side;\n};\n\nstruct expression {\n  std::variant<sum_expression, int, std::string> value;\n};\n\nexpression simplify(const expression & exp) {\n  if(sum_expression const * const sum = std::get_if<sum_expression>(&exp)) {\n    if( int const * const lhsInt = std::get_if<int>( sum->left_hand_side.get() )\n      && *lhsInt == 0 ) {\n      return simplify(*sum->right_hand_side);\n    }\n    else if( int const * const rhsInt = std::get_if<int>( sum->right_hand_side.get() )\n            && *rhsInt == 0 ) {\n      return simplify(*sum->left_hand_side);\n    } else {\n      return {sum_expression{\n        std::make_unique<expression>(simplify(*sum->left_hand_side)),\n        std::make_unique<expression>(simplify(*sum->right_hand_side))}}\n    }\n  }\n  return exp;\n}\n\nvoid simplify2(expression & exp) {\n  if(sum_expression * const sum = std::get_if<sum_expression>(&exp)) {\n    if( int * const lhsInt = std::get_if<int>( sum->left_hand_side.get() )\n      && *lhsInt == 0 ) {\n      expression tmp(std::move(*sum->right_hand_side));\n      exp = std::move(tmp);\n      simplify(exp);\n    }\n    else if( int * const rhsInt = std::get_if<int>( sum->right_hand_side.get() )\n            && *rhsInt == 0 ) {\n      expression tmp(std::move(*sum->left_hand_side));\n      exp = std::move(tmp);\n      simplify(exp);\n    } else {\n      simplify(*sum->left_hand_side);\n      simplify(*sum->right_hand_side);\n    }\n  }\n  return exp;\n}\n```\n\n</td><td>\n\n```c++\nlvariant expression;\n\nstruct sum_expression {\n  std::unique_ptr<expression> left_hand_side;\n  std::unique_ptr<expression> right_hand_side;\n};\n\nlvariant expression {\n  sum_expression sum;\n  int literal;\n  std::string var;\n};\n\nexpression simplify(const expression & exp) {\n  return inspect(exp) {\n           sum {*(literal 0),         *rhs} => simplify(rhs)\n           sum {*lhs        , *(literal 0)} => simplify(lhs)\n           sum {*lhs        ,         *rhs}\n             => expression::sum{\n                  std::make_unique<expression>(simplify(lhs)),\n                  std::make_unique<expression>(simplify(rhs))};\n           _ => exp\n         };\n}\n\nvoid simplify2(expression & exp) {\n  inspect(exp) {\n     sum {*(literal 0),         *rhs} => {\n       expression tmp(std::move(rhs));\n       exp = std::move(tmp);\n       simplify2(exp);\n     }\n     sum {*lhs        , *(literal 0)} => {\n       expression tmp(std::move(lhs));\n       exp = std::move(tmp);\n       simplify2(exp);\n     }\n     sum {*lhs        ,         *rhs} => {\n       simplify2(lhs);\n       simplify2(rhs);\n     }\n     _ => ;\n   };\n}\n```\n\n</td><td>\n\n```carbon\nchoice expression {\n  sum(UniquePtr(expression), UniquePtr(expression)),\n  literal(i32),\n  var: String\n}\n\n// This assumes that UniquePtr provides the matching\n// functionality described in #2187.\nfn simplify(exp: expression) -> expression {\n  match (exp) {\n    case .sum(.PtrTo(.literal(0)), .PtrTo(rhs: expression)) => {\n      return simplify(rhs);\n    }\n    case .sum(.PtrTo(lhs: expression), .PtrTo(.literal(0))) => {\n      return simplify(lhs);\n    }\n    case .sum(.PtrTo(lhs: expression), .PtrTo(rhs: expression)) => {\n      return expression.sum(MakeUnique(simplify(lhs)),\n                            MakeUnique(simplify(rhs)));\n    }\n    default => { return exp; }\n  }\n}\n```\n\n</td></tr>\n</table>\n\n#### Figure 5. `struct` inspection\n\n<table>\n<tr><th>C++</th><th>P0095R1</th><th>This proposal</th></tr>\n<tr markdown=\"block\"><td colspan=2>\n\n```c++\nstruct player {\n  std::string name;\n  int hitpoints;\n  int lives;\n};\n```\n\n</td><td>\n\n```carbon\nclass player {\n  var name: String;\n  var hitpoints: i32;\n  var lives: i32;\n}\n```\n\n</td></tr>\n<tr markdown=\"block\"><td>\n\n```c++\nvoid takeDamage(player &p) {\n  if(p.hitpoints == 0 && p.lives == 0)\n    gameOver();\n  else if(p.hitpoints == 0) {\n    p.hitpoints = 10;\n    p.lives--;\n  }\n  else if(p.hitpoints <= 3) {\n    p.hitpoints--;\n    messageAlmostDead();\n  }\n  else {\n    p.hitpoints--;\n  }\n}\n```\n\n</td><td>\n\n```c++\nvoid takeDamage(player &p) {\n  inspect(p) {\n    {hitpoints:   0, lives:0}   => gameOver();\n    {hitpoints:hp@0, lives:l}   => hp=10, l--;\n    {hitpoints:hp} if (hp <= 3) => { hp--; messageAlmostDead(); }\n    {hitpoints:hp} => hp--;\n  }\n}\n```\n\n</td><td>\n\n```carbon\nfn takeDamage(p: player*) {\n  match (*p) {\n    case {.hitpoints = 0, .lives = 0, _} => { gameOver(); }\n    case {.hitpoints = 0, _} => { p->hitpoints = 10; --p->lives; }\n    case {.hitpoints = hp: i32, _} if hp <= 3 => {\n      --p->hitpoints;\n      messageAlmostDead();\n    }\n    default => { --p->hitpoints; }\n  }\n}\n```\n\n</td></tr>\n</table>\n\n### Example from P1371R5: Red-black tree rebalancing\n\n#### With P1371R5 pattern matching\n\n```c++\nenum Color { Red, Black };\n\ntemplate <typename T>\nstruct Node {\n  void balance();\n\n  Color color;\n  std::shared_ptr<Node> lhs;\n  T value;\n  std::shared_ptr<Node> rhs;\n};\n\ntemplate <typename T>\nvoid Node<T>::balance() {\n  *this = inspect (*this) {\n    [case Black, (*?) [case Red, (*?) [case Red, a, x, b], y, c], z, d]\n      => Node{Red, std::make_shared<Node>(Black, a, x, b),\n                   y,\n                   std::make_shared<Node>(Black, c, z, d)};\n    [case Black, (*?) [case Red, a, x, (*?) [case Red, b, y, c]], z, d] // left-right case\n      => Node{Red, std::make_shared<Node>(Black, a, x, b),\n                   y,\n                   std::make_shared<Node>(Black, c, z, d)};\n    [case Black, a, x, (*?) [case Red, (*?) [case Red, b, y, c], z, d]] // right-left case\n      => Node{Red, std::make_shared<Node>(Black, a, x, b),\n                   y,\n                   std::make_shared<Node>(Black, c, z, d)};\n    [case Black, a, x, (*?) [case Red, b, y, (*?) [case Red, c, z, d]]] // right-right case\n      => Node{Red, std::make_shared<Node>(Black, a, x, b),\n                   y,\n                   std::make_shared<Node>(Black, c, z, d)};\n    self => self;\n  };\n}\n```\n\n#### With this proposal\n\n```carbon\nchoice Color { Red, Black }\n\nclass Node(T:! Type) {\n  fn balance[addr me: Self*]();\n\n  var color: Color;\n  var lhs: SharedPtr(Node);\n  var value: T;\n  var rhs: SharedPtr(Node);\n}\n\nfn MakeBalanced[T:! Type](a: SharedPtr(Node(T)), x: T,\n                          b: SharedPtr(Node(T)), y: T,\n                          c: SharedPtr(Node(T)), z: T,\n                          d: SharedPtr(Node(T))) -> Node(T) {\n  return {.color = Color.Red,\n          .lhs = MakeShared({.color = Color.Black, .lhs = a, .value = x, .rhs = b}),\n          .value = y,\n          .rhs = MakeShared({.color = Color.Black, .lhs = c, .value = z, .rhs = d})};\n}\n\nfn Node(T:! Type).balance[addr me: Self*]() {\n  match (*me) {\n    {.color = .Black, .lhs = .PtrTo(\n      {.color = .Red, .lhs = .PtrTo(\n        {.color = .Red, .lhs = a: auto, .value = x: T, .rhs = b: auto}),\n       .value = y: T, .rhs = c: auto}),\n     .value = z: T, .rhs = d: auto} => {\n      *me = MakeBalanced(a, x, b, y, c, z, d);\n    }\n    {.color = .Black, .lhs = .PtrTo(\n      {.color = .Red, .lhs = a: auto, .value = x: T, .rhs = .PtrTo(\n        {.color = .Red, .lhs = b: auto, .value = y: T, .rhs = c: auto})}),\n     .value = z: T, .rhs = d: auto} => {\n      *me = MakeBalanced(a, x, b, y, c, z, d);\n    }\n    {.color = .Black, .lhs = a: auto, .value = x: T, .rhs = .PtrTo(\n      {.color = .Red, .lhs = .PtrTo(\n        {.color = .Red, .lhs = b: auto, .value = y: T, .rhs = c: auto}),\n       .value = z: T, .rhs = d: auto})} => {\n      *me = MakeBalanced(a, x, b, y, c, z, d);\n    }\n    {.color = .Black, .lhs = a: auto, .value = x: T, .rhs = .PtrTo(\n      {.color = .Red, .lhs = b: auto, .value = y: T, .rhs = .PtrTo(\n        {.color = .Red, .lhs = c: auto, .value = z: T, .rhs = d: auto})})} => {\n      *me = MakeBalanced(a, x, b, y, c, z, d);\n    }\n    default => {}\n  };\n}\n```\n\n#### With this proposal plus #2187\n\n```carbon\nchoice Color { Red, Black }\n\nclass Node(T:! Type) {\n  fn balance[addr me: Self*]();\n\n  var color: Color;\n  var lhs: SharedPtr(Self);\n  var value: T;\n  var rhs: SharedPtr(Self);\n\n  external impl as Match {\n    interface Continuation {\n      extends Match.BaseContinuation;\n      fn Red[addr me: Self*](lhs: SharedPtr(Self), value: T, rhs: SharedPtr(Self)) -> ReturnType;\n      fn Black[addr me: Self*](lhs: SharedPtr(Self), value: T, rhs: SharedPtr(Self)) -> ReturnType;\n    }\n    fn Op[me: Self, C:! Continuation](continuation: C*) -> C.ReturnType {\n      match (me.color) {\n        case .Red => { return continuation->Red(me.lhs, me.value, me.rhs); }\n        case .Black => { return continuation->Black(me.lhs, me.value, me.rhs); }\n      }\n    }\n  }\n}\n\nfn MakeBalanced[T:! Type](a: SharedPtr(Node(T)), x: T,\n                          b: SharedPtr(Node(T)), y: T,\n                          c: SharedPtr(Node(T)), z: T,\n                          d: SharedPtr(Node(T))) -> Node(T) {\n  return {.color = Color.Red,\n          .lhs = MakeShared({.color = Color.Black, .lhs = a, .value = x, .rhs = b}),\n          .value = y,\n          .rhs = MakeShared({.color = Color.Black, .lhs = c, .value = z, .rhs = d})};\n}\n\nfn Node(T:! Type).balance[addr me: Self*]() {\n  match (*me) {\n    .Black(.PtrTo(.Red(.PtrTo(.Red(a: auto, x: T, b: auto)), y: T, c: auto)), z: T, d: auto) => {\n      *me = MakeBalanced(a, x, b, y, c, z, d);\n    }\n    .Black(.PtrTo(.Red(a: auto, x: T, .PtrTo(.Red(b: auto, y: T, c: auto)))), z: T, d: auto) => {\n      *me = MakeBalanced(a, x, b, y, c, z, d);\n    }\n    .Black(a: auto, x: T, .PtrTo(.Red(.PtrTo(.Red(b: auto, y: T, c: auto)), z: T, d: auto))) => {\n      *me = MakeBalanced(a, x, b, y, c, z, d);\n    }\n    .Black(a: auto, x: T, .PtrTo(.Red(b: auto, y: T, .PtrTo(.Red(c: auto, z: T, d: auto))))) => {\n      *me = MakeBalanced(a, x, b, y, c, z, d);\n    }\n    default => {}\n  };\n}\n```\n"
  },
  {
    "path": "proposals/p2200.md",
    "content": "# Template generics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2200)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Terminology](#terminology)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Syntax](#syntax)\n        -   [Branching on type identity](#branching-on-type-identity)\n    -   [Value phases](#value-phases)\n    -   [`auto`](#auto)\n    -   [Template constraints](#template-constraints)\n    -   [Name lookup](#name-lookup)\n    -   [Transition from C++ templates to Carbon checked generics](#transition-from-c-templates-to-carbon-checked-generics)\n        -   [To template Carbon with structural constraints](#to-template-carbon-with-structural-constraints)\n        -   [To interface constraints](#to-interface-constraints)\n        -   [To checked generic](#to-checked-generic)\n    -   [Validity can depend on value](#validity-can-depend-on-value)\n    -   [Template dependent](#template-dependent)\n        -   [Simple member access](#simple-member-access)\n        -   [Compound member access](#compound-member-access)\n        -   [Impl lookup](#impl-lookup)\n        -   [Use of dependent value is dependent](#use-of-dependent-value-is-dependent)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Only checked generics](#only-checked-generics)\n    -   [SFINAE](#sfinae)\n    -   [Ad hoc API specialization](#ad-hoc-api-specialization)\n    -   [Value phase of bindings determined by initializer](#value-phase-of-bindings-determined-by-initializer)\n    -   [Simpler template dependent rules that delayed more checking](#simpler-template-dependent-rules-that-delayed-more-checking)\n-   [Future work](#future-work)\n    -   [Expanded template constraints](#expanded-template-constraints)\n    -   [Predicates: constraints on values](#predicates-constraints-on-values)\n    -   [Checked generics calling templates](#checked-generics-calling-templates)\n    -   [Which expressions will be evaluated at compile time](#which-expressions-will-be-evaluated-at-compile-time)\n\n<!-- tocstop -->\n\n## Abstract\n\nAdd template generics, with optional constraints but no\n[SFINAE](https://en.cppreference.com/w/cpp/language/sfinae), to Carbon. Template\ngenerics allows the compiler to postpone type checking of expressions dependent\non a template parameter until the function is called and the value of that\nparameter is known.\n\nExample usage:\n\n```carbon\nfn Identity[template T:! Type](x: T) -> T {\n  return x;\n}\n```\n\n## Problem\n\nStarting with\n[#24: Generics goals](https://github.com/carbon-language/carbon-lang/pull/24),\nwe have assumed templates (also known as \"template generics\" in Carbon) will be\na feature of Carbon, but it has not been an accepted part of the design. We now\nunderstand enough about how they should fit into the language to decide that we\nare including the feature in the language, and what form they should take.\n\nTemplate generics will address these use cases:\n\n-   They provide a step in the transition from C++ templates to Carbon checked\n    generics.\n-   They provide a generics programming model familiar to C++ developers.\n-   They allow Carbon to separate features that we don't want to expose by\n    default in checked generics. These are features that pierce abstraction\n    boundaries that we want to discourage for software engineering reasons or at\n    least mark when they are in use. Examples in this category include:\n    -   Compile-time duck typing features that use the structural properties of\n        types, like having a method with a particular name, rather than semantic\n        properties like implementing an interface.\n    -   Branching in code based on type identity.\n\nOut of scope for this proposal are any questions about passing a checked generic\nargument value to a template parameter. See question-for-leads issue\n[#2153: Generics calling templates](https://github.com/carbon-language/carbon-lang/issues/2153).\n\n## Background\n\nTemplates are the mechanism for performing\n[generic programming](https://en.wikipedia.org/wiki/Generic_programming) in C++,\nsee [cppreference.com](https://en.cppreference.com/w/cpp/language/templates).\n\nThere have been a number of prior proposals and questions-for-leads issues on\ntemplate generics on which this proposal builds:\n\n-   Proposal\n    [#24: Generics goals](https://github.com/carbon-language/carbon-lang/pull/24)\n    talked about the reasons for templates, without committing Carbon to\n    including them. These reasons include making it easier to transition C++\n    template code to Carbon and providing functionality outside of what we want\n    to support with checked generics.\n-   Proposal\n    [#447: Generics terminology](https://github.com/carbon-language/carbon-lang/pull/447)\n    defined terminology. This included some of the differences between checked\n    and template generics, and definitions for terms like _instantiation_.\n-   Proposal\n    [#553: Generic details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n    defined `auto` as a template construct, and described how templates do not\n    require constraints to find member names.\n-   Question-for-leads issue\n    [#565: Generic syntax to replace provisional `$`s](https://github.com/carbon-language/carbon-lang/issues/565)\n    implemented in proposal\n    [#676: `:!` generic syntax](https://github.com/carbon-language/carbon-lang/pull/676)\n    defined the syntax for template bindings.\n-   Proposal\n    [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n    included that template values may be passed to generic parameters.\n-   Proposal\n    [#818: Constraints for generics](https://github.com/carbon-language/carbon-lang/pull/818)\n    included `template constraint` to defined named constraints with fewer\n    restrictions for use with template parameters.\n-   Proposal\n    [#875: Principle: information accumulation](https://github.com/carbon-language/carbon-lang/pull/875)\n    considered how the principle benefited and was impacted by templates.\n-   Question-for-leads issue\n    [#949: Constrained template name lookup](https://github.com/carbon-language/carbon-lang/issues/949)\n    implemented in proposal\n    [#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n    defined how name lookup works for template parameters. It provided a path to\n    incrementally adopt constraints on template parameters, a stepping stone to\n    transitioning to checked generics.\n-   Proposal\n    [#950: Generics details 6: remove facets](https://github.com/carbon-language/carbon-lang/pull/950)\n    included the impact on the semantics of templates in its rationale.\n-   Proposal\n    [#1146: Generic details 12: parameterized types](https://github.com/carbon-language/carbon-lang/pull/1146)\n    allowed template type parameters.\n-   Proposal\n    [#1270: Update and expand README content and motivation for Carbon](https://github.com/carbon-language/carbon-lang/pull/1270)\n    advertised that Carbon would support templates for \"seamless C++ interop.\"\n-   Terminology was updated in proposal\n    [#2138: Checked and template generic terminology](https://github.com/carbon-language/carbon-lang/pull/2138).\n\nTODO: Update if proposal\n[#2188: Pattern matching syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2188)\nis accepted first.\n\n## Terminology\n\n-   A _template dependent_ name or expression is one whose meaning depends on,\n    that is varies with, some template generic parameter. Specifically this\n    refers to an expression that can not be fully checked until the value of the\n    parameter is known. This is consistent with the meaning of this term in\n    [C++](https://en.cppreference.com/w/cpp/language/dependent_name), but is\n    different from\n    [\"dependent types\"](https://en.wikipedia.org/wiki/Dependent_type). The\n    specifics of how this works in Carbon are being proposed in\n    [a later section](#template-dependent).\n-   [_Instantiation_](/docs/design/generics/terminology.md#instantiation),\n    _substitution_, or\n    [_monomorphizaton_](https://en.wikipedia.org/wiki/Monomorphization) is the\n    process of duplicating the implementation of a function and then\n    substituting in the values of any (checked or template) generic arguments.\n-   Errors that are only detected once the argument value from the call site is\n    known are called _monomorphization errors_. These mostly occur in\n    expressions dependent on some template parameter, but can also occur for\n    other reasons like hitting an implementation limit.\n-   _SFINAE_ stands for \"Substitution failure is not an error\", which is the\n    policy in C++, see\n    [cppreference](https://en.cppreference.com/w/cpp/language/sfinae),\n    [wikipedia](https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error).\n    It means that functions from an overload set with monorphization errors, or\n    \"substitution failure,\" within their signatures are simply ignored instead\n    of causing compilation to fail.\n\n## Proposal\n\nWe propose that template generics are included as an official feature of Carbon.\n\nIn many ways, template generic parameters work like checked generic parameters.\nThe following are true for any kind of generic parameter:\n\n-   The value passed to a generic parameter must be able to be evaluated at\n    compile time.\n-   Generic parameters may have constraints that will be enforced by the\n    compiler on the value supplied by the caller.\n-   The compiler may choose to generate multiple copies of a generic function\n    for different values of the generic parameters.\n\nThe main differences between checked and templated generics are:\n\n-   Member lookup into a templated type looks in the actual type value provided\n    by the caller in addition to in any constraints on that type; see\n    [proposal #989](https://github.com/carbon-language/carbon-lang/pull/989).\n-   A templated parameter may be used in ways where the validity of the result\n    depends on the value of the parameter, not just its type.\n-   Impl lookup is delayed until all templated types, interfaces, and parameters\n    are known.\n\nAs a consequence of these differences, type checking of any expression dependent\non a templated parameter may not be completed until its value is known. In\naddition, templated generics support branching on the value of a templated type.\n\nIn contrast with C++ templates, with Carbon template generics:\n\n-   Substitution failure is an error. In C++, [the SFINAE rule](#terminology)\n    will skip functions in overload resolution that fail to instantiate.\n    Instead, Carbon template parameters use constraints to control when the\n    function is available.\n-   Carbon template specialization does not allow ad hoc changes to the API of\n    the function or type being specialized, only its implementation. This is in\n    contrast to C++, where\n    [C++'s `std::vector<bool>`](https://en.cppreference.com/w/cpp/container/vector_bool)\n    has different return types for certain methods. Anything that can vary in an\n    API must be explicitly marked using associated types of an interface, as is\n    described in the\n    [\"parameterized type specialization\" design](/docs/design/generics/details.md#specialization).\n-   Constraints on a Carbon template type affect how lookup is done into that\n    type, as described in\n    [proposal #989](https://github.com/carbon-language/carbon-lang/pull/989).\n\n## Details\n\n### Syntax\n\nTemplate generic bindings are declared using the `template` keyword in addition\nto the `:!` of all generic bindings. This includes `let` declarations, as in:\n\n```carbon\n// `N` is a constant that may be used in types.\nlet template N:! i64 = 4;\nvar my_array: [u8; N] = (255, 128, 64, 255);\n```\n\nFunction parameters also default to a `let` context and may use `template`:\n\n```carbon\n// `U` is a templated type parameter that must be specified\n// explicitly by the caller.\nfn Cast[template T:! Type](x: T, template U:! Type) -> U {\n  // OK, check for `T is As(U)` delayed until values of `T` and `U` are known.\n  return x as U;\n}\n\nlet x: i32 = 7;\n// Calls `Cast` with `T` set to `i32` and `U` set to `i64`.\nlet y: auto = Cast(x, i64);\n// Type of `y` is `i64`.\n```\n\nNote that generic bindings, checked or template, can only be used in `let`\ncontext to produce r-values, not in a `var` context to produce l-values.\n\n```carbon\n// ❌ Error: Can't use `:!` with `var`. Can't be both a\n//           compile-time constant and a variable.\nvar N:! i64 = 4;\n// ❌ Error: Can't use `template :!` with `var` for the\n//           same reason.\nvar template M:! i64 = 5;\n```\n\n#### Branching on type identity\n\nBranching on the value of a templated type will be done using a `match`\nstatement, but is outside the scope of this proposal. See instead pending\nproposal\n[#2188: Pattern matching syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2188).\n\n### Value phases\n\nR-values are divided into three different _value phases_:\n\n-   A _constant_ has a value known at compile time, and that value is available\n    during type checking, for example to use as the size of an array. These\n    include literals (integer, floating-point, string), concrete type values\n    (like `f64` or `Optional(i32*)`), expressions in terms of constants, and\n    values of `template` parameters.\n-   A _symbolic value_ has a value that will be known at the code generation\n    stage of compilation when monomorphization happens, but is not known during\n    type checking. This includes checked-generic parameters, and type\n    expressions with checked-generic arguments, like `Optional(T*)`.\n-   A _runtime value_ has a dynamic value only known at runtime.\n\nSo:\n\n-   A `let template T:! ...` or `fn F(template T:! ...)` declaration binds `T`\n    with constant value phase,\n-   A `let T:! ...` or `fn F(T:! ...)` declaration binds `T` with symbolic value\n    phase,\n-   A `let x: ...` or `fn F(x: ...)` declaration binds `x` with runtime value\n    phase.\n\n**Note:** The naming of value phases is the subject of open question-for-leads\nissue\n[#1391: New name for \"constant\" value phase](https://github.com/carbon-language/carbon-lang/issues/1391).\nThis terminology comes from\n[a discussion in #typesystem on Discord](https://discord.com/channels/655572317891461132/708431657849585705/992817321074774098),\nin particular\n[this message](https://discord.com/channels/655572317891461132/708431657849585705/994396535561408623).\n\n**Note:** This reflects the resolution of question-for-leads issue\n[#1371: Is `let` referentially transparent?](https://github.com/carbon-language/carbon-lang/issues/1371)\nthat the value phase of a binding is determined by the kind of binding, and not\nanything about the initializer.\n\n**Note:** The situations in which a value with one phase can be used to\ninitialize a binding with a different value phase is future work, partially\nconsidered in question-for-leads issue\n[#2153: Generics calling templates](https://github.com/carbon-language/carbon-lang/issues/2153)\nin addition to\n[#1371: Is `let` referentially transparent?](https://github.com/carbon-language/carbon-lang/issues/1371).\n\n**Note:** Exactly which expressions in terms of constants result in constants is\nan open question that is not resolved by this proposal. In particular, which\nfunction calls will be evaluated at compile time is not yet specified. See\n[future work](#which-expressions-will-be-evaluated-at-compile-time).\n\n### `auto`\n\nThe `auto` keyword is a shortcut for an unnamed templated type, as in:\n\n```carbon\n// Type of `x` is the same as the return type of function `F`.\nlet x: auto = F();\n```\n\nThis was first added to Carbon in proposal\n[#553: Generic details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\nand further specified by open proposal\n[#2188: Pattern matching syntax and semantics](https://github.com/carbon-language/carbon-lang/pull/2188).\n\nThe `auto` keyword may also be used to omit the return type, as specified in\n[#826: Function return type inference](https://github.com/carbon-language/carbon-lang/pull/826).\n\nThe semantics of `let x:! auto = ...` is the subject of open question-for-leads\nissue\n[#996: Generic `let` with `auto`?](https://github.com/carbon-language/carbon-lang/issues/996).\n\n### Template constraints\n\nTemplate constraints have already been introduced in proposal\n[#818: Constraints for generics](https://github.com/carbon-language/carbon-lang/pull/818).\nIn brief, a `template constraint` declaration is like a `constraint`\ndeclaration, except that it may also contain function and field declarations,\ncalled _structural constraints_. Only types with matching declarations will\nsatisfy the template constraint. Note that the declarations matching the\nstructural constraints must be found by member lookups in the type. It is not\nsufficient for them to be declared only in an external impl.\n\n```carbon\ninterface A { fn F[me: Self](); }\ninterface B { fn F[me: Self](); }\nclass C { }\nexternal impl C as A;\nexternal impl C as B;\ntemplate constraint HasF {\n  fn F[me: Self]();\n}\nfn G[template T:! HasF](x: T);\nvar y: C = {};\n// Can't call `G` with with `y` since it doesn't have any internal\n// implementation of a method `F` satisfying `HasF`, even though `C`\n// externally implements both `A` and `B` with such an `F`. May\n// define an adapter for `C` to get a type that implements `HasF`,\n// with `A.F`, `B.F`, or some other definition.\n```\n\nThis was discussed in\n[#generics-and-templates on 2022-09-20](https://discord.com/channels/655572317891461132/941071822756143115/1021903925613449316).\n\nStructural constraints do not affect [name lookup](#name-lookup) into template\ntype parameters. They guarantee that a name will be available in the type, but\ndon't change the outcome.\n\n```carbon\ntemplate constraint HasF {\n  fn F[me: Self]();\n}\nclass C {\n  fn F[me: Self]();\n}\nfn G[template T:! HasF](x: T) {\n  x.F();\n}\nvar y: C = {};\n// Call to `F` inside `G` is not ambiguous since\n// `C.F` and `HasF.F` refer to the same function.\nG(y);\nclass D extends C {\n  alias F = C.(A.F);\n}\n// OK, `z.(HasF.F)` will resolve to `z.(C.(A.F))`.\nfn Run(z: D) { G(z); }\n```\n\nWhether template constraints may be used as constraints on checked-generic\nparameters is being considered in question-for-leads issue\n[#2153: Generics calling templates](https://github.com/carbon-language/carbon-lang/issues/2153).\nEven if we allow a checked-generic parameter to use a template constraint, we\nwant to focus checked generics on semantic properties encapsulated in\ninterfaces, not structural properties tested by template constraints. So we\nwould not allow lookup into a checked-generic type to find type members outside\nof an interface:\n\n```carbon\ntemplate constraint HasF {\n  fn F[me: Self]();\n}\n// ❓ If we allow a checked generic to use a template\n// constraint, as in:\nfn H[T:! HasF](x: T) {\n  // We still will not support calling `F` on `x`:\n  // ❌ x.F();\n}\n```\n\nThese members would only be found using a template type parameter.\n\n[Expanding the kinds of template constraints](#expanded-template-constraints)\nand\n[defining a way to put constraints on values](#predicates-constraints-on-values)\nare both [future work](#future-work).\n\n### Name lookup\n\nName lookup for templates has already been decided in question-for-leads issue\n[#949: Constrained template name lookup](https://github.com/carbon-language/carbon-lang/issues/949)\nand proposal\n[#989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989).\nBriefly, name lookup is done both in the actual type value supplied at the call\nsite and the interface constraints on the parameter. If the name is found in\nboth, it is an error if they resolve to different entities.\n\nLook up into the calling type gives _compile-time duck typing_ behavior, much\nlike C++ templates, as in:\n\n```carbon\nfn F[template T:! Type](x: T) {\n  // Calls whatever `M` is declared in `T`, and will\n  // fail if `T` does not have a matching member `M`.\n  x.M();\n}\n\nclass C1 { fn M[me: Self](); }\nvar x1: C1 = {};\n// Calls `F` with `T` equal to `C1`, which succeeds.\nF(x1);\n\nclass C2 { fn M[addr me: Self*](); }\nvar x2: C2 = {};\n// Calls `F` with `T` equal to `C2`, which fails,\n// since `x` is an r-value in `F` and `C2.M` requires\n// an l-value.\nF(x2);\n\nclass C3 { fn M[me: Self](p: i32); }\nvar x3: C3 = {};\n// Calls `F` with `T` equal to `C3`, which fails,\n// since `C3.M` must be passed an argument value.\nF(x3);\n\nclass C4 { fn M[me: Self](p: i32 = 4); }\nvar x4: C4 = {};\n// Calls `F` with `T` equal to `C4`, which succeeds,\n// using the default value of `4` for `p` when\n// calling `C4.M`.\nF(x4);\n\nclass C5 { var v: i32; }\nvar x5: C5 = {.v = 5};\n// Calls `F` with `T` equal to `C5`, which fails,\n// since `T` has no member `M`.\nF(x5);\n```\n\nNote that in some cases of looking up a qualified name, lookup will not depend\non the value of the template parameter and can be checked before instantiation,\nas in:\n\n```carbon\ninterface A {\n  fn F[me: Self]();\n}\n\nfn G[template T:! A](x: T) {\n  // No question what this resolves to, can be checked\n  // when `G` is defined:\n  x.(A.F)();\n\n  // Will generate a monomorphization error if\n  // `T.F` means something different than `T.(A.F)`,\n  // can only be checked when `G` is called:\n  x.F();\n}\n```\n\n### Transition from C++ templates to Carbon checked generics\n\nWe have a specific\n[goal for generics](/docs/design/generics/goals.md#upgrade-path-from-templates)\nthat we have a smooth story for transitioning from C++ templates to Carbon\nchecked generics. Adding template generics to Carbon allows this to be done in\nsteps. These steps serve two purposes. One is to allow any updates needed for\ncallers and types used as parameters to be done incrementally. The second is to\navoid any silent changes in semantics that would occur from jumping directly to\nCarbon checked generics. Each step will either preserve the meaning of the code\nor result in compile failures.\n\n#### To template Carbon with structural constraints\n\nThe first step is to convert the C++ function with one or more template\nparameters to a Carbon function with template generic parameters. Any\n[non-type template parameters](https://en.cppreference.com/w/cpp/language/template_parameters#Non-type_template_parameter)\ncan be converted to template generic parameters with the equivalent type, as in:\n\n```\n// This C++ function:\nvoid F_CPlusPlus<int N>();\n\n// gets converted to Carbon:\nfn F_Carbon(template N:! i32);\n```\n\nOther template parameters can either be declared without constraints, using\n`template T:! Type`, or using [structural constraints](#template-constraints).\n\nTo see if this transition can cause silent changes in meaning, consider how this\nnew Carbon function will be different from the old C++ one:\n\n-   The conversion of the body of the code in the function could introduce\n    differences, but only template concerns are in scope for this proposal.\n-   The C++ code could use ad hoc API specialization. The only way to translate\n    that to Carbon is through\n    [explicit parameterization of the API](/docs/design/generics/details.md#specialization),\n    which is not expected to introduce silent changes in meaning.\n-   The C++ code could rely on [SFINAE](#terminology). C++ uses of\n    `std::enable_if` should be translated to equivalent\n    [template constraints](#template-constraints). Generally making substitution\n    failure an error is expected to make less code compile, not introduce silent\n    changes in meaning.\n-   As long as the constraints on template type parameters are\n    [structural](#template-constraints) and not interface constraints, the name\n    lookup rules into those type parameters will consistently look in the type\n    for both C++ and Carbon.\n\n#### To interface constraints\n\nThe next step is to switch from structural constraints to interface constraints.\nThe interfaces that are providing the functionality that the function relies on\nmust be identified or created. In some cases this could be done automatically\nwhen names are resolved consistently to interface methods in the types currently\nbeing used to instantiate the function. Once that is done, there are two\napproaches:\n\n-   Implement the interface for every instantiating type. Once that is done, the\n    function's constraint can be updated.\n-   Alternatively, a blanket implementation of the interface could be defined\n    for any type implementing the structural constraints so that the function's\n    constraint can be updated first. After that, the interface can be\n    implemented for types individually, overriding the blanket implementation\n    until the blanket implementation is no longer needed. This second choice\n    requires changes to the library defining the interface, and is most\n    appropriate when it is a new interface specifically created for this\n    function.\n\nIn either case, the compiler will give an error if the interface is not\nimplemented for some types before the step is finished.\n\nAn example of the second approach, starting with a templated function with a\nstructural constraint:\n\n```carbon\ntemplate constraint HasF {\n  fn F[me: Self]();\n}\n\nfn G[template T:! HasF](x: T) {\n  x.F();\n}\n\nclass C {\n  fn F[me: Self]();\n}\nvar y: C = {};\nG(y);\n```\n\nFirst, a new interface is created with a blanket implementation and the\nfunction's constraints are updated to use it instead. Calls in the function body\nshould be qualified to avoid ambiguity errors.\n\n```carbon\ntemplate constraint HasF {\n  fn F[me: Self]();\n}\n\n// New interface\ninterface NewF {\n  fn DoF[me: Self]();\n}\n\n// Blanket implementation\nexternal impl forall [template T:! HasF] T as NewF {\n  // If the functions are identical, can instead do:\n  //    alias DoF = T.F;\n  fn DoF[me: Self]() {\n    me.F();\n    // Or: me.(T.F)();\n  }\n}\n\n// Changed constraint\nfn G[template T:! NewF](x: T) {\n  // Call function from interface\n  x.(NewF.DoF)();\n  // Could use `x.DoF();` instead, but that will\n  // give a compile error if `T` has a definition\n  // for `DoF` in addition to the one in `NewF`.\n}\n\nclass C {\n  fn F[me: Self]();\n}\nvar y: C = {};\n// Still works since `C` implements `NewF`\n// from blanket implementation.\nG(y);\n```\n\nThen the interface is implemented for types used as parameters:\n\n```carbon\n// ...\nclass C {\n  impl as NewF {\n    // `NewF.DoF` will be called by `G`, not `C.F`.\n    fn DoF[me: Self]();\n  }\n  // No longer needed: fn F[me: Self]();\n}\n// ...\n```\n\nOnce all types have implemented the new interface, the blanket implementation\ncan be removed:\n\n```carbon\n// Template constraint `HasF` no longer needed.\n\n// New interface\ninterface NewF {\n  fn DoF[me: Self]();\n}\n\n// Blanket implementation no longer needed.\n\nfn G[template T:! NewF](x: T) {\n  x.(NewF.DoF)();\n}\n\nclass C {\n  impl as NewF {\n    fn DoF[me: Self]();\n  }\n}\nvar y: C = {};\n// `C` implements `NewF` directly.\nG(y);\n```\n\nThe [name lookup rules](#name-lookup) ensure that unqualified names will only\nhave one possible meaning, or the compiler will report an error. This error may\nbe resolved by adding qualifications, which is done with the context of an\nambiguity for a specific type. This avoids silent changes in the meaning of the\ncode. Once the disambiguating qualifications have been added, the transition to\nchecked generic becomes safe.\n\n#### To checked generic\n\nOnce all needed qualifications are in place, the `template` keyword can be\nremoved. After this, names will only be looked up in the interface constraints,\nnot the type. If this does not cover the names used by the function, the\ncompiler will report an error and this step can be rolled back and the previous\nstep can be repeated to cover what was missed.\n\nQualifications in the body of the function can be removed at this point, if\ndesired, since the compiler will complain if this introduces an ambiguity from\ntwo different interfaces using that name. It would be reasonable to leave the\nqualifications in if the type parameter has multiple interface constraints, both\nas documentation for readers and to protect against future name collisions if\nthe interfaces are changed.\n\n### Validity can depend on value\n\nA templated parameter may be used in ways where the validity of the result\ndepends on the value of the parameter, not just its type. As an example, whether\ntwo array types are compatible depends on whether they have the same size. With\na symbolic constant sizes, they will only be considered equal if the compiler\ncan show that the two sizes are always equal symbolically. If the size is a\ntemplate parameter, the checking will be delayed until the value of the template\nparameter is known.\n\n### Template dependent\n\nExpressions fall under three categories:\n\n-   Expressions that are valid and have meaning determined without knowing the\n    value of any template parameter are _not template dependent_.\n-   Expressions whose meaning and validity requires knowing the value of a\n    template parameter are _template dependent_. Template dependent expressions\n    are not fully type checked until the template is instantiated, which can\n    result in monomorphization errors. Further, template dependent\n    subexpressions commonly cause a containing expression to also be dependent,\n    as described in the\n    [\"use of dependent value is dependent\" section](#use-of-dependent-value-is-dependent).\n-   Expressions that have a meaning without knowing the value of any template\n    parameter, assuming it is valid, but whose validity requires knowing the\n    value of a template parameter are _template validity dependent_. These\n    expressions can trigger a monomorphization error, but are not considered\n    template dependent for purposes of a containing expression.\n\nThe compiler will type check expressions that are not template dependent when\nthe function is defined, and they won't trigger monomorphization errors.\n\nNote that an expression may not be template dependent even though it has a\ntemplate-dependent sub-expression. For example, a function may have a value that\nis function dependent, but calling that function only needs the type of the\nfunction (meaning the function's signature) to not be template dependent.\n\n#### Simple member access\n\nThere are three cases when performing unqualified member-name lookup into a\ntemplated type:\n\n```carbon\nfn F[template T:! I](x: T) {\n  x.G();\n}\n```\n\n-   If generic name lookup would succeed, in this example it would be because\n    `G` is a member of `I`, then the result of name lookup is template validity\n    dependent. This means that template instantiation may fail if `T` has a\n    member `G` different than `T.(I.G)`. Assuming it succeeds, though, it will\n    definitely have meaning determined by `I.G`. There may still be ambiguity\n    making the result dependent if it is not known whether `x` is a type and\n    `I.G` is a method and so has an implicit `me` parameter.\n-   If the member name is not found in the constraint, lookup may still succeed\n    once the type is known, so the result is template dependent.\n-   If the lookup is ambiguous prior to knowing the value of the type, for\n    example if `G` has two distinct meanings in `I`, then the code is invalid.\n\nThe value of the expression will be dependent. For example, if `U` is an\nassociated type of `I`, then `T.U` as an expression is template validity\ndependent, but the value of that expression is dependent. The value is not\nalways needed to perform checking, for example `x.G()` can be checked without\never determining the value of `x.G` as long as its signature can be determined,\nif it is valid.\n\n#### Compound member access\n\nAdding qualifier to the member name, as in `x.(U.V)`, can make the lookup less\ndependent on the template parameter:\n\n-   If `x` is dependent, and `U` is an interface, the value of the expression is\n    dependent, but the type of the expression is not dependent unless the type\n    of `U.V` involves `Self`. The lookup itself follows proposal\n    [#2360](https://github.com/carbon-language/carbon-lang/pull/2360):\n\n    -   If `U.V` is an _instance_ member, and the type of `x` is known to\n        implement `U`, then the lookup is not dependent. For example, there\n        could be a requirement on `x` or a sufficiently general implementation\n        of `U` that includes all possible types of `x`. The resulting value is\n        dependent unless the implementation of `U` is `final`, see\n        [the impl lookup section](#impl-lookup).\n    -   Otherwise, the lookup is template validity dependent.\n\n    ```carbon\n    interface Serializable {\n      fn Serialize[me: Self]();\n    }\n\n    interface Printable {\n      fn Print[me: Self]();\n    }\n\n    interface Hashable {\n      let HashType:! Type;\n      fn Hash[me: Self]() -> HashType;\n    }\n\n    external impl forall [T:! Serializable] T as Hashable;\n\n    fn F[template T:! Serializable](x: T) {\n      // `T` is required to implement `Serializable` and\n      // `Serialize` is an instance member, so this is not\n      // dependent.\n      x.(Serializable.Serialize)();\n\n      // Any `T` implementing `Serializable` also implements\n      // `Hashable`, since there is a blanket implementation,\n      // so this is not dependent. Note: there may be a\n      // specialization of this impl, so we can't rely on\n      // knowing how `T` implements `Hashable`.\n      x.(Hashable.Hash)();\n\n      // Unclear whether `T` implements `Printable`, but if\n      // does, clear what this means, so this is template\n      // validity dependent\n      x.(Printable.Print)();\n\n      match (x.(Hashable.Hash)()) {\n        // Uses the value of the associated type\n        // `Hashable.HashType` that is template dependent.\n        case _: u64 => { ... }\n        default => { ... }\n      }\n    }\n    ```\n\n-   If `U.V` is dependent, then the entire expression is dependent.\n\n#### Impl lookup\n\nIf the validity of an expression requires that an impl exist for a type, and\nthat can't be determined until the value of a template parameter is known, then\nthe expression is template validity dependent. For example, in the example from\nthe previous section, `x.(Printable.Print)()` is valid if `T` implements\n`Printable`. This can also occur without a qualified lookup, for example:\n\n```carbon\nfn F[T:! Printable](x: T);\nfn G[template T:! Type](x: T) {\n  // Valid if `T` implements `Printable`, so this\n  // expression is template validity dependent.\n  F(x);\n}\n```\n\nThe values of members of an impl for a template-dependent type are template\ndependent, unless they can be resolved to a not template-dependent expression\nusing checked-generic impl resolution.\n\n```\nfinal external impl [T:! Type] T* as D\n    where .Result = T and .Index = i32;\nfn F[T:! Type](p: T*) {\n  // `(T*).(D.Index)` uses the final impl of `D` for `T*`,\n  // and so equals `i32`, which is not dependent.\n  // `(T*).(D.Result)` is recognized as equal to `T`, which\n  // is template dependent.\n}\n```\n\n#### Use of dependent value is dependent\n\nTo match the expectations of C++ templates, uses of dependent values are also\ntemplate dependent, propagating dependence from subexpressions to enclosing\nexpressions. For example, if `expr` is a dependent expression, each of these is\ndependent:\n\n-   `(expr)`\n-   `F(expr)`\n-   `expr + 1`\n-   `if a then expr else b`\n-   `a as expr`\n\nIn some cases, an expression's type and value category can be determined even\nwhen a subexpression is dependent. This makes the expression template validity\ndependent, rather than dependent. For example, the types of these expressions\nare not dependent, even when `expr` is a dependent subexpression:\n\n-   `if expr then a else b`\n-   `expr as T`\n\nFor `match`, which `case` body is executed may be dependent on the type of the\nmatch expression. For example:\n\n```\nfn TypeName[template T:! Type](x: T) -> String {\n  match (x) {\n    // Each entire case body is dependent\n    case _: i32 => { return \"int\"; }\n    case _: bool => { return \"bool\"; }\n    case _: auto* => { return \"pointer\"; }\n    // Allowed even though body of case is invalid for\n    // `T != Vector(String)`\n    case _: Vector(String) => { return x.front(); }\n    default => { return \"unknown\"; }\n  }\n}\n```\n\n## Rationale\n\nThis proposal advances these Carbon goals:\n\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software),\n    by providing an alternative to checked generics that has greater access to\n    the specific value of the parameter.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    by specifically marking code that is using features that should receive\n    greater scruitiny.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code),\n    specifically migrating C++ code using templates, as detailed in the\n    [\"transition from C++ templates to Carbon checked generics\" section](#transition-from-c-templates-to-carbon-checked-generics).\n\n## Alternatives considered\n\n### Only checked generics\n\nLike Rust, Carbon could use only checked generics and not support templates. The\nreasons for this approach are detailed in the [\"problem\" section](#problem).\n\n### SFINAE\n\nWe could use the [SFINAE rule](#terminology), to match C++. While familiar, it\nprevents the compiler from being able to distinguish between \"this code is not\nmeant for this case\" from \"this code has an error.\" The goal of eliminating\nSFINAE is to get away from the verbose and unclear errors that templates are\ninfamous for. C++ itself, with\n[concepts](https://en.cppreference.com/w/cpp/language/constraints), is moving\ntoward stating requirements up front to improve the quality of error\ndiagnostics.\n\n### Ad hoc API specialization\n\nConsider a type with a template type parameter:\n\n```carbon\nclass Vector(template T:! Type) {\n  fn GetPointer[addr me: Self*](index: i32) -> T*;\n  // ...\n}\n```\n\nTo be able to type check a checked generic function using that type:\n\n```carbon\nfn SetFirst[T:! Type](vec: Vector(T)*, val: T) {\n  let p: T* = vec->GetPointer(0);\n  *p = val;\n}\n```\n\nwe need a guarantee that the function signature used to type check the function\nis correct. This won't in general be true if ad hoc specialization is allowed:\n\n```carbon\n// ❌ Not legal Carbon, no ad hoc specialization\nclass Vector(bool) {\n  // `let p: T* = vec->GetPointer(0)` won't type check\n  // in `SetFirst` with `T == bool`.\n  fn GetPointer[addr me: Self*](index: i32) -> BitProxy;\n  // ...\n}\n```\n\nSpecialization is still important for performance, but Carbon's\n[existing approach to specialization of parameterized types](/docs/design/generics/details.md#specialization)\nmakes it clear what parts of the signature can vary, and what properties all\nspecializations will have. In this example, `Vector` would have to be declared\nalongside an interface, and implementations of that interface, as in:\n\n```carbon\nclass Vector(template T:! Type);\n\ninterface VectorSpecialization {\n  let PointerType: Deref(Self);\n  fn GetPointer(p: Vector(Self)*, index: i32) -> PointerType;\n}\n\n// Blanket implementation provides default when there is\n// no specialization.\nimpl forall [T:! Type] T as VectorSpecialization\n    where .PointerType = T* { ... }\n\n// Specialization for `bool`.\nimpl bool as VectorSpecialization\n    where .PointerType = BitProxy { ... }\n\nclass Vector(template T:! Type) {\n  // Return type of `GetPointer` varies with `T`, but must\n  // implement `Deref(T)`.\n  fn GetPointer[addr me: Self*](index: i32)\n      -> T.(VectorSpecialization.PointerType) {\n    return T.(VectorSpecialization.GetPointer)(me, index);\n  }\n  // ...\n}\n```\n\n### Value phase of bindings determined by initializer\n\nWe considered allowing a `let` binding to result in a name with\n[constant value phase](#value-phases) if the initializer was a constant, even if\nit was not declared using the `template` keyword. That would mean that\n`let x: i32 = 5;` would declare `x` as constant, rather than a runtime value.\n\nFor non-type values, this would be a strict improvement in usability. With the\nproposal, there is a choice between writing the concise form `let x: i32 = 5;`\nand `let template x:! i32 = 5;` that lets the compiler use the value of `x`\ndirectly. The `let template` form is both longer and uses `template` which in\nother contexts might merit closer scrutiny, but is generally either desirable or\nharmless in this context. The problem is that for type values, changing from a\nsymbolic value to a constant results in a change to the\n[name lookup](#name-lookup) rules, which is not going to always be desired.\n\nThis decision was the result of a discussion in open discussions on\n[2022-09-09](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#heading=h.g1xcokypbstm).\n\n### Simpler template dependent rules that delayed more checking\n\nWe considered simpler rules for which expressions were considered\n[template dependent](#template-dependent), like that any expression involving a\ntemplate parameter was template dependent. This had the downside that it would\nhave delayed checking of more expressions, and would have resulted in greater\ndifferences between template and checked generic semantics. Ultimately we\nthought that the developer experience would be better if errors were delivered\nearlier.\n\nThis was discussed in\n[open discussion on 2022-10-10](https://discord.com/channels/655572317891461132/941071822756143115/1029411854277165137)\nand on\n[Discord #generics-and-templates starting 2022-10-11](https://discord.com/channels/655572317891461132/941071822756143115/1029411854277165137).\n\n## Future work\n\n### Expanded template constraints\n\n[Template constraints](#template-constraints) will need to support other kinds\nof structural constraints. In particular, the kinds of constraints that can be\nexpressed in C++20 Concepts:\n\n-   [Constraints and concepts (since C++20)](https://en.cppreference.com/w/cpp/language/constraints)\n-   [Requires expression (since C++20)](https://en.cppreference.com/w/cpp/language/requires)\n\nThis is both to allow the constraints of existing C++ code to be migrated, and\nbecause we expect constraints that were found to be useful in C++ will also be\nuseful for Carbon.\n\n### Predicates: constraints on values\n\nWe will need some mechanism to express that the value of a non-type template\nparameter meets some criteria. For example, the size parameter of an array must\nnot be less than 0. We are considering a construct called _predicates_ to\nrepresent these kinds of constraints, see the question-for-leads issue\n[#2153: Generics calling templates](https://github.com/carbon-language/carbon-lang/issues/2153).\n\n### Checked generics calling templates\n\nFor checked generics interoperation with existing templates, and to allow\ntemplates to be migrated to checked generics in any order, we want Carbon to\nsupport supplying a symbolic constant argument value, such as from a checked\ngeneric function, to a function taking a template parameter. One approach that\nalready works is using a template implementation of an interface, as in this\nexample:\n\n```carbon\nfn TemplateFunction[template T:! Type](x: T) -> T;\n\n// `Wrapper` is an interface wrapper around\n// `TemplateFunction`.\n\ninterface Wrapper {\n  fn F[me: Self]() -> Self;\n}\n\nexternal impl forall [template T:! Type] T as Wrapper {\n  fn F[me: Self]() -> Self {\n    TemplateFunction(me);\n  }\n}\n\n// ✅ Allowed:\nfn CheckedGeneric[T:! Wrapper](z: T) -> T {\n  return z.(Wrapper.F)();\n}\n\n// ⚠️ Future work, see #2153:\nfn CheckedGenericDirect[T:! Type](z: T) -> T {\n  return TemplateFunction(z);\n}\n```\n\nMore direct interoperation is being considered in question-for-leads issue\n[#2153: Generics calling templates](https://github.com/carbon-language/carbon-lang/issues/2153).\n\n### Which expressions will be evaluated at compile time\n\nThe section on [value phases](#value-phases) and the\n[\"value phase of bindings determined by initializer\" alternative](#value-phase-of-bindings-determined-by-initializer)\nstill leave open some questions about how value phases interact, and what gets\nevaluated at compile time. For example, what happens when there is a function\ncall in the initializer of a `let template`, as in:\n\n```carbon\nlet x: i32 = 5;\nlet template Y:! i32 = F(x);\n```\n\nIs the function call evaluated at compile time in order to determine a value for\n`Y`, or is this an error? Does it depend on something about `F`, such as its\ndefinition being visible to the caller and being free of side effects? Is this\nonly allowed since the value of `x` can be determined at compile time, even\nthough it is a runtime value, or would the declaration of `x` have to change? If\nwe allow this construction, observe that the parameter to `F` has different\nvalue phases when called at compile time compared to run time, which might\naffect the interpretation of the body of `F`.\n"
  },
  {
    "path": "proposals/p2240.md",
    "content": "# Variadics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2240)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Examples](#examples)\n    -   [Comparisons](#comparisons)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Member packs](#member-packs)\n    -   [Single semantic model for pack expansions](#single-semantic-model-for-pack-expansions)\n    -   [Generalize `expand`](#generalize-expand)\n    -   [Omit `expand`](#omit-expand)\n    -   [Support expanding arrays](#support-expanding-arrays)\n    -   [Omit each-names](#omit-each-names)\n        -   [Disallow pack-type bindings](#disallow-pack-type-bindings)\n    -   [Fold expressions](#fold-expressions)\n    -   [Allow multiple pack expansions in a tuple pattern](#allow-multiple-pack-expansions-in-a-tuple-pattern)\n    -   [Allow nested pack expansions](#allow-nested-pack-expansions)\n    -   [Use postfix instead of prefix `...`](#use-postfix-instead-of-prefix-)\n    -   [Avoid context-sensitity in pack expansions](#avoid-context-sensitity-in-pack-expansions)\n        -   [Fold-like syntax](#fold-like-syntax)\n        -   [Variadic blocks](#variadic-blocks)\n        -   [Keyword syntax](#keyword-syntax)\n    -   [Require parentheses around `each`](#require-parentheses-around-each)\n    -   [Fused expansion tokens](#fused-expansion-tokens)\n    -   [No parameter merging](#no-parameter-merging)\n    -   [Exhaustive function call typechecking](#exhaustive-function-call-typechecking)\n\n<!-- tocstop -->\n\n## Abstract\n\nProposes a set of core features for declaring and implementing generic variadic\nfunctions.\n\nA \"pack expansion\" is a syntactic unit beginning with `...`, which is a kind of\ncompile-time loop over sequences called \"packs\". Packs are initialized and\nreferred to using \"each-names\", which are marked with the `each` keyword at the\npoint of declaration and the point of use.\n\nThe syntax and behavior of a pack expansion depends on its context, and in some\ncases by a keyword following the `...`:\n\n-   In a tuple literal expression (such as a function call argument list), `...`\n    iteratively evaluates its operand expression, and treats the values as\n    successive elements of the tuple.\n-   `...and` and `...or` iteratively evaluate a boolean expression, combining\n    the values using `and` and `or`, and ending the loop early if the underlying\n    operator short-circuits.\n-   In a statement context, `...` iteratively executes a statement.\n-   In a tuple literal pattern (such as a function parameter list), `...`\n    iteratively matches the elements of the scrutinee tuple. In conjunction with\n    pack bindings, this enables functions to take an arbitrary number of\n    arguments.\n\n## Problem\n\nCarbon needs a way to define functions and parameterized types that are\n_variadic_, meaning they can take a variable number of arguments.\n\n## Background\n\nC has long supported variadic functions through the \"varargs\" mechanism, but\nthat's heavily disfavored in C++ because it isn't type-safe. Instead, C++\nprovides a separate feature for defining variadic _templates_, which can be\nfunctions, classes, or even variables. However, variadic templates currently\nsuffer from several shortcomings. Most notably:\n\n-   They must be templates, which means they cannot be definition-checked, and\n    suffer from a variety of other costs such as needing to be defined in header\n    files, and code bloat due to template instantiation.\n-   It is inordinately difficult to define a variadic function whose parameters\n    have a fixed type, and the signature of such a function does not clearly\n    communicate that fixed type to readers.\n-   The design encourages using recursion rather than iteration to process the\n    elements of a variadic parameter list. This results in more template\n    instantiations, and typically has at least quadratic overhead in the size of\n    the pack (at compile time, and sometimes at run time). In recent versions of\n    C++ it is also possible to iterate over packs procedurally, using a\n    [fold expressions](https://en.cppreference.com/w/cpp/language/fold) over the\n    comma operator, but that technique is awkward to use and not widely known.\n\nThere have been a number of C++ standard proposals to address some of these\nissues, and improve variadic templates in other ways, such as\n[P1219R2: Homogeneous variadic function parameters](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1219r2.html),\n[P1306R1: Expansion Statements](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1306r1.pdf),\n[P1858R2: Generalized Pack Declaration and Usage](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1858r2.html),\nand\n[P2277R0: Packs Outside of Templates](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2277r0.html).\nHowever, C++ has chosen not to pursue definition-checking even for non-variadic\nfunctions, so definition-checked variadics seem out of reach. The most recent\nproposal to support fixed-type parameter packs was\n[rejected](https://github.com/cplusplus/papers/issues/297). A proposal to\nsupport iterating over parameter packs was inactive for several years, but has\nvery recently been [revived](https://github.com/cplusplus/papers/issues/156).\n\nSwift supports\n[variadic parameters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/#Variadic-Parameters)\nso long as all elements have the same type, and has recently approved\n[SE-0393: Value and Type Parameter Packs](https://github.com/apple/swift-evolution/blob/main/proposals/0393-parameter-packs.md),\nwhich adds support for definition-checked, heterogeneous variadic parameters\n(with a disjoint syntax).\n[SE-0404: Pack Iteration](https://github.com/simanerush/swift-evolution/blob/se-0404-pack-iteration/proposals/0404-pack-iteration.md),\nwhich extends that to support iterating through a variadic parameter list, has\nbeen positively received, but hasn't yet been approved.\n\nThere have been several attempts to add such a feature to Rust, but that work is\n[currently inactive](https://github.com/rust-lang/rfcs/issues/376#issuecomment-830034029).\n\n## Proposal\n\nSee `/docs/design/variadics.md` in this pull request.\n\n### Examples\n\n```carbon\n// Computes the sum of its arguments, which are i64s\nfn SumInts(... each param: i64) -> i64 {\n  var sum: i64 = 0;\n  ... sum += each param;\n  return sum;\n}\n```\n\n```carbon\n// Concatenates its arguments, which are all convertible to String\nfn StrCat[... each T:! ConvertibleToString](... each param: each T) -> String {\n  var len: i64 = 0;\n  ... len += each param.Length();\n  var result: String = \"\";\n  result.Reserve(len);\n  ... result.Append(each param.ToString());\n  return result;\n}\n```\n\n```carbon\n// Returns the minimum of its arguments, which must all have the same type T.\nfn Min[T:! Comparable & Value](var result: T, ... each next: T) -> T {\n  ... if (each next < result) {\n    result = each next;\n  }\n  return result;\n}\n```\n\n```carbon\n// Invokes f, with the tuple `args` as its arguments.\nfn Apply[... each T:! type, F:! CallableWith(... each T)]\n    (f: F, args: (... each T)) -> auto {\n  return f(...expand args);\n}\n```\n\n```carbon\n// Takes an arbitrary number of vectors with arbitrary element types, and\n// returns a vector of tuples where the i'th element of the vector is\n// a tuple of the i'th elements of the input vectors.\nfn Zip[... each ElementType:! type]\n      (... each vector: Vector(each ElementType))\n      -> Vector((... each ElementType)) {\n  ... var each iter: auto = each vector.Begin();\n  var result: Vector((... each ElementType));\n  while (...and each iter != each vector.End()) {\n    result.push_back((... each iter));\n    ... each iter++;\n  }\n  return result;\n}\n```\n\n```carbon\n// Toy example of mixing variadic and non-variadic parameters.\n// Takes an i64, any number of f64s, and then another i64.\nfn MiddleVariadic(first: i64, ... each middle: f64, last: i64);\n```\n\n```carbon\n// Toy example of using the result of variadic type deduction.\nfn TupleConcat[... each T1: type, ... each T2: type](\n    t1: (... each T1), t2: (... each T2)) -> (... each T1, ... each T2) {\n  return (...expand t1, ...expand t2);\n}\n```\n\n### Comparisons\n\nThe following table compares selected examples of Carbon variadics against\nequivalent code written in C++20 (with and without the extensions discussed\n[earlier](#background)) and Swift.\n\n<table>\n<tr>\n<th>Carbon</th>\n<th>C++20</th>\n<th>C++20 with extensions</th>\n<th>Swift with extensions</th>\n</tr>\n\n<tr>\n<td>\n\n```carbon\n// Computes the sum of its arguments, which are i64s\nfn SumInts(... each param: i64) -> i64 {\n  var sum: i64 = 0;\n  ... sum += each param;\n  return sum;\n}\n```\n\n</td>\n<td>\n\n```cpp\ntemplate <typename... Params>\n    requires (std::convertible_to<Params, int64_t> && ...)\nint64_t SumInts(const Params&... params) {\n  return (static_cast<int64_t>(params) + ... + 0);\n}\n```\n\n</td>\n<td>\n\nWith P1219R2:\n\n```C++\nint64_t SumInts(int64... params) {\n  return (static_cast<int64_t>(params) + ... + 0);\n}\n```\n\n</td>\n<td>\n\n(No extensions)\n\n```swift\nfunc SumInts(_ params: Int64...) {\n  var sum: Int64 = 0\n  for param in params {\n    sum += param\n  }\n  return sum\n}\n```\n\n</td>\n</tr>\n<tr>\n<td>\n\n```carbon\nfn Min[T:! Comparable & Value](first: T, ... each next: T) -> T {\n  var result: T = first;\n  ... if (each next < result) {\n    result = each next;\n  }\n  return result;\n}\n```\n\n</td>\n<td>\n\n```cpp\ntemplate <typename T, typename... Params>\n    requires std::totally_ordered<T> && std::copyable<T> &&\n             (std::same_as<T, Params> && ...)\nT Min(T first, Params... rest) {\n  if constexpr (sizeof...(rest) == 0) {\n    // Base case.\n    return first;\n  } else {\n    T min_rest = Min(rest...);\n    if (min_rest < first) {\n      return min_rest;\n    } else {\n      return first;\n    }\n  }\n}\n```\n\n</td>\n<td>\n\nWith P1219R2 and P1306R2\n\n```cpp\ntemplate <typename T>\n    requires std::totally_ordered<T> && std::copyable<T>\nT Min(const T& first, const T&... rest) {\n  T result = first;\n  template for (const T& t: rest) {\n    if (t < result) {\n      result = t;\n    }\n  }\n  return result;\n}\n```\n\n</td>\n<td>\n\n(No extensions)\n\n```swift\nfunc Min<T: Comparable>(_ first: T, _ rest: T...) -> T {\n  var result: T = first;\n  for t in rest {\n    if (t < result) {\n      result = t\n    }\n  }\n  return result\n}\n```\n\n</td>\n</tr>\n<tr>\n<td>\n\n```carbon\nfn StrCat[... each T:! ConvertibleToString](... each param: each T) -> String {\n  var len: i64 = 0;\n  ... len += each param.Length();\n  var result: String = \"\";\n  result.Reserve(len);\n  ... result.Append(each param.ToString());\n  return result;\n}\n```\n\n</td>\n<td>\n\n```cpp\ntemplate <ConvertibleToString... Ts>\nstd::string StrCat(const Ts&... params) {\n  std::string result;\n  result.reserve((params.Length() + ... + 0));\n  (result.append(params.ToString()), ...);\n  return result;\n}\n```\n\n</td>\n<td>\n\nWith P1306R2\n\n```cpp\ntemplate <ConvertibleToString... Ts>\nstd::string StrCat(const Ts&... params) {\n  std::string result;\n  result.reserve((params.Length() + ... + 0));\n  template for (auto param: params) {\n    result.append(param.ToString());\n  }\n  return result;\n}\n```\n\n</td>\n<td>\n\nWith SE-0393 and SE-404\n\n```swift\nfunc StrCat<each T: ConvertibleToString>(_ param: repeat each T) -> String {\n  var len: Int64 = 0;\n  for param in repeat each param {\n    len += param.Length()\n  }\n  var result: String = \"\"\n  result.reserveCapacity(len)\n  for param in repeat each param {\n    result.append(param.ToString())\n  }\n  return result\n}\n```\n\n</td>\n</tr>\n</table>\n\n## Rationale\n\nCarbon needs variadics to effectively support\n[interoperation with and migration from C++](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code),\nwhere variadic templates are fairly common. Variadics also make code\n[easier to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\nbecause some APIs (such as `printf`) can't be naturally expressed in terms of a\nfixed number of parameters.\n\nFurthermore, Carbon needs to support _generic_ variadics for the same reasons it\nneeds to support generic non-variadic functions: for example,\ndefinition-checking makes APIs\n[easier to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\nand [easier to evolve](/docs/project/goals.md#software-and-language-evolution).\nFurthermore, the language as a whole is easier to understand and write code in\nif separate features like variadics and generics compose in natural ways, rather\nthan being mutually exclusive.\n\nVariadics are also important for supporting\n[performance-critical software](/docs/project/goals.md#performance-critical-software),\nbecause variadic APIs can be more efficient than their non-variadic\ncounterparts. For example, `StrCat` is fundamentally more efficient than\nsomething like a chain of `operator+` calls on `std::string`, because it does\nnot need to materialize a series of partial results, and it can pre-allocate a\nbuffer large enough for the final result.\n\nVariadics are also needed to support the principle that\n[all APIs are library APIs](/docs/project/principles/library_apis_only.md),\nbecause the library representations of types such as tuples and callables will\nneed to be variadic. This proposal may appear to deviate from that principle in\nsome ways, but that appearance is misleading:\n\n-   The design of pack expansion expressions treats the tuple literal syntax as\n    built-in, but this isn't a problem because literal syntaxes are explicitly\n    excluded from the principle.\n-   The design of pack expansion patterns treats tuple types as built-in. This\n    is arguably consistent with the principle, if we regard a tuple pattern as a\n    kind of tuple literal (note that they have identical syntax). This proposal\n    also revises the text of the principle to make that more explicit.\n-   Pack types themselves are built-in types, with no library API. However, the\n    principle only applies to first-class types, and pack types are decidedly\n    not first-class: they cannot be function return types, they cannot even be\n    named, and an expression cannot evaluate to a value with a pack type unless\n    it's within a pack expansion _and_ it has compile-time expression phase (and\n    even that narrow exception only exists to make the formalism more\n    convenient).\n\n## Alternatives considered\n\n### Member packs\n\nWe could potentially support declaring each-names as class members. However,\nthis raises some novel design issues. In particular, pack bindings currently\nrely exclusively on type deduction for information like the arity of the pack,\nbut for class members, there usually isn't an initializer available to drive\ntype deduction.\n\nIn addition, it's usually if not always possible to work around the lack of\nmember packs by using members with tuple or array types instead. Consequently,\nthis feature is deferred to future work.\n\n### Single semantic model for pack expansions\n\nThere's a subtle discrepancy in how this proposal models expression pack\nexpansions: at run time, all pack expansions are modeled as procedural loops\nthat successively evaluate the expansion body for each element of the input\npack, and within each iteration, expressions have scalar values. However, in the\ntype system, expressions within a pack expansion are notionally evaluated once,\nproducing a pack value. In effect, this treats pack expansions like SIMD code,\nwith expressions operating on \"vectors\" of data in parallel, rather than\niteratively executing the code on a series of scalar values.\n\nThis discrepancy leads to an impedance mismatch where the two models meet. In\nparticular, it leads to the result that expressions within a pack expansion have\npack types, but do not evaluate to pack values. This contravenes one of the\nbasic expectations of a type system, that the type of an expression equals (or\nis at least a supertype of) the type of its value.\n\nIt's tempting to resolve the inconsistency by applying the parallel model at run\ntime as well as in the type system. However, that isn't feasible, because the\nparallel model has the same limitation for variadics as it does for SIMD: it\ncan't model branching control flow. For example, consider\n`(... if (expand cond) then F(expand param) else G(expand param))`: if\n`expand param` truly evaluated to a pack value, then evaluating this expression\nwould require N calls to _both_ `F` and `G`, rather than N calls to _either_ `F`\nor `G`. Even for expressions that don't contain control flow, the same problem\napplies when they occur within a statement pack expansion that does. We can't\neven statically detect these problems, because a branch could be hidden inside a\nfunction call. And this isn't just a performance problem -- if `F` or `G` have\nside effects, it can also be a correctness problem.\n\nAn earlier version of this proposal tried to address this problem in a more\nlimited way by saying that expressions within a pack expansion don't have types\nat all, but instead have \"type packs\". This shift in terminology nominally\navoids the problem of having expressions that don't evaluate to a value of the\nexpression's type, but it doesn't seem to be very clarifying in practice, and it\ndoesn't address the substance of the problem.\n\n### Generalize `expand`\n\nThe syntax \"`...expand` _expression_\" behaves like syntactic sugar for\n`... each x`, where `x` is an invented pack binding in the same scope, defined\nas if by \"`let (... each x: auto) =` _expression_\". We could generalize that by\nsaying that `expand` is a prefix operator with the same precedence as `*` that\ncan be used anywhere in a pack expansion, where \"`expand` _expression_\" is\nsyntactic sugar for `each x` (with `x` defined as before, in the scope\ncontaining the pack expansion). This would make `expand` more useful, and also\nresolve the anomaly where `...expand` is the only syntax that begins with `...`\nbut is not a pack expansion. It is also a precondition for several of the\nalternatives discussed below.\n\nHowever, those semantics could be very surprising in practice. For example:\n\n```carbon\n...if (Condition()) {\n  var x: auto = expand F(y);\n}\n```\n\nIn this code, `F(y)` is evaluated before the pack expansion is entered, which\nmeans that it is evaluated unconditionally, and it cannot refer to names\ndeclared inside the `if` block.\n\nWe can avoid the name-resolution issue by disallowing `expand` in statement pack\nexpansions, but the sequencing of evaluation could still be surprising,\nparticularly with `if` expressions.\n\n### Omit `expand`\n\nAs noted above, `...expand` is fundamentally syntactic sugar, so we could omit\nit altogether. This would somewhat simplify the design, and avoid the anomaly of\nhaving one syntax that starts with `...` but isn't a pack expansion. However,\nthat would make it substantially less ergonomic to do things like expand a tuple\ninto an argument list, which we expect to be relatively common.\n\n### Support expanding arrays\n\nStatically-sized arrays are very close to being a special case of tuple types:\nthe only difference between an array type `[i32; 2]` (using Rust syntax) and a\ntuple type `(i32, i32)` is that the array type can be indexed with a run-time\nsubscript. Consequently, it would be fairly natural to allow `expand` to operate\non arrays as well as tuples, and even to allow arrays of types to be treated as\ntuple types (in the same way that tuples of types can be treated as tuple\ntypes).\n\nThis functionality is omitted from the current proposal because we have no\nmotivating use cases, but it could be added as an extension. Note that there are\nimportant motivating use cases under some of the alternatives considered below.\n\n### Omit each-names\n\nRather than having packs be distinguished by their names, we could instead\ndistinguish them by their types. For example, under the current proposal, the\nsignature of `Zip` is:\n\n```carbon\nfn Zip[... each ElementType:! type]\n      (... each vector: Vector(each ElementType))\n      -> Vector((... each ElementType));\n```\n\nWith this alternative, it could instead be written:\n\n```carbon\nfn Zip[ElementTypes:! [type;]]\n      (... vectors: Vector(expand ElementTypes))\n      -> Vector((... expand ElementTypes));\n```\n\nThis employs several features not in the primary proposal:\n\n-   In cases where the declared type of the each-name does not vary across\n    iterations (like `ElementType`), we can re-express it as an array binding if\n    [`expand` supports arrays](#support-expanding-arrays), and if\n    [`expand` is a stand-alone operator](#generalize-expand). Note that we only\n    need this in type position of a binding pattern, where we could more easily\n    restrict `expand` to avoid the problems discussed earlier.\n-   In cases where the declared type of the binding does vary, that fact alone\n    implies that the binding refers to a pack, so we can effectively infer the\n    presence of `each` from the type, rather than make the user spell it out\n    explicitly.\n\nThis slight change in syntax belies a much larger shift in the underlying\nsemantics: since these are ordinary bindings, a given call to `Zip` must bind\neach of them to a single value that represents the whole sequence of arguments\n(which is why their names are now plural). In the case of `ElementTypes`, that\nfollows straightforwardly from its type: it represents the argument types as an\narray of `type`s. The situation with `vectors` is more subtle: we have to\ninterpret `Vector(expand ElementTypes)` as the type of the whole sequence of\nargument values, rather than as a generic description of the type of a single\nargument. In other words, we have to interpret it as a pack type, and that means\n`vectors` notionally binds to a run-time pack value.\n\nConsequently, when `vectors` is used in the function body, it doesn't need an\n`each` prefix: we've chosen to express variadicity in terms of types, and it\nalready has a pack type, so it can be directly used as an expansion site.\n\nThis approach has a few advantages:\n\n-   We don't have to introduce the potentially-confusing concept of a binding\n    that binds to multiple values simultaneously.\n-   It avoids the anomaly where we have pack types in the type system, but no\n    actual values of those types.\n-   Removing the `each` keyword makes it more natural to spell `expand` as a\n    symbolic token (earlier versions of this proposal used `[:]`), which is more\n    concise and doesn't need surrounding whitespace.\n-   For fully homogeneous variadics (such as `SumInts` and `Min`) it's actually\n    possible to write the function body as an ordinary loop with no variadics,\n    by expressing the signature in terms of a non-pack binding with an array\n    type.\n\nHowever, it also has some major disadvantages:\n\n-   The implicit expansion of pack-type bindings hurts readability. For example,\n    it's easy to overlook the fact that the loop condition\n    `while (...and expand iters != vectors.End())` in `Zip` has two expansion\n    sites, not just one. This problem is especially acute in cases where a\n    non-local name has a pack type.\n-   We have to forbid template-dependent names from having pack types (see\n    [leads issue #1162](https://github.com/carbon-language/carbon-lang/issues/1162)),\n    because the possibility that an expression might be an expansion site in\n    some instantiations but not others would cause serious readability and\n    implementability issues.\n-   A given _use_ of such a binding really represents a single value at a time,\n    in the same way that the iteration variable of a for-each loop does, so\n    giving the binding a plural name and a pack type creates confusion in that\n    context rather than alleviating it.\n\nIt's also worth noting that we may eventually want to introduce operations that\ntreat the sequence of bound values as a unit, such as to determine the length of\nthe sequence (like `sizeof...` in C++), or even to index into it. This approach\nmight seem more amenable to that, because it conceptually treats the sequence of\nvalues as a value in itself, which could have its own operations. However, this\napproach leaves no \"room\" in the syntax to spell those operations, because any\nmention of a pack-type binding implicitly refers to one of its elements.\n\nConversely, the status quo proposal seems to leave a clear syntactic opening for\nthose operations: you can refer to the sequence as a whole by omitting `each`,\nso `each vector.Size()` refers to the size of the current iteration's `vector`,\nwhereas `vector.Size()` could refer to the size of the sequence of bound values.\nHowever, this could easily turn out to be a \"wrong default\": omitting `each`\nseems easy to do by accident, and easy to misread during code review.\n\nThere are other solutions to this problem that work equally well with the status\nquo or this alternative. In particular, it's already possible to express these\noperations outside of a pack expansion by converting to a tuple, as in\n`(... each vector).Size()` (status quo) or `(... vectors).Size()` (this\nalternative). That may be sufficient to address those use cases, especially if\nwe relax the restrictions on nesting pack expansions. Failing that,\nvariadic-only spellings for these operations (like `sizeof...` in C++) would\nalso work with both approaches. So this issue does not seem like an important\ndifferentiator between the two approaches.\n\n#### Disallow pack-type bindings\n\nAs a variant of the above approach, it's possible to omit both each-names and\npack-type bindings, and instead rely on variadic tuple-type bindings. For\nexample, the signature of `Zip` could instead be:\n\n```carbon\nfn Zip[ElementTypes:! [type;]]\n      (... expand vectors: (... Vector(expand ElementTypes)))\n      -> Vector((... expand ElementTypes));\n```\n\nThis signature doesn't change the callsite semantics, but within the function\nbody `vectors` will be a tuple rather than a pack. This avoids or mitigates all\nof the major disadvantages of pack-type bindings, but it comes at a substantial\ncost: the function signature is substantially more complex and opaque. That\nseems likely to be a bad tradeoff -- the disadvantages of pack-type bindings\nmostly concern the function body, but readability of variadic function\nsignatures seems much more important than readability of variadic function\nbodies, because the signatures will be read far more often, and by programmers\nwho have less familiarity with variadics.\n\nThis approach requires us to relax the ban on nested pack expansions. This does\ncreate some risk of confusion about which pack expansion a given `expand`\nbelongs to, but probably much less than if we allowed unrestricted nesting.\n\nThe leads chose not to pursue this approach in\n[leads issue #1162](https://github.com/carbon-language/carbon-lang/issues/1162).\n\n### Fold expressions\n\nWe could generalize the `...and` and `...or` syntax to support a wider variety\nof binary operators, and to permit specifying an initial value for the chain of\nbinary operators, as with C++'s\n[fold expressions](https://en.cppreference.com/w/cpp/language/fold). This would\nbe more consistent with C++, and would give users more control over\nassociativity and over the behavior of the arity-zero case.\n\nHowever, fold expressions are arguably too general in some respects: folding\nover a non-commutative operator like `-` is more likely to be confusing than to\nbe useful. Similarly, there are few if any plausible use cases for customizing\nthe arity-zero behavior of `and` or `or`. Conversely, fold expressions are\narguably not general enough in other respects, because they only support folding\nover a fixed set of operators, not over functions or compound expressions.\n\nFurthermore, in order to support folds over operator tokens that can be either\nbinary or prefix-unary (such as `*`), we would need to choose a different syntax\nfor tuple element lists. Otherwise, `...*each foo` would be ambiguous between\n`*foo[:0:], *foo[:1:],` etc. and `foo[:0:] * foo[:1:] *` etc.\n\nNote that even if Carbon supported more general C++-like fold expressions, we\nwould still probably have to give `and` and `or` special-case treatment, because\nthey are short-circuiting.\n\nAs a point of comparison, C++ fold expressions give special-case treatment to\nthe same two operators, along with `,`: they are the only ones where the initial\nvalue can be omitted (such as `... && args` rather than `true && ... && args`)\neven if the pack may be empty. Furthermore, folding over `&&` appears to have\nbeen the original motivation for adding fold expressions to C++; it's not clear\nif there are important motivating use cases for the other operators.\n\nGiven that we are only supporting a minimal set of operators, allowing `...` to\noccur in ordinary binary syntax has few advantages and several drawbacks:\n\n-   It might conflict with a future general fold facility.\n-   It would invite users to try other operators, and would probably give less\n    clear errors if they do.\n-   It would substantially complicate parsing and the AST.\n-   It would force users to make a meaningless choice between `x or ...` and\n    `... or x`, and likewise for `and`.\n\nSee also the discussion [below](#fold-like-syntax) of using `...,` and `...;` in\nplace of the tuple and statement forms of `...`. This is inspired by fold\nexpressions, but distinct from them, because `,` and `;` are not truly binary\noperators, and it's targeting a different problem.\n\n### Allow multiple pack expansions in a tuple pattern\n\nAs currently proposed, we allow multiple `...` expressions within a tuple\nliteral expression, but only allow one `...` pattern within a tuple pattern. It\nis superficially tempting to relax this restriction, but fundamentally\ninfeasible.\n\nAllowing multiple `...` patterns would create a potential for ambiguity about\nwhere their scrutinees begin and end. For example, given a signature like\n`fn F(... each xs: i32, ... each ys: i32)`, there is no way to tell where `xs`\nends and `ys` begins in the argument list; every choice is equally valid. That\nambiguity can be avoided if the types are different, but that would make type\n_non_-equality a load-bearing part of the pattern. That's a very unusual thing\nto need to reason about in the type system, so it's liable to be a source of\nsurprise and confusion for programmers, and in particular it looks difficult if\nnot impossible to usefully express with generic types, which would greatly limit\nthe usefulness of such a feature.\n\nFunction authors can straightforwardly work around this restriction by adding\ndelimiters. For example, the current design disallows\n`fn F(... each xs: i32, ... each ys: i32)`, but it allows\n`fn F((... each xs: i32), (... each ys: i32))`, which is not only easier to\nsupport, but makes the callsite safer and more readable, since the boundary\nbetween the `xs` and `ys` arguments is explicitly marked. By contrast, if we\ndisallowed multiple `...` expressions in a function argument list, function\ncallers who ran into that restriction would often find it difficult or\nimpossible to work around. Note, however, that this workaround presupposes that\nfunction signatures can have bindings below top-level, which is\n[currently undecided](https://github.com/carbon-language/carbon-lang/issues/1229).\n\nTo take a more abstract view of this situation: when we reuse expression syntax\nas pattern syntax, we are effectively inverting expression evaluation, by asking\nthe language to find the operands that would cause an expression to evaluate to\na given value. That's only possible if the operations involved are invertible,\nmeaning that they do not lose information. When a tuple literal contains\nmultiple `...` expressions, evaluating it effectively discards structural\ninformation about for example where `xs` ends and `ys` begins. The operation of\nforming a tuple from multiple packs is not invertible, and consequently we\ncannot use it as a pattern operation. Our rule effectively says that if the\nfunction needs that structural information, it must ask the caller to provide\nit, rather than asking the compiler to infer it.\n\n### Allow nested pack expansions\n\nEarlier versions of this design allowed pack expansions to contain other pack\nexpansions. This is in some ways a natural generalization, but it added\nnontrivial complexity to the design. In particular, when an each-name is\nlexically within two or more pack expansions, we need a rule for determining\nwhich pack expansion iterates over it, in a way that is unsurprising and\nsupports the intended use cases. However, we have few if any motivating use\ncases for it, which made it difficult to evaluate that aspect of the design.\nConsequently, this proposal does not support nested pack expansions, although it\ntries to avoid ruling them out as a future extension.\n\n### Use postfix instead of prefix `...`\n\n`...` is a postfix operator in C++, which aligns with the natural-language use\nof \"…\", so it would be more consistent with both if `...`, `...and`, and `...or`\nwere postfix operators spelled `...`, `and...`, and `or...`, and likewise if\nstatement pack expansions were marked by a `...` at the end rather than the\nbeginning.\n\nHowever, prefix syntaxes are usually easier to parse (particularly for humans),\nbecause they ensure that by the time you start parsing an utterance, you already\nknow the context in which it is used. This is clearest in the case of\nstatements: the reader might have to read an arbitrary amount of code in the\nblock before realizing that the code they've been reading will be executed\nvariadically, so that seems out of the question. The cases of `and`, `or`, and\n`,` are less clear-cut, but we have chosen to make them all prefix operators for\nconsistency with statements.\n\n### Avoid context-sensitity in pack expansions\n\nThis proposal \"overloads\" the `...` token with multiple different meanings\n(including different precedences), and the meaning depends in part on the\nsurrounding context, despite Carbon's principle of\n[avoiding context-sensitivity](/docs/project/principles/low_context_sensitivity.md).\nWe could instead represent the different meanings using separate syntaxes.\n\nThere are several variants of this approach, but they all have substantial\ndrawbacks (see the following subsections). Furthermore, the problems associated\nwith context-sensitivity appear to be fairly mild in this case: the difference\nbetween a tuple literal context and a statement context is usually quite local,\nand is usually so fundamental that confusion seems unlikely.\n\n#### Fold-like syntax\n\nWe could use a modifier after `...` to select the expansion's meaning (as we\nalready do with `and` and `or`). In particular, we could write `...,` to\niteratively form elements of a tuple, and write `...;` to iteratively execute a\nstatement. This avoids context-sensitivity (apart from `...,` having a dual role\nin expressions and patterns, like many other syntaxes), and has an underlying\nunity: `...,`, `...;` `...and`, and `...or` represent \"folds\" over the `,`, `;`,\n`and`, and `or` tokens, respectively. As a side benefit, this would preserve the\nproperty that a tuple literal always contains a `,` character (unlike the\ncurrent proposal).\n\nHowever, this approach has major readability problems. Using `...;` as a prefix\noperator is completely at odds with the fact that `;` marks the end of a\nstatement, not the beginning. Furthermore, it would probably be surprising to\nuse `...;` in contexts where `;` is not needed, because the end of the statement\nis marked with `}`.\n\nThe problems with `...,` are less severe, but still substantial. In this syntax\n`,` does not behave like a separator, but our eyes are trained to read it as\none, and that habit is difficult to unlearn. For example, most readers have\nfound that they can't help automatically reading `(..., each x)` as having two\nsub-expressions, `...` and `each x`. This effect is particularly disruptive when\nskimming a larger body of code, such as:\n\n```carbon\nfn TupleConcat[..., each T1: type, ..., each T2: type](\n    t1: (..., each T1), t2: (..., each T2)) -> (..., each T1, ..., each T2) {\n  return (..., expand t1, ..., expand t2);\n}\n```\n\n#### Variadic blocks\n\nWe could replace the statement form of `...` with a variadic block syntax such\nas `...{ }`. However, this doesn't give us an alternative for the tuple form of\n`...`, and yet heightens the problems with it: `...{` could read as as applying\nthe `...` operator to a struct literal.\n\nFurthermore, it gives us no way to variadically declare a variable that's\nvisible outside the expansion (such as `each iter` in the `Zip` example). This\ncan be worked around by declaring those variables as tuples, but this adds\nunnecessary complexity to the code.\n\n#### Keyword syntax\n\nWe could drop `...` altogether, and use a separate keyword for each kind of pack\nexpansion. For example, we could use `repeat` for variadic lists of tuple\nelements, `do_repeat` for variadic statements, and `all_of` and `any_of` in\nplace of `...and` and `...or`. This leads to code like:\n\n```carbon\n// Takes an arbitrary number of vectors with arbitrary element types, and\n// returns a vector of tuples where the i'th element of the vector is\n// a tuple of the i'th elements of the input vectors.\nfn Zip[repeat each ElementType:! type]\n      (repeat each vector: Vector(each ElementType))\n      -> Vector((repeat each ElementType)) {\n  do_repeat var each iter: auto = each vector.Begin();\n  var result: Vector((repeat each ElementType));\n  while (all_of each iter != each vector.End()) {\n    result.push_back((repeat each iter));\n    repeat each iter++;\n  }\n  return result;\n}\n```\n\nThis approach is heavily influenced by\n[Swift variadics](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0393-parameter-packs.md),\nbut not quite the same. It has some major advantages: the keywords are more\nconsistent with `each` (and `expand` to some extent), substantially less\nvisually noisy than `...`, and they may also be more self-explanatory. However,\nit does have some substantial drawbacks.\n\nMost notably, there is no longer any syntactic commonality between the different\ntokens that mark the root of an expansion. That makes it harder to visually\nidentify expansions, and could also make variadics harder to learn, because the\nspelling does not act as a mnemonic cue. And while it's already not ideal that\nunder the primary proposal a tuple literal is identified by the presence of\neither `,` or `...`, it seems even worse if one of those two tokens is instead a\nkeyword.\n\nRelatedly, the keywords have less clear precedence relationships, because\n`all_of` and `any_of` can't as easily \"borrow\" their precedence from their\nnon-variadic counterparts. For example, consider this line from `Zip`:\n\n```carbon\nwhile (...and each iter != each vector.End()) {\n```\n\nUnder this alternative, that becomes:\n\n```carbon\nwhile (all_of each iter != each vector.End()) {\n```\n\nI find the precedence relationships in the initial `all_of expand iters !=` more\nopaque than in `...and expand iters !=`, to the extent that we might need to\nrequire additional parentheses:\n\n```carbon\n  while (all_of (expand iters != each vectors.End())) {\n```\n\nThat avoids outright ambiguity, but obliging readers to maintain a mental stack\nof parentheses in order to parse the expression creates its own readability\nproblems.\n\nIt's appealing that the `repeat` keyword combines with `each` to produce code\nthat's almost readable as English, but it creates a temptation to read `expand`\nthe same way, which will usually be misleading. For example, `repeat expand foo`\nsounds like it is repeatedly expanding `foo`, but in fact it expands it only\nonce. It's possible that a different spelling of `expand` could avoid that\nproblem, but I haven't been able to find one that does so while also avoiding\nthe potential for confusion with `each`. This is somewhat mitigated by the fact\nthat `expand` expressions are likely to be rare.\n\nIt's somewhat awkward, and potentially even confusing, to use an imperative word\nlike `repeat` in a pattern context. By design, the pattern language is\ndescriptive rather than imperative: it describes the values that match rather\nthan giving instructions for how to match them. As a result, in a pattern like\n`(repeat each param: i64)`, it's not clear what action is being repeated.\n\nFinally, it bears mentioning that the keywords occupy lexical space that could\notherwise be used for identifiers. Notably, `all_of`, `any_of`, and `repeat` are\nall names of functions in the C++ standard library. This is not a fundamental\nproblem, because we expect Carbon to have some way of \"quoting\" a keyword for\nuse as an identifier (such as Rust's\n[raw identifiers](https://doc.rust-lang.org/rust-by-example/compatibility/raw_identifiers.html)),\nbut it is likely to be a source of friction.\n\n### Require parentheses around `each`\n\nWe could give `each` a lower precedence, so that expressions such as\n`each vector.End()` would need to be written as `(each vector).End()`. This\ncould make the code clearer for readers, especially if they are new to Carbon\nvariadics. However, this would make the code visually busier, and might give the\nmisleading impression that `each` can be applied to anything other than an\nidentifier. I propose that we wait and see whether the unparenthesized syntax\nhas readability problems in practice, before attempting to solve those problems.\n\nWe have discussed a more general solution to this kind of problem, where a\nprefix operator could be embedded in a `->` token, in order to apply the prefix\noperator to the left-hand operand without needing parentheses. However, this\napproach is much more appealing when the prefix operator is a symbolic token:\n`x-?>y` may be a plausible alternative to `(?x).y`, but `x-each>y` seems much\nharder to visually parse. Furthermore, this approach is hard to reconcile with\ntreating `each` as fundamentally part of the name, rather than an operator\napplied to the name.\n\n### Fused expansion tokens\n\nInstead of treating `...and` and `...or` as two tokens with whitespace\ndiscouraged between them, we could treat them as single tokens. This might more\naccurately reflect the fact that they are semantically different operations than\n`...`, and reduce the potential for readability problems in code that doesn't\nfollow our recommended whitespace conventions. However, that could lead to a\nworse user experience if users accidentally insert a space after the `...`.\n\n### No parameter merging\n\nUnder the current proposal, the compiler attempts to merge function parameters\nin order to support use cases like this one, where merging the parameters of\n`Min` enables us to pair each argument with a single logical parameter that will\nmatch it:\n\n```carbon\nfn Min[T:! type](first: T, ... each next: T) -> T;\n\nfn F(... each arg: i32) {\n  Min(... each arg, 0 as i32);\n}\n```\n\nHowever, this approach makes typechecking hard to understand (and predict),\nbecause the complex conditions governing merging mean that subtle differences in\nthe code can cause dramatic differences in the semantics. For example:\n\n```carbon\nfn F[A:! I, ... each B:! I](a: A, ... each b: each B);\nfn G[A:! I, ... each B:! I](a: A, ... each b: each B) -> A;\n```\n\nThese two function signatures are identical other than their return types, but\nthey actually have different requirements on their arguments: `G` requires the\nfirst argument to be singular, whereas `F` only requires _some_ argument to be\nsingular. It seems likely to be hard to teach programmers that the function's\nreturn type sometimes affects whether a given argument list is valid. Relatedly,\nit's hard to see how a diagnostic could concisely explain why a given call to\n`G` is invalid, in a way that doesn't seem to also apply to `F`.\n\nWe could solve that problem by omitting parameter merging, and interpreting all\nof the above signatures as requiring that the first argument must be singular,\nbecause the first parameter is singular. Thus, there would be a clear and\npredictable connection between the parameter list and the requirements on the\nargument list.\n\nIn order to support use cases like `Min` where the author doesn't intend to\nimpose such a requirement, we would need to provide some syntax for declaring\n`Min` so that it has a single parameter, but can't be called with no arguments.\nMore generally, this syntax would probably need to support setting an arbitrary\nminimum number of arguments, not just 1. For example, an earlier version of this\nproposal used `each(>=N)` to require that a parameter match at least N\narguments, so `Min` could be written like this:\n\n```carbon\nfn Min[T:! type](... each(>=1) param: T) -> T;\n```\n\nHowever, this alternative has several drawbacks:\n\n-   We haven't been able to find a satisfactory arity-constraint syntax. In\n    addition to its aesthetic problems, `each(>=1) param` disrupts the mental\n    model where `each` is part of the name, and it's conceptually awkward\n    because the constraint actually applies to the pack expansion as a whole,\n    not to the each-name in particular. However, it's even harder to find an\n    arity-constraint syntax that could attach to `...` without creating\n    ambiguity. Furthermore, any arity-constraint syntax would be an additional\n    syntax that users need to learn, and an additional choice they need to make\n    when writing a function signature.\n-   Ideally, generic code should typecheck if every possible monomorphization of\n    it would typecheck. This alternative does not live up to that principle --\n    see, for example, the above example of `Min`. The current design does not\n    fully achieve that aspiration either, but it's far more difficult to find\n    plausible examples where it fails.\n-   The first/rest style will probably be more natural to programmers coming\n    from C++, and if they define APIs in that style, there isn't any plausible\n    way for them to find out that they're imposing an unwanted constraint on\n    callers, until someone actually tries to make a call with the wrong shape.\n\n### Exhaustive function call typechecking\n\nThe current proposal uses merging and splitting to try to align the argument and\nparameter lists so that each argument has exactly one parameter than can match\nit. We also plan to extend this design to also try the opposite approach,\naligning them so that each parameter has exactly one argument that it can match.\nHowever, it isn't always possible to align arguments and parameters in that way.\nFor example:\n\n```carbon\nfn F[... each T:! type](x: i32, ... each y: each T);\n\nfn G(... each z: i32) {\n  F(... each z, 0 as i16);\n}\n```\n\nEvery possible monomorphization of this code would typecheck, but we can't merge\nthe parameters because they have different types, and we can't merge the\narguments for the same reason. We also can't split the variadic parameter or the\nvariadic argument, because either of them could be empty.\n\nThe fundamental problem is that, although every possible monomorphization\ntypechecks, some monomorphizations are structurally different from others. For\nexample, if `each z` is empty, the monomorphized code converts `0 as i16` to\n`i32`, but otherwise `0 as i16` is passed into `F` unmodified.\n\nWe could support such use cases by determining which parameters can potentially\nmatch which arguments, and then typechecking each pair. For example, we could\ntypecheck the above code by cases:\n\n-   If `each z` is empty, `x: i32` matches `0 as i16` (which typechecks because\n    `i16` is convertible to `i32`), and `each y: each T` matches nothing.\n-   If `each z` is not empty, `x: i32` matches its first element (which\n    typechecks because `i32` is convertible to `i32`), and `each y: each T`\n    matches the remaining elements of `each z`, followed by `0 as i16` (which\n    typechecks by binding `each T` to `⟬«i32; ‖each z‖-1», i16⟭`).\n\nMore generally, this approach works by identifying all of the structurally\ndifferent ways that arguments could match parameters, typechecking them all in\nparallel, and then combining the results with logical \"and\".\n\nHowever, the number of such cases (and hence the cost of typechecking) grows\nquadratically, because the number of cases grows with the number of parameters,\nand the case analysis has to be repeated for each variadic argument.\n[Fast development cycles](/docs/project/goals.md#fast-and-scalable-development)\nare a priority for Carbon, so if at all possible we want to avoid situations\nwhere compilation costs grow faster than linearly with the amount of code.\n\nFurthermore, typechecking a function call doesn't merely need to output a\nboolean decision about whether the code typechecks. In order to typecheck the\ncode that uses the call, and support subsequent phases of compilation, it needs\nto also output the type of the call expression, and that can depend on the\nvalues of deduced parameters of the function.\n\nThese more complex outputs make it much harder to combine the results of\ntypechecking the separate cases. To do this in a general way, we would need to\nincorporate some form of case branching directly into the type system. For\nexample:\n\n```carbon\nfn P[T:! I, ... each U:! J](t: T, ... each u: each U) -> T;\n\nfn Q[X:! I&J, ... each Y:! I&J](x: X, ... each y: each Y) -> auto {\n  return P(... each y, x);\n}\n\nfn R[A:! I&J ... each B:! I&J](a: A, ... each b: each B) {\n  Q(... each b, a);\n}\n```\n\nThe typechecker would need to represent the type of `P(... each x, y)` as\nsomething like `(... each Y, X).0`. That subscript `.0` acts as a disguised form\nof case branching, because now any subsequent code that depends on\n`P(... each y, x)` needs to be typechecked separately for the cases where\n`... each Y` is and is not empty. In this case, that even leaks back into the\ncaller `R` through `Q`'s return type, which compounds the complexity: the type\nof `Q(... each b, a)` would need to be something like\n`((... each B, A).(1..‖each B‖), (... each B, A).0).0` (where `.(M..N)` is a\nhypothetical tuple slice notation).\n\nAll of this may be feasible, but the cost in type system complexity and\nperformance would be daunting, and the benefits are at best unclear, because we\nhave not yet found plausible motivating use cases that benefit from this kind of\ntypechecking.\n"
  },
  {
    "path": "proposals/p2274.md",
    "content": "# Subscript syntax and semantics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2274)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Examples](#examples)\n-   [Rationale based on Carbon's goals](#rationale-based-on-carbons-goals)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Different subscripting syntaxes](#different-subscripting-syntaxes)\n    -   [Multiple indices](#multiple-indices)\n    -   [Read-only subscripting](#read-only-subscripting)\n    -   [Rvalue-only subscripting](#rvalue-only-subscripting)\n    -   [Map-like subscripting](#map-like-subscripting)\n        -   [Usage-based rewriting](#usage-based-rewriting)\n\n<!-- tocstop -->\n\n## Abstract\n\nAdds support for subscripting using the conventional square-bracket syntax, with\nsupport for both array-like and slice-like semantics.\n\nCloned from [#1356](https://github.com/carbon-language/carbon-lang/pull/1356),\nwhich was cloned from\n[#1059](https://github.com/carbon-language/carbon-lang/pull/1059).\n\n## Problem\n\nCarbon needs a convenient way of indexing into objects like arrays and slices.\n\n## Background\n\nFor purposes of this proposal, a \"slice\" is an object that refers to some region\nof an array, and provides access to it, such as a `std::string_view` or\n`std::span` in C++. Slices have subtly different indexing API semantics than\narrays: indexing into an array can produce an l-value only if the array itself\nis an l-value, but indexing into a slice can produce an l-value regardless of\nthe slice's value category.\n\nInterfaces are Carbon's\n[only static open extension mechanism](/docs/project/principles/static_open_extension.md),\nso user-defined indexing must be defined in terms of interfaces. In order to\nsupport\n[definition checking of generic functions](/docs/design/generics/goals.md#checked-generics-will-be-checked-when-defined),\nit must be possible to fully typecheck indexing operations using only the\ninformation exposed by those interfaces. And in order to provide\n[coherence](/docs/design/generics/goals.md#coherence), a given indexing\nexpression must execute the same code regardless of how much type information we\nhave about it, so long as we have enough type information to establish that the\nexpression is valid.\n\nThe primary problem this proposal needs to solve is how to support both\narray-like and slice-like indexing semantics while satisfying those\nrequirements.\n\n## Proposal\n\nCarbon will support indexing using the conventional `a[i]` subscript syntax.\nWhen `a` is an l-value, the result of subscripting will always be an l-value,\nbut when `a` is an r-value, the result can be an l-value or an r-value,\ndepending on which interface the type implements:\n\n-   If subscripting an r-value produces an r-value result, as with an array, the\n    type should implement `IndexWith`.\n-   If subscripting an r-value produces an l-value result, as with a slice, the\n    type should implement `IndirectIndexWith`.\n\n`IndirectIndexWith` is a subtype of `IndexWith`, and subscript expressions are\nrewritten to method calls on `IndirectIndexWith` if the type is known to\nimplement that interface, or to method calls on `IndexWith` otherwise.\n\nA type can implement at most one of these two interfaces. `IndirectIndexWith`\nprovides a final blanket `impl` of `IndexWith`, which ensures coherence.\n\nOne implication of this design is that the requirement of coherence must apply\nto value categories as well as types (and for those purposes, \"l-value\" is a\nsubcategory of \"r-value\"). This implies that for any valid expression containing\nan r-value sub-expression, replacing that sub-expression with an l-value\nexpression cannot change the validity or semantics of the outer expression, so\nlong as the r-value expression has the same type and evaluates to the same\nvalue. This, in turn, ensures that once we know a value implements `IndexWith`,\nadditionally learning that it implements `IndirectIndexWith` can't invalidate\ncode that previously typechecked, or change its semantics.\n\n## Details\n\nA subscript expression has the form \"_lhs_ `[` _index_ `]`\". As in C++, this\nsyntax has the same precedence as `.`, `->`, and function calls, and associates\nleft-to-right with all of them.\n\nIts semantics are defined in terms of the following interfaces:\n\n```\ninterface IndexWith(SubscriptType:! Type) {\n  let ElementType:! Type;\n  fn At[me: Self](subscript: SubscriptType) -> ElementType;\n  fn Addr[addr me: Self*](subscript: SubscriptType) -> ElementType*;\n}\n\ninterface IndirectIndexWith(SubscriptType:! Type) {\n  impl as IndexWith(SubscriptType);\n  fn Addr[me: Self](subscript: SubscriptType) -> ElementType*;\n}\n```\n\nA subscript expression where _lhs_ has type `T` and _index_ has type `I` is\nrewritten based on the value category of _lhs_ and whether `T` is known to\nimplement `IndirectIndexWith(I)`:\n\n-   If `T` implements `IndirectIndexWith(I)`, the expression is rewritten to\n    \"`*((` _lhs_ `).(IndirectIndexWith(I).Addr)(` _index_ `))`\".\n-   Otherwise, if _lhs_ is an l-value, the expression is rewritten to \"`*((`\n    _lhs_ `).(IndexWith(I).Addr)(` _index_ `))`\".\n-   Otherwise, the expression is rewritten to \"`(` _lhs_ `).(IndexWith(I).At)(`\n    _index_ `)`\".\n\nOn their own, these rules would oblige `IndirectIndexWith` types to define three\nmethods to support a single syntax. Worse, they would permit those types to\ndefine those methods in inconsistent ways, which would violate coherence. To\navoid those problems, `IndirectIndexWith` provides a blanket `final impl` for\n`IndexWith`:\n\n```\nfinal external impl forall\n    [SubscriptType:! Type, T:! IndirectIndexWith(SubscriptType)]\n    T as IndexWith(SubscriptType) {\n  let ElementType:! Type = T.(IndirectIndexWith(SubscriptType)).ElementType;\n  fn At[me: Self](subscript: SubscriptType) -> ElementType {\n    return *(me.(IndirectIndexWith(SubscriptType).Addr)(index));\n  }\n  fn Addr[addr me: Self*](subscript: SubscriptType) -> ElementType* {\n    return me->(IndirectIndexWith(SubscriptType).Addr)(index);\n  }\n}\n```\n\nThus, a type that implements `IndirectIndexWith` need not, and cannot, provide\nits own definitions of `IndexWith.At` and `IndexWith.Addr`.\n\n### Examples\n\nAn array type could implement subscripting like so:\n\n```\nclass Array(template T:! Type) {\n  external impl as IndexWith(like i64) {\n    let ElementType:! Type = T;\n    fn At[me: Self](subscript: i64) -> T;\n    fn Addr[addr me: Self*](subscript: i64) -> T*;\n  }\n}\n```\n\nAnd a slice type could look like this:\n\n```\nclass Slice(T:! Type) {\n  external impl as IndirectIndexWith(like i64) {\n    let ElementType:! Type = T;\n    fn Addr[me: Self](subscript: i64) -> T*;\n  }\n}\n```\n\nWe can even approximate support for indexing on tuple types. We don't have\nenough of a design for metaprogramming or variadics to specify it generically,\nbut we can illustrate how it would look for a particular tuple type, such as\n`(i8, f64)`:\n\n```\nexternal impl (i8, f64) as IndexWith(typeof(0)) {\n  let ElementType:! Type = i8;\n  fn At[me: Self](0) -> i8;\n  fn Addr[addr me: Self*](0) -> i8*;\n}\n\nexternal impl (i8, f64) as IndexWith(typeof(1)) {\n  let ElementType:! Type = f64;\n  fn At[me: Self](1) -> f64;\n  fn Addr[addr me: Self*](1) -> f64*;\n}\n```\n\nHowever, this approach presupposes that every integer literal has a distinct\ntype, which is not yet settled. It also only supports indexing with integer\nliterals, not with constant values of ordinary integer types. This is somewhat\ncontrary to Carbon's metaprogramming philosophy: Carbon treats types as values\nin order to make metaprogramming more like ordinary programming, but here we're\ndoing the reverse, treating values as types. Consequently, the eventual design\nfor tuple-style indexing may look very different.\n\n## Rationale based on Carbon's goals\n\nIndexing is a fundamental operation in procedural programming, and is especially\ncommon in performance-critical code, so supporting it with a concise, familiar\nsyntax helps us make\n[code easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\nand support\n[performance-critical software](/docs/project/goals.md#performance-critical-software).\nUsing the same syntax as C++, even for slice-like types, supports\n[interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\n\n## Alternatives considered\n\n### Different subscripting syntaxes\n\nThe reason that slices have different semantics from arrays is that a slice\nrepresents an indirection, like a pointer. Indexing behaves the same for slice\nl-values and r-values for the same reason that dereferencing behaves the same\nfor pointer l-values and r-values. Thus, our attempts to make a single\nsubscripting syntax work for both arrays and slices are arguably analogous to\ntrying to make the same method-call syntax work for both pointers and objects.\nOr, to put it another way, the difficulty with slices is that they behave like\n_references_.\n\nFrom that point of view, it would be more consistent to have different\nsubscripting syntaxes for the two cases. The most naive version of that would be\nto say that only array-like types support subscripting, and slice-like types\nshould instead support dereferencing, so indexing into a slice would look like\n`(*s)[i]`. However, that would be syntactically onerous, and it's not clear how\nto define the type of `*s` in a way that doesn't beg the question.\n\nInstead, we could define a distinct syntax for slice subscripting, such as\n`s*[i]`, and define separate interfaces for the two subscript syntax. The two\ninterfaces would be very similar to `IndexWith` and `IndirectIndexWith`, but\nneither would extend the other, and the rewrite from subscript syntax to method\ncalls would not depend on type information (although it would depend on value\ncategory). However, any such syntax would be quite novel and unfamiliar, and\nthere seem to be few good choices for how to spell it. `s*[i]` is almost the\nonly syntax that seems both viable and somewhat mnemonic, but it would add\nfurther complexity to the already-fraught parsing of `*` (for humans as well as\ntools).\n\n### Multiple indices\n\nThis proposal does not support multiple comma-separated indices (such as\n`a[i, j]`), which is desirable for types like multidimensional arrays. We do\nsupport syntax like `a[(i, j)]`, which is a single index whose type is a tuple,\nbut the extra parens are syntactically noisy. We could add those parens\nimplicitly, but that would effectively move the syntactic noise to the\nimplementation, even for the single-index case (for example\n`impl Foo as IndexWith((i64,))`). It should be much cleaner to make the\ninterfaces and their methods variadic, once we have a design for variadics.\n\n### Read-only subscripting\n\nThis proposal does not provide an obvious path for supporting types like C++'s\n`std::string_view` or `std::span<const T>`, whose subscripting operations expose\nread-only access to their contents. It is tempting to try to extend this\nproposal to support those use cases, both because of their inherent importance\nand because it already has to deal with read-only versus read-write access in\norder to support array r-values.\n\nHowever, there's a fundamental difference between the true immutability of\nsomething like an array r-value, and the contextual lack of mutable _access_\nprovided by something like `string_view`. While value categories can express the\nformer, they are not well-suited to expressing the latter. To address these use\ncases, Carbon will probably need something like C++'s `const` type system, but\nthat should be largely orthogonal to this proposal.\n\n### Rvalue-only subscripting\n\nThis proposal does not support subscripting operations that can't produce\nl-values. In particular, this means it does not support using subscript syntax\nto form slices, as in Python's `a[i:j]` or Swift's `a[i...j]`. To support this,\nwe would need a separate pair of interfaces that return by value:\n\n```\ninterface RValueIndexWith(SubscriptType:! Type) {\n  let ElementType:! Type;\n  fn Addr[addr me: Self*](subscript: SubscriptType) -> ElementType;\n}\n\ninterface RValueIndirectIndexWith(SubscriptType:! Type) {\n  extends RValueIndexWith(SubscriptType);\n  let ElementType:! Type;\n  fn Addr[me: Self](subscript: SubscriptType) -> ElementType;\n}\n\nfinal external impl [SubscriptType:! Type,\n                     T:! RValueIndirectIndexWith(SubscriptType)]\n    T as IndexWith(SubscriptType) {\n  let ElementType:! Type =\n      T.(RValueIndirectIndexWith(SubscriptType)).ElementType;\n  fn Addr[addr me: Self*](subscript: SubscriptType) -> ElementType {\n    return me->Addr(subscript);\n  }\n}\n```\n\nNote that we still need a pair of interfaces, and a blanket final `impl` to\nenforce consistency, because arrays and slices have different semantics in this\ncontext as well: taking a slice of an r-value array is invalid, because taking a\nslice is equivalent to (and presumably implemented in terms of) taking an\naddress. On the other hand, taking a slice of an r-value slice is valid and\nshould be supported.\n\nWe would likewise need to extend the rewrite rules for subscript syntax to\ndetect and use implementations of these interfaces. This should not lead to a\ncombinatorial explosion of cases, though; if `T` implements both `IndexWith(I)`\nand `RValueIndexWith(I)`, the program should be ill-formed due to ambiguity.\n\nHowever, it's not clear if this would provide enough benefit to justify the\nadded complexity.\n\n### Map-like subscripting\n\nThis proposal does not support subscripting operations that insert new elements\ninto a collection, as in C++'s `std::map` and `std::unordered_map`, because it\nrequires subscriptable types to support subscripting of r-values, which are\nimmutable. We could support this with an additional interface for types that are\nsubscriptable only as l-values, and a corresponding extension to the rewrite\nrules.\n\nHowever, it's debatable whether such insertion behavior is desirable; it has not\nbeen a clear-cut success in C++. Code like `x = m[i];` looks like it reads from\n`m`, and the fact that it can write to `m` is surprising, and easy for even\nexperienced programmers to overlook. Even for wary readers, it doesn't convey\nthe author's intent, because it's not clear whether the author assumed `i` is\npresent, or is relying on the implicit insertion. Furthermore, the implicit\ninsertion means that `x = m[i];` won't compile when `m` is const. On the other\nhand, while it's relatively unsurprising that `m[i] = x;` might insert, that\ninsertion is also potentially inefficient, since it must default-construct a new\nvalue before assigning `x` to it.\n\nWe could fix most of these problems by giving special treatment to syntax of the\nform `m[i] = x;`, and defining separate methods for it:\n\n```\ninterface IndexWith(SubscriptType:! Type) {\n  let ElementType:! Type;\n  fn At[me: Self](subscript: SubscriptType) -> ElementType;\n  fn Addr[addr me: Self*](subscript: SubscriptType) -> ElementType*;\n  fn Assign[addr me: Self*](subscript: SubscriptType, element: ElementType) {\n    (*me->Addr(index)) = element;\n  }\n}\n\ninterface IndirectIndexWith(SubscriptType:! Type) {\n  extends IndexWith(SubscriptType);\n  let ElementType:! Type;\n  fn Addr[me: Self](subscript: SubscriptType) -> ElementType*;\n  fn Assign[me: Self](subscript: SubscriptType, element: ElementType) {\n    me->Addr(subscript) = element;\n  }\n}\n\nfinal external impl [SubscriptType:! Type, T:! IndirectIndexWith(SubscriptType)]\n    T as IndexWith(SubscriptType) {\n  ...\n  fn Assign[addr me: Self*](subscript: SubscriptType, element: ElementType) {\n    me->(IndirectIndexWith.AssignAsRValue)(subscript, element);\n  }\n}\n```\n\nWith this approach, expressions of the form `m[i] = x` would be rewritten to\ncall the appropriate `Assign` method, while all other subscript expressions are\nrewritten as in the primary proposal. However, this does add some complexity to\nboth the interfaces and the rewrite rules (for example, we presumably want\n`(m[i]) = x` to be treated the same as `m[i] = x`), so I'm leaving this as a\npotential future extension.\n\n#### Usage-based rewriting\n\nAs an alternative way of getting `std::map`-like behavior, we could rewrite\nsubscript expressions to use `At` instead of `Addr` when the usage context only\nneeds an r-value, even if the operand is an l-value, in much the same way that\nRust rewrites subscript expressions depending on whether the usage expects the\nresult to be mutable. This would enable type authors to make `m[i] = x;`\npotentially-inserting while ensuring that `x = m[i];` is not, by making `Addr`\nbut not `At` potentially-inserting.\n\nHowever, this would mean that `m[i].Method()` is potentially inserting if\n`Method` takes `me` by pointer, and would have the same performance drawback as\nin C++. Furthermore, it would violate the principle (which we have discussed but\nnot yet adopted) that type information should flow from subexpressions to the\nparent expression, but never the reverse.\n\nA variant of this approach would be to allow the compiler to choose between `At`\nand `Addr` when the operand is an l-value but the usage context only needs an\nr-value. This might enable the compiler to make the generated code more\nefficient and/or safer, and might create pressure for libraries to ensure `At`\nand `Addr` are consistent with each other.\n\nHowever, if the compiler predictably chooses `At` under those conditions, that\ncould create a temptation for library authors to leverage that implementation\ndetail to try to implement a `std::map`-like API, by having `Addr` implicitly\ninsert while `At` does not. That would have all the same drawbacks as if we\nsupported it intentionally, plus the evolutionary drawbacks of having user code\ndepend on unsupported implementation details.\n"
  },
  {
    "path": "proposals/p2287.md",
    "content": "# Allow unqualified name lookup\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/####)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Classes](#classes)\n    -   [Interfaces](#interfaces)\n    -   [Namespaces](#namespaces)\n-   [Open question](#open-question)\n    -   [Implicit instance binding to `me`](#implicit-instance-binding-to-me)\n    -   [Out-of-line definitions for impls](#out-of-line-definitions-for-impls)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [No unqualified lookup when defining outside a scope](#no-unqualified-lookup-when-defining-outside-a-scope)\n\n<!-- tocstop -->\n\n## Abstract\n\nAllow unqualified name lookup in multiple situations:\n\n-   For classes and interfaces, whether inside the class scope or within an\n    out-of-line function definition.\n-   For namespaces, when the namespace is used in a declaration.\n\n## Problem\n\n[Member access](/docs/design/expressions/member_access.md) defines certain\nmember access behaviors. However, it doesn't cover what happens if an\nunqualified name lookup occurs within a class, particularly for an out-of-line\nmember function definition, or other situations.\n\n## Background\n\nThe [member access design](/docs/design/expressions/member_access.md) and\n[information accumulation principle](/docs/project/principles/information_accumulation.md)\naffect this.\n\nThis will also work similarly to\n[unqualified lookup within C++](https://en.cppreference.com/w/cpp/language/unqualified_lookup).\n\n## Proposal\n\nAllow unqualified name lookup which will use the appropriate scope.\n\nImplicit instance binding to `me` is not proposed; it is left as an\n[open question](#implicit-instance-binding-to-me).\n\n### Classes\n\nThis proposal updates [the class design](/docs/design/classes.md) to address\nclasses.\n\n### Interfaces\n\n```carbon\ninterface Vector {\n  fn Scale[me: Self](v: f64) -> Self;\n  // Default definition of `Invert` calls `Scale`.\n  default fn Invert[me: Self]() -> Self;\n}\n\n// `Self` is valid here because it's doing unqualified name lookup into\n// `Vector`.\ndefault fn Vector.Invert[me: Self]() -> Self {\n  // `Scale` is valid here because it does unqualified name lookup into\n  // `Vector`, then an instance binding with `me`.\n  return me.(Scale)(-1.0);\n}\n```\n\n### Namespaces\n\nMore generally, this should also be true of other scopes used in declarations.\nIn particular, namespaces should also follow the same rule. However, since\n[name lookup](/docs/design/name_lookup.md) has not been fleshed out, this won't\nmake much of an update to it.\n\nAn example for namespaces would be:\n\n```carbon\nnamespace Foo;\nvar Foo.a: i32 = 0;\n\nclass Foo.B {}\n\n// `B` and `a` are valid here because unqualified name lookup occurs within\n// `Foo`.\nfn Foo.C(B b) -> i32 {\n  return a;\n}\n```\n\n## Open question\n\n### Implicit instance binding to `me`\n\nIn C++, unqualified name lookup can implicitly do instance binding to `this`. In\nother words, `this->Member()` and `Member()` behave similarly inside a method\ndefinition.\n\nIn Carbon, the current design hasn't fleshed out whether `me` would behave\nsimilarly. Most design documentation assumes it will not, but it hasn't been\ndirectly considered in a proposal, and\n[implicit scoped function parameters](https://github.com/carbon-language/carbon-lang/issues/1974)\nmight offer a way to make it work in a language-consistent manner.\n\nThis proposal takes no stance on unqualified name lookup resolving `me`: it is\nnot intended to change behavior from previous proposals.\n\n### Out-of-line definitions for impls\n\nIssue [#2377](https://github.com/carbon-language/carbon-lang/issues/2377) asks\nhow unqualified lookup should work for `impl`. The\n[generics design](/docs/design/generics/details.md) also doesn't appear to give\nsyntax for out-of-line definitions of other impls.\n\n## Rationale\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Performing unqualified name lookup for class members should be fairly\n        unsurprising to readers, and should allow for more concise code when\n        working within a namespace.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   This behavior will be similar to how C++ works.\n\n## Alternatives considered\n\n### No unqualified lookup when defining outside a scope\n\nWe could decide not to support unqualified lookup when defining something that\nis presented within the top-level scope of the file.\n\nNote this has subtle implications. If `Foo.C` in the namespace example is\nconsidered to be outside the `Foo` scope for this purpose, it means the function\nwould need to look like:\n\n```\nfn Foo.C(Foo.B b) -> i32 {\n   return Foo.a;\n}\n```\n\nIt could also mean that, on a class, an inline declaration\n`fn Foo() -> ClassMember` is valid, while an out-of-line definition\n`fn Class.Foo() -> ClassMember` is not, requiring `Class.ClassMember`.\n\nAdvantages:\n\n-   Explicit in access.\n    -   For example, name lookup results could be mildly confusing if both\n        `package.a` and `package.Foo.a` are defined but `package.Foo.a` is\n        hidden in code while `package.a` is easy to find. It's likely that\n        `package.Foo.a` would be considered unambiguous for unqualified name\n        lookup.\n\nDisadvantages:\n\n-   Very verbose, and could prove un-ergonomic for developers.\n"
  },
  {
    "path": "proposals/p2295.md",
    "content": "# Begin publishing CoC and moderation transparency reports\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2295)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Automated dashboards](#automated-dashboards)\n    -   [Different cadence](#different-cadence)\n    -   [Different publishing options](#different-publishing-options)\n\n<!-- tocstop -->\n\n## Abstract\n\nProposes a documented cadence, publishing target, and template for Code of\nConduct and moderation transparency reports.\n\n## Problem\n\nThe Carbon community wants to be an example in terms of diversity, equity and\ninclusion. One of the best practices that supports such ambition is publishing\ntransparency reports about misconduct within the community and actions taken in\nresponse. There is no previous experience with reporting back to the community\nabout this so far.\n\n## Background\n\nTransparency reports are not very common practice, but already around. So there\nare some ideas to grab from other communities, with their permission.\n\n## Proposal\n\nWe will benchmark relevant transparency reports to find inspiration to create\nour own. We will look at their scope, their format, their regularity and\npossibly community feedback we have access to.\n\nWe will create a template for Carbon's transparency reports and maintain that as\npart of the project. Our Code of Conduct team will then create and publish\nregular reports in the GitHub discussion forum based on that template.\n\n## Details\n\nSome examples of transparency reports in which conduct incidents had been\nreported:\n\nConferences:\n\n-   PyCon US 2022:\n    https://pycon.blogspot.com/2022/06/pycon-us-2022-transparency-report.html\n-   CppCon 2021: https://cppcon.org/cppcon-2021-transparency-report/\n-   PyConDE 2019:\n    https://2019.pycon.de/blog/code-of-conduct-transparency-report/\n\nOther:\n\n-   LLVM CoC July 15, 2022: https://llvm.org/coc-reports/2022-07-15-report.html\n-   Linux Foundation 2021:\n    https://www.linuxfoundation.org/blog/blog/linux-foundation-events-code-of-conduct-transparency-report-2021-event-summary\n\nWe propose a [template](/docs/project/transparency_reports.md#template) for our\nown CoC transparency report, which has been greatly inspired by transparency\nreports issued by the Python community worldwide. Thank you, Pythonistas!\n\nWe also document there the\n[cadence and target of publishing](/docs/project/transparency_reports.md#cadence-and-publishing).\n\n## Rationale\n\nTransparent moderation and handling of conduct issues is essential to sustaining\na healthy [community and culture](/docs/project/goals.md#community-and-culture),\none of Carbon's primary goals. We need to clearly and transparently surface the\nconduct of our community and how we respond to it.\n\n## Alternatives considered\n\n### Automated dashboards\n\nAn automated dashboard (for example “X days since AutoMod detected a “guys” in\nour Discord”, “Y incidents of harmful language”) would be great, but we are\nstill figuring out the basics and principles together before we can automate\nmore.\n\nSuch a dashboard could be an attractive alternative for the future.\n\n### Different cadence\n\nPublishing quarterly may result in some quarters with very little or even\nnothing to publish. That seems fine. We considered a slower cadence of annually,\nbut we worry that would be too slow for folks in the community to hold the\nconduct team and leadership accountable as things start to be forgotten.\n\nWe also thought about how to respond rapidly when needed but would prefer to\npublish out-of-band when needed rather than run an even more rapid cadence.\n\n### Different publishing options\n\nWe considered different places to publish the individual transparency reports.\n\nThey don't seem to belong as part of our version controlled repository as they\naren't something that should be persistent -- they reflect a report at a moment\nin time. And while we hope to never need it, we should retain the ability to\neasily redact information or make permanent edits to them if necessary. GitHub\ndiscussions seem like a good fit overall compared to alternatives like the main\nrepository, the wiki, etc.\n\nUsing GitHub discussions also allows comments and discussion where folks could\nfor example ask questions or get more information about how and why we are\ntaking our moderation approaches. While there is some risk of these discussions\nbeing unproductive, we hope to be able to moderate them as well and still\nprovide a place where productive and on-topic discussion can still take place.\n"
  },
  {
    "path": "proposals/p2347.md",
    "content": "# What can be done with an incomplete interface\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2347)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Allow declaration and definition in different files](#allow-declaration-and-definition-in-different-files)\n    -   [No specific restriction on `where` clauses on incomplete constraints](#no-specific-restriction-on-where-clauses-on-incomplete-constraints)\n    -   [Don't allow combinations of incomplete constraints as in `C & D`](#dont-allow-combinations-of-incomplete-constraints-as-in-c--d)\n\n<!-- tocstop -->\n\n## Abstract\n\nClarify what can and cannot be done with a incomplete interface or named\nconstraint.\n\n## Problem\n\nFor purposes of this proposal, the term _constraints_ refers to interfaces and\nnamed constraints. Interfaces do not require any different treatment from named\nconstraints, and treating them the same is good for simplicity and uniformity.\n\nWe want to support forward declaring constraints so that they may be used before\nthey are allowed to be defined, due to recursion or a reference cycle. Some uses\nrequire the definition of the constraint to be visible to be checked, however.\nIn some cases, those checks may be delayed at the cost of complexity in the\nimplementation of the compiler. This proposal aims to specify what uses are\nallowed, particularly those cases that were not covered by\n[the previous proposal on forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084).\n\n## Background\n\nProposal\n[#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084)\noriginally laid out the rules for incomplete constraints. Since then, the\n[discussion on 2022-10-12](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#heading=h.q7afaawbc5k)\nconsidered how we needed to update and fill in those rules, as part of an effort\nto implement those rules in the Carbon Explorer.\n\n## Proposal\n\nThe new rule details have been added by this proposal PR to the\n[Forward declarations and cyclic references: declaring interfaces and named constraints](/docs/design/generics/details.md#declaring-interfaces-and-named-constraints)\nsection of\n[Generics: details design document](/docs/design/generics/details.md).\n\n## Rationale\n\nThis proposal is balancing the expressivity needed to make code easier to write\nwith implementation simplicity, both concerns of Carbon's\n[\"code that is easy to read, understand, and write\"](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\ngoal.\n\n## Alternatives considered\n\n### Allow declaration and definition in different files\n\nIn particular, we considered allowing the declaration of an interface or named\nconstraint in an API file and the definition in the impl file of the same\nlibrary. We considered some use cases that might benefit from this in\n[#931](p0931.md#private-interfaces-in-public-api-files) and\n[#971](https://github.com/carbon-language/carbon-lang/issues/971). In\n[#generics-and-templates on 2022-10-24](https://discord.com/channels/655572317891461132/941071822756143115/1034207895392358431),\nwe decided those use cases would be okay including the definition of the private\ninterface in the API file. So to support checking for invalid uses of an\nincomplete interfaces with information local to that file, we reaffirmed the\ndecision in #971 and implemented in proposal\n[#1084](https://github.com/carbon-language/carbon-lang/pull/1084) to require the\ndefinition to be in the same file as the declaration.\n\n### No specific restriction on `where` clauses on incomplete constraints\n\nWe considered not having a specific rule preventing any `where` clause on an\nincomplete constraint. The idea is that the problematic cases, such as those\nthat access members of the constraint like `where .X = T`, are already\nforbidden. By removing this rule, we would allow constructions like\n`C where Vector(.Self) is Hashable` for incomplete `C`. We decided to wait until\nwe had a motivating use case to allow this, and start with the more restrictive\nrule.\n\n### Don't allow combinations of incomplete constraints as in `C & D`\n\nWe considered forbidding the combination of incomplete constraints with the `&`\noperator, because otherwise we would not be able to diagnose conflicts between\nthe two constraints. For example,\n\n```carbon\nconstraint C;\nconstraint D;\n\n// Can't tell if there is a conflict between `C` and `D`.\nfn F[T:! C & D](x: T);\n\n// These definitions of `C` and `D` conflict.\nconstraint C {\n  extends I where .X = i32;\n}\nconstraint D {\n  extends I where .X = bool;\n}\n```\n\nSince our existing examples of using forward declarations to define a graph with\ncyclic references between the edge and node interfaces needed this feature, we\ndecided to support it. This motivated the requirement that\n[the definition be in the same file as the declaration](#allow-declaration-and-definition-in-different-files),\nso the error could be detected once the compiler reached the definitions.\n"
  },
  {
    "path": "proposals/p2360.md",
    "content": "# Types are values of type `type`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2360)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n    -   [Tuples behave inconsistently](#tuples-behave-inconsistently)\n    -   [Qualified access to constraint members is inconsistent](#qualified-access-to-constraint-members-is-inconsistent)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Terminology](#terminology)\n    -   [`type` and `Core.Type`](#type-and-coretype)\n    -   [Compound member access](#compound-member-access)\n        -   [Instance binding](#instance-binding)\n        -   [Impl lookup](#impl-lookup)\n        -   [Examples](#examples)\n    -   [Tuple and struct literals](#tuple-and-struct-literals)\n    -   [Name lookup into values with constrained types](#name-lookup-into-values-with-constrained-types)\n    -   [Types in diagnostics](#types-in-diagnostics)\n-   [Rationale](#rationale)\n    -   [Teachability](#teachability)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Alternative member access rules](#alternative-member-access-rules)\n    -   [Alternative terminology](#alternative-terminology)\n    -   [`Core.Type` is an empty named constraint](#coretype-is-an-empty-named-constraint)\n    -   [Write tuple types differently than tuples](#write-tuple-types-differently-than-tuples)\n\n<!-- tocstop -->\n\n## Abstract\n\nDefine a \"type\" to be a value of type `type`. Contexts expecting a type perform\nan implicit conversion to `type`. Values like `()`, `(i32, i32)`, and `{}` are\nno longer types, but instead implicitly convert to `type`. Values of interface\nor constraint type (now called \"facets\") are similarly not formally types but\nimplicitly convert to `type`.\n\nThe practical impact to the language semantics is relatively small. This\nproposal primarily establishes clearer, more principled terminology and design\nconcepts with a few narrow improvements to the design's consistency.\n\n## Problem\n\n### Tuples behave inconsistently\n\nCurrently, the type of `(i32, i32)` is `(Type, Type)`, and similarly the type of\n`(Type, Type)` is also `(Type, Type)`. This leads to an inconsistency: for most\nvalues, asking for the type, then the type-of-type, and so on, quickly leads to\n`Type`, whose type is `Type`. But for a few values, notably tuples and empty\nstructs, we instead bottom out at a different value.\n\nThis leads to implementation complexity and a lack of clarity around what is or\nis not a type. It is easy to find examples where explorer misbehaves or crashes\ndue to getting tuple values and types mixed up.\n\nMoreover, this inconsistency is limited to a few built-in types. There is no way\nto design a class type so it behaves like a tuple type.\n\n### Qualified access to constraint members is inconsistent\n\nGiven the expression `x.(Interface.Function)`, where the function is an instance\nmethod, the behavior depends on whether `x` is a type.\n\n-   If `x` is not a type, but a value of type `T`, this requires\n    `T is Interface` and looks for `Function` in the corresponding `impl`.\n    Instance binding is performed.\n-   If `x` is a type, this requires `x` to have symbolic value phase and\n    requires that `x is Interface`. The result is an unbound member name.\n\nThis dual meaning has some problematic consequences:\n\n-   Even if `Interface.Function` is non-dependent, if `x` depends on a template\n    parameter then we must treat the compound member access as being dependent.\n    Qualification cannot be used to avoid dependence in templates.\n-   Worse, if `x` is a template parameter, the interpretation will differ\n    between instantiations, meaning that a template and a checked generic will\n    have a discontinuity in behavior when `x` happens to be a type.\n-   While it is possible to `impl Type as ...`, this rule means it is not\n    possible to directly invoke methods that have been implemented this way. For\n    example, given an `impl Type as DebugPrintable`,\n    `i32.(DebugPrintable.Print)()` will look for `i32 as DebugPrintable` not\n    `Type as DebugPrintable`.\n\n## Background\n\n-   [#989: Member access expressions](/proposals/p0989.md) introduced the\n    current compound member access rules.\n-   [Issue #495](https://github.com/carbon-language/carbon-lang/issues/495)\n    suggested adding an implicit conversion from tuples of types to type `Type`.\n-   [Issue #508](https://github.com/carbon-language/carbon-lang/issues/508)\n    raised the question of whether we want tuples like `((), (), ())` to be\n    self-typed.\n-   [Issue #2113](https://github.com/carbon-language/carbon-lang/issues/2113)\n    gave us spelling and behavior guidelines for predefined names like `type`.\n\n## Proposal\n\nInstead of treating type-like values as being types regardless of the type of\nthose values, we define a _type_ as being a value of type `type`.\n\nThis has the following consequences:\n\n-   `()` is a value of type `() as type`, not a value of type `()` (because the\n    latter is not a type).\n    -   `() as type` is a value of type `type`.\n    -   Similarly, `(i32, i32)` is of type `(type, type) as type`, which is of\n        type `type`.\n    -   Similarly, `{}` is of type `{} as type`, which is of type `type`.\n    -   More generally, _the type of any type is `type`_.\n-   Given `T:! Hashable`, `T` is formally not a type, because it is not of type\n    `type`. Indeed, member lookup into `type`, and hence into types, finds\n    nothing, but member lookup into `T` finds members of `Hashable`.\n-   Contexts in which a type is required, such as on the right hand side of a\n    `:` or `:!` binding or the return type of a function, perform an implicit\n    conversion to type `type`.\n    -   This means that a user-defined type can implement `ImplicitAs(type)`,\n        annotated in whatever way we eventually decide to annotate functions\n        that are usable at compile time, and values of that type will be usable\n        as types, in the same way that `()` and `{}` are.\n-   There are no singleton type-of-types. It's still possible to have, for\n    example, the type of `i32` be a type whose only value is `i32`. The value\n    `i32` would then not formally be a type, as its type would not be `type`,\n    but it could still implicitly convert to `type`, as `()` does, if we so\n    desire.\n    -   This extends to other cases: we could say that for integer literals,\n        which we have recently been describing as having type `IntLiteral(n)`,\n        there is an `impl IntLiteral(n) as ImplicitAs(type)` which converts a\n        value of type `IntLiteral(n)` to the `type` value `IntLiteral(n)`. This\n        would then permit `let v: 0 = 0;`.\n    -   Such changes to `i32` or integer literals are not part of this proposal.\n\n## Details\n\n### Terminology\n\nThe changes to the language rules in this proposal are fairly small, but there\nis a significant change in how we describe those rules. We now use the following\nterminology:\n\n-   A _type_ is a value of type `type`.\n-   A _facet type_ is a type whose values are some subset of the values of\n    `type`, determined by a set of constraints.\n\n    -   Interface types and named constraint types are facet types whose\n        constraints are that the interface or named constraint is satisfied by\n        the type.\n    -   The values produced by `&` operations between facet types and by `where`\n        expressions are facet types, whose set of constraints are determined by\n        the `&` or `where` expression.\n    -   `type` is a facet type whose set of constraints is empty.\n\n    We previously referred to a facet type as a type-of-type, but that is no\n    longer accurate, as the type of any type is now by definition `type`.\n\n-   A _facet_ is a value of a facet type. For example, `i32 as Hashable` is a\n    facet, and `Hashable` is a facet type. Note that all types are facets.\n    -   A facet value can be thought of as a tuple of a possibly-symbolic\n        identity for a type, plus any witnesses needed to demonstrate that the\n        type satisfies the constraints of the facet type. A type is then a facet\n        value that has no witnesses.\n-   We use the term _generic type_ to refer to a type or facet introduced by a\n    `:!` binding, such as in a generic parameter or associated constant.\n    -   This gives rise to terms such as _generic type parameter_ and\n        _associated generic type_.\n    -   It is worth noting that a generic type is not necessarily a type. It may\n        be a facet, and its type may be a facet type other than `type`.\n\n### `type` and `Core.Type`\n\nThis proposal introduces the name `type` as a keyword -- a type literal -- that\nnames the facet type with an empty set of constraints. This keyword replaces the\nprovisional name `Type` for this functionality.\n\nIn [issue #2113](https://github.com/carbon-language/carbon-lang/issues/2113), it\nwas decided that such functionality may be an alias for a name in the prelude,\nsuch as `Core.Type`. This proposal does not introduce a corresponding prelude\nname. The facet type `type` is primitive and provided by the compiler, and not\nan alias.\n\n[As noted in the generics design](/docs/design/generics/details.md#named-constraints),\na declaration such as `constraint MyVersionOfType {}` would introduce a facet\ntype that is equivalent to `type`. This proposal does not change this decision.\nBecause such a named constraint `MyVersionOfType` is equivalent to `type`, that\nis, because they are the same facet type, a value `T:! MyVersionOfType` is a\ntype under this proposal. There is an open\n[issue for leads](https://github.com/carbon-language/carbon-lang/issues/2409) on\nwhether this is the right behavior or if we'd prefer a different rule.\n\n### Compound member access\n\n#### Instance binding\n\nFor the syntax `x.y`, if `x` is an entity that has member names, such as a\nnamespace or a type, then `y` is looked up within `x`, and instance binding is\nnot performed. Otherwise, `y` is looked up within the type of `x` and instance\nbinding is performed if an instance member is found.\n\nThe syntax `x.(Y)`, where `Y` names an instance member, always performs instance\nbinding. Therefore, for a suitable `DebugPrintable`:\n\n-   `1.(DebugPrintable.Print)()` still prints `1`, as before.\n-   `i32.(DebugPrintable.Print)()` now prints `i32`, rather than forming a\n    member name.\n-   `1.(i32.(DebugPrintable.Print))()` is now an error, rather than printing\n    `1`.\n\nIn order to get the old effect of `x.(MyType.(MyInterface.InstanceMember))()`,\none can now write `x.((MyType as MyInterface).InstanceMember)()`. This behaves\nthe same as the member access in:\n\n```\nfn F(MyType:! MyInterface, x: MyType) -> auto {\n  return x.(MyType.InstanceMember)();\n}\n```\n\n... because it is the same thing. `MyType as InstanceMember` is a facet, which\nroughly corresponds to a fully-instanstiated `impl`, and lookup into a facet\nfinds members of that corresponding `impl`. And if `MyType` is declared as\n`MyType:! MyInterface` instead of as `MyType:! type`, then `MyType` and\n`MyType as MyInterface` are equivalent.\n\n#### Impl lookup\n\nPrior to this proposal, when a member access names a member of interface `I`,\nthe rules for `impl` lookup also depend on whether the left hand operand is a\ntype:\n\n-   If the left hand operand is a type-of-type (now, facet type), `impl` lookup\n    is not performed.\n-   If the left hand operand evaluates to a type `T`, then `impl` lookup is\n    performed for `T as I`.\n-   Otherwise, the first operand is an expression of some type `T`, and `impl`\n    lookup is performed for `T as I`.\n\nDue to the non-uniform treatment of types and non-types, this rule is also\nchanged to the following:\n\n-   For a simple member access `a.b` where `b` names a member of an interface\n    `I`:\n    -   If the interface member was found by searching a non-facet-type scope\n        `T`, for example a class or an adapter, then `impl` lookup is performed\n        for `T as I`. For example:\n        -   `MyClass.AliasForInterfaceMember` finds the member of the\n            `impl MyClass as I`, not the interface member.\n        -   `my_value.AliasForInterfaceMember`, with `my_value: MyClass`, finds\n            the member of the `impl MyClass as I`, and performs instance binding\n            if the member is an instance member.\n        -   In the case where the member was found in a base class of the class\n            that was searched, `T` is the derived class that was searched, not\n            the base class in which the name was declared.\n    -   Otherwise, `impl` lookup is not performed:\n        -   `MyInterface.AliasForInterfaceMember` finds the member in the\n            interface `MyInterface` and does not perform `impl` lookup.\n-   For a compound member access `a.(b)` where `b` names a member of an\n    interface `I`, `impl` lookup is performed for `T as I`, where:\n    -   If `b` is an instance member, `T` is the type of `a`.\n        -   `my_value.(Interface.InstanceInterfaceMember)()`, where `my_value`\n            is of type `MyClass`, uses `MyClass as Interface`.\n        -   `MyClass.(Interface.InstanceInterfaceMember)()` uses\n            `type as Interface`.\n    -   Otherwise, `a` is implicitly converted to `I`, and `T` is the result of\n        symbolically evaluating the converted expression.\n        -   `MyClass.(Interface.NonInstanceInterfaceMember)()` uses\n            `MyClass as Interface`.\n        -   `my_value.(Interface.NonInstanceInterfaceMember)()` is an error\n            unless `my_value` implicitly converts to a type.\n\nThis approach aims to change as little as possible of the existing `impl` lookup\nbehavior while removing inconsistencies and behavioral differences based on\nwhether a value is a type.\n\n#### Examples\n\n```\ninterface Iface {\n  fn Static();\n  fn Method[me: Self]();\n}\n\nimpl type as Iface { ... }\n\nfn F[T:! Iface](x: T) {\n  // ✅ Uses `T as Iface`.\n  x.Static();\n  T.Static();\n  // ❌ Uses `T as Iface`, but method call is missing an instance.\n  T.Method();\n  // ✅ OK, instance is provided. Uses `T as Iface`.\n  x.Method();\n  x.(T.Method)();\n\n  // ❌ Would use `(x as Iface).Static`.\n  // Error because `x` is not a symbolic constant.\n  x.(Iface.Static)();\n  // ✅ Uses `(T as Iface).Static`.\n  T.(Iface.Static)();\n  // ✅ Uses `(type as Iface).Static`.\n  type.(Iface.Static)();\n\n  // ✅ Uses `(T as Iface).Method`, with `me = x`.\n  x.(Iface.Method)();\n  // ✅ Uses `(type as Iface).Method`, with `me = T`.\n  T.(Iface.Method)();\n}\n\nbase class Base {\n  fn Static();\n  fn Method[me: Self]();\n  alias IfaceStatic = Iface.Static;\n  alias IfaceMethod = Iface.Method;\n}\nexternal impl Base as Iface { ... }\n\nfn G(b: Base) {\n  // ✅ OK\n  b.Static();\n  Base.Static();\n  // ❌ Uses `Base as Iface`, but method call is missing an instance.\n  Base.Method();\n  // ✅ OK\n  b.Method();\n  b.(Base.Method)();\n\n  // ✅ OK, same as `(Base as Iface).Static()`.\n  b.IfaceStatic();\n  Base.IfaceStatic();\n  // ❌ Uses `Base as Iface`, but method call is missing an instance.\n  Base.IfaceMethod();\n  // ✅ OK, uses `Base as Iface`.\n  b.IfaceMethod();\n  b.(Base.IfaceMethod)();\n  b.((Base as Iface).Method)();\n  b.(Iface.Method)();\n}\n\nclass Derived extends Base {}\nexternal impl Derived as Iface { ... }\n\nfn H(d: Derived) {\n  // ✅ OK, calls `Base.Static`.\n  d.Static();\n  Derived.Static();\n  // ❌ Uses `Derived as Iface`, but method call is missing an instance.\n  Derived.Method();\n  // ✅ OK, calls `Base.Method`.\n  d.Method();\n  d.(Base.Method)();\n  d.(Derived.Method)();\n\n  // ✅ OK, same as `(Derived as Iface).Static()`.\n  d.IfaceStatic();\n  Derived.IfaceStatic();\n  // ❌ Uses `Derived as Iface`, but method call is missing an instance.\n  Derived.IfaceMethod();\n  // ✅ OK, uses `Derived as Iface`.\n  d.IfaceMethod();\n  d.(Derived.IfaceMethod)();\n  d.((Derived as Iface).Method)();\n  d.(Iface.Method)();\n  // ✅ OK, uses `Base as Iface`.\n  d.(Base.IfaceMethod)();\n  d.((Base as Iface).Method)();\n}\n```\n\n### Tuple and struct literals\n\nA tuple literal such as `(1, 2, 3)` produces a tuple value. Its type cannot be\nwritten directly as a literal: the literal `(i32, i32, i32)` also produces a\ntuple value, not a type value. However, the type of `(1, 2, 3)` is easy to\nexpress: it is the result of implicitly converting `(i32, i32, i32)` to a type,\nso for example `(i32, i32, i32) as type` evaluates to the type of `(1, 2, 3)`.\n\nThere is no conversion from a tuple type to a tuple value, because tuple types\nare values of type `type`, and the type `type` does not implicitly convert to a\ntuple type. For metaprogramming, it is likely that we will benefit from having a\nmechanism to convert a tuple type into a tuple of types, but this is likely to\nbe possible using a variadic:\n\n```\n// Takes a tuple of values. Returns a tuple containing the types of those values.\nfn TupleTypeToTupleOfTypes[Types:! type,...](x: (Types,...)) -> auto {\n  return (Types,...);\n}\n```\n\n### Name lookup into values with constrained types\n\nGiven a generic function with a generic type parameter, uses of that parameter\nwill be implicitly converted to type `type`. For example:\n\n```\nfn F[T:! Printable](x: T) { x.Print(); }\n```\n\n... is equivalent to ...\n\n```\nfn F[T:! Printable](x: T as type) { x.Print(); }\n```\n\nAs a result, we can no longer describe lookup for `x` as looking into the\ntype-of-type, that is, the type of the expression after `x:`, because after\nimplicit conversion, that expression is of type `type`. Instead, lookup will\nlook into the type of `x`, which symbolically evaluates to the value\ncorresponding to `T` in type `type`, and will look at that value to determine\nwhere else to look. Because that value is symbolically the name of a generic\ntype parameter, we will look in the type of `T`, which is `Printable`.\n\n### Types in diagnostics\n\nConcern has been raised that this proposal could lead to `as type` appearing\nfrequently in diagnostics when types are printed. This is not expected to be the\ncase. When a type appears in a diagnostic, it will generally be in one of two\nforms:\n\n-   A reflection of source-level syntax that the programmer wrote.\n-   A string generated by the compiler to describe the type to the programmer.\n\nIn both cases, we expect the type of a variable such as `var v: (i32, i32)` to\nbe displayed as `(i32, i32)`, not as `(i32, i32) as type`, unless either the\ncontext requires the `as type` suffix for disambiguation or the programmer wrote\nit in the source code.\n\nThis is analogous to how integer literals behave: when describing the value `1`\nof type `i32` in a diagnostic, the type is usually treated as assumed context,\nso the diagnostic would say simply `1` rather than `1 as i32`. Similarly, C++\ncompilers typically avoid printing things like `(short)5` when including values\nof type `short`, for which there is no literal syntax, in diagnostics.\n\n## Rationale\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   Making the behavior of tuples and empty structs more like other types is\n        easier for tooling to handle.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   The transition between templates and generics is made smoother by\n        changing compound member access to behave consistently regardless of\n        whether the left-hand operand is a type.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Bottoming out at the same type, `type`, for all types is likely to be\n        easier to understand. However, having `(i32, i32)` not be the type of a\n        pair of integers, but instead be _implicitly convertible to_ the type of\n        a pair of integers, is likely to be harder to understand. It's unclear\n        which of these will be more dominant, but the new behavior is more\n        consistent.\n\n### Teachability\n\nOne of the bigger concerns with this proposal is how teachable it is. The\ndetails of this model are likely to be challenging for new-comers to Carbon,\neven ones with experience in C++.\n\nWhen explaining this model, we suggest focusing on the goal and how it is\nachieved, rather than what happens under the covers. For example, we can say\n\n> You can use `var n: (i32, i32)` to declare that `n` is a pair of `i32`s\n\nwithout mentioning that the actual type of `(i32, i32)` is `(type, type)`, and\nthat an implicit conversion is performed here. This is analogous to how we can\nsay\n\n> You can use `n = (1, 2);` to assign `1` to the first element of `n` and `2` to\n> the second element\n\nwithout mentioning that again an implicit conversion is performed.\n\nIn practice, this is a relatively small change from Carbon's design prior to\nthis proposal, and there are also teachability concerns with the ability to\ntreat a tuple of types as a type despite it _not_ being a value of type `type`.\nShould there prove to be sustained problems with teachability, we should\nconsider making more significant changes, such as adopting a distinct syntax for\ntuple types and empty structs.\n\n## Alternatives considered\n\n### Alternative member access rules\n\nWe considered rules where `T.(Interface.Member)` would either always mean\n`(T as Interface).Member` or always mean `(typeof(T) as Interface).Member`, but\nthat did not allow aliases to work as expected. We wanted an alias to an\ninterface method or class function defined inside of a class to be usable as a\nmethod or class function member of the class.\n\n```\ninterface A {\n  fn F[me: Self]();\n  fn S();\n}\nclass B {\n  external impl as A;\n  alias G = A.F;\n  fn H[me: Self]();\n  alias T = A.S;\n  fn U();\n}\n```\n\nWe want `B.G` to act like a method of `B`, like `B.H`, and `B.T` to act like a\nstatic class function of `B`, like `B.U`. We could have accomplished this by\nrequiring those aliases to be written in a different way, for example\n`alias G = (Self as A).F`, but needing to do that was surprising. We made it\nwork by making the interpretation of `T.(Interface.Member)` depend on whether\n`Member` was an _instance_ member of `Interface`, with an implicit `me`\nparameter, or not.\n\nThis was discussed in\n[the #syntax channel on discord on 2022-11-07](https://discord.com/channels/655572317891461132/709488742942900284/1039298322625744987)\nand in\n[open discussion on 2022-11-10](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#heading=h.1y65biik2vr).\n\n### Alternative terminology\n\nWe considered various alternatives for the terminology choices listed above in\n[open discussion on 2022-10-27](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#heading=h.lecxe8qywdxa).\n\nInstead of \"facet type\" we considered:\n\n-   constraint type\n    -   Concern: a \"foo type\" can mean \"a type that is also a foo\" like \"class\n        type\" or it can mean \"a type that holds foos\" like \"integer type\".\n-   constrained type\n    -   Concern: for some of us, this name seemed to better describe facets than\n        facet types.\n-   constraint\n    -   Concern: this may sound like it should refer to a boolean predicate,\n        `T is C`, not `C` itself.\n-   kind\n    -   Concern: while this terminology is used to describe the type of a type\n        in computer science literature, that usage is different from this one in\n        that it generally refers to the arity of type constructors rather than\n        classifying subsets of the set of types.\n\nInstead of \"generic type\" we considered:\n\n-   archetype\n    -   Concern: the usage here didn't match some of our intuitions based on\n        existing usage of this term.\n    -   Concern: while this might fit usage within the scope of the parameter,\n        it fits usage from outside the scope less well. It seemed awkward to say\n        that a class has an archetype parameter, as opposed to our chosen\n        terminology of a generic type parameter.\n-   constrained type variable\n    -   Concern: for some of us, the name \"constrained type\" seemed to better\n        describe facet types than facets.\n-   type-like\n    -   Concern: derived terms like \"generic type-like parameter\" and\n        \"associated type-like constant\" are awkward.\n-   kinded\n    -   Concern: derived terms like \"generic kinded parameter\" and \"associated\n        kinded constant\" are awkward.\n\nInstead of \"facet\" we considered:\n\n-   type\n    -   The idea here is that, because facets can be used in type contexts,\n        calling them types is reasonable.\n    -   Concern: we want `i32 as Sortable` and `i32 as Hashable` to be\n        different, but we do not want to say that they are \"different types\".\n    -   Concern: we use `type` to refer to types, not facets, and it's important\n        that conversion to type `type` erases the facet type from a facet. If we\n        call facets \"types\" then we mean different things by \"type\" and\n        \"`type`\", and for example conversion of a type to type `type` would\n        change its meaning, which seems surprising.\n-   impl\n    -   Concern: facets are analogous to `impl`s but are not in direct\n        correspondence, because a facet can be for a constraint that involves\n        multiple interfaces and hence potentially multiple `impl`s, and an\n        `impl` can be for a constraint that involves multiple interfaces and\n        hence a facet can refer to only _part of_ an `impl`.\n-   archetype\n    -   Concern: this seems inappropriate for non-generic facets, such as\n        `i32 as Hashable`.\n-   witness\n    -   Concern: doesn't quite represent what we mean: a facet is more like a\n        pair of a type and a witness that that type implements the facet's type.\n\n### `Core.Type` is an empty named constraint\n\nWe considered making `type` an alias for an empty type constraint defined in the\nprelude, `Core.Type`. While it is possible to define a constraint that is\nequivalent to `type` as a named constraint, we decided not to define `type` as\nan alias to such a named constraint in order to reduce complexity:\n\n-   Type-checking the prelude itself becomes more challenging if `type` is a\n    named constraint, due to the ubiquity of its usage.\n-   If `type` is an alias to `Core.Type`, then either the implementation would\n    need to ensure that it introduces no member names and no constraints, or it\n    would need to faithfully look into `Core.Type` every type a property of\n    `type` is consulted, adding either compile-time cost or complexity to the\n    implementation.\n\nGiven that we have no current desire to add member names or constraints to\n`type`, we do not get any benefit from defining it in the Carbon library. If we\nlater choose to make `type` imply some other constraints by default, such as\n`Sized` or `Movable`, this decision should be revisited.\n\nThis was discussed in:\n\n-   [#naming on 2022-10-31](https://discord.com/channels/655572317891461132/963846118964350976/1036750048899366954)\n-   [#syntax on 2022-10-27](https://discord.com/channels/655572317891461132/709488742942900284/1035222720864071740)\n-   [open discussion on 2022-10-31](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#heading=h.9x8m0qwhuux)\n\n### Write tuple types differently than tuples\n\nWe considered having the way to write tuple types be different than tuples. So\ninstead of `var x: (i32, i32) = (1, 2);` you might write:\n\n```carbon\nvar x: TupleType(i32, i32) = (1, 2);\n\n// Or, with dedicated syntax:\nvar y: (|i32, i32|) = (1, 2);\n```\n\nThere are a few reasons we decided not to go with this approach:\n\n-   There is a significant cost to having more balanced delimiters, particularly\n    ones consisting of multiple characters.\n-   Since types are values in Carbon, `(i32, i32)` is a valid and meaningful\n    expression. Users would be surprised if they cannot use it as a type.\n-   Allowing tuples in pattern syntax but not in type syntax may be surprising.\n    For example, given that `var (x: i32, y: i32);` is valid, it may be\n    surprising if `var p: (i32, i32);` is not valid.\n-   We expect that, when teaching or speaking casually, we would not need to\n    explain that `(i32, i32)` was not a type but was usable as a type. That\n    distinction would generally not affect users, who would generally be able to\n    treat the type of a tuple as the tuple of the types of its elements.\n-   This would prevent operations from working generically on both tuples values\n    and tuple types. We would need to instead duplicate the set of operations.\n    For example, there would need to be separate `TupleCat` and `TupleTypeCat`\n    operations to perform concatenation. This would be extra machinery, and a\n    burden for users to know about all of the functions and call the right one.\n\nThis was discussed\n[in the #syntax channel on 2022-11-03](https://discord.com/channels/655572317891461132/708431657849585705/1037793379813167166)\nand\n[in open discussion on 2022-12-07](https://docs.google.com/document/d/1gnJBTfY81fZYvI_QXjwKk1uQHYBNHGqRLI2BS_cYYNQ/edit?resourcekey=0-ql1Q1WvTcDvhycf8LbA9DQ#heading=h.qu6e01wbzrhz).\n"
  },
  {
    "path": "proposals/p2365.md",
    "content": "# Remove artificial version ceiling on C++ interop.\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2365)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Do nothing](#do-nothing)\n    -   [Enumerate specific versions and feature sets](#enumerate-specific-versions-and-feature-sets)\n\n<!-- tocstop -->\n\n## Abstract\n\nRemove a confusing mention of a specific version of C++ (C++17) from the\ninteroperability goals.\n\nExpand the content of the goals to make it clear that we have a moving and\nongoing target of C++ as it continues to evolve. Also emphasize that we will\nprioritize among the different features during Carbon's development based on how\nthey impact the overall project.\n\nHowever, this intends to preserve the fact that there may exist long-tail or\ncorner-case features in C++ that never end up with high quality or exhaustive\nsupport in our interop story simply because their impact on Carbon users is\nsufficiently small that it doesn't justify the cost.\n\n## Problem\n\nThe text referring to C++17 was bound to become out-of-date as time marched\nonward. As a result, it was increasingly confusing and anchored us in the past.\n\nIt was also easily misunderstood in several cases as foreclosing _any_ effort to\ninteroperate with future versions or features of C++. While at the time written,\nthis may not have been a priority, it seems to increasingly be a source of\nconfusion or friction for users without benefit.\n\n## Proposal\n\nRemove the specific version and replace it with an attempt to explain the\nlong-term goal and how we will prioritize within that long-term goal.\nEventually, we should be aiming to support all major features and versions of\nC++ that are used in the industry. However, we should be pragmatic in our\nprioritization by focusing on those features and versions with the maximum\nimpact on the project.\n\n## Details\n\nSee the updated text in the\n[interop goals](/docs/design/interoperability/philosophy_and_goals.md#never-require-bridge-code).\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   This change should address confusion across the community, especially as\n        that community has grown.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Our goal is overall interoperability with C++ and the new wording should\n        better capture that.\n\n## Alternatives considered\n\n### Do nothing\n\nWe could not make this change, and live with some amount of confusion. However,\nthat seems to be enough confusion to be a distraction and so it seems worth\nupdating our documentation.\n\n### Enumerate specific versions and feature sets\n\nWe could try to enumerate specific versions and feature sets but it seems likely\nfor this list to change frequently and be a new source of confusion or\nmaintenance burden.\n\nGiven the current stage of the project, it seems preferable to instead describe\nthe high level goal and how we expect to prioritize features. The actual work to\ndesign interop can in turn present the specific features covered.\n"
  },
  {
    "path": "proposals/p2376.md",
    "content": "# Constraints must use `Self`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2376)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Abstract\n\nRequire `impl as` constraints in an `interface` or `constraint` definition to\nmention `Self` implicitly or explicitly. Require `where` clauses to refer to\n`.Self` directly, or through a designator like `.Foo`.\n\n## Problem\n\nWhen trying to implement constraints in Carbon Explorer, we\n[came up with an example](https://discord.com/channels/655572317891461132/941071822756143115/986054308179103765)\nthat raised questions:\n\n```carbon\ninterface A {}\ninterface B {}\nexternal impl forall [T:! Type] T as A where T is B {}\n```\n\nThere were multiple possible interpretations for what the meaning of that\n`where` clause was.\n\n-   It could be equivalent to\n    `external impl forall [T:! Type where .Self is B] T as A {}`. That is, this\n    introduces an implementation of A for only those T that satisfy the where\n    condition.\n-   It could be equivalent to `external impl forall [T:! Type] T as A {}` but\n    invalid if there is no `impl forall [T:! Type] T as B`. that is, this\n    requires an implementation of `B` to exist for all `T`.\n-   It could be equivalent to `external impl forall [T:! Type] T as A & B {}`.\n    That is, this introduces an implementation of `B` for all `T`.\n-   It could be invalid for various reasons.\n\nThat advantage of making this construction invalid is that it would force the\ncode into a form with a clearer meaning.\n\nOther cases suggested that constraints that were modifying other types were in\ngeneral surprising,\n[for example](https://discord.com/channels/655572317891461132/941071822756143115/986061766226214932):\n\n```carbon\nfn F[A:! Type, B:! Type, C:! Type where A == B](a: A, b: B, c: C);\n```\n\nwould be better written as:\n\n```carbon\nfn F[A:! Type, B:! Type where A == .Self, C:! Type](a: A, b: B, c: C);\n```\n\nso the relationship between types `A` and `B` would be established from their\ntwo declarations, not later modified by the declaration of `C`.\n\nIn summary, we ended up with a number of reasons to say a `where` clause should\nbe a constraint on the type being modified:\n\n-   We prefer there only be [one way](/docs/project/principles/one_way.md) to\n    write constraints. We believe that the examples that don't meet this\n    restriction can always be rewritten to a form that meets this restriction.\n-   We believe that after the rewrite, there is less ambiguity about what the\n    code means.\n-   We think it is valuable that the constraints on a type are complete when the\n    type's declaration is complete.\n\nWe found similar restrictions are valuable for `impl as` constraints in an\n`interface` or `constraint` definition. The restriction that they always involve\nthe `Self` type means that the search that compiler has to do to find relevant\nconstraints is limited to a finite number of definitions. Furthermore, without\nthis restriction, the set of interfaces known to implement a type would change\ndepending on which interfaces definitions are imported and known to be\nsatisfied, which is a coherence problem.\n\nThis restriction also allows interfaces and named constraints to be used while\nincomplete, which allows some use cases that involve circular references,\nincluding self reference. The logic goes like this:\n\n-   we want to limit when information from a constraint is found,\n-   to increase the cases where we don't need to look in a constraint,\n-   so constraints are allowed to be incomplete in those cases.\n\nProposal [#2347](https://github.com/carbon-language/carbon-lang/pull/2347) lists\nconditions when we want to allow constraints to be incomplete.\n\n## Background\n\nThere are a number of earlier proposals related to or modified by this proposal:\n\n-   [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n    introduced `impl as` restrictions in interfaces and named constraints.\n-   [#818: Constraints for generics (generics details 3)](https://github.com/carbon-language/carbon-lang/pull/818)\n    introduce `where` constraints.\n-   [#1013: Generics: Set associated constants using `where` constraints](https://github.com/carbon-language/carbon-lang/pull/1013)\n    switched to using `where` constraints in `impl` declarations to specify\n    associated constants.\n-   [#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084)\n    allowed forward declaration of interfaces and named constraints, explicitly\n    supporting incomplete interfaces and named constraints beyond when they were\n    being defined.\n-   [#2107: Clarify rules around `Self` and `.Self`](https://github.com/carbon-language/carbon-lang/pull/2107)\n    established some rules around `Self` and `.Self`, which this proposal adds\n    to.\n-   [#2347: What can be done with an incomplete interface](https://github.com/carbon-language/carbon-lang/pull/2347)\n    clarifies what can be done with an incomplete interface or named constraint.\n    Those rules rely on this proposal to be implementable.\n\n## Proposal\n\n`where` clauses must use a designator, either `.Self` or `.Foo` for some member\n`Foo`. The designator may be used directly, or supplied as an argument to a\ntype, interface, or named constraint used in the `where` clause, as in these\nexamples:\n\n-   `Container where .ElementType = i32`\n-   `Type where Vector(.Self) is Sortable`\n-   `Addable where i32 is AddableWith(.Result)`\n\n`impl as` declarations in interfaces and named constraints must always involve\n`Self`:\n\n-   Can be the implicit `Self` when no type is specified, as in `impl as ...`,\n    or the equivalent declarations with `Self` declared explicitly, as in\n    `impl Self as ...`\n-   Can be an argument to a type. The type can be what is to the left of the\n    `as`, as in `impl Vector(Self) as ...`, or a type argument to the interface\n    or constraint, as in `impl Vector(i32) as AddWith(Vector(Self))`.\n-   Can be a parameter to the interface or constraint to the right of the `as`,\n    as in `impl T as Bar(Self)`.\n\nWhen the compiler looks to see if any constraints imply that an impl exists, the\nonly place it needs to look are the places that involve the type the impl is for\n(`Self`). This means the compiler never needs to look in forward-declared (or\notherwise incomplete) constraints that don't involve that type. This applies\nrecursively. This allows incomplete interfaces and named constraints as\ndescribed in proposal\n[#2347](https://github.com/carbon-language/carbon-lang/pull/2347).\n\nThis solves a problem: when doing impl lookup, what is the set of imlps that you\ncan look up? There may be an infinite set of constraints reachable through\ninterfaces, but with this rule, you only need to consider a finite subset.\n\n## Details\n\nThe [\"Generics: Details\" design document](/docs/design/generics/details.md) has\nbeen updated with this proposal. It includes clarification in the\n[conditional conformance section](/docs/design/generics/details.md#conditional-conformance)\nthat an `impl` in a `class` definition can only be for the type being defined.\n\n## Rationale\n\nThese restrictions are in support of the\n[\"prefer providing only one way to do a given thing\" principle](/docs/project/principles/one_way.md),\nby reducing the number of equivalent ways of expressing a constraint.\n\nAs described in the [problem section](#problem), these restrictions make code\n[easier to read and understand](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\nby avoiding confusing or ambiguous constructions.\n\nThese restrictions reduce the search the compiler needs to perform to find\nrelevant constraints during impl lookup, in support of\n[fast and scalable development](/docs/project/goals.md#fast-and-scalable-development).\n\n## Alternatives considered\n\nThe main alternative we considered, was not imposing these restrictions. We\ndecided these restrictions were a good idea in these conversations:\n\n-   [#generics-and-templates on 2022-06-13](https://discord.com/channels/655572317891461132/941071822756143115/986061509815844864)\n-   [Open discussion on 2022-10-12](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#heading=h.q7afaawbc5k)\n-   [#generics-and-templates 2022-10-24](https://discord.com/channels/655572317891461132/941071822756143115/1034198851059466292)\n-   [2022-10-24 open discussion](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#heading=h.hb5qukkw7d3l)\n\nThe advantages of this proposal are outlined in the [problem section](#problem).\n\nThe main disadvantage of this proposal that\n[we considered](https://discord.com/channels/655572317891461132/941071822756143115/986063589016215614)\nis that it removes the option to use another name for the type than `.Self`. The\nconcern was that `.Self` might be seen as an advanced feature that is difficult\nto understand, or it might be longer.\n"
  },
  {
    "path": "proposals/p2483.md",
    "content": "# Replace keyword `is` with `impls`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2483)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [`T as C`](#t-as-c)\n    -   [`T: C`](#t-c)\n\n<!-- tocstop -->\n\n## Abstract\n\nUse the keyword `impls` instead of `is` when writing a `where` constraint that a\ntype variable needs to implement an interface or named constraint.\n\nWhat was previously (provisionally) written:\n\n```\nfn Sort[T:! Container where .ElementType is Ordered](x: T*);\n```\n\nwill now be written:\n\n```\nfn Sort[T:! Container where .ElementType impls Ordered](x: T*);\n```\n\n## Problem\n\nThe `is` keyword has been used as a placeholder in `where` constraints\nexpressing that a type variable is required to implement an interface or named\nconstraint. It has been an open question what word should be used in that\nposition since its original adoption in\n[#818](https://github.com/carbon-language/carbon-lang/pull/818). Since then,\nreasons to use a different word in this position have been discovered:\n\n-   The word \"is\" is unspecific and could represent many different\n    relationships.\n-   This specific relationship is not symmetric.\n-   We potentially want to use `is` as a keyword for another purpose.\n-   The precedent for `is` came from Swift where `x is T` means \"`x` has the\n    type `T`\". With the changes to Carbon generic semantics, particularly\n    [#2360: Types are values of type `type`](https://github.com/carbon-language/carbon-lang/pull/2360),\n    that is increasingly a poor fit for what we mean by this condition.\n\n## Background\n\nThe `is` keyword as a constraint operator was introduced in\n[#818: Constraints for generics (generics details 3)](https://github.com/carbon-language/carbon-lang/pull/818),\nalong with the open question about how to spell it.\n\nThe choice of `is` in that proposal followed\n[`is` being Swift's type check operator](https://docs.swift.org/swift-book/LanguageGuide/TypeCasting.html#ID340),\nwhere `x is T` is `true` if `x` has type `T`. Note that there are differences\nbetween the `is` operator in Swift and what we have used it for in Carbon. In\nSwift, it is used to test whether a value dynamically has a specific derived\ntype, when you have a value of a base class type and are using inheritance. In\nCarbon:\n\n-   it is used on types instead of values;\n-   it is about conformance to an interface (the equivalent of Swift's\n    protocols), and not about inheritance; and\n-   it is resolved at compile time.\n\n## Proposal\n\nUse the keyword `impls` instead of `is` when writing a `where` constraint that\nat type variable needs to implement an interface or named constraint. The\nspecific changes are included in\n[the same PR as this proposal](https://github.com/carbon-language/carbon-lang/pull/2483).\n\n## Rationale\n\nThis proposal is working towards Carbon's\n[code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\ngoal:\n\n-   Examples read naturally using \"implements\" in the place of the `impls`\n    keyword, commonly matching how a comment would describe the constraint.\n-   More clearly communicates the relationship between the two sides and that\n    the relationship is not symmetric.\n-   If a function has a `where T impls C` constraint that is not satisfied for\n    some calling type `T`, the fix is for the caller to add an `impl T as C`\n    definition.\n\n## Alternatives considered\n\nOne concern with using `impls` is the potential for confusion with the plural of\n`impl`, meaning \"implementations,\" rather than acting as the verb \"implements.\"\nWe hope to mitigate that concern by avoiding use of \"impls\" to mean anything\nother than `impls` in our documentation. For example, we would say \"`impl`\ndeclarations\" instead of \"`impl`s\".\n\nAlternatives were considered in\n[#2495: Keyword to use in place of `is` in `where`...`is` constraints](https://github.com/carbon-language/carbon-lang/issues/2495).\nA number of alternatives were considered:\n\n-   `T is C`\n-   `T isa C`\n-   `T impls C`\n-   `T implements C`\n-   `T ~ C`\n-   `T: C`\n-   `T as C`\n-   `T impl C`\n-   `T impl as C`\n-   `impl T as C`\n\nThe reasons against `is` were outlined in the [problem](#problem) and\n[rationale](#rationale) sections. Reasons against other alternatives:\n\n-   `isa` seems (much) too rooted in inheritance.\n-   `implements` is long but otherwise fine. This is a specific place where\n    being verbose has worrisome negative impact.\n-   `~` is already being considered for something a bit more fitting --\n    bidirectional convertibility of our type \"equality\" constraints.\n-   `impl` seems a bit clunky, and surprising to see in this position when it\n    usually isn't.\n-   `impl as` seems even more clunky\n-   `impl T as C` also seems even more clunky, and would be confusing with the\n    rules around rewrite constraints (different here from the use of\n    `impl T as C` in a type).\n\nIn general there were concerns that the alternatives were confusing and risk\nappearing to mean something other than what it does.\n\n### `T as C`\n\nThe keyword `as` received more consideration:\n\n-   Already a thing, and names the _facet_ that is required to exist.\n-   Already used in a facet-like-but-not-facet context for\n    `impl T as C { ... }`.\n-   Short, easy to read, etc.\n\nIt had some disadvantages, though:\n\n-   Doesn't connect readers as directly and effectively to the need for an\n    `impl` to satisfy the constraint.\n-   Doesn't read as nicely in context:\n    `T:! C where C.ElementType as AddWith(i32)`. This was a big consideration in\n    deciding against using `as`.\n-   Underlying the above disadvantage, it doesn't fit into the model of a\n    boolean expression that should be true. Instead, it is a cast that should be\n    _possible_ or _meaningful_, which is somewhat different from the rest of the\n    things in a `where` clause.\n    -   However, \"rewrite\" constraints don't quite fit this model either.\n    -   When using `==` constraints, they don't actually imply any boolean\n        expression that would return true. In fact, at least my understanding is\n        that the `T == U` constraint _could_ be written as a boolean expression\n        but it would return _false_ even when the constraint holds.\n\n### `T: C`\n\n`T: C` matches how Swift and Rust write this, and is similar to the way you'd\nwrite the same constraint in an ordinary declaration, `T:! I`. This syntactic\nsimilarity is also a liability due to the differences in semantics when used in\na `where` clause: the `where` clause doesn't make the names from `I` available\nin `T`, and it doesn't propagate `where .A = B` rewrites from `I` to `T`.\n\nThere's also some concern that the use of `:` would make parameter lists hard to\nread when they contain embedded `where` clauses, like\n`T:! Container where .ElementType: Printable, U:! OtherConstraint`.\n"
  },
  {
    "path": "proposals/p2511.md",
    "content": "# Assignment statements\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2511)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Allow assignment as a subexpression](#allow-assignment-as-a-subexpression)\n    -   [Allow chained assignment](#allow-chained-assignment)\n    -   [Do not provide increment and decrement](#do-not-provide-increment-and-decrement)\n    -   [Treat increment as syntactic sugar for adding `1`](#treat-increment-as-syntactic-sugar-for-adding-1)\n    -   [Define `$` in terms of `$=`](#define--in-terms-of-)\n    -   [Do not allow overloading the behavior of `=`](#do-not-allow-overloading-the-behavior-of-)\n    -   [Treat the left hand side of `=` as a pattern](#treat-the-left-hand-side-of--as-a-pattern)\n    -   [Different names for interfaces](#different-names-for-interfaces)\n\n<!-- tocstop -->\n\n## Abstract\n\nAssignment is permitted only as a complete statement, not as a subexpression.\nAssignment and compound assignment syntax follow C++ in all other respects.\nPre-increment is provided. Post-increment is not. Uses of all of these operators\nare translated into calls to interface members.\n\n## Problem\n\nAssignment is a cornerstone of imperative programming. Carbon does not currently\nhave an approved proposal describing the syntax and interpretation of\nassignment.\n\n## Background\n\nIn C-family languages, there are three kinds of assignment-like operators:\n\n-   Simple assignment: `variable = value`\n-   Compound assignment: `variable $= value`, for some binary operators `$`,\n    meaning `variable = variable $ value`, except that `variable` is evaluated\n    only once.\n-   Increment and decrement: `++variable` and `--variable` meaning\n    `variable += 1` and `variable -= 1`, and `variable++` and `variable--`\n    acting similarly but returning the prior value of `variable`.\n\nThese operators behave mostly like other binary operators, and in particular the\nabove expression forms can be used as subexpressions of other expressions.\n\nChained assignment is supported, and associates from right to left: `a = b = 1`\nassigns `1` to `b`, then assigns the result of that assignment to `a`. In C++,\nthat result is typically an lvalue referring to `b`, but in C, it is an rvalue\ncontaining the result of converting `1` to the type of `b`. Note that all other\noperators in C and C++ associate in the other direction.\n\nThese operators have a collection of known issues, including:\n\n-   Confusion between assignment and comparison, for example in constructs such\n    as `if (variable = 3) { ... }`. This is sufficiently rife that a de facto\n    compiler-warning-enforced convention has arisen of using additional\n    parentheses for the rare cases when assignment is intended:\n    `if ((variable = 3))`.\n-   Risk of unsequenced modification and access to the same variable, resulting\n    in undefined behavior. For example, `n = a + n++;` has undefined behavior in\n    C and C++ for this reason, because the act of incrementing `n` is not\n    sequenced with respect to the rest of the computation, including the\n    assignment.\n-   In C++, post-increment can be a performance trap, because it is expected to\n    return the old value of the variable, which might otherwise not be\n    preserved. The additional copying may be optimized away if the `operator++`\n    can be inlined, at the cost of additional work for the compiler.\n-   In C++, overloading an operator `$` does not automatically provide a\n    matching `$=`, resulting in additional work or incomplete operator sets.\n\n## Proposal\n\nC-family assignment operators are provided as statements:\n\n-   `variable = value;` is a simple assignment statement.\n-   `variable $= value;` is a compound assignment for each binary operator `$`,\n    other than comparisons. `<=` and `>=` mean \"less than or equal to\" and\n    \"greater than or equal to\", not \"compare and assign\".\n-   `++variable;` and `--variable;` are supported as increment and decrement\n    syntax. Because these are statements, there is no distinction between pre-\n    and post-increment, and post-increment is not provided.\n\nThese operations are translated into calls on interfaces.\n\n## Details\n\nSee the changes to the design.\n\nThis proposal does not define the semantics of assignment that are provided for\nclasses by default. Leads issue\n[#686](https://github.com/carbon-language/carbon-lang/issues/686) gives some\nrules, but those rules are not part of this proposal.\n\n## Rationale\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   The values of variables can only change if either the address is taken,\n        including implicitly by `addr` self parameters, or at assignment\n        statements, making it easier to reason about where the value of a\n        variable can change in the control flow of a function.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   This approach is conservative and can evolve to support assignment as a\n        subexpression.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Assignments in subexpressions tend to be hard for humans to read and\n        understand. Disallowing them at the language level avoids the potential\n        for confusion, making code easier to read at the cost of making certain\n        constructs such as `n = arr[i++];` a little harder to write.\n    -   Easier to write a complete operator set because both `$` and `$=` can be\n        provided by implementing a single interface.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   Replaces correctness warning on `if (a = b)` with a language rule.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Providing largely the same set of symbols makes migration easier.\n    -   Some cost may be imposed by forcing a translation from assignment in\n        subexpressions to assignment as separate statements.\n\n## Alternatives considered\n\n### Allow assignment as a subexpression\n\nWe could allow some or all forms of assignment as subexpressions, either with\nthe same syntax or with some other syntax. This proposal does not support\nassignment as a subexpression because the utility of this feature in C++ is very\nlimited and leads to problems where equality comparison and assignment are\neasily confused. Modeling assignment as a statement also makes it easier to\ntreat it as the transition point between a variable being in an unformed state\nand in a fully-formed state, as it prevents such transitions from happening at a\nnot-fully-sequenced point within the evaluation of an expression.\n\nTo avoid the syntactic confusion between assignment and comparison, we could\nallow assignment as a subexpression with some other syntax. For example, we\ncould adopt Python's \"walrus operator\" `variable := value`. For now, we are\nchoosing to not pursue this option in order to determine how much motivation\nthere is for such a feature.\n\nIf we allow a three-term form of `for` statements, `for (init; cond; incr)`, we\ncould allow assignment in the `incr` term. However, we currently do not support\nthis syntax.\n\nThe absence of assignment as a subexpression can be worked around with an\nergonomic cost, either by using a direct function call `x.(Assign.Op)(y)` or\nwith a lambda wrapping an assignment. Post-increment `a++` could be transformed\ninto `${var b: auto = a; ++a; return b;}`, where `${...}` is a placeholder for\nCarbon's eventual lambda syntax.\n\nWorkarounds that are not assignment statements would likely be treated as\ncapturing `x` for static analysis purposes, not as definitely initializing `x`,\nso unformedness checks and other similar checks we might choose to include in\nthe Carbon language design may treat these workarounds conservatively.\n\n```\nvar a: i32;\nvar b: i32;\nvar c: i32;\n// ✅ OK, per pending proposal #2006.\na = 1;\n// 🤷 Might result in an error or warning;\n// `b` is in an unformed state.\nb.(Assign.Op)(1);\n// 🤷 Undecided whether we will guarantee that\n// assignment to `c` precedes read from `c`.\na += c.(Assign.Op)(1) + c;\n```\n\n### Allow chained assignment\n\nAs a special case of assignment as a subexpression, we could allow chained\nassignment:\n\n```\na = b = c = 0;\n```\n\nWe could restrict this to only apply to simple assignment, not cases like\n`a += b -= c *= 2;`\n\nIn leads issue [#451](https://github.com/carbon-language/carbon-lang/issues/451)\nit was decided that we would initially not support chained assignment, although\nthis was largely the result of a lack of arguments in favor of support that\nwould justify the complexity of adding a special case, and should be\nreconsidered if compelling arguments in favor of chained assignment are\nuncovered.\n\n### Do not provide increment and decrement\n\nWe could remove `++var;` and `--var;` in favor of `var += 1;` and `var -= 1;`.\nHowever, developers coming from C-family languages will expect these operators\nto exist, and they may more directly convey the intended semantics of counting\nand navigating in a one-dimensional granular space than a `+=` operation would.\n\n### Treat increment as syntactic sugar for adding `1`\n\nWe could treat `++a;` as being syntactic sugar for `a += 1;`, in the same way\nthat we treat `a += 1;` as being syntactic sugar for `a = a + 1;`, and similarly\nfor `--a;`. This would mean that floating-point types gain increment and\ndecrement operators, as in C++.\n\nThe literal `1` has its own type, which means that this approach would not\nrequire a type to support adding integers in general in order to support\nincrement and decrement, and types such as non-random-access iterators could\nprovide an `it + 1` operation without exposing a non-constant-time `it + n`\noperation.\n\nOne potential advantage of this approach is that a generic constraint that is\nsufficient to allow `a = a + 1;` to type-check would also allow `++a;` to\ntype-check. For example, `T:! Assign & Add where i32 is ImplicitAs(.Self)` would\nsuffice to allow such an increment, as would a facet type with a narrower\n`ImplicitAs` constraint that permits only the literal `1`. However, this benefit\nis minor, given that writing `a += 1;` instead is not a major burden.\n\nThe cost of making this change would be that the semantics of increment and\ndecrement are tied to a very numerical notion of \"adding 1\". That may not be\nappropriate for all types that want to support a more general notion of \"move to\nthe next value\" or \"move to the previous value\", such as a more generalized\nnotion of cursor. It may also not be appropriate for all types that support\naddition of exactly 1 to support increment; for example:\n\n-   For floating-point types, adding exactly 1 does not necessarily produce a\n    different number, and there is a different meaningful notion of \"move to the\n    next value\" -- namely, moving to the next _representable_ value -- which may\n    be intended instead. In C++ code, where increment of floating-point types is\n    permitted, it is vanishingly rare.\n-   For complex numbers, for example in a Gaussian integer type, having `++c;`\n    move one unit in the real direction seems arbitrary.\n-   For a rational number type, as for floating-point types, adding exactly 1\n    seems unlikely to be a common \"navigation\" operation, even though there is\n    no other reasonable notion of \"move to the next value\".\n\n### Define `$` in terms of `$=`\n\nInstead of defining `$=` in terms of `$` and `=`, we could define `$` in terms\nof `$=` and copying. Our experience from C++ is that `$=` can frequently be\nimplemented more efficiently than `$`, by operating in-place and reusing\nallocated storage from the left-hand operand, so this might be a better default.\n\nThere are a few reasons why we choose to not do this:\n\n-   The direction in this proposal is expected to be less surprising. Defining\n    `$=` in terms of `$` and `=` seems more in line with programmer expectations\n    based both on the morphology of the token and on how it is generally taught.\n-   Under the rules in this proposal, an `Add & Assign` constraint ends up being\n    effectively equivalent to an `AddAssign` constraint, due to the blanket\n    implementation of `AddAssign` in terms of `Add` and `Assign`. This means\n    that constraining a type to provide both `Add` and `Assign` is sufficient to\n    use `+=`, which seems desirable. If the defaults were reversed, this would\n    not be achievable.\n-   If the reverse rule were adopted, two separate `impl`s would still be\n    required in order to permit implicit conversions on the left hand side of\n    the `$` for a type, but not on the left hand side of a `$=`.\n-   There are cases where `$` can be implemented more efficiently than making a\n    copy and performing a `$=` operation. For example, if the type is large,\n    implementing `$` in terms of `$=` can require two passes over the\n    destination instead of one, which may increase the constant factor\n    performance of the operation.\n\n### Do not allow overloading the behavior of `=`\n\nWe could define that an `=` expression always carries out these steps:\n\n-   Initialize a value of the left-hand operand's type from the right-hand\n    operand.\n-   Destroy the left-hand operand.\n-   Move the value created earlier into the left-hand operand.\n\nHowever, this removes some flexibility and could harm performance, for example\nin the case where the left-hand operand has a buffer that it could reuse to\nstore its new value. This would also be a significant deviation from C++, where\nsome types take advantage of this additional flexibility, and would be expected\nto harm interoperability and migration.\n\n### Treat the left hand side of `=` as a pattern\n\nWe could allow pattern-like syntax on the left hand side of `=` instead of an\nexpression.\n\n```\nfn GCD(var a: i32, var b: i32) -> i32 {\n  if (b < a) {\n    // Swap `a` and `b`.\n    (a, b) = (b, a);\n  }\n  while (a != 0) {\n    // Calculate both `b % a` and `a`,\n    // then assign to both `a` and `b`.\n    (a, b) = (b % a, a);\n  }\n  return b;\n}\n```\n\nHowever, this would be a novel interpretation of pattern syntax: there is no\nmechanism in the current pattern syntax to assign to an existing variable.\nPattern-matching `(a, b)` against `(b % a, a)` would instead compare `a` to\n`b % a` and compare `b` to `a` in the current mechanism. It is not clear that\nthis level of novelty is justified by the value added by this functionality.\n\n### Different names for interfaces\n\nWe considered various different names for the interfaces in this proposal.\nDifferences from the proposed names are highlighted:\n\n-   `Assign`, `AssignWith`, `OpAssign`, `OpAssignWith` (proposed)\n\n    -   Consistently uses `With` suffix to describe the right-hand type.\n    -   These names have a direct connection to the lexical operator syntax: the\n        interface for `$=` is named as the interface for `$` followed by the\n        interface for `=`.\n    -   The word order in the name describes the order in which the operations\n        are notionally performed: first `Op`, then `Assign`.\n    -   Compound assignment interfaces will group alphabetically with the\n        corresponding operator, rather than with assignments, which is likely to\n        be better for people searching for items in a sorted list.\n    -   Matches the choice made in Rust.\n\n-   `Assign`, **_`AssignFrom`_**, `OpAssign`, `OpAssignWith`\n\n    -   This reads more naturally in English. `With` isn't really the right word\n        to use in this context, and may be confusing.\n    -   Violates the consistency of using `...With` for all the parameterized\n        operator interfaces.\n    -   Given how common this interface is expected to be compared to the rest,\n        the inconsistency of using `AssignFrom` might be acceptable, but for now\n        we will use `AssignWith`. If there are sustained concerns with this name\n        (if we don't \"get used to it\"), we should reconsider.\n\n-   `Assign`, `AssignWith`, **_`AssignOp`_**, **_`AssignOpWith`_**\n\n    -   Consistently uses `With` suffix to describe the right-hand type.\n    -   The name `AssignOpWith(U)` decomposes as `Assign` + `OpWith(U)` in a way\n        that describes the two operations being performed.\n    -   When written as function calls, the behavior is `Assign(x, Op(x, y))`,\n        which again uses the `AssignOp` word order.\n\n-   `Assign`, **_`AssignGiven`_**, `OpAssign`, **_`OpAssignGiven`_**\n\n    -   `Given` might be a less surprising word for simple assignment than\n        `With`, but is still not ideal.\n    -   This choice seems slightly worse in most existing cases that use `With`,\n        and we didn't consider the benefit of `AssignGiven` over `AssignWith` to\n        be sufficient to justify that cost.\n\n-   `Assign`, `AssignWith` or **_`AssignFrom`_**, **_`InPlaceOp`_**,\n    **_`InPlaceOpWith`_**\n\n    -   Might make `AssignFrom` more viable by making `Assign` / `AssignFrom` no\n        longer parallel `InPlaceOp` / `InPlaceOpWith` so closely.\n    -   Might better match how these operations are described in everyday\n        parlance.\n\nOverall, the proposed set of names seem like the best choice, despite some of\nthe names not reading completely naturally. The English readability concern is\nprobably not much worse than for `LeftShiftWith`, where we already decided that\nconsistency was more important.\n"
  },
  {
    "path": "proposals/p2550.md",
    "content": "# Simplified package declaration for the `Main` package\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2550)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Require the use of the identifier `Main` in package declarations](#require-the-use-of-the-identifier-main-in-package-declarations)\n    -   [Permit the use of the identifier `Main` in package declarations](#permit-the-use-of-the-identifier-main-in-package-declarations)\n    -   [Distinguish file scope from package scope](#distinguish-file-scope-from-package-scope)\n    -   [Keep the package name in imports](#keep-the-package-name-in-imports)\n    -   [Make the main package be unnamed](#make-the-main-package-be-unnamed)\n    -   [Use a different name for the entry point](#use-a-different-name-for-the-entry-point)\n    -   [Use a different name for the main package](#use-a-different-name-for-the-main-package)\n-   [Acknowledgements](#acknowledgements)\n\n<!-- tocstop -->\n\n## Abstract\n\nMake the preamble of simple programs more ergonomic, by removing the\n`package Main` from the main package and removing the `package` declaration\nentirely from the main source file. Imports within a single package no longer\nneed to, and are not permitted to, specify the package name.\n\n## Problem\n\nEvery Carbon source file is required to start with a `package` declaration:\n\n```\npackage Main impl;\n```\n\nThis introduces complexity and syntactic overhead to very simple programs, such\nas might be encountered by beginners learning Carbon. This is also inconvenient\nfor slide code and small examples in teaching material, where the author must\nchoose between including boilerplate or providing an example that Carbon\nimplementations will reject.\n\nIn addition, imports within a single package are required to restate the name of\nthe package:\n\n```\npackage Geometry library \"Shapes\" api;\nimport Geometry library \"Points\";\n```\n\nThis creates additional syntactic overhead for a common operation, and misses\nthe opportunity to visually distinguish between different categories of imports\n-- \"our library\" versus \"their library\". Additionally, under\n[#1136](https://github.com/carbon-language/carbon-lang/issues/1136), imports\nfrom the same package have different semantics than imports from a different\npackage, so giving the two operations the same syntax seems confusing.\n\nGiven that every package has an arbitrary, developer-selected identifier name,\nit is also unclear how to determine which package contains the entry point of\nthe program. The name `Main` could be reserved for this, but no such decision\nhas been made.\n\n## Background\n\nProposal\n[#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107/files)\nintroduced our current `package` syntax.\n\nIn issue\n[#1869: What is the main entry point for execution? `Main` or `Run`?](https://github.com/carbon-language/carbon-lang/issues/1869)\nthe leads decided that the entry point of a Carbon program is named `Main.Run`.\nThat decision is implemented by this proposal.\n\nIn issue\n[#1136: what is the top-level scope in a source file, and what names are found there?](https://github.com/carbon-language/carbon-lang/issues/1136),\nthe leads decided that a package's name should not be injected into the scope of\nits files, and that same-package `import`s should not mention the package name.\nThose decisions are also implemented by this proposal. Note that other decisions\nwere also made in #1136 regarding name access (`private`) and the behavior of\nunqualified name lookup that are not part of this proposal.\n\n## Proposal\n\nA Carbon program has a `Main` package, which is the package that contains the\nentry point of the program. The entry point is a function named `Run`.\n\nIt is also possible to link Carbon libraries into programs written in other\nlanguages, and in particular, Carbon libraries can be used from C++ programs. In\nthis case, there will be no Carbon `Run` function, and the C++ program will\nprovide a `main` function that is used as the entry point.\n\nIn the `Main` package, the package declaration does not explicitly specify a\npackage name. The package declaration syntax becomes:\n\n-   `package` _Foo_ [`library \"`_Bar_`\"`] \\(`api` | `impl`) `;`, unchanged from #107,\n    for a file that is part of a package other than the `Main` package.\n-   `library \"`_Bar_`\"` (`api` | `impl`) `;` for a library that is part of the\n    `Main` package.\n-   Omitted entirely for an `impl` file in the `Main` package that is not part\n    of a named library.\n\nThere is no way to define an `api` file for the `Main` package that is not part\nof a named library -- there is no equivalent of `package Main api;`.\n\nThe import syntax becomes:\n\n-   `import` _Foo_ `;` to import the default library of package _Foo_, or\n    `import` _Foo_ `library \"`_Bar_`\"` `;` to import library _Bar_. This\n    introduces the name _Foo_ in the current source file as a name for that\n    package, containing whatever subset of the package was imported. `Foo` is\n    not allowed to be the name of the current package.\n-   `import library \"`_Bar_`\";` to import library _Bar_ of the current package.\n    This introduces the names from that library at file scope. _Bar_ is not\n    allowed to be the name of the current library.\n-   `import library default;` to import the default library of the current\n    package. This is not allowed within the default library.\n\nIt is an error to explicitly specify the package name `Main` in a package\ndeclaration or an import declaration. As a result, there is no way to import\nlibraries of the `Main` package from any other package.\n\nIt is permitted for a Carbon program to contain a source file that has no\n`package` declaration and does not contain a `Run` function -- or even to\ncontain multiple such source files. Such a source file cannot implement any\nimportable functionality, as there is no corresponding `api` file, but may still\nbe useful to support Carbon features that have not yet been designed, such as:\n\n-   Global registration mechanisms.\n-   Some way of defining functions with well-known symbols, analogous to\n    `extern \"C\"` declarations in C++.\n\n## Details\n\nSee design changes.\n\n## Rationale\n\n-   [Goal: Community and culture](/docs/project/goals.md#community-and-culture)\n    -   This change allows small complete programs and source files to be\n        discussed in Carbon forums without the overhead of `package`\n        declarations. Cumbersome top-level syntax hampers technical discussion.\n-   [Goal: Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   Test cases for language tools are made unnecessarily verbose by the\n        mandatory inclusion of a `package` declaration and a `Main` function.\n        This proposal makes these components optional.\n-   [Goal: Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Simple programs, such as `\"hello, world\"` examples written by beginners,\n        have less boilerplate.\n    -   Reduction of verbosity that is not contributing to increased\n        understanding of the program.\n-   [Goal: Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   This proposal explicitly acknowledges and permits the entry point for a\n        program that includes Carbon code to be written in a different language.\n    -   The use of the name `Main.Run` for the entry point is intended to be\n        similar enough to the use of the name `main` in C++ to be familiar.\n-   [Principle: Prefer providing only one way to do a given thing](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/principles/one_way.md)\n    -   Each `package` and `import` declaration has only one valid spelling. We\n        do not allow redundantly specifying the current package in an `import`,\n        nor using `library default` in any context where the `library` stanza\n        can be omitted with the same meaning, and we do not allow explicitly\n        writing a `package` declaration within the `Main` package.\n\n## Alternatives considered\n\n### Require the use of the identifier `Main` in package declarations\n\nInstead of the name `Main` being implied in `package` declarations, we could\nrequire it to be explicitly written:\n\n```\npackage Main impl;\nimport SimpleIO;\n\nfn Main() {\n  SimpleIO.Print(\"Hello, Carbon!\");\n}\n```\n\nThis would keep the Carbon language more consistent, and remove a special case.\nHowever, it would also increase verbosity in the simplest of programs, where the\nadded verbosity has the most cost.\n\n### Permit the use of the identifier `Main` in package declarations\n\nWe could allow the name `Main` to be used in package declarations and treat it\nthe same as if the name were omitted, making the other forms merely shorthand.\nHowever, this would introduce a syntactic choice that doesn't correspond to any\ndifference in intent, creating the opportunity for meaningless stylistic\ndivergence, and we\n[prefer to leave only one syntactic choice](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/principles/one_way.md)\nin order to enforce consistency.\n\n### Distinguish file scope from package scope\n\nUnder this proposal, the names from the current package that are visible, either\nby being declared locally or by being imported, are visible at the top level\nfile scope. We could pick a different rule that distinguishes package scope from\nfile scope, such as by introducing only locally-declared names into file scope\nand requiring a `PackageName.` prefix on all other names in the package.\n\nThis was discussed at length in\n[#1136](https://github.com/carbon-language/carbon-lang/issues/1136). We found\nthat distinguishing the package from the subset of the package visible at file\nscope led to problems that were more substantial than the potential\nsimplification of treating imports of the current package as being the same as\nimports of any other package. See that issue for the full discussion.\n\nIn [#1136](https://github.com/carbon-language/carbon-lang/issues/1136), it was\nalso decided to add a `package.Name` syntax to allow shadowed names from the\npackage scope to be referenced. That is not part of this proposal; until we add\nsuch a mechanism, its absence can be worked around by using private aliases:\n\n```\nfn Foo();\nprivate alias OuterFoo = Foo;\n\nclass Bar {\n  fn Foo() {\n    // 🤷 Either ambiguous or calls `Bar.Foo`.\n    Foo();\n    // Calls `Foo` from package scope.\n    OuterFoo();\n  }\n}\n```\n\n### Keep the package name in imports\n\nWe could consistently name the package targeted by an import in the `import`\ndeclaration:\n\n```\npackage Foo api;\nimport Foo library \"Bar\";\n```\n\nThis would lead to a more uniform syntax and, as noted in\n[a very similar alternative considered by #107](/proposals/p0107.md#optional-package-names),\nwould make it easier to search for all imports of a given library with a simple\ntool.\n\nThere are two reasons to want to avoid this:\n\n-   Use of the same syntax suggests that same-package imports and cross-package\n    imports have the same semantics. But they do not: a same-package import\n    introduces the set of public names in the nominated library, whereas a\n    cross-package import of package `Bar` introduces exactly the name `Bar`.\n-   This would require writing a name for the `Main` package, in order to allow\n    libraries of that package to be imported within the same package. Adding\n    that name would provide a syntax to import those libraries from another\n    package, which we wanted to disallow.\n\n### Make the main package be unnamed\n\nWe don't allow writing the name `Main` of the main package in `package`\ndeclarations nor in `import` declarations, so we could say that the main package\nhas no name or has the empty name. We chose to give it a specific name for a few\nreasons:\n\n-   Conversationally and in documentation, it is clearer to talk about the main\n    package than the unnamed package, and we expect people to call it \"the main\n    package\" or similar regardless of which name we pick.\n-   There may still be reasons we need an identifier name to refer to this\n    package. For example, this need may arise in name mangling, in attributes,\n    in error messages, in conventions for naming source files, and in other\n    technical contexts that require an identifier referring to the package.\n\nOne downside of picking a name is that it causes us to reserve an identifier and\nassign it special meaning, but we felt that using the name `Main` for any other\npackage would be confusing, so this cost is small.\n\nUltimately this decision was marginal, and the painter made the choice to use a\nnamed package in\n[#1869](https://github.com/carbon-language/carbon-lang/issues/1869).\n\n### Use a different name for the entry point\n\nWe could use a variety of different names for the entry point and for the\npackage that contains it. `Main` was the obvious first choice, as it is the name\nused in C and C++. However, we generally want to use verbs and verb phrases as\nfunction names, because functions describe actions and we find that verb phrases\nare easier to read and understand as function names as a result.\n\nSome other function names were considered but rejected:\n\n-   `Start` -- we preferred to use a word that describes the entire action of\n    the function, and the `Main.Run` function covers the complete execution of\n    the program, not just the beginning of that execution.\n-   `Entry` or `Entrypoint` -- same problems as `Start`, plus less discoverable,\n    potentially longer, not a familiar term to beginners, and not verbs.\n-   `Exec` or `Execute` -- we were concerned about a semantic collision between\n    the action of executing _some other_ program, as is performed by the C\n    `exec` function, and the action of executing the current program.\n\nSee [#1869](https://github.com/carbon-language/carbon-lang/issues/1869) for more\ninformation about this decision.\n\n### Use a different name for the main package\n\nWe considered other options for the main package name. The primary option\nconsidered was `Program`, but there were no decisive technical arguments to\nselect one name over another. The painter selected `Main` with the following\nrough rationale:\n\n> -   We weren't using `Main` for the function name, so it seemed available.\n> -   Given that it is the \"main package\" and in fact contains the entry point,\n>     it didn't seem likely to have any confusion with `main` functions in other\n>     languages.\n> -   It is shorter than `Program`.\n> -   I guess that it will work better to indicate a conventional filename of\n>     `main.carbon`.\n> -   For folks looking for a `main` function, it may help them find our\n>     version.\n\nSee [#1869](https://github.com/carbon-language/carbon-lang/issues/1869) for more\ninformation about this decision.\n\n## Acknowledgements\n\nThanks to [Allison Poppe](https://github.com/acpoppe) for authoring proposal\n[#2265 Name of application entry point](https://github.com/carbon-language/carbon-lang/pull/2265)\nwhich explored another option for naming the entry point.\n"
  },
  {
    "path": "proposals/p2551.md",
    "content": "# Roadmap for 2023 and retrospective for 2022\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2551)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Proposal](#proposal)\n-   [Retrospective on 2022](#retrospective-on-2022)\n    -   [Broaden participation so no organization >50%](#broaden-participation-so-no-organization-50)\n    -   [Example ports of C++ libraries to Carbon (100% of woff2, 99% of RE2)](#example-ports-of-c-libraries-to-carbon-100-of-woff2-99-of-re2)\n    -   [Carbon explorer implementation of core features with test cases](#carbon-explorer-implementation-of-core-features-with-test-cases)\n    -   [Demo implementation of core features with working examples](#demo-implementation-of-core-features-with-working-examples)\n\n<!-- tocstop -->\n\n## Abstract\n\nWe propose a roadmap for 2023 focus on:\n\n-   Progressing towards a concrete goal of an MVP / 0.1 language.\n-   Engaging more broadly and deeply with the C++ community.\n\nWe also reflect on our overly ambitious\n[roadmap for 2022](https://github.com/carbon-language/carbon-lang/blob/3d90a85f2439bb74b71a553c5017012369ec0f63/docs/project/roadmap.md)\nand how the year went.\n\n## Proposal\n\nOur primary goals for 2023 are:\n\n-   Define a concrete set of milestones for our Minimum Viable Product or MVP.\n    -   Because Carbon is an experiment, our MVP is focused on the _evaluation_\n        of the Carbon language, not any other usage.\n    -   We consider this MVP-for-evaluation our 0.1 language.\n-   Complete all of the 0.1 design and feature milestones.\n-   Complete as many of the 0.1 implementation milestones as we can.\n    -   Realistically, we don't expect to finish all of them in 2023.\n-   Begin actively engaging and sharing Carbon's design and ideas with the C++\n    community.\n\nSee our [updated roadmap](/docs/project/roadmap.md) for more details and how we\nexpect to measure our success.\n\n## Retrospective on 2022\n\nOur\n[roadmap for 2022](https://github.com/carbon-language/carbon-lang/blob/3d90a85f2439bb74b71a553c5017012369ec0f63/docs/project/roadmap.md)\nwas in retrospect wildly optimistic. We're sorry about that, and are going to\nwork to set more realistic goals and milestones going forward. That said, we\nstill achieved a tremendous amount and it's useful to look in some detail at how\neverything went.\n\nWe had two primary goals for 2022 and somewhat split the difference between\nthem:\n\n-   Make the Carbon experiment public: **100%** as we\n    [announced](https://youtu.be/omrY53kbVoA) Carbon publicly in July at\n    [CppNorth](https://cppnorth.ca/)!\n-   Complete the language design: lots of progress, but nowhere near the finish\n    line here. This ended up also being poorly defined in some cases, which\n    we're going to try to address going forward.\n\nWe can also measure the key results we had in mind with more precision.\n\n### Broaden participation so no organization >50%\n\n> Our goal is that no single organization makes up >50% of participation in the\n> Carbon project, to ensure that we are including as broad and representative a\n> set of perspectives in the evolution of Carbon as possible. As a proxy for the\n> amount of participation, we will count the number of active participants from\n> each organization in 2022, with the aim that each organization is represented\n> by less than 50% of all active participants.\n\nThe simplest participation measures are from commits to the repository over 2022\nwhich shows 92 contributors over the year, and definitely fewer than 46 of those\nfrom a single organization. But it's hard to consider a single typo fix in July\nas being an _active_ participant. Some other measures:\n\n-   During the last quarter of 2022 we had 14 authors contributing to patches,\n    and likely the largest single organization was only 5 of them.\n-   We had 171 issue authors this year, and 43 filing more than one issue. Well\n    below 50% from any single organization.\n-   We had 258 issue commenters, and 64 making over 4 comments over the course\n    of the year, both _far_ below 50% from a single organization.\n-   Looking at the weekly meetings in August, September, and October, we had\n    just under 50% of the meetings with less than 50% of attendees from a single\n    organization.\n\nLargely, we feel we hit this goal solidly. However, we still see specific areas\nwhere we need to broaden participation, for example:\n\n-   Language proposal authors (as opposed to other kinds of PRs and commits).\n-   Design discussion and meeting participation.\n\nSome of this will likely need Carbon to make substantial progress beyond\nexperimentation in order to have more organizations devote the significant\nresources that can be necessary for more in-depth participation.\n\n### Example ports of C++ libraries to Carbon (100% of woff2, 99% of RE2)\n\nWe ended up de-prioritizing this entirely so we could focus on the design and\nmoving the project public.\n\n### Carbon explorer implementation of core features with test cases\n\nLike the top-level goals for 2022, this specific result was much too ambitious.\nHowever, we have made tremendous progress on the design and the Carbon Explorer.\nFor example, we have a\n[detailed mapping](https://github.com/carbon-language/carbon-lang/wiki/Are-we-explorer-yet%3F)\nof the implementation status of the designed features, with approximately 50% of\nthese implemented.\n\nThe Carbon Explorer is also now integrated into the amazing\n[compiler explorer](https://carbon.godbolt.org/)! This largely addresses the\ncore of the \"repl\" and experimentation access goals, and our focus has otherwise\nbeen on completing the implementation.\n\n### Demo implementation of core features with working examples\n\nWe ended up prioritizing the Carbon Explorer over the toolchain in 2022 in order\nto have an easier path to a minimal demo implementation.\n\nHowever, we did begin fleshing out more of the toolchain implementation that\nwill eventually be used to compile Carbon into working binaries, and it has\nstarted to provide the first pieces of semantic analysis along with a much\nimproved parser for Carbon.\n"
  },
  {
    "path": "proposals/p2665.md",
    "content": "# Semicolons terminate statements\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2665)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Discussion in Carbon](#discussion-in-carbon)\n    -   [In other languages](#in-other-languages)\n        -   [Requiring semicolons](#requiring-semicolons)\n        -   [Optional semicolons](#optional-semicolons)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Optional semicolons](#optional-semicolons-1)\n\n<!-- tocstop -->\n\n## Abstract\n\nStatements, declarations, and definitions will terminate with either a semicolon\n(`;`) or a close curly brace (`}`). Semicolons are never optional.\n\nFor example, with a semicolon, `x = x + 2;` or `class C;`. With a close curly\nbrace, `for ( ... ) { ... }`, or `class C { ...}`.\n\nThis does not affect any approved proposal; rather, it makes an important\nassumption explicit.\n\n## Problem\n\nStatements need some system for separation. There are two main options for this:\n\n1. Require semicolons to terminate statements.\n2. Automatically determine where statements terminate.\n    - Some languages, such as Python, define a syntax where a newline terminates\n      statements.\n    - Other languages, such as Javascript, require semicolons but define rules\n      for semicolon insertion.\n\nAlthough Carbon's design currently assumes semicolons are required, it hasn't\nbeen directly addressed by a proposal.\n\n## Background\n\n### Discussion in Carbon\n\nThis was discussed on leads issue\n[#1924: Semicolon](https://github.com/carbon-language/carbon-lang/issues/1924).\nSome rationale is provided there, stemming from discussion\n[#1739: Semicolon](https://github.com/carbon-language/carbon-lang/discussions/1739).\n\n### In other languages\n\n[This blog](https://pling.jondgoodwin.com/post/semicolon-inference/) provides a\nsimilar survey of multiple languages.\n\n#### Requiring semicolons\n\nIn C++, C#, and Java, semicolons are always required.\n\nIn Rust, semicolons are generally required, but may be omitted for an\n[implicit return](https://doc.rust-lang.org/std/keyword.return.html). Because\n[blocks are expressions](https://doc.rust-lang.org/reference/expressions/block-expr.html),\nthere are\n[ambiguities in expression statements](https://doc.rust-lang.org/reference/statements.html#expression-statements)\nbetween parsing as a standalone statement and parsing as part of an expression.\n\n#### Optional semicolons\n\nIn Python, a line is a\n[simple statement](https://docs.python.org/3/reference/simple_stmts.html), and\nparentheses are an idiomatic way to create multi-line statements. Semicolons may\nbe used to explicitly separate statements. For example:\n\n```python\nvalue = (\n  \"text\"\n)\na = 1; b = 2; c = 3\n```\n\nSwift allows some statements to wrap lines, although multiple statements on the\nsame line (`x = 1 x = 1`) require a semicolon. The detailed rules aren't\ndocumented so it's difficult to assess other than that Swift developers are\ngenerally happy with the results. Swift's\n[statements section](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/statements)\ndoesn't define statement boundaries, and the\n[grammar](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/summaryofthegrammar/)\ndocuments that line-breaks are treated as whitespace. However, there are\nobservable ways the behavior can lead to small mistakes; these may may often be\ncaught by the compiler, but will sometimes be missed. For example:\n\n```swift\n// One statement in Swift, but two in Python and Kotlin.\nvar x = 1\n      + 1\n// Two statements in Swift because of whitespace sensitivity. Second statement\n// is a compiler warning.\nvar x = 1\n      +1\n// Two calls, the second on the return value of the first.\nMake() ()\n// A single call followed by an empty tuple. Second statement is valid.\nMake()\n()\n```\n\nKotlin permits a newline to be used to terminate statements instead of a\nsemicolon. Kotlin's grammar\n[explicitly enumerates](https://kotlinlang.org/spec/syntax-and-grammar.html) all\nthe places where newlines can appear (see mentions of `NL` in the grammar), and\ndoesn't allow newlines in places where they would introduce ambiguity.\n\n```kotlin\n// This is unambiguously parsed as two statements, because\n// a newline is not permitted before a `+` operator.\nvar x = 1\n+ 1\n```\n\nIn JavaScript and TypeScript, semicolons are part of the formal syntax, and\nECMAScript provides\n[Automatic Semicolon Insertion (ASI)](https://tc39.es/ecma262/#sec-automatic-semicolon-insertion).\nNote ECMAScript also documents\n[Interesting Cases](https://tc39.es/ecma262/#sec-interesting-cases-of-automatic-semicolon-insertion)\nwhich may lead to confusion for developers.\n\nIn Go, semicolons are similarly part of the formal syntax, and\n[certain tokens cause a semicolon insertion](https://go.dev/ref/spec#Semicolons).\nThis is also used to enforce style, for example by requiring the opening `{` of\nan `if` body to be on the same line in order to avoid semicolon insertion.\n\n## Proposal\n\nAs described in the abstract, Carbon will require semicolons to terminate\nstatements and forward declarations.\n\nExamples with a semicolon include:\n\n-   Most statements, such as `Foo();` and `x = x + 2;`.\n-   `var` statements and declarations, such as `var x: i32 = 0;`\n-   Forward declarations, such as `class C;` or `fn Foo();`.\n\nExamples with a close curly brace include:\n\n-   Statement grammars that terminate with a curly brace, such as\n    `if ( ... ) { ... }` or `match ( ... ) { ... }`.\n-   Declarations that include a definition, such as `class C { ... }` or\n    `fn Foo() { ... }`.\n    -   This is partly in contrast with C++, which would requires a semicolon in\n        `class C { ... };`.\n\nCarbon's current design has been written assuming the above; this is making\nrequiring semicolons an explicit decision.\n\n## Rationale\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   We expect it to be easier to write tools that parse and operate on\n        source code if semicolons are required.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Requiring semicolons leaves open the most evolutionary paths; any\n        optional semicolon approach means the design would need to be more\n        thoughtful about handling ambiguities.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Semicolons are a\n        [visual aid](/docs/project/principles/low_context_sensitivity.md#visual-aids)\n        that reinforces statement termination, even though they might be viewed\n        as a nuisance to write or visually unnecessary for some developers.\n        -   Carbon weighs readability more heavily because of the expectation\n            that code will be read more often.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   The use of semicolons is expected to improve familiarity for C++\n        developers, even for developers who might prefer optional semicolons.\n\n## Alternatives considered\n\n### Optional semicolons\n\nSemicolons could be made optional. This would most likely be with an approach\nsimilar to Python, based mainly on newlines.\n\nAdvantages:\n\n-   Languages with optional semicolons are very popular. Python is either the\n    most, or the 2nd most, widely used programming language by most measures\n    ([1](https://pypl.github.io/PYPL.html)\n    [2](https://octoverse.github.com/2022/top-programming-languages)\n    [3](https://www.tiobe.com/tiobe-index/)).\n-   Echoes the direction of evolution in other languages.\n    -   For example, Swift and Kotlin are recently designed languages that make\n        semicolons optional in ways that work well for developers in practice.\n-   Compile-time validation and errors on no-op statements could be used to\n    detect some of the issues that arise with optional semicolons in Python and\n    JavaScript.\n    -   For example, TypeScript may improve the handling of ASI ambiguities by\n        [increasing detectability of mistakes](https://medium.com/@eugenkiss/dont-use-semicolons-in-typescript-474ccfe4bdb3).\n-   While optional semicolons seem to get fewer complaints, requiring semicolons\n    is likely to lead to ongoing friction due to the overall trend. This can be\n    seen for languages like Rust\n    ([1](https://github.com/rust-lang/rust/issues/27116)\n    [2](https://internals.rust-lang.org/t/make-some-separators-optional/4846)\n    [3](https://github.com/rust-lang/rfcs/issues/2583)\n    [4](https://users.rust-lang.org/t/why-semicolons/25074)) or C#\n    ([1](https://github.com/dotnet/roslyn/issues/5355)\n    [2](https://github.com/dotnet/csharplang/discussions/496)\n    [3](https://github.com/dotnet/csharplang/discussions/5655)).\n\nDisadvantages:\n\n-   Semicolons are a visual anchor for statement termination when scanning code.\n-   Requiring semicolons leaves more evolutionary paths available for Carbon.\n    This includes both syntactic changes without introducing ambiguity and\n    implicit returns as in Rust.\n    -   Although it's not clear Carbon will fully adopt implicit returns,\n        similar syntactic choices may arise for lambdas.\n-   Semicolons are a signal to the compiler about where statements were intended\n    to terminate, and can be used to provide better error detection as a\n    consequence.\n    -   For contrast, optional semicolons may lead to unintended statements.\n        While ASI's problems are\n        [documented](https://tc39.es/ecma262/#sec-automatic-semicolon-insertion),\n        we expect any optional semicolon approach will lead to some increase in\n        bugs that the compiler cannot detect, if only because fewer mistakes are\n        necessary in order to produce valid but incorrect code.\n-   Making code with no semicolons idiomatic may increase the \"strangeness\" for\n    C++ developers, who are the primary target for Carbon.\n\nSemicolons are expected to be a net benefit, as explained by the\n[rationale](#rationale).\n"
  },
  {
    "path": "proposals/p2687.md",
    "content": "# Termination algorithm for impl selection\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2687)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Non-type arguments](#non-type-arguments)\n    -   [Proof of termination](#proof-of-termination)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Measure complexity using type tree depth](#measure-complexity-using-type-tree-depth)\n    -   [Consider each type parameter in an `impl` declaration separately](#consider-each-type-parameter-in-an-impl-declaration-separately)\n    -   [Consider types in the interface being implemented as distinct](#consider-types-in-the-interface-being-implemented-as-distinct)\n    -   [Require some count to decrease](#require-some-count-to-decrease)\n    -   [Require non-type values to stay the same](#require-non-type-values-to-stay-the-same)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal replaces the termination algorithm for `impl` selection. The\nprevious algorithm relied on a recursion limit, which is counter to\n[our goal for predictability](/docs/design/generics/goals.md#predictability).\n\nThe replacement is to terminate if any `impl` lookup performed while considering\nan `impl` declaration depends transitively on the same `impl` declaration with a\n\"strict superset\" of the types in the query.\n\n## Problem\n\nConsider this `impl` declaration:\n\n```\ninterface I;\nimpl forall [T:! type where Optional(.Self) is I] T as I;\n```\n\nA type like `i32` is a valid value of `T`, and so implements `I`, if\n`Optional(i32)` implements `I`. This `impl` declaration could also possibly be\nused to give an implementation of `Optional(i32)` for interface `I`, but only if\nthere was an implementation of `Optional(Optional(i32))` for interface `I`. The\njob of the termination rule is to report an error instead of being caught in an\ninfinite loop in this situation.\n\nIdeally, a termination rule would identify the loop in a minimal way. This has a\nfew benefits, including reducing compile times and making error messages as\nshort and understandable as possible. One downside of the original recursion\nlimit rule is its tendency to only detect a problem after the loop had been\nrepeated many times. This problem is worse if the recursion limit is large.\n\nAnother concern with using a recursion limit is that refactorings that would\notherwise be legal can increase the depth of recursion, causing spurious\nfailures. The workaround for this and other spurious failures is to increase the\nrecursion limit. This makes the other problems with using a recursion limit\nworse.\n\nNote that determining whether a particular set of `impl` declarations terminates\nis\n[equivalent to the halting problem](https://sdleffler.github.io/RustTypeSystemTuringComplete/)\n(content warning: contains many instances of an obscene word as part of a\nprogramming language name), and so is undecidable in general. So any termination\nrule will have some false positives or spurious failures, where it reports an\nerror even though it would in fact complete if allowed to continue running. We\nwould like a criteria that correctly classifies the examples that arise in\npractice.\n\n## Background\n\nThe first termination rule was introduced in proposal\n[#920: Generic parameterized impls (details 5)](https://github.com/carbon-language/carbon-lang/pull/920),\nfollowing Rust and C++. The problems with using a recursion limit were\n[recognized at the time that proposal was written](https://github.com/carbon-language/carbon-lang/blob/f282bca20e41e2f8dc05881d9d6b38213d6c6c87/docs/design/generics/details.md#termination-rule),\nbut no alternative was known.\n\nAlternatives termination rules have since been discussed:\n\n-   in open discussion on\n    [2022-04-13](https://docs.google.com/document/d/1tEt4iM6vfcY0O0DG0uOEMIbaXcZXlNREc2ChNiEtn_w/edit#heading=h.cja3fkwzv9tr),\n    prompted by a question on\n    [#1088: Generic details 10: interface-implemented requirements](https://github.com/carbon-language/carbon-lang/pull/1088);\n    and\n-   in issue\n    [#2458: Infinite recursion during impl selection](https://github.com/carbon-language/carbon-lang/issues/2458),\n    which includes summaries of discussions including those on\n    [2023-02-07](https://docs.google.com/document/d/1gnJBTfY81fZYvI_QXjwKk1uQHYBNHGqRLI2BS_cYYNQ/edit?resourcekey=0-ql1Q1WvTcDvhycf8LbA9DQ#heading=h.9u2u6078figt).\n\nPR\n[#2602: Implement the termination algorithm for impl selection described in #2458](https://github.com/carbon-language/carbon-lang/pull/2602)\nimplements the termination rule of this proposal in Explorer.\n\n## Proposal\n\nWe replace the termination criteria with a rule that the types in the `impl`\nquery must never get strictly more complicated when considering the same `impl`\ndeclaration again. The way we measure the complexity of a set of types is by\ncounting how many of each base type appears. A base type is the name of a type\nwithout its parameters. For example, the base types in this query\n`Pair(Optional(i32), bool) impls AddWith(Optional(i32))` are:\n\n-   `Pair`\n-   `Optional` twice\n-   `i32` twice\n-   `bool`\n-   `AddWith`\n\nA query is strictly more complicated if at least one count increases, and no\ncount decreases. So `Optional(Optional(i32))` is strictly more complicated than\n`Optional(i32)` but not strictly more complicated than `Optional(bool)`.\n\nThis rule, when combined with\n[the acyclic rule](/docs/design/generics/details.md#acyclic-rule) that a query\ncan't repeat exactly, [guarantees termination](#proof-of-termination). This rule\nis expected to identify a problematic sequence of `impl` declaration\ninstantiations in a way that is easier for the user to understand. Consider the\nexample from before,\n\n```\ninterface I;\nimpl forall [T:! type where Optional(.Self) is I] T as I;\n```\n\nThis `impl` declaration matches the query `i32 impls I` as long as\n`Optional(i32) impls I`. That is a strictly more complicated query, though,\nsince it contains all the base types of the starting query (`i32` and `I`), plus\none more (`Optional`). As a result, an error can be given after one step, rather\nthan after hitting a large recursion limit. And that error can state explicitly\nwhat went wrong: we went from a query with no `Optional` to one with one,\nwithout anything else decreasing.\n\nNote this only triggers a failure when the same `impl` declaration is considered\nwith the strictly more complicated query. For example, if the declaration is not\nconsidered since there is a more specialized `impl` declaration that is\npreferred by the\n[type-structure overlap rule](/docs/design/generics/details.md#overlap-rule), as\nin:\n\n```\nimpl forall [T:! type where Optional(.Self) is I] T as I;\nimpl Optional(bool) as I;\n\n// OK, because we never consider the first `impl`\n// declaration when looking for `Optional(bool) impls I`.\nlet U:! I = bool;\n\n// Error: cycle with `i32 impls I` depending on\n// `Optional(i32) impls I`, using the same `impl`\n// declaration, as before.\nlet V:! I = i32;\n```\n\nThe rule is also robust in the face of refactoring:\n\n-   It does not depend on the specifics of how an `impl` declaration is\n    parameterized, only on the query.\n-   It does not depend on the length of the chain of queries.\n-   It does not depend on a measure of type-expression complexity, like depth.\n\n## Details\n\n### Non-type arguments\n\nFor non-type arguments we have to expand beyond base types to consider other\nkinds of keys. These other keys are in a separate namespace from base types.\n\n-   Values with an integral type use the name of the type as the key and the\n    absolute value as a count. This means integer arguments are considered more\n    complicated if they increase in absolute value. For example, if the values\n    `2` and `-3` are used as arguments to parameters with type `i32`, then the\n    `i32` key will have count `5`.\n-   Every option of a choice type is its own key, counting how many times a\n    value using that option occurs. Any parameters to the option are recorded as\n    separate keys. For example, the `Optional(i32)` value of `.Some(7)` is\n    recorded as keys `.Some` (with a count of `1`) and `i32` (with a count of\n    `7`).\n-   Yet another namespace of keys is used to track counts of variadic arguments,\n    under the base type. This is to defend against having a variadic type `V`\n    that takes any number of `i32` arguments, with an infinite set of distinct\n    instantiations: `V(0)`, `V(0, 0)`, `V(0, 0, 0)`, ...\n    -   A `tuple` key in this namespace is used to track the total number of\n        components of tuple values. The values of those elements will be tracked\n        using their own keys.\n\nNon-type argument values not covered by these cases are deleted from the query\nentirely for purposes of the termination algorithm. This requires that two\nqueries that only differ by non-type arguments are considered identical and\ntherefore are rejected by the acyclic rule. Otherwise, we could construct an\ninfinite family of non-type argument values that could be used to avoid\ntermination.\n\n### Proof of termination\n\nLet's call a (finite or infinite) sequence of type expressions \"good\" if no\nlater element is strictly more complex than an earlier element, and no type\nexpression is repeated. We would like to prove that any good sequence of type\nexpressions with a finite set of keys is finite.\n\nWe can restrict to good sequences that don't repeat any multiset of keys, since\nthere are only a finite number of types with a given multiset of keys. Proof: If\nnone of the types have a variadic parameter list, then there is at most one type\nfor every distinct permutation of base types. If some types are variadic, then\nwe can get a conservative finite upper bound by multiplying the number of\ndistinct permutations by the number of different possible arity combinations.\nThe number of arity combinations is finite since, ignoring non-type arguments,\nthe total arity must equal the number of base types in the type minus 1.\n\nThe proof of termination is by induction on the number `N` of distinct keys.\n\n-   If `N == 1`, then types map to a multiset of a single key, which can be\n    represented by the count of the number of times that key appears. That\n    number must be non-negative and decreasing in the sequence, and so the\n    length of the sequence is bounded by the value of the first element. So good\n    sequences with `N == 1` must be finite.\n-   Assuming that good sequences with `N` distinct keys must be finite, consider\n    a good sequence with `N+1` distinct keys. Its first element will be\n    represented by a non-negative integer `(N+1)`-tuple, `(i_0, i_1, ..., i_N)`.\n    Every element after that will be in at least one of the\n    `i_0 + i_1 + ... + i_N` hyperplanes (co-dimension 1) given by these\n    equations:\n    -   `x_0 = 0`, `x_0 = 1`, ..., `x_0 = i_0 - 1` (`i_0` different equations,\n        each defining a separate hyperplane)\n    -   `x_1 = 0`, `x_1 = 1`, ..., `x_1 = i_1 - 1`\n    -   ...\n    -   `x_N = 0`, `x_N = 1`, ..., `x_N = i_N - 1`\n-   Any point not in one of those hyperplanes has components all >= the first\n    element, and so can't be in the sequence if it is good.\n-   The restriction of the sequence to the subsequence in each of those\n    hyperplanes is finite, by the induction hypothesis.\n-   The sequence visits points in this finite union of finite sets without\n    repetition, and so must be finite.\n-   Conclusion: Any good sequence with `N+1` distinct keys is finite, completing\n    the induction.\n\nThis bound given by this construction is not completely tight, since there is\noverlap between the hyperplanes. It is tight once that overlap is taken into\naccount, though. We can construct sequences that reach the upper bound by\nvisiting the points in the union of the hyperplanes in descending order of their\nL1-norm (sum of the components).\n\nNote: The text of this argument was derived from comments on\n[issue #2458: Infinite recursion during impl selection](https://github.com/carbon-language/carbon-lang/issues/2458).\n\n## Rationale\n\nThis proposal advances these [Carbon goals](/docs/project/goals.md):\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    by improving the quality of diagnostics.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    since we've chosen alternatives that avoid introducing failures as the\n    result of refactorings, particularly those outside the files changed in the\n    refactoring.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    by having a relatively simple language rule, that is predictable when\n    authoring code, and allows independent modules to compose without triggering\n    errors.\n\n## Alternatives considered\n\n### Measure complexity using type tree depth\n\nWe\n[considered](https://github.com/carbon-language/carbon-lang/issues/2458#issuecomment-1371412985)\na rule which would ensure termination by forbidding the depth of the type tree\nin the query from increasing. This depth could either be measured in the query\nor in the values of types used to parameterize `impl` declaration. Either way,\nthis raises a concern that otherwise safe refactorings might trigger spurious\ntermination errors. Specifically, refactorings that replace a type, like\n`String`, with an alias to a parameterized type, like `BasicString(Char8)`,\ncould change the tree depths in `impl` declarations in files that were not part\nof the refactoring.\n\n### Consider each type parameter in an `impl` declaration separately\n\nInstead of measuring the complexity of the `impl` query as a whole, we\nconsidered measuring the complexity of the argument values of parameters in an\nindividual `impl` declaration. The advantage of this would be fewer spurious\nfailures due to the termination rule.\n\nWe decided against it because it is a more complex rule and it is sensitive to\nthe specifics of how `impl` declarations are parameterized. This raises concerns\nabout refactorings introducing termination rule failures. We did not want to\nincorporate this change without evidence that those spurious failures would be a\nproblem in practice.\n\n### Consider types in the interface being implemented as distinct\n\nInstead of measuring the complexity of the entire `impl` query together, we\ncould consider keys in the type and interface parts of the query to be in\ndistinct namespaces. This would reduce the spurious failures due to the\ntermination rule, but not as much as the previous alternative. It avoids the\nproblem of the previous alternative, since it is not sensitive to the specifics\nof how `impl` declarations are parameterized.\n\nWe are not choosing this alternative now since it is a more complicated rule to\nexplain. But we would consider this alternative in the future if we find it\nbeneficial in practice to support the additional cases this rule permits.\n\n### Require some count to decrease\n\nWe considered a rule that would forbid repeating the multiset of types. This\nwould simplify the termination argument. However, we thought it important to\nsupport `impl` declarations that effectively shuffled the terms around into some\ncanonical form, as in this example:\n\n```\nimpl forall [T:! I(Optional(.Self))] Optional(T) as I(T);\n```\n\nHere, `Optional(bool) impls I(bool)` if `bool impls I(Optional(bool))`. This\nrule can only be applied a finite number of times, and is something we imagine\nmight arise naturally, so it seemed good to support.\n\n### Require non-type values to stay the same\n\nWe considered different handling for\n[non-type argument values](#non-type-arguments) that did not have an integral or\nchoice type. The alternative rule required the value to stay constant. This led\nto\n[a number of edge cases](https://github.com/carbon-language/carbon-lang/pull/2687#discussion_r1151028867)\nto consider, like how to identify the same argument when the type constructor\nmay be called a different number of times. The rule we chose to use instead has\nthe advantages of being simpler and also accepting more cases. With the current\nrule, the value of those arguments may change freely, they just don't create\ndifferent type expressions for purposes of detecting termination.\n"
  },
  {
    "path": "proposals/p2759.md",
    "content": "# Defining the 0.1 language\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2759)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Narrowing the proposed milestone definitions to just 0.1 initially.](#narrowing-the-proposed-milestone-definitions-to-just-01-initially)\n    -   [Make a more incremental, less ambitious initial milestone.](#make-a-more-incremental-less-ambitious-initial-milestone)\n    -   [Skip the 0.1 milestone and aim for feature completeness.](#skip-the-01-milestone-and-aim-for-feature-completeness)\n\n<!-- tocstop -->\n\n## Abstract\n\nProvides a clear definition of our goals for the 0.1 Carbon language, and a\nconcrete feature-set that is expected to satisfy these goals.\n\nThe high level goal proposed for the 0.1 language is to reach an evaluation-MVP\n(Minimal Viable Product): it should be sufficiently complete to evaluate its\nsuitability specifically with respect to fitness as a C++ successor language.\n\nThe features proposed for 0.1 language in turn focus on C++ interoperability and\na minimal subset of foundational aspects of the language.\n\nBeyond the language itself, the other project features and milestones proposed\nfocus on enabling evaluation of the language design and interoperating with C++\nin practice.\n\n## Problem\n\nThe initial set of concrete goals for the Carbon project have focused on\nestablishing the project itself (governance, evolution, community,\ninfrastructure, etc.) and exploratory work on both the language design and\nimplementation.\n\nThe project is now reasonably healthy and executing effectively in the open, and\nwe've made enough exploratory progress on both design and implementation that we\nneed to pick a much more specific target to prioritize further work effectively.\n\nThe obvious next goal, as outlined in our 2023 roadmap, is to prepare Carbon for\ndetailed and in-depth evaluation by potential users to see if it could\npotentially meet their needs for a C++ successor language. While some aspects of\nour potential value proposition can be considered abstractly, many of the hard\nquestions around \"will it work with my code?\" and \"how well will it work?\" need\ndirect evaluation to gain confidence.\n\nWe need to prioritize a specific set of features and milestones that are\nsufficient for this evaluation. Once this 0.1 language is \"done\" we can start\nadvocating for in-depth evaluation.\n\n## Background\n\n-   [Carbon's 2023 roadmap](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/roadmap.md)\n\n## Proposal\n\nWe suggest a set of initial milestones for the Carbon project with version\nnumbers to make them easy to talk about. For each milestone, we try to outline\nwhat the theme is, provide some concrete goals that should be addressed, and a\nlist of concrete features we expect to be complete.\n\nWhile the proposal only suggests three milestones initially, it isn't precluding\nadding additional milestones when and where they make sense as the project\nprogresses.\n\nThis proposal is suggesting a concrete and near-complete set of features for the\nfirst milestone. While this list may be updated based on new information, we are\nreasonably confident in its completeness. However, subsequent milestones are\nintentionally left incomplete and open-ended. They will be filled in as they get\ncloser. The intent in having them here is to allow us to explicitly defer things\nto later milestones without leaving them out entirely in cases where there is\nspecific interest in knowing when a major feature is expected.\n\n**Summary of proposed milestones:**\n\n-   \"0.1\" -- the MVP (Minimum Viable Product) language for the _evaluation_ of\n    Carbon by C++ community and developers.\n-   \"0.2\" -- feature complete for initial users to finish their evaluation and\n    the project to conclude its experiment\n-   \"1.0\" -- the result of a successful experiment and production-ready\n\nOne important detail is that a core goal of Carbon is to be a language prepared\nfor on-going evolution. This means that even if Carbon gets to 1.0, that isn't\nexpected to be a _final_ version in any sense, nor is any version expected to be\nfinal. Carbon should continue to evolve and develop going forward, and a\ncomprehensive plan for that is\n[part of our later milestones](/docs/project/milestones.md#features-explicitly-deferred-beyond-02).\n\n## Details\n\nThis proposal adds a [milestones](/docs/project/milestones.md) document to the\nCarbon project with the full details of the initial milestones.\n\n## Rationale\n\nThis proposal is advancing Carbon's goal for the community and culture, and\non-going language evolution:\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   We need to engage the Carbon community and the broader C++ community in\n        evaluating the Carbon experiment, and this proposal identifies concrete\n        steps we expect to take in order to ensure we can do this.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Clearly define milestones help set direction and make language evolution\n        effective. These milestones will provide that directional clarity for\n        Carbon and markers where we can measure how effectively evolution is\n        proceeding.\n\n## Alternatives considered\n\n### Narrowing the proposed milestone definitions to just 0.1 initially.\n\nWhile this would narrow the scope of the proposal and remove some of the more\nvague aspects, it would make it difficult for readers to understand when\nsomething is missing entirely versus when it is merely deferred for a later\nmilestone.\n\nWe also expect that explicitly deferring things in this way will make it easier\nto focus our energy and efforts on the next milestone by avoiding distractions\nof features that _might_ be interesting absent that deferral.\n\n### Make a more incremental, less ambitious initial milestone.\n\nThe initial milestone currently proposed is relatively ambitious, and much\nlarger than most programming language MVPs. Carbon could have a much less\naggressive initial milestone and hit it both sooner and with higher confidence.\n\nUnfortunately, a more incremental milestone doesn't seem to add much value due\nto the inherent goal of evaluating Carbon _in the context of C++ as it exists_.\nThat context forces us to have a much larger initial feature set in order to not\nend up in somewhat of an \"apples versus oranges\" comparison where the feature\nsets are so different as to thwart any attempt at in-depth comparison and\nevaluation.\n\n### Skip the 0.1 milestone and aim for feature completeness.\n\nWe could have fewer milestones overall and aim for the more ambitious goal. We\nknow that 0.1 will be insufficient to finish most real evaluations of the Carbon\nexperiment, and we might waste time putting it out and then iterating towards\n0.2.\n\nHowever, in general software and project planning is not hindered by having more\nincremental milestones. If anything, having more incremental milestones is often\nuseful for staying focused and making rapid progress. Moreover, we expect to be\nable to parallelize a reasonably large amount of time during the initial\nevaluation with completing 0.2. By putting 0.1 out first we hope to\nsignificantly reduce the latency on getting initial feedback from users on\nwhether the Carbon experiment is making sense for their use.\n"
  },
  {
    "path": "proposals/p2760.md",
    "content": "# Consistent `class` and `interface` syntax\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2760)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Class inheritance](#class-inheritance)\n    -   [Class implementing an interface](#class-implementing-an-interface)\n    -   [Class conditional implementation](#class-conditional-implementation)\n    -   [Adapters](#adapters)\n    -   [Interfaces](#interfaces)\n-   [Future work: mixins](#future-work-mixins)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use `extends` instead of `extend`](#use-extends-instead-of-extend)\n    -   [Allow interfaces to `require` another interface without writing `Self impls`](#allow-interfaces-to-require-another-interface-without-writing-self-impls)\n    -   [Allow other kinds of `where` clauses after `require`](#allow-other-kinds-of-where-clauses-after-require)\n    -   [Continue to use `impl as` for interface requirements](#continue-to-use-impl-as-for-interface-requirements)\n    -   [Continue to use `adapter` or `adaptor` instead of `adapt`](#continue-to-use-adapter-or-adaptor-instead-of-adapt)\n    -   [Use some other syntax for extending adapters](#use-some-other-syntax-for-extending-adapters)\n    -   [Continue to have some term for \"external\" or non-extended implementations](#continue-to-have-some-term-for-external-or-non-extended-implementations)\n    -   [More direct support for conditionally implementing internal interfaces](#more-direct-support-for-conditionally-implementing-internal-interfaces)\n    -   [Use `external` consistently instead of `extend`](#use-external-consistently-instead-of-extend)\n    -   [Use `mix` keyword for mixins](#use-mix-keyword-for-mixins)\n    -   [Allow more control over access to mixins](#allow-more-control-over-access-to-mixins)\n    -   [List base class in class declaration](#list-base-class-in-class-declaration)\n\n<!-- tocstop -->\n\n## Abstract\n\nUpdate syntax of `class` and `interface` definitions to be more consistent.\nConstructs that add names to the class or interface from another definition are\nalways prefixed by the `extend` keyword.\n\nImplements the decisions in:\n\n-   [#995: Generics external impl versus extends](https://github.com/carbon-language/carbon-lang/issues/995),\n-   [#1159: adaptor versus adapter may be harder to spell than we'd like](https://github.com/carbon-language/carbon-lang/issues/1159),\n-   [#2580: How should Carbon handle conditionally implemented internal interfaces](https://github.com/carbon-language/carbon-lang/issues/2580),\n    and\n-   [#2770: Terminology for internal and external implementations](https://github.com/carbon-language/carbon-lang/issues/2770).\n\n## Problem\n\nClasses and adapters, prior to this proposal, use `impl` to say that an\ninterface is\n[implemented internally](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/terminology.md#internal-impl),\nwhich means that the names that are members of the interface are included as\nnames of the class. The keyword `external` is added to indicate the names should\nnot be included. Interfaces and named constraints, in contrast, use `impl` to\nmean another interface is required, but its names are not included. Instead, to\ninclude the names, the `extends` keyword used instead of `impl`.\n\n| Include names:            | Yes       | No              |\n| ------------------------- | --------- | --------------- |\n| `class`, `adapter`        | `impl`    | `external impl` |\n| `interface`, `constraint` | `extends` | `impl`          |\n\nIn the time since this syntax has been introduced, we have found `external` in\nparticular easy to accidentally omit.\n\nIn addition to resolving this inconsistency, it would be an advantage if readers\nof a class could quickly scan the definition to identify other places to look\nfor members that contribute to the class' API.\n\n## Background\n\nThese proposals that defined the syntax for these entities that are being\nmodified:\n\n-   [#553: Generics details part 1](https://github.com/carbon-language/carbon-lang/pull/553)\n    defined the syntax for classes implementing interfaces, internally or\n    externally, and the syntax for named constraints (then \"structural\n    interfaces\") and interfaces requiring or extending other interfaces.\n-   [#731: Generics details 2: adapters, associated types, parameterized interfaces](https://github.com/carbon-language/carbon-lang/pull/731)\n    defined the syntax for adapters and extending adapters.\n-   [#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084)\n    allowed forward declaration of implementations, so internal `impl`\n    declarations may appear outside of a class definition, and `external impl`\n    declarations may appear inside.\n-   [#777: Inheritance](https://github.com/carbon-language/carbon-lang/pull/777)\n    defined the syntax for a class to extend a base class.\n\nNo proposal so far has defined how forward declarations work for classes. The\nrule used for forward `interface`, `constraint`, and `impl` declarations is that\nthe declaration part of the definition is everything up to the opening `{` of\nthe definition body. See\n[the forward declaration section of the Generics details design doc](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#forward-declarations-and-cyclic-references)\nadded in proposal\n[#1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084).\n\nThis proposal incorporates the decisions made in these question-for-leads\nissues:\n\n-   [#995: Generics external impl versus extends](https://github.com/carbon-language/carbon-lang/issues/995),\n-   [#1159: adaptor versus adapter may be harder to spell than we'd like](https://github.com/carbon-language/carbon-lang/issues/1159),\n-   [#2580: How should Carbon handle conditionally implemented internal interfaces](https://github.com/carbon-language/carbon-lang/issues/2580),\n    and\n-   [#2770: Terminology for internal and external implementations](https://github.com/carbon-language/carbon-lang/issues/2770).\n\nSome of thinking around the resolution of #995 was documented in\n[issue #2293: reconsider syntax for internal / external implementation of interfaces](https://github.com/carbon-language/carbon-lang/issues/2293),\nwhich was closed as a duplicate of #995.\n\nIn addition to modifying syntax from previous proposals,\n[#995](https://github.com/carbon-language/carbon-lang/issues/995) also gives a\nsyntax for using a mixin in a class. Mixins are described as a use case in\n[#561: Basic classes: use cases, struct literals, struct types, and future work](https://github.com/carbon-language/carbon-lang/pull/561),\nbut have not been added in any proposal. Question-for-leads issue\n[#1000: Mixins: base classes or data members?](https://github.com/carbon-language/carbon-lang/issues/1000),\ndoes state that a class will treat a mixin syntactically like a data member\ninstead of a base class.\n\n## Proposal\n\nAny declaration that adds the names from another entity shall start with the\n(new) `extend` keyword. This includes:\n\n-   _Inheritance_: A class now indicates that it inherits from a base class\n    using an\n\n    > `extend base:` _base-class_ `;`\n\n    declaration inside the class definition. The `extend` keyword indicates that\n    the API of the base class is included.\n\n-   _Adapters_: Adapter types are now declared as a class, with an\n\n    > [ `extend` ] `adapt` _adapted-class_ `;`\n\n    declaration inside the definition, as an alternative to a base class\n    declaration. The optional `extend` keyword controls whether the API of the\n    adapted class is included.\n\n-   _Implementations_: Internal implementations are marked with the `extend`\n    keyword on the declaration inside the class. Only the declaration inside the\n    class, which is required for internal implementations, uses the `extend`\n    keyword. External implementations are not marked.\n\n    > [ `extend` ] `impl` ...\n\n-   _Interfaces_: The `extends` declaration in an interface definition is\n    replaced by an `extend` declaration, with no change except removing the `s`\n    from the end of the keyword. Other interface requirements are now written\n    using a `require` declaration, with a constraint that matches a `where`\n    clause. This means\n\n    > `impl as` _required-interface_ `;`\n\n    will now be written as\n\n    > `require Self impls` _required-interface_ `;`\n\n    and\n\n    > `impl` _type-expression_ `as` _required-interface_ `;`\n\n    will now be written as\n\n    > `require` _type-expression_ `impls` _required-interface_ `;`\n\n    For now, only the `impls` forms of `where` clauses are permitted after\n    `require`.\n\nIn summary:\n\n| Before                          | After                                   |\n| ------------------------------- | --------------------------------------- |\n| `class D extends B { ... }`     | `class D { extend base: B; ... }`       |\n| `external impl C as Sub;`       | `impl C as Sub;`                        |\n| `class C { impl as Sortable; }` | `class C { extend impl as Sortable; }`  |\n| `adapter A for C { ... }`       | `class A { adapt C; ... }`              |\n| `adapter A extends C { ... }`   | `class A { extend adapt C; ... }`       |\n| `interface I { impl as J; }`    | `interface I { require Self impls J; }` |\n| `interface I { impl T as J; }`  | `interface I { require T impls J; }`    |\n| `interface I { extends J; }`    | `interface I { extend J; }`             |\n\nNone of `adapter`, `extends`, `external` will continue to be keywords. To match\nthese changes, \"internal implementations\" will now be referred to as \"extended\nimplementations,\" and we will no longer use \"external\" to refer to\nimplementations.\n\nIn addition, we drop the syntax for conditionally implemented internal\ninterfaces. Instead, an external interface implementation can be combined with\naliases to the members of the interface.\n\n## Details\n\n### Class inheritance\n\nWhat was previously written:\n\n```\nbase class B;\nclass D extends B;\nclass D extends B {\n  ...\n}\n```\n\nis now written:\n\n```\nbase class B;\nclass D;\nclass D {\n  extend base: B;\n  ...\n}\n```\n\nAn extend base class declaration may appear in the body of a class definition,\nand has this form:\n\n> `extend` `base` `:` _type-expression_ `;`\n\nThe `extend base: B;` declaration must appear before any other data member\ndeclaration, including any [mixin declaration](#future-work-mixins), once those\nare added. This reflects both the importance of the information, and the fact\nthat the base subobject appears first in the memory layout of objects.\n\nNote that `base` is already a keyword, for example used in `base class`\ndeclarations. The colon in `base: B` is to indicate that `base` acts like a data\nmember for\n[purposes of initialization](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/classes.md#constructors).\n\nThis makes the part of a class definition that is used in forward declarations\nbe exactly the part before the curly braces (`{`...`}`). Before this proposal,\nclass forward declarations would exclude the `extends` clause from the first\nline of the class definition. This change makes classes consistent with other\nentities that may be forward declared.\n\n### Class implementing an interface\n\nWhat was previously written:\n\n```\ninterface Sortable;\ninterface Add;\ninterface Sub;\nclass C;\n\n// Forward declaration says whether external.\nimpl C as Sortable;\nexternal impl C as Add;\n\nclass C {\n  // Internal impl contributes to the API.\n  impl as Sortable;\n\n  // External impl of an operator.\n  external impl as Add;\n}\n\n// External impl of an operator.\nexternal impl C as Sub;\n\n// Definition of `impl` declared earlier.\nimpl C as Sortable { ... }\nexternal impl C as Add { ... }\n```\n\nis now written:\n\n```\ninterface Sortable;\ninterface Add;\ninterface Sub;\nclass C;\n\n// Forward declaration same whether extended or not.\nimpl C as Sortable;\nimpl C as Add;\n\nclass C {\n  // Extended impl contributes to the API.\n  extend impl as Sortable;\n\n  // (Non-extended) Impl of an operator.\n  impl as Add;\n}\n\n// (Non-extended) Impl of an operator.\nimpl C as Sub;\n\n// Definition of `impl` declared earlier.\nimpl C as Sortable { ... }\nimpl C as Add { ... }\n```\n\nWhether an interface is extended or not is now only reflected in its declaration\ninside the class body, not in any declaration or definition outside.\n\nAn `impl` declaration, with this proposal, must have one of these two forms:\n\n-   Without an `extend` keyword prefix, used for non-extended `impl`\n    declarations and for all `impl` declarations outside of a class body:\n\n    <!-- prettier-ignore -->\n    > `impl` [`forall` `[` _deduced-parameters_ `]`] [_type-expression_] `as`\n    > _facet-type-expression_ (`;`|`{` _impl-body_ `}`)\n\n    The _type-expression_ is required outside of a class body, otherwise it\n    defaults to `Self`.\n\n-   With an `extend` keyword prefix, to indicate this implementation is\n    extended, only in a class body:\n\n    > `extend` `impl` `as` _facet-type-expression_ (`;`|`{` _impl-body_ `}`)\n\n    Note that this form does not allow either a `forall` clause nor a\n    _type-expression_ before the `as` keyword. This reflects the restriction\n    that\n    [wildcard `impl` declarations must never be extended (formerly: \"always be external\")](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#wildcard-impl-declarations),\n    and that this proposal removes support for\n    [extended (formerly \"internal\") conditional implementation](#class-conditional-implementation).\n\n### Class conditional implementation\n\nWe remove direct support for conditionally implemented extended (formerly\n\"internal\") interfaces, called\n[conditional conformance](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#conditional-conformance).\nWe can work around this restriction by using an non-extended interface\nimplementation and aliases to the members of the interface.\n\nWhat was previously written:\n\n```\ninterface Printable {\n  fn Print[self: Self]();\n}\n\nclass Vector(T:! type) {\n  // ...\n\n  impl forall [U:! Printable] Vector(U) as Printable {\n    fn Print[self: Self]();\n  }\n}\n```\n\nis now written:\n\n```\ninterface Printable {\n  fn Print[self: Self]();\n}\n\nclass Vector(T:! type) {\n  // ...\n  alias Print = Printable.Print;\n}\n\nimpl forall [U:! Printable] Vector(U) as Printable {\n  fn Print[self: Self]();\n}\n```\n\nThe way this works is that `Vector.Print` is equivalent to\n`Vector.(Printable.Print)`, which may or may not be defined. The name\n`Vector.Print` can no longer be conditional, and the meaning of that name is\nfixed. However, the implementation of `Printable` for `Vector(T)` may not exist\nfor some types `T`.\n\n### Adapters\n\nWhat was previously written:\n\n```\nclass C;\n// Forward declarations of adapters.\nadapter A for C;\nadapter E extends C;\n\n// Definitions of an adapter.\nadapter A for C {\n  ...\n}\n// Definition of an extending adapter.\nadapter E extends C {\n  ...\n}\n```\n\nis now written:\n\n```\nclass C;\n// Forward declarations of adapters.\nclass A;\nclass E;\n\n// Definitions of an adapter.\nclass A {\n  adapt C;\n  ...\n}\n// Definition of an extending adapter.\nclass E {\n  extend adapt C;\n  ...\n}\n```\n\nNote:\n\n-   Adapters are now a special case of classes, not a distinct top-level\n    declaration.\n-   Classes with `adapt` still must not contain anything that was previously\n    forbidden for adapters: no fields, no base class, no virtual methods, no\n    implementations of virtual methods, and so on.\n-   The `adapt` declaration must appear before\n    [mixin declarations](#future-work-mixins), if any.\n-   The syntax for an `adapt` declaration inside a class body is:\n\n    > [`extend`] `adapt` _type-expression_ `;`\n\n### Interfaces\n\nWhat was previously written:\n\n```\ninterface A { let T:! Type; }\ninterface B { let U:! Type; }\ninterface C(V:! Type) { }\n\ninterface I {\n  // `A`'s interface is incorporated into `I`:\n  extends A where .T = i32;\n\n  // No impact on `I`s interface, but an\n  // implementation must exist:\n  impl as B where .U = i32;\n\n  // Implementation must exist on another type:\n  impl i32 as C(Self);\n}\n```\n\nis now written:\n\n```\ninterface A { let T:! Type; }\ninterface B { let U:! Type; }\ninterface C(V:! Type) { }\n\ninterface I {\n  // `A`'s interface is incorporated into `I`:\n  extend A where .T = i32;\n\n  // No impact on `I`s interface, but an\n  // implementation must exist:\n  require Self impls B where .U = i32;\n\n  // Implementation must exist on another type:\n  require i32 impls C(Self);\n}\n```\n\nNotes:\n\n-   The same change applies to named constraints, and is intended to be used in\n    the future for named predicates used as template constraints.\n-   One syntax for constraints in either `where` clauses or `require`\n    declarations.\n-   Want to open up the syntax to expressing more general constraints.\n-   Syntax for a `require` declaration in an interface or named constraint:\n\n    > `require` _type-expression_ `impls` _facet-type-expression_ `;`\n\n    As\n    [with `impl`...`as` declarations before](/docs/design/generics/details.md#interface-requiring-other-interfaces-revisited),\n    a `require` declaration must use `Self`, either to the left or right of\n    `impls`. Note that `require` only supports this subset of `where` clause\n    expressions. Adding other kinds of constraints is future work.\n\n-   Syntax for an `extend` declaration in an interface or named constraint:\n\n    > `extend` _facet-type-expression_ `;`\n\n## Future work: mixins\n\nMixins have not been defined in a proposal so far. However, part of the process\nof resolving\n[issue #995](https://github.com/carbon-language/carbon-lang/issues/995) was\ndeciding on a syntax for including a mixin in a class. This was done in order to\nmake sure that class declarations that included names from another entity were\ntreated consistently, for example always starting with the `extend` keyword.\n\n```\n// Mixin declarations and definitions are\n// outside the scope of this proposal.\nmixin M1;\nmixin M2;\n\nclass C {\n  // Mixing in mixin M1\n  extend m: M1;\n\n  // Mixing in mixin M2. This member is not named.\n  // Initialized using `M2.MakeDefault()`.\n  extend _: M2 = M2.MakeDefault();\n\n  // Alternative to the above `M2` that uses a\n  // private name instead of no name:\n  extend private m2: M2;\n}\n```\n\nThe declaration that a class uses a mixin is called a \"mix\" declaration. The\nsyntax of a mix declaration is:\n\n<!-- prettier-ignore -->\n> `extend` [`private`|`protected`] (`_`|_id_) `:` _mixin-expression_ [`=`\n> _initializer-expression_] `;`\n\nThe _id_ part of the mix declaration defines the name assigned to that mixin\nsubobject. This name is may be used to access members of the mixin and to\ninitialize the mixin in a constructor for the class. The optional `private` or\n`protected` access specifier controls the access to this name.\n\nWith this proposal, base class declarations appear in the body of the class\ndefinition, like data members, so decision of whether mixins are more like base\nclasses or data members of issue\n[#1000: Mixins: base classes or data members?](https://github.com/carbon-language/carbon-lang/issues/1000)\nis less significant. Like base classes, the mix declaration syntax begins with\n`extend`. Like data members, a class may have multiple mix declarations and they\nmay be intermixed with field declarations. The layout of the memory of an object\nreflects the order of the declarations in the class body, defining the order of\nthe mixin and field subobjects.\n\n## Rationale\n\nThe main reason for the new syntax is consistency and simplification:\n\n-   The use of the `extend` keyword is the consistent way to mark what other\n    entities are consulted during name lookup.\n-   The `class` declaration is simplified by moving more into the definition\n    body.\n-   Making adapters a kind of class removes a kind of top-level declaration, a\n    simplification, and matches how base classes are declared, a consistency.\n-   Dropping the class conditional implementation is a simplification.\n\nThese consistency and simplification improvements help:\n\n-   ease the implementation of\n    [language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    by reducing the size of the language, and providing regularities\n    implementations can use to reuse code or more easily identify relevant parts\n    of the code for queries;\n-   make Carbon code\n    [easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n-   teaching the language, since there is less to learn.\n\n## Alternatives considered\n\n### Use `extends` instead of `extend`\n\nKeyword `extend` was chosen over `extends` to parallel `impl`, a declaration,\ninstead of `impls`, a binary predicate, decided in\n[issue #2495](https://github.com/carbon-language/carbon-lang/issues/2495) and\naccepted in\n[proposal #2483](https://github.com/carbon-language/carbon-lang/pull/2483).\n\nWe chose to use `require` instead of `requires` and `adapt` instead of `adapts`\nfor the same consistency.\n\n### Allow interfaces to `require` another interface without writing `Self impls`\n\nWe\n[considered](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1418387971)\nallowing `interface I { require J; }` as a short-hand for\n`interface I { require Self impls J; }`. This is something we would consider\nadding in the future based on experience with the current approach, but for now\nwe wanted to maintain consistency with the constraint syntax of `where` clauses.\n\nThis decision and rationale was described in\n[this comment in #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1416659207).\n\n### Allow other kinds of `where` clauses after `require`\n\nThe decision on\n[#995](https://github.com/carbon-language/carbon-lang/issues/995), see\n[1](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1439336141)\nand\n[2](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1496781087),\ncalled for the same constraint syntax after `require` as we are using after\n`where`. This proposal _only_ allows `impls` clauses after `require`, since\nthere were concerns about the other kinds of clauses:\n\n-   We had questions about what syntax to use to refer to members of the\n    interface, such as associated types, to constrain them. Must they start with\n    `Self.` or `.`? See\n    [this comment thread on #2760](https://github.com/carbon-language/carbon-lang/pull/2760#discussion_r1213789364).\n-   Modifying the constraints on an associated type after the declaration for\n    that associated type was not something we clearly wanted to allow. Allowing\n    that would mean having to read the whole interface definition body to\n    understand a single member.\n-   It was unclear if rewrite constraints (using `=` instead of `==`), would be\n    allowed in a `require` declaration, and if they were, whether they would be\n    changed into equality constraints (as if they were declared using `==`). See\n    [this comment on #2760](https://github.com/carbon-language/carbon-lang/pull/2760#discussion_r1213791304).\n-   It would have provided more different ways of declaring equivalent\n    interfaces. This concern was raised\n    [in this comment on #2760](https://github.com/carbon-language/carbon-lang/pull/2760#discussion_r1214571215).\n\nFor now, we only needed to replace the existing uses of `impl as` constraints,\nwhich had none of these concerns. We did not want to block this proposal, so we\nmade sure the `require` clauses were consistent with that _subset_ of `where`\nclauses.\n\n### Continue to use `impl as` for interface requirements\n\nThere were a few reasons motivating the change to use the new `require`\ndeclarations in interfaces and named constraints, instead of using `impl as` to\nmatch how a type could satisfy that requirement. These mostly came down to some\nobserved breaks in the parallel structure between the requirement in interfaces\nand the satisfaction of that requirement in types.\n\n-   Whether an interface `I` extends or just requires another interface `J` is\n    independent of whether a type implementing `I` extends or just implements\n    `J`.\n-   If `R` requires interface `I`, the implementation of `R` for a type won't\n    have the implementation of `I` as a nested sub-block.\n-   With the change in\n    [#2173: Associated constant assignment versus equality](https://github.com/carbon-language/carbon-lang/pull/2173),\n    the behavior of `impl as` in interfaces is different from in classes with\n    respect to rewrites of associated types, motivating a change to make those\n    look more different.\n\nFurthermore, we had a desire to be able to express the full range of constraints\nin `where` clauses in named constraints, and we wanted the transformation from a\n`where` clause to a named constraint to be straightforward. We also wanted the\nsyntax for constraints to be the same between interfaces and named constraints,\nat least for all constraints that were allowed in both.\n\nThis was discussed in\n[#generics-and-templates on 2023-01-30](https://discord.com/channels/655572317891461132/941071822756143115/1069691751968817283)\nand in\n[issue #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1412478644).\n\n### Continue to use `adapter` or `adaptor` instead of `adapt`\n\nWe didn't want to allow both `adapter` and `adaptor`, since that adds complexity\nfor readers and tooling, but neither seemed clearly dominant enough in usage to\npick one over the other. By moving the declaration into the body of the class\ndefinition, we were able to switch from the noun form to the verb form of\n`adapt`, which doesn't have an alternate form in common usage. See\n[#1159: adaptor versus adapter may be harder to spell than we'd like](https://github.com/carbon-language/carbon-lang/issues/1159)\nfor the discussion.\n\nWe also considered using `adapts` in a class declaration, as in\n`class PlayableSong adapts Song { ... }`, see\n[this comment in #1159](https://github.com/carbon-language/carbon-lang/issues/1159#issuecomment-1316669416).\nThis would have also worked, but was not consistent with our resolution of\n[#995: Generics external impl versus extends](https://github.com/carbon-language/carbon-lang/issues/995).\n\n### Use some other syntax for extending adapters\n\nIn the\n[open discussion on 2023-02-27](https://docs.google.com/document/d/1gnJBTfY81fZYvI_QXjwKk1uQHYBNHGqRLI2BS_cYYNQ/edit?resourcekey=0-ql1Q1WvTcDvhycf8LbA9DQ#heading=h.9steyq834zuq),\nwe discussed some alternatives to `extend adapt` _adapted-class_ `;`:\n\n-   Adding `and` to make it read more like fluent English:\n\n    > `extend and adapt` _adapted-class_ `;`\n\n    However, this felt arbitrary and not compositional.\n\n-   Make the extending and adapting be separate declarations:\n\n    > `extend` _adapted-class_ `;` <br> `adapt` _adapted-class_ `;`\n\n    This felt too repetitive.\n\n-   Make the only way to make an extending adapter be trying to inherit from a\n    final base class\n\n    > `extend base:` _adapted-class_ `;`\n\n    However, this meant using the same syntax for two different things that\n    could only be distinguished by looking at the declaration of the adapted\n    class, which could be far away. It also would have meant making an extending\n    adapter of a non-final class much more cumbersome.\n\nUltimately, we decided that `extend adapt` would be the most compositional way\nof combining `extend` and `adapt`, so that is what users would expect. Reading\nlike natural English was not considered essential.\n\n### Continue to have some term for \"external\" or non-extended implementations\n\nThe fact that there were some different rules for external implementations was\nbrought up in\n[this post in #2770](https://github.com/carbon-language/carbon-lang/issues/2770#issuecomment-1509288478).\nHowever,\n[this reply](https://github.com/carbon-language/carbon-lang/issues/2770#issuecomment-1515522070)\npointed out those rules could be clearly stated in terms of where you are\nallowed to write `extend`. That same post made the convincing argument that to\nget the maximum benefit of the decision on\n[#995](https://github.com/carbon-language/carbon-lang/issues/995), we should\ntreat `extend` and `impl` as separate orthogonal concepts as much as possible.\n\n### More direct support for conditionally implementing internal interfaces\n\nWe considered two different ways of more directly supporting conditionally\nextending a class by an interface:\n\n-   Prior to this proposal, both name lookup and the implementation were\n    conditional on the same condition. This has the disadvantage of entangling\n    the concerns of name lookup and implementation, and was considered a complex\n    and difficult model.\n-   We also considered fully separating these features, and allowing a type to\n    separately extend its API with an interface and then only conditionally\n    implement that interface. This would allow name lookup to succeed\n    unconditionally, but in cases where the names were in fact not implemented\n    it would produce an error.\n\nBoth of these approaches would have required some support for expressing this in\nthe new syntax. None of the syntactic approaches we considered were found to be\nsatisfactory. By making name lookup never conditional, it made it much easier to\nhave a consistent marker for declarations that extended name lookup.\n\nUltimately, the alternative of not having a dedicated syntax to support this\ncase seemed the simplest in the short term, given the workaround of conditional\nexternal (non-extending) implementation paired with aliases that provide the\nname lookup, unconditionally. We can always add dedicated syntax later, given\nsufficient motivating information.\n\nThe options were considered in\n[#2580: How should Carbon handle conditionally implemented internal interfaces](https://github.com/carbon-language/carbon-lang/issues/2580).\n\n### Use `external` consistently instead of `extend`\n\nWe considered making \"extending name lookup\" the default and overriding that\ndefault with the `external` keyword. The argument for this option rested on it\nbeing more convenient to express conditional internal implementation, and wasn't\nseen as attractive once that feature was removed. In the discussion, we\ngenerally preferred marking additional places to consult in name lookup since\nthat was something we expected readers of the code to want to specifically look\nfor.\n\nThis option was proposed as the third option in the\n[original #995 question](https://github.com/carbon-language/carbon-lang/issues/995#issue-1085174338),\nand was considered in\n[this comment](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1006096692).\n\n### Use `mix` keyword for mixins\n\nWe considered a variety of different syntax options for using a mixin for a type\nin\n[this comment on #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1315948818).\nMany of them used the `mix` keyword, but we ultimately decided that `mix` was\nredundant with saying `extend`, which we wanted to be included with all\nconstructs extending the type's API by another entity.\n\n### Allow more control over access to mixins\n\nThere were three different aspects of mixins that we considered giving control\nover access:\n\n-   the inclusion of names exported by the mixin into the mixer class,\n-   the ability to cast between the mixin and the mixer class types, and\n-   the ability to use the name of the mixin given by the mixer class to access\n    members of the mixin.\n\nThis was particularly relevant when we were considering separate declarations\nfor declaring the mixin member and the API extension\n([1](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1315948818),\n[2](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1317598076)).\n\nThis approach had the problem that the common case for mixins was extending the\nAPI, which would not have been the default. The only examples we had where the\nmixer class would not want to include the names exported by the mixin were cases\nwhere the mixin had nothing to export. This led to\n[the position](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1325746398)\nthat the mixin would control which of its member would be included into the\nmixer class' API -- that is the mixin would \"inject\" members rather than\n\"export\" them and leave it up to the mixer class to import them.\n\nWe had concerns that there might be name conflicts, but we thought those might\nbe handled by some other mechanism. This is being considered in\nquestion-for-leads issue\n[#2745: Name conflicts beyond inheritance](https://github.com/carbon-language/carbon-lang/issues/2745).\n\nWe wanted mixin member names to behave consistently like other class member\nnames, and so default to public but can have a `private` modifier to make\nprivate, following\n[#665: `private` vs `public` _syntax_ strategy, as well as other visibility tools like `external`/`api`/etc.](https://github.com/carbon-language/carbon-lang/issues/665).\nWe decided to put the `private` keyword _between_ the `extend` keyword and the\nmember name for two reasons:\n\n-   to make it easier to scan for all uses of `extend` in a class, and\n-   to make it clearer that the `private` access control only applies to the\n    member name, not what the `extend` controls.\n\nWe did not see a use case for controlling the ability to cast between the mixin\nand the mixer class types separately from being able to access the name the\nmixin member of the mixin class. This was consistent with our desire to limit\ndeclarations to a single access control specifier per declaration, see\n[this update in #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1322892195).\n\n### List base class in class declaration\n\nBy moving the base class into the class body, we accomplished three things:\n\n-   made forward declarations shorter,\n-   made it possible to inherit from a type declared inside the body of the\n    class definition, and\n-   allowed greater consistency, all API extensions are now declarations in the\n    body of the class definition starting with `extend`.\n\nThis was decided in\n[this comment on #995](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1317598076).\n\nThis left open the question of what keyword introducer to use in base class\ndeclarations, since using `base` would cause an ambiguity with declaring a\nmember class that could be extended, as considered in\n[this comment](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1320614313).\nUltimately we avoided this problem by requiring base class declarations to\nalways begin with `extend`, not support any form of private or protected\ninheritance (see\n[this comment](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1325746398)),\nand not support any combination of an `extend` declaration with a member class\ndeclaration.\n"
  },
  {
    "path": "proposals/p2868.md",
    "content": "# Allow overlap with a `final impl` if identical\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2868)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Allow interfaces with member functions to compare equal](#allow-interfaces-with-member-functions-to-compare-equal)\n    -   [Mark associated constants as `final` instead of an `impl` declaration](#mark-associated-constants-as-final-instead-of-an-impl-declaration)\n    -   [Allow type inequality constraints](#allow-type-inequality-constraints)\n    -   [Prioritize a `final impl` over a more specific `impl` on the overlap](#prioritize-a-final-impl-over-a-more-specific-impl-on-the-overlap)\n\n<!-- tocstop -->\n\n## Abstract\n\nAllow an `impl` to overlap with a `final impl` if they agree on the overlap.\nAgreement is defined as all values comparing equal, and functions never\ncomparing equal. Implements the decision in question-for-leads\n[issue #1077: find a way to permit impls of CommonTypeWith where the LHS and RHS type overlap](https://github.com/carbon-language/carbon-lang/issues/1077).\n\n## Problem\n\nThe\n[current design](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/if.md#same-type)\nincludes a `final impl` declaration for the `CommonTypeWith(T)` interface:\n\n```carbon\nfinal impl forall [T:! type]\n    T as CommonTypeWith(T)\n    where .Result = T {}\n```\n\n[Marking an `impl` declaration `final`](/docs/design/generics/details.md#final-impl-declarations),\nprevents any overlapping implementation that would be considered more specific\nby the [overlap rule](/docs/design/generics/details.md#overlap-rule). This\nincludes cases where the overlap is harmless, such as:\n\n```carbon\nimpl forall [U:! type, T:! CommonTypeWith(U)]\n    Vec(T) as CommonTypeWith(Vec(U))\n    where .Result = Vec(T.Result) {}\n```\n\nThis is an implementation we would like to define, along with a number of\nsimilar cases. And this `impl` declaration doesn't actually conflict with the\nprevious `final impl` because the value of `Result`, the only member of the\n`CommonTypeWith` interface, agrees where the two implementations overlap.\n\n## Background\n\nThe `CommonTypeWith(T)` interface and `final impl` above were introduced in\n[proposal #911: Conditional expressions](https://github.com/carbon-language/carbon-lang/pull/911).\n\n[Proposal #983: Generics details 7: final impls](https://github.com/carbon-language/carbon-lang/pull/983)\nintroduced and defined the rules for `final impl` declarations.\n\nThe overlap rule was introduced in\n[proposal #920](https://github.com/carbon-language/carbon-lang/pull/920).\n\nThere were a number of different resolutions for this problem considered in\nquestion-for-leads\n[issue #1077: find a way to permit impls of CommonTypeWith where the LHS and RHS type overlap](https://github.com/carbon-language/carbon-lang/issues/1077).\nThis proposal codifies the resolution of that issue.\n\n## Proposal\n\nWe allow an `impl` declaration to overlap with a `final impl` declaration if it\nagrees on the overlap. Since we do not require the compiler to compare the\ndefinitions of functions, agreement is only possible for interfaces without any\nfunction members. The details about how the intersection is computed and how\ntemplated `impl` declarations are handled have been added to\n[the section on `final` impl declarations in the generics design doc](/docs/design/generics/details.md#final-impl-declarations).\n\n## Rationale\n\nThis proposal is intentionally keeping the language small by making a simple\nrule that addresses the only identified use case and nothing more. This benefits\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n\nby relying on Carbon's commitment to\n[software and language evolution](/docs/project/goals.md#software-and-language-evolution)\nto update our approach as needed, rather then trying to proactively address\nconcerns ahead of time.\n\n## Alternatives considered\n\n### Allow interfaces with member functions to compare equal\n\nThere are some specific cases where the compiler can verify that two functions\nare the same without having to compare their definitions. For example, two\nimplementations that don't implement a function and instead inherit the default\nfrom the interface could be considered equal. This creates an evolution hazard,\nthough, that copying the definition from the interface into the implementation\nmeans that the interface could now compare not equal without any change in\nbehavior. For now, the simple rule that we don't compare functions at all is\nsufficient for our identified [use case](#problem). This is something we would\nreconsider given new use cases.\n\n### Mark associated constants as `final` instead of an `impl` declaration\n\nThe biggest benefit from knowing that an `impl` declaration won't be specialized\nis being able to use the values of the associated constants, particularly\nassociated types. Thus, it is natural to focus on associated constants, which\ndon't have the same concerns as functions with comparing for equality.\n\nHowever, for the [motivating use case](#problem), we would still need this\nproposal, just restricted to the associated constants that are declared `final`.\nSo we may still add this feature, if it is warranted by demand, but we did not\nyet have that justification. This is essentially the same position as when this\nfeature was considered in\n[proposal #983](/proposals/p0983.md#final-associated-constants-instead-of-final-impls).\n\n### Allow type inequality constraints\n\nAnother approach would be to provide type inequality constraints so the more\nspecialized implementation could exclude the overlapping cases. This has some\ndownsides:\n\n-   The more specialized implementation has to be aware of the `final` impl to\n    specifically exclude it. This would add extra steps to the development\n    process since this discovery is likely to occur as the result of a failed\n    compile.\n-   The more specialized implementation becomes more verbose, with extra\n    conditions that don't add any value.\n-   The current approach for establishing whether two types are equal doesn't in\n    general provide a way to show two types are not equal in generic code.\n\n### Prioritize a `final impl` over a more specific `impl` on the overlap\n\nThis was a possible fix, but was seen as a bigger change that we didn't yet have\njustification for.\n"
  },
  {
    "path": "proposals/p2875.md",
    "content": "# Functions, function types, and function calls\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2875)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Functions and function types](#functions-and-function-types)\n    -   [Bound methods](#bound-methods)\n    -   [Call syntax](#call-syntax)\n    -   [Direct calls](#direct-calls)\n    -   [Generic callable parameters](#generic-callable-parameters)\n    -   [Function types and `Call`](#function-types-and-call)\n    -   [Overloaded call operator](#overloaded-call-operator)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Signature-based function types](#signature-based-function-types)\n    -   [Make direct and indirect calls behave uniformly](#make-direct-and-indirect-calls-behave-uniformly)\n-   [Future work](#future-work)\n    -   [Overloading](#overloading)\n    -   [Overloading on expression category and phase](#overloading-on-expression-category-and-phase)\n    -   [Variadics](#variadics)\n    -   [Lambdas](#lambdas)\n    -   [Function pointers](#function-pointers)\n\n<!-- tocstop -->\n\n## Abstract\n\nSpecify the behavior of function calls and the type and behavior of the entity\nintroduced by a function declaration.\n\n## Problem\n\nFunctions are a primitive building block through which we define Carbon's\nexecution semantics, but we don't currently have a specification for what a\nfunction is in Carbon nor how function calls work. We have open questions around\nwhether Carbon has first-class function types, how types can overload the\nfunction call operation, and how callable entities such as the name of a\nparameterized class fit into the picture -- are they functions or something\nelse?\n\n## Background\n\nThis proposal assumes the reader understands how functions and function pointers\nwork in C or C++.\n\n## Proposal\n\nA function declaration in Carbon introduces a new, unique, stateless type,\ncalled a _function type_. The function name is bound to a value of that function\ntype.\n\nFunction calls use C-like syntax: an expression naming a callable is followed by\na syntax resembling a tuple of arguments. There are several kinds of callable:\n\n-   Functions, and more generally\n    [values of function types](#functions-and-function-types).\n-   [Bound methods](#bound-methods), such as `my_vector.Begin`.\n-   Lambdas, once they are introduced to Carbon.\n-   Parameterized entities, such as a generic class `Vector` or a generic\n    interface `AddWith`.\n-   Values of dependent types that are\n    [constrained to be callable](#generic-callable-parameters).\n-   User-defined class types that\n    [overload function call syntax](#overloaded-call-operator).\n\nIn the first four cases, argument deduction is used to determine the values of\ndeduced arguments, and then pattern matching is used to bind parameter patterns\nto argument values.\n\nIn the remaining cases, the built-in `Call` interface is used to determine the\nsemantics of the call, and the call `F(args)` is translated into\n`F.(Call(ArgTypes).Op)(args)`. Note that this is itself a bound member function\ncall, and `Call(ArgTypes)` is a call to a parameterized entity, so this\ntransformation is only performed once.\n\n## Details\n\n### Functions and function types\n\nA function declaration such as\n\n```\nfn F[T:! type](x: T) -> T { return x; }\n```\n\nintroduces a value named `F`, whose type is a unique _function type_. Distinct\nfunctions have distinct function types, even if they have the same signature. A\nfunction type is an empty, trivial type. There is no way to name a function type\nother than asking for the type of the function value.\n\n```\n// Compile-time function.\nfn TypeOf[T:! type](x: T) -> type { return T; }\n\n// ✅ `F` is a first-class value with a first-class type.\nlet template FType:! type = TypeOf(F);\nvar my_f: FType = F;\n```\n\nFunction values are regular values that can be stored in variables, passed to\nfunctions, and so on.\n\n```\nfn G() -> i32 {\n  // ✅ `my_f` has function type `FType`. This is a direct call to `F`.\n  return my_f(1);\n}\n\nfn Sort[template F:! type, T:! type](v: Vector(T)*, f: F);\nfn Compare(a: i32, b: i32) -> Ordering { return a.(Ordered.Compare)(b); }\nfn SortInts(v: Vector(i32)*) { Sort(v, Compare); }\n```\n\nFor the purpose of the\n[orphan rule](/docs/design/generics/details.md#orphan-rule), a function type is\nconsidered to be declared by the function declaration that introduces the\nfunction value.\n\n### Bound methods\n\nFor each function type corresponding to a method, there is a corresponding\n_bound method type_. When a member access is performed on an object of class\ntype to access a method, the result is a _bound method value_ of bound method\ntype. A bound method type describes the callee in a method call, and a bound\nmethod value describes the `self` parameter of the call.\n\n```\nclass HasMember {\n  // `HasMember.F` has a stateless function type, with signature\n  // `[self: Self](n: i32) -> i32`.\n  fn F[self: Self](n: i32) -> i32;\n}\nfn F(h1: HasMember, h2: HasMember) -> i32 {\n  // ✅ `h1.F` is a bound method value whose type is a bound method type,\n  // with signature `(n: i32) -> i32`.\n  var hf: auto = h1.F;\n  // ✅ `h1.F` and `h2.F` are of the same bound method type.\n  hf = h2.F;\n  // ✅ Same as `h2.F(4)`.\n  return hf(4);\n}\n```\n\n### Call syntax\n\nCalls take the form `a(b, c, d)` or `a(b, c, d,)`, where:\n\n-   `a` is the callee, which can be a name, a literal, a member access, or some\n    more complex expression enclosed parentheses.\n-   `b`, `c`, `d` are any number of argument expressions. Arguments are\n    separated by commas, and if the argument list is not empty, an optional\n    trailing comma is permitted but not required after the final argument.\n\nCall syntax is syntactically equivalent to a primary expression followed by a\ntuple literal, except that a tuple literal requires a trailing comma to form a\nsingle-element tuple `(b,)`, whereas in call syntax both `a(b)` and `a(b,)` are\npermitted.\n\n### Direct calls\n\nA call expression is a _direct call_ when the callee:\n\n-   is the name of a parameterized entity, like a generic class or interface, or\n-   has a function type or bound method type.\n\nIn a direct call, a call signature is available which is used to check the given\narguments against the callee's declared implicit and explicit parameters. This\nchecking proceeds as follows:\n\n-   Argument deduction is performed by comparing the declared parameter types\n    against the actual argument types and deducing values for implicit arguments\n    that make the types equal.\n-   Then, for each binding in the explicit parameter list in turn, all argument\n    values that have been deduced are substituted into the parameter.\n\n    -   If the parameter is a `template :!` binding, the argument expression is\n        converted to have the same type as the binding and template constant\n        expression phase.\n    -   If the parameter is a symbolic `:!` binding, the argument expression is\n        converted to have the same type as the binding and symbolic constant\n        expression phase.\n    -   Otherwise, the parameter is pattern-matched against the argument.\n\n    If a parameter is a `:!` binding, its corresponding converted argument\n    expression is evaluated, and its value is added to the list of deduced\n    argument values before any later parameters are processed.\n\nThe result of the call expression depends on the callee:\n\n-   If the callee is a parameterized entity such as a generic class or a generic\n    interface, the result is the specific instance of that generic, such as a\n    class or interface, and the call is a value expression of type `type`.\n-   If the callee is a function value, the call is an initializing expression\n    whose type is the substituted return type of the function. When evaluated,\n    the call expression will invoke the function and produce whatever value it\n    returns.\n-   If the callee is a bound method value, it behaves the same as a function\n    value, except that the `self` parameter of the called function is bound to\n    the `self` value in the bound method value.\n\n### Generic callable parameters\n\nA generic parameter can be constrained to be a callable type using the `Call`\ninterface:\n\n```\ninterface Call(Args: type) {\n  let Result:! type;\n  fn Op[self: Self](args: Args) -> Result;\n}\n```\n\n> **TODO:** `Call` should be variadic. For now, we model it as taking a tuple\n> type, and we model `Call.Op` as taking a tuple value.\n\nFor example:\n\n```\nfn Sort[T:! type, F:! Call((T, T)) where .Result = Ordering]\n       (v: Vector(T)*, cmp: F) {\n```\n\nA call expression that is not a direct call is translated into an invocation of\n`Call(Args).Op`, where `Args` is the type of the call's argument tuple.\n\n```\n  // In Sort...\n  auto ord: auto = cmp((*v)[i], (*v)[j]);\n  // ... is translated into ...\n  auto ord: auto = cmp.(Call((T, T)).Op)((*v)[i], (*v)[j]);\n```\n\nNote that the types of the call arguments are modeled as an interface parameter.\nThis permits the call interface to model function overloading. However, the\nreturn type is an associated type, not a parameter -- we do not permit\noverloading on return types, and we don't want type information to propagate\nfrom the context in which a call expression appears inwards to the call.\n\n### Function types and `Call`\n\nA function type or bound method type implements the `Call` interface for every\nset of runtime argument types that a direct call to the function or bound method\nwould accept. The behavior of `Call.Op` is to call the function or bound method\nwith the provided argument list.\n\n```\nfn Select[T:! type](b: bool, x: T, y: T) -> T {\n  return if b then x else y;\n}\n\n// Generated:\nimpl forall [T:! type, BType:! ImplicitAs(bool)]\n    Select as Call((BType, T, T)) where .Result = T {\n  fn Op[self: Self](args: (BType, T, T)) {\n    let (b: bool, x: T, y: T) = args;\n    return Select(b, x, y);\n  }\n}\n```\n\nImplicit conversions are permitted for parameters whose types do not involve\ndeduced parameters. The intent is for the `impl` to support indirect calls in\nthe same cases where the function supports direct calls, with the same meaning.\n\n```\nfn TakeI32Fn[F:! Call(i32)](f: F);\nfn I64Fn(n: i64);\nfn Run() {\n  // ✅ `I64Fn` can be called with an `i32`, because\n  // `i32 impls ImplicitAs(i64)`.\n  TakeI32Fn(I64Fn);\n}\n```\n\n> **Note:** A call made using the `Call` interface always takes its arguments as\n> value expressions and the call is always an initializing expression. If the\n> function takes its arguments using `var`, or if a language mechanism is added\n> that permits a direct function call to not be an initializing expression,\n> additional conversions will be required. The `Call` interface is treated as\n> not being implemented in cases where those conversions are not possible, for\n> example because an argument or return value is not copyable. If we add a\n> mechanism to allow an `impl` to specify a different expression category for\n> its parameters or result than the one in the interface, for example by taking\n> a `var` parameter where the interface took a `let` parameter, that would\n> automatically also be available for overloaded function calls.\n>\n> We anticipate revisiting these constraints in a future proposal, and expanding\n> the function call interface to provide the same generality that is provided by\n> `fn` declarations. This is described more in the\n> [future work](#overloading-on-expression-category-and-phase) section.\n\nThe `Call` interface only models function calls for which arbitrary runtime\nvalues of the given parameter types can be passed to the function. If the\nsignature of the function has compile-time parameters in its explicit argument\nlist or has any refutable pattern matching between the call arguments and\nfunction parameters, the function type will not implement `Call`.\n\n```\nfn Runtime[T:! type](x: T);\nfn CompileTime(T:! type, x: T);\n// 🤷 Undecided whether this is valid.\nfn RefutablePattern(1 as i32);\n\nfn Run() {\n  // ✅ Calls `Runtime(0)`.\n  Runtime.(Call(i32).Op)(0);\n  // ❌ Can't call `CompileTime` this way, it can't implement `Call(type, i32)`\n  // because the type would be passed at runtime.\n  CompileTime.(Call(type, i32).Op)(i32, 0);\n  // ❌ Can't call `RefutablePattern` this way, it can't implement `Call(i32)`\n  // for arbitrary i32 arguments.\n  RefutablePattern.(Call(i32).Op)(0);\n}\n```\n\n### Overloaded call operator\n\nThe `Call` interface can be implemented to overload the meaning of the function\ncall operator for a type.\n\n```\nclass Func(Arg:! type) {\n  impl as Call((Arg,)) where .Result = () {\n    fn Op[self: Self](arg: (Arg,)) { Print(\"hello, world\"); }\n  }\n}\n\nfn Run() {\n  let f: Func(i32) = {};\n  // ✅ Prints \"hello, world\".\n  f(42);\n}\n```\n\nThere are no constraints on the callee type, beyond the normal constraints for\nimplementing an interface.\n\n```\nclass X { var n: i32; }\n// ✅ OK, but inadvisable.\nimpl {.a: X} as Call(()) where .Result = i32 {\n  fn Op[self: Self](args: ()) -> i32 {\n    return self.a.n;\n  }\n}\nfn Run() -> i32 {\n  // Returns 1.\n  return {.a = {.n = 1} as X}();\n}\n```\n\nThere is no way to directly define a function-like callable class type that\ntakes a compile-time argument. This is similar to the situation in C++ where\nthere is no way to define an `operator()` for a value `x` of class type so that\n`x<T>()` passes `T` to `operator()` at compile time. However, this can be worked\naround by putting the compile-time value in the type of an argument instead:\n\n```\nclass Wrap(T:! type) {}\nclass Callable {\n  impl forall [T:! Printable] as Call((Wrap(T), T)) where .Result = () {\n    fn Op[self: Self](args: (Wrap(T), T)) {\n      let (_: auto, v: T) = args;\n      Print(v);\n    }\n  }\n}\nfn CallIt[F:! Call(Wrap(i32), i32)](f: F) {\n  f({} as Wrap(i32), 0);\n}\nfn Run() {\n  CallIt({} as Callable);\n}\n```\n\n## Rationale\n\nPrinciples:\n\n-   [Principle: one static open extension mechanism](/docs/project/principles/static_open_extension.md).\n    -   Overloaded calls are supported by implementing an interface.\n-   [Principle: Prefer providing only one way to do a given thing](/docs/project/principles/one_way.md).\n    -   There is only one obvious way to pass a callable to a generic function,\n        and it works efficiently whether the argument is a function, a callable\n        object, or (eventually) a lambda.\n\nGoals:\n\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software)\n    -   Passing around functions is no less efficient than passing around\n        callable objects.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Function types in C and C++ are notoriously hard to read. We avoid this\n        problem by not having signature-based function types.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   As [future work](#function-pointers) we have the basis for a design for\n        function pointers. C++ function pointers can be modeled in Carbon code\n        as values that implement `Call`, as can member function pointers.\n\n## Alternatives considered\n\n### Signature-based function types\n\nWe could give each function signature a distinct type, as is done in C and C++.\nThis would provide a story for [function pointers](#function-pointers) that does\nnot rely on generics or type erasure or fancy representation optimizations.\n\nThe main down side of this approach is one we see frequently in C++: passing a\nfunction to a template generic would be less efficient than passing a function\nobject to the same template. For example, in C++, given\n\n```\nstd::vector<int> v;\nbool cmp(int a, int b) { return simple_calculation(a, b); }\n```\n\n... calling `ranges::sort(v, cmp)` may be much less efficient than calling\n`ranges::sort(v, [](int a, int b) { return cmp(a, b); })`, because the latter\nperforms a direct call and the former passes a function pointer, resulting in an\nindirect call.\n\nMaking functions result in unique types means that calls to functions, lambdas,\nand function-like objects have semantics that are more similar and have similar\nefficiency properties.\n\n### Make direct and indirect calls behave uniformly\n\nIt would be desirable to remove the difference between direct and indirect\ncalls. Unfortunately, that doesn't seem to be practical, for a number of\nreasons:\n\n-   Indirect calls need to be transformed into another call expression. We need\n    a foundation for our semantics at some point, where we make an actual\n    function call rather than transforming one function call into another.\n-   We have chosen that\n    [interfaces are the only static open extension mechanism](/docs/project/principles/static_open_extension.md).\n    This means that any general mechanism we provide to overload function calls\n    must fit within the boundaries of Carbon's `interface` and `impl`\n    mechanisms.\n-   We could try to support passing compile-time parameters to functions by\n    specifying in the `impl` query whether each argument can be passed at\n    compile time, but any such query will need to be able to fall back to\n    passing each argument at runtime, which can result in an exponential-time\n    search for a matching `impl`.\n\n## Future work\n\n### Overloading\n\nWe intend to support function overloading, and although it outside the scope of\nthis proposal, it is important to ensure that we have reasonable paths forward\nto support overloading within this framework.\n\nAn overloaded function has multiple different signatures -- sets of implicit and\nexplicit parameters -- that will be checked against the provided arguments. In\nthis proposal, that means that a set of overloaded functions introduces a single\nfunction type that supports being called in different ways.\n\nDepending on how we approach overloading, overload selection might be done by\nchecking each candidate in turn until we find one that matches, or checking them\nall and somehow selecting the best match, and our current intent is to use the\nformer approach. Translated into this proposal, one important consequence is\nthat the function type corresponding to the set of overloaded functions has\nmultiple parameterized implementations of the `Call(...)` interface, and the\nimplementation selected for a particular call will need to follow whatever rules\nthe overloading mechanism picks. For example, if function overloading picks the\nfirst matching function, then given the following, using placeholder syntax:\n\n```\noverloaded fn Abs[T:! Unsigned](x: T) -> T { return x; }\noverloaded fn Abs[T:! Floating](x: T) -> T { return x < 0 ? -x : x }\n```\n\nwe would synthesize implementations that behave as follows:\n\n```\nmatch_first {\n  impl forall [T:! Unsigned] Abs as Call((T,)) where .Result = T { ... }\n  impl forall [T:! Floating] Abs as Call((T,)) where .Result = T { ... }\n}\n```\n\nFor a type that is `Unsigned & Floating`, the former `impl` will be selected,\nmatching the behavior of overload selection.\n\n### Overloading on expression category and phase\n\nWe should consider whether calls can be overloaded on the expression category\nand expression phase of the callee and arguments. For compile-time arguments, we\nmay also wish to support overloading on the constant value.\n\nOther languages support overloading on the expression category of the callable\nobject. Rust provides separate `Fn`, `FnMut`, and `FnOnce` to distinguish\nbetween different ways of passing the callable object into an overloaded\nfunction call, and C++ permits `operator()` to take `*this` as `const`,\nnon-`const`, or even `&&`.\n\nIn Carbon, we could follow the Rust approach and provide multiple `Call`\ninterfaces to handle different kinds of `self` parameter, modeled in a similar\nway to the `IndexWith` and `IndirectIndexWith` interfaces used for subscripting.\nA more general, ambitious and ergonomic approach that we have started exploring\nwould be to allow the function call signature to be described as part of the\ncall interface:\n\n```carbon\nimpl MyCallable as call(T:! type, x: T) -> T;\n```\n\nThis might be a shorthand syntax for some way of expressing the signature as an\ninterface, or a new form of first-class language primitive.\n\nThe options in this space are currently being explored in issue\n[#3154](https://github.com/carbon-language/carbon-lang/issues/3154).\n\n### Variadics\n\nOnce Carbon supports variadics, the overloaded call mechanism should be revised\nto make use of them, instead of using a tuple type to approximate a variadic\nparameter list.\n\n### Lambdas\n\nA lambda is expected to behave much like a function under this proposal, with\nthe primary difference being that lambdas can be stateful, whereas functions are\nstateless.\n\n### Function pointers\n\nFor interoperability with C++, and for purposes of cheaply storing references to\nstateless functions, function pointers should be supported. A function pointer\ncould be modeled as:\n\n```\nalias FunctionPtr(Args:! type, Result:! type) =\n    DynPtr(Stateless & Call(Args) where .Result = Result);\n```\n\nwhere:\n\n-   `Stateless` is an interface describing types that are empty, do not have a\n    notion of identity, and for which instances can be created and destroyed\n    trivially.\n-   `DynPtr` is a\n    [type that performs type erasure and runtime dispatch](/docs/design/generics/details.md#dynamic-types)\n    for a given facet type.\n-   `DynPtr` has an optimization that `DynPtr(Stateless & I)`, where `I` is an\n    interface with exactly one associated function, is represented as a pointer\n    to that function.\n"
  },
  {
    "path": "proposals/p2922.md",
    "content": "# Introduce a new Conduct Team\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/####)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Strategy for a sustainable Conduct Team](#strategy-for-a-sustainable-conduct-team)\n    -   [What we are looking for in Conduct team members](#what-we-are-looking-for-in-conduct-team-members)\n    -   [Initial team members](#initial-team-members)\n    -   [Process](#process)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Make no changes](#make-no-changes)\n    -   [Have some overlap between Carbon leads and the Conduct team](#have-some-overlap-between-carbon-leads-and-the-conduct-team)\n    -   [Keep the restriction on new conduct team members accessing prior reports](#keep-the-restriction-on-new-conduct-team-members-accessing-prior-reports)\n\n<!-- tocstop -->\n\n## Abstract\n\nThe Carbon Project relied on the three leads to handle conduct concerns\ninitially as it bootstrapped its community team and expertise. We now have an\nactive and effective community lead and team of moderators. Our community lead\nhas worked to train and ramp up a new and independent conduct team.\n\nThis proposal both provides an overview of the process and hands off conduct\nhandling to the new team! Going forward, we expect routine updates to the\nconduct team to happen without full proposals as they allow trained folks to\nrotate in and out of this difficult but essential role on the project.\n\nLast but not least, making these changes uncovered a restriction in the Code of\nConduct itself that we expect to be problematic to adhere to going forward.\nWhile well intentioned, it has a bunch of unanticipated effects that made both\ncurrent and new conduct teams want to remove it. A related section has had its\nwording strengthened to try and address the underlying motivation at least\npartially.\n\n## Problem\n\n-   Our Code of Conduct team is made up of those with the highest power in the\n    community (Carbon leads), and our current framework does not allow for clear\n    accountability in terms of their own conduct due to this lack of separation.\n-   The diversity of backgrounds and perspectives is limited among our current\n    CoC team.\n-   The Carbon leads have limited time and availability to intervene in urgent\n    and important misconduct situations.\n\nSo, it is time to build a specialized team to deal with escalations which is not\nsubordinate to the Carbon leads, and is able to handle diverse misconduct\nescalations in an adequate and timely manner. This means we can recruit and/or\ntrain people from diverse backgrounds to handle such escalations for the Carbon\ncommunity, and provide competent support to the leads, the rest of the\nmoderation team, and everyone else in the community.\n\n## Background\n\nOur Code of Conduct:\nhttps://github.com/carbon-language/carbon-lang/blob/trunk/CODE_OF_CONDUCT.md\n\nOur current CoC team:\n\n-   Chandler Carruth (@chandlerc on Discord and GitHub)\n-   Kate Gregory (@KateGregory on Discord and GitHub)\n-   Richard Smith (@zygoloid on Discord and GitHub)\n\n## Proposal\n\nCreate a new [Conduct Team](/docs/project/teams/conduct_team.md) as follows:\n\n-   Recruit and train 5+ potential new conduct team members to deal with\n    conduct-related escalations on behalf of and for the Carbon community, and\n    replace the current CoC team as soon as enough members are ready.\n-   We should always have at least 3 conduct team members available to respond\n    promptly, even factoring in vacations, getting sick, or other normal\n    disruptions.\n-   Subsequent updates to the exact members will be managed by the new conduct\n    team themselves, and without full proposals but just PRs to update the\n    relevant documentation.\n\nAlso remove a restriction on how reports are shared with new conduct team\nmembers going forward (but _not_ retroactively, which would violate our past\npromise). While this restriction was well intentioned, it isn't a restriction\nthat the conduct team can effectively uphold going forward. For example, it\nwould prevent informing new conduct team members of people banned because of\nbad-faith reports. We understand that reports are sensitive, and have\nstrengthened our statements around keeping them confidential and only using them\nas needed.\n\n## Details\n\n### Strategy for a sustainable Conduct Team\n\nThe Carbon community needs a **distinct, qualified, empowered, and diverse**\nCode of Conduct team.\n\nThis crucial and particularly straining work needs to be shared among the team,\nso all members get enough support and rest. The proposal is for a member\nrotation strategy. Carbon's long-term goal should be to have 5+ trained Conduct\nTeam members, so at least 3 are available to discuss and act upon incident\nreports in a timely and adequate manner.\n\nThe initial team was recruited by our Community lead and pulls from the current\ntrained moderator pool. We propose that the Conduct team itself is responsible\nto continue recruiting both new Conduct team members and new moderators to make\nboth efforts sustainable. They will work toward better representation, embracing\nboth broad and intersectional diversity.\n\n### What we are looking for in Conduct team members\n\nTeam members need a track record showing:\n\n-   Effective and constructive engagement with online, technical, and/or\n    open-source software communities\n-   Advanced moderation and mediation skills\n-   Intercultural competence\n-   Extensive knowledge of human diversity and systemic discrimination forms\n-   Proficient written English communication skills\n\nOther essential things we prioritize for all team members:\n\n-   Kindness\n-   Thoughtfulness, including while dealing with highly sensitive information\n-   Prioritizing the most vulnerable\n-   Readiness to have uncomfortable conversations, including sparking them\n-   Resilience in the face of abuse, including when becoming a target\n-   Verified Discord and GitHub user account\n-   Readiness to use Google Drive collaboration tools\n-   Readiness to deal with every escalation reported to the team while on duty\n\nHigh-value things we look for but are not necessary:\n\n-   Personal experience of marginalization in tech communities (for example\n    based on ability/disability, race/ethnicity, gender identity, lifestyle,\n    first language, etc.)\n-   Already active in the C++ or Carbon community\n-   Figure of authority in some relevant domain\n-   Non-corporate working experience\n\nNote that it is _not_ important to be good at coding or a native English speaker\nto be effective as a member of the team.\n\n### Initial team members\n\n-   Allison Poppe (@acpoppe on Discord and GitHub)\n-   Céline Dedaj (@celineausberlin on Discord and GitHub)\n-   Christopher Di Bella (@cjdb on Discord and GitHub)\n-   Lexi Bromfield (@lexinadia on Discord and @lexi-nadia on GitHub)\n-   flysand (@flysand on Discord and @flysand7 on GitHub)\n\n### Process\n\nSelection and sourcing:\n\n-   Candidates were identified and recruited by our Community lead.\n-   Candidates met with both Carbon leads and the Community lead individually to\n    make sure everyone was comfortable with the role and responsibilities\n    involved.\n\nOnboarding and support:\n\n-   New members will have access to coaching and mentoring from the Community\n    lead as a diversity, equity and inclusion specialist, and general support by\n    a senior moderation team member.\n-   The project organizes regular informal moderation meetups to learn with and\n    from each other, including a book club.\n\nExit:\n\n-   This work tends to be straining and that each person's involvement may only\n    be temporary.\n-   Both the Carbon leads and the newly formed conduct team will make sure that\n    individual conduct team members feel safe to leave the team and community\n    when they need to step out by developing a bench of candidates.\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   The Carbon project needs to have an effective and scalable process for\n        handling conduct concerns to continue to be an inclusive and welcoming\n        community.\n    -   Having a separate team focused on these concerns both enables more\n        specialized skills and can provide a more effective path to hold the\n        Carbon leads accountable to the same conduct standards.\n\n## Alternatives considered\n\n### Make no changes\n\nThis would leave the fundamental problems of both scale and external\naccountability unresolved.\n\n### Have some overlap between Carbon leads and the Conduct team\n\nWe considered having some amount of overlap between the leads and the conduct\nteam on an ongoing basis. While this would help ensure that the Carbon leads are\naware and attending to the community, culture, and conduct needs of the project,\nit ultimately had a number of disadvantages that made us decide to have a fully\nseparate team:\n\n-   The Conduct team can and should focus their energy and leverage their\n    special skills at evaluating conduct challenges. This is different from the\n    focus, skills, and priorities of the leads.\n-   The leads want to encourage the conduct team to hold the leads own conduct\n    accountable to the rest of the community, and so want to keep the conduct\n    team especially as independent as possible.\n-   Even if in practice no conflict arises, having a _visible_ separation is\n    valuable to the community to build trust.\n-   Having two fully independent groups helps facilitate them each helping,\n    supporting, empowering, and when necessary, challenging the other.\n\n### Keep the restriction on new conduct team members accessing prior reports\n\nWe considered this, as we are very sympathetic to ensuring community members\nfeel safe making reports, even though the composition of the conduct team might\nchange in the future.\n\nUnfortunately, we weren't able to find an effective restriction in this space\nthat still allowed the conduct team to effectively respond to conduct concerns.\nWe have tried to further clarify the expectations on the narrow and limited ways\nin which it is ever appropriate for this information to be used. Misusing\nconduct reports, much like other abuses of the Code of Conduct's process, is\nitself a serious violation of the code.\n"
  },
  {
    "path": "proposals/p2964.md",
    "content": "# Expression phase terminology\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/2964)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Abstract\n\nUpdate terminology around expression properties:\n\n-   \"value phase\" -> \"expression phase\"\n-   \"symbolic value\" -> \"symbolic constant\"\n-   \"constant\" -> \"template constant\"\n-   \"constant or symbolic value\" -> \"constant\"\n\nImplements the decision in\n[#1391](https://github.com/carbon-language/carbon-lang/issues/1391).\n\n## Problem\n\nThere are a few concerns with the current terminology:\n\n-   We were not happy with it at the time it was introduced in\n    [proposal #1378](https://github.com/carbon-language/carbon-lang/pull/1378/files/198c7bd152bc4e223f1fc2484455e17ba31f19f9#r921592116),\n    but didn't want to block that proposal on finding better names.\n-   It is a property of expressions, not values. We are switching from \"value\n    categories\" to \"expression categories\" for the same reason. See\n    [proposal #2006](https://github.com/carbon-language/carbon-lang/pull/2006)\n    and [PR #2744](https://github.com/carbon-language/carbon-lang/pull/2744).\n-   No good term for the bindings that use `:!`, which share a number of\n    properties, and often we want to refer to those together.\n\nThe concerns about the names of the individual phases led to\n[questions-for-leads issue #1391: New name for \"constant\" value phase](https://github.com/carbon-language/carbon-lang/issues/1391).\nThis proposal implements the resolution from that issue.\n\n## Background\n\nThe current names were introduced in\n[proposal #1378: Design overview update part 7: values](https://github.com/carbon-language/carbon-lang/pull/1378)\nbased on a discussion in\n[#typesystem on Discord](https://discord.com/channels/655572317891461132/708431657849585705/996547601451204630).\nI am not aware of corresponding terminology in other programming languages.\n\n## Proposal\n\nWe update terminology around expression properties, specifically what we\npreviously referred to as \"value phase\" and values it can have, as follows:\n\n-   \"value phase\" -> \"expression phase\": since this is a property of\n    expressions, not values.\n-   \"symbolic value\" -> \"symbolic constant\": for symbolic compile-time values\n    like checked-generic parameters.\n-   \"constant\" -> \"template constant\": for compile-time values where the value\n    is available during type checking, like literals and `template` parameters.\n\nBy making these last two terms both end in \"constant,\" we allow their\ncombination (including all compile-time values) to be collectively referred to\nusing the term \"constant.\" For example, either kind of constant may be passed to\na function with either kind of constant binding.\n\n## Rationale\n\nThe goals of this proposal are:\n\n-   clearer and more concise communication, and\n-   making it easier for people to learn Carbon by using more consistent\n    terminology.\n\nThis supports Carbon's goal of having\n[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\n\n## Alternatives considered\n\nWe were happy with this option and did not spend time coming up with more\nalternatives.\n"
  },
  {
    "path": "proposals/p3162.md",
    "content": "# Reduce ambiguity in terminology\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3162)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Abstract\n\nChange terminology away from terms that are ambiguous:\n\n-   Reserve \"generic type\" for types with (compile-time) parameters, like\n    `Vector` in `Vector(T:! type)`. Don't use that term to refer to `T`, as it\n    would with [#2360](/proposals/p2360.md#terminology).\n-   Use the term \"compile-time\" instead of \"constant\" to mean \"template or\n    symbolic.\" Expand the term \"constant\" to include values, such as from `let`\n    bindings.\n\n## Problem\n\nRight now, the term \"generic type\" has two meanings. In this example:\n\n```\nclass Vector(T:! type);\n```\n\nBoth `Vector` and `T` could be called a \"generic type.\" It would be much less\nconfusing if one of those two would have a different name.\n\nSimilarly, \"constant\" can currently mean multiple things:\n\n-   \"evaluation at compile time,\" as in \"constant evaluation\"\n-   \"not variable,\" as in `let` instead of `var`\n-   \"non-mutating view,\" as in `const T*`\n\nIn practice, this has resulted in confusion. For example, the term \"constant\nbindings\" doesn't include all `let` bindings, even though they are not variable\nbindings.\n\n## Background\n\nThe two meanings of \"generic type\" come from:\n\n-   Proposal [#2360](/proposals/p2360.md#terminology) defines a generic type to\n    be a type or facet introduced by a `:!` binding, such as in a generic\n    parameter or associated constant.\n-   Other uses of the term generic, such as in generic function, mean a language\n    construct with a compile-time parameter (as in\n    [Rust](https://doc.rust-lang.org/rust-by-example/generics.html)). This is\n    the usage in the broader programming language community, and includes\n    calling parameterized types \"generic types\" (as in\n    [Java](https://docs.oracle.com/javase/tutorial/java/generics/types.html),\n    [.NET](https://learn.microsoft.com/en-us/dotnet/standard/generics/#terminology),\n    [Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/generics/#Generic-Types)).\n\nIssue\n[#1391: New name for \"constant\" value phase](https://github.com/carbon-language/carbon-lang/issues/1391)\nimplemented in proposal\n[#2964: Expression phase terminology](https://github.com/carbon-language/carbon-lang/pull/2964),\nexpanded the term \"constant\" from referring to just template constants to also\ninclude symbolic constants from checked generics. Since then proposal\n[#2006: Values, variables, pointers, and references](https://github.com/carbon-language/carbon-lang/pull/2006)\nintroduced the `const` modifier on types, providing a read-only view.\n\n## Proposal\n\nWe make these changes:\n\n-   Reserve \"generic type\" for types with (compile-time) parameters, like\n    `Vector` in `Vector(T:! type)`. Don't use that term to refer to `T`, as it\n    would with\n    [#2360](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p2360.md#terminology).\n-   Expand \"constant binding\" to include all `let` bindings.\n-   Use the term \"compile-time binding\" to refer to the collection of template\n    and symbolic bindings, such as from generic parameters and associated\n    constants.\n-   Similarly \"compile-time constants\" to refer to template and symbolic\n    constants, as opposed to just \"constants.\"\n-   The term \"compile-time parameter\" may be used instead of \"generic\n    parameter.\" For now, both terms will be used, but in the future it might be\n    clearer to only use \"generic\" to mean \"has compile-time parameters.\"\n-   Only use \"symbolic binding\" and \"template binding\" not \"symbolic constant\n    binding\" nor \"template constant binding.\"\n-   Where applicable, switch from talking about parameters to bindings, since\n    almost everything that applies to compile-time parameters also applies to\n    compile-time bindings. For example, see\n    [\"binding patterns\"](/docs/design/generics/terminology.md#bindings) and\n    [\"facet binding\"](/docs/design/generics/terminology.md#facet-binding) in the\n    generics terminology doc.\n\n## Details\n\nThe following design documents have been updated in this proposal to reflect\nthese changes:\n\n-   [Language design overview](/docs/design/README.md)\n-   [Generics terminology](/docs/design/generics/terminology.md)\n-   [Member access expressions](/docs/design/expressions/member_access.md)\n\nSome of these changes have already been implemented in:\n\n-   [PR #3048: Update Generics terminology document](https://github.com/carbon-language/carbon-lang/pull/3048)\n-   [PR #3061: Update generics overview](https://github.com/carbon-language/carbon-lang/pull/3061)\n\n## Rationale\n\nThis proposal advances these goals of Carbon:\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem):\n    Having clear and unambiguous terminology is important for making a precise\n    language specification and as well as other design and developer\n    documentation.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n    particularly the sub-goal that \"The behavior and semantics of code should be\n    clearly and simply specified whenever possible.\"\n\n## Alternatives considered\n\nThe main alternative considered was the status quo. This was discussed:\n\n-   [starting 2023-Jul-14 in #naming](https://discord.com/channels/655572317891461132/963846118964350976/1129542605538074777)\n-   [2023-Jul-27 in open discussion](https://docs.google.com/document/d/1gnJBTfY81fZYvI_QXjwKk1uQHYBNHGqRLI2BS_cYYNQ/edit?resourcekey=0-ql1Q1WvTcDvhycf8LbA9DQ#heading=h.3tki3lncihf)\n-   [2023-Aug-28 in #naming](https://discord.com/channels/655572317891461132/963846118964350976/1145790947083423777)\n\nDuring those discussions, we also considered \"symbolic type\" instead of \"generic\ntype\". This did not work out, though, since it conflicted with the term\n\"symbolic\" used as an expression phase. We considered other possibilities:\n\"figurative type\", \"computed type\", \"hole type\", \"open type\", and \"placeholder\ntype\" (though that might be better applied to `auto`).\n\nIt also came up that we did not want to use the term \"generic binding\" to mean a\ncompile-time binding, because that term would be better applied to a\nparameterized binding, see\n[#naming on 2023-Jul-31](https://discord.com/channels/655572317891461132/963846118964350976/1135704682128494712).\nThose are not currently supported in Carbon, but are something we are likely to\nadd. For example,\n[Rust has generic associated types](https://rust-lang.github.io/generic-associated-types-initiative/explainer/motivation.html)\nas of [v1.65](https://blog.rust-lang.org/2022/10/28/gats-stabilization.html).\n"
  },
  {
    "path": "proposals/p3403.md",
    "content": "# Change Main//default to an api file\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3403)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Default to `Main//default impl` instead of `Main//default api`](#default-to-maindefault-impl-instead-of-maindefault-api)\n\n<!-- tocstop -->\n\n## Abstract\n\nWhen there is no `package` directive, default to `Main//default api` instead of\n`Main//default impl`. This has two user-visible consequences:\n\n-   The extension will be `.carbon`, not `.impl.carbon`.\n-   Only one `Main//default api` is allowed.\n\n## Problem\n\n[Code and name organization](/docs/design/code_and_name_organization/#libraries)\nsays:\n\n-   API filenames must have the `.carbon` extension. They must not have a\n    `.impl.carbon` extension.\n-   Implementation filenames must have the `.impl.carbon` extension.\n\nThe `Main//default` library is currently specified as an `impl` file. This means\nthat it should be something like `main.impl.carbon`.\n\n## Background\n\nMore generally in Carbon, a single-file library can be an `api` file, not an\n`impl` file. This comes as a side-effect from `impl` files implicitly importing\nthe `api`, which would fail if there were an `impl` file without an `api`. On\nthe other hand, there is no requirement that an `api` file have an `impl`.\n\nProposal\n[#2550: Simplified package declaration for the `Main` package](https://github.com/carbon-language/carbon-lang/pull/2550)\nchose `impl` as the default, providing an empty `api` file that cannot otherwise\nbe imported. The proposal doesn't provide rationale for this choice; it likely\nwasn't considered key to the proposal.\n\nIn C++, we often see `main.cpp`. This might be where the `impl` choice for\n`Main//default` comes from, as it has a more equivalent feel.\n\n## Proposal\n\nOmitting the package directive means `Main//default api`, rather than `impl`. As\na consequence:\n\n-   The `.carbon` extension applies instead of the `.impl.carbon` extension.\n-   An `api` can only be defined once, so there is a limit of one such file per\n    executable.\n\nMentions of `Main//default api` as being an empty file are removed.\n\nThe rules preventing use of `Main//default` in `package`, `library`, or `import`\nremain. The library can only be defined by omission of `package` and `library`,\nand cannot be imported.\n\n## Rationale\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n\n    -   Writing `Run` logic in a `main.carbon` file is expected to be more\n        intuitive than `main.impl.carbon`.\n\n## Alternatives considered\n\n### Default to `Main//default impl` instead of `Main//default api`\n\n`Main//default impl`, the status quo, is now a declined alternative. Key\nconsiderations are:\n\n-   Using `Main//default api` is consistent with single-file libraries in other\n    contexts.\n-   `main.carbon` is preferred over `main.impl.carbon`, and using\n    `Main//default api` allows the `main.carbon` extension without\n    special-casing the file extension choices.\n-   The special-case definition of `Main//default api` as an empty file is no\n    longer needed.\n-   Being able to have multiple `Main//default impl` files is of limited\n    utility. `Run` could only be defined in one such file, and the\n    `Main//default api` was defined as empty so no sharing was allowed.\n"
  },
  {
    "path": "proposals/p3407.md",
    "content": "# Clarify name bindings in namespaces.\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3407)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Allow prefixing a tuple binding pattern with a namespace](#allow-prefixing-a-tuple-binding-pattern-with-a-namespace)\n    -   [Allow binding patterns to declare names in multiple namespaces](#allow-binding-patterns-to-declare-names-in-multiple-namespaces)\n    -   [Allow declaring names in namespaces not owned by the current scope](#allow-declaring-names-in-namespaces-not-owned-by-the-current-scope)\n    -   [Allow declaring namespaces in scopes other than the file scope](#allow-declaring-namespaces-in-scopes-other-than-the-file-scope)\n\n<!-- tocstop -->\n\n## Abstract\n\n-   Require namespace members be declared in the same name scope as the\n    namespace is declared.\n    -   Declaring namespaces outside file scope is disallowed, so this means\n        only at file scope.\n-   Allow binding patterns to directly declare names in namespaces.\n-   Disallow introducing bindings in different namespaces in the same pattern.\n\n## Problem\n\nWhile the trivial case of `class NS.C` seems to be supported as a consequence of\nproposal\n[#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107),\nit lacks detail. For example, there are a couple syntactic options when binding\nmultiple names.\n\nAlso, there's no clear decision around code such as:\n\n```carbon\nnamespace NS;\nclass ClassT {\n  // Is this a class member accessed through `NS`, or a file scope member inside\n  // `NS`? What is its lifetime?\n  var NS.a: i32 = 0;\n}\n```\n\nThis proposal mainly aims to remove ambiguities.\n\n## Background\n\nNamespaces are covered in\n[code and name organization](/docs/design/code_and_name_organization/#namespaces).\nBinding patterns are covered in\n[pattern matching](/docs/design/pattern_matching.md#binding-patterns).\n\nThere's some discussion of `var` in\n[values, variables, and pointers](/docs/design/values.md), but it's specific to\nlocals. That doesn't address other use cases, such as globals or member\nvariables.\n\n## Proposal\n\nWhen used to declare names in binding patterns, as in `var` or `let`, all names\nmust be in the same namespace. `namespace` members must be declared from within\nthe same scope that declared the `namespace`.\n\nThere was uncertainty about whether namespaces could be declared outside of file\nscopes; for now, disallow it.\n\nSee the changes to\n[code and name organization](/docs/design/code_and_name_organization/#namespaces)\nfor reference.\n\n## Rationale\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n\n    -   Requiring that declarations of multiple names use `NS.a` syntax is\n        consistent with the single variable case.\n    -   Requiring namespace members be declared while in the same name scope as\n        the namespace itself makes lifetimes clearer.\n\n## Alternatives considered\n\n### Allow prefixing a tuple binding pattern with a namespace\n\nWe could use the namespace to prefix the binding tuple. For example:\n\n```carbon\nvar NS.(a: i32, b: i32) = (3, 4);\n```\n\nIt's rare that we would have a single statement declare multiple names. As a\nconsequence, the separation of the namespace qualifier from the declared\nidentifier might end up unique to this syntax. In that context, we prefer `NS.a`\nfor consistency with other cases, such as `class NS.class`.\n\n### Allow binding patterns to declare names in multiple namespaces\n\nWe could allow binding patterns to declare names in multiple namespaces. For\nexample:\n\n```carbon\nnamespace NS;\nvar (NS.a: i32, b: i32) = InitData();\n```\n\nMixing namespaces could be confusing: for example, `b` could be misunderstood to\nbe declared in `NS`. We lack data that would demonstrate benefits to offset\nthat.\n\nWe disallow mixing namespaces in a single declaration for simplicity.\n\n### Allow declaring names in namespaces not owned by the current scope\n\nWe could allow declaring names in namespaces not owned by the current scope. For\nexample:\n\n```carbon\nnamespace NS;\nclass ClassT {\n  var NS.val: i32;\n\n  class NS.ChildT {}\n}\n```\n\nHere, `package.NS.val` would be a global, but `ClassT.NS.val` looks more like an\ninstance member. It's also unclear whether `ClassT.NS.val` (or\n`instance.NS.val`) could be used to reference the produced variable, since `NS`\nis not inside `ClassT`'s name scope. The naming problems extend to non-binding\ndeclarations such as `NS.ChildT`, too.\n\nDisallowing using namespaces to cross name scopes is consistent with rules that\ngenerally prevent declaring names in other name scopes, such as:\n\n```carbon\nclass A {\n    class B {\n        // `C` must be declared directly inside `A`.\n        class A.C;\n    }\n}\n\n// `D` must be declared within `A`, even if separately defined.\nclass A.D {}\n```\n\nBoth the `namespace` declaration and names declared within the `namespace` must\nbe written in the same name scope. This avoids name lookup ambiguities, and\nbuilds consistency in name scope boundaries across declarations.\n\n### Allow declaring namespaces in scopes other than the file scope\n\nWe could allow declaring namespaces in scopes other than the file scope. It's\nambiguous what path should have resulted from proposal\n[#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107),\nalthough examples all focus on file scope, so other scopes weren't carefully\nconsidered.\n\nIt might prove useful in some situations. For example, perhaps a complex class\nwould find a member namespace useful:\n\n```carbon\nclass Complex {\n   namespace OptionSet1;\n   class OptionSet1.MemberClassA;\n   class OptionSet1.MemberClassB;\n\n   namespace OptionSet2;\n   class OptionSet2.MemberClassC;\n   class OptionSet2.MemberClassD;\n\n   namespace Vars;\n   var Vars.a;\n}\n```\n\nThis proposal takes a stance against declaring namespaces other than the file\nscope because:\n\n-   Proposal\n    [#107: Code and name organization](https://github.com/carbon-language/carbon-lang/pull/107)\n    only mentions file scope namespaces, implicitly disallowing it in other\n    scopes.\n-   Disallowing namespaces in other scopes is consistent with C++.\n\nIf allowed, it would be necessary to decide whether `Complex.Vars.a` would have\ninstance or global lifetime.\n\nFor now, namespaces may only be declared at file scope, which gives consistency\nwith C++. This decision may be reevaluated in a future proposal.\n"
  },
  {
    "path": "proposals/p3532.md",
    "content": "# Focus implementation effort on the toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3532)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Do nothing](#do-nothing)\n    -   [Front-load porting the functionality and output](#front-load-porting-the-functionality-and-output)\n\n<!-- tocstop -->\n\n## Abstract\n\nProposal to focus implementation effort for the next 1-2 years on the Carbon\ntoolchain instead of the explorer. This will impact the explorer in a few ways:\n\n-   We will keep the explorer's code in place, building, and passing its basic\n    tests. It can remain a good baseline for exploring Carbon's language\n    features.\n-   We won't prioritize expanding the explorer's coverage of Carbon features or\n    other improvements -- it is good enough for what we need until the toolchain\n    catches up.\n-   We will stop actively fuzzing and expanding test coverage for the explorer.\n-   Eventually, when we want to resume work on the explorer, we'll evaluate the\n    best platform to build on -- the current explorer codebase or on top of the\n    toolchain's semantic IR.\n\n## Problem\n\nCarbon is still a relatively small project, and we need to avoid spreading\nourselves out too much over too many efforts. Currently, we're maintaining two\nimplementation codebases -- the Carbon Explorer and the Carbon Toolchain. While\nhistorically these have served importantly different needs of the project, the\ncurrent state has changed. We're now moving slower as a consequence of spreading\nout our energy across both.\n\n## Background\n\nOriginally, the Carbon Explorer served two major purposes:\n\n1. A high-level or \"abstract machine\" executable semantic model for the design\n   of the language.\n\n2. A rapid prototyping platform with a generated parser and maximally simple &\n   traditional internal architecture (ASTs, etc.).\n\nThe first purpose and use case remains extremely important and something that we\nshould support. However, long-term it may make more sense to build on the same\ncore internal representation as the toolchain in order to avoid duplicated\neffort and maximize its utility. We'll understand the tradeoffs there better\nonce the toolchain is similarly feature complete.\n\nThe second use case is no longer critical. At the time, the toolchain was\nnascent and using a highly experimental architecture with many unknowns. It was\nhard to be confident it would work at all, much less add a feature to it. We\nalso had a large number of design features for Carbon that needed to have some\nform of implementation experience in order to validate the designs themselves.\n\nThe current state of the project is very different. The driving purpose of\nprototyping many of the core language features, from inheritance, to generics,\nto expression category, has been achieved. While there are large designs that\nare not yet in the explorer, we have proven out the most critical components and\ngotten critical implementation feedback.\n\nThe toolchain is also rapidly maturing and its core architecture is holding up\nwell. While implementing a new feature on top of the toolchain's architecture is\nsignificantly more expensive than on the explorer's architecture, it isn't\nstarting from nothing and the most uncertain aspects of the core architecture\nand design have become concrete. It is also increasingly necessary for us to get\nfeatures implemented here so that we can evaluate them in a realistic\ncompilation context and integrate them with C++ interop which we only anticipate\nto be able to build in the toolchain architecture.\n\nThe toolchain has also developed a Semantics IR that is an especially\ninteresting potential platform for building support for the executable semantics\nuse case. When the toolchain reaches feature coverage and maturity, it seems\nimportant to carefully consider whether that's the best approach to take, and\nwhat the tradeoffs are there.\n\n## Proposal\n\nWe should focus all of our efforts for the next 1-2 years on the toolchain, in\norder to make as much progress as possible. This in turn is likely to give us\nthe best evaluation of the Carbon experiment in the shortest time frame.\n\nWe should keep the Explorer's code in place, building, and passing its basic\nregression tests because the built artifacts of the Explorer remain really\nvaluable given its coverage of our design's feature sets. But we shouldn't take\non new work, or drive significant fuzzing, refactoring, or code cleanups in the\nexplorer.\n\nWe should also explicitly consider re-building the core functionality of the\nExplorer's abstract machine semantic execution on top of the toolchain's\nSemantics IR model. If this is the right approach given all the tradeoffs, it\nshould still leverage the existing work done and lessons learned on the Explorer\nfor how to model these semantics and how to render them in an understandable way\nfor users. This is another reason why we should keep all of the code in place,\nbuilding and passing its tests, until we complete this. While the code itself is\nunlikely to just directly port across in this way, having the artifacts ensures\nwe'll have a good point of comparison and reference for the ideas and designs.\nWe also may find that it isn't the right direction, and instead resume work on\ntop of the explorer's model directly.\n\n## Details\n\nThe short term practical details of this proposal are essentially:\n\n-   Update all of our documentation to direct contributors to the toolchain\n    rather than the Explorer.\n-   Document that the explorer's code is largely an archive and we're not\n    planning to do significant bug fixes, much less feature development in it.\n-   Document that we plan to eventually rebuild the explorer's core\n    functionality on top of the toolchain's semantic model, once that model is\n    sufficiently feature complete. And that we will _not_ remove the explorer's\n    code until that replacement is ready.\n-   Close the various bugs open for working on the explorer with links to this\n    proposal & documentation updates.\n-   Close open PRs and new PRs for the explorer linking to this proposal for\n    details. Note that closed PRs aren't deleted and so we can revisit them if\n    our priorities change and they end up remaining relevant.\n-   Update the issue form to make it clear that we're not planning to do more\n    work on the explorer codebase as-is.\n\nLong term, we need to plan to figure out how we want to pursue the core\nfunctionality of the explorer, whether in its current implementation or on top\nof the toolchain's Semantic IR model. Even if there isn't much code that can be\ndirectly reused, we should still heavily learn from and incorporate the relevant\nideas of the design of the explorer's abstract machine model, output rendering,\nand test suite.\n\n## Alternatives considered\n\n### Do nothing\n\nWe could simply leave things in the status-quo. However, this has the serious\ndownside that the contributors to Carbon are sufficiently stretched currently\nthat they are foregoing work on the explorer already. In some ways, at the\ncurrent size of the project, it isn't clear that we can sustain the status quo\nin practice even if we don't update our documentation.\n\n### Front-load porting the functionality and output\n\nWe could immediately try to port the functionality and output so that the\nexplorer tooling and workflow is immediately available on top of the toolchain's\nsemantic representation.\n\nUnfortunately there is a significant amount of implementation work left for the\ntoolchain to catch up in terms of feature completeness with the explorer. We\nneed to complete the functionality before we can really pursue this path. And\nthis proposal is trying to maximize how much energy the project can devote to\nthat.\n\nBeyond this fundamental limit, the current project roadmap and priorities focus\non getting C++ interop working with the toolchain above expanding functionality\nof the explorer. As a consequence, it seems better to focus on that priority in\nthe toolchain and to revisit rebuilding the explorer on top of the toolchain's\nsemantic model later, at least after the main interop goals are achieved. At\nthat point, it is also likely that most if not all of the feature gaps will have\nbeen closed.\n\nThe proposed approach to essentially archiving the explorer code seems like the\nbest way to align the effort and energy of the project contributors with these\npriorities.\n"
  },
  {
    "path": "proposals/p3564.md",
    "content": "# Roadmap for 2024 and a retrospective for 2023\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3564)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Proposal](#proposal)\n-   [Retrospective on 2023](#retrospective-on-2023)\n\n<!-- tocstop -->\n\n## Abstract\n\nWe propose a roadmap for 2024 focused on a working Carbon toolchain that\nsupports Carbon ↔ C++ interop.\n\n## Proposal\n\nWe propose the following goals for 2024:\n\n-   Implementing enough in the toolchain to build meaningful code on the Carbon\n    side of interop.\n-   Teaching the toolchain to compile enough C++ code (by way of Clang) to build\n    meaningful code on the C++ side of interop.\n-   Implementing the interop itself between Carbon and C++ code.\n-   Sharing various aspects of this with the broader Carbon, C++, and open\n    source communities.\n\nThis focuses significantly more on implementation than we have done in previous\nyears, which is a response to feedback that folks looking at Carbon and trying\nto evaluate or contribute are increasingly blocked on the lack of implementation\nsupport -- either of language features or compiler functionality. We also think\nthe design is far enough along to support this level of implementation, making\nit an effective time to adopt this more focused roadmap.\n\nThe full details are in the updated [roadmap] document.\n\n[roadmap]: /docs/project/roadmap.md\n\n## Retrospective on 2023\n\nOur [roadmap for 2023] focused on getting both the language and tools ready for\nevaluation, and building of context in the C++ community to support that\nevaluation. We executed on this really well, but with mixed results.\n\n[Roadmap for 2023]:\n    https://github.com/carbon-language/carbon-lang/blob/840cb1bed7cf9bd57e000cb4a61e986c383d3038/docs/project/roadmap.md\n\nOn getting ready for evaluation, we made fantastic progress on getting the\nlanguage (design) ready. We have [milestone definitions], and closed the most critical\ngaps in the design from the start of the year. The remaining gaps are either lower\nrisk, almost finished, or really need interop to effectively explore.\n\n[milestone definitions]: /docs/project/milestones.md\n\nThe tooling side also made fantastic progress, but has a lot further to go and\nforms the focus for 2024.\n\nWe also engaged more deeply with the C++ community on the technical\nunderpinnings, but the response highlighted that until we have (much) more\ncomplete tooling, we're going to struggle to deepen our engagement with the\nexternal community, and especially struggle to broaden that engagement to larger\ncommunities.\n\nBoth the amount remaining on the tooling side of things, and the fact that it\nhas proved a limiting factor in external engagement, are driving our priorities\nfor this year.\n\nBreaking down the specific key results we aimed at for 2023:\n\n-   A concrete definition of our MVP for evaluation, the 0.1 language\n    -   [Done][mvp-milestone]!\n-   Complete design coverage of the 0.1 language's necessary features\n    -   High risk, non-interop features are mostly done! The rest is taking a\n        back seat to getting the toolchain & interop ready.\n-   Complete 0.1 language implementation in the Carbon Explorer\n    -   There was nuance in this result: we only needed to complete as much\n        design validation as needed to have confidence in the design's cohesion\n        and behavior. We think the explorer got there in 2023 and have\n        [pivoted][toolchain-pivot] fully to the toolchain, so this is somewhat\n        by construction done.\n-   A toolchain that can build a minimal mixed C++ and Carbon program\n    -   As called out in the 2023 roadmap, we didn't expect to be able to\n        complete this by the end of 2023, and indeed, this has turned into our\n        focus for 2024.\n-   Give talks at 2-3 conferences covering 3-4 different Carbon topics\n    -   We only got to one conference, but we did cover 3+ topics this year.\n        We're hoping as we have a more complete toolchain we'll have more\n        relevant topics for more conferences.\n\n[mvp-milestone]:\n    /docs/project/milestones.md#milestone-01-a-minimum-viable-product-mvp-for-evaluation\n[toolchain-pivot]: /proposals/p3532.md\n\nOverall, 2023 was pretty amazing, and we hit some of the most important\nmilestones in the project over the past year.\n"
  },
  {
    "path": "proposals/p3646.md",
    "content": "# Tuples and tuple indexing\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3646)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Lexing](#lexing)\n    -   [Indexes as names](#indexes-as-names)\n    -   [Precedence](#precedence)\n    -   [Expression operand](#expression-operand)\n    -   [Bounds](#bounds)\n    -   [Tuple slicing](#tuple-slicing)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Alternative lexing rule](#alternative-lexing-rule)\n    -   [Decimal indexing restriction](#decimal-indexing-restriction)\n    -   [Square bracket notation](#square-bracket-notation)\n    -   [Negative indexing from the end of the tuple](#negative-indexing-from-the-end-of-the-tuple)\n    -   [Trailing commas](#trailing-commas)\n\n<!-- tocstop -->\n\n## Abstract\n\nAdd support for extracting elements of a tuple by their numerical index.\n\nAlso formally add the well-established basic syntactic and semantic rules for\ntuples, for which we have had leads issues but no proposal, into the design.\n\n## Problem\n\nCurrently, the only way to access the elements of a tuple is through pattern\nmatching. While this handles many cases well, it is sometimes desirable to\naccess an element of a tuple more succinctly, especially in cases where only a\nsingle element's value is needed.\n\n## Background\n\nIn Python, tuple indexing is performed using square brackets:\n\n```python\ntup = (1, 2, 3)\n# Prints 2.\nprint(tup[1])\n```\n\nIn C++, `std::pair` is indexed using `.first` and `.second`, and `std::tuple` is\nindexed using `std::get<I>`.\n\nIn Rust and Swift, a tuple is indexed using `.N`, where `N` is a decimal integer\nliteral.\n\n-   Rust disallows digit separators and base prefixes in `N`, but allows certain\n    literal suffixes\n    [for historical reasons](https://github.com/rust-lang/rust/issues/60210).\n-   Swift disallows digit separators and base prefixes in `N`. `swiftc` allows\n    leading `0` digits, although this appears to be an unintentional consequence\n    of `llvm::StringRef::getAsInteger` allowing them.\n\nThe current Carbon documentation suggests using `tuple[i]` for tuple indexing,\nbut this has not been the subject of an approved proposal.\n\n## Proposal\n\nFormally, we have not yet approved a proposal that says that Carbon has tuple\ntypes, although we have approved several proposals that explicitly include\nsupport for tuples. So, this proposal does that: tuples exist in Carbon, and are\nproduct types with unnamed positional elements.\n\nThis proposal also updates the design to match other decisions that have been\nmade in leads issues but not captured by a proposal, specifically:\n\n-   Leads issue #2191 (one-tuples and one-tuple syntax), despite being focused\n    on one-tuples, established the syntax for tuples of all arities.\n-   Leads issue #710 established rules for assignment, comparison, and implicit\n    conversion of tuples. These operations are performed elementwise, with\n    relational comparisons being performed lexicographically.\n\nFinally, the main intent of this proposal is to add support for indexing tuples,\nusing the following syntaxes:\n\n-   `.` _N_, where _N_ is an integer literal, and\n-   `.` `(` _expr_ `)`, where _expr_ is a template constant of integer type.\n\nFor pointers to tuples, `->` _N_ and `->` `(` _expr_ `)` are also supported.\n\n## Details\n\n### Lexing\n\nMulti-level tuple indexing will result in constructs such as\n`tuple_of_tuples.1.2`. It's important that these are lexed as two tuple indexing\noperations, not as `tuple_of_tuples` `.` `1.2`, as it would be under the current\nlexical rules, so a new rule is introduced:\n\n-   When a `.` or `->` token is followed immediately by a digit, it is lexed as\n    a `.` or `->` token followed by an integer literal, never a real literal.\n\nNote that this results in lexing being slightly contextual: the rule to lex a\ntoken after a `.` or `->` is different from the rule to lex a token in any other\ncontext. However, there is an alternative equivalent formulation of the rule\nthat is not context-sensitive: that `.integer` is treated as a single lexeme\nthat produces two tokens, and likewise for `->integer`.\n\n### Indexes as names\n\nThe elements of a tuple are treated as if they had decimal integers as their\nnames: `.0`, `.1`, and so on. It is an error to use a different spelling of that\ninteger in a simple member access, because that spelling would not match the\nelement name. For example, `(1, 2).0x0` is invalid, as is `large_tuple.1_2`.\nThese spellings can be used as an [expression operand](#expression-operand) as\ndescribed below: `(1, 2).(0x0)` and `large_tuple.(1_2)` are both valid.\n\n### Precedence\n\nThe `.` _N_ syntax has the same precedence as postfix member access syntax, `.`\n_name_, and can be combined in the same expression: `a.0.x.1` is valid.\n\nThe `.` `(` _expr_ `)` syntax is not new in this proposal, and continues to have\nthe same precedence as `.` _name_.\n\n### Expression operand\n\nIn the `.` `(` _expr_ `)` syntax, if the first operand is a tuple and the second\noperand is a constant of any integer type, the result is the corresponding tuple\nelement, as if specified by a decimal integer literal. This rule is built into\nthe language; the `.` `(` ... `)` notion is not currently overloadable.\n\n### Bounds\n\nIf the tuple index is not between 0 and one less than the number of elements in\nthe tuple, inclusive, the indexing is invalid.\n\n### Tuple slicing\n\nThe current skeleton design suggests using `tuple[a .. b]` to slice tuples. For\nexample, `tuple[0 .. 2]` could be used to extract the first two elements of a\ntuple. Tuple slicing support is not covered by this proposal, but could be added\nin the future with syntax such as `tuple.(0 .. 2)`. However, note that there is\na risk that this syntax may lead to an incorrect theory about how Carbon works:\nnamely, that `tuple.__` gives an element whereas `tuple.(__)` gives a tuple.\n\n## Rationale\n\nGoals:\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   The lexing rule is relatively simple to implement. Tools such as syntax\n        highlighters can treat `.i` as a distinct kind of token rather than\n        implementing any kind of context-sensitive lexing.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Consistent use of tuple field indexes can be used to support code that\n        adds new tuple elements over time.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   This feature allows tuple access to be written more concisely than\n        pattern matching would allow.\n    -   Lexing `.1.2` as four tokens rather than two avoids a surprise that\n        would make chained member access hard to write.\n    -   For simple member access, requiring a decimal integer with no digit\n        separators allows the member access to be treated as an element name,\n        making the indexing easier to understand.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   This feature provides a migration syntax for existing use of `.first`,\n        `.second`, and `std::get<I>`. The permission to use expressions rather\n        than only literals supports migration of `std::get<expression>`.\n\nPrinciples:\n\n-   [Low context sensitivity](/docs/project/principles/low_context_sensitivity.md).\n    -   We look only at the character immediately before a numeric literal to\n        determine whether it is lexed as a tuple index that stops before the\n        next `.` or as a general numeric literal.\n\n## Alternatives considered\n\n### Alternative lexing rule\n\nWe could lex `.0`, `.1`, ... as a single token rather than as separate `.` and\n`0`, `1`, ... tokens. This would somewhat simplify the lexing rules, because\nthey would no longer be contextual. We choose to not do this because:\n\n-   This would be inconsistent with our handling of `struct.fieldname`.\n-   Either `tuple . 0` would be invalid, unlike `struct.fieldname`, or it would\n    need to use a distinct grammar production from `tuple.0`.\n\nWe could lex an integer literal when the previous token is `.`, regardless of\nwhether the literal follows the `.` immediately. For example, we could treat\n\n```carbon\nlet n: i32 = ((1, 2, 3), 4) . 0.1;\n```\n\nas tuple indexing, rather than as a tuple followed by a `.` and a real literal.\nThis is what Swift does. We choose to not do this because:\n\n-   The `0.1` literal in this case looks like a real literal, not tuple\n    indexing, so this would likely cause surprise for readers.\n-   This would make the context-sensitive lexing be non-local. The chosen rule\n    can be interpreted as lexing `.[0-9]*` as a single lexeme, but forming two\n    tokens from it, whereas this alternative rule would be much more firmly a\n    context-sensitive lexing rule.\n\nWe could get a similar result in other ways:\n\n-   We could allowing a real literal after a `.`, and split it into a pair of\n    member accesses when needed. This is\n    [what `rustc` does](https://github.com/rust-lang/rust/pull/71322).\n-   We could lex a real literal as three tokens: an integer token, a `.` token,\n    and a suffix token, and merge them back together in the parser. This is\n    [what `intellij` does](https://github.com/intellij-rust/intellij-rust/commit/f82f6cd68567e574bf1e30f5e0d263ee15d1d36e)\n    when parsing Rust.\n\nNote that these approaches are not entirely equivalent to each other. In Rust,\nfor example, the difference is observable in proc macros. Also, using any kind\nof token merging or splitting approach would result in the token stream not\nmatching the interpretation of the program, which is problematic for tooling.\nFor example, many common Rust syntax highlighters do not properly highlight\nchained tuple indexing.\n\n### Decimal indexing restriction\n\nCarbon follows Rust and Swift in restricting tuple indexes to being decimal\nintegers:\n\n```carbon\n// OK\nlet a: i32 = (1, 2, 3).0;\n\n// Error, invalid index for tuple element.\nlet b: i32 = (1, 2, 3).0x0;\n```\n\nThis restriction introduces an inconsistency between `.0x0` and `.(0x0)`, and we\ncould easily drop it. However, the restriction allows us to consider `.0`, `.1`,\nand so on to simply be the names of the tuple elements, analogous to struct\nfield names, and there isn't a clear utility for permitting a base prefix or a\ndigit separator in a tuple index.\n\n### Square bracket notation\n\nInstead of `tuple.0` and `tuple.(IndexConstant)`, we could use `tuple[0]` and\n`tuple[IndexConstant]`. This would result in more consistent syntax for indexing\nwith a constant versus with an expression, but would make accessing an element\nof a tuple less consistent with accessing an element of a struct. We expect\ntuple access with a non-literal index to be a rare operation, so the consistency\nwith that syntax seems to have lower value.\n\nAlso, the use of `.` notation aims to convey the intent of the developer better:\nwe intend `x[n]` notation to be used primarily for _homogenous_ indexing,\nwhereas `.` notation is used for _heterogenous_ access. This also reflects the\ndifference in phase: tuple indexing requires a constant index in the same way\nthat struct member access requires a constant name, whereas array or container\nindexing would typically be expected to permit a runtime index.\n\nThe `.N` notation can also be extended to perform member indexing into a struct\nor class, at least the latter of which would not be reasonable to support with\n`[]` notation. However, such support is not part of this proposal.\n\nUse of `[]` notation has the advantage of reducing visual ambiguity for cases\nsuch as `O.0`, `l.0`, and `Z.0`, which might be visually confused with `0.0`,\n`1.0`, and `2.0`, respectively. However, we're not aware of this being a problem\nin practice in Rust or Swift, which use this notation, and the same problem\nexists even without the `.0` suffix: `F(O, l, Z)` may resemble `F(0, 1, 2)`.\n\n### Negative indexing from the end of the tuple\n\nWe could support `tuple.-1`, or perhaps `tuple.(-1)`, as a notation for \"the\nlast element of the tuple\", as used for example in Python. We choose not to\nsupport this at this time because such notation can be confusing and has awkward\nedge cases. An off-by-one error, or an attempt to access a one-past-the-start\nelement, will sometimes be accepted and silently do the wrong thing.\n\nIf a future proposal introduces tuple slicing, it should revisit this question,\nbecause this kind of indexing from the end is often desirable when forming a\nslice. The possibility of using a different notation for this operation should\nbe considered, such as `tuple.(.size - 1)`.\n\n### Trailing commas\n\nCarbon permits optional trailing commas in tuples, with mandatory trailing\ncommas for one-tuples. Alternatives to this choice were considered in\n[leads issue #2191](https://github.com/carbon-language/carbon-lang/issues/2191).\n"
  },
  {
    "path": "proposals/p3720.md",
    "content": "# Member binding operators\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3720)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Inheritance and other implicit conversions](#inheritance-and-other-implicit-conversions)\n    -   [Data fields](#data-fields)\n    -   [Generic type of a class member](#generic-type-of-a-class-member)\n        -   [Methods](#methods)\n        -   [Fields](#fields)\n    -   [C++ pointer to member](#c-pointer-to-member)\n    -   [Instance interface members](#instance-interface-members)\n    -   [Non-instance interface members](#non-instance-interface-members)\n    -   [C++ operator overloading](#c-operator-overloading)\n-   [Future work](#future-work)\n    -   [Future: tuple indexing](#future-tuple-indexing)\n    -   [Future: properties](#future-properties)\n    -   [Future: building block for language features such as API extension](#future-building-block-for-language-features-such-as-api-extension)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Swap the member binding interface parameters](#swap-the-member-binding-interface-parameters)\n    -   [Member binding to references produces a value that wraps a pointer](#member-binding-to-references-produces-a-value-that-wraps-a-pointer)\n    -   [Separate interface for compile-time member binding instead of type member binding](#separate-interface-for-compile-time-member-binding-instead-of-type-member-binding)\n    -   [Non-instance members are idempotent under member binding](#non-instance-members-are-idempotent-under-member-binding)\n    -   [Separate `Result` types for `BindToValue` and `BindToRef`](#separate-result-types-for-bindtovalue-and-bindtoref)\n    -   [`BindToValue` is a subtype of `BindToRef`](#bindtovalue-is-a-subtype-of-bindtoref)\n    -   [Directly rewrite all calls to interface member functions to method call intrinsics](#directly-rewrite-all-calls-to-interface-member-functions-to-method-call-intrinsics)\n\n<!-- tocstop -->\n\n## Abstract\n\nDefine the member binding operation used to compute the result of `x.y`, `p->y`,\n`x.(C.y)`, and `p->(C.y)` as calling a method from user-implementable\ninterfaces.\n\n## Problem\n\nWhat happens when member binding is performed between an object instance and a\nmember of its type? We'd like to define the semantics in a way that is simple,\northogonal, supports the use cases from C++, allows users to express their\nintent in code in a natural and predictable way that is consistent with other\nCarbon constructs, and is consistent with Carbon's goals.\n\nConsider a class with a method and a field:\n\n```carbon\nclass C {\n  fn M[self: Self]();\n  var f: i32;\n}\nvar x: C = {.f = 2};\n```\n\nThe expressions `C.M` and `C.f` correspond roughly to\n[C++ pointers to members](https://en.cppreference.com/w/cpp/language/pointer#Pointers_to_members).\nThey may be used to access the members of `x` using Carbon's\n[compound member syntax](/docs/design/expressions/member_access.md), as in\n`x.(C.M)` or `x.(C.f)`. What is their type? Can they be passed to a function\nseparately from the instance of `C` to bind with it?\n\nThe expression `x.M` on the other hand doesn't have a trivial correspondence in\nC++ despite being a useful to bind a specific instance and produce a stand-alone\ncallable object. We would like a model that allows `x.M` to be meaningful in a\nway that is consistent with the existing meaning of `x.f` and generalizes well\nacross different kinds of methods and callables.\n\nAnother issue is how we clearly delineate the `self` associated with a method\nsignature as separate from the `self` of function values.\n\n## Background\n\nMember access has been specified in two proposals:\n\n-   [Proposal #989: Member access expressions](https://github.com/carbon-language/carbon-lang/pull/989)\n-   [Proposal #2360: Types are values of type `type`](https://github.com/carbon-language/carbon-lang/pull/2360)\n\nThe results of these proposals is recorded in the\n[\"qualified names and member access\" design document](/docs/design/expressions/member_access.md).\nNotably, there is the process of\n[instance binding](/docs/design/expressions/member_access.md#instance-binding),\nthat can convert a method into a bound method. This is described as an\nuncustomizable process, with the members of classes being non-first-class names.\n\nWith\n[proposal #3646: Tuples and tuple indexing](https://github.com/carbon-language/carbon-lang/pull/3646),\ntuple indexing also uses the member-access syntax, except with numeric names for\nthe fields.\n\nThe currently accepted proposals for functions, most notably\n[Proposal #2875: Functions, function types, and function calls](https://github.com/carbon-language/carbon-lang/pull/2875),\ndon't support all of the different function signatures for the `Call` interface.\nFor example, it does not support `addr self` or explicit compile-time\nparameters. That is out of scope of this proposal, and will be addressed\nseparately, and means that `addr self` methods won't be considered here. The\ndifference between functions and methods, however, is in scope.\n\nOther languages, such as\n[C#](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/delegates/using-delegates)\nand [D](https://tour.dlang.org/tour/en/basics/delegates), have constructs that\nrepresent bound and unbound methods, such as \"delegates\".\n\n## Proposal\n\nWe propose that Carbon defines the compound member access operator, specifically\n`x.(y)`, in terms of rewrites to invoking an interface method, like other\noperators. There are three different interfaces used, depending on whether `x`\nis a value expression, a reference expression, or a facet:\n\n```carbon\n// This determines the type of the result of member binding. It is\n// a separate interface shared by `BindToValue` and `BindToRef` to\n// ensure they produce the same result type. We don't want the\n// type of an expression to depend on the expression category\n// of the arguments.\ninterface Bind(T:! type) {\n  let Result:! type;\n}\n\n// For a value expression `x` with type `T` and an expression\n// `y` of type `U`, `x.(y)` is `y.((U as BindToValue(T)).Op)(x)`\ninterface BindToValue(T:! type) {\n  extend Bind(T);\n  fn Op[self: Self](x: T) -> Result;\n}\n\n// For a reference expression `x` using a member binding `var x: T`\n// and an expression `y` of type `U`, `x.(y)` is\n// `*y.((U as BindToRef(T)).Op)(&x)`\ninterface BindToRef(T:! type) {\n  extend Bind(T);\n  fn Op[self: Self](p: T*) -> Result*;\n}\n\n// For a facet value, which includes all type values, `T` and\n// an expression `y` of type `U`, `T.(y)` is\n// `y.((U as BindToType(T)).Op)()`.\ninterface BindToType(T:! type) {\n  let Result:! type;\n  fn Op[self: Self]() -> Result;\n}\n```\n\n> **Note:** `BindToType` is its own interface since the members of a type are\n> defined by their values, not by their type. Observe that this means that a\n> generic function might not use `BindToType` on a symbolic value that was not\n> known to be a facet, where it would use `BindToType` on the concrete value.\n\nThe other member access operators -- `x.y`, `x->y`, and `x->(y)` -- are defined\nby how they rewrite into the `x.(y)` form using these two rules:\n\n-   `x.y` is interpreted using the existing\n    [member resolution rules](/docs/design/expressions/member_access.md#member-resolution).\n    For example, `x.y` is treated as `x.(T.y)` for non-type values `x` with type\n    `T`.\n    -   Simple member access of a facet `T`, as in `T.y`, is not rewritten into\n        the `T.(`\\_\\_\\_`)` form.\n-   `x->y` and `x->(y)` are interpreted as `(*x).y` and `(*x).(y)` respectively.\n\n## Details\n\nTo use instance members of a class, we need to go through the additional step of\n_member binding_. Consider a class `C`:\n\n```carbon\nclass C {\n  fn F[self: Self]() -> i32 { return self.x + 5; }\n  fn Static() -> i32 { return 2; }\n  var x: i32;\n}\n```\n\nEach member of `C` with a distinct name will have a corresponding type (like\n`__TypeOf_C_F`) and value of that type (like `__C_F`). There are two more types\nfor each member function (either static class function or method), though, that\n[adapt](/docs/design/generics/terminology.md#adapting-a-type) `C` and represent\nthe type of binding that member with either a `C` value or variable.\n\n```carbon\nclass __TypeOf_C_F {}\nlet __C_F:! __TypeOf_C_F = {};\nclass __Binding_C_F {\n  adapt C;\n}\n\n// and similarly for Static\n```\n\nThese are the types that result from\n[instance binding](/docs/design/expressions/member_access.md#instance-binding)\nan instance of `C` with these member names. They define the bound method value\nand bound method type of [proposal #2875](/proposals/p2875.md#bound-methods).\nFor example,\n\n```carbon\nlet v: C = {.x = 3};\nAssert(v.F() == 8);\nAssert(v.Static() == 2);\nvar r: C = {.x = 4};\nAssert(r.F() == 9);\nAssert(r.Static() == 2);\n```\n\nis interpreted as:\n\n```carbon\nlet v: C = {.x = 3};\nAssert((v as __Binding_C_F).(Call(()).Op)() == 8);\nAssert((v as __Binding_C_Static).(Call(()).Op)() == 2);\nvar r: C = {.x = 4};\nAssert((r as __Binding_C_F).(Call(()).Op)() == 9);\nAssert((r as __Binding_C_Static).(Call(()).Op)() == 2);\n```\n\nHow does this arise?\n\n1. First the simple member access is resolved using the type of the receiver: \\\n   `v.F` -> `v.(C.F)`, `v.Static` -> `v.(C.Static)`, `r.F` -> `r.(C.F)`,\n   `r.Static` -> `r.(C.Static)`. \\\n   Note that `C.F` is `__C_F` with type `__TypeOf_C_F`, and `C.Static` is\n   `__C_Static` with type `__TypeOf_C_Static`.\n2. It then looks at the expression to the left of the `.`:\n    - If it is a facet value, the \"member binding to type\" (`BindToType`)\n      operator is applied.\n    - If it is a reference expression, the \"member binding to reference\"\n      (`BindToRef`) operator is applied.\n    - If it is a value expression, the \"member binding to value\" (`BindToValue`)\n      operator is applied.\n3. The result of the member binding has a type that implements the call\n   interface.\n\n> **Note:** The current wording in\n> [member_access.md](/docs/design/expressions/member_access.md) says that\n> `v.(C.Static)` and `r.(C.Static)` are both invalid, because they don't perform\n> member name lookup, instance binding, nor impl lookup -- the `v.` and `r.`\n> portions are redundant. That rule is removed by this proposal.\n>\n> Instead, tools such as linters can highlight such code as suspicious on a\n> best-effort basis, particularly when the issue is contained in a single\n> expression. Such tools may still allow code that performs the same operation\n> across multiple statements, as in:\n>\n> ```carbon\n> let M:! auto = C.Static;\n> v.(M)();\n> r.(M)();\n> ```\n>\n> Note that if `M` is an overloaded name, it could be an instance member in some\n> cases and a non-instance member in others, depending on the arguments passed.\n> This is another reason to delegate this to linters analyzing a whole\n> expression on a best-effort basis, rather than a strict rule just about member\n> binding.\n\nThe member binding operators are defined using three dedicated interfaces --\n`BindToValue`, `BindToRef`, and `BindToType` --\n[as defined in the \"proposal\" section](#proposal). These member binding\noperations are implemented for the types of the class members:\n\n```carbon\nimpl __TypeOf_C_F as BindToValue(C)\n    where .Result = __Binding_C_F {\n  fn Op[unused self: Self](x: C) -> __Binding_C_F {\n    return x as __Binding_C_F;\n  }\n}\n\n// Note that the `Result` type has to match, since\n// it is an associated type in the `Bind(C)` interface\n// that both `BindToValue(C)` and `BindToRef(C)` extend.\nimpl __TypeOf_C_F as BindToRef(C)\n    where .Result = __Binding_C_F {\n  fn Op[unused self: Self](p: C*) -> __Binding_C_F* {\n    return p as __Binding_C_F*;\n  }\n}\n```\n\n> **Note:** `BindToType` is used for\n> [non-instance interface members](#non-instance-interface-members).\n\nThose implementations are how we get from `__C_F` with type `__TypeOf_C_F` to\n`v as __Binding_C_F` or `&r as __Binding_C_F*`, conceptually following these\nsteps:\n\n```carbon\n// `v` is a value and so uses `BindToValue`\nv.F() == v.(C.F)()\n      == v.(__C_F)()\n      == __C_F.((__TypeOf_C_F as BindToValue(C)).Op)(v)()\n      == (v as __Binding_C_F)()\n\n// `r` is a reference expression and so uses `BindToRef`\nr.F() == r.(C.F)()\n      == r.(__C_F)()\n      == (*__C_F.((__TypeOf_C_F as BindToRef(C)).Op)(&r))()\n      == (*(&r as __Binding_C_F*))()\n```\n\nHowever, to avoid recursive application of these same rules, we need to avoid\nexpressing this in terms of evaluating `__C_F.(`...`)`. Instead the third step\nuses an intrinsic compiler primitive, as in:\n\n```carbon\n// `v` is a value and so uses `BindToValue`\nv.F() == v.(C.F)()\n      == v.(__C_F)()\n      == inlined_method_call_compiler_intrinsic(\n              <function body (__TypeOf_C_F as BindToValue(C)).Op overload 0>,\n              __C_F, (v))()\n      == (v as __Binding_C_F)()\n\n// `r` is a reference expression and so uses `BindToRef`\nr.F() == r.(C.F)()\n      == r.(__C_F)()\n      == (*inlined_method_call_compiler_intrinsic(\n              <function body (__TypeOf_C_F as BindToRef(C)).Op overload 0>,\n              __C_F, (&r)))()\n      == (*(&r as __Binding_C_F*))()\n```\n\nAt this point we have resolved the member binding, and are left with an\nexpression of type `__Binding_C_F` followed by `()`. In the first case, that\nexpression is a value expression. In the second case, it is a reference\nexpression.\n\nThe last ingredient is the implementation of the call interfaces for these bound\ntypes.\n\n```carbon\n// Member binding with `C.F` produces something with type\n// `__Binding_C_F` whether it is a value or reference\n// expression. Since `C.F` takes `self: Self` it can be\n// used in both cases.\nimpl __Binding_C_F as Call(()) with .Result = i32 {\n  fn Op[self: Self]() -> i32 {\n    // Calls `(self as C).(C.F)()`, but without triggering\n    // member binding again.\n    return inlined_method_call_compiler_intrinsic(\n        <function body C.F overload 0>, self as C, ());\n  }\n}\n\n// `C.Static` works the same as `C.F`, except it also\n// implements the call interfaces on `__TypeOf_C_Static`.\n// This allows `C.Static()` to work, in addition to\n// `v.Static()` and `r.Static()`.\nimpl __Binding_C_Static as Call(()) with .Result = i32 {\n  // Other implementations of `Call(())` are the same.\n  fn Op[unused self: Self]() -> i32 {\n    // Calls `C.Static()`, without triggering member binding again.\n    return inlined_call_compiler_intrinsic(\n               <function body C.Static overload 0>, ());\n  }\n}\nimpl __TypeOf_C_Static as Call(()) where .Result = i32;\n```\n\nGoing back to `v.F()` and `r.F()`, after member binding the next step is to\nresolve the call. As described in\n[proposal #2875](https://github.com/carbon-language/carbon-lang/pull/2875), this\ncall is rewritten to an invocation of the `Op` method of the `Call(())`\ninterface, using the implementations just defined. Note:\n\n-   Passing `*(&r as __Binding_C_F*)` to the `self` parameter of `Call(()).Op`\n    converts the reference expression to a value. Note that mutating\n    (`addr self`) methods are [out of scope for this proposal](#background).\n-   The `Call` interface is special. We don't\n    [rewrite](#instance-interface-members) calls to `Call(__).Op` to avoid\n    infinite recursion.\n\n```carbon\nv.F() == (v as __Binding_C_F)()\n      == (v as __Binding_C_F).((__Binding_C_F as Call(())).Op)()\n      == inlined_method_call_compiler_intrinsic(\n            <function body (__Binding_C_F as Call(())).Op overload 0>,\n            v as __Binding_C_F, ());\n      == inlined_method_call_compiler_intrinsic(\n             <function body C.F overload 0>,\n             (v as __Binding_C_F) as C, ())\n      == inlined_method_call_compiler_intrinsic(\n             <function body C.F overload 0>, v, ())\n\nr.F() == (*(&r as __Binding_C_F*))()\n      == (*(&r as __Binding_C_F*)).((__Binding_C_F as Call(())).Op)()\n      == inlined_method_call_compiler_intrinsic(\n            <function body (__Binding_C_F as Call(())).Op overload 0>,\n            *(&r as __Binding_C_F*) <as value expression>, ());\n      == inlined_method_call_compiler_intrinsic(\n             <function body C.F overload 0>,\n             *(&r as __Binding_C_F*) as C, ())\n      == inlined_method_call_compiler_intrinsic(\n             <function body C.F overload 0>,\n             r <as value expression>, ())\n```\n\n> **Note:** This rewrite results in compiler intrinsics for calling. This is to\n> show that no more rewrites are applied.\n\n### Inheritance and other implicit conversions\n\nNow consider methods of a base class:\n\n```carbon\nbase class B {\n  fn F[self: Self]();\n  virtual fn V[self: Self]();\n}\n\nclass D {\n  extend base: B;\n  impl fn V[self: Self]();\n}\n\nvar d: D = {}\nd.(B.F)();\nd.(B.V)();\n```\n\nTo allow this to work, we need the implementation of the member binding\ninterfaces to allow implicit conversions:\n\n```carbon\nimpl [T:! ImplicitAs(B)] __TypeOf_B_F as BindToValue(T)\n    where .Result = __Binding_B_F {\n  fn Op[self: Self](x: T) -> __Binding_B_F {\n    return (x as B) as __Binding_B_F;\n  }\n}\n\nimpl [T:! type where .Self* impls ImplicitAs(B*)]\n    __TypeOf_B_F as BindToRef(T)\n    where .Result = __Binding_B_F {\n  fn Op[self: Self](p: T*) -> __Binding_B_F* {\n    return (p as B*) as __Binding_B_F*;\n  }\n}\n```\n\nThis matches the expected semantics of method calls, even for methods of final\nclasses.\n\nNote that the implementation of the member binding interfaces is where the\n`Self` type of a method is used. If that type is different from the class it is\nbeing defined in, as considered in\n[#1345](https://github.com/carbon-language/carbon-lang/issues/1345), that will\nbe reflected in the member binding implementations.\n\n```carbon\nclass C {\n  // Note: not `self: Self` or `self: C`!\n  fn G[self: Different]();\n}\n\nlet c: C = {};\n// `c.G()` is only allowed if there is an implicit\n// conversion from `C` to `Different`.\n\nlet d: Different = {};\n// Allowed:\nd.(C.G)();\n```\n\nresults in an implementation using `Different` instead of `C`:\n\n```carbon\n// `C.G` will only member bind to values that can implicitly convert\n// to type `Different`.\nimpl [T:! ImplicitAs(Different)] __TypeOf_C_G as BindToValue(T)\n    where .Result = __Binding_C_G;\n```\n\n### Data fields\n\nThe same `BindToValue` and `BindToRef` operations allow us to define access to\nthe data fields in an object, without any additional changes.\n\nFor example, given a class with a data member `m` with type `i32`:\n\n```carbon\nclass C {\n  var m: i32;\n}\n```\n\nwe want the usual operations to work, with `x.m` equivalent to `x.(C.m)`:\n\n```carbon\nlet v: C = {.m = 4};\nvar x: C = {.m = 3};\nx.m += 5;\nAssert(x.(C.m) == v.m + v.(C.m));\n```\n\nTo accomplish this we will, as before, associate an empty (stateless or\nzero-sized) type with the `m` member of `C`, that just exists to support the\nmember binding operation. However, this time the result type of member binding\nis simply `i32`, the type of the variable, instead of a new, dedicated type.\n\n```carbon\nclass __TypeOf_C_m {}\nlet __C_m:! __TypeOf_C_m = {};\n\nimpl __TypeOf_C_m as BindToValue(C) where .Result = i32 {\n  fn Op[self: Self](x: C) -> i32 {\n    // Effectively performs `x.m`, but without triggering member binding again.\n    return value_compiler_intrinsic(x, __OffsetOf_C_m, i32)\n  }\n}\n\nimpl __TypeOf_C_m as BindToRef(C) where .Result = i32 {\n  fn Op[self: Self](p: C*) -> i32* {\n    // Effectively performs `&p->m`, but without triggering member binding again,\n    // by doing something like `((p as byte*) + __OffsetOf_C_m) as i32*`\n    return offset_compiler_intrinsic(p, __OffsetOf_C_m, i32);\n  }\n}\n```\n\nThese definitions give us the desired semantics:\n\n```carbon\n// For value `v` with type `T` and `y` of type `U`,\n// `v.(y)` is `y.((U as BindToValue(T)).Op)(v)`\nv.m == v.(C.m)\n    == v.(__C_m)\n    == v.(__C_m as (__TypeOf_C_m as BindToValue(C)))\n    == __C_m.((__TypeOf_C_m as BindToValue(C)).Op)(v)\n    == value_compiler_intrinsic(v, __OffsetOf_C_m, i32)\n\n// For reference expression `var x: T` and `y` of type `U`,\n// `x.(y)` is `*y.(U as BindToRef(T)).Op(&x)`\nx.m == x.(C.m)\n    == x.(__C_m)\n    == *__C_m.((__TypeOf_C_m as BindToRef(C)).Op)(&x)\n    == *offset_compiler_intrinsic(&x, __OffsetOf_C_m, i32)\n// Note that this requires `x` to be a reference expression,\n// so `&x` is valid, and produces a reference expression,\n// since it is the result of dereferencing a pointer.\n```\n\nThe fields of [tuple types](/docs/design/tuples.md) and\n[struct types](/docs/design/classes.md#struct-types) operate the same way.\n\n```carbon\nlet t_let: (i32, i32) = (3, 6);\nAssert(t_let.(((i32, i32) as type).0) == 3);\n\nvar t_var: (i32, i32) = (4, 8);\nAssert(t_var.(((i32, i32) as type).1) == 8);\nt_var.(((i32, i32) as type).1) = 9;\nAssert(t_var.1 == 9);\n\nlet s_let: {.x: i32, .y: i32} = {.x = 5, .y = 10};\nAssert(s_let.({.x: i32, .y: i32}.x) == 5);\n\nvar s_var: {.x: i32, .y: i32} = {.x = 6, .y = 12};\nAssert(s_var.({.x: i32, .y: i32}.y) == 12);\ns_var.({.x: i32, .y: i32}.y) = 13;\nAssert(s_var.y == 13);\n```\n\nFor example, `{.x: i32, .y: i32}.x` is a value `__Struct_x_i32_y_i32_Field_x`,\nanalogous to `__C_m`, of a type `__TypeOf_Struct_x_i32_y_i32_Field_x` (that is\nzero-sized / has no state), analogous to `__TypeOf_C_m`, that implements the\nmember binding interfaces for any type that implicitly converts to\n`{.x: i32, .y: i32}`.\n\nNote that for tuples, the `as type` is needed since `(i32, i32)` on its own is a\ntuple, not a type. In particular `(i32, i32)` is not the type of `t_let` or\n`t_var`. `(i32, i32).0` is just `i32`, and isn't the name of the first element\nof an `(i32, i32)` tuple.\n\n### Generic type of a class member\n\nGiven the above, we can now write a constraint on a symbolic parameter to match\nthe names of an unbound class member. There are a two cases: methods and fields.\n\n#### Methods\n\nRestricting to value methods, since mutating (`addr self`) methods are\n[out of scope for this proposal](#background), the receiver object may be passed\nby value. To be able to call the method, we must include a restriction that the\nresult of `BindToValue` implements `Call(())`:\n\n```carbon\n// `m` can be any method object that implements `Call(())` once bound.\nfn CallMethod\n    [T:! type, M:! BindToValue(T) where .Result impls Call(())]\n    (x: T, m: M) -> auto {\n  // `x.(m)` is rewritten to a call to `BindToValue(T).Op`. The\n  // constraint on `M` ensures the result implements `Call(())`.\n  return x.(m)();\n}\n```\n\nThis will work with any value method or static class function. This will also\nwork with inheritance and virtual methods, using\n[the support for implicit conversions of self](#inheritance-and-other-implicit-conversions).\n\n```carbon\nbase class X {\n  virtual fn V[self: Self]() -> i32 { return 1; }\n  fn B[self: Self]() -> i32 { return 0; }\n}\nclass Y {\n  extend base: X;\n  impl fn V[self: Self]() -> i32 { return 2; }\n}\nclass Z {\n  extend base: X;\n  impl fn V[self: Self]() -> i32 { return 3; }\n}\n\nvar (x: X, y: Y, z: Z);\n\n// Respects inheritance\nAssert(CallMethod(x, X.B) == 0);\nAssert(CallMethod(y, X.B) == 0);\nAssert(CallMethod(z, X.B) == 0);\n\n// Respects method overriding\nAssert(CallMethod(x, X.V) == 1);\nAssert(CallMethod(y, X.V) == 2);\nAssert(CallMethod(z, X.V) == 3);\n```\n\n#### Fields\n\nFields can be accessed, given the type of the field\n\n```carbon\nfn GetField\n    [T:! type, F:! BindToValue(T) where .Result = i32]\n    (x: T, f: F) -> i32 {\n  // `x.(f)` is rewritten to `f.((F as BindToValue(T)).Op)(x)`,\n  // and `(F as BindToValue(T)).Op` is a method on `f` with\n  // return type `i32` by the constraint on `F`.\n  return x.(f);\n}\n\nfn SetField\n    [T:! type, F:! BindToRef(T) where .Result = i32]\n    (x: T*, f: F, y: i32) {\n  // `x->(f)` is rewritten to `(*x).(f)`, which then\n  // becomes: `*f.((F as BindToRef(T)).Op)(&*x)`\n  // The constraint `F` says the return type of\n  // `(F as BindToRef(T)).Op` is `i32*`, which is\n  // dereferenced to get an `i32` reference expression\n  // which may then be assigned.\n  x->(f) = y;\n}\n\nclass C {\n  var m: i32;\n  var n: i32;\n}\nvar c: C = {.m = 5, .n = 6};\nAssert(GetField(c, C.m) == 5);\nAssert(GetField(c, C.n) == 6);\nSetField(&c, C.m, 42);\nSetField(&c, C.n, 12);\nAssert(GetField(c, C.m) == 42);\nAssert(GetField(c, C.n) == 12);\n```\n\n### C++ pointer to member\n\nIn [the generic type of member section](#generic-type-of-a-class-member), the\nnames of members, such as `D.K`, `X.B`, `X.V`, and `C.n`, refer to zero-sized /\nstateless objects where all the offset information is encoded in the type.\nHowever, the definitions of `CallMethod`, `SetField`, and `GetField` do not\ndepend on that fact and will be usable with objects, such as C++\npointers-to-members, that include the offset information in the runtime object\nstate. So we can define member binding implementations for them so that they may\nbe used with Carbon's `.(`**`)` and `->(`**`)` operators.\n\nFor example, this is how we expect C++ code to call the above Carbon functions:\n\n```cpp\nstruct C {\n  int F() const { return m + 1; }\n  int m;\n};\n\nint main() {\n  // pointer to data member `m` of class C\n  int C::* p = &C::m;\n  C c = {2};\n  assert(c.*p == 2);\n  assert(Carbon::GetField(c, p) == 2);\n  Carbon::SetField(&c, p, 4);\n  assert(c.m == 4);\n  // pointer to method `F` of class C\n  int (C::*q)() const = &C::F;\n  assert(Carbon::CallMethod(&c, q) == 5);\n}\n```\n\n### Instance interface members\n\nInstance members of an interface, such as methods, can use this framework. For\nexample, given these declarations:\n\n```carbon\ninterface I {\n  fn F[self: Self]();\n}\nclass C {\n  impl as I;\n}\nlet c: C = {};\n```\n\nThen `I.F` is its own value with its own type:\n\n```carbon\nclass __TypeOf_I_F {}\nlet __I_F:! __TypeOf_I_F = {};\n```\n\nThat type implements `BindToValue` for any type that implements the interface\n`I`:\n\n```carbon\nclass __Binding_I_F(T:! I) {\n  adapt T;\n}\nimpl forall [T:! I] __TypeOf_I_F as BindToValue(T)\n    where .Result = __Binding_I_F(T) {\n  fn Op[self: Self](x: T) -> __Binding_I_F(T) {\n    // Valid since `__Binding_I_F(T)` adapts `T`:\n    return x as __Binding_I_F(T);\n  }\n}\n```\n\nThe actual dispatch to the `I.F` method of `C` happens in the implementation of\nthe `Call` interface of this adapter type that is the result of member binding\nto a value. So, this implementation of `C as I`:\n\n```carbon\nimpl C as I {\n  fn F[self: Self]() {\n    Fanfare(self);\n  }\n}\n```\n\nResults in this implementation:\n\n```carbon\nimpl __Binding_I_F(C) as Call(()) where .Result = () {\n  fn Op[self: Self]() {\n    inlined_method_call_compiler_intrinsic(\n        <function body (C as I).F overload 0>, self as C, ());\n  }\n}\n```\n\nA call such as `c.(I.F)()` goes through these rewrites:\n\n```carbon\nc.(I.F)() == c.(__I_F)()\n          == __I_F.((__TypeOf_I_F as BindToValue(C)).Op)(c)()\n          == (c as __Binding_I_F(C))()\n          == (c as __Binding_I_F(C)).((__Binding_I_F(C) as Call(())).Op)()\n```\n\nWhich results in invoking the above implementation that will ultimately call\n`Fanfare(c)`.\n\n> **Note:** The `Call` interface gets special treatment and does not get these\n> rewrites to avoid recursing forever.\n\n### Non-instance interface members\n\nNon-instance members use the `BindToType` interface instead. For example, if `G`\nis a non-instance function of an interface `J`:\n\n```carbon\ninterface J {\n  fn G();\n}\nimpl C as J;\n```\n\nAgain the member is given its own type and value:\n\n```carbon\nclass __TypeOf_J_G {}\nlet __J_G:! __TypeOf_J_G = {};\n```\n\nSince this is a non-instance member, this type implements `BindToType` instead\nof `BindToValue`:\n\n```carbon\nclass __TypeBinding_J_G(T:! J) {}\nimpl forall [T:! J] __TypeOf_J_G as BindToType(T)\n    where .Result = __TypeBinding_J_G(T) {\n  fn Op[self: Self]() -> __TypeBinding_J_G(T) {\n    return {};\n  }\n}\n```\n\nSo, this implementation of `C as J`:\n\n```carbon\nimpl C as J {\n  fn G() {\n    Fireworks();\n  }\n}\n```\n\nResults in this implementation:\n\n```carbon\nimpl __TypeBinding_J_G(C) as Call(()) where .Result = () {\n  fn Op[self: Self]() {\n    Fireworks();\n  }\n}\n```\n\nA call such as `C.(J.G)()` goes through these rewrites:\n\n```carbon\nC.(J.G)() == C.(__J_G)()\n          == __J_G.((__TypeOf_J_G as BindToType(C)).Op)()()\n          == ({} as __TypeBinding_J_G(C))()\n          == (({} as __TypeBinding_J_G(C)) as Call(())).Op()\n```\n\nWhich calls the above implementation that calls `Fireworks()`.\n\n> **Note:** Member binding for non-instance members doesn't work with\n> `BindToValue`, we need `BindToType`. Otherwise there is no way to get the\n> value `C` into the result type. Furthermore, we want `BindToType`\n> implementation no matter which facet of the type is used in the code.\n\n### C++ operator overloading\n\nC++ does not support customizing the behavior of `x.y`. It does support\ncustomizing the behavior of `operator*` and `operator->` which is frequently\nused to support smart pointers and iterators. There is, however, nothing\nrestricting the implementations of those two operators to be consistent, so that\n`(*x).y` and `x->y` are the same.\n\nCarbon instead will only have a single interface for customizing dereference,\ncorresponding to `operator*` not `operator->`. All uses of `x->y` will be\nrewritten to use `(*x).y` instead. This may cause some friction when porting C++\ncode where those operators are not consistent. If the C++ code is just missing\nthe definition of `operator*` corresponding to an `operator->`, a workaround\nwould be just to define `operator*`.\n\nOther cases of divergence between those operators should be rare, since that is\nboth surprising to users and for the common case of iterators, violates the C++\nrequirements. If necessary, we can in the future introduce a specific construct\njust for C++ interop that invokes the C++ arrow operator, such as\n`CppArrowOperator(x)`, that returns a pointer.\n\n**Context:** This was discuseed in\n[2024-02-29 open discussion](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.5vj8ohrvqjqh)\nand in\n[a comment on this proposal](https://github.com/carbon-language/carbon-lang/pull/3720/files#r1507917882).\n\n## Future work\n\n### Future: tuple indexing\n\nWe can reframe the use of the compound member access syntax for tuple fields as\nan implementation of member binding of tuples with compile-time integer\nexpressions. The specifics of how this works will be resolved later, once we\naddress how compile-time interacts with interfaces.\n\n### Future: properties\n\nIf there was a way to implement the member binding operator to only produce\nvalues, even when the expression to the left of the `.` was a reference\nexpression, then that could be used to implement read-only properties. This\nwould support something like:\n\n```carbon\nlet Pi: f64 = 3.1415926535897932384626433832795;\n\nclass Circle {\n  var radius: f64;\n  read_property area -> f64 {\n    return Pi * self.radius * self.radius;\n  }\n}\n\nlet c: Circle = {.radius = 2};\nAssert(NearlyEqual(c.area, 4 * Pi));\n```\n\nIn this example, the member binding of `c` of type `Circle` to `Circle.area`\nwould perform the computation and return the result as an `f64`.\n\nIf there was some way to customize the result of member binding, this could be\nextended to support other kinds of properties, such as mutable properties that\nuse `get` and `set` methods to access and mutate the value. The main obstacle to\nany support for properties with member binding is how the customization would be\ndone. The most natural way to support this customization would be to have\nmultiple interfaces. The compiler would try them in a specified order and use\nthe one it found first. This has the downside of the possibility of different\nbehavior in a checked generic context where only some of the implementations are\nvisible. Our choice to\n[make the result type the same `Result` associated type of the `Bind` interface](#proposal)\nindependent of whether the `BindToValue` or `BindToRef` interface is used makes\nthis less concerning. Only the phase of the result, not the type, would depend\non which implementations were found, similar to\n[how indexing works](/docs/design/expressions/indexing.md).\n\n### Future: building block for language features such as API extension\n\nWe should be able to express other language features, such as API extension, in\nterms of customized member binding, plus possibly some new language primitives.\nThis should be explored in a future proposal.\n\n## Rationale\n\nThis proposal is about:\n\n-   Orthogonality: separating the member binding process as a distinct and\n    independent step of using the members of a type.\n-   Being consistent with our overall strategy for defining operators in terms\n    of interface implementations.\n-   Allows member-binding-related functionality to be defined through\n    [library APIs](/docs/project/principles/library_apis_only.md).\n-   Increases uniformity by making member names into ordinary values with types.\n-   Adds expressiveness, enabling member forwarding, passing a member as an\n    argument, and other use cases.\n\nThese benefits advance Carbon's goals including:\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem):\n    by making it easier to reason about more Carbon entities within Carbon\n    itself, and reducing the number of different concepts that have to be\n    modeled.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n    through increased consistency, uniformity, and expressiveness.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):\n    by adding support for pointer-to-member constructs.\n\n## Alternatives considered\n\n### Swap the member binding interface parameters\n\nWe considered instead making the receiver object the `Self` type of the\ninterface, and using the member type as the parameter to the interface. This\nwould have the advantage of matching the order that they appear in the source,\nconsistent with other operators.\n\n> **Alternative:**\n>\n> ```carbon\n> // For value `x` with type `T` and `y` of type `U`,\n> // `x.(y)` is `x.((T as ValueBind(U)).Op)(y)`\n> interface ValueBind(U:! type) {\n>   extend Bind(U);\n>   fn Op[self: Self](x: U) -> Result;\n> }\n>\n> // For reference expression `var x: T` and `y` of type `U`,\n> // `x.(y)` is `*x.((T as RefBind(U)).Op)(y)`\n> interface RefBind(U:! type) {\n>   extend Bind(U);\n>   fn Op[addr self: Self*](x: U) -> Result*;\n> }\n> ```\n\nThis had some disadvantages however:\n\n-   The binding property is more associated with the member than the receiver.\n-   Some patterns are more awkward in the alternative syntax.\n\nAs an example of this last point, consider a function that takes multiple (or\neven a variadic list) methods to call on a receiver object. With the proposed\napproach, each method type is constrained:\n\n```carbon\n// `m1`, `m2`, and `m3` are methods on class `T`.\nfn Call3Methods[T:! type,\n                M1:! BindToValue(T) where .Result impls Call(()),\n                M2:! BindToValue(T) where .Result impls Call(()),\n                M3:! BindToValue(T) where .Result impls Call(())]\n    (x: T, m1: M1, m2: M2, m3: M3) -> auto;\n```\n\nWith the alternative, the type of the receiver would be constrained, and the\ndeduced types would be written in a different order:\n\n> **Alternative:**\n>\n> ```carbon\n> // `m1`, `m2`, and `m3` are methods on class `T`.\n> fn Call3MethodsAlternative1\n>     [M1:! type, M2:! type, M3:! type,\n>      T:! ValueBid(M1) & ValueBind(M2) & ValueBind(M3)\n>          where .(ValueBind(M1).Result) impls Call(())\n>            and .(ValueBind(M2).Result) impls Call(())\n>            and .(ValueBind(M3).Result) impls Call(())]\n>     (x: T, m1: M1, m2: M2, m3: M3) -> auto;\n> ```\n\nOr, the constraints can be moved to the method types at the cost of additional\nlength:\n\n> **Alternative:**\n>\n> ```carbon\n> // `m1`, `m2`, and `m3` are methods on class `T`.\n> fn Call3MethodsAlternative2\n>     [T:! type,\n>      M1:! type where T impls (ValueBind(.Self) where .Result impls Call(())),\n>      M2:! type where T impls (ValueBind(.Self) where .Result impls Call(())),\n>      M3:! type where T impls (ValueBind(.Self) where .Result impls Call(()))]\n>     (x: T, m1: M1, m2: M2, m3: M3) -> auto;\n> ```\n\n### Member binding to references produces a value that wraps a pointer\n\nConsider a mutating method on a class:\n\n```carbon\nclass Counter {\n  var count: i32 = 0;\n  fn Increment[addr self: Self*]() {\n    self->count += 1;\n  }\n}\n\nvar c: Counter = {};\n```\n\nThis proposal says `c.Increment` is a reference expression with a type that\nadapts `Counter`. For `c.Increment()` to affect the value of `c.count`, there\nneeds to be some way for the `Call` operator to mutate `c`. The current\ndefinition of `Call` takes `self` by value, though, so this doesn't work.\nAddressing this is [out of scope of the current proposal](#background).\n\nWe could instead make `c.Increment` be a value holding `&c`. That would allow\n`Call` to work even when taking `self` by value. This is the solution likely\nimplied by the current [proposal #2875](/proposals/p2875.md#bound-methods),\nthough that proposal does not say what the bound method type is at all. It\nleaves two other problems, however:\n\n-   We will still need a way to support function objects that are mutated by\n    calling them. This comes up, for example, with C++ types that define\n    `operator()`.\n-   We want the proposed behavior when member binding a [field](#data-fields).\n\nAs a result, it would be better to evaluate this alternative later as part of\nconsidering mutation in calls.\n\n### Separate interface for compile-time member binding instead of type member binding\n\nThe first proposed way to handle\n[non-instance interface members](#non-instance-interface-members) was in\n[the #typesystem channel on Discord on 2024-03-07](https://discord.com/channels/655572317891461132/708431657849585705/1215405895752618134).\nThe suggestion was to have a `CompileBind` interface used for any compile-time\nvalue to the left of the `.`. It would have access to the value, which is needed\nwhen accessing the members of a type.\n\nWe eventually concluded that the special treatment was specifically needed for\ntypes, not all compile-time values. The\n[insight](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.1k8r5fhfwyh6)\nwas that types are special because their members are defined by their values,\nnot by their type\n([which is always `type`](https://github.com/carbon-language/carbon-lang/pull/2360)).\n\n### Non-instance members are idempotent under member binding\n\nIn the current proposal, member binding of non-instance members results in an\nadapter type, the same as an instance member. For example,\n\n```carbon\nclass C {\n  fn Static() -> i32;\n}\n```\n\nis translated into something like:\n\n> **Current proposal:**\n>\n> ```carbon\n> class __TypeOf_C_Static {}\n> let __C_Static:! __TypeOf_C_Static = {};\n>\n> class __Binding_C_Static {\n>   adapt C;\n> }\n>\n> impl __TypeOf_C_Static as BindToValue(C)\n>     where .Result = __Binding_C_Static;\n>\n> impl __TypeOf_C_Static as BindToRef(C)\n>     where .Result = __Binding_C_Static;\n> ```\n\nAn alternative is that member binding of a non-instance member is idempotent, so\nthere is no `__Binding_C_Static` type and `BindToValue(C)` results in a value of\ntype `__TypeOf_C_Static` instead:\n\n> **Alternative:**\n>\n> ```carbon\n> class __TypeOf_C_Static {}\n> // Might need to be a `var` instead?\n> let __C_Static:! __TypeOf_C_Static = {};\n>\n> impl __TypeOf_C_Static as BindToValue(C)\n>     where .Result = __TypeOf_C_Static;\n> impl __TypeOf_C_Static as BindToRef(C)\n>     where .Result = __TypeOf_C_Static;\n> ```\n\nThere are a few concerns with this alternative:\n\n-   This is less consistent with the instance member case.\n-   There would be a discontinuity when adding an instance overload to a name\n    that was previously only a non-instance member.\n-   Member binding to a reference is trickier, since it would have to return the\n    address of an object of type `__TypeOf_C_Static`. Perhaps a global variable?\n-   The current proposal rejects `v.(v.(C.Static))`, which is desirable.\n\nThis was discussed in\n[this comment on #3720](https://github.com/carbon-language/carbon-lang/pull/3720/files#r1513681915).\n\n### Separate `Result` types for `BindToValue` and `BindToRef`\n\nAn earlier iteration of this proposal had separate `Result` associated types for\n`BindToValue` and `BindToRef`, as in:\n\n```carbon\ninterface BindToValue(T:! type) {\n  let Result:! type;\n  fn Op[self: Self](x: T) -> Result;\n}\n\ninterface BindToRef(T:! type) {\n  let Result:! type;\n  fn Op[self: Self](p: T*) -> Result*;\n}\n```\n\nHowever, this results in the type of a member binding depending on the what\n[category](/docs/design/values.md#expression-categories) the expression to the\nleft of the dot has. This could change the interpretation of code using\n[indexing](/docs/design/expressions/indexing.md), such as an expression like\n`a[b].F()`, when the type of `a` is changed from or to a checked generic. This\nis because the the expression is legal as long as the type of `a` implements\n`IndexWith(typeof(b))`, but category of `a[b]` depends on whether the type of\n`a` is known to implement `IndirectIndexWith(typeof(b))`.\n\nTo avoid this problem, we make the result type of the member binding the same\nwhether it is binding to a value or reference. See\n[this comment on #3720](https://github.com/carbon-language/carbon-lang/pull/3720/files/99fb69aaaa24bd502d71cd4259f37cfa8346b244#r1597317217).\n\n### `BindToValue` is a subtype of `BindToRef`\n\nWe could make `BindToValue` be a subtype of `BindToRef`, as suggested in\n[this comment on #3720](https://github.com/carbon-language/carbon-lang/pull/3720/files/99fb69aaaa24bd502d71cd4259f37cfa8346b244#r1597317217).\nThis would be a step beyond just saying they have to have the same `Result`\ntype, which is achieved by that type being defined in the `Bind` interface they\nboth extend.\n\nThis approach would rule out the use case where value binding _computes_ a new\nvalue rather than returning an existing one -- that is, a read-only property.\nThat use case isn't currently well supported by this proposal -- while you can\nmake `x.ComputeSize` work when `x` is a value expression, you can't make it work\nwhen `x` is a reference expression. However, that use case can be supported with\nthe approach described in [future work](#future-properties).\n\n### Directly rewrite all calls to interface member functions to method call intrinsics\n\nIn this proposal, the `Call` interface is given special treatment, in that\ninvoking its method is rewritten into a primitive operation rather than going\nthrough the customizable member binding that other interfaces use. This is\ndescribed in the [Details](#details) and\n[Instance interface members](#instance-interface-members) sections.\n\nIn a comment on #3720\n([1](https://github.com/carbon-language/carbon-lang/pull/3720#discussion_r1597324225),\n[2](https://github.com/carbon-language/carbon-lang/pull/3720/files#r1597324225)),\nwe considered the possibility that invoking any interface member would be\ndirectly rewritten into a primitive operation. We realized the downside of this\napproach in\n[open discussion on 2024-05-16](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.3qlpp5e56u46),\nthat this would not allow interface members to support overloading.\n"
  },
  {
    "path": "proposals/p3762.md",
    "content": "# Merging forward declarations\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3762)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Prior discussion](#prior-discussion)\n    -   [Forward declarations in current design](#forward-declarations-in-current-design)\n    -   [ODR (One definition rule)](#odr-one-definition-rule)\n    -   [Requiring matching declarations to merge](#requiring-matching-declarations-to-merge)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [`extern` keyword](#extern-keyword)\n    -   [When declarations are allowed](#when-declarations-are-allowed)\n        -   [No forward declarations after declarations](#no-forward-declarations-after-declarations)\n        -   [Files must either use an imported declaration or declare their own](#files-must-either-use-an-imported-declaration-or-declare-their-own)\n        -   [Libraries cannot both define an entity and declare it `extern`](#libraries-cannot-both-define-an-entity-and-declare-it-extern)\n        -   [`impl` files with a forward declaration must contain the definition](#impl-files-with-a-forward-declaration-must-contain-the-definition)\n        -   [Type scopes may contain both a forward declaration and definition](#type-scopes-may-contain-both-a-forward-declaration-and-definition)\n    -   [Using `extern` declarations in `extern impl`](#using-extern-declarations-in-extern-impl)\n    -   [`impl` lookup involving `extern` types](#impl-lookup-involving-extern-types)\n    -   [Modifier keywords](#modifier-keywords)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Other modifier keyword merging approaches](#other-modifier-keyword-merging-approaches)\n    -   [No `extern` keyword](#no-extern-keyword)\n    -   [Looser restrictions on declarations](#looser-restrictions-on-declarations)\n    -   [`extern` naming](#extern-naming)\n    -   [Default `extern` to private](#default-extern-to-private)\n    -   [Opaque types](#opaque-types)\n    -   [Require a library provide its own `extern` declarations](#require-a-library-provide-its-own-extern-declarations)\n    -   [Allow cross-package `extern` declarations](#allow-cross-package-extern-declarations)\n-   [Appendix](#appendix)\n    -   [Migration of C++ forward declarations](#migration-of-c-forward-declarations)\n\n<!-- tocstop -->\n\n## Abstract\n\n-   Add the `extern` keyword for forward declarations in libraries that don't\n    provide the definition.\n-   Treat repeated forward declarations as redundant.\n    -   Allow them when they prevent a dependence on an imported name.\n-   Clarify rules for when modifier keywords should be on forward declarations\n    and definitions.\n\n## Problem\n\nA forward declaration can be merged with a definition when they match. However,\nthere is ambiguity about behavior:\n\n-   Whether a forward declaration can be repeated, including after a definition.\n-   Whether a keyword is required to make a forward declaration separate from\n    the implementing library.\n-   Whether modifier keywords need to match between forward declarations and\n    definitions.\n\n## Background\n\n### Prior discussion\n\n-   [Proposal #1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084)\n    covered specifics for `impl` and `interface`.\n-   [Issue #1132: How do we match forward declarations with their definitions?](https://github.com/carbon-language/carbon-lang/issues/1132)\n-   [Issue #3384: are abstract / base specifiers permitted or required on class forward declarations?](https://github.com/carbon-language/carbon-lang/issues/3384)\n    asks one question about which keywords exist on declarations versus\n    definitions. There has also been discussion about what happens for member\n    functions and other situations. At present there is no decision on #3384.\n-   The\n    [2023-11-21 toolchain meeting](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.y377x4v44h2c)\n    had some early discussion regarding forward declarations and the need for a\n    syntactic difference, which evolved to `extern` here.\n-   [On Discord's #syntax on 2024-01-29](https://discord.com/channels/655572317891461132/709488742942900284/1201693766449102878),\n    there was discussion about the question \"What is the intended interaction\n    between declaration modifiers and qualified declaration names?\"\n-   [On Discord's #syntax on 2024-02-23](https://discord.com/channels/655572317891461132/709488742942900284/1210694116955000932),\n    there was discussion that started about how `alias` would resolve forward\n    declaration conflicts. This continued to forward declarations in general,\n    and has discussion about `extern` use.\n    -   This discussion led to a substantial fraction of this proposal.\n\n### Forward declarations in current design\n\nExample rules for forward declarations in the current design:\n\n-   [High-level](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/README.md#declarations-definitions-and-scopes)\n-   [Classes](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/classes.md#forward-declaration)\n-   [Functions](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/functions.md#function-declarations)\n-   Generics:\n    -   [`impl`](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#forward-impl-declaration)\n    -   [`interface`](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#declaring-interfaces-and-named-constraints)\n-   [Matching and agreeing](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#matching-and-agreeing)\n\n### ODR (One definition rule)\n\n[C++'s ODR](https://en.cppreference.com/w/cpp/language/definition) requires each\nentity to have only one definition. C++ has trouble detecting issues at compile\ntime, and linking has trouble catching linker issues too. ODR violation\ndetection is an active problem\n(https://maskray.me/blog/2022-11-13-odr-violation-detection).\n\nThis similarly applies to Carbon. In Carbon, only one library can define an\nentity; other libraries can make forward declarations of it, but those don't\nconstitute a definition. Part of the goal in declaration syntax (`extern` in\nparticular) is to be able to better diagnose ODR violations based on\ndeclarations.\n\n### Requiring matching declarations to merge\n\nWhen two declarations have the same name, either within the same file or through\nimports, they need to \"match\", or will be diagnosed as a conflict. This is laid\nout at under\n[Matching and agreeing](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#matching-and-agreeing)\nin generics. This proposal does not significantly affect these type and name\nrestrictions.\n\nFor example:\n\n-   `fn F(); fn F() {}` could merge because the function signatures match,\n    forward declaring a function is valid, and only one definition is provided.\n-   `fn F(); fn F(x: i32);` won't merge because they differ in parameters,\n    resulting in a diagnostic.\n\n## Proposal\n\n1.  Add `extern` declarations.\n    1.  `extern` is used to mark forward declarations of entities defined in a\n        different library.\n        -   The defining library must declare the entity as public in an `api`\n            file.\n        -   It is invalid for the defining library to declare as `extern`.\n        -   `extern` must only be used for declarations in libraries that don't\n            contain the definition.\n    2.  In modifiers, `extern` comes immediately after access control keywords,\n        and before other keywords.\n    3.  Declaring an entity as `extern` anywhere in a file means it must be used\n        as `extern` _throughout_ that file.\n        -   The entity cannot be used _at all_ prior to the `extern`\n            declaration, even if there is an imported declaration.\n        -   This allows refactoring to add and remove declarations without\n            impacting files that have an `extern`.\n    4.  If a library declares an entity as non-`extern` in either the `api` or\n        `impl`, it is invalid to declare the same entity as `extern` elsewhere\n        within the library.\n2.  An entity may only be forward declared once in a given file. A forward\n    declaration is only allowed before a definition.\n3.  Modifier keywords will be handled on a case-by-case basis for merging\n    declarations.\n\n## Details\n\n### `extern` keyword\n\nAn `extern` modifier keyword is added. It modifies a forward declaration to\nindicate that the entity is not defined by the declaring library. A library\nusing `extern` to declare an entity cannot define that entity. Only the library\nwhich defines an entity can omit `extern`, and omitting `extern` means it must\nprovide a definition.\n\nAn `extern` declaration forms an entity which has no definition or storage. For\nexample:\n\n-   `extern fn` forms a function that can be called.\n-   `extern class` forms an incomplete type.\n-   `extern interface` forms an undefined interface.\n-   `extern var` or `extern let` will bind the name without allocating storage.\n    Initializers are disallowed.\n\nThe `extern` keyword is invalid on declarations that have _only_ a declaration\nsyntax and lack storage, such as `alias` or `namespace`. It is only valid on\nnamespace-scoped names; it is invalid on type-scoped names\n(`class Foo { extern fn Member(); }`).\n\nIn declaration modifiers, `extern` comes immediately after access control\nkeywords, and before other keywords. For example,\n`private extern <other modifiers> class B;`. At present, when `extern` is on a\ndeclaration, only access modifiers are valid (see\n[Modifier keywords](#modifier-keywords)).\n\n### When declarations are allowed\n\nWhen considering whether a declaration is allowed, we apply the rules:\n\n1. A declaration should always add new information.\n    - No declarations after a definition.\n2. Only one library can declare an entity without `extern`.\n3. Support moving declarations between already-imported `api` files without\n   affecting compilation of client libraries.\n\n#### No forward declarations after declarations\n\nIn a file, a forward declaration must never follow a forward declaration or\ndefinition for the same entity.\n\nFor example:\n\n```carbon\nclass A { ... }\n// Invalid: Disallowed after the definition.\nclass A;\n\nclass B;\n// Invalid: Disallowed due to repetition.\nclass B;\n\nclass C;\n// Valid: Allowed because the definition is added.\nclass C { ... }\n```\n\n#### Files must either use an imported declaration or declare their own\n\nIn a file, if a declaration or definition of an entity is imported, the file\nmust choose between either using that version or declaring its own. It cannot do\nboth.\n\nFor example:\n\n```carbon\npackage Foo library \"a\" api;\n\nclass C { ... }\n```\n\n```carbon\npackage Foo library \"b\" api;\nimport library \"a\";\n\nextern class C;\n\n// Valid: Uses the incomplete type of the extern declaration.\nfn Foo(c: C*);\n```\n\n```carbon\npackage Foo library \"c\" api;\nimport library \"a\";\n\n// Valid: Uses the complete type of the imported definition.\nfn Foo(c: C);\n```\n\n```carbon\npackage Foo library \"d\" api;\nimport library \"a\";\n\nfn Foo(c: C);\n\n// Invalid: `Foo` used the imported `C`, so an `extern` declaration of `C` is now\n// invalid.\nextern class C;\n```\n\n#### Libraries cannot both define an entity and declare it `extern`\n\nIn a library, if the `impl` defines an entity, the `api` must not use `extern`\nwhen declaring it.\n\nFor example:\n\n```carbon\npackage Wiz library \"a\" api;\n\nextern class C;\n```\n\n```carbon\npackage Wiz library \"a\" impl;\n\n// Invalid: The `api` file declared `C` as `extern`.\nclass C { ... }\n```\n\nIn a library, the `api` might make an `extern` declaration that the `impl`\nimports and uses the definition of. This is consistent because the `impl` file\nis not declaring the entity.\n\n#### `impl` files with a forward declaration must contain the definition\n\nIn an `impl` file, if the `impl` file forward declares an entity, it must also\nprovide the definition. In libraries with multiple `impl` files, this means that\nusing an entity in one `impl` file when it's defined in a different `impl` file\nrequires a (possibly `private`) forward declaration in the `api` file. An\n`extern` declaration cannot be used for this purpose because the library defines\nthe entity.\n\nThis allows Carbon to provide a compile-time diagnostic if an entity declared in\nthe `impl` is not defined locally. Note that an entity declared in the `api` may\nstill not get a compile-time diagnostic unless the compiler is told it's seeing\n_all_ available `impl` files.\n\nFor example:\n\n```carbon\npackage Bar library \"a\" api;\n\nclass C;\n\nclass D { ... }\n```\n\n```carbon\npackage Bar library \"a\" impl;\n\n// Invalid: Missing a definition in the `impl` file, but if one were added, then\n// this would be valid.\nclass C;\n\n// Invalid: The `api` defines `D`. As a consequence, there is no way to make\n// this forward declaration valid.\nclass D;\n```\n\nThis doesn't prevent `impl` from providing a forward declaration. It might when\nit also provides the definition, which can be useful to unravel dependency\ncycles:\n\n```carbon\npackage Bar library \"a\" api;\n\nclass D;\n```\n\n```\npackage Bar library \"a\" impl;\n\nclass D;\n\nclass E {\n  fn F[self: Self](d: D*) { ... }\n}\n\nclass D {\n  fn G[self: Self](e: E) { ... }\n}\n```\n\nHere, the `impl` could not use the imported forward declaration in the `api`\nbecause of the rule\n[Files must either use an imported declaration or declare their own](#files-must-either-use-an-imported-declaration-or-declare-their-own).\nWithout `class D;` present, the definition of `F` would be invalid.\n\n#### Type scopes may contain both a forward declaration and definition\n\nThe combination of a forward declaration and a definition is allowed in type\nscopes.\n\nFor example:\n\n```carbon\nclass C {\n  class D;\n\n  fn F() -> D;\n\n  class D {\n    fn G() -> Self { return C.F(); }\n\n    var x: i32;\n  }\n\n  fn F() -> D { return {.x = 42}; }\n}\n```\n\nThis is necessary because type bodies are not automatically moved out-of-line,\nunlike function bodies.\n\n### Using `extern` declarations in `extern impl`\n\nIt is invalid for a non-`extern` `impl` declaration to use an `extern` type in\nits type structure.\n\nConsider two libraries, one defining `A` and declaring `B` as `extern`, and the\nother defining `B` and declaring `A` as `extern`. Neither should be able to\ndefine an `impl` involving both `A` and `B`, otherwise both could.\n\n### `impl` lookup involving `extern` types\n\nIf `impl` lookup involving `extern` types finds a non-`final` parameterized\n`impl`, the result is that the lookup succeeds, but none of the values of the\nassociated entities of interface are known. This is because there may be another\nmore specialized `impl` that applies that is not visible (as can also happen\nwith constrained generics).\n\nFor example:\n\n```\nlibrary \"a\" api;\nextern class C;\nextern class D(T:! type);\nextern impl forall [T:! type] D(T) as I where .Result = i32;\n```\n\nIn the above, `D(C)` impls `I`, but with unknown `.Result`, since it might not\nbe `i32`.\n\n### Modifier keywords\n\nWhen considering various modifiers on a forward declaration versus definition:\n\n-   `extern` is only valid on a forward declaration. Rules are detailed above.\n-   `extend` in `extend impl` is only on the declaration in the class body\n    (whether that is a forward declaration or definition), as described at\n    [Forward `impl` declaration](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#forward-impl-declaration).\n-   Other class, impl, and interface modifiers (`abstract`, `base`, `final`)\n    exist only on the definition, not on the forward declaration.\n-   Function modifiers (`impl`, `virtual`, `default`, `abstract`, `final`) must\n    match between forward declaration and definition.\n    -   This only affects type-scoped names because they are invalid on\n        namespace names.\n    -   `abstract` won't have a definition so is moot here.\n-   Access modifiers (`private` and `protected`) must match.\n    -   As an exception, an `extern` name may be `private` when the actual name\n        is public.\n        -   This allows a library to forward declare another library's type\n            without allowing clients to depend on its forward declaration.\n        -   On merging, the more public declaration will take precedence, hiding\n            `private extern` declarations.\n    -   This affects both type-scoped names and namespace names.\n\n## Rationale\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   This proposal supports moving classes between libraries without\n        affecting the compilation of clients.\n        -   Allowing a redundant `extern` declaration when a non-`extern`\n            declaration is imported allows _adding_ the class to an\n            already-imported library where `extern` declarations were previously\n            present.\n        -   Requiring the use of a local `extern` declaration prevents\n            accidental uses that might hinder _removing_ the class from an\n            imported library.\n    -   Requiring keywords on `extern` declarations only when they affect\n        calling conventions means that, in most cases, keywords can be added and\n        removed from declarations in the defining library without breaking\n        `extern` declarations in other libraries.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Explicitly flagging `extern` will assist readers in understanding when a\n        library is working with a type in order to avoid dependency loops, with\n        minimal impact on writing code.\n    -   Preventing redundant forward declaration removes a potential avenue for\n        confusion by making the meaning of entities clearer.\n    -   Requiring keywords be repeated for type-scoped functions is intended to\n        improve readability.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   Requiring `extern` declarations be clearly marked should improve our\n        ability to diagnose ODR violations. This will help developers by\n        improving detection of a subtle correctness issue.\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n    -   `extern` declarations are considered essential to supporting separate\n        compilation of libraries, which in turn supports scaling compilation.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   `extern` is chosen for consistency with C++, and carries a similar --\n        albeit slightly different -- meaning.\n-   [Principle: Prefer providing only one way to do a given thing](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/principles/one_way.md)\n    -   Setting _requirements_ for whether a keyword belongs on a forward\n        declaration or with the definition, instead of making places _optional_,\n        supports developers making conclusions based on which keywords they see\n        -- either by presence or absence.\n\n## Alternatives considered\n\n### Other modifier keyword merging approaches\n\nThere has been intermittent discussion about which modifiers to allow or require\non forward declarations versus definitions. There are advantages and\ndisadvantages about redundancy and being able to copy-paste declarations. There\nmight be strict requirements for some modifiers to be present in order to\ncorrectly use a forward declaration.\n\nThis proposal suggests a partial decision here, at least for a reasonable\nstarting point that we can implement towards. This will likely evolve in future\nproposals, particularly as more keywords are added. However, this still offers a\nbaseline.\n\nThe trade-offs we consider are:\n\n-   Consistency in when a modifier keyword is expected (if applicable) is\n    valuable.\n    -   Adding a keyword to an entity with a separate definition may require\n        adding the keyword to the forward declaration, the separate definition,\n        or both. It is disallowed where not required to be added.\n        -   For example, `base` is added to `class C { ... }`, and disallowed on\n            `class C;`.\n    -   Although we could make keywords optional where it would not affect\n        semantics, we prefer for the presence or absence of a keyword to carry a\n        clear meaning.\n        -   For example, if `base` were optional to allow `base class C;`, then\n            an adjacent `class D;` lends itself to being incorrectly interpreted\n            as meaning \"`D` is not a base class\" when it actually means \"`D` may\n            or may not be a base class\".\n-   Access control has a certain necessity for consistency, so that a consumer\n    of a forward declaration would still be allowed to use the definition if\n    refactored.\n    -   We could require similar consistency on `extern`, and should have more\n        nuanced rules if the access control rules go beyond public and\n        `private`. For example, a package-private type shouldn't be allowed to\n        be made public through an `extern` declaration; but package-private\n        isn't actually part of the language right now.\n-   For a type, we are choosing to have minimal modifiers on the declaration.\n    -   The modifiers we disallow (`abstract`, `base`, `final`, and `default`)\n        have no effect on uses because the forward declared type is incomplete.\n        -   Requiring them would end up leaking an implementation detail and\n            create toil.\n        -   Requiring them would be somewhat inconsistent with C++.\n    -   `extern` is a special-case where its presence is intrinsic to the\n        keyword's semantics.\n-   For type-scoped members, we are choosing to duplicate modifiers between the\n    declaration and definition.\n\n    -   For example:\n\n        ```\n        class A {\n          private class B;\n        }\n        // `private` is required here.\n        private class A.B { ... }\n        ```\n\n    -   There is more emphasis on being able to copy-paste a function\n        declaration. This in particular may help developers more than classes\n        because all the parameters must also be copied. Things such as `static`\n        in C++ being declaration-only is also something we view as a source of\n        friction rather than a benefit.\n    -   Modifiers such as `virtual` affect the calling convention of functions,\n        and as a consequence _must_ be on the first declaration.\n    -   A downside of this approach is that it means the class name is inserted\n        in the middle of the out-of-scope definition, rather than near the\n        front.\n\nThe most likely alternative would be to disallow most modifiers on out-of-line\ndefinitions after a forward declaration, for type member functions in specific.\nThis would be because, unlike other situations, a member must have a forward\ndeclaration if there is an out-of-line definition. We would probably want to\ndrop these collectively in order to maximize copy-paste ability (ideally,\neverything before `fn` is dropped). However, it would shift understandability of\nthe definition in a way that may be harmful. For now this proposal suggests\nadopting the more verbose approach and seeing how it goes.\n\nAnother alternative is that we could allow flexibility to choose which modifier\nkeywords are provided where. For example, keywords on a function definition must\nbe some subset of the keywords on the declaration; keywords on a type\ndeclaration must be some subset of the keywords on the definition. This would\nallow authors to choose when they expect keywords will be most relevant.\nHowever, it could also serve to detract from readability: two functions in the\nsame file might be declared similarly, but have different keywords on the\ndefinition, implying a difference in behavior that would not exist. With\nconsideration for the\n[Principle: Prefer providing only one way to do a given thing](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/principles/one_way.md),\nthis proposal takes the more prescriptive approach, rather than offering\nflexibility.\n\nNote a common aspect between types and functions in the proposed model is that\nmodifiers on the definition are typically a superset of modifiers on the\ndeclaration (`extern` as an exception). While looking at the declaration always\ngives an incomplete view, looking at the definition can give a complete view.\n\n### No `extern` keyword\n\nIf we had no `extern` keyword, then a declaration wouldn't give any hint of\nwhether a library contains the definition. Given two forward declarations in\ndifferent `api` files, either both or neither could have a definition in their\n`impl` file. Sometimes this would be detected during linking, particularly if\nboth are linked together. However, providing an `extern` keyword gives a hint\nabout the intended behavior, allowing us to evaluate more cases for warnings. It\nalso gives a hint to the reader, about whether an entity is expected to be\ndeclared later in the library (even if not in the same file).\n\nFor example:\n\n```carbon\npackage Foo library \"a\" api;\n\nclass C;\n```\n\n```carbon\npackage Foo library \"a\" impl;\n\nclass C {}\n```\n\n```carbon\npackage Foo library \"b\" api;\nimport library \"a\";\n\nclass C {};\n```\n\nWithout the `extern` keyword, this code should be expected to compile. Ideally\nit would be caught during linking that there are two definitions of `class C`,\nbut that relies on some tricks to catch issues. When `extern` is added, then the\nprocessing of library \"b\" results in a conflict between the `class C;` forward\ndeclared in the api of library \"a\".\n\nNote this probably does not fundamentally alter the amount that can be\ndiagnosed, but will mainly allow some diagnostics to occur during compilation\nthat otherwise would either be linker diagnostics or missed.\n\nThe `extern` keyword is being added mainly for diagnostics and readability.\n\n### Looser restrictions on declarations\n\nWe are being restrictive with declarations and when they're allowed. Primarily,\nwe want to avoid confusion with code such as:\n\n```carbon\nclass C { ... }\n\n// This declaration has no effect.\nclass C;\n```\n\nBut, we could also allow code such as:\n\n```carbon\npackage Foo library \"a\" api;\n\nclass C { ... }\n```\n\n```carbon\npackage Foo library \"b\" api;\nimport library \"a\";\n\nfn F(c: C) { ... }\n\nextern class C;\n\nfn G(c: C*) { ... }\n```\n\nHere, `F` requires the imported definition of `C`. But, is `G` seeing an\nincomplete type from the `extern`, or is the `extern` redundant and `G` sees the\nimported definition of `C`? Would a library importing library \"b\" see `C` as an\nincomplete type, or a complete type?\n\nIn order to eliminate potential understandability issues with the choices we may\nmake, we are choosing the more restrictive approaches which disallow both of\nthese. In the first case, the redeclaration after a definition in the same file\nis simply disallowed. In the second case, library \"b\" cannot declare `C` as\n`extern` after using the imported definition. Restrictions such as these should\nmake code clearer by helping developers catch redundant, and possibly incorrect,\ncode.\n\n### `extern` naming\n\nBeyond `extern`, we also considered `external`. `extern` implies external\nlinkage in C++. We're choosing `extern` mainly for the small consistency with\nC++.\n\n### Default `extern` to private\n\nThe `extern` keyword could have an access control implication equivalent to\n`private`. Then `extern` would need explicit work to export the symbol. The\n`export` keyword was proposed for this purpose, with the idea that\n`export import` syntax might also be provided to re-export all symbols of an\nimported library.\n\n1.  `extern` and `export` semantic consistency\n\n    This would mean that `extern` declarations have different access control\n    than other declarations, which is a different visibility model to\n    understand, and may also not be intuitive from the \"external\" meaning. The\n    use of `export` matches C++'s `export` keyword, which may also imply to\n    developers that other semantics match C++, such as `export` being necessary\n    for all declared names.\n\n2.  Interaction with additional access control features\n\n    We'll probably also want more granular access control than just public and\n    private for API names. Adding package-private access modifier seems useful\n    (for example, Java provides this as `package`): in C++, this is sometimes\n    achieved through an \"internal\" or \"details\" namespace. If Carbon only\n    supports library-private symbols, that still addresses some of these\n    use-cases, but will sometimes require private implementation details to\n    exist in a single `api` file in order to get language-supported visibility\n    restrictions. In some cases this will result in an unwieldy amount of code\n    for a single file.\n\n    For example of how package-private visibility might be used, gtest has\n    [an internal header directory](https://github.com/google/googletest/blob/main/googletest/include/gtest/internal)\n    that contains thousands of lines of code. If this needed to migrate to `api`\n    files in Carbon, it would be ideal if users could not access the names by\n    importing an internal library.\n\n    For example of how this would interact:\n\n    | Default visibility             | Public (proposed)         | Private (alternative)            |\n    | ------------------------------ | ------------------------- | -------------------------------- |\n    | Public                         | `extern class C;`         | `export extern class C;`         |\n    | Library-private                | `private extern class C;` | `extern class C;`                |\n    | Package-private (hypothetical) | `package extern class C;` | `export package extern class C;` |\n\n3.  Risks of a public extern\n\n    When making an `extern fn`, it is callable. This creates a risk of a\n    function being declared as `extern` for internal use, but accidentally\n    allowing dependencies on the function. This risk could be mitigated by\n    requiring access control of an `extern` to be either equal to or more\n    restrictive than the original symbol (which might be hard to validate, but\n    could be validated when both symbols are seen together).\n\n    When making an `extern class`, it's an incomplete type. It cannot be\n    instantiated, but pointers and references may be declared. This is only\n    really useful if there are functions which take a pointer as a parameter,\n    but an instance of the pointer could only be created by either unsafe casts\n    or if there's a function that returns the pointer type.\n\n    Unsafe casts carry an inherent risk. In the case of a returned pointer, that\n    type could be captured by `auto`. Having `extern class` default to private\n    does not prevent the type's use.\n\nConsidering the trade-offs involved combination of these three points, this\nproposal suggests using the regular access control semantic. That choice may be\nreconsidered later, based on how the semantics work out and any issues that\narise, particularly around access control.\n\n### Opaque types\n\nOmitting the `extern` modifier means a definition is required in a library.\nThere may be a use-case for opaque types which are \"owned\" by a library and have\nno definition. If so, there are possible solutions such as a modifier keyword to\nindicate an opaque type. For now, an empty definition in the `impl` file of a\nlibrary should have a similar effect: `api` users would not be able to provide a\ndefinition.\n\nFor example:\n\n```carbon\npackage Foo library \"a\" api;\n\n// An opaque type which can be imported by other libraries.\nclass C;\n```\n\n```carbon\npackage Foo library \"a\" impl;\n\n// An empty definition. This could be in its own file, or at the end after logic,\n// to prevent misuse.\nclass C {}\n```\n\nThis proposal requires a definition to exist. That choice may be reconsidered\nlater, based on use-cases.\n\n### Require a library provide its own `extern` declarations\n\nAs proposed, any library can provide `extern` declarations for other libraries\nin the same package. It was proposed that this should be restricted so that a\nlibrary would need to make `extern` declarations available, either through a\nseparate `extern` file (similar to `api` and `impl`) or through additional\nmarkup in the `api` file which could be used to automatically generate an\n`extern`-only subset of the `api` (still requiring entities which _should_ be\n`extern` to be explicitly marked).\n\nAdvantages:\n\n-   Centralizes ownership of `extern` declarations.\n    -   We are already planning to require a package to provide `extern`\n        declarations. This goes a step further, requiring the `extern`\n        declaration be provided by the same library that's defining the entity,\n        providing a clear, central ownership.\n-   Simplifies refactoring.\n    -   The current plan of record is to require that `extern` declarations\n        agree with the library's declaration of the definition. This includes\n        small details such as parameter names. A consequence of this is that\n        changing these details in one declaration requires changing them in\n        _all_ declarations, atomically. There's a desire to limit the scope of\n        atomic refactorings; for example, similar package-scope atomic\n        refactoring requirements lead us to _allow_ certain redundant forward\n        declarations elsewhere in this proposal.\n-   Reduces complexity for migrating C++ forward declarations.\n    -   As described in\n        [Migration of C++ forward declarations](#migration-of-c-forward-declarations),\n        we expect migrating forward declarations to be difficult. Several of the\n        steps needed already can produce results similar to this alternative.\n        Under this alternative, we would make the handling of an entity defined\n        in a different library identical to as if it were in a different\n        package: a reduction of one case.\n\nDisadvantages:\n\n-   Makes it difficult for libraries which want to use `extern` declarations to\n    use minimal imports for a declaration.\n    -   If a library provides multiple `extern` declarations, the `extern`\n        file's imports would be a superset of the imports for those\n        declarations. If a client library only wants one of those `extern`\n        declarations, it would still get the full set of dependencies; under the\n        proposed syntax, only the single declaration's dependencies are\n        required. This allows for fewer dependencies.\n-   Does not support use-cases that may occur in C++.\n    -   It's possible that an extern declaration may depend on a defined entity,\n        where that entity is being defined in the same file. For example,\n        `class C { ... }; extern fn F(c: C);`. Under the proposed syntax, this\n        is supported; under the alternative syntax, another solution would need\n        to be found. There are potential ways to fix this through refactoring,\n        including moving one entity to a different library, changing the\n        `extern` declaration to use only `extern` declarations, or using generic\n        programming to create an indirection. However, each of these is a\n        refactoring that may hinder adoption.\n\nAt present, the disadvantages are considered to outweigh the advantages. It's\npossible that this may be revisited later if we get more code and libraries\nusing these tools and recognize some patterns that we can better or more\ndirectly support. However, we should be hesitant to provide a second syntax for\n`extern` if it's not adding substantial value, under\n[Principle: Prefer providing only one way to do a given thing](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/principles/one_way.md).\n\n### Allow cross-package `extern` declarations\n\nWe could choose a syntax for `extern` declarations that allows cross-package\n`extern` declarations. These are effectively supported in C++, where there are\nno package boundaries. Dropping support will create a migration barrier.\n\nHowever, there is a strong desire to restrict the use of cross-package\ndeclarations in order to reduce the difficult and complex refactoring costs that\nresult from cross-package declarations: requiring that a particular name not\nchange its declaration category (a `class` must remain a `class`, preventing\n`alias`) and that parameters (either function or generic) must remain the same,\nnot even allowing implicit conversions.\n\nThe package boundaries serve an important purpose in balancing costs for\nrefactoring.\n\n## Appendix\n\n### Migration of C++ forward declarations\n\nThis is not proposing a particular approach to migration. However, for\nconsideration of the proposal, it can be helpful to consider how migration will\nwork.\n\nIt's expected under this approach that migration of a forward declaration will\nrequire identifying the Carbon library that defines the entity. Then:\n\n-   The forward declaration will need to be adjusted based on library and\n    package boundaries:\n    -   If the forward declaration is disallowed in Carbon, it may need to be\n        removed.\n    -   If the forward declaration is in the same library as the defining\n        library, then no `extern` is required.\n    -   If the forward declaration is in a different library but the same\n        package, then `extern` is added.\n    -   If the forward declaration is in a different package, the forward\n        declaration must be removed. To replace it, there are a couple options\n        which would need to be chosen by heuristic:\n        1.  Add a dependency on the actual definition. This might be infeasible\n            when the defining library has many complex dependencies.\n        2.  Add a library to the other package that provides the necessary\n            `extern` declaration. This might be infeasible when the package is\n            not owned by the package being migrated.\n    -   If the forward declared code is in C++, we need to retain a forward\n        declaration in C++. A couple examples of how we might achieve that are:\n        -   Provide Carbon syntax for an in-file forward declaration of C++ code\n            (for example, `extern cpp <declaration>`).\n        -   Create a small C++ header providing the forward declaration, and\n            depend on it.\n-   Fix meaningful differences in parameter names, for example by updating the\n    forward declaration's parameter names to match the definition.\n-   Fix meaningful differences in modifier keywords, for example by adding a\n    function forward declaration's modifiers to the definition.\n"
  },
  {
    "path": "proposals/p3763.md",
    "content": "# Matching redeclarations\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3763)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [#1132 rule](#1132-rule)\n    -   [C++ rule](#c-rule)\n    -   [One-definition rule](#one-definition-rule)\n    -   [Where declarations can appear](#where-declarations-can-appear)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Syntactic vs semantic matching](#syntactic-vs-semantic-matching)\n        -   [Unqualified name lookup](#unqualified-name-lookup)\n        -   [`impl`s that have not yet been declared](#impls-that-have-not-yet-been-declared)\n    -   [Declaration modifiers](#declaration-modifiers)\n    -   [`_` parameter names and `unused` modifier](#_-parameter-names-and-unused-modifier)\n    -   [Scope differences](#scope-differences)\n    -   [`impl` declarations](#impl-declarations)\n        -   [Redeclarations](#redeclarations)\n        -   [Differences between `impl` declarations](#differences-between-impl-declarations)\n        -   [Out-of-line definitions of associated functions](#out-of-line-definitions-of-associated-functions)\n        -   [`impl` members vs `interface` members](#impl-members-vs-interface-members)\n    -   [`virtual` functions](#virtual-functions)\n    -   [`extern` declarations](#extern-declarations)\n    -   [`let` and `var` declarations](#let-and-var-declarations)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use a partially or fully semantic rule](#use-a-partially-or-fully-semantic-rule)\n    -   [Use package-wide name poisoning](#use-package-wide-name-poisoning)\n    -   [Allow shadowing in implementation file after use in API file](#allow-shadowing-in-implementation-file-after-use-in-api-file)\n\n<!-- tocstop -->\n\n## Abstract\n\nRequire exact syntactic matching in redeclarations. Provide new terminology for\nredeclaration matching and agreement. Specify non-redeclaration rules for the\nother contexts where we require multiple declarations to match, such as `impl`s\nof `interfaces`, `impl`s of `virtual fn`s.\n\n## Problem\n\nWhen we see two declarations that might declare the same entity, we need to\nknow:\n\n-   Do they actually declare the same entity?\n-   Are they similar enough to be _valid_ declarations of the same entity?\n\n[Leads issue #1132](https://github.com/carbon-language/carbon-lang/issues/1132)\nhas rules for this, and those rules were partially incorporated into the design\nby [#1084 Generics details 9: forward declarations](/proposals/p1084.md).\nHowever:\n\n-   #1084 only covers generics, not the whole scope of the language, and\n\n-   #1132's hybrid approach of using a syntactic rule but allowing syntactic\n    deviations for aliases has proven challenging and awkward to implement in\n    the Carbon toolchain.\n\n## Background\n\nRelated issues and proposals:\n\n-   [Issue #472: Open question: Calling functions defined later in the same file](https://github.com/carbon-language/carbon-lang/issues/472)\n-   [Issue #1132: How do we match forward declarations with their definitions?](https://github.com/carbon-language/carbon-lang/issues/1132)\n-   [Proposal #875: Principle: information accumulation](https://github.com/carbon-language/carbon-lang/pull/875)\n-   [Proposal #1084: Generics details 9: forward declarations](https://github.com/carbon-language/carbon-lang/pull/1084)\n-   [Proposal #3762: Merging forward declarations](https://github.com/carbon-language/carbon-lang/pull/3762)\n\n### #1132 rule\n\nUnder issue #1132, as fleshed out by proposal #1084:\n\nTwo declarations declare the same entity if they _match_, which in most cases\nsimply means that they have the same name and same scope. For `impl`\ndeclarations, which don't have names, there is a more complicated rule.\n\nTwo declarations that declare the same entity _agree_ if they are similar enough\nto be valid redeclarations of that entity. This requires them to have the same\nsyntactic form, with some exceptions:\n\n1.  Parameter names can be replaced by `_` if the parameter is not used in the\n    declaration.\n2.  Grouping parentheses can be present in one declaration and absent in another\n    if it doesn't change the parse result.\n3.  An alias can be used in one declaration, where the alias target or a\n    different alias to the same target is used in the other declaration.\n\n[Concerns have been raised](https://discord.com/channels/655572317891461132/963846118964350976/1214372759224983562)\nthat the terminology in use here is problematic:\n\n-   Declarations are said to \"match\" even when they are quite dissimilar -- for\n    example, functions with different signatures are said to match.\n-   The term \"match\" is easy to confuse with pattern-matching terminology.\n-   The term \"agree\" sounds like it is expressing an opinion.\n-   These terms don't fit well into diagnostics. For example, we considered\n    diagnostic text similar to \"Declaration X does not agree with matching\n    declaration Y\", which doesn't clearly describe the problem. While it's not\n    necessary for us to use the formal, technical terminology in diagnostics, it\n    would be useful to have terminology that also works in that context.\n\nThe chosen rule has also been found to be problematic to implement in practice,\nbecause it combines the purely-syntactic concern of whether the same syntax is\nused with the semantic, scope-based concern of the name lookup result, at least\nfor aliases.\n\n### C++ rule\n\nIn C++, two function or function template declarations declare the same entity\nif they have the same:\n\n-   scope\n-   name\n-   template parameter lists\n-   return type, if a function template\n-   parameter types and trailing ellipsis\n\nIn each case, the component of the declaration can be written in different ways\nbetween declaration and definition. In general, names of parameters can be\narbitrarily different. Types can be written in different ways, so long as they\nresolve to the same thing. However, parts of the declaration that depend on\ntemplate parameters must be written with the same token sequence, which must be\ninterpreted in the same way, or the dragons of \"ill-formed, no diagnostic\nrequired\" may burn your program to the ground.\n\nThere is also a grey area between cases where token-by-token matching is\nrequired and more liberal matching is permitted, where it's not clear what rule\nto apply. The oldest still-open core language issue against C++,\n[CWG issue 2](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2),\nconcerns such a case, but there are many more examples.\n\nIn C++, because the scope of a declaration is only entered part-way through\ndeclaring it -- specifically, after the return type -- such problems are hard to\navoid. There are constructs that must be written differently in an in-class\ndeclaration versus in an out-of-line definition.\n\n```c++\nstruct A {\n  struct B {};\n  B f();\n};\n// Can't write this as `B f()`.\nA::B A::f() {}\n```\n\nIn Carbon, there is no such problem, so a simpler rule is available to us.\nIndeed, it's desirable to support a simple syntactic rule for transforming an\nin-class declaration into an out-of-class definition, both for tooling and for\nprogrammers.\n\n### One-definition rule\n\nProposal #3762 establishes the following rules:\n\nIf an entity is declared in the `api` file of a library, it can be redeclared in\n`impl` files subject to other rules on redundant redeclarations, and a\ndefinition is required in exactly one `impl` file.\n\nIf the entity is _not_ declared in the `api` file, and is instead introduced as\nnon-`extern` in an `impl` file, then it must be defined in that `impl` file.\nNote that this means that such an entity can only be declared in a single `impl`\nfile; if an entity is intended to be shared by multiple `impl` files, it must be\ndeclared in the `api` file, typically as a `private` member of the library.\n\n### Where declarations can appear\n\nBecause declarations always declare their entity within the lexically-enclosing\npackage, and the package forms part of the scope, declarations for an entity can\nonly appear in a single package.\n\nAs specified in #3762, entities can be declared in more than one library: Each\nentity has an owning library, and all declarations of that entity outside the\nowning library are declared `extern`. All declarations of an entity without the\n`extern` keyword are required to appear in the same library.\n\n## Proposal\n\nReplace the terminology (\"match\" and \"agree\") and corresponding rules here as\nfollows:\n\n-   Two named declarations _declare the same entity_ if they have the same scope\n    and the same name.\n-   One declaration _redeclares_ another if they declare the same entity and the\n    second declaration appears after the first, including the case where the\n    first declaration is imported. In this case, the second declaration is said\n    to be a _redeclaration_ of the first.\n-   Two declarations _differ_ if the sequence of tokens in the declaration\n    following the introducer keyword and the optional scope, up to the semicolon\n    or open brace, is different, except for `unused` modifiers on parameters.\n-   The program is invalid if it contains two declarations of the same entity\n    that differ.\n\n```carbon\nclass A {\n  fn F(n: i32);\n  fn G(n: i32);\n}\n\n// ❌ Error, parameter name differs.\nfn A.F(m: i32) {}\n\n// ❌ Error, parameter type differs syntactically.\nfn A.G(n: (i32)) {}\n```\n\n## Details\n\n### Syntactic vs semantic matching\n\nRedeclarations are primarily checked syntactically. The intention is that\nwhenever the syntax matches, the semantics must also match. This is largely\ntrue, and is supported by the\n[information accumulation principle](https://github.com/carbon-language/carbon-lang/pull/875)\nthat it is an error if information learned later would have affected the meaning\nof earlier code.\n\nTwo specific cases are worth calling out here:\n\n-   [Unqualified name lookup](#unqualified-name-lookup)\n-   [`impl`s that have not yet been declared](#impls-that-have-not-yet-been-declared)\n\nBecause the semantics of declarations should always match if the syntax matches,\nwe expect implementations of Carbon to be able to call out semantic differences\nbetween redeclarations -- for example, \"type of parameter `x` in redeclaration\nis different from type in previous declaration\" -- not only point to where the\nsyntax diverged.\n\nAll non-`extern` declarations of an entity are in the same library, and all\nnon-`extern` declarations see the first non-`extern` declaration of the entity,\nwhich is either in the same file or, for a declaration in an implementation\nfile, in the API file, so we can always perform a precise syntactic\nredeclaration check if we persist syntactic information from the API file to\nimplementation files.\n\n#### Unqualified name lookup\n\n```carbon\nnamespace N;\nclass C;\nfn N.F(x: C);\nclass N.C;\nfn N.F(x: C) {}\n```\n\nHere, it appears that the unqualified reference to `C` resolves to two different\nclasses in the two declarations. However, following the information accumulation\nprinciple, we consider the declaration of `N.C` invalid because it would change\nthe meaning of the unqualified name `C` that has already been used.\n\nSpecifically, we add the following rule:\n\n-   In a declarative scope, it is an error if a name is first looked up and not\n    found, and later introduced.\n\nNames for which unqualified lookup is performed and fails are said to be\n_poisoned_ in that scope.\n\n_Declarative scopes_ here are scopes like namespaces, classes, and interfaces.\nAnother way of looking at this rule is that reordering the declarations in a\ndeclarative scope should never result in a program that is still valid but has a\ndifferent meaning.\n\nIt is also possible to declare an entity in a non-declarative scope, such as in\na function body. We call non-declarative scopes _sequential scopes_, and use a\ndifferent rule:\n\n-   It is an error to redeclare an entity in a sequential scope.\n\nThis rule is provisional: no alternative has been suggested, and we don't know\nwhether there is strong motivation for supporting redeclaration in sequential\nscopes. In C++, such redeclarations are permitted, but we are not aware of any\ninstance of this functionality being used. There are likely other good options\nto use here, but we consider them outside the scope of this proposal.\n\nIn order to ensure that two declarations with the same syntax have the same\nsemantics when one declaration is in an API file and a redeclaration is in an\nimplementation file of the same library, we start each implementation file with\nthe name lookup state from the end of its API file. In particular:\n\n-   All names declared in the API file are visible in the implementation file,\n    even if they're `private`.\n-   All imports in the API file are visible in the implementation file, even if\n    they're not `export`ed.\n-   Poisoned names are persisted from the API file to the implementation file:\n    if a name is looked up by unqualified name lookup in an API file, but not\n    found in that scope, the name cannot be declared in that scope in an\n    implementation file.\n\nNote that the above only apply within the same library. It is permitted for a\nname to be poisoned in one library but declared in another.\n\nSome [additional considerations](#extern-declarations) apply to `extern`\ndeclarations, where it is possible for name lookups in two syntactically\nidentical declarations to have different results.\n\n#### `impl`s that have not yet been declared\n\nIt is possible for a declaration of an entity to have one meaning because `impl`\nlookup finds a broad `impl`, and for a redeclaration to have a second meaning\nbecause `impl` lookup finds a narrower `impl`. However, in such a case, the\ndeclaration of the narrower `impl` declaration is invalid, because it would\nchange the meaning of an earlier `impl` lookup. From #875:\n\n> When an `impl` needs to be resolved, only those `impl` declarations that have\n> that appear earlier are considered. However, if a later `impl` declaration\n> would change the result of any earlier `impl` lookup, the program is invalid.\n\n### Declaration modifiers\n\nDeclaration modifier keywords appear prior to the introducer keyword and scope\nin a declaration, so are not involved in checking whether two declarations\ndiffer. There may be other rules that determine whether modifiers may or must be\nrepeated on a redeclaration, but they are out of scope for this proposal.\n\n```carbon\nclass A {\n  virtual fn F[self: Self]();\n}\n\n// ✅︎ OK, `virtual` not required to match.\nfn A.F[self: Self]() {}\n```\n\n### `_` parameter names and `unused` modifier\n\nIssue #1132 permitted redeclarations of a function to differ by having one\ndeclaration of a function name a parameter and the other leave it unnamed with\n`_`. That flexibility is removed by this proposal.\n\nThis change improves the consistency of redeclarations, and also closes a hole\nin the syntactic matching rule:\n\n```carbon\nfn F(T:! type, x: T);\n\nalias T = i32;\n\n// ❌ Not equivalent to previous declaration, but same syntax\n// other than replacing parameter name with `_`.\nfn F(_:! type, x: T);\n```\n\nHowever, it is important that a function definition can choose to not use its\nparameter, in a way that is not visible in the API. Therefore we exclude\n`unused` modifiers from the syntactic difference check.\n\n```carbon\n// Now equivalent to the first declaration above.\n// However, this is invalid because `T` is declared unused\n// but is used in the type of `x`.\nfn F(unused T:! type, x: T):\n```\n\nFor simplicity, and to avoid any need to check `unused` annotations match\nbetween declaration and definition, we disallow `unused` from appearing on a\nparameter in a non-defining declaration.\n\nMore generally, annotations on a declaration that are only relevant to the\ndefinition should be excluded from the check. At the moment, the `unused`\nannotation is the only such case, but we anticipate more cases emerging in the\nfuture. Attributes on function parameters are another example that may need\nspecial-casing.\n\n### Scope differences\n\nIn addition to comparing whether the name and parameter portion of a declaration\ndiffer from that of another declaration, we also need rules governing the scope\nportion. The rule we use for a qualified declaration is:\n\n-   Take the portion of the declaration from the introducer up to the end of the\n    scope.\n-   Replace the introducer keyword with the introducer keyword of the scope.\n-   Replace the trailing `.` with a `;`.\n-   The result must be a valid declaration of the scope, ignoring restrictions\n    on how often the scope can be redeclared.\n\nPut another way: each portion of the qualified name must not differ from the\ndeclaration of the corresponding entity.\n\nFor example:\n\n```carbon\nnamespace N;\n\nclass N.C(T:! type) {\n  class D(U:! type) {\n    fn F(a: T, b: U);\n  }\n}\n\nfn N.C(T:! type).D(U:! type).F(a: T, b: U) {}\n```\n\nIn this function definition:\n\n-   `F(a: T, b: U)` does not differ from the declaration of `F`.\n-   `class N.C(T:! type).D(U:! type);` would be a valid redeclaration of `D`,\n    because:\n    -   `D(U:! type)` does not differ from the declaration of `D`.\n    -   `class N.C(T:! type);` would be a valid redeclaration of `C`, because:\n        -   `C(T:! type)` does not differ from the declaration of `C`.\n        -   `namespace N;` would be a valid redeclaration of `N`.\n\nSo this is a valid definition of `F`.\n\nNote that this means that, for example, all members of a class must use the same\nname for each generic parameter of that class. It cannot be `T` in one\nout-of-line member definition and `ElementType` in another, or the scope in the\nout-of-line definition would not match.\n\n> **Future work:** This rule does not permit aliases to be used for top-level\n> names in a declaration. This may be reasonable in most cases, because all\n> declarations other than perhaps an `extern` declaration will be in the same\n> library. However, names within namespaces may be declared anywhere within a\n> package, and a mechanism to permit renaming of a namespace without making an\n> atomic change to the entire package would be useful.\n\n### `impl` declarations\n\n#### Redeclarations\n\nThe rules from #1084 for `impl` declarations are largely unchanged in this\nproposal, except that the allowance for `alias`es to be expanded is removed.\n\nWe cannot use the declaration name to determine whether two `impl` declarations\ndeclare the same entity. Instead, two `impl` declarations declare the same\nentity if the portion of the declaration from the introducer keyword until the\n`;` or `{` does not differ, except:\n\n-   If the constraint type in the `impl` is of the syntactic form\n    `expression where constraints`, then the `constraints` portion is not\n    considered.\n-   `impl as` is rewritten to `impl Self as` before looking for a previous\n    declaration and checking for differences from any previous declaration that\n    is found.\n\n```\ninterface I {\n  let T:! type;\n}\n\nclass A {\n  impl as I where .T = ();\n  // ✅︎ Redeclaration of previous declaration.\n  impl Self as I where _ {}\n}\n```\n\n> **Note:** These rules assume that `impl` declarations have an associated\n> scope, and can only be redeclared in that scope, like all other declarations.\n> This was\n> [the consensus in discussion on 2024-03-11](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.p69b78lovqb7)\n> but has not yet been incorporated into a design proposal. This will be the\n> subject of a separate proposal.\n>\n> In the same discussion, the consensus was to permit such an `impl` to be\n> redeclared out-of-line, with parentheses added around the name of the `impl`.\n> That would lead to the following behavior under this proposal:\n>\n> ```carbon\n> // ✅︎ Redeclaration of the `impl` from the previous example.\n> impl A.(Self as I) where _;\n>\n> // ✅︎ Rewritten to `impl A.(Self as I) where _;` before redeclaration check.\n> // Same as previous example.\n> impl A.(as I) where _;\n> ```\n>\n> However, this syntax change for `impl`s is not part of this proposal.\n\n#### Differences between `impl` declarations\n\nAs specified in #1084, an `impl` declaration can be of the form\n\n> `impl [...] as interface where _;`\n\nwith an `_` replacing the constraints in the `where` expression. For such a\ndeclaration, a prior declaration must be found or the `impl` is invalid. The `_`\nis replaced by the constraints in the prior declaration.\n\nAfter this transformation, the normal rule is applied: the `impl` declaration\ncannot differ from the previous declaration. For an implementation that performs\na semantic replacement of `_` rather than a syntactic one, it can terminate the\ncomparison when it reaches the `_`.\n\n#### Out-of-line definitions of associated functions\n\nA small change is made to the rule for [scopes](#scope-differences) for `impl`\nmembers: parentheses are added around the corresponding portion of the scope.\nFor example:\n\n```carbon\nimpl Type as Interface {\n  fn F();\n}\n// Not `fn Type as Interface.F() {}`.\nfn (Type as Interface).F() {}\n```\n\nSimilarly for parameterized `impl`s:\n\n```carbon\nimpl forall [T:! type] T as Interface(T) {\n  fn F();\n}\nfn (forall [T:! type] T as Interface(T)).F() {}\n```\n\nAnd for class-scope `impl` members:\n\n```carbon\nclass Class {\n  impl as Interface {\n    fn F();\n    fn G();\n  }\n}\n\n// ✅︎ OK\nfn Class.(Self as Interface).F() {}\n\n// ✅︎ Rewritten to `Self as Interface`.\nfn Class.(as Interface).G() {}\n```\n\n> **Note:** As part of associating `impl` declarations with a scope,\n> [the consensus in our discussion](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.p69b78lovqb7)\n> was to also change the `impl forall` syntax to:\n>\n> ```\n> impl [T:! type](T as Interface(T));\n> ```\n>\n> If that change is made, the scope syntax will similarly change to reflect the\n> new syntax:\n>\n> ```\n> fn [T:! type](T as Interface(T)).F() {}\n> ```\n>\n> However, that change is out of scope for this proposal.\n\n#### `impl` members vs `interface` members\n\nWe need rules governing how associated functions in an `impl` are permitted to\ndiffer from the corresponding declarations in the `interface`:\n\n```carbon\ninterface I {\n  fn F(s: Self);\n}\nimpl i32 as I {\n  // Is this valid?\n  fn F(s: i32);\n}\n```\n\nIt is tempting to base the rules here on the rules we use to check\nredeclarations. However, this turns out to be a poor choice:\n\n-   The redeclaration rule would syntactically couple the declaration in the\n    `interface` to the definition in the `impl`. But these declarations could be\n    in different libraries, or even different packages, so such coupling would\n    make refactorings that change the way that code is expressed but not its\n    meaning either difficult or impossible.\n-   The associated function in an `impl` is expected to have different syntax\n    than that in the interface in some cases. The two declarations are in\n    different scopes, so will refer to the same types in different ways. And the\n    declaration in the `impl` is declared with knowledge of the `Self` type and\n    associated constants for the interface, which it may be reasonable to use\n    directly in the declaration of the function, as in the preceding example.\n\nTherefore, different rules are used. In the specific case where an associated\nfunction declaration in the `impl` can be used directly to satisfy a requirement\nintroduced by a function declaration in the `interface`, it is used directly.\nFor example, this is necessary to avoid infinite recursion when implementing the\n`Call` interface.\n\nThe function in the `impl` is used directly when:\n\n-   Each parameter in the `impl` function has the same type as the parameter in\n    the `interface`. This includes the `self` parameter, which must be present\n    in both functions if it is present in either.\n-   Each parameter in the `impl` has the same category -- either `var` or not --\n    as the parameter in the `interface`.\n-   The return type in the `interface` and `impl` are the same type.\n\n> **Note:** More constraints are expected to appear here over time. The key\n> property we aim to identify is whether the two functions have the same calling\n> convention.\n\nOtherwise, a synthetic function called a _thunk_ is generated:\n\n-   The declaration of the thunk is formed by substituting the `Self` type of\n    the `impl` into the declaration in the `interface`. This implicitly also\n    provides values for any associated constants used in the declaration.\n-   The body of the thunk calls the function in the `impl`, passing in the\n    arguments to the thunk, and, if a return type is specified in the interface,\n    returning the value returned by the call.\n\nIf the function in the interface does not have a return type, the program is\ninvalid if the function in the `impl` specifies a return type.\n\n> **Note:** Another rule might work better here. For example, we could allow\n> `impl`s to add a return type in anticipation of the `interface` later adding\n> one. However, such a feature is considered out of scope for this proposal.\n\nImplicit conversions are performed as necessary to initialize the parameters of\nthe function in the `impl` from the parameters of the thunk, and to initialize\nthe return value of the function from the result of the call.\n\nIt is an error if a thunk is needed to wrap a function declaration with a `var`\nparameter, because otherwise a copy would always be performed when initializing\nthe parameter.\n\n> **Note:** Here as well another rule may work better and we should revisit in\n> the future. Specifically, it might be better to allow these cases and simply\n> move from the outer `var` to the inner `var` even though this still leaves two\n> allocations in principle.\n\n> **Note:** These rules do not cover the case where the function declaration in\n> the `interface` or `impl` has implicit generic bindings. That case is\n> considered to be out of scope for this proposal.\n\n### `virtual` functions\n\nFor a `virtual` function, the same approach is taken as for `impl` functions: a\nthunk is generated that differs from the declaration in the base class by\nreplacing the type of `self` with the derived class, unless the function chosen\nfor a class can be used directly. When a virtual function is used directly in a\nbase class and not overridden in the derived class, it is also used directly in\nthe derived class, even though its declared `self` parameter does not have a\nmatching type.\n\n```carbon\nbase class B {\n  // No thunk used.\n  virtual fn F[addr self: B*]();\n  virtual fn G[addr self: B*]();\n}\nbase class C {\n  extend B;\n  // No thunk used: `self` has expected type `C*`.\n  impl fn F[addr self: C*]();\n  // Uses a thunk due to unexpected `self` type.\n  impl fn G[addr self: B*]();\n}\nclass D {\n  // No thunk for `F`, because no thunk was used in `C`.\n  // Uses thunk for `F`, because thunk was used in `C`.\n  extend C;\n}\n```\n\nNote that this supports covariant return types automatically, as well as any\nother case where the return value from the derived class function can be\nimplicitly converted to the base class function's return type. However, an\n`impl fn` doesn't introduce a new name lookup result, so the return type of a\ncall expression is always that of the `virtual fn`, which means this feature is\nnot useful.\n\n> **Future work:** It might be useful to allow a declaration to both implement\n> an existing virtual function and introduce a new one. This would allow\n> introducing functions with covariant return types that work as expected. This\n> could be achieved with syntax such as:\n>\n> ```carbon\n> base class A {\n>   virtual fn Clone[self: Self]() -> A*;\n> }\n> base class B {\n>   virtual impl fn Clone[self: Self]() -> B*;\n> }\n> ```\n>\n> Here, a call to `b->Clone()` would find `B.Clone` rather than `A.Clone`, and\n> so would have return type `B*`. The downside is that the vtable for `B` would\n> have two `Clone` slots, for `A.Clone` and `B.Clone`, whereas a covariant\n> return in C++ would only need a single vtable slot to express the same thing.\n\nIt is an error for a class with a custom value representation to declare or\nimplement a virtual function that passes `self` by value.\n\n### `extern` declarations\n\nFor `extern` declarations, some additional considerations apply to the rule\ndisallowing redeclarations from syntactically differing:\n\n-   This rule cannot in general be checked during compilation. For example,\n    there may be no file that imports both an `extern` declaration and the\n    library that owns the entity.\n-   Despite being syntactically identical, `extern` declarations can have\n    different meanings from the entity they redeclare due to unqualified lookup\n    results differing.\n-   A constraint that the declarations be syntactically identical is a greater\n    burden, because it introduces syntactic coupling across libraries that may\n    make refactoring harder.\n\nWe address these points as follows:\n\n-   Checking whether `extern` declarations properly redeclare their targets\n    during compilation is best-effort.\n    -   `extern` declarations are expected to be fully checked at link time,\n        including both syntactic and semantic checks, by emitting extra\n        information into the object files.\n    -   Some level of semantic checks may be important for an implementation in\n        order to ensure its data structures are consistent. For example,\n        constant evaluation may cross between file boundaries, and it may be\n        important that types used in compile-time functions have the same\n        meaning in the caller and callee in order to support such calls.\n    -   Any further compile-time checking is optional and best-effort. Carbon\n        implementations are encouraged to perform a reasonable set of checks\n        during compilation in order to improve the quality of diagnostics and\n        produce diagnostics earlier, but can defer harder cases until link time.\n        For example, an implementation could choose to not track the syntactic\n        form of a declaration, and perform only semantic checks during\n        compilation, deferring syntactic checking until link time.\n-   To support `extern` declarations, an additional constraint is imposed: the\n    lookup results for names used in each declaration of an entity are required\n    to be the same. This rule actually applies to all declarations of all\n    entities, but it only has an effect -- and needs to be checked -- for\n    `extern` declarations.\n    -   It is an error if an `extern` declaration mentions any `private` entity\n        that is not also `extern`. Such a declaration could never match an\n        entity owned by another library.\n    -   This check will in general need to be performed at link time, in\n        addition to the link time syntactic checks.\n-   For now, we will try this restrictive rule, even though it creates\n    refactoring burden.\n    -   This was discussed and tentatively agreed in the\n        [open discussion on 2024-03-05](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.q9kh9bx2nmli)\n    -   Creating an `extern` declaration necessarily creates additional coupling\n        between libraries. Even a very permissive matching rule would not fully\n        address the potential problems here.\n\n### `let` and `var` declarations\n\nPer\n[issue #2590: syntax for declaring global variables in a namespace](https://github.com/carbon-language/carbon-lang/issues/2590),\nthere are two different forms for `let` and `var` declarations in declarative\nscopes:\n\n```carbon\n// An optional scope, and a single name binding.\nlet Scope.A: Type = Value;\n\n// An arbitrary pattern that is not a name binding.\nlet (A: Type1, B: Type2) = Value;\n```\n\nNote that this presentation is slightly different from #2590, which divided the\ncases into qualified name bindings and arbitrary patterns, but the set of cases\nis the same.\n\nThe former of these two cases is treated the same as any other declaration with\nan introducer, an optional scope, a name, and a body, except that the end of the\ndeclaration is at the `=` or `;` rather than at the `}` or `;`. If `let` and\n`var` declarations can be redeclared -- which is a decision that is out of scope\nfor this proposal -- then these declarations follow the normal rules for\nredeclarations, and the type of the variable is in the declaration portion, so\nis not permitted to differ between declarations.\n\nThe latter case, with an arbitrary pattern that is not a single binding, does\nnot permit redeclarations.\n\n## Rationale\n\nGoals:\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   Matching of declarations by simple tools is possible without\n        sophisticated semantic analysis. A simple token comparison is sufficient\n        to match an out-of-line definition to a declaration.\n    -   Moving a definition out of line is similarly a straightforward syntactic\n        transformation.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Function declarations that differ only in some subtle way are\n        disallowed, leaving the maximum room available for future function\n        overloading features.\n    -   Functions in `impl`s and `interface`s are allowed to differ so long as\n        conversions are available, allowing `interface`s to be changed in\n        compatible ways.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Requires writing code consistently between declarations.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Provides a framework within which C++ virtual functions with covariant\n        return types can be supported.\n\nPrinciples:\n\n-   [Information accumulation](https://github.com/carbon-language/carbon-lang/pull/875)\n    -   Unqualified lookups follow the information accumulation rule: reordering\n        declarations can't result in a different but valid program.\n\n## Alternatives considered\n\n### Use a partially or fully semantic rule\n\nWe could allow declarations to differ more arbitrarily. We would need a rule to\nsupport comparisons of portions of declarations that are dependent on template\nparameters, and such comparisons likely need to be partially or fully syntactic.\n\nAdvantages:\n\n-   Allows the interface to be presented in a way that is suitable for a reader\n    of the interface, and the implementation to be presented in a different way\n    that is suitable for a reader of the implementation.\n-   Additional flexibility for refactorings that are partially or incrementally\n    applied.\n\nDisadvantages:\n\n-   A syntactic rule would still be needed sometimes, but would be applied\n    inconsistently.\n-   Drawing a line between the syntactic and semantic checks would be\n    complicated and difficult, as evidenced by such a line not having been\n    successfully drawn in C++.\n-   Allowing divergence between the syntax used in redeclarations makes code\n    harder to read and understand, and can permit unintended divergence, or even\n    bugs such as function parameters of the same type being swapped.\n\n### Use package-wide name poisoning\n\nInstead of name poison only propagating from the API file to implementation\nfiles of the same library, we could poison names across the whole package if an\nunqualified lookup in a scope fails. If fully enforced, this would improve the\nability to move code between libraries, as it wouldn't be possible for\nunqualified lookup results to change depending on where the code is. Full\nenforcement of this rule would require a link-time check, but it could be\npartially enforced at compile time, in cases where the poisoning lookup and the\ndeclaration are both visible in some compilation step.\n\nWhether this option might be appealing may depend on our position on name\nshadowing. In addition to the option commonly used in other languages, of\nallowing names in inner scopes to hide names in outer scopes, we have been\nconsidering a more restrictive option: always look in all enclosing scopes, and\ndiagnose an ambiguity if an unqualified name is found in more than one enclosing\nscope.\n\nWe do not yet have a proposal with a name shadowing rule. If we pick the more\nrestrictive option, the impact of package-wide name poisoning is also quite\nrestrictive: for example, a name used as a local variable in a function in one\nlibrary cannot be used as a public name in any enclosing namespace in any\nlibrary in that package. If we pick the less-restrictive rule, then package-wide\npoisoning may become more palatable and should be reconsidered.\n\nWith either shadowing rule, some special accommodation for private names might\nbe reasonable. A use of a name in one library that results in the name being\npoisoned should probably not conflict with a private declaration in another\nlibrary, because the two uses of the name cannot interact.\n\n### Allow shadowing in implementation file after use in API file\n\nIn this proposal, we say it is an error for a name to be shadowed in an\nimplementation file after it is used in an API file:\n\n```carbon\nlibrary \"foo\" api;\nnamespace N;\nclass A {}\nfn N.F(x: A);\n```\n\n```carbon\nlibrary \"foo\" impl;\n// ❌ Shadows `class A`. Cannot declare `N.A` after we already\n// looked for it in the declaration of `N.F`.\nclass N.A {}\nfn N.F(x: A) {}\n```\n\nWe could allow such code. However, this would mean that the redeclaration check\nfor `N.F` would not be purely syntactic.\n\nWe considered other ways of addressing this. In particular, we considered\ndisallowing the declaration of `N.F` in the implementation file because it uses\na local name to declare a non-local function. However, this doesn't resolve the\nproblem: the class `N.A` could be imported from a different library instead of\nbeing declared locally. Variations of this were considered, but none of them\nseemed to work adequately.\n"
  },
  {
    "path": "proposals/p3797.md",
    "content": "# Raw identifier syntax\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3797)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Prior discussion](#prior-discussion)\n    -   [Other languages](#other-languages)\n-   [Proposal](#proposal)\n    -   [Diagnostics](#diagnostics)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Other raw identifier syntaxes](#other-raw-identifier-syntaxes)\n    -   [Restrict raw identifier syntax to current and future keywords](#restrict-raw-identifier-syntax-to-current-and-future-keywords)\n    -   [Don't require syntax for references to raw identifiers](#dont-require-syntax-for-references-to-raw-identifiers)\n    -   [Don't provide raw identifier syntax](#dont-provide-raw-identifier-syntax)\n\n<!-- tocstop -->\n\n## Abstract\n\nWe want to support legacy identifiers that overlap with new keywords (for\nexample, `base`). This is being called \"raw identifier syntax\" using\n`r#<identifier>`, and is based on\n[Rust](https://doc.rust-lang.org/reference/identifiers.html).\n\nNote this proposal is derived from\n[Proposal #17: Lexical conventions](https://github.com/carbon-language/carbon-lang/pull/17).\n\n## Problem\n\nOne of Carbon's most important goals is to support program and language\nevolution. We know that the set of keywords in Carbon will grow over time, and\nthe easiest kind of language change from an evolutionary perspective is one that\nis known to break no programs, that lets programs migrate incrementally to the\nnew language rule, and that either has no migration cost or only imposes\nautomatable migration cost on the code that intends to use the new feature.\n\n## Background\n\n### Prior discussion\n\nWe have proposals that discussed using `r#` but did not make a decision in favor\nof it:\n\n-   [Proposal #17: Lexical conventions](https://github.com/carbon-language/carbon-lang/pull/17)\n    originally proposed it, but when it was split into multiple proposals, raw\n    identifiers were not retained.\n    -   This proposal copies substantial parts of its text from here.\n-   [Proposal #2107: Clarify rules around `Self` and `.Self`](https://github.com/carbon-language/carbon-lang/pull/2107)\n    mentions `r#` syntax as proposed but not in use.\n\n### Other languages\n\n[Rust](https://doc.rust-lang.org/reference/identifiers.html) provides this as\n\"Raw identifiers\", using `r#` as a prefix (`r#self`). The documented syntax is:\n\n```\nRAW_IDENTIFIER : r# IDENTIFIER_OR_KEYWORD Except crate, self, super, Self\n```\n\n[C#](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/verbatim)\nprovides this as \"vebatim identifiers\", using `@` as a prefix (`@self`). The\n[documented syntax](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#643-identifiers)\nis:\n\n```\nfragment Escaped_Identifier\n    // Includes keywords and contextual keywords prefixed by '@'.\n    // See note below.\n    : '@' Basic_Identifier\n    ;\n```\n\n[Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/lexicalstructure/#Identifiers)\nprovides this as part of the identifier grammar, using backticks (\\`self\\`). The\ndocumented syntax is:\n\n```\nidentifier → `identifier-head identifier-characters?`\n```\n\n## Proposal\n\nA _raw identifier_ can be specified by prefixing a word with `r#`, such as\n`r#requires`. Raw identifiers can be used to introduce and use names that are\nlexically identical to keywords. The declaration of a raw identifier does not\nprevent the base word from being interpreted as a keyword; otherwise, they\nbehave identically to the word formed by removing the `r#` prefix.\n\n### Diagnostics\n\nIn diagnostics, if there is a keyword `r#<identifier>`, then raw identifiers\nshould be expected to print with the `r#` prefix. Otherwise, they will typically\nuse the non-prefixed identifier name for consistency.\n\n## Rationale\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Raw identifier syntax provides a way to add keywords to the language\n        while still offering code a reasonable upgrade path, which can also be\n        automated.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   The `r#` syntax is consistent with raw string literals, and should be\n        representative to readers that something unusual is being done.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   C++ code using identifiers that are keywords in Carbon can use raw\n        identifier syntax.\n    -   The converse does not work: if Carbon code has an identifier that is a\n        C++ keyword, it needs to be renamed for use from C++ code.\n\n## Alternatives considered\n\n### Other raw identifier syntaxes\n\nFor considering other syntaxes, a couple initial considerations for\n`r#identifier` prefixing is:\n\n-   We use `#` prefixes for\n    [string literals](/docs/design/lexical_conventions/string_literals.md), and\n    it's likely we'll support syntax similar to `f#\"...\"` for interpolated\n    string literals. The `r#` syntax offers consistency with this, and will\n    hopefully be recognizable to users.\n-   Consistency with Rust.\n    -   Rust uses `r#\"...\"` for raw string literals, whereas Carbon uses\n        `#\"...\"`.\n-   Introduces another code execution path in lexing identifiers. This likely\n    causes a slowdown;\n    [PR #3044](https://github.com/carbon-language/carbon-lang/pull/3344)\n    indicates roughly 2%, although that was run on a system with noisy\n    benchmarks -- details would require a better system for benchmark. Note 2%\n    could represent that `r` is 1-in-55 identifiers with a 100% slowdown with\n    linear cost scaling for other similar code, or it could indicate that the\n    additional code path causes incremental slowdown but if other code (such as\n    `f#\"...\"`) used the same codepath it may instead have constant cost scaling\n    (negligible incremental cost). This may also be either reduced or become\n    more significant if we enable tail calls and other optimizations. As a\n    consequence, the precise overhead is difficult to quantify at this time.\n\nVarious other prefixes have been discussed, mostly using a special character\nprefix in order to restrict the lexing impact. In particular:\n\n-   `\\` prefix, as in `\\identifier`.\n    -   Similar to `\\` escaping in strings.\n    -   More intuitive \"escaping\" semantic for some developers versus `r#`.\n    -   Creates a different meaning for `\\n` as an identifier versus `\\n` as a\n        character escape.\n        -   Some of this could be addressed by restricting `\\` raw identifiers\n            to only keywords in the language, meaning `\\n` would only be a\n            character escape. The alternative\n            [Restrict raw identifier syntax to current and future keywords](#restrict-raw-identifier-syntax-to-current-and-future-keywords)\n            applies to this solution.\n-   `#` prefix without `r`, as in `#identifier`.\n    -   Would be more consistent with string literals, and avoid the lexing\n        overhead.\n    -   We are considering using a `#` prefix for metaprogramming, so the `r`\n        offers a way to keep the `#` prefix available for other purposes.\n    -   `#if` may look to C++ developers like a compiler directive, rather than\n        a raw identifier for `if`.\n-   `@` prefix, as in `@identifier`.\n    -   Consistent with C#.\n    -   We've also discussed using a `@` prefix for attributes, similar to\n        Python. Similar to `#`, this would be conflicting.\n-   `` ` `` wrapping, as in `` `identifier` ``.\n    -   Consistent with Swift.\n    -   We prefer not to use backticks for Carbon syntax so that it is easy to\n        write in Markdown, which uses backticks for inline code. For example, to\n        render a backtick there are a couple options:\n        -   Use more backticks: ``` `` ` `` ```\n        -   Use inline HTML: ``<code>\\`</code>``\n-   Other currently unused characters as prefix, such as `~identifier`,\n    `$identifier`, or `%identifier`.\n    -   We expect raw identifiers to be relatively rare. There may be future\n        uses for these characters that allow us to serve a broader use-case.\n    -   While we could change raw string literal syntax to use the same\n        character, it would be helpful if raw string literal syntax had some\n        degree of cross-language syntactic consistency in order to reduce\n        learning curves.\n\nRaw identifier syntax is expected to be an edge case of the language. As a\nconsequence, it should probably be expected that developers reading it will be\nmore likely to rely on their understanding of the syntax either from other parts\nof Carbon, or from other languages. This means it's helpful if the syntax can be\nunderstood on its own, but if it's confusable with C++ syntax, the relative\nrarity could exacerbate understandability issues.\n\nIf performance of the `r#` prefix is prohibitive, that would be a justification\nfor changing approaches.\n\n### Restrict raw identifier syntax to current and future keywords\n\nWe had discussed maintaining a list of current and future keywords, and only\nallowing raw identifier syntax in those cases. If this were done as part of the\ntoolchain, releases would need to push versions that \"declare\" future keywords\nwithout turning them into actual keywords. For a library that used those\nidentifiers, it would initially be compatible with compiler versions up to and\nincluding the \"future\" keyword version; upon using raw identifier syntax, that\nwould become the minimum compiler version. This creates a compiler versioning\ndependency that it might be helpful to avoid.\n\nAs an alternative approach, Carbon could provide a command line option which\nlibraries could use to specify future keywords that are used in the program.\nWhile some systems such as `bazel` allow libraries to indicate options they need\nfor compilation, other build systems such as `cmake` might require library users\nto update their dependencies as well. The consequence would be that library\nusers might need to more carefully monitor options when updating compilers.\n\n### Don't require syntax for references to raw identifiers\n\nWe could say that, in a scope where a raw identifier has been declared, the\ntoken without `r#` now refers to the identifier instead of the keyword. If the\nuser actually needs the keyword within that scope, they could instead use `k#`\nor something similar.\n\nA particular example of this can be seen with the `base` keyword:\n\n```\nclass C {\n    // `base` now means this name in the scope of `C`.\n    var r#base: i32;\n    // To extend, `k#base` is now required.\n    extend k#base: T;\n}\n\nfn MakeC() -> C {\n  // The struct literal's `base` is outside the scope of `C`, so must use\n  // `r#base`.\n  var c: C = {.r#base = 0, .base = { ... }};\n  // A member reference could use the identifier-default for `base` in `C`.\n  c.base = 1;\n  c.k#base = {...};\n  return c;\n}\n```\n\nThe equivalent under proposed syntax (uniformly using `r#base`) is:\n\n```\nclass C {\n    var r#base: i32;\n    extend base: T;\n}\n\nfn MakeC() -> C {\n  var c: C = {.r#base = 0, .base = { ... }};\n  c.r#base = 1;\n  c.base = {...};\n  return c;\n}\n```\n\nAt present we are deciding this is unnecessary complexity, and it's better to\nrequire `r#` in all references to the identifier.\n\n### Don't provide raw identifier syntax\n\nWe could omit raw identifier syntax. It introduces a novel risk of underhanded\ncode that appears to mean one thing but means a different thing, by shadowing a\nkeyword with an identifier. This risk is discussed in\n[Initial Analysis of Underhanded Source Code (Wheeler 2020)](https://www.ida.org/-/media/feature/publications/i/in/initial-analysis-of-underhanded-source-code/d-13166.ashx)\n(page 4-2).\n\nThis concern is considered non-blocking.\n"
  },
  {
    "path": "proposals/p3833.md",
    "content": "# SemIR fidelity when representing rewrite semantics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3833)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Work to incorporate needed simplifications directly into the design](#work-to-incorporate-needed-simplifications-directly-into-the-design)\n    -   [Keep a full fidelity mode for any other optimizations](#keep-a-full-fidelity-mode-for-any-other-optimizations)\n    -   [Example: overloaded operators](#example-overloaded-operators)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Strictly adhere to a full-fidelity model](#strictly-adhere-to-a-full-fidelity-model)\n    -   [Directly implement the optimized model](#directly-implement-the-optimized-model)\n\n<!-- tocstop -->\n\n## Abstract\n\nThe toolchain's [Semantic IR][semir] should start off modeling the full,\ncomplex, and rich library-based and generic extension point semantics of Carbon\nwithout eliding any layers or rewrites for compile time efficiency. We shouldn't\nfront-load elision or optimization when implementing the designs.\n\nOnce we have a full-fidelity implementation, we should work to build an\nefficient elision, short-circuit, or common case simplification into the design\nitself sufficient to make the SemIR model efficient. Only if we cannot find a\nreasonable approach for that should we diverge the SemIR model to optimize its\nefficiency, and we should preserve full fidelity in an optional mode.\n\n[semir]:\n    https://docs.google.com/document/d/1RRYMm42osyqhI2LyjrjockYCutQ5dOf8Abu50kTrkX0/edit?resourcekey=0-kHyqOESbOHmzZphUbtLrTw#heading=h.503m6lfcnmui\n\n## Problem\n\nCarbon's design heavily leverages types and APIs defined in the `Core` package\nand implicitly imported with the prelude. It also defines rich extension points\nand generic semantic models for the language, typically through rewrites from\nthe user-facing syntax into more complex syntax that operates through\n`interface`s and `impl`s that provide the generic model and customization\npoints.\n\nModeling this at full fidelity in the toolchain's [Semantic IR][semir] is\nexpected to create an unreasonably expensive representation for common and\npervasive patterns in code. On the other hand, every divergence between the\nSemIR model and the design adds both risk and cost. When we can keep the two in\nsync, we get the best engineering tradeoffs, provided it is reasonably\nefficient.\n\n## Background\n\nSeveral proposals have started to surface these kinds of challenge, but to a\nlesser degree. Some examples:\n\n-   [Proposal #820 - Implicit conversions](https://github.com/carbon-language/carbon-lang/pull/820)\n-   [Proposal #845 - `as` expressions](https://github.com/carbon-language/carbon-lang/pull/845)\n-   [Proposal #1083 - Arithmetic expressions](https://github.com/carbon-language/carbon-lang/pull/1083)\n\nThe most significant step that motivates capturing an explicit strategy here is\n[proposal #3720 - Binding operators](https://github.com/carbon-language/carbon-lang/pull/3720).\n\n## Proposal\n\nInitially, the toolchain should have SemIR model the full semantics of Carbon,\nwith all rewrites, expressive hooks, and library references. This will serve two\npurposes as we build out the toolchain's support for all of Carbon's features.\n\n### Work to incorporate needed simplifications directly into the design\n\nFirst, this will allow us to study the resulting SemIR, and understand exactly\nhow and where the efficiency explodes for expected coding patterns. We should\nuse this to try to adjust the design to build in targeted common-case\nsimplifications and elisions that make precise modeling of the design\nsufficiently cheap in practice.\n\nWe see this pattern emerging in good ways already today in the toolchain with\nimplicit conversions: when calling functions, we need to allow for implicit\nconversions. But we don't want to have an identity implicit conversion on all\nthe arguments which already are the correct type. Rather than notionally\n\"always\" implicitly converting, we make the design itself specify that the\nimplicit conversion only occurs when needed and can then have the desired\nminimal representation in SemIR.\n\nBeyond simplifying the SemIR model, it also ends up addressing an important\naspect of the semantics -- we don't want to create unnecessary temporaries to\ninitialize rather than directly initializing. The toolchain in fact follows\nsimilar patterns to model expression categories for similar reasons -- the\nminimal semantic model is also the desired design.\n\nWe can even incorporate other kinds of design changes to allow the full fidelity\nSemIR model to be efficient, such as assuring that we can build and reuse a\ncached representation repeatedly and cheaply rather than requiring it to be\nrebuilt on each instance of a specific pattern.\n\n### Keep a full fidelity mode for any other optimizations\n\nWe may still ultimately end up unable to achieve the desired SemIR efficiency\neven after making all the simplifications we can to the design itself. If and\nwhen we reach this point, we will still want to have the full fidelity\nimplementation and be able to use it behind some option. We can use it to\nunderstand how the design works in complex cases and to debug unexpected\nbehavior in the toolchain. This means starting with that implementation doesn't\nresult in sunk cost.\n\n### Example: overloaded operators\n\n> Note: this example isn't trying to capture all the nuance of the current\n> design or suggest any change to the design. It is merely trying to provide an\n> illustration of how we might follow the proposal in practice.\n\nAs an example to help illustrate this, how should the toolchain model overloaded\noperators? This proposal suggests that _initially_, the implementation should\naim to fully model the rewrite-based dispatch through interfaces in the prelude.\nThat is, each use of `x + y` should turn into roughly equivalent SemIR as would\nbe used to model the rewritten semantics of\n`x.(package#Core.AddWith(typeof(y)).Op)(y)`. This in turn would dispatch to an\nexact-type implementation which would provide any implicit conversions, and so\non. And importantly, this would occur even when we know that the types of `x`\nand `y` are exactly `i32` and we could alternatively directly hard code the\ntoolchain to use the desired builtin implementation.\n\nTo be precise, the expectation is that the SemIR for `x + y` should as a\nconsequence model all of:\n\n-   Looking up the `package#Core.AddWith` interface, using the imagined syntax\n    `package#<Name>` for directly looking up a specific package name (as opposed\n    to doing unqualified name lookup).\n-   Passing the type of `y` as a parameter to the interface, which is\n    illustrated with the imagined syntax `typeof(<expression>)` but would likely\n    directly use the type rather than forming an actual `typeof` expression (see\n    below).\n-   Looking up the `Op` method.\n-   Calling that `Op` method on `x` with `y` as its parameter just as we would\n    model any call to `object.(Interface.Method)(y)`.\n\n> Note: this isn't a proposal for either the `package#<Name>` or\n> `typeof(<expression>)` imagined syntaxes. If we want these syntaxes, that will\n> be a separate proposal.\n\nHowever, specific things that would still be reasonable without deviating from\nthe full semantic modeling here:\n\n-   Not representing a user-written `typeof` style expression to compute the\n    type, or duplicating the `y` expression.\n-   Caching and reusing SemIR for immutable things like successfully resolved\n    name lookup. Concretely, reusing a single cached lookup of\n    `package#Core.AddWith` would still provide the full model. And similarly,\n    reusing an already computed parameterization such as\n    `package#Core.AddWith(i32)` repeatedly, and the lookup of `Op` within that\n    parameterization.\n\nThe reason is that these don't change the semantics in any way -- they are\nconstructively the same results.\n\nThis should be the initial implementation _goal_, not a requirement for any\nincremental progress on implementation. Short-circuiting or other approximations\nused in incrementally building towards this goal should always be reasonable to\nconsider based on the tradeoffs at hand. But they should be seen as temporary,\nincremental measures and where possible removed so we can evaluate the full\nsemantic model when the implementation is complete.\n\nBased on the practical costs that this kind of model incurs once we have it\nimplemented, we should first look for ways to adjust the design itself to avoid\nforming the complex semantic expansion in enough cases to make the model\nscalable. And only when we've exhausted those options begin adding long-term\nshortcuts in the SemIR model for common cases with a option to disable them for\ntesting and debugging.\n\n## Rationale\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   It's easy when specifying the design of the language with rewrite\n        semantics in a way that accidentally has a cycle -- where the rewrite\n        result is still a construct that should be rewritten. Without the\n        proposed constraint, these accidental cycles are easily resolved in the\n        implementation by exiting at a convenient place. However, this proposal\n        will ensure that the rule for where the cycle is broken is actually\n        surfaced into the design, making the design more robust and complete in\n        describing the expected behavior.\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   Preserving a full fidelity model of the language design in SemIR helps\n        ensure we can build rich and powerful tools that reason about even\n        complex or typically \"hidden\" parts of Carbon's design. This has\n        regularly proven critical in the design of effective tooling for C++ and\n        other languages.\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n    -   We can't afford for full fidelity representation of Carbon's design to\n        make the practical use of the toolchain have poor compile times and slow\n        down the development experience with Carbon. We need to have a strategy\n        for addressing the expected overhead of the level of customization and\n        layered design that we're building into Carbon.\n\n## Alternatives considered\n\n### Strictly adhere to a full-fidelity model\n\nWe could simply insist on never deviating from the full-fidelity model. However,\nthis would force us to compromise at least one of our top-level goals for\nCarbon: either we would have to regress the speed and scalability of\ndevelopment, or lose some of the simplicity and cohesive design.\n\nBoth of those seem worse outcomes than having some limited divergence between\nSemIR and the design, and there exist reasonable mitigations such as a option to\nswitch between modes.\n\n### Directly implement the optimized model\n\nWe could directly jump to an optimized model that we expect to match the common\ncase behavior, and add opt-in complexity when needed for non-common-cases.\nHowever, this would both remove a useful tool in driving simplification of the\ndesign itself that can result in a overall superior tradeoff. It would also\ncreate risk of divergence, and the need to eventually implement mode to disable\nthe optimization.\n\nIn some cases, we would end up discovering a need to simplify the design for\nsemantic reasons, and the divergence would have resulted in wasted effort in the\ntoolchain.\n\nStarting with the full fidelity model seems to more reliably converge the design\nearly and result in a minimal set of effective optimizations.\n"
  },
  {
    "path": "proposals/p3848.md",
    "content": "# Lambdas\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3848)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Syntax Overview](#syntax-overview)\n    -   [Syntax Defined](#syntax-defined)\n-   [Introducer](#introducer)\n-   [Positional Parameters](#positional-parameters)\n    -   [Positional Parameter Restrictions](#positional-parameter-restrictions)\n-   [Function Captures](#function-captures)\n    -   [Capture Modes](#capture-modes)\n    -   [Default Capture Mode](#default-capture-mode)\n-   [Function Fields](#function-fields)\n-   [Copy Semantics](#copy-semantics)\n-   [Self and Recursion](#self-and-recursion)\n-   [Rationale](#rationale)\n-   [Alternatives Considered](#alternatives-considered)\n    -   [Alternative Considered: Terse vs Elaborated](#alternative-considered-terse-vs-elaborated)\n    -   [Alternative Considered: Sigil](#alternative-considered-sigil)\n    -   [Alternative Considered: Additional Positional Parameter Restriction](#alternative-considered-additional-positional-parameter-restriction)\n    -   [Alternative Considered: Recursive Self](#alternative-considered-recursive-self)\n-   [Future Work](#future-work)\n    -   [Future Work: Reference Captures](#future-work-reference-captures)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis document proposes a path forward to add lambdas to Carbon. It further\nproposes augmenting function declarations to create a more continuous syntax\nbetween the two categories of functions. In short, both lambdas and function\ndeclarations will be introduced with the `fn` keyword. The presence of a name\ndistinguishes a function declaration from a lambda expression, and the rest of\nthe syntax applies to both kinds. By providing a valid lambda syntax in Carbon,\nmigration from from C++ to Carbon will be made easier and more idiomatic. In\nC++, lambdas are defined at their point of use and are often anonymous, meaning\nreplacing them solely with function declarations would create an ergonomic\nburden compounded by the need for the migration tool to select a name.\n\nAssociated discussion docs:\n\n-   [Lambdas Discussion 1](https://docs.google.com/document/d/1rZ9SXL4Voa3z20EQz4UgBMOZg8xc8xzKqA1ufPQdTao/)\n-   [Lambdas Discussion 2](https://docs.google.com/document/d/14K_YLjChWyyNv3wv5Mn7uLFHa0JZTc21v_WP8RzC8M4/)\n-   [Lambdas Discussion 3](https://docs.google.com/document/d/1VVOlRuPGt8GQpjsygMwH2B7Wd0mBsS3Qif8Ve2yhX_A/)\n-   [Lambdas Discussion 4](https://docs.google.com/document/d/1Sevhvjo06Bc6wTigNL1pK-mlF3IXvzmU1lI2X1W9OYA/)\n\n# Background\n\nRefer to the following documentation about lambdas in other languages. What\nseparates these three and makes them more analegous to Carbon's direction is the\nuse of \"captures\" such that the lambda has state, a lifetime, etc.\n\n-   [Lambdas in C++](https://en.cppreference.com/w/cpp/language/lambda)\n-   [Closures in Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/)\n-   [Closures in Rust](https://doc.rust-lang.org/rust-by-example/fn/closures.html)\n\n## Syntax Overview\n\n**Proposal**: A largely continuous syntax between lambdas and function\ndeclarations.\n\nAt a high level, lambdas and function declarations will look like the following.\n\n```\n// In a variable:\nlet lambda: auto = fn => T.Make();\n// Equivalent in C++23:\n// const auto lambda = [] { return T::Make(); };\n\n// In a function call:\nFoo(10, 20, fn => T.Make());\n// Equivalent in C++23:\n// Foo(10, 20, [] { return T::Make(); });\n```\n\n```\n// In a variable:\nlet lambda: auto = fn -> T { return T.Make(); };\n// Equivalent in C++23:\n// const auto lambda = [] -> T { return T::Make(); };\n\n// In a function call:\nPushBack(my_list, fn => T.Make());\n// Equivalent in C++23:\n// PushBack(my_list, [] { return T::Make(); });\n```\n\n```\nfn FunctionDeclaration => T.Make();\n// Equivalent in C++23:\n// auto FunctionDeclaration() { return T.Make(); }\n```\n\n```\nfn FunctionDeclaration -> T { return T.Make(); }\n// Equivalent in C++23:\n// auto FunctionDeclaration() -> T { return T::Make(); }\n```\n\nThere are functions which return an expression, such that the return type is\n`auto`.\n\n```\n// In a variable:\nlet lambda: auto = fn => T.Make();\n// Equivalent in C++23:\n// const auto lambda = [] { return T::Make(); };\n\n// In a function call:\nFoo(fn => T.Make());\n// Equivalent in C++23:\n// Foo([] { return T::Make(); });\n```\n\n```\nfn FunctionDeclaration => T.Make();\n// Equivalent in C++23:\n// auto FunctionDeclaration() { return T::Make(); }\n```\n\nAnd there are functions with an explicit return type that provide a body of\nstatements.\n\n```\n// In a variable:\nlet lambda: auto = fn -> T { return T.Make(); };\n// Equivalent in C++23:\n// const auto lambda = [] -> T { return T::Make(); };\n\n// In a function call:\nFoo(fn -> T { return T.Make(); })\n// Equivalent in C++23:\n// Foo([] -> T { return T::Make(); });\n```\n\n```\nfn FunctionDeclaration -> T { return T.Make(); }\n// Equivalent in C++23:\n// auto FunctionDeclaration() -> T { return T::Make(); }\n```\n\nThere are even functions that provide a body of statements but no return value.\n\n```\n// In a variable:\nlet lambda: auto = fn { Print(T.Make()); };\n// Equivalent in C++23:\n// const auto lambda = [] -> void { Print(T::Make()); };\n\n// In a function call:\nFoo(fn { Print(T.Make()); });\n// Equivalent in C++23:\n// Foo([] -> void { Print(T::Make()); });\n```\n\n```\nfn FunctionDeclaration { Print(T.Make()); }\n// Equivalent in C++23:\n// auto FunctionDeclaration() -> void { Print(T::Make()); }\n```\n\nFunctions support [captures](#function-captures), [fields](#function-fields) and\ndeduced parameters in the square brackets. In addition, `self: Self` or\n`addr self: Self*` can be added to the square brackets of function declarations\nthat exist inside class or interface definitions.\n\n```\nfn Foo(x: i32) {\n  // In a variable:\n  let lambda: auto = fn [var x, var y: i32 = 0] { Print(++x, ++y); };\n  // Equivalent in C++23:\n  // const auto lambda = [x, y = int32_t{0}] mutable -> void { Print(++x, ++y); };\n\n  // In a function call:\n  Foo(fn [var x, var y: i32 = 0] { Print(++x, ++y); });\n  // Equivalent in C++23:\n  // Foo([x, y = int32_t{0}] mutable -> void { Print(++x, ++y); });\n\n  fn FunctionDeclaration[var x, var y: i32 = 0] { Print(++x, ++y); }\n  // Equivalent in C++23:\n  // auto FunctionDeclaration = [x, y = int32_t{0}] mutable -> void { Print(++x, ++y); };\n}\n```\n\nFunctions also support so-called\n[\"positional parameters\"](#positional-parameters) that are defined at their\npoint of use using a dollar sign and a non-negative integer. They are implicitly\nof type `auto`.\n\n```\nfn Foo() {\n  let lambda: auto = fn { Print($0); };\n  // Equivalent in C++23:\n  // auto lambda = [](auto _0, auto...) -> void { Print(_0); };\n  // Equivalent in Swift:\n  // let lambda = { Print($0) };\n\n  fn FunctionDeclaration { Print($0); }\n  // Equivalent in C++23:\n  // auto FunctionDeclaration = [](auto _0, auto...) -> void { Print(_0); };\n  // Equivalent in Swift:\n  // let FunctionDeclaration = { Print($0) };\n}\n```\n\nOf course, functions can also have named parameters, but a single function can't\nhave both named and positional parameters.\n\n```\nfn Foo() {\n  // In a variable:\n  let lambda: auto = fn (v: auto) { Print(v); };\n  // Equivalent in C++23:\n  // const auto lambda = [](v: auto) -> void { Print(v); };\n\n  // In a function call:\n  Foo(fn (v: auto) { Print(v); });\n  // Equivalent in C++23:\n  // Foo([](v: auto) { Print(v); });\n\n  fn FunctionDeclaration(v: auto) { Print(v); }\n  // Equivalent in C++23:\n  // auto FunctionDeclaration(v: auto) -> void { Print(v); }\n}\n```\n\nAnd in additional the option between positional and named parameters, deduced\nparameters are always permitted.\n\n```\nfn Foo() {\n  let lambda: auto = fn [T:! Printable](t: T) { Print(t); };\n\n  fn FunctionDeclaration[T:! Printable](t: T) { Print(t); }\n}\n```\n\n### Syntax Defined\n\nFunction definitions and lambda expressions have one of the following syntactic\nforms (where items in square brackets are optional and independent):\n\n`fn` \\[_name_\\] \\[_implicit-parameters_\\] \\[_tuple-pattern_\\] `=>` _expression_\n\\[`;`\\]\n\n`fn` \\[_name_\\] \\[_implicit-parameters_\\] \\[_tuple-pattern_\\] \\[`->`\n_return-type_\\] `{` _statements_ `}`\n\nThe first form is a shorthand for the second: \"`=>` _expression_ `;`\" is\nequivalent to \"`-> auto { return` _expression_ `; }`\".\n\n_implicit-parameters_ consists of square brackets enclosing a optional default\ncapture mode and any number of explicit captures, function fields, and deduced\nparameters, all separated by commas. The default capture mode (if any) must come\nfirst; the other items can appear in any order. If _implicit-parameters_ is\nomitted, it is equivalent to `[]`.\n\nThe presence of _name_ determines whether this is a function definition or a\nlambda expression. The trailing `;` in the first form is required for a function\ndefinition, but is not part of the syntax of a lambda expression.\n\nThe presence of _tuple-pattern_ determines whether the function body uses named\nor positional parameters.\n\nThe presence of \"`->` _return-type_\" determines whether the function body can\n(and must) return a value.\n\nTo understand how the syntax between lambdas and function declarations is\nreasonably \"continuous\", refer to this table of syntactic positions and the\nfollowing code examples.\n\n| Syntactic Position |                        Syntax Allowed in Given Position (optional, unless otherwise stated)                        |\n| :----------------: | :----------------------------------------------------------------------------------------------------------------: |\n|         A1         |               Required Returned Expression ([positional parameters](#positional-parameters) allowed)               |\n|         A2         |             Required Returned Expression ([positional parameters](#positional-parameters) disallowed)              |\n|         B          |                                   [Default Capture Mode](#default-capture-mode)                                    |\n|         C          | Explicit [Captures](#function-captures), [Function Fields](#function-fields) and Deduced Parameters (in any order) |\n|         D          |                                                Explicit Parameters                                                 |\n|         E1         |           Body of Statements (no return value) ([positional parameters](#positional-parameters) allowed)           |\n|         E2         |          Body of Statements (with return value) ([positional parameters](#positional-parameters) allowed)          |\n|         E3         |         Body of Statements (no return value) ([positional parameters](#positional-parameters) disallowed)          |\n|         E4         |        Body of Statements (with return value) ([positional parameters](#positional-parameters) disallowed)         |\n|         F          |                                                Required Return Type                                                |\n|         G          |                                             Function Declaration Name                                              |\n\n```\n// Lambdas (all the following are in an expression context and are\n// themselves expressions)\n\nfn => A1\n\nfn [B, C] => A1\n\nfn (D) => A2\n\nfn [B, C](D) => A2\n\nfn { E1; }\n\nfn -> F { E2; }\n\nfn [B, C] { E1; }\n\nfn [B, C] -> F { E2; }\n\nfn (D) { E3; }\n\nfn (D) -> F { E4; }\n\nfn [B, C](D) { E3; }\n\nfn [B, C](D) -> F { E4; }\n```\n\n```\n// Function Declarations (all the following are allowed as statements in a\n// function body or as declarations in other scopes)\n\nfn G => A1;\n\nfn G[B, C] => A1;\n\nfn G(D) => A2;\n\nfn G[B, C](D) => A2;\n\nfn G { E1; }\n\nfn G -> F { E2; }\n\nfn G[B, C] { E1; }\n\nfn G[B, C] -> F { E2; }\n\nfn G(D) { E3; }\n\nfn G(D) -> F { E4; }\n\nfn G[B, C](D) { E3; }\n\nfn G[B, C](D) -> F { E4; }\n```\n\n## Introducer\n\n**Proposal**: Introduce with the `fn` keyword to mirror function declarations.\nIf a statement or declaration begins with `fn`, a name is required and it\nbecomes a function declaration. Otherwise, if in an expression context, `fn`\nintroduces a lambda.\n\n```\nlet lambda1: auto = fn => T.Make();\n\nlet lambda2: auto = fn -> T { return T.Make(); };\n\nfn FunctionDeclaration1 => T.Make();\n\nfn FunctionDeclaration2 -> T { return T.Make(); }\n```\n\n## Positional Parameters\n\n**Proposal**: Positional parameters, introduced in the body of a function by way\nof the dollar sign and a corresponding non-negative parameter position integer\n(ex: `$3`), are `auto` parameters to the function in which they are defined.\nThey can be used in any lambda or function declaration that lacks an explicit\nparameter list (parentheses). They are variadic by design, meaning an unbounded\nnumber of arguments can be passed to any function that lacks an explicit\nparameter list. Only the parameters that are named in the body will be read\nfrom, meaning the highest named parameter denotes the minimum number of\narguments required by the function. The function body is free to omit\nlower-numbered parameters (ex: `fn { Print($10); }`).\n\nThis syntax was inpsired by Swift's\n[Shorthand Argument Names](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/#Shorthand-Argument-Names).\n\n```\n// A lambda that takes two positional parameters being used as a comparator\nSort(my_list, fn => $0.val < $1.val);\n// In Swift: { $0.val < $1.val }\n```\n\n### Positional Parameter Restrictions\n\n**Proposal**: There are two restrictions applied to functions with positional\nparameters. The first restriction is that the definitions of function\ndeclarations must be attached to the declarations. The second restriction is\nthat positional parameters can only be used in a context where there is exactly\none enclosing function without an explicit parameter list. For example...\n\n```\nfn Foo1 {\n  fn Bar1 {}  // ❌ Invalid: Foo1 is already using positional parameters\n}\n\nfn Foo2 {\n  Print($0);\n  fn Bar2 {}  // ❌ Invalid: Foo2 is already using positional parameters\n}\n\nfn Foo3 {\n  fn Bar3 {\n    Print($0);  // ❌ Invalid: Foo3 is already using positional parameters\n  }\n}\n\nfn Foo4() {\n  fn Bar4 {\n    Print($0);  // ✅ Valid: Foo4 has explicit parameters\n  }\n}\n\nfn Foo5 {\n  fn Bar5() {}  // ✅ Valid: Bar5 has explicit parameters\n}\n\nfn Foo6() {\n  my_list.Sort(\n    fn => $0 < $1  // ✅ Valid: Foo6 has explicit parameters\n  );\n}\n```\n\n## Function Captures\n\n**Proposal**: Function captures in Carbon mirror the non-init captures of C++. A\nfunction capture declaration consists of a capture mode (for `var` captures)\nfollowed by the name of a binding from the enclosing scope, and makes that\nidentifier available in the inner function body. The lifetime of a capture is\nthe lifetime of the function in which it exists. For example...\n\n```\nfn Foo() {\n  let handle: Handle = Handle.Get();\n  var thread: Thread = Thread.Make(fn [var handle] { handle.Process(); });\n  thread.Join();\n}\n```\n\n```\nfn Foo() {\n  let handle: Handle = Handle.Get();\n  fn MyThread[handle]() { handle.Process(); }\n  var thread: Thread = Thread.Make(MyThread);\n  thread.Join();\n}\n```\n\n### Capture Modes\n\n**Proposal**: `let` and `var` can appear as function captures. They behave as\nthey would in regular bindings.\n\nTo prevent ambiguities, captures can only exist on functions where the\ndefinition is attached to the declaration. This means they are supported on\nlambdas (which always exist in an expression context) and they are supported on\nfunction declarations that are immediately defined inside the body of another\nfunction (which is in a statement context), but they are not supported on\nforward-declared functions nor are they supported as class members where\n`self: Self` is permitted.\n\nCapture modes can be used as\n[default capture mode specifiers](#default-capture-mode) or for explicit\ncaptures as shown in the example code below.\n\n```\nfn Example {\n  var a: i32 = 0;\n  var b: i32 = 0;\n\n  let lambda: auto = fn [a, var b] {\n    a += 1;  // ❌ Invalid: by-value captures are immutable\n\n    b += 1;  // ✅ Valid: Modifies the captured copy of the by-object capture\n  };\n\n  lambda();\n}\n```\n\n```\nfn Example {\n  fn Invalid() -> auto {\n    var s: String = \"Hello world\";\n    return fn [s]() => s;\n  }\n\n  // ❌ Invalid: returned lambda references `s` which is no longer alive\n  // when the lambda is invoked.\n  Print(Invalid()());\n}\n```\n\nNote: If a function object F has mutable state, either because it has a\nby-object capture or because it has a by-object function field, then a call to F\nshould require the callee to be a reference expression rather than a value\nexpression. We need a mutable handle to the function in order to be able to\nmutate its mutable state.\n\n### Default Capture Mode\n\n**Proposal**: By default, there is no capturing in functions. The lack of any\nsquare brackets is the same as an empty pair of square brackets. Users can opt\ninto capturing behavior. This is done either by way of individual explicit\ncaptures, or more succinctly by way of a default capture mode. The default\ncapture mode roughly mirrors the syntax `[=]` and `[&]` capture modes from C++\nby being the first thing to appear in the square brackets.\n\n```\nfn Foo1() {\n  let handle: Handle = Handle.Get();\n  fn MyThread[var]() {\n    handle.Process();  // `handle` is captured by-object due to the default capture\n                       // mode specifier of `var`\n  }\n  var thread: Thread = Thread.Make(MyThread);\n  thread.Join();\n}\n\nfn Foo2() {\n  let handle: Handle = Handle.Get();\n  fn MyThread[let]() {\n    handle.Process();  // `handle` is captured by-value due to the default capture\n                       // mode specifier of `let`\n  }\n  var thread: Thread = Thread.Make(MyThread);\n  thread.Join();\n}\n```\n\n## Function Fields\n\n**Proposal**: Function fields mirror the behavior of init captures in C++. A\nfunction field definition consists of an irrefutable pattern, `=`, and an\ninitializer. It matches the pattern with the initializer when the function\ndefinition is evaluated. The bindings in the pattern have the same lifetime as\nthe function, and their scope extends to the end of the function body.\n\nTo prevent ambiguities, function fields can only exist on functions where the\ndefinition is attached to the declaration. This means they are supported on\nlambdas (which always exist in an expression context) and they are supported on\nfunction declarations that are immediately defined inside the body of another\nfunction (which is in a statement context), but they are not supported on\nforward-declared functions nor are they supported as class members where\n`self: Self` is permitted.\n\n```\nfn Foo() {\n  var h1: Handle = Handle.Get();\n  var h2: Handle = Handle.Get();\n  var thread: Thread = Thread.Make(fn [a: auto = h1, var b: auto = h2] {\n    a.Process();\n    b.Process();\n  });\n  thread.Join();\n}\n```\n\n## Copy Semantics\n\n**Proposal**: To mirror the behavior of C++, function declarations and lambdas\nwill be as copyable as their contained function fields and function captures.\nThis means that, if a function holds a by-object function field, if the type of\nthe field is copyable, so too is the function that contains it. This also\napplies to captures.\n\nThe other case is by-value function fields. Since C++ const references, when\nmade into fields of a class, prevent the class from being copied assigned, so\ntoo should by-value function fields prevent the function in which it is\ncontained from being copied assigned.\n\n## Self and Recursion\n\n**Proposal**: To mirror C++'s use of capturing `this`, `self` should always come\nfrom the outer scope as a capture. `self: Self` is never permitted on lambdas.\nFor function declarations, it is only permitted when the function is a member of\na class type or an interface, such that it refers to the class/interface and not\nto the function itself.\n\nNote: Given the direction in\n[#3720](https://github.com/carbon-language/carbon-lang/pull/3720), an expression\nof the form `x.(F)`, where `F` is a function with a `self` or `addr self`\nparameter, produces a callable that holds the value of `x`, and does not hold\nthe value of `F`. As a consequence, we can't support combining captures and\nfunction fields with a `self` parameter.\n\n## Rationale\n\nLambdas in Carbon serve two purposes. The primary purpose is in support of the\n[\"Code that is easy to read, understand, and write\"](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\ngoal. It is because of this goal that we leverage syntactic features such as the\nreturned expression (indicated by `=>`) and positional parameters (indicated by\nthe lack of a tuple pattern of explicit parameters as well as the use of `$N` in\nthe body of such functions). In addition, Lambdas serve to support the\n[Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\ngoal. They are defined at their point of use and are often anonymous, meaning\nreplacing C++ lambdas solely with function declarations will create an ergonomic\nburden compounded by the need for the migration tool to select a name.\n\n## Alternatives Considered\n\n### Alternative Considered: Terse vs Elaborated\n\nProposed above is a continuous syntax between lambdas and function declarations.\nAlternatively, Carbon could adopt a few different categories of functions, as\nwas considered in a previous discussion doc\n([Lambdas Discussion 2](https://docs.google.com/document/d/14K_YLjChWyyNv3wv5Mn7uLFHa0JZTc21v_WP8RzC8M4/)).\nThese categories would be terse lambdas, elaborated lambdas, and function\ndeclarations. Unfortunately, separating these categories out presented a\nsyntactic challenge in the form of cliffs, explained below. As a result, they\nwere decided against.\n\nTerse lambdas were slated to be the most compact form of a lambda. Combined with\na [sigil introducer](#alternative-considered-sigil), they would be syntactically\nminimal. One way in which syntax was minimized was the granting of an\n**implicit** default [capture](#function-captures) mode. If no square brackets\nwere present, by-value captures would be allowed. This, combined with the lack\nof an arrow to signify a return value, created syntax of the following form\n(being passed into the filter function below).\n\n```\nlet zero: i32 = 0;\nlet list_all: List(i32) = GetAllValues();\nlet list_positive: List(i32) = list_all.Filter(\n  @ $0 > zero\n);\n```\n\nTo give users more control over the feature set in a lambda, the next step up\nwas an elaborated lambda. This provided the ability to add both square brackets\nand explicit parameters to lambdas at the cost of more syntax. Unfortunately,\nthis also meant there was a bit of a _syntactic cliff_ and a stumbling block. It\nwas considered desirable for empty square brackets to mean capturing is\ndisabled. But since the no-square-brackets form needed to support capturing for\nterse lambdas, elaborated lambdas needed to both add the square brackets and\nalso add an explicit default capture mode at the same time just to maintain the\nexisting capturing behavior. The net result was code that looked like the\nfollowing (being passed into the filter function again).\n\n```\nlet zero: i32 = 0;\nlet list_all: List(i32) = GetAllValues();\nlet list_positive: List(i32) = list_all.Filter(\n  @[let](x: auto) x > zero\n);\n```\n\nFinally, if a user wanted to upgrade a lambda to a function declaration, this\ncreated another cliff where they needed to switch from the sigil to the `fn`\nkeyword, on top of adding a name. Ultimately these downsides suggested that a\ncontinuous syntax was the better path forward, despite the face that the\nshortest spellable lambda would be a bit less terse than the alternative\nconsidered.\n\n### Alternative Considered: Sigil\n\nProposed above is the use of `fn` as the [introducer](#introducer) for all\nfunctions/lambdas. An alternative considered was to tntroduce with a sigil, such\nas `$` or `@`. Since introducer punctuation is such a scarce resource, and since\nthere was no consensus on what sigil would best represent a lambda, and since\nthere was a desire to create a more continuous syntax between lambdas and\nfunction declarations, this alternative was decided against. It would have\nlooked like the following:\n\n```\nlet lambda1: auto = @ => T.Make();\n\nlet lambda2: auto = @[]() -> T { return T.Make(); };\n```\n\n### Alternative Considered: Additional Positional Parameter Restriction\n\nIn addition to\n[the above proposed restrictions](#positional-parameter-restrictions) to\npositional parameters, an additional restriction was considered. That being,\nvisibility of functions with positional parameters could be restricted to only\nnon-public interfaces. This alternative was considered by way of a leads\nquestion ([#3860](https://github.com/carbon-language/carbon-lang/issues/3860))\nand was decided against, with the speculation that such a restriction may be\nenforced by way of an HOA rule as opposed to a compiler error.\n\n### Alternative Considered: Recursive Self\n\nProposed above is a deliniation between function declarations that can provide a\n`self` parameter and functions declarations (plus lambdas) which cannot. An\nalternative was considered such that, for use in recursion, `self: Self` could\nbe permitted on all functions and lambdas and refer to the function itself.\nUnfortunately, it created a bit of a discontinuity between class members and\nnon-class members and was thus decided against.\n\n## Future Work\n\n### Future Work: Reference Captures\n\nMuch discussion has been had so far about the implications of capturing by\nreference. For now, such behavior is supported not through captures but instead\nthrough function fields formed from the address of an object in the outer scope.\nIt is **imperative** that more work be done in this area to address the\nergonomic concerns of the current solution.\n"
  },
  {
    "path": "proposals/p3927.md",
    "content": "# More consistent package syntax\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3927)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Mandatory `api` or `impl` as suffix](#mandatory-api-or-impl-as-suffix)\n    -   [Put the `impl` modifier before `library`](#put-the-impl-modifier-before-library)\n\n<!-- tocstop -->\n\n## Abstract\n\nChange the syntax for `package` declarations from:\n\n```carbon\n[package Foo] [library \"bar\"] api;\n[package Foo] [library \"bar\"] impl;\n```\n\nto\n\n```carbon\n[package Foo] [library \"bar\"];\nimpl [package Foo] [library \"bar\"];\n```\n\n## Problem\n\nThe `package` declaration is currently inconsistent with other Carbon\ndeclarations:\n\n-   Modifier keywords for other declarations precede the introducer keyword.\n    However, for package declarations, the `api` / `impl` modifier appears at\n    the end of the declaration.\n-   For most declarations describing the public interface of a library, we\n    default to `public` because we prioritize the readability of the public\n    interface over other concerns. However, the `api` tag in a `package` API\n    declaration is mandatory, making the library interface more verbose than\n    necessary.\n\n## Background\n\n[Proposal #107: Code and name organization](/proposals/p0107.md) introduced the\ncurrent syntax. It did\n[consider the possibility of omitting the `api` keyword](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0107.md#different-file-type-labels):\n\n> We've considered dropping `api` from naming, but that creates a definition\n> from absence of a keyword. It also would be more unusual if both `impl` and\n> `test` must be required, that api would be excluded. We prefer the more\n> explicit name.\n\nHowever, this argument did not and could not consider the inconsistencies\nbetween the choice made for package declaration and the choices made for other\ndeclarations, because those inconsistencies were created by later changes:\n\n-   #107 used the `api` keyword as a marker for exporting names from an API\n    file. Later, [proposal #752: api file default public](/proposals/p0752.md)\n    removed this use of the `api` keyword, with the new rule being that\n    declarations are in the public API by default, with an explicit keyword used\n    to mark non-public declarations. This removed all uses of the `api` keyword\n    other than in package declarations.\n-   Rules for modifier keywords were added incrementally by various proposals,\n    with the common syntactic approach that modifier keywords precede an\n    introducer keyword in a declaration.\n\nIn addition, the idea of having `test` files in addition to `api` and `impl`\nfiles has not yet been realised, and we have no current plans to add such a\nfeature. While that may be an interesting avenue to pursue in future, using\n`test` as a modifier keyword may also be an interesting avenue to explore in\nthat case too -- for example, to allow functions and types within an API file to\nbe declared as test-only with a `test` modifier -- and so the possibility of\n`test` files isn't a robust rationale for choosing the syntax for `api` and\n`impl`.\n\n## Proposal\n\nRemove the `api` keyword from `package` and `library` declarations. Consistent\nwith #752, the way we define a public interface is by saying nothing at all.\n\nTurn the `impl` keyword on such declarations into a modifier keyword, consistent\nwith its use in `impl fn` declarations. This reorders the `impl` keyword to the\nstart of the declaration.\n\nIn documentation, we refer to API files as \"API files\", not as \"`api` files\".\nFor consistency, we also refer to implementation files as \"implementation\nfiles\", not as \"`impl` files\". We were previously inconsistent and used both\nterms.\n\n## Details\n\nSee design changes.\n\n## Rationale\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Small readability and writability gain for API files.\n    -   More consistency between different kinds of declaration.\n    -   Minor risk that an `impl` file will be interpreted as an API file due to\n        missing the `impl` modifier. However, this is likely to be caught\n        quickly, whether by file naming conventions, the lack of an implicit\n        import of the \"real\" API file, or by duplicate API file detection in the\n        toolchain.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Marginally more consistent with C++ modules, which use `module Foo` vs\n        `export module Foo` for the two cases -- with a leading keyword.\n        However, C++ defaults to not exporting, so the case with a keyword is\n        reversed, both here and in all other declarations.\n\n## Alternatives considered\n\n### Mandatory `api` or `impl` as suffix\n\nThe rationale for changing from the status quo ante of having a mandatory `impl`\nor `api` keyword as a suffix is documented above.\n\nThis proposal also harmonizes the `impl package` syntax with the\n`import package` syntax:\n\n```carbon\nimpl package Foo library \"bar\";\n\nimport package Baz library \"quux\";\n```\n\nWe consistently use a prefix for the package declaration for both of these\ncases. We also anticipate doing so for the `import reexport package ...` or\n`export import package ...` syntax that is currently under discussion.\n\nAs a trivial side benefit, the degenerate case of the package declaration for\nthe default library in the Main package would now be expressed as simply `;`\nrather than `api;`. We retain the rule that the package declaration is omitted\nentirely in this case, which is slightly easier to justify given that the\nomitted declaration would comprise only a semicolon.\n\n### Put the `impl` modifier before `library`\n\nBecause an implementation file is implementing part of a library, we can\nconsider placing the `impl` keyword before the `library` keyword -- as a\nmodifier on the `library` portion of the declaration -- instead of at the start\nof the overall package declaration.\n\nThis leads to constructs such as:\n\n```carbon\npackage Foo impl library \"bar\";\npackage Foo impl;\nimpl library \"bar\";\n```\n\nWhile there is a logical rationale and consistent explanation for this approach,\nit results in the `impl` keyword's positioning appearing inconsistent: sometimes\nat the start, middle, or end of the declaration. This also doesn't make the\n`impl` declaration consistent with `import`, where the same argument can be\nmade: an `import` imports the library, not the package.\n\nAs a result, we do not pursue this direction.\n"
  },
  {
    "path": "proposals/p3938.md",
    "content": "# Exporting imported names\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3938)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Carbon exports](#carbon-exports)\n    -   [Other languages](#other-languages)\n-   [Proposal](#proposal)\n    -   [Source file introduction](#source-file-introduction)\n-   [Future work](#future-work)\n    -   [Namespaces](#namespaces)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Other `export` syntax structures](#other-export-syntax-structures)\n    -   [Other `export name` placements](#other-export-name-placements)\n    -   [Re-exporting cross-package](#re-exporting-cross-package)\n\n<!-- tocstop -->\n\n## Abstract\n\nIn order to support exporting imported names, add\n`export import library <library>` and `export <name reference>` syntax.\n\n## Problem\n\nAs we develop libraries such as the prelude, we want the ability to indicate\nthat an imported name should be re-exported for indirect use. At present, we can\nuse the prototype `alias` to expose names on a case-by-case basis\n(`alias Foo = Bar;`), but it doesn't work to export the _same_ name\n(`alias Foo = Foo;` is a name conflict), and we want to be able to more broadly\nforward a library's exported names.\n\nFor example:\n\n```\npackage Foo library \"internal\";\n\n// Declare C.\nclass C;\n```\n\n```\npackage Foo;\n\n// We want the ability to expose everything imported here.\nimport library \"internal\";\n```\n\n```\nimport library Foo;\n\n// Uses C by way of the default library.\nvar c: Foo.C;\n```\n\n## Background\n\nSome of the syntax options were discussed\n[on Discord](https://discord.com/channels/655572317891461132/1217182321933815820/1234534411350048810).\n\n### Carbon exports\n\nNames declared in a Carbon file are currently exported by default. A `private`\nkeyword may be used to prevent that export. Note C++ and TypeScript use\nprivate-by-default behavior, so the syntax choices that make sense elsewhere may\nnot make as much sense for Carbon.\n\nAs described in the problem statement, `alias` offers incomplete re-export\nsupport. However, `alias` is not fully designed; it's modeled on informal\ndiscussions.\n\n### Other languages\n\nIn [C++ modules](https://en.cppreference.com/w/cpp/language/modules), this is\n`export import ...`.\n\nIn\n[TypeScript modules](https://www.typescriptlang.org/docs/handbook/2/modules.html),\nsimilar syntax might look like:\n\n```typescript\nimport * from '<module>'\nexport * from '<module>'\n```\n\nIn Python, names in a module are generally public, and imported names are\naccessible too. For example, given `import datetime`, the module makes the name\n`datetime` available to clients. There is interest in\n[more explicit `export` syntax](https://discuss.python.org/t/add-the-export-keyword-to-python/28444).\n\nIn other languages, such as Java, Kotlin, or Go, direct re-exports aren't\nsupported. Instead, the expectation seems to be that either a copy of the entity\nwould be exported, or it should just be moved.\n\n## Proposal\n\nSupport the `export` keyword as a modifier to `import library <library>`\n(excluding cross-package imports). This is `export import` for short. For\nexample:\n\n```carbon\nexport import library \"lib\";\n```\n\nAdditionally, support the `export` keyword on individual, file-scoped or\nnamespace-scoped entities (excluding entities in other packages, and namespaces\nthemselves). This is `export name` for short. For example:\n\n```carbon\n// Export an entity:\nexport Foo;\n// Export an entity inside a namespace:\nexport NS.Bar;\n\n// Invalid: exporting namespaces is disallowed.\nexport NS;\n```\n\nAlthough exporting cross-package names is disallowed, note that `alias` can be\nused to add a package-local name that originates from another package, which\nthen is valid for export. For example:\n\n```carbon\nimport package Other;\n\n// Invalid: cross-package exports are disallowed.\nexport Other.Obj;\n\n// This introduces a package-local name. The alias is exported, and other\n// libraries importing this library may export `Obj`.\nalias Obj = Other.Obj;\n```\n\nThe `export` keyword is only valid in files which are valid to import. It is\ninvalid in files which cannot be imported: implementation files and\n`Main//default`.\n\n### Source file introduction\n\nIn the\n[source file introduction](/docs/design/code_and_name_organization/README.md#source-file-introduction),\n`export import` directives are intermingled with other `import` directives.\n`export name` directives are normal code and cannot be intermingled with any\n`import` directives, including `export import` directives.\n\nThis allows:\n\n```\nimport library \"foo\";\nexport import library \"wiz\";\nimport library \"bar\";\n\nexport FooType;\n\nclass C { ... };\n\nexport BarType;\n```\n\nThis disallows:\n\n```\nimport library \"foo\";\n// Invalid: All `import` directives must come before other code, including\n// `export name`.\nexport FooType;\n\nimport library \"bar\";\n\nclass C { ... };\n\n// Invalid: `export import` must be grouped with `import` directives.\nexport import library \"wiz\";\n```\n\n## Future work\n\n### Namespaces\n\nNamespaces are not valid arguments to `export`; entities in namespaces must be\nindividually exported.\n\nThis keeps open a future design option of having `export` on a namespace export\nall imported names inside the namespace, such as `export NS;`. This could also\nbe achieved with `*` syntax, such as `export NS.*;`. There hasn't been\ndiscussion of this option, and this proposal takes no stance on the option.\n\n## Rationale\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   `export <name>` allows moving entities between libraries without needing\n        to make modifications to clients, enabling more incremental\n        refactorings.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Export logic in general is intended to support factoring large or\n        complex APIs into multiple, smaller files. For example, with the\n        prelude, we'll have many types, interfaces, and implementations: concise\n        re-exporting logic will make it easy to provide a singular\n        `prelude.carbon` that exports all related functionality.\n\n## Alternatives considered\n\n### Other `export` syntax structures\n\nWe discussed several different syntax choices.\n\nA couple placement alternatives discussed were:\n\n-   Put `export` before `library`. For example, `import export library \"lib\"`.\n    -   An advantage of this is that if we support cross-package re-exports,\n        `import Foo export library \"lib\"` could make it clearer the library is\n        being re-exported, rather than the package.\n    -   A disadvantage is that we would probably not put other keywords between\n        the package and library.\n-   Put `export` as a suffix. For example, `import library \"lib\" export`.\n    -   An advantage of this is that it makes `import` statements line up better\n        when some may not have the `export` modifier.\n\nThe current design uses `export` as a prefix. This is for consistency with how\nwe put other modifier keywords, such as `private` or `extern`, prior to the\nintroducer keyword.\n\nA couple keyword alternatives discussed (alongside placement options) were:\n\n-   `reexport`\n    -   An advantage noted is that it may read more intuitively for some\n        developers.\n    -   This proposal suggests `export` because it mirrors `import`, and it's\n        consistent with multiple other languages. It's also shorter, and Carbon\n        often chooses keywords for shortness.\n-   `exported` and `reexported`\n    -   These didn't seem to read as clearly as `export` or `reexport`.\n\n### Other `export name` placements\n\nWe see several options for `export name` placement. This compares them, focusing\non advantages and disadvantages for each option.\n\n1. `export name` with `import`s\n\n    `export name` can (only) appear in the preamble, with the imports, and\n    cannot appear with the other declarations in the library. Note this option\n    could either have `export name` refer to earlier `import`s (creating an\n    ordering consistency issue), or expend additional effort in order to track\n    whether a name was already imported at the site of the `export`.\n\n    Advantages:\n\n    - No need to teach developers they cannot (don't need to) `export` locally\n      introduced names.\n\n    Disadvantages:\n\n    - Although the restricted placement might imply placement is tied to\n      specific libraries, that's not the case. This could mislead developers.\n        - In theory, we could enforce this, but then we could end up breaking\n          code if the path a name is imported through changes.\n\n2. `export name` with other declarations\n\n    `export name` can only appear after imports. This means that all names valid\n    for `export` will already be made available.\n\n    Advantages:\n\n    - `import` remains very special.\n    - Makes it unambiguous that names valid for `export` are already imported.\n\n    Disadvantages:\n\n    - Prevents placing `export name` next to the import that is expected to add\n      the name.\n    - Means `export import` and `export name` will be in different sections: no\n      single place to look for re-exports.\n\n3. No ordering for `export name`\n\n    Let developers choose what the prefer.\n\n    Advantages:\n\n    - Maximum flexibility, HOA rule.\n\n    Disadvantages:\n\n    - Most inconsistent with the desire to treat `import` as special.\n\nWe're choosing option (2). The name lookup issues avoided by requiring `export`\nbe below `import` directives seem worthwhile.\n\nA possible option to (2) might be to create an additional section dedicated to\n`export name` below the `import` section. This proposal suggests avoiding that\nin order to avoid increasing the amount of enforced ordering in Carbon files.\n\n### Re-exporting cross-package\n\nAs proposed, re-exporting names from other packages will not be supported. This\nis done to continue maintaining package boundaries, and so that names aren't\nunexpectedly introduced. For example:\n\n```carbon\npackage Foo;\n\nclass C;\n```\n\n```carbon\npackage Bar;\n\nexport import Foo;\n```\n\n```carbon\npackage Wiz;\n\nimport Bar;\n```\n\nIn the last package `Wiz`, it might be confusing if the name `Foo.C` should be\nintroduced: typically importing `Bar` would put everything under the `Bar`\nnamespace.\n\nWe may choose to re-examine this choice, but this proposal does not include\nsupport.\n"
  },
  {
    "path": "proposals/p3980.md",
    "content": "# Singular `extern` declarations\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/3980)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Declarations](#declarations)\n    -   [Owning `extern` declarations](#owning-extern-declarations)\n-   [Details](#details)\n    -   [Type coherency](#type-coherency)\n        -   [Impact on indirect imports](#impact-on-indirect-imports)\n        -   [Indirect imports of non-`extern` types](#indirect-imports-of-non-extern-types)\n    -   [Using imported declarations](#using-imported-declarations)\n    -   [`private extern`](#private-extern)\n    -   [Validation for non-owning `extern library` declarations](#validation-for-non-owning-extern-library-declarations)\n    -   [No syntactic matching for `extern library` declarations](#no-syntactic-matching-for-extern-library-declarations)\n    -   [Versus proposal #3762](#versus-proposal-3762)\n-   [Rationale](#rationale)\n-   [Future work](#future-work)\n    -   [`extern` and template interactions](#extern-and-template-interactions)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Allow multiple non-owning declarations, remove the import requirement, or both](#allow-multiple-non-owning-declarations-remove-the-import-requirement-or-both)\n    -   [Total number of allowed declarations (owning and non-owning)](#total-number-of-allowed-declarations-owning-and-non-owning)\n        -   [Do not restrict the number of forward declarations](#do-not-restrict-the-number-of-forward-declarations)\n        -   [Allow up to two declarations total](#allow-up-to-two-declarations-total)\n        -   [Allow up to four declarations total](#allow-up-to-four-declarations-total)\n    -   [Don't require a modifier on the owning declarations](#dont-require-a-modifier-on-the-owning-declarations)\n    -   [Only require `extern` on the first owning declaration](#only-require-extern-on-the-first-owning-declaration)\n    -   [Separate require-direct-import from non-owning declarations](#separate-require-direct-import-from-non-owning-declarations)\n    -   [Other `extern` syntaxes](#other-extern-syntaxes)\n    -   [Have types with `extern` members re-export them](#have-types-with-extern-members-re-export-them)\n    -   [Require syntactic matching for `extern library` declarations](#require-syntactic-matching-for-extern-library-declarations)\n\n<!-- tocstop -->\n\n## Abstract\n\nAn entity may be declared `extern` (such as `extern class Foo;`); this means\nthat its type is only complete if the definition is directly imported. It also\nallows for a single declaration in a different library, which must be marked as\n`extern library \"<owning_library>\"` (such as `extern library \"Bar\" class Foo;`).\n\nAlso, establish a different rule of thumb for when modifier keywords are\nrequired: modifier keywords are required when, if prior optional declarations\nwere removed, the lack of the modifier keyword would change behavior.\n\n## Problem\n\nIn the `extern` model from\n[#3762: Merging forward declarations](https://github.com/carbon-language/carbon-lang/pull/3762),\nmultiple `extern` declarations are allowed.\n[#3763: Matching redeclarations](https://github.com/carbon-language/carbon-lang/pull/3763)\nfurther evolved the `extern` keyword.\n\nThe prior `extern` model assumed that the `extern` and non-`extern` declarations\nof a class formed two different types, which could be merged.\n[As discussed on #packages-and-libraries](https://discord.com/channels/655572317891461132/1217182321933815820/1230990636073881693),\nthis runs into an issue with code such as:\n\n```\nlibrary \"a\";\nclass C {}\n```\n\n```\nlibrary \"b\";\nextern class C;\nextern fn F() -> C*;\n```\n\n```\nlibrary \"c\";\nimport library \"a\";\nextern fn F() -> C*;\n```\n\nHere, the return types of `F` differ.\n\nThis proposal aims to address the differing return types by unifying the type of\n`C` regardless of whether it's `extern`. This could be done under multiple\ndifferent approaches, and this proposal aims for one which enables efficient\nimplementation strategies.\n\n## Background\n\nProposals:\n\n-   [#3762: Merging forward declarations](https://github.com/carbon-language/carbon-lang/pull/3762)\n-   [#3763: Matching redeclarations](https://github.com/carbon-language/carbon-lang/pull/3763)\n\nDiscussions:\n\n-   [#packages-and-libraries: `extern` type coherency](https://discord.com/channels/655572317891461132/1217182321933815820/1230990636073881693)\n-   [#packages-and-libraries: When to allow/disallow redeclarations](https://discord.com/channels/655572317891461132/1217182321933815820/1236016051632865421)\n-   [Open discussion 2024-05-09: Number of allowed redeclarations](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.bu7djkos4xo)\n-   [Issue #3986: Alternative naming for `has_extern` keyword](https://github.com/carbon-language/carbon-lang/issues/3986)\n-   [Issue #4025: Handling of indirect access of `extern` types](https://github.com/carbon-language/carbon-lang/issues/4025)\n-   [#typesystem: Will `&` have an extension point?](https://discord.com/channels/655572317891461132/708431657849585705/1258150877714452581)\n\n## Proposal\n\n### Declarations\n\nA given entity may have up to three declarations:\n\n-   An optional, non-owning `extern library \"<owning_library>\"` declaration\n    -   It must be in a separate library from the definition.\n    -   The owning library's API file must import the `extern` declaration, and\n        must also contain a declaration.\n-   An optional, owning forward declaration\n    -   This must come before the definition. The API file is considered to be\n        before the implementation file.\n-   A required, owning definition\n\nThe consequential changes to the [problem example](#problem) are then:\n\n```\nlibrary \"a\";\n\n// This proposal makes the import required.\nimport library \"b\";\n\n// This proposal makes `extern` required here.\nextern class C {}\n```\n\n```\nlibrary \"b\";\n// This proposal makes `library \"a\"` required here.\nextern library \"a\" class C;\nextern fn F() -> C*;\n```\n\n```\nlibrary \"c\";\nimport library \"a\";\nextern fn F() -> C*;\n```\n\n### Owning `extern` declarations\n\nOn an owning `extern` declaration, such as `extern class C {}`, there are two\nkey effects:\n\n1.  The declaration must be explicitly imported in order to be complete.\n    -   An \"explicit import\" means some import path exists where the name is\n        available to name lookup, including `export import` and `export <name>`.\n2.  A non-owning `extern library \"<owning_library\">` declaration is allowed, but\n    not required.\n\nIf _either_ owning declaration has the `extern` modifier, _both_ must have it.\n\n## Details\n\n### Type coherency\n\nIn the context of the example that is the [problem](#problem), `C` will produce\nthe same type regardless of whether `C` is the owning or non-owning declaration.\nThis means that both function signatures have identical types.\n\nWe do this by only producing a complete type if the owning definition of `C` is\nimported by name: either directly through `import library \"a\"`, or indirectly\nthrough a chain of `export import library \"a\"` and `export C;`. Otherwise, an\nincomplete type is used.\n\nThis does mean that adding `extern` to an owning declaration changes the import\nsemantic. As a consequence, it is a potentially breaking change for API\nconsumers that didn't explicitly import the time.\n\nIn the presence of `extern library \"a\" class C;`, the required\n`import library \"b\"` means that all owning `extern class C` declarations are\nable to see the `extern library \"a\" class C` declaration as a name collision,\nwhich is merged. This allows the compiler to easily apply the same type to all\ndeclarations. That in turn will be used to ensure libraries which import both\nunderstand the type equality.\n\n#### Impact on indirect imports\n\nAn entity marked as `extern` is only complete when the definition is explicitly\nimported. In the following, examples of indirect, non-explicit uses are given\ninside `library \"o\"`.\n\n```\nlibrary \"m\";\n\nextern class C { fn Member(); }\n```\n\n```\nlibrary \"n\";\nimport library \"m\";\n\nfn F() -> C;\nvar c: C = {};\nvar pc: C* = &c;\n```\n\n```\nlibrary \"o\";\nimport library \"n\";\n\n// Invalid: The return type of `C` is incomplete, making the function signature\n// invalid.\nfn G() { F(); }\n\n// Invalid: Accessing members requires `C` to be complete.\nfn UseC() { c.Member(); }\n\n// Valid: Taking the address of `C` doesn't require it to be complete. This is\n// possible because `&` doesn't have an extension point.\nvar indirect_pc: auto = &c;\n\n// Invalid: Copying `C` requires the complete type.\nvar copy_c: auto = c;\n\n// Valid: Pointer-to-pointer copies are okay.\nvar copy_pc: auto = pc;\n```\n\n#### Indirect imports of non-`extern` types\n\nThe above rules explicitly do not apply for non-`extern` types, as decided in\n[Issue #4025](https://github.com/carbon-language/carbon-lang/issues/4025). In\nother words:\n\n```\nlibrary \"a\";\n\nclass C { fn F(); }\n```\n\n```\nlibrary \"b\";\nimport library \"a\";\n\nfn G() -> C;\n```\n\n```\nlibrary \"c\";\nimport library \"b\";\n\n// Valid: `C` is complete here, even though it's not in name lookup.\nG().F();\n```\n\n### Using imported declarations\n\nSince `extern library \"a\" class C;` must be imported by the owning library, we\nnow allow uses of the imported name prior to its declaration within the same\nfile. This is a divergence from\n[#3762](https://github.com/carbon-language/carbon-lang/pull/3762). It means the\nfollowing now works:\n\n```\nlibrary \"extern\";\n\nextern library \"use_extern\" class MyType;\n```\n\n```\nlibrary \"use_extern\";\nimport library \"extern\"\n\n// Uses the `extern library` declaration.\nfn Foo(val: MyType*);\n\nextern class MyType {\n  fn Bar[addr self: Self*]() { Foo(self); }\n}\n```\n\n### `private extern`\n\nPreviously, in\n[#3762](https://github.com/carbon-language/carbon-lang/pull/3762), a non-owning\n`private extern` was valid to declare something as extern without exposing the\nname. In this proposal, that would be a non-owning\n`private extern library \"<owning_library>\"` for an owning public `extern`\ndeclaration. However, rather than supporting this version of the syntax, it will\ninstead be invalid because the name would never be visible to the owning\nlibrary. Instead, visibility must match between an\n`extern library \"<owning_library>\"` declaration and the owning `extern`\ndeclaration.\n\nNote, because an owning `extern` declaration can be used independently of\n`extern library \"<owning_library>\"`, an owning `private extern` declaration is\nvalid in an API file. It has no special behaviors about it, and is merged as\nnormal.\n\n### Validation for non-owning `extern library` declarations\n\nWe should offer some validation that the library in `extern library` is correct.\nWhen the owning library is incorrect, it's very likely to be detected in two\ncases:\n\n-   A compile-time error when the owning library imports the non-owning library,\n    when the owning declaration is evaluated.\n-   A link-time error as a fallback.\n\nOther cases, such as when both libraries are independently imported, may or may\nnot be caught, dependent upon the cost of validation.\n\n### No syntactic matching for `extern library` declarations\n\nThe non-owned `extern library` declarations will only use semantic matching for\nredeclarations, not syntactic matching. Details of syntactic matching laid out\nin [#3763](https://github.com/carbon-language/carbon-lang/pull/3763) will only\napply to owned declarations in the same library, which may include owned\n`extern` declarations.\n\n### Versus proposal #3762\n\nVersus proposal\n[#3762](https://github.com/carbon-language/carbon-lang/pull/3762), the `extern`\nfeature is essentially rewritten. No part of `extern` should be assumed to still\napply.\n\n## Rationale\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Unifying the type of `extern` entities addresses a type coherency issue.\n    -   The `extern` behavior of requiring an explicit import is intended to\n        assist library authors in carefully managing the dependencies on their\n        API.\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n    -   Requiring the non-owning `extern library` declaration be imported by the\n        owning library should improve compiler performance.\n\nThis proposal makes a trade-off with\n[Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\nThe restriction of a unique `extern` declaration is expected to require\nadditional work in migration, because C++ `extern` declarations will need to be\nconsolidated. This is currently counter-balanced by the trade-offs involved,\nalthough it may result in a reevaluation of that aspect of this proposal.\n\n## Future work\n\n### `extern` and template interactions\n\nWe've only loosely discussed template interactions with `extern`. Right now,\nwhat we expect is that when a template declaration uses an `extern` type, the\n_instantiation_ still occurs in the calling file. Thus, the `extern` type's name\nwould need to be imported in both the file declaring the template, and the file\ncalling the template.\n\nWhen the template is in the same package as the `extern` type, it could\nre-export it. However, we don't support re-exporting names cross-package, and\nsomething like `let template ExternType:! auto = OwningPackage.ExternType;`\nwould not actually forward the _completeness_ of `ExternType`.\n\nThis is expected to be inconvenient, but it may be okay if `extern` sees limited\nuse. It may also be that the template model ends up different from expected.\n\n## Alternatives considered\n\n### Allow multiple non-owning declarations, remove the import requirement, or both\n\nWe limit to one non-owning `extern library` declaration. Continuing to allow\nmultiple `extern library` declarations (the previous state) is feasible.\nSimilarly, we could not require the owning `extern` declaration to import the\nnon-owning `extern library` declaration; this could be done with or without\nmultiple non-owning `extern library` declarations. For this set of alternatives,\nthe issues which would arise are similar.\n\nIn the compiler, we want to be able to determine that two types are equal\nthrough a unique identifier, such as a 32-bit integer. When one declaration sees\nanother directly, as through an import, we identify the redeclaration by name,\nand reuse the unique identifier. This deduplication can occur once per\ndeclaration. Indirect imports can continue to use the unique identifier.\n\nWe could instead support unifying declarations that did not see each other.\nHowever, this would require canonicalizing all types by name instead of by\nunique identifier. For example, consider:\n\n```\npackage Other library \"type\";\nextern class MyType {\n  fn Print();\n};\n```\n\n```\npackage Other library \"use_type\";\nimport library \"type\";\nfn Make() -> MyType*;\n```\n\n```\npackage Other library \"extern\";\nextern library \"type\" class MyType;\n```\n\n```\npackage Other library \"use_extern\";\nimport library \"extern\";\nfn Print(val: MyType*);\n```\n\n```\nlibrary \"merge\";\nimport Other library \"use_type\";\nimport Other library \"use_extern\";\nOther.Print(Other.Make());\n```\n\nHere, the \"merge\" library doesn't see either declaration of `MyType` directly.\nHowever, `Print(Make())` requires that both declarations of `MyType` be\ndetermined as equivalent. This particular indirect use also means that the names\nwill not have been added to name lookup, so there is no reason for the two\ndeclarations to be associated by name.\n\nIn order to do merge these declarations, we would need to identify that fully\nqualified names and other structural details are equivalent when the type is\nused (including non-explicit uses, such as interface lookup). We could achieve\nthis, for example, by having a name lookup table for in-use types, managed per\nlibrary. Each library would also need to validate that declarations were\nsemantically equivalent, versus the current approach validating as part of the\nredeclaration. The cost of a per-library approach is expected to have a\nsignificant impact on the amount of work done as part of semantic analysis.\n\nWe may end up wanting to do similar work in order to improve diagnostics for\ninvalid cases where the non-owning `extern library` is not correctly declared\nand imported. However, additional work building good diagnostics for\nalready-identified invalid code is less of a concern than additional work on\nfully valid code.\n\nIn order to maintain a high-performance compiler, we are taking a restrictive\napproach that makes it simpler to associate type information.\n\n### Total number of allowed declarations (owning and non-owning)\n\nA few options were considered regarding the number of allowed declarations.\n\nWe limit to two owning declarations: the optional forward declaration, and\nrequired definition. The need to provide interface implementations (for example,\n`impl MyType as Add`) is considered to constrain this choice.\n\nIn this category, alternatives considered were:\n\n-   Do not restrict the number of declarations\n-   Allow up to two declarations total\n-   Allow up to four declarations total\n\nDetails for why each alternative was declined are below.\n\n#### Do not restrict the number of forward declarations\n\nWe could not restrict the number of forward declarations, allowing an arbitrary\namount -- possibly also after the definition. This would be consistent with C++.\n\nOne thing to consider here is modifier keyword behavior. If we require modifier\nkeywords to match across all declarations, that could become a maintenance\nburden for developers. If we don't, it makes the meaning of a given forward\ndeclaration more ambiguous.\n\nThis option is declined due to the lack of clear benefit.\n\n#### Allow up to two declarations total\n\nUnder this option, we would only allow one forward declaration, treating the\nnon-owning `extern library` declaration as a forward declaration. This would\nmean two declarations overall, instead of three.\n\nFor this, the main concern was interactions between file placement of the\ndefinition, and file placement of interface implementations. Interface\nimplementations must generally be in API files in order to be seen by other\nlibraries.\n\nFor example:\n\n```\nlibrary \"i\";\ninterface I {}\n```\n\n```\nlibrary \"e\";\nimport library \"i\";\nextern library \"o\" class C;\nextern library \"o\" impl C as I;\n```\n\n```\nlibrary \"o\";\nimport library \"e\";\nextern class C { }\nextern impl C as I;\n```\n\n```\nimpl library \"o\";\nextern impl C as I { }\n```\n\nIf the definition is required to be in the API file in order to allow the\ninterface implementations in the API file, the API file would need to import\nlibraries required to construct the definition. That could create issues for\nseparation of build dependencies, and could also make it more difficult to\nunravel some dependency cycles between libraries.\n\nIf the definition was allowed to be in the implementation file even when there\nwere interface implementations in the API file, the ambiguity of seeing a\nnon-owning `extern library` declaration and being unsure of whether this was the\nowning library could have negative consequences for evaluation of interface\nconstraints.\n\nThe purpose of allowing a forward declaration when there is a non-owning\n`extern` declaration is to make it clear for interface implementations that they\nexist in the owning library, while processing the API file.\n\n#### Allow up to four declarations total\n\nThe four declarations would be:\n\n1.  Non-owning `extern library` declaration\n2.  Forward declaration in API file\n3.  Forward declaration in implementation file\n4.  Definition\n\nThe number of forward declarations allowed is consistent with the current state\nfrom [#3762](https://github.com/carbon-language/carbon-lang/pull/3762).\n\nThis would allow for clarity when defining in the implementation file, to also\nbe able to put a forward declaration above -- even when the forward declaration\nis pulled from the API file.\n\nIf we're allowing declarations from another file (including the non-owning\n`extern library` declaration) to be used before an entity is declared in the\nsame file, the motivating factor for allowing a repeat forward declaration in an\nimplementation file is removed. Previously, that was required for an entity to\nbe referenced prior to its definition.\n\nIn discussion of this option, it was considered unclear why we would allow two\nforward declarations, but not allow even more. The more popular choice seemed to\nbe not restricting, which was also declined.\n\n### Don't require a modifier on the owning declarations\n\nInstead of requiring an `extern` modifier on owning declarations, we could infer\nfrom the presence of a non-owning `extern library` declaration.\n\nWe had declined allowing a definition to control whether `extern library` was\nallowed in discussion of\n[#3762](https://github.com/carbon-language/carbon-lang/pull/3762), although this\nis not directly mentioned in the proposal. At the time, it was dropped because\nthe owning library didn't need to include `extern` declarations, and so having\nthe definition opt-in to allowing `extern` was viewed as low benefit. However,\nnow that the owning library must import the `extern` declaration, there is a\ntighter association and so we reevaluated.\n\nThe `extern` modifier offers a benefit for being able to verify the association\nbetween non-owning and owning declarations, and offers additional parity in\nmodifiers. It also makes it easy for a tool to know if it's missing a\ndeclaration.\n\n### Only require `extern` on the first owning declaration\n\nAt present, we require `extern` on _all_ owning declarations. We could instead\nonly require `extern` on the first owning declaration and, if there's a separate\nforward declaration and definition, infer it for the definition. For example:\n\n```\n// `extern` on the forward declaration.\nextern class C;\n// Infer `extern` for the definition.\nclass C {}\n```\n\nThe decision to require `extern` on all owning declarations is based on wanting\nthe forward declaration to be optional. A rule of thumb was discussed wherein if\na forward declaration could be removed without breaking the definition (as\ndefined by it being in the same lexical scope), keywords should be duplicated to\nthe definition. This is not proposed as a rule because it's not clear whether\nwe'll generally follow it, but it's why this particular choice is taken.\n\n### Separate require-direct-import from non-owning declarations\n\nAt present, an `extern` modifier on an owning declaration serves two purposes:\n\n1.  Indicates that a non-owning `extern library` declaration _can_ exist.\n2.  Indicates the declaration must be directly imported in order to be complete.\n\nThis means that:\n\n-   The presence of `extern` on an owning declaration cannot be used to\n    determine whether a non-owning declaration exists.\n    -   Because the location of a non-owning declaration isn't explicit in the\n        owning code, this may lead to a developer failing to find the non-owning\n        declaration and misunderstanding that as the non-existence of a\n        non-owning declaration.\n-   Libraries which happen to be imported by the owning declaration may freely\n    add or remove non-owning `extern library` declarations without modifying the\n    owning library.\n\nWe could give distinct syntax to the two purposes, so that they could be managed\nseparately. The preference at present is to use a single syntax for both\npurposes, rather than emphasizing control or correspondence.\n\n### Other `extern` syntaxes\n\n[Issue #3986](https://github.com/carbon-language/carbon-lang/issues/3986)\ndiscussed other syntaxes for `extern` + `extern library`. These were mainly\n`has_extern`/`is_extern`/`externed` + `extern`.\n\nBreaking down `extern`, there are two features which could have been provided\nseparately:\n\n1.  Declaring an entity has a forward declaration in a separate library.\n    -   Also, declaring that forward declaration in a separate library:\n        `extern library \"<owning_library>\"`.\n2.  Declaring an entity must be imported directly.\n\nAlthough (1) must depend on (2), a different design could provide (2) without\nmaking (1) possible, for example with different keywords to differentiate\nbetween intended usage (`has_extern class C;` meaning (1) and (2), `must_import`\nmeaning (2) only). However, the `extern` keyword approach means developers have\nall or nothing.\n\nConsidering that, the trade-offs are viewed as:\n\n-   The primary motivation is to provide feature (1).\n-   Leads wanted a syntax on the owning declaration that states something\n    positive about the owning declaration itself, rather than expressing that\n    other declarations exist, which suggests that the syntax on the owning\n    declaration should provide feature (2).\n-   Leads consider it valuable, though secondary, to support (2) separate from\n    (1), and find it acceptable to make (1) optional to achieve this (in other\n    words, making the `extern library \"<owning_library>\"` declaration optional).\n    -   It's okay that that `extern library \"<owning_library>\"` can be added and\n        removed from imported libraries without modifying the owning library.\n    -   If a developer considers it important to disambiguate the intended use\n        of a declaration `extern class C;` and whether there should be a\n        declaration in a separate library, they can add comments.\n-   `extern` seemed like an acceptable name for this approach, and alternative\n    names seemed significantly less good.\n-   Using `extern` for both features still only creates one new keyword, versus\n    multi-keyword approaches.\n-   Adding the owning library with `extern library \"<owning_library>\"` will\n    hopefully improve diagnostics and human understandability of the code.\n    -   It is _very_ verbose, but this verbosity goes on the forward declaration\n        in the non-owning library. When it's read, which will hopefully be less\n        often than the actual declaration, it will provide the reader directions\n        to find the actual declaration.\n    -   If in practice we find the verbosity becomes a significant issue, we can\n        revisit syntaxes to address that specifically. For example, if we have\n        significant repetiton, we might consider a grouping structure such as\n        `extern library \"...\" { <many forward declarations> }`.\n\n### Have types with `extern` members re-export them\n\nWe expect there will be types that have `extern` members; these types are only\ntruly complete if their members are complete.\n\nWe discussed having such types automatically re-export the `extern` members,\npossibly requiring the types to also be `extern` in order to be allowed to have\n`extern` members. For example:\n\n```\nlibrary \"a\"\nextern library \"b\" class A;\n```\n\n```\nlibrary \"b\"\nimport library \"a\"\nextern class A {}\n// B re-exports A so that it's complete on use.\nclass B { var a: A; }\n```\n\n```\nlibrary \"c\"\nimport library \"b\"\n// Importing this function declaration gets B, which again, re-exports A so that\n// it's complete on use.\nfn F() -> B { ... }\n```\n\n```\nlibrary \"d\"\n// This import loads the incomplete name for A.\nimport library \"a\"\n// This import loads F, which loads B, which loads the definition of A.\nimport library \"c\"\n\n// Because of the import behaviors, this is valid.\nvar a: A;\n```\n\nWe consider this action-at-a-distance. Type coherency means the `A` member of\n`B` is the same as the `A` in name lookup; we could make them behave slightly\ndifferently, but then we get into provenance tracking of type information.\nSeveral various forms of this have been discussed as part of the `extern`\ndesign, and it's something we've decided to avoid.\n\nAlthough it's more inconvenient, we will require `A` to be deliberately imported\nin order for `B` to be complete.\n\n### Require syntactic matching for `extern library` declarations\n\nWe will not require syntactic matching for `extern library` declarations, but we\ncould.\n\nWhen a redeclaration is in the same library, we've designed name lookup in a way\nsuch that syntactic matching is effectively a superset of semantic matching.\nHowever, that relies on poisoning entries in name lookup, with later\nredeclarations seeing identical name lookup data. Because different libraries\nhave different name lookup data, syntactic matching _not_ a superset of semantic\nmatching cross-library. We address this schism by only requiring semantic\nmatching.\n\nSemantic matching will include parameter names. The difference is primarily in\nwhether different ways of producing the same type information are considered\ninvalid or not.\n\nFor example:\n\n```\nlibrary \"a\";\n\nclass A {}\nnamespace NS;\nextern library \"c\" fn NS.F() -> A;\n```\n\n```\nlibrary \"b\";\n\nnamespace NS;\nclass A {}\n```\n\n```\nlibrary \"c\"; import library \"a\" import library \"b\"\n\nextern fn NS.F() -> NS.A {}\n```\n\nSemantically, `NS.F` in libraries \"a\" and \"c\" are identical. Syntactically, they\ndiffer because of `NS.A` in \"c\". Writing `A` in \"c\" is invalid because it would\nuse `NS.A` from \"b\". But in \"a\", there is nothing to make the declaration\ninvalid: it would only be invalid after completing cross-library compilation.\n\nHowever, we could also have code such as:\n\n```\nlibrary \"d\";\n\nclass D {}\nnamespace NS;\nextern library \"e\" fn NS.G() -> D;\n```\n\n```\nlibrary \"e\";\n\nnamespace NS;\nalias NS.D = D;\nextern fn NS.G() -> D {}\n```\n\nHere, the semantics and syntax match, but this would be invalid in a normal\nredeclaration due to the different name lookup result for `D`.\n\nThis additionally gets into a different statement made in\n[#3763](https://github.com/carbon-language/carbon-lang/pull/3763) to justify\nsynactic matching: \"The intention is that whenever the syntax matches, the\nsemantics must also match.\" Due to the differences in name lookup, syntax\nmatching does not mean semantics must match; instead of `alias NS.D = D;`, that\ncould have been `alias NS.D = i32;` and the syntax would have still matched.\nThis only works in a library because \"...we persist syntactic information from\nthe API file to implementation files.\" We cannot persist syntactic information\ncross-library, across imports.\n\nDue to the differences in the guarantees that syntactic matching provides for\nowned declarations versus non-owned declarations, we will not enforced syntactic\nmatching on the non-owned `extern library` declarations.\n"
  },
  {
    "path": "proposals/p4075.md",
    "content": "# Change operator precedence\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/4075)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [`as` and `where` could be peers of `if`...`then`...`else`](#as-and-where-could-be-peers-of-ifthenelse)\n    -   [Make `T as I where R` mean `T as (I where R)`](#make-t-as-i-where-r-mean-t-as-i-where-r)\n    -   [Make fewer changes](#make-fewer-changes)\n    -   [Different `where` syntax](#different-where-syntax)\n\n<!-- tocstop -->\n\n## Abstract\n\nUpdate the operator precedence to achieve a few goals:\n\n-   Form operators into groups which behave similarly\n-   Make the group of operators (\"top-level operators\") that capture everything\n    to the right, like `if`...`then`...`else`, behave similarly to the left, so\n    that rearranging expressions won't change how they group.\n-   Add the `where` operator, used to specify constraints on facet types, to the\n    precedence chart, to define how it interacts with other operators.\n-   Make the operator precedence diagram prettier, so that it eventually can be\n    made into a poster that Carbon programmers can hang on their walls.\n\n## Problem\n\nThe `where` operator is particularly tricky:\n\n-   It is used in an `impl` declaration to specify the values of associated\n    constants (such as associated types). In that context, `impl T as I where R`\n    is interpreted conceptually as `impl T as (I where R)`. It would be nice if\n    `T as I where R` would mean the same thing in other contexts. If not, we'd\n    rather it to be invalid rather than meaning `(T as I) where R`. That is,\n    That is, considered in isolation, we would prefer `T as (I where R)` over\n    invalid over `(T as I) where R`.\n-   The `where` operator will frequently be used with the binary `&` operator,\n    since that is how facet types are combined. It is desirable that\n    `I & J where R` be interpreted as `(I & J) where R`. If not, we'd rather it\n    be invalid than be interpreted as `I & (J where R)`. This usage of `&` with\n    `where` is expected to be more common than combining `where` and `as`\n    outside of an `impl` declaration.\n-   The \"restriction\" on the right side of a `where` uses operators that mean\n    something else in an expression context: `and`, `==`, `=`. We would like to\n    minimize the confusion when both kinds of uses of those operators appear in\n    the same expression.\n\nThese goals are in conflict with the current precedence partial order.\n\n## Background\n\nThe initial operator precedence approach, including using a partial precedence\nordering instead of a total ordering as found in most languages, was established\nby [propsoal #555](https://github.com/carbon-language/carbon-lang/pull/555).\n[PR #1070](https://github.com/carbon-language/carbon-lang/pull/1070) established\nthe current precedence chart, which has been incrementally added to since then.\n\n## Proposal\n\nWe are making a number of changes:\n\n-   `x as T` is no longer allowed on either side of a comparison operator, or\n    the short-circuiting operators `and` & `or`.\n-   `x where R` is a peer to `as`, but its arguments can be binary operators\n    (like `&`). This matches the comparison operators, which are either illegal\n    or reinterpreted as an argument to `where`.\n-   The type constructors `T*` and `const T` are no longer separate from the\n    other unary operators, and can now be the argument of any binary operator.\n\n## Details\n\nPlease see the new precedence diagram in\n[docs/design/expressions/README.md](/docs/design/expressions/README.md).\n\n## Rationale\n\nPrecedence is about\n[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nWe don't want to require parentheses too often since that makes the code harder\nto write, and if it goes too far even reading becomes difficult. However, we do\nwant parentheses to mark code that would otherwise be misinterpreted. This is a\nbalancing act we expect to have to refine with experience.\n\n## Alternatives considered\n\n### `as` and `where` could be peers of `if`...`then`...`else`\n\nWe considered making all the \"top-level\" operators act the same for precedence,\nbut we expect users to want to use `as` to force the two branches of an\n`if`...`then`...`else` expression to a common type often enough, and we didn't\nexpect the result of doing that to be confusing to read.\n\n### Make `T as I where R` mean `T as (I where R)`\n\nWe wanted to make `T as I where R` mean the same facet type as that same\nsequence of tokens in an `impl` declaration. However, this was in conflict with\nthe arguments to `where` being the same as the arguments to comparison\noperators. We didn't want to allow an expression mixing binary operators with\n`as` since we expected users to expect that to mean performing the operation\nwith that casted-to type. For example, `x + y as i64` would mean\n`(x + y) as i64`, which would perform the addition and only then cast to `i64`,\nwhich is probably not what would be intended by that expression. We thought it\nbetter to make `x + y as i64` illegal to force users to use parentheses, even if\nthat meant also using parentheses with `T as I where R` in an expression\ncontext.\n\n### Make fewer changes\n\nWe considered making fewer changes to precedence, but that lead to an operator\nprecedence diagram with crossing edges (it was\n[non-planar](https://en.wikipedia.org/wiki/Planar_graph)). This was felt to be a\nsign that the graph was too complex, making it harder for humans to understand\nand remember. It was suggested that developers using Carbon may want to have the\nprecedence graph posted for reference, and a planar graph would make a\nmore-appealing poster.\n\nThis was\n[discussed in open discussion on 2024-06-20](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.p524bg7cnd32).\n\n### Different `where` syntax\n\nWe considered other ways of marking the end of a `where` restriction expression,\nsuch as requiring parens `(`...`)` (either around the argument or the whole\n`where` expression) or having a keyword at the end. We ultimately decided none\nof those options were satisfactory since they added noise that reduced clarity,\nand decided to go with a greedy approach (\"all the way to the right\") instead.\n\nThis was discussed in\n[open discussion on 2024-06-13](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.p46elxrmhh8x)\n"
  },
  {
    "path": "proposals/p4105.md",
    "content": "# Establish toolchain and language versioning\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/4105)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Directional sketch for the future](#directional-sketch-for-the-future)\n    -   [Language evolution and breaking changes](#language-evolution-and-breaking-changes)\n    -   [Long-Term Stable (LTS) versions and standardization](#long-term-stable-lts-versions-and-standardization)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Do nothing, or just talk about a minimal nightly version.](#do-nothing-or-just-talk-about-a-minimal-nightly-version)\n    -   [Make no breaking changes past 1.0.](#make-no-breaking-changes-past-10)\n    -   [Version different parts of the language separately.](#version-different-parts-of-the-language-separately)\n    -   [Use a custom versioning scheme rather than SemVer.](#use-a-custom-versioning-scheme-rather-than-semver)\n    -   [Include more pre-release variations](#include-more-pre-release-variations)\n\n<!-- tocstop -->\n\n## Abstract\n\nProposal for how Carbon version numbers work:\n\n-   A single version across language, standard library, compiler, linker, etc.\n-   Semantic Versioning (SemVer) based\n-   Details of how SemVer criteria for major, minor, and patch should apply to\n    Carbon\n-   Details of how we will operate before 1.0 and how this connects to Carbon's\n    milestones\n-   Directional guidance for future work including post-1.0 versions, LTS\n    versions, and standardization\n\n## Problem\n\nWe need a versioning scheme for Carbon both for the language and the reference\ntoolchain implementing that language. This is important even before we reach any\nspecific milestone, as we want to define the schema and implement it _before_ it\nbecomes useful for marking specific milestones.\n\n## Background\n\n-   [Semantic Versioning](https://semver.org/)\n-   [Rust Editions](https://doc.rust-lang.org/edition-guide/editions/)\n\n## Proposal\n\nFirst, Carbon should have a single versioning scheme across both the language\nitself and toolchain, including the standard library, compiler, linker, and all\ndevelopment tools released by the main Carbon project.\n\nSecond, the Carbon versioning scheme should conform to and be closely based on\nSemantic Versioning (SemVer), which is the de-facto standard for versioning\nschemes in software today. Beyond that, it needs to clarify how the standards\nlaid out in SemVer map into a programming language context as programming\nlanguages and standard libraries have an extraordinarily broad and tightly\ncoupled \"API\" to their users -- all of the source code written in the language.\nCarbon needs to provide extra clarity around what constitutes our \"public API\"\nfor SemVer purposes and the criteria for changes.\n\nThird, SemVer provides a schema for pre-release versions, but is largely\nopen-ended on their semantics. Carbon should have a specific set of well defined\npre-release versions with clearly communicated purpose, nature, and meaning to\navoid confusion.\n\nFourth, language versioning is an especially important area for the long-term\nevolution and so Carbon should have some directional guidance around the future\nwork expected in the versioning front. This should speak to specific use cases\nand needs that may be left seemingly unaddressed otherwise.\n\nSummarizing the proposed outcome of these together:\n\n-   Carbon versions: `MAJOR.MINOR.PATCH`\n-   `MAJOR` increments on backwards incompatible changes, including a\n    deprecation that might trigger a build-breaking warning.\n    -   Doesn't make it free to make such changes. Each change must pay for its\n        adoption and churn cost. But when a change is needed and well justified,\n        this signifies its introduction.\n    -   Used to establish our milestones for the language.\n    -   Some explicit carve-outs of things designated to not be in the \"public\n        API\" of the language.\n-   `MINOR` increments only expected during early development with a major\n    version of `0`.\n    -   If Carbon some day stabilizes sufficiently to motivate it, we may\n        revisit this and begin to use the minor version number to signal\n        backwards compatible releases.\n-   `PATCH` increments represent bug fixes only.\n    -   Goal is always fully backwards compatible.\n    -   When fixing the bug makes code written against the release with the bug\n        break, may be unavoidable as the intent was never the buggy behavior.\n        But this is rare and we hold a very high bar for such bug fixes due to\n        their disruptive nature.\n-   Pre-release suffixes:\n    -   `MAJOR.MINOR.PATCH-rc.N`: The N-th potentially viable candidate for a\n        release.\n    -   `MAJOR.MINOR.PATCH-0.nightly.YYYY.MM.DD`: A nightly incremental\n        development build on a particular day during development of that\n        version.\n    -   `MAJOR.MINOR.PATCH-0.dev`: An interactive, incremental development build\n        on a particular day by some developer during development of that\n        version.\n\n## Details\n\nSee the added [versioning document](/docs/project/versioning.md).\n\n## Directional sketch for the future\n\nThe mechanics outlined above provide a good basis for the initial versions of\nthe language (up to 1.0) and any necessary mechanics and tooling around those\nversions. However, beyond 1.0 we expect the needs of the language and project to\nexpand and more detailed versioning and evolution tools to become critical. We\nlay out directional sketches here for where Carbon should go in the future to\naddress these needs, but these are just directional guidance and will need their\nown carefully considered proposals when the time comes.\n\n### Language evolution and breaking changes\n\nWe don't expect a simple version number to be sufficient long-term for the\nevolution needs of the Carbon language. We should plan to at least map these\nmajor versions into Rust-edition-like controls within source code itself to\nallow incremental adoption across a codebase of fixes for breaking changes or\nadoption of new language features with a single toolchain version. That is, some\ncode will want to compile using previous major version semantics even with the\nnew compiler.\n\nThe approach taken in Rust and proposed for C++ to address this are \"editions\"\nthat source code opts into in order to allow the compiler to support a mixture\nof code in a codebase during incremental adoption. Carbon will need at least\nsomething equivalent to this, and may want to explore a more fine-grained system\nof opting into specific functionality sets similar to how pragma-based extension\nusage or Circle works.\n\nRegardless of the specifics, a key is that breaking changes are not forcibly\ncoupled in their roll-out to updates to the Carbon toolchain. Each step needs to\nbe incrementally tackled.\n\n### Long-Term Stable (LTS) versions and standardization\n\nSemVer alone isn't sufficient to address some user needs for language stability.\nIt is enough to _detect_ the issues when they arise, but Carbon should also plan\nfor how to _address_ these issues.\n\nThe suggested direction here is towards designated LTS versions based on a\nparticular level of completeness and quality and the user demand. These versions\nwill likely need even longer time horizons of support than Linux distro LTS\nreleases. The direction should be to embrace this and the potential for\nmulti-decade support windows to support users' needs. As the windows of LTSes\nexpand, their frequency should reduce to avoid supporting an unsustainable\ndiversity of versions.\n\nExactly how a version is designated as LTS is left to the future work here, but\nit should not be expected to change the schema and structure of the versioning,\njust the support policy applied to the specific release version in question.\n\nSome users may even require standardization of a programming language to make it\nusable in their environment. Carbon should again embrace this need and see the\nstandardization as an analogous process to promoting a normal release into an\nLTS. Some relevant and effective LTS should be selected and taken through\nwhatever process is identified to create a standard reflecting that LTS version\nof Carbon. Updates to the standard should in turn track as updates to a newer\nLTS. The specifics of how to do this are left to the future work, and they may\nchange exactly how this works.\n\nNote that the goal of this future direction isn't to constrain how Carbon can\narrive effectively at either an LTS release or a standard. Instead, the goal is\nto make it clear that we _should_ be open and planning to achieve these in order\nto meet the needs of candidate Carbon users.\n\n## Rationale\n\n-   [Language tools and ecosystem](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#language-tools-and-ecosystem)\n    -   Carbon needs a coherent versioning scheme across the language itself as\n        well as its ecosystem. Especially as the language is developing rapidly,\n        being able to sync across all of these with a single, simple versioning\n        scheme is especially important to have the tooling and ecosystem agree\n        about features of the language.\n-   [Software and language evolution](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#software-and-language-evolution)\n    -   Users of Carbon need a clear model for understanding the language's\n        evolution, tracking it, and responding to significant aspects of it.\n    -   The versioning scheme needs to support a wide variety of versions built\n        in the process of evolving the language without creating confusion.\n\n## Alternatives considered\n\n### Do nothing, or just talk about a minimal nightly version.\n\nAdvantages:\n\n-   Carbon is at a very early stage and is a long way from needing release\n    candidates for stable releases or incrementing its major version numbers.\n-   No need to imagine distant future scenarios.\n\nDisadvantages:\n\n-   We already discuss version numbers in various places in the Carbon project,\n    including our [milestones](/docs/project/milestones.md) and\n    [roadmap](/docs/project/roadmap.md).\n-   Establishing how the Carbon project will communicate its updates with\n    version number changes in advance of those updates makes that communication\n    more effective.\n-   Lets us telegraph our intentions and how we are thinking about releasing and\n    cadence to the community and get earlier feedback.\n\nA key to adopting the more detailed versioning plan is that we can change any\nand all of this if and when we need to. This does not lock Carbon into using\nthis exact versioning scheme. We will listen to any feedback from potential\nusers and can adapt our approach if needed.\n\n### Make no breaking changes past 1.0.\n\nAdvantages:\n\n-   Stable languages have the lowest churn costs for users, and are easier to\n    learn at scale.\n\nDisadvantages:\n\n-   This would be in direct opposition to our language goal of supporting\n    software and language evolution.\n    -   This relieves pressure on adding things to the language by avoiding an\n        unreasonably high bar. The pressure is still large due to the very real\n        churn costs, but we avoid amplifying that further with an absolute\n        restriction on fixing issues.\n    -   We expect Carbon to be a reasonably complex language in order to succeed\n        at its goals, ranging from C++ interop to incremental memory safety.\n        This complexity inherently comes with an increased risk and importance\n        of being able to improve and fix issues.\n\n### Version different parts of the language separately.\n\nAdvantages:\n\n-   There will be eventually be many differences between changes to the\n    toolchain and changes to the language itself. We might be able to capitalize\n    on those to have a better cadence or versioning scheme for these\n    independently.\n\nDisadvantages:\n\n-   We would have to carefully define and maintain a compatibility matrix\n    between the different components. Increasingly in modern languages and\n    development, the compiler, language, standard library, and tooling are all\n    deeply interdependent.\n-   Experience rolling out major updates to Clang and GCC in large codebases and\n    software ecosystems show even compiler-only or toolchain-only changes easily\n    become as disruptive as smaller updates to the C++ language itself have been\n    over the years. As a consequence, while it is tempting to hope for a sharp\n    difference here we don't in practice anticipate one.\n\n### Use a custom versioning scheme rather than SemVer.\n\nAdvantages:\n\n-   We don't actually use all parts of SemVer, which results in awkward unused\n    component of our version number.\n-   SemVer doesn't actually provide an opinionated versioning scheme, merely a\n    relaxed schema that many versioning schemes can fit into.\n\nDisadvantages:\n\n-   Fitting into SemVer ends up needing only very cosmetic changes to a scheme\n    that is meaningful for Carbon. And we can easily specify the open-ended\n    parts of the scheme.\n-   Allows us to easily fit into scripts and people's understanding using SemVer\n    as a baseline model.\n-   Avoids confusion when people from outside the community first encounter\n    Carbon versions as their most likely intuition about the meaning of various\n    aspects of the number will be a reasonable starting point.\n\n### Include more pre-release variations\n\nInitially there was a discussion of potentially defining `alpha` and `beta`\npre-release versions along with release candidate versions, nightly, and\ndevelopment versions. The specific idea was to document versioning we could use\nfor longer-lived releases we want to make when not yet ready to call it a\nrelease candidate.\n\nAdvantages:\n\n-   If we end up wanting longer-lived releases prior to arriving at a numbered\n    milestone such as `0.1`, this would provide a ready-made solution.\n-   Specifically, communicating the option for this early might help others\n    avoid being confused by what exactly the state of such a pre-release would\n    be.\n\nDisadvantages:\n\n-   There's no real indication we would ever want to make such a release. It\n    seems easy to imagine the combination of nightly builds and pre-releases\n    completely covering all of the use cases we end up with in practice.\n-   Keeping the infrastructure and documentation for such improbable use cases\n    is drag and friction that doesn't buy us enough to be worthwhile.\n"
  },
  {
    "path": "proposals/p4246.md",
    "content": "# Getting commit access\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/4246)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Commit access](#commit-access)\n    -   [Related policies](#related-policies)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Longer idle times](#longer-idle-times)\n\n<!-- tocstop -->\n\n## Abstract\n\nEstablish a process for getting commit access. We will:\n\n-   Grant access based on a developer's commit history.\n    -   Someone with commit access should nominate, and a contributor may ask.\n    -   A lead will approve nominations. Only one lead is needed.\n-   Remove commit access once someone is idle for 6 months.\n    -   \"Idle\" means no significant project activity on any of GitHub, Discord,\n        or in meetings.\n    -   Access removed due to being idle will be restored on request.\n\n## Problem\n\nRight now, we have an undocumented process for getting commit access, and no\nreal agreement for when to remove it. Commit access is important, so rather than\njust making a documentation edit, I'm submitting this as a proposal.\n\n## Background\n\n### Commit access\n\nWhen we say \"commit access\", what we mean is the ability to push commits to the\nmain `carbon-lang` repository, regardless of branch. Some details about the\nimplications:\n\n-   Review and approvals would remain required for pushes to `trunk`.\n    -   This does grant access to push to other branches, although we will\n        continue to encourage fork-based workflows.\n-   Pushing PRs becomes easier with commit access.\n    -   Action workflows will automatically execute, instead of requiring a\n        per-commit approval by someone with commit access.\n    -   Modifying PRs after review approval is possible.\n        -   This is both good (for small updates such as fixing typos and\n            resolving conflicts) and bad (particularly for code security).\n    -   Communication delays can make it hard for an author to resolve conflicts\n        and reviewer to approve and merge before more conflicts are introduced.\n        -   A possible solution to the conflict problem is to have the reviewer\n            merge PRs more frequently, and regardless of any decision here, we\n            may eventually need to adopt that approach.\n-   Commit access functionally means the ability to approve and merge PRs from\n    others.\n    -   As alternatives, we could use either a separate GitHub team for\n        approvals or\n        [CODEOWNERS](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners).\n        We have avoided these so far because we're small, having backup\n        approvers can be helpful, and mistakes are easy to undo.\n-   This does not include the ability to push to other repositories. While there\n    are a few in the `carbon-language` organization, only the `carbon-lang`\n    repository is actively used.\n-   People with commit access in effect have access to secrets, can make\n    releases, and so on.\n\n### Related policies\n\nThis proposal does not supersede other project policies, in particular:\n\n-   [CLA](/CONTRIBUTING.md#contributor-license-agreements-clas)\n-   [Code of Conduct](/CODE_OF_CONDUCT.md)\n-   [Review process](/docs/project/code_review.md)\n\n## Proposal\n\nThe key things I think should be covered in this proposal are:\n\n-   Whether we want to require a lead to approve commit access additions.\n-   We're choosing to do a 6 month inactive period for removal.\n\nThings I think we should be okay iterating on without going through evolution\ninclude:\n\n-   Exactly how we define non-idle activity beyond merging and approving PRs,\n    both of which mechanically require this access.\n-   The detailed process for additions, including nominating.\n    -   We want a good starting point, but it may not be worth sending all\n        changes through the proposal process.\n-   The detailed process for removals, such as whether leads are approving\n    removals.\n    -   This is something it's been suggested to fully automate, preventing\n        review of removals.\n\nSee the new [Commit access](/docs/project/commit_access.md) document for\ndetails.\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   Establishing the processes around commit access, and making sure they're\n        reasonable, is important to maintaining the community.\n\n## Alternatives considered\n\n### Longer idle times\n\nWe discussed using a longer idle time, like 1, 2, or 3 years. We're leaning\ntowards the shorter 6 month period because of concerns about forgotten access\ncausing issues. We're hoping 6 months is a minimum of inconvenience, and want it\nto be easy to get access back on request.\n"
  },
  {
    "path": "proposals/p4682.md",
    "content": "# The Core.Array type for direct-storage immutably-sized buffers\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/4682)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Rust](#rust)\n    -   [Swift](#swift)\n    -   [Safe C++](#safe-c)\n    -   [Goals](#goals)\n        -   [Privileging the most common type names](#privileging-the-most-common-type-names)\n        -   [Absence of syntax should make clear defaults](#absence-of-syntax-should-make-clear-defaults)\n        -   [Avoiding confusion with other languages](#avoiding-confusion-with-other-languages)\n        -   [Avoiding confusion with other domains](#avoiding-confusion-with-other-domains)\n    -   [No predeclared identifiers](#no-predeclared-identifiers)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Future work](#future-work)\n    -   [Namespacing the `Core` package](#namespacing-the-core-package)\n-   [Alternatives considered](#alternatives-considered)\n    -   [`[T; N]` builtin syntax](#t-n-builtin-syntax)\n    -   [`array [T; N]` builtin syntax](#array-t-n-builtin-syntax)\n    -   [Just the `Core.Array(T, N)` library type](#just-the-corearrayt-n-library-type)\n    -   [Implicitly importing `Core.Array(T, N)` to the file scope](#implicitly-importing-corearrayt-n-to-the-file-scope)\n\n<!-- tocstop -->\n\n## Abstract\n\nWe propose to add `Core.Array(T, N)` as a library type in the `prelude` library\nof the `Core` package. Since arrays are a very frequent type, we propose to\nprivilege use of this type by providing a builtin keyword `array(T, N)` that\nresolves to the `Core.Array(T, N)` type.\n\n## Problem\n\nCarbon's current syntax for a fixed-size, direct storage array (hereafter called\n\"array\") is the provisional `[T; N]` and there is no syntax yet for a\nmutably-sized indirect storage buffer (hereafter called \"heap-buffer\").\n\nArrays and heap-buffers are some of the most commonly used types, after\nfundamental types. The syntax, whatever it is, will be incredibly frequent in\nCarbon source code.\n\nWe explore and propose a new syntax for arrays that addresses design issues with\nthe provisional syntax that allows for writing each of the following in clear\nways: slice, compile-time sized slice, array, and pointer to array. And that\nleaves clear room for a sibling indirect-storage type.\n\n## Background\n\nWe have developed a matrix for enumerating and describing the vocabulary of\nowning array and buffer types. Direct refers to an in-place storage buffer, as\nwith arrays. Indirect refers to heap allocation, where the type itself holds\nstorage of a pointer to the buffer, as with heap-buffers.\n\nHere we are discussing the location of storage (direct vs indirect) as a way to\ncategorize types. Indirect-storage types may, for small payloads, store state\ndirectly in its fields (such as with the Small String Optimization), but this is\nan optimization for specific payloads and the category of the type remains an\nindirect-storage type.\n\nTo provide familiarity, here is the table for the C++ language as a baseline:\n\n| Owning type              | Runtime Sized          | Compile-time Sized          |\n| ------------------------ | ---------------------- | --------------------------- |\n| Direct, Immutable Size   | -                      | `T[N]` / `std::array<T, N>` |\n| Indirect, Immutable Size | `std::unique_ptr<T[]>` | `std::unique_ptr<T[N]>`     |\n| Indirect, Mutable Size   | `std::vector<T>`       | -                           |\n\n### Rust\n\nThe Rust vocabulary is as follows:\n\n| Owning type              | Runtime Sized | Compile-time Sized |\n| ------------------------ | ------------- | ------------------ |\n| Direct, Immutable Size   | -             | `[T; N]`           |\n| Indirect, Immutable Size | `Box<[T]>`    | `Box<[T; N]>`      |\n| Indirect, Mutable Size   | `Vec<T>`      | -                  |\n\nThere are a few things of note when comparing to C++:\n\n-   The Rust `Box` and `Vec` types are part of `std` but are imported into the\n    current scope automatically, so they do not need any prefix.\n-   The `[T]` type represents a fixed-runtime-size buffer. The type itself is\n    not instantiable since its size is not known at compile time. `Box` is\n    specialized for the type to store a runtime size in its own type.\n-   The array type syntax matches the Carbon provisional syntax.\n-   The heap-buffer type name matches the C++ `vector` type, but it is\n    privileged with a shorter name. The `Vec` type name is at most the same\n    length as an array type name (for the same `T`).\n\n### Swift\n\nThe Swift vocabulary is significantly smaller, to support automatic refcounting:\n\n| Owning type              | Runtime Sized      | Compile-time Sized |\n| ------------------------ | ------------------ | ------------------ |\n| Direct, Immutable Size   | `InlineArray<T>`   | -                  |\n| Indirect, Immutable Size | -                  | -                  |\n| Indirect, Mutable Size   | `Array<T>` / `[T]` | -                  |\n\nBecause there was historically no direct storage option, only one name was\nneeded, and \"Array\" was used to refer to a heap-buffer.\n\nOn\n[Feb 5 2025](https://forums.swift.org/t/accepted-with-modifications-se-0453-inlinearray-formerly-vector-a-fixed-size-array/77678),\na proposal was accepted to\n[introduce `InlineArray<T>` for the direct storage immutably sized array type](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md).\nBecause \"Array\" is already taken, the original proposal called this new type\n\"Vector\" in reference to mathematical vectors. The choice of name was\n[heavily discussed](https://forums.swift.org/t/second-review-se-0453-vector-a-fixed-size-array/76412)\nhowever, due to the confusion with C++'s `std::vector` and Rust's\n`std::vec::Vec`. It was\n[provisionally renamed to `Slab`](https://github.com/swiftlang/swift/pull/76438)\nbut settled on `InlineArray`.\n\n### Safe C++\n\nThe [Safe C++ proposal](https://safecpp.org/draft.html#tuples-arrays-and-slices)\nintroduces array syntax very similar to Rust:\n\n| Owning type              | Runtime Sized         | Compile-time Sized  |\n| ------------------------ | --------------------- | ------------------- |\n| Direct, Immutable Size   | -                     | `[T; N]`            |\n| Indirect, Immutable Size | `std2::box<[T; dyn]>` | `std2::box<[T; N]>` |\n| Indirect, Mutable Size   | `std2::vector<T>`     | -                   |\n\nThere are a few things of note:\n\n-   While Rust omits a size to indicate the size is known only at runtime, Safe\n    C++ uses a `dyn` keyword indicate the same.\n-   The heap-buffer type name is unchanged from C++, sticking with `vector`.\n\n### Goals\n\nIt will help to establish some goals in order to weigh alternatives against.\nThese goals are based on the\n[open discussion from 2024-12-05](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?usp=sharing&resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA#heading=h.h0tg34pzq5yz),\nwhere we discussed the\n[Pointers, Arrays, Slices](https://docs.google.com/document/d/1hdYyCLmzEOj9gDulm7Eo1SVNc0pY7zbMvFmEzenMhYE/edit?usp=sharing)\ndocument.\n\nThe goals here are largely informed by and trying to achieve the top-level goal\nof\n[\"Code that is easy to read, understand, and write\"](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nWe define some more specific targets here as relate to the specifics of the\narray syntax.\n\n#### Privileging the most common type names\n\n-   \"Explicitness must be balanced against conciseness, as verbosity and\n    ceremony add cognitive overhead for the reader, while explicitness reduces\n    the amount of outside context the reader must have or assume.\"\n\nThe more common it will be for a type to be used, the shorter we would like the\nname to be. This follows from the presumption that we weigh conciseness as\nincreasingly valuable for types that will appear more frequently in Carbon code.\n\nWe expect the ordering of frequency in Carbon code to be:\n\n-   fundamental types ≈ tuples >> heap-buffers > arrays >> everything else[^1].\n\nWhere fundamental types are: machine-sized integers (8 bit, 16 bit, etc.),\nmachine-sized floating points, and pointers including slices[^2]. Function\nparameters/arguments are an example of tuples.\n\nFrom this, we derive that we want:\n\n-   Fundamental types and tuples to have the most concise names.\n    -   We can lean on special syntax or keywords as needed to make them concise\n        but descriptive.\n-   Heap-buffers to have a concise name, even more so than arrays.\n    -   We could use special syntax or keywords if needed to achieve\n        conciseness.\n-   Arrays to have a concise name, but they do not need to be comparably concise\n    to fundamental types and tuples.\n    -   We should try to avoid special syntax.\n-   Everything else should be written as idiomatic types with descriptive names.\n\n[^1]:\n    \"[chandlerc] Prioritize: slices first, then [resizable storage], then compile-time\n    sized storage, then everything else is vastly less common. Between those three,\n    the difference in frequency between the first two is the biggest.\" from [open discussion on 2024-12-05](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0)\n\n[^2]:\n    Slices are included with fundamental types for simplicity, since they will\n    take the place of many pointers in C++, giving them similar frequency to\n    pointers, and can be logically thought of as a bounded pointer.\n\n#### Absence of syntax should make clear defaults\n\nOne way to write arrays and compile-time-sized slices is like we see in Rust:\n`[T; N]` and `&[T; N]`. This suggests a relationship where array is like slice,\nand the default form. But they are very different types, rather than a\nmodification of a single type, and this can be confusing[^3] for developers\nlearning the language.\n\n[^3]: https://fire.asta.lgbt/notes/a1iay7r3e7or0a59 (content-warning: swearing)\n\nWe want to avoid the situation where\n[absence of syntax](https://www.youtube.com/watch?v=-Hb-9TUyjoo), such as a\nmissing pointer indicator, changes the entire meaning of the remaining syntax or\nis otherwise confusing.\n\n#### Avoiding confusion with other languages\n\nThe most general meaning of \"array\" is a range of consecutive values in memory.\n\nHowever in many languages it is used, either in formally or informally, to refer\nto a direct-storage, immutably-sized memory range:\n\n-   C,\n    [colloquial](https://en.wikibooks.org/wiki/C_Programming/Arrays_and_strings)\n-   C++, colloquial (from C) and\n    [`std::array`](https://en.cppreference.com/w/cpp/container/array)\n-   Go, [colloquial](https://go.dev/tour/moretypes/6)\n-   Rust, [colloquial](https://doc.rust-lang.org/std/primitive.array.html)[^4]\n\nIn particular, this is the usage in the languages which Carbon will most\nfrequently interoperate, and/or from which code will be migrated to Carbon and\nthus comments and variable names would use these terms in this way.\n\n[^4]:\n    Maybe this is more formal than colloquial, but the name is not part of the\n    typename/syntax.\n\nLanguages which require shared ownership _don't have direct-storage arrays_, so\nthe same term gets used for indirect storage:\n\n-   Swift, [`Array`](https://developer.apple.com/documentation/swift/array)\n    -   As noted earlier, Swift is in the processes of adding a direct-storage\n        array called\n        [`InlineArray`](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0453-vector.md).\n        Backwards compatibility prevents the use of `Array` for this.\n-   Javascript,\n    [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)\n-   Java and Kotlin,\n    [`ArrayList`](https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html)\n\nAnd some languages use array to refer to both direct and indirect storage types.\n\n-   Dlang has direct-storage arrays\n    [colloqually](https://dlang.org/spec/arrays.html) and the indirect-storage\n    [`Array`](https://dlang.org/phobos/std_container_array.html) type.\n-   Pascal uses the presence or absence of a size to determine if\n    [`Array`](https://www.freepascal.org/docs-html/ref/refsu14.html) uses direct\n    (immutably-sized) or indirect (mutably-sized) storage.\n\nIn sum, languages which have direct-storage immutably-sized arrays use the term\n\"array\" to refer to those, and most then use a separate name for the\nindirect-storage type.\n\n#### Avoiding confusion with other domains\n\nThe term \"vector\" in mathematics refers to a fixed-size set of numbers. This\nleads to confusion with the C++ type `std::vector` since it holds a\nmutably-sized set of values. Developers coming from other domains must learn a\nnew and contradictory term of art. The Rust language chose naming that derives\nfrom C++, with `std::vec::Vec`.\n\nThese type names conflict with names in mathematical and graphics libraries,\nwhich want to use vector in its mathematical sense. In Rust this leads to `Vec`\nfor a mutably-sized array, and\n[`Vec3`](https://docs.rs/bevy/latest/bevy/prelude/struct.Vec3.html),\n[`Vec4`](https://docs.rs/bevy/latest/bevy/prelude/struct.Vec4.html), and so on\nfor fixed-size mathematical vectors. While not fatal, this does create ambiguity\nthat must be overcome by developers.\n\n### No predeclared identifiers\n\nRecently the proposal\n[p4864: No predeclared identifiers, Core is a keyword](https://docs.carbon-lang.dev/proposals/p4864.html)\nclarified a direction for the Carbon language, wherein there will not be\nimplicit imports from the `Core` library. Anything accessible directly in the\nlanguage, rather than through a package name, is done so through a builtin\nkeyword. This ensures that raw identifier syntax is always available for those\nsame names in Carbon code.\n\n## Proposal\n\nThe\n[All APIs are library APIs principle](/docs/project/principles/library_apis_only.md)\nstates:\n\n> In Carbon, every public function is declared in some Carbon API file.\n\nAs such, we propose a `Core` library type for a direct-storage immutably-sized\narray, and then a builtin shorthand for referring to that library type.\n\nIn line with other languages surveyed above, given the presence of a\ndirect-storage immutably-sized array in Carbon, we will reserve the unqualified\nname \"array\" for this type. In full, its name is `Core.Array(T, N)`, where `T`\nis the type of elements in the array, and `N` is the number of elements. Notably\nthis leaves room for supporting multi-dimensional arrays by adding further\noptional size parameters, either in the `Array` type or in a similar sibling\ntype.\n\nHere is a provisional vocabulary table to compare with other languages:\n\n| Owning type              | Runtime Sized | Compile-time Sized                 |\n| ------------------------ | ------------- | ---------------------------------- |\n| Direct, Immutable Size   | -             | `array(T, N)` / `Core.Array(T, N)` |\n| Indirect, Immutable Size | ?             | `Core.Box(Array(T, N))`            |\n| Indirect, Mutable Size   | `Core.Buf(T)` | -                                  |\n\nCarbon does not have proposed names for heap-allocated storage, so we use some\nplaceholders here, in order to show where `Array` fits into the picture:\n\n-   `Box(T)` for a heap-allocated `T` value.\n-   `Buf(T)` for a heap-buffer of `T` values.\n\nAn indirect, immutably-sized buffer does not have a clearly expressible syntax\nat the moment. `Box([T])` is the closest fit with the current provisional syntax\nfor slices. But `[T]` is a sized pointer, which would make this type a\nheap-allocated sized pointer, rather than a heap-allocated fixed-size array.\nThis is in contrast with Rust where `&[T]` is a slice, and `[T]` is a fixed-size\nbuffer; so it then follows that `Box<[T]>` is a heap-allocated fixed-size\nbuffer.\n\nBecause arrays will be very common in Carbon code, we want to privilege their\nusage. There are at least two ways in which we can do so. The first is to\ninclude them in the `prelude` library of the `Core` package. This ensures they\nare available in every Carbon file as `Core.Array(T, N)`. The second is by\nmaking the type available through a shorthand without being qualfiied by the\n`Core` package name. We propose the `array(T, N)` builtin keyword as that\nshorthand.\n\n## Rationale\n\nAs this proposal is addressing the question of introducing a new `prelude`\nlibrary type in `Core`, it is mostly focused on the goal\n[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n\nThis proposal aims to make code easy to understand by using a name that is\nconsistent across systems programming languages, and avoiding names that have\nconflicting meaning. It also uses a standard type syntax, with a type in the\n`Core` package, making the type and its documentation maximally discoverable\nwithout requiring special-casing.\n\nWe introduced some more specific sub-goals above:\n\n1. Privileging the most common type names\n\nThis proposal privileges `Core.Array` as it will appear frequently in code, by\nplacing it in the `prelude` library. This avoids the need for developers to\n`import` another `Core` library in order to access the type.\n\nSince array types are expected to be very frequent, we also propose an `array`\nbuiltin keyword as a shorthand. This is in line with the\n[No predeclared identifiers](https://docs.carbon-lang.dev/proposals/p4864.html)\nproposal, and uses a lowercase spelling to mark the word as a builtin. The\nspelling of `array(T, N)` will resolve to the library type `Core.Array(T, N)`.\n\nIn this proposal, we avoid introducing additional syntax (such as with `[T; N]`\nor `(1, 2)`) because the frequency of use of arrays will be lower than that of\nfundamental types and tuples.\n\n2. Absence of syntax should make clear defaults\n\nWe introduce a type name, with a keyword that has a clear relationship to the\ngeneric type name, rather than making arrays look more like slices but without\nbeing a pointer. This is maent to avoid the confusion raised when removing\nsyntax changes the meaning significantly, and especially in ways that differ\nfrom defaults/options for a single language concept.\n\n3. Avoiding confusion with other languages\n\nWe propose using the `Array` type name, and `array` shorthand, in line with how\nother languages use the same term. When a direct-storage array type is part of\nthe language, it's consistently referred to as an \"array\" without\nqualifications.\n\nMost importantly, the name is consistent with the meaning in C++ and its\nstandard library (`std::array<T, N>`) as well as with Rust, the languages which\nwe expect Carbon code to interact with the most.\n\n4. Avoiding confusion with other domains\n\nThe name `Vector` is a possible choice for a fixed-length set of values, due to\nits mathematical meaning, as was originally proposed for the direct-storage\nimmutably-sized array type in Swift. However any use of the name `Vector` in a\ncore systems programming language construct is fraught. Either the name is to be\nincorrectly confused with a mathematical vector or with a C++ `std::vector`. We\navoid the confusion by avoiding this name.\n\n## Future work\n\n### Namespacing the `Core` package\n\nAt this time, the `Core` package remains small, but there will come a time where\nthe names within need to be split into smaller namespaces. Then the name\n`Core.Array`, among others, will become longer and the act of previleging the\nname through the `array` keyword will become more pronounced and helpful. At\nthis time, we don't propose to put `Array` into a namespace in `Core` as there's\nno such existing structure to point to yet.\n\n## Alternatives considered\n\n### `[T; N]` builtin syntax\n\nThis is the current syntax used by the toolchain, however it had the following\nproblems raised:\n\n-   It's very similar to the syntax for slices, which is `[T]`, but very\n    different in nature, being storage instead of a reference to storage.\n-   Given `[T]` is a slice, `[T; N]` would better suit a compile-time-sized\n    slice.\n\nThe syntax for a slice may also be changed, we discussed\n[adding a pointer annotation](https://docs.google.com/document/d/1hdYyCLmzEOj9gDulm7Eo1SVNc0pY7zbMvFmEzenMhYE/edit?tab=t.0#heading=h.fahgww8db6f0)\nto it, such as `[T]*` and `[T; N]*`. Some downsides remained:\n\n-   The `[T; N]*` syntax would be a fixed-size slice, rather than a pointer to\n    an array. This leaves no room for writing a pointer to an array, which can\n    indicate a different intent, that it always includes the full memory range\n    of the array. Without this distinction, we can't model both\n    `std::span<T, N>` and `std::array<T, N>*` in code migrated from C++ to\n    Carbon and would need to collapse these to a single type.\n-   Removing the pointer annotation would change the meaning of the type\n    expression more then we'd like, since it would change from a slice into an\n    array, rather than pointer-to-an-array into an array.\n\n### `array [T; N]` builtin syntax\n\nThis introduces a keyword as a modifier of a fixed-size slice, rather than a\nbuiltin forwarding type. While arrays will be very common, it's not clear that\nthey rise to the level of requiring breaking the languages naming rules (using a\nlowercase name) in order to provide a shorthand. And the shorthand is longer in\nthe end than the `Array(T, N)` being proposed here. So this uses a larger\nweirdness budget for privileging the type while achieving less conciseness.\n\nThis has a similar issue as with `[T; N]` but in the reverse. Removing the\n`array` modifier keyword changes the meaning of the type expression in ways that\nare larger than a default/modifier relationship. Fixed-size slices are not the\nmore-default array.\n\nThe use of a lowercase keyword also costs us by preventing users from using the\nword `array` in variables, a name which is quite common.\n\n### Just the `Core.Array(T, N)` library type\n\nProviding just the library type is possible, but arrays will be one of the most\ncommon types in Carbon code, as described earlier. Privileging them with a\nshorthand that avoids `Core.` will help make Carbon code significantly more\nconcise, due to the frequency, without hurting understandability. This makes it\nworth the tradeoff of putting a name into the file scope (by way of a builtin\ntype).\n\n### Implicitly importing `Core.Array(T, N)` to the file scope\n\nWe considered a direction where some subset of names in the `Core` packages's\n`prelude` library are imported automatically to the file scope. This would be\nsimilar to the\n[Rust `std::prelude` module](https://doc.rust-lang.org/stable/std/prelude/index.html),\nwhich names aliases that are pulled into the global scope.\n\nImporting names poses challenges for migrating code to Carbon. Names imported\nfrom a library may allow shadowing in other scopes, which would create ambiguity\nabout the meaning of these names. And names imported from a library would not be\navoidable using the raw identifier syntax: `Array` and `r#Array` would both\nrefer to the same imported `Core.Array` type. This would present a challenge for\ncode migrated to Carbon which uses the name `Array` in its own types or\nvariables. Whereas with a builtin keyword, `array` and `r#array` refer to\ndifferent things: The first is the keyword, and the second is a name that the\ndeveloper can use freely for other purposes.\n\nThe\n[No predeclared identifiers, Core is a keyword](https://docs.carbon-lang.dev/proposals/p4864.html)\nproposal discusses in more detail why this approach was not taken.\n"
  },
  {
    "path": "proposals/p4864.md",
    "content": "# No predeclared identifiers, `Core` is a keyword\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/4864)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Future work](#future-work)\n    -   [Package name `Cpp`](#package-name-cpp)\n    -   [Package name `Main`](#package-name-main)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Have both predeclared identifiers and keywords](#have-both-predeclared-identifiers-and-keywords)\n    -   [Reserve words with a certain spelling](#reserve-words-with-a-certain-spelling)\n\n<!-- tocstop -->\n\n## Abstract\n\nIntroduce a principle that the Carbon language should not encroach on the\ndeveloper's namespace. Satisfy this principle by making `Core` a keyword.\n\n## Problem\n\nOngoing design work needs rules for how to expose types such as a primitive\narray type to Carbon code, and in particular, if we choose to make it available\nby default, whether that should be accomplished by a keyword or a predeclared\nidentifier.\n\n## Background\n\nSee the\n[Background section of the added principle](/docs/project/principles/namespace_cleanliness.md#background).\n\n## Proposal\n\nWe choose to not have any predeclared identifiers in Carbon. If a word has\nspecial meaning to the language, then that word is a keyword, and a plain\nidentifier with no special meaning is always available using raw identifier\nsyntax.\n\n## Details\n\nSee [the principle document](/docs/project/principles/namespace_cleanliness.md)\nfor details of the added principle. In addition, we make one change and one\nclarification:\n\n-   `Core` is changed from being an identifier that happens to be the name of\n    the Carbon standard library, and happens to be predeclared in every source\n    file as naming that library, to being a keyword. The keyword can only be\n    used:\n\n    -   When importing the `Core` package.\n    -   When implementing the `Core` package as part of the language\n        implementation.\n    -   As a keyword naming the `Core` package, much like the `package` keyword.\n\n    The identifier `r#Core` can be used freely and does not conflict with the\n    keyword. This includes use of `r#Core` as the name of a package. Language\n    constructs that are defined in terms of entities in the `Core` package refer\n    specifically to the package named with the _keyword_ `Core`, not to any\n    other entity named `Core`.\n\n-   The `self` keyword is now included in the list of keywords. It is already\n    treated as a keyword by the toolchain.\n\n## Rationale\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   Code generation tools can have a uniform handling for all words with\n        special meaning, with no need to alter the spelling of names from other\n        languages.\n    -   Language tools can determine the meaning of `Core.<name>` without\n        needing to do any name lookup or sophisticated analysis.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Migration between versions of Carbon with a changed set of reserved\n        words can be done uniformly.\n    -   Adding names to the prelude remains a non-breaking change. Adding new\n        predeclared names requires adding a keyword, with the same cost and\n        value tradeoffs regardless of whether the keyword names a library\n        declaration or introduces new language syntax.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Syntax highlighting tools can easily distinguish between words with\n        special meaning and words with program-defined meaning.\n    -   The meaning of core language constructs can be defined as a rewrite in\n        terms of `Core.<name>` without concern that `Core` may have some\n        different local interpretation.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   All C++ identifiers are nameable from Carbon code without conflicts.\n        Virtual functions introduced in C++ can be overridden in Carbon\n        regardless of their name. C++ code can be migrated to Carbon even if its\n        name in C++ has special meaning in Carbon.\n-   [Principle: Prefer providing only one way to do a given thing](/docs/project/principles/one_way.md)\n    -   This proposal specifies that there is only one way to give words special\n        meaning in Carbon, and one way to resolve issues if that special meaning\n        conflicts with another desired meaning.\n\n## Future work\n\n### Package name `Cpp`\n\nThe special package name `Cpp` that refers to code written in C++ is not made a\nkeyword by this proposal, but this proposal is also not deciding that it should\n_not_ be a keyword. While this name has special meaning to the language, it's\nnot predeclared in any context, so it's considered to be out of scope. A future\nproposal that describes the details of C++ import should determine whether this\nname becomes a keyword. Notably, making `Cpp` a keyword would also allow an\n`import Cpp` declaration to have custom syntax, which may be useful.\n\n### Package name `Main`\n\nThe special package name `Main` that is currently reserved in all package name\ncontexts is not made a keyword in this proposal either. There would be no\nmeaning in making it a keyword, as it is never used as a special package name in\nCarbon source files. However, we could consider using an empty package name as\nthe name of the main package, and unreserving the package name `Main`, if it\nbecomes a concern that we reserve this name.\n\n## Alternatives considered\n\n### Have both predeclared identifiers and keywords\n\nWe could provide both predeclared identifiers and keywords. Many languages\nfollow this path. However, predeclared identifiers have some problems compared\nto keywords:\n\n-   In order to locally declare a name matching a predeclared identifier, the\n    name would need to be shadowed.\n    -   Such shadowing may be invalid, depending on how the name is used.\n    -   Readability is harmed by using a name used as basic vocabulary with a\n        different, local meaning.\n    -   Shadowing a predeclared identifier typically makes the original name\n        hard to access -- an alias or similar must be established in advance.\n-   There need to be two different stories for how to deal with adding a new\n    word with special meaning to the language, depending on whether it is a\n    keyword.\n-   For each word with special meaning, we must make an arbitrary decision as to\n    which kind it is, resulting in a largely meaningless distinction that\n    nonetheless is visible and would need to be known by developers in some\n    contexts.\n\n### Reserve words with a certain spelling\n\nWe could reserve words with certain spellings for future use as keywords or as\nvendor extensions. Some languages do this:\n\n-   C reserves words starting with an underscore followed by a capital letter or\n    an underscore.\n-   C++ additionally reserves words containing a double underscore anywhere.\n-   Python uses the `__name__` namespace for certain special names, and by\n    convention these names are reserved for that purpose.\n\nIn Carbon we could accomplish this by saying that all words of the reserved\nforms are keywords, with no meaning ascribed to them yet.\n\nHowever, we do not have a clear need for such reserved words at this time, and\nwe would not want to use such spellings when we do add language keywords later.\nMoreover, C++ programs frequently declare reserved words in practice, and we\nshould expect the same in Carbon. Without enforcement, the names are not\neffectively reserved.\n\nIf we find a need at a later time to introduce vendor-specific language\nextension keywords, we can revisit this, but should also consider alternatives\nsuch as a `k#foo` spelling to turn what is normally an identifier into a\n(potentially vendor-specific) keyword.\n"
  },
  {
    "path": "proposals/p4880.md",
    "content": "# Safety milestones and a 2025 roadmap\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/4880)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Proposal](#proposal)\n-   [Retrospective on 2024](#retrospective-on-2024)\n\n<!-- tocstop -->\n\n## Abstract\n\nWe propose updating our milestones to accelerate design and implementation of\nmemory safety in Carbon, and a roadmap for 2025 reflecting this change. We also\nprovide a retrospective for 2024's progress.\n\n## Proposal\n\nRecently, we have seen several new contributors join the Carbon project and a\ncorresponding up-tick in activity across the project. We are all really excited\nboth by the new folks participating and seeing things move faster.\n\nHowever, we have also had some good conversations with potential users and other\ninterested parties about the project and our roadmap. Everyone has been very\nhappy to see the rapid progress on a realistic toolchain, but we have also\ngotten even stronger feedback than previously around memory safety, and we\npropose updating our plans to better address that feedback.\n\nFor the past two years we have been working on the C++-interop focused aspect of\nCarbon, and deferring the work to build out a strong memory safety story. While\nthere was strong interest in memory safety, and for many an essential\nrequirement long term, it seemed reasonable to tackle first interop, and then\nlook at safety. This was heavily informed both by having a very small set of\ncontributors and a desire to ship an 0.1 milestone with C++ interop as quickly\nas possible.\n\nNow we both have a larger set of contributors, and even stronger and more\nspecific feedback asking for a concrete and detailed design for memory safety in\nCarbon sooner rather than later. We propose as a consequence to add a concrete\n_design_ for memory safe Carbon to our 0.1 milestone, and begin working on this\nin parallel to the toolchain in 2025.\n\nOur projected timeline for reaching 0.1 was historically based on growing the\nset of contributors while keeping all of them focused on the smaller prior 0.1\nmilestone. Adding a memory safety design to our target for 0.1 will make it\nimpossible to ship in 2025 even with the larger contributor base. We are\nshifting our target from 2025 for 0.1 to, at the soonest, the end of 2026; and\nas always with these projections, they should be understood as a lower bound.\n\nWith these updated milestones, we propose the following goals for 2025:\n\n-   Complete design and implementation for remaining Carbon features needed for\n    non-template C++ interop\n-   Complete most of the interop layer for non-template Carbon ↔ C++,\n    prioritizing calling/using C++ APIs from Carbon, and then exposing Carbon\n    APIs back to C++.\n-   Full support for compiling C++ code with the Carbon toolchain using Clang\n-   Update our safety strategy, and establish a detailed strategy for memory\n    safety\n-   Design for compile-time & type-system based temporal and mutation safety\n\nBoth the C++ interop and the memory safety designs are expected to have\ndependencies that we will need to prioritize in 2025. The C++ interop will\ndepend on finishing the implementation of many parts of the Carbon language in\nour toolchain, and the safety designs will build on top of the existing Carbon\ntype-system design, including refinements to it from our implementation\nexperience.\n\nAs with previous years, we will also continually share our progress and what we\nlearn with the broader open source and C++ communities.\n\n## Retrospective on 2024\n\nOur [roadmap for 2024] was an ambitious pivot to focus heavily on implementing\nthe Carbon language in a realistic compiler and toolchain. At a high level, this\npivot was _very_ successful. Carbon's compiler has made massive strides over the\nyear, and all of the active contributors to Carbon have thoroughly ramped up on\nour implementation and are making meaningful contributions to it.\n\n[roadmap for 2024]:\n    https://github.com/carbon-language/carbon-lang/blob/10189bbb78db7b143a6d9d62797fc9698363fe4d/docs/project/roadmap.md\n\nGoing into 2024, Carbon's compiler didn't have any support for generics,\nimporting, expression categories, debug info, mangling, a prelude, or so many\nother things now in flight. Constant evaluation didn't know about aggregates,\nand classes couldn't be initialized at all. We had no examples, much less\nworking ones. By the end of 2024, with a surprisingly minimal number of hacks,\nit was possible to solve much of Advent of Code! The progress here has been\nphenomenal, and we made awesome strides towards our goal of a working toolchain.\n\nLooking in more detail at our key results for 2024:\n\n-   [Carbon's toolchain implements enough of the language to build realistic code](https://github.com/carbon-language/carbon-lang/blob/10189bbb78db7b143a6d9d62797fc9698363fe4d/docs/project/roadmap.md#carbons-toolchain-implements-enough-of-the-language-to-build-realistic-code)\n    -   A smashing success, overall.\n    -   We have imports, a working prelude, generic types and functions.\n    -   We have many of the building blocks of dispatching through interfaces\n        for operator overloading, but there are still a few gaps left. Despite\n        the gaps, we're actually using our generic building blocks effectively,\n        including with a working `Core.Int` generic integer type that backs\n        `i32` instead of a hard coded type!\n    -   We didn't get to the more stretch parts of this goal like templates\n        though.\n-   [Carbon's toolchain can build C++ code](https://github.com/carbon-language/carbon-lang/blob/10189bbb78db7b143a6d9d62797fc9698363fe4d/docs/project/roadmap.md#carbons-toolchain-can-build-c-code)\n    -   We have Clang integrated into the toolchain!\n    -   It works reasonably well for C++ code without system `#include`s.\n    -   But we still need to get some critical headers and other data that Clang\n        depends on to get this fully working with system `#include`s.\n-   [Carbon's toolchain works with existing, simple C++ build systems](https://github.com/carbon-language/carbon-lang/blob/10189bbb78db7b143a6d9d62797fc9698363fe4d/docs/project/roadmap.md#carbons-toolchain-works-with-existing-simple-c-build-systems)\n    -   Until we have all the system `#include` support work done, we can't drop\n        our toolchain into a C++ build system. =/ This one ended up largely not\n        landing this year.\n    -   We did end up integrating Carbon's toolchain into very simple Bazel\n        build rules that we use to continuously build and test a collection of\n        example Carbon code. This made sure the compilation model does work in a\n        realistic toolchain situation for Carbon code.\n-   [Carbon has a design and toolchain implementation of basic C++ interop](https://github.com/carbon-language/carbon-lang/blob/10189bbb78db7b143a6d9d62797fc9698363fe4d/docs/project/roadmap.md#carbon-has-a-design-and-toolchain-implementation-of-basic-c-interop)\n    -   This was too ambitious of a goal, but we actually got very close. The\n        first importing of C++ headers (but without doing anything) has already\n        landed, so we weren't too far away from the most basic parts of this.\n-   [Give talks at 2-3 conferences covering 3-4 different Carbon topics](https://github.com/carbon-language/carbon-lang/blob/10189bbb78db7b143a6d9d62797fc9698363fe4d/docs/project/roadmap.md#give-talks-at-2-3-conferences-covering-3-4-different-carbon-topics)\n    -   We had a really strong year delivering talks at both C++ and LLVM\n        conferences: 5 talks on different topics plus a panel session.\n-   [Start building our initial tutorial and introductory material](https://github.com/carbon-language/carbon-lang/blob/10189bbb78db7b143a6d9d62797fc9698363fe4d/docs/project/roadmap.md#start-building-our-initial-tutorial-and-introductory-material)\n    -   We got an important start here with newsletters every other month,\n        packaged pre-releases, and even some \"first look\" courses introducing\n        people to Carbon.\n    -   However, tutorial material still seems somewhat far away.\n\nOverall, we achieved the majority of what we set out to for 2024. While our\nroadmaps are always a bit ambitious to push us, this year didn't seem excessive\nand is likely to reflect roughly how ambitious we want to be in our roadmaps.\n"
  },
  {
    "path": "proposals/p5017.md",
    "content": "# Destructor syntax\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5017)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [Not directly callable](#not-directly-callable)\n-   [Future work](#future-work)\n    -   [Extend syntax to allow explicit marking of _trivial_ destructors](#extend-syntax-to-allow-explicit-marking-of-trivial-destructors)\n    -   [Decide whether to desugar destructors to interfaces](#decide-whether-to-desugar-destructors-to-interfaces)\n    -   [Copy and move functions](#copy-and-move-functions)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Destructor syntax options](#destructor-syntax-options)\n    -   [Destructor name options](#destructor-name-options)\n\n<!-- tocstop -->\n\n## Abstract\n\nFix destructor syntax ambiguity by switching to `fn destroy` mirroring standard\nfunction syntax. This is a purely syntactic change, maintaining destructor\nsemantics.\n\n## Problem\n\nThe\n[accepted destructor syntax](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/classes.md#destructors)\nincludes out-of-line definitions such as:\n\n```carbon\nclass MyClass {\n  destructor [addr self: Self*];\n}\ndestructor MyClass [addr self: Self*] { ... }\n```\n\nThe implicit parameter here could be interpreted as either an implicit parameter\nfor `MyClass` or an implicit parameter for the destructor. How should\nambiguities like this be resolved?\n\nFor comparison, note a generic might look like:\n\n```carbon\nclass GenericClass[T:! type](N:! T) { ... }\ndestructor GenericClass[T:! type](N:! T) [addr self: Self*] { ... }\n```\n\nThe toolchain is able to parse this in constant time, but only because the lexer\nwill pair brackets, so we can do lookahead at the bracket in `GenericClass[` for\nthe closing `]`, and look past that for the `(` versus `{`. However, this is\narbitrary lookahead and may be significantly less efficient in other parsers\nthat people might want to use with Carbon, such as tree-sitter.\n\n## Background\n\n-   Proposal\n    [#1154: Destructors](https://github.com/carbon-language/carbon-lang/pull/1154)\n-   Leads question\n    [#4999: Out-of-line destructor syntax ambiguity](https://github.com/carbon-language/carbon-lang/issues/4999)\n-   [2025-02-25 Toolchain minutes](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.vootuzze8e8e)\n\nIn particular, we are discussing destruction as possibly similar to copy and\nmove syntax, and trying to create a consistency between the functions.\n\n## Proposal\n\nDestructor syntax will use standard function syntax, with `destroy` as a keyword\nfor the function name.\n\nFor example, in contrast with [problem examples](#problem):\n\n```carbon\nclass MyClass {\n  fn destroy[addr self: Self*]();\n}\nfn MyClass.destroy[addr self: Self*]() { ... }\n\nclass GenericClass[T:! type](N:! T) { ... }\nfn GenericClass[T:! type](N:! T).destroy[addr self: Self*]() { ... }\n```\n\nIt is invalid to add other implicit or explicit parameters to the `destroy`\nfunction.\n\n### Not directly callable\n\nAlthough the syntax of `fn destroy` looks similar to a regular function, the\nfunctions are not designed to be directly callable. This does not add support\nfor `my_var.destroy()`. See Proposal #1154, alternative\n[Allow functions to act as destructors](/proposals/p1154.md#allow-functions-to-act-as-destructors)\nfor details.\n\n## Future work\n\n### Extend syntax to allow explicit marking of _trivial_ destructors\n\nDiscussion has indicated potential utility in syntax to make the expectation of\na trivial destructor _explicit_. This would allow a declarative way of ensuring\nno member accidentally caused a type to have non-trivial destruction.\n\nStill, this requires a further extension of syntax that isn't proposed at this\ntime. Both determining syntax for such a feature and motivating it fully are\nleft as future work.\n\n### Decide whether to desugar destructors to interfaces\n\nUnder this proposal, `fn destroy` remains a special function. We may want to\nmake it desugar to an interface implementation, but even if we do so, the terse\ndestructor syntax seems likely to remain. There are concerns about the\nergonomics of requiring an `impl` in order to add a destructor to a type, and\ndecisions would need to be made for how virtual destructors should be handled.\n\n### Copy and move functions\n\nThis proposal is set up for consistency with a possible `fn copy` and `fn move`,\nbut those will be evaluated as part of copy and move semantics.\n\n## Rationale\n\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n    -   Eliminates ambiguity in `destructor` syntax, by creating consistency\n        with `fn` syntax.\n    -   Claiming `destroy` as a keyword is considered to be a good balance.\n    -   Syntax choices, particularly with the keyword as a function name, should\n        not create a barrier for desugaring to an interface approach for\n        destructions.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Consistency with `fn` syntax should improve readability.\n    -   Features that impact data layout are consistently written like member\n        declarations.\n\n## Alternatives considered\n\n### Destructor syntax options\n\nThe ambiguity between `destructor MyClass [...]` out-of-line destructor syntax\nand implicit parameters for generics is a sufficient barrier to change syntax.\nWe do not want parsing Carbon to require arbitrary lookahead.\n\n`fn destroy` was preferred because it builds on existing `fn` syntax.\n\nAlthough adding a `.`, as in `destructor MyClass.[...]`, was brought up, it\ndidn't present interesting advantages over `fn destroy`.\n\n### Destructor name options\n\nWe expect more name conflicts with C++ code using the `destroy` keyword than\nwith the `destructor` keyword, for example with\n[`std::allocator::destroy`](https://en.cppreference.com/w/cpp/memory/allocator/destroy),\nor visible\n[searching LLVM code](https://github.com/search?q=repository%3Allvm%2Fllvm-project+language%3Ac%2B%2B+symbol%3A%2F%28%3F-i%29%5Edestroy%24%2F&type=code).\n\nStill, the phrasing of `destroy`, particularly if we have `copy` and `move` to\nmatch, is preferred. Raw identifier syntax (`r#destroy`) is expected to be\nsufficient for name conflicts.\n\n`fn delete` was mentioned as an option reusing current keywords, but declined\ndue to the \"heap allocated\" implication of `delete`.\n\nNon-keyword names were considered as part of proposal\n[#1154: Destructors](https://github.com/carbon-language/carbon-lang/pull/1154),\nand the trade-off considerations still apply.\n"
  },
  {
    "path": "proposals/p5087.md",
    "content": "# Qualified lookup into types being defined\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5087)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Uses requiring a complete type](#uses-requiring-a-complete-type)\n    -   [Lookups into an incomplete generic](#lookups-into-an-incomplete-generic)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Require completeness for qualified name lookup](#require-completeness-for-qualified-name-lookup)\n    -   [Do not require a definition for name lookup](#do-not-require-a-definition-for-name-lookup)\n\n<!-- tocstop -->\n\n## Abstract\n\nAllow qualified name lookup into classes and interfaces as soon as we reach the\n`{` of the definition, rather than disallowing such lookups until we reach the\n`}`.\n\n## Problem\n\nWe allow unqualified lookups within a type definition to find names that were\nalready declared, but not qualified lookups:\n\n```carbon\nclass A {\n  class B {}\n  // ✅ OK, `B` names `A.B`.\n  fn F() -> B;\n  // ❌ Error (before this proposal): `A` is not complete.\n  fn G() -> A.B;\n}\n\ninterface I {\n  let T:! type;\n  // ✅ OK, `T` names `Self.T`.\n  fn F() -> T;\n  // ❌ Error (before this proposal): type `I` of `Self` is not complete.\n  fn G() -> Self.T;\n}\n```\n\nThis is inconsistent and prevents useful code:\n\n```carbon\ninterface Container {\n  let ValueType:! type\n  // ❌ Error (before this proposal): type `Container` of `.Self`\n  // is not complete in implicit access to `.Self.ValueType`.\n  // Implicit access to `Self.ValueType` is OK though.\n  let SliceType:! Container where .ValueType == ValueType;\n}\n```\n\nAn additional inconsistency is that namespaces already support qualified lookup\nbefore the full list of names is known -- indeed, the full list of names in a\nnamespace is never known.\n\n## Background\n\nProposal\n[#3763](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p3763.md)\nintroduces a name poisoning rule:\n\n> In a declarative scope, it is an error if a name is first looked up and not\n> found, and later introduced.\n\nThis is achieved by _poisoning_ a name in a scope when we perform a failed\nlookup for that name in that scope, and diagnosing if the name is later declared\nin a scope where it is poisoned.\n\nWith that rule, there is no risk in allowing name lookups into a scope to\nsucceed even before the scope is complete. If the name lookup's meaning would be\nchanged by a later declaration, an error is issued.\n\nThe motivation for this proposal and the proposed rule change were discussed in\nopen discussion on\n[2025-02-21](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.ix77am1xk6po),\n[2025-02-27a](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.ank09kkr0tnn),\nand\n[2025-03-03b](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.19yyjdek3asm).\n\n## Proposal\n\nAllow name lookups into a type once it is defined, even before it is complete.\n\n## Details\n\nWe adopt the following terminology:\n\n-   An entity is _defined_ at the point where we reach the `{` of its\n    definition. _Exception:_ A namespace is defined by its first declaration.\n-   An entity is _complete_ at the point where we reach the `}` of its\n    definition.\n\nInstead of qualified name lookup into the scope of a type requiring the type to\nbe complete, we now only require it to be defined. Therefore, qualified lookup\nwithin the braces of the type definition are now permitted.\n\nSuch a name lookup only finds names that were declared prior to the lookup, in\nline with the\n[information accumulation principle](/docs/project/principles/information_accumulation.md).\nIf the name is first declared after the point at which it is looked up, the\nlater declaration of the name is rejected by to the poisoning rule [described earlier](#background].\n\n```carbon\nbase class A {\n  class Inner {}\n}\n\nclass B {\n  extend base: A;\n  // ✅ OK for now, `Inner` names `A.Inner` because\n  // no results were found directly in scope of `B`.\n  var i: B.Inner;\n  // ❌ Error: name `Inner` is poisoned due to prior lookup in this scope.\n  class Inner {}\n}\n```\n\n### Uses requiring a complete type\n\nWhile this proposal permits qualified name lookup into types that are\nincomplete, many uses of the names found by such lookups will still require\ncompleteness. For example:\n\n-   Instance binding for a class instance member requires a complete type.\n\n    ```carbon\n    class X[T:! type](v: T) {}\n\n    class A {\n      var n: i32;\n      fn F() -> A;\n      // ❌ Error: `A` is not complete.\n      var m: X(fn (A a) => F().n);\n    }\n    ```\n\n-   Some uses of interfaces require the interface to be complete, although\n    determining which uses require this is outside the scope of this proposal.\n\n### Lookups into an incomplete generic\n\nIt is possible to perform qualified name lookup into a generic type before the\ntype is complete.\n\n```carbon\nclass X[T:! type](x: T) {}\n\nclass A(T:! type) {\n  fn F() -> A(T);\n  // OK, argument to `X` is the `F` function in `A(i32)`.\n  var v: X(A(i32).F);\n}\n```\n\nThis may require extra work to handle in the toolchain. In particular, we\ncurrently cannot form a specific for the class definition until the class is\ncomplete. We have at least two viable implementation strategies to handle this:\n\n-   Ensure all declarations that can be nested within a type have their own\n    corresponding generic. This is already the case for most such declarations,\n    with field declarations and alias declarations being notable exceptions.\n-   Support evaluating an incomplete eval block for a generic, and finish\n    evaluating each incomplete eval block at the end of the generic definition.\n\n## Rationale\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   This change removes an ergonomic hurdle and an inconsistency in the\n        language rules.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   This rule is more closely aligned with the C++ rule for lookup of class\n        members within the class definition, which allows members to be named\n        before the class is complete.\n\n## Alternatives considered\n\n### Require completeness for qualified name lookup\n\nThe status quo ante is to disallow qualified access into types until they are\ncomplete. The rationale for rejecting that alternative is described in this\nproposal.\n\n### Do not require a definition for name lookup\n\nWe could permit qualified and unqualified name lookup into types that are merely\ndeclared and not yet defined. Such a lookup would find nothing. This allowance\ncould be used in a case where a type's scope can be extended before the type is\ndefined, which is itself currently not permitted. For example:\n\n```carbon\ninterface I;\ninterface J {\n  let T:! type;\n}\n\ninterface K {\n  extend I;\n  extend J;\n  let Unqual:! T;\n  let Qual:! K.T;\n}\n```\n\nWe could choose to permit this, and make the lookups for the name `T` in the\nscope of `I` find nothing and poison the name `T` in `I`, so that the name can\nbe resolved immediately to `J.T`. If `I` were to later introduce a name `T`,\nthat would result in an error.\n\nHowever, this seems like it may be a step too far, and isn't justified by the\nmotivations for this change. From an implementation standpoint, it would also\nrequire tracking a list of poisoned names in a type that doesn't even have a\nscope yet, although that is likely straightforward to handle.\n"
  },
  {
    "path": "proposals/p5164.md",
    "content": "# Updates to pattern matching for objects\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5164)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Alternative approaches for declaring movable bindings](#alternative-approaches-for-declaring-movable-bindings)\n        -   [Treat all bindings under `var` as variable bindings](#treat-all-bindings-under-var-as-variable-bindings)\n        -   [Make `var` a binding pattern modifier](#make-var-a-binding-pattern-modifier)\n    -   [Alternative approaches to the other problems](#alternative-approaches-to-the-other-problems)\n        -   [Initialize storage once pattern matching succeeds](#initialize-storage-once-pattern-matching-succeeds)\n        -   [Allow variable binding patterns to alias across `case`s](#allow-variable-binding-patterns-to-alias-across-cases)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal re-affirms (with additional rationale) that a `var` pattern\ndeclares a durable complete object, and refines the terminology for binding\npatterns in a `var` pattern to be more explicit about the intended semantics. It\nalso makes several other changes and clarifications to the semantics of pattern\nmatching on objects:\n\n-   The storage for a variable pattern is initialized eagerly, rather than being\n    deferred until the end of pattern matching.\n-   Any initializing expressions in the scrutinee of a `match` statement are\n    materialized before matching the `case`s.\n-   An initializing expression can only initialize temporary storage or a single\n    variable pattern, not a tuple/struct pattern or a subobject of a variable\n    pattern. Removing this limitation is left as future work.\n\nFinally, as a drive-by fix, it clarifies what parts of the `match` design are\nstill placeholders.\n\n## Problem\n\nDiscussions arising from the implementation of `var` patterns have surfaced some\nproblems with how pattern matching deals with objects:\n\n-   If binding patterns bind to subobjects of an enclosing `var` object,\n    destructively moving them will lead to double-destruction.\n-   Deferring initialization of variable bindings contradicts our specification\n    of copy/move elision, and makes `if`-guards much less useful.\n-   It was unclear what happens when a `match` statement's scrutinee is an\n    initializing expression, since the result of an initializing expression\n    can't be reused.\n-   It was unclear whether and how copy/move elision applies when initializing a\n    subobject of a variable binding or tuple/struct pattern.\n\nThe first point deserves some elaboration. We don't yet have a concrete proposal\nfor move semantics, but it's possible to discern the overall direction well\nenough to see a problem with how it interacts with `var`. The following sketch\nof move semantics should be considered a **placeholder**, not an approved\ndesign.\n\n`~x` is a _move_ from the reference expression `x`. It is an initializing\nexpression that initializes an object with the value that `x` held prior to the\nmove, while arbitrarily mutating `x` to make the move more efficient. By default\n`~x` is _destructive_, meaning that it ends the lifetime of `x`; under some\nconditions it may instead leave `x` in an\n[unformed state](/docs/design/README.md#unformed-state), or make a copy of `x`,\nbut only if the type supports doing so.\n\nConsider the following code, where `X` and `Y` are types that are movable but\nnot copyable, have nontrivial destructors, and do not have unformed states:\n\n```carbon\nfn A() -> (X, Y);\nfn B(var x: X);\n\nfn F() {\n  var (x: X, y: Y) = A();\n  B(~x);\n}\n```\n\nUnder the current design of pattern matching, the first line of `F` declares a\ncomplete object of type `(X, Y)`, and binds `x` and `y` to its elements. At the\nend of the body of `F`, that tuple object is still live, so its destructor will\nrun, which will recursively run the destructors for its elements. However, its\nfirst element was already destroyed by `~x`, so this would result in\ndouble-destruction of that sub-object.\n\nIn order to avoid that problem, the expression `~x` must be ill-formed. More\ngenerally, if a `var` pattern contains a tuple or struct subpattern, the\nbindings it declares cannot be moved from (unless, possibly, their types permit\nthem to be non-destructively moved, and/or safely destroyed twice). In order to\nbe well-formed, the first line of `F` must be rewritten as:\n\n```carbon\n  let (var x: X, var y: Y) = A();\n```\n\nThis makes the code more verbose, and may be surprising to users.\n\n## Proposal\n\nThe decision that `var` declares a single complete object is reaffirmed,\nnotwithstanding the problem described above. To be more explicit about the\nintended meaning, we will adjust the terminology:\n\n-   The term \"variable binding pattern\" is now limited to a binding pattern that\n    binds to the entire object declared by an enclosing `var` pattern.\n-   We introduce the term \"reference binding pattern\" to refer to any binding\n    pattern that has an enclosing `var` pattern. Thus, every variable binding\n    pattern is a reference binding pattern, but not vice-versa.\n\nTo address the other problems:\n\n-   The storage for a variable binding pattern is initialized eagerly, rather\n    than being deferred until the end of pattern matching.\n-   Any initializing expressions in the scrutinee of a `match` statement are\n    materialized before matching the `case`s.\n-   An initializing expression can only initialize temporary storage or a single\n    variable binding, not a tuple/struct pattern or a subobject of a variable\n    binding. Removing this limitation is left as future work.\n\n## Alternatives considered\n\n### Alternative approaches for declaring movable bindings\n\nSee\n[leads issue #5250](https://github.com/carbon-language/carbon-lang/issues/5250)\nfor further discussion of this problem.\n\n#### Treat all bindings under `var` as variable bindings\n\nWe could treat all bindings under a `var` pattern as variable bindings, instead\nof limiting that to the case of a single binding pattern immediately under the\n`var` pattern. This would mean that all such bindings declare complete objects,\nand hence are movable. By the same token, it would mean that a `var` pattern\ndoes not declare a complete object.\n\nHowever, we are likely to eventually need a way for a pattern to declare a\ncomplete object and bind names to its parts, for example to support Rust-style\n[@-bindings](https://doc.rust-lang.org/book/ch19-03-pattern-syntax.html#-bindings)\nor to support in-place destructuring of user-defined types (where destroying the\nobject in order to make its subojects movable could have unwanted side effects).\nThis approach would make it difficult to do that with good ergonomics, because\nboth `var` and the hypothetical complete-object pattern syntax would change the\nmeanings of nested bindings, and the behavior of destructuring, in conflicting\nways.\n\nThis approach also expresses the programmer's intent less clearly, which could\nharm readability, because a `var` with several nested bindings could be intended\nto make those bindings movable, or just to make them mutable.\n\nThat also makes this option less future-proof. If we start with this approach\nand later migrate to the status quo because we need the extra expressive power,\nwe would need to somehow infer the missing intent information. Conversely, if we\nstart with the status quo and later conclude we aren't going to make its extra\nexpressive power observable, existing valid code will remain valid, with the\nsame behavior, after switching to this approach.\n\nThe only major advantage of this approach over the status quo is that it's less\nverbose when declaring multiple movable bindings, and may be less surprising to\nusers because it's less restrictive by default. However, those advantages aren't\nsignificant enough to offset those costs.\n\n#### Make `var` a binding pattern modifier\n\nThe current design makes binding patterns fairly context-sensitive, which we\ngenerally [try to avoid](/docs/project/principles/low_context_sensitivity.md): a\nbinding pattern declares a variable binding pattern if it's the immediate child\nof a `var` pattern, a non-variable reference binding pattern if it's an indirect\ndescendant of a `var` pattern, and a value binding pattern otherwise.\n\nWe could avoid context-sensitivity by making `var` a modifier on binding\npatterns, like `template`. That would mean there are no reference binding\npatterns, and the distinction between variable and value binding patterns is\nalways purely local.\n\nHowever, allowing `var` to apply to many bindings at once improves the\nergonomics of destructuring into variables, which is likely to be a common use\ncase. Furthermore, the offsetting costs of allowing that are fairly minimal:\n\n-   We are likely to eventually need reference bindings anyway, so introducing\n    those semantics now isn't adding a cost, it's just incurring that cost\n    sooner.\n-   The cost of context-sensitivity in patterns is comparatively low, because\n    patterns are generally quite small, and there's rarely much need to factor\n    subpatterns out of their initial context.\n\n### Alternative approaches to the other problems\n\n#### Initialize storage once pattern matching succeeds\n\nPrior to this proposal, the status quo was that the storage associated with a\npattern is not initialized until we know that the complete pattern matches. This\nhelps avoid situations where a `case` that does not match nevertheless has\nvisible side effects. However, this approach has several major drawbacks:\n\n-   It contradicts or at least greatly complicates the guarantee that\n    declarations like `var x: X = F();` do not require any temporary storage,\n    because it would imply that `F()` is not even evaluated until we know the\n    pattern matches. That's feasible for irrefutable patterns like this one, but\n    not for refutable patterns. Even if we were willing to limit that guarantee\n    to contexts that require irrefutable patterns, it would complicate the\n    implementation, because the underlying logic would have major structural\n    differences in the two cases.\n-   It precludes using a variable binding before its enclosing complete pattern\n    is known to match, because that variable would not be initialized. In\n    particular, that means an\n    [`if`-guard](/docs/design/pattern_matching.md#guards) cannot use variable\n    bindings from the pattern it guards. Practically all the motivating use\n    cases for `if`-guards involve using bindings from the guarded pattern, so\n    this is tantamount to making `var` and `if` mutually exclusive.\n\n#### Allow variable binding patterns to alias across `case`s\n\nConsider the following code:\n\n```carbon\nfn F() -> X;\nfn G() -> i32;\n\nmatch ((F(), G())) {\n  case (var x: X, 0) => { ... }\n  case (var x: X, 1) => { ... }\n  case (var x: X, 2) => { ... }\n  case (var x: X, 3) => { ... }\n  ...\n}\n```\n\nUnder this proposal, the result of `F()` is materialized in temporary storage,\nand then copied into the storage for `x` as part of matching each `case` (it\ncan't be moved, because it must remain available for the next `case`). As a\nresult, this code may make as many copies of `X` as there are `case`s, and\ndoesn't even compile if `X` isn't copyable.\n\nWe could instead treat those `var x: X` declarations as aliases for the\nmaterialized temporary. However, in order to generalize that approach we would\nneed to answer questions like:\n\n-   Do the bindings alias between `case (var x: X, 0)` and `case var (x: X, 1)`?\n-   Do the bindings alias if their names are different?\n-   Do the bindings alias if the two `case`s are separated by another `case`\n    that doesn't have a binding in that position?\n-   Do the bindings alias if they have the same type as each other, but not the\n    same type as the scrutinee?\n\nFurthermore, the behavior of these rules would need to be intuitive and\nunsurprising, because any change that prevents aliasing (in even one case) could\nbreak the build or cause surprising performance changes.\n\nEven in the best case, this approach is inherently limited. If the bindings have\ndifferent types, at most one of them can be an alias for the scrutinee; the\nother must be initialized by a copying conversion.\n\nThis approach would open up the possibility of a non-taken `case` mutating the\nstate of the scrutinee, by invoking a mutating operation on a variable binding\nin an expression pattern or an `if`-guard. We may be able to statically forbid\nsuch mutations, but that will be easier to assess once we understand the role of\nmutability in our broader safety story.\n\nWe conjecture that in most if not all cases where aliasing would be desirable,\nit will be straightforward to rewrite the code to avoid the problem. For\nexample, the example above can be rewritten as:\n\n```carbon\nfn F() -> X;\nfn G() -> i32;\n\nvar x: X = F();\nmatch (G()) {\n  case 0 => { ... }\n  case 1 => { ... }\n  case 2 => { ... }\n  case 3 => { ... }\n  ...\n}\n```\n\nWe can revisit this alternative if that conjecture turns out to be incorrect in\npractice.\n"
  },
  {
    "path": "proposals/p5168.md",
    "content": "# Forward `impl` declaration of an incomplete interface\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5168)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Related work and past discussion](#related-work-and-past-discussion)\n    -   [Terminology](#terminology)\n    -   [Other considerations](#other-considerations)\n-   [Proposal](#proposal)\n    -   [Prior to this proposal](#prior-to-this-proposal)\n    -   [Proposed rules](#proposed-rules)\n-   [Details](#details)\n    -   [An `impl` implements a single interface](#an-impl-implements-a-single-interface)\n    -   [Associated constants may be assigned in the body of an `impl` definition](#associated-constants-may-be-assigned-in-the-body-of-an-impl-definition)\n    -   [An `impl` may be forward declared without the interface being complete](#an-impl-may-be-forward-declared-without-the-interface-being-complete)\n    -   [Interface requirements](#interface-requirements)\n    -   [Examples](#examples)\n-   [Future work](#future-work)\n    -   [Addressing the subsumption use case previously addressed by `extend` in interfaces](#addressing-the-subsumption-use-case-previously-addressed-by-extend-in-interfaces)\n    -   [Opt-in to using the interface's default definition of an associated function](#opt-in-to-using-the-interfaces-default-definition-of-an-associated-function)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Allow implementing multiple interfaces with a single `impl` declaration](#allow-implementing-multiple-interfaces-with-a-single-impl-declaration)\n    -   [An `impl` of an interface also implements the interfaces it extends](#an-impl-of-an-interface-also-implements-the-interfaces-it-extends)\n    -   [Use the contents of definitions if available](#use-the-contents-of-definitions-if-available)\n    -   [Delayed checking of incomplete types](#delayed-checking-of-incomplete-types)\n    -   [Allow `impl` declarations with rewrites of defined but not complete interfaces](#allow-impl-declarations-with-rewrites-of-defined-but-not-complete-interfaces)\n    -   [Can omit function declarations from `impl` body](#can-omit-function-declarations-from-impl-body)\n    -   [Different introducer for assigning associated constants in an `impl` definition](#different-introducer-for-assigning-associated-constants-in-an-impl-definition)\n\n<!-- tocstop -->\n\n## Abstract\n\nRevise rules for what is required and provided by declarations and definitions\nof interfaces and impls. In particular:\n\n-   allow `impl` declarations of incomplete interfaces, and\n-   shift from a \"use the information from the type definition if it happens to\n    be complete\" model to a \"only use the information from the definition in\n    contexts where it is required to be defined or complete\" model.\n\nResolves questions-for-leads issues\n[#4566](https://github.com/carbon-language/carbon-lang/issues/4566),\n[#4672](https://github.com/carbon-language/carbon-lang/issues/4672),\n[#4579](https://github.com/carbon-language/carbon-lang/issues/4579).\n\n## Problem\n\nThere are several kinds of entities in Carbon, and most of them support separate\nforward declaration from definition. You might declare an entity before defining\nit for a few reasons:\n\n-   Non-generic runtime functions may be called using only a declaration in an\n    api file, as long as they are defined in the corresponding impl file. This\n    hides implementation details, and allows build work to be parallelized by\n    way of separate compilation.\n-   By\n    [the information accumulation principle](https://docs.carbon-lang.dev/docs/project/principles/information_accumulation.html),\n    we don't want code to rely on information written later in the file. For\n    example, names can't be used before the declaration that introduces that\n    name. This requires the developer to order their code in a way that\n    satisfies those constraints.\n\nFor example, functions and types (classes, interfaces, named constraints, and so\non) can reference the names of any kind of type in their declaration and\ndefinition.\n\nIn some cases, two types will reference each other, requiring forward\ndeclarations:\n\nA\n[more complex example with interfaces](/docs/design/generics/details.md#example-of-declaring-interfaces-with-cyclic-references)\ncan be found in the generics design, that requires introducing named constraint\nforward declarations to represent constraints that can't be expressed yet.\n\nWe don't want to create a situation where Carbon is introducing a lot of\n[accidental complexity](https://en.wikipedia.org/wiki/No_Silver_Bullet) into the\nprogramming process by creating a declaration ordering puzzle that is difficult\nor impossible to solve. We would like ordering rules that are straightforward to\nsatisfy, and simple to remember.\n\nThere are a few different options for ordering requirements, all of which have\ndownsides:\n\n-   Light requirements are easy to satisfy, but don't provide as much\n    information to use. For example, if you don't require that an interface is\n    defined at a point, then you can't use the interface requirements from its\n    definition.\n-   Strong requirements are difficult to satisfy, and in the worst case can\n    create dependency cycles that can't be satisfied at all.\n-   We could have light requirements, but then use additional information when\n    it is available. This creates complexity. There is complexity in the\n    implementation since there are many cases to consider, and if something goes\n    wrong it could be for many different possible reasons. It increases the\n    danger of introducing coherence concerns, where reordering declarations and\n    definitions could change the meaning of the code. This gives some\n    (situational) flexibility to the developer to solve ordering problems.\n\nThe design prior to this proposal often uses this last option, creating\nimplementation complexity. We would like to find an alternate approach that\ngives similar flexibility without the downsides.\n\n## Background\n\n### Related work and past discussion\n\n-   [Proposal #722](https://github.com/carbon-language/carbon-lang/pull/722):\n    Nominal classes and methods\n-   [Proposal #818](https://github.com/carbon-language/carbon-lang/pull/818):\n    Constraints for generics (generics details 3)\n    -   Introduced implied constraints.\n-   [PR #1026](https://github.com/carbon-language/carbon-lang/pull/1026):\n    Clarify class declaration syntax\n-   [Proposal #1084](https://github.com/carbon-language/carbon-lang/pull/1084):\n    Generics details 9: forward declarations\n    -   See\n        [the section in the generic details design document](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#forward-declarations-and-cyclic-references)\n-   [Proposal #2760](https://github.com/carbon-language/carbon-lang/pull/2760):\n    Consistent class and interface syntax\n-   [Proposal #3762](https://github.com/carbon-language/carbon-lang/pull/3762):\n    Merging forward declarations\n-   [Proposal #3763](https://github.com/carbon-language/carbon-lang/pull/3763):\n    Matching redeclarations\n    -   Updated the rules of `impl` declarations and matching\n-   [Proposal #3980](https://github.com/carbon-language/carbon-lang/pull/3980):\n    Singular extern declarations\n-   [PR #4230](https://github.com/carbon-language/carbon-lang/pull/4230): Add\n    documentation for entity declaration design work\n-   Pending\n    [leads question #4566](https://github.com/carbon-language/carbon-lang/issues/4566):\n    Implementing multiple interfaces with a single impl definition\n    -   The currently proposed resolution includes `impl`ing an interface does\n        not `impl` the interfaces it `extend`s, reducing the need to see the\n        `interface` definition in `impl` declarations.\n-   Pending\n    [leads question #4579](https://github.com/carbon-language/carbon-lang/issues/4579):\n    When are interface requirements enforced for an `impl`?\n    -   Considers what is required and provided by `impl` forward declarations\n        and definitions. This proposal offers a resolution to these questions.\n-   Pending\n    [leads question #4672](https://github.com/carbon-language/carbon-lang/issues/4672):\n    Declaration and definition of impls and their associated functions\n    -   The currently proposed resolution includes moving assignment of\n        associated constants into the `impl` definition in the normal case,\n        reducing the need to see the `interface` definition in `impl`\n        declarations.\n-   [Proposal #5087](https://github.com/carbon-language/carbon-lang/pull/5087):\n    Qualified lookup into types being defined\n    -   Allows member access inside a type's definition, in addition to\n        afterwards. Introduces the _defined_ terminology.\n\n### Terminology\n\n-   A _declaration_ specifies information about an entity. Declarations are\n    either _forward declarations_ (which generally end with a semicolon `;`) or\n    _definitions_ (which generally end with a body enclosed in curly braces\n    `{`...`}`).\n-   We say an entity is _declared_ by the first declaration textually in the\n    source. If that declaration is a definition, we say the entity is declared\n    at the point the body begins (at the open curly `{`).\n-   We say an entity is _defined_ once the body of its definition is started (at\n    the open curly `{`). We allow name lookup into an entity once it is defined.\n    See\n    [proposal #5087: Qualified lookup into types being defined](https://github.com/carbon-language/carbon-lang/pull/5087).\n-   We say an entity is _complete_ at the end of its definition (at the close\n    curly `}`).\n-   We say a facet type is _identified_ if all the interfaces it references are\n    declared and all of its named constraints are complete. An identified facet\n    type is associated with a known set of interfaces.\n-   An _implied constraint_ is a condition that must hold if a type is used in a\n    given type expression, which we enforce in some way other than checking that\n    the condition holds at that point. For example:\n\n    ```\n    interface Hash { ... }\n    class HashSet(T:! Hash) { ... }\n\n    // `U` must satisfy the constraints on the `T` parameter to `HashSet`.\n    // In this case, we enforce it using an implied constraint, so we don't\n    // require `U impls Hash` beforehand (say by being declared `U:! Hash`).\n    fn Contains[U:! type](needle: U, haystack: HashSet(U)) -> bool;\n    // In this case, `Contains` is equivalent to this declaration that\n    // doesn't use implied constraints:\n    fn Contains[U:! type where .Self impls Hash]\n               (needle: U, haystack: HashSet(U)) -> bool;\n\n    // In this example, the implied constraint is on something more\n    // complicated than a single symbolic parameter.\n    fn F[V:! type, W:! type](x: HashSet(Pair(V, W)));\n    // is equivalent to:\n    fn F[V:! type, W:! type where Pair(V, .Self) impls Hash]\n        (x: HashSet(Pair(V, W)));\n    ```\n\n    -   We generally require that there always be a way to explicitly declare\n        constraints so implied constraints are not needed.\n    -   Implied constraints allow declarations to be more concise, particularly\n        we hope that common requirements can be omitted since they are implied.\n    -   Implied constraints are also a tool we can choose to use to say that a\n        requirement on a parameter can be enforced at a later point. In this\n        example,\n\n        ```\n        interface B {}\n        interface A;\n        class C(T:! B);\n        fn F(U:! A, x: C(U));\n\n        interface A {\n        require Self impls B;\n        }\n        ```\n\n        the symbolic type parameter `U` has a constraint that it impls `A`, and\n        we can add an implied constraint that it also impls `B` because it is\n        used as an argument to `C`. This constraint might be redundant with a\n        requirement from the definition of `A`, which may or may not have been\n        available at the point where `F` is declared. Callers have to provide\n        arguments that satisfy the additional requirement if it turns out that\n        `A` alone is not sufficient.\n\n### Other considerations\n\nDifferent kinds of entities have different requirements (ignoring `extern`\ndeclarations):\n\n-   A compile-time function must be defined before a call to it is evaluated.\n-   A generic function must be defined before the end of each file in which a\n    call to it is type-checked.\n-   Non-generic runtime functions may be defined separately. They may be forward\n    declared in an api file and defined in a corresponding impl file.\n-   Types must be complete before they are used in a function definition. This\n    includes the parameter types, the return type, the argument types of\n    functions that are called in the body, and the types of local variables.\n-   Interfaces and named constraints must be defined in the same file they are\n    declared.\n-   We want to allow some uses of classes that are declared in an api file and\n    defined in a corresponding impl file -- in particular, we treat the \"pointer\n    to `C`\" type `C*` to be complete even if `C` is not.\n\nOur main tool for making ordering easier is forward declarations. Declarations\nnecessarily come after all the declarations of entities named in its parameter\nand return types. So declarations need to be ordered in some\n[topological sorted order](https://en.wikipedia.org/wiki/Topological_sorting)\nthat respects those dependencies. This is unavoidable, though, as long as we are\nnot allowing forward references, following\n[the information accumulation principle](https://docs.carbon-lang.dev/docs/project/principles/information_accumulation.html).\n\nDefinitions will have all the dependencies of a declaration, plus perhaps some\nmore. As a result we will want to put them later in the file. This is possible\nif a forward declaration is good enough for other declarations to use that name\nin all the ways that they need to.\n\n## Proposal\n\nThe goal is to allow forward declarations in more situations, and allow them to\nsatisfy requirements in more situations. In particular, we make these changes:\n\n-   We accept the proposed resolution of\n    [leads question #4566](https://github.com/carbon-language/carbon-lang/issues/4566):\n    -   An `impl` of an interface `I` does not `impl` any interface `I` extends.\n    -   A single `impl` can be for only a single interface.\n-   We accept the proposed resolution of\n    [leads question #4672](https://github.com/carbon-language/carbon-lang/issues/4672):\n    -   Assignment of associated constants is moved into the `impl` definition\n        in the normal case, though may still be present in a `where` clause at\n        the end of the declaration.\n    -   Associated constants are assigned using `where X = value;` declarations,\n        with semantics matching rewrite constraints in `where` clauses.\n    -   No part of the `impl` declaration will be excluded from syntactic match.\n    -   Every `impl` must be defined in the same file (not just the same\n        library) as its declaration.\n        -   However, the definitions of its member functions may be separate in\n            the impl file, out of line, as provided in\n            [proposal #3763](/proposals/p3763.md#out-of-line-definitions-of-associated-functions).\n-   An `impl` may be forward declared without the interface being defined.\n    -   This is enabled by not needing access to the definition to see other\n        interfaces required or extended or to see the associated constants that\n        need to be given values.\n    -   Instead we require the interface to be _identified_. This means that if\n        the facet type to the right of the `as` is given by a named constraint,\n        that named constraint needs to be complete so we can see which interface\n        it corresponds to. (It is an error if it doesn't correspond to a single\n        interface, by the resolution of\n        [#4566](https://github.com/carbon-language/carbon-lang/issues/4566).)\n    -   However, an `impl` declaration of a facet type with `.A =`... rewrite\n        constraints (for example in a `where` clause), does still require the\n        interface to be complete.\n-   We answer questions from\n    [leads issue #4579](https://github.com/carbon-language/carbon-lang/issues/4579):\n    -   Since `impl` forward declarations do not require the interface to be\n        defined, any requirements that other interfaces be defined from the\n        interface definition are ignored.\n    -   An `impl` definition of an interface `I` requires first establishing\n        that the type implements any interfaces required by `I`, but that can be\n        satisfied by an `impl` declaration.\n-   We shift from a \"use the information from the type definition if it happens\n    to be complete\" model to a \"only use the information from the definition in\n    contexts where it is required to be defined or complete\" model\n    -   However, an interface `I` containing a `require Self impls J` or\n        `extend J` declaration adds a fact that \"types `T` satisfying\n        `T impls I` also satisfy `T impls J`\" to the environment.\n\nThese changes are intended to allow developers to write their api files in an\norder that roughly follows:\n\n-   namespace declarations in any order;\n-   other declarations in any topological dependency order;\n-   type (interface, constraint, class) definitions in any order;\n-   impl definitions in any order;\n-   function definitions, including both those that are needed in the api file\n    plus those the developer wishes to include, in any order.\n\nThis would be sufficient except we have a few additional constraints, which\nremain:\n\n-   Performing member access into a type requires the type to be defined, not\n    just declared.\n-   Members of an effectively final impl may only be accessed after their value\n    has been established.\n-   A function that is called at compile time must be defined before that call\n    is executed by the compiler.\n\n### Prior to this proposal\n\n|                                                                                     | prereq                                                                                 | provides                                                                               | complete by [EOF](https://en.wikipedia.org/wiki/End-of-file) |\n| :---------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | :----------------------------------------------------------- |\n| `impl C as Y;`                                                                      | **`Y` complete**                                                                       | `C impls Y`                                                                            |                                                              |\n| `impl C as Y where .A =` ...                                                        | `Y` complete                                                                           | `C impls Y`                                                                            |                                                              |\n| `impl C as Y {` ... `}`                                                             | `Y` complete                                                                           | `C impls Y`                                                                            | `C`                                                          |\n| `interface I;`                                                                      |                                                                                        | `I` declared                                                                           | `I`                                                          |\n| `interface Y {` <br> ` require Self impls Z;` <br> `}`                              | **`Z` declared**                                                                       | **`Y` complete**                                                                       | `Z`                                                          |\n| `interface Y {` <br> ` require Self impls Z;` <br> `}` <br> `impl C as Y {` ... `}` | **open question [\\#4579](https://github.com/carbon-language/carbon-lang/issues/4579)** | **open question [\\#4579](https://github.com/carbon-language/carbon-lang/issues/4579)** |                                                              |\n| `fn F[T:! I](x: T);`                                                                | `I` declared                                                                           |                                                                                        | `F`, `I`                                                     |\n| `fn F[T:! I](x: T) {` ... `}`                                                       | `I` complete                                                                           | `F` complete                                                                           |                                                              |\n| `interface I;` <br> `class C;` <br> `class D(T:! I);` <br> `fn F(x: D(C));`         | `C impls I`                                                                            |                                                                                        | `I`, `C`?, `D`                                               |\n| `interface I;` <br> `class D(T:! I);` <br> `fn F[U:! type](x: D(U));`               |                                                                                        | `U impls I` <br> (implied constraint)                                                  | `I`, `D`, `F`                                                |\n\n### Proposed rules\n\n|                                                                                     | prereq             | provides                                                                               | complete by [EOF](https://en.wikipedia.org/wiki/End-of-file) |\n| :---------------------------------------------------------------------------------- | :----------------- | :------------------------------------------------------------------------------------- | :----------------------------------------------------------- |\n| `impl C as Y;`                                                                      | **`Y` identified** | `C impls Y`                                                                            | **`Y`, `impl C as Y`**                                       |\n| `impl C as Y where .A =` ...                                                        | `Y` complete       | `C impls Y`                                                                            | **`impl C as Y` ...**                                        |\n| `impl C as Y {` ... `}`                                                             | `Y` complete       | `C impls Y`                                                                            | `C`                                                          |\n| `interface I;`                                                                      |                    | `I` declared                                                                           | `I`                                                          |\n| `interface Y {` <br> ` require Self impls Z;` <br> `}`                              | **`Z` identified** | **for any symbolic type `T`, <br> `T impls Y` implies `T impls Z`; <br> `Y` complete** | `Z`                                                          |\n| `interface Y {` <br> ` require Self impls Z;` <br> `}` <br> `impl C as Y {` ... `}` | **`C impls Z`**    | **`C impls Y`**                                                                        |                                                              |\n| `fn F[T:! I](x: T);`                                                                | `I` declared       |                                                                                        | `F`, `I`                                                     |\n| `fn F[T:! I](x: T) {` ... `}`                                                       | `I` complete       | `F` complete                                                                           |                                                              |\n| `interface I;` <br> `class C;` <br> `class D(T:! I);` <br> `fn F(x: D(C));`         | `C impls I`        |                                                                                        | `I`, `C`?, `D`                                               |\n| `interface I;` <br> `class D(T:! I);` <br> `fn F[U:! type](x: D(U));`               |                    | `U impls I` <br> (implied constraint)                                                  | `I`, `D`, `F`                                                |\n\n> Whether classes need to be complete by the end of the file is not the subject\n> of this proposal.\n\n## Details\n\n### An `impl` implements a single interface\n\nWe resolve\n[leads question #4566](https://github.com/carbon-language/carbon-lang/issues/4566)\nwith two rules:\n\n-   Implementing an interface does not implement any of the interfaces it\n    extends.\n-   An impl declaration should implement a single interface.\n\nWe allow facet type expressions to the right of `impl`...`as`, as long as that\nfacet type corresponds to a single interface (ignoring interfaces it extends,\nwhich incidentally seems to\n[match Rust supertraits](https://stackoverflow.com/questions/75847426/why-do-we-need-a-separate-impl-for-a-supertrait)).\nThis supports the use case of `Core.Add` actually being a named constraint\ndefined in terms of `Core.AddWith`. This requires that the facet type is\nidentified, at a minimum, when used in an `impl` declaration, so it can be\nresolved into the single interface actually being implemented.\n\nThe \"subsumption\" use case of \"when an interface X is implemented, Y will be\nimplemented without the user having to write a separate impl definition\" will\ninstead be handled using\n[blanket implementations](/docs/design/generics/details.md#blanket-impl-declarations).\nThere are a couple of variations:\n\n-   One interface is a strict superset of the other. In this case it would be a\n    lot less confusing/surprising if the interfaces use the same implementations\n    of functions that overlap. This is accomplished using a\n    [`final`](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/generics/details.md#final-impl-declarations)\n    blanket implementation. For example, we will define\n    `final impl forall [T:! type, U:! ImplicitAs(T)] U as As(T)` and have\n    `As(T).Convert` forward to `ImplicitAs(T).Convert`. This way types will\n    either implement `ImplicitAs(T)` or `As(T)`, and will get an error if they\n    try to implement both.\n\n-   One interface can be implemented in terms of the other. For example, if\n    `Ordered` implies an implementation of `IsEqual`, types might still want to\n    provide an explicit definition of `IsEqual` when they can do so more\n    efficiently. This would use a non-`final` blanket implementation.\n\nNote that the orphan rule prevents this blanket impl from being written unless\nthe two interfaces in a subsumption relationship are in the same library.\nSupport for these use cases is\n[future work](#addressing-the-subsumption-use-case-previously-addressed-by-extend-in-interfaces).\nFor now, `extend I;` in an interface definition continues to mean that `I` is\nrequired and the names of `I` are included as aliases, matching the meaning in\nnamed constraints, see \"interface extension\" in\n[proposal #553](https://github.com/carbon-language/carbon-lang/pull/553).\n\n### Associated constants may be assigned in the body of an `impl` definition\n\nWe resolve\n[leads question #4672](https://github.com/carbon-language/carbon-lang/issues/4672)\nwith the following updated rules:\n\n-   The `impl` definition must be in the same file as its owning declaration.\n-   The first declaration establishes that the type implements the interface.\n-   That declaration may optionally specify a subset of the associated constants\n    in a `where` clause. The `where` clause syntax is the same as before this\n    proposal, but the requirement that all associated constants be given their\n    final values (or accept their defaults where available) is removed.\n    -   This adds some flexibility to ordering, allowing a developer to say that\n        a type implements an interface before being able to specify the values\n        of its associated constants, while also allowing a subset to be\n        specified if some later declaration needs to access their values.\n-   Redeclarations of an `impl` no longer have any special treatment of `where`\n    clauses.\n    -   Each redeclaration is required to match syntactically, so all will have\n        the same `where` clause, if any.\n    -   The part between `impl` and the end of the declaration (marked by a `{`\n        or `;`) is the name of the `impl`. This will be used in places where we\n        want to name the `impl`, such as in an impl priority (\"match first\")\n        block or out-of-line definitions of `impl` members.\n-   Associated constant assignments should be encouraged to be placed in the\n    `impl` definition rather than in a `where` clause in the declaration, unless\n    needed in the declaration to resolve dependencies.\n    -   This makes the name of the `impl` shorter and easier to state.\n    -   The syntax for specifying the value of an associated constant in an\n        `impl` definition is `where X = value;`, just like a rewrite clause in a\n        `where` expression, except that `where` in this case is an introducer\n        rather than a binary operator, and the names of the associated constants\n        are in scope, so there is no need to prefix them with a period (`.`).\n-   The non-function associated constants are fixed at the closing curly `}` of\n    the `impl` definition. At that point, each associated constant that has not\n    been assigned a value is given its default value. If it does not have a\n    default, an error diagnostic is issued.\n-   The associated function declarations are fixed by the end of the `impl`\n    definition.\n    -   Only associated functions with defaults may be omitted from the `impl`\n        definition.\n    -   Not mentioning an associated function with a default in the `impl`\n        definition means the default version from the interface will be used.\n    -   Associated functions declared in the `impl` definition must have a\n        matching definition.\n    -   If the declared signature of an associated function in the `impl`\n        definition does not match the signature given in the `interface`\n        definition, but are compatible, a stub function that does the conversion\n        is generated to bridge between the two versions.\n-   Out-of-line function bodies are allowed in the impl file, even when the\n    `impl` definition is in the api file.\n    -   This parallels how function definitions are not part of the definition\n        of classes.\n-   Missing function body definitions are diagnosed at link time.\n\n### An `impl` may be forward declared without the interface being complete\n\nWe have removed the reasons to require that the interfaces being implemented are\ndefined for an `impl` forward declaration:\n\n-   We no longer need to see which interfaces are required or extended from the\n    definition of the interface, since the `impl` no longer implements those.\n-   We no longer need to see which associated constants are members of the\n    interface to see if a declaration specifies values for all of them.\n-   If a `where` clause is used in the declaration, the interface must be\n    defined in order to name the associated constants, but `where` clauses are\n    discouraged.\n\nHowever, if the facet type being implemented is a named constraint, we do need\nthat to be complete so we can resolve the interface it resolves to. (It is an\nerror if it doesn't correspond to a single interface, by the resolution of\n[#4566](https://github.com/carbon-language/carbon-lang/issues/4566).)\n\nThis means that generally we can establish that a type implements an interface\nright after they are both declared.\n\n### Interface requirements\n\n[Leads issue #4579](https://github.com/carbon-language/carbon-lang/issues/4579)\nconcerns itself with interfaces that require other interfaces to be implemented,\nas in:\n\n```\ninterface Z;\n\ninterface Y {\n  require Self impls Z;\n}\n```\n\nThere are two sides to this: what do you have to establish about `Z` before an\n`impl` declaration or definition that a type implements `Y`, and what does a\ndeclaration or definition that a type implements `Y` establish about `Z`?\n\nWe adopt the following rules:\n\n-   Since `impl` forward declarations do not require the interface to be\n    defined, any requirements that other interfaces be defined from the\n    interface definition are ignored.\n\n    ```\n    class C1;\n    // ✅ Allowed\n    impl C1 as Y;\n\n    // `class C1` and `impl C1 as Y` must be defined in the same file.\n    ```\n\n-   An `impl` definition of an interface `I` requires first establishing that\n    the type implements any interfaces required by `I`, but that can be\n    satisfied by an `impl` declaration.\n\n    ```\n    class C2;\n    // ❌ Invalid, must first establish `C2 impls Z`. Still invalid if\n    // `impl C2 as Z` appears later in the file.\n    impl C2 as Y {}\n\n    class C3;\n    // ✅ Allowed\n    impl C3 as Z;\n    impl C3 as Y {}\n\n    class C4;\n    // ✅ Allowed\n    impl C4 as Z {}\n    impl C4 as Y {}\n\n    // The classes and `impl C3 as Z` must be defined in the same file.\n    ```\n\nThis is is aligned with the shift from a \"use the information from the type\ndefinition if it happens to be complete\" model to a \"only use the information\nfrom the definition in contexts where it is required to be defined or complete\"\nmodel that this proposal this is switching to. To recapture some of that context\nsensitivity, we say that the definition of an interface with requirements, like\n`Y` above, introduces the extra information that \"symbolic types `T` that\nsatisfy `T impls Y` also satisfy `T impls J`.\"\n\nFor example:\n\n```\ninterface Z;\n\ninterface Y {\n  require Self impls Z;\n}\n\nclass C(T:! Z);\n\nclass D(U:! Y) {\n  // ✅ U impls Y so it also impls Z.\n  //\n  // Wouldn't use implied constraints here since `U` is\n  // from a containing scope.\n  fn F(x: C(U));\n}\n```\n\nThis rule only applies to symbolic types, since we want to only say that\nconcrete types implement an interface if we have a declared `impl` to witness\nthat fact. Symbolic types depend on the value of some generic parameters and we\naccept that some accesses of interface members will result in symbolic values\nthat will only have known values once concrete argument values are supplied for\nthe generic parameters. For concrete types, the access is performed immediately,\nand it is an error if we don't have an `impl` declaration we can point to with\nthe witness. For concrete types, there is no later point where an argument is\nsupplied to delay these checks. For example:\n\n```\ninterface Z;\n\ninterface Y {\n  require Self impls Z;\n}\n\nclass C(T:! Z);\n\nclass D {}\n\n// ✅ Allowed, since `impl` declarations are allowed for declared\n// entities. Interface requirements are not considered.\nimpl D as Y;\n\n// ❌ Error: D is not known to implement Z. The fact that Y\n// requires Z is not used since D is a concrete type.\nfn F(x: C(D));\n\n// Too late to affect the previous declaration, by the information\n// accumulation principle.\nimpl D as Z;\n```\n\nSimilarly, it is also an error to access a member of an `impl` of a concrete\ntype that doesn't have a known value, even if it is given a value later in the\nfile. For example:\n\n```\ninterface I {\n  let A:! type;\n  let B:! type;\n}\n\nfn F(T:! I) -> T.A;\n\nclass C {}\nclass D {}\n\nimpl C as I;\n\nfn G1() {\n  // ❌ Error: C impls I, but C.(I.A) is unknown.\n  var x: auto = F(C);\n  // ❌ Error: C.(I.A) is unknown.\n  let y: C.(I.A) = 0;\n  // ❌ Error: C.(I.B) is unknown.\n  let b: C.(I.B) = false;\n}\n\nimpl D as I where .A = i32;\n\nfn H() {\n  // ✅ Allowed: D.(I.A) = i32;\n  var x: auto = F(D);\n  var y: D.(I.A) = 0;\n  // ❌ Error: D.(I.B) is unknown.\n  let b: D.(I.B) = false;\n}\n\nimpl C as I {\n  where A = i32;\n  where B = bool;\n}\n\nfn G2() {\n  // ✅ Allowed: C.(I.A) = i32;\n  var x: auto = F(C);\n  let y: C.(I.A) = 0;\n  // ✅ Allowed: C.(I.B) = bool;\n  let b: C.(I.B) = false;\n}\n```\n\n### Examples\n\nThis example shows using incomplete entities following the rules of this\nproposal:\n\n```\ninterface X;\n\n// ✅ Allowed to use incomplete interfaces in function declarations.\nfn F(U:! X);\n\nclass C;\n\n// ✅ Allowed to use incomplete types and interfaces in impl declarations.\nimpl C as X;\n\ninterface Y;\n\ninterface X {\n  // ✅ Allowed to use an incomplete interface.\n  require Self impls Y;\n}\n\n// Classes must be defined before being used in a function definition.\nclass C { ... }\n\nfn G() {\n  // ✅ Allowed since C is complete and we have a declaration `impl C as X;`\n  F(C);\n}\n\n// The above declarations require that `interface Y`, `fn F` (since it is\n// generic), and `impl C as X` are defined in the same file.\ninterface Y { ... }\nfn F(U:! X) { ... }\n// Required for `impl C as X` definition.\nimpl C as Y;\nimpl C as X { ... }\nimpl C as Y { }\n```\n\nThis example demonstrates using associated constants and interface requirements:\n\n```\ninterface X2 {\n  let A:! type;\n  let B:! type;\n}\ninterface Y2 {\n  require Self impls X2;\n  // ✅ Allowed since `X2` is required and we can access\n  // its `A` member since `X2` is complete.\n  fn F() -> X2.A;\n}\n\nclass C2 {}\n\nimpl C2 as X2 where .A = i32;\n\n// ✅ Allowed since `C2` and `Y2` are complete, and\n// `C2 impls X2` so `C2` satisfies the requirement in `Y2`.\nimpl C2 as Y2 {\n  // ✅ Allowed since the value of `C2.(X2.A)` is known to\n  // be `i32`, even though `impl C2 as X2` is not complete.\n  fn F() -> i32;\n}\n\n// There needs to be a definition of `C2 as X2 where .A = i32`\n// in the same file. The `where` clause needs to be repeated\n// verbatim, since redeclaration requires a syntactic match.\nimpl C2 as X2 where .A = i32 {\n  // Remaining members of `X2` that do not have default\n  // values need to be assigned.\n  where B = i32;\n}\n```\n\n## Future work\n\n### Addressing the subsumption use case previously addressed by `extend` in interfaces\n\nWe do expect to have collections of interfaces that have a stronger \"extending\"\nrelationship than is provided by the current `extend` declaration in interfaces.\nFor example, a type implementing `ImplicitAs` should not have to have a separate\ndeclaration that it also implements `As`. Addressing this use case is out of\nscope of this proposal, though, and will be addressed in a future proposal. This\nfuture proposal may include:\n\n-   A feature to copy the members of an interface into another to make the\n    subsumption use case easier to write and involve less duplication.\n\n-   A feature to define an implementation of an interface in terms of another by\n    forwarding, for similar reasons.\n\n-   A `final` version of the `match_first`/`impl_priority` feature to resolve\n    conflicts when multiple interfaces want to subsume a common interface. We\n    likely want a feature like this for function overloading as well.\n\n-   Some way of handling an `impl` that could overlap with a `final impl`, but\n    doesn't in practice.\n\n-   Possible support for implementing multiple interfaces with a single impl\n    definition, as the result of using an `&` operator or named constraint to\n    the right of `as`, as in\n    [the considered alternative](#allow-implementing-multiple-interfaces-with-a-single-impl-declaration).\n\nFor now, we leave `extend` as meaning \"requires plus include aliases of the\nnames,\" matching the behavior in named constraints. But this will be\nreconsidered once we have support for this other use case.\n\n### Opt-in to using the interface's default definition of an associated function\n\nWe've considered that we may want to allow an `impl` to opt into using the\ndefault definition of a function from the interface by writing `= default;`\ninstead of an inline body in curly braces `{`...`}`. We will see if that is a\ndesirable construct to add with experience. This idea was suggested in\n[issue #4672](https://github.com/carbon-language/carbon-lang/issues/4672#issuecomment-2539845620).\n\n## Rationale\n\nThe specific solution was chosen to align with\n[the information accumulation principle](https://docs.carbon-lang.dev/docs/project/principles/information_accumulation.html).\nIn particular, allowing `impl` declarations for incomplete interfaces gives\nadditional flexibility to developers to satisfy those constraints.\n\nBy reducing the different behavior based on whether a previous declaration was a\ndefinition, this proposal reduces complexity in the toolchain and tools that\noperate on Carbon source code. This benefits the\n[Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\nand\n[Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n[Carbon goals](/docs/project/goals.md).\n\nThis is intended to also help humans have a simpler mental model of the\ncompiler, to help the\n[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\ngoal.\n\n## Alternatives considered\n\nThe trade offs and alternatives were discussed in\n[this document](https://docs.google.com/document/d/1NNhBU5tywGkeneLmTQ4DwHyCp5vYlwTiR_wmnjn9wnM/edit)\nand in open discussion meetings on these dates:\n\n-   [2025-02-07](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.6ziehwl15x6a)\n-   [2025-03-04](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.22fvs78tr2ej)\n-   [2025-03-05](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.x0brmxoi93n4)\n-   [2025-03-06](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.lsqxlvgwdvoh)\n-   [2025-03-13](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.lsufbqunqul0)\n-   [2025-03-18](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.v0stu27nansb)\n-   [2025-03-20](https://docs.google.com/document/d/1Iut5f2TQBrtBNIduF4vJYOKfw7MbS8xH_J01_Q4e6Rk/edit?resourcekey=0-mc_vh5UzrzXfU4kO-3tOjA&tab=t.0#heading=h.jagz2i1dynjx)\n\n### Allow implementing multiple interfaces with a single `impl` declaration\n\nThis was considered in\n[leads question #4566](https://github.com/carbon-language/carbon-lang/issues/4566).\nThere are definite use cases for this feature, particularly arising from\nevolution. For example, you might want to split an interface into two new\ninterfaces, and have a named constraint with the original name extend both so\nthat existing code continues to work the same. With this proposal, those changes\nwill be harder and have more steps.\n\nTwo specific approaches to implementing multiple interfaces were eliminated from\nconsideration in that issue:\n\n-   The \"all or nothing\" approach where the `impl` definition is used for all of\n    the interfaces, or none of them are. This would create too much uncertainty\n    about whether an `impl` is applicable, particularly since constraints in\n    generic code are not sensitive to whether something is specialized.\n-   The \"Constrained impls\" approach where an `impl` of multiple interfaces is\n    treated as a collection of `impl`s of the individual interfaces with the\n    additional constraint that no specialization changes the values of any\n    non-function associated constants of any of the interfaces. Those\n    constraints though are ultimately circular and not well defined.\n\nThe remaining \"independent impls\" approach seemed possible. In this approach an\nimpl of multiple interfaces is treated as a collection of impls of the\nindividual interfaces. In particular, the definition of a member of one\ninterface can assume that the other interfaces are implemented, but not that the\nassociated types (or other non-function associated constants) have expected\nvalues. This would introduce some complexities and a number of questions would\nneed to be answered around how a single `impl` definition would be split into\ndefinitions of the individual interfaces, how dependencies between those pieces\nwould be resolved, and how these restrictions would be exposed to the user in\ndiagnostics.\n\n### An `impl` of an interface also implements the interfaces it extends\n\nThis was the design before this proposal, but in\n[leads question #4566](https://github.com/carbon-language/carbon-lang/issues/4566)\nwe found a number of problems with that approach:\n\n-   A parameterized interface extending a non-parameterized interface, or an\n    interface with fewer parameters, leads to multiple implementations of the\n    extended interface.\n\n-   There are multiple possible semantics you might want, and having a single\n    `impl` does not provide the affordances for choosing between those options,\n    where one `impl` per interface would. For example, in\n    `impl forall [T:! type] C(T) as I & J where .(I.x) = i32 and .(J.y) = .(I.x)`,\n    if there is a specialization of `C(T)` for `I`, will `J.y` have the value\n    `i32` or the `I.x` from the specialization? In practice, the semantics of\n    rewrites mean that `.(I.x)` is replaced with `i32` at an early stage in the\n    compiler (to support things like `.(J.y) = .(I.x).D`), and so only the first\n    option is consistent. This is a particular concern for the \"Independent\n    impls\" option above. If this `impl` is split into two, then the different\n    possible meanings have different spellings:\n\n    -   `impl forall [T:! type] C(T) as J where .(J.y) = i32` means `J.y` will\n        be `i32` independent of any specialization of `C(T)` for `I`\n\n    -   `impl forall [T:! type where C(T) impls I] C(T) as J where .(J.y) = .(I.x)`\n        means `J.y` matches `I.x` even if `C(T)` is specialized\n\n    -   `impl forall [T:! type where C(T) impls (I where .x = i32)] C(T) as J where .(J.y) = .(I.x)`\n        means this impl won't be used unless `I.x` is `i32`. Note this last form\n        approximates the \"Constrained impls\" approach above, but with an\n        explicit ordering to determine the semantics, and the existing language\n        rules preventing the code from declaring cycles that would make it\n        ambiguous.\n\n-   If an interface `J` extends `I` but they are defined in distinct libraries,\n    there is no guarantee that an implementation of `J` belongs in the same\n    library as an implementation of `I` for the same type due to the orphan\n    rule.\n\n-   The current documented rule for which interfaces an impl implements is those\n    whose members are defined in the interface definition. This rule is\n    ambiguous for empty interfaces or interfaces where all the associated\n    functions have defaults. It also requires\n    [a lot of context](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/principles/low_context_sensitivity.md)\n    to answer that question (this was intentional, to allow options for\n    refactoring an interface without having to update implementations of it). In\n    addition to being the source of readability concerns, this muddies the\n    meaning of `impl` declarations, and make the compiler implementation much\n    trickier (the compiler can't say what an impl declaration provides at the\n    point where it is written, making it hard to give that declaration a clear\n    type in the SemIR).\n\n-   Ideas we considered to determine the interfaces implemented from only the\n    impl declaration ran into problems. Without being able to control which\n    interfaces an impl is defining, then it isn't clear how to handle\n    implementing two interfaces that have common interface they both extend\n    unless you implement them both in a single impl definition (which may not\n    even be possible due to the orphan rule). Another idea we had in this space\n    was a way to say \"this interface minus one of the interfaces it extends\"\n    (maybe `J \\ I`?).\n\nWe considered some restrictions on `extend` to address some of these concerns:\n\n-   Perhaps implementing an interface only implemented the interfaces it extends\n    that have to be defined in this library by the orphan rule.\n\n-   Perhaps an interface may only extend an interface defined in the same\n    library.\n\n-   Perhaps an interface may only be extended by a single interface. This\n    precluded motivating use cases for `extend`, though, like the subtyping\n    relationships between different kinds of graphs used in\n    [the Boost Graph library](https://docs.google.com/document/d/15Brjv8NO_96jseSesqer5HbghqSTJICJ_fTaZOH0Mg4/edit?resourcekey=0-CYSbd6-xF8vYHv9m1rolEQ&tab=t.0)).\n\nChanging the meaning of `extend` is left for a future proposal, when we address\n[the subsumption use case previously addressed by `extend` in interfaces](#addressing-the-subsumption-use-case-previously-addressed-by-extend-in-interfaces).\n\n### Use the contents of definitions if available\n\nIn the course of implementing the existing design, uses of \"TryToCompleteType\"\nfunction were found to be prone to leading to coherence issues. If being\nincomplete does not lead to an error, we need to establish that the results of\nthe definition appearing before and after that test are the same. When there\nwere multiple types involved, this led to an explosion of combinations to test.\nThe new model has less conditional logic, and as a result less complexity.\n\n### Delayed checking of incomplete types\n\nWe could delay checking uses of incomplete types until some later point, either\nwhen the type is complete, a use that requires that type to be complete, or the\nend of the file where we know the most about it. This is an option, and we might\nadopt it if we found that it was too hard in practice to satisfy the constraints\nadopted by this proposal. However it would significantly increase the complexity\nof the toolchain implementation, which would lead to a corresponding increase in\nthe difficulty of understanding how the code will be interpreted.\n\n### Allow `impl` declarations with rewrites of defined but not complete interfaces\n\nWe at first did not have a rule saying that `I` needed to be complete in\n`impl C as I where .X = ...`. The rationale was that accessing members of `I`\nonly needed `I` to be defined, not complete. However, an `impl` declaration\ninside the definition of the interface being implemented could ultimately never\nbe defined, even if we allowed the declaration. This is because the `impl`\ndefinition would have to be in a different scope than its declaration, as can be\nseen in this example that uses a lambda function to get a scope that can have an\n`impl` declaration inside an `interface` definition:\n\n```\ninterface I {\n  let U:! type;\n  default let T:! type = (fn() -> type {\n    class C { }\n\n    // ✅ Allowed since `I` is declared, with the exception that\n    // this requires a definition before the end of the file.\n    impl C as I;\n\n    // ✅ Would be allowed since `I` is defined, including its\n    // member `U`. Again this requires a definition in this file.\n    impl C as I where .U = C;\n\n    // ❌ Neither of the above impls may be defined:\n    // - Can't be defined here since `I` is not complete.\n    // - Can't define after `I` is complete, since redeclarations\n    //   must match syntactically and have no hope of naming this\n    //   `C` that way.\n    // - In general, the impl definition would have to re-enter the\n    //   same scope.\n    impl C as I where .U = C {}\n\n    return C;\n  })();\n}\n```\n\nThis simplifies the toolchain implementation of this feature, since it means we\ncan create an `impl` witness for declarations that use rewrite constraints with\nthe full knowledge of the interface's definition.\n\n### Can omit function declarations from `impl` body\n\nWe considered saying that an `impl` definition does not need to include\ndeclarations that are unchanged from the interface definition. However, this\nraised a number of questions and problems:\n\n-   The `interface` definition is in a different scope from the `impl`, and\n    potentially a different file. This, combined with the evolution problems of\n    depending on the specific token sequence used in the `interface` definition,\n    suggest that we would need a different matching rule that was semantic\n    instead of syntactic.\n-   Having a different declaration matching rule was anticipated as creating a\n    bunch of difficulties once function overloading is added to Carbon,\n    particularly overloaded functions in interfaces.\n-   Without a declaration in the `impl` body, there were a number of problems\n    resolving how to handle a function in the `impl` that was compatible with\n    but a different signature from the interface, and when that different\n    signature would be used.\n-   These issues seemed to magnify if the interface had a default definition for\n    the function.\n\n### Different introducer for assigning associated constants in an `impl` definition\n\nOther options we considered were `provides`, `alias`, and whatever we eventually\nchoose for [#5028](https://github.com/carbon-language/carbon-lang/issues/5028).\nWe ultimately liked matching how you would assign associated constants in the\ndeclaration using the `where` operator and a rewrite constraint, particularly\nsince we wanted to use the same semantics.\n"
  },
  {
    "path": "proposals/p5233.md",
    "content": "# Towards more async \"sync\"-ing\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5233)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Last Week In Carbon](#last-week-in-carbon)\n        -   [Discord channel to surface interesting topics](#discord-channel-to-surface-interesting-topics)\n    -   [Discussion / demo session every two months](#discussion--demo-session-every-two-months)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Keep the existing structure](#keep-the-existing-structure)\n    -   [Drop the discussion sessions entirely](#drop-the-discussion-sessions-entirely)\n    -   [Drop the weekly summaries entirely](#drop-the-weekly-summaries-entirely)\n    -   [Select a slightly different format or structure](#select-a-slightly-different-format-or-structure)\n\n<!-- tocstop -->\n\n## Abstract\n\nProposal to switch our week-to-week Carbon project development syncs to be more\nasync.\n\n-   Start of each week, create a summary of what happened last week.\n-   Publish this in GitHub discussions for async reading and further discussion.\n-   Stop our weekly meeting focused on these summaries.\n-   Start up a new discussion meetings every two months.\n    -   Structure will be a 10-minutes-or-less update, and a \"demo\".\n    -   Demo may be traditional: showcase a newly landed thing in Carbon.\n    -   Or demo may showcase an interesting top-of-mind language design\n        discussion.\n    -   Either way, goal will be to field lots of questions about the topic and\n        have a good discussion everyone understands, not to reach some\n        \"conclusion\" or \"decision\".\n\n## Problem\n\nThe weekly Carbon meeting is providing value by aggregating all the activity\nacross our forums and helping both active contributors and folks following the\nCarbon project keep up-to-date on the different discussions that take place.\n\nHowever, it has stopped being a forum with active discussions where we dive\ndeeply into any specific topics. The summaries are also presented live and\nsynchronously which isn't adding much value on top of having them written up in\nour notes.\n\nSomewhat tongue-in-cheek version of the problem: our weekly meeting in its\ncurrent format should probably be an email. ;]\n\nBut we don't want to just get rid of the meeting and lose the value of\naggregating activity across the project. We need a new structure that is closer\nto that of an email. And ideally, we should re-capture some of the discussion\nbenefits that we have had in the past.\n\n## Background\n\nCurrently, Carbon has a\n[weekly sync](https://github.com/carbon-language/carbon-lang/blob/trunk/CONTRIBUTING.md#:~:text=The%20weekly%20sync%2C%20where%20contributors%20are%20welcome.)\nmeeting for contributors, that opens with a detailed summary of all the\ndiscussions and activity over the past week.\n\n## Proposal\n\nWe propose to restructure our weekly sync meeting to be an asynchronous process\nthat still provides weekly cross-project and cross-contributor visibility. We\nsuggest a \"Last Week in Carbon\" structure based on the weekly summary structure\nwe are already using in our weekly syncs. But these will instead be posted\ntowards the beginning of the week in a GitHub Discussion thread.\n\nWe also suggest adding a less frequent discussion meetings with a structure\ndesigned to help elicit broader discussion across the community. We suggest a\ncadence based on the Carbon Copy newsletter of every two months. The start will\nbe a _very_ brief 10-minute update on major developments in the project, and\nthen a 45-minute \"demo\" of some kind. Anyone working on Carbon who has a good\nidea for something to demo can sign up to do so. If we don't have a technical\ndemo, we'll pick an active and interesting language design discussion and demo\nour language design process by having a small part of that discussion live.\nWe'll encourage everyone to ask any questions needed to follow along and focus\non letting folks understand a slice of what is happening in Carbon development\nover reaching a specific resolution or outcome.\n\n## Details\n\n### Last Week In Carbon\n\nThe goal is to base these heavily on the existing weekly sync meeting minute\nsummaries of discussion and activity in the Carbon project and weekly\nnewsletters like LLVM Weekly.\n\nNote, these should _not_ be prose newsletters. They should focus on structured\ninformation in a bulleted format that is easily skimmed.\n\nThe exact structure, process, and format used should be heavily driven by the\ncontributors producing these posts, but we suggest using a collaborative tool\n(docs) for drafting, and then posting the results to GitHub Discussions for\nbroader visibility and discussion. We also suggest that these be time boxed to a\nfew hours of work total and the content filtered as needed to fit that time box\nrather than pushing to include every topic for summarizing. Beyond that\nhigh-level guidance, the exact format is up to those authoring it. We do\nencourage authors to pull in other contributors to help wherever useful.\n\nWe specifically suggest that only issues-for-leads and proposals be\n_exhaustively_ summarized. Whoever is creating these summaries should use their\nown judgement to filter to the most relevant things to summarize while trying to\ncatch things that might otherwise be missed. As this is imperfect, we will also\ncreate some specific ways that individuals can help surface a specific thing\nthey would like to see included in these.\n\n#### Discord channel to surface interesting topics\n\nWe would like an easy way for folks to flag things that are interesting to\ninclude into the summaries, especially PRs that might otherwise be missed. We\nsuggest one or both of two options far flagging these:\n\n1. Create a dedicated discord channel that folks can post links / snippets to\n   that they find interesting.\n2. Create a discord channel that automatically gets bot postings for each PR\n   that is merged, and encourage folks to use reactions to signal interest in\n   that being included in the summary.\n\n### Discussion / demo session every two months\n\nThe goal is to provide an easy way for a much wider audience to follow along\nwith Carbon's development and get to see interesting details about how that\ndevelopment is progressing.\n\nWe suggest starting this off with a brief overview of project progress since the\nprevious session, but keep this overview _very_ brief: strictly less than 10\nminutes of the meeting.\n\nThen we suggest soliciting a specific \"demo\" of something recent and interesting\nin the project. These can take a wide variety of forms, but some primary ones we\nanticipate initially:\n\n-   Demo of recently working functionality in the toolchain (or a recent &\n    interesting bug).\n-   \"Demo\" of our design process by selecting a current and relevant discussion\n    topic and holding an initial discussion on that topic live for folks to\n    observe and participate if interested.\n\nWe will explicitly encourage folks to persistently ask questions for context and\nbackground they don't understand, as answering these questions is an effective\ninformal way of spreading basic understanding of Carbon as it develops.\n\nThe goal is not to resolve questions about the design or decide anything in\nthese sessions, but to give a wider audience an opportunity to see and join some\naspects of our development process periodically while also getting a very brief\nupdate on the overall project status.\n\nInitially we suggest scheduling these for every two months with the goal of\naligning them to newsletters. However, this is not a strict scheduling goal and\nwe should consider adjusting frequency as needed. We should also reschedule as\nneeded to maximize folks' availability and freely skip any where we don't have a\ngood demo ready-to-hand.\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   Creates a more timezone and working schedule inclusive way to track\n        Carbon progress week-over-week.\n    -   Creates a more easily accessed synchronous meeting by having it be\n        scheduled infrequently to minimize schedule disruption.\n    -   Makes the synchronous meeting a more welcoming and engaging environment\n        by focusing on a relevant topic and using a structure that lets people\n        engage in different ways.\n\n## Alternatives considered\n\n### Keep the existing structure\n\nWe could make no change, but there has been a consistent lack of fully utilizing\nthe current meeting structure and so it seems like some change is motivated\nbased on how people are engaging.\n\nThe current structure is also especially expensive for the team, and so it seems\nimportant to at least explore some alternatives that may open up better scaling,\neither in team size or timezones.\n\n### Drop the discussion sessions entirely\n\nA different approach would be to completely drop having a synchronous discussion\nmeeting. However, this would lose one of the historically impactful aspects of\nthe weekly meeting that we hope to recover with this approach: telegraphing to\nthe broader potential Carbon community (largely the existing C++ community) how\nwe are going about developing Carbon.\n\nWe have had several instances of specifically positive feedback from observers\nor more casual participants in historical weekly meetings where deeper design\ndiscussions took place or where we showcased specific issues or capabilities.\nHowever, these kinds of topics are not always available and so not something we\ncan sustain at the pace of every week.\n\nThe proposal picks the alternative of reducing the frequency and adjusting the\nstructure of the synchronous meeting to try and capture this value at a much\nmore sustainable cost and with a larger and more consistent audience. If the\naudience doesn't materialize or we get feedback that this impact isn't landing,\nwe should revisit this aspect of the structure.\n\n### Drop the weekly summaries entirely\n\nThis would lose the main value that we currently get from the weekly meeting,\nand one that many across the team have repeatedly cited: both a way to catch up\nand a way to avoid missing discussions happening in a forum or at a time that\nthey missed.\n\nKeeping this, and making it _even more_ asynchronous in nature, further our goal\nof making the Carbon development processes and community open and welcoming of\npeople from different locations, working on different schedules, or with\ndifferent levels of involvement.\n\n### Select a slightly different format or structure\n\nThere is a wide range of possible formats and structures for both weekly\nsummaries and a discussion meeting. This proposal picks two based on trying to\nclosely fit the distinct goals and value propositions of each component of our\nhistorically weekly meeting. But there are many others that could potentially be\nconsidered.\n\nCurrently, the suggestion is to try these out and iterate on these based on the\nexperience. When making this significant of a change it seems hard to predict\naccurately how the details will land, and simply selecting a plausible starting\nstructure is more important than getting the _best_ structure. We should make\nminor adjustments to both as needed based on our experience with the new format.\n"
  },
  {
    "path": "proposals/p5270.md",
    "content": "# Move explorer out of toolchain git repository\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5270)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use a branch to refer to the explorer codebase](#use-a-branch-to-refer-to-the-explorer-codebase)\n    -   [Do nothing](#do-nothing)\n\n<!-- tocstop -->\n\n## Abstract\n\nThe explorer codebase is no longer actively developed or maintained, but retains\nvalue as a place to look for implementations of various parts of the design.\nHaving both the explorer and toolchain in the working git repository causes\nconfusion for developers and users, and increases our incremental maintenance\nburden. We will move explorer out of the working git repository so that it\nremains accessible but is clearly deliniated from the toolchain and is more\nclearly frozen or archived.\n\n## Problem\n\nUsers have expressed confusion when they come across examples or tests for the\nexplorer that involve `Main()`, whereas the design and implementation of the\ntoolchain have moved on to `Run()` as the entry point.\n\nDevelopers have attempted to update the explorer codebase to fix style guide\nissues[^1], as tools like grep or clang-tidy do not differentiate our active\ntoolchain codebase from the frozen explorer one.\n\nAs we update Bazel, Clang, Clang-tidy, etc, we also have to update the explorer\ncodebase to keep it building cleanly.\n\nAs we modify the `//testing` harness, we have to accommodate and work around the\nexplorer tests[^2][^3][^4].\n\n[^1]: https://github.com/carbon-language/carbon-lang/pull/5224\n\n[^2]: https://github.com/carbon-language/carbon-lang/pull/4979\n\n[^3]: https://github.com/carbon-language/carbon-lang/pull/5025\n\n[^4]: https://github.com/carbon-language/carbon-lang/pull/5036\n\n## Background\n\n-   Previous proposal:\n    [#3532: Focus implementation effort on the toolchain](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p3532.md)\n-   Kick-off of this discussion\n    [#5224](https://github.com/carbon-language/carbon-lang/pull/5224#pullrequestreview-2730512195)\n-   Discord discussion:\n    [2025-04-02 #explorer](https://discord.com/channels/655572317891461132/763516049710120960/1356979197070803095)\n\n## Proposal\n\n1. Add a tag `explorer-archived` in the main `carbon-lang` git repository.\n2. Create a new `explorer` repository under the `carbon-language` organization\n   that only contains the `//explorer` and `//installers` directories and their\n   dependencies at head.\n3. Locally ensure the explorer tests build and pass under the `explorer`\n   repository.\n4. Add a `README.md` to the `explorer` repository that explains explorer is\n   archived and not under active development.\n5. Stop building, or remove the \"Explorer (trunk)\" compiler option from\n   [carbon.compiler-explorer.com](https://carbon.compiler-explorer.com).\n6. Delete `//explorer` and `//installers` in the main `carbon-lang` repository.\n7. Archive the `explorer` repository in GitHub, making it read-only.\n\nNote that fuzzer test cases from the explorer are already relocated under\n`//toolchain/*/fuzzer_corpus/`.\n\n## Rationale\n\nThe primary purpose of the explorer codebase at this time is as a demonstration\nof past work implementing the carbon language design. This can help to inform\nthe implementation of the toolchain as it catches up in various areas, as long\nas the design has not deviated from the explorer implementation.\n\nSearching in, and providing links to the explorer codebase comes up in design\ndiscussions occasionally [^5][^6][^7][^8][^9][^10], and we should maintain the\nability of toolchain developers to look through the explorer easily. The primary\nplace they do so is on GitHub, where the code can be linked to. GitHub search\nonly works\n[on the main branch](https://docs.github.com/en/search-github/github-code-search/understanding-github-code-search-syntax#using-qualifiers)\nof a repository, so the `trunk` branch for the `carbon-lang` repository. To\nmaintain searchability, the explorer codebase must either remain on `trunk` in\n`carbon-lang` or in a sibling repository. GitHub search does continue to work in\narchived repositories.\n\nProposal\n[p3532](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p3532.md)\ndirected to keep the explorer codebase active in the main repository, with its\ntests building and running:\n\n> We should keep the Explorer's code in place, building, and passing its basic\n> regression tests because the built artifacts of the Explorer remain really\n> valuable given its coverage of our design's feature sets.\n\nHowever the [problems](#problem) discussed above result from this situation. We\ncan gain the benefit of access to the codebase while reducing its impact on\ndevelopers and users by moving it into a separate git repository.\n\n[^5]:\n    https://discord.com/channels/655572317891461132/998959756045713438/1225116234199203860\n\n[^6]:\n    https://discord.com/channels/655572317891461132/998959756045713438/1237143981150830673\n\n[^7]:\n    https://discord.com/channels/655572317891461132/709488742942900284/1250577021474443376\n\n[^8]:\n    https://discord.com/channels/655572317891461132/748959784815951963/1255669935439482993\n\n[^9]:\n    https://discord.com/channels/655572317891461132/655578254970716160/1302033729761443963\n\n[^10]:\n    https://discord.com/channels/655572317891461132/941071822756143115/1349523309682753606\n\n## Alternatives considered\n\n### Use a branch to refer to the explorer codebase\n\nWe could create a branch in the `carbon-lang` repository that contains explorer,\nbut delete it from `trunk`. This would also allow the code to be found and\nlinked to, however GitHub search does not support searching in a branch. The\nmain purpose of the explorer code while archived is for reading the\nimplementation, and search is an important part of that.\n\n### Do nothing\n\nIn the future, we may want to restart development of the explorer codebase. At\nthat time we would benefit from keeping the codebase building as we upgrade\nBazel, Clang, Clang-tidy, etc. However we don't currently have the resources to\nbuild two implementations of the language, and there's no plan in our roadmaps\nto restart explorer development. So the cost of letting the explorer codebase\nbecome stale is outweighed by the costs of keeping it active.\n"
  },
  {
    "path": "proposals/p5337.md",
    "content": "# Interface extension and `final impl` update\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5337)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [`extend require`](#extend-require)\n    -   [`extend impl as` with parameterized interfaces](#extend-impl-as-with-parameterized-interfaces)\n    -   [`extend impl as` restrictions](#extend-impl-as-restrictions)\n    -   [Name conflicts](#name-conflicts)\n    -   [Final `impl` priority](#final-impl-priority)\n        -   [Overlapping final `impl`s](#overlapping-final-impls)\n        -   [Using associated constants from `impl`s in a `final match_first`](#using-associated-constants-from-impls-in-a-final-match_first)\n        -   [`impl` selection algorithm](#impl-selection-algorithm)\n        -   [An `impl` that can never match is an error](#an-impl-that-can-never-match-is-an-error)\n    -   [Impl names for prioritization](#impl-names-for-prioritization)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Allow overlap between a non-final and final impl but only if no queries pick the non-final on the overlap](#allow-overlap-between-a-non-final-and-final-impl-but-only-if-no-queries-pick-the-non-final-on-the-overlap)\n    -   [Forbid overlap between final impls](#forbid-overlap-between-final-impls)\n    -   [Prioritize between final impls using type structure](#prioritize-between-final-impls-using-type-structure)\n    -   [Allow mixing final and non-final impls in the same `match_first` block](#allow-mixing-final-and-non-final-impls-in-the-same-match_first-block)\n    -   [No default `Self` in `require Self impls I`](#no-default-self-in-require-self-impls-i)\n    -   [Different rules for prioritizing between final impls](#different-rules-for-prioritizing-between-final-impls)\n    -   [Different `final match_first` associated constant rules](#different-final-match_first-associated-constant-rules)\n\n<!-- tocstop -->\n\n## Abstract\n\nWe make 5 changes:\n\n-   Allow `require Self impls I` in an `interface` or `constraint` scope to omit\n    the `Self`, so it can be written `require impls I`.\n-   Rename `extend I` to `extend require impls I` in an `interface` or\n    `constraint` scope.\n-   Define `extend impl as I` and `extend final impl as I` in an `interface`\n    scope to copy the members of `I` and define an `impl` of `I` in terms of the\n    extending interface.\n-   Allow a non-final `impl` to overlap a final `impl` as long as it isn't\n    subsumed by the final `impl`. The final `impl` will be given priority on the\n    overlap.\n-   Allow `final` on a `match_first` block, used to declare overlapping final\n    impls, which are required to be in a single file.\n\nThese features work together to allow a form of interface extension where:\n\n-   Types only need to `impl` the extending interface to also get an `impl` of\n    the extended interface.\n-   Multiple interfaces can extend the same interface.\n-   An interface can extend multiple interfaces.\n\n## Problem\n\nAs part of investigating\n[leads issue #4566](https://github.com/carbon-language/carbon-lang/issues/4566),\nwe discovered problems with using a single `impl` to implement multiple\ninterfaces.\n[Proposal #5168 (Forward `impl` declaration of an incomplete interface)](https://github.com/carbon-language/carbon-lang/pull/5168)\nremoved that, but this changed the experience of `impl` of an interface that\nuses `extend`. Consider two closely coupled interfaces, such as:\n\n```carbon\ninterface As(T:! type) {\n  fn Convert[self: Self]() -> T;\n}\n\ninterface ImplicitAs(T:! type) {\n  extend As(T);\n}\n```\n\nWith #5168, you can no longer just `impl` `ImplicitAs(T)` with something like\n\n```carbon\nimpl ThisType as ImplicitAs(ThatType) {\n  fn Convert[self: Self]() -> ThatType { ... }\n}\n```\n\nInstead, two `impl` definitions are needed:\n\n```carbon\nimpl ThisType as As(ThatType) {\n  fn Convert[self: Self]() -> ThatType { ... }\n}\nimpl ThisType as ImplicitAs(ThatType) { }\n```\n\nThis is additional friction, which will increase with the depth of the interface\nhierarchy, which we would like to eliminate. The suggestion in\n[proposal #5168](https://github.com/carbon-language/carbon-lang/pull/5168), is\nto support the `ImplicitAs` use case with a `final` blanket `impl` of the\n`As(T)` interface for any type that `impls ImplicitAs(T)`, as in:\n\n```carbon\ninterface As(T:! type) {\n  fn Convert[self: Self]() -> T;\n}\n\ninterface ImplicitAs(T:! type) {\n  fn Convert[self: Self]() -> T;\n}\n\nfinal impl\n    forall [T:! type, U:! ImplicitAs(T)]\n    U as As(T) {\n  fn Convert[self: Self]() -> T =\n      U.(ImplicitAs(T).Convert);\n}\n```\n\nThis means that types that `impl as ImplicitAs(T)` automatically get an `impl`\nof `As(T)`, and can't `impl as As(T)` themselves. However, there are some\nconcerns:\n\n-   There is significant ceremony to express this relationship.\n-   These semantics are closer to what we expect users will think `extend` in an\n    interface will do.\n-   We still want a way to get the current meaning of `extend` in an `interface`\n    scope for a few reasons:\n    -   This `final impl` requires the two interfaces to be defined in the same\n        file, which won't always be possible.\n    -   A `final impl` doesn't give much flexibility for situations where you\n        need more control, for example to\n        [reuse an impl of a specific interface](/docs/design/generics/details.md#use-case-defining-an-impl-for-use-by-other-types).\n    -   Also the current `extend` matches the semantics of `extend` in a named\n        constraint.\n-   Having a `final impl` of `interface As(T)` currently makes it quite\n    difficult to have other `impl`s of the same interface.\n\nOn this last point, under the current rules the following example would be\nrejected:\n\n```carbon\nclass C(T:! type) { ... }\n\ninterface I {}\nimpl forall [T:! I] C(T) as As(T) { ... }\n```\n\nThe issue is that this `impl` overlaps with the `final impl` of\n`interface As(T)` for any type `C(T)` that implements `ImplicitAs(T)`. This\n`impl` is rejected preemptively because it conflicts on the overlap, whether or\nnot anything inhabits that overlap in the developer's program. This avoids\nconflicts only being discovered by some consuming library.\n\n## Background\n\n-   [Proposal #553](https://github.com/carbon-language/carbon-lang/pull/553)\n    introduced interface extension\n-   [Proposal #983](https://github.com/carbon-language/carbon-lang/pull/983)\n    introduced `final impl`\n-   [Proposal #2760](https://github.com/carbon-language/carbon-lang/pull/2760)\n    introduced `require Self impls I` in an `interface` or `constraint` scope,\n    replacing the previous spelling of `impl as I` from\n    [proposal #553](https://github.com/carbon-language/carbon-lang/pull/553).\n-   [Proposal #2868](https://github.com/carbon-language/carbon-lang/pull/2868)\n    allowed an `impl` to overlap a `final impl` as long as agreed on the\n    overlap.\n\n## Proposal\n\nFirst, to make `require Self impls I` usage more consistent with\n`impl Self as I` (and since we will be using this more after this proposal), we\nallow the `Self` to be omitted. So:\n\n-   `require Self impls I` ✅ allowed, same meaning as before\n-   `require impls I` ✅ allowed, same as `require Self impls I`\n-   `require T impls I` ✅ allowed, same meaning as before\n\nNext, since we are creating another way that an `interface` can `extend` another\ninterface, we change the existing usage of `extend` from being an introducer of\nits own declaration, to a modifier on a `require` declaration. In this case, the\nonly type that can be constrained is `Self`, since that is the type being\nextended. To match the restriction that an `extend impl` must be followed by\n`as` in `class` scope, `extend require` can only be followed by `impls` in\n`interface` scope:\n\n-   `extend require Self impls I` ❌ forbidden, `Self` must be omitted since no\n    other value allowed\n-   `extend require impls I` ✅ allowed\n-   `extend require T impls I` ❌ forbidden\n\n`extend require impls I` after this proposal has the same meaning as `extend I`\ndid before this proposal, so:\n\n```carbon\ninterface A {\n  fn F();\n}\n\ninterface B {\n  extend require impls A;\n  fn G();\n}\n```\n\nis equivalent to:\n\n```carbon\ninterface A {\n  fn F();\n}\n\ninterface B {\n  require impls A;\n  alias F = A.F;\n  fn G();\n}\n```\n\nWe then add another way to use `extend` as a modifier in an `interface` scope.\nWe define the meaning of `extend impl as I;` in an `interface J` scope to do two\nthings:\n\n-   Copy the members of `I` to form new members of `J`.\n-   Define a blanket `impl` that anything that `impls J` also `impls I`, by\n    forwarding to the corresponding members of `J`.\n\nThese semantics are intended to be similar to `extend impl` in a `class`, except\nthat the definition of the blanket `impl` is generated automatically (and `impl`\nwithout `extend` is not allowed in an interface).\n\nIn this example:\n\n```carbon\ninterface I {\n  let T:! type;\n  fn F();\n  fn G();\n}\n\ninterface J {\n  extend impl as I;\n  fn H();\n}\n```\n\nThe definition of `interface J` is equivalent to:\n\n```carbon\ninterface J {\n  let T:! type;\n  fn F();\n  fn G();\n  fn H();\n}\nimpl forall [U:! J] U as I {\n  let T:! type = U.(J.T);\n  fn F() = U.(J.F);\n  fn G() = U.(J.G);\n}\n```\n\nThe keyword `final` can be added between `extend` and `impl` to make the\ngenerated `impl` definition `final`. For example, the\n`final impl forall [T:! type, U:! ImplicitAs(T)] U as As(T)` from\n[the \"Problem\" section](#problem) would be generated from this:\n\n```carbon\ninterface ImplicitAs(T:! type) {\n  extend final impl as As(T);\n}\n```\n\nTo allow a non-final `impl` to overlap a final `impl`, we say the final `impl`\nis prioritized over a non-final `impl` anytime they overlap. This addresses a\n[problem](#problem) caused by the fact that we don't support the negative\nconstraints that would allow a developer to avoid the overlap -- and the only\nsound choice is to prefer the final `impl`. However, if a non-final `impl` can\nnever be used because it is completely subsumed by a final `impl`, that is an\nerror.\n\nTo allow multiple interfaces extending the same interface, we also want to\nsupport a way to declare overlapping final `impl`s. We do this by listing the\nnames of the overlapping `impl`s in a `final match_first` block instead of\nputting `final` on the `impl` declarations. Note this requires all of the final\n`impl`s to be in the same file.\n\nThe `impl` generated by an `extend impl as Foo` in an interface `Bar` can be\nnamed as `impl Bar.(as Foo)`. This name can be used to put such an `impl` into a\n`match_first` block (or a `final match_first` block).\n\nThis example inspired by\n[C++ iterator categories](https://en.cppreference.com/w/cpp/iterator) shows\nusing these pieces together:\n\n```carbon\ninterface Iterator {\n  fn Increment[addr self: Self*]();\n}\n\ninterface InputIterator {\n  let Element:! type;\n  extend impl as Iterator;\n  fn Get[addr self: Self*]() -> Element;\n}\n\ninterface OutputIterator {\n  let Element:! type;\n  extend impl as Iterator;\n  fn Set[addr self: Self*](x: Element);\n}\n\n// Makes both impls final and prioritizes them.\nfinal match_first {\n  impl InputIterator.(as Iterator);\n  impl OutputIterator.(as Iterator);\n}\n\ninterface ForwardIterator {\n  extend final impl as InputIterator;\n  fn Copy[self: Self]() -> Self;\n  fn Equal[self: Self](compare: Self) -> bool;\n}\n\ninterface OutputForwardIterator {\n  // Need to be careful with `Element`, see the\n  // \"Name conflicts\" section.\n  let Element:! type;\n  extend final impl as ForwardIterator\n      where .Element = Element;\n  extend final impl as OutputIterator\n      where .Element = Element;\n}\n\nclass MyIntIterator { ... }\n// An impl of OutputForwardIterator also implements:\n// Iterator, InputIterator, OutputIterator, and\n// ForwardIterator.\nimpl MyIntIterator as OutputForwardIterator {\n  where Element = i32;\n  fn Increment[addr self: Self*]() { ... }\n  fn Get[addr self: Self*]() -> i32 { ... }\n  fn Set[addr self: Self*](x: i32) { ... }\n  fn Copy[self: Self]() -> Self { ... }\n  fn Equal[self: Self](compare: Self) -> bool { ... }\n}\n```\n\n## Details\n\nNote that `extend` being first, before `final` or `impl`, follows\n[our other uses of `extend`](https://github.com/carbon-language/carbon-lang/issues/995#issuecomment-1417391051).\n\n### `extend require`\n\nSome notes and clarifications on `extend require`:\n\n-   To be consistent with other uses of `extend`, we use the same name lookup\n    rule: name lookup into a scope that extends other scopes first looks in that\n    scope, and then if it finds nothing, it looks into all of the extended\n    scopes, and the lookup is an error if there's more than one different\n    result. Example:\n\n    ```carbon\n    interface A {\n      fn F();\n      fn G();\n      fn H();\n    }\n\n    interface B {\n      fn G();\n      fn J();\n      fn K();\n    }\n\n    interface C {\n      extend require impls A;\n      extend require impls B;\n      fn F();\n      fn J();\n    }\n    ```\n\n    This definition of `interface C` means `A` and `B` are required and name\n    lookup into `C` for:\n\n    -   `F` finds `C.F`, hiding `A.F`;\n    -   `G` is ambiguous, due to the conflict between `A.G` and `B.G`;\n    -   `H` finds `A.H`;\n    -   `J` finds `C.J`, hiding `B.J`;\n    -   `K` finds `B.K`.\n\n    Note that if we had two more interfaces:\n\n    ```carbon\n    interface D {\n      fn G();\n    }\n    interface E {\n      extend require impls C;\n      extend require impls D;\n    }\n    ```\n\n    then lookup into `E` for `G` is also ambiguous, since the ambiguous lookup\n    into `C` for `G` still counts as a conflict with `D.G`.\n\n-   If interface `B` has `extend require impls A`, then any `impl C as B` will\n    require an `impl C as A`. We no longer support implementing the members of\n    `A` in an `impl` of `B`, see\n    [leads issue #4566](https://github.com/carbon-language/carbon-lang/issues/4566)\n    and\n    [proposal #5168](https://github.com/carbon-language/carbon-lang/pull/5168).\n\n-   If we accept\n    [the `extend api`/`extend alias` proposal #3802](https://github.com/carbon-language/carbon-lang/pull/3802),\n    then `extend require impls A;` becomes equivalent to `require impls A;` plus\n    `extend api A;` (or `extend alias A;`, depending on the syntax we choose).\n\n### `extend impl as` with parameterized interfaces\n\nWhen using `extend impl as` in a parameterized interface, those parameters end\nup in the `forall` clause in the generated `impl`. For example:\n\n```carbon\ninterface PointerContainer(T:! type) {\n  extend impl as Container(T*);\n}\n```\n\ngenerates this `impl`:\n\n```carbon\nimpl forall\n    [T:! type, U:! PointerContainer(T)]\n    U as Container(T*) { ... }\n```\n\n### `extend impl as` restrictions\n\n`extend impl as` can only be used if the generated `impl` would be legal. This\nincludes the [the orphan rule](/docs/design/generics/details.md#orphan-rule), so\nthe interface or type argument must be in the same file. For example:\n\n```carbon\nclass BigInt { ... }\n\ninterface IntLike {\n  // Only valid in the same library as `ImplicitAs`\n  // or `BigInt`.\n  extend impl as ImplicitAs(BigInt);\n}\n```\n\nThe\n[additional restrictions on final impls](/docs/design/generics/details.md#libraries-that-can-contain-a-final-impl)\nmean that `extend final impl as` can only be used in the same library as the\ninterface being extended, not the type arguments.\n\nSimilarly, the expression to the right of the `as` must correspond to a single\ninterface, due to\n[leads issue #4566](https://github.com/carbon-language/carbon-lang/issues/4566)\nand [proposal #5168](https://github.com/carbon-language/carbon-lang/pull/5168).\n\n### Name conflicts\n\nIf two associated constants or functions have the same name in the two\ninterfaces, this is an error since there is no way to assign values to both in\nan `impl` of the extending interface.\n\nExample with an associated function:\n\n```carbon\ninterface A {\n  fn F();\n}\n\ninterface B {\n  fn F();\n  // Name conflict with `F`.\n  extend impl as A;\n}\n\nclass C {\n  impl as B {\n    // Probably refers to the `F` explicitly declared in `B` --\n    // no way to implement the `F` that comes from `A`.\n    fn F() { ... }\n  }\n}\n```\n\nExample with an associated constant:\n\n```carbon\ninterface A {\n  let T:! type;\n}\n\ninterface B {\n  let T:! type;\n  // Name conflict with `T`.\n  extend impl as A;\n}\n\nclass C {\n  impl as B {\n    // Two different associated constants named `T` and no way\n    // to distinguish them.\n    where T = i32;\n  }\n}\n```\n\nNotice that the rewrite to put the members of `A` into `B` would result in a\nconflict. Further, if there is only one member with that name after the rewrite\nin `B`, then there is no way to write the generated `impl` to set the member of\n`A` from the values of the associated constants in `B`.\n\nHowever, if the extending interface gives a value to the associated constant,\nthere is no need to specify that value in an `impl`, so that is not an error.\n\n```carbon\ninterface A {\n  let T:! type;\n  fn F() -> T;\n}\n\ninterface B {\n  let T:! type;\n  // Okay\n  extend impl as A where .T = T*;\n}\n\nclass C {\n  impl as B {\n    // `T` here is `B.T`\n    where T = i32;\n    // `F` here is `B.F` and `A.F`.\n    fn F() -> i32*;\n  }\n}\n```\n\nThis is equivalent to:\n\n```carbon\ninterface A {\n  let T:! type;\n  fn F() -> T;\n}\n\ninterface B {\n  let T:! type;\n  // Skip A.T due to conflict.\n  fn F() -> T*;\n}\n\nimpl forall [U:! B] U as A where .T = .(B.T)* {\n  fn F() -> T = U.(B.F);\n}\n\nclass C {\n  impl as B {\n    where T = i32;\n    fn F() -> i32*;\n  }\n}\n```\n\nThis was used in the `OutputForwardIterator` example in\n[the \"Proposal\" section](#proposal).\n\nName conflicts are not expected to generally be a problem in practice since this\nform of extension often requires the two interfaces to be defined in the same\nfile.\n\n### Final `impl` priority\n\nWith the design prior to this proposal, a final `impl` can only overlap another\n(final or non-final) `impl` if they have the same definition on their overlap.\nThis means that if there is a `final` blanket impl of an interface, as is\ngenerated by `extend final impl as` in the interface's scope, then other `impl`s\nof that interface may be overly restricted. This example:\n\n```carbon\npackage Core;\n\ninterface As(T:! type) {\n  fn Convert[self: Self]() -> T;\n}\n\ninterface ImplicitAs(T:! type) {\n  extend final impl as As(T);\n}\n```\n\nis equivalent to:\n\n```carbon\npackage Core;\n\ninterface As(T:! type) {\n  fn Convert[self: Self]() -> T;\n}\n\ninterface ImplicitAs(T:! type) {\n  fn Convert[self: Self]() -> T;\n}\n\nfinal impl forall [T:! type, U:! ImplicitAs(T)] U as As(T) {\n  fn Convert[self: Self]() -> T = U.(ImplicitAs(T).Convert);\n}\n```\n\nAny other `impl` of `As(T)` is going to overlap unless we could establish that\nthe type does not implement `ImplicitAs(T)`. However, in a generic context, we\ndon't support (and don't intend to support) that sort of negative constraint. So\nthere would be no way to prove the following `impl` of `As(T)` doesn't overlap\nthe `final impl` of `As(T)`:\n\n```carbon\nimport Core;\n\nclass X(T:! type) {\n  impl as As(T);\n}\n```\n\nIn particular, an unrelated library defining `MyType` could define\n`impl X(MyType) as ImplicitAs(MyType)`, which would create a conflict between\nthe `impl` in `X(T)` and the `final impl` associated with `ImplicitAs(T)`.\n\nThis motivates a change to the rules: we want to allow a non-final `impl` to\noverlap with a final `impl`. The question is what to do for queries in the\noverlap.\n\nNow consider this second example:\n\n```carbon\nimport Core;\n\nclass Array(Element:! type) { ... }\n\n// Impl 1\nimpl forall [T:! type, U:! As(T)]\n    Array(U) as As(Array(T)) { ... }\n\n// Impl 2\nimpl forall [T:! type, U:! ImplicitAs(T)]\n    Array(U) as ImplicitAs(Array(T)) { ... }\n```\n\nThis creates a conflict:\n\n1.  Impl 1 provides `impl Array(U) as As(Array(T))`.\n2.  Impl 2 provides `impl Array(U) as ImplicitAs(Array(T))`.\n3.  The\n    [`Core` package defined at the beginning of this section](#final-impl-priority)\n    has `final impl forall [T:! type, U:! ImplicitAs(T)] U as As(T)`.\n4.  Combining 2 and 3 provides another definition of\n    `impl Array(U) as As(Array(T))` which is final. Impl 1 has a more specific\n    [type structure](/docs/design/generics/details.md#overlap-rule), though.\n\nFurthermore, this example is realistic:\n\n-   The final blanket `impl` defined in the `Core` package is the definition we\n    expect to use.\n-   We need impl 1 to support types `T` that only `impl` `As(U)` and not\n    `ImplicitAs(U)`.\n-   We need impl 2 to support types `T` that `impl` `ImplicitAs(U)`.\n-   Carbon will define an implicit conversion from `i32` to `i64`, and it would\n    be reasonable to ask if `Array(i32)` implicitly converts to `Array(i64)`,\n    which would be a query in the overlap.\n\nAny generic code that sees the final `impl` can assume it applies whenever it is\nused. If we don't want to forbid this overlap situation (either when defining a\nnon-final `impl` with a more-specific type structure or when doing an `impl`\nquery in the overlap that selects the non-final one), the only sound choice is\nto use the final `impl`. And we don't want to give an error here since:\n\n-   It would reduce expressiveness, since there isn't a good workaround to\n    prevent the overlap.\n-   It would reduce the ability to compose libraries.\n-   We want to support examples like this interaction between `Array`, `As`, and\n    `ImplicitAs`.\n\nNote that prioritizing the final `impl` over the non-final `impl` (even when the\nnon-final `impl` has a preferred type structure) produces the desired result in\nthe example above. By writing `final` we ensure that `Convert` in `ImplicitAs`\nalways matches `Convert` in `As`, when they are both defined.\n\nAlso note that this gives the desired behavior that this `final impl` of the\n`CommonTypeWith` interface:\n\n```\nfinal impl forall [T:! type] T as CommonTypeWith(T) where .Result = T {}\n```\n\nis prioritized as if it is more specialized than user-written `impl`s of\n`CommonTypeWith`,\n[as desired](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/if.md#same-type).\n\n#### Overlapping final `impl`s\n\nThe next question is what to do if there are overlapping final `impl`s. We\nconsidered options that allowed them to be in different files, but this led to\nprioritization that was inconsistent with the\n[type structure rules](/docs/design/generics/details.md#overlap-rule) for\nnon-final `impl`s.\n\nIn particular, the restrictions on\n[which libraries can define a final `impl`](/docs/design/generics/details.md#libraries-that-can-contain-a-final-impl)\nmean there are at most two files that can contain two final `impl` definitions\nthat both match a particular (type, interface) query: the one defining the root\ntype and the one defining the root interface. The only way to have the final\n`impl`s in different files is if there is a\n[blanket impl](/docs/design/generics/details.md#blanket-impl-declarations) of\nthe interface in the file defining the interface and the other in the file\ndefining the type. Generic code may only see the file with the interface, and\nsince it is marked \"final\" will assume it is safe to use. As a result, the only\nsound solution is to prioritize the final blanket `impl` over the final `impl`\nthat specifies the type, the opposite of how non-final impls prioritize using\ntype structure. Furthermore, there would be queries that would match the final\n`impl` that specifies the type but would not select that `impl`, a property we\nwould like to have. So we require that overlapping final `impl`s be declared in\nthe same file, a restriction that the compiler can enforce due to the file\nlimitations.\n\n> **Future work:** If we determine that we do want to support overlapping final\n> impls across the two files, we thought the second file could use\n> `extend final match_first` to say \"these entries are notionally added to the\n> earlier `final match_first`.\n\nWithin a file, we have two tools here we could use to select between the\ncandidates: type structure and\n[`impl_priority`/`match_first` blocks](/docs/design/generics/details.md#prioritization-rule).\n(We will use the placeholder term of \"`match_first` blocks\" to refer to these\nwithout asserting how they will be spelled.)\n\nThe decision here is to only use `match_first` blocks, not type structure to\nchoose between overlapping final `impl` definitions, for a few reasons:\n\n-   Type structure is needed to pick betewen `impl` defined in different files,\n    which we are not allowing for final impls.\n-   A `match_first` block is very explicit way of prioritizing, and with final\n    `impl`s in particular it is helpful to be clear about the conditions where\n    they won't be selected even when they match.\n\nWith this decision not to use type structure to prioritize final `impl`s, it\ndoesn't make sense to mix `final` and non-final `impl`s in the same\n`match_first` block. Furthermore, until the compiler sees the `match_first`\nblock, we can't treat an `impl` as final since we don't know if another final\n`impl` will be appear earlier in the `match_first` block and used instead. Which\nleads to the decision to put the `final` modifier on the `match_first` block\ninstead of the `impl` declaration, when it appears in a `match_first` block.\nExample:\n\n```carbon\n// Compiler does not treat this as final, so it\n// won't use `A = i32`.\nimpl forall [T:! Z] T as J {\n  where A = i32;\n  // ...\n}\n\nfn F(T:! Z) {\n  // Can assume `T impls J`.\n  // Can't assume `T.(J.A)` is `i32`.\n\n  // If we were to mark the above `impl` as `final`,\n  // this code would assume it is selected, and we\n  // would have to poison the impl lookup to prevent\n  // the following conflicting `impl` and\n  // `match_first` declarations.\n}\n\n// Also not treated as final yet, so the compiler\n// won't use `A = bool`.\nimpl forall [U:! Y] U as J {\n  where A = bool;\n  // ...\n}\n\n// Matching `bool` assignment to `J.A` as the\n// previous impl.\nimpl forall [V:! W] V as J {\n  where A = bool;\n  // ...\n}\n\nfinal match_first {\n  impl forall [U:! Y] U as J;\n  impl forall [V:! W] V as J;\n  impl forall [T:! Z] T as J;\n}\n\n// Now all are considered final, with the\n// understanding that `impl forall [T:! Z] T as J`\n// may not be used even when it matches. The\n// compiler can now tell if it can use `A = bool`\n// from `impl forall [U:! Y] U as J`.\n\nfn G(U:! Y) {\n  // Can assume `U impls J` and `U.(J.A)` is `bool`.\n}\n\nfn H(V:! W) {\n  // Don't know if `V impls Y`, so we don't know\n  // which `impl` is selected. We use a symbolic\n  // witness for `V` and `V.(J.A)` is unknown\n  // (despite that it would be `bool` in either\n  // case).\n}\n```\n\n> Note: `final match_first` was considered in\n> [open discussion on 2023-09-13](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.4r37mjr7c42h)\n> as a part of function overloading, and other times since.\n\nThis leads us to these rules:\n\n-   An `impl` is considered \"final\" if is declared with the `final` keyword\n    modifier or if it is named in a `final match_first` block.\n    -   In the first case (a `final impl` declaration), that `impl` may not\n        appear in any `match_first` block.\n-   An `impl` may appear in at most one `match_first` block.\n    -   This is true whether or not the block is marked `final`.\n-   Two final `impl`s in the same file must appear in the same\n    `final match_first` block if they overlap, as determined by their type\n    structure.\n\n#### Using associated constants from `impl`s in a `final match_first`\n\nAs established by\n[proposal #5168](https://github.com/carbon-language/carbon-lang/pull/5168),\nconcrete `impl` queries resolve to a concrete `impl` witness, with the\nassociated constants from a single `impl` definition. A symbolic `impl` query\ncan in some cases use the associated constants from a final `impl`. If an `impl`\nquery matches an `impl` marked `final` (as opposed to one in a\n`final match_first`), then that `impl` will definitely be used. In that case,\nthe associated constants from the `impl` can be used.\n\nIf a symbolic query selects an `impl` from a `final match_first` block, though,\nthat `impl`'s associated constants may only be used if it is the first that\n_could_ match in its `final match` block, as determined by the type structures\nof the `impl`s that appear earlier. Phrased another way, a query will use the\nassociated constants of a final `impl` if it both matches and has no overlap\nwith the type structure of any of the `impl`s that appear before it in its\n`final match` first block. For example:\n\n```carbon\ninterface L(T:! type) {\n  let B:! type;\n}\nclass C(T:! type) {}\n\nfinal match_first {\n  // Can use the associated constants from this impl,\n  // since it is the first, so nothing could match ahead\n  // of it.\n  impl forall [U:! Y] C(U) as L(bool) where .B = i32;\n\n  // Queries that match this impl and can't match the\n  // previous impl's type structure can use the\n  // associated constants from this impl. In this case,\n  // that happens if the self type (left of the `as`) of\n  // the query can't match `C(?)`.\n  impl forall [V:! W] V as L(bool) where .B = bool;\n\n  // Can use the associated constants from this impl,\n  // since any query that matches `T as L(i32)` won't\n  // match the type structure of the earlier impls in\n  // the `final match_first`, since they all have\n  // `L(bool)` to the right of `as`.\n  impl forall [T:! Z] T as L(i32) where .B = f32;\n}\n\nclass D(X:! type) {}\nimpl forall [X:! type] D(X) as W {}\n// D(X) as L(bool) uses the middle `impl forall` from\n// the `final match_first` so the return type is `bool`.\n// Note that we can conclude `D(X)` does not match the\n// type structure of the first `impl forall` of\n// `C(?) as`... even though the query is not concrete.\nfn F(X:! type) -> (D(X) as L(bool)).B {\n  return true;\n}\n\nclass E(T:! type) {}\nimpl forall [T:! type] C(E(T)) as W {}\n// `C(E(T))` does impl `W`, so it impls `L(bool)`. But\n// since we don't know whether `E(T)` impls `Y`, we\n// don't know which impl it will ultimately use, and so\n// `(C(E(T)) as L(bool)).B` is unknown.\n```\n\n#### `impl` selection algorithm\n\nIn conclusion, we prioritize final `impl`s over non-final `impl`s. In the case\nthat there are multiple matching final `impl`s defined in the same file, they\noverlap so they must be in a single `final match_first` block. In that case,\npick the first matching one listed in the `final match_first` block.\n\nIf no final `impl` declarations match the query, we fall back to the original\nrules:\n\n-   The non-final `impl` declarations matching the query with the most preferred\n    type structure must be in the same non-final `match_first` block, or a\n    single non-final `impl` declaration not in a `match_first` can match.\n    -   In the latter case, that `impl` is selected. Alternatively, `impl`\n        declarations not in any `match_first` block could be considered to be\n        the only member of their own `match_first` block.\n-   If a non-final `match_first` block is chosen, the first matching `impl` in\n    that block is selected.\n\nSince it may be observable which `impl` declarations are considered during impl\nlookup, due to the [acyclic rule](/docs/design/generics/details.md#acyclic-rule)\nand [termination rule](/docs/design/generics/details.md#termination-rule), we\nspecify this more precisely:\n\n-   Only (final or non-final) `impl`s with a type structure compatible with the\n    query are considered.\n-   Final `impl`s are considered in the order they appear in the\n    `final match_first` block, if any.\n    -   The first matching final `impl` considered is returned, skipping the\n        remaining steps.\n-   Non-final `impl`s are considered most specific type structure first.\n-   Non-final `impl`s with the same type structure are considered in the order\n    they appear in their common `match_first` block.\n-   Once the first matching non-final `impl` is found:\n    -   If it is not in a `match_first` block, it can be returned, skipping the\n        remaining steps.\n    -   The non-final `impl`s earlier in the same `match_first` block with\n        compatible type structure are considered in the order they appear in the\n        `match_first` block\n        -   We skip those with an equal or preferred type structure compared to\n            the matching `impl`, since those have already been considered and\n            determined to not be matching.\n    -   The first matching `impl` is selected. If no `impl` matches before the\n        one used to select the `match_first` block, that `impl` is selected and\n        no later `impl`s will be considered.\n\n#### An `impl` that can never match is an error\n\nInstead of the current rule that prevents a (final or non-final) `impl` from\noverlapping an existing final `impl`, we have a replacement rule that says a\n(final or non-final) `impl` that will never be selected due to being subsumed by\na final `impl` is an error.\n\nThe compiler can detect whether an `impl` declaration is subsumed by performing\nan `impl` lookup (restricting to final impls) for the query represented by its\ndeclaration (ignoring any trailing `where` clause setting associated constants).\nFor the declaration `impl forall [T:! I] X(T) as J where .A = bool`, as an\nexample, the query would be \"`X(T) impls J` with `T impls I`\".\n\nNote that\n[the rules for which libraries can define a final `impl`](/docs/design/generics/details.md#libraries-that-can-contain-a-final-impl)\nmean that a subsuming final `impl` is either visible or is later in the same\nfile (and such will be diagnosed due to poisoning when we look for a subsuming\nfinal `impl`). In order to detect the subsumption, the query for the final\n`impl` should either be delayed to the end of the file, or poisoned.\n\n> _**Concern**_: Consider a situation where a library defines a broad final\n> `impl`, but has determined it is a bad idea and wants to remove it in the\n> future. One strategy would be to ask clients of the library to define their\n> own non-final `impl`s first. This non-final `impl` would be ignored before the\n> transition since the final `impl` has higher priority, but would be used once\n> the final `impl` is removed. In this case, we would like to suppress the error\n> for the subsumed non-final `impl` defined in the client. This is future work,\n> but our current idea is to associate the final `impl` with some build\n> configuration constant to mark it as conditionally available. A final `impl`\n> marked in that way would not be considered to subsume any `impl` not marked\n> the same way. This could also be used to allow temporary changes made while\n> debugging.\n\n### Impl names for prioritization\n\nThe generated `impl` from an `extend impl` in an interface is given a name\nsimilar to an `impl` defined in a `class` scope, as\n[discussed on 2024-03-11](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.p69b78lovqb7),\nmentioned in [proposal #3763](/proposals/p3763.md#redeclarations), and proposed\nin pending\n[proposal #5366](https://github.com/carbon-language/carbon-lang/pull/5366).\n\nFor example, these names can be used to allow multiple interfaces to extend a\nsingle interface:\n\n```carbon\ninterface A(T:! type) {\n  fn F() -> T;\n}\n\ninterface B {\n  extend impl as A(i32);\n  // Produces impl with name `B.(as A(i32))`.\n}\n\ninterface C1 {\n  let U:! type;\n  extend impl as A(U);\n  // Produces impl with name `C1.(as A(U))`.\n}\n\ninterface C2 {\n  let U:! type;\n  // Only difference from C1 is using `Self.U` instead of `U`.\n  extend impl as A(Self.U);\n  // Produces impl with name `C2.(as A(Self.U))`.\n}\n\ninterface D(V:! type) {\n  extend impl as A(V);\n  // Produces impl with name `D(V:! type).(as A(V))`.\n}\n\ninterface E {}\nimpl forall [W:! E] W as A(W) { ... }\n\nclass F {}\nimpl F as A(F) { ... }\n\n// Placeholder impl priority syntax\nmatch_first {\n  impl B.(as A(i32));\n\n  impl C1.(as A(U));\n  impl C2.(as A(Self.U));\n  // Can't write `impl C1.(as A(Self.U))` or `impl C2.(as A(U))`.\n\n  impl D(V:! type).(as A(V));\n\n  impl forall [W:! E] W as A(W);\n\n  impl F as A(F);\n}\n```\n\nNote how the expression after the `as` has to match syntactically between the\ntwo declarations.\n\nWithout the `impl` prioritization, these would be conflicting `impl`s of the\ninterface `A`. Note that by the\n[overlapping final `impl` rules](#overlapping-final-impls), at most one\ninterface can `final extend impl as` a given interface. `final match_first` must\nbe used instead of multiple `final impl`s, so that there is an explicit\nprioritization between them, as in this example:\n\n```carbon\ninterface I {\n  fn IFn();\n}\n\ninterface J {\n  // Can't mark as `final` here.\n  extend impl as I;\n  fn JFn();\n}\n\ninterface K {\n  // Can't mark as `final` here.\n  extend impl as I;\n  fn KFn();\n}\n\n// Makes both impls final and prioritizes them.\nfinal match_first {\n  impl J.(as I);\n  impl K.(as I);\n}\n```\n\nWhen the extending interface is parameterized, following the approach of\n[proposal #3763: Matching redeclarations](https://github.com/carbon-language/carbon-lang/pull/3763),\nthe same sequence of tokens (between the `interface` and `{`) is used to name\nthe interface, allowing a syntactic match. For example:\n\n```\ninterface Z(T:! type) { ... }\n\ninterface Y(T:! type) {\n  extend impl as Z(T*);\n}\n// ...\n\nfinal match_first {\n  impl Y(T:! type).(as Z(T*));\n  // ...\n}\n```\n\n## Rationale\n\nThis proposal's end goal is to support a form of interface extension that\nmatches user's expectations, to aid the\n[\"Code that is easy to read, understand, and write\" goal](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nThis goal also informed the choice to be explicit about prioritizing overlapping\nfinal impls.\n\nThe choice to not treat an `impl` as final when it overlaps another final impl\nuntil we see how to choose between them on the overlap is in accord with the\n[information accumulation principle](/docs/project/principles/information_accumulation.md).\n\n## Alternatives considered\n\n### Allow overlap between a non-final and final impl but only if no queries pick the non-final on the overlap\n\nThis question was considered in the\n[\"final `impl` priority\" section](#final-impl-priority).\n\n### Forbid overlap between final impls\n\nThe downside of allowing them to overlap is we no longer have the property that\na final `impl` is selected anytime it matches. This puts limits on when the\ncompiler can use the values of associated constants from a final `impl`.\nHowever, the use cases, such as having multiple interfaces extend a single\ninterface, were compelling.\n\n### Prioritize between final impls using type structure\n\nThis question was considered in the\n[\"Overlapping final `impl`s\" section](#overlapping-final-impls).\n\n### Allow mixing final and non-final impls in the same `match_first` block\n\nThere were some ways we could imagine supporting a mix of final and non-final\nimpls in the same `match_first` block. With\n[the decision to not use type structure to prioritize between final impls](#prioritize-between-final-impls-using-type-structure),\nthough, reconciling the differences seemed like it would lead to a lot of\ncomplexity and surprising behavior, like priority inversions. We thought the\napproach of putting `final` on the `match_first` block resulted in simpler\nrules.\n\n### No default `Self` in `require Self impls I`\n\nShortening of `require Self impls I` to just `require I` was considered in\n[proposal #2760](p2760.md#allow-interfaces-to-require-another-interface-without-writing-self-impls).\nIt was not chosen to be consistent with `where` clauses, but the door was left\nopen if it was found to be too verbose. The `require impls I` approach adopted\nby this proposal, though, could be extended to work with `where` as well. The\nconsideration of that change has been left to future proposals, and is out of\nscope for this one.\n\n### Different rules for prioritizing between final impls\n\nWe considered five options in discussions in\n[a GitHub comment on this proposal](https://github.com/carbon-language/carbon-lang/pull/5337/files#r2072024118),\n[#generics-and-templates on Discord](https://discord.com/channels/655572317891461132/941071822756143115/1367982721141440734)\non 2025-05-02, and\n[open discussion on 2025-05-05](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.g213t2menkod).\n\n1.  Final `impl`s in the file with the interface are prioritized over the final\n    `impl`s in the file with root self type of the `impl` (when they are\n    different).\n2.  Blanket final `impl`s with a `?` for the whole self type in the type\n    structure are prioritized over final `impl`s with a concrete root self type.\n3.  Final `impl`s are prioritized using the reverse of type structure\n    prioritization.\n4.  The syntax of final `impl`s associates them with either the interface\n    (`final match_first`) or the root self type (`extend final match_first`).\n    Those associated with the interface are prioritized first, and then those\n    associated with the type are prioritized after. Ties are resolved by type\n    structure and then `match_first`.\n5.  Final `impl` overlap is only allowed within a `final match_first` block.\n\nNote: Each final `impl`\n[must be declared either in the file with the interface or the root type](/docs/design/generics/details.md#libraries-that-can-contain-a-final-impl).\n\nThe concern with option 1 was that concatenating files that contain overlapping\nfinal `impl`s, such as when creating a reproduction of a bug, would necessitate\n`match_first` changes.\n\nThe concern with option 2 was that it was a new rule to learn, unrelated to the\nrule for non-final impls. It has the advantage of using explicit `match_first`\nto prioritize almost as much as option 1, while allowing files to be\nconcatenated with fewer changes.\n\nThe concern with option 3 was that it might not do what developers expect, due\nto being the opposite of non-final `impl` prioritization.\n\nIn general, options 1-4 were more complex than option 5. Option 5 maximized the\nuse of explicit `match_first` to resolve priority on final `impl` overlap,\nrather than an implicit prioritization. We were also interested these two\nproperties:\n\n-   If we have two impls A and B where A is preferred over B, and then we make\n    them both final, we should not make them valid but with B preferred over A.\n-   A final `impl` is selected for any query that it matches.\n\nwhich options 1-3 did not satisfy. The main concern with option 5 was that it\nmight not be able to express desired use cases. We noted, though, that you could\ncreate additional interfaces to support different prioritization policies. For\nexample:\n\n```carbon\ninterface ImplicitAs(T:! type) { ... }\ninterface HighPriorityImplicitAs(T:! type) { ... }\ninterface LowerPriorityFrom(U:! type) { ... }\n\nfinal match_first {\n  impl forall [T:! type] T as ImplicitAs(T);\n  impl forall [T:! type, U:! HighPriorityImplicitAs(T)]\n      U as ImplicitAs(T);\n  impl forall [U:! type, T:! LowerPriorityFrom(U)]\n      U as ImplicitAs(T);\n}\n```\n\nNotes:\n\n-   This gives control over which type is given special treatment as the self\n    type when implementing one of the auxiliary added interfaces.\n-   This `final match_first` is with the interfaces, but that does not preclude\n    a `final impl` of `HighPriorityImplicitAs` or `LowerPriorityFrom` in the\n    files with the self root types.\n\n### Different `final match_first` associated constant rules\n\nWe considered\n[in discussion on 2025-05-06](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.mygxcb6k4wpm)\na couple of alternative rules for determining when associated constants were\nconsidered to be known, and what value to use, when matching an `impl` from a\n`final match_first`.\n\nOne approach was to say that the `final match_first` would be allowed to have a\n`where` clause specifying the value of a subset of the associated constants of\nthe interface. Every `impl` named in the body would have to have a consistent\nassignment to those associated constants in their definitions. This had two\ndownsides:\n\n-   It did not support the anticipated overloading use cases well, where the\n    return type would vary across overloads.\n-   Supporting associated constants whose value varied with the value of a type\n    or interface parameter would have added a lot of complexity.\n\nAnother approach we considered was to say an associated constant would have a\nvalue if every impl that could match gave the same value. For example, in\n[the first example from the \"Overlapping final `impl`s\" section](#overlapping-final-impls),\nthe first two impls in the `final match_first` both set `A.J` to `bool`, so\nanything matching either of them could use `bool` for the value of `A.J`. This\nseemed hard to reason about. Also, there were concerns that this would be very\nsensitive to changes, introduce additional fragility in the case of evolution.\n\nWe also considered only using associated constants that were included in the\n`impl`'s name (using a `where` clause in the facet type instead of a `where`\ndeclaration in the `impl` definition body). This had the advantage that the\nlogic for determining the values of those associated constants could be done\nwithout the `impl` definitions. This would introduce implementation complexity,\nand would cause `impl` names to be longer increasing verbosity. It would also\nintroduce a difference between a `final impl` and a single `impl` by itself\ninside a `final match_first`.\n"
  },
  {
    "path": "proposals/p5366.md",
    "content": "# The name of an `impl` in `class` scope\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5366)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Optional `Self` before `as`](#optional-self-before-as)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Use semantic match for the scope](#use-semantic-match-for-the-scope)\n\n<!-- tocstop -->\n\n## Abstract\n\n```\nclass C {\n  impl as I;\n}\n```\n\nis redeclared\n\n```\nimpl C.(as I)\n```\n\nfor purposes of `match_first`/`impl_priority` blocks and definitions.\n\n## Problem\n\nAn `impl` declaration can be declared in `class` scope:\n\n```\nclass C {\n  alias T = bool;\n  impl as As(T);\n}\n```\n\nor in file scope:\n\n```\nclass C {\n  alias T = bool;\n}\nalias T = i32;\nimpl C as As(T);\n```\n\nThese `impl` declarations need to be named so they may be redeclared in a\ndefinition or\n[`match_first`/`impl_priority` block](/docs/design/generics/details.md#prioritization-rule).\nUnder the current rules introduced in\n[proposal #1084](https://github.com/carbon-language/carbon-lang/pull/1084) and\nmodified in [#3763](https://github.com/carbon-language/carbon-lang/pull/3763),\nan `impl` redeclaration must match syntactically, and that only works if the\nredeclaration enters the same scope as the original declaration.\n\nThis problem is demonstrated in the example above. We need some indication\nwhether to lookup `T` in the file or the class scope, otherwise these both would\nbe redeclared as `impl C as As(T)`.\n\n```carbon\nclass C(T:! type) {\n  class E {}\n  impl E as I(C(T), E);\n}\n\n// No ability to do syntactic match\n// C(T) does not match C(T:! type)\n// C(T).E does not match E\nimpl forall [T:! type] C(T).E as I(C(T), C(T).E);\n```\n\n## Background\n\nThe need for forward declarations of entities comes from the\n[information accumulation principle](/docs/project/principles/information_accumulation.md).\n\n[Leads issue #1132](https://github.com/carbon-language/carbon-lang/issues/1132)\ndefined the initial rules for matching forward declarations to their\ndefinitions. Those rules were partially incorporated into the design by\n[proposal #1084, \"Generics details 9: forward declarations\"](/proposals/p1084.md).\n\nA replacement approach was\n[discussed on 2024-03-11](https://docs.google.com/document/d/1s3mMCupmuSpWOFJGnvjoElcBIe2aoaysTIdyczvKX84/edit?resourcekey=0-G095Wc3sR6pW1hLJbGgE0g&tab=t.0#heading=h.p69b78lovqb7)\nand mentioned in [proposal #3763](/proposals/p3763.md#redeclarations). This is\nthe approach of syntactic matching and re-entering the same scope. The syntax\nadopted by this proposal was first suggested in those.\n\n[Proposal #3762: Merging forward declarations](https://github.com/carbon-language/carbon-lang/pull/3762)\nand\n[proposal #3980: Singular `extern` declarations](https://github.com/carbon-language/carbon-lang/pull/3980)\nrefined the rules for forward declarations, including the rules for `extern`\ndeclarations.\n\n[Leads issue #5251: `impl` declarations in a generic class context](https://github.com/carbon-language/carbon-lang/issues/5251)\nis (pending resolution) saying that an `impl` declaration in class scope must\nuse `Self` in a deducible position.\n\n## Proposal\n\nAn `impl` declaration is associated with the scope it is first declared in, and\ncan only be redeclared in that scope, matching all other declarations. Consider\nhow a function is redeclared outside the scope of a class in which it was\noriginally defined:\n\n```\nclass Z(T:! type) {\n  // Forward declaration of a function.\n  fn F();\n}\n\n// Definition of the function that was forward declared.\nfn Z(T:! type).F() { ... }\n```\n\nTo redeclare an `impl` after the end of the scope it was declared in, that scope\nmay be re-entered as part of the `impl` redeclaration, in the same way, except\nwith parentheses around the name of the `impl`, as in:\n\n```carbon\nclass X {\n  // Forward declaration that `X impls Y`:\n  impl as Y;\n}\n\n// Definition of the `impl` that `X impls Y`\n// that was forward declared in `X`:\nimpl X.(as Y) { ... }\n```\n\nMore generally, in a `class` scope\n\n```carbon\nclass __X__ {\n  impl __Y__;\n}\n```\n\nis redeclared `impl __X__.(__Y__)` outside of that `class` scope. Here `__X__`\nis whatever sequence of tokens appears in that position in the `class`\ndeclaration, and `__Y__` is the sequence of tokens in the `impl` declaration.\nThese declarations are matched syntactically, and anything in `__Y__` is\ninterpreted as if it appeared in the scope of `__X__` like it was first\ndeclared.\n\n## Details\n\nHere are some examples of this in practice:\n\n```carbon\nclass F {}\n\nclass A {\n  impl as As(i32);\n  impl Self as As(bool);\n  impl A as As(f64);\n\n  impl F as As(A);\n\n  class G {}\n  impl G as As(A);\n}\n\nimpl A.(as As(i32)) { ... }\nimpl A.(Self as As(bool)) { ... }\nimpl A.(A as As(f64)) { ... }\nimpl A.(F as As(A)) { ... }\nimpl A.(G as As(A)) { ... }\n```\n\nParameterized classes:\n\n```carbon\nclass B(T:! type) {\n  impl B(i32) as AddWith(A(T));\n}\n\nimpl B(T:! type).(B(i32) as AddWith(A(T))) { ... }\n```\n\nParameterized impl:\n\n```carbon\nclass C {\n  impl forall [T:! type] as I(T);\n}\n\nimpl C.(forall [T:! type] as I(T));\n```\n\nPutting the `forall` inside the parens both simplifies the syntactic match and\nmeans that any mentions of names in that clause are in scope. For example:\n\n```\nclass D(T:! type) {\n  class E {}\n  impl forall [U:! J(E)] as I(U);\n}\n\nimpl D(T:! type).(forall [U:! J(E)] as I(U));\n```\n\nNotice how the `E` in the constraint on `U` is found in the `D(T:! type)` scope.\n\nNested classes:\n\n```\nclass C1 {\n  class C2 {\n    class C3 {\n      impl as I;\n      class C4 {}\n    }\n  }\n}\n\n// Defining impl that was forward declared within the `C3` definition:\nimpl C1.C2.C3.(as I) { ... }\n\n// Defining a new impl:\nimpl C1.C2.C3.C4 as I { ... }\n```\n\nNotice that we don't know which form will be used until we see:\n\n-   the open paren (`(`) after a `.`,\n-   a parameter pattern,\n-   a non-parameter argument, or\n-   the `as`.\n\n### Optional `Self` before `as`\n\nThe normalization to add `Self` before `as` when that type is omitted before\nperforming syntactic match is preserved from proposals\n[#1084](https://github.com/carbon-language/carbon-lang/pull/1084) and\n[#3763](https://github.com/carbon-language/carbon-lang/pull/3763). Note that the\n`Self` is inserted in the parentheses when the `as` appears there. So:\n\n```\nclass A {\n  // First impl declaration is equivalent\n  // to `impl Self as As(i32);`\n  impl as As(i32);\n\n  // Second impl declaration.\n  impl Self as As(bool);\n}\n\n// Redeclaration of the first impl declaration.\nimpl A.(Self as As(i32)) { ... }\n\n// Since this is equivalent to\n// `impl A.(Self as As(bool)) { ... }`, is a\n// valid redeclaration of the second impl\n// declaration.\nimpl A.(as As(bool)) { ... }\n```\n\n## Rationale\n\nThe need for this proposal comes from supporting forward declarations for the\n[information accumulation principle](/docs/project/principles/information_accumulation.md).\nThe specifics of this proposal were chosen comply with these\n[Carbon goals](/docs/project/goals.md):\n\n-   Unambiguous rules that are simple to implement benefit\n    [language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem).\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    benefits by having rules that are simple to state and validate. The\n    syntactic match rule means redeclarations are close to a copy of the\n    original declaration, which makes authoring straightforward and automatable.\n\n## Alternatives considered\n\n### Use semantic match for the scope\n\n[Leads issue #5367: `impl` in `class` redeclaration syntax with parameterization](https://github.com/carbon-language/carbon-lang/issues/5367)\nconsidered an alternative where\n\n```carbon\n// Alternative\nimpl forall [T:! type] B(T).(as I) { ... }\n```\n\ninstead of:\n\n```carbon\n// This proposal\nimpl B(T:! type).(as I) { ... }\n```\n\nIt avoided putting a `forall` clause inside the parentheses, but that both\ngreatly limited the syntactic matching that we could do, and meant examples\nlike:\n\n```carbon\n// This proposal\nimpl D(T:! type).(forall [U:! J(E)] as I(U));\n```\n\nhad to instead be written with more qualfiers:\n\n```carbon\n// Alternative\nimpl forall [T:! type, U:! J(D(T).E)] D(T).(as I(U));\n```\n\nIt is not just helpful for the compiler: being able to make fewer and more\nmechanical changes after copy-pasting the `impl` declaration to make the\nredeclaration makes authoring the code easier, and simplifies tooling to\nautomate the process.\n"
  },
  {
    "path": "proposals/p5434.md",
    "content": "# `ref` parameters, arguments, returns and `val` returns\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5434)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n    -   [`ref` bindings](#ref-bindings)\n    -   [`ref` and `val` returns](#ref-and-val-returns)\n-   [Details](#details)\n    -   [Compound return forms and patterns](#compound-return-forms-and-patterns)\n    -   [Nested binding patterns](#nested-binding-patterns)\n    -   [Mututation restriction on objects bound to a value](#mututation-restriction-on-objects-bound-to-a-value)\n    -   [No optimization on erroneous behavior](#no-optimization-on-erroneous-behavior)\n    -   [`bound` parameters](#bound-parameters)\n    -   [How addresses interact with `ref`](#how-addresses-interact-with-ref)\n    -   [Improved interop and migration with C++ references](#improved-interop-and-migration-with-c-references)\n    -   [Part of the expression type system, not object types](#part-of-the-expression-type-system-not-object-types)\n    -   [Interaction with `returned var`](#interaction-with-returned-var)\n    -   [Use case: `Deref` interface](#use-case-deref-interface)\n    -   [Use case: indexing interfaces](#use-case-indexing-interfaces)\n    -   [Use case: member binding interfaces](#use-case-member-binding-interfaces)\n    -   [Use case: class accessors](#use-case-class-accessors)\n    -   [Type completeness](#type-completeness)\n    -   [Pointer value representation](#pointer-value-representation)\n-   [Future work](#future-work)\n    -   [Temporary lifetimes](#temporary-lifetimes)\n    -   [`ref` bindings in lambdas](#ref-bindings-in-lambdas)\n    -   [Interaction with effects](#interaction-with-effects)\n    -   [More precise lifetimes](#more-precise-lifetimes)\n    -   [Combining with compile-time](#combining-with-compile-time)\n    -   [Interaction with `Call` or other interfaces](#interaction-with-call-or-other-interfaces)\n    -   [Destructuring assignment](#destructuring-assignment)\n    -   [Restore `addr`](#restore-addr)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [No `ref`, only pointers](#no-ref-only-pointers)\n    -   [Remove pointers after adding references](#remove-pointers-after-adding-references)\n    -   [Allow `ref` bindings in the fields of classes](#allow-ref-bindings-in-the-fields-of-classes)\n    -   [No call-site annotation](#no-call-site-annotation)\n    -   [Top-level `ref` introducer](#top-level-ref-introducer)\n    -   [Allow immutable value semantic bindings nested within variable patterns](#allow-immutable-value-semantic-bindings-nested-within-variable-patterns)\n    -   [Remove `var` as a top-level statement introducer](#remove-var-as-a-top-level-statement-introducer)\n    -   [`ref` as a type qualifier](#ref-as-a-type-qualifier)\n    -   [`bound` would change the default return to `val`](#bound-would-change-the-default-return-to-val)\n    -   [Other return conventions](#other-return-conventions)\n    -   [`return var` with compound return forms](#return-var-with-compound-return-forms)\n    -   [Other syntax for compound return forms](#other-syntax-for-compound-return-forms)\n    -   [`ref` parameters allow aliasing](#ref-parameters-allow-aliasing)\n    -   [`let` to mark value returns instead of `val`](#let-to-mark-value-returns-instead-of-val)\n    -   [`=>` infers form, not just type](#-infers-form-not-just-type)\n\n<!-- tocstop -->\n\n## Abstract\n\n-   A parameter binding can be marked `ref` instead of `var` or the default. It\n    will bind to reference argument expressions in the caller and produces a\n    reference expression in the callee.\n    -   Unlike pointers, a `ref` binding can't be rebound to a different object.\n    -   This replaces `addr`, and is not restricted to the `self` parameter.\n    -   A `ref` binding, like a value binding, can't be used in fields of\n        classes or structs.\n    -   When calling functions, arguments to non-`self` `ref` parameters are\n        also marked with `ref`.\n-   The return of a function can optionally be marked `ref`, `val`, or `var`.\n    These control the category of the call expression invoking the function, and\n    how the return expression is returned.\n    -   These may be mixed for functions returning tuple or struct forms.\n-   Any parameters whose lifetime needs to contain the lifetime of the return\n    must be marked `bound`.\n-   The address of a `ref` binding is `nocapture` and `noalias`.\n-   We mark parameters of a function that may be referenced by the return value\n    with `bound`.\n\n## Problem\n\nReference bindings have come up multiple times:\n\n-   as a better alternative to `addr self: Self*`;\n-   for use in [lambda captures](/docs/design/lambdas.md);\n-   to model different kinds of C++ references for interop and migration;\n-   to support nested bindings within a destructured `var`, see\n    [issue #5250](https://github.com/carbon-language/carbon-lang/issues/5250)\n    and\n    [proposal #5164](https://github.com/carbon-language/carbon-lang/pull/5164);\n-   for forwarding arguments while preserving\n    [expression category](/docs/design/README.md#expression-categories);\n-   to add a feature to pattern matching to modify things after they have been\n    matched;\n-   to support refactoring code without changing all the uses of a name, a\n    problem we are already seeing with `self` and `addr self`, and would be a\n    point of friction in local pattern matching in the future; and\n-   to support breaking up an expression into pieces without altering the\n    expression category of individual pieces.\n\nReference returns have also come up before, particularly to support operators\nsuch as indexing `[`...`]` and other functions that should produce a reference\nexpression. It is desirable, though, that this not introduce new memory unsafety\nconcerns, due to returning a reference to something with insufficient lifetime.\n\nIn addition, we have been interested in adding other return mechanisms that\nsupport returning values in registers in cases that our current convention\nwon't.\n\n## Background\n\n-   Carbon has\n    [reference expressions](/docs/design/values.md#reference-expressions).\n-   Using\n    [the `addr` keyword on mutating methods to get a `self` with a pointer type](/docs/design/classes.md#methods)\n    was introduced in\n    [proposal #722: \"Nominal classes and methods\"](/proposals/p0722.md#keyword-to-indicate-pass-by-address).\n-   [Leads issue #5261: \"We should add `ref` bindings to Carbon, paralleling reference expressions\"](https://github.com/carbon-language/carbon-lang/issues/5261)\n    supports adding `ref` bindings to Carbon.\n-   [LLVM's `noalias` attribute](https://llvm.org/docs/LangRef.html#function-attributes)\n    is used to mark a pointer as being aliased in only limited ways to enable\n    optimization. Also see\n    [LLVM's pointer aliasing rules](https://llvm.org/docs/LangRef.html#pointer-aliasing-rules).\n-   Marking a pointer as not captured, to allow optimizations, was originally\n    done with\n    [LLVM's `nocapture` attribute](https://releases.llvm.org/11.0.0/docs/LangRef.html#parameter-attributes),\n    which has become\n    [`captures(none)` and `captures(ret: address, provenance)`](https://llvm.org/docs/LangRef.html#function-attributes),\n    which is governed by\n    [pointer capture rules](https://llvm.org/docs/LangRef.html#pointer-capture).\n-   Clang allows C++ code to use the\n    [`clang::lifetimebound` attribute](https://clang.llvm.org/docs/AttributeReference.html#lifetimebound)\n    to mark parameters that may be referenced by the return value, in order to\n    detect some classes of use-after-free memory-safety bugs.\n-   [C++ has reference types](https://en.cppreference.com/w/cpp/language/reference).\n\n## Proposal\n\n### `ref` bindings\n\nWe introduce a new keyword `ref`. This may be added to a `:` binding to mark it\nas binding to a reference expression, as in:\n\n```carbon\nfn F(ptr: i32*) {\n  // A reference binding `x`.\n  let ref x: i32 = *ptr;\n\n  // Use of `x` is a reference expression that\n  // refers to the same object as `*ptr`.\n  Assert(&x == ptr);\n\n  // Equivalent to `*ptr += 1;`.\n  x += 1;\n}\n\nfn G() {\n  var y: i32 = 2;\n  F(&y);\n  Assert(y == 3);\n}\n```\n\nThe use of the name (`x` in the example) of a `ref` binding forms a durable\nreference expression. We ensure that reference expressions formed by way of\nreference bindings _do not dangle_. A `ref` binding may only bind to a durable\nreference expression or an expression that can be converted to one. The bound\ndurable reference expression must outlive the `ref` binding.\n\nThe address of a `ref` bound name gives the address of the bound object, so\n`&x == ptr` above. The reference itself does not have an address, and unlike a\npointer can't be rebound to reference a different object.\n\nWe remove `addr`, and use instead use `ref` for the `self` parameter when an\nobject is required. Note that the type will change from `Self*` to `Self` in\nthis case. In the future, we might\n[re-add `addr` back if needed](#restore-addr).\n\n```carbon\nclass C {\n  // ❌ No longer valid.\n  fn OldMethod[addr self: Self*]() {\n    // Previously would dereference `self` in\n    // the body of the method.\n    self->x += 3;\n  }\n\n  // ✅ Now valid.\n  fn NewMethod[ref self: Self]() {\n    // Now `self` is a reference expression,\n    // and is not dereferenced.\n    self.x += 3;\n  }\n\n  // ✅ Other uses are unchanged.\n  fn Get[self: Self]() -> i32 {\n    return self.x;\n  }\n\n  var x: i32;\n}\n```\n\nPotentially abbreviating the syntax further (to allow `ref self` as a short form\nof `ref self: Self`) is left as future work.\n\nThe `ref` modifier is allowed on `:` bindings that are not:\n\n-   inside a `var` pattern,\n-   a field of a `class` type, or\n-   a field of a struct type.\n\n```carbon\nfn AddTwoToRef(ref x: i32) {\n  x += 1;\n  let ref y: i32 = x;\n  y += 1;\n}\n\n// Equivalent to:\nfn AddTwoToRef(ref x: i32) {\n  x += 1;\n  let y_ptr: i32* = &x;\n  *y_ptr += 1;\n}\n```\n\nWe add support for `ref` and `var` in a\n[struct pattern](/docs/design/pattern_matching.md#struct-patterns) when using\nthe shorthand `a: T` syntax for `.a = a: T`:\n\n```carbon\nlet {var a: i32, ref b: i32} = ...;\n\n// Now equivalent to:\nlet {.a = var a: i32, .b = ref b: i32} = ...;\n```\n\n> Note: This takes us one step closer to `{` ambiguity. Previously we could\n> distinguish between a struct literal/pattern and a non-empty block with only\n> up to two tokens of lookahead (the struct cases start with `.` or `_` or\n> identifier followed by `:`, and the block cases don't). Now we have things\n> like:\n>\n> ```carbon\n> fn F() -> X { var a: i32 = 0; }\n> ```\n>\n> ... where we're getting incrementally closer to ambiguity. We've got a few\n> more steps before we get there, though, since we don't have an `X{...}`\n> expression yet, and `var ...` is only allowed in struct patterns rather than\n> struct expressions. So we're still fine, but this is cutting down our options\n> for future syntactic expansion a little.\n\nThe `ref` modifier is forbidden on the bindings in `class` or struct type\nfields.\n\n```\nvar outer_size: i32 = 123;\n\nclass Invalid {\n  // ❌ Invalid. We don't currently have runtime `let` bindings in classes,\n  // or `ref` on `var`s, but the intent is to not have `ref` bindings as fields.\n  let ref invalid_ref_field: i32 = outer_size;\n}\n\n// ❌ Invalid.\nvar invalid_struct_type_field:\n    {ref .invalid: i32} = {.invalid = outer_size};\n```\n\nIn a function argument list, arguments to non-`self` `ref` parameters are also\nmarked with `ref`. Continuing the example:\n\n```carbon\nvar z: i32 = 3;\nAddTwoToRef(ref z);\nAssert(z == 5);\n\n// No `ref` though on the `self` argument.\nvar c: C = {.x = 4};\nc.NewMethod();\nAssert(c.Get() == 7);\n```\n\n> **Note:** It is important that this restriction is syntactic, not just\n> semantic, because it means that `ref` is never the first token of a full\n> expression, and so we know without lookahead that a `ref` in a pattern context\n> must be the start of a binding pattern, not the start of an expression\n> pattern.\n\nNormally an argument to a non-`ref` parameter should not be marked `ref`, but it\nis allowed in a generic context where the parameter may sometimes be `ref`.\n\nExpression operators will mostly not take `ref` parameters, with these\nexceptions:\n\n-   [the address-of operator](/docs/design/expressions/pointer_operators.md)\n    `&`;\n-   the first operand of\n    [the indexing operator](/docs/design/expressions/indexing.md) `[`...`]`; and\n-   [the member access operator](#use-case-member-binding-interfaces) introduced\n    in\n    [proposal #3720: \"Member binding operators\"](https://github.com/carbon-language/carbon-lang/pull/3720)\n    `.`.\n\nThe statement operators now use `ref` instead of pointers:\n\n-   the left-hand operand of [assignment operators](/docs/design/assignment.md)\n    such as `=` and `+=`.\n-   [the `++` and `--` operators](/docs/design/assignment.md).\n\nEven in these cases, the arguments will not be marked with `ref` at the call\nsite. (Generally the `ref` parameter is the `self` parameter, and so wouldn't be\nmarked. The exception is `BindToRef`, but we don't want to mark its argument\nwith `ref`.)\n\nAs an _experiment_, we are saying a pointer formed by taking the address of a\n`ref` bound name is LLVM-`captures(none)` and LLVM-`noalias`. This means that\nwhile a `ref` parameter could be passed into a function by address, the\nrestrictions also allow a \"move-in-move-out\" approach (once we define the move\noperation), assuming it is not [marked `bound`](#bound-parameters). The intent\nhere is to leave the door open to a calling convention using registers and less\nindirection for small-enough objects.\n\nThis means that the following code is invalid:\n\n```carbon\nfn F(ref a: i32, ref b: i32) -> bool;\n\nfn G() -> bool {\n  var v: i32 = 1;\n  return F(ref v, ref v);\n}\n```\n\nEnforcing this restriction will be part of the memory safety story. Until then,\ndoing this is erroneous behavior. This\n[means](#no-optimization-on-erroneous-behavior) that the compiler won't use\nthose LLVM attributes unless the compiler can itself prove that the restrictions\nhold.\n\n### `ref` and `val` returns\n\nThe return of a function can optionally be marked `ref` or `val`. These control\nthe category of the call expression invoking the function, and how the return\nexpression is returned.\n\n```carbon\nvar global: i32 = 2;\nfn ReturnRef() -> ref i32 {\n  // ❌ Invalid: return 2;\n\n  // ✅ Valid: return a reference expression with\n  // sufficient lifetime.\n  return global;\n}\n// Call `ReturnRef` and use the resulting reference.\nReturnRef() += 3;\nAssert(global == 5);\n\n// Result of `ReturnRef` can be bound using a `ref`\n// binding.\nfn AddFive() {\n  let ref r: i32 = ReturnRef();\n  r += 5;\n}\nAddFive();\nAssert(global == 10);\n\nfn ReturnVal() -> val i32 {\n  return 2;\n}\n// ReturnVal() is a value expression.\nlet l: i32 = ReturnVal();\n\n// Returning an initializing expression is the\n// default.\nfn ReturnDefault() -> i32 {\n  return 2;\n}\n// ReturnDefault() is an initializing expression.\nvar j: i32 = ReturnDefault();\n\n// Use `var` to explicitly specify returning an\n// initializing expression.\nfn ReturnVar() -> var i32 {\n  return 2;\n}\n// `ReturnVar()` is the same as `ReturnDefault()`.\n```\n\n-   A call to a function declared `-> ref T` is a durable reference expression.\n    The generated code for that function will return the address of a `T`\n    object.\n-   A call to a function declared `-> val T` is a value expression. The function\n    will return the value representation of `T`. Since values have no address,\n    the value representation may be returned in registers.\n-   The behavior of a call to a function declared `-> T` is unchanged. It is an\n    initializing expression, returning in place or by copy depending on the\n    initializing representation of `T`. This is the same behavior as `-> var T`.\n-   The behavior of `auto` as the return type is unchanged, but now supports an\n    optional `ref`, `val`, or `var` between the `->` and `auto`. `-> auto`\n    continues to return an initializing expression, as does `-> var auto`.\n    `-> val auto` returns a value expression, and `-> ref auto` returns a\n    durable reference expression.\n-   Using `=>` to specify a return continues to return an initializing\n    expression, as before. See\n    [this relevant alternative considered](#-infers-form-not-just-type).\n\nA function may have multiple returns, each with their own marker, by using a\ntuple or struct compound return form.\n\n```carbon\nfn TupleReturn() -> (val bool, ref i32, C) {\n  return (true, global, {.x = 3});\n}\n\nfn StructReturn()\n    -> {.a: val bool,\n        .b: ref i32,\n        .c: C} {\n  return {.a = true,\n          .b = global,\n          .c = {.x = 3}};\n}\n```\n\nIf the return of a function may reference the storage of one or more parameters\nto the function, those parameters must be marked `bound`. This allows the\ncompiler to diagnose if the function's return is used after the lifetime of the\n`bound` parameter ends. The semantics of `bound` are intended to match the\n[`clang::lifetimebound` attribute](https://clang.llvm.org/docs/AttributeReference.html#id8).\n\n```carbon\nfn Member(bound ref c: C) -> ref i32 {\n  return c.x;\n}\n\n// Lifetime of a pointer includes the lifetime\n// of what it points to.\nfn Deref(bound p: i32*) -> ref i32 {\n  return *p;\n}\n\nfn Both(bound pc: C*) -> ref i32 {\n  return p->x;\n}\n\nfn Invalid1() -> ref i32 {\n  var x: i32 = 4;\n  // ❌ Error: returning reference to `x`\n  // whose lifetime ends when this function\n  // returns.\n  return x;\n}\n\nfn Invalid2() -> ref i32 {\n  var c: C = {.x = 1};\n  // ❌ Error: returning reference bound to `c`\n  // whose lifetime ends when this function\n  // returns.\n  return Member(c)\n}\n```\n\nThe address of a `bound ref` parameter is the\n[LLVM attribute `captures(ret: address, provenance)`](#background) instead of\n[`captures(none)`](#background).\n\n## Details\n\nThe intent is that we would encourage using references instead of pointers when\npossible. Their benefits are related to their limitations, so to get those\nbenefits we should use them when a use is restricted enough to be within those\nlimitations.\n\n### Compound return forms and patterns\n\nMirroring the [tuple](/docs/design/pattern_matching.md#tuple-patterns) and\n[struct](/docs/design/pattern_matching.md#struct-patterns) pattern forms, we\nalso support tuple and struct return forms.\n\n```carbon\n// `->` begins a \"return form\"\nfn F()     -> <return-form>;\n\n// Within any return form, if the first token is\n// `val`, `ref`, `var`, `(`, or `{`, it is not\n// treated as type expression:\n\n// Value return, with type as specified\nfn Val()   -> val <type-expr>\n\n// Reference return, with type as specified\nfn Ref()   -> ref <type-expr>\n\n// Initializing return, with type as specified\nfn Var()   -> var <type-expr>\n\n// Tuple compound return, with a list of\n// return forms.\nfn TupleCompound() -> ( <return-form>, ... )\n// Tuple return, with a list of type\n// expressions. Used if all members of the\n// list are type expressions.\nfn Tuple() -> ( <type-expr>, ... )\n\n// Struct compound return, with a mapping from\n// designators to return forms.\nfn StructCompound()\n    -> { .<id>: <return-form>, ... }\n// Struct return, used if all of the members\n// are type expressions.\nfn Struct() -> { .<id>: <type-expr>, ... }\n\n// Otherwise, implicit `var` means returns\n// an initializing expression.\nfn Other() -> <type-expr>\n```\n\nNote that in the absence of `val`, `ref`, and `var` keywords, the implicit `var`\nis placed in the outermost position, minimizing the number of primitive forms\nreturned. So `fn F() -> (i32, i32)` means `fn F() -> var (i32, i32)` not\n`fn F() -> (var i32, var i32)`. Generally the `var` is left off if not required,\nand so will be rare in return forms, to minimize confusion with `val`.\n\n```carbon\nfn TupleReturn(...)\n    -> (val bool, ref i32, C);\n// Equivalent to:\n//  -> (val bool, ref i32, var C);\n\nlet (a: bool, ref b: i32, var c: C)\n    = TupleReturn(...);\n\nfn StructReturn(...)\n    -> {.a: val bool,\n        .b: ref i32,\n        .c: C};\n// Equivalent to:\n//  -> {.a: val bool,\n//      .b: ref i32,\n//      .c: var C};\n\n// Binds to the names `x`, `y`, `z`:\nlet {.a = x: bool,\n     .b = ref y: i32,\n     .c = var z: C} = StructReturn(...);\n\n// Binds to the names `a`, `b`, `c`:\nlet {a: bool,\n     ref b: i32,\n     var c: C} = StructReturn(...);\n\n// Above two can be mixed, binding to\n// names `a`, `y`, `z`.\nlet {a: bool,\n     .b = ref y: i32\n     .c = var z: C} = StructReturn(...);\n```\n\nOnly types are allowed after a `-> val`, `-> ref`, or `-> var`, not a compound\nreturn form. Examples:\n\n```carbon\n// Returns a tuple of type\n// `(bool, f32, C, i32)`.\nfn OneTupleReturn(...)\n    -> (bool, f32, C, i32);\n\n// Returns a compound tuple form\nfn CompoundReturn(...)\n    -> (bool, val f32);\n// Equivalent to:\n//  -> (var bool, val f32);\n\n// ❌ Invalid, can't specify `ref` inside\n// of `val`.\nfn Invalid(...) -> val (bool, ref f32);\n```\n\nThe compound return forms may be nested, as in:\n\n```carbon\nfn CompoundInParens(...)\n    -> ({.a: bool, .b: val f32}, C, ref i32);\n// Equivalent to:\n//  -> ({.a: var bool, .b: val f32}, var C, ref i32);\n\nlet ({.a = var x: bool, .b = val y: f32},\n     var c: C, ref d: i32) = CompoundInParens(...);\n// or without renaming:\nlet ({var a: bool, b: f32},\n     var c: C, ref d: i32) = CompoundInParens(...);\n\n// Contrast with a compound tuple form containing\n// a struct type (not compound):\nfn StructInParens(...)\n    -> ({.a: bool, .b: f32}, C, ref i32);\n// Equivalent to:\n//  -> (var {.a: bool, .b: f32}, var C, ref i32);\n\nfn CompoundInBraces(...)\n    -> {.a: bool, .b: (val f32, C), .c: ref i32};\n// Equivalent to:\n    -> {.a: var bool, .b: (val f32, var C), .c: ref i32};\n\nlet {a: bool,\n     .b = (x: f32, var y: C),\n     ref c: i32} = ParensInBraces(...);\n\n// Contrast with a compound struct form containing\n// a tuple type (not compound):\nfn TupleInBraces(...)\n    -> {.a: bool, .b: (f32, C), .c: ref i32};\n// Equivalent to:\n    -> {.a: var bool, .b: var (f32, C), .c: ref i32};\n```\n\nThis feature is intended to support cases like `enumerate` that will want to\nreturn a value for the index but a reference to the element of the sequence\nbeing enumerated.\n\n### Nested binding patterns\n\nSince a `ref` binding may only bind to a durable reference expression, it can't\nbe used to bind the result of a function returning an initializing expression.\nHowever, if the initializing expression is bound to a `var`, any nested patterns\nare reference binding patterns bound to the subobject, following\n[proposal #5164: \"Updates to pattern matching for objects\"](https://github.com/carbon-language/carbon-lang/pull/5164).\n\nFor example:\n\n```carbon\nfn F() -> (bool, (C, i32));\nlet (b: bool, var (c: C, i: i32)) = F();\n```\n\nis equivalent to:\n\n```carbon\nfn F() -> (bool, (C, i32));\nlet (b: bool, var v: (C, i32)) = F();\nlet ref c: C = v.0;\nlet ref i: i32 = v.1;\n```\n\nNote that `ref` is disallowed inside `var` since that would be redundant.\n\n### Mututation restriction on objects bound to a value\n\nMutation of objects with a non-copy-value representation in an active value\nbinding (\"borrowed objects\") is erroneous behavior.\n\n-   Our plan is to prevent mutation of borrowed objects in Carbon's strict safe\n    dialect.\n    -   We should only relax our stance here and consider making such mutation\n        _allowed_ if we discover difficulty with this that we cannot overcome.\n    -   But we _should_ revisit the underlying idea of mutation being erroneous\n        if enforcing it in the strict mode proves fundamentally untenable due to\n        ergonomic costs.\n-   There will always be the potential for unchecked code, either unsafe Carbon\n    code or C++ code by way of interop, to mutate a borrowed object, hence the\n    need to define it as erroneous behavior.\n-   There is no need to ever make it anything more than erroneous behavior, see\n    below.\n-   If we can prove the mutation doesn't occur, then we can use that to optimize\n    under \"as-if\", and we don't need anything else.\n-   We are deferring the decision of whether strict enforcement is enabled in\n    Carbon's current C++-friendly mode, when not explicitly marking the code as\n    \"unsafe.\"\n\nThis was\n[discussed 2025-05-22](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.uot97ukynlsi)\nand then made the subject of\n[leads issue #5524](https://github.com/carbon-language/carbon-lang/issues/5524).\n\n### No optimization on erroneous behavior\n\nThe Carbon compiler should not optimize on erroneous behavior, ever, unless the\ncompiler literally proves that it does not occur, ever. In which case, we don't\nneed any license to start optimizing on this, as it falls under \"as-if\".\n\nThe fact that undefined behavior (\"UB\",\n[cppreference](https://en.cppreference.com/w/cpp/language/ub.html),\n[wikipedia](https://en.wikipedia.org/wiki/Undefined_behavior)) provides \"as-if\"\n_without_ a proof is precisely the risk of using UB for any semantics, and why\nwe don't use it here and elsewhere we use erroneous behavior.\n\n### `bound` parameters\n\nIt is erroneous behavior to return something that references a local object that\nwon't live once the function returns, even if it is a parameter marked `bound`.\nLocal objects include local variables, temporary objects, and `var` parameters.\n\n```carbon\nfn Invalid1() -> i32* {\n  var x: i32 = 4;\n  // ❌ Invalid.\n  return &x;\n}\n\nfn Invalid2(bound x: i32) -> ref i32 {\n  var y: i32 = x;\n  // ❌ Invalid.\n  return y;\n}\n\n// ✅ Valid\nfn Valid1(bound p: i32*) -> ref i32 {\n  return *p;\n}\n\nfn Invalid3(bound var x: i32) -> ref i32 {\n  // ❌ Invalid: lifetime of `var` parameter\n  // ends when function returns.\n  return x;\n}\n\nclass ReturnMember {\n  // ✅ Valid\n  fn ValidRef[bound ref self: Self]() -> ref i32 {\n    return self.m;\n  }\n\n  // ❌ Invalid: can't return reference to value.\n  fn InvalidVal[bound self: Self]() -> ref i32 {\n    return self.m;\n  }\n\n  // ❌ Invalid: `var self` lifetime ends.\n  fn InvalidVar[bound var self: Self]()\n      -> ref i32 { return self.m; }\n\n  var m: i32;\n}\n\nclass DerefPointerMember {\n  // ✅ Valid\n  fn ValidRef[bound ref self: Self]() -> ref i32 {\n    return *self.pm;\n  }\n\n  // ✅ Valid\n  fn ValidVal[bound self: Self]() -> ref i32 {\n    return *self.pm;\n  }\n\n  // ✅ Valid\n  fn ValidVar[bound var self: Self]()\n      -> ref i32 { return *self.pm; }\n\n  var pm: i32*;\n}\n```\n\nOtherwise, `bound` parameters and global variables are the sources of storage\nthat can be referenced by a return, but need not be referenced, particularly not\non every code path.\n\n```carbon\n// Result references `r` if `b` is true, and `p`\n// otherwise. Valid as long as both are marked `bound`.\nfn Conditional(b: bool, bound ref r: C, bound p: C*)\n    -> ref C {\n  if (b) {\n    return r;\n  } else {\n    return *p;\n  }\n}\n```\n\nThe parameters of functions defined in an interface may also be marked as\n`bound`. The `impl` of that interface for a type can omit occurrences of `bound`\nfrom the interface, but cannot add new ones.\n\n```carbon\ninterface I {\n  fn F[bound ref self: Self]\n      (a: Self, bound b: Self, bound c: Self*)\n      -> ref Self;\n}\n\nimpl C1 as I {\n  // ✅ Valid: matches interface\n  fn F[bound ref self: Self]\n      (a: Self, bound b: Self, bound c: Self*)\n      -> ref Self;\n}\n\nimpl C2 as I {\n  // ✅ Valid: proper subset of `bound` params\n  fn F[ref self: Self]\n      (a: Self, bound b: Self, c: Self*)\n      -> ref Self;\n}\n\nimpl C2 as I {\n  // ❌ Invalid: `a` is not bound in `I.F`.\n  fn F[ref self: Self]\n      (bound a: Self, b: Self, c: Self*)\n      -> ref Self;\n}\n```\n\nLike `[[clang::lifetimebound]]` in C++, `bound` does not affect semantics or\ncalling conventions, just what code is legal. This helps avoid mismatches\nbetween typechecking against the signatures in an interface when the `impl`\nfunctions are different. Exception: the question of whether `bound` affects the\nlifetime of temporaries is [future work](#temporary-lifetimes).\n\nNote that all combinations of a `val`/`ref`/default return can be bound to a\nvalue/`ref`/`var` parameter. Examples:\n\n```carbon\nfn RefToVal(bound ref x: C) -> val D { return x.d; }\nfn ValToRef(bound y: C) -> ref D { return *y.ptr; }\nfn VarToRef(bound var p: i32*) -> ref i32 { return *p; }\nfn VarToDefault(bound var p: i32*) -> i32* { return p; }\n```\n\nFor full safety, we need each bound parameter to be immutable for the duration\nof the lifetime of the returned result. However, the objective for now is only\nmatching `[[clang::lifetimebound]]`, which has the goal of preventing some\nclasses of bugs, not full memory safety. We will reconsider this with the memory\nsafety design.\n\nClang's `lifetimebound` attribute also only applies to the immediately pointed\nto objects (by pointers or reference parameters, or pointers or reference\nsubobjects of an aggregate parameter). We suggest a simpler, transitive model\nhere that is more restrictive but should be compatible. That said, pinning down\nthe exact and firm semantics of `bound`, especially in these complex cases, is\ndeferred to the full memory safety design as well.\n\n### How addresses interact with `ref`\n\nThe address of a `ref` binding is `noalias` and either `captures(none)` or\n`captures(ret: address, provenance)`, depending on whether the binding is marked\n`bound`.\n\n-   `noalias` means like C `restrict`; you can't observe mutations through\n    aliases; mutation through a restricted pointer is not observable through\n    another pointer\n-   `captures(none)` means there is no transitive escape: you can pass a\n    nocapture pointer to another nocapture function, but you can't store to\n    memory or return\n-   `captures(ret: address, provenance)`: is like `captures(none)` but may be\n    referenced by a return.\n\nThe combination of `noalias` and `captures(none)` semantics are the minimum for\nthe \"move-in-move-out\" optimization. But this condition is hard to check, so\nsafe code will use a stricter criteria. Unsafe code will be required to adhere\nto just the `noalias` restrictions, but will not be checked (except possibly by\na sanitizer at runtime). The details here will be tackled as part of the memory\nsafety design.\n\nOptimizations will only be performed based on information that is enforced or\nchecked by the compiler, so these attributes won't be passed to LLVM unless\ntheir requirements can be established. This avoids introducing undefined\nbehavior, which we particularly don't want to do in situations where C++\ndoesn't.\n\nThe goal of these rules it to nudge us towards function boundaries that don't\nconstructively create aliasing in their API boundary and don't capture pointers\nunnecessarily.\n\nThese restrictions are experimental, and we should keep track of everything we\nend up needing to do to work around these restrictions so any reconsideration\ncan be properly informed.\n\n### Improved interop and migration with C++ references\n\nWe expect this to improve interop and migration by allowing significantly more\ninterface similarity between Carbon and C++. Previously, many things in C++ that\nused references on interface boundaries would be forced to switch to pointers.\nThis adds ergonomic friction both at a basic level because of the forced change\nbut also a deeper level because it will make it significantly harder to see the\nparallel usage across the boundary between C++ and Carbon. With reference\nbindings, the vast majority of this dissonance will be removed.\n\nThis does create a migration concern, raised in\n[open discussion on 2025-05-01](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.dffumsu6wzlc),\nthat the `nocapture` and `noalias` modifiers don't match C++ restrictions,\nparticularly on the `this` parameter that we are going to require migrate to\n`ref self`. We may have to add back in `addr` to allow a different pointer type\nfor those cases.\n\n> **Future work:** Addressing how we model the various kinds of C++ references\n> that Carbon code may need to interact with is\n> [something we are actively considering](https://docs.google.com/document/d/1l5TbNuwZEcwm96ejGPLn9GdoQO1fByUW0tFRLU9BqXE/edit?tab=t.0)\n> and will be tackled in a future proposal.\n\n### Part of the expression type system, not object types\n\nMuch like value/`val` and `var` bindings, `ref` binding and the new return forms\nare are part of the type system, but only through expression categories,\npatterns (function parameters and so on), and returns. Specifically, we don't\nexpect them to be part of the _object types_ in Carbon. Like value bindings, we\nretain a great deal of implementation flexibility around layout, and the\nspecifics of how they are lowered.\n\nThis specifically means we will need to incorporate `ref` bindings into the\n`Call` interface and we will be adding complexity there that will need to be\nhandled by overloading. The changes to the `Call` interface is future work, and\noverloading, once we add support, will need to carry additional complexity to\nhandle `ref`.\n\n### Interaction with `returned var`\n\nThe rule is: `returned var` may only be used when there is a single atomic\nreturn form, and it is the default `var` category.\n\n```carbon\n// ✅ Allowed\nfn F(...) -> V {\n  returned var v: V = ...;\n  // ...\n  return var;\n}\n\nfn F(...) -> {var .a : T} {\n  // ❌ Invalid: composite form\n  returned var ret: T = ...;\n  // ...\n}\n\nfn F(...) -> val T {\n  // ❌ Invalid: value return\n  returned var ret: T = ...;\n  // ...\n}\n```\n\nWe can revisit and expand this later if this does not handle use cases we would\nlike to support.\n\n### Use case: `Deref` interface\n\nTo support customization of the prefix-`*` dereferencing operator, we introduce\nthe `Deref` interface.\n\n```carbon\ninterface Deref {\n  let Result:! type;\n  fn Op[bound ref self: Self]() -> ref Result;\n}\n\nfinal impl forall [T:! type] T* as Deref {\n  where Result = T;\n  fn Op[bound self: Self]() -> ref T\n      = \"builtin.deref\";\n}\n```\n\nThen `*p` is rewritten to `p.(Deref.Op)()`, and `p->m` is rewritten to\n`p.(Deref.Op)().m`. For example, this might be used by a smart pointer:\n\n```\nclass SmartPtr(T:! type) {\n  fn Make(p: T*) -> Self { return {.ptr = p}; }\n  impl as Deref {\n    where Result = T;\n    fn Op[bound ref self: Self]() -> ref Result {\n      return *self.ptr;\n    }\n  }\n  private var ptr: T*;\n}\n```\n\n### Use case: indexing interfaces\n\n[Proposal #2274: \"Subscript syntax and semantics\"](https://github.com/carbon-language/carbon-lang/pull/2274)\nadded the interfaces used to support indexing with the subscripting operator\n`[`...`]`. We change these in the following ways:\n\n-   The `addr self` parameters are changed to `bound ref self`, to allow the\n    result to reference the `self` object.\n-   The `At` method returns by `val`.\n-   The `Addr` methods are renamed `Ref` and return a reference instead of a\n    pointer that is automatically dereferenced.\n\n[This proposal's PR](https://github.com/carbon-language/carbon-lang/pull/5434)\nmakes those changes to the\n[indexing design](/docs/design/expressions/indexing.md).\n\n### Use case: member binding interfaces\n\nThe member binding interface used for reference expressions from\n[proposal #3720](https://github.com/carbon-language/carbon-lang/pull/3720) can\nnow be changed to use references instead of pointers.\n\nBefore:\n\n```carbon\n// For a reference expression `x` with type `T`\n// and an expression `y` of type `U`, `x.(y)` is\n// `*y.((U as BindToRef(T)).Op)(&x)`\ninterface BindToRef(T:! type) {\n  extend impl as Bind(T);\n  fn Op[self: Self](p: T*) -> Result*;\n}\n```\n\nAfter:\n\n```carbon\n// For a reference expression `x` with type `T`\n// and an expression `y` of type `U`, `x.(y)` is\n// `y.((U as BindToRef(T)).Op)(x)`\ninterface BindToRef(T:! type) {\n  extend impl as Bind(T);\n  fn Op[self: Self](bound ref p: T) -> ref Result;\n}\n```\n\nSimilarly, the `BindToValue` interface is changed to use a `val`/value return,\npotentially avoiding a copy of large objects.\n\nBefore:\n\n```carbon\ninterface BindToValue(T:! type) {\n  extend Bind(T);\n  fn Op[self: Self](x: T) -> Result;\n}\n```\n\nAfter:\n\n```carbon\ninterface BindToValue(T:! type) {\n  extend Bind(T);\n  fn Op[self: Self](bound x: T) -> val Result;\n}\n```\n\n### Use case: class accessors\n\nA `ref` return can be used to expose the state of an object in a way that can be\nmutated:\n\n```carbon\nclass Four {\n  fn Get[self: Self](i: i32) -> i32 {\n    Assert(i >= 0 and i < 4);\n    return self.m[i];\n  }\n  fn GetMut[bound ref self: Self](i: i32) -> ref i32 {\n    Assert(i >= 0 and i < 4);\n    return self.m[i];\n  }\n  private var m: array(i32, 4);\n}\n\nvar x: HasMember = {.m = (0, 2, 4, 6)};\nx.GetMut(2) += 1;\nfn Check(y: Four) {\n  Assert(y.Get(2) == 5);\n}\nCheck(x);\n```\n\n**Future work**: this will in the future often be done with an overloaded\nmethod, as in:\n\n```carbon\nclass Four {\n  overload Access {\n    fn [bound ref self: Self](i: i32) -> ref i32 {\n      Assert(i >= 0 and i < 4);\n      return self.m[i];\n    }\n    fn [self: Self](i: i32) -> i32 {\n      Assert(i >= 0 and i < 4);\n      return self.m[i];\n    }\n  }\n  private var m: array(i32, 4);\n}\n\nvar x: HasMember = {.m = (0, 2, 4, 6)};\nx.Access(2) += 1;\nfn Check(y: Four) {\n  Assert(y.Access(2) == 5);\n}\nCheck(x);\n```\n\nThis may be a common enough use case that we will want to introduce a dedicated\nsyntax:\n\n```carbon\nclass HasMember {\n  fn Access[bound ref? self: Self](i: i32) -> ref? i32 {\n    Assert(i >= 0 and i < 4);\n    return self.m[i];\n  }\n  private var m: array(i32, 4);\n}\n```\n\n### Type completeness\n\nNot a change by this proposal, but note that our existing rules will require the\ntype in a `ref` binding to be complete in situations where it would not need to\nbe if you were using a value binding with a pointer type instead. We may need to\nchange this in the future to match C++ which treats reference types more like\npointer types for completeness purposes.\n\nAfter this change, a `ref` binding to type `T` will require `T` to be complete\nin the same situations that other bindings to type `T` require `T` to be\ncomplete.\n\n### Pointer value representation\n\nPurely as a change in syntax, the way to specify that\n[the value representation of a class](/docs/design/values.md#value-representation-and-customization)\nuses a pointer is changed from writing `const Self *` to `const ref`.\n\n## Future work\n\n### Temporary lifetimes\n\nFor safety, we need bindings and returns that reference storage to only be used\nwhile that storage remains valid. When the referenced storage is owned by a\ntemporary, we have a choice to either control the lifetime of the temporary or\ndiagnose when the lifetime of the temporary is insufficient. Deciding on our\npolicy is future work.\n\nNote that in many cases we can explicitly provide storage in a variable instead\nof referencing a temporary. For example, using\n`var x: ... = ReturnsATemporary();` instead of\n`let ref x: ... = ReturnsATemporary();`. This won't apply in all situations,\nthough, such as temporaries that are reachable transitively through pointers.\n\n### `ref` bindings in lambdas\n\nWe have already identified\n[future work to support reference captures in lambdas as part of proposal #3848](/proposals/p3848.md#future-work-reference-captures).\nThis might be a reason to support `ref` bindings as fields of objects, with all\nthe restrictions that comes with that.\n\n### Interaction with effects\n\nWe still need to determine how references and the other return types interact\nwith effects, like `Optional`, errors, co-routines, and so on. For example, we\ndon't want to give up the benefits of being able to directly return a reference\nwhen a function has an error path.\n\nIt is unclear if this will mean putting references into the object type system,\nbut we may be able to handle this with additional types or the ability to\ncustomize return representations. For example, we might have an alternate\nversion of the `Optional` type that holds a reference:\n\n```carbon\nclass OptionalRef(T:! type) {\n  fn Make(bound ref r: T) -> Self {\n    return {.p = &r};\n  }\n  fn MakeEmpty() -> Self {\n    return {.p = Optional(T*).MakeEmpty()};\n  }\n  fn HasValue[self: Self]() -> bool {\n    return p.HasValue();\n  }\n  fn Get[bound ref self: Self]() -> ref Result {\n    Assert(self.HasValue());\n    return *self.p.Get();\n  }\n\n  private var p: Optional(T*);\n}\n```\n\n### More precise lifetimes\n\nMore precise lifetime tracking will be considered with the memory safety design.\nFor example, the `bound` approach does not distinguish different components of a\ncompound return, or different parts of a parameter object that might have\ndifferent lifetimes.\n\n### Combining with compile-time\n\nWe plan to support references to compile-time state when executing a function at\ncompile time. That will be part of a future proposal.\n\n### Interaction with `Call` or other interfaces\n\nFor now, `ref` is not represented in the `Call` interface introduced in\n[proposal #2875: Functions, function types, and function calls](https://github.com/carbon-language/carbon-lang/pull/2875).\nThis will be tackled together in a future proposal with other aspects of\nbindings not represented by the type, such as `var` and compile-time, along with\nbeing generic across these aspects of bindings.\n\n### Destructuring assignment\n\nHaving more support for multiple returns from a function opens the question of\nhow to do different things with the different returns. We may want a syntax for\nsaying some of the returns are bound to new names, and some are used in\nassignments to existing variables. One possibility would be to have some pattern\nsyntax for re-initializing an existing object, as in:\n\n```carbon\nfn F() -> (-> bool, ->T);\nfn G() {\n  var x: T = ...;\n  Consume(~x);\n  let (b: bool, init x) = F();\n  // Continue to use `x`...\n}\n```\n\nThis was discussed in\n[the #syntax channel on Discord on 05-19-2025](https://discord.com/channels/655572317891461132/709488742942900284/1374126123595727000).\n\n### Restore `addr`\n\nThere are two reasons we might restore `addr` as an alternative to `ref` for the\nimplicit `self` parameter:\n\n-   As a way to express uses of `self` that we want to disallow for `ref`\n    bindings generally but need an escape hatch for migrated C++ code that\n    relies on these patterns.\n-   To allow the `self` parameter to use one of the pointer semantics we create\n    as part of the upcoming memory safety design, that can't be achieved with\n    `ref`.\n\n## Rationale\n\nThis proposal tries to advance these [Carbon goals](/docs/project/goals.md):\n\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software)\n    -   Having a \"move-in-move-out\" option as a calling convention is a\n        potential performance improvement for using `ref` parameters instead of\n        pointers.\n    -   Giving additional options for the return convention gives opportunities\n        for improved performance. Having this set by explicit return markings is\n        about giving control and predictability to the code author.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   `ref` bindings and returns avoid the ceremony of round-tripping through\n        pointers.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   Checking that reference bindings are not dangling is important for\n        avoiding use-after-free bugs.\n    -   `bound` markings on parameters to allow safety equivalent to Clang's\n        `[[clang::lifetimebound]]` when returning a reference.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Including references in Carbon allows for less mismatch for C++ code\n        using references.\n\n## Alternatives considered\n\nThese ideas were discussed in open discussion on:\n\n-   [2025-05-01](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.dffumsu6wzlc)\n-   [2025-05-06](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.s42g5iv67d3c)\n-   2025-05-07\n    [a](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.sfx9d7ltud5)\n    [b](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.4zbo49wg5rmk)\n-   [2025-05-08](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.vdognq1upsf5)\n-   [2025-05-12](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.1mjh6unumnwu)\n-   [2025-05-13](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.bdznj2d0by2g)\n-   [2025-05-14](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.52tb7l2he343)\n\nThey were also discussed in the\n[#pointers-and-references channel in Discord starting 2025-05-05](https://discord.com/channels/655572317891461132/753021843459538996/1369085231038074901),\nand\n[#syntax on 2025-05-14](https://discord.com/channels/655572317891461132/709488742942900284/1372285365162872943).\n\n### No `ref`, only pointers\n\nThe rationale to add `ref` instead of staying with pointers was discussed on\n[2025-05-01](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.dffumsu6wzlc).\nIn addition to the motivating problems given in\n[the \"Problem\" section](#problem), that discussion included some additional\ndepth to the reasons to add reference bindings.\n\nThere is a tension between wanting to have mutating expressions and only having\npointers. You need some concept like a reference in order to mutate an object\nwith an expression. The question is how small a box the references are\nrestricted to, and where the line is drawn. C has lvalues, which contain\nreferences but are restricted to a quite small box. Reference bindings\nspecifically are about keeping a small box around references while still adding\nenough expressivity to support our use cases. We have started with a model\nsimilar to C, but it fell down when it comes down to composition. Decomposing an\nexpression into pieces loses the tools the expression provided to you. The\nmissing tool for that was reference bindings.\n\nWe saw how much we were leaning on value bindings. The asymmetry between having\nvalue binding but not reference bindings when have value expressions and\nreference expressions was creating pressure. For example, when accessing members\nof an object, we had to escape to pointers in that operator.\n\nOne downside of this change is that before indirections were more visible in the\ncode.\n\nAlso, this does fundamentally mean that we now have another kind of \"pointer\",\npotentially adding complexity to any memory-safety story. However, this ship\nalready sailed to some extent with value bindings. Fundamentally, bindings are\nallowed to have pointer-like semantics from a lifetime perspective, and so will\nneed to be considered as a pointer-like thing as we build out lifetime safety.\n\n### Remove pointers after adding references\n\nIf we removed pointers after adding references, we would need something\nrebindable for assignable objects. The viable path forward without separate\npointers and references is to have something rebindable like pointers but\nautomatically dereferenced like references, which is the approach Rust takes.\nSee\n[this comment on issue #5261](https://github.com/carbon-language/carbon-lang/issues/5261#issuecomment-2786462775).\n\nOne of the features of a reference is what it cannot do, and we would have to\nremove those restrictions to be able to satisfy the pointer use cases with\nreferences.\n\n### Allow `ref` bindings in the fields of classes\n\nA type with reference binding fields would need a lot of restrictions since\nreference bindings are not assignable. We did not see enough motivation to put\nreferences into objects, given the complexity that it would introduce, so we are\nkeeping references out of types for now. This could change to support lambda\nreference captures.\n\n### No call-site annotation\n\nThis question was discussed on\n[2025-05-07](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.sfx9d7ltud5).\n\nWe decided that the marking is not about lifetime, but ability to mutate. A\n`val` may reference an object in a similar way to a `ref`, restricting\noperations on the original object, but we are not going to mark `val`s since\nthose restrictions are enforced by the compiler. We thought the ability to\nmutate, though, was something important enough to highlight to readers of the\ncode, even at the expense of extra work for the writer.\n\nSwift `inout` parameters are\n[marked at caller with an `&` before the argument](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/#In-Out-Parameters).\nJordon Rose has published\n[a regret](https://belkadan.com/blog/2021/12/Swift-Regret-inout-Syntax/) that\nthey didn't use `inout` to mark the argument instead of `&`.\n\nOn the other hand, not marking is not known to be a source of bugs.\n\nThis is a \"try it and see how well it works\" sort of decision.\n\n### Top-level `ref` introducer\n\nFor now, we don't believe `let ref` to be so common as to need a shorter way to\nwrite, unlike what we do for `var`. This was considered in\n[leads issue #5523](https://github.com/carbon-language/carbon-lang/issues/5523),\nwhich provided this rationale:\n\n> I feel like this would often be used for non-local mutation due to it\n> fundamentally deporting mutable value semantics and instead having reference\n> semantics. Unlike the local mutation, that seems more worthwhile to have\n> incentives around minimizing.\n>\n> However, this seems the easiest of all to revisit later if we discover that\n> the added verbosity in practice is costing more than is worth any improvements\n> from explicitly flagging mutable reference semantics, or if we find code is\n> reaching for antipatterns due to the incentive.\n\nIn addition,\n[this comment on leads issue #5522](https://github.com/carbon-language/carbon-lang/issues/5522#issuecomment-2972029100)\nargued that it would be more consistent for `ref` and `val` to only apply to\nbindings, and not introduce patterns, like `let` and `var`.\n\n### Allow immutable value semantic bindings nested within variable patterns\n\nThis was considered in\n[leads issue #5523](https://github.com/carbon-language/carbon-lang/issues/5523),\nwhich provided this rationale:\n\n> While it may be an obvious point of orthogonality, I think it adds choice\n> without sufficient motivation, and even _having_ that choice does add some\n> complexity to the language.\n>\n> It also seems like we could add this later if there is sufficient demand when\n> we have larger usage experience body to pull from with the rest of the Carbon\n> language. Currently, the affordance that feels more natural to me is what we\n> have.\n\n> I think we're happy to see motivating use cases and revisit this. At the\n> moment, we've just not seen motivating use cases -- everything has seemed a\n> bit too contrived.\n\n### Remove `var` as a top-level statement introducer\n\nThis was considered in\n[leads issue #5523](https://github.com/carbon-language/carbon-lang/issues/5523),\nwhich provided this rationale:\n\n> Locals are important, frequent, and frequently mutable. I don't think forcing\n> varying locals to go through `let var` for orthogonality aids readability\n> enough to offset the verbosity cost of added keywords on a reasonably common\n> pattern.\n>\n> I'm still currently in the position that locally owned objects being mutable\n> should not be \"discouraged\" or \"disincentivized\" by the language. And I think\n> adding artificial incentives to try and avoid needing a mutable local variable\n> would either have no effect beyond verbosity, or if it _did_ have effect, it\n> wouldn't be a net positive effect due to code being written in a less\n> straightforward manner in order to avoid mutation.\n>\n> To be clear, this is based on intuition and judgement based on my experience,\n> not in any way based on data or specific motivating examples. I can imagine\n> data or evidence or even a new perspective changing my position here, but so\n> far the discussion we've had haven't done that.\n\n### `ref` as a type qualifier\n\nThe big concern is that any effect that is represented by a type, like\n`Optional` or `Result`, will want to compose with reference returns. This could\nbe done by allowing `ref` to create an object type that could be used as a\nparameter to those, as in `Optional(ref T)`, but\n[we are trying to avoid going down that path](https://github.com/carbon-language/carbon-lang/issues/5261#issuecomment-2790421894).\nWe have [future work](#interaction-with-effects) to tackle this problem\nspecifically.\n\nThere was also\n[a concern that we might need `ref` types to represent argument lists with tuples](https://github.com/carbon-language/carbon-lang/issues/5261#issuecomment-2790506515),\nbut tuples already can't represent `var` or compile-time parameters. We have\nother plans for this, instead of trying to stretch tuples to encompass these use\ncases.\n\nWe also noted that including references in the type system led to a number of\ninconsistencies in C++, such as no there not being references of references.\n\n### `bound` would change the default return to `val`\n\nWe considered saying that `bound` would change the default return to use the\n`->val` return convention. This was discussed on\n[2025-05-01](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.dffumsu6wzlc)\nand\n[2025-05-08](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.vdognq1upsf5).\nThe idea is that `val` is expected to be efficient, so we should encourage using\nit, but we can't always use `val`, since some types have a reference value\nrepresentation, but `bound` alleviates that concern.\n\nOnce we realized that `bound` is relevant for all return conventions, we\nreconsidered that approach, since has a number of concerns:\n\n-   Changing defaults is action at a distance, changing the behavior without\n    changing the code in the relevant location.\n-   We don't want to have to make changes to the return category of copy-paste\n    of a function from an interface to an `impl` of it when removing `bound`.\n-   Lifetimes in Rust and Clang's `[[clang::lifetimebound]]` don't change\n    calling conventions, only what code is valid.\n\nGoing with an approach where less depends on `bound` makes sense for now, since\nwe are going to reconsider these issues as part of our upcoming memory safety\nwork.\n\n### Other return conventions\n\nWe also considered other conventions for returning from functions, in\n[a comment on #5434](https://github.com/carbon-language/carbon-lang/pull/5434/files#r2099145225),\non\n[2025-05-08](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.vdognq1upsf5)\nand on\n[2025-05-12](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.1mjh6unumnwu),\nmost notably:\n\n-   **in place**: This convention was like `->`, but always using the \"in place\"\n    convention where the caller allocates storage and provides the callee with\n    its address, the callee initializes the storage at that address, and the\n    caller is responsible for destroying after the return.\n-   **var without storage**: The callee returns a pointer to the storage of a\n    subobject of a `bound var` parameter, that caller is then responsible for\n    destroying. A call to this function is reference expression, but with\n    additional responsibility to destroy.\n-   **hybrid**: If the type has a copy value representation or trivial\n    destructive move then return the object representation directly; otherwise\n    caller passes a pointer and callee initializes it.\n\nThere were also some variations on what the conditions for returning in\nregisters using the default return convention.\n\nWe seriously considered \"var without storage\", but the fact that it couldn't\nreliably be used to initialize a variable, particularly in the middle of an\nobject, meant it did not seem valuable enough to include.\n\nIt seemed more valuable to support the \"in place\" return convention. That return\nform allows you to guarantee knowing the address of the object being\nconstructed, and was a good match for `returned var`. However, we realized that\n`var` declarations shouldn't always be associated with in-memory storage, in\nparticular for types that may be trivially moved. For example, a `var` parameter\nwith the C++ type `std::unique_ptr<T>` should be passed in registers. A function\nreturning a `std::unique_ptr<T>` in place would not be as efficient as returning\nit by moving it into registers.\n\n### `return var` with compound return forms\n\nWe considered various syntax options on\n[2025-05-12](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.1mjh6unumnwu),\nbut none of them seemed good enough to justify inclusion at this time:\n\n```carbon\nfn F(...) -> (ref R, val L, V) {\n  // No longer a `var` being returned. Ideally these\n  // shouldn't have to be initialized together.\n  returned ??? (ref r: R, val l: L, var v: V) = ...?\n  return var;\n}\n\n// We could restrict to one `var` return component,\n// but this is a lot of machinery for a small increase\n// in expressiveness and applicability.\nfn F(...) -> (ref R, val L, V) {\n  returned var v: V = ...;\n  let l: L = ...;\n  return (*r, l, var);\n}\n\nfn F(...) -> (ref R, val L, V) {\n  // These don't have the right category, and ideally\n  // shouldn't have to be initialized together.\n  returned var ret: (R, L, V) = ...?\n  return var;\n}\n\nfn F(...) -> (ref R, val L, V) {\n  returned var (_, _, var v: V) = <what goes here?>;\n}\n```\n\nThere was another approach we considered for `returned var` originally:\n\n```carbon\nfn F(...) -> (ref R, val L, v1: V1, var v2: V2) {\n  // ...\n  // Must use the same names for the `var` (implicit or explicit) returns\n  // with bound names.\n  return (r, l, v1, v2);\n}\n```\n\nBut this had downsides that still apply:\n\n-   Requires `V1` and `V2` to have unformed states. Otherwise, `v1` and `v2`\n    would need be initialized when they are declared.\n-   This does not support only having some branches use `return var`.\n\nOur current approach handles our main use case for `returned var`: factory\nfunctions.\n\nWe could support an \"only `var`s\" approach in the future if we want:\n\n```carbon\nfn F(...) -> (var V1, var V2, var V3) {\n  returned (var v1: V1, var v2: V2, var v3: V3) = ...;\n  // ...\n  return var;\n}\n```\n\n### Other syntax for compound return forms\n\nWe considered other options for the syntax of compound return forms on\n[2025-05-13](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.bdznj2d0by2g),\n[#syntax in Discord on 2025-05-14](https://discord.com/channels/655572317891461132/709488742942900284/1372285365162872943),\nand\n[2025-05-14](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.52tb7l2he343).\nThe option of omitting the `->` in each component did not distinguish tuples\nfrom tuple return forms sufficiently:\n\n```carbon\n-> (ref i32, var i32)\n-> (bool, ref i32)\n\n// Is this a single return of a tuple, or a triple\n// return using the default return convention?\n-> (i32, i32, i32)\n```\n\nWe also considered an approach where compound return forms would start with\n`->?`, but this raised concerns about what the meaning of that syntax would be\nand whether we want to expose users to that in cases we might be able to avoid\nit.\n\nThe original proposed syntax used an arrow `->` in each component of a compound\nform.\n\n```carbon\nfn TupleReturn(...)\n    -> (->val bool, ->ref i32, -> C);\n\nfn StructReturn(...)\n    -> {->val .a: bool,\n        ->ref .b: i32,\n        -> .c: C};\n```\n\nThis avoided ambiguity, but was verbose and visually noisy. An alternative was\nsuggested in\n[discussion on 2025-06-13](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.52ru7ner80b4).\nThis alternative used a default of compound returns for paren `(`...`)` and\nbrace `{`...`}` expressions, which you could opt out of by using one of the\nthree category keywords such as `var` to introduce a type expression that would\nnot be considered a compound return.\n\nThis had the downside that `-> T` would be interpreted as `-> var T` even if `T`\nwas a tuple type like `(i32, i64)`. However, textually substituting in\n`(i32, i64)` in for `T` to get `-> (i32, i64)` would instead be interpreted as\n`-> (var i32, var i64)`.\n\nTo overcome this problem, in\n[discussion on 2025-06-16](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.rdbzk5jnin3x),\nwe switched to the approach from this proposal.\n\n### `ref` parameters allow aliasing\n\nIf requiring `ref` parameters to be `noalias` ends up being too restrictive, we\ncould instead have the \"move-in-move-out\" optimization be done only when the\ncompiler can prove it safe. One strategy would be to generate an alternate\nversion of the function that is only used in the cases where the `noalias`\nconditions can be shown to hold statically.\n\n### `let` to mark value returns instead of `val`\n\nThis proposal initially used `let` instead of `val` to mark\n[immutable value returns](#ref-and-val-returns). However, `let` is used, in\nCarbon and other languages, primarily to bind names. In Carbon, the default\nbinding is a value binding, but that was not considered a close enough to\nconnect the `let` keyword to value semantics.\n\nThere was also a concern about reusing `let` in multiple contexts to mean\ndifferent things, and having separate keywords that were only used to mark the\ncategory of the binding was deemed better separation of concerns.\n\nWe considered making a parallel change to use `init` instead of `var`, but this\nhad some problems:\n\n-   By making initializing returns the default, there is little expected usage,\n    so perhaps not worth spending another keyword on.\n-   The `init` keyword would be particularly expensive, because C++ code\n    commonly use that word in APIs.\n\nThis question was considered in\n[leads issue #5522](https://github.com/carbon-language/carbon-lang/issues/5522).\n\n### `=>` infers form, not just type\n\nThere was support for the idea that the `=>` return syntax introduced in\n[proposal #3848](https://github.com/carbon-language/carbon-lang/pull/3848)\nshould deduce the form of the return, not just its type. This was discussed in\n[#lambdas on 2025-05-20](https://discord.com/channels/655572317891461132/999638000126394370/1374462658723450981).\n\nHowever, trying to infer the expression category from the category of the\nexpression after the `=>` runs into the problem of this often requiring the\nparameters to be marked `bound`. A more complicated rule, for example using\nwhether any parameter is marked `bound`, could be adopted in the future, if the\nsimple rule proves inadequate.\n\nAlternatively, the compiler could infer which parameters should be marked\n`bound` in this case. That is something to consider with the memory safety\ndesign.\n"
  },
  {
    "path": "proposals/p5448.md",
    "content": "# Carbon <-> C++ Interop: Primitive Types\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5448)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Data models](#data-models)\n    -   [Carbon Primitive Types](#carbon-primitive-types)\n    -   [C++ Fundamental Types](#c-fundamental-types)\n        -   [void](#void)\n        -   [std::nullptr_t](#stdnullptr_t)\n        -   [std::byte](#stdbyte)\n        -   [Character types](#character-types)\n        -   [Signed integer types](#signed-integer-types)\n        -   [Unsigned integer types](#unsigned-integer-types)\n        -   [Floating-point types](#floating-point-types)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [C++ -> Carbon mapping details](#c---carbon-mapping-details)\n    -   [Carbon -> C++ mapping details](#carbon---c-mapping-details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n-   [Open questions](#open-questions)\n\n<!-- tocstop -->\n\n## Abstract\n\nDefine the type mapping of the primitive types between Carbon and C++.\n\n## Problem\n\nInteroperability of Carbon with C++ is one of the Carbon language goals (see\n[Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)).\nProviding\n[unsurprising mappings between C++ and Carbon types](/docs/design/interoperability/philosophy_and_goals.md#unsurprising-mappings-between-c-and-carbon-types)\nis one of it's sub goals.\n\nThis proposal addresses the type mapping between the two languages to support\nachieving this goal.\n\n## Background\n\n### Data models\n\nThe following data models are widely accepted:\n\n-   32-bit systems:\n    -   `LP32` (Win16 API): `int` 16-bit; `long` 32-bit; `pointer` 32-bit.\n    -   `ILP32` (Win32 API; Unix and Unix-like systems): `int` 32-bit; `long`\n        32-bit; `pointer` 32-bit.\n-   64-bit systems:\n    -   `LLP64` (Win32 API: 64-bit ARM or x86-64): `int` 32-bit; `long` 32-bit;\n        `pointer` 64-bit.\n    -   `LP64` (Unix and Unix-like systems (Linux, macOS)): `int` 32-bit; `long`\n        64-bit; `pointer` 64-bit.\n\n[Carbon supported platforms](/docs/project/principles/success_criteria.md#modern-os-platforms-hardware-architectures-and-environments)\n\nCarbon will prioritize supporting modern OS, 64-bit little endian platforms (for\nexample [LLP64](/proposals/p5448.md#data-models),\n[LP64](/proposals/p5448.md#data-models)). Historic platforms like\n[LP32](/proposals/p5448.md#data-models) won't be supported.\n\nFor clarity, the text below omits [LP32](/proposals/p5448.md#data-models)\nrelevant information and focuses only on the Carbon supported platforms.\n\n### Carbon Primitive Types\n\nCarbon has the following\n[primitive types](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/README.md#primitive-types):\n\n-   `bool`: boolean type taking `true` or `false`\n-   integer types:\n    -   signed integer types: `iN` (`N` - bit width, a positive multiple of 8)\n        -   `i8`, `i16`, `i32`, `i64`, `i128`, `i256`\n    -   unsigned integer types: `uN` (`N` - bit width, a positive multiple of 8)\n        -   `u8`, `u16`, `u32`, `u64`, `u128`, `u256`\n-   floating-point types: `fN` (`N` - bit width, a positive multiple of 8),\n    IEEE-754 format\n    -   `f16`, `f32`, and `f64` - always available\n    -   `f80`, `f128`, or `f256` may be available, depending on the platform\n\n### C++ Fundamental Types\n\nC++ calls the primitive types\n[fundamental types](https://en.cppreference.com/w/cpp/language/types). The\nfollowing fundamental types exist in C++:\n\n-   `void`\n-   `std::nullptr_t`\n-   `std::byte`\n-   integral types (also integer types):\n    -   `bool`\n    -   character types:\n        -   narrow character types: `signed char`, `unsigned char`, `char`,\n            `char8_t` (c++20)\n        -   wide character types: `char16_t`, `char32_t`, `wchar_t`\n    -   signed integer types:\n        -   standard signed integer types: `signed char`, `short`, `int`,\n            `long`, `long long`\n        -   extended signed integer types (implementation-defined)\n    -   unsigned integer types:\n        -   standard unsigned integer types: `unsigned char`, `unsigned short`,\n            `unsigned int`, `unsigned long`, `unsigned long long`\n        -   extended unsigned integer types\n-   floating-point types:\n    -   standard floating-point types: `float`, `double`, `long double`\n    -   extended floating-point types:\n        -   fixed width floating-point types (since C++23): `float16_t`,\n            `float32_t`, `float64_t`, `float128_t`, `bfloat16_t`\n        -   other implementation-defined extended floating-point types\n\n#### void\n\nObjects of type `void` are not allowed, neither are arrays of `void`, nor\nreferences to `void`. Pointers to `void` and functions returning `void` are\nallowed.\n\n#### std::nullptr_t\n\nThe type of `nullptr` (the null pointer literal). It's a distinct type that is\nnot itself a pointer type.\n\n#### std::byte\n\n| Type        | Width in bits | Notes                                                                                                                  |\n| ----------- | ------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| `std::byte` | 8-bit         | can be used to access raw memory, same as `unsigned char`, but it's not a character type and is not an arithmetic type |\n\n#### Character types\n\n| Type            | Width in bits                      | Notes                                                                                                                                                         |\n| --------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `char`          | 8-bit                              | multibyte characters; same representation, alignment and signedness as either `signed char` or `unsigned char` (platform-dependent), but it's a distinct type |\n| `signed char`   | 8-bit                              | signed character representation                                                                                                                               |\n| `unsigned char` | 8-bit                              | unsigned character representation; raw memory access                                                                                                          |\n| `char8_t`       | 8-bit                              | UTF-8 character representation; same size, alignment and signedness as `unsigned char`, but a distinct type                                                   |\n| `char16_t`      | 16-bit                             | UTF-16 character representation; same size, alignment and signedness as `std::uint_least16_t`, but a distinct type                                            |\n| `char32_t`      | 32-bit                             | UTF-32 character representation; same size, alignment and signedness as `std::uint_least32_t`, but a distinct type                                            |\n| `wchar_t`       | 32-bit on Linux, 16-bit on Windows | wide character representation, holds UTF-32 on Linux and other non-Windows platforms, UTF-16 on Windows.                                                      |\n\n#### Signed integer types\n\n**Standard signed integer types**\n\n| Type          | Width in bits                                                                                     |\n| ------------- | ------------------------------------------------------------------------------------------------- |\n| `signed char` | 8-bit                                                                                             |\n| `short`       | 16-bit                                                                                            |\n| `int`         | 32-bit                                                                                            |\n| `long`        | [LLP64](/proposals/p5448.md#data-models): 32-bit; [LP64](/proposals/p5448.md#data-models): 64-bit |\n| `long long`   | 64-bit                                                                                            |\n\n**Exact-width integer types**\n\nTypically aliases of the standard integer types.\n\n| Type           | Width in bits | Defined as                                                                   |\n| -------------- | ------------- | ---------------------------------------------------------------------------- |\n| `std::int8_t`  | 8-bit         | `typedef signed char int8_t`                                                 |\n| `std::int16_t` | 16-bit        | `typedef signed short int16_t`                                               |\n| `std::int32_t` | 32-bit        | `typedef signed int int32_t`                                                 |\n| `std::int64_t` | 64-bit        | [LLP64](/proposals/p5448.md#data-models): `typedef signed long long int64_t` |\n|                |               | [LP64](/proposals/p5448.md#data-models): `typedef signed long int64_t`       |\n\n**Fastest minimum-width integer types**\n\nInteger types that are usually fastest to operate with among all integer types\nthat have the minimum specified width.\n\n| Type                | Width in bits | Defined as                                                                        |\n| ------------------- | ------------- | --------------------------------------------------------------------------------- |\n| `std::int_fast8_t`  | >=8-bit       | `typedef signed char int_fast8_t`                                                 |\n| `std::int_fast16_t` | >=16-bit      | implementation dependent                                                          |\n| `std::int_fast32_t` | >=32-bit      | implementation dependent                                                          |\n| `std::int_fast64_t` | >=64-bit      | [LLP64](/proposals/p5448.md#data-models): `typedef signed long long int_fast64_t` |\n|                     |               | [LP64](/proposals/p5448.md#data-models): `typedef signed long int_fast64_t`       |\n\n**Minimum-width integer types**\n\nSmallest signed integer type with width of at least N-bits.\n\n| Type                 | Width in bits | Defined as                                                                         |\n| -------------------- | ------------- | ---------------------------------------------------------------------------------- |\n| `std::int_least8_t`  | >=8-bit       | `typedef signed char int_least8_t`                                                 |\n| `std::int_least16_t` | >=16-bit      | `typedef short int_least16_t`                                                      |\n| `std::int_least32_t` | >=32-bit      | `typedef int int_least32_t`                                                        |\n| `std::int_least64_t` | >=64-bit      | [LLP64](/proposals/p5448.md#data-models): `typedef signed long long int_least64_t` |\n|                      |               | [LP64](/proposals/p5448.md#data-models): `typedef signed long int_least64_t`       |\n\n**Greatest-width integer types**\n\nMaximum-width signed integer type.\n\n| Type            | Width in bits | Defined as                                                                    |\n| --------------- | ------------- | ----------------------------------------------------------------------------- |\n| `std::intmax_t` | >=32-bit      | [LLP64](/proposals/p5448.md#data-models): `typedef signed long long intmax_t` |\n|                 |               | [LP64](/proposals/p5448.md#data-models): `typedef signed long intmax_t`       |\n\n**Integer types capable of holding object pointers**\n\nSigned integer type, capable of holding any pointer.\n\n| Type            | Width in bits | Defined as                                                           |\n| --------------- | ------------- | -------------------------------------------------------------------- |\n| `std::intptr_t` | >=16-bit      | most platforms: `typedef long intptr_t`                              |\n|                 |               | some [ILP32](/proposals/p5448.md#data-models):`typedef int intptr_t` |\n\n**Other signed integer types**\n\n| Type        | Width in bits | Defined as                                        |\n| ----------- | ------------- | ------------------------------------------------- |\n| `ptrdiff_t` | >=16-bit      | most platforms: `typedef std::intptr_t ptrdiff_t` |\n|             |               | Holds the result of subtracting two pointers.     |\n\n#### Unsigned integer types\n\nThe unsigned integer types have the same sizes as their\n[signed counterparts](/proposals/p5448.md#signed-integer-types).\n\n| Type     | Width in bits | Defined as                                 |\n| -------- | ------------- | ------------------------------------------ |\n| `size_t` | >=16-bit      | most platforms: `typedef uintptr_t size_t` |\n|          |               | Holds the result of the `sizeof` operator. |\n\n#### Floating-point types\n\n**Standard floating-point types**\n\n| Type          | Format                                                                                                              | Width in bits    | Note                                                                        |\n| ------------- | ------------------------------------------------------------------------------------------------------------------- | ---------------- | --------------------------------------------------------------------------- |\n| `float`       | usually [IEEE-754 binary32](https://en.wikipedia.org/wiki/Single-precision_floating-point_format)                   | 32-bits          | The format or the size can vary depending on the compiler and the platform. |\n| `double`      | usually [IEEE-754 binary64](https://en.wikipedia.org/wiki/Double-precision_floating-point_format)                   | 64-bits          | The format or the size can vary depending on the compiler and the platform. |\n| `long double` | [IEEE-754 binary128](https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format)                       | 128-bit          | used by some SPARC, MIPS, ARM64 implementations.                            |\n|               | [IEEE-754 binary64-extended format](https://en.wikipedia.org/wiki/Extended_precision)                               | 80-bit or 64-bit | 80-bit (most x86 and x86-64 implementations); 64-bit used by MSVC.          |\n|               | [`double-double`](https://en.wikipedia.org/wiki/Quadruple-precision_floating-point_format#Double-double_arithmetic) | 128-bit          | used on PowerPC.                                                            |\n\n**Fixed-width floating-point types (C++23)**\n\nThey aren’t aliases to the standard floating-point types (`float`, `double`,\n`long double`), but to an extended floating-point type.\n\n| Type              | Width in bits | Defined as                     |\n| ----------------- | ------------- | ------------------------------ |\n| `std::float16_t`  | 16-bit        | `using float16_t = _Float16`   |\n| `std::float32_t`  | 32-bit        | `using float32_t = _Float32`   |\n| `std::float64_t`  | 64-bit        | `using float64_t = _Float64`   |\n| `std::float128_t` | 128-bit       | `using float128_t = _Float128` |\n| `std::bfloat16_t` | 16-bit        |                                |\n\n## Proposal\n\n-   The C++ fixed-width integer types `intN_t` will be the same type as Carbon\n    integer types `iN`. Likewise for `uintN_t` <-> `uN`.\n-   A C++ `builtin type` will be available in Carbon as `Cpp.builtin_type`, for\n    the standard C++ signed/unsigned integer and floating-point types.\n-   A C++ integer `builtin type` that is not the same as `intN_t` or `uintN_t`\n    for any N, will be nameable in Carbon only as `Cpp.builtin_type`.\n-   Different C++ types will be considered different in Carbon, so C++ overload\n    resolution can be handled without issues.\n\n## Details\n\nThe table of Carbon <-> C++ mappings is as follows:\n\n| Carbon                   | C++                                    |\n| ------------------------ | -------------------------------------- |\n| `()` as a return type    | `void`                                 |\n| `bool`                   | `bool`                                 |\n| `i8`                     | `int8_t`                               |\n| `i16`                    | `int16_t`                              |\n| `i32`                    | `int32_t`                              |\n| `i64`                    | `int64_t`                              |\n| `i128`                   | `int128_t`                             |\n| `u8`                     | `uint8_t`                              |\n| `u16`                    | `uint16_t`                             |\n| `u32`                    | `uint32_t`                             |\n| `u64`                    | `uint64_t`                             |\n| `u128`                   | `uint128_t`                            |\n| `Cpp.signed_char`        | `signed char`                          |\n| `Cpp.short`              | `short`                                |\n| `Cpp.int`                | `int`                                  |\n| `Cpp.long`               | `long`                                 |\n| `Cpp.long_long`          | `long long`                            |\n| `Cpp.unsigned_char`      | `unsigned char`                        |\n| `Cpp.unsigned_short`     | `unsigned short`                       |\n| `Cpp.unsigned_int`       | `unsigned int`                         |\n| `Cpp.unsigned_long`      | `unsigned long`                        |\n| `Cpp.unsigned_long_long` | `unsigned long long`                   |\n| `Cpp.float`              | `float`                                |\n| `Cpp.double`             | `double`                               |\n| `Cpp.long_double`        | `long double`                          |\n| `f16`                    | `std::float16_t (_Float16)`            |\n| `f128`                   | `std::float128_t (_Float128)`          |\n| TBD                      | `float32_t`, `float64_t`, `bfloat16_t` |\n| TBD                      | `char`, `charN_t`, `wchar_t`           |\n| TBD                      | `std::byte`                            |\n| TBD                      | `std::nullptr_t`                       |\n\nIn addition to the exact mappings above, the following are expected to be the\nsame type due to the different spellings of the types in C++ being the same:\n\n| Carbon type | C++ type                                |\n| ----------- | --------------------------------------- |\n| `i8`        | `signed char`                           |\n| `u8`        | `unsigned char`                         |\n| `i16`       | `short`                                 |\n| `u16`       | `unsigned short`                        |\n| `i32`       | `int`                                   |\n| `u32`       | `unsigned int`                          |\n| `i64`       | `long` or `long long`                   |\n| `u64`       | `unsigned long` or `unsigned long long` |\n\n### C++ -> Carbon mapping details\n\n-   C++ `intN_t` type will be considered the same type as Carbon's `iN` type.\n    Likewise for `uintN_t` <-> `uN`.\n-   C++ `builtin type` will be available in Carbon inside the `Cpp` namespace\n    under the name `Cpp.builtin_type`, for the standard signed/unsigned integer\n    and floating-point types.\n\n    -   The names will follow the pattern:\n\n        -   `Cpp.[unsigned_](long_long|long|int|short|double|float)`\n\n        that is signedness, then size keyword(s), then a type keyword only if\n        there are no size keywords. For example `Cpp.unsigned_int` not\n        `Cpp.unsigned`, `Cpp.long` not `Cpp.long_int`.\n\n    -   They will be available when an `import Cpp` declaration is present.\n\n    -   Name collision: This naming may cause name collisions if such a name\n        already exist in the unnamed C++ namespace. We consider this not to be a\n        common case and would not support such cases, for the benefit of having\n        the C++-specific stuff in the package `Cpp`.\n\n    -   `Cpp.builtin_type` will be the same type as `iN`/`uN`, if the\n        corresponding C++ `builtin type` is the same as `intN_t`/`uintN_t` on\n        that platform. Otherwise it will be available in Carbon as a new,\n        distinct type that is compatible with some of the `iN`/`uN` types. For\n        example:\n\n        -   If `int32_t` is the same type as `int`, then `Cpp.int` will be the\n            same type as `i32`.\n\n        -   If `int64_t` is the same type as `long`, then `Cpp.long` will be the\n            same type as `i64`. `Cpp.long_long` will be a different type,\n            compatible with `i64`.\n\n    -   `Cpp.float` and `Cpp.double` will be the same type as `f32` and `f64`\n        correspondingly.\n\n-   The type aliases `[u]int_fastN_t`, `[u]int_leastN_t`, `[u]intmax_t`,\n    `[u]intptr_t`, `ptrdiff_t` and `size_t` will be available in Carbon in the\n    `Cpp` namespace if the C++ header declaring them is imported (for example\n    `<stdint.h>`, `<cstdint>` etc), with names like `Cpp.[u]int_fastN_t`,\n    `Cpp.[u]int_leastN_t`, `Cpp.size_t` etc. No special support will be\n    provided.\n\n### Carbon -> C++ mapping details\n\n-   Same as above, Carbon `iN`/`uN` types will map to the C++ `intN_t`/`uintN_t`\n    types.\n-   `f32`/`f64` will map to `float`/`double` correspondingly.\n-   `f16`/`f128` will map to\n    `std::float16_t (_Float16)`/`std::float128_t (_Float128)` correspondingly.\n-   Some Carbon types may not have direct mappings in C++: `i256`, `u256` ,\n    `f80`, `f256`.\n\n## Rationale\n\nOne of Carbon's goals is seamless interoperability with C++ (see\n[Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)),\ncalling for clarity of the calls and high performance.\n\nThe proposal maps the Carbon types to their direct equivalents in C++, with zero\noverhead, supporting the request for unsurprising mappings between C++ and\nCarbon types with high performance.\n\n## Alternatives considered\n\nNaming of new types:\n\n-   Allow all keyword permutations.\n    -   Reason not to do this: unnecessary and complicated.\n-   Only include the keywords, and provide some syntax for combining them (eg,\n    `Cpp.unsigned` & `Cpp.long` or `Cpp.unsigned(Cpp.long)`).\n    -   Reason to do this: avoids taking any identifiers from Cpp that are not\n        C++ keywords.\n    -   Reason not to do this: overly complicated.\n-   Use `Core.Cpp.T` instead of `Cpp.T`.\n    -   Reason to do this: avoid name collisions with C++ code.\n    -   Reason not to do this: The name collisions should not be a problem in\n        practice, and would prefer to keep C++-specific stuff in package Cpp.\n\n`long`\n\n-   `Cpp.long` and `Cpp.long_long` both map to Carbon types that are distinct\n    from `iN` for any `N`, but are compatible with either `i32` or `i64` as\n    appropriate.\n    -   Reason to not do this: unnecessary conversions and handling `long` and\n        `long long` differently than the other C++ types.\n-   Provide platform-dependent conversion functions for `long`.\n    -   Reason to do this: the conversions will be clearly outlined.\n    -   Reason not to do this: performance overhead for certain platforms.\n-   Map `long` always to a fixed-sized Carbon type depending on the platform\n    (for example to either `i32` or `i64`)\n    -   Reason to do this: all the code will be using fixed-sized types.\n    -   Reason not to do this: the same C++ function may map differently on\n        different platforms and the Carbon code should compensate for that to\n        make the code compile.\n\n`float32_t`, `float64_t`\n\n-   Map `f32` <-> `float32_t` and `f64` <-> `float64_t`\n    -   Reason to do this: follow the same analogy as for the integer types\n        (`iN` <-> `intN_t`)\n    -   Reason not to do this:\n        -   `float32_t`, `float64_t` are new types since C++23, so this won't be\n            directly achievable, but the corresponding `_FloatN` types will need\n            to be used for the older C++ versions.\n        -   they are not aliases for the standard floating-point types (`float`,\n            `double`, `long double`), but for extended floating-point types, so\n            type conversions will be needed for the standard types.\n\n## Open questions\n\nThe mapping of the following types remains open and will be discussed at a later\npoint:\n\n-   `char`, `char8_t`, `char16_t`, `char32_t`, `wchar_t`\n    -   Carbon still doesn't have character types, so the mapping of these types\n        will be discussed once they are available.\n    -   These are all distinct types in C++, which should be taken into account\n        to prevent any issues for overloading.\n-   `std::byte`\n-   `std::nullptr_t`\n-   `void*`\n-   `Cpp.long_double` - details of this new type is still to be discussed.\n-   `float32_t`, `float64_t`, `bfloat16_t`.\n"
  },
  {
    "path": "proposals/p5545.md",
    "content": "# Expression form basics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5545)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Mixed expression categories](#mixed-expression-categories)\n    -   [Don't implicitly convert to less-primitive forms](#dont-implicitly-convert-to-less-primitive-forms)\n    -   [Breadth-first evaluation order](#breadth-first-evaluation-order)\n    -   [Depth-first evaluation with a different \"horizontal\" order](#depth-first-evaluation-with-a-different-horizontal-order)\n    -   [Support binding `ref self` to ephemeral references](#support-binding-ref-self-to-ephemeral-references)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal introduces the concept of a _form_, which is a generalization of\n\"type\" that encompasses all of the information about an expression that's\nvisible to the type system, including type and expression category. Forms can be\ncomposed into _tuple forms_ and _struct forms_, which lets us track the\ncategories of individual tuple and struct literal elements.\n\n## Problem\n\nIt's unclear what expression category tuple and struct literals should have. For\nexample, this code can only compile if the tuple literal is an initializing\nexpression:\n\n```carbon\nvar t: (NonMovable, NonMovable) = (MakeNonMovable(), MakeNonMovable())\n```\n\nBut this code can only compile if the tuple literal is a value expression:\n\n```carbon\nlet x: NonCopyable = MakeNonCopyable();\nlet t: (NonCopyable, NonCopyable) = (x, MakeNonCopyable());\n```\n\nAnd there's plausible code that can't compile if the tuple literal has _any_\nsingle expression category:\n\n```carbon\nlet x: NonCopyable = MakeNonCopyable();\nlet (a: NonCopyable, var b: NonMovable) = (x, MakeNonMovable());\n```\n\nAt present it's always possible to rewrite examples like that to avoid the\nproblem by disaggregating the tuple patterns into separate statements. However,\nwhen the copy and move operations in question are expensive rather than outright\ndisabled, those examples will result in silent inefficiency rather than a noisy\nbuild failure, which is less harmful but easier to overlook.\n\n## Background\n\nThe Carbon toolchain already implements a solution to this problem: it treats\ntuple and struct literals as having a \"mixed\" expression category, and when\nindividual elements of the literal are accessed (such as during pattern\nmatching), the element's original category is propagated.\n\nProposal [#5434](https://github.com/carbon-language/carbon-lang/pull/5434)\nintroduces plausible use cases that cannot compile if we assign any single\nexpression category to a tuple or struct literal, and there is no way to avoid\nthe problem by rewriting. For example:\n\n```carbon\nfn F() -> (ref NonCopyable, NonMovable);\nlet (a: NonCopyable, var b: NonMovable) = F();\n```\n\n## Proposal\n\nThis proposal solves that problem by introducing the concept of a _form_, which\nis a generalization of \"type\" that encompasses all of the information about an\nexpression that's visible to the type system, including type and expression\ncategory. In the common case, an expression has a _primitive form_ which\nconsists of a type, an expression category, and a few other properties. However,\na tuple literal has a _tuple form_, which is a tuple of the forms of its\nelements. This allows us to directly represent the fact that different elements\nhave different categories, and propagate that difference into operations that\naccess those elements.\n\nIn order to help describe the semantics of forms, this proposal also formalizes\nthe concept of the _result_ of an expression evaluation. Results are a\ngeneralization of values and references in the same way that forms are a\ngeneralization of types. In this proposal they are primarily a descriptive\nconvenience, but they are also intended to function as the thing that a\nform-generic binding binds to, when that is proposed.\n\nThe results of initializing expressions, called _initializing results_, have\nsomewhat subtle semantics. Results present an idealized model of expression\nevaluation where information flows from each expression to the context where it\nis used, but initializing expressions require information to flow in both\ndirections: the context supplies a storage location, and then the expression\nsupplies the contents of that storage location. We finesse this \"impedance\nmismatch\" by saying that the initializing result represents an obligation on the\ncontext to supply a storage location (somewhat like a callback or\n`std::promise`), which it must fulfill by either materializing or transferring\nthe result. Furthermore, even though this formally happens after the expression\nis evaluated, it is constrained in such a way that it can actually be computed\nbeforehand and passed to the expression's hidden output parameter.\n\nThis proposal also integrates type, category, and phase conversions into a\nunified set of rules for form conversions. Notably, those rules call for\nconversions to be evaluated depth-first (along with the expressions they convert\nfrom and the pattern-matches they feed into), and for struct conversions to use\nthe field order of the source, not the target.\n\nFinally, this proposal splits the reference expression categories into _entire_\nand _non-entire_ references, where an entire reference is known to refer to a\ncomplete object. This lets us decouple materialization (which now produces an\nephemeral entire reference) from `var` binding (which now expects an ephemeral\nentire reference), which lets us resolve a TODO to allow an initializing\nexpression to be destructured into multiple `var` bindings.\n\nIn the process of doing this, it became clear that the special case that allowed\n`ref self` patterns to match ephemeral references was not internally consistent,\nso that special case has been removed. We will need some way of supporting the\nuse cases that were intended to be covered by that rule, but that is being left\nas future work.\n\n## Details\n\nSee the edits in the\n[pull request](https://github.com/carbon-language/carbon-lang/pull/5545)\nassociated with this proposal, particularly in `values.md`.\n\n## Rationale\n\nThis proposal supports\n[performance-critical software](/docs/project/goals.md#performance-critical-software)\nand making\n[code easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\nby ensuring that tuple and struct literals don't introduce unnecessary category\nconversions (which may cause build failures and performance overhead).\n\n## Alternatives considered\n\n### Mixed expression categories\n\nThis proposal models an expression like `(x, MakeNonMovable())` from the earlier\nexample as having a tuple form consisting of primitive forms with `NonCopyable`\nand `NonMovable` types (respectively) and \"value\" and \"initializing\" categories\n(respectively). We could instead support composite expression categories, so\nthat it has type `(NonCopyable, NonMovable)` and expression category\n`(value, initializing)`.\n\nThis would avoid the need to introduce the concept of \"form\", and preserve the\nexisting separation between types and categories. That separation would be\nsomewhat superficial (for example, an expression couldn't have a tuple\nexpression category if it doesn't have a tuple type), but no more so than the\nseparation between types and values.\n\nHowever, we expect to need an explicit syntax to express these properties of\nexpressions, for example to define functions that return tuples whose elements\nhave different categories. A syntax consisting of separate type and category\ntuples will be much less ergonomic, and much easier to misuse, than a syntax\nthat combines both in a single tuple (for example,\n[#5434](https://github.com/carbon-language/carbon-lang/pull/5434) represents the\nform of `(x, MakeNonMovable())` as `(val NonCopyable, NonMovable)`).\n\nFurthermore, we anticipate needing to support code that is generic with respect\nto forms, not just with respect to types. We plan to achieve that with\nparameters of a special \"form\" type together with ways of deducing and using\nthem. It might be possible to instead support category parameters that are\ndeduced and used in conjunction with type parameters, but that would be\nsyntactically onerous, and oblige users to keep each category correctly paired\nwith the corresponding type, in order to bring them together at the point of\nuse. Those challenges will be further compounded when/if it becomes possible to\nmanipulate types and categories by way of metaprogramming.\n\nGiven that we need to present forms as an integrated whole at the syntactic and\nmetaprogramming levels, there is very little to be gained by decoupling them at\nthe level of language semantics.\n\n### Don't implicitly convert to less-primitive forms\n\nConsider the following possible ways of initializing an array, where there is an\nimplicit conversion from integer literals to `X`:\n\n```carbon\nimpl Y as Core.ImplicitAs(X);\nlet a: array(X, 3) = (MakeY(), MakeY(), MakeY());\n\nlet x_tuple: (X, X, X) = (MakeY(), MakeY(), MakeY());\nlet b: array(X, 3) = x_tuple;\n```\n\nUnder this proposal, both `a` and `b` are valid. However, some people's\nintuition is that a tuple is different enough from an array that there should\nnot be implicit conversions between them in general. In this mental model, a\ntuple-form expression wouldn't represent a tuple per se; rather, it would\nabstractly represent a sequence of results, which can be used to initialize\neither a tuple or an array (or a user-defined type). Similarly, a struct-form\nexpression wouldn't represent a struct per se, but rather a more abstract\nsequence of _named_ results. Consequently, there would be no implicit conversion\nfrom a tuple value to a tuple form, and so `array` could disallow `b` by\nrequiring its initializer to have a tuple form.\n\nPerhaps more importantly, making this distinction could simplify C++ interop,\nbecause we could map C++ braced initializer lists to tuple and struct forms,\nwhile mapping C++ `std::pair`s and `std::tuple`s to primitive-form Carbon\ntuples, and mapping C++ structs to primitive-form Carbon structs. We cannot do\nthat under the status quo, because Carbon's implicit conversions from primitive\nto composite forms would have no C++ counterpart, and so overload resolution\nbehavior would change too radically when crossing the language boundary.\n\nHowever, consider the following examples:\n\n```carbon\nlet c: array(X, 3) = (MakeY(), MakeY(), MakeY()) as (X, X, X);\n\nlet y_tuple: (Y, Y, Y) = (MakeY(), MakeY(), MakeY());\nlet d: array(X, 3) = y_tuple as (X, X, X);\n```\n\nPresumably we would want the declaration of `c` to be valid, because it just\nmakes the implicit type conversion from `a` explicit. That result emerges pretty\nnaturally, because the `as` conversion operates element-wise on its tuple-form\ninput, so its output would likewise have a tuple form. On the other hand, the\ndeclaration of `d` should not be valid, because it just makes the implicit type\nconversion from `b` explicit. That result does not emerge naturally; instead, we\nhave to add a final form composition step at the end of the type conversion, to\nensure the result has a primitive form (but only when the input had a primitive\nform).\n\nBut that means we need to choose the category of that primitive form, that is\nwhether the conversion from `(Y, Y, Y)` to `(X, X, X)` is a value expression or\nan initializing expression (form composition can't produce reference\nexpressions). Upcoming proposals are expected to enable the user to define the\nimplicit conversion from `Y` to `X` to have any category, so suppose that the\nconversion from `Y` to `X` is a reference expression. In that case, the\nrequirement to convert to a primitive form breaks some use cases that would\notherwise be valid:\n\n```carbon\nlet (ref s1: X, ref s2: X, ref r3: X) = y_tuple as (X, X, X);\n```\n\nEven for usages that are not broken outright, this conversion may add\nsubstantial inefficiency, depending on which category we convert to:\n\n```carbon\nlet (p1: X, p2: X, p3: X) = y_tuple as (X, X, X);\n```\n\nThis requires 3 value acquisitions in either case, but if we convert to an\ninitializing expression it also requires 3 copy-init and materialization steps.\n\n```carbon\nlet (var q1: X, var q2: X, var q3: X) = y_tuple as (X, X, X);\n```\n\nIn either case we're starting and ending with the object representation of `X`,\npassing through the initializing representation (which is typically very closely\ntied to the object representation), but if the type conversion produces a value\nexpression we also pass through the value representation (which can be much less\ntrivial to convert to and from).\n\nFinally, examples like this one are less efficient if we have to convert to a\nprimitive form, regardless of which category we convert to:\n\n```carbon\nlet (r1: X, var r2: X, var r3: X) = y_tuple as (X, X, X);\n```\n\nSome but not all of these problems can be mitigated by making the target\ncategory an input to the type conversion, but that has a number of unwelcome\nconsequences:\n\n-   It adds complexity to the conversion APIs that user-defined types will\n    almost never need.\n-   We would need to change the syntax for `x as T` so that it specifies the\n    category as well as the type.\n-   It would enable user-defined conversions to produce different values\n    depending on the target category, which we definitely don't want.\n-   It makes overload resolution more complicated and more surprising.\n\nThis alternative was considered and rejected in\n[leads issue #6160](https://github.com/carbon-language/carbon-lang/issues/6160).\n\n### Breadth-first evaluation order\n\nUnder this proposal, the observable effects of a pattern-matching operation take\nplace in depth-first order (with respect to tuple and struct elements), but\nbreadth-first order would have several advantages:\n\n-   It would help enable us to define tuple type conversions as ordinary impls\n    of the type conversion APIs, because modeling conversion as a function call\n    is inherently breadth-first. Opting for depth-first evaluation seems to rule\n    that out.\n-   It would give us more options for supporting struct and class conversions\n    where the field orders doesn't match. For example, the previously-preferred\n    approach was to evaluate the source expression in its own field order, but\n    then perform conversions in the target's field order. This seemed to provide\n    a good balance of efficiency and ergonomics, but it's inherently\n    breadth-first. With the depth-first approach, we have to use a single field\n    order.\n-   It would simplify the specification, because the logical semantics of\n    conversion and pattern matching are much more naturally described\n    breadth-first, so opting for depth-first creates an \"impedance mismatch\"\n    between the logical and physical semantics.\n\nHowever, breadth-first evaluation order has a crucial efficiency cost: in all\nbut the most trivial use cases, it forces (and in some sense even maximizes)\nlifetime overlap between the results of the function calls that make up the\npattern-matching operation. That means it requires more temporary storage, and\nmore work to manage that storage (particularly at the register level).\n\nFor example, consider this\n[generated code](https://cpp.compiler-explorer.com/z/Pxaar4edb) for C++\napproximating the two options. The `LayerWise` function templates model the\nbreadth-first evaluation order, while the `ElementWise` model the proposed\ndepth-first order. Looking at the two element case for ARM:\n\n```asm\nvoid LayerWise<S1, S1>(S1, S1):\n        stp     x29, x30, [sp, #-32]!\n        stp     x20, x19, [sp, #16]\n        mov     x29, sp\n        mov     x19, x1\n        bl      Convert1(S1)\n        mov     x20, x0\n        mov     x0, x19\n        bl      Convert1(S1)\n        mov     x19, x0\n        mov     x0, x20\n        bl      Convert2(S2)\n        mov     x20, x0\n        mov     x0, x19\n        bl      Convert2(S2)\n        mov     x1, x0\n        mov     x0, x20\n        ldp     x20, x19, [sp, #16]\n        ldp     x29, x30, [sp], #32\n        b       void Target<S1, S1>(S1, S1)\n\nvoid ElementWise<S1, S1>(S1, S1):\n        stp     x29, x30, [sp, #-32]!\n        stp     x20, x19, [sp, #16]\n        mov     x29, sp\n        mov     x19, x1\n        bl      Convert1(S1)\n        bl      Convert2(S2)\n        mov     x20, x0\n        mov     x0, x19\n        bl      Convert1(S1)\n        bl      Convert2(S2)\n        mov     x1, x0\n        mov     x0, x20\n        ldp     x20, x19, [sp, #16]\n        ldp     x29, x30, [sp], #32\n        b       void Target<S1, S1>(S1, S1)\n```\n\nThe breadth-first approach forces significantly more data movement (the extra\nmoves between `x20` and `x19`) and temporary registers. This distinction\ncontinues in versions with more elements, making the problem more and more\nsevere. This is an inherent cost, and not something we can realistically expect\nan optimizing compiler to recover.\n\nFurthermore, we don't see any general way for developers to work around this\nproblem, and achieve the performance they would get automatically with\ndepth-first evaluation. On the other hand, with depth-first evaluation within\npattern-matching operations, developers can still ensure a breadth-first\nevaluation order relatively easily, by expressing each \"layer\" as a separate\npattern-matching operation (for example with a sequence of statements, or a\nchain of function calls). In some cases, this may involve move operations that\ncould be elided in a language-native breadth-first evaluation, but that depends\non the to-be-determined design of move semantics.\n\nIn short, the ergonomic costs of depth-first evaluation appear to be manageable,\nwhereas the performance cost of breadth-first evaluation is unavoidable (and\ncarries more weight, because supporting\n[performance-critical software](/docs/project/goals.md#performance-critical-software)\nis our top goal for the language).\n\nThis alternative was considered and rejected in\n[leads issue #6456](https://github.com/carbon-language/carbon-lang/issues/6456).\n\n### Depth-first evaluation with a different \"horizontal\" order\n\nTo order operations that don't have a dependency relationship, this proposal\nuses a hybrid scheme that follows both the lexical order of the primitive\npatterns and the lexical order of the scrutinee function calls (diagnosing an\nerror if they conflict), and also follows the lexical order of the scrutinee's\ndeclared type to the extent that it doesn't conflict with the primitive pattern\norder.\n\nOne potential drawback of this rule is it means that it means that, unlike C++,\nCarbon doesn't guarantee that the fields of an object are initialized in\ndeclaration order (or in any fixed order), and so it can't guarantee that\nthey'll be destroyed in reverse order of initialization.\n\nWe could solve that problem by guaranteeing to evaluate in the scrutinee type's\nfield order. However, that would mean evaluating function calls out of lexical\norder in cases like this:\n\n```carbon\nvar ab: {.a: A, .b: B} = {.b = MakeB(), .a = MakeA()};\n```\n\nEvaluating `MakeA()` before `MakeB()` risks causing surprises, or even bugs, and\nit would mean that the evaluation order within a single expression depends on\nhow it's used.\n\nInstead, we adopt a rule that ensures side effects are evaluated in lexical\norder within both the pattern and the scrutinee. We expect that to be sufficient\nfor struct types, where destruction order is unlikely to be an issue. Class\ntypes may be more sensitive to these ordering issues, so we may also need some\nway for the class to disallow initializers whose field order doesn't match the\nclass, but this is left as future work.\n\n### Support binding `ref self` to ephemeral references\n\n`ref` patterns can only match durable reference expressions, but prior to this\nproposal, `ref self` patterns could match ephemeral references as a special-case\nexception. This was intended to support certain C++ idioms that rely on\nmaterializing a temporary and then mutating it in place, such as fluent\nbuilders. For example:\n\n```carbon\nclass FooBuilder {\n   // These methods mutate `self` and then return a reference to it.\n   fn SetBar[ref self: Self]() -> ref Self;\n   fn SetBaz[ref self: Self]() -> ref Self;\n\n   fn Build[ref self: Self]() -> Foo;\n}\nfn MakeFoo() -> FooBuilder;\n\nlet foo: Foo = MakeFoo().SetBar().SetBaz().Build();\n```\n\nPrior to this proposal, this code would be valid: `MakeFoo()` is an initializing\nexpression, but when it is matched with `ref self: Self` as part of the `SetBar`\ncall, it is implicitly converted to an ephemeral reference, and then the\nspecial-case rule allows `ref self: Self` to bind to the materialized temporary.\n\nHowever, those rules also imply that code like this would be valid:\n\n```carbon\nlet builder: FooBuilder = MakeFoo();\nbuilder.SetBar();\nbuilder.SetBaz();\nlet foo: Foo = builder.Build();\n```\n\nHere the programmer has accidentally used `let` instead of `var`, so `builder`\nis an immutable value. But a value expression can be implicitly converted to an\ninitializing expression by direct initialization, and as we already saw, it's\nvalid to call `MakeFoo()` and `MakeBar()` on an initializing expression. So this\ncode repeatedly materializes, mutates, and then discards a copy of `builder`,\nand then ultimately initializes `foo` with the state returned by `MakeFoo()`,\nwhich is surely not what the programmer intended. This sort of \"lost mutation\"\nbug is exactly what the distinction between durable and ephemeral references was\nintended to prevent, but the `ref self` special case combines with the\ntransitivity of category conversions to defeat that protection.\n\nA proper resolution of this issue seems beyond the scope of this proposal, so\nthis proposal removes that special case without replacement, leaving the problem\nof supporting idioms like fluent builders as future work.\n"
  },
  {
    "path": "proposals/p5606.md",
    "content": "# Keep design documents current\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5606)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Require documentation updates as part of the proposal](#require-documentation-updates-as-part-of-the-proposal)\n    -   [One TODO per document](#one-todo-per-document)\n    -   [Link to the PR instead of the proposal document](#link-to-the-pr-instead-of-the-proposal-document)\n\n<!-- tocstop -->\n\n## Abstract\n\nRequire language design proposals to either update the design documents to\nreflect the proposed changes, or add \"TODO\" comments to mark where those changes\nwill be needed, with links back to the proposal. This is intended to ensure that\nthe design documentation accurately informs readers about the current language\ndesign, without excessively burdening the proposal process.\n\n## Problem\n\nThe current evolution process allows us to adopt language design changes while\ndeferring the corresponding changes in `/docs/design`. We have no process for\nensuring that those follow-up changes actually happen, and in practice some\nadopted proposals have gone for well over a year without corresponding design\ndocument changes.\n\nThis problem is not limited to proposals for new features, but also applies to\nproposals to change existing, documented features. As a result, the design\ndocuments are not merely incomplete, but in some cases actually misleading,\nwhich has led to miscommunication and wasted effort within the Carbon team.\n\n## Proposal\n\nThis proposal modifies our evolution process to require proposals to either\nimplement the corresponding changes to the design documents, or mark the places\nthat will need to be changed with \"TODO\" comments that point back to the\nproposal. The presence of those comments should help ensure that readers are not\nmisled by the design documentation, and the links to the proposals should help\nensure readers can discover the actual design for a given feature with\nreasonable effort.\n\nThe proposal PR also adds \"TODO\" comments to `/docs/design`, both as an\nillustration of what this policy asks for, and because the policy needs to be\napplied retroactively in order to actually solve the problem. However, these\nchanges are necessarily best-effort, because it wasn't feasible for me to fully\nevaluate every proposal against the current state of the docs. In particular, I\ndidn't look at proposals numbered below 2000, and I assumed that proposals fully\nupdated `/docs/design` if they touched it at all. In addition, I did not add\n\"TODO\" comments for the terminology changes in [p2964](/proposals/p2964.md),\nbecause they would be pervasive, and probably add little value for the reader.\nInstead, I filed issue\n[#5599](https://github.com/carbon-language/carbon-lang/issues/5599) to track the\ntask of making those changes.\n\n## Details\n\nSee the changes in the proposal PR.\n\n## Rationale\n\nThis proposal will help advance our goal of\n[promoting a healthy and vibrant community with an inclusive, welcoming, and pragmatic culture](/docs/project/goals.md#community-and-culture):\nin order to effectively participate in extending, implementing, or evaluating\nthe design of Carbon, people need to be able to find accurate information about\nthat design (and avoid inaccurate information) with reasonable effort.\n\n## Alternatives considered\n\n### Require documentation updates as part of the proposal\n\nWe could require all language design proposals to implement the corresponding\nchanges in `/docs/design`. This would more thoroughly address the risk of\nreaders being misled, because you might mistakenly read documentation that's\nmarked with a \"TODO\" comment, but you can't mistakenly read documentation that\ndoesn't exist anymore.\n\nThis would also push proposals to be more concrete, detailed, and fully\nintegrated with the rest of the language. However, that's a double-edged sword:\nit could help us identify problems with a proposal before it's adopted, but it\ncould also close off the option of deferring those problems to future work in\norder to make incremental progress. More mundanely, it would also increase both\nthe up-front cost of creating a proposal, and the cost of iteratively changing\nit during review.\n\nThe loss of agility from those factors is likely to outweigh the somewhat\ntenuous and speculative benefits of this approach, at least at this early stage\nof Carbon's development.\n\n### One TODO per document\n\nThis policy intentionally encourages fairly granular TODO comments attached to\nthe specific passages where changes are needed (see especially the proposed\nchanges in\n[`details.md`](https://github.com/carbon-language/carbon-lang/pull/5606/files#diff-b84aebe5ad22a2be2b4c222cf68fd93981ebcd2451bafb56ed5fe46ec186a3c8)).\nWe could instead encourage having a single TODO comment per document, in order\nto reduce the burden on proposal authors.\n\nHowever, this would have several related drawbacks for readers of the\ndocumentation:\n\n-   It increases the risk that the reader will overlook the TODO comment\n    altogether, because it may be quite far away from the passage they're\n    reading.\n-   It increases the risk of false positives, where passages that remain valid\n    are caught up in the scope of a file-level TODO comment.\n-   It may force the TODO comment to be less specific about how the proposal\n    changes the content of the document. This compounds the previous problem,\n    because it means the reader has to do more work to distinguish true from\n    false positives.\n\nTogether, these drawbacks could severely undermine the purpose of this proposal.\nBy contrast, the burden of granular TODOs on proposal authors seems relatively\nmarginal. For example, I was able to add TODO comments for 8 proposals in a few\nhours, despite in most cases being quite unfamiliar with their contents.\n\n### Link to the PR instead of the proposal document\n\nThis policy specifies that the TODOs should include a link to the proposal\ndocument, but we could instead link to the proposal PR. This would be more\nconsistent with existing documentation, which rarely links to proposal documents\n(among other things, this makes it easier to find all references to a given\nproposal). The PR also surfaces some information not available in the proposal\ndocument, such as the discussion associated with a proposal, and the other\nplaces where TODOs were added. Finally, the PR UI gives you access to a rendered\nview of the proposal document (accessible through \"View file\" in the drop-down\nmenu for the file), in which links to other documents take you to the versions\nthat existed as of when the proposal was committed, which may help clarify the\nhistorical context of the proposal if those documents have changed in the\nmeantime.\n\nHowever, the TODO links serve a very different purpose than other proposal\nlinks: when we link to a proposal in a \"References\" or \"Alternatives considered\"\nsection of a document, we're providing interested readers with supplementary\ninformation about the rationale and history of the design being documented, and\nfor those purposes the additional information in the PR is directly relevant.\nHere, by contrast, the proposal is acting as the sole documentation for _the\ndesign itself_, and for that purpose all the relevant information is in the\nproposal document itself.\n\nFinally, in the event that the reader wants additional information from the PR,\nevery proposal document has a prominent PR link at the top, so the additional\nburden on those readers is a single click. By contrast, the link from a proposal\nPR to the corresponding rendered document is hidden in a drop-down menu\nsomewhere in the middle of the PR's \"files changed\" page.\n"
  },
  {
    "path": "proposals/p5661.md",
    "content": "# Progressive disclosure principle\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5661)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal codifies our preference for designs that support \"progressive\ndisclosure\", meaning that programmers can ignore a given language concept (or\neven be unaware of it) until it is directly relevant to the task they're doing.\n\n## Problem\n\nCarbon's design choices have been motivated in part by a desire for \"progressive\ndisclosure\", but that approach has not been codified as a design principle.\n\n## Proposal\n\nSee\n(`docs/project/principles/progressive_disclosure.md`)[/docs/project/principles/progressive_disclosure.md],\nwhich is introduced by this proposal.\n\n## Rationale\n\nIn order to have a vibrant\n[community and culture](/docs/project/goals.md#community-and-culture), Carbon\nneeds to be effectively teachable and learnable. Progressive disclosure supports\nthat goal by minimizing the amount that must be learned at any one time, and by\nenabling concepts to be introduced when they are most salient to the programmer.\n\nRelatedly, although\n[\"lies-to-children\"](https://en.wikipedia.org/wiki/Lie-to-children) can be an\nappropriate teaching tool, they also risk undermining the health of the\ncommunity by creating distance between those who know the full truth and those\nwho have only been taught the \"lie\". This principle helps minimize that risk,\nthrough the expectation that progressive disclosure not invalidate the\nprogrammer's prior understanding of the language.\n\nFinally, this principle helps make Carbon code\n[easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write),\nby minimizing the amount of Carbon knowledge that a programmer needs in order to\nread, understand, or write a given piece of code.\n"
  },
  {
    "path": "proposals/p5670.md",
    "content": "# Guidance on AI coding tools\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5670)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Place more restrictions around AI-based tool usage when contributing](#place-more-restrictions-around-ai-based-tool-usage-when-contributing)\n\n<!-- tocstop -->\n\n## Abstract\n\nEstablish some guidance on using AI coding tools when contributing to the Carbon\nLanguage project. These tools have growing popularity and interest, and it would\nbe good to have a clear and actively documented set of guidance for folks\ninterested or already using them.\n\n## Problem\n\nAI-based coding tools are wildly popular at this point and we should have active\nguidance about how and when to use them when contributing to Carbon rather than\nbeing reactive.\n\n## Background\n\n-   [LLVM Developer Policy guidance on AI generated code](https://llvm.org/docs/DeveloperPolicy.html#ai-generated-contributions)\n\n## Proposal\n\nAll submissions to Carbon need to follow our Contributor License Agreement\n(CLA), in which contributors agree that their contribution is an original work\nof authorship. This doesn’t prohibit the use of coding assistance tools, but\nwhat’s submitted does need to be a contributor’s original creation.\n\nCarbon's license was also selected specifically to maintain full compatibility\nbetween any contributions to Carbon and contributions to LLVM so that we can\npotentially move things between these projects easily. We want the same to be\ntrue regarding the use of AI-based coding tools, and so any contributions to\nCarbon should also abide by the guidance in the\n[LLVM Developer Policy around AI generated code](https://llvm.org/docs/DeveloperPolicy.html#ai-generated-contributions)\n\nThis proposal updates our contributing documentation to contain both these\npoints.\n\n## Rationale\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n    -   Explicitly documenting what is and isn't required when contributing to\n        Carbon makes the project more open and welcoming to new contributors.\n\n## Alternatives considered\n\n### Place more restrictions around AI-based tool usage when contributing\n\nWe could consider adopting more restrictions on how AI-based tools can be used\nas part of contributing to Carbon. However, at this point we don't have a\ncompelling rationale for this.\n\nThere are real concerns around the quality of code output from AI-based tools in\nsome cases. However, we should not rely on avoiding the tools to provide\nprotection from low-quality code. Instead, as we already do, we have a system of\ncode review, coding standards, and extensive testing to ensure high-quality\ncontributions regardless of the tools used. **The quality, correctness, and\nutility expectations of contributions are true regardless of which tools are\nused as part of authoring the contribution.**\n\nWe have also seen abuse where large volumes of automatically generated\n\"contributions\" have been sent to projects, overwhelming their community. Again,\nthis is never OK, regardless of which tools are used to achieve it. We hold the\ncontributors responsible for using any and all tools responsibly and making\nuseful and constructive contributions with them.\n\nLast but not least, we also understand that there may contributors who do not\nwish to use these tools. Currently, we are not proposing any tools in the\nrequired workflow of the project.\n"
  },
  {
    "path": "proposals/p5689.md",
    "content": "# Semantic Identity and Order-Dependent Resolution for Rewrite Constraints\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5689)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n    -   [Canonicalization](#canonicalization)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Order independence](#order-independence)\n    -   [Syntactic equivalence](#syntactic-equivalence)\n\n<!-- tocstop -->\n\n## Abstract\n\nThe rules for rewrite constraint resolution say that when there are multiple\nassignments to the same associated constant in a facet type, they must all be\nidentical. But it does not clearly identify whether that means syntactically\nidentical or semantically. And if semantically, whether that is before or after\nsubstituting from the RHS of other rewrite constraints.\n\n## Problem\n\nPreviously we had been working with the intention of requiring syntactical\nequivalence for all rewrite constraints within a facet type that assign to the\nsame associated constant. However this is highly problematic for implementation\nin the toolchain, since we lose syntactic information when we create the semir\nof the rewrite constraints. In particular, once a facet type is fully\nconstructed, all syntactic information is lost, as individual instructions are\nevaluated and their canonical constant values are what is stored in the facet\ntype in order to make facet types themselves canonical.\n\nThis problem becomes most visible when applying\n[the `&` operation](https://docs.carbon-lang.dev/docs/design/generics/details.html#combining-interfaces-by-anding-facet-types)\nto combine two facet types with rewrite constraints of the same associated\nconstant, such as: `(I where .X = ()) & (I where .X = .Y and .Y = ())`. Here the\nfacet type on the right will be resolved to `I where .X = () and .Y = ()` before\napplying the `&` operation, so we have lost syntactic knowledge that `.X` was\nbeing assigned `.Y`. That makes things inconsistent if we consider it an error\nto give `.X` two differently-written values in a single facet type, such as\n`I where .X = () and .X = .Y and .Y = ()`.\n\nTherefore we would like to consider a semantic identity requirement instead,\nhowever there are soundness issues, implementation-specific inconsistencies, or\ndiagnostic inconsistencies, unless we carefully specify how rewrite constraints\nare applied through substitution when checking for conflicting assignments and\ncycles between rewrite constraints.\n\nFor example, given `I where .Y = () and .Y = .X and .X = .Y`:\n\n-   If `.X = .Y` is resolved to `.X = ()` first, then the two assignments to\n    `.Y` are not in conflict and can be considered identical, and no cycle is\n    found.\n-   If `.Y = .X` is resolved to `.Y = .Y` first, however, we find a cycle and\n    diagnose this as an error.\n-   If `.X = .Y` is resolved to `.X = .X` by using the second constraint for\n    `.Y` instead of the first one, we also find a cycle and diagnose an error.\n\nThat leaves us with the question of whether this facet type contains a cycle\n`.Y = .Y` after being resolved, or contains two identical assignments of\n`.Y = ()` and one of `.X = .Y`.\n\nOne question is whether we should have any reliance on ordering of rewrite\nconstraints in resolution. In other words, whether it's okay that reordering the\nrewrite constraints changes whether a cycle is found or not.\n\nIf ordering should not affect the determination of cycles, then we have a choice\nfor what to look for:\n\n-   Should we always use an ordering that finds a cycle, if such an ordering\n    exists?\n-   Should we always use an ordering that avoids a cycle, if such an ordering\n    exists?\n\nIf we are okay with the ordering of rewrite constraints affecting the detection\nof cycles, then we need to precisely specify how the ordering works in order to\nmake implementations consistent:\n\n-   In what order are the RHS of rewrite constraints resolved?\n-   When substituting for a reference to another rewrite constraint, in what\n    order do we choose a constraint to substitute from?\n\n## Background\n\n-   [Design: Rewrite constraint resolution](https://github.com/carbon-language/carbon-lang/blob/67b67af7a61b9cea1d47c3a1009f78ac00790a47/docs/design/generics/appendix-rewrite-constraints.md?plain=1#L195-L304).\n-   [Open discussion notes from 2025-06-17](https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.qti4vn50zwy).\n-   Conversation on\n    [this proposal's PR](https://github.com/carbon-language/carbon-lang/pull/5689),\n    in particular\n    [this comment thread](https://github.com/carbon-language/carbon-lang/pull/5689#discussion_r2164881833).\n-   Discord discussion from #generics-and-templates on\n    [2025-06-17](https://discord.com/channels/655572317891461132/941071822756143115/1384632814196101171)\n    and\n    [2025-06-25](https://discord.com/channels/655572317891461132/941071822756143115/1387499929056055469).\n\n## Proposal\n\nWe propose to allow ordering of rewrite constraints to affect cycle detection,\nwith the following orderings specified when resolving:\n\n-   Rewrite constraints should be resolved left-to-right.\n-   When a reference to another rewrite constraint is found, it should be\n    substituted with the first matching rewrite constraint found from\n    left-to-right.\n-   When combining two facet types `LHS & RHS`, the LHS facet type's rewrite\n    constraints are ordered before the RHS facet type's constraints when\n    resolving the combined facet type. Effectively, the rewrite constraints from\n    the RHS are concatenated onto the constraints from the LHS, then the facet\n    type is resolved.\n\n## Rationale\n\nWe believe that order dependence is in line with the design direction of the\nlanguage overall. In particular, this aligns with the\n[information accumulation principle](/docs/project/principles/information_accumulation.md).\nThe principle says:\n\n> If a program attempts to use information that has not yet been provided, the\n> program is invalid.\n\nThis suggests that looking ahead for a rewrite constraint to avoid a cycle is an\ninvalid operation.\n\nHowever, it also states that:\n\n> Carbon programs are invalid if they would have a different meaning if more\n> information were available.\n\nThis might seem to suggest that the meaning can not change when the order in\nwhich code is written changes. But here we take _meaning_ to refer to the\nresolved state of all associated constants when there are no errors present.\nUsing ordering to avoid cycles and prevent error diagnostics is a common\npractice in Carbon, such as with the use of forward declarations. This proposal\nmakes the ordering effect whether a cycle is found and diagnosed, but in the\nabsence of a cycle, the ordering does not affect the resulting values of the\nassociated constants.\n\nUsing a prescribed ordering to resolve and find cycles simplifies the\nimplementation, avoiding the need to consider all `n!` orderings of `n`\nconstraints. It also simplifies explaining the language rules, as you can step\nthrough the resolving algorithm without excessive branching choices, much like\nyou would step through lines of code in a debugger.\n\nUsing a left-to-right order is consistent with how Carbon is parsed and executed\ngenerally. If there were multiple statements written on the same line, they\nwould also be executed left-to-right.\n\n### Canonicalization\n\nA key part of toolchain implementation is the ability to canonicalize constant\nvalues, including facet types. This means that once resolved, the order of the\nrewrite constraints must be able to be effectively lost, as different orderings\nwould all result in the same canonical facet type.\n\nAfter being resolved, a facet type rewrite constraints have two key properties:\n\n-   Each associated constant appears at most once on the LHS of a rewrite\n    constraint. There are no duplicate assignments.\n-   Each associated constant that appears on the RHS of a rewrite constraint\n    does not appear on the LHS of any rewrite constraint. There are no\n    relationships between rewrite constraints.\n\nWhen combining two facet types with `LHS & RHS` we said that the rewrite\nconstraints of the LHS come before the rewrite constraints of the RHS. Since the\nLHS and RHS are each fully resolved before being combined, canonicalization\nrequires that the rewrite constraints within the LHS and the RHS can be ordered\nin arbitrary ways without changing whether a cycle is found.\n\nAssume that we have two orderings such that one produces a cycle, and one does\nnot. That means we have a branching point from an associated constant, so there\nare two rewrite constraints for that same constant, so one must appear on the\nLHS and one on the RHS of the `&` operator. Now their order is fixed, as we have\nspecified that all rewrite constraints from the LHS come before those from the\nRHS. So we will always choose the same constraint when replacing that associated\nconstant, and consistently find a cycle or not, regardless of how constraints\nare ordered within the LHS and RHS facet types.\n\n## Alternatives considered\n\n### Order independence\n\nThis has two possibilities: eagerly finding cycles or eagerly avoiding cycles.\nIn either case, this complicates the toolchain implementation without making the\nlanguage more expressive. The user can always write constraints in a way that\ndoes not produce a cycle in a left-to-right ordering if the constraints are\nvalid.\n\nEagerly finding cycles produces errors when unnecessary, which seems more\nhostile than needed. Eagerly avoiding cycles could be seen as being helpful, as\nwe find a way to complete the concrete assignments whenever possible. In that\ncase, given a cycle of rewrite constraints, adding a concrete value for any\nassociated constant in the cycle, written anywhere in the facet type, breaks the\ncycle. Whereas with left-to-right ordering, the concrete value needs to be the\nfirst rewrite constraint for the associated constant.\n\nWith eager cycle breaking, this cycle `I where .Y = .X and .X = .Y` is broken by\nadding `.X = ()` anywhere in the facet type:\n`I where .Y = .X and .X = .Y and .X = ()`. For a human reading left to right, we\nstill read a cycle, but have to keep reading to understand why it's not.\n\nWith left-to-right cycle breaking, the same expressivity is kept, but the\nconcrete value must be written before other rewrites of the same associated\nconstant: `I where .Y = .X and .X = () and .X = .Y`. Now for a human reading\nfrom left to right, we can read that `.Y = () and .X = ()` and can disregard\nother later assignments to `.X`.\n\n### Syntactic equivalence\n\nWe could choose to diagnose `I where .X = () and .X = .Y and .Y = ()` as a\nconflicting assignment to `.X`, since the RHS of the two assignments are written\ndifferently, even though the resolved value of the RHS can be found to be `()`\nin both of them.\n\nThis is perhaps the simplest rule for humans to understand, but requires\nmaintaining syntactic information throughout the toolchain, complicating the\nimplementation and is at odds with canonicalization.\n\nGiven the following example:\n\n```\n(I where .X = .Y and .Y = ()) & (I where .X = ())\n```\n\nThe combined facet type combines `.X = .Y` and `.X = ()` which are syntactically\ndifferent. But the facet type on either side of the `&` operator are resolved\nand canonicalized. Canonicalization requires that `I where .X = .Y and .Y = ()`\nis the same type as `I where .X = () and .Y = ()`, but when combined with\n`I where .X = ()` one violates the syntactic rule and one does not.\n\nThus we would need to only apply syntactic identity within a single facet type,\nbut use a semantic identity when combining facet types. This makes for a more\ninconsistent experience and implementation.\n"
  },
  {
    "path": "proposals/p5914.md",
    "content": "# Updating Carbon's safety strategy\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/5914)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Goals and requirements](#goals-and-requirements)\n-   [Proposal](#proposal)\n-   [Direction for temporal and data-race memory-safe type system model](#direction-for-temporal-and-data-race-memory-safe-type-system-model)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Defer beginning the concrete safety design](#defer-beginning-the-concrete-safety-design)\n    -   [Pursue an alternative strategy towards memory safety specifically](#pursue-an-alternative-strategy-towards-memory-safety-specifically)\n    -   [Adopt a memory safety strategy more closely based on Rust](#adopt-a-memory-safety-strategy-more-closely-based-on-rust)\n\n<!-- tocstop -->\n\n## Abstract\n\nCarbon is accelerating and adjusting its safety strategy, specifically to flesh\nout its memory safety strategy and reflect simplifying developments in the\nsafety space.\n\nThis proposal replaces the previous directional safety strategy with a new\nconcrete and updated framework for the safety design. It includes a specific\nframework for memory safety, simplified build modes, specific \"safety modes\",\nand terminology.\n\nThis proposal also provides a _directional_ suggestion for temporal and\ndata-race safety specifically.\n\nIn addition to fully building out the above directional component, there are\nseveral other aspects of our safety design that will follow in subsequent\nproposals. The hope is to establish the initial framework here.\n\n## Problem\n\nCarbon's safety strategy pre-dates the increased importance and urgency of\nhaving a memory safety strategy, and our subsequent efforts to accelerate this\npart of Carbon's design. It also was written at a time with deep uncertainty\nabout the performance costs of both safety and hardening efforts. And it left\nmajor areas as future work that are now needed such as a specific model for\ndelineating when Carbon code has memory safety enforced.\n\nWe need an updated, more concrete, and more precise strategy now that we're\nbeginning to directly develop safety designs.\n\n## Background\n\n-   [Basic Concepts and Taxonomy of Dependable and Secure Computing](https://doi.org/10.1109%2FTDSC.2004.2)\n-   [Secure by Design: Google's Perspective on Memory Safety](https://research.google/pubs/secure-by-design-googles-perspective-on-memory-safety/)\n-   [Story-time: C++, bounds checking, performance, and compilers](https://chandlerc.blog/posts/2024/11/story-time-bounds-checking/)\n\n## Goals and requirements\n\nOur end goal for Carbon's memory safety strategy is to allow large-scale,\nexisting C++ codebases to _incrementally and scalably_ begin writing new code in\na memory-safe language without loss of their existing legacy codebase. Handling\nreal-world C++ codebases also means handling large-scale dependencies on C++,\nbut also on C and even Rust.\n\nWe plan to support a two step migration process:\n\n1. Highly automated, minimal supervision migration from C++ to a dialect of\n   Carbon designed for C++ interop and migration.\n2. Incremental refactoring of the Carbon code to adopt memory safe designs,\n   patterns, and APIs.\n\nFrom this framing of our problem statement and end-goal, we can extract detailed\nrequirements on the memory safety design in Carbon:\n\n-   The ability to write Carbon as a \"rigorously memory safe programming\n    language\" (defined in the \"Secure by Design\" paper).\n    -   Requires temporal, spatial, and type errors to be rejected at compile\n        time or detected at runtime with fail-stop behavior.\n    -   Requires initialization errors to not have undefined behavior, but\n        allows, for example, zero-initialization rather than fail-stop behavior.\n    -   This does not require complete elimination of data races, but does\n        require\n        [addressing temporal memory safety even in the face of concurrency](/docs/design/safety#data-races-versus-unsynchronized-temporal-safety).\n    -   We directly refer to this as simply a\n        [\"memory-safe language\"](/docs/design/safety/terminology.md#memory-safe-language)\n        in Carbon.\n-   Seamless integration between Carbon's memory safe code and the memory unsafe\n    code resulting from migrating existing C++.\n    -   Safe and unsafe code should be freely mixed, with incremental checking\n        of the strictly safe aspects of the code.\n-   A smooth, incremental path for this memory unsafe Carbon code to become more\n    memory safe over time.\n    -   Must resonate with users as _significantly_ more incremental than\n        migrating directly to Rust. That is, the granularity of increasing\n        safety needs to be significantly smaller than moving an entire file from\n        C++ to Rust.\n-   Similar level of runtime spatial safety checks as Rust with similar runtime\n    overhead.\n-   No reference counting or garbage collection by default -- we want to\n    preserve C++ (and Rust) precise and explicit control over the lifetime of\n    resources.\n-   Minimal temporal safety runtime overhead: in aggregate and in real-world\n    application benchmarks, any performance overhead would need to be under 1%.\n    -   We expect to spend 1-2% of runtime overhead achieving spatial safety,\n        and these would be cumulative.\n    -   There has been strong, persistent resistance to over 2% runtime overhead\n        in broad contexts.\n    -   Rust shows that this is achievable using primarily compile time\n        techniques.\n\nWe also have some less critical but still _highly desirable_ goals:\n\n-   Seamless _safe_ Rust interop -- able to reliably and consistently avoid\n    unsafe on the boundary with Rust code\n    -   Should be no worse than the best Rust/C++ interop which uses extra\n        safety annotations for the C++ API\n-   Data race prevention\n\nWhether we fully achieve these secondary goals or not, we need to clearly\ndemonstrate where we end up and what any remaining gap there is towards these\ngoals.\n\n## Proposal\n\nSee the new [proposed safety design](/docs/design/safety/README.md) and\n[safety terminology](/docs/design/safety/terminology.md) for the core proposed\nstrategy and model.\n\n## Direction for temporal and data-race memory-safe type system model\n\n> Note: this is a _directional_ component of the proposal, and should be treated\n> as provisional until dedicated proposals fully establish our model here.\n\nWe expect Carbon to tackle temporal and data-race safety through its type\nsystem, much as Rust and strict Swift do. However, we believe there are\nsubstantial opportunities to select a model that:\n\n-   provides comparable and compatible levels of safety;\n-   improves the ergonomics of interop with existing C++ APIs; and\n-   enables significantly more incremental adoption when starting from C++ code.\n\nHowever, these benefits aren't free: they come at the cost of added complexity\nin the type system itself. Fundamentally, while we will strive to keep Carbon as\nsimple as we can within its design constraints, we expect Rust to be a simpler\nlanguage than Carbon, and for Carbon's improved interop model and incremental\nadoption to always come at the cost of complexity. We also don't expect this\ncomplexity to be something that can be fully hidden in implementation details of\nstandard libraries; some of it will be fundamental and visible to user code in\norder to allow the greater degree of flexibility.\n\nThere are at least five relevant places where we expect Carbon to differ from\nRust in this category:\n\n-   Including constructs parallel to C++ constructs that are not present in\n    Rust.\n-   More precise modeling using more pointer types, to allow _safe_ and\n    _ergonomic_ mutable aliasing.\n-   More incremental enforcement of data-race safety.\n-   Aligning concepts and idioms with C++.\n-   Having fewer assumptions about unsafe code.\n\nFirst, Carbon is going to include language constructs to match C++ that Rust\navoids completely, and this comes at a complexity cost. A canonical example is\ninheritance: Carbon will have inheritance and virtual dispatch built into the\nlanguage, allowing straightforward C++ interop and migration for APIs that use\nit. These features increase the size of the language overall, and through\ninteraction increase the complexity of safety features.\n\nThe second of these is the most significant change to safety: supporting safe,\nshared mutation. We think this will open up the door to significantly more\nflexible code while still providing memory safety. With Rust, there are two\nkinds of safe pointers: shared borrows (`&`), and mutable borrows (`&mut`). The\nlatter are required to be exclusive -- no other safe pointers alias the mutable\nobject. We expect to have more distinguished types of pointers in Carbon to be\nable to model more C++ coding patterns safely, including both shared mutable\npointers, and exclusive mutable pointers -- this is where the complexity\nincreases. While the exact design of this needs to be carefully fleshed out, our\ncurrent idea is to build on the concepts of\n[safe, shared mutability in the Ante Language](https://antelang.org/blog/safe_shared_mutability/).\nBuilding illustrative examples of how this impacts C++ code migrating towards\nmemory safety is an important part of our planned deliverables for 2025.\n\nThird, we expect to have more incremental enforcement of data-race safety in\nCarbon, similar to how\n[Swift allowed code to incrementally adopt the necessary patterns and restrictions](https://www.swift.org/documentation/concurrency/)\nto be data-race safe. The necessary infrastructure was provided as independently\nadoptable APIs, and enforcement was then available optionally prior to Swift 6\nmaking this a requirement.\n\nFourth, we will express Carbon's core concepts around mutation in terms of C++\nidioms and concepts. For example, in a container, we expect iterators can use\nshared mutable pointers, and the C++ concept of \"iterator invalidation\" will be\ncaptured by methods that require exclusive mutable access, precluding any\noutstanding shared mutable pointers.\n\nLastly, Carbon's safety model will make fewer assumptions about what unsafe code\nis allowed to do than Rust. To avoid undefined behavior, the optimization of\nsafe code will not rely on properties that are not established locally. For\nexample, there won't be an assumption that a call to C++ code won't save a copy\nof pointers to passed-in objects. When there are restrictions on what unsafe\ncode can do, we will endeavor to make violations into\n[erroneous behavior](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2795r2.html#bigpic),\nwhere the behavior is well-defined while still considered a diagnosable\nprogramming mistake. This reduces the risks of unsafe code during its\nincremental migration to memory safe code. It also leaves unsafe Carbon code as\nreasonable to work in and maintain over a longer period, which can enable more\nwidespread migration of C++ to unsafe Carbon. The amount of change and effort\nrequired to convert a piece of code from unsafe Carbon to safe Carbon is much\nless than the amount of change required to also change languages, introduce an\ninterop boundary, and make any API changes needed to enable memory safety all at\nonce. We believe this will significantly reduce churn effort along the\nboundaries of memory safety during incremental migration from unsafe Carbon to\nmemory safe Carbon code as opposed to moving from C++ directly to a memory safe\nlanguage.\n\nSome of these differences may eventually be compelling directions for Rust to\nimprove its C++ interop, and we plan to develop these in active collaboration\nwith the Rust community. For these areas of potential overlap, Carbon largely\nprovides an open field for experimentation and proving out ideas. However, we\nexpect the majority of the differences we can achieve here would introduce\ncomplexity and might change the nature of Rust making it difficult to retrofit.\nAs a consequence, there are likely to remain durable tradeoff differences\nbetween Carbon and Rust going forward.\n\n## Rationale\n\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software)\n    -   Without memory safety, it will not be reasonably secure to continue to\n        write high performance software in low-level languages that provide the\n        desired performance control.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   Our understanding of practical safety techniques, especially new details\n        of this uncovered over the past several years, directly form the need\n        for an update to our safety strategy.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   A primary motivation and constraint across the surface of safety\n        features is to better enable C++ code interop and migration.\n\n## Alternatives considered\n\n### Defer beginning the concrete safety design\n\nThe current directional strategy has served us well, and it would be technically\npossible to continue to defer turning this into a concrete design. However, we\nhave had strong feedback from multiple interested users that they need the\nsafety component to be concrete to do any further evaluation of Carbon, and we\nare accelerating our work to meet this need.\n\n### Pursue an alternative strategy towards memory safety specifically\n\nThere are many different approaches to memory safety that we could pursue. We\nhaven't exhaustively listed them, however most of the major candidates are\nexcluded by our specific goals. For example, a GC-based strategy for solving\ntemporal memory safety is a non-starter for users who specifically need non-GC\nmemory management. Rather than exhaustively list the alternatives that are\nexcluded, we have tried to list the specific [goals](#goals-and-requirements)\nthat led to the proposed direction.\n\n### Adopt a memory safety strategy more closely based on Rust\n\nAn especially appealing alternative is to base our memory safety model\n_precisely_ on Rust's. It would give us a strong existence proof, a good basis\nto understand soundness, etc. Many of the most difficult questions have already\nbeen answered. This was a seriously considered direction.\n\nHowever, Rust already exists and is an excellent language. Replicating Rust is\n_not_ a goal of Carbon. Our goal is to specifically address use cases where Rust\nis not viable at the moment, specifically due to the need for pervasive C++\ninterop or automated migration from a large, existing C++ codebase. This\ndirectly motivates pursuing a memory safety model that attempts to further\noptimize the ergonomics and incrementality of adopting memory safety when\nstarting in this position.\n"
  },
  {
    "path": "proposals/p6008.md",
    "content": "# Replace `impl fn` with `override fn`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6008)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal renames the syntax used to mark an overriding definition of a\nvirtual method from `impl fn` to `override fn` to avoid ambiguity.\n\n## Problem\n\nThe phrase `impl fn` was introduced to mark overriding virtual functions,\nhowever, it is now ambiguous: besides indicating an overriding virtual function,\nit can be parsed as an \"impl\" declaration when the construct following \"impl\"\nbegins with a lambda introduced by \"fn\".\n\n## Background\n\nThe original syntax was adopted in\n[proposal #777](https://github.com/carbon-language/carbon-lang/pull/777) to\nemphasize that implementing interfaces and overriding virtual functions are\nsimilar operations.\n\n## Proposal\n\nThis proposal is to replace the `impl fn` syntax with `override fn` for method\noverriding in class inheritance.\n\nNote that `impl` is still a modifier keyword for library and package\ndeclarations (`impl library ...` and `impl package ...` respectively). The\nformer is unambiguous and the latter is easy to disambiguate, so no change is\nneeded for these two cases.\n\n## Rationale\n\nThis proposal is focused on the\n[That code is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\nCarbon goal. Changing the keyword from `impl` to `override` makes the intent\nclearer, resolves syntax ambiguity, and adheres to existing C++ conventions.\n"
  },
  {
    "path": "proposals/p6177.md",
    "content": "# C++ Interop: Mapping `std::string_view` to `Core.Str`\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6177)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [1. Provide a Wrapper Type](#1-provide-a-wrapper-type)\n    -   [2. Do Nothing](#2-do-nothing)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal defines a direct, zero-cost mapping between C++'s\n`std::string_view` and Carbon's `Core.Str` for C++ interoperability. The goal is\nto make C++ APIs that use `std::string_view` feel native and seamless when used\nfrom Carbon. This mapping relies on the two types having an identical memory\nrepresentation, a condition that we will work to ensure across all supported\nplatforms.\n\n## Problem\n\nSeamless interoperability with C++ is a core goal for Carbon. `std::string_view`\nhas become a ubiquitous, fundamental type in modern C++ for passing non-owning\nstring data. Without a direct mapping, Carbon developers would be forced to work\nwith ABI-incompatible wrapper types or manually unpack `std::string_view`\ninstances into pointers and sizes.\n\nThis creates significant friction:\n\n1.  **Ergonomics:** C++ APIs would not feel idiomatic. Developers would need to\n    perform constant, boilerplate conversions.\n2.  **Performance:** Any wrapper-based solution would break the zero-cost\n    abstraction principle, potentially introducing overhead at the boundary.\n3.  **Adoption:** The lack of seamless integration for such a basic type would\n    be a significant barrier to migrating or integrating C++ codebases.\n\nTo provide a truly smooth migration path and interoperability story, Carbon must\ntreat `std::string_view` as a first-class citizen, ideally as the same type as\nits native string view.\n\n## Background\n\nCarbon's `Core.Str` is, per\n[#5969](https://github.com/carbon-language/carbon-lang/issues/5969), the\nlanguage's fundamental non-owning view of a sequence of bytes. It is\n[currently implemented as a pair of a pointer to the data and a 64-bit integer representing the size in bytes](https://github.com/carbon-language/carbon-lang/blob/7c13bddc92be8ceac758189df76ebbb048e1a9d5/core/prelude/types/string.carbon#L19-L22).\nThe assumed memory layout is the pointer followed by the size.\n\nC++'s `std::string_view` serves the same purpose. However, its memory layout is\nnot standardized and varies between standard library implementations. This is\ncritical for ABI compatibility.\n\nThe layouts for major C++ standard library implementations are as follows:\n\n| Standard Library | Platform/Compiler    | Member Order         | Size Type (`size_t`) | Notes                         | Source                                                                                                                                                |\n| ---------------- | -------------------- | -------------------- | -------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **libc++**       | Clang (macOS, etc.)  | `__data_`, `__size_` | 64-bit (on 64-bit)   | Pointer first, then size.     | [`string_view`](https://github.com/llvm/llvm-project/blob/fd5bc6033e521b946f04cb9c473d9cca3da2da9b/libcxx/include/string_view#L711-L712)              |\n| **MSVC STL**     | Microsoft Visual C++ | `_Mydata`, `_Mysize` | 64-bit (on 64-bit)   | Pointer first, then size.     | [`__msvc_string_view.hpp`](https://github.com/microsoft/STL/blob/ba64eaaa8592c700949f3c09a0d8570b932828f5/stl/inc/__msvc_string_view.hpp#L1924-L1925) |\n| **libstdc++**    | GCC (Linux, etc.)    | `_M_len`, `_M_str`   | 64-bit (on 64-bit)   | **Size first, then pointer.** | [`string_view`](https://github.com/gcc-mirror/gcc/blob/6b999bf40090f356c5bb5ff8a82e7e0dc4c4ae05/libstdc%2B%2B-v3/include/std/string_view#L590-L591)   |\n\nAs the table shows, there is a key difference in member ordering, with\n`libstdc++` being the outlier compared to the assumed layout of `Core.Str`.\n\n## Proposal\n\nWe propose to map C++ `std::string_view` directly to Carbon's `Core.Str` when\nimporting C++ headers. This means the Carbon compiler will treat\n`std::string_view` as a type alias for `Core.Str` at the ABI level.\n\nTo achieve this, the following conditions must be met:\n\n1.  **Identical Representation:** The memory layout (sequence of fields, size,\n    and alignment) of `std::string_view` and `Core.Str` must be identical for\n    the target platform and C++ standard library.\n2.  **Platform-Wide Compatibility:** The ultimate goal is for this mapping to\n    work seamlessly across all Carbon-supported architectures.\n\nInitially, this direct mapping will be enabled only for targets where the\nrepresentation is known to match. For other platforms, we will pursue one of two\nstrategies:\n\n-   Work with standard library vendors (for example, `libstdc++`) to align on a\n    consistent representation for `std::string_view` across architectures,\n    falling back to providing a patched version of these libraries if necessary.\n-   Adapt the memory layout of Carbon's `Core.Str` on a per-platform basis to\n    match the target's native `std::string_view` ABI.\n\nThis ensures that while the initial implementation may be constrained, the\nlong-term design is for universal, zero-cost compatibility.\n\n## Details\n\nThe initial implementation will assume `Core.Str` has a `(pointer, size)`\nlayout. This means the direct mapping will work out-of-the-box on platforms\nusing `libc++` (Clang) and MSVC STL.\n\nFor platforms using `libstdc++`, the current `(size, pointer)` layout is\nincompatible. The direct mapping will be disabled on these platforms by default\nuntil compatibility is achieved. Our strategy is to first align `Core.Str`'s\nlayout with the dominant `(pointer, size)` convention used by Clang and MSVC. We\nwill then engage with the `libstdc++` community to explore standardizing this\nlayout for better cross-compiler compatibility.\n\nFurthermore, `Core.Str` is defined with a 64-bit size field. C++\n`std::string_view` uses `size_t`, which is 32-bit on 32-bit targets. Therefore,\nthis direct mapping will initially be restricted to 64-bit targets, which are\nCarbon's primary focus.\n\nIt is essential to recognize that both `Core.Str` and `std::string_view` are\nfundamentally views over bytes, not Unicode characters. This proposal maintains\nthat semantic alignment. If Carbon requires a string type that understands\ncharacter boundaries, it should be a separate, distinct type in the standard\nlibrary and not interfere with this fundamental C++ interoperability mechanism.\n\n## Rationale\n\nThis proposal directly supports the following Carbon goals:\n\n-   **Interoperability with and migration from existing C++ code:**\n    `std::string_view` is one of the most common types in modern C++ interface\n    design. A seamless mapping is not a luxury but a requirement for effective\n    interoperability.\n-   **Performance-critical software:** By ensuring a direct, zero-cost mapping,\n    we avoid any performance penalties at the C++/Carbon boundary for string\n    data. This is critical for systems programming where such overhead is\n    unacceptable.\n-   **Code that is easy to read, understand, and write:** A direct mapping\n    allows developers to think of `std::string_view` and `Core.Str` as the same\n    concept, reducing cognitive load and eliminating the need for manual\n    conversions.\n-   **Naming of `Core.Str`:** The choice of `Str` over `String` for the\n    non-owning view type is intentional. It avoids confusion with owning types\n    like C++'s `std::string`. `Str` is introduced as a new term of art for\n    Carbon, providing a concise and readable name for this fundamental type. The\n    shorter name is preferred for its clarity and reduced verbosity, especially\n    for a type that will be used frequently. This is based on the decision in\n    leads question\n    [#5969](https://github.com/carbon-language/carbon-lang/issues/5969).\n\nBy defining a clear path toward universal ABI compatibility for this type, we\nare building a solid foundation for deep and performant integration with the\nexisting C++ ecosystem.\n\n## Alternatives considered\n\n### 1. Provide a Wrapper Type\n\nWe could choose to always import `std::string_view` as an opaque Carbon struct,\nfor example, `Core.Cpp.string_view`.\n\n-   **Advantages:** This would be ABI-safe on all platforms immediately.\n-   **Disadvantages:** This approach is not seamless. It would require explicit\n    conversions between `Core.Str` and `Core.Cpp.string_view`, adding\n    boilerplate and potential performance overhead. It violates the goal of\n    making C++ APIs feel native to Carbon.\n\n### 2. Do Nothing\n\nWe could leave it to the developer to manually handle `std::string_view` by\naccepting it as an opaque type and using C++ helper functions to extract the\npointer and size.\n\n-   **Advantages:** Simplest to implement in the compiler.\n-   **Disadvantages:** This provides a terrible developer experience and runs\n    directly counter to Carbon's core goal of excellent C++ interoperability. It\n    would make using a vast number of modern C++ libraries prohibitively\n    difficult.\n\nThe proposed approach of a direct mapping is superior as it prioritizes the\nlong-term goals of performance and ergonomics, even if it requires a phased\nimplementation to achieve full platform support.\n"
  },
  {
    "path": "proposals/p6231.md",
    "content": "# Disambiguate \"value binding\"\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6231)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Rename \"a binding declared by a value binding pattern\"](#rename-a-binding-declared-by-a-value-binding-pattern)\n    -   [Other names for \"primitive conversion from reference to value\"](#other-names-for-primitive-conversion-from-reference-to-value)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal removes the definition of the term \"value binding\" as a primitive\ncategory conversion from reference to value, replacing it with the term \"value\nacquisition\". The other meaning of \"value binding\", a binding declared by a\nvalue binding pattern, is unchanged.\n\n## Problem\n\nThe design docs currently define \"value binding\" in two conflicting ways: it can\nmean the binding declared by a value binding pattern, or it can mean a primitive\ncategory conversion from reference to value. The two can usually be\ndisambiguated based on context, but it's not always straightforward, and the\ndouble meaning complicates naming within the toolchain implementation.\n\n## Proposal\n\nThis proposal removes the definition of the term \"value binding\" as a primitive\ncategory conversion from reference to value, replacing it with the term \"value\nacquisition\".\n\n## Details\n\nSee the changes elsewhere in the\n[proposal PR](https://github.com/carbon-language/carbon-lang/pull/6231).\n\n## Rationale\n\nUsing unambiguous terminology advances our\n[community and culture](/docs/project/goals.md#community-and-culture) goals, by\nfacilitating clear communication.\n\n## Alternatives considered\n\n### Rename \"a binding declared by a value binding pattern\"\n\nWe could instead rename the other meaning of \"value binding\", but that would be\nconsiderably more difficult because that meaning appears to be more common, and\nbecause it's part of a cluster of other heavily-used terms, such as \"reference\nbinding\" and \"binding pattern\", which we would need to rename for consistency.\n\n### Other names for \"primitive conversion from reference to value\"\n\nWe considered several alternative names before settling on \"value acquisition\":\n\n-   \"Value borrowing\" highlights the close analogy to Rust borrowing, which\n    similarly forbids mutation of the object for the lifetime of the borrow.\n    However, this naming choice somewhat prejudges the safety story for this\n    operation.\n-   \"Value snapshotting\" and \"value observation\" may not effectively communicate\n    the ongoing coupling between the object and the value.\n-   \"Value capturing\" reuses and extends the existing meaning of \"capturing\" in\n    lambdas. However, it may be confusing that a lambda can have value captures\n    that are not initialized by value capturing (for example because the\n    initializer is a value, not a reference).\n-   \"Value expression conversion\" is straightforward and hard to misunderstand.\n    However, we sometimes use \"value binding\" to refer to the _result_ of a\n    reference-to-value conversion, for example \"the lifetime of a value\n    binding\". \"Value expression conversion\" doesn't seem to lend itself to that\n    usage, possibly because it's too generic to be a recognizable term of art.\n"
  },
  {
    "path": "proposals/p6254.md",
    "content": "# C++ Interop: Toolchain Implementation for Function Calls\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6254)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Importing C++ functions](#importing-c-functions)\n    -   [Overload resolution](#overload-resolution)\n    -   [Direct calls versus thunks](#direct-calls-versus-thunks)\n    -   [Thunk generation](#thunk-generation)\n    -   [Parameter and return value handling](#parameter-and-return-value-handling)\n    -   [Member function calls](#member-function-calls)\n    -   [Operator calls](#operator-calls)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Require manual C++ wrappers](#require-manual-c-wrappers)\n    -   [Mandate Carbon ABI compatibility with C++](#mandate-carbon-abi-compatibility-with-c)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal details the toolchain implementation for calling imported C++\nfunctions from Carbon. It covers how C++ overload sets are handled, the process\nof overload resolution leveraging Clang, and the generation of \"thunks\"\n(intermediate functions) when necessary to bridge Application Binary Interface\n(ABI) differences between Carbon and C++.\n\n## Problem\n\nSeamless, high-performance interoperability with C++\n[is a fundamental goal of Carbon](https://github.com/carbon-language/carbon-lang/blob/f9bd01536b97961039257cc10fb20b495f7a9b33/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code).\nThe Carbon language design for C++ interoperability, particularly for function\ncalls, is described in the\n[Carbon calling convention design](https://docs.google.com/document/d/1KUxumZtNe3mY3TsjW2s_ZADOlAaFlrtsLKHVILtqIaM).\nTo implement that design, the Carbon toolchain must be able to translate\nCarbon-side calls to C++ functions into instructions the C++ side can\nunderstand. Several challenges arise at the toolchain level:\n\n-   C++ supports function overloading, requiring the toolchain to resolve calls\n    to the correct C++ function within an overload set.\n-   C++ types do not always have identical representations or ABIs to their\n    Carbon counterparts (see\n    [Carbon <-> C++ Interop: Primitive Types](https://github.com/carbon-language/carbon-lang/blob/44b2f60c90df5c1b0ce86f97bb0ece2a94eb50ea/proposals/p5448.md)).\n    For example, parameter passing conventions (by value, by pointer) or return\n    value handling (direct return versus return slot) might differ. This may\n    require the toolchain to synthesize adapter code.\n-   C++ member functions require special handling of the `this` pointer.\n-   C++ supports features like default arguments which need a defined mapping.\n\nA clear, robust implementation strategy is needed to handle these complexities,\nensuring both correctness and performance.\n\n## Background\n\n[Carbon's C++ interoperability philosophy](https://github.com/carbon-language/carbon-lang/blob/01e12111a8a685694ccd2c9deb2779f907917543/docs/design/interoperability/philosophy_and_goals.md)\naims to minimize bridge code and provide unsurprising mappings. When Carbon code\nimports a C++ header, the functions declared within become potentially callable\nentities. C++ overload resolution rules are complex, and replicating them\nperfectly within Carbon would be difficult and likely divergent over time.\nFurthermore, direct calls are only possible when the ABI conventions of the\nCarbon call site precisely match the expectations of the C++ callee.\n\n## Proposal\n\n1.  **Import:** C++ functions and methods, including overload sets, are imported\n    into Carbon and represented internally (conceptually, as specific overload\n    set instructions in SemIR).\n2.  **Overload Resolution:** When a call to an imported C++ function or overload\n    set occurs in Carbon, Carbon leverages Clang's overload resolution\n    mechanism. Carbon argument types are mapped to hypothetical C++ types /\n    expressions, and Clang's `Sema` determines the best viable function.\n3.  **ABI Bridging (Thunks):**\n    -   If the selected C++ function's ABI (parameter types, return type\n        handling, calling convention) matches the Carbon call site's ABI based\n        on defined type mappings, a direct call is generated.\n    -   If the ABIs mismatch, Carbon generates an intermediate function, called\n        a **C++ thunk**. This thunk has a \"simple\" ABI callable directly from\n        Carbon (typically using only pointers and basic integer types like\n        `i32`/`i64`). The thunk internally calls the actual C++ function,\n        performing necessary argument conversions (for example, loading a value\n        from a pointer) and handling return value conventions (for example,\n        managing a return slot).\n4.  **Call Execution:** The Carbon code either calls the C++ function directly\n    or calls the generated C++ thunk.\n\n## Details\n\n### Importing C++ functions\n\nWhen a C++ header is imported using `import Cpp`, declarations within that\nheader are made available. Function declarations, including member functions and\noverloaded functions, are represented internally within Carbon's SemIR. An\noverload set from C++ is represented as a single callable entity in Carbon,\nassociated with the set of C++ candidate functions.\n\n### Overload resolution\n\nTo resolve a call like `Cpp.MyNamespace.MyFunc(arg1, arg2)` where `MyFunc` might\nbe an overload set imported from C++:\n\n1.  **Map Arguments:** Carbon argument instructions (`arg1`, `arg2`) are mapped\n    to placeholder C++ expressions (conceptually similar to\n    [`clang::OpaqueValueExpr`](https://github.com/llvm/llvm-project/blob/1e99026b45b048a52f8372399ab83d488132842e/clang/include/clang/AST/Expr.h#L1178)).\n    The types of these expressions are determined by mapping the Carbon argument\n    types to corresponding C++ types\n    ([Carbon <-> C++ Interop: Primitive Types](https://github.com/carbon-language/carbon-lang/blob/44b2f60c90df5c1b0ce86f97bb0ece2a94eb50ea/proposals/p5448.md)).\n2.  **Invoke Clang Sema:** Carbon invokes Clang's overload resolution logic\n    ([`clang::OverloadCandidateSet::BestViableFunction()`](https://github.com/llvm/llvm-project/blob/1e99026b45b048a52f8372399ab83d488132842e/clang/include/clang/Sema/Overload.h#L1456))\n    with the mapped C++ name, the candidate functions from the imported overload\n    set, and the placeholder argument expressions.\n3.  **Select Candidate:** Clang determines the best viable C++ function based on\n    C++ rules (implicit conversions, template argument deduction if applicable\n    later, etc.). If resolution fails (no viable function, ambiguity), Clang's\n    diagnostics are surfaced as Carbon diagnostics.\n4.  **Access Check:** After selecting a function, Carbon checks if the function\n    is accessible based on C++ access specifiers (`public`, `protected`,\n    `private`) in the context of the call.\n\n### Direct calls versus thunks\n\nA direct call from Carbon to C++ is possible only if the ABI matches exactly. A\n**C++ thunk** is required if:\n\n-   **Type Representation Mismatch:** A parameter or the return type has a\n    different representation in Carbon than expected by the C++ ABI, requiring\n    conversion. For example, a Carbon `bool` (`i1`) passed to a C++ `bool`\n    (often `i8`), or complex struct types.\n-   **Return Convention Mismatch:** The C++ function returns a non-trivial type\n    by value, which typically requires a hidden return slot parameter in the\n    ABI, whereas Carbon might expect a direct return value.\n-   **Parameter Convention Mismatch:** C++ expects a parameter by way of\n    pointer/reference where Carbon provides a value, or vice-versa.\n-   **Default Arguments:** The Carbon call omits arguments that have default\n    values in C++. The thunk provides the default values.\n-   **Variadic arguments:** (Future work) Calling\n    [C++ variadic arguments](https://en.cppreference.com/w/cpp/language/variadic_arguments.html)\n    functions.\n\nIf a thunk is _not_ required, Carbon emits a direct call instruction targeting\nthe mangled name of the C++ function.\n\n### Thunk generation\n\nIf a thunk is required for a C++ function `CppOriginalFunc()`, Carbon generates\na new internal function, conceptually `CppOriginalFunc__carbon_thunk()`:\n\n1.  **Signature:** The thunk has an ABI that is simple and directly callable\n    from Carbon.\n    -   Parameters corresponding to C++ parameters with complex ABIs are passed\n        by pointer (`T*`).\n    -   Parameters with simple ABIs (like `i32`, `i64`, raw pointers) are passed\n        directly.\n    -   If `CppOriginalFunc` uses a return slot, the thunk takes a pointer\n        parameter for the return slot. Its LLVM return type becomes `void`.\n    -   If `CppOriginalFunc` returns a simple type directly, the thunk returns\n        the same simple type directly.\n2.  **Body:** The thunk body performs the following:\n    -   Loads values from pointer arguments passed by Carbon where necessary.\n    -   Performs necessary type conversions between Carbon simple ABI types and\n        C++ expected types (for example, `i1` to `i8` for `bool`).\n    -   Calls `CppOriginalFunc` with the converted arguments, potentially\n        passing the return slot address.\n    -   If `CppOriginalFunc` returned directly, the thunk returns that value. If\n        it used a return slot, the thunk returns `void`.\n3.  **Attributes:** The thunk is typically marked `always_inline` to encourage\n    the optimizer to remove the indirection. It is given a predictable mangled\n    name based on the original function's mangled name plus a suffix.\n\nThe Carbon call site then calls the thunk instead of the original C++ function.\n\n### Parameter and return value handling\n\n-   **Arguments:** When calling a C++ function (directly or by way of a thunk),\n    Carbon arguments undergo implicit conversions as needed to match the\n    parameter types determined by overload resolution. For calls requiring a\n    thunk, additional conversions might occur at the call site (for example,\n    taking the address of an object to pass by pointer to the thunk) and within\n    the thunk (for example, loading the object from the pointer).\n-   **Return Values:** If the C++ function returns `void`, the Carbon call\n    expression has type `()`. If it returns a simple type directly, the Carbon\n    call has the corresponding mapped Carbon type. If the C++ function uses a\n    return slot, the Carbon call is modeled as initializing the storage\n    designated by the return slot argument (often a temporary created at the\n    call site), and the overall call expression typically results in the\n    initialized value.\n\n### Member function calls\n\n-   **Instance Methods:** When `object.CppMethod()` is called, `object` becomes\n    the implicit `this` argument. Clang's overload resolution handles the\n    qualification (for example, `const`). The `this` pointer is passed as the\n    first argument, either directly or to the thunk.\n-   **Static Methods:** Calls like `CppClass::StaticMethod()` are treated like\n    free function calls; no `this` pointer is involved.\n\n### Operator calls\n\nCalls to overloaded C++ operators are handled similarly to function calls.\nCarbon identifies the operator call, looks up potential C++ operator functions\n(both member and non-member), and uses Clang's overload resolution to select the\nbest candidate. Thunks may be generated if required by the selected operator\nfunction's ABI.\n\n## Rationale\n\n-   **Leverages Clang:** Reusing Clang's overload resolution avoids\n    reimplementing complex C++ rules and ensures consistency.\n-   **Performance:** Direct calls are used when possible. Thunks are designed to\n    be minimal and aggressively inlined, minimizing overhead.\n-   **Correctness:** Thunks handle ABI mismatches systematically, ensuring\n    correct data marshalling between Carbon and C++.\n-   **Developer Experience:** Aims for C++ calls to feel natural in Carbon,\n    hiding much of the complexity of ABI bridging.\n-   **Interop Goal:** Directly supports the core goal of seamless C++\n    interoperability.\n\n## Alternatives considered\n\n### Require manual C++ wrappers\n\nInstead of generating thunks automatically, Carbon could require developers to\nwrite C++ wrapper functions with simple C-like ABIs for any C++ function whose\nABI doesn't directly match Carbon's expectations.\n\n-   **Rejected because:** This places a significant burden on the developer,\n    increases boilerplate, hinders rapid iteration, and makes C++ libraries feel\n    less integrated. It violates the goal of minimizing bridge code.\n\n### Mandate Carbon ABI compatibility with C++\n\nCarbon could define its types and calling conventions to always match a specific\nC++ ABI (for example, Itanium).\n\n-   **Rejected because:** This would heavily constrain Carbon's own evolution\n    and design choices. It wouldn't solve the problem entirely, as C++ ABIs\n    themselves vary (for example, between platforms, compilers, or even\n    libraries like libc++ vs libstdc++ for `string_view`). It conflicts with the\n    goal of software and language evolution.\n"
  },
  {
    "path": "proposals/p6333.md",
    "content": "# CLI and separate compilation\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6333)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Look-and-feel](#look-and-feel)\n    -   [Bazel rule design](#bazel-rule-design)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Command changes](#command-changes)\n        -   [Compile command](#compile-command)\n        -   [Build command](#build-command)\n        -   [Link command](#link-command)\n    -   [Mapping packaging directives to filenames](#mapping-packaging-directives-to-filenames)\n        -   [Support for other packages](#support-for-other-packages)\n        -   [Disallow ambiguous library names](#disallow-ambiguous-library-names)\n-   [Example interaction with Bazel](#example-interaction-with-bazel)\n    -   [carbon_library and carbon_binary](#carbon_library-and-carbon_binary)\n        -   [Indirect API exposure](#indirect-api-exposure)\n        -   [Core package rules](#core-package-rules)\n-   [Future work](#future-work)\n    -   [Caching checked IR, C++ AST, and other possible compile artifacts](#caching-checked-ir-c-ast-and-other-possible-compile-artifacts)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Naming of commands and rules](#naming-of-commands-and-rules)\n    -   [Support a full-fledged build system](#support-a-full-fledged-build-system)\n    -   [Don't support packaging directive to filename mappings](#dont-support-packaging-directive-to-filename-mappings)\n    -   [Distribute pre-compiled versions of Core files](#distribute-pre-compiled-versions-of-core-files)\n    -   [Create an explicit mapping from packaging directives to files](#create-an-explicit-mapping-from-packaging-directives-to-files)\n\n<!-- tocstop -->\n\n## Abstract\n\n-   Change the look-and-feel of the `carbon` compilation command set to use\n    `compile`, `link`, and `build`.\n-   Build library-to-file discovery for `Core`, but support it in a general\n    manner.\n\n## Problem\n\nThe current command line is still a prototype, and lacks support for regular\nuse. For example:\n\n-   `carbon compile` produces one object file per input file. When\n    `--output-file` is specified and there are multiple inputs, the output is\n    repeatedly overwritten.\n-   `carbon compile` doesn't provide a trivial way to produce object files for\n    the prelude. The `carbon_binary` rule is, behind the scenes, separately\n    compiling all the prelude files individually and doing its own custom\n    linking with those.\n-   When writing a small test program (for example \"hello world\") it would be\n    nice to have a single command to run to produce a program. Right now,\n    `carbon compile` and `carbon link` must be used in combination.\n\nEssentially, we have a decent setup for testing, but not one that's easy to use\nin real-world situations.\n\n## Background\n\nIn C++, `clang++ main.cpp -o program` is a way to produce `program`. This is\ntrying to reach a similar goal to make it easy to build and test small programs.\n\nKey commands related to this proposal are `carbon compile`, `carbon clang`, and\n`carbon link`. The end result will likely compose multiple command elements in\norder to build the output.\n\n### Look-and-feel\n\nNote the goal here is to align on look-and-feel of separate compilation.\nAlthough the `carbon` CLI is important to the language, most details aren't\nnecessary to address through the proposal process. For example, we want to get\nflag names right here, but also we wouldn't expect a proposal for flag name\nchanges.\n\n### Bazel rule design\n\nThis is a proposal for the command line. Bazel rules are mentioned because it\ncan help illustrate interactions with build systems. However, this proposal is\nnot intended to decide Bazel design, and the existing Bazel rules have not been\nthrough the proposal process.\n\n## Proposal\n\nRestructure compilation into:\n\n-   `carbon compile`: Take a single input to build, and produce a single output\n    `.o`.\n-   `carbon build`: Take multiple inputs in order to produce a linked binary.\n    -   Overlaps with `carbon compile` and `carbon link`.\n\nThese are intended to accept flexible inputs:\n\n-   Support passing in standard C++ file extensions to any of these for\n    compilation.\n-   For `carbon build` in particular, it should not be necessary to pass in\n    `Core` files that are required.\n    -   We will require a correlation between library names inside `Core` and\n        directory structure. For example, `prelude/types`\n        [maps to](#mapping-packaging-directives-to-filenames)\n        `core/prelude/types.carbon`.\n    -   The same strict correlation will be supported for other packages.\n\nAt the end, it should be possible to:\n\n-   Run `carbon build program.carbon` with non-prelude `Core` imports, and get\n    an executable program.\n-   Have Bazel rules that mix C++ code and Carbon code. For example:\n\n    ```bazel\n    carbon_library(\n        name = \"foo\",\n        srcs = [\"foo.cpp\", \"foo.impl.carbon\"],\n        apis = [\"foo.carbon\"],\n    )\n    carbon_binary(\n        name = \"bar\",\n        srcs = [\"main.cpp\"],\n        deps = [\":carbon_library\"],\n    )\n    ```\n\n## Details\n\n### Command changes\n\n#### Compile command\n\nThe `carbon compile` command is intended to be a straightforward single input,\nsingle output command. Dependencies will be provided through a combination of:\n\n-   Given a package name to directory mapping, a\n    [filename mapping](#mapping-packaging-directives-to-filenames) based on the\n    library name.\n-   Potentially other input files passed through a flag, for use in imports (not\n    producing their own object files).\n-   A single input source file for primary compilation.\n-   A single optional output file, which for `<filename>.carbon` will default to\n    `<filename>.o` (including `.impl.carbon` becoming `.impl.o`).\n\nAs part of supporting a mix of C++ and Carbon files, we will support\n`carbon compile foo.cpp` with results similar to `carbon clang -- -c foo.cpp`.\n\n#### Build command\n\nThe `carbon build` command will be the new, simple way to compile, as a\nreplacement for `carbon compile`. It will:\n\n-   Load provided files.\n-   For packages with directory mappings, particularly `Core`, add all `.carbon`\n    files as inputs.\n    -   For `Core`, we expect `.o` files to be produced in the same way as for\n        `carbon link`.\n    -   For other packages, all files in the directory will be compiled,\n        although there may be some support added for using pre-compiled state\n        (not explicitly proposed).\n-   Do something similar to the appropriate series of `carbon compile`\n    invocations.\n    -   A key divergence is that we should avoid re-checking files that would be\n        used across multiple `carbon compile` invocations.\n-   Run the equivalent of `carbon link` over produced inputs.\n\nWhile the build command will default to providing an executable program, we may\nalso want it to be capable of producing `.a` and `.so` files. However, we can\ndecide whether `carbon build` should be required for these kinds of outputs as\nan implementation detail.\n\n#### Link command\n\nThe `carbon link` command will change to make the following work:\n\n```sh\ncarbon compile foo.carbon -o foo.o\ncarbon link foo.o -o program\n```\n\nIt will be typical to link multiple object files into a single output file. The\noutput file flag will be optional, defaulting to `program`, possibly with a\ntarget-specific extension; for example, `program.exe` for Windows.\n\nThis requires that `Core` files (not just the prelude) will have been compiled,\nso that their object files can be included in output. It's expected that this\nwill be provided through on-demand runtimes. It should be possible to opt out of\nincluding these, for example so that the Bazel `carbon_binary` rule can use\n`carbon link` while also providing its own `Core` object files. However, it\nshould be on-by-default.\n\n### Mapping packaging directives to filenames\n\nWhen we need a file for a packaging directive:\n\n-   The package name will correspond to a root directory. For example,\n    `package Core ...` could correspond to `lib/carbon/core/...`.\n-   The library name will correspond to a path under that, suffixed by\n    `.carbon`. For example, `package Core library \"prelude/types\";` could\n    correspond to `lib/carbon/core/prelude/types.carbon`.\n    -   The default library will use the name `default.carbon`. For example,\n        `package Core;` could correspond to `lib/carbon/core/default.carbon`.\n\nSuppose we have some command line `carbon compile a.carbon`, and in `a.carbon`,\nit does `import Core library \"map\";`. This needs to load `core/map.carbon`, and\nwithout parsing every file matching `core/**/*.carbon`.\n\nIn order to achieve this:\n\n-   The `compile` command will have a built-in directory mapping for the `Core`\n    package, for example to `/usr/share/carbon/core` (when installed to the\n    `/usr` prefix).\n-   The `map` library name will need to match the filename, so\n    `/usr/share/carbon/core/map.carbon`.\n    -   Slashes may be provided in the library name, for subdirectories.\n-   If `map.carbon` has other `Core` imports, they will be recursively loaded\n    once parsed.\n    -   Checking isn't required to process imports from a file.\n\nWe never need to map `impl` files by library name to a filename, or the other\nway around; they cannot be discovered through an `import`, and we always need to\nparse them in order to discover their imports. As a consequence, there is no\nneed to define rules mapping libraries to `.impl.carbon` files.\n\n#### Support for other packages\n\nBecause we'll build this for Core, it would probably be straightforward to\nexpose this for other packages, too. So for example, we could support\n`--package-path=MyPackage:/my/package` for getting API files. However, that is\nsecondary to the `Core` behavior, so any support may become more of an\nimplementation detail for what makes sense.\n\n#### Disallow ambiguous library names\n\nFor imports which rely on the implicit mapping (not in general), we will\ndisallow ambiguous library names. This includes an explicit `library \"default\"`\nstring name, which can be ambiguous with the implicit `default` library (both\nwould map to `default.carbon`).\n\n## Example interaction with Bazel\n\n### carbon_library and carbon_binary\n\nThe Bazel build rules will expose `carbon compile` and `carbon link` behaviors\nin a slightly more Bazel-idiomatic way. For example, given:\n\n```bazel\ncarbon_library(\n    name = \"lib\",\n    srcs = [\"a.impl.carbon\", \"b.impl.carbon\", \"b.carbon\"],\n    apis = [\"a.carbon\"],\n)\ncarbon_binary(\n    name = \"bin\",\n    srcs = [\"main.carbon\"],\n    deps = [\":lib\"],\n)\n```\n\nThe way this will approximately work is:\n\n-   `carbon_library` will have an implicit dependency on a set of `Core`\n    libraries (such as a build target `//carbon/lang:core`).\n    -   This will have a network of `carbon_library` rules, some of which may\n        look like `lib`.\n-   For `lib`:\n    -   Invoke `carbon compile` four times, producing a `.o` file for each\n        input.\n    -   The API files will be additional inputs to the `impl` file compilations.\n-   For `bin`:\n    -   Source files will be compiled similarly to `lib`.\n        -   The `deps` means `a.carbon` and `b.carbon` will be additional\n            inputs, but it should ideally be an error if `b.carbon` is imported\n            directly. This is required because `a.carbon` can expose `b.carbon`\n            on the import boundary, meaning an indirect import of `b.carbon`\n            must work.\n    -   Link object files into an executable.\n\nIt's possible that we may use `carbon build` where `carbon compile` is\nmentioned, but if so, it should not make a significant difference in the\nuser-visible behavior.\n\nFor both, there should be an implicit dependency on the full Core package, not\njust the prelude. This is because we want the Core package to be easy to access.\n\n#### Indirect API exposure\n\nThe `apis` attribute is suggested to support only _direct_ dependencies. For\nexample:\n\n```bazel\ncarbon_library(\n    name = \"a\",\n    apis = [\"a.carbon\"],\n)\ncarbon_library(\n    name = \"b\",\n    apis = [\"b.carbon\"],\n    deps = [\":a\"],\n)\ncarbon_library(\n    name = \"c\",\n    srcs = [\"c.carbon\"],\n    deps = [\":b\"],\n)\n```\n\nIf `c.carbon` imports `a.carbon`, the build should error that `a.carbon`\nrequires a direct dependency. We should allow forwarding, so that the same could\ncompile without requiring `c` to have a direct dependency on `a`. This should\nlook like `exports = [\":a\"]`, added to `b` (and superseding the need to list\n`:a` in `deps`).\n\nThis feature may see frequent use, for example in `Core` to allow writing it as\nmultiple libraries instead of one large glob. But it's probably also something\nthat can be delayed a little, because we can just use a big glob and force\ndirect dependencies.\n\n#### Core package rules\n\nIn the `core/` directory, we will set up corresponding `carbon_library` rules.\nThese will need to pass flags to opt-out of normal behaviors, in particular the\ndependency on the prelude library.\n\n## Future work\n\n### Caching checked IR, C++ AST, and other possible compile artifacts\n\nAs designed, every time any of the `build`, `compile`, or `link` commands are\nused, all prelude files and possibly more of the `Core` package will be\nre-checked, along with C++ ASTs being reproduced.\n\nInstead, Carbon could serialize checked IR, store produced C++ ASTs, and so on.\nC++ ASTs in particular could be substantially constructed based on parsed Carbon\nstate, rather than checked Carbon state, allowing more build parallelism. In\ndistributed or cached build systems, being able to reuse portions of the build\nmay increase performance.\n\nThe specific build outputs we want to store may substantially affect how we\nwould set up a build process. The absence of a decision may lead to the\nimplementation diverging from what's actually needed, meaning parts will be\nreimplemented later. This isn't expected to be too high cost.\n\nThere are also ways to improve build performance without taking these steps.\n[Clang modules](https://clang.llvm.org/docs/Modules.html) might be used for\nimproving Clang compile performance without significant support from Carbon.\n\nFor now we will rely on whatever caching Bazel does for the `.a` output of a\n`carbon_library`. No other outputs will be made available. That may change, but\nleads want to spend our limited development and review time on other features\nfor the 0.1 milestone.\n\n## Rationale\n\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n    -   `carbon build` should support easy experimentation with Carbon, and also\n        small projects.\n    -   Other build support is intended to scale up for larger codebases.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   The intent is to be able to migrate a CMake, Makefile, or other build at\n        relatively low cost. An invocation to `clang` can typically be replaced\n        with `carbon clang`, linking a binary becomes `carbon link`, and so on.\n    -   Similarly, `carbon_library` and `carbon_binary` are important to us for\n        Bazel support and a migration from `cc_library` and `cc_binary`.\n\n## Alternatives considered\n\n### Naming of commands and rules\n\nFor `carbon compile` and `carbon build`, this is trying to split apart concepts.\nSome considered alternatives are:\n\n-   Merge `compile`, and possibly also `link`, into `build`. Flags could be used\n    to differentiate between the versions desired, rather than subcommand names.\n    -   We expect that splitting these apart makes it easier to turn them into\n        replacements in C++ builds, and easier to understand even in\n        Carbon-specific builds.\n-   Have `carbon build` produce `a.out`\n    -   `a.out` is the default output of most C++ compilers, but it reflects a\n        legacy executable file format. Using the legacy name may reflect\n        backwards compatibility that Carbon doesn't plan.\n    -   Changing the default output name is probably low-cost, and people will\n        get used to it.\n\n### Support a full-fledged build system\n\nThe `build` command as proposed here is intended to be sufficient for quick\ntesting and simple tools. However, it's not intended to be flexible with custom\nrules, plugins, and so on. These are features offered by systems such as CMake\nor Bazel.\n\nInstead, we could provide a full build system. Multiple other languages have\ngone in that direction:\n\n-   In Rust, `cargo` combines a\n    [build system](https://doc.rust-lang.org/cargo/commands/cargo-build.html)\n    and package manager.\n-   In Swift,\n    [SwiftPM](https://www.swift.org/documentation/server/guides/building.html)\n    provides a similar offering as to `cargo`.\n-   In Zig, there are\n    [multiple build system](https://ziglang.org/learn/build-system/) commands.\n\nCarbon's\n[project goal](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\nis migration of existing C++ developers, particularly \"This means integrating\ninto the existing C++ ecosystem by supporting incremental migration from C++ to\nCarbon.\"\n\nThe expectation is that C++ users will already be using a fully featured build\nsystem, such as CMake. Migration should be easier if users can retain their\nexisting build system, particularly since a typical migration can be expected to\nmix both Carbon and C++ code.\n\nWhile Carbon could provide _both_ a separate compilation system _and_ a fully\nfeatured build system, a build system is a substantial undertaking and we expect\nC++ developers to already have one.\n\n### Don't support packaging directive to filename mappings\n\nInstead of making a mapping from packaging directives to filenames, we could\ngenerate a list specific to the `Core` package, and not expose that for other\npackages.\n\nWe shouldn't manually maintain a mapping for the `Core` package; it should be\nautomated. It's likely that whatever we do in this space, however we would\nsupport a mapping, would be of interest to small projects. It will probably be\nlow cost for us to build support for things other than `Core`, so we should just\ndo that.\n\n### Distribute pre-compiled versions of Core files\n\nInstead of building object files for `Core` on demand, we could distribute them\nas part of Carbon. The upside of this is it would make builds a little faster;\nthe downside is that we'd end up in more of a situation where supported target\nplatforms were enumerated, or perhaps where special platforms could be built\non-demand in a bespoke manner.\n\nWe can probably add limited caching where it'd help, and support all platforms\nusing similar logic that way with little performance penalty.\n\n### Create an explicit mapping from packaging directives to files\n\nThe current `package` and `library` directive design means a given `api` file\nmay have 0 or more `impl` files.\n\nWe could make it clear from the declaration in an `api` file what `impl` files\nexist. This would require a split to describe the possible situations. For\nexample:\n\n-   `library \"foo\";`: The common case of 1 `impl` file.\n-   `library \"foo\" api_only;`: Add a single keyword that indicates this is a\n    library with no `impl` file.\n-   `library \"foo\" multi_impl 3;`: Indicates this is an unusual library with 3\n    `impl` files.\n    -   Multiple impl files are expected to be rare.\n    -   We could require numbered filenames (such as `a.impl.carbon`,\n        `a.1.impl.carbon`, `a.2.impl.carbon`), but even knowing how many exist\n        would allow compiles to do validation. If we didn't do this, then it may\n        be equivalent to not require specifying the number of `impl` files (in\n        the example, `multi_impl;` instead of `multi_impl 3;`).\n\nSome advantages are:\n\n-   In the common cases of API-only or 1 impl file, we could avoid scanning the\n    file system for more files. In other words, it reduces file I/O for better\n    performance.\n-   Changes most \"missing definition\" failures from linker errors to\n    compile-time.\n    -   For example at present, if a forward declaration is in an `api` file,\n        then even if we find an `impl` file that is missing the definition we\n        don't know if there's another `impl` file that contains the definition.\n        With this feature, we could diagnose while compiling the common 0 or 1\n        `impl` file cases.\n-   Allows diagnosing unexpected or missing `impl` files, which can indicate a\n    developer mistake in the build.\n-   If multi-`impl` filenames were constrained to be numbered, we could:\n    -   When building, look for specific filenames, instead of doing a file\n        system glob for `impl` filenames.\n    -   Loosen the ambiguity constraint on library names to only disallow\n        library names ending with `\\.\\d+`.\n\nSome disadvantages are:\n\n-   Adds more keywords to the packaging declaration.\n-   Requires updating the API file's declaration in order to modify the number\n    of `impl` files.\n\nThis has been discussed in the past, but does not seem to be outlined in any\nproposals as a considered alternative, and this proposal adds new trade-offs for\nfile mappings. Leads have declined this option in order to keep packaging\ndirectives simple.\n"
  },
  {
    "path": "proposals/p6357.md",
    "content": "# C++ Interop: Mapping pointer types\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6357)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Non-nullable pointers to object types](#non-nullable-pointers-to-object-types)\n        -   [Inconsistent type sugar](#inconsistent-type-sugar)\n    -   [Non-nullable pointers to void](#non-nullable-pointers-to-void)\n    -   [Nullable pointers and `Core.Optional`](#nullable-pointers-and-coreoptional)\n    -   [`nullptr_t`](#nullptr_t)\n        -   [`nullptr`](#nullptr)\n    -   [Indexing and pointer arithmetic](#indexing-and-pointer-arithmetic)\n-   [Rationale](#rationale)\n-   [Future work](#future-work)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Map all pointers to `T*`](#map-all-pointers-to-t)\n    -   [Map `void*` to `()*`](#map-void-to-)\n    -   [Map `void*` to `u8*`](#map-void-to-u8)\n    -   [Map `void f()` to `fn Cpp.f() -> Cpp.void`](#map-void-f-to-fn-cppf---cppvoid)\n    -   [Use the name `Core.CppCompat.Void` instead of `Core.CppCompat.VoidBase`](#use-the-name-corecppcompatvoid-instead-of-corecppcompatvoidbase)\n    -   [Map `Cpp.void` to `()` instead of `Core.CppCompat.VoidBase`](#map-cppvoid-to--instead-of-corecppcompatvoidbase)\n    -   [Do not provide `Cpp.void` at all](#do-not-provide-cppvoid-at-all)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal defines direct, zero-overhead mappings from C++ object pointer\ntypes and `std::nullptr_t` to corresponding Carbon types.\n\n## Problem\n\nIn order to support interoperability between C++ and Carbon, we need to map\ntypes in each language to the other language. Currently we do not have a defined\nmapping for pointer types, which are an important concept in both languages.\nHowever, a direct mapping is not appropriate, as pointer types have different\nsemantics in Carbon versus in C++.\n\n## Background\n\nPointer types in Carbon and in C++ have different semantics. C++ pointers can be\nnull, can be indexed if they point into an array, treat any non-array object as\npointing to an array of a single element for indexing purposes, and can point to\na position one past the last element of an array. Carbon pointers allow none of\nthese things, and always point to an object.\n\nThere are three kinds of pointer type in C++:\n\n-   A _pointer to object type_ is a pointer whose pointee type is an object\n    type, such as a scalar type or a class type.\n-   A _pointer to void_ is a pointer type whose pointee type is (possibly\n    `const` and/or `volatile`) `void`.\n    -   Collectively, pointer to object types and pointer to void types are\n        called _object pointer types_, despite `void` not being an object type.\n-   A _pointer to function type_, or equivalently _function pointer type_, is a\n    pointer whose pointee type is a function type.\n\nC++ pointers to object types support arithmetic operations:\n\n-   Addition and subtraction are supported, treating pointers as an affine space\n    over the integers. Formally, arithmetic is only permitted between pointers\n    that point to elements of the same array object, but in practice these\n    operations are used substantially more broadly.\n-   Pointers can be compared relationally, if they point to subobjects of the\n    same object. The exact rules are a little more subtle than this, but\n    formally, comparisons across distinct complete objects have unspecified\n    results and most comparisons within a complete object have specified\n    results. In practice, pointer comparisons on modern architectures are\n    treated as a total order, except that the status of comparisons of\n    bitwise-equal pointers where one points past the end of one complete object\n    and the other points to the start of a distinct complete object are\n    nebulous.\n-   Pointers support array indexing notation `p[i]` -- and, to the surprise of\n    many and the delight of few, `i[p]` -- which is mostly equivalent to\n    `*(p + i)`.\n\nIn addition, the type of `nullptr`, known commonly by its standard library alias\n`std::nullptr_t`, is important to modern C++ as a mechanism for forming null\npointer values. This type is not a pointer type, but implicitly converts to\nevery pointer type, forming a null pointer value of that type.\n\nC++ also has pointers to members, `T C::*`, which are a distinct type from\npointer types in C++.\n\n## Proposal\n\nThis proposal defines a mapping from C++ object pointer types and\n`std::nullptr_t` into Carbon types, introducing new Carbon types as necessary to\nprovide the mapping:\n\n| C++ type         | Carbon type                                     | Notes                                       |\n| ---------------- | ----------------------------------------------- | ------------------------------------------- |\n| `T*`             | `Core.Optional(T*)`                             | null pointers map to `None`                 |\n| `T* _Nonnull`    | `T*`                                            | non-nullable pointers don't need `Optional` |\n| `const T*`       | `Core.Optional(const T*)`                       |                                             |\n| `void*`          | `Core.Optional(Core.CppCompat.VoidBase*)`       | `void` maps to `()` in some other contexts  |\n| `void* _Nonnull` | `Core.CppCompat.VoidBase*`                      |                                             |\n| `const void*`    | `Core.Optional(const Core.CppCompat.VoidBase*)` |                                             |\n| `nullptr_t`      | `Core.CppCompat.NullptrT`                       |                                             |\n\nFunction pointer types and pointer to member types are out of scope for this\npropopsal.\n\n## Details\n\n### Non-nullable pointers to object types\n\nC++ doesn't have non-nullable pointer types, but C++ implementations do, in\nvarious forms:\n\n| C++ type                                  | Supported by | Behavior if null |\n| ----------------------------------------- | ------------ | ---------------- |\n| `T* _Nonnull`                             | Clang        | Erroneous        |\n| `T* __attribute__((nonnull))`             | Clang        | Undefined        |\n| `void f(T*) __attribute__((nonnull))`     | GCC, Clang   | Undefined        |\n| `T* f() __attribute__((returns_nonnull))` | GCC, Clang   | Undefined        |\n| `void f(_Notnull_ T*)`                    | MSVC         | Defined          |\n| `_Ret_notnull_ T* f()`                    | MSVC         | Defined          |\n\nWe will support and encourage use of Clang's `_Nonnull` annotation, as it is the\nonly form that applies to a general pointer type rather than to a function\nparameter or return type. Clang's `T* _Nonnull` maps to Carbon's `T*`.\n\nThe `__attribute__((nonnull))` and `__attribute__((returns_nonnull))` forms will\nalso be mapped into non-nullable Carbon pointers, as these attributes are\nwidespread in existing code. A pointer type that is the type of a function\nparameter or the return type of a function that is annotated with these\nattributes maps to Carbon's `T*`.\n\nThe MSVC attributes are intended for use by static analysis tools only, not as\ncompiler inputs, so are not suitable for our uses, and are mentioned here only\nfor completeness.\n\n#### Inconsistent type sugar\n\nThe `_Nonnull` annotation is treated as _type sugar_, not as producing a\ndifferent type. This has some significant consequences for its use:\n\n-   Type sugar is easily lost through incautious type navigation. Any operation\n    that maps to a canonical type will lose the annotation. This is largely just\n    a constraint that the toolchain implementation be careful, except...\n-   ... type sugar is lost across template instantiations. There is work in\n    Clang to preserve type sugar across template instantiations, but\n    [at this time it is not complete](https://godbolt.org/z/hP35776zj). This\n    means that in templates, the distinction between non-nullable pointers and\n    nullable pointers should be expected to be lost.\n-   The annotation can differ between redeclarations of the same entity.\n    Inconsistent annotations may lead to a type being treated as either nullable\n    or non-nullable. Clang will warn on this in some cases, but the fragility of\n    type sugar means that such warnings should not be expected to be entirely\n    robust.\n\nThe consequences in C++ for losing or incorrectly determining nullability are\nmostly not too severe -- loss of best-effort diagnostics, and the compiler\ntreating the program as having defined behavior when the rules say its behavior\nis undefined. But if it causes a type to map to a different type in Carbon, that\nis potentially a larger issue, as it may affect whether the Carbon program\ncompiles.\n\nFor now we will use these type sugar anontations to inform our type mapping, but\nwill revisit this decision if they are too problematic in practice.\n\n### Non-nullable pointers to void\n\n`void` broadly has two different meanings in C++:\n\n-   A complete type with an empty representation, a size and alignment of 1, and\n    a single unique value. This is the meaning that is used by `void f()`,\n    `static_cast<void>(expr)`, and arguably by the special case `int f(void)`.\n-   An incomplete type that is a supertype of all other types (sometimes known\n    as a top type ⊤, or a universal type). This is the meaning that is used by\n    `void*`, as well as related ideas like `dynamic_cast<void*>`. While C++\n    models this form of `void` as incomplete, it would be more accurate to\n    consider it to be abstract.\n\nThere have been long-lived attempts to replace the second meaning in C++ with\nthe first, but so far they have not succeeded. If they do succeed, our approach\nwill need to shift to accommodate that change.\n\nWe map the first kind of `void` to Carbon's `()` type. In particular, a function\nthat returns `void` in C++ returns `()` in Carbon. While these types don't have\nthe same representation in general, they do have the same representation as a\nreturn type, with both types corresponding to nothing being returned.\n\nFor the second kind of `void`, we introduce a new compatibility type:\n\n```carbon\nabstract class Core.CppCompat.VoidBase {}\n```\n\nNotionally, we think of every Carbon type, including types imported from C++, as\ninheriting from this type, but practically we support a conversion from any\npointer type to a pointer to `VoidBase`, and we support a conversion from a\nvalue of any type to a value of type `VoidBase`. Other inheritance-based\nlanguage properties should decide whether to treat `VoidBase` as a supertype of\nall other types by considering how C++ treats `void` in similar contexts.\n\nThis new type is our primary mapping for `void`; the mapping of `void` return\ntypes is treated as a special case that applies only in return position. Because\n`void` in C++ can only appear in very limited positions, this means that\n`VoidBase` is used as the mapping for `void` in only the following situations:\n\n-   As the pointee type of a pointer type.\n-   As a type template argument.\n-   As a type of a typedef or type alias.\n\nThis seems like the best balance: for example, given\n\n```c++\ntypedef void OpaqueObject;\nvoid Call(OpaqueObject* handle);\n```\n\n... it seems useful to map `Cpp.OpaqueObject*` to `VoidBase*`, not to `()*`. And\ngiven:\n\n```c++\ntemplate<typename T> T ReturnAT() { return T(); }\n```\n\n... the call `Cpp.ReturnAT(VoidBase)` will still have a return type of `()`\nrather than an abstract return type, because the type appeared in return\nposition after instantiation.\n\nAs a convenience shorthand, the name `Cpp.void` is added to the `Cpp` package\nand refers to `Core.CppCompat.VoidBase`. C++'s `void* _Nonnull` maps to\n`Cpp.void*`, and similarly `const void* _Nonnull` maps to `const Cpp.void*`.\n\n### Nullable pointers and `Core.Optional`\n\nNullable object pointers, including nullable pointers to `void`, map to\n`Core.Optional(T*)`. Null pointer values map to the optional's \"none\" value.\nThis places a constraint on the implementation of `Core.Optional(T*)` that it\nhas the same ABI as a C++ pointer, including that the \"none\" state is\nrepresented with a C++ null pointer representation.\n\nWhile we do not yet have an approved design for the `Core.Optional` type, it is\nalready in use in the design of `for` statements. Adding a design for\n`Core.Optional` is out of scope for this proposal.\n\n### `nullptr_t`\n\nThe C++ null pointer type, `decltype(nullptr)`, is exposed in the standard\nlibrary as `std::nullptr_t`. This type is a scalar type built into the C++\nlanguage, and as such, we need a custom mapping for it -- our mappings for other\ncategories of C++ types don't cover it.\n\nC++'s `nullptr_t` has the same representation as `void*`, but its representation\ncomprises only padding bits. This doesn't correspond to any existing type in\nCarbon, so we introduce a new compatibility type to model it:\n\n```carbon\nclass Core.CppCompat.NullptrT {\n  adapt MaybeUnformed(VoidBase*);\n}\n```\n\nThe C++ type maps to the above type, so after `import Cpp library \"<cstddef>\";`,\nit can also be named as `Cpp.std.nullptr_t`.\n\n#### `nullptr`\n\nThe name `Cpp.nullptr` is added to the `Cpp` package, and refers to the (empty)\nconstant value of type `Core.Cpp.NullptrT`.\n\n### Indexing and pointer arithmetic\n\nThis proposal provides no support for indexing or pointer arithmetic on Carbon\npointers mapped from C++ pointers. Carbon pointers do not support indexing, and\nthe result of mapping a C++ pointer into Carbon would be a pointer that does not\nsupport indexing. In the other direction, no mechanism prevents a Carbon pointer\nfrom being passed into C++ code and then indexed, even though that is not an\noperation that would be possible in pure, safe Carbon code.\n\nEventually we will need to provide some way to take a C++ pointer and perform\nthe equivalent of indexing into it in Carbon code. However, this mechanism will\nrequire additional Carbon language features to be designed before it can be\nspecified. In particular, we will need a safety story for bounds safety, and a\ntype for representing an indexable location in some way, such as an array\niterator or array cursor type. As a result, we leave support for indexing and\npointer arithmetic as future work.\n\n## Rationale\n\nGoals:\n\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software)\n    -   C++ types are mapped to Carbon types with the same representation. This\n        avoids the need for any deep copies on the interop boundary.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   The convenience names `Cpp.void` and `Cpp.nullptr` make it easier to\n        write code that interoperates with C++ void pointers and C++ nullable\n        pointers.\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   C++ null pointers cannot \"leak\" into Carbon non-nullable pointer types,\n        except by violating a \"nonnull\" annotation in the C++ code. If\n        `_Nonnull` is violated, the result is not undefined behavior unless the\n        pointer is used in a context that would result in undefined behavior in\n        C++, such as a load or store through the pointer.\n-   [Modern OS platforms, hardware architectures, and environments](/docs/project/goals.md#modern-os-platforms-hardware-architectures-and-environments)\n    -   We do not assume that a null pointer has an all-zero-bits\n        representation. This is not true in practice on some modern\n        heterogeneous compute architectures.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   This proposal significantly enhances interoperability with C++ code, by\n        providing a mapping for very common vocabulary types in C++.\n\nPrinciples:\n\n-   [All APIs are library APIs](/docs/project/principles/library_apis_only.md)\n    -   The types added to support C++ are all ordinary class types provided in\n        the Carbon prelude.\n-   [Low context-sensitivity](/docs/project/principles/low_context_sensitivity.md)\n    -   The Carbon `Cpp.void` type has only one meaning, rather than having a\n        context-sensitive meaning. The C++ `void` type still has two different\n        meanings, and therefore two different mappings into Carbon, but that\n        problem is outside our domain.\n-   [Namespace cleanliness](/docs/project/principles/namespace_cleanliness.md)\n    -   The names we are adding to the `Cpp` package, `void` and `nullptr`, are\n        C++ keywords, and so do not conflict with any C++ identifier. While\n        Clang does provide an extension to define entities with these names, for\n        example `int __identifier(void);`, interoperting with such code is not a\n        priority.\n\n## Future work\n\n-   Add a design for `Core.Optional`, as we now have multiple language proposals\n    that depend upon it.\n-   Design interop for function pointers.\n-   Design interop for pointers to members.\n-   Design an approach for providing the functionality that C++ exposes as\n    pointer indexing and pointer arithmetic.\n\n## Alternatives considered\n\n### Map all pointers to `T*`\n\nWe could avoid wrapping nullable pointers with `Core.Optional`. However, doing\nso opens a large hole in Carbon's story for pointers, wherein pointers are not\nnullable.\n\n### Map `void*` to `()*`\n\nWe could map `void` to `()` in all contexts, and map C++'s `void*` to Carbon's\n`()*` -- or rather, to `Core.Optional(()*)`. However, in order to support\npassing arbitrary Carbon pointers to C++ `void*` parameters, we would need to\nallow `T*` to implicitly convert to `void*` in Carbon, which means we would need\nto allow `T*` to implicitly convert to `()*`. Therefore the C++ modeling of\n`void` as a supertype of all other types leaks out into pure Carbon code. This\nseems undesirable.\n\n### Map `void*` to `u8*`\n\nWe could map `void*` to `u8*` or to a pointer to some other byte-like type, to\nreflect that it represents a pointer to storage. This would result in an N:1\nmapping from C++ types to Carbon types, because both `void*` and `uint8_t*`\nwould map to the same Carbon type. The same would happen if we picked any other\nCarbon type that has a corresponding C++ type that is not `void`.\n\nIt's strongly desirable that our mapping between C++ and Carbon types fully\nround trips, because otherwise passing types between the two languages, such as\nin metaprogramming or by way of template argument deduction, would be lossy. For\nexample, if both a `vector<void*>` and a `vector<uint8_t*>` map to the same\nCarbon type `buf(u8*)`, then passing an object of that type from C++ into Carbon\nand then back into C++ must result in a type that mismatches at least one of the\noriginal types.\n\nIt's possible that we could accept some N:1 mappings, but given how common\n`void*` is on C and C++ API boundaries, the risk of problems seems particularly\nsignificant in this case.\n\n### Map `void f()` to `fn Cpp.f() -> Cpp.void`\n\nWe could use the custom `Cpp.void` type even as a function return type, removing\nthe non-uniformity of mapping it to `()` in function returns and to `Cpp.void`\nelsewhere. However, `Cpp.void` is an abstract type, so there should not exist\ninitializing expressions of this type.\n\nWe could address that by instead mapping `void` to `partial Cpp.void`, or\naliasing `Cpp.void` to `partial Core.CppCompat.VoidBase`, but either way that\nmeans that `void*` maps to a type whose pointee doesn't have the abstract /\nincomplete behavior that we desire.\n\n### Use the name `Core.CppCompat.Void` instead of `Core.CppCompat.VoidBase`\n\nWe could use a simpler name for the compatibillity type. However, given that\nthere are two different meanings of `void` in C++, having some extra clarity\nabout which meaning is intended seems useful.\n\n### Map `Cpp.void` to `()` instead of `Core.CppCompat.VoidBase`\n\nWe could pick the other meaning of `void` as the meaning of `Cpp.void`. However,\nthe `()` meaning is only really interesting as a function return type, and there\nis no reason to reach for `Cpp.void` if that meaning is desired. So mapping\n`Cpp.void` to `VoidBase` is more useful.\n\nAlso, we want the mappings between C++ and Carbon types to be bidirectional, to\nthe extent that's possible. Mapping Carbon's `()` to C++'s `void` type would\nmean that we can't consistently map all Carbon tuple types to the same family of\nC++ tuple types, such as `std::tuple`.\n\n### Do not provide `Cpp.void` at all\n\nWe could ask developers to write out the name of `VoidBase` when needed. But\nit's long and cumbersome, and we expect most other C++ types with a\ncorresponding keyword to be provided in the `Cpp` package, so providing it is\nboth useful and improves language consistency.\n"
  },
  {
    "path": "proposals/p6358.md",
    "content": "# C++ Interop: API importing and semantics\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6358)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [The `Cpp` package and namespace mapping](#the-cpp-package-and-namespace-mapping)\n    -   [`import Cpp library` directive](#import-cpp-library-directive)\n    -   [C++ built-in types](#c-built-in-types)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal defines the concrete technical mechanisms for C++\ninteroperability. It specifies the precise syntax and semantics for importing\nC++ APIs. This includes the `import Cpp library \"...\"` and implicitly importing\nC++ built-in entities, and the establishment of the `Cpp` package as the\ndedicated namespace for all imported entities.\n\n## Problem\n\nWhile Carbon has a stated goal of seamless C++ interoperability, and a\nhigh-level direction has been agreed upon, there is currently no concrete,\nspecified mechanism for developers to actually import and use C++ APIs. This\nproposal aims to address that by defining the specific syntax and semantics for\nC++ interoperability.\n\n## Background\n\nOne of Carbon's primary goals is to be a successor language. This strategy is\nentirely dependent on seamless, bidirectional interoperability with C++ to\nenable large-scale adoption and migration for existing C++ codebases.\n\nThis proposal provides the necessary details on how C++ APIs should be imported.\n\n## Proposal\n\nWe propose to formalize the following specific design elements for C++\ninteroperability:\n\n1.  **The `Cpp` Package:** All imported C++ entities, whether from built-ins or\n    library headers (see below), will be nested within a dedicated `Cpp`\n    package. This prevents name collisions with Carbon code and makes the\n    language boundary explicit.\n\n    ```carbon\n    fn UseCppTypes() {\n      // Access C++ types and functions by way of the Cpp package\n      var circle: Cpp.Circle = Cpp.GenerateCircle();\n      Cpp.PrintCircle(circle);\n    }\n    ```\n\n2.  **Importing C++ Header-Defined APIs:** To import C++ APIs from a specific\n    library header file (for example, `<vector>` or `\"my_library.h\"`), Carbon\n    code will use the `import Cpp library \"...\"` directive.\n\n    ```carbon\n    import Cpp library \"<vector>\";\n    import Cpp library \"circle.h\";\n    ```\n\n3.  **Importing C++ Built-in Entities:** To access fundamental C++ types (such\n    as `int`, `bool`, etc.), no explicit importing is needed and writing\n    `Cpp.int` and `Cpp.bool` would just work.\n\n## Details\n\n### The `Cpp` package and namespace mapping\n\nAll C++ declarations will be imported into the `Cpp` package. C++ namespaces\nwill be mapped to nested packages within `Cpp`. For example, a C++ function\n`std::string::find` would be accessible in Carbon as `Cpp.std.string.find`. The\nC++ global namespace will be mapped to the `Cpp` package itself. So a function\n`MyGlobalFunction` in the C++ global namespace will be `Cpp.MyGlobalFunction` in\nCarbon.\n\n### `import Cpp library` directive\n\nThe `import Cpp library \"...\"` directive will instruct the Carbon compiler to\nparse the specified C++ header file. The compiler will use the standard C++\ninclude paths to locate the header. Additional paths can be provided through\ncompiler flags.\n\nThe Carbon compiler will leverage a C++ front-end, like Clang, to parse the\nheaders. This ensures a high degree of compatibility with existing C++ code.\nOnly the declarations from the header will be imported, not the definitions\n(unless they are inline).\n\n### C++ built-in types\n\nA set of fundamental C++ types will be available within the `Cpp` package\nwithout any explicit `import` directive. Mapping examples:\n\n| C++ Type       | Carbon Type        |\n| -------------- | ------------------ |\n| `int`          | `Cpp.int`          |\n| `unsigned int` | `Cpp.unsigned_int` |\n| `double`       | `Cpp.double`       |\n| `float`        | `Cpp.float`        |\n| `bool`         | `Cpp.bool`         |\n| `char`         | `Cpp.char`         |\n\nThis automatic availability of built-in types is designed to make basic\ninteroperability tasks as smooth as possible.\n\n## Rationale\n\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   **Explicitness and Clarity:** The `import Cpp library \"...\"` directives\n        make all dependencies on C++ headers.\n    -   **Preventing Name Collisions:** The `Cpp` package is a critical design\n        element. It provides a clean, unambiguous namespace for all imported C++\n        code.\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   This proposal defines a foundation for seamless C++ interoperability.\n\n## Alternatives considered\n\n-   **Alternative: Explicitly importing built-ins:** We considered making C++\n    built-in types (like `int`) require some `import Cpp` directive like\n    `import Cpp;`.\n    -   **Reason for Rejection:** Since `Cpp` is a special package, it should be\n        implicitly imported, similar to Carbon's prelude.\n"
  },
  {
    "path": "proposals/p6395.md",
    "content": "# Type completeness in extend\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6395)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## Abstract\n\nRequire any target scopes in an `extend` declaration to be complete, since\n`extend` changes the scopes which are looked in for name lookup to include those\nnamed in the declaration.\n\n## Problem\n\nProposal\n[#5168](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p5168.md)\nlaid out rules for when a facet type needs to be identified or complete. When\n`require impls X` is written, then `X` must be identified. However it does not\nspecify any rule for `extend require impls X`. And we lack completeness rules\nfor other `extend` declarations, including `extend impl as X`, `extend base: X`,\nand `extend adapt X`.\n\nAn `extend` declaration always names one or more target entities which will be\nincluded in the search for names when looking in the enclosing scope of the\n`extend` declaration. In order to do name lookup into an entity, it must be\ncomplete to avoid poisoning names in the entity.\n\n## Background\n\n-   Proposal\n    [#5168](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p5168.md):\n    Forward `impl` declaration of an incomplete interface\n-   Proposal\n    [#2760](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p2760.md):\n    Consistent `class` and `interface` syntax\n-   Proposal\n    [#0777](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p0777.md):\n    Inheritance\n\n## Proposal\n\nAn `extend` declaration declares that the enclosing scope extends the scope\nassociated with any target entity named in the declaration. That is to say name\nlookups into the enclosing scope will also look into the scopes which are\nnominated by the `extend` declaration. The `extend` declaration requires that\nthe target scopes named in an `extend` declaration are complete, or if the\ntarget is a generic parameter, requires the type of the parameter to be\ncomplete.\n\nThe scope of a facet type formed by a `where` declaration extends the scope of\nits first operand. And the scope of a facet type formed by a `&` operator\nextends the scopes of both of its operands. In either case, the scope of the\nfacet type is complete if every scope it extends is complete. The facet type\n`type` is associated with an empty scope and is complete.\n\n| Facet type                   | Requirement                           |\n| ---------------------------- | ------------------------------------- |\n| `I`                          | Requires `I` is complete.             |\n| `I & J`                      | Requires `I` and `J` are complete.    |\n| `type where U impls J`       | Requires `type` is complete.          |\n| `I & (type where U impls J)` | Requires `I` and `type` are complete. |\n\n## Details\n\nTo `extend` an entity `Y` with another `Z` means that name lookups into `Y` will\nalso look into `Z`. Immediately after the `extend` operation, members of `Z`\nshould also be found when doing name lookup into `Y`, both from outside and from\ninside the definition of `Y`. In order to be able to perform lookups into `Z`,\nwe require that `extend` operations only target scopes that are complete.\n\nThis requirement functions recursively. Given an interface `B` that extends\nanother interface `A`: By naming `A` in an extend declaration, we require `A` is\ncomplete. This provides that its entire definition is known, and thus its\n`extend` relationship to `B`. The `extend` relationship there also provides that\n`B` is complete.\n\nIf the target scope of an `extend` declaration is a generic parameter, its type\nmust be complete where the `extend` declaration is written, as name lookups into\nthe extended scope will look into the type of the generic parameter.\n\n```carbon\ninterface I {\n  fn F();\n}\n\nclass C(T:! I) {\n  extend base: T;\n  // `F` names `T.F` here, found in `I`.\n  fn G() { F(); }\n}\n```\n\nAs any generic parameter in the enclosing scope is replaced by a more specific\nvalue, extended scopes that depend on a generic parameter must remain complete.\nThis includes forming a specific for the extended scope involving the parameter\nin order to surface any monomorphization errors in the resulting specific.\n\nIn the next example, the `extend` declaration in interface `A(N)` names a\nsymbolic facet type which can produce monomorphization errors when a negative\nvalue is provided for `N`. When a more specific value for the target `B(N)` is\nprovided, we require the specific value to be complete as well by forming the\nspecific. A diagnostic error would be produced while checking `C(-1)` for\ncompleteness, as it requires `A(-1)` to be complete, which requires\n`B(array(i32, -1))` to be complete, and that contains an invalid type.\n\n```carbon\ninterface B(T:! type) {}\n\ninterface A(N:! i32) {\n  // Requires `B(N)` to be complete.\n  extend require impls B(array(i32, N)) {}\n}\n\nclass C(N! i32) {\n  // Requires `A(N)` to be complete, which requires `B(N)` to be complete.\n  extend impl as A(N);\n}\n\nfn F() {\n  // Requires `C(-1)` to be complete, which requires `A(-1)` to be complete, which requires `B(array(i32, -1))` to be complete.\n  var c: C(-1);\n}\n```\n\nThese rules prohibit an `extend` declaration from naming its enclosing scope,\nsince by being part of the definition of that scope, it is implied that the\nenclosing scope is not complete. This seems reasonable as all names available\ninside the enclosing interface or named constraint are already available or\nwould conflict with the ones that are.\n\n## Rationale\n\nThis is based on the principle of\n[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write).\nFor code to be easy to write, the rules need to be consistent. Once an `extend`\ndeclaration has been written, the names inside should become available through\nthe enclosing scope immediately. If we allow an interface named in an `extend`\ndeclaration to be incomplete, then name lookup will fail ambiguously. Those same\nnames may become valid later once the interface is defined.\n\n## Alternatives considered\n\nWe considered not requiring that the scope named in an `extend` declaration be\ncomplete where it is written, but only when the enclosing scope is required to\nbe complete. This is more flexible, allowing entities to be defined later in the\nprogram. However this does not allow the use of names from the target scope in\nthe `extend` to be used from within the enclosing definition scope. They would\nnot become available until the enclosing definition scope was closed and\ncomplete.\n\nIn particular, we want this to work:\n\n```carbon\ninterface Z {\n  let X:! type;\n  fn F() -> X;\n}\nclass C {\n  extend impl as Z where .X = () {\n    // Names `X` directly.\n    fn F() -> X;\n  }\n\n  // Names `X` and `F` directly.\n  fn G() -> X { return F(); }\n}\n\n// Now `C` is complete, `C.X` and `C.F` are also available.\nfn H() -> C.X {\n  return C.F();\n}\n```\n"
  },
  {
    "path": "proposals/p6641.md",
    "content": "# Clang IRGen in Carbon\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6641)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [PR5543 More closely mimic the Clang compilation](#pr5543-more-closely-mimic-the-clang-compilation)\n    -   [Status Quo with Improvements](#status-quo-with-improvements)\n    -   [Upstream Clang Changes to use Phase Based Lowering](#upstream-clang-changes-to-use-phase-based-lowering)\n\n<!-- tocstop -->\n\n## Abstract\n\nDocument a principled and robust approach to Clang interop with respect to the\nconflict between Clang's continuous lowering approach and Carbon's phase based\nlowering.\n\n## Problem\n\nClang performs the equivalent of Carbon's `lower` progressively, interleaved\nwith parsing/semantic analysis. This is in conflict with Carbon's phase-based\napproach and leads to bugs in missing functionality in Clang's generated IR\nduring Carbon/C++ interop.\n\n## Background\n\nA review of different ways Carbon and other tools use Clang APIs is written up\n[here](../toolchain/docs/design/clang_api.md). While Swift looks like the most\ncomparable, its hand-crafted reimplementation of the Clang Sema/IRGen\ninteraction seems like a maintenance risk.\n\n## Proposal\n\nCarbon should use Clang is such a way that Clang can have the\n`clang::CodeGenerator` attached throughout Clang's Sema phase, to ensure parity\nwith existing Clang usage/behavior.\n\nThis means Clang will diverge from Carbon's strict phase-based approach (Clang\nwill be creating LLVM IR during `check` despite Carbon deferring all LLVM IR\nlowering for Carbon itself to the `lower` phase). This divergence seems\nworthwhile to keep Carbon as compatible with Clang's functionality as possible\nnow and in the face of possible changes to Clang in the future.\n\n(practically speaking, this is implemented in\n[PR6569](https://github.com/carbon-language/carbon-lang/pull/6569))\n\n## Rationale\n\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Establishing a design that leaves us as consistent with Clang's C++\n        behavior as possible both now, and in the future, with as little\n        maintenance needed when Clang changes are made.\n\n## Alternatives considered\n\n### [PR5543](https://github.com/carbon-language/carbon-lang/pull/5543) More closely mimic the Clang compilation\n\nThis looks closer/identical to Clang's API usage. But the problem is that\nClang’s `FrontendAction` API (down through… `CreateFrontendBaseAction`,\n`EmitObjAction`, `ASTFrontendAction`, `ParseAST`) is a closed system (does all\nthe work from the start to the end) whereas Carbon wants to incrementally use\nClang while parsing more Carbon, calling back into C++, etc, before finishing\nthe C++ parsing. To address that atomicity, PR5543 uses a background thread\n(without actual concurrency) \\- doing part of the `FrontendAction` work,\npausing, doing some Carbon work, then finishing up in lowering:\n\n-   `check` executes the `clang::FrontendAction` on a background thread\n    -   This runs up until `handleTranslationUnit` and blocks\n-   `check` does things to the AST, trigger template instantiation, etc\n-   `lower` triggers the background thread to continue to IR generation from the\n    AST\n\nHowever, using a background thread to achieve this requires a great deal of\ncomplexity. We have to both spawn and maintain the background thread, as well as\ninject cross-thread synchronization to orchestrate each phase of Clang's\nexecution. Especially with many different C++ compilations, this complexity and\noverhead would be increasingly concerning.\n\n### Status Quo with Improvements\n\nKeep Clang parsing without an attached `clang::CodeGenerator`, use our own\nASTConsumer to gather whatever we seem to need during parsing/sema that will be\nneeded during lowering. The code snippets above show some functionality we’re\nmissing based on the callbacks that aren’t implemented/replayed in Carbon’s\ncurrent implementation.\n\nRisk: Missing Clang features because we didn’t save the right things for\nlowering either now or with Clang changes in the future.\n\n### Upstream Clang Changes to use Phase Based Lowering\n\nChange Clang to no longer lower during parsing/sema, but in a single pass after\nthat work.\n\nThis could benefit Swift and similar API users, might simplify Clang/improve its\nperformance/make Clang’s IRGen more flexible (it wouldn’t struggle so much when\nAST properties chang (currently that’s not allowed, but even when a definition\nis found after a previous declaration - updates have to be made, etc - that\nwouldn’t be a problem if all IRGen was done late)).\n\nRisk: Upstream changes are slower, require more social engineering, buy\nin/consensus building, and the benefit to Carbon (being able to do Clang\nlowering at the same time as Carbon lowering) seems limited.\n"
  },
  {
    "path": "proposals/p6668.md",
    "content": "# C++ interop type mapping for integer and floating-point literals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6668)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [C++ literals](#c-literals)\n        -   [Integer literals](#integer-literals)\n            -   [Type of C++ integer literals](#type-of-c-integer-literals)\n            -   [Clang](#clang)\n            -   [Gcc](#gcc)\n        -   [Floating-point literals](#floating-point-literals)\n    -   [Carbon literals](#carbon-literals)\n        -   [Integer literals](#integer-literals-1)\n        -   [Floating-point literals](#floating-point-literals-1)\n        -   [Literal types](#literal-types)\n        -   [No suffixes](#no-suffixes)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Carbon to C++ type mapping](#carbon-to-c-type-mapping)\n        -   [Integer literals](#integer-literals-2)\n        -   [Floating-point literals](#floating-point-literals-2)\n    -   [C++ to Carbon type mapping](#c-to-carbon-type-mapping)\n        -   [Integer literals](#integer-literals-3)\n        -   [Floating-point literals](#floating-point-literals-3)\n-   [Future work](#future-work)\n    -   [More robust hexadecimal and binary literals in Carbon](#more-robust-hexadecimal-and-binary-literals-in-carbon)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Carbon to C++ type mapping](#carbon-to-c-type-mapping-1)\n        -   [Use the C++ standard rules for hexadecimal and binary literals](#use-the-c-standard-rules-for-hexadecimal-and-binary-literals)\n        -   [Use the Clang way of determining the type](#use-the-clang-way-of-determining-the-type)\n    -   [C++ to Carbon type mapping](#c-to-carbon-type-mapping-1)\n        -   [Use Carbon literal types](#use-carbon-literal-types)\n\n<!-- tocstop -->\n\n## Abstract\n\nProvides bidirectional mappings for types of integer and floating-point literals\nbetween Carbon and C++. For example, given a literal `123`, defines the interop\ntype.\n\n## Problem\n\nThis document addresses Carbon &lt;-> C++ type mapping of integer and floating\nliterals. This comes to use for example during overloading resolution of C++\nfunctions, when a C++ function is called from Carbon with a literal as a call\nargument. It also appears for example when importing C++ macros to Carbon for\nexample macros which define constants where the constant is a literal.\n\n## Background\n\n### C++ literals\n\n#### Integer literals\n\n##### Type of C++ integer literals\n\nAs specified in the\n[C++ standard](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf#page=31&zoom=100,85,693),\nthe type of the literal is the first type from the list below in which the value\ncan fit based on its **suffix** and the **base** of the literal.\n\n| Suffix                                  | Decimal bases                                     | Binary, octal or hexadecimal bases                                            |\n| --------------------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------- |\n| (none)                                  | `int`, `long`, `long long`                        | `int`, `unsigned`, `long`, `unsigned long`, `long long`, `unsigned long long` |\n| `u` or `U`                              | `unsigned`, `unsigned long`, `unsigned long long` | `unsigned`, `unsigned long`, `unsigned long long`                             |\n| `l` or `L`                              | `long`, `long long`                               | `long`, `unsigned long`, `long long`, `unsigned long long`                    |\n| `u` or `U` and `l` or `L`               | `unsigned long`, `unsigned long long`             | `unsigned long`, `unsigned long long`                                         |\n| `ll` or `LL`                            | `long long`                                       | `long long`, `unsigned long long`                                             |\n| `u` or `U` and `ll` or `LL`             | `unsigned long long`                              | `unsigned long long`                                                          |\n| `z` or `Z` (since C++23)                | the signed version of `std::size_t`               | the signed version of `std::size_t`, `std::size_t`                            |\n| `u` or `U` and `z` or `Z` (since C++23) | `std::size_t`                                     | `std::size_t`                                                                 |\n\nFor details on `std::size_t`, see\n[cppreference](https://en.cppreference.com/w/cpp/types/size_t).\n\nIf the value is too big to fit in any of these types, and an extended integer\ntype exists, then it may be assigned an extended type. If all types are signed,\nthen it may fit into a signed extended type. If all types are unsigned then it\nmay be fitted into an unsigned extended type. If there are both signed and\nunsigned types in the list, then both signed and unsigned extended types are\npossible types. If the value can’t fit in any of the types, the program is\nill-formed.\n\n##### Clang\n\nClang diverges from the standard in that if the decimal integer literal doesn’t\nfit to a type from the list, instead of assigning an extended integer type, it\nassigns `unsigned long long`.\n\nExample:\n\n```cpp\n#include <iostream>\n\ninline auto foo(long a) -> void { printf(\"hello from foo_long(%ld)\", a); }\ninline auto foo(unsigned long a) -> void { printf(\"hello from foo_unsigned_long(%lu)\", a); }\n\ninline auto foo(long long a) -> void { printf(\"hello from foo_long_long(%lld)\", a); }\ninline auto foo(unsigned long long a) -> void { printf(\"hello from foo_unsigned_long_long(%llu)\", a); }\n\ninline auto foo(__int128 a) -> void { printf(\"hello from foo___int128\");}\n\nint main() {\n   foo(9223372036854775808);  // MAX_LONG + 1\n   return 0;\n}\n```\n\nOutput:\n\n```\n<source>:12:9: warning: integer literal is too large to be represented in a signed integer type, interpreting as unsigned [-Wimplicitly-unsigned-literal]\n  12 |     foo(9223372036854775808);\n     |        ^\n1 warning generated.\nExecution build compiler returned: 0\nProgram returned: 0\nhello from foo_unsigned_long_long(9223372036854775808)\n```\n\n##### Gcc\n\nGcc shows a warning that the value will be treated as an unsigned integer, but\nit actually assigns the type `__int128` to it.\n\nOutput of the example above:\n\n```\n<source>:12:9: warning: integer constant is so large that it is unsigned\n  12 |     foo(9223372036854775808);\n     |         ^~~~~~~~~~~~~~~~~~~\nExecution build compiler returned: 0\nProgram returned: 0\nhello from foo___int128\n```\n\n#### Floating-point literals\n\nThe type of a floating literal is `double` unless explicitly specified by a\nsuffix. When there is a suffix, then the suffix determines the type.\n\n| Suffix                         | Floating-point literal type |\n| ------------------------------ | --------------------------- |\n| (none)                         | `double`                    |\n| `f` or `F`                     | `float`                     |\n| `l` or `L`                     | `long double`               |\n| `f16` or `F16` (since C++23)   | `std::float16_t`            |\n| `f32` or `F32` (since C++23)   | `std::float32_t`            |\n| `f64` or `F64` (since C++23)   | `std::float64_t`            |\n| `f128` or `F128` (since C++23) | `std::float128_t`           |\n| `bf16` or `BF16` (since C++23) | `std::bfloat16_t`           |\n\nIf the value doesn’t fit the type, the program is ill-formed.\n\n### Carbon literals\n\n#### Integer literals\n\nCarbon has **decimal, hexadecimal and binary** integer literals. Example:\n\n-   `123` (decimal)\n-   `0x1FE` (hexadecimal)\n-   `0b10` (binary)\n\nThere are no suffixes for the integer literal types.\n\n#### Floating-point literals\n\nCarbon supports **decimal and hexadecimal** floating-point literals. Example:\n\n1. Decimal:\n\n    - `123.456`\n    - `1.23456e791`\n\n2. Hexadecimal:\n    - `0x1.Ap123`\n\n#### Literal types\n\nCarbon has literal types, currently `Core.IntLiteral` and `Core.FloatLiteral`.\nThese are convertible to any type where they fit without any truncation or loss\nof precision.\n\nAt present, type deduction would retain the type of the literal. For example,\n`let x: auto = 1;` would result in `x` having type `Core.IntLiteral`. This is\nnot the desired behavior, and so can be expected to change in the future.\n\n#### No suffixes\n\nCarbon literals have no suffix. The reasons for this are covered in\n[Proposal #144's alternative \"Use an ordinary integer or floating-point type for literals\"](p0144.md#use-an-ordinary-integer-or-floating-point-type-for-literals).\n\n## Proposal\n\n-   **Carbon literal to C++ type**: A Carbon literal will be given a C++ type\n    according to the C++ rules when used in C++ context, such as calling a C++\n    function.\n-   **C++ literal to Carbon type**: A C++ literal will be given a C++ type\n    following the C++ rules, which will then be mapped to a Carbon type as\n    defined in [primitive types mapping](p5448.md#carbon-primitive-types).\n    -   For example, `1` becomes `int` according to C++ rules, and `int` maps to\n        `i32` in Carbon.\n\n## Details\n\n### Carbon to C++ type mapping\n\n#### Integer literals\n\nThere are no suffixes in Carbon for the integer types, so a Carbon decimal\ninteger literal will follow the C++ rules for decimal integers. Carbon also\ndoesn't make a distinction between hexadecimal and binary literals, so these\nliterals will also follow the C++ rules for decimal integers without a suffix.\n\nThe first type from this list in which the value can fit will be selected:\n\n-   `int`\n-   `long`\n-   `long long`\n-   `__int128`\n\nIf the value doesn’t fit in any of these types, the program will be ill-formed\nand diagnosed with an error. This is intended to match the C++ standard\nbehavior, instead of Clang's `-Wimplicitly-unsigned-literal` behavior.\n\nDecimal numbers are most commonly used as integer literals, so this should match\nmost of the existing C++ calls. To match the C++ calls with a non-decimal\nliteral argument, an explicit `unsigned` type will need to be provided. For\nexample, `0xDEADBEEF as u32`.\n\n#### Floating-point literals\n\nAs there are no suffixes in Carbon for the floating-point literals, a Carbon\nfloating-point literal will map to C++ `double`. If the value doesn’t fit to\ndouble, the program is ill-formed.\n\n### C++ to Carbon type mapping\n\n#### Integer literals\n\nA C++ integer literal will be given a C++ integer type following the C++ rules,\nwhich will then be mapped to a Carbon type as defined in\n[primitive types mapping](p5448.md#carbon-primitive-types).\n\n| C++ literal suffix                      | Carbon type with decimal C++ integer literals                     | Carbon type with hexadecimal, binary and octal C++ integer literals                                       |\n| --------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |\n| (none)                                  | `Cpp.int`, `Cpp.long`, `Cpp.long_long`                            | `Cpp.int`, `Cpp.unsigned_int`, `Cpp.long`, `Cpp.unsigned_long`, `Cpp.long_long`, `Cpp.unsigned_long_long` |\n| `u` or `U`                              | `Cpp.unsigned_int`, `Cpp.unsigned_long`, `Cpp.unsigned_long_long` | `Cpp.unsigned_int`, `Cpp.unsigned_long`, `Cpp.unsigned_long_long`                                         |\n| `l` or `L`                              | `Cpp.long`, `Cpp.long_long`                                       | `Cpp.long`, `Cpp.unsigned_long`, `Cpp.long_long`, `Cpp.unsigned_long_long`                                |\n| `u` or `U` and `l` or `L`               | `Cpp.unsigned_long`, `Cpp.unsigned_long_long`                     | `Cpp.unsigned_long`, `Cpp.unsigned_long_long`                                                             |\n| `ll` or `LL`                            | `Cpp.long_long`                                                   | `Cpp.long_long`, `Cpp.unsigned_long_long`                                                                 |\n| `u` or `U` and `ll` or `LL`             | `Cpp.unsigned_long_long`                                          | `Cpp.unsigned_long_long`                                                                                  |\n| `z` or `Z` (since C++23)                | `Cpp.uintptr_t`                                                   | `Cpp.uintptr_t`, `Cpp.size_t`                                                                             |\n| `u` or `U` and `z` or `Z` (since C++23) | `Cpp.size_t`                                                      | `Cpp.size_t`                                                                                              |\n\n#### Floating-point literals\n\nA C++ floating literal will be given a C++ type following the C++ rules, which\nwill then be mapped to a Carbon type as defined in\n[primitive types mapping](p5448.md#carbon-primitive-types). That means:\n\n| C++ floating-point literal suffix | Carbon floating-point literal type |\n| --------------------------------- | ---------------------------------- |\n| (none)                            | `f64`                              |\n| `f` or `F`                        | `f32`                              |\n| `l` or `L`                        | `Cpp.long_double`                  |\n| `f16` or `F16` (since C++23)      | `f16`                              |\n| `f32` or `F32` (since C++23)      | TBD                                |\n| `f64` or `F64` (since C++23)      | TBD                                |\n| `f128` or `F128` (since C++23)    | `f128`                             |\n| `bf16` or `BF16` (since C++23)    | TBD                                |\n\n## Future work\n\n### More robust hexadecimal and binary literals in Carbon\n\nWe may want to use C++ standard rules for Carbon's hexadecimal and binary\nliterals, per the\n[alternative below](#use-the-c-standard-rules-for-hexadecimal-and-binary-literals).\nHowever, that requires addressing how that should be handled in the integer\nliteral space; for example, either adding more information to `Core.IntLiteral`\nor a new type, as well as addressing what kind of type is produced when\nperforming arithmetic on mixed literal types. That may be desirable, but\naddressing it here would substantially increase the scope of this proposal.\n\n## Rationale\n\nThis work will contribute to Carbon’s goal for seamless interoperability with\nC++\n([Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)),\nby keeping the consistency with the existing C++ usage.\n\n## Alternatives considered\n\n### Carbon to C++ type mapping\n\n#### Use the C++ standard rules for hexadecimal and binary literals\n\nFor example, when dealing with `0xFFFF_FFFF`, we could make that be interpreted\nas `unsigned` instead of `long`. This will be discernible in cases of overload\nresolution and type deduction.\n\nFor example:\n\n```cpp\nimport Cpp inline '''\nvoid f(unsigned);\n\nvoid g(unsigned);\nvoid g(long);\n\ntemplate<typename T> void h(T);\n''';\n\nfn CallF() {\n  // OK in both Carbon and C++.\n  // We select the f(unsigned) overload, and can call it.\n  Cpp.f(0xFFFF_FFFF);\n}\n\nfn CallG() {\n  // Would call g(unsigned) in C++.\n  // Calls g(long) in Carbon.\n  Cpp.g(0xFFFF_FFFF);\n}\n\nfn CallH() {\n  // Would call h<unsigned> in C++.\n  // Calls h<long> in Carbon.\n  Cpp.h(0xFFFF_FFFF);\n}\n```\n\nAdvantages:\n\n-   This would allow using the unsigned types for the cases where it’s important\n    (for example bit manipulation). This affects understandability for\n    interactions on interop boundaries, where developers might reasonably expect\n    that `0xFFFF_FFFF` would behave identically in Carbon and C++.\n\nDisadvantages:\n\n-   The current integer literal design doesn't support this distinction.\n-   These cases seem to be less often used than the decimal literals.\n\nThis decision is probably good enough for now, although we should consider it\nfor [future work](#more-robust-hexadecimal-and-binary-literals-in-carbon).\n\n#### Use the Clang way of determining the type\n\nAs described in [background](#clang), we could use the biggest unsigned integer\ntype currently supported for C++ (`unsigned __int128`) if the value doesn’t fit\nto `int`, `long`, or `long long`.\n\nAdvantages:\n\n-   This will match the C++ calls for the users that use Clang.\n\nDisadvantages:\n\n-   Using `__int128` gives a consistently signed type interpretation regardless\n    of bit width. This is also consistent to how we plan to require an explicit\n    `unsigned` conversion.\n\nIt's not clear how much this issue would arise, so we believe a consistent\nsigned type interpretation is a good default.\n\n### C++ to Carbon type mapping\n\n#### Use Carbon literal types\n\nIn other words, import a literal to a Carbon literal type; `Core.IntLiteral` or\n`Core.FloatLiteral`.\n\nAdvantages:\n\n-   This would allow determining the type later according to the Carbon rules.\n\nDisadvantages:\n\n-   This may not be always feasible. For example, sometimes a variable or\n    constant needs to be initialized with the value of the literal.\n\nRather than trying to detect feasibility, we are choosing to assign a sized\nnumeric type.\n"
  },
  {
    "path": "proposals/p6676.md",
    "content": "# Carbon/C++ Interop: Importing C/C++ object-like macros\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6676)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n    -   [Macros in C++](#macros-in-c)\n        -   [Object-like macros](#object-like-macros)\n        -   [Function-like macros](#function-like-macros)\n        -   [Predefined macros](#predefined-macros)\n    -   [Swift / C interop [GitHub][documentation]](#swift--c-interop-githubdocumentation)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Namespace](#namespace)\n    -   [Constant type](#constant-type)\n    -   [Constant value](#constant-value)\n    -   [Constant expressions](#constant-expressions)\n    -   [Empty macros](#empty-macros)\n    -   [Implementation](#implementation)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n-   [Open questions](#open-questions)\n    -   [Object-like macros](#object-like-macros-1)\n    -   [Function-like macros](#function-like-macros-1)\n    -   [Predefined macros](#predefined-macros-1)\n\n<!-- tocstop -->\n\n## Abstract\n\nThis proposal addresses importing object-like C/C++ macros into Carbon.\n\n## Problem\n\nC/C++ object-like macros are used to define constants, conditional compilation,\nheader guards, etc. and are common for low-level, cross-platform libraries, with\nC like APIs. Despite the recommendations for replacing them in C++ with safer\ntechniques (for example `constexpr`), they remain to be present in C++ code\nbases. Of particular interest for the interoperability are cases such as macros\npresent in the APIs of the standard C++ library (for example error codes in\n`<errno.h>`), which can't be easily changed, but remain to be widely used in\nlow-level C++ libraries. A mechanism for properly importing and handling these\nmacros is necessary for a seamless interoperability.\n\n## Background\n\n### Macros in C++\n\nMacros are defined with the `#define` directive and processed by the\npreprocessor, which replaces the occurrences of the defined identifier with a\nreplacement-list. There are two types of macros: _object-like_ and\n_function-like_ macros. The directive `#undef` undefines a defined macro.\n\n#### Object-like macros\n\n```\n#define identifier replacement-list (optional)\n```\n\nReplacement-lists can have elements that are:\n\n-   Literals: integer, floating-point, string, char, bool etc.\n-   Non-literal types: structs, classes etc.\n-   Identifiers: pointing to other macros, variables, types, keywords etc.\n-   Operators: `+, -, <<, >>, |` etc. with one or more operands.\n\n#### Function-like macros\n\n```\n#define identifier(parameters) replacement-list (optional)\n#define identifier(parameters, ...) replacement-list (optional)\n#define identifier(...) replacement-list (optional)\n```\n\nThe syntax of function-like macros is similar to the syntax of a function call.\nThey accept a list of arguments and replace their occurrence in the\nreplacement-list.\n\nAs this is only a text replacement, it can lead to unexpected behaviour if the\narguments are not properly separated with brackets.\n\nIn function-like macros, the operators `#` and `##` enable:\n\n-   `#operator (stringification)` - the arguments of the macro are converted to\n    a string literal without expanding the argument. When `#` is used in front\n    of a parameter in a macro definition (`#param`), the preprocessor replaces\n    `#param` with the argument tokens as a string literal.\n\n-   `##operator (concatenation or token pasting)` - two tokens are merged in a\n    single token during a macro expansion. For example, when `a##b` is used as\n    part of the macro definition, the preprocessor merges `a` and `b`, removing\n    any white spaces in between to form a single token. When some of the tokens\n    on either side of the `##` operator are parameter names, they are replaced\n    by the actual argument before the execution of `##`. This is used for\n    example to create new identifiers like variables, function names etc. and in\n    general to avoid creating repeated boilerplate code.\n\n#### Predefined macros\n\nThere are also predefined macros available in every translation unit. Examples\ninclude: `__cplusplus`, `__FILE__`, `__LINE__`, `__DATE__`, `__TIME__` etc.\n\n### Swift / C interop [[GitHub](https://github.com/swiftlang/swift/blob/main/lib/ClangImporter/ImportMacro.cpp)][[documentation](https://developer.apple.com/documentation/swift/using-imported-c-macros-in-swift)]\n\nSwift supports importing object-like C macros as global constants. Macros that\nuse integer, floating-point and string literals are supported. Also simple\noperators like `+, -, <<, >>` etc. between literals or macros are supported.\n\nFunction-like macros are not supported. Instead, using Swift functions and\ngenerics is recommended.\n\n## Proposal\n\nAn object-like macro that evaluates to a constant expression is imported from\nC++ as a constant in Carbon. For example:\n\nC++:\n\n```\n#define BUFFER_SIZE 4096\n```\n\nCarbon:\n\n```\nlet a: i32 = Cpp.BUFFER_SIZE; // Cpp.BUFFER_SIZE is imported as an int value of type i32 with a value of 4096\n\n```\n\n## Details\n\n### Namespace\n\nThe macro is evaluated in the global Cpp namespace and accessible as\nCpp.BUFFER_SIZE.\n\n### Constant type\n\nThe type of the imported constant is deduced by Clang by evaluating the constant\nexpression and then mapped to a Carbon type following the existing\n[Carbon <-> C++ type mapping rules](https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p5448.md).\n\n### Constant value\n\nThe value is deduced by evaluating the tokens of a replacement list as a\nconstant expression.\n\n### Constant expressions\n\nThe replacement list in the object-like macro expanding to a constant expression\ncan contain:\n\n-   **Operators**: arithmetic: `+, -, *, /`; bitwise: `|, &, ^, <<, >>` ;\n    logical: `||, &&`; comparison: `<, >, <=, >=, ==`; casts etc, with arbitrary\n    number of operands.\n\nFor example:\n\n```\n#define ADDITION 1+2+3\n```\n\n-   **Chained macros**: macros that expand to another macro which evaluates to a\n    constant.\n\nFor example:\n\n```\n#define VALUE 123\n#define MY_VALUE VALUE\n```\n\n-   **Enum constants and `constexpr` variables**: if a macro's replacement list\n    refers to a named constant, such as an enum constant or a `constexpr`\n    variable, it is imported as an alias rather than as a literal value. This\n    allows Carbon to preserve the specific type of the constant (such as `Color`\n    in the example below). In the case of `constexpr` variables, importing as an\n    alias also preserves addressability (that the constant is an lvalue), which\n    would be lost if only the value were imported.\n\nFor example:\n\nC++:\n\n```\nenum class Color { Red = 1, Green = 2 };\n#define GREEN_COLOR Color::Green\n\nconstexpr int kValue = 123;\n#define VALUE kValue\n```\n\nCarbon:\n\n```\n// Cpp.GREEN_COLOR is an alias to Cpp.Color.Green which has a type Cpp.Color.\nlet b: Cpp.Color = Cpp.GREEN_COLOR;\n\n// Cpp.VALUE is an alias to kValue.\nlet a: i32 = Cpp.VALUE;\n```\n\nThe macro will be evaluated by default in the global namespace (for example\n`Cpp.VALUE`). Evaluating it in a child namespace (`Cpp.SomeNamespace.VALUE`) may\nalso be possible, though details about that are outside of the scope of this\nproposal.\n\n### Empty macros\n\nThe macro should have at least one value in the replacement-list so that it’s\nimported. For example, the following macro won’t have a Carbon equivalent:\n\n```\n#define EMPTY\n```\n\n### Implementation\n\n1. _Name lookup_: When a C++ macro name is encountered in Carbon it is looked-up\n   before any other name. Following the C++ rules, this allows the macro to be\n   found in case there is a non-macro with the same name (for example named\n   variable).\n\n2. _Macro import_: If a macro is found, it is imported as a constant to Carbon,\n   by parsing the tokens of the replacement list to a constant expression and\n   evaluating the result.\n\nFor example, given a macro:\n\n```\n#define MY_MACRO <some tokens>\n```\n\nThe following constexpr will be (effectively) generated and imported:\n\n```\nconstexpr inline decltype(auto) __carbon_import_MY_MACRO = (MY_MACRO);\n```\n\nThat is, we would try to generate such a `constexpr` and import the macro if\nthat succeeds.\n\n## Rationale\n\nThis work contributes to the Carbon’s goal for seamless interoperability with\nC++\n([Interoperability with and migration from existing C++ code](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)),\nby enabling reusing and migrating existing macros, while adhering to the best\npractices to use constant variables.\n\n## Alternatives considered\n\n-   Implementation\n\n    a) Reuse Swift/C implementation\n\n    -   _Reason to do this_: use existing implementation.\n    -   _Reason not to do this_: this implementation is much more limited,\n        longer and harder to maintain than the proposed one, as it manually\n        scans the replacement tokens and tries to evaluate them, instead of\n        using Clang for that. Limitations include for example type of supported\n        operators, number and type of operands etc. Also, due to the licensing,\n        it is not directly available.\n\n    b) Manually scanning tokens (own implementation)\n\n    -   _Reason not to do this_: this is a much longer implementation compared\n        to the proposed one, with much more limitations compared to using Clang\n        to do that.\n\n-   Importing macros that refer to enum constants and `constexpr` variables as\n    constant values, instead of aliases in Carbon\n    -   _Reason to do this_: This would be a simpler implementation and\n        consistent with how other object-like macros are imported.\n    -   _Reason not to do this_: This would not preserve the enum's type (for\n        example, `Color::Green` would be imported as an integer literal `2`\n        instead of as a constant of type `Color`) or the addressability of\n        `constexpr` variables (which are lvalues).\n\n## Open questions\n\n### Object-like macros\n\nThe support for the following cases still needs to be clarified:\n\n-   non-constant variable name\n\n```\nint x;\n#define VAL x\n```\n\n-   types:\n\n```\n#define SHORT_TYPE short\n```\n\n-   Statements or keywords:\n\n```\n#define RET return\n#define FOREVER for(;;)\n```\n\n-   Expanding macros in child namespaces (`Cpp.SubNamespace.MACRO`)\n\n### Function-like macros\n\nThe support for function-like macros will still need to be discussed in detail.\nThe current proposal could be extended for function-like macros in the following\ndirection:\n\nGiven a function-like macro:\n\n```\n#define MY_MACRO(a, b) ((a) + (b))\n```\n\nA function template whose body invokes the macro could be (eventually) generated\nand imported:\n\n```\nconstexpr decltype(auto) __carbon_import_MY_MACRO(auto a, auto b) {\n  return (MY_MACRO(a, b));\n}\n```\n\n### Predefined macros\n\nDetails on the support for predefined macros remains open as well.\n"
  },
  {
    "path": "proposals/p6699.md",
    "content": "# Diagnostic sorting\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6699)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Don't sort diagnostics](#dont-sort-diagnostics)\n    -   [Sort by line and column](#sort-by-line-and-column)\n    -   [Sort by last processed token](#sort-by-last-processed-token)\n\n<!-- tocstop -->\n\n## Abstract\n\nChange `SortingConsumer` from sorting by last processed token (per-phase) to\nadditionally allow diagnostics to request sorting by start position (line and\ncolumn) when the last processed token is the same.\n\n## Problem\n\nDiagnostics in many toolchains are emitted in the order they are discovered\nduring code traversal. While this naturally reflects the causal relationship\nbetween errors (for example, an error in a macro expansion causing subsequent\nparse errors), it can lead to a confusing experience for developers if the\ndiagnostics jump back and forth through the file. Conversely, sorting purely by\nsource location (line and column) can break causality, presenting a consequence\nbefore its cause. We need a sorting strategy that feels natural to humans but\nrespects the underlying toolchain logic.\n\n## Background\n\nCarbon's processing of code in stages (lex, parse, check) causes diagnostics to\nbe produced in that order. In contrast, Clang interleaves parse and check, and\nas a consequence the diagnostics produced are similarly interleaved.\n\nA more detailed overview of Carbon's diagnostic infrastructure can be found in\n[diagnostics.md](/toolchain/docs/diagnostics.md).\n\n## Proposal\n\nIn addition to sorting by the last processed token (which `SortingConsumer`\nalready does), add a way to sort based on the start position (line and column)\nby request. This is being called \"on-scope\" because current cases we've\ndiscussed are scope-related.\n\nSee [SortingConsumer](/toolchain/docs/diagnostics.md#sortingconsumer) for more\ndocumentation.\n\n## Details\n\nThis was already implemented in\n[PR #6687](https://github.com/carbon-language/carbon-lang/pull/6687).\n\n## Rationale\n\nThis proposal advances Carbon's goal of providing\n[Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\nand creating\n[Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\nby making the developer experience with error messages more predictable and\nlogical. It respects the inherent causal order of the toolchain while tailoring\nthe output to human expectations.\n\n## Alternatives considered\n\n### Don't sort diagnostics\n\nWe could just print diagnostics in the order they are produced. This would print\nall lex errors, then all parse errors, then all check errors. This would be\nsimple, but might be confusing when a parse error at the end of a file comes\nbefore check errors, and fixing the check errors would fix the parse error.\n\n### Sort by line and column\n\nWe could sort diagnostics purely by their line and column. This runs into issues\nwith cases such as:\n\n```carbon\nfn F(x: i32, y: i32);\n\nfn G() {\n  F(1 2);\n}\n```\n\nHere, the diagnostic for an invalid parse of `1 2` would appear after the\ndiagnostic that `F` expects two arguments, not one. This is confusing because\nthe missing comma is the root cause of the incorrect argument count.\n\n### Sort by last processed token\n\nWe could sort diagnostics purely by the last token that was processed when the\ndiagnostic was emitted. This runs into issues with cases such as:\n\n```carbon\nfn F(x: i32, y: i32) {}\n```\n\nHere, both `x` and `y` would be diagnosed as unused at the `}`. The order would\nbe non-deterministic, hindering golden tests.\n\nThis could be partially addressed by sorting the diagnostics locally (for\nexample, sorting each `unused` diagnostic together), but this is an incomplete\nsolution because we may introduce further scope-related checks, particularly\nflow checking (for example, checking if there are provable out-of-bounds\naccesses). These would all have the same last processed tokens. It also would\nlikely lead to sorting regardless of whether sorting was requested by the tool\nuser, a performance overhead we want to avoid.\n\nWe believe sorting by the last processed token is a partial solution, which\nwe're building on.\n"
  },
  {
    "path": "proposals/p6710.md",
    "content": "# `char` redesign\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6710)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n    -   [Add a `char` type literal](#add-a-char-type-literal)\n        -   [Escape sequences](#escape-sequences)\n    -   [Add a `Core.CharLiteral` type for character literals](#add-a-corecharliteral-type-for-character-literals)\n    -   [Operators](#operators)\n        -   [Conversion operators](#conversion-operators)\n        -   [Comparison operators](#comparison-operators)\n        -   [Arithmetic operators](#arithmetic-operators)\n            -   [`char` integer parameters](#char-integer-parameters)\n            -   [Overflow semantics](#overflow-semantics)\n            -   [Preferring i32 returns](#preferring-i32-returns)\n    -   [Revoke and replace proposal #1964: Character Literals](#revoke-and-replace-proposal-1964-character-literals)\n-   [Rationale](#rationale)\n-   [Future work](#future-work)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Align `char` fully with C++, or make it fully valid](#align-char-fully-with-c-or-make-it-fully-valid)\n    -   [Raw character literals](#raw-character-literals)\n    -   [Disallow hex escape sequences in character literals](#disallow-hex-escape-sequences-in-character-literals)\n    -   [Allow grapheme clusters in character literals](#allow-grapheme-clusters-in-character-literals)\n    -   [Reuse string literal syntax for character literals](#reuse-string-literal-syntax-for-character-literals)\n        -   [Treat single-character string literals as a third \"text literal\" type](#treat-single-character-string-literals-as-a-third-text-literal-type)\n\n<!-- tocstop -->\n\n## Abstract\n\n-   Add a `char` type literal mapping to `Core.Char` and equivalent to C++'s\n    `char`.\n    -   8 bits, unsigned, treated as a single UTF-8\n        [code unit](https://en.wikipedia.org/wiki/Character_encoding#Code_unit).\n-   Add a `Core.CharLiteral` type for character literals, similar to\n    `Core.IntLiteral`.\n-   Allow operations for `char` and `Core.CharLiteral` which reinforce the\n    \"character\" concept, versus an integer value.\n-   Revokes and replaces\n    [#1964: Character Literals](https://github.com/carbon-language/carbon-lang/pull/1964).\n\n## Problem\n\n`char` is an important type due to its common use in C++ code. However, the\nrelated proposal\n[#1964: Character Literals](https://github.com/carbon-language/carbon-lang/pull/1964)\nhas several issues, including:\n\n-   Lacks a decision for `char` handling; it is not mentioned in proposal #1964.\n    -   Similarly, decides there are character literals, but more detail is\n        needed for implementation.\n-   Type literal naming no longer reflects naming consensus.\n    -   `Char8` seems potentially more equivalent to `std::char8_t` instead of\n        `char`, and for interop purposes these are slightly different types.\n        Similar applies to `Char16` and `Char32`.\n    -   As a design direction, we have been lowercasing type literals (such as\n        `u8`).\n-   Conflicting statements about behavior.\n    -   For example, \"Rationale\" states that `var b: u8 = 'a' + 1` would be\n        supported, while \"Operations\" states that `+` is returning a character\n        literal (not a `u8`).\n    -   For character literals, states \"Escape sequences which would result in\n        non-UTF-8 encodings or more than one code point are not included.\"\n        However, it goes on to say that `let smiley: Char16 = '\\u{1F600}'` is\n        valid even though `1F600` would require multiple code units in both\n        UTF-8 and UTF-16.\n-   Unclear that it gives us a good UTF plan.\n    -   Does not decide what a single character in a Carbon string is.\n    -   No consideration regarding interop with the `std::char32_t` family of\n        types or [ICU](https://github.com/unicode-org/icu) compatibility.\n\nIn other words, it's likely we want something similar to `Char32`, but it may be\nnamed something like `Core.Char32` and have slightly different type behaviors\nthan decided in #1964. On the other hand, we need something compatible with the\nC++ `char` in order to proceed with basic C++ interop, and #1964 doesn't provide\nthat.\n\n## Background\n\n-   [Proposal #1964: Character Literals](https://github.com/carbon-language/carbon-lang/pull/1964)\n    is fundamental, and a lot of the underlying thoughts still apply. In\n    particular, we still want character types to be distinct from numeric types.\n-   [Proposal #199: String literals](https://github.com/carbon-language/carbon-lang/pull/199)\n    is important because we want character and string literals to have mirrored\n    escaping concepts.\n-   [Proposal #5448: Carbon &lt;-> C++ Interop: Primitive Types](https://github.com/carbon-language/carbon-lang/pull/5448)\n    left the question of character type mappings open. This proposal aims to\n    answer it for `char`.\n-   [Issue #5903: Built-in character type questions](https://github.com/carbon-language/carbon-lang/issues/5903)\n    addressed type questions.\n-   [Issue #5922: Built-in character operators](https://github.com/carbon-language/carbon-lang/issues/5922)\n    addressed operators.\n\n## Proposal\n\nThe way `char` will work is:\n\n-   Add a `char` type literal.\n    -   Carbon's `str` type will use `char` for elements.\n    -   For interop, map Carbon's `char` to C++'s `char`.\n-   Add a `Core.CharLiteral` type for character literals, similar to\n    `Core.IntLiteral`.\n-   Provide operators which are consistent with the character concept.\n\nThis proposal additionally revokes and replaces proposal #1964, rather than\ntrying to define which parts we are keeping and which are changing.\n\n## Details\n\n### Add a `char` type literal\n\n`char` is intended to offer a basic construct for Carbon's strings that is both\ncompatible with UTF-8, and has high fidelity with C++ strings.\n\nIn support of that, important notes are:\n\n-   `char` itself will be a\n    [type literal](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/lexical_conventions/words.md#type-literals).\n-   `char` notionally represents a UTF-8 code unit.\n    -   It can contain invalid code units, as long as it remains 8 bits. We do\n        not assume runtime validation.\n-   `char` will be backed by `Core.Char`, in the prelude.\n    -   `Core.Char` will adapt `u8`.\n-   C++ interoperability will transparently map `char` and `Cpp.char` on API\n    boundaries.\n    -   When used with Carbon, C++ `char` will be unsigned by default\n        (`-funsigned-char`). A program can switch back to signed\n        (`-fno-unsigned-char`), and Carbon will maintain interoperability but\n        bits will be interpreted differently in each language.\n\n#### Escape sequences\n\nEscape sequences are the same as for a string literal. Only one escape sequence\nmay be provided in a character literal.\n\n### Add a `Core.CharLiteral` type for character literals\n\n`Core.CharLiteral` is the type of a character literal, similar to how\n`Core.IntLiteral` is the type of integer literals. It abstractly represents a\nsingle Unicode code point. This gives us a compile-time structure for characters\nthat can be typed and referred to in programs.\n\nSemantics of a character literal will be equivalent to a\n[simple string literal](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/lexical_conventions/string_literals.md#simple-and-block-string-literals),\nexcept that:\n\n-   A character literal has a validated Unicode code point value.\n-   The enclosing character is `'`.\n-   The contents are precisely one character or escape sequence.\n    -   The `\\x` escape sequence is limited to values up to `7F`, where the\n        UTF-8 code unit and Unicode code point values are identical.\n\nAn important detail of the character literal type is it gives us a way to track\nconstant values at compile time. For example, `'a' + 1` has a constant value of\n`b`. This means we can diagnose uses of character literals that don't represent\na valid Unicode code point, such as `'a' + 0xFFFFFF`.\n\n### Operators\n\nThe goal of provided operators is to provide a set of operators which map to\ncommon operations a user would want to do. It is a non-goal to support use of\n`char` as an arbitrary byte or integer: developers should use `u8` for that.\n\nIn general, `char` and `Core.CharLiteral` operators are intended to be mirrors\nof each other.\n\n#### Conversion operators\n\n-   `char`\n    -   `ImplicitAs`: None\n    -   `ExplicitAs`: To/from `u8`, plus the set of `ImplicitAs` for `u8`.\n        -   For example, `u8` has `ImplicitAs` to `u16`, so `char` has\n            `ExplicitAs` to `u16`.\n-   `Core.CharLiteral`\n    -   `ImplicitAs`: to `char` only\n    -   `ExplicitAs`: To/from the set of `ImplicitAs` for `i32` and `u32`.\n        -   For example, `i32` has `ImplicitAs` to `i64`, so `Core.CharLiteral`\n            has `ExplicitAs` to `i64`.\n        -   For example, `i64` does not have `ImplicitAs` to `i32`; conversion\n            requires two casts, `((i64_val as i32) as Core.CharLiteral)`.\n\nCasting from a `char` to a `Core.CharLiteral` is not supported.\n\nSee also\n[implicit numeric conversions](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/implicit_conversions.md#data-types).\n\n#### Comparison operators\n\n-   `char`\n    -   `EqWith` and `OrderedWith` when both operands are `char`.\n    -   `ImplicitAs` should allow substituting one operand with\n        `Core.CharLiteral`.\n-   `Core.CharLiteral`\n    -   `EqWith` and `OrderedWith` when operands are `Core.CharLiteral`.\n\n#### Arithmetic operators\n\n-   `char`\n    -   `AddWith`: `char + &lt;integer> -> char` (with reversible operands)\n        -   Equivalent to `(((char as i16) + &lt;integer>) as u8) as char)`\n    -   `SubWith`:\n        -   `char - &lt;integer> -> char` (non-reversible operands)\n            -   Equivalent to `(((char as i16) - &lt;integer>) as u8) as char)`\n        -   `char - char -> i32`\n            -   Equivalent to `(lhs as i32) - (rhs as i32)`.\n            -   `ImplicitAs` should allow substituting one operand with\n                `Core.CharLiteral`.\n-   `Core.CharLiteral`\n    -   `AddWith`: `Core.CharLiteral + &lt;integer> -> Core.CharLiteral` (with\n        reversible operands)\n    -   `SubWith`:\n        -   `Core.CharLiteral - &lt;integer> -> Core.CharLiteral`\n            (non-reversible operands)\n        -   `Core.CharLiteral - Core.CharLiteral -> i32`\n            -   Provides a unicode code point delta.\n\n##### `char` integer parameters\n\nArbitrary integers are supported for most of these operations. For example, we\nwant to allow addition of negative numbers, even though the representation of\n`char` is unsigned, without requiring additional casts.\n\n##### Overflow semantics\n\nOperations will use error overflow semantics,\n[similar to signed integers](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/expressions/arithmetic.md#overflow-and-other-error-conditions).\nFor example, `(('a' as char) + 500)` is invalid code because it causes `char`\noverflow. That's why conversions are to signed values (for example,\n`char as i16`).\n\n##### Preferring i32 returns\n\nIn arithmetic, `i32` returns are preferred for deltas because they should be\nvalid for unicode code points. Even though `char` is only 8-bits, using `i32`\nfor returns there too creates consistency with `Core.CharLiteral`.\n\n### Revoke and replace proposal #1964: Character Literals\n\nThis revokes proposal #1964 for simplicity. Rather than trying to detail which\ndecisions still apply and which don't, this proposal is acting from an\nassumption that all decisions there no longer apply. We can still benefit by\npointing towards the rationale in explicitly maintaining decisions, but we want\nto go through that step.\n\n## Rationale\n\n-   [Performance-critical software](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#performance-critical-software)\n    -   The intent is that Carbon's main string type privileges UTF-8 over other\n        potential encodings. A `char` represents a single code unit within that,\n        and is consequently efficient to access. It can also be invalid, meaning\n        we don't guarantee performing runtime validation for users (avoiding\n        performance overhead), and that users might be able to use it for other\n        encodings.\n-   [Software and language evolution](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#software-and-language-evolution)\n    -   `Core.CharLiteral` is designed as a Unicode code point, and even though\n        this design doesn't include a way to use values over `7F`, we anticipate\n        those will be added in the future. It's being provided as a building\n        block for more elaborate Unicode functionality, including both UTF-16\n        and UTF-32, even as we prioritize UTF-8.\n-   [Code that is easy to read, understand, and write](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n    -   Character literal syntax mirrors string literal syntax. The main\n        divergence is `\\x80` and higher similar escapes, which are not supported\n        due to potentially ambiguous behavior, still in furtherance of this\n        goal.\n-   [Practical safety and testing mechanisms](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n    -   Restricting the set of operators valid for `char` gives us a way to do\n        different sorts of validation that can be more character-oriented than\n        if we treated it as an arbitrary byte.\n    -   Treating `Core.CharLiteral` as a valid Unicode character allows us to\n        provide static checking for some operations, such as `'a' + 1` resulting\n        in another valid Unicode code point; more is also transitively possible,\n        including involving `char`.\n-   [Interoperability with and migration from existing C++ code](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n    -   Modeling `char` as a UTF-8 code unit creates behavior which is very\n        similar to C++, but still shifts towards a more character-oriented\n        approach. We do expect some migration friction as a consequence (as\n        use-cases might need either more casts, or to switch to a byte type).\n\n## Future work\n\nThere's still significant future work, including:\n\n-   `signed char`, `unsigned char`\n-   `std::char8_t`, `std::char16_t`, `std::char32_t`\n-   UTF-16 and UTF-32 support\n\nIt should not be assumed that there's any restriction on the designs of those\nfeatures, particularly no restrictions from #1964.\n\n## Alternatives considered\n\n### Align `char` fully with C++, or make it fully valid\n\nAlternatives were discussed in\n[zygoloid's comment on #5903](https://github.com/carbon-language/carbon-lang/issues/5903#issuecomment-3494068591).\n\nThe comment notes that three options were proposed:\n\n1. `char` is fully aligned with C++.\n\n    There is no universal convention for what the value in a `char` means, and\n    the numerical encoding of Unicode characters into `char` sequences might\n    even be platform-dependent. For example, we might use some code page on\n    Windows, EBCDIC on some IBM targets, and probably UTF-8 everywhere else.\n    Likely the encoding would match what a character literal in C++ code would\n    do for that target. Even when the target normally uses UTF-8, it would be\n    reasonable to use an array of `char` as the type of the output buffer when\n    transcoding from UTF-8 to some other encoding, and generally an encoded text\n    buffer (in any encoding) would typically be represented as an array of\n    `char`. It might also be reasonable to use an array of `char` for things\n    that aren't necessarily text, such as file contents.\n\n2. `char` models a UTF-8 code unit, although it may not necessarily be valid,\n   and may appear in a sequence that is not a valid UTF-8 encoding.\n\n    As with the first option, `char` can represent an integer in [0, 255], although\n    it is not an integer type. Higher-level abstractions would likely (eventually)\n    be provided to represent different views of the code unit sequence as (for example)\n    a sequence of code points or a sequence of graphemes, but the fundamental model\n    exposes the encoding. Functions taking `char` or `char` sequences would assume\n    UTF-8 encoding, and would need to consider how to handle invalid `char`s and\n    invalid `char` sequences.\n\n3. Use a foundation that enforces Unicode string validity, for some definition\n   of \"Unicode string validity\".\n\n    The `char` type is a Unicode character. Strings would notionally be a\n    sequence of Unicode characters, possibly also maintaining some higher-level\n    string invariants. String indexing, if it exists, would likely treat the\n    string as a sequence of Unicode characters. String invariants would be\n    enforced by type conversion into the string type rather than within the\n    string operations, and certain classes of invalid strings would be\n    unrepresentable.\n\nRationale as evaluated are:\n\n-   **Privilege UTF-8 over other encodings:** UTF-8 is\n    [typically the best choice](https://utf8everywhere.org/) for representing\n    text, even when targeting languages where characters are 3 bytes in UTF-8\n    but 2 in UTF-16, and even on Windows where the system APIs typically operate\n    primarily in UTF-16 or UCS-2. We should create affordances that encourage\n    use of UTF-8 (such as having the `char` type be conventionally UTF-8).\n    -   Our overall goal to support (only) modern environments and a general\n        desire for consistency and portability argues against supporting\n        non-Unicode encodings for character types.\n    -   Having _some_ convention for the meaning of the value of a `char` seems\n        important, and the lack of one in C++ has been a notable problem over\n        time, leading to the addition of `char8_t` et al, which have not been\n        entirely satisfactory solutions due to the existing widespread usage of\n        plain `char`.\n-   **Do not privilege any particular meaning of \"validity\":** There are many\n    different ways in which you can view a sequence of UTF-8 code units as being\n    valid or invalid. For example: Can a string start with a combining\n    character? Can it have mismatched LRE/RLE/PDF characters in it? Can it be\n    unnormalized, or must it be in NFC, or in NFD? Can it contain unassigned\n    Unicode characters? Can it contain PUA characters? Can it contain\n    non-characters? Picking any set of answers to these questions as being our\n    canonical notion of \"validity\" is somewhat arbitrary.\n-   **Do not privilege any particular level for accessing elements of the string\n    other than code units:** There are many different layers of abstraction at\n    which you can interpret the contents of a string. The atoms that users want\n    to interact with, such as glyphs or grapheme clusters in rendering, or\n    combining characters when editing or performing substring searches, aren't\n    in one-to-one correspondence with Unicode characters any more than they're\n    in one-to-one correspondence with UTF-8 code units. So it's not clear that\n    privileging Unicode-character-oriented access (or indeed any of the other\n    higher-level Unicode views) is appropriate. However, code units are in\n    direct correspondence with bytes of memory, which is directly relevant for\n    low-level operations, so there is a reason to provide direct access to\n    byte-level / code-unit-level operations.\n    -   If string indexing operates on Unicode characters, it would either be\n        non-constant-time or would require not storing strings as just a\n        sequence of UTF-8. Having a constant-time indexing operation on strings\n        seems very important (especially for interop and for meeting C++\n        developers where they are), even though a lot of the desired\n        functionality (perhaps all of it) can be provided with iterator- or\n        cursor-like machinery instead.\n-   **Enforcing validity is problematic for existing API structures:** Requiring\n    strings to be valid UTF-8 presents difficulties when moving text into or out\n    of other sources. For example, when reading text from a validly-encoded\n    UTF-8 file into a text buffer, one would need to deal with a read that ends\n    in the middle of an encoding of a character. I don't know how Rust deals\n    with this, but it seems like it would create significant impedance mismatch\n    with C-like buffered I/O utilities. Similarly, when interoperating with C++,\n    it would create friction if our string representation requires strings to be\n    valid UTF-8 encodings.\n-   **We can allow additional invariants without requiring them:** For a\n    known-to-be-valid UTF-8 sequence, a higher-level abstraction can be built,\n    and similarly, yet-higher-level abstractions can be built for whatever other\n    invariants we want to enforce. So using option 2 rather than option 3 as our\n    foundation doesn't prevent enforcing invariants in the type system (but nor\n    does it encourage doing so).\n\nThis proposal is choosing option 2, that `char` models a UTF-8 code unit without\nvalidation. In some sense, option 2 is still \"fully aligned with C++\", but with\nC++'s `char8_t` rather than with C++'s `char`.\n\n### Raw character literals\n\n[Raw string literals](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/lexical_conventions/string_literals.md#raw-string-literals)\nuse a `#` prefix. There's limited use for this in character literals;\ntechnically, `'\\\\'` could instead be `#'\\'#`, but that's longer and extra\ncharacters may prove distracting. Raw string literals are more useful when\nthere's a longer character sequence, whereas character literals have one\ncharacter by definition. For simplicity, character literals won't have raw\nsyntax.\n\n### Disallow hex escape sequences in character literals\n\nA `\\x##` escape sequence abstractly represents a UTF-8 code unit. Whereas values\nover 7F are valid in string literals (allowing arbitrary byte values), these are\ndisallowed in character literals because we want a more validated Unicode\nbehavior. Developers could instead rely on `\\u` escapes for `\\x`.\n\nIt can still be useful to allow `\\x` escapes for low-range values because some\ndevelopers will still need to specify\n[ANSI escapes](https://en.wikipedia.org/wiki/ANSI_escape_code). Carbon\n[drops support for some escape sequences](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/lexical_conventions/string_literals.md#escape-sequences),\nsuch as `\\a`, and specifically advises `\\x` as an alternative for developers\nthat need it. Requiring `\\a` -> `\\x07` -> `\\u{07}` is incrementally more verbose\nsyntax, and developers may be confused why `\"\\x1B\"` is allowed for strings but\n`'\\u{1B}'` is required for characters.\n\nValues over 7F are ambiguous between an arbitrary byte value and a Unicode code\npoint, and so should be invalid. However, where both interpretations are\nidentical for UTF-8 (values up to and including 7F), we will allow `\\x` escape\nsequences.\n\n### Allow grapheme clusters in character literals\n\nThis proposal carries forward the decision in #1964\n[to not support grapheme clusters](https://github.com/carbon-language/carbon-lang/pull/1964/files#diff-192d5568d8c1d15e68abe0c46cc52cc0b375a372d1dad8d2154d09f8b29666c5R340)\nin character literals.\n\n### Reuse string literal syntax for character literals\n\nInstead of using single quotes (for example, `'a'`), we could use string literal\nsyntax with a conversion (for example, `\"a\" as char`) for character literals.\nThis was proposed because it would free up the single quote for other,\nunspecified syntax uses.\n\nFor background, character literals are common in C++. For example, in\nSourceGraph search statistics (some of these are in comments -- a search\nlimitation):\n\n-   `'(.|\\\\.)'`:\n    [46.2 million](https://sourcegraph.com/search?q=context:global+lang:c%2B%2B+count:50000000+/%27%28.%7C%5C%5C.%29%27/&patternType=keyword&sm=0)\n-   `<<`:\n    [over 100 million](https://sourcegraph.com/search?q=context:global+lang:c%2B%2B+count:100000000+/+%3C%3C+/&patternType=keyword&sm=0)\n-   `>>`:\n    [10.4 million](https://sourcegraph.com/search?q=context:global+lang:c%2B%2B+count:50000000+/+%3E%3E+/&patternType=keyword&sm=0)\n-   `%`:\n    [5.3 million](https://sourcegraph.com/search?q=context:global+lang:c%2B%2B+count:10000000+/+%25+/&patternType=keyword&sm=0)\n\nThis creates several disadvantages for removing character literals in Carbon:\n\n-   **Migrating C++ developers to Carbon:** The frequency of use can be expected\n    to have trained developers to expect single quotes to be used for\n    characters, especially the C++ developers that Carbon is targeting.\n    Repurposing them would create a friction for C++ developers to need to\n    understand the different meanings of the same syntax in each of C++ and\n    Carbon, something Carbon prefers to avoid.\n\n-   **Increased runtime error risks:** Runtime errors could take the form of\n    simple increased overhead, such as converting a string literal to a `str`\n    then to a `char`. However, they could also be more insidious, such as doing\n    `[0]` on a string literal and not validating that the string is exactly one\n    character (this would also likely return a null byte for `\"\"[0]`). By having\n    a character literal type, Carbon encourages developers to stay within guide\n    rails that make it easier to get compile-time behavior and program\n    validation.\n\n-   **Block string literal use:** We already have another use for single quotes\n    in Carbon:\n    [block string literals](/docs/design/lexical_conventions/string_literals.md).\n    The syntax may need to change along with removing character literals, to\n    make room for other uses of single quotes.\n\n    -   If retained, it would constrain uses of single quotes. For example, a\n        unary operator syntax has overlap (that is, if `'a` and `''a` are valid,\n        then `'''a` is ambiguous).\n\n    -   The choice of single quotes in proposal\n        [#1360: Change raw string literal syntax](https://github.com/carbon-language/carbon-lang/pull/1360)\n        was made accounting for single quotes in character literals, and that\n        commonality would be lost.\n\n-   **Tooling:** The prevalence of single quotes being used for either strings\n    or characters also affects their treatment in tools not specialized to\n    Carbon: they expect them to be used for strings. For example, Rust's use of\n    single quotes for lifetime annotations has been observed to break\n    language-agnostic syntax highlighting.\n\nWhile a compelling proposal for a different use of single quotes may come up in\nthe future, freeing up the character for other purposes is insufficient to\njustify a different syntax for character literals.\n\n#### Treat single-character string literals as a third \"text literal\" type\n\nA related alternative with the same goal of eliminating single quotes for\ncharacter literals is that, rather than requiring single-character string\nliterals be explicitly converted to `char`, they could instead have a third type\nof text literal. This would implicitly cast to either `str` or `char`.\n\nThis approach would lead to three literal types: `StrLiteral`, `CharLiteral`,\nand `TextLiteral`. The distinction of `CharLiteral` is important because we\nstill want to support arithmetic on character literals, such as `'a' + 1` (which\nwe would not want to be allowed for `StrLiteral`).\n\nThe existence of a third type would be important for generic code, even when not\ntrying to use character literals. For example:\n\n```carbon\n  fn StoreValue[U:! type](ref a: Optional(U), b: U) {\n    a = b;\n  }\n\n  fn StrLogic[T:! type](a: T) {\n    var x: Optional(T) = a;\n    StoreValue(x, \"str\");\n  }\n\n  fn F() {\n    StrLogic(\"a\");\n  }\n```\n\nHere, `T` is deduced to be `TextLiteral`. However, `U` has no valid value: it's\npassed `Optional(TextLiteral)`, while `\"str\"` is a `StrLiteral` (which should\nnot be convertible to `TextLiteral`). As a consequence, this code is invalid,\neven though the same code would be valid if there were not `TextLiteral` type.\n\nAdvantages:\n\n-   Avoids an explicit cast.\n\nDisadvantages:\n\n-   Shares most of the disadvantages of the primary explicit conversion\n    approach.\n    -   This includes the risk that developers will write `\"...\"[0]` instead of\n        `\"...\" as char` when they need a character, although the frequency may\n        be reduced.\n-   Having additional types in common literals could lead to programmer errors\n    in deducing generic types, as described above.\n-   Implicit casts cause more operator ambiguity.\n    -   How are operators that have different meanings for string and character\n        literals handled, such as `Cpp.std.cout <<` or `<=>`?\n    -   In Carbon, we'd probably still want string operators to work; for\n        example, `\"a\" + \"b\" => \"ab\"`, and that can be compile-time. Is `\"a\" + 1`\n        a pointer to the null byte as it is in C++ (similar to `&(\"a\"[1])`), a\n        character addition (`'a' + 1 => 'b'`), or does it require an explicit\n        cast in order to ensure behavior is deliberate?\n"
  },
  {
    "path": "proposals/p6716.md",
    "content": "# Move toolchain alternatives to proposals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6716)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Proposal](#proposal)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [Lex](#lex)\n        -   [Bracket matching in parser](#bracket-matching-in-parser)\n    -   [Parse](#parse)\n        -   [Restrictive parsing](#restrictive-parsing)\n    -   [Check](#check)\n        -   [Using a traditional AST representation](#using-a-traditional-ast-representation)\n    -   [Coalescing generic functions emitted when lowering to LLVM IR](#coalescing-generic-functions-emitted-when-lowering-to-llvm-ir)\n        -   [Coalescing in the front-end vs back-end?](#coalescing-in-the-front-end-vs-back-end)\n        -   [When to do coalescing in the front-end?](#when-to-do-coalescing-in-the-front-end)\n        -   [Compile-time trade-offs](#compile-time-trade-offs)\n        -   [Coalescing duplicate non-specific functions](#coalescing-duplicate-non-specific-functions)\n\n<!-- tocstop -->\n\n## Abstract\n\nAs part of using the evolution process with the toolchain, alternatives should\nbe in proposals. This proposal migrates existing alternatives here.\n\n## Problem\n\nLeads want to use the evolution process with more of the toolchain changes.\nHistorically, alternatives were documented as part of the toolchain design, not\ngoing through evolution. Switching leaves those older alternatives in the\ntoolchain design, while putting newer alternatives in the proposals directory.\n\n## Proposal\n\nMove existing alternatives to this proposal. Future proposals will more\nnaturally have alternatives in the proposal document itself.\n\n## Rationale\n\nThis is in support of the\n[evolution process](/docs/project/goals.md#software-and-language-evolution),\naligning the toolchain documentation with design documentation.\n\n## Alternatives considered\n\n### Lex\n\n#### Bracket matching in parser\n\nBracket matching could have also been implemented in the parser, with some\nawareness of parse state. However, that would shift some of the complexity of\nrecovery in other error situations, such as where the parser searches for the\nnext comma in a list. That needs to skip over bracketed ranges. We don't think\nthe trade-offs would yield a net benefit, so any change in this direction would\nneed to show concrete improvement, for example better diagnostics for common\nissues.\n\n### Parse\n\n#### Restrictive parsing\n\nThe toolchain will often parse code that could theoretically be rejected,\ninstead allowing the check phase to reject incorrect structures.\n\nFor example, consider the code `abstract var x: i32 = 0;`. When parsing the\n`abstract` modifier, parse could do single-token lookahead to see `var`, and\nerror in the parse (`abstract var` is never valid). Instead, we save the\nmodifier and diagnose it during check.\n\nThe problem is that code isn't always this simple. Considering the above\nexample, there could be other modifiers, such as\n`abstract private returned var x: i32 = 0;`, so single-token lookahead isn't a\ngeneral solution. Some modifiers are also contextually valid; for example,\n`abstract fn` is only valid inside an `abstract class` scope. As a consequence,\na form of either arbitrary lookahead or additional context would be necessary in\nparse in order to reliably diagnose incorrect uses of `abstract`. In contrast\nwith parse, check will have that additional context.\n\nRejecting incorrect code during parsing can also have negative consequences for\ndiagnostics. The additional information that check has about semantics may\nproduce better diagnostics. Alternately, sometimes check will produce\ndiagnostics equivalent to what parse could, but with less work overall.\n\nAs a consequence, at times we will defer to the check phase to produce\ndiagnostics instead of trying to produce those same diagnostics during parse.\nSome examples of why we might diagnose in check instead of parse are:\n\n-   To issue better diagnostics based on semantic information.\n-   To diagnose similar invalid uses in one place, versus partly in check and\n    partly in parse.\n-   To support syntax highlighting for IDEs in near-correct code, still being\n    typed.\n\nSome examples of why we might diagnose in parse are:\n\n-   When it's important to distinguish between multiple possible syntaxes.\n-   When permitting the syntax would require more work than rejecting it.\n\nA few examples of parse designs to avoid are:\n\n-   Using arbitrary lookahead.\n    -   Looking ahead one or two tokens is okay. However, we should never have\n        arbitrary lookahead.\n    -   This includes approaches which would require using the mapping of\n        opening brackets to closing brackets that is produced by\n        `TokenizedBuffer`. Those are helpful for error recovery.\n-   Building complex context.\n    -   We want parsing to be faster and lighter weight than check.\n-   Duplicating diagnostics between parse and check.\n    -   When there are closely related invalid variants of syntax, only some of\n        which can be diagnosed during parse, consider diagnosing all variants\n        during check.\n\nThis is a balance. We don't want to unnecessarily shift costs from parse onto\ncheck, and we don't try to allow clearly invalid constructs. Parse still tries\nto produce a reasonable parse tree. However, parse leans more towards a\npermissive parse, and an error-free parse tree does not mean the code is\ngrammatically correct.\n\n### Check\n\n#### Using a traditional AST representation\n\nClang creates an AST as part of compilation. In Carbon, it's something we could\ndo as a step between parsing and checking, possibly replacing the SemIR. It's\nlikely that doing so would be simpler, amongst other possible trade-offs.\nHowever, we think the SemIR approach is going to yield higher performance,\nenough so that it's the chosen approach.\n\n### Coalescing generic functions emitted when lowering to LLVM IR\n\n#### Coalescing in the front-end vs back-end?\n\nAn alternative considered was not doing any coalescing in the front-end and\nrelying on LLVM to make the analysis and optimization. The current choice was\nmade based on the expectation that such an\n[LLVM pass](https://llvm.org/docs/MergeFunctions.html) would be more costly in\nterms of compile-time. The relative cost has not yet been evaluated.\n\n#### When to do coalescing in the front-end?\n\nThe analysis and coalescing could be done prior to lowering, after\nspecialization. The advantage of that choice would be avoiding to lower\nduplicate LLVM functions and then removing the duplicates. The disadvantage of\nthat choice would be duplicating much of the lowering logic, currently necessary\nto make the equivalence determination.\n\n#### Compile-time trade-offs\n\nNot doing any coalescing is also expected to increase the back-end codegen time\nmore than performing the analysis and deduplication. This can be evaluated in\npractice and the feature disabled if found to be too costly.\n\n#### Coalescing duplicate non-specific functions\n\nWe could coalesce duplicate functions in non-specific cases, similar to lld's\n[Identical Code Folding](https://lld.llvm.org/NewLLD.html#glossary) or LLVM's\n[MergeFunctions pass](https://llvm.org/docs/MergeFunctions.html). This would\nrequire fingerprinting all instructions in all functions, whereas specific\ncoalescing can focus on cases that only Carbon's front-end knows about. Carbon\nwould also be restricted to coalescing functions in a single compilation unit,\nwhich would require replacing function definitions that allow external calls\nwith a placeholder that calls the coalesced definition. We don't expect\nsufficient advantages over existing support.\n"
  },
  {
    "path": "proposals/p6910.md",
    "content": "# Support octal literals\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/6910)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Future work](#future-work)\n    -   [File permissions API](#file-permissions-api)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n    -   [No octal literals](#no-octal-literals)\n\n<!-- tocstop -->\n\n## Abstract\n\nSupport octal literals, mainly for migrating Unix file permissions. Reflects\nleads decision\n[#6821](https://github.com/carbon-language/carbon-lang/issues/6821).\n\n## Problem\n\nCarbon currently does not support octal numeric literals, because they're very\nrare, as previously decided in proposal\n[#143: Numeric literals](https://github.com/carbon-language/carbon-lang/pull/143).\nHowever, as part of interoperability with POSIX file system calls such as\n[`umask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/umask.html),\nwe want an easy way to express octal file permissions.\n\n## Background\n\nLeads discussed support of octal literals in issue\n[#6821: Support octal literals](https://github.com/carbon-language/carbon-lang/issues/6821).\n\nUnix file permissions written in octal are familiar to both programmers and\nnon-programmers who have experience administering Unix-like machines. For\nexample:\n\n-   `chmod OCTAL-MODE FILE...`\n-   [POSIX `mode_t` values](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html),\n    including the argument to\n    [`umask`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/umask.html).\n\nHowever, they are are not likely to be readable to those unfamiliar with them,\nnor are they very common in code. We also expect these to be the primary use of\noctal numeric literals in Carbon.\n\nGiven these issues, proposal #143\n[rejected octal literals](/proposals/p0143.md#octal-literals). Now, we're\ntesting interoperability of POSIX file system calls, and we are considering\noctal literals as a potential solution.\n\nProposal #143 [discussed the Carbon-style `0o` versus C++-style `0` prefix for\noctal literals. The same logic still applies, so we will not address it here.\n\n## Proposal\n\nIntroduce support for octal literals using the `0o` prefix (for example,\n`0o755`), followed by one or more octal digits (`0-7`). This provides a very\nsimple lexical space for octal numbers, mapping clearly from C++ and building\nconsistently off the existing `0x...` syntax for hexadecimal and `0b...` syntax\nfor binary.\n\n## Future work\n\n### File permissions API\n\nWe may still provide a file permissions API in Carbon, for example as part of a\n`Core` file system API. This proposal takes no stance on what that API should\nlook like. The only decision being made right now is that supporting octal\nliterals is worthwhile for interoperability and migration.\n\n## Rationale\n\nThis proposal effectively advances Carbon's goals by focusing on:\n\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code):\n    Providing a direct counterpart for C++ octal literals simplifies the\n    migration of Unix file system code without needing to wait for a better file\n    permission API.\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write):\n    The explicit `0o` prefix avoids the frequent confusion caused by C++'s\n    leading `0` syntax, while maintaining consistency with hex and binary\n    prefixes.\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution):\n    The `0o` octal literal syntax is consistent with other literals. We don't\n    expect it to hinder future language features.\n\n## Alternatives considered\n\n### No octal literals\n\nProposal #143 rejected octal literals. The main argument was that they are\nrarely used. However, the cost of octal literal syntax is low, and the benefit\nfor C++ interoperability and migration is enough that we should add them.\n"
  },
  {
    "path": "proposals/scripts/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@rules_python//python:defs.bzl\", \"py_binary\", \"py_test\")\n\npy_binary(\n    name = \"new_proposal\",\n    srcs = [\"new_proposal.py\"],\n    python_version = \"PY3\",\n)\n\npy_test(\n    name = \"new_proposal_test\",\n    size = \"small\",\n    srcs = [\"new_proposal_test.py\"],\n    data = [\"template.md\"],\n    python_version = \"PY3\",\n    deps = [\":new_proposal\"],\n)\n"
  },
  {
    "path": "proposals/scripts/README.md",
    "content": "# Scripts\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nScripts for use with proposals.\n\nSee individual scripts for more details.\n"
  },
  {
    "path": "proposals/scripts/__init__.py",
    "content": ""
  },
  {
    "path": "proposals/scripts/new_proposal.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Prepares a new proposal file and PR.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport argparse\nimport os\nimport re\nimport shlex\nimport shutil\nimport subprocess\nimport sys\nfrom pathlib import Path\nfrom typing import List, Optional\n\n_PROMPT = \"\"\"This will:\n  - Create and switch to a new branch named '%s'.\n  - Create a new proposal titled '%s'.\n  - Create a PR for the proposal.\n\nContinue? (Y/n) \"\"\"\n\n_LINK_TEMPLATE = \"\"\"Proposal links (add links as proposal evolves):\n\n-   Evolution links:\n    -   [Proposal PR](https://github.com/carbon-language/carbon-lang/pull/%s)\n    -   `[RFC topic](TODO)`\n    -   `[Decision topic](TODO)`\n    -   `[Decision PR](TODO)`\n    -   `[Announcement](TODO)`\n-   Related links (optional):\n    -   `[Idea topic](TODO)`\n    -   `[TODO](TODO)`\n\"\"\"\n\n\ndef _parse_args(args: Optional[List[str]] = None) -> argparse.Namespace:\n    \"\"\"Parses command-line arguments and flags.\"\"\"\n    parser = argparse.ArgumentParser(\n        description=\"Generates a branch and PR for a new proposal with the \"\n        \"specified title.\"\n    )\n    parser.add_argument(\n        \"title\",\n        metavar=\"TITLE\",\n        help=\"The title of the proposal.\",\n    )\n    parser.add_argument(\n        \"--branch\",\n        metavar=\"BRANCH\",\n        help=\"The name of the branch. Automatically generated from the title \"\n        \"by default.\",\n    )\n    parser.add_argument(\n        \"--remote\",\n        metavar=\"REMOTE\",\n        default=\"origin\",\n        help=\"The git remote name where the branch will be pushed. Defaults to \"\n        \"'origin'.\",\n    )\n    parser.add_argument(\n        \"--repo_root\",\n        metavar=\"REPO_ROOT\",\n        default=Path(__file__).parents[2],\n        help=\"The repository root, mainly for testing cross-repository. \"\n        \"Automatically found by default.\",\n    )\n    parser.add_argument(\n        \"--branch-start-point\",\n        metavar=\"BRANCH_START_POINT\",\n        default=\"trunk\",\n        type=str,\n        help=\"The starting point for the new branch.\",\n    )\n    return parser.parse_args(args=args)\n\n\ndef _calculate_branch(parsed_args: argparse.Namespace) -> str:\n    \"\"\"Returns the branch name.\"\"\"\n    if parsed_args.branch:\n        assert isinstance(parsed_args.branch, str)\n        return parsed_args.branch\n    # Only use the first 20 chars of the title for branch names.\n    return \"proposal-%s\" % (parsed_args.title.lower().replace(\" \", \"-\")[0:20])\n\n\ndef _find_tool(tool: str) -> str:\n    \"\"\"Checks if a tool is present.\"\"\"\n    tool_path = shutil.which(tool)\n    if not tool_path:\n        exit(\"ERROR: Missing the '%s' command-line tool.\" % tool)\n    return tool_path\n\n\ndef _fill_template(template_path: str, title: str, pr_num: int) -> str:\n    \"\"\"Fills out template TODO fields.\"\"\"\n    with open(template_path) as template_file:\n        content = template_file.read()\n    content = re.sub(r\"^# TODO\\n\", \"# %s\\n\" % title, content)\n    content = re.sub(\n        r\"(https://github.com/[^/]+/[^/]+/pull/)####\",\n        r\"\\g<1>%d\" % pr_num,\n        content,\n    )\n    content = re.sub(r\"\\n## TODO(?:.|\\n)*?(\\n## )\", r\"\\1\", content)\n    return content\n\n\ndef _run(\n    argv: List[str], check: bool = True, get_stdout: bool = False\n) -> Optional[str]:\n    \"\"\"Runs a command.\"\"\"\n    cmd = \" \".join([shlex.quote(x) for x in argv])\n    print(\"\\n+ RUNNING: %s\" % cmd, file=sys.stderr)\n\n    stdout_pipe = None\n    if get_stdout:\n        stdout_pipe = subprocess.PIPE\n\n    p = subprocess.Popen(argv, stdout=stdout_pipe)\n    stdout, _ = p.communicate()\n    if get_stdout:\n        out = stdout.decode(\"utf-8\")\n        print(out, end=\"\")\n    if check and p.returncode != 0:\n        exit(\"ERROR: Command failed: %s\" % cmd)\n    if get_stdout:\n        return out\n    return None\n\n\ndef _run_pr_create(argv: List[str]) -> int:\n    \"\"\"Runs a command and returns the PR#.\"\"\"\n    out = _run(argv, get_stdout=True)\n    assert out is not None\n    match = re.search(\n        r\"^https://github.com/[^/]+/[^/]+/pull/(\\d+)$\", out, re.MULTILINE\n    )\n    if not match:\n        exit(\"ERROR: Failed to find PR# in output.\")\n    return int(match.group(1))\n\n\ndef main() -> None:\n    parsed_args = _parse_args()\n\n    # Switch to repo root early for consistent execution.\n    os.chdir(parsed_args.repo_root)\n\n    title = parsed_args.title\n    branch = _calculate_branch(parsed_args)\n\n    # Verify tools are available.\n    gh_bin = _find_tool(\"gh\")\n    if Path(\".jj\").is_dir():\n        jj_bin = _find_tool(\"jj\")\n        git_bin = None\n    else:\n        git_bin = _find_tool(\"git\")\n        jj_bin = None\n    precommit_bin = _find_tool(\"pre-commit\")\n\n    # Verify there are no uncommitted changes (jj has no equivalent).\n    if git_bin:\n        p = subprocess.run([git_bin, \"diff-index\", \"--quiet\", \"HEAD\", \"--\"])\n        if p.returncode != 0:\n            exit(\"ERROR: There are uncommitted changes in your git repo.\")\n\n    # Prompt before proceeding.\n    response = \"?\"\n    while response not in (\"y\", \"n\", \"\"):\n        response = input(_PROMPT % (branch, title)).lower()\n    if response == \"n\":\n        exit(\"ERROR: Cancelled\")\n\n    # Create a proposal branch.\n    if git_bin:\n        _run(\n            [\n                git_bin,\n                \"switch\",\n                \"--create\",\n                branch,\n                parsed_args.branch_start_point,\n            ]\n        )\n        _run([git_bin, \"push\", \"-u\", parsed_args.remote, branch])\n    else:\n        assert jj_bin  # For mypy.\n        _run([jj_bin, \"new\", parsed_args.branch_start_point])\n        _run([jj_bin, \"bookmark\", \"create\", branch])\n        _run(\n            [\n                jj_bin,\n                \"bookmark\",\n                \"track\",\n                branch,\n                \"--remote\",\n                parsed_args.remote,\n            ]\n        )\n\n    # Copy template.md to a temp file.\n    template_path = \"proposals/scripts/template.md\"\n    temp_path = \"proposals/new-proposal.tmp.md\"\n    shutil.copyfile(template_path, temp_path)\n    initial_desc = \"Creating new proposal: %s\" % title\n    if git_bin:\n        _run([git_bin, \"add\", temp_path])\n        _run([git_bin, \"commit\", \"-m\", initial_desc])\n    else:\n        assert jj_bin  # For mypy.\n        _run([jj_bin, \"describe\", \"-m\", initial_desc])\n\n    # Create a PR with WIP+proposal labels.\n    if git_bin:\n        _run([git_bin, \"push\"])\n        user = _run([git_bin, \"config\", \"get\", \"user.name\"], get_stdout=True)\n    else:\n        assert jj_bin  # For mypy.\n        _run([jj_bin, \"git\", \"push\"])\n        user = _run([jj_bin, \"config\", \"get\", \"user.name\"], get_stdout=True)\n    assert user  # For mypy.\n    user = user.strip()\n    pr_num = _run_pr_create(\n        [\n            gh_bin,\n            \"pr\",\n            \"create\",\n            \"--head\",\n            \"%s:%s\" % (user, branch),\n            \"--draft\",\n            \"--label\",\n            \"proposal\",\n            \"--label\",\n            \"proposal draft\",\n            \"--repo\",\n            \"carbon-language/carbon-lang\",\n            \"--title\",\n            title,\n            \"--body\",\n            \"TODO: add summary and links here\",\n        ]\n    )\n\n    # Remove the temp file, create p####.md, and fill in PR information.\n    os.remove(temp_path)\n    final_path = \"proposals/p%04d.md\" % pr_num\n    content = _fill_template(template_path, title, pr_num)\n    with open(final_path, \"w\") as final_file:\n        final_file.write(content)\n\n    # Run pre-commit for a ToC update, then push the PR update.\n    final_desc = \"Filling out template with PR %d\" % pr_num\n    if git_bin:\n        _run([git_bin, \"add\", temp_path, final_path])\n        _run([precommit_bin, \"run\"], check=False)\n        _run([git_bin, \"commit\", \"--amend\", \"-m\", final_desc])\n\n        _run([git_bin, \"push\", \"--force-with-lease\"])\n    else:\n        assert jj_bin  # For mypy.\n\n        _run(\n            [precommit_bin, \"run\", \"--files\", \"$(jj diff --name-only)\"],\n            check=False,\n        )\n        _run([jj_bin, \"describe\", \"-m\", final_desc])\n        _run([jj_bin, \"git\", \"push\"])\n\n    print(\n        \"\\nCreated PR %d for %s. Make changes to:\\n  %s\"\n        % (pr_num, title, final_path)\n    )\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "proposals/scripts/new_proposal_test.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Tests for new_proposal.py.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport os\nimport unittest\n\nfrom proposals.scripts import new_proposal\n\n\nclass TestNewProposal(unittest.TestCase):\n    def test_calculate_branch_short(self):\n        parsed_args = new_proposal._parse_args([\"foo bar\"])\n        self.assertEqual(\n            new_proposal._calculate_branch(parsed_args), \"proposal-foo-bar\"\n        )\n\n    def test_calculate_branch_long(self):\n        parsed_args = new_proposal._parse_args(\n            [\"A really long long long title\"]\n        )\n        self.assertEqual(\n            new_proposal._calculate_branch(parsed_args),\n            \"proposal-a-really-long-long-l\",\n        )\n\n    def test_calculate_branch_flag(self):\n        parsed_args = new_proposal._parse_args([\"--branch=wiz\", \"foo\"])\n        self.assertEqual(new_proposal._calculate_branch(parsed_args), \"wiz\")\n\n    def test_fill_template(self):\n        # Switch directories for the test.\n        parsed_args = new_proposal._parse_args([\"foo\"])\n        os.chdir(parsed_args.repo_root)\n\n        content = new_proposal._fill_template(\n            \"proposals/scripts/template.md\",\n            \"TITLE\",\n            123,\n        )\n        self.assertTrue(content.startswith(\"# TITLE\\n\\n\"), content)\n        self.assertTrue(\n            \"[Pull request](https://github.com/carbon-language/carbon-lang/\"\n            \"pull/123)\" in content,\n            content,\n        )\n        self.assertTrue(\n            \"<!-- tocstop -->\\n\\n## Abstract\\n\\n\" in content, content\n        )\n\n    def test_run_success(self):\n        new_proposal._run([\"true\"])\n\n    def test_run_failure(self):\n        self.assertRaises(SystemExit, new_proposal._run, [\"false\"])\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "proposals/scripts/template.md",
    "content": "# TODO\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n[Pull request](https://github.com/carbon-language/carbon-lang/pull/####)\n\n<!-- toc -->\n\n## Table of contents\n\n-   [TODO: Initial proposal setup](#todo-initial-proposal-setup)\n-   [Abstract](#abstract)\n-   [Problem](#problem)\n-   [Background](#background)\n-   [Proposal](#proposal)\n-   [Details](#details)\n-   [Rationale](#rationale)\n-   [Alternatives considered](#alternatives-considered)\n\n<!-- tocstop -->\n\n## TODO: Initial proposal setup\n\n> TIP: Run `./new_proposal.py \"TITLE\"` to do new proposal setup.\n\n1. Copy this template to `new.md`, and create a commit.\n2. Create a GitHub pull request, to get a pull request number.\n    - Add the `proposal draft` label to the pull request.\n3. Rename `new.md` to `/proposals/p####.md`, where `####` should be the pull\n   request number.\n4. Update the title of the proposal (the `TODO` on line 1).\n5. Update the link to the pull request (the `####` on line 11).\n6. Delete this section.\n\nTODOs indicate where content should be updated for a proposal. See\n[Carbon Governance and Evolution](/docs/project/evolution.md) for more details.\n\n## Abstract\n\nTODO: Describe, in a succinct paragraph, the gist of this document. This\nparagraph should be reproduced verbatim in the PR summary.\n\n## Problem\n\nTODO: What problem are you trying to solve? How important is that problem? Who\nis impacted by it?\n\n## Background\n\nTODO: Is there any background that readers should consider to fully understand\nthis problem and your approach to solving it?\n\n## Proposal\n\nTODO: Briefly and at a high level, how do you propose to solve the problem? Why\nwill that in fact solve it?\n\n## Details\n\nTODO: Fully explain the details of the proposed solution.\n\n## Rationale\n\nTODO: How does this proposal effectively advance Carbon's goals? Rather than\nre-stating the full motivation, this should connect that motivation back to\nCarbon's stated goals and principles. This may evolve during review. Use links\nto appropriate sections of [`/docs/project/goals.md`](/docs/project/goals.md),\nand/or to documents in [`/docs/project/principles`](/docs/project/principles).\nFor example:\n\n-   [Community and culture](/docs/project/goals.md#community-and-culture)\n-   [Language tools and ecosystem](/docs/project/goals.md#language-tools-and-ecosystem)\n-   [Performance-critical software](/docs/project/goals.md#performance-critical-software)\n-   [Software and language evolution](/docs/project/goals.md#software-and-language-evolution)\n-   [Code that is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write)\n-   [Practical safety and testing mechanisms](/docs/project/goals.md#practical-safety-and-testing-mechanisms)\n-   [Fast and scalable development](/docs/project/goals.md#fast-and-scalable-development)\n-   [Modern OS platforms, hardware architectures, and environments](/docs/project/goals.md#modern-os-platforms-hardware-architectures-and-environments)\n-   [Interoperability with and migration from existing C++ code](/docs/project/goals.md#interoperability-with-and-migration-from-existing-c-code)\n\n## Alternatives considered\n\nTODO: What alternative solutions have you considered?\n"
  },
  {
    "path": "pyproject.toml",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n[tool.black]\nline-length = 80\ntarget-version = ['py310']\ninclude = '\\.pyi?$'\n"
  },
  {
    "path": "scripts/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"@rules_python//python:defs.bzl\", \"py_test\")\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_library\")\n\npy_test(\n    name = \"no_op_test\",\n    size = \"small\",\n    srcs = [\"no_op_test.py\"],\n    main = \"no_op_test.py\",\n)\n\ncc_library(\n    name = \"deps_for_clangd_tidy\",\n    srcs = [\"deps_for_clangd_tidy.cpp\"],\n    deps = [\n        # `@boost.unordered` uses `strip_prefix`, which results in\n        # `_virtual_includes` being part of the `compile_commands.json`. To\n        # support tools like `clangd-tidy`, this is intended to generate that directory.\n        #\n        # `@boost.unordered` uses `strip_prefix`, which results in\n        # bazel-out/<mode>/bin/external/+_repo_rules+boost.unordered/_virtual_includes/boost.unordered\n        \"@boost.unordered\",\n    ],\n)\n"
  },
  {
    "path": "scripts/bazel_mod_deps.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Run `bazel mod deps` for pre-commit. Lets pre-commit handle modifications.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport subprocess\n\nimport scripts_utils\n\n\ndef main() -> None:\n    scripts_utils.chdir_repo_root()\n    bazel = scripts_utils.locate_bazel()\n    subprocess.run([bazel, \"mod\", \"deps\"])\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/bench_runner.py",
    "content": "#!/usr/bin/env -S uv run --script\n\n# /// script\n# requires-python = \">=3.10\"\n# dependencies = [\n#     \"numpy\",\n#     \"rich\",\n#     \"scipy\",\n#     \"quantiphy\",\n# ]\n# ///\n\n\"\"\"Script to run GoogleBenchmark binaries repeatedly and render results.\n\nThis script helps run benchmarks repeatedly and render the resulting\nmeasurements in a way that effectively surfaces noisy benchmarks and provides\nstatistically significant information about the measurements.\n\nThere are two primary modes:\n\n1) Running a single experiment benchmark binary repeatedly to understand that\n   benchmark's performance.\n\n2) Running both an experiment and a baseline benchmark binary that include the\n   same benchmark names to understand the change in performance for each named\n   benchmark.\n\nAcross all of these modes, when rendering a specific metric for a benchmark, we\nalso render the confidence intervals based on the specified `--alpha` parameter.\n\nFor mode (1) when running a single benchmark binary, there is additional support\nfor passing regular expressions that describe a set of comparable benchmarks for\nsome main benchmark. When used, the comparable benchmarks for each main one are\nrendered as a delta of the main rather than as completely independent metrics.\n\nFor mode (2) when running an experiment and baseline binary, every benchmark is\nrendered as a delta of the experiment vs. the baseline.\n\nWhenever rendering a delta, this script will flag statistically significant\n(according to the provided `--alpha`) improvements or regressions, compute the\nimprovement or regression, and display the resulting p-value. This script uses\nnon-parametric U-test for statistical significance, the same as Go's benchmark\ncomparison tools, based on the large body of evidence that benchmarks rarely if\never tend to adhere to a normal or other known distribution. A non-parametric\nstatistical model instead provides a much more realistic basis for comparing two\nmeasurements.\n\nThe reported metrics themselves are also classified into \"speed\" vs. \"cost\"\nmetrics in order to model whether larger is an improvement or a regression.\n\nThe script uses `uv` to run it rather than Python directly, which manages and\ncaches its dependencies. For installation instructions for `uv` see:\n- Carbon's documentation:\n  https://docs.carbon-lang.dev/docs/project/contribution_tools.html#optional-tools\n- UV's documentation: https://docs.astral.sh/uv/getting-started/installation/\n\"\"\"\n\nfrom __future__ import annotations\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport argparse\nimport json\nimport math\nimport numpy as np  # type: ignore\nimport re\nimport scipy as sp  # type: ignore\nimport subprocess\nimport sys\nfrom collections import defaultdict\nfrom dataclasses import dataclass, field\nfrom enum import Enum\nfrom pathlib import Path\nfrom quantiphy import Quantity  # type: ignore\nfrom rich.console import Console\nfrom rich.padding import Padding\nfrom rich.progress import track\nfrom rich.table import Column, Table\nfrom rich.text import Text\nfrom rich.theme import Theme\nfrom typing import Optional\n\n\ndef parse_args(args: Optional[list[str]] = None) -> argparse.Namespace:\n    \"\"\"Parsers command-line arguments and flags.\"\"\"\n    parser = argparse.ArgumentParser(description=__doc__)\n    parser.add_argument(\n        \"--exp_benchmark\",\n        metavar=\"BINARY\",\n        required=True,\n        type=Path,\n        help=\"The experiment benchmark binary to run\",\n    )\n    parser.add_argument(\n        \"--base_benchmark\",\n        metavar=\"BINARY\",\n        type=Path,\n        help=\"\"\"\nThe baseline benchmark binary to run.\n\nPassing this flag will enable both a baseline and experiment, and change the\nanalysis to compute and display any statistically significant delta as well\nas the before and after values of the each benchmark run.\n\"\"\".strip(),\n    )\n    parser.add_argument(\n        \"--benchmark_args\",\n        action=\"append\",\n        default=[],\n        metavar=\"ARG\",\n        help=\"Extra arguments to both the experiment and baseline benchmark\",\n    )\n    parser.add_argument(\n        \"--exp_benchmark_args\",\n        action=\"append\",\n        default=[],\n        metavar=\"ARG\",\n        help=\"Extra arguments to the experiment benchmark\",\n    )\n    parser.add_argument(\n        \"--base_benchmark_args\",\n        action=\"append\",\n        default=[],\n        metavar=\"ARG\",\n        help=\"Extra arguments to the baseline benchmark\",\n    )\n    parser.add_argument(\n        \"--benchmark_comparable_re\",\n        metavar=\"PATTERN\",\n        action=\"append\",\n        default=[],\n        help=\"\"\"\nA regular expression that is used to match sets of benchmarks that should be\ncompared with each other. This flag may be specified multiple times with\ndifferent regular expressions to handle multiple different grouping schemes or\nstructures. May not be combined with `base_benchmark`.\n\nEach regular expression is used to group together benchmark names distinguished\nby a \"tag\" substring in the name. Either the regex as a whole or a `tag`\nsymbolic capture group within the regex designates this substring. Further, a\n`main` symbolic capture group _must_ be included and only match when the\nspecific substring is the main benchmark name and other matching ones should be\nviewed as comparisons against it. When rendering, only the name matching the\nmain capture group will be rendered, with others rendered as comparisons against\nit based on the tag, and with statistical significance to evaluate the\ncomparison.\n\nExample regex: `(?P<tag>(?P<main>Carbon)|Abseil|LLVM)HashBench`\n\nThis produces three tags, `Carbon`, `Abseil`, and `LLVM`. The main tag is\n`Carbon`.\n\nTODO: This is only currently supported without a base benchmark to provide\nrelative comparisons within a single benchmark binary. There are good models for\nhandling this and surfacing delta-of-delta information with a base benchmark\nbinary.\n\"\"\".strip(),\n    )\n    parser.add_argument(\n        \"--runs\",\n        default=10,\n        metavar=\"N\",\n        type=int,\n        help=\"Number of runs of the benchmark\",\n    )\n    parser.add_argument(\n        \"--wall_time\",\n        action=\"store_true\",\n        help=\"Use wall-clock time instead of CPU time\",\n    )\n    parser.add_argument(\n        \"--show_iterations\",\n        action=\"store_true\",\n        help=\"Show the iteration counts\",\n    )\n    parser.add_argument(\n        \"--extra_metrics_filter\",\n        metavar=\"PATTERN\",\n        type=str,\n        help=\"A regex filter on the names of extra metrics to display.\",\n    )\n    parser.add_argument(\n        \"--alpha\",\n        default=0.05,\n        metavar=\"𝛂\",\n        type=float,\n        help=\"\"\"\nThreshold for P-values to be considered statistically significant. Also used to\ncompute the confidence intervals for individual metrics.\n\"\"\".strip(),\n    )\n    parser.add_argument(\n        \"--output\",\n        choices=[\"console\", \"json\"],\n        default=\"console\",\n        help=\"\"\"\nOutput format to use, note that `json` output doesn't do any analysis of the\nresults, and just dumps the aggregate JSON data from the repeated runs.\n\"\"\".strip(),\n    )\n    return parser.parse_args(args=args)\n\n\n# Default arguments that will be passed even when arguments are passed with\n# `--benchmark_args` to the script. These can be undone by overriding them in\n# explicitly passed arguments.\nDEFAULT_BENCHMARK_ARGS = [\n    # Randomize the order in which the benchmarks run to avoid skewed results\n    # due to a specific order.\n    \"--benchmark_enable_random_interleaving\",\n    # Reduce the default minimum time to 0.1s as it's more effective to use\n    # multiple runs to improve confidence in measurements.\n    \"--benchmark_min_time=0.1s\",\n]\n\n\n# Pre-compiled regexes to match metrics that measure _speed_: larger is better.\nSPEED_METRIC_PATTERNS = [\n    re.compile(p)\n    for p in [\n        r\"(?i)rate\",\n        r\"(?i).*per[\\s_](second|ms|ns)\",\n    ]\n]\n\n\n# Pre-compiled regexes to match metrics that measure _cost_: smaller is better.\nCOST_METRIC_PATTERNS = [\n    re.compile(p)\n    for p in [\n        r\"(?i)cycles\",\n        r\"(?i)instructions\",\n        r\"(?i)time\",\n    ]\n]\n\n\n# Theme for use with the Rich `Console` printing.\nTHEME = Theme(\n    {\n        \"base_median\": \"cyan\",\n        \"exp_median\": \"magenta\",\n        \"base_conf\": \"cyan\",\n        \"exp_conf\": \"magenta\",\n        \"slower\": \"bright_red\",\n        \"faster\": \"bright_green\",\n    }\n)\n\n\n# The set of benchmark keys we ignore in the JSON data structure. Most of these\n# are things are incidental, but a few are more surprising. See comments on\n# specific entries for details.\nIGNORED_BENCHMARK_KEYS = set(\n    [\n        \"name\",\n        \"family_index\",\n        \"per_family_instance_index\",\n        \"run_name\",\n        \"run_type\",\n        \"repetitions\",\n        \"repetition_index\",\n        \"threads\",\n        # We don't render `iterations` because we instead directly compute\n        # statistical error bars using the multiple iterations. This removes the\n        # need for manually considering the iteration count.\n        \"iterations\",\n        # We ignore the time and time unit metrics here because we directly\n        # access and special case these metrics in order to apply the unit to\n        # the times.\n        \"real_time\",\n        \"cpu_time\",\n        \"time_unit\",\n    ]\n)\n\n\nclass DeltaKind(Enum):\n    \"\"\"Models the relevant kinds of deltas that we end up wanting to render.\"\"\"\n\n    IMPROVEMENT = \"[faster]👍[/faster]\"\n    NEUTRAL = \"~\"\n    REGRESSION = \"[slower]👎[/slower]\"\n    NOISE = \"\"\n\n    def __str__(self) -> str:\n        return self.value\n\n\n@dataclass\nclass RenderedDelta:\n    \"\"\"Rendered delta and pvalue for some metric.\"\"\"\n\n    kind: DeltaKind\n    delta: str\n    pvalue: str\n\n\n@dataclass\nclass RenderedMetric:\n    \"\"\"Rendered non-delta metric and its confidence interval.\"\"\"\n\n    median: str\n    conf: str\n\n\n@dataclass\nclass BenchmarkRunMetrics:\n    \"\"\"The main data class used to collect metrics for benchmark runs.\n\n    The data is read in using a JSON format that isn't organized in a convenient\n    way to analyze and render, so we re-organize it into this data class and use\n    that for analysis.\n\n    Each object of this class corresponds to a specific named benchmark.\n    \"\"\"\n\n    # The main metrics for this named benchmark, or the \"experiment\". This field\n    # is always populated.\n    exp: list[Quantity] = field(default_factory=lambda: [])\n\n    # The metrics for this named benchmark in the base execution. May be empty\n    # if no base execution was provided to compute a delta against.\n    base: list[Quantity] = field(default_factory=lambda: [])\n\n    # Any comparable benchmark metrics, indexed by the tag name to use when\n    # rendering the comparison. May be empty if there are no comparable\n    # benchmarks for the main one this represents.\n    comps: defaultdict[str, list[Quantity]] = field(\n        default_factory=lambda: defaultdict(list)\n    )\n\n\n@dataclass\nclass ComparableBenchmarkMapping:\n    \"\"\"Organizes any comparable benchmarks.\n\n    Constructed with the list of benchmark names and regexes that describe\n    comparable name structures.\n\n    Names that match one of these regexes are organized into the main name in\n    `main_benchmark_names`, and the comparable names in various mappings to\n    allow computing comparisons metrics between the main and comparable names.\n\n    Names that don't match any of the regexes are just directly included in\n    `main_benchmark_names`.\n    \"\"\"\n\n    # Names that are considered \"main\" benchmarks after filtering.\n    main_benchmark_names: list[str]\n    # Maps a comparison benchmark name to its base name (tag removed).\n    name_to_base: dict[str, str]\n    # Maps a base name to its main benchmark name.\n    base_to_main_name: dict[str, str]\n    # Maps a comparison benchmark name to its tag.\n    name_to_comp_tag: dict[str, str]\n    # Maps a main benchmark name to a list of its comparison tags.\n    main_name_to_comp_tags: dict[str, list[str]]\n\n    def __init__(\n        self,\n        original_benchmark_names: list[str],\n        comparable_re_strs: list[str],\n        console: Console,\n    ):\n        \"\"\"Identify main and comparable benchmarks.\"\"\"\n        self.main_benchmark_names = []\n        self.name_to_base = {}\n        self.base_to_main_name = {}\n        self.name_to_comp_tag = {}\n        self.main_name_to_comp_tags = {}\n\n        comp_res = [\n            re.compile(comparable_re_str)\n            for comparable_re_str in comparable_re_strs\n        ]\n        for comp_re in comp_res:\n            if \"main\" not in comp_re.groupindex:\n                console.log(\n                    \"ERROR: No main capture group in the \"\n                    \"`--benchmark_comparable_re` flag!\"\n                )\n                sys.exit(1)\n\n        for name in original_benchmark_names:\n            comp_match = next(\n                (m for comp_re in comp_res if (m := comp_re.search(name))), None\n            )\n            if not comp_match:\n                # Non-comparable benchmark\n                self.main_benchmark_names.append(name)\n                continue\n\n            tag_group = 0\n            if \"tag\" in comp_match.re.groupindex:\n                tag_group = comp_match.re.groupindex[\"tag\"]\n\n            tag = comp_match.group(tag_group)\n            tag_begin, tag_end = comp_match.span(tag_group)\n            base_name = name[:tag_begin] + name[tag_end:]\n            self.name_to_base[name] = base_name\n\n            if comp_match.group(\"main\"):\n                self.base_to_main_name[base_name] = name\n                self.main_benchmark_names.append(name)\n            else:\n                self.name_to_comp_tag[name] = tag\n\n        # Verify that for all the comparable benchmarks we actually found a main\n        # benchmark name. We can't do this while processing initially as we\n        # don't know the relative order of main and comparable benchmark names.\n        #\n        # Also collect a list of all the comparison tags for a given main name.\n        # self.main_name_to_comp_tags: dict[str, list[str]] = {}\n        for comp, comp_tag in self.name_to_comp_tag.items():\n            base_name = self.name_to_base[comp]\n            main_name = self.base_to_main_name[base_name]\n            if not main_name:\n                console.log(\n                    f\"ERROR: Comparable benchmark `{comp}` has no corresponding\"\n                    \" main benchmark name!\"\n                )\n                sys.exit(1)\n\n            if comp_tag in self.main_name_to_comp_tags.get(main_name, []):\n                console.log(\n                    f\"ERROR: Duplicate comparison tag `{comp_tag}` for main \"\n                    f\"benchmark `{main_name}`!\"\n                )\n                sys.exit(1)\n            self.main_name_to_comp_tags.setdefault(main_name, []).append(\n                comp_tag\n            )\n\n\ndef float_ratio(nom: float, denom: float) -> float:\n    \"\"\"Translate a ratio of floats into a float, handling divide by zero.\"\"\"\n    if denom != 0.0:\n        return nom / denom\n    elif nom > 0.0:\n        return math.inf\n    elif nom < 0.0:\n        return -math.inf\n    else:\n        return 0.0\n\n\ndef render_fixed_width_float(x: float) -> str:\n    \"\"\"Renders a floating point value into a fixed width string.\"\"\"\n    if math.isinf(x):\n        return f\"{x:>4f}{'':<3}\"\n\n    frac, whole = math.modf(x)\n    frac_str = f\"{math.fabs(frac):<4.3f}\"[1:]\n    return f\"{int(whole):> 3}{frac_str}\"\n\n\ndef render_ratio(ratio: float) -> str:\n    \"\"\"Renders a ratio into a human-friendly string form.\n\n    This uses a % for ratios with a magnitude less than 1.0. For ratios with a\n    larger magnitude, they are rendered as a fixed width floating point number\n    with an `x` suffix.\n    \"\"\"\n    if ratio > 1.0 or ratio < -1.0:\n        return f\"{render_fixed_width_float(ratio)}x\"\n    else:\n        return f\"{render_fixed_width_float(ratio * 100.0)}%\"\n\n\ndef render_metric(\n    alpha: float, times: list[Quantity], is_base: bool\n) -> RenderedMetric:\n    \"\"\"Render a non-delta metric.\n\n    Computes the string to use for both the metric itself and the string to show\n    the confidence interval for that metric.\n\n    Args:\n        alpha: The alpha value to use for the confidence interval.\n        times: The list of measurements.\n        is_base:\n            Whether to use the \"baseline\" or \"experiment\" theme in the rendered\n            strings.\n    \"\"\"\n\n    if is_base:\n        style_prefix = \"base_\"\n    else:\n        style_prefix = \"exp_\"\n\n    units = times[0].units\n    if all(x == times[0] for x in times):\n        with Quantity.prefs(number_fmt=\"{whole:>3}{frac:<4} {units}\"):\n            return RenderedMetric(\n                f\"[{style_prefix}median]{times[0]:.3}[/{style_prefix}median]\",\n                \"\",\n            )\n\n    median = Quantity(np.median(times), units=units)\n    median_test = sp.stats.quantile_test(times, q=median)\n    median_ci = median_test.confidence_interval(confidence_level=(1.0 - alpha))\n\n    ci_str = \"?\"\n    if not math.isnan(median_ci.low) and not math.isnan(median_ci.high):\n        low_delta = median - median_ci.low\n        high_delta = median_ci.high - median\n        assert low_delta >= 0.0, high_delta >= 0.0\n        delta = max(low_delta, high_delta)\n        ci_str = render_ratio(float_ratio(delta, median))\n\n    with Quantity.prefs(number_fmt=\"{whole:>3}{frac:<4} {units}\"):\n        return RenderedMetric(\n            f\"[{style_prefix}median]{median:.3}[/{style_prefix}median]\",\n            f\"[{style_prefix}conf]{ci_str:9}[/{style_prefix}conf]\",\n        )\n\n\ndef render_delta(\n    metric: str, alpha: float, base: list[Quantity], exp: list[Quantity]\n) -> RenderedDelta:\n    \"\"\"Render a delta metric.\n\n    This handles computing the delta, its statistical significance, and\n    whether that delta is an improvement or a regression based on the specific\n    metric name.\n\n    Args:\n        metric:\n            The name of the metric to guide whether bigger or smaller is an\n            improvement.\n        alpha: The alpha value to use for the confidence interval.\n        base: The baseline measurements.\n        exp: The experiment measurements.\n    \"\"\"\n    # Skip any delta when all the data is zero. This typically occurs for\n    # uninteresting metrics or metrics that weren't collected for a given run.\n    if all(b == 0 for b in base) and all(e == 0 for e in exp):\n        return RenderedDelta(DeltaKind.NEUTRAL, \"\", \"\")\n\n    if any(speed_pat.search(metric) for speed_pat in SPEED_METRIC_PATTERNS):\n        bigger_style = \"faster\"\n        smaller_style = \"slower\"\n        bigger_kind = DeltaKind.IMPROVEMENT\n        smaller_kind = DeltaKind.REGRESSION\n    elif any(cost_pat.search(metric) for cost_pat in COST_METRIC_PATTERNS):\n        bigger_style = \"slower\"\n        smaller_style = \"faster\"\n        bigger_kind = DeltaKind.REGRESSION\n        smaller_kind = DeltaKind.IMPROVEMENT\n    else:\n        return RenderedDelta(DeltaKind.NEUTRAL, \"\", \"\")\n\n    u_test = sp.stats.mannwhitneyu(base, exp)\n    if u_test.pvalue >= alpha:\n        return RenderedDelta(\n            DeltaKind.NOISE, \"  ??       \", f\"p={u_test.pvalue:.3}\"\n        )\n\n    kind = DeltaKind.NEUTRAL\n\n    base_median = np.median(base)\n    exp_median = np.median(exp)\n    exp_ratio = float_ratio(exp_median, base_median)\n    # TODO: Maybe the threshold of \"interesting\" should be configurable instead\n    # of being fixed at 0.1%.\n    if exp_ratio >= 1.001:\n        style = bigger_style\n        kind = bigger_kind\n    elif exp_ratio <= 0.999:\n        style = smaller_style\n        kind = smaller_kind\n    else:\n        style = \"default\"\n\n    if exp_ratio >= 2.0 or exp_ratio <= 0.5:\n        return RenderedDelta(\n            kind,\n            f\"[{style}]{render_fixed_width_float(exp_ratio)}x[/{style}]\",\n            f\"p={u_test.pvalue:.3}\",\n        )\n\n    # Use a percent-delta for smaller ratios to make the delta more easily\n    # understood by readers.\n    exp_delta_percent = (\n        float_ratio(exp_median - base_median, base_median) * 100.0\n    )\n    return RenderedDelta(\n        kind,\n        f\"[{style}]{render_fixed_width_float(exp_delta_percent)}%[/{style}]\",\n        f\"p={u_test.pvalue:.3}\",\n    )\n\n\ndef render_metric_column(\n    metric: str,\n    alpha: float,\n    runs: list[BenchmarkRunMetrics],\n) -> Table:\n    \"\"\"Render the column of the benchmark results table for a given metric.\n\n    We render a single column for each metric, and use a careful line-oriented\n    layout within the column to ensure \"rows\" line up for each individual\n    benchmark. Within the column, we use a nested table to layout the different\n    rendered strings.\n\n    A key goal of the rendering throughout is to arrange for rendered numbers to\n    have the decimal point in a consistent column so that it isn't confusing for\n    readers to identify the position of the decimal point and magnitude of the\n    number rendered.\n\n    Args:\n        metric: The name of the metric to render.\n        alpha: The alpha value to use for the confidence interval.\n        runs: The list of benchmark runs.\n    \"\"\"\n    t = Table.grid(\n        Column(),\n        # It might seem like we want the left column here to be right-aligned,\n        # but we're going to carefully align the digits in the format string,\n        # and we can't easily control the length of units. So we left-align to\n        # simplify the digit layout.\n        Column(justify=\"left\"),\n        Column(justify=\"center\"),\n        Column(justify=\"left\"),\n        padding=(0, 1),\n    )\n\n    for run in runs:\n        if len(run.base) != 0:\n            # We have a baseline run to compare against, so compute the delta\n            # between it and the experiment as well as the specific baseline run\n            # metric.\n            rendered_delta = render_delta(metric, alpha, run.base, run.exp)\n            rendered_base = render_metric(alpha, run.base, is_base=True)\n\n            # Add the delta as the first row, then the baseline metric.\n            t.add_row(\n                str(rendered_delta.kind),\n                rendered_delta.delta,\n                \"\",\n                rendered_delta.pvalue,\n            )\n            t.add_row(\"\", rendered_base.median, \"±\", rendered_base.conf)\n\n        # Now render the experiment metric and add its row.\n        rendered_exp = render_metric(alpha, run.exp, is_base=False)\n        t.add_row(\"\", rendered_exp.median, \"±\", rendered_exp.conf)\n\n        # If we have any comparable benchmarks, render each of them as first a\n        # delta and then the specific comparable metric as its own kind of\n        # baseline.\n        #\n        # TODO: At some point when we support combining baseline _runs_ with\n        # comparable metrics, we'll need to change this to render both baseline\n        # and experiment comparables and a delta-of-delta. But currently we\n        # don't support combining these which simplifies the rendering here.\n        for name, comp in sorted(run.comps.items()):\n            rendered_delta = render_delta(metric, alpha, comp, run.exp)\n            t.add_row(\n                str(rendered_delta.kind),\n                rendered_delta.delta,\n                \"\",\n                rendered_delta.pvalue,\n            )\n            rendered_comp = render_metric(alpha, comp, is_base=True)\n            t.add_row(\"\", rendered_comp.median, \"±\", rendered_comp.conf)\n\n        # Lastly, if we had a baseline run or any comparable metrics we will\n        # have rendered multiple lines of data. Add a blank line so that these\n        # form a visual group.\n        if len(run.base) != 0 or len(run.comps) != 0:\n            t.add_row()\n\n    return t\n\n\ndef run_benchmark_binary(\n    binary_path: Path,\n    common_args: list[str],\n    specific_args: list[str],\n    num_runs: int,\n    console: Console,\n) -> list[dict]:\n    \"\"\"Runs a benchmark binary multiple times and collects results.\n\n    The results are parsed out of the JSON output from each run, and returned as\n    a list of dictionaries. Each dictionary represents one run.\n\n    This will log the command being run, show a progress bar for each run\n    performed, and then log de-duplicated `stderr` output from the runs.\n    \"\"\"\n    # If the binary path has no directory components and exists as a relative\n    # file, add `./` as a prefix. Otherwise, we want to pass the name unchanged\n    # for `PATH` search.\n    binary_str = str(binary_path)\n    if len(binary_path.parts) == 1 and binary_path.exists():\n        binary_str = f\"./{binary_str}\"\n    run_cmd = (\n        [binary_str]\n        + DEFAULT_BENCHMARK_ARGS\n        + common_args\n        + specific_args\n        # Pass the format flag last as it is required and can't be overridden.\n        + [\"--benchmark_format=json\"]\n    )\n    console.log(f\"Executing: {' '.join(run_cmd)}\")\n\n    runs_data = []\n    unique_stderr: list[bytes] = []\n    for _ in track(\n        range(num_runs), description=f\"Running {binary_path.name}...\"\n    ):\n        p = subprocess.run(\n            run_cmd,\n            check=True,\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n        )\n        runs_data.append(json.loads(p.stdout))\n        stderr = p.stderr.strip()\n        if len(stderr) != 0 and stderr not in unique_stderr:\n            unique_stderr.append(stderr)\n\n    for stderr_output in unique_stderr:\n        # Decode stderr, replacing errors in case of non-UTF-8 characters.\n        console.log(\n            f\"{binary_path.name} stderr:\\n\"\n            f\"{stderr_output.decode('utf-8', errors='replace')}\"\n        )\n\n    return runs_data\n\n\ndef print_run_context(\n    console: Console,\n    num_runs: int,\n    exp_runs: list[dict],\n    has_baseline: bool,\n) -> None:\n    \"\"\"Prints the context from the benchmark runs.\n\n    This replicates the useful context information from Google Benchmark's\n    default output, such as CPU information and cache sizes.\n\n    TODO: Print differently when context of base and experiment runs differ.\n\n    Args:\n        console: The rich console to print to.\n        num_runs: The number of times the benchmarks were run.\n        exp_runs: The results from the experiment benchmark runs.\n        has_baseline: Whether a baseline benchmark was also run.\n    \"\"\"\n    if has_baseline:\n        runs_description = f\"Ran baseline and experiment {num_runs} times\"\n    else:\n        runs_description = f\"Ran {num_runs} times\"\n    context = exp_runs[0][\"context\"]\n    console.print(\n        f\"{runs_description} on \"\n        f\"{context['num_cpus']} x {context['mhz_per_cpu']} MHz CPUs\"\n    )\n    console.print(\"CPU caches:\")\n    for cache in context[\"caches\"]:\n        size = Quantity(cache[\"size\"], binary=True)\n        console.print(f\"  L{cache['level']} {cache['type']} {size:b}\")\n    console.print(\n        f\"Load avg: {' '.join([str(load) for load in context['load_avg']])}\"\n    )\n\n\ndef get_benchmark_names_and_metrics(\n    console: Console,\n    parsed_args: argparse.Namespace,\n    exp_runs: list[dict],\n    base_runs: list[dict],\n) -> tuple[list[str], list[str]]:\n    \"\"\"Extracts benchmark names and metrics from benchmark run results.\n\n    This function determines the list of unique benchmark names and the metrics\n    to be displayed based on the benchmark output and command-line arguments.\n\n    Args:\n        parsed_args: The parsed command-line arguments.\n        exp_runs: A list of benchmark run results for the experiment binary.\n        base_runs: A list of benchmark run results for the baseline binary.\n\n    Returns:\n        - The list of unique benchmark names, maintaining their order.\n        - The list of metrics to display.\n    \"\"\"\n    # Start with the base time and iteration metrics requested.\n    metrics: list[str] = []\n    if parsed_args.wall_time:\n        metrics.append(\"real_time\")\n    else:\n        metrics.append(\"cpu_time\")\n    if parsed_args.show_iterations:\n        metrics.append(\"iterations\")\n\n    # Compile a regex for filtering extra metrics, if provided.\n    if metrics_filter_str := parsed_args.extra_metrics_filter:\n        metrics_filter = re.compile(metrics_filter_str)\n    else:\n        metrics_filter = None\n\n    # We only need to inspect the first run to find all benchmark and metric\n    # names. We combine benchmarks from both experiment and baseline runs to get\n    # a complete set.\n    one_run_benchmarks = exp_runs[0][\"benchmarks\"]\n    if parsed_args.base_benchmark:\n        one_run_benchmarks += base_runs[0][\"benchmarks\"]\n\n    benchmark_name_set: set[str] = set()\n    benchmark_name_indices: dict[str, tuple[int, int]] = {}\n    for benchmark in one_run_benchmarks:\n        name = benchmark[\"name\"]\n        benchmark_name_set.add(name)\n        indices = (\n            benchmark[\"family_index\"],\n            benchmark[\"per_family_instance_index\"],\n        )\n        if name not in benchmark_name_indices:\n            benchmark_name_indices[name] = indices\n        else:\n            if benchmark_name_indices[name] != indices:\n                console.print(\n                    f\"ERROR: Inconsintent indices {indices} and \"\n                    f\"{benchmark_name_indices[name]} for benchmark `{name}`.\"\n                )\n                sys.exit(1)\n\n        # Add any extra metrics from this benchmark.\n        for key in benchmark.keys():\n            if key in metrics or key in IGNORED_BENCHMARK_KEYS:\n                continue\n            if metrics_filter and not re.search(metrics_filter, key):\n                continue\n            metrics.append(key)\n\n    benchmark_names = sorted(\n        list(benchmark_name_set), key=lambda name: benchmark_name_indices[name]\n    )\n    return benchmark_names, metrics\n\n\ndef collect_benchmark_metrics(\n    benchmark_names: list[str],\n    metrics: list[str],\n    exp_runs: list[dict],\n    base_runs: list[dict],\n    comp_mapping: ComparableBenchmarkMapping,\n) -> dict[str, dict[str, BenchmarkRunMetrics]]:\n    \"\"\"Collects and organizes all benchmark metrics from raw run data.\n\n    This function takes the raw benchmark run data and organizes it into a\n    structured format suitable for analysis and rendering. It initializes the\n    main data structure, handles the mapping of comparable benchmarks, and\n    populates the metrics for both experiment and baseline runs.\n\n    Args:\n        benchmark_names: The initial list of unique benchmark names.\n        metrics: A list of all metric names to be collected.\n        exp_runs: A list of benchmark run results for the experiment binary.\n        base_runs: A list of benchmark run results for the baseline binary.\n        comp_mapping: The mapping of comparable benchmarks.\n\n    Returns:\n        A dictionary where keys are metric names. The values are another\n        dictionary where keys are benchmark names and values are\n        BenchmarkRunMetrics objects containing the collected measurements.\n    \"\"\"\n    # Initialize the data structure to hold all collected metrics.\n    benchmark_metrics: dict[str, dict[str, BenchmarkRunMetrics]] = {\n        metric: {name: BenchmarkRunMetrics() for name in benchmark_names}\n        for metric in metrics\n    }\n\n    # Populate metrics from the experiment runs.\n    for run in exp_runs:\n        for b in run[\"benchmarks\"]:\n            name = b[\"name\"]\n            for metric in metrics:\n                # Time metrics have a `time_unit` field that needs to be\n                # appended for correct parsing by the Quantity library.\n                unit = b.get(\"time_unit\", \"\") if \"time\" in metric else \"\"\n\n                # If this is a comparable benchmark, add its metrics to the\n                # 'comps' list of its corresponding main benchmark.\n                if maybe_comp_tag := comp_mapping.name_to_comp_tag.get(name):\n                    main_name = comp_mapping.base_to_main_name[\n                        comp_mapping.name_to_base[name]\n                    ]\n                    benchmark_metrics[metric][main_name].comps[\n                        maybe_comp_tag\n                    ].append(Quantity(f\"{b[metric]}{unit}\"))\n                # Otherwise, add it to the 'exp' list of its own entry if it's\n                # a main benchmark.\n                elif name in benchmark_names:\n                    benchmark_metrics[metric][name].exp.append(\n                        Quantity(f\"{b[metric]}{unit}\")\n                    )\n\n    # Populate metrics from the baseline runs.\n    for run in base_runs:\n        for b in run[\"benchmarks\"]:\n            name = b[\"name\"]\n            # Baseline runs don't have comparable benchmarks, so we only need\n            # to populate the 'base' list for main benchmarks.\n            if name in benchmark_names:\n                for metric in metrics:\n                    unit = b.get(\"time_unit\", \"\") if \"time\" in metric else \"\"\n                    benchmark_metrics[metric][name].base.append(\n                        Quantity(f\"{b[metric]}{unit}\")\n                    )\n\n    return benchmark_metrics\n\n\ndef print_metric_key(\n    console: Console,\n    alpha: float,\n    has_baseline: bool,\n    comp_mapping: ComparableBenchmarkMapping,\n) -> None:\n    \"\"\"Prints a legend for the metrics table.\n\n    This explains the format of the output table, including what the delta,\n    median, and confidence interval values represent.\n\n    Args:\n        console: The rich console to print to.\n        alpha: The alpha value for statistical significance.\n        has_baseline: Whether a baseline benchmark was run.\n    \"\"\"\n    console.print(\"Metric key:\")\n\n    conf = int(100 * (1.0 - alpha))\n\n    name = \"BenchmarkName...\"\n    delta_icon = str(DeltaKind.IMPROVEMENT)\n    delta = \"[faster]<delta>[/faster]\"\n    p = \"p=<U-test P-value>\"\n    base_median = \"[base_median]<median>[/base_median]\"\n    base_conf = f\"[base_conf]<% at {conf}th conf>[/base_conf]\"\n    exp_median = \"[exp_median]<median>[/exp_median]\"\n    exp_conf = f\"[exp_conf]<% at {conf}th conf>[/exp_conf]\"\n\n    key_table = Table.grid(\n        Column(justify=\"right\"),\n        Column(),\n        Column(),\n        Column(),\n        Column(),\n        padding=(0, 1),\n    )\n    if has_baseline:\n        key_table.add_row(name, delta_icon, delta, \"\", p)\n        key_table.add_row(\"baseline:\", \"\", base_median, \"±\", base_conf)\n        key_table.add_row(\"experiment:\", \"\", exp_median, \"±\", exp_conf)\n    else:\n        key_table.add_row(name, \"\", exp_median, \"±\", exp_conf)\n        # Only display comparable key if we have comparables to display.\n        if bool(comp_mapping.name_to_comp_tag):\n            key_table.add_row(\"vs Comparable:\", delta_icon, delta, p)\n            key_table.add_row(\"\", \"\", base_median, \"±\", base_conf)\n    console.print(Padding(key_table, (0, 0, 1, 3)))\n\n\ndef print_results_table(\n    console: Console,\n    alpha: float,\n    has_baseline: bool,\n    metrics: list[str],\n    benchmark_names: list[str],\n    benchmark_metrics: dict[str, dict[str, BenchmarkRunMetrics]],\n    comp_mapping: ComparableBenchmarkMapping,\n) -> None:\n    \"\"\"Builds and prints the main results table.\n\n    This function constructs a rich `Table` to display the benchmark results,\n    including deltas, medians, and confidence intervals for each metric. It then\n    prints this to the provided `console`.\n\n    Args:\n        console: The rich console to print to.\n        metrics: A list of metric names to be displayed as columns.\n        benchmark_names: A list of main benchmark names for the rows.\n        alpha: The alpha value for statistical significance.\n        benchmark_metrics: A nested dictionary containing the collected metrics\n                           for each benchmark and metric.\n        has_baseline: Whether a baseline benchmark was run.\n        comp_mapping: The mapping of comparable benchmarks.\n    \"\"\"\n    METRIC_TITLES = {\n        \"real_time\": \"Wall Time\",\n        \"cpu_time\": \"CPU Time\",\n        \"iterations\": \"Iterations\",\n    }\n\n    name_width = max(\n        (\n            len(name)\n            for name in (\n                benchmark_names\n                + [\n                    f\"vs {tag}:\"\n                    for tag in comp_mapping.name_to_comp_tag.values()\n                ]\n                + [\"experiment:\"]\n            )\n        )\n    )\n\n    table = Table(show_edge=False)\n    # The benchmark name column we want to justify right for the sub-labels, but\n    # we will fill the name in the column completed and the name will visually\n    # be justified to the left, so force the heading to justify left unlike the\n    # column text. We also disable wrapping because we manually fill the column\n    # and require line-precise layout.\n    table.add_column(\n        Text(\"Benchmark\", justify=\"left\"), justify=\"right\", no_wrap=True\n    )\n    for metric in metrics:\n        title = Text(METRIC_TITLES.get(metric, metric), justify=\"center\")\n        table.add_column(title, justify=\"left\", no_wrap=True)\n\n    name_t = Table.grid(Column(justify=\"right\", no_wrap=True), expand=True)\n    for name in benchmark_names:\n        name_t.add_row(f\"{name}{'.' * (name_width - len(name))}\")\n        if has_baseline:\n            name_t.add_row(\"baseline:\")\n            name_t.add_row(\"experiment:\")\n            name_t.add_row()\n        elif comp_tags := comp_mapping.main_name_to_comp_tags.get(name):\n            for tag in comp_tags:\n                name_t.add_row(f\"vs {tag}:\")\n                name_t.add_row()\n            name_t.add_row()\n\n    row = [name_t]\n    for metric in metrics:\n        metric_runs = benchmark_metrics[metric]\n        row.append(\n            render_metric_column(\n                metric, alpha, [metric_runs[name] for name in benchmark_names]\n            )\n        )\n    table.add_row(*row)\n    console.print(table)\n\n\ndef main() -> None:\n    parsed_args = parse_args()\n    console = Console(theme=THEME)\n    Quantity.set_prefs(spacer=\" \", map_sf=Quantity.map_sf_to_greek)\n\n    if parsed_args.base_benchmark and parsed_args.benchmark_comparable_re:\n        console.print(\n            \"ERROR: Cannot mix a base benchmark binary with benchmark \"\n            \"comparisons.\"\n        )\n        sys.exit(1)\n\n    # Run the benchmark(s) and collect the results into a data structure for\n    # processing.\n    num_runs = parsed_args.runs\n    base_runs: list[dict] = []\n    has_baseline = bool(parsed_args.base_benchmark)\n    if has_baseline:\n        base_runs = run_benchmark_binary(\n            parsed_args.base_benchmark,\n            parsed_args.benchmark_args,\n            parsed_args.base_benchmark_args,\n            num_runs,\n            console,\n        )\n\n    exp_runs = run_benchmark_binary(\n        parsed_args.exp_benchmark,\n        parsed_args.benchmark_args,\n        parsed_args.exp_benchmark_args,\n        num_runs,\n        console,\n    )\n\n    # If JSON output is requested, just dump the data without further\n    # processing.\n    if parsed_args.output == \"json\":\n        console.log(\"Printing JSON results...\")\n        console.print_json(json.dumps(exp_runs))\n        if has_baseline:\n            console.print_json(json.dumps(base_runs))\n        return\n\n    print_run_context(console, num_runs, exp_runs, has_baseline)\n\n    # Collect the benchmark names and metric names.\n    benchmark_names, metrics = get_benchmark_names_and_metrics(\n        console, parsed_args, exp_runs, base_runs\n    )\n\n    # Build any mappings between main benchmark names and comparables, and reset\n    # our benchmark names to the main ones.\n    comp_mapping = ComparableBenchmarkMapping(\n        benchmark_names, parsed_args.benchmark_comparable_re, console\n    )\n    benchmark_names = comp_mapping.main_benchmark_names\n\n    # Collect and organize the actual benchmark metrics from the raw JSON\n    # structures across the runs. This pivots the data into an easy to analyze\n    # and render structure, but doesn't do the analysis itself.\n    benchmark_metrics = collect_benchmark_metrics(\n        benchmark_names, metrics, exp_runs, base_runs, comp_mapping\n    )\n\n    # Analyze and render a readable table of the collected metrics. This is\n    # where we do statistical analysis and render confidence intervals,\n    # significance, and other helpful indicators based on the collected data. We\n    # also print relevant keys to reading and interpreting the rendered data.\n    alpha = parsed_args.alpha\n    console.print(\n        \"Computing statistically significant deltas only where\"\n        f\"the P-value < 𝛂 of {alpha}\"\n    )\n    print_metric_key(console, alpha, has_baseline, comp_mapping)\n    print_results_table(\n        console,\n        alpha,\n        has_baseline,\n        metrics,\n        benchmark_names,\n        benchmark_metrics,\n        comp_mapping,\n    )\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/calculate_release_shas.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Prints sha information for tracked tool releases.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport scripts_utils\n\n\ndef main() -> None:\n    scripts_utils.calculate_release_shas()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/check_build_graph.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Verify that the bazel build graph is in a valid state, for pre-commit.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport subprocess\n\nimport scripts_utils\n\n\ndef main() -> None:\n    scripts_utils.chdir_repo_root()\n    bazel = scripts_utils.locate_bazel()\n    subprocess.check_call([bazel, \"build\", \"--nobuild\", \"//...\"])\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/check_header_guards.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Checks for missing or incorrect header guards.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nfrom collections.abc import Iterable\nfrom pathlib import Path\nimport re\nimport sys\nfrom typing import NamedTuple, Optional\n\n\nclass Guard(NamedTuple):\n    \"\"\"A guard line in a file.\"\"\"\n\n    line: int\n    guard: str\n\n\ndef find_guard(\n    lines: list[str], pattern: str, from_end: bool\n) -> Optional[Guard]:\n    \"\"\"Searches the lines for something matching the pattern.\"\"\"\n    lines_range: Iterable[str] = lines\n    if from_end:\n        lines_range = reversed(lines)\n    for index, line in enumerate(lines_range):\n        m = re.match(pattern, line)\n        if m:\n            if from_end:\n                index = len(lines) - index - 1\n            return Guard(index, m[1])\n    return None\n\n\ndef maybe_replace(\n    lines: list[str], old_guard: Guard, guard_prefix: str, guard: str\n) -> None:\n    \"\"\"Replaces a header guard in the file if needed.\"\"\"\n    if guard != old_guard.guard:\n        line = lines[old_guard.line].rstrip(\"\\n\")\n        print(f\"- Replacing line {old_guard.line}: `{line}`\", file=sys.stderr)\n        lines[old_guard.line] = f\"{guard_prefix} {guard}\\n\"\n\n\ndef check_path(path: Path) -> bool:\n    \"\"\"Checks the path for header guard issues.\"\"\"\n    if path.suffix != \".h\":\n        print(f\"Not a header: {path}\", file=sys.stderr)\n        return True\n\n    with path.open() as f:\n        lines = f.readlines()\n\n    guard_path = str(path).upper().replace(\"/\", \"_\").replace(\".\", \"_\")\n    guard = f\"CARBON_{guard_path}_\"\n    ifndef = find_guard(lines, \"#ifndef ([A-Z0-9_]+_H_)\", False)\n    define = find_guard(lines, \"#define ([A-Z0-9_]+_H_)\", False)\n    endif = find_guard(lines, \"#endif(?:  // ([A-Z0-9_]+_H_))?\", True)\n    if ifndef is None or define is None or endif is None:\n        print(f\"Incomplete header guard in {path}:\", file=sys.stderr)\n        if ifndef is None:\n            print(f\"- Missing `#ifndef {guard}`\", file=sys.stderr)\n        if define is None:\n            print(f\"- Missing `#define {guard}`\", file=sys.stderr)\n        if endif is None:\n            print(f\"- Missing `#endif  // {guard}`\", file=sys.stderr)\n        return True\n\n    if ifndef.line + 1 != define.line:\n        print(\n            f\"Non-consecutive header guard in {path}: \"\n            f\"#ifndef on line {ifndef.line + 1}, \"\n            f\"#define on line {define.line + 1}.\",\n            file=sys.stderr,\n        )\n        return True\n\n    if endif.line != len(lines) - 1:\n        print(\n            f\"Misordered header guard in {path}: #endif on line {endif.line}, \"\n            f\"should be on last line ({len(lines) - 1}).\",\n            file=sys.stderr,\n        )\n        return True\n\n    if guard != ifndef.guard or guard != define.guard or guard != endif.guard:\n        print(f\"Fixing header guard in {path} to {guard}:\", file=sys.stderr)\n        maybe_replace(lines, ifndef, \"#ifndef\", guard)\n        maybe_replace(lines, define, \"#define\", guard)\n        maybe_replace(lines, endif, \"#endif  //\", guard)\n        with path.open(\"w\") as f:\n            f.writelines(lines)\n        return True\n\n    return False\n\n\ndef main() -> None:\n    has_errors = False\n    for arg in sys.argv[1:]:\n        if check_path(Path(arg)):\n            has_errors = True\n    if has_errors:\n        exit(1)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/check_sha_filenames.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Requires files be named for their SHA1.\n\nWe name fuzzer corpus files for their SHA1. The choice of SHA1 is for\nconsistency with git.\n\nThis maintains the current extension for .textproto, but at some point we might\nwant to specify the extension by path.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport hashlib\nfrom pathlib import Path\nimport sys\n\n\ndef main() -> None:\n    has_errors = False\n    for arg in sys.argv[1:]:\n        path = Path(arg)\n        with path.open(\"rb\") as f:\n            content = f.read()\n        if len(content) == 0:\n            want = \"empty\"\n        else:\n            want = hashlib.sha1(content).hexdigest()\n        want_path = path.parent.joinpath(want).with_suffix(path.suffix)\n        if path != want_path:\n            print(f\"Renaming {path} to {want_path}\", file=sys.stderr)\n            path.rename(want_path)\n            has_errors = True\n    if has_errors:\n        exit(1)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/create_compdb.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Create a compilation database for Clang tools like `clangd`.\n\nIf you want `clangd` to be able to index this project, run this script from\nthe workspace root to generate a rich compilation database. After the first\nrun, you should only need to run it if you encounter `clangd` problems, or if\nyou want `clangd` to build an up-to-date index of the entire project. Note\nthat in the latter case you may need to manually clear and rebuild clangd's\nindex after running this script.\n\nNote that this script will build generated files in the Carbon project and\notherwise touch the Bazel build. It works to do the minimum amount necessary.\nOnce setup, generally subsequent builds, even of small parts of the project,\ndifferent configurations, or that hit errors won't disrupt things. But, if\nyou do hit errors, you can get things back to a good state by fixing the\nbuild of generated files and re-running this script.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport argparse\nimport json\nimport subprocess\nimport sys\nfrom typing import Any, Dict\n\nimport scripts_utils\n\n\ndef _build_generated_files(\n    bazel: str,\n    logtostderr: bool,\n    dump_files: bool,\n    extra_bazel_flags: list[str] = [],\n) -> None:\n    print(\"Building the generated files so that tools can find them...\")\n\n    # Collect the generated file labels. Include some rules which generate\n    # files but aren't classified as \"generated file\".\n    kinds_query = (\n        \"filter(\"\n        ' \".*\\\\.(h|hpp|hxx|cpp|cc|c|cxx|def|inc|s|S)$\",'\n        ' kind(\"(.*generate.*|manifest_as_cpp)\",'\n        # tree_sitter is excluded here because it causes the query to failure on\n        # `@platforms`.\n        \"      deps(//... except //utils/tree_sitter/...))\"\n        \")\"\n    )\n    log_to = None\n    if not logtostderr:\n        log_to = subprocess.DEVNULL\n    generated_file_labels = subprocess.check_output(\n        [bazel, \"query\"]\n        + extra_bazel_flags\n        + [\"--keep_going\", \"--output=label\", kinds_query],\n        stderr=log_to,\n        encoding=\"utf-8\",\n    ).splitlines()\n    if dump_files:\n        for f in sorted(generated_file_labels):\n            print(f)\n        sys.exit(0)\n    print(f\"Found {len(generated_file_labels)} generated files...\", flush=True)\n\n    # Directly build these labels so that indexing can find them. Allow this to\n    # fail in case there are build errors in the client, and just warn the user\n    # that they may be missing generated files.\n    subprocess.check_call(\n        [bazel, \"build\"]\n        + extra_bazel_flags\n        + [\"--keep_going\", \"--remote_download_outputs=toplevel\"]\n        + generated_file_labels\n        # We also need the Bazel C++ runfiles that aren't \"generated\", but are\n        # not linked into place until built.\n        + [\"@bazel_tools//tools/cpp/runfiles:runfiles\"]\n    )\n\n\ndef _get_config_for_entry(entry: Dict[str, Any]) -> str:\n    \"\"\"Returns the configuration for a compile command entry.\"\"\"\n    arguments = entry.get(\"arguments\")\n\n    # Only handle files where the object file argument is easily found as\n    # the last argument, which matches the expected structure from Bazel.\n    if not arguments or len(arguments) < 2 or arguments[-2] != \"-o\":\n        return \"unknown\"\n    obj_file = arguments[-1]\n\n    # The configuration is the name of the subdirectory of `bazel-out`.\n    if not obj_file.startswith(\"bazel-out/\"):\n        return \"unknown\"\n    return str(obj_file.split(\"/\")[1])\n\n\ndef _filter_compilation_database(file_path: str) -> None:\n    \"\"\"Filters out duplicate exec-config entries from the database.\"\"\"\n    print(\"Filtering out duplicate exec-configuration entries...\")\n    try:\n        with open(file_path, \"r\") as f:\n            commands = json.load(f)\n    except FileNotFoundError:\n        print(f\"Error: The file '{file_path}' was not found.\")\n        sys.exit(1)\n    except json.JSONDecodeError:\n        print(f\"Error: The file '{file_path}' is not a valid JSON file.\")\n        sys.exit(1)\n\n    # We want to skip compiles that were in the \"exec\" configuration for tools.\n    # Because we generate compile commands for every bazel cc_* target in the\n    # main configuration, even if only used by tools, their sources should be\n    # covered and the exec configuration would simply be a duplicate.\n    #\n    # Detecting this based on the `-exec-` string in the configuration name of\n    # the directory is a bit of a hack, but even using the `--notool_deps`\n    # argument, Bazel seems to sometimes include this configuration in the query\n    # that produces the compilation database.\n    filtered_commands = [\n        entry\n        for entry in commands\n        if \"-exec-\" not in _get_config_for_entry(entry)\n    ]\n\n    with open(file_path, \"w\") as f:\n        # Use indent=4 for a human-readable, pretty-printed output file\n        json.dump(filtered_commands, f, indent=4)\n    print(\n        \"Filtered out \"\n        f\"{len(commands) - len(filtered_commands)} \"\n        \"duplicate entries...\"\n    )\n\n\ndef main() -> None:\n    parser = argparse.ArgumentParser(\n        description=__doc__,\n        allow_abbrev=False,\n    )\n    parser.add_argument(\n        \"--alsologtostderr\",\n        action=\"store_true\",\n        help=\"Prints subcommand errors to stderr (default: False)\",\n    )\n    parser.add_argument(\n        \"--dump-files\",\n        action=\"store_true\",\n        help=\"Dumps the full list of generated files (default: False)\",\n    )\n    parser.add_argument(\n        \"--extra-bazel-flag\",\n        action=\"append\",\n        default=[],\n        help=(\n            \"Extra flag to pass to Bazel invocations, may be specified more \"\n            \"than once\"\n        ),\n    )\n\n    args = parser.parse_args()\n    scripts_utils.chdir_repo_root()\n    bazel = scripts_utils.locate_bazel()\n\n    _build_generated_files(\n        bazel, args.alsologtostderr, args.dump_files, args.extra_bazel_flag\n    )\n\n    print(\n        \"Generating compile_commands.json (may take a few minutes)...\",\n        flush=True,\n    )\n    subprocess.run(\n        [\n            bazel,\n            \"run\",\n        ]\n        + args.extra_bazel_flag\n        + [\n            \"@hedron_compile_commands//:refresh_all\",\n            \"--\",\n        ]\n        + args.extra_bazel_flag\n        + [\n            \"--notool_deps\",\n        ]\n    )\n\n    _filter_compilation_database(\"compile_commands.json\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/deps_for_clangd_tidy.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// This file is only validating expected includes exist. See the BUILD target\n// for more information.\n\n#include <boost/unordered/unordered_flat_map.hpp>\n"
  },
  {
    "path": "scripts/fix_cc_deps.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Automatically fixes bazel C++ dependencies.\n\nBazel has some support for detecting when an include refers to a missing\ndependency. However, the ideal state is that a given build target depends\ndirectly on all #include'd headers, and Bazel doesn't enforce that. This\nautomates the addition for technical correctness.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport re\nimport subprocess\nfrom typing import Callable, NamedTuple\nfrom xml.etree import ElementTree\n\nimport scripts_utils\n\n\nclass ExternalRepo(NamedTuple):\n    # A function for remapping files to #include paths.\n    remap: Callable[[str], str]\n    # The target expression to gather rules for within the repo.\n    target: str\n    # Whether to use \"\" or <> for the include.\n    use_system_include: bool = False\n\n\nclass RuleChoice(NamedTuple):\n    # Whether to use \"\" or <> for the include.\n    use_system_include: bool\n    # Possible rules that may be used.\n    rules: set[str]\n\n\n# Maps external repository names to a method translating bazel labels to file\n# paths for that repository.\nEXTERNAL_REPOS: dict[str, ExternalRepo] = {\n    # llvm:include/llvm/Support/Error.h ->llvm/Support/Error.h\n    # clang-tools-extra/clangd:URI.h -> clang-tools-extra/clangd/URI.h\n    \"@llvm-project\": ExternalRepo(\n        lambda x: re.sub(\":\", \"/\", re.sub(\"^(.*:(lib|include))/\", \"\", x)),\n        \"...\",\n    ),\n    # tools/cpp/runfiles:runfiles.h -> tools/cpp/runfiles/runfiles.h\n    \"@bazel_tools\": ExternalRepo(lambda x: re.sub(\":\", \"/\", x), \"...\"),\n    # absl/flags:flag.h -> absl/flags/flag.h\n    \"@abseil-cpp\": ExternalRepo(lambda x: re.sub(\":\", \"/\", x), \"...\"),\n    # :re2/re2.h -> re2/re2.h\n    \"@re2\": ExternalRepo(lambda x: re.sub(\":\", \"\", x), \":re2\"),\n    # :googletest/include/gtest/gtest.h -> gtest/gtest.h\n    \"@googletest\": ExternalRepo(\n        lambda x: re.sub(\":google(?:mock|test)/include/\", \"\", x),\n        \":gtest\",\n        use_system_include=True,\n    ),\n    \"@boost.unordered\": ExternalRepo(\n        lambda x: re.sub(\"^(.*:include)/\", \"\", x),\n        \":boost.unordered\",\n        use_system_include=True,\n    ),\n}\n\nIGNORE_SOURCE_FILE_REGEX = re.compile(\n    r\"^(third_party/clangd.*|common/version.*\\.cpp\"\n    r\"|.*_autogen_manifest\\.cpp\"\n    r\"|toolchain/base/llvm_tools.def\"\n    r\"|toolchain/base/runtimes_build_info.h)$\"\n)\n\n\nclass Rule(NamedTuple):\n    # For cc_* rules:\n    # The hdrs + textual_hdrs attributes, as relative paths to the file.\n    hdrs: set[str]\n    # The srcs attribute, as relative paths to the file.\n    srcs: set[str]\n    # The deps attribute, as full bazel labels.\n    deps: set[str]\n\n    # For genrules:\n    # The outs attribute, as relative paths to the file.\n    outs: set[str]\n\n\ndef remap_file(label: str) -> str:\n    \"\"\"Remaps a bazel label to a file.\"\"\"\n    repo, _, path = label.partition(\"//\")\n    if not repo:\n        return path.replace(\":\", \"/\")\n    # Ignore the version, just use the repo name.\n    repo = repo.split(\"~\", 1)[0]\n    assert repo in EXTERNAL_REPOS, repo\n    return EXTERNAL_REPOS[repo].remap(path)\n\n\ndef get_bazel_list(list_child: ElementTree.Element, is_file: bool) -> set[str]:\n    \"\"\"Returns the contents of a bazel list.\n\n    The return will normally be the full label, unless `is_file` is set, in\n    which case the label will be translated to the underlying file.\n    \"\"\"\n    results: set[str] = set()\n    for label in list_child:\n        assert label.tag in (\"label\", \"output\"), label.tag\n        value = label.attrib[\"value\"]\n        if is_file:\n            value = remap_file(value)\n        results.add(value)\n    return results\n\n\ndef get_rules(bazel: str, targets: str, keep_going: bool) -> dict[str, Rule]:\n    \"\"\"Queries the specified targets, returning the found rules.\n\n    keep_going will be set to true for external repositories, where sometimes we\n    see query errors.\n\n    The return maps rule names to rule data.\n    \"\"\"\n    args = [\n        bazel,\n        \"query\",\n        \"--output=xml\",\n        f\"kind('(cc_binary|cc_library|cc_test|genrule)', set({targets}))\",\n    ]\n    if keep_going:\n        args.append(\"--keep_going\")\n    p = subprocess.run(\n        args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding=\"utf-8\"\n    )\n    # 3 indicates incomplete results from --keep_going, which is fine here.\n    if p.returncode not in {0, 3}:\n        print(p.stderr)\n        exit(f\"bazel query returned {p.returncode}\")\n    rules: dict[str, Rule] = {}\n    for rule_xml in ElementTree.fromstring(p.stdout):\n        assert rule_xml.tag == \"rule\", rule_xml.tag\n        rule_name = rule_xml.attrib[\"name\"]\n        hdrs: set[str] = set()\n        srcs: set[str] = set()\n        deps: set[str] = set()\n        outs: set[str] = set()\n        rule_class = rule_xml.attrib[\"class\"]\n        for list_child in rule_xml.findall(\"list\"):\n            list_name = list_child.attrib[\"name\"]\n            if rule_class in (\"cc_library\", \"cc_binary\", \"cc_test\"):\n                if list_name in (\"hdrs\", \"textual_hdrs\"):\n                    hdrs = hdrs.union(get_bazel_list(list_child, True))\n                elif list_name == \"srcs\":\n                    srcs = get_bazel_list(list_child, True)\n                elif list_name == \"deps\":\n                    deps = get_bazel_list(list_child, False)\n            elif rule_class == \"genrule\":\n                if list_name == \"outs\":\n                    outs = get_bazel_list(list_child, True)\n            elif rule_class in (\"tree_sitter_cc_library\", \"cc_library_wrapper\"):\n                # Note that `cc_library_wrapper` isn't a general rule, it is a\n                # specialized rule from inside LLVM wrapping some of its\n                # dependencies and injecting configuration macro defines.\n                continue\n            else:\n                exit(f\"unexpected rule type: {rule_class}\")\n        rules[rule_name] = Rule(hdrs, srcs, deps, outs)\n    return rules\n\n\ndef map_headers(\n    header_to_rule_map: dict[str, RuleChoice], rules: dict[str, Rule]\n) -> None:\n    \"\"\"Accumulates headers provided by rules into the map.\n\n    The map maps header paths to rule names.\n    \"\"\"\n    for rule_name, rule in rules.items():\n        repo, _, path = rule_name.partition(\"//\")\n        use_system_include = False\n        if repo in EXTERNAL_REPOS:\n            use_system_include = EXTERNAL_REPOS[repo].use_system_include\n        for header in rule.hdrs:\n            if header in header_to_rule_map:\n                header_to_rule_map[header].rules.add(rule_name)\n                if (\n                    use_system_include\n                    != header_to_rule_map[header].use_system_include\n                ):\n                    exit(\n                        \"Unexpected use_system_include inconsistency in \"\n                        f\"{header_to_rule_map[header]}\"\n                    )\n            else:\n                header_to_rule_map[header] = RuleChoice(\n                    use_system_include, {rule_name}\n                )\n\n\ndef get_missing_deps(\n    header_to_rule_map: dict[str, RuleChoice],\n    generated_files: set[str],\n    rule: Rule,\n) -> tuple[set[str], bool]:\n    \"\"\"Returns missing dependencies for the rule.\n\n    On return, the set is dependency labels that should be added; the bool\n    indicates whether some where omitted due to ambiguity.\n    \"\"\"\n    missing_deps: set[str] = set()\n    ambiguous = False\n    rule_files = rule.hdrs.union(rule.srcs)\n    for source_file in rule_files:\n        if source_file in generated_files:\n            continue\n        if IGNORE_SOURCE_FILE_REGEX.match(source_file):\n            continue\n\n        with open(source_file, \"r\") as f:\n            file_content = f.read()\n        file_content_changed = False\n\n        for header_groups in re.findall(\n            r'^(#include (?:([\"<])([^\">]+)[\">]))',\n            file_content,\n            re.MULTILINE,\n        ):\n            full_include, include_open, header = header_groups\n            is_system_include = include_open == \"<\"\n\n            if header in rule_files:\n                continue\n            if header not in header_to_rule_map:\n                if is_system_include:\n                    # Don't error for unexpected system includes.\n                    continue\n                exit(\n                    f\"Missing rule for \" f\"'{full_include}' in '{source_file}'\"\n                )\n            rule_choice = header_to_rule_map[header]\n            if not rule_choice.rules.intersection(rule.deps):\n                if len(rule_choice.rules) > 1:\n                    print(\n                        f\"Ambiguous dependency choice for \"\n                        f\"'{full_include}' in '{source_file}': \"\n                        f\"{', '.join(rule_choice.rules)}\"\n                    )\n                    ambiguous = True\n                # Use the single dep without removing it.\n                missing_deps.add(next(iter(rule_choice.rules)))\n\n            # If the include style should change, update file content.\n            if is_system_include != rule_choice.use_system_include:\n                if rule_choice.use_system_include:\n                    new_include = f\"#include <{header}>\"\n                else:\n                    new_include = f'#include \"{header}\"'\n                print(\n                    f\"Fixing include format in '{source_file}': \"\n                    f\"'{full_include}' to '{new_include}'\"\n                )\n                file_content = file_content.replace(full_include, new_include)\n                file_content_changed = True\n        if file_content_changed:\n            with open(source_file, \"w\") as f:\n                f.write(file_content)\n    return missing_deps, ambiguous\n\n\ndef main() -> None:\n    scripts_utils.chdir_repo_root()\n    bazel = scripts_utils.locate_bazel()\n\n    print(\"Querying bazel for Carbon targets...\")\n    carbon_rules = get_rules(bazel, \"//...\", False)\n    print(\"Querying bazel for external targets...\")\n    external_repo_query = \" \".join(\n        [f\"{repo}//{EXTERNAL_REPOS[repo].target}\" for repo in EXTERNAL_REPOS]\n    )\n    external_rules = get_rules(bazel, external_repo_query, True)\n\n    print(\"Building header map...\")\n    header_to_rule_map: dict[str, RuleChoice] = {}\n    map_headers(header_to_rule_map, carbon_rules)\n    map_headers(header_to_rule_map, external_rules)\n\n    print(\"Building generated file list...\")\n    generated_files: set[str] = set()\n    for rule in carbon_rules.values():\n        generated_files = generated_files.union(rule.outs)\n\n    print(\"Parsing headers from source files...\")\n    all_missing_deps: list[tuple[str, set[str]]] = []\n    any_ambiguous = False\n    for rule_name, rule in carbon_rules.items():\n        missing_deps, ambiguous = get_missing_deps(\n            header_to_rule_map, generated_files, rule\n        )\n        if missing_deps:\n            all_missing_deps.append((rule_name, missing_deps))\n        if ambiguous:\n            any_ambiguous = True\n    if any_ambiguous:\n        exit(\"Stopping due to ambiguous dependency choices.\")\n\n    if all_missing_deps:\n        print(\"Checking buildozer availability...\")\n        buildozer = scripts_utils.get_release(scripts_utils.Release.BUILDOZER)\n\n        print(\"Fixing dependencies...\")\n        SEPARATOR = \"\\n- \"\n        for rule_name, missing_deps in sorted(all_missing_deps):\n            friendly_missing_deps = SEPARATOR.join(missing_deps)\n            print(\n                f\"Adding deps to {rule_name}:{SEPARATOR}{friendly_missing_deps}\"\n            )\n            args = [\n                buildozer,\n                f\"add deps {' '.join(missing_deps)}\",\n                rule_name,\n            ]\n            subprocess.check_call(args)\n\n    print(\"Done!\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/forbid_llvm_googletest.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Detects and prevents dependencies on LLVM's googletest.\n\nCarbon uses googletest directly, and it's a significantly more recent version\nthan is provided by LLVM. Using both versions in the same binary leads to\nproblems, so this detects dependencies.\n\nWe also have some dependency checking at //bazel/check_deps. This is a separate\nscript because check_deps relies on being able to validate specific binaries\nwhich change infrequently, whereas this effectively monitors all cc_test rules,\nthe set of which is expected to be altered more often.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport subprocess\n\nimport scripts_utils\n\n_MESSAGE = \"\"\"\\\nDependencies on @llvm-project//llvm:gtest are forbidden, but a dependency path\nwas detected:\n\n%s\nCarbon uses GoogleTest through @googletest, which is a different\nversion than LLVM uses at @llvm-project//llvm:gtest. As a consequence,\ndependencies on @llvm-project//llvm:gtest must be avoided.\n\"\"\"\n\n\ndef main() -> None:\n    scripts_utils.chdir_repo_root()\n    args = [\n        scripts_utils.locate_bazel(),\n        \"query\",\n        \"somepath(\"\n        # tree_sitter is excluded here because it causes the query to failure on\n        # `@platforms`.\n        + \"//... except //utils/tree_sitter/..., \"\n        + \"@llvm-project//third-party/unittest:gtest)\",\n    ]\n    p = subprocess.run(\n        args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding=\"utf-8\"\n    )\n    if p.returncode != 0:\n        print(p.stderr)\n        exit(f\"bazel query returned {p.returncode}\")\n    if p.stdout:\n        exit(_MESSAGE % p.stdout)\n    print(\"Done!\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/lldbinit.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Initialization for lldb.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\n# This script is only meant to be used from LLDB.\nimport lldb  # type: ignore\nimport os\nimport re\nfrom typing import Any\n\nproject_root = os.path.dirname(os.path.realpath(__file__))\n\nci = lldb.debugger.GetCommandInterpreter()\nresult = lldb.SBCommandReturnObject()\n\n\ndef RunCommand(cmd: str, print_command: bool = True) -> Any:\n    \"\"\"Runs a command and prints it to the console to show that it ran.\"\"\"\n    if print_command:\n        print(f\"(lldb) {cmd}\")\n    ci.HandleCommand(cmd, result)\n    return result.GetOutput()\n\n\nRunCommand(f\"settings append target.source-map . {project_root}\")\nRunCommand(f\"settings append target.source-map /proc/self/cwd {project_root}\")\n\n# Matches the output of `print Dump(...)` and captures the stuff from inside the\n# std::string while discarding the std::string type.\ndump_re = re.compile(r'\\(std::string\\) \"([\\s\\S]+)\"', re.MULTILINE)\n\n\n# A helper to ease calling the Dump() free functions.\ndef cmd_dump(debugger: Any, command: Any, result: Any, dict: Any) -> None:\n    def print_usage() -> None:\n        print(\"\"\"\nDumps the value of an associated ID, using the C++ Dump() functions.\n\nUsage:\n  dump <CONTEXT> [<EXPR>|-- <EXPR>|<TYPE><ID>|<TYPE> <ID>]\n\nArgs:\n  CONTEXT is the dump context, such a SemIR::Context reference, a SemIR::File,\n          a Parse::Context, or a Lex::TokenizeBuffer.\n  EXPR is a C++ expression such as a variable name. Use `--` to prevent it from\n       being treated as a TYPE and ID.\n  TYPE can be `inst`, `constant`, `generic`, `impl`, `entity_name`, etc. See\n       the `Label` string in `IdBase` classes to find possible TYPE names,\n       though only Id types that have a matching `Make...Id()` function are\n       supported.\n  ID is an integer number, such as `42`, in hex, such as in `inst6000000A`. It\n       can come with a `0x` prefix, allowing easier copy-paste from raw printed\n       hex values (such as via the `p/x` lldb command).\n\nExample usage:\n  # Dumps the `inst_id` local variable, with a `context` local variable.\n  dump context inst_id\n\n  # Dumps the instruction with id 42, with a `context()` method for accessing\n  # the `Check::Context&`.\n  dump context() inst42\n\"\"\")\n\n    args = command.split(\" \")\n    if len(args) < 2:\n        print_usage()\n        return\n\n    context = args[0]\n\n    # The set of \"Make\" functions in dump.cpp.\n    id_types = {\n        \"class\": \"SemIR::MakeClassId\",\n        \"constant\": \"SemIR::MakeConstantId\",\n        \"constraint\": \"SemIR::MakeNamedConstraintId\",\n        \"symbolic_constant\": \"SemIR::MakeSymbolicConstantId\",\n        \"entity_name\": \"SemIR::MakeEntityNameId\",\n        \"facet_type\": \"SemIR::MakeFacetTypeId\",\n        \"function\": \"SemIR::MakeFunctionId\",\n        \"generic\": \"SemIR::MakeGenericId\",\n        \"impl\": \"SemIR::MakeImplId\",\n        \"inst_block\": \"SemIR::MakeInstBlockId\",\n        \"inst\": \"SemIR::MakeInstId\",\n        \"interface\": \"SemIR::MakeInterfaceId\",\n        \"name\": \"SemIR::MakeNameId\",\n        \"name_scope\": \"SemIR::MakeNameScopeId\",\n        \"identified_facet_type\": \"SemIR::MakeIdentifiedFacetTypeId\",\n        \"require_block\": \"SemIR::MakeRequireImplsBlockId\",\n        \"require\": \"SemIR::MakeRequireImplsId\",\n        \"specific\": \"SemIR::MakeSpecificId\",\n        \"specific_interface\": \"SemIR::MakeSpecificInterfaceId\",\n        \"struct_type_fields\": \"SemIR::MakeStructTypeFieldsId\",\n        \"type\": \"SemIR::MakeTypeId\",\n    }\n\n    def print_dump(context: str, expr: str) -> None:\n        cmd = f\"p Dump({context}, {expr})\"\n        out = RunCommand(cmd, print_command=False)\n        if m := re.match(dump_re, out):\n            # Use the `dump_re` match to print just the interesting part of the\n            # dump output.\n            print(m[1])\n        else:\n            # Unexpected output, show the command that was run.\n            print(f\"(lldb) {cmd}\")\n            print(out)\n\n    # Try to find a type + id from the input args. If not, the id will be passed\n    # through directly to C++, as it can be a variable name.\n    found_id_type = False\n\n    # Look for <type><id> as a single argument.\n    if m := re.fullmatch(\"([a-z_]+)(?:0x)?([0-9A-Fa-f]+)\", args[1]):\n        if m[1] in id_types:\n            if len(args) != 2:\n                print_usage()\n                return\n            make_id_fn = id_types[m[1]]\n            id = int(m[2], 16)\n            print_dump(context, f\"{make_id_fn}({id})\")\n            found_id_type = True\n\n    # Look for <type> <id> as two arguments.\n    if args[1] in id_types:\n        if len(args) != 3:\n            print_usage()\n            return\n        if m := re.fullmatch(\"(?:0x)?([0-9A-Fa-f]+)\", args[2]):\n            make_id_fn = id_types[args[1]]\n            id = int(m[1], 16)\n            print_dump(context, f\"{make_id_fn}({id})\")\n            found_id_type = True\n\n    if not found_id_type:\n        # Use `--` to escape a variable name like `inst22`.\n        if args[1] == \"--\":\n            expr = \" \".join(args[2:])\n        else:\n            expr = \" \".join(args[1:])\n        print_dump(context, expr)\n\n\ndef __lldb_init_module(debugger: Any, internal_dict: Any) -> None:\n    RunCommand(\"command script add -f lldbinit.cmd_dump dump\")\n"
  },
  {
    "path": "scripts/no_op_test.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"No-op test that should always pass.\n\nThis is designed to have the fewest avoidable dependencies to make no-op build\nand test runs in CI as inexpensive as possible.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n"
  },
  {
    "path": "scripts/query_module_versions.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Queries latest module versions from MODULE.bazel.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport json\nimport re\nimport subprocess\nimport urllib.error\nimport urllib.request\n\n\ndef _query_bazel_deps(module_text: str) -> None:\n    \"\"\"Query BCR for `bazel_dep` rule versions.\"\"\"\n    bazel_dep_re = re.compile(\n        r'bazel_dep\\([^)]*name\\s*=\\s*\"([^\"]+)\"[^)]*version\\s*='\n    )\n    packages = sorted([m[1] for m in bazel_dep_re.finditer(module_text)])\n    print(\"- BCR:\")\n    for pkg in packages:\n        try:\n            url = f\"https://bcr.bazel.build/modules/{pkg}/metadata.json\"\n            with urllib.request.urlopen(url) as response:\n                data = json.loads(response.read().decode())\n                versions = data.get(\"versions\", [])\n                print(f\"  - {pkg}: {versions[-1] if versions else 'Unknown'}\")\n        except Exception as e:\n            print(f\"  - {pkg}: Error {e}\")\n\n\ndef _query_git_overrides(module_text: str) -> None:\n    \"\"\"Query GitHub for `git_override` rule versions.\"\"\"\n    git_re = re.compile(\n        r\"git_override\\(\\s*\"\n        r'module_name\\s*=\\s*\"([^\"]+)\".*?'\n        r'remote\\s*=\\s*\"([^\"]+)\"',\n        re.DOTALL,\n    )\n    git_repos = sorted([(m[1], m[2]) for m in git_re.finditer(module_text)])\n    print(\"- Git HEAD:\")\n    for pkg, url in git_repos:\n        try:\n            output = subprocess.check_output(\n                [\"git\", \"ls-remote\", url, \"HEAD\"], text=True\n            )\n            commit = output.split()[0]\n            print(f\"  - {pkg}: {commit}\")\n        except Exception as e:\n            print(f\"  - {pkg}: Error {e}\")\n\n\ndef main() -> None:\n    with open(\"MODULE.bazel\", \"r\") as f:\n        module_text = f.read()\n\n    _query_bazel_deps(module_text)\n    _query_git_overrides(module_text)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/run_bazel.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Runs bazel on arguments.\n\nThis is provided for other scripts to run bazel without requiring it be\nmanually installed.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport argparse\nimport subprocess\nimport sys\nimport time\n\nimport scripts_utils\n\n\ndef main() -> None:\n    parser = argparse.ArgumentParser(description=\"Runs bazel.\")\n    parser.add_argument(\n        \"--attempts\",\n        metavar=\"COUNT\",\n        type=int,\n        default=1,\n        help=\"The number of attempts to execute the command, automatically \"\n        \"retrying errors that may be transient.\",\n    )\n    parser.add_argument(\n        \"--jobs-on-last-attempt\",\n        metavar=\"COUNT\",\n        type=int,\n        help=\"Sets the number of jobs in user.bazelrc on the last attempt. If \"\n        \"there is only one attempt, this will be set immediately.\",\n    )\n    parser.add_argument(\n        \"--retry-all-errors\",\n        action=\"store_true\",\n        help=\"Retries permanent errors in addition to transient.\",\n    )\n    script_args, bazel_args = parser.parse_known_args()\n\n    bazel = scripts_utils.locate_bazel()\n    attempt = 0\n    while True:\n        attempt += 1\n        if attempt == script_args.attempts and script_args.jobs_on_last_attempt:\n            with open(\"user.bazelrc\", \"a\") as bazelrc:\n                bazelrc.write(\n                    f\"build --jobs={script_args.jobs_on_last_attempt}\\n\"\n                )\n\n        p = subprocess.run([bazel] + bazel_args)\n\n        # If this was the last attempt, or it succeeded, we're done.\n        if attempt == script_args.attempts or p.returncode == 0:\n            exit(p.returncode)\n\n        # Several error codes are reliably permanent, break immediately.\n        # `1`  -- The build failed.\n        # `2`  -- Command line or environment problem.\n        # `3`  -- Tests failed or timed out, we don't retry at this layer\n        #         on execution timeout.\n        # `4`  -- Test command but no tests found.\n        # `8`  -- Explicitly interrupted build.\n        #\n        # Note that `36` is documented as \"likely permanent\", but we retry\n        # it as most of our transient failures actually produce that error\n        # code.\n        perm_error = (1, 2, 3, 4, 8)\n        if not script_args.retry_all_errors and p.returncode in perm_error:\n            exit(p.returncode)\n\n        print(\n            f\"Retrying exit code {p.returncode} because it may be transient...\"\n        )\n        # Also sleep a bit to try to skip over transient machine load.\n        time.sleep(attempt)\n\n\nif __name__ == \"__main__\":\n    try:\n        main()\n    except KeyboardInterrupt:\n        sys.exit(1)\n"
  },
  {
    "path": "scripts/run_bazelisk.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Runs bazelisk with arbitrary arguments.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport os\nimport sys\n\nimport scripts_utils\n\n\ndef main() -> None:\n    bazelisk = scripts_utils.get_release(scripts_utils.Release.BAZELISK)\n    os.execv(bazelisk, [bazelisk] + sys.argv[1:])\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/run_buildifier.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Runs buildifier on passed-in BUILD files, mainly for pre-commit.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport os\nimport sys\n\nimport scripts_utils\n\n\ndef main() -> None:\n    buildifier = scripts_utils.get_release(scripts_utils.Release.BUILDIFIER)\n    os.execv(buildifier, [buildifier] + sys.argv[1:])\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/run_buildozer.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Runs buildozer on arguments.\n\nThis is provided for other scripts to run buildozer without requiring it be\nmanually installed.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport os\nimport sys\n\nimport scripts_utils\n\n\ndef main() -> None:\n    buildozer = scripts_utils.get_release(scripts_utils.Release.BUILDOZER)\n    os.execv(buildozer, [buildozer] + sys.argv[1:])\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/scripts_utils.py",
    "content": "\"\"\"Utilities for scripts.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nfrom enum import Enum\nimport fcntl\nimport hashlib\nimport os\nfrom pathlib import Path\nimport platform\nimport shutil\nimport tempfile\nimport time\nfrom typing import NamedTuple, Optional\nimport urllib.request\n\n\n# The tools we track releases for.\nclass Release(Enum):\n    BAZELISK = \"bazelisk\"\n    BUILDIFIER = \"buildifier\"\n    BUILDOZER = \"buildozer\"\n    TARGET_DETERMINATOR = \"target-determinator\"\n\n\nclass ReleaseInfo(NamedTuple):\n    # The base URL for downloads. Should include the version.\n    url: str\n    # The separator in a binary's name, either `-` or `.`.\n    separator: str\n\n\n_BAZEL_TOOLS_URL = (\n    \"https://github.com/bazelbuild/buildtools/releases/download/v8.5.1/\"\n)\n\n# Structured information per release tool.\n_RELEASES = {\n    Release.BAZELISK: ReleaseInfo(\n        \"https://github.com/bazelbuild/bazelisk/releases/download/v1.28.1/\", \"-\"\n    ),\n    Release.BUILDIFIER: ReleaseInfo(_BAZEL_TOOLS_URL, \"-\"),\n    Release.BUILDOZER: ReleaseInfo(_BAZEL_TOOLS_URL, \"-\"),\n    Release.TARGET_DETERMINATOR: ReleaseInfo(\n        \"https://github.com/bazel-contrib/target-determinator/releases/download/v0.32.0/\",  # noqa: E501\n        \".\",\n    ),\n}\n\n\n# Shas for the tools.\n#\n# To update, change the version in a tool's URL and use\n# `calculate_release_shas.py`. This is maintained separate from _RELEASES just\n# to make copy-paste updates simpler.\n_RELEASE_SHAS = {\n    Release.BAZELISK: {\n        \"darwin-amd64\": \"023225736cea5dc88f2b0807d5b1af4eb0f69a4ed45e3994b2c18c263bc80e48\",  # noqa: E501\n        \"darwin-arm64\": \"dea3f3f5de2dbc5e269e0132cdd369d5efe738f7b973d5d4eb2b4f7055a97b39\",  # noqa: E501\n        \"linux-amd64\": \"22e7d3a188699982f661cf4687137ee52d1f24fec1ec893d91a6c4d791a75de8\",  # noqa: E501\n        \"linux-arm64\": \"8ded44b58a0d9425a4178af26cf17693feac3b87bdcfef0a2a0898fcd1afc9f2\",  # noqa: E501\n        \"windows-amd64.exe\": \"b9d65a1f7c2d7af885a96a4fd5aa36b40fb41816d30944390569eef908bdc954\",  # noqa: E501\n    },\n    Release.BUILDIFIER: {\n        \"darwin-amd64\": \"31de189e1a3fe53aa9e8c8f74a0309c325274ad19793393919e1ca65163ca1a4\",  # noqa: E501\n        \"darwin-arm64\": \"62836a9667fa0db309b0d91e840f0a3f2813a9c8ea3e44b9cd58187c90bc88ba\",  # noqa: E501\n        \"linux-amd64\": \"887377fc64d23a850f4d18a077b5db05b19913f4b99b270d193f3c7334b5a9a7\",  # noqa: E501\n        \"linux-arm64\": \"947bf6700d708026b2057b09bea09abbc3cafc15d9ecea35bb3885c4b09ccd04\",  # noqa: E501\n        \"windows-amd64.exe\": \"f4ecb9c73de2bc38b845d4ee27668f6248c4813a6647db4b4931a7556052e4e1\",  # noqa: E501\n    },\n    Release.BUILDOZER: {\n        \"darwin-amd64\": \"b85b9ad59c1543999a5d8bc8bee6e42b9f025be3ff520bc2d090213698850b43\",  # noqa: E501\n        \"darwin-arm64\": \"d0cf2f6e11031d62bfd4584e46eb6bb708a883ff948be76538b34b83de833262\",  # noqa: E501\n        \"linux-amd64\": \"2b745ca2ad41f1e01673fb59ac50af6b45ca26105c1d20fad64c3d05a95522f5\",  # noqa: E501\n        \"linux-arm64\": \"87ee1d2d81d08ccae8f9147fc58503967c85878279e892f2990912412feef1a1\",  # noqa: E501\n        \"windows-amd64.exe\": \"e177155c2c8ef41569791de34f13077cefe3e5623f9f02e099347232bc028901\",  # noqa: E501\n    },\n    Release.TARGET_DETERMINATOR: {\n        \"darwin.amd64\": \"289c61f8f4553a29d6ad2fbf1779a83180e7504c278196851becfd3f4163f6f4\",  # noqa: E501\n        \"darwin.arm64\": \"6e688292b43f99f7b76d0af0fc32ac1eec8c110571a323c7e30bcfc9ac41275c\",  # noqa: E501\n        \"linux.amd64\": \"792ed4c6f53aad60e8255686c272f28d3c039eaaef03518dbbde33519713802a\",  # noqa: E501\n        \"linux.arm64\": \"339d0b7d3c72734f435d67e9b66936261c58c02be4ce64bdb76c85f1683e8084\",  # noqa: E501\n        \"windows.amd64.exe\": \"457aba640e737edaf06d3922fa33914109dbe6382af951dfe6a99dbdf50c714c\",  # noqa: E501\n    },\n}\n\n\ndef chdir_repo_root() -> None:\n    \"\"\"Change the working directory to the repository root.\n\n    This is done so that scripts run from a consistent directory.\n    \"\"\"\n    os.chdir(Path(__file__).parents[1])\n\n\ndef _get_hash(file: Path) -> str:\n    \"\"\"Returns the sha256 of a file.\"\"\"\n    digest = hashlib.sha256()\n    with file.open(\"rb\") as f:\n        while True:\n            chunk = f.read(1024 * 64)\n            if not chunk:\n                break\n            digest.update(chunk)\n    return digest.hexdigest()\n\n\ndef _download(url: str, local_path: Path) -> Optional[int]:\n    \"\"\"Downloads the URL to the path. Returns an HTTP error code on failure.\"\"\"\n    with urllib.request.urlopen(url) as response:\n        if response.code != 200:\n            return int(response.code)\n        with local_path.open(\"wb\") as f:\n            shutil.copyfileobj(response, f)\n    return None\n\n\ndef _get_cached_binary(name: str, url: str, want_hash: str) -> str:\n    \"\"\"Returns the path to the cached binary.\n\n    If the matching version is already cached, returns it. Otherwise, downloads\n    from the URL and verifies the hash matches.\n    \"\"\"\n    cache_dir = Path.home().joinpath(\".cache\", \"carbon-lang-scripts\")\n    cache_dir.mkdir(parents=True, exist_ok=True)\n\n    # Hold a lock while checksumming and downloading the path. Otherwise,\n    # parallel runs by pre-commit may conflict with one another with\n    # simultaneous downloads.\n    with open(cache_dir.joinpath(f\"{name}.lock\"), \"w\") as lock_file:\n        fcntl.lockf(lock_file.fileno(), fcntl.LOCK_EX)\n\n        # Check if there's a cached file that can be used.\n        local_path = cache_dir.joinpath(name)\n        if local_path.is_file() and want_hash == _get_hash(local_path):\n            return str(local_path)\n\n        # Download the file.\n        retries = 5\n        while True:\n            err = _download(url, local_path)\n            if err is None:\n                break\n            retries -= 1\n            if retries == 0:\n                exit(f\"Failed to download {url}: HTTP {err}.\")\n            time.sleep(1)\n        local_path.chmod(0o755)\n\n        # Verify the downloaded hash.\n        found_hash = _get_hash(local_path)\n        if want_hash != found_hash:\n            exit(\n                f\"Downloaded {url} but found sha256 \"\n                f\"{found_hash} ({local_path.stat().st_size} bytes), wanted \"\n                f\"{want_hash}\"\n            )\n\n    return str(local_path)\n\n\ndef _get_machine() -> str:\n    machine = platform.machine()\n    if machine == \"x86_64\":\n        machine = \"amd64\"\n    elif machine == \"aarch64\":\n        machine = \"arm64\"\n    return machine\n\n\ndef _get_platform_ext() -> str:\n    if platform.system() == \"Windows\":\n        return \".exe\"\n    else:\n        return \"\"\n\n\ndef _select_hash(hashes: dict[str, str], version: str) -> str:\n    # Ensure the platform version is supported and has a hash.\n    if version not in hashes:\n        # If this because a platform support issue, we may need to print errors.\n        exit(f\"No release available for platform: {version}\")\n    return hashes[version]\n\n\ndef get_release(release: Release) -> str:\n    \"\"\"Install a tool to carbon-lang's cache and return its path.\n\n    release: The release to cache.\n    \"\"\"\n    info = _RELEASES[release]\n    shas = _RELEASE_SHAS[release]\n\n    # Translate platform information into Bazel's release form.\n    ext = _get_platform_ext()\n    platform_label = (\n        f\"{platform.system().lower()}{info.separator}{_get_machine()}{ext}\"\n    )\n    url = f\"{info.url}/{release.value}{info.separator}{platform_label}\"\n    want_hash = _select_hash(shas, platform_label)\n\n    return _get_cached_binary(f\"{release.value}{ext}\", url, want_hash)\n\n\ndef calculate_release_shas() -> None:\n    \"\"\"Prints sha information for tracked tool releases.\"\"\"\n    print(\"_RELEASE_SHAS = {\")\n    for release, info in _RELEASES.items():\n        shas = _RELEASE_SHAS[release]\n\n        print(f\"  {release}: {{\")\n        for platform_label in shas.keys():\n            url = f\"{info.url}/{release.value}{info.separator}{platform_label}\"\n            with tempfile.NamedTemporaryFile() as f:\n                path = Path(f.name)\n                _download(url, path)\n                hash = _get_hash(path)\n            print(f'    \"{platform_label}\": \"{hash}\",  # noqa: E501')\n        print(\"  },\")\n    print(\"}\")\n\n\ndef locate_bazel() -> str:\n    \"\"\"Returns the bazel command.\n\n    In order, try:\n    1. The `BAZEL` environment variable.\n    2. `bazelisk`\n    3. `bazel`\n    4. `run_bazelisk.py`\n    \"\"\"\n    bazel = os.environ.get(\"BAZEL\")\n    if bazel:\n        return bazel\n\n    for cmd in (\"bazelisk\", \"bazel\"):\n        target = shutil.which(cmd)\n        if target:\n            return target\n\n    return str(Path(__file__).parent / \"run_bazelisk.py\")\n"
  },
  {
    "path": "scripts/source_stats.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Script to compute statistics about source code.\"\"\"\n\nfrom __future__ import annotations\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport argparse\nfrom alive_progress import alive_bar  # type: ignore\nimport math\nfrom multiprocessing import Pool\nimport re\nimport termplotlib as tpl  # type: ignore\nfrom pathlib import Path\nfrom typing import Optional\nfrom dataclasses import dataclass, field, asdict\nfrom collections import Counter\n\nBLANK_RE = re.compile(r\"\\s*\")\nCOMMENT_RE = re.compile(r\"\\s*///*\\s*\")\nLINE_RE = re.compile(\n    r\"\"\"\n    (?P<class_intro>\\b(class|struct)\\s+(?P<class_name>\\w+)\\b)|\n    (?P<end_open_curly>{\\s*(?P<open_curly_trailing_comment>//.*)?)|\n    (?P<trailing_comment>//.*)|\n    (?P<internal_comment>/\\*.*\\*/)|\n    (?P<string_literal>\"([^\"]|\\\\\")*\"|'([^']|\\\\')*')|\n    (?P<float_literal>\\b(0[xb][0-9a-fA-F']*|[0-9][0-9']*)\\.[0-9a-fA-F']*([eEpP][0-9a-fA-F']*)?)|\n    (?P<int_literal>\\b(0[xb][0-9a-fA-F']+|[0-9][0-9']*)([eEpP][0-9a-fA-F']*)?)|\n    (?P<symbol>[\\[\\]{}(),.;]|[-+=!@#$%^&*/?|<>]+)|\n    (?P<keyword>\\b(auto|bool|break|case|catch|char|class|const|continue|default|do|double|else|enum|explicit|extern|false|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|nullptr|operator|private|protected|public|return|short|signed|sizeof|static|struct|switch|template|this|throw|true|try|typedef|union|unsigned|using|virtual|void|while)\\b)|\n    (?P<id>\\b\\w+\\b)\n\"\"\",\n    re.X,\n)\n\n\n@dataclass\nclass Stats:\n    \"\"\"Stats collected while scanning source files\"\"\"\n\n    lines: int = 0\n    blank_lines: int = 0\n    comment_lines: int = 0\n    empty_comment_lines: int = 0\n    comment_line_widths: Counter[int] = field(default_factory=lambda: Counter())\n    lines_with_trailing_comments: int = 0\n    classes: int = 0\n    internal_comments: int = 0\n    string_literals: int = 0\n    string_literals_per_line: Counter[int] = field(\n        default_factory=lambda: Counter()\n    )\n    int_literals: int = 0\n    int_literals_per_line: Counter[int] = field(\n        default_factory=lambda: Counter()\n    )\n    float_literals: int = 0\n    float_literals_per_line: Counter[int] = field(\n        default_factory=lambda: Counter()\n    )\n    symbols: int = 0\n    symbols_per_line: Counter[int] = field(default_factory=lambda: Counter())\n    keywords: int = 0\n    keywords_per_line: Counter[int] = field(default_factory=lambda: Counter())\n    identifiers: int = 0\n    identifier_widths: Counter[int] = field(default_factory=lambda: Counter())\n    ids_per_line: Counter[int] = field(default_factory=lambda: Counter())\n    unique_ids_per_ten_lines: Counter[int] = field(\n        default_factory=lambda: Counter()\n    )\n\n    def accumulate(self, other: Stats) -> None:\n        self.lines += other.lines\n        self.blank_lines += other.blank_lines\n        self.empty_comment_lines += other.empty_comment_lines\n        self.comment_lines += other.comment_lines\n        self.comment_line_widths.update(other.comment_line_widths)\n        self.lines_with_trailing_comments += other.lines_with_trailing_comments\n        self.classes += other.classes\n        self.internal_comments += other.internal_comments\n        self.string_literals += other.string_literals\n        self.string_literals_per_line.update(other.string_literals_per_line)\n        self.int_literals += other.int_literals\n        self.int_literals_per_line.update(other.int_literals_per_line)\n        self.float_literals += other.float_literals\n        self.float_literals_per_line.update(other.float_literals_per_line)\n        self.symbols += other.symbols\n        self.symbols_per_line.update(other.symbols_per_line)\n        self.keywords += other.keywords\n        self.keywords_per_line.update(other.keywords_per_line)\n        self.identifiers += other.identifiers\n        self.identifier_widths.update(other.identifier_widths)\n        self.ids_per_line.update(other.ids_per_line)\n        self.unique_ids_per_ten_lines.update(other.unique_ids_per_ten_lines)\n\n\ndef scan_file(file: Path) -> Stats:\n    \"\"\"Scans the provided file and accumulates stats.\"\"\"\n    stats = Stats()\n    unique_ids = set()\n    for line in file.open():\n        # Strip off the line endings.\n        line = line.rstrip(\"\\r\\n\")\n        # Skip over super long lines that are often URLs or structured data that\n        # doesn't match \"normal\" source code patterns.\n        if len(line) > 80:\n            continue\n        stats.lines += 1\n        if re.fullmatch(BLANK_RE, line):\n            stats.blank_lines += 1\n            continue\n        if m := re.match(COMMENT_RE, line):\n            stats.comment_lines += 1\n            if m.end() == len(line):\n                stats.empty_comment_lines += 1\n            else:\n                stats.comment_line_widths[len(line)] += 1\n            continue\n        line_string_literals = 0\n        line_int_literals = 0\n        line_float_literals = 0\n        line_symbols = 0\n        line_keywords = 0\n        line_identifiers = 0\n        for m in re.finditer(LINE_RE, line):\n            if m.group(\"trailing_comment\"):\n                stats.lines_with_trailing_comments += 1\n                break\n            if m.group(\"class_intro\"):\n                stats.classes += 1\n                line_keywords += 1\n                line_identifiers += 1\n                stats.identifier_widths[len(m.group(\"class_name\"))] += 1\n            elif m.group(\"end_open_curly\"):\n                line_symbols += 1\n            elif m.group(\"internal_comment\"):\n                stats.internal_comments += 1\n            elif m.group(\"string_literal\"):\n                line_string_literals += 1\n            elif m.group(\"int_literal\"):\n                line_int_literals += 1\n            elif m.group(\"float_literal\"):\n                line_float_literals += 1\n            elif m.group(\"symbol\"):\n                line_symbols += 1\n            elif m.group(\"keyword\"):\n                line_keywords += 1\n            else:\n                assert m.group(\"id\"), \"Line is '%s', and match is '%s'\" % (\n                    line,\n                    line[m.start() : m.end()],\n                )\n                line_identifiers += 1\n                stats.identifier_widths[len(m.group(\"id\"))] += 1\n                unique_ids.add(m.group(\"id\"))\n        stats.string_literals += line_string_literals\n        stats.string_literals_per_line[line_string_literals] += 1\n        stats.int_literals += line_int_literals\n        stats.int_literals_per_line[line_int_literals] += 1\n        stats.float_literals += line_float_literals\n        stats.float_literals_per_line[line_float_literals] += 1\n        stats.symbols += line_symbols\n        stats.symbols_per_line[line_symbols] += 1\n        stats.keywords += line_keywords\n        stats.keywords_per_line[line_keywords] += 1\n        stats.identifiers += line_identifiers\n        stats.ids_per_line[line_identifiers] += 1\n    if stats.lines > 0:\n        stats.unique_ids_per_ten_lines[\n            math.ceil((len(unique_ids) * 10) / stats.lines)\n        ] += 1\n    return stats\n\n\ndef parse_args(args: Optional[list[str]] = None) -> argparse.Namespace:\n    \"\"\"Parsers command-line arguments and flags.\"\"\"\n    parser = argparse.ArgumentParser(description=__doc__)\n    parser.add_argument(\n        \"files\",\n        metavar=\"FILE\",\n        type=Path,\n        nargs=\"+\",\n        help=\"A file to scan while collecting statistics.\",\n    )\n    return parser.parse_args(args=args)\n\n\ndef main() -> None:\n    parsed_args = parse_args()\n    stats = Stats()\n    with alive_bar(len(parsed_args.files)) as bar:\n        with Pool() as p:\n            for file_stats in p.imap_unordered(scan_file, parsed_args.files):\n                stats.accumulate(file_stats)\n                bar()\n\n    print(\"\"\"\n## Stats ##\nLines: %(lines)d\nBlank lines: %(blank_lines)d\nComment lines: %(comment_lines)d\nEmpty comment lines: %(empty_comment_lines)d\nLines with trailing comments: %(lines_with_trailing_comments)d\nClasses: %(classes)d\nInternal comments: %(internal_comments)d\nString literals: %(string_literals)d\nInt literals: %(int_literals)d\nFloat literals: %(float_literals)d\nSymbols: %(symbols)d\nKeywords: %(keywords)d\nIDs: %(identifiers)d\"\"\" % asdict(stats))\n\n    tokens = (\n        stats.string_literals\n        + stats.int_literals\n        + stats.float_literals\n        + stats.symbols\n        + stats.keywords\n        + stats.identifiers\n    )\n    print(f\"\"\"\nFraction of blank lines: {stats.blank_lines / stats.lines}\nFraction of comment lines: {stats.comment_lines / stats.lines}\n\nTotal counted tokens: {tokens}\nFraction string literals: {stats.string_literals / tokens}\nFraction int literals: {stats.int_literals / tokens}\nFraction float literals: {stats.float_literals / tokens}\nFraction symbols: {stats.symbols / tokens}\nFraction keywords: {stats.keywords / tokens}\nFraction IDs: {stats.identifiers / tokens}\n    \"\"\")\n\n    def print_histogram(\n        title: str, data: dict[int, int], column_format: str\n    ) -> None:\n        print()\n        key_min = min(data.keys())\n        key_max = max(data.keys()) + 1\n        values = [data.get(k, 0) for k in range(key_min, key_max)]\n        keys = [column_format % k for k in range(key_min, key_max)]\n        total = sum(values)\n        median = key_min\n        p90 = key_min\n        p95 = key_min\n        p99 = key_min\n        count = total\n        for k in range(key_min, key_max):\n            count -= data.get(k, 0)\n            if median == key_min and count <= total / 2:\n                median = k\n            if p90 == key_min and count <= total / 10:\n                p90 = k\n            if p95 == key_min and count <= total / 20:\n                p95 = k\n            if p99 == key_min and count <= total / 100:\n                p99 = k\n\n        print(\n            title + f\" (median: {median}, p90: {p90}, p95: {p95}, p99: {p99})\"\n        )\n        fig = tpl.figure()\n        fig.barh(values, keys)\n        fig.show()\n\n    print_histogram(\n        \"## Comment line widths ##\", stats.comment_line_widths, \"%d columns\"\n    )\n\n    print_histogram(\n        \"## String literals per line ##\",\n        stats.string_literals_per_line,\n        \"%d literals\",\n    )\n    print_histogram(\n        \"## Int literals per line ##\",\n        stats.int_literals_per_line,\n        \"%d literals\",\n    )\n    print_histogram(\n        \"## Float literals per line ##\",\n        stats.float_literals_per_line,\n        \"%d literals\",\n    )\n    print_histogram(\n        \"## Symbols per line ##\", stats.symbols_per_line, \"%d symbols\"\n    )\n    print_histogram(\n        \"## Keywords per line ##\", stats.keywords_per_line, \"%d keywords\"\n    )\n\n    print_histogram(\"## ID widths ##\", stats.identifier_widths, \"%d characters\")\n    print_histogram(\"## IDs per line ##\", stats.ids_per_line, \"%d ids\")\n    print_histogram(\n        \"## Unique IDs per 10 lines ##\",\n        stats.unique_ids_per_ten_lines,\n        \"%d ids\",\n    )\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/sync_repos.sh",
    "content": "#!/usr/bin/env bash\n#\n# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n#\n# Sync directories in the main Carbon repository into dedicated child\n# repositories to better match repository-oriented installing and tooling.\n\nset -eux\n\nORIGIN_DIR=\"$PWD\"\nCOMMIT_SHA=\"$(git rev-parse --short $GITHUB_SHA)\"\nCOMMIT_SUMMARY=\"Original $(git show -s --pretty=full \"$COMMIT_SHA\")\n\n$(git diff --summary \"${COMMIT_SHA}^!\")\n\"\n\n# Setup global git configuration.\nGIT_USERNAME=\"CarbonInfraBot\"\ngit config --global user.email \"carbon-external-infra@google.com\"\ngit config --global user.name \"$GIT_USERNAME\"\n\ndeclare -A MIRRORS\nMIRRORS[\"utils/vim\"]=\"vim-carbon-lang\"\n\nfor dir in \"${!MIRRORS[@]}\"; do\n  SRC_DIR=\"$dir\"\n  DEST_REPO=\"${MIRRORS[$SRC_DIR]}\"\n  DEST_REPO_URL=\"https://$GIT_USERNAME:$API_TOKEN_GITHUB@github.com/carbon-language/$DEST_REPO.git\"\n  DEST_CLONE_DIR=\"$(mktemp -d)\"\n\n  git clone --single-branch \"$DEST_REPO_URL\" \"$DEST_CLONE_DIR\"\n  cd \"$DEST_CLONE_DIR\"\n\n  # Print out the destination repository to help with debugging failures in\n  # GitHub's actions.\n  ls -al\n\n  # Remove all the existing files to rebuild it from scratch. We ignore when\n  # this matches no files to handle freshly created repositories. Also print the\n  # status afterward for debugging.\n  git rm --ignore-unmatch -r .\n  git status\n\n  # Copy the basic framework from the origin repository.\n  cp \"$ORIGIN_DIR/.gitignore\" \\\n    \"$ORIGIN_DIR/CODE_OF_CONDUCT.md\" \\\n    \"$ORIGIN_DIR/LICENSE\" \\\n    .\n\n  # Copy the mirrored directory. We use `rsync` to get a more reliable way of\n  # handling the mirroring of the contents of a directory. We also make this\n  # verbose to help with debugging action failures on GitHub.\n  rsync -av \"$ORIGIN_DIR/$SRC_DIR/\" .\n\n  # Add back all the files now, and print the status for debugging.\n  git add -A\n  git status\n\n  # See if there is anything to commit and push. This works the same way as\n  # diff(1) and so exits zero when there are no changes.\n  if ! git diff --cached --quiet; then\n    # Commit the new state.\n    git commit -F- <<EOF\nSync $DEST_REPO to carbon-language/carbon-lang@$COMMIT_SHA\n\n$COMMIT_SUMMARY\nEOF\n    git log\n\n    # Push the new commit.\n    git push\n  fi\n\n  # Cleanup.\n  cd \"$ORIGIN_DIR\"\n  rm -rf \"$DEST_CLONE_DIR\"\ndone\n"
  },
  {
    "path": "scripts/target_determinator.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Computes the potentially differing rules from some git commit.\n\nWraps the \"target-determinator\" Go program here:\nhttps://github.com/bazel-contrib/target-determinator\n\nThe purpose is to compute the potentially impacted set of targets from some\nprovided Git commit to the current checkout.\n\nThis script will ensure a cached version of the latest release is available, and\nthen forward a limited set of flags to it. This script also filters the\nresulting targets using `bazel query` to make it the most relevant list for\ncontinuous integration.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport subprocess\nimport argparse\nimport tempfile\nimport sys\nfrom pathlib import Path\n\nimport scripts_utils\n\n\ndef log(s: str) -> None:\n    print(s, file=sys.stderr)\n\n\ndef filter_targets(bazel: Path, targets: str) -> str:\n    # Need to quote targets for inclusion in another query.\n    quoted_targets = \"\\n\".join([f'\"{t}\"' for t in targets.splitlines()])\n\n    with tempfile.NamedTemporaryFile(mode=\"w+\") as tmp:\n        query = (\n            f\"let t = set({quoted_targets}) in \"\n            \"kind(rule, $t) except attr(tags, manual, $t)\\n\"\n        )\n        query_lines = query.splitlines()\n        if len(query_lines) <= 10:\n            query_snippet = \"\\n\".join(query_lines)\n        else:\n            query_snippet = \"\\n\".join(\n                query_lines[:5] + [\"...\"] + query_lines[-5:]\n            )\n        log(f\"Bazel query snippet:\\n```\\n{query_snippet}\\n```\")\n        tmp.write(query)\n        tmp.flush()\n        try:\n            p = subprocess.run(\n                [str(bazel), \"query\", f\"--query_file={tmp.name}\"],\n                stdout=subprocess.PIPE,\n                stderr=subprocess.PIPE,\n                check=True,\n                encoding=\"utf-8\",\n            )\n            return p.stdout\n        except subprocess.CalledProcessError as err:\n            log(err.stderr)\n            log(\"Full query file:\\n```\")\n            with open(tmp.name) as f:\n                log(f.read())\n            log(\"```\")\n            raise\n\n\ndef main() -> None:\n    parser = argparse.ArgumentParser(__doc__)\n    parser.add_argument(\n        \"baseline\", nargs=1, help=\"Git commit of the diff baseline.\"\n    )\n    parser.add_argument(\n        \"args\",\n        nargs=\"*\",\n        help=\"Remaining args to forward to the underlying tool.\",\n    )\n    parsed_args = parser.parse_args()\n\n    scripts_utils.chdir_repo_root()\n    bazel = Path(scripts_utils.locate_bazel())\n    target_determinator = scripts_utils.get_release(\n        scripts_utils.Release.TARGET_DETERMINATOR\n    )\n    p = subprocess.run(\n        [\n            target_determinator,\n            f\"--bazel={bazel}\",\n            parsed_args.baseline[0],\n        ]\n        + parsed_args.args,\n        check=True,\n        stdout=subprocess.PIPE,\n        encoding=\"utf-8\",\n    )\n\n    targets = p.stdout\n    if targets.strip() != \"\":\n        targets = filter_targets(bazel, targets)\n    log(f\"Found {len(targets.splitlines())} impacted targets!\")\n\n    print(targets.rstrip())\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scripts/workspace_status.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Bazel `--workspace_status_command` script.\n\nThis script is designed to be used in Bazel`s `--workspace_status_command` and\ngenerate any desirable status artifacts.\n\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport subprocess\n\n\ndef git_commit_sha() -> str:\n    return subprocess.check_output(\n        [\"git\", \"rev-parse\", \"--short\", \"HEAD\"], encoding=\"utf-8\"\n    ).strip()\n\n\ndef git_dirty_suffix() -> str:\n    status = subprocess.check_output(\n        [\"git\", \"status\", \"--porcelain\"], encoding=\"utf-8\"\n    ).strip()\n    return \".dirty\" if len(status) > 0 else \"\"\n\n\ndef main() -> None:\n    print(\"STABLE_GIT_COMMIT_SHA \" + git_commit_sha())\n    print(\"STABLE_GIT_DIRTY_SUFFIX \" + git_dirty_suffix())\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "setup.cfg",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n[flake8]\nmax-line-length = 80\n# E203: This warning is not PEP 8 compliant.\nextend-ignore = E203\n\n[mypy]\npretty = True\n# Define flags relative to strict mode.\nstrict = True\n# TODO: Look at updating code to fix these.\ndisallow_any_generics = False\n"
  },
  {
    "path": "testing/README.md",
    "content": "# Testing\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nTesting-specific libraries.\n"
  },
  {
    "path": "testing/base/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n#\n# Trivial, single-file testing libraries. More complex libraries should get\n# their own directory.\n\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_binary\", \"cc_library\", \"cc_test\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\n# This does extra initialization on top of googletest's gtest_main in order to\n# provide stack traces on unexpected exits, because we normally rely on LLVM\n# code for that.\n#\n# This replaces \"@googletest//:gtest_main\";\n# \"@googletest//:gtest\" should still be used directly.\ncc_library(\n    name = \"gtest_main\",\n    testonly = 1,\n    srcs = [\"gtest_main.cpp\"],\n    deps = [\n        \":global_exe_path\",\n        \"//common:init_llvm\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\n# This does extra initialization on top of Google benchmark's main in order to\n# provide stack traces and setup LLVM.\n#\n# This replaces `@google_benchmark//:benchmark_main`;\n# `@google_benchmark//:benchmark` should still be used directly.\ncc_library(\n    name = \"benchmark_main\",\n    testonly = 1,\n    srcs = [\"benchmark_main.cpp\"],\n    deps = [\n        \":global_exe_path\",\n        \"//common:init_llvm\",\n        \"@abseil-cpp//absl/flags:parse\",\n        \"@google_benchmark//:benchmark\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"capture_std_streams\",\n    testonly = 1,\n    srcs = [\"capture_std_streams.cpp\"],\n    hdrs = [\"capture_std_streams.h\"],\n    deps = [\n        \"//common:ostream\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"source_gen_lib\",\n    testonly = 1,\n    srcs = [\"source_gen.cpp\"],\n    hdrs = [\"source_gen.h\"],\n    deps = [\n        \"//common:check\",\n        \"//common:map\",\n        \"//common:raw_string_ostream\",\n        \"//common:set\",\n        \"//toolchain/lex:token_kind\",\n        \"@abseil-cpp//absl/random\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"source_gen_test\",\n    size = \"small\",\n    srcs = [\"source_gen_test.cpp\"],\n    deps = [\n        \":global_exe_path\",\n        \":gtest_main\",\n        \":source_gen_lib\",\n        \"//common:all_llvm_targets\",\n        \"//common:set\",\n        \"//toolchain/base:install_paths_test_helpers\",\n        \"//toolchain/driver\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_binary(\n    name = \"source_gen\",\n    testonly = 1,\n    srcs = [\"source_gen_main.cpp\"],\n    deps = [\n        \":source_gen_lib\",\n        \"//common:bazel_working_dir\",\n        \"//common:command_line\",\n        \"//common:init_llvm\",\n        \"//common:ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"file_helpers\",\n    testonly = 1,\n    srcs = [\"file_helpers.cpp\"],\n    hdrs = [\"file_helpers.h\"],\n    deps = [\n        \"//common:error\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"global_exe_path\",\n    testonly = 1,\n    srcs = [\"global_exe_path.cpp\"],\n    hdrs = [\"global_exe_path.h\"],\n    deps = [\n        \"//common:check\",\n        \"//common:exe_path\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"global_exe_path_test\",\n    size = \"small\",\n    srcs = [\"global_exe_path_test.cpp\"],\n    deps = [\n        \":global_exe_path\",\n        \":gtest_main\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"unified_diff_matcher\",\n    testonly = 1,\n    hdrs = [\"unified_diff_matcher.h\"],\n    deps = [\n        \"//common:check\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"unified_diff_matcher_test\",\n    size = \"small\",\n    srcs = [\"unified_diff_matcher_test.cpp\"],\n    deps = [\n        \":gtest_main\",\n        \":unified_diff_matcher\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n"
  },
  {
    "path": "testing/base/benchmark_main.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <benchmark/benchmark.h>\n\n#include \"absl/flags/parse.h\"\n#include \"common/init_llvm.h\"\n#include \"testing/base/global_exe_path.h\"\n\nauto main(int orig_argc, char** orig_argv) -> int {\n  // Do LLVM's initialization first, this will also transform UTF-16 to UTF-8.\n  Carbon::InitLLVM init_llvm(orig_argc, orig_argv);\n\n  Carbon::Testing::SetExePath(orig_argv[0]);\n\n  // Inject a flag to override the defaults for benchmarks. This can still be\n  // disabled by user arguments.\n  llvm::SmallVector<char*> injected_argv_storage(orig_argv,\n                                                 orig_argv + orig_argc + 1);\n  char injected_flag[] = \"--benchmark_counters_tabular\";\n  injected_argv_storage.insert(injected_argv_storage.begin() + 1,\n                               injected_flag);\n  char** argv = injected_argv_storage.data();\n  int argc = injected_argv_storage.size() - 1;\n\n  benchmark::Initialize(&argc, argv);\n  absl::ParseCommandLine(argc, argv);\n  benchmark::RunSpecifiedBenchmarks();\n  benchmark::Shutdown();\n  return 0;\n}\n"
  },
  {
    "path": "testing/base/capture_std_streams.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/base/capture_std_streams.h\"\n\n#include <gtest/gtest.h>\n\n#include <fstream>\n#include <sstream>\n#include <string>\n\n#include \"common/ostream.h\"\n\nnamespace Carbon::Testing::Internal {\n\n// While these are marked as \"internal\" APIs, they seem to work and be pretty\n// widely used for their exact documented behavior.\nusing ::testing::internal::CaptureStderr;\nusing ::testing::internal::CaptureStdout;\nusing ::testing::internal::GetCapturedStderr;\nusing ::testing::internal::GetCapturedStdout;\n\nauto BeginStdStreamCapture() -> void {\n  CaptureStderr();\n  CaptureStdout();\n}\nauto EndStdStreamCapture(std::string& out, std::string& err) -> void {\n  // No need to flush stderr.\n  err = GetCapturedStderr();\n  llvm::outs().flush();\n  out = GetCapturedStdout();\n}\n\n}  // namespace Carbon::Testing::Internal\n"
  },
  {
    "path": "testing/base/capture_std_streams.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_BASE_CAPTURE_STD_STREAMS_H_\n#define CARBON_TESTING_BASE_CAPTURE_STD_STREAMS_H_\n\n#include <string>\n\nnamespace Carbon::Testing {\n\n// Implementation details.\nnamespace Internal {\nauto BeginStdStreamCapture() -> void;\nauto EndStdStreamCapture(std::string& out, std::string& err) -> void;\n}  // namespace Internal\n\n// Calls the provided function while capturing both `stdout` and `stderr`. The\n// `out` and `err` strings are set to whatever is captured after the function\n// returns.\n//\n// Note that any output that is captured will not be visible when running, which\n// can make debugging tests that use this routine difficult. Make sure to either\n// print back out or otherwise expose any of the contents of the captured output\n// that are needed when debugging.\ntemplate <typename FnT>\nstatic auto CallWithCapturedOutput(std::string& out, std::string& err,\n                                   FnT function) -> auto {\n  Internal::BeginStdStreamCapture();\n  auto result = function();\n  Internal::EndStdStreamCapture(out, err);\n  return result;\n}\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_BASE_CAPTURE_STD_STREAMS_H_\n"
  },
  {
    "path": "testing/base/file_helpers.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/base/file_helpers.h\"\n\n#include <gtest/gtest.h>\n\n#include <cstdlib>\n#include <fstream>\n#include <sstream>\n#include <string>\n#include <system_error>\n\nnamespace Carbon::Testing {\n\nauto GetTempDirectory() -> std::filesystem::path {\n  if (char* tmpdir_env = getenv(\"TEST_TMPDIR\"); tmpdir_env != nullptr) {\n    return tmpdir_env;\n  } else {\n    return std::filesystem::temp_directory_path();\n  }\n}\n\nauto ReadFile(std::filesystem::path path) -> ErrorOr<std::string> {\n  std::ifstream file_stream(path);\n  if (file_stream.fail()) {\n    return Error(llvm::formatv(\"Error opening file: {0}\", path));\n  }\n  std::stringstream buffer;\n  buffer << file_stream.rdbuf();\n  if (file_stream.fail()) {\n    return Error(llvm::formatv(\"Error reading file: {0}\", path));\n  }\n  return buffer.str();\n}\n\nauto WriteTestFile(llvm::StringRef name, llvm::StringRef contents)\n    -> ErrorOr<std::filesystem::path> {\n  std::filesystem::path test_tmpdir = GetTempDirectory();\n  const auto* unit_test = ::testing::UnitTest::GetInstance();\n  const auto* test_info = unit_test->current_test_info();\n  std::filesystem::path test_file =\n      test_tmpdir / llvm::formatv(\"{0}_{1}_{2}\", test_info->test_suite_name(),\n                                  test_info->name(), name)\n                        .str();\n  // Make debugging a bit easier by cleaning up any files from previous runs.\n  // This is only necessary when not run in Bazel's test environment.\n  std::filesystem::remove(test_file);\n  if (std::filesystem::exists(test_file)) {\n    return Error(\n        llvm::formatv(\"Unable to remove an existing file: {0}\", test_file));\n  }\n\n  std::error_code ec;\n  llvm::raw_fd_ostream test_file_stream(test_file.string(), ec);\n  if (ec) {\n    return Error(llvm::formatv(\"Test file error: {0}\", ec.message()));\n  }\n  test_file_stream << contents;\n\n  return test_file;\n}\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/base/file_helpers.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_BASE_FILE_HELPERS_H_\n#define CARBON_TESTING_BASE_FILE_HELPERS_H_\n\n#include <filesystem>\n#include <string>\n\n#include \"common/error.h\"\n\nnamespace Carbon::Testing {\n\n// Returns a directory that should be used to hold temporary files created by\n// test execution.\nauto GetTempDirectory() -> std::filesystem::path;\n\n// Reads a file to string.\nauto ReadFile(std::filesystem::path path) -> ErrorOr<std::string>;\n\n// Writes a test file to disk and returns an error or the full path to the file.\n//\n// Note that this expects to be run from within a GoogleTest test, and relies on\n// global state of GoogleTest.\n//\n// This locates a suitable temporary directory for the test, creates a file with\n// the requested name in that directory, and writes the provided content to that\n// file. The full path to the written file is returned.\n//\n// Where possible, this will use a Bazel-provided test temporary directory.\n// However, if unavailable, it falls back to a system temporary directory. This\n// helps tests be runnable outside of Bazel, for example under a debugger. It\n// also works to create test file names that are unlikely to conflict with other\n// tests when run.\nauto WriteTestFile(llvm::StringRef name, llvm::StringRef contents)\n    -> ErrorOr<std::filesystem::path>;\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_BASE_FILE_HELPERS_H_\n"
  },
  {
    "path": "testing/base/global_exe_path.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/base/global_exe_path.h\"\n\n#include <optional>\n#include <string>\n\n#include \"common/check.h\"\n#include \"common/exe_path.h\"\n\nstatic constinit std::optional<std::string> exe_path = {};\n\nnamespace Carbon::Testing {\n\nauto GetExePath() -> llvm::StringRef {\n  CARBON_CHECK(\n      exe_path,\n      \"Must not query the executable path until after it has been set!\");\n  return *exe_path;\n}\n\nauto SetExePath(const char* argv_zero) -> void {\n  CARBON_CHECK(!exe_path, \"Must not call `SetExePath` more than once!\");\n  exe_path.emplace(Carbon::FindExecutablePath(argv_zero));\n}\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/base/global_exe_path.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_BASE_GLOBAL_EXE_PATH_H_\n#define CARBON_TESTING_BASE_GLOBAL_EXE_PATH_H_\n\n#include \"llvm/ADT/StringRef.h\"\n\n// When using the Carbon `main` function for GoogleTest, we export some extra\n// information about the test binary that can be accessed with this header.\n\nnamespace Carbon::Testing {\n\n// The executable path of the test binary.\nauto GetExePath() -> llvm::StringRef;\n\n// Sets the executable path of a test binary from its `argv[0]`.\n//\n// This function must only be called once for an execution, and before any\n// callers to `GetExePath`. Typically, it is called from within `main`.\nauto SetExePath(const char* argv_zero) -> void;\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_BASE_GLOBAL_EXE_PATH_H_\n"
  },
  {
    "path": "testing/base/global_exe_path_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/base/global_exe_path.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include \"llvm/Support/FileSystem.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing ::testing::StrNe;\n\nTEST(TestExePathTest, Test) {\n  llvm::StringRef exe_path = GetExePath();\n  EXPECT_THAT(exe_path, StrNe(\"\"));\n  EXPECT_TRUE(llvm::sys::fs::exists(exe_path));\n  EXPECT_TRUE(llvm::sys::fs::can_execute(exe_path));\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/base/gtest_main.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <gtest/gtest.h>\n\n#include \"common/init_llvm.h\"\n#include \"testing/base/global_exe_path.h\"\n\nauto main(int argc, char** argv) -> int {\n  // Initialize LLVM first, as that will also handle ensuring UTF-8 encoding.\n  Carbon::InitLLVM init_llvm(argc, argv);\n\n  Carbon::Testing::SetExePath(argv[0]);\n  testing::InitGoogleTest(&argc, argv);\n  return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "testing/base/source_gen.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/base/source_gen.h\"\n\n#include <algorithm>\n#include <array>\n#include <numeric>\n#include <string>\n#include <utility>\n\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/Sequence.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n#include \"toolchain/lex/token_kind.h\"\n\nnamespace Carbon::Testing {\n\nauto SourceGen::Global() -> SourceGen& {\n  static SourceGen global_gen;\n  return global_gen;\n}\n\nSourceGen::SourceGen(Language language) : language_(language) {}\n\n// Heuristic numbers used in synthesizing various identifier sequences.\nstatic constexpr int MinClassNameLength = 5;\nstatic constexpr int MinMemberNameLength = 4;\n\n// The shuffled state used to generate some number of classes.\n//\n// This state encodes everything used to generate class definitions. The state\n// will be consumed until empty.\n//\n// Detailed comments for out-of-line methods are on their definitions.\nclass SourceGen::ClassGenState {\n public:\n  ClassGenState(SourceGen& gen, int num_classes,\n                const ClassParams& class_params,\n                const TypeUseParams& type_use_params);\n\n  auto public_function_param_counts() -> llvm::SmallVectorImpl<int>& {\n    return public_function_param_counts_;\n  }\n  auto public_method_param_counts() -> llvm::SmallVectorImpl<int>& {\n    return public_method_param_counts_;\n  }\n  auto private_function_param_counts() -> llvm::SmallVectorImpl<int>& {\n    return private_function_param_counts_;\n  }\n  auto private_method_param_counts() -> llvm::SmallVectorImpl<int>& {\n    return private_method_param_counts_;\n  }\n\n  auto class_names() -> llvm::SmallVectorImpl<llvm::StringRef>& {\n    return class_names_;\n  }\n  auto member_names() -> llvm::SmallVectorImpl<llvm::StringRef>& {\n    return member_names_;\n  }\n  auto param_names() -> llvm::SmallVectorImpl<llvm::StringRef>& {\n    return param_names_;\n  }\n\n  auto type_names() -> llvm::SmallVectorImpl<llvm::StringRef>& {\n    return type_names_;\n  }\n\n  auto AddValidTypeName(llvm::StringRef type_name) -> void {\n    valid_type_names_.Insert(type_name);\n  }\n\n  auto GetValidTypeName() -> llvm::StringRef;\n\n private:\n  auto BuildClassAndTypeNames(SourceGen& gen, int num_classes, int num_types,\n                              const TypeUseParams& type_use_params) -> void;\n\n  llvm::SmallVector<int> public_function_param_counts_;\n  llvm::SmallVector<int> public_method_param_counts_;\n  llvm::SmallVector<int> private_function_param_counts_;\n  llvm::SmallVector<int> private_method_param_counts_;\n\n  llvm::SmallVector<llvm::StringRef> class_names_;\n  llvm::SmallVector<llvm::StringRef> member_names_;\n  llvm::SmallVector<llvm::StringRef> param_names_;\n\n  llvm::SmallVector<llvm::StringRef> type_names_;\n  Set<llvm::StringRef> valid_type_names_;\n  int last_type_name_index_ = 0;\n};\n\n// A helper to sum elements of a range.\ntemplate <typename T>\nstatic auto Sum(const T& range) -> int {\n  return std::accumulate(range.begin(), range.end(), 0);\n}\n\n// Given a number of class definitions and the params with which to generate\n// them, builds the state that will be used while generating that many classes.\n//\n// We build the state first and across all the class definitions that will be\n// generated so that we can distribute random components across all the\n// definitions.\nSourceGen::ClassGenState::ClassGenState(SourceGen& gen, int num_classes,\n                                        const ClassParams& class_params,\n                                        const TypeUseParams& type_use_params) {\n  public_function_param_counts_ =\n      gen.GetShuffledInts(num_classes * class_params.public_function_decls, 0,\n                          class_params.public_function_decl_params.max_params);\n  public_method_param_counts_ =\n      gen.GetShuffledInts(num_classes * class_params.public_method_decls, 0,\n                          class_params.public_method_decl_params.max_params);\n  private_function_param_counts_ =\n      gen.GetShuffledInts(num_classes * class_params.private_function_decls, 0,\n                          class_params.private_function_decl_params.max_params);\n  private_method_param_counts_ =\n      gen.GetShuffledInts(num_classes * class_params.private_method_decls, 0,\n                          class_params.private_method_decl_params.max_params);\n\n  int num_members =\n      num_classes *\n      (class_params.public_function_decls + class_params.public_method_decls +\n       class_params.private_function_decls + class_params.private_method_decls +\n       class_params.private_field_decls);\n  member_names_ = gen.GetShuffledIdentifiers(\n      num_members, /*min_length=*/MinMemberNameLength);\n  int num_params =\n      Sum(public_function_param_counts_) + Sum(public_method_param_counts_) +\n      Sum(private_function_param_counts_) + Sum(private_method_param_counts_);\n  param_names_ = gen.GetShuffledIdentifiers(num_params);\n\n  BuildClassAndTypeNames(gen, num_classes, num_members + num_params,\n                         type_use_params);\n}\n\nauto SourceGen::ClassGenState::GetValidTypeName() -> llvm::StringRef {\n  // Check that we don't completely wrap the type names by tracking where we\n  // started.\n  int initial_last_type_name_index = last_type_name_index_;\n\n  // Now search the type names, starting from the last used index, to find the\n  // first valid name.\n  for (;;) {\n    if (last_type_name_index_ == 0) {\n      last_type_name_index_ = type_names_.size();\n    }\n    --last_type_name_index_;\n    llvm::StringRef& type_name = type_names_[last_type_name_index_];\n    if (valid_type_names_.Contains(type_name)) {\n      // Found a valid type name, swap it with the back and pop that off.\n      std::swap(type_names_.back(), type_name);\n      return type_names_.pop_back_val();\n    }\n\n    CARBON_CHECK(last_type_name_index_ != initial_last_type_name_index,\n                 \"Failed to find a valid type name with {0} candidates, an \"\n                 \"initial index of {1}, and with {2} classes left to emit!\",\n                 type_names_.size(), initial_last_type_name_index,\n                 class_names_.size());\n  }\n}\n\n// Build both the class names this file will declare and a list of type\n// references to use throughout those classes.\n//\n// We combine a list of fixed types in the `type_use_params` with the list of\n// class names that will be defined to form the spelling of all the referenced\n// types. The `type_use_params` provides weights for each fixed type as well as\n// an overall weight for referencing class names that are being declared. We\n// build a set of type references so that its histogram will roughly match these\n// weights.\n//\n// For each of the fixed types, `type_use_params` provides a spelling for both\n// Carbon and C++.\n//\n// We distribute our references to declared class names evenly to the extent\n// possible.\n//\n// Before all the references are formed, the class names are kept their original\n// unshuffled order. This ensures that any uneven sampling of names is done\n// deterministically. At the end, we randomly shuffle the sequences of both the\n// declared class names and type references to provide an unpredictable order in\n// the generated output.\nauto SourceGen::ClassGenState::BuildClassAndTypeNames(\n    SourceGen& gen, int num_classes, int num_types,\n    const TypeUseParams& type_use_params) -> void {\n  // Initially get the sequence of class names without shuffling so we can\n  // compute our type name pool from them prior to any shuffling.\n  class_names_ =\n      gen.GetUniqueIdentifiers(num_classes, /*min_length=*/MinClassNameLength);\n\n  type_names_.reserve(num_types);\n\n  // Compute the sum of weights and pre-process the fixed types.\n  int type_weight_sum = type_use_params.declared_types_weight;\n  for (const auto& fixed_type_weight : type_use_params.fixed_type_weights) {\n    type_weight_sum += fixed_type_weight.weight;\n    // Add all the fixed type spellings as immediately valid.\n    valid_type_names_.Insert(gen.IsCpp() ? fixed_type_weight.cpp_spelling\n                                         : fixed_type_weight.carbon_spelling);\n  }\n\n  // Compute the number of declared types used. We expect to have a decent\n  // number of repeated names, so we repeatedly append the entire sequence of\n  // class names until there is some remainder of names needed.\n  int num_declared_types =\n      num_types * type_use_params.declared_types_weight / type_weight_sum;\n  for ([[maybe_unused]] auto _ : llvm::seq(num_declared_types / num_classes)) {\n    llvm::append_range(type_names_, class_names_);\n  }\n  // Now append the remainder number of class names. This is where the class\n  // names being un-shuffled is essential. We're going to have one extra\n  // reference to some fraction of the class names and we want that to be a\n  // stable subset.\n  type_names_.append(class_names_.begin(),\n                     class_names_.begin() + (num_declared_types % num_classes));\n  CARBON_CHECK(static_cast<int>(type_names_.size()) == num_declared_types);\n\n  // Use each fixed type weight to append the expected number of copies of that\n  // type. This isn't exact however, and is designed to stop short.\n  for (const auto& fixed_type_weight : type_use_params.fixed_type_weights) {\n    int num_fixed_type = num_types * fixed_type_weight.weight / type_weight_sum;\n    type_names_.append(num_fixed_type, gen.IsCpp()\n                                           ? fixed_type_weight.cpp_spelling\n                                           : fixed_type_weight.carbon_spelling);\n  }\n\n  // If we need a tail of types to hit the exact number, simply round-robin\n  // through the fixed types without any weighting. With reasonably large\n  // numbers of types this won't distort the distribution in an interesting way\n  // and is simpler than trying to scale the distribution down.\n  while (static_cast<int>(type_names_.size()) < num_types) {\n    for (const auto& fixed_type_weight :\n         llvm::ArrayRef(type_use_params.fixed_type_weights)\n             .take_front(num_types - type_names_.size())) {\n      type_names_.push_back(gen.IsCpp() ? fixed_type_weight.cpp_spelling\n                                        : fixed_type_weight.carbon_spelling);\n    }\n  }\n  CARBON_CHECK(static_cast<int>(type_names_.size()) == num_types);\n  last_type_name_index_ = num_types;\n\n  // Now shuffle both the class names and the type names.\n  std::shuffle(class_names_.begin(), class_names_.end(), gen.rng_);\n  std::shuffle(type_names_.begin(), type_names_.end(), gen.rng_);\n}\n\n// Some heuristic numbers used when formatting generated code. These heuristics\n// are loosely based on what we expect to make Carbon code readable, and might\n// not fit as well in C++, but we use the same heuristics across languages for\n// simplicity and to make the output in different languages more directly\n// comparable.\nstatic constexpr int NumSingleLineFunctionParams = 3;\nstatic constexpr int NumSingleLineMethodParams = 2;\nstatic constexpr int MaxParamsPerLine = 4;\n\nstatic auto EstimateAvgFunctionDeclLines(SourceGen::FunctionDeclParams params)\n    -> double {\n  // Currently model a uniform distribution [0, max] parameters. Assume a line\n  // break before the first parameter for >3 and after every 4th.\n  int param_lines = 0;\n  for (int num_params : llvm::seq_inclusive(0, params.max_params)) {\n    if (num_params > NumSingleLineFunctionParams) {\n      param_lines += (num_params + MaxParamsPerLine - 1) / MaxParamsPerLine;\n    }\n  }\n  return 1.0 + static_cast<double>(param_lines) / (params.max_params + 1);\n}\n\nstatic auto EstimateAvgMethodDeclLines(SourceGen::MethodDeclParams params)\n    -> double {\n  // Currently model a uniform distribution [0, max] parameters. Assume a line\n  // break before the first parameter for >2 and after every 4th.\n  int param_lines = 0;\n  for (int num_params : llvm::seq_inclusive(0, params.max_params)) {\n    if (num_params > NumSingleLineMethodParams) {\n      param_lines += (num_params + MaxParamsPerLine - 1) / MaxParamsPerLine;\n    }\n  }\n  return 1.0 + static_cast<double>(param_lines) / (params.max_params + 1);\n}\n\n// Note that this should match the heuristics used when formatting.\n// TODO: See top-level TODO about line estimates and formatting.\nstatic auto EstimateAvgClassDefLines(SourceGen::ClassParams params) -> double {\n  // Comment line, and class open line.\n  double avg = 2.0;\n\n  // One comment line and blank line per function, plus the function lines.\n  avg +=\n      (2.0 + EstimateAvgFunctionDeclLines(params.public_function_decl_params)) *\n      params.public_function_decls;\n  avg += (2.0 + EstimateAvgMethodDeclLines(params.public_method_decl_params)) *\n         params.public_method_decls;\n  avg += (2.0 +\n          EstimateAvgFunctionDeclLines(params.private_function_decl_params)) *\n         params.private_function_decls;\n  avg += (2.0 + EstimateAvgMethodDeclLines(params.private_method_decl_params)) *\n         params.private_method_decls;\n\n  // A blank line and all the fields (if any).\n  if (params.private_field_decls > 0) {\n    avg += 1.0 + params.private_field_decls;\n  }\n\n  // No need to account for the class close line, we have an extra blank line\n  // count for the last of the above.\n  return avg;\n}\n\nauto SourceGen::GenApiFileDenseDecls(int target_lines,\n                                     const DenseDeclParams& params)\n    -> std::string {\n  RawStringOstream source;\n\n  // Figure out how many classes fit in our target lines, each separated by a\n  // blank line. We need to account the comment lines below to start the file.\n  // Note that we want a blank line after our file comment block, so every class\n  // needs a blank line.\n  constexpr int NumFileCommentLines = 4;\n  double avg_class_lines = EstimateAvgClassDefLines(params.class_params);\n  CARBON_CHECK(target_lines > NumFileCommentLines + avg_class_lines,\n               \"Not enough target lines to generate a single class!\");\n  int num_classes = static_cast<double>(target_lines - NumFileCommentLines) /\n                    (avg_class_lines + 1);\n  int expected_lines =\n      NumFileCommentLines + num_classes * (avg_class_lines + 1);\n\n  source << \"// Generated \" << (!IsCpp() ? \"Carbon\" : \"C++\")\n         << \" source file.\\n\";\n  source << llvm::formatv(\n                \"// {0} target lines: {1} classes, {2} expected lines\",\n                target_lines, num_classes, expected_lines)\n         << \"\\n\";\n  source << \"//\\n// Generating as an API file with dense declarations.\\n\";\n\n  // Carbon uses an implicitly imported prelude to get builtin types, but C++\n  // requires header files so include those.\n  if (IsCpp()) {\n    source << \"\\n\";\n    // Header for specific integer types like `std::int64_t`.\n    source << \"#include <cstdint>\\n\";\n    // Header for `std::pair`.\n    source << \"#include <utility>\\n\";\n  }\n\n  auto class_gen_state = ClassGenState(*this, num_classes, params.class_params,\n                                       params.type_use_params);\n  for ([[maybe_unused]] auto _ : llvm::seq(num_classes)) {\n    source << \"\\n\";\n    GenerateClassDef(params.class_params, class_gen_state, source);\n  }\n\n  // Make sure we consumed all the state.\n  CARBON_CHECK(class_gen_state.public_function_param_counts().empty());\n  CARBON_CHECK(class_gen_state.public_method_param_counts().empty());\n  CARBON_CHECK(class_gen_state.private_function_param_counts().empty());\n  CARBON_CHECK(class_gen_state.private_method_param_counts().empty());\n  CARBON_CHECK(class_gen_state.class_names().empty());\n  CARBON_CHECK(class_gen_state.type_names().empty());\n\n  return source.TakeStr();\n}\n\nauto SourceGen::GetShuffledIdentifiers(int number, int min_length,\n                                       int max_length, bool uniform)\n    -> llvm::SmallVector<llvm::StringRef> {\n  llvm::SmallVector<llvm::StringRef> idents =\n      GetIdentifiers(number, min_length, max_length, uniform);\n  std::shuffle(idents.begin(), idents.end(), rng_);\n  return idents;\n}\n\nauto SourceGen::GetShuffledUniqueIdentifiers(int number, int min_length,\n                                             int max_length, bool uniform)\n    -> llvm::SmallVector<llvm::StringRef> {\n  CARBON_CHECK(min_length >= 4,\n               \"Cannot trivially guarantee enough distinct, unique identifiers \"\n               \"for lengths <= 3\");\n  llvm::SmallVector<llvm::StringRef> idents =\n      GetUniqueIdentifiers(number, min_length, max_length, uniform);\n  std::shuffle(idents.begin(), idents.end(), rng_);\n  return idents;\n}\n\nauto SourceGen::GetIdentifiers(int number, int min_length, int max_length,\n                               bool uniform)\n    -> llvm::SmallVector<llvm::StringRef> {\n  llvm::SmallVector<llvm::StringRef> idents = GetIdentifiersImpl(\n      number, min_length, max_length, uniform,\n      [this](int length, int length_count,\n             llvm::SmallVectorImpl<llvm::StringRef>& dest) {\n        llvm::append_range(dest,\n                           GetSingleLengthIdentifiers(length, length_count));\n      });\n\n  return idents;\n}\n\nauto SourceGen::GetUniqueIdentifiers(int number, int min_length, int max_length,\n                                     bool uniform)\n    -> llvm::SmallVector<llvm::StringRef> {\n  CARBON_CHECK(min_length >= 4,\n               \"Cannot trivially guarantee enough distinct, unique identifiers \"\n               \"for lengths <= 3\");\n  llvm::SmallVector<llvm::StringRef> idents =\n      GetIdentifiersImpl(number, min_length, max_length, uniform,\n                         [this](int length, int length_count,\n                                llvm::SmallVectorImpl<llvm::StringRef>& dest) {\n                           AppendUniqueIdentifiers(length, length_count, dest);\n                         });\n\n  return idents;\n}\n\nauto SourceGen::GetSingleLengthIdentifiers(int length, int number)\n    -> llvm::ArrayRef<llvm::StringRef> {\n  llvm::SmallVector<llvm::StringRef>& idents =\n      identifiers_by_length_.Insert(length, {}).value();\n\n  if (static_cast<int>(idents.size()) < number) {\n    idents.reserve(number);\n    for ([[maybe_unused]] auto _ : llvm::seq<int>(idents.size(), number)) {\n      auto ident_storage =\n          llvm::MutableArrayRef(reinterpret_cast<char*>(storage_.Allocate(\n                                    /*Size=*/length, /*Alignment=*/1)),\n                                length);\n      GenerateRandomIdentifier(ident_storage);\n      llvm::StringRef new_id(ident_storage.data(), length);\n      idents.push_back(new_id);\n    }\n    CARBON_CHECK(static_cast<int>(idents.size()) == number);\n  }\n  return llvm::ArrayRef(idents).slice(0, number);\n}\n\nstatic auto IdentifierStartChars() -> llvm::ArrayRef<char> {\n  static llvm::SmallVector<char> chars = [] {\n    llvm::SmallVector<char> chars;\n    for (char c : llvm::seq_inclusive('A', 'Z')) {\n      chars.push_back(c);\n    }\n    for (char c : llvm::seq_inclusive('a', 'z')) {\n      chars.push_back(c);\n    }\n    return chars;\n  }();\n  return chars;\n}\n\nstatic auto IdentifierChars() -> llvm::ArrayRef<char> {\n  static llvm::SmallVector<char> chars = [] {\n    llvm::ArrayRef<char> start_chars = IdentifierStartChars();\n    llvm::SmallVector<char> chars(start_chars.begin(), start_chars.end());\n    chars.push_back('_');\n    for (char c : llvm::seq_inclusive('0', '9')) {\n      chars.push_back(c);\n    }\n    return chars;\n  }();\n  return chars;\n}\n\nstatic constexpr llvm::StringRef NonCarbonCppKeywords[] = {\n    \"asm\", \"do\",  \"double\", \"float\",    \"int\", \"long\", \"new\", \"signed\",\n    \"std\", \"try\", \"unix\",   \"unsigned\", \"xor\", \"NAN\",  \"M_E\", \"M_PI\",\n};\n\n// Returns a random identifier string of the specified length.\n//\n// Ensures this is a valid identifier, avoiding any overlapping syntaxes or\n// keywords both in Carbon and C++.\n//\n// This routine is somewhat expensive and so is useful to cache and reduce the\n// frequency of calls. However, each time it is called it computes a completely\n// new random identifier and so can be useful to eventually find a distinct\n// identifier when needed.\nauto SourceGen::GenerateRandomIdentifier(\n    llvm::MutableArrayRef<char> dest_storage) -> void {\n  llvm::ArrayRef<char> start_chars = IdentifierStartChars();\n  llvm::ArrayRef<char> chars = IdentifierChars();\n\n  llvm::StringRef ident(dest_storage.data(), dest_storage.size());\n  do {\n    dest_storage[0] =\n        start_chars[absl::Uniform<int>(rng_, 0, start_chars.size())];\n    for (int i : llvm::seq<int>(1, dest_storage.size())) {\n      dest_storage[i] = chars[absl::Uniform<int>(rng_, 0, chars.size())];\n    }\n  } while (\n      // TODO: Clean up and simplify this code. With some small refactorings and\n      // post-processing we should be able to make this both easier to read and\n      // less inefficient.\n      llvm::any_of(\n          Lex::TokenKind::KeywordTokens,\n          [ident](auto token) { return ident == token.fixed_spelling(); }) ||\n      llvm::is_contained(NonCarbonCppKeywords, ident) ||\n      ident.ends_with(\"_t\") || ident.ends_with(\"_MIN\") ||\n      ident.ends_with(\"_MAX\") || ident.ends_with(\"_C\") ||\n      (llvm::is_contained({'i', 'u', 'f'}, ident[0]) &&\n       llvm::all_of(ident.substr(1),\n                    [](const char c) { return llvm::isDigit(c); })));\n}\n\n// Appends a number of unique, random identifiers with a particular length to\n// the provided destination vector.\n//\n// Uses, and when necessary grows, a cached sequence of random identifiers with\n// the specified length. Because these are cached, this is efficient to call\n// repeatedly, but will not produce a different sequence of identifiers.\nauto SourceGen::AppendUniqueIdentifiers(\n    int length, int number, llvm::SmallVectorImpl<llvm::StringRef>& dest)\n    -> void {\n  auto& [count, unique_idents] =\n      unique_identifiers_by_length_.Insert(length, {}).value();\n\n  // See if we need to grow our pool of unique identifiers with the requested\n  // length.\n  if (count < number) {\n    // We'll need to insert exactly the requested new unique identifiers. All\n    // our other inserts will find an existing entry.\n    unique_idents.GrowForInsertCount(count - number);\n\n    // Generate the needed number of identifiers.\n    for ([[maybe_unused]] auto _ : llvm::seq<int>(count, number)) {\n      // Allocate stable storage for the identifier so we can form stable\n      // `StringRef`s to it.\n      auto ident_storage =\n          llvm::MutableArrayRef(reinterpret_cast<char*>(storage_.Allocate(\n                                    /*Size=*/length, /*Alignment=*/1)),\n                                length);\n      // Repeatedly generate novel identifiers of this length until we find a\n      // new unique one.\n      for (;;) {\n        GenerateRandomIdentifier(ident_storage);\n        auto result =\n            unique_idents.Insert(llvm::StringRef(ident_storage.data(), length));\n        if (result.is_inserted()) {\n          break;\n        }\n      }\n    }\n    count = number;\n  }\n  // Append all the identifiers directly out of the set. We make no guarantees\n  // about the relative order so we just use the non-deterministic order of the\n  // set and avoid additional storage.\n  //\n  // TODO: It's awkward the `ForEach` here can't early-exit. This just walks the\n  // whole set which is harmless if inefficient. We should add early exiting\n  // the loop support to `Set` and update this code.\n  unique_idents.ForEach([&](llvm::StringRef ident) {\n    if (number > 0) {\n      dest.push_back(ident);\n      --number;\n    }\n  });\n  CARBON_CHECK(number == 0);\n}\n\n// An array of the counts that should be used for each identifier length to\n// produce our desired distribution.\n//\n// Note that the zero-based index corresponds to a 1-based length, so the count\n// for identifiers of length 1 is at index 0.\nstatic constexpr std::array<int, 64> IdentifierLengthCounts = [] {\n  std::array<int, 64> ident_length_counts;\n  // For non-uniform distribution, we simulate a distribution roughly based on\n  // the observed histogram of identifier lengths, but smoothed a bit and\n  // reduced to small counts so that we cycle through all the lengths\n  // reasonably quickly. We want sampling of even 10% of NumTokens from this\n  // in a round-robin form to not be skewed overly much. This still inherently\n  // compresses the long tail as we'd rather have coverage even though it\n  // distorts the distribution a bit.\n  //\n  // The distribution here comes from a script that analyzes source code run\n  // over a few directories of LLVM. The script renders a visual ascii-art\n  // histogram along with the data for each bucket, and that output is\n  // included in comments above each bucket size below to help visualize the\n  // rough shape we're aiming for.\n  //\n  // 1 characters   [3976]  ███████████████████████████████▊\n  ident_length_counts[0] = 40;\n  // 2 characters   [3724]  █████████████████████████████▊\n  ident_length_counts[1] = 40;\n  // 3 characters   [4173]  █████████████████████████████████▍\n  ident_length_counts[2] = 40;\n  // 4 characters   [5000]  ████████████████████████████████████████\n  ident_length_counts[3] = 50;\n  // 5 characters   [1568]  ████████████▌\n  ident_length_counts[4] = 20;\n  // 6 characters   [2226]  █████████████████▊\n  ident_length_counts[5] = 20;\n  // 7 characters   [2380]  ███████████████████\n  ident_length_counts[6] = 20;\n  // 8 characters   [1786]  ██████████████▎\n  ident_length_counts[7] = 18;\n  // 9 characters   [1397]  ███████████▏\n  ident_length_counts[8] = 12;\n  // 10 characters  [ 739]  █████▉\n  ident_length_counts[9] = 12;\n  // 11 characters  [ 779]  ██████▎\n  ident_length_counts[10] = 12;\n  // 12 characters  [1344]  ██████████▊\n  ident_length_counts[11] = 12;\n  // 13 characters  [ 498]  ████\n  ident_length_counts[12] = 5;\n  // 14 characters  [ 284]  ██▎\n  ident_length_counts[13] = 3;\n  // 15 characters  [ 172]  █▍\n  // 16 characters  [ 278]  ██▎\n  // 17 characters  [ 191]  █▌\n  // 18 characters  [ 207]  █▋\n  for (int i = 14; i < 18; ++i) {\n    ident_length_counts[i] = 2;\n  }\n  // 19 - 63 characters are all <100 but non-zero, and we map them to 1 for\n  // coverage despite slightly over weighting the tail.\n  for (int i = 18; i < 64; ++i) {\n    ident_length_counts[i] = 1;\n  }\n  return ident_length_counts;\n}();\n\n// A template function that implements the common logic of `GetIdentifiers` and\n// `GetUniqueIdentifiers`. Most parameters correspond to the parameters of those\n// functions. Additionally, an `AppendFunc` callable is provided to implement\n// the appending operation.\n//\n// The main functionality provided here is collecting the correct number of\n// identifiers from each of the lengths in the range [min_length, max_length]\n// and either in our default representative distribution or a uniform\n// distribution.\nauto SourceGen::GetIdentifiersImpl(int number, int min_length, int max_length,\n                                   bool uniform,\n                                   llvm::function_ref<AppendFn> append)\n    -> llvm::SmallVector<llvm::StringRef> {\n  CARBON_CHECK(min_length <= max_length);\n  CARBON_CHECK(\n      uniform || max_length <= 64,\n      \"Cannot produce a meaningful non-uniform distribution of lengths longer \"\n      \"than 64 as those are exceedingly rare in our observed data sets.\");\n\n  llvm::SmallVector<llvm::StringRef> idents;\n  idents.reserve(number);\n\n  // First, compute the total weight of the distribution so we know how many\n  // identifiers we'll get each time we collect from it.\n  int num_lengths = max_length - min_length + 1;\n  auto length_counts =\n      llvm::ArrayRef(IdentifierLengthCounts).slice(min_length - 1, num_lengths);\n  int count_sum = uniform ? num_lengths : Sum(length_counts);\n  CARBON_CHECK(count_sum >= 1);\n\n  int number_rem = number % count_sum;\n\n  // Finally, walk through each length in the distribution.\n  for (int length : llvm::seq_inclusive(min_length, max_length)) {\n    // Scale how many identifiers we want of this length if computing a\n    // non-uniform distribution. For uniform, we always take one.\n    int scale = uniform ? 1 : IdentifierLengthCounts[length - 1];\n\n    // Now we can compute how many identifiers of this length to request.\n    int length_count = (number / count_sum) * scale;\n    if (number_rem > 0) {\n      int rem_adjustment = std::min(scale, number_rem);\n      length_count += rem_adjustment;\n      number_rem -= rem_adjustment;\n    }\n    append(length, length_count, idents);\n  }\n  CARBON_CHECK(number_rem == 0, \"Unexpected number remaining: {0}\", number_rem);\n  CARBON_CHECK(static_cast<int>(idents.size()) == number,\n               \"Ended up with {0} identifiers instead of the requested {1}\",\n               idents.size(), number);\n\n  return idents;\n}\n\n// Returns a shuffled sequence of integers in the range [min, max].\n//\n// The order of the returned integers is random, but each integer in the range\n// appears the same number of times in the result, with the number of\n// appearances rounded up for lower numbers and rounded down for higher numbers\n// in order to exactly produce `number` results.\nauto SourceGen::GetShuffledInts(int number, int min, int max)\n    -> llvm::SmallVector<int> {\n  llvm::SmallVector<int> ints;\n  ints.reserve(number);\n\n  // Evenly distribute to each value between min and max.\n  int num_values = max - min + 1;\n  for (int i : llvm::seq_inclusive(min, max)) {\n    int i_count = number / num_values;\n    i_count += i < (min + (number % num_values));\n    ints.append(i_count, i);\n  }\n  CARBON_CHECK(static_cast<int>(ints.size()) == number);\n\n  std::shuffle(ints.begin(), ints.end(), rng_);\n  return ints;\n}\n\n// A helper to pop series of unique identifiers off a sequence of random\n// identifiers that may have duplicates.\n//\n// This is particularly designed to work with the sequences of non-unique\n// identifiers produced by `GetShuffledIdentifiers` with the important property\n// that while popping off unique identifiers found in the shuffled list, we\n// don't change the distribution of identifier lengths.\n//\n// The uniqueness is only per-instance of the class, and so an instance can be\n// used to extract a series of names that share a scope.\n//\n// It works by scanning the sequence to extract each unique identifier found,\n// swapping it to the back and popping it off the list. This does shuffle the\n// order, but it isn't expected to do so in an interesting way.\n//\n// It also provides a fallback path in case there are no unique identifiers left\n// which computes fresh, random identifiers with the same length as the next one\n// in the sequence until a unique one is found.\n//\n// For simplicity of the fallback path, the lifetime of the identifiers produced\n// is bound to the lifetime of the popper instance, and not the generator as a\n// whole. If this is ever a problematic constraint, we can start copying\n// fallback identifiers into the generator's storage.\nclass SourceGen::UniqueIdentifierPopper {\n public:\n  explicit UniqueIdentifierPopper(SourceGen& gen,\n                                  llvm::SmallVectorImpl<llvm::StringRef>& data)\n      : gen_(&gen), data_(&data), it_(data_->rbegin()) {}\n\n  // Pop the next unique identifier that can be found in the data, or synthesize\n  // one with a valid length. Always consumes exactly one identifier from the\n  // data.\n  //\n  // Note that the lifetime of the underlying identifier is that of the popper\n  // and not the underlying data.\n  auto Pop() -> llvm::StringRef {\n    for (auto end = data_->rend(); it_ != end; ++it_) {\n      auto insert = set_.Insert(*it_);\n      if (!insert.is_inserted()) {\n        continue;\n      }\n\n      if (it_ != data_->rbegin()) {\n        std::swap(*data_->rbegin(), *it_);\n      }\n      CARBON_CHECK(insert.key() == data_->back());\n      return data_->pop_back_val();\n    }\n\n    // Out of unique elements. Overwrite the back, preserving its length,\n    // generating a new identifiers until we find a unique one and return that.\n    // This ensures we continue to consume the structure and produce the same\n    // size identifiers even in the fallback.\n    int length = data_->pop_back_val().size();\n    auto fallback_ident_storage =\n        llvm::MutableArrayRef(reinterpret_cast<char*>(gen_->storage_.Allocate(\n                                  /*Size=*/length, /*Alignment=*/1)),\n                              length);\n    for (;;) {\n      gen_->GenerateRandomIdentifier(fallback_ident_storage);\n      auto fallback_id = llvm::StringRef(fallback_ident_storage.data(), length);\n      if (set_.Insert(fallback_id).is_inserted()) {\n        return fallback_id;\n      }\n    }\n  }\n\n private:\n  SourceGen* gen_;\n  llvm::SmallVectorImpl<llvm::StringRef>* data_;\n  llvm::SmallVectorImpl<llvm::StringRef>::reverse_iterator it_;\n  Set<llvm::StringRef> set_;\n};\n\n// Generates a function declaration and writes it to the provided stream.\n//\n// The declaration can be configured with a function name, private modifier,\n// whether it is a method, the parameter count, an how indented it is.\n//\n// This is also provided a collection of identifiers to consume as parameter\n// names -- it will use a unique popper to extract unique parameter names from\n// this collection.\nauto SourceGen::GenerateFunctionDecl(\n    llvm::StringRef name, bool is_private, bool is_method, int param_count,\n    llvm::StringRef indent, llvm::SmallVectorImpl<llvm::StringRef>& param_names,\n    llvm::function_ref<auto()->llvm::StringRef> get_type_name,\n    llvm::raw_ostream& os) -> void {\n  os << indent << \"// TODO: make better comment text\\n\";\n  if (!IsCpp()) {\n    os << indent << (is_private ? \"private \" : \"\") << \"fn \" << name;\n\n    if (is_method) {\n      os << \"[self: Self]\";\n    }\n  } else {\n    os << indent;\n    if (!is_method) {\n      os << \"static \";\n    }\n    os << \"auto \" << name;\n  }\n\n  os << \"(\";\n\n  if (param_count >\n      (is_method ? NumSingleLineMethodParams : NumSingleLineFunctionParams)) {\n    os << \"\\n\" << indent << \"    \";\n  }\n  UniqueIdentifierPopper unique_param_names(*this, param_names);\n  for (int i : llvm::seq(param_count)) {\n    if (i > 0) {\n      if ((i % MaxParamsPerLine) == 0) {\n        os << \",\\n\" << indent << \"    \";\n      } else {\n        os << \", \";\n      }\n    }\n    if (!IsCpp()) {\n      os << unique_param_names.Pop() << \": \" << get_type_name();\n    } else {\n      os << get_type_name() << \" \" << unique_param_names.Pop();\n    }\n  }\n  os << \")\";\n\n  os << \" -> \" << get_type_name();\n  os << \";\\n\";\n}\n\n// Generate a class definition and write it to the provided stream.\n//\n// The structure of the definition is guided by the `params` provided, and it\n// consumes the provided state.\nauto SourceGen::GenerateClassDef(const ClassParams& params,\n                                 ClassGenState& state, llvm::raw_ostream& os)\n    -> void {\n  llvm::StringRef name = state.class_names().pop_back_val();\n  os << \"// TODO: make better comment text\\n\";\n  os << \"class \" << name << \" {\\n\";\n  if (IsCpp()) {\n    os << \" public:\\n\";\n  }\n\n  // Field types can't be the class we're currently declaring. We enforce this\n  // by collecting them before inserting that type into the valid set.\n  llvm::SmallVector<llvm::StringRef> field_type_names;\n  field_type_names.reserve(params.private_field_decls);\n  for ([[maybe_unused]] auto _ : llvm::seq(params.private_field_decls)) {\n    field_type_names.push_back(state.GetValidTypeName());\n  }\n\n  // Mark this class as now a valid type now that field type names have been\n  // collected. We can reference this class from functions and methods within\n  // the definition.\n  state.AddValidTypeName(name);\n\n  UniqueIdentifierPopper unique_member_names(*this, state.member_names());\n  llvm::ListSeparator line_sep(\"\\n\");\n  for ([[maybe_unused]] auto _ : llvm::seq(params.public_function_decls)) {\n    os << line_sep;\n    GenerateFunctionDecl(\n        unique_member_names.Pop(), /*is_private=*/false,\n        /*is_method=*/false,\n        state.public_function_param_counts().pop_back_val(),\n        /*indent=*/\"  \", state.param_names(),\n        [&] { return state.GetValidTypeName(); }, os);\n  }\n  for ([[maybe_unused]] auto _ : llvm::seq(params.public_method_decls)) {\n    os << line_sep;\n    GenerateFunctionDecl(\n        unique_member_names.Pop(), /*is_private=*/false,\n        /*is_method=*/true, state.public_method_param_counts().pop_back_val(),\n        /*indent=*/\"  \", state.param_names(),\n        [&] { return state.GetValidTypeName(); }, os);\n  }\n\n  if (IsCpp()) {\n    os << \"\\n private:\\n\";\n    // Reset the separator.\n    line_sep = llvm::ListSeparator(\"\\n\");\n  }\n\n  for ([[maybe_unused]] auto _ : llvm::seq(params.private_function_decls)) {\n    os << line_sep;\n    GenerateFunctionDecl(\n        unique_member_names.Pop(), /*is_private=*/true,\n        /*is_method=*/false,\n        state.private_function_param_counts().pop_back_val(),\n        /*indent=*/\"  \", state.param_names(),\n        [&] { return state.GetValidTypeName(); }, os);\n  }\n  for ([[maybe_unused]] auto _ : llvm::seq(params.private_method_decls)) {\n    os << line_sep;\n    GenerateFunctionDecl(\n        unique_member_names.Pop(), /*is_private=*/true,\n        /*is_method=*/true, state.private_method_param_counts().pop_back_val(),\n        /*indent=*/\"  \", state.param_names(),\n        [&] { return state.GetValidTypeName(); }, os);\n  }\n  os << line_sep;\n  for (llvm::StringRef type_name : field_type_names) {\n    if (!IsCpp()) {\n      os << \"  private var \" << unique_member_names.Pop() << \": \" << type_name\n         << \";\\n\";\n    } else {\n      os << \"  \" << type_name << \" \" << unique_member_names.Pop() << \";\\n\";\n    }\n  }\n  os << \"}\" << (IsCpp() ? \";\" : \"\") << \"\\n\";\n}\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/base/source_gen.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_BASE_SOURCE_GEN_H_\n#define CARBON_TESTING_BASE_SOURCE_GEN_H_\n\n#include <string>\n\n#include \"absl/random/random.h\"\n#include \"common/map.h\"\n#include \"common/set.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/Allocator.h\"\n\nnamespace Carbon::Testing {\n\n// Provides source code generation facilities.\n//\n// This class works to generate valid but random & meaningless source code in\n// interesting patterns for benchmarking. It is very incomplete. A high level\n// set of long-term goals:\n//\n// - Generate interesting patterns and structures of code that have emerged as\n//   toolchain performance bottlenecks in practice in C++ codebases.\n// - Generate code that includes most Carbon language features (and whatever\n//   reasonable C++ analogs could be used for comparative purposes):\n//   - Functions\n//   - Classes with class functions, methods, and fields\n//   - Interfaces\n//   - Checked generics and templates\n//   - Nested and unnested impls\n//   - Nested classes\n//   - Inline and out-of-line function and method definitions\n//   - Imports and exports\n//   - API files and impl files.\n// - Be random but deterministic. The goal is benchmarking and so while this\n//   code should strive for not producing trivially predictable patterns, it\n//   should also strive to be consistent and suitable for benchmarking. Wherever\n//   possible, it should permute the order and content without randomizing the\n//   total count, size, or complexity.\n//\n// Note that the default and primary generation target is interesting Carbon\n// source code. We have a best-effort to alternatively generate comparable C++\n// constructs to the Carbon ones for comparative benchmarking, but there is no\n// goal to cover all the interesting C++ patterns we might want to benchmark,\n// and we don't aim for perfectly synthesizing C++ analogs. We can always drop\n// fidelity for the C++ code path if needed for simplicity.\n//\n// TODO: There are numerous places where we hard code a fixed quantity. Instead,\n// we should build a rich but general system to easily encode a discrete\n// distribution that is sampled. We have a specialized version of this for\n// identifiers that should be generalized.\nclass SourceGen {\n public:\n  enum class Language : uint8_t {\n    Carbon,\n    Cpp,\n  };\n\n  struct FunctionDeclParams {\n    // TODD: Arbitrary default, should switch to a distribution from data.\n    int max_params = 4;\n  };\n\n  struct MethodDeclParams {\n    // TODD: Arbitrary default, should switch to a distribution from data.\n    int max_params = 4;\n  };\n\n  // Parameters used to generate a class in a generated file.\n  //\n  // Currently, this uses a fixed number of each kind of declaration, with\n  // arbitrary defaults chosen. The defaults currently skew towards large\n  // classes with lots of nested declarations.\n  // TODO: Switch these to distributions based on data.\n  //\n  // TODO: Add support for generating definitions and parameters to control\n  // them.\n  //\n  // TODO: Add heuristic for how many functions have return types.\n  struct ClassParams {\n    int public_function_decls = 4;\n    FunctionDeclParams public_function_decl_params = {.max_params = 8};\n\n    int public_method_decls = 10;\n    MethodDeclParams public_method_decl_params;\n\n    int private_function_decls = 2;\n    FunctionDeclParams private_function_decl_params = {.max_params = 6};\n\n    int private_method_decls = 8;\n    MethodDeclParams private_method_decl_params = {.max_params = 6};\n\n    int private_field_decls = 6;\n  };\n\n  // Parameters used to select type _uses_, as opposed to definitions.\n  //\n  // These govern what distribution of types are used for function parameters,\n  // returns, and fields.\n  //\n  // Mainly these provide a coarse histogram of weights to shape the\n  // distribution of different type options, and try to fit that as closely as\n  // possible.\n  //\n  // The default weights in the histogram were arbitrarily selected based on\n  // intuition about importance for benchmarking and not based on any\n  // measurement. We arrange for them to sum to 100 so that the weights can be\n  // view as %s of the type uses.\n  //\n  // The specific builtin type options used in the weights were also selected\n  // arbitrarily.\n  //\n  // TODO: Improve the set of builtin types and the weighting if real world code\n  // ends up sharply different.\n  //\n  // TODO: Add a heuristic to make some % of type references via pointers (or\n  // other compound types).\n  struct TypeUseParams {\n    // The weights in the histogram start with a sequence fixed types described\n    // with a Carbon and C++ string, and their associated weight.\n    struct FixedTypeWeight {\n      llvm::StringRef carbon_spelling;\n      llvm::StringRef cpp_spelling;\n      int weight;\n    };\n\n    llvm::SmallVector<FixedTypeWeight> fixed_type_weights = {\n        // Combined weight of 65 for a core set of builtin types.\n        {.carbon_spelling = \"bool\", .cpp_spelling = \"bool\", .weight = 25},\n        {.carbon_spelling = \"i32\", .cpp_spelling = \"int\", .weight = 20},\n        {.carbon_spelling = \"i64\",\n         .cpp_spelling = \"std::int64_t\",\n         .weight = 10},\n        {.carbon_spelling = \"i32*\", .cpp_spelling = \"int*\", .weight = 5},\n        {.carbon_spelling = \"i64*\",\n         .cpp_spelling = \"std::int64_t*\",\n         .weight = 5},\n\n        // A weight of 5 distributed across tuple structures\n        {.carbon_spelling = \"(bool, i64)\",\n         .cpp_spelling = \"std::pair<bool, std::int64_t>\",\n         .weight = 2},\n        {.carbon_spelling = \"(i32, i64*)\",\n         .cpp_spelling = \"std::pair<int, std::int64_t*>\",\n         .weight = 3},\n    };\n\n    // The weight for using types declared in the file. These will be randomly\n    // shuffled references, and when there are more type references than\n    // declared, include repeated references.\n    int declared_types_weight = 30;\n  };\n\n  // Parameters used to generate a file with dense declarations.\n  struct DenseDeclParams {\n    // TODO: Add more parameters to control generating top-level constructs\n    // other than class definitions.\n\n    // Parameters used when generating class definitions.\n    ClassParams class_params = {};\n\n    // Parameters used to guide the selection of types for use in declarations.\n    TypeUseParams type_use_params = {};\n  };\n\n  // Access a global instance of this type to generate Carbon code for\n  // benchmarks, tests, or other places where sharing a common instance is\n  // useful. Note that there is nothing thread safe about this instance or type.\n  static auto Global() -> SourceGen&;\n\n  // Construct a source generator for the provided language, by default Carbon.\n  explicit SourceGen(Language language = Language::Carbon);\n\n  // Generate an API file with dense classes containing function forward\n  // declarations.\n  //\n  // Accepts a number of `target_lines` for the resulting source code. This is a\n  // rough approximation used to scale all the other constructs up and down\n  // accordingly. For C++ source generation, we work to generate the same number\n  // of constructs as Carbon would for the given line count over keeping the\n  // actual line count close to the target.\n  //\n  // TODO: Currently, the formatting and line breaks of generating code are\n  // extremely rough still, and those are a large factor in adherence to\n  // `target_lines`. Long term, the goal is to get as close as we can to any\n  // automatically formatted code while still keeping the stability of\n  // benchmarking.\n  auto GenApiFileDenseDecls(int target_lines, const DenseDeclParams& params)\n      -> std::string;\n\n  // Get some number of randomly shuffled identifiers.\n  //\n  // The identifiers start with a character [A-Za-z], other characters may also\n  // include [0-9_]. Both Carbon and C++ keywords are excluded along with any\n  // other non-identifier syntaxes that overlap to ensure all of these can be\n  // used as identifiers.\n  //\n  // The order will be different for each call to this function, but the\n  // specific identifiers may remain the same in order to reduce the cost of\n  // repeated calls. However, the sum of the identifier sizes returned is\n  // guaranteed to be the same for every call with the same number of\n  // identifiers so that benchmarking all of these identifiers has predictable\n  // and stable cost.\n  //\n  // Optionally, callers can request a minimum and maximum length. By default,\n  // the length distribution used across the identifiers will mirror the\n  // observed distribution of identifiers in C++ source code and our expectation\n  // of them in Carbon source code. The maximum length in this default\n  // distribution cannot be more than 64.\n  //\n  // Callers can request a uniform distribution across [min_length, max_length],\n  // and when it is requested there is no limit on `max_length`.\n  auto GetShuffledIdentifiers(int number, int min_length = 1,\n                              int max_length = 64, bool uniform = false)\n      -> llvm::SmallVector<llvm::StringRef>;\n\n  // Same as `GetShuffledIdentifiers`, but ensures there are no collisions.\n  auto GetShuffledUniqueIdentifiers(int number, int min_length = 4,\n                                    int max_length = 64, bool uniform = false)\n      -> llvm::SmallVector<llvm::StringRef>;\n\n  // Returns a collection of un-shuffled identifiers, otherwise the same as\n  // `GetShuffledIdentifiers`.\n  //\n  // Usually, benchmarks should use the shuffled version. However, this is\n  // useful when deterministic access to the identifiers is needed to avoid\n  // introducing noise, or if there is already a post-processing step to shuffle\n  // things, since shuffling is very expensive in debug builds.\n  auto GetIdentifiers(int number, int min_length = 1, int max_length = 64,\n                      bool uniform = false)\n      -> llvm::SmallVector<llvm::StringRef>;\n\n  // Returns a collection of un-shuffled unique identifiers, otherwise the same\n  // as `GetShuffledUniqueIdentifiers`.\n  //\n  // Usually, benchmarks should use the shuffled version. However, this is\n  // useful when deterministic access to the identifiers is needed to avoid\n  // introducing noise, or if there is already a post-processing step to shuffle\n  // things, since shuffling is very expensive in debug builds.\n  auto GetUniqueIdentifiers(int number, int min_length = 1, int max_length = 64,\n                            bool uniform = false)\n      -> llvm::SmallVector<llvm::StringRef>;\n\n  // Returns a shared collection of random identifiers of a specific length.\n  //\n  // For a single, exact length, we have an even cheaper routine to return\n  // access to a shared collection of identifiers. The order of these is a\n  // single fixed random order for a given execution. The returned array\n  // reference is only valid until the next call any method on this generator.\n  auto GetSingleLengthIdentifiers(int length, int number)\n      -> llvm::ArrayRef<llvm::StringRef>;\n\n private:\n  class ClassGenState;\n  friend ClassGenState;\n\n  class UniqueIdentifierPopper;\n  friend UniqueIdentifierPopper;\n\n  using AppendFn = auto(int length, int number,\n                        llvm::SmallVectorImpl<llvm::StringRef>& dest) -> void;\n\n  auto IsCpp() -> bool { return language_ == Language::Cpp; }\n\n  auto GenerateRandomIdentifier(llvm::MutableArrayRef<char> dest_storage)\n      -> void;\n  auto AppendUniqueIdentifiers(int length, int number,\n                               llvm::SmallVectorImpl<llvm::StringRef>& dest)\n      -> void;\n  auto GetIdentifiersImpl(int number, int min_length, int max_length,\n                          bool uniform, llvm::function_ref<AppendFn> append)\n      -> llvm::SmallVector<llvm::StringRef>;\n\n  auto GetShuffledInts(int number, int min, int max) -> llvm::SmallVector<int>;\n\n  auto GenerateFunctionDecl(\n      llvm::StringRef name, bool is_private, bool is_method, int param_count,\n      llvm::StringRef indent,\n      llvm::SmallVectorImpl<llvm::StringRef>& param_names,\n      llvm::function_ref<auto()->llvm::StringRef> get_type_name,\n      llvm::raw_ostream& os) -> void;\n  auto GenerateClassDef(const ClassParams& params, ClassGenState& state,\n                        llvm::raw_ostream& os) -> void;\n\n  absl::BitGen rng_;\n  llvm::BumpPtrAllocator storage_;\n\n  Map<int, llvm::SmallVector<llvm::StringRef>> identifiers_by_length_;\n  Map<int, std::pair<int, Set<llvm::StringRef>>> unique_identifiers_by_length_;\n\n  Language language_;\n};\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_BASE_SOURCE_GEN_H_\n"
  },
  {
    "path": "testing/base/source_gen_main.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <optional>\n#include <system_error>\n\n#include \"common/bazel_working_dir.h\"\n#include \"common/command_line.h\"\n#include \"common/init_llvm.h\"\n#include \"common/ostream.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/FileSystem.h\"\n#include \"testing/base/source_gen.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nconstexpr CommandLine::CommandInfo Info = {\n    .name = \"source_gen\",\n    .help = R\"\"\"(\nA source generator for Carbon.\n)\"\"\",\n};\n\nconstexpr CommandLine::ArgInfo OutputArgInfo = {\n    .name = \"output\",\n    .value_name = \"FILE\",\n    .help = R\"\"\"(\nWrites the generate source code to a file rather than stdout.\n)\"\"\",\n};\n\nconstexpr CommandLine::ArgInfo LinesArgInfo = {\n    .name = \"lines\",\n    .value_name = \"N\",\n    .help = R\"\"\"(\nThe number of lines of code to target for a generated source file.\n)\"\"\",\n};\n\nconstexpr CommandLine::ArgInfo LanguageArgInfo = {\n    .name = \"language\",\n    //.value_name = \"[carbon|cpp]\",\n    .help = R\"\"\"(\nThe language of source code to generate. The C++ source generation is best\neffort to try to provide as much comparable benchmarking as possible, but the\nprimary language focus is generating Carbon.\n)\"\"\",\n};\n\nauto Run(llvm::ArrayRef<llvm::StringRef> args) -> bool {\n  // Default to outputting to stdout and writing 10k lines of source code.\n  llvm::StringRef output_filename = \"-\";\n  int lines = 10'000;\n  SourceGen::Language language;\n\n  auto parse_result = CommandLine::Parse(\n      args, llvm::outs(), Info, [&](CommandLine::CommandBuilder& b) {\n        b.AddStringOption(OutputArgInfo,\n                          [&](auto& arg_b) { arg_b.Set(&output_filename); });\n        b.AddIntegerOption(LinesArgInfo,\n                           [&](auto& arg_b) { arg_b.Set(&lines); });\n        b.AddOneOfOption(LanguageArgInfo, [&](auto& arg_b) {\n          arg_b.SetOneOf(\n              {\n                  arg_b.OneOfValue(\"carbon\", SourceGen::Language::Carbon)\n                      .Default(true),\n                  arg_b.OneOfValue(\"cpp\", SourceGen::Language::Cpp),\n              },\n              &language);\n        });\n\n        // No-op action as there is only one operation for this command.\n        b.Do([] {});\n      });\n  if (!parse_result.ok()) {\n    llvm::errs() << \"error: \" << *parse_result << \"\\n\";\n    return false;\n  } else if (*parse_result == CommandLine::ParseResult::MetaSuccess) {\n    // Fully handled by the CLI library.\n    return true;\n  }\n\n  std::optional<llvm::raw_fd_ostream> output_file;\n  llvm::raw_fd_ostream* output = &llvm::outs();\n  if (output_filename != \"-\") {\n    std::error_code ec;\n    output_file.emplace(output_filename, ec, llvm::sys::fs::OF_None);\n    if (ec) {\n      llvm::errs() << \"ERROR: Unable to open output file '\" << output_filename\n                   << \"': \" << ec.message() << \"\\n\";\n      return false;\n    }\n    output = &*output_file;\n  }\n\n  SourceGen gen(language);\n  *output << gen.GenApiFileDenseDecls(lines, SourceGen::DenseDeclParams{});\n  output->flush();\n  return true;\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n\nauto main(int argc, char** argv) -> int {\n  // Do LLVM's initialization first, this will also transform UTF-16 to UTF-8.\n  Carbon::InitLLVM init_llvm(argc, argv);\n\n  Carbon::SetWorkingDirForBazelRun();\n\n  llvm::SmallVector<llvm::StringRef> args(argv + 1, argv + argc);\n  bool success = Carbon::Testing::Run(args);\n  return success ? EXIT_SUCCESS : EXIT_FAILURE;\n}\n"
  },
  {
    "path": "testing/base/source_gen_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/base/source_gen.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"common/set.h\"\n#include \"testing/base/global_exe_path.h\"\n#include \"toolchain/base/install_paths_test_helpers.h\"\n#include \"toolchain/driver/driver.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing ::testing::AllOf;\nusing ::testing::ContainerEq;\nusing ::testing::Contains;\nusing ::testing::Each;\nusing ::testing::Eq;\nusing ::testing::Ge;\nusing ::testing::Gt;\nusing ::testing::Le;\nusing ::testing::MatchesRegex;\nusing ::testing::SizeIs;\n\n// Tiny helper to sum the sizes of a range of ranges. Uses a template to avoid\n// hard coding any specific types for the two ranges.\ntemplate <typename T>\nstatic auto SumSizes(const T& range) -> ssize_t {\n  ssize_t sum = 0;\n  for (const auto& inner_range : range) {\n    sum += inner_range.size();\n  }\n  return sum;\n}\n\nTEST(SourceGenTest, Identifiers) {\n  SourceGen gen;\n\n  auto idents = gen.GetShuffledIdentifiers(1000);\n  EXPECT_THAT(idents.size(), Eq(1000));\n  for (llvm::StringRef ident : idents) {\n    EXPECT_THAT(ident, MatchesRegex(\"[A-Za-z][A-Za-z0-9_]*\"));\n  }\n\n  // We should have at least one identifier of each length [1, 64]. The exact\n  // distribution is an implementation detail designed to vaguely match the\n  // expected distribution in source code.\n  for (int size : llvm::seq_inclusive(1, 64)) {\n    EXPECT_THAT(idents, Contains(SizeIs(size)));\n  }\n\n  // Check that identifiers 4 characters or shorter are more common than longer\n  // lengths. This is a very rough way of double checking that we got the\n  // intended distribution.\n  for (int short_size : llvm::seq_inclusive(1, 4)) {\n    int short_count = llvm::count_if(idents, [&](auto ident) {\n      return static_cast<int>(ident.size()) == short_size;\n    });\n    for (int long_size : llvm::seq_inclusive(5, 64)) {\n      EXPECT_THAT(short_count, Gt(llvm::count_if(idents, [&](auto ident) {\n                    return static_cast<int>(ident.size()) == long_size;\n                  })));\n    }\n  }\n\n  // Check that repeated calls are different in interesting ways, but have the\n  // exact same total bytes.\n  ssize_t idents_size_sum = SumSizes(idents);\n  for ([[maybe_unused]] auto _ : llvm::seq(10)) {\n    auto idents2 = gen.GetShuffledIdentifiers(1000);\n    EXPECT_THAT(idents2, SizeIs(1000));\n    // Should be (at least) a different shuffle of identifiers.\n    EXPECT_THAT(idents2, Not(ContainerEq(idents)));\n    // But the sum of lengths should be identical.\n    EXPECT_THAT(SumSizes(idents2), Eq(idents_size_sum));\n  }\n\n  // Check length constraints have the desired effect.\n  idents =\n      gen.GetShuffledIdentifiers(1000, /*min_length=*/10, /*max_length=*/20);\n  EXPECT_THAT(idents, Each(SizeIs(AllOf(Ge(10), Le(20)))));\n}\n\nTEST(SourceGenTest, UniformIdentifiers) {\n  SourceGen gen;\n  // Check that uniform identifier length results in exact coverage of each\n  // possible length for an easy case, both without and with a remainder.\n  auto idents =\n      gen.GetShuffledIdentifiers(100, /*min_length=*/10, /*max_length=*/19,\n                                 /*uniform=*/true);\n  EXPECT_THAT(idents, Contains(SizeIs(10)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(11)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(12)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(13)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(14)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(15)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(16)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(17)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(18)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(19)).Times(10));\n\n  idents = gen.GetShuffledIdentifiers(97, /*min_length=*/10, /*max_length=*/19,\n                                      /*uniform=*/true);\n  EXPECT_THAT(idents, Contains(SizeIs(10)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(11)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(12)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(13)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(14)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(15)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(16)).Times(10));\n  EXPECT_THAT(idents, Contains(SizeIs(17)).Times(9));\n  EXPECT_THAT(idents, Contains(SizeIs(18)).Times(9));\n  EXPECT_THAT(idents, Contains(SizeIs(19)).Times(9));\n}\n\n// Largely covered by `Identifiers` and `UniformIdentifiers`, but need to check\n// for uniqueness specifically.\nTEST(SourceGenTest, UniqueIdentifiers) {\n  SourceGen gen;\n\n  auto unique = gen.GetShuffledUniqueIdentifiers(1000);\n  EXPECT_THAT(unique.size(), Eq(1000));\n  Set<llvm::StringRef> set;\n  for (llvm::StringRef ident : unique) {\n    EXPECT_THAT(ident, MatchesRegex(\"[A-Za-z][A-Za-z0-9_]*\"));\n    EXPECT_TRUE(set.Insert(ident).is_inserted())\n        << \"Colliding identifier: \" << ident;\n  }\n\n  // Check single length specifically where uniqueness is the most challenging.\n  set.Clear();\n  unique = gen.GetShuffledUniqueIdentifiers(1000, /*min_length=*/4,\n                                            /*max_length=*/4);\n  for (llvm::StringRef ident : unique) {\n    EXPECT_TRUE(set.Insert(ident).is_inserted())\n        << \"Colliding identifier: \" << ident;\n  }\n}\n\n// Check that the source code doesn't have compiler errors.\nauto TestCompile(llvm::StringRef source) -> bool {\n  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> fs =\n      new llvm::vfs::InMemoryFileSystem;\n  InstallPaths installation(\n      InstallPaths::MakeForBazelRunfiles(Testing::GetExePath()));\n  Driver driver(fs, &installation, /*input_stream=*/nullptr, &llvm::outs(),\n                &llvm::errs());\n\n  AddPreludeFilesToVfs(installation, fs);\n\n  fs->addFile(\"test.carbon\", /*ModificationTime=*/0,\n              llvm::MemoryBuffer::getMemBuffer(source));\n  return driver.RunCommand({\"compile\", \"--phase=check\", \"test.carbon\"}).success;\n}\n\nTEST(SourceGenTest, GenApiFileDenseDeclsTest) {\n  SourceGen gen;\n\n  std::string source =\n      gen.GenApiFileDenseDecls(1000, SourceGen::DenseDeclParams{});\n  // Should be within 1% of the requested line count.\n  EXPECT_THAT(source, Contains('\\n').Times(AllOf(Ge(950), Le(1050))));\n\n  // Make sure we generated valid Carbon code.\n  EXPECT_TRUE(TestCompile(source));\n}\n\nTEST(SourceGenTest, GenApiFileDenseDeclsCppTest) {\n  SourceGen gen(SourceGen::Language::Cpp);\n\n  // Generate a 1000-line file which is enough to have a reasonably accurate\n  // line count estimate and have a few classes.\n  std::string source =\n      gen.GenApiFileDenseDecls(1000, SourceGen::DenseDeclParams{});\n  // Should be within 10% of the requested line count.\n  EXPECT_THAT(source, Contains('\\n').Times(AllOf(Ge(900), Le(1100))));\n\n  // TODO: When the driver supports compiling C++ code as easily as Carbon, we\n  // should test that the generated C++ code is valid.\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/base/unified_diff_matcher.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_BASE_UNIFIED_DIFF_MATCHER_H_\n#define CARBON_TESTING_BASE_UNIFIED_DIFF_MATCHER_H_\n\n#include <gmock/gmock.h>\n\n#include <algorithm>\n#include <optional>\n#include <string>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"llvm/ADT/STLExtras.h\"\n#include \"llvm/ADT/Sequence.h\"\n#include \"llvm/ADT/SmallVector.h\"\n\nnamespace Carbon::Testing {\n\n// Matcher that compares the elements of two containers and produces a unified\n// diff on failure.\ntemplate <typename Container>\nclass UnifiedDiffMatcher {\n public:\n  explicit UnifiedDiffMatcher(Container expected)\n      : expected_(std::move(expected)) {}\n\n  // Matches `actual` against `expected_`. Returns true on a match; returns\n  // false and prints a unified diff to `listener` on a mismatch.\n  template <typename ActualContainer>\n  auto MatchAndExplain(const ActualContainer& actual,\n                       testing::MatchResultListener* listener) const -> bool;\n\n  auto DescribeTo(std::ostream* os) const -> void {\n    *os << \"matches elements with unified diff\";\n  }\n\n  auto DescribeNegationTo(std::ostream* os) const -> void {\n    *os << \"does not match elements with unified diff\";\n  }\n\n private:\n  // A 2D array, stored contiguously. Rows correspond to `expected_`'s elements,\n  // and columns correspond to the actual container's elements.\n  template <typename T>\n  class Table;\n\n  // The result of a `Matches` check between an expected and actual element.\n  enum class MatchResult : uint8_t { Unknown, Matches, DoesNotMatch };\n\n  // Checks whether `actual_element` matches `expected_[expected_index]`. It\n  // first checks whether a cached result exists. If not, it evaluates the\n  // match and stores the result in `match_results`.\n  template <typename ActualElement>\n  auto IsElementMatch(size_t expected_index, size_t actual_index,\n                      const ActualElement& actual_element,\n                      Table<MatchResult>& match_results) const -> bool {\n    MatchResult cached_result = match_results.Get(expected_index, actual_index);\n    if (cached_result != MatchResult::Unknown) {\n      return cached_result == MatchResult::Matches;\n    }\n    bool is_match =\n        testing::MatcherCast<const ActualElement&>(expected_[expected_index])\n            .Matches(actual_element);\n    match_results.Set(\n        expected_index, actual_index,\n        is_match ? MatchResult::Matches : MatchResult::DoesNotMatch);\n    return is_match;\n  }\n\n  // Returns true if every element in `expected_` matches the corresponding\n  // element in `actual`. Stores comparisons in `match_results`.\n  template <typename ActualContainer>\n  auto IsEqual(const ActualContainer& actual,\n               Table<MatchResult>& match_results) const -> bool;\n\n  // Populates `subsequences` with the longest common matching subsequences\n  // found when comparing `actual` and `expected_`. Stores comparisons in\n  // `match_results`.\n  template <typename ActualContainer>\n  auto GetLongestCommonSubsequences(const ActualContainer& actual,\n                                    Table<MatchResult>& match_results,\n                                    Table<int>& subsequences) const -> void;\n\n  // Prints the unified diff.\n  template <typename ActualContainer>\n  auto PrintDiff(const ActualContainer& actual,\n                 Table<MatchResult>& match_results,\n                 const Table<int>& subsequences,\n                 testing::MatchResultListener* listener) const -> void;\n\n  // The expected elements.\n  Container expected_;\n};\n\n// Returns a polymorphic matcher that acts similarly to\n// ElementsAreArray but produces a unified diff on failure.\ntemplate <typename Container>\nauto ElementsAreArrayWithUnifiedDiff(Container expected) {\n  return testing::MakePolymorphicMatcher(\n      UnifiedDiffMatcher<Container>(std::move(expected)));\n}\n\n// -----------------------------------------------------------------------------\n// Internal implementation details follow.\n// -----------------------------------------------------------------------------\n\ntemplate <typename Container>\ntemplate <typename T>\nclass UnifiedDiffMatcher<Container>::Table {\n public:\n  // Constructs a table with dimensions of expected_size and actual_size,\n  // corresponding to the containers being compared.\n  Table(int expected_size, int actual_size, T default_value)\n      : actual_size_(actual_size),\n        data_(expected_size * actual_size, default_value) {}\n\n  // Sets the value at the given expected_index and actual_index.\n  auto Set(int expected_index, int actual_index, T value) -> void {\n    data_[expected_index * actual_size_ + actual_index] = std::move(value);\n  }\n\n  // Gets the value at the given expected_index and actual_index.\n  auto Get(int expected_index, int actual_index) const -> T {\n    return data_[expected_index * actual_size_ + actual_index];\n  }\n\n private:\n  // The actual_size of the table.\n  int actual_size_;\n  // The contiguous data storage for the table.\n  llvm::SmallVector<T> data_;\n};\n\ntemplate <typename Container>\ntemplate <typename ActualContainer>\nauto UnifiedDiffMatcher<Container>::MatchAndExplain(\n    const ActualContainer& actual, testing::MatchResultListener* listener) const\n    -> bool {\n  Table<MatchResult> match_results(expected_.size(), std::size(actual),\n                                   MatchResult::Unknown);\n\n  if (IsEqual(actual, match_results)) {\n    return true;\n  }\n\n  if (listener->IsInterested()) {\n    Table<int> subsequences(expected_.size() + 1, std::size(actual) + 1, 0);\n    GetLongestCommonSubsequences(actual, match_results, subsequences);\n    PrintDiff(actual, match_results, subsequences, listener);\n  }\n  return false;\n}\n\ntemplate <typename Container>\ntemplate <typename ActualContainer>\nauto UnifiedDiffMatcher<Container>::IsEqual(\n    const ActualContainer& actual, Table<MatchResult>& match_results) const\n    -> bool {\n  if (expected_.size() != std::size(actual)) {\n    return false;\n  }\n\n  for (auto [i, actual_element] : llvm::enumerate(actual)) {\n    if (!IsElementMatch(i, i, actual_element, match_results)) {\n      return false;\n    }\n  }\n  return true;\n}\n\ntemplate <typename Container>\ntemplate <typename ActualContainer>\nauto UnifiedDiffMatcher<Container>::GetLongestCommonSubsequences(\n    const ActualContainer& actual, Table<MatchResult>& match_results,\n    Table<int>& subsequences) const -> void {\n  for (auto expected_index : llvm::seq(expected_.size())) {\n    for (auto [actual_index, actual_element] : llvm::enumerate(actual)) {\n      int subsequence_value;\n      if (IsElementMatch(expected_index, actual_index, actual_element,\n                         match_results)) {\n        // If the elements match, the LCS length increases by 1 relative to\n        // the prefixes where both elements are excluded.\n        subsequence_value = subsequences.Get(expected_index, actual_index) + 1;\n      } else {\n        // Otherwise, the LCS length is the maximum of the LCS lengths\n        // relative to the prefixes where one element is excluded.\n        subsequence_value =\n            std::max(subsequences.Get(expected_index, actual_index + 1),\n                     subsequences.Get(expected_index + 1, actual_index));\n      }\n      subsequences.Set(expected_index + 1, actual_index + 1, subsequence_value);\n    }\n  }\n}\n\ntemplate <typename Container>\ntemplate <typename ActualContainer>\nauto UnifiedDiffMatcher<Container>::PrintDiff(\n    const ActualContainer& actual, Table<MatchResult>& match_results,\n    const Table<int>& subsequences,\n    testing::MatchResultListener* listener) const -> void {\n  // A line in the diff output.\n  struct DiffLine {\n    enum class Kind { Match, ActualOnly, ExpectedOnly };\n    Kind kind;\n    // Only used for `Match` and `ActualOnly`.\n    const ActualContainer::value_type* actual_value;\n    int expected_index;\n  };\n\n  llvm::SmallVector<DiffLine> diff;\n  // Reserve a quick upper bound of the size.\n  diff.reserve(expected_.size() + std::size(actual));\n\n  // Reconstruct the diff by backtracking from the end of the table.\n  int expected_index = expected_.size() - 1;\n  int actual_index = std::size(actual) - 1;\n  auto actual_it = std::end(actual) - 1;\n  while (expected_index >= 0 || actual_index >= 0) {\n    auto match_result = (expected_index >= 0 && actual_index >= 0)\n                            ? match_results.Get(expected_index, actual_index)\n                            : MatchResult::DoesNotMatch;\n    CARBON_CHECK(match_result != MatchResult::Unknown);\n    if (match_result == MatchResult::Matches) {\n      // The element is in both lists for the diff.\n      diff.push_back({.kind = DiffLine::Kind::Match,\n                      .actual_value = &*actual_it,\n                      .expected_index = expected_index});\n      --expected_index;\n      --actual_index;\n      --actual_it;\n    } else if (actual_index >= 0 &&\n               (expected_index < 0 ||\n                subsequences.Get(expected_index + 1, actual_index) >=\n                    subsequences.Get(expected_index, actual_index + 1))) {\n      // Dropping an element from `actual` preserves the LCS length, so treat it\n      // as an insertion.\n      diff.push_back({.kind = DiffLine::Kind::ActualOnly,\n                      .actual_value = &*actual_it,\n                      .expected_index = std::max(0, expected_index)});\n      --actual_index;\n      --actual_it;\n    } else {\n      // Otherwise, treat it as a deletion from `expected`.\n      diff.push_back({.kind = DiffLine::Kind::ExpectedOnly,\n                      .actual_value = nullptr,\n                      .expected_index = expected_index});\n      --expected_index;\n    }\n  }\n\n  struct PrintRange {\n    int begin;\n    int end;\n  };\n  llvm::SmallVector<PrintRange> print_ranges;\n\n  constexpr int ContextLines = 3;\n  for (auto [i, line] :\n       llvm::reverse(llvm::zip_equal(llvm::seq<int>(diff.size()), diff))) {\n    if (line.kind != DiffLine::Kind::Match) {\n      PrintRange range = {\n          .begin = std::max(0, i - ContextLines),\n          .end = std::min<int>(diff.size() - 1, i + ContextLines)};\n      if (print_ranges.empty() || print_ranges.back().begin > range.end + 1) {\n        print_ranges.push_back(range);\n      } else {\n        // Merge diffs with overlapping context.\n        print_ranges.back().begin = range.begin;\n      }\n    }\n  }\n\n  *listener << \"unified diff (- expected, + actual):\\n\";\n  for (const auto& range : print_ranges) {\n    *listener << \"=== diff in expected elements \"\n              << diff[range.end].expected_index + 1 << \" to \"\n              << diff[range.begin].expected_index + 1 << \" (1-based index):\\n\";\n    for (auto i : llvm::reverse(llvm::seq_inclusive(range.begin, range.end))) {\n      const auto& line = diff[i];\n      if (line.kind == DiffLine::Kind::Match) {\n        *listener << \"  \" << *line.actual_value << \"\\n\";\n      } else if (line.kind == DiffLine::Kind::ActualOnly) {\n        *listener << \"+ \" << *line.actual_value << \"\\n\";\n      } else {\n        *listener << \"- \";\n        expected_[line.expected_index].DescribeTo(listener->stream());\n        *listener << \"\\n\";\n      }\n    }\n  }\n  *listener << \"=== diff end\\n\";\n}\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_BASE_UNIFIED_DIFF_MATCHER_H_\n"
  },
  {
    "path": "testing/base/unified_diff_matcher_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/base/unified_diff_matcher.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"llvm/ADT/SmallVector.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing ::testing::Matcher;\nusing ::testing::StrEq;\n\n// Asserts that when expected does not match actual, the string\n// representation of the produced diff equals expected_diff.\nauto ExpectUnifiedDiff(const llvm::SmallVector<std::string>& actual,\n                       const llvm::SmallVector<Matcher<std::string>>& expected,\n                       const std::string& expected_diff) -> void {\n  testing::StringMatchResultListener listener;\n  EXPECT_FALSE(testing::ExplainMatchResult(\n      ElementsAreArrayWithUnifiedDiff(expected), actual, &listener));\n  EXPECT_THAT(listener.str(), testing::Eq(expected_diff));\n}\n\nTEST(UnifiedDiffMatcherTest, Matches) {\n  llvm::SmallVector<std::string> actual = {\"A\", \"B\", \"C\"};\n  llvm::SmallVector<Matcher<std::string>> expected = {StrEq(\"A\"), StrEq(\"B\"),\n                                                      StrEq(\"C\")};\n  EXPECT_THAT(actual, ElementsAreArrayWithUnifiedDiff(expected));\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchMissing) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 3 (1-based index):\n  A\n- is equal to \"B\"\n  C\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"A\", \"C\"}, {StrEq(\"A\"), StrEq(\"B\"), StrEq(\"C\")},\n                    ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchExtra) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 2 (1-based index):\n  A\n+ B\n  C\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"A\", \"B\", \"C\"}, {StrEq(\"A\"), StrEq(\"C\")}, ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchBoth) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 2 (1-based index):\n  A\n- is equal to \"C\"\n+ B\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"A\", \"B\"}, {StrEq(\"A\"), StrEq(\"C\")}, ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchMultiple) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 5 (1-based index):\n  A\n- is equal to \"B\"\n+ X\n  C\n- is equal to \"D\"\n+ Y\n  E\n=== diff end\n)\";\n  ExpectUnifiedDiff(\n      {\"A\", \"X\", \"C\", \"Y\", \"E\"},\n      {StrEq(\"A\"), StrEq(\"B\"), StrEq(\"C\"), StrEq(\"D\"), StrEq(\"E\")},\n      ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchLongContext) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 2 to 8 (1-based index):\n  1\n  2\n  3\n- is equal to \"X\"\n+ 4\n  5\n  6\n  7\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\"},\n                    {StrEq(\"0\"), StrEq(\"1\"), StrEq(\"2\"), StrEq(\"3\"), StrEq(\"X\"),\n                     StrEq(\"5\"), StrEq(\"6\"), StrEq(\"7\"), StrEq(\"8\")},\n                    ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, Mismatch5LineContext) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 7 (1-based index):\n- is equal to \"X\"\n+ 0\n  1\n  2\n  3\n  4\n  5\n- is equal to \"Y\"\n+ 6\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\"},\n                    {StrEq(\"X\"), StrEq(\"1\"), StrEq(\"2\"), StrEq(\"3\"), StrEq(\"4\"),\n                     StrEq(\"5\"), StrEq(\"Y\")},\n                    ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, Mismatch6LineContext) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 8 (1-based index):\n- is equal to \"X\"\n+ 0\n  1\n  2\n  3\n  4\n  5\n  6\n- is equal to \"Y\"\n+ 7\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\"},\n                    {StrEq(\"X\"), StrEq(\"1\"), StrEq(\"2\"), StrEq(\"3\"), StrEq(\"4\"),\n                     StrEq(\"5\"), StrEq(\"6\"), StrEq(\"Y\")},\n                    ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, Mismatch7LineContext) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 4 (1-based index):\n- is equal to \"X\"\n+ 0\n  1\n  2\n  3\n=== diff in expected elements 6 to 9 (1-based index):\n  5\n  6\n  7\n- is equal to \"Y\"\n+ 8\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\"},\n                    {StrEq(\"X\"), StrEq(\"1\"), StrEq(\"2\"), StrEq(\"3\"), StrEq(\"4\"),\n                     StrEq(\"5\"), StrEq(\"6\"), StrEq(\"7\"), StrEq(\"Y\")},\n                    ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchEmptyExpected) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 1 (1-based index):\n+ A\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"A\"}, {}, ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchEmptyActual) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 1 (1-based index):\n- is equal to \"A\"\n=== diff end\n)\";\n  ExpectUnifiedDiff({}, {StrEq(\"A\")}, ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchLongDifference) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 4 (1-based index):\n  1\n- is equal to \"2\"\n- is equal to \"3\"\n+ X\n+ Y\n+ Z\n  4\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"1\", \"X\", \"Y\", \"Z\", \"4\"},\n                    {StrEq(\"1\"), StrEq(\"2\"), StrEq(\"3\"), StrEq(\"4\")},\n                    ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchGreedyResyncActualMissing) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 6 (1-based index):\n  1\n  2\n- is equal to \"3\"\n+ X\n+ 7\n  4\n  5\n  6\n=== diff end\n)\";\n  ExpectUnifiedDiff({\"1\", \"2\", \"X\", \"7\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"},\n                    {StrEq(\"1\"), StrEq(\"2\"), StrEq(\"3\"), StrEq(\"4\"), StrEq(\"5\"),\n                     StrEq(\"6\"), StrEq(\"7\"), StrEq(\"8\"), StrEq(\"9\")},\n                    ExpectedDiff);\n}\n\nTEST(UnifiedDiffMatcherTest, MismatchGreedyResyncExpectedMissing) {\n  constexpr char ExpectedDiff[] = R\"(unified diff (- expected, + actual):\n=== diff in expected elements 1 to 7 (1-based index):\n  1\n  2\n- is equal to \"X\"\n- is equal to \"7\"\n+ 3\n  4\n  5\n  6\n=== diff end\n)\";\n  ExpectUnifiedDiff(\n      {\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\"},\n      {StrEq(\"1\"), StrEq(\"2\"), StrEq(\"X\"), StrEq(\"7\"), StrEq(\"4\"), StrEq(\"5\"),\n       StrEq(\"6\"), StrEq(\"7\"), StrEq(\"8\"), StrEq(\"9\")},\n      ExpectedDiff);\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/file_test/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_library\", \"cc_test\")\nload(\"rules.bzl\", \"file_test\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncc_library(\n    name = \"autoupdate\",\n    testonly = 1,\n    srcs = [\"autoupdate.cpp\"],\n    hdrs = [\n        \"autoupdate.h\",\n        \"line.h\",\n    ],\n    deps = [\n        \"//common:check\",\n        \"//common:ostream\",\n        \"//common:raw_string_ostream\",\n        \"//testing/base:file_helpers\",\n        \"@abseil-cpp//absl/strings\",\n        \"@abseil-cpp//absl/strings:string_view\",\n        \"@llvm-project//llvm:Support\",\n        \"@re2\",\n    ],\n)\n\ncc_library(\n    name = \"file_test_base\",\n    testonly = 1,\n    srcs = [\n        \"file_test_base.cpp\",\n        \"run_test.cpp\",\n        \"run_test.h\",\n        \"test_file.cpp\",\n    ],\n    hdrs = [\n        \"file_test_base.h\",\n        \"test_file.h\",\n    ],\n    deps = [\n        \":autoupdate\",\n        \":manifest\",\n        \"//common:build_data\",\n        \"//common:check\",\n        \"//common:error\",\n        \"//common:exe_path\",\n        \"//common:find\",\n        \"//common:init_llvm\",\n        \"//common:ostream\",\n        \"//common:pretty_stack_trace_function\",\n        \"//common:raw_string_ostream\",\n        \"//common:set\",\n        \"//testing/base:file_helpers\",\n        \"//testing/base:unified_diff_matcher\",\n        \"@abseil-cpp//absl/flags:flag\",\n        \"@abseil-cpp//absl/flags:parse\",\n        \"@abseil-cpp//absl/strings\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"test_file_test\",\n    size = \"small\",\n    srcs = [\"test_file_test.cpp\"],\n    deps = [\n        \":file_test_base\",\n        \":manifest_impl\",\n        \"//common:error_test_helpers\",\n        \"//testing/base:file_helpers\",\n        \"@googletest//:gtest\",\n    ],\n)\n\nfile_test(\n    name = \"file_test_base_test\",\n    size = \"small\",\n    srcs = [\"file_test_base_test.cpp\"],\n    data = glob([\"testdata/include_files/**\"]),\n    tests = glob(\n        [\"testdata/**\"],\n        exclude = [\"testdata/include_files/**\"],\n    ),\n    deps = [\n        \":file_test_base\",\n        \"//common:ostream\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\n# Note this is separate from the implementation; see the .h file.\ncc_library(\n    name = \"manifest\",\n    testonly = 1,\n    hdrs = [\"manifest.h\"],\n    deps = [\"@llvm-project//llvm:Support\"],\n)\n\n# Used through `file_test` in rules.bzl.\ncc_library(\n    name = \"manifest_impl\",\n    testonly = 1,\n    srcs = [\"manifest.cpp\"],\n    deps = [\":manifest\"],\n)\n"
  },
  {
    "path": "testing/file_test/README.md",
    "content": "# file_test\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\n<!--\n{% raw %}\nHides `{{` from jekyll's liquid parsing. Note endraw at the bottom.\n-->\n\n## BUILD\n\nA typical BUILD target will look like:\n\n```starlark\nload(\"rules.bzl\", \"file_test\")\n\nfile_test(\n    name = \"my_file_test\",\n    srcs = [\"my_file_test.cpp\"],\n    tests = glob([\"testdata/**\"]),\n    deps = [\n        \":my_lib\",\n        \"//testing/file_test:file_test_base\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n```\n\n## Implementation\n\nA typical implementation will look like:\n\n```cpp\n#include \"my_library.h\"\n\n#include \"testing/file_test/file_test_base.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nclass MyFileTest : public FileTestBase {\n public:\n  using FileTestBase::FileTestBase;\n\n  // Called as part of individual test executions.\n  auto Run(const llvm::SmallVector<llvm::StringRef>& test_args,\n           const llvm::SmallVector<TestFile>& test_files,\n           FILE* input_stream, llvm::raw_pwrite_stream& output_stream,\n           llvm::raw_pwrite_stream& error_stream)\n      -> ErrorOr<RunResult> override {\n    return MyFunctionality(test_args, input_stream, output_stream,\n                           error_stream);\n  }\n\n  // Provides arguments which are used in tests that don't provide ARGS.\n  auto GetDefaultArgs() -> llvm::SmallVector<std::string> override {\n    return {\"default_args\", \"%s\"};\n  }\n};\n\n}  // namespace\n\n// Registers for the framework to construct the tests.\nCARBON_FILE_TEST_FACTORY(MyFileTest);\n\n}  // namespace Carbon::Testing\n```\n\n## Filename `fail_` prefixes\n\nWhen a run fails, information about what pieces failed are returned on\n`RunResult`. This affects whether a `fail_` prefix on the file is required,\nincluding in combination with split-file tests (using the `// --- <filename>`\ncomment marker).\n\nThe main test file and any split-files must have a `fail_` prefix if and only if\nthey have an associated error. An exception is that the main test file may omit\n`fail_` when it contains split-files that have a `fail_` prefix.\n\n## Content replacement\n\nSome keywords can be inserted for content:\n\n-   ```\n    [[@LSP:<method>:<extra content>]]\n    [[@LSP-CALL:<method>:<extra content>]]\n    [[@LSP-NOTIFY:<method>:<extra content>]]\n    [[@LSP-REPLY:<id>:<extra content>]]\n    ```\n\n    Produces JSON for an LSP method call, notification, or reply. Each includes\n    the `Content-Length` header. The `:<extra content>` is optional, and may be\n    omitted.\n\n    The difference between the replacements mirrors LSP calling conventions:\n\n    -   `LSP` does a minimal JSON format, and is primarily intended for testing\n        errors.\n        -   `method`: Assigned from `<method>`.\n    -   `LSP-CALL` maps to\n        [Request Message](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage).\n        -   `method`: Assigned from `<method>`.\n        -   `id`: Automatically incremented across calls.\n        -   `params`: Optionally assigned from `<extra content>`.\n    -   `LSP-NOTIFY` maps to\n        [Notification Message](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notificationMessage).\n        -   `method`: Assigned from `<method>`.\n        -   `params`: Optionally assigned from `<extra content>`.\n    -   `LSP-REPLY` maps to\n        [Response Message](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#responseMessage).\n        -   `id`: Assigned from `<id>`.\n        -   `result`: Optionally assigned from `<extra content>`.\n\n    Additional substitutions are made to `<extra contents>` in the following\n    cases:\n\n    -   ```\n        [[@LSP-NOTIFY:textDocument/didOpen:\"textDocument\": {\n            \"uri\": \"file:/<filename>\",\n            \"text\": \"FROM_FILE_SPLIT\"\n        }]]\n        ```\n\n        The keyword `FROM_FILE_SPLIT` is substituted with the content of the\n        file split `<filename>`. All other properties are unchanged.\n\n-   ```\n    [[@TEST_NAME]]\n    ```\n\n    Replaces with the test name, which is the filename with the extension and\n    any `fail_` or `todo_` prefixes removed. For split files, this is based on\n    the split filename.\n\nThe `[[@` string is reserved for future replacements, but `[[` is allowed in\ncontent (comment markers don't allow `[[`).\n\n## Comment markers\n\nSettings in files are provided in comments, similar to `FileCheck` syntax.\n`bazel run :file_test -- --autoupdate` automatically constructs compatible\nCHECK:STDOUT: and CHECK:STDERR: lines.\n\nSupported comment markers are:\n\n-   ```\n    // AUTOUDPATE\n    // NOAUTOUPDATE\n    ```\n\n    Controls whether the checks in the file will be autoupdated if\n    `--autoupdate` is passed. Exactly one of these markers must be present. If\n    the file uses splits, the marker must currently be before any splits.\n\n    When autoupdating, `CHECK`s will be inserted starting below `AUTOUPDATE`.\n    When a `CHECK` has line information, autoupdate will try to insert the\n    `CHECK` immediately next to the line it's associated with, with stderr\n    `CHECK`s preceding the line and stdout `CHECK`s following the line. When\n    that happens, any subsequent `CHECK` lines without line information, or that\n    refer to lines appearing earlier, will immediately follow. As an exception,\n    if no `STDOUT` check line refers to any line in the test, all `STDOUT` check\n    lines are placed at the end of the file instead of immediately after\n    `AUTOUPDATE`.\n\n    When using split files, if the last split file is named\n    `// --- AUTOUPDATE-SPLIT`, all `CHECK`s will be added there; no line\n    associations occur.\n\n-   ```\n    // ARGS: <arguments>\n    ```\n\n    Provides a space-separated list of arguments, which will be passed to\n    RunWithFiles as test_args. These are intended for use by the command as\n    arguments.\n\n    Supported replacements within arguments are:\n\n    -   `%s`\n\n        Replaced with the list of files. Currently only allowed as a standalone\n        argument, not a substring.\n\n    -   `%t`\n\n        Replaced with `${TEST_TMPDIR}/temp_file`.\n\n    -   `%{identifier}`\n\n        Replaces some implementation-specific identifier with a value. (Mappings\n        provided by way of an optional `MyFileTest::GetArgReplacements`)\n\n    `ARGS` can be specified at most once. If not provided, the `FileTestBase`\n    child is responsible for providing default arguments.\n\n-   ```\n    // EXTRA-ARGS: <arguments>\n    ```\n\n    Same as `ARGS`, including substitution behavior, but appends to the argument\n    list instead of replacing it.\n\n    `EXTRA-ARGS` can be repeated, and provided with `ARGS`.\n\n-   ```\n    // INCLUDE-FILE: <path/from/repository/root>\n    ```\n\n    Includes the specified file in the test's virtual file system and adds the\n    included file's content to the current file's splits. Included files can\n    use:\n\n    -   `// ARGS`\n    -   `// EXTRA-ARGS`\n        -   Included `EXTRA-ARGS` will come before `EXTRA-ARGS` in the main test\n            file.\n    -   `// INCLUDE-FILE`\n    -   `// --- <filename>`\n\n    Included files will use `include_files/<filename>` for their name when a\n    split isn't provided.\n\n    This can be used to provide a minimal `Core` package (and `prelude` library)\n    in toolchain tests. See the\n    [toolchain docs](/toolchain/docs/adding_features.md) for how.\n\n-   ```\n    // SET-CAPTURE-CONSOLE-OUTPUT\n    ```\n\n    By default, stderr and stdout are expected to be piped through provided\n    streams. Adding this causes the test's own stderr and stdout to be captured\n    and added as well.\n\n    This should be avoided because we are partly ensuring that streams are an\n    API, but is helpful when wrapping Clang, where stderr is used directly.\n\n    `SET-CAPTURE-CONSOLE-OUTPUT` can be specified at most once.\n\n-   ```\n    // SET-CHECK-SUBSET\n    ```\n\n    By default, all lines of output must have a `CHECK` match. Adding this as a\n    option sets it so that non-matching lines are ignored. All provided\n    `CHECK:STDOUT:` and `CHECK:STDERR:` lines must still have a match in output.\n\n    `SET-CHECK-SUBSET`can be specified at most once.\n\n-   ```\n    // --- <filename>\n    ```\n\n    By default, all file content is provided to the test as a single file in\n    `test_files`. Using this marker allows the file to be split into multiple\n    files which will all be passed to `test_files`.\n\n    Files are not created on disk; instead, content is passed in through the\n    `fs` passed to `Run`.\n\n    If the filename is `STDIN`, it will be provided as `input_stream` instead of\n    in `test_files`. Currently, autoupdate can place `CHECK` lines in the\n    `STDIN` split; use `AUTOUPDATE-SPLIT` to avoid that (see `AUTOUPDATE` for\n    information).\n\n-   ```\n    // CHECK:STDOUT: <output line>\n    // CHECK:STDERR: <output line>\n    ```\n\n    These provide a match for output from the command. See `SET-CHECK-SUBSET`\n    for how to change from full to subset matching of output.\n\n    Output line matchers may contain `[[@LINE+offset]` and `{{regex}}` syntaxes,\n    similar to `FileCheck`.\n\n-   ```\n    // TIP: <tip>\n    ```\n\n    Tips like this are added by autoupdate, for example providing commands to\n    run the test directly. Tips have no impact on validation; the marker informs\n    autoupdate that it can update or remove them as needed.\n\n<!--\n{% endraw %}\n-->\n"
  },
  {
    "path": "testing/file_test/autoupdate.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/file_test/autoupdate.h\"\n\n#include <fstream>\n#include <string>\n#include <utility>\n\n#include \"absl/strings/str_replace.h\"\n#include \"absl/strings/string_view.h\"\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/ADT/DenseMap.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n#include \"testing/base/file_helpers.h\"\n\nnamespace Carbon::Testing {\n\n// Converts a matched line number to an int, trimming whitespace. Returns 0 if\n// there is no line number, to assist early placement.\nstatic auto ParseLineNumber(absl::string_view matched_line_number) -> int {\n  llvm::StringRef trimmed = matched_line_number;\n  trimmed = trimmed.trim();\n  if (trimmed.empty()) {\n    return 0;\n  }\n  // NOLINTNEXTLINE(google-runtime-int): API requirement.\n  long long val;\n  CARBON_CHECK(!llvm::getAsSignedInteger(trimmed, 10, val), \"{0}\",\n               matched_line_number);\n  return val;\n}\n\nFileTestAutoupdater::FileAndLineNumber::FileAndLineNumber(\n    const LineNumberReplacement* replacement, int file_number,\n    absl::string_view line_number)\n    : replacement(replacement),\n      file_number(file_number),\n      line_number(ParseLineNumber(line_number)) {}\n\nauto FileTestAutoupdater::CheckLine::RemapLineNumbers(\n    const llvm::DenseMap<llvm::StringRef, int>& file_to_number_map,\n    const llvm::DenseMap<std::pair<int, int>, int>& output_line_remap,\n    const llvm::SmallVector<int>& new_last_line_numbers) -> void {\n  // Only need to do remappings when there's a line number replacement.\n  if (!replacement_) {\n    return;\n  }\n\n  // Use a cursor for the line so that we can't keep matching the same\n  // content, which may occur when we keep a literal line number.\n  int line_offset = 0;\n  while (true) {\n    // Rebuild the cursor each time because we're editing the line, which\n    // could cause a reallocation.\n    absl::string_view line_cursor = line_;\n    line_cursor.remove_prefix(line_offset);\n    // Look for a line number to replace. There may be multiple, so we\n    // repeatedly check.\n    absl::string_view matched_filename;\n    absl::string_view matched_line_number;\n    if (replacement_->has_file) {\n      RE2::PartialMatch(line_cursor, *replacement_->re, &matched_filename,\n                        &matched_line_number);\n    } else {\n      RE2::PartialMatch(line_cursor, *replacement_->re, &matched_line_number);\n    }\n    if (matched_line_number.empty()) {\n      return;\n    }\n\n    // Map the matched filename to its file number.\n    auto matched_file_number = file_number();\n    if (replacement_->has_file) {\n      auto it = file_to_number_map.find(matched_filename);\n      if (it != file_to_number_map.end()) {\n        matched_file_number = it->second;\n      }\n    }\n\n    // Calculate the new line number (possibly with new CHECK lines added, or\n    // some removed).\n    int old_line_number = ParseLineNumber(matched_line_number);\n    int new_line_number = -1;\n    if (auto remapped =\n            output_line_remap.find({matched_file_number, old_line_number});\n        remapped != output_line_remap.end()) {\n      // Map old non-check lines to their new line numbers.\n      new_line_number = remapped->second;\n    } else {\n      // We assume unmapped references point to the end-of-file.\n      new_line_number = new_last_line_numbers[matched_file_number];\n    }\n\n    std::string replacement;\n    if (matched_file_number == output_file_number_) {\n      int offset = new_line_number - output_line_number_;\n      // Update the line offset in the CHECK line.\n      const char* offset_prefix = offset < 0 ? \"\" : \"+\";\n      replacement = llvm::formatv(\n          replacement_->line_formatv.c_str(),\n          llvm::formatv(\"[[@LINE{0}{1}]]\", offset_prefix, offset));\n    } else {\n      // If the CHECK was written to a different file from the file that it\n      // refers to, leave behind an absolute line reference rather than a\n      // cross-file offset.\n      replacement =\n          llvm::formatv(replacement_->line_formatv.c_str(), new_line_number);\n    }\n    auto line_number_offset = matched_line_number.data() - line_.data();\n    line_.replace(line_number_offset, matched_line_number.size(), replacement);\n\n    // Resume matching from the end of the replacement line number.\n    line_offset = line_number_offset + replacement.size();\n  }\n}\n\nauto FileTestAutoupdater::GetFileAndLineNumber(\n    const llvm::DenseMap<llvm::StringRef, int>& file_to_number_map,\n    int default_file_number, const std::string& check_line)\n    -> FileAndLineNumber {\n  for (const auto& replacement : line_number_replacements_) {\n    if (replacement.has_file) {\n      absl::string_view filename;\n      absl::string_view line_number;\n      if (RE2::PartialMatch(check_line, *replacement.re, &filename,\n                            &line_number)) {\n        if (auto it = file_to_number_map.find(filename);\n            it != file_to_number_map.end()) {\n          return FileAndLineNumber(&replacement, it->second, line_number);\n        } else {\n          return FileAndLineNumber(default_file_number);\n        }\n      }\n    } else {\n      // There's no file association, so we only look at the line, and assume\n      // it refers to the default file.\n      absl::string_view line_number;\n      if (RE2::PartialMatch(check_line, *replacement.re, &line_number)) {\n        return FileAndLineNumber(&replacement, default_file_number,\n                                 line_number);\n      }\n    }\n  }\n  return FileAndLineNumber(default_file_number);\n}\n\nauto FileTestAutoupdater::BuildCheckLines(llvm::StringRef output,\n                                          bool is_stderr) -> CheckLines {\n  if (output.empty()) {\n    return CheckLines({});\n  }\n\n  // %t substitution means we may see the temporary directory's path in output.\n  std::filesystem::path tmpdir_path = GetTempDirectory();\n  llvm::StringRef tmpdir = tmpdir_path.native();\n\n  llvm::SmallVector<llvm::StringRef> lines(llvm::split(output, '\\n'));\n  // It's typical that output ends with a newline, but we don't want to add a\n  // blank CHECK for it.\n  if (lines.back().empty()) {\n    lines.pop_back();\n  }\n\n  auto label =\n      is_stderr ? llvm::StringLiteral(\"STDERR\") : llvm::StringLiteral(\"STDOUT\");\n\n  // The default file number for when no specific file is found.\n  int default_file_number = 0;\n\n  CheckLineArray check_lines;\n  for (const auto& line : lines) {\n    // This code is relatively hot in our testing, and because when testing it\n    // isn't run with an optimizer we benefit from making it use simple\n    // constructs. For this reason, we avoid `llvm::formatv` and similar tools.\n    std::string check_line;\n    check_line.reserve(line.size() + label.size() + strlen(\"// CHECK:: \"));\n    check_line.append(\"// CHECK:\");\n    check_line.append(label);\n    check_line.append(\":\");\n    if (!line.empty()) {\n      check_line.append(\" \");\n      check_line.append(line);\n    }\n\n    // \\r and \\t are invisible characters worth marking.\n    // {{ and [[ are autoupdate syntax which we need to escape.\n    check_line = absl::StrReplaceAll(check_line, {{\"\\r\", R\"({{\\r}})\"},\n                                                  {\"\\t\", R\"({{\\t}})\"},\n                                                  {\"{{\", R\"({{\\{\\{}})\"},\n                                                  {\"[[\", R\"({{\\[\\[}})\"}});\n    // Add an empty regex to call out end-of-line whitespace.\n    if (check_line.ends_with(' ')) {\n      check_line.append(\"{{}}\");\n    }\n\n    // Ignore mentions of the temporary directory in output.\n    if (auto pos = check_line.find(tmpdir); pos != std::string::npos) {\n      check_line.replace(pos, tmpdir.size(), \"{{.+}}\");\n    }\n\n    do_extra_check_replacements_(check_line);\n    if (check_line.empty()) {\n      continue;\n    }\n\n    if (default_file_re_) {\n      absl::string_view filename;\n      if (RE2::PartialMatch(line, *default_file_re_, &filename)) {\n        auto it = file_to_number_map_.find(filename);\n        CARBON_CHECK(it != file_to_number_map_.end(),\n                     \"default_file_re had unexpected match in '{0}' (`{1}`)\",\n                     line, default_file_re_->pattern());\n        default_file_number = it->second;\n      }\n    }\n    auto file_and_line = GetFileAndLineNumber(file_to_number_map_,\n                                              default_file_number, check_line);\n    check_lines.push_back(CheckLine(file_and_line, check_line));\n  }\n  finalize_check_lines_(check_lines, is_stderr);\n  return CheckLines(check_lines);\n}\n\nauto FileTestAutoupdater::AddRemappedNonCheckLine() -> void {\n  new_lines_.push_back(non_check_line_);\n  CARBON_CHECK(output_line_remap_\n                   .insert({{non_check_line_->file_number(),\n                             non_check_line_->line_number()},\n                            ++output_line_number_})\n                   .second);\n}\n\nauto FileTestAutoupdater::AddTips() -> void {\n  CARBON_CHECK(tips_.empty(), \"Should only add tips once\");\n\n  tips_.reserve(4);\n  // This puts commands on a single line so that they can be easily copied.\n  tips_.emplace_back(\"// TIP: To test this file alone, run:\");\n  tips_.emplace_back(\"// TIP:   \" + test_command_);\n  tips_.emplace_back(\"// TIP: To dump output, run:\");\n  tips_.emplace_back(\"// TIP:   \" + dump_command_);\n\n  for (const auto& tip : tips_) {\n    new_lines_.push_back(&tip);\n    ++output_line_number_;\n  }\n}\n\nauto FileTestAutoupdater::ShouldAddCheckLine(const CheckLines& check_lines,\n                                             bool to_file_end) const -> bool {\n  return !autoupdate_split_file_ &&\n         check_lines.cursor != check_lines.lines.end() &&\n         (check_lines.cursor->file_number() < output_file_number_ ||\n          (check_lines.cursor->file_number() == output_file_number_ &&\n           (to_file_end || check_lines.cursor->line_number() <=\n                               non_check_line_->line_number())));\n}\n\nauto FileTestAutoupdater::AddCheckLines(CheckLines& check_lines,\n                                        bool to_file_end) -> void {\n  for (; ShouldAddCheckLine(check_lines, to_file_end); ++check_lines.cursor) {\n    new_lines_.push_back(check_lines.cursor);\n    check_lines.cursor->SetOutputLine(\n        to_file_end ? \"\" : non_check_line_->indent(), output_file_number_,\n        ++output_line_number_);\n  }\n}\n\nauto FileTestAutoupdater::FinishFile(bool is_last_file) -> void {\n  bool include_stdout = any_attached_stdout_lines_ || is_last_file;\n\n  // At the end of each file, print any remaining lines which are associated\n  // with the file.\n  if (ShouldAddCheckLine(stderr_, /*to_file_end=*/true) ||\n      (include_stdout && ShouldAddCheckLine(stdout_, /*to_file_end=*/true))) {\n    // Ensure there's a blank line before any trailing CHECKs.\n    if (!new_lines_.empty() && !new_lines_.back()->is_blank()) {\n      new_lines_.push_back(&blank_line_);\n      ++output_line_number_;\n    }\n\n    AddCheckLines(stderr_, /*to_file_end=*/true);\n    if (include_stdout) {\n      AddCheckLines(stdout_, /*to_file_end=*/true);\n    }\n  }\n\n  new_last_line_numbers_.push_back(output_line_number_);\n}\n\nauto FileTestAutoupdater::StartSplitFile() -> void {\n  // Advance the file.\n  ++output_file_number_;\n  output_line_number_ = 0;\n  CARBON_CHECK(output_file_number_ == non_check_line_->file_number(),\n               \"Non-sequential file: {0}\", non_check_line_->file_number());\n\n  // Each following file has precisely one split line.\n  CARBON_CHECK(non_check_line_->line_number() < 1,\n               \"Expected a split line, got {0}\", *non_check_line_);\n  // The split line is ignored when calculating line counts.\n  new_lines_.push_back(non_check_line_);\n\n  // Add any file-specific but line-unattached STDOUT messages here. STDERR is\n  // handled through the main loop because it's before the next line.\n  if (any_attached_stdout_lines_) {\n    AddCheckLines(stdout_, /*to_file_end=*/false);\n  }\n\n  ++non_check_line_;\n}\n\nauto FileTestAutoupdater::Run(bool dry_run) -> bool {\n  // Print everything until the autoupdate line.\n  while (non_check_line_->line_number() != autoupdate_line_number_) {\n    CARBON_CHECK(non_check_line_ != non_check_lines_.end() &&\n                     non_check_line_->file_number() == 0,\n                 \"Missed autoupdate?\");\n    AddRemappedNonCheckLine();\n    ++non_check_line_;\n  }\n\n  // Add the AUTOUPDATE line along with any early STDERR lines, so that the\n  // initial batch of CHECK lines have STDERR before STDOUT. This also ensures\n  // we don't insert a blank line before the STDERR checks if there are no more\n  // lines after AUTOUPDATE.\n  AddRemappedNonCheckLine();\n  AddTips();\n  if (!autoupdate_split_file_) {\n    AddCheckLines(stderr_, /*to_file_end=*/false);\n    if (any_attached_stdout_lines_) {\n      AddCheckLines(stdout_, /*to_file_end=*/false);\n    }\n  }\n  ++non_check_line_;\n\n  // Loop through remaining content.\n  while (non_check_line_ != non_check_lines_.end()) {\n    if (output_file_number_ < non_check_line_->file_number()) {\n      FinishFile(/*is_last_file=*/false);\n      StartSplitFile();\n      if (output_file_number_ == autoupdate_split_file_) {\n        break;\n      }\n      continue;\n    }\n\n    // STDERR check lines are placed before the line they refer to, or as\n    // early as possible if they don't refer to a line. Include all STDERR\n    // lines until we find one that wants to go later in the file.\n    AddCheckLines(stderr_, /*to_file_end=*/false);\n    AddRemappedNonCheckLine();\n\n    // STDOUT check lines are placed after the line they refer to, or at the\n    // end of the file if none of them refers to a line.\n    if (any_attached_stdout_lines_) {\n      AddCheckLines(stdout_, /*to_file_end=*/false);\n    }\n\n    ++non_check_line_;\n  }\n\n  // Clear out the autoupdate split, which would otherwise prevent check lines\n  // being written to the autoupdate file. When autoupdate_split_file_ was set,\n  // this will result in all check lines (and only check lines) being added to\n  // the split by FinishFile. We don't use autoupdate_split_file_ past this\n  // point.\n  autoupdate_split_file_ = std::nullopt;\n\n  FinishFile(/*is_last_file=*/true);\n\n  for (auto& check_line : stdout_.lines) {\n    check_line.RemapLineNumbers(file_to_number_map_, output_line_remap_,\n                                new_last_line_numbers_);\n  }\n  for (auto& check_line : stderr_.lines) {\n    check_line.RemapLineNumbers(file_to_number_map_, output_line_remap_,\n                                new_last_line_numbers_);\n  }\n\n  // Generate the autoupdated file.\n  RawStringOstream new_content_stream;\n  for (const auto& line : new_lines_) {\n    new_content_stream << *line << '\\n';\n  }\n  std::string new_content = new_content_stream.TakeStr();\n\n  // Update the file on disk if needed.\n  if (new_content == input_content_) {\n    return false;\n  }\n  if (!dry_run) {\n    std::ofstream out(file_test_path_);\n    out << new_content;\n  }\n  return true;\n}\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/file_test/autoupdate.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_FILE_TEST_AUTOUPDATE_H_\n#define CARBON_TESTING_FILE_TEST_AUTOUPDATE_H_\n\n#include <filesystem>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"llvm/ADT/DenseMap.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"re2/re2.h\"\n#include \"testing/file_test/line.h\"\n\nnamespace Carbon::Testing {\n\nclass FileTestAutoupdater {\n public:\n  struct LineNumberReplacement {\n    bool has_file;\n\n    // The line replacement. The pattern should match lines. If has_file,\n    // pattern should have a file and line group; otherwise, only a line group,\n    // but default_file_re should be provided.\n    //\n    // Uses shared_ptr for storage in SmallVector.\n    std::shared_ptr<RE2> re;\n\n    // line_formatv should provide {0} to substitute with [[@LINE...]] deltas.\n    std::string line_formatv;\n  };\n\n  // The file and line number that a CHECK line refers to, and the\n  // replacement from which they were determined, if any.\n  struct FileAndLineNumber {\n    explicit FileAndLineNumber(int file_number) : file_number(file_number) {}\n\n    explicit FileAndLineNumber(const LineNumberReplacement* replacement,\n                               int file_number, absl::string_view line_number);\n\n    const LineNumberReplacement* replacement = nullptr;\n    int file_number;\n    int line_number = -1;\n  };\n\n  // A CHECK line which is integrated into autoupdate output.\n  //\n  // `final` because we use pointer arithmetic on this type.\n  class CheckLine final : public FileTestLineBase {\n   public:\n    explicit CheckLine(FileAndLineNumber file_and_line_number, std::string line)\n        : FileTestLineBase(file_and_line_number.file_number,\n                           file_and_line_number.line_number),\n          replacement_(file_and_line_number.replacement),\n          line_(std::move(line)) {}\n\n    auto Print(llvm::raw_ostream& out) const -> void override {\n      out << indent_ << line_;\n    }\n\n    // When the location of the CHECK in output is known, we can set the indent\n    // and its line.\n    auto SetOutputLine(llvm::StringRef indent, int output_file_number,\n                       int output_line_number) -> void {\n      indent_ = indent;\n      output_file_number_ = output_file_number;\n      output_line_number_ = output_line_number;\n    }\n\n    // When the location of all lines in a file are known, we can set the line\n    // offset based on the target line.\n    auto RemapLineNumbers(\n        const llvm::DenseMap<llvm::StringRef, int>& file_to_number_map,\n        const llvm::DenseMap<std::pair<int, int>, int>& output_line_remap,\n        const llvm::SmallVector<int>& new_last_line_numbers) -> void;\n\n    auto line() const -> llvm::StringRef { return line_; }\n\n    auto is_blank() const -> bool override { return false; }\n\n   private:\n    const LineNumberReplacement* replacement_;\n    std::string line_;\n    llvm::StringRef indent_;\n    int output_file_number_ = -1;\n    int output_line_number_ = -1;\n  };\n\n  using CheckLineArray = llvm::SmallVector<FileTestAutoupdater::CheckLine>;\n\n  explicit FileTestAutoupdater(\n      const std::filesystem::path& file_test_path, std::string test_command,\n      std::string dump_command, llvm::StringRef input_content,\n      const llvm::SmallVector<llvm::StringRef>& filenames,\n      int autoupdate_line_number, bool autoupdate_split,\n      const llvm::SmallVector<FileTestLine>& non_check_lines,\n      llvm::StringRef actual_stdout, llvm::StringRef actual_stderr,\n      const std::optional<RE2>& default_file_re,\n      const llvm::SmallVector<LineNumberReplacement>& line_number_replacements,\n      std::function<auto(std::string&)->void> do_extra_check_replacements,\n      std::function<auto(CheckLineArray&, bool)->void> finalize_check_lines)\n      : file_test_path_(file_test_path),\n        test_command_(std::move(test_command)),\n        dump_command_(std::move(dump_command)),\n        input_content_(input_content),\n        autoupdate_line_number_(autoupdate_line_number),\n        non_check_lines_(non_check_lines),\n        default_file_re_(default_file_re),\n        line_number_replacements_(line_number_replacements),\n        do_extra_check_replacements_(std::move(do_extra_check_replacements)),\n        finalize_check_lines_(std::move(finalize_check_lines)),\n        autoupdate_split_file_(\n            autoupdate_split ? std::optional(filenames.size()) : std::nullopt),\n        file_to_number_map_(BuildFileToNumberMap(filenames)),\n        // BuildCheckLines should only be called after other member\n        // initialization.\n        stdout_(BuildCheckLines(actual_stdout, /*is_stderr=*/false)),\n        stderr_(BuildCheckLines(actual_stderr, /*is_stderr=*/true)),\n        any_attached_stdout_lines_(llvm::any_of(\n            stdout_.lines,\n            [&](const CheckLine& line) { return line.line_number() != -1; })),\n        non_check_line_(non_check_lines_.begin()) {\n    for (const auto& replacement : line_number_replacements_) {\n      CARBON_CHECK(replacement.has_file || default_file_re_,\n                   \"For replacement with pattern `{0}` to have has_file=false, \"\n                   \"override GetDefaultFileRE.\",\n                   replacement.re->pattern());\n      CARBON_CHECK(replacement.re->ok(), \"Invalid line replacement RE2: {0}\",\n                   replacement.re->error());\n    }\n  }\n\n  // Automatically updates CHECKs in the provided file when dry_run=false.\n  // Returns true if generated file content differs from actual file content.\n  auto Run(bool dry_run) -> bool;\n\n private:\n  // A TIP line added by autoupdate. Not associated with any line in output.\n  class TipLine : public FileTestLineBase {\n   public:\n    explicit TipLine(std::string line)\n        : FileTestLineBase(-1, -1), line_(std::move(line)) {}\n\n    auto Print(llvm::raw_ostream& out) const -> void override { out << line_; }\n\n    auto is_blank() const -> bool override { return line_.empty(); }\n\n   private:\n    std::string line_;\n  };\n\n  // Clusters information for stdout and stderr.\n  struct CheckLines {\n    explicit CheckLines(CheckLineArray lines)\n        : lines(std::move(lines)), cursor(this->lines.begin()) {}\n\n    // The full list of check lines.\n    CheckLineArray lines;\n    // An iterator into check_lines.\n    CheckLine* cursor;\n  };\n\n  // Looks for the patterns in the line. Returns the first match, or defaulted\n  // information if not found.\n  auto GetFileAndLineNumber(\n      const llvm::DenseMap<llvm::StringRef, int>& file_to_number_map,\n      int default_file_number, const std::string& check_line)\n      -> FileAndLineNumber;\n\n  // Builds a mapping from file name to file number.\n  auto BuildFileToNumberMap(const llvm::SmallVector<llvm::StringRef>& filenames)\n      -> llvm::DenseMap<llvm::StringRef, int> {\n    llvm::DenseMap<llvm::StringRef, int> file_to_number_map;\n    for (auto [number, name] : llvm::enumerate(filenames)) {\n      file_to_number_map.insert({name, number});\n    }\n    return file_to_number_map;\n  }\n\n  // Builds CheckLine lists for autoupdate.\n  auto BuildCheckLines(llvm::StringRef output, bool is_stderr) -> CheckLines;\n\n  // Adds a non-check line to the new_lines and output_line_remap. The caller\n  // still needs to advance the cursor when ready.\n  auto AddRemappedNonCheckLine() -> void;\n\n  // Adds TIP lines for file_test usage.\n  auto AddTips() -> void;\n\n  // Returns true if there's a CheckLine that should be added at\n  // `to_line_number`.\n  auto ShouldAddCheckLine(const CheckLines& check_lines, bool to_file_end) const\n      -> bool;\n\n  // Adds check_lines until output reaches:\n  // - If not to_file_end, non_check_line.\n  // - If to_file_end, the end of the file.\n  auto AddCheckLines(CheckLines& check_lines, bool to_file_end) -> void;\n\n  // Adds remaining check lines for the current file. stderr is always included,\n  // but stdout is only included when either any_attached_stdout_lines_ or\n  // is_last_file is true.\n  auto FinishFile(bool is_last_file) -> void;\n\n  // Starts a new split file, updating file and line numbers. Advances past the\n  // split line.\n  auto StartSplitFile() -> void;\n\n  // Passed-in state.\n  const std::filesystem::path& file_test_path_;\n  std::string test_command_;\n  std::string dump_command_;\n  llvm::StringRef input_content_;\n  int autoupdate_line_number_;\n  const llvm::SmallVector<FileTestLine>& non_check_lines_;\n  const std::optional<RE2>& default_file_re_;\n  const llvm::SmallVector<LineNumberReplacement>& line_number_replacements_;\n  std::function<auto(std::string&)->void> do_extra_check_replacements_;\n  std::function<auto(CheckLineArray&, bool)->void> finalize_check_lines_;\n\n  // If we have an autoupdate split that still needs to be processed, the file\n  // number of the autoupdate split. Otherwise, this is nullopt.\n  std::optional<int> autoupdate_split_file_;\n\n  // Generated TIP lines, from AddTips.\n  llvm::SmallVector<TipLine> tips_;\n\n  // Mapping from file names to file numbers.\n  llvm::DenseMap<llvm::StringRef, int> file_to_number_map_;\n\n  // The constructed CheckLine list and cursor.\n  CheckLines stdout_;\n  CheckLines stderr_;\n\n  // Whether any stdout lines have an associated line number.\n  bool any_attached_stdout_lines_;\n\n  // Iterators for the main Run loop.\n  const FileTestLine* non_check_line_;\n\n  // Tracks the new last line numbers for each file.\n  llvm::SmallVector<int> new_last_line_numbers_;\n\n  // A reusable blank line. new_lines_ can contain a reference back to it.\n  const FileTestLine blank_line_ = FileTestLine(-1, -1, \"\");\n\n  // Stitched-together content.\n  llvm::SmallVector<const FileTestLineBase*> new_lines_;\n\n  // Maps {file_number, original line number} to a new line number.\n  llvm::DenseMap<std::pair<int, int>, int> output_line_remap_;\n\n  // The current output file number; mainly used for tracking progression.\n  int output_file_number_ = 0;\n  // The current output line number in stitched content.\n  int output_line_number_ = 0;\n};\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_FILE_TEST_AUTOUPDATE_H_\n"
  },
  {
    "path": "testing/file_test/autoupdate_testdata.sh",
    "content": "#!/usr/bin/env bash\n\n# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"$(dirname \"$0\")/../../scripts/run_bazel.py\" \\\n  run --experimental_convenience_symlinks=ignore \\\n  --ui_event_filters=-info,-stdout,-stderr,-finish \\\n  //testing/file_test:file_test_base_test -- --autoupdate \"$@\"\n"
  },
  {
    "path": "testing/file_test/file_test_base.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// Implementation-wise, this:\n//\n// - Uses the registered `FileTestFactory` to construct `FileTestBase`\n//   instances.\n// - Constructs a `FileTestCase` that wraps each `FileTestBase` instance to\n//   register with googletest, and to provide the actual `TestBody`.\n// - Using `FileTestEventListener`, runs tests in parallel prior to normal\n//   googletest execution.\n//   - This is required to support `--gtest_filter` and access `should_run`.\n//   - Runs each `FileTestBase` instance to cache the `TestFile` on\n//     `FileTestInfo`.\n//   - Determines whether autoupdate would make changes, autoupdating if\n//     requested.\n// - When googletest would normally execute the test, `FileTestCase::TestBody`\n//   instead uses the cached state on `FileTestInfo`.\n//   - This only occurs when neither autoupdating nor dumping output.\n\n#include \"testing/file_test/file_test_base.h\"\n\n#include <atomic>\n#include <chrono>\n#include <cstdlib>\n#include <filesystem>\n#include <functional>\n#include <memory>\n#include <mutex>\n#include <optional>\n#include <string>\n#include <string_view>\n#include <system_error>\n#include <utility>\n\n#include \"absl/flags/flag.h\"\n#include \"absl/flags/parse.h\"\n#include \"absl/strings/str_join.h\"\n#include \"common/build_data.h\"\n#include \"common/check.h\"\n#include \"common/error.h\"\n#include \"common/exe_path.h\"\n#include \"common/init_llvm.h\"\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/Support/CrashRecoveryContext.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n#include \"llvm/Support/MemoryBuffer.h\"\n#include \"llvm/Support/PrettyStackTrace.h\"\n#include \"llvm/Support/Process.h\"\n#include \"llvm/Support/ThreadPool.h\"\n#include \"testing/base/unified_diff_matcher.h\"\n#include \"testing/file_test/autoupdate.h\"\n#include \"testing/file_test/run_test.h\"\n#include \"testing/file_test/test_file.h\"\n\nABSL_FLAG(std::vector<std::string>, file_tests, {},\n          \"A comma-separated list of repo-relative names of test files. \"\n          \"Similar to and overrides `--gtest_filter`, but doesn't require the \"\n          \"test class name to be known.\");\nABSL_FLAG(bool, autoupdate, false,\n          \"Instead of verifying files match test output, autoupdate files \"\n          \"based on test output.\");\nABSL_FLAG(unsigned int, threads, 0,\n          \"Number of threads to use when autoupdating tests, or 0 to \"\n          \"automatically determine a thread count.\");\nABSL_FLAG(bool, dump_output, false,\n          \"Instead of verifying files match test output, directly dump output \"\n          \"to stderr.\");\nABSL_FLAG(int, print_slowest_tests, 5,\n          \"The number of tests to print when showing slowest tests. Set to 0 \"\n          \"to disabling printing. Set to -1 to print all tests.\");\n\nnamespace Carbon::Testing {\n\n// Information for a test case.\nstruct FileTestInfo {\n  // The name.\n  std::string test_name;\n\n  // A factory function for creating the test object.\n  std::function<auto()->std::unique_ptr<FileTestBase>> factory_fn;\n\n  // gtest's information about the test.\n  ::testing::TestInfo* registered_test;\n\n  // The test result, set after running.\n  std::optional<ErrorOr<TestFile>> test_result;\n\n  // Whether running autoupdate would change (or when autoupdating, already\n  // changed) the test file. This may be true even if output passes test\n  // expectations.\n  bool autoupdate_differs = false;\n\n  // Time spent in the test total, including processing and autoupdate.\n  std::chrono::milliseconds elapsed_ms = std::chrono::milliseconds(0);\n};\n\n// Adapts a `FileTestBase` instance to gtest for outputting results.\nclass FileTestCase : public testing::Test {\n public:\n  explicit FileTestCase(FileTestInfo* test_info) : test_info_(test_info) {}\n\n  // Runs a test and compares output. This keeps output split by line so that\n  // issues are a little easier to identify by the different line.\n  auto TestBody() -> void final;\n\n private:\n  FileTestInfo* test_info_;\n};\n\n// Splits outputs to string_view because gtest handles string_view by default.\nstatic auto SplitOutput(llvm::StringRef output)\n    -> llvm::SmallVector<std::string_view> {\n  if (output.empty()) {\n    return {};\n  }\n  llvm::SmallVector<llvm::StringRef> lines;\n  llvm::StringRef(output).split(lines, \"\\n\");\n  return llvm::SmallVector<std::string_view>(lines.begin(), lines.end());\n}\n// Verify that the success and `fail_` prefix use correspond. Separately handle\n// both cases for clearer test failures.\nstatic auto CompareFailPrefix(llvm::StringRef filename, bool success) -> void {\n  if (success) {\n    EXPECT_FALSE(filename.starts_with(\"fail_\"))\n        << \"`\" << filename\n        << \"` succeeded; if success is expected, remove the `fail_` \"\n           \"prefix.\";\n  } else {\n    EXPECT_TRUE(filename.starts_with(\"fail_\"))\n        << \"`\" << filename\n        << \"` failed; if failure is expected, add the `fail_` prefix.\";\n  }\n}\n\n// Returns the requested bazel command string for the given execution mode.\nauto FileTestBase::GetBazelCommand(BazelMode mode) -> std::string {\n  RawStringOstream args;\n  args << \"bazel \" << ((mode == BazelMode::Test) ? \"test\" : \"run\") << \" \"\n       << BuildData::TargetName << \" \";\n\n  switch (mode) {\n    case BazelMode::Autoupdate:\n      args << \"-- --autoupdate \";\n      break;\n\n    case BazelMode::Dump:\n      args << \"-- --dump_output \";\n      break;\n\n    case BazelMode::Test:\n      args << \"--test_arg=\";\n      break;\n  }\n\n  args << \"--file_tests=\";\n  args << test_name();\n  return args.TakeStr();\n}\n\n// Runs the FileTestAutoupdater, returning the result.\nstatic auto RunAutoupdater(FileTestBase* test_base, const TestFile& test_file,\n                           bool dry_run) -> bool {\n  if (!test_file.autoupdate_line_number) {\n    return false;\n  }\n\n  llvm::SmallVector<llvm::StringRef> filenames;\n  filenames.reserve(test_file.non_check_lines.size());\n  if (test_file.has_splits) {\n    // There are splits, so we provide an empty name for the first file.\n    filenames.push_back({});\n  }\n  for (const auto& file : test_file.file_splits) {\n    filenames.push_back(file.filename);\n  }\n\n  llvm::ArrayRef expected_filenames = filenames;\n  if (filenames.size() > 1) {\n    expected_filenames.consume_front();\n  }\n\n  return FileTestAutoupdater(\n             std::filesystem::absolute(test_base->test_name().str()),\n             test_base->GetBazelCommand(FileTestBase::BazelMode::Test),\n             test_base->GetBazelCommand(FileTestBase::BazelMode::Dump),\n             test_file.input_content, filenames,\n             *test_file.autoupdate_line_number, test_file.autoupdate_split,\n             test_file.non_check_lines, test_file.actual_stdout,\n             test_file.actual_stderr,\n             test_base->GetDefaultFileRE(expected_filenames),\n             test_base->GetLineNumberReplacements(expected_filenames),\n             [&](std::string& line) {\n               test_base->DoExtraCheckReplacements(line);\n             },\n             [&](FileTestBase::CheckLineArray& lines, bool is_stderr) {\n               test_base->FinalizeCheckLines(lines, is_stderr);\n             })\n      .Run(dry_run);\n}\n\nauto FileTestCase::TestBody() -> void {\n  if (absl::GetFlag(FLAGS_autoupdate) || absl::GetFlag(FLAGS_dump_output)) {\n    return;\n  }\n\n  CARBON_CHECK(test_info_->test_result,\n               \"Expected test to be run prior to TestBody: {0}\",\n               test_info_->test_name);\n\n  ASSERT_TRUE(test_info_->test_result->ok())\n      << test_info_->test_result->error();\n  auto test_filename = std::filesystem::path(test_info_->test_name).filename();\n\n  // Check success/failure against `fail_` prefixes.\n  TestFile& test_file = **(test_info_->test_result);\n  if (test_file.run_result.per_file_success.empty()) {\n    CompareFailPrefix(test_filename.string(), test_file.run_result.success);\n  } else {\n    bool require_overall_failure = false;\n    for (const auto& [filename, success] :\n         test_file.run_result.per_file_success) {\n      CompareFailPrefix(filename, success);\n      if (!success) {\n        require_overall_failure = true;\n      }\n    }\n\n    if (require_overall_failure) {\n      EXPECT_FALSE(test_file.run_result.success)\n          << \"There is a per-file failure expectation, so the overall result \"\n             \"should have been a failure.\";\n    } else {\n      // Individual files all succeeded, so the prefix is enforced on the main\n      // test file.\n      CompareFailPrefix(test_filename.string(), test_file.run_result.success);\n    }\n  }\n\n  // Check results. Include a reminder for NOAUTOUPDATE tests.\n  std::unique_ptr<testing::ScopedTrace> scoped_trace;\n  if (!test_file.autoupdate_line_number) {\n    scoped_trace = std::make_unique<testing::ScopedTrace>(\n        __FILE__, __LINE__,\n        \"This file is NOAUTOUPDATE, so expected differences require manual \"\n        \"updates.\");\n  }\n  if (test_file.check_subset) {\n    EXPECT_THAT(SplitOutput(test_file.actual_stdout),\n                IsSupersetOf(test_file.expected_stdout))\n        << \"Actual text:\\n\"\n        << test_file.actual_stdout;\n    EXPECT_THAT(SplitOutput(test_file.actual_stderr),\n                IsSupersetOf(test_file.expected_stderr))\n        << \"Actual text:\\n\"\n        << test_file.actual_stderr;\n\n  } else {\n    EXPECT_THAT(SplitOutput(test_file.actual_stdout),\n                ElementsAreArrayWithUnifiedDiff(test_file.expected_stdout));\n    EXPECT_THAT(SplitOutput(test_file.actual_stderr),\n                ElementsAreArrayWithUnifiedDiff(test_file.expected_stderr));\n  }\n\n  if (HasFailure()) {\n    llvm::errs() << \"\\nTo test this file alone, run:\\n  \"\n                 << test_info_->factory_fn()->GetBazelCommand(\n                        FileTestBase::BazelMode::Test)\n                 << \"\\n\\n\";\n    if (!test_file.autoupdate_line_number) {\n      llvm::errs() << \"\\nThis test is NOAUTOUPDATE.\\n\\n\";\n    }\n  }\n  if (test_info_->autoupdate_differs) {\n    ADD_FAILURE() << \"Autoupdate would make changes to the file content. Run:\\n\"\n                  << test_info_->factory_fn()->GetBazelCommand(\n                         FileTestBase::BazelMode::Autoupdate);\n  }\n}\n\nauto FileTestBase::GetLineNumberReplacements(\n    llvm::ArrayRef<llvm::StringRef> filenames) const\n    -> llvm::SmallVector<LineNumberReplacement> {\n  return {{.has_file = true,\n           .re = std::make_shared<RE2>(\n               llvm::formatv(R\"(({0}):(\\d+)?)\", llvm::join(filenames, \"|\"))),\n           .line_formatv = R\"({0})\"}};\n}\n\n// If `--file_tests` is set, transform it into a `--gtest_filter`.\nstatic auto MaybeApplyFileTestsFlag(llvm::StringRef factory_name) -> void {\n  if (absl::GetFlag(FLAGS_file_tests).empty()) {\n    return;\n  }\n  RawStringOstream filter;\n  llvm::ListSeparator sep(\":\");\n  for (const auto& file : absl::GetFlag(FLAGS_file_tests)) {\n    filter << sep << factory_name << \".\" << file;\n  }\n  absl::SetFlag(&FLAGS_gtest_filter, filter.TakeStr());\n}\n\n// Loads tests from the manifest file, and registers them for execution. The\n// vector is taken as an output parameter so that the address of entries is\n// stable for the factory.\nstatic auto RegisterTests(FileTestFactory* test_factory,\n                          llvm::StringRef exe_path,\n                          llvm::SmallVectorImpl<FileTestInfo>& tests)\n    -> ErrorOr<Success> {\n  // Prepare the vector first, so that the location of entries won't change.\n  for (auto& test_name : GetFileTestManifest()) {\n    tests.push_back({.test_name = test_name});\n  }\n\n  // Amend entries with factory functions.\n  for (auto& test : tests) {\n    const std::string& test_name = test.test_name;\n    test.factory_fn = [test_factory, exe_path, &test_name]() {\n      return test_factory->factory_fn(exe_path, test_name);\n    };\n    test.registered_test = testing::RegisterTest(\n        test_factory->name, test_name.c_str(), nullptr, test_name.c_str(),\n        __FILE__, __LINE__, [&test]() { return new FileTestCase(&test); });\n  }\n  return Success();\n}\n\n// Implements the parallel test execution through gtest's listener support.\nclass FileTestEventListener : public testing::EmptyTestEventListener {\n public:\n  explicit FileTestEventListener(llvm::MutableArrayRef<FileTestInfo> tests)\n      : tests_(tests) {}\n\n  // Runs test during start, after `should_run` is initialized. This is\n  // multi-threaded to get extra speed.\n  auto OnTestProgramStart(const testing::UnitTest& /*unit_test*/)\n      -> void override;\n\n private:\n  llvm::MutableArrayRef<FileTestInfo> tests_;\n};\n\n// Returns true if the main thread should be used to run tests. This is if\n// either --dump_output is specified, or only 1 thread is needed to run tests.\nstatic auto SingleThreaded(llvm::ArrayRef<FileTestInfo> tests) -> bool {\n  if (absl::GetFlag(FLAGS_dump_output) || absl::GetFlag(FLAGS_threads) == 1) {\n    return true;\n  }\n\n  bool found_test_to_run = false;\n  for (const auto& test : tests) {\n    if (!test.registered_test->should_run()) {\n      continue;\n    }\n    if (found_test_to_run) {\n      // At least two tests will run, so multi-threaded.\n      return false;\n    }\n    // Found the first test to run.\n    found_test_to_run = true;\n  }\n  // 0 or 1 test will be run, so single-threaded.\n  return true;\n}\n\n// Runs the test in the section that would be inside a lock, possibly inside a\n// CrashRecoveryContext.\nstatic auto RunSingleTestHelper(FileTestInfo& test, FileTestBase& test_instance)\n    -> void {\n  Timer timer;\n  // Add a crash trace entry with the single-file test command.\n  std::string test_command =\n      test_instance.GetBazelCommand(FileTestBase::BazelMode::Test);\n  llvm::PrettyStackTraceString stack_trace_entry(test_command.c_str());\n\n  if (auto err = RunTestFile(test_instance, absl::GetFlag(FLAGS_dump_output),\n                             **test.test_result);\n      !err.ok()) {\n    test.test_result = std::move(err).error();\n  }\n  test.elapsed_ms += timer.elapsed_ms();\n}\n\n// Runs a single test. Uses a CrashRecoveryContext, and returns false on a\n// crash. For test_elapsed_ms, try to exclude time spent waiting on\n// output_mutex.\nstatic auto RunSingleTest(FileTestInfo& test, bool single_threaded,\n                          std::mutex& output_mutex) -> bool {\n  std::unique_ptr<FileTestBase> test_instance(test.factory_fn());\n\n  if (absl::GetFlag(FLAGS_dump_output)) {\n    std::unique_lock<std::mutex> lock(output_mutex);\n    llvm::errs() << \"\\n--- Dumping: \" << test.test_name << \"\\n\\n\";\n  } else if (single_threaded) {\n    std::unique_lock<std::mutex> lock(output_mutex);\n    llvm::errs() << \"\\nTEST: \" << test.test_name << ' ';\n  }\n\n  // Load expected output.\n  Timer process_timer;\n  test.test_result = ProcessTestFile(test_instance->test_name(),\n                                     absl::GetFlag(FLAGS_autoupdate));\n  test.elapsed_ms = process_timer.elapsed_ms();\n\n  if (test.test_result->ok()) {\n    // Execution must be serialized for either serial tests or console\n    // output.\n    std::unique_lock<std::mutex> output_lock;\n\n    if ((*test.test_result)->capture_console_output ||\n        !test_instance->AllowParallelRun()) {\n      output_lock = std::unique_lock<std::mutex>(output_mutex);\n    }\n\n    if (single_threaded) {\n      RunSingleTestHelper(test, *test_instance);\n    } else {\n      // Use a crash recovery context to try to get a stack trace when\n      // multiple threads may crash in parallel, which otherwise leads to the\n      // program aborting without printing a stack trace.\n      llvm::CrashRecoveryContext crc;\n      crc.DumpStackAndCleanupOnFailure = true;\n      if (!crc.RunSafely([&] { RunSingleTestHelper(test, *test_instance); })) {\n        return false;\n      }\n    }\n  }\n\n  if (!test.test_result->ok()) {\n    std::unique_lock<std::mutex> lock(output_mutex);\n    if (!single_threaded) {\n      llvm::errs() << \"\\n\" << test.test_name << \": \";\n    }\n    llvm::errs() << test.test_result->error().message() << \"\\n\";\n    return true;\n  }\n\n  Timer autoupdate_timer;\n  test.autoupdate_differs =\n      RunAutoupdater(test_instance.get(), **test.test_result,\n                     /*dry_run=*/!absl::GetFlag(FLAGS_autoupdate));\n  test.elapsed_ms += autoupdate_timer.elapsed_ms();\n\n  std::unique_lock<std::mutex> lock(output_mutex);\n  if (absl::GetFlag(FLAGS_dump_output)) {\n    llvm::outs().flush();\n    const TestFile& test_file = **test.test_result;\n    llvm::errs() << \"\\n--- Exit with success: \"\n                 << (test_file.run_result.success ? \"true\" : \"false\")\n                 << \"\\n--- Autoupdate differs: \"\n                 << (test.autoupdate_differs ? \"true\" : \"false\") << \"\\n\";\n  } else {\n    llvm::errs() << (test.autoupdate_differs ? \"!\" : \".\");\n  }\n\n  return true;\n}\n\nauto FileTestEventListener::OnTestProgramStart(\n    const testing::UnitTest& /*unit_test*/) -> void {\n  bool single_threaded = SingleThreaded(tests_);\n\n  std::unique_ptr<llvm::ThreadPoolInterface> pool;\n  if (single_threaded) {\n    pool = std::make_unique<llvm::SingleThreadExecutor>();\n  } else {\n    // Enable the CRC for use in `RunSingleTest`.\n    llvm::CrashRecoveryContext::Enable();\n    llvm::ThreadPoolStrategy thread_strategy = {\n        .ThreadsRequested = absl::GetFlag(FLAGS_threads),\n        // Disable hyper threads to reduce contention.\n        .UseHyperThreads = false};\n    pool = std::make_unique<llvm::DefaultThreadPool>(thread_strategy);\n  }\n  if (!absl::GetFlag(FLAGS_dump_output)) {\n    llvm::errs() << \"Running tests with \" << pool->getMaxConcurrency()\n                 << \" thread(s)\\n\";\n  }\n\n  // Guard access to output (stdout and stderr).\n  std::mutex output_mutex;\n\n  std::atomic<bool> crashed = false;\n  Timer all_timer;\n  int run_count = 0;\n  for (auto& test : tests_) {\n    if (!test.registered_test->should_run()) {\n      continue;\n    }\n    ++run_count;\n\n    pool->async([&] {\n      // If any thread crashed, don't try running more.\n      if (crashed) {\n        return;\n      }\n\n      if (!RunSingleTest(test, single_threaded, output_mutex)) {\n        crashed = true;\n      }\n    });\n  }\n\n  pool->wait();\n  if (crashed) {\n    // Abort rather than returning so that we don't get a LeakSanitizer report.\n    // We expect to have leaked memory if one or more of our tests crashed.\n    std::abort();\n  }\n\n  // Calculate the total test time.\n  auto all_elapsed_ms = all_timer.elapsed_ms();\n  auto total_elapsed_ms = std::chrono::milliseconds(0);\n  for (auto& test : tests_) {\n    total_elapsed_ms += test.elapsed_ms;\n  }\n\n  llvm::errs() << \"\\nRan \" << run_count << \" tests in \"\n               << all_elapsed_ms.count() << \" ms wall time, \"\n               << total_elapsed_ms.count() << \" ms across threads\\n\";\n\n  // When there are multiple tests, give additional timing details, particularly\n  // slowest tests.\n  auto print_slowest_tests = absl::GetFlag(FLAGS_print_slowest_tests);\n  if (run_count > 1 && print_slowest_tests != 0) {\n    // Sort in a copy so that `FileTestCase` pointers to the original tests\n    // remain stable.\n    llvm::SmallVector<const FileTestInfo*> sorted_tests(\n        llvm::make_pointer_range(tests_));\n    llvm::sort(sorted_tests,\n               [](const FileTestInfo* lhs, const FileTestInfo* rhs) {\n                 return lhs->elapsed_ms > rhs->elapsed_ms;\n               });\n\n    llvm::errs() << \"  Slowest tests:\\n\";\n    int count = print_slowest_tests > 0 ? print_slowest_tests : run_count;\n    for (const auto* test : llvm::ArrayRef(sorted_tests).take_front(count)) {\n      std::chrono::milliseconds run_ms(0);\n      if (test->test_result && test->test_result->ok()) {\n        run_ms = test->test_result.value()->run_elapsed_ms;\n      }\n      llvm::errs() << \"  - \" << test->test_name << \": \"\n                   << test->elapsed_ms.count() << \" ms, \" << run_ms.count()\n                   << \" ms in Run\\n\";\n    }\n  }\n}\n\n// Implements main() within the Carbon::Testing namespace for convenience.\nstatic auto Main(int argc, char** argv) -> ErrorOr<int> {\n  // Default to brief because we expect lots of tests, and `FileTestBase`\n  // provides some summaries. Note `--test_arg=--gtest_brief=0` works to restore\n  // output.\n  absl::SetFlag(&FLAGS_gtest_brief, 1);\n\n  Carbon::InitLLVM init_llvm(argc, argv);\n  testing::InitGoogleTest(&argc, argv);\n  auto args = absl::ParseCommandLine(argc, argv);\n\n  if (args.size() > 1) {\n    ErrorBuilder b;\n    b << \"Unexpected arguments:\";\n    for (char* arg : llvm::ArrayRef(args).drop_front()) {\n      b << \" \" << FormatEscaped(arg);\n    }\n    return b;\n  }\n\n  std::string exe_path = FindExecutablePath(argv[0]);\n\n  // Tests might try to read from stdin. Ensure those reads fail by closing\n  // stdin and reopening it as /dev/null. Note that STDIN_FILENO doesn't exist\n  // on Windows, but POSIX requires it to be 0.\n  if (std::error_code error =\n          llvm::sys::Process::SafelyCloseFileDescriptor(0)) {\n    return Error(\"Unable to close standard input: \" + error.message());\n  }\n  if (std::error_code error =\n          llvm::sys::Process::FixupStandardFileDescriptors()) {\n    return Error(\"Unable to correct standard file descriptors: \" +\n                 error.message());\n  }\n  if (absl::GetFlag(FLAGS_autoupdate) && absl::GetFlag(FLAGS_dump_output)) {\n    return Error(\"--autoupdate and --dump_output are mutually exclusive.\");\n  }\n\n  auto test_factory = GetFileTestFactory();\n\n  MaybeApplyFileTestsFlag(test_factory.name);\n\n  // Inline 0 entries because it will always be too large to store on the stack.\n  llvm::SmallVector<FileTestInfo, 0> tests;\n  CARBON_RETURN_IF_ERROR(RegisterTests(&test_factory, exe_path, tests));\n\n  testing::TestEventListeners& listeners =\n      testing::UnitTest::GetInstance()->listeners();\n  if (absl::GetFlag(FLAGS_autoupdate) || absl::GetFlag(FLAGS_dump_output)) {\n    // Suppress all of the default output.\n    delete listeners.Release(listeners.default_result_printer());\n  }\n  // Use a listener to run tests in parallel.\n  listeners.Append(new FileTestEventListener(tests));\n\n  return RUN_ALL_TESTS();\n}\n\n}  // namespace Carbon::Testing\n\nauto main(int argc, char** argv) -> int {\n  if (auto result = Carbon::Testing::Main(argc, argv); result.ok()) {\n    return *result;\n  } else {\n    llvm::errs() << result.error() << \"\\n\";\n    return EXIT_FAILURE;\n  }\n}\n"
  },
  {
    "path": "testing/file_test/file_test_base.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_FILE_TEST_FILE_TEST_BASE_H_\n#define CARBON_TESTING_FILE_TEST_FILE_TEST_BASE_H_\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <functional>\n#include <mutex>\n\n#include \"common/error.h\"\n#include \"common/ostream.h\"\n#include \"llvm/ADT/SmallString.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringMap.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/VirtualFileSystem.h\"\n#include \"testing/file_test/autoupdate.h\"\n#include \"testing/file_test/manifest.h\"\n\nnamespace Carbon::Testing {\n\n// A framework for testing files. See README.md for documentation.\nclass FileTestBase {\n public:\n  // Provided for child class convenience.\n  using LineNumberReplacement = FileTestAutoupdater::LineNumberReplacement;\n  using CheckLineArray = FileTestAutoupdater::CheckLineArray;\n\n  // The result of Run(), used to detect errors. Failing test files should be\n  // named with a `fail_` prefix to indicate an expectation of failure.\n  //\n  // If per_file_success is empty:\n  // - The main file has a `fail_` prefix if !success.\n  // - The prefix of split files is unused.\n  //\n  // If per_file_success is non-empty:\n  // - Each file has a `fail_` prefix if !per_file_success[i].second.\n  //   - Files may be in per_file_success that aren't part of the main test\n  //     file. This allows tracking success in handling files that are\n  //     well-known, such as standard libraries. It is still the responsibility\n  //     of callers to use a `fail_` prefix if !per_file_success[i].second.\n  // - If any file has a `fail_` prefix, success must be false, and the prefix\n  //   of the main file is unused.\n  // - If no file has a `fail_` prefix, the main file has a `fail_` prefix if\n  //   !success.\n  struct RunResult {\n    bool success;\n\n    // Per-file success results. May be empty.\n    llvm::SmallVector<std::pair<std::string, bool>> per_file_success;\n  };\n\n  explicit FileTestBase(llvm::StringRef test_name) : test_name_(test_name) {}\n  virtual ~FileTestBase() = default;\n\n  // Implemented by children to run the test. The framework will validate the\n  // content written to `output_stream` and `error_stream`. Children should use\n  // `fs` for file content, and may add more files.\n  //\n  // If there is a split test file named \"STDIN\", then its contents will be\n  // provided at `input_stream` instead of `fs`. Otherwise, `input_stream` will\n  // be null.\n  //\n  // This cannot be used for test expectations, such as EXPECT_TRUE.\n  //\n  // The return value should be an error if there was an abnormal error, and\n  // RunResult otherwise.\n  virtual auto Run(const llvm::SmallVector<llvm::StringRef>& test_args,\n                   llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>& fs,\n                   FILE* input_stream, llvm::raw_pwrite_stream& output_stream,\n                   llvm::raw_pwrite_stream& error_stream) const\n      -> ErrorOr<RunResult> = 0;\n\n  // Returns default arguments. Only called when a file doesn't set ARGS.\n  virtual auto GetDefaultArgs() const -> llvm::SmallVector<std::string> = 0;\n\n  // Returns a map of string replacements to implement `%{key}` -> `value` in\n  // arguments.\n  virtual auto GetArgReplacements() const -> llvm::StringMap<std::string> {\n    return {};\n  }\n\n  // Returns a regex to match the default file when a line may not be present.\n  // May return `std::nullopt` if unused. If `GetLineNumberReplacements` returns\n  // an entry with `has_file=false`, this is required.\n  virtual auto GetDefaultFileRE(llvm::ArrayRef<llvm::StringRef> /*filenames*/)\n      const -> std::optional<RE2> {\n    return std::nullopt;\n  }\n\n  // Returns replacement information for line numbers. See LineReplacement for\n  // construction.\n  virtual auto GetLineNumberReplacements(\n      llvm::ArrayRef<llvm::StringRef> filenames) const\n      -> llvm::SmallVector<LineNumberReplacement>;\n\n  // Optionally allows children to provide extra replacements for autoupdate.\n  virtual auto DoExtraCheckReplacements(std::string& /*check_line*/) const\n      -> void {}\n\n  // Optionally allows children to perform tweaks on check lines before\n  // they are merged into the output file.\n  virtual auto FinalizeCheckLines(CheckLineArray& /*check_lines*/,\n                                  bool /*is_stderr*/) const -> void {}\n\n  // Whether to allow running the test in parallel, particularly for autoupdate.\n  // This can be overridden to force some tests to be run serially. At any given\n  // time, all parallel tests and a single non-parallel test will be allowed to\n  // run.\n  virtual auto AllowParallelRun() const -> bool { return true; }\n\n  // Modes for GetBazelCommand.\n  enum class BazelMode : uint8_t {\n    Autoupdate,\n    Dump,\n    Test,\n  };\n\n  // Returns the requested bazel command string for the given execution mode.\n  auto GetBazelCommand(BazelMode mode) -> std::string;\n\n  auto test_name() const -> llvm::StringRef { return test_name_; }\n\n private:\n  llvm::StringRef test_name_;\n};\n\n// Aggregate a name and factory function for tests using this framework.\nstruct FileTestFactory {\n  // The test fixture name.\n  const char* name;\n\n  // A factory function for tests.\n  std::function<auto(llvm::StringRef exe_path, llvm::StringRef test_name)\n                    ->std::unique_ptr<FileTestBase>>\n      factory_fn;\n};\n\n// Must be implemented by the individual file_test to initialize tests.\n//\n// We can't use INSTANTIATE_TEST_CASE_P because of ordering issues between\n// container initialization and test instantiation by InitGoogleTest, but this\n// also allows us more flexibility in execution.\n//\n// The `CARBON_FILE_TEST_FACTOR` macro below provides a standard, convenient way\n// to implement this function.\nextern auto GetFileTestFactory() -> FileTestFactory;\n\n// Provides a standard GetFileTestFactory implementation.\n#define CARBON_FILE_TEST_FACTORY(Name)                                       \\\n  auto GetFileTestFactory() -> FileTestFactory {                             \\\n    return {#Name, [](llvm::StringRef exe_path, llvm::StringRef test_name) { \\\n              return std::make_unique<Name>(exe_path, test_name);            \\\n            }};                                                              \\\n  }\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_FILE_TEST_FILE_TEST_BASE_H_\n"
  },
  {
    "path": "testing/file_test/file_test_base_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/file_test/file_test_base.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <functional>\n#include <memory>\n#include <optional>\n#include <string>\n\n#include \"common/ostream.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/ADT/StringSwitch.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nclass FileTestBaseTest : public FileTestBase {\n public:\n  FileTestBaseTest(llvm::StringRef /*exe_path*/, llvm::StringRef test_name)\n      : FileTestBase(test_name) {}\n\n  auto Run(const llvm::SmallVector<llvm::StringRef>& test_args,\n           llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>& fs,\n           FILE* input_stream, llvm::raw_pwrite_stream& output_stream,\n           llvm::raw_pwrite_stream& error_stream) const\n      -> ErrorOr<RunResult> override;\n\n  auto GetArgReplacements() const -> llvm::StringMap<std::string> override {\n    return {{\"replacement\", \"replaced\"}};\n  }\n\n  auto GetDefaultArgs() const -> llvm::SmallVector<std::string> override {\n    return {\"default_args\", \"%s\"};\n  }\n\n  auto GetDefaultFileRE(llvm::ArrayRef<llvm::StringRef> filenames) const\n      -> std::optional<RE2> override {\n    return std::make_optional<RE2>(\n        llvm::formatv(R\"(file: ({0}))\", llvm::join(filenames, \"|\")));\n  }\n\n  auto GetLineNumberReplacements(llvm::ArrayRef<llvm::StringRef> filenames)\n      const -> llvm::SmallVector<LineNumberReplacement> override {\n    auto replacements = FileTestBase::GetLineNumberReplacements(filenames);\n    auto filename = std::filesystem::path(test_name().str()).filename();\n    if (llvm::StringRef(filename).starts_with(\"file_only_re_\")) {\n      replacements.push_back({.has_file = false,\n                              .re = std::make_shared<RE2>(R\"(line: (\\d+))\"),\n                              .line_formatv = \"{0}\"});\n    }\n    return replacements;\n  }\n};\n\n// Prints arguments so that they can be validated in tests.\nstatic auto PrintArgs(llvm::ArrayRef<llvm::StringRef> args,\n                      llvm::raw_pwrite_stream& output_stream) -> void {\n  llvm::ListSeparator sep;\n  output_stream << args.size() << \" args: \";\n  for (auto arg : args) {\n    output_stream << sep << \"`\" << arg << \"`\";\n  }\n  output_stream << \"\\n\";\n}\n\n// Verifies arguments are well-structured, and returns the files in them.\nstatic auto GetFilesFromArgs(llvm::ArrayRef<llvm::StringRef> args,\n                             llvm::vfs::InMemoryFileSystem& fs)\n    -> ErrorOr<llvm::ArrayRef<llvm::StringRef>> {\n  if (args.empty() || args.front() != \"default_args\") {\n    return ErrorBuilder() << \"missing `default_args` argument\";\n  }\n  args.consume_front();\n\n  for (auto arg : args) {\n    if (!fs.exists(arg)) {\n      return ErrorBuilder() << \"Missing file: \" << arg;\n    }\n  }\n  return args;\n}\n\n// Parameters used to by individual test handlers, for easy value forwarding.\nstruct TestParams {\n  // These are the arguments to `Run()`.\n  llvm::vfs::InMemoryFileSystem& fs;\n  FILE* input_stream;\n  llvm::raw_pwrite_stream& output_stream;\n  llvm::raw_pwrite_stream& error_stream;\n\n  // This is assigned after construction.\n  llvm::ArrayRef<llvm::StringRef> files;\n};\n\n// Prints and returns expected results for alternating_files.carbon.\nstatic auto TestAlternatingFiles(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  params.output_stream << \"unattached message 1\\n\"\n                       << \"a.carbon:2: message 2\\n\"\n                       << \"b.carbon:5: message 3\\n\"\n                       << \"a.carbon:2: message 4\\n\"\n                       << \"b.carbon:5: message 5\\n\"\n                       << \"unattached message 6\\n\";\n  params.error_stream << \"unattached message 1\\n\"\n                      << \"a.carbon:2: message 2\\n\"\n                      << \"b.carbon:5: message 3\\n\"\n                      << \"a.carbon:2: message 4\\n\"\n                      << \"b.carbon:5: message 5\\n\"\n                      << \"unattached message 6\\n\";\n  return {{.success = true}};\n}\n\n// Prints and returns expected results for capture_console_output.carbon.\nstatic auto TestCaptureConsoleOutput(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  llvm::errs() << \"llvm::errs\\n\";\n  params.error_stream << \"params.error_stream\\n\";\n  llvm::outs() << \"llvm::outs\\n\";\n  params.output_stream << \"params.output_stream\\n\";\n  return {{.success = true}};\n}\n\n// Prints and returns expected results for escaping.carbon.\nstatic auto TestEscaping(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  params.error_stream << \"carriage return\\r\\n\"\n                         \"{one brace}\\n\"\n                         \"{{two braces}}\\n\"\n                         \"[one bracket]\\n\"\n                         \"[[two brackets]]\\n\"\n                         \"end of line whitespace   \\n\"\n                         \"\\ttabs\\t\\n\";\n  return {{.success = true}};\n}\n\n// Prints and returns expected results for example.carbon.\nstatic auto TestExample(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  int delta_line = 10;\n  params.output_stream << \"something\\n\"\n                       << \"\\n\"\n                       << \"example.carbon:\" << delta_line + 1\n                       << \": Line delta\\n\"\n                       << \"example.carbon:\" << delta_line\n                       << \": Negative line delta\\n\"\n                       << \"+*[]{}\\n\"\n                       << \"Foo baz\\n\";\n  return {{.success = true}};\n}\n\n// Prints and returns expected results for fail_example.carbon.\nstatic auto TestFailExample(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  params.error_stream << \"Oops\\n\";\n  return {{.success = false}};\n}\n\n// Prints and returns expected results for\n// file_only_re_multi_file.carbon.\nstatic auto TestFileOnlyREMultiFile(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  int msg_count = 0;\n  params.output_stream << \"unattached message \" << ++msg_count << \"\\n\"\n                       << \"file: a.carbon\\n\"\n                       << \"unattached message \" << ++msg_count << \"\\n\"\n                       << \"line: 3: attached message \" << ++msg_count << \"\\n\"\n                       << \"unattached message \" << ++msg_count << \"\\n\"\n                       << \"line: 8: late message \" << ++msg_count << \"\\n\"\n                       << \"unattached message \" << ++msg_count << \"\\n\"\n                       << \"file: b.carbon\\n\"\n                       << \"line: 2: attached message \" << ++msg_count << \"\\n\"\n                       << \"unattached message \" << ++msg_count << \"\\n\"\n                       << \"line: 7: late message \" << ++msg_count << \"\\n\"\n                       << \"unattached message \" << ++msg_count << \"\\n\";\n  return {{.success = true}};\n}\n\n// Prints and returns expected results for file_only_re_one_file.carbon.\nstatic auto TestFileOnlyREOneFile(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  params.output_stream << \"unattached message 1\\n\"\n                       << \"file: file_only_re_one_file.carbon\\n\"\n                       << \"line: 1\\n\"\n                       << \"unattached message 2\\n\";\n  return {{.success = true}};\n}\n\n// Prints and returns expected results for no_line_number.carbon.\nstatic auto TestNoLineNumber(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  params.output_stream << \"a.carbon: msg1\\n\"\n                          \"msg2\\n\"\n                          \"b.carbon: msg3\\n\"\n                          \"msg4\\n\"\n                          \"a.carbon: msg5\\n\";\n  return {{.success = true}};\n}\n\n// Prints and returns expected results for unattached_multi_file.carbon.\nstatic auto TestUnattachedMultiFile(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  params.output_stream << \"unattached message 1\\n\"\n                       << \"unattached message 2\\n\";\n  params.error_stream << \"unattached message 3\\n\"\n                      << \"unattached message 4\\n\";\n  return {{.success = true}};\n}\n\n// Prints and returns expected results for:\n// - fail_multi_success_overall_fail.carbon\n// - multi_success.carbon\n// - multi_success_and_fail.carbon\n//\n// Parameters indicate overall and per-file success.\nstatic auto HandleMultiSuccessTests(bool overall, bool a, bool b)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  FileTestBaseTest::RunResult result = {.success = overall};\n  result.per_file_success.push_back({a ? \"a.carbon\" : \"fail_a.carbon\", a});\n  result.per_file_success.push_back({b ? \"b.carbon\" : \"fail_b.carbon\", b});\n  return result;\n}\n\n// Echoes back non-comment file content. Used for default file handling.\nstatic auto EchoFileContent(TestParams& params)\n    -> ErrorOr<FileTestBaseTest::RunResult> {\n  // By default, echo non-comment content of files back.\n  for (auto test_file : params.files) {\n    // Describe file contents to stdout to validate splitting.\n    auto file = params.fs.getBufferForFile(test_file, /*FileSize=*/-1,\n                                           /*RequiresNullTerminator=*/false);\n    if (file.getError()) {\n      return Error(file.getError().message());\n    }\n    llvm::StringRef buffer = file.get()->getBuffer();\n    for (int line_number = 1; !buffer.empty(); ++line_number) {\n      auto [line, remainder] = buffer.split('\\n');\n      if (!line.empty() && !line.starts_with(\"//\")) {\n        params.output_stream << test_file << \":\" << line_number << \": \" << line\n                             << \"\\n\";\n      }\n      buffer = remainder;\n    }\n  }\n  if (params.input_stream) {\n    params.error_stream << \"--- STDIN:\\n\";\n    constexpr int ReadSize = 1024;\n    char buf[ReadSize];\n    while (feof(params.input_stream) == 0) {\n      auto read = fread(&buf, sizeof(char), ReadSize, params.input_stream);\n      if (read > 0) {\n        params.error_stream.write(buf, read);\n      }\n    }\n  }\n  return {{.success = true}};\n}\n\nauto FileTestBaseTest::Run(\n    const llvm::SmallVector<llvm::StringRef>& test_args,\n    llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>& fs,\n    FILE* input_stream, llvm::raw_pwrite_stream& output_stream,\n    llvm::raw_pwrite_stream& error_stream) const -> ErrorOr<RunResult> {\n  PrintArgs(test_args, output_stream);\n\n  auto filename = std::filesystem::path(test_name().str()).filename();\n  if (filename == \"args.carbon\" || filename == \"include_args.carbon\" ||\n      filename == \"include_extra_args.carbon\" ||\n      filename == \"include_args_and_extra_args.carbon\") {\n    // These files are testing argument behavior, which doesn't work with the\n    // default test logic.\n    return {{.success = true}};\n  }\n\n  // Choose the test function based on filename.\n  auto test_fn =\n      llvm::StringSwitch<std::function<auto(TestParams&)->ErrorOr<RunResult>>>(\n          filename.string())\n          .Case(\"alternating_files.carbon\", &TestAlternatingFiles)\n          .Case(\"capture_console_output.carbon\", &TestCaptureConsoleOutput)\n          .Case(\"escaping.carbon\", &TestEscaping)\n          .Case(\"example.carbon\", &TestExample)\n          .Case(\"fail_example.carbon\", &TestFailExample)\n          .Case(\"file_only_re_one_file.carbon\", &TestFileOnlyREOneFile)\n          .Case(\"file_only_re_multi_file.carbon\", &TestFileOnlyREMultiFile)\n          .Case(\"no_line_number.carbon\", &TestNoLineNumber)\n          .Case(\"unattached_multi_file.carbon\", &TestUnattachedMultiFile)\n          .Case(\"fail_multi_success_overall_fail.carbon\",\n                [&](TestParams&) {\n                  return HandleMultiSuccessTests(/*overall=*/false, /*a=*/true,\n                                                 /*b=*/true);\n                })\n          .Case(\"multi_success.carbon\",\n                [&](TestParams&) {\n                  return HandleMultiSuccessTests(/*overall=*/true, /*a=*/true,\n                                                 /*b=*/true);\n                })\n          .Case(\"multi_success_and_fail.carbon\",\n                [&](TestParams&) {\n                  return HandleMultiSuccessTests(/*overall=*/false, /*a=*/true,\n                                                 /*b=*/false);\n                })\n          .Default(&EchoFileContent);\n\n  // Call the appropriate test function for the file.\n  TestParams params = {.fs = *fs,\n                       .input_stream = input_stream,\n                       .output_stream = output_stream,\n                       .error_stream = error_stream};\n  CARBON_ASSIGN_OR_RETURN(params.files, GetFilesFromArgs(test_args, *fs));\n  return test_fn(params);\n}\n\n}  // namespace\n\nCARBON_FILE_TEST_FACTORY(FileTestBaseTest)\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/file_test/line.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_FILE_TEST_LINE_H_\n#define CARBON_TESTING_FILE_TEST_LINE_H_\n\n#include \"common/ostream.h\"\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon::Testing {\n\n// Interface for lines.\nclass FileTestLineBase : public Printable<FileTestLineBase> {\n public:\n  explicit FileTestLineBase(int file_number, int line_number)\n      : file_number_(file_number), line_number_(line_number) {}\n  virtual ~FileTestLineBase() = default;\n\n  // Prints the autoupdated line.\n  virtual auto Print(llvm::raw_ostream& out) const -> void = 0;\n\n  virtual auto is_blank() const -> bool = 0;\n\n  auto file_number() const -> int { return file_number_; }\n  auto line_number() const -> int { return line_number_; }\n\n  void set_location(int file_number, int line_number) {\n    file_number_ = file_number;\n    line_number_ = line_number;\n  }\n\n private:\n  int file_number_;\n  int line_number_;\n};\n\n// A line in the original file test.\n//\n// `final` because we use pointer arithmetic on this type.\nclass FileTestLine final : public FileTestLineBase {\n public:\n  explicit FileTestLine(int file_number, int line_number, llvm::StringRef line)\n      : FileTestLineBase(file_number, line_number), line_(line) {}\n\n  auto Print(llvm::raw_ostream& out) const -> void override { out << line_; }\n\n  auto is_blank() const -> bool override { return line_.empty(); }\n\n  auto indent() const -> llvm::StringRef {\n    return line_.substr(0, line_.find_first_not_of(\" \\n\"));\n  }\n\n private:\n  llvm::StringRef line_;\n};\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_FILE_TEST_LINE_H_\n"
  },
  {
    "path": "testing/file_test/manifest.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/file_test/manifest.h\"\n\n#include <string>\n\n// The test manifest, produced by `manifest_as_cpp`.\n// NOLINTNEXTLINE(readability-identifier-naming): Constant in practice.\nextern const char* CarbonFileTestManifest[];\n\nnamespace Carbon::Testing {\n\nauto GetFileTestManifest() -> llvm::SmallVector<std::string> {\n  llvm::SmallVector<std::string> manifest;\n  for (int i = 0; CarbonFileTestManifest[i]; ++i) {\n    manifest.push_back(CarbonFileTestManifest[i]);\n  }\n  return manifest;\n}\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/file_test/manifest.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_FILE_TEST_MANIFEST_H_\n#define CARBON_TESTING_FILE_TEST_MANIFEST_H_\n\n#include <string>\n\n#include \"llvm/ADT/SmallVector.h\"\n\nnamespace Carbon::Testing {\n\n// Returns the manifest path, which is provided by rules.bzl and manifest.cpp.\n// This is exposed separately so that the explorer sharding approach can use a\n// different implementation.\nauto GetFileTestManifest() -> llvm::SmallVector<std::string>;\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_FILE_TEST_MANIFEST_H_\n"
  },
  {
    "path": "testing/file_test/rules.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Rules for building file tests.\n\nfile_test uses the tests_as_input_file rule to transform test dependencies into\na file which can be accessed as a list. This avoids long argument parsing.\n\"\"\"\n\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_test\")\nload(\"//bazel/manifest:defs.bzl\", \"manifest_as_cpp\")\n\ndef file_test(\n        name,\n        tests,\n        srcs = [],\n        deps = [],\n        data = [],\n        args = [],\n        **kwargs):\n    \"\"\"Generates tests using the file_test base.\n\n    There will be one main test using `name` that can be sharded, and includes\n    all files. Additionally, per-file tests will be generated as\n    `name.file_path`; these per-file tests will be manual.\n\n    Args:\n      name: The base name of the tests.\n      tests: The list of test files to use as data, typically a glob.\n      srcs: Passed to cc_test.\n      deps: Passed to cc_test.\n      data: Passed to cc_test.\n      args: Passed to cc_test.\n      **kwargs: Passed to cc_test.\n    \"\"\"\n\n    # Ensure tests are always a filegroup for tests_as_input_file_rule.\n    manifest_cpp = \"{0}_autogen_manifest.cpp\".format(name)\n    manifest_as_cpp(\n        name = manifest_cpp,\n        var_name = \"CarbonFileTestManifest\",\n        srcs = tests,\n        testonly = 1,\n    )\n    cc_test(\n        name = name,\n        srcs = srcs + [\":\" + manifest_cpp],\n        deps = deps + [\"//testing/file_test:manifest_impl\"],\n        data = tests + data,\n        args = args,\n        **kwargs\n    )\n"
  },
  {
    "path": "testing/file_test/run_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/file_test/run_test.h\"\n\n#include <gtest/gtest.h>\n\n#include <string>\n#include <utility>\n\n#include \"common/pretty_stack_trace_function.h\"\n#include \"llvm/ADT/ScopeExit.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringMap.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/PrettyStackTrace.h\"\n#include \"testing/base/file_helpers.h\"\n#include \"testing/file_test/file_test_base.h\"\n#include \"testing/file_test/test_file.h\"\n\nnamespace Carbon::Testing {\n\n// While these are marked as \"internal\" APIs, they seem to work and be pretty\n// widely used for their exact documented behavior.\nusing ::testing::internal::CaptureStderr;\nusing ::testing::internal::CaptureStdout;\nusing ::testing::internal::GetCapturedStderr;\nusing ::testing::internal::GetCapturedStdout;\n\nstatic constexpr llvm::StringLiteral StdinFilename = \"STDIN\";\n\n// Does replacements in ARGS for %s and %t.\nstatic auto DoArgReplacements(llvm::SmallVector<std::string>& test_args,\n                              const llvm::StringMap<std::string>& replacements,\n                              llvm::ArrayRef<TestFile::Split*> split_files)\n    -> ErrorOr<Success> {\n  for (auto* it = test_args.begin(); it != test_args.end(); ++it) {\n    auto percent = it->find(\"%\");\n    if (percent == std::string::npos) {\n      continue;\n    }\n\n    if (percent + 1 >= it->size()) {\n      return ErrorBuilder() << \"% is not allowed on its own: \" << *it;\n    }\n    char c = (*it)[percent + 1];\n    switch (c) {\n      case 's': {\n        if (*it != \"%s\") {\n          return ErrorBuilder() << \"%s must be the full argument: \" << *it;\n        }\n        it = test_args.erase(it);\n        for (const auto& split : split_files) {\n          const std::string& filename = split->filename;\n          if (filename == StdinFilename || filename.ends_with(\".h\")) {\n            continue;\n          }\n          it = test_args.insert(it, filename);\n          ++it;\n        }\n        // Back up once because the for loop will advance.\n        --it;\n        break;\n      }\n      case 't': {\n        std::filesystem::path tmpdir = GetTempDirectory();\n        it->replace(percent, 2, llvm::formatv(\"{0}/temp_file\", tmpdir));\n        break;\n      }\n      case '{': {\n        auto end_brace = it->find('}', percent);\n        if (end_brace == std::string::npos) {\n          return ErrorBuilder() << \"%{ without closing }: \" << *it;\n        }\n        llvm::StringRef substr(&*(it->begin() + percent + 2),\n                               end_brace - percent - 2);\n        auto replacement = replacements.find(substr);\n        if (replacement == replacements.end()) {\n          return ErrorBuilder()\n                 << \"unknown substitution: %{\" << substr << \"}: \" << *it;\n        }\n        it->replace(percent, end_brace - percent + 1, replacement->second);\n        break;\n      }\n      default:\n        return ErrorBuilder() << \"%\" << c << \" is not supported: \" << *it;\n    }\n  }\n  return Success();\n}\n\n// Collects captured output when enabled.\nstatic auto CollectOutputIfCapturing(TestFile& test_file) -> void {\n  if (!test_file.capture_console_output) {\n    return;\n  }\n  // No need to flush stderr.\n  llvm::outs().flush();\n  test_file.actual_stdout += GetCapturedStdout();\n  test_file.actual_stderr += GetCapturedStderr();\n}\n\nauto RunTestFile(const FileTestBase& test_base, bool dump_output,\n                 TestFile& test_file) -> ErrorOr<Success> {\n  llvm::SmallVector<TestFile::Split*> all_splits;\n  for (auto& split : test_file.include_file_splits) {\n    all_splits.push_back(&split);\n  }\n  for (auto& split : test_file.file_splits) {\n    all_splits.push_back(&split);\n  }\n\n  // Process arguments.\n  if (test_file.test_args.empty()) {\n    test_file.test_args = test_base.GetDefaultArgs();\n  }\n  test_file.test_args.append(test_file.extra_args);\n  CARBON_RETURN_IF_ERROR(DoArgReplacements(\n      test_file.test_args, test_base.GetArgReplacements(), all_splits));\n\n  // stdin needs to exist on-disk for compatibility. We'll use a pointer for it.\n  FILE* input_stream = nullptr;\n  auto erase_input_on_exit = llvm::scope_exit([&input_stream]() {\n    if (input_stream) {\n      // fclose should delete the tmpfile.\n      fclose(input_stream);\n      input_stream = nullptr;\n    }\n  });\n\n  // Create the files in-memory.\n  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> fs =\n      new llvm::vfs::InMemoryFileSystem;\n  for (const auto& split : all_splits) {\n    if (split->filename == StdinFilename) {\n      input_stream = tmpfile();\n      fwrite(split->content.c_str(), sizeof(char), split->content.size(),\n             input_stream);\n      CARBON_CHECK(!fseek(input_stream, 0, SEEK_SET));\n    } else if (!fs->addFile(split->filename, /*ModificationTime=*/0,\n                            llvm::MemoryBuffer::getMemBuffer(\n                                split->content, split->filename,\n                                /*RequiresNullTerminator=*/false))) {\n      return ErrorBuilder() << \"File is repeated: \" << split->filename;\n    }\n  }\n\n  // Convert the arguments to StringRef and const char* to match the\n  // expectations of PrettyStackTraceProgram and Run.\n  llvm::SmallVector<llvm::StringRef> test_args_ref;\n  llvm::SmallVector<const char*> test_argv_for_stack_trace;\n  test_args_ref.reserve(test_file.test_args.size());\n  test_argv_for_stack_trace.reserve(test_file.test_args.size() + 1);\n  for (const auto& arg : test_file.test_args) {\n    test_args_ref.push_back(arg);\n    test_argv_for_stack_trace.push_back(arg.c_str());\n  }\n  // Add a trailing null so that this is a proper argv.\n  test_argv_for_stack_trace.push_back(nullptr);\n\n  // Add a stack trace entry for the test invocation.\n  llvm::PrettyStackTraceProgram stack_trace_entry(\n      test_argv_for_stack_trace.size() - 1, test_argv_for_stack_trace.data());\n\n  // Conditionally capture console output. We use a scope exit to ensure the\n  // captures terminate even on run failures.\n  if (test_file.capture_console_output) {\n    CaptureStderr();\n    CaptureStdout();\n  }\n\n  // Prepare string streams to capture output. In order to address casting\n  // constraints, we split calls to Run as a ternary based on whether we want to\n  // capture output.\n  llvm::raw_svector_ostream output_stream(test_file.actual_stdout);\n  llvm::raw_svector_ostream error_stream(test_file.actual_stderr);\n\n  // Dump any available captured output if `Run` crashes.\n  PrettyStackTraceFunction stack_trace_streams([&](llvm::raw_ostream& out) {\n    CollectOutputIfCapturing(test_file);\n\n    auto dump_stream = [&](llvm::SmallString<16> stream) {\n      if (stream.empty()) {\n        out << \" (none)\\n\";\n      } else {\n        out << \"\\n\" << stream << \"\\n\";\n      }\n    };\n\n    out << \"Test stdout:\";\n    dump_stream(test_file.actual_stdout);\n\n    out << \"\\tTest stderr:\";\n    dump_stream(test_file.actual_stderr);\n  });\n\n  Timer timer;\n  ErrorOr<FileTestBase::RunResult> run_result =\n      dump_output ? test_base.Run(test_args_ref, fs, input_stream, llvm::outs(),\n                                  llvm::errs())\n                  : test_base.Run(test_args_ref, fs, input_stream,\n                                  output_stream, error_stream);\n  test_file.run_elapsed_ms = timer.elapsed_ms();\n\n  // Collect captured stdout/stderr, even when discarded on error.\n  CollectOutputIfCapturing(test_file);\n\n  if (!run_result.ok()) {\n    return std::move(run_result).error();\n  }\n  test_file.run_result = std::move(*run_result);\n  return Success();\n}\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/file_test/run_test.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_FILE_TEST_RUN_TEST_H_\n#define CARBON_TESTING_FILE_TEST_RUN_TEST_H_\n\n#include \"common/error.h\"\n#include \"testing/file_test/file_test_base.h\"\n#include \"testing/file_test/test_file.h\"\n\nnamespace Carbon::Testing {\n\n// Runs the test, updating `test_file`.\nauto RunTestFile(const FileTestBase& test_base, bool dump_output,\n                 TestFile& test_file) -> ErrorOr<Success>;\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_FILE_TEST_RUN_TEST_H_\n"
  },
  {
    "path": "testing/file_test/test_file.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/file_test/test_file.h\"\n\n#include <fstream>\n#include <optional>\n#include <string>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/error.h\"\n#include \"common/find.h\"\n#include \"common/raw_string_ostream.h\"\n#include \"common/set.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/Support/JSON.h\"\n#include \"testing/base/file_helpers.h\"\n#include \"testing/file_test/line.h\"\n\nnamespace Carbon::Testing {\n\nusing ::testing::Matcher;\nusing ::testing::MatchesRegex;\nusing ::testing::StrEq;\n\n// Represents the different kinds of version-control conflict markers that are\n// relevant for the autoupdater. One key concern here is the distinction between\n// \"snapshot\" and \"diff\" conflict regions. Snapshot regions are the more\n// traditional kind, where the entire region between two markers represents the\n// exact state of a region of the underlying file at some snapshot (e.g. the\n// base commit or one of the conflicting commits). Diff regions are\n// produced by jj. They show the diff between the base and one side of the\n// conflict, using a prefix character on each line: '+' indicates an added line,\n// '-' indicates a removed line, and ' ' indicates an unchanged line. Note that\n// a single conflict may contain both snapshot and diff regions.\n//\n// See https://docs.jj-vcs.dev/latest/conflicts/ for more information.\nenum class MarkerKind {\n  // Represents a line that is not a conflict marker.\n  None,\n  // Marks the start of a conflict, and potentially a snapshot region.\n  Start,\n  // Marks the end of a conflict.\n  End,\n  // Marks the start of a snapshot region.\n  Snapshot,\n  // Marks the start of a diff region.\n  Diff\n};\n\n// Processes conflict markers, including tracking the previous conflict marker.\n// Returns true if the line is consumed.\nstatic auto TryConsumeConflictMarker(bool running_autoupdate,\n                                     llvm::StringRef line,\n                                     llvm::StringRef line_trimmed,\n                                     MarkerKind& previous_marker)\n    -> ErrorOr<bool> {\n  MarkerKind new_marker;\n  if (line.starts_with(\"<<<<<<<\")) {\n    new_marker = MarkerKind::Start;\n  } else if (line.starts_with(\">>>>>>>\")) {\n    new_marker = MarkerKind::End;\n  } else if (line.starts_with(\"=======\") || line.starts_with(\"|||||||\") ||\n             line.starts_with(\"+++++++\") || line.starts_with(\"-------\")) {\n    // git uses \"=======\" and \"|||||||\" to mark boundaries between conflict\n    // regions (which are always snapshots). jj uses \"+++++++\" and \"-------\" to\n    // mark the start of different kinds of snapshot regions.\n    new_marker = MarkerKind::Snapshot;\n  } else if (line.starts_with(\"%%%%%%%\") || line.starts_with(R\"(\\\\\\\\\\\\\\)\")) {\n    // jj uses \"%%%%%%%\" to mark the start of a diff region, and \"\\\\\\\\\\\\\\\" to\n    // add a second line to a \"%%%%%%%\" marker for formatting purposes.\n    new_marker = MarkerKind::Diff;\n  } else {\n    new_marker = MarkerKind::None;\n  }\n\n  // When running the test, any conflict marker is an error.\n  if (!running_autoupdate && (new_marker != MarkerKind::None)) {\n    return ErrorBuilder() << \"Conflict marker found:\\n\" << line;\n  }\n\n  bool inside_conflict_marker = [&] {\n    switch (previous_marker) {\n      case MarkerKind::None:\n      case MarkerKind::End:\n        return false;\n      case MarkerKind::Start:\n      case MarkerKind::Snapshot:\n      case MarkerKind::Diff:\n        return true;\n    }\n  }();\n\n  switch (new_marker) {\n    case MarkerKind::End:\n    case MarkerKind::Snapshot:\n    case MarkerKind::Diff:\n      if (!inside_conflict_marker) {\n        return ErrorBuilder()\n               << \"Unexpected conflict marker outside conflict:\\n\"\n               << line;\n      }\n      previous_marker = new_marker;\n      return true;\n    case MarkerKind::Start:\n      if (inside_conflict_marker) {\n        return ErrorBuilder() << \"Unexpected conflict marker inside conflict:\\n\"\n                              << line;\n      }\n      previous_marker = new_marker;\n      return true;\n    case MarkerKind::None:\n      if (!inside_conflict_marker) {\n        return false;\n      }\n\n      if (previous_marker == MarkerKind::Diff) {\n        if (!line.consume_front(\" \") && !line.consume_front(\"+\") &&\n            !line.consume_front(\"-\")) {\n          return ErrorBuilder() << \"Line inside diff-style conflict doesn't \"\n                                   \"start with '+', '-', or ' ':\\n\"\n                                << line;\n        }\n        line_trimmed = line.ltrim();\n      }\n\n      // Look for CHECK and TIP lines, which can be discarded.\n      if (line_trimmed.starts_with(\"// CHECK:STDOUT:\") ||\n          line_trimmed.starts_with(\"// CHECK:STDERR:\") ||\n          line_trimmed.starts_with(\"// TIP:\")) {\n        return true;\n      }\n\n      return ErrorBuilder() << \"Autoupdate can't discard non-CHECK lines \"\n                               \"inside conflicts:\\n\";\n  }\n}\n\n// State for file splitting logic: TryConsumeSplit and FinishSplit.\nstruct SplitState {\n  auto has_splits() const -> bool { return file_index > 0; }\n\n  auto add_content(llvm::StringRef line) -> void {\n    content.append(line.str());\n    content.append(\"\\n\");\n  }\n\n  // Whether content has been found. Only updated before a file split is found\n  // (which may be never).\n  bool found_code_pre_split = false;\n\n  // The current file name, considering splits. Empty for the default file.\n  llvm::StringRef filename = \"\";\n\n  // The accumulated content for the file being built. This may elide some of\n  // the original content, such as conflict markers.\n  std::string content;\n\n  // The current file index.\n  int file_index = 0;\n};\n\n// Given a `file:/<filename>` URI, returns the filename.\nstatic auto ExtractFilePathFromUri(llvm::StringRef uri)\n    -> ErrorOr<llvm::StringRef> {\n  static constexpr llvm::StringRef FilePrefix = \"file:/\";\n  if (!uri.starts_with(FilePrefix)) {\n    return ErrorBuilder() << \"uri `\" << uri << \"` is not a file uri\";\n  }\n  return uri.drop_front(FilePrefix.size());\n}\n\n// When `FROM_FILE_SPLIT` is used in path `textDocument.text`, populate the\n// value from the split matching the `uri`. Only used for\n// `textDocument/didOpen`.\nstatic auto AutoFillDidOpenParams(llvm::json::Object& params,\n                                  llvm::ArrayRef<TestFile::Split> splits)\n    -> ErrorOr<Success> {\n  auto* text_document = params.getObject(\"textDocument\");\n  if (text_document == nullptr) {\n    return Success();\n  }\n\n  auto attr_it = text_document->find(\"text\");\n  if (attr_it == text_document->end() || attr_it->second != \"FROM_FILE_SPLIT\") {\n    return Success();\n  }\n\n  auto uri = text_document->getString(\"uri\");\n  if (!uri) {\n    return Error(\"missing uri in params.textDocument\");\n  }\n\n  CARBON_ASSIGN_OR_RETURN(auto file_path, ExtractFilePathFromUri(*uri));\n  const auto* split = FindIfOrNull(splits, [&](const TestFile::Split& split) {\n    return split.filename == file_path;\n  });\n  if (!split) {\n    return ErrorBuilder() << \"No split found for uri: \" << *uri;\n  }\n  attr_it->second = split->content;\n  return Success();\n}\n\n// Reformats `[[@LSP:` and similar keyword as an LSP call with headers. Returns\n// the position to start a find for the next keyword.\nstatic auto ReplaceLspKeywordAt(std::string& content, size_t keyword_pos,\n                                int& lsp_call_id,\n                                llvm::ArrayRef<TestFile::Split> splits)\n    -> ErrorOr<size_t> {\n  llvm::StringRef content_at_keyword =\n      llvm::StringRef(content).substr(keyword_pos);\n\n  auto [keyword, body_start] = content_at_keyword.split(\":\");\n  if (keyword.size() == content_at_keyword.size()) {\n    return ErrorBuilder() << \"Missing `:` for `\"\n                          << content_at_keyword.take_front(10) << \"`\";\n  }\n\n  // Whether the first param is a method or id.\n  llvm::StringRef method_or_id_label = \"method\";\n  // Whether to attach the `lsp_call_id`.\n  bool use_call_id = false;\n  // The JSON label for extra content.\n  llvm::StringRef extra_content_label;\n  if (keyword == \"[[@LSP-CALL\") {\n    use_call_id = true;\n    extra_content_label = \"params\";\n  } else if (keyword == \"[[@LSP-NOTIFY\") {\n    extra_content_label = \"params\";\n  } else if (keyword == \"[[@LSP-REPLY\") {\n    method_or_id_label = \"id\";\n    extra_content_label = \"result\";\n  } else if (keyword != \"[[@LSP\") {\n    return ErrorBuilder() << \"Unrecognized @LSP keyword at `\"\n                          << keyword.take_front(10) << \"`\";\n  }\n\n  static constexpr llvm::StringLiteral LspEnd = \"]]\";\n  auto [body, rest] = body_start.split(\"]]\");\n  if (body.size() == body_start.size()) {\n    return ErrorBuilder() << \"Missing `\" << LspEnd << \"` after `\" << keyword\n                          << \"`\";\n  }\n  auto [method_or_id, extra_content] = body.split(\":\");\n\n  llvm::json::Value parsed_extra_content = nullptr;\n  if (!extra_content.empty()) {\n    std::string extra_content_as_object =\n        llvm::formatv(\"{{{0}}\", extra_content);\n    auto parse_result = llvm::json::parse(extra_content_as_object);\n    if (auto err = parse_result.takeError()) {\n      return ErrorBuilder() << \"Error parsing extra content: \" << err;\n    }\n    parsed_extra_content = std::move(*parse_result);\n    CARBON_CHECK(parsed_extra_content.kind() == llvm::json::Value::Object);\n    if (extra_content_label == \"params\" &&\n        method_or_id == \"textDocument/didOpen\") {\n      CARBON_RETURN_IF_ERROR(\n          AutoFillDidOpenParams(*parsed_extra_content.getAsObject(), splits));\n    }\n  }\n\n  // Form the JSON.\n  RawStringOstream buffer;\n  llvm::json::OStream json(buffer);\n\n  json.object([&] {\n    json.attribute(\"jsonrpc\", \"2.0\");\n    json.attribute(method_or_id_label, method_or_id);\n\n    if (use_call_id) {\n      json.attribute(\"id\", ++lsp_call_id);\n    }\n    if (parsed_extra_content != nullptr) {\n      if (!extra_content_label.empty()) {\n        json.attribute(extra_content_label, parsed_extra_content);\n      } else {\n        for (const auto& [key, value] : *parsed_extra_content.getAsObject()) {\n          json.attribute(key, value);\n        }\n      }\n    }\n  });\n\n  // Add the Content-Length header. The `2` accounts for extra newlines.\n  int content_length = buffer.size() + 2;\n  auto json_with_header = llvm::formatv(\"Content-Length: {0}\\n\\n{1}\\n\",\n                                        content_length, buffer.TakeStr())\n                              .str();\n  size_t keyword_len = rest.data() - keyword.data();\n  content.replace(keyword_pos, keyword_len, json_with_header);\n  return keyword_pos + json_with_header.size();\n}\n\n// Replaces `[[@0xAB]]` with the raw byte with value 0xAB. Returns the position\n// to start a find for the next keyword.\nstatic auto ReplaceRawByteKeywordAt(std::string& content, size_t keyword_pos)\n    -> ErrorOr<size_t> {\n  llvm::StringRef content_at_keyword =\n      llvm::StringRef(content).substr(keyword_pos);\n  auto [keyword, rest] = content_at_keyword.split(\"]]\");\n  if (keyword.size() == content_at_keyword.size()) {\n    return ErrorBuilder() << \"Missing `]]` after \" << keyword.take_front(10)\n                          << \"`\";\n  }\n\n  unsigned char byte_value;\n  if (keyword.substr(std::size(\"[[@0x\") - 1).getAsInteger(16, byte_value)) {\n    return ErrorBuilder() << \"Invalid raw byte specifier `\"\n                          << keyword.take_front(10) << \"`\";\n  }\n\n  content.replace(keyword_pos, keyword.size() + 2, 1, byte_value);\n  return keyword_pos + 1;\n}\n\n// Replaces the keyword at the given position. Returns the position to start a\n// find for the next keyword.\nstatic auto ReplaceContentKeywordAt(std::string& content, size_t keyword_pos,\n                                    llvm::StringRef test_name, int& lsp_call_id,\n                                    llvm::ArrayRef<TestFile::Split> splits)\n    -> ErrorOr<size_t> {\n  auto keyword = llvm::StringRef(content).substr(keyword_pos);\n\n  // Line replacements aren't handled here.\n  static constexpr llvm::StringLiteral Line = \"[[@LINE\";\n  if (keyword.starts_with(Line)) {\n    // Just move past the prefix to find the next one.\n    return keyword_pos + Line.size();\n  }\n\n  // Replaced with the actual test name.\n  static constexpr llvm::StringLiteral TestName = \"[[@TEST_NAME]]\";\n  if (keyword.starts_with(TestName)) {\n    content.replace(keyword_pos, TestName.size(), test_name);\n    return keyword_pos + test_name.size();\n  }\n\n  if (keyword.starts_with(\"[[@LSP\")) {\n    return ReplaceLspKeywordAt(content, keyword_pos, lsp_call_id, splits);\n  }\n\n  if (keyword.starts_with(\"[[@0x\")) {\n    return ReplaceRawByteKeywordAt(content, keyword_pos);\n  }\n\n  return ErrorBuilder() << \"Unexpected use of `[[@` at `\"\n                        << keyword.substr(0, 5) << \"`\";\n}\n\n// Replaces the content keywords.\n//\n// This handles content keywords such as [[@TEST_NAME]] and [[@LSP*]]. Unknown\n// content keywords are diagnosed.\nstatic auto ReplaceContentKeywords(llvm::StringRef filename,\n                                   std::string& content,\n                                   llvm::ArrayRef<TestFile::Split> splits)\n    -> ErrorOr<Success> {\n  static constexpr llvm::StringLiteral Prefix = \"[[@\";\n\n  auto keyword_pos = content.find(Prefix);\n  // Return early if not finding anything.\n  if (keyword_pos == std::string::npos) {\n    return Success();\n  }\n\n  // Construct the test name by getting the base name without the extension,\n  // then removing any \"fail_\" or \"todo_\" prefixes.\n  llvm::StringRef test_name = filename;\n  if (auto last_slash = test_name.rfind(\"/\");\n      last_slash != llvm::StringRef::npos) {\n    test_name = test_name.substr(last_slash + 1);\n  }\n  if (auto ext_dot = test_name.find(\".\"); ext_dot != llvm::StringRef::npos) {\n    test_name = test_name.substr(0, ext_dot);\n  }\n  // Note this also handles `fail_todo_` and `todo_fail_`.\n  test_name.consume_front(\"todo_\");\n  test_name.consume_front(\"fail_\");\n  test_name.consume_front(\"todo_\");\n\n  // A counter for LSP calls.\n  int lsp_call_id = 0;\n  while (keyword_pos != std::string::npos) {\n    CARBON_ASSIGN_OR_RETURN(\n        auto keyword_end,\n        ReplaceContentKeywordAt(content, keyword_pos, test_name, lsp_call_id,\n                                splits));\n    keyword_pos = content.find(Prefix, keyword_end);\n  }\n  return Success();\n}\n\n// Adds a file. Used for both split and unsplit test files.\nstatic auto AddSplit(llvm::StringRef filename, std::string& content,\n                     llvm::SmallVector<TestFile::Split>& file_splits)\n    -> ErrorOr<Success> {\n  CARBON_RETURN_IF_ERROR(\n      ReplaceContentKeywords(filename, content, file_splits));\n  file_splits.push_back(\n      {.filename = filename.str(), .content = std::move(content)});\n  content.clear();\n  return Success();\n}\n\n// Process file split (\"---\") lines when found. Returns true if the line is\n// consumed. `non_check_lines` is only provided for the main file, and will be\n// null for includes.\nstatic auto TryConsumeSplit(llvm::StringRef line, llvm::StringRef line_trimmed,\n                            bool missing_autoupdate, int& line_index,\n                            SplitState& split,\n                            llvm::SmallVector<TestFile::Split>& file_splits,\n                            llvm::SmallVector<FileTestLine>* non_check_lines)\n    -> ErrorOr<bool> {\n  if (!line_trimmed.consume_front(\"// ---\")) {\n    if (!split.has_splits() && !line_trimmed.starts_with(\"//\") &&\n        !line_trimmed.empty()) {\n      split.found_code_pre_split = true;\n    }\n\n    // Add the line to the current file's content (which may not be a split\n    // file).\n    split.add_content(line);\n    return false;\n  }\n\n  if (missing_autoupdate) {\n    // If there's a split, all output is appended at the end of each file\n    // before AUTOUPDATE. We may want to change that, but it's not\n    // necessary to handle right now.\n    return Error(\n        \"AUTOUPDATE/NOAUTOUPDATE setting must be in \"\n        \"the first file.\");\n  }\n\n  // On a file split, add the previous file, then start a new one.\n  if (split.has_splits()) {\n    CARBON_RETURN_IF_ERROR(\n        AddSplit(split.filename, split.content, file_splits));\n  } else {\n    split.content.clear();\n    if (split.found_code_pre_split) {\n      // For the first split, we make sure there was no content prior.\n      return Error(\n          \"When using split files, there must be no content before the first \"\n          \"split file.\");\n    }\n  }\n\n  ++split.file_index;\n  split.filename = line_trimmed.trim();\n  if (split.filename.empty()) {\n    return Error(\"Missing filename for split.\");\n  }\n  // The split line is added to non_check_lines for retention in autoupdate, but\n  // is not added to the test file content.\n  line_index = 0;\n  if (non_check_lines) {\n    non_check_lines->push_back(\n        FileTestLine(split.file_index, line_index, line));\n  }\n  return true;\n}\n\n// Converts a `FileCheck`-style expectation string into a single complete regex\n// string by escaping all regex characters outside of the designated `{{...}}`\n// regex sequences, and switching those to a normal regex sub-pattern syntax.\nstatic auto ConvertExpectationStringToRegex(std::string& str) -> void {\n  for (int pos = 0; pos < static_cast<int>(str.size());) {\n    switch (str[pos]) {\n      case '(':\n      case ')':\n      case '[':\n      case ']':\n      case '}':\n      case '.':\n      case '^':\n      case '$':\n      case '*':\n      case '+':\n      case '?':\n      case '|':\n      case '\\\\': {\n        // Escape regex characters.\n        str.insert(pos, \"\\\\\");\n        pos += 2;\n        break;\n      }\n      case '{': {\n        if (pos + 1 == static_cast<int>(str.size()) || str[pos + 1] != '{') {\n          // Single `{`, escape it.\n          str.insert(pos, \"\\\\\");\n          pos += 2;\n          break;\n        }\n\n        // Replace the `{{...}}` regex syntax with standard `(...)` syntax.\n        str.replace(pos, 2, \"(\");\n        for (++pos; pos < static_cast<int>(str.size() - 1); ++pos) {\n          if (str[pos] == '}' && str[pos + 1] == '}') {\n            str.replace(pos, 2, \")\");\n            ++pos;\n            break;\n          }\n        }\n        break;\n      }\n      default: {\n        ++pos;\n      }\n    }\n  }\n}\n\n// Transforms an expectation on a given line from `FileCheck` syntax into a\n// standard regex matcher.\nstatic auto TransformExpectation(int line_index, llvm::StringRef in)\n    -> ErrorOr<Matcher<std::string>> {\n  if (in.empty()) {\n    return Matcher<std::string>{StrEq(\"\")};\n  }\n  if (!in.consume_front(\" \")) {\n    return ErrorBuilder() << \"Malformated CHECK line: \" << in;\n  }\n\n  // Check early if we have a regex component as we can avoid building an\n  // expensive matcher when not using those.\n  bool has_regex = in.find(\"{{\") != llvm::StringRef::npos;\n\n  // Now scan the string and expand any keywords. Note that this needs to be\n  // `size_t` to correctly store `npos`.\n  size_t keyword_pos = in.find(\"[[\");\n\n  // If there are neither keywords nor regex sequences, we can match the\n  // incoming string directly.\n  if (!has_regex && keyword_pos == llvm::StringRef::npos) {\n    return Matcher<std::string>{StrEq(in)};\n  }\n\n  std::string str = in.str();\n\n  // First expand the keywords.\n  while (keyword_pos != std::string::npos) {\n    llvm::StringRef line_keyword_cursor =\n        llvm::StringRef(str).substr(keyword_pos);\n    CARBON_CHECK(line_keyword_cursor.consume_front(\"[[\"));\n\n    static constexpr llvm::StringLiteral LineKeyword = \"@LINE\";\n    if (!line_keyword_cursor.consume_front(LineKeyword)) {\n      return ErrorBuilder()\n             << \"Unexpected [[, should be {{\\\\[\\\\[}} at `\"\n             << line_keyword_cursor.substr(0, 5) << \"` in: \" << in;\n    }\n\n    // Allow + or - here; consumeInteger handles -.\n    line_keyword_cursor.consume_front(\"+\");\n    int offset;\n    // consumeInteger returns true for errors, not false.\n    if (line_keyword_cursor.consumeInteger(10, offset) ||\n        !line_keyword_cursor.consume_front(\"]]\")) {\n      return ErrorBuilder()\n             << \"Unexpected @LINE offset at `\"\n             << line_keyword_cursor.substr(0, 5) << \"` in: \" << in;\n    }\n    std::string int_str = llvm::Twine(line_index + offset).str();\n    int remove_len = (line_keyword_cursor.data() - str.data()) - keyword_pos;\n    str.replace(keyword_pos, remove_len, int_str);\n    keyword_pos += int_str.size();\n    // Find the next keyword start or the end of the string.\n    keyword_pos = str.find(\"[[\", keyword_pos);\n  }\n\n  // If there was no regex, we can directly match the adjusted string.\n  if (!has_regex) {\n    return Matcher<std::string>{StrEq(str)};\n  }\n\n  // Otherwise, we need to turn the entire string into a regex by escaping\n  // things outside the regex region and transforming the regex region into a\n  // normal syntax.\n  ConvertExpectationStringToRegex(str);\n  return Matcher<std::string>{MatchesRegex(str)};\n}\n\n// Once all content is processed, do any remaining split processing.\nstatic auto FinishSplit(llvm::StringRef filename, bool is_include_file,\n                        SplitState& split,\n                        llvm::SmallVector<TestFile::Split>& file_splits)\n    -> ErrorOr<Success> {\n  if (split.has_splits()) {\n    return AddSplit(split.filename, split.content, file_splits);\n  } else {\n    // If no file splitting happened, use the main file as the test file.\n    // There will always be a `/` unless tests are in the repo root.\n    std::string split_name = std::filesystem::path(filename.str()).filename();\n    if (is_include_file) {\n      split_name.insert(0, \"include_files/\");\n    }\n    return AddSplit(split_name, split.content, file_splits);\n  }\n}\n\n// Process CHECK lines when found. Returns true if the line is consumed.\n// `expected_stdout` and `expected_stderr` are null in included files, where\n// it's an error to use `CHECK`.\nstatic auto TryConsumeCheck(\n    bool running_autoupdate, int line_index, llvm::StringRef line,\n    llvm::StringRef line_trimmed,\n    llvm::SmallVector<testing::Matcher<std::string>>* expected_stdout,\n    llvm::SmallVector<testing::Matcher<std::string>>* expected_stderr)\n    -> ErrorOr<bool> {\n  if (!line_trimmed.consume_front(\"// CHECK\")) {\n    return false;\n  }\n\n  if (!expected_stdout) {\n    return ErrorBuilder() << \"Included files can't add CHECKs: \"\n                          << line_trimmed;\n  }\n\n  // Don't build expectations when doing an autoupdate. We don't want to\n  // break the autoupdate on an invalid CHECK line.\n  if (!running_autoupdate) {\n    llvm::SmallVector<Matcher<std::string>>* expected;\n    if (line_trimmed.consume_front(\":STDOUT:\")) {\n      expected = expected_stdout;\n    } else if (line_trimmed.consume_front(\":STDERR:\")) {\n      expected = expected_stderr;\n    } else {\n      return ErrorBuilder() << \"Unexpected CHECK in input: \" << line.str();\n    }\n    CARBON_ASSIGN_OR_RETURN(Matcher<std::string> check_matcher,\n                            TransformExpectation(line_index, line_trimmed));\n    expected->push_back(check_matcher);\n  }\n  return true;\n}\n\n// Processes ARGS and EXTRA-ARGS lines when found. Returns true if the line is\n// consumed.\nstatic auto TryConsumeArgs(llvm::StringRef line, llvm::StringRef line_trimmed,\n                           llvm::SmallVector<std::string>& args)\n    -> ErrorOr<bool> {\n  if (!line_trimmed.consume_front(\"// ARGS: \")) {\n    return false;\n  }\n\n  if (!args.empty()) {\n    return ErrorBuilder() << \"ARGS specified multiple times: \" << line.str();\n  }\n\n  // Split the line into arguments.\n  std::pair<llvm::StringRef, llvm::StringRef> cursor =\n      llvm::getToken(line_trimmed);\n  while (!cursor.first.empty()) {\n    args.push_back(std::string(cursor.first));\n    cursor = llvm::getToken(cursor.second);\n  }\n\n  return true;\n}\nstatic auto TryConsumeExtraArgs(llvm::StringRef line_trimmed,\n                                llvm::SmallVector<std::string>& extra_args)\n    -> ErrorOr<bool> {\n  if (!line_trimmed.consume_front(\"// EXTRA-ARGS: \")) {\n    return false;\n  }\n\n  // Split the line into arguments.\n  std::pair<llvm::StringRef, llvm::StringRef> cursor =\n      llvm::getToken(line_trimmed);\n  while (!cursor.first.empty()) {\n    extra_args.push_back(std::string(cursor.first));\n    cursor = llvm::getToken(cursor.second);\n  }\n\n  return true;\n}\n\nstatic auto TryConsumeIncludeFile(llvm::StringRef line_trimmed,\n                                  llvm::SmallVector<std::string>& include_files)\n    -> ErrorOr<bool> {\n  if (!line_trimmed.consume_front(\"// INCLUDE-FILE: \")) {\n    return false;\n  }\n\n  include_files.push_back(line_trimmed.str());\n  return true;\n}\n\n// Processes AUTOUPDATE lines when found. Returns true if the line is consumed.\n// `found_autoupdate` and `autoupdate_line_number` are only provided for the\n// main file; it's an error to have autoupdate in included files.\nstatic auto TryConsumeAutoupdate(int line_index, llvm::StringRef line_trimmed,\n                                 bool* found_autoupdate,\n                                 std::optional<int>* autoupdate_line_number)\n    -> ErrorOr<bool> {\n  static constexpr llvm::StringLiteral Autoupdate = \"// AUTOUPDATE\";\n  static constexpr llvm::StringLiteral NoAutoupdate = \"// NOAUTOUPDATE\";\n  if (line_trimmed != Autoupdate && line_trimmed != NoAutoupdate) {\n    return false;\n  }\n  if (!found_autoupdate) {\n    return ErrorBuilder() << \"Included files can't control autoupdate: \"\n                          << line_trimmed;\n  }\n  if (*found_autoupdate) {\n    return Error(\"Multiple AUTOUPDATE/NOAUTOUPDATE settings found\");\n  }\n  *found_autoupdate = true;\n  if (line_trimmed == Autoupdate) {\n    *autoupdate_line_number = line_index;\n  }\n  return true;\n}\n\n// Processes SET-* lines when found. Returns true if the line is consumed.\n// If `flag` is null, we're in an included file where the flag can't be set.\nstatic auto TryConsumeSetFlag(llvm::StringRef line_trimmed,\n                              llvm::StringLiteral flag_name, bool* flag)\n    -> ErrorOr<bool> {\n  if (!line_trimmed.consume_front(\"// \") || line_trimmed != flag_name) {\n    return false;\n  }\n  if (!flag) {\n    return ErrorBuilder() << \"Included files can't set flag: \" << line_trimmed;\n  }\n  if (*flag) {\n    return ErrorBuilder() << flag_name << \" was specified multiple times\";\n  }\n  *flag = true;\n  return true;\n}\n\n// Process content for either the main file (with `test_file` and\n// `found_autoupdate` provided) or an included file (with those arguments null).\n//\n// - `found_autoupdate` is set to true when either `AUTOUPDATE` or\n//   `NOAUTOUPDATE` are found.\n// - `args` is set from `ARGS`.\n// - `extra_args` accumulates `EXTRA-ARGS`.\n// - `splits` accumulates split form for the test (`// --- <filename>`, or the\n//   full file named as `filename` when there are no splits in the file).\n// - `include_files` accumulates `INCLUDE-FILE`.\nstatic auto ProcessFileContent(llvm::StringRef filename,\n                               llvm::StringRef content_cursor,\n                               bool running_autoupdate, TestFile* test_file,\n                               bool* found_autoupdate,\n                               llvm::SmallVector<std::string>& args,\n                               llvm::SmallVector<std::string>& extra_args,\n                               llvm::SmallVector<TestFile::Split>& splits,\n                               llvm::SmallVector<std::string>& include_files)\n    -> ErrorOr<Success> {\n  // The index in the current test file. Will be reset on splits.\n  int line_index = 0;\n\n  // When autoupdating, we track whether we're inside conflict markers.\n  // Otherwise conflict markers are errors.\n  auto previous_conflict_marker = MarkerKind::None;\n\n  SplitState split_state;\n\n  while (!content_cursor.empty()) {\n    auto [line, next_cursor] = content_cursor.split(\"\\n\");\n    content_cursor = next_cursor;\n    auto line_trimmed = line.ltrim();\n\n    bool is_consumed = false;\n\n    CARBON_ASSIGN_OR_RETURN(\n        is_consumed,\n        TryConsumeConflictMarker(running_autoupdate, line, line_trimmed,\n                                 previous_conflict_marker));\n    if (is_consumed) {\n      continue;\n    }\n\n    // At this point, remaining lines are part of the test input.\n\n    // We need to consume a split, but the main file has a little more handling.\n    bool missing_autoupdate = false;\n    llvm::SmallVector<FileTestLine>* non_check_lines = nullptr;\n    if (test_file) {\n      missing_autoupdate = !*found_autoupdate;\n      non_check_lines = &test_file->non_check_lines;\n    }\n    CARBON_ASSIGN_OR_RETURN(\n        is_consumed,\n        TryConsumeSplit(line, line_trimmed, missing_autoupdate, line_index,\n                        split_state, splits, non_check_lines));\n    if (is_consumed) {\n      continue;\n    }\n\n    ++line_index;\n\n    // TIP lines have no impact on validation.\n    if (line_trimmed.starts_with(\"// TIP:\")) {\n      continue;\n    }\n\n    CARBON_ASSIGN_OR_RETURN(\n        is_consumed,\n        TryConsumeCheck(running_autoupdate, line_index, line, line_trimmed,\n                        test_file ? &test_file->expected_stdout : nullptr,\n                        test_file ? &test_file->expected_stderr : nullptr));\n    if (is_consumed) {\n      continue;\n    }\n\n    if (test_file) {\n      // At this point, lines are retained as non-CHECK lines.\n      test_file->non_check_lines.push_back(\n          FileTestLine(split_state.file_index, line_index, line));\n    }\n\n    CARBON_ASSIGN_OR_RETURN(is_consumed,\n                            TryConsumeArgs(line, line_trimmed, args));\n    if (is_consumed) {\n      continue;\n    }\n    CARBON_ASSIGN_OR_RETURN(is_consumed,\n                            TryConsumeExtraArgs(line_trimmed, extra_args));\n    if (is_consumed) {\n      continue;\n    }\n    CARBON_ASSIGN_OR_RETURN(is_consumed,\n                            TryConsumeIncludeFile(line_trimmed, include_files));\n    if (is_consumed) {\n      continue;\n    }\n\n    CARBON_ASSIGN_OR_RETURN(\n        is_consumed,\n        TryConsumeAutoupdate(\n            line_index, line_trimmed, found_autoupdate,\n            test_file ? &test_file->autoupdate_line_number : nullptr));\n    if (is_consumed) {\n      continue;\n    }\n    CARBON_ASSIGN_OR_RETURN(\n        is_consumed,\n        TryConsumeSetFlag(\n            line_trimmed, \"SET-CAPTURE-CONSOLE-OUTPUT\",\n            test_file ? &test_file->capture_console_output : nullptr));\n    if (is_consumed) {\n      continue;\n    }\n    CARBON_ASSIGN_OR_RETURN(\n        is_consumed,\n        TryConsumeSetFlag(line_trimmed, \"SET-CHECK-SUBSET\",\n                          test_file ? &test_file->check_subset : nullptr));\n    if (is_consumed) {\n      continue;\n    }\n  }\n\n  CARBON_RETURN_IF_ERROR(FinishSplit(filename, /*is_include_file=*/!test_file,\n                                     split_state, splits));\n\n  if (test_file) {\n    test_file->has_splits = split_state.has_splits();\n  }\n  return Success();\n}\n\nauto ProcessTestFile(llvm::StringRef test_name, bool running_autoupdate)\n    -> ErrorOr<TestFile> {\n  TestFile test_file;\n\n  // Store the original content, to avoid a read when autoupdating.\n  CARBON_ASSIGN_OR_RETURN(test_file.input_content, ReadFile(test_name.str()));\n\n  // Whether either AUTOUDPATE or NOAUTOUPDATE was found.\n  bool found_autoupdate = false;\n\n  // INCLUDE-FILE uses, accumulated across both the main file and any includes\n  // (recursively).\n  llvm::SmallVector<std::string> include_files;\n\n  // Store the main file's `EXTRA-ARGS` so that they can be put after any that\n  // come from `INCLUDE-FILE`.\n  llvm::SmallVector<std::string> main_extra_args;\n\n  // Process the main file.\n  CARBON_RETURN_IF_ERROR(ProcessFileContent(\n      test_name, test_file.input_content, running_autoupdate, &test_file,\n      &found_autoupdate, test_file.test_args, main_extra_args,\n      test_file.file_splits, include_files));\n\n  if (!found_autoupdate) {\n    return ErrorBuilder() << \"Missing AUTOUPDATE/NOAUTOUPDATE setting\";\n  }\n\n  constexpr llvm::StringLiteral AutoupdateSplit = \"AUTOUPDATE-SPLIT\";\n\n  // Validate AUTOUPDATE-SPLIT use, and remove it from test files if present.\n  if (test_file.has_splits) {\n    for (const auto& test_file :\n         llvm::ArrayRef(test_file.file_splits).drop_back()) {\n      if (test_file.filename == AutoupdateSplit) {\n        return Error(\"AUTOUPDATE-SPLIT must be the last split\");\n      }\n    }\n    if (test_file.file_splits.back().filename == AutoupdateSplit) {\n      if (!test_file.autoupdate_line_number) {\n        return Error(\"AUTOUPDATE-SPLIT requires AUTOUPDATE\");\n      }\n      test_file.autoupdate_split = true;\n      test_file.file_splits.pop_back();\n    }\n  }\n\n  // Assume there is always a suffix `\\n` in output.\n  if (!test_file.expected_stdout.empty()) {\n    test_file.expected_stdout.push_back(StrEq(\"\"));\n  }\n  if (!test_file.expected_stderr.empty()) {\n    test_file.expected_stderr.push_back(StrEq(\"\"));\n  }\n\n  // Process includes. This can add entries to `include_files`.\n  Set<std::string> processed_includes;\n  for (size_t i = 0; i < include_files.size(); ++i) {\n    const auto& filename = include_files[i];\n    if (!processed_includes.Insert(filename).is_inserted()) {\n      // Ignore repeated includes, mainly so that included files can include the\n      // same file (i.e., repeated indirectly).\n      continue;\n    }\n    CARBON_ASSIGN_OR_RETURN(std::string content, ReadFile(filename));\n    // Note autoupdate never touches included files.\n    CARBON_RETURN_IF_ERROR(ProcessFileContent(\n        filename, content, /*running_autoupdate=*/false,\n        /*test_file=*/nullptr,\n        /*found_autoupdate=*/nullptr, test_file.test_args, test_file.extra_args,\n        test_file.include_file_splits, include_files));\n  }\n\n  for (const auto& split : test_file.include_file_splits) {\n    if (split.filename == AutoupdateSplit) {\n      return Error(\"AUTOUPDATE-SPLIT is disallowed in included files\");\n    }\n  }\n\n  // Copy over `EXTRA-ARGS` from the main file (after includes).\n  test_file.extra_args.append(main_extra_args);\n\n  return std::move(test_file);\n}\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/file_test/test_file.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_FILE_TEST_TEST_FILE_H_\n#define CARBON_TESTING_FILE_TEST_TEST_FILE_H_\n\n#include <gmock/gmock.h>\n\n#include <chrono>\n#include <string>\n\n#include \"llvm/ADT/SmallString.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"testing/file_test/file_test_base.h\"\n#include \"testing/file_test/line.h\"\n\nnamespace Carbon::Testing {\n\n// A small timer for getting elapsed durations.\nclass Timer {\n public:\n  explicit Timer() : start_(std::chrono::steady_clock::now()) {}\n\n  auto elapsed_ms() -> std::chrono::milliseconds {\n    return std::chrono::duration_cast<std::chrono::milliseconds>(\n        std::chrono::steady_clock::now() - start_);\n  }\n\n private:\n  std::chrono::steady_clock::time_point start_;\n};\n\n// Encapsulates test context generated by processing and running.\n//\n// Note this should remain internal to `FileTestBase`, not exposed to individual\n// tests.\nstruct TestFile {\n  // Represents a split within the test file.\n  struct Split {\n    friend auto PrintTo(const Split& f, std::ostream* os) -> void {\n      // Print content escaped.\n      llvm::raw_os_ostream os_wrap(*os);\n      os_wrap << \"Split(\" << f.filename << \", \\\"\" << FormatEscaped(f.content)\n              << \"\\\")\";\n    }\n\n    std::string filename;\n    std::string content;\n  };\n\n  // The input test file content. Other parts may reference this.\n  std::string input_content;\n\n  // Lines which don't contain CHECKs, and thus need to be retained by\n  // autoupdate. Their file and line numbers are attached.\n  //\n  // If there are splits, then the splitting line is in the respective file.\n  // For N splits, the 0th file is the parts of the input file which are not\n  // in any split, plus one file per split file.\n  llvm::SmallVector<FileTestLine> non_check_lines;\n\n  // Whether there are splits.\n  bool has_splits = false;\n\n  // Arguments for the test, generated from ARGS.\n  llvm::SmallVector<std::string> test_args;\n\n  // Extra arguments for the test, generated from EXTRA-ARGS. Unlike ARGS,\n  // setting EXTRA-ARGS does not suppress the default arguments.\n  llvm::SmallVector<std::string> extra_args;\n\n  // Files in the test, generated by content and splits.\n  llvm::SmallVector<Split> file_splits;\n\n  // Files pulled in by `INCLUDE-FILE`. They're combined with `file_splits` for\n  // execution.\n  llvm::SmallVector<Split> include_file_splits;\n\n  // The location of the autoupdate marker, for autoupdated files.\n  std::optional<int> autoupdate_line_number;\n\n  // Whether there should be an AUTOUPDATE-SPLIT.\n  bool autoupdate_split = false;\n\n  // Whether to capture stderr and stdout that would head to console,\n  // generated from SET-CAPTURE-CONSOLE-OUTPUT.\n  bool capture_console_output = false;\n\n  // Whether checks are a subset, generated from SET-CHECK-SUBSET.\n  bool check_subset = false;\n\n  // stdout and stderr based on CHECK lines in the file.\n  llvm::SmallVector<testing::Matcher<std::string>> expected_stdout;\n  llvm::SmallVector<testing::Matcher<std::string>> expected_stderr;\n\n  // stdout and stderr from Run. 16 is arbitrary but a required value.\n  llvm::SmallString<16> actual_stdout;\n  llvm::SmallString<16> actual_stderr;\n\n  FileTestBase::RunResult run_result = {.success = false};\n\n  // Time spent inside FileTestBase::Run.\n  std::chrono::milliseconds run_elapsed_ms = std::chrono::milliseconds(0);\n};\n\n// Processes the test input, producing test files and expected output.\nauto ProcessTestFile(llvm::StringRef test_name, bool running_autoupdate)\n    -> ErrorOr<TestFile>;\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_FILE_TEST_TEST_FILE_H_\n"
  },
  {
    "path": "testing/file_test/test_file_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"testing/file_test/test_file.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include \"common/error_test_helpers.h\"\n#include \"testing/base/file_helpers.h\"\n#include \"testing/file_test/file_test_base.h\"\n\n// The current BUILD structure of this library means that in order to unit-test\n// test_file.h, we have to pretend to be a file_test. That means there has to\n// be a definition of CarbonFileTestManifest (normally generated by a file_test\n// Bazel rule), and there has to be a registered FileTestFactory, so we define\n// them both as dummies.\n// TODO: restructure BUILD rules to avoid the need for this hack.\n\n// Dummy empty manifest.\n// NOLINTNEXTLINE(readability-identifier-naming): manifest.cpp dictates spelling\nconst char* CarbonFileTestManifest[] = {nullptr};\n\nnamespace Carbon::Testing {\n\n// Dummy unusable FileTestBase.\nclass DummyFileTest : public FileTestBase {\n public:\n  DummyFileTest(llvm::StringRef /*exe_path*/, llvm::StringRef test_name)\n      : FileTestBase(test_name) {}\n\n  auto Run(const llvm::SmallVector<llvm::StringRef>& /*test_args*/,\n           llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>& /*fs*/,\n           FILE* /*input_stream*/, llvm::raw_pwrite_stream& /*output_stream*/,\n           llvm::raw_pwrite_stream& /*error_stream*/) const\n      -> ErrorOr<RunResult> override {\n    CARBON_FATAL(\"Called method of dummy object\");\n  }\n\n  auto GetDefaultArgs() const -> llvm::SmallVector<std::string> override {\n    CARBON_FATAL(\"Called method of dummy object\");\n  }\n};\nCARBON_FILE_TEST_FACTORY(DummyFileTest)\n\nnamespace {\n\nusing ::testing::_;\nusing ::testing::StrEq;\n\n// Returns the non-check lines of test_file as a string.\nauto NonCheckFileContents(const TestFile& test_file) -> std::string {\n  std::string buffer;\n  llvm::raw_string_ostream out(buffer);\n  for (const auto& line : test_file.non_check_lines) {\n    line.Print(out);\n    out << \"\\n\";\n  }\n  return buffer;\n}\n\n// Returns a string consisting of 7 repetitions of `c`, for use as a simulated\n// merge conflict marker. We use this in test inputs instead of writing the\n// conflict markers directly in the string literals so that tools don't treat\n// them as genuine merge conflicts in this file.\nauto Marker(char c) -> std::string { return std::string(7, c); }\n\nTEST(AutoupdateTest, SnapshotMergeConflict) {\n  std::string initial_contents = R\"(\n// AUTOUPDATE\nSome text\n)\" + Marker('<') + R\"(\n// CHECK:STDOUT: side 1\n)\" + Marker('=') + R\"(\n// CHECK:STDOUT: side 2\n)\" + Marker('>') + R\"(\nMore text\n)\";\n\n  constexpr std::string_view ExpectedContents = R\"(\n// AUTOUPDATE\nSome text\nMore text\n)\";\n  auto file_path = *WriteTestFile(\"tmp\", initial_contents);\n  auto test_file =\n      ProcessTestFile(file_path.c_str(), /*running_autoupdate=*/true);\n  ASSERT_THAT(test_file, IsSuccess(_)) << test_file.error();\n  EXPECT_THAT(NonCheckFileContents(*test_file), StrEq(ExpectedContents));\n}\n\nTEST(AutoupdateTest, SnapshotTheeWayMergeConflict) {\n  std::string initial_contents = R\"(\n// AUTOUPDATE\nSome text\n)\" + Marker('<') + R\"(\n// CHECK:STDOUT: side 1\n)\" + Marker('|') + R\"(\n// CHECK:STDOUT: base\n)\" + Marker('=') + R\"(\n// CHECK:STDOUT: side 2\n)\" + Marker('>') + R\"(\nMore text\n)\";\n\n  constexpr std::string_view ExpectedContents = R\"(\n// AUTOUPDATE\nSome text\nMore text\n)\";\n  auto file_path = *WriteTestFile(\"tmp\", initial_contents);\n  auto test_file =\n      ProcessTestFile(file_path.c_str(), /*running_autoupdate=*/true);\n  ASSERT_THAT(test_file, IsSuccess(_)) << test_file.error();\n  EXPECT_THAT(NonCheckFileContents(*test_file), StrEq(ExpectedContents));\n}\n\nTEST(AutoupdateTest, DiffMergeConflict) {\n  std::string initial_contents = R\"(\n// AUTOUPDATE\nSome text\n)\" + Marker('<') + R\"(\n)\" + Marker('%') + R\"(\n)\" + Marker('\\\\') + R\"(\n // CHECK:STDOUT: unchanged\n-// CHECK:STDOUT: base\n+// CHECK:STDOUT: side 1\n)\" + Marker('+') + R\"(\n// CHECK:STDOUT: side 2\n)\" + Marker('>') + R\"(\nMore text\n)\";\n\n  constexpr std::string_view ExpectedContents = R\"(\n// AUTOUPDATE\nSome text\nMore text\n)\";\n  auto file_path = *WriteTestFile(\"tmp\", initial_contents);\n  auto test_file =\n      ProcessTestFile(file_path.c_str(), /*running_autoupdate=*/true);\n  ASSERT_THAT(test_file, IsSuccess(_)) << test_file.error();\n  EXPECT_THAT(NonCheckFileContents(*test_file), StrEq(ExpectedContents));\n}\n\nTEST(AutoupdateTest, NonCheckInDiffRegion) {\n  std::string initial_contents = R\"(\n// AUTOUPDATE\nSome text\n)\" + Marker('<') + R\"(\n)\" + Marker('%') + R\"(\n)\" + Marker('\\\\') + R\"(\n // unchanged\n-// CHECK:STDOUT: base\n+// CHECK:STDOUT: side 1\n)\" + Marker('+') + R\"(\n// CHECK:STDOUT: side 2\n)\" + Marker('>') + R\"(\nMore text\n)\";\n\n  auto file_path = *WriteTestFile(\"tmp\", initial_contents);\n  auto test_file =\n      ProcessTestFile(file_path.c_str(), /*running_autoupdate=*/true);\n  ASSERT_THAT(test_file, IsError(_));\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "testing/file_test/testdata/alternating_files.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/alternating_files.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/alternating_files.carbon\n// CHECK:STDERR: unattached message 1\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`\n// CHECK:STDOUT: unattached message 1\n\n// --- a.carbon\n// CHECK:STDERR: a.carbon:[[@LINE+1]]: message 2\naaa\n// CHECK:STDOUT: a.carbon:[[@LINE-1]]: message 2\n\n// --- b.carbon\n// CHECK:STDERR: b.carbon:[[@LINE+4]]: message 3\n// CHECK:STDERR: a.carbon:2: message 4\n// CHECK:STDERR: b.carbon:[[@LINE+2]]: message 5\n// CHECK:STDERR: unattached message 6\nbbb\n// CHECK:STDOUT: b.carbon:[[@LINE-1]]: message 3\n// CHECK:STDOUT: a.carbon:2: message 4\n// CHECK:STDOUT: b.carbon:[[@LINE-3]]: message 5\n// CHECK:STDOUT: unattached message 6\nbbbbbb\n"
  },
  {
    "path": "testing/file_test/testdata/args.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// ARGS: abc file=%t %s prefix_%{replacement}_suffix\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/args.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/args.carbon\n\n// CHECK:STDOUT: 4 args: `abc`, `file={{.+}}/temp_file`, `args.carbon`, `prefix_replaced_suffix`\n"
  },
  {
    "path": "testing/file_test/testdata/autoupdate_split.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/autoupdate_split.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/autoupdate_split.carbon\n\n// --- a.carbon\naaa\n\n// --- b.carbon\nbbb\n\n// --- AUTOUPDATE-SPLIT\n\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`\n// CHECK:STDOUT: a.carbon:1: aaa\n// CHECK:STDOUT: b.carbon:1: bbb\n"
  },
  {
    "path": "testing/file_test/testdata/autoupdate_split_standalone.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/autoupdate_split_standalone.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/autoupdate_split_standalone.carbon\n\n// --- AUTOUPDATE-SPLIT\n\n// CHECK:STDOUT: 1 args: `default_args`\n"
  },
  {
    "path": "testing/file_test/testdata/capture_console_output.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// SET-CAPTURE-CONSOLE-OUTPUT\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/capture_console_output.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/capture_console_output.carbon\n// CHECK:STDERR: params.error_stream\n// CHECK:STDERR: llvm::errs\n\n// CHECK:STDOUT: 2 args: `default_args`, `capture_console_output.carbon`\n// CHECK:STDOUT: params.output_stream\n// CHECK:STDOUT: llvm::outs\n"
  },
  {
    "path": "testing/file_test/testdata/escaping.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// SET-CAPTURE-CONSOLE-OUTPUT\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/escaping.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/escaping.carbon\n// CHECK:STDERR: carriage return{{\\r}}\n// CHECK:STDERR: {one brace}\n// CHECK:STDERR: {{\\{\\{}}two braces}}\n// CHECK:STDERR: [one bracket]\n// CHECK:STDERR: {{\\[\\[}}two brackets]]\n// CHECK:STDERR: end of line whitespace   {{}}\n// CHECK:STDERR: {{\\t}}tabs{{\\t}}\n\n// CHECK:STDOUT: 2 args: `default_args`, `escaping.carbon`\n"
  },
  {
    "path": "testing/file_test/testdata/example.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// Can't autoupdate due to the `{{.+}}` check.\n// NOAUTOUPDATE\n// CHECK:STDOUT: 2 args: `default_args`, `example.carbon`\n// CHECK:STDOUT: something\n// CHECK:STDOUT:\n// CHECK:STDOUT: example.carbon:[[@LINE+1]]: Line delta\n// CHECK:STDOUT: example.carbon:[[@LINE-1]]: Negative line delta\n// CHECK:STDOUT: +*[]{}\n// CHECK:STDOUT: F{{.+}}z\n"
  },
  {
    "path": "testing/file_test/testdata/fail_example.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/fail_example.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/fail_example.carbon\n// CHECK:STDERR: Oops\n\n// CHECK:STDOUT: 2 args: `default_args`, `fail_example.carbon`\n"
  },
  {
    "path": "testing/file_test/testdata/fail_multi_success_overall_fail.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/fail_multi_success_overall_fail.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/fail_multi_success_overall_fail.carbon\n\n// --- a.carbon\naaa\n\n// --- b.carbon\nbbb\n\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`\n"
  },
  {
    "path": "testing/file_test/testdata/file_only_re_multi_file.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/file_only_re_multi_file.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/file_only_re_multi_file.carbon\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`\n// CHECK:STDOUT: unattached message 1\n\n// --- a.carbon\n// CHECK:STDOUT: file: a.carbon\n// CHECK:STDOUT: unattached message 2\naaa\n// CHECK:STDOUT: line: [[@LINE-1]]: attached message 3\n// CHECK:STDOUT: unattached message 4\n\n// CHECK:STDOUT: line: [[@LINE+1]]: late message 5\n// CHECK:STDOUT: unattached message 6\n// --- b.carbon\n// CHECK:STDOUT: file: b.carbon\nbbb\n// CHECK:STDOUT: line: [[@LINE-1]]: attached message 7\n// CHECK:STDOUT: unattached message 8\n\n// CHECK:STDOUT: line: [[@LINE+1]]: late message 9\n// CHECK:STDOUT: unattached message 10\n"
  },
  {
    "path": "testing/file_test/testdata/file_only_re_one_file.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/file_only_re_one_file.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/file_only_re_one_file.carbon\n// CHECK:STDOUT: 2 args: `default_args`, `file_only_re_one_file.carbon`\n// CHECK:STDOUT: unattached message 1\n// CHECK:STDOUT: file: file_only_re_one_file.carbon\n// CHECK:STDOUT: line: [[@LINE-12]]\n// CHECK:STDOUT: unattached message 2\n"
  },
  {
    "path": "testing/file_test/testdata/include_args.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: testing/file_test/testdata/include_files/args.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/include_args.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_args.carbon\n\n// CHECK:STDOUT: 3 args: `foo`, `bar`, `baz`\n"
  },
  {
    "path": "testing/file_test/testdata/include_args_and_extra_args.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: testing/file_test/testdata/include_files/extra_args.carbon\n// ARGS: foo\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/include_args_and_extra_args.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_args_and_extra_args.carbon\n\n// CHECK:STDOUT: 3 args: `foo`, `bar`, `baz`\n"
  },
  {
    "path": "testing/file_test/testdata/include_empty.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: testing/file_test/testdata/include_files/empty.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/include_empty.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_empty.carbon\n\n// CHECK:STDOUT: 3 args: `default_args`, `empty.carbon`, `include_empty.carbon`\n"
  },
  {
    "path": "testing/file_test/testdata/include_extra_args.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// EXTRA-ARGS: foo\n// INCLUDE-FILE: testing/file_test/testdata/include_files/extra_args.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/include_extra_args.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_extra_args.carbon\n\n// CHECK:STDOUT: 6 args: `default_args`, `include_files/extra_args.carbon`, `include_extra_args.carbon`, `bar`, `baz`, `foo`\n"
  },
  {
    "path": "testing/file_test/testdata/include_files/args.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// ARGS: foo bar baz\n"
  },
  {
    "path": "testing/file_test/testdata/include_files/empty.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// --- empty.carbon\n"
  },
  {
    "path": "testing/file_test/testdata/include_files/extra_args.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// EXTRA-ARGS: bar baz\n"
  },
  {
    "path": "testing/file_test/testdata/include_files/no_split.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nno split\n"
  },
  {
    "path": "testing/file_test/testdata/include_files/recursive.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// INCLUDE-FILE: testing/file_test/testdata/include_files/split.carbon\n\n// --- c.carbon\n\nc\n\n// --- d.carbon\n\nd\n"
  },
  {
    "path": "testing/file_test/testdata/include_files/split.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// --- a.carbon\n\na\n\n// --- b.carbon\n\nb\n"
  },
  {
    "path": "testing/file_test/testdata/include_no_split.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: testing/file_test/testdata/include_files/no_split.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/include_no_split.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_no_split.carbon\n\n// CHECK:STDOUT: 3 args: `default_args`, `include_files/no_split.carbon`, `include_no_split.carbon`\n// CHECK:STDOUT: include_files/no_split.carbon:5: no split\n"
  },
  {
    "path": "testing/file_test/testdata/include_recursive.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: testing/file_test/testdata/include_files/recursive.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/include_recursive.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_recursive.carbon\n\n// CHECK:STDOUT: 6 args: `default_args`, `c.carbon`, `d.carbon`, `a.carbon`, `b.carbon`, `include_recursive.carbon`\n// CHECK:STDOUT: c.carbon:2: c\n// CHECK:STDOUT: d.carbon:2: d\n// CHECK:STDOUT: a.carbon:2: a\n// CHECK:STDOUT: b.carbon:2: b\n"
  },
  {
    "path": "testing/file_test/testdata/include_repeated.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: testing/file_test/testdata/include_files/no_split.carbon\n// INCLUDE-FILE: testing/file_test/testdata/include_files/no_split.carbon\n// INCLUDE-FILE: testing/file_test/testdata/include_files/no_split.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/include_repeated.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_repeated.carbon\n\n// CHECK:STDOUT: 3 args: `default_args`, `include_files/no_split.carbon`, `include_repeated.carbon`\n// CHECK:STDOUT: include_files/no_split.carbon:5: no split\n"
  },
  {
    "path": "testing/file_test/testdata/include_split.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: testing/file_test/testdata/include_files/split.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/include_split.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/include_split.carbon\n\n// CHECK:STDOUT: 4 args: `default_args`, `a.carbon`, `b.carbon`, `include_split.carbon`\n// CHECK:STDOUT: a.carbon:2: a\n// CHECK:STDOUT: b.carbon:2: b\n"
  },
  {
    "path": "testing/file_test/testdata/lsp_autofill.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/lsp_autofill.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/lsp_autofill.carbon\n\n// --- foo.carbon\nclass Foo {\n  fn foo();\n  fn bar() {}\n}\n\n// --- STDIN\n[[@LSP-NOTIFY:textDocument/didOpen:\n  \"textDocument\": {\n    \"uri\": \"file:/foo.carbon\",\n    \"languageId\": \"carbon\",\n    \"text\": \"FROM_FILE_SPLIT\"\n  }\n]]\n\n// --- AUTOUPDATE-SPLIT\n\n// CHECK:STDERR: --- STDIN:\n// CHECK:STDERR: Content-Length: 182\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"method\":\"textDocument/didOpen\",\"params\":{\"textDocument\":{\"languageId\":\"carbon\",\"text\":\"class Foo {\\n  fn foo();\\n  fn bar() {}\\n}\\n\\n\",\"uri\":\"file:/foo.carbon\"}}}\n// CHECK:STDERR:\n// CHECK:STDERR:\n// CHECK:STDOUT: 2 args: `default_args`, `foo.carbon`\n// CHECK:STDOUT: foo.carbon:1: class Foo {\n// CHECK:STDOUT: foo.carbon:2:   fn foo();\n// CHECK:STDOUT: foo.carbon:3:   fn bar() {}\n// CHECK:STDOUT: foo.carbon:4: }\n"
  },
  {
    "path": "testing/file_test/testdata/lsp_keywords.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/lsp_keywords.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/lsp_keywords.carbon\n\n// --- STDIN\n[[@LSP:foo:]]\n[[@LSP:foo]]\n[[@LSP:bar:\"content\": 0]]\n[[@LSP:baz:\n\"multi\": 0,\n\"line\": 1\n]]\n[[@LSP-CALL:bar:\"content\": 0]]\n[[@LSP-CALL:baz:\n\"multi\": 0,\n\"line\": 1]]\n[[@LSP-REPLY:7]]\n[[@LSP-REPLY:8:\"bar\": 0]]\n[[@LSP-NOTIFY:exit]]\n\n// --- AUTOUPDATE-SPLIT\n\n// CHECK:STDERR: --- STDIN:\n// CHECK:STDERR: Content-Length: 34\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"method\":\"foo\"}\n// CHECK:STDERR:\n// CHECK:STDERR: Content-Length: 34\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"method\":\"foo\"}\n// CHECK:STDERR:\n// CHECK:STDERR: Content-Length: 46\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"method\":\"bar\",\"content\":0}\n// CHECK:STDERR:\n// CHECK:STDERR: Content-Length: 53\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"method\":\"baz\",\"multi\":0,\"line\":1}\n// CHECK:STDERR:\n// CHECK:STDERR: Content-Length: 64\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"method\":\"bar\",\"id\":1,\"params\":{\"content\":0}}\n// CHECK:STDERR:\n// CHECK:STDERR: Content-Length: 71\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"method\":\"baz\",\"id\":2,\"params\":{\"line\":1,\"multi\":0}}\n// CHECK:STDERR:\n// CHECK:STDERR: Content-Length: 28\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"id\":\"7\"}\n// CHECK:STDERR:\n// CHECK:STDERR: Content-Length: 47\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"id\":\"8\",\"result\":{\"bar\":0}}\n// CHECK:STDERR:\n// CHECK:STDERR: Content-Length: 35\n// CHECK:STDERR:\n// CHECK:STDERR: {\"jsonrpc\":\"2.0\",\"method\":\"exit\"}\n// CHECK:STDERR:\n// CHECK:STDERR:\n// CHECK:STDOUT: 1 args: `default_args`\n"
  },
  {
    "path": "testing/file_test/testdata/multi_success.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/multi_success.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/multi_success.carbon\n\n// --- a.carbon\naaa\n\n// --- b.carbon\nbbb\n\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`\n"
  },
  {
    "path": "testing/file_test/testdata/multi_success_and_fail.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/multi_success_and_fail.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/multi_success_and_fail.carbon\n\n// --- a.carbon\naaa\n\n// --- fail_b.carbon\nbbb\n\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `fail_b.carbon`\n"
  },
  {
    "path": "testing/file_test/testdata/multiple_file_refs_in_line.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/multiple_file_refs_in_line.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/multiple_file_refs_in_line.carbon\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`\n\n// --- a.carbon\na.carbon:1: b.carbon:3: a.carbon:3: hello\n// CHECK:STDOUT: a.carbon:[[@LINE-1]]: a.carbon:[[@LINE-1]]: b.carbon:3: a.carbon:[[@LINE+1]]: hello\n\n// --- b.carbon\n\n\na.carbon:1: b.carbon:3: a.carbon:3: hello\n// CHECK:STDOUT: b.carbon:[[@LINE-1]]: a.carbon:1: b.carbon:[[@LINE-1]]: a.carbon:3: hello\na.carbon:1: b.carbon:5: a.carbon:3: hello\n// CHECK:STDOUT: b.carbon:[[@LINE-1]]: a.carbon:1: b.carbon:[[@LINE-1]]: a.carbon:3: hello\na.carbon:1: b.carbon:7: a.carbon:3: hello\n// CHECK:STDOUT: b.carbon:[[@LINE-1]]: a.carbon:1: b.carbon:[[@LINE-1]]: a.carbon:3: hello\n"
  },
  {
    "path": "testing/file_test/testdata/no_line_number.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/no_line_number.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/no_line_number.carbon\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`\n\n// --- a.carbon\n// CHECK:STDOUT: a.carbon: msg1\n// CHECK:STDOUT: msg2\naaa\n\n// --- b.carbon\n// CHECK:STDOUT: b.carbon: msg3\n// CHECK:STDOUT: msg4\n// CHECK:STDOUT: a.carbon: msg5\nbbb\n"
  },
  {
    "path": "testing/file_test/testdata/not_split.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/not_split.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/not_split.carbon\n// CHECK:STDOUT: 2 args: `default_args`, `not_split.carbon`\n\nnot split\n// CHECK:STDOUT: not_split.carbon:[[@LINE-1]]: not split\n"
  },
  {
    "path": "testing/file_test/testdata/replace_content.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/replace_content.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/replace_content.carbon\n// CHECK:STDOUT: 2 args: `default_args`, `replace_content.carbon`\n\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDOUT: replace_content.carbon:[[@LINE-1]]: library \"replace_content\";\n\nvar x: str = \"[[@0x48]][[@0x65]][[@0x6C]][[@0x6C]][[@0x6F]]\";\n// CHECK:STDOUT: replace_content.carbon:[[@LINE-1]]: var x: str = \"Hello\";\n"
  },
  {
    "path": "testing/file_test/testdata/replace_split_content.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/replace_split_content.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/replace_split_content.carbon\n// CHECK:STDOUT: 6 args: `default_args`, `a.carbon`, `b.impl.carbon`, `todo_c.carbon`, `todo_fail_d.carbon`, `triplicate.carbon`\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDOUT: a.carbon:[[@LINE-1]]: library \"a\";\n\n// --- b.impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDOUT: b.impl.carbon:[[@LINE-1]]: library \"b\";\n\n// --- todo_c.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDOUT: todo_c.carbon:[[@LINE-1]]: library \"c\";\n\n// --- todo_fail_d.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDOUT: todo_fail_d.carbon:[[@LINE-1]]: library \"d\";\n\n// --- triplicate.carbon\n\n[[@TEST_NAME]][[@TEST_NAME]][[@TEST_NAME]]\n// CHECK:STDOUT: triplicate.carbon:[[@LINE-1]]: triplicatetriplicatetriplicate\n"
  },
  {
    "path": "testing/file_test/testdata/stdin.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/stdin.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/stdin.carbon\n\n// --- a.carbon\n\n// --- STDIN\n\nS\nt\nd\ni\nn\n\n// --- AUTOUPDATE-SPLIT\n\n// CHECK:STDERR: --- STDIN:\n// CHECK:STDERR:\n// CHECK:STDERR: S\n// CHECK:STDERR: t\n// CHECK:STDERR: d\n// CHECK:STDERR: i\n// CHECK:STDERR: n\n// CHECK:STDERR:\n// CHECK:STDOUT: 2 args: `default_args`, `a.carbon`\n"
  },
  {
    "path": "testing/file_test/testdata/two_files.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/two_files.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/two_files.carbon\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`\n\n// --- a.carbon\naaa\n// CHECK:STDOUT: a.carbon:[[@LINE-1]]: aaa\n\n\n// --- b.carbon\nbbb\n// CHECK:STDOUT: b.carbon:[[@LINE-1]]: bbb\n"
  },
  {
    "path": "testing/file_test/testdata/unattached_multi_file.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //testing/file_test:file_test_base_test --test_arg=--file_tests=testing/file_test/testdata/unattached_multi_file.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //testing/file_test:file_test_base_test -- --dump_output --file_tests=testing/file_test/testdata/unattached_multi_file.carbon\n// CHECK:STDERR: unattached message 3\n// CHECK:STDERR: unattached message 4\n\n// --- a.carbon\naaa\n\n// --- b.carbon\nbbb\n\n// CHECK:STDOUT: 3 args: `default_args`, `a.carbon`, `b.carbon`\n// CHECK:STDOUT: unattached message 1\n// CHECK:STDOUT: unattached message 2\n"
  },
  {
    "path": "testing/fuzzing/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\n# Header for LibFuzzer, does not provide the implementation which should come\n# from some other source such as a fuzz test target.\ncc_library(\n    name = \"libfuzzer_header\",\n    testonly = 1,\n    hdrs = [\"libfuzzer.h\"],\n)\n"
  },
  {
    "path": "testing/fuzzing/libfuzzer.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TESTING_FUZZING_LIBFUZZER_H_\n#define CARBON_TESTING_FUZZING_LIBFUZZER_H_\n\n#include <cstddef>\n\nnamespace Carbon::Testing {\n\n// Declaration for the LLVM libfuzzer API that we implement in our fuzz tests.\n// This is useful to ensure we get the API correct and avoid warnings about\n// defining an undeclared extern function due to a Clang warning bug:\n// https://github.com/llvm/llvm-project/issues/94138\n// NOLINTNEXTLINE: Match the documented fuzzer entry point declaration style.\nextern \"C\" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size);\n\n// Optional API that can be implemented but isn't required. This allows fuzzers\n// to observe the `argv` during initialization.\n// NOLINTNEXTLINE: Match the documented fuzzer entry point declaration style.\nextern \"C\" int LLVMFuzzerInitialize(int* argc, char*** argv);\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TESTING_FUZZING_LIBFUZZER_H_\n"
  },
  {
    "path": "testing/fuzzing/rules.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Rules for building fuzz tests.\"\"\"\n\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_test\")\n\ndef _cc_fuzz_test(corpus, args, data, **kwargs):\n    \"\"\"Generates a single test target.\n\n    Append the corpus files to the test arguments. When run on a list of\n    files rather than a directory, libFuzzer-based fuzzers will perform a\n    regression test against the corpus.\n    \"\"\"\n    cc_test(\n        data = data + corpus,\n        args = args + [\"$(location %s)\" % file for file in corpus],\n        **kwargs\n    )\n\ndef cc_fuzz_test(\n        name,\n        corpus,\n        args = [],\n        data = [],\n        features = [],\n        tags = [],\n        deps = [],\n        shard_count = 1,\n        **kwargs):\n    \"\"\"Macro for C++ fuzzing test.\n\n    In order to run tests on a single file, run the fuzzer binary under\n    bazel-bin directly. That will avoid the args being passed by Bazel.\n\n    Args:\n        name: The main fuzz test rule name.\n        corpus: List of files to use as a fuzzing corpus.\n        args: Will have the locations of the corpus files added and passed down\n            to the fuzz test.\n        data: Will have the corpus added and passed down to the fuzz test.\n        features: Will have the \"fuzzer\" feature added and passed down to the\n            fuzz test.\n        tags: Will have \"fuzz_test\" added and passed down to the fuzz test.\n        deps: Will have \"@llvm-project//compiler-rt:FuzzerMain\" added and passed\n            down to the fuzz test.\n        shard_count: Provides sharding of the fuzz test.\n        **kwargs: Remaining arguments passed down to the fuzz test.\n    \"\"\"\n\n    # Add relevant tag and feature if necessary.\n    if \"fuzz_test\" not in tags:\n        tags = tags + [\"fuzz_test\"]\n    if \"fuzzer\" not in features:\n        features = features + [\"fuzzer\"]\n    if \"@llvm-project//compiler-rt:FuzzerMain\" not in deps:\n        deps = deps + [\"@llvm-project//compiler-rt:FuzzerMain\"]\n\n    # The FuzzerMain library doesn't support sharding based on inputs, so we\n    # general separate test targets in order to shard execution.\n    if shard_count == 1:\n        # When there's one shard, only one target is needed.\n        _cc_fuzz_test(\n            corpus,\n            args,\n            data,\n            name = name,\n            features = features,\n            tags = tags,\n            deps = deps,\n            **kwargs\n        )\n    else:\n        # Calculate the number of inputs per shard. This is equivalent to\n        # ceiling division, so that the corpus subsetting doesn't miss odd\n        # files.\n        shard_size = len(corpus) // shard_count\n        if shard_count * shard_size < len(corpus):\n            shard_size += 1\n\n        # Create separate targets for each shard.\n        shards = []\n        for shard in range(shard_count):\n            shard_name = \"{0}.shard{1}\".format(name, shard)\n            shards.append(shard_name)\n\n            _cc_fuzz_test(\n                corpus[shard * shard_size:(shard + 1) * shard_size],\n                args,\n                data,\n                name = shard_name,\n                features = features,\n                tags = tags,\n                deps = deps,\n                **kwargs\n            )\n\n        # Create a suite containing all shards.\n        native.test_suite(\n            name = name,\n            tests = shards,\n        )\n\n        # Create one target that includes the full corpus.\n        _cc_fuzz_test(\n            corpus,\n            args,\n            data,\n            name = \"{0}.full_corpus\".format(name),\n            features = features,\n            tags = tags + [\"manual\"],\n            deps = deps,\n            **kwargs\n        )\n"
  },
  {
    "path": "third_party/README.md",
    "content": "# Third-party\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThe `/third_party` directory is for any code that doesn't follow Carbon's normal\ncontribution rules, and thus requires special care. The intent is that code\n_not_ under `/third_party` should not require special contribution rules.\n\nExamples of code belonging under `/third_party` include:\n\n-   Code not licensed under the standard\n    [Apache-2.0 WITH LLVM-exception license](/LICENSE).\n-   Code which is maintained externally or imported from another repository.\n-   Code which is not fully under\n    [Carbon's CLA](/CONTRIBUTING.md#contributor-license-agreements-clas).\n"
  },
  {
    "path": "third_party/examples/README.md",
    "content": "# Third-party examples\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis directory contains third-party examples of C++ libraries and how they might\nbe ported to Carbon. The goal is to illustrate both how Carbon works using\nreal-world code as well as relevant and expected steps when migrating from C++\nto Carbon.\n\nTODO: Example submodules need to be replaced\n([issue #1067](https://github.com/carbon-language/carbon-lang/issues/1067)).\n"
  },
  {
    "path": "third_party/examples/re2/LICENSE",
    "content": "// Copyright (c) 2009 The RE2 Authors. All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without\n// modification, are permitted provided that the following conditions are\n// met:\n//\n//    * Redistributions of source code must retain the above copyright\n// notice, this list of conditions and the following disclaimer.\n//    * Redistributions in binary form must reproduce the above\n// copyright notice, this list of conditions and the following disclaimer\n// in the documentation and/or other materials provided with the\n// distribution.\n//    * Neither the name of Google Inc. nor the names of its\n// contributors may be used to endorse or promote products derived from\n// this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n// \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "third_party/examples/re2/re2.carbon",
    "content": "// Copyright 2003-2009 The RE2 Authors.  All Rights Reserved.\n// Use of this source code is governed by a BSD-style\n// license that can be found in the LICENSE file.\n\n// TODO: Package name conflicts with member class RE2!\npackage RE2 api;\n\n// C++ interface to the re2 regular-expression library.\n// RE2 supports Perl-style regular expressions (with extensions like\n// \\d, \\w, \\s, ...).\n//\n// -----------------------------------------------------------------------\n// REGEXP SYNTAX:\n//\n// This module uses the re2 library and hence supports\n// its syntax for regular expressions, which is similar to Perl's with\n// some of the more complicated things thrown away.  In particular,\n// backreferences and generalized assertions are not available, nor is \\Z.\n//\n// See https://github.com/google/re2/wiki/Syntax for the syntax\n// supported by RE2, and a comparison with PCRE and PERL regexps.\n//\n// For those not familiar with Perl's regular expressions,\n// here are some examples of the most commonly used extensions:\n//\n//   \"hello (\\\\w+) world\"  -- \\w matches a \"word\" character\n//   \"version (\\\\d+)\"      -- \\d matches a digit\n//   \"hello\\\\s+world\"      -- \\s matches any whitespace character\n//   \"\\\\b(\\\\w+)\\\\b\"        -- \\b matches non-empty string at word boundary\n//   \"(?i)hello\"           -- (?i) turns on case-insensitive matching\n//   \"/\\\\*(.*?)\\\\*/\"       -- .*? matches . minimum no. of times possible\n//\n// The double backslashes are needed when writing C++ string literals.\n// However, they should NOT be used when writing C++11 raw string literals:\n//\n//   R\"(hello (\\w+) world)\"  -- \\w matches a \"word\" character\n//   R\"(version (\\d+))\"      -- \\d matches a digit\n//   R\"(hello\\s+world)\"      -- \\s matches any whitespace character\n//   R\"(\\b(\\w+)\\b)\"          -- \\b matches non-empty string at word boundary\n//   R\"((?i)hello)\"          -- (?i) turns on case-insensitive matching\n//   R\"(/\\*(.*?)\\*/)\"        -- .*? matches . minimum no. of times possible\n//\n// When using UTF-8 encoding, case-insensitive matching will perform\n// simple case folding, not full case folding.\n//\n// -----------------------------------------------------------------------\n// MATCHING INTERFACE:\n//\n// The \"FullMatch\" operation checks that supplied text matches a\n// supplied pattern exactly.\n//\n// Example: successful match\n//    CHECK(RE2::FullMatch(\"hello\", \"h.*o\"));\n//\n// Example: unsuccessful match (requires full match):\n//    CHECK(!RE2::FullMatch(\"hello\", \"e\"));\n//\n// -----------------------------------------------------------------------\n// UTF-8 AND THE MATCHING INTERFACE:\n//\n// By default, the pattern and input text are interpreted as UTF-8.\n// The RE2::Latin1 option causes them to be interpreted as Latin-1.\n//\n// Example:\n//    CHECK(RE2::FullMatch(utf8_string, RE2(utf8_pattern)));\n//    CHECK(RE2::FullMatch(latin1_string, RE2(latin1_pattern, RE2::Latin1)));\n//\n// -----------------------------------------------------------------------\n// MATCHING WITH SUBSTRING EXTRACTION:\n//\n// You can supply extra pointer arguments to extract matched substrings.\n// On match failure, none of the pointees will have been modified.\n// On match success, the substrings will be converted (as necessary) and\n// their values will be assigned to their pointees until all conversions\n// have succeeded or one conversion has failed.\n// On conversion failure, the pointees will be in an indeterminate state\n// because the caller has no way of knowing which conversion failed.\n// However, conversion cannot fail for types like string and StringPiece\n// that do not inspect the substring contents. Hence, in the common case\n// where all of the pointees are of such types, failure is always due to\n// match failure and thus none of the pointees will have been modified.\n//\n// Example: extracts \"ruby\" into \"s\" and 1234 into \"i\"\n//    int i;\n//    std::string s;\n//    CHECK(RE2::FullMatch(\"ruby:1234\", \"(\\\\w+):(\\\\d+)\", &s, &i));\n//\n// Example: fails because string cannot be stored in integer\n//    CHECK(!RE2::FullMatch(\"ruby\", \"(.*)\", &i));\n//\n// Example: fails because there aren't enough sub-patterns\n//    CHECK(!RE2::FullMatch(\"ruby:1234\", \"\\\\w+:\\\\d+\", &s));\n//\n// Example: does not try to extract any extra sub-patterns\n//    CHECK(RE2::FullMatch(\"ruby:1234\", \"(\\\\w+):(\\\\d+)\", &s));\n//\n// Example: does not try to extract into NULL\n//    CHECK(RE2::FullMatch(\"ruby:1234\", \"(\\\\w+):(\\\\d+)\", NULL, &i));\n//\n// Example: integer overflow causes failure\n//    CHECK(!RE2::FullMatch(\"ruby:1234567891234\", \"\\\\w+:(\\\\d+)\", &i));\n//\n// NOTE(rsc): Asking for substrings slows successful matches quite a bit.\n// This may get a little faster in the future, but right now is slower\n// than PCRE.  On the other hand, failed matches run *very* fast (faster\n// than PCRE), as do matches without substring extraction.\n//\n// -----------------------------------------------------------------------\n// PARTIAL MATCHES\n//\n// You can use the \"PartialMatch\" operation when you want the pattern\n// to match any substring of the text.\n//\n// Example: simple search for a string:\n//      CHECK(RE2::PartialMatch(\"hello\", \"ell\"));\n//\n// Example: find first number in a string\n//      int number;\n//      CHECK(RE2::PartialMatch(\"x*100 + 20\", \"(\\\\d+)\", &number));\n//      CHECK_EQ(number, 100);\n//\n// -----------------------------------------------------------------------\n// PRE-COMPILED REGULAR EXPRESSIONS\n//\n// RE2 makes it easy to use any string as a regular expression, without\n// requiring a separate compilation step.\n//\n// If speed is of the essence, you can create a pre-compiled \"RE2\"\n// object from the pattern and use it multiple times.  If you do so,\n// you can typically parse text faster than with sscanf.\n//\n// Example: precompile pattern for faster matching:\n//    RE2 pattern(\"h.*o\");\n//    while (ReadLine(&str)) {\n//      if (RE2::FullMatch(str, pattern)) ...;\n//    }\n//\n// -----------------------------------------------------------------------\n// SCANNING TEXT INCREMENTALLY\n//\n// The \"Consume\" operation may be useful if you want to repeatedly\n// match regular expressions at the front of a string and skip over\n// them as they match.  This requires use of the \"StringPiece\" type,\n// which represents a sub-range of a real string.\n//\n// Example: read lines of the form \"var = value\" from a string.\n//      std::string contents = ...;     // Fill string somehow\n//      StringPiece input(contents);    // Wrap a StringPiece around it\n//\n//      std::string var;\n//      int value;\n//      while (RE2::Consume(&input, \"(\\\\w+) = (\\\\d+)\\n\", &var, &value)) {\n//        ...;\n//      }\n//\n// Each successful call to \"Consume\" will set \"var/value\", and also\n// advance \"input\" so it points past the matched text.  Note that if the\n// regular expression matches an empty string, input will advance\n// by 0 bytes.  If the regular expression being used might match\n// an empty string, the loop body must check for this case and either\n// advance the string or break out of the loop.\n//\n// The \"FindAndConsume\" operation is similar to \"Consume\" but does not\n// anchor your match at the beginning of the string.  For example, you\n// could extract all words from a string by repeatedly calling\n//     RE2::FindAndConsume(&input, \"(\\\\w+)\", &word)\n//\n// -----------------------------------------------------------------------\n// USING VARIABLE NUMBER OF ARGUMENTS\n//\n// The above operations require you to know the number of arguments\n// when you write the code.  This is not always possible or easy (for\n// example, the regular expression may be calculated at run time).\n// You can use the \"N\" version of the operations when the number of\n// match arguments are determined at run time.\n//\n// Example:\n//   const RE2::Arg* args[10];\n//   int n;\n//   // ... populate args with pointers to RE2::Arg values ...\n//   // ... set n to the number of RE2::Arg objects ...\n//   bool match = RE2::FullMatchN(input, pattern, args, n);\n//\n// The last statement is equivalent to\n//\n//   bool match = RE2::FullMatch(input, pattern,\n//                               *args[0], *args[1], ..., *args[n - 1]);\n//\n// -----------------------------------------------------------------------\n// PARSING HEX/OCTAL/C-RADIX NUMBERS\n//\n// By default, if you pass a pointer to a numeric value, the\n// corresponding text is interpreted as a base-10 number.  You can\n// instead wrap the pointer with a call to one of the operators Hex(),\n// Octal(), or CRadix() to interpret the text in another base.  The\n// CRadix operator interprets C-style \"0\" (base-8) and \"0x\" (base-16)\n// prefixes, but defaults to base-10.\n//\n// Example:\n//   int a, b, c, d;\n//   CHECK(RE2::FullMatch(\"100 40 0100 0x40\", \"(.*) (.*) (.*) (.*)\",\n//         RE2::Octal(&a), RE2::Hex(&b), RE2::CRadix(&c), RE2::CRadix(&d));\n// will leave 64 in a, b, c, and d.\n\nimport Cpp library \"<algorithm>\";\nimport Cpp library \"<map>\";\nimport Cpp library \"<mutex>\";\nimport Cpp library \"<vector>\";\n\n// TODO: How to express target-specific conditional compilation?\n// TODO: #if defined(__APPLE__)\n// TODO: #include <TargetConditionals.h>\n// TODO: #endif\n\n// TODO: How to forward declare classes from another library?\n// Is a physical dependency on the library required?\n// TODO: namespace re2 {\n// TODO: class Prog;\n// TODO: class Regexp;\n// TODO: }  // namespace re2\n\nprivate interface Parse4ary;\n\n// Interface for regular expression matching.  Also corresponds to a\n// pre-compiled regular expression.  An \"RE2\" object is safe for\n// concurrent use by multiple threads.\nclass RE2 {\n  // We convert user-passed pointers into special Arg objects\n  class Arg;\n  class Options;\n\n  // Defined in set.h.\n  class Set;\n\n  // TODO: Assuming a C++-like enum syntax for now.\n  enum ErrorCode {\n    NoError = 0,\n\n    // Unexpected error\n    ErrorInternal,\n\n    // Parse errors\n    // bad escape sequence\n    ErrorBadEscape,\n    // bad character class\n    ErrorBadCharClass,\n    // bad character class range\n    ErrorBadCharRange,\n    // missing closing ]\n    ErrorMissingBracket,\n    // missing closing )\n    ErrorMissingParen,\n    // unexpected closing )\n    ErrorUnexpectedParen,\n    // trailing \\ at end of regexp\n    ErrorTrailingBackslash,\n    // repeat argument missing, e.g. \"*\"\n    ErrorRepeatArgument,\n    // bad repetition argument\n    ErrorRepeatSize,\n    // bad repetition operator\n    ErrorRepeatOp,\n    // bad perl operator\n    ErrorBadPerlOp,\n    // invalid UTF-8 in regexp\n    ErrorBadUTF8,\n    // bad named capture group\n    ErrorBadNamedCapture,\n    // pattern too large (compile failed)\n    ErrorPatternTooLarge\n  }\n\n  // Predefined common options.\n  // If you need more complicated things, instantiate\n  // an Option class, possibly passing one of these to\n  // the Option constructor, change the settings, and pass that\n  // Option class to the RE2 constructor.\n  enum CannedOptions {\n    DefaultOptions = 0,\n    // treat input as Latin-1 (default UTF-8)\n    Latin1,\n    // POSIX syntax, leftmost-longest match\n    POSIX,\n    // do not log about regexp parse errors\n    Quiet\n  }\n\n  fn Make(pattern: StringPiece) -> RE2;\n  fn Make(pattern: StringPiece, options: Options) -> RE2;\n\n  // TODO: Should a Carbonic RE2 support these?\n  impl StringView as ImplicitAs(RE2) {\n    fn Convert[self: Self]() -> RE2 { return Make(self); }\n  }\n  impl String as ImplicitAs(RE2) {\n    fn Convert[self: Self]() -> RE2 { return Make(self); }\n  }\n  impl StringPiece as ImplicitAs(RE2) {\n    fn Convert[self: Self]() -> RE2 { return Make(self); }\n  }\n\n  impl as Destroyable;\n\n  // Returns whether RE2 was created properly.\n  fn ok[self: Self]() -> bool { return self.error_code() == ErrorCode.NoError; }\n\n  // The string specification for this RE2.  E.g.\n  //   RE2 re(\"ab*c?d+\");\n  //   re.pattern();    // \"ab*c?d+\"\n  fn pattern[self: Self]() -> String { return self.pattern_; }\n\n  // If RE2 could not be created properly, returns an error string.\n  // Else returns the empty string.\n  fn error[self: Self]() -> String { return *self.error_; }\n\n  // If RE2 could not be created properly, returns an error code.\n  // Else returns RE2::NoError (== 0).\n  fn error_code[self: Self]() -> ErrorCode { return self.error_code_; }\n\n  // If RE2 could not be created properly, returns the offending\n  // portion of the regexp.\n  fn error_arg[self: Self]() -> String { return self.error_arg_; }\n\n  // Returns the program size, a very approximate measure of a regexp's \"cost\".\n  // Larger numbers are more expensive than smaller numbers.\n  fn ProgramSize[self: Self]() -> i32;\n  fn ReverseProgramSize[self: Self]() -> i32;\n\n  // If histogram is not null, outputs the program fanout\n  // as a histogram bucketed by powers of 2.\n  // Returns the number of the largest non-empty bucket.\n  fn ProgramFanout[self: Self](histogram: Cpp.std.vector(i32)*) -> i32;\n  fn ReverseProgramFanout[self: Self](histogram: Cpp.std.vector(i32)*) -> i32;\n\n  // Returns the underlying Regexp; not for general use.\n  // Returns entire_regexp_ so that callers don't need\n  // to know about prefix_ and prefix_foldcase_.\n  fn Regexp[self: Self]() -> package.Regexp* { return self.entire_regexp_; }\n\n  /***** The array-based matching interface ******/\n\n  // The functions here have names ending in 'N' and are used to implement\n  // the functions whose names are the prefix before the 'N'. It is sometimes\n  // useful to invoke them directly, but the syntax is awkward, so the 'N'-less\n  // versions should be preferred.\n  // TODO: pointer with const pointee\n  fn FullMatchN(text: StringPiece, re: Self,\n                args: Array(const Arg*), n: i32) -> bool;\n  fn PartialMatchN(text: StringPiece, re: Self,\n                   args: Array(const Arg*), n: i32) -> bool;\n  fn ConsumeN(input: StringPiece*, re: Self,\n              args: Array(const Arg*), n: i32) -> bool;\n  fn FindAndConsumeN(input: StringPiece*, re: RE2,\n                     args: Array(const Arg*), n: i32) -> bool;\n\n  private fn Apply[template F:! type, SP:! type](f: F, sp: SP, re: Self) {\n    return f(sp, re, nullptr, 0);\n  }\n\n  // TODO: (variadics)\n  // TODO: template <typename F, typename SP, typename... A>\n  // TODO: static inline bool Apply(F f, SP sp, const RE2& re, const A&... a) {\n  // TODO:   const Arg* const args[] = {&a...};\n  // TODO:   const int n = sizeof...(a);\n  // TODO:   return f(sp, re, args, n);\n  // TODO: }\n\n  // In order to allow FullMatch() et al. to be called with a varying number\n  // of arguments of varying types, we use two layers of variadic templates.\n  // The first layer constructs the temporary Arg objects. The second layer\n  // (above) constructs the array of pointers to the temporary Arg objects.\n\n  /***** The useful part: the matching interface *****/\n\n  // Matches \"text\" against \"re\".  If pointer arguments are\n  // supplied, copies matched sub-patterns into them.\n  //\n  // You can pass in a \"const char*\" or a \"std::string\" for \"text\".\n  // You can pass in a \"const char*\" or a \"std::string\" or a \"RE2\" for \"re\".\n  //\n  // The provided pointer arguments can be pointers to any scalar numeric\n  // type, or one of:\n  //    std::string     (matched piece is copied to string)\n  //    StringPiece     (StringPiece is mutated to point to matched piece)\n  //    T               (where \"bool T::ParseFrom(const char*, size_t)\" exists)\n  //    (void*)NULL     (the corresponding matched sub-pattern is not copied)\n  //\n  // Returns true iff all of the following conditions are satisfied:\n  //   a. \"text\" matches \"re\" fully - from the beginning to the end of \"text\".\n  //   b. The number of matched sub-patterns is >= number of supplied pointers.\n  //   c. The \"i\"th argument has a suitable type for holding the\n  //      string captured as the \"i\"th sub-pattern.  If you pass in\n  //      NULL for the \"i\"th argument, or pass fewer arguments than\n  //      number of sub-patterns, the \"i\"th captured sub-pattern is\n  //      ignored.\n  //\n  // CAVEAT: An optional sub-pattern that does not exist in the\n  // matched string is assigned the empty string.  Therefore, the\n  // following will return false (because the empty string is not a\n  // valid number):\n  //    int number;\n  //    RE2::FullMatch(\"abc\", \"[a-z]+(\\\\d+)?\", &number);\n  fn FullMatch(text: StringPiece, re: Self) -> bool {\n    return Apply(FullMatchN, text, re);\n  }\n  // TODO: template <typename... A>\n  // TODO: static bool FullMatch(const StringPiece& text, const RE2& re, A&&... a) {\n  // TODO:   return Apply(FullMatchN, text, re, Arg(std::forward<A>(a))...);\n  // TODO: }\n\n  // Like FullMatch(), except that \"re\" is allowed to match a substring\n  // of \"text\".\n  //\n  // Returns true iff all of the following conditions are satisfied:\n  //   a. \"text\" matches \"re\" partially - for some substring of \"text\".\n  //   b. The number of matched sub-patterns is >= number of supplied pointers.\n  //   c. The \"i\"th argument has a suitable type for holding the\n  //      string captured as the \"i\"th sub-pattern.  If you pass in\n  //      NULL for the \"i\"th argument, or pass fewer arguments than\n  //      number of sub-patterns, the \"i\"th captured sub-pattern is\n  //      ignored.\n  fn PartialMatch(text: StringPiece, re: Self) -> bool {\n    return Apply(PartialMatchN, text, re);\n  }\n  // TODO: template <typename... A>\n  // TODO: static bool PartialMatch(const StringPiece& text, const RE2& re, A&&... a) {\n  // TODO:   return Apply(PartialMatchN, text, re, Arg(std::forward<A>(a))...);\n  // TODO: }\n\n  // Like FullMatch() and PartialMatch(), except that \"re\" has to match\n  // a prefix of the text, and \"input\" is advanced past the matched\n  // text.  Note: \"input\" is modified iff this routine returns true\n  // and \"re\" matched a non-empty substring of \"input\".\n  //\n  // Returns true iff all of the following conditions are satisfied:\n  //   a. \"input\" matches \"re\" partially - for some prefix of \"input\".\n  //   b. The number of matched sub-patterns is >= number of supplied pointers.\n  //   c. The \"i\"th argument has a suitable type for holding the\n  //      string captured as the \"i\"th sub-pattern.  If you pass in\n  //      NULL for the \"i\"th argument, or pass fewer arguments than\n  //      number of sub-patterns, the \"i\"th captured sub-pattern is\n  //      ignored.\n  fn Consume(input: StringPiece*, re: Self) {\n    return Apply(ConsumeN, input, re);\n  }\n  // TODO: template <typename... A>\n  // TODO: static bool Consume(StringPiece* input, const RE2& re, A&&... a) {\n  // TODO:   return Apply(ConsumeN, input, re, Arg(std::forward<A>(a))...);\n  // TODO: }\n\n  // Like Consume(), but does not anchor the match at the beginning of\n  // the text.  That is, \"re\" need not start its match at the beginning\n  // of \"input\".  For example, \"FindAndConsume(s, \"(\\\\w+)\", &word)\" finds\n  // the next word in \"s\" and stores it in \"word\".\n  //\n  // Returns true iff all of the following conditions are satisfied:\n  //   a. \"input\" matches \"re\" partially - for some substring of \"input\".\n  //   b. The number of matched sub-patterns is >= number of supplied pointers.\n  //   c. The \"i\"th argument has a suitable type for holding the\n  //      string captured as the \"i\"th sub-pattern.  If you pass in\n  //      NULL for the \"i\"th argument, or pass fewer arguments than\n  //      number of sub-patterns, the \"i\"th captured sub-pattern is\n  //      ignored.\n  fn FindAndConsume(input: StringPiece*, re: Self) {\n    return Apply(FindAndConsumeN, input, re);\n  }\n  // TODO: template <typename... A>\n  // TODO: static bool FindAndConsume(StringPiece* input, const RE2& re, A&&... a) {\n  // TODO:   return Apply(FindAndConsumeN, input, re, Arg(std::forward<A>(a))...);\n  // TODO: }\n\n  // Replace the first match of \"re\" in \"str\" with \"rewrite\".\n  // Within \"rewrite\", backslash-escaped digits (\\1 to \\9) can be\n  // used to insert text matching corresponding parenthesized group\n  // from the pattern.  \\0 in \"rewrite\" refers to the entire matching\n  // text.  E.g.,\n  //\n  //   std::string s = \"yabba dabba doo\";\n  //   CHECK(RE2::Replace(&s, \"b+\", \"d\"));\n  //\n  // will leave \"s\" containing \"yada dabba doo\"\n  //\n  // Returns true if the pattern matches and a replacement occurs,\n  // false otherwise.\n  fn Replace(str: String*, re: Self, rewrite: StringPiece) -> bool;\n\n  // Like Replace(), except replaces successive non-overlapping occurrences\n  // of the pattern in the string with the rewrite. E.g.\n  //\n  //   std::string s = \"yabba dabba doo\";\n  //   CHECK(RE2::GlobalReplace(&s, \"b+\", \"d\"));\n  //\n  // will leave \"s\" containing \"yada dada doo\"\n  // Replacements are not subject to re-matching.\n  //\n  // Because GlobalReplace only replaces non-overlapping matches,\n  // replacing \"ana\" within \"banana\" makes only one replacement, not two.\n  //\n  // Returns the number of replacements made.\n  fn GlobalReplace(str: String*, re: Self, rewrite: StringPiece) -> i32;\n\n  // Like Replace, except that if the pattern matches, \"rewrite\"\n  // is copied into \"out\" with substitutions.  The non-matching\n  // portions of \"text\" are ignored.\n  //\n  // Returns true iff a match occurred and the extraction happened\n  // successfully;  if no match occurs, the string is left unaffected.\n  //\n  // REQUIRES: \"text\" must not alias any part of \"*out\".\n  fn Extract(text: StringPiece,\n             re: Self,\n             rewrite: StringPiece,\n             out: String*)\n    -> bool;\n\n  // Escapes all potentially meaningful regexp characters in\n  // 'unquoted'.  The returned string, used as a regular expression,\n  // will match exactly the original string.  For example,\n  //           1.5-2.0?\n  // may become:\n  //           1\\.5\\-2\\.0\\?\n  fn QuoteMeta(unquoted: StringPiece) -> String;\n\n  // Computes range for any strings matching regexp. The min and max can in\n  // some cases be arbitrarily precise, so the caller gets to specify the\n  // maximum desired length of string returned.\n  //\n  // Assuming PossibleMatchRange(&min, &max, N) returns successfully, any\n  // string s that is an anchored match for this regexp satisfies\n  //   min <= s && s <= max.\n  //\n  // Note that PossibleMatchRange() will only consider the first copy of an\n  // infinitely repeated element (i.e., any regexp element followed by a '*' or\n  // '+' operator). Regexps with \"{N}\" constructions are not affected, as those\n  // do not compile down to infinite repetitions.\n  //\n  // Returns true on success, false on error.\n  fn PossibleMatchRange[self: Self](min: String*, max: String*, maxlen: i32);\n\n  // Generic matching interface\n\n  // Type of match.\n  enum Anchor {\n    // No anchoring\n    UNANCHORED,\n    // Anchor at start only\n    ANCHOR_START,\n    // Anchor at start and end\n    ANCHOR_BOTH\n  }\n\n  // Return the number of capturing subpatterns, or -1 if the\n  // regexp wasn't valid on construction.  The overall match ($0)\n  // does not count: if the regexp is \"(a)(b)\", returns 2.\n  fn NumberOfCapturingGroups[self: Self]() -> i32 { return self.num_captures_; }\n\n  // Return a map from names to capturing indices.\n  // The map records the index of the leftmost group\n  // with the given name.\n  // NOTE: Originally returned by reference with comment \"valid until re is deleted\".\n  fn NamedCapturingGroups[self: Self]() -> Map(String, i32);\n\n  // Return a map from capturing indices to names.\n  // The map has no entries for unnamed groups.\n  // NOTE: Originally returned by reference with comment \"valid until re is deleted\".\n  fn CapturingGroupNames[self: Self]() -> Map(i32, String);\n\n  // General matching routine.\n  // Match against text starting at offset startpos\n  // and stopping the search at offset endpos.\n  // Returns true if match found, false if not.\n  // On a successful match, fills in submatch[] (up to nsubmatch entries)\n  // with information about submatches.\n  // I.e. matching RE2(\"(foo)|(bar)baz\") on \"barbazbla\" will return true, with\n  // submatch[0] = \"barbaz\", submatch[1].data() = NULL, submatch[2] = \"bar\",\n  // submatch[3].data() = NULL, ..., up to submatch[nsubmatch-1].data() = NULL.\n  // Caveat: submatch[] may be clobbered even on match failure.\n  //\n  // Don't ask for more match information than you will use:\n  // runs much faster with nsubmatch == 1 than nsubmatch > 1, and\n  // runs even faster if nsubmatch == 0.\n  // Doesn't make sense to use nsubmatch > 1 + NumberOfCapturingGroups(),\n  // but will be handled correctly.\n  //\n  // Passing text == StringPiece(NULL, 0) will be handled like any other\n  // empty string, but note that on return, it will not be possible to tell\n  // whether submatch i matched the empty string or did not match:\n  // either way, submatch[i].data() == NULL.\n  fn Match[self: Self](text: StringPiece,\n                     startpos: i64,\n                     endpos: i64,\n                     re_anchor: Anchor,\n                     submatch: ArrayIterator(StringPiece),\n                     nsubmatch: i32)\n    -> bool;\n\n  // Check that the given rewrite string is suitable for use with this\n  // regular expression.  It checks that:\n  //   * The regular expression has enough parenthesized subexpressions\n  //     to satisfy all of the \\N tokens in rewrite\n  //   * The rewrite string doesn't have any syntax errors.  E.g.,\n  //     '\\' followed by anything other than a digit or '\\'.\n  // A true return value guarantees that Replace() and Extract() won't\n  // fail because of a bad rewrite string.\n  fn CheckRewriteString[self: Self](rewrite: StringPiece, error: String*) -> bool;\n\n  // Returns the maximum submatch needed for the rewrite to be done by\n  // Replace(). E.g. if rewrite == \"foo \\\\2,\\\\1\", returns 2.\n  fn MaxSubmatch(rewrite: StringPiece) -> i32;\n\n  // Append the \"rewrite\" string, with backslash substitutions from \"vec\",\n  // to string \"out\".\n  // Returns true on success.  This method can fail because of a malformed\n  // rewrite string.  CheckRewriteString guarantees that the rewrite will\n  // be successful.\n  fn Rewrite[self: Self](out: String*, rewrite: StringPiece,\n                       vec: ArrayIterator(StringPiece), veclen: i32)\n    -> bool;\n\n  // Constructor options\n  class Options {\n    // The options are (defaults in parentheses):\n    //\n    //   utf8             (true)  text and pattern are UTF-8; otherwise Latin-1\n    //   posix_syntax     (false) restrict regexps to POSIX egrep syntax\n    //   longest_match    (false) search for longest match, not first match\n    //   log_errors       (true)  log syntax and execution errors to ERROR\n    //   max_mem          (see below)  approx. max memory footprint of RE2\n    //   literal          (false) interpret string as literal, not regexp\n    //   never_nl         (false) never match \\n, even if it is in regexp\n    //   dot_nl           (false) dot matches everything including new line\n    //   never_capture    (false) parse all parens as non-capturing\n    //   case_sensitive   (true)  match is case-sensitive (regexp can override\n    //                              with (?i) unless in posix_syntax mode)\n    //\n    // The following options are only consulted when posix_syntax == true.\n    // When posix_syntax == false, these features are always enabled and\n    // cannot be turned off; to perform multi-line matching in that case,\n    // begin the regexp with (?m).\n    //   perl_classes     (false) allow Perl's \\d \\s \\w \\D \\S \\W\n    //   word_boundary    (false) allow Perl's \\b \\B (word boundary and not)\n    //   one_line         (false) ^ and $ only match beginning and end of text\n    //\n    // The max_mem option controls how much memory can be used\n    // to hold the compiled form of the regexp (the Prog) and\n    // its cached DFA graphs.  Code Search placed limits on the number\n    // of Prog instructions and DFA states: 10,000 for both.\n    // In RE2, those limits would translate to about 240 KB per Prog\n    // and perhaps 2.5 MB per DFA (DFA state sizes vary by regexp; RE2 does a\n    // better job of keeping them small than Code Search did).\n    // Each RE2 has two Progs (one forward, one reverse), and each Prog\n    // can have two DFAs (one first match, one longest match).\n    // That makes 4 DFAs:\n    //\n    //   forward, first-match    - used for UNANCHORED or ANCHOR_START searches\n    //                               if opt.longest_match() == false\n    //   forward, longest-match  - used for all ANCHOR_BOTH searches,\n    //                               and the other two kinds if\n    //                               opt.longest_match() == true\n    //   reverse, first-match    - never used\n    //   reverse, longest-match  - used as second phase for unanchored searches\n    //\n    // The RE2 memory budget is statically divided between the two\n    // Progs and then the DFAs: two thirds to the forward Prog\n    // and one third to the reverse Prog.  The forward Prog gives half\n    // of what it has left over to each of its DFAs.  The reverse Prog\n    // gives it all to its longest-match DFA.\n    //\n    // Once a DFA fills its budget, it flushes its cache and starts over.\n    // If this happens too often, RE2 falls back on the NFA implementation.\n\n    // For now, make the default budget something close to Code Search.\n    // TODO: How to define a class-scope constant?\n    let kDefaultMaxMem:! i32 = 8 << 20;\n\n    enum Encoding {\n      EncodingUTF8 = 1,\n      EncodingLatin1\n    }\n\n    // TODO: A `;` after this would be nicer than a `{}`.\n    impl as DefaultValue where .Value = {\n      .encoding_ = EncodingUTF8,\n      .posix_syntax_ = false,\n      .longest_match_ = false,\n      .log_errors_ = true,\n      .max_mem_ = kDefaultMaxMem,\n      .literal_ = false,\n      .never_nl_ = false,\n      .dot_nl_ = false,\n      .never_capture_ = false,\n      .case_sensitive_ = true,\n      .perl_classes_ = false,\n      .word_boundary_ = false,\n      .one_line_ = false} {}\n\n    impl CannedOptions as ImplicitAs(Self);\n\n    fn encoding[self: Self]() -> Encoding { return self.encoding_; }\n    fn set_encoding[ref self: Self](encoding: Encoding) { self.encoding_ = encoding; }\n\n    fn posix_syntax[self: Self]() -> bool { return self.posix_syntax_; }\n    fn set_posix_syntax[ref self: Self](b: bool) { self.posix_syntax_ = b; }\n\n    fn longest_match[self: Self]() -> bool { return self.longest_match_; }\n    fn set_longest_match[ref self: Self](b: bool) { self.longest_match_ = b; }\n\n    fn log_errors[self: Self]() -> bool { return self.log_errors_; }\n    fn set_log_errors[ref self: Self](b: bool) { self.log_errors_ = b; }\n\n    fn max_mem[self: Self]() -> i64 { return self.max_mem_; }\n    fn set_max_mem[ref self: Self](m: i64) { self.max_mem_ = m; }\n\n    fn literal[self: Self]() -> bool { return self.literal_; }\n    fn set_literal[ref self: Self](b: bool) { self.literal_ = b; }\n\n    fn never_nl[self: Self]() -> bool { return self.never_nl_; }\n    fn set_never_nl[ref self: Self](b: bool) { self.never_nl_ = b; }\n\n    fn dot_nl[self: Self]() -> bool { return self.dot_nl_; }\n    fn set_dot_nl[ref self: Self](b: bool) { self.dot_nl_ = b; }\n\n    fn never_capture[self: Self]() -> bool { return self.never_capture_; }\n    fn set_never_capture[ref self: Self](b: bool) { self.never_capture_ = b; }\n\n    fn case_sensitive[self: Self]() -> bool { return self.case_sensitive_; }\n    fn set_case_sensitive[ref self: Self](b: bool) { self.case_sensitive_ = b; }\n\n    fn perl_classes[self: Self]() -> bool { return self.perl_classes_; }\n    fn set_perl_classes[ref self: Self](b: bool) { self.perl_classes_ = b; }\n\n    fn word_boundary[self: Self]() -> bool { return self.word_boundary_; }\n    fn set_word_boundary[ref self: Self](b: bool) { self.word_boundary_ = b; }\n\n    fn one_line[self: Self]() -> bool { return self.one_line_; }\n    fn set_one_line[ref self: Self](b: bool) { self.one_line_ = b; }\n\n    fn Copy[ref self: Self](src: Options) {\n      self = src;\n    }\n\n    fn ParseFlags[self: Self]() -> i32;\n\n    private var encoding_: Encoding;\n    private var posix_syntax_: bool;\n    private var longest_match_: bool;\n    private var log_errors_: bool;\n    private var max_mem_: i64;\n    private var literal_: bool;\n    private var never_nl_: bool;\n    private var dot_nl_: bool;\n    private var never_capture_: bool;\n    private var case_sensitive_: bool;\n    private var perl_classes_: bool;\n    private var word_boundary_: bool;\n    private var one_line_: bool;\n  };\n\n  // Returns the options set in the constructor.\n  fn options[self: Self]() -> Options { return self.options_; }\n\n  // Argument converters; see below.\n  // TODO: Should these be package members not class members in Carbon\n  // so you use `RE2.Hex` not `RE2.RE2.Hex`?\n  fn CRadix[T:! Parse4ary](ptr: T*) -> Self.Arg;\n  fn Hex[T:! Parse4ary](ptr: T*) -> Self.Arg;\n  fn Octal[T:! Parse4ary](ptr: T*) -> Self.Arg;\n\n  private fn Init[addr self: Self](pattern: StringPiece, options: Options);\n\n  private fn DoMatch[self: Self](text: StringPiece,\n                               re_anchor: Anchor,\n                               consumed: i64*,\n                               // TODO: Pointer to `const Arg`.\n                               args: Array(Arg*),\n                               n: i32)\n    -> bool;\n\n  fn ReverseProg[self: Self]() -> package.Prog*;\n\n  // string regular expression\n  private var pattern_: String;\n  // option flags\n  private var options_: Options;\n  // parsed regular expression\n  private var entire_regexp_: package.Regexp*;\n  // error indicator (or points to empty string)\n  // TODO: pointer to `const String`\n  private var error_: String*;\n  // error code\n  private var error_code_: ErrorCode;\n  // fragment of regexp showing error\n  private var error_arg_: String;\n  // required prefix (before suffix_regexp_)\n  private var prefix_: String;\n  // prefix_ is ASCII case-insensitive\n  private var prefix_foldcase_: bool;\n  // parsed regular expression, prefix_ removed\n  private var suffix_regexp_: package.Regexp*;\n  // compiled program for regexp\n  private var prog_: package.Prog*;\n  // number of capturing groups\n  private var num_captures_: i32;\n  // can use prog_->SearchOnePass?\n  private var is_one_pass_: bool;\n\n  // TODO: Rest of the member variables are mutable.\n\n  // Reverse Prog for DFA execution only\n  private var rprog_: package.Prog*;\n  // Map from capture names to indices\n  // TODO: pointer to const map\n  private var named_groups_: Map(String, i32)*;\n  // Map from capture indices to names\n  // TODO: pointer to const map\n  private var group_names_: Map(i32, String)*;\n\n  private var rprog_once_: Cpp.std.once_flag;\n  private var named_groups_once_: Cpp.std.once_flag;\n  private var group_names_once_: Cpp.std.once_flag;\n};\n\n/***** Implementation details *****/\n\nprivate interface Parse3ary {\n  fn Parse(str: StringView, n: i64, dest: Self) -> bool;\n}\nimpl void as Parse3ary;\nimpl String as Parse3ary;\nimpl StringPiece as Parse3ary;\nimpl Char as Parse3ary;\nimpl f32 as Parse3ary;\nimpl f64 as Parse3ary;\n\nprivate interface Parse4ary {\n  fn Parse(str: StringView, n: i64, dest: Self, radix: i32) -> bool;\n}\nimpl i16 as Parse4ary;\nimpl u16 as Parse4ary;\nimpl i32 as Parse4ary;\nimpl u32 as Parse4ary;\nimpl i64 as Parse4ary;\nimpl u64 as Parse4ary;\n\ninterface ParseFrom {\n  fn Parse(str: StringView, n: i64) -> bool;\n}\n\nclass RE2.Arg {\n  fn Make() -> Self { return Make(nullptr); }\n  // TODO: Can we put an irrefutable pattern here?\n  // TODO: Is 'nullptr' an irrefutable pattern of type nullptr_t (whatever we call that)?\n  fn Make(nullptr) -> Self { return Make(nullptr as NullArg*); }\n\n  interface Parseable {\n    fn Parse[ref self: Self](str: StringView, n: i64) -> bool;\n  }\n  match_first {\n    impl [T:! Parse3ary] T as Parseable {\n      fn Parse[ref self: Self](str: StringView, n: i64) -> bool {\n        return T.Parse(str, n, self);\n      }\n    }\n    impl [T:! Parse4ary] T as Parseable {\n      fn Parse[ref self: Self](str: StringView, n: i64) -> bool {\n        return T.Parse(str, n, self, 10);\n      }\n    }\n    impl [T:! ParseFrom] T as Parseable {\n      fn Parse[ref self: Self](str: StringView, n: i64) -> bool {\n        if (self == nullptr) { return true; }\n        return T.Parse(str, n, self);\n      }\n    }\n  }\n\n  private class NullArg {}\n  impl NullArg as Parseable {\n    fn Parse[ref self: Self](str: StringView, n: i64) -> bool {\n      return true;\n    }\n  }\n\n  fn Make[T:! Parseable](ptr: T*) {\n    return {.type_ = T, .arg_ = ptr};\n  }\n\n  fn Parse[self: Self](str: StringView, n: i64) -> bool {\n    return self.arg_->Parse(str, n);\n  }\n\n  // TODO: Existential types or `DynPtr(Parseable)`.\n  private let type_: Parseable;\n  private var arg_: Nullable(type_*);\n}\n\nprivate adapter ParseAsBase(T:! Parse4ary, base: i32) for T {\n  impl as Self.Arg.Parseable {\n    fn Parse[ref self: Self](str: StringView, n: i64) -> bool {\n      return T.Parse(str, n, self, base);\n    }\n  }\n}\n\nfn RE2.CRadix[T:! Parse4ary](ptr: T*) -> Self.Arg {\n  return Self.Arg.Make(ptr as ParseAsBase(T, 0)*);\n}\n\nfn RE2.Hex[T:! Parse4ary](ptr: T*) -> Self.Arg {\n  return Self.Arg.Make(ptr as ParseAsBase(T, 16)*);\n}\n\nfn RE2.Octal[T:! Parse4ary](ptr: T*) -> Self.Arg {\n  return Self.Arg.Make(ptr as ParseAsBase(T, 8)*);\n}\n\n// Helper for writing global or static RE2s safely.\n// Write\n//     static LazyRE2 re = {\".*\"};\n// and then use *re instead of writing\n//     static RE2 re(\".*\");\n// The former is more careful about multithreaded\n// situations than the latter.\n//\n// N.B. This class never deletes the RE2 object that\n// it constructs: that's a feature, so that it can be used\n// for global and function static variables.\nclass LazyRE2 {\n  class NoArg {}\n\n  alias element_type = RE2;  // support std::pointer_traits\n\n  // Permit implicit conversion from a struct.\n  // TODO: Think about how this interacts with the access check for the `As`\n  // and `ImplicitAs` conversions from structs to classes.\n  impl {.pattern_: StringPiece} as ImplicitAs(Self) {}\n  impl {.pattern_: StringPiece, .options_: RE2.CannedOptions} as ImplicitAs(Self) {}\n\n  // Pretend to be a pointer to Type (never NULL due to on-demand creation):\n  impl as Pointer where .Pointee = RE2 {\n    fn Resolve[self: Self]() -> Pointee* { return self.get(); }\n  }\n\n  // Named accessor/initializer:\n  fn get[ref self: Self]() -> RE* {\n    Cpp.std.call_once(once_, Self.Init, self);\n    return ptr_;\n  }\n\n  var pattern_: StringPiece;\n  var options_: RE2.CannedOptions;\n\n  // TODO: mutable?\n  private var ptr_: RE2*;\n  private var once_: Cpp.std.once_flag;\n\n  private fn Init(ref lazy_re2: LazyRE2) {\n    lazy_re2->ptr_ = heap.New!(RE2.Make(lazy_re2->pattern_, lazy_re2->options_));\n  }\n}\n\n// TODO: namespace hooks {\n// TODO:\n// TODO: // Most platforms support thread_local. Older versions of iOS don't support\n// TODO: // thread_local, but for the sake of brevity, we lump together all versions\n// TODO: // of Apple platforms that aren't macOS. If an iOS application really needs\n// TODO: // the context pointee someday, we can get more specific then...\n// TODO: //\n// TODO: // As per https://github.com/google/re2/issues/325, thread_local support in\n// TODO: // MinGW seems to be buggy. (FWIW, Abseil folks also avoid it.)\n// TODO: #define RE2_HAVE_THREAD_LOCAL\n// TODO: #if (defined(__APPLE__) && !(defined(TARGET_OS_OSX) && TARGET_OS_OSX)) || defined(__MINGW32__)\n// TODO: #undef RE2_HAVE_THREAD_LOCAL\n// TODO: #endif\n// TODO:\n// TODO: // A hook must not make any assumptions regarding the lifetime of the context\n// TODO: // pointee beyond the current invocation of the hook. Pointers and references\n// TODO: // obtained via the context pointee should be considered invalidated when the\n// TODO: // hook returns. Hence, any data about the context pointee (e.g. its pattern)\n// TODO: // would have to be copied in order for it to be kept for an indefinite time.\n// TODO: //\n// TODO: // A hook must not use RE2 for matching. Control flow reentering RE2::Match()\n// TODO: // could result in infinite mutual recursion. To discourage that possibility,\n// TODO: // RE2 will not maintain the context pointer correctly when used in that way.\n// TODO: #ifdef RE2_HAVE_THREAD_LOCAL\n// TODO: extern thread_local const RE2* context;\n// TODO: #endif\n// TODO:\n// TODO: struct DFAStateCacheReset {\n// TODO:   int64_t state_budget;\n// TODO:   size_t state_cache_size;\n// TODO: };\n// TODO:\n// TODO: struct DFASearchFailure {\n// TODO:   // Nothing yet...\n// TODO: };\n// TODO:\n// TODO: #define DECLARE_HOOK(type)                  \\\n// TODO:   using type##Callback = void(const type&); \\\n// TODO:   void Set##type##Hook(type##Callback* cb); \\\n// TODO:   type##Callback* Get##type##Hook();\n// TODO:\n// TODO: DECLARE_HOOK(DFAStateCacheReset)\n// TODO: DECLARE_HOOK(DFASearchFailure)\n// TODO:\n// TODO: #undef DECLARE_HOOK\n// TODO:\n// TODO: }  // namespace hooks\n"
  },
  {
    "path": "third_party/llvm/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_library\")\n\ncc_library(\n    name = \"clang_cc1\",\n    srcs = [\"clang_cc1.cpp\"],\n    hdrs = [\"clang_cc1.h\"],\n    visibility = [\"//visibility:public\"],\n    deps = [\n        \"//common:check\",\n        \"//toolchain/base:install_paths\",\n        \"@llvm-project//clang:basic\",\n        \"@llvm-project//clang:codegen\",\n        \"@llvm-project//clang:frontend\",\n        \"@llvm-project//clang:frontend_tool\",\n        \"@llvm-project//clang:serialization\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n"
  },
  {
    "path": "third_party/llvm/README.md",
    "content": "# Extracted LLVM code\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nThis directory holds code extracted from the LLVM project and used in various\nplaces in Carbon. This mostly happens when some logic isn't readily exposed in a\nlibrary-suitable API, or needs excessive customization.\n\nWe separate the baseline code and customizations here as these are really\nderived from the LLVM project. However, both Carbon and LLVM use the same\nlicense, so linking these isn't a problem. We also use the standard Carbon\nbanner at the top of these files as the license is accurate and the collection\nand arrangement of the code are part of Carbon. The code itself should be\nassumed to be derived from LLVM.\n\nWhenever possible, we should eventually refactor the upstream code until the\nlogic can be exposed and then we can depend on it rather than extracting it\nhere.\n"
  },
  {
    "path": "third_party/llvm/clang_cc1.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"third_party/llvm/clang_cc1.h\"\n\n#include <stdlib.h>\n\n#include <memory>\n#include <utility>\n\n#include \"clang/Basic/DiagnosticDriver.h\"\n#include \"clang/Basic/DiagnosticIDs.h\"\n#include \"clang/CodeGen/ObjectFilePCHContainerWriter.h\"\n#include \"clang/Frontend/CompilerInstance.h\"\n#include \"clang/Frontend/CompilerInvocation.h\"\n#include \"clang/Frontend/TextDiagnosticBuffer.h\"\n#include \"clang/Frontend/TextDiagnosticPrinter.h\"\n#include \"clang/FrontendTool/Utils.h\"\n#include \"clang/Serialization/ObjectFilePCHContainerReader.h\"\n#include \"clang/Serialization/PCHContainerOperations.h\"\n#include \"common/check.h\"\n#include \"llvm/ADT/IntrusiveRefCntPtr.h\"\n#include \"llvm/ADT/STLExtras.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/Statistic.h\"\n#include \"llvm/Support/Allocator.h\"\n#include \"llvm/Support/BuryPointer.h\"\n#include \"llvm/Support/CommandLine.h\"\n#include \"llvm/Support/Error.h\"\n#include \"llvm/Support/TimeProfiler.h\"\n#include \"llvm/Support/Timer.h\"\n#include \"llvm/Support/raw_ostream.h\"\n#include \"toolchain/base/install_paths.h\"\n\nnamespace Carbon {\n\nauto RunClangCC1(const InstallPaths& installation,\n                 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n                 llvm::SmallVectorImpl<const char*>& cc1_args,\n                 bool enable_leaking) -> int {\n  llvm::BumpPtrAllocator allocator;\n  llvm::cl::ExpansionContext expansion_context(\n      allocator, llvm::cl::TokenizeGNUCommandLine);\n  if (llvm::Error error = expansion_context.expandResponseFiles(cc1_args)) {\n    llvm::errs() << toString(std::move(error)) << '\\n';\n    return 1;\n  }\n  CARBON_CHECK(cc1_args[1] == llvm::StringRef(\"-cc1\"));\n\n  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diag_ids =\n      clang::DiagnosticIDs::create();\n\n  // Register the support for object-file-wrapped Clang modules.\n  auto pch_ops = std::make_shared<clang::PCHContainerOperations>();\n  pch_ops->registerWriter(\n      std::make_unique<clang::ObjectFilePCHContainerWriter>());\n  pch_ops->registerReader(\n      std::make_unique<clang::ObjectFilePCHContainerReader>());\n\n  // Buffer diagnostics from argument parsing so that we can output them using a\n  // well formed diagnostic object.\n  clang::DiagnosticOptions diag_opts;\n  clang::TextDiagnosticBuffer diag_buffer;\n  clang::DiagnosticsEngine diags(diag_ids, diag_opts, &diag_buffer,\n                                 /*ShouldOwnClient=*/false);\n\n  // Setup round-trip remarks for the DiagnosticsEngine used in CreateFromArgs.\n  if (llvm::find(cc1_args, llvm::StringRef(\"-Rround-trip-cc1-args\")) !=\n      cc1_args.end()) {\n    diags.setSeverity(clang::diag::remark_cc1_round_trip_generated,\n                      clang::diag::Severity::Remark, {});\n  }\n\n  auto invocation = std::make_shared<clang::CompilerInvocation>();\n  bool success = clang::CompilerInvocation::CreateFromArgs(\n      *invocation, llvm::ArrayRef(cc1_args).slice(1), diags, cc1_args[0]);\n\n  // Heap allocate the compiler instance so that if we disable freeing we can\n  // discard the pointer without destroying or deallocating it.\n  auto clang_instance = std::make_unique<clang::CompilerInstance>(\n      std::move(invocation), std::move(pch_ops));\n\n  // Override the disabling of free when we don't want to leak memory.\n  if (!enable_leaking) {\n    clang_instance->getFrontendOpts().DisableFree = false;\n    clang_instance->getCodeGenOpts().DisableFree = false;\n  }\n\n  if (!clang_instance->getFrontendOpts().TimeTracePath.empty()) {\n    llvm::timeTraceProfilerInitialize(\n        clang_instance->getFrontendOpts().TimeTraceGranularity, cc1_args[0],\n        clang_instance->getFrontendOpts().TimeTraceVerbose);\n  }\n\n  // TODO: These options should take priority over the actual compilation.\n  // However, their implementation is currently not accessible from a library.\n  // We should factor the implementation into a reusable location and then use\n  // that here.\n  CARBON_CHECK(!clang_instance->getFrontendOpts().PrintSupportedCPUs &&\n               !clang_instance->getFrontendOpts().PrintSupportedExtensions &&\n               !clang_instance->getFrontendOpts().PrintEnabledExtensions);\n\n  // Infer the builtin include path if unspecified.\n  if (clang_instance->getHeaderSearchOpts().UseBuiltinIncludes &&\n      clang_instance->getHeaderSearchOpts().ResourceDir.empty()) {\n    clang_instance->getHeaderSearchOpts().ResourceDir =\n        installation.clang_resource_path();\n  }\n\n  // Create the filesystem.\n  clang_instance->createVirtualFileSystem(std::move(fs), &diag_buffer);\n\n  // Create the actual diagnostics engine.\n  clang_instance->createDiagnostics();\n  if (!clang_instance->hasDiagnostics()) {\n    return EXIT_FAILURE;\n  }\n\n  // Now flush the buffered diagnostics into the Clang instance's diagnostic\n  // engine. If we've already hit an error, we can exit early once that's done.\n  diag_buffer.FlushDiagnostics(clang_instance->getDiagnostics());\n  if (!success) {\n    return EXIT_FAILURE;\n  }\n\n  // Execute the frontend actions.\n  {\n    llvm::TimeTraceScope time_scope(\"ExecuteCompiler\");\n    bool time_passes = clang_instance->getCodeGenOpts().TimePasses;\n    if (time_passes) {\n      clang_instance->createFrontendTimer();\n    }\n    llvm::TimeRegion timer(time_passes ? &clang_instance->getFrontendTimer()\n                                       : nullptr);\n    success = clang::ExecuteCompilerInvocation(clang_instance.get());\n  }\n\n  // If any timers were active but haven't been destroyed yet, print their\n  // results now.  This happens in -disable-free mode.\n  std::unique_ptr<llvm::raw_ostream> io_file = llvm::CreateInfoOutputFile();\n  if (clang_instance->getCodeGenOpts().TimePassesJson) {\n    *io_file << \"{\\n\";\n    llvm::TimerGroup::printAllJSONValues(*io_file, \"\");\n    *io_file << \"\\n}\\n\";\n  } else if (!clang_instance->getCodeGenOpts().TimePassesStatsFile) {\n    llvm::TimerGroup::printAll(*io_file);\n  }\n  llvm::TimerGroup::clearAll();\n\n  if (llvm::timeTraceProfilerEnabled()) {\n    // It is possible that the compiler instance doesn't own a file manager here\n    // if we're compiling a module unit, since the file manager is owned by the\n    // AST when we're compiling a module unit. So the file manager may be\n    // invalid here.\n    //\n    // It should be fine to create file manager here since the file system\n    // options are stored in the compiler invocation and we can recreate the VFS\n    // from the compiler invocation.\n    if (!clang_instance->hasFileManager()) {\n      clang_instance->createFileManager();\n    }\n\n    if (auto profiler_output = clang_instance->createOutputFile(\n            clang_instance->getFrontendOpts().TimeTracePath, /*Binary=*/false,\n            /*RemoveFileOnSignal=*/false,\n            /*useTemporary=*/false)) {\n      llvm::timeTraceProfilerWrite(*profiler_output);\n      profiler_output.reset();\n      llvm::timeTraceProfilerCleanup();\n      clang_instance->clearOutputFiles(false);\n    }\n  }\n\n  // When running with -disable-free, don't do any destruction or shutdown.\n  if (clang_instance->getFrontendOpts().DisableFree) {\n    llvm::BuryPointer(std::move(clang_instance));\n  }\n  return success ? EXIT_SUCCESS : EXIT_FAILURE;\n}\n\n}  // namespace Carbon\n"
  },
  {
    "path": "third_party/llvm/clang_cc1.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_THIRD_PARTY_LLVM_CLANG_CC1_H_\n#define CARBON_THIRD_PARTY_LLVM_CLANG_CC1_H_\n\n#include \"llvm/ADT/IntrusiveRefCntPtr.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/Support/VirtualFileSystem.h\"\n#include \"toolchain/base/install_paths.h\"\n\nnamespace Carbon {\n\n// Emulates Clang's `cc1_main` but in a way that doesn't assume it is running\n// in the main thread and can more easily fit into library calls to do\n// compiles.\n//\n// TODO: Much of the logic here should be factored out of the CC1\n// implementation in Clang's driver and into a reusable part of its libraries.\n// That should allow reducing the code here to a minimal amount.\nauto RunClangCC1(const InstallPaths& installation,\n                 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n                 llvm::SmallVectorImpl<const char*>& cc1_args,\n                 bool enable_leaking) -> int;\n\n}  // namespace Carbon\n\n#endif  // CARBON_THIRD_PARTY_LLVM_CLANG_CC1_H_\n"
  },
  {
    "path": "toolchain/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/cc_toolchains:defs.bzl\", \"cc_env\")\nload(\"run_tool.bzl\", \"run_tool\")\n\n# Support `bazel run` and create a convenience symlink for the tool in the\n# toolchain's install.\nrun_tool(\n    name = \"carbon\",\n    data = [\"//toolchain/install:install_data\"],\n    env = cc_env(),\n    tool = \"//toolchain/install:prefix/bin/carbon\",\n)\n\n# A convenience target for running the toolchain with the full prelude\n# available.\nalias(\n    name = \"toolchain\",\n    actual = \":carbon\",\n)\n"
  },
  {
    "path": "toolchain/README.md",
    "content": "# Toolchain\n\n<!--\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n-->\n\nSee [docs](docs/).\n"
  },
  {
    "path": "toolchain/autoupdate_testdata.py",
    "content": "#!/usr/bin/env python3\n\n\"\"\"Autoupdates testdata in toolchain.\"\"\"\n\n__copyright__ = \"\"\"\nPart of the Carbon Language project, under the Apache License v2.0 with LLVM\nExceptions. See /LICENSE for license information.\nSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\"\"\"\n\nimport argparse\nimport re\nimport shlex\nimport subprocess\nimport sys\nfrom pathlib import Path\n\n\ndef main() -> None:\n    bazel = str(Path(__file__).parents[1] / \"scripts\" / \"run_bazel.py\")\n    configs = []\n    # Use the most recently used build mode, or `fastbuild` if missing\n    # `bazel-bin`.\n    build_mode = \"fastbuild\"\n    workspace = subprocess.check_output(\n        [\n            bazel,\n            \"info\",\n            \"workspace\",\n            \"--ui_event_filters=stdout\",\n        ],\n        encoding=\"utf-8\",\n    ).strip()\n    bazel_bin_path = Path(workspace).joinpath(\"bazel-bin\")\n    if bazel_bin_path.exists():\n        link = str(bazel_bin_path.readlink())\n        m = re.search(r\"-(\\w+)/bin$\", link)\n        if m:\n            build_mode = m[1]\n        else:\n            exit(f\"Build mode not found in `bazel-bin` symlink: {link}\")\n\n    # Parse arguments.\n    parser = argparse.ArgumentParser(__doc__)\n    parser.add_argument(\"--non-fatal-checks\", action=\"store_true\")\n    parser.add_argument(\n        \"--print_slowest_tests\", default=0, help=\"Forwarded to file_test\"\n    )\n    parser.add_argument(\"--threads\", help=\"Forwarded to file_test\")\n    parser.add_argument(\"files\", nargs=\"*\")\n    args = parser.parse_args()\n\n    if args.non_fatal_checks:\n        if build_mode == \"optimize\":\n            exit(\n                \"`--non-fatal-checks` is incompatible with inferred \"\n                \"`-c optimize` build mode\"\n            )\n        configs.append(\"--config=non-fatal-checks\")\n\n    argv = [\n        bazel,\n        \"run\",\n        \"-c\",\n        build_mode,\n        *configs,\n        \"--experimental_convenience_symlinks=ignore\",\n        \"--ui_event_filters=-info,-stdout,-stderr,-finish\",\n        \"//toolchain/testing:file_test\",\n        \"--\",\n        \"--autoupdate\",\n        \"--print_slowest_tests\",\n        str(args.print_slowest_tests),\n    ]\n    if args.threads:\n        argv += [\"--threads\", args.threads]\n    # Support specifying tests to update, such as:\n    # ./autoupdate_testdata.py lex/**/*\n    if args.files:\n        repo_root = Path(__file__).parents[1]\n        file_tests = []\n        # Filter down to just test files.\n        for f in args.files:\n            if f.endswith(\".carbon\"):\n                path = str(Path(f).resolve().relative_to(repo_root))\n                if path.count(\"/testdata/\"):\n                    file_tests.append(path)\n        if not file_tests:\n            sys.exit(\n                \"Args do not seem to be test files; for example, \"\n                f\"{args.files[0]}\"\n            )\n        argv.append(\"--file_tests=\" + \",\".join(file_tests))\n    # Provide an empty stdin so that the driver tests that read from stdin\n    # don't block waiting for input. This matches the behavior of `bazel test`.\n    result = subprocess.run(argv)\n    if result.returncode != 0:\n        sys.exit(\n            f\"Command `{shlex.join(argv)}` failed with exit code \"\n            f\"`{result.returncode}`\"\n        )\n\n\nif __name__ == \"__main__\":\n    try:\n        main()\n    except KeyboardInterrupt:\n        sys.exit(1)\n"
  },
  {
    "path": "toolchain/base/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_binary\", \"cc_library\", \"cc_test\")\nload(\"llvm_tools.bzl\", \"LLVM_MAIN_TOOLS\", \"generate_llvm_tools_def\")\nload(\"runtimes_build_info.bzl\", \"generate_runtimes_build_info_cc_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files([\n    \"runtimes_build_vars.tpl.bzl\",\n])\n\ncc_library(\n    name = \"block_value_store\",\n    hdrs = [\"block_value_store.h\"],\n    deps = [\n        \":id_tag\",\n        \":mem_usage\",\n        \":value_store\",\n        \":yaml\",\n        \"//common:check\",\n        \"//common:hashing\",\n        \"//common:set\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"canonical_value_store\",\n    hdrs = [\"canonical_value_store.h\"],\n    deps = [\n        \":mem_usage\",\n        \":value_store\",\n        \":value_store_types\",\n        \":yaml\",\n        \"//common:hashtable_key_context\",\n        \"//common:set\",\n    ],\n)\n\ncc_test(\n    name = \"canonical_value_store_test\",\n    size = \"small\",\n    srcs = [\"canonical_value_store_test.cpp\"],\n    deps = [\n        \":canonical_value_store\",\n        \":value_ids\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"clang_invocation\",\n    srcs = [\"clang_invocation.cpp\"],\n    hdrs = [\"clang_invocation.h\"],\n    deps = [\n        \":install_paths\",\n        \"//common:check\",\n        \"//common:string_helpers\",\n        \"//toolchain/diagnostics:emitter\",\n        \"@llvm-project//clang:basic\",\n        \"@llvm-project//clang:driver\",\n        \"@llvm-project//clang:frontend\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"fixed_size_value_store\",\n    hdrs = [\"fixed_size_value_store.h\"],\n    deps = [\n        \":mem_usage\",\n        \":value_store\",\n        \":value_store_types\",\n        \"//common:check\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"for_each_macro\",\n    hdrs = [\"for_each_macro.h\"],\n    deps = [\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"id_tag\",\n    hdrs = [\"id_tag.h\"],\n    deps = [\n        \"//common:check\",\n        \"//common:ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"index_base\",\n    hdrs = [\"index_base.h\"],\n    deps = [\n        \"//common:ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\n# A library for computing install paths for the toolchain. Note that this\n# library does *not* include the data itself, as that would form a dependency\n# cycle. Each part of the toolchain should add the narrow data file groups to\n# their data dependencies, and then use this library to locate them.\ncc_library(\n    name = \"install_paths\",\n    srcs = [\"install_paths.cpp\"],\n    hdrs = [\"install_paths.h\"],\n    deps = [\n        \":llvm_tools\",\n        \"//common:check\",\n        \"//common:error\",\n        \"//common:filesystem\",\n        \"@bazel_tools//tools/cpp/runfiles\",\n        \"@llvm-project//clang:basic\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_binary(\n    name = \"test_binary\",\n    testonly = 1,\n    srcs = [\"test_binary.cpp\"],\n    data = [\"//toolchain/install:install_data\"],\n)\n\ncc_test(\n    name = \"install_paths_test\",\n    size = \"small\",\n    srcs = [\"install_paths_test.cpp\"],\n    data = [\n        \":test_binary\",\n        \"//toolchain/install:install_data\",\n    ],\n    deps = [\n        \":install_paths\",\n        \"//common:check\",\n        \"//common:error_test_helpers\",\n        \"//common:filesystem\",\n        \"//common:ostream\",\n        \"//testing/base:global_exe_path\",\n        \"//testing/base:gtest_main\",\n        \"@bazel_tools//tools/cpp/runfiles\",\n        \"@googletest//:gtest\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"install_paths_test_helpers\",\n    testonly = 1,\n    srcs = [\"install_paths_test_helpers.cpp\"],\n    hdrs = [\"install_paths_test_helpers.h\"],\n    deps = [\n        \":install_paths\",\n        \"//testing/base:global_exe_path\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"kind_switch\",\n    hdrs = [\"kind_switch.h\"],\n    deps = [\n        \":for_each_macro\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"kind_switch_test\",\n    size = \"small\",\n    srcs = [\"kind_switch_test.cpp\"],\n    deps = [\n        \":kind_switch\",\n        \"//common:raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"mem_usage\",\n    hdrs = [\"mem_usage.h\"],\n    deps = [\n        \":yaml\",\n        \"//common:map\",\n        \"//common:set\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"relational_value_store\",\n    hdrs = [\"relational_value_store.h\"],\n    deps = [\n        \":value_store\",\n        \":value_store_types\",\n        \"//common:check\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"timings\",\n    hdrs = [\"timings.h\"],\n    deps = [\n        \":yaml\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"value_ids\",\n    hdrs = [\"value_ids.h\"],\n    deps = [\n        \":index_base\",\n        \"//common:check\",\n        \"//common:ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"value_store\",\n    hdrs = [\"value_store.h\"],\n    deps = [\n        \":id_tag\",\n        \":mem_usage\",\n        \":value_store_types\",\n        \":yaml\",\n        \"//common:check\",\n        \"//common:hashtable_key_context\",\n        \"//common:ostream\",\n        \"//common:set\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"value_store_test\",\n    size = \"small\",\n    srcs = [\"value_store_test.cpp\"],\n    deps = [\n        \":value_ids\",\n        \":value_store\",\n        \"//common:raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"value_store_types\",\n    hdrs = [\"value_store_types.h\"],\n    deps = [\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"int\",\n    srcs = [\"int.cpp\"],\n    hdrs = [\"int.h\"],\n    deps = [\n        \":canonical_value_store\",\n        \":index_base\",\n        \":mem_usage\",\n        \":value_store\",\n        \":yaml\",\n        \"//common:check\",\n        \"//common:hashtable_key_context\",\n        \"//common:ostream\",\n        \"//common:set\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"int_test\",\n    size = \"small\",\n    srcs = [\"int_test.cpp\"],\n    deps = [\n        \":int\",\n        \"//common:raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"//toolchain/testing:yaml_test_helpers\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ngenerate_llvm_tools_def(\n    name = \"llvm_tools_def\",\n    out = \"llvm_tools.def\",\n)\n\nconfig_setting(\n    name = \"is_macos\",\n    constraint_values = [\"@platforms//os:macos\"],\n)\n\ncc_library(\n    name = \"llvm_tools\",\n    srcs = [\"llvm_tools.cpp\"],\n    hdrs = [\"llvm_tools.h\"],\n    linkopts = select({\n        # TODO: This should be moved upstream to LLVM's tool libraries that\n        # require it.\n        \":is_macos\": [\n            \"-framework\",\n            \"CoreFoundation\",\n        ],\n        \"//conditions:default\": [],\n    }),\n    deps = [\n        \":llvm_tools_def\",\n        \"//common:command_line\",\n        \"//common:enum_base\",\n        \"@llvm-project//llvm:Support\",\n    ] + [info.lib for info in LLVM_MAIN_TOOLS.values()],\n)\n\ngenerate_runtimes_build_info_cc_library(name = \"runtimes_build_info\")\n\ncc_library(\n    name = \"shared_value_stores\",\n    hdrs = [\"shared_value_stores.h\"],\n    deps = [\n        \":canonical_value_store\",\n        \":int\",\n        \":mem_usage\",\n        \":value_ids\",\n        \":value_store\",\n        \":yaml\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_test(\n    name = \"shared_value_stores_test\",\n    size = \"small\",\n    srcs = [\"shared_value_stores_test.cpp\"],\n    deps = [\n        \":shared_value_stores\",\n        \"//common:raw_string_ostream\",\n        \"//testing/base:gtest_main\",\n        \"//toolchain/testing:yaml_test_helpers\",\n        \"@googletest//:gtest\",\n    ],\n)\n\ncc_library(\n    name = \"yaml\",\n    hdrs = [\"yaml.h\"],\n    deps = [\n        \"//common:check\",\n        \"//common:ostream\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n"
  },
  {
    "path": "toolchain/base/block_value_store.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_BLOCK_VALUE_STORE_H_\n#define CARBON_TOOLCHAIN_BASE_BLOCK_VALUE_STORE_H_\n\n#include <type_traits>\n\n#include \"common/check.h\"\n#include \"common/set.h\"\n#include \"llvm/Support/Allocator.h\"\n#include \"toolchain/base/id_tag.h\"\n#include \"toolchain/base/mem_usage.h\"\n#include \"toolchain/base/value_store.h\"\n#include \"toolchain/base/yaml.h\"\n\nnamespace Carbon::SemIR {\n\n// Provides a block-based ValueStore, which uses slab allocation of added\n// blocks. This allows references to values to outlast vector resizes that might\n// otherwise invalidate references.\n//\n// BlockValueStore is used as-is, but there are also children that expose the\n// protected members for type-specific functionality.\ntemplate <typename IdT, typename ElementT, typename TagIdT = Untagged>\nclass BlockValueStore\n    : public Yaml::Printable<BlockValueStore<IdT, ElementT, TagIdT>> {\n public:\n  using IdType = IdT;\n  using IdTagType = IdTag<IdT, TagIdT>;\n  using ElementType = ElementT;\n  using RefType = llvm::MutableArrayRef<ElementT>;\n  using ConstRefType = llvm::ArrayRef<ElementT>;\n\n  explicit BlockValueStore(llvm::BumpPtrAllocator& allocator,\n                           IdTagType::TagIdType tag_id,\n                           int32_t initial_reserved_ids = 0)\n    requires(!IdTagIsUntagged<IdTagType>)\n      : allocator_(&allocator), values_(tag_id, initial_reserved_ids) {\n    auto empty = RefType();\n    auto empty_val = canonical_blocks_.Insert(\n        empty, [&] { return values_.Add(empty); }, KeyContext(this));\n    CARBON_CHECK(empty_val.key() == IdT::Empty);\n  }\n\n  // Adds a block with the given content, returning an ID to reference it.\n  auto Add(ConstRefType content) -> IdT {\n    if (content.empty()) {\n      return IdT::Empty;\n    }\n    return values_.Add(AllocateCopy(content));\n  }\n\n  // Returns the requested block.\n  auto Get(IdT id) const -> ConstRefType { return values_.Get(id); }\n\n  // Returns a mutable view of the requested block. This operation should be\n  // avoided where possible; we generally want blocks to be immutable once\n  // created.\n  auto GetMutable(IdT id) -> RefType { return values_.Get(id); }\n\n  // Returns a new block formed by applying `transform(elem_id)` to each element\n  // in the specified block.\n  template <typename TransformFnT>\n  auto Transform(IdT id, TransformFnT transform) -> IdT {\n    llvm::SmallVector<ElementType> block(llvm::map_range(Get(id), transform));\n    return Add(block);\n  }\n\n  // Adds a block or finds an existing canonical block with the given content,\n  // and returns an ID to reference it.\n  auto AddCanonical(ConstRefType content) -> IdT {\n    if (content.empty()) {\n      return IdT::Empty;\n    }\n    auto result = canonical_blocks_.Insert(\n        content, [&] { return Add(content); }, KeyContext(this));\n    return result.key();\n  }\n\n  // Promotes an existing block ID to a canonical block ID, or returns an\n  // existing canonical block ID if the block was already added. The specified\n  // block must not be modified after this point.\n  auto MakeCanonical(IdT id) -> IdT {\n    // Get the content first so that we don't have unnecessary translation of\n    // the `id` into the content during insertion.\n    auto result = canonical_blocks_.Insert(\n        Get(id), [id] { return id; }, KeyContext(this));\n    return result.key();\n  }\n\n  auto OutputYaml() const -> Yaml::OutputMapping {\n    return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {\n      for (auto [block_id, block] : values_.enumerate()) {\n        map.Add(PrintToString(block_id),\n                Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {\n                  for (auto [i, elem_id] : llvm::enumerate(block)) {\n                    map.Add(llvm::itostr(i), Yaml::OutputScalar(elem_id));\n                  }\n                }));\n      }\n    });\n  }\n\n  // Collects memory usage of members.\n  auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const\n      -> void {\n    mem_usage.Collect(MemUsage::ConcatLabel(label, \"values_\"), values_);\n    mem_usage.Collect(MemUsage::ConcatLabel(label, \"canonical_blocks_\"),\n                      canonical_blocks_, KeyContext(this));\n  }\n\n  auto size() const -> int { return values_.size(); }\n\n  auto GetRawIndex(IdT id) const -> int { return values_.GetRawIndex(id); }\n\n protected:\n  // Allocates a copy of the given data using our slab allocator.\n  auto AllocateCopy(ConstRefType data) -> RefType {\n    auto result = AllocateUninitialized(data.size());\n    std::uninitialized_copy(data.begin(), data.end(), result.begin());\n    return result;\n  }\n\n  // Allocates an uninitialized array using our slab allocator.\n  auto AllocateUninitialized(size_t size) -> RefType {\n    // We're not going to run a destructor, so ensure that's OK.\n    static_assert(std::is_trivially_destructible_v<ElementType>);\n\n    auto storage = static_cast<ElementType*>(\n        allocator_->Allocate(size * sizeof(ElementType), alignof(ElementType)));\n    return RefType(storage, size);\n  }\n\n  // Allow children to have more complex value handling.\n  auto values() -> ValueStore<IdT, RefType, TagIdT>& { return values_; }\n\n private:\n  class KeyContext;\n\n  llvm::BumpPtrAllocator* allocator_;\n  ValueStore<IdT, RefType, TagIdT> values_;\n  Set<IdT, /*SmallSize=*/0, KeyContext> canonical_blocks_;\n};\n\ntemplate <typename IdT, typename ElementT, typename TagIdT>\nclass BlockValueStore<IdT, ElementT, TagIdT>::KeyContext\n    : public TranslatingKeyContext<KeyContext> {\n public:\n  explicit KeyContext(const BlockValueStore* store) : store_(store) {}\n\n  auto TranslateKey(IdT id) const -> ConstRefType { return store_->Get(id); }\n\n private:\n  const BlockValueStore* store_;\n};\n\n}  // namespace Carbon::SemIR\n\n#endif  // CARBON_TOOLCHAIN_BASE_BLOCK_VALUE_STORE_H_\n"
  },
  {
    "path": "toolchain/base/canonical_value_store.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_CANONICAL_VALUE_STORE_H_\n#define CARBON_TOOLCHAIN_BASE_CANONICAL_VALUE_STORE_H_\n\n#include \"common/hashtable_key_context.h\"\n#include \"common/set.h\"\n#include \"toolchain/base/mem_usage.h\"\n#include \"toolchain/base/value_store.h\"\n#include \"toolchain/base/value_store_types.h\"\n#include \"toolchain/base/yaml.h\"\n\nnamespace Carbon {\n\n// A wrapper for accumulating immutable values with deduplication, providing IDs\n// to later retrieve the value.\n//\n// `ValueT` represents the type being stored.\n//\n// `KeyT` can optionally be different from `ValueT`, and if so is used for the\n// argument to `Lookup`. In this case, `ValueT` must provide a `GetAsKey` member\n// function that returns the corresponding key.\ntemplate <typename IdT, typename KeyT, typename TagIdT = Untagged,\n          typename ValueT = KeyT>\nclass CanonicalValueStore {\n public:\n  using IdType = IdT;\n  using IdTagType = IdTag<IdT, TagIdT>;\n  using KeyType = std::remove_cvref_t<KeyT>;\n  using ValueType = ValueStoreTypes<ValueT>::ValueType;\n  using RefType = ValueStoreTypes<ValueT>::RefType;\n  using ConstRefType = ValueStoreTypes<ValueT>::ConstRefType;\n\n  CanonicalValueStore() = default;\n  template <typename Id>\n  explicit CanonicalValueStore(Id id, int32_t initial_reserved_ids = 0)\n      : values_(id, initial_reserved_ids) {}\n\n  // Stores a canonical copy of the value and returns an ID to reference it. If\n  // the value is already in the store, returns the ID of the existing value.\n  auto Add(ValueType value) -> IdT;\n\n  // Returns the value for an ID.\n  auto Get(IdT id) const -> ConstRefType { return values_.Get(id); }\n\n  // Looks up the canonical ID for a value, or returns `None` if not in the\n  // store.\n  auto Lookup(KeyType key) const -> IdT;\n\n  // Reserves space.\n  auto Reserve(size_t size) -> void;\n\n  // These are to support printable structures, and are not guaranteed.\n  auto OutputYaml() const -> Yaml::OutputMapping {\n    return values_.OutputYaml();\n  }\n\n  auto values() const [[clang::lifetimebound]]\n  -> ValueStore<IdT, ValueType, TagIdT>::Range {\n    return values_.values();\n  }\n  auto size() const -> size_t { return values_.size(); }\n  auto enumerate() const -> auto { return values_.enumerate(); }\n\n  // Collects memory usage of the values and deduplication set.\n  auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const\n      -> void {\n    mem_usage.Collect(MemUsage::ConcatLabel(label, \"values_\"), values_);\n    auto bytes = set_.ComputeMetrics(KeyContext(&values_)).storage_bytes;\n    mem_usage.Add(MemUsage::ConcatLabel(label, \"set_\"), bytes, bytes);\n  }\n\n  auto GetRawIndex(IdT id) const -> int32_t { return values_.GetRawIndex(id); }\n\n  auto GetIdTag() const -> IdTagType { return values_.GetIdTag(); }\n\n private:\n  class KeyContext;\n\n  static auto GetAsKey(ConstRefType value) -> ConstRefType\n    requires std::same_as<KeyT, ValueT>\n  {\n    return value;\n  }\n\n  template <typename T>\n  static auto GetAsKey(T&& value) -> decltype(value.GetAsKey()) {\n    return value.GetAsKey();\n  }\n\n  ValueStore<IdT, ValueType, TagIdT> values_;\n  Set<IdT, /*SmallSize=*/0, KeyContext> set_;\n};\n\ntemplate <typename IdT, typename KeyT, typename TagIdT, typename ValueT>\nclass CanonicalValueStore<IdT, KeyT, TagIdT, ValueT>::KeyContext\n    : public TranslatingKeyContext<KeyContext> {\n public:\n  explicit KeyContext(const ValueStore<IdT, ValueType, TagIdT>* values)\n      : values_(values) {}\n\n  // Note that it is safe to return a reference here as the underlying object's\n  // lifetime is provided by the `ValueStore`.\n  auto TranslateKey(IdT id) const\n      -> decltype(GetAsKey(std::declval<ConstRefType>())) {\n    return GetAsKey(values_->Get(id));\n  }\n\n private:\n  const ValueStore<IdT, ValueType, TagIdT>* values_;\n};\n\ntemplate <typename IdT, typename KeyT, typename TagIdT, typename ValueT>\nauto CanonicalValueStore<IdT, KeyT, TagIdT, ValueT>::Add(ValueType value)\n    -> IdT {\n  auto make_key = [&] { return IdT(values_.Add(std::move(value))); };\n  return set_.Insert(GetAsKey(value), make_key, KeyContext(&values_)).key();\n}\n\ntemplate <typename IdT, typename KeyT, typename TagIdT, typename ValueT>\nauto CanonicalValueStore<IdT, KeyT, TagIdT, ValueT>::Lookup(KeyType key) const\n    -> IdT {\n  if (auto result = set_.Lookup(key, KeyContext(&values_))) {\n    return result.key();\n  }\n  return IdT::None;\n}\n\ntemplate <typename IdT, typename KeyT, typename TagIdT, typename ValueT>\nauto CanonicalValueStore<IdT, KeyT, TagIdT, ValueT>::Reserve(size_t size)\n    -> void {\n  // Compute the resulting new insert count using the size of values -- the\n  // set doesn't have a fast to compute current size.\n  if (size > values_.size()) {\n    set_.GrowForInsertCount(size - values_.size(), KeyContext(&values_));\n  }\n  values_.Reserve(size);\n}\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_CANONICAL_VALUE_STORE_H_\n"
  },
  {
    "path": "toolchain/base/canonical_value_store_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/canonical_value_store.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"llvm/ADT/APFloat.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"toolchain/base/value_ids.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing ::testing::Eq;\nusing ::testing::Not;\n\nTEST(CanonicalValueStore, Float) {\n  llvm::APFloat float1(1.0);\n  llvm::APFloat float2(2.0);\n\n  CanonicalValueStore<FloatId, llvm::APFloat> floats;\n  FloatId id1 = floats.Add(float1);\n  FloatId id2 = floats.Add(float2);\n\n  ASSERT_TRUE(id1.has_value());\n  ASSERT_TRUE(id2.has_value());\n  EXPECT_THAT(id1, Not(Eq(id2)));\n\n  EXPECT_THAT(floats.Get(id1).compare(float1), Eq(llvm::APFloatBase::cmpEqual));\n  EXPECT_THAT(floats.Get(id2).compare(float2), Eq(llvm::APFloatBase::cmpEqual));\n}\n\nTEST(CanonicalValueStore, Identifiers) {\n  std::string a = \"a\";\n  std::string b = \"b\";\n  CanonicalValueStore<IdentifierId, llvm::StringRef> identifiers;\n\n  // Make sure reserve works, we use it with identifiers.\n  identifiers.Reserve(100);\n\n  auto a_id = identifiers.Add(a);\n  auto b_id = identifiers.Add(b);\n\n  ASSERT_TRUE(a_id.has_value());\n  ASSERT_TRUE(b_id.has_value());\n  EXPECT_THAT(a_id, Not(Eq(b_id)));\n\n  EXPECT_THAT(identifiers.Get(a_id), Eq(a));\n  EXPECT_THAT(identifiers.Get(b_id), Eq(b));\n\n  EXPECT_THAT(identifiers.Lookup(a), Eq(a_id));\n  EXPECT_THAT(identifiers.Lookup(\"c\"), Eq(IdentifierId::None));\n}\n\nTEST(CanonicalValueStore, StringLiterals) {\n  std::string a = \"a\";\n  std::string b = \"b\";\n  CanonicalValueStore<StringLiteralValueId, llvm::StringRef> string_literals;\n\n  auto a_id = string_literals.Add(a);\n  auto b_id = string_literals.Add(b);\n\n  ASSERT_TRUE(a_id.has_value());\n  ASSERT_TRUE(b_id.has_value());\n  EXPECT_THAT(a_id, Not(Eq(b_id)));\n\n  EXPECT_THAT(string_literals.Get(a_id), Eq(a));\n  EXPECT_THAT(string_literals.Get(b_id), Eq(b));\n\n  EXPECT_THAT(string_literals.Lookup(a), Eq(a_id));\n  EXPECT_THAT(string_literals.Lookup(\"c\"), Eq(StringLiteralValueId::None));\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "toolchain/base/clang_invocation.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/clang_invocation.h\"\n\n#include <filesystem>\n#include <string>\n\n#include \"clang/Driver/CreateInvocationFromArgs.h\"\n#include \"clang/Frontend/CompilerInstance.h\"\n#include \"clang/Frontend/Utils.h\"\n#include \"common/string_helpers.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n\nnamespace Carbon {\n\n// The fake file name to use for the synthesized includes file.\nstatic constexpr const char IncludesFileName[] = \"<carbon Cpp imports>\";\n\nauto ClangDriverDiagnosticConsumer::HandleDiagnostic(\n    clang::DiagnosticsEngine::Level diag_level, const clang::Diagnostic& info)\n    -> void {\n  DiagnosticConsumer::HandleDiagnostic(diag_level, info);\n\n  llvm::SmallString<256> message;\n  info.FormatDiagnostic(message);\n\n  switch (diag_level) {\n    case clang::DiagnosticsEngine::Ignored:\n    case clang::DiagnosticsEngine::Note:\n    case clang::DiagnosticsEngine::Remark: {\n      // TODO: Emit notes and remarks.\n      break;\n    }\n    case clang::DiagnosticsEngine::Warning:\n    case clang::DiagnosticsEngine::Error:\n    case clang::DiagnosticsEngine::Fatal: {\n      CARBON_DIAGNOSTIC(CppInteropDriverWarning, Warning, \"{0}\", std::string);\n      CARBON_DIAGNOSTIC(CppInteropDriverError, Error, \"{0}\", std::string);\n      emitter_->Emit(diag_level == clang::DiagnosticsEngine::Warning\n                         ? CppInteropDriverWarning\n                         : CppInteropDriverError,\n                     message.str().str());\n      break;\n    }\n  }\n}\n\nauto BuildClangInvocation(Diagnostics::Consumer& consumer,\n                          llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n                          const InstallPaths& install_paths,\n                          llvm::StringRef target_str,\n                          llvm::ArrayRef<llvm::StringRef> extra_args)\n    -> std::unique_ptr<clang::CompilerInvocation> {\n  Diagnostics::ErrorTrackingConsumer error_tracker(consumer);\n  Diagnostics::NoLocEmitter emitter(&error_tracker);\n\n  ClangDriverDiagnosticConsumer diagnostics_consumer(&emitter);\n\n  llvm::SmallVector<std::string> args;\n  args.push_back(\"--start-no-unused-arguments\");\n  AppendDefaultClangArgs(install_paths, target_str, args);\n  args.push_back(\"--end-no-unused-arguments\");\n  args.append({\n      llvm::formatv(\"--target={0}\", target_str).str(),\n\n      // Add our include file name as the input file, and force it to be\n      // interpreted as C++.\n      \"-x\",\n      \"c++\",\n      IncludesFileName,\n  });\n\n  // The clang driver inconveniently wants an array of `const char*`, so convert\n  // the arguments.\n  llvm::BumpPtrAllocator alloc;\n  llvm::SmallVector<const char*> cstr_args = BuildCStrArgs(\n      install_paths.clang_path().native(), args, extra_args, alloc);\n\n  // Build a diagnostics engine. Note that we don't have any diagnostic options\n  // yet; they're produced by running the driver.\n  clang::DiagnosticOptions driver_diag_opts;\n  llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> driver_diags(\n      clang::CompilerInstance::createDiagnostics(*fs, driver_diag_opts,\n                                                 &diagnostics_consumer,\n                                                 /*ShouldOwnClient=*/false));\n\n  // Ask the driver to process the arguments and build a corresponding clang\n  // frontend invocation.\n  auto invocation =\n      clang::createInvocation(cstr_args, {.Diags = driver_diags, .VFS = fs});\n\n  // If Clang produced an error, throw away its invocation.\n  if (error_tracker.seen_error()) {\n    return nullptr;\n  }\n\n  if (invocation) {\n    // Do not emit Clang's name and version as the creator of the output file.\n    invocation->getCodeGenOpts().EmitVersionIdentMetadata = false;\n    invocation->getCodeGenOpts().DiscardValueNames = false;\n  }\n\n  return invocation;\n}\n\nauto AppendDefaultClangArgs(const InstallPaths& install_paths,\n                            llvm::StringRef target_str,\n                            llvm::SmallVectorImpl<std::string>& args) -> void {\n  args.append({\n      // Enable PIE by default, but allow it to be overridden by Clang\n      // arguments. Clang's default is configurable, but we'd like our\n      // defaults to be more stable.\n      // TODO: Decide if we want this.\n      \"-fPIE\",\n\n      // Enable function and data sections by default, and don't waste object\n      // file size on unique section names. Allow these to be overridden by\n      // Clang arguments.\n      \"-ffunction-sections\",\n      \"-fdata-sections\",\n      \"-fno-unique-section-names\",\n\n      // Override runtime library defaults.\n      //\n      // TODO: We should consider if there is a reasonable way to build Clang\n      // with its configuration macros set to establish these defaults rather\n      // than doing it with runtime flags.\n      \"-rtlib=compiler-rt\",\n      \"-unwindlib=libunwind\",\n      \"-stdlib=libc++\",\n\n      // Override the default linker to use.\n      \"-fuse-ld=lld\",\n  });\n\n  // Add target-specific flags.\n  llvm::Triple triple(target_str);\n  switch (triple.getOS()) {\n    case llvm::Triple::Darwin:\n    case llvm::Triple::MacOSX:\n      // On macOS we need to set the sysroot to a viable SDK. Currently, this\n      // hard codes the path to be the unversioned symlink. The prefix is also\n      // hard coded in Homebrew and so this seems likely to work reasonably\n      // well. Homebrew and I suspect the Xcode Clang both have this hard coded\n      // at build time, so this seems reasonably safe but we can revisit if/when\n      // needed.\n      args.push_back(\n          \"--sysroot=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk\");\n\n      // We also need to insist on a modern linker, otherwise the driver tries\n      // too old and deprecated flags. The specific number here comes from an\n      // inspection of the Clang driver source code to understand where features\n      // were enabled, and this appears to be the latest version to control\n      // driver behavior.\n      //\n      // TODO: We should replace this with use of `lld` eventually.\n      args.push_back(\"-mlinker-version=705\");\n      break;\n\n    default:\n      break;\n  }\n\n  // Append our exact header search paths for the various parts of the C++\n  // standard library headers as we don't build a single unified tree.\n  for (const std::filesystem::path& runtime_path :\n       {install_paths.libunwind_path(), install_paths.libcxx_path(),\n        install_paths.libcxxabi_path()}) {\n    args.push_back(\n        llvm::formatv(\"-stdlib++-isystem{0}\", runtime_path / \"include\").str());\n  }\n}\n\n}  // namespace Carbon\n"
  },
  {
    "path": "toolchain/base/clang_invocation.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_CLANG_INVOCATION_H_\n#define CARBON_TOOLCHAIN_BASE_CLANG_INVOCATION_H_\n\n#include <string>\n\n#include \"clang/Basic/Diagnostic.h\"\n#include \"clang/Frontend/CompilerInvocation.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/IntrusiveRefCntPtr.h\"\n#include \"llvm/Support/VirtualFileSystem.h\"\n#include \"toolchain/base/install_paths.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n\nnamespace Carbon {\n\n// Converts diagnostics from the Clang driver to Carbon diagnostics.\nclass ClangDriverDiagnosticConsumer : public clang::DiagnosticConsumer {\n public:\n  // Creates an instance with the location that triggers calling Clang.\n  // `context` must not be null.\n  explicit ClangDriverDiagnosticConsumer(Diagnostics::NoLocEmitter* emitter)\n      : emitter_(emitter) {}\n\n  // Generates a Carbon warning for each Clang warning and a Carbon error for\n  // each Clang error or fatal.\n  auto HandleDiagnostic(clang::DiagnosticsEngine::Level diag_level,\n                        const clang::Diagnostic& info) -> void override;\n\n private:\n  // Diagnostic emitter. Note that driver diagnostics don't have meaningful\n  // locations attached.\n  Diagnostics::NoLocEmitter* emitter_;\n};\n\n// Builds and returns a clang `CompilerInvocation` to use when building code for\n// interop, from a list of clang driver arguments. Emits diagnostics to\n// `consumer` if the arguments are invalid.\nauto BuildClangInvocation(Diagnostics::Consumer& consumer,\n                          llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n                          const InstallPaths& install_paths,\n                          llvm::StringRef target_str,\n                          llvm::ArrayRef<llvm::StringRef> extra_args = {})\n    -> std::unique_ptr<clang::CompilerInvocation>;\n\n// Appends the default Clang command line arguments used when building a\n// Carbon-compatible Clang invocation.\n//\n// Where possible, code should use `BuildClangInvocation` above. However, when\n// invoking Clang directly, this can be used to get the core compatible flags.\nauto AppendDefaultClangArgs(const InstallPaths& install_paths,\n                            llvm::StringRef target_str,\n                            llvm::SmallVectorImpl<std::string>& args) -> void;\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_CLANG_INVOCATION_H_\n"
  },
  {
    "path": "toolchain/base/fixed_size_value_store.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_FIXED_SIZE_VALUE_STORE_H_\n#define CARBON_TOOLCHAIN_BASE_FIXED_SIZE_VALUE_STORE_H_\n\n#include <concepts>\n#include <type_traits>\n\n#include \"common/check.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/ADT/iterator_range.h\"\n#include \"toolchain/base/mem_usage.h\"\n#include \"toolchain/base/value_store.h\"\n#include \"toolchain/base/value_store_types.h\"\n\nnamespace Carbon {\n\n// A value store with a predetermined size.\ntemplate <typename IdT, typename ValueT, typename TagIdT = Untagged>\nclass FixedSizeValueStore {\n public:\n  using IdType = IdT;\n  using IdTagType = IdTag<IdT, TagIdT>;\n  using ValueType = ValueStoreTypes<ValueT>::ValueType;\n  using RefType = ValueStoreTypes<ValueT>::RefType;\n  using ConstRefType = ValueStoreTypes<ValueT>::ConstRefType;\n\n  // Makes a ValueStore of the specified size, but without initializing values.\n  // Entries must be set before reading.\n  static auto MakeForOverwriteWithExplicitSize(size_t size,\n                                               IdTagType::TagIdType tag_id,\n                                               int32_t initial_reserved_ids = 0)\n      -> FixedSizeValueStore\n    requires(!IdTagIsUntagged<IdTagType>)\n  {\n    FixedSizeValueStore store(IdTagType(tag_id, initial_reserved_ids));\n    store.values_.resize_for_overwrite(size);\n    return store;\n  }\n\n  static auto MakeForOverwriteWithExplicitSize(size_t size)\n      -> FixedSizeValueStore\n    requires(IdTagIsUntagged<IdTagType>)\n  {\n    FixedSizeValueStore store;\n    store.values_.resize_for_overwrite(size);\n    return store;\n  }\n\n  // Makes a ValueStore of the same size as a source `ValueStoreT`, but without\n  // initializing values. Entries must be set before reading.\n  template <typename ValueStoreT>\n    requires(std::same_as<IdT, typename ValueStoreT::IdType> &&\n             !IdTagIsUntagged<typename ValueStoreT::IdTagType>)\n  static auto MakeForOverwrite(const ValueStoreT& size_source)\n      -> FixedSizeValueStore {\n    FixedSizeValueStore store(size_source.GetIdTag());\n    store.values_.resize_for_overwrite(size_source.size());\n    return store;\n  }\n\n  // Makes a ValueStore of the specified size, initialized to a default.\n  static auto MakeWithExplicitSize(size_t size, IdTagType tag,\n                                   ConstRefType default_value)\n      -> FixedSizeValueStore\n    requires(!IdTagIsUntagged<IdTagType>)\n  {\n    FixedSizeValueStore store(tag);\n    store.values_.resize(size, default_value);\n    return store;\n  }\n\n  static auto MakeWithExplicitSize(size_t size, ConstRefType default_value)\n      -> FixedSizeValueStore\n    requires(IdTagIsUntagged<IdTagType>)\n  {\n    FixedSizeValueStore store;\n    store.values_.resize(size, default_value);\n    return store;\n  }\n\n  // Makes a ValueStore of the specified size, initialized to values returned\n  // from a callback. This allows initializing non-copyable values.\n  static auto MakeWithExplicitSizeFrom(\n      size_t size, llvm::function_ref<auto()->ValueT> callable)\n      -> FixedSizeValueStore {\n    FixedSizeValueStore store;\n    store.values_.reserve(size);\n    for (auto _ : llvm::seq(size)) {\n      store.values_.push_back(callable());\n    }\n    return store;\n  }\n\n  // Makes a ValueStore of the same size as a source `ValueStoreT`. This is\n  // the safest constructor to use, since it ensures everything's initialized to\n  // a default, and verifies a matching `IdT` for the size.\n  template <typename ValueStoreT>\n    requires(std::same_as<IdT, typename ValueStoreT::IdType> &&\n             !IdTagIsUntagged<IdTagType> && !IdTagIsUntagged<ValueStoreT>)\n  explicit FixedSizeValueStore(const ValueStoreT& size_source,\n                               ConstRefType default_value)\n      : tag_(size_source.GetIdTag()) {\n    values_.resize(size_source.size(), default_value);\n  }\n\n  template <typename ValueStoreT>\n    requires(std::same_as<IdT, typename ValueStoreT::IdType> &&\n             IdTagIsUntagged<IdTagType> && IdTagIsUntagged<ValueStoreT>)\n  explicit FixedSizeValueStore(const ValueStoreT& size_source,\n                               ConstRefType default_value) {\n    values_.resize(size_source.size(), default_value);\n  }\n\n  explicit FixedSizeValueStore(IdTagType tag) : tag_(tag) {}\n\n  // Makes a ValueStore using a mapped range of `source`. The `factory_fn`\n  // receives each enumerated entry for construction of `ValueType`.\n  template <typename ValueStoreT>\n    requires(std::same_as<IdT, typename ValueStoreT::IdType> &&\n             !IdTagIsUntagged<IdTagType> && !IdTagIsUntagged<ValueStoreT>)\n  explicit FixedSizeValueStore(\n      const ValueStoreT& source,\n      llvm::function_ref<\n          auto(IdT, typename ValueStoreT::ConstRefType)->ValueType>\n          factory_fn)\n      : values_(llvm::map_range(source.enumerate(), factory_fn)),\n        tag_(GetIdTag(source)) {}\n\n  template <typename ValueStoreT>\n    requires(std::same_as<IdT, typename ValueStoreT::IdType> &&\n             IdTagIsUntagged<IdTagType> && IdTagIsUntagged<ValueStoreT>)\n  explicit FixedSizeValueStore(\n      const ValueStoreT& source,\n      llvm::function_ref<\n          auto(IdT, typename ValueStoreT::ConstRefType)->ValueType>\n          factory_fn)\n      : values_(llvm::map_range(source.enumerate(), factory_fn)) {}\n\n  // Move-only.\n  FixedSizeValueStore(FixedSizeValueStore&&) noexcept = default;\n  auto operator=(FixedSizeValueStore&&) noexcept\n      -> FixedSizeValueStore& = default;\n\n  // Sets the value for an ID.\n  auto Set(IdT id, ValueType value) -> void {\n    CARBON_DCHECK(id.index >= 0, \"{0}\", id);\n    auto index = tag_.Remove(id);\n    values_[index] = value;\n  }\n\n  // Returns a mutable value for an ID.\n  auto Get(IdT id) -> RefType {\n    CARBON_DCHECK(id.index >= 0, \"{0}\", id);\n    auto index = tag_.Remove(id);\n    return values_[index];\n  }\n\n  // Returns the value for an ID.\n  auto Get(IdT id) const -> ConstRefType {\n    CARBON_DCHECK(id.index >= 0, \"{0}\", id);\n    auto index = tag_.Remove(id);\n    return values_[index];\n  }\n\n  // Collects memory usage of the values.\n  auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const\n      -> void {\n    mem_usage.Collect(label.str(), values_);\n  }\n\n  auto size() const -> size_t { return values_.size(); }\n\n  auto values()\n      -> llvm::iterator_range<typename llvm::SmallVector<ValueT, 0>::iterator> {\n    return llvm::make_range(values_.begin(), values_.end());\n  }\n\n  auto values() const -> llvm::iterator_range<\n      typename llvm::SmallVector<ValueT, 0>::const_iterator> {\n    return llvm::make_range(values_.begin(), values_.end());\n  }\n\n private:\n  // Allow default construction for `Make` functions.\n  FixedSizeValueStore() = default;\n\n  // Storage for the `ValueT` objects, indexed by the id.\n  llvm::SmallVector<ValueT, 0> values_;\n\n  IdTagType tag_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_FIXED_SIZE_VALUE_STORE_H_\n"
  },
  {
    "path": "toolchain/base/for_each_macro.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_FOR_EACH_MACRO_H_\n#define CARBON_TOOLCHAIN_BASE_FOR_EACH_MACRO_H_\n\n/// CARBON_FOR_EACH() will apply `macro` to each argument in the variadic\n/// argument list, putting the output of `sep()` between each one.\n///\n/// The `sep` should be a function macro that returns a separator. Premade\n/// separataors are provided as CARBON_FOR_EACH_XYZ() macros.\n#define CARBON_FOR_EACH(macro, sep, ...)      \\\n  __VA_OPT__(CARBON_INTERNAL_FOR_EACH_EXPAND( \\\n      CARBON_INTERNAL_FOR_EACH(macro, sep, __VA_ARGS__)))\n\n#define CARBON_FOR_EACH_COMMA() ,\n#define CARBON_FOR_EACH_SEMI() ;\n#define CARBON_FOR_EACH_CONCAT()\n\n// Internal helpers\n\n#define CARBON_INTERNAL_FOR_EACH(macro, sep, a1, ...)                 \\\n  macro(a1) __VA_OPT__(sep()) __VA_OPT__(                             \\\n      CARBON_INTERNAL_FOR_EACH_AGAIN CARBON_INTERNAL_FOR_EACH_PARENS( \\\n          macro, sep, __VA_ARGS__))\n#define CARBON_INTERNAL_FOR_EACH_PARENS ()\n#define CARBON_INTERNAL_FOR_EACH_AGAIN() CARBON_INTERNAL_FOR_EACH\n\n#define CARBON_INTERNAL_FOR_EACH_EXPAND(...)                             \\\n  CARBON_INTERNAL_FOR_EACH_EXPAND1(                                      \\\n      CARBON_INTERNAL_FOR_EACH_EXPAND1(CARBON_INTERNAL_FOR_EACH_EXPAND1( \\\n          CARBON_INTERNAL_FOR_EACH_EXPAND1(__VA_ARGS__))))\n#define CARBON_INTERNAL_FOR_EACH_EXPAND1(...)                            \\\n  CARBON_INTERNAL_FOR_EACH_EXPAND2(                                      \\\n      CARBON_INTERNAL_FOR_EACH_EXPAND2(CARBON_INTERNAL_FOR_EACH_EXPAND2( \\\n          CARBON_INTERNAL_FOR_EACH_EXPAND2(__VA_ARGS__))))\n#define CARBON_INTERNAL_FOR_EACH_EXPAND2(...)                            \\\n  CARBON_INTERNAL_FOR_EACH_EXPAND3(                                      \\\n      CARBON_INTERNAL_FOR_EACH_EXPAND3(CARBON_INTERNAL_FOR_EACH_EXPAND3( \\\n          CARBON_INTERNAL_FOR_EACH_EXPAND3(__VA_ARGS__))))\n#define CARBON_INTERNAL_FOR_EACH_EXPAND3(...) __VA_ARGS__\n\n#endif  // CARBON_TOOLCHAIN_BASE_FOR_EACH_MACRO_H_\n"
  },
  {
    "path": "toolchain/base/id_tag.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_ID_TAG_H_\n#define CARBON_TOOLCHAIN_BASE_ID_TAG_H_\n\n#include <stdint.h>\n\n#include <limits>\n\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n#include \"llvm/Support/MathExtras.h\"\n\nnamespace Carbon {\n\n// A sentinel type to construct an IdTag without tagging.\nstruct Untagged : Printable<Untagged> {\n  auto Print(llvm::raw_ostream& out) const -> void { out << \"<untagged>\"; }\n};\n\n// A wrapper type used as the template argument to IdTag, in order to mark the\n// tag type as such.\ntemplate <typename TagIdT>\nstruct Tag {};\n\ntemplate <typename T>\nstruct GetTagIdType {\n  static_assert(false, \"IdTag with TagT that is neither Untagged nor Tag\");\n};\ntemplate <>\nstruct GetTagIdType<Untagged> {\n  using TagIdType = Untagged;\n};\ntemplate <typename TagIdT>\nstruct GetTagIdType<Tag<TagIdT>> {\n  using TagIdType = TagIdT;\n};\n\n// Tests if an `IdTag` type is untagged.\ntemplate <typename IdTagT>\nconcept IdTagIsUntagged = std::same_as<typename IdTagT::TagIdType, Untagged>;\n\n// A tagged Id. It is used to add a tag into the unused bits of the id, in order\n// to verify ids are used in the correct context. The tag type must be `Tag` or\n// `Untagged`.\ntemplate <typename IdT, typename TagT>\nstruct IdTag {\n  using IdType = IdT;\n  using TagIdType = GetTagIdType<TagT>::TagIdType;\n\n  IdTag()\n    requires(IdTagIsUntagged<IdTag>)\n  = default;\n\n  IdTag(TagIdType tag, int32_t initial_reserved_ids)\n    requires(!IdTagIsUntagged<IdTag>)\n      :  // Shift down by 1 to get out of the high bit to avoid using any\n         // negative ids, since they have special uses. Shift down by another 1\n         // to free up the second highest bit for a marker to indicate whether\n         // the index is tagged (& needs to be untagged) or not. Add one to the\n         // index so it's not zero-based, to make it a bit less likely this\n         // doesn't collide with anything else (though with the\n         // second-highest-bit-tagging this might not be needed).\n        tag_(llvm::reverseBits((((tag.index + 1) << 1) | 1) << 1)),\n        initial_reserved_ids_(initial_reserved_ids) {}\n\n  auto Apply(int32_t index) const -> IdT {\n    CARBON_DCHECK(index >= 0, \"{0}\", index);\n    if (index < initial_reserved_ids_) {\n      return IdT(index);\n    }\n    // TODO: Assert that tag_ doesn't have the second highest bit set.\n    auto tagged_index = index ^ tag_;\n    CARBON_DCHECK(tagged_index >= 0, \"{0}\", tagged_index);\n    return IdT(tagged_index);\n  }\n\n  auto Remove(IdT id) const -> int32_t {\n    CARBON_DCHECK(id.index >= 0, \"{0}\", id);\n    if (!HasTag(id.index)) {\n      CARBON_DCHECK(id.index < initial_reserved_ids_,\n                    \"This untagged index is outside the initial reserved ids \"\n                    \"and should have been tagged.\");\n      return id.index;\n    }\n    auto untagged_index = id.index ^ tag_;\n    CARBON_DCHECK(untagged_index >= initial_reserved_ids_,\n                  \"When removing tagging bits, found an index that \"\n                  \"shouldn't've been tagged in the first place.\");\n    return untagged_index;\n  }\n\n  // Gets the value unique to this IdTag instance that is added to indices in\n  // Apply, and removed in Remove.\n  auto GetContainerTag() const -> TagIdType {\n    if constexpr (IdTagIsUntagged<IdTag>) {\n      return TagIdType();\n    } else {\n      return TagIdType((llvm::reverseBits(tag_) >> 2) - 1);\n    }\n  }\n\n  // Returns whether `tagged_index` has an IdTag applied to it, from this IdTag\n  // instance or any other one.\n  static auto HasTag(int32_t tagged_index) -> bool {\n    return (llvm::reverseBits(2) & tagged_index) != 0;\n  }\n\n  struct TagAndIndex {\n    TagIdType tag;\n    int32_t index;\n  };\n\n  static auto DecomposeWithBestEffort(IdT id) -> TagAndIndex {\n    if constexpr (IdTagIsUntagged<IdTag>) {\n      return {TagIdType(), id.index};\n    } else {\n      if (!id.has_value()) {\n        return {TagIdType::None, id.index};\n      }\n      if (!HasTag(id.index)) {\n        return {TagIdType::None, id.index};\n      }\n      int length = 0;\n      int location = 0;\n      for (int i = 0; i != 32; ++i) {\n        int current_run = 0;\n        int location_of_current_run = i;\n        while (i != 32 && (id.index & (1 << i)) == 0) {\n          ++current_run;\n          ++i;\n        }\n        if (current_run != 0) {\n          --i;\n        }\n        if (current_run > length) {\n          length = current_run;\n          location = location_of_current_run;\n        }\n      }\n      if (length < 8) {\n        return {TagIdType::None, id.index};\n      }\n      auto index_mask = llvm::maskTrailingOnes<uint32_t>(location);\n      auto tag = (llvm::reverseBits(id.index & ~index_mask) >> 2) - 1;\n      auto index = id.index & index_mask;\n      return {.tag = TagIdType(static_cast<int32_t>(tag)),\n              .index = static_cast<int32_t>(index)};\n    }\n  }\n\n  // Converts an IdTag to be used for a different ID type. This is only valid\n  // when the id indices are interchangeable, as they will have the same tag and\n  // the same reserved ids.\n  template <typename OtherIdT>\n    requires(!IdTagIsUntagged<IdTag>)\n  auto ToEquivalentIdType() -> IdTag<OtherIdT, Tag<TagIdType>> {\n    return {GetContainerTag(), initial_reserved_ids_};\n  }\n\n private:\n  int32_t tag_ = 0;\n  int32_t initial_reserved_ids_ = std::numeric_limits<int32_t>::max();\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_ID_TAG_H_\n"
  },
  {
    "path": "toolchain/base/index_base.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_\n#define CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_\n\n#include <compare>\n#include <concepts>\n#include <iterator>\n#include <type_traits>\n\n#include \"common/ostream.h\"\n#include \"llvm/ADT/iterator.h\"\n#include \"llvm/Support/Format.h\"\n\nnamespace Carbon {\n\ntemplate <typename DataType>\nclass DataIterator;\n\n// Non-templated portions of `IdBase`.\nstruct AnyIdBase {\n  static constexpr int32_t NoneIndex = -1;\n\n  AnyIdBase() = delete;\n  constexpr explicit AnyIdBase(int index) : index(index) {}\n\n  constexpr auto has_value() const -> bool { return index != NoneIndex; }\n\n  int32_t index;\n};\n\n// A lightweight handle to an item identified by an opaque ID.\n//\n// This class is intended to be derived from by classes representing a specific\n// kind of ID, whose meaning as an integer is an implementation detail of the\n// type that vends the IDs. Typically this will be a vector index.\n//\n// Classes derived from IdBase are designed to be passed by value, not\n// reference or pointer. They are also designed to be small and efficient to\n// store in data structures.\n//\n// This uses CRTP for the `Print` function. Children should have:\n//   static constexpr llvm::StringLiteral Label = \"my_label\";\n// Children can also define their own `Print` function, removing the dependency\n// on `Label`.\ntemplate <typename IdT>\nstruct IdBase : public AnyIdBase, public Printable<IdT> {\n  using AnyIdBase::AnyIdBase;\n\n  // Provide a standard `None` mapping to `NoneIndex`.\n  //\n  // This uses a `&` to trigger slightly different instantiation behaviors in\n  // Clang. For context on why this is needed, see http://wg21.link/CWG2800.\n  // NOLINTNEXTLINE(readability-identifier-naming)\n  static const IdT& None;\n\n  auto Print(llvm::raw_ostream& out) const -> void {\n    out << IdT::Label;\n    if (has_value()) {\n      out << llvm::format_hex_no_prefix(index, 0, /*Upper=*/true);\n    } else {\n      out << \"<none>\";\n    }\n  }\n\n  // Support simple equality comparison for ID types.\n  friend constexpr auto operator==(IdBase<IdT> lhs, IdBase<IdT> rhs) -> bool {\n    return lhs.index == rhs.index;\n  }\n};\n\ntemplate <typename IdT>\nconstexpr const IdT& IdBase<IdT>::None = IdT(NoneIndex);\n\n// A lightweight handle to an item that behaves like an index.\n//\n// Unlike IdBase, classes derived from IndexBase are not completely opaque, and\n// provide at least an ordering between indexes that has meaning to an API\n// user. Additional semantics may be specified by the derived class.\ntemplate <typename IdT>\nstruct IndexBase : public IdBase<IdT> {\n  using IdBase<IdT>::IdBase;\n\n  // Support relational comparisons for index types.\n  friend auto operator<=>(IndexBase<IdT> lhs, IndexBase<IdT> rhs)\n      -> std::strong_ordering {\n    return lhs.index <=> rhs.index;\n  }\n\n  // Print indexed ids in decimal, since they won't have tagging (because, as\n  // the class comment explains, these ids are not entirely opaque).\n  auto Print(llvm::raw_ostream& out) const -> void {\n    out << IdT::Label;\n    if (this->has_value()) {\n      out << this->index;\n    } else {\n      out << \"<none>\";\n    }\n  }\n};\n\n// A random-access iterator for arrays using IndexBase-derived types.\ntemplate <typename IndexT>\nclass IndexIterator\n    : public llvm::iterator_facade_base<IndexIterator<IndexT>,\n                                        std::random_access_iterator_tag,\n                                        const IndexT, int>,\n      public Printable<IndexIterator<IndexT>> {\n public:\n  IndexIterator() = delete;\n\n  explicit IndexIterator(IndexT index) : index_(index) {}\n\n  friend auto operator==(const IndexIterator& lhs, const IndexIterator& rhs)\n      -> bool {\n    return lhs.index_ == rhs.index_;\n  }\n  friend auto operator<=>(const IndexIterator& lhs, const IndexIterator& rhs)\n      -> std::strong_ordering {\n    return lhs.index_ <=> rhs.index_;\n  }\n\n  auto operator*() const -> const IndexT& { return index_; }\n\n  using llvm::iterator_facade_base<IndexIterator,\n                                   std::random_access_iterator_tag,\n                                   const IndexT, int>::operator-;\n  friend auto operator-(const IndexIterator& lhs, const IndexIterator& rhs)\n      -> int {\n    return lhs.index_.index - rhs.index_.index;\n  }\n\n  auto operator+=(int n) -> IndexIterator& {\n    index_.index += n;\n    return *this;\n  }\n  auto operator-=(int n) -> IndexIterator& {\n    index_.index -= n;\n    return *this;\n  }\n\n  // Prints the raw index.\n  auto Print(llvm::raw_ostream& output) const -> void {\n    output << index_.index;\n  }\n\n private:\n  IndexT index_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_\n"
  },
  {
    "path": "toolchain/base/install_paths.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/install_paths.h\"\n\n#include <filesystem>\n#include <memory>\n#include <string>\n\n#include \"clang/Basic/Version.h\"\n#include \"common/check.h\"\n#include \"common/filesystem.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/FileSystem.h\"\n#include \"llvm/Support/Path.h\"\n#include \"llvm/Support/VirtualFileSystem.h\"\n#include \"tools/cpp/runfiles/runfiles.h\"\n\nnamespace Carbon {\n\n// The location within our Bazel output tree of the install root.\nstatic constexpr llvm::StringLiteral BazelRoot =\n    \"carbon/toolchain/install/prefix/lib/carbon/\";\n\n// Path within an install root for our marker of a valid install.\nstatic constexpr llvm::StringLiteral MarkerPath = \"carbon_install.txt\";\n\nauto InstallPaths::MakeExeRelative(llvm::StringRef exe_path) -> InstallPaths {\n  InstallPaths paths;\n\n  // Double check the exe was present.\n  auto exe_access_result = Filesystem::Cwd().Access(exe_path.str());\n  if (!exe_access_result.ok()) {\n    paths.SetError(llvm::Twine(\"Failed to test for access executable: \") +\n                   exe_access_result.error().ToString());\n    return paths;\n  } else if (!*exe_access_result) {\n    paths.SetError(llvm::Twine(\"Unable to access executable: \") + exe_path);\n    return paths;\n  }\n\n  return MakeFromFile(exe_path.str());\n}\n\nauto InstallPaths::MakeForBazelRunfiles(llvm::StringRef exe_path)\n    -> InstallPaths {\n  using bazel::tools::cpp::runfiles::Runfiles;\n  std::string runtimes_error;\n  std::unique_ptr<Runfiles> runfiles(\n      Runfiles::Create(exe_path.str(), &runtimes_error));\n  CARBON_CHECK(runfiles != nullptr, \"Failed to find runtimes tree: {0}\",\n               runtimes_error);\n\n  std::string relative_marker_path = (BazelRoot.str() + MarkerPath).str();\n  std::filesystem::path runtimes_marker_path =\n      runfiles->Rlocation(relative_marker_path);\n\n  // Directly use the marker file's path.\n  return MakeFromFile(std::move(runtimes_marker_path));\n}\n\nauto InstallPaths::Make(llvm::StringRef install_root) -> InstallPaths {\n  InstallPaths paths(install_root.str());\n  auto open_result = Filesystem::Cwd().OpenDir(paths.root_);\n  if (!open_result.ok()) {\n    paths.SetError(open_result.error().ToString());\n  } else {\n    paths.root_dir_ = *std::move(open_result);\n    paths.CheckMarkerFile();\n  }\n  return paths;\n}\n\nauto InstallPaths::ReadPreludeManifest() const\n    -> ErrorOr<llvm::SmallVector<std::string>> {\n  return ReadManifest(core_package(), \"prelude_manifest.txt\");\n}\n\nauto InstallPaths::ReadClangHeadersManifest() const\n    -> ErrorOr<llvm::SmallVector<std::string>> {\n  // TODO: This is the only place where we read from outside of the install\n  // root. Consider whether this manifest should be within the install or\n  // consider moving the code to access it to be separate and specific to the\n  // infrastructure needing it.\n  return ReadManifest(root_ / \"../../..\", \"clang_headers_manifest.txt\");\n}\n\nauto InstallPaths::ReadManifest(std::filesystem::path manifest_path,\n                                std::filesystem::path manifest_file) const\n    -> ErrorOr<llvm::SmallVector<std::string>> {\n  // This is structured to avoid a vector copy on success.\n  ErrorOr<llvm::SmallVector<std::string>> result =\n      llvm::SmallVector<std::string>();\n\n  // TODO: It would be nice to adjust the manifests to be within the install\n  // root and use that open directory to access the manifest. Also to update\n  // callers to be able to use the relative paths via an open directory rather\n  // than having to form absolute paths for all the entries.\n  auto read_result =\n      Filesystem::Cwd().ReadFileToString(manifest_path / manifest_file);\n  if (!read_result.ok()) {\n    result = ErrorBuilder()\n             << \"Loading manifest `\" << (manifest_path / manifest_file)\n             << \"`: \" << read_result.error();\n    return result;\n  }\n\n  // The manifest should have one file per line.\n  llvm::StringRef buffer = *read_result;\n  while (true) {\n    auto [token, remainder] = llvm::getToken(buffer, \"\\n\");\n    if (token.empty()) {\n      break;\n    }\n    result->push_back((manifest_path / std::string_view(token)).native());\n    buffer = remainder;\n  }\n\n  if (result->empty()) {\n    result = ErrorBuilder()\n             << \"Manifest `\" << (manifest_path / manifest_file) << \"` is empty\";\n  }\n  return result;\n}\n\nauto InstallPaths::MakeFromFile(std::filesystem::path file_path)\n    -> InstallPaths {\n  // TODO: Add any custom logic needed to detect the correct install root on\n  // Windows once we have support for that platform.\n  //\n  // We assume the provided path is either the marker file itself or the busybox\n  // executable that is adjacent to the marker file. That means the root is just\n  // the directory of this path.\n  InstallPaths paths(std::move(file_path).remove_filename());\n\n  auto open_result = Filesystem::Cwd().OpenDir(paths.root_);\n  if (!open_result.ok()) {\n    paths.SetError(open_result.error().ToString());\n    return paths;\n  }\n\n  paths.root_dir_ = *std::move(open_result);\n  paths.CheckMarkerFile();\n  return paths;\n}\n\nauto InstallPaths::SetError(llvm::Twine message) -> void {\n  // Use an empty root on error as that should use the working directory which\n  // is the least likely problematic.\n  root_ = \"\";\n  root_dir_ = Filesystem::Dir();\n  error_ = {message.str()};\n}\n\nauto InstallPaths::CheckMarkerFile() -> void {\n  auto access_result = root_dir_.Access(MarkerPath.str());\n  if (!access_result.ok()) {\n    SetError(access_result.error().ToString());\n    return;\n  }\n  if (!*access_result) {\n    SetError(llvm::Twine(\"No install marker at path: \") +\n             (root_ / std::string_view(MarkerPath)).native());\n    return;\n  }\n\n  // Success!\n}\n\nauto InstallPaths::core_package() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return root_ / \"core\";\n}\n\nauto InstallPaths::llvm_install_bin() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return root_ / \"llvm/bin\";\n}\n\nauto InstallPaths::clang_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return llvm_install_bin() / \"clang\";\n}\n\nauto InstallPaths::lld_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return llvm_install_bin() / \"lld\";\n}\n\nauto InstallPaths::ld_lld_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return llvm_install_bin() / \"ld.lld\";\n}\n\nauto InstallPaths::ld64_lld_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return llvm_install_bin() / \"ld64.lld\";\n}\n\nauto InstallPaths::llvm_tool_path(LLVMTool tool) const\n    -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return llvm_install_bin() / std::string_view(tool.bin_name());\n}\n\nauto InstallPaths::clang_resource_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return root_ / \"llvm/lib/clang/\" CLANG_VERSION_MAJOR_STRING;\n}\n\nauto InstallPaths::runtimes_root() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return root_ / \"runtimes\";\n}\n\nauto InstallPaths::libunwind_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return runtimes_root() / \"libunwind\";\n}\n\nauto InstallPaths::libcxx_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return runtimes_root() / \"libcxx\";\n}\n\nauto InstallPaths::libcxxabi_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return runtimes_root() / \"libcxxabi\";\n}\n\nauto InstallPaths::libc_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return runtimes_root() / \"libc\";\n}\n\nauto InstallPaths::digest_path() const -> std::filesystem::path {\n  // TODO: Adjust this to work equally well on Windows.\n  return root_ / \"install_digest.txt\";\n}\n\n}  // namespace Carbon\n"
  },
  {
    "path": "toolchain/base/install_paths.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_INSTALL_PATHS_H_\n#define CARBON_TOOLCHAIN_BASE_INSTALL_PATHS_H_\n\n#include <filesystem>\n\n#include \"common/error.h\"\n#include \"common/filesystem.h\"\n#include \"llvm/ADT/SmallString.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/ADT/Twine.h\"\n#include \"toolchain/base/llvm_tools.h\"\n\nnamespace Carbon {\n\n// Locates the toolchain installation and provides paths to various components.\n//\n// The Carbon toolchain expects to be installed into a tree rooted at `root_`.\n// This root contains the marker file and the busy box binary.\n//\n// In a Unix-like filesystem environment, the root is typically located as\n// `<some prefix>/lib/carbon`, with symlinks in the other parts of the FHS-based\n// layout back to entries below this tree. However, this class and the toolchain\n// itself should only directly use things below the installation root to support\n// non-FHS usage.\n//\n// When locating an install, we verify it with `CheckMarkerFile`. When errors\n// occur, `SetError` makes `error()` available for diagnostics and clears the\n// install root, leaving things minimally functional but with the installation\n// root of the current working directory.\n//\n// The factory methods locate the install root based on their use-case:\n//\n//   - `MakeExeRelative` for command line tools in an install.\n//   - `MakeForBazelRunfiles` for locating through Bazel's runfile tree.\n//   - `Make` for an explicit path, for example in tests.\n//\n// An instance of this class provides methods that query for specific paths\n// within the install. Note that we want to abstract away any platform\n// differences in the installation layout. When a specific part of the install\n// is needed, a dedicated accessor should be added that computes the path for\n// that component.\n//\n// TODO: Need to check the installation structure of LLVM on Windows and figure\n// out what Carbon's should be within a Windows prefix and how much of the\n// structure we can share with the Unix-y layout of the prefix.\n//\n// TODO: InstallPaths is typically called from places using a VFS (both tests\n// and the Driver), but does not use a VFS itself. It currently only supports\n// using the real filesystem, but should probably support a VFS.\nclass InstallPaths {\n public:\n  // Provide the current executable's path to detect the correct installation\n  // root. This assumes the toolchain to be in its installed layout.\n  static auto MakeExeRelative(llvm::StringRef exe_path) -> InstallPaths;\n\n  // Provide the current executable's path, and use that to detect a Bazel or\n  // Bazel-compatible runfiles install root. This should only be used where it\n  // is reasonable to rely on this rather than a fixed install location such as\n  // for internal development purposes or other Bazel users of the Carbon\n  // library.\n  //\n  // This method of construction also ensures the result is valid. If detection\n  // fails for any reason, it will `CARBON_CHECK` fail with the error message.\n  static auto MakeForBazelRunfiles(llvm::StringRef exe_path) -> InstallPaths;\n\n  // Provide an explicit install paths root. This is useful for testing or for\n  // using Carbon in an environment with an unusual path to the installed files.\n  static auto Make(llvm::StringRef install_root) -> InstallPaths;\n\n  // Returns the contents of the prelude manifest file. This is the list of\n  // files that define the prelude, and will always be non-empty on success.\n  auto ReadPreludeManifest() const -> ErrorOr<llvm::SmallVector<std::string>>;\n\n  // Returns the contents of the clang builtin headers manifest file. This is\n  // the list of header files that are installed as part of the clang compiler,\n  // and will always be non-empty on success.\n  auto ReadClangHeadersManifest() const\n      -> ErrorOr<llvm::SmallVector<std::string>>;\n\n  // Check for an error detecting the install paths correctly.\n  //\n  // A nullopt return means no errors encountered and the paths should work\n  // correctly.\n  //\n  // A string return means there was an error, and details of the error are\n  // in the `StringRef` for inclusion in any user report.\n  [[nodiscard]] auto error() const -> std::optional<llvm::StringRef> {\n    return error_;\n  }\n\n  // The path to the root of this installation.\n  auto root() const -> std::filesystem::path { return root_; }\n\n  // The directory containing the `Core` package. Computed on demand.\n  auto core_package() const -> std::filesystem::path;\n\n  // The directory containing LLVM install binaries. Computed on demand.\n  auto llvm_install_bin() const -> std::filesystem::path;\n\n  // The path to `clang`.\n  auto clang_path() const -> std::filesystem::path;\n\n  // The path to `lld' and various aliases of `lld`.\n  auto lld_path() const -> std::filesystem::path;\n  auto ld_lld_path() const -> std::filesystem::path;\n  auto ld64_lld_path() const -> std::filesystem::path;\n\n  // The path to any of the LLVM tools.\n  auto llvm_tool_path(LLVMTool tool) const -> std::filesystem::path;\n\n  // The path to the Clang resources.\n  auto clang_resource_path() const -> std::filesystem::path;\n\n  // The path to the root of the runtimes.\n  auto runtimes_root() const -> std::filesystem::path;\n\n  // The path to `libunwind` runtime.\n  auto libunwind_path() const -> std::filesystem::path;\n\n  // The path to `libunwind` runtime.\n  auto libcxx_path() const -> std::filesystem::path;\n\n  // The path to `libunwind` runtime.\n  auto libcxxabi_path() const -> std::filesystem::path;\n\n  // The path to the LLVM `libc` runtime.\n  auto libc_path() const -> std::filesystem::path;\n\n  // The installation digest path.\n  //\n  // This file contains a digest of the installation.\n  auto digest_path() const -> std::filesystem::path;\n\n private:\n  friend class InstallPathsTestPeer;\n\n  InstallPaths() { SetError(\"No root provided!\"); }\n  explicit InstallPaths(std::filesystem::path root) : root_(std::move(root)) {}\n\n  static auto MakeFromFile(std::filesystem::path file) -> InstallPaths;\n\n  // Set an error message on the install paths and reset the `root_` to empty,\n  // which should use the current working directory.\n  auto SetError(llvm::Twine message) -> void;\n\n  // Check that the install paths have a marker file at\n  // `root()/lib/carbon/carbon_install.txt\". If not, calls `SetError` with the\n  // relevant error message.\n  auto CheckMarkerFile() -> void;\n\n  // Read a manifest file.\n  auto ReadManifest(std::filesystem::path manifest_path,\n                    std::filesystem::path manifest_file) const\n      -> ErrorOr<llvm::SmallVector<std::string>>;\n\n  // The computed installation root. In the event of an error, this will be the\n  // empty string.\n  //\n  // When run from Bazel (for example, in unit tests or development binaries)\n  // this will look like:\n  // `bazel-bin/some/bazel/target.runfiles/_main/toolchain/install/prefix/lib/carbon`\n  //\n  // When installed, it's expected to be similar to the CMake install prefix,\n  // followed by `lib/carbon`:\n  //\n  // - `/usr/lib/carbon` or `/usr/local/lib/carbon` on Linux and most BSDs.\n  // - `/opt/homebrew/lib/carbon` or similar on macOS with Homebrew.\n  // - TODO: Figure out if this is `C:/Program Files/Carbon` or something else\n  //   on Windows.\n  //\n  // See https://cmake.org/cmake/help/latest/variable/CMAKE_INSTALL_PREFIX.html\n  // for more details. While we don't build the toolchain with CMake, we expect\n  // our installation to behave in a similar and compatible way.\n  //\n  // The hierarchy of files beneath the install root can be found in the\n  // BUILD's `install_dirs` entry for `lib/carbon`.\n  std::filesystem::path root_;\n\n  // The opened root directory.\n  Filesystem::Dir root_dir_;\n\n  std::optional<std::string> error_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_INSTALL_PATHS_H_\n"
  },
  {
    "path": "toolchain/base/install_paths_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/install_paths.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <filesystem>\n#include <memory>\n#include <string>\n\n#include \"common/check.h\"\n#include \"common/error_test_helpers.h\"\n#include \"common/filesystem.h\"\n#include \"llvm/ADT/SmallString.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n#include \"testing/base/global_exe_path.h\"\n#include \"tools/cpp/runfiles/runfiles.h\"\n\nnamespace Carbon {\n\nclass InstallPathsTestPeer {\n public:\n  static auto GetRoot(const InstallPaths& paths) -> std::filesystem::path {\n    return paths.root_;\n  }\n};\n\nnamespace {\n\nusing ::bazel::tools::cpp::runfiles::Runfiles;\nusing ::testing::_;\nusing ::testing::EndsWith;\nusing ::testing::Eq;\nusing ::testing::HasSubstr;\nusing Testing::IsSuccess;\nusing ::testing::Optional;\nusing ::testing::StartsWith;\n\nclass InstallPathsTest : public ::testing::Test {\n public:\n  InstallPathsTest() {\n    std::string error;\n    test_runfiles_.reset(Runfiles::Create(Testing::GetExePath().str(), &error));\n    CARBON_CHECK(test_runfiles_ != nullptr, \"{0}\", error);\n  }\n\n  // Test the install paths found with the given `exe_path`. Will check that\n  // the detected install root path has the expected location relative to the\n  // FHS layout, and then check that the path accessors point to the right kind\n  // of file or directory.\n  auto TestInstallPaths(const InstallPaths& paths) -> void {\n    std::filesystem::path root_path = InstallPathsTestPeer::GetRoot(paths);\n\n    SCOPED_TRACE(llvm::formatv(\"Install root: '{0}'\", root_path));\n\n    // Open the root directory.\n    auto root_result = Filesystem::Cwd().OpenDir(root_path);\n    ASSERT_THAT(root_result, IsSuccess(_));\n    Filesystem::Dir root = *std::move(root_result);\n\n    // Check that the root is located in the expected part of the FHS layout.\n    // TODO: Adjust this to work equally well on Windows.\n    EXPECT_THAT(root_path.native(), EndsWith(\"lib/carbon/\"));\n    EXPECT_THAT(\n        root.Access(\"../../bin/carbon\", Filesystem::AccessCheckFlags::Execute),\n        IsSuccess(Eq(true)))\n        << \"path: \" << (root_path / \"../../bin/carbon\");\n\n    std::filesystem::path core_package_path = paths.core_package();\n    ASSERT_THAT(core_package_path, StartsWith(root_path));\n    EXPECT_THAT(Filesystem::Cwd().Access(core_package_path / \"prelude.carbon\"),\n                IsSuccess(Eq(true)))\n        << \"path: \" << core_package_path;\n\n    std::filesystem::path llvm_bin_path = paths.llvm_install_bin();\n    ASSERT_THAT(llvm_bin_path, StartsWith(root_path));\n    auto open_result = Filesystem::Cwd().OpenDir(llvm_bin_path);\n    ASSERT_THAT(open_result, IsSuccess(_));\n    Filesystem::Dir llvm_bin = *std::move(open_result);\n\n    for (std::filesystem::path bin_name : {\"ld.lld\", \"ld64.lld\"}) {\n      EXPECT_THAT(\n          llvm_bin.Access(bin_name, Filesystem::AccessCheckFlags::Execute),\n          IsSuccess(Eq(true)))\n          << \"path: \" << (llvm_bin_path / bin_name);\n    }\n  }\n\n  std::unique_ptr<Runfiles> test_runfiles_;\n};\n\nTEST_F(InstallPathsTest, RootBusybox) {\n  std::string installed_busybox_path = test_runfiles_->Rlocation(\n      \"carbon/toolchain/install/prefix/lib/carbon/carbon-busybox\");\n\n  auto paths = InstallPaths::MakeExeRelative(installed_busybox_path);\n  ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();\n  TestInstallPaths(paths);\n}\n\nTEST_F(InstallPathsTest, RootExplicit) {\n  std::string marker_path = test_runfiles_->Rlocation(\n      \"carbon/toolchain/install/prefix/lib/carbon/carbon_install.txt\");\n\n  llvm::StringRef root_path = marker_path;\n  CARBON_CHECK(root_path.consume_back(\"carbon_install.txt\"),\n               \"Unexpected suffix of the marker path: {0}\", marker_path);\n\n  auto paths = InstallPaths::Make(root_path);\n  ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();\n  TestInstallPaths(paths);\n}\n\nTEST_F(InstallPathsTest, TestRunfiles) {\n  auto paths = InstallPaths::MakeForBazelRunfiles(Testing::GetExePath());\n  ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();\n  TestInstallPaths(paths);\n}\n\nTEST_F(InstallPathsTest, BinaryRunfiles) {\n  std::filesystem::path test_binary_path =\n      test_runfiles_->Rlocation(\"carbon/toolchain/base/test_binary\");\n  ASSERT_THAT(Filesystem::Cwd().Access(test_binary_path,\n                                       Filesystem::AccessCheckFlags::Execute),\n              IsSuccess(Eq(true)))\n      << \"path: \" << test_binary_path;\n\n  auto paths = InstallPaths::MakeForBazelRunfiles(test_binary_path.native());\n  ASSERT_THAT(paths.error(), Eq(std::nullopt)) << *paths.error();\n  TestInstallPaths(paths);\n}\n\nTEST_F(InstallPathsTest, Errors) {\n  auto paths = InstallPaths::Make(\"/foo/bar/baz\");\n  EXPECT_THAT(paths.error(), Optional(HasSubstr(\"foo/bar/baz\")));\n  EXPECT_THAT(InstallPathsTestPeer::GetRoot(paths), Eq(\"\"));\n\n  paths = InstallPaths::MakeExeRelative(\"foo/bar/baz\");\n  EXPECT_THAT(paths.error(), Optional(HasSubstr(\"foo/bar/baz\")));\n  EXPECT_THAT(InstallPathsTestPeer::GetRoot(paths), Eq(\"\"));\n\n  // Note that we can't test the runfiles code path from within a test because\n  // it succeeds some of the time even with a bogus executable name.\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "toolchain/base/install_paths_test_helpers.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/install_paths_test_helpers.h\"\n\n#include <memory>\n#include <utility>\n\n#include \"testing/base/global_exe_path.h\"\n\nnamespace Carbon::Testing {\n\n// Prepares the VFS with prelude files from the real filesystem. Primarily for\n// tests.\nauto AddPreludeFilesToVfs(\n    const InstallPaths& install_paths,\n    llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>& vfs) -> void {\n  // Load the prelude into the test VFS.\n  auto real_fs = llvm::vfs::getRealFileSystem();\n  auto prelude = install_paths.ReadPreludeManifest();\n  CARBON_CHECK(prelude.ok(), \"{0}\", prelude.error());\n\n  for (const auto& path : *prelude) {\n    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> file =\n        real_fs->getBufferForFile(path);\n    CARBON_CHECK(file, \"Error getting file: {0}\", file.getError().message());\n    bool added = vfs->addFile(path, /*ModificationTime=*/0, std::move(*file));\n    CARBON_CHECK(added, \"Duplicate file: {0}\", path);\n  }\n}\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "toolchain/base/install_paths_test_helpers.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_INSTALL_PATHS_TEST_HELPERS_H_\n#define CARBON_TOOLCHAIN_BASE_INSTALL_PATHS_TEST_HELPERS_H_\n\n#include \"llvm/Support/VirtualFileSystem.h\"\n#include \"toolchain/base/install_paths.h\"\n\nnamespace Carbon::Testing {\n\n// Prepares the VFS with prelude files from the real filesystem.\nauto AddPreludeFilesToVfs(\n    const InstallPaths& install_paths,\n    llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>& vfs) -> void;\n\n}  // namespace Carbon::Testing\n\n#endif  // CARBON_TOOLCHAIN_BASE_INSTALL_PATHS_TEST_HELPERS_H_\n"
  },
  {
    "path": "toolchain/base/int.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/int.h\"\n\n#include <algorithm>\n#include <string>\n\nnamespace Carbon {\n\nauto IntStore::CanonicalBitWidth(int significant_bits) -> int {\n  // For larger integers, we store them in as a signed APInt with a canonical\n  // width that is the smallest multiple of the word type's bits, but no\n  // smaller than a minimum of 64 bits to avoid spurious resizing of the most\n  // common cases (<= 64 bits).\n  static constexpr int WordWidth = llvm::APInt::APINT_BITS_PER_WORD;\n\n  return std::max<int>(\n      MinAPWidth, ((significant_bits + WordWidth - 1) / WordWidth) * WordWidth);\n}\n\nauto IntStore::CanonicalizeSigned(llvm::APInt value) -> llvm::APInt {\n  return value.sextOrTrunc(CanonicalBitWidth(value.getSignificantBits()));\n}\n\nauto IntStore::CanonicalizeUnsigned(llvm::APInt value) -> llvm::APInt {\n  // We need the width to include a zero sign bit as we canonicalize to a\n  // signed representation.\n  return value.zextOrTrunc(CanonicalBitWidth(value.getActiveBits() + 1));\n}\n\nauto IntStore::AddLarge(int64_t value) -> IntId {\n  auto ap_id =\n      values_.Add(llvm::APInt(CanonicalBitWidth(64), value, /*isSigned=*/true));\n  return MakeIndexOrNone(ap_id.index);\n}\n\nauto IntStore::AddSignedLarge(llvm::APInt value) -> IntId {\n  auto ap_id = values_.Add(CanonicalizeSigned(value));\n  return MakeIndexOrNone(ap_id.index);\n}\n\nauto IntStore::AddUnsignedLarge(llvm::APInt value) -> IntId {\n  auto ap_id = values_.Add(CanonicalizeUnsigned(value));\n  return MakeIndexOrNone(ap_id.index);\n}\n\nauto IntStore::LookupLarge(int64_t value) const -> IntId {\n  auto ap_id = values_.Lookup(\n      llvm::APInt(CanonicalBitWidth(64), value, /*isSigned=*/true));\n  return MakeIndexOrNone(ap_id.index);\n}\n\nauto IntStore::LookupSignedLarge(llvm::APInt value) const -> IntId {\n  auto ap_id = values_.Lookup(CanonicalizeSigned(value));\n  return MakeIndexOrNone(ap_id.index);\n}\n\nauto IntStore::OutputYaml() const -> Yaml::OutputMapping {\n  return values_.OutputYaml();\n}\n\nauto IntStore::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const\n    -> void {\n  mem_usage.Collect(std::string(label), values_);\n}\n\n}  // namespace Carbon\n"
  },
  {
    "path": "toolchain/base/int.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_INT_H_\n#define CARBON_TOOLCHAIN_BASE_INT_H_\n\n#include \"common/check.h\"\n#include \"llvm/ADT/APInt.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/base/canonical_value_store.h\"\n#include \"toolchain/base/index_base.h\"\n#include \"toolchain/base/mem_usage.h\"\n#include \"toolchain/base/value_store.h\"\n#include \"toolchain/base/yaml.h\"\n\nnamespace Carbon {\n\n// Forward declare a testing peer so we can friend it.\nnamespace Testing {\nstruct IntStoreTestPeer;\n}  // namespace Testing\n\n// Corresponds to a canonicalized integer value. This is used both for integer\n// literal tokens, and integer values in SemIR. These always represent the\n// abstract mathematical value -- signed and regardless of the needed precision.\n//\n// Small values are internalized into the ID itself. Large values are\n// represented as an index into an array of `APInt`s with a canonicalized bit\n// width. The ID itself can be queried for whether it is a value-embedded-ID or\n// an index ID. The ID also provides APIs for extracting either the value or an\n// index.\n//\n// ## Details of the encoding scheme ##\n//\n// We need all the values from a maximum to minimum, as well as a healthy range\n// of indices, to fit within the token ID bits.\n//\n// We represent this as a signed `TokenIdBits`-bit 2s compliment integer. The\n// sign extension from TokenIdBits to a register size can be folded into the\n// shift used to extract those bits from compressed bitfield storage.\n//\n// We then divide the smallest 1/4th of that bit width's space to represent\n// indices, and the larger 3/4ths to embedded values. For 23-bits total this\n// still gives us 2 million unique integers larger than the embedded ones, which\n// would be difficult to fill without exceeding the number of tokens we can lex\n// (8 million). For non-token based integers, the indices can continue downward\n// to the 32-bit signed integer minimum, supporting approximately 1.998 billion\n// unique larger integers.\n//\n// Note the `None` ID can't be used with a token. This is OK as we expect\n// invalid tokens to be *error* tokens and not need to represent an invalid\n// integer.\nclass IntId : public Printable<IntId> {\n public:\n  static constexpr llvm::StringLiteral Label = \"int\";\n\n  // The encoding of integer IDs ensures that IDs associated with tokens during\n  // lexing can fit into a compressed storage space. We arrange for\n  // `TokenIdBits` to be the minimum number of bits of storage for token\n  // associated IDs. The constant is public so the lexer can ensure it reserves\n  // adequate space.\n  //\n  // Note that there may still be IDs either not associated with\n  // tokens or computed after lexing outside of this range.\n  static constexpr int TokenIdBits = 23;\n\n  static const IntId None;\n\n  static auto MakeFromTokenPayload(uint32_t payload) -> IntId {\n    // Token-associated IDs are signed `TokenIdBits` integers, so force sign\n    // extension from that bit.\n    return IntId(static_cast<int32_t>(payload << TokenIdBitsShift) >>\n                 TokenIdBitsShift);\n  }\n\n  // Construct an ID from a raw 32-bit ID value.\n  static constexpr auto MakeRaw(int32_t raw_id) -> IntId {\n    return IntId(raw_id);\n  }\n\n  // Tests whether the ID is an embedded value ID.\n  //\n  // Note `None` is not an embedded value, so this implies `has_value()` is\n  // true.\n  constexpr auto is_embedded_value() const -> bool { return id_ > ZeroIndexId; }\n\n  // Tests whether the ID is an index ID.\n  //\n  // Note `None` is represented as an index ID, so this is *not* sufficient to\n  // test `has_value()`.\n  constexpr auto is_index() const -> bool { return id_ <= ZeroIndexId; }\n\n  // Test whether a value is present.\n  //\n  // This does not distinguish between embedded values and index IDs, only\n  // whether some value is present.\n  constexpr auto has_value() const -> bool { return id_ != NoneId; }\n\n  // Converts an ID to the embedded value. Requires that `is_embedded_value()`\n  // is true.\n  constexpr auto AsValue() const -> int {\n    CARBON_DCHECK(is_embedded_value());\n    return id_;\n  }\n\n  // Converts an ID to an index. Requires that `is_index()` is true.\n  //\n  // Note `None` is represented as an index ID, and can be converted here.\n  constexpr auto AsIndex() const -> int {\n    CARBON_DCHECK(is_index());\n    return ZeroIndexId - id_;\n  }\n\n  // Returns the ID formatted as a lex token payload.\n  constexpr auto AsTokenPayload() const -> uint32_t {\n    uint32_t payload = id_;\n    // Ensure this ID round trips as the token payload.\n    CARBON_DCHECK(*this == MakeFromTokenPayload(payload));\n    return payload;\n  }\n\n  constexpr auto AsRaw() const -> int32_t { return id_; }\n\n  auto Print(llvm::raw_ostream& out) const -> void {\n    out << Label << \"(\";\n    if (is_embedded_value()) {\n      out << \"value: \" << AsValue();\n    } else if (is_index()) {\n      out << \"index: \" << AsIndex();\n    } else {\n      CARBON_CHECK(!has_value());\n      out << \"<none>\";\n    }\n    out << \")\";\n  }\n\n  friend constexpr auto operator==(IntId lhs, IntId rhs) -> bool {\n    return lhs.id_ == rhs.id_;\n  }\n  friend constexpr auto operator<=>(IntId lhs, IntId rhs)\n      -> std::strong_ordering {\n    return lhs.id_ <=> rhs.id_;\n  }\n\n private:\n  friend class IntStore;\n  friend Testing::IntStoreTestPeer;\n\n  // The shift needed when adjusting a between a `TokenIdBits`-width integer and\n  // a 32-bit integer.\n  static constexpr int TokenIdBitsShift = 32 - TokenIdBits;\n\n  // The maximum embedded value in an ID.\n  static constexpr int32_t MaxValue =\n      std::numeric_limits<int32_t>::max() >> TokenIdBitsShift;\n\n  // The ID value that represents an index of `0`. This is the first ID value\n  // representing an index, and all indices are `<=` to this.\n  //\n  // `ZeroIndexId` is the first index ID, and we encode indices as successive\n  // negative numbers counting downwards. The setup allows us to both use a\n  // comparison with this ID to distinguish value and index IDs, and to compute\n  // the actual index from the ID.\n  //\n  // The computation of an index in fact is just a subtraction:\n  // `ZeroIndexId - id_`. Subtraction is *also* how most CPUs implement the\n  // comparison, and so all of this ends up carefully constructed to enable very\n  // small code size when testing for an embedded value and when that test fails\n  // computing and using the index.\n  static constexpr int32_t ZeroIndexId =\n      std::numeric_limits<int32_t>::min() >> (TokenIdBitsShift + 1);\n\n  // The minimum embedded value in an ID.\n  static constexpr int32_t MinValue = ZeroIndexId + 1;\n\n  // The `None` ID, which needs to be placed after the largest index, which\n  // count downwards as IDs so below the smallest index ID, in order to optimize\n  // the code sequence needed to distinguish between integer and value IDs and\n  // to convert index IDs into actual indices small.\n  static constexpr int32_t NoneId = std::numeric_limits<int32_t>::min();\n\n  // The `None` index. This is the result of converting a `None` ID into an\n  // index. We ensure that conversion can be done so that we can simplify the\n  // code that first tries to use an embedded value, then converts to an index\n  // and checks that the index is still `None`.\n  static const int32_t NoneIndex;\n\n  // Document the specific values of some of these constants to help visualize\n  // how the bit patterns map from the above computations.\n  //\n  // clang-format off: visualizing bit positions\n  //\n  // Each bit is either `T` for part of the token or `P` as part\n  // of the available payload that we use for the ID:\n  //\n  //                           0bTTTT'TTTT'TPPP'PPPP'PPPP'PPPP'PPPP'PPPP\n  static_assert(MaxValue    == 0b0000'0000'0011'1111'1111'1111'1111'1111);\n  static_assert(ZeroIndexId == 0b1111'1111'1110'0000'0000'0000'0000'0000);\n  static_assert(MinValue    == 0b1111'1111'1110'0000'0000'0000'0000'0001);\n  static_assert(NoneId      == 0b1000'0000'0000'0000'0000'0000'0000'0000);\n  // clang-format on\n\n  constexpr explicit IntId(int32_t id) : id_(id) {}\n\n  int32_t id_;\n};\n\ninline constexpr IntId IntId::None(IntId::NoneId);\n\n// Note that we initialize the `None` index in a constexpr context which\n// ensures there is no UB in forming it. This helps ensure all the ID -> index\n// conversions are correct because the `None` ID is at the limit of that range.\ninline constexpr int32_t IntId::NoneIndex = None.AsIndex();\n\n// A canonicalizing value store with deep optimizations for integers.\n//\n// This stores integers as abstract, signed mathematical integers. The bit width\n// of specific `APInt` values, either as inputs or outputs, is disregarded for\n// the purpose of canonicalization and the returned integer may use a very\n// different bit width `APInt` than was used when adding. There are also\n// optimized paths for adding integer values representable using native integer\n// types.\n//\n// Because the integers in the store are canonicalized with only a minimum bit\n// width, there are helper functions to coerce them to a specific desired bit\n// width for use.\n//\n// This leverages a significant optimization for small integer values -- rather\n// than canonicalizing and making them unique in a `ValueStore`, they are\n// directly embedded in the `IntId` itself. Only larger integers are stored in\n// an array of `APInt` values and represented as an index in the ID.\nclass IntStore {\n public:\n  // We rely on `APInt` values having a minimum bit width.\n  static constexpr int MinAPWidth = 64;\n\n  // The maximum supported bit width of an integer type.\n  // TODO: Pick a maximum size and document it in the design. For now\n  // we use 2^^23, because that's the largest size that LLVM supports.\n  static constexpr int MaxIntWidth = 1 << 23;\n\n  // Pick a canonical bit width for the provided number of significant bits.\n  static auto CanonicalBitWidth(int significant_bits) -> int;\n\n  // Accepts a signed `int64_t` and uses the mathematical signed integer value\n  // of it as the added integer value.\n  //\n  // Returns the ID corresponding to this integer value, storing an `APInt` if\n  // necessary to represent it.\n  auto Add(int64_t value) -> IntId {\n    // First try directly making this into an ID.\n    if (IntId id = TryMakeValue(value); id.has_value()) [[likely]] {\n      return id;\n    }\n\n    // Fallback for larger values.\n    return AddLarge(value);\n  }\n\n  // Returns the ID corresponding to this integer value.\n  auto Add(llvm::APSInt value) -> IntId {\n    return value.isSigned() ? AddSigned(value) : AddUnsigned(value);\n  }\n\n  // Returns the ID corresponding to this signed integer value, storing an\n  // `APInt` if necessary to represent it.\n  auto AddSigned(llvm::APInt value) -> IntId {\n    // First try directly making this into an ID.\n    if (IntId id = TryMakeSignedValue(value); id.has_value()) [[likely]] {\n      return id;\n    }\n\n    // Fallback for larger values.\n    return AddSignedLarge(std::move(value));\n  }\n\n  // Returns the ID corresponding to an equivalent signed integer value for the\n  // provided unsigned integer value, storing an `APInt` if necessary to\n  // represent it.\n  auto AddUnsigned(llvm::APInt value) -> IntId {\n    // First try directly making this into an ID.\n    if (IntId id = TryMakeUnsignedValue(value); id.has_value()) [[likely]] {\n      return id;\n    }\n\n    // Fallback for larger values.\n    return AddUnsignedLarge(std::move(value));\n  }\n\n  // Returns the value for an ID.\n  //\n  // This will always be a signed `APInt` with a canonical bit width for the\n  // specific integer value in question.\n  auto Get(IntId id) const -> llvm::APInt {\n    if (id.is_embedded_value()) [[likely]] {\n      return llvm::APInt(MinAPWidth, id.AsValue(), /*isSigned=*/true);\n    }\n    return values_.Get(APIntId(id.AsIndex()));\n  }\n\n  // Returns the value for an ID adjusted to a specific bit width.\n  //\n  // Note that because we store canonical mathematical integers as signed\n  // integers, this always sign extends or truncates to the target width. The\n  // caller can then use that as a signed or unsigned integer as needed.\n  auto GetAtWidth(IntId id, int bit_width) const -> llvm::APInt {\n    llvm::APInt value = Get(id);\n    if (static_cast<int>(value.getBitWidth()) != bit_width) {\n      value = value.sextOrTrunc(bit_width);\n    }\n    return value;\n  }\n\n  // Returns the value for an ID adjusted to the bit width specified with\n  // another integer ID.\n  //\n  // This simply looks up the width integer ID, and then calls the above\n  // `GetAtWidth` overload using the value found for it. See that overload for\n  // more details.\n  auto GetAtWidth(IntId id, IntId bit_width_id) const -> llvm::APInt {\n    const llvm::APInt bit_width = Get(bit_width_id);\n    CARBON_CHECK(\n        bit_width.isStrictlyPositive() && bit_width.isSignedIntN(MinAPWidth),\n        \"Invalid bit width value: {0}\", bit_width);\n    return GetAtWidth(id, bit_width.getSExtValue());\n  }\n\n  // Accepts a signed `int64_t` and uses the mathematical signed integer value\n  // of it as the integer value to lookup. Returns the canonical ID for that\n  // value or returns `None` if not in the store.\n  auto Lookup(int64_t value) const -> IntId {\n    if (IntId id = TryMakeValue(value); id.has_value()) [[likely]] {\n      return id;\n    }\n\n    // Fallback for larger values.\n    return LookupLarge(value);\n  }\n\n  // Looks up the canonical ID for this signed integer value, or returns `None`\n  // if not in the store.\n  auto LookupSigned(llvm::APInt value) const -> IntId {\n    if (IntId id = TryMakeSignedValue(value); id.has_value()) [[likely]] {\n      return id;\n    }\n\n    // Fallback for larger values.\n    return LookupSignedLarge(std::move(value));\n  }\n\n  // Output a YAML description of this data structure. Note that this will only\n  // include the integers that required storing, not those successfully embedded\n  // into the ID space.\n  auto OutputYaml() const -> Yaml::OutputMapping;\n\n  auto values() const [[clang::lifetimebound]] -> auto {\n    return values_.values();\n  }\n  auto size() const -> size_t { return values_.size(); }\n\n  // Collects the memory usage of the separately stored integers.\n  auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const\n      -> void;\n\n private:\n  friend struct Testing::IntStoreTestPeer;\n\n  // Used for `values_`; tracked using `IntId`'s index range.\n  struct APIntId : IdBase<APIntId> {\n    static constexpr llvm::StringLiteral Label = \"ap_int\";\n    static const APIntId None;\n    using IdBase::IdBase;\n  };\n\n  static auto MakeIndexOrNone(int index) -> IntId {\n    CARBON_DCHECK(index >= 0 && index <= IntId::NoneIndex);\n    return IntId(IntId::ZeroIndexId - index);\n  }\n\n  // Tries to make a signed 64-bit integer into an embedded value in the ID, and\n  // if unable to do that returns the `None` ID.\n  static auto TryMakeValue(int64_t value) -> IntId {\n    if (IntId::MinValue <= value && value <= IntId::MaxValue) {\n      return IntId(value);\n    }\n\n    return IntId::None;\n  }\n\n  // Tries to make a signed APInt into an embedded value in the ID, and if\n  // unable to do that returns the `None` ID.\n  static auto TryMakeSignedValue(llvm::APInt value) -> IntId {\n    if (value.sge(IntId::MinValue) && value.sle(IntId::MaxValue)) {\n      return IntId(value.getSExtValue());\n    }\n\n    return IntId::None;\n  }\n\n  // Tries to make an unsigned APInt into an embedded value in the ID, and if\n  // unable to do that returns the `None` ID.\n  static auto TryMakeUnsignedValue(llvm::APInt value) -> IntId {\n    if (value.ule(IntId::MaxValue)) {\n      return IntId(value.getZExtValue());\n    }\n\n    return IntId::None;\n  }\n\n  // Canonicalize an incoming signed APInt to the correct bit width.\n  static auto CanonicalizeSigned(llvm::APInt value) -> llvm::APInt;\n\n  // Canonicalize an incoming unsigned APInt to the correct bit width.\n  static auto CanonicalizeUnsigned(llvm::APInt value) -> llvm::APInt;\n\n  // Helper functions for handling values that are large enough to require an\n  // allocated `APInt` for storage. Creating or manipulating that storage is\n  // only a few lines of code, but we move these out-of-line because the\n  // generated code is big and harms performance for the non-`Large` common\n  // case.\n  auto AddLarge(int64_t value) -> IntId;\n  auto AddSignedLarge(llvm::APInt value) -> IntId;\n  auto AddUnsignedLarge(llvm::APInt value) -> IntId;\n  auto LookupLarge(int64_t value) const -> IntId;\n  auto LookupSignedLarge(llvm::APInt value) const -> IntId;\n\n  // Stores values which don't fit in an IntId. These are always signed.\n  CanonicalValueStore<APIntId, llvm::APInt> values_;\n};\n\ninline constexpr IntStore::APIntId IntStore::APIntId::None(\n    IntId::None.AsIndex());\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_INT_H_\n"
  },
  {
    "path": "toolchain/base/int_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/int.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <algorithm>\n#include <limits>\n\nnamespace Carbon::Testing {\n\nstruct IntStoreTestPeer {\n  static constexpr int MinAPWidth = IntStore::MinAPWidth;\n\n  static constexpr int32_t MaxIdEmbeddedValue = IntId::MaxValue;\n  static constexpr int32_t MinIdEmbeddedValue = IntId::MinValue;\n};\n\nnamespace {\n\nusing ::testing::Eq;\n\nstatic constexpr int MinAPWidth = IntStoreTestPeer::MinAPWidth;\n\nstatic constexpr int32_t MaxIdEmbeddedValue =\n    IntStoreTestPeer::MaxIdEmbeddedValue;\nstatic constexpr int32_t MinIdEmbeddedValue =\n    IntStoreTestPeer::MinIdEmbeddedValue;\n\nTEST(IntStore, Basic) {\n  IntStore ints;\n  IntId id_0 = ints.Add(0);\n  IntId id_1 = ints.Add(1);\n  IntId id_2 = ints.Add(2);\n  IntId id_42 = ints.Add(42);\n  IntId id_n1 = ints.Add(-1);\n  IntId id_n42 = ints.Add(-42);\n  IntId id_nines = ints.Add(999'999'999'999);\n  IntId id_max64 = ints.Add(std::numeric_limits<int64_t>::max());\n  IntId id_min64 = ints.Add(std::numeric_limits<int64_t>::min());\n\n  for (IntId id :\n       {id_0, id_1, id_2, id_42, id_n1, id_n42, id_nines, id_max64, id_min64}) {\n    ASSERT_TRUE(id.has_value());\n  }\n\n  // Small values should be embedded.\n  EXPECT_THAT(id_0.AsValue(), Eq(0));\n  EXPECT_THAT(id_1.AsValue(), Eq(1));\n  EXPECT_THAT(id_2.AsValue(), Eq(2));\n  EXPECT_THAT(id_42.AsValue(), Eq(42));\n  EXPECT_THAT(id_n1.AsValue(), Eq(-1));\n  EXPECT_THAT(id_n42.AsValue(), Eq(-42));\n\n  // Rest should be indices as they don't fit as embedded values.\n  EXPECT_TRUE(!id_nines.is_embedded_value());\n  EXPECT_TRUE(id_nines.is_index());\n  EXPECT_TRUE(!id_max64.is_embedded_value());\n  EXPECT_TRUE(id_max64.is_index());\n  EXPECT_TRUE(!id_min64.is_embedded_value());\n  EXPECT_TRUE(id_min64.is_index());\n\n  // And round tripping all the way through the store should work.\n  EXPECT_THAT(ints.Get(id_0), Eq(0));\n  EXPECT_THAT(ints.Get(id_1), Eq(1));\n  EXPECT_THAT(ints.Get(id_2), Eq(2));\n  EXPECT_THAT(ints.Get(id_42), Eq(42));\n  EXPECT_THAT(ints.Get(id_n1), Eq(-1));\n  EXPECT_THAT(ints.Get(id_n42), Eq(-42));\n  EXPECT_THAT(ints.Get(id_nines), Eq(999'999'999'999));\n  EXPECT_THAT(ints.Get(id_max64), Eq(std::numeric_limits<int64_t>::max()));\n  EXPECT_THAT(ints.Get(id_min64), Eq(std::numeric_limits<int64_t>::min()));\n}\n\n// Helper struct to hold test values and the resulting IDs.\nstruct APAndId {\n  llvm::APInt ap;\n  IntId id = IntId::None;\n};\n\nTEST(IntStore, APSigned) {\n  IntStore ints;\n\n  llvm::APInt big_128_ap =\n      llvm::APInt(128, 0x1234'abcd'1234'abcd, /*isSigned=*/true) * 0xabcd'0000;\n  llvm::APInt max_embedded_ap(MinAPWidth, MaxIdEmbeddedValue,\n                              /*isSigned=*/true);\n  llvm::APInt min_embedded_ap(MinAPWidth, MinIdEmbeddedValue,\n                              /*isSigned=*/true);\n\n  APAndId ap_and_ids[] = {\n      {.ap = llvm::APInt(MinAPWidth, 1, /*isSigned=*/true)},\n      {.ap = llvm::APInt(MinAPWidth, 2, /*isSigned=*/true)},\n      {.ap = llvm::APInt(MinAPWidth, 999'999'999'999, /*isSigned=*/true)},\n      {.ap = big_128_ap},\n      {.ap = -big_128_ap},\n      {.ap =\n           big_128_ap.sext(512) * big_128_ap.sext(512) * big_128_ap.sext(512)},\n      {.ap =\n           -big_128_ap.sext(512) * big_128_ap.sext(512) * big_128_ap.sext(512)},\n      {.ap = max_embedded_ap},\n      {.ap = max_embedded_ap + 1},\n      {.ap = min_embedded_ap},\n      {.ap = min_embedded_ap - 1},\n  };\n  for (auto& [ap, id] : ap_and_ids) {\n    id = ints.AddSigned(ap);\n    ASSERT_TRUE(id.has_value()) << ap;\n  }\n\n  for (const auto& [ap, id] : ap_and_ids) {\n    // The sign extend here may be a no-op, but the original bit width is a\n    // reliable one at which to do the comparison.\n    EXPECT_THAT(ints.Get(id).sext(ap.getBitWidth()), Eq(ap));\n  }\n}\n\nTEST(IntStore, APUnsigned) {\n  IntStore ints;\n\n  llvm::APInt big_128_ap =\n      llvm::APInt(128, 0xabcd'abcd'abcd'abcd) * 0xabcd'0000'abcd'0000;\n  llvm::APInt max_embedded_ap(MinAPWidth, MaxIdEmbeddedValue);\n\n  APAndId ap_and_ids[] = {\n      {.ap = llvm::APInt(MinAPWidth, 1)},\n      {.ap = llvm::APInt(MinAPWidth, 2)},\n      {.ap = llvm::APInt(MinAPWidth, 999'999'999'999)},\n      {.ap = llvm::APInt(MinAPWidth, std::numeric_limits<uint64_t>::max())},\n      {.ap = llvm::APInt(MinAPWidth + 1, std::numeric_limits<uint64_t>::max()) +\n             1},\n      {.ap = big_128_ap},\n      {.ap =\n           big_128_ap.zext(512) * big_128_ap.zext(512) * big_128_ap.zext(512)},\n      {.ap = max_embedded_ap},\n      {.ap = max_embedded_ap + 1},\n  };\n  for (auto& [ap, id] : ap_and_ids) {\n    id = ints.AddUnsigned(ap);\n    ASSERT_TRUE(id.has_value()) << ap;\n  }\n\n  for (const auto& [ap, id] : ap_and_ids) {\n    auto stored_ap = ints.Get(id);\n    // Pick a bit width wide enough to represent both whatever is returned and\n    // the original value as a *signed* integer without any truncation.\n    int width = std::max(stored_ap.getBitWidth(), ap.getBitWidth() + 1);\n    // We sign extend the stored value and zero extend the original number. This\n    // ensures that anything added as unsigned ends up stored as a positive\n    // number even when sign extended.\n    EXPECT_THAT(stored_ap.sext(width), Eq(ap.zext(width)));\n  }\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "toolchain/base/kind_switch.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_KIND_SWITCH_H_\n#define CARBON_TOOLCHAIN_BASE_KIND_SWITCH_H_\n\n#include <type_traits>\n\n#include \"llvm/ADT/STLExtras.h\"\n#include \"toolchain/base/for_each_macro.h\"\n\n// This library provides switch-like behaviors for Carbon's kind-based types.\n//\n// An expected use case is to mix regular switch `case` statements and\n// `CARBON_KIND`. However, the `switch` must be defined using\n// `CARBON_KIND_SWITCH`. For example:\n//\n//   CARBON_KIND_SWITCH(untyped_inst) {\n//     case CARBON_KIND(SomeInstType inst): {\n//       return inst.typed_field;\n//     }\n//     case CARBON_KIND_ANY(AnyKind, any_inst): {\n//       return any_inst.typed_field;\n//     }\n//\n//     case OtherType1::Kind:\n//     case OtherType2::Kind:\n//       return value;\n//     default:\n//       return default_value;\n//   }\n//\n// When used on kind-like types, this requires:\n//\n// - The type passed to `CARBON_KIND_SWITCH` has `.kind()` to switch on, and\n//   `.As<CaseT>` for `CARBON_KIND` to cast to.\n// - Each type passed to `CARBON_KIND` (`CaseT` above) provides\n//   `CaseT::Kind`, which is passed to the `case` keyword.\n//   `CaseT::Kind::RawEnumType` is the type returned by `.kind()`.\n// - Each type passed to `CARBON_KIND_ANY` must have a macro of the form:\n//   ```\n//   #define AnyKind_CARBON_KIND_ANY_EXPAND   \\\n//     CARBON_KIND_ANY_EXPAND_BEGIN() CARBON_KIND_ANY_EXPAND_CASE(Kind1) \\\n//     CARBON_KIND_ANY_EXPAND_SEP()   CARBON_KIND_ANY_EXPAND_CASE(Kind2) \\\n//     ...\n//     CARBON_KIND_ANY_EXPAND_SEP()   CARBON_KIND_ANY_EXPAND_CASE(KindN)\n//   ```\n//   Note the prefix `,` is required.\n//\n// When used with `std::variant` (e.g., `CARBON_KIND_SWITCH(variant_value)`),\n// members of the variant are passed to `CARBON_KIND`, instead of types that\n// have a `::Kind` member.\n\n// Produces a switch statement on value.kind().\n#define CARBON_KIND_SWITCH(value)                       \\\n  switch (                                              \\\n      auto&& carbon_internal_kind_switch_value = value; \\\n      ::Carbon::Internal::Kind::SwitchOn(carbon_internal_kind_switch_value))\n\n// Produces a case-compatible block of code that also instantiates a local typed\n// variable. typed_variable_decl looks like `int i`; the `CARBON_KIND` value\n// will be cast to the provided type.\n//\n// Because of the dangling else, braces should always be used with a `case\n// CARBON_KIND`. Otherwise, only the first statement is going to see the\n// variable. Even if that sometimes works, it can lead to confusing issues when\n// statements are added, and `if`/`else` coding style already requires braces.\n#define CARBON_KIND(typed_variable_decl)               \\\n  CARBON_KIND_INTERNAL_CASE_VALUE(typed_variable_decl) \\\n      : CARBON_KIND_INTERNAL_DECLARE(typed_variable_decl)\n\n// Macros for clients to add support for `Type_CARBON_KIND_ANY_EXPAND` (see\n// example above). Empty parameters are used to allow delaying macro expansion.\n#define CARBON_KIND_ANY_EXPAND_CASE(X) CARBON_KIND_INTERNAL_CASE_VALUE(X)\n#define CARBON_KIND_ANY_EXPAND_BEGIN() ,\n#define CARBON_KIND_ANY_EXPAND_SEP() : case\n\n// Produces a case-compatible block of code that also instantiates a local typed\n// variable. Versus `CARBON_KIND(int i)`, note this requires a comma after the\n// type, as in `CARBON_KIND_ANY(AnyKind, i)`.\n#define CARBON_KIND_ANY(Type, variable_name)               \\\n  CARBON_KIND_ANY_INTERNAL_WITH_SUFFIX(Type variable_name, \\\n                                       Type##_CARBON_KIND_ANY_EXPAND)\n\n// -----------------------------------------------------------------------------\n// Internal implementation details follow.\n// -----------------------------------------------------------------------------\n\nnamespace Carbon::Internal::Kind {\n\ntemplate <typename T>\nconstexpr bool IsStdVariantValue = false;\n\ntemplate <typename... Ts>\nconstexpr bool IsStdVariantValue<std::variant<Ts...>> = true;\n\ntemplate <typename T>\nconcept IsStdVariant = IsStdVariantValue<std::decay_t<T>>;\n\n#define CARBON_INTERNAL_KIND_IDENTIFIER(name) T##name\n// Turns a list of numbers into a list `T0, T1, ...`.\n#define CARBON_INTERNAL_KIND_IDENTIFIERS(...)                             \\\n  CARBON_FOR_EACH(CARBON_INTERNAL_KIND_IDENTIFIER, CARBON_FOR_EACH_COMMA, \\\n                  __VA_ARGS__)\n\n#define CARBON_INTERNAL_KIND_TYPENAME(name) \\\n  typename CARBON_INTERNAL_KIND_IDENTIFIER(name)\n// Turns a list of numbers into a list `typename T0, typename T1, ...`.\n#define CARBON_INTERNAL_KIND_TYPENAMES(...)                             \\\n  CARBON_FOR_EACH(CARBON_INTERNAL_KIND_TYPENAME, CARBON_FOR_EACH_COMMA, \\\n                  __VA_ARGS__)\n\n#define CARBON_INTERNAL_KIND_ENUM_NAME(n) VariantType##n##NotHandledInSwitch\n// Turns a list of numbers into a list `VariantType0NotHandledInSwitch, ...`.\n#define CARBON_INTERNAL_KIND_TYPES_TO_ENUM_NAMES(...)                    \\\n  CARBON_FOR_EACH(CARBON_INTERNAL_KIND_ENUM_NAME, CARBON_FOR_EACH_COMMA, \\\n                  __VA_ARGS__)\n\n// Turns a list of numbers into a set of template specializations of the\n// variable `EnumType EnumValue`, with each specialization having the Nth value\n// in the EnumType (as defined by CARBON_INTERNAL_KIND_TYPES_TO_ENUM_NAMES).\n#define CARBON_INTERNAL_KIND_TYPE_TO_ENUM_NAME(n)                    \\\n  template <>                                                        \\\n  constexpr EnumType EnumValue<CARBON_INTERNAL_KIND_IDENTIFIER(n)> = \\\n      EnumType::CARBON_INTERNAL_KIND_ENUM_NAME(n)\n\n// Used to provide a reason in the compiler error from `ValidCaseType`, which\n// will state that \"T does not satisfy TypeFoundInVariant\".\ntemplate <typename T>\nconcept TypeFoundInVariant = false;\n\n// Used to cause a compler error, which will state that \"ValidCaseType was not\n// satisfied\" for T and std::variant<...>.\ntemplate <typename T, typename StdVariant>\n  requires TypeFoundInVariant<T>\nstruct ValidCaseType;\n\ntemplate <typename T>\nstruct StdVariantTypeMap;\n\n#define CARBON_INTERNAL_KIND_TYPE_MAP(...)                                     \\\n  template <CARBON_INTERNAL_KIND_TYPENAMES(__VA_ARGS__)>                       \\\n  struct StdVariantTypeMap<                                                    \\\n      std::variant<CARBON_INTERNAL_KIND_IDENTIFIERS(__VA_ARGS__)>> {           \\\n    /* An enum with a value for each type in the std::variant. The switch will \\\n     * be on this enum so that we get a warning if one of the enum values is   \\\n     * not handled. They are named in a way to help explain the warning, that  \\\n     * it means a type in the std::variant<...> type list does not have a      \\\n     * matching case statement.                                                \\\n     */                                                                        \\\n    enum class EnumType {                                                      \\\n      CARBON_INTERNAL_KIND_TYPES_TO_ENUM_NAMES(__VA_ARGS__)                    \\\n    };                                                                         \\\n    /* A mapping from a single type in the std::variant<...> type list to a    \\\n     * value in the EnumType. This value is only used in the case a type is    \\\n     * queried which is not part of the type list, and ValidCaseType is used   \\\n     * to produce a diagnostic explaining the situation.  */                   \\\n    template <typename Tn>                                                     \\\n    static constexpr EnumType EnumValue = ValidCaseType<                       \\\n        Tn, std::variant<CARBON_INTERNAL_KIND_IDENTIFIERS(__VA_ARGS__)>>();    \\\n    /**/                                                                       \\\n    CARBON_FOR_EACH(CARBON_INTERNAL_KIND_TYPE_TO_ENUM_NAME,                    \\\n                    CARBON_FOR_EACH_SEMI, __VA_ARGS__);                        \\\n  }\n\ntemplate <typename... Ts>\nstruct StdVariantTypeMap<std::variant<Ts...>> {\n  // The number here should match the number of arguments in the largest\n  // `CARBON_INTERNAL_KIND_TYPE_MAP` invocation below.\n  static_assert(sizeof...(Ts) <= 24,\n                \"CARBON_KIND_SWITCH supports std::variant with up to 24 types. \"\n                \"Add more if needed.\");\n};\n\n// Generate StdVariantTypeMap specializations for each number of types in the\n// std::variant<...> type list. The numbers here represent which number is\n// printed in diagnostics stating a type in the variant has no matching case\n// statement. Duplicate numbers would create an error.\nCARBON_INTERNAL_KIND_TYPE_MAP(0);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                              15);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                              15, 16);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                              15, 16, 17);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                              15, 16, 17, 18);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                              15, 16, 17, 18, 19);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                              15, 16, 17, 18, 19, 20);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                              15, 16, 17, 18, 19, 20, 21);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                              15, 16, 17, 18, 19, 20, 21, 22);\nCARBON_INTERNAL_KIND_TYPE_MAP(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,\n                              15, 16, 17, 18, 19, 20, 21, 22, 23);\n\n#undef CARBON_INTERNAL_KIND_IDENTIFIER\n#undef CARBON_INTERNAL_KIND_IDENTIFIERS\n#undef CARBON_INTERNAL_KIND_TYPENAME\n#undef CARBON_INTERNAL_KIND_TYPENAMES\n#undef CARBON_INTERNAL_KIND_ENUM_NAME\n#undef CARBON_INTERNAL_KIND_TYPES_TO_ENUM_NAMES\n#undef CARBON_INTERNAL_KIND_TYPE_TO_ENUM_NAME\n#undef CARBON_INTERNAL_KIND_TYPE_MAP\n\n// Uses the above `CARBON_INTERNAL_KIND_TYPE_MAP` expansions to make an enum\n// with a value for each type in a std::variant<...> type list.\ntemplate <typename StdVariant>\nusing StdVariantEnum = StdVariantTypeMap<std::decay_t<StdVariant>>::EnumType;\n\n// Uses the `CARBON_INTERNAL_KIND_TYPE_MAP` expanstions to find the enum value\n// in `StdVariantEnum` for a given type `T` in the type list of a\n// std::variant<...>.\ntemplate <typename T, typename StdVariant>\nconstexpr auto CaseValueOfTypeInStdVariant =\n    StdVariantTypeMap<std::decay_t<StdVariant>>::template EnumValue<T>;\n\n// Given `CARBON_KIND_SWITCH(value)` this returns the actual value to switch on.\n//\n// For types with a `kind()` accessor, this is the just the value of `kind()`.\n// The type returned from `kind()` is expected to be a `TypeEnum`, as it\n// is required to have its API, including a nested `RawEnumType`.\n//\n// For std::variant<...> this is an enum synthesized from the types in the\n// variant's type list.\ntemplate <typename SwitchT>\nconstexpr auto SwitchOn(SwitchT&& switch_value) -> auto {\n  if constexpr (IsStdVariant<SwitchT>) {\n    return static_cast<StdVariantEnum<SwitchT>>(switch_value.index());\n  } else {\n    return switch_value.kind();\n  }\n}\n\n// Given `CARBON_KIND(CaseT name)` this generates the case value to compare\n// against the switch value from `SwitchOn`.\n//\n// For types with a `kind()` accessor that returns a `TypeEnum`,\n// this gets the `TypeEnum<...>::RawTypeEnum` for the case type `CaseT`.\n//\n// For std::variant<...> this returns the value corresponding to the case type\n// from the enum synthesized (in `SwitchOn`) for the types in the variant's\n// type list.\ntemplate <typename SwitchT, typename CaseFnT>\nconsteval auto ForCase() -> auto {\n  using CaseT = llvm::function_traits<CaseFnT>::template arg_t<0>;\n  if constexpr (IsStdVariant<SwitchT>) {\n    using NoRefCaseT = std::remove_cvref_t<CaseT>;\n    return CaseValueOfTypeInStdVariant<NoRefCaseT, SwitchT>;\n  } else {\n    using KindT = llvm::function_traits<\n        decltype(&std::remove_cvref_t<SwitchT>::kind)>::result_t;\n    return static_cast<KindT::RawEnumType>(KindT::template For<CaseT>);\n  }\n}\n\n// Given `CARBON_KIND_SWITCH(value)` and `CARBON_KIND(CaseT name)` this converts\n// the `value` to `CaseT`.\n//\n// For types with a `kind()` accessor this uses `value.As<CaseT>`.\n//\n// For `std::variant<...>` this uses `std::get<CaseT>(value)`.\ntemplate <typename CaseFnT, typename SwitchT>\nauto Cast(SwitchT&& kind_switch_value) -> decltype(auto) {\n  using CaseT = llvm::function_traits<CaseFnT>::template arg_t<0>;\n  if constexpr (IsStdVariant<SwitchT>) {\n    using NoRefCaseT = std::remove_cvref_t<CaseT>;\n    return std::get<NoRefCaseT>(std::forward<SwitchT>(kind_switch_value));\n  } else {\n    return kind_switch_value.template As<CaseT>();\n  }\n}\n\n#define CARBON_INTERNAL_KIND_MERGE(Prefix, Line) Prefix##Line\n#define CARBON_INTERNAL_KIND_LABEL(Line) \\\n  CARBON_INTERNAL_KIND_MERGE(carbon_internal_kind_case_, Line)\n\n// To extract the type from an argument, we wrap it in a lambda and will use\n// `function_traits` to extract the type. This supports `typed_param` either\n// being `Type name`, or just `Type`.\n#define CARBON_KIND_INTERNAL_WRAP_TYPE(typed_param) \\\n  decltype([]([[maybe_unused]] typed_param) {})\n\n// Produces the value for a `case` statement on the type of `typed_param`.\n#define CARBON_KIND_INTERNAL_CASE_VALUE(typed_param) \\\n  ::Carbon::Internal::Kind::ForCase<                 \\\n      decltype(carbon_internal_kind_switch_value),   \\\n      CARBON_KIND_INTERNAL_WRAP_TYPE(typed_param)>()\n\n// Produces a declaration using `typed_variable_decl`.\n//\n// This uses `if` to scope the variable, and provides a dangling `else` in order\n// to prevent accidental `else` use. The label allows `:` to follow the macro\n// name, making it look more like a typical `case`.\n#define CARBON_KIND_INTERNAL_DECLARE(typed_variable_decl)                \\\n  if (typed_variable_decl =                                              \\\n          ::Carbon::Internal::Kind::Cast<CARBON_KIND_INTERNAL_WRAP_TYPE( \\\n              typed_variable_decl)>(                                     \\\n              std::forward<decltype(carbon_internal_kind_switch_value)>( \\\n                  carbon_internal_kind_switch_value));                   \\\n      false) {                                                           \\\n  } else [[maybe_unused]]                                                \\\n    CARBON_INTERNAL_KIND_LABEL(__LINE__)\n\n// Helper for `CARBON_KIND_ANY` that expands the now-suffixed macro.\n#define CARBON_KIND_ANY_INTERNAL_WITH_SUFFIX(typed_variable_decl,         \\\n                                             Type_CARBON_KIND_ANY_EXPAND) \\\n  CARBON_KIND_ANY_INTERNAL_IMPL(typed_variable_decl,                      \\\n                                Type_CARBON_KIND_ANY_EXPAND)\n\n// Helper for `CARBON_KIND_ANY` that forms the final case setup. The variadic\n// arguments are the expansion of `Type_CARBON_KIND_ANY_EXPAND`, which may\n// contain commas.\n//\n// As a consequence of the macro suffixing along with the required prefix comma\n// in `Type_CARBON_KIND_ANY_EXPAND`, input of `Namespace::Type` will have become\n// `Namespace::, Type_CARBON_KIND_ANY_EXPAND`, and `DiscardNamespace` exists to\n// discard `Namespace::`.\n#define CARBON_KIND_ANY_INTERNAL_IMPL(typed_variable_decl, DiscardNamespace, \\\n                                      ...)                                   \\\n  __VA_ARGS__:                                                               \\\n  CARBON_KIND_INTERNAL_DECLARE(typed_variable_decl)\n\n}  // namespace Carbon::Internal::Kind\n\n#endif  // CARBON_TOOLCHAIN_BASE_KIND_SWITCH_H_\n"
  },
  {
    "path": "toolchain/base/kind_switch_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/kind_switch.h\"\n\n#include <gtest/gtest.h>\n\n#include <string>\n#include <variant>\n\n#include \"common/raw_string_ostream.h\"\n\nnamespace Carbon {\nnamespace {\n\nTEST(KindSwitch, Variant) {\n  auto f = [](std::variant<int, float, char> v) -> std::string {\n    CARBON_KIND_SWITCH(v) {\n      case CARBON_KIND(int n): {\n        return llvm::formatv(\"int = {0}\", n);\n      }\n      case CARBON_KIND(float f): {\n        return llvm::formatv(\"float = {0}\", f);\n      }\n      case CARBON_KIND(char c): {\n        return llvm::formatv(\"char = {0}\", c);\n      }\n    }\n  };\n\n  EXPECT_EQ(f(int{1}), \"int = 1\");\n  EXPECT_EQ(f(float{2}), \"float = 2.00\");\n  EXPECT_EQ(f(char{'h'}), \"char = h\");\n}\n\nTEST(KindSwitch, VariantUnusedValue) {\n  auto f = [](std::variant<int, float> v) -> std::string {\n    CARBON_KIND_SWITCH(v) {\n      case CARBON_KIND(int n): {\n        return llvm::formatv(\"int = {0}\", n);\n      }\n      case CARBON_KIND(float _):\n        // The float value is not used, we see that using `_` works.\n        return \"float\";\n    }\n  };\n\n  EXPECT_EQ(f(int{1}), \"int = 1\");\n  EXPECT_EQ(f(float{2}), \"float\");\n}\n\n}  // namespace\n}  // namespace Carbon\n"
  },
  {
    "path": "toolchain/base/llvm_tools.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Provides variables and rules to automate working with LLVM's CLI tools.\"\"\"\n\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_library\")\n\n# The main LLVM command line tools, including their \"primary\" name, binary name,\n# and the library dependency required to use them.\nLLVM_MAIN_TOOLS = {\n    \"ar\": struct(bin_name = \"llvm-ar\", lib = \"@llvm-project//llvm:llvm-ar-lib\"),\n    \"cgdata\": struct(bin_name = \"llvm-cgdata\", lib = \"@llvm-project//llvm:llvm-cgdata-lib\"),\n    \"cxxfilt\": struct(bin_name = \"llvm-cxxfilt\", lib = \"@llvm-project//llvm:llvm-cxxfilt-lib\"),\n    \"debuginfod-find\": struct(bin_name = \"llvm-debuginfod-find\", lib = \"@llvm-project//llvm:llvm-debuginfod-find-lib\"),\n    \"dsymutil\": struct(bin_name = \"dsymutil\", lib = \"@llvm-project//llvm:dsymutil-lib\"),\n    \"dwp\": struct(bin_name = \"llvm-dwp\", lib = \"@llvm-project//llvm:llvm-dwp-lib\"),\n    \"gsymutil\": struct(bin_name = \"llvm-gsymutil\", lib = \"@llvm-project//llvm:llvm-gsymutil-lib\"),\n    \"ifs\": struct(bin_name = \"llvm-ifs\", lib = \"@llvm-project//llvm:llvm-ifs-lib\"),\n    \"libtool-darwin\": struct(bin_name = \"llvm-libtool-darwin\", lib = \"@llvm-project//llvm:llvm-libtool-darwin-lib\"),\n    \"lipo\": struct(bin_name = \"llvm-lipo\", lib = \"@llvm-project//llvm:llvm-lipo-lib\"),\n    \"ml\": struct(bin_name = \"llvm-ml\", lib = \"@llvm-project//llvm:llvm-ml-lib\"),\n    \"mt\": struct(bin_name = \"llvm-mt\", lib = \"@llvm-project//llvm:llvm-mt-lib\"),\n    \"nm\": struct(bin_name = \"llvm-nm\", lib = \"@llvm-project//llvm:llvm-nm-lib\"),\n    \"objcopy\": struct(bin_name = \"llvm-objcopy\", lib = \"@llvm-project//llvm:llvm-objcopy-lib\"),\n    \"objdump\": struct(bin_name = \"llvm-objdump\", lib = \"@llvm-project//llvm:llvm-objdump-lib\"),\n    \"rc\": struct(bin_name = \"llvm-rc\", lib = \"@llvm-project//llvm:llvm-rc-lib\"),\n    \"readobj\": struct(bin_name = \"llvm-readobj\", lib = \"@llvm-project//llvm:llvm-readobj-lib\"),\n    \"sancov\": struct(bin_name = \"sancov\", lib = \"@llvm-project//llvm:sancov-lib\"),\n    \"size\": struct(bin_name = \"llvm-size\", lib = \"@llvm-project//llvm:llvm-size-lib\"),\n    \"symbolizer\": struct(bin_name = \"llvm-symbolizer\", lib = \"@llvm-project//llvm:llvm-symbolizer-lib\"),\n}\n\n# A collection of additional alias names that should be available for the main\n# tools. The key is the main tool with the support for these names, followed by\n# a list of the aliased names.\n#\n# Note that we don't track separate binary names for the alias names as those\n# are always formed by prepending `llvm-` for the aliases.\nLLVM_TOOL_ALIASES = {\n    \"ar\": [\"ranlib\", \"lib\", \"dlltool\"],\n    \"objcopy\": [\"bitcode-strip\", \"install-name-tool\", \"strip\"],\n    \"objdump\": [\"otool\"],\n    \"rc\": [\"windres\"],\n    \"readobj\": [\"readelf\"],\n    \"symbolizer\": [\"addr2line\"],\n}\n\n_DEF_FILE_TEMPLATE = \"\"\"\n// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// This is a generated X-macro header for defining LLVM tools. It does not use\n// `#include` guards, and instead is designed to be `#include`ed after the\n// x-macro is defined in order for its inclusion to expand to the desired\n// output. Macro definitions are cleaned up at the end of this file.\n//\n// Each X-macro takes four arguments:\n// - `Id` is the identifier-shaped PascalCased tool name.\n// - `Name` is a string literal of the tool name.\n// - `BinName` is a string literal of the binary name of the tool when installed\n//    as a stand-alone command line tool.\n// - `MainFn` is the function symbol name used to run the tool as-if its `main`.\n//\n// There are three X-macros available:\n// - `CARBON_LLVM_TOOL` is available for every tool.\n//   - `CARBON_LLVM_MAIN_TOOL` is available for each tool with a distinct\n//     `MainFn` symbol name.\n//   - `CARBON_LLVM_ALIAS_TOOL` is available for each tool that is an alias of\n//     some other tool. It's `MainFn` will be the alias-target symbol name.\n//\n// See toolchain/driver/llvm_tools.bzl for more details.\n\n#ifndef CARBON_LLVM_TOOL\n#define CARBON_LLVM_TOOL(Id, Name, BinName, MainFn)\n#endif\n\n#ifndef CARBON_LLVM_MAIN_TOOL\n#define CARBON_LLVM_MAIN_TOOL(Id, Name, BinName, MainFn) \\\\\n  CARBON_LLVM_TOOL(Id, Name, BinName, MainFn)\n#endif\n\n#ifndef CARBON_LLVM_ALIAS_TOOL\n#define CARBON_LLVM_ALIAS_TOOL(Id, Name, BinName, MainFn) \\\\\n  CARBON_LLVM_TOOL(Id, Name, BinName, MainFn)\n#endif\n\n{}\n\n#undef CARBON_LLVM_TOOL\n#undef CARBON_LLVM_MAIN_TOOL\n#undef CARBON_LLVM_ALIAS_TOOL\n\"\"\"\n\n_DEF_MACRO_TEMPLATE = \"\"\"\nCARBON_LLVM_{kind}TOOL({id}, \"{name}\", \"{bin_name}\", {main_fn})\n\"\"\".strip()\n\ndef _build_def_macro(kind, name, bin_name, main_info):\n    id = \"\".join([w.title() for w in name.split(\"-\")])\n    main_fn = main_info.bin_name.replace(\"-\", \"_\") + \"_main\"\n    return _DEF_MACRO_TEMPLATE.format(\n        kind = kind,\n        id = id,\n        name = name,\n        bin_name = bin_name,\n        main_fn = main_fn,\n    )\n\ndef _generate_llvm_tools_def_rule(ctx):\n    def_lines = []\n\n    for name, tool_info in LLVM_MAIN_TOOLS.items():\n        def_lines.append(_build_def_macro(\"MAIN_\", name, tool_info.bin_name, tool_info))\n\n    for target, aliases in LLVM_TOOL_ALIASES.items():\n        tool_info = LLVM_MAIN_TOOLS[target]\n        for alias in aliases:\n            bin_name = \"llvm-\" + alias\n            def_lines.append(_build_def_macro(\"ALIAS_\", alias, bin_name, tool_info))\n\n    def_file = ctx.actions.declare_file(ctx.label.name)\n    ctx.actions.write(def_file, _DEF_FILE_TEMPLATE.format(\"\\n\".join(def_lines)))\n    return [DefaultInfo(files = depset([def_file]))]\n\ngenerate_llvm_tools_def_rule = rule(\n    implementation = _generate_llvm_tools_def_rule,\n    attrs = {},\n)\n\ndef generate_llvm_tools_def(name, out, **kwargs):\n    \"\"\"Generates the LLVM tools `.def` file.\n\n    This first generates the `.def` file into the `out` filename, and then\n    synthesizes a `cc_library` rule exporting that file in its `textual_hdrs`.\n\n    The `cc_library` rule name is the provided `name` and should be depended on\n    by code that includes the generated file. The `kwargs` are expanded into the\n    `cc_library` in case other attributes need to be configured there.\n\n    The two-step process is necessary to avoid trying to compile or otherwise\n    process the generated file as something other than a textual header.\n    \"\"\"\n    generate_llvm_tools_def_rule(name = out)\n    cc_library(\n        name = name,\n        textual_hdrs = [out],\n        **kwargs\n    )\n"
  },
  {
    "path": "toolchain/base/llvm_tools.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/llvm_tools.h\"\n\n#include \"common/command_line.h\"\n\n// NOLINTBEGIN(readability-identifier-naming): External library name.\n#define CARBON_LLVM_MAIN_TOOL(Identifier, Name, BinName, MainFn)              \\\n  extern auto MainFn(int argc, char** argv, const llvm::ToolContext& context) \\\n      -> int;\n#include \"toolchain/base/llvm_tools.def\"\n// NOLINTEND(readability-identifier-naming): External library name.\n\nnamespace Carbon {\n\nCARBON_DEFINE_ENUM_CLASS_NAMES(LLVMTool) {\n#define CARBON_LLVM_TOOL(Identifier, Name, BinName, MainFn) Name,\n#include \"toolchain/base/llvm_tools.def\"\n};\n\nconstexpr llvm::StringLiteral LLVMTool::BinNames[] = {\n#define CARBON_LLVM_TOOL(Identifier, Name, BinName, MainFn) BinName,\n#include \"toolchain/base/llvm_tools.def\"\n};\n\nconstexpr LLVMTool::MainFnT* LLVMTool::MainFns[] = {\n#define CARBON_LLVM_TOOL(Identifier, Name, BinName, MainFn) &::MainFn,\n#include \"toolchain/base/llvm_tools.def\"\n};\n\nconstexpr CommandLine::CommandInfo LLVMTool::SubcommandInfos[] = {\n#define CARBON_LLVM_TOOL(Identifier, Name, BinName, MainFn) \\\n  {.name = Name,                                            \\\n   .help = \"Runs the LLVM \" Name                            \\\n           \" command line tool with the provided arguments.\"},\n#include \"toolchain/base/llvm_tools.def\"\n};\n\n}  // namespace Carbon\n"
  },
  {
    "path": "toolchain/base/llvm_tools.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_LLVM_TOOLS_H_\n#define CARBON_TOOLCHAIN_BASE_LLVM_TOOLS_H_\n\n#include <cstdint>\n\n#include \"common/command_line.h\"\n#include \"common/enum_base.h\"\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/LLVMDriver.h\"\n\nnamespace Carbon {\n\nCARBON_DEFINE_RAW_ENUM_CLASS(LLVMTool, uint8_t) {\n#define CARBON_LLVM_TOOL(Identifier, Name, BinName, MainFn) \\\n  CARBON_RAW_ENUM_ENUMERATOR(Identifier)\n#include \"toolchain/base/llvm_tools.def\"\n};\n\n// An enum-like class for each of the LLVM tools.\n//\n// This can be used like an enum to track a specific one of the LLVM tools. It\n// also has a collection of methods to access various aspects of the tools\n// themselves, including the symbol used to invoke the given tool.\n//\n// The instances of this class are generated from `llvm_tools.bzl`, see that\n// file for more details.\nclass LLVMTool : public CARBON_ENUM_BASE(LLVMTool) {\n public:\n#define CARBON_LLVM_TOOL(Identifier, Name, BinName, MainFn) \\\n  CARBON_ENUM_CONSTANT_DECL(Identifier)\n#include \"toolchain/base/llvm_tools.def\"\n\n  static const llvm::ArrayRef<LLVMTool> Tools;\n\n  using MainFnT = auto(int argc, char** argv, const llvm::ToolContext& context)\n      -> int;\n\n  using EnumBase::EnumBase;\n\n  auto bin_name() const -> llvm::StringLiteral { return BinNames[AsInt()]; }\n\n  auto main_fn() const -> MainFnT* { return MainFns[AsInt()]; }\n\n  auto subcommand_info() const -> const CommandLine::CommandInfo& {\n    return SubcommandInfos[AsInt()];\n  }\n\n private:\n  static const LLVMTool ToolsStorage[];\n\n  static const llvm::StringLiteral BinNames[];\n  static MainFnT* const MainFns[];\n\n  static const CommandLine::CommandInfo SubcommandInfos[];\n};\n\n#define CARBON_LLVM_TOOL(Identifier, Name, BinName, MainFn) \\\n  CARBON_ENUM_CONSTANT_DEFINITION(LLVMTool, Identifier)\n#include \"toolchain/base/llvm_tools.def\"\n\ninline constexpr LLVMTool LLVMTool::ToolsStorage[] = {\n#define CARBON_LLVM_TOOL(Identifier, Name, BinName, MainFn) \\\n  LLVMTool::Identifier,\n#include \"toolchain/base/llvm_tools.def\"\n};\ninline constexpr llvm::ArrayRef<LLVMTool> LLVMTool::Tools = ToolsStorage;\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_LLVM_TOOLS_H_\n"
  },
  {
    "path": "toolchain/base/mem_usage.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_MEM_USAGE_H_\n#define CARBON_TOOLCHAIN_BASE_MEM_USAGE_H_\n\n#include <cstdint>\n\n#include \"common/map.h\"\n#include \"common/set.h\"\n#include \"llvm/ADT/STLFunctionalExtras.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/FormatVariadic.h\"\n#include \"toolchain/base/yaml.h\"\n\nnamespace Carbon {\n\n// Helps track memory usage for a compile.\n//\n// Users will mix `Add` and `Collect` calls, using `ConcatLabel` to label\n// allocation sources. Typically we'll collect stats for growable, potentially\n// large data types (such as `SmallVector`), ignoring small fixed-size members\n// (such as pointers or `int32_t`).\n//\n// For example:\n//\n//   auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const\n//       -> void {\n//     // Explicit tracking.\n//     mem_usage.Add(MemUsage::ConcatLabel(label, \"data_\"), data_.used_bytes(),\n//                   data_.reserved_bytes());\n//     // Common library types like `Map` and `llvm::SmallVector` have\n//     // type-specific support.\n//     mem_usage.Add(MemUsage::Concat(label, \"array_\"), array_);\n//     // Implementing `CollectMemUsage` allows use with the same interface.\n//     mem_usage.Collect(MemUsage::Concat(label, \"obj_\"), obj_);\n//   }\nclass MemUsage {\n public:\n  // Adds tracking for used and reserved bytes, paired with the given label.\n  auto Add(std::string label, int64_t used_bytes, int64_t reserved_bytes)\n      -> void {\n    mem_usage_.push_back({.label = std::move(label),\n                          .used_bytes = used_bytes,\n                          .reserved_bytes = reserved_bytes});\n  }\n\n  // Adds memory usage for a `llvm::BumpPtrAllocator`.\n  auto Collect(std::string label, const llvm::BumpPtrAllocator& allocator)\n      -> void {\n    Add(std::move(label), allocator.getBytesAllocated(),\n        allocator.getTotalMemory());\n  }\n\n  // Adds memory usage for a `Map`.\n  template <typename KeyT, typename ValueT, ssize_t SmallSize,\n            typename KeyContextT>\n  auto Collect(std::string label,\n               const Map<KeyT, ValueT, SmallSize, KeyContextT>& map,\n               KeyContextT key_context = KeyContextT()) -> void {\n    // These don't track used bytes, so we set the same value for used and\n    // reserved bytes.\n    auto bytes = map.ComputeMetrics(key_context).storage_bytes;\n    Add(std::move(label), bytes, bytes);\n  }\n\n  // Adds memory usage for a `Set`.\n  template <typename KeyT, ssize_t SmallSize, typename KeyContextT>\n  auto Collect(std::string label, const Set<KeyT, SmallSize, KeyContextT>& set,\n               KeyContextT key_context = KeyContextT()) -> void {\n    // These don't track used bytes, so we set the same value for used and\n    // reserved bytes.\n    auto bytes = set.ComputeMetrics(key_context).storage_bytes;\n    Add(std::move(label), bytes, bytes);\n  }\n\n  // Adds memory usage of an array's data. This ignores the possible overhead of\n  // a SmallVector's in-place storage; if it's used, it's going to be tiny\n  // relative to scaling memory costs.\n  //\n  // This uses SmallVector in order to get proper inference for T, which\n  // ArrayRef misses.\n  template <typename T>\n  auto Collect(std::string label, const llvm::SmallVectorImpl<T>& array)\n      -> void {\n    Add(std::move(label), array.size_in_bytes(), array.capacity_in_bytes());\n  }\n\n  // Adds memory usage for an object that provides `CollectMemUsage`.\n  //\n  // The expected signature of `CollectMemUsage` is above, in MemUsage class\n  // comments.\n  template <typename T>\n    requires requires(MemUsage& mem_usage, llvm::StringRef label,\n                      const T& arg) {\n      { arg.CollectMemUsage(mem_usage, label) };\n    }\n  auto Collect(std::string label, const T& arg) -> void {\n    arg.CollectMemUsage(*this, label);\n  }\n\n  // Constructs a label for memory usage, handling the `.` concatenation.\n  // We don't expect much depth in labels per-call.\n  static auto ConcatLabel(llvm::StringRef label, llvm::StringRef child_label)\n      -> std::string {\n    return llvm::formatv(\"{0}.{1}\", label, child_label);\n  }\n  static auto ConcatLabel(llvm::StringRef label, llvm::StringRef child_label1,\n                          llvm::StringRef child_label2) -> std::string {\n    return llvm::formatv(\"{0}.{1}.{2}\", label, child_label1, child_label2);\n  }\n\n  auto OutputYaml(llvm::StringRef filename) const -> Yaml::OutputMapping {\n    // Explicitly copy the filename.\n    return Yaml::OutputMapping([&, filename](Yaml::OutputMapping::Map map) {\n      map.Add(\"filename\", filename);\n      int64_t total_used = 0;\n      int64_t total_reserved = 0;\n      for (const auto& entry : mem_usage_) {\n        total_used += entry.used_bytes;\n        total_reserved += entry.reserved_bytes;\n        map.Add(entry.label,\n                Yaml::OutputMapping([&](Yaml::OutputMapping::Map byte_map) {\n                  byte_map.Add(\"used_bytes\", entry.used_bytes);\n                  byte_map.Add(\"reserved_bytes\", entry.reserved_bytes);\n                }));\n      }\n      map.Add(\"Total\",\n              Yaml::OutputMapping([&](Yaml::OutputMapping::Map byte_map) {\n                byte_map.Add(\"used_bytes\", total_used);\n                byte_map.Add(\"reserved_bytes\", total_reserved);\n              }));\n    });\n  }\n\n private:\n  // Memory usage for a specific label.\n  struct Entry {\n    std::string label;\n    int64_t used_bytes;\n    int64_t reserved_bytes;\n  };\n\n  // The accumulated data on memory usage.\n  llvm::SmallVector<Entry> mem_usage_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_MEM_USAGE_H_\n"
  },
  {
    "path": "toolchain/base/relational_value_store.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_RELATIONAL_VALUE_STORE_H_\n#define CARBON_TOOLCHAIN_BASE_RELATIONAL_VALUE_STORE_H_\n\n#include <optional>\n\n#include \"common/check.h\"\n#include \"toolchain/base/value_store.h\"\n#include \"toolchain/base/value_store_types.h\"\n\nnamespace Carbon {\n\n// A ValueStore that builds a 1:1 relationship between two IDs.\n// * `RelatedStoreT` represents a related ValueStore with ids that can be used\n//   to find values in this store.\n// * `IdT` is the actual ID of values in this store, and `IdT::ValueType` is the\n//   value type being stored.\n//\n// The value store builds a mapping so that either ID can be used later to find\n// a value. And the user can query if a related `RelatedStoreT::IdType` has been\n// used to add a value to the store or not.\n//\n// When adding to the store, the user provides the related\n// `RelatedStoreT::IdType` along with the value being stored, and gets back the\n// ID of the value in the store.\n//\n// This store requires more storage space than normal ValueStore does, as it\n// requires storing a bit for presence of each `RelatedStore::IdType`. And it\n// allocates memory for values for all IDs up largest ID present in the store,\n// even if they are not yet used.\ntemplate <typename RelatedStoreT, typename IdT, typename ValueT>\nclass RelationalValueStore {\n public:\n  using RelatedIdType = RelatedStoreT::IdType;\n  using RelatedIdTagType = RelatedStoreT::IdTagType;\n  using RelatedTagIdType = RelatedIdTagType::TagIdType;\n  using ValueType = ValueStoreTypes<ValueT>::ValueType;\n  using ConstRefType = ValueStoreTypes<ValueT>::ConstRefType;\n\n  explicit RelationalValueStore(const RelatedStoreT* related_store)\n      : values_(related_store->GetIdTag()), related_store_(related_store) {}\n\n  // Given the related ID and a value, stores the value and returns a mapped ID\n  // to reference it in the store.\n  auto Add(RelatedIdType related_id, ValueType value) -> IdT {\n    auto related_index = related_store_->GetRawIndex(related_id);\n    values_.Resize(related_index + 1, std::nullopt);\n    auto& opt = values_.Get(related_id);\n    CARBON_CHECK(!opt.has_value(),\n                 \"Add with `related_id` that was already added to the store\");\n    opt.emplace(std::move(value));\n    return IdT(related_store_->GetIdTag().Apply(related_index).index);\n  }\n\n  // Returns the ID of a value in the store if the `related_id` was previously\n  // used to add a value to the store, or None.\n  auto TryGetId(RelatedIdType related_id) const -> IdT {\n    auto related_index = related_store_->GetRawIndex(related_id);\n    if (static_cast<size_t>(related_index) >= values_.size()) {\n      return IdT::None;\n    }\n    auto& opt = values_.Get(related_id);\n    if (!opt.has_value()) {\n      return IdT::None;\n    }\n    return IdT(related_store_->GetIdTag().Apply(related_index).index);\n  }\n\n  // Returns a value for an ID.\n  auto Get(IdT id) const -> ConstRefType {\n    return *values_.Get(RelatedIdType(id.index));\n  }\n\n private:\n  ValueStore<RelatedIdType, std::optional<ValueType>, Tag<RelatedTagIdType>>\n      values_;\n  const RelatedStoreT* related_store_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_RELATIONAL_VALUE_STORE_H_\n"
  },
  {
    "path": "toolchain/base/runtimes_build_info.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"Provides variables and rules to work with Clang's runtime library sources.\n\nThese are organized into groups based on the Clang runtimes providing them and\nhow they are built:\n- CRT: The C language runtimes not provided by the C standard library, currently\n  just infrastructure for global initialization and teardown.\n- Builtins: The compiler builtins library mirroring `libgcc` that provides\n  function definitions for operations not reliably available in hardware but\n  needed by Clang.\n- Libc++ and libc++abi: The C++ standard library and its ABI components.\n- Libunwind: The unwinding library.\n\nFuture runtimes we plan to add support for but not yet included:\n- Sanitizers\n- Profiling runtimes\n\"\"\"\n\nload(\"@llvm-project//:vars.bzl\", \"LLVM_VERSION_MAJOR\")\nload(\"@llvm-project//compiler-rt:compiler-rt.bzl\", \"builtins_copts\", \"crt_copts\")\nload(\"@llvm-project//libcxx:libcxx_library.bzl\", \"libcxx_and_abi_copts\")\nload(\"@llvm-project//libunwind:libunwind_library.bzl\", \"libunwind_copts\")\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_library\")\n\nCRT_FILES = {\n    \"crtbegin_src\": \"@llvm-project//compiler-rt:builtins_crtbegin_src\",\n    \"crtend_src\": \"@llvm-project//compiler-rt:builtins_crtend_src\",\n}\n\nBUILTINS_SRCS_FILEGROUPS = [\n    \"@llvm-project//compiler-rt:builtins_aarch64_srcs\",\n    \"@llvm-project//compiler-rt:builtins_i386_srcs\",\n    \"@llvm-project//compiler-rt:builtins_x86_64_srcs\",\n]\n\nBUILTINS_TEXTUAL_SRCS_FILEGROUPS = [\n    \"@llvm-project//compiler-rt:builtins_aarch64_textual_srcs\",\n    \"@llvm-project//compiler-rt:builtins_i386_textual_srcs\",\n    \"@llvm-project//compiler-rt:builtins_x86_64_textual_srcs\",\n]\n\nRUNTIMES_HDRS_FILEGROUPS = [\n    \"@llvm-project//libc:libcxx_shared_headers_hdrs\",\n    \"@llvm-project//libcxx:libcxx_hdrs\",\n    \"@llvm-project//libcxxabi:libcxxabi_hdrs\",\n    \"@llvm-project//libunwind:libunwind_hdrs\",\n]\n\nRUNTIMES_SRCS_FILEGROUPS = [\n    \"@llvm-project//libcxx:libcxx_linux_srcs\",\n    \"@llvm-project//libcxx:libcxx_macos_srcs\",\n    \"@llvm-project//libcxx:libcxx_win32_srcs\",\n    \"@llvm-project//libcxxabi:libcxxabi_srcs\",\n    \"@llvm-project//libunwind:libunwind_srcs\",\n]\n\nRUNTIMES_TEXTUAL_SRCS_FILEGROUPS = [\n    \"@llvm-project//libcxxabi:libcxxabi_textual_srcs\",\n]\n\nRUNTIMES_PREFIXES = {\n    \"libcxx_hdrs\": \"libcxx/\",\n    \"libcxx_linux_srcs\": \"libcxx/\",\n    \"libcxx_macos_srcs\": \"libcxx/\",\n    \"libcxx_shared_headers_hdrs\": \"libc/internal/\",\n    \"libcxx_win32_srcs\": \"libcxx/\",\n    \"libcxxabi_hdrs\": \"libcxxabi/\",\n    \"libcxxabi_srcs\": \"libcxxabi/\",\n    \"libcxxabi_textual_srcs\": \"libcxxabi/\",\n    \"libunwind_hdrs\": \"libunwind/\",\n    \"libunwind_srcs\": \"libunwind/\",\n}\n\ndef _get_name(target):\n    return target.split(\":\")[1]\n\ndef _format_one_per_line(list):\n    return \"\\n\" + \"\\n\".join([\n        '    \"{0}\",'.format(item)\n        for item in list\n    ]) + \"\\n\"\n\ndef _builtins_path(file):\n    \"\"\"Returns the install path for a file in CompilerRT's builtins library.\"\"\"\n    path = file.path\n\n    # Skip to the relative path below the workspace root.\n    path = path.rpartition(file.owner.workspace_root + \"/\")[2]\n\n    # And now we can predictably remove the `compiler-rt/lib` prefix.\n    path = path.removeprefix(\"compiler-rt/lib/\")\n    if not path.startswith(\"builtins/\"):\n        fail(\"Not a builtins-relative path for: {0}\".format(file.path))\n    return path\n\ndef _runtimes_path(file):\n    \"\"\"Returns the install path for a file in a normal runtimes library.\"\"\"\n    return file.owner.name\n\ndef _get_path(file_attr, to_path_fn):\n    files = file_attr[DefaultInfo].files.to_list()\n    if len(files) > 1:\n        fail(\"Expected a single file and got {0} files.\".format(len(files)))\n\n    return '\"{0}\"'.format(to_path_fn(files[0]))\n\ndef _get_paths(files_attr, to_path_fn, prefix = \"\"):\n    files = []\n    for src in files_attr:\n        files.extend(src[DefaultInfo].files.to_list())\n        files.extend(src[DefaultInfo].default_runfiles.files.to_list())\n\n    return _format_one_per_line([\n        \"{0}{1}\".format(prefix, to_path_fn(f))\n        for f in files\n    ])\n\ndef _get_substitutions(ctx):\n    key_attr = lambda k: getattr(ctx.attr, \"_\" + k)\n    return {\n        \"BUILTINS_COPTS\": _format_one_per_line(builtins_copts),\n        \"CRT_COPTS\": _format_one_per_line(crt_copts),\n        \"LIBCXX_AND_ABI_COPTS\": _format_one_per_line(libcxx_and_abi_copts),\n        \"LIBUNWIND_COPTS\": _format_one_per_line(libunwind_copts),\n        \"LLVM_VERSION_MAJOR\": LLVM_VERSION_MAJOR,\n    } | {\n        k.upper(): _get_path(key_attr(k), _builtins_path)\n        for k in CRT_FILES.keys()\n    } | {\n        name.upper(): _get_paths(key_attr(name), _builtins_path)\n        for name in [_get_name(g) for g in (\n            BUILTINS_SRCS_FILEGROUPS + BUILTINS_TEXTUAL_SRCS_FILEGROUPS\n        )]\n    } | {\n        # Other runtimes are installed under separate directories named the\n        # same as their key.\n        name.upper(): _get_paths(\n            key_attr(name),\n            _runtimes_path,\n            RUNTIMES_PREFIXES[name],\n        )\n        for name in [_get_name(g) for g in (\n            RUNTIMES_HDRS_FILEGROUPS + RUNTIMES_SRCS_FILEGROUPS +\n            RUNTIMES_TEXTUAL_SRCS_FILEGROUPS\n        )]\n    }\n\n_common_runtimes_rule_attrs = {\n    \"_\" + k: attr.label(default = v, allow_single_file = True)\n    for k, v in CRT_FILES.items()\n} | {\n    \"_\" + _get_name(g): attr.label_list(default = [g], allow_files = True)\n    for g in (\n        BUILTINS_SRCS_FILEGROUPS +\n        BUILTINS_TEXTUAL_SRCS_FILEGROUPS +\n        RUNTIMES_HDRS_FILEGROUPS +\n        RUNTIMES_SRCS_FILEGROUPS +\n        RUNTIMES_TEXTUAL_SRCS_FILEGROUPS\n    )\n}\n\ndef _generate_runtimes_build_info_h_rule(ctx):\n    h_file = ctx.actions.declare_file(ctx.label.name)\n    ctx.actions.expand_template(\n        template = ctx.file._template_file,\n        output = h_file,\n        substitutions = _get_substitutions(ctx),\n    )\n    return [DefaultInfo(files = depset([h_file]))]\n\ngenerate_runtimes_build_info_h = rule(\n    implementation = _generate_runtimes_build_info_h_rule,\n    attrs = _common_runtimes_rule_attrs | {\n        \"_template_file\": attr.label(\n            default = \"runtimes_build_info.tpl.h\",\n            allow_single_file = True,\n        ),\n    },\n)\n\ndef generate_runtimes_build_info_cc_library(name, deps = [], **kwargs):\n    \"\"\"Generates a `runtimes_build_info.h` header and a `cc_library` rule.\n\n    This first generates the header file with variables describing the runtimes\n    build info from Clang, and then a `cc_library` that exports that header.\n\n    The `cc_library` rule name is the provided `name` and should be depended on\n    by code that includes the generated header. The `kwargs` are expanded into\n    the `cc_library` in case other attributes need to be configured there.\n    \"\"\"\n    generate_runtimes_build_info_h(name = \"runtimes_build_info.h\")\n    cc_library(\n        name = name,\n        hdrs = [\"runtimes_build_info.h\"],\n        deps = [\n            # For StringRef.h\n            \"@llvm-project//llvm:Support\",\n        ] + deps,\n        **kwargs\n    )\n\ndef _generate_runtimes_build_vars_rule(ctx):\n    file = ctx.actions.declare_file(ctx.label.name)\n    ctx.actions.expand_template(\n        template = ctx.file._template_file,\n        output = file,\n        substitutions = _get_substitutions(ctx),\n    )\n    return [DefaultInfo(files = depset([file]))]\n\ngenerate_runtimes_build_vars = rule(\n    implementation = _generate_runtimes_build_vars_rule,\n    attrs = _common_runtimes_rule_attrs | {\n        \"_template_file\": attr.label(\n            default = \"runtimes_build_vars.tpl.bzl\",\n            allow_single_file = True,\n        ),\n    },\n)\n"
  },
  {
    "path": "toolchain/base/runtimes_build_info.tpl.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// Header file template expanded with strings describing build info for Carbon's\n// runtimes.\n//\n// See toolchain/base/runtimes_build_info.bzl for more details.\n\n#ifndef CARBON_TOOLCHAIN_BASE_RUNTIMES_BUILD_INFO_TPL_H_\n#define CARBON_TOOLCHAIN_BASE_RUNTIMES_BUILD_INFO_TPL_H_\n\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon::RuntimesBuildInfo {\n\ninline constexpr llvm::StringLiteral CrtBegin = CRTBEGIN_SRC;\ninline constexpr llvm::StringLiteral CrtEnd = CRTEND_SRC;\n\ninline constexpr llvm::StringLiteral CrtCopts[] = {CRT_COPTS};\n\n// Prevent wrapping these lines -- the expansion of the variables will add line\n// breaks.\n//\n// clang-format off\ninline constexpr llvm::StringLiteral BuiltinsAarch64Srcs[] = {BUILTINS_AARCH64_SRCS};\n// NOLINTNEXTLINE(readability-identifier-naming)\ninline constexpr llvm::StringLiteral BuiltinsX86_64Srcs[] = {BUILTINS_X86_64_SRCS};\ninline constexpr llvm::StringLiteral BuiltinsI386Srcs[] = {BUILTINS_I386_SRCS};\n// clang-format on\n\ninline constexpr llvm::StringLiteral BuiltinsCopts[] = {BUILTINS_COPTS};\n\ninline constexpr llvm::StringLiteral LibcxxLinuxSrcs[] = {LIBCXX_LINUX_SRCS};\ninline constexpr llvm::StringLiteral LibcxxMacosSrcs[] = {LIBCXX_MACOS_SRCS};\ninline constexpr llvm::StringLiteral LibcxxWin32Srcs[] = {LIBCXX_WIN32_SRCS};\ninline constexpr llvm::StringLiteral LibcxxabiSrcs[] = {LIBCXXABI_SRCS};\ninline constexpr llvm::StringLiteral LibcxxCopts[] = {LIBCXX_AND_ABI_COPTS};\n\ninline constexpr llvm::StringLiteral LibunwindSrcs[] = {LIBUNWIND_SRCS};\ninline constexpr llvm::StringLiteral LibunwindCopts[] = {LIBUNWIND_COPTS};\n\n}  // namespace Carbon::RuntimesBuildInfo\n\n#endif  // CARBON_TOOLCHAIN_BASE_RUNTIMES_BUILD_INFO_TPL_H_\n"
  },
  {
    "path": "toolchain/base/runtimes_build_vars.tpl.bzl",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n\"\"\"A Starlark file exporting Carbon toolchain runtimes build info variables.\n\nThis file is a template that is expanded into a starlark file for the installed\nCarbon toolchain that provides a trivial textual definition of the relevant\nbuild info in variables.\n\"\"\"\n\nllvm_version_major = LLVM_VERSION_MAJOR\n\ncrtbegin_src = CRTBEGIN_SRC\ncrtend_src = CRTEND_SRC\n\ncrt_copts = [CRT_COPTS]\n\nbuiltins_aarch64_srcs = [BUILTINS_AARCH64_SRCS]\nbuiltins_x86_64_srcs = [BUILTINS_X86_64_SRCS]\nbuiltins_i386_srcs = [BUILTINS_I386_SRCS]\n\nbuiltins_aarch64_textual_srcs = [BUILTINS_AARCH64_TEXTUAL_SRCS]\nbuiltins_x86_64_textual_srcs = [BUILTINS_X86_64_TEXTUAL_SRCS]\nbuiltins_i386_textual_srcs = [BUILTINS_I386_TEXTUAL_SRCS]\n\nbuiltins_copts = [BUILTINS_COPTS]\n\nlibcxx_hdrs = [LIBCXX_HDRS]\nlibcxx_linux_srcs = [LIBCXX_LINUX_SRCS]\nlibcxx_macos_srcs = [LIBCXX_MACOS_SRCS]\nlibcxx_win32_srcs = [LIBCXX_WIN32_SRCS]\n\nlibc_internal_libcxx_hdrs = [LIBCXX_SHARED_HEADERS_HDRS]\n\nlibcxxabi_hdrs = [LIBCXXABI_HDRS]\nlibcxxabi_srcs = [LIBCXXABI_SRCS]\nlibcxxabi_textual_srcs = [LIBCXXABI_TEXTUAL_SRCS]\n\nlibcxx_copts = [LIBCXX_AND_ABI_COPTS]\n\nlibunwind_hdrs = [LIBUNWIND_HDRS]\nlibunwind_srcs = [LIBUNWIND_SRCS]\n\nlibunwind_copts = [LIBUNWIND_COPTS]\n"
  },
  {
    "path": "toolchain/base/shared_value_stores.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_SHARED_VALUE_STORES_H_\n#define CARBON_TOOLCHAIN_BASE_SHARED_VALUE_STORES_H_\n\n#include \"llvm/ADT/APFloat.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"toolchain/base/canonical_value_store.h\"\n#include \"toolchain/base/int.h\"\n#include \"toolchain/base/mem_usage.h\"\n#include \"toolchain/base/value_ids.h\"\n#include \"toolchain/base/value_store.h\"\n#include \"toolchain/base/yaml.h\"\n\nnamespace Carbon {\n\n// Stores that will be used across compiler phases for a given compilation unit.\n// This is provided mainly so that they don't need to be passed separately.\nclass SharedValueStores : public Yaml::Printable<SharedValueStores> {\n public:\n  // Provide types that can be used by APIs to forward access to these stores.\n  using IntStore = IntStore;\n  using RealStore = ValueStore<RealId, Real>;\n  using FloatStore = CanonicalValueStore<FloatId, llvm::APFloat>;\n  using IdentifierStore = CanonicalValueStore<IdentifierId, llvm::StringRef>;\n  using StringLiteralStore =\n      CanonicalValueStore<StringLiteralValueId, llvm::StringRef>;\n\n  explicit SharedValueStores() = default;\n\n  // Not copyable or movable.\n  SharedValueStores(const SharedValueStores&) = delete;\n  auto operator=(const SharedValueStores&) -> SharedValueStores& = delete;\n\n  auto identifiers() -> IdentifierStore& { return identifiers_; }\n  auto identifiers() const -> const IdentifierStore& { return identifiers_; }\n  auto ints() -> IntStore& { return ints_; }\n  auto ints() const -> const IntStore& { return ints_; }\n  auto reals() -> RealStore& { return reals_; }\n  auto reals() const -> const RealStore& { return reals_; }\n  auto floats() -> FloatStore& { return floats_; }\n  auto floats() const -> const FloatStore& { return floats_; }\n  auto string_literal_values() -> StringLiteralStore& {\n    return string_literals_;\n  }\n  auto string_literal_values() const -> const StringLiteralStore& {\n    return string_literals_;\n  }\n\n  auto OutputYaml(std::optional<llvm::StringRef> filename = std::nullopt) const\n      -> Yaml::OutputMapping {\n    return Yaml::OutputMapping([&, filename](Yaml::OutputMapping::Map map) {\n      if (filename) {\n        map.Add(\"filename\", *filename);\n      }\n      map.Add(\"shared_values\",\n              Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {\n                map.Add(\"ints\", ints_.OutputYaml());\n                map.Add(\"reals\", reals_.OutputYaml());\n                map.Add(\"floats\", floats_.OutputYaml());\n                map.Add(\"identifiers\", identifiers_.OutputYaml());\n                map.Add(\"strings\", string_literals_.OutputYaml());\n              }));\n    });\n  }\n\n  // Collects memory usage for the various shared stores.\n  auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const\n      -> void {\n    mem_usage.Collect(MemUsage::ConcatLabel(label, \"ints_\"), ints_);\n    mem_usage.Collect(MemUsage::ConcatLabel(label, \"reals_\"), reals_);\n    mem_usage.Collect(MemUsage::ConcatLabel(label, \"floats_\"), floats_);\n    mem_usage.Collect(MemUsage::ConcatLabel(label, \"identifiers_\"),\n                      identifiers_);\n    mem_usage.Collect(MemUsage::ConcatLabel(label, \"string_literals_\"),\n                      string_literals_);\n  }\n\n private:\n  IntStore ints_;\n  RealStore reals_;\n  FloatStore floats_;\n\n  IdentifierStore identifiers_;\n  StringLiteralStore string_literals_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_SHARED_VALUE_STORES_H_\n"
  },
  {
    "path": "toolchain/base/shared_value_stores_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/shared_value_stores.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include \"common/raw_string_ostream.h\"\n#include \"toolchain/testing/yaml_test_helpers.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing ::testing::ElementsAre;\nusing ::testing::IsEmpty;\nusing ::testing::Pair;\n\nauto MatchSharedValues(testing::Matcher<Yaml::MappingValue> ints,\n                       testing::Matcher<Yaml::MappingValue> reals,\n                       testing::Matcher<Yaml::MappingValue> floats,\n                       testing::Matcher<Yaml::MappingValue> identifiers,\n                       testing::Matcher<Yaml::MappingValue> strings) -> auto {\n  return Yaml::IsYaml(Yaml::Sequence(ElementsAre(Yaml::Mapping(ElementsAre(Pair(\n      \"shared_values\",\n      Yaml::Mapping(ElementsAre(Pair(\"ints\", Yaml::Mapping(ints)),\n                                Pair(\"reals\", Yaml::Mapping(reals)),\n                                Pair(\"floats\", Yaml::Mapping(floats)),\n                                Pair(\"identifiers\", Yaml::Mapping(identifiers)),\n                                Pair(\"strings\", Yaml::Mapping(strings))))))))));\n}\n\nTEST(SharedValueStores, PrintEmpty) {\n  SharedValueStores value_stores;\n  RawStringOstream out;\n  value_stores.Print(out);\n  EXPECT_THAT(\n      Yaml::Value::FromText(out.TakeStr()),\n      MatchSharedValues(IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty(), IsEmpty()));\n}\n\nTEST(SharedValueStores, PrintVals) {\n  SharedValueStores value_stores;\n  llvm::APInt apint(64, 8, /*isSigned=*/true);\n  value_stores.ints().AddSigned(apint);\n  value_stores.ints().AddSigned(llvm::APInt(64, 999'999'999'999));\n  value_stores.reals().Add(\n      Real{.mantissa = apint, .exponent = apint, .is_decimal = true});\n  value_stores.identifiers().Add(\"a\");\n  value_stores.string_literal_values().Add(\"foo'\\\"baz\");\n  RawStringOstream out;\n  value_stores.Print(out);\n\n  EXPECT_THAT(Yaml::Value::FromText(out.TakeStr()),\n              MatchSharedValues(\n                  ElementsAre(Pair(\"ap_int0\", Yaml::Scalar(\"999999999999\"))),\n                  ElementsAre(Pair(\"real0\", Yaml::Scalar(\"8*10^8\"))), IsEmpty(),\n                  ElementsAre(Pair(\"identifier0\", Yaml::Scalar(\"a\"))),\n                  ElementsAre(Pair(\"string0\", Yaml::Scalar(\"foo'\\\"baz\")))));\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "toolchain/base/test_binary.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nauto main() -> int { return 0; }\n"
  },
  {
    "path": "toolchain/base/timings.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_TIMINGS_H_\n#define CARBON_TOOLCHAIN_BASE_TIMINGS_H_\n\n#include <chrono>\n\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"toolchain/base/yaml.h\"\n\nnamespace Carbon {\n\n// Helps track timings for a compile.\nclass Timings {\n public:\n  // Records a timing for a scope, if the timings object is present.\n  class ScopedTiming {\n   public:\n    // The `timings` may be null, in which case the `ScopedTiming` is a no-op.\n    explicit ScopedTiming(Timings* timings, llvm::StringRef label)\n        : timings_(timings),\n          label_(label),\n          start_(timings ? std::chrono::steady_clock::now()\n                         : std::chrono::steady_clock::time_point::min()) {}\n\n    ~ScopedTiming() {\n      if (timings_) {\n        timings_->Add(label_, std::chrono::steady_clock::now() - start_);\n      }\n    }\n\n   private:\n    Timings* timings_;\n    llvm::StringRef label_;\n    std::chrono::steady_clock::time_point start_;\n  };\n\n  // Adds tracking for nanoseconds, paired with the given label.\n  auto Add(llvm::StringRef label, std::chrono::nanoseconds nanoseconds)\n      -> void {\n    timings_.push_back(\n        {.label = std::string(label), .nanoseconds = nanoseconds});\n  }\n\n  auto OutputYaml(llvm::StringRef filename) const -> Yaml::OutputMapping {\n    // Explicitly copy the filename.\n    return Yaml::OutputMapping([&, filename](Yaml::OutputMapping::Map map) {\n      map.Add(\"filename\", filename);\n      map.Add(\"nanoseconds\",\n              Yaml::OutputMapping([&](Yaml::OutputMapping::Map label_map) {\n                std::chrono::nanoseconds total_nanoseconds(0);\n                for (const auto& entry : timings_) {\n                  total_nanoseconds += entry.nanoseconds;\n                  label_map.Add(entry.label, static_cast<int64_t>(\n                                                 entry.nanoseconds.count()));\n                }\n                label_map.Add(\"Total\",\n                              static_cast<int64_t>(total_nanoseconds.count()));\n              }));\n    });\n  }\n\n private:\n  // Timing for a specific label.\n  struct Entry {\n    std::string label;\n    std::chrono::nanoseconds nanoseconds;\n  };\n\n  // The accumulated data on timings.\n  llvm::SmallVector<Entry> timings_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_TIMINGS_H_\n"
  },
  {
    "path": "toolchain/base/value_ids.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_VALUE_IDS_H_\n#define CARBON_TOOLCHAIN_BASE_VALUE_IDS_H_\n\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n#include \"llvm/ADT/APInt.h\"\n#include \"llvm/ADT/StringExtras.h\"\n#include \"llvm/Support/YAMLParser.h\"\n#include \"toolchain/base/index_base.h\"\n\nnamespace Carbon {\n\n// The value of a real literal token.\n//\n// This is either a dyadic fraction (mantissa * 2^exponent) or a decadic\n// fraction (mantissa * 10^exponent).\n//\n// These values are not canonicalized, because we don't expect them to repeat.\n// We use RealIds in SemIR::FloatLiteralValues, and this results in all real\n// literals being distinct constants, even if they represent the same value.\n// TODO: Address this by using a different representation in SemIR.\nstruct Real : public Printable<Real> {\n  auto Print(llvm::raw_ostream& output_stream) const -> void {\n    mantissa.print(output_stream, /*isSigned=*/false);\n    output_stream << \"*\" << (is_decimal ? \"10\" : \"2\") << \"^\" << exponent;\n  }\n\n  // The mantissa, represented as an unsigned integer.\n  llvm::APInt mantissa;\n\n  // The exponent, represented as a signed integer.\n  llvm::APInt exponent;\n\n  // If false, the value is mantissa * 2^exponent.\n  // If true, the value is mantissa * 10^exponent.\n  // TODO: This field increases Real from 32 bytes to 40 bytes. Consider\n  // changing how it's tracked for space savings.\n  bool is_decimal;\n};\n\n// Corresponds to a float value represented by an APFloat. This is used for\n// floating-point values in SemIR.\nstruct FloatId : public IdBase<FloatId> {\n  static constexpr llvm::StringLiteral Label = \"float\";\n  static const FloatId None;\n  using IdBase::IdBase;\n};\ninline constexpr FloatId FloatId::None(FloatId::NoneIndex);\n\n// Corresponds to a Real value.\nstruct RealId : public IdBase<RealId> {\n  // TODO: We don't use Diagnostics::TypeInfo here for layering reasons.\n  struct DiagnosticType {\n    using StorageType = std::string;\n  };\n\n  static constexpr llvm::StringLiteral Label = \"real\";\n  static const RealId None;\n  using IdBase::IdBase;\n};\ninline constexpr RealId RealId::None(RealId::NoneIndex);\n\n// Corresponds to StringRefs for identifiers.\n//\n// `NameId` relies on the values of this type other than `None` all being\n// non-negative.\nstruct IdentifierId : public IdBase<IdentifierId> {\n  static constexpr llvm::StringLiteral Label = \"identifier\";\n  static const IdentifierId None;\n  using IdBase::IdBase;\n};\ninline constexpr IdentifierId IdentifierId::None(IdentifierId::NoneIndex);\n\n// The name of a package, which is either an identifier or the special `Core`\n// package name.\n//\n// TODO: Consider also treating `Main` and `Cpp` as special package names.\nstruct PackageNameId : public IdBase<PackageNameId> {\n  static constexpr llvm::StringLiteral Label = \"package\";\n  static const PackageNameId None;\n  static const PackageNameId Core;\n  static const PackageNameId Cpp;\n\n  // Returns the PackageNameId corresponding to a particular IdentifierId.\n  static auto ForIdentifier(IdentifierId id) -> PackageNameId {\n    return PackageNameId(id.index);\n  }\n\n  using IdBase::IdBase;\n\n  // Returns the IdentifierId corresponding to this PackageNameId, or `None` if\n  // this is a special package name.\n  auto AsIdentifierId() const -> IdentifierId {\n    return index >= 0 ? IdentifierId(index) : IdentifierId::None;\n  }\n\n  // Returns the special package name corresponding to this PackageNameId.\n  // Requires that this name is not an identifier name.\n  auto AsSpecialName() const -> llvm::StringLiteral {\n    CARBON_CHECK(index <= NoneIndex);\n    if (*this == None) {\n      return \"Main\";\n    }\n    if (*this == Core) {\n      return \"Core\";\n    }\n    if (*this == Cpp) {\n      return \"Cpp\";\n    }\n    CARBON_FATAL(\"Unknown special package name kind {0}\", index);\n  }\n\n  auto Print(llvm::raw_ostream& out) const -> void {\n    if (index <= NoneIndex) {\n      out << Label << AsSpecialName();\n    } else {\n      IdBase::Print(out);\n    }\n  }\n};\ninline constexpr PackageNameId PackageNameId::None(PackageNameId::NoneIndex);\ninline constexpr PackageNameId PackageNameId::Core(PackageNameId::NoneIndex -\n                                                   1);\ninline constexpr PackageNameId PackageNameId::Cpp(PackageNameId::NoneIndex - 2);\n\n// Corresponds to StringRefs for string literals.\nstruct StringLiteralValueId : public IdBase<StringLiteralValueId> {\n  static constexpr llvm::StringLiteral Label = \"string\";\n  static const StringLiteralValueId None;\n  using IdBase::IdBase;\n};\ninline constexpr StringLiteralValueId StringLiteralValueId::None(\n    StringLiteralValueId::NoneIndex);\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_VALUE_IDS_H_\n"
  },
  {
    "path": "toolchain/base/value_store.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_VALUE_STORE_H_\n#define CARBON_TOOLCHAIN_BASE_VALUE_STORE_H_\n\n#include <bit>\n#include <cstddef>\n#include <limits>\n#include <memory>\n#include <type_traits>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n#include \"llvm/ADT/STLExtras.h\"\n#include \"llvm/ADT/Sequence.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"llvm/Support/MemAlloc.h\"\n#include \"toolchain/base/id_tag.h\"\n#include \"toolchain/base/mem_usage.h\"\n#include \"toolchain/base/value_store_types.h\"\n#include \"toolchain/base/yaml.h\"\n\nnamespace Carbon {\n\nnamespace Internal {\n\n// Used as a parent class for non-printable types. This is just for\n// std::conditional, not as an API.\nclass ValueStoreNotPrintable {};\n\n}  // namespace Internal\n\n// A simple wrapper for accumulating values, providing IDs to later retrieve the\n// value. This does not do deduplication.\ntemplate <typename IdT, typename ValueT, typename TagIdT = Untagged>\nclass ValueStore\n    : public std::conditional<std::is_base_of_v<Printable<ValueT>, ValueT>,\n                              Yaml::Printable<ValueStore<IdT, ValueT, TagIdT>>,\n                              Internal::ValueStoreNotPrintable> {\n public:\n  using IdType = IdT;\n  using IdTagType = IdTag<IdT, TagIdT>;\n  using ValueType = ValueStoreTypes<ValueT>::ValueType;\n  using RefType = ValueStoreTypes<ValueT>::RefType;\n  using ConstRefType = ValueStoreTypes<ValueT>::ConstRefType;\n\n  // A range over references to the values in a ValueStore, returned from\n  // `ValueStore::values()`. Hides the complex type name of the iterator\n  // internally to provide a type name (`Range`) that can be\n  // referred to without auto and templates.\n  class Range {\n   public:\n    explicit Range(const ValueStore& store [[clang::lifetimebound]])\n        : flattened_range_(MakeFlattenedRange(store)) {}\n\n    auto begin() const -> auto { return flattened_range_.begin(); }\n    auto end() const -> auto { return flattened_range_.end(); }\n\n   private:\n    // Flattens the range of `Chunk`s of `ValueType`s into a single\n    // range of `ValueType`s.\n    static auto MakeFlattenedRange(const ValueStore& store) -> auto {\n      // Because indices into `ValueStore` are all sequential values from 0, we\n      // can use llvm::seq to walk all indices in the store.\n      return llvm::map_range(llvm::seq(store.size_),\n                             [&](int32_t i) -> ConstRefType {\n                               return store.Get(IdType(store.tag_.Apply(i)));\n                             });\n    }\n\n    using FlattenedRangeType =\n        decltype(MakeFlattenedRange(std::declval<const ValueStore&>()));\n    FlattenedRangeType flattened_range_;\n  };\n\n  // Default constructor, only valid when the IdTag's tag type is Untagged.\n  ValueStore()\n    requires(IdTagIsUntagged<IdTagType>)\n  = default;\n\n  // Construct a ValueStore sharing the IdTag from another ValueStore. Useful\n  // for when two ValueStores are sharing the same ID types.\n  explicit ValueStore(IdTagType tag)\n    requires(!IdTagIsUntagged<IdTagType>)\n      : tag_(tag) {}\n\n  // Construct a ValueStore with a given tag and set of untagged (reserved) ids.\n  explicit ValueStore(IdTagType::TagIdType id, int32_t initial_reserved_ids = 0)\n    requires(!IdTagIsUntagged<IdTagType>)\n      : tag_(id, initial_reserved_ids) {}\n\n  // Stores the value and returns an ID to reference it.\n  auto Add(ValueType value) -> IdType {\n    // This routine is especially hot and the check here relatively expensive\n    // for the value provided, so only do this in non-optimized builds to make\n    // tracking down issues easier.\n    CARBON_DCHECK(size_ < std::numeric_limits<int32_t>::max(), \"Id overflow\");\n\n    IdType id = tag_.Apply(size_);\n    auto [chunk_index, pos] = RawIndexToChunkIndices(size_);\n    ++size_;\n\n    CARBON_DCHECK(static_cast<size_t>(chunk_index) <= chunks_.size(),\n                  \"{0} <= {1}\", chunk_index, chunks_.size());\n    if (static_cast<size_t>(chunk_index) == chunks_.size()) {\n      chunks_.emplace_back();\n    }\n\n    CARBON_DCHECK(pos == chunks_[chunk_index].size());\n    chunks_[chunk_index].Add(std::move(value));\n    return id;\n  }\n\n  // Returns a mutable value for an ID.\n  auto Get(IdType id) -> RefType {\n    CARBON_DCHECK(id.index >= 0, \"{0}\", id);\n    auto [chunk_index, pos] = IdToChunkIndices(id);\n    return chunks_[chunk_index].Get(pos);\n  }\n\n  // Returns the value for an ID.\n  auto Get(IdType id) const -> ConstRefType {\n    CARBON_DCHECK(id.index >= 0, \"{0}\", id);\n    auto [chunk_index, pos] = IdToChunkIndices(id);\n    return chunks_[chunk_index].Get(pos);\n  }\n\n  // Returns the value for an ID, or a specified default value if a value has\n  // not yet been added for this ID.\n  auto GetWithDefault(IdType id,  //\n                      ConstRefType default_value [[clang::lifetimebound]]) const\n      -> ConstRefType {\n    CARBON_DCHECK(id.index >= 0, \"{0}\", id);\n    auto index = tag_.Remove(id);\n    if (index >= size_) {\n      return default_value;\n    }\n    auto [chunk_index, pos] = RawIndexToChunkIndices(index);\n    return chunks_[chunk_index].Get(pos);\n  }\n\n  // Reserves space.\n  auto Reserve(int32_t size) -> void {\n    if (size <= size_) {\n      return;\n    }\n    auto [final_chunk_index, _] = RawIndexToChunkIndices(size - 1);\n    chunks_.resize(final_chunk_index + 1);\n  }\n\n  // Grows the ValueStore to `size`. Fills entries with `default_value`.\n  auto Resize(int32_t size, ConstRefType default_value) -> void {\n    if (size <= size_) {\n      return;\n    }\n\n    auto [begin_chunk_index, begin_pos] = RawIndexToChunkIndices(size_);\n    // Use an inclusive range so that if `size` would be the next chunk, we\n    // don't try doing something with it.\n    auto [end_chunk_index, end_pos] = RawIndexToChunkIndices(size - 1);\n    chunks_.resize(end_chunk_index + 1);\n\n    // If the begin and end chunks are the same, we only fill from begin to end.\n    if (begin_chunk_index == end_chunk_index) {\n      chunks_[begin_chunk_index].UninitializedFill(end_pos - begin_pos + 1,\n                                                   default_value);\n    } else {\n      // Otherwise, we do partial fills on the begin and end chunk, and full\n      // fills on intermediate chunks.\n      chunks_[begin_chunk_index].UninitializedFill(\n          Chunk::Capacity() - begin_pos, default_value);\n      for (auto i = begin_chunk_index + 1; i < end_chunk_index; ++i) {\n        chunks_[i].UninitializedFill(Chunk::Capacity(), default_value);\n      }\n      chunks_[end_chunk_index].UninitializedFill(end_pos + 1, default_value);\n    }\n\n    // Update size.\n    size_ = size;\n  }\n\n  // These are to support printable structures, and are not guaranteed.\n  auto OutputYaml() const -> Yaml::OutputMapping {\n    return Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {\n      for (auto [id, value] : enumerate()) {\n        map.Add(PrintToString(id), Yaml::OutputScalar(value));\n      }\n    });\n  }\n\n  // Collects memory usage of the values.\n  auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const\n      -> void {\n    mem_usage.Add(label.str(), size_ * sizeof(ValueType),\n                  Chunk::CapacityBytes * chunks_.size());\n  }\n\n  auto size() const -> size_t { return size_; }\n\n  // Makes an iterable range over references to all values in the ValueStore.\n  auto values() [[clang::lifetimebound]] -> auto {\n    return llvm::map_range(llvm::seq(size_), [&](int32_t i) -> RefType {\n      return Get(tag_.Apply(i));\n    });\n  }\n  auto values() const [[clang::lifetimebound]] -> Range { return Range(*this); }\n\n  // Makes an iterable range over pairs of the index and a reference to the\n  // value for each value in the store.\n  //\n  // The range is over references to the values in the store, even if used with\n  // `auto` to destructure the pair. In this example, the `value` is a\n  // `ConstRefType`:\n  // ```\n  // for (auto [id, value] : store.enumerate()) { ... }\n  // ```\n  auto enumerate() const [[clang::lifetimebound]] -> auto {\n    // For `it->val`, writing `const std::pair` is required; otherwise\n    // `mapped_iterator` incorrectly infers the pointer type for `PointerProxy`.\n    // NOLINTNEXTLINE(readability-const-return-type)\n    auto index_to_id = [&](int32_t i) -> const std::pair<IdType, ConstRefType> {\n      IdType id = tag_.Apply(i);\n      return std::pair<IdType, ConstRefType>(id, Get(id));\n    };\n    // Because indices into `ValueStore` are all sequential values from 0, we\n    // can use llvm::seq to walk all indices in the store.\n    return llvm::map_range(llvm::seq(size_), index_to_id);\n  }\n\n  auto GetIdTag() const -> IdTagType { return tag_; }\n  auto GetRawIndex(IdT id) const -> int32_t {\n    CARBON_DCHECK(id.index >= 0, \"{0}\", index);\n    auto index = tag_.Remove(id);\n#ifndef NDEBUG\n    if (index >= size_) {\n      // Attempt to decompose id.index to include extra detail in the check\n      // here.\n      //\n      // TODO: Teach ValueStore the type of the tag id with a template, then we\n      // can print it with proper formatting instead of just as an integer.\n      auto [id_tag, id_untagged_index] = IdTagType::DecomposeWithBestEffort(id);\n      CARBON_DCHECK(\n          index < size_,\n          \"Untagged index was outside of container range. Tagged index {0}. \"\n          \"Best-effort decomposition: Tag: {1}, Index: {2}. \"\n          \"Container size: {3}. \"\n          \"Expected Tag for this container: {4}.\",\n          id.index, id_tag, id_untagged_index, size_, tag_.GetContainerTag());\n    }\n#endif\n    return index;\n  }\n\n private:\n  // A chunk of `ValueType`s which has a fixed capacity, but variable size.\n  // Tracks the size internally for verifying bounds.\n  struct Chunk {\n   public:\n    // The max size of each chunk allocation for `ValueStore`. This is based on\n    // TLB page sizes for the target platform.\n    //\n    // See https://docs.kernel.org/admin-guide/mm/hugetlbpage.html\n    //\n    // A 4K chunk size outperforms a 1M chunk size on Linux-x64 and MacOS-arm64\n    // in benchmarks and when running file_test.\n    //\n    // Linux-x64: x64 CPUs support 4K and 2M page sizes, but we see 1M is slower\n    // than 4K with tcmalloc in opt builds for our tests.\n    //\n    // Mac-arm64: arm64 CPUs support 4K, 8K, 64K, 256K, 1M, 4M and up. Like for\n    // Linux-x64, 4K outperformed 1M. We didn't try other sizes yet.\n    //\n    // TODO: Is there a more optimize size for Mac-arm64? What should\n    // Linux-arm64 and Mac-x64 use? What should Windows use?\n    //\n    // TODO: The previous SmallVector<ValueType> seems to outperform 4K chunks\n    // (they may be slower by up to 5%) in benchmarks. Find ways to make\n    // chunking faster. Should successive chunks get larger in size? That will\n    // greatly complicate math for choosing a chunk though.\n    static constexpr auto MaxAllocationBytes() -> int32_t {\n#if !defined(NDEBUG) || LLVM_ADDRESS_SANITIZER_BUILD\n      // Use a small size in unoptimized builds to ensure multiple chunks get\n      // used. And do the same in ASAN builds to reduce bookkeeping overheads.\n      // Using large allocations (e.g. 1M+) incurs a 10x runtime cost for our\n      // tests under ASAN.\n      return sizeof(ValueType) * 5;\n#else\n      return 4 * 1024;\n#endif\n    }\n\n    // The number of elements stored in each chunk allocation.\n    //\n    // The number must be a power of two so that that there are no unused values\n    // in bits indexing into the allocation.\n    static constexpr auto Capacity() -> int32_t {\n      constexpr auto MaxElements = MaxAllocationBytes() / sizeof(ValueType);\n      return std::bit_floor(MaxElements);\n    }\n\n    // The number of bits needed to index each element in a chunk allocation.\n    static constexpr auto IndexBits() -> int32_t {\n      static_assert(Capacity() > 0);\n      return std::bit_width(uint32_t{Capacity() - 1});\n    }\n\n    static constexpr auto CapacityBytes = Capacity() * sizeof(ValueType);\n\n    explicit Chunk()\n        : buf_(reinterpret_cast<ValueType*>(\n              llvm::allocate_buffer(CapacityBytes, alignof(ValueType)))) {}\n\n    // Moving leaves nullptr behind in the moved-from object so that the\n    // destructor is a no-op (preventing double free).\n    Chunk(Chunk&& rhs) noexcept\n        : buf_(std::exchange(rhs.buf_, nullptr)), num_(rhs.num_) {}\n\n    auto operator=(Chunk&& rhs) noexcept -> Chunk& {\n      buf_ = std::exchange(rhs.buf_, nullptr);\n      num_ = rhs.num_;\n      return *this;\n    }\n\n    ~Chunk() {\n      if (buf_) {\n        if constexpr (!std::is_trivially_destructible_v<ValueType>) {\n          std::destroy_n(buf_, num_);\n        }\n        llvm::deallocate_buffer(buf_, CapacityBytes, alignof(ValueType));\n      }\n    }\n\n    auto Get(int32_t i) -> ValueType& {\n      CARBON_DCHECK(i < num_, \"{0}\", i);\n      return buf_[i];\n    }\n    auto Get(int32_t i) const -> const ValueType& {\n      CARBON_DCHECK(i < num_, \"{0}\", i);\n      return buf_[i];\n    }\n\n    auto Add(ValueType&& value) -> void {\n      CARBON_DCHECK(num_ < Capacity());\n      std::construct_at(buf_ + num_, std::move(value));\n      ++num_;\n    }\n\n    // Fills `fill_count` entries with `default_value`, increasing the size\n    // respectively.\n    auto UninitializedFill(int32_t fill_count, ConstRefType default_value)\n        -> void {\n      CARBON_DCHECK(num_ + fill_count <= Capacity());\n      std::uninitialized_fill_n(buf_ + num_, fill_count, default_value);\n      num_ += fill_count;\n    }\n\n    auto size() const -> int32_t { return num_; }\n\n   private:\n    // Verify using an `int32_t` for `num_` is sound.\n    static_assert(Capacity() <= std::numeric_limits<int32_t>::max());\n\n    ValueType* buf_;\n    int32_t num_ = 0;\n  };\n\n  // Converts a raw index into an index into the set of chunks, and an offset\n  // into that specific chunk. Looks for index overflow in non-optimized builds.\n  static auto RawIndexToChunkIndices(int32_t index)\n      -> std::pair<int32_t, int32_t> {\n    constexpr auto LowBits = Chunk::IndexBits();\n\n    // Verify there are no unused bits when indexing up to the `Capacity`. This\n    // ensures that ids are contiguous values from 0, as if the values were all\n    // stored in a single array, and allows using the ids to index into other\n    // arrays.\n    static_assert((1 << LowBits) == Chunk::Capacity());\n    // Simple check to make sure nothing went wildly wrong with the `Capacity`,\n    // and we have some room for a chunk index, and that shifting by the number\n    // of bits won't be UB in an int32_t.\n    static_assert(LowBits < 30);\n\n    // The index of the chunk is the high bits.\n    auto chunk = index >> LowBits;\n    // The index into the chunk is the low bits.\n    auto pos = index & ((1 << LowBits) - 1);\n    return {chunk, pos};\n  }\n\n  // Converts an id into an index into the set of chunks, and an offset into\n  // that specific chunk.\n  auto IdToChunkIndices(IdType id) const -> std::pair<int32_t, int32_t> {\n    return RawIndexToChunkIndices(GetRawIndex(id));\n  }\n\n  // Number of elements added to the store. The number should never exceed what\n  // fits in an `int32_t`, which is checked in non-optimized builds in Add().\n  int32_t size_ = 0;\n\n  IdTagType tag_;\n\n  // Storage for the `ValueType` objects, indexed by the id. We use a vector of\n  // chunks of `ValueType` instead of just a vector of `ValueType` so that\n  // addresses of `ValueType` objects are stable. This allows the rest of the\n  // toolchain to hold references into `ValueStore` without having to worry\n  // about invalidation and use-after-free. We ensure at least one Chunk is held\n  // inline so that in the case where there is only a single Chunk (i.e. small\n  // files) we can avoid one indirection.\n  llvm::SmallVector<Chunk, 1> chunks_;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_VALUE_STORE_H_\n"
  },
  {
    "path": "toolchain/base/value_store_test.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/value_store.h\"\n\n#include <gmock/gmock.h>\n#include <gtest/gtest.h>\n\n#include <string>\n\n#include \"toolchain/base/value_ids.h\"\n\nnamespace Carbon::Testing {\nnamespace {\n\nusing ::testing::Eq;\nusing ::testing::Not;\n\nTEST(ValueStore, Real) {\n  Real real1{.mantissa = llvm::APInt(64, 1),\n             .exponent = llvm::APInt(64, 11),\n             .is_decimal = true};\n  Real real2{.mantissa = llvm::APInt(64, 2),\n             .exponent = llvm::APInt(64, 22),\n             .is_decimal = false};\n\n  ValueStore<RealId, Real> reals;\n  RealId id1 = reals.Add(real1);\n  RealId id2 = reals.Add(real2);\n\n  ASSERT_TRUE(id1.has_value());\n  ASSERT_TRUE(id2.has_value());\n  EXPECT_THAT(id1, Not(Eq(id2)));\n\n  const auto& real1_copy = reals.Get(id1);\n  EXPECT_THAT(real1.mantissa, Eq(real1_copy.mantissa));\n  EXPECT_THAT(real1.exponent, Eq(real1_copy.exponent));\n  EXPECT_THAT(real1.is_decimal, Eq(real1_copy.is_decimal));\n\n  const auto& real2_copy = reals.Get(id2);\n  EXPECT_THAT(real2.mantissa, Eq(real2_copy.mantissa));\n  EXPECT_THAT(real2.exponent, Eq(real2_copy.exponent));\n  EXPECT_THAT(real2.is_decimal, Eq(real2_copy.is_decimal));\n}\n\n}  // namespace\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "toolchain/base/value_store_types.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_VALUE_STORE_TYPES_H_\n#define CARBON_TOOLCHAIN_BASE_VALUE_STORE_TYPES_H_\n\n#include <concepts>\n#include <type_traits>\n\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon {\n\n// Common calculation for ValueStore types.\ntemplate <typename ValueT>\nclass ValueStoreTypes {\n public:\n  using ValueType = std::remove_cvref_t<ValueT>;\n\n  // Typically we want to use `ValueType&` and `const ValueType& to avoid\n  // copies, but when the value type is a `StringRef`, we assume external\n  // storage for the string data and both our value type and ref type will be\n  // `StringRef`. This will preclude mutation of the string data.\n  using RefType = std::conditional_t<std::same_as<llvm::StringRef, ValueType>,\n                                     llvm::StringRef, ValueType&>;\n  using ConstRefType =\n      std::conditional_t<std::same_as<llvm::StringRef, ValueType>,\n                         llvm::StringRef, const ValueType&>;\n};\n\n}  // namespace Carbon\n\n#endif  // CARBON_TOOLCHAIN_BASE_VALUE_STORE_TYPES_H_\n"
  },
  {
    "path": "toolchain/base/yaml.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_BASE_YAML_H_\n#define CARBON_TOOLCHAIN_BASE_YAML_H_\n\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/YAMLTraits.h\"\n\n// This file provides adapters for outputting YAML using llvm::yaml's APIs. It\n// only supports output, not input. However, it addresses the mix of const and\n// non-const expectations of the llvm::yaml that make it difficult to otherwise\n// use the trait-based approach.\n\nnamespace Carbon::Yaml {\n\n// Helper for printing YAML, to maintain a consistent configuration.\ntemplate <typename T>\ninline auto Print(llvm::raw_ostream& out, T yaml) -> void {\n  llvm::yaml::Output yout(out, /*Ctxt=*/nullptr, /*WrapColumn=*/80);\n  yout << yaml;\n}\n\n// Similar to the standard Printable<T>, but relies on OutputYaml for printing.\ntemplate <typename T>\nclass Printable : public Carbon::Printable<T> {\n public:\n  auto Print(llvm::raw_ostream& out) const -> void {\n    Carbon::Yaml::Print(out, static_cast<const T*>(this)->OutputYaml());\n  }\n};\n\n// Adapts a function for outputting YAML as a scalar. This currently assumes no\n// scalars passed through this should be quoted.\nclass OutputScalar {\n public:\n  template <typename T>\n  explicit OutputScalar(const T& val)\n      : output_([&](llvm::raw_ostream& out) -> void { out << val; }) {}\n\n  explicit OutputScalar(const llvm::APInt& val)\n      : output_([&](llvm::raw_ostream& out) -> void {\n          // Carbon's plain APInt storage is typically unsigned.\n          val.print(out, /*isSigned=*/false);\n        }) {}\n\n  explicit OutputScalar(std::function<auto(llvm::raw_ostream&)->void> output)\n      : output_(std::move(output)) {}\n\n  auto Output(llvm::raw_ostream& out) const -> void { output_(out); }\n\n private:\n  std::function<auto(llvm::raw_ostream&)->void> output_;\n};\n\n// Adapts a function for outputting YAML as a mapping.\nclass OutputMapping {\n public:\n  class Map {\n   public:\n    // `io` must not be null.\n    explicit Map(llvm::yaml::IO* io) : io_(io) {}\n\n    // Maps a value. This mainly takes responsibility for copying the value,\n    // letting mapRequired take `&value`.\n    template <typename T>\n    auto Add(llvm::StringRef key, T value) -> void {\n      io_->mapRequired(key.data(), value);\n    }\n\n   private:\n    llvm::yaml::IO* io_;\n  };\n\n  explicit OutputMapping(std::function<auto(OutputMapping::Map)->void> output)\n      : output_(std::move(output)) {}\n\n  auto Output(llvm::yaml::IO& io) -> void { output_(Map(&io)); }\n\n private:\n  std::function<auto(OutputMapping::Map)->void> output_;\n};\n\n}  // namespace Carbon::Yaml\n\n// Link OutputScalar to the llvm::yaml::IO API.\ntemplate <>\nstruct llvm::yaml::ScalarTraits<Carbon::Yaml::OutputScalar> {\n  static auto output(const Carbon::Yaml::OutputScalar& value, void* /*ctxt*/,\n                     llvm::raw_ostream& out) -> void {\n    value.Output(out);\n  }\n  static auto input(StringRef /*scalar*/, void* /*ctxt*/,\n                    Carbon::Yaml::OutputScalar& /*value*/) -> StringRef {\n    CARBON_FATAL(\"Input is unsupported.\");\n  }\n  static auto mustQuote(StringRef /*value*/) -> QuotingType {\n    return QuotingType::None;\n  }\n};\nstatic_assert(llvm::yaml::has_ScalarTraits<Carbon::Yaml::OutputScalar>::value);\n\n// Link OutputMapping to the llvm::yaml::IO API.\ntemplate <>\nstruct llvm::yaml::MappingTraits<Carbon::Yaml::OutputMapping> {\n  static auto mapping(IO& io, Carbon::Yaml::OutputMapping& mapping) -> void {\n    mapping.Output(io);\n  }\n};\nstatic_assert(llvm::yaml::has_MappingTraits<Carbon::Yaml::OutputMapping,\n                                            llvm::yaml::EmptyContext>::value);\n\n#endif  // CARBON_TOOLCHAIN_BASE_YAML_H_\n"
  },
  {
    "path": "toolchain/check/BUILD",
    "content": "# Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n# Exceptions. See /LICENSE for license information.\n# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\nload(\"//bazel/cc_rules:defs.bzl\", \"cc_library\")\nload(\"//testing/fuzzing:rules.bzl\", \"cc_fuzz_test\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nfilegroup(\n    name = \"testdata\",\n    srcs = glob([\"testdata/**/*.carbon\"]),\n)\n\ncc_library(\n    name = \"context\",\n    srcs = [\n        \"action.cpp\",\n        \"call.cpp\",\n        \"class.cpp\",\n        \"context.cpp\",\n        \"control_flow.cpp\",\n        \"convert.cpp\",\n        \"cpp/access.cpp\",\n        \"cpp/call.cpp\",\n        \"cpp/constant.cpp\",\n        \"cpp/context.cpp\",\n        \"cpp/custom_type_mapping.cpp\",\n        \"cpp/generate_ast.cpp\",\n        \"cpp/impl_lookup.cpp\",\n        \"cpp/import.cpp\",\n        \"cpp/location.cpp\",\n        \"cpp/macros.cpp\",\n        \"cpp/operators.cpp\",\n        \"cpp/overload_resolution.cpp\",\n        \"cpp/thunk.cpp\",\n        \"cpp/type_mapping.cpp\",\n        \"custom_witness.cpp\",\n        \"decl_name_stack.cpp\",\n        \"deduce.cpp\",\n        \"deferred_definition_worklist.cpp\",\n        \"eval.cpp\",\n        \"eval_inst.cpp\",\n        \"facet_type.cpp\",\n        \"function.cpp\",\n        \"generic.cpp\",\n        \"global_init.cpp\",\n        \"impl.cpp\",\n        \"impl_lookup.cpp\",\n        \"impl_validation.cpp\",\n        \"import.cpp\",\n        \"import_ref.cpp\",\n        \"inst.cpp\",\n        \"inst_block_stack.cpp\",\n        \"interface.cpp\",\n        \"keyword_modifier_set.cpp\",\n        \"literal.cpp\",\n        \"member_access.cpp\",\n        \"merge.cpp\",\n        \"modifiers.cpp\",\n        \"name_component.cpp\",\n        \"name_lookup.cpp\",\n        \"name_ref.cpp\",\n        \"name_scope.cpp\",\n        \"operator.cpp\",\n        \"pattern.cpp\",\n        \"pattern_match.cpp\",\n        \"pointer_dereference.cpp\",\n        \"return.cpp\",\n        \"scope_stack.cpp\",\n        \"subst.cpp\",\n        \"thunk.cpp\",\n        \"type.cpp\",\n        \"type_completion.cpp\",\n        \"type_structure.cpp\",\n        \"unused.cpp\",\n    ],\n    hdrs = [\n        \"action.h\",\n        \"call.h\",\n        \"class.h\",\n        \"context.h\",\n        \"control_flow.h\",\n        \"convert.h\",\n        \"cpp/access.h\",\n        \"cpp/call.h\",\n        \"cpp/constant.h\",\n        \"cpp/context.h\",\n        \"cpp/custom_type_mapping.h\",\n        \"cpp/generate_ast.h\",\n        \"cpp/impl_lookup.h\",\n        \"cpp/import.h\",\n        \"cpp/location.h\",\n        \"cpp/macros.h\",\n        \"cpp/operators.h\",\n        \"cpp/overload_resolution.h\",\n        \"cpp/thunk.h\",\n        \"cpp/type_mapping.h\",\n        \"custom_witness.h\",\n        \"decl_introducer_state.h\",\n        \"decl_name_stack.h\",\n        \"deduce.h\",\n        \"deferred_definition_worklist.h\",\n        \"diagnostic_helpers.h\",\n        \"eval.h\",\n        \"eval_inst.h\",\n        \"facet_type.h\",\n        \"full_pattern_stack.h\",\n        \"function.h\",\n        \"generic.h\",\n        \"global_init.h\",\n        \"impl.h\",\n        \"impl_lookup.h\",\n        \"impl_validation.h\",\n        \"import.h\",\n        \"import_ref.h\",\n        \"inst.h\",\n        \"inst_block_stack.h\",\n        \"interface.h\",\n        \"keyword_modifier_set.h\",\n        \"lexical_lookup.h\",\n        \"literal.h\",\n        \"member_access.h\",\n        \"merge.h\",\n        \"modifiers.h\",\n        \"name_component.h\",\n        \"name_lookup.h\",\n        \"name_ref.h\",\n        \"name_scope.h\",\n        \"operator.h\",\n        \"param_and_arg_refs_stack.h\",\n        \"pattern.h\",\n        \"pattern_match.h\",\n        \"pending_block.h\",\n        \"pointer_dereference.h\",\n        \"region_stack.h\",\n        \"return.h\",\n        \"scope_index.h\",\n        \"scope_stack.h\",\n        \"subst.h\",\n        \"thunk.h\",\n        \"type.h\",\n        \"type_completion.h\",\n        \"type_structure.h\",\n        \"unused.h\",\n    ],\n    deps = [\n        \":core_identifier\",\n        \":node_stack\",\n        \"//common:array_stack\",\n        \"//common:check\",\n        \"//common:concepts\",\n        \"//common:emplace_by_calling\",\n        \"//common:enum_mask_base\",\n        \"//common:find\",\n        \"//common:growing_range\",\n        \"//common:map\",\n        \"//common:move_only\",\n        \"//common:ostream\",\n        \"//common:raw_string_ostream\",\n        \"//common:set\",\n        \"//common:vlog\",\n        \"//toolchain/base:canonical_value_store\",\n        \"//toolchain/base:index_base\",\n        \"//toolchain/base:int\",\n        \"//toolchain/base:kind_switch\",\n        \"//toolchain/base:shared_value_stores\",\n        \"//toolchain/base:value_ids\",\n        \"//toolchain/base:value_store\",\n        \"//toolchain/check:generic_region_stack\",\n        \"//toolchain/diagnostics:emitter\",\n        \"//toolchain/diagnostics:format_providers\",\n        \"//toolchain/lex:token_info\",\n        \"//toolchain/lex:token_kind\",\n        \"//toolchain/lex:tokenized_buffer\",\n        \"//toolchain/parse:node_kind\",\n        \"//toolchain/parse:tree\",\n        \"//toolchain/sem_ir:absolute_node_id\",\n        \"//toolchain/sem_ir:clang_decl\",\n        \"//toolchain/sem_ir:cpp_file\",\n        \"//toolchain/sem_ir:expr_info\",\n        \"//toolchain/sem_ir:file\",\n        \"//toolchain/sem_ir:formatter\",\n        \"//toolchain/sem_ir:typed_insts\",\n        \"@llvm-project//clang:ast\",\n        \"@llvm-project//clang:basic\",\n        \"@llvm-project//clang:codegen\",\n        \"@llvm-project//clang:frontend\",\n        \"@llvm-project//clang:lex\",\n        \"@llvm-project//clang:parse\",\n        \"@llvm-project//clang:sema\",\n        \"@llvm-project//clang:tooling\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"dump\",\n    srcs = [\"dump.cpp\"],\n    deps = [\n        \":context\",\n        \"//common:check\",\n        \"//common:ostream\",\n        \"//common:raw_string_ostream\",\n        \"//toolchain/lex:dump\",\n        \"//toolchain/lex:tokenized_buffer\",\n        \"//toolchain/parse:dump\",\n        \"//toolchain/parse:tree\",\n        \"//toolchain/sem_ir:dump\",\n        \"//toolchain/sem_ir:file\",\n    ],\n    # Always link dump methods.\n    alwayslink = 1,\n)\n\ncc_library(\n    name = \"check\",\n    srcs = [\n        \"check.cpp\",\n        \"check_unit.cpp\",\n        \"check_unit.h\",\n        \"handle.h\",\n        \"node_id_traversal.cpp\",\n        \"node_id_traversal.h\",\n    ] +\n    # Glob handler files to avoid missing any.\n    glob([\n        \"handle_*.cpp\",\n    ]),\n    hdrs = [\"check.h\"],\n    deps = [\n        \":context\",\n        \":core_identifier\",\n        \":dump\",\n        \":emitter\",\n        \"//common:check\",\n        \"//common:error\",\n        \"//common:find\",\n        \"//common:growing_range\",\n        \"//common:map\",\n        \"//common:ostream\",\n        \"//common:pretty_stack_trace_function\",\n        \"//common:vlog\",\n        \"//toolchain/base:fixed_size_value_store\",\n        \"//toolchain/base:kind_switch\",\n        \"//toolchain/base:shared_value_stores\",\n        \"//toolchain/base:timings\",\n        \"//toolchain/diagnostics:emitter\",\n        \"//toolchain/diagnostics:format_providers\",\n        \"//toolchain/lex:token_index\",\n        \"//toolchain/lex:token_kind\",\n        \"//toolchain/lex:tokenized_buffer\",\n        \"//toolchain/parse:node_category\",\n        \"//toolchain/parse:node_kind\",\n        \"//toolchain/parse:tree\",\n        \"//toolchain/sem_ir:absolute_node_id\",\n        \"//toolchain/sem_ir:entry_point\",\n        \"//toolchain/sem_ir:expr_info\",\n        \"//toolchain/sem_ir:file\",\n        \"//toolchain/sem_ir:formatter\",\n        \"//toolchain/sem_ir:typed_insts\",\n        \"@llvm-project//clang:frontend\",\n        \"@llvm-project//clang:sema\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_fuzz_test(\n    name = \"check_fuzzer\",\n    size = \"small\",\n    srcs = [\"check_fuzzer.cpp\"],\n    corpus = glob([\"fuzzer_corpus/*\"]),\n    deps = [\n        \"//common:exe_path\",\n        \"//testing/fuzzing:libfuzzer_header\",\n        \"//toolchain/driver\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"generic_region_stack\",\n    srcs = [\"generic_region_stack.cpp\"],\n    hdrs = [\"generic_region_stack.h\"],\n    deps = [\n        \"//common:array_stack\",\n        \"//common:check\",\n        \"//common:map\",\n        \"//common:ostream\",\n        \"//common:vlog\",\n        \"//toolchain/sem_ir:file\",\n        \"//toolchain/sem_ir:typed_insts\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"node_stack\",\n    srcs = [\"node_stack.cpp\"],\n    hdrs = [\"node_stack.h\"],\n    deps = [\n        \"//common:check\",\n        \"//common:ostream\",\n        \"//common:vlog\",\n        \"//toolchain/parse:node_kind\",\n        \"//toolchain/parse:tree\",\n        \"//toolchain/sem_ir:typed_insts\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n\ncc_library(\n    name = \"core_identifier\",\n    srcs = [\"core_identifier.cpp\"],\n    hdrs = [\"core_identifier.h\"],\n    textual_hdrs = [\"core_identifier.def\"],\n    deps = [\n        \"//common:enum_base\",\n        \"//toolchain/base:shared_value_stores\",\n        \"//toolchain/base:value_ids\",\n        \"//toolchain/sem_ir:typed_insts\",\n    ],\n)\n\ncc_library(\n    name = \"emitter\",\n    srcs = [\"diagnostic_emitter.cpp\"],\n    hdrs = [\"diagnostic_emitter.h\"],\n    deps = [\n        \":context\",\n        \"//common:ostream\",\n        \"//common:raw_string_ostream\",\n        \"//toolchain/diagnostics:emitter\",\n        \"//toolchain/lex:token_index\",\n        \"//toolchain/parse:tree\",\n        \"//toolchain/sem_ir:absolute_node_id\",\n        \"//toolchain/sem_ir:diagnostic_loc_converter\",\n        \"//toolchain/sem_ir:file\",\n        \"//toolchain/sem_ir:stringify\",\n        \"//toolchain/sem_ir:typed_insts\",\n        \"@llvm-project//llvm:Support\",\n    ],\n)\n"
  },
  {
    "path": "toolchain/check/action.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/action.h\"\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/generic_region_stack.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/sem_ir/constant.h\"\n#include \"toolchain/sem_ir/id_kind.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto PerformAction(Context& context, SemIR::LocId loc_id,\n                   SemIR::RefineTypeAction action) -> SemIR::InstId {\n  return AddInst<SemIR::AsCompatible>(\n      context, loc_id,\n      {.type_id =\n           context.types().GetTypeIdForTypeInstId(action.inst_type_inst_id),\n       .source_id = action.inst_id});\n}\n\nstatic auto OperandIsDependent(Context& context, SemIR::ConstantId const_id)\n    -> bool {\n  // A type operand makes the instruction dependent if it is a\n  // template-dependent constant.\n  if (!const_id.is_symbolic()) {\n    return false;\n  }\n  return context.constant_values().GetSymbolicConstant(const_id).dependence ==\n         SemIR::ConstantDependence::Template;\n}\n\nauto OperandIsDependent(Context& context, SemIR::TypeId type_id) -> bool {\n  // A type operand makes the instruction dependent if it is a\n  // template-dependent type.\n  return OperandIsDependent(context, context.types().GetConstantId(type_id));\n}\n\nauto OperandIsDependent(Context& context, SemIR::InstId inst_id) -> bool {\n  // An instruction operand makes the instruction dependent if its type or\n  // constant value is dependent.\n  return OperandIsDependent(context, context.insts().Get(inst_id).type_id()) ||\n         OperandIsDependent(context, context.constant_values().Get(inst_id));\n}\n\nauto OperandIsDependent(Context& context, SemIR::TypeInstId inst_id) -> bool {\n  // An instruction operand makes the instruction dependent if its type or\n  // constant value is dependent. TypeInstId has type `TypeType` which is\n  // concrete, so we only need to look at the constant value.\n  return OperandIsDependent(context, context.constant_values().Get(inst_id));\n}\n\nstatic auto OperandIsDependent(Context& context, SemIR::Inst::ArgAndKind arg)\n    -> bool {\n  CARBON_KIND_SWITCH(arg) {\n    case CARBON_KIND(SemIR::InstId inst_id): {\n      return OperandIsDependent(context, inst_id);\n    }\n\n    case CARBON_KIND(SemIR::MetaInstId inst_id): {\n      return OperandIsDependent(context, inst_id);\n    }\n\n    case CARBON_KIND(SemIR::TypeInstId inst_id): {\n      return OperandIsDependent(context, inst_id);\n    }\n\n    case SemIR::IdKind::None:\n    case SemIR::IdKind::For<SemIR::AbsoluteInstId>:\n    case SemIR::IdKind::For<SemIR::NameId>:\n      return false;\n\n    default:\n      // TODO: Properly handle different argument kinds.\n      CARBON_FATAL(\"Unexpected argument kind for action\");\n  }\n}\n\nauto ActionIsDependent(Context& context, SemIR::Inst action_inst) -> bool {\n  if (auto refine_action = action_inst.TryAs<SemIR::RefineTypeAction>()) {\n    // `RefineTypeAction` can be performed whenever the type is non-dependent,\n    // even if we don't know the instruction yet.\n    return OperandIsDependent(context, refine_action->inst_type_inst_id);\n  }\n\n  if (OperandIsDependent(context, action_inst.type_id())) {\n    return true;\n  }\n  return OperandIsDependent(context, action_inst.arg0_and_kind()) ||\n         OperandIsDependent(context, action_inst.arg1_and_kind());\n}\n\nstatic auto AddDependentActionSpliceImpl(Context& context,\n                                         SemIR::LocIdAndInst action,\n                                         SemIR::TypeInstId result_type_inst_id)\n    -> SemIR::InstId {\n  auto inst_id = AddDependentActionInst(context, action);\n  if (!result_type_inst_id.has_value()) {\n    result_type_inst_id = AddDependentActionTypeInst(\n        context, action.loc_id,\n        SemIR::TypeOfInst{.type_id = SemIR::TypeType::TypeId,\n                          .inst_id = inst_id});\n  }\n  return AddInst(\n      context, action.loc_id,\n      SemIR::SpliceInst{.type_id = context.types().GetTypeIdForTypeInstId(\n                            result_type_inst_id),\n                        .inst_id = inst_id});\n}\n\n// Refine one operand of an action. Given an argument from a template, this\n// produces an argument that has the template-dependent parts replaced with\n// their concrete values, so that the action doesn't need to know which specific\n// it is operating on.\nstatic auto RefineOperand(Context& context, SemIR::LocId loc_id,\n                          SemIR::Inst::ArgAndKind arg) -> int32_t {\n  if (auto inst_id = arg.TryAs<SemIR::MetaInstId>()) {\n    auto inst = context.insts().Get(*inst_id);\n    if (inst.Is<SemIR::SpliceInst>()) {\n      // The argument will evaluate to the spliced instruction, which is already\n      // refined.\n      return arg.value();\n    }\n\n    // If the type of the action argument is dependent, refine to an instruction\n    // with a concrete type.\n    if (OperandIsDependent(context, inst.type_id())) {\n      auto type_inst_id = context.types().GetTypeInstId(inst.type_id());\n      inst_id = AddDependentActionSpliceImpl(\n          context,\n          SemIR::LocIdAndInst(\n              loc_id,\n              SemIR::RefineTypeAction{.type_id = GetSingletonType(\n                                          context, SemIR::InstType::TypeInstId),\n                                      .inst_id = *inst_id,\n                                      .inst_type_inst_id = type_inst_id}),\n          type_inst_id);\n    }\n\n    // TODO: Handle the case where the constant value of the instruction is\n    // template-dependent.\n\n    return inst_id->index;\n  }\n\n  return arg.value();\n}\n\n// Refine the operands of an action, ensuring that they will refer to concrete\n// instructions that don't have template-dependent types.\nstatic auto RefineOperands(Context& context, SemIR::LocId loc_id,\n                           SemIR::Inst action) -> SemIR::Inst {\n  auto arg0 = RefineOperand(context, loc_id, action.arg0_and_kind());\n  auto arg1 = RefineOperand(context, loc_id, action.arg1_and_kind());\n  action.SetArgs(arg0, arg1);\n  return action;\n}\n\nauto AddDependentActionSplice(Context& context, SemIR::LocIdAndInst action,\n                              SemIR::TypeInstId result_type_inst_id)\n    -> SemIR::InstId {\n  action.inst = RefineOperands(context, action.loc_id, action.inst);\n  return AddDependentActionSpliceImpl(context, action, result_type_inst_id);\n}\n\nauto Internal::BeginPerformDelayedAction(Context& context) -> void {\n  // Push an `InstBlock` to hold any instructions created by the action.\n  // Note that we assume that actions don't need to create multiple blocks. If\n  // this changes, we should push a region too.\n  context.inst_block_stack().Push();\n}\n\nauto Internal::EndPerformDelayedAction(Context& context,\n                                       SemIR::InstId result_id)\n    -> SemIR::InstId {\n  // If the only created instruction is the result, then we can use it directly.\n  auto contents = context.inst_block_stack().PeekCurrentBlockContents();\n  if (contents.size() == 1 && contents[0] == result_id) {\n    context.inst_block_stack().PopAndDiscard();\n    return result_id;\n  }\n\n  // Otherwise, create a splice_block to represent the sequence of instructions\n  // created by the action.\n  auto result = context.insts().GetWithLocId(result_id);\n  return AddInstInNoBlock(\n      context, result.loc_id,\n      SemIR::SpliceBlock{.type_id = result.inst.type_id(),\n                         .block_id = context.inst_block_stack().Pop(),\n                         .result_id = result_id});\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/action.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_ACTION_H_\n#define CARBON_TOOLCHAIN_CHECK_ACTION_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n\nnamespace Carbon::Check {\n\n// Performs a member access action. Defined in member_access.cpp.\nauto PerformAction(Context& context, SemIR::LocId loc_id,\n                   SemIR::AccessMemberAction action) -> SemIR::InstId;\nauto PerformAction(Context& context, SemIR::LocId loc_id,\n                   SemIR::AccessOptionalMemberAction action) -> SemIR::InstId;\n\n// Performs a conversion action. Defined in convert.cpp.\nauto PerformAction(Context& context, SemIR::LocId loc_id,\n                   SemIR::ConvertToValueAction action) -> SemIR::InstId;\n\n// Performs a type refinement action, by creating a conversion from an\n// instruction with a template-dependent symbolic type to the corresponding\n// instantiated type.\nauto PerformAction(Context& context, SemIR::LocId loc_id,\n                   SemIR::RefineTypeAction action) -> SemIR::InstId;\n\n// Determines whether the given action depends on a template parameter in a way\n// that means it cannot be performed immediately.\nauto ActionIsDependent(Context& context, SemIR::Inst action_inst) -> bool;\n\n// Determines whether the given action operand depends on a template parameter\n// in a way that means the action cannot be performed immediately.\nauto OperandIsDependent(Context& context, SemIR::InstId inst_id) -> bool;\n\n// Determines whether the given action operand depends on a template parameter\n// in a way that means the action cannot be performed immediately.\nauto OperandIsDependent(Context& context, SemIR::TypeInstId inst_id) -> bool;\n\n// Determines whether the given type depends on a template parameter\n// in a way that means the action cannot be performed immediately.\nauto OperandIsDependent(Context& context, SemIR::TypeId type_id) -> bool;\n\n// Adds an instruction to the current block to splice in the result of\n// performing a dependent action.\nauto AddDependentActionSplice(Context& context, SemIR::LocIdAndInst action,\n                              SemIR::TypeInstId result_type_inst_id)\n    -> SemIR::InstId;\n\n// Convenience wrapper for `AddDependentActionSplice`.\ntemplate <typename LocT, typename InstT>\nauto AddDependentActionSplice(Context& context, LocT loc, InstT inst,\n                              SemIR::TypeInstId result_type_inst_id)\n    -> SemIR::InstId {\n  return AddDependentActionSplice(context, SemIR::LocIdAndInst(loc, inst),\n                                  result_type_inst_id);\n}\n\n// Handles a new action. If the action is not dependent, it is performed\n// immediately. Otherwise, adds the action to the enclosing template's eval\n// block and creates an instruction to splice in the result of the action.\ntemplate <typename ActionT>\nauto HandleAction(Context& context, SemIR::LocId loc_id, ActionT action_inst,\n                  SemIR::TypeInstId result_type_inst_id =\n                      SemIR::TypeInstId::None) -> SemIR::InstId {\n  if (ActionIsDependent(context, action_inst) ||\n      (result_type_inst_id.has_value() &&\n       OperandIsDependent(context, result_type_inst_id))) {\n    return AddDependentActionSplice(\n        context, SemIR::LocIdAndInst(loc_id, action_inst), result_type_inst_id);\n  }\n\n  return PerformAction(context, loc_id, action_inst);\n}\n\nnamespace Internal {\n// Performs setup steps for performing a delayed action. This is an\n// implementation detail of PerformDelayedAction and should not be called\n// directly.\nauto BeginPerformDelayedAction(Context& context) -> void;\n\n// Performs cleanup steps for performing a delayed action. This is an\n// implementation detail of PerformDelayedAction and should not be called\n// directly.\nauto EndPerformDelayedAction(Context& context, SemIR::InstId result_id)\n    -> SemIR::InstId;\n}  // namespace Internal\n\n// Performs an action as a result of evaluation of a template's eval block.\ntemplate <typename ActionT>\nauto PerformDelayedAction(Context& context, SemIR::LocId loc_id,\n                          ActionT action_inst) -> SemIR::InstId {\n  if (ActionIsDependent(context, action_inst)) {\n    return SemIR::InstId::None;\n  }\n  Internal::BeginPerformDelayedAction(context);\n  auto inst_id = PerformAction(context, loc_id, action_inst);\n  return Internal::EndPerformDelayedAction(context, inst_id);\n}\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_ACTION_H_\n"
  },
  {
    "path": "toolchain/check/call.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/call.h\"\n\n#include <optional>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/cpp/call.h\"\n#include \"toolchain/check/cpp/thunk.h\"\n#include \"toolchain/check/deduce.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/function.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/name_ref.h\"\n#include \"toolchain/check/thunk.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/sem_ir/builtin_function_kind.h\"\n#include \"toolchain/sem_ir/entity_with_params_base.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nnamespace {\n// Entity kinds, for diagnostics. Converted to an int for a select.\nenum class EntityKind : uint8_t {\n  Function = 0,\n  GenericClass = 1,\n  GenericInterface = 2,\n  GenericNamedConstraint = 3,\n};\n}  // namespace\n\n// Resolves the callee expression in a call to a specific callee, or diagnoses\n// if no specific callee can be identified. This verifies the arity of the\n// callee and determines any compile-time arguments, but doesn't check that the\n// runtime arguments are convertible to the parameter types.\n//\n// `self_id` and `arg_ids` are the self argument and explicit arguments in the\n// call.\n//\n// Returns a `SpecificId` for the specific callee, `SpecificId::None` if the\n// callee is not generic, or `nullopt` if an error has been diagnosed.\nstatic auto ResolveCalleeInCall(Context& context, SemIR::LocId loc_id,\n                                const SemIR::EntityWithParamsBase& entity,\n                                EntityKind entity_kind_for_diagnostic,\n                                SemIR::SpecificId enclosing_specific_id,\n                                SemIR::InstId self_id,\n                                llvm::ArrayRef<SemIR::InstId> arg_ids)\n    -> std::optional<SemIR::SpecificId> {\n  // Check that the arity matches.\n  auto params = context.inst_blocks().GetOrEmpty(entity.param_patterns_id);\n  if (arg_ids.size() != params.size()) {\n    CARBON_DIAGNOSTIC(CallArgCountMismatch, Error,\n                      \"{0} argument{0:s} passed to \"\n                      \"{1:=0:function|=1:generic class|=2:generic \"\n                      \"interface|=3:generic constraint}\"\n                      \" expecting {2} argument{2:s}\",\n                      Diagnostics::IntAsSelect, Diagnostics::IntAsSelect,\n                      Diagnostics::IntAsSelect);\n    CARBON_DIAGNOSTIC(InCallToEntity, Note,\n                      \"calling {0:=0:function|=1:generic class|=2:generic \"\n                      \"interface|=3:generic constraint}\"\n                      \" declared here\",\n                      Diagnostics::IntAsSelect);\n    context.emitter()\n        .Build(loc_id, CallArgCountMismatch, arg_ids.size(),\n               static_cast<int>(entity_kind_for_diagnostic), params.size())\n        .Note(entity.latest_decl_id(), InCallToEntity,\n              static_cast<int>(entity_kind_for_diagnostic))\n        .Emit();\n    return std::nullopt;\n  }\n\n  // Perform argument deduction.\n  auto specific_id = SemIR::SpecificId::None;\n  if (entity.generic_id.has_value()) {\n    specific_id = DeduceGenericCallArguments(\n        context, loc_id, entity.generic_id, enclosing_specific_id,\n        entity.implicit_param_patterns_id, entity.param_patterns_id, self_id,\n        arg_ids);\n    if (!specific_id.has_value()) {\n      return std::nullopt;\n    }\n  }\n  return specific_id;\n}\n\n// Performs a call where the callee is the name of a generic class, such as\n// `Vector(i32)`.\nstatic auto PerformCallToGenericClass(Context& context, SemIR::LocId loc_id,\n                                      SemIR::ClassId class_id,\n                                      SemIR::SpecificId enclosing_specific_id,\n                                      llvm::ArrayRef<SemIR::InstId> arg_ids)\n    -> SemIR::InstId {\n  const auto& generic_class = context.classes().Get(class_id);\n  auto callee_specific_id =\n      ResolveCalleeInCall(context, loc_id, generic_class,\n                          EntityKind::GenericClass, enclosing_specific_id,\n                          /*self_id=*/SemIR::InstId::None, arg_ids);\n  if (!callee_specific_id) {\n    return SemIR::ErrorInst::InstId;\n  }\n  return GetOrAddInst<SemIR::ClassType>(context, loc_id,\n                                        {.type_id = SemIR::TypeType::TypeId,\n                                         .class_id = class_id,\n                                         .specific_id = *callee_specific_id});\n}\n\nstatic auto EntityFromInterfaceOrNamedConstraint(\n    Context& context, SemIR::InterfaceId interface_id)\n    -> const SemIR::EntityWithParamsBase& {\n  return context.interfaces().Get(interface_id);\n}\n\nstatic auto EntityFromInterfaceOrNamedConstraint(\n    Context& context, SemIR::NamedConstraintId named_constraint_id)\n    -> const SemIR::EntityWithParamsBase& {\n  return context.named_constraints().Get(named_constraint_id);\n}\n\n// Performs a call where the callee is the name of a generic interface or named\n// constraint, such as `AddWith(i32)`.\ntemplate <typename IdT>\n  requires SameAsOneOf<IdT, SemIR::InterfaceId, SemIR::NamedConstraintId>\nstatic auto PerformCallToGenericInterfaceOrNamedConstaint(\n    Context& context, SemIR::LocId loc_id, IdT id,\n    SemIR::SpecificId enclosing_specific_id,\n    llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::InstId {\n  const auto& entity = EntityFromInterfaceOrNamedConstraint(context, id);\n\n  auto entity_kind_for_diagnostic = EntityKind::GenericInterface;\n  if constexpr (std::same_as<IdT, SemIR::NamedConstraintId>) {\n    entity_kind_for_diagnostic = EntityKind::GenericNamedConstraint;\n  }\n  auto callee_specific_id =\n      ResolveCalleeInCall(context, loc_id, entity, entity_kind_for_diagnostic,\n                          enclosing_specific_id,\n                          /*self_id=*/SemIR::InstId::None, arg_ids);\n  if (!callee_specific_id) {\n    return SemIR::ErrorInst::InstId;\n  }\n  std::optional<SemIR::FacetType> facet_type;\n  if constexpr (std::same_as<IdT, SemIR::InterfaceId>) {\n    facet_type = FacetTypeFromInterface(context, id, *callee_specific_id);\n  } else {\n    facet_type = FacetTypeFromNamedConstraint(context, id, *callee_specific_id);\n  }\n  return GetOrAddInst(context, loc_id, *facet_type);\n}\n\n// Builds an appropriate specific function for the callee, also handling\n// instance binding.\nstatic auto BuildCalleeSpecificFunction(\n    Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,\n    SemIR::InstId callee_function_self_type_id,\n    SemIR::SpecificId callee_specific_id) -> SemIR::InstId {\n  auto generic_callee_id = callee_id;\n\n  // Strip off a bound_method so that we can form a constant specific callee.\n  auto bound_method = context.insts().TryGetAs<SemIR::BoundMethod>(callee_id);\n  if (bound_method) {\n    generic_callee_id = bound_method->function_decl_id;\n  }\n\n  // Form a specific callee.\n  if (callee_function_self_type_id.has_value()) {\n    // This is an associated function in an interface; the callee is the\n    // specific function in the impl that corresponds to the specific function\n    // we deduced.\n    callee_id =\n        GetOrAddInst(context, SemIR::LocId(generic_callee_id),\n                     SemIR::SpecificImplFunction{\n                         .type_id = GetSingletonType(\n                             context, SemIR::SpecificFunctionType::TypeInstId),\n                         .callee_id = generic_callee_id,\n                         .specific_id = callee_specific_id});\n  } else {\n    // This is a regular generic function. The callee is the specific function\n    // we deduced.\n    callee_id =\n        GetOrAddInst(context, SemIR::LocId(generic_callee_id),\n                     SemIR::SpecificFunction{\n                         .type_id = GetSingletonType(\n                             context, SemIR::SpecificFunctionType::TypeInstId),\n                         .callee_id = generic_callee_id,\n                         .specific_id = callee_specific_id});\n  }\n\n  // Add the `self` argument back if there was one.\n  if (bound_method) {\n    callee_id =\n        GetOrAddInst<SemIR::BoundMethod>(context, loc_id,\n                                         {.type_id = bound_method->type_id,\n                                          .object_id = bound_method->object_id,\n                                          .function_decl_id = callee_id});\n  }\n\n  return callee_id;\n}\n\nauto PerformCallToFunction(Context& context, SemIR::LocId loc_id,\n                           SemIR::InstId callee_id,\n                           const SemIR::CalleeFunction& callee_function,\n                           llvm::ArrayRef<SemIR::InstId> arg_ids,\n                           bool is_operator_syntax) -> SemIR::InstId {\n  // If the callee is a generic function, determine the generic argument values\n  // for the call.\n  auto callee_specific_id = ResolveCalleeInCall(\n      context, loc_id, context.functions().Get(callee_function.function_id),\n      EntityKind::Function, callee_function.enclosing_specific_id,\n      callee_function.self_id, arg_ids);\n  if (!callee_specific_id) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  if (callee_specific_id->has_value()) {\n    callee_id = BuildCalleeSpecificFunction(context, loc_id, callee_id,\n                                            callee_function.self_type_id,\n                                            *callee_specific_id);\n  }\n\n  auto& callee = context.functions().Get(callee_function.function_id);\n  auto return_type_id =\n      callee.GetDeclaredReturnType(context.sem_ir(), *callee_specific_id);\n  if (!return_type_id.has_value()) {\n    return_type_id = GetTupleType(context, {});\n  }\n\n  llvm::SmallVector<SemIR::InstId, 1> return_arg_ids;\n  for (auto return_pattern_id :\n       context.inst_blocks().GetOrEmpty(callee.return_patterns_id)) {\n    Diagnostics::AnnotationScope annotate_diagnostics(\n        &context.emitter(), [&](auto& builder) {\n          CARBON_DIAGNOSTIC(IncompleteReturnTypeHere, Note,\n                            \"return type declared here\");\n          builder.Note(return_pattern_id, IncompleteReturnTypeHere);\n        });\n    auto arg_type_id = CheckFunctionReturnPatternType(\n        context, loc_id, return_pattern_id, *callee_specific_id);\n    if (arg_type_id == SemIR::ErrorInst::TypeId) {\n      return_type_id = SemIR::ErrorInst::TypeId;\n    }\n    switch (SemIR::InitRepr::ForType(context.sem_ir(), arg_type_id).kind) {\n      case SemIR::InitRepr::InPlace:\n      case SemIR::InitRepr::Dependent:\n        // Tentatively use storage for a temporary as the return argument.\n        // This will be replaced if necessary when we perform initialization.\n        return_arg_ids.push_back(AddInst<SemIR::TemporaryStorage>(\n            context, loc_id, {.type_id = arg_type_id}));\n        break;\n      case SemIR::InitRepr::None:\n      case SemIR::InitRepr::ByCopy:\n      case SemIR::InitRepr::Incomplete:\n      case SemIR::InitRepr::Abstract:\n        return_arg_ids.push_back(SemIR::InstId::None);\n        break;\n    }\n  }\n  // Convert the arguments to match the parameters.\n  auto converted_args_id = ConvertCallArgs(\n      context, loc_id, callee_function.self_id, arg_ids, return_arg_ids, callee,\n      *callee_specific_id, is_operator_syntax);\n  switch (callee.special_function_kind) {\n    case SemIR::Function::SpecialFunctionKind::Thunk: {\n      // If we're about to form a direct call to a thunk, inline it.\n      LoadImportRef(context, callee.thunk_decl_id());\n\n      // Name the thunk target within the enclosing scope of the thunk.\n      auto thunk_ref_id =\n          BuildNameRef(context, loc_id, callee.name_id, callee.thunk_decl_id(),\n                       callee_function.enclosing_specific_id);\n\n      // This recurses back into `PerformCall`. However, we never form a thunk\n      // to a thunk, so we only recurse once.\n      return PerformThunkCall(context, loc_id, callee_function.function_id,\n                              context.inst_blocks().Get(converted_args_id),\n                              thunk_ref_id);\n    }\n\n    case SemIR::Function::SpecialFunctionKind::HasCppThunk: {\n      return PerformCppThunkCall(context, loc_id, callee_function.function_id,\n                                 context.inst_blocks().Get(converted_args_id),\n                                 callee.cpp_thunk_decl_id());\n    }\n\n    case SemIR::Function::SpecialFunctionKind::None:\n    case SemIR::Function::SpecialFunctionKind::Builtin:\n    case SemIR::Function::SpecialFunctionKind::CoreWitness: {\n      return GetOrAddInst<SemIR::Call>(context, loc_id,\n                                       {.type_id = return_type_id,\n                                        .callee_id = callee_id,\n                                        .args_id = converted_args_id});\n    }\n  }\n}\n\n// Performs a call where the callee is a generic type. If it's not a generic\n// type, produces a diagnostic.\nstatic auto PerformCallToNonFunction(Context& context, SemIR::LocId loc_id,\n                                     SemIR::InstId callee_id,\n                                     llvm::ArrayRef<SemIR::InstId> arg_ids)\n    -> SemIR::InstId {\n  auto type_inst =\n      context.types().GetAsInst(context.insts().Get(callee_id).type_id());\n  CARBON_KIND_SWITCH(type_inst) {\n    case CARBON_KIND(SemIR::CppTemplateNameType template_name): {\n      return PerformCallToCppTemplateName(context, loc_id,\n                                          template_name.decl_id, arg_ids);\n    }\n    case CARBON_KIND(SemIR::GenericClassType generic_class): {\n      return PerformCallToGenericClass(context, loc_id, generic_class.class_id,\n                                       generic_class.enclosing_specific_id,\n                                       arg_ids);\n    }\n    case CARBON_KIND(SemIR::GenericInterfaceType generic_interface): {\n      return PerformCallToGenericInterfaceOrNamedConstaint(\n          context, loc_id, generic_interface.interface_id,\n          generic_interface.enclosing_specific_id, arg_ids);\n    }\n    case CARBON_KIND(SemIR::GenericNamedConstraintType generic_constraint): {\n      return PerformCallToGenericInterfaceOrNamedConstaint(\n          context, loc_id, generic_constraint.named_constraint_id,\n          generic_constraint.enclosing_specific_id, arg_ids);\n    }\n    default: {\n      CARBON_DIAGNOSTIC(CallToNonCallable, Error,\n                        \"value of type {0} is not callable\", TypeOfInstId);\n      context.emitter().Emit(loc_id, CallToNonCallable, callee_id);\n      return SemIR::ErrorInst::InstId;\n    }\n  }\n}\n\nauto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,\n                 llvm::ArrayRef<SemIR::InstId> arg_ids, bool is_operator_syntax)\n    -> SemIR::InstId {\n  // Try treating the callee as a function first.\n  auto callee = GetCallee(context.sem_ir(), callee_id);\n  CARBON_KIND_SWITCH(callee) {\n    case CARBON_KIND(SemIR::CalleeError _): {\n      return SemIR::ErrorInst::InstId;\n    }\n    case CARBON_KIND(SemIR::CalleeFunction fn): {\n      return PerformCallToFunction(context, loc_id, callee_id, fn, arg_ids,\n                                   is_operator_syntax);\n    }\n    case CARBON_KIND(SemIR::CalleeNonFunction _): {\n      return PerformCallToNonFunction(context, loc_id, callee_id, arg_ids);\n    }\n\n    case CARBON_KIND(SemIR::CalleeCppOverloadSet overload): {\n      return PerformCallToCppFunction(\n          context, loc_id, overload.cpp_overload_set_id, overload.self_id,\n          arg_ids, is_operator_syntax);\n    }\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/call.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CALL_H_\n#define CARBON_TOOLCHAIN_CHECK_CALL_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Checks and builds SemIR for a call to `callee_id` with arguments `args_id`,\n// where the callee is a function. `is_operator_syntax` indicates that this call\n// was generated from an operator rather than from function call syntax, so\n// arguments to `ref` parameters aren't required to have `ref` tags.\nauto PerformCallToFunction(Context& context, SemIR::LocId loc_id,\n                           SemIR::InstId callee_id,\n                           const SemIR::CalleeFunction& callee_function,\n                           llvm::ArrayRef<SemIR::InstId> arg_ids,\n                           bool is_operator_syntax) -> SemIR::InstId;\n\n// Checks and builds SemIR for a call to `callee_id` with arguments `args_id`.\n// `is_operator_syntax` indicates that this call\n// was generated from an operator rather than from function call syntax, so\n// arguments to `ref` parameters aren't required to have `ref` tags.\nauto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id,\n                 llvm::ArrayRef<SemIR::InstId> arg_ids,\n                 bool is_operator_syntax = false) -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CALL_H_\n"
  },
  {
    "path": "toolchain/check/check.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/check.h\"\n\n#include <string>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/map.h\"\n#include \"common/pretty_stack_trace_function.h\"\n#include \"toolchain/check/check_unit.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/diagnostic_emitter.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/diagnostics/consumer.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/lex/token_kind.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/parse/tree.h\"\n#include \"toolchain/sem_ir/file.h\"\n#include \"toolchain/sem_ir/formatter.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// The package and library names, used as map keys.\nusing ImportKey = std::pair<llvm::StringRef, llvm::StringRef>;\n\n// Returns a key form of the package object. file_package_id is only used for\n// imports, not the main package declaration; as a consequence, it will be\n// `None` for the main package declaration.\nstatic auto GetImportKey(UnitAndImports& unit_info,\n                         PackageNameId file_package_id,\n                         Parse::Tree::PackagingNames names) -> ImportKey {\n  auto* stores = unit_info.unit->value_stores;\n  PackageNameId package_id =\n      names.package_id.has_value() ? names.package_id : file_package_id;\n  llvm::StringRef package_name;\n  if (package_id.has_value()) {\n    auto package_ident_id = package_id.AsIdentifierId();\n    package_name = package_ident_id.has_value()\n                       ? stores->identifiers().Get(package_ident_id)\n                       : package_id.AsSpecialName();\n  }\n  llvm::StringRef library_name =\n      names.library_id.has_value()\n          ? stores->string_literal_values().Get(names.library_id)\n          : \"\";\n  return {package_name, library_name};\n}\n\nstatic constexpr llvm::StringLiteral MainPackageName = \"Main\";\n\nstatic auto RenderImportKey(ImportKey import_key) -> std::string {\n  if (import_key.first.empty()) {\n    import_key.first = MainPackageName;\n  }\n  if (import_key.second.empty()) {\n    return import_key.first.str();\n  }\n  return llvm::formatv(\"{0}//{1}\", import_key.first, import_key.second).str();\n}\n\n// Marks an import as required on both the source and target file.\n//\n// The ID comparisons between the import and unit are okay because they both\n// come from the same file.\nstatic auto TrackImport(Map<ImportKey, UnitAndImports*>& api_map,\n                        Map<ImportKey, Parse::NodeId>* explicit_import_map,\n                        UnitAndImports& unit_info,\n                        Parse::Tree::PackagingNames import, bool fuzzing)\n    -> void {\n  if (import.package_id == PackageNameId::Cpp) {\n    if (!explicit_import_map) {\n      // Don't diagnose the implicit import in `impl package Cpp`, because we'll\n      // have diagnosed the use of `Cpp` in the declaration.\n      return;\n    }\n    if (fuzzing) {\n      // Clang is not crash-resilient.\n      CARBON_DIAGNOSTIC(CppInteropFuzzing, Error,\n                        \"`Cpp` import found during fuzzing\");\n      unit_info.emitter.Emit(import.node_id, CppInteropFuzzing);\n      return;\n    }\n    unit_info.cpp_imports.push_back(import);\n    return;\n  }\n  if (import.inline_body_id.has_value()) {\n    CARBON_DIAGNOSTIC(InlineImportNotCpp, Error,\n                      \"`inline` import not in package `Cpp`\");\n    unit_info.emitter.Emit(import.node_id, InlineImportNotCpp);\n    return;\n  }\n\n  const auto& packaging = unit_info.parse_tree().packaging_decl();\n  PackageNameId file_package_id =\n      packaging ? packaging->names.package_id : PackageNameId::None;\n  const auto import_key = GetImportKey(unit_info, file_package_id, import);\n\n  // True if the import has `Main` as the package name, even if it comes from\n  // the file's packaging (diagnostics may differentiate).\n  bool is_explicit_main = import_key.first == MainPackageName;\n\n  // Explicit imports need more validation than implicit ones. We try to do\n  // these in an order of imports that should be removed, followed by imports\n  // that might be valid with syntax fixes.\n  if (explicit_import_map) {\n    // Diagnose redundant imports.\n    if (auto insert_result =\n            explicit_import_map->Insert(import_key, import.node_id);\n        !insert_result.is_inserted()) {\n      CARBON_DIAGNOSTIC(RepeatedImport, Error,\n                        \"library imported more than once\");\n      CARBON_DIAGNOSTIC(FirstImported, Note, \"first import here\");\n      unit_info.emitter.Build(import.node_id, RepeatedImport)\n          .Note(insert_result.value(), FirstImported)\n          .Emit();\n      return;\n    }\n\n    // True if the file's package is implicitly `Main` (by omitting an explicit\n    // package name).\n    bool is_file_implicit_main =\n        !packaging || !packaging->names.package_id.has_value();\n    // True if the import is using implicit \"current package\" syntax (by\n    // omitting an explicit package name).\n    bool is_import_implicit_current_package = !import.package_id.has_value();\n    // True if the import is using `default` library syntax.\n    bool is_import_default_library = !import.library_id.has_value();\n    // True if the import and file point at the same package, even by\n    // incorrectly specifying the current package name to `import`.\n    bool is_same_package = is_import_implicit_current_package ||\n                           import.package_id == file_package_id;\n    // True if the import points at the same library as the file's library.\n    bool is_same_library =\n        is_same_package &&\n        (packaging ? import.library_id == packaging->names.library_id\n                   : is_import_default_library);\n\n    // Diagnose explicit imports of the same library, whether from `api` or\n    // `impl`.\n    if (is_same_library) {\n      CARBON_DIAGNOSTIC(ExplicitImportApi, Error,\n                        \"explicit import of `api` from `impl` file is \"\n                        \"redundant with implicit import\");\n      CARBON_DIAGNOSTIC(ImportSelf, Error, \"file cannot import itself\");\n      bool is_impl = !packaging || packaging->is_impl;\n      unit_info.emitter.Emit(import.node_id,\n                             is_impl ? ExplicitImportApi : ImportSelf);\n      return;\n    }\n\n    // Diagnose explicit imports of `Main//default`. There is no `api` for it.\n    // This lets other diagnostics handle explicit `Main` package naming.\n    if (is_file_implicit_main && is_import_implicit_current_package &&\n        is_import_default_library) {\n      CARBON_DIAGNOSTIC(ImportMainDefaultLibrary, Error,\n                        \"cannot import `Main//default`\");\n      unit_info.emitter.Emit(import.node_id, ImportMainDefaultLibrary);\n\n      return;\n    }\n\n    if (!is_import_implicit_current_package) {\n      // Diagnose explicit imports of the same package that use the package\n      // name.\n      if (is_same_package || (is_file_implicit_main && is_explicit_main)) {\n        CARBON_DIAGNOSTIC(\n            ImportCurrentPackageByName, Error,\n            \"imports from the current package must omit the package name\");\n        unit_info.emitter.Emit(import.node_id, ImportCurrentPackageByName);\n        return;\n      }\n\n      // Diagnose explicit imports from `Main`.\n      if (is_explicit_main) {\n        CARBON_DIAGNOSTIC(ImportMainPackage, Error,\n                          \"cannot import `Main` from other packages\");\n        unit_info.emitter.Emit(import.node_id, ImportMainPackage);\n        return;\n      }\n    }\n  } else if (is_explicit_main) {\n    // An implicit import with an explicit `Main` occurs when a `package` rule\n    // has bad syntax, which will have been diagnosed when building the API map.\n    // As a consequence, we return silently.\n    return;\n  }\n\n  // Get the package imports, or create them if this is the first.\n  auto create_imports = [&]() -> int32_t {\n    int32_t index = unit_info.package_imports.size();\n    unit_info.package_imports.push_back(\n        PackageImports(import.package_id, import.node_id));\n    return index;\n  };\n  auto insert_result =\n      unit_info.package_imports_map.Insert(import.package_id, create_imports);\n  PackageImports& package_imports =\n      unit_info.package_imports[insert_result.value()];\n\n  if (auto api_lookup = api_map.Lookup(import_key)) {\n    // Add references between the file and imported api.\n    UnitAndImports* api = api_lookup.value();\n    package_imports.imports.push_back({import, api});\n    ++unit_info.imports_remaining;\n    api->incoming_imports.push_back(&unit_info);\n\n    // If this is the implicit import, note we have it.\n    if (!explicit_import_map) {\n      CARBON_CHECK(!unit_info.api_for_impl);\n      unit_info.api_for_impl = api;\n    }\n  } else {\n    // The imported api is missing.\n    package_imports.has_load_error = true;\n    CARBON_DIAGNOSTIC(LibraryApiNotFound, Error,\n                      \"corresponding API for '{0}' not found\", std::string);\n    CARBON_DIAGNOSTIC(ImportNotFound, Error, \"imported API '{0}' not found\",\n                      std::string);\n    unit_info.emitter.Emit(\n        import.node_id,\n        explicit_import_map ? ImportNotFound : LibraryApiNotFound,\n        RenderImportKey(import_key));\n  }\n}\n\n// Builds a map of `api` files which might be imported. Also diagnoses issues\n// related to the packaging because the strings are loaded as part of getting\n// the ImportKey (which we then do for `impl` files too).\nstatic auto BuildApiMapAndDiagnosePackaging(\n    llvm::MutableArrayRef<UnitAndImports> unit_infos)\n    -> Map<ImportKey, UnitAndImports*> {\n  Map<ImportKey, UnitAndImports*> api_map;\n  for (auto& unit_info : unit_infos) {\n    const auto& packaging = unit_info.parse_tree().packaging_decl();\n    // An import key formed from the `package` or `library` declaration. Or, for\n    // Main//default, a placeholder key.\n    auto import_key = packaging ? GetImportKey(unit_info, PackageNameId::None,\n                                               packaging->names)\n                                // Construct a boring key for Main//default.\n                                : ImportKey{\"\", \"\"};\n\n    // Diagnose restricted package names before they become marked as possible\n    // APIs.\n    if (import_key.first == MainPackageName) {\n      CARBON_DIAGNOSTIC(ExplicitMainPackage, Error,\n                        \"`Main//default` must omit `package` declaration\");\n      CARBON_DIAGNOSTIC(\n          ExplicitMainLibrary, Error,\n          \"use `library` declaration in `Main` package libraries\");\n      unit_info.emitter.Emit(packaging->names.node_id,\n                             import_key.second.empty() ? ExplicitMainPackage\n                                                       : ExplicitMainLibrary);\n      continue;\n    }\n    if (packaging && packaging->names.package_id == PackageNameId::Cpp) {\n      CARBON_DIAGNOSTIC(CppPackageDeclaration, Error,\n                        \"`Cpp` cannot be used by a `package` declaration\");\n      unit_info.emitter.Emit(packaging->names.node_id, CppPackageDeclaration);\n      continue;\n    }\n\n    bool is_impl = packaging && packaging->is_impl;\n\n    // Add to the `api` map and diagnose duplicates. This occurs before the\n    // file extension check because we might emit both diagnostics in situations\n    // where the user forgets (or has syntax errors with) a package line\n    // multiple times.\n    if (!is_impl) {\n      auto insert_result = api_map.Insert(import_key, &unit_info);\n      if (!insert_result.is_inserted()) {\n        llvm::StringRef prev_filename =\n            insert_result.value()->source().filename();\n        if (packaging) {\n          CARBON_DIAGNOSTIC(DuplicateLibraryApi, Error,\n                            \"library's API previously provided by `{0}`\",\n                            std::string);\n          unit_info.emitter.Emit(packaging->names.node_id, DuplicateLibraryApi,\n                                 prev_filename.str());\n        } else {\n          CARBON_DIAGNOSTIC(DuplicateMainApi, Error,\n                            \"`Main//default` previously provided by `{0}`\",\n                            std::string);\n          // Use `NodeId::None` because there's no node to associate with.\n          unit_info.emitter.Emit(Parse::NodeId::None, DuplicateMainApi,\n                                 prev_filename.str());\n        }\n      }\n    }\n\n    // Validate file extensions. Note imports rely the packaging declaration,\n    // not the extension. If the input is not a regular file, for example\n    // because it is stdin, no filename checking is performed.\n    if (unit_info.source().is_regular_file()) {\n      auto filename = unit_info.source().filename();\n      static constexpr llvm::StringLiteral ApiExt = \".carbon\";\n      static constexpr llvm::StringLiteral ImplExt = \".impl.carbon\";\n      bool is_api_with_impl_ext = !is_impl && filename.ends_with(ImplExt);\n      auto want_ext = is_impl ? ImplExt : ApiExt;\n      if (is_api_with_impl_ext || !filename.ends_with(want_ext)) {\n        CARBON_DIAGNOSTIC(\n            IncorrectExtension, Error,\n            \"file extension of `{0:.impl|}.carbon` required for {0:`impl`|api}\",\n            Diagnostics::BoolAsSelect);\n        auto diag = unit_info.emitter.Build(\n            packaging ? packaging->names.node_id : Parse::NodeId::None,\n            IncorrectExtension, is_impl);\n        if (is_api_with_impl_ext) {\n          CARBON_DIAGNOSTIC(\n              IncorrectExtensionImplNote, Note,\n              \"file extension of `.impl.carbon` only allowed for `impl`\");\n          diag.Note(Parse::NodeId::None, IncorrectExtensionImplNote);\n        }\n        diag.Emit();\n      }\n    }\n  }\n  return api_map;\n}\n\n// Handles printing of formatted SemIR.\nstatic auto MaybeDumpFormattedSemIR(\n    const SemIR::File& sem_ir, int total_ir_count,\n    Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter, bool include_in_dumps,\n    const CheckParseTreesOptions& options) -> void {\n  bool dump = options.dump_stream && include_in_dumps;\n  if (!options.vlog_stream && !dump) {\n    return;\n  }\n\n  const auto& tokens = sem_ir.parse_tree().tokens();\n  if (options.dump_sem_ir_ranges ==\n          CheckParseTreesOptions::DumpSemIRRanges::Only &&\n      !tokens.has_dump_sem_ir_ranges() && !tokens.has_include_in_dumps()) {\n    return;\n  }\n\n  bool use_dump_sem_ir_ranges =\n      options.dump_sem_ir_ranges !=\n          CheckParseTreesOptions::DumpSemIRRanges::Ignore &&\n      tokens.has_dump_sem_ir_ranges();\n  SemIR::Formatter formatter(&sem_ir, total_ir_count, tree_and_subtrees_getter,\n                             options.include_in_dumps, use_dump_sem_ir_ranges);\n  formatter.Format();\n  if (options.vlog_stream) {\n    CARBON_VLOG_TO(options.vlog_stream, \"*** SemIR::File ***\\n\");\n    formatter.Write(*options.vlog_stream);\n  }\n  if (dump) {\n    formatter.Write(*options.dump_stream);\n  }\n}\n\n// Handles options for dumping SemIR, including verbose output.\nstatic auto MaybeDumpSemIR(\n    llvm::ArrayRef<Unit> units,\n    const Parse::GetTreeAndSubtreesStore& tree_and_subtrees_getters,\n    const CheckParseTreesOptions& options) -> void {\n  if (!options.vlog_stream && !options.dump_stream &&\n      !options.raw_dump_stream) {\n    return;\n  }\n\n  // Flush diagnostics before printing.\n  for (const auto& unit : units) {\n    unit.consumer->Flush();\n  }\n\n  for (const auto& unit : units) {\n    bool include_in_dumps =\n        options.include_in_dumps->Get(unit.sem_ir->check_ir_id());\n    if (include_in_dumps && options.raw_dump_stream) {\n      unit.sem_ir->Print(*options.raw_dump_stream,\n                         options.dump_raw_sem_ir_builtins);\n    }\n\n    MaybeDumpFormattedSemIR(\n        *unit.sem_ir, units.size(),\n        tree_and_subtrees_getters.Get(unit.sem_ir->check_ir_id()),\n        include_in_dumps, options);\n  }\n}\n\n// Handles options for dumping C++ AST.\nstatic auto MaybeDumpCppAST(llvm::ArrayRef<Unit> units,\n                            const CheckParseTreesOptions& options) -> void {\n  if (!options.dump_cpp_ast_stream) {\n    return;\n  }\n\n  for (const Unit& unit : units) {\n    if (options.include_in_dumps->Get(unit.sem_ir->check_ir_id())) {\n      if (auto* cpp_file = unit.sem_ir->cpp_file()) {\n        cpp_file->ast_context().getTranslationUnitDecl()->dump(\n            *options.dump_cpp_ast_stream);\n      }\n    }\n  }\n}\n\nauto CheckParseTrees(\n    llvm::MutableArrayRef<Unit> units,\n    const Parse::GetTreeAndSubtreesStore& tree_and_subtrees_getters,\n    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n    const CheckParseTreesOptions& options,\n    std::shared_ptr<clang::CompilerInvocation> clang_invocation) -> void {\n  // UnitAndImports is big due to its SmallVectors, so we default to 0 on the\n  // stack.\n  llvm::SmallVector<UnitAndImports, 0> unit_infos(\n      llvm::map_range(units, [&](Unit& unit) {\n        return UnitAndImports(\n            &unit, tree_and_subtrees_getters.Get(unit.sem_ir->check_ir_id()));\n      }));\n\n  // Dump the raw SemIR in the event of a crash. We dump it to a separate file\n  // to keep the stack trace manageable.\n  PrettyStackTraceFunction sem_ir_dumper([&](llvm::raw_ostream& output) {\n    if (!options.sem_ir_crash_dump.empty()) {\n      output << \"Dumping raw SemIR to \" << options.sem_ir_crash_dump << \"\\n\";\n      std::error_code error_code;\n      llvm::raw_fd_ostream sem_ir_dump(options.sem_ir_crash_dump, error_code);\n      if (error_code) {\n        output << \"Raw SemIR dump failed: \" << error_code.category().name()\n               << \":\" << error_code.value() << \": \" << error_code.message()\n               << \"\\n\";\n      } else {\n        for (const auto& unit_info : unit_infos) {\n          if (unit_info.is_checked && unit_info.unit->sem_ir != nullptr) {\n            unit_info.unit->sem_ir->Print(sem_ir_dump);\n          }\n        }\n      }\n    }\n  });\n\n  Map<ImportKey, UnitAndImports*> api_map =\n      BuildApiMapAndDiagnosePackaging(unit_infos);\n\n  // Mark down imports for all files.\n  llvm::SmallVector<UnitAndImports*> ready_to_check;\n  ready_to_check.reserve(units.size());\n  for (auto& unit_info : unit_infos) {\n    const auto& packaging = unit_info.parse_tree().packaging_decl();\n    if (packaging && packaging->is_impl) {\n      // An `impl` has an implicit import of its `api`.\n      auto implicit_names = packaging->names;\n      implicit_names.package_id = PackageNameId::None;\n      TrackImport(api_map, nullptr, unit_info, implicit_names, options.fuzzing);\n    }\n\n    Map<ImportKey, Parse::NodeId> explicit_import_map;\n\n    // Add the prelude import. It's added to explicit_import_map so that it can\n    // conflict with an explicit import of the prelude.\n    if (options.prelude_import &&\n        !(packaging && packaging->names.package_id == PackageNameId::Core)) {\n      auto prelude_id =\n          unit_info.unit->value_stores->string_literal_values().Add(\"prelude\");\n      TrackImport(api_map, &explicit_import_map, unit_info,\n                  {.node_id = Parse::NoneNodeId(),\n                   .package_id = PackageNameId::Core,\n                   .library_id = prelude_id},\n                  options.fuzzing);\n    }\n\n    for (const auto& import : unit_info.parse_tree().imports()) {\n      TrackImport(api_map, &explicit_import_map, unit_info, import,\n                  options.fuzzing);\n    }\n\n    // If there were no imports, mark the file as ready to check for below.\n    if (unit_info.imports_remaining == 0) {\n      ready_to_check.push_back(&unit_info);\n    }\n  }\n\n  // Check everything with no dependencies. Earlier entries with dependencies\n  // will be checked as soon as all their dependencies have been checked.\n  for (int check_index = 0;\n       check_index < static_cast<int>(ready_to_check.size()); ++check_index) {\n    auto* unit_info = ready_to_check[check_index];\n    CheckUnit(unit_info, &tree_and_subtrees_getters, fs,\n              unit_info->unit->llvm_context, clang_invocation,\n              options.vlog_stream)\n        .Run();\n    for (auto* incoming_import : unit_info->incoming_imports) {\n      --incoming_import->imports_remaining;\n      if (incoming_import->imports_remaining == 0) {\n        ready_to_check.push_back(incoming_import);\n      }\n    }\n  }\n\n  // If there are still units with remaining imports, it means there's a\n  // dependency loop.\n  if (ready_to_check.size() < unit_infos.size()) {\n    // Go through units and mask out unevaluated imports. This breaks everything\n    // associated with a loop equivalently, whether it's part of it or depending\n    // on a part of it.\n    // TODO: Better identify cycles, maybe try to untangle them.\n    for (auto& unit_info : unit_infos) {\n      if (unit_info.imports_remaining > 0) {\n        for (auto& package_imports : unit_info.package_imports) {\n          for (auto* import_it = package_imports.imports.begin();\n               import_it != package_imports.imports.end();) {\n            if (import_it->unit_info->is_checked) {\n              // The import is checked, so continue.\n              ++import_it;\n            } else {\n              // The import hasn't been checked, indicating a cycle.\n              CARBON_DIAGNOSTIC(ImportCycleDetected, Error,\n                                \"import cannot be used due to a cycle; cycle \"\n                                \"must be fixed to import\");\n              unit_info.emitter.Emit(import_it->names.node_id,\n                                     ImportCycleDetected);\n              // Make this look the same as an import which wasn't found.\n              package_imports.has_load_error = true;\n              if (unit_info.api_for_impl == import_it->unit_info) {\n                unit_info.api_for_impl = nullptr;\n              }\n              import_it = package_imports.imports.erase(import_it);\n            }\n          }\n        }\n      }\n    }\n\n    // Check the remaining file contents, which are probably broken due to\n    // incomplete imports.\n    for (auto& unit_info : unit_infos) {\n      if (unit_info.imports_remaining > 0) {\n        CheckUnit(&unit_info, &tree_and_subtrees_getters, fs,\n                  unit_info.unit->llvm_context, clang_invocation,\n                  options.vlog_stream)\n            .Run();\n      }\n    }\n  }\n\n  MaybeDumpSemIR(units, tree_and_subtrees_getters, options);\n  MaybeDumpCppAST(units, options);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/check.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CHECK_H_\n#define CARBON_TOOLCHAIN_CHECK_CHECK_H_\n\n#include \"clang/Frontend/CompilerInvocation.h\"\n#include \"common/ostream.h\"\n#include \"toolchain/base/shared_value_stores.h\"\n#include \"toolchain/base/timings.h\"\n#include \"toolchain/check/diagnostic_emitter.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/parse/tree_and_subtrees.h\"\n#include \"toolchain/sem_ir/file.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Checking information that's tracked per file. All members are caller-owned.\n// Other than `timings`, members must be non-null.\nstruct Unit {\n  Diagnostics::Consumer* consumer;\n  SharedValueStores* value_stores;\n  // The `timings` may be null if nothing is to be recorded.\n  Timings* timings;\n\n  // The unit's SemIR, provided as empty and filled in by CheckParseTrees.\n  SemIR::File* sem_ir;\n  llvm::LLVMContext* llvm_context;\n  // The total number of files.\n  int total_ir_count;\n};\n\nstruct CheckParseTreesOptions {\n  // Options must be set individually, not through initialization.\n  explicit CheckParseTreesOptions() = default;\n\n  // Whether to import the prelude.\n  bool prelude_import = false;\n\n  // If set, enables verbose output.\n  llvm::raw_ostream* vlog_stream = nullptr;\n\n  // Whether fuzzing is being run. Used to disable features we don't want to\n  // fuzz.\n  bool fuzzing = false;\n\n  // Whether to include each unit in dumps. This is required when dumping\n  // (either of `dump_stream` or `raw_dump_stream`), and must have entries based\n  // on CheckIRId.\n  const FixedSizeValueStore<SemIR::CheckIRId, bool>* include_in_dumps = nullptr;\n\n  // If set, SemIR will be dumped to this.\n  llvm::raw_ostream* dump_stream = nullptr;\n\n  // If set, C++ AST will be dumped to this.\n  llvm::raw_ostream* dump_cpp_ast_stream = nullptr;\n\n  // When dumping textual SemIR (or printing it to for verbose output), whether\n  // to use ranges.\n  enum class DumpSemIRRanges : int8_t {\n    IfPresent,\n    Only,\n    Ignore,\n  };\n  DumpSemIRRanges dump_sem_ir_ranges = DumpSemIRRanges::IfPresent;\n\n  // If set, raw SemIR will be dumped to this.\n  llvm::raw_ostream* raw_dump_stream = nullptr;\n\n  // When dumping raw SemIR, whether to include builtins.\n  bool dump_raw_sem_ir_builtins = false;\n\n  // If not empty, a raw SemIR dump should be written to this path in the event\n  // of a crash.\n  llvm::StringRef sem_ir_crash_dump;\n};\n\n// Checks a group of parse trees. This will use imports to decide the order of\n// checking.\n//\n// `units` will only contain units which should be checked, and is not indexed\n// by `CheckIRId`.\nauto CheckParseTrees(\n    llvm::MutableArrayRef<Unit> units,\n    const Parse::GetTreeAndSubtreesStore& tree_and_subtrees_getters,\n    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n    const CheckParseTreesOptions& options,\n    std::shared_ptr<clang::CompilerInvocation> clang_invocation) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CHECK_H_\n"
  },
  {
    "path": "toolchain/check/check_fuzzer.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/exe_path.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/MemoryBuffer.h\"\n#include \"llvm/Support/VirtualFileSystem.h\"\n#include \"testing/fuzzing/libfuzzer.h\"\n#include \"toolchain/driver/driver.h\"\n\nnamespace Carbon::Testing {\n\nstatic const InstallPaths* install_paths = nullptr;\n\n// NOLINTNEXTLINE(readability-non-const-parameter): External API required types.\nextern \"C\" auto LLVMFuzzerInitialize(int* argc, char*** argv) -> int {\n  CARBON_CHECK(*argc >= 1, \"Need the `argv[0]` value to initialize!\");\n  install_paths = new InstallPaths(\n      InstallPaths::MakeForBazelRunfiles(FindExecutablePath((*argv)[0])));\n  return 0;\n}\n\n// NOLINTNEXTLINE: Match the documented fuzzer entry point declaration style.\nextern \"C\" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) {\n  // Ignore large inputs.\n  // TODO: See tokenized_buffer_fuzzer.cpp.\n  if (size > 100000) {\n    return 0;\n  }\n\n  static constexpr llvm::StringLiteral TestFileName = \"test.carbon\";\n  llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> fs =\n      new llvm::vfs::InMemoryFileSystem;\n  llvm::StringRef data_ref(reinterpret_cast<const char*>(data), size);\n  CARBON_CHECK(fs->addFile(\n      TestFileName, /*ModificationTime=*/0,\n      llvm::MemoryBuffer::getMemBuffer(data_ref, /*BufferName=*/TestFileName,\n                                       /*RequiresNullTerminator=*/false)));\n\n  llvm::raw_null_ostream null_ostream;\n  Driver driver(fs, install_paths, /*input_stream=*/nullptr, &null_ostream,\n                &null_ostream, /*fuzzing=*/true);\n\n  // TODO: Get checking to a point where it can handle invalid parse trees\n  // without crashing.\n  if (!driver.RunCommand({\"compile\", \"--phase=parse\", TestFileName}).success) {\n    return 0;\n  }\n  driver.RunCommand({\"compile\", \"--phase=check\", TestFileName});\n  return 0;\n}\n\n}  // namespace Carbon::Testing\n"
  },
  {
    "path": "toolchain/check/check_unit.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/check_unit.h\"\n\n#include <iterator>\n#include <string>\n#include <tuple>\n#include <utility>\n\n#include \"clang/Sema/Sema.h\"\n#include \"common/growing_range.h\"\n#include \"common/pretty_stack_trace_function.h\"\n#include \"llvm/ADT/IntrusiveRefCntPtr.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/VirtualFileSystem.h\"\n#include \"toolchain/base/fixed_size_value_store.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/cpp/generate_ast.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/impl.h\"\n#include \"toolchain/check/impl_lookup.h\"\n#include \"toolchain/check/impl_validation.h\"\n#include \"toolchain/check/import.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/node_id_traversal.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_structure.h\"\n#include \"toolchain/check/unused.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/import_ir.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Returns the number of imported IRs, to assist in Context construction.\nstatic auto GetImportedIRCount(UnitAndImports* unit_and_imports) -> int {\n  int count = 0;\n  for (auto& package_imports : unit_and_imports->package_imports) {\n    count += package_imports.imports.size();\n  }\n  if (!unit_and_imports->api_for_impl) {\n    // Leave an empty slot for `ImportIRId::ApiForImpl`.\n    ++count;\n  }\n  if (!unit_and_imports->cpp_imports.empty()) {\n    // Leave an empty slot for `ImportIRId::Cpp`.\n    ++count;\n  }\n  return count;\n}\n\nCheckUnit::CheckUnit(\n    UnitAndImports* unit_and_imports,\n    const Parse::GetTreeAndSubtreesStore* tree_and_subtrees_getters,\n    llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n    llvm::LLVMContext* llvm_context,\n    std::shared_ptr<clang::CompilerInvocation> clang_invocation,\n    llvm::raw_ostream* vlog_stream)\n    : unit_and_imports_(unit_and_imports),\n      tree_and_subtrees_getter_(tree_and_subtrees_getters->Get(\n          unit_and_imports->unit->sem_ir->check_ir_id())),\n      fs_(std::move(fs)),\n      llvm_context_(llvm_context),\n      clang_invocation_(std::move(clang_invocation)),\n      emitter_(&unit_and_imports_->err_tracker, tree_and_subtrees_getters,\n               unit_and_imports_->unit->sem_ir),\n      context_(&emitter_, tree_and_subtrees_getter_,\n               unit_and_imports_->unit->sem_ir,\n               GetImportedIRCount(unit_and_imports),\n               unit_and_imports_->unit->total_ir_count, vlog_stream) {}\n\nauto CheckUnit::Run() -> void {\n  Timings::ScopedTiming timing(unit_and_imports_->unit->timings, \"check\");\n\n  // We can safely mark this as checked at the start.\n  unit_and_imports_->is_checked = true;\n\n  PrettyStackTraceFunction context_dumper(\n      [&](llvm::raw_ostream& output) { context_.PrintForStackDump(output); });\n\n  // Add a block for the file.\n  context_.inst_block_stack().Push();\n\n  InitPackageScopeAndImports();\n\n  // Eagerly import the impls declared in the api file to prepare to redeclare\n  // them.\n  ImportImplsFromApiFile(context_);\n\n  if (!ProcessNodeIds()) {\n    context_.sem_ir().set_has_errors(true);\n    return;\n  }\n\n  FinishRun();\n}\n\nauto CheckUnit::InitPackageScopeAndImports() -> void {\n  // Importing makes many namespaces, so only canonicalize the type once.\n  auto namespace_type_id =\n      GetSingletonType(context_, SemIR::NamespaceType::TypeInstId);\n\n  // Use the name of the package for the package scope.\n  SemIR::NameId package_name_id = SemIR::NameId::MainPackage;\n  const auto& packaging = context_.parse_tree().packaging_decl();\n  if (packaging && packaging->names.package_id.has_value()) {\n    package_name_id =\n        SemIR::NameId::ForPackageName(packaging->names.package_id);\n  }\n\n  // Define the package scope, with an instruction for `package` expressions to\n  // reference.\n  auto package_scope_id =\n      context_.name_scopes().Add(SemIR::Namespace::PackageInstId,\n                                 package_name_id, SemIR::NameScopeId::None);\n  CARBON_CHECK(package_scope_id == SemIR::NameScopeId::Package);\n\n  auto package_inst_id =\n      AddInst<SemIR::Namespace>(context_, Parse::NodeId::None,\n                                {.type_id = namespace_type_id,\n                                 .name_scope_id = SemIR::NameScopeId::Package,\n                                 .import_id = SemIR::InstId::None});\n  CARBON_CHECK(package_inst_id == SemIR::Namespace::PackageInstId);\n\n  // Call `SetSpecialImportIRs()` to set `ImportIRId::ApiForImpl` and\n  // `ImportIRId::Cpp` first, as required.\n  if (unit_and_imports_->api_for_impl) {\n    const auto& names = packaging->names;\n    auto import_decl_id = AddInst<SemIR::ImportDecl>(\n        context_, names.node_id,\n        {.package_id = SemIR::NameId::ForPackageName(names.package_id)});\n    SetSpecialImportIRs(\n        context_, {.decl_id = import_decl_id,\n                   .is_export = false,\n                   .sem_ir = unit_and_imports_->api_for_impl->unit->sem_ir});\n  } else {\n    SetSpecialImportIRs(context_,\n                        {.decl_id = SemIR::InstId::None, .sem_ir = nullptr});\n  }\n\n  // Add import instructions for everything directly imported. Implicit imports\n  // are handled separately.\n  for (auto& package_imports : unit_and_imports_->package_imports) {\n    CARBON_CHECK(!package_imports.import_decl_id.has_value());\n    package_imports.import_decl_id = AddInst<SemIR::ImportDecl>(\n        context_, package_imports.node_id,\n        {.package_id =\n             SemIR::NameId::ForPackageName(package_imports.package_id)});\n  }\n  // Process the imports.\n  if (unit_and_imports_->api_for_impl) {\n    ImportApiFile(context_, namespace_type_id,\n                  *unit_and_imports_->api_for_impl->unit->sem_ir);\n  }\n  ImportCurrentPackage(package_inst_id, namespace_type_id);\n  CARBON_CHECK(context_.scope_stack().PeekIndex() == ScopeIndex::Package);\n  ImportOtherPackages(namespace_type_id);\n\n  const auto& cpp_imports = unit_and_imports_->cpp_imports;\n  if (!cpp_imports.empty()) {\n    ImportCpp(context_, cpp_imports, fs_, llvm_context_, clang_invocation_);\n  }\n}\n\nauto CheckUnit::CollectDirectImports(\n    llvm::SmallVector<SemIR::ImportIR>& results,\n    CheckIRIdToIntStore& ir_to_result_index, SemIR::InstId import_decl_id,\n    const PackageImports& imports, bool is_local) -> void {\n  for (const auto& import : imports.imports) {\n    const auto& direct_ir = *import.unit_info->unit->sem_ir;\n    auto& index = ir_to_result_index.Get(direct_ir.check_ir_id());\n    if (index != -1) {\n      // This should only happen when doing API imports for an implementation\n      // file. Don't change the entry; is_export doesn't matter.\n      continue;\n    }\n    index = results.size();\n    results.push_back({.decl_id = import_decl_id,\n                       // Only tag exports in API files, ignoring the value in\n                       // implementation files.\n                       .is_export = is_local && import.names.is_export,\n                       .sem_ir = &direct_ir});\n  }\n}\n\nauto CheckUnit::CollectTransitiveImports(SemIR::InstId import_decl_id,\n                                         const PackageImports* local_imports,\n                                         const PackageImports* api_imports)\n    -> llvm::SmallVector<SemIR::ImportIR> {\n  llvm::SmallVector<SemIR::ImportIR> results;\n\n  // Track whether an IR was imported in full, including `export import`. This\n  // distinguishes from IRs that are indirectly added without all names being\n  // exported to this IR.\n  auto ir_to_result_index = CheckIRIdToIntStore::MakeWithExplicitSize(\n      unit_and_imports_->unit->total_ir_count, -1);\n\n  // First add direct imports. This means that if an entity is imported both\n  // directly and indirectly, the import path will reflect the direct import.\n  if (local_imports) {\n    CollectDirectImports(results, ir_to_result_index, import_decl_id,\n                         *local_imports,\n                         /*is_local=*/true);\n  }\n  if (api_imports) {\n    CollectDirectImports(results, ir_to_result_index, import_decl_id,\n                         *api_imports,\n                         /*is_local=*/false);\n  }\n\n  // Loop through direct imports for any indirect exports. The underlying vector\n  // is appended during iteration, so take the size first.\n  const int direct_imports = results.size();\n  for (int direct_index : llvm::seq(direct_imports)) {\n    bool is_export = results[direct_index].is_export;\n\n    for (const auto& indirect_ir :\n         results[direct_index].sem_ir->import_irs().values()) {\n      if (!indirect_ir.is_export) {\n        continue;\n      }\n\n      auto& indirect_index =\n          ir_to_result_index.Get(indirect_ir.sem_ir->check_ir_id());\n      if (indirect_index == -1) {\n        indirect_index = results.size();\n        // TODO: In the case of a recursive `export import`, this only points at\n        // the outermost import. May want something that better reflects the\n        // recursion.\n        results.push_back({.decl_id = results[direct_index].decl_id,\n                           .is_export = is_export,\n                           .sem_ir = indirect_ir.sem_ir});\n      } else if (is_export) {\n        results[indirect_index].is_export = true;\n      }\n    }\n  }\n\n  return results;\n}\n\nauto CheckUnit::ImportCurrentPackage(SemIR::InstId package_inst_id,\n                                     SemIR::TypeId namespace_type_id) -> void {\n  // Add imports from the current package.\n  auto import_map_lookup =\n      unit_and_imports_->package_imports_map.Lookup(PackageNameId::None);\n  if (!import_map_lookup) {\n    // Push the scope; there are no names to add.\n    context_.scope_stack().PushForEntity(\n        package_inst_id, SemIR::NameScopeId::Package, SemIR::SpecificId::None,\n        /*lexical_lookup_has_load_error=*/false);\n    return;\n  }\n  PackageImports& self_import =\n      unit_and_imports_->package_imports[import_map_lookup.value()];\n\n  if (self_import.has_load_error) {\n    context_.name_scopes().Get(SemIR::NameScopeId::Package).set_has_error();\n  }\n\n  ImportLibrariesFromCurrentPackage(\n      context_, namespace_type_id,\n      CollectTransitiveImports(self_import.import_decl_id, &self_import,\n                               /*api_imports=*/nullptr));\n\n  context_.scope_stack().PushForEntity(\n      package_inst_id, SemIR::NameScopeId::Package, SemIR::SpecificId::None,\n      context_.name_scopes().Get(SemIR::NameScopeId::Package).has_error());\n}\n\nauto CheckUnit::ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void {\n  // api_imports_list is initially the size of the current file's imports,\n  // including for API files, for simplicity in iteration. It's only really used\n  // when processing an implementation file, in order to combine the API file\n  // imports.\n  //\n  // For packages imported by the API file, the PackageNameId is the package\n  // name and the index is into the API's import list. Otherwise, the initial\n  // {None, -1} state remains.\n  llvm::SmallVector<std::pair<PackageNameId, int32_t>> api_imports_list;\n  api_imports_list.resize(unit_and_imports_->package_imports.size(),\n                          {PackageNameId::None, -1});\n\n  // When there's an API file, add the mapping to api_imports_list.\n  if (unit_and_imports_->api_for_impl) {\n    const auto& api_identifiers =\n        unit_and_imports_->api_for_impl->unit->value_stores->identifiers();\n    auto& impl_identifiers =\n        unit_and_imports_->unit->value_stores->identifiers();\n\n    for (auto [api_imports_index, api_imports] :\n         llvm::enumerate(unit_and_imports_->api_for_impl->package_imports)) {\n      // Skip the current package.\n      if (!api_imports.package_id.has_value()) {\n        continue;\n      }\n\n      // Translate the package ID from the API file to the implementation file.\n      auto impl_package_id = api_imports.package_id;\n      if (auto package_identifier_id = impl_package_id.AsIdentifierId();\n          package_identifier_id.has_value()) {\n        impl_package_id = PackageNameId::ForIdentifier(\n            impl_identifiers.Add(api_identifiers.Get(package_identifier_id)));\n      }\n\n      if (auto lookup =\n              unit_and_imports_->package_imports_map.Lookup(impl_package_id)) {\n        // On a hit, replace the entry to unify the API and implementation\n        // imports.\n        api_imports_list[lookup.value()] = {impl_package_id, api_imports_index};\n      } else {\n        // On a miss, add the package as API-only.\n        api_imports_list.push_back({impl_package_id, api_imports_index});\n      }\n    }\n  }\n\n  for (auto [i, api_imports_entry] : llvm::enumerate(api_imports_list)) {\n    // These variables are updated after figuring out which imports are present.\n    auto import_decl_id = SemIR::InstId::None;\n    PackageNameId package_id = PackageNameId::None;\n    bool has_load_error = false;\n\n    // Identify the local package imports if present.\n    PackageImports* local_imports = nullptr;\n    if (i < unit_and_imports_->package_imports.size()) {\n      local_imports = &unit_and_imports_->package_imports[i];\n      if (!local_imports->package_id.has_value()) {\n        // Skip the current package.\n        continue;\n      }\n      import_decl_id = local_imports->import_decl_id;\n\n      package_id = local_imports->package_id;\n      has_load_error |= local_imports->has_load_error;\n    }\n\n    // Identify the API package imports if present.\n    PackageImports* api_imports = nullptr;\n    if (api_imports_entry.second != -1) {\n      api_imports = &unit_and_imports_->api_for_impl\n                         ->package_imports[api_imports_entry.second];\n\n      if (local_imports) {\n        CARBON_CHECK(package_id == api_imports_entry.first);\n      } else {\n        auto import_ir_inst_id =\n            context_.import_ir_insts().Add(SemIR::ImportIRInst(\n                SemIR::ImportIRId::ApiForImpl, api_imports->import_decl_id));\n        import_decl_id =\n            AddInst(context_, MakeImportedLocIdAndInst<SemIR::ImportDecl>(\n                                  context_, import_ir_inst_id,\n                                  {.package_id = SemIR::NameId::ForPackageName(\n                                       api_imports_entry.first)}));\n        package_id = api_imports_entry.first;\n      }\n      has_load_error |= api_imports->has_load_error;\n    }\n\n    // Do the actual import.\n    ImportLibrariesFromOtherPackage(\n        context_, namespace_type_id, import_decl_id, package_id,\n        CollectTransitiveImports(import_decl_id, local_imports, api_imports),\n        has_load_error);\n  }\n}\n\n// Loops over all nodes in the tree. On some errors, this may return early,\n// for example if an unrecoverable state is encountered.\nauto CheckUnit::ProcessNodeIds() -> bool {\n  NodeIdTraversal traversal(&context_);\n\n  Parse::NodeId node_id = Parse::NodeId::None;\n\n  // On crash, report which token we were handling.\n  PrettyStackTraceFunction node_dumper([&](llvm::raw_ostream& output) {\n    const auto& tree = tree_and_subtrees_getter_();\n    auto converted = tree.NodeToDiagnosticLoc(node_id, /*token_only=*/false);\n    converted.loc.FormatLocation(output);\n    output << \"Checking \" << context_.parse_tree().node_kind(node_id) << \"\\n\";\n    // Crash output has a tab indent; try to indent slightly past that.\n    converted.loc.FormatSnippet(output, /*indent=*/10);\n  });\n\n  while (auto maybe_node_id = traversal.Next()) {\n    node_id = *maybe_node_id;\n\n    emitter_.AdvanceToken(context_.parse_tree().node_token(node_id));\n\n    if (context_.parse_tree().node_has_error(node_id)) {\n      context_.TODO(node_id, \"handle invalid parse trees in `check`\");\n      return false;\n    }\n\n    bool result;\n    auto parse_kind = context_.parse_tree().node_kind(node_id);\n    switch (parse_kind) {\n#define CARBON_PARSE_NODE_KIND(Name)                                   \\\n  case Parse::NodeKind::Name: {                                        \\\n    result = HandleParseNode(                                          \\\n        context_, context_.parse_tree().As<Parse::Name##Id>(node_id)); \\\n    break;                                                             \\\n  }\n#include \"toolchain/parse/node_kind.def\"\n    }\n\n    if (!result) {\n      CARBON_CHECK(\n          unit_and_imports_->err_tracker.seen_error(),\n          \"HandleParseNode for `{0}` returned false without diagnosing.\",\n          parse_kind);\n      return false;\n    }\n    traversal.Handle(parse_kind);\n  }\n  return true;\n}\n\nauto CheckUnit::CheckRequiredDeclarations() -> void {\n  for (const auto& function : context_.functions().values()) {\n    if (!function.first_owning_decl_id.has_value() &&\n        function.extern_library_id == context_.sem_ir().library_id()) {\n      auto function_import_id =\n          context_.insts().GetImportSource(function.non_owning_decl_id);\n      CARBON_CHECK(function_import_id.has_value());\n      auto import_ir_id =\n          context_.sem_ir().import_ir_insts().Get(function_import_id).ir_id();\n      auto& import_ir = context_.import_irs().Get(import_ir_id);\n      if (import_ir.sem_ir->package_id().has_value() !=\n          context_.sem_ir().package_id().has_value()) {\n        continue;\n      }\n\n      CARBON_DIAGNOSTIC(\n          MissingOwningDeclarationInApi, Error,\n          \"owning declaration required for non-owning declaration\");\n      if (!import_ir.sem_ir->package_id().has_value() &&\n          !context_.sem_ir().package_id().has_value()) {\n        emitter_.Emit(function.non_owning_decl_id,\n                      MissingOwningDeclarationInApi);\n        continue;\n      }\n\n      if (import_ir.sem_ir->identifiers().Get(\n              import_ir.sem_ir->package_id().AsIdentifierId()) ==\n          context_.sem_ir().identifiers().Get(\n              context_.sem_ir().package_id().AsIdentifierId())) {\n        emitter_.Emit(function.non_owning_decl_id,\n                      MissingOwningDeclarationInApi);\n      }\n    }\n  }\n}\n\nauto CheckUnit::CheckRequiredDefinitions() -> void {\n  CARBON_DIAGNOSTIC(MissingDefinitionInImpl, Error,\n                    \"no definition found for declaration in impl file\");\n  for (SemIR::InstId decl_inst_id : context_.definitions_required_by_decl()) {\n    SemIR::Inst decl_inst = context_.insts().Get(decl_inst_id);\n    CARBON_KIND_SWITCH(context_.insts().Get(decl_inst_id)) {\n      case CARBON_KIND(SemIR::ClassDecl class_decl): {\n        if (!context_.classes().Get(class_decl.class_id).is_complete()) {\n          emitter_.Emit(decl_inst_id, MissingDefinitionInImpl);\n        }\n        break;\n      }\n      case CARBON_KIND(SemIR::FunctionDecl function_decl): {\n        if (context_.functions().Get(function_decl.function_id).definition_id ==\n            SemIR::InstId::None) {\n          emitter_.Emit(decl_inst_id, MissingDefinitionInImpl);\n        }\n        break;\n      }\n      case CARBON_KIND(SemIR::ImplDecl impl_decl): {\n        auto& impl = context_.impls().Get(impl_decl.impl_id);\n        if (!impl.is_complete()) {\n          FillImplWitnessWithErrors(context_, impl);\n          CARBON_DIAGNOSTIC(ImplMissingDefinition, Error,\n                            \"impl declared but not defined\");\n          emitter_.Emit(decl_inst_id, ImplMissingDefinition);\n        }\n        break;\n      }\n      case SemIR::InterfaceDecl::Kind: {\n        // TODO: Handle `interface` as well, once we can test it without\n        // triggering\n        // https://github.com/carbon-language/carbon-lang/issues/4071.\n        CARBON_FATAL(\"TODO: Support interfaces in DiagnoseMissingDefinitions\");\n      }\n      default: {\n        CARBON_FATAL(\"Unexpected inst in definitions_required_by_decl: {0}\",\n                     decl_inst);\n      }\n    }\n  }\n\n  for (auto [loc, specific_id] :\n       GrowingRange(context_.definitions_required_by_use())) {\n    // This is using the location for the use. We could track the\n    // list of enclosing locations if this was used from a generic.\n    if (!ResolveSpecificDefinition(context_, loc, specific_id)) {\n      CARBON_DIAGNOSTIC(MissingGenericFunctionDefinition, Error,\n                        \"use of undefined generic function\");\n      CARBON_DIAGNOSTIC(MissingGenericFunctionDefinitionHere, Note,\n                        \"generic function declared here\");\n      auto generic_decl_id =\n          context_.generics()\n              .Get(context_.specifics().Get(specific_id).generic_id)\n              .decl_id;\n      emitter_.Build(loc, MissingGenericFunctionDefinition)\n          .Note(generic_decl_id, MissingGenericFunctionDefinitionHere)\n          .Emit();\n    }\n  }\n}\n\nauto CheckUnit::CheckPoisonedConcreteImplLookupQueries() -> void {\n  // Impl lookup can generate instructions (via deduce) which we don't use, as\n  // we're only generating diagnostics here, so we catch and discard them.\n  context_.inst_block_stack().Push();\n  auto poisoned_queries =\n      std::exchange(context_.poisoned_concrete_impl_lookup_queries(), {});\n  for (const auto& poison : poisoned_queries) {\n    auto witness_result = EvalLookupSingleImplWitness(\n        context_, poison.loc_id, poison.query, poison.query.query_self_inst_id,\n        EvalImplLookupMode::RecheckPoisonedLookup);\n    CARBON_CHECK(witness_result.has_final_value());\n    auto found_witness_id = witness_result.final_witness();\n    if (found_witness_id == SemIR::ErrorInst::InstId) {\n      // Errors may have been diagnosed with the impl used in the poisoned query\n      // in the meantime (such as a missing definition).\n      continue;\n    }\n    if (found_witness_id != poison.impl_witness) {\n      auto witness_to_impl_id = [&](SemIR::InstId witness_id) {\n        auto table_id = context_.insts()\n                            .GetAs<SemIR::ImplWitness>(witness_id)\n                            .witness_table_id;\n        return context_.insts()\n            .GetAs<SemIR::ImplWitnessTable>(table_id)\n            .impl_id;\n      };\n\n      // We can get the `Impl` from the resulting witness here, which is the\n      // `Impl` that conflicts with the previous poison query.\n      auto bad_impl_id = witness_to_impl_id(found_witness_id);\n      const auto& bad_impl = context_.impls().Get(bad_impl_id);\n\n      auto prev_impl_id = witness_to_impl_id(poison.impl_witness);\n      const auto& prev_impl = context_.impls().Get(prev_impl_id);\n\n      CARBON_DIAGNOSTIC(\n          PoisonedImplLookupConcreteResult, Error,\n          \"found `impl` that would change the result of an earlier \"\n          \"use of `{0} as {1}`\",\n          InstIdAsRawType, SpecificInterfaceIdAsRawType);\n      auto builder =\n          emitter_.Build(poison.loc_id, PoisonedImplLookupConcreteResult,\n                         poison.query.query_self_inst_id,\n                         poison.query.query_specific_interface_id);\n      CARBON_DIAGNOSTIC(\n          PoisonedImplLookupConcreteResultNoteBadImpl, Note,\n          \"the use would select the `impl` here but it was not found yet\");\n      builder.Note(bad_impl.first_decl_id(),\n                   PoisonedImplLookupConcreteResultNoteBadImpl);\n      CARBON_DIAGNOSTIC(PoisonedImplLookupConcreteResultNotePreviousImpl, Note,\n                        \"the use had selected the `impl` here\");\n      builder.Note(prev_impl.first_decl_id(),\n                   PoisonedImplLookupConcreteResultNotePreviousImpl);\n      builder.Emit();\n    }\n  }\n  context_.inst_block_stack().PopAndDiscard();\n}\n\nauto CheckUnit::CheckImpls() -> void { ValidateImplsInFile(context_); }\n\nauto CheckUnit::FinishRun() -> void {\n  CheckRequiredDeclarations();\n  CheckRequiredDefinitions();\n  CheckPoisonedConcreteImplLookupQueries();\n  CheckImpls();\n\n  // Finalizes the C++ portion of the compilation.\n  FinishAst(context_);\n\n  // Pop information for the file-level scope.\n  context_.sem_ir().set_top_inst_block_id(context_.inst_block_stack().Pop());\n  context_.scope_stack().Pop(/*check_unused=*/true);\n\n  // Finalizes reserved blocks, using `ReservedIds` to avoid missing values.\n  for (auto reserved_id : SemIR::InstBlockId::ReservedIds) {\n    if (reserved_id == SemIR::InstBlockId::Empty) {\n      continue;\n    }\n    if (reserved_id == SemIR::InstBlockId::GlobalInit) {\n      context_.global_init().Finalize();\n      continue;\n    }\n\n    llvm::ArrayRef<SemIR::InstId> block;\n    if (reserved_id == SemIR::InstBlockId::Exports) {\n      block = context_.exports();\n    } else if (reserved_id == SemIR::InstBlockId::Generated) {\n      block = context_.generated();\n    } else if (reserved_id == SemIR::InstBlockId::Imports) {\n      block = context_.imports();\n    } else {\n      CARBON_FATAL(\"Unexpected reserved InstBlockId: {0}\", reserved_id);\n    }\n    context_.inst_blocks().ReplacePlaceholder(reserved_id, block);\n  }\n\n  emitter_.Flush();\n\n  context_.sem_ir().set_has_errors(unit_and_imports_->err_tracker.seen_error());\n\n  // Verify that Context cleanly finished.\n  context_.VerifyOnFinish();\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/check_unit.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CHECK_UNIT_H_\n#define CARBON_TOOLCHAIN_CHECK_CHECK_UNIT_H_\n\n#include \"clang/Frontend/CompilerInvocation.h\"\n#include \"common/map.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/check/check.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/diagnostic_emitter.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nstruct UnitAndImports;\n\n// A file's imports corresponding to a single package, for\n// `UnitAndImports::package_imports`.\nstruct PackageImports {\n  // A given import within the file, with its destination.\n  struct Import {\n    Parse::Tree::PackagingNames names;\n    UnitAndImports* unit_info;\n  };\n\n  // Use the constructor so that the SmallVector is only constructed\n  // as-needed.\n  explicit PackageImports(PackageNameId package_id,\n                          Parse::AnyPackagingDeclId node_id)\n      : package_id(package_id), node_id(node_id) {}\n\n  // The identifier of the imported package.\n  PackageNameId package_id;\n  // The first `package` or `import` declaration in the file, which declared the\n  // package's identifier (even if the import failed). Used for associating\n  // diagnostics not specific to a single import.\n  Parse::AnyPackagingDeclId node_id;\n  // The associated `import` instruction. Has a value after a file is checked.\n  SemIR::InstId import_decl_id = SemIR::InstId::None;\n  // Whether there's an import that failed to load.\n  bool has_load_error = false;\n  // The list of valid imports.\n  llvm::SmallVector<Import> imports;\n};\n\n// Contains information accumulated while checking a `Unit` (primarily import\n// information), in addition to the `Unit` itself.\nstruct UnitAndImports {\n  // Converts a `NodeId` to a diagnostic location for `UnitAndImports`.\n  class NodeEmitter : public Diagnostics::Emitter<Parse::NodeId> {\n   public:\n    explicit NodeEmitter(Diagnostics::Consumer* consumer,\n                         Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter)\n        : Emitter(consumer),\n          tree_and_subtrees_getter_(tree_and_subtrees_getter) {}\n\n   protected:\n    auto ConvertLoc(Parse::NodeId node_id, ContextFnT /*context_fn*/) const\n        -> Diagnostics::ConvertedLoc override {\n      return tree_and_subtrees_getter_().NodeToDiagnosticLoc(\n          node_id, /*token_only=*/false);\n    }\n\n   private:\n    Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter_;\n  };\n\n  explicit UnitAndImports(Unit* unit,\n                          Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter)\n      : unit(unit),\n        err_tracker(*unit->consumer),\n        emitter(&err_tracker, tree_and_subtrees_getter) {}\n\n  auto parse_tree() -> const Parse::Tree& { return unit->sem_ir->parse_tree(); }\n  auto source() -> const SourceBuffer& {\n    return parse_tree().tokens().source();\n  }\n\n  Unit* unit;\n\n  // Emitter information.\n  Diagnostics::ErrorTrackingConsumer err_tracker;\n  NodeEmitter emitter;\n\n  // List of the outgoing imports. If a package includes unavailable library\n  // imports, it has an entry with has_load_error set. Invalid imports (for\n  // example, `import Main;`) aren't added because they won't add identifiers to\n  // name lookup.\n  llvm::SmallVector<PackageImports> package_imports;\n\n  // A map of the package names to the outgoing imports above.\n  Map<PackageNameId, int32_t> package_imports_map;\n\n  // List of the `import Cpp` imports.\n  llvm::SmallVector<Parse::Tree::PackagingNames> cpp_imports;\n\n  // The remaining number of imports which must be checked before this unit can\n  // be processed.\n  int32_t imports_remaining = 0;\n\n  // A list of incoming imports. This will be empty for `impl` files, because\n  // imports only touch `api` files.\n  llvm::SmallVector<UnitAndImports*> incoming_imports;\n\n  // The corresponding `api` unit if this is an `impl` file. The entry should\n  // also be in the corresponding `PackageImports`.\n  UnitAndImports* api_for_impl = nullptr;\n\n  // Whether the unit has been checked.\n  bool is_checked = false;\n};\n\n// Handles checking of a single unit. Requires that all dependencies have been\n// checked.\n//\n// This mainly splits out the single-unit logic from the higher level cross-unit\n// logic in check.cpp.\nclass CheckUnit {\n public:\n  // `unit_and_imports` and `tree_and_subtrees_getters` must be non-null.\n  // `vlog_stream` is optional.\n  explicit CheckUnit(\n      UnitAndImports* unit_and_imports,\n      const Parse::GetTreeAndSubtreesStore* tree_and_subtrees_getters,\n      llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n      llvm::LLVMContext* llvm_context,\n      std::shared_ptr<clang::CompilerInvocation> clang_invocation,\n      llvm::raw_ostream* vlog_stream);\n\n  // Produces and checks the IR for the provided unit.\n  auto Run() -> void;\n\n private:\n  using CheckIRIdToIntStore = FixedSizeValueStore<SemIR::CheckIRId, int>;\n\n  // Add imports to the root block.\n  auto InitPackageScopeAndImports() -> void;\n\n  // Collects direct imports, for CollectTransitiveImports.\n  auto CollectDirectImports(llvm::SmallVector<SemIR::ImportIR>& results,\n                            CheckIRIdToIntStore& ir_to_result_index,\n                            SemIR::InstId import_decl_id,\n                            const PackageImports& imports, bool is_local)\n      -> void;\n\n  // Collects transitive imports, handling deduplication. These will be unified\n  // between local_imports and api_imports.\n  auto CollectTransitiveImports(SemIR::InstId import_decl_id,\n                                const PackageImports* local_imports,\n                                const PackageImports* api_imports)\n      -> llvm::SmallVector<SemIR::ImportIR>;\n\n  // Imports the current package.\n  auto ImportCurrentPackage(SemIR::InstId package_inst_id,\n                            SemIR::TypeId namespace_type_id) -> void;\n\n  // Imports all other Carbon packages (excluding the current package).\n  auto ImportOtherPackages(SemIR::TypeId namespace_type_id) -> void;\n\n  // Checks that each required declaration is available. This applies for\n  // declarations that should exist in an owning library, for which an extern\n  // declaration exists that assigns ownership to the current API.\n  auto CheckRequiredDeclarations() -> void;\n\n  // Checks that each required definition is available. If the definition can be\n  // generated by resolving a specific, does so, otherwise emits a diagnostic\n  // for each declaration in context.definitions_required_by_decl() and\n  // context.definitions_required_by_use that doesn't have a definition.\n  auto CheckRequiredDefinitions() -> void;\n\n  // Re-run every impl lookup with a concrete result and make sure they find the\n  // same witnesses.\n  auto CheckPoisonedConcreteImplLookupQueries() -> void;\n\n  // Look for `impl` declarations that are invalid.\n  auto CheckImpls() -> void;\n\n  // Does work after processing the parse tree, such as finishing the IR and\n  // checking for missing contents.\n  auto FinishRun() -> void;\n\n  // Loops over all nodes in the tree. On some errors, this may return early,\n  // for example if an unrecoverable state is encountered.\n  auto ProcessNodeIds() -> bool;\n\n  UnitAndImports* unit_and_imports_;\n  Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter_;\n  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs_;\n  llvm::LLVMContext* llvm_context_;\n  std::shared_ptr<clang::CompilerInvocation> clang_invocation_;\n\n  DiagnosticEmitter emitter_;\n  Context context_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CHECK_UNIT_H_\n"
  },
  {
    "path": "toolchain/check/class.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/class.h\"\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/function.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/impl.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/name_ref.h\"\n#include \"toolchain/check/pattern.h\"\n#include \"toolchain/check/pattern_match.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/builtin_function_kind.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto SetClassSelfType(Context& context, SemIR::ClassId class_id) -> void {\n  auto& class_info = context.classes().Get(class_id);\n  auto specific_id = context.generics().GetSelfSpecific(class_info.generic_id);\n  class_info.self_type_id = GetClassType(context, class_id, specific_id);\n}\n\nauto StartClassDefinition(Context& context, SemIR::Class& class_info,\n                          SemIR::InstId definition_id) -> void {\n  // Track that this declaration is the definition.\n  CARBON_CHECK(!class_info.has_definition_started());\n  class_info.definition_id = definition_id;\n  class_info.scope_id = context.name_scopes().Add(\n      definition_id, SemIR::NameId::None, class_info.parent_scope_id);\n\n  // Introduce `Self`.\n  context.name_scopes().AddRequiredName(\n      class_info.scope_id, SemIR::NameId::SelfType,\n      context.types().GetTypeInstId(class_info.self_type_id));\n}\n\n// Checks that the specified finished adapter definition is valid and builds and\n// returns a corresponding complete type witness instruction.\nstatic auto CheckCompleteAdapterClassType(\n    Context& context, Parse::NodeId node_id, SemIR::ClassId class_id,\n    llvm::ArrayRef<SemIR::InstId> field_decls,\n    llvm::ArrayRef<SemIR::InstId> body) -> SemIR::InstId {\n  const auto& class_info = context.classes().Get(class_id);\n  if (class_info.base_id.has_value()) {\n    CARBON_DIAGNOSTIC(AdaptWithBase, Error, \"adapter with base class\");\n    CARBON_DIAGNOSTIC(AdaptWithBaseHere, Note, \"`base` declaration is here\");\n    context.emitter()\n        .Build(class_info.adapt_id, AdaptWithBase)\n        .Note(class_info.base_id, AdaptWithBaseHere)\n        .Emit();\n    return SemIR::ErrorInst::InstId;\n  }\n\n  if (!field_decls.empty()) {\n    CARBON_DIAGNOSTIC(AdaptWithFields, Error, \"adapter with fields\");\n    CARBON_DIAGNOSTIC(AdaptWithFieldHere, Note,\n                      \"first field declaration is here\");\n    context.emitter()\n        .Build(class_info.adapt_id, AdaptWithFields)\n        .Note(field_decls.front(), AdaptWithFieldHere)\n        .Emit();\n    return SemIR::ErrorInst::InstId;\n  }\n\n  for (auto inst_id : body) {\n    if (auto function_decl =\n            context.insts().TryGetAs<SemIR::FunctionDecl>(inst_id)) {\n      auto& function = context.functions().Get(function_decl->function_id);\n      if (function.virtual_modifier ==\n          SemIR::Function::VirtualModifier::Virtual) {\n        CARBON_DIAGNOSTIC(AdaptWithVirtual, Error,\n                          \"adapter with virtual function\");\n        CARBON_DIAGNOSTIC(AdaptWithVirtualHere, Note,\n                          \"first virtual function declaration is here\");\n        context.emitter()\n            .Build(class_info.adapt_id, AdaptWithVirtual)\n            .Note(inst_id, AdaptWithVirtualHere)\n            .Emit();\n        return SemIR::ErrorInst::InstId;\n      }\n    }\n  }\n\n  // The object representation of the adapter is the object representation\n  // of the adapted type.\n  auto adapted_type_id =\n      class_info.GetAdaptedType(context.sem_ir(), SemIR::SpecificId::None);\n  auto object_repr_id = context.types().GetObjectRepr(adapted_type_id);\n\n  return AddInst<SemIR::CompleteTypeWitness>(\n      context, node_id,\n      {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),\n       // TODO: Use InstId from the adapt declaration.\n       .object_repr_type_inst_id =\n           context.types().GetTypeInstId(object_repr_id)});\n}\n\nstatic auto AddStructTypeFields(\n    Context& context,\n    llvm::SmallVector<SemIR::StructTypeField>& struct_type_fields,\n    llvm::ArrayRef<SemIR::InstId> field_decls) -> SemIR::StructTypeFieldsId {\n  for (auto field_decl_id : field_decls) {\n    auto field_decl = context.insts().GetAs<SemIR::FieldDecl>(field_decl_id);\n    field_decl.index =\n        SemIR::ElementIndex{static_cast<int>(struct_type_fields.size())};\n    ReplaceInstPreservingConstantValue(context, field_decl_id, field_decl);\n    if (field_decl.type_id == SemIR::ErrorInst::TypeId) {\n      struct_type_fields.push_back(\n          {.name_id = field_decl.name_id,\n           .type_inst_id = SemIR::ErrorInst::TypeInstId});\n      continue;\n    }\n    auto unbound_element_type =\n        context.sem_ir().types().GetAs<SemIR::UnboundElementType>(\n            field_decl.type_id);\n    struct_type_fields.push_back(\n        {.name_id = field_decl.name_id,\n         .type_inst_id = unbound_element_type.element_type_inst_id});\n  }\n  auto fields_id =\n      context.struct_type_fields().AddCanonical(struct_type_fields);\n  return fields_id;\n}\n\n// Builds and returns a vtable for the current class. Assumes that the virtual\n// functions for the class are listed as the top element of the `vtable_stack`.\nstatic auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id,\n                        SemIR::ClassId class_id,\n                        std::optional<SemIR::ClassType> base_class_type,\n                        llvm::ArrayRef<SemIR::InstId> vtable_contents)\n    -> SemIR::VtableId {\n  auto base_vtable_id = SemIR::VtableId::None;\n  auto base_class_specific_id = SemIR::SpecificId::None;\n\n  // Get some base class/type/specific info.\n  if (base_class_type) {\n    auto& base_class_info = context.classes().Get(base_class_type->class_id);\n    auto base_vtable_decl_inst_id = base_class_info.vtable_decl_id;\n    if (base_vtable_decl_inst_id.has_value()) {\n      LoadImportRef(context, base_vtable_decl_inst_id);\n      auto canonical_base_vtable_inst_id =\n          context.constant_values().GetConstantInstId(base_vtable_decl_inst_id);\n      const auto& base_vtable_decl_inst =\n          context.insts().GetAs<SemIR::VtableDecl>(\n              canonical_base_vtable_inst_id);\n      base_vtable_id = base_vtable_decl_inst.vtable_id;\n      base_class_specific_id = base_class_type->specific_id;\n    }\n  }\n\n  const auto& class_info = context.classes().Get(class_id);\n  auto class_generic_id = class_info.generic_id;\n\n  // Wrap vtable entries in SpecificFunctions as needed/in generic classes.\n  auto build_specific_function =\n      [&](SemIR::InstId fn_decl_id) -> SemIR::InstId {\n    if (!class_generic_id.has_value()) {\n      return fn_decl_id;\n    }\n    const auto& fn_decl =\n        context.insts().GetAs<SemIR::FunctionDecl>(fn_decl_id);\n    const auto& function = context.functions().Get(fn_decl.function_id);\n    return GetOrAddInst<SemIR::SpecificFunction>(\n        context, node_id,\n        {.type_id =\n             GetSingletonType(context, SemIR::SpecificFunctionType::TypeInstId),\n         .callee_id = fn_decl_id,\n         .specific_id =\n             context.generics().GetSelfSpecific(function.generic_id)});\n  };\n\n  llvm::SmallVector<SemIR::InstId> vtable;\n  Set<SemIR::FunctionId> implemented_impls;\n  if (base_vtable_id.has_value()) {\n    auto base_vtable_inst_block = context.inst_blocks().Get(\n        context.vtables().Get(base_vtable_id).virtual_functions_id);\n    // TODO: Avoid quadratic search. Perhaps build a map from `NameId` to the\n    // elements of the top of `vtable_stack`.\n    for (auto base_vtable_entry_id : base_vtable_inst_block) {\n      auto [derived_vtable_entry_id, derived_vtable_entry_const_id, fn_id,\n            specific_id] =\n          DecomposeVirtualFunction(context.sem_ir(), base_vtable_entry_id,\n                                   base_class_specific_id);\n      const auto& fn = context.sem_ir().functions().Get(fn_id);\n      const auto* i = llvm::find_if(\n          vtable_contents, [&](SemIR::InstId override_fn_decl_id) -> bool {\n            const auto& override_fn = context.functions().Get(\n                context.insts()\n                    .GetAs<SemIR::FunctionDecl>(override_fn_decl_id)\n                    .function_id);\n            return override_fn.virtual_modifier ==\n                       SemIR::FunctionFields::VirtualModifier::Override &&\n                   override_fn.name_id == fn.name_id;\n          });\n      if (i != vtable_contents.end()) {\n        auto override_fn_id =\n            context.insts().GetAs<SemIR::FunctionDecl>(*i).function_id;\n        implemented_impls.Insert(override_fn_id);\n        auto& override_fn = context.functions().Get(override_fn_id);\n        CheckFunctionTypeMatches(context, override_fn, fn, specific_id,\n                                 /*check_syntax=*/false,\n                                 /*check_self=*/false);\n        derived_vtable_entry_id = build_specific_function(*i);\n        override_fn.virtual_index = vtable.size();\n        CARBON_CHECK(override_fn.virtual_index == fn.virtual_index);\n      } else if (auto base_vtable_specific_function =\n                     context.insts().TryGetAs<SemIR::SpecificFunction>(\n                         derived_vtable_entry_id)) {\n        if (derived_vtable_entry_const_id.is_symbolic()) {\n          // Create a new instruction here that is otherwise identical to\n          // `derived_vtable_entry_id` but is dependent within the derived\n          // class. This ensures we can `GetConstantValueInSpecific` for it\n          // with the derived class's specific (when forming further derived\n          // classes, lowering the vtable, etc).\n          derived_vtable_entry_id = GetOrAddInst<SemIR::SpecificFunction>(\n              context, node_id,\n              {.type_id = GetSingletonType(\n                   context, SemIR::SpecificFunctionType::TypeInstId),\n               .callee_id = base_vtable_specific_function->callee_id,\n               .specific_id = base_vtable_specific_function->specific_id});\n        }\n      }\n      vtable.push_back(derived_vtable_entry_id);\n    }\n  }\n\n  for (auto inst_id : vtable_contents) {\n    auto fn_decl = context.insts().GetAs<SemIR::FunctionDecl>(inst_id);\n    auto& fn = context.functions().Get(fn_decl.function_id);\n    if (fn.virtual_modifier !=\n        SemIR::FunctionFields::VirtualModifier::Override) {\n      fn.virtual_index = vtable.size();\n      vtable.push_back(build_specific_function(inst_id));\n    } else if (!implemented_impls.Lookup(fn_decl.function_id)) {\n      CARBON_DIAGNOSTIC(OverrideWithoutVirtualInBase, Error,\n                        \"override without compatible virtual in base class\");\n      context.emitter().Emit(SemIR::LocId(inst_id),\n                             OverrideWithoutVirtualInBase);\n    }\n  }\n\n  return context.vtables().Add(\n      {{.class_id = class_id,\n        .virtual_functions_id = context.inst_blocks().Add(vtable)}});\n}\n\n// Checks that the specified finished class definition is valid and builds and\n// returns a corresponding complete type witness instruction.\nstatic auto CheckCompleteClassType(\n    Context& context, Parse::ClassDefinitionId node_id, SemIR::ClassId class_id,\n    llvm::ArrayRef<SemIR::InstId> field_decls,\n    llvm::ArrayRef<SemIR::InstId> vtable_contents,\n    llvm::ArrayRef<SemIR::InstId> body) -> SemIR::InstId {\n  auto& class_info = context.classes().Get(class_id);\n  if (class_info.adapt_id.has_value()) {\n    return CheckCompleteAdapterClassType(context, node_id, class_id,\n                                         field_decls, body);\n  }\n\n  bool defining_vptr = class_info.is_dynamic;\n  auto base_type_id =\n      class_info.GetBaseType(context.sem_ir(), SemIR::SpecificId::None);\n  // TODO: Use InstId from base declaration.\n  auto base_type_inst_id = context.types().GetTypeInstId(base_type_id);\n  std::optional<SemIR::ClassType> base_class_type;\n  if (base_type_id.has_value()) {\n    // TODO: If the base class is template dependent, we will need to decide\n    // whether to add a vptr as part of instantiation.\n    base_class_type = context.types().TryGetAs<SemIR::ClassType>(base_type_id);\n    if (base_class_type &&\n        context.classes().Get(base_class_type->class_id).is_dynamic) {\n      defining_vptr = false;\n    }\n  }\n\n  llvm::SmallVector<SemIR::StructTypeField> struct_type_fields;\n  struct_type_fields.reserve(defining_vptr + class_info.base_id.has_value() +\n                             field_decls.size());\n  if (defining_vptr) {\n    struct_type_fields.push_back(\n        {.name_id = SemIR::NameId::Vptr,\n         .type_inst_id = context.types().GetTypeInstId(\n             GetPointerType(context, SemIR::VtableType::TypeInstId))});\n  }\n  if (base_type_id.has_value()) {\n    auto base_decl = context.insts().GetAs<SemIR::BaseDecl>(class_info.base_id);\n    base_decl.index =\n        SemIR::ElementIndex{static_cast<int>(struct_type_fields.size())};\n    ReplaceInstPreservingConstantValue(context, class_info.base_id, base_decl);\n    struct_type_fields.push_back(\n        {.name_id = SemIR::NameId::Base, .type_inst_id = base_type_inst_id});\n  }\n\n  if (class_info.is_dynamic) {\n    auto vtable_id = BuildVtable(context, node_id, class_id, base_class_type,\n                                 vtable_contents);\n    auto vptr_type_id = GetPointerType(context, SemIR::VtableType::TypeInstId);\n    class_info.vtable_decl_id = AddInst<SemIR::VtableDecl>(\n        context, node_id, {.type_id = vptr_type_id, .vtable_id = vtable_id});\n  }\n\n  auto struct_type_id = GetStructType(\n      context, AddStructTypeFields(context, struct_type_fields, field_decls));\n\n  return AddInst<SemIR::CompleteTypeWitness>(\n      context, node_id,\n      {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),\n       .object_repr_type_inst_id =\n           context.types().GetTypeInstId(struct_type_id)});\n}\n\nauto ComputeClassObjectRepr(Context& context, Parse::ClassDefinitionId node_id,\n                            SemIR::ClassId class_id,\n                            llvm::ArrayRef<SemIR::InstId> field_decls,\n                            llvm::ArrayRef<SemIR::InstId> vtable_contents,\n                            llvm::ArrayRef<SemIR::InstId> body) -> void {\n  auto complete_type_witness_id = CheckCompleteClassType(\n      context, node_id, class_id, field_decls, vtable_contents, body);\n  auto& class_info = context.classes().Get(class_id);\n  class_info.complete_type_witness_id = complete_type_witness_id;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/class.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CLASS_H_\n#define CARBON_TOOLCHAIN_CHECK_CLASS_H_\n\n#include \"toolchain/check/context.h\"\n\nnamespace Carbon::Check {\n\n// Sets the `Self` type for the class.\nauto SetClassSelfType(Context& context, SemIR::ClassId class_id) -> void;\n\n// Starts the class definition, adding `Self` to name lookup.\nauto StartClassDefinition(Context& context, SemIR::Class& class_info,\n                          SemIR::InstId definition_id) -> void;\n\n// Computes the object representation for a fully defined class.\nauto ComputeClassObjectRepr(Context& context, Parse::ClassDefinitionId node_id,\n                            SemIR::ClassId class_id,\n                            llvm::ArrayRef<SemIR::InstId> field_decls,\n                            llvm::ArrayRef<SemIR::InstId> vtable_contents,\n                            llvm::ArrayRef<SemIR::InstId> body) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CLASS_H_\n"
  },
  {
    "path": "toolchain/check/context.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n\n#include <string>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/deferred_definition_worklist.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nContext::Context(DiagnosticEmitterBase* emitter,\n                 Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter,\n                 SemIR::File* sem_ir, int imported_ir_count, int total_ir_count,\n                 llvm::raw_ostream* vlog_stream)\n    : emitter_(emitter),\n      tree_and_subtrees_getter_(tree_and_subtrees_getter),\n      sem_ir_(sem_ir),\n      total_ir_count_(total_ir_count),\n      vlog_stream_(vlog_stream),\n      node_stack_(sem_ir->parse_tree(), vlog_stream),\n      inst_block_stack_(\"inst_block_stack_\", *sem_ir, vlog_stream),\n      pattern_block_stack_(\"pattern_block_stack_\", *sem_ir, vlog_stream),\n      param_and_arg_refs_stack_(*sem_ir, vlog_stream, node_stack_),\n      args_type_info_stack_(\"args_type_info_stack_\", *sem_ir, vlog_stream),\n      decl_name_stack_(this),\n      scope_stack_(*this),\n      deferred_definition_worklist_(vlog_stream),\n      generic_region_stack_(vlog_stream),\n      vtable_stack_(\"vtable_stack_\", *sem_ir, vlog_stream),\n      check_ir_map_(CheckIRToImpportIRStore::MakeWithExplicitSize(\n          total_ir_count_, SemIR::ImportIRId::None)),\n      global_init_(this),\n      region_stack_([this](SemIR::LocId loc_id, std::string label) {\n        TODO(loc_id, label);\n      }),\n      core_identifiers_(&identifiers()) {\n  // Prepare fields which relate to the number of IRs available for import.\n  import_irs().Reserve(imported_ir_count);\n  import_ir_constant_values_.reserve(imported_ir_count);\n}\n\nauto Context::TODO(SemIR::LocId loc_id, std::string label) -> bool {\n  CARBON_DIAGNOSTIC(SemanticsTodo, Error, \"semantics TODO: `{0}`\", std::string);\n  emitter_->Emit(loc_id, SemanticsTodo, std::move(label));\n  return false;\n}\n\nauto Context::TODO(SemIR::InstId loc_inst_id, std::string label) -> bool {\n  return TODO(SemIR::LocId(loc_inst_id), label);\n}\n\nauto Context::VerifyOnFinish() const -> void {\n  // Information in all the various context objects should be cleaned up as\n  // various pieces of context go out of scope. At this point, nothing should\n  // remain, so we verify stacks are empty. `node_stack_` is an exception\n  // because it ends containing all top-level entities.\n  inst_block_stack_.VerifyOnFinish();\n  pattern_block_stack_.VerifyOnFinish();\n  param_and_arg_refs_stack_.VerifyOnFinish();\n  args_type_info_stack_.VerifyOnFinish();\n  CARBON_CHECK(struct_type_fields_stack_.empty());\n  CARBON_CHECK(field_decls_stack_.empty());\n  decl_name_stack_.VerifyOnFinish();\n  decl_introducer_state_stack_.VerifyOnFinish();\n  scope_stack_.VerifyOnFinish();\n  generic_region_stack_.VerifyOnFinish();\n  vtable_stack_.VerifyOnFinish();\n  region_stack_.VerifyOnFinish();\n  CARBON_CHECK(impl_lookup_stack_.empty());\n  CARBON_CHECK(return_form_expr_ == std::nullopt);\n\n#ifndef NDEBUG\n  if (auto verify = sem_ir_->Verify(); !verify.ok()) {\n    CARBON_FATAL(\"{0}Built invalid semantics IR: {1}\\n\", sem_ir_,\n                 verify.error());\n  }\n#endif\n}\n\nauto Context::PrintForStackDump(llvm::raw_ostream& output) const -> void {\n  output << \"Check::Context\\n\";\n\n  // In a stack dump, this is probably indented by a tab. We treat that as 8\n  // spaces then add a couple to indent past the Context label.\n  constexpr int Indent = 10;\n\n  output.indent(Indent);\n  output << \"filename: \" << tokens().source().filename() << \"\\n\";\n\n  node_stack_.PrintForStackDump(Indent, output);\n  inst_block_stack_.PrintForStackDump(Indent, output);\n  pattern_block_stack_.PrintForStackDump(Indent, output);\n  param_and_arg_refs_stack_.PrintForStackDump(Indent, output);\n  args_type_info_stack_.PrintForStackDump(Indent, output);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/context.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CONTEXT_H_\n#define CARBON_TOOLCHAIN_CHECK_CONTEXT_H_\n\n#include <string>\n\n#include \"common/map.h\"\n#include \"common/ostream.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/base/canonical_value_store.h\"\n#include \"toolchain/base/value_store.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/check/cpp/context.h\"\n#include \"toolchain/check/decl_introducer_state.h\"\n#include \"toolchain/check/decl_name_stack.h\"\n#include \"toolchain/check/deferred_definition_worklist.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/full_pattern_stack.h\"\n#include \"toolchain/check/generic_region_stack.h\"\n#include \"toolchain/check/global_init.h\"\n#include \"toolchain/check/inst_block_stack.h\"\n#include \"toolchain/check/node_stack.h\"\n#include \"toolchain/check/param_and_arg_refs_stack.h\"\n#include \"toolchain/check/region_stack.h\"\n#include \"toolchain/check/scope_stack.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/parse/tree.h\"\n#include \"toolchain/parse/tree_and_subtrees.h\"\n#include \"toolchain/sem_ir/facet_type_info.h\"\n#include \"toolchain/sem_ir/file.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/import_ir.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/specific_interface.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Context stored during check.\n//\n// This file stores state, and members objects may provide an API. Other files\n// may also have helpers that operate on Context. To keep this file manageable,\n// please put logic into other files.\n//\n// For example, consider the API for functions:\n// - `context.functions()`: Exposes storage of `SemIR::Function` objects.\n// - `toolchain/check/function.h`: Contains helper functions which use\n//   `Check::Context`.\n// - `toolchain/sem_ir/function.h`: Contains helper functions which only need\n//   `SemIR` objects, for which it's helpful not to depend on `Check::Context`\n//   (for example, shared with lowering).\nclass Context {\n public:\n  // Stores references for work.\n  explicit Context(DiagnosticEmitterBase* emitter,\n                   Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter,\n                   SemIR::File* sem_ir, int imported_ir_count,\n                   int total_ir_count, llvm::raw_ostream* vlog_stream);\n\n  // Marks an implementation TODO. Always returns false.\n  auto TODO(SemIR::LocId loc_id, std::string label) -> bool;\n  auto TODO(SemIR::InstId loc_inst_id, std::string label) -> bool;\n\n  // Runs verification that the processing cleanly finished.\n  auto VerifyOnFinish() const -> void;\n\n  // Prints information for a stack dump.\n  auto PrintForStackDump(llvm::raw_ostream& output) const -> void;\n\n  // Get the Lex::TokenKind of a node for diagnostics.\n  auto token_kind(Parse::NodeId node_id) -> Lex::TokenKind {\n    return tokens().GetKind(parse_tree().node_token(node_id));\n  }\n\n  auto emitter() -> DiagnosticEmitterBase& { return *emitter_; }\n\n  auto parse_tree_and_subtrees() -> const Parse::TreeAndSubtrees& {\n    return tree_and_subtrees_getter_();\n  }\n\n  auto sem_ir() -> SemIR::File& { return *sem_ir_; }\n  auto sem_ir() const -> const SemIR::File& { return *sem_ir_; }\n\n  auto cpp_context() -> CppContext* { return cpp_context_.get(); }\n\n  // TODO: Remove this and pass the C++ context to the constructor.\n  auto set_cpp_context(std::unique_ptr<CppContext> cpp_context) {\n    CARBON_CHECK(!cpp_context_ || !cpp_context, \"Already have a C++ context\");\n    cpp_context_ = std::move(cpp_context);\n  }\n\n  // Convenience functions for major phase data.\n  auto parse_tree() const -> const Parse::Tree& {\n    return sem_ir_->parse_tree();\n  }\n  auto tokens() const -> const Lex::TokenizedBuffer& {\n    return parse_tree().tokens();\n  }\n\n  auto vlog_stream() -> llvm::raw_ostream* { return vlog_stream_; }\n\n  auto node_stack() -> NodeStack& { return node_stack_; }\n\n  auto inst_block_stack() -> InstBlockStack& { return inst_block_stack_; }\n  auto pattern_block_stack() -> InstBlockStack& { return pattern_block_stack_; }\n\n  auto param_and_arg_refs_stack() -> ParamAndArgRefsStack& {\n    return param_and_arg_refs_stack_;\n  }\n\n  auto args_type_info_stack() -> InstBlockStack& {\n    return args_type_info_stack_;\n  }\n\n  auto struct_type_fields_stack() -> ArrayStack<SemIR::StructTypeField>& {\n    return struct_type_fields_stack_;\n  }\n\n  auto field_decls_stack() -> ArrayStack<SemIR::InstId>& {\n    return field_decls_stack_;\n  }\n\n  auto require_impls_stack() -> ArrayStack<SemIR::RequireImplsId>& {\n    return require_impls_stack_;\n  }\n\n  auto decl_name_stack() -> DeclNameStack& { return decl_name_stack_; }\n\n  auto decl_introducer_state_stack() -> DeclIntroducerStateStack& {\n    return decl_introducer_state_stack_;\n  }\n\n  auto scope_stack() -> ScopeStack& { return scope_stack_; }\n\n  // Convenience functions for frequently-used `scope_stack` members.\n  auto break_continue_stack()\n      -> llvm::SmallVector<ScopeStack::BreakContinueScope>& {\n    return scope_stack().break_continue_stack();\n  }\n  auto full_pattern_stack() -> FullPatternStack& {\n    return scope_stack_.full_pattern_stack();\n  }\n\n  auto deferred_definition_worklist() -> DeferredDefinitionWorklist& {\n    return deferred_definition_worklist_;\n  }\n\n  auto generic_region_stack() -> GenericRegionStack& {\n    return generic_region_stack_;\n  }\n\n  auto vtable_stack() -> InstBlockStack& { return vtable_stack_; }\n\n  auto exports() -> llvm::SmallVector<SemIR::InstId>& { return exports_; }\n\n  using CheckIRToImpportIRStore =\n      FixedSizeValueStore<SemIR::CheckIRId, SemIR::ImportIRId>;\n  auto check_ir_map() -> CheckIRToImpportIRStore& { return check_ir_map_; }\n\n  auto import_ir_constant_values()\n      -> llvm::SmallVector<SemIR::ConstantValueStore, 0>& {\n    return import_ir_constant_values_;\n  }\n\n  auto definitions_required_by_decl() -> llvm::SmallVector<SemIR::InstId>& {\n    return definitions_required_by_decl_;\n  }\n\n  auto definitions_required_by_use()\n      -> llvm::SmallVector<std::pair<SemIR::LocId, SemIR::SpecificId>>& {\n    return definitions_required_by_use_;\n  }\n\n  auto global_init() -> GlobalInit& { return global_init_; }\n\n  auto imports() -> llvm::SmallVector<SemIR::InstId>& { return imports_; }\n\n  auto generated() -> llvm::SmallVector<SemIR::InstId>& { return generated_; }\n\n  // Pre-computed parts of a binding pattern.\n  // TODO: Consider putting this behind a narrower API to guard against emitting\n  // multiple times.\n  struct BindingPatternInfo {\n    // The corresponding AnyBinding inst.\n    SemIR::InstId bind_name_id;\n    // The region of insts that computes the type of the binding.\n    SemIR::ExprRegionId type_expr_region_id;\n  };\n  auto bind_name_map() -> Map<SemIR::InstId, BindingPatternInfo>& {\n    return bind_name_map_;\n  }\n\n  auto var_storage_map() -> Map<SemIR::InstId, SemIR::InstId>& {\n    return var_storage_map_;\n  }\n\n  // During Choice typechecking, each alternative turns into a name binding on\n  // the Choice type, but this can't be done until the full Choice type is\n  // known. This represents each binding to be done at the end of checking the\n  // Choice type.\n  struct ChoiceDeferredBinding {\n    Parse::NodeIdOneOf<Parse::ChoiceAlternativeListCommaId,\n                       Parse::ChoiceDefinitionId>\n        node_id;\n    NameComponent name_component;\n  };\n  auto choice_deferred_bindings() -> llvm::SmallVector<ChoiceDeferredBinding>& {\n    return choice_deferred_bindings_;\n  }\n\n  auto region_stack() -> RegionStack& { return region_stack_; }\n\n  // An ongoing impl lookup, used to ensure termination.\n  struct ImplLookupStackEntry {\n    SemIR::ConstantId query_self_const_id;\n    SemIR::ConstantId query_facet_type_const_id;\n    // The location of the impl being looked at for the stack entry.\n    SemIR::InstId impl_loc = SemIR::InstId::None;\n  };\n  auto impl_lookup_stack() -> llvm::SmallVector<ImplLookupStackEntry>& {\n    return impl_lookup_stack_;\n  }\n\n  // A map from a (self, interface) pair to a final witness.\n  using ImplLookupCacheKey =\n      std::pair<SemIR::ConstantId, SemIR::SpecificInterfaceId>;\n  using ImplLookupCacheMap = Map<ImplLookupCacheKey, SemIR::InstId>;\n  auto impl_lookup_cache() -> ImplLookupCacheMap& { return impl_lookup_cache_; }\n\n  // An impl lookup query that resulted in a concrete witness from finding an\n  // `impl` declaration (not though a facet value), and its result. Used to look\n  // for conflicting `impl` declarations.\n  struct PoisonedConcreteImplLookupQuery {\n    // The location the LookupImplWitness originated from.\n    SemIR::LocId loc_id;\n    // The query for a witness of an impl for an interface.\n    SemIR::LookupImplWitness query;\n    // The resulting ImplWitness.\n    SemIR::InstId impl_witness;\n  };\n  auto poisoned_concrete_impl_lookup_queries()\n      -> llvm::SmallVector<PoisonedConcreteImplLookupQuery>& {\n    return poisoned_concrete_impl_lookup_queries_;\n  }\n\n  // A stack that tracks the rewrite constraints from a `where` expression being\n  // checked. The back of the stack is the currently checked `where` expression.\n  auto rewrites_stack()\n      -> llvm::SmallVector<Map<SemIR::ConstantId, SemIR::InstId>>& {\n    return rewrites_stack_;\n  }\n\n  // Data about a form expression.\n  //\n  // TODO: consider moving this out of Context.\n  struct FormExpr {\n    static const FormExpr Error;\n\n    // The inst ID of the form expression itself. This is always a form inst,\n    // such as InitForm or RefForm.\n    // TODO: Consider creating an AnyForm inst category to refer to those insts.\n    SemIR::InstId form_inst_id;\n    // The inst ID of the form expression's type component.\n    SemIR::TypeInstId type_component_inst_id;\n    // The type ID corresponding to type_component_id.\n    SemIR::TypeId type_component_id;\n  };\n\n  // Pushes form_expr onto the stack of return form declarations for in-progress\n  // function declarations.\n  //\n  // Note: the \"stack\" currently can only have one element, but that restriction\n  // can be relaxed if it becomes possible to have multiple pending return type\n  // declarations.\n  auto PushReturnForm(FormExpr form_expr) -> void {\n    CARBON_CHECK(return_form_expr_ == std::nullopt,\n                 \"TODO: make form_expr_ a stack if necessary\");\n    return_form_expr_ = form_expr;\n  }\n\n  // Pops a FormExpr off the stack of return form declarations for in-progress\n  // function declarations.\n  auto PopReturnForm() -> FormExpr {\n    CARBON_CHECK(return_form_expr_ != std::nullopt);\n    return *std::exchange(return_form_expr_, std::nullopt);\n  }\n\n  auto core_identifiers() -> CoreIdentifierCache& { return core_identifiers_; }\n\n  // --------------------------------------------------------------------------\n  // Directly expose SemIR::File data accessors for brevity in calls.\n  // --------------------------------------------------------------------------\n\n  auto identifiers() -> SharedValueStores::IdentifierStore& {\n    return sem_ir().identifiers();\n  }\n  auto ints() -> SharedValueStores::IntStore& { return sem_ir().ints(); }\n  auto reals() -> SharedValueStores::RealStore& { return sem_ir().reals(); }\n  auto floats() -> SharedValueStores::FloatStore& { return sem_ir().floats(); }\n  auto string_literal_values() -> SharedValueStores::StringLiteralStore& {\n    return sem_ir().string_literal_values();\n  }\n  auto entity_names() -> SemIR::EntityNameStore& {\n    return sem_ir().entity_names();\n  }\n  auto cpp_global_names() -> SemIR::CppGlobalVarStore& {\n    return sem_ir().cpp_global_vars();\n  }\n  auto cpp_overload_sets() -> SemIR::CppOverloadSetStore& {\n    return sem_ir().cpp_overload_sets();\n  }\n  auto functions() -> SemIR::FunctionStore& { return sem_ir().functions(); }\n  auto classes() -> SemIR::ClassStore& { return sem_ir().classes(); }\n  auto vtables() -> SemIR::VtableStore& { return sem_ir().vtables(); }\n  auto interfaces() -> SemIR::InterfaceStore& { return sem_ir().interfaces(); }\n  auto named_constraints() -> SemIR::NamedConstraintStore& {\n    return sem_ir().named_constraints();\n  }\n  auto require_impls() -> SemIR::RequireImplsStore& {\n    return sem_ir().require_impls();\n  }\n  auto require_impls_blocks() -> SemIR::RequireImplsBlockStore& {\n    return sem_ir().require_impls_blocks();\n  }\n  auto associated_constants() -> SemIR::AssociatedConstantStore& {\n    return sem_ir().associated_constants();\n  }\n  auto facet_types() -> SemIR::FacetTypeInfoStore& {\n    return sem_ir().facet_types();\n  }\n  auto identified_facet_types() -> SemIR::IdentifiedFacetTypeStore& {\n    return sem_ir().identified_facet_types();\n  }\n  auto impls() -> SemIR::ImplStore& { return sem_ir().impls(); }\n  auto specific_interfaces() -> SemIR::SpecificInterfaceStore& {\n    return sem_ir().specific_interfaces();\n  }\n  auto generics() -> SemIR::GenericStore& { return sem_ir().generics(); }\n  auto specifics() -> SemIR::SpecificStore& { return sem_ir().specifics(); }\n  auto import_irs() -> SemIR::ImportIRStore& { return sem_ir().import_irs(); }\n  auto import_ir_insts() -> SemIR::ImportIRInstStore& {\n    return sem_ir().import_ir_insts();\n  }\n  auto ast_context() -> clang::ASTContext& {\n    return cpp_context()->ast_context();\n  }\n  auto clang_sema() -> clang::Sema& { return cpp_context()->sema(); }\n  auto clang_decls() -> SemIR::ClangDeclStore& {\n    return sem_ir().clang_decls();\n  }\n  auto names() -> SemIR::NameStoreWrapper { return sem_ir().names(); }\n  auto name_scopes() -> SemIR::NameScopeStore& {\n    return sem_ir().name_scopes();\n  }\n  auto struct_type_fields() -> SemIR::StructTypeFieldsStore& {\n    return sem_ir().struct_type_fields();\n  }\n  auto custom_layouts() -> SemIR::CustomLayoutStore& {\n    return sem_ir().custom_layouts();\n  }\n  auto types() -> SemIR::TypeStore& { return sem_ir().types(); }\n  // Instructions should be added with `AddInst` or `AddInstInNoBlock` from\n  // `inst.h`. This is `const` to prevent accidental misuse.\n  auto insts() const -> const SemIR::InstStore& { return sem_ir().insts(); }\n  auto constant_values() -> SemIR::ConstantValueStore& {\n    return sem_ir().constant_values();\n  }\n  auto inst_blocks() -> SemIR::InstBlockStore& {\n    return sem_ir().inst_blocks();\n  }\n  auto constants() -> SemIR::ConstantStore& { return sem_ir().constants(); }\n\n  // --------------------------------------------------------------------------\n  // End of SemIR::File members.\n  // --------------------------------------------------------------------------\n\n private:\n  // Handles diagnostics.\n  DiagnosticEmitterBase* emitter_;\n\n  // Returns a lazily constructed TreeAndSubtrees.\n  Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter_;\n\n  // The SemIR::File being added to.\n  SemIR::File* sem_ir_;\n  // The total number of files.\n  int total_ir_count_;\n\n  // The C++ checking context.\n  std::unique_ptr<CppContext> cpp_context_;\n\n  // Whether to print verbose output.\n  llvm::raw_ostream* vlog_stream_;\n\n  // The stack during Build. Will contain file-level parse nodes on return.\n  NodeStack node_stack_;\n\n  // The stack of instruction blocks being used for general IR generation.\n  InstBlockStack inst_block_stack_;\n\n  // The stack of instruction blocks that contain pattern instructions.\n  InstBlockStack pattern_block_stack_;\n\n  // The stack of instruction blocks being used for param and arg ref blocks.\n  ParamAndArgRefsStack param_and_arg_refs_stack_;\n\n  // The stack of instruction blocks being used for type information while\n  // processing arguments. This is used in parallel with\n  // param_and_arg_refs_stack_. It's used for:\n  // - Struct literals, where we need to track names for a type separate from\n  //   the literal arguments.\n  // - The associated entries witness table, while parsing an interface.\n  InstBlockStack args_type_info_stack_;\n\n  // The stack of StructTypeFields for in-progress StructTypeLiterals.\n  ArrayStack<SemIR::StructTypeField> struct_type_fields_stack_;\n\n  // The stack of FieldDecls for in-progress Class definitions.\n  ArrayStack<SemIR::InstId> field_decls_stack_;\n\n  // The stack of RequireImpls for in-progress Interface and Constraint\n  // definitions.\n  ArrayStack<SemIR::RequireImplsId> require_impls_stack_;\n\n  // The stack used for qualified declaration name construction.\n  DeclNameStack decl_name_stack_;\n\n  // The stack of declarations that could have modifiers.\n  DeclIntroducerStateStack decl_introducer_state_stack_;\n\n  // The stack of scopes we are currently within.\n  ScopeStack scope_stack_;\n\n  // The worklist of deferred definition tasks to perform at the end of the\n  // enclosing deferred definition scope.\n  DeferredDefinitionWorklist deferred_definition_worklist_;\n\n  // The stack of generic regions we are currently within.\n  GenericRegionStack generic_region_stack_;\n\n  // Contains a vtable block for each `class` scope which is currently being\n  // defined, regardless of whether the class can have virtual functions.\n  InstBlockStack vtable_stack_;\n\n  // Instructions which are operands to an `export` directive. This becomes\n  // `InstBlockId::Exports`.\n  llvm::SmallVector<SemIR::InstId> exports_;\n\n  // Maps CheckIRId to ImportIRId.\n  CheckIRToImpportIRStore check_ir_map_;\n\n  // Per-import constant values. These refer to the main IR and mainly serve as\n  // a lookup table for quick access.\n  //\n  // Inline 0 elements because it's expected to require heap allocation.\n  llvm::SmallVector<SemIR::ConstantValueStore, 0> import_ir_constant_values_;\n\n  // Declaration instructions of entities that should have definitions by the\n  // end of the current source file.\n  llvm::SmallVector<SemIR::InstId> definitions_required_by_decl_;\n\n  // Entities that should have definitions by the end of the current source\n  // file, because of a generic was used a concrete specific. This is currently\n  // only tracking specific functions that should have a definition emitted.\n  llvm::SmallVector<std::pair<SemIR::LocId, SemIR::SpecificId>>\n      definitions_required_by_use_;\n\n  // State for global initialization.\n  GlobalInit global_init_;\n\n  // Instructions which are generated as a result of imports; both `ImportRef`s\n  // and instructions they generate. For example, when a name reference resolves\n  // an imported function, the `ImportRefLoaded` results in a `FunctionDecl`,\n  // and both end up here. The `FunctionDecl` shouldn't use the current block on\n  // inst_block_stack_ because it's not tied to the referencing scope.\n  //\n  // This becomes `InstBlockId::Imports`.\n  llvm::SmallVector<SemIR::InstId> imports_;\n\n  // Entities which are generated internally to the toolchain, to represent\n  // builtin concepts which should be dumped as part of `SemIR`. For example,\n  // when doing destruction, the `Destroy.Op` function is generated, and will be\n  // found here.\n  //\n  // This becomes `InstBlockId::Generated`.\n  llvm::SmallVector<SemIR::InstId> generated_;\n\n  // Map from an AnyBindingPattern inst to precomputed parts of the\n  // pattern-match SemIR for it.\n  Map<SemIR::InstId, BindingPatternInfo> bind_name_map_;\n\n  // Map from VarPattern insts to the corresponding VarStorage insts. The\n  // VarStorage insts are allocated, emitted, and stored in the map after\n  // processing the enclosing full-pattern.\n  Map<SemIR::InstId, SemIR::InstId> var_storage_map_;\n\n  // Each alternative in a Choice gets an entry here, they are stored in\n  // declaration order. The vector is consumed and emptied at the end of the\n  // Choice definition.\n  //\n  // TODO: This may need to be a stack of vectors if it becomes possible to\n  // define a Choice type inside an alternative's parameter set.\n  llvm::SmallVector<ChoiceDeferredBinding> choice_deferred_bindings_;\n\n  // Stack of single-entry regions being built.\n  RegionStack region_stack_;\n\n  // Tracks all ongoing impl lookups in order to ensure that lookup terminates\n  // via the acyclic rule and the termination rule.\n  llvm::SmallVector<ImplLookupStackEntry> impl_lookup_stack_;\n\n  // Tracks a mapping from (self, interface) to witness, for queries that had\n  // final results.\n  ImplLookupCacheMap impl_lookup_cache_;\n\n  // Tracks impl lookup queries that lead to concrete witness results, along\n  // with those results. Used to verify that the same queries produce the same\n  // results at the end of the file. Any difference is diagnosed.\n  llvm::SmallVector<PoisonedConcreteImplLookupQuery>\n      poisoned_concrete_impl_lookup_queries_;\n\n  // A map from an ImplWitnessAccess on the LHS of a rewrite constraint to its\n  // value on the RHS. Used during checking of a `where` expression to allow\n  // constraints to access values from earlier constraints.\n  llvm::SmallVector<Map<SemIR::ConstantId, SemIR::InstId>> rewrites_stack_;\n\n  // Declared return form for the in-progress function declaration, if any.\n  std::optional<FormExpr> return_form_expr_;\n\n  // See `CoreIdentifierCache` for details.\n  CoreIdentifierCache core_identifiers_;\n};\n\ninline constexpr Context::FormExpr Context::FormExpr::Error = {\n    .form_inst_id = SemIR::ErrorInst::InstId,\n    .type_component_inst_id = SemIR::ErrorInst::TypeInstId,\n    .type_component_id = SemIR::ErrorInst::TypeId};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CONTEXT_H_\n"
  },
  {
    "path": "toolchain/check/control_flow.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/control_flow.h\"\n\n#include <initializer_list>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/operator.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\ntemplate <typename BranchNode, typename... Args>\nstatic auto AddDominatedBlockAndBranchImpl(Context& context,\n                                           Parse::NodeId node_id, Args... args)\n    -> SemIR::InstBlockId {\n  if (!context.inst_block_stack().is_current_block_reachable()) {\n    return SemIR::InstBlockId::Unreachable;\n  }\n  auto block_id = context.inst_blocks().AddPlaceholder();\n  AddInst<BranchNode>(context, node_id, {block_id, args...});\n  return block_id;\n}\n\nauto AddDominatedBlockAndBranch(Context& context, Parse::NodeId node_id)\n    -> SemIR::InstBlockId {\n  return AddDominatedBlockAndBranchImpl<SemIR::Branch>(context, node_id);\n}\n\nauto AddDominatedBlockAndBranchWithArg(Context& context, Parse::NodeId node_id,\n                                       SemIR::InstId arg_id)\n    -> SemIR::InstBlockId {\n  return AddDominatedBlockAndBranchImpl<SemIR::BranchWithArg>(context, node_id,\n                                                              arg_id);\n}\n\nauto AddDominatedBlockAndBranchIf(Context& context, Parse::NodeId node_id,\n                                  SemIR::InstId cond_id) -> SemIR::InstBlockId {\n  return AddDominatedBlockAndBranchImpl<SemIR::BranchIf>(context, node_id,\n                                                         cond_id);\n}\n\nauto AddConvergenceBlockAndPush(Context& context, Parse::NodeId node_id,\n                                int num_blocks) -> void {\n  CARBON_CHECK(num_blocks >= 2, \"no convergence\");\n\n  SemIR::InstBlockId new_block_id = SemIR::InstBlockId::Unreachable;\n  for ([[maybe_unused]] auto _ : llvm::seq(num_blocks)) {\n    if (context.inst_block_stack().is_current_block_reachable()) {\n      if (new_block_id == SemIR::InstBlockId::Unreachable) {\n        new_block_id = context.inst_blocks().AddPlaceholder();\n      }\n      CARBON_CHECK(node_id.has_value());\n      AddInst<SemIR::Branch>(context, node_id, {.target_id = new_block_id});\n    }\n    context.inst_block_stack().Pop();\n  }\n  context.inst_block_stack().Push(new_block_id);\n  context.region_stack().AddToRegion(new_block_id, node_id);\n}\n\nauto AddConvergenceBlockWithArgAndPush(\n    Context& context, Parse::NodeId node_id,\n    std::initializer_list<SemIR::InstId> block_args) -> SemIR::InstId {\n  CARBON_CHECK(block_args.size() >= 2, \"no convergence\");\n\n  SemIR::InstBlockId new_block_id = SemIR::InstBlockId::Unreachable;\n  for (auto arg_id : block_args) {\n    if (context.inst_block_stack().is_current_block_reachable()) {\n      if (new_block_id == SemIR::InstBlockId::Unreachable) {\n        new_block_id = context.inst_blocks().AddPlaceholder();\n      }\n      AddInst<SemIR::BranchWithArg>(\n          context, node_id, {.target_id = new_block_id, .arg_id = arg_id});\n    }\n    context.inst_block_stack().Pop();\n  }\n  context.inst_block_stack().Push(new_block_id);\n  context.region_stack().AddToRegion(new_block_id, node_id);\n\n  // Acquire the result value.\n  SemIR::TypeId result_type_id =\n      context.insts().Get(*block_args.begin()).type_id();\n  return AddInst<SemIR::BlockArg>(\n      context, node_id, {.type_id = result_type_id, .block_id = new_block_id});\n}\n\nauto SetBlockArgResultBeforeConstantUse(Context& context,\n                                        SemIR::InstId select_id,\n                                        SemIR::InstId cond_id,\n                                        SemIR::InstId if_true,\n                                        SemIR::InstId if_false) -> void {\n  CARBON_CHECK(context.insts().Is<SemIR::BlockArg>(select_id));\n\n  // Determine the constant result based on the condition value.\n  SemIR::ConstantId const_id = SemIR::ConstantId::NotConstant;\n  auto cond_const_id = context.constant_values().Get(cond_id);\n  if (!cond_const_id.is_concrete()) {\n    // Symbolic or non-constant condition means a non-constant result.\n  } else if (auto literal = context.insts().TryGetAs<SemIR::BoolLiteral>(\n                 context.constant_values().GetInstId(cond_const_id))) {\n    const_id = context.constant_values().Get(\n        literal.value().value.ToBool() ? if_true : if_false);\n  } else {\n    CARBON_CHECK(cond_const_id == SemIR::ErrorInst::ConstantId,\n                 \"Unexpected constant branch condition.\");\n    const_id = SemIR::ErrorInst::ConstantId;\n  }\n\n  if (const_id.is_constant()) {\n    CARBON_VLOG_TO(context.vlog_stream(), \"Constant: {0} -> {1}\\n\",\n                   context.insts().Get(select_id),\n                   context.constant_values().GetInstId(const_id));\n    context.constant_values().Set(select_id, const_id);\n  }\n}\n\nauto IsCurrentPositionReachable(Context& context) -> bool {\n  if (!context.inst_block_stack().is_current_block_reachable()) {\n    return false;\n  }\n\n  // Our current position is at the end of a reachable block. That position is\n  // reachable unless the previous instruction is a terminator instruction.\n  auto block_contents = context.inst_block_stack().PeekCurrentBlockContents();\n  if (block_contents.empty()) {\n    return true;\n  }\n  const auto& last_inst = context.insts().Get(block_contents.back());\n  return last_inst.kind().terminator_kind() !=\n         SemIR::TerminatorKind::Terminator;\n}\n\nauto MaybeAddCleanupForInst(Context& context, SemIR::InstId inst_id) -> void {\n  if (!context.scope_stack().IsInFunctionScope()) {\n    // Cleanup can only occur in function scopes.\n    return;\n  }\n\n  context.scope_stack().destroy_id_stack().AppendToTop(inst_id);\n}\n\n// Common support for cleanup blocks.\nstatic auto AddCleanupBlock(Context& context) -> void {\n  auto destroy_ids = context.scope_stack().destroy_id_stack().PeekArray();\n\n  // If there's nothing to destroy, add the final instruction to the current\n  // block.\n  if (destroy_ids.empty()) {\n    return;\n  }\n\n  for (auto destroy_id : llvm::reverse(destroy_ids)) {\n    // TODO: This does the `Destroy` lookup and call at every cleanup block.\n    // Control flow can lead to the same variable being destroyed by multiple\n    // cleanup blocks, so we'll want to avoid this in the future.\n    BuildUnaryOperator(context,\n                       context.insts().GetLocIdForDesugaring(destroy_id),\n                       {.interface_name = CoreIdentifier::Destroy}, destroy_id);\n  }\n}\n\nauto AddReturnCleanupBlock(Context& context,\n                           SemIR::LocIdAndInst loc_id_and_inst) -> void {\n  AddCleanupBlock(context);\n  AddInst(context, loc_id_and_inst);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/control_flow.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CONTROL_FLOW_H_\n#define CARBON_TOOLCHAIN_CHECK_CONTROL_FLOW_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/parse/typed_nodes.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n\nnamespace Carbon::Check {\n\n// Adds a `Branch` instruction branching to a new instruction block, and\n// returns the ID of the new block. All paths to the branch target must go\n// through the current block, though not necessarily through this branch.\nauto AddDominatedBlockAndBranch(Context& context, Parse::NodeId node_id)\n    -> SemIR::InstBlockId;\n\n// Adds a `Branch` instruction branching to a new instruction block with a\n// value, and returns the ID of the new block. All paths to the branch target\n// must go through the current block.\nauto AddDominatedBlockAndBranchWithArg(Context& context, Parse::NodeId node_id,\n                                       SemIR::InstId arg_id)\n    -> SemIR::InstBlockId;\n\n// Adds a `BranchIf` instruction branching to a new instruction block, and\n// returns the ID of the new block. All paths to the branch target must go\n// through the current block.\nauto AddDominatedBlockAndBranchIf(Context& context, Parse::NodeId node_id,\n                                  SemIR::InstId cond_id) -> SemIR::InstBlockId;\n\n// Handles recovergence of control flow. Adds branches from the top\n// `num_blocks` on the instruction block stack to a new block, pops the\n// existing blocks, pushes the new block onto the instruction block stack,\n// and adds it to the most recently pushed region.\nauto AddConvergenceBlockAndPush(Context& context, Parse::NodeId node_id,\n                                int num_blocks) -> void;\n\n// Handles recovergence of control flow with a result value. Adds branches\n// from the top few blocks on the instruction block stack to a new block, pops\n// the existing blocks,  pushes the new block onto the instruction block\n// stack, and adds it to the most recently pushed region. The number of blocks\n// popped is the size of `block_args`, and the corresponding result values are\n// the elements of `block_args`. Returns an instruction referring to the\n// result value.\nauto AddConvergenceBlockWithArgAndPush(\n    Context& context, Parse::NodeId node_id,\n    std::initializer_list<SemIR::InstId> block_args) -> SemIR::InstId;\n\n// Sets the constant value of a block argument created as the result of a\n// branch.  `select_id` should be a `BlockArg` that selects between two\n// values. `cond_id` is the condition, `if_false` is the value to use if the\n// condition is false, and `if_true` is the value to use if the condition is\n// true.  We don't track enough information in the `BlockArg` inst for\n// `TryEvalInst` to do this itself.\nauto SetBlockArgResultBeforeConstantUse(Context& context,\n                                        SemIR::InstId select_id,\n                                        SemIR::InstId cond_id,\n                                        SemIR::InstId if_true,\n                                        SemIR::InstId if_false) -> void;\n\n// Returns whether the current position in the current block is reachable.\nauto IsCurrentPositionReachable(Context& context) -> bool;\n\n// Determines whether the instruction requires cleanup and, if so, adds it for\n// cleanup blocks. Note for example that a class may not need destruction when\n// neither it nor its members have `destroy` functions.\nauto MaybeAddCleanupForInst(Context& context, SemIR::InstId inst_id) -> void;\n\n// Adds an instruction that has cleanup associated.\ntemplate <typename InstT, typename LocT>\n  requires(InstT::Kind.has_cleanup() && std::convertible_to<LocT, SemIR::LocId>)\nauto AddInstWithCleanup(Context& context, LocT loc, InstT inst)\n    -> SemIR::InstId {\n  auto inst_id = AddInst(context, SemIR::LocIdAndInst(loc, inst));\n  MaybeAddCleanupForInst(context, inst_id);\n  return inst_id;\n}\n\n// Adds an instruction that has cleanup associated.\ntemplate <typename InstT, typename LocT>\n  requires(InstT::Kind.has_cleanup() && std::convertible_to<LocT, SemIR::LocId>)\nauto AddInstWithCleanupInNoBlock(Context& context, LocT loc, InstT inst)\n    -> SemIR::InstId {\n  auto inst_id = AddInstInNoBlock(context, SemIR::LocIdAndInst(loc, inst));\n  MaybeAddCleanupForInst(context, inst_id);\n  return inst_id;\n}\n\n// Adds a return cleanup block, including the returning instruction.\n//\n// Cleanup blocks are an effort to share cleanup instructions across equivalent\n// scope-ending instructions (for example, all `return;` instructions are\n// equivalent). Structurally, they should first run non-shared cleanup, then\n// either dispatch to a cleanup block that includes shared cleanup, or invoke\n// the control flow instruction.\n//\n// For example:\n//\n//   fn F() {\n//     var a: C;\n//     if (...) {\n//       // Cleanup block 1: destroy a, return\n//       return;\n//     }\n//\n//     var b: C;\n//     if (...) {\n//       // Cleanup block 2: destroy b, reuse cleanup block 1.\n//       return;\n//     }\n//\n//     DoSomethingMore();\n//     // Cleanup block 3: reuse cleanup block 2.\n//   }\n//\n// TODO: Add support for `break;` and `continue;`.\n// TODO: Add reuse (described above but not done).\nauto AddReturnCleanupBlock(Context& context,\n                           SemIR::LocIdAndInst loc_id_and_inst) -> void;\n\ntemplate <typename LocT>\nauto AddReturnCleanupBlock(Context& context, LocT loc) -> void {\n  AddReturnCleanupBlock(context, SemIR::LocIdAndInst(loc, SemIR::Return{}));\n}\ntemplate <typename LocT>\nauto AddReturnCleanupBlockWithExpr(Context& context, LocT loc,\n                                   SemIR::ReturnExpr inst) -> void {\n  AddReturnCleanupBlock(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CONTROL_FLOW_H_\n"
  },
  {
    "path": "toolchain/check/convert.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/convert.h\"\n\n#include <optional>\n#include <string>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/map.h\"\n#include \"llvm/ADT/STLExtras.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/action.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/impl_lookup.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/member_access.h\"\n#include \"toolchain/check/operator.h\"\n#include \"toolchain/check/pattern_match.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/sem_ir/copy_on_write_block.h\"\n#include \"toolchain/sem_ir/expr_info.h\"\n#include \"toolchain/sem_ir/file.h\"\n#include \"toolchain/sem_ir/generic.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/inst_kind.h\"\n#include \"toolchain/sem_ir/type.h\"\n#include \"toolchain/sem_ir/type_info.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\n// TODO: This contains a lot of recursion. Consider removing it in order to\n// prevent accidents.\n// NOLINTBEGIN(misc-no-recursion)\n\nnamespace Carbon::Check {\n\n// If the initializing expression `init_id` has a storage argument that refers\n// to a temporary, overwrites it with the inst at `target.storage_id`, and\n// returns the ID that should now be used to refer to `init_id`'s storage. Has\n// no effect and returns `target.storage_id` unchanged if `target.storage_id` is\n// None, if `init_id` doesn't have a storage arg, or if the storage argument\n// doesn't point to a temporary. In the latter case, we assume it was set\n// correctly when the instruction was created.\nstatic auto OverwriteTemporaryStorageArg(SemIR::File& sem_ir,\n                                         SemIR::InstId init_id,\n                                         const ConversionTarget& target)\n    -> SemIR::InstId {\n  CARBON_CHECK(target.is_initializer());\n  if (!target.storage_id.has_value()) {\n    return SemIR::InstId::None;\n  }\n  auto storage_arg_id = FindStorageArgForInitializer(sem_ir, init_id);\n  if (!storage_arg_id.has_value() || storage_arg_id == target.storage_id ||\n      !sem_ir.insts().Is<SemIR::TemporaryStorage>(storage_arg_id)) {\n    return target.storage_id;\n  }\n  // Replace the temporary in the storage argument with a reference to our\n  // target.\n  return target.storage_access_block->MergeReplacing(storage_arg_id,\n                                                     target.storage_id);\n}\n\n// Materializes and returns a temporary initialized from the initializer\n// `init_id`. If `init_id` has a storage arg, it must be a `TemporaryStorage`;\n// if not, this function allocates one for it.\nstatic auto MaterializeTemporary(Context& context, SemIR::InstId init_id)\n    -> SemIR::InstId {\n  auto& sem_ir = context.sem_ir();\n  auto category = SemIR::GetExprCategory(sem_ir, init_id);\n  CARBON_CHECK(SemIR::IsInitializerCategory(category));\n  auto init = sem_ir.insts().Get(init_id);\n  auto storage_id = FindStorageArgForInitializer(sem_ir, init_id);\n  if (!storage_id.has_value()) {\n    CARBON_CHECK(category == SemIR::ExprCategory::ReprInitializing);\n    // The initializer has no storage arg, but we want to produce an ephemeral\n    // reference, so we need to allocate temporary storage.\n    storage_id = AddInst<SemIR::TemporaryStorage>(\n        context, SemIR::LocId(init_id), {.type_id = init.type_id()});\n  }\n\n  CARBON_CHECK(\n      sem_ir.insts().Get(storage_id).kind() == SemIR::TemporaryStorage::Kind,\n      \"Storage arg for initializer does not contain a temporary; \"\n      \"initialized multiple times? Have {0}\",\n      sem_ir.insts().Get(storage_id));\n  return AddInstWithCleanup<SemIR::Temporary>(context, SemIR::LocId(init_id),\n                                              {.type_id = init.type_id(),\n                                               .storage_id = storage_id,\n                                               .init_id = init_id});\n}\n\n// Discards the initializer `init_id`. If `init_id` intrinsically writes to\n// memory, this materializes a temporary for it and starts its lifetime.\n//\n// TODO: We should probably start its lifetime unconditionally, because\n// types with by-copy representations can still have nontrivial destructors.\nstatic auto DiscardInitializer(Context& context, SemIR::InstId init_id)\n    -> void {\n  auto& sem_ir = context.sem_ir();\n  auto storage_id = FindStorageArgForInitializer(sem_ir, init_id);\n  if (!storage_id.has_value()) {\n    CARBON_CHECK(SemIR::GetExprCategory(sem_ir, init_id) ==\n                 SemIR::ExprCategory::ReprInitializing);\n    return;\n  }\n\n  // init_id writes to temporary storage, so we need to materialize a temporary\n  // for it.\n  MaterializeTemporary(context, init_id);\n}\n\n// If `expr_id` is an initializer, materializes it and returns the resulting\n// ephemeral reference expression. Otherwise, returns `expr_id`.\nstatic auto MaterializeIfInitializer(Context& context, SemIR::InstId expr_id)\n    -> SemIR::InstId {\n  if (SemIR::IsInitializerCategory(\n          SemIR::GetExprCategory(context.sem_ir(), expr_id))) {\n    return MaterializeTemporary(context, expr_id);\n  } else {\n    return expr_id;\n  }\n}\n\n// Helper to allow `MakeElementAccessInst` to call `AddInst` with either a\n// `PendingBlock` or `Context` (defined in `inst.h`).\ntemplate <typename AccessInstT>\nstatic auto AddInst(PendingBlock& block, SemIR::LocId loc_id, AccessInstT inst)\n    -> SemIR::InstId {\n  return block.AddInst<AccessInstT>(loc_id, inst);\n}\n\n// Creates and adds an instruction to perform element access into an aggregate.\ntemplate <typename AccessInstT, typename InstBlockT>\nstatic auto MakeElementAccessInst(Context& context, SemIR::LocId loc_id,\n                                  SemIR::InstId aggregate_id,\n                                  SemIR::TypeId elem_type_id, InstBlockT& block,\n                                  size_t i) -> SemIR::InstId {\n  if (!aggregate_id.has_value()) {\n    return SemIR::InstId::None;\n  }\n  if constexpr (std::is_same_v<AccessInstT, SemIR::ArrayIndex>) {\n    // TODO: Add a new instruction kind for indexing an array at a constant\n    // index so that we don't need an integer literal instruction here, and\n    // remove this special case.\n    auto index_id = block.template AddInst<SemIR::IntValue>(\n        loc_id, {.type_id = GetSingletonType(context,\n                                             SemIR::IntLiteralType::TypeInstId),\n                 .int_id = context.ints().Add(static_cast<int64_t>(i))});\n    return AddInst<AccessInstT>(block, loc_id,\n                                {elem_type_id, aggregate_id, index_id});\n  } else {\n    return AddInst<AccessInstT>(\n        block, loc_id, {elem_type_id, aggregate_id, SemIR::ElementIndex(i)});\n  }\n}\n\n// Get the conversion target kind to use when initializing an element of an\n// aggregate.\nstatic auto GetAggregateElementConversionTargetKind(SemIR::File& sem_ir,\n                                                    ConversionTarget target)\n    -> ConversionTarget::Kind {\n  // If we're forming an initializer, then we want an initializer for each\n  // element.\n  if (target.is_initializer()) {\n    // Perform a final destination store if we're performing an in-place\n    // initialization.\n    auto init_repr = SemIR::InitRepr::ForType(sem_ir, target.type_id);\n    CARBON_CHECK(init_repr.kind != SemIR::InitRepr::Dependent,\n                 \"Aggregate should not have dependent init kind\");\n    if (init_repr.kind == SemIR::InitRepr::InPlace) {\n      return ConversionTarget::InPlaceInitializing;\n    }\n    return ConversionTarget::Initializing;\n  }\n\n  // Otherwise, we want a value representation for each element.\n  return ConversionTarget::Value;\n}\n\n// Converts an element of one aggregate so that it can be used as an element of\n// another aggregate.\n//\n// For the source: `src_id` is the source aggregate, `src_elem_type` is the\n// element type, `src_field_index` is the index, and `SourceAccessInstT` is the\n// kind of instruction used to access the source element.\n//\n// For the target: `kind` is the kind of conversion or initialization,\n// `target_elem_type` is the element type. For initialization, `target_id` is\n// the destination, `target_block` is a pending block for target location\n// calculations that will be spliced as the return slot of the initializer if\n// necessary, `target_field_index` is the index, and `TargetAccessInstT` is the\n// kind of instruction used to access the destination element.\ntemplate <typename SourceAccessInstT, typename TargetAccessInstT>\nstatic auto ConvertAggregateElement(\n    Context& context, SemIR::LocId loc_id, SemIR::InstId src_id,\n    SemIR::TypeInstId src_elem_type_inst,\n    llvm::ArrayRef<SemIR::InstId> src_literal_elems,\n    ConversionTarget::Kind kind, SemIR::InstId target_id,\n    SemIR::TypeInstId target_elem_type_inst, PendingBlock* target_block,\n    size_t src_field_index, size_t target_field_index) -> SemIR::InstId {\n  auto src_elem_type =\n      context.types().GetTypeIdForTypeInstId(src_elem_type_inst);\n  auto target_elem_type =\n      context.types().GetTypeIdForTypeInstId(target_elem_type_inst);\n\n  // Compute the location of the source element. This goes into the current code\n  // block, not into the target block.\n  // TODO: Ideally we would discard this instruction if it's unused.\n  auto src_elem_id = !src_literal_elems.empty()\n                         ? src_literal_elems[src_field_index]\n                         : MakeElementAccessInst<SourceAccessInstT>(\n                               context, loc_id, src_id, src_elem_type, context,\n                               src_field_index);\n\n  // If we're performing a conversion rather than an initialization, we won't\n  // have or need a target.\n  ConversionTarget target = {.kind = kind, .type_id = target_elem_type};\n  if (!target.is_initializer()) {\n    return Convert(context, loc_id, src_elem_id, target);\n  }\n\n  // Compute the location of the target element and initialize it.\n  PendingBlock::DiscardUnusedInstsScope scope(target_block);\n  target.storage_access_block = target_block;\n  target.storage_id = MakeElementAccessInst<TargetAccessInstT>(\n      context, loc_id, target_id, target_elem_type, *target_block,\n      target_field_index);\n  return Convert(context, loc_id, src_elem_id, target);\n}\n\n// Performs a conversion from a tuple to an array type. This function only\n// converts the type, and does not perform a final conversion to the requested\n// expression category.\nstatic auto ConvertTupleToArray(Context& context, SemIR::TupleType tuple_type,\n                                SemIR::ArrayType array_type,\n                                SemIR::InstId value_id, ConversionTarget target)\n    -> SemIR::InstId {\n  auto& sem_ir = context.sem_ir();\n  auto tuple_elem_types = sem_ir.inst_blocks().Get(tuple_type.type_elements_id);\n\n  auto value = sem_ir.insts().Get(value_id);\n  SemIR::LocId value_loc_id(value_id);\n\n  // If we're initializing from a tuple literal, we will use its elements\n  // directly. Otherwise, materialize a temporary if needed and index into the\n  // result.\n  llvm::ArrayRef<SemIR::InstId> literal_elems;\n  if (auto tuple_literal = value.TryAs<SemIR::TupleLiteral>()) {\n    literal_elems = sem_ir.inst_blocks().Get(tuple_literal->elements_id);\n  } else {\n    value_id = MaterializeIfInitializer(context, value_id);\n  }\n\n  // Check that the tuple is the right size.\n  std::optional<uint64_t> array_bound =\n      sem_ir.GetArrayBoundValue(array_type.bound_id);\n  if (!array_bound) {\n    // TODO: Should this fall back to using `ImplicitAs`?\n    if (target.diagnose) {\n      CARBON_DIAGNOSTIC(ArrayInitDependentBound, Error,\n                        \"cannot initialize array with dependent bound from a \"\n                        \"list of initializers\");\n      context.emitter().Emit(value_loc_id, ArrayInitDependentBound);\n    }\n    return SemIR::ErrorInst::InstId;\n  }\n  if (tuple_elem_types.size() != array_bound) {\n    if (target.diagnose) {\n      CARBON_DIAGNOSTIC(ArrayInitFromLiteralArgCountMismatch, Error,\n                        \"cannot initialize array of {0} element{0:s} from {1} \"\n                        \"initializer{1:s}\",\n                        Diagnostics::IntAsSelect, Diagnostics::IntAsSelect);\n      CARBON_DIAGNOSTIC(\n          ArrayInitFromExprArgCountMismatch, Error,\n          \"cannot initialize array of {0} element{0:s} from tuple \"\n          \"with {1} element{1:s}\",\n          Diagnostics::IntAsSelect, Diagnostics::IntAsSelect);\n      context.emitter().Emit(value_loc_id,\n                             literal_elems.empty()\n                                 ? ArrayInitFromExprArgCountMismatch\n                                 : ArrayInitFromLiteralArgCountMismatch,\n                             *array_bound, tuple_elem_types.size());\n    }\n    return SemIR::ErrorInst::InstId;\n  }\n\n  PendingBlock target_block_storage(&context);\n  PendingBlock* target_block = target.storage_access_block\n                                   ? target.storage_access_block\n                                   : &target_block_storage;\n\n  // Arrays are always initialized in-place. Allocate a temporary as the\n  // destination for the array initialization if we weren't given one.\n  SemIR::InstId return_slot_arg_id = target.storage_id;\n  if (!target.storage_id.has_value()) {\n    return_slot_arg_id = target_block->AddInst<SemIR::TemporaryStorage>(\n        value_loc_id, {.type_id = target.type_id});\n  }\n\n  // Initialize each element of the array from the corresponding element of the\n  // tuple.\n  // TODO: Annotate diagnostics coming from here with the array element index,\n  // if initializing from a tuple literal.\n  llvm::SmallVector<SemIR::InstId> inits;\n  inits.reserve(*array_bound + 1);\n  for (auto [i, src_type_inst_id] : llvm::enumerate(\n           context.types().GetBlockAsTypeInstIds(tuple_elem_types))) {\n    // TODO: This call recurses back into conversion. Switch to an iterative\n    // approach.\n    auto init_id =\n        ConvertAggregateElement<SemIR::TupleAccess, SemIR::ArrayIndex>(\n            context, value_loc_id, value_id, src_type_inst_id, literal_elems,\n            ConversionTarget::InPlaceInitializing, return_slot_arg_id,\n            array_type.element_type_inst_id, target_block, i, i);\n    if (init_id == SemIR::ErrorInst::InstId) {\n      return SemIR::ErrorInst::InstId;\n    }\n    inits.push_back(init_id);\n  }\n\n  // Flush the temporary here if we didn't insert it earlier, so we can add a\n  // reference to the return slot.\n  target_block->InsertHere();\n  return AddInst<SemIR::ArrayInit>(context, value_loc_id,\n                                   {.type_id = target.type_id,\n                                    .inits_id = sem_ir.inst_blocks().Add(inits),\n                                    .dest_id = return_slot_arg_id});\n}\n\n// Performs a conversion from a tuple to a tuple type. This function only\n// converts the type, and does not perform a final conversion to the requested\n// expression category.\nstatic auto ConvertTupleToTuple(Context& context, SemIR::TupleType src_type,\n                                SemIR::TupleType dest_type,\n                                SemIR::InstId value_id, ConversionTarget target)\n    -> SemIR::InstId {\n  auto& sem_ir = context.sem_ir();\n  auto src_elem_types = sem_ir.inst_blocks().Get(src_type.type_elements_id);\n  auto dest_elem_types = sem_ir.inst_blocks().Get(dest_type.type_elements_id);\n\n  auto value = sem_ir.insts().Get(value_id);\n  SemIR::LocId value_loc_id(value_id);\n\n  // If we're initializing from a tuple literal, we will use its elements\n  // directly. Otherwise, materialize a temporary if needed and index into the\n  // result.\n  llvm::ArrayRef<SemIR::InstId> literal_elems;\n  auto literal_elems_id = SemIR::InstBlockId::None;\n  if (auto tuple_literal = value.TryAs<SemIR::TupleLiteral>()) {\n    literal_elems_id = tuple_literal->elements_id;\n    literal_elems = sem_ir.inst_blocks().Get(literal_elems_id);\n  } else {\n    value_id = MaterializeIfInitializer(context, value_id);\n  }\n\n  // Check that the tuples are the same size.\n  if (src_elem_types.size() != dest_elem_types.size()) {\n    if (target.diagnose) {\n      CARBON_DIAGNOSTIC(\n          TupleInitElementCountMismatch, Error,\n          \"cannot initialize tuple of {0} element{0:s} from tuple \"\n          \"with {1} element{1:s}\",\n          Diagnostics::IntAsSelect, Diagnostics::IntAsSelect);\n      context.emitter().Emit(value_loc_id, TupleInitElementCountMismatch,\n                             dest_elem_types.size(), src_elem_types.size());\n    }\n    return SemIR::ErrorInst::InstId;\n  }\n\n  ConversionTarget::Kind inner_kind =\n      GetAggregateElementConversionTargetKind(sem_ir, target);\n\n  // Initialize each element of the destination from the corresponding element\n  // of the source.\n  // TODO: Annotate diagnostics coming from here with the element index.\n  auto new_block =\n      literal_elems_id.has_value()\n          ? SemIR::CopyOnWriteInstBlock(&sem_ir, literal_elems_id)\n          : SemIR::CopyOnWriteInstBlock(\n                &sem_ir, SemIR::CopyOnWriteInstBlock::UninitializedBlock{\n                             src_elem_types.size()});\n  for (auto [i, src_type_inst_id, dest_type_inst_id] : llvm::enumerate(\n           context.types().GetBlockAsTypeInstIds(src_elem_types),\n           context.types().GetBlockAsTypeInstIds(dest_elem_types))) {\n    // TODO: This call recurses back into conversion. Switch to an iterative\n    // approach.\n    auto init_id =\n        ConvertAggregateElement<SemIR::TupleAccess, SemIR::TupleAccess>(\n            context, value_loc_id, value_id, src_type_inst_id, literal_elems,\n            inner_kind, target.storage_id, dest_type_inst_id,\n            target.storage_access_block, i, i);\n    if (init_id == SemIR::ErrorInst::InstId) {\n      return SemIR::ErrorInst::InstId;\n    }\n    new_block.Set(i, init_id);\n  }\n\n  if (target.is_initializer()) {\n    target.storage_access_block->InsertHere();\n    return AddInst<SemIR::TupleInit>(context, value_loc_id,\n                                     {.type_id = target.type_id,\n                                      .elements_id = new_block.id(),\n                                      .dest_id = target.storage_id});\n  } else {\n    return AddInst<SemIR::TupleValue>(\n        context, value_loc_id,\n        {.type_id = target.type_id, .elements_id = new_block.id()});\n  }\n}\n\n// Converts a tuple of elements that are convertible to `type` into a `type`\n// that is a tuple of types.\nstatic auto ConvertTupleToType(Context& context, SemIR::LocId loc_id,\n                               SemIR::InstId value_id,\n                               SemIR::TypeId value_type_id,\n                               ConversionTarget target) -> SemIR::TypeInstId {\n  auto value_const_id = context.constant_values().Get(value_id);\n  if (!value_const_id.is_constant()) {\n    // Types are constants. The input value must have a constant value to\n    // convert.\n    return SemIR::TypeInstId::None;\n  }\n\n  llvm::SmallVector<SemIR::InstId> type_inst_ids;\n\n  auto value_const_inst_id =\n      context.constant_values().GetInstId(value_const_id);\n  if (auto tuple_value =\n          context.insts().TryGetAs<SemIR::TupleValue>(value_const_inst_id)) {\n    for (auto tuple_inst_id :\n         context.inst_blocks().Get(tuple_value->elements_id)) {\n      // TODO: This call recurses back into conversion. Switch to an\n      // iterative approach.\n      type_inst_ids.push_back(\n          ExprAsType(context, loc_id, tuple_inst_id, target.diagnose).inst_id);\n    }\n  } else {\n    // A value of type TupleType that isn't a TupleValue must be a symbolic\n    // binding.\n    CARBON_CHECK(\n        context.insts().Is<SemIR::SymbolicBinding>(value_const_inst_id));\n    // Form a TupleAccess for each element in the symbolic value, which is then\n    // converted to a `type` or diagnosed as an error.\n    auto tuple_type = context.types().GetAs<SemIR::TupleType>(value_type_id);\n    auto type_elements = context.types().GetBlockAsTypeIds(\n        context.inst_blocks().Get(tuple_type.type_elements_id));\n    for (auto [i, type_id] : llvm::enumerate(type_elements)) {\n      auto access_inst_id =\n          GetOrAddInst<SemIR::TupleAccess>(context, loc_id,\n                                           {.type_id = type_id,\n                                            .tuple_id = value_id,\n                                            .index = SemIR::ElementIndex(i)});\n      // TODO: This call recurses back into conversion. Switch to an\n      // iterative approach.\n      type_inst_ids.push_back(\n          ExprAsType(context, loc_id, access_inst_id, target.diagnose).inst_id);\n    }\n  }\n\n  // TODO: Should we add this as an instruction? It will contain\n  // references to local InstIds.\n  auto tuple_type_id = GetTupleType(context, type_inst_ids);\n  return context.types().GetTypeInstId(tuple_type_id);\n}\n\n// Create a reference to the vtable pointer for a class. Returns None if the\n// class has no vptr.\nstatic auto CreateVtablePtrRef(Context& context, SemIR::LocId loc_id,\n                               SemIR::ClassType vtable_class_type)\n    -> SemIR::InstId {\n  auto vtable_decl_id =\n      context.classes().Get(vtable_class_type.class_id).vtable_decl_id;\n  if (!vtable_decl_id.has_value()) {\n    return SemIR::InstId::None;\n  }\n\n  LoadImportRef(context, vtable_decl_id);\n  auto canonical_vtable_decl_id =\n      context.constant_values().GetConstantInstId(vtable_decl_id);\n  return AddInst<SemIR::VtablePtr>(\n      context, loc_id,\n      {.type_id = GetPointerType(context, SemIR::VtableType::TypeInstId),\n       .vtable_id = context.insts()\n                        .GetAs<SemIR::VtableDecl>(canonical_vtable_decl_id)\n                        .vtable_id,\n       .specific_id = vtable_class_type.specific_id});\n}\n\n// Returns whether the given expression performs in-place initialization (or is\n// invalid).\nstatic auto IsInPlaceInitializing(Context& context, SemIR::InstId result_id) {\n  auto category = SemIR::GetExprCategory(context.sem_ir(), result_id);\n  return category == SemIR::ExprCategory::InPlaceInitializing ||\n         (category == SemIR::ExprCategory::ReprInitializing &&\n          SemIR::InitRepr::ForType(context.sem_ir(),\n                                   context.insts().Get(result_id).type_id())\n                  .kind == SemIR::InitRepr::InPlace) ||\n         category == SemIR::ExprCategory::Error;\n}\n\n// Returns the index of the vptr field in the given struct type fields, or\n// None if there is no vptr field.\nstatic auto GetVptrFieldIndex(llvm::ArrayRef<SemIR::StructTypeField> fields)\n    -> SemIR::ElementIndex {\n  // If the type introduces a vptr, it will always be the first field.\n  bool has_vptr =\n      !fields.empty() && fields.front().name_id == SemIR::NameId::Vptr;\n  return has_vptr ? SemIR::ElementIndex(0) : SemIR::ElementIndex::None;\n}\n\n// Builds a member access expression naming the vptr field of the given class\n// object. This is analogous to what `PerformMemberAccess` for `NameId::Vptr`\n// would return if the vptr could be found by name lookup.\nstatic auto PerformVptrAccess(Context& context, SemIR::LocId loc_id,\n                              SemIR::InstId class_ref_id) -> SemIR::InstId {\n  auto class_type_id = context.insts().Get(class_ref_id).type_id();\n  while (class_ref_id.has_value()) {\n    // The type of `ref_id` must be a class type.\n    if (class_type_id == SemIR::ErrorInst::TypeId) {\n      return SemIR::ErrorInst::InstId;\n    }\n    auto class_type = context.types().GetAs<SemIR::ClassType>(class_type_id);\n    auto& class_info = context.classes().Get(class_type.class_id);\n\n    // Get the object representation.\n    auto object_repr_id =\n        class_info.GetObjectRepr(context.sem_ir(), class_type.specific_id);\n    if (object_repr_id == SemIR::ErrorInst::TypeId) {\n      return SemIR::ErrorInst::InstId;\n    }\n    if (context.types().Is<SemIR::CustomLayoutType>(object_repr_id)) {\n      context.TODO(loc_id, \"accessing vptr of custom layout class\");\n      return SemIR::ErrorInst::InstId;\n    }\n\n    // Check to see if this class introduces the vptr.\n    auto repr_struct_type =\n        context.types().GetAs<SemIR::StructType>(object_repr_id);\n    auto repr_fields =\n        context.struct_type_fields().Get(repr_struct_type.fields_id);\n    if (auto vptr_field_index = GetVptrFieldIndex(repr_fields);\n        vptr_field_index.has_value()) {\n      return AddInst<SemIR::ClassElementAccess>(\n          context, loc_id,\n          {.type_id = context.types().GetTypeIdForTypeInstId(\n               repr_fields[vptr_field_index.index].type_inst_id),\n           .base_id = class_ref_id,\n           .index = vptr_field_index});\n    }\n\n    // Otherwise, step through to the base class and try again.\n    CARBON_CHECK(class_info.base_id.has_value(),\n                 \"Could not find vptr for dynamic class\");\n    auto base_decl = context.insts().GetAs<SemIR::BaseDecl>(class_info.base_id);\n    class_type_id = context.types().GetTypeIdForTypeInstId(\n        repr_fields[base_decl.index.index].type_inst_id);\n    class_ref_id =\n        AddInst<SemIR::ClassElementAccess>(context, loc_id,\n                                           {.type_id = class_type_id,\n                                            .base_id = class_ref_id,\n                                            .index = base_decl.index});\n  }\n  return class_ref_id;\n}\n\n// Converts an initializer for a type `partial T` to an initializer for `T` by\n// initializing the vptr if necessary.\nstatic auto ConvertPartialInitializerToNonPartial(\n    Context& context, ConversionTarget target,\n    SemIR::ClassType vtable_class_type, SemIR::InstId result_id)\n    -> SemIR::InstId {\n  auto loc_id = SemIR::LocId(result_id);\n  auto vptr_id = CreateVtablePtrRef(context, loc_id, vtable_class_type);\n  if (!vptr_id.has_value()) {\n    // No vtable pointer in this class, nothing to do.\n    return result_id;\n  }\n\n  CARBON_CHECK(\n      IsInPlaceInitializing(context, result_id),\n      \"Type with vptr should have in-place initializing representation\");\n\n  target.storage_access_block->InsertHere();\n  auto dest_id = PerformVptrAccess(context, loc_id, target.storage_id);\n  auto vptr_init_id = AddInst<SemIR::InPlaceInit>(\n      context, loc_id,\n      {.type_id = context.insts().Get(dest_id).type_id(),\n       .src_id = vptr_id,\n       .dest_id = dest_id});\n  return AddInst<SemIR::UpdateInit>(context, loc_id,\n                                    {.type_id = target.type_id,\n                                     .base_init_id = result_id,\n                                     .update_init_id = vptr_init_id});\n}\n\n// Common implementation for ConvertStructToStruct and ConvertStructToClass.\ntemplate <typename TargetAccessInstT>\nstatic auto ConvertStructToStructOrClass(\n    Context& context, SemIR::StructType src_type, SemIR::StructType dest_type,\n    SemIR::InstId value_id, ConversionTarget target,\n    SemIR::ClassType* vtable_class_type = nullptr) -> SemIR::InstId {\n  static_assert(std::is_same_v<SemIR::ClassElementAccess, TargetAccessInstT> ||\n                std::is_same_v<SemIR::StructAccess, TargetAccessInstT>);\n  constexpr bool ToClass =\n      std::is_same_v<SemIR::ClassElementAccess, TargetAccessInstT>;\n\n  auto& sem_ir = context.sem_ir();\n  auto src_elem_fields = sem_ir.struct_type_fields().Get(src_type.fields_id);\n  auto dest_elem_fields = sem_ir.struct_type_fields().Get(dest_type.fields_id);\n  auto dest_vptr_index = GetVptrFieldIndex(dest_elem_fields);\n  auto dest_elem_fields_size =\n      dest_elem_fields.size() - (dest_vptr_index.has_value() ? 1 : 0);\n\n  auto value = sem_ir.insts().Get(value_id);\n  SemIR::LocId value_loc_id(value_id);\n\n  // If we're initializing from a struct literal, we will use its elements\n  // directly. Otherwise, materialize a temporary if needed and index into the\n  // result.\n  llvm::ArrayRef<SemIR::InstId> literal_elems;\n  auto literal_elems_id = SemIR::InstBlockId::None;\n  if (auto struct_literal = value.TryAs<SemIR::StructLiteral>()) {\n    literal_elems_id = struct_literal->elements_id;\n    literal_elems = sem_ir.inst_blocks().Get(literal_elems_id);\n  } else {\n    value_id = MaterializeIfInitializer(context, value_id);\n  }\n\n  // Check that the structs are the same size.\n  // TODO: If not, include the name of the first source field that doesn't\n  // exist in the destination or vice versa in the diagnostic.\n  if (src_elem_fields.size() != dest_elem_fields_size) {\n    if (target.diagnose) {\n      CARBON_DIAGNOSTIC(\n          StructInitElementCountMismatch, Error,\n          \"cannot initialize {0:class|struct} with {1} field{1:s} from struct \"\n          \"with {2} field{2:s}\",\n          Diagnostics::BoolAsSelect, Diagnostics::IntAsSelect,\n          Diagnostics::IntAsSelect);\n      context.emitter().Emit(value_loc_id, StructInitElementCountMismatch,\n                             ToClass, dest_elem_fields_size,\n                             src_elem_fields.size());\n    }\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // Prepare to look up fields in the source by index.\n  Map<SemIR::NameId, int32_t> src_field_indexes;\n  if (src_type.fields_id != dest_type.fields_id) {\n    for (auto [i, field] : llvm::enumerate(src_elem_fields)) {\n      auto result = src_field_indexes.Insert(field.name_id, i);\n      CARBON_CHECK(result.is_inserted(), \"Duplicate field in source structure\");\n    }\n  }\n\n  ConversionTarget::Kind inner_kind =\n      GetAggregateElementConversionTargetKind(sem_ir, target);\n\n  // Initialize each element of the destination from the corresponding element\n  // of the source.\n  // TODO: Annotate diagnostics coming from here with the element index.\n  auto new_block =\n      literal_elems_id.has_value() && !dest_vptr_index.has_value()\n          ? SemIR::CopyOnWriteInstBlock(&sem_ir, literal_elems_id)\n          : SemIR::CopyOnWriteInstBlock(\n                &sem_ir, SemIR::CopyOnWriteInstBlock::UninitializedBlock{\n                             dest_elem_fields.size()});\n  for (auto [i, dest_field] : llvm::enumerate(dest_elem_fields)) {\n    if (dest_field.name_id == SemIR::NameId::Vptr) {\n      if constexpr (!ToClass) {\n        CARBON_FATAL(\"Only classes should have vptrs.\");\n      }\n      target.storage_access_block->InsertHere();\n      auto vptr_type_id =\n          context.types().GetTypeIdForTypeInstId(dest_field.type_inst_id);\n      auto dest_id =\n          AddInst<SemIR::ClassElementAccess>(context, value_loc_id,\n                                             {.type_id = vptr_type_id,\n                                              .base_id = target.storage_id,\n                                              .index = SemIR::ElementIndex(i)});\n      auto vtable_ptr_id = SemIR::InstId::None;\n      if (vtable_class_type) {\n        vtable_ptr_id =\n            CreateVtablePtrRef(context, value_loc_id, *vtable_class_type);\n        // Track that we initialized the vptr so we don't do it again.\n        vtable_class_type = nullptr;\n      } else {\n        // For a partial class type, we leave the vtable pointer uninitialized.\n        // TODO: Consider storing a specified value such as null for hardening.\n        vtable_ptr_id = AddInst<SemIR::UninitializedValue>(\n            context, value_loc_id,\n            {.type_id =\n                 GetPointerType(context, SemIR::VtableType::TypeInstId)});\n      }\n      auto init_id = AddInst<SemIR::InPlaceInit>(context, value_loc_id,\n                                                 {.type_id = vptr_type_id,\n                                                  .src_id = vtable_ptr_id,\n                                                  .dest_id = dest_id});\n      new_block.Set(i, init_id);\n      continue;\n    }\n\n    // Find the matching source field.\n    auto src_field_index = i;\n    if (src_type.fields_id != dest_type.fields_id) {\n      if (auto lookup = src_field_indexes.Lookup(dest_field.name_id)) {\n        src_field_index = lookup.value();\n      } else {\n        if (target.diagnose) {\n          if (literal_elems_id.has_value()) {\n            CARBON_DIAGNOSTIC(\n                StructInitMissingFieldInLiteral, Error,\n                \"missing value for field `{0}` in struct initialization\",\n                SemIR::NameId);\n            context.emitter().Emit(value_loc_id,\n                                   StructInitMissingFieldInLiteral,\n                                   dest_field.name_id);\n          } else {\n            CARBON_DIAGNOSTIC(StructInitMissingFieldInConversion, Error,\n                              \"cannot convert from struct type {0} to {1}: \"\n                              \"missing field `{2}` in source type\",\n                              TypeOfInstId, SemIR::TypeId, SemIR::NameId);\n            context.emitter().Emit(value_loc_id,\n                                   StructInitMissingFieldInConversion, value_id,\n                                   target.type_id, dest_field.name_id);\n          }\n        }\n        return SemIR::ErrorInst::InstId;\n      }\n    }\n    auto src_field = src_elem_fields[src_field_index];\n\n    // When initializing the `.base` field of a class, the destination type is\n    // `partial Base`, not `Base`.\n    // TODO: Skip this if the source field is an initializing expression of the\n    // non-partial type in order to produce smaller IR.\n    auto dest_field_type_inst_id = dest_field.type_inst_id;\n    if (dest_field.name_id == SemIR::NameId::Base) {\n      auto partial_type_id = GetQualifiedType(\n          context,\n          context.types().GetTypeIdForTypeInstId(dest_field.type_inst_id),\n          SemIR::TypeQualifiers::Partial);\n      dest_field_type_inst_id = context.types().GetTypeInstId(partial_type_id);\n    }\n\n    // TODO: This call recurses back into conversion. Switch to an iterative\n    // approach.\n    auto dest_field_index = src_field_index;\n    if (dest_vptr_index.has_value() &&\n        static_cast<int32_t>(src_field_index) >= dest_vptr_index.index) {\n      dest_field_index += 1;\n    }\n    auto init_id =\n        ConvertAggregateElement<SemIR::StructAccess, TargetAccessInstT>(\n            context, value_loc_id, value_id, src_field.type_inst_id,\n            literal_elems, inner_kind, target.storage_id,\n            dest_field_type_inst_id, target.storage_access_block,\n            src_field_index, dest_field_index);\n    if (init_id == SemIR::ErrorInst::InstId) {\n      return SemIR::ErrorInst::InstId;\n    }\n\n    // When initializing the base, adjust the type of the initializer from\n    // `partial Base` to `Base`. This isn't strictly correct, since we haven't\n    // finished initializing a `Base` until we store to the vptr, but is better\n    // than having an inconsistent type for the struct field initializer.\n    if (dest_field_type_inst_id != dest_field.type_inst_id) {\n      init_id = AddInst<SemIR::AsCompatible>(\n          context, value_loc_id,\n          {.type_id =\n               context.types().GetTypeIdForTypeInstId(dest_field.type_inst_id),\n           .source_id = init_id});\n    }\n\n    new_block.Set(i, init_id);\n  }\n\n  bool is_init = target.is_initializer();\n  if (ToClass) {\n    target.storage_access_block->InsertHere();\n    CARBON_CHECK(is_init,\n                 \"Converting directly to a class value is not supported\");\n    auto result_id = AddInst<SemIR::ClassInit>(context, value_loc_id,\n                                               {.type_id = target.type_id,\n                                                .elements_id = new_block.id(),\n                                                .dest_id = target.storage_id});\n    if (vtable_class_type) {\n      result_id = ConvertPartialInitializerToNonPartial(\n          context, target, *vtable_class_type, result_id);\n    }\n    return result_id;\n  } else if (is_init) {\n    target.storage_access_block->InsertHere();\n    return AddInst<SemIR::StructInit>(context, value_loc_id,\n                                      {.type_id = target.type_id,\n                                       .elements_id = new_block.id(),\n                                       .dest_id = target.storage_id});\n  } else {\n    return AddInst<SemIR::StructValue>(\n        context, value_loc_id,\n        {.type_id = target.type_id, .elements_id = new_block.id()});\n  }\n}\n\n// Performs a conversion from a struct to a struct type. This function only\n// converts the type, and does not perform a final conversion to the requested\n// expression category.\nstatic auto ConvertStructToStruct(Context& context, SemIR::StructType src_type,\n                                  SemIR::StructType dest_type,\n                                  SemIR::InstId value_id,\n                                  ConversionTarget target) -> SemIR::InstId {\n  return ConvertStructToStructOrClass<SemIR::StructAccess>(\n      context, src_type, dest_type, value_id, target);\n}\n\n// Performs a conversion from a struct to a class type. This function only\n// converts the type, and does not perform a final conversion to the requested\n// expression category.\nstatic auto ConvertStructToClass(Context& context, SemIR::StructType src_type,\n                                 SemIR::ClassType dest_type,\n                                 SemIR::InstId value_id,\n                                 ConversionTarget target,\n                                 bool is_partial = false) -> SemIR::InstId {\n  PendingBlock target_block(&context);\n  auto& dest_class_info = context.classes().Get(dest_type.class_id);\n  CARBON_CHECK(is_partial ||\n               dest_class_info.inheritance_kind != SemIR::Class::Abstract);\n  auto object_repr_id =\n      dest_class_info.GetObjectRepr(context.sem_ir(), dest_type.specific_id);\n  if (object_repr_id == SemIR::ErrorInst::TypeId) {\n    return SemIR::ErrorInst::InstId;\n  }\n  if (context.types().Is<SemIR::CustomLayoutType>(object_repr_id)) {\n    // Builtin conversion does not apply.\n    return value_id;\n  }\n  auto dest_struct_type =\n      context.types().GetAs<SemIR::StructType>(object_repr_id);\n\n  // If we're trying to create a class value, form temporary storage to hold the\n  // initializer.\n  if (!target.is_initializer()) {\n    target.kind = ConversionTarget::Initializing;\n    target.storage_access_block = &target_block;\n    target.storage_id = target_block.AddInst<SemIR::TemporaryStorage>(\n        SemIR::LocId(value_id), {.type_id = target.type_id});\n  }\n\n  return ConvertStructToStructOrClass<SemIR::ClassElementAccess>(\n      context, src_type, dest_struct_type, value_id, target,\n      is_partial ? nullptr : &dest_type);\n}\n\n// An inheritance path is a sequence of `BaseDecl`s and corresponding base types\n// in order from derived to base.\nusing InheritancePath =\n    llvm::SmallVector<std::pair<SemIR::InstId, SemIR::TypeId>>;\n\n// Computes the inheritance path from class `derived_id` to class `base_id`.\n// Returns nullopt if `derived_id` is not a class derived from `base_id`.\nstatic auto ComputeInheritancePath(Context& context, SemIR::LocId loc_id,\n                                   SemIR::TypeId derived_id,\n                                   SemIR::TypeId base_id)\n    -> std::optional<InheritancePath> {\n  // We intend for NRVO to be applied to `result`. All `return` statements in\n  // this function should `return result;`.\n  std::optional<InheritancePath> result(std::in_place);\n  if (!TryToCompleteType(context, derived_id, loc_id)) {\n    // TODO: Should we give an error here? If we don't, and there is an\n    // inheritance path when the class is defined, we may have a coherence\n    // problem.\n    result = std::nullopt;\n    return result;\n  }\n  while (derived_id != base_id) {\n    auto derived_class_type =\n        context.types().TryGetAs<SemIR::ClassType>(derived_id);\n    if (!derived_class_type) {\n      result = std::nullopt;\n      break;\n    }\n    auto& derived_class = context.classes().Get(derived_class_type->class_id);\n    auto base_type_id = derived_class.GetBaseType(\n        context.sem_ir(), derived_class_type->specific_id);\n    if (!base_type_id.has_value()) {\n      result = std::nullopt;\n      break;\n    }\n    result->push_back({derived_class.base_id, base_type_id});\n    derived_id = base_type_id;\n  }\n  return result;\n}\n\n// Performs a conversion from a derived class value or reference to a base class\n// value or reference.\nstatic auto ConvertDerivedToBase(Context& context, SemIR::LocId loc_id,\n                                 SemIR::InstId value_id,\n                                 const InheritancePath& path) -> SemIR::InstId {\n  // Materialize a temporary if necessary.\n  value_id = ConvertToValueOrRefExpr(context, value_id);\n\n  // Preserve type qualifiers.\n  auto quals = context.types()\n                   .GetUnqualifiedTypeAndQualifiers(\n                       context.insts().Get(value_id).type_id())\n                   .second;\n\n  // Add a series of `.base` accesses.\n  for (auto [base_id, base_type_id] : path) {\n    auto base_decl = context.insts().GetAs<SemIR::BaseDecl>(base_id);\n    value_id = AddInst<SemIR::ClassElementAccess>(\n        context, loc_id,\n        {.type_id = GetQualifiedType(context, base_type_id, quals),\n         .base_id = value_id,\n         .index = base_decl.index});\n  }\n  return value_id;\n}\n\n// Performs a conversion from a derived class pointer to a base class pointer.\nstatic auto ConvertDerivedPointerToBasePointer(\n    Context& context, SemIR::LocId loc_id, SemIR::PointerType src_ptr_type,\n    SemIR::TypeId dest_ptr_type_id, SemIR::InstId ptr_id,\n    const InheritancePath& path) -> SemIR::InstId {\n  auto pointee_type_id =\n      context.types().GetTypeIdForTypeInstId(src_ptr_type.pointee_id);\n\n  // Form `*p`.\n  ptr_id = ConvertToValueExpr(context, ptr_id);\n  auto ref_id = AddInst<SemIR::Deref>(\n      context, loc_id, {.type_id = pointee_type_id, .pointer_id = ptr_id});\n\n  // Convert as a reference expression.\n  ref_id = ConvertDerivedToBase(context, loc_id, ref_id, path);\n\n  // Take the address.\n  return AddInst<SemIR::AddrOf>(\n      context, loc_id, {.type_id = dest_ptr_type_id, .lvalue_id = ref_id});\n}\n\n// Returns whether `category` is a valid expression category to produce as a\n// result of a conversion with kind `target_kind`.\nstatic auto IsValidExprCategoryForConversionTarget(\n    SemIR::ExprCategory category, ConversionTarget::Kind target_kind) -> bool {\n  switch (target_kind) {\n    case ConversionTarget::Value:\n      return category == SemIR::ExprCategory::Value;\n    case ConversionTarget::ValueOrRef:\n      return category == SemIR::ExprCategory::Value ||\n             category == SemIR::ExprCategory::DurableRef ||\n             category == SemIR::ExprCategory::EphemeralRef;\n    case ConversionTarget::Discarded:\n      return category == SemIR::ExprCategory::Value ||\n             category == SemIR::ExprCategory::DurableRef ||\n             category == SemIR::ExprCategory::EphemeralRef ||\n             category == SemIR::ExprCategory::ReprInitializing ||\n             category == SemIR::ExprCategory::InPlaceInitializing;\n    case ConversionTarget::RefParam:\n    case ConversionTarget::UnmarkedRefParam:\n      return category == SemIR::ExprCategory::DurableRef ||\n             category == SemIR::ExprCategory::EphemeralRef;\n    case ConversionTarget::DurableRef:\n      return category == SemIR::ExprCategory::DurableRef;\n    case ConversionTarget::CppThunkRef:\n      return category == SemIR::ExprCategory::EphemeralRef;\n    case ConversionTarget::NoOp:\n    case ConversionTarget::ExplicitAs:\n    case ConversionTarget::ExplicitUnsafeAs:\n      return true;\n    case ConversionTarget::InPlaceInitializing:\n      return category == SemIR::ExprCategory::InPlaceInitializing;\n    case ConversionTarget::Initializing:\n      return category == SemIR::ExprCategory::ReprInitializing;\n  }\n}\n\n// Determines whether the initialization representation of the type is a copy of\n// the value representation.\nstatic auto InitReprIsCopyOfValueRepr(const SemIR::File& sem_ir,\n                                      SemIR::TypeId type_id) -> bool {\n  // The initializing representation is a copy of the value representation if\n  // they're both copies of the object representation.\n  return SemIR::InitRepr::ForType(sem_ir, type_id).IsCopyOfObjectRepr() &&\n         SemIR::ValueRepr::ForType(sem_ir, type_id)\n             .IsCopyOfObjectRepr(sem_ir, type_id);\n}\n\n// Determines whether we can pull a value directly out of an initializing\n// expression of type `type_id` to initialize a target of type `type_id` and\n// kind `target_kind`.\nstatic auto CanUseValueOfInitializer(const SemIR::File& sem_ir,\n                                     SemIR::TypeId type_id,\n                                     ConversionTarget::Kind target_kind)\n    -> bool {\n  if (!IsValidExprCategoryForConversionTarget(SemIR::ExprCategory::Value,\n                                              target_kind)) {\n    // We don't want a value expression.\n    return false;\n  }\n\n  // We can pull a value out of an initializing expression if it holds one.\n  return InitReprIsCopyOfValueRepr(sem_ir, type_id);\n}\n\n// Determine whether the given set of qualifiers can be added by a conversion\n// of an expression of the given category.\nstatic auto CanAddQualifiers(SemIR::TypeQualifiers quals,\n                             SemIR::ExprCategory cat) -> bool {\n  if (quals.HasAnyOf(SemIR::TypeQualifiers::MaybeUnformed) &&\n      !SemIR::IsRefCategory(cat)) {\n    // `MaybeUnformed(T)` may have a different value representation or\n    // initializing representation from `T`, so only allow it to be added for a\n    // reference expression.\n    // TODO: We should allow converting an initializing expression of type `T`\n    // to `MaybeUnformed(T)`. `PerformBuiltinConversion` will need to generate\n    // an `InPlaceInit` instruction when needed.\n    // NOLINTNEXTLINE(readability-simplify-boolean-expr)\n    return false;\n  }\n\n  // `const` and `partial` can always be added.\n  return true;\n}\n\n// Determine whether the given set of qualifiers can be removed by a conversion\n// of an expression of the given category.\nstatic auto CanRemoveQualifiers(SemIR::TypeQualifiers quals,\n                                SemIR::ExprCategory cat,\n                                ConversionTarget::Kind kind) -> bool {\n  bool allow_unsafe = kind == ConversionTarget::ExplicitUnsafeAs;\n\n  if (quals.HasAnyOf(SemIR::TypeQualifiers::Const) && !allow_unsafe &&\n      SemIR::IsRefCategory(cat) &&\n      IsValidExprCategoryForConversionTarget(cat, kind)) {\n    // Removing `const` is an unsafe conversion for a reference expression. But\n    // it's OK if we will be converting to a different category as part of this\n    // overall conversion anyway.\n    return false;\n  }\n\n  if (quals.HasAnyOf(SemIR::TypeQualifiers::Partial) && !allow_unsafe &&\n      !SemIR::IsInitializerCategory(cat)) {\n    // Removing `partial` is an unsafe conversion for a non-initializing\n    // expression. But it's OK for an initializing expression because we will\n    // initialize the vptr as part of the conversion.\n    return false;\n  }\n\n  if (quals.HasAnyOf(SemIR::TypeQualifiers::MaybeUnformed) &&\n      (!allow_unsafe || SemIR::IsInitializerCategory(cat))) {\n    // As an unsafe conversion, `MaybeUnformed` can be removed from a value or\n    // reference expression.\n    return false;\n  }\n\n  return true;\n}\n\nstatic auto DiagnoseConversionFailureToConstraintValue(\n    Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,\n    SemIR::TypeId target_type_id) -> void {\n  CARBON_CHECK(context.types().IsFacetType(target_type_id));\n\n  // If the source type is/has a facet value (converted with `as type` or\n  // otherwise), then we can include its `FacetType` in the diagnostic to help\n  // explain what interfaces the source type implements.\n  auto const_expr_id = GetCanonicalFacetOrTypeValue(context, expr_id);\n  auto const_expr_type_id = context.insts().Get(const_expr_id).type_id();\n\n  if (context.types().Is<SemIR::FacetType>(const_expr_type_id)) {\n    CARBON_DIAGNOSTIC(ConversionFailureFacetToFacet, Error,\n                      \"cannot convert type {0} that implements {1} into type \"\n                      \"implementing {2}\",\n                      InstIdAsType, SemIR::TypeId, SemIR::TypeId);\n    context.emitter().Emit(loc_id, ConversionFailureFacetToFacet, expr_id,\n                           const_expr_type_id, target_type_id);\n  } else {\n    CARBON_DIAGNOSTIC(ConversionFailureTypeToFacet, Error,\n                      \"cannot convert type {0} into type implementing {1}\",\n                      InstIdAsType, SemIR::TypeId);\n    context.emitter().Emit(loc_id, ConversionFailureTypeToFacet, expr_id,\n                           target_type_id);\n  }\n}\n\nstatic auto PerformBuiltinConversion(Context& context, SemIR::LocId loc_id,\n                                     SemIR::InstId value_id,\n                                     ConversionTarget target) -> SemIR::InstId {\n  auto& sem_ir = context.sem_ir();\n  auto value = sem_ir.insts().Get(value_id);\n  auto value_type_id = value.type_id();\n  auto target_type_inst = sem_ir.types().GetAsInst(target.type_id);\n\n  // Various forms of implicit conversion are supported as builtin conversions,\n  // either in addition to or instead of `impl`s of `ImplicitAs` in the Carbon\n  // prelude. There are a few reasons we need to perform some of these\n  // conversions as builtins:\n  //\n  // 1) Conversions from struct and tuple *literals* have special rules that\n  //    cannot be implemented by invoking `ImplicitAs`. Specifically, we must\n  //    recurse into the elements of the literal before performing\n  //    initialization in order to avoid unnecessary conversions between\n  //    expression categories that would be performed by `ImplicitAs.Convert`.\n  // 2) (Not implemented yet) Conversion of a facet to a facet type depends on\n  //    the value of the facet, not only its type, and therefore cannot be\n  //    modeled by `ImplicitAs`.\n  // 3) Some of these conversions are used while checking the library\n  //    definition of `ImplicitAs` itself or implementations of it.\n  //\n  // We also expect to see better performance by avoiding an `impl` lookup for\n  // common conversions.\n  //\n  // TODO: We should provide a debugging flag to turn off as many of these\n  // builtin conversions as we can so that we can test that they do the same\n  // thing as the library implementations.\n  //\n  // The builtin conversions that correspond to `impl`s in the library all\n  // correspond to `final impl`s, so we don't need to worry about `ImplicitAs`\n  // being specialized in any of these cases.\n\n  // If the value is already of the right kind and expression category, there's\n  // nothing to do. Performing a conversion would decompose and rebuild tuples\n  // and structs, so it's important that we bail out early in this case.\n  if (value_type_id == target.type_id) {\n    auto value_cat = SemIR::GetExprCategory(sem_ir, value_id);\n    if (IsValidExprCategoryForConversionTarget(value_cat, target.kind)) {\n      return value_id;\n    }\n\n    // If the source is an initializing expression, we may be able to pull a\n    // value right out of it.\n    if (value_cat == SemIR::ExprCategory::ReprInitializing &&\n        CanUseValueOfInitializer(sem_ir, value_type_id, target.kind)) {\n      return AddInst<SemIR::ValueOfInitializer>(\n          context, loc_id, {.type_id = value_type_id, .init_id = value_id});\n    }\n\n    // Materialization is handled as part of the enclosing conversion.\n    if (SemIR::IsInitializerCategory(value_cat) &&\n        target.kind == ConversionTarget::ValueOrRef) {\n      return value_id;\n    }\n\n    // Final destination store is handled as part of the enclosing conversion.\n    if (value_cat == SemIR::ExprCategory::ReprInitializing &&\n        target.kind == ConversionTarget::InPlaceInitializing) {\n      return value_id;\n    }\n\n    // PerformBuiltinConversion converts each part of a tuple or struct, even\n    // when the types are the same. This is not done for classes since they have\n    // to define their conversions as part of their api.\n    //\n    // If a class adapts a tuple or struct, we convert each of its parts when\n    // there's no other conversion going on (the source and target types are the\n    // same). To do so, we have to insert a conversion of the value up to the\n    // foundation and back down, and a conversion of the initializing object if\n    // there is one.\n    //\n    // Implementation note: We do the conversion through a call to\n    // PerformBuiltinConversion() call rather than a Convert() call to avoid\n    // extraneous `converted` semir instructions on the adapted types, and as a\n    // shortcut to doing the explicit calls to walk the parts of the\n    // tuple/struct which happens inside PerformBuiltinConversion().\n    if (auto foundation_type_id =\n            context.types().GetTransitiveAdaptedType(value_type_id);\n        foundation_type_id != value_type_id &&\n        context.types().IsOneOf<SemIR::StructType, SemIR::TupleType>(\n            foundation_type_id)) {\n      auto foundation_value_id = AddInst<SemIR::AsCompatible>(\n          context, loc_id,\n          {.type_id = foundation_type_id, .source_id = value_id});\n\n      auto foundation_init_id = target.storage_id;\n      if (foundation_init_id != SemIR::InstId::None) {\n        foundation_init_id =\n            target.storage_access_block->AddInst<SemIR::AsCompatible>(\n                loc_id, {.type_id = foundation_type_id,\n                         .source_id = target.storage_id});\n      }\n\n      {\n        // While the types are the same, the conversion can still fail if it\n        // performs a copy while converting the value to another category, and\n        // the type (or some part of it) is not copyable.\n        Diagnostics::AnnotationScope annotate_diagnostics(\n            &context.emitter(), [&](auto& builder) {\n              CARBON_DIAGNOSTIC(InCopy, Note, \"in copy of {0}\", TypeOfInstId);\n              builder.Note(value_id, InCopy, value_id);\n            });\n\n        foundation_value_id = PerformBuiltinConversion(\n            context, loc_id, foundation_value_id,\n            {.kind = target.kind,\n             .type_id = foundation_type_id,\n             .storage_id = foundation_init_id,\n             .storage_access_block = target.storage_access_block,\n             .diagnose = target.diagnose});\n        if (foundation_value_id == SemIR::ErrorInst::InstId) {\n          return SemIR::ErrorInst::InstId;\n        }\n      }\n\n      return AddInst<SemIR::AsCompatible>(\n          context, loc_id,\n          {.type_id = target.type_id, .source_id = foundation_value_id});\n    }\n  }\n\n  // T implicitly converts to U if T and U are the same ignoring qualifiers, and\n  // we're allowed to remove / add any qualifiers that differ. Similarly, T\n  // explicitly converts to U if T is compatible with U, and we're allowed to\n  // remove / add any qualifiers that differ.\n  if (target.type_id != value_type_id) {\n    auto [target_foundation_id, target_quals] =\n        target.is_explicit_as()\n            ? context.types().GetTransitiveUnqualifiedAdaptedType(\n                  target.type_id)\n            : context.types().GetUnqualifiedTypeAndQualifiers(target.type_id);\n    auto [value_foundation_id, value_quals] =\n        target.is_explicit_as()\n            ? context.types().GetTransitiveUnqualifiedAdaptedType(value_type_id)\n            : context.types().GetUnqualifiedTypeAndQualifiers(value_type_id);\n    if (target_foundation_id == value_foundation_id) {\n      auto category = SemIR::GetExprCategory(context.sem_ir(), value_id);\n      auto added_quals = target_quals & ~value_quals;\n      auto removed_quals = value_quals & ~target_quals;\n      if (CanAddQualifiers(added_quals, category) &&\n          CanRemoveQualifiers(removed_quals, category, target.kind)) {\n        // For a struct or tuple literal, perform a category conversion if\n        // necessary.\n        if (category == SemIR::ExprCategory::Mixed) {\n          value_id = PerformBuiltinConversion(context, loc_id, value_id,\n                                              {.kind = ConversionTarget::Value,\n                                               .type_id = value_type_id,\n                                               .diagnose = target.diagnose});\n        }\n\n        // `MaybeUnformed(T)` might have a pointer value representation when `T`\n        // does not, so convert as needed when removing `MaybeUnformed`.\n        bool need_value_binding = false;\n        if ((removed_quals & SemIR::TypeQualifiers::MaybeUnformed) !=\n                SemIR::TypeQualifiers::None &&\n            category == SemIR::ExprCategory::Value) {\n          auto value_rep =\n              SemIR::ValueRepr::ForType(context.sem_ir(), value_type_id);\n          auto unformed_value_rep =\n              SemIR::ValueRepr::ForType(context.sem_ir(), target.type_id);\n          if (value_rep.kind != unformed_value_rep.kind) {\n            CARBON_CHECK(unformed_value_rep.kind == SemIR::ValueRepr::Pointer);\n            value_id = AddInst<SemIR::ValueAsRef>(\n                context, loc_id,\n                {.type_id = value_type_id, .value_id = value_id});\n            need_value_binding = true;\n          }\n        }\n\n        if ((removed_quals & SemIR::TypeQualifiers::Partial) !=\n                SemIR::TypeQualifiers::None &&\n            SemIR::IsInitializerCategory(category)) {\n          auto unqual_target_type_id =\n              context.types().GetUnqualifiedType(target.type_id);\n          if (auto target_class_type =\n                  context.types().TryGetAs<SemIR::ClassType>(\n                      unqual_target_type_id)) {\n            value_id = ConvertPartialInitializerToNonPartial(\n                context, target, *target_class_type, value_id);\n          }\n        }\n\n        value_id = AddInst<SemIR::AsCompatible>(\n            context, loc_id,\n            {.type_id = target.type_id, .source_id = value_id});\n\n        if (need_value_binding) {\n          value_id = AddInst<SemIR::AcquireValue>(\n              context, loc_id,\n              {.type_id = target.type_id, .value_id = value_id});\n        }\n        return value_id;\n      } else {\n        // TODO: Produce a custom diagnostic explaining that we can't perform\n        // this conversion due to the change in qualifiers and/or the expression\n        // category.\n      }\n    }\n  }\n\n  // A tuple (T1, T2, ..., Tn) converts to (U1, U2, ..., Un) if each Ti\n  // converts to Ui.\n  if (auto target_tuple_type = target_type_inst.TryAs<SemIR::TupleType>()) {\n    if (auto src_tuple_type =\n            sem_ir.types().TryGetAs<SemIR::TupleType>(value_type_id)) {\n      return ConvertTupleToTuple(context, *src_tuple_type, *target_tuple_type,\n                                 value_id, target);\n    }\n  }\n\n  // A struct {.f_1: T_1, .f_2: T_2, ..., .f_n: T_n} converts to\n  // {.f_p(1): U_p(1), .f_p(2): U_p(2), ..., .f_p(n): U_p(n)} if\n  // (p(1), ..., p(n)) is a permutation of (1, ..., n) and each Ti converts\n  // to Ui.\n  if (auto target_struct_type = target_type_inst.TryAs<SemIR::StructType>()) {\n    if (auto src_struct_type =\n            sem_ir.types().TryGetAs<SemIR::StructType>(value_type_id)) {\n      return ConvertStructToStruct(context, *src_struct_type,\n                                   *target_struct_type, value_id, target);\n    }\n  }\n\n  // No other conversions apply when the source and destination types are the\n  // same.\n  if (value_type_id == target.type_id) {\n    return value_id;\n  }\n\n  // A tuple (T1, T2, ..., Tn) converts to array(T, n) if each Ti converts to T.\n  if (auto target_array_type = target_type_inst.TryAs<SemIR::ArrayType>()) {\n    if (auto src_tuple_type =\n            sem_ir.types().TryGetAs<SemIR::TupleType>(value_type_id)) {\n      return ConvertTupleToArray(context, *src_tuple_type, *target_array_type,\n                                 value_id, target);\n    }\n  }\n\n  // Split the qualifiers off the target type.\n  // TODO: Most conversions should probably be looking at the unqualified target\n  // type.\n  auto [target_unqual_type_id, target_quals] =\n      context.types().GetUnqualifiedTypeAndQualifiers(target.type_id);\n  auto target_unqual_type_inst =\n      sem_ir.types().GetAsInst(target_unqual_type_id);\n\n  // A struct {.f_1: T_1, .f_2: T_2, ..., .f_n: T_n} converts to a class type\n  // if it converts to the struct type that is the class's representation type\n  // (a struct with the same fields as the class, plus a base field where\n  // relevant).\n  if (auto target_class_type =\n          target_unqual_type_inst.TryAs<SemIR::ClassType>()) {\n    if (auto src_struct_type =\n            sem_ir.types().TryGetAs<SemIR::StructType>(value_type_id)) {\n      if (!context.classes()\n               .Get(target_class_type->class_id)\n               .adapt_id.has_value()) {\n        return ConvertStructToClass(\n            context, *src_struct_type, *target_class_type, value_id, target,\n            target_quals.HasAnyOf(SemIR::TypeQualifiers::Partial));\n      }\n    }\n\n    // An expression of type T converts to U if T is a class derived from U.\n    //\n    // TODO: Combine this with the qualifiers and adapter conversion logic above\n    // to allow qualifiers and inheritance conversions to be performed together.\n    if (auto path = ComputeInheritancePath(context, loc_id, value_type_id,\n                                           target.type_id);\n        path && !path->empty()) {\n      return ConvertDerivedToBase(context, loc_id, value_id, *path);\n    }\n  }\n\n  // A pointer T* converts to [qualified] U* if T is the same as U, or is a\n  // class derived from U.\n  if (auto target_pointer_type = target_type_inst.TryAs<SemIR::PointerType>()) {\n    if (auto src_pointer_type =\n            sem_ir.types().TryGetAs<SemIR::PointerType>(value_type_id)) {\n      auto target_pointee_id = context.types().GetTypeIdForTypeInstId(\n          target_pointer_type->pointee_id);\n      auto src_pointee_id =\n          context.types().GetTypeIdForTypeInstId(src_pointer_type->pointee_id);\n      // Try to complete the pointee types so that we can walk through adapters\n      // to their adapted types.\n      TryToCompleteType(context, target_pointee_id, loc_id);\n      TryToCompleteType(context, src_pointee_id, loc_id);\n      auto [unqual_target_pointee_type_id, target_quals] =\n          sem_ir.types().GetTransitiveUnqualifiedAdaptedType(target_pointee_id);\n      auto [unqual_src_pointee_type_id, src_quals] =\n          sem_ir.types().GetTransitiveUnqualifiedAdaptedType(src_pointee_id);\n\n      // If the qualifiers are incompatible, we can't perform a conversion,\n      // except with `unsafe as`.\n      if ((src_quals & ~target_quals) != SemIR::TypeQualifiers::None &&\n          target.kind != ConversionTarget::ExplicitUnsafeAs) {\n        // TODO: Consider producing a custom diagnostic here for a cast that\n        // discards constness.\n        return value_id;\n      }\n\n      if (unqual_target_pointee_type_id != unqual_src_pointee_type_id) {\n        // If there's an inheritance path from target to source, this is a\n        // derived to base conversion.\n        if (auto path = ComputeInheritancePath(context, loc_id,\n                                               unqual_src_pointee_type_id,\n                                               unqual_target_pointee_type_id);\n            path && !path->empty()) {\n          value_id = ConvertDerivedPointerToBasePointer(\n              context, loc_id, *src_pointer_type, target.type_id, value_id,\n              *path);\n        } else {\n          // No conversion was possible.\n          return value_id;\n        }\n      }\n\n      // Perform a compatible conversion to add any new qualifiers.\n      if (src_quals != target_quals) {\n        return AddInst<SemIR::AsCompatible>(\n            context, loc_id,\n            {.type_id = target.type_id, .source_id = value_id});\n      }\n      return value_id;\n    }\n  }\n\n  if (sem_ir.types().IsFacetType(target.type_id)) {\n    auto type_value_id = SemIR::TypeInstId::None;\n\n    // A tuple of types converts to type `type`.\n    if (sem_ir.types().Is<SemIR::TupleType>(value_type_id)) {\n      type_value_id =\n          ConvertTupleToType(context, loc_id, value_id, value_type_id, target);\n    }\n\n    // `{}` converts to `{} as type`.\n    if (auto struct_type =\n            sem_ir.types().TryGetAs<SemIR::StructType>(value_type_id)) {\n      if (struct_type->fields_id == SemIR::StructTypeFieldsId::Empty) {\n        type_value_id = sem_ir.types().GetTypeInstId(value_type_id);\n      }\n    }\n\n    if (type_value_id != SemIR::InstId::None) {\n      if (sem_ir.types().Is<SemIR::FacetType>(target.type_id)) {\n        // Use the converted `TypeType` value for converting to a facet.\n        value_id = type_value_id;\n        value_type_id = SemIR::TypeType::TypeId;\n      } else {\n        // We wanted a `TypeType`, and we've done that.\n        return type_value_id;\n      }\n    }\n  }\n\n  // FacetType converts to Type by wrapping the facet value in\n  // FacetAccessType.\n  if (target.type_id == SemIR::TypeType::TypeId &&\n      sem_ir.types().Is<SemIR::FacetType>(value_type_id)) {\n    return AddInst<SemIR::FacetAccessType>(\n        context, loc_id,\n        {.type_id = target.type_id, .facet_value_inst_id = value_id});\n  }\n\n  // Type values can convert to facet values, and facet values can convert to\n  // other facet values, as long as they satisfy the required interfaces of the\n  // target `FacetType`.\n  if (sem_ir.types().Is<SemIR::FacetType>(target.type_id) &&\n      sem_ir.types().IsOneOf<SemIR::TypeType, SemIR::FacetType>(\n          value_type_id)) {\n    // TODO: Runtime facet values should be allowed to convert based on their\n    // FacetTypes, but we assume constant values for impl lookup at the moment.\n    if (!context.constant_values().Get(value_id).is_constant()) {\n      context.TODO(loc_id, \"conversion of runtime facet value\");\n      return SemIR::ErrorInst::InstId;\n    }\n\n    // Get the canonical type for which we want to attach a new set of witnesses\n    // to match the requirements of the target FacetType.\n    auto type_inst_id = SemIR::TypeInstId::None;\n    if (sem_ir.types().Is<SemIR::FacetType>(value_type_id)) {\n      type_inst_id = AddTypeInst<SemIR::FacetAccessType>(\n          context, loc_id,\n          {.type_id = SemIR::TypeType::TypeId,\n           .facet_value_inst_id = value_id});\n    } else {\n      type_inst_id = context.types().GetAsTypeInstId(value_id);\n\n      // Shortcut for lossless round trips through a FacetAccessType (which\n      // evaluates to SymbolicBindingType when wrapping a symbolic binding) when\n      // converting back to the type of the original symbolic binding facet\n      // value.\n      //\n      // In the case where the FacetAccessType wraps a SymbolicBinding with the\n      // exact facet type that we are converting to, the resulting FacetValue\n      // would evaluate back to the original SymbolicBinding as its canonical\n      // form. We can skip past the whole impl lookup step then and do that\n      // here.\n      //\n      // TODO: This instruction is going to become a `SymbolicBindingType`, so\n      // we'll need to handle that instead.\n      auto facet_value_inst_id =\n          GetCanonicalFacetOrTypeValue(context, type_inst_id);\n      if (sem_ir.insts().Get(facet_value_inst_id).type_id() == target.type_id) {\n        return facet_value_inst_id;\n      }\n    }\n\n    // Conversion from a facet value (which has type `FacetType`) or a type\n    // value (which has type `TypeType`) to a facet value. We can do this if the\n    // type satisfies the requirements of the target `FacetType`, as determined\n    // by finding impl witnesses for the target FacetType.\n    auto lookup_result = LookupImplWitness(\n        context, loc_id, sem_ir.constant_values().Get(type_inst_id),\n        sem_ir.types().GetConstantId(target.type_id));\n    if (lookup_result.has_value()) {\n      if (lookup_result.has_error_value()) {\n        return SemIR::ErrorInst::InstId;\n      } else {\n        // Note that `FacetValue`'s type is the same `FacetType` that was used\n        // to construct the set of witnesses, ie. the query to\n        // `LookupImplWitness()`. This ensures that the witnesses are in the\n        // same order as the `required_impls()` in the `IdentifiedFacetType` of\n        // the `FacetValue`'s type.\n        return AddInst<SemIR::FacetValue>(\n            context, loc_id,\n            {.type_id = target.type_id,\n             .type_inst_id = type_inst_id,\n             .witnesses_block_id = lookup_result.inst_block_id()});\n      }\n    } else {\n      // If impl lookup fails, don't keep looking for another way to convert.\n      // See https://github.com/carbon-language/carbon-lang/issues/5122.\n      // TODO: Pass this function into `LookupImplWitness` so it can construct\n      // the error add notes explaining failure.\n      if (target.diagnose) {\n        DiagnoseConversionFailureToConstraintValue(context, loc_id, value_id,\n                                                   target.type_id);\n      }\n      return SemIR::ErrorInst::InstId;\n    }\n  }\n\n  // No builtin conversion applies.\n  return value_id;\n}\n\n// Determine whether this is a C++ enum type.\n// TODO: This should be removed once we can properly add a `Copy` impl for C++\n// enum types.\nstatic auto IsCppEnum(Context& context, SemIR::TypeId type_id) -> bool {\n  auto class_type = context.types().TryGetAs<SemIR::ClassType>(type_id);\n  if (!class_type) {\n    return false;\n  }\n\n  // A C++-imported class type that is an adapter is an enum.\n  auto& class_info = context.classes().Get(class_type->class_id);\n  return class_info.adapt_id.has_value() &&\n         context.name_scopes().Get(class_info.scope_id).is_cpp_scope();\n}\n\n// Given a value expression, form a corresponding initializer that copies from\n// that value to the specified target, if it is possible to do so.\nstatic auto PerformCopy(Context& context, SemIR::InstId expr_id,\n                        const ConversionTarget& target) -> SemIR::InstId {\n  // TODO: We don't have a mechanism yet to generate `Copy` impls for each enum\n  // type imported from C++. For now we fake it by providing a direct copy.\n  auto type_id = context.insts().Get(expr_id).type_id();\n  if (IsCppEnum(context, type_id)) {\n    return expr_id;\n  }\n\n  auto copy_id = BuildUnaryOperator(\n      context, SemIR::LocId(expr_id), {.interface_name = CoreIdentifier::Copy},\n      expr_id, target.diagnose, [&](auto& builder) {\n        CARBON_DIAGNOSTIC(CopyOfUncopyableType, Context,\n                          \"cannot copy value of type {0}\", TypeOfInstId);\n        builder.Context(expr_id, CopyOfUncopyableType, expr_id);\n      });\n  return copy_id;\n}\n\n// Convert a value expression so that it can be used to initialize a C++ thunk\n// parameter.\nstatic auto ConvertValueForCppThunkRef(Context& context, SemIR::InstId expr_id)\n    -> SemIR::InstId {\n  auto expr = context.insts().Get(expr_id);\n\n  // If the expression has a pointer value representation, extract that and use\n  // it directly.\n  if (SemIR::ValueRepr::ForType(context.sem_ir(), expr.type_id()).kind ==\n      SemIR::ValueRepr::Pointer) {\n    return AddInst<SemIR::ValueAsRef>(\n        context, SemIR::LocId(expr_id),\n        {.type_id = expr.type_id(), .value_id = expr_id});\n  }\n\n  // Otherwise, we need a temporary to pass as the thunk argument. Create a copy\n  // and initialize a temporary from it.\n  auto temporary_id = AddInst<SemIR::TemporaryStorage>(\n      context, SemIR::LocId(expr_id), {.type_id = expr.type_id()});\n  expr_id = Initialize(context, SemIR::LocId(expr_id), temporary_id, expr_id);\n  return AddInstWithCleanup<SemIR::Temporary>(context, SemIR::LocId(expr_id),\n                                              {.type_id = expr.type_id(),\n                                               .storage_id = temporary_id,\n                                               .init_id = expr_id});\n}\n\n// Returns the Core interface name to use for a given kind of conversion.\nstatic auto GetConversionInterfaceName(ConversionTarget::Kind kind)\n    -> CoreIdentifier {\n  switch (kind) {\n    case ConversionTarget::ExplicitAs:\n      return CoreIdentifier::As;\n    case ConversionTarget::ExplicitUnsafeAs:\n      return CoreIdentifier::UnsafeAs;\n    default:\n      return CoreIdentifier::ImplicitAs;\n  }\n}\n\nauto PerformAction(Context& context, SemIR::LocId loc_id,\n                   SemIR::ConvertToValueAction action) -> SemIR::InstId {\n  return Convert(context, loc_id, action.inst_id,\n                 {.kind = ConversionTarget::Value,\n                  .type_id = context.types().GetTypeIdForTypeInstId(\n                      action.target_type_inst_id)});\n}\n\n// State machine for performing category conversions.\nclass CategoryConverter {\n public:\n  // Constructs a converter which converts an expression at the given location\n  // to the given conversion target.\n  CategoryConverter(Context& context, SemIR::LocId loc_id,\n                    ConversionTarget& target)\n      : context_(context),\n        sem_ir_(context.sem_ir()),\n        loc_id_(loc_id),\n        target_(target) {}\n\n  // Converts expr_id to the target specified in the constructor, and returns\n  // the converted inst.\n  auto Convert(SemIR::InstId expr_id) && -> SemIR::InstId {\n    auto category = SemIR::GetExprCategory(sem_ir_, expr_id);\n    while (true) {\n      if (expr_id == SemIR::ErrorInst::InstId) {\n        return expr_id;\n      }\n      CARBON_KIND_SWITCH(DoStep(expr_id, category)) {\n        case CARBON_KIND(NextStep next_step): {\n          CARBON_CHECK(next_step.expr_id != SemIR::InstId::None);\n          expr_id = next_step.expr_id;\n          category = next_step.category;\n          break;\n        }\n        case CARBON_KIND(Done done): {\n          return done.expr_id;\n        }\n      }\n    }\n  }\n\n private:\n  // State that indicates there's more work to be done. As a convenience,\n  // if expr_id is SemIR::ErrorInst::InstId, this is equivalent to\n  // Done{SemIR::ErrorInst::InstId}.\n  struct NextStep {\n    // The inst to convert.\n    SemIR::InstId expr_id;\n    // The category of expr_id.\n    SemIR::ExprCategory category;\n  };\n\n  // State that indicates we've finished category conversion.\n  struct Done {\n    // The result of the conversion.\n    SemIR::InstId expr_id;\n  };\n\n  using State = std::variant<NextStep, Done>;\n\n  // Performs the first step of converting `expr_id` with category `category`\n  // to the target specified in the constructor, and returns the state after\n  // that step.\n  auto DoStep(SemIR::InstId expr_id, SemIR::ExprCategory category) const\n      -> State;\n\n  Context& context_;\n  SemIR::File& sem_ir_;\n  SemIR::LocId loc_id_;\n  const ConversionTarget& target_;\n};\n\nauto CategoryConverter::DoStep(const SemIR::InstId expr_id,\n                               const SemIR::ExprCategory category) const\n    -> State {\n  CARBON_DCHECK(SemIR::GetExprCategory(sem_ir_, expr_id) == category ||\n                // TODO: Drop this special case once PerformCopy on C++ enums\n                // produces an initializing expression.\n                IsCppEnum(context_, target_.type_id));\n  switch (category) {\n    case SemIR::ExprCategory::NotExpr:\n    case SemIR::ExprCategory::Mixed:\n    case SemIR::ExprCategory::Pattern:\n      CARBON_FATAL(\"Unexpected expression {0} after builtin conversions\",\n                   sem_ir_.insts().Get(expr_id));\n\n    case SemIR::ExprCategory::Error:\n      return Done{SemIR::ErrorInst::InstId};\n\n    case SemIR::ExprCategory::Dependent:\n      context_.TODO(expr_id, \"Support symbolic expression forms\");\n      return Done{SemIR::ErrorInst::InstId};\n\n    case SemIR::ExprCategory::InPlaceInitializing:\n    case SemIR::ExprCategory::ReprInitializing:\n      if (target_.is_initializer()) {\n        // Overwrite the initializer's storage argument with the inst currently\n        // at target_.storage_id, if both are present and the storage argument\n        // hasn't already been set. However, we skip this if the type is a C++\n        // enum: in that case, we don't actually have an initializing\n        // expression, we're just pretending we do.\n        auto new_storage_id = target_.storage_id;\n        if (!IsCppEnum(context_, target_.type_id)) {\n          new_storage_id =\n              OverwriteTemporaryStorageArg(sem_ir_, expr_id, target_);\n        }\n\n        // If in-place initialization was requested, and it hasn't already\n        // happened, ensure it happens now.\n        if (target_.kind == ConversionTarget::InPlaceInitializing &&\n            category != SemIR::ExprCategory::InPlaceInitializing &&\n            SemIR::InitRepr::ForType(sem_ir_, target_.type_id)\n                .MightBeByCopy()) {\n          target_.storage_access_block->InsertHere();\n          return Done{AddInst<SemIR::InPlaceInit>(context_, loc_id_,\n                                                  {.type_id = target_.type_id,\n                                                   .src_id = expr_id,\n                                                   .dest_id = new_storage_id})};\n        }\n        return Done{expr_id};\n      }\n\n      if (target_.kind == ConversionTarget::Discarded) {\n        DiscardInitializer(context_, expr_id);\n        return Done{SemIR::InstId::None};\n      } else if (IsValidExprCategoryForConversionTarget(category,\n                                                        target_.kind)) {\n        return Done{expr_id};\n      } else {\n        // Commit to using a temporary for this initializing expression.\n        // TODO: Don't create a temporary if the initializing representation is\n        // already a value representation.\n        // TODO: If the target is DurableRef, materialize a VarStorage instead\n        // of a TemporaryStorage to lifetime-extend.\n        return NextStep{.expr_id = MaterializeTemporary(context_, expr_id),\n                        .category = SemIR::ExprCategory::EphemeralRef};\n      }\n\n    case SemIR::ExprCategory::RefTagged: {\n      auto tagged_expr_id =\n          sem_ir_.insts().GetAs<SemIR::RefTagExpr>(expr_id).expr_id;\n      auto tagged_expr_category =\n          SemIR::GetExprCategory(sem_ir_, tagged_expr_id);\n      if (target_.diagnose &&\n          tagged_expr_category != SemIR::ExprCategory::DurableRef) {\n        CARBON_DIAGNOSTIC(\n            RefTagNotDurableRef, Error,\n            \"expression tagged with `ref` is not a durable reference\");\n        context_.emitter().Emit(tagged_expr_id, RefTagNotDurableRef);\n      }\n\n      if (target_.kind == ConversionTarget::RefParam) {\n        return Done{expr_id};\n      }\n\n      // If the target isn't a reference parameter, ignore the `ref` tag.\n      // Unnecessary `ref` tags are diagnosed earlier.\n      return NextStep{.expr_id = tagged_expr_id,\n                      .category = tagged_expr_category};\n    }\n\n    case SemIR::ExprCategory::DurableRef:\n      if (target_.kind == ConversionTarget::DurableRef ||\n          target_.kind == ConversionTarget::UnmarkedRefParam) {\n        return Done{expr_id};\n      }\n      if (target_.kind == ConversionTarget::RefParam) {\n        if (target_.diagnose) {\n          CARBON_DIAGNOSTIC(\n              RefParamNoRefTag, Error,\n              \"argument to `ref` parameter not marked with `ref`\");\n          context_.emitter().Emit(expr_id, RefParamNoRefTag);\n        }\n        return Done{expr_id};\n      }\n      [[fallthrough]];\n\n    case SemIR::ExprCategory::EphemeralRef:\n      // If a reference expression is an acceptable result, we're done.\n      if (target_.kind == ConversionTarget::ValueOrRef ||\n          target_.kind == ConversionTarget::Discarded ||\n          target_.kind == ConversionTarget::CppThunkRef ||\n          target_.kind == ConversionTarget::RefParam ||\n          target_.kind == ConversionTarget::UnmarkedRefParam) {\n        return Done{expr_id};\n      }\n\n      // If we have a reference and don't want one, form a value binding.\n      // TODO: Support types with custom value representations.\n      return NextStep{.expr_id = AddInst<SemIR::AcquireValue>(\n                          context_, SemIR::LocId(expr_id),\n                          {.type_id = target_.type_id, .value_id = expr_id}),\n                      .category = SemIR::ExprCategory::Value};\n\n    case SemIR::ExprCategory::Value:\n      if (target_.kind == ConversionTarget::DurableRef) {\n        if (target_.diagnose) {\n          CARBON_DIAGNOSTIC(ConversionFailureNonRefToRef, Error,\n                            \"cannot bind durable reference to non-reference \"\n                            \"value of type {0}\",\n                            SemIR::TypeId);\n          context_.emitter().Emit(loc_id_, ConversionFailureNonRefToRef,\n                                  target_.type_id);\n        }\n        return Done{SemIR::ErrorInst::InstId};\n      }\n      if (target_.kind == ConversionTarget::RefParam ||\n          target_.kind == ConversionTarget::UnmarkedRefParam) {\n        if (target_.diagnose) {\n          CARBON_DIAGNOSTIC(ValueForRefParam, Error,\n                            \"value expression passed to reference parameter\");\n          context_.emitter().Emit(loc_id_, ValueForRefParam);\n        }\n        return Done{SemIR::ErrorInst::InstId};\n      }\n\n      // When initializing from a value, perform a copy.\n      if (target_.is_initializer()) {\n        auto copy_id = PerformCopy(context_, expr_id, target_);\n        if (copy_id == SemIR::ErrorInst::InstId) {\n          return Done{SemIR::ErrorInst::InstId};\n        }\n        // Deal with special-case category behavior of PerformCopy.\n        switch (SemIR::GetExprCategory(sem_ir_, copy_id)) {\n          case SemIR::ExprCategory::Value:\n            // As a temporary workaround, PerformCopy on a C++ enum currently\n            // returns the unchanged value, but we treat it as an initializing\n            // expression.\n            // TODO: Drop this case once it's no longer applicable.\n            CARBON_CHECK(IsCppEnum(context_, target_.type_id));\n            [[fallthrough]];\n          case SemIR::ExprCategory::ReprInitializing:\n            // The common case: PerformCopy produces an initializing expression.\n            return NextStep{.expr_id = copy_id,\n                            .category = SemIR::ExprCategory::ReprInitializing};\n          case SemIR::ExprCategory::InPlaceInitializing:\n            // A C++ copy operation produces an ephemeral entire reference.\n            return NextStep{\n                .expr_id = copy_id,\n                .category = SemIR::ExprCategory::InPlaceInitializing};\n          default:\n            CARBON_FATAL(\"Unexpected category of copy operation {0}\", category);\n        }\n      }\n\n      // When initializing a C++ thunk parameter, form a reference, creating a\n      // temporary if needed.\n      if (target_.kind == ConversionTarget::CppThunkRef) {\n        return Done{ConvertValueForCppThunkRef(context_, expr_id)};\n      }\n\n      return Done{expr_id};\n  }\n}\n\n// Returns true if converting `expr_id` to `target` requires `target.type_id`\n// to be complete.\nstatic auto ConversionNeedsCompleteTarget(Context& context,\n                                          SemIR::InstId expr_id,\n                                          ConversionTarget target) -> bool {\n  auto source_type_id = context.insts().Get(expr_id).type_id();\n\n  // We allow conversion to incomplete facet types, since their representation\n  // is fixed. This allows us to support using the `Self` of an interface inside\n  // its definition.\n  if (context.types().IsFacetType(target.type_id)) {\n    return false;\n  }\n\n  // If the types are the same, we only have to worry about form conversions.\n  if (source_type_id == target.type_id) {\n    auto source_category = SemIR::GetExprCategory(context.sem_ir(), expr_id);\n\n    // If there's no form conversion and no type conversion, the conversion is\n    // a no-op, so we don't need a complete type.\n    if (IsValidExprCategoryForConversionTarget(source_category, target.kind)) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\nauto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,\n             ConversionTarget target) -> SemIR::InstId {\n  auto& sem_ir = context.sem_ir();\n  auto orig_expr_id = expr_id;\n\n  // Start by making sure both sides are non-errors. If any part is an error,\n  // the result is an error and we shouldn't diagnose.\n  if (sem_ir.insts().Get(expr_id).type_id() == SemIR::ErrorInst::TypeId ||\n      target.type_id == SemIR::ErrorInst::TypeId) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto starting_category = SemIR::GetExprCategory(sem_ir, expr_id);\n  if (starting_category == SemIR::ExprCategory::NotExpr) {\n    // TODO: We currently encounter this for use of namespaces and functions.\n    // We should provide a better diagnostic for inappropriate use of\n    // namespace names, and allow use of functions as values.\n    if (target.diagnose) {\n      CARBON_DIAGNOSTIC(UseOfNonExprAsValue, Error,\n                        \"expression cannot be used as a value\");\n      context.emitter().Emit(expr_id, UseOfNonExprAsValue);\n    }\n    return SemIR::ErrorInst::InstId;\n  }\n\n  if (target.kind == ConversionTarget::NoOp) {\n    CARBON_CHECK(target.type_id == sem_ir.insts().Get(expr_id).type_id());\n    return expr_id;\n  }\n\n  // Diagnose unnecessary `ref` tags early, so that they're not obscured by\n  // conversions.\n  if (starting_category == SemIR::ExprCategory::RefTagged &&\n      target.kind != ConversionTarget::RefParam && target.diagnose) {\n    CARBON_DIAGNOSTIC(RefTagNoRefParam, Error,\n                      \"`ref` tag is not an argument to a `ref` parameter\");\n    context.emitter().Emit(expr_id, RefTagNoRefParam);\n  }\n\n  // TODO: Allow abstract but complete types if the conversion is just a\n  // same-type value acqisition.\n  // TODO: Push this check down to the points where we perform operations that\n  // need the type to be complete.\n  if (ConversionNeedsCompleteTarget(context, expr_id, target)) {\n    if (target.diagnose) {\n      if (!RequireConcreteType(\n              context, target.type_id, loc_id,\n              [&](auto& builder) {\n                CARBON_CHECK(\n                    !target.is_initializer(),\n                    \"Initialization of incomplete types is expected to be \"\n                    \"caught elsewhere.\");\n                CARBON_DIAGNOSTIC(IncompleteTypeInValueConversion, Context,\n                                  \"forming value of incomplete type {0}\",\n                                  SemIR::TypeId);\n                CARBON_DIAGNOSTIC(IncompleteTypeInConversion, Context,\n                                  \"invalid use of incomplete type {0}\",\n                                  SemIR::TypeId);\n                builder.Context(loc_id,\n                                target.kind == ConversionTarget::Value\n                                    ? IncompleteTypeInValueConversion\n                                    : IncompleteTypeInConversion,\n                                target.type_id);\n              },\n              [&](auto& builder) {\n                CARBON_DIAGNOSTIC(AbstractTypeInInit, Context,\n                                  \"initialization of abstract type {0}\",\n                                  SemIR::TypeId);\n                builder.Context(loc_id, AbstractTypeInInit, target.type_id);\n              })) {\n        return SemIR::ErrorInst::InstId;\n      }\n    } else {\n      if (!TryIsConcreteType(context, target.type_id, loc_id)) {\n        return SemIR::ErrorInst::InstId;\n      }\n    }\n  }\n\n  // Clear storage_id in cases where it's clearly meaningless, to avoid misuse\n  // and simplify the resulting SemIR.\n  if (!target.is_initializer() ||\n      SemIR::InitRepr::ForType(context.sem_ir(), target.type_id).kind ==\n          SemIR::InitRepr::None) {\n    target.storage_id = SemIR::InstId::None;\n  }\n\n  // The source type doesn't need to be complete, but its completeness can\n  // affect the result. For example, we don't know what type it adapts or\n  // derives from unless it's complete.\n  // TODO: Is there a risk of coherence problems if the source type is\n  // incomplete, but a conversion would have been possible or would have behaved\n  // differently if it were complete?\n  TryToCompleteType(context, context.insts().Get(expr_id).type_id(), loc_id);\n\n  // Check whether any builtin conversion applies.\n  expr_id = PerformBuiltinConversion(context, loc_id, expr_id, target);\n  if (expr_id == SemIR::ErrorInst::InstId) {\n    return expr_id;\n  }\n\n  // Defer the action if it's dependent. We do this now rather than before\n  // attempting any conversion so that we can still perform builtin conversions\n  // on dependent arguments. This matters for things like converting a\n  // `template T:! SomeInterface` to `type`, where it's important to form a\n  // `FacetAccessType` when checking the template. But when running the action\n  // later, we need to try builtin conversions again, because one may apply that\n  // didn't apply in the template definition.\n  // TODO: Support this for targets other than `Value`.\n  if (sem_ir.insts().Get(expr_id).type_id() != target.type_id &&\n      target.kind == ConversionTarget::Value &&\n      (OperandIsDependent(context, expr_id) ||\n       OperandIsDependent(context, target.type_id))) {\n    auto target_type_inst_id = context.types().GetTypeInstId(target.type_id);\n    return AddDependentActionSplice(\n        context, loc_id,\n        SemIR::ConvertToValueAction{\n            .type_id = GetSingletonType(context, SemIR::InstType::TypeInstId),\n            .inst_id = expr_id,\n            .target_type_inst_id = target_type_inst_id},\n        target_type_inst_id);\n  }\n\n  // If this is not a builtin conversion, try an `ImplicitAs` conversion.\n  if (sem_ir.insts().Get(expr_id).type_id() != target.type_id) {\n    SemIR::InstId interface_args[] = {\n        context.types().GetTypeInstId(target.type_id)};\n    Operator op = {\n        .interface_name = GetConversionInterfaceName(target.kind),\n        .interface_args_ref = interface_args,\n        .op_name = CoreIdentifier::Convert,\n    };\n    expr_id = BuildUnaryOperator(\n        context, loc_id, op, expr_id, target.diagnose, [&](auto& builder) {\n          int target_kind_for_diag =\n              target.kind == ConversionTarget::ExplicitAs         ? 1\n              : target.kind == ConversionTarget::ExplicitUnsafeAs ? 2\n                                                                  : 0;\n          if (target.type_id == SemIR::TypeType::TypeId ||\n              sem_ir.types().Is<SemIR::FacetType>(target.type_id)) {\n            CARBON_DIAGNOSTIC(\n                ConversionFailureNonTypeToFacet, Context,\n                \"cannot{0:=0: implicitly|:} convert non-type value of type {1} \"\n                \"{2:to|into type implementing} {3}\"\n                \"{0:=1: with `as`|=2: with `unsafe as`|:}\",\n                Diagnostics::IntAsSelect, TypeOfInstId,\n                Diagnostics::BoolAsSelect, SemIR::TypeId);\n            builder.Context(loc_id, ConversionFailureNonTypeToFacet,\n                            target_kind_for_diag, expr_id,\n                            target.type_id == SemIR::TypeType::TypeId,\n                            target.type_id);\n          } else {\n            CARBON_DIAGNOSTIC(\n                ConversionFailure, Context,\n                \"cannot{0:=0: implicitly|:} convert expression of type \"\n                \"{1} to {2}{0:=1: with `as`|=2: with `unsafe as`|:}\",\n                Diagnostics::IntAsSelect, TypeOfInstId, SemIR::TypeId);\n            builder.Context(loc_id, ConversionFailure, target_kind_for_diag,\n                            expr_id, target.type_id);\n          }\n        });\n\n    // Pull a value directly out of the initializer if possible and wanted.\n    if (expr_id != SemIR::ErrorInst::InstId &&\n        CanUseValueOfInitializer(sem_ir, target.type_id, target.kind)) {\n      expr_id = AddInst<SemIR::ValueOfInitializer>(\n          context, loc_id, {.type_id = target.type_id, .init_id = expr_id});\n    }\n  }\n\n  // Track that we performed a type conversion, if we did so.\n  if (orig_expr_id != expr_id) {\n    expr_id = AddInst<SemIR::Converted>(context, loc_id,\n                                        {.type_id = target.type_id,\n                                         .original_id = orig_expr_id,\n                                         .result_id = expr_id});\n  }\n\n  // For `as`, don't perform any value category conversions. In particular, an\n  // identity conversion shouldn't change the expression category.\n  if (target.is_explicit_as()) {\n    return expr_id;\n  }\n\n  // Now perform any necessary value category conversions.\n  expr_id = CategoryConverter(context, loc_id, target).Convert(expr_id);\n\n  return expr_id;\n}\n\nauto Initialize(Context& context, SemIR::LocId loc_id, SemIR::InstId storage_id,\n                SemIR::InstId value_id, bool for_return) -> SemIR::InstId {\n  auto type_id = context.insts().Get(storage_id).type_id();\n  if (for_return &&\n      !SemIR::InitRepr::ForType(context.sem_ir(), type_id).MightBeInPlace()) {\n    // TODO: is it safe to use storage_id when the init repr is dependent?\n    storage_id = SemIR::InstId::None;\n  }\n  // TODO: add CHECK that storage_id.index < value_id.index to enforce the\n  // precondition, once existing violations have been cleaned up.\n  PendingBlock target_block(&context);\n  return Convert(context, loc_id, value_id,\n                 {.kind = ConversionTarget::Initializing,\n                  .type_id = type_id,\n                  .storage_id = storage_id,\n                  .storage_access_block = &target_block});\n}\n\nauto ConvertToValueExpr(Context& context, SemIR::InstId expr_id)\n    -> SemIR::InstId {\n  return Convert(context, SemIR::LocId(expr_id), expr_id,\n                 {.kind = ConversionTarget::Value,\n                  .type_id = context.insts().Get(expr_id).type_id()});\n}\n\nauto ConvertToValueOrRefExpr(Context& context, SemIR::InstId expr_id)\n    -> SemIR::InstId {\n  return Convert(context, SemIR::LocId(expr_id), expr_id,\n                 {.kind = ConversionTarget::ValueOrRef,\n                  .type_id = context.insts().Get(expr_id).type_id()});\n}\n\nauto ConvertToValueOfType(Context& context, SemIR::LocId loc_id,\n                          SemIR::InstId expr_id, SemIR::TypeId type_id,\n                          bool diagnose) -> SemIR::InstId {\n  return Convert(context, loc_id, expr_id,\n                 {.kind = ConversionTarget::Value,\n                  .type_id = type_id,\n                  .diagnose = diagnose});\n}\n\nauto ConvertToValueOrRefOfType(Context& context, SemIR::LocId loc_id,\n                               SemIR::InstId expr_id, SemIR::TypeId type_id)\n    -> SemIR::InstId {\n  return Convert(context, loc_id, expr_id,\n                 {.kind = ConversionTarget::ValueOrRef, .type_id = type_id});\n}\n\n// Like ConvertToValueOfType but failure to convert does not result in\n// diagnostics. An ErrorInst instruction is still returned on failure.\nauto TryConvertToValueOfType(Context& context, SemIR::LocId loc_id,\n                             SemIR::InstId expr_id, SemIR::TypeId type_id)\n    -> SemIR::InstId {\n  return Convert(\n      context, loc_id, expr_id,\n      {.kind = ConversionTarget::Value, .type_id = type_id, .diagnose = false});\n}\n\nauto ConvertToBoolValue(Context& context, SemIR::LocId loc_id,\n                        SemIR::InstId value_id) -> SemIR::InstId {\n  return ConvertToValueOfType(\n      context, loc_id, value_id,\n      GetSingletonType(context, SemIR::BoolType::TypeInstId));\n}\n\nauto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,\n                          SemIR::InstId value_id, SemIR::TypeId type_id,\n                          bool unsafe) -> SemIR::InstId {\n  return Convert(context, as_node, value_id,\n                 {.kind = unsafe ? ConversionTarget::ExplicitUnsafeAs\n                                 : ConversionTarget::ExplicitAs,\n                  .type_id = type_id});\n}\n\n// TODO: Consider moving this to pattern_match.h.\nauto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,\n                     SemIR::InstId self_id,\n                     llvm::ArrayRef<SemIR::InstId> arg_refs,\n                     llvm::ArrayRef<SemIR::InstId> return_arg_ids,\n                     const SemIR::Function& callee,\n                     SemIR::SpecificId callee_specific_id,\n                     bool is_operator_syntax) -> SemIR::InstBlockId {\n  auto param_patterns =\n      context.inst_blocks().GetOrEmpty(callee.param_patterns_id);\n  auto return_patterns_id = callee.return_patterns_id;\n\n  // The caller should have ensured this callee has the right arity.\n  CARBON_CHECK(arg_refs.size() == param_patterns.size());\n\n  if (callee.self_param_id.has_value() && !self_id.has_value()) {\n    CARBON_DIAGNOSTIC(MissingObjectInMethodCall, Error,\n                      \"missing object argument in method call\");\n    CARBON_DIAGNOSTIC(InCallToFunction, Note, \"calling function declared here\");\n    context.emitter()\n        .Build(call_loc_id, MissingObjectInMethodCall)\n        .Note(callee.latest_decl_id(), InCallToFunction)\n        .Emit();\n    self_id = SemIR::ErrorInst::InstId;\n  }\n\n  return CallerPatternMatch(context, callee_specific_id, callee.self_param_id,\n                            callee.param_patterns_id, return_patterns_id,\n                            self_id, arg_refs, return_arg_ids,\n                            is_operator_syntax);\n}\n\nauto TypeExpr::ForUnsugared(Context& context, SemIR::TypeId type_id)\n    -> TypeExpr {\n  return {.inst_id = context.types().GetTypeInstId(type_id),\n          .type_id = type_id};\n}\n\nstatic auto DiagnoseTypeExprEvaluationFailure(Context& context,\n                                              SemIR::LocId loc_id) -> void {\n  CARBON_DIAGNOSTIC(TypeExprEvaluationFailure, Error,\n                    \"cannot evaluate type expression\");\n  context.emitter().Emit(loc_id, TypeExprEvaluationFailure);\n}\n\nauto ExprAsType(Context& context, SemIR::LocId loc_id, SemIR::InstId value_id,\n                bool diagnose) -> TypeExpr {\n  auto type_as_inst_id = ConvertToValueOfType(\n      context, loc_id, value_id, SemIR::TypeType::TypeId, diagnose);\n  if (type_as_inst_id == SemIR::ErrorInst::InstId) {\n    return {.inst_id = SemIR::ErrorInst::TypeInstId,\n            .type_id = SemIR::ErrorInst::TypeId};\n  }\n\n  auto type_as_const_id = context.constant_values().Get(type_as_inst_id);\n  if (!type_as_const_id.is_constant()) {\n    if (diagnose) {\n      DiagnoseTypeExprEvaluationFailure(context, loc_id);\n    }\n    return {.inst_id = SemIR::ErrorInst::TypeInstId,\n            .type_id = SemIR::ErrorInst::TypeId};\n  }\n\n  return {\n      .inst_id = context.types().GetAsTypeInstId(type_as_inst_id),\n      .type_id = context.types().GetTypeIdForTypeConstantId(type_as_const_id)};\n}\n\nauto FormExprAsForm(Context& context, SemIR::LocId loc_id,\n                    SemIR::InstId value_id) -> Context::FormExpr {\n  auto form_inst_id =\n      ConvertToValueOfType(context, loc_id, value_id, SemIR::FormType::TypeId);\n  if (form_inst_id == SemIR::ErrorInst::InstId) {\n    return Context::FormExpr::Error;\n  }\n\n  auto form_const_id = context.constant_values().Get(form_inst_id);\n  if (!form_const_id.is_constant()) {\n    CARBON_DIAGNOSTIC(FormExprEvaluationFailure, Error,\n                      \"cannot evaluate form expression\");\n    context.emitter().Emit(loc_id, FormExprEvaluationFailure);\n    return Context::FormExpr::Error;\n  }\n\n  auto type_id = GetTypeComponent(context, form_inst_id);\n  auto type_inst_id = context.types().GetTypeInstId(type_id);\n  return {.form_inst_id = form_inst_id,\n          .type_component_inst_id = type_inst_id,\n          .type_component_id = type_id};\n}\n\nauto ReturnExprAsForm(Context& context, SemIR::LocId loc_id,\n                      SemIR::InstId value_id) -> Context::FormExpr {\n  auto form_inst_id = SemIR::InstId::None;\n  auto type_inst_id = SemIR::InstId::None;\n  if (auto ref_tag = context.insts().TryGetAs<SemIR::RefTagExpr>(value_id)) {\n    type_inst_id = ConvertToValueOfType(context, loc_id, ref_tag->expr_id,\n                                        SemIR::TypeType::TypeId);\n    if (type_inst_id == SemIR::ErrorInst::InstId) {\n      return Context::FormExpr::Error;\n    }\n    if (!context.constant_values().Get(type_inst_id).is_constant()) {\n      DiagnoseTypeExprEvaluationFailure(context,\n                                        SemIR::LocId(ref_tag->expr_id));\n      return Context::FormExpr::Error;\n    }\n    form_inst_id = AddInst(\n        context,\n        SemIR::LocIdAndInst::UncheckedLoc(\n            loc_id,\n            SemIR::RefForm{.type_id = SemIR::FormType::TypeId,\n                           .type_component_inst_id =\n                               context.types().GetAsTypeInstId(type_inst_id)}));\n  } else {\n    type_inst_id = ConvertToValueOfType(context, loc_id, value_id,\n                                        SemIR::TypeType::TypeId);\n    if (type_inst_id == SemIR::ErrorInst::InstId) {\n      return Context::FormExpr::Error;\n    }\n    if (!context.constant_values().Get(type_inst_id).is_constant()) {\n      DiagnoseTypeExprEvaluationFailure(context, loc_id);\n      return Context::FormExpr::Error;\n    }\n    form_inst_id = AddInst(\n        context,\n        SemIR::LocIdAndInst::UncheckedLoc(\n            loc_id, SemIR::InitForm{\n                        .type_id = SemIR::FormType::TypeId,\n                        .type_component_inst_id =\n                            context.types().GetAsTypeInstId(type_inst_id)}));\n  }\n\n  auto type_const_id = context.constant_values().Get(type_inst_id);\n  CARBON_CHECK(type_const_id.is_constant());\n\n  return {\n      .form_inst_id = form_inst_id,\n      .type_component_inst_id = context.types().GetAsTypeInstId(type_inst_id),\n      .type_component_id =\n          context.types().GetTypeIdForTypeConstantId(type_const_id)};\n}\n\nauto DiscardExpr(Context& context, SemIR::InstId expr_id) -> void {\n  // If we discard an initializing expression, convert it to a value or\n  // reference so that it has something to initialize.\n  auto expr = context.insts().Get(expr_id);\n  Convert(context, SemIR::LocId(expr_id), expr_id,\n          {.kind = ConversionTarget::Discarded, .type_id = expr.type_id()});\n\n  // TODO: This will eventually need to do some \"do not discard\" analysis.\n}\n\n}  // namespace Carbon::Check\n\n// NOLINTEND(misc-no-recursion)\n"
  },
  {
    "path": "toolchain/check/convert.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CONVERT_H_\n#define CARBON_TOOLCHAIN_CHECK_CONVERT_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/pending_block.h\"\n#include \"toolchain/sem_ir/entity_with_params_base.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Description of the target of a conversion.\nstruct ConversionTarget {\n  enum Kind : int8_t {\n    // Perform no conversion. The source expression must already have type\n    // `type_id`.\n    NoOp,\n    // Convert to a value of type `type_id`.\n    Value,\n    // Convert to either a value or a reference of type `type_id`.\n    ValueOrRef,\n    // Convert to a durable reference of type `type_id`.\n    DurableRef,\n    // Convert to a reference, suitable for binding to a reference parameter.\n    // This allows both durable and ephemeral references. The restriction that\n    // only a `ref self` parameter can bind to an ephemeral reference is\n    // enforced separately when handling `ref` tags on call arguments.\n    RefParam,\n    // Equivalent to RefParam, except that the source expression is not required\n    // to be marked with a `ref` tag, such as an argument to a `ref self`\n    // parameter or an operator operand.\n    UnmarkedRefParam,\n    // Convert to a reference of type `type_id`, for use as the argument to a\n    // C++ thunk.\n    CppThunkRef,\n    // Convert for an explicit `as` cast. This allows any expression category\n    // as the result, and uses the `As` interface instead of the `ImplicitAs`\n    // interface.\n    ExplicitAs,\n    // Convert for an explicit `unsafe as` cast. This allows any expression\n    // category as the result, and uses the `UnsafeAs` interface instead of the\n    // `As` or `ImplicitAs` interface.\n    ExplicitUnsafeAs,\n    // The result of the conversion is discarded. It can't be an initializing\n    // expression, but can be anything else.\n    Discarded,\n    // Convert to an initializing expression that uses `type_id`'s initializing\n    // representation. The resulting expression will usually be a\n    // repr-initializing expression, but may be an in-place initializing\n    // expression if the source expression was. If `storage_id` is present, it\n    // is used as the storage argument for the converted expression, and it must\n    // be present if the initializing representation might be in-place.\n    Initializing,\n    // Convert to an in-place initializing expression whose storage is\n    // designated by `storage_id` (which must not be `None`)\n    InPlaceInitializing,\n    Last = InPlaceInitializing\n  };\n  // The kind of the target for this conversion.\n  Kind kind;\n  // The target type for the conversion.\n  SemIR::TypeId type_id;\n  // The storage being initialized, if any.\n  SemIR::InstId storage_id = SemIR::InstId::None;\n  // For an initializer, a block of pending instructions that `storage_id`\n  // depends on, and that can be discarded if `storage_id` is not accessed.\n  // If this is not null or empty, its last element must be storage_id.\n  PendingBlock* storage_access_block = nullptr;\n  // Whether failure of conversion is an error and is diagnosed to the user.\n  // When looking for a possible conversion but with graceful fallback,\n  // `diagnose` should be false. If `diagnose` is false, an `ErrorInst` may be\n  // returned, but it must be discarded.\n  bool diagnose = true;\n\n  // Are we converting this value into an initializer for an object?\n  auto is_initializer() const -> bool {\n    return kind == Initializing || kind == InPlaceInitializing;\n  }\n  // Is this some kind of explicit `as` conversion?\n  auto is_explicit_as() const -> bool {\n    return kind == ExplicitAs || kind == ExplicitUnsafeAs;\n  }\n};\n\n// Convert a value to another type and expression category.\nauto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,\n             ConversionTarget target) -> SemIR::InstId;\n\n// Converts `value_id` to an initializing expression of the type of\n// `storage_id`, and returns the possibly-converted initializing expression.\n// `storage_id` is used as the storage argument of the resulting expression\n// except as noted below, and when it is used as the storage argument it must\n// precede `value_id`. The caller is responsible for passing the result to an\n// inst that is documented as consuming it, such as `Assign`.\n//\n// `for_return` indicates that this conversion is initializing the operand of a\n// `return` statement. This means that `storage_id` will be the return slot\n// parameter, which isn't valid to access if the type's initializing\n// representation is not in-place, so in that case `storage_id` will be used\n// solely for its type.\n//\n// TODO: Consider making the target type a separate parameter, and making\n// storage_id optional.\nauto Initialize(Context& context, SemIR::LocId loc_id, SemIR::InstId storage_id,\n                SemIR::InstId value_id, bool for_return = false)\n    -> SemIR::InstId;\n\n// Convert the given expression to a value expression of the same type.\nauto ConvertToValueExpr(Context& context, SemIR::InstId expr_id)\n    -> SemIR::InstId;\n\n// Convert the given expression to a value or reference expression of the same\n// type.\nauto ConvertToValueOrRefExpr(Context& context, SemIR::InstId expr_id)\n    -> SemIR::InstId;\n\n// Converts `expr_id` to a value expression of type `type_id`.\n//\n// If `diagnose` is true, errors are diagnosed to the user. Set it to false when\n// looking to see if a conversion is possible but with graceful fallback. If\n// `diagnose` is false, an `ErrorInst` may be returned, but it must be\n// discarded.\nauto ConvertToValueOfType(Context& context, SemIR::LocId loc_id,\n                          SemIR::InstId expr_id, SemIR::TypeId type_id,\n                          bool diagnose = true) -> SemIR::InstId;\n\n// Convert the given expression to a value or reference expression of the given\n// type.\nauto ConvertToValueOrRefOfType(Context& context, SemIR::LocId loc_id,\n                               SemIR::InstId expr_id, SemIR::TypeId type_id)\n    -> SemIR::InstId;\n\n// Attempted to convert `expr_id` to a value expression of type `type_id`, with\n// graceful failure, which does not result in diagnostics. An ErrorInst\n// instruction is still returned on failure.\nauto TryConvertToValueOfType(Context& context, SemIR::LocId loc_id,\n                             SemIR::InstId expr_id, SemIR::TypeId type_id)\n    -> SemIR::InstId;\n\n// Converts `value_id` to a value expression of type `bool`.\nauto ConvertToBoolValue(Context& context, SemIR::LocId loc_id,\n                        SemIR::InstId value_id) -> SemIR::InstId;\n\n// Converts `value_id` to type `type_id` for an `as` expression.\nauto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,\n                          SemIR::InstId value_id, SemIR::TypeId type_id,\n                          bool unsafe) -> SemIR::InstId;\n\n// Implicitly converts a set of arguments to match the parameter types in a\n// function call. Returns a block containing the converted implicit and explicit\n// argument values for runtime parameters. `is_operator_syntax` indicates that\n// this call was generated from an operator rather than from function call\n// syntax, so arguments to `ref` parameters aren't required to have `ref` tags.\nauto ConvertCallArgs(Context& context, SemIR::LocId call_loc_id,\n                     SemIR::InstId self_id,\n                     llvm::ArrayRef<SemIR::InstId> arg_refs,\n                     llvm::ArrayRef<SemIR::InstId> return_arg_ids,\n                     const SemIR::Function& callee,\n                     SemIR::SpecificId callee_specific_id,\n                     bool is_operator_syntax) -> SemIR::InstBlockId;\n\n// A type that has been converted for use as a type expression.\nstruct TypeExpr {\n  static const TypeExpr None;\n\n  // Returns a TypeExpr describing a type with no associated spelling or type\n  // sugar.\n  static auto ForUnsugared(Context& context, SemIR::TypeId type_id) -> TypeExpr;\n\n  // The converted expression of type `type`, or `ErrorInst::InstId`.\n  SemIR::TypeInstId inst_id;\n  // The corresponding type, or `ErrorInst::TypeId`.\n  SemIR::TypeId type_id;\n};\n\ninline constexpr TypeExpr TypeExpr::None = {.inst_id = SemIR::TypeInstId::None,\n                                            .type_id = SemIR::TypeId::None};\n\n// Converts an expression for use as a type.\n//\n// If `diagnose` is true, errors are diagnosed to the user. Set it to false when\n// looking to see if a conversion is possible but with graceful fallback. If\n// `diagnose` is false, an `ErrorInst` may be returned, but it must be\n// discarded.\n//\n// TODO: Most of the callers of this function discard the `inst_id` and lose\n// track of the conversion. In most cases we should be retaining that as the\n// operand of some downstream instruction.\nauto ExprAsType(Context& context, SemIR::LocId loc_id, SemIR::InstId value_id,\n                bool diagnose = true) -> TypeExpr;\n\n// Converts an expression in a form position for use as a form.\n//\n// Note that the right-hand side of a `->` return type declaration is not\n// a form position for this purpose, because it uses a special syntax to specify\n// forms. `ReturnExprAsForm` should be used instead in that case.\n//\n// `diagnose` has the same effect as in `ExprAsType`.\nauto FormExprAsForm(Context& context, SemIR::LocId loc_id,\n                    SemIR::InstId value_id) -> Context::FormExpr;\n\n// Evaluates an expression in the return-type position (following `->`, not\n// `->?`) for use as a form, following the special-case language rules for\n// evaluating an expression in that position.\nauto ReturnExprAsForm(Context& context, SemIR::LocId loc_id,\n                      SemIR::InstId value_id) -> Context::FormExpr;\n\n// Handles an expression whose result value is unused.\nauto DiscardExpr(Context& context, SemIR::InstId expr_id) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CONVERT_H_\n"
  },
  {
    "path": "toolchain/check/core_identifier.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/core_identifier.h\"\n\nnamespace Carbon::Check {\n\nCARBON_DEFINE_ENUM_CLASS_NAMES(CoreIdentifier) {\n#define CARBON_CORE_IDENTIFIER(Name) CARBON_ENUM_CLASS_NAME_STRING(Name)\n#include \"toolchain/check/core_identifier.def\"\n};\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/core_identifier.def",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// This is an X-macro header. It does not use `#include` guards, and instead is\n// designed to be `#include`ed after the x-macro is defined in order for its\n// inclusion to expand to the desired output. Macro definitions are cleaned up\n// at the end of this file.\n//\n// This macro should be defined before including this header:\n// - CARBON_CORE_IDENTIFIER(Name)\n//   Invoked for each `Core` identifier.\n\n#ifndef CARBON_CORE_IDENTIFIER\n#error \"Must define the x-macro to use this file.\"\n#define CARBON_CORE_IDENTIFIER(Name)\n#endif\n\nCARBON_CORE_IDENTIFIER(AddAssignWith)\nCARBON_CORE_IDENTIFIER(AddWith)\nCARBON_CORE_IDENTIFIER(As)\nCARBON_CORE_IDENTIFIER(AssignWith)\nCARBON_CORE_IDENTIFIER(At)\nCARBON_CORE_IDENTIFIER(BitAndAssignWith)\nCARBON_CORE_IDENTIFIER(BitAndWith)\nCARBON_CORE_IDENTIFIER(BitComplement)\nCARBON_CORE_IDENTIFIER(BitOrAssignWith)\nCARBON_CORE_IDENTIFIER(BitOrWith)\nCARBON_CORE_IDENTIFIER(BitXorAssignWith)\nCARBON_CORE_IDENTIFIER(BitXorWith)\nCARBON_CORE_IDENTIFIER(Bool)\nCARBON_CORE_IDENTIFIER(Char)\nCARBON_CORE_IDENTIFIER(Convert)\nCARBON_CORE_IDENTIFIER(Copy)\nCARBON_CORE_IDENTIFIER(CppCompat)\nCARBON_CORE_IDENTIFIER(CppUnsafeDeref)\nCARBON_CORE_IDENTIFIER(Dec)\nCARBON_CORE_IDENTIFIER(DefaultOrUnformed)\nCARBON_CORE_IDENTIFIER(Destroy)\nCARBON_CORE_IDENTIFIER(DivAssignWith)\nCARBON_CORE_IDENTIFIER(DivWith)\nCARBON_CORE_IDENTIFIER(EqWith)\nCARBON_CORE_IDENTIFIER(Equal)\nCARBON_CORE_IDENTIFIER(Float)\nCARBON_CORE_IDENTIFIER(Get)\nCARBON_CORE_IDENTIFIER(Greater)\nCARBON_CORE_IDENTIFIER(GreaterOrEquivalent)\nCARBON_CORE_IDENTIFIER(HasValue)\nCARBON_CORE_IDENTIFIER(ImplicitAs)\nCARBON_CORE_IDENTIFIER(Inc)\nCARBON_CORE_IDENTIFIER(IndexWith)\nCARBON_CORE_IDENTIFIER(Int)\nCARBON_CORE_IDENTIFIER(IntFitsIn)\nCARBON_CORE_IDENTIFIER(Iterate)\nCARBON_CORE_IDENTIFIER(LeftShiftAssignWith)\nCARBON_CORE_IDENTIFIER(LeftShiftWith)\nCARBON_CORE_IDENTIFIER(Less)\nCARBON_CORE_IDENTIFIER(LessOrEquivalent)\nCARBON_CORE_IDENTIFIER(Long32)\nCARBON_CORE_IDENTIFIER(LongLong64)\nCARBON_CORE_IDENTIFIER(ModAssignWith)\nCARBON_CORE_IDENTIFIER(ModWith)\nCARBON_CORE_IDENTIFIER(MulAssignWith)\nCARBON_CORE_IDENTIFIER(MulWith)\nCARBON_CORE_IDENTIFIER(Negate)\nCARBON_CORE_IDENTIFIER(NewCursor)\nCARBON_CORE_IDENTIFIER(Next)\nCARBON_CORE_IDENTIFIER(NotEqual)\nCARBON_CORE_IDENTIFIER(NullptrT)\nCARBON_CORE_IDENTIFIER(Op)\nCARBON_CORE_IDENTIFIER(Optional)\nCARBON_CORE_IDENTIFIER(OrderedWith)\nCARBON_CORE_IDENTIFIER(RightShiftAssignWith)\nCARBON_CORE_IDENTIFIER(RightShiftWith)\nCARBON_CORE_IDENTIFIER(String)\nCARBON_CORE_IDENTIFIER(SubAssignWith)\nCARBON_CORE_IDENTIFIER(SubWith)\nCARBON_CORE_IDENTIFIER(UInt)\nCARBON_CORE_IDENTIFIER(ULong32)\nCARBON_CORE_IDENTIFIER(ULongLong64)\nCARBON_CORE_IDENTIFIER(UnsafeAs)\nCARBON_CORE_IDENTIFIER(VoidBase)\n\n#undef CARBON_CORE_IDENTIFIER\n"
  },
  {
    "path": "toolchain/check/core_identifier.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CORE_IDENTIFIER_H_\n#define CARBON_TOOLCHAIN_CHECK_CORE_IDENTIFIER_H_\n\n#include \"common/enum_base.h\"\n#include \"toolchain/base/shared_value_stores.h\"\n#include \"toolchain/base/value_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nCARBON_DEFINE_RAW_ENUM_CLASS(CoreIdentifier, uint8_t) {\n#define CARBON_CORE_IDENTIFIER(Name) CARBON_RAW_ENUM_ENUMERATOR(Name)\n#include \"toolchain/check/core_identifier.def\"\n};\n\n// An identifier in `Core` that's significant for the language (typically used\n// by desugaring) but not a builtin or keyword. Note this includes non-top-level\n// identifiers, such as both `AddWith` and `Op` in `Core.AddWith.Op`.\nclass CoreIdentifier : public CARBON_ENUM_BASE(CoreIdentifier) {\n public:\n#define CARBON_CORE_IDENTIFIER(Name) CARBON_ENUM_CONSTANT_DECL(Name)\n#include \"toolchain/check/core_identifier.def\"\n\n private:\n  // Exposes `AsInt`.\n  friend class CoreIdentifierCache;\n};\n\n#define CARBON_CORE_IDENTIFIER(Name) \\\n  CARBON_ENUM_CONSTANT_DEFINITION(CoreIdentifier, Name)\n#include \"toolchain/check/core_identifier.def\"\n\n// A cache of added `Core` identifiers. These are added to the identifier\n// store on first use.\nclass CoreIdentifierCache {\n public:\n  explicit CoreIdentifierCache(SharedValueStores::IdentifierStore* identifiers)\n      : identifiers_(identifiers) {}\n\n  // Returns the `NameId` for a `CoreIdentifier`.\n  auto AddNameId(CoreIdentifier identifier) -> SemIR::NameId {\n    auto& value = cache_[identifier.AsInt()];\n    if (!value.has_value()) {\n      value =\n          SemIR::NameId::ForIdentifier(identifiers_->Add(identifier.name()));\n    }\n    return value;\n  }\n\n private:\n  // The number of cache entries.\n  static constexpr int CacheSize = 0\n#define CARBON_CORE_IDENTIFIER(Name) +1\n#include \"toolchain/check/core_identifier.def\"\n      ;\n\n  // A pointer for adding identifiers.\n  SharedValueStores::IdentifierStore* identifiers_;\n\n  // The cache of added identifiers. These are stored as a `NameId` because the\n  // `IdentifierId` isn't directly used.\n  SemIR::NameId cache_[CacheSize] = {\n#define CARBON_CORE_IDENTIFIER(Name) SemIR::NameId::None,\n#include \"toolchain/check/core_identifier.def\"\n  };\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CORE_IDENTIFIER_H_\n"
  },
  {
    "path": "toolchain/check/cpp/access.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/access.h\"\n\nnamespace Carbon::Check {\n\nstatic auto CalculateEffectiveAccess(clang::DeclAccessPair access_pair)\n    -> clang::AccessSpecifier {\n  // Note that we use `.getAccess()` here, not `->getAccess()`, which is\n  // equivalent to `.getDecl()->getAccess()`, because we want to consider the\n  // lookup access and not the lexical access.\n  switch (access_pair.getAccess()) {\n    // Lookup access takes precedence.\n    case clang::AS_public:\n    case clang::AS_protected:\n    case clang::AS_private:\n      return access_pair.getAccess();\n    case clang::AS_none:\n      // No access specified meaning depends on the declaration. For non class\n      // members, it means there's no access associated with this function so we\n      // treat it as public. For class members it means we lost access along the\n      // inheritance path, and the difference between `none` and `private` only\n      // matters when the access check is performed within a friend or member of\n      // the naming class. Because the naming class is a C++ class, and we don't\n      // yet have a mechanism for a C++ class to befriend a Carbon class, we can\n      // safely map `none` to `private` for now.\n      return access_pair->isCXXClassMember() ? clang::AS_private\n                                             : clang::AS_public;\n  }\n}\n\nauto MapCppAccess(clang::DeclAccessPair access_pair) -> SemIR::AccessKind {\n  switch (CalculateEffectiveAccess(access_pair)) {\n    case clang::AS_public:\n      return SemIR::AccessKind::Public;\n    case clang::AS_protected:\n      return SemIR::AccessKind::Protected;\n    case clang::AS_private:\n      return SemIR::AccessKind::Private;\n    case clang::AS_none:\n      CARBON_FATAL(\"Couldn't convert access\");\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/access.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_ACCESS_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_ACCESS_H_\n\n#include \"toolchain/sem_ir/name_scope.h\"\n\nnamespace Carbon::Check {\n\n// Calculates the effective access kind from the given (declaration, lookup\n// access) pair.\nauto MapCppAccess(clang::DeclAccessPair access_pair) -> SemIR::AccessKind;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_ACCESS_H_\n"
  },
  {
    "path": "toolchain/check/cpp/call.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/call.h\"\n\n#include \"clang/Sema/Sema.h\"\n#include \"clang/Sema/Template.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/cpp/constant.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/cpp/location.h\"\n#include \"toolchain/check/cpp/operators.h\"\n#include \"toolchain/check/cpp/overload_resolution.h\"\n#include \"toolchain/check/cpp/type_mapping.h\"\n#include \"toolchain/check/literal.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Returns true if the given instruction can only be a template argument, and\n// not a function argument. We classify arguments as definitely being template\n// arguments if they are types or the name of a template or generic.\n// TODO: We should also have a way to specify that an argument is a non-type\n// template argument.\nstatic auto IsTemplateArg(Context& context, SemIR::InstId arg_id) -> bool {\n  auto arg_type_id = context.insts().Get(arg_id).type_id();\n  auto arg_type = context.types().GetAsInst(arg_type_id);\n  return arg_type\n      .IsOneOf<SemIR::TypeType, SemIR::FacetType, SemIR::CppTemplateNameType,\n               SemIR::GenericClassType, SemIR::GenericInterfaceType,\n               SemIR::GenericNamedConstraintType>();\n}\n\n// Splits a call argument list into a list of template arguments followed by a\n// list of function arguments. We split the argument list as early as possible,\n// subject to the constraint that if an argument is a template argument, it goes\n// in the template argument list.\nstatic auto SplitCallArgumentList(Context& context,\n                                  llvm::ArrayRef<SemIR::InstId> arg_ids)\n    -> std::pair<llvm::ArrayRef<SemIR::InstId>, llvm::ArrayRef<SemIR::InstId>> {\n  for (auto [n, arg_id] : llvm::enumerate(llvm::reverse(arg_ids))) {\n    if (IsTemplateArg(context, arg_id)) {\n      return {arg_ids.drop_back(n), arg_ids.take_back(n)};\n    }\n  }\n  // No template arguments found.\n  return {{}, arg_ids};\n}\n\nauto PerformCallToCppFunction(Context& context, SemIR::LocId loc_id,\n                              SemIR::CppOverloadSetId overload_set_id,\n                              SemIR::InstId self_id,\n                              llvm::ArrayRef<SemIR::InstId> arg_ids,\n                              bool is_operator_syntax) -> SemIR::InstId {\n  auto [template_arg_ids, function_arg_ids] =\n      SplitCallArgumentList(context, arg_ids);\n  auto callee_id = PerformCppOverloadResolution(\n      context, loc_id, context.cpp_overload_sets().Get(overload_set_id),\n      template_arg_ids, self_id, function_arg_ids);\n  SemIR::Callee callee = GetCallee(context.sem_ir(), callee_id);\n  CARBON_KIND_SWITCH(callee) {\n    case CARBON_KIND(SemIR::CalleeError _): {\n      return SemIR::ErrorInst::InstId;\n    }\n    case CARBON_KIND(SemIR::CalleeFunction fn): {\n      CARBON_CHECK(!fn.self_id.has_value());\n      if (self_id.has_value()) {\n        // Preserve the `self` argument from the original callee.\n        fn.self_id = self_id;\n      }\n      return PerformCallToFunction(context, loc_id, callee_id, fn,\n                                   function_arg_ids, is_operator_syntax);\n    }\n    case CARBON_KIND(SemIR::CalleeCppOverloadSet _): {\n      CARBON_FATAL(\"overloads can't be recursive\");\n    }\n    case CARBON_KIND(SemIR::CalleeNonFunction _): {\n      CARBON_FATAL(\"overloads should produce functions\");\n    }\n  }\n}\n\n// Synthesize a placeholder `void{}` template argument, that will never be a\n// valid argument for any template parameter. This is used in order to get Clang\n// to diagnose invalid template argument errors for us. The location of the\n// Carbon expression is used as the location of the C++ expression, so\n// Clang's diagnostics will point into the Carbon code.\n//\n// TODO: If Clang ever tries to print the type of the expression or to\n// pretty-print the expression itself, it would print the wrong thing. Currently\n// this doesn't appear to happen, but in principle it could. Ideally we'd add an\n// extension point to Clang to represent a \"foreign expression\" and use it here\n// instead of creating a bogus placeholder expression.\nstatic auto MakePlaceholderTemplateArg(Context& context, SemIR::InstId arg_id)\n    -> clang::TemplateArgumentLoc {\n  auto arg_loc = GetCppLocation(context, SemIR::LocId(arg_id));\n  auto void_type = context.ast_context().VoidTy;\n  auto* arg = new (context.ast_context()) clang::CXXScalarValueInitExpr(\n      void_type,\n      context.ast_context().getTrivialTypeSourceInfo(void_type, arg_loc),\n      arg_loc);\n  return clang::TemplateArgumentLoc(\n      clang::TemplateArgument(arg, /*IsCanonical=*/false), arg);\n}\n\n// Converts an argument in a call to a C++ template name into a corresponding\n// clang template argument, given the template parameter it will be matched\n// against.\nstatic auto ConvertArgToTemplateArg(\n    Context& context, clang::TemplateDecl* template_decl,\n    clang::NamedDecl* param_decl, SemIR::InstId arg_id,\n    clang::SmallVector<clang::TemplateArgument>* template_args,\n    unsigned argument_pack_index, bool diagnose)\n    -> std::optional<clang::TemplateArgumentLoc> {\n  if (isa<clang::TemplateTypeParmDecl>(param_decl)) {\n    auto type = ExprAsType(context, SemIR::LocId(arg_id), arg_id, diagnose);\n    if (type.type_id == SemIR::ErrorInst::TypeId) {\n      return std::nullopt;\n    }\n    auto clang_type = MapToCppType(context, type.type_id);\n    if (clang_type.isNull()) {\n      if (diagnose) {\n        context.TODO(arg_id, \"unsupported type used as template argument\");\n      }\n      return std::nullopt;\n    }\n    return clang::TemplateArgumentLoc(\n        clang_type,\n        context.ast_context().getTrivialTypeSourceInfo(\n            clang_type, GetCppLocation(context, SemIR::LocId(arg_id))));\n  }\n\n  if (isa<clang::TemplateTemplateParmDecl>(param_decl)) {\n    auto inst = context.sem_ir().insts().Get(arg_id);\n    if (auto template_name_type =\n            context.types().TryGetAs<SemIR::CppTemplateNameType>(\n                inst.type_id())) {\n      clang::TemplateName name(cast<clang::TemplateDecl>(\n          context.clang_decls().Get(template_name_type->decl_id).key.decl));\n      return clang::TemplateArgumentLoc(\n          context.ast_context(), clang::TemplateArgument(name),\n          /*TemplateKWLoc=*/clang::SourceLocation(),\n          clang::NestedNameSpecifierLoc(),\n          GetCppLocation(context, SemIR::LocId(arg_id)));\n    }\n\n    // TODO: Eventually we should also support passing Carbon generics as\n    // template template arguments.\n    return MakePlaceholderTemplateArg(context, arg_id);\n  }\n\n  if (auto* non_type = dyn_cast<clang::NonTypeTemplateParmDecl>(param_decl)) {\n    auto param_type = non_type->getType();\n    if (non_type->isParameterPack() && non_type->isExpandedParameterPack()) {\n      param_type = non_type->getExpansionType(argument_pack_index);\n    }\n\n    // Handle non-type parameters with a dependent type. For example:\n    //\n    // C++:    template<typename T, T N> struct S{};\n    // Carbon: Cpp.S(i32, 42)\n    //\n    // When evaluating the second template argument, the generic type of\n    // `T` should be substituted with `i32`.\n    if (param_type->isInstantiationDependentType()) {\n      // If we don't want to diagnose errors, create a SFINAE context so that\n      // Clang knows to suppress error messages.\n      std::optional<clang::Sema::SFINAETrap> sfinae;\n      if (!diagnose) {\n        sfinae.emplace(context.clang_sema());\n      }\n\n      clang::Sema::InstantiatingTemplate inst(\n          context.clang_sema(), clang::SourceLocation(), param_decl, non_type,\n          *template_args, clang::SourceRange());\n      if (inst.isInvalid()) {\n        return std::nullopt;\n      }\n      clang::MultiLevelTemplateArgumentList mltal(template_decl, *template_args,\n                                                  /*Final=*/true);\n\n      mltal.addOuterRetainedLevels(non_type->getDepth());\n      if (const auto* pet = param_type->getAs<clang::PackExpansionType>()) {\n        clang::Sema::ArgPackSubstIndexRAII subst_index(context.clang_sema(),\n                                                       argument_pack_index);\n        param_type = context.clang_sema().SubstType(pet->getPattern(), mltal,\n                                                    non_type->getLocation(),\n                                                    non_type->getDeclName());\n      } else {\n        param_type = context.clang_sema().SubstType(param_type, mltal,\n                                                    non_type->getLocation(),\n                                                    non_type->getDeclName());\n      }\n\n      if (!param_type.isNull()) {\n        param_type = context.clang_sema().CheckNonTypeTemplateParameterType(\n            param_type, non_type->getLocation());\n      }\n      if (param_type.isNull() || (sfinae && sfinae->hasErrorOccurred())) {\n        return std::nullopt;\n      }\n    }\n\n    // Get the Carbon type corresponding to the parameter's Clang type.\n    const auto type_expr =\n        ImportCppType(context, SemIR::LocId(arg_id), param_type);\n\n    // Try to convert the argument to the parameter type.\n    const auto converted_inst_id =\n        Convert(context, SemIR::LocId(arg_id), arg_id,\n                {\n                    .kind = ConversionTarget::Value,\n                    .type_id = type_expr.type_id,\n                    .diagnose = diagnose,\n                });\n\n    if (converted_inst_id == SemIR::ErrorInst::InstId) {\n      return std::nullopt;\n    }\n\n    // TODO: provide a better location.\n    auto template_loc = clang::TemplateArgumentLocInfo();\n\n    auto const_inst_id =\n        context.constant_values().GetConstantInstId(converted_inst_id);\n    if (const_inst_id.has_value()) {\n      if (param_type->isPointerType()) {\n        if (auto addr_of =\n                context.insts().TryGetAs<SemIR::AddrOf>(const_inst_id)) {\n          if (auto* var_decl = GetAsClangVarDecl(context, addr_of->lvalue_id)) {\n            clang::TemplateArgument template_arg(var_decl, param_type);\n            return clang::TemplateArgumentLoc(template_arg, template_loc);\n          }\n\n          // TODO: support pointers to variables declared in Carbon.\n        }\n      } else if (auto ap_value =\n                     MapConstantToAPValue(context, const_inst_id, param_type)) {\n        clang::TemplateArgument template_arg(context.ast_context(), param_type,\n                                             *ap_value);\n        return clang::TemplateArgumentLoc(template_arg, template_loc);\n      }\n    }\n\n    // TODO: Support other types.\n    if (diagnose) {\n      context.TODO(arg_id,\n                   \"unsupported argument type for non-type template parameter\");\n    }\n    return std::nullopt;\n  }\n\n  CARBON_FATAL(\"Unknown declaration kind for template parameter\");\n}\n\nauto ConvertArgsToTemplateArgs(Context& context,\n                               clang::TemplateDecl* template_decl,\n                               llvm::ArrayRef<SemIR::InstId> arg_ids,\n                               clang::TemplateArgumentListInfo& arg_list,\n                               bool diagnose) -> bool {\n  clang::SmallVector<clang::TemplateArgument> template_args;\n  for (auto* param_decl : template_decl->getTemplateParameters()->asArray()) {\n    if (arg_ids.empty()) {\n      return true;\n    }\n\n    // A parameter pack consumes all remaining arguments; otherwise, it consumes\n    // a single argument.\n    // TODO: Handle expanded template parameter packs, which have a known, fixed\n    // arity.\n    llvm::ArrayRef<SemIR::InstId> args_for_param =\n        param_decl->isTemplateParameterPack() ? std::exchange(arg_ids, {})\n                                              : arg_ids.consume_front();\n    for (auto [argument_pack_index, arg_id] : llvm::enumerate(args_for_param)) {\n      if (auto arg = ConvertArgToTemplateArg(context, template_decl, param_decl,\n                                             arg_id, &template_args,\n                                             argument_pack_index, diagnose)) {\n        arg_list.addArgument(*arg);\n        template_args.push_back(arg->getArgument());\n        argument_pack_index++;\n      } else {\n        return false;\n      }\n    }\n  }\n\n  // If there are any remaining arguments, that's an error; convert them to\n  // placeholder template arguments so that Clang will diagnose it for us.\n  for (auto arg_id : arg_ids) {\n    // Synthesize a placeholder `void{}` template argument.\n    arg_list.addArgument(MakePlaceholderTemplateArg(context, arg_id));\n  }\n\n  return true;\n}\n\n// Given a template and an template argument list, builds a Carbon value\n// describing the corresponding C++ template-id.\nstatic auto BuildTemplateId(Context& context, SemIR::LocId loc_id,\n                            clang::SourceLocation loc,\n                            clang::TemplateDecl* template_decl,\n                            clang::TemplateArgumentListInfo& arg_list)\n    -> SemIR::InstId {\n  if (auto* var_template_decl =\n          dyn_cast<clang::VarTemplateDecl>(template_decl)) {\n    auto decl_result = context.clang_sema().CheckVarTemplateId(\n        var_template_decl, /*TemplateLoc=*/clang::SourceLocation(), loc,\n        arg_list, /*SetWrittenArgs=*/false);\n    return decl_result.isInvalid()\n               ? SemIR::ErrorInst::InstId\n               : ImportCppDecl(context, loc_id,\n                               SemIR::ClangDeclKey::ForNonFunctionDecl(\n                                   decl_result.get()));\n  }\n\n  if (auto* concept_decl = dyn_cast<clang::ConceptDecl>(template_decl)) {\n    auto expr_result = context.clang_sema().CheckConceptTemplateId(\n        clang::CXXScopeSpec(), /*TemplateKWLoc=*/clang::SourceLocation(),\n        clang::DeclarationNameInfo(concept_decl->getDeclName(), loc),\n        concept_decl, concept_decl, &arg_list);\n    if (expr_result.isInvalid()) {\n      return SemIR::ErrorInst::InstId;\n    }\n    auto* expr = expr_result.getAs<clang::ConceptSpecializationExpr>();\n    return MakeBoolLiteral(context, loc_id,\n                           SemIR::BoolValue::From(expr->isSatisfied()));\n  }\n\n  clang::TemplateName template_name(template_decl);\n  auto clang_type = context.clang_sema().CheckTemplateIdType(\n      clang::ElaboratedTypeKeyword::None, template_name, loc, arg_list,\n      /*Scope=*/nullptr, /*ForNestedNameSpecifier=*/false);\n  if (clang_type.isNull()) {\n    return SemIR::ErrorInst::InstId;\n  }\n  return ImportCppType(context, loc_id, clang_type).inst_id;\n}\n\nauto PerformCallToCppTemplateName(Context& context, SemIR::LocId loc_id,\n                                  SemIR::ClangDeclId template_decl_id,\n                                  llvm::ArrayRef<SemIR::InstId> arg_ids)\n    -> SemIR::InstId {\n  auto* template_decl = dyn_cast<clang::TemplateDecl>(\n      context.clang_decls().Get(template_decl_id).key.decl);\n  auto loc = GetCppLocation(context, loc_id);\n\n  // Form a template argument list for this template.\n  clang::TemplateArgumentListInfo arg_list(loc, loc);\n  if (!ConvertArgsToTemplateArgs(context, template_decl, arg_ids, arg_list)) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  return BuildTemplateId(context, loc_id, loc, template_decl, arg_list);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/call.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_CALL_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_CALL_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Converts a call argument list into a Clang template argument list for a given\n// template. Returns true on success, or false if an error was diagnosed.\n//\n// If `diagnose` is false, errors will be suppressed.\nauto ConvertArgsToTemplateArgs(Context& context,\n                               clang::TemplateDecl* template_decl,\n                               llvm::ArrayRef<SemIR::InstId> arg_ids,\n                               clang::TemplateArgumentListInfo& arg_list,\n                               bool diagnose = true) -> bool;\n\n// Checks and builds SemIR for a call to a C++ function in the given overload\n// set with self `self_id` and arguments `arg_ids`. `is_operator_syntax`\n// indicates that this call was generated from an operator rather than from\n// function call syntax, so arguments to `ref` parameters aren't required to\n// have `ref` tags.\n//\n// Chooses the best viable C++ function by performing Clang overloading\n// resolution over the overload set.\n//\n// Preserves the given self, if set. If not set, and the function is a C++\n// member operator, self will be set to the first argument, which in turn will\n// be removed from the given args.\n//\n// A set with a single non-templated function goes through the same rules for\n// overloading resolution. This is to make sure that calls that have no viable\n// implicit conversion sequence are rejected even when an implicit conversion is\n// possible. Keeping the same behavior here for consistency and supporting\n// migrations so that the migrated callers from C++ remain valid.\nauto PerformCallToCppFunction(Context& context, SemIR::LocId loc_id,\n                              SemIR::CppOverloadSetId overload_set_id,\n                              SemIR::InstId self_id,\n                              llvm::ArrayRef<SemIR::InstId> arg_ids,\n                              bool is_operator_syntax) -> SemIR::InstId;\n\n// Checks and builds SemIR for a call to a C++ template name with arguments\n// `arg_ids`.\n//\n// Converts the arguments to a C++ template argument list and attempts to\n// instantiate a template specialization and import a declaration of it.\nauto PerformCallToCppTemplateName(Context& context, SemIR::LocId loc_id,\n                                  SemIR::ClangDeclId template_decl_id,\n                                  llvm::ArrayRef<SemIR::InstId> arg_ids)\n    -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_CALL_H_\n"
  },
  {
    "path": "toolchain/check/cpp/constant.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/constant.h\"\n\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/cpp/type_mapping.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/member_access.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n\nnamespace Carbon::Check {\n\nstatic auto MapLValueToConstant(Context& context, SemIR::LocId loc_id,\n                                const clang::APValue& ap_value,\n                                clang::QualType type) -> SemIR::ConstantId {\n  CARBON_CHECK(ap_value.isLValue(), \"not an LValue\");\n\n  const auto* value_decl =\n      ap_value.getLValueBase().get<const clang::ValueDecl*>();\n\n  if (!ap_value.hasLValuePath()) {\n    context.TODO(loc_id, \"lvalue has no path\");\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  if (ap_value.isLValueOnePastTheEnd()) {\n    context.TODO(loc_id, \"one-past-the-end lvalue\");\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  auto key = SemIR::ClangDeclKey::ForNonFunctionDecl(\n      // TODO: can this const_cast be avoided?\n      const_cast<clang::ValueDecl*>(value_decl));\n\n  auto inst_id = ImportCppDecl(context, loc_id, key);\n  if (ap_value.getLValuePath().empty()) {\n    return context.constant_values().Get(inst_id);\n  }\n\n  // Import the base type so that its fields can be accessed.\n  auto var_storage = context.insts().GetAs<SemIR::VarStorage>(inst_id);\n  // TODO: currently an error isn't reachable here because incomplete\n  // array types can't be imported. Once that changes, switch to\n  // `RequireCompleteType` and handle the error.\n  CompleteTypeOrCheckFail(context, var_storage.type_id);\n\n  clang::QualType qual_type = ap_value.getLValueBase().getType();\n  for (const auto& entry : ap_value.getLValuePath()) {\n    if (qual_type->isArrayType()) {\n      context.TODO(loc_id, \"lvalue path contains an array type\");\n    } else {\n      const auto* decl =\n          cast<clang::Decl>(entry.getAsBaseOrMember().getPointer());\n\n      const auto* field_decl = dyn_cast<clang::FieldDecl>(decl);\n      if (!field_decl) {\n        context.TODO(loc_id, \"lvalue path contains a base class subobject\");\n        return SemIR::ErrorInst::ConstantId;\n      }\n\n      auto field_inst_id =\n          ImportCppDecl(context, loc_id,\n                        SemIR::ClangDeclKey::ForNonFunctionDecl(\n                            const_cast<clang::FieldDecl*>(field_decl)));\n\n      if (field_inst_id == SemIR::ErrorInst::InstId) {\n        context.TODO(loc_id,\n                     \"unsupported field in lvalue path: \" +\n                         ap_value.getAsString(context.ast_context(), type));\n        return SemIR::ErrorInst::ConstantId;\n      }\n\n      const SemIR::FieldDecl& field_decl_inst =\n          context.insts().GetAs<SemIR::FieldDecl>(field_inst_id);\n\n      qual_type = field_decl->getType();\n      inst_id = PerformMemberAccess(context, loc_id, inst_id,\n                                    field_decl_inst.name_id);\n    }\n  }\n\n  return context.constant_values().Get(inst_id);\n}\n\nauto MapAPValueToConstant(Context& context, SemIR::LocId loc_id,\n                          const clang::APValue& ap_value, clang::QualType type,\n                          bool is_lvalue) -> SemIR::ConstantId {\n  SemIR::TypeId type_id = ImportCppType(context, loc_id, type).type_id;\n  if (!type_id.has_value()) {\n    return SemIR::ConstantId::NotConstant;\n  }\n\n  if (is_lvalue) {\n    return MapLValueToConstant(context, loc_id, ap_value, type);\n  } else if (type->isPointerType()) {\n    auto const_id = MapLValueToConstant(context, loc_id, ap_value, type);\n    auto inst_id = AddInst<SemIR::AddrOf>(\n        context, loc_id,\n        {.type_id = type_id,\n         .lvalue_id = context.constant_values().GetInstId(const_id)});\n    return context.constant_values().Get(inst_id);\n  } else if (ap_value.isInt()) {\n    if (type->isBooleanType()) {\n      auto value = SemIR::BoolValue::From(!ap_value.getInt().isZero());\n      return TryEvalInst(\n          context, SemIR::BoolLiteral{.type_id = type_id, .value = value});\n    } else {\n      CARBON_CHECK(type->isIntegralOrEnumerationType());\n\n      IntId int_id = context.ints().Add(ap_value.getInt());\n      return TryEvalInst(context,\n                         SemIR::IntValue{.type_id = type_id, .int_id = int_id});\n    }\n  } else if (ap_value.isFloat()) {\n    FloatId float_id = context.floats().Add(ap_value.getFloat());\n    return TryEvalInst(\n        context, SemIR::FloatValue{.type_id = type_id, .float_id = float_id});\n  } else {\n    // TODO: support other types.\n    context.TODO(loc_id, \"unsupported conversion to constant from APValue \" +\n                             ap_value.getAsString(context.ast_context(), type));\n    return SemIR::ErrorInst::ConstantId;\n  }\n}\n\nstatic auto MapAPValueToConstantForConstexpr(Context& context,\n                                             SemIR::LocId loc_id,\n                                             const clang::APValue& ap_value,\n                                             clang::QualType type)\n    -> SemIR::ConstantId {\n  bool is_lvalue = false;\n  if (type->isReferenceType()) {\n    is_lvalue = true;\n    type = type.getNonReferenceType();\n  }\n  return MapAPValueToConstant(context, loc_id, ap_value, type, is_lvalue);\n}\n\nauto EvalCppVarDecl(Context& context, SemIR::LocId loc_id,\n                    const clang::VarDecl* var_decl, SemIR::TypeId type_id)\n    -> SemIR::ConstantId {\n  // If the C++ global is constant, map it to a Carbon constant.\n  if (var_decl->isUsableInConstantExpressions(context.ast_context())) {\n    if (const auto* ap_value = var_decl->getEvaluatedValue()) {\n      auto clang_type = MapToCppType(context, type_id);\n      if (clang_type.isNull()) {\n        context.TODO(loc_id, \"failed to map C++ type to Carbon\");\n        return SemIR::ErrorInst::ConstantId;\n      }\n\n      return MapAPValueToConstantForConstexpr(context, loc_id, *ap_value,\n                                              clang_type);\n    }\n  }\n\n  return SemIR::ConstantId::NotConstant;\n}\n\nauto MapConstantToAPValue(Context& context, SemIR::InstId const_inst_id,\n                          clang::QualType param_type)\n    -> std::optional<clang::APValue> {\n  if (param_type->isIntegerType()) {\n    const bool is_signed = param_type->isSignedIntegerOrEnumerationType();\n    if (auto int_value =\n            context.insts().TryGetAs<SemIR::IntValue>(const_inst_id)) {\n      const auto& ap_int = context.ints().Get(int_value->int_id);\n      auto aps_int =\n          llvm::APSInt(ap_int, !is_signed)\n              .extOrTrunc(context.ast_context().getIntWidth(param_type));\n      return clang::APValue(aps_int);\n    } else if (auto bool_value = context.insts().TryGetAs<SemIR::BoolLiteral>(\n                   const_inst_id)) {\n      llvm::APInt ap_int(context.ast_context().getIntWidth(param_type),\n                         bool_value->value.ToBool(), is_signed);\n      auto aps_int =\n          llvm::APSInt(ap_int, !is_signed)\n              .extOrTrunc(context.ast_context().getIntWidth(param_type));\n      return clang::APValue(aps_int);\n    }\n  } else if (param_type->isFloatingType()) {\n    if (auto float_value =\n            context.insts().TryGetAs<SemIR::FloatValue>(const_inst_id)) {\n      const auto& ap_float = context.floats().Get(float_value->float_id);\n      return clang::APValue(ap_float);\n    }\n  }\n\n  // TODO: support additional parameter types.\n  return std::nullopt;\n}\n\nstatic auto ConvertArgToExpr(Context& context, SemIR::InstId arg_inst_id,\n                             clang::QualType param_type) -> clang::Expr* {\n  auto const_inst_id = context.constant_values().GetConstantInstId(arg_inst_id);\n  if (!const_inst_id.has_value()) {\n    return nullptr;\n  }\n\n  auto ap_value = MapConstantToAPValue(context, const_inst_id, param_type);\n  if (!ap_value.has_value()) {\n    return nullptr;\n  }\n\n  auto* opaque_value_expr = new (context.ast_context()) clang::OpaqueValueExpr(\n      clang::SourceLocation(), param_type, clang::VK_PRValue);\n\n  return clang::ConstantExpr::Create(context.ast_context(), opaque_value_expr,\n                                     *ap_value);\n}\n\nauto EvalCppCall(Context& context, SemIR::LocId loc_id,\n                 SemIR::ClangDeclId clang_decl_id, SemIR::InstBlockId args_id)\n    -> SemIR::ConstantId {\n  const auto& args = context.inst_blocks().Get(args_id);\n\n  auto* decl = context.clang_decls().Get(clang_decl_id).GetAsKey().decl;\n\n  auto* function_decl = cast<clang::FunctionDecl>(decl);\n\n  // Create expr for the function declaration.\n  auto* decl_ref_expr = clang::DeclRefExpr::Create(\n      context.ast_context(), /*QualifierLoc=*/clang::NestedNameSpecifierLoc(),\n      /*TemplateKWLoc=*/clang::SourceLocation(), function_decl,\n      /*RefersToEnclosingVariableOrCapture=*/false,\n      /*NameLoc=*/clang::SourceLocation(), function_decl->getType(),\n      clang::VK_LValue);\n\n  // Cast to a function pointer type.\n  auto function_ptr_type =\n      context.ast_context().getPointerType(function_decl->getType());\n  auto* implicit_cast_expr = clang::ImplicitCastExpr::Create(\n      context.ast_context(), function_ptr_type,\n      clang::CK_FunctionToPointerDecay, decl_ref_expr, nullptr,\n      clang::VK_PRValue, clang::FPOptionsOverride());\n\n  // Convert the arguments to exprs.\n  clang::SmallVector<clang::Expr*> arg_exprs;\n  for (auto [arg_inst_id, parm_var_decl] :\n       llvm::zip(args, function_decl->parameters())) {\n    if (auto* arg_expr =\n            ConvertArgToExpr(context, arg_inst_id, parm_var_decl->getType())) {\n      arg_exprs.push_back(arg_expr);\n    } else {\n      return SemIR::ConstantId::NotConstant;\n    }\n  }\n\n  // Create an expr to call the function.\n  auto* call_expr = clang::CallExpr::Create(\n      context.ast_context(), implicit_cast_expr, arg_exprs,\n      function_decl->getCallResultType(), clang::VK_PRValue,\n      /*RParenLoc=*/clang::SourceLocation(), clang::FPOptionsOverride());\n\n  // Evaluate the expr as a constant and map that to Carbon constant.\n  clang::Expr::EvalResult eval_result;\n  if (!call_expr->EvaluateAsConstantExpr(eval_result, context.ast_context())) {\n    // TODO: improve this diagnostic with information from `eval_result`.\n    CARBON_DIAGNOSTIC(CppConstexprEval, Error,\n                      \"failed to evaluate {0:consteval|constexpr} function \"\n                      \"call as a constant\",\n                      Diagnostics::BoolAsSelect);\n    context.emitter().Emit(loc_id, CppConstexprEval,\n                           function_decl->isConsteval());\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  return MapAPValueToConstantForConstexpr(context, loc_id, eval_result.Val,\n                                          function_decl->getCallResultType());\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/constant.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_CONSTANT_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_CONSTANT_H_\n\n#include <optional>\n\n#include \"clang/AST/APValue.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Converts an `APValue` to a Carbon `ConstantId`.\nauto MapAPValueToConstant(Context& context, SemIR::LocId loc_id,\n                          const clang::APValue& ap_value, clang::QualType type,\n                          bool is_lvalue) -> SemIR::ConstantId;\n\n// Converts a Carbon constant instruction to an `APValue`.\nauto MapConstantToAPValue(Context& context, SemIR::InstId const_inst_id,\n                          clang::QualType param_type)\n    -> std::optional<clang::APValue>;\n\n// Attempt to evaluate a C++ constexpr variable as a Carbon constant.\nauto EvalCppVarDecl(Context& context, SemIR::LocId loc_id,\n                    const clang::VarDecl* var_decl, SemIR::TypeId type_id)\n    -> SemIR::ConstantId;\n\n// Attempt to evaluate a call to a C++ constexpr/consteval function as a\n// Carbon constant.\nauto EvalCppCall(Context& context, SemIR::LocId loc_id,\n                 SemIR::ClangDeclId clang_decl_id, SemIR::InstBlockId args_id)\n    -> SemIR::ConstantId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_CONSTANT_H_\n"
  },
  {
    "path": "toolchain/check/cpp/context.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/context.h\"\n\n#include \"clang/AST/Mangle.h\"\n\nnamespace Carbon::Check {\n\nCppContext::CppContext(clang::CompilerInstance& instance,\n                       std::unique_ptr<clang::Parser> parser)\n    : ast_context_(&instance.getASTContext()),\n      sema_(&instance.getSema()),\n      parser_(std::move(parser)) {}\n\nCppContext::~CppContext() = default;\n\nauto CppContext::clang_mangle_context() -> clang::MangleContext& {\n  if (!clang_mangle_context_) {\n    clang_mangle_context_.reset(ast_context().createMangleContext());\n  }\n  return *clang_mangle_context_;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/context.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_CONTEXT_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_CONTEXT_H_\n\n#include <memory>\n\n#include \"clang/Basic/SourceLocation.h\"\n#include \"clang/Frontend/CompilerInstance.h\"\n#include \"clang/Frontend/FrontendAction.h\"\n#include \"clang/Parse/Parser.h\"\n#include \"common/check.h\"\n#include \"llvm/ADT/SmallVector.h\"\n\nnamespace Carbon::Check {\n\n// Context for C++ code during check.\n//\n// This stores state for a Clang AST and Sema, as well as any additional\n// information needed to perform mapping between Carbon and C++ types,\n// declarations, and similar values.\nclass CppContext {\n public:\n  explicit CppContext(clang::CompilerInstance& instance,\n                      std::unique_ptr<clang::Parser> parser);\n  ~CppContext();\n\n  auto ast_context() -> clang::ASTContext& { return *ast_context_; }\n  auto sema() -> clang::Sema& { return *sema_; }\n  auto parser() -> clang::Parser& { return *parser_; }\n\n  auto clang_mangle_context() -> clang::MangleContext&;\n\n  auto carbon_file_locations() -> llvm::SmallVector<clang::SourceLocation>& {\n    return carbon_file_locations_;\n  }\n\n private:\n  // The Clang AST context.\n  clang::ASTContext* ast_context_;\n\n  // The Clang semantic analysis engine.\n  clang::Sema* sema_;\n\n  // The Clang parser.\n  std::unique_ptr<clang::Parser> parser_;\n\n  // Per-Carbon-file start locations for corresponding Clang source buffers.\n  // Owned and managed by code in location.cpp.\n  llvm::SmallVector<clang::SourceLocation> carbon_file_locations_;\n\n  // The Clang mangle context for the target in the ASTContext.\n  std::unique_ptr<clang::MangleContext> clang_mangle_context_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_CONTEXT_H_\n"
  },
  {
    "path": "toolchain/check/cpp/custom_type_mapping.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/custom_type_mapping.h\"\n\n#include \"clang/AST/DeclCXX.h\"\n#include \"clang/AST/DeclTemplate.h\"\n#include \"llvm/ADT/STLExtras.h\"\n#include \"llvm/ADT/StringRef.h\"\n\nnamespace Carbon::Check {\n\n// A small, lightweight library of AST matchers. Unlike clang's ASTMatchers,\n// this avoids heap allocations and is suitable for one-off matching rather than\n// matching against a whole AST.\nnamespace Matchers {\n// A matcher for a type T is just a function that takes a T and returns whether\n// it matched. Matchers should be invoked immediately, and are not expected to\n// outlive the arguments of the call that created them.\n// TODO: We could avoid the indirect calls by making the below functions be\n// templated on the inner matcher.\ntemplate <typename T>\nusing Matcher = llvm::function_ref<auto(T)->bool>;\n\n// Returns a matcher for class declarations that determines whether the given\n// class is a class template specialization in namespace std with the specified\n// name and template arguments matching the given predicate.\nstatic auto StdClassTemplate(\n    llvm::StringLiteral name,\n    Matcher<const clang::TemplateArgumentList&> args_matcher\n    [[clang::lifetimebound]]) -> auto {\n  return [=](const clang::CXXRecordDecl* class_decl) -> bool {\n    const auto* specialization =\n        dyn_cast<clang::ClassTemplateSpecializationDecl>(class_decl);\n    const auto* identifier = class_decl->getIdentifier();\n    return specialization && identifier && identifier->isStr(name) &&\n           specialization->isInStdNamespace() &&\n           args_matcher(specialization->getTemplateArgs());\n  };\n}\n\n// Returns a matcher that matches types if they are class types whose class\n// matches the given matcher.\nstatic auto Class(Matcher<const clang::CXXRecordDecl*> class_matcher\n                  [[clang::lifetimebound]]) -> auto {\n  return [=](clang::QualType type) -> bool {\n    const auto* class_decl = type->getAsCXXRecordDecl();\n    return !type.hasQualifiers() && class_decl && class_matcher(class_decl);\n  };\n}\n\n// Returns a matcher that determines whether the given template argument is a\n// type matching the given predicate.\nstatic auto TypeTemplateArgument(Matcher<clang::QualType> type_matcher\n                                 [[clang::lifetimebound]]) -> auto {\n  return [=](clang::TemplateArgument arg) -> bool {\n    return arg.getKind() == clang::TemplateArgument::Type &&\n           type_matcher(arg.getAsType());\n  };\n}\n\n// A matcher that determines whether the given type is `char`.\nstatic auto Char(clang::QualType type) -> bool {\n  return !type.hasQualifiers() && type->isCharType();\n}\n\n// Returns a matcher that determines whether the given template argument list\n// matches the given sequence of template argument matchers.\nstatic auto TemplateArgumentsAre(\n    std::initializer_list<Matcher<clang::TemplateArgument>> arg_matchers\n    [[clang::lifetimebound]]) -> auto {\n  return [=](const clang::TemplateArgumentList& args) -> bool {\n    if (args.size() != arg_matchers.size()) {\n      return false;\n    }\n    for (auto [arg, matcher] : llvm::zip_equal(args.asArray(), arg_matchers)) {\n      if (!matcher(arg)) {\n        return false;\n      }\n    }\n    return true;\n  };\n}\n\n// A matcher for `std::char_traits<char>`.\nstatic auto StdCharTraitsChar(clang::QualType type) -> bool {\n  return Class(StdClassTemplate(\n      \"char_traits\", TemplateArgumentsAre({TypeTemplateArgument(Char)})))(type);\n}\n\n// A matcher for `std::string_view`.\nstatic auto StdStringView(const clang::CXXRecordDecl* record_decl) -> bool {\n  return StdClassTemplate(\n      \"basic_string_view\",\n      TemplateArgumentsAre({TypeTemplateArgument(Char),\n                            TypeTemplateArgument(StdCharTraitsChar)}))(\n      record_decl);\n}\n}  // end namespace Matchers\n\nauto GetCustomCppTypeMapping(const clang::CXXRecordDecl* record_decl)\n    -> CustomCppTypeMapping {\n  if (Matchers::StdStringView(record_decl)) {\n    return CustomCppTypeMapping::Str;\n  }\n\n  return CustomCppTypeMapping::None;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/custom_type_mapping.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_CUSTOM_TYPE_MAPPING_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_CUSTOM_TYPE_MAPPING_H_\n\n#include \"clang/AST/DeclCXX.h\"\n\nnamespace Carbon::Check {\n\n// Carbon types that have a custom mapping from C++.\nenum class CustomCppTypeMapping : uint8_t {\n  // None.\n  None,\n\n  // The Carbon `Str` type, which maps to `std::string_view`.\n  Str,\n};\n\n// Determines whether record_decl is a C++ class that has a custom mapping into\n// Carbon, and if so, returns the corresponding Carbon type. Otherwise returns\n// None.\nauto GetCustomCppTypeMapping(const clang::CXXRecordDecl* record_decl)\n    -> CustomCppTypeMapping;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_CUSTOM_TYPE_MAPPING_H_\n"
  },
  {
    "path": "toolchain/check/cpp/generate_ast.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/generate_ast.h\"\n\n#include <memory>\n#include <string>\n\n#include \"clang/AST/ASTContext.h\"\n#include \"clang/Basic/FileManager.h\"\n#include \"clang/CodeGen/ModuleBuilder.h\"\n#include \"clang/Frontend/CompilerInstance.h\"\n#include \"clang/Frontend/CompilerInvocation.h\"\n#include \"clang/Frontend/FrontendAction.h\"\n#include \"clang/Frontend/TextDiagnostic.h\"\n#include \"clang/Lex/PreprocessorOptions.h\"\n#include \"clang/Parse/Parser.h\"\n#include \"clang/Sema/ExternalSemaSource.h\"\n#include \"clang/Sema/MultiplexExternalSemaSource.h\"\n#include \"clang/Sema/Sema.h\"\n#include \"common/check.h\"\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/ADT/IntrusiveRefCntPtr.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/raw_ostream.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/cpp_file.h\"\n\nnamespace Carbon::Check {\n\n// Add a line marker directive pointing at the location of the `import Cpp`\n// declaration in the Carbon source file. This will cause Clang's diagnostics\n// machinery to track and report the location in Carbon code where the import\n// was written.\nstatic auto GenerateLineMarker(Context& context, llvm::raw_ostream& out,\n                               int line) {\n  out << \"# \" << line << \" \\\"\"\n      << FormatEscaped(context.tokens().source().filename()) << \"\\\"\\n\";\n}\n\n// Generates C++ file contents to #include all requested imports.\nstatic auto GenerateCppIncludesHeaderCode(\n    Context& context, llvm::ArrayRef<Parse::Tree::PackagingNames> imports)\n    -> std::string {\n  std::string code;\n  llvm::raw_string_ostream code_stream(code);\n  for (const Parse::Tree::PackagingNames& import : imports) {\n    if (import.inline_body_id.has_value()) {\n      // Expand `import Cpp inline \"code\";` directly into the specified code.\n      auto code_token = context.parse_tree().node_token(import.inline_body_id);\n\n      // Compute the line number on which the C++ code starts. Usually the code\n      // is specified as a block string literal and starts on the line after the\n      // start of the string token.\n      // TODO: Determine if this is a block string literal without calling\n      // `GetTokenText`, which re-lexes the string.\n      int line = context.tokens().GetLineNumber(code_token);\n      if (context.tokens().GetTokenText(code_token).contains('\\n')) {\n        ++line;\n      }\n\n      GenerateLineMarker(context, code_stream, line);\n      code_stream << context.string_literal_values().Get(\n                         context.tokens().GetStringLiteralValue(code_token))\n                  << \"\\n\";\n      // TODO: Inject a clang pragma here to produce an error if there are\n      // unclosed scopes at the end of this inline C++ fragment.\n    } else if (import.library_id.has_value()) {\n      // Translate `import Cpp library \"foo.h\";` into `#include \"foo.h\"`.\n      GenerateLineMarker(context, code_stream,\n                         context.tokens().GetLineNumber(\n                             context.parse_tree().node_token(import.node_id)));\n      auto name = context.string_literal_values().Get(import.library_id);\n      if (name.starts_with('<') && name.ends_with('>')) {\n        code_stream << \"#include <\"\n                    << FormatEscaped(name.drop_front().drop_back()) << \">\\n\";\n      } else {\n        code_stream << \"#include \\\"\" << FormatEscaped(name) << \"\\\"\\n\";\n      }\n    }\n  }\n\n  // Inject a declaration of placement operator new, because the code we\n  // generate in thunks depends on it for placement new expressions. Clang has\n  // special-case logic for lowering a new-expression using this, so a\n  // definition is not required.\n  // TODO: This is a hack. We should be able to directly generate Clang AST to\n  // construct objects in-place without this.\n  // TODO: Once we can rely on libc++ being available, consider including\n  // `<__new/placement_new_delete.h>` instead.\n  code_stream << R\"(# 1 \"<carbon-internal>\"\n#undef constexpr\n#if __cplusplus > 202302L\nconstexpr\n#endif\n#undef void\n#undef operator\n#undef new\nvoid* operator new(__SIZE_TYPE__, void*)\n#if __cplusplus < 201103L\n#undef throw\nthrow()\n#else\n#undef noexcept\nnoexcept\n#endif\n;\n)\";\n\n  return code;\n}\n\n// Adds the given source location and an `ImportIRInst` referring to it in\n// `ImportIRId::Cpp`.\nstatic auto AddImportIRInst(SemIR::File& file,\n                            clang::SourceLocation clang_source_loc)\n    -> SemIR::ImportIRInstId {\n  SemIR::ClangSourceLocId clang_source_loc_id =\n      file.clang_source_locs().Add(clang_source_loc);\n  return file.import_ir_insts().Add(SemIR::ImportIRInst(clang_source_loc_id));\n}\n\nnamespace {\n\n// Used to convert Clang diagnostics to Carbon diagnostics.\n//\n// Handling of Clang notes is a little subtle: as far as Clang is concerned,\n// notes are separate diagnostics, not connected to the error or warning that\n// precedes them. But in Carbon's diagnostics system, notes are part of the\n// enclosing diagnostic. To handle this, we buffer Clang diagnostics until we\n// reach a point where we know we're not in the middle of a diagnostic, and then\n// emit a diagnostic along with all of its notes. This is triggered when adding\n// or removing a Carbon context note, which could otherwise get attached to the\n// wrong C++ diagnostics, and at the end of the Carbon program.\nclass CarbonClangDiagnosticConsumer : public clang::DiagnosticConsumer {\n public:\n  // Creates an instance with the location that triggers calling Clang. The\n  // `context` is not stored here, and the diagnostics consumer is expected to\n  // outlive it.\n  explicit CarbonClangDiagnosticConsumer(\n      Context& context, std::shared_ptr<clang::CompilerInvocation> invocation)\n      : sem_ir_(&context.sem_ir()),\n        emitter_(&context.emitter()),\n        invocation_(std::move(invocation)) {\n    emitter_->AddFlushFn([this] { EmitDiagnostics(); });\n  }\n\n  ~CarbonClangDiagnosticConsumer() override {\n    // Do not inspect `emitter_` here; it's typically destroyed before the\n    // consumer is.\n    // TODO: If Clang produces diagnostics after check finishes, they'll get\n    // added to the list of pending diagnostics and never emitted.\n    CARBON_CHECK(diagnostic_infos_.empty(),\n                 \"Missing flush before destroying diagnostic consumer\");\n  }\n\n  // Generates a Carbon warning for each Clang warning and a Carbon error for\n  // each Clang error or fatal.\n  auto HandleDiagnostic(clang::DiagnosticsEngine::Level diag_level,\n                        const clang::Diagnostic& info) -> void override {\n    DiagnosticConsumer::HandleDiagnostic(diag_level, info);\n\n    SemIR::ImportIRInstId clang_import_ir_inst_id =\n        AddImportIRInst(*sem_ir_, info.getLocation());\n\n    llvm::SmallString<256> message;\n    info.FormatDiagnostic(message);\n\n    // Render a code snippet including any highlighted ranges and fixit hints.\n    // TODO: Also include the #include stack and macro expansion stack in the\n    // diagnostic output in some way.\n    RawStringOstream snippet_stream;\n    if (!info.hasSourceManager()) {\n      // If we don't have a source manager, this is an error from early in the\n      // frontend. Don't produce a snippet.\n      CARBON_CHECK(info.getLocation().isInvalid());\n    } else {\n      CodeContextRenderer(snippet_stream, invocation_->getLangOpts(),\n                          invocation_->getDiagnosticOpts())\n          .emitDiagnostic(\n              clang::FullSourceLoc(info.getLocation(), info.getSourceManager()),\n              diag_level, message, info.getRanges(), info.getFixItHints());\n    }\n\n    diagnostic_infos_.push_back({.level = diag_level,\n                                 .import_ir_inst_id = clang_import_ir_inst_id,\n                                 .message = message.str().str(),\n                                 .snippet = snippet_stream.TakeStr()});\n  }\n\n  // Returns the diagnostic to use for a given Clang diagnostic level.\n  static auto GetDiagnostic(clang::DiagnosticsEngine::Level level)\n      -> const Diagnostics::DiagnosticBase<std::string>& {\n    switch (level) {\n      case clang::DiagnosticsEngine::Ignored: {\n        CARBON_FATAL(\"Emitting an ignored diagnostic\");\n        break;\n      }\n      case clang::DiagnosticsEngine::Note: {\n        CARBON_DIAGNOSTIC(CppInteropParseNote, Note, \"{0}\", std::string);\n        return CppInteropParseNote;\n      }\n      case clang::DiagnosticsEngine::Remark:\n      case clang::DiagnosticsEngine::Warning: {\n        // TODO: Add a distinct Remark level to Carbon diagnostics, and stop\n        // mapping remarks to warnings.\n        CARBON_DIAGNOSTIC(CppInteropParseWarning, Warning, \"{0}\", std::string);\n        return CppInteropParseWarning;\n      }\n      case clang::DiagnosticsEngine::Error:\n      case clang::DiagnosticsEngine::Fatal: {\n        CARBON_DIAGNOSTIC(CppInteropParseError, Error, \"{0}\", std::string);\n        return CppInteropParseError;\n      }\n    }\n  }\n\n  // Outputs Carbon diagnostics based on the collected Clang diagnostics. Must\n  // be called after the AST is set in the context.\n  auto EmitDiagnostics() -> void {\n    CARBON_CHECK(\n        sem_ir_->cpp_file(),\n        \"Attempted to emit C++ diagnostics before the C++ file is set\");\n\n    for (size_t i = 0; i != diagnostic_infos_.size(); ++i) {\n      const ClangDiagnosticInfo& info = diagnostic_infos_[i];\n      auto builder = emitter_->Build(SemIR::LocId(info.import_ir_inst_id),\n                                     GetDiagnostic(info.level), info.message);\n      builder.OverrideSnippet(info.snippet);\n      for (; i + 1 < diagnostic_infos_.size() &&\n             diagnostic_infos_[i + 1].level == clang::DiagnosticsEngine::Note;\n           ++i) {\n        const ClangDiagnosticInfo& note_info = diagnostic_infos_[i + 1];\n        builder\n            .Note(SemIR::LocId(note_info.import_ir_inst_id),\n                  GetDiagnostic(note_info.level), note_info.message)\n            .OverrideSnippet(note_info.snippet);\n      }\n      // TODO: This will apply all current Carbon annotation functions. We\n      // should instead track how Clang's context notes and Carbon's annotation\n      // functions are interleaved, and interleave the notes in the same order.\n      builder.Emit();\n    }\n    diagnostic_infos_.clear();\n  }\n\n private:\n  // A diagnostics renderer based on clang's TextDiagnostic that captures just\n  // the code context (the snippet).\n  class CodeContextRenderer : public clang::TextDiagnostic {\n   protected:\n    using TextDiagnostic::TextDiagnostic;\n\n    void emitDiagnosticMessage(\n        clang::FullSourceLoc /*loc*/, clang::PresumedLoc /*ploc*/,\n        clang::DiagnosticsEngine::Level /*level*/, llvm::StringRef /*message*/,\n        llvm::ArrayRef<clang::CharSourceRange> /*ranges*/,\n        clang::DiagOrStoredDiag /*info*/) override {}\n    void emitDiagnosticLoc(\n        clang::FullSourceLoc /*loc*/, clang::PresumedLoc /*ploc*/,\n        clang::DiagnosticsEngine::Level /*level*/,\n        llvm::ArrayRef<clang::CharSourceRange> /*ranges*/) override {}\n\n    // emitCodeContext is inherited from clang::TextDiagnostic.\n\n    void emitIncludeLocation(clang::FullSourceLoc /*loc*/,\n                             clang::PresumedLoc /*ploc*/) override {}\n    void emitImportLocation(clang::FullSourceLoc /*loc*/,\n                            clang::PresumedLoc /*ploc*/,\n                            llvm::StringRef /*module_name*/) override {}\n    void emitBuildingModuleLocation(clang::FullSourceLoc /*loc*/,\n                                    clang::PresumedLoc /*ploc*/,\n                                    llvm::StringRef /*module_name*/) override {}\n\n    // beginDiagnostic and endDiagnostic are inherited from\n    // clang::TextDiagnostic in case it wants to do any setup / teardown work.\n  };\n\n  // Information on a Clang diagnostic that can be converted to a Carbon\n  // diagnostic.\n  struct ClangDiagnosticInfo {\n    // The Clang diagnostic level.\n    clang::DiagnosticsEngine::Level level;\n\n    // The ID of the ImportIR instruction referring to the Clang source\n    // location.\n    SemIR::ImportIRInstId import_ir_inst_id;\n\n    // The Clang diagnostic textual message.\n    std::string message;\n\n    // The code snippet produced by clang.\n    std::string snippet;\n  };\n\n  // The Carbon file that this C++ compilation is attached to.\n  SemIR::File* sem_ir_;\n\n  // The diagnostic emitter that we're emitting diagnostics into.\n  DiagnosticEmitterBase* emitter_;\n\n  // The compiler invocation that is producing the diagnostics.\n  std::shared_ptr<clang::CompilerInvocation> invocation_;\n\n  // Collects the information for all Clang diagnostics to be converted to\n  // Carbon diagnostics after the context has been initialized with the Clang\n  // AST.\n  llvm::SmallVector<ClangDiagnosticInfo> diagnostic_infos_;\n};\n\n// A wrapper around a clang::CompilerInvocation that allows us to make a shallow\n// copy of most of the invocation and only make a deep copy of the parts that we\n// want to change.\n//\n// clang::CowCompilerInvocation almost allows this, but doesn't derive from\n// CompilerInvocation or support shallow copies from a CompilerInvocation, so is\n// not useful to us as we can't build an ASTUnit from it.\nclass ShallowCopyCompilerInvocation : public clang::CompilerInvocation {\n public:\n  explicit ShallowCopyCompilerInvocation(\n      const clang::CompilerInvocation& invocation) {\n    shallow_copy_assign(invocation);\n\n    // Make a deep copy of options that we modify.\n    FrontendOpts = std::make_shared<clang::FrontendOptions>(*FrontendOpts);\n    PPOpts = std::make_shared<clang::PreprocessorOptions>(*PPOpts);\n  }\n};\n\nclass CarbonExternalASTSource : public clang::ExternalASTSource {\n public:\n  explicit CarbonExternalASTSource(Context* context,\n                                   clang::ASTContext* ast_context)\n      : context_(context), ast_context_(ast_context) {}\n\n  auto FindExternalVisibleDeclsByName(\n      const clang::DeclContext* decl_context, clang::DeclarationName decl_name,\n      const clang::DeclContext* original_decl_context) -> bool override;\n\n  auto StartTranslationUnit(clang::ASTConsumer* consumer) -> void override;\n\n private:\n  Check::Context* context_;\n  clang::ASTContext* ast_context_;\n  clang::NamespaceDecl* carbon_cpp_namespace_ = nullptr;\n};\n\nvoid CarbonExternalASTSource::StartTranslationUnit(\n    clang::ASTConsumer* /*Consumer*/) {\n  auto& translation_unit = *ast_context_->getTranslationUnitDecl();\n  // Mark the translation unit as having external storage so we get a query for\n  // the `Carbon` namespace in the top level/translation unit scope.\n  translation_unit.setHasExternalVisibleStorage();\n}\n\n// Map a Carbon entity to a Clang NamedDecl.\nstatic auto MapInstIdToClangDecl(Context& context,\n                                 clang::ASTContext& ast_context,\n                                 clang::DeclContext& decl_context,\n                                 LookupResult lookup) -> clang::NamedDecl* {\n  auto target_inst_id = lookup.scope_result.target_inst_id();\n  if (auto target_inst =\n          context.insts().TryGetAs<SemIR::Namespace>(target_inst_id)) {\n    auto& name_scope = context.name_scopes().Get(target_inst->name_scope_id);\n    auto* identifier_info =\n        GetClangIdentifierInfo(context, name_scope.name_id());\n    // TODO: Don't immediately use the decl_context - build any intermediate\n    // namespaces iteratively.\n    // Eventually add a mapping and use that/populate it/keep it up to date.\n    // decl_context could be prepopulated in that mapping and not passed\n    // explicitly to MapInstIdToClangDecl.\n    return clang::NamespaceDecl::Create(\n        ast_context, &decl_context, false, clang::SourceLocation(),\n        clang::SourceLocation(), identifier_info, nullptr, false);\n  }\n  return nullptr;\n}\n\nauto CarbonExternalASTSource::FindExternalVisibleDeclsByName(\n    const clang::DeclContext* decl_context, clang::DeclarationName decl_name,\n    const clang::DeclContext* /*OriginalDC*/) -> bool {\n  if (decl_context != carbon_cpp_namespace_) {\n    if (decl_context->getDeclKind() != clang::Decl::Kind::TranslationUnit) {\n      return false;\n    }\n\n    static const llvm::StringLiteral carbon_namespace_name = \"Carbon\";\n    if (auto* identifier = decl_name.getAsIdentifierInfo();\n        !identifier || !identifier->isStr(carbon_namespace_name)) {\n      return false;\n    }\n\n    // Build the top level 'Carbon' namespace\n    auto& ast_context = decl_context->getParentASTContext();\n    auto& mutable_tu_decl_context = *ast_context.getTranslationUnitDecl();\n    carbon_cpp_namespace_ = clang::NamespaceDecl::Create(\n        ast_context, &mutable_tu_decl_context, false, clang::SourceLocation(),\n        clang::SourceLocation(), &ast_context.Idents.get(carbon_namespace_name),\n        nullptr, false);\n    carbon_cpp_namespace_->setHasExternalVisibleStorage();\n    SetExternalVisibleDeclsForName(decl_context, decl_name,\n                                   {carbon_cpp_namespace_});\n    return true;\n  }\n\n  // Lookup the name in Carbon package scope\n\n  llvm::SmallVector<Check::LookupScope> lookup_scopes;\n\n  // LocId::None seems fine here because we shouldn't produce any diagnostics\n  // here - completeness should've been checked by clang before this point.\n  if (!AppendLookupScopesForConstant(\n          *context_, SemIR::LocId::None,\n          context_->constant_values().Get(SemIR::Namespace::PackageInstId),\n          SemIR::ConstantId::None, &lookup_scopes)) {\n    return false;\n  }\n\n  auto* identifier = decl_name.getAsIdentifierInfo();\n  if (!identifier) {\n    // Only supporting identifiers for now.\n    return false;\n  }\n\n  auto name_id = AddIdentifierName(*context_, identifier->getName());\n\n  // `required=false` so Carbon doesn't diagnose a failure, let Clang diagnose\n  // it or even SFINAE.\n  LookupResult result =\n      LookupQualifiedName(*context_, SemIR::LocId::None, name_id, lookup_scopes,\n                          /*required=*/false);\n  if (!result.scope_result.is_found()) {\n    return false;\n  }\n\n  // Map the found Carbon entity to a Clang NamedDecl.\n  auto* clang_decl = MapInstIdToClangDecl(*context_, *ast_context_,\n                                          *carbon_cpp_namespace_, result);\n  if (!clang_decl) {\n    return false;\n  }\n\n  SetExternalVisibleDeclsForName(decl_context, decl_name, {clang_decl});\n  return true;\n}\n\n// An action and a set of registered Clang callbacks used to generate an AST\n// from a set of Cpp imports.\nclass GenerateASTAction : public clang::ASTFrontendAction {\n public:\n  explicit GenerateASTAction(Context& context) : context_(&context) {}\n\n protected:\n  auto CreateASTConsumer(clang::CompilerInstance& clang_instance,\n                         llvm::StringRef /*file*/)\n      -> std::unique_ptr<clang::ASTConsumer> override {\n    auto& cpp_file = *context_->sem_ir().cpp_file();\n    if (!cpp_file.llvm_context()) {\n      return std::make_unique<clang::ASTConsumer>();\n    }\n    auto code_generator =\n        std::unique_ptr<clang::CodeGenerator>(clang::CreateLLVMCodeGen(\n            cpp_file.diagnostics(), context_->sem_ir().filename(),\n            clang_instance.getVirtualFileSystemPtr(),\n            clang_instance.getHeaderSearchOpts(),\n            clang_instance.getPreprocessorOpts(),\n            clang_instance.getCodeGenOpts(), *cpp_file.llvm_context()));\n    cpp_file.SetCodeGenerator(code_generator.get());\n    return code_generator;\n  }\n\n  auto BeginSourceFileAction(clang::CompilerInstance& /*clang_instance*/)\n      -> bool override {\n    // TODO: `clang.getPreprocessor().enableIncrementalProcessing();` to avoid\n    // the TU scope getting torn down before we're done parsing macros.\n    return true;\n  }\n\n  // Parse the imports and inline C++ fragments. This is notionally very similar\n  // to `clang::ParseAST`, which `ASTFrontendAction::ExecuteAction` calls, but\n  // this version doesn't parse C++20 modules and stops just before reaching the\n  // end of the translation unit.\n  auto ExecuteAction() -> void override {\n    clang::CompilerInstance& clang_instance = getCompilerInstance();\n    clang_instance.createSema(getTranslationUnitKind(),\n                              /*CompletionConsumer=*/nullptr);\n\n    auto parser_ptr = std::make_unique<clang::Parser>(\n        clang_instance.getPreprocessor(), clang_instance.getSema(),\n        /*SkipFunctionBodies=*/false);\n    auto& parser = *parser_ptr;\n\n    clang_instance.getPreprocessor().EnterMainSourceFile();\n    if (auto* source = clang_instance.getASTContext().getExternalSource()) {\n      source->StartTranslationUnit(&clang_instance.getASTConsumer());\n    }\n\n    parser.Initialize();\n    clang_instance.getSema().ActOnStartOfTranslationUnit();\n\n    context_->set_cpp_context(\n        std::make_unique<CppContext>(clang_instance, std::move(parser_ptr)));\n\n    // Don't allow C++20 module declarations in inline Cpp code fragments.\n    auto module_import_state = clang::Sema::ModuleImportState::NotACXX20Module;\n\n    // Parse top-level declarations until we see EOF. Do not parse EOF, as that\n    // will cause the parser to end the translation unit prematurely.\n    while (parser.getCurToken().isNot(clang::tok::eof)) {\n      clang::Parser::DeclGroupPtrTy decl_group;\n      bool eof = parser.ParseTopLevelDecl(decl_group, module_import_state);\n      CARBON_CHECK(!eof);\n      if (decl_group && !clang_instance.getASTConsumer().HandleTopLevelDecl(\n                            decl_group.get())) {\n        break;\n      }\n    }\n  }\n\n private:\n  Context* context_;\n};\n\n}  // namespace\n\nauto GenerateAst(Context& context,\n                 llvm::ArrayRef<Parse::Tree::PackagingNames> imports,\n                 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n                 llvm::LLVMContext* llvm_context,\n                 std::shared_ptr<clang::CompilerInvocation> base_invocation)\n    -> bool {\n  CARBON_CHECK(!context.cpp_context());\n  CARBON_CHECK(!context.sem_ir().cpp_file());\n\n  auto invocation =\n      std::make_shared<ShallowCopyCompilerInvocation>(*base_invocation);\n\n  // Ask Clang to not leak memory.\n  invocation->getFrontendOpts().DisableFree = false;\n\n  // Build a diagnostics engine.\n  llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(\n      clang::CompilerInstance::createDiagnostics(\n          *fs, invocation->getDiagnosticOpts(),\n          new CarbonClangDiagnosticConsumer(context, invocation),\n          /*ShouldOwnClient=*/true));\n\n  // Extract the input from the frontend invocation and make sure it makes\n  // sense.\n  const auto& inputs = invocation->getFrontendOpts().Inputs;\n  CARBON_CHECK(inputs.size() == 1 &&\n               inputs[0].getKind().getLanguage() == clang::Language::CXX &&\n               inputs[0].getKind().getFormat() == clang::InputKind::Source);\n  llvm::StringRef file_name = inputs[0].getFile();\n\n  // Remap the imports file name to the corresponding `#include`s.\n  // TODO: Modify the frontend options to specify this memory buffer as input\n  // instead of remapping the file.\n  std::string includes = GenerateCppIncludesHeaderCode(context, imports);\n  auto includes_buffer =\n      llvm::MemoryBuffer::getMemBufferCopy(includes, file_name);\n  invocation->getPreprocessorOpts().addRemappedFile(file_name,\n                                                    includes_buffer.release());\n\n  auto clang_instance_ptr =\n      std::make_unique<clang::CompilerInstance>(invocation);\n  auto& clang_instance = *clang_instance_ptr;\n  context.sem_ir().set_cpp_file(std::make_unique<SemIR::CppFile>(\n      std::move(clang_instance_ptr), llvm_context));\n\n  clang_instance.setDiagnostics(diags);\n  clang_instance.setVirtualFileSystem(fs);\n  clang_instance.createFileManager();\n  clang_instance.createSourceManager();\n  if (!clang_instance.createTarget()) {\n    return false;\n  }\n\n  GenerateASTAction action(context);\n  if (!action.BeginSourceFile(clang_instance, inputs[0])) {\n    return false;\n  }\n\n  auto& ast = clang_instance.getASTContext();\n  // TODO: Clang's modules support is implemented as an ExternalASTSource\n  // (ASTReader) and there's no multiplexing support for ExternalASTSources at\n  // the moment - so registering CarbonExternalASTSource breaks Clang modules\n  // support. Implement multiplexing support (possibly in Clang) to restore\n  // modules functionality.\n  ast.setExternalSource(\n      llvm::makeIntrusiveRefCnt<CarbonExternalASTSource>(&context, &ast));\n\n  if (llvm::Error error = action.Execute()) {\n    // `Execute` currently never fails, but its contract allows it to.\n    context.TODO(SemIR::LocId::None, \"failed to execute clang action: \" +\n                                         llvm::toString(std::move(error)));\n    return false;\n  }\n\n  // Flush any diagnostics. We know we're not part-way through emitting a\n  // diagnostic now.\n  context.emitter().Flush();\n\n  return true;\n}\n\nauto FinishAst(Context& context) -> void {\n  if (!context.cpp_context()) {\n    return;\n  }\n\n  context.cpp_context()->sema().ActOnEndOfTranslationUnit();\n\n  // We don't call FrontendAction::EndSourceFile, because that destroys the AST.\n  context.set_cpp_context(nullptr);\n\n  context.emitter().Flush();\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/generate_ast.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_GENERATE_AST_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_GENERATE_AST_H_\n\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/IntrusiveRefCntPtr.h\"\n#include \"llvm/Support/VirtualFileSystem.h\"\n#include \"toolchain/check/context.h\"\n\nnamespace Carbon::Check {\n\n// Generates a Clang AST for the given C++ imports and sets it as the context's\n// `cpp_context` and the SemIR's `cpp_file`. Returns a bool that represents\n// whether compilation was successful.\nauto GenerateAst(Context& context,\n                 llvm::ArrayRef<Parse::Tree::PackagingNames> imports,\n                 llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n                 llvm::LLVMContext* llvm_context,\n                 std::shared_ptr<clang::CompilerInvocation> base_invocation)\n    -> bool;\n\n// Finishes AST generation for the given checking context. Performs end of file\n// steps such as template instantiation and warning on unused declarations.\nauto FinishAst(Context& context) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_GENERATE_AST_H_\n"
  },
  {
    "path": "toolchain/check/cpp/impl_lookup.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/impl_lookup.h\"\n\n#include \"clang/Sema/Sema.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/cpp/location.h\"\n#include \"toolchain/check/cpp/overload_resolution.h\"\n#include \"toolchain/check/custom_witness.h\"\n#include \"toolchain/check/impl.h\"\n#include \"toolchain/check/impl_lookup.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// If the given type is a C++ class type, returns the corresponding class\n// declaration. Otherwise returns nullptr.\n// TODO: Handle qualified types.\nstatic auto TypeAsClassDecl(Context& context,\n                            SemIR::ConstantId query_self_const_id)\n    -> clang::CXXRecordDecl* {\n  auto self_inst_id = context.constant_values().GetInstId(query_self_const_id);\n  auto class_type = context.insts().TryGetAs<SemIR::ClassType>(self_inst_id);\n  if (!class_type) {\n    // Not a class.\n    return nullptr;\n  }\n\n  SemIR::NameScopeId class_scope_id =\n      context.classes().Get(class_type->class_id).scope_id;\n  if (!class_scope_id.has_value()) {\n    return nullptr;\n  }\n\n  const auto& scope = context.name_scopes().Get(class_scope_id);\n  auto decl_id = scope.clang_decl_context_id();\n  if (!decl_id.has_value()) {\n    return nullptr;\n  }\n\n  return dyn_cast<clang::CXXRecordDecl>(\n      context.clang_decls().Get(decl_id).key.decl);\n}\n\nnamespace {\nstruct DeclInfo {\n  // If null, no C++ decl was found and no witness can be created.\n  clang::NamedDecl* decl = nullptr;\n  SemIR::ClangDeclKey::Signature signature;\n};\n}  // namespace\n\n// Finds the InstId for the C++ function that is called by a specific interface.\n// Returns SemIR::InstId::None if a C++ function is not found, and\n// SemIR::ErrorInst::InstId if an error occurs.\nstatic auto GetFunctionId(Context& context, SemIR::LocId loc_id,\n                          DeclInfo decl_info,\n                          const TypeStructure* best_impl_type_structure,\n                          SemIR::LocId best_impl_loc_id) -> SemIR::InstId {\n  if (!decl_info.decl) {\n    // The C++ type is not able to implement the interface.\n    return SemIR::InstId::None;\n  }\n\n  auto* cpp_fn = cast<clang::FunctionDecl>(decl_info.decl);\n\n  if (context.clang_sema().DiagnoseUseOfOverloadedDecl(\n          cpp_fn, GetCppLocation(context, loc_id))) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto fn_id =\n      ImportCppFunctionDecl(context, loc_id, cpp_fn, decl_info.signature);\n  if (fn_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ErrorInst::InstId;\n  }\n  CheckCppOverloadAccess(\n      context, loc_id, clang::DeclAccessPair::make(cpp_fn, cpp_fn->getAccess()),\n      context.insts().GetAsKnownInstId<SemIR::FunctionDecl>(fn_id));\n\n  // TODO: Infer a C++ type structure and check whether it's less strict than\n  // the best Carbon type structure.\n  static_cast<void>(best_impl_type_structure);\n  static_cast<void>(best_impl_loc_id);\n\n  return fn_id;\n}\n\nstatic auto BuildCopyWitness(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::ConstantId query_self_const_id,\n    SemIR::SpecificInterfaceId query_specific_interface_id,\n    const TypeStructure* best_impl_type_structure,\n    SemIR::LocId best_impl_loc_id) -> SemIR::InstId {\n  auto& clang_sema = context.clang_sema();\n\n  // TODO: This should provide `Copy` for enums and other trivially copyable\n  // types.\n  auto* class_decl = TypeAsClassDecl(context, query_self_const_id);\n  if (!class_decl) {\n    return SemIR::InstId::None;\n  }\n  auto decl_info = DeclInfo{.decl = clang_sema.LookupCopyingConstructor(\n                                class_decl, clang::Qualifiers::Const),\n                            .signature = {.num_params = 1}};\n  auto fn_id = GetFunctionId(context, loc_id, decl_info,\n                             best_impl_type_structure, best_impl_loc_id);\n  if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) {\n    return fn_id;\n  }\n  return BuildCustomWitness(context, loc_id, query_self_const_id,\n                            query_specific_interface_id, {fn_id});\n}\n\nstatic auto BuildDestroyWitness(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::ConstantId query_self_const_id,\n    SemIR::SpecificInterfaceId query_specific_interface_id,\n    const TypeStructure* best_impl_type_structure,\n    SemIR::LocId best_impl_loc_id) -> SemIR::InstId {\n  auto& clang_sema = context.clang_sema();\n\n  // TODO: This should provide `Destroy` for enums and other trivially\n  // destructible types.\n  auto* class_decl = TypeAsClassDecl(context, query_self_const_id);\n  if (!class_decl) {\n    return SemIR::InstId::None;\n  }\n  auto decl_info = DeclInfo{.decl = clang_sema.LookupDestructor(class_decl),\n                            .signature = {.num_params = 0}};\n  auto fn_id = GetFunctionId(context, loc_id, decl_info,\n                             best_impl_type_structure, best_impl_loc_id);\n  if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) {\n    return fn_id;\n  }\n  return BuildCustomWitness(context, loc_id, query_self_const_id,\n                            query_specific_interface_id, {fn_id});\n}\n\nstatic auto BuildCppUnsafeDerefWitness(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::ConstantId query_self_const_id,\n    SemIR::SpecificInterfaceId query_specific_interface_id,\n    const TypeStructure* best_impl_type_structure,\n    SemIR::LocId best_impl_loc_id) -> SemIR::InstId {\n  auto& clang_sema = context.clang_sema();\n\n  auto* class_decl = TypeAsClassDecl(context, query_self_const_id);\n  if (!class_decl) {\n    return SemIR::InstId::None;\n  }\n  auto candidates = class_decl->lookup(\n      clang_sema.getASTContext().DeclarationNames.getCXXOperatorName(\n          clang::OO_Star));\n  if (candidates.empty()) {\n    return SemIR::InstId::None;\n  }\n  if (!candidates.isSingleResult()) {\n    context.TODO(loc_id, \"operator* overload sets not implemented yet\");\n    return SemIR::ErrorInst::InstId;\n  }\n  auto decl_info =\n      DeclInfo{.decl = *candidates.begin(), .signature = {.num_params = 0}};\n  auto fn_id = GetFunctionId(context, loc_id, decl_info,\n                             best_impl_type_structure, best_impl_loc_id);\n  if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) {\n    return fn_id;\n  }\n\n  auto result_type_id =\n      context.functions()\n          .Get(context.insts().GetAs<SemIR::FunctionDecl>(fn_id).function_id)\n          .return_type_inst_id;\n  if (result_type_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  return BuildCustomWitness(context, loc_id, query_self_const_id,\n                            query_specific_interface_id,\n                            {result_type_id, fn_id});\n}\n\nauto LookupCppImpl(Context& context, SemIR::LocId loc_id,\n                   CoreInterface core_interface,\n                   SemIR::ConstantId query_self_const_id,\n                   SemIR::SpecificInterfaceId query_specific_interface_id,\n                   const TypeStructure* best_impl_type_structure,\n                   SemIR::LocId best_impl_loc_id) -> SemIR::InstId {\n  switch (core_interface) {\n    case CoreInterface::Copy:\n      return BuildCopyWitness(context, loc_id, query_self_const_id,\n                              query_specific_interface_id,\n                              best_impl_type_structure, best_impl_loc_id);\n    case CoreInterface::Destroy:\n      return BuildDestroyWitness(context, loc_id, query_self_const_id,\n                                 query_specific_interface_id,\n                                 best_impl_type_structure, best_impl_loc_id);\n    case CoreInterface::CppUnsafeDeref:\n      return BuildCppUnsafeDerefWitness(\n          context, loc_id, query_self_const_id, query_specific_interface_id,\n          best_impl_type_structure, best_impl_loc_id);\n\n    // IntFitsIn is for Carbon integer types only.\n    case CoreInterface::IntFitsIn:\n      return SemIR::InstId::None;\n\n    case CoreInterface::Unknown:\n      CARBON_FATAL(\"unexpected CoreInterface `{0}`\", core_interface);\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/impl_lookup.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_IMPL_LOOKUP_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_IMPL_LOOKUP_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/custom_witness.h\"\n#include \"toolchain/check/impl_lookup.h\"\n#include \"toolchain/check/interface.h\"\n#include \"toolchain/check/type_structure.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/specific_interface.h\"\n\nnamespace Carbon::Check {\n\n// Performs lookup for an impl witness for a query involving C++ types.\n// Shouldn't be called with `CoreInterface::Unknown`, because only core\n// interfaces can have lookup results. Returns a witness value, or `None` if a\n// synthesized C++ witness should not be used.\n//\n// Given a known `core_interface`, we can synthesize a witness based on C++\n// operator overloads or special member functions. Performs the suitable C++\n// lookup to determine if this interface should be considered implemented for\n// the specified type, and if so, synthesizes and returns a suitable witness.\n//\n// `best_impl_type_structure` provides the type structure of the best-matching\n// impl declaration. If this is better than every viable C++ candidate, a \"none\"\n// result will be returned. If this is worse than the best viable C++ candidate\n// according to C++ rules, a witness for the C++ candidate will be returned.\n// Otherwise, it is at least as good as the best viable C++ candidate, but there\n// is some C++ candidate that has a better type structure, in which case the\n// result is ambiguous and we diagnose an error. This parameter can be null if\n// there is no usable impl for this query.\n//\n// `best_impl_loc_id` gives the location of the impl corresponding to the best\n// type structure, and can be `None` if `best_impl_type_structure` is null. This\n// parameter is used only for ambiguity diagnostics.\nauto LookupCppImpl(Context& context, SemIR::LocId loc_id,\n                   CoreInterface core_interface,\n                   SemIR::ConstantId query_self_const_id,\n                   SemIR::SpecificInterfaceId query_specific_interface_id,\n                   const TypeStructure* best_impl_type_structure,\n                   SemIR::LocId best_impl_loc_id) -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_IMPL_LOOKUP_H_\n"
  },
  {
    "path": "toolchain/check/cpp/import.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/import.h\"\n\n#include <algorithm>\n#include <memory>\n#include <optional>\n#include <string>\n#include <tuple>\n#include <utility>\n\n#include \"clang/AST/ASTContext.h\"\n#include \"clang/AST/RecordLayout.h\"\n#include \"clang/AST/UnresolvedSet.h\"\n#include \"clang/AST/VTableBuilder.h\"\n#include \"clang/Frontend/CompilerInvocation.h\"\n#include \"clang/Sema/Lookup.h\"\n#include \"clang/Sema/Overload.h\"\n#include \"common/check.h\"\n#include \"common/ostream.h\"\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/ADT/IntrusiveRefCntPtr.h\"\n#include \"llvm/ADT/ScopeExit.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/raw_ostream.h\"\n#include \"toolchain/base/int.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/base/value_ids.h\"\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/class.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/check/cpp/access.h\"\n#include \"toolchain/check/cpp/custom_type_mapping.h\"\n#include \"toolchain/check/cpp/generate_ast.h\"\n#include \"toolchain/check/cpp/location.h\"\n#include \"toolchain/check/cpp/macros.h\"\n#include \"toolchain/check/cpp/thunk.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/function.h\"\n#include \"toolchain/check/import.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/literal.h\"\n#include \"toolchain/check/member_access.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/operator.h\"\n#include \"toolchain/check/pattern.h\"\n#include \"toolchain/check/pattern_match.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/check/unused.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/clang_decl.h\"\n#include \"toolchain/sem_ir/class.h\"\n#include \"toolchain/sem_ir/cpp_file.h\"\n#include \"toolchain/sem_ir/cpp_overload_set.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/pattern.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Adds the name to the scope with the given `access_kind` and `inst_id`.\n// `inst_id` must have a value.\nstatic auto AddNameToScope(Context& context, SemIR::NameScopeId scope_id,\n                           SemIR::NameId name_id, SemIR::AccessKind access_kind,\n                           SemIR::InstId inst_id) -> void {\n  CARBON_CHECK(inst_id.has_value());\n  context.name_scopes().Get(scope_id).AddRequired(\n      {.name_id = name_id,\n       .result = SemIR::ScopeLookupResult::MakeFound(inst_id, access_kind)});\n}\n\n// Maps a Clang name to a Carbon `NameId`.\nauto AddIdentifierName(Context& context, llvm::StringRef name)\n    -> SemIR::NameId {\n  return SemIR::NameId::ForIdentifier(context.identifiers().Add(name));\n}\n\n// Adds the given source location and an `ImportIRInst` referring to it in\n// `ImportIRId::Cpp`.\nstatic auto AddImportIRInst(SemIR::File& file,\n                            clang::SourceLocation clang_source_loc)\n    -> SemIR::ImportIRInstId {\n  SemIR::ClangSourceLocId clang_source_loc_id =\n      file.clang_source_locs().Add(clang_source_loc);\n  return file.import_ir_insts().Add(SemIR::ImportIRInst(clang_source_loc_id));\n}\n\n// Adds a namespace for the `Cpp` import and returns its `NameScopeId`.\nstatic auto AddNamespace(Context& context, PackageNameId cpp_package_id,\n                         llvm::ArrayRef<Parse::Tree::PackagingNames> imports)\n    -> SemIR::NameScopeId {\n  return AddImportNamespaceToScope(\n             context,\n             GetSingletonType(context, SemIR::NamespaceType::TypeInstId),\n             SemIR::NameId::ForPackageName(cpp_package_id),\n             SemIR::NameScopeId::Package,\n             /*diagnose_duplicate_namespace=*/false,\n             [&]() {\n               return AddInst<SemIR::ImportCppDecl>(\n                   context,\n                   context.parse_tree().As<Parse::ImportDeclId>(\n                       imports.front().node_id),\n                   {});\n             })\n      .add_result.name_scope_id;\n}\n\nauto ImportCpp(Context& context,\n               llvm::ArrayRef<Parse::Tree::PackagingNames> imports,\n               llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n               llvm::LLVMContext* llvm_context,\n               std::shared_ptr<clang::CompilerInvocation> invocation) -> void {\n  if (imports.empty()) {\n    // TODO: Consider always having a (non-null) AST even if there are no Cpp\n    // imports.\n    return;\n  }\n\n  PackageNameId package_id = imports.front().package_id;\n  CARBON_CHECK(\n      llvm::all_of(imports, [&](const Parse::Tree::PackagingNames& import) {\n        return import.package_id == package_id;\n      }));\n\n  auto name_scope_id = AddNamespace(context, package_id, imports);\n  SemIR::NameScope& name_scope = context.name_scopes().Get(name_scope_id);\n  name_scope.set_is_closed_import(true);\n\n  if (GenerateAst(context, imports, fs, llvm_context, std::move(invocation))) {\n    name_scope.set_clang_decl_context_id(context.clang_decls().Add(\n        {.key = SemIR::ClangDeclKey(\n             context.ast_context().getTranslationUnitDecl()),\n         .inst_id = name_scope.inst_id()}));\n  } else {\n    name_scope.set_has_error();\n  }\n}\n\n// Returns the Clang `DeclContext` for the given name scope. Return the\n// translation unit decl if no scope is provided.\nstatic auto GetDeclContext(Context& context, SemIR::NameScopeId scope_id)\n    -> clang::DeclContext* {\n  if (!scope_id.has_value()) {\n    return context.ast_context().getTranslationUnitDecl();\n  }\n  auto scope_clang_decl_context_id =\n      context.name_scopes().Get(scope_id).clang_decl_context_id();\n  return dyn_cast<clang::DeclContext>(\n      context.clang_decls().Get(scope_clang_decl_context_id).key.decl);\n}\n\n// Returns true if the given Clang declaration is the implicit injected class\n// name within the class.\nstatic auto IsDeclInjectedClassName(Context& context,\n                                    SemIR::NameScopeId scope_id,\n                                    SemIR::NameId name_id,\n                                    const clang::NamedDecl* named_decl)\n    -> bool {\n  if (!named_decl->isImplicit()) {\n    return false;\n  }\n\n  const auto* record_decl = dyn_cast<clang::CXXRecordDecl>(named_decl);\n  if (!record_decl) {\n    return false;\n  }\n\n  const SemIR::ClangDecl& clang_decl = context.clang_decls().Get(\n      context.name_scopes().Get(scope_id).clang_decl_context_id());\n  const auto* scope_record_decl =\n      cast<clang::CXXRecordDecl>(clang_decl.key.decl);\n\n  const clang::ASTContext& ast_context = context.ast_context();\n  CARBON_CHECK(ast_context.getCanonicalTagType(scope_record_decl) ==\n               ast_context.getCanonicalTagType(record_decl));\n\n  auto class_decl = context.insts().GetAs<SemIR::ClassDecl>(clang_decl.inst_id);\n  CARBON_CHECK(name_id == context.classes().Get(class_decl.class_id).name_id);\n  return true;\n}\n\n// Performs a qualified name lookup of the identifier in the given scope.\n// Returns the lookup result if lookup was successful.\nstatic auto ClangLookupName(Context& context, SemIR::NameScopeId scope_id,\n                            clang::IdentifierInfo* identifier_name)\n    -> std::optional<clang::LookupResult> {\n  CARBON_CHECK(identifier_name, \"Identifier name is empty\");\n  clang::Sema& sema = context.clang_sema();\n\n  // TODO: Map the LocId of the lookup to a clang SourceLocation and provide it\n  // here so that clang's diagnostics can point into the carbon code that uses\n  // the name.\n  clang::LookupResult lookup(\n      sema,\n      clang::DeclarationNameInfo(clang::DeclarationName(identifier_name),\n                                 clang::SourceLocation()),\n      clang::Sema::LookupNameKind::LookupOrdinaryName);\n\n  bool found =\n      sema.LookupQualifiedName(lookup, GetDeclContext(context, scope_id));\n\n  if (!found) {\n    return std::nullopt;\n  }\n\n  return lookup;\n}\n\n// Returns whether `decl` already mapped to an instruction.\nstatic auto IsClangDeclImported(Context& context, SemIR::ClangDeclKey key)\n    -> bool {\n  return context.clang_decls().Lookup(key).has_value();\n}\n\n// If `decl` already mapped to an instruction, returns that instruction.\n// Otherwise returns `None`.\nstatic auto LookupClangDeclInstId(Context& context, SemIR::ClangDeclKey key)\n    -> SemIR::InstId {\n  const auto& clang_decls = context.clang_decls();\n  if (auto context_clang_decl_id = clang_decls.Lookup(key);\n      context_clang_decl_id.has_value()) {\n    return clang_decls.Get(context_clang_decl_id).inst_id;\n  }\n  return SemIR::InstId::None;\n}\n\n// Returns the parent of the given declaration. Skips declaration types we\n// ignore.\nstatic auto GetParentDecl(clang::Decl* clang_decl) -> clang::Decl* {\n  auto* parent_dc = clang_decl->getDeclContext();\n  while (!parent_dc->isLookupContext()) {\n    parent_dc = parent_dc->getParent();\n  }\n  return cast<clang::Decl>(parent_dc);\n}\n\n// Returns the given declaration's parent scope. Assumes the parent declaration\n// was already imported.\nstatic auto GetParentNameScopeId(Context& context, clang::Decl* clang_decl)\n    -> SemIR::NameScopeId {\n  auto* parent_decl = GetParentDecl(clang_decl);\n\n  if (auto* tag_decl = dyn_cast<clang::TagDecl>(parent_decl)) {\n    auto class_inst_id =\n        LookupClangDeclInstId(context, SemIR::ClangDeclKey(tag_decl));\n    CARBON_CHECK(class_inst_id.has_value());\n    auto class_inst = context.insts().Get(class_inst_id);\n    auto class_id = SemIR::ClassId::None;\n    if (auto class_decl = class_inst.TryAs<SemIR::ClassDecl>()) {\n      // Common case: the tag was imported as a new Carbon class.\n      class_id = class_decl->class_id;\n    } else {\n      // Rare case: the tag was imported as an existing Carbon class. This\n      // happens for C++ classes that get mapped to Carbon prelude types, such\n      // as `std::string_view`.\n      // TODO: In this case, should we import the C++ class declaration and use\n      // it as the parent, rather than using the existing Carbon class?\n      class_id = class_inst.As<SemIR::ClassType>().class_id;\n    }\n    return context.classes().Get(class_id).scope_id;\n  }\n\n  if (isa<clang::NamespaceDecl, clang::TranslationUnitDecl>(parent_decl)) {\n    auto namespace_inst_id = LookupClangDeclInstId(\n        context, SemIR::ClangDeclKey::ForNonFunctionDecl(parent_decl));\n    CARBON_CHECK(namespace_inst_id.has_value());\n    return context.insts()\n        .GetAs<SemIR::Namespace>(namespace_inst_id)\n        .name_scope_id;\n  }\n\n  CARBON_FATAL(\"Unexpected kind of parent {0}\", parent_decl->getDeclKindName());\n}\n\n// Imports a namespace declaration from Clang to Carbon. If successful, returns\n// the new Carbon namespace declaration `InstId`. If the declaration was already\n// imported, returns the mapped instruction.\nstatic auto ImportNamespaceDecl(Context& context,\n                                clang::NamespaceDecl* clang_decl)\n    -> SemIR::InstId {\n  auto key = SemIR::ClangDeclKey(clang_decl);\n  // Check if the declaration is already mapped.\n  if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key);\n      existing_inst_id.has_value()) {\n    return existing_inst_id;\n  }\n  auto result = AddImportNamespace(\n      context, GetSingletonType(context, SemIR::NamespaceType::TypeInstId),\n      AddIdentifierName(context, clang_decl->getName()),\n      GetParentNameScopeId(context, clang_decl),\n      /*import_id=*/SemIR::InstId::None);\n  context.name_scopes()\n      .Get(result.name_scope_id)\n      .set_clang_decl_context_id(\n          context.clang_decls().Add({.key = key, .inst_id = result.inst_id}));\n  return result.inst_id;\n}\n\n// Creates a class declaration for the given class name in the given scope.\n// Returns the `InstId` for the declaration.\nstatic auto BuildClassDecl(Context& context,\n                           SemIR::ImportIRInstId import_ir_inst_id,\n                           SemIR::NameScopeId parent_scope_id,\n                           SemIR::NameId name_id)\n    -> std::tuple<SemIR::ClassId, SemIR::TypeInstId> {\n  // Add the class declaration.\n  auto class_decl = SemIR::ClassDecl{.type_id = SemIR::TypeType::TypeId,\n                                     .class_id = SemIR::ClassId::None,\n                                     .decl_block_id = SemIR::InstBlockId::None};\n  auto class_decl_id = AddPlaceholderImportedInstInNoBlock(\n      context,\n      MakeImportedLocIdAndInst(context, import_ir_inst_id, class_decl));\n\n  SemIR::Class class_info = {\n      {.name_id = name_id,\n       .parent_scope_id = parent_scope_id,\n       .generic_id = SemIR::GenericId::None,\n       .first_param_node_id = Parse::NodeId::None,\n       .last_param_node_id = Parse::NodeId::None,\n       .pattern_block_id = SemIR::InstBlockId::None,\n       .implicit_param_patterns_id = SemIR::InstBlockId::None,\n       .param_patterns_id = SemIR::InstBlockId::None,\n       .is_extern = false,\n       .extern_library_id = SemIR::LibraryNameId::None,\n       .non_owning_decl_id = SemIR::InstId::None,\n       .first_owning_decl_id = class_decl_id},\n      {// `.self_type_id` depends on the ClassType, so is set below.\n       .self_type_id = SemIR::TypeId::None,\n       // TODO: Support Dynamic classes.\n       // TODO: Support Final classes.\n       .inheritance_kind = SemIR::Class::Base}};\n\n  class_decl.class_id = context.classes().Add(class_info);\n\n  // Write the class ID into the ClassDecl.\n  ReplaceInstBeforeConstantUse(context, class_decl_id, class_decl);\n\n  SetClassSelfType(context, class_decl.class_id);\n\n  return {class_decl.class_id, context.types().GetAsTypeInstId(class_decl_id)};\n}\n\n// Imports a tag declaration from Clang to Carbon. This covers classes (which\n// includes structs and unions) as well as enums. If successful, returns the new\n// Carbon class declaration `InstId`.\nstatic auto ImportTagDecl(Context& context, clang::TagDecl* clang_decl)\n    -> SemIR::InstId {\n  auto import_ir_inst_id =\n      AddImportIRInst(context.sem_ir(), clang_decl->getLocation());\n\n  auto [class_id, class_inst_id] = BuildClassDecl(\n      context, import_ir_inst_id, GetParentNameScopeId(context, clang_decl),\n      AddIdentifierName(context, clang_decl->getName()));\n\n  // TODO: The caller does the same lookup. Avoid doing it twice.\n  auto key = SemIR::ClangDeclKey(clang_decl);\n  auto clang_decl_id =\n      context.clang_decls().Add({.key = key, .inst_id = class_inst_id});\n\n  // Name lookup into the Carbon class looks in the C++ class definition.\n  auto& class_info = context.classes().Get(class_id);\n  class_info.scope_id = context.name_scopes().Add(\n      class_inst_id, SemIR::NameId::None, class_info.parent_scope_id);\n  context.name_scopes()\n      .Get(class_info.scope_id)\n      .set_clang_decl_context_id(clang_decl_id);\n\n  return class_inst_id;\n}\n\n// Determines the Carbon inheritance kind to use for a C++ class definition.\nstatic auto GetInheritanceKind(clang::CXXRecordDecl* class_def)\n    -> SemIR::Class::InheritanceKind {\n  if (class_def->isUnion()) {\n    // Treat all unions as final classes to match their C++ semantics. While we\n    // could support this, the author of a C++ union has no way to mark their\n    // type as `final` to prevent it, and so we assume the intent was to\n    // disallow inheritance.\n    return SemIR::Class::Final;\n  }\n\n  if (class_def->hasAttr<clang::FinalAttr>()) {\n    // The class is final in C++; don't allow Carbon types to derive from it.\n    // Note that such a type might also be abstract in C++; we treat final as\n    // taking precedence.\n    //\n    // We could also treat classes with a final destructor as being final, as\n    // Clang does when determining whether a class is \"effectively final\", but\n    // to keep our rules simpler we do not.\n    return SemIR::Class::Final;\n  }\n\n  if (class_def->getNumVBases()) {\n    // TODO: We treat classes with virtual bases as final for now. We use the\n    // layout of the class including its virtual bases as its Carbon type\n    // layout, so we wouldn't behave correctly if we derived from it.\n    return SemIR::Class::Final;\n  }\n\n  if (class_def->isAbstract()) {\n    // If the class has any abstract members, it's abstract.\n    return SemIR::Class::Abstract;\n  }\n\n  // Allow inheritance from any other C++ class type.\n  return SemIR::Class::Base;\n}\n\n// Checks that the specified finished class definition is valid and builds and\n// returns a corresponding complete type witness instruction.\nstatic auto ImportClassObjectRepr(Context& context, SemIR::ClassId class_id,\n                                  SemIR::ImportIRInstId import_ir_inst_id,\n                                  SemIR::TypeInstId class_type_inst_id,\n                                  const clang::CXXRecordDecl* clang_def)\n    -> SemIR::TypeInstId {\n  if (clang_def->isInvalidDecl()) {\n    // Clang already diagnosed this error.\n    return SemIR::ErrorInst::TypeInstId;\n  }\n\n  // For now, if the class is empty and an aggregate, produce an empty struct as\n  // the object representation. This allows our tests to continue to pass while\n  // we don't properly support initializing imported C++ classes. We only do\n  // this for aggregates so that non-aggregate classes are not incorrectly\n  // initializable from `{}`.\n  // TODO: Remove this.\n  if (clang_def->isEmpty() && !clang_def->getNumBases() &&\n      clang_def->isAggregate()) {\n    return context.types().GetAsTypeInstId(AddInst(\n        context,\n        MakeImportedLocIdAndInst(\n            context, import_ir_inst_id,\n            SemIR::StructType{.type_id = SemIR::TypeType::TypeId,\n                              .fields_id = SemIR::StructTypeFieldsId::Empty})));\n  }\n\n  const auto& clang_layout =\n      context.ast_context().getASTRecordLayout(clang_def);\n\n  llvm::SmallVector<uint64_t> layout;\n  llvm::SmallVector<SemIR::StructTypeField> fields;\n\n  static_assert(SemIR::CustomLayoutId::SizeIndex == 0);\n  layout.push_back(clang_layout.getSize().getQuantity());\n\n  static_assert(SemIR::CustomLayoutId::AlignIndex == 1);\n  layout.push_back(clang_layout.getAlignment().getQuantity());\n\n  static_assert(SemIR::CustomLayoutId::FirstFieldIndex == 2);\n\n  // TODO: Import vptr(s).\n\n  // The kind of base class we've picked so far. These are ordered in increasing\n  // preference order.\n  enum class BaseKind {\n    None,\n    Empty,\n    NonEmpty,\n    Polymorphic,\n  };\n  BaseKind base_kind = BaseKind::None;\n\n  // Import bases.\n  for (const auto& base : clang_def->bases()) {\n    if (base.isVirtual()) {\n      // If the base is virtual, skip it from the layout. We don't know where it\n      // will actually appear within the complete object layout, as a pointer to\n      // this class might point to a derived type that puts the vbase in a\n      // different place.\n      // TODO: Track that the virtual base existed. Support derived-to-vbase\n      // conversions by generating a clang AST fragment.\n      continue;\n    }\n\n    auto [base_type_inst_id, base_type_id] =\n        ImportCppType(context, import_ir_inst_id, base.getType());\n    if (!base_type_id.has_value()) {\n      // TODO: If the base class's type can't be mapped, skip it.\n      continue;\n    }\n\n    auto base_decl_id = AddInst(\n        context,\n        MakeImportedLocIdAndInst(\n            context, import_ir_inst_id,\n            SemIR::BaseDecl{.type_id = GetUnboundElementType(\n                                context, class_type_inst_id, base_type_inst_id),\n                            .base_type_inst_id = base_type_inst_id,\n                            .index = SemIR::ElementIndex(fields.size())}));\n\n    auto* base_class = base.getType()->getAsCXXRecordDecl();\n    CARBON_CHECK(base_class, \"Base class {0} is not a class\",\n                 base.getType().getAsString());\n\n    // If there's a unique \"best\" base class, treat it as a Carbon base class\n    // too.\n    // TODO: Improve handling for the case where the class has multiple base\n    // classes.\n    BaseKind kind = base_class->isPolymorphic() ? BaseKind::Polymorphic\n                    : base_class->isEmpty()     ? BaseKind::Empty\n                                                : BaseKind::NonEmpty;\n    auto& class_info = context.classes().Get(class_id);\n    if (kind > base_kind) {\n      // This base is better than the previous best.\n      class_info.base_id = base_decl_id;\n      base_kind = kind;\n    } else if (kind == base_kind) {\n      // Multiple base classes of this kind: no unique best.\n      class_info.base_id = SemIR::InstId::None;\n    }\n\n    // TODO: If the base class has virtual bases, the size of the type that we\n    // add to the layout here will be the full size of the class (including\n    // virtual bases), whereas the size actually occupied by this base class is\n    // only the nvsize (excluding virtual bases).\n    auto base_offset = base.isVirtual()\n                           ? clang_layout.getVBaseClassOffset(base_class)\n                           : clang_layout.getBaseClassOffset(base_class);\n    layout.push_back(base_offset.getQuantity());\n    fields.push_back(\n        {.name_id = SemIR::NameId::Base, .type_inst_id = base_type_inst_id});\n  }\n\n  // Import fields.\n  for (auto* decl : clang_def->decls()) {\n    auto* field = dyn_cast<clang::FieldDecl>(decl);\n\n    // Track the chain of fields from the class to this field. This chain is\n    // only one element long unless the field is a member of an anonymous struct\n    // or union.\n    clang::NamedDecl* single_field_chain[1] = {field};\n    llvm::ArrayRef<clang::NamedDecl*> chain = single_field_chain;\n\n    // If this isn't a field, it might be an indirect field in an anonymous\n    // struct or union.\n    if (!field) {\n      auto* indirect_field = dyn_cast<clang::IndirectFieldDecl>(decl);\n      if (!indirect_field) {\n        continue;\n      }\n      chain = indirect_field->chain();\n      field = indirect_field->getAnonField();\n    }\n\n    if (field->isBitField()) {\n      // TODO: Add a representation for named bitfield members.\n      continue;\n    }\n\n    if (field->isAnonymousStructOrUnion()) {\n      // Fields within an anonymous structure or union will be added via their\n      // IndirectFieldDecls.\n      continue;\n    }\n\n    auto field_name_id = AddIdentifierName(context, field->getName());\n    auto [field_type_inst_id, field_type_id] =\n        ImportCppType(context, import_ir_inst_id, field->getType());\n    if (!field_type_inst_id.has_value()) {\n      // TODO: For now, just skip over fields whose types we can't map.\n      continue;\n    }\n\n    // Create a field now, as we know the index to use.\n    // TODO: Consider doing this lazily instead.\n    auto field_decl_id = AddInst(\n        context, MakeImportedLocIdAndInst(\n                     context, import_ir_inst_id,\n                     SemIR::FieldDecl{\n                         .type_id = GetUnboundElementType(\n                             context, class_type_inst_id, field_type_inst_id),\n                         .name_id = field_name_id,\n                         .index = SemIR::ElementIndex(fields.size())}));\n    // The imported SemIR::FieldDecl represents the original declaration `decl`,\n    // which is either the field or the indirect field declaration.\n    auto key = SemIR::ClangDeclKey::ForNonFunctionDecl(decl);\n    context.clang_decls().Add({.key = key, .inst_id = field_decl_id});\n\n    // Compute the offset to the field that appears directly in the class.\n    uint64_t offset = clang_layout.getFieldOffset(\n        cast<clang::FieldDecl>(chain.front())->getFieldIndex());\n\n    // If this is an indirect field, walk the path and accumulate the offset to\n    // the named field.\n    for (auto* inner_decl : chain.drop_front()) {\n      auto* inner_field = cast<clang::FieldDecl>(inner_decl);\n      const auto& inner_layout =\n          context.ast_context().getASTRecordLayout(inner_field->getParent());\n      offset += inner_layout.getFieldOffset(inner_field->getFieldIndex());\n    }\n\n    layout.push_back(\n        context.ast_context().toCharUnitsFromBits(offset).getQuantity());\n    fields.push_back(\n        {.name_id = field_name_id, .type_inst_id = field_type_inst_id});\n  }\n\n  // TODO: Add a field to prevent tail padding reuse if necessary.\n\n  return AddTypeInst(context,\n                     MakeImportedLocIdAndInst<SemIR::CustomLayoutType>(\n                         context, import_ir_inst_id,\n                         {.type_id = SemIR::TypeType::TypeId,\n                          .fields_id = context.struct_type_fields().Add(fields),\n                          .layout_id = context.custom_layouts().Add(layout)}));\n}\n\n// Creates a Carbon class definition based on the information in the given Clang\n// class declaration, which is assumed to be for a class definition.\nstatic auto BuildClassDefinition(Context& context,\n                                 SemIR::ImportIRInstId import_ir_inst_id,\n                                 SemIR::ClassId class_id,\n                                 SemIR::TypeInstId class_inst_id,\n                                 clang::CXXRecordDecl* clang_def) -> void {\n  auto& class_info = context.classes().Get(class_id);\n  CARBON_CHECK(!class_info.has_definition_started());\n  class_info.definition_id = class_inst_id;\n\n  context.inst_block_stack().Push();\n\n  class_info.inheritance_kind = GetInheritanceKind(clang_def);\n\n  // Compute the class's object representation.\n  auto object_repr_id = ImportClassObjectRepr(\n      context, class_id, import_ir_inst_id, class_inst_id, clang_def);\n  class_info.complete_type_witness_id = AddInst(\n      context,\n      MakeImportedLocIdAndInst<SemIR::CompleteTypeWitness>(\n          context, import_ir_inst_id,\n          {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),\n           .object_repr_type_inst_id = object_repr_id}));\n\n  class_info.body_block_id = context.inst_block_stack().Pop();\n}\n\n// Computes and returns the Carbon type to use as the object representation of\n// the given C++ enum type. This is a builtin int type matching the enum's\n// representation.\nstatic auto ImportEnumObjectRepresentation(\n    Context& context, SemIR::ImportIRInstId import_ir_inst_id,\n    clang::EnumDecl* enum_decl) -> SemIR::TypeInstId {\n  auto int_type = enum_decl->getIntegerType();\n  CARBON_CHECK(!int_type.isNull(), \"incomplete enum type {0}\",\n               enum_decl->getNameAsString());\n\n  auto int_kind = int_type->isSignedIntegerType() ? SemIR::IntKind::Signed\n                                                  : SemIR::IntKind::Unsigned;\n  auto bit_width_id = GetOrAddInst(\n      context, MakeImportedLocIdAndInst<SemIR::IntValue>(\n                   context, import_ir_inst_id,\n                   {.type_id = GetSingletonType(\n                        context, SemIR::IntLiteralType::TypeInstId),\n                    .int_id = context.ints().AddUnsigned(llvm::APInt(\n                        64, context.ast_context().getIntWidth(int_type)))}));\n  return context.types().GetAsTypeInstId(\n      GetOrAddInst(context, SemIR::LocIdAndInst::NoLoc(SemIR::IntType{\n                                .type_id = SemIR::TypeType::TypeId,\n                                .int_kind = int_kind,\n                                .bit_width_id = bit_width_id})));\n}\n\n// Creates a Carbon class definition based on the information in the given Clang\n// enum declaration.\nstatic auto BuildEnumDefinition(Context& context,\n                                SemIR::ImportIRInstId import_ir_inst_id,\n                                SemIR::ClassId class_id,\n                                SemIR::TypeInstId class_inst_id,\n                                clang::EnumDecl* enum_decl) -> void {\n  auto& class_info = context.classes().Get(class_id);\n  CARBON_CHECK(!class_info.has_definition_started());\n  class_info.definition_id = class_inst_id;\n\n  context.inst_block_stack().Push();\n\n  // Don't allow inheritance from C++ enums, to match the behavior in C++.\n  class_info.inheritance_kind = SemIR::Class::Final;\n\n  // Compute the enum type's object representation. An enum is an adapter for\n  // the corresponding builtin integer type.\n  auto object_repr_id =\n      ImportEnumObjectRepresentation(context, import_ir_inst_id, enum_decl);\n  class_info.adapt_id = AddInst(\n      context, MakeImportedLocIdAndInst(\n                   context, import_ir_inst_id,\n                   SemIR::AdaptDecl{.adapted_type_inst_id = object_repr_id}));\n  class_info.complete_type_witness_id = AddInst(\n      context,\n      MakeImportedLocIdAndInst<SemIR::CompleteTypeWitness>(\n          context, import_ir_inst_id,\n          {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),\n           .object_repr_type_inst_id = object_repr_id}));\n\n  class_info.body_block_id = context.inst_block_stack().Pop();\n}\n\n// Imports an enumerator declaration from Clang to Carbon.\nstatic auto ImportEnumConstantDecl(Context& context,\n                                   clang::EnumConstantDecl* enumerator_decl)\n    -> SemIR::InstId {\n  auto key = SemIR::ClangDeclKey(enumerator_decl);\n  CARBON_CHECK(!IsClangDeclImported(context, key));\n\n  // Find the enclosing enum type.\n  auto enum_key = SemIR::ClangDeclKey(\n      cast<clang::EnumDecl>(enumerator_decl->getDeclContext()));\n  auto type_inst_id = LookupClangDeclInstId(context, enum_key);\n  auto type_id = context.types().GetTypeIdForTypeInstId(type_inst_id);\n\n  // Build a corresponding IntValue.\n  auto int_id = context.ints().Add(enumerator_decl->getInitVal());\n  auto import_ir_inst_id =\n      AddImportIRInst(context.sem_ir(), enumerator_decl->getLocation());\n  auto inst_id = AddInstInNoBlock(\n      context,\n      MakeImportedLocIdAndInst<SemIR::IntValue>(\n          context, import_ir_inst_id, {.type_id = type_id, .int_id = int_id}));\n  context.imports().push_back(inst_id);\n  context.clang_decls().Add({.key = key, .inst_id = inst_id});\n  return inst_id;\n}\n\n// Mark the given `key` as failed in `clang_decls`.\nstatic auto MarkFailedDecl(Context& context, SemIR::ClangDeclKey key) {\n  context.clang_decls().Add({.key = key, .inst_id = SemIR::ErrorInst::InstId});\n}\n\n// Creates an integer type of the given size.\nstatic auto MakeIntType(Context& context, IntId size_id, bool is_signed)\n    -> TypeExpr {\n  auto type_inst_id = MakeIntTypeLiteral(\n      context, Parse::NodeId::None,\n      is_signed ? SemIR::IntKind::Signed : SemIR::IntKind::Unsigned, size_id);\n  return ExprAsType(context, Parse::NodeId::None, type_inst_id);\n}\n\nstatic auto MakeCppCompatType(Context& context, SemIR::LocId loc_id,\n                              CoreIdentifier name) -> TypeExpr {\n  return ExprAsType(\n      context, loc_id,\n      LookupNameInCore(context, loc_id, {CoreIdentifier::CppCompat, name}));\n}\n\n// Maps a C++ builtin integer type to a Carbon `Core.CppCompat` type.\nstatic auto MapBuiltinCppCompatIntegerType(Context& context,\n                                           unsigned int cpp_width,\n                                           unsigned int carbon_width,\n                                           CoreIdentifier cpp_compat_name)\n    -> TypeExpr {\n  if (cpp_width != carbon_width) {\n    return TypeExpr::None;\n  }\n\n  return MakeCppCompatType(context, Parse::NodeId::None, cpp_compat_name);\n}\n\n// Maps a C++ builtin integer type to a Carbon type.\n// TODO: Handle integer types that map to named aliases.\nstatic auto MapBuiltinIntegerType(Context& context, SemIR::LocId loc_id,\n                                  clang::QualType qual_type,\n                                  const clang::BuiltinType& type) -> TypeExpr {\n  clang::ASTContext& ast_context = context.ast_context();\n  unsigned width = ast_context.getIntWidth(qual_type);\n  bool is_signed = type.isSignedInteger();\n  auto int_n_type = ast_context.getIntTypeForBitwidth(width, is_signed);\n  if (clang::ASTContext::hasSameType(qual_type, int_n_type)) {\n    TypeExpr type_expr =\n        MakeIntType(context, context.ints().Add(width), is_signed);\n    // Try to make sure integer types of 32 or 64 bits are complete so we can\n    // check against them when deciding whether we need to generate a thunk.\n    if (width == 32 || width == 64) {\n      SemIR::TypeId type_id = type_expr.type_id;\n      if (!context.types().IsComplete(type_id)) {\n        TryToCompleteType(context, type_id, loc_id);\n      }\n    }\n    return type_expr;\n  }\n  if (clang::ASTContext::hasSameType(qual_type, ast_context.CharTy)) {\n    return ExprAsType(context, Parse::NodeId::None,\n                      MakeCharTypeLiteral(context, Parse::NodeId::None));\n  }\n  if (clang::ASTContext::hasSameType(qual_type, ast_context.LongTy)) {\n    return MapBuiltinCppCompatIntegerType(context, width, 32,\n                                          CoreIdentifier::Long32);\n  }\n  if (clang::ASTContext::hasSameType(qual_type, ast_context.UnsignedLongTy)) {\n    return MapBuiltinCppCompatIntegerType(context, width, 32,\n                                          CoreIdentifier::ULong32);\n  }\n  if (clang::ASTContext::hasSameType(qual_type, ast_context.LongLongTy)) {\n    return MapBuiltinCppCompatIntegerType(context, width, 64,\n                                          CoreIdentifier::LongLong64);\n  }\n  if (clang::ASTContext::hasSameType(qual_type,\n                                     ast_context.UnsignedLongLongTy)) {\n    return MapBuiltinCppCompatIntegerType(context, width, 64,\n                                          CoreIdentifier::ULongLong64);\n  }\n  return TypeExpr::None;\n}\n\nstatic auto MapNullptrType(Context& context, SemIR::LocId loc_id) -> TypeExpr {\n  return MakeCppCompatType(context, loc_id, CoreIdentifier::NullptrT);\n}\n\n// Maps a C++ builtin type to a Carbon type.\n// TODO: Support more builtin types.\nstatic auto MapBuiltinType(Context& context, SemIR::LocId loc_id,\n                           clang::QualType qual_type,\n                           const clang::BuiltinType& type) -> TypeExpr {\n  clang::ASTContext& ast_context = context.ast_context();\n  if (type.isBooleanType()) {\n    CARBON_CHECK(ast_context.hasSameType(qual_type, ast_context.BoolTy));\n    return ExprAsType(context, Parse::NodeId::None,\n                      context.types().GetTypeInstId(GetSingletonType(\n                          context, SemIR::BoolType::TypeInstId)));\n  }\n  if (type.isInteger()) {\n    return MapBuiltinIntegerType(context, loc_id, qual_type, type);\n  }\n  if (type.isFloatingPoint()) {\n    if (type.isFloat16Type() || type.isFloat32Type() || type.isDoubleType() ||\n        type.isFloat128Type()) {\n      return ExprAsType(\n          context, Parse::NodeId::None,\n          MakeFloatTypeLiteral(\n              context, Parse::NodeId::None,\n              context.ints().Add(ast_context.getTypeSize(qual_type))));\n    }\n    // TODO: Handle floating-point types that map to named aliases.\n  } else if (type.isVoidType()) {\n    return MakeCppCompatType(context, loc_id, CoreIdentifier::VoidBase);\n  } else if (type.isNullPtrType()) {\n    return MapNullptrType(context, loc_id);\n  }\n\n  return TypeExpr::None;\n}\n\n// Determines whether record_decl is a C++ class that has a custom mapping into\n// Carbon, and if so, returns the corresponding Carbon type. Otherwise returns\n// None.\nstatic auto LookupCustomRecordType(Context& context,\n                                   const clang::CXXRecordDecl* record_decl)\n    -> TypeExpr {\n  switch (GetCustomCppTypeMapping(record_decl)) {\n    case CustomCppTypeMapping::None:\n      return TypeExpr::None;\n\n    case CustomCppTypeMapping::Str:\n      return MakeStringType(\n          context,\n          AddImportIRInst(context.sem_ir(), record_decl->getLocation()));\n  }\n}\n\n// Maps a C++ tag type (class, struct, union, enum) to a Carbon type.\nstatic auto MapTagType(Context& context, const clang::TagType& type)\n    -> TypeExpr {\n  auto* tag_decl = type.getDecl();\n  CARBON_CHECK(tag_decl);\n\n  // Check if the declaration is already mapped.\n  auto key = SemIR::ClangDeclKey(tag_decl);\n  SemIR::InstId tag_inst_id = LookupClangDeclInstId(context, key);\n  if (!tag_inst_id.has_value()) {\n    if (auto* record_decl = dyn_cast<clang::CXXRecordDecl>(tag_decl)) {\n      auto custom_type = LookupCustomRecordType(context, record_decl);\n      if (custom_type.inst_id.has_value()) {\n        context.clang_decls().Add({.key = key, .inst_id = custom_type.inst_id});\n        return custom_type;\n      }\n    }\n\n    tag_inst_id = ImportTagDecl(context, tag_decl);\n  }\n  SemIR::TypeInstId record_type_inst_id =\n      context.types().GetAsTypeInstId(tag_inst_id);\n  return {\n      // TODO: inst_id's location should be the location of the usage, not\n      // the location of the type definition. Possibly we should synthesize a\n      // NameRef inst, to match how this would work in Carbon code.\n      .inst_id = record_type_inst_id,\n      .type_id = context.types().GetTypeIdForTypeInstId(record_type_inst_id)};\n}\n\n// Maps a C++ type that is not a wrapper type such as a pointer to a Carbon\n// type.\n// TODO: Support more types.\nstatic auto MapNonWrapperType(Context& context, SemIR::LocId loc_id,\n                              clang::QualType type) -> TypeExpr {\n  if (const auto* builtin_type = type->getAs<clang::BuiltinType>()) {\n    return MapBuiltinType(context, loc_id, type, *builtin_type);\n  }\n\n  if (const auto* tag_type = type->getAs<clang::TagType>()) {\n    return MapTagType(context, *tag_type);\n  }\n\n  CARBON_CHECK(!type.hasQualifiers() && !type->isPointerType(),\n               \"Should not see wrapper types here\");\n\n  return TypeExpr::None;\n}\n\n// Maps a qualified C++ type to a Carbon type.\nstatic auto MapQualifiedType(Context& context, clang::QualType type,\n                             TypeExpr type_expr) -> TypeExpr {\n  auto quals = type.getQualifiers();\n\n  if (quals.hasConst()) {\n    auto type_id = GetConstType(context, type_expr.inst_id);\n    type_expr = TypeExpr::ForUnsugared(context, type_id);\n    quals.removeConst();\n  }\n\n  // TODO: Support other qualifiers.\n  if (!quals.empty()) {\n    return TypeExpr::None;\n  }\n\n  return type_expr;\n}\n\n// Returns true if the type has the `_Nonnull` attribute.\nstatic auto IsClangTypeNonNull(clang::QualType type) -> bool {\n  auto nullability = type->getNullability();\n  return nullability.has_value() &&\n         *nullability == clang::NullabilityKind::NonNull;\n}\n\n// Like `clang::QualType::getUnqualifiedType()`, retrieves the unqualified\n// variant of the given type, but preserves `_Nonnull`.\nstatic auto ClangGetUnqualifiedTypePreserveNonNull(\n    Context& context, clang::QualType original_type) -> clang::QualType {\n  clang::QualType type = original_type.getUnqualifiedType();\n  // Preserve non-nullability.\n  if (IsClangTypeNonNull(original_type) && !IsClangTypeNonNull(type)) {\n    type = context.ast_context().getAttributedType(\n        clang::NullabilityKind::NonNull, type, type);\n  }\n  return type;\n}\n\n// Returns the type `Core.Optional(T)`, where  `T` is described by\n// `inner_type_inst_id`.\nstatic auto MakeOptionalType(Context& context, SemIR::LocId loc_id,\n                             SemIR::InstId inner_type_inst_id) -> TypeExpr {\n  auto fn_inst_id = LookupNameInCore(context, loc_id, CoreIdentifier::Optional);\n  auto call_id = PerformCall(context, loc_id, fn_inst_id, {inner_type_inst_id});\n  return ExprAsType(context, loc_id, call_id);\n}\n\n// Maps a C++ pointer type to a Carbon pointer type.\nstatic auto MapPointerType(Context& context, SemIR::LocId loc_id,\n                           clang::QualType type, TypeExpr pointee_type_expr)\n    -> TypeExpr {\n  CARBON_CHECK(type->isPointerType());\n\n  bool optional =\n      !IsClangTypeNonNull(type) &&\n      // If the type was produced by C++ template substitution, then we assume\n      // it was deduced from a Carbon pointer type, so it's non-null.\n      !type->getAs<clang::SubstTemplateTypeParmType>();\n\n  TypeExpr pointer_type_expr = TypeExpr::ForUnsugared(\n      context, GetPointerType(context, pointee_type_expr.inst_id));\n  if (optional) {\n    pointer_type_expr =\n        MakeOptionalType(context, loc_id, pointer_type_expr.inst_id);\n  }\n  return pointer_type_expr;\n}\n\n// Maps a C++ reference type to a Carbon type. We map all references to\n// pointers for now. Note that when mapping function parameters and return\n// types, a different rule is used; see MapParameterType for details.\n// TODO: Revisit this and decide what we really want to do here.\nstatic auto MapReferenceType(Context& context, clang::QualType type,\n                             TypeExpr referenced_type_expr) -> TypeExpr {\n  CARBON_CHECK(type->isReferenceType());\n  SemIR::TypeId pointer_type_id =\n      GetPointerType(context, referenced_type_expr.inst_id);\n  pointer_type_id =\n      GetConstType(context, context.types().GetTypeInstId(pointer_type_id));\n  return TypeExpr::ForUnsugared(context, pointer_type_id);\n}\n\n// Maps a C++ type to a Carbon type. `type` should not be canonicalized because\n// we check for pointer nullability and nullability will be lost by\n// canonicalization.\nstatic auto MapType(Context& context, SemIR::LocId loc_id, clang::QualType type)\n    -> TypeExpr {\n  // Unwrap any type modifiers and wrappers.\n  llvm::SmallVector<clang::QualType> wrapper_types;\n  while (true) {\n    clang::QualType orig_type = type;\n    if (type.hasQualifiers()) {\n      type = ClangGetUnqualifiedTypePreserveNonNull(context, type);\n    } else if (type->isPointerType()) {\n      type = type->getPointeeType();\n    } else if (type->isReferenceType()) {\n      type = type.getNonReferenceType();\n    } else {\n      break;\n    }\n    wrapper_types.push_back(orig_type);\n  }\n\n  auto mapped = MapNonWrapperType(context, loc_id, type);\n\n  for (auto wrapper : llvm::reverse(wrapper_types)) {\n    if (!mapped.inst_id.has_value() ||\n        mapped.type_id == SemIR::ErrorInst::TypeId) {\n      break;\n    }\n\n    if (wrapper.hasQualifiers()) {\n      mapped = MapQualifiedType(context, wrapper, mapped);\n    } else if (wrapper->isPointerType()) {\n      mapped = MapPointerType(context, loc_id, wrapper, mapped);\n    } else if (wrapper->isReferenceType()) {\n      mapped = MapReferenceType(context, wrapper, mapped);\n    } else {\n      CARBON_FATAL(\"Unexpected wrapper type {0}\", wrapper.getAsString());\n    }\n  }\n\n  return mapped;\n}\n\nnamespace {\n// Information about how to map a C++ parameter type into Carbon.\nstruct ParameterTypeInfo {\n  // The type to use for the Carbon parameter.\n  TypeExpr type;\n  // Whether to build a `ref` pattern.\n  bool want_ref_pattern;\n};\n}  // namespace\n\n// Given the type of a C++ function parameter, returns information about the\n// type to use for the corresponding Carbon parameter.\n//\n// Note that if the parameter has a type for which `IsSimpleAbiType` returns\n// true, we must produce a parameter type that has the same calling convention\n// as the C++ type.\nstatic auto MapParameterType(Context& context, SemIR::LocId loc_id,\n                             clang::QualType param_type) -> ParameterTypeInfo {\n  ParameterTypeInfo info = {.type = TypeExpr::None, .want_ref_pattern = false};\n\n  // Perform some custom mapping for parameters of reference type:\n  //\n  //   * `T& x` -> `ref x: T`.\n  //   * `const T& x` -> `x: T`.\n  //   * `T&& x` -> `x: T`.\n  //\n  // TODO: For the `&&` mapping, we allow an rvalue reference to bind to a\n  // durable reference expression. This should not be allowed.\n  if (param_type->isReferenceType()) {\n    clang::QualType pointee_type = param_type->getPointeeType();\n    if (param_type->isLValueReferenceType()) {\n      if (pointee_type.isConstQualified()) {\n        // TODO: Consider only doing this if `const` is the only qualifier. For\n        // now, any other qualifier will fail when mapping the type.\n        auto split_type = pointee_type.getSplitUnqualifiedType();\n        split_type.Quals.removeConst();\n        pointee_type = context.ast_context().getQualifiedType(split_type);\n      } else {\n        // The reference will map to a `ref` pattern.\n        info.want_ref_pattern = true;\n      }\n    }\n    param_type = pointee_type;\n  }\n\n  info.type = MapType(context, loc_id, param_type);\n  return info;\n}\n\n// Returns a block for the implicit parameters of the given function\n// declaration. Because function templates are not yet supported, this currently\n// only contains the `self` parameter. On error, produces a diagnostic and\n// returns None.\nstatic auto MakeImplicitParamPatternsBlockId(\n    Context& context, SemIR::LocId loc_id,\n    const clang::FunctionDecl& clang_decl) -> SemIR::InstBlockId {\n  const auto* method_decl = dyn_cast<clang::CXXMethodDecl>(&clang_decl);\n  if (!method_decl || method_decl->isStatic() ||\n      isa<clang::CXXConstructorDecl>(clang_decl)) {\n    return SemIR::InstBlockId::Empty;\n  }\n\n  // Build a `self` parameter from the object parameter.\n  BeginSubpattern(context);\n\n  clang::QualType param_type =\n      method_decl->getFunctionObjectParameterReferenceType();\n  auto param_info = MapParameterType(context, loc_id, param_type);\n  auto [type_inst_id, type_id] = param_info.type;\n  SemIR::ExprRegionId type_expr_region_id =\n      EndSubpatternAsExpr(context, type_inst_id);\n\n  if (!type_id.has_value()) {\n    context.TODO(loc_id,\n                 llvm::formatv(\"Unsupported: object parameter type: {0}\",\n                               param_type.getAsString()));\n    return SemIR::InstBlockId::None;\n  }\n\n  // TODO: Fill in a location once available.\n  auto pattern_id = AddParamPattern(context, loc_id, SemIR::NameId::SelfValue,\n                                    type_expr_region_id, type_id,\n                                    param_info.want_ref_pattern);\n\n  return context.inst_blocks().Add({pattern_id});\n}\n\n// Returns a block id for the explicit parameters of the given function\n// declaration. If the function declaration has no parameters, it returns\n// `SemIR::InstBlockId::Empty`. In the case of an unsupported parameter type, it\n// produces an error and returns `SemIR::InstBlockId::None`. `signature`\n// specifies how to convert the C++ signature to the Carbon signature.\n// TODO: Consider refactoring to extract and reuse more logic from\n// `HandleAnyBindingPattern()`.\nstatic auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,\n                                     const clang::FunctionDecl& clang_decl,\n                                     SemIR::ClangDeclKey::Signature signature)\n    -> SemIR::InstBlockId {\n  llvm::SmallVector<SemIR::InstId> param_ids;\n  llvm::SmallVector<SemIR::InstId> param_type_ids;\n  param_ids.reserve(signature.num_params);\n  param_type_ids.reserve(signature.num_params);\n  CARBON_CHECK(static_cast<int>(clang_decl.getNumNonObjectParams()) >=\n                   signature.num_params,\n               \"Function has fewer parameters than requested: {0} < {1}\",\n               clang_decl.getNumNonObjectParams(), signature.num_params);\n  const auto* function_type =\n      clang_decl.getType()->castAs<clang::FunctionProtoType>();\n  for (int i : llvm::seq(signature.num_params)) {\n    const auto* param = clang_decl.getNonObjectParameter(i);\n    clang::QualType orig_param_type = function_type->getParamType(\n        clang_decl.hasCXXExplicitFunctionObjectParameter() + i);\n\n    // The parameter type is decayed but hasn't necessarily had its qualifiers\n    // removed.\n    // TODO: The presence of qualifiers here is probably a Clang bug.\n    clang::QualType param_type =\n        ClangGetUnqualifiedTypePreserveNonNull(context, orig_param_type);\n\n    // Mark the start of a region of insts, needed for the type expression\n    // created later with the call of `EndSubpatternAsExpr()`.\n    BeginSubpattern(context);\n    auto param_info = MapParameterType(context, loc_id, param_type);\n    auto [type_inst_id, type_id] = param_info.type;\n    // Type expression of the binding pattern - a single-entry/single-exit\n    // region that allows control flow in the type expression e.g. fn F(x: if C\n    // then i32 else i64).\n    SemIR::ExprRegionId type_expr_region_id =\n        EndSubpatternAsExpr(context, type_inst_id);\n\n    if (!type_id.has_value()) {\n      context.TODO(loc_id, llvm::formatv(\"Unsupported: parameter type: {0}\",\n                                         orig_param_type.getAsString()));\n      return SemIR::InstBlockId::None;\n    }\n\n    llvm::StringRef param_name = param->getName();\n    SemIR::NameId name_id =\n        param_name.empty()\n            // Translate an unnamed parameter to an underscore to\n            // match Carbon's naming of unnamed/unused function params.\n            ? SemIR::NameId::Underscore\n            : AddIdentifierName(context, param_name);\n\n    SemIR::LocId param_loc_id =\n        AddImportIRInst(context.sem_ir(), param->getLocation());\n\n    // TODO: Add template support.\n    SemIR::InstId pattern_id =\n        AddParamPattern(context, param_loc_id, name_id, type_expr_region_id,\n                        type_id, param_info.want_ref_pattern);\n    param_ids.push_back(pattern_id);\n    param_type_ids.push_back(type_inst_id);\n  }\n\n  switch (signature.kind) {\n    case SemIR::ClangDeclKey::Signature::Normal: {\n      // Use the converted parameter list as-is.\n      break;\n    }\n\n    case SemIR::ClangDeclKey::Signature::TuplePattern: {\n      // Replace the parameters with a single tuple pattern containing the\n      // converted parameter list.\n      auto param_block_id = context.inst_blocks().Add(param_ids);\n      auto tuple_pattern_type_id =\n          GetPatternType(context, GetTupleType(context, param_type_ids));\n      SemIR::InstId pattern_id = AddPatternInst(\n          context,\n          SemIR::LocIdAndInst::UncheckedLoc(\n              loc_id, SemIR::TuplePattern{.type_id = tuple_pattern_type_id,\n                                          .elements_id = param_block_id}));\n      param_ids = {pattern_id};\n      break;\n    }\n  }\n\n  return context.inst_blocks().Add(param_ids);\n}\n\n// Returns the return `TypeExpr` of the given function declaration. In case of\n// an unsupported return type, returns `SemIR::ErrorInst::InstId`. Constructors\n// are treated as returning a class instance.\n// TODO: Support more return types.\nstatic auto GetReturnTypeExpr(Context& context, SemIR::LocId loc_id,\n                              clang::FunctionDecl* clang_decl)\n    -> Context::FormExpr {\n  auto make_init_form = [&](SemIR::TypeInstId type_component_inst_id) {\n    SemIR::InitForm inst = {.type_id = SemIR::FormType::TypeId,\n                            .type_component_inst_id = type_component_inst_id};\n    return context.constant_values().GetInstId(TryEvalInst(context, inst));\n  };\n  auto make_ref_form = [&](SemIR::TypeInstId type_component_inst_id) {\n    SemIR::RefForm inst = {.type_id = SemIR::FormType::TypeId,\n                           .type_component_inst_id = type_component_inst_id};\n    return context.constant_values().GetInstId(TryEvalInst(context, inst));\n  };\n  clang::QualType orig_ret_type = clang_decl->getReturnType();\n  if (!orig_ret_type->isVoidType()) {\n    bool is_reference = orig_ret_type->isReferenceType();\n    if (is_reference) {\n      orig_ret_type = orig_ret_type->getPointeeType();\n    }\n    // TODO: We should eventually map reference returns to non-pointer types\n    // here. We should return by `ref` for `T&` return types once `ref` return\n    // is implemented.\n    auto [orig_type_inst_id, type_id] = MapType(context, loc_id, orig_ret_type);\n    if (!orig_type_inst_id.has_value()) {\n      context.TODO(loc_id, llvm::formatv(\"Unsupported: return type: {0}\",\n                                         orig_ret_type.getAsString()));\n      return Context::FormExpr::Error;\n    }\n    Context::FormExpr result = {\n        .form_inst_id = is_reference ? make_ref_form(orig_type_inst_id)\n                                     : make_init_form(orig_type_inst_id),\n        .type_component_inst_id = orig_type_inst_id,\n        .type_component_id = type_id};\n\n    return result;\n  }\n\n  auto* ctor = dyn_cast<clang::CXXConstructorDecl>(clang_decl);\n  if (!ctor) {\n    // void.\n    return {.form_inst_id = SemIR::InstId::None,\n            .type_component_inst_id = SemIR::TypeInstId::None,\n            .type_component_id = SemIR::TypeId::None};\n  }\n\n  // TODO: Make this a `PartialType`.\n  SemIR::TypeInstId record_type_inst_id = context.types().GetAsTypeInstId(\n      LookupClangDeclInstId(context, SemIR::ClangDeclKey(ctor->getParent())));\n  return {.form_inst_id = make_init_form(record_type_inst_id),\n          .type_component_inst_id = record_type_inst_id,\n          .type_component_id =\n              context.types().GetTypeIdForTypeInstId(record_type_inst_id)};\n}\n\n// Information about a function's declared return type, corresponding to the\n// fields of SemIR::Function with the same names.\nstruct ReturnInfo {\n  SemIR::TypeInstId return_type_inst_id;\n  SemIR::InstId return_form_inst_id;\n  SemIR::InstBlockId return_patterns_id;\n};\n\n// Returns information about the declared return type of the given function\n// declaration. In case of an unsupported return type, it produces a diagnostic,\n// and the returned return_type_inst_id will be `SemIR::ErrorInst::InstId`.\n// Constructors are treated as returning a class instance.\nstatic auto GetReturnInfo(Context& context, SemIR::LocId loc_id,\n                          clang::FunctionDecl* clang_decl) -> ReturnInfo {\n  auto [form_inst_id, type_inst_id, type_id] =\n      GetReturnTypeExpr(context, loc_id, clang_decl);\n  if (!form_inst_id.has_value()) {\n    // void.\n    return {.return_type_inst_id = SemIR::TypeInstId::None,\n            .return_form_inst_id = SemIR::InstId::None,\n            .return_patterns_id = SemIR::InstBlockId::None};\n  }\n  if (form_inst_id == SemIR::ErrorInst::InstId) {\n    return {.return_type_inst_id = SemIR::ErrorInst::TypeInstId,\n            .return_form_inst_id = SemIR::ErrorInst::InstId,\n            .return_patterns_id = SemIR::InstBlockId::None};\n  }\n  auto pattern_type_id = GetPatternType(context, type_id);\n  clang::SourceLocation return_type_loc =\n      clang_decl->getReturnTypeSourceRange().getBegin();\n  if (return_type_loc.isInvalid()) {\n    // TODO: While `getReturnTypeSourceRange()` should work, it seems broken for\n    // trailing return type. See\n    // https://github.com/llvm/llvm-project/issues/162649. Until this is fixed,\n    // we fallback to `getTypeSpecStartLoc()`.\n    return_type_loc = clang_decl->getTypeSpecStartLoc();\n  }\n  SemIR::ImportIRInstId return_type_import_ir_inst_id =\n      AddImportIRInst(context.sem_ir(), return_type_loc);\n  auto return_patterns_id = SemIR::InstBlockId::Empty;\n  if (auto init_form =\n          context.insts().TryGetAs<SemIR::InitForm>(form_inst_id)) {\n    SemIR::InstId return_slot_pattern_id = AddPatternInst(\n        context, MakeImportedLocIdAndInst(\n                     context, return_type_import_ir_inst_id,\n                     SemIR::ReturnSlotPattern({.type_id = pattern_type_id,\n                                               .type_inst_id = type_inst_id})));\n    auto param_pattern_id = AddPatternInst(\n        context,\n        MakeImportedLocIdAndInst(\n            context, return_type_import_ir_inst_id,\n            SemIR::OutParamPattern({.type_id = pattern_type_id,\n                                    .subpattern_id = return_slot_pattern_id})));\n    return_patterns_id = context.inst_blocks().Add({param_pattern_id});\n  }\n  return {.return_type_inst_id = type_inst_id,\n          .return_form_inst_id = form_inst_id,\n          .return_patterns_id = return_patterns_id};\n}\n\nnamespace {\n// Represents the insts and inst blocks associated with the parameters and\n// returns of a function declaration, corresponding to the fields of\n// SemIR::Function with the same names.\nstruct FunctionSignatureInsts {\n  SemIR::InstBlockId implicit_param_patterns_id;\n  SemIR::InstBlockId param_patterns_id;\n  SemIR::TypeInstId return_type_inst_id;\n  SemIR::InstId return_form_inst_id;\n  SemIR::InstBlockId return_patterns_id;\n  SemIR::InstBlockId call_param_patterns_id;\n  SemIR::InstBlockId call_params_id;\n  SemIR::Function::CallParamIndexRanges param_ranges;\n};\n}  // namespace\n\n// Creates the insts and inst blocks that represent the parameters and returns\n// of the given C++ function's Carbon counterpart, including emitting a callee\n// pattern match to create the `Call` parameters, and returns a\n// FunctionSignatureInsts containing the results. Produces a diagnostic and\n// returns `std::nullopt` if the function declaration has an unsupported\n// parameter type. `signature` specifies how to convert the C++ function\n// signature to the Carbon function signature.\nstatic auto CreateFunctionSignatureInsts(\n    Context& context, SemIR::LocId loc_id, clang::FunctionDecl* clang_decl,\n    SemIR::ClangDeclKey::Signature signature)\n    -> std::optional<FunctionSignatureInsts> {\n  context.full_pattern_stack().StartImplicitParamList();\n  auto implicit_param_patterns_id =\n      MakeImplicitParamPatternsBlockId(context, loc_id, *clang_decl);\n  if (!implicit_param_patterns_id.has_value()) {\n    return std::nullopt;\n  }\n  context.full_pattern_stack().EndImplicitParamList();\n  context.full_pattern_stack().StartExplicitParamList();\n  auto param_patterns_id =\n      MakeParamPatternsBlockId(context, loc_id, *clang_decl, signature);\n  if (!param_patterns_id.has_value()) {\n    return std::nullopt;\n  }\n  context.full_pattern_stack().EndExplicitParamList();\n  auto [return_type_inst_id, return_form_inst_id, return_patterns_id] =\n      GetReturnInfo(context, loc_id, clang_decl);\n  if (return_type_inst_id == SemIR::ErrorInst::TypeInstId) {\n    return std::nullopt;\n  }\n\n  auto match_results =\n      CalleePatternMatch(context, implicit_param_patterns_id, param_patterns_id,\n                         return_patterns_id);\n\n  return {{.implicit_param_patterns_id = implicit_param_patterns_id,\n           .param_patterns_id = param_patterns_id,\n           .return_type_inst_id = return_type_inst_id,\n           .return_form_inst_id = return_form_inst_id,\n           .return_patterns_id = return_patterns_id,\n           .call_param_patterns_id = match_results.call_param_patterns_id,\n           .call_params_id = match_results.call_params_id,\n           .param_ranges = match_results.param_ranges}};\n}\n\n// Returns the Carbon function name for the given function.\nstatic auto GetFunctionName(Context& context, clang::FunctionDecl* clang_decl)\n    -> SemIR::NameId {\n  switch (clang_decl->getDeclName().getNameKind()) {\n    case clang::DeclarationName::CXXConstructorName: {\n      auto key = SemIR::ClangDeclKey(\n          cast<clang::CXXConstructorDecl>(clang_decl)->getParent());\n      return context.classes()\n          .Get(context.insts()\n                   .GetAs<SemIR::ClassDecl>(LookupClangDeclInstId(context, key))\n                   .class_id)\n          .name_id;\n    }\n\n    case clang::DeclarationName::CXXDestructorName: {\n      return SemIR::NameId::CppDestructor;\n    }\n\n    case clang::DeclarationName::CXXOperatorName:\n    case clang::DeclarationName::CXXConversionFunctionName: {\n      return SemIR::NameId::CppOperator;\n    }\n\n    default: {\n      return AddIdentifierName(context, clang_decl->getName());\n    }\n  }\n}\n\n// Creates a `FunctionDecl` and a `Function` without C++ thunk information.\n// Returns std::nullopt on failure.\n//\n// The given Clang declaration is assumed to:\n// * Have not been imported before.\n// * Be of supported type (ignoring parameters).\n//\n// `signature` specifies how to convert the C++ function signature to the Carbon\n// function signature.\nstatic auto ImportFunction(Context& context, SemIR::LocId loc_id,\n                           SemIR::ImportIRInstId import_ir_inst_id,\n                           clang::FunctionDecl* clang_decl,\n                           SemIR::ClangDeclKey::Signature signature)\n    -> std::optional<SemIR::FunctionId> {\n  StartFunctionSignature(context);\n\n  auto function_params_insts =\n      CreateFunctionSignatureInsts(context, loc_id, clang_decl, signature);\n\n  auto [pattern_block_id, decl_block_id] =\n      FinishFunctionSignature(context, /*check_unused=*/false);\n\n  if (!function_params_insts.has_value()) {\n    return std::nullopt;\n  }\n\n  auto virtual_modifier = SemIR::Function::VirtualModifier::None;\n  int32_t virtual_index = -1;\n  if (auto* method_decl = dyn_cast<clang::CXXMethodDecl>(clang_decl)) {\n    if (method_decl->size_overridden_methods()) {\n      virtual_modifier = SemIR::Function::VirtualModifier::Override;\n    } else if (method_decl->isVirtual()) {\n      virtual_modifier = SemIR::Function::VirtualModifier::Virtual;\n    }\n    if (virtual_modifier != SemIR::Function::VirtualModifier::None) {\n      // TODO: Add support for Microsoft/non-Itanium vtables.\n      virtual_index = dyn_cast<clang::ItaniumVTableContext>(\n                          context.ast_context().getVTableContext())\n                          ->getMethodVTableIndex(method_decl);\n    }\n  }\n\n  SemIR::FunctionFields::EvaluationMode evaluation_mode =\n      SemIR::FunctionFields::EvaluationMode::None;\n  if (clang_decl->isConsteval()) {\n    evaluation_mode = SemIR::FunctionFields::EvaluationMode::MustEval;\n  } else if (clang_decl->isConstexpr()) {\n    evaluation_mode = SemIR::FunctionFields::EvaluationMode::Eval;\n  }\n\n  auto [decl_id, function_id] = MakeFunctionDecl(\n      context, import_ir_inst_id, decl_block_id, /*build_generic=*/false,\n      /*is_definition=*/false,\n      SemIR::Function{\n          {\n              .name_id = GetFunctionName(context, clang_decl),\n              .parent_scope_id = GetParentNameScopeId(context, clang_decl),\n              .generic_id = SemIR::GenericId::None,\n              .first_param_node_id = Parse::NodeId::None,\n              .last_param_node_id = Parse::NodeId::None,\n              .pattern_block_id = pattern_block_id,\n              .implicit_param_patterns_id =\n                  function_params_insts->implicit_param_patterns_id,\n              .param_patterns_id = function_params_insts->param_patterns_id,\n              .is_extern = false,\n              .extern_library_id = SemIR::LibraryNameId::None,\n              .non_owning_decl_id = SemIR::InstId::None,\n              // Set by `MakeFunctionDecl`.\n              .first_owning_decl_id = SemIR::InstId::None,\n          },\n          {\n              .call_param_patterns_id =\n                  function_params_insts->call_param_patterns_id,\n              .call_params_id = function_params_insts->call_params_id,\n              .call_param_ranges = function_params_insts->param_ranges,\n              .return_type_inst_id = function_params_insts->return_type_inst_id,\n              .return_form_inst_id = function_params_insts->return_form_inst_id,\n              .return_patterns_id = function_params_insts->return_patterns_id,\n              .virtual_modifier = virtual_modifier,\n              .virtual_index = virtual_index,\n              .evaluation_mode = evaluation_mode,\n              .self_param_id = FindSelfPattern(\n                  context, function_params_insts->implicit_param_patterns_id),\n          }});\n  context.imports().push_back(decl_id);\n\n  context.functions().Get(function_id).clang_decl_id =\n      context.clang_decls().Add(\n          {.key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature),\n           .inst_id = decl_id});\n\n  return function_id;\n}\n\n// Imports a C++ function, returning a corresponding Carbon function.\n// `signature` specifies how to convert the C++ function signature to the Carbon\n// function signature. `signature.num_params` may be less than the number of\n// parameters that the C++ function has if default arguments are available for\n// the trailing parameters.\nstatic auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,\n                               clang::FunctionDecl* clang_decl,\n                               SemIR::ClangDeclKey::Signature signature)\n    -> SemIR::InstId {\n  auto key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature);\n\n  // Check if the declaration is already mapped.\n  if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key);\n      existing_inst_id.has_value()) {\n    return existing_inst_id;\n  }\n\n  if (clang_decl->isVariadic()) {\n    context.TODO(loc_id, \"Unsupported: Variadic function\");\n    MarkFailedDecl(context, key);\n    return SemIR::ErrorInst::InstId;\n  }\n\n  if (clang_decl->getTemplatedKind() ==\n      clang::FunctionDecl::TK_FunctionTemplate) {\n    context.TODO(loc_id, \"Unsupported: Template function\");\n    MarkFailedDecl(context, key);\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto import_ir_inst_id =\n      AddImportIRInst(context.sem_ir(), clang_decl->getLocation());\n\n  CARBON_CHECK(clang_decl->getFunctionType()->isFunctionProtoType(),\n               \"Not Prototype function (non-C++ code)\");\n  auto function_id =\n      ImportFunction(context, loc_id, import_ir_inst_id, clang_decl, signature);\n  if (!function_id) {\n    MarkFailedDecl(context, key);\n    return SemIR::ErrorInst::InstId;\n  }\n\n  SemIR::Function& function_info = context.functions().Get(*function_id);\n  if (IsCppThunkRequired(context, function_info)) {\n    Diagnostics::AnnotationScope annotate_diagnostics(\n        &context.emitter(), [&](auto& builder) {\n          CARBON_DIAGNOSTIC(InCppThunk, Note,\n                            \"in thunk for C++ function used here\");\n          builder.Note(loc_id, InCppThunk);\n        });\n\n    if (clang::FunctionDecl* thunk_clang_decl =\n            BuildCppThunk(context, function_info)) {\n      if (auto thunk_function_id = ImportFunction(\n              context, loc_id, import_ir_inst_id, thunk_clang_decl,\n              {.num_params =\n                   static_cast<int32_t>(thunk_clang_decl->getNumParams())})) {\n        SemIR::InstId thunk_function_decl_id =\n            context.functions().Get(*thunk_function_id).first_owning_decl_id;\n        function_info.SetHasCppThunk(thunk_function_decl_id);\n      }\n    }\n  } else {\n    // Inform Clang that the function has been referenced. This will trigger\n    // instantiation if needed.\n    context.clang_sema().MarkFunctionReferenced(GetCppLocation(context, loc_id),\n                                                clang_decl);\n\n    // If the function is trivial, mark it as being a builtin if possible.\n    if (clang_decl->isTrivial()) {\n      // Trivial destructors map to a \"no_op\" builtin.\n      if (isa<clang::CXXDestructorDecl>(clang_decl)) {\n        function_info.SetBuiltinFunction(SemIR::BuiltinFunctionKind::NoOp);\n      }\n      // TODO: Should we model a trivial default constructor as performing\n      // value-initialization (zero-initializing all fields) or\n      // default-initialization (leaving fields uniniitalized)? Either way we\n      // could model that effect as a builtin.\n      // TODO: Add a builtin to model trivial copies.\n    }\n  }\n\n  return function_info.first_owning_decl_id;\n}\n\nnamespace {\n// An item to be imported in an import worklist.\n// TODO: If worklists ever become particularly large, consider changing this\n// to use a `PointerIntPair`.\nstruct ImportItem {\n  // A declaration that we want to import.\n  SemIR::ClangDeclKey decl_key;\n  // Whether we have added `decl`'s dependencies to the worklist.\n  bool added_dependencies;\n};\n// A worklist of declarations to import.\nusing ImportWorklist = llvm::SmallVector<ImportItem>;\n}  // namespace\n\n// Adds the given declaration to our list of declarations to import.\nstatic auto AddDependentDecl(Context& context, SemIR::ClangDeclKey decl,\n                             ImportWorklist& worklist) -> void {\n  if (!IsClangDeclImported(context, decl)) {\n    worklist.push_back({.decl_key = decl, .added_dependencies = false});\n  }\n}\n\n// Finds all decls that need to be imported before importing the given type and\n// adds them to the given set.\nstatic auto AddDependentUnimportedTypeDecls(Context& context,\n                                            clang::QualType type,\n                                            ImportWorklist& worklist) -> void {\n  while (true) {\n    if (type->isPointerType() || type->isReferenceType()) {\n      type = type->getPointeeType();\n    } else if (const clang::ArrayType* array_type =\n                   type->getAsArrayTypeUnsafe()) {\n      type = array_type->getElementType();\n    } else {\n      break;\n    }\n  }\n\n  if (const auto* tag_type = type->getAs<clang::TagType>()) {\n    AddDependentDecl(context, SemIR::ClangDeclKey(tag_type->getDecl()),\n                     worklist);\n  }\n}\n\n// Finds all decls that need to be imported before importing the given function\n// and adds them to the given set.\nstatic auto AddDependentUnimportedFunctionDecls(\n    Context& context, const clang::FunctionDecl& clang_decl,\n    SemIR::ClangDeclKey::Signature signature, ImportWorklist& worklist)\n    -> void {\n  const auto* function_type =\n      clang_decl.getType()->castAs<clang::FunctionProtoType>();\n  for (int i : llvm::seq(clang_decl.hasCXXExplicitFunctionObjectParameter() +\n                         signature.num_params)) {\n    AddDependentUnimportedTypeDecls(context, function_type->getParamType(i),\n                                    worklist);\n  }\n  AddDependentUnimportedTypeDecls(context, clang_decl.getReturnType(),\n                                  worklist);\n}\n\n// Finds all decls that need to be imported before importing the given\n// declaration and adds them to the given set.\nstatic auto AddDependentUnimportedDecls(Context& context,\n                                        SemIR::ClangDeclKey key,\n                                        ImportWorklist& worklist) -> void {\n  clang::Decl* clang_decl = key.decl;\n  if (auto* clang_function_decl = clang_decl->getAsFunction()) {\n    AddDependentUnimportedFunctionDecls(context, *clang_function_decl,\n                                        key.signature, worklist);\n  } else if (auto* type_decl = dyn_cast<clang::TypeDecl>(clang_decl)) {\n    if (!isa<clang::TagDecl>(clang_decl)) {\n      AddDependentUnimportedTypeDecls(\n          context, type_decl->getASTContext().getTypeDeclType(type_decl),\n          worklist);\n    }\n  } else if (auto* var_decl = dyn_cast<clang::VarDecl>(clang_decl)) {\n    AddDependentUnimportedTypeDecls(context, var_decl->getType(), worklist);\n  }\n  auto* parent = GetParentDecl(clang_decl);\n  if (llvm::isa_and_nonnull<clang::TagDecl, clang::NamespaceDecl,\n                            clang::TranslationUnitDecl>(parent)) {\n    AddDependentDecl(context, SemIR::ClangDeclKey::ForNonFunctionDecl(parent),\n                     worklist);\n  }\n}\n\nstatic auto ImportVarDecl(Context& context, SemIR::LocId loc_id,\n                          clang::VarDecl* var_decl) -> SemIR::InstId {\n  if (SemIR::InstId existing_inst_id =\n          LookupClangDeclInstId(context, SemIR::ClangDeclKey(var_decl));\n      existing_inst_id.has_value()) {\n    return existing_inst_id;\n  }\n\n  // Extract type and name.\n  clang::QualType var_type = var_decl->getType();\n  SemIR::TypeId var_type_id = MapType(context, loc_id, var_type).type_id;\n  if (!var_type_id.has_value()) {\n    context.TODO(loc_id, llvm::formatv(\"Unsupported: var type: {0}\",\n                                       var_type.getAsString()));\n    return SemIR::ErrorInst::InstId;\n  }\n  SemIR::NameId var_name_id = AddIdentifierName(context, var_decl->getName());\n\n  // Create an entity name to identify this variable.\n  SemIR::EntityNameId entity_name_id = context.entity_names().Add(\n      {.name_id = var_name_id,\n       .parent_scope_id = GetParentNameScopeId(context, var_decl),\n       .is_unused = false});\n\n  // Create `RefBindingPattern` and `VarPattern`. Mirror the behavior of\n  // import_ref and don't create a `NameBindingDecl` here; we'd never use it for\n  // anything.\n  SemIR::TypeId pattern_type_id = GetPatternType(context, var_type_id);\n  SemIR::InstId binding_pattern_inst_id =\n      AddInstInNoBlock<SemIR::RefBindingPattern>(\n          context, loc_id,\n          {.type_id = pattern_type_id, .entity_name_id = entity_name_id});\n  context.imports().push_back(binding_pattern_inst_id);\n  auto pattern_id = AddInstInNoBlock<SemIR::VarPattern>(\n      context, Parse::VariablePatternId::None,\n      {.type_id = pattern_type_id, .subpattern_id = binding_pattern_inst_id});\n  context.imports().push_back(pattern_id);\n\n  // Create the imported storage for the global. We intentionally use the\n  // untyped form of `AddInstInNoBlock` to bypass the check on adding an\n  // instruction that requires a cleanup, because we don't want a cleanup here!\n  SemIR::InstId var_storage_inst_id = AddInstInNoBlock(\n      context, {loc_id, SemIR::VarStorage{.type_id = var_type_id,\n                                          .pattern_id = pattern_id}});\n  context.imports().push_back(var_storage_inst_id);\n\n  // Register the variable so we don't create it again, and track the\n  // corresponding declaration to use for mangling.\n  auto clang_decl_id = context.clang_decls().Add(\n      {.key = SemIR::ClangDeclKey(var_decl), .inst_id = var_storage_inst_id});\n  context.cpp_global_names().Add({.key = {.entity_name_id = entity_name_id},\n                                  .clang_decl_id = clang_decl_id});\n\n  // Inform Clang that the variable has been referenced.\n  context.clang_sema().MarkVariableReferenced(GetCppLocation(context, loc_id),\n                                              var_decl);\n\n  return var_storage_inst_id;\n}\n\nstatic auto ImportTemplateDecl(Context& context,\n                               clang::TemplateDecl* template_decl)\n    -> SemIR::InstId {\n  auto key = SemIR::ClangDeclKey(template_decl);\n\n  // TODO: Avoid doing this lookup both here and in the insertion below.\n  if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key);\n      existing_inst_id.has_value()) {\n    return existing_inst_id;\n  }\n\n  // Add a placeholder instruction to resolve cycle between the clang\n  // declaration and the type.\n  auto import_loc_id =\n      AddImportIRInst(context.sem_ir(), template_decl->getLocation());\n  SemIR::StructValue value = {.type_id = SemIR::TypeId::None,\n                              .elements_id = SemIR::InstBlockId::Empty};\n  auto inst_id = AddPlaceholderImportedInstInNoBlock(\n      context, MakeImportedLocIdAndInst(context, import_loc_id, value));\n\n  // Create a type for the constant value.\n  auto name_id = context.entity_names().Add(\n      {.name_id = AddIdentifierName(context, template_decl->getName()),\n       .parent_scope_id = GetParentNameScopeId(context, template_decl)});\n  auto decl_id = context.clang_decls().Add({.key = key, .inst_id = inst_id});\n  value.type_id = GetCppTemplateNameType(context, name_id, decl_id);\n\n  // Update the value with its type.\n  ReplaceInstBeforeConstantUse(context, inst_id, value);\n  return inst_id;\n}\n\n// Imports a declaration from Clang to Carbon. Returns the instruction for the\n// new Carbon declaration, which will be an ErrorInst on failure. Assumes all\n// dependencies have already been imported.\nstatic auto ImportDeclAfterDependencies(Context& context, SemIR::LocId loc_id,\n                                        SemIR::ClangDeclKey key)\n    -> SemIR::InstId {\n  clang::Decl* clang_decl = key.decl;\n  if (auto* clang_function_decl = clang_decl->getAsFunction()) {\n    return ImportFunctionDecl(context, loc_id, clang_function_decl,\n                              key.signature);\n  }\n  if (auto* clang_namespace_decl = dyn_cast<clang::NamespaceDecl>(clang_decl)) {\n    return ImportNamespaceDecl(context, clang_namespace_decl);\n  }\n  if (auto* type_decl = dyn_cast<clang::TypeDecl>(clang_decl)) {\n    auto type = clang_decl->getASTContext().getTypeDeclType(type_decl);\n    auto type_inst_id = MapType(context, loc_id, type).inst_id;\n    if (!type_inst_id.has_value()) {\n      context.TODO(AddImportIRInst(context.sem_ir(), type_decl->getLocation()),\n                   llvm::formatv(\"Unsupported: Type declaration: {0}\",\n                                 type.getAsString()));\n      return SemIR::ErrorInst::InstId;\n    }\n    context.clang_decls().Add({.key = key, .inst_id = type_inst_id});\n    return type_inst_id;\n  }\n  if (isa<clang::FieldDecl, clang::IndirectFieldDecl>(clang_decl)) {\n    // Usable fields get imported as a side effect of importing the class.\n    if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key);\n        existing_inst_id.has_value()) {\n      return existing_inst_id;\n    }\n    context.TODO(AddImportIRInst(context.sem_ir(), clang_decl->getLocation()),\n                 \"Unsupported: field declaration has unhandled type or kind\");\n    return SemIR::ErrorInst::InstId;\n  }\n  if (auto* enum_const_decl = dyn_cast<clang::EnumConstantDecl>(clang_decl)) {\n    return ImportEnumConstantDecl(context, enum_const_decl);\n  }\n  if (auto* var_decl = dyn_cast<clang::VarDecl>(clang_decl)) {\n    return ImportVarDecl(context, loc_id, var_decl);\n  }\n  if (auto* template_decl = dyn_cast<clang::TemplateDecl>(clang_decl)) {\n    return ImportTemplateDecl(context, template_decl);\n  }\n\n  context.TODO(AddImportIRInst(context.sem_ir(), clang_decl->getLocation()),\n               llvm::formatv(\"Unsupported: Declaration type {0}\",\n                             clang_decl->getDeclKindName()));\n  return SemIR::ErrorInst::InstId;\n}\n\n// Attempts to import a set of declarations. Returns `false` if an error was\n// produced, `true` otherwise.\nstatic auto ImportDeclSet(Context& context, SemIR::LocId loc_id,\n                          ImportWorklist& worklist) -> bool {\n  // Walk the dependency graph in depth-first order, and import declarations\n  // once we've imported all of their dependencies.\n  while (!worklist.empty()) {\n    auto& item = worklist.back();\n    if (!item.added_dependencies) {\n      // Skip items we've already imported. We checked this when initially\n      // adding the item to the worklist, but it might have been added to the\n      // worklist twice before the first time we visited it. For example, this\n      // happens for `fn F(a: Cpp.T, b: Cpp.T)`.\n      if (IsClangDeclImported(context, item.decl_key)) {\n        worklist.pop_back();\n        continue;\n      }\n\n      // First time visiting this declaration (preorder): add its dependencies\n      // to the work list.\n      item.added_dependencies = true;\n      AddDependentUnimportedDecls(context, item.decl_key, worklist);\n    } else {\n      // Second time visiting this declaration (postorder): its dependencies are\n      // already imported, so we can import it now.\n      auto decl_key = worklist.pop_back_val().decl_key;\n      auto inst_id = ImportDeclAfterDependencies(context, loc_id, decl_key);\n      CARBON_CHECK(inst_id.has_value());\n      if (inst_id == SemIR::ErrorInst::InstId) {\n        return false;\n      }\n      CARBON_CHECK(IsClangDeclImported(context, decl_key));\n    }\n  }\n\n  return true;\n}\n\nauto ImportCppDecl(Context& context, SemIR::LocId loc_id,\n                   SemIR::ClangDeclKey key) -> SemIR::InstId {\n  // Collect dependencies by walking the dependency graph in depth-first order.\n  ImportWorklist worklist;\n  AddDependentDecl(context, key, worklist);\n  if (!ImportDeclSet(context, loc_id, worklist)) {\n    return SemIR::ErrorInst::InstId;\n  }\n  return LookupClangDeclInstId(context, key);\n}\n\nauto ImportCppType(Context& context, SemIR::LocId loc_id, clang::QualType type)\n    -> TypeExpr {\n  // Collect dependencies by walking the dependency graph in depth-first order.\n  ImportWorklist worklist;\n  AddDependentUnimportedTypeDecls(context, type, worklist);\n  if (!ImportDeclSet(context, loc_id, worklist)) {\n    return {.inst_id = SemIR::ErrorInst::TypeInstId,\n            .type_id = SemIR::ErrorInst::TypeId};\n  }\n  return MapType(context, loc_id, type);\n}\n\n// Imports a Clang declaration into Carbon and adds that name into the\n// `NameScope`.\nstatic auto ImportNameDeclIntoScope(Context& context, SemIR::LocId loc_id,\n                                    SemIR::NameScopeId scope_id,\n                                    SemIR::NameId name_id,\n                                    SemIR::ClangDeclKey key,\n                                    SemIR::AccessKind access_kind)\n    -> SemIR::ScopeLookupResult {\n  SemIR::InstId inst_id = ImportCppDecl(context, loc_id, key);\n  if (!inst_id.has_value()) {\n    return SemIR::ScopeLookupResult::MakeNotFound();\n  }\n  AddNameToScope(context, scope_id, name_id, access_kind, inst_id);\n  return SemIR::ScopeLookupResult::MakeWrappedLookupResult(inst_id,\n                                                           access_kind);\n}\n\n// Returns true if the scope is the top `Cpp` scope.\nstatic auto IsTopCppScope(Context& context, SemIR::NameScopeId scope_id)\n    -> bool {\n  const SemIR::NameScope& name_scope = context.name_scopes().Get(scope_id);\n  CARBON_CHECK(name_scope.is_cpp_scope());\n  return name_scope.parent_scope_id() == SemIR::NameScopeId::Package;\n}\n\n// For a builtin name like `Cpp.long`, returns the associated type.\nstatic auto LookupBuiltinName(Context& context, SemIR::LocId loc_id,\n                              SemIR::NameScopeId scope_id,\n                              SemIR::NameId name_id) -> SemIR::InstId {\n  if (!IsTopCppScope(context, scope_id)) {\n    return SemIR::InstId::None;\n  }\n\n  auto name = context.names().GetAsStringIfIdentifier(name_id);\n  if (!name) {\n    return SemIR::InstId::None;\n  }\n\n  const clang::ASTContext& ast_context = context.ast_context();\n\n  // List of types based on\n  // https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p5448.md#details\n  auto builtin_type =\n      llvm::StringSwitch<clang::QualType>(*name)\n          .Case(\"signed_char\", ast_context.SignedCharTy)\n          .Case(\"short\", ast_context.ShortTy)\n          .Case(\"int\", ast_context.IntTy)\n          .Case(\"long\", ast_context.LongTy)\n          .Case(\"long_long\", ast_context.LongLongTy)\n          .Case(\"unsigned_char\", ast_context.UnsignedCharTy)\n          .Case(\"unsigned_short\", ast_context.UnsignedShortTy)\n          .Case(\"unsigned_int\", ast_context.UnsignedIntTy)\n          .Case(\"unsigned_long\", ast_context.UnsignedLongTy)\n          .Case(\"unsigned_long_long\", ast_context.UnsignedLongLongTy)\n          .Case(\"float\", ast_context.FloatTy)\n          .Case(\"double\", ast_context.DoubleTy)\n          .Case(\"long_double\", ast_context.LongDoubleTy)\n          .Case(\"void\", ast_context.VoidTy)\n          .Default(clang::QualType());\n  if (builtin_type.isNull()) {\n    if (*name == \"nullptr\") {\n      // Map `Cpp.nullptr` to an uninitialized value of type `Core.CppNullptrT`.\n      auto type_id = MapNullptrType(context, loc_id).type_id;\n      return GetOrAddInst<SemIR::UninitializedValue>(\n          context, SemIR::LocId::None, {.type_id = type_id});\n    }\n    return SemIR::InstId::None;\n  }\n\n  SemIR::InstId inst_id =\n      MapNonWrapperType(context, loc_id, builtin_type).inst_id;\n  if (!inst_id.has_value()) {\n    context.TODO(loc_id, llvm::formatv(\"Unsupported: builtin type: {0}\",\n                                       builtin_type.getAsString()));\n    return SemIR::ErrorInst::InstId;\n  }\n  return inst_id;\n}\n\nauto ImportCppOverloadSet(\n    Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id,\n    SemIR::NameId name_id, clang::CXXRecordDecl* naming_class,\n    clang::UnresolvedSet<4>&& overload_set,\n    clang::OverloadCandidateSet::OperatorRewriteInfo operator_rewrite_info)\n    -> SemIR::InstId {\n  SemIR::CppOverloadSetId overload_set_id = context.cpp_overload_sets().Add(\n      SemIR::CppOverloadSet{.name_id = name_id,\n                            .parent_scope_id = scope_id,\n                            .naming_class = naming_class,\n                            .candidate_functions = std::move(overload_set),\n                            .operator_rewrite_info = operator_rewrite_info});\n  auto overload_set_inst_id = AddInstInNoBlock<SemIR::CppOverloadSetValue>(\n      context, loc_id,\n      {.type_id = GetCppOverloadSetType(context, overload_set_id,\n                                        SemIR::SpecificId::None),\n       .overload_set_id = overload_set_id});\n\n  context.imports().push_back(overload_set_inst_id);\n  return overload_set_inst_id;\n}\n\n// Gets the best access for an overloaded function set. This is the access that\n// we use for the overload set as a whole. More fine-grained checking is done\n// after overload resolution.\nstatic auto GetOverloadSetAccess(const clang::UnresolvedSet<4>& overload_set)\n    -> SemIR::AccessKind {\n  SemIR::AccessKind access_kind = SemIR::AccessKind::Private;\n  for (clang::DeclAccessPair overload : overload_set.pairs()) {\n    access_kind = std::min(access_kind, MapCppAccess(overload));\n    if (access_kind == SemIR::AccessKind::Public) {\n      break;\n    }\n  }\n  return access_kind;\n}\n\n// Imports an overload set from Clang to Carbon and adds the name into the\n// `NameScope`.\nstatic auto ImportOverloadSetIntoScope(Context& context, SemIR::LocId loc_id,\n                                       SemIR::NameScopeId scope_id,\n                                       SemIR::NameId name_id,\n                                       clang::CXXRecordDecl* naming_class,\n                                       clang::UnresolvedSet<4>&& overload_set)\n    -> SemIR::ScopeLookupResult {\n  SemIR::AccessKind access_kind = GetOverloadSetAccess(overload_set);\n  SemIR::InstId inst_id = ImportCppOverloadSet(\n      context, loc_id, scope_id, name_id, naming_class, std::move(overload_set),\n      /*operator_rewrite_info=*/{});\n  AddNameToScope(context, scope_id, name_id, access_kind, inst_id);\n  return SemIR::ScopeLookupResult::MakeWrappedLookupResult(inst_id,\n                                                           access_kind);\n}\n\n// Imports the constructors for a given class name. The found constructors are\n// imported as part of an overload set into the scope. Currently copy/move\n// constructors are not imported.\nstatic auto ImportConstructorsIntoScope(Context& context, SemIR::LocId loc_id,\n                                        SemIR::NameScopeId scope_id,\n                                        SemIR::NameId name_id)\n    -> SemIR::ScopeLookupResult {\n  auto* naming_class =\n      cast<clang::CXXRecordDecl>(GetDeclContext(context, scope_id));\n  clang::DeclContextLookupResult constructors_lookup =\n      context.clang_sema().LookupConstructors(naming_class);\n\n  clang::UnresolvedSet<4> overload_set;\n  for (auto* decl : constructors_lookup) {\n    auto info = clang::getConstructorInfo(decl);\n    if (!info.Constructor || info.Constructor->isCopyOrMoveConstructor()) {\n      continue;\n    }\n    overload_set.addDecl(info.FoundDecl, info.FoundDecl.getAccess());\n  }\n  if (overload_set.empty()) {\n    return SemIR::ScopeLookupResult::MakeNotFound();\n  }\n\n  return ImportOverloadSetIntoScope(context, loc_id, scope_id, name_id,\n                                    naming_class, std::move(overload_set));\n}\n\n// Attempts to import a builtin name from Clang to Carbon and adds the name into\n// the scope.\nstatic auto ImportBuiltinNameIntoScope(Context& context, SemIR::LocId loc_id,\n                                       SemIR::NameScopeId scope_id,\n                                       SemIR::NameId name_id)\n    -> SemIR::ScopeLookupResult {\n  SemIR::InstId builtin_inst_id =\n      LookupBuiltinName(context, loc_id, scope_id, name_id);\n  if (builtin_inst_id.has_value()) {\n    AddNameToScope(context, scope_id, name_id, SemIR::AccessKind::Public,\n                   builtin_inst_id);\n    return SemIR::ScopeLookupResult::MakeWrappedLookupResult(\n        builtin_inst_id, SemIR::AccessKind::Public);\n  }\n  return SemIR::ScopeLookupResult::MakeNotFound();\n}\n\n// Checks if the name scope is a class that is not complete.\nstatic auto IsIncompleteClass(Context& context, SemIR::NameScopeId scope_id)\n    -> bool {\n  auto class_decl = context.insts().TryGetAs<SemIR::ClassDecl>(\n      context.name_scopes().Get(scope_id).inst_id());\n  return class_decl.has_value() &&\n         !context.types().IsComplete(\n             context.classes().Get(class_decl->class_id).self_type_id);\n}\n\n// Imports a macro definition into the scope. Currently supports only simple\n// object-like macros that expand to a constant integer value.\n// TODO: Add support for other macro types and non-integer literal values.\nstatic auto ImportMacro(Context& context, SemIR::LocId loc_id,\n                        SemIR::NameScopeId scope_id, SemIR::NameId name_id,\n                        clang::MacroInfo* macro_info)\n    -> SemIR::ScopeLookupResult {\n  auto inst_id = TryEvaluateMacro(context, loc_id, name_id, macro_info);\n  if (inst_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ScopeLookupResult::MakeNotFound();\n  }\n\n  AddNameToScope(context, scope_id, name_id, SemIR::AccessKind::Public,\n                 inst_id);\n  return SemIR::ScopeLookupResult::MakeWrappedLookupResult(\n      inst_id, SemIR::AccessKind::Public);\n}\n\n// Looks up a macro definition in the top-level `Cpp` scope. Returns nullptr if\n// the macro is not found or if it is a builtin macro, function-like macro or a\n// macro used for header guards.\n// TODO: Function-like and builtin macros are currently not supported and their\n// support still needs to be clarified.\nstatic auto LookupMacro(Context& context, SemIR::NameScopeId scope_id,\n                        clang::IdentifierInfo* identifier_info)\n    -> clang::MacroInfo* {\n  if (!IsTopCppScope(context, scope_id)) {\n    return nullptr;\n  }\n  CARBON_CHECK(identifier_info, \"Identifier info is empty\");\n  clang::MacroInfo* macro_info =\n      context.clang_sema().getPreprocessor().getMacroInfo(identifier_info);\n  if (macro_info && !macro_info->isUsedForHeaderGuard() &&\n      !macro_info->isFunctionLike() && !macro_info->isBuiltinMacro()) {\n    return macro_info;\n  }\n\n  return nullptr;\n}\n\nauto GetClangIdentifierInfo(Context& context, SemIR::NameId name_id)\n    -> clang::IdentifierInfo* {\n  std::optional<llvm::StringRef> string_name =\n      context.names().GetAsStringIfIdentifier(name_id);\n  if (!string_name) {\n    return nullptr;\n  }\n  clang::IdentifierInfo* identifier_info =\n      context.clang_sema().getPreprocessor().getIdentifierInfo(*string_name);\n  return identifier_info;\n}\n\nauto ImportNameFromCpp(Context& context, SemIR::LocId loc_id,\n                       SemIR::NameScopeId scope_id, SemIR::NameId name_id)\n    -> SemIR::ScopeLookupResult {\n  Diagnostics::AnnotationScope annotate_diagnostics(\n      &context.emitter(), [&](auto& builder) {\n        CARBON_DIAGNOSTIC(InCppNameLookup, Note,\n                          \"in `Cpp` name lookup for `{0}`\", SemIR::NameId);\n        builder.Note(loc_id, InCppNameLookup, name_id);\n      });\n  if (IsIncompleteClass(context, scope_id)) {\n    return SemIR::ScopeLookupResult::MakeError();\n  }\n\n  clang::IdentifierInfo* identifier_info =\n      GetClangIdentifierInfo(context, name_id);\n  if (!identifier_info) {\n    return SemIR::ScopeLookupResult::MakeNotFound();\n  }\n\n  if (clang::MacroInfo* macro_info =\n          LookupMacro(context, scope_id, identifier_info)) {\n    return ImportMacro(context, loc_id, scope_id, name_id, macro_info);\n  }\n  auto lookup = ClangLookupName(context, scope_id, identifier_info);\n  if (!lookup) {\n    return ImportBuiltinNameIntoScope(context, loc_id, scope_id, name_id);\n  }\n  // Access checks are performed separately by the Carbon name lookup logic.\n  lookup->suppressAccessDiagnostics();\n\n  if (lookup->isOverloadedResult() ||\n      (lookup->isSingleResult() &&\n       lookup->getFoundDecl()->isFunctionOrFunctionTemplate())) {\n    clang::UnresolvedSet<4> overload_set;\n    overload_set.append(lookup->begin(), lookup->end());\n    return ImportOverloadSetIntoScope(context, loc_id, scope_id, name_id,\n                                      lookup->getNamingClass(),\n                                      std::move(overload_set));\n  }\n\n  if (!lookup->isSingleResult()) {\n    // Clang will diagnose ambiguous lookup results for us.\n    if (!lookup->isAmbiguous()) {\n      context.TODO(loc_id,\n                   llvm::formatv(\"Unsupported: Lookup succeeded but couldn't \"\n                                 \"find a single result; LookupResultKind: {0}\",\n                                 static_cast<int>(lookup->getResultKind())));\n    }\n    context.name_scopes().AddRequiredName(scope_id, name_id,\n                                          SemIR::ErrorInst::InstId);\n    return SemIR::ScopeLookupResult::MakeError();\n  }\n  if (IsDeclInjectedClassName(context, scope_id, name_id,\n                              lookup->getFoundDecl())) {\n    return ImportConstructorsIntoScope(context, loc_id, scope_id, name_id);\n  }\n  auto key = SemIR::ClangDeclKey::ForNonFunctionDecl(lookup->getFoundDecl());\n  return ImportNameDeclIntoScope(context, loc_id, scope_id, name_id, key,\n                                 MapCppAccess(lookup->begin().getPair()));\n}\n\nauto ImportClassDefinitionForClangDecl(Context& context,\n                                       SemIR::ClassId class_id,\n                                       SemIR::ClangDeclId clang_decl_id)\n    -> bool {\n  SemIR::CppFile* cpp_file = context.sem_ir().cpp_file();\n  CARBON_CHECK(cpp_file);\n\n  auto* clang_decl =\n      cast<clang::TagDecl>(context.clang_decls().Get(clang_decl_id).key.decl);\n  auto class_inst_id = context.types().GetAsTypeInstId(\n      context.classes().Get(class_id).first_owning_decl_id);\n\n  clang::SourceLocation loc = clang_decl->getLocation();\n  // Ask Clang whether the type is complete. This triggers template\n  // instantiation if necessary.\n  clang::DiagnosticErrorTrap trap(cpp_file->diagnostics());\n  if (!context.cpp_context()->sema().isCompleteType(\n          loc, context.ast_context().getCanonicalTagType(clang_decl))) {\n    // Type is incomplete. Nothing more to do, but tell the caller if we\n    // produced an error.\n    return !trap.hasErrorOccurred();\n  }\n\n  auto import_ir_inst_id =\n      context.insts().GetCanonicalLocId(class_inst_id).import_ir_inst_id();\n\n  if (auto* class_decl = dyn_cast<clang::CXXRecordDecl>(clang_decl)) {\n    auto* class_def = class_decl->getDefinition();\n    CARBON_CHECK(class_def, \"Complete type has no definition\");\n\n    BuildClassDefinition(context, import_ir_inst_id, class_id, class_inst_id,\n                         class_def);\n  } else if (auto* enum_decl = dyn_cast<clang::EnumDecl>(clang_decl)) {\n    BuildEnumDefinition(context, import_ir_inst_id, class_id, class_inst_id,\n                        enum_decl);\n  }\n  return true;\n}\n\nauto GetAsClangVarDecl(Context& context, SemIR::InstId inst_id)\n    -> clang::VarDecl* {\n  if (const auto& var_storage =\n          context.insts().TryGetAs<SemIR::VarStorage>(inst_id)) {\n    auto var_name_id = SemIR::GetFirstBindingNameFromPatternId(\n        context.sem_ir(), var_storage->pattern_id);\n    if (auto cpp_global_var_id = context.sem_ir().cpp_global_vars().Lookup(\n            {.entity_name_id = var_name_id});\n        cpp_global_var_id.has_value()) {\n      SemIR::ClangDeclId clang_decl_id = context.sem_ir()\n                                             .cpp_global_vars()\n                                             .Get(cpp_global_var_id)\n                                             .clang_decl_id;\n      return cast<clang::VarDecl>(\n          context.clang_decls().Get(clang_decl_id).key.decl);\n    }\n  }\n\n  return nullptr;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/import.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_IMPORT_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_IMPORT_H_\n\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/IntrusiveRefCntPtr.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"llvm/Support/VirtualFileSystem.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/sem_ir/clang_decl.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Generates a C++ header that includes the imported cpp files, parses it,\n// generates the AST from it and links `SemIR::File` to it. Reports C++ errors\n// and warnings. If successful, adds a `Cpp` namespace.\nauto ImportCpp(Context& context,\n               llvm::ArrayRef<Parse::Tree::PackagingNames> imports,\n               llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,\n               llvm::LLVMContext* llvm_context,\n               std::shared_ptr<clang::CompilerInvocation> invocation) -> void;\n\n// Imports a declaration from Clang to Carbon. If successful, returns the new\n// Carbon declaration `InstId`. If the declaration was already imported, returns\n// the mapped instruction. All unimported dependencies are imported first.\nauto ImportCppDecl(Context& context, SemIR::LocId loc_id,\n                   SemIR::ClangDeclKey key) -> SemIR::InstId;\n\n// Imports a function declaration from Clang to Carbon. If successful, returns\n// the new Carbon function declaration `InstId`. If the declaration was already\n// imported, returns the mapped instruction.\ninline auto ImportCppFunctionDecl(Context& context, SemIR::LocId loc_id,\n                                  clang::FunctionDecl* clang_decl,\n                                  SemIR::ClangDeclKey::Signature signature)\n    -> SemIR::InstId {\n  return ImportCppDecl(\n      context, loc_id,\n      SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature));\n}\n\n// Imports a function declaration from Clang to Carbon. If successful, returns\n// the new Carbon function declaration `InstId`. If the declaration was already\n// imported, returns the mapped instruction. All unimported dependencies are\n// imported first.\nauto ImportCppType(Context& context, SemIR::LocId loc_id, clang::QualType type)\n    -> TypeExpr;\n\n// Imports an overloaded function set from Clang to Carbon.\nauto ImportCppOverloadSet(\n    Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id,\n    SemIR::NameId name_id, clang::CXXRecordDecl* naming_class,\n    clang::UnresolvedSet<4>&& overload_set,\n    clang::OverloadCandidateSet::OperatorRewriteInfo operator_rewrite_info)\n    -> SemIR::InstId;\n\n// Looks up the given name in the Clang AST generated when importing C++ code\n// and returns a lookup result. If using the injected class name (`X.X()`),\n// imports the class constructor as a function named as the class.\nauto ImportNameFromCpp(Context& context, SemIR::LocId loc_id,\n                       SemIR::NameScopeId scope_id, SemIR::NameId name_id)\n    -> SemIR::ScopeLookupResult;\n\n// Given a Carbon class declaration that was imported from some kind of C++\n// declaration, such as a class or enum, attempt to import a corresponding class\n// definition. Returns true if nothing went wrong (whether or not a definition\n// could be imported), false if a diagnostic was produced.\nauto ImportClassDefinitionForClangDecl(Context& context,\n                                       SemIR::ClassId class_id,\n                                       SemIR::ClangDeclId clang_decl_id)\n    -> bool;\n\n// Gets the identifier info for a name. Returns `nullptr` if the name is not an\n// identifier name.\nauto GetClangIdentifierInfo(Context& context, SemIR::NameId name_id)\n    -> clang::IdentifierInfo*;\n\n// Maps from a `VarStorage` instruction to a `clang::VarDecl`. Returns\n// null if the instruction is not a `VarStorage`, or if its contents\n// cannot be mapped to a `clang::VarDecl`.\nauto GetAsClangVarDecl(Context& context, SemIR::InstId inst_id)\n    -> clang::VarDecl*;\n\n// Maps a Clang name to a Carbon `NameId`.\nauto AddIdentifierName(Context& context, llvm::StringRef name) -> SemIR::NameId;\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_IMPORT_H_\n"
  },
  {
    "path": "toolchain/check/cpp/location.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/location.h\"\n\n#include \"toolchain/sem_ir/absolute_node_id.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nnamespace {\nstruct FileInfo {\n  const SemIR::File* sem_ir;\n  clang::SourceLocation start_loc;\n};\n}  // namespace\n\n// Map a CheckIRId into information about the corresponding file in both SemIR\n// and Clang's source manager.\nstatic auto GetFileInfo(Context& context, SemIR::CheckIRId ir_id) -> FileInfo {\n  const SemIR::File* sem_ir = &context.sem_ir();\n  int file_index = 0;\n\n  // If the file is imported, locate it in our imports map.\n  if (ir_id != context.sem_ir().check_ir_id()) {\n    auto import_id = context.check_ir_map().Get(ir_id);\n    CARBON_CHECK(import_id.has_value());\n    file_index = import_id.index + 1;\n\n    sem_ir = context.import_irs().Get(import_id).sem_ir;\n    CARBON_CHECK(sem_ir, \"Node location in nonexistent IR\");\n  }\n\n  // If we've seen this file before, reuse the same FileID.\n  auto& file_start_locs = context.cpp_context()->carbon_file_locations();\n  if (static_cast<int>(file_start_locs.size()) <= file_index) {\n    // Never valid; prepare a slot for the caching below.\n    file_start_locs.resize(file_index + 1);\n  } else if (file_start_locs[file_index].isValid()) {\n    return {.sem_ir = sem_ir, .start_loc = file_start_locs[file_index]};\n  }\n\n  // We've not seen this file before. Create a corresponding virtual file in\n  // Clang's source manager.\n  // TODO: Consider recreating the complete import path instead of only the\n  // final entry.\n  const auto& source = sem_ir->parse_tree().tokens().source();\n  auto& src_mgr = context.ast_context().getSourceManager();\n  auto file_id = src_mgr.createFileID(\n      llvm::MemoryBufferRef(source.text(), source.filename()));\n  auto file_start_loc = src_mgr.getLocForStartOfFile(file_id);\n  file_start_locs[file_index] = file_start_loc;\n  return {.sem_ir = sem_ir, .start_loc = file_start_loc};\n}\n\nauto GetCppLocation(Context& context, SemIR::LocId loc_id)\n    -> clang::SourceLocation {\n  if (!context.sem_ir().cpp_file()) {\n    return clang::SourceLocation();\n  }\n\n  // Break down the `LocId` into an import path. If that ends in a C++ location,\n  // we can just return that directly.\n  llvm::SmallVector<SemIR::AbsoluteNodeId> absolute_node_ids =\n      SemIR::GetAbsoluteNodeId(&context.sem_ir(), loc_id);\n  if (absolute_node_ids.back().check_ir_id() == SemIR::CheckIRId::Cpp) {\n    return context.sem_ir().clang_source_locs().Get(\n        absolute_node_ids.back().clang_source_loc_id());\n  }\n\n  // This is a location in Carbon code; get or create a corresponding file in\n  // Clang and build a corresponding location.\n  auto absolute_node_id = absolute_node_ids.back();\n  auto [ir, start_loc] = GetFileInfo(context, absolute_node_id.check_ir_id());\n  const auto& tree = ir->parse_tree();\n  auto offset =\n      tree.tokens().GetByteOffset(tree.node_token(absolute_node_id.node_id()));\n  return start_loc.getLocWithOffset(offset);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/location.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_LOCATION_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_LOCATION_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Maps a Carbon source location into an equivalent Clang source location.\nauto GetCppLocation(Context& context, SemIR::LocId loc_id)\n    -> clang::SourceLocation;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_LOCATION_H_\n"
  },
  {
    "path": "toolchain/check/cpp/macros.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/macros.h\"\n\n#include \"clang/AST/ASTContext.h\"\n#include \"clang/AST/Expr.h\"\n#include \"clang/Parse/Parser.h\"\n#include \"clang/Sema/Sema.h\"\n#include \"common/check.h\"\n#include \"toolchain/check/cpp/constant.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/literal.h\"\n\nnamespace Carbon::Check {\n\n// Maps a Clang literal expression to a Carbon constant.\nstatic auto MapConstant(Context& context, SemIR::LocId loc_id,\n                        clang::Expr* expr) -> SemIR::InstId {\n  CARBON_CHECK(expr, \"empty expression\");\n\n  if (auto* string_literal = dyn_cast<clang::StringLiteral>(expr)) {\n    if (!string_literal->isOrdinary() && !string_literal->isUTF8()) {\n      context.TODO(loc_id,\n                   llvm::formatv(\"Unsupported: string literal type: {0}\",\n                                 expr->getType()));\n      return SemIR::ErrorInst::InstId;\n    }\n    StringLiteralValueId string_id =\n        context.string_literal_values().Add(string_literal->getString());\n    auto inst_id =\n        MakeStringLiteral(context, Parse::StringLiteralId::None, string_id);\n    return inst_id;\n  } else if (isa<clang::CXXNullPtrLiteralExpr>(expr)) {\n    auto type_id = ImportCppType(context, loc_id, expr->getType()).type_id;\n    return GetOrAddInst<SemIR::UninitializedValue>(context, SemIR::LocId::None,\n                                                   {.type_id = type_id});\n  }\n\n  context.TODO(loc_id,\n               llvm::formatv(\"Unsupported: C++ constant expression type: '{0}'\",\n                             expr->getType().getAsString()));\n  return SemIR::ErrorInst::InstId;\n}\n\nauto TryEvaluateMacro(Context& context, SemIR::LocId loc_id,\n                      SemIR::NameId name_id, clang::MacroInfo* macro_info)\n    -> SemIR::InstId {\n  auto name_str_opt = context.names().GetAsStringIfIdentifier(name_id);\n  CARBON_CHECK(macro_info, \"macro info missing\");\n\n  if (macro_info->getNumTokens() == 0) {\n    context.TODO(loc_id, \"Unsupported: macro with 0 replacement tokens\");\n    return SemIR::ErrorInst::InstId;\n  }\n\n  clang::Sema& sema = context.clang_sema();\n  clang::Preprocessor& preprocessor = sema.getPreprocessor();\n  auto& parser = context.cpp_context()->parser();\n\n  llvm::SmallVector<clang::Token> tokens(macro_info->tokens().begin(),\n                                         macro_info->tokens().end());\n\n  clang::Token current_token = parser.getCurToken();\n\n  // Add eof token\n  clang::Token eof;\n  eof.startToken();\n  eof.setKind(clang::tok::eof);\n  eof.setLocation(current_token.getEndLoc());\n  tokens.push_back(eof);\n\n  tokens.push_back(current_token);\n\n  preprocessor.EnterTokenStream(tokens, /*DisableMacroExpansion=*/false,\n                                /*IsReinject=*/false);\n  parser.ConsumeAnyToken(true);\n\n  clang::ExprResult result = parser.ParseConstantExpression();\n\n  clang::Expr* result_expr = result.get();\n\n  bool success =\n      !result.isInvalid() && parser.getCurToken().is(clang::tok::eof);\n\n  if (!success) {\n    parser.SkipUntil(clang::tok::eof);\n    CARBON_DIAGNOSTIC(\n        InCppMacroEvaluation, Error,\n        \"failed to parse macro Cpp.{0} to a valid constant expression\",\n        std::string);\n    context.emitter().Emit(loc_id, InCppMacroEvaluation, (*name_str_opt).str());\n    return SemIR::ErrorInst::InstId;\n  }\n\n  result_expr = result_expr->IgnoreParenImpCasts();\n\n  if (isa<clang::StringLiteral>(result_expr) ||\n      isa<clang::CXXNullPtrLiteralExpr>(result_expr)) {\n    return MapConstant(context, loc_id, result_expr);\n  }\n\n  clang::Expr::EvalResult evaluated_result;\n  if (!result_expr->EvaluateAsConstantExpr(evaluated_result,\n                                           sema.getASTContext())) {\n    CARBON_FATAL(\"failed to evaluate macro as constant expression\");\n  }\n\n  auto const_id = MapAPValueToConstant(context, loc_id, evaluated_result.Val,\n                                       result_expr->getType(),\n                                       /*is_lvalue=*/result_expr->isGLValue());\n  if (const_id == SemIR::ConstantId::NotConstant) {\n    context.TODO(loc_id,\n                 \"Unsupported: macro evaluated to a constant of type: \" +\n                     result_expr->getType().getAsString());\n    return SemIR::ErrorInst::InstId;\n  }\n\n  return context.constant_values().GetInstId(const_id);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/macros.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_MACROS_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_MACROS_H_\n\n#include \"toolchain/check/context.h\"\n\nnamespace Carbon::Check {\n\n// Tries to evaluate the given macro. The macro will be evaluated as a\n// constant if possible. Returns an `InstId` on success or\n// `SemIR::ErrorInst::InstId` otherwise.\nauto TryEvaluateMacro(Context& context, SemIR::LocId loc_id,\n                      SemIR::NameId name_id, clang::MacroInfo* macro_info)\n    -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_MACROS_H_\n"
  },
  {
    "path": "toolchain/check/cpp/operators.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/operators.h\"\n\n#include \"clang/Sema/Initialization.h\"\n#include \"clang/Sema/Overload.h\"\n#include \"clang/Sema/Sema.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/cpp/location.h\"\n#include \"toolchain/check/cpp/overload_resolution.h\"\n#include \"toolchain/check/cpp/type_mapping.h\"\n#include \"toolchain/check/function.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/sem_ir/builtin_function_kind.h\"\n#include \"toolchain/sem_ir/cpp_initializer_list.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Maps Carbon operator interface and operator names to Clang operator kinds.\nstatic auto GetClangOperatorKind(Context& context, SemIR::LocId loc_id,\n                                 CoreIdentifier interface_name,\n                                 CoreIdentifier op_name)\n    -> std::optional<clang::OverloadedOperatorKind> {\n  switch (interface_name) {\n      // Unary operators.\n    case CoreIdentifier::Destroy:\n    case CoreIdentifier::As:\n    case CoreIdentifier::ImplicitAs:\n    case CoreIdentifier::UnsafeAs:\n    case CoreIdentifier::Copy: {\n      // TODO: Support destructors and conversions.\n      return std::nullopt;\n    }\n\n    // Increment and decrement.\n    case CoreIdentifier::Inc: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_PlusPlus;\n    }\n    case CoreIdentifier::Dec: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_MinusMinus;\n    }\n\n    // Arithmetic.\n    case CoreIdentifier::Negate: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Minus;\n    }\n\n    // Bitwise.\n    case CoreIdentifier::BitComplement: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Tilde;\n    }\n\n    // Binary operators.\n\n    // Arithmetic operators.\n    case CoreIdentifier::AddWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Plus;\n    }\n    case CoreIdentifier::SubWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Minus;\n    }\n    case CoreIdentifier::MulWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Star;\n    }\n    case CoreIdentifier::DivWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Slash;\n    }\n    case CoreIdentifier::ModWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Percent;\n    }\n\n    // Bitwise operators.\n    case CoreIdentifier::BitAndWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Amp;\n    }\n    case CoreIdentifier::BitOrWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Pipe;\n    }\n    case CoreIdentifier::BitXorWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Caret;\n    }\n    case CoreIdentifier::LeftShiftWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_LessLess;\n    }\n    case CoreIdentifier::RightShiftWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_GreaterGreater;\n    }\n\n    // Assignment.\n    case CoreIdentifier::AssignWith: {\n      // TODO: This is not yet reached because we don't use the `AssignWith`\n      // interface for assignment yet.\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_Equal;\n    }\n\n    // Compound assignment arithmetic operators.\n    case CoreIdentifier::AddAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_PlusEqual;\n    }\n    case CoreIdentifier::SubAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_MinusEqual;\n    }\n    case CoreIdentifier::MulAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_StarEqual;\n    }\n    case CoreIdentifier::DivAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_SlashEqual;\n    }\n    case CoreIdentifier::ModAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_PercentEqual;\n    }\n\n    // Compound assignment bitwise operators.\n    case CoreIdentifier::BitAndAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_AmpEqual;\n    }\n    case CoreIdentifier::BitOrAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_PipeEqual;\n    }\n    case CoreIdentifier::BitXorAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_CaretEqual;\n    }\n    case CoreIdentifier::LeftShiftAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_LessLessEqual;\n    }\n    case CoreIdentifier::RightShiftAssignWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::Op);\n      return clang::OO_GreaterGreaterEqual;\n    }\n\n    // Relational operators.\n    case CoreIdentifier::EqWith: {\n      if (op_name == CoreIdentifier::Equal) {\n        return clang::OO_EqualEqual;\n      }\n      CARBON_CHECK(op_name == CoreIdentifier::NotEqual);\n      return clang::OO_ExclaimEqual;\n    }\n    case CoreIdentifier::OrderedWith: {\n      switch (op_name) {\n        case CoreIdentifier::Less:\n          return clang::OO_Less;\n        case CoreIdentifier::Greater:\n          return clang::OO_Greater;\n        case CoreIdentifier::LessOrEquivalent:\n          return clang::OO_LessEqual;\n        case CoreIdentifier::GreaterOrEquivalent:\n          return clang::OO_GreaterEqual;\n        default:\n          CARBON_FATAL(\"Unexpected OrderedWith op `{0}`\", op_name);\n      }\n    }\n\n    // Array indexing.\n    case CoreIdentifier::IndexWith: {\n      CARBON_CHECK(op_name == CoreIdentifier::At);\n      return clang::OO_Subscript;\n    }\n\n    default: {\n      context.TODO(loc_id, llvm::formatv(\"Unsupported operator interface `{0}`\",\n                                         interface_name));\n      return std::nullopt;\n    }\n  }\n}\n\n// Creates and returns a function that can be used to construct a\n// std::initializer_list from an array.\n//\n// TODO: This should ideally be implemented in Carbon code rather than by\n// synthesizing a function.\n// TODO: We should cache and reuse the generated function.\nstatic auto MakeCppStdInitializerListMake(Context& context, SemIR::LocId loc_id,\n                                          clang::QualType init_list_type,\n                                          int32_t size) -> SemIR::InstId {\n  // Extract the element type `T` from the `std::initializer_list<T>` type.\n  clang::QualType element_type;\n  bool is_std_initializer_list =\n      context.clang_sema().isStdInitializerList(init_list_type, &element_type);\n  CARBON_CHECK(is_std_initializer_list);\n  auto element_type_inst_id =\n      ImportCppType(context, loc_id, element_type).inst_id;\n  if (element_type_inst_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // Import the `std::initializer_list<T>` type and check we recognize its\n  // layout.\n  auto [init_list_type_inst_id, init_list_type_id] =\n      ImportCppType(context, loc_id, init_list_type);\n  if (init_list_type_id == SemIR::ErrorInst::TypeId) {\n    return SemIR::ErrorInst::InstId;\n  }\n  auto layout =\n      SemIR::GetStdInitializerListLayout(context.sem_ir(), init_list_type_id);\n  if (layout.kind == SemIR::StdInitializerListLayout::None) {\n    context.TODO(loc_id, \"Unsupported layout for std::initializer_list\");\n    return SemIR::ErrorInst::InstId;\n  }\n  auto init_list_class_id = context.sem_ir()\n                                .types()\n                                .GetAs<SemIR::ClassType>(init_list_type_id)\n                                .class_id;\n  auto& init_list_class = context.classes().Get(init_list_class_id);\n\n  // Build the array type `T[size]` that we use as the parameter type.\n  // TODO: This will eventually be called from impl lookup, possibly while\n  // forming a specific, so we should not be adding instructions here.\n  auto bound_id = AddInst(\n      context, SemIR::LocIdAndInst(\n                   loc_id, SemIR::IntValue{\n                               .type_id = GetSingletonType(\n                                   context, SemIR::IntLiteralType::TypeInstId),\n                               .int_id = context.ints().Add(size)}));\n  auto array_type_inst_id = AddTypeInst(\n      context, SemIR::LocIdAndInst::UncheckedLoc(\n                   loc_id, SemIR::ArrayType{\n                               .type_id = SemIR::TypeType::TypeId,\n                               .bound_id = bound_id,\n                               .element_type_inst_id = element_type_inst_id}));\n  auto array_type_id =\n      context.types().GetTypeIdForTypeInstId(array_type_inst_id);\n\n  // Create a builtin function to perform the conversion from array type to\n  // initializer list type. We name the synthesized function as if it were a\n  // constructor of std::initializer_list.\n  // TODO: Find a better way to handle this. Ideally we should stop using this\n  // function entirely and declare the necessary builtin in the prelude.\n  auto [decl_id, function_id] =\n      MakeGeneratedFunctionDecl(context, loc_id,\n                                {.parent_scope_id = init_list_class.scope_id,\n                                 .name_id = init_list_class.name_id,\n                                 .param_type_ids = {array_type_id},\n                                 .return_type_id = init_list_type_id});\n\n  auto& function = context.functions().Get(function_id);\n  CARBON_CHECK(IsValidBuiltinDeclaration(\n      context, function,\n      SemIR::BuiltinFunctionKind::CppStdInitializerListMake));\n  function.SetBuiltinFunction(\n      SemIR::BuiltinFunctionKind::CppStdInitializerListMake);\n\n  return decl_id;\n}\n\n// Returns information about the Carbon signature to import when importing a C++\n// constructor or conversion operator.\nstatic auto GetConversionSignatureToImport(\n    Context& context, SemIR::InstId source_id,\n    clang::InitializationSequence::StepKind step_kind,\n    clang::FunctionDecl* function_decl) -> SemIR::ClangDeclKey::Signature {\n  // If we're performing a constructor initialization from a list, form a\n  // function signature that takes a single tuple or struct pattern\n  // instead of a function signature with one parameter per C++ parameter.\n  if (step_kind ==\n      clang::InitializationSequence::SK_ConstructorInitializationFromList) {\n    // The source type should always be a tuple type, because we don't support\n    // C++ initialization from struct types.\n    auto tuple_type = context.types().TryGetAs<SemIR::TupleType>(\n        context.insts().Get(source_id).type_id());\n    CARBON_CHECK(tuple_type, \"List initialization from non-tuple type\");\n\n    // Initialization from a tuple `(a, b, c)` results in a constructor\n    // function that takes a tuple pattern:\n    //\n    //   fn Class.Class((a: A, b: B, c: C)) -> Class;\n    return {\n        .kind = SemIR::ClangDeclKey::Signature::Kind::TuplePattern,\n        .num_params = static_cast<int32_t>(\n            context.inst_blocks().Get(tuple_type->type_elements_id).size())};\n  }\n\n  // Any other initialization using a constructor is calling a converting\n  // constructor:\n  //\n  //   fn Class.Class(a: A) -> Class;\n  if (isa<clang::CXXConstructorDecl>(function_decl)) {\n    return {.kind = SemIR::ClangDeclKey::Signature::Kind::Normal,\n            .num_params = 1};\n  }\n\n  // Otherwise, the initialization is calling a conversion function\n  // `Source::operator Dest`:\n  //\n  //   fn Source.<conversion function>[self: Source]() -> Dest;\n  CARBON_CHECK(isa<clang::CXXConversionDecl>(function_decl));\n  return {.kind = SemIR::ClangDeclKey::Signature::Kind::Normal,\n          .num_params = 0};\n}\n\nstatic auto LookupCppConversion(Context& context, SemIR::LocId loc_id,\n                                SemIR::InstId source_id,\n                                SemIR::TypeId dest_type_id, bool allow_explicit)\n    -> SemIR::InstId {\n  if (context.types().Is<SemIR::StructType>(\n          context.insts().Get(source_id).type_id())) {\n    // Structs can only be used to initialize C++ aggregates. That case is\n    // handled by Convert, not here.\n    return SemIR::InstId::None;\n  }\n\n  auto dest_type = MapToCppType(context, dest_type_id);\n  if (dest_type.isNull()) {\n    return SemIR::InstId::None;\n  }\n\n  auto* arg_expr = InventClangArg(context, source_id);\n  // If we can't map the argument, we can't perform the conversion.\n  if (!arg_expr) {\n    return SemIR::InstId::None;\n  }\n\n  auto loc = GetCppLocation(context, loc_id);\n\n  // Form a Clang initialization sequence.\n  auto& sema = context.clang_sema();\n  clang::InitializedEntity entity =\n      clang::InitializedEntity::InitializeTemporary(dest_type);\n  clang::InitializationKind kind =\n      allow_explicit ? clang::InitializationKind::CreateDirect(\n                           loc, /*LParenLoc=*/clang::SourceLocation(),\n                           /*RParenLoc=*/clang::SourceLocation())\n                     : clang::InitializationKind::CreateCopy(\n                           loc, /*EqualLoc=*/clang::SourceLocation());\n  clang::MultiExprArg args(arg_expr);\n  // `(a, b) as T` uses `T{a, b}`, not `T({a, b})`. The latter would introduce\n  // a redundant extra copy.\n  // TODO: We need to communicate this back to the caller so they know to call\n  // the constructor with an exploded argument list somehow.\n  if (allow_explicit && isa<clang::InitListExpr>(arg_expr)) {\n    kind = clang::InitializationKind::CreateDirectList(loc);\n  }\n  clang::InitializationSequence init(sema, entity, kind, args);\n\n  if (init.Failed()) {\n    // TODO: Are there initialization failures that we should translate into\n    // errors rather than a missing conversion?\n    return SemIR::InstId::None;\n  }\n\n  // Scan the steps looking for user-defined conversions. For now we just find\n  // and return the first such conversion function. We skip over standard\n  // conversions; we'll perform those using the Carbon rules as part of calling\n  // the C++ conversion function.\n  for (const auto& step : init.steps()) {\n    switch (step.Kind) {\n      case clang::InitializationSequence::SK_UserConversion:\n      case clang::InitializationSequence::SK_ConstructorInitialization:\n      case clang::InitializationSequence::SK_StdInitializerListConstructorCall:\n      case clang::InitializationSequence::\n          SK_ConstructorInitializationFromList: {\n        if (auto* ctor =\n                dyn_cast<clang::CXXConstructorDecl>(step.Function.Function);\n            ctor && ctor->isCopyOrMoveConstructor()) {\n          // Skip copy / move constructor calls. They shouldn't be performed\n          // this way because they're not considered conversions in Carbon, and\n          // will frequently lead to infinite recursion because we'll end up\n          // back here when attempting to convert the argument.\n          continue;\n        }\n\n        if (sema.DiagnoseUseOfOverloadedDecl(step.Function.Function, loc)) {\n          return SemIR::ErrorInst::InstId;\n        }\n\n        sema.MarkFunctionReferenced(loc, step.Function.Function);\n\n        auto signature = GetConversionSignatureToImport(\n            context, source_id, step.Kind, step.Function.Function);\n        auto result_id = ImportCppFunctionDecl(\n            context, loc_id, step.Function.Function, signature);\n        if (auto fn_decl = context.insts().TryGetAsWithId<SemIR::FunctionDecl>(\n                result_id)) {\n          CheckCppOverloadAccess(context, loc_id, step.Function.FoundDecl,\n                                 fn_decl->inst_id);\n        } else {\n          CARBON_CHECK(result_id == SemIR::ErrorInst::InstId);\n        }\n\n        // TODO: There may be other conversions later in the sequence that we\n        // need to model; we've only applied the first one here.\n        return result_id;\n      }\n\n      case clang::InitializationSequence::SK_StdInitializerList: {\n        return MakeCppStdInitializerListMake(\n            context, loc_id, step.Type,\n            cast<clang::InitListExpr>(arg_expr)->getNumInits());\n      }\n\n      case clang::InitializationSequence::SK_ListInitialization: {\n        // Aggregate initialization is handled by the normal Carbon conversion\n        // logic, so we ignore it here.\n        // TODO: So far we only support aggregate initialization for arrays and\n        // empty classes.\n        continue;\n      }\n\n      case clang::InitializationSequence::SK_ConversionSequence:\n      case clang::InitializationSequence::SK_ConversionSequenceNoNarrowing: {\n        // Implicit conversions are handled by the normal Carbon conversion\n        // logic, so we ignore them here.\n        continue;\n      }\n\n      default: {\n        // TODO: Handle other kinds of initialization steps. For now we assume\n        // they will be handled by our function call logic and we can skip them.\n        RawStringOstream os;\n        os << \"Unsupported initialization sequence:\\n\";\n        init.dump(os);\n        context.TODO(loc_id, os.TakeStr());\n        return SemIR::ErrorInst::InstId;\n      }\n    }\n  }\n\n  return SemIR::InstId::None;\n}\n\nauto LookupCppOperator(Context& context, SemIR::LocId loc_id, Operator op,\n                       llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::InstId {\n  // Register an annotation scope to flush any Clang diagnostics when we return.\n  // This is important to ensure that Clang diagnostics are properly interleaved\n  // with Carbon diagnostics.\n  Diagnostics::AnnotationScope annotate_diagnostics(&context.emitter(),\n                                                    [](auto& /*builder*/) {});\n\n  // Handle `ImplicitAs` and `As`.\n  if (op.interface_name == CoreIdentifier::ImplicitAs ||\n      op.interface_name == CoreIdentifier::As) {\n    if (op.interface_args_ref.size() != 1 || arg_ids.size() != 1) {\n      return SemIR::InstId::None;\n    }\n    // The argument is the destination type for both interfaces.\n    auto dest_const_id =\n        context.constant_values().Get(op.interface_args_ref[0]);\n    auto dest_type_id =\n        context.types().TryGetTypeIdForTypeConstantId(dest_const_id);\n    if (!dest_type_id.has_value()) {\n      return SemIR::InstId::None;\n    }\n\n    return LookupCppConversion(\n        context, loc_id, arg_ids[0], dest_type_id,\n        /*allow_explicit=*/op.interface_name == CoreIdentifier::As);\n  }\n\n  auto op_kind =\n      GetClangOperatorKind(context, loc_id, op.interface_name, op.op_name);\n  if (!op_kind) {\n    return SemIR::InstId::None;\n  }\n\n  // Make sure all operands are complete before lookup.\n  for (SemIR::InstId arg_id : arg_ids) {\n    SemIR::TypeId arg_type_id = context.insts().Get(arg_id).type_id();\n    if (!RequireCompleteType(context, arg_type_id, loc_id, [&](auto& builder) {\n          CARBON_DIAGNOSTIC(\n              IncompleteOperandTypeInCppOperatorLookup, Context,\n              \"looking up a C++ operator with incomplete operand type {0}\",\n              SemIR::TypeId);\n          builder.Context(loc_id, IncompleteOperandTypeInCppOperatorLookup,\n                          arg_type_id);\n        })) {\n      return SemIR::ErrorInst::InstId;\n    }\n  }\n\n  auto maybe_arg_exprs = InventClangArgs(context, arg_ids);\n  if (!maybe_arg_exprs.has_value()) {\n    return SemIR::ErrorInst::InstId;\n  }\n  auto& arg_exprs = *maybe_arg_exprs;\n\n  clang::SourceLocation loc = GetCppLocation(context, loc_id);\n  clang::OverloadCandidateSet::OperatorRewriteInfo operator_rewrite_info(\n      *op_kind, loc, /*AllowRewritten=*/true);\n  clang::OverloadCandidateSet candidate_set(\n      loc, clang::OverloadCandidateSet::CSK_Operator, operator_rewrite_info);\n\n  clang::Sema& sema = context.clang_sema();\n\n  // This works for both unary and binary operators.\n  sema.LookupOverloadedBinOp(candidate_set, *op_kind, clang::UnresolvedSet<0>{},\n                             arg_exprs);\n\n  clang::OverloadCandidateSet::iterator best_viable_fn;\n  switch (candidate_set.BestViableFunction(sema, loc, best_viable_fn)) {\n    case clang::OverloadingResult::OR_Success: {\n      if (!best_viable_fn->Function) {\n        // The best viable candidate was a builtin. Let the Carbon operator\n        // machinery handle that.\n        return SemIR::InstId::None;\n      }\n      if (best_viable_fn->RewriteKind) {\n        context.TODO(\n            loc_id,\n            llvm::formatv(\"Rewriting operator{0} using {1} is not supported\",\n                          clang::getOperatorSpelling(\n                              candidate_set.getRewriteInfo().OriginalOperator),\n                          best_viable_fn->Function->getNameAsString()));\n        return SemIR::ErrorInst::InstId;\n      }\n      sema.MarkFunctionReferenced(loc, best_viable_fn->Function);\n\n      // If this is an operator method, the first arg will be used as self.\n      int32_t num_params = arg_ids.size();\n      if (isa<clang::CXXMethodDecl>(best_viable_fn->Function)) {\n        --num_params;\n      }\n\n      auto result_id =\n          ImportCppFunctionDecl(context, loc_id, best_viable_fn->Function,\n                                {.num_params = num_params});\n      if (result_id != SemIR::ErrorInst::InstId) {\n        CheckCppOverloadAccess(\n            context, loc_id, best_viable_fn->FoundDecl,\n            context.insts().GetAsKnownInstId<SemIR::FunctionDecl>(result_id));\n      }\n      return result_id;\n    }\n    case clang::OverloadingResult::OR_No_Viable_Function: {\n      // OK, didn't find a viable C++ candidate, but this is not an error, as\n      // there might be a Carbon candidate.\n      return SemIR::InstId::None;\n    }\n    case clang::OverloadingResult::OR_Ambiguous: {\n      const char* spelling = clang::getOperatorSpelling(*op_kind);\n      candidate_set.NoteCandidates(\n          clang::PartialDiagnosticAt(\n              loc, sema.PDiag(clang::diag::err_ovl_ambiguous_oper_binary)\n                       << spelling << arg_exprs[0]->getType()\n                       << arg_exprs[1]->getType()),\n          sema, clang::OCD_AmbiguousCandidates, arg_exprs, spelling, loc);\n      return SemIR::ErrorInst::InstId;\n    }\n    case clang::OverloadingResult::OR_Deleted:\n      const char* spelling = clang::getOperatorSpelling(*op_kind);\n      auto* message = best_viable_fn->Function->getDeletedMessage();\n      // The best viable function might be a different operator if the best\n      // candidate is a rewritten candidate, so use the operator kind of the\n      // candidate itself in the diagnostic.\n      candidate_set.NoteCandidates(\n          clang::PartialDiagnosticAt(\n              loc, sema.PDiag(clang::diag::err_ovl_deleted_oper)\n                       << clang::getOperatorSpelling(\n                              best_viable_fn->Function->getOverloadedOperator())\n                       << (message != nullptr)\n                       << (message ? message->getString() : llvm::StringRef())),\n          sema, clang::OCD_AllCandidates, arg_exprs, spelling, loc);\n      return SemIR::ErrorInst::InstId;\n  }\n}\n\nauto IsCppOperatorMethodDecl(clang::Decl* decl) -> bool {\n  auto* clang_method_decl = dyn_cast<clang::CXXMethodDecl>(decl);\n  return clang_method_decl &&\n         (clang_method_decl->isOverloadedOperator() ||\n          isa<clang::CXXConversionDecl>(clang_method_decl));\n}\n\nstatic auto GetAsCppFunctionDecl(Context& context, SemIR::InstId inst_id)\n    -> clang::FunctionDecl* {\n  if (inst_id == SemIR::InstId::None) {\n    return nullptr;\n  }\n  auto function_type = context.types().TryGetAs<SemIR::FunctionType>(\n      context.insts().Get(inst_id).type_id());\n  if (!function_type) {\n    return nullptr;\n  }\n  SemIR::ClangDeclId clang_decl_id =\n      context.functions().Get(function_type->function_id).clang_decl_id;\n  return clang_decl_id.has_value()\n             ? dyn_cast<clang::FunctionDecl>(\n                   context.clang_decls().Get(clang_decl_id).key.decl)\n             : nullptr;\n}\n\nauto IsCppOperatorMethod(Context& context, SemIR::InstId inst_id) -> bool {\n  auto* function_decl = GetAsCppFunctionDecl(context, inst_id);\n  return function_decl && IsCppOperatorMethodDecl(function_decl);\n}\n\nauto IsCppConstructorOrNonMethodOperator(Context& context,\n                                         SemIR::InstId inst_id) -> bool {\n  auto* function_decl = GetAsCppFunctionDecl(context, inst_id);\n  if (!function_decl) {\n    return false;\n  }\n  if (isa<clang::CXXConstructorDecl>(function_decl)) {\n    return true;\n  }\n  return !isa<clang::CXXMethodDecl>(function_decl) &&\n         function_decl->isOverloadedOperator();\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/operators.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_OPERATORS_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_OPERATORS_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/operator.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Looks up the given operator in the Clang AST generated when importing C++\n// code using argument dependent lookup (ADL) and return overload set\n// instruction.\nauto LookupCppOperator(Context& context, SemIR::LocId loc_id, Operator op,\n                       llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::InstId;\n\n// Returns whether the decl is an operator member function.\nauto IsCppOperatorMethodDecl(clang::Decl* decl) -> bool;\n\n// Returns whether the specified instruction refers to a C++ overloaded operator\n// that is a method. If so, the first operand will be passed as `self` rather\n// than as the first argument.\nauto IsCppOperatorMethod(Context& context, SemIR::InstId inst_id) -> bool;\n\n// Returns whether the specified instruction refers to a C++ constructor or\n// non-operator method. If so, when mapping from a Carbon interface to a C++\n// call, we pass a `self` parameter as the first argument instead.\nauto IsCppConstructorOrNonMethodOperator(Context& context,\n                                         SemIR::InstId inst_id) -> bool;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_OPERATORS_H_\n"
  },
  {
    "path": "toolchain/check/cpp/overload_resolution.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/overload_resolution.h\"\n\n#include \"clang/Basic/DiagnosticSema.h\"\n#include \"clang/Sema/Overload.h\"\n#include \"clang/Sema/Sema.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/cpp/access.h\"\n#include \"toolchain/check/cpp/call.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/cpp/location.h\"\n#include \"toolchain/check/cpp/operators.h\"\n#include \"toolchain/check/cpp/type_mapping.h\"\n#include \"toolchain/check/member_access.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Map a Carbon name into a C++ name.\nstatic auto GetCppName(Context& context, SemIR::NameId name_id)\n    -> clang::DeclarationName {\n  // TODO: Some special names should probably use different formatting. In\n  // particular, NameId::CppOperator should probably map back to a\n  // CXXOperatorName.\n  auto name_str = context.names().GetFormatted(name_id);\n  return clang::DeclarationName(&context.ast_context().Idents.get(name_str));\n}\n\n// Adds the given overload candidates to the candidate set.\nstatic auto AddOverloadCandidates(\n    Context& context, clang::OverloadCandidateSet& candidate_set,\n    const clang::UnresolvedSet<4>& functions,\n    llvm::ArrayRef<SemIR::InstId> template_arg_ids, clang::Expr* self_arg,\n    llvm::ArrayRef<clang::Expr*> args) -> void {\n  clang::Sema& sema = context.clang_sema();\n\n  constexpr bool SuppressUserConversions = false;\n  constexpr bool PartialOverloading = false;\n\n  for (auto found_decl : functions.pairs()) {\n    auto* decl = found_decl->getUnderlyingDecl();\n\n    // Form an explicit template argument list if needed. Note that this is done\n    // per-candidate, as the conversions performed on the template arguments\n    // differ based on the corresponding template parameters.\n    auto* template_decl = dyn_cast<clang::FunctionTemplateDecl>(decl);\n    clang::TemplateArgumentListInfo explicit_template_arg_storage;\n    clang::TemplateArgumentListInfo* explicit_template_args = nullptr;\n    if (!template_arg_ids.empty()) {\n      if (!template_decl) {\n        continue;\n      }\n      if (!ConvertArgsToTemplateArgs(context, template_decl, template_arg_ids,\n                                     explicit_template_arg_storage,\n                                     /*diagnose=*/false)) {\n        continue;\n      }\n      explicit_template_args = &explicit_template_arg_storage;\n    }\n\n    auto* fn_decl = template_decl ? template_decl->getTemplatedDecl()\n                                  : cast<clang::FunctionDecl>(decl);\n    auto* method_decl = dyn_cast<clang::CXXMethodDecl>(fn_decl);\n    if (method_decl && !method_decl->isStatic() &&\n        !isa<clang::CXXConstructorDecl>(fn_decl)) {\n      clang::QualType self_type;\n      clang::Expr::Classification self_classification;\n      if (self_arg) {\n        self_type = self_arg->getType();\n        self_classification = self_arg->Classify(sema.Context);\n      }\n      if (template_decl) {\n        sema.AddMethodTemplateCandidate(\n            template_decl, found_decl,\n            cast<clang::CXXRecordDecl>(template_decl->getDeclContext()),\n            explicit_template_args, self_type, self_classification, args,\n            candidate_set, SuppressUserConversions, PartialOverloading);\n      } else if (method_decl->isOverloadedOperator()) {\n        sema.AddMemberOperatorCandidates(method_decl->getOverloadedOperator(),\n                                         candidate_set.getLocation(), args,\n                                         candidate_set);\n      } else {\n        sema.AddMethodCandidate(method_decl, found_decl,\n                                method_decl->getParent(), self_type,\n                                self_classification, args, candidate_set,\n                                SuppressUserConversions, PartialOverloading);\n      }\n    } else if (template_decl) {\n      sema.AddTemplateOverloadCandidate(\n          template_decl, found_decl, explicit_template_args, args,\n          candidate_set, SuppressUserConversions, PartialOverloading);\n    } else {\n      sema.AddOverloadCandidate(fn_decl, found_decl, args, candidate_set,\n                                SuppressUserConversions, PartialOverloading);\n    }\n  }\n}\n\nauto CheckCppOverloadAccess(\n    Context& context, SemIR::LocId loc_id, clang::DeclAccessPair overload,\n    SemIR::KnownInstId<SemIR::FunctionDecl> overload_inst_id,\n    SemIR::NameScopeId parent_scope_id) -> void {\n  SemIR::AccessKind member_access_kind = MapCppAccess(overload);\n  if (member_access_kind == SemIR::AccessKind::Public) {\n    return;\n  }\n\n  auto function_id = context.insts().Get(overload_inst_id).function_id;\n  auto& function = context.functions().Get(function_id);\n  if (!parent_scope_id.has_value()) {\n    parent_scope_id = function.parent_scope_id;\n  }\n\n  auto name_scope_const_id = context.constant_values().Get(\n      context.name_scopes().Get(parent_scope_id).inst_id());\n  SemIR::AccessKind allowed_access_kind =\n      GetHighestAllowedAccess(context, loc_id, name_scope_const_id);\n  CheckAccess(context, loc_id, SemIR::LocId(overload_inst_id), function.name_id,\n              member_access_kind,\n              /*is_parent_access=*/false,\n              {.constant_id = name_scope_const_id,\n               .highest_allowed_access = allowed_access_kind});\n}\n\nauto PerformCppOverloadResolution(\n    Context& context, SemIR::LocId loc_id,\n    const SemIR::CppOverloadSet& overload_set,\n    llvm::ArrayRef<SemIR::InstId> template_arg_ids, SemIR::InstId self_id,\n    llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::InstId {\n  // Register an annotation scope to flush any Clang diagnostics when we return.\n  // This is important to ensure that Clang diagnostics are properly interleaved\n  // with Carbon diagnostics.\n  Diagnostics::AnnotationScope annotate_diagnostics(&context.emitter(),\n                                                    [](auto& /*builder*/) {});\n\n  // Map Carbon call argument types to C++ types.\n  clang::Expr* self_expr = nullptr;\n  if (self_id.has_value()) {\n    self_expr = InventClangArg(context, self_id);\n    if (!self_expr) {\n      return SemIR::ErrorInst::InstId;\n    }\n  }\n  auto maybe_arg_exprs = InventClangArgs(context, arg_ids);\n  if (!maybe_arg_exprs.has_value()) {\n    return SemIR::ErrorInst::InstId;\n  }\n  auto& arg_exprs = *maybe_arg_exprs;\n\n  clang::SourceLocation loc = GetCppLocation(context, loc_id);\n\n  // Add candidate functions from the name lookup.\n  clang::OverloadCandidateSet candidate_set(\n      loc,\n      overload_set.operator_rewrite_info.OriginalOperator\n          ? clang::OverloadCandidateSet::CandidateSetKind::CSK_Operator\n          : clang::OverloadCandidateSet::CandidateSetKind::CSK_Normal,\n      overload_set.operator_rewrite_info);\n\n  AddOverloadCandidates(context, candidate_set,\n                        overload_set.candidate_functions, template_arg_ids,\n                        self_expr, arg_exprs);\n\n  // Find best viable function among the candidates.\n  clang::Sema& sema = context.clang_sema();\n  clang::OverloadCandidateSet::iterator best_viable_fn;\n  clang::OverloadingResult overloading_result =\n      candidate_set.BestViableFunction(sema, loc, best_viable_fn);\n\n  switch (overloading_result) {\n    case clang::OverloadingResult::OR_Success: {\n      CARBON_CHECK(best_viable_fn->Function);\n      CARBON_CHECK(!best_viable_fn->RewriteKind);\n      SemIR::InstId result_id = ImportCppFunctionDecl(\n          context, loc_id, best_viable_fn->Function,\n          {.num_params = static_cast<int32_t>(arg_exprs.size())});\n      if (result_id != SemIR::ErrorInst::InstId) {\n        CheckCppOverloadAccess(\n            context, loc_id, best_viable_fn->FoundDecl,\n            context.insts().GetAsKnownInstId<SemIR::FunctionDecl>(result_id),\n            overload_set.parent_scope_id);\n      }\n      return result_id;\n    }\n    case clang::OverloadingResult::OR_No_Viable_Function: {\n      candidate_set.NoteCandidates(\n          clang::PartialDiagnosticAt(\n              loc, sema.PDiag(clang::diag::err_ovl_no_viable_function_in_call)\n                       << GetCppName(context, overload_set.name_id)),\n          sema, clang::OCD_AllCandidates, arg_exprs);\n      return SemIR::ErrorInst::InstId;\n    }\n    case clang::OverloadingResult::OR_Ambiguous: {\n      candidate_set.NoteCandidates(\n          clang::PartialDiagnosticAt(\n              loc, sema.PDiag(clang::diag::err_ovl_ambiguous_call)\n                       << GetCppName(context, overload_set.name_id)),\n          sema, clang::OCD_AmbiguousCandidates, arg_exprs);\n      return SemIR::ErrorInst::InstId;\n    }\n    case clang::OverloadingResult::OR_Deleted: {\n      sema.DiagnoseUseOfDeletedFunction(\n          loc, clang::SourceRange(loc, loc),\n          GetCppName(context, overload_set.name_id), candidate_set,\n          best_viable_fn->Function, arg_exprs);\n      return SemIR::ErrorInst::InstId;\n    }\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/overload_resolution.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_OVERLOAD_RESOLUTION_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_OVERLOAD_RESOLUTION_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Checks whether a selected overload is accessible and diagnoses if not.\n// `parent_scope_id`, if specified, describes the scope that was named to find\n// the overload. If unspecified, we assume the overload was found in the class\n// that it is a direct member of, rather than a derived class.\nauto CheckCppOverloadAccess(\n    Context& context, SemIR::LocId loc_id, clang::DeclAccessPair overload,\n    SemIR::KnownInstId<SemIR::FunctionDecl> overload_inst_id,\n    SemIR::NameScopeId parent_scope_id = SemIR::NameScopeId::None) -> void;\n\n// Resolves which function to call using Clang overload resolution. Returns an\n// instruction referring to that function, or an error instruction if overload\n// resolution failed.\n//\n// A set with a single non-templated function goes through the same rules for\n// overload resolution. This is to make sure that calls that have no viable\n// implicit conversion sequence are rejected even when an implicit conversion is\n// possible. Keeping the same behavior here for consistency and supporting\n// migrations so that the migrated callers from C++ remain valid.\nauto PerformCppOverloadResolution(\n    Context& context, SemIR::LocId loc_id,\n    const SemIR::CppOverloadSet& overload_set,\n    llvm::ArrayRef<SemIR::InstId> template_arg_ids, SemIR::InstId self_id,\n    llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_OVERLOAD_RESOLUTION_H_\n"
  },
  {
    "path": "toolchain/check/cpp/thunk.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/thunk.h\"\n\n#include \"clang/AST/ASTConsumer.h\"\n#include \"clang/AST/GlobalDecl.h\"\n#include \"clang/AST/Mangle.h\"\n#include \"clang/Sema/Lookup.h\"\n#include \"clang/Sema/Overload.h\"\n#include \"clang/Sema/Sema.h\"\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/literal.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Returns the GlobalDecl to use to represent the given function declaration.\n// TODO: Refactor with `Lower::CreateGlobalDecl`.\nstatic auto GetGlobalDecl(const clang::FunctionDecl* decl)\n    -> clang::GlobalDecl {\n  if (const auto* ctor = dyn_cast<clang::CXXConstructorDecl>(decl)) {\n    return clang::GlobalDecl(ctor, clang::CXXCtorType::Ctor_Complete);\n  }\n  if (const auto* dtor = dyn_cast<clang::CXXDestructorDecl>(decl)) {\n    return clang::GlobalDecl(dtor, clang::CXXDtorType::Dtor_Complete);\n  }\n  return clang::GlobalDecl(decl);\n}\n\n// Returns the C++ thunk mangled name given the callee function.\nstatic auto GenerateThunkMangledName(\n    clang::MangleContext& mangle_context,\n    const clang::FunctionDecl& callee_function_decl,\n    SemIR::ClangDeclKey::Signature::Kind signature_kind, int num_params)\n    -> std::string {\n  RawStringOstream mangled_name_stream;\n  mangle_context.mangleName(GetGlobalDecl(&callee_function_decl),\n                            mangled_name_stream);\n  switch (signature_kind) {\n    case SemIR::ClangDeclKey::Signature::Normal:\n      mangled_name_stream << \".carbon_thunk\";\n      break;\n    case SemIR::ClangDeclKey::Signature::TuplePattern:\n      mangled_name_stream << \".carbon_thunk_tuple\";\n      break;\n  }\n\n  if (num_params !=\n      static_cast<int>(callee_function_decl.getNumNonObjectParams())) {\n    mangled_name_stream << num_params;\n  }\n\n  return mangled_name_stream.TakeStr();\n}\n\n// Returns whether the Carbon lowering for a parameter or return of this type is\n// known to match the C++ lowering.\nstatic auto IsSimpleAbiType(clang::ASTContext& ast_context,\n                            clang::QualType type, bool for_parameter) -> bool {\n  if (type->isVoidType() || type->isPointerType()) {\n    return true;\n  }\n\n  if (type->isReferenceType()) {\n    if (for_parameter) {\n      // A reference parameter has a simple ABI if it's a non-const lvalue\n      // reference.  Otherwise, we map it to pass-by-value, and it's only simple\n      // if the type uses a pointer value representation.\n      //\n      // TODO: Check whether the pointee type maps to a Carbon type that uses a\n      // pointer value representation, and treat it as simple if so.\n      return type->isLValueReferenceType() &&\n             !type->getPointeeType().isConstQualified();\n    }\n\n    // A reference return type is always mapped to a Carbon pointer, which uses\n    // the same ABI rule as a C++ reference.\n    return true;\n  }\n\n  if (const auto* enum_decl = type->getAsEnumDecl()) {\n    // An enum type has a simple ABI if its underlying type does.\n    type = enum_decl->getIntegerType();\n    if (type.isNull()) {\n      return false;\n    }\n  }\n\n  if (const auto* builtin_type = type->getAs<clang::BuiltinType>()) {\n    if (builtin_type->isIntegerType()) {\n      uint64_t type_size = ast_context.getIntWidth(type);\n      return type_size == 32 || type_size == 64;\n    }\n  }\n\n  return false;\n}\n\nnamespace {\n// Information about the callee of a thunk.\nstruct CalleeFunctionInfo {\n  explicit CalleeFunctionInfo(clang::FunctionDecl* decl,\n                              SemIR::ClangDeclKey::Signature signature)\n      : decl(decl),\n        signature_kind(signature.kind),\n        num_params(signature.num_params +\n                   decl->hasCXXExplicitFunctionObjectParameter()) {\n    auto& ast_context = decl->getASTContext();\n    const auto* method_decl = dyn_cast<clang::CXXMethodDecl>(decl);\n    bool is_ctor = isa<clang::CXXConstructorDecl>(decl);\n    has_object_parameter = method_decl && !method_decl->isStatic() && !is_ctor;\n    if (has_object_parameter && method_decl->isImplicitObjectMemberFunction()) {\n      implicit_object_parameter_type =\n          method_decl->getFunctionObjectParameterReferenceType();\n    }\n    effective_return_type =\n        is_ctor ? ast_context.getCanonicalTagType(method_decl->getParent())\n                : decl->getReturnType();\n    has_simple_return_type = IsSimpleAbiType(ast_context, effective_return_type,\n                                             /*for_parameter=*/false);\n  }\n\n  // Returns whether this callee has an implicit `this` parameter.\n  auto has_implicit_object_parameter() const -> bool {\n    return !implicit_object_parameter_type.isNull();\n  }\n\n  // Returns whether this callee has an explicit `this` parameter.\n  auto has_explicit_object_parameter() const -> bool {\n    return has_object_parameter && !has_implicit_object_parameter();\n  }\n\n  // Returns the number of parameters the thunk should have.\n  auto num_thunk_params() const -> unsigned {\n    return has_implicit_object_parameter() + num_params +\n           !has_simple_return_type;\n  }\n\n  // Returns the thunk parameter index corresponding to a given callee parameter\n  // index.\n  auto GetThunkParamIndex(unsigned callee_param_index) const -> unsigned {\n    return has_implicit_object_parameter() + callee_param_index;\n  }\n\n  // Returns the thunk parameter index corresponding to the parameter that holds\n  // the address of the return value.\n  auto GetThunkReturnParamIndex() const -> unsigned {\n    CARBON_CHECK(!has_simple_return_type);\n    return has_implicit_object_parameter() + num_params;\n  }\n\n  // The callee function.\n  clang::FunctionDecl* decl;\n\n  // The kind of function signature being imported.\n  SemIR::ClangDeclKey::Signature::Kind signature_kind;\n\n  // The number of explicit parameters to import. This may be less than the\n  // number of parameters that the function has if default arguments are being\n  // used.\n  int num_params;\n\n  // Whether the callee has an object parameter, which might be explicit or\n  // implicit.\n  bool has_object_parameter;\n\n  // If the callee has an implicit object parameter, the type of that parameter,\n  // which will always be a reference type. Otherwise a null type.\n  clang::QualType implicit_object_parameter_type;\n\n  // The return type that the callee has when viewed from Carbon. This is the\n  // C++ return type, except that constructors return the class type in Carbon\n  // and return void in Clang's AST.\n  clang::QualType effective_return_type;\n\n  // Whether the callee has a simple return type, that we can return directly.\n  // If not, we'll return through an out parameter instead.\n  bool has_simple_return_type;\n};\n}  // namespace\n\nauto IsCppThunkRequired(Context& context, const SemIR::Function& function)\n    -> bool {\n  if (!function.clang_decl_id.has_value()) {\n    return false;\n  }\n\n  const auto& decl_info = context.clang_decls().Get(function.clang_decl_id);\n  auto* decl = cast<clang::FunctionDecl>(decl_info.key.decl);\n  if (decl_info.key.signature.kind != SemIR::ClangDeclKey::Signature::Normal ||\n      decl_info.key.signature.num_params !=\n          static_cast<int>(decl->getNumNonObjectParams())) {\n    // We require a thunk if the number of parameters we want isn't all of them.\n    // This happens if default arguments are in use, or (eventually) when\n    // calling a varargs function.\n    return true;\n  }\n\n  CalleeFunctionInfo callee_info(decl, decl_info.key.signature);\n  if (!callee_info.has_simple_return_type) {\n    return true;\n  }\n\n  auto& ast_context = context.ast_context();\n  if (callee_info.has_implicit_object_parameter() &&\n      !IsSimpleAbiType(ast_context, callee_info.implicit_object_parameter_type,\n                       /*for_parameter=*/true)) {\n    return true;\n  }\n\n  const auto* function_type =\n      decl->getType()->castAs<clang::FunctionProtoType>();\n  for (int i : llvm::seq(decl->getNumParams())) {\n    if (!IsSimpleAbiType(ast_context, function_type->getParamType(i),\n                         /*for_parameter=*/true)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n// Given a pointer type, returns the corresponding _Nonnull-qualified pointer\n// type.\nstatic auto GetNonnullType(clang::ASTContext& ast_context,\n                           clang::QualType pointer_type) -> clang::QualType {\n  return ast_context.getAttributedType(clang::NullabilityKind::NonNull,\n                                       pointer_type, pointer_type);\n}\n\n// Given a type, returns the corresponding _Nonnull-qualified pointer type,\n// ignoring references.\nstatic auto GetNonNullablePointerType(clang::ASTContext& ast_context,\n                                      clang::QualType type) {\n  return GetNonnullType(ast_context,\n                        ast_context.getPointerType(type.getNonReferenceType()));\n}\n\n// Given the type of a callee parameter, returns the type to use for the\n// corresponding thunk parameter.\nstatic auto GetThunkParameterType(clang::ASTContext& ast_context,\n                                  clang::QualType callee_type)\n    -> clang::QualType {\n  if (IsSimpleAbiType(ast_context, callee_type, /*for_parameter=*/true)) {\n    return callee_type;\n  }\n  return GetNonNullablePointerType(ast_context, callee_type);\n}\n\n// Creates the thunk parameter types given the callee function.\nstatic auto BuildThunkParameterTypes(clang::ASTContext& ast_context,\n                                     CalleeFunctionInfo callee_info)\n    -> llvm::SmallVector<clang::QualType> {\n  llvm::SmallVector<clang::QualType> thunk_param_types;\n  thunk_param_types.reserve(callee_info.num_thunk_params());\n  if (callee_info.has_implicit_object_parameter()) {\n    thunk_param_types.push_back(callee_info.implicit_object_parameter_type);\n  }\n\n  const auto* function_type =\n      callee_info.decl->getType()->castAs<clang::FunctionProtoType>();\n  for (int i : llvm::seq(callee_info.num_params)) {\n    thunk_param_types.push_back(\n        GetThunkParameterType(ast_context, function_type->getParamType(i)));\n  }\n\n  if (!callee_info.has_simple_return_type) {\n    thunk_param_types.push_back(GetNonNullablePointerType(\n        ast_context, callee_info.effective_return_type));\n  }\n\n  CARBON_CHECK(thunk_param_types.size() == callee_info.num_thunk_params());\n  return thunk_param_types;\n}\n\n// Returns the thunk parameters using the callee function parameter identifiers.\nstatic auto BuildThunkParameters(clang::ASTContext& ast_context,\n                                 CalleeFunctionInfo callee_info,\n                                 clang::FunctionDecl* thunk_function_decl)\n    -> llvm::SmallVector<clang::ParmVarDecl*> {\n  clang::SourceLocation clang_loc = callee_info.decl->getLocation();\n\n  const auto* thunk_function_proto_type =\n      thunk_function_decl->getType()->castAs<clang::FunctionProtoType>();\n\n  llvm::SmallVector<clang::ParmVarDecl*> thunk_params;\n  unsigned num_thunk_params = thunk_function_decl->getNumParams();\n  thunk_params.reserve(num_thunk_params);\n\n  if (callee_info.has_implicit_object_parameter()) {\n    clang::ParmVarDecl* thunk_param =\n        clang::ParmVarDecl::Create(ast_context, thunk_function_decl, clang_loc,\n                                   clang_loc, &ast_context.Idents.get(\"this\"),\n                                   thunk_function_proto_type->getParamType(0),\n                                   nullptr, clang::SC_None, nullptr);\n    thunk_params.push_back(thunk_param);\n  }\n\n  for (int i : llvm::seq(callee_info.num_params)) {\n    clang::ParmVarDecl* thunk_param = clang::ParmVarDecl::Create(\n        ast_context, thunk_function_decl, clang_loc, clang_loc,\n        callee_info.decl->getParamDecl(i)->getIdentifier(),\n        thunk_function_proto_type->getParamType(\n            callee_info.GetThunkParamIndex(i)),\n        nullptr, clang::SC_None, nullptr);\n    thunk_params.push_back(thunk_param);\n  }\n\n  if (!callee_info.has_simple_return_type) {\n    clang::ParmVarDecl* thunk_param =\n        clang::ParmVarDecl::Create(ast_context, thunk_function_decl, clang_loc,\n                                   clang_loc, &ast_context.Idents.get(\"return\"),\n                                   thunk_function_proto_type->getParamType(\n                                       callee_info.GetThunkReturnParamIndex()),\n                                   nullptr, clang::SC_None, nullptr);\n    thunk_params.push_back(thunk_param);\n  }\n\n  CARBON_CHECK(thunk_params.size() == num_thunk_params);\n  return thunk_params;\n}\n\n// Computes a name to use for a thunk, based on the name of the thunk's target.\n// The actual name used isn't critical, since it doesn't show up much except in\n// AST dumps and SemIR output, but we try to produce a valid C++ identifier.\nstatic auto GetDeclNameForThunk(clang::ASTContext& ast_context,\n                                clang::DeclarationName name)\n    -> clang::DeclarationName {\n  llvm::SmallString<64> thunk_name;\n  switch (name.getNameKind()) {\n    case clang::DeclarationName::NameKind::Identifier: {\n      thunk_name = name.getAsIdentifierInfo()->getName();\n      break;\n    }\n    case clang::DeclarationName::NameKind::CXXOperatorName: {\n      thunk_name = \"operator_\";\n      switch (name.getCXXOverloadedOperator()) {\n        case clang::OO_None:\n        case clang::NUM_OVERLOADED_OPERATORS:\n          break;\n#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \\\n  case clang::OO_##Name:                                                      \\\n    thunk_name += #Name;                                                      \\\n    break;\n#include \"clang/Basic/OperatorKinds.def\"\n      }\n      break;\n    }\n    default: {\n      break;\n    }\n  }\n  if (auto type = name.getCXXNameType(); !type.isNull()) {\n    if (auto* class_decl = type->getAsCXXRecordDecl()) {\n      thunk_name += class_decl->getName();\n    }\n  }\n  thunk_name += \"__carbon_thunk\";\n  return &ast_context.Idents.get(thunk_name);\n}\n\n// Returns the thunk function declaration given the callee function and the\n// thunk parameter types.\nstatic auto CreateThunkFunctionDecl(\n    Context& context, CalleeFunctionInfo callee_info,\n    llvm::ArrayRef<clang::QualType> thunk_param_types) -> clang::FunctionDecl* {\n  clang::ASTContext& ast_context = context.ast_context();\n  clang::SourceLocation clang_loc = callee_info.decl->getLocation();\n  clang::DeclarationName name =\n      GetDeclNameForThunk(ast_context, callee_info.decl->getDeclName());\n\n  auto ext_proto_info = clang::FunctionProtoType::ExtProtoInfo();\n  clang::QualType thunk_function_type = ast_context.getFunctionType(\n      callee_info.has_simple_return_type ? callee_info.effective_return_type\n                                         : ast_context.VoidTy,\n      thunk_param_types, ext_proto_info);\n\n  clang::DeclContext* decl_context = ast_context.getTranslationUnitDecl();\n  // TODO: Thunks should not have external linkage, consider using `SC_Static`.\n  clang::FunctionDecl* thunk_function_decl =\n      clang::FunctionDecl::Create(ast_context, decl_context, clang_loc,\n                                  clang_loc, name, thunk_function_type,\n                                  /*TInfo=*/nullptr, clang::SC_Extern);\n  decl_context->addDecl(thunk_function_decl);\n\n  thunk_function_decl->setParams(\n      BuildThunkParameters(ast_context, callee_info, thunk_function_decl));\n\n  // Set always_inline.\n  thunk_function_decl->addAttr(\n      clang::AlwaysInlineAttr::CreateImplicit(ast_context));\n\n  // Set asm(\"<callee function mangled name>.carbon_thunk\").\n  thunk_function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(\n      ast_context,\n      GenerateThunkMangledName(\n          context.cpp_context()->clang_mangle_context(), *callee_info.decl,\n          callee_info.signature_kind,\n          callee_info.num_params - callee_info.has_explicit_object_parameter()),\n      clang_loc));\n\n  // Set function declaration type source info.\n  thunk_function_decl->setTypeSourceInfo(ast_context.getTrivialTypeSourceInfo(\n      thunk_function_decl->getType(), clang_loc));\n\n  return thunk_function_decl;\n}\n\n// Builds a reference to the given parameter thunk. If `type` is specified, that\n// is the callee parameter type that's being held by the parameter, and\n// conversions will be performed as necessary to recover a value of that type.\nstatic auto BuildThunkParamRef(clang::Sema& sema,\n                               clang::FunctionDecl* thunk_function_decl,\n                               unsigned thunk_index,\n                               clang::QualType type = clang::QualType())\n    -> clang::Expr* {\n  clang::ParmVarDecl* thunk_param =\n      thunk_function_decl->getParamDecl(thunk_index);\n  clang::SourceLocation clang_loc = thunk_param->getLocation();\n\n  clang::Expr* call_arg = sema.BuildDeclRefExpr(\n      thunk_param, thunk_param->getType().getNonReferenceType(),\n      clang::VK_LValue, clang_loc);\n  if (!type.isNull() && thunk_param->getType() != type) {\n    clang::ExprResult deref_result =\n        sema.BuildUnaryOp(nullptr, clang_loc, clang::UO_Deref, call_arg);\n    CARBON_CHECK(deref_result.isUsable());\n    call_arg = deref_result.get();\n  }\n\n  // Cast to an rvalue when initializing an rvalue reference. The validity of\n  // the initialization of the reference should be validated by the caller of\n  // the thunk.\n  //\n  // TODO: Consider inserting a cast to an rvalue in more cases. Note that we\n  // currently pass pointers to non-temporary objects as the argument when\n  // calling a thunk, so we'll need to either change that or generate\n  // different thunks depending on whether we're moving from each parameter.\n  if (!type.isNull() && type->isRValueReferenceType()) {\n    call_arg = clang::ImplicitCastExpr::Create(\n        sema.getASTContext(), call_arg->getType(), clang::CK_NoOp, call_arg,\n        nullptr, clang::ExprValueKind::VK_XValue, clang::FPOptionsOverride());\n  }\n  return call_arg;\n}\n\n// Builds a reference to the parameter thunk parameter corresponding to the\n// given callee parameter index.\nstatic auto BuildParamRefForCalleeArg(clang::Sema& sema,\n                                      clang::FunctionDecl* thunk_function_decl,\n                                      CalleeFunctionInfo callee_info,\n                                      unsigned callee_index) -> clang::Expr* {\n  unsigned thunk_index = callee_info.GetThunkParamIndex(callee_index);\n  return BuildThunkParamRef(\n      sema, thunk_function_decl, thunk_index,\n      callee_info.decl->getParamDecl(callee_index)->getType());\n}\n\n// Builds an argument list for the callee function by creating suitable uses of\n// the corresponding thunk parameters.\nstatic auto BuildCalleeArgs(clang::Sema& sema,\n                            clang::FunctionDecl* thunk_function_decl,\n                            CalleeFunctionInfo callee_info)\n    -> llvm::SmallVector<clang::Expr*> {\n  llvm::SmallVector<clang::Expr*> call_args;\n  // The object parameter is always passed as `self`, not in the callee argument\n  // list, so the first argument corresponds to the second parameter if there is\n  // an explicit object parameter and the first parameter otherwise.\n  int first_param = callee_info.has_explicit_object_parameter();\n  call_args.reserve(callee_info.num_params - first_param);\n  for (unsigned callee_index : llvm::seq(first_param, callee_info.num_params)) {\n    call_args.push_back(BuildParamRefForCalleeArg(sema, thunk_function_decl,\n                                                  callee_info, callee_index));\n  }\n  return call_args;\n}\n\n// Builds the thunk function body which calls the callee function using the call\n// args and returns the callee function return value. Returns nullptr on\n// failure.\nstatic auto BuildThunkBody(clang::Sema& sema,\n                           clang::FunctionDecl* thunk_function_decl,\n                           CalleeFunctionInfo callee_info)\n    -> clang::StmtResult {\n  // TODO: Consider building a CompoundStmt holding our created statement to\n  // make our result more closely resemble a real C++ function.\n\n  clang::SourceLocation clang_loc = callee_info.decl->getLocation();\n\n  // If the callee has an object parameter, build a member access expression as\n  // the callee. Otherwise, build a regular reference to the function.\n  clang::ExprResult callee;\n  if (callee_info.has_object_parameter) {\n    clang::QualType object_param_type =\n        cast<clang::CXXMethodDecl>(callee_info.decl)\n            ->getFunctionObjectParameterReferenceType();\n    auto* object_param_ref =\n        BuildThunkParamRef(sema, thunk_function_decl, 0, object_param_type);\n    constexpr bool IsArrow = false;\n    auto object =\n        sema.PerformMemberExprBaseConversion(object_param_ref, IsArrow);\n    if (object.isInvalid()) {\n      return clang::StmtError();\n    }\n    callee = sema.BuildMemberExpr(\n        object.get(), IsArrow, clang_loc, clang::NestedNameSpecifierLoc(),\n        clang::SourceLocation(), callee_info.decl,\n        clang::DeclAccessPair::make(callee_info.decl, clang::AS_public),\n        /*HadMultipleCandidates=*/false, clang::DeclarationNameInfo(),\n        sema.getASTContext().BoundMemberTy, clang::VK_PRValue,\n        clang::OK_Ordinary);\n  } else if (!isa<clang::CXXConstructorDecl>(callee_info.decl)) {\n    callee =\n        sema.BuildDeclRefExpr(callee_info.decl, callee_info.decl->getType(),\n                              clang::VK_PRValue, clang_loc);\n  }\n\n  if (callee.isInvalid()) {\n    return clang::StmtError();\n  }\n\n  // Build the argument list.\n  llvm::SmallVector<clang::Expr*> call_args =\n      BuildCalleeArgs(sema, thunk_function_decl, callee_info);\n\n  clang::ExprResult call;\n  if (auto info = clang::getConstructorInfo(callee_info.decl);\n      info.Constructor) {\n    // In C++, there are no direct calls to constructors, only initialization,\n    // so we need to type-check and build the call ourselves.\n    auto type = sema.Context.getCanonicalTagType(\n        cast<clang::CXXRecordDecl>(callee_info.decl->getParent()));\n    llvm::SmallVector<clang::Expr*> converted_args;\n    converted_args.reserve(call_args.size());\n    if (sema.CompleteConstructorCall(info.Constructor, type, call_args,\n                                     clang_loc, converted_args)) {\n      return clang::StmtError();\n    }\n    call = sema.BuildCXXConstructExpr(\n        clang_loc, type, callee_info.decl, info.Constructor, converted_args,\n        false, false, false, false, clang::CXXConstructionKind::Complete,\n        clang_loc);\n  } else {\n    call = sema.BuildCallExpr(nullptr, callee.get(), clang_loc, call_args,\n                              clang_loc);\n  }\n  if (!call.isUsable()) {\n    return clang::StmtError();\n  }\n\n  if (callee_info.has_simple_return_type) {\n    return sema.BuildReturnStmt(clang_loc, call.get());\n  }\n\n  auto* return_object_addr = BuildThunkParamRef(\n      sema, thunk_function_decl, callee_info.GetThunkReturnParamIndex());\n  auto return_type = callee_info.effective_return_type.getNonReferenceType();\n  auto* return_type_info =\n      sema.Context.getTrivialTypeSourceInfo(return_type, clang_loc);\n  auto placement_new = sema.BuildCXXNew(\n      clang_loc, /*UseGlobal=*/true, clang_loc, {return_object_addr}, clang_loc,\n      /*TypeIdParens=*/clang::SourceRange(), return_type, return_type_info,\n      /*ArraySize=*/std::nullopt, clang_loc, call.get());\n  return sema.ActOnExprStmt(placement_new, /*DiscardedValue=*/true);\n}\n\nauto BuildCppThunk(Context& context, const SemIR::Function& callee_function)\n    -> clang::FunctionDecl* {\n  auto clang_decl_key =\n      context.clang_decls().Get(callee_function.clang_decl_id).key;\n  clang::FunctionDecl* callee_function_decl =\n      clang_decl_key.decl->getAsFunction();\n  CARBON_CHECK(callee_function_decl);\n\n  // TODO: The signature kind doesn't affect the thunk that we build, so we\n  // shouldn't consider it here. However, to do that, we would need to cache the\n  // thunks we build so that we don't build the same thunk multiple times if\n  // it's used with multiple different signature kinds.\n  CalleeFunctionInfo callee_info(callee_function_decl,\n                                 clang_decl_key.signature);\n\n  // Build the thunk function declaration.\n  auto thunk_param_types =\n      BuildThunkParameterTypes(context.ast_context(), callee_info);\n  clang::FunctionDecl* thunk_function_decl =\n      CreateThunkFunctionDecl(context, callee_info, thunk_param_types);\n\n  // Build the thunk function body.\n  clang::Sema& sema = context.clang_sema();\n  clang::Sema::ContextRAII context_raii(sema, thunk_function_decl);\n  sema.ActOnStartOfFunctionDef(nullptr, thunk_function_decl);\n  clang::StmtResult body =\n      BuildThunkBody(sema, thunk_function_decl, callee_info);\n  sema.ActOnFinishFunctionBody(thunk_function_decl, body.get());\n  if (body.isInvalid()) {\n    return nullptr;\n  }\n\n  context.clang_sema().getASTConsumer().HandleTopLevelDecl(\n      clang::DeclGroupRef(thunk_function_decl));\n  return thunk_function_decl;\n}\n\nauto PerformCppThunkCall(Context& context, SemIR::LocId loc_id,\n                         SemIR::FunctionId callee_function_id,\n                         llvm::ArrayRef<SemIR::InstId> callee_arg_ids,\n                         SemIR::InstId thunk_callee_id) -> SemIR::InstId {\n  auto& callee_function = context.functions().Get(callee_function_id);\n  auto callee_function_params =\n      context.inst_blocks().Get(callee_function.call_params_id);\n  auto callee_return_patterns =\n      context.inst_blocks().GetOrEmpty(callee_function.return_patterns_id);\n\n  auto thunk_callee = GetCalleeAsFunction(context.sem_ir(), thunk_callee_id);\n  auto& thunk_function = context.functions().Get(thunk_callee.function_id);\n  auto thunk_function_params =\n      context.inst_blocks().Get(thunk_function.call_params_id);\n  auto thunk_return_patterns =\n      context.inst_blocks().GetOrEmpty(thunk_function.return_patterns_id);\n\n  CARBON_CHECK(\n      callee_return_patterns.size() <= 1 && thunk_return_patterns.size() <= 1,\n      \"TODO: generalize this logic to support multiple return patterns.\");\n\n  // Whether we need to pass a return address to the thunk as a final argument.\n  bool thunk_takes_return_address =\n      !callee_return_patterns.empty() && thunk_return_patterns.empty();\n\n  // The number of arguments we should be acquiring in order to call the thunk.\n  // This includes the return address parameters, if any.\n  unsigned num_thunk_args =\n      context.inst_blocks().Get(thunk_function.param_patterns_id).size();\n\n  // The corresponding number of arguments that would be provided in a syntactic\n  // call to the callee. This excludes the return slot.\n  unsigned num_callee_args = num_thunk_args - thunk_takes_return_address;\n\n  // Grab the return slot argument, if we were given one.\n  auto return_slot_id = SemIR::InstId::None;\n  if (callee_arg_ids.size() == num_callee_args + 1) {\n    return_slot_id = callee_arg_ids.consume_back();\n  }\n\n  // If there are return slot patterns, drop the corresponding parameters.\n  // TODO: The parameter should probably only be created if the return pattern\n  // actually needs a return address to be passed in.\n  thunk_function_params =\n      thunk_function_params.drop_back(thunk_return_patterns.size());\n  callee_function_params =\n      callee_function_params.drop_back(callee_return_patterns.size());\n\n  // We assume that the call parameters exactly match the parameter patterns for\n  // both the thunk and the callee. This is guaranteed even when we generate a\n  // tuple pattern wrapping the function parameters.\n  CARBON_CHECK(num_callee_args == callee_function_params.size(), \"{0} != {1}\",\n               num_callee_args, callee_function_params.size());\n  CARBON_CHECK(num_callee_args == callee_arg_ids.size());\n  CARBON_CHECK(num_thunk_args == thunk_function_params.size());\n\n  // Build the thunk arguments by converting the callee arguments as needed.\n  llvm::SmallVector<SemIR::InstId> thunk_arg_ids;\n  thunk_arg_ids.reserve(num_thunk_args);\n  for (auto [callee_param_inst_id, thunk_param_inst_id, callee_arg_id] :\n       llvm::zip(callee_function_params, thunk_function_params,\n                 callee_arg_ids)) {\n    SemIR::TypeId callee_param_type_id =\n        context.insts().GetAs<SemIR::AnyParam>(callee_param_inst_id).type_id;\n    SemIR::TypeId thunk_param_type_id =\n        context.insts().GetAs<SemIR::AnyParam>(thunk_param_inst_id).type_id;\n\n    SemIR::InstId arg_id = callee_arg_id;\n    if (callee_param_type_id != thunk_param_type_id) {\n      arg_id = Convert(context, loc_id, arg_id,\n                       {.kind = ConversionTarget::CppThunkRef,\n                        .type_id = callee_param_type_id});\n      arg_id = AddInst<SemIR::AddrOf>(\n          context, loc_id,\n          {.type_id = GetPointerType(\n               context, context.types().GetTypeInstId(callee_param_type_id)),\n           .lvalue_id = arg_id});\n      arg_id =\n          ConvertToValueOfType(context, loc_id, arg_id, thunk_param_type_id);\n    }\n    thunk_arg_ids.push_back(arg_id);\n  }\n\n  // Add an argument to hold the result of the call, if necessary.\n  auto return_type_id = callee_function.GetDeclaredReturnType(context.sem_ir());\n  if (thunk_takes_return_address) {\n    // Create a temporary if the caller didn't provide a return slot.\n    if (!return_slot_id.has_value()) {\n      return_slot_id = AddInst<SemIR::TemporaryStorage>(\n          context, loc_id, {.type_id = return_type_id});\n    }\n\n    auto arg_id = AddInst<SemIR::AddrOf>(\n        context, loc_id,\n        {.type_id = GetPointerType(\n             context, context.types().GetTypeInstId(\n                          context.insts().Get(return_slot_id).type_id())),\n         .lvalue_id = return_slot_id});\n    thunk_arg_ids.push_back(arg_id);\n  } else if (return_slot_id.has_value()) {\n    thunk_arg_ids.push_back(return_slot_id);\n  }\n\n  // Compute the return type of the call to the thunk.\n  auto thunk_return_type_id =\n      thunk_function.GetDeclaredReturnType(context.sem_ir());\n  if (!thunk_return_type_id.has_value()) {\n    CARBON_CHECK(thunk_takes_return_address || !return_type_id.has_value());\n    thunk_return_type_id = GetTupleType(context, {});\n  } else {\n    CARBON_CHECK(thunk_return_type_id == return_type_id);\n  }\n\n  auto result_id = GetOrAddInst<SemIR::Call>(\n      context, loc_id,\n      {.type_id = thunk_return_type_id,\n       .callee_id = thunk_callee_id,\n       .args_id = context.inst_blocks().Add(thunk_arg_ids)});\n\n  // Produce the result of the call, taking the value from the return storage.\n  if (thunk_takes_return_address) {\n    result_id = AddInst<SemIR::MarkInPlaceInit>(context, loc_id,\n                                                {.type_id = return_type_id,\n                                                 .src_id = result_id,\n                                                 .dest_id = return_slot_id});\n  }\n\n  return result_id;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/thunk.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_THUNK_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_THUNK_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Returns whether the given C++ imported function requires a C++ thunk to be\n// used to call it. A C++ thunk is required for functions whose ABI uses any\n// type except void, pointer and reference types, and signed 32-bit and 64-bit\n// integers.\nauto IsCppThunkRequired(Context& context, const SemIR::Function& function)\n    -> bool;\n\n// Given a function signature and a callee function, builds a C++ thunk with\n// simple ABI (pointers, i32 and i64 types) that calls the specified callee.\n// Assumes `IsCppThunkRequired()` return true for `callee_function`. Returns\n// `nullptr` on failure.\nauto BuildCppThunk(Context& context, const SemIR::Function& callee_function)\n    -> clang::FunctionDecl*;\n\n// Builds a call to a thunk function that forwards a call argument list built\n// for `callee_function_id` to a call to `thunk_callee_id`, for use when\n// building a call from a C++ thunk to its target. This is like `PerformCall`,\n// except that it takes a list of call arguments for `callee_function_id`, not a\n// syntactic argument list.\nauto PerformCppThunkCall(Context& context, SemIR::LocId loc_id,\n                         SemIR::FunctionId callee_function_id,\n                         llvm::ArrayRef<SemIR::InstId> callee_arg_ids,\n                         SemIR::InstId thunk_callee_id) -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_THUNK_H_\n"
  },
  {
    "path": "toolchain/check/cpp/type_mapping.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/cpp/type_mapping.h\"\n\n#include <cstddef>\n#include <iostream>\n#include <optional>\n\n#include \"clang/AST/Type.h\"\n#include \"clang/Basic/TargetInfo.h\"\n#include \"clang/Sema/Lookup.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/base/int.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/base/value_ids.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/cpp/location.h\"\n#include \"toolchain/check/literal.h\"\n#include \"toolchain/sem_ir/class.h\"\n#include \"toolchain/sem_ir/expr_info.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/inst_kind.h\"\n#include \"toolchain/sem_ir/type.h\"\n#include \"toolchain/sem_ir/type_info.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// A function that wraps a C++ type to form another C++ type. Note that this is\n// a raw function pointer; we don't currently use any lambda captures here. This\n// can be replaced by a `std::function` if captures are found to be needed.\nusing WrapFn = auto (*)(Context& context, clang::QualType inner_type)\n    -> clang::QualType;\n\n// Represents a type that requires a subtype to be mapped into a Clang type\n// before it can be mapped.\nstruct WrappedType {\n  // The type contained in this wrapped type.\n  SemIR::TypeId inner_type_id;\n  // A function to construct the wrapped type from the mapped unwrapped type.\n  WrapFn wrap_fn;\n};\n\n// Possible results from attempting to map a type. A null QualType indicates\n// that the type couldn't be mapped.\nusing TryMapTypeResult = std::variant<clang::QualType, WrappedType>;\n\n// Find the bit width of an integer literal. Following the C++ standard rules\n// for assigning a type to a decimal integer literal, the first signed integer\n// in which the value could fit among bit widths of 32, 64 and 128 is selected.\n// If the value can't fit into a signed integer with width of 128-bits, then a\n// diagnostic is emitted and the function returns IntId::None. Returns\n// IntId::None also if the argument is not a constant integer, if it is an\n// error constant, or if it is a symbolic constant.\nstatic auto FindIntLiteralBitWidth(Context& context, SemIR::LocId loc_id,\n                                   SemIR::ConstantId arg_const_id) -> IntId {\n  if (!arg_const_id.is_constant() ||\n      arg_const_id == SemIR::ErrorInst::ConstantId ||\n      arg_const_id.is_symbolic()) {\n    // TODO: Add tests for these cases.\n    return IntId::None;\n  }\n  auto arg = context.insts().TryGetAs<SemIR::IntValue>(\n      context.constant_values().GetInstId(arg_const_id));\n  if (!arg) {\n    return IntId::None;\n  }\n  llvm::APInt arg_val = context.ints().Get(arg->int_id);\n  int arg_non_sign_bits = arg_val.getSignificantBits() - 1;\n\n  if (arg_non_sign_bits >= 128) {\n    CARBON_DIAGNOSTIC(IntTooLargeForCppType, Error,\n                      \"integer value {0} too large to fit in a signed C++ \"\n                      \"integer type; requires {1} bits, but max is 128\",\n                      TypedInt, int);\n    context.emitter().Emit(loc_id, IntTooLargeForCppType,\n                           {.type = arg->type_id, .value = arg_val},\n                           arg_non_sign_bits + 1);\n    return IntId::None;\n  }\n\n  return (arg_non_sign_bits < 32)\n             ? IntId::MakeRaw(32)\n             : ((arg_non_sign_bits < 64) ? IntId::MakeRaw(64)\n                                         : IntId::MakeRaw(128));\n}\n\n// Attempts to look up a type by name, and returns the corresponding `QualType`,\n// or a null type if lookup fails. `name_components` is the full path of the\n// type, including any namespaces or nested types, separated into separate\n// strings.\nstatic auto LookupCppType(\n    Context& context, std::initializer_list<llvm::StringRef> name_components)\n    -> clang::QualType {\n  clang::Sema& sema = context.clang_sema();\n\n  clang::Decl* decl = sema.getASTContext().getTranslationUnitDecl();\n  for (auto name_component : name_components) {\n    auto* scope = dyn_cast<clang::DeclContext>(decl);\n    if (!scope) {\n      return clang::QualType();\n    }\n\n    // TODO: Map the LocId of the lookup to a clang SourceLocation and provide\n    // it here so that clang's diagnostics can point into the carbon code that\n    // uses the name.\n    auto* identifier = sema.getPreprocessor().getIdentifierInfo(name_component);\n    clang::LookupResult lookup(\n        sema, clang::DeclarationNameInfo(identifier, clang::SourceLocation()),\n        clang::Sema::LookupNameKind::LookupOrdinaryName);\n    if (!sema.LookupQualifiedName(lookup, scope) || !lookup.isSingleResult()) {\n      return clang::QualType();\n    }\n    decl = lookup.getFoundDecl();\n  }\n\n  auto* type_decl = dyn_cast<clang::TypeDecl>(decl);\n  return type_decl ? sema.getASTContext().getTypeDeclType(type_decl)\n                   : clang::QualType();\n}\n\n// Returns the given integer type if its width is as expected. Otherwise returns\n// the null type.\nstatic auto VerifyIntegerTypeWidth(Context& context, clang::QualType type,\n                                   unsigned int expected_width)\n    -> clang::QualType {\n  if (context.ast_context().getIntWidth(type) == expected_width) {\n    return type;\n  }\n  return clang::QualType();\n}\n\n// Maps a Carbon class type to a C++ type. Returns a null `QualType` if the\n// type is not supported.\nstatic auto TryMapClassType(Context& context, SemIR::ClassType class_type)\n    -> TryMapTypeResult {\n  clang::ASTContext& ast_context = context.ast_context();\n\n  // If the class was imported from C++, return the original C++ type.\n  auto clang_decl_id =\n      context.name_scopes()\n          .Get(context.classes().Get(class_type.class_id).scope_id)\n          .clang_decl_context_id();\n  if (clang_decl_id.has_value()) {\n    clang::Decl* clang_decl = context.clang_decls().Get(clang_decl_id).key.decl;\n    auto* tag_type_decl = clang::cast<clang::TagDecl>(clang_decl);\n    return ast_context.getCanonicalTagType(tag_type_decl);\n  }\n\n  // If the class represents a Carbon type literal, map it to the corresponding\n  // C++ builtin type.\n  auto type_info =\n      SemIR::RecognizedTypeInfo::ForType(context.sem_ir(), class_type);\n  switch (type_info.kind) {\n    case SemIR::RecognizedTypeInfo::None: {\n      break;\n    }\n    case SemIR::RecognizedTypeInfo::Numeric: {\n      // Carbon supports large bit width beyond C++ builtins; we don't translate\n      // those into integer types.\n      if (!type_info.numeric.bit_width_id.is_embedded_value()) {\n        break;\n      }\n      int bit_width = type_info.numeric.bit_width_id.AsValue();\n\n      switch (type_info.numeric.kind) {\n        case SemIR::NumericTypeLiteralInfo::None: {\n          CARBON_FATAL(\"Unexpected invalid numeric type literal\");\n        }\n        case SemIR::NumericTypeLiteralInfo::Float: {\n          return ast_context.getRealTypeForBitwidth(\n              bit_width, clang::FloatModeKind::NoFloat);\n        }\n        case SemIR::NumericTypeLiteralInfo::Int: {\n          return ast_context.getIntTypeForBitwidth(bit_width, true);\n        }\n        case SemIR::NumericTypeLiteralInfo::UInt: {\n          return ast_context.getIntTypeForBitwidth(bit_width, false);\n        }\n      }\n    }\n    case SemIR::RecognizedTypeInfo::Char: {\n      return ast_context.CharTy;\n    }\n    case SemIR::RecognizedTypeInfo::CppLong32: {\n      return VerifyIntegerTypeWidth(context, ast_context.LongTy, 32);\n    }\n    case SemIR::RecognizedTypeInfo::CppULong32: {\n      return VerifyIntegerTypeWidth(context, ast_context.UnsignedLongTy, 32);\n    }\n    case SemIR::RecognizedTypeInfo::CppLongLong64: {\n      return VerifyIntegerTypeWidth(context, ast_context.LongLongTy, 64);\n    }\n    case SemIR::RecognizedTypeInfo::CppULongLong64: {\n      return VerifyIntegerTypeWidth(context, ast_context.UnsignedLongLongTy,\n                                    64);\n    }\n    case SemIR::RecognizedTypeInfo::CppNullptrT: {\n      return ast_context.NullPtrTy;\n    }\n    case SemIR::RecognizedTypeInfo::CppVoidBase: {\n      return ast_context.VoidTy;\n    }\n    case SemIR::RecognizedTypeInfo::Optional: {\n      auto args = context.inst_blocks().GetOrEmpty(type_info.args_id);\n      if (args.size() == 1) {\n        auto arg_id = args[0];\n        if (auto facet = context.insts().TryGetAs<SemIR::FacetValue>(arg_id)) {\n          arg_id = facet->type_inst_id;\n        }\n        if (auto pointer_type =\n                context.insts().TryGetAs<SemIR::PointerType>(arg_id)) {\n          return WrappedType{\n              .inner_type_id = context.types().GetTypeIdForTypeInstId(\n                  pointer_type->pointee_id),\n              .wrap_fn = [](Context& context, clang::QualType inner_type) {\n                return context.ast_context().getPointerType(inner_type);\n              }};\n        }\n      }\n      break;\n    }\n    case SemIR::RecognizedTypeInfo::Str: {\n      return LookupCppType(context, {\"std\", \"string_view\"});\n    }\n  }\n\n  // Otherwise we don't have a mapping for this Carbon class type.\n  // TODO: If the class type wasn't imported from C++, create a corresponding\n  // C++ class type.\n  return clang::QualType();\n}\n\n// Maps a Carbon type to a C++ type. Either returns the mapped type, a null type\n// as a placeholder indicating the type can't be mapped, or a `WrappedType`\n// representing a type that needs more work before it can be mapped.\n// TODO: Have both Carbon -> C++ and C++ -> Carbon mappings in a single place\n// to keep them in sync.\nstatic auto TryMapType(Context& context, SemIR::TypeId type_id)\n    -> TryMapTypeResult {\n  auto type_inst = context.types().GetAsInst(type_id);\n\n  CARBON_KIND_SWITCH(type_inst) {\n    case SemIR::BoolType::Kind: {\n      return context.ast_context().BoolTy;\n    }\n    case Carbon::SemIR::CharLiteralType::Kind: {\n      return context.ast_context().CharTy;\n    }\n    case CARBON_KIND(SemIR::ClassType class_type): {\n      return TryMapClassType(context, class_type);\n    }\n    case CARBON_KIND(SemIR::ConstType const_type): {\n      return WrappedType{\n          .inner_type_id =\n              context.types().GetTypeIdForTypeInstId(const_type.inner_id),\n          .wrap_fn = [](Context& /*context*/, clang::QualType inner_type) {\n            return inner_type.withConst();\n          }};\n    }\n    case SemIR::FloatLiteralType::Kind: {\n      return context.ast_context().DoubleTy;\n    }\n    case CARBON_KIND(SemIR::PointerType pointer_type): {\n      return WrappedType{\n          .inner_type_id =\n              context.types().GetTypeIdForTypeInstId(pointer_type.pointee_id),\n          .wrap_fn = [](Context& context, clang::QualType inner_type) {\n            auto pointer_type =\n                context.ast_context().getPointerType(inner_type);\n            return context.ast_context().getAttributedType(\n                clang::attr::TypeNonNull, pointer_type, pointer_type);\n          }};\n    }\n\n    default: {\n      return clang::QualType();\n    }\n  }\n\n  return clang::QualType();\n}\n\nauto MapToCppType(Context& context, SemIR::TypeId type_id) -> clang::QualType {\n  // TODO: unify this with the C++ to Carbon type mapping function.\n  llvm::SmallVector<WrapFn> wrap_fns;\n  while (true) {\n    CARBON_KIND_SWITCH(TryMapType(context, type_id)) {\n      case CARBON_KIND(clang::QualType type): {\n        for (auto wrap_fn : llvm::reverse(wrap_fns)) {\n          if (type.isNull()) {\n            break;\n          }\n          type = wrap_fn(context, type);\n        }\n        return type;\n      }\n\n      case CARBON_KIND(WrappedType wrapped): {\n        wrap_fns.push_back(wrapped.wrap_fn);\n        type_id = wrapped.inner_type_id;\n        break;\n      }\n    }\n  }\n}\n\nnamespace {\n// Information about the form of an expression.\nstruct FormInfo {\n  enum Kind : int8_t {\n    Primitive,\n    Tuple,\n    Struct,\n  };\n\n  // The kind of the form.\n  Kind kind;\n  // The category component of the form. For a composite form, if this is not\n  // `Mixed` it represents the category component of all primitive sub-forms\n  // of this form.\n  SemIR::ExprCategory category;\n  // The type component of the form.\n  SemIR::TypeId type_id;\n  // The constant value component of the form.\n  SemIR::ConstantId constant_id;\n  // The location of the expression whose form this is.\n  SemIR::LocId loc_id;\n  // The underlying instruction, if there is one. This is only present in order\n  // to support lazy form decomposition, and should not be used for other\n  // purposes. May be `None` if this is not the form of a tuple or struct\n  // literal that can be decomposed further.\n  SemIR::InstId inst_id;\n\n  // Returns whether this is a compound form.\n  auto is_compound() const -> bool { return kind == Tuple || kind == Struct; }\n};\n}  // namespace\n\n// Given a type, determines the category of the decomposed form of an expression\n// of that type. This is Primitive if the type does not support form\n// decomposition.\nstatic auto GetDecomposedFormKindForType(Context& context,\n                                         SemIR::TypeId type_id)\n    -> FormInfo::Kind {\n  if (context.types().Is<SemIR::TupleType>(type_id)) {\n    return FormInfo::Tuple;\n  }\n  if (context.types().Is<SemIR::StructType>(type_id)) {\n    return FormInfo::Struct;\n  }\n  return FormInfo::Primitive;\n}\n\n// Gets information about the form of an instruction.\nstatic auto GetFormInfo(Context& context, SemIR::InstId inst_id) -> FormInfo {\n  auto inst = context.insts().Get(inst_id);\n\n  SemIR::ExprCategory category =\n      SemIR::GetExprCategory(context.sem_ir(), inst_id);\n  if (inst.type_id() == SemIR::ErrorInst::TypeId) {\n    // TODO: Should `GetExprCategory` do this?\n    category = SemIR::ExprCategory::Error;\n  }\n\n  FormInfo::Kind kind = FormInfo::Primitive;\n  if (category == SemIR::ExprCategory::Mixed) {\n    kind = GetDecomposedFormKindForType(context, inst.type_id());\n    CARBON_CHECK(kind != FormInfo::Primitive,\n                 \"Unexpected type {0} for mixed category\",\n                 context.types().GetAsInst(inst.type_id()));\n  }\n\n  return {.kind = kind,\n          .category = category,\n          .type_id = inst.type_id(),\n          .constant_id = context.constant_values().Get(inst_id),\n          .loc_id = SemIR::LocId(inst_id),\n          .inst_id = inst_id};\n}\n\n// Given a form, attempts to perform form decomposition, converting it from a\n// primitive form into a compound form if possible. Otherwise, returns the form\n// unchanged.\nstatic auto DecomposeForm(Context& context, FormInfo form) -> FormInfo {\n  if (form.kind == FormInfo::Primitive) {\n    form.kind = GetDecomposedFormKindForType(context, form.type_id);\n    // TODO: Should we replace a category of Initializing with\n    // EphemeralReference here to model temporary materialization if we\n    // performed decomposition?\n  }\n  return form;\n}\n\nusing FormVisitor = llvm::function_ref<auto(FormInfo)->void>;\n\n// Gets information about the forms of the instructions in a block.\nstatic auto VisitFormInfos(Context& context, SemIR::InstBlockId inst_block_id,\n                           FormVisitor visitor) -> void {\n  auto inst_ids = context.inst_blocks().Get(inst_block_id);\n  for (auto inst_id : inst_ids) {\n    visitor(GetFormInfo(context, inst_id));\n  }\n}\n\n// Given a tuple form, visits the forms of the elements.\nstatic auto VisitTupleElementForms(Context& context, FormInfo form,\n                                   FormVisitor visitor) -> void {\n  // If we have a tuple literal, directly grab the forms of its elements.\n  if (auto tuple_lit_inst =\n          context.insts().TryGetAsIfValid<SemIR::TupleLiteral>(form.inst_id)) {\n    VisitFormInfos(context, tuple_lit_inst->elements_id, visitor);\n    return;\n  }\n\n  // Otherwise, decompose the type and, if available, the constant value.\n  auto tuple_type = context.types().GetAs<SemIR::TupleType>(form.type_id);\n  auto element_type_inst_ids =\n      context.inst_blocks().Get(tuple_type.type_elements_id);\n\n  llvm::SmallVector<FormInfo> result;\n  result.reserve(element_type_inst_ids.size());\n\n  auto tuple_const_inst = context.insts().TryGetAsIfValid<SemIR::TupleValue>(\n      context.constant_values().GetInstIdIfValid(form.constant_id));\n  auto tuple_const_inst_ids =\n      tuple_const_inst\n          ? context.inst_blocks().Get(tuple_const_inst->elements_id)\n          : llvm::ArrayRef<SemIR::InstId>();\n\n  for (auto [type_inst_id, const_inst_id] :\n       llvm::zip_longest(element_type_inst_ids, tuple_const_inst_ids)) {\n    visitor({.kind = FormInfo::Primitive,\n             .category = form.category,\n             .type_id = context.types().GetTypeIdForTypeInstId(*type_inst_id),\n             .constant_id = const_inst_id\n                                ? context.constant_values().Get(*const_inst_id)\n                                : SemIR::ConstantId::NotConstant,\n             .loc_id = form.loc_id,\n             .inst_id = SemIR::InstId::None});\n  }\n}\n\n// Given a struct form, returns the forms of the elements.\nstatic auto VisitStructElementForms(Context& context, FormInfo form,\n                                    FormVisitor visitor) -> void {\n  // If we have a struct literal, directly grab the forms of its elements.\n  if (auto struct_lit_inst =\n          context.insts().TryGetAsIfValid<SemIR::StructLiteral>(form.inst_id)) {\n    VisitFormInfos(context, struct_lit_inst->elements_id, visitor);\n    return;\n  }\n\n  // Otherwise, decompose the type and, if available, the constant value.\n  auto struct_type = context.types().GetAs<SemIR::StructType>(form.type_id);\n  auto fields = context.struct_type_fields().Get(struct_type.fields_id);\n\n  llvm::SmallVector<FormInfo> result;\n  result.reserve(fields.size());\n\n  auto struct_const_inst = context.insts().TryGetAsIfValid<SemIR::StructValue>(\n      context.constant_values().GetInstIdIfValid(form.constant_id));\n  auto struct_const_inst_ids =\n      struct_const_inst\n          ? context.inst_blocks().Get(struct_const_inst->elements_id)\n          : llvm::ArrayRef<SemIR::InstId>();\n\n  for (auto [field, const_inst_id] :\n       llvm::zip_longest(fields, struct_const_inst_ids)) {\n    visitor(\n        {.kind = FormInfo::Primitive,\n         .category = form.category,\n         .type_id = context.types().GetTypeIdForTypeInstId(field->type_inst_id),\n         .constant_id = const_inst_id\n                            ? context.constant_values().Get(*const_inst_id)\n                            : SemIR::ConstantId::NotConstant,\n         .loc_id = form.loc_id,\n         .inst_id = SemIR::InstId::None});\n  }\n}\n\n// Invent a primitive Clang argument given the form of the corresponding Carbon\n// expression.\nstatic auto InventPrimitiveClangArg(Context& context, FormInfo form)\n    -> clang::Expr* {\n  clang::ExprValueKind value_kind;\n  switch (form.category) {\n    case SemIR::ExprCategory::Error:\n      // The argument error has already been diagnosed.\n      return nullptr;\n\n    case SemIR::ExprCategory::Pattern:\n      CARBON_FATAL(\"Passing a pattern as a function argument\");\n\n    case SemIR::ExprCategory::DurableRef:\n    case SemIR::ExprCategory::RefTagged:\n      value_kind = clang::ExprValueKind::VK_LValue;\n      break;\n\n    case SemIR::ExprCategory::EphemeralRef:\n      value_kind = clang::ExprValueKind::VK_XValue;\n      break;\n\n    case SemIR::ExprCategory::NotExpr:\n      // A call using this expression as an argument won't be valid, but we\n      // don't diagnose that until we convert the expression to the parameter\n      // type.\n      value_kind = clang::ExprValueKind::VK_PRValue;\n      break;\n\n    case SemIR::ExprCategory::Value:\n      value_kind = clang::ExprValueKind::VK_PRValue;\n      break;\n\n    case SemIR::ExprCategory::ReprInitializing:\n    case SemIR::ExprCategory::InPlaceInitializing:\n      value_kind = clang::ExprValueKind::VK_PRValue;\n      break;\n\n    case SemIR::ExprCategory::Mixed:\n    case SemIR::ExprCategory::Dependent:\n      CARBON_FATAL(\"Argument does not have primitive form\");\n  }\n\n  clang::QualType arg_cpp_type;\n\n  // Special case: if the argument is an integer literal, look at its value.\n  // TODO: Consider producing a `clang::IntegerLiteral` in this case instead, so\n  // that C++ overloads that behave differently for zero-valued int literals can\n  // recognize it.\n  if (context.types().Is<SemIR::IntLiteralType>(form.type_id)) {\n    IntId bit_width_id =\n        FindIntLiteralBitWidth(context, form.loc_id, form.constant_id);\n    if (bit_width_id != IntId::None) {\n      arg_cpp_type = context.ast_context().getIntTypeForBitwidth(\n          bit_width_id.AsValue(), true);\n    }\n  }\n\n  if (arg_cpp_type.isNull()) {\n    arg_cpp_type = MapToCppType(context, form.type_id);\n  }\n\n  if (arg_cpp_type.isNull()) {\n    CARBON_DIAGNOSTIC(CppCallArgTypeNotSupported, Error,\n                      \"call argument of type {0} is not supported\",\n                      SemIR::TypeId);\n    context.emitter().Emit(form.loc_id, CppCallArgTypeNotSupported,\n                           form.type_id);\n    return nullptr;\n  }\n\n  // Map a value expression to a const-qualified prvalue so that overload\n  // resolution doesn't think it's a suitable argument for a non-const-qualified\n  // object parameter or a `T&&` parameter. We can only do this for class\n  // prvalues, because non-class non-array prvalues can't be qualified in C++.\n  if (form.category == SemIR::ExprCategory::Value &&\n      arg_cpp_type->isRecordType()) {\n    arg_cpp_type = context.ast_context().getConstType(arg_cpp_type);\n  }\n\n  // TODO: Avoid heap allocating more of these on every call. Either cache them\n  // somewhere or put them on the stack.\n  return new (context.ast_context())\n      clang::OpaqueValueExpr(GetCppLocation(context, form.loc_id),\n                             arg_cpp_type.getNonReferenceType(), value_kind);\n}\n\n// Invent an initializer list Clang argument given the form of the corresponding\n// Carbon expression, which is a compound form. The initializers for the\n// elements are taken from the end of `results`.\nstatic auto InventCompoundClangArg(Context& context, FormInfo form,\n                                   llvm::SmallVectorImpl<clang::Expr*>& results)\n    -> clang::Expr* {\n  auto make_init_list = [&](llvm::ArrayRef<clang::Expr*> inits) {\n    // TODO: Compute the `(` and `)` locations for a tuple literal or the `{`\n    // and `}` locations for a struct literal.\n    auto compound_loc = GetCppLocation(context, form.loc_id);\n    auto lbrace_loc = compound_loc;\n    auto rbrace_loc = compound_loc;\n\n    auto* init_list = new (context.ast_context()) clang::InitListExpr(\n        context.ast_context(), lbrace_loc, inits, rbrace_loc);\n    init_list->setType(context.ast_context().VoidTy);\n    return init_list;\n  };\n\n  switch (form.kind) {\n    case FormInfo::Primitive:\n      CARBON_FATAL(\"Not a compound form\");\n\n    case FormInfo::Tuple: {\n      // For a tuple, form a non-designated init list containing the\n      // corresponding initializers.\n      auto num_elements = context.inst_blocks()\n                              .Get(context.types()\n                                       .GetAs<SemIR::TupleType>(form.type_id)\n                                       .type_elements_id)\n                              .size();\n      CARBON_CHECK(results.size() >= num_elements);\n\n      auto* init_list =\n          make_init_list(llvm::ArrayRef(results).take_back(num_elements));\n      results.truncate(results.size() - num_elements);\n      return init_list;\n    }\n\n    case FormInfo::Struct: {\n      // For a struct, form a designated initializer list, converting the struct\n      // field names into designator names.\n      auto fields = context.struct_type_fields().Get(\n          context.types().GetAs<SemIR::StructType>(form.type_id).fields_id);\n      llvm::SmallVector<clang::Expr*> field_inits;\n      field_inits.reserve(fields.size());\n\n      for (auto [field, init] : llvm::zip(\n               fields, llvm::ArrayRef(results).take_back(fields.size()))) {\n        auto loc = init->getExprLoc();\n        auto* field_name = GetClangIdentifierInfo(context, field.name_id);\n        if (!field_name) {\n          CARBON_DIAGNOSTIC(CppCallFieldNameNotSupported, Error,\n                            \"field name `{0}` cannot be mapped into C++\",\n                            SemIR::NameId);\n          context.emitter().Emit(form.loc_id, CppCallFieldNameNotSupported,\n                                 field.name_id);\n          return nullptr;\n        }\n\n        auto designator =\n            clang::DesignatedInitExpr::Designator::CreateFieldDesignator(\n                field_name, /*DotLoc=*/loc, /*FieldLoc=*/loc);\n        field_inits.push_back(clang::DesignatedInitExpr::Create(\n            context.ast_context(), designator, /*IndexExprs*/ {},\n            /*EqualOrColonLoc=*/loc, /*GNUSyntax=*/false, init));\n      }\n\n      results.truncate(results.size() - fields.size());\n\n      return make_init_list(field_inits);\n    }\n  }\n}\n\nauto InventClangArg(Context& context, SemIR::InstId arg_id) -> clang::Expr* {\n  enum Phase { Initial, AfterSubexpressions };\n  llvm::SmallVector<std::pair<FormInfo, Phase>> worklist = {\n      {GetFormInfo(context, arg_id), Initial}};\n  llvm::SmallVector<clang::Expr*> pending_results = {};\n\n  while (!worklist.empty()) {\n    auto [form, phase] = worklist.pop_back_val();\n\n    switch (phase) {\n      case Initial: {\n        form = DecomposeForm(context, form);\n        switch (form.kind) {\n          case FormInfo::Primitive: {\n            auto* expr = InventPrimitiveClangArg(context, form);\n            if (!expr) {\n              return nullptr;\n            }\n            pending_results.push_back(expr);\n            break;\n          }\n\n          case FormInfo::Tuple:\n          case FormInfo::Struct: {\n            worklist.push_back({form, AfterSubexpressions});\n            auto initial_size = worklist.size();\n            auto visitor = [&](FormInfo element) {\n              worklist.push_back({element, Initial});\n            };\n            if (form.kind == FormInfo::Tuple) {\n              VisitTupleElementForms(context, form, visitor);\n            } else {\n              VisitStructElementForms(context, form, visitor);\n            }\n            // Reverse the added elements so that we pop them in element order.\n            std::reverse(worklist.begin() + initial_size, worklist.end());\n            break;\n          }\n        }\n        break;\n      }\n\n      case AfterSubexpressions: {\n        auto* expr = InventCompoundClangArg(context, form, pending_results);\n        if (!expr) {\n          return nullptr;\n        }\n        pending_results.push_back(expr);\n        break;\n      }\n    }\n  }\n\n  CARBON_CHECK(pending_results.size() == 1);\n  return pending_results.back();\n}\n\nauto InventClangArgs(Context& context, llvm::ArrayRef<SemIR::InstId> arg_ids)\n    -> std::optional<llvm::SmallVector<clang::Expr*>> {\n  std::optional<llvm::SmallVector<clang::Expr*>> arg_exprs;\n  arg_exprs.emplace();\n  arg_exprs->reserve(arg_ids.size());\n  for (SemIR::InstId arg_id : arg_ids) {\n    auto* arg_expr = InventClangArg(context, arg_id);\n    if (!arg_expr) {\n      arg_exprs = std::nullopt;\n      return arg_exprs;\n    }\n    arg_exprs->push_back(arg_expr);\n  }\n  return arg_exprs;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/cpp/type_mapping.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CPP_TYPE_MAPPING_H_\n#define CARBON_TOOLCHAIN_CHECK_CPP_TYPE_MAPPING_H_\n\n#include \"clang/AST/Type.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Converts a Carbon type to a corresponding C++ type. This uses the default\n// type mapping, which is suitable for template arguments, typedefs, etc. but\n// may not be the right mapping to use in a function signature. Returns a null\n// type if there is no mapping.\nauto MapToCppType(Context& context, SemIR::TypeId type_id) -> clang::QualType;\n\n// Invents a Clang argument expression to use in overload resolution to\n// represent the given Carbon argument instruction.\nauto InventClangArg(Context& context, SemIR::InstId arg_id) -> clang::Expr*;\n\n// For each arg, invents a Clang argument expression to use in overload\n// resolution or argument dependent lookup (ADL) to represent the given Carbon\n// argument instructions. Returns std::nullopt if any arg failed.\nauto InventClangArgs(Context& context, llvm::ArrayRef<SemIR::InstId> arg_ids)\n    -> std::optional<llvm::SmallVector<clang::Expr*>>;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CPP_TYPE_MAPPING_H_\n"
  },
  {
    "path": "toolchain/check/custom_witness.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/custom_witness.h\"\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/function.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/impl.h\"\n#include \"toolchain/check/impl_lookup.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/sem_ir/builtin_function_kind.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Given a value whose type `IsFacetTypeOrError`, returns the corresponding\n// type.\nstatic auto GetFacetAsType(Context& context,\n                           SemIR::ConstantId facet_or_type_const_id)\n    -> SemIR::TypeId {\n  auto facet_or_type_id =\n      context.constant_values().GetInstId(facet_or_type_const_id);\n  auto type_type_id = context.insts().Get(facet_or_type_id).type_id();\n  CARBON_CHECK(context.types().IsFacetTypeOrError(type_type_id));\n\n  if (context.types().Is<SemIR::FacetType>(type_type_id)) {\n    // It's a facet; access its type.\n    facet_or_type_id = context.types().GetTypeInstId(\n        GetFacetAccessType(context, facet_or_type_id));\n  }\n  return context.types().GetTypeIdForTypeInstId(facet_or_type_id);\n}\n\n// Returns the body for `Destroy.Op`. This will return `None` if using the\n// builtin `NoOp` is appropriate.\n//\n// TODO: This is a placeholder still not actually destroying things, intended to\n// maintain mostly-consistent behavior with current logic while working. That\n// also means using `self`.\n// TODO: This mirrors `TypeCanDestroy` below, think about ways to share what's\n// handled.\nstatic auto MakeDestroyOpBody(Context& context, SemIR::LocId loc_id,\n                              SemIR::TypeId self_type_id)\n    -> SemIR::InstBlockId {\n  context.inst_block_stack().Push();\n  auto inst = context.types().GetAsInst(self_type_id);\n\n  while (auto class_type = inst.TryAs<SemIR::ClassType>()) {\n    // Switch to looking at the object representation.\n    auto class_info = context.classes().Get(class_type->class_id);\n    CARBON_CHECK(class_info.is_complete());\n    inst = context.types().GetAsInst(\n        class_info.GetObjectRepr(context.sem_ir(), class_type->specific_id));\n  }\n\n  CARBON_KIND_SWITCH(inst) {\n    case SemIR::ArrayType::Kind:\n    case SemIR::ConstType::Kind:\n    case SemIR::MaybeUnformedType::Kind:\n    case SemIR::PartialType::Kind:\n    case SemIR::StructType::Kind:\n    case SemIR::TupleType::Kind:\n      // TODO: Implement iterative destruction of types.\n      break;\n    case SemIR::BoolType::Kind:\n    case SemIR::FloatType::Kind:\n    case SemIR::IntType::Kind:\n    case SemIR::PointerType::Kind:\n      // For trivially destructible types, we don't generate anything, so that\n      // this can collapse to a noop implementation when possible.\n      break;\n    case SemIR::ErrorInst::Kind:\n      // Errors can't be destroyed, but we'll still try to generate calls for\n      // other members.\n      break;\n    default:\n      CARBON_FATAL(\"Unexpected type for destroy: {0}\", inst);\n  }\n\n  if (context.inst_block_stack().PeekCurrentBlockContents().empty()) {\n    context.inst_block_stack().PopAndDiscard();\n    return SemIR::InstBlockId::None;\n  }\n  AddInst(context, loc_id, SemIR::Return{});\n  return context.inst_block_stack().Pop();\n}\n\n// Returns a manufactured `Destroy.Op` function with the `self` parameter typed\n// to `self_type_id`.\nstatic auto MakeDestroyOpFunction(Context& context, SemIR::LocId loc_id,\n                                  SemIR::TypeId self_type_id,\n                                  SemIR::NameScopeId parent_scope_id)\n    -> SemIR::InstId {\n  auto name_id = context.core_identifiers().AddNameId(CoreIdentifier::Op);\n\n  auto [decl_id, function_id] =\n      MakeGeneratedFunctionDecl(context, loc_id,\n                                {.parent_scope_id = parent_scope_id,\n                                 .name_id = name_id,\n                                 .self_type_id = self_type_id});\n\n  auto& function = context.functions().Get(function_id);\n\n  auto body_id = MakeDestroyOpBody(context, loc_id, self_type_id);\n  if (body_id.has_value()) {\n    function.SetCoreWitness();\n    function.body_block_ids.push_back(body_id);\n  } else {\n    function.SetCoreWitness(SemIR::BuiltinFunctionKind::NoOp);\n  }\n\n  return decl_id;\n}\n\nstatic auto MakeCustomWitnessConstantInst(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::SpecificInterfaceId query_specific_interface_id,\n    SemIR::InstBlockId associated_entities_block_id) -> SemIR::InstId {\n  // The witness is a CustomWitness of the query interface with a table that\n  // contains each associated entity.\n  auto const_id = EvalOrAddInst<SemIR::CustomWitness>(\n      context, loc_id,\n      {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),\n       .elements_id = associated_entities_block_id,\n       .query_specific_interface_id = query_specific_interface_id});\n  return context.constant_values().GetInstId(const_id);\n}\n\nstruct TypesForSelfFacet {\n  // A FacetType that contains only the query interface.\n  SemIR::TypeId facet_type_for_query_specific_interface;\n  // The query self as a type, which involves a conversion if it was a facet.\n  SemIR::TypeId query_self_as_type_id;\n};\n\nstatic auto GetTypesForSelfFacet(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::ConstantId query_self_const_id,\n    SemIR::SpecificInterfaceId query_specific_interface_id)\n    -> TypesForSelfFacet {\n  const auto query_specific_interface =\n      context.specific_interfaces().Get(query_specific_interface_id);\n\n  // The Self facet will have type FacetType, for the query interface.\n  auto facet_type_for_query_specific_interface =\n      context.types().GetTypeIdForTypeConstantId(\n          EvalOrAddInst<SemIR::FacetType>(\n              context, loc_id,\n              FacetTypeFromInterface(context,\n                                     query_specific_interface.interface_id,\n                                     query_specific_interface.specific_id)));\n  // The Self facet needs to point to a type value. If it's not one already,\n  // convert to type.\n  auto query_self_as_type_id = GetFacetAsType(context, query_self_const_id);\n  return {facet_type_for_query_specific_interface, query_self_as_type_id};\n}\n\n// Build a new facet from the query self, using a CustomWitness for the query\n// interface with an entry for each associated entity so far.\nstatic auto MakeSelfFacetWithCustomWitness(\n    Context& context, SemIR::LocId loc_id, TypesForSelfFacet query_types,\n    SemIR::SpecificInterfaceId query_specific_interface_id,\n    SemIR::InstBlockId associated_entities_block_id) -> SemIR::ConstantId {\n  // We are building a facet value for a single interface, so the witness block\n  // is a single witness for that interface.\n  auto witnesses_block_id =\n      context.inst_blocks().Add({MakeCustomWitnessConstantInst(\n          context, loc_id, query_specific_interface_id,\n          associated_entities_block_id)});\n\n  return EvalOrAddInst<SemIR::FacetValue>(\n      context, loc_id,\n      {.type_id = query_types.facet_type_for_query_specific_interface,\n       .type_inst_id =\n           context.types().GetTypeInstId(query_types.query_self_as_type_id),\n       .witnesses_block_id = witnesses_block_id});\n}\n\nauto BuildCustomWitness(Context& context, SemIR::LocId loc_id,\n                        SemIR::ConstantId query_self_const_id,\n                        SemIR::SpecificInterfaceId query_specific_interface_id,\n                        llvm::ArrayRef<SemIR::InstId> values) -> SemIR::InstId {\n  const auto query_specific_interface =\n      context.specific_interfaces().Get(query_specific_interface_id);\n  const auto& interface =\n      context.interfaces().Get(query_specific_interface.interface_id);\n  auto assoc_entities =\n      context.inst_blocks().GetOrEmpty(interface.associated_entities_id);\n  if (assoc_entities.size() != values.size()) {\n    context.TODO(loc_id, (\"Unsupported definition of interface \" +\n                          context.names().GetFormatted(interface.name_id))\n                             .str());\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto query_types_for_self_facet = GetTypesForSelfFacet(\n      context, loc_id, query_self_const_id, query_specific_interface_id);\n\n  // The values that will go in the witness table.\n  llvm::SmallVector<SemIR::InstId> entries;\n\n  // Fill in the witness table.\n  for (const auto& [assoc_entity_id, value_id] :\n       llvm::zip_equal(assoc_entities, values)) {\n    LoadImportRef(context, assoc_entity_id);\n\n    // Build a witness with the current contents of the witness table. This will\n    // grow as we progress through the impl. In theory this will build O(n^2)\n    // table entries, but in practice n <= 2, so that's OK.\n    //\n    // This is necessary because later associated entities may refer to earlier\n    // associated entities in their signatures. In particular, an associated\n    // result type may be used as the return type of an associated function.\n    auto self_facet = MakeSelfFacetWithCustomWitness(\n        context, loc_id, query_types_for_self_facet,\n        query_specific_interface_id, context.inst_blocks().Add(entries));\n    auto interface_with_self_specific_id = MakeSpecificWithInnerSelf(\n        context, loc_id, interface.generic_id, interface.generic_with_self_id,\n        query_specific_interface.specific_id, self_facet);\n\n    auto decl_id =\n        context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(\n            context.sem_ir(), interface_with_self_specific_id,\n            assoc_entity_id));\n    CARBON_CHECK(decl_id.has_value(), \"Non-constant associated entity\");\n    auto decl = context.insts().Get(decl_id);\n    CARBON_KIND_SWITCH(decl) {\n      case CARBON_KIND(SemIR::StructValue struct_value): {\n        if (struct_value.type_id == SemIR::ErrorInst::TypeId) {\n          return SemIR::ErrorInst::InstId;\n        }\n        // TODO: If a thunk is needed, this will build a different value each\n        // time it's called, so we won't properly deduplicate repeated\n        // witnesses.\n        entries.push_back(CheckAssociatedFunctionImplementation(\n            context,\n            context.types().GetAs<SemIR::FunctionType>(struct_value.type_id),\n            query_specific_interface.specific_id, value_id,\n            /*defer_thunk_definition=*/false));\n        break;\n      }\n      case SemIR::AssociatedConstantDecl::Kind: {\n        context.TODO(loc_id,\n                     \"Associated constant in interface with synthesized impl\");\n        return SemIR::ErrorInst::InstId;\n      }\n      default:\n        CARBON_CHECK(decl_id == SemIR::ErrorInst::InstId,\n                     \"Unexpected kind of associated entity {0}\", decl);\n        return SemIR::ErrorInst::InstId;\n    }\n  }\n\n  // TODO: Consider building one witness after all associated constants, and\n  // then a second after all associated functions, rather than building one in\n  // each `StructValue`. Right now the code is written assuming at most one\n  // function, though this CHECK can be removed as a temporary workaround.\n  CARBON_CHECK(entries.size() <= 1,\n               \"TODO: Support multiple associated functions\");\n\n  return MakeCustomWitnessConstantInst(context, loc_id,\n                                       query_specific_interface_id,\n                                       context.inst_blocks().Add(entries));\n}\n\nauto GetCoreInterface(Context& context, SemIR::InterfaceId interface_id)\n    -> CoreInterface {\n  const auto& interface = context.interfaces().Get(interface_id);\n  if (!context.name_scopes().IsCorePackage(interface.parent_scope_id) ||\n      !interface.name_id.AsIdentifierId().has_value()) {\n    return CoreInterface::Unknown;\n  }\n\n  constexpr auto CoreIdentifiersToInterfaces = std::array{\n      std::pair{CoreIdentifier::Copy, CoreInterface::Copy},\n      std::pair{CoreIdentifier::Destroy, CoreInterface::Destroy},\n      std::pair{CoreIdentifier::IntFitsIn, CoreInterface::IntFitsIn},\n      std::pair{CoreIdentifier::CppUnsafeDeref, CoreInterface::CppUnsafeDeref}};\n\n  for (auto [core_identifier, core_interface] : CoreIdentifiersToInterfaces) {\n    if (interface.name_id ==\n        context.core_identifiers().AddNameId(core_identifier)) {\n      return core_interface;\n    }\n  }\n  return CoreInterface::Unknown;\n}\n\n// Returns true if the `Self` should impl `Destroy`.\nstatic auto TypeCanDestroy(Context& context,\n                           SemIR::ConstantId query_self_const_id,\n                           SemIR::InterfaceId destroy_interface_id) -> bool {\n  auto inst = context.insts().Get(context.constant_values().GetInstId(\n      GetCanonicalFacetOrTypeValue(context, query_self_const_id)));\n\n  // For facet values, look if the FacetType provides the same.\n  if (auto facet_type =\n          context.types().TryGetAs<SemIR::FacetType>(inst.type_id())) {\n    const auto& info = context.facet_types().Get(facet_type->facet_type_id);\n    for (auto interface : info.extend_constraints) {\n      if (interface.interface_id == destroy_interface_id) {\n        return true;\n      }\n    }\n  }\n\n  CARBON_KIND_SWITCH(inst) {\n    case CARBON_KIND(SemIR::ClassType class_type): {\n      auto class_info = context.classes().Get(class_type.class_id);\n      // Incomplete and abstract classes can't be destroyed.\n      if (!class_info.is_complete() ||\n          class_info.inheritance_kind ==\n              SemIR::Class::InheritanceKind::Abstract) {\n        return false;\n      }\n\n      // `LookupCppImpl` handles C++ types.\n      if (context.name_scopes().Get(class_info.scope_id).is_cpp_scope()) {\n        return false;\n      }\n\n      // TODO: Return false if the object repr doesn't impl `Destroy`.\n      return true;\n    }\n    case SemIR::ArrayType::Kind:\n    case SemIR::ConstType::Kind:\n    case SemIR::MaybeUnformedType::Kind:\n    case SemIR::PartialType::Kind:\n    case SemIR::StructType::Kind:\n    case SemIR::TupleType::Kind:\n      // TODO: Return false for types that indirectly reference a type that\n      // doesn't impl `Destroy`.\n      return true;\n    case SemIR::BoolType::Kind:\n    case SemIR::FloatType::Kind:\n    case SemIR::IntType::Kind:\n    case SemIR::PointerType::Kind:\n      // Trivially destructible.\n      return true;\n    default:\n      return false;\n  }\n}\n\nstatic auto MakeDestroyWitness(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::ConstantId query_self_const_id,\n    SemIR::SpecificInterfaceId query_specific_interface_id)\n    -> std::optional<SemIR::InstId> {\n  auto query_specific_interface =\n      context.specific_interfaces().Get(query_specific_interface_id);\n\n  if (!TypeCanDestroy(context, query_self_const_id,\n                      query_specific_interface.interface_id)) {\n    return std::nullopt;\n  }\n\n  if (query_self_const_id.is_symbolic()) {\n    return SemIR::InstId::None;\n  }\n\n  // Mark functions with the interface's scope as a hint to mangling. This does\n  // not add them to the scope.\n  auto parent_scope_id = context.interfaces()\n                             .Get(query_specific_interface.interface_id)\n                             .scope_without_self_id;\n\n  auto self_type_id = GetFacetAsType(context, query_self_const_id);\n  auto op_id =\n      MakeDestroyOpFunction(context, loc_id, self_type_id, parent_scope_id);\n  return BuildCustomWitness(context, loc_id, query_self_const_id,\n                            query_specific_interface_id, {op_id});\n}\n\nstatic auto MakeIntFitsInWitness(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::ConstantId query_self_const_id,\n    SemIR::SpecificInterfaceId query_specific_interface_id)\n    -> std::optional<SemIR::InstId> {\n  auto query_specific_interface =\n      context.specific_interfaces().Get(query_specific_interface_id);\n\n  auto args_id = query_specific_interface.specific_id;\n  if (!args_id.has_value()) {\n    return std::nullopt;\n  }\n  auto args_block_id = context.specifics().Get(args_id).args_id;\n  auto args_block = context.inst_blocks().Get(args_block_id);\n  if (args_block.size() != 1) {\n    return std::nullopt;\n  }\n\n  auto dest_const_id = context.constant_values().Get(args_block[0]);\n  if (!dest_const_id.is_constant()) {\n    return std::nullopt;\n  }\n\n  auto src_type_id = GetFacetAsType(context, query_self_const_id);\n  auto dest_type_id = GetFacetAsType(context, dest_const_id);\n\n  auto context_fn = [](DiagnosticContextBuilder& /*builder*/) -> void {};\n  if (!RequireCompleteType(context, src_type_id, loc_id, context_fn) ||\n      !RequireCompleteType(context, dest_type_id, loc_id, context_fn)) {\n    return std::nullopt;\n  }\n\n  auto src_info = context.types().TryGetIntTypeInfo(src_type_id);\n  auto dest_info = context.types().TryGetIntTypeInfo(dest_type_id);\n\n  if (!src_info || !dest_info) {\n    return std::nullopt;\n  }\n\n  // If the bit width is unknown (e.g., due to symbolic evaluation), we cannot\n  // determine whether it fits yet.\n  if (src_info->bit_width == IntId::None ||\n      dest_info->bit_width == IntId::None) {\n    return std::nullopt;\n  }\n\n  const auto& src_width = context.ints().Get(src_info->bit_width);\n  const auto& dest_width = context.ints().Get(dest_info->bit_width);\n\n  bool fits = false;\n  if (src_info->is_signed && !dest_info->is_signed) {\n    // Signed -> unsigned: would truncate the sign bit.\n    fits = false;\n  } else if (src_info->is_signed == dest_info->is_signed) {\n    // Signed -> signed or unsigned -> unsigned: allow widening or preserving\n    // width.\n    fits = src_width.sle(dest_width);\n  } else {\n    // Unsigned -> signed: strict widening required.\n    fits = src_width.slt(dest_width);\n  }\n\n  if (!fits) {\n    return std::nullopt;\n  }\n\n  return BuildCustomWitness(context, loc_id, query_self_const_id,\n                            query_specific_interface_id, {});\n}\n\nauto LookupCustomWitness(Context& context, SemIR::LocId loc_id,\n                         CoreInterface core_interface,\n                         SemIR::ConstantId query_self_const_id,\n                         SemIR::SpecificInterfaceId query_specific_interface_id)\n    -> std::optional<SemIR::InstId> {\n  switch (core_interface) {\n    case CoreInterface::Destroy:\n      return MakeDestroyWitness(context, loc_id, query_self_const_id,\n                                query_specific_interface_id);\n    case CoreInterface::IntFitsIn:\n      return MakeIntFitsInWitness(context, loc_id, query_self_const_id,\n                                  query_specific_interface_id);\n    case CoreInterface::CppUnsafeDeref:\n    case CoreInterface::Copy:\n    case CoreInterface::Unknown:\n      // TODO: Handle more interfaces, particularly copy, move, and conversion.\n      return std::nullopt;\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/custom_witness.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_CUSTOM_WITNESS_H_\n#define CARBON_TOOLCHAIN_CHECK_CUSTOM_WITNESS_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Builds a witness that the given type implements the given interface,\n// populating it with the specified set of values. Returns a corresponding\n// lookup result. Produces a diagnostic and returns `None` if the specified\n// values aren't suitable for the interface.\nauto BuildCustomWitness(Context& context, SemIR::LocId loc_id,\n                        SemIR::ConstantId query_self_const_id,\n                        SemIR::SpecificInterfaceId query_specific_interface_id,\n                        llvm::ArrayRef<SemIR::InstId> values) -> SemIR::InstId;\n\n// Significant interfaces in `Core` which correspond to language features and\n// can have custom witnesses.\nenum class CoreInterface {\n  Copy,\n  Destroy,\n  IntFitsIn,\n  CppUnsafeDeref,\n\n  Unknown,\n};\n\n// Given an interface, returns the corresponding enum if it's covered by\n// `CoreInterface`, or `Unknown` if it's some other interface.\nauto GetCoreInterface(Context& context, SemIR::InterfaceId interface_id)\n    -> CoreInterface;\n\n// Returns a witness for a `CoreInterface` `CustomWitness`. A return value of\n// `None` indicates a non-final witness should be produced, while `std::nullopt`\n// indicates the query is final and no witness can be produced.\nauto LookupCustomWitness(Context& context, SemIR::LocId loc_id,\n                         CoreInterface core_interface,\n                         SemIR::ConstantId query_self_const_id,\n                         SemIR::SpecificInterfaceId query_specific_interface_id)\n    -> std::optional<SemIR::InstId>;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_CUSTOM_WITNESS_H_\n"
  },
  {
    "path": "toolchain/check/decl_introducer_state.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_DECL_INTRODUCER_STATE_H_\n#define CARBON_TOOLCHAIN_CHECK_DECL_INTRODUCER_STATE_H_\n\n#include \"toolchain/check/keyword_modifier_set.h\"\n#include \"toolchain/lex/token_kind.h\"\n#include \"toolchain/parse/node_ids.h\"\n\nnamespace Carbon::Check {\n\n// State stored for each declaration we are introducing: the kind of\n// declaration and the keyword modifiers that apply to that declaration\n// introducer.\nstruct DeclIntroducerState {\n  auto modifier_node_id(ModifierOrder order) const -> Parse::NodeId {\n    return ordered_modifier_node_ids[static_cast<int8_t>(order)];\n  }\n  auto set_modifier_node_id(ModifierOrder order, Parse::NodeId node_id)\n      -> void {\n    ordered_modifier_node_ids[static_cast<int8_t>(order)] = node_id;\n  }\n\n  // The token kind of the introducer.\n  Lex::TokenKind kind;\n\n  // Nodes of modifiers on this declaration, in expected order. `None` if no\n  // modifier of that kind is present.\n  Parse::NodeId\n      ordered_modifier_node_ids[static_cast<int8_t>(ModifierOrder::Last) + 1] =\n          {Parse::NodeId::None, Parse::NodeId::None, Parse::NodeId::None,\n           Parse::NodeId::None, Parse::NodeId::None};\n\n  // Invariant: contains just the modifiers represented by `saw_*_modifier`.\n  KeywordModifierSet modifier_set = KeywordModifierSet();\n\n  // If there's an `extern library` in use, the library name.\n  SemIR::LibraryNameId extern_library = SemIR::LibraryNameId::None;\n};\n\n// Stack of `DeclIntroducerState` values, representing all the declaration\n// introducers we are currently nested within. Commonly size 0 or 1, as nested\n// introducers are rare.\nclass DeclIntroducerStateStack {\n private:\n  // Returns true for introducer tokens. Supports Push/Pop `requires`.\n  template <Lex::TokenKind::RawEnumType Kind>\n  static constexpr auto IsDeclIntroducer() -> bool {\n    switch (Kind) {\n#define CARBON_TOKEN(...)\n#define CARBON_DECL_INTRODUCER_TOKEN(Name, ...) case Lex::TokenKind::Name:\n#include \"toolchain/lex/token_kind.def\"\n      return true;\n      default:\n        return false;\n    }\n  }\n\n public:\n  // Begins a declaration introducer `Kind`.\n  template <Lex::TokenKind::RawEnumType Kind>\n    requires(IsDeclIntroducer<Kind>())\n  auto Push() -> void {\n    stack_.push_back({.kind = Lex::TokenKind::Make(Kind)});\n  }\n\n  // Gets the state of declaration at the top of the stack -- the innermost\n  // declaration currently being processed.\n  auto innermost() -> DeclIntroducerState& { return stack_.back(); }\n\n  // Finishes a declaration introducer `Kind` and returns the produced state.\n  template <Lex::TokenKind::RawEnumType Kind>\n    requires(IsDeclIntroducer<Kind>())\n  auto Pop() -> DeclIntroducerState {\n    CARBON_CHECK(stack_.back().kind == Kind, \"Found: {0} expected: {1}\",\n                 stack_.back().kind, Lex::TokenKind::Make(Kind));\n    return stack_.pop_back_val();\n  }\n\n  // Runs verification that the processing cleanly finished.\n  auto VerifyOnFinish() const -> void {\n    CARBON_CHECK(stack_.empty(),\n                 \"decl_introduce_state_stack still has {0} entries\",\n                 stack_.size());\n  }\n\n private:\n  llvm::SmallVector<DeclIntroducerState> stack_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_DECL_INTRODUCER_STATE_H_\n"
  },
  {
    "path": "toolchain/check/decl_name_stack.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/decl_name_stack.h\"\n\n#include <utility>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/merge.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/check/unused.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto DeclNameStack::NameContext::prev_inst_id() const -> SemIR::InstId {\n  switch (state) {\n    case NameContext::State::Error:\n      // The name is malformed and a diagnostic has already been emitted.\n      return SemIR::InstId::None;\n\n    case NameContext::State::Empty:\n      CARBON_FATAL(\n          \"Name is missing, not expected to call existing_inst_id (but that \"\n          \"may change based on error handling).\");\n\n    case NameContext::State::Resolved:\n      return resolved_inst_id;\n\n    case NameContext::State::Unresolved:\n      return SemIR::InstId::None;\n\n    case NameContext::State::Poisoned:\n      CARBON_FATAL(\"Poisoned state should not call prev_inst_id()\");\n\n    case NameContext::State::Finished:\n      CARBON_FATAL(\"Finished state should only be used internally\");\n  }\n}\n\nauto DeclNameStack::MakeEmptyNameContext() -> NameContext {\n  return NameContext{\n      .initial_scope_index = context_->scope_stack().PeekIndex(),\n      .parent_scope_id = context_->scope_stack().PeekNameScopeId()};\n}\n\nauto DeclNameStack::MakeUnqualifiedName(SemIR::LocId loc_id,\n                                        SemIR::NameId name_id) -> NameContext {\n  NameContext context = MakeEmptyNameContext();\n  ApplyAndLookupName(context, loc_id, name_id);\n  return context;\n}\n\nauto DeclNameStack::PushScopeAndStartName() -> void {\n  decl_name_stack_.push_back(MakeEmptyNameContext());\n\n  // Create a scope for any parameters introduced in this name.\n  context_->scope_stack().PushForDeclName();\n}\n\nauto DeclNameStack::FinishName(const NameComponent& name) -> NameContext {\n  CARBON_CHECK(decl_name_stack_.back().state != NameContext::State::Finished,\n               \"Finished name twice\");\n\n  ApplyAndLookupName(decl_name_stack_.back(), name.name_loc_id, name.name_id);\n\n  NameContext result = decl_name_stack_.back();\n  decl_name_stack_.back().state = NameContext::State::Finished;\n  return result;\n}\n\nauto DeclNameStack::FinishImplName() -> NameContext {\n  CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Empty,\n               \"Impl has a name\");\n\n  NameContext result = decl_name_stack_.back();\n  decl_name_stack_.back().state = NameContext::State::Finished;\n  return result;\n}\n\nauto DeclNameStack::PopScope(bool check_unused) -> void {\n  CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Finished,\n               \"Missing call to FinishName before PopScope\");\n  context_->scope_stack().PopTo(decl_name_stack_.back().initial_scope_index,\n                                check_unused);\n  decl_name_stack_.pop_back();\n}\n\nauto DeclNameStack::Suspend() -> SuspendedName {\n  CARBON_CHECK(decl_name_stack_.back().state == NameContext::State::Finished,\n               \"Missing call to FinishName before Suspend\");\n  SuspendedName result = {.name_context = decl_name_stack_.pop_back_val(),\n                          .scopes = {}};\n  auto scope_index = result.name_context.initial_scope_index;\n  auto& scope_stack = context_->scope_stack();\n  while (scope_stack.PeekIndex() > scope_index) {\n    result.scopes.push_back(scope_stack.Suspend());\n  }\n  CARBON_CHECK(scope_stack.PeekIndex() == scope_index,\n               \"Scope index {0} does not enclose the current scope {1}\",\n               scope_index, scope_stack.PeekIndex());\n  return result;\n}\n\nauto DeclNameStack::Restore(SuspendedName&& sus) -> void {\n  // The parent state must be the same when a name is restored.\n  CARBON_CHECK(context_->scope_stack().PeekIndex() ==\n                   sus.name_context.initial_scope_index,\n               \"Name restored at the wrong position in the name stack.\");\n\n  // clang-tidy warns that the `std::move` below has no effect. While that's\n  // true, this `move` defends against `NameContext` growing more state later.\n  // NOLINTNEXTLINE(performance-move-const-arg)\n  decl_name_stack_.push_back(std::move(sus.name_context));\n  for (auto& suspended_scope : llvm::reverse(sus.scopes)) {\n    // Reattempt to resolve the definition of the specific. The generic might\n    // have been defined after we suspended this scope.\n    if (suspended_scope.entry.specific_id.has_value()) {\n      ResolveSpecificDefinition(*context_, sus.name_context.loc_id,\n                                suspended_scope.entry.specific_id);\n    }\n\n    context_->scope_stack().Restore(std::move(suspended_scope));\n  }\n}\n\nauto DeclNameStack::AddName(NameContext name_context, SemIR::InstId target_id,\n                            SemIR::AccessKind access_kind) -> void {\n  switch (name_context.state) {\n    case NameContext::State::Error:\n      return;\n\n    case NameContext::State::Unresolved:\n      if (!name_context.parent_scope_id.has_value()) {\n        AddNameToLookup(*context_, name_context.name_id, target_id,\n                        name_context.initial_scope_index);\n      } else {\n        auto& name_scope =\n            context_->name_scopes().Get(name_context.parent_scope_id);\n        if (name_context.has_qualifiers) {\n          auto inst = context_->insts().Get(name_scope.inst_id());\n          if (!inst.Is<SemIR::Namespace>()) {\n            // TODO: Point at the declaration for the scoped entity.\n            CARBON_DIAGNOSTIC(\n                QualifiedDeclOutsideScopeEntity, Error,\n                \"out-of-line declaration requires a declaration in \"\n                \"scoped entity\");\n            context_->emitter().Emit(name_context.loc_id,\n                                     QualifiedDeclOutsideScopeEntity);\n          }\n        }\n\n        // Exports are only tracked when the declaration is at the file-level\n        // scope. Otherwise, it's in some other entity, such as a class.\n        if (access_kind == SemIR::AccessKind::Public &&\n            name_context.initial_scope_index == ScopeIndex::Package) {\n          context_->exports().push_back(target_id);\n        }\n\n        name_scope.AddRequired({.name_id = name_context.name_id,\n                                .result = SemIR::ScopeLookupResult::MakeFound(\n                                    target_id, access_kind)});\n      }\n      break;\n\n    default:\n      CARBON_FATAL(\"Should not be calling AddName\");\n      break;\n  }\n}\n\nauto DeclNameStack::AddNameOrDiagnose(NameContext name_context,\n                                      SemIR::InstId target_id,\n                                      SemIR::AccessKind access_kind) -> void {\n  if (name_context.state == DeclNameStack::NameContext::State::Poisoned) {\n    DiagnosePoisonedName(*context_, name_context.name_id_for_new_inst(),\n                         name_context.poisoning_loc_id, name_context.loc_id);\n  } else if (auto id = name_context.prev_inst_id(); id.has_value()) {\n    DiagnoseDuplicateName(*context_, name_context.name_id, name_context.loc_id,\n                          SemIR::LocId(id));\n  } else {\n    AddName(name_context, target_id, access_kind);\n  }\n}\n\nauto DeclNameStack::LookupOrAddName(NameContext name_context,\n                                    SemIR::InstId target_id,\n                                    SemIR::AccessKind access_kind)\n    -> SemIR::ScopeLookupResult {\n  if (name_context.state == NameContext::State::Poisoned) {\n    return SemIR::ScopeLookupResult::MakePoisoned(\n        name_context.poisoning_loc_id);\n  }\n  if (auto id = name_context.prev_inst_id(); id.has_value()) {\n    return SemIR::ScopeLookupResult::MakeFound(id, access_kind);\n  }\n  AddName(name_context, target_id, access_kind);\n  return SemIR::ScopeLookupResult::MakeNotFound();\n}\n\n// Get the name scope and generic to use for associated entities in `scope`.\n// Typically this is None, in which case the input scope should be used, but\n// some entities have a separate generic and inner scope used for associated\n// entities.\nstatic auto GetAssociatedEntityScope(Context& context,\n                                     const SemIR::NameScope& scope)\n    -> std::pair<SemIR::NameScopeId, SemIR::GenericId> {\n  auto scope_inst = context.insts().Get(scope.inst_id());\n  CARBON_KIND_SWITCH(scope_inst) {\n    case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {\n      const auto& interface =\n          context.interfaces().Get(interface_decl.interface_id);\n      return {interface.scope_with_self_id, interface.generic_with_self_id};\n    }\n    case CARBON_KIND(SemIR::InterfaceWithSelfDecl _): {\n      CARBON_FATAL(\"Expected InterfaceDecl as qualifier scope\");\n    }\n    case CARBON_KIND(SemIR::NamedConstraintDecl _): {\n      // ResolveAsScope() does not allow named constraints as a scope qualifier.\n      CARBON_FATAL(\n          \"Did not expect to find named constraint as scope qualifier\");\n    }\n    case CARBON_KIND(SemIR::NamedConstraintWithSelfDecl _): {\n      CARBON_FATAL(\"Expected NamedConstraintDecl as qualifier scope\");\n    }\n    default:\n      return {SemIR::NameScopeId::None, SemIR::GenericId::None};\n  }\n}\n\n// Push a scope corresponding to a name qualifier. For example, for\n// `fn Class(T:! type).F(n: i32)` we will push the scope for `Class(T:! type)`\n// between the scope containing the declaration of `T` and the scope\n// containing the declaration of `n`.\n//\n// Returns the NameScopeId to use as the parent scope of the next name.\nstatic auto PushNameQualifierScope(Context& context, SemIR::LocId loc_id,\n                                   SemIR::NameScopeId scope_id,\n                                   SemIR::GenericId generic_id,\n                                   bool has_error = false)\n    -> SemIR::NameScopeId {\n  // If the qualifier has no parameters, we don't need to keep around a\n  // parameter scope.\n  context.scope_stack().PopIfEmpty(/*check_unused=*/true);\n\n  auto self_specific_id = SemIR::SpecificId::None;\n  if (generic_id.has_value()) {\n    self_specific_id = context.generics().GetSelfSpecific(generic_id);\n    // When declaring a member of a generic, resolve the self specific.\n    ResolveSpecificDefinition(context, loc_id, self_specific_id);\n  }\n\n  // Close the generic stack scope and open a new one for whatever comes after\n  // the qualifier. As this is a qualifier it must not be the initial\n  // declaration of the entity, so we treat it as a redeclaration.\n  FinishGenericRedecl(context, generic_id);\n  // What follows the qualifier will be a declaration. The signature of an\n  // entity is also a declaration even if it is followed by curly braces\n  // providing the definition.\n  StartGenericDecl(context);\n\n  const auto& scope = context.name_scopes().Get(scope_id);\n  context.scope_stack().PushForEntity(scope.inst_id(), scope_id,\n                                      self_specific_id, has_error);\n\n  auto [assoc_entity_scope_id, assoc_entity_generic_id] =\n      GetAssociatedEntityScope(context, scope);\n\n  if (assoc_entity_scope_id.has_value()) {\n    const auto& assoc_entity_scope =\n        context.name_scopes().Get(assoc_entity_scope_id);\n    // InterfaceDecl is the only inst that can be a scope qualifier and that has\n    // an associated entity scope, the InterfaceWithSelfDecl.\n    auto interface_decl = context.insts().GetAs<SemIR::InterfaceWithSelfDecl>(\n        assoc_entity_scope.inst_id());\n    auto& interface = context.interfaces().Get(interface_decl.interface_id);\n    // An interface also introduces its 'Self' parameter into the associated\n    // entity scope, despite it not being redeclared as part of the qualifier.\n    context.scope_stack().AddCompileTimeBinding();\n    context.scope_stack().PushCompileTimeBinding(interface.self_param_id);\n    // Move into the interface-with-self scope.\n    context.scope_stack().PushForEntity(\n        assoc_entity_scope.inst_id(), assoc_entity_scope_id,\n        context.generics().GetSelfSpecific(assoc_entity_generic_id), has_error);\n  }\n\n  // Enter a parameter scope in case the qualified name itself has parameters.\n  context.scope_stack().PushForSameRegion();\n\n  return assoc_entity_scope_id.has_value() ? assoc_entity_scope_id : scope_id;\n}\n\nauto DeclNameStack::ApplyNameQualifier(const NameComponent& name) -> void {\n  auto& name_context = decl_name_stack_.back();\n  ApplyAndLookupName(name_context, name.name_loc_id, name.name_id);\n  name_context.has_qualifiers = true;\n\n  // Resolve the qualifier as a scope and enter the new scope.\n  auto [scope_id, generic_id] = ResolveAsScope(name_context, name);\n  if (scope_id.has_value()) {\n    name_context.parent_scope_id = PushNameQualifierScope(\n        *context_, name_context.loc_id, scope_id, generic_id,\n        context_->name_scopes().Get(scope_id).has_error());\n  } else {\n    name_context.state = NameContext::State::Error;\n  }\n}\n\nauto DeclNameStack::ApplyAndLookupName(NameContext& name_context,\n                                       SemIR::LocId loc_id,\n                                       SemIR::NameId name_id) -> void {\n  // Update the final name component.\n  name_context.loc_id = loc_id;\n  name_context.name_id = name_id;\n\n  // Don't perform any more lookups after we hit an error. We still track the\n  // final name, though.\n  if (name_context.state == NameContext::State::Error) {\n    return;\n  }\n\n  // For identifier nodes, we need to perform a lookup on the identifier.\n  auto lookup_result = LookupNameInDecl(*context_, name_context.loc_id, name_id,\n                                        name_context.parent_scope_id,\n                                        name_context.initial_scope_index);\n  if (lookup_result.is_poisoned()) {\n    name_context.poisoning_loc_id = lookup_result.poisoning_loc_id();\n    name_context.state = NameContext::State::Poisoned;\n  } else if (!lookup_result.is_found()) {\n    // Invalid indicates an unresolved name. Store it and return.\n    name_context.state = NameContext::State::Unresolved;\n  } else {\n    // Store the resolved instruction and continue for the target scope\n    // update.\n    name_context.resolved_inst_id = lookup_result.target_inst_id();\n    name_context.state = NameContext::State::Resolved;\n  }\n}\n\n// Checks and returns whether name_context, which is used as a name qualifier,\n// was successfully resolved. Issues a suitable diagnostic if not.\nstatic auto CheckQualifierIsResolved(\n    Context& context, const DeclNameStack::NameContext& name_context) -> bool {\n  switch (name_context.state) {\n    case DeclNameStack::NameContext::State::Empty:\n      CARBON_FATAL(\"No qualifier to resolve\");\n\n    case DeclNameStack::NameContext::State::Resolved:\n      return true;\n\n    case DeclNameStack::NameContext::State::Poisoned:\n    case DeclNameStack::NameContext::State::Unresolved:\n      // Because more qualifiers were found, we diagnose that the earlier\n      // qualifier failed to resolve.\n      DiagnoseNameNotFound(context, name_context.loc_id, name_context.name_id);\n      return false;\n\n    case DeclNameStack::NameContext::State::Finished:\n      CARBON_FATAL(\"Added a qualifier after calling FinishName\");\n\n    case DeclNameStack::NameContext::State::Error:\n      // Already in an error state, so return without examining.\n      return false;\n  }\n}\n\n// Diagnose that a qualified declaration name specifies an incomplete class as\n// its scope.\nstatic auto DiagnoseQualifiedDeclInIncompleteClassScope(Context& context,\n                                                        SemIR::LocId loc_id,\n                                                        SemIR::ClassId class_id)\n    -> void {\n  Diagnostics::ContextScope diagnostic_context(\n      &context.emitter(), [&](auto& builder) {\n        CARBON_DIAGNOSTIC(QualifiedDeclInIncompleteClassScope, Context,\n                          \"cannot declare a member of incomplete class {0}\",\n                          SemIR::TypeId);\n        builder.Context(loc_id, QualifiedDeclInIncompleteClassScope,\n                        context.classes().Get(class_id).self_type_id);\n      });\n  DiagnoseIncompleteClass(context, class_id);\n}\n\n// Diagnose that a qualified declaration name specifies an undefined interface\n// as its scope.\nstatic auto DiagnoseQualifiedDeclInUndefinedInterfaceScope(\n    Context& context, SemIR::LocId loc_id, SemIR::InterfaceId interface_id,\n    SemIR::InstId interface_inst_id) -> void {\n  Diagnostics::ContextScope diagnostic_context(\n      &context.emitter(), [&](auto& builder) {\n        CARBON_DIAGNOSTIC(QualifiedDeclInUndefinedInterfaceScope, Context,\n                          \"cannot declare a member of undefined interface {0}\",\n                          InstIdAsType);\n        builder.Context(loc_id, QualifiedDeclInUndefinedInterfaceScope,\n                        interface_inst_id);\n      });\n  DiagnoseIncompleteInterface(context, interface_id);\n}\n\n// Diagnose that a qualified declaration name specifies a different package as\n// its scope.\nstatic auto DiagnoseQualifiedDeclInImportedPackage(Context& context,\n                                                   SemIR::LocId use_loc_id,\n                                                   SemIR::LocId import_loc_id)\n    -> void {\n  CARBON_DIAGNOSTIC(QualifiedDeclOutsidePackage, Error,\n                    \"imported packages cannot be used for declarations\");\n  CARBON_DIAGNOSTIC(QualifiedDeclOutsidePackageSource, Note,\n                    \"package imported here\");\n  context.emitter()\n      .Build(use_loc_id, QualifiedDeclOutsidePackage)\n      .Note(import_loc_id, QualifiedDeclOutsidePackageSource)\n      .Emit();\n}\n\n// Diagnose that a qualified declaration name specifies a non-scope entity as\n// its scope.\nstatic auto DiagnoseQualifiedDeclInNonScope(\n    Context& context, SemIR::LocId use_loc_id,\n    SemIR::LocId non_scope_entity_loc_id) -> void {\n  CARBON_DIAGNOSTIC(QualifiedNameInNonScope, Error,\n                    \"name qualifiers are only allowed for entities that \"\n                    \"provide a scope\");\n  CARBON_DIAGNOSTIC(QualifiedNameNonScopeEntity, Note,\n                    \"referenced non-scope entity declared here\");\n  context.emitter()\n      .Build(use_loc_id, QualifiedNameInNonScope)\n      .Note(non_scope_entity_loc_id, QualifiedNameNonScopeEntity)\n      .Emit();\n}\n\nauto DeclNameStack::ResolveAsScope(const NameContext& name_context,\n                                   const NameComponent& name) const\n    -> std::pair<SemIR::NameScopeId, SemIR::GenericId> {\n  constexpr std::pair<SemIR::NameScopeId, SemIR::GenericId> InvalidResult = {\n      SemIR::NameScopeId::None, SemIR::GenericId::None};\n\n  if (!CheckQualifierIsResolved(*context_, name_context)) {\n    return InvalidResult;\n  }\n\n  if (name_context.state == NameContext::State::Poisoned) {\n    return InvalidResult;\n  }\n\n  auto new_params = DeclParams(\n      name.name_loc_id, name.first_param_node_id, name.last_param_node_id,\n      name.implicit_param_patterns_id, name.param_patterns_id);\n\n  // Find the scope corresponding to the resolved instruction.\n  // TODO: When diagnosing qualifiers on names, print a diagnostic that talks\n  // about qualifiers instead of redeclarations. Maybe also rename\n  // CheckRedeclParamsMatch.\n  CARBON_KIND_SWITCH(context_->insts().Get(name_context.resolved_inst_id)) {\n    case CARBON_KIND(SemIR::ClassDecl class_decl): {\n      const auto& class_info = context_->classes().Get(class_decl.class_id);\n      if (!CheckRedeclParamsMatch(*context_, new_params,\n                                  DeclParams(class_info))) {\n        return InvalidResult;\n      }\n      if (!class_info.is_complete()) {\n        DiagnoseQualifiedDeclInIncompleteClassScope(\n            *context_, name_context.loc_id, class_decl.class_id);\n        return InvalidResult;\n      }\n      return {class_info.scope_id, class_info.generic_id};\n    }\n    case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {\n      const auto& interface_info =\n          context_->interfaces().Get(interface_decl.interface_id);\n      if (!CheckRedeclParamsMatch(*context_, new_params,\n                                  DeclParams(interface_info))) {\n        return InvalidResult;\n      }\n      if (!interface_info.is_complete()) {\n        DiagnoseQualifiedDeclInUndefinedInterfaceScope(\n            *context_, name_context.loc_id, interface_decl.interface_id,\n            name_context.resolved_inst_id);\n        return InvalidResult;\n      }\n      // The scope and generic of an `I(T:! type)` is the outer\n      // interface-without-self. That is the generic where parameters appear.\n      // However when moving to the next qualifier, we need to move to the\n      // interface-with-self for the associated entity name.\n      return {interface_info.scope_without_self_id, interface_info.generic_id};\n    }\n    case CARBON_KIND(SemIR::Namespace resolved_inst): {\n      auto scope_id = resolved_inst.name_scope_id;\n      auto& scope = context_->name_scopes().Get(scope_id);\n      // This is specifically for qualified name handling.\n      if (!CheckRedeclParamsMatch(\n              *context_, new_params,\n              DeclParams(SemIR::LocId(name_context.resolved_inst_id),\n                         Parse::NodeId::None, Parse::NodeId::None,\n                         SemIR::InstBlockId::None, SemIR::InstBlockId::None))) {\n        return InvalidResult;\n      }\n      if (scope.is_closed_import()) {\n        DiagnoseQualifiedDeclInImportedPackage(*context_, name_context.loc_id,\n                                               SemIR::LocId(scope.inst_id()));\n        // Only error once per package. Recover by allowing this package name to\n        // be used as a name qualifier.\n        scope.set_is_closed_import(false);\n      }\n      return {scope_id, SemIR::GenericId::None};\n    }\n    default: {\n      DiagnoseQualifiedDeclInNonScope(\n          *context_, name_context.loc_id,\n          SemIR::LocId(name_context.resolved_inst_id));\n      return InvalidResult;\n    }\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/decl_name_stack.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_DECL_NAME_STACK_H_\n#define CARBON_TOOLCHAIN_CHECK_DECL_NAME_STACK_H_\n\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/check/scope_index.h\"\n#include \"toolchain/check/scope_stack.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nclass Context;\n\n// Provides support and stacking for qualified declaration name handling.\n//\n// A qualified declaration name will consist of entries, which are `Name`s\n// optionally followed by generic parameter lists, such as `Vector(T:! type)`\n// in `fn Vector(T:! type).Clear();`, but parameter lists aren't supported yet.\n// Identifiers such as `Clear` will be resolved to a name if possible, for\n// example when declaring things that are in a non-generic type or namespace,\n// and are otherwise marked as an unresolved identifier.\n//\n// Unresolved identifiers are valid if and only if they are the last step of a\n// qualified name; all resolved qualifiers must resolve to an entity with\n// members, such as a namespace. Resolved identifiers in the last step will\n// occur for both out-of-line definitions and new declarations, depending on\n// context.\n//\n// For each name component that is processed and denotes a scope, the\n// corresponding scope is also entered. This is important for unqualified name\n// lookup both in the definition of the entity being declared, and for names\n// appearing later in the declaration name itself. For example, in:\n//\n// ```\n// fn ClassA.ClassB(T:! U).Fn() { var x: V; }\n// ```\n//\n// the lookup for `U` looks in `ClassA`; the lookup for `V` looks first in\n// `ClassA.ClassB`, then its parent scope `ClassA`. Scopes entered as part of\n// processing the name are exited when the name is popped from the stack.\n//\n// Example state transitions:\n//\n// ```\n// // Empty -> Unresolved, because `MyNamespace` is newly declared.\n// namespace MyNamespace;\n//\n// // Empty -> Resolved -> Unresolved, because `MyType` is newly declared.\n// class MyNamespace.MyType;\n//\n// // Empty -> Resolved -> Resolved, because `MyType` was forward declared.\n// class MyNamespace.MyType {\n//   // Empty -> Unresolved, because `DoSomething` is newly declared.\n//   fn DoSomething();\n// }\n//\n// // Empty -> Resolved -> Resolved -> ResolvedNonScope, because `DoSomething`\n// // is forward declared in `MyType`, but is not a scope itself.\n// fn MyNamespace.MyType.DoSomething() { ... }\n// ```\nclass DeclNameStack {\n public:\n  // Context for declaration name construction.\n  // TODO: Add a helper for class, function, and interface to turn a NameContext\n  // into an EntityWithParamsBase.\n  struct NameContext {\n    enum class State : int8_t {\n      // A context that has not processed any parts of the qualifier.\n      Empty,\n\n      // The name has been resolved to an instruction ID.\n      Resolved,\n\n      // An identifier didn't resolve.\n      Unresolved,\n\n      // An identifier was poisoned in this scope.\n      Poisoned,\n\n      // The name has already been finished. This is not set in the name\n      // returned by `FinishName`, but is used internally to track that\n      // `FinishName` has already been called.\n      Finished,\n\n      // An error has occurred, such as an additional qualifier past an\n      // unresolved name. No new diagnostics should be emitted.\n      Error,\n    };\n\n    // Combines name information to produce a base struct for entity\n    // construction.\n    auto MakeEntityWithParamsBase(const NameComponent& name,\n                                  SemIR::InstId decl_id, bool is_extern,\n                                  SemIR::LibraryNameId extern_library) const\n        -> SemIR::EntityWithParamsBase {\n      return {\n          .name_id = name.name_id,\n          .parent_scope_id = parent_scope_id,\n          .generic_id = SemIR::GenericId::None,\n          .first_param_node_id = name.first_param_node_id,\n          .last_param_node_id = name.last_param_node_id,\n          .pattern_block_id = name.pattern_block_id,\n          .implicit_param_patterns_id = name.implicit_param_patterns_id,\n          .param_patterns_id = name.param_patterns_id,\n          .is_extern = is_extern,\n          .extern_library_id = extern_library,\n          .non_owning_decl_id =\n              extern_library.has_value() ? decl_id : SemIR::InstId::None,\n          .first_owning_decl_id =\n              extern_library.has_value() ? SemIR::InstId::None : decl_id,\n      };\n    }\n\n    // Returns any name collision found, or `None`. Requires a non-poisoned\n    // value.\n    auto prev_inst_id() const -> SemIR::InstId;\n\n    // Returns the name_id for a new instruction. This is `None` when the name\n    // resolved.\n    auto name_id_for_new_inst() const -> SemIR::NameId {\n      switch (state) {\n        case State::Unresolved:\n        case State::Poisoned:\n          return name_id;\n        default:\n          return SemIR::NameId::None;\n      }\n    }\n\n    // The current scope when this name began. This is the scope that we will\n    // return to at the end of the declaration.\n    ScopeIndex initial_scope_index;\n\n    State state = State::Empty;\n\n    // Whether there have been qualifiers in the name.\n    bool has_qualifiers = false;\n\n    // The scope which qualified names are added to. For unqualified names in\n    // an unnamed scope, this will be `None` to indicate the current scope\n    // should be used.\n    SemIR::NameScopeId parent_scope_id;\n\n    // The location of the final name component.\n    SemIR::LocId loc_id = SemIR::LocId::None;\n\n    // The name of the final name component.\n    SemIR::NameId name_id = SemIR::NameId::None;\n\n    union {\n      // The ID of a resolved qualifier, including both identifiers and\n      // expressions. `None` indicates resolution failed.\n      SemIR::InstId resolved_inst_id;\n\n      // When `state` is `Poisoned` (name is unresolved due to name poisoning),\n      // the poisoning location.\n      SemIR::LocId poisoning_loc_id = SemIR::LocId::None;\n    };\n  };\n\n  // Information about a declaration name that has been temporarily removed from\n  // the stack and will later be restored. Names can only be suspended once they\n  // are finished.\n  //\n  // This type is large, so moves of this type should be avoided.\n  struct SuspendedName : public MoveOnly<SuspendedName> {\n    // The declaration name information.\n    NameContext name_context;\n\n    // Suspended scopes. We only preallocate space for two of these, because\n    // suspended names are usually used for classes and functions with\n    // unqualified names, which only need at most two scopes -- one scope for\n    // the parameter and one scope for the entity itself, and we can store quite\n    // a few of these when processing a large class definition.\n    llvm::SmallVector<ScopeStack::SuspendedScope, 2> scopes;\n  };\n\n  explicit DeclNameStack(Context* context) : context_(context) {}\n\n  // Pushes processing of a new declaration name, which will be used\n  // contextually, and prepares to enter scopes for that name. To pop this\n  // state, `FinishName` and `PopScope` must be called, in that order.\n  auto PushScopeAndStartName() -> void;\n\n  // Creates and returns a name context corresponding to declaring an\n  // unqualified name in the current context. This is suitable for adding to\n  // name lookup in situations where a qualified name is not permitted, such as\n  // a pattern binding.\n  auto MakeUnqualifiedName(SemIR::LocId loc_id, SemIR::NameId name_id)\n      -> NameContext;\n\n  // Applies a name component as a qualifier for the current name. This will\n  // enter the scope corresponding to the name if the name describes an existing\n  // scope, such as a namespace or a defined class.\n  auto ApplyNameQualifier(const NameComponent& name) -> void;\n\n  // Finishes the current declaration name processing, returning the final\n  // context for adding the name to lookup. The final name component should be\n  // popped and passed to this function, and will be added to the declaration\n  // name.\n  auto FinishName(const NameComponent& name) -> NameContext;\n\n  // Finishes the current declaration name processing for an `impl`, returning\n  // the final context for adding the name to lookup.\n  //\n  // `impl`s don't actually have names, but want the rest of the name processing\n  // logic such as building parameter scopes, so are a special case.\n  auto FinishImplName() -> NameContext;\n\n  // Pops the declaration name from the declaration name stack, and pops all\n  // scopes that were entered as part of handling the declaration name. These\n  // are the scopes corresponding to name qualifiers in the name, for example\n  // the `A.B` in `fn A.B.F()`.\n  //\n  // This should be called at the end of the declaration.\n  // If check_unused is true, then performs unused bindings checks and emits\n  // associated diagnostics.\n  auto PopScope(bool check_unused = false) -> void;\n\n  // Peeks the current parent scope of the name on top of the stack. Note\n  // that if we're still processing the name qualifiers, this can change before\n  // the name is completed. Also, if the name up to this point was already\n  // declared and is a scope, this will be that scope, rather than the scope\n  // containing it.\n  auto PeekParentScopeId() const -> SemIR::NameScopeId {\n    return decl_name_stack_.back().parent_scope_id;\n  }\n\n  // Peeks the resolution scope index of the name on top of the stack.\n  auto PeekInitialScopeIndex() const -> ScopeIndex {\n    return decl_name_stack_.back().initial_scope_index;\n  }\n\n  // Temporarily remove the current declaration name and its associated scopes\n  // from the stack. Can only be called once the name is finished.\n  auto Suspend() -> SuspendedName;\n\n  // Restore a previously suspended name.\n  auto Restore(SuspendedName&& sus) -> void;\n\n  // Adds a name to name lookup. Assumes duplicates are already handled.\n  auto AddName(NameContext name_context, SemIR::InstId target_id,\n               SemIR::AccessKind access_kind) -> void;\n\n  // Adds a name to name lookup. Prints a diagnostic for name conflicts.\n  auto AddNameOrDiagnose(NameContext name_context, SemIR::InstId target_id,\n                         SemIR::AccessKind access_kind) -> void;\n\n  // Adds a name to name lookup if neither already declared nor poisoned in this\n  // scope.\n  auto LookupOrAddName(NameContext name_context, SemIR::InstId target_id,\n                       SemIR::AccessKind access_kind)\n      -> SemIR::ScopeLookupResult;\n\n  // Runs verification that the processing cleanly finished.\n  auto VerifyOnFinish() const -> void {\n    CARBON_CHECK(decl_name_stack_.empty(),\n                 \"decl_name_stack still has {0} entries\",\n                 decl_name_stack_.size());\n  }\n\n private:\n  // Returns a name context corresponding to an empty name.\n  auto MakeEmptyNameContext() -> NameContext;\n\n  // Appends a name to the given name context, and performs a lookup to find\n  // what, if anything, the name refers to.\n  auto ApplyAndLookupName(NameContext& name_context, SemIR::LocId loc_id,\n                          SemIR::NameId name_id) -> void;\n\n  // Attempts to resolve the given name context as a scope, and returns the\n  // corresponding scope. Issues a suitable diagnostic and returns `None` if\n  // the name doesn't resolve to a scope.\n  auto ResolveAsScope(const NameContext& name_context,\n                      const NameComponent& name) const\n      -> std::pair<SemIR::NameScopeId, SemIR::GenericId>;\n\n  // The linked context.\n  Context* context_;\n\n  // Provides nesting for construction.\n  llvm::SmallVector<NameContext> decl_name_stack_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_DECL_NAME_STACK_H_\n"
  },
  {
    "path": "toolchain/check/deduce.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/deduce.h\"\n\n#include \"llvm/ADT/SmallBitVector.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/subst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/impl.h\"\n#include \"toolchain/sem_ir/type.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nnamespace {\n// A list of pairs of (instruction from generic, corresponding instruction from\n// call to of generic) for which we still need to perform deduction, along with\n// methods to add and pop pending deductions from the list. Deductions are\n// popped in order from most- to least-recently pushed, with the intent that\n// they are visited in depth-first order, although the order is not expected to\n// matter except when it influences which error is diagnosed.\nclass DeductionWorklist {\n public:\n  // `context` must not be null.\n  explicit DeductionWorklist(Context* context) : context_(context) {}\n\n  struct PendingDeduction {\n    SemIR::InstId param;\n    SemIR::InstId arg;\n  };\n\n  // Adds a single (param, arg) deduction.\n  auto Add(SemIR::InstId param, SemIR::InstId arg) -> void {\n    deductions_.push_back({.param = param, .arg = arg});\n  }\n\n  // Adds a single (param, arg) type deduction.\n  auto Add(SemIR::TypeId param, SemIR::TypeId arg) -> void {\n    Add(context_->types().GetTypeInstId(param),\n        context_->types().GetTypeInstId(arg));\n  }\n\n  // Adds a single (param, arg) deduction of a specific.\n  auto Add(SemIR::SpecificId param, SemIR::SpecificId arg) -> void {\n    if (!param.has_value() || !arg.has_value()) {\n      return;\n    }\n    auto& param_specific = context_->specifics().Get(param);\n    auto& arg_specific = context_->specifics().Get(arg);\n    if (param_specific.generic_id != arg_specific.generic_id) {\n      // TODO: Decide whether to error on this or just treat the specific as\n      // non-deduced. For now we treat it as non-deduced.\n      return;\n    }\n    AddAll(param_specific.args_id, arg_specific.args_id);\n  }\n\n  // Adds a list of (param, arg) deductions. These are added in reverse order so\n  // they are popped in forward order.\n  template <typename ElementId>\n  auto AddAll(llvm::ArrayRef<ElementId> params, llvm::ArrayRef<ElementId> args)\n      -> void {\n    if (params.size() != args.size()) {\n      // TODO: Decide whether to error on this or just treat the parameter list\n      // as non-deduced. For now we treat it as non-deduced.\n      return;\n    }\n    for (auto [param, arg] : llvm::reverse(llvm::zip_equal(params, args))) {\n      Add(param, arg);\n    }\n  }\n\n  auto AddAll(SemIR::InstBlockId params, llvm::ArrayRef<SemIR::InstId> args)\n      -> void {\n    AddAll(context_->inst_blocks().Get(params), args);\n  }\n\n  auto AddAll(SemIR::StructTypeFieldsId params, SemIR::StructTypeFieldsId args)\n      -> void {\n    const auto& param_fields = context_->struct_type_fields().Get(params);\n    const auto& arg_fields = context_->struct_type_fields().Get(args);\n    if (param_fields.size() != arg_fields.size()) {\n      // TODO: Decide whether to error on this or just treat the parameter list\n      // as non-deduced. For now we treat it as non-deduced.\n      return;\n    }\n    // Don't do deduction unless the names match in order.\n    // TODO: Support reordering of names.\n    for (auto [param, arg] : llvm::zip_equal(param_fields, arg_fields)) {\n      if (param.name_id != arg.name_id) {\n        return;\n      }\n    }\n    for (auto [param, arg] :\n         llvm::reverse(llvm::zip_equal(param_fields, arg_fields))) {\n      Add(param.type_inst_id, arg.type_inst_id);\n    }\n  }\n\n  auto AddAll(SemIR::InstBlockId params, SemIR::InstBlockId args) -> void {\n    AddAll(context_->inst_blocks().Get(params),\n           context_->inst_blocks().Get(args));\n  }\n\n  // Adds a (param, arg) pair for an instruction argument, given its kind.\n  auto AddInstArg(SemIR::Inst::ArgAndKind param, int32_t arg) -> void {\n    CARBON_KIND_SWITCH(param) {\n      case SemIR::IdKind::None:\n      case SemIR::IdKind::For<SemIR::ClassId>:\n      case SemIR::IdKind::For<SemIR::IntKind>:\n        break;\n      case CARBON_KIND(SemIR::InstId inst_id): {\n        Add(inst_id, SemIR::InstId(arg));\n        break;\n      }\n      case CARBON_KIND(SemIR::TypeInstId inst_id): {\n        Add(inst_id, SemIR::InstId(arg));\n        break;\n      }\n      case CARBON_KIND(SemIR::StructTypeFieldsId fields_id): {\n        AddAll(fields_id, SemIR::StructTypeFieldsId(arg));\n        break;\n      }\n      case CARBON_KIND(SemIR::InstBlockId inst_block_id): {\n        AddAll(inst_block_id, SemIR::InstBlockId(arg));\n        break;\n      }\n      case CARBON_KIND(SemIR::SpecificId specific_id): {\n        Add(specific_id, SemIR::SpecificId(arg));\n        break;\n      }\n      default:\n        CARBON_FATAL(\"unexpected argument kind\");\n    }\n  }\n\n  // Returns whether we have completed all deductions.\n  auto Done() -> bool { return deductions_.empty(); }\n\n  // Pops the next deduction. Requires `!Done()`.\n  auto PopNext() -> PendingDeduction { return deductions_.pop_back_val(); }\n\n private:\n  Context* context_;\n  llvm::SmallVector<PendingDeduction> deductions_;\n};\n\n// State that is tracked throughout the deduction process.\nclass DeductionContext {\n public:\n  // Preparse to perform deduction. If an enclosing specific or self type\n  // are provided, adds the corresponding arguments as known arguments that will\n  // not be deduced. `context` must not be null.\n  DeductionContext(Context* context, SemIR::LocId loc_id,\n                   SemIR::GenericId generic_id,\n                   SemIR::SpecificId enclosing_specific_id, bool diagnose);\n\n  auto context() const -> Context& { return *context_; }\n\n  // Adds a pending deduction of `param` from `arg`. `needs_substitution`\n  // indicates whether we need to substitute known generic parameters into\n  // `param`.\n  template <typename ParamT, typename ArgT>\n  auto Add(ParamT param, ArgT arg) -> void {\n    worklist_.Add(param, arg);\n  }\n\n  // Same as `Add` but for an array or block of operands.\n  template <typename ParamT, typename ArgT>\n  auto AddAll(ParamT param, ArgT arg) -> void {\n    worklist_.AddAll(param, arg);\n  }\n\n  // Performs all deductions in the deduction worklist. Returns whether\n  // deduction succeeded.\n  auto Deduce() -> bool;\n\n  // Returns whether every generic parameter has a corresponding deduced generic\n  // argument. If not, issues a suitable diagnostic.\n  auto CheckDeductionIsComplete() -> bool;\n\n  // Forms a specific corresponding to the deduced generic with the deduced\n  // argument list. Must not be called before deduction is complete.\n  auto MakeSpecific() -> SemIR::SpecificId;\n\n private:\n  auto NoteInitializingParam(SemIR::InstId param_id, auto& builder) -> void {\n    if (auto param = context().insts().TryGetAs<SemIR::SymbolicBindingPattern>(\n            param_id)) {\n      CARBON_DIAGNOSTIC(InitializingGenericParam, Note,\n                        \"initializing generic parameter `{0}` declared here\",\n                        SemIR::NameId);\n      builder.Note(param_id, InitializingGenericParam,\n                   context().entity_names().Get(param->entity_name_id).name_id);\n    } else {\n      NoteGenericHere(context(), generic_id_, builder);\n    }\n  }\n\n  Context* context_;\n  SemIR::LocId loc_id_;\n  SemIR::GenericId generic_id_;\n  bool diagnose_;\n\n  DeductionWorklist worklist_;\n\n  llvm::SmallVector<SemIR::InstId> result_arg_ids_;\n  llvm::SmallVector<Substitution> substitutions_;\n  SemIR::CompileTimeBindIndex first_deduced_index_;\n  // Non-deduced indexes, indexed by parameter index - first_deduced_index_.\n  llvm::SmallBitVector non_deduced_indexes_;\n};\n\n}  // namespace\n\nstatic auto NoteGenericHere(Context& context, SemIR::GenericId generic_id,\n                            DiagnosticBuilder& diag) -> void {\n  CARBON_DIAGNOSTIC(DeductionGenericHere, Note,\n                    \"while deducing parameters of generic declared here\");\n  diag.Note(context.generics().Get(generic_id).decl_id, DeductionGenericHere);\n}\n\nDeductionContext::DeductionContext(Context* context, SemIR::LocId loc_id,\n                                   SemIR::GenericId generic_id,\n                                   SemIR::SpecificId enclosing_specific_id,\n                                   bool diagnose)\n    : context_(context),\n      loc_id_(loc_id),\n      generic_id_(generic_id),\n      diagnose_(diagnose),\n      worklist_(context),\n      first_deduced_index_(0) {\n  CARBON_CHECK(generic_id.has_value(),\n               \"Performing deduction for non-generic entity\");\n\n  // Initialize the deduced arguments to `None`.\n  result_arg_ids_.resize(\n      context->inst_blocks()\n          .Get(context->generics().Get(generic_id_).bindings_id)\n          .size(),\n      SemIR::InstId::None);\n\n  if (enclosing_specific_id.has_value()) {\n    // Copy any outer generic arguments from the specified instance and prepare\n    // to substitute them into the function declaration.\n    auto args = context->inst_blocks().Get(\n        context->specifics().Get(enclosing_specific_id).args_id);\n    llvm::copy(args, result_arg_ids_.begin());\n\n    // TODO: Subst is linear in the length of the substitutions list. Change\n    // it so we can pass in an array mapping indexes to substitutions instead.\n    substitutions_.reserve(args.size() + result_arg_ids_.size());\n    for (auto [i, subst_inst_id] : llvm::enumerate(args)) {\n      substitutions_.push_back(\n          {.bind_id = SemIR::CompileTimeBindIndex(i),\n           .replacement_id = context->constant_values().Get(subst_inst_id)});\n    }\n    first_deduced_index_ = SemIR::CompileTimeBindIndex(args.size());\n  }\n\n  non_deduced_indexes_.resize(result_arg_ids_.size() -\n                              first_deduced_index_.index);\n}\n\nauto DeductionContext::Deduce() -> bool {\n  while (!worklist_.Done()) {\n    auto [param_id, arg_id] = worklist_.PopNext();\n\n    // TODO: Bail out if there's nothing to deduce: if we're not in a pattern\n    // and the parameter doesn't have a symbolic constant value.\n\n    auto param_type_id = context().insts().Get(param_id).type_id();\n    if (context().types().Is<SemIR::PatternType>(param_type_id)) {\n      param_type_id =\n          SemIR::ExtractScrutineeType(context().sem_ir(), param_type_id);\n    } else if (context().types().IsFacetType(param_type_id)) {\n      // Given `fn F[G:! Interface](g: G)`, the type of `g` is `G as type`. For\n      // deduction, we want to ignore the `as type`, and check that the argument\n      // can convert to the FacetType of the canonical facet value.\n      param_id = GetCanonicalFacetOrTypeValue(context(), param_id);\n      param_type_id = context().insts().Get(param_id).type_id();\n    }\n\n    // If the parameter has a symbolic type, deduce against that.\n    if (param_type_id.is_symbolic()) {\n      // TODO: This looks liable to add redundant work (possibly even\n      // exponential amounts of it) in some of the cases handled below.\n      Add(context().types().GetTypeInstId(param_type_id),\n          context().types().GetTypeInstId(\n              context().insts().Get(arg_id).type_id()));\n    } else {\n      // The argument (e.g. a TupleLiteral of types) may be convertible to a\n      // compile-time value (e.g. TupleType) that we can decompose further.\n      // So we do this conversion here, even though we will later try convert\n      // again when we have deduced all of the bindings.\n      Diagnostics::AnnotationScope annotate_diagnostics(\n          &context().emitter(), [&](auto& builder) {\n            if (diagnose_) {\n              NoteInitializingParam(param_id, builder);\n            }\n          });\n      // TODO: The call logic should reuse the conversion here (if any) instead\n      // of doing the same conversion again. At the moment we throw away the\n      // converted arg_id.\n      arg_id = diagnose_ ? ConvertToValueOfType(context(), loc_id_, arg_id,\n                                                param_type_id)\n                         : TryConvertToValueOfType(context(), loc_id_, arg_id,\n                                                   param_type_id);\n      if (arg_id == SemIR::ErrorInst::InstId) {\n        return false;\n      }\n    }\n\n    // Attempt to match `param_inst` against `arg_id`. If the match succeeds,\n    // this should `continue` the outer loop. On `break`, we will try to desugar\n    // the parameter to continue looking for a match.\n    auto param_inst = context().insts().Get(param_id);\n    CARBON_KIND_SWITCH(param_inst) {\n      // Deducing a symbolic binding pattern from an argument deduces the\n      // binding as having that constant value. For example, deducing\n      // `(T:! type)` against `(i32)` deduces `T` to be `i32`. This only arises\n      // when initializing a generic parameter from an explicitly specified\n      // argument, and in this case, the argument is required to be a\n      // compile-time constant.\n      case CARBON_KIND(SemIR::SymbolicBindingPattern bind): {\n        auto& entity_name = context().entity_names().Get(bind.entity_name_id);\n        auto index = entity_name.bind_index();\n        if (!index.has_value()) {\n          break;\n        }\n        CARBON_CHECK(\n            index >= first_deduced_index_ &&\n                static_cast<size_t>(index.index) < result_arg_ids_.size(),\n            \"Unexpected index {0} for symbolic binding pattern; \"\n            \"expected to be in range [{1}, {2})\",\n            index.index, first_deduced_index_.index, result_arg_ids_.size());\n        CARBON_CHECK(!result_arg_ids_[index.index].has_value(),\n                     \"Deduced a value for parameter prior to its declaration\");\n\n        auto arg_const_inst_id =\n            context().constant_values().GetConstantInstId(arg_id);\n        if (!arg_const_inst_id.has_value()) {\n          if (diagnose_) {\n            CARBON_DIAGNOSTIC(CompTimeArgumentNotConstant, Error,\n                              \"argument for generic parameter is not a \"\n                              \"compile-time constant\");\n            auto diag =\n                context().emitter().Build(loc_id_, CompTimeArgumentNotConstant);\n            NoteInitializingParam(param_id, diag);\n            diag.Emit();\n          }\n          return false;\n        }\n\n        result_arg_ids_[index.index] = arg_const_inst_id;\n        // This parameter index should not be deduced if it appears later.\n        non_deduced_indexes_[index.index - first_deduced_index_.index] = true;\n        continue;\n      }\n\n      // Deducing a symbolic binding appearing within an expression against a\n      // constant value deduces the binding as having that value. For example,\n      // deducing `[T:! type](x: T)` against `(\"foo\")` deduces `T` as `String`.\n      case CARBON_KIND(SemIR::SymbolicBinding bind): {\n        auto& entity_name = context().entity_names().Get(bind.entity_name_id);\n        auto index = entity_name.bind_index();\n        if (!index.has_value() || index < first_deduced_index_ ||\n            non_deduced_indexes_[index.index - first_deduced_index_.index]) {\n          break;\n        }\n\n        CARBON_CHECK(static_cast<size_t>(index.index) < result_arg_ids_.size(),\n                     \"Deduced value for unexpected index {0}; expected to \"\n                     \"deduce {1} arguments.\",\n                     index, result_arg_ids_.size());\n        auto arg_const_inst_id =\n            context().constant_values().GetConstantInstId(arg_id);\n        if (arg_const_inst_id.has_value()) {\n          if (result_arg_ids_[index.index].has_value() &&\n              result_arg_ids_[index.index] != arg_const_inst_id) {\n            if (diagnose_) {\n              // TODO: Include the two different deduced values.\n              CARBON_DIAGNOSTIC(DeductionInconsistent, Error,\n                                \"inconsistent deductions for value of generic \"\n                                \"parameter `{0}`\",\n                                SemIR::NameId);\n              auto diag = context().emitter().Build(\n                  loc_id_, DeductionInconsistent, entity_name.name_id);\n              NoteGenericHere(context(), generic_id_, diag);\n              diag.Emit();\n            }\n            return false;\n          }\n          result_arg_ids_[index.index] = arg_const_inst_id;\n        }\n        continue;\n      }\n\n      case SemIR::StructValue::Kind:\n        // TODO: Match field name order between param and arg.\n        break;\n\n        // TODO: Handle more cases.\n\n      default:\n        if (param_inst.kind().deduce_through()) {\n          // Various kinds of parameter should match an argument of the same\n          // form, if the operands all match.\n          auto arg_inst = context().insts().Get(arg_id);\n          if (arg_inst.kind() != param_inst.kind()) {\n            break;\n          }\n          worklist_.AddInstArg(param_inst.arg0_and_kind(), arg_inst.arg0());\n          worklist_.AddInstArg(param_inst.arg1_and_kind(), arg_inst.arg1());\n          continue;\n        }\n        break;\n    }\n\n    // We didn't manage to deduce against the syntactic form of the parameter.\n    // Convert it to a canonical constant value and try deducing against that.\n    auto param_const_id = context().constant_values().Get(param_id);\n    if (!param_const_id.has_value() || !param_const_id.is_symbolic()) {\n      // It's not a symbolic constant. There's nothing here to deduce.\n      continue;\n    }\n    auto param_const_inst_id =\n        context().constant_values().GetInstId(param_const_id);\n    if (param_const_inst_id != param_id) {\n      Add(param_const_inst_id, arg_id);\n      continue;\n    }\n  }\n\n  return true;\n}\n\n// Gets the entity name of a generic binding. The generic binding may be an\n// imported instruction.\nstatic auto GetEntityNameForGenericBinding(Context& context,\n                                           SemIR::InstId binding_id)\n    -> SemIR::NameId {\n  // If `binding_id` is imported (or referenced indirectly perhaps in the\n  // future), it may not have an entity name. Get a canonical local instruction\n  // from its constant value which does.\n  binding_id = context.constant_values().GetConstantInstId(binding_id);\n\n  if (auto bind_name =\n          context.insts().TryGetAs<SemIR::AnyBinding>(binding_id)) {\n    return context.entity_names().Get(bind_name->entity_name_id).name_id;\n  } else {\n    CARBON_FATAL(\"Instruction without entity name in generic binding position\");\n  }\n}\n\nauto DeductionContext::CheckDeductionIsComplete() -> bool {\n  // Check we deduced an argument value for every parameter, and convert each\n  // argument to match the final parameter type after substituting any deduced\n  // types it depends on.\n  for (auto&& [i, deduced_arg_id] :\n       llvm::enumerate(llvm::MutableArrayRef(result_arg_ids_)\n                           .drop_front(first_deduced_index_.index))) {\n    auto binding_index = first_deduced_index_.index + i;\n    auto binding_id = context().inst_blocks().Get(\n        context().generics().Get(generic_id_).bindings_id)[binding_index];\n    if (!deduced_arg_id.has_value()) {\n      if (diagnose_) {\n        CARBON_DIAGNOSTIC(DeductionIncomplete, Error,\n                          \"cannot deduce value for generic parameter `{0}`\",\n                          SemIR::NameId);\n        auto diag = context().emitter().Build(\n            loc_id_, DeductionIncomplete,\n            GetEntityNameForGenericBinding(context(), binding_id));\n        NoteGenericHere(context(), generic_id_, diag);\n        diag.Emit();\n      }\n      return false;\n    }\n\n    // If the binding is symbolic it can refer to other earlier bindings in the\n    // same generic, or from an enclosing specific. Substitute to replace those\n    // and get a non-symbolic type in order for us to know the final type that\n    // the argument needs to be converted to.\n    //\n    // Note that when typechecking a checked generic, the arguments can\n    // still be symbolic, so the substitution would also be symbolic. We are\n    // unable to get the final type for symbolic bindings until deducing with\n    // non-symbolic arguments.\n    //\n    // TODO: If arguments of different values, but that _convert to_ the same\n    // value, are deduced for the same symbolic binding, then we will fail\n    // typechecking in Deduce() with conflicting types via the\n    // `DeductionInconsistent` diagnostic. If we defer that check until after\n    // all conversions are done (after the code below) then we won't diagnose\n    // that incorrectly.\n    auto binding_type_id = context().insts().Get(binding_id).type_id();\n    if (binding_type_id.is_symbolic()) {\n      auto param_type_const_id =\n          SubstConstant(context(), SemIR::LocId(binding_id),\n                        binding_type_id.AsConstantId(), substitutions_);\n      CARBON_CHECK(param_type_const_id.has_value());\n      binding_type_id =\n          context().types().GetTypeIdForTypeConstantId(param_type_const_id);\n\n      Diagnostics::AnnotationScope annotate_diagnostics(\n          &context().emitter(), [&](auto& builder) {\n            if (diagnose_) {\n              NoteInitializingParam(binding_id, builder);\n            }\n          });\n      auto converted_arg_id =\n          diagnose_ ? ConvertToValueOfType(context(), loc_id_, deduced_arg_id,\n                                           binding_type_id)\n                    : TryConvertToValueOfType(context(), loc_id_,\n                                              deduced_arg_id, binding_type_id);\n      // The conversion of the argument to the parameter type can fail after\n      // applying the enclosing specific, in which case deduction fails.\n      if (converted_arg_id == SemIR::ErrorInst::InstId) {\n        return false;\n      }\n\n      // Replace the deduced arg with its value converted to the parameter\n      // type. The conversion of the argument type must produce a constant value\n      // to be used in deduction.\n      if (auto const_inst_id =\n              context().constant_values().GetConstantInstId(converted_arg_id);\n          const_inst_id.has_value()) {\n        deduced_arg_id = const_inst_id;\n      } else {\n        if (diagnose_) {\n          CARBON_DIAGNOSTIC(RuntimeConversionDuringCompTimeDeduction, Error,\n                            \"compile-time value requires runtime conversion, \"\n                            \"constructing value of type {0}\",\n                            SemIR::TypeId);\n          auto diag = context().emitter().Build(\n              loc_id_, RuntimeConversionDuringCompTimeDeduction,\n              binding_type_id);\n          NoteGenericHere(context(), generic_id_, diag);\n          diag.Emit();\n        }\n        deduced_arg_id = SemIR::ErrorInst::InstId;\n      }\n    }\n\n    substitutions_.push_back(\n        {.bind_id = SemIR::CompileTimeBindIndex(binding_index),\n         .replacement_id = context().constant_values().Get(deduced_arg_id)});\n  }\n  return true;\n}\n\nauto DeductionContext::MakeSpecific() -> SemIR::SpecificId {\n  // TODO: Convert the deduced values to the types of the bindings.\n\n  return Check::MakeSpecific(context(), loc_id_, generic_id_, result_arg_ids_);\n}\n\nauto DeduceGenericCallArguments(\n    Context& context, SemIR::LocId loc_id, SemIR::GenericId generic_id,\n    SemIR::SpecificId enclosing_specific_id,\n    [[maybe_unused]] SemIR::InstBlockId implicit_param_patterns_id,\n    SemIR::InstBlockId param_patterns_id,\n    [[maybe_unused]] SemIR::InstId self_id,\n    llvm::ArrayRef<SemIR::InstId> arg_ids) -> SemIR::SpecificId {\n  DeductionContext deduction(&context, loc_id, generic_id,\n                             enclosing_specific_id,\n                             /*diagnose=*/true);\n\n  // Prepare to perform deduction of the explicit parameters against their\n  // arguments.\n  // TODO: Also perform deduction for type of self.\n  deduction.AddAll(param_patterns_id, arg_ids);\n\n  if (!deduction.Deduce() || !deduction.CheckDeductionIsComplete()) {\n    return SemIR::SpecificId::None;\n  }\n\n  return deduction.MakeSpecific();\n}\n\nauto DeduceImplArguments(Context& context, SemIR::LocId loc_id,\n                         const SemIR::Impl& impl, SemIR::ConstantId self_id,\n                         SemIR::SpecificId constraint_specific_id)\n    -> SemIR::SpecificId {\n  DeductionContext deduction(&context, loc_id, impl.generic_id,\n                             /*enclosing_specific_id=*/SemIR::SpecificId::None,\n                             /*diagnose=*/false);\n\n  // Prepare to perform deduction of the type and interface. Use the canonical\n  // `self_id` to save a trip through the deduce loop, which will then need to\n  // get the canonical instruction.\n  deduction.Add(context.constant_values().GetConstantInstId(impl.self_id),\n                context.constant_values().GetInstId(self_id));\n  deduction.Add(impl.interface.specific_id, constraint_specific_id);\n\n  // TODO: Deduce has side effects in the semir by generating `Converted`\n  // instructions, and may also introduce intermediate states like\n  // `FacetAccessType`. We should stop generating those when deducing for impl\n  // lookup, but for now we discard them by pushing an InstBlock on the stack\n  // and dropping it right after. We also need to avoid adding those dropped\n  // instructions to any enclosing generic, so we push a fresh generic region.\n  context.inst_block_stack().Push();\n  context.generic_region_stack().Push({.generic_id = SemIR::GenericId::None});\n\n  bool success = deduction.Deduce() && deduction.CheckDeductionIsComplete();\n\n  context.generic_region_stack().Pop();\n  context.inst_block_stack().PopAndDiscard();\n\n  if (!success) {\n    return SemIR::SpecificId::None;\n  }\n  return deduction.MakeSpecific();\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/deduce.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_DEDUCE_H_\n#define CARBON_TOOLCHAIN_CHECK_DEDUCE_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Deduces the generic arguments to use in a call to a generic.\nauto DeduceGenericCallArguments(Context& context, SemIR::LocId loc_id,\n                                SemIR::GenericId generic_id,\n                                SemIR::SpecificId enclosing_specific_id,\n                                SemIR::InstBlockId implicit_param_patterns_id,\n                                SemIR::InstBlockId param_patterns_id,\n                                SemIR::InstId self_id,\n                                llvm::ArrayRef<SemIR::InstId> arg_ids)\n    -> SemIR::SpecificId;\n\n// Deduces the impl arguments to use in a use of a parameterized impl. Returns\n// `None` if deduction fails.\nauto DeduceImplArguments(Context& context, SemIR::LocId loc_id,\n                         const SemIR::Impl& impl, SemIR::ConstantId self_id,\n                         SemIR::SpecificId constraint_specific_id)\n    -> SemIR::SpecificId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_DEDUCE_H_\n"
  },
  {
    "path": "toolchain/check/deferred_definition_worklist.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/deferred_definition_worklist.h\"\n\n#include <algorithm>\n#include <optional>\n#include <variant>\n\n#include \"common/emplace_by_calling.h\"\n#include \"common/vlog.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n\nnamespace Carbon::Check {\n\nstatic constexpr llvm::StringLiteral VlogPrefix = \"DeferredDefinitionWorklist \";\n\nDeferredDefinitionWorklist::DeferredDefinitionWorklist(\n    llvm::raw_ostream* vlog_stream)\n    : vlog_stream_(vlog_stream) {\n  // See declaration of `worklist_`.\n  worklist_.reserve(64);\n}\n\nauto DeferredDefinitionWorklist::SuspendFunctionAndPush(\n    Parse::DeferredDefinitionIndex index,\n    llvm::function_ref<auto()->SuspendedFunction> suspend) -> void {\n  worklist_.emplace_back(EmplaceByCalling([&] {\n    return CheckSkippedDefinition{.definition_index = index,\n                                  .suspended_fn = suspend()};\n  }));\n  CARBON_VLOG(\"{0}Push CheckSkippedDefinition {1}\\n\", VlogPrefix, index.index);\n}\n\nauto DeferredDefinitionWorklist::SuspendThunkAndPush(Context& context,\n                                                     ThunkInfo info) -> void {\n  worklist_.emplace_back(EmplaceByCalling([&] {\n    return DefineThunk{.info = info, .scope = context.scope_stack().Suspend()};\n  }));\n  CARBON_VLOG(\"{0}Push DefineThunk {1}\\n\", VlogPrefix, info.function_id);\n}\n\nauto DeferredDefinitionWorklist::PushEnterDeferredDefinitionScope(\n    Context& context) -> bool {\n  bool nested = !entered_scopes_.empty() &&\n                entered_scopes_.back().scope_index ==\n                    context.decl_name_stack().PeekInitialScopeIndex();\n  entered_scopes_.push_back({.nested = nested,\n                             .worklist_start_index = worklist_.size(),\n                             .scope_index = context.scope_stack().PeekIndex()});\n  if (nested) {\n    worklist_.emplace_back(EmplaceByCalling([&] {\n      return EnterNestedDeferredDefinitionScope{.suspended_name = std::nullopt};\n    }));\n    CARBON_VLOG(\"{0}Push EnterDeferredDefinitionScope (nested)\\n\", VlogPrefix);\n  } else {\n    // Don't push a task to re-enter a non-nested scope. Instead,\n    // SuspendFinishedScopeAndPush will remain in the scope when executing the\n    // worklist tasks.\n    CARBON_VLOG(\"{0}Entered non-nested deferred definition scope\\n\",\n                VlogPrefix);\n  }\n  return !nested;\n}\n\nauto DeferredDefinitionWorklist::SuspendFinishedScopeAndPush(Context& context)\n    -> FinishedScopeKind {\n  auto [nested, start_index, _] = entered_scopes_.pop_back_val();\n\n  // If we've not found any tasks to perform in this scope, clean up the stack.\n  // For non-nested scope, there will be no tasks on the worklist for this scope\n  // in this case; for a nested scope, there will just be a task to re-enter the\n  // nested scope.\n  if (!nested && start_index == worklist_.size()) {\n    context.decl_name_stack().PopScope();\n    CARBON_VLOG(\"{0}Left non-nested empty deferred definition scope\\n\",\n                VlogPrefix);\n    return FinishedScopeKind::NonNestedEmpty;\n  }\n  if (nested && start_index == worklist_.size() - 1) {\n    CARBON_CHECK(std::holds_alternative<EnterNestedDeferredDefinitionScope>(\n        worklist_.back()));\n    worklist_.pop_back();\n    context.decl_name_stack().PopScope();\n    CARBON_VLOG(\"{0}Pop EnterNestedDeferredDefinitionScope (empty)\\n\",\n                VlogPrefix);\n    return FinishedScopeKind::Nested;\n  }\n\n  // If we're finishing a nested deferred definition scope, keep track of that\n  // but don't type-check deferred definitions now.\n  if (nested) {\n    auto& enter_scope =\n        get<EnterNestedDeferredDefinitionScope>(worklist_[start_index]);\n    // This is a nested deferred definition scope. Suspend the inner scope so we\n    // can restore it when we come to type-check the deferred definitions.\n    enter_scope.suspended_name.emplace(\n        EmplaceByCalling([&] { return context.decl_name_stack().Suspend(); }));\n\n    // Enqueue a task to leave the nested scope.\n    worklist_.emplace_back(LeaveNestedDeferredDefinitionScope{});\n    CARBON_VLOG(\"{0}Push LeaveNestedDeferredDefinitionScope\\n\", VlogPrefix);\n    return FinishedScopeKind::Nested;\n  }\n\n  // We're at the end of a non-nested deferred definition scope. Start checking\n  // deferred definitions.\n  CARBON_VLOG(\"{0}Starting deferred definition processing\\n\", VlogPrefix);\n  return FinishedScopeKind::NonNestedWithWork;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/deferred_definition_worklist.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_DEFERRED_DEFINITION_WORKLIST_H_\n#define CARBON_TOOLCHAIN_CHECK_DEFERRED_DEFINITION_WORKLIST_H_\n\n#include <optional>\n#include <variant>\n\n#include \"common/ostream.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/check/decl_name_stack.h\"\n#include \"toolchain/parse/tree.h\"\n\nnamespace Carbon::Check {\n\n// A worklist of pending tasks to perform to check deferred function definitions\n// in the right order.\nclass DeferredDefinitionWorklist {\n public:\n  // State saved for a function definition that has been suspended after\n  // processing its declaration and before processing its body. This is used for\n  // inline method handling.\n  //\n  // This type is large, so moves of this type should be avoided.\n  struct SuspendedFunction : public MoveOnly<SuspendedFunction> {\n    // The function that was declared.\n    SemIR::FunctionId function_id;\n    // The instruction ID of the FunctionDecl instruction.\n    SemIR::InstId decl_id;\n    // The declaration name information of the function. This includes the scope\n    // information, such as parameter names.\n    DeclNameStack::SuspendedName saved_name_state;\n  };\n\n  // A worklist task that indicates we should check a deferred function\n  // definition that we previously skipped.\n  //\n  // This type is large, so moves of this type should be avoided.\n  struct CheckSkippedDefinition : public MoveOnly<CheckSkippedDefinition> {\n    // The definition that we skipped.\n    Parse::DeferredDefinitionIndex definition_index;\n    // The suspended function.\n    SuspendedFunction suspended_fn;\n  };\n\n  // A description of a thunk.\n  struct ThunkInfo {\n    SemIR::FunctionId signature_id;\n    SemIR::FunctionId function_id;\n    SemIR::InstId decl_id;\n    SemIR::InstId callee_id;\n  };\n\n  // A worklist task that indicates we should define a thunk that was previously\n  // declared.\n  //\n  // This type is large, so moves of this type should be avoided.\n  struct DefineThunk : public MoveOnly<DefineThunk> {\n    ThunkInfo info;\n    ScopeStack::SuspendedScope scope;\n  };\n\n  // A worklist task that indicates we should enter a nested deferred definition\n  // scope. We delay processing the contents of nested deferred definition\n  // scopes until we reach the end of the parent scope. For example:\n  //\n  // ```\n  // class A {\n  //   class B {\n  //     fn F() -> A { return {}; }\n  //   }\n  // } // A.B.F is type-checked here, with A complete.\n  //\n  // fn F() {\n  //   class C {\n  //     fn G() {}\n  //   } // C.G is type-checked here.\n  // }\n  // ```\n  //\n  // This type is large, so moves of this type should be avoided.\n  struct EnterNestedDeferredDefinitionScope\n      : public MoveOnly<EnterNestedDeferredDefinitionScope> {\n    // The suspended scope. This is only set once we reach the end of the scope.\n    std::optional<DeclNameStack::SuspendedName> suspended_name;\n  };\n\n  // A worklist task that indicates we should leave a nested deferred definition\n  // scope.\n  struct LeaveNestedDeferredDefinitionScope {};\n\n  // A pending type-checking task.\n  using Task = std::variant<CheckSkippedDefinition, DefineThunk,\n                            EnterNestedDeferredDefinitionScope,\n                            LeaveNestedDeferredDefinitionScope>;\n\n  explicit DeferredDefinitionWorklist(llvm::raw_ostream* vlog_stream);\n\n  // Suspends the current function definition and pushes a task onto the\n  // worklist to finish it later.\n  auto SuspendFunctionAndPush(\n      Parse::DeferredDefinitionIndex index,\n      llvm::function_ref<auto()->SuspendedFunction> suspend) -> void;\n\n  // Suspends the current thunk scope and pushes a task onto the worklist to\n  // define it later.\n  auto SuspendThunkAndPush(Context& context, ThunkInfo info) -> void;\n\n  // Pushes a task to re-enter a function scope, so that functions defined\n  // within it are type-checked in the right context. Returns whether a\n  // non-nested scope was entered.\n  auto PushEnterDeferredDefinitionScope(Context& context) -> bool;\n\n  // The kind of scope that we just finished.\n  enum class FinishedScopeKind {\n    // We finished a nested scope. No further action is taken at this point.\n    Nested,\n    // We finished a non-nested scope that has no further actions to perform.\n    NonNestedEmpty,\n    // We finished a non-nested scope that has further actions to perform.\n    NonNestedWithWork,\n  };\n\n  // Suspends the current deferred definition scope, which is finished but still\n  // on the decl_name_stack, and pushes a task to leave the scope when we're\n  // type-checking deferred definitions. Returns `true` if the current list of\n  // deferred definitions should be type-checked immediately.\n  auto SuspendFinishedScopeAndPush(Context& context) -> FinishedScopeKind;\n\n  // Returns the current size of the worklist.\n  auto size() const -> size_t { return worklist_.size(); }\n\n  // Truncates the worklist to the given size.\n  auto truncate(int new_size) -> void { worklist_.truncate(new_size); }\n\n  // Gets the given item on the worklist.\n  auto operator[](int index) -> Task& { return worklist_[index]; }\n\n  // CHECK that the work list has no further work.\n  auto VerifyEmpty() {\n    CARBON_CHECK(worklist_.empty() && entered_scopes_.empty(),\n                 \"Tasks left behind on worklist.\");\n  }\n\n private:\n  // A deferred definition scope that is currently still open.\n  struct EnteredScope {\n    // Whether this scope is nested immediately within the enclosing scope. If\n    // so, deferred definitions are not processed at the end of this scope.\n    bool nested;\n    // The index in worklist_ of the first task in this scope. For a nested\n    // scope, this is a EnterNestedDeferredDefinitionScope task.\n    size_t worklist_start_index;\n    // The corresponding lexical scope index.\n    ScopeIndex scope_index;\n  };\n\n  llvm::raw_ostream* vlog_stream_;\n\n  // A worklist of type-checking tasks we'll need to do later.\n  //\n  // Don't allocate any inline storage here. A Task is fairly large, so we never\n  // want this to live on the stack. Instead, we reserve space in the\n  // constructor for a fairly large number of deferred definitions.\n  llvm::SmallVector<Task, 0> worklist_;\n\n  // The deferred definition scopes for the current checking actions.\n  llvm::SmallVector<EnteredScope> entered_scopes_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_DEFERRED_DEFINITION_WORKLIST_H_\n"
  },
  {
    "path": "toolchain/check/diagnostic_emitter.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/diagnostic_emitter.h\"\n\n#include <algorithm>\n#include <optional>\n#include <string>\n\n#include \"common/raw_string_ostream.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/sem_ir/absolute_node_id.h\"\n#include \"toolchain/sem_ir/diagnostic_loc_converter.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/stringify.h\"\n\nnamespace Carbon::Check {\n\nauto DiagnosticEmitter::ConvertLoc(LocIdForDiagnostics loc_id,\n                                   ContextFnT context_fn) const\n    -> Diagnostics::ConvertedLoc {\n  auto [imports, converted] = loc_converter_.ConvertWithImports(\n      loc_id.loc_id(), loc_id.is_token_only());\n  for (const auto& import : imports) {\n    CARBON_DIAGNOSTIC(InImport, LocationInfo, \"in import\");\n    CARBON_DIAGNOSTIC(InCppInclude, LocationInfo, \"in file included here\");\n    CARBON_DIAGNOSTIC(InCppModule, LocationInfo, \"in module imported here\");\n    CARBON_DIAGNOSTIC(InCppMacroExpansion, LocationInfo,\n                      \"in expansion of macro defined here\");\n    switch (import.kind) {\n      case Carbon::SemIR::DiagnosticLocConverter::ImportLoc::Import:\n        // TODO: Include the library name in the note.\n        context_fn(import.loc, InImport);\n        break;\n      case Carbon::SemIR::DiagnosticLocConverter::ImportLoc::CppInclude:\n        // TODO: Include the file name in the note.\n        context_fn(import.loc, InCppInclude);\n        break;\n      case Carbon::SemIR::DiagnosticLocConverter::ImportLoc::CppModuleImport:\n        // TODO: Include the module name in the note.\n        context_fn(import.loc, InCppModule);\n        break;\n      case Carbon::SemIR::DiagnosticLocConverter::ImportLoc::CppMacroExpansion:\n        // TODO: Include the macro name in the note.\n        context_fn(import.loc, InCppMacroExpansion);\n        break;\n    }\n  }\n\n  // Use the token when possible, but -1 is the default value.\n  auto last_offset = -1;\n  if (last_token_.has_value()) {\n    last_offset = sem_ir_->parse_tree().tokens().GetByteOffset(last_token_);\n  }\n\n  // When the diagnostic is in the same file, we use the last possible offset;\n  // otherwise, we ignore the offset because it's probably in that file.\n  if (converted.loc.filename == sem_ir_->filename()) {\n    converted.last_byte_offset =\n        std::max(converted.last_byte_offset, last_offset);\n  } else {\n    converted.last_byte_offset = last_offset;\n  }\n\n  return converted;\n}\n\nauto DiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any {\n  if (auto* library_name_id = llvm::any_cast<SemIR::LibraryNameId>(&arg)) {\n    std::string library_name;\n    if (*library_name_id == SemIR::LibraryNameId::Default) {\n      library_name = \"default library\";\n    } else if (!library_name_id->has_value()) {\n      library_name = \"library <none>\";\n    } else {\n      RawStringOstream stream;\n      stream << \"library \\\"\"\n             << sem_ir_->string_literal_values().Get(\n                    library_name_id->AsStringLiteralValueId())\n             << \"\\\"\";\n      library_name = stream.TakeStr();\n    }\n    return library_name;\n  }\n  if (auto* name_id = llvm::any_cast<SemIR::NameId>(&arg)) {\n    return sem_ir_->names().GetFormatted(*name_id).str();\n  }\n  if (auto* type_of_expr = llvm::any_cast<TypeOfInstId>(&arg)) {\n    if (!type_of_expr->inst_id.has_value()) {\n      return \"<none>\";\n    }\n    // TODO: Where possible, produce a better description of the type based on\n    // the expression.\n    return \"`\" +\n           StringifyConstantInst(\n               *sem_ir_,\n               sem_ir_->types().GetTypeInstId(\n                   sem_ir_->insts().Get(type_of_expr->inst_id).type_id())) +\n           \"`\";\n  }\n  if (auto* expr = llvm::any_cast<InstIdAsConstant>(&arg)) {\n    return \"`\" + StringifyConstantInst(*sem_ir_, expr->inst_id) + \"`\";\n  }\n  if (auto* type_expr = llvm::any_cast<InstIdAsRawType>(&arg)) {\n    return StringifyConstantInst(*sem_ir_, type_expr->inst_id);\n  }\n  if (auto* type = llvm::any_cast<TypeIdAsRawType>(&arg)) {\n    return StringifyConstantInst(*sem_ir_,\n                                 sem_ir_->types().GetTypeInstId(type->type_id));\n  }\n  if (auto* type_id = llvm::any_cast<SemIR::TypeId>(&arg)) {\n    return \"`\" +\n           StringifyConstantInst(*sem_ir_,\n                                 sem_ir_->types().GetTypeInstId(*type_id)) +\n           \"`\";\n  }\n  if (auto* facet_type_id = llvm::any_cast<SemIR::FacetTypeId>(&arg)) {\n    return \"`\" + StringifyFacetType(*sem_ir_, *facet_type_id) + \"`\";\n  }\n  if (auto* specific_id = llvm::any_cast<SemIR::SpecificId>(&arg)) {\n    return \"`\" + StringifySpecific(*sem_ir_, *specific_id) + \"`\";\n  }\n  if (auto* typed_int = llvm::any_cast<TypedInt>(&arg)) {\n    return llvm::APSInt(typed_int->value,\n                        !sem_ir_->types().IsSignedInt(typed_int->type));\n  }\n  if (auto* real_id = llvm::any_cast<RealId>(&arg)) {\n    RawStringOstream out;\n    sem_ir_->reals().Get(*real_id).Print(out);\n    return out.TakeStr();\n  }\n  if (auto* specific_interface =\n          llvm::any_cast<SemIR::SpecificInterface>(&arg)) {\n    return StringifySpecificInterface(*sem_ir_, *specific_interface);\n  }\n  if (auto* specific_interface_id =\n          llvm::any_cast<SemIR::SpecificInterfaceId>(&arg)) {\n    auto specific_interface =\n        sem_ir_->specific_interfaces().Get(*specific_interface_id);\n    return \"`\" + StringifySpecificInterface(*sem_ir_, specific_interface) + \"`\";\n  }\n  if (auto* specific_interface_raw =\n          llvm::any_cast<SpecificInterfaceIdAsRawType>(&arg)) {\n    auto specific_interface = sem_ir_->specific_interfaces().Get(\n        specific_interface_raw->specific_interface_id);\n    return StringifySpecificInterface(*sem_ir_, specific_interface);\n  }\n  return DiagnosticEmitterBase::ConvertArg(arg);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/diagnostic_emitter.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_EMITTER_H_\n#define CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_EMITTER_H_\n\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/lex/token_index.h\"\n#include \"toolchain/sem_ir/diagnostic_loc_converter.h\"\n\nnamespace Carbon::Check {\n\n// Handles the transformation of a SemIR::LocId to a DiagnosticLoc.\nclass DiagnosticEmitter : public DiagnosticEmitterBase {\n public:\n  // `consumer`, `tree_and_subtrees_getters`, and `sem_ir` must be non-null.\n  explicit DiagnosticEmitter(\n      Diagnostics::Consumer* consumer,\n      const Parse::GetTreeAndSubtreesStore* tree_and_subtrees_getters,\n      const SemIR::File* sem_ir)\n      : DiagnosticEmitterBase(consumer),\n        sem_ir_(sem_ir),\n        loc_converter_(tree_and_subtrees_getters, sem_ir) {}\n\n  // If a byte offset is past the current last byte offset, advances forward.\n  // Earlier offsets are ignored.\n  auto AdvanceToken(Lex::TokenIndex token) -> void {\n    last_token_ = std::max(last_token_, token);\n  }\n\n protected:\n  // Implements argument conversions for supported check-phase arguments.\n  auto ConvertArg(llvm::Any arg) const -> llvm::Any override;\n\n  // Implements `DiagnosticConverter::ConvertLoc`. Adds context for any imports\n  // used in the current SemIR to get to the underlying code.\n  //\n  // For the last byte offset, this uses `last_token_` exclusively for imported\n  // locations, or `loc` if it's in the same file and (for whatever reason)\n  // later.\n  auto ConvertLoc(LocIdForDiagnostics loc_id, ContextFnT context_fn) const\n      -> Diagnostics::ConvertedLoc override;\n\n private:\n  // The current SemIR being processed.\n  const SemIR::File* sem_ir_;\n\n  // Converter for locations.\n  SemIR::DiagnosticLocConverter loc_converter_;\n\n  // The last token encountered during processing.\n  Lex::TokenIndex last_token_ = Lex::TokenIndex::None;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_EMITTER_H_\n"
  },
  {
    "path": "toolchain/check/diagnostic_helpers.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_HELPERS_H_\n#define CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_HELPERS_H_\n\n#include <concepts>\n\n#include \"llvm/ADT/APSInt.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// The `DiagnosticEmitterBase` is templated on this type so that\n// diagnostics can be passed an `InstId` as a location, without having to\n// explicitly construct a `LocId` from it first.\nclass LocIdForDiagnostics {\n public:\n  // Constructs a token-only location for a diagnostic.\n  //\n  // This means the displayed location will include only the location's specific\n  // parse node, instead of also including its descendants.\n  static auto TokenOnly(Parse::NodeId node_id) -> LocIdForDiagnostics {\n    return LocIdForDiagnostics(SemIR::LocId(node_id), true);\n  }\n\n  template <typename LocT>\n    requires std::constructible_from<SemIR::LocId, LocT>\n  explicit(false) LocIdForDiagnostics(LocT loc_id)\n      : LocIdForDiagnostics(SemIR::LocId(loc_id), false) {}\n\n  auto loc_id() const -> SemIR::LocId { return loc_id_; }\n\n  auto is_token_only() const -> bool { return is_token_only_; }\n\n private:\n  explicit LocIdForDiagnostics(SemIR::LocId loc_id, bool is_token_only)\n      : loc_id_(loc_id), is_token_only_(is_token_only) {}\n\n  SemIR::LocId loc_id_;\n  bool is_token_only_;\n};\n\n// We define the emitter separately for dependencies, so only provide a base\n// here.\nusing DiagnosticEmitterBase = Diagnostics::Emitter<LocIdForDiagnostics>;\n\nusing DiagnosticBuilder = DiagnosticEmitterBase::Builder;\nusing DiagnosticContextBuilder = DiagnosticEmitterBase::ContextBuilder;\n\n// A function that adds a Context message for a diagnostic.\nusing DiagnosticContextFn =\n    llvm::function_ref<auto(DiagnosticContextBuilder&)->void>;\n\n// An expression with a constant value, for rendering in a diagnostic. The\n// diagnostic rendering will include enclosing \"`\"s.\nstruct InstIdAsConstant {\n  using DiagnosticType = Diagnostics::TypeInfo<std::string>;\n\n  explicit(false) InstIdAsConstant(SemIR::InstId inst_id) : inst_id(inst_id) {}\n\n  SemIR::InstId inst_id;\n};\n\n// An expression whose type should be rendered in a diagnostic. The diagnostic\n// rendering will include enclosing \"`\"s, and may also include extra information\n// about the type if it might otherwise be ambiguous or context-dependent, such\n// as the targets of aliases used in the type.\n//\n// TODO: Include such additional information where relevant. For example:\n// \"`StdString` (aka `Cpp.std.basic_string(Char)`)\".\n//\n// This should be used instead of `TypeId` as a diagnostic argument wherever\n// possible, because we should eventually be able to produce a sugared type name\n// in this case, whereas a `TypeId` will render as a canonical type.\nstruct TypeOfInstId {\n  using DiagnosticType = Diagnostics::TypeInfo<std::string>;\n\n  explicit(false) TypeOfInstId(SemIR::InstId inst_id) : inst_id(inst_id) {}\n\n  SemIR::InstId inst_id;\n};\n\n// A type expression, for rendering in a diagnostic. The diagnostic rendering\n// will include enclosing \"`\"s, and may also include extra information about the\n// type if it would otherwise be ambiguous.\n//\n// TODO: Include such additional information where relevant.\n//\n// This should be used when the source expression used to construct a type is\n// available.\n//\n// Note that this is currently an alias for InstIdAsConstant. However, using\n// InstIdAsType is clearer when defining CARBON_DIAGNOSTICs, and we may wish to\n// distinguish type arguments in diagnostics from more general constants in some\n// way in the future.\nusing InstIdAsType = InstIdAsConstant;\n\n// A type expression, for rendering in a diagnostic as a raw type. When\n// formatting as a raw type in a diagnostic, the type will be formatted as a\n// simple Carbon expression, without enclosing \"`\"s. Once we start including\n// extra information about types, such annotations will also not be included for\n// raw types.\n//\n// This is intended for cases where the type is part of a larger syntactic\n// construct in a diagnostic, such as \"redefinition of `impl {0} as {1}`\".\nstruct InstIdAsRawType {\n  using DiagnosticType = Diagnostics::TypeInfo<std::string>;\n\n  explicit(false) InstIdAsRawType(SemIR::InstId inst_id) : inst_id(inst_id) {}\n\n  SemIR::InstId inst_id;\n};\n\n// A type value for rendering in a diagnostic without enclosing \"`\"s. See\n// `InstIdAsRawType` for details on raw type formatting.\n//\n// As with `TypeId`, this should be avoided as a diagnostic argument where\n// possible, because it can't be formatted with syntactic sugar such as aliases\n// that describe how the type was written.\nstruct TypeIdAsRawType {\n  using DiagnosticType = Diagnostics::TypeInfo<std::string>;\n\n  explicit(false) TypeIdAsRawType(SemIR::TypeId type_id) : type_id(type_id) {}\n\n  SemIR::TypeId type_id;\n};\n\n// An integer value together with its type. The type is used to determine how to\n// format the value in diagnostics.\nstruct TypedInt {\n  using DiagnosticType = Diagnostics::TypeInfo<llvm::APSInt>;\n\n  SemIR::TypeId type;\n  llvm::APInt value;\n};\n\nstruct SpecificInterfaceIdAsRawType {\n  using DiagnosticType = Diagnostics::TypeInfo<std::string>;\n\n  explicit(false) SpecificInterfaceIdAsRawType(\n      SemIR::SpecificInterfaceId specific_interface_id)\n      : specific_interface_id(specific_interface_id) {}\n\n  SemIR::SpecificInterfaceId specific_interface_id;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_HELPERS_H_\n"
  },
  {
    "path": "toolchain/check/dump.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n// This library contains functions to assist dumping objects to stderr during\n// interactive debugging. Functions named `Dump` are intended for direct use by\n// developers, and should use overload resolution to determine which will be\n// invoked. The debugger should do namespace resolution automatically. For\n// example:\n//\n// - lldb: `expr Dump(context, id)`\n// - gdb: `call Dump(context, id)`\n\n#ifndef NDEBUG\n\n#include \"toolchain/lex/dump.h\"\n\n#include <string>\n\n#include \"common/check.h\"\n#include \"common/raw_string_ostream.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/lex/tokenized_buffer.h\"\n#include \"toolchain/parse/dump.h\"\n#include \"toolchain/parse/tree.h\"\n#include \"toolchain/sem_ir/dump.h\"\n#include \"toolchain/sem_ir/file.h\"\n\nnamespace Carbon::Check {\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context, Lex::TokenIndex token)\n    -> std::string {\n  return Parse::Dump(context.parse_tree(), token);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context, Parse::NodeId node_id)\n    -> std::string {\n  return Parse::Dump(context.parse_tree(), node_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::ClassId class_id) -> std::string {\n  return SemIR::Dump(context.sem_ir(), class_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::ConstantId const_id) -> std::string {\n  return SemIR::Dump(context.sem_ir(), const_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::EntityNameId entity_name_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), entity_name_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::FacetTypeId facet_type_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), facet_type_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::FunctionId function_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), function_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::GenericId generic_id) -> std::string {\n  return SemIR::Dump(context.sem_ir(), generic_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(\n    const Context& context,\n    SemIR::IdentifiedFacetTypeId identified_facet_type_id) -> std::string {\n  return SemIR::Dump(context.sem_ir(), identified_facet_type_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::ImplId impl_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), impl_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::InstBlockId inst_block_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), inst_block_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::InstId inst_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), inst_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::InterfaceId interface_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), interface_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::LocId loc_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), loc_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::NameId name_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), name_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::NameScopeId name_scope_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), name_scope_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::NamedConstraintId named_constraint_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), named_constraint_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(\n    const Context& context, SemIR::RequireImplsBlockId require_impls_block_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), require_impls_block_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::RequireImplsId require_impls_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), require_impls_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context,\n                                  SemIR::SpecificId specific_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), specific_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(\n    const Context& context, SemIR::SpecificInterfaceId specific_interface_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), specific_interface_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(\n    const Context& context, SemIR::StructTypeFieldsId struct_type_fields_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), struct_type_fields_id);\n}\n\nLLVM_DUMP_METHOD static auto Dump(const Context& context, SemIR::TypeId type_id)\n    -> std::string {\n  return SemIR::Dump(context.sem_ir(), type_id);\n}\n\n}  // namespace Carbon::Check\n\n#endif  // NDEBUG\n"
  },
  {
    "path": "toolchain/check/eval.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/eval.h\"\n\n#include <algorithm>\n#include <array>\n#include <optional>\n#include <utility>\n\n#include \"common/raw_string_ostream.h\"\n#include \"llvm/Support/ConvertUTF.h\"\n#include \"toolchain/base/canonical_value_store.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/action.h\"\n#include \"toolchain/check/cpp/constant.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/eval_inst.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/sem_ir/builtin_function_kind.h\"\n#include \"toolchain/sem_ir/constant.h\"\n#include \"toolchain/sem_ir/facet_type_info.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/generic.h\"\n#include \"toolchain/sem_ir/id_kind.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/impl.h\"\n#include \"toolchain/sem_ir/inst_categories.h\"\n#include \"toolchain/sem_ir/inst_kind.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nnamespace {\n// Information about an eval block of a specific that we are currently building.\nstruct SpecificEvalInfo {\n  // The region within the specific whose eval block we are building.\n  SemIR::GenericInstIndex::Region region;\n  // The work-in-progress contents of the eval block.\n  llvm::ArrayRef<SemIR::InstId> values;\n};\n\n// Information about a local scope that we're currently evaluating, such as a\n// call to an `eval fn`. In this scope, instructions with runtime phase may\n// locally have constant values, for example values that are computed from the\n// arguments to the call. These values are specific to the current evaluation\n// and not global properties of the instruction.\nstruct LocalEvalInfo {\n  // A mapping from instructions with runtime phase within the local scope to\n  // the values that they have in the current evaluation. This is populated as\n  // the local scope is evaluated, and due to control flow, the same instruction\n  // may have its value set multiple times. This map tracks the most recent\n  // value that the instruction had, which is the one that a reference to it in\n  // well-formed SemIR should refer to.\n  Map<SemIR::InstId, SemIR::ConstantId>* locals;\n};\n\n// Information about the context within which we are performing evaluation.\n// `context` must not be null.\nclass EvalContext {\n public:\n  explicit EvalContext(\n      Context* context, SemIR::LocId fallback_loc_id,\n      SemIR::SpecificId specific_id = SemIR::SpecificId::None,\n      std::optional<SpecificEvalInfo> specific_eval_info = std::nullopt)\n      : context_(context),\n        fallback_loc_id_(fallback_loc_id),\n        specific_id_(specific_id),\n        specific_eval_info_(specific_eval_info) {}\n\n  EvalContext(const EvalContext&) = delete;\n  auto operator=(const EvalContext&) -> EvalContext& = delete;\n\n  // Gets the location to use for diagnostics if a better location is\n  // unavailable.\n  // TODO: This is also sometimes unavailable.\n  auto fallback_loc_id() const -> SemIR::LocId { return fallback_loc_id_; }\n\n  // Returns a location to use to point at an instruction in a diagnostic, given\n  // a list of instructions that might have an attached location. This is the\n  // location of the first instruction in the list that has a location if there\n  // is one, and otherwise the fallback location.\n  auto GetDiagnosticLoc(llvm::ArrayRef<SemIR::InstId> inst_ids)\n      -> SemIR::LocId {\n    for (auto inst_id : inst_ids) {\n      if (inst_id.has_value()) {\n        auto loc_id = context_->insts().GetCanonicalLocId(inst_id);\n        if (loc_id.has_value()) {\n          return loc_id;\n        }\n      }\n    }\n    return fallback_loc_id_;\n  }\n\n  // Gets the value of the specified compile-time binding in this context.\n  // Returns `None` if the value is not fixed in this context.\n  auto GetCompileTimeBindValue(SemIR::CompileTimeBindIndex bind_index)\n      -> SemIR::ConstantId {\n    if (!bind_index.has_value() || !specific_id_.has_value()) {\n      return SemIR::ConstantId::None;\n    }\n\n    const auto& specific = specifics().Get(specific_id_);\n    auto args = inst_blocks().Get(specific.args_id);\n\n    // Bindings past the ones with known arguments can appear as local\n    // bindings of entities declared within this generic.\n    if (static_cast<size_t>(bind_index.index) >= args.size()) {\n      return SemIR::ConstantId::None;\n    }\n    return constant_values().Get(args[bind_index.index]);\n  }\n\n  // Given information about a symbolic constant, determine its value in the\n  // currently-being-evaluated eval block, if it refers to that eval block. If\n  // we can't find a value in this way, returns `None`.\n  auto GetInEvaluatedSpecific(const SemIR::SymbolicConstant& symbolic_info)\n      -> SemIR::ConstantId {\n    if (!specific_eval_info_ || !symbolic_info.index.has_value()) {\n      return SemIR::ConstantId::None;\n    }\n\n    CARBON_CHECK(\n        symbolic_info.generic_id == specifics().Get(specific_id_).generic_id,\n        \"Instruction has constant operand in wrong generic\");\n    if (symbolic_info.index.region() != specific_eval_info_->region) {\n      return SemIR::ConstantId::None;\n    }\n\n    auto inst_id = specific_eval_info_->values[symbolic_info.index.index()];\n    CARBON_CHECK(inst_id.has_value(),\n                 \"Forward reference in eval block: index {0} referenced \"\n                 \"before evaluation\",\n                 symbolic_info.index.index());\n    return constant_values().Get(inst_id);\n  }\n\n  // Gets the constant value of the specified instruction in this context.\n  auto GetConstantValue(SemIR::InstId inst_id) -> SemIR::ConstantId {\n    auto const_id = constant_values().GetAttached(inst_id);\n\n    // While evaluating a function, map from local non-constant instructions to\n    // their earlier-evaluated values.\n    if (!const_id.is_constant()) {\n      if (local_eval_info_) {\n        if (auto local = local_eval_info_->locals->Lookup(inst_id)) {\n          return local.value();\n        }\n      }\n      return const_id;\n    }\n\n    if (!const_id.is_symbolic()) {\n      return const_id;\n    }\n\n    // While resolving a specific, map from previous instructions in the eval\n    // block into their evaluated values. These values won't be present on the\n    // specific itself yet, so `GetConstantValueInSpecific` won't be able to\n    // find them.\n    const auto& symbolic_info = constant_values().GetSymbolicConstant(const_id);\n    if (auto eval_block_const_id = GetInEvaluatedSpecific(symbolic_info);\n        eval_block_const_id.has_value()) {\n      return eval_block_const_id;\n    }\n\n    return GetConstantValueInSpecific(sem_ir(), specific_id_, inst_id);\n  }\n\n  // Gets the type of the specified instruction in this context.\n  auto GetTypeOfInst(SemIR::InstId inst_id) -> SemIR::TypeId {\n    auto type_id = insts().GetAttachedType(inst_id);\n    if (!type_id.is_symbolic()) {\n      return type_id;\n    }\n\n    // While resolving a specific, map from previous instructions in the eval\n    // block into their evaluated values. These values won't be present on the\n    // specific itself yet, so `GetTypeOfInstInSpecific` won't be able to\n    // find them.\n    const auto& symbolic_info =\n        constant_values().GetSymbolicConstant(types().GetConstantId(type_id));\n    if (auto eval_block_const_id = GetInEvaluatedSpecific(symbolic_info);\n        eval_block_const_id.has_value()) {\n      return types().GetTypeIdForTypeConstantId(eval_block_const_id);\n    }\n\n    return GetTypeOfInstInSpecific(sem_ir(), specific_id_, inst_id);\n  }\n\n  auto ints() -> SharedValueStores::IntStore& { return sem_ir().ints(); }\n  auto floats() -> SharedValueStores::FloatStore& { return sem_ir().floats(); }\n  auto entity_names() -> SemIR::EntityNameStore& {\n    return sem_ir().entity_names();\n  }\n  auto functions() -> const SemIR::FunctionStore& {\n    return sem_ir().functions();\n  }\n  auto classes() -> const SemIR::ClassStore& { return sem_ir().classes(); }\n  auto interfaces() -> const SemIR::InterfaceStore& {\n    return sem_ir().interfaces();\n  }\n  auto specific_interfaces() -> SemIR::SpecificInterfaceStore& {\n    return sem_ir().specific_interfaces();\n  }\n  auto facet_types() -> SemIR::FacetTypeInfoStore& {\n    return sem_ir().facet_types();\n  }\n  auto generics() -> const SemIR::GenericStore& { return sem_ir().generics(); }\n  auto specifics() -> const SemIR::SpecificStore& {\n    return sem_ir().specifics();\n  }\n  auto insts() -> const SemIR::InstStore& { return sem_ir().insts(); }\n  auto inst_blocks() -> SemIR::InstBlockStore& {\n    return sem_ir().inst_blocks();\n  }\n\n  // Gets the constant value store. Note that this does not provide the constant\n  // values that should be used from this evaluation context, and so should be\n  // used with caution.\n  auto constant_values() -> const SemIR::ConstantValueStore& {\n    return sem_ir().constant_values();\n  }\n\n  // Gets the types store. Note that this does not provide the type values that\n  // should be used from this evaluation context, and so should be used with\n  // caution.\n  auto types() -> const SemIR::TypeStore& { return sem_ir().types(); }\n\n  auto context() -> Context& { return *context_; }\n\n  auto sem_ir() -> SemIR::File& { return context().sem_ir(); }\n\n  auto emitter() -> DiagnosticEmitterBase& { return context().emitter(); }\n\n protected:\n  explicit EvalContext(Context* context, SemIR::LocId fallback_loc_id,\n                       SemIR::SpecificId specific_id,\n                       std::optional<LocalEvalInfo> local_eval_info)\n      : context_(context),\n        fallback_loc_id_(fallback_loc_id),\n        specific_id_(specific_id),\n        local_eval_info_(local_eval_info) {}\n\n  // Returns the current locals map, which is assumed to exist.\n  auto locals() -> Map<SemIR::InstId, SemIR::ConstantId>& {\n    return *local_eval_info_->locals;\n  }\n\n private:\n  // The type-checking context in which we're performing evaluation.\n  Context* context_;\n  // The location to use for diagnostics when a better location isn't available.\n  SemIR::LocId fallback_loc_id_;\n  // The specific that we are evaluating within.\n  SemIR::SpecificId specific_id_;\n  // If we are currently evaluating an eval block for `specific_id_`,\n  // information about that evaluation.\n  std::optional<SpecificEvalInfo> specific_eval_info_;\n  // If we are currently evaluating within a local scope, values of local\n  // instructions that have already been evaluated. This is here rather than in\n  // `FunctionEvalContext` so we can reference it from `GetConstantValue`.\n  std::optional<LocalEvalInfo> local_eval_info_;\n};\n}  // namespace\n\nnamespace {\n// The evaluation phase for an expression, computed by evaluation. These are\n// ordered so that the phase of an expression is the numerically highest phase\n// of its constituent evaluations. Note that an expression with any runtime\n// component is known to have Runtime phase even if it involves an evaluation\n// with UnknownDueToError phase.\nenum class Phase : uint8_t {\n  // Value could be entirely and concretely computed.\n  Concrete,\n  // Evaluation phase is symbolic because the expression involves specifically a\n  // reference to `.Self`.\n  PeriodSelfSymbolic,\n  // Evaluation phase is symbolic because the expression involves a reference to\n  // a non-template symbolic binding other than `.Self`.\n  CheckedSymbolic,\n  // Evaluation phase is symbolic because the expression involves a reference to\n  // a template parameter, or otherwise depends on something template dependent.\n  // The expression might also reference non-template symbolic bindings.\n  TemplateSymbolic,\n  // The evaluation phase is unknown because evaluation encountered an\n  // already-diagnosed semantic or syntax error. This is treated as being\n  // potentially constant, but with an unknown phase.\n  UnknownDueToError,\n  // The expression has runtime phase because of a non-constant subexpression.\n  Runtime,\n};\n}  // namespace\n\nstatic auto IsConstantOrError(Phase phase) -> bool {\n  return phase != Phase::Runtime;\n}\n\n// Gets the phase in which the value of a constant will become available.\nstatic auto GetPhase(const SemIR::ConstantValueStore& constant_values,\n                     SemIR::ConstantId constant_id) -> Phase {\n  if (!constant_id.is_constant()) {\n    return Phase::Runtime;\n  } else if (constant_id == SemIR::ErrorInst::ConstantId) {\n    return Phase::UnknownDueToError;\n  }\n  switch (constant_values.GetDependence(constant_id)) {\n    case SemIR::ConstantDependence::None:\n      return Phase::Concrete;\n    case SemIR::ConstantDependence::PeriodSelf:\n      return Phase::PeriodSelfSymbolic;\n    case SemIR::ConstantDependence::Checked:\n      return Phase::CheckedSymbolic;\n    case SemIR::ConstantDependence::Template:\n      return Phase::TemplateSymbolic;\n  }\n}\n\n// Returns the later of two phases.\nstatic auto LatestPhase(Phase a, Phase b) -> Phase {\n  return static_cast<Phase>(\n      std::max(static_cast<uint8_t>(a), static_cast<uint8_t>(b)));\n}\n\n// Forms a `constant_id` describing a given evaluation result.\nstatic auto MakeConstantResult(Context& context, SemIR::Inst inst, Phase phase)\n    -> SemIR::ConstantId {\n  switch (phase) {\n    case Phase::Concrete:\n      return context.constants().GetOrAdd(inst,\n                                          SemIR::ConstantDependence::None);\n    case Phase::PeriodSelfSymbolic:\n      return context.constants().GetOrAdd(\n          inst, SemIR::ConstantDependence::PeriodSelf);\n    case Phase::CheckedSymbolic:\n      return context.constants().GetOrAdd(inst,\n                                          SemIR::ConstantDependence::Checked);\n    case Phase::TemplateSymbolic:\n      return context.constants().GetOrAdd(inst,\n                                          SemIR::ConstantDependence::Template);\n    case Phase::UnknownDueToError:\n      return SemIR::ErrorInst::ConstantId;\n    case Phase::Runtime:\n      return SemIR::ConstantId::NotConstant;\n  }\n}\n\n// Forms a `constant_id` describing why an evaluation was not constant.\nstatic auto MakeNonConstantResult(Phase phase) -> SemIR::ConstantId {\n  return phase == Phase::UnknownDueToError ? SemIR::ErrorInst::ConstantId\n                                           : SemIR::ConstantId::NotConstant;\n}\n\n// Forms a constant for an empty tuple value.\nstatic auto MakeEmptyTupleResult(EvalContext& eval_context)\n    -> SemIR::ConstantId {\n  auto type_id = GetTupleType(eval_context.context(), {});\n  return MakeConstantResult(\n      eval_context.context(),\n      SemIR::TupleValue{.type_id = type_id,\n                        .elements_id = SemIR::InstBlockId::Empty},\n      Phase::Concrete);\n}\n\n// Converts a bool value into a ConstantId.\nstatic auto MakeBoolResult(Context& context, SemIR::TypeId bool_type_id,\n                           bool result) -> SemIR::ConstantId {\n  return MakeConstantResult(\n      context,\n      SemIR::BoolLiteral{.type_id = bool_type_id,\n                         .value = SemIR::BoolValue::From(result)},\n      Phase::Concrete);\n}\n\n// Converts an APInt value into a ConstantId.\nstatic auto MakeIntResult(Context& context, SemIR::TypeId type_id,\n                          bool is_signed, llvm::APInt value)\n    -> SemIR::ConstantId {\n  CARBON_CHECK(is_signed == context.types().IsSignedInt(type_id));\n  auto result = is_signed ? context.ints().AddSigned(std::move(value))\n                          : context.ints().AddUnsigned(std::move(value));\n  return MakeConstantResult(\n      context, SemIR::IntValue{.type_id = type_id, .int_id = result},\n      Phase::Concrete);\n}\n\n// Converts an APFloat value into a ConstantId.\nstatic auto MakeFloatResult(Context& context, SemIR::TypeId type_id,\n                            llvm::APFloat value) -> SemIR::ConstantId {\n  auto result = context.floats().Add(std::move(value));\n  return MakeConstantResult(\n      context, SemIR::FloatValue{.type_id = type_id, .float_id = result},\n      Phase::Concrete);\n}\n\n// Creates a FacetType constant.\nstatic auto MakeFacetTypeResult(Context& context,\n                                const SemIR::FacetTypeInfo& info, Phase phase)\n    -> SemIR::ConstantId {\n  SemIR::FacetTypeId facet_type_id = context.facet_types().Add(info);\n  return MakeConstantResult(context,\n                            SemIR::FacetType{.type_id = SemIR::TypeType::TypeId,\n                                             .facet_type_id = facet_type_id},\n                            phase);\n}\n\n// `GetConstantValue` checks to see whether the provided ID describes a value\n// with constant phase, and if so, returns the corresponding constant value.\n// Overloads are provided for different kinds of ID. `RequireConstantValue` does\n// the same, but produces an error diagnostic if the input is not constant.\n\n// AbsoluteInstId can not have its values substituted, so this overload is\n// deleted. This prevents conversion to InstId.\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::AbsoluteInstId inst_id, Phase* phase)\n    -> SemIR::InstId = delete;\n\n// If the given instruction is constant, returns its constant value.\nstatic auto GetConstantValue(EvalContext& eval_context, SemIR::InstId inst_id,\n                             Phase* phase) -> SemIR::InstId {\n  if (!inst_id.has_value()) {\n    return SemIR::InstId::None;\n  }\n  auto const_id = eval_context.GetConstantValue(inst_id);\n  *phase =\n      LatestPhase(*phase, GetPhase(eval_context.constant_values(), const_id));\n  return eval_context.constant_values().GetInstId(const_id);\n}\n\n// Issue a suitable diagnostic for an instruction that evaluated to a\n// non-constant value but was required to evaluate to a constant.\nstatic auto DiagnoseNonConstantValue(EvalContext& eval_context,\n                                     SemIR::InstId inst_id) -> void {\n  if (inst_id != SemIR::ErrorInst::InstId) {\n    CARBON_DIAGNOSTIC(EvalRequiresConstantValue, Error,\n                      \"expression is runtime; expected constant\");\n    eval_context.emitter().Emit(eval_context.GetDiagnosticLoc({inst_id}),\n                                EvalRequiresConstantValue);\n  }\n}\n\n// Gets a constant value for an `inst_id`, diagnosing when the input is not a\n// constant value.\nstatic auto RequireConstantValue(EvalContext& eval_context,\n                                 SemIR::InstId inst_id, Phase* phase)\n    -> SemIR::InstId {\n  if (!inst_id.has_value()) {\n    return SemIR::InstId::None;\n  }\n  auto const_id = eval_context.GetConstantValue(inst_id);\n  *phase =\n      LatestPhase(*phase, GetPhase(eval_context.constant_values(), const_id));\n  if (const_id.is_constant()) {\n    return eval_context.constant_values().GetInstId(const_id);\n  }\n\n  DiagnoseNonConstantValue(eval_context, inst_id);\n  *phase = Phase::UnknownDueToError;\n  return SemIR::ErrorInst::InstId;\n}\n\n// If the given instruction is constant, returns its constant value. Otherwise,\n// produces an error diagnostic. When determining the phase of the result,\n// ignore any dependence on `.Self`.\n//\n// This is used when evaluating facet types, for which `where` expressions using\n// `.Self` should not be considered symbolic\n// - `Interface where .Self impls I and .A = bool` -> concrete\n// - `T:! type` ... `Interface where .A = T` -> symbolic, since uses `T` which\n//   is symbolic and not due to `.Self`.\nstatic auto RequireConstantValueIgnoringPeriodSelf(EvalContext& eval_context,\n                                                   SemIR::InstId inst_id,\n                                                   Phase* phase)\n    -> SemIR::InstId {\n  if (!inst_id.has_value()) {\n    return SemIR::InstId::None;\n  }\n  Phase constant_phase = *phase;\n  auto const_inst_id =\n      RequireConstantValue(eval_context, inst_id, &constant_phase);\n  // Since LatestPhase(x, Phase::Concrete) == x, this is equivalent to replacing\n  // Phase::PeriodSelfSymbolic with Phase::Concrete.\n  if (constant_phase != Phase::PeriodSelfSymbolic) {\n    *phase = LatestPhase(*phase, constant_phase);\n  }\n  return const_inst_id;\n}\n\n// Gets a constant value for an `inst_id`, diagnosing when the input is not\n// constant, and CHECKing that it is concrete. Should only be used in contexts\n// where non-concrete constants cannot appear.\nstatic auto CheckConcreteValue(EvalContext& eval_context, SemIR::InstId inst_id)\n    -> SemIR::InstId {\n  auto phase = Phase::Concrete;\n  auto value_inst_id = RequireConstantValue(eval_context, inst_id, &phase);\n  if (phase == Phase::UnknownDueToError) {\n    return SemIR::ErrorInst::InstId;\n  }\n  CARBON_CHECK(phase == Phase::Concrete,\n               \"expression evaluates to symbolic value {0}\",\n               eval_context.insts().Get(value_inst_id));\n  return value_inst_id;\n}\n\n// Find the instruction that the given instruction instantiates to, and return\n// that.\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::MetaInstId inst_id, Phase* phase)\n    -> SemIR::MetaInstId {\n  Phase inner_phase = Phase::Concrete;\n  if (auto const_inst_id =\n          GetConstantValue(eval_context, SemIR::InstId(inst_id), &inner_phase);\n      const_inst_id.has_value()) {\n    // The instruction has a constant value. Use that as the operand of the\n    // action.\n    *phase = LatestPhase(*phase, inner_phase);\n    return const_inst_id;\n  }\n\n  // If this instruction is splicing in an action result, that action result is\n  // our operand.\n  if (auto splice = eval_context.insts().TryGetAs<SemIR::SpliceInst>(inst_id)) {\n    if (auto spliced_inst_id =\n            GetConstantValue(eval_context, splice->inst_id, phase);\n        spliced_inst_id.has_value()) {\n      if (auto inst_value_id = eval_context.insts().TryGetAs<SemIR::InstValue>(\n              spliced_inst_id)) {\n        return inst_value_id->inst_id;\n      }\n    }\n  }\n\n  // Otherwise, this is a normal instruction.\n  if (OperandIsDependent(eval_context.context(), inst_id)) {\n    *phase = LatestPhase(*phase, Phase::TemplateSymbolic);\n  }\n  return inst_id;\n}\n\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::TypeInstId inst_id, Phase* phase)\n    -> SemIR::TypeInstId {\n  // The input instruction is a TypeInstId, and eval does not change concrete\n  // types (like TypeType which TypeInstId implies), so the result is also a\n  // valid TypeInstId.\n  return SemIR::TypeInstId::UnsafeMake(GetConstantValue(\n      eval_context, static_cast<SemIR::InstId>(inst_id), phase));\n}\n\n// Explicitly discard a `DestInstId`, because we should not be using the\n// destination as part of evaluation.\nstatic auto GetConstantValue(EvalContext& /*eval_context*/,\n                             SemIR::DestInstId /*inst_id*/, Phase* /*phase*/)\n    -> SemIR::DestInstId {\n  return SemIR::InstId::None;\n}\n\n// Given an instruction whose type may refer to a generic parameter, returns the\n// corresponding type in the evaluation context.\n//\n// If the `InstId` is not provided, the instruction is assumed to be new and\n// therefore unattached, and the type of the given instruction is returned\n// unchanged, but the phase is still updated.\nstatic auto GetTypeOfInst(EvalContext& eval_context, SemIR::InstId inst_id,\n                          SemIR::Inst inst, Phase* phase) -> SemIR::TypeId {\n  auto type_id = inst_id.has_value() ? eval_context.GetTypeOfInst(inst_id)\n                                     : inst.type_id();\n  *phase = LatestPhase(*phase,\n                       GetPhase(eval_context.constant_values(),\n                                eval_context.types().GetConstantId(type_id)));\n  return type_id;\n}\n\n// AbsoluteInstBlockId can not have its values substituted, so this overload is\n// deleted. This prevents conversion to InstBlockId.\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::AbsoluteInstBlockId inst_block_id,\n                             Phase* phase) -> SemIR::InstBlockId = delete;\n\n// If the given instruction block contains only constants, returns a\n// corresponding block of those values.\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::InstBlockId inst_block_id, Phase* phase)\n    -> SemIR::InstBlockId {\n  if (!inst_block_id.has_value()) {\n    return SemIR::InstBlockId::None;\n  }\n  auto insts = eval_context.inst_blocks().Get(inst_block_id);\n  llvm::SmallVector<SemIR::InstId> const_insts;\n  for (auto inst_id : insts) {\n    auto const_inst_id = GetConstantValue(eval_context, inst_id, phase);\n    if (!const_inst_id.has_value()) {\n      return SemIR::InstBlockId::None;\n    }\n\n    // Once we leave the small buffer, we know the first few elements are all\n    // constant, so it's likely that the entire block is constant. Resize to the\n    // target size given that we're going to allocate memory now anyway.\n    if (const_insts.size() == const_insts.capacity()) {\n      const_insts.reserve(insts.size());\n    }\n\n    const_insts.push_back(const_inst_id);\n  }\n  // TODO: If the new block is identical to the original block, and we know the\n  // old ID was canonical, return the original ID.\n  return eval_context.inst_blocks().AddCanonical(const_insts);\n}\n\n// Compute the constant value of a type block. This may be different from the\n// input type block if we have known generic arguments.\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::StructTypeFieldsId fields_id, Phase* phase)\n    -> SemIR::StructTypeFieldsId {\n  if (!fields_id.has_value()) {\n    return SemIR::StructTypeFieldsId::None;\n  }\n  auto fields = eval_context.context().struct_type_fields().Get(fields_id);\n  llvm::SmallVector<SemIR::StructTypeField> new_fields;\n  for (auto field : fields) {\n    auto new_type_inst_id =\n        GetConstantValue(eval_context, field.type_inst_id, phase);\n    if (!new_type_inst_id.has_value()) {\n      return SemIR::StructTypeFieldsId::None;\n    }\n\n    // Once we leave the small buffer, we know the first few elements are all\n    // constant, so it's likely that the entire block is constant. Resize to the\n    // target size given that we're going to allocate memory now anyway.\n    if (new_fields.size() == new_fields.capacity()) {\n      new_fields.reserve(fields.size());\n    }\n\n    new_fields.push_back(\n        {.name_id = field.name_id, .type_inst_id = new_type_inst_id});\n  }\n  // TODO: If the new block is identical to the original block, and we know the\n  // old ID was canonical, return the original ID.\n  return eval_context.context().struct_type_fields().AddCanonical(new_fields);\n}\n\n// The constant value of a specific is the specific with the corresponding\n// constant values for its arguments.\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::SpecificId specific_id, Phase* phase)\n    -> SemIR::SpecificId {\n  if (!specific_id.has_value()) {\n    return SemIR::SpecificId::None;\n  }\n\n  const auto& specific = eval_context.specifics().Get(specific_id);\n  auto args_id = GetConstantValue(eval_context, specific.args_id, phase);\n  if (!args_id.has_value()) {\n    return SemIR::SpecificId::None;\n  }\n\n  // Generally, when making a new specific, it's done through MakeSpecific(),\n  // which will ensure the declaration is resolved.\n  //\n  // However, the SpecificId returned here is intentionally left without its\n  // declaration resolved. Imported instructions with SpecificIds should not\n  // have the specific's declaration resolved, but other instructions which\n  // include a new SpecificId should.\n  //\n  // The resolving of the specific's declaration will be ensured later when\n  // evaluating the instruction containing the SpecificId.\n  if (args_id == specific.args_id) {\n    return specific_id;\n  }\n  return eval_context.context().specifics().GetOrAdd(specific.generic_id,\n                                                     args_id);\n}\n\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::SpecificInterfaceId specific_interface_id,\n                             Phase* phase) -> SemIR::SpecificInterfaceId {\n  const auto& interface =\n      eval_context.specific_interfaces().Get(specific_interface_id);\n  if (!interface.specific_id.has_value()) {\n    return specific_interface_id;\n  }\n  return eval_context.specific_interfaces().Add(\n      {.interface_id = interface.interface_id,\n       .specific_id =\n           GetConstantValue(eval_context, interface.specific_id, phase)});\n}\n\n// Like `GetConstantValue` but for a `FacetTypeInfo`.\nstatic auto GetConstantFacetTypeInfo(EvalContext& eval_context,\n                                     SemIR::LocId loc_id,\n                                     const SemIR::FacetTypeInfo& orig,\n                                     Phase* phase) -> SemIR::FacetTypeInfo {\n  SemIR::FacetTypeInfo info = {};\n\n  info.extend_constraints.reserve(orig.extend_constraints.size());\n  for (const auto& extend : orig.extend_constraints) {\n    info.extend_constraints.push_back(\n        {.interface_id = extend.interface_id,\n         .specific_id =\n             GetConstantValue(eval_context, extend.specific_id, phase)});\n  }\n\n  info.self_impls_constraints.reserve(orig.self_impls_constraints.size());\n  for (const auto& self_impls : orig.self_impls_constraints) {\n    info.self_impls_constraints.push_back(\n        {.interface_id = self_impls.interface_id,\n         .specific_id =\n             GetConstantValue(eval_context, self_impls.specific_id, phase)});\n  }\n\n  info.extend_named_constraints.reserve(orig.extend_named_constraints.size());\n  for (const auto& extend : orig.extend_named_constraints) {\n    info.extend_named_constraints.push_back(\n        {.named_constraint_id = extend.named_constraint_id,\n         .specific_id =\n             GetConstantValue(eval_context, extend.specific_id, phase)});\n  }\n\n  info.self_impls_named_constraints.reserve(\n      orig.self_impls_named_constraints.size());\n  for (const auto& self_impls : orig.self_impls_named_constraints) {\n    info.self_impls_named_constraints.push_back(\n        {.named_constraint_id = self_impls.named_constraint_id,\n         .specific_id =\n             GetConstantValue(eval_context, self_impls.specific_id, phase)});\n  }\n\n  // Rewrite constraints are resolved first before replacing them with their\n  // canonical instruction, so that in a `WhereExpr` we can work with the\n  // `ImplWitnessAccess` references to `.Self` on the LHS of the constraints\n  // rather than the value of the associated constant they reference.\n  //\n  // This also implies that we may find `ImplWitnessAccessSubstituted`\n  // instructions in the LHS and RHS of these constraints, which are preserved\n  // to maintain them as an unresolved reference to an associated constant, but\n  // which must be handled gracefully during resolution. They will be replaced\n  // with the constant value of the `ImplWitnessAccess` below when they are\n  // substituted with a constant value.\n  info.rewrite_constraints = orig.rewrite_constraints;\n  if (!ResolveFacetTypeRewriteConstraints(eval_context.context(), loc_id,\n                                          info.rewrite_constraints)) {\n    *phase = Phase::UnknownDueToError;\n  }\n\n  for (auto& rewrite : info.rewrite_constraints) {\n    // `where` requirements using `.Self` should not be considered symbolic.\n    auto lhs_id = RequireConstantValueIgnoringPeriodSelf(eval_context,\n                                                         rewrite.lhs_id, phase);\n    auto rhs_id = RequireConstantValueIgnoringPeriodSelf(eval_context,\n                                                         rewrite.rhs_id, phase);\n    rewrite = {.lhs_id = lhs_id, .rhs_id = rhs_id};\n  }\n\n  // TODO: Process other requirements.\n  info.other_requirements = orig.other_requirements;\n\n  info.Canonicalize();\n  return info;\n}\n\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::FacetTypeId facet_type_id, Phase* phase)\n    -> SemIR::FacetTypeId {\n  SemIR::FacetTypeInfo info = GetConstantFacetTypeInfo(\n      eval_context, SemIR::LocId::None,\n      eval_context.facet_types().Get(facet_type_id), phase);\n  return eval_context.facet_types().Add(info);\n}\n\nstatic auto GetConstantValue(EvalContext& eval_context,\n                             SemIR::EntityNameId entity_name_id, Phase* phase)\n    -> SemIR::EntityNameId {\n  const auto& bind_name = eval_context.entity_names().Get(entity_name_id);\n  Phase name_phase;\n  if (bind_name.name_id == SemIR::NameId::PeriodSelf) {\n    name_phase = Phase::PeriodSelfSymbolic;\n  } else if (!bind_name.bind_index().has_value()) {\n    name_phase = Phase::Concrete;\n  } else if (bind_name.is_template) {\n    name_phase = Phase::TemplateSymbolic;\n  } else {\n    name_phase = Phase::CheckedSymbolic;\n  }\n  *phase = LatestPhase(*phase, name_phase);\n  return eval_context.entity_names().MakeCanonical(entity_name_id);\n}\n\n// Replaces the specified field of the given typed instruction with its constant\n// value, if it has constant phase. Returns true on success, false if the value\n// has runtime phase.\ntemplate <typename InstT, typename FieldIdT>\nstatic auto ReplaceFieldWithConstantValue(EvalContext& eval_context,\n                                          InstT* inst, FieldIdT InstT::* field,\n                                          Phase* phase) -> bool {\n  auto unwrapped = GetConstantValue(eval_context, inst->*field, phase);\n  if (!unwrapped.has_value() && (inst->*field).has_value()) {\n    return false;\n  }\n  inst->*field = unwrapped;\n  return IsConstantOrError(*phase);\n}\n\n// Function template that can be called with an argument of type `T`. Used below\n// to detect which overloads of `GetConstantValue` exist.\ntemplate <typename T>\nstatic void Accept(T /*arg*/) {}\n\n// Determines whether a `GetConstantValue` overload exists for a given ID type.\n// Note that we do not check whether `GetConstantValue` is *callable* with a\n// given ID type, because that would use the `InstId` overload for\n// `AbsoluteInstId` and similar wrapper types, which should be left alone.\ntemplate <typename IdT>\nstatic constexpr bool HasGetConstantValueOverload = requires {\n  Accept<auto (*)(EvalContext&, IdT, Phase*)->IdT>(GetConstantValue);\n};\n\nusing ArgHandlerFnT = auto(EvalContext& context, int32_t arg, Phase* phase)\n    -> int32_t;\n\n// Returns the arg handler for an `IdKind`.\ntemplate <typename... Types>\nstatic auto GetArgHandlerFn(TypeEnum<Types...> id_kind) -> ArgHandlerFnT* {\n  static constexpr std::array<ArgHandlerFnT*, SemIR::IdKind::NumValues> Table =\n      {\n          [](EvalContext& eval_context, int32_t arg, Phase* phase) -> int32_t {\n            auto id = SemIR::Inst::FromRaw<Types>(arg);\n            if constexpr (HasGetConstantValueOverload<Types>) {\n              // If we have a custom `GetConstantValue` overload, call it.\n              return SemIR::Inst::ToRaw(\n                  GetConstantValue(eval_context, id, phase));\n            } else {\n              // Otherwise, we assume the value is already constant.\n              return arg;\n            }\n          }...,\n          // Invalid and None handling (ordering-sensitive).\n          [](auto...) -> int32_t { CARBON_FATAL(\"Unexpected invalid IdKind\"); },\n          [](EvalContext& /*context*/, int32_t arg,\n             Phase* /*phase*/) -> int32_t { return arg; },\n      };\n  return Table[id_kind.ToIndex()];\n}\n\n// Given the stored value `arg` of an instruction field and its corresponding\n// kind `kind`, returns the constant value to use for that field, if it has a\n// constant phase. `*phase` is updated to include the new constant value. If\n// the resulting phase is not constant, the returned value is not useful and\n// will typically be `NoneIndex`.\nstatic auto GetConstantValueForArg(EvalContext& eval_context,\n                                   SemIR::Inst::ArgAndKind arg_and_kind,\n                                   Phase* phase) -> int32_t {\n  return GetArgHandlerFn(arg_and_kind.kind())(eval_context,\n                                              arg_and_kind.value(), phase);\n}\n\n// Given an instruction, replaces its operands with their constant values from\n// the specified evaluation context. `*phase` is updated to describe the\n// constant phase of the result. Returns whether `*phase` is a constant phase;\n// if not, `inst` may not be fully updated and should not be used.\nstatic auto ReplaceAllFieldsWithConstantValues(EvalContext& eval_context,\n                                               SemIR::Inst* inst, Phase* phase)\n    -> bool {\n  auto arg0 =\n      GetConstantValueForArg(eval_context, inst->arg0_and_kind(), phase);\n  if (!IsConstantOrError(*phase)) {\n    return false;\n  }\n  auto arg1 =\n      GetConstantValueForArg(eval_context, inst->arg1_and_kind(), phase);\n  if (!IsConstantOrError(*phase)) {\n    return false;\n  }\n  inst->SetArgs(arg0, arg1);\n  return true;\n}\n\n// Given an instruction and its ID, replaces its type with the corresponding\n// value in this evaluation context. Updates `*phase` to describe the phase of\n// the result, and returns whether `*phase` is a constant phase.\nstatic auto ReplaceTypeWithConstantValue(EvalContext& eval_context,\n                                         SemIR::InstId inst_id,\n                                         SemIR::Inst* inst, Phase* phase)\n    -> bool {\n  inst->SetType(GetTypeOfInst(eval_context, inst_id, *inst, phase));\n  return IsConstantOrError(*phase);\n}\n\ntemplate <typename InstT>\nstatic auto ReplaceTypeWithConstantValue(EvalContext& eval_context,\n                                         SemIR::InstId inst_id, InstT* inst,\n                                         Phase* phase) -> bool {\n  inst->type_id = GetTypeOfInst(eval_context, inst_id, *inst, phase);\n  return IsConstantOrError(*phase);\n}\n\ntemplate <typename... Types>\nstatic auto KindHasGetConstantValueOverload(TypeEnum<Types...> e) -> bool {\n  static constexpr std::array<bool, SemIR::IdKind::NumTypes> Values = {\n      (HasGetConstantValueOverload<Types>)...};\n  return Values[e.ToIndex()];\n}\n\nstatic auto ResolveSpecificDeclForSpecificId(EvalContext& eval_context,\n                                             SemIR::SpecificId specific_id)\n    -> void {\n  if (!specific_id.has_value()) {\n    return;\n  }\n\n  const auto& specific = eval_context.specifics().Get(specific_id);\n  const auto& generic = eval_context.generics().Get(specific.generic_id);\n  if (specific_id == generic.self_specific_id) {\n    // Impl witness table construction happens before its generic decl is\n    // finish, in order to make the table's instructions dependent\n    // instructions of the Impl's generic. But those instructions can refer to\n    // the generic's self specific. We can not resolve the specific\n    // declaration for the self specific until the generic is finished, but it\n    // is explicitly resolved at that time in `FinishGenericDecl()`.\n    return;\n  }\n  ResolveSpecificDecl(eval_context.context(), eval_context.fallback_loc_id(),\n                      specific_id);\n}\n\n// Resolves the specific declarations for a specific id in any field of the\n// `inst` instruction.\nstatic auto ResolveSpecificDeclForInst(EvalContext& eval_context,\n                                       const SemIR::Inst& inst) -> void {\n  for (auto arg_and_kind : {inst.arg0_and_kind(), inst.arg1_and_kind()}) {\n    // This switch must handle any field type that has a GetConstantValue()\n    // overload which canonicalizes a specific (and thus potentially forms a new\n    // specific) as part of forming its constant value.\n    CARBON_KIND_SWITCH(arg_and_kind) {\n      case CARBON_KIND(SemIR::FacetTypeId facet_type_id): {\n        const auto& info =\n            eval_context.context().facet_types().Get(facet_type_id);\n        for (const auto& interface : info.extend_constraints) {\n          ResolveSpecificDeclForSpecificId(eval_context, interface.specific_id);\n        }\n        for (const auto& interface : info.self_impls_constraints) {\n          ResolveSpecificDeclForSpecificId(eval_context, interface.specific_id);\n        }\n        for (const auto& constraint : info.extend_named_constraints) {\n          ResolveSpecificDeclForSpecificId(eval_context,\n                                           constraint.specific_id);\n        }\n        for (const auto& constraint : info.self_impls_named_constraints) {\n          ResolveSpecificDeclForSpecificId(eval_context,\n                                           constraint.specific_id);\n        }\n        break;\n      }\n      case CARBON_KIND(SemIR::SpecificId specific_id): {\n        ResolveSpecificDeclForSpecificId(eval_context, specific_id);\n        break;\n      }\n      case CARBON_KIND(SemIR::SpecificInterfaceId specific_interface_id): {\n        ResolveSpecificDeclForSpecificId(eval_context,\n                                         eval_context.specific_interfaces()\n                                             .Get(specific_interface_id)\n                                             .specific_id);\n        break;\n      }\n\n        // These id types have a GetConstantValue() overload but that overload\n        // does not canonicalize any SpecificId in the value type.\n      case SemIR::IdKind::For<SemIR::DestInstId>:\n      case SemIR::IdKind::For<SemIR::EntityNameId>:\n      case SemIR::IdKind::For<SemIR::InstBlockId>:\n      case SemIR::IdKind::For<SemIR::InstId>:\n      case SemIR::IdKind::For<SemIR::MetaInstId>:\n      case SemIR::IdKind::For<SemIR::StructTypeFieldsId>:\n      case SemIR::IdKind::For<SemIR::TypeInstId>:\n        break;\n\n      case SemIR::IdKind::None:\n        // No arg.\n        break;\n\n      default:\n        CARBON_CHECK(\n            !KindHasGetConstantValueOverload(arg_and_kind.kind()),\n            \"Missing case for {0} which has a GetConstantValue() overload\",\n            arg_and_kind.kind());\n        break;\n    }\n  }\n}\n\nauto AddImportedConstant(Context& context, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  EvalContext eval_context(&context, SemIR::LocId::None);\n  CARBON_CHECK(inst.kind().has_type(), \"Can't import untyped instructions: {0}\",\n               inst.kind());\n  Phase phase = GetPhase(context.constant_values(),\n                         context.types().GetConstantId(inst.type_id()));\n  // We ignore the return value of ReplaceAllFieldsWithConstantValues and just\n  // propagate runtime and error constant values into the resulting ConstantId.\n  ReplaceAllFieldsWithConstantValues(eval_context, &inst, &phase);\n  return MakeConstantResult(context, inst, phase);\n}\n\n// Performs an index into a homogeneous aggregate, retrieving the specified\n// element.\nstatic auto PerformArrayIndex(EvalContext& eval_context, SemIR::ArrayIndex inst)\n    -> SemIR::ConstantId {\n  Phase phase = Phase::Concrete;\n  auto index_id = GetConstantValue(eval_context, inst.index_id, &phase);\n\n  if (!index_id.has_value()) {\n    return MakeNonConstantResult(phase);\n  }\n  auto index = eval_context.insts().TryGetAs<SemIR::IntValue>(index_id);\n  if (!index) {\n    CARBON_CHECK(phase != Phase::Concrete,\n                 \"Concrete constant integer should be a literal\");\n    return MakeNonConstantResult(phase);\n  }\n\n  // Array indexing is invalid if the index is constant and out of range,\n  // regardless of whether the array itself is constant.\n  const auto& index_val = eval_context.ints().Get(index->int_id);\n  auto aggregate_type_id = eval_context.GetTypeOfInst(inst.array_id);\n  if (auto array_type =\n          eval_context.types().TryGetAs<SemIR::ArrayType>(aggregate_type_id)) {\n    if (auto bound = eval_context.insts().TryGetAs<SemIR::IntValue>(\n            array_type->bound_id)) {\n      // This awkward call to `getZExtValue` is a workaround for APInt not\n      // supporting comparisons between integers of different bit widths.\n      if (index_val.getActiveBits() > 64 ||\n          eval_context.ints()\n              .Get(bound->int_id)\n              .ule(index_val.getZExtValue())) {\n        CARBON_DIAGNOSTIC(ArrayIndexOutOfBounds, Error,\n                          \"array index `{0}` is past the end of type {1}\",\n                          TypedInt, SemIR::TypeId);\n        eval_context.emitter().Emit(\n            eval_context.GetDiagnosticLoc(inst.index_id), ArrayIndexOutOfBounds,\n            {.type = index->type_id, .value = index_val}, aggregate_type_id);\n        return SemIR::ErrorInst::ConstantId;\n      }\n    }\n  }\n\n  auto aggregate_id = GetConstantValue(eval_context, inst.array_id, &phase);\n  if (!aggregate_id.has_value()) {\n    return MakeNonConstantResult(phase);\n  }\n  auto aggregate =\n      eval_context.insts().TryGetAs<SemIR::AnyAggregateValue>(aggregate_id);\n  if (!aggregate) {\n    // TODO: Consider forming a symbolic constant or reference constant array\n    // index in this case.\n    return MakeNonConstantResult(phase);\n  }\n\n  auto elements = eval_context.inst_blocks().Get(aggregate->elements_id);\n  return eval_context.GetConstantValue(elements[index_val.getZExtValue()]);\n}\n\n// Performs a conversion between character types, diagnosing if the value\n// doesn't fit in the destination type.\nstatic auto PerformCheckedCharConvert(Context& context, SemIR::LocId loc_id,\n                                      SemIR::InstId arg_id,\n                                      SemIR::TypeId dest_type_id)\n    -> SemIR::ConstantId {\n  auto arg = context.insts().GetAs<SemIR::CharLiteralValue>(arg_id);\n\n  // Values over 0x80 require multiple code units in UTF-8.\n  if (arg.value.index >= 0x80) {\n    CARBON_DIAGNOSTIC(CharTooLargeForType, Error,\n                      \"character value {0} too large for type {1}\",\n                      SemIR::CharId, SemIR::TypeId);\n    context.emitter().Emit(loc_id, CharTooLargeForType, arg.value,\n                           dest_type_id);\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  llvm::APInt int_val(8, arg.value.index, /*isSigned=*/false);\n  return MakeIntResult(context, dest_type_id, /*is_signed=*/false, int_val);\n}\n\n// Forms a constant int type as an evaluation result. Requires that width_id is\n// constant.\nstatic auto MakeIntTypeResult(Context& context, SemIR::LocId loc_id,\n                              SemIR::IntKind int_kind, SemIR::InstId width_id,\n                              Phase phase) -> SemIR::ConstantId {\n  auto result = SemIR::IntType{.type_id = SemIR::TypeType::TypeId,\n                               .int_kind = int_kind,\n                               .bit_width_id = width_id};\n  if (!ValidateIntType(context, loc_id, result)) {\n    return SemIR::ErrorInst::ConstantId;\n  }\n  return MakeConstantResult(context, result, phase);\n}\n\n// Forms a constant float type as an evaluation result. Requires that width_id\n// is constant.\nstatic auto MakeFloatTypeResult(Context& context, SemIR::LocId loc_id,\n                                SemIR::InstId width_id, Phase phase)\n    -> SemIR::ConstantId {\n  auto result = SemIR::FloatType{.type_id = SemIR::TypeType::TypeId,\n                                 .bit_width_id = width_id,\n                                 .float_kind = SemIR::FloatKind::None};\n  if (!ValidateFloatTypeAndSetKind(context, loc_id, result)) {\n    return SemIR::ErrorInst::ConstantId;\n  }\n  return MakeConstantResult(context, result, phase);\n}\n\n// Performs a conversion between integer types, truncating if the value doesn't\n// fit in the destination type.\nstatic auto PerformIntConvert(Context& context, SemIR::InstId arg_id,\n                              SemIR::TypeId dest_type_id) -> SemIR::ConstantId {\n  auto arg_val =\n      context.ints().Get(context.insts().GetAs<SemIR::IntValue>(arg_id).int_id);\n  auto [dest_is_signed, bit_width_id] =\n      context.sem_ir().types().GetIntTypeInfo(dest_type_id);\n  if (bit_width_id.has_value()) {\n    // TODO: If the value fits in the destination type, reuse the existing\n    // int_id rather than recomputing it. This is probably the most common case.\n    bool src_is_signed = context.sem_ir().types().IsSignedInt(\n        context.insts().Get(arg_id).type_id());\n    unsigned width = context.ints().Get(bit_width_id).getZExtValue();\n    arg_val =\n        src_is_signed ? arg_val.sextOrTrunc(width) : arg_val.zextOrTrunc(width);\n  }\n  return MakeIntResult(context, dest_type_id, dest_is_signed, arg_val);\n}\n\n// Performs a conversion between integer types, diagnosing if the value doesn't\n// fit in the destination type.\nstatic auto PerformCheckedIntConvert(Context& context, SemIR::LocId loc_id,\n                                     SemIR::InstId arg_id,\n                                     SemIR::TypeId dest_type_id)\n    -> SemIR::ConstantId {\n  auto arg = context.insts().GetAs<SemIR::IntValue>(arg_id);\n  auto arg_val = context.ints().Get(arg.int_id);\n\n  auto [is_signed, bit_width_id] =\n      context.sem_ir().types().GetIntTypeInfo(dest_type_id);\n  auto width = bit_width_id.has_value()\n                   ? context.ints().Get(bit_width_id).getZExtValue()\n                   : arg_val.getBitWidth();\n\n  if (!is_signed && arg_val.isNegative()) {\n    CARBON_DIAGNOSTIC(\n        NegativeIntInUnsignedType, Error,\n        \"negative integer value {0} converted to unsigned type {1}\", TypedInt,\n        SemIR::TypeId);\n    context.emitter().Emit(loc_id, NegativeIntInUnsignedType,\n                           {.type = arg.type_id, .value = arg_val},\n                           dest_type_id);\n  }\n\n  unsigned arg_non_sign_bits = arg_val.getSignificantBits() - 1;\n  if (arg_non_sign_bits + is_signed > width) {\n    CARBON_DIAGNOSTIC(IntTooLargeForType, Error,\n                      \"integer value {0} too large for type {1}\", TypedInt,\n                      SemIR::TypeId);\n    context.emitter().Emit(loc_id, IntTooLargeForType,\n                           {.type = arg.type_id, .value = arg_val},\n                           dest_type_id);\n  }\n\n  return MakeConstantResult(\n      context, SemIR::IntValue{.type_id = dest_type_id, .int_id = arg.int_id},\n      Phase::Concrete);\n}\n\n// Performs a conversion between floating-point types, diagnosing if the value\n// doesn't fit in the destination type.\nstatic auto PerformCheckedFloatConvert(Context& context, SemIR::LocId loc_id,\n                                       SemIR::InstId arg_id,\n                                       SemIR::TypeId dest_type_id)\n    -> SemIR::ConstantId {\n  auto dest_type_object_rep_id = context.types().GetObjectRepr(dest_type_id);\n  CARBON_CHECK(dest_type_object_rep_id.has_value(),\n               \"Conversion to incomplete type\");\n  auto dest_float_type =\n      context.types().TryGetAs<SemIR::FloatType>(dest_type_object_rep_id);\n  CARBON_CHECK(dest_float_type || context.types().Is<SemIR::FloatLiteralType>(\n                                      dest_type_object_rep_id));\n\n  if (auto literal =\n          context.insts().TryGetAs<SemIR::FloatLiteralValue>(arg_id)) {\n    if (!dest_float_type) {\n      return MakeConstantResult(\n          context,\n          SemIR::FloatLiteralValue{.type_id = dest_type_id,\n                                   .real_id = literal->real_id},\n          Phase::Concrete);\n    }\n\n    // Convert the real literal to an llvm::APFloat and add it to the floats\n    // ValueStore. In the future this would use an arbitrary precision Rational\n    // type.\n    //\n    // TODO: Implement Carbon's actual implicit conversion rules for\n    // floating-point constants, as per the design\n    // docs/design/expressions/implicit_conversions.md\n    auto real_value = context.sem_ir().reals().Get(literal->real_id);\n\n    // Convert the real value to a string.\n    llvm::SmallString<64> str;\n    real_value.mantissa.toString(str, real_value.is_decimal ? 10 : 16,\n                                 /*signed=*/false, /*formatAsCLiteral=*/true);\n    str += real_value.is_decimal ? \"e\" : \"p\";\n    real_value.exponent.toStringSigned(str);\n\n    // Convert the string to an APFloat.\n    llvm::APFloat result(dest_float_type->float_kind.Semantics());\n    // TODO: The implementation of this conversion effectively converts back to\n    // APInts, but unfortunately the conversion from integer mantissa and\n    // exponent in IEEEFloat::roundSignificandWithExponent is not part of the\n    // public API.\n    auto status =\n        result.convertFromString(str, llvm::APFloat::rmNearestTiesToEven);\n    if (auto error = status.takeError()) {\n      // The literal we create should always successfully parse.\n      CARBON_FATAL(\"Float literal parsing failed: {0}\",\n                   toString(std::move(error)));\n    }\n    if (status.get() & llvm::APFloat::opOverflow) {\n      CARBON_DIAGNOSTIC(FloatLiteralTooLargeForType, Error,\n                        \"value {0} too large for floating-point type {1}\",\n                        RealId, SemIR::TypeId);\n      context.emitter().Emit(loc_id, FloatLiteralTooLargeForType,\n                             literal->real_id, dest_type_id);\n      return SemIR::ErrorInst::ConstantId;\n    }\n    return MakeFloatResult(context, dest_type_id, std::move(result));\n  }\n\n  if (!dest_float_type) {\n    context.TODO(loc_id, \"conversion from float to float literal\");\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  // Convert to the destination float semantics.\n  auto arg = context.insts().GetAs<SemIR::FloatValue>(arg_id);\n  llvm::APFloat result = context.floats().Get(arg.float_id);\n  bool loses_info;\n  auto status = result.convert(dest_float_type->float_kind.Semantics(),\n                               llvm::APFloat::rmNearestTiesToEven, &loses_info);\n  if (status & llvm::APFloat::opOverflow) {\n    CARBON_DIAGNOSTIC(FloatTooLargeForType, Error,\n                      \"value {0} too large for floating-point type {1}\",\n                      llvm::APFloat, SemIR::TypeId);\n    context.emitter().Emit(loc_id, FloatTooLargeForType,\n                           context.floats().Get(arg.float_id), dest_type_id);\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  return MakeFloatResult(context, dest_type_id, std::move(result));\n}\n\n// Issues a diagnostic for a compile-time division by zero.\nstatic auto DiagnoseDivisionByZero(Context& context, SemIR::LocId loc_id)\n    -> void {\n  CARBON_DIAGNOSTIC(CompileTimeDivisionByZero, Error, \"division by zero\");\n  context.emitter().Emit(loc_id, CompileTimeDivisionByZero);\n}\n\n// Get an integer at a suitable bit-width: either `bit_width_id` if it has a\n// value, or the canonical width from the value store if not.\nstatic auto GetIntAtSuitableWidth(Context& context, IntId int_id,\n                                  IntId bit_width_id) -> llvm::APInt {\n  return bit_width_id.has_value()\n             ? context.ints().GetAtWidth(int_id, bit_width_id)\n             : context.ints().Get(int_id);\n}\n\n// Performs a builtin unary integer -> integer operation.\nstatic auto PerformBuiltinUnaryIntOp(Context& context, SemIR::LocId loc_id,\n                                     SemIR::BuiltinFunctionKind builtin_kind,\n                                     SemIR::InstId arg_id)\n    -> SemIR::ConstantId {\n  auto op = context.insts().GetAs<SemIR::IntValue>(arg_id);\n  auto [is_signed, bit_width_id] =\n      context.sem_ir().types().GetIntTypeInfo(op.type_id);\n  llvm::APInt op_val = GetIntAtSuitableWidth(context, op.int_id, bit_width_id);\n\n  switch (builtin_kind) {\n    case SemIR::BuiltinFunctionKind::IntSNegate:\n      if (op_val.isMinSignedValue()) {\n        if (bit_width_id.has_value()) {\n          CARBON_DIAGNOSTIC(CompileTimeIntegerNegateOverflow, Error,\n                            \"integer overflow in negation of {0}\", TypedInt);\n          context.emitter().Emit(loc_id, CompileTimeIntegerNegateOverflow,\n                                 {.type = op.type_id, .value = op_val});\n        } else {\n          // Widen the integer so we don't overflow into the sign bit.\n          op_val = op_val.sext(op_val.getBitWidth() +\n                               llvm::APInt::APINT_BITS_PER_WORD);\n        }\n      }\n      op_val.negate();\n      break;\n    case SemIR::BuiltinFunctionKind::IntUNegate:\n      CARBON_CHECK(bit_width_id.has_value(), \"Unsigned negate on unsized int\");\n      op_val.negate();\n      break;\n    case SemIR::BuiltinFunctionKind::IntComplement:\n      // TODO: Should we have separate builtins for signed and unsigned\n      // complement? Like with signed/unsigned negate, these operations do\n      // different things to the integer value, even though they do the same\n      // thing to the bits. We treat IntLiteral complement as signed complement,\n      // given that the result of unsigned complement depends on the bit width.\n      op_val.flipAllBits();\n      break;\n    default:\n      CARBON_FATAL(\"Unexpected builtin kind\");\n  }\n\n  return MakeIntResult(context, op.type_id, is_signed, std::move(op_val));\n}\n\nnamespace {\n// A pair of APInts that are the operands of a binary operator. We use an\n// aggregate rather than `std::pair` to allow RVO of the individual ints.\nstruct APIntBinaryOperands {\n  llvm::APInt lhs;\n  llvm::APInt rhs;\n};\n}  // namespace\n\n// Get a pair of integers at the same suitable bit-width: either their actual\n// width if they have a fixed width, or the smallest canonical width in which\n// they both fit otherwise.\nstatic auto GetIntsAtSuitableWidth(Context& context, IntId lhs_id, IntId rhs_id,\n                                   IntId bit_width_id) -> APIntBinaryOperands {\n  // Unsized operands: take the wider of the bit widths.\n  if (!bit_width_id.has_value()) {\n    APIntBinaryOperands result = {.lhs = context.ints().Get(lhs_id),\n                                  .rhs = context.ints().Get(rhs_id)};\n    if (result.lhs.getBitWidth() != result.rhs.getBitWidth()) {\n      if (result.lhs.getBitWidth() > result.rhs.getBitWidth()) {\n        result.rhs = result.rhs.sext(result.lhs.getBitWidth());\n      } else {\n        result.lhs = result.lhs.sext(result.rhs.getBitWidth());\n      }\n    }\n    return result;\n  }\n\n  return {.lhs = context.ints().GetAtWidth(lhs_id, bit_width_id),\n          .rhs = context.ints().GetAtWidth(rhs_id, bit_width_id)};\n}\n\nnamespace {\n// The result of performing a binary int operation.\nstruct BinaryIntOpResult {\n  llvm::APInt result_val;\n  bool overflow;\n  Lex::TokenKind op_token;\n};\n}  // namespace\n\n// Computes the result of a homogeneous binary (int, int) -> int operation.\nstatic auto ComputeBinaryIntOpResult(SemIR::BuiltinFunctionKind builtin_kind,\n                                     const llvm::APInt& lhs_val,\n                                     const llvm::APInt& rhs_val)\n    -> BinaryIntOpResult {\n  llvm::APInt result_val;\n  bool overflow = false;\n  Lex::TokenKind op_token = Lex::TokenKind::Not;\n\n  switch (builtin_kind) {\n    // Arithmetic.\n    case SemIR::BuiltinFunctionKind::IntSAdd:\n      result_val = lhs_val.sadd_ov(rhs_val, overflow);\n      op_token = Lex::TokenKind::Plus;\n      break;\n    case SemIR::BuiltinFunctionKind::IntSSub:\n      result_val = lhs_val.ssub_ov(rhs_val, overflow);\n      op_token = Lex::TokenKind::Minus;\n      break;\n    case SemIR::BuiltinFunctionKind::IntSMul:\n      result_val = lhs_val.smul_ov(rhs_val, overflow);\n      op_token = Lex::TokenKind::Star;\n      break;\n    case SemIR::BuiltinFunctionKind::IntSDiv:\n      result_val = lhs_val.sdiv_ov(rhs_val, overflow);\n      op_token = Lex::TokenKind::Slash;\n      break;\n    case SemIR::BuiltinFunctionKind::IntSMod:\n      result_val = lhs_val.srem(rhs_val);\n      // LLVM weirdly lacks `srem_ov`, so we work it out for ourselves:\n      // <signed min> % -1 overflows because <signed min> / -1 overflows.\n      overflow = lhs_val.isMinSignedValue() && rhs_val.isAllOnes();\n      op_token = Lex::TokenKind::Percent;\n      break;\n    case SemIR::BuiltinFunctionKind::IntUAdd:\n      result_val = lhs_val + rhs_val;\n      op_token = Lex::TokenKind::Plus;\n      break;\n    case SemIR::BuiltinFunctionKind::IntUSub:\n      result_val = lhs_val - rhs_val;\n      op_token = Lex::TokenKind::Minus;\n      break;\n    case SemIR::BuiltinFunctionKind::IntUMul:\n      result_val = lhs_val * rhs_val;\n      op_token = Lex::TokenKind::Star;\n      break;\n    case SemIR::BuiltinFunctionKind::IntUDiv:\n      result_val = lhs_val.udiv(rhs_val);\n      op_token = Lex::TokenKind::Slash;\n      break;\n    case SemIR::BuiltinFunctionKind::IntUMod:\n      result_val = lhs_val.urem(rhs_val);\n      op_token = Lex::TokenKind::Percent;\n      break;\n\n    // Bitwise.\n    case SemIR::BuiltinFunctionKind::IntAnd:\n      result_val = lhs_val & rhs_val;\n      op_token = Lex::TokenKind::And;\n      break;\n    case SemIR::BuiltinFunctionKind::IntOr:\n      result_val = lhs_val | rhs_val;\n      op_token = Lex::TokenKind::Pipe;\n      break;\n    case SemIR::BuiltinFunctionKind::IntXor:\n      result_val = lhs_val ^ rhs_val;\n      op_token = Lex::TokenKind::Caret;\n      break;\n\n    case SemIR::BuiltinFunctionKind::IntLeftShift:\n    case SemIR::BuiltinFunctionKind::IntRightShift:\n      CARBON_FATAL(\"Non-homogeneous operation handled separately.\");\n\n    default:\n      CARBON_FATAL(\"Unexpected operation kind.\");\n  }\n  return {.result_val = std::move(result_val),\n          .overflow = overflow,\n          .op_token = op_token};\n}\n\n// Performs a builtin integer bit shift operation.\nstatic auto PerformBuiltinIntShiftOp(Context& context, SemIR::LocId loc_id,\n                                     SemIR::BuiltinFunctionKind builtin_kind,\n                                     SemIR::InstId lhs_id, SemIR::InstId rhs_id)\n    -> SemIR::ConstantId {\n  auto lhs = context.insts().GetAs<SemIR::IntValue>(lhs_id);\n  auto rhs = context.insts().GetAs<SemIR::IntValue>(rhs_id);\n\n  auto [lhs_is_signed, lhs_bit_width_id] =\n      context.sem_ir().types().GetIntTypeInfo(lhs.type_id);\n\n  llvm::APInt lhs_val =\n      GetIntAtSuitableWidth(context, lhs.int_id, lhs_bit_width_id);\n  const auto& rhs_orig_val = context.ints().Get(rhs.int_id);\n  if (lhs_bit_width_id.has_value() && rhs_orig_val.uge(lhs_val.getBitWidth())) {\n    CARBON_DIAGNOSTIC(\n        CompileTimeShiftOutOfRange, Error,\n        \"shift distance >= type width of {0} in `{1} {2:<<|>>} {3}`\", unsigned,\n        TypedInt, Diagnostics::BoolAsSelect, TypedInt);\n    context.emitter().Emit(\n        loc_id, CompileTimeShiftOutOfRange, lhs_val.getBitWidth(),\n        {.type = lhs.type_id, .value = lhs_val},\n        builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift,\n        {.type = rhs.type_id, .value = rhs_orig_val});\n    // TODO: Is it useful to recover by returning 0 or -1?\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  if (rhs_orig_val.isNegative() &&\n      context.sem_ir().types().IsSignedInt(rhs.type_id)) {\n    CARBON_DIAGNOSTIC(CompileTimeShiftNegative, Error,\n                      \"shift distance negative in `{0} {1:<<|>>} {2}`\",\n                      TypedInt, Diagnostics::BoolAsSelect, TypedInt);\n    context.emitter().Emit(\n        loc_id, CompileTimeShiftNegative,\n        {.type = lhs.type_id, .value = lhs_val},\n        builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift,\n        {.type = rhs.type_id, .value = rhs_orig_val});\n    // TODO: Is it useful to recover by returning 0 or -1?\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  llvm::APInt result_val;\n  if (builtin_kind == SemIR::BuiltinFunctionKind::IntLeftShift) {\n    if (!lhs_bit_width_id.has_value() && !lhs_val.isZero()) {\n      // Ensure we don't generate a ridiculously large integer through a bit\n      // shift.\n      auto width = rhs_orig_val.trySExtValue();\n      if (!width ||\n          *width > IntStore::MaxIntWidth - lhs_val.getSignificantBits()) {\n        CARBON_DIAGNOSTIC(CompileTimeUnsizedShiftOutOfRange, Error,\n                          \"shift distance of {0} would result in an \"\n                          \"integer whose width is greater than the \"\n                          \"maximum supported width of {1}\",\n                          TypedInt, int);\n        context.emitter().Emit(loc_id, CompileTimeUnsizedShiftOutOfRange,\n                               {.type = rhs.type_id, .value = rhs_orig_val},\n                               IntStore::MaxIntWidth);\n        return SemIR::ErrorInst::ConstantId;\n      }\n      lhs_val = lhs_val.sext(\n          IntStore::CanonicalBitWidth(lhs_val.getSignificantBits() + *width));\n    }\n\n    result_val =\n        lhs_val.shl(rhs_orig_val.getLimitedValue(lhs_val.getBitWidth()));\n  } else if (lhs_is_signed) {\n    result_val =\n        lhs_val.ashr(rhs_orig_val.getLimitedValue(lhs_val.getBitWidth()));\n  } else {\n    CARBON_CHECK(lhs_bit_width_id.has_value(), \"Logical shift on unsized int\");\n    result_val =\n        lhs_val.lshr(rhs_orig_val.getLimitedValue(lhs_val.getBitWidth()));\n  }\n  return MakeIntResult(context, lhs.type_id, lhs_is_signed,\n                       std::move(result_val));\n}\n\n// Performs a homogeneous builtin binary integer -> integer operation.\nstatic auto PerformBuiltinBinaryIntOp(Context& context, SemIR::LocId loc_id,\n                                      SemIR::BuiltinFunctionKind builtin_kind,\n                                      SemIR::InstId lhs_id,\n                                      SemIR::InstId rhs_id)\n    -> SemIR::ConstantId {\n  auto lhs = context.insts().GetAs<SemIR::IntValue>(lhs_id);\n  auto rhs = context.insts().GetAs<SemIR::IntValue>(rhs_id);\n\n  CARBON_CHECK(rhs.type_id == lhs.type_id, \"Heterogeneous builtin integer op!\");\n  auto type_id = lhs.type_id;\n  auto [is_signed, bit_width_id] =\n      context.sem_ir().types().GetIntTypeInfo(type_id);\n  auto [lhs_val, rhs_val] =\n      GetIntsAtSuitableWidth(context, lhs.int_id, rhs.int_id, bit_width_id);\n\n  // Check for division by zero.\n  switch (builtin_kind) {\n    case SemIR::BuiltinFunctionKind::IntSDiv:\n    case SemIR::BuiltinFunctionKind::IntSMod:\n    case SemIR::BuiltinFunctionKind::IntUDiv:\n    case SemIR::BuiltinFunctionKind::IntUMod:\n      if (rhs_val.isZero()) {\n        DiagnoseDivisionByZero(context, loc_id);\n        return SemIR::ErrorInst::ConstantId;\n      }\n      break;\n    default:\n      break;\n  }\n\n  BinaryIntOpResult result =\n      ComputeBinaryIntOpResult(builtin_kind, lhs_val, rhs_val);\n\n  if (result.overflow && !bit_width_id.has_value()) {\n    // Retry with a larger bit width. Most operations can only overflow by one\n    // bit, but signed n-bit multiplication can overflow to 2n-1 bits. We don't\n    // need to handle unsigned multiplication here because it's not permitted\n    // for unsized integers.\n    //\n    // Note that we speculatively first perform the calculation in the width of\n    // the wider operand: smaller operations are faster and overflow to a wider\n    // integer is unlikely to be needed, especially given that the width will\n    // have been rounded up to a multiple of 64 bits by the int store.\n    CARBON_CHECK(builtin_kind != SemIR::BuiltinFunctionKind::IntUMul,\n                 \"Unsigned arithmetic requires a fixed bitwidth\");\n    int new_width =\n        builtin_kind == SemIR::BuiltinFunctionKind::IntSMul\n            ? lhs_val.getBitWidth() * 2\n            : IntStore::CanonicalBitWidth(lhs_val.getBitWidth() + 1);\n    new_width = std::min(new_width, IntStore::MaxIntWidth);\n    lhs_val = context.ints().GetAtWidth(lhs.int_id, new_width);\n    rhs_val = context.ints().GetAtWidth(rhs.int_id, new_width);\n\n    // Note that this can in theory still overflow if we limited `new_width` to\n    // `MaxIntWidth`. In that case we fall through to the signed overflow\n    // diagnostic below.\n    result = ComputeBinaryIntOpResult(builtin_kind, lhs_val, rhs_val);\n    CARBON_CHECK(!result.overflow || new_width == IntStore::MaxIntWidth);\n  }\n\n  if (result.overflow) {\n    CARBON_DIAGNOSTIC(CompileTimeIntegerOverflow, Error,\n                      \"integer overflow in calculation `{0} {1} {2}`\", TypedInt,\n                      Lex::TokenKind, TypedInt);\n    context.emitter().Emit(loc_id, CompileTimeIntegerOverflow,\n                           {.type = type_id, .value = lhs_val}, result.op_token,\n                           {.type = type_id, .value = rhs_val});\n  }\n\n  return MakeIntResult(context, type_id, is_signed,\n                       std::move(result.result_val));\n}\n\n// Performs a builtin integer comparison.\nstatic auto PerformBuiltinIntComparison(Context& context,\n                                        SemIR::BuiltinFunctionKind builtin_kind,\n                                        SemIR::InstId lhs_id,\n                                        SemIR::InstId rhs_id,\n                                        SemIR::TypeId bool_type_id)\n    -> SemIR::ConstantId {\n  auto lhs = context.insts().GetAs<SemIR::IntValue>(lhs_id);\n  auto rhs = context.insts().GetAs<SemIR::IntValue>(rhs_id);\n  llvm::APInt lhs_val = context.ints().Get(lhs.int_id);\n  llvm::APInt rhs_val = context.ints().Get(rhs.int_id);\n\n  bool result;\n  switch (builtin_kind) {\n    case SemIR::BuiltinFunctionKind::IntEq:\n      result = (lhs_val == rhs_val);\n      break;\n    case SemIR::BuiltinFunctionKind::IntNeq:\n      result = (lhs_val != rhs_val);\n      break;\n    case SemIR::BuiltinFunctionKind::IntLess:\n      result = lhs_val.slt(rhs_val);\n      break;\n    case SemIR::BuiltinFunctionKind::IntLessEq:\n      result = lhs_val.sle(rhs_val);\n      break;\n    case SemIR::BuiltinFunctionKind::IntGreater:\n      result = lhs_val.sgt(rhs_val);\n      break;\n    case SemIR::BuiltinFunctionKind::IntGreaterEq:\n      result = lhs_val.sge(rhs_val);\n      break;\n    default:\n      CARBON_FATAL(\"Unexpected operation kind.\");\n  }\n\n  return MakeBoolResult(context, bool_type_id, result);\n}\n\n// Performs a builtin unary float -> float operation.\nstatic auto PerformBuiltinUnaryFloatOp(Context& context,\n                                       SemIR::BuiltinFunctionKind builtin_kind,\n                                       SemIR::InstId arg_id)\n    -> SemIR::ConstantId {\n  auto op = context.insts().GetAs<SemIR::FloatValue>(arg_id);\n  auto op_val = context.floats().Get(op.float_id);\n\n  switch (builtin_kind) {\n    case SemIR::BuiltinFunctionKind::FloatNegate:\n      op_val.changeSign();\n      break;\n    default:\n      CARBON_FATAL(\"Unexpected builtin kind\");\n  }\n\n  return MakeFloatResult(context, op.type_id, std::move(op_val));\n}\n\n// Performs a builtin binary float -> float operation.\nstatic auto PerformBuiltinBinaryFloatOp(Context& context,\n                                        SemIR::BuiltinFunctionKind builtin_kind,\n                                        SemIR::InstId lhs_id,\n                                        SemIR::InstId rhs_id)\n    -> SemIR::ConstantId {\n  auto lhs = context.insts().GetAs<SemIR::FloatValue>(lhs_id);\n  auto rhs = context.insts().GetAs<SemIR::FloatValue>(rhs_id);\n  auto lhs_val = context.floats().Get(lhs.float_id);\n  auto rhs_val = context.floats().Get(rhs.float_id);\n\n  llvm::APFloat result_val(lhs_val.getSemantics());\n\n  switch (builtin_kind) {\n    case SemIR::BuiltinFunctionKind::FloatAdd:\n      result_val = lhs_val + rhs_val;\n      break;\n    case SemIR::BuiltinFunctionKind::FloatSub:\n      result_val = lhs_val - rhs_val;\n      break;\n    case SemIR::BuiltinFunctionKind::FloatMul:\n      result_val = lhs_val * rhs_val;\n      break;\n    case SemIR::BuiltinFunctionKind::FloatDiv:\n      result_val = lhs_val / rhs_val;\n      break;\n    default:\n      CARBON_FATAL(\"Unexpected operation kind.\");\n  }\n\n  return MakeFloatResult(context, lhs.type_id, std::move(result_val));\n}\n\n// Performs a builtin float comparison.\nstatic auto PerformBuiltinFloatComparison(\n    Context& context, SemIR::BuiltinFunctionKind builtin_kind,\n    SemIR::InstId lhs_id, SemIR::InstId rhs_id, SemIR::TypeId bool_type_id)\n    -> SemIR::ConstantId {\n  auto lhs = context.insts().GetAs<SemIR::FloatValue>(lhs_id);\n  auto rhs = context.insts().GetAs<SemIR::FloatValue>(rhs_id);\n  const auto& lhs_val = context.floats().Get(lhs.float_id);\n  const auto& rhs_val = context.floats().Get(rhs.float_id);\n\n  bool result;\n  switch (builtin_kind) {\n    case SemIR::BuiltinFunctionKind::FloatEq:\n      result = (lhs_val == rhs_val);\n      break;\n    case SemIR::BuiltinFunctionKind::FloatNeq:\n      result = (lhs_val != rhs_val);\n      break;\n    case SemIR::BuiltinFunctionKind::FloatLess:\n      result = lhs_val < rhs_val;\n      break;\n    case SemIR::BuiltinFunctionKind::FloatLessEq:\n      result = lhs_val <= rhs_val;\n      break;\n    case SemIR::BuiltinFunctionKind::FloatGreater:\n      result = lhs_val > rhs_val;\n      break;\n    case SemIR::BuiltinFunctionKind::FloatGreaterEq:\n      result = lhs_val >= rhs_val;\n      break;\n    default:\n      CARBON_FATAL(\"Unexpected operation kind.\");\n  }\n\n  return MakeBoolResult(context, bool_type_id, result);\n}\n\n// Performs a builtin boolean comparison.\nstatic auto PerformBuiltinBoolComparison(\n    Context& context, SemIR::BuiltinFunctionKind builtin_kind,\n    SemIR::InstId lhs_id, SemIR::InstId rhs_id, SemIR::TypeId bool_type_id) {\n  bool lhs = context.insts().GetAs<SemIR::BoolLiteral>(lhs_id).value.ToBool();\n  bool rhs = context.insts().GetAs<SemIR::BoolLiteral>(rhs_id).value.ToBool();\n  return MakeBoolResult(context, bool_type_id,\n                        builtin_kind == SemIR::BuiltinFunctionKind::BoolEq\n                            ? lhs == rhs\n                            : lhs != rhs);\n}\n\n// Converts a call argument to a FacetTypeId.\nstatic auto ArgToFacetTypeId(Context& context, SemIR::LocId loc_id,\n                             SemIR::InstId arg_id) -> SemIR::FacetTypeId {\n  auto type_arg_id = context.types().GetAsTypeInstId(arg_id);\n  if (auto facet_type =\n          context.insts().TryGetAs<SemIR::FacetType>(type_arg_id)) {\n    return facet_type->facet_type_id;\n  }\n  CARBON_DIAGNOSTIC(FacetTypeRequiredForTypeAndOperator, Error,\n                    \"non-facet type {0} combined with `&` operator\",\n                    SemIR::TypeId);\n  // TODO: Find a location for the lhs or rhs specifically, instead of\n  // the whole thing. If that's not possible we can change the text to\n  // say if it's referring to the left or the right side for the error.\n  // The `arg_id` instruction has no location in it for some reason.\n  context.emitter().Emit(loc_id, FacetTypeRequiredForTypeAndOperator,\n                         context.types().GetTypeIdForTypeInstId(type_arg_id));\n  return SemIR::FacetTypeId::None;\n}\n\n// Returns a constant for a call to a builtin function.\nstatic auto MakeConstantForBuiltinCall(EvalContext& eval_context,\n                                       SemIR::LocId loc_id, SemIR::Call call,\n                                       SemIR::BuiltinFunctionKind builtin_kind,\n                                       llvm::ArrayRef<SemIR::InstId> arg_ids,\n                                       Phase phase) -> SemIR::ConstantId {\n  auto& context = eval_context.context();\n  switch (builtin_kind) {\n    case SemIR::BuiltinFunctionKind::None:\n      CARBON_FATAL(\"Not a builtin function.\");\n\n    case SemIR::BuiltinFunctionKind::NoOp: {\n      return MakeEmptyTupleResult(eval_context);\n    }\n\n    case SemIR::BuiltinFunctionKind::PrimitiveCopy: {\n      return context.constant_values().Get(arg_ids[0]);\n    }\n\n    case SemIR::BuiltinFunctionKind::StringAt: {\n      Phase phase = Phase::Concrete;\n      auto str_id = GetConstantValue(eval_context, arg_ids[0], &phase);\n      auto index_id = GetConstantValue(eval_context, arg_ids[1], &phase);\n\n      if (phase != Phase::Concrete) {\n        return MakeNonConstantResult(phase);\n      }\n\n      auto str_struct = eval_context.insts().GetAs<SemIR::StructValue>(str_id);\n      auto elements = eval_context.inst_blocks().Get(str_struct.elements_id);\n      // String struct has two fields: a pointer to the string data and the\n      // length.\n      CARBON_CHECK(elements.size() == 2, \"String struct should have 2 fields.\");\n\n      auto string_literal = eval_context.insts().GetAs<SemIR::StringLiteral>(\n          eval_context.constant_values().GetConstantInstId(elements[0]));\n\n      const auto& string_value =\n          eval_context.sem_ir().string_literal_values().Get(\n              string_literal.string_literal_id);\n\n      auto index_inst = eval_context.insts().GetAs<SemIR::IntValue>(index_id);\n      const auto& index_val = eval_context.ints().Get(index_inst.int_id);\n\n      if (index_val.isNegative()) {\n        CARBON_DIAGNOSTIC(StringAtIndexNegative, Error,\n                          \"index `{0}` is negative.\", TypedInt);\n        context.emitter().Emit(\n            loc_id, StringAtIndexNegative,\n            {.type = eval_context.insts().Get(index_id).type_id(),\n             .value = index_val});\n        return SemIR::ConstantId::NotConstant;\n      }\n\n      if (index_val.getZExtValue() >= string_value.size()) {\n        CARBON_DIAGNOSTIC(\n            StringAtIndexOutOfBounds, Error,\n            \"string index `{0}` is out of bounds; string has length {1}.\",\n            TypedInt, size_t);\n        context.emitter().Emit(\n            loc_id, StringAtIndexOutOfBounds,\n            {.type = eval_context.insts().Get(index_id).type_id(),\n             .value = index_val},\n            string_value.size());\n        return SemIR::ConstantId::NotConstant;\n      }\n\n      auto char_value =\n          static_cast<uint8_t>(string_value[index_val.getZExtValue()]);\n\n      auto int_id = eval_context.ints().Add(\n          llvm::APSInt(llvm::APInt(32, char_value), /*isUnsigned=*/false));\n      return MakeConstantResult(\n          eval_context.context(),\n          SemIR::IntValue{.type_id = call.type_id, .int_id = int_id}, phase);\n    }\n\n    case SemIR::BuiltinFunctionKind::MakeUninitialized:\n    case SemIR::BuiltinFunctionKind::PrintChar:\n    case SemIR::BuiltinFunctionKind::PrintInt:\n    case SemIR::BuiltinFunctionKind::ReadChar:\n    case SemIR::BuiltinFunctionKind::FloatAddAssign:\n    case SemIR::BuiltinFunctionKind::FloatSubAssign:\n    case SemIR::BuiltinFunctionKind::FloatMulAssign:\n    case SemIR::BuiltinFunctionKind::FloatDivAssign:\n    case SemIR::BuiltinFunctionKind::IntSAddAssign:\n    case SemIR::BuiltinFunctionKind::IntSSubAssign:\n    case SemIR::BuiltinFunctionKind::IntSMulAssign:\n    case SemIR::BuiltinFunctionKind::IntSDivAssign:\n    case SemIR::BuiltinFunctionKind::IntSModAssign:\n    case SemIR::BuiltinFunctionKind::IntUAddAssign:\n    case SemIR::BuiltinFunctionKind::IntUSubAssign:\n    case SemIR::BuiltinFunctionKind::IntUMulAssign:\n    case SemIR::BuiltinFunctionKind::IntUDivAssign:\n    case SemIR::BuiltinFunctionKind::IntUModAssign:\n    case SemIR::BuiltinFunctionKind::IntAndAssign:\n    case SemIR::BuiltinFunctionKind::IntOrAssign:\n    case SemIR::BuiltinFunctionKind::IntXorAssign:\n    case SemIR::BuiltinFunctionKind::IntLeftShiftAssign:\n    case SemIR::BuiltinFunctionKind::IntRightShiftAssign:\n    case SemIR::BuiltinFunctionKind::PointerMakeNull:\n    case SemIR::BuiltinFunctionKind::PointerIsNull:\n    case SemIR::BuiltinFunctionKind::PointerUnsafeConvert:\n    case SemIR::BuiltinFunctionKind::CppStdInitializerListMake: {\n      // These are runtime-only builtins.\n      // TODO: Consider tracking this on the `BuiltinFunctionKind`.\n      return SemIR::ConstantId::NotConstant;\n    }\n\n    case SemIR::BuiltinFunctionKind::TypeAnd: {\n      CARBON_CHECK(arg_ids.size() == 2);\n      auto lhs_facet_type_id = ArgToFacetTypeId(context, loc_id, arg_ids[0]);\n      auto rhs_facet_type_id = ArgToFacetTypeId(context, loc_id, arg_ids[1]);\n\n      // Allow errors to be diagnosed for both sides of the operator before\n      // returning here if any error occurred on either side.\n      if (!lhs_facet_type_id.has_value() || !rhs_facet_type_id.has_value()) {\n        return SemIR::ErrorInst::ConstantId;\n      }\n      // Reuse one of the argument instructions if nothing has changed.\n      if (lhs_facet_type_id == rhs_facet_type_id) {\n        return context.types().GetConstantId(\n            context.types().GetTypeIdForTypeInstId(arg_ids[0]));\n      }\n      auto combined_info = SemIR::FacetTypeInfo::Combine(\n          context.facet_types().Get(lhs_facet_type_id),\n          context.facet_types().Get(rhs_facet_type_id));\n      if (!ResolveFacetTypeRewriteConstraints(\n              eval_context.context(), loc_id,\n              combined_info.rewrite_constraints)) {\n        phase = Phase::UnknownDueToError;\n      }\n      combined_info.Canonicalize();\n      return MakeFacetTypeResult(eval_context.context(), combined_info, phase);\n    }\n\n    case SemIR::BuiltinFunctionKind::CharLiteralMakeType: {\n      return context.constant_values().Get(SemIR::CharLiteralType::TypeInstId);\n    }\n\n    case SemIR::BuiltinFunctionKind::FloatLiteralMakeType: {\n      return context.constant_values().Get(SemIR::FloatLiteralType::TypeInstId);\n    }\n\n    case SemIR::BuiltinFunctionKind::IntLiteralMakeType: {\n      return context.constant_values().Get(SemIR::IntLiteralType::TypeInstId);\n    }\n\n    case SemIR::BuiltinFunctionKind::IntMakeTypeSigned: {\n      return MakeIntTypeResult(context, loc_id, SemIR::IntKind::Signed,\n                               arg_ids[0], phase);\n    }\n\n    case SemIR::BuiltinFunctionKind::IntMakeTypeUnsigned: {\n      return MakeIntTypeResult(context, loc_id, SemIR::IntKind::Unsigned,\n                               arg_ids[0], phase);\n    }\n\n    case SemIR::BuiltinFunctionKind::FloatMakeType: {\n      return MakeFloatTypeResult(context, loc_id, arg_ids[0], phase);\n    }\n\n    case SemIR::BuiltinFunctionKind::BoolMakeType: {\n      return context.constant_values().Get(SemIR::BoolType::TypeInstId);\n    }\n\n    case SemIR::BuiltinFunctionKind::MaybeUnformedMakeType: {\n      return MakeConstantResult(\n          context,\n          SemIR::MaybeUnformedType{\n              .type_id = SemIR::TypeType::TypeId,\n              .inner_id = context.types().GetAsTypeInstId(arg_ids[0])},\n          phase);\n    }\n\n    case SemIR::BuiltinFunctionKind::FormMakeType: {\n      return context.constant_values().Get(SemIR::FormType::TypeInstId);\n    }\n\n    // Character conversions.\n    case SemIR::BuiltinFunctionKind::CharConvertChecked: {\n      if (phase != Phase::Concrete) {\n        return MakeConstantResult(context, call, phase);\n      }\n      return PerformCheckedCharConvert(context, loc_id, arg_ids[0],\n                                       call.type_id);\n    }\n\n    // Integer conversions.\n    case SemIR::BuiltinFunctionKind::IntConvertChar: {\n      if (phase != Phase::Concrete) {\n        return MakeConstantResult(context, call, phase);\n      }\n      return PerformIntConvert(context, arg_ids[0], call.type_id);\n    }\n    case SemIR::BuiltinFunctionKind::IntConvert: {\n      if (phase != Phase::Concrete) {\n        return MakeConstantResult(context, call, phase);\n      }\n      return PerformIntConvert(context, arg_ids[0], call.type_id);\n    }\n    case SemIR::BuiltinFunctionKind::IntConvertChecked: {\n      if (phase != Phase::Concrete) {\n        return MakeConstantResult(context, call, phase);\n      }\n      return PerformCheckedIntConvert(context, loc_id, arg_ids[0],\n                                      call.type_id);\n    }\n\n    // Unary integer -> integer operations.\n    case SemIR::BuiltinFunctionKind::IntSNegate:\n    case SemIR::BuiltinFunctionKind::IntUNegate:\n    case SemIR::BuiltinFunctionKind::IntComplement: {\n      if (phase != Phase::Concrete) {\n        break;\n      }\n      return PerformBuiltinUnaryIntOp(context, loc_id, builtin_kind,\n                                      arg_ids[0]);\n    }\n\n    // Homogeneous binary integer -> integer operations.\n    case SemIR::BuiltinFunctionKind::IntSAdd:\n    case SemIR::BuiltinFunctionKind::IntSSub:\n    case SemIR::BuiltinFunctionKind::IntSMul:\n    case SemIR::BuiltinFunctionKind::IntSDiv:\n    case SemIR::BuiltinFunctionKind::IntSMod:\n    case SemIR::BuiltinFunctionKind::IntUAdd:\n    case SemIR::BuiltinFunctionKind::IntUSub:\n    case SemIR::BuiltinFunctionKind::IntUMul:\n    case SemIR::BuiltinFunctionKind::IntUDiv:\n    case SemIR::BuiltinFunctionKind::IntUMod:\n    case SemIR::BuiltinFunctionKind::IntAnd:\n    case SemIR::BuiltinFunctionKind::IntOr:\n    case SemIR::BuiltinFunctionKind::IntXor: {\n      if (phase != Phase::Concrete) {\n        break;\n      }\n      return PerformBuiltinBinaryIntOp(context, loc_id, builtin_kind,\n                                       arg_ids[0], arg_ids[1]);\n    }\n\n    // Bit shift operations.\n    case SemIR::BuiltinFunctionKind::IntLeftShift:\n    case SemIR::BuiltinFunctionKind::IntRightShift: {\n      if (phase != Phase::Concrete) {\n        break;\n      }\n      return PerformBuiltinIntShiftOp(context, loc_id, builtin_kind, arg_ids[0],\n                                      arg_ids[1]);\n    }\n\n    // Integer comparisons.\n    case SemIR::BuiltinFunctionKind::IntEq:\n    case SemIR::BuiltinFunctionKind::IntNeq:\n    case SemIR::BuiltinFunctionKind::IntLess:\n    case SemIR::BuiltinFunctionKind::IntLessEq:\n    case SemIR::BuiltinFunctionKind::IntGreater:\n    case SemIR::BuiltinFunctionKind::IntGreaterEq: {\n      if (phase != Phase::Concrete) {\n        break;\n      }\n      return PerformBuiltinIntComparison(context, builtin_kind, arg_ids[0],\n                                         arg_ids[1], call.type_id);\n    }\n\n    // Floating-point conversions.\n    case SemIR::BuiltinFunctionKind::FloatConvertChecked: {\n      if (phase != Phase::Concrete) {\n        return MakeConstantResult(context, call, phase);\n      }\n      return PerformCheckedFloatConvert(context, loc_id, arg_ids[0],\n                                        call.type_id);\n    }\n\n    // Unary float -> float operations.\n    case SemIR::BuiltinFunctionKind::FloatNegate: {\n      if (phase != Phase::Concrete) {\n        break;\n      }\n\n      return PerformBuiltinUnaryFloatOp(context, builtin_kind, arg_ids[0]);\n    }\n\n    // Binary float -> float operations.\n    case SemIR::BuiltinFunctionKind::FloatAdd:\n    case SemIR::BuiltinFunctionKind::FloatSub:\n    case SemIR::BuiltinFunctionKind::FloatMul:\n    case SemIR::BuiltinFunctionKind::FloatDiv: {\n      if (phase != Phase::Concrete) {\n        break;\n      }\n      return PerformBuiltinBinaryFloatOp(context, builtin_kind, arg_ids[0],\n                                         arg_ids[1]);\n    }\n\n    // Float comparisons.\n    case SemIR::BuiltinFunctionKind::FloatEq:\n    case SemIR::BuiltinFunctionKind::FloatNeq:\n    case SemIR::BuiltinFunctionKind::FloatLess:\n    case SemIR::BuiltinFunctionKind::FloatLessEq:\n    case SemIR::BuiltinFunctionKind::FloatGreater:\n    case SemIR::BuiltinFunctionKind::FloatGreaterEq: {\n      if (phase != Phase::Concrete) {\n        break;\n      }\n      return PerformBuiltinFloatComparison(context, builtin_kind, arg_ids[0],\n                                           arg_ids[1], call.type_id);\n    }\n\n    // Bool comparisons.\n    case SemIR::BuiltinFunctionKind::BoolEq:\n    case SemIR::BuiltinFunctionKind::BoolNeq: {\n      if (phase != Phase::Concrete) {\n        break;\n      }\n      return PerformBuiltinBoolComparison(context, builtin_kind, arg_ids[0],\n                                          arg_ids[1], call.type_id);\n    }\n  }\n\n  return SemIR::ConstantId::NotConstant;\n}\n\nstatic auto TryEvalCall(EvalContext& outer_eval_context, SemIR::LocId loc_id,\n                        const SemIR::Function& function,\n                        SemIR::SpecificId specific_id,\n                        SemIR::InstBlockId args_id) -> SemIR::ConstantId;\n\n// Makes a constant for a call instruction.\nstatic auto MakeConstantForCall(EvalContext& eval_context,\n                                SemIR::InstId inst_id, SemIR::Call call)\n    -> SemIR::ConstantId {\n  Phase phase = Phase::Concrete;\n\n  // A call with an invalid argument list is used to represent an erroneous\n  // call.\n  //\n  // TODO: Use a better representation for this.\n  if (call.args_id == SemIR::InstBlockId::None) {\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  // Find the constant value of the callee.\n  bool has_constant_callee = ReplaceFieldWithConstantValue(\n      eval_context, &call, &SemIR::Call::callee_id, &phase);\n\n  auto callee = SemIR::GetCallee(eval_context.sem_ir(), call.callee_id);\n  const SemIR::Function* function = nullptr;\n  auto builtin_kind = SemIR::BuiltinFunctionKind::None;\n  auto evaluation_mode = SemIR::Function::EvaluationMode::None;\n  if (auto* callee_function = std::get_if<SemIR::CalleeFunction>(&callee)) {\n    function = &eval_context.functions().Get(callee_function->function_id);\n    builtin_kind = function->builtin_function_kind();\n    evaluation_mode = function->evaluation_mode;\n    // Calls to builtins and to `eval` or `musteval` functions might be\n    // constant.\n    if (builtin_kind == SemIR::BuiltinFunctionKind::None &&\n        evaluation_mode == SemIR::Function::EvaluationMode::None) {\n      return SemIR::ConstantId::NotConstant;\n    }\n  } else {\n    // Calls to non-functions, such as calls to generic entity names, might be\n    // constant.\n  }\n\n  // Find the argument values and the return type.\n  bool has_constant_operands =\n      has_constant_callee &&\n      ReplaceTypeWithConstantValue(eval_context, inst_id, &call, &phase) &&\n      ReplaceFieldWithConstantValue(eval_context, &call, &SemIR::Call::args_id,\n                                    &phase);\n  if (phase == Phase::UnknownDueToError) {\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  // If any operand of the call is non-constant, the call is non-constant.\n  // TODO: Some builtin calls might allow some operands to be non-constant.\n  if (!has_constant_operands) {\n    if (builtin_kind.IsCompTimeOnly(\n            eval_context.sem_ir(), eval_context.inst_blocks().Get(call.args_id),\n            call.type_id) ||\n        evaluation_mode == SemIR::Function::EvaluationMode::MustEval) {\n      CARBON_DIAGNOSTIC(NonConstantCallToCompTimeOnlyFunction, Error,\n                        \"non-constant call to compile-time-only function\");\n      CARBON_DIAGNOSTIC(CompTimeOnlyFunctionHere, Note,\n                        \"compile-time-only function declared here\");\n      const auto& function = eval_context.functions().Get(\n          std::get<SemIR::CalleeFunction>(callee).function_id);\n      eval_context.emitter()\n          .Build(inst_id, NonConstantCallToCompTimeOnlyFunction)\n          .Note(function.latest_decl_id(), CompTimeOnlyFunctionHere)\n          .Emit();\n    }\n    return SemIR::ConstantId::NotConstant;\n  }\n\n  // Handle calls to builtins.\n  if (builtin_kind != SemIR::BuiltinFunctionKind::None) {\n    return MakeConstantForBuiltinCall(\n        eval_context, SemIR::LocId(inst_id), call, builtin_kind,\n        eval_context.inst_blocks().Get(call.args_id), phase);\n  }\n\n  // Handle calls to `eval` and `musteval` functions.\n  if (evaluation_mode != SemIR::Function::EvaluationMode::None) {\n    // A non-concrete call to `eval` or `musteval` is a template symbolic\n    // constant, regardless of the phase of the arguments.\n    if (phase != Phase::Concrete) {\n      CARBON_CHECK(phase <= Phase::TemplateSymbolic);\n      return MakeConstantResult(eval_context.context(), call,\n                                Phase::TemplateSymbolic);\n    }\n\n    // TODO: Instead of performing the call immediately, add it to a work queue\n    // and do it non-recursively.\n    return TryEvalCall(\n        eval_context, SemIR::LocId(inst_id), *function,\n        std::get<SemIR::CalleeFunction>(callee).resolved_specific_id,\n        call.args_id);\n  }\n\n  return SemIR::ConstantId::NotConstant;\n}\n\n// Given an instruction, compute its phase based on its operands.\nstatic auto ComputeInstPhase(Context& context, SemIR::Inst inst) -> Phase {\n  EvalContext eval_context(&context, SemIR::LocId::None);\n\n  auto phase = GetPhase(context.constant_values(),\n                        context.types().GetConstantId(inst.type_id()));\n  GetConstantValueForArg(eval_context, inst.arg0_and_kind(), &phase);\n  GetConstantValueForArg(eval_context, inst.arg1_and_kind(), &phase);\n  CARBON_CHECK(IsConstantOrError(phase));\n  return phase;\n}\n\n// Convert a ConstantEvalResult to a ConstantId. Factored out of\n// TryEvalTypedInst to avoid repeated instantiation of common code.\nstatic auto ConvertEvalResultToConstantId(Context& context,\n                                          ConstantEvalResult result,\n                                          Phase orig_phase)\n    -> SemIR::ConstantId {\n  if (result.is_new()) {\n    return MakeConstantResult(\n        context, result.new_inst(),\n        result.same_phase_as_inst()\n            ? orig_phase\n            : ComputeInstPhase(context, result.new_inst()));\n  }\n  return result.existing();\n}\n\n// Evaluates an instruction of a known type in an evaluation context. The\n// default behavior of this function depends on the constant kind of the\n// instruction:\n//\n//  -  InstConstantKind::Never: returns ConstantId::NotConstant.\n//  -  InstConstantKind::Indirect, SymbolicOnly, SymbolicOrReference,\n//     Conditional: evaluates all the operands of the instruction, and calls\n//     `EvalConstantInst` to evaluate the resulting constant instruction.\n//  -  InstConstantKind::WheneverPossible, Always: evaluates all the operands of\n//     the instruction, and produces the resulting constant instruction as the\n//     result.\n//  -  InstConstantKind::Unique: returns the `inst_id` as the resulting\n//     constant.\n//\n// Returns an error constant ID if any of the nested evaluations fail, and\n// returns NotConstant if any of the nested evaluations is non-constant.\n//\n// This template is explicitly specialized for instructions that need special\n// handling.\ntemplate <typename InstT>\nstatic auto TryEvalTypedInst(EvalContext& eval_context, SemIR::InstId inst_id,\n                             SemIR::Inst inst) -> SemIR::ConstantId {\n  constexpr auto ConstantKind = InstT::Kind.constant_kind();\n  if constexpr (ConstantKind == SemIR::InstConstantKind::Never) {\n    return SemIR::ConstantId::NotConstant;\n  } else if constexpr (ConstantKind == SemIR::InstConstantKind::AlwaysUnique) {\n    CARBON_CHECK(inst_id.has_value());\n    return SemIR::ConstantId::ForConcreteConstant(inst_id);\n  } else {\n    // Build a constant instruction by replacing each non-constant operand with\n    // its constant value.\n    Phase phase = Phase::Concrete;\n    if ((SemIR::Internal::HasTypeIdMember<InstT> &&\n         !ReplaceTypeWithConstantValue(eval_context, inst_id, &inst, &phase)) ||\n        !ReplaceAllFieldsWithConstantValues(eval_context, &inst, &phase)) {\n      if constexpr (ConstantKind == SemIR::InstConstantKind::Always) {\n        CARBON_FATAL(\"{0} should always be constant\", InstT::Kind);\n      }\n      return SemIR::ConstantId::NotConstant;\n    }\n    // If any operand of the instruction has an error in it, the instruction\n    // itself evaluates to an error.\n    if (phase == Phase::UnknownDueToError) {\n      return SemIR::ErrorInst::ConstantId;\n    }\n\n    // When canonicalizing a SpecificId, we defer resolving the specific's\n    // declaration until here, to avoid resolving declarations from imported\n    // specifics. (Imported instructions are not evaluated.)\n    ResolveSpecificDeclForInst(eval_context, inst);\n\n    if constexpr (ConstantKind == SemIR::InstConstantKind::Always ||\n                  ConstantKind == SemIR::InstConstantKind::WheneverPossible) {\n      return MakeConstantResult(eval_context.context(), inst, phase);\n    } else if constexpr (ConstantKind == SemIR::InstConstantKind::InstAction) {\n      auto result_inst_id = PerformDelayedAction(\n          eval_context.context(), SemIR::LocId(inst_id), inst.As<InstT>());\n      if (result_inst_id.has_value()) {\n        // The result is an instruction.\n        return MakeConstantResult(\n            eval_context.context(),\n            SemIR::InstValue{\n                .type_id = GetSingletonType(eval_context.context(),\n                                            SemIR::InstType::TypeInstId),\n                .inst_id = result_inst_id},\n            Phase::Concrete);\n      }\n      // Couldn't perform the action because it's still dependent.\n      return MakeConstantResult(eval_context.context(), inst,\n                                Phase::TemplateSymbolic);\n    } else if constexpr (InstT::Kind.constant_needs_inst_id() !=\n                         SemIR::InstConstantNeedsInstIdKind::No) {\n      CARBON_CHECK(inst_id.has_value());\n      return ConvertEvalResultToConstantId(\n          eval_context.context(),\n          EvalConstantInst(eval_context.context(), inst_id, inst.As<InstT>()),\n          phase);\n    } else {\n      return ConvertEvalResultToConstantId(\n          eval_context.context(),\n          EvalConstantInst(eval_context.context(), inst.As<InstT>()), phase);\n    }\n  }\n}\n\n// Specialize evaluation for array indexing because we want to check the index\n// expression even if the array expression is non-constant.\ntemplate <>\nauto TryEvalTypedInst<SemIR::ArrayIndex>(EvalContext& eval_context,\n                                         SemIR::InstId /*inst_id*/,\n                                         SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  return PerformArrayIndex(eval_context, inst.As<SemIR::ArrayIndex>());\n}\n\n// Specialize evaluation for function calls because we want to check the callee\n// expression even if an argument expression is non-constant, and because we\n// will eventually want to perform control flow handling here.\ntemplate <>\nauto TryEvalTypedInst<SemIR::Call>(EvalContext& eval_context,\n                                   SemIR::InstId inst_id, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  return MakeConstantForCall(eval_context, inst_id, inst.As<SemIR::Call>());\n}\n\n// ImportRefLoaded can have a constant value, but it's owned and maintained by\n// `import_ref.cpp`, not by us.\n// TODO: Rearrange how `ImportRefLoaded` instructions are created so we never\n// call this.\ntemplate <>\nauto TryEvalTypedInst<SemIR::ImportRefLoaded>(EvalContext& /*eval_context*/,\n                                              SemIR::InstId /*inst_id*/,\n                                              SemIR::Inst /*inst*/)\n    -> SemIR::ConstantId {\n  return SemIR::ConstantId::NotConstant;\n}\n\n// Symbolic bindings are a special case because they can reach into the eval\n// context and produce a context-specific value.\ntemplate <>\nauto TryEvalTypedInst<SemIR::SymbolicBinding>(EvalContext& eval_context,\n                                              SemIR::InstId inst_id,\n                                              SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto bind = inst.As<SemIR::SymbolicBinding>();\n\n  // If we know which specific we're evaluating within and this is an argument\n  // of that specific, its constant value is the corresponding argument value.\n  const auto& bind_name = eval_context.entity_names().Get(bind.entity_name_id);\n  if (bind_name.bind_index().has_value()) {\n    if (auto value =\n            eval_context.GetCompileTimeBindValue(bind_name.bind_index());\n        value.has_value()) {\n      return value;\n    }\n  }\n\n  // The constant form of a symbolic binding is an idealized form of the\n  // original, with no equivalent value.\n  Phase phase = Phase::Concrete;\n  bind.value_id = SemIR::InstId::None;\n  if (!ReplaceTypeWithConstantValue(eval_context, inst_id, &bind, &phase) ||\n      !ReplaceFieldWithConstantValue(eval_context, &bind,\n                                     &SemIR::SymbolicBinding::entity_name_id,\n                                     &phase)) {\n    return SemIR::ConstantId::NotConstant;\n  }\n  // This correctly handles `Phase::UnknownDueToError`.\n  return MakeConstantResult(eval_context.context(), bind, phase);\n}\n\ntemplate <>\nauto TryEvalTypedInst<SemIR::SymbolicBindingType>(EvalContext& eval_context,\n                                                  SemIR::InstId inst_id,\n                                                  SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  // If a specific provides a new value for the binding with `entity_name_id`,\n  // the SymbolicBindingType is evaluated for that new value.\n  const auto& bind_name = eval_context.entity_names().Get(\n      inst.As<SemIR::SymbolicBindingType>().entity_name_id);\n  if (bind_name.bind_index().has_value()) {\n    if (auto value =\n            eval_context.GetCompileTimeBindValue(bind_name.bind_index());\n        value.has_value()) {\n      auto value_inst_id = eval_context.constant_values().GetInstId(value);\n\n      // A SymbolicBindingType can evaluate to a FacetAccessType if the new\n      // value of the entity is a facet value that that does not have a concrete\n      // type (a FacetType) and does not have a new EntityName to point to (a\n      // SymbolicBinding).\n      auto access = SemIR::FacetAccessType{\n          .type_id = SemIR::TypeType::TypeId,\n          .facet_value_inst_id = value_inst_id,\n      };\n      return ConvertEvalResultToConstantId(\n          eval_context.context(),\n          EvalConstantInst(eval_context.context(), access),\n          ComputeInstPhase(eval_context.context(), access));\n    }\n  }\n\n  Phase phase = Phase::Concrete;\n  if (!ReplaceTypeWithConstantValue(eval_context, inst_id, &inst, &phase) ||\n      !ReplaceAllFieldsWithConstantValues(eval_context, &inst, &phase)) {\n    return SemIR::ConstantId::NotConstant;\n  }\n  // Propagate error phase after getting the constant value for all fields.\n  if (phase == Phase::UnknownDueToError) {\n    return SemIR::ErrorInst::ConstantId;\n  }\n\n  // Evaluation of SymbolicBindingType.\n  //\n  // Like FacetAccessType, a SymbolicBindingType of a FacetValue just evaluates\n  // to the type inside.\n  //\n  // TODO: Look in ScopeStack with the entity_name_id to find the facet value\n  // and get its constant value in the current specific context. The\n  // facet_value_inst_id will go away.\n  if (auto facet_value = eval_context.insts().TryGetAs<SemIR::FacetValue>(\n          inst.As<SemIR::SymbolicBindingType>().facet_value_inst_id)) {\n    return eval_context.constant_values().Get(facet_value->type_inst_id);\n  }\n\n  return MakeConstantResult(eval_context.context(), inst, phase);\n}\n\n// Returns whether `const_id` is the same constant facet value as\n// `facet_value_inst_id`.\n//\n// Compares with the canonical facet value of `const_id`, dropping any `as type`\n// conversions.\nstatic auto IsSameFacetValue(Context& context, SemIR::ConstantId const_id,\n                             SemIR::InstId facet_value_inst_id) -> bool {\n  auto canon_const_id = GetCanonicalFacetOrTypeValue(context, const_id);\n  return canon_const_id == context.constant_values().Get(facet_value_inst_id);\n}\n\n// TODO: Convert this to an EvalConstantInst function. This will require\n// providing a `GetConstantValue` overload for a requirement block.\ntemplate <>\nauto TryEvalTypedInst<SemIR::WhereExpr>(EvalContext& eval_context,\n                                        SemIR::InstId inst_id, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto typed_inst = inst.As<SemIR::WhereExpr>();\n\n  Phase phase = Phase::Concrete;\n  SemIR::FacetTypeInfo info;\n\n  // Add the constraints from the `WhereExpr` instruction into `info`.\n  if (typed_inst.requirements_id.has_value()) {\n    auto insts = eval_context.inst_blocks().Get(typed_inst.requirements_id);\n    for (auto inst_id : insts) {\n      if (auto base =\n              eval_context.insts().TryGetAs<SemIR::RequirementBaseFacetType>(\n                  inst_id)) {\n        if (base->base_type_inst_id == SemIR::ErrorInst::TypeInstId) {\n          return SemIR::ErrorInst::ConstantId;\n        }\n\n        if (auto base_facet_type =\n                eval_context.insts().TryGetAs<SemIR::FacetType>(\n                    base->base_type_inst_id)) {\n          const auto& base_info =\n              eval_context.facet_types().Get(base_facet_type->facet_type_id);\n          info.extend_constraints.append(base_info.extend_constraints);\n          info.self_impls_constraints.append(base_info.self_impls_constraints);\n          info.rewrite_constraints.append(base_info.rewrite_constraints);\n          info.other_requirements |= base_info.other_requirements;\n        }\n      } else if (auto rewrite =\n                     eval_context.insts().TryGetAs<SemIR::RequirementRewrite>(\n                         inst_id)) {\n        info.rewrite_constraints.push_back(\n            {.lhs_id = rewrite->lhs_id, .rhs_id = rewrite->rhs_id});\n      } else if (auto impls =\n                     eval_context.insts().TryGetAs<SemIR::RequirementImpls>(\n                         inst_id)) {\n        SemIR::ConstantId lhs_const_id =\n            eval_context.GetConstantValue(impls->lhs_id);\n        SemIR::ConstantId rhs_const_id =\n            eval_context.GetConstantValue(impls->rhs_id);\n        if (IsSameFacetValue(eval_context.context(), lhs_const_id,\n                             typed_inst.period_self_id)) {\n          auto rhs_inst_id =\n              eval_context.constant_values().GetInstId(rhs_const_id);\n          if (rhs_inst_id == SemIR::ErrorInst::InstId) {\n            // `.Self impls <error>`.\n            return SemIR::ErrorInst::ConstantId;\n          } else if (rhs_inst_id == SemIR::TypeType::TypeInstId) {\n            // `.Self impls type` -> nothing to do.\n          } else {\n            auto facet_type = eval_context.insts().GetAs<SemIR::FacetType>(\n                RequireConstantValue(eval_context, impls->rhs_id, &phase));\n            const auto& more_info =\n                eval_context.facet_types().Get(facet_type.facet_type_id);\n            // The way to prevent lookup into the interface requirements of a\n            // facet type is to put it to the right of a `.Self impls`, which we\n            // accomplish by putting them into `self_impls_constraints`.\n            llvm::append_range(info.self_impls_constraints,\n                               more_info.extend_constraints);\n            llvm::append_range(info.self_impls_constraints,\n                               more_info.self_impls_constraints);\n            llvm::append_range(info.self_impls_named_constraints,\n                               more_info.extend_named_constraints);\n            llvm::append_range(info.self_impls_named_constraints,\n                               more_info.self_impls_named_constraints);\n            // Other requirements are copied in.\n            llvm::append_range(info.rewrite_constraints,\n                               more_info.rewrite_constraints);\n            info.other_requirements |= more_info.other_requirements;\n          }\n        } else {\n          // TODO: Handle `impls` constraints beyond `.Self impls`.\n          info.other_requirements = true;\n        }\n      } else {\n        // TODO: Handle other requirements.\n        info.other_requirements = true;\n      }\n    }\n  }\n\n  auto const_info = GetConstantFacetTypeInfo(\n      eval_context, SemIR::LocId(inst_id), info, &phase);\n  return MakeFacetTypeResult(eval_context.context(), const_info, phase);\n}\n\n// Implementation for `TryEvalInst`, wrapping `Context` with `EvalContext`.\nstatic auto TryEvalInstInContext(EvalContext& eval_context,\n                                 SemIR::InstId inst_id, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  using EvalInstFn =\n      auto(EvalContext & eval_context, SemIR::InstId inst_id, SemIR::Inst inst)\n          ->SemIR::ConstantId;\n  static constexpr EvalInstFn* EvalInstFns[] = {\n#define CARBON_SEM_IR_INST_KIND(Kind) &TryEvalTypedInst<SemIR::Kind>,\n#include \"toolchain/sem_ir/inst_kind.def\"\n  };\n  [[clang::musttail]] return EvalInstFns[inst.kind().AsInt()](eval_context,\n                                                              inst_id, inst);\n}\n\nauto TryEvalInstUnsafe(Context& context, SemIR::InstId inst_id,\n                       SemIR::Inst inst) -> SemIR::ConstantId {\n  EvalContext eval_context(&context, SemIR::LocId(inst_id));\n  return TryEvalInstInContext(eval_context, inst_id, inst);\n}\n\nauto TryEvalBlockForSpecific(Context& context, SemIR::LocId loc_id,\n                             SemIR::SpecificId specific_id,\n                             SemIR::GenericInstIndex::Region region)\n    -> SemIR::InstBlockId {\n  auto generic_id = context.specifics().Get(specific_id).generic_id;\n  auto eval_block_id = context.generics().Get(generic_id).GetEvalBlock(region);\n  auto eval_block = context.inst_blocks().Get(eval_block_id);\n\n  llvm::SmallVector<SemIR::InstId> result;\n  result.resize(eval_block.size(), SemIR::InstId::None);\n\n  EvalContext eval_context(&context, loc_id, specific_id,\n                           SpecificEvalInfo{\n                               .region = region,\n                               .values = result,\n                           });\n\n  Diagnostics::ContextScope diagnostic_context(\n      &context.emitter(), [&](auto& builder) {\n        CARBON_DIAGNOSTIC(ResolvingSpecificHere, SoftContext,\n                          \"unable to monomorphize specific {0}\",\n                          SemIR::SpecificId);\n        builder.Context(loc_id, ResolvingSpecificHere, specific_id);\n      });\n\n  for (auto [i, inst_id] : llvm::enumerate(eval_block)) {\n    auto const_id = TryEvalInstInContext(eval_context, inst_id,\n                                         context.insts().Get(inst_id));\n    result[i] = context.constant_values().GetInstId(const_id);\n    CARBON_CHECK(result[i].has_value(), \"Failed to evaluate {0} in eval block\",\n                 context.insts().Get(inst_id));\n  }\n\n  return context.inst_blocks().Add(result);\n}\n\n// Information about the function call we are currently executing. Unlike\n// evaluation, execution sequentially interprets instructions, and can handle\n// control flow and (eventually) side effects and mutable state.\nclass FunctionExecContext : public EvalContext {\n public:\n  // A block argument passed to `BranchWithArg`.\n  struct BlockArgValue {\n    SemIR::InstBlockId block_id = SemIR::InstBlockId::None;\n    SemIR::ConstantId arg_id = SemIR::ConstantId::None;\n  };\n\n  FunctionExecContext(Context* context, SemIR::LocId loc_id,\n                      SemIR::SpecificId specific_id,\n                      Map<SemIR::InstId, SemIR::ConstantId>* locals,\n                      SemIR::InstBlockId args_id)\n      : EvalContext(context, loc_id, specific_id,\n                    LocalEvalInfo{.locals = locals}),\n        args_(context->inst_blocks().Get(args_id)) {}\n\n  // Returns the argument values supplied in the call to the function.\n  auto args() const -> llvm::ArrayRef<SemIR::InstId> { return args_; }\n\n  using EvalContext::locals;\n\n  // Branch control flow to the given block. This replaces the innermost block\n  // in the block stack, but doesn't affect any enclosing blocks.\n  auto BranchTo(SemIR::InstBlockId block_id) -> void {\n    blocks_.back() = inst_blocks().Get(block_id);\n  }\n\n  // Push a new block to be executed immediately. After the block finishes,\n  // control will resume after the current instruction.\n  auto PushBlock(SemIR::InstBlockId block_id) -> void {\n    blocks_.push_back(inst_blocks().Get(block_id));\n  }\n\n  // Pops and returns the next instruction to be executed.\n  auto PopNextInstId() -> SemIR::InstId {\n    while (blocks_.back().empty()) {\n      blocks_.pop_back();\n      CARBON_CHECK(!blocks_.empty(), \"Fell off end of function\");\n    }\n    return blocks_.back().consume_front();\n  }\n\n  // Sets the most recent block argument value provided by a `BranchWithArg`.\n  // This can later be retrieved by a `BlockArg`.\n  auto SetCurrentBlockArgValue(BlockArgValue arg) -> void {\n    current_block_arg_value_ = arg;\n  }\n\n  // Returns the most recent block argument value provided by a `BranchWithArg`.\n  auto current_block_arg_value() const -> BlockArgValue {\n    return current_block_arg_value_;\n  }\n\n private:\n  // The stack of code blocks that we are currently evaluating. This is kept as\n  // a stack so that we can schedule the function body to execute after the decl\n  // block and so that we can handle `SpliceBlock`s. When the innermost block is\n  // complete, it will be popped and the next outer block will execute.\n  llvm::SmallVector<llvm::ArrayRef<SemIR::InstId>, 4> blocks_;\n\n  // The arguments in the function call.\n  llvm::ArrayRef<SemIR::InstId> args_;\n\n  // The block argument provided by the most recently executed `BranchWithArg`.\n  // We assume that we only need to track one of these, as the branch target\n  // will invoke `BlockArg` before the next `BranchWithArg` happens. We will\n  // need to track more than one of these if that ever changes.\n  BlockArgValue current_block_arg_value_;\n};\n\n// Handles the result of executing an instruction in a function. Returns an\n// error the result is not a constant, and otherwise updates the locals map to\n// track the result as an input to later evaluations in this function and\n// returns None.\nstatic auto HandleExecResult(FunctionExecContext& eval_context,\n                             SemIR::InstId inst_id, SemIR::ConstantId const_id)\n    -> SemIR::ConstantId {\n  if (!const_id.has_value() || !const_id.is_constant()) {\n    DiagnoseNonConstantValue(eval_context, inst_id);\n    return SemIR::ErrorInst::ConstantId;\n  }\n  if (const_id == SemIR::ErrorInst::ConstantId) {\n    return const_id;\n  }\n  eval_context.locals().Update(inst_id, const_id);\n  return SemIR::ConstantId::None;\n}\n\n// Executes an instruction for TryEvalCall. By default, performs normal\n// evaluation of the instruction within a context that supplies the values\n// produced by executing prior instructions in this function execution. This is\n// specialized for instructions that have special handling in function\n// execution, such as those that access parameters or perform flow control. If\n// execution should continue, returns `SemIR::ConstantId::None`, otherwise\n// returns the result to produce for the enclosing function call, which should\n// be either the returned value or an error.\ntemplate <typename InstT>\nstatic auto TryExecTypedInst(FunctionExecContext& eval_context,\n                             SemIR::InstId inst_id, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  if constexpr (InstT::Kind.expr_category().TryAsFixedCategory() ==\n                SemIR::ExprCategory::NotExpr) {\n    // Instructions in this category are assumed to not have a runtime effect.\n    // This includes some kinds of declaration.\n    return SemIR::ConstantId::None;\n  }\n\n  if constexpr (InstT::Kind.constant_kind() != SemIR::InstConstantKind::Never) {\n    if (eval_context.constant_values().Get(inst_id).is_concrete()) {\n      // Instruction has a concrete constant value that doesn't depend on the\n      // context. We don't need to evaluate it again.\n      return SemIR::ConstantId::None;\n    }\n  }\n\n  // Evaluate the instruction in the current context.\n  auto const_id = TryEvalTypedInst<InstT>(eval_context, inst_id, inst);\n  return HandleExecResult(eval_context, inst_id, const_id);\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::BlockArg>(FunctionExecContext& eval_context,\n                                       SemIR::InstId inst_id, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto block_arg = inst.As<SemIR::BlockArg>();\n  CARBON_CHECK(\n      block_arg.block_id == eval_context.current_block_arg_value().block_id,\n      \"BlockArg does not refer to most recent BranchWithArg\");\n  eval_context.locals().Update(inst_id,\n                               eval_context.current_block_arg_value().arg_id);\n  return SemIR::ConstantId::None;\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::Branch>(FunctionExecContext& eval_context,\n                                     SemIR::InstId /*inst_id*/,\n                                     SemIR::Inst inst) -> SemIR::ConstantId {\n  auto branch = inst.As<SemIR::Branch>();\n  eval_context.BranchTo(branch.target_id);\n  return SemIR::ConstantId::None;\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::BranchIf>(FunctionExecContext& eval_context,\n                                       SemIR::InstId /*inst_id*/,\n                                       SemIR::Inst inst) -> SemIR::ConstantId {\n  auto branch_if = inst.As<SemIR::BranchIf>();\n  auto cond_id = CheckConcreteValue(eval_context, branch_if.cond_id);\n  if (cond_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ErrorInst::ConstantId;\n  }\n  auto cond = eval_context.insts().GetAs<SemIR::BoolLiteral>(cond_id);\n  if (cond.value == SemIR::BoolValue::True) {\n    eval_context.BranchTo(branch_if.target_id);\n  }\n  return SemIR::ConstantId::None;\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::BranchWithArg>(FunctionExecContext& eval_context,\n                                            SemIR::InstId /*inst_id*/,\n                                            SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto branch = inst.As<SemIR::BranchWithArg>();\n  eval_context.SetCurrentBlockArgValue(\n      {.block_id = branch.target_id,\n       .arg_id = eval_context.GetConstantValue(branch.arg_id)});\n  eval_context.BranchTo(branch.target_id);\n  return SemIR::ConstantId::None;\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::Return>(FunctionExecContext& eval_context,\n                                     SemIR::InstId /*inst_id*/,\n                                     SemIR::Inst /*inst*/)\n    -> SemIR::ConstantId {\n  return MakeEmptyTupleResult(eval_context);\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::ReturnExpr>(FunctionExecContext& eval_context,\n                                         SemIR::InstId /*inst_id*/,\n                                         SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto return_expr = inst.As<SemIR::ReturnExpr>();\n  return eval_context.GetConstantValue(return_expr.expr_id);\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::ReturnSlot>(FunctionExecContext& eval_context,\n                                         SemIR::InstId inst_id,\n                                         SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto return_slot = inst.As<SemIR::ReturnSlot>();\n  // In the case where the function's return type is not in-place, the return\n  // slot will refer to an out parameter that doesn't have an argument. In that\n  // case, we don't have a constant value for storage_id. To handle this, copy\n  // the value directly from the locals map rather than using GetConstantValue.\n  //\n  // TODO: Remove this and use a normal call to `GetConstantValue` if we stop\n  // adding out parameters with no corresponding argument.\n  eval_context.locals().Insert(\n      inst_id, eval_context.locals().Lookup(return_slot.storage_id).value());\n  return SemIR::ConstantId::None;\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::SpliceBlock>(FunctionExecContext& eval_context,\n                                          SemIR::InstId /*inst_id*/,\n                                          SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto splice_block = inst.As<SemIR::SpliceBlock>();\n  eval_context.PushBlock(splice_block.block_id);\n  // TODO: Copy the values from the result_id instruction to the result of\n  // the splice_block instruction once the spliced block finishes.\n  return SemIR::ConstantId::None;\n}\n\n// Executes the introduction of a parameter into the local scope. Copies the\n// argument supplied by the caller for the parameter into the locals map.\nstatic auto TryExecTypedParam(FunctionExecContext& eval_context,\n                              SemIR::InstId inst_id, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto param = inst.As<SemIR::AnyParam>();\n  CARBON_CHECK(static_cast<size_t>(param.index.index) <\n               eval_context.args().size());\n  eval_context.locals().Insert(inst_id,\n                               eval_context.constant_values().Get(\n                                   eval_context.args()[param.index.index]));\n  return SemIR::ConstantId::None;\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::OutParam>(FunctionExecContext& eval_context,\n                                       SemIR::InstId inst_id, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto param = inst.As<SemIR::OutParam>();\n  if (static_cast<size_t>(param.index.index) >= eval_context.args().size()) {\n    // For return values that have a copy initializing representation, the SemIR\n    // has an OutParam with an index that has no corresponding argument. In that\n    // case, we do not have a constant value for the parameter, but this doesn't\n    // prevent the call from being constant.\n    //\n    // TODO: Remove this once we stop adding out parameters with no\n    // corresponding argument.\n    eval_context.locals().Insert(inst_id, SemIR::ConstantId::None);\n    return SemIR::ConstantId::None;\n  }\n\n  return TryExecTypedParam(eval_context, inst_id, inst);\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::RefParam>(FunctionExecContext& eval_context,\n                                       SemIR::InstId inst_id, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  return TryExecTypedParam(eval_context, inst_id, inst);\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::ValueParam>(FunctionExecContext& eval_context,\n                                         SemIR::InstId inst_id,\n                                         SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  return TryExecTypedParam(eval_context, inst_id, inst);\n}\n\ntemplate <>\nauto TryExecTypedInst<SemIR::ValueBinding>(FunctionExecContext& eval_context,\n                                           SemIR::InstId inst_id,\n                                           SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  auto value_binding = inst.As<SemIR::ValueBinding>();\n  auto local_value_id = eval_context.GetConstantValue(value_binding.value_id);\n  eval_context.locals().Insert(inst_id, local_value_id);\n  return SemIR::ConstantId::None;\n}\n\nstatic auto TryExecInst(FunctionExecContext& eval_context,\n                        SemIR::InstId inst_id, SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  using ExecInstFn = auto(FunctionExecContext & eval_context,\n                          SemIR::InstId inst_id, SemIR::Inst inst)\n                         ->SemIR::ConstantId;\n  static constexpr ExecInstFn* ExecInstFns[] = {\n#define CARBON_SEM_IR_INST_KIND(Kind) &TryExecTypedInst<SemIR::Kind>,\n#include \"toolchain/sem_ir/inst_kind.def\"\n  };\n  [[clang::musttail]] return ExecInstFns[inst.kind().AsInt()](eval_context,\n                                                              inst_id, inst);\n}\n\n// Evaluates a call to an `eval` or `musteval` function by executing the\n// function body.\nstatic auto TryEvalCall(EvalContext& outer_eval_context, SemIR::LocId loc_id,\n                        const SemIR::Function& function,\n                        SemIR::SpecificId specific_id,\n                        SemIR::InstBlockId args_id) -> SemIR::ConstantId {\n  if (function.clang_decl_id != SemIR::ClangDeclId::None) {\n    return EvalCppCall(outer_eval_context.context(), loc_id,\n                       function.clang_decl_id, args_id);\n  } else if (function.body_block_ids.empty()) {\n    // TODO: Diagnose this.\n    return SemIR::ConstantId::NotConstant;\n  }\n\n  // TODO: Consider tracking the lowest and highest inst_id in the function and\n  // using an array instead of a map. We would still need a map for instantiated\n  // portions of a function template.\n  Map<SemIR::InstId, SemIR::ConstantId> locals;\n\n  FunctionExecContext eval_context(&outer_eval_context.context(), loc_id,\n                                   specific_id, &locals, args_id);\n\n  Diagnostics::AnnotationScope annotate_diagnostics(\n      &eval_context.emitter(), [&](auto& builder) {\n        CARBON_DIAGNOSTIC(InCallToEvalFn, Note, \"in call to {0} here\",\n                          SemIR::NameId);\n        builder.Note(loc_id, InCallToEvalFn, function.name_id);\n      });\n\n  // Execute the function decl block followed by the body.\n  eval_context.PushBlock(function.body_block_ids.front());\n  eval_context.PushBlock(eval_context.insts()\n                             .GetAs<SemIR::FunctionDecl>(function.definition_id)\n                             .decl_block_id);\n\n  // Execute the blocks. This is mostly expression evaluation, with special\n  // handling for control flow and parameters.\n  while (true) {\n    auto inst_id = eval_context.PopNextInstId();\n    auto inst = eval_context.context().insts().Get(inst_id);\n    if (auto result = TryExecInst(eval_context, inst_id, inst);\n        result.has_value()) {\n      return result;\n    }\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/eval.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_EVAL_H_\n#define CARBON_TOOLCHAIN_CHECK_EVAL_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/inst_kind.h\"\n\nnamespace Carbon::Check {\n\n// Adds a `ConstantId` for a constant that has been imported from another IR.\n// Does not evaluate the instruction, instead trusting that it is already in a\n// suitable form, but does canonicalize the operands if necessary.\n// TODO: Rely on import to canonicalize the operands to avoid this work.\nauto AddImportedConstant(Context& context, SemIR::Inst inst)\n    -> SemIR::ConstantId;\n\n// Evaluates the instruction `inst`. If `inst_id` is specified, it is the ID of\n// the instruction; otherwise, evaluation of the instruction must not require an\n// `InstId` to be provided.\nauto TryEvalInstUnsafe(Context& context, SemIR::InstId inst_id,\n                       SemIR::Inst inst) -> SemIR::ConstantId;\n\n// Determines the phase of the instruction `inst_id`, and returns its constant\n// value if it has constant phase. If it has runtime phase, returns\n// `SemIR::ConstantId::NotConstant`.\ninline auto TryEvalInst(Context& context, SemIR::InstId inst_id)\n    -> SemIR::ConstantId {\n  return TryEvalInstUnsafe(context, inst_id, context.insts().Get(inst_id));\n}\n\n// Same, but for a typed instruction that doesn't have an InstId assigned yet,\n// in the case where evaluation doesn't need an InstId. This can be used to\n// avoid allocating an instruction in the case where you just want a constant\n// value and the instruction is known to not matter. However, even then care\n// should be taken: if the produced constant is symbolic, you may still need an\n// instruction to associate the constant with the enclosing generic.\n//\n// To evaluate an instruction and add it to SemIR only if necessary, use\n// EvalOrAddInst instead.\ntemplate <typename InstT>\n  requires(InstT::Kind.constant_needs_inst_id() ==\n           SemIR::InstConstantNeedsInstIdKind::No)\nauto TryEvalInst(Context& context, InstT inst) -> SemIR::ConstantId {\n  return TryEvalInstUnsafe(context, SemIR::InstId::None, inst);\n}\n\n// Evaluates the eval block for a region of a specific. Produces a block\n// containing the evaluated constant values of the instructions in the eval\n// block.\n//\n// TODO: Return whether any of the instructions produced contain an ErrorInst.\nauto TryEvalBlockForSpecific(Context& context, SemIR::LocId loc_id,\n                             SemIR::SpecificId specific_id,\n                             SemIR::GenericInstIndex::Region region)\n    -> SemIR::InstBlockId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_EVAL_H_\n"
  },
  {
    "path": "toolchain/check/eval_inst.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/eval_inst.h\"\n\n#include <variant>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/action.h\"\n#include \"toolchain/check/cpp/constant.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/cpp/type_mapping.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/impl_lookup.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/parse/typed_nodes.h\"\n#include \"toolchain/sem_ir/builtin_function_kind.h\"\n#include \"toolchain/sem_ir/expr_info.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/pattern.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Performs an access into an aggregate, retrieving the specified element.\nstatic auto PerformAggregateAccess(Context& context, SemIR::Inst inst)\n    -> ConstantEvalResult {\n  auto access_inst = inst.As<SemIR::AnyAggregateAccess>();\n  if (auto aggregate = context.insts().TryGetAs<SemIR::AnyAggregateValue>(\n          access_inst.aggregate_id)) {\n    auto elements = context.inst_blocks().Get(aggregate->elements_id);\n    auto index = static_cast<size_t>(access_inst.index.index);\n    CARBON_CHECK(index < elements.size(), \"Access out of bounds.\");\n    // `Phase` is not used here. If this element is a concrete constant, then\n    // so is the result of indexing, even if the aggregate also contains a\n    // symbolic context.\n    return ConstantEvalResult::Existing(\n        context.constant_values().Get(elements[index]));\n  }\n\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::ArrayInit inst)\n    -> ConstantEvalResult {\n  // TODO: Add an `ArrayValue` to represent a constant array object\n  // representation instead of using a `TupleValue`.\n  return ConstantEvalResult::NewSamePhase(\n      SemIR::TupleValue{.type_id = inst.type_id, .elements_id = inst.inits_id});\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::ArrayType inst) -> ConstantEvalResult {\n  auto bound_inst = context.insts().Get(inst.bound_id);\n  auto int_bound = bound_inst.TryAs<SemIR::IntValue>();\n  if (!int_bound) {\n    CARBON_CHECK(context.constant_values().Get(inst.bound_id).is_symbolic(),\n                 \"Unexpected inst {0} for template constant int\", bound_inst);\n    return ConstantEvalResult::NewSamePhase(inst);\n  }\n  // TODO: We should check that the size of the resulting array type\n  // fits in 64 bits, not just that the bound does. Should we use a\n  // 32-bit limit for 32-bit targets?\n  const auto& bound_val = context.ints().Get(int_bound->int_id);\n  if (context.types().IsSignedInt(int_bound->type_id) &&\n      bound_val.isNegative()) {\n    CARBON_DIAGNOSTIC(ArrayBoundNegative, Error,\n                      \"array bound of {0} is negative\", TypedInt);\n    context.emitter().Emit(\n        context.insts().GetAs<SemIR::ArrayType>(inst_id).bound_id,\n        ArrayBoundNegative, {.type = int_bound->type_id, .value = bound_val});\n    return ConstantEvalResult::Error;\n  }\n  if (bound_val.getActiveBits() > 64) {\n    CARBON_DIAGNOSTIC(ArrayBoundTooLarge, Error,\n                      \"array bound of {0} is too large\", TypedInt);\n    context.emitter().Emit(\n        context.insts().GetAs<SemIR::ArrayType>(inst_id).bound_id,\n        ArrayBoundTooLarge, {.type = int_bound->type_id, .value = bound_val});\n    return ConstantEvalResult::Error;\n  }\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::AsCompatible inst)\n    -> ConstantEvalResult {\n  // AsCompatible changes the type of the source instruction; its constant\n  // value, if there is one, needs to be modified to be of the same type.\n  auto value_id = context.constant_values().Get(inst.source_id);\n  CARBON_CHECK(value_id.is_constant());\n\n  auto value_inst =\n      context.insts().Get(context.constant_values().GetInstId(value_id));\n  value_inst.SetType(inst.type_id);\n  return ConstantEvalResult::NewAnyPhase(value_inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::AliasBinding inst)\n    -> ConstantEvalResult {\n  // An alias evaluates to the value it's bound to.\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.value_id));\n}\n\nauto EvalConstantInst(Context& context, SemIR::RefBinding inst)\n    -> ConstantEvalResult {\n  // A reference binding evaluates to the value it's bound to.\n  if (inst.value_id.has_value()) {\n    return ConstantEvalResult::Existing(\n        context.constant_values().Get(inst.value_id));\n  }\n  return ConstantEvalResult::NotConstant;\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::ValueBinding /*inst*/)\n    -> ConstantEvalResult {\n  // Non-`:!` value bindings are not constant.\n  return ConstantEvalResult::NotConstant;\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::AcquireValue inst) -> ConstantEvalResult {\n  if (const auto* var_decl = GetAsClangVarDecl(context, inst.value_id)) {\n    auto const_id =\n        EvalCppVarDecl(context, SemIR::LocId(inst_id), var_decl, inst.type_id);\n    if (const_id.has_value() && const_id.is_constant()) {\n      return ConstantEvalResult::Existing(const_id);\n    }\n\n    return ConstantEvalResult::NotConstant;\n  }\n\n  return ConstantEvalResult::TODO;\n}\n\nauto EvalConstantInst(Context& context, SemIR::ClassElementAccess inst)\n    -> ConstantEvalResult {\n  return PerformAggregateAccess(context, inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::ClassDecl inst)\n    -> ConstantEvalResult {\n  const auto& class_info = context.classes().Get(inst.class_id);\n\n  // If the class has generic parameters, we don't produce a class type, but a\n  // callable whose return value is a class type.\n  if (class_info.has_parameters()) {\n    return ConstantEvalResult::NewSamePhase(SemIR::StructValue{\n        .type_id = inst.type_id, .elements_id = SemIR::InstBlockId::Empty});\n  }\n\n  // A non-generic class declaration evaluates to the class type.\n  return ConstantEvalResult::NewAnyPhase(SemIR::ClassType{\n      .type_id = SemIR::TypeType::TypeId,\n      .class_id = inst.class_id,\n      .specific_id =\n          context.generics().GetSelfSpecific(class_info.generic_id)});\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::ClassInit inst)\n    -> ConstantEvalResult {\n  // TODO: Add a `ClassValue` to represent a constant class object\n  // representation instead of using a `StructValue`.\n  return ConstantEvalResult::NewSamePhase(SemIR::StructValue{\n      .type_id = inst.type_id, .elements_id = inst.elements_id});\n}\n\nauto EvalConstantInst(Context& context, SemIR::ConstType inst)\n    -> ConstantEvalResult {\n  // `const (const T)` evaluates to `const T`.\n  if (context.insts().Is<SemIR::ConstType>(inst.inner_id)) {\n    return ConstantEvalResult::Existing(\n        context.constant_values().Get(inst.inner_id));\n  }\n  // Otherwise, `const T` evaluates to itself.\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::PartialType inst)\n    -> ConstantEvalResult {\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::Converted inst)\n    -> ConstantEvalResult {\n  // A conversion evaluates to the result of the conversion.\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.result_id));\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::Deref /*inst*/)\n    -> ConstantEvalResult {\n  // TODO: Handle this.\n  return ConstantEvalResult::TODO;\n}\n\nauto EvalConstantInst(Context& context, SemIR::ExportDecl inst)\n    -> ConstantEvalResult {\n  // An export instruction evaluates to the exported declaration.\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.value_id));\n}\n\nauto EvalConstantInst(Context& context, SemIR::FacetAccessType inst)\n    -> ConstantEvalResult {\n  if (auto facet_value = context.insts().TryGetAs<SemIR::FacetValue>(\n          inst.facet_value_inst_id)) {\n    return ConstantEvalResult::Existing(\n        context.constant_values().Get(facet_value->type_inst_id));\n  }\n\n  if (auto bind_name = context.insts().TryGetAs<SemIR::SymbolicBinding>(\n          inst.facet_value_inst_id)) {\n    return ConstantEvalResult::NewSamePhase(SemIR::SymbolicBindingType{\n        .type_id = SemIR::TypeType::TypeId,\n        .entity_name_id = bind_name->entity_name_id,\n        // TODO: This is to be removed, at which point explore if we should\n        // replace NewSamePhase with NewAnyPhase (to make the constant value\n        // concrete). This is still a symbolic type though even if the inst\n        // doesn't contain a symbolic constant. Previously we crashed in CHECKs\n        // when we had a symbolic instruction with only an EntityNameId, due to\n        // it not changing in a generic eval block. Maybe that has improved in\n        // the latest version of this instruction. If it's not symbolic, then\n        // SubstConstantCallbacks and other Subst callers may need to handle\n        // looking through concrete instructions which would be unfortunate.\n        .facet_value_inst_id = inst.facet_value_inst_id});\n  }\n\n  // The `facet_value_inst_id` is always a facet value (has type facet type).\n  CARBON_CHECK(context.types().Is<SemIR::FacetType>(\n      context.insts().Get(inst.facet_value_inst_id).type_id()));\n\n  // Other instructions (e.g. ImplWitnessAccess) of type FacetType can appear\n  // here, in which case the constant inst is a FacetAccessType until those\n  // instructions resolve to one of the above.\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::FacetValue inst)\n    -> ConstantEvalResult {\n  // A FacetValue that just wraps a SymbolicBinding without adding/removing any\n  // witnesses is evaluated back to the SymbolicBinding itself.\n  if (auto bind_as_type = context.insts().TryGetAs<SemIR::SymbolicBindingType>(\n          inst.type_inst_id)) {\n    // TODO: Look in ScopeStack with the entity_name_id to find the facet value.\n    auto bind_id = bind_as_type->facet_value_inst_id;\n    auto bind = context.insts().GetAs<SemIR::SymbolicBinding>(bind_id);\n    // If the FacetTypes are the same, then the FacetValue didn't add/remove\n    // any witnesses.\n    if (bind.type_id == inst.type_id) {\n      return ConstantEvalResult::Existing(\n          context.constant_values().Get(bind_id));\n    }\n  }\n\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::FloatType inst) -> ConstantEvalResult {\n  return ValidateFloatTypeAndSetKind(context, SemIR::LocId(inst_id), inst)\n             ? ConstantEvalResult::NewSamePhase(inst)\n             : ConstantEvalResult::Error;\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::FunctionDecl inst)\n    -> ConstantEvalResult {\n  // A function declaration evaluates to a function object, which is an empty\n  // object of function type.\n  // TODO: Eventually we may need to handle captures here.\n  return ConstantEvalResult::NewSamePhase(SemIR::StructValue{\n      .type_id = inst.type_id, .elements_id = SemIR::InstBlockId::Empty});\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::LookupImplWitness inst) -> ConstantEvalResult {\n  // The self value is canonicalized in order to produce a canonical\n  // LookupImplWitness instruction, avoiding multiple constant values for\n  // `<facet value>` and `<facet value>` as type, which always have the same\n  // lookup result.\n  auto self_facet_value_inst_id =\n      GetCanonicalFacetOrTypeValue(context, inst.query_self_inst_id);\n\n  // When we look for a witness in the (facet) type of self, we may get a\n  // concrete witness from a `FacetValue` (which is `self_facet_value_inst_id`)\n  // in which case this instruction evaluates to that witness.\n  //\n  // If we only get a symbolic witness result though, then this instruction\n  // evaluates to a `LookupImplWitness`. Since there was no concrete result in\n  // the `FacetValue`, we don't need to preserve it. By looking through the\n  // `FacetValue` at the type value it wraps to generate a more canonical value\n  // for a symbolic `LookupImplWitness`. This makes us produce the same constant\n  // value for symbolic lookups in `FacetValue(T)` and `T`, since they will\n  // always have the same lookup result later, when `T` is replaced in a\n  // specific by something that can provide a concrete witness.\n  if (auto facet_value = context.insts().TryGetAs<SemIR::FacetValue>(\n          self_facet_value_inst_id)) {\n    inst.query_self_inst_id =\n        GetCanonicalFacetOrTypeValue(context, facet_value->type_inst_id);\n  } else {\n    inst.query_self_inst_id = self_facet_value_inst_id;\n  }\n\n  auto result = EvalLookupSingleImplWitness(context, SemIR::LocId(inst_id),\n                                            inst, self_facet_value_inst_id,\n                                            EvalImplLookupMode::Normal);\n  if (!result.has_value()) {\n    // We use NotConstant to communicate back to impl lookup that the lookup\n    // failed. This can not happen for a deferred symbolic lookup in a generic\n    // eval block, since we only add the deferred lookup instruction (being\n    // evaluated here) to the SemIR if the lookup succeeds.\n    return ConstantEvalResult::NotConstant;\n  }\n  if (result.has_final_value()) {\n    return ConstantEvalResult::Existing(\n        context.constant_values().Get(result.final_witness()));\n  }\n\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::ImplWitnessAccess inst) -> ConstantEvalResult {\n  CARBON_DIAGNOSTIC(ImplAccessMemberBeforeSet, Error,\n                    \"accessing member from impl before it has a defined value\");\n  CARBON_KIND_SWITCH(context.insts().Get(inst.witness_id)) {\n    case CARBON_KIND(SemIR::ImplWitness witness): {\n      // This is PerformAggregateAccess followed by GetConstantValueInSpecific.\n      auto witness_table = context.insts().GetAs<SemIR::ImplWitnessTable>(\n          witness.witness_table_id);\n      auto elements = context.inst_blocks().Get(witness_table.elements_id);\n      // `elements` can be empty if there is only a forward declaration of the\n      // impl.\n      if (!elements.empty()) {\n        auto index = static_cast<size_t>(inst.index.index);\n        CARBON_CHECK(index < elements.size(), \"Access out of bounds.\");\n        auto element = elements[index];\n        if (element.has_value()) {\n          LoadImportRef(context, element);\n          return ConstantEvalResult::Existing(GetConstantValueInSpecific(\n              context.sem_ir(), witness.specific_id, element));\n        }\n      }\n      // If we get here, this impl witness table entry has not been populated\n      // yet, because the impl was referenced within its own definition.\n      // TODO: Add note pointing to the impl declaration.\n      context.emitter().Emit(inst_id, ImplAccessMemberBeforeSet);\n      return ConstantEvalResult::Error;\n    }\n    case CARBON_KIND(SemIR::CustomWitness custom_witness): {\n      auto elements = context.inst_blocks().Get(custom_witness.elements_id);\n      auto index = static_cast<size_t>(inst.index.index);\n      // `elements` can be shorter than the number of associated entities while\n      // we're building the synthetic witness.\n      if (index < elements.size()) {\n        return ConstantEvalResult::Existing(\n            context.constant_values().Get(elements[index]));\n      }\n      // If we get here, this synthesized witness table entry has not been\n      // populated yet.\n      // TODO: Is this reachable? We have no test coverage for this diagnostic.\n      context.emitter().Emit(inst_id, ImplAccessMemberBeforeSet);\n      return ConstantEvalResult::Error;\n    }\n    case CARBON_KIND(SemIR::LookupImplWitness witness): {\n      // If the witness is symbolic but has a self type that is a FacetType, it\n      // can pull rewrite values from the self type. If the access is for one of\n      // those rewrites, evaluate to the RHS of the rewrite.\n\n      auto witness_self_type_id =\n          context.insts().Get(witness.query_self_inst_id).type_id();\n      if (!context.types().Is<SemIR::FacetType>(witness_self_type_id)) {\n        return ConstantEvalResult::NewSamePhase(inst);\n      }\n\n      // The `ImplWitnessAccess` is accessing a value, by index, for this\n      // interface.\n      auto access_interface_id = witness.query_specific_interface_id;\n\n      auto witness_self_facet_type_id =\n          context.types()\n              .GetAs<SemIR::FacetType>(witness_self_type_id)\n              .facet_type_id;\n      // TODO: We could consider something better than linear search here, such\n      // as a map. However that would probably require heap allocations which\n      // may be worse overall since the number of rewrite constraints is\n      // generally low. If the `rewrite_constraints` were sorted so that\n      // associated constants are grouped together, as in\n      // ResolveFacetTypeRewriteConstraints(), and limited to just the\n      // `ImplWitnessAccess` entries, then a binary search may work here.\n      for (auto witness_rewrite : context.facet_types()\n                                      .Get(witness_self_facet_type_id)\n                                      .rewrite_constraints) {\n        // Look at each rewrite constraint in the self facet value's type. If\n        // the LHS is an `ImplWitnessAccess` into the same interface that `inst`\n        // is indexing into, then we can use its RHS as the value.\n        auto witness_rewrite_lhs_access =\n            context.insts().TryGetAs<SemIR::ImplWitnessAccess>(\n                witness_rewrite.lhs_id);\n        if (!witness_rewrite_lhs_access) {\n          continue;\n        }\n        if (witness_rewrite_lhs_access->index != inst.index) {\n          continue;\n        }\n\n        auto witness_rewrite_lhs_interface_id =\n            context.insts()\n                .GetAs<SemIR::LookupImplWitness>(\n                    witness_rewrite_lhs_access->witness_id)\n                .query_specific_interface_id;\n        if (witness_rewrite_lhs_interface_id != access_interface_id) {\n          continue;\n        }\n\n        // The `ImplWitnessAccess` evaluates to the RHS from the witness self\n        // facet value's type.\n        return ConstantEvalResult::Existing(\n            context.constant_values().Get(witness_rewrite.rhs_id));\n      }\n      break;\n    }\n    default:\n      break;\n  }\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context,\n                      SemIR::ImplWitnessAccessSubstituted inst)\n    -> ConstantEvalResult {\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.value_id));\n}\n\nauto EvalConstantInst(Context& context,\n                      SemIR::ImplWitnessAssociatedConstant inst)\n    -> ConstantEvalResult {\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.inst_id));\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::ImportRefUnloaded inst)\n    -> ConstantEvalResult {\n  CARBON_FATAL(\"ImportRefUnloaded should be loaded before TryEvalInst: {0}\",\n               inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::InPlaceInit inst)\n    -> ConstantEvalResult {\n  // Initialization is not performed in-place during constant evaluation, so\n  // just return the value of the initializer.\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.src_id));\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::IntType inst) -> ConstantEvalResult {\n  return ValidateIntType(context, SemIR::LocId(inst_id), inst)\n             ? ConstantEvalResult::NewSamePhase(inst)\n             : ConstantEvalResult::Error;\n}\n\nauto EvalConstantInst(Context& context, SemIR::InterfaceDecl inst)\n    -> ConstantEvalResult {\n  const auto& interface_info = context.interfaces().Get(inst.interface_id);\n\n  // If the interface has generic parameters, we don't produce an interface\n  // type, but a callable whose return value is an interface type.\n  if (interface_info.has_parameters()) {\n    return ConstantEvalResult::NewSamePhase(SemIR::StructValue{\n        .type_id = inst.type_id, .elements_id = SemIR::InstBlockId::Empty});\n  }\n\n  // A non-parameterized interface declaration evaluates to a declared facet\n  // type containing just the interface.\n  return ConstantEvalResult::NewAnyPhase(FacetTypeFromInterface(\n      context, inst.interface_id,\n      context.generics().GetSelfSpecific(interface_info.generic_id)));\n}\n\nauto EvalConstantInst(Context& context, SemIR::NamedConstraintDecl inst)\n    -> ConstantEvalResult {\n  const auto& named_constraint_info =\n      context.named_constraints().Get(inst.named_constraint_id);\n\n  // If the named constraint has generic parameters, we don't produce a named\n  // constraint type, but a callable whose return value is a named constraint\n  // type.\n  if (named_constraint_info.has_parameters()) {\n    return ConstantEvalResult::NewSamePhase(SemIR::StructValue{\n        .type_id = inst.type_id, .elements_id = SemIR::InstBlockId::Empty});\n  }\n\n  // A non-parameterized named constraint declaration evaluates to a declared\n  // facet type containing just the named constraint.\n  return ConstantEvalResult::NewAnyPhase(FacetTypeFromNamedConstraint(\n      context, inst.named_constraint_id,\n      context.generics().GetSelfSpecific(named_constraint_info.generic_id)));\n}\n\nauto EvalConstantInst(Context& context, SemIR::NameRef inst)\n    -> ConstantEvalResult {\n  // A name reference evaluates to the value the name resolves to.\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.value_id));\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::RequireCompleteType inst) -> ConstantEvalResult {\n  auto witness_type_id =\n      GetSingletonType(context, SemIR::WitnessType::TypeInstId);\n\n  // If the type is a concrete constant, require it to be complete now.\n  auto complete_type_id =\n      context.types().GetTypeIdForTypeInstId(inst.complete_type_inst_id);\n  if (complete_type_id.is_concrete()) {\n    Diagnostics::ContextScope diagnostic_context(\n        &context.emitter(), [&](auto& builder) {\n          CARBON_DIAGNOSTIC(IncompleteTypeInMonomorphization, Context,\n                            \"{0} evaluates to incomplete type {1}\",\n                            InstIdAsType, InstIdAsType);\n          builder.Context(inst_id, IncompleteTypeInMonomorphization,\n                          context.insts()\n                              .GetAs<SemIR::RequireCompleteType>(inst_id)\n                              .complete_type_inst_id,\n                          inst.complete_type_inst_id);\n        });\n    // We use TryToCompleteType() instead of RequireCompleteType() because we\n    // are currently evaluating a RequireCompleteType instruction, and calling\n    // RequireCompleteType() would insert another copy of the same instruction.\n    if (!TryToCompleteType(context, complete_type_id, SemIR::LocId(inst_id),\n                           true)) {\n      return ConstantEvalResult::Error;\n    }\n    return ConstantEvalResult::NewSamePhase(SemIR::CompleteTypeWitness{\n        .type_id = witness_type_id,\n        .object_repr_type_inst_id = context.types().GetTypeInstId(\n            context.types().GetObjectRepr(complete_type_id))});\n  }\n\n  // If it's not a concrete constant, require it to be complete once it\n  // becomes one.\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::RequireSpecificDefinition inst)\n    -> ConstantEvalResult {\n  // This can return false, we just need to try it.\n  ResolveSpecificDefinition(context, SemIR::LocId::None, inst.specific_id);\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::SpecificConstant inst)\n    -> ConstantEvalResult {\n  // Pull the constant value out of the specific.\n  return ConstantEvalResult::Existing(SemIR::GetConstantValueInSpecific(\n      context.sem_ir(), inst.specific_id, inst.inst_id));\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::SpecificImplFunction inst) -> ConstantEvalResult {\n  auto callee_inst = context.insts().Get(inst.callee_id);\n  // If the callee is not a function value, we're not ready to evaluate this\n  // yet. Build a symbolic `SpecificImplFunction` constant.\n  if (!callee_inst.Is<SemIR::StructValue>()) {\n    return ConstantEvalResult::NewSamePhase(inst);\n  }\n  auto callee_type_id = callee_inst.type_id();\n  auto callee_fn_type =\n      context.types().TryGetAs<SemIR::FunctionType>(callee_type_id);\n  if (!callee_fn_type) {\n    return ConstantEvalResult::NewSamePhase(inst);\n  }\n\n  // If the callee function found in the impl witness is not generic, the result\n  // is simply that function.\n  // TODO: We could do this even before the callee is concrete.\n  auto generic_id =\n      context.functions().Get(callee_fn_type->function_id).generic_id;\n  if (!generic_id.has_value()) {\n    return ConstantEvalResult::Existing(\n        context.constant_values().Get(inst.callee_id));\n  }\n\n  // Find the arguments to use.\n  auto enclosing_specific_id = callee_fn_type->specific_id;\n  auto enclosing_args = context.inst_blocks().Get(\n      context.specifics().GetArgsOrEmpty(enclosing_specific_id));\n  auto interface_fn_args = context.inst_blocks().Get(\n      context.specifics().GetArgsOrEmpty(inst.specific_id));\n\n  // Form new specific for the generic callee function. The arguments for this\n  // specific are the enclosing arguments of the callee followed by the\n  // remaining arguments from the interface function. Impl checking has ensured\n  // that these arguments can also be used for the function in the impl witness.\n  auto num_params = context.inst_blocks()\n                        .Get(context.generics().Get(generic_id).bindings_id)\n                        .size();\n  llvm::SmallVector<SemIR::InstId> args;\n  args.reserve(num_params);\n  args.append(enclosing_args.begin(), enclosing_args.end());\n  int remaining_params = num_params - args.size();\n  CARBON_CHECK(static_cast<int>(interface_fn_args.size()) >= remaining_params);\n  args.append(interface_fn_args.end() - remaining_params,\n              interface_fn_args.end());\n  auto specific_id =\n      MakeSpecific(context, SemIR::LocId(inst_id), generic_id, args);\n  context.definitions_required_by_use().push_back(\n      {SemIR::LocId(inst_id), specific_id});\n\n  return ConstantEvalResult::NewSamePhase(\n      SemIR::SpecificFunction{.type_id = inst.type_id,\n                              .callee_id = inst.callee_id,\n                              .specific_id = specific_id});\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::SpecificFunction inst) -> ConstantEvalResult {\n  auto callee_function =\n      SemIR::GetCalleeAsFunction(context.sem_ir(), inst.callee_id);\n  const auto& fn = context.functions().Get(callee_function.function_id);\n  if (!callee_function.self_type_id.has_value() &&\n      fn.builtin_function_kind() != SemIR::BuiltinFunctionKind::NoOp &&\n      fn.virtual_modifier != SemIR::Function::VirtualModifier::Abstract) {\n    // This is not an associated function. Those will be required to be defined\n    // as part of checking that the impl is complete.\n    context.definitions_required_by_use().push_back(\n        {SemIR::LocId(inst_id), inst.specific_id});\n  }\n  // Create new constant for a specific function.\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::SpliceBlock inst)\n    -> ConstantEvalResult {\n  // SpliceBlock evaluates to the result value that is (typically) within the\n  // block. This can be constant even if the block contains other non-constant\n  // instructions.\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.result_id));\n}\n\nauto EvalConstantInst(Context& context, SemIR::SpliceInst inst)\n    -> ConstantEvalResult {\n  // The constant value of a SpliceInst is the constant value of the instruction\n  // being spliced. Note that `inst.inst_id` is the instruction being spliced,\n  // so we need to go through another round of obtaining the constant value in\n  // addition to the one performed by the eval infrastructure.\n  if (auto inst_value =\n          context.insts().TryGetAs<SemIR::InstValue>(inst.inst_id)) {\n    return ConstantEvalResult::Existing(\n        context.constant_values().Get(inst_value->inst_id));\n  }\n  // TODO: Consider creating a new `ValueOfInst` instruction analogous to\n  // `TypeOfInst` to defer determining the constant value until we know the\n  // instruction. Alternatively, produce a symbolic `SpliceInst` constant.\n  return ConstantEvalResult::NotConstant;\n}\n\nauto EvalConstantInst(Context& context, SemIR::StructAccess inst)\n    -> ConstantEvalResult {\n  return PerformAggregateAccess(context, inst);\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::StructInit inst)\n    -> ConstantEvalResult {\n  return ConstantEvalResult::NewSamePhase(SemIR::StructValue{\n      .type_id = inst.type_id, .elements_id = inst.elements_id});\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::StructLiteral inst)\n    -> ConstantEvalResult {\n  return ConstantEvalResult::NewSamePhase(SemIR::StructValue{\n      .type_id = inst.type_id, .elements_id = inst.elements_id});\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::Temporary /*inst*/)\n    -> ConstantEvalResult {\n  // TODO: Handle this. Can we just return the value of `init_id`?\n  return ConstantEvalResult::TODO;\n}\n\nauto EvalConstantInst(Context& context, SemIR::TupleAccess inst)\n    -> ConstantEvalResult {\n  return PerformAggregateAccess(context, inst);\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::TupleInit inst)\n    -> ConstantEvalResult {\n  return ConstantEvalResult::NewSamePhase(SemIR::TupleValue{\n      .type_id = inst.type_id, .elements_id = inst.elements_id});\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::TupleLiteral inst)\n    -> ConstantEvalResult {\n  return ConstantEvalResult::NewSamePhase(SemIR::TupleValue{\n      .type_id = inst.type_id, .elements_id = inst.elements_id});\n}\n\nauto EvalConstantInst(Context& context, SemIR::TypeComponentOf inst)\n    -> ConstantEvalResult {\n  auto form_constant_inst_id =\n      context.constant_values().GetConstantInstId(inst.form_inst_id);\n  if (auto primitive_form = context.insts().TryGetAs<SemIR::AnyPrimitiveForm>(\n          form_constant_inst_id)) {\n    return ConstantEvalResult::Existing(\n        context.constant_values().Get(primitive_form->type_component_id));\n  }\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::TypeLiteral inst)\n    -> ConstantEvalResult {\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.value_id));\n}\n\nauto EvalConstantInst(Context& context, SemIR::TypeOfInst inst)\n    -> ConstantEvalResult {\n  // Grab the type from the instruction produced as our operand.\n  if (auto inst_value =\n          context.insts().TryGetAs<SemIR::InstValue>(inst.inst_id)) {\n    return ConstantEvalResult::Existing(context.types().GetConstantId(\n        context.insts().Get(inst_value->inst_id).type_id()));\n  }\n  return ConstantEvalResult::NewSamePhase(inst);\n}\n\nauto EvalConstantInst(Context& context, SemIR::UnaryOperatorNot inst)\n    -> ConstantEvalResult {\n  // `not true` -> `false`, `not false` -> `true`.\n  // All other uses of unary `not` are non-constant.\n  auto const_id = context.constant_values().Get(inst.operand_id);\n  if (const_id.is_concrete()) {\n    auto value = context.insts().GetAs<SemIR::BoolLiteral>(\n        context.constant_values().GetInstId(const_id));\n    value.value = SemIR::BoolValue::From(!value.value.ToBool());\n    return ConstantEvalResult::NewSamePhase(value);\n  }\n  return ConstantEvalResult::NotConstant;\n}\n\nauto EvalConstantInst(Context& /*context*/, SemIR::UpdateInit /*inst*/)\n    -> ConstantEvalResult {\n  // TODO: Support folding together a ClassInit with an update that sets the\n  // vptr.\n  return ConstantEvalResult::TODO;\n}\n\nauto EvalConstantInst(Context& context, SemIR::ValueOfInitializer inst)\n    -> ConstantEvalResult {\n  // Values of value expressions and initializing expressions are represented in\n  // the same way during constant evaluation, so just return the value of the\n  // operand.\n  return ConstantEvalResult::Existing(\n      context.constant_values().Get(inst.init_id));\n}\n\nauto EvalConstantInst(Context& context, SemIR::InstId inst_id,\n                      SemIR::VarStorage inst) -> ConstantEvalResult {\n  if (!inst.pattern_id.has_value()) {\n    // This variable was not created from a `var` pattern, so isn't a global\n    // variable.\n    return ConstantEvalResult::NotConstant;\n  }\n\n  // A variable is constant if it's global.\n  auto entity_name_id = SemIR::GetFirstBindingNameFromPatternId(\n      context.sem_ir(), inst.pattern_id);\n  if (!entity_name_id.has_value()) {\n    // Variable doesn't introduce any bindings, so can only be referenced by its\n    // own initializer. We treat such a reference as not being constant.\n    return ConstantEvalResult::NotConstant;\n  }\n\n  auto scope_id = context.entity_names().Get(entity_name_id).parent_scope_id;\n  if (!scope_id.has_value()) {\n    return ConstantEvalResult::NotConstant;\n  }\n  auto scope_inst =\n      context.insts().Get(context.name_scopes().Get(scope_id).inst_id());\n  if (!scope_inst.Is<SemIR::Namespace>() &&\n      !scope_inst.Is<SemIR::ClassDecl>()) {\n    // Only namespace-scope and class-scope variables are reference constants.\n    // Class-scope variables cannot currently be declared directly, but can\n    // occur when static data members are imported from C++.\n    return ConstantEvalResult::NotConstant;\n  }\n\n  // This is a constant reference expression denoting this global variable.\n  return ConstantEvalResult::Existing(\n      SemIR::ConstantId::ForConcreteConstant(inst_id));\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/eval_inst.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_EVAL_INST_H_\n#define CARBON_TOOLCHAIN_CHECK_EVAL_INST_H_\n\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/sem_ir/inst_kind.h\"\n\nnamespace Carbon::Check {\n\n// The result of constant evaluation of an instruction.\nclass ConstantEvalResult {\n public:\n  // Produce a new constant as the result of an evaluation. The phase of the\n  // produced constant must be the same as the greatest phase of the operands in\n  // the evaluation. This will typically be the case if the evaluation uses all\n  // of its operands.\n  static auto NewSamePhase(SemIR::Inst inst) -> ConstantEvalResult {\n    return ConstantEvalResult(inst, /*same_phase_as_inst=*/true);\n  }\n\n  // Produce a new constant as the result of an evaluation. The constant may\n  // have any phase. Use `NewSamePhase` instead where possible, as it avoids a\n  // phase recomputation.\n  static auto NewAnyPhase(SemIR::Inst inst) -> ConstantEvalResult {\n    return ConstantEvalResult(inst, /*same_phase_as_inst=*/false);\n  }\n\n  // Produce an existing constant as the result of an evaluation.\n  static constexpr auto Existing(SemIR::ConstantId existing_id)\n      -> ConstantEvalResult {\n    CARBON_CHECK(existing_id.has_value());\n    return ConstantEvalResult(existing_id);\n  }\n\n  // Indicates that an error was produced by evaluation.\n  static const ConstantEvalResult Error;\n\n  // Indicates that we encountered an instruction whose evaluation is\n  // non-constant despite having constant operands. This should be rare;\n  // usually we want to produce an error in this case.\n  static const ConstantEvalResult NotConstant;\n\n  // Indicates that we encountered an instruction for which we've not\n  // implemented constant evaluation yet. Instruction is treated as not\n  // constant.\n  static const ConstantEvalResult TODO;\n\n  // Returns whether the result of evaluation is that we should produce a new\n  // constant described by `new_inst()` rather than an existing `ConstantId`\n  // described by `existing()`.\n  auto is_new() const -> bool { return !result_id_.has_value(); }\n\n  // Returns the existing constant that this the instruction evaluates to, or\n  // `None` if this is evaluation produces a new constant.\n  auto existing() const -> SemIR::ConstantId { return result_id_; }\n\n  // Returns the new constant instruction that is the result of evaluation.\n  auto new_inst() const -> SemIR::Inst {\n    CARBON_CHECK(is_new());\n    return new_inst_;\n  }\n\n  // Whether the new constant instruction is known to have the same phase as the\n  // evaluated instruction. Requires `is_new()`.\n  auto same_phase_as_inst() const -> bool {\n    CARBON_CHECK(is_new());\n    return same_phase_as_inst_;\n  }\n\n private:\n  constexpr explicit ConstantEvalResult(SemIR::ConstantId raw_id)\n      : result_id_(raw_id), same_phase_as_inst_(false) {}\n\n  explicit ConstantEvalResult(SemIR::Inst inst, bool same_phase_as_inst)\n      : result_id_(SemIR::ConstantId::None),\n        new_inst_(inst),\n        same_phase_as_inst_(same_phase_as_inst) {}\n\n  SemIR::ConstantId result_id_;\n  union {\n    SemIR::Inst new_inst_;\n  };\n  bool same_phase_as_inst_;\n};\n\ninline constexpr ConstantEvalResult ConstantEvalResult::Error =\n    Existing(SemIR::ErrorInst::ConstantId);\n\ninline constexpr ConstantEvalResult ConstantEvalResult::NotConstant =\n    ConstantEvalResult(SemIR::ConstantId::NotConstant);\n\ninline constexpr ConstantEvalResult ConstantEvalResult::TODO = NotConstant;\n\n// Implementation details to compute the type of the `EvalConstantInst`\n// functions.\nnamespace Internal {\n\n// Returns whether an `EvalConstantInst` overload is expected to exist for this\n// instruction constant kind.\nconstexpr auto ConstantKindHasEvalConstantInst(SemIR::InstConstantKind kind)\n    -> bool {\n  switch (kind) {\n    case SemIR::InstConstantKind::Never:\n    case SemIR::InstConstantKind::InstAction:\n    case SemIR::InstConstantKind::WheneverPossible:\n    case SemIR::InstConstantKind::Always:\n    case SemIR::InstConstantKind::AlwaysUnique:\n      return false;\n\n    case SemIR::InstConstantKind::Indirect:\n    case SemIR::InstConstantKind::SymbolicOnly:\n    case SemIR::InstConstantKind::SymbolicOrReference:\n    case SemIR::InstConstantKind::Conditional:\n    case SemIR::InstConstantKind::ConditionalUnique:\n      return true;\n  }\n}\n\n// Given an instruction kind, determines the type that should be used to declare\n// `EvalConstantInst` for that instruction.\ntemplate <typename InstT, bool HasFn, bool HasInstId>\nstruct FunctionTypeForEvalConstantInstImpl {\n  // By default, we want no `EvalConstantInst` function at all. But we can't\n  // express that, so use the type `auto () -> void` as a placeholder.\n  using Type = auto() -> void;\n};\ntemplate <typename InstT>\nstruct FunctionTypeForEvalConstantInstImpl<InstT, true, false> {\n  // Can be evaluated, evaluation doesn't need InstId.\n  using Type = auto(Context& context, InstT inst) -> ConstantEvalResult;\n};\ntemplate <typename InstT>\nstruct FunctionTypeForEvalConstantInstImpl<InstT, true, true> {\n  // Can be evaluated, evaluation needs InstId.\n  using Type = auto(Context& context, SemIR::InstId inst_id, InstT inst)\n      -> ConstantEvalResult;\n};\ntemplate <typename InstT>\nusing FunctionTypeForEvalConstantInst =\n    typename FunctionTypeForEvalConstantInstImpl<\n        InstT, ConstantKindHasEvalConstantInst(InstT::Kind.constant_kind()),\n        InstT::Kind.constant_needs_inst_id() !=\n            SemIR::InstConstantNeedsInstIdKind::No>::Type;\n\n}  // namespace Internal\n\n// Explicitly delete the overload generated for non-evaluatable instructions.\n// These all produce the same signature, so we only need to delete it once.\nauto EvalConstantInst() -> void = delete;\n\n// `EvalConstantInst` evaluates an instruction whose operands are all constant,\n// in a context unrelated to the enclosing evaluation. The function is given the\n// instruction after its operands, including its type, are replaced by their\n// evaluated value, and returns a `ConstantEvalResult` describing the result of\n// evaluating the instruction.\n//\n// An overload is defined for each type whose constant kind is one of the\n// following:\n//\n// - InstConstantKind::Indirect\n// - InstConstantKind::SymbolicOnly\n// - InstConstantKind::SymbolicOrReference\n// - InstConstantKind::Conditional\n// - InstConstantKind::ConditionalUnique\n//\n// ... except for cases where the result of evaluation depends on the evaluation\n// context itself. Those cases are handled by explicit specialization of\n// `TryEvalTypedInst` in `eval.cpp` instead.\n//\n// The signature of an overload is\n//\n//   auto EvalConstantInst(Context& context, SemIR::InstId inst_id, InstT inst)\n//       -> ConstantEvalResult;\n//\n// if `InstT::Kind.constant_needs_inst_id()` is true, and\n//\n//   auto EvalConstantInst(Context& context, InstT inst) -> ConstantEvalResult;\n//\n// otherwise.\n//\n// Overloads are *declared* for all types, because there isn't a good way to\n// declare only the overloads we want here without duplicating the list of\n// types. Missing overloads will be diagnosed when linking. Excess overloads\n// map to a deleted signature to prevent accidental calls.\n#define CARBON_SEM_IR_INST_KIND(Kind) \\\n  Internal::FunctionTypeForEvalConstantInst<SemIR::Kind> EvalConstantInst;\n#include \"toolchain/sem_ir/inst_kind.def\"\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_EVAL_INST_H_\n"
  },
  {
    "path": "toolchain/check/facet_type.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/facet_type.h\"\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/interface.h\"\n#include \"toolchain/check/subst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/sem_ir/generic.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto FacetTypeFromInterface(Context& context, SemIR::InterfaceId interface_id,\n                            SemIR::SpecificId specific_id) -> SemIR::FacetType {\n  auto info = SemIR::FacetTypeInfo{};\n  info.extend_constraints.push_back({interface_id, specific_id});\n  info.Canonicalize();\n  SemIR::FacetTypeId facet_type_id = context.facet_types().Add(info);\n  return {.type_id = SemIR::TypeType::TypeId, .facet_type_id = facet_type_id};\n}\n\nauto FacetTypeFromNamedConstraint(Context& context,\n                                  SemIR::NamedConstraintId named_constraint_id,\n                                  SemIR::SpecificId specific_id)\n    -> SemIR::FacetType {\n  auto info = SemIR::FacetTypeInfo{};\n  info.extend_named_constraints.push_back({named_constraint_id, specific_id});\n  info.Canonicalize();\n  SemIR::FacetTypeId facet_type_id = context.facet_types().Add(info);\n  return {.type_id = SemIR::TypeType::TypeId, .facet_type_id = facet_type_id};\n}\n\nauto GetImplWitnessAccessWithoutSubstitution(Context& context,\n                                             SemIR::InstId inst_id)\n    -> SemIR::InstId {\n  if (auto inst = context.insts().TryGetAs<SemIR::ImplWitnessAccessSubstituted>(\n          inst_id)) {\n    return inst->impl_witness_access_id;\n  }\n  return inst_id;\n}\n\n// A mapping of each associated constant (represented as `ImplWitnessAccess`) to\n// its value (represented as an `InstId`). Used to track rewrite constraints,\n// with the LHS mapping to the resolved value of the RHS.\nclass AccessRewriteValues {\n public:\n  enum State {\n    NotRewritten,\n    BeingRewritten,\n    FullyRewritten,\n  };\n  struct Value {\n    State state;\n    SemIR::InstId inst_id;\n  };\n\n  auto InsertNotRewritten(\n      Context& context, SemIR::KnownInstId<SemIR::ImplWitnessAccess> access_id,\n      SemIR::InstId inst_id) -> void {\n    map_.Insert(context.constant_values().Get(access_id),\n                {NotRewritten, inst_id});\n  }\n\n  // Finds and returns a pointer into the cache for a given ImplWitnessAccess.\n  // The pointer will be invalidated by mutating the cache. Returns `nullptr`\n  // if `access` is not found.\n  auto FindRef(Context& context,\n               SemIR::KnownInstId<SemIR::ImplWitnessAccess> access_id)\n      -> Value* {\n    auto result = map_.Lookup(context.constant_values().Get(access_id));\n    if (!result) {\n      return nullptr;\n    }\n    return &result.value();\n  }\n\n  auto SetBeingRewritten(Value& value) -> void {\n    if (value.state == NotRewritten) {\n      value.state = BeingRewritten;\n    }\n  }\n\n  auto SetFullyRewritten(Context& context, Value& value, SemIR::InstId inst_id)\n      -> void {\n    if (value.state == FullyRewritten) {\n      CARBON_CHECK(context.constant_values().Get(value.inst_id) ==\n                   context.constant_values().Get(inst_id));\n    }\n    value = {FullyRewritten, inst_id};\n  }\n\n private:\n  // Try avoid heap allocations in the common case where there are a small\n  // number of rewrite rules referring to each other by keeping up to 16 on\n  // the stack.\n  //\n  // TODO: Revisit if 16 is an appropriate number when we can measure how deep\n  // rewrite constraint chains go in practice.\n  Map<SemIR::ConstantId, Value, 16> map_;\n};\n\n// To be used for substituting into the RHS of a rewrite constraint.\n//\n// It will substitute any `ImplWitnessAccess` into `.Self` (a reference to an\n// associated constant) with the RHS of another rewrite constraint that writes\n// to the same associated constant. For example:\n// ```\n// Z where .X = () and .Y = .X\n// ```\n// Here the second `.X` is an `ImplWitnessAccess` which would be substituted by\n// finding the first rewrite constraint, where the LHS is for the same\n// associated constant and using its RHS. So the substitution would produce:\n// ```\n// Z where .X = () and .Y = ()\n// ```\n//\n// This additionally diagnoses cycles when the `ImplWitnessAccess` is reading\n// from the same rewrite constraint, and is thus assigning to the associated\n// constant a value that refers to the same associated constant, such as with `Z\n// where .X = C(.X)`. In the event of a cycle, the `ImplWitnessAccess` is\n// replaced with `ErrorInst` so that further evaluation of the\n// `ImplWitnessAccess` will not loop infinitely.\n//\n// The `rewrite_values` given to the constructor must be set up initially with\n// each rewrite rule of an associated constant inserted with its unresolved\n// value via `InsertNotRewritten`. Then for each rewrite rule of an associated\n// constant, the LHS access should be set as being rewritten with its state\n// changed to `BeingRewritten` in order to detect cycles before performing\n// SubstInst. The result of SubstInst should be preserved afterward by changing\n// the state and value for the LHS to `FullyRewritten` and the subst output\n// instruction, respectively, to avoid duplicating work.\nclass SubstImplWitnessAccessCallbacks : public SubstInstCallbacks {\n public:\n  explicit SubstImplWitnessAccessCallbacks(Context* context,\n                                           SemIR::LocId loc_id,\n                                           AccessRewriteValues* rewrite_values)\n      : SubstInstCallbacks(context),\n        loc_id_(loc_id),\n        rewrite_values_(rewrite_values) {}\n\n  auto Subst(SemIR::InstId& rhs_inst_id) -> SubstResult override {\n    auto rhs_access =\n        context().insts().TryGetAsWithId<SemIR::ImplWitnessAccess>(rhs_inst_id);\n    if (!rhs_access) {\n      // We only want to substitute ImplWitnessAccesses written directly on the\n      // RHS of the rewrite constraint, not when they are nested inside facet\n      // types that are part of the RHS, like `.X = C as (I where .Y = {})`.\n      if (context().insts().Is<SemIR::FacetType>(rhs_inst_id)) {\n        return SubstResult::FullySubstituted;\n      }\n      if (context().constant_values().Get(rhs_inst_id).is_concrete()) {\n        // There's no ImplWitnessAccess that we care about inside this\n        // instruction.\n        return SubstResult::FullySubstituted;\n      }\n      if (auto subst =\n              context().insts().TryGetAs<SemIR::ImplWitnessAccessSubstituted>(\n                  rhs_inst_id)) {\n        // The reference to an associated constant was eagerly replaced with the\n        // value of an earlier rewrite constraint, but may need further\n        // substitution if it contains an `ImplWitnessAccess`.\n        rhs_inst_id = subst->value_id;\n        substs_in_progress_.push_back(rhs_inst_id);\n        return SubstResult::SubstAgain;\n      }\n      // SubstOperands will result in a Rebuild or ReuseUnchanged callback, so\n      // push the non-ImplWitnessAccess to get proper bracketing, allowing us\n      // to pop it in the paired callback.\n      substs_in_progress_.push_back(rhs_inst_id);\n      return SubstResult::SubstOperands;\n    }\n\n    // If the access is going through a nested `ImplWitnessAccess`, that\n    // access needs to be resolved to a facet value first. If it can't be\n    // resolved then the outer one can not be either.\n    if (auto lookup = context().insts().TryGetAs<SemIR::LookupImplWitness>(\n            rhs_access->inst.witness_id)) {\n      if (context().insts().Is<SemIR::ImplWitnessAccess>(\n              lookup->query_self_inst_id)) {\n        substs_in_progress_.push_back(rhs_inst_id);\n        return SubstResult::SubstOperandsAndRetry;\n      }\n    }\n\n    auto* rewrite_value =\n        rewrite_values_->FindRef(context(), rhs_access->inst_id);\n    if (!rewrite_value) {\n      // The RHS refers to an associated constant for which there is no rewrite\n      // rule.\n      return SubstResult::FullySubstituted;\n    }\n\n    // Diagnose a cycle if the RHS refers to something that depends on the value\n    // of the RHS.\n    if (rewrite_value->state == AccessRewriteValues::BeingRewritten) {\n      CARBON_DIAGNOSTIC(FacetTypeConstraintCycle, Error,\n                        \"found cycle in facet type constraint for {0}\",\n                        InstIdAsConstant);\n      // TODO: It would be nice to note the places where the values are\n      // assigned but rewrite constraint instructions are from canonical\n      // constant values, and have no locations. We'd need to store a location\n      // along with them in the rewrite constraints, and track propagation of\n      // locations here, which may imply heap allocations.\n      context().emitter().Emit(loc_id_, FacetTypeConstraintCycle, rhs_inst_id);\n      rhs_inst_id = SemIR::ErrorInst::InstId;\n      return SubstResult::FullySubstituted;\n    } else if (rewrite_value->state == AccessRewriteValues::FullyRewritten) {\n      rhs_inst_id = rewrite_value->inst_id;\n      return SubstResult::FullySubstituted;\n    }\n\n    // We have a non-rewritten RHS. We need to recurse on rewriting it. Reuse\n    // the previous lookup by mutating it in place.\n    rewrite_values_->SetBeingRewritten(*rewrite_value);\n\n    // The ImplWitnessAccess was replaced with some other instruction, which may\n    // contain or be another ImplWitnessAccess. Keep track of the associated\n    // constant we are now computing the value of.\n    substs_in_progress_.push_back(rhs_inst_id);\n    rhs_inst_id = rewrite_value->inst_id;\n    return SubstResult::SubstAgain;\n  }\n\n  auto Rebuild(SemIR::InstId /*orig_inst_id*/, SemIR::Inst new_inst)\n      -> SemIR::InstId override {\n    auto inst_id = RebuildNewInst(loc_id_, new_inst);\n    auto subst_inst_id = substs_in_progress_.pop_back_val();\n    if (auto access =\n            context().insts().TryGetAsWithId<SemIR::ImplWitnessAccess>(\n                subst_inst_id)) {\n      if (auto* rewrite_value =\n              rewrite_values_->FindRef(context(), access->inst_id)) {\n        rewrite_values_->SetFullyRewritten(context(), *rewrite_value, inst_id);\n      }\n    }\n    return inst_id;\n  }\n\n  auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId override {\n    auto subst_inst_id = substs_in_progress_.pop_back_val();\n    if (auto access =\n            context().insts().TryGetAsWithId<SemIR::ImplWitnessAccess>(\n                subst_inst_id)) {\n      if (auto* rewrite_value =\n              rewrite_values_->FindRef(context(), access->inst_id)) {\n        rewrite_values_->SetFullyRewritten(context(), *rewrite_value,\n                                           orig_inst_id);\n      }\n    }\n    return orig_inst_id;\n  }\n\n private:\n  struct SubstInProgress {\n    // The associated constant whose value is being determined, represented as\n    // an ImplWitnessAccess. Or another instruction that we are recursing\n    // through.\n    SemIR::InstId inst_id;\n  };\n\n  // The location of the rewrite constraints as a whole.\n  SemIR::LocId loc_id_;\n  // Tracks the resolved value of each rewrite constraint, keyed by the\n  // `ImplWitnessAccess` of the associated constant on the LHS of the\n  // constraint. The value of each associated constant may be changed during\n  // substitution, replaced with a fully resolved value for the RHS. This allows\n  // us to cache work; when a value for an associated constant is found once it\n  // can be reused cheaply, avoiding exponential runtime when rewrite rules\n  // refer to each other in ways that create exponential references.\n  AccessRewriteValues* rewrite_values_;\n  // A stack of instructions being replaced in Subst(). When it's an associated\n  // constant, then it represents the constant value is being determined,\n  // represented as an ImplWitnessAccess.\n  //\n  // Avoid heap allocations in common cases, if there are chains of instructions\n  // in associated constants with a depth at most 16.\n  llvm::SmallVector<SemIR::InstId, 16> substs_in_progress_;\n};\n\nauto ResolveFacetTypeRewriteConstraints(\n    Context& context, SemIR::LocId loc_id,\n    llvm::SmallVector<SemIR::FacetTypeInfo::RewriteConstraint>& rewrites)\n    -> bool {\n  if (rewrites.empty()) {\n    return true;\n  }\n\n  AccessRewriteValues rewrite_values;\n\n  for (auto& constraint : rewrites) {\n    auto lhs_access = context.insts().TryGetAsWithId<SemIR::ImplWitnessAccess>(\n        GetImplWitnessAccessWithoutSubstitution(context, constraint.lhs_id));\n    if (!lhs_access) {\n      continue;\n    }\n\n    rewrite_values.InsertNotRewritten(context, lhs_access->inst_id,\n                                      constraint.rhs_id);\n  }\n\n  for (auto& constraint : rewrites) {\n    auto lhs_access = context.insts().TryGetAsWithId<SemIR::ImplWitnessAccess>(\n        GetImplWitnessAccessWithoutSubstitution(context, constraint.lhs_id));\n    if (!lhs_access) {\n      continue;\n    }\n\n    auto* lhs_rewrite_value =\n        rewrite_values.FindRef(context, lhs_access->inst_id);\n    // Every LHS was added with InsertNotRewritten above.\n    CARBON_CHECK(lhs_rewrite_value);\n    rewrite_values.SetBeingRewritten(*lhs_rewrite_value);\n\n    auto replace_witness_callbacks =\n        SubstImplWitnessAccessCallbacks(&context, loc_id, &rewrite_values);\n    auto rhs_subst_inst_id =\n        SubstInst(context, constraint.rhs_id, replace_witness_callbacks);\n    if (rhs_subst_inst_id == SemIR::ErrorInst::InstId) {\n      return false;\n    }\n\n    if (lhs_rewrite_value->state == AccessRewriteValues::FullyRewritten) {\n      auto rhs_existing_const_id =\n          context.constant_values().Get(lhs_rewrite_value->inst_id);\n      auto rhs_subst_const_id =\n          context.constant_values().Get(rhs_subst_inst_id);\n      if (rhs_subst_const_id != rhs_existing_const_id) {\n        if (rhs_existing_const_id != SemIR::ErrorInst::ConstantId) {\n          CARBON_DIAGNOSTIC(AssociatedConstantWithDifferentValues, Error,\n                            \"associated constant {0} given two different \"\n                            \"values {1} and {2}\",\n                            InstIdAsConstant, InstIdAsConstant,\n                            InstIdAsConstant);\n          // Use inst id ordering as a simple proxy for source ordering, to\n          // try to name the values in the same order they appear in the facet\n          // type.\n          auto source_order1 =\n              lhs_rewrite_value->inst_id.index < rhs_subst_inst_id.index\n                  ? lhs_rewrite_value->inst_id\n                  : rhs_subst_inst_id;\n          auto source_order2 =\n              lhs_rewrite_value->inst_id.index >= rhs_subst_inst_id.index\n                  ? lhs_rewrite_value->inst_id\n                  : rhs_subst_inst_id;\n          // TODO: It would be nice to note the places where the values are\n          // assigned but rewrite constraint instructions are from canonical\n          // constant values, and have no locations. We'd need to store a\n          // location along with them in the rewrite constraints.\n          context.emitter().Emit(loc_id, AssociatedConstantWithDifferentValues,\n                                 GetImplWitnessAccessWithoutSubstitution(\n                                     context, constraint.lhs_id),\n                                 source_order1, source_order2);\n        }\n        return false;\n      }\n    }\n\n    rewrite_values.SetFullyRewritten(context, *lhs_rewrite_value,\n                                     rhs_subst_inst_id);\n  }\n\n  // Rebuild the `rewrites` vector with resolved values for the RHS. Drop any\n  // duplicate rewrites in the `rewrites` vector by walking through the\n  // `rewrite_values` map and dropping the computed RHS value for each LHS the\n  // first time we see it, and erasing the constraint from the vector if we see\n  // the same LHS again.\n  size_t keep_size = rewrites.size();\n  for (size_t i = 0; i < keep_size;) {\n    auto& constraint = rewrites[i];\n\n    auto lhs_access = context.insts().TryGetAsWithId<SemIR::ImplWitnessAccess>(\n        GetImplWitnessAccessWithoutSubstitution(context, constraint.lhs_id));\n    if (!lhs_access) {\n      ++i;\n      continue;\n    }\n\n    auto& rewrite_value = *rewrite_values.FindRef(context, lhs_access->inst_id);\n    auto rhs_id = std::exchange(rewrite_value.inst_id, SemIR::InstId::None);\n    if (rhs_id == SemIR::InstId::None) {\n      std::swap(rewrites[i], rewrites[keep_size - 1]);\n      --keep_size;\n    } else {\n      rewrites[i].rhs_id = rhs_id;\n      ++i;\n    }\n  }\n  rewrites.erase(rewrites.begin() + keep_size, rewrites.end());\n\n  return true;\n}\n\nauto MakePeriodSelfFacetValue(Context& context, SemIR::TypeId self_type_id)\n    -> SemIR::InstId {\n  auto entity_name_id = context.entity_names().AddCanonical({\n      .name_id = SemIR::NameId::PeriodSelf,\n      .parent_scope_id = context.scope_stack().PeekNameScopeId(),\n  });\n  auto inst_id = AddInst(\n      context, SemIR::LocIdAndInst::NoLoc<SemIR::SymbolicBinding>({\n                   .type_id = self_type_id,\n                   .entity_name_id = entity_name_id,\n                   // `None` because there is no equivalent non-symbolic value.\n                   .value_id = SemIR::InstId::None,\n               }));\n  auto existing = context.scope_stack().LookupOrAddName(\n      SemIR::NameId::PeriodSelf, inst_id, ScopeIndex::None,\n      IsCurrentPositionReachable(context));\n  // Shouldn't have any names in newly created scope.\n  CARBON_CHECK(!existing.has_value());\n  return inst_id;\n}\n\nauto GetEmptyFacetType(Context& context) -> SemIR::TypeId {\n  SemIR::FacetTypeId facet_type_id =\n      context.facet_types().Add(SemIR::FacetTypeInfo{});\n  auto const_id = EvalOrAddInst<SemIR::FacetType>(\n      context, SemIR::LocId::None,\n      {.type_id = SemIR::TypeType::TypeId, .facet_type_id = facet_type_id});\n  return context.types().GetTypeIdForTypeConstantId(const_id);\n}\n\nauto GetConstantFacetValueForType(Context& context,\n                                  SemIR::TypeInstId type_inst_id)\n    -> SemIR::ConstantId {\n  // We use an empty facet type because values of type `type` do not provide any\n  // witnesses of their own.\n  auto type_facet_type = GetEmptyFacetType(context);\n  return EvalOrAddInst<SemIR::FacetValue>(\n      context, SemIR::LocId::None,\n      {.type_id = type_facet_type,\n       .type_inst_id = type_inst_id,\n       .witnesses_block_id = SemIR::InstBlockId::Empty});\n}\n\nauto GetConstantFacetValueForTypeAndInterface(\n    Context& context, SemIR::TypeInstId type_inst_id,\n    SemIR::SpecificInterface specific_interface, SemIR::InstId witness_id)\n    -> SemIR::ConstantId {\n  // Get the type of the inner `Self`, which is the facet type of the interface.\n  auto interface_facet_type = EvalOrAddInst(\n      context, SemIR::LocId::None,\n      FacetTypeFromInterface(context, specific_interface.interface_id,\n                             specific_interface.specific_id));\n  auto self_facet_type_in_generic_without_self =\n      context.types().GetTypeIdForTypeConstantId(interface_facet_type);\n\n  auto witnesses_block_id = context.inst_blocks().AddCanonical({witness_id});\n  auto self_value_const_id = EvalOrAddInst<SemIR::FacetValue>(\n      context, SemIR::LocId::None,\n      {.type_id = self_facet_type_in_generic_without_self,\n       .type_inst_id = type_inst_id,\n       .witnesses_block_id = witnesses_block_id});\n  return self_value_const_id;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/facet_type.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_\n#define CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_\n\n#include <compare>\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/entity_with_params_base.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Create a FacetType typed instruction object consisting of a interface. The\n// `specific_id` specifies arguments in the case the interface is generic.\nauto FacetTypeFromInterface(Context& context, SemIR::InterfaceId interface_id,\n                            SemIR::SpecificId specific_id) -> SemIR::FacetType;\n\n// Create a FacetType typed instruction object consisting of a named constraint.\n// The `specific_id` specifies arguments in the case the named constraint is\n// generic.\nauto FacetTypeFromNamedConstraint(Context& context,\n                                  SemIR::NamedConstraintId named_constraint_id,\n                                  SemIR::SpecificId specific_id)\n    -> SemIR::FacetType;\n\n// Given an ImplWitnessAccessSubstituted, returns the InstId of the\n// ImplWitnessAccess. Otherwise, returns the input `inst_id` unchanged.\n//\n// This must be used when accessing the LHS of a rewrite constraint which has\n// not yet been resolved in order to preserve which associated constant is being\n// rewritten.\nauto GetImplWitnessAccessWithoutSubstitution(Context& context,\n                                             SemIR::InstId inst_id)\n    -> SemIR::InstId;\n\n// Perform rewrite constraint resolution for a facet type. The rewrite\n// constraints resolution is described here:\n// https://docs.carbon-lang.dev/docs/design/generics/appendix-rewrite-constraints.html#rewrite-constraint-resolution\n//\n// This function:\n// * Replaces the RHS of rewrite rules referring to `.Self` with the value\n//   coming from other rewrite rules. For example in `.X = () and .Y = .X` the\n//   result is `.X = () and .Y = ()`.\n// * Discards duplicate assignments to the same associated constant, such as in\n//   `.X = () and .X = ()` which becomes just `.X = ()`.\n// * Diagnoses multiple assignments of different values to the same associated\n//   constant such as `.X = () and .X = .Y`.\n// * Diagnoses cycles between rewrite rules such as `.X = .Y and .Y = .X` or\n//   even `.X = .X`.\n//\n// The rewrite constraints in `rewrites` are modified in place and may be\n// reordered, with `ErrorInst` inserted when diagnosing errors.\n//\n// Returns false if resolve failed due to diagnosing an error. The resulting\n// value of the facet type should be an error constant.\nauto ResolveFacetTypeRewriteConstraints(\n    Context& context, SemIR::LocId loc_id,\n    llvm::SmallVector<SemIR::FacetTypeInfo::RewriteConstraint>& rewrites)\n    -> bool;\n\n// Introduce `.Self` as a symbolic binding into the current scope, and return\n// the `SymbolicBinding` instruction.\n//\n// The `self_type_id` is either a facet type (as `FacetType`) or `type` (as\n// `TypeType`).\nauto MakePeriodSelfFacetValue(Context& context, SemIR::TypeId self_type_id)\n    -> SemIR::InstId;\n\n// Get a FacetType instruction for an empty FacetType. This is the facet\n// equivalent to TypeType.\n//\n// TODO: We vaguely plan to replace TypeType with this FacetType in the future,\n// though that's a big change.\nauto GetEmptyFacetType(Context& context) -> SemIR::TypeId;\n\n// Make a facet value for a type value, which has an empty FacetType as its\n// type. Returns a constant value, whose instruction payload is a FacetValue.\nauto GetConstantFacetValueForType(Context& context,\n                                  SemIR::TypeInstId type_inst_id)\n    -> SemIR::ConstantId;\n\nauto GetConstantFacetValueForTypeAndInterface(\n    Context& context, SemIR::TypeInstId type_inst_id,\n    SemIR::SpecificInterface specific_interface, SemIR::InstId witness_id)\n    -> SemIR::ConstantId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_FACET_TYPE_H_\n"
  },
  {
    "path": "toolchain/check/full_pattern_stack.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_FULL_PATTERN_STACK_H_\n#define CARBON_TOOLCHAIN_CHECK_FULL_PATTERN_STACK_H_\n\n#include \"common/array_stack.h\"\n#include \"common/check.h\"\n#include \"toolchain/check/lexical_lookup.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Stack of full-patterns currently being checked (a full-pattern is a pattern\n// that is not part of an enclosing pattern). It is structured as a stack to\n// handle situations like a pattern that contains an initializer, or a pattern\n// in a lambda in an expression pattern.\n//\n// When a pattern is followed by an explicit initializer, name bindings should\n// not be used within that initializer, although they are usable before it\n// (within the pattern) and after it. This class keeps track of those state\n// transitions, as well as the kind of full-pattern (e.g. parameter list or name\n// binding pattern).\n//\n// TODO: Unify this with Context::pattern_block_stack, or differentiate them\n// more clearly (and consider unifying this with ScopeStack instead).\nclass FullPatternStack {\n public:\n  explicit FullPatternStack(LexicalLookup* lookup) : lookup_(lookup) {}\n\n  // The kind of a full-pattern. There are two primary kinds: name binding\n  // declarations and parameterized entity declarations. However, for efficiency\n  // we also use this enum to track state transitions within a parameterized\n  // entity declaration. A parameterized entity declaration always starts and\n  // finishes in the `NotInEitherParamList` state, and can transition to either\n  // the `ImplicitParamList` or `ExplicitParamList` state, and then back to the\n  // `NotInEitherParamList` state.\n  enum class Kind {\n    // A name-binding declaration, such as a `let` or `var` statement.\n    NameBindingDecl,\n\n    // The implicit parameter list of a function or impl declaration.\n    ImplicitParamList,\n\n    // The explicit parameter list of a function declaration.\n    ExplicitParamList,\n\n    // This kind indicates that we're within the declaration of a parameterized\n    // entity (such as a function or impl), but not within an explicit or\n    // implicit parameter list. This is primarily useful for the return part of\n    // a function declaration, which doesn't contain pattern syntax, but can\n    // implicitly introduce output parameter patterns. However, the parse tree\n    // doesn't let us reliably distinguish the return part from the part before\n    // the parameter lists (or between them), particularly in the case where\n    // there is no explicit parameter list.\n    NotInEitherParamList\n  };\n\n  auto empty() const -> bool { return kind_stack_.empty(); }\n\n  // The kind of the current full-pattern.\n  auto CurrentKind() const -> Kind { return kind_stack_.back(); }\n\n  // Marks the start of a new full-pattern for a parameterized entity\n  // declaration, such as a function or impl. The kind is initially\n  // NotInEitherParamList.\n  auto PushParameterizedDecl() -> void {\n    kind_stack_.push_back(Kind::NotInEitherParamList);\n    bind_name_stack_.PushArray();\n  }\n\n  // Marks the start of a new full-pattern for a name binding declaration.\n  auto PushNameBindingDecl() -> void {\n    kind_stack_.push_back(Kind::NameBindingDecl);\n    bind_name_stack_.PushArray();\n  }\n\n  // Marks the start of the current parameterized entity's implicit parameter\n  // list.\n  auto StartImplicitParamList() -> void {\n    CARBON_CHECK(kind_stack_.back() == Kind::NotInEitherParamList, \"{0}\",\n                 kind_stack_.back());\n    kind_stack_.back() = Kind::ImplicitParamList;\n  }\n\n  // Marks the end of the current parameterized entity's implicit parameter\n  // list.\n  auto EndImplicitParamList() -> void {\n    CARBON_CHECK(kind_stack_.back() == Kind::ImplicitParamList, \"{0}\",\n                 kind_stack_.back());\n    kind_stack_.back() = Kind::NotInEitherParamList;\n  }\n\n  // Marks the start of the current parameterized entity's explicit parameter\n  // list.\n  auto StartExplicitParamList() -> void {\n    CARBON_CHECK(kind_stack_.back() == Kind::NotInEitherParamList, \"{0}\",\n                 kind_stack_.back());\n    kind_stack_.back() = Kind::ExplicitParamList;\n  }\n\n  // Marks the end of the current parameterized entity's explicit parameter\n  // list.\n  auto EndExplicitParamList() -> void {\n    CARBON_CHECK(kind_stack_.back() == Kind::ExplicitParamList, \"{0}\",\n                 kind_stack_.back());\n    kind_stack_.back() = Kind::NotInEitherParamList;\n  }\n\n  // Marks the start of the initializer for the current name binding decl.\n  auto StartPatternInitializer() -> void {\n    CARBON_CHECK(kind_stack_.back() == Kind::NameBindingDecl);\n    for (auto& [name_id, inst_id] : bind_name_stack_.PeekArray()) {\n      CARBON_CHECK(inst_id == SemIR::InstId::InitTombstone);\n      auto& lookup_result = lookup_->Get(name_id);\n      if (!lookup_result.empty()) {\n        // TODO: find a way to preserve location information, so that we can\n        // provide good diagnostics for a redeclaration of `name_id` in\n        // the initializer, if that becomes possible.\n        std::swap(lookup_result.back().inst_id, inst_id);\n      }\n    }\n  }\n\n  // Marks the end of the initializer for the current name-binding decl.\n  auto EndPatternInitializer() -> void {\n    for (auto& [name_id, inst_id] : bind_name_stack_.PeekArray()) {\n      auto& lookup_result = lookup_->Get(name_id);\n      if (!lookup_result.empty()) {\n        std::swap(lookup_result.back().inst_id, inst_id);\n      }\n      CARBON_CHECK(inst_id == SemIR::InstId::InitTombstone);\n    }\n  }\n\n  // Marks the end of checking for the current full-pattern. This cannot be\n  // called while processing an initializer for the top pattern.\n  auto PopFullPattern() -> void {\n    kind_stack_.pop_back();\n    bind_name_stack_.PopArray();\n  }\n\n  // Records that `name_id` was introduced by the current full-pattern.\n  auto AddBindName(SemIR::NameId name_id) -> void {\n    bind_name_stack_.AppendToTop(\n        {.name_id = name_id, .inst_id = SemIR::InstId::InitTombstone});\n  }\n\n  // Runs verification that the processing cleanly finished.\n  auto VerifyOnFinish() const -> void {\n    CARBON_CHECK(kind_stack_.empty(),\n                 \"full_pattern_stack still has {0} entries\",\n                 kind_stack_.size());\n  }\n\n private:\n  LexicalLookup* lookup_;\n\n  llvm::SmallVector<Kind> kind_stack_;\n\n  struct LookupEntry {\n    SemIR::NameId name_id;\n    SemIR::InstId inst_id;\n  };\n  ArrayStack<LookupEntry> bind_name_stack_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_FULL_PATTERN_STACK_H_\n"
  },
  {
    "path": "toolchain/check/function.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/function.h\"\n\n#include \"common/find.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/merge.h\"\n#include \"toolchain/check/pattern.h\"\n#include \"toolchain/check/pattern_match.h\"\n#include \"toolchain/check/scope_stack.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/sem_ir/builtin_function_kind.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/pattern.h\"\n\nnamespace Carbon::Check {\n\nauto FindSelfPattern(Context& context,\n                     SemIR::InstBlockId implicit_param_patterns_id)\n    -> SemIR::InstId {\n  auto implicit_param_patterns =\n      context.inst_blocks().GetOrEmpty(implicit_param_patterns_id);\n  return FindIfOrNone(implicit_param_patterns, [&](auto implicit_param_id) {\n    return SemIR::IsSelfPattern(context.sem_ir(), implicit_param_id);\n  });\n}\n\nauto AddReturnPatterns(Context& context, SemIR::LocId loc_id,\n                       Context::FormExpr form_expr) -> SemIR::InstBlockId {\n  llvm::SmallVector<SemIR::InstId, 1> return_patterns;\n  auto form_inst = context.insts().Get(\n      context.constant_values().GetConstantInstId(form_expr.form_inst_id));\n  CARBON_KIND_SWITCH(form_inst) {\n    case SemIR::RefForm::Kind:\n    case SemIR::ValueForm::Kind: {\n      break;\n    }\n    case CARBON_KIND(SemIR::InitForm _): {\n      auto pattern_type_id =\n          GetPatternType(context, form_expr.type_component_id);\n      auto return_slot_pattern_id = AddPatternInst<SemIR::ReturnSlotPattern>(\n          context, loc_id,\n          {.type_id = pattern_type_id,\n           .type_inst_id = form_expr.type_component_inst_id});\n      return_patterns.push_back(AddPatternInst<SemIR::OutParamPattern>(\n          context, SemIR::LocId(form_expr.form_inst_id),\n          {.type_id = pattern_type_id,\n           .subpattern_id = return_slot_pattern_id}));\n      break;\n    }\n    case SemIR::ErrorInst::Kind: {\n      break;\n    }\n    case SemIR::SymbolicBinding::Kind:\n      CARBON_CHECK(\n          context.constant_values().Get(form_expr.form_inst_id).is_symbolic());\n      context.TODO(loc_id, \"Support symbolic return forms\");\n      break;\n    default:\n      CARBON_FATAL(\"unexpected inst kind: {0}\", form_inst);\n  }\n  return context.inst_blocks().AddCanonical(return_patterns);\n}\n\nauto IsValidBuiltinDeclaration(Context& context,\n                               const SemIR::Function& function,\n                               SemIR::BuiltinFunctionKind builtin_kind)\n    -> bool {\n  if (!function.call_params_id.has_value()) {\n    // For now, we have no builtins that support positional parameters.\n    return false;\n  }\n\n  // Find the list of call parameters other than the implicit return slots.\n  auto call_params =\n      context.inst_blocks()\n          .Get(function.call_params_id)\n          .take_front(function.call_param_ranges.explicit_end().index);\n\n  // Get the return type. This is `()` if none was specified.\n  auto return_type_id = function.GetDeclaredReturnType(context.sem_ir());\n  if (!return_type_id.has_value()) {\n    return_type_id = GetTupleType(context, {});\n  }\n\n  return builtin_kind.IsValidType(context.sem_ir(), call_params,\n                                  return_type_id);\n}\n\nnamespace {\n// Function signature fields for `MakeFunctionSignature`.\nstruct FunctionSignatureInsts {\n  SemIR::InstBlockId decl_block_id = SemIR::InstBlockId::None;\n  SemIR::InstBlockId pattern_block_id = SemIR::InstBlockId::None;\n  SemIR::InstBlockId implicit_param_patterns_id = SemIR::InstBlockId::None;\n  SemIR::InstBlockId param_patterns_id = SemIR::InstBlockId::None;\n  SemIR::InstBlockId call_param_patterns_id = SemIR::InstBlockId::None;\n  SemIR::InstBlockId call_params_id = SemIR::InstBlockId::None;\n  SemIR::Function::CallParamIndexRanges call_param_ranges =\n      SemIR::Function::CallParamIndexRanges::Empty;\n  SemIR::TypeInstId return_type_inst_id = SemIR::TypeInstId::None;\n  SemIR::InstId return_form_inst_id = SemIR::InstId::None;\n  SemIR::InstBlockId return_patterns_id = SemIR::InstBlockId::None;\n  SemIR::InstId self_param_id = SemIR::InstId::None;\n};\n}  // namespace\n\n// Handles construction of the signature's parameter and return types.\nstatic auto MakeFunctionSignature(Context& context, SemIR::LocId loc_id,\n                                  const FunctionDeclArgs& args)\n    -> FunctionSignatureInsts {\n  FunctionSignatureInsts insts;\n\n  StartFunctionSignature(context);\n\n  // Build and add a `[ref self: Self]` parameter if needed.\n  if (args.self_type_id.has_value()) {\n    context.full_pattern_stack().StartImplicitParamList();\n\n    BeginSubpattern(context);\n    auto self_type_region_id = EndSubpatternAsExpr(\n        context, context.types().GetTypeInstId(args.self_type_id));\n\n    insts.self_param_id = AddParamPattern(\n        context, loc_id, SemIR::NameId::SelfValue, self_type_region_id,\n        args.self_type_id, args.self_is_ref);\n    insts.implicit_param_patterns_id =\n        context.inst_blocks().Add({insts.self_param_id});\n\n    context.full_pattern_stack().EndImplicitParamList();\n  }\n\n  // Build and add any explicit parameters. We always use value parameters for\n  // now.\n  context.full_pattern_stack().StartExplicitParamList();\n  if (args.param_type_ids.empty()) {\n    insts.param_patterns_id = SemIR::InstBlockId::Empty;\n  } else {\n    context.inst_block_stack().Push();\n    for (auto param_type_id : args.param_type_ids) {\n      BeginSubpattern(context);\n      auto param_type_region_id = EndSubpatternAsExpr(\n          context, context.types().GetTypeInstId(param_type_id));\n\n      context.inst_block_stack().AddInstId(AddParamPattern(\n          context, loc_id, SemIR::NameId::Underscore, param_type_region_id,\n          param_type_id, /*is_ref=*/false));\n    }\n    insts.param_patterns_id = context.inst_block_stack().Pop();\n  }\n  context.full_pattern_stack().EndExplicitParamList();\n\n  // Build and add the return type. We always use an initializing form for now.\n  if (args.return_type_id.has_value()) {\n    auto return_form = ReturnExprAsForm(\n        context, loc_id, context.types().GetTypeInstId(args.return_type_id));\n    insts.return_type_inst_id = return_form.type_component_inst_id;\n    insts.return_form_inst_id = return_form.form_inst_id;\n    insts.return_patterns_id = AddReturnPatterns(context, loc_id, return_form);\n  }\n\n  auto match_results =\n      CalleePatternMatch(context, insts.implicit_param_patterns_id,\n                         insts.param_patterns_id, insts.return_patterns_id);\n  insts.call_param_patterns_id = match_results.call_param_patterns_id;\n  insts.call_params_id = match_results.call_params_id;\n  insts.call_param_ranges = match_results.param_ranges;\n\n  auto [pattern_block_id, decl_block_id] =\n      FinishFunctionSignature(context, /*check_unused=*/false);\n  insts.pattern_block_id = pattern_block_id;\n  insts.decl_block_id = decl_block_id;\n\n  return insts;\n}\n\nauto MakeGeneratedFunctionDecl(Context& context, SemIR::LocId loc_id,\n                               const FunctionDeclArgs& args)\n    -> std::pair<SemIR::InstId, SemIR::FunctionId> {\n  auto insts = MakeFunctionSignature(context, loc_id, args);\n\n  // Add the function declaration.\n  auto [decl_id, function_id] = MakeFunctionDecl(\n      context, loc_id, insts.decl_block_id, /*build_generic=*/false,\n      /*is_definition=*/true,\n      SemIR::Function{\n          {\n              .name_id = args.name_id,\n              .parent_scope_id = args.parent_scope_id,\n              .generic_id = SemIR::GenericId::None,\n              .first_param_node_id = Parse::NodeId::None,\n              .last_param_node_id = Parse::NodeId::None,\n              .pattern_block_id = insts.pattern_block_id,\n              .implicit_param_patterns_id = insts.implicit_param_patterns_id,\n              .param_patterns_id = insts.param_patterns_id,\n              .is_extern = false,\n              .extern_library_id = SemIR::LibraryNameId::None,\n              .non_owning_decl_id = SemIR::InstId::None,\n              // Set by `MakeFunctionDecl`.\n              .first_owning_decl_id = SemIR::InstId::None,\n          },\n          {\n              .call_param_patterns_id = insts.call_param_patterns_id,\n              .call_params_id = insts.call_params_id,\n              .call_param_ranges = insts.call_param_ranges,\n              .return_type_inst_id = insts.return_type_inst_id,\n              .return_form_inst_id = insts.return_form_inst_id,\n              .return_patterns_id = insts.return_patterns_id,\n              .self_param_id = insts.self_param_id,\n          }});\n  context.generated().push_back(decl_id);\n\n  return {decl_id, function_id};\n}\n\nauto CheckFunctionReturnTypeMatches(Context& context,\n                                    const SemIR::Function& new_function,\n                                    const SemIR::Function& prev_function,\n                                    SemIR::SpecificId prev_specific_id,\n                                    bool diagnose) -> bool {\n  // TODO: Pass a specific ID for `prev_function` instead of substitutions and\n  // use it here.\n  auto new_return_type_id =\n      new_function.GetDeclaredReturnType(context.sem_ir());\n  auto prev_return_type_id =\n      prev_function.GetDeclaredReturnType(context.sem_ir(), prev_specific_id);\n  if (new_return_type_id == SemIR::ErrorInst::TypeId ||\n      prev_return_type_id == SemIR::ErrorInst::TypeId) {\n    return false;\n  }\n  if (!context.types().AreEqualAcrossDeclarations(new_return_type_id,\n                                                  prev_return_type_id)) {\n    if (!diagnose) {\n      return false;\n    }\n\n    CARBON_DIAGNOSTIC(\n        FunctionRedeclReturnTypeDiffers, Error,\n        \"function redeclaration differs because return type is {0}\",\n        SemIR::TypeId);\n    CARBON_DIAGNOSTIC(\n        FunctionRedeclReturnTypeDiffersNoReturn, Error,\n        \"function redeclaration differs because no return type is provided\");\n    auto diag =\n        new_return_type_id.has_value()\n            ? context.emitter().Build(new_function.latest_decl_id(),\n                                      FunctionRedeclReturnTypeDiffers,\n                                      new_return_type_id)\n            : context.emitter().Build(new_function.latest_decl_id(),\n                                      FunctionRedeclReturnTypeDiffersNoReturn);\n    if (prev_return_type_id.has_value()) {\n      CARBON_DIAGNOSTIC(FunctionRedeclReturnTypePrevious, Note,\n                        \"previously declared with return type {0}\",\n                        SemIR::TypeId);\n      diag.Note(prev_function.latest_decl_id(),\n                FunctionRedeclReturnTypePrevious, prev_return_type_id);\n    } else {\n      CARBON_DIAGNOSTIC(FunctionRedeclReturnTypePreviousNoReturn, Note,\n                        \"previously declared with no return type\");\n      diag.Note(prev_function.latest_decl_id(),\n                FunctionRedeclReturnTypePreviousNoReturn);\n    }\n    diag.Emit();\n    return false;\n  }\n\n  return true;\n}\n\n// Checks that a function declaration's evaluation mode matches the previous\n// declaration's evaluation mode. Returns `false` and optionally produces a\n// diagnostic on mismatch.\nstatic auto CheckFunctionEvaluationModeMatches(\n    Context& context, const SemIR::Function& new_function,\n    const SemIR::Function& prev_function, bool diagnose) -> bool {\n  if (prev_function.evaluation_mode == new_function.evaluation_mode) {\n    return true;\n  }\n  if (!diagnose) {\n    return false;\n  }\n  auto eval_mode_index = [](SemIR::Function::EvaluationMode mode) {\n    switch (mode) {\n      case SemIR::Function::EvaluationMode::None:\n        return 0;\n      case SemIR::Function::EvaluationMode::Eval:\n        return 1;\n      case SemIR::Function::EvaluationMode::MustEval:\n        return 2;\n    }\n  };\n  auto prev_eval_mode_index = eval_mode_index(prev_function.evaluation_mode);\n  auto new_eval_mode_index = eval_mode_index(new_function.evaluation_mode);\n  CARBON_DIAGNOSTIC(\n      FunctionRedeclEvaluationModeDiffers, Error,\n      \"function redeclaration differs because new function is \"\n      \"{0:=-1:not `eval`|=-2:not `musteval`|=1:`eval`|=2:`musteval`}\",\n      Diagnostics::IntAsSelect);\n  CARBON_DIAGNOSTIC(FunctionRedeclEvaluationModePrevious, Note,\n                    \"previously {0:<0:not |:}declared as \"\n                    \"{0:=-1:`eval`|=-2:`musteval`|=1:`eval`|=2:`musteval`}\",\n                    Diagnostics::IntAsSelect);\n  context.emitter()\n      .Build(new_function.latest_decl_id(), FunctionRedeclEvaluationModeDiffers,\n             new_eval_mode_index ? new_eval_mode_index : -prev_eval_mode_index)\n      .Note(prev_function.latest_decl_id(),\n            FunctionRedeclEvaluationModePrevious,\n            prev_eval_mode_index ? prev_eval_mode_index : -new_eval_mode_index)\n      .Emit();\n  return false;\n}\n\nauto CheckFunctionTypeMatches(Context& context,\n                              const SemIR::Function& new_function,\n                              const SemIR::Function& prev_function,\n                              SemIR::SpecificId prev_specific_id,\n                              bool check_syntax, bool check_self, bool diagnose)\n    -> bool {\n  if (!CheckRedeclParamsMatch(context, DeclParams(new_function),\n                              DeclParams(prev_function), prev_specific_id,\n                              diagnose, check_syntax, check_self)) {\n    return false;\n  }\n  if (!CheckFunctionReturnTypeMatches(context, new_function, prev_function,\n                                      prev_specific_id, diagnose)) {\n    return false;\n  }\n  if (!CheckFunctionEvaluationModeMatches(context, new_function, prev_function,\n                                          diagnose)) {\n    return false;\n  }\n  return true;\n}\n\nauto CheckFunctionReturnPatternType(Context& context, SemIR::LocId loc_id,\n                                    SemIR::InstId return_pattern_id,\n                                    SemIR::SpecificId specific_id)\n    -> SemIR::TypeId {\n  auto arg_type_id = SemIR::ExtractScrutineeType(\n      context.sem_ir(), SemIR::GetTypeOfInstInSpecific(\n                            context.sem_ir(), specific_id, return_pattern_id));\n  auto init_repr = SemIR::InitRepr::ForType(context.sem_ir(), arg_type_id);\n  if (!init_repr.is_valid()) {\n    // TODO: Consider suppressing the diagnostics if we've already diagnosed a\n    // definition or call to this function.\n    if (!RequireConcreteType(\n            context, arg_type_id, SemIR::LocId(return_pattern_id),\n            [&](auto& builder) {\n              CARBON_DIAGNOSTIC(IncompleteTypeInFunctionReturnType, Context,\n                                \"function returns incomplete type {0}\",\n                                SemIR::TypeId);\n              builder.Context(loc_id, IncompleteTypeInFunctionReturnType,\n                              arg_type_id);\n            },\n            [&](auto& builder) {\n              CARBON_DIAGNOSTIC(AbstractTypeInFunctionReturnType, Context,\n                                \"function returns abstract type {0}\",\n                                SemIR::TypeId);\n              builder.Context(loc_id, AbstractTypeInFunctionReturnType,\n                              arg_type_id);\n            })) {\n      return SemIR::ErrorInst::TypeId;\n    }\n  }\n\n  return arg_type_id;\n}\n\nauto CheckFunctionDefinitionSignature(Context& context,\n                                      SemIR::FunctionId function_id) -> void {\n  auto& function = context.functions().Get(function_id);\n\n  auto params_to_complete =\n      context.inst_blocks().GetOrEmpty(function.call_params_id);\n\n  // The return parameter will be diagnosed after and differently from other\n  // parameters.\n  auto return_call_param = SemIR::InstId::None;\n  if (!params_to_complete.empty() && function.return_patterns_id.has_value()) {\n    return_call_param = params_to_complete.consume_back();\n  }\n\n  // Check the parameter types are complete.\n  for (auto param_ref_id : params_to_complete) {\n    if (param_ref_id == SemIR::ErrorInst::InstId) {\n      continue;\n    }\n\n    // The parameter types need to be complete.\n    RequireCompleteType(\n        context, context.insts().GetAs<SemIR::AnyParam>(param_ref_id).type_id,\n        SemIR::LocId(param_ref_id), [&](auto& builder) {\n          CARBON_DIAGNOSTIC(\n              IncompleteTypeInFunctionParam, Context,\n              \"parameter has incomplete type {0} in function definition\",\n              TypeOfInstId);\n          builder.Context(param_ref_id, IncompleteTypeInFunctionParam,\n                          param_ref_id);\n        });\n  }\n\n  // Check the return type is complete.\n  if (function.return_patterns_id.has_value()) {\n    for (auto return_pattern_id :\n         context.inst_blocks().Get(function.return_patterns_id)) {\n      CheckFunctionReturnPatternType(context, SemIR::LocId(return_pattern_id),\n                                     return_pattern_id,\n                                     SemIR::SpecificId::None);\n    }\n\n    // `CheckFunctionReturnPatternType` should have diagnosed incomplete types,\n    // so don't `RequireCompleteType` on the return type.\n    if (return_call_param.has_value()) {\n      // TODO: If the types are already checked for completeness then this does\n      // nothing?\n      TryToCompleteType(\n          context,\n          context.insts().GetAs<SemIR::AnyParam>(return_call_param).type_id,\n          SemIR::LocId(return_call_param));\n    }\n  }\n}\n\nauto StartFunctionSignature(Context& context) -> void {\n  context.scope_stack().PushForDeclName();\n  context.inst_block_stack().Push();\n  context.pattern_block_stack().Push();\n  context.full_pattern_stack().PushParameterizedDecl();\n}\n\nauto FinishFunctionSignature(Context& context, bool check_unused)\n    -> FinishFunctionSignatureResult {\n  context.full_pattern_stack().PopFullPattern();\n  auto pattern_block_id = context.pattern_block_stack().Pop();\n  auto decl_block_id = context.inst_block_stack().Pop();\n  context.scope_stack().Pop(check_unused);\n  return {.pattern_block_id = pattern_block_id, .decl_block_id = decl_block_id};\n}\n\nauto MakeFunctionDecl(Context& context, SemIR::LocId loc_id,\n                      SemIR::InstBlockId decl_block_id, bool build_generic,\n                      bool is_definition, SemIR::Function function)\n    -> std::pair<SemIR::InstId, SemIR::FunctionId> {\n  CARBON_CHECK(!function.first_owning_decl_id.has_value());\n\n  SemIR::FunctionDecl function_decl = {SemIR::TypeId::None,\n                                       SemIR::FunctionId::None, decl_block_id};\n  auto decl_id = AddPlaceholderInstInNoBlock(\n      context, SemIR::LocIdAndInst::UncheckedLoc(loc_id, function_decl));\n  function.first_owning_decl_id = decl_id;\n  if (is_definition) {\n    function.definition_id = decl_id;\n  }\n\n  if (build_generic) {\n    function.generic_id = BuildGenericDecl(context, decl_id);\n  }\n\n  // Create the `Function` object.\n  function_decl.function_id = context.functions().Add(std::move(function));\n  function_decl.type_id =\n      GetFunctionType(context, function_decl.function_id,\n                      build_generic ? context.scope_stack().PeekSpecificId()\n                                    : SemIR::SpecificId::None);\n  ReplaceInstBeforeConstantUse(context, decl_id, function_decl);\n  return {decl_id, function_decl.function_id};\n}\n\nauto StartFunctionDefinition(Context& context, SemIR::InstId decl_id,\n                             SemIR::FunctionId function_id) -> void {\n  // Create the function scope and the entry block.\n  context.scope_stack().PushForFunctionBody(decl_id);\n  context.inst_block_stack().Push();\n  context.region_stack().PushRegion(context.inst_block_stack().PeekOrAdd());\n  StartGenericDefinition(context,\n                         context.functions().Get(function_id).generic_id);\n\n  CheckFunctionDefinitionSignature(context, function_id);\n}\n\nauto FinishFunctionDefinition(Context& context, SemIR::FunctionId function_id)\n    -> void {\n  context.inst_block_stack().Pop();\n  context.scope_stack().Pop(/*check_unused=*/true);\n\n  auto& function = context.functions().Get(function_id);\n  function.body_block_ids = context.region_stack().PopRegion();\n\n  // If this is a generic function, collect information about the definition.\n  FinishGenericDefinition(context, function.generic_id);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/function.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_FUNCTION_H_\n#define CARBON_TOOLCHAIN_CHECK_FUNCTION_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/custom_witness.h\"\n#include \"toolchain/check/decl_name_stack.h\"\n#include \"toolchain/check/subst.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Returns the ID of the self parameter pattern, or None.\n// TODO: Do this during initial traversal of implicit params.\nauto FindSelfPattern(Context& context,\n                     SemIR::InstBlockId implicit_param_patterns_id)\n    -> SemIR::InstId;\n\n// Creates suitable return patterns for the given return form, and adds them to\n// the current pattern block.\nauto AddReturnPatterns(Context& context, SemIR::LocId loc_id,\n                       Context::FormExpr form_expr) -> SemIR::InstBlockId;\n\n// Returns whether `function` is a valid declaration of `builtin_kind`.\nauto IsValidBuiltinDeclaration(Context& context,\n                               const SemIR::Function& function,\n                               SemIR::BuiltinFunctionKind builtin_kind) -> bool;\n\n// Arguments for making a function declaration.\nstruct FunctionDeclArgs {\n  SemIR::NameScopeId parent_scope_id;\n  SemIR::NameId name_id;\n  // The type of the implicit `[self: Self]` parameter, or `None` if there is\n  // none.\n  SemIR::TypeId self_type_id = SemIR::TypeId::None;\n  // Whether `self` is a ref parameter.\n  bool self_is_ref = true;\n  // The types of the explicit parameters.\n  llvm::ArrayRef<SemIR::TypeId> param_type_ids = {};\n  // The return type, or `None` if the function doesn't declare a return type.\n  SemIR::TypeId return_type_id = SemIR::TypeId::None;\n};\n\n// Generates and returns a function declaration. The caller should update the\n// function object to add a definition. The caller is responsible for ensuring\n// that the signature is non-generic.\nauto MakeGeneratedFunctionDecl(Context& context, SemIR::LocId loc_id,\n                               const FunctionDeclArgs& args)\n    -> std::pair<SemIR::InstId, SemIR::FunctionId>;\n\n// Checks that `new_function` has the same return type as `prev_function`, or if\n// `prev_function_id` is specified, a specific version of `prev_function`.\n// Prints a suitable diagnostic and returns false if not. Never checks for a\n// syntactic match.\nauto CheckFunctionReturnTypeMatches(Context& context,\n                                    const SemIR::Function& new_function,\n                                    const SemIR::Function& prev_function,\n                                    SemIR::SpecificId prev_specific_id,\n                                    bool diagnose = true) -> bool;\n\n// Checks that `new_function` has the same parameter types and return type as\n// `prev_function`, or if `prev_function_id` is specified, a specific version of\n// `prev_function`. Prints a suitable diagnostic and returns false if not.\n//\n// `check_syntax` is false if the redeclaration can be called via a thunk with\n// implicit conversions from the original declaration.\n// `check_self` is false if the self declaration does not have to match (for\n// instance in impls of virtual functions).\nauto CheckFunctionTypeMatches(Context& context,\n                              const SemIR::Function& new_function,\n                              const SemIR::Function& prev_function,\n                              SemIR::SpecificId prev_specific_id,\n                              bool check_syntax, bool check_self,\n                              bool diagnose = true) -> bool;\n\ninline auto CheckFunctionTypeMatches(Context& context,\n                                     const SemIR::Function& new_function,\n                                     const SemIR::Function& prev_function)\n    -> bool {\n  return CheckFunctionTypeMatches(context, new_function, prev_function,\n                                  SemIR::SpecificId::None,\n                                  /*check_syntax=*/true, /*check_self=*/true);\n}\n\n// Checks that the scrutinee type of `return_pattern_id` in `specific_id` is\n// concrete. If so, it returns that type; if not, it issues an error and returns\n// SemIR::ErrorInst::TypeId. `return_pattern_id` must be part of a function's\n// return form, or the error message will be nonsensical.\nauto CheckFunctionReturnPatternType(Context& context, SemIR::LocId loc_id,\n                                    SemIR::InstId return_pattern_id,\n                                    SemIR::SpecificId specific_id)\n    -> SemIR::TypeId;\n\n// Checks that a function declaration's signature is suitable to support a\n// function definition. This requires the parameter types to be complete and the\n// return type to be concrete.\nauto CheckFunctionDefinitionSignature(Context& context,\n                                      SemIR::FunctionId function_id) -> void;\n\n// Prepares for a function signature. Handles necessary stack setup. This is\n// used for generated functions/thunks, not user-declared functions.\nauto StartFunctionSignature(Context& context) -> void;\n\n// Results for `FinishFunctionSignature`.\nstruct FinishFunctionSignatureResult {\n  SemIR::InstBlockId pattern_block_id;\n  SemIR::InstBlockId decl_block_id;\n};\n\n// Finishes signatures started by `StartFunctionSignature`.\nauto FinishFunctionSignature(Context& context, bool check_unused = true)\n    -> FinishFunctionSignatureResult;\n\n// Creates a function object for the given function declaration. The caller must\n// add the returned `decl_id` to a block (typically the current block or\n// imports).\nauto MakeFunctionDecl(Context& context, SemIR::LocId loc_id,\n                      SemIR::InstBlockId decl_block_id, bool build_generic,\n                      bool is_definition, SemIR::Function function)\n    -> std::pair<SemIR::InstId, SemIR::FunctionId>;\n\n// Starts a function definition. Handles necessary stack setup, creating the\n// function scope and entry block, and definition validation. This is used for\n// both generated functions/thunks and user-declared functions.\nauto StartFunctionDefinition(Context& context, SemIR::InstId decl_id,\n                             SemIR::FunctionId function_id) -> void;\n\n// Finishes definitions started by `StartFunctionDefinition`.\nauto FinishFunctionDefinition(Context& context, SemIR::FunctionId function_id)\n    -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_FUNCTION_H_\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/008cb7b685ac13c051abc8e778bb56c6be8c920d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nvar x: i32;\n\nfn Main() -> i32 {\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/016a8df42375f098eaf2bda8fa7ed1cdd322e51d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nchoice Ints {\n  None,\n  One(i32),\n  Two(i32, i32)\n}\n\n// Test some alternate syntaxes\nchoice MoreInts {\n  None(),\n  One(i32),\n  Two(i32, i32),\n}\n\nfn Main() -> i32 {\n  var x: Ints = Ints.None;\n  var y: Ints = Ints.One(42);\n  var z: MoreInts = MoreInts.None();\n  var n: i32 = 0;\n  match (y) {\n    case Ints.None => { n = n + 2; }\n    case Ints.One(x: auto) => { n = x + 1 - 42; }\n    case Ints.Two(a: auto, b: auto) => { n = 2; }\n  }\n  match (x) {\n    case Ints.One(x: auto) => { n = x + 2; }\n    case Ints.None => { n = n - 1; }\n    case Ints.Two(x: auto, y: auto) => { n = 5; }\n  }\n  match (z) {\n    case MoreInts.None() => { ++n; }\n  }\n  return n;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/01b6283c2544cf135b8c219478e5b0f8da2325ed",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 10\n// CHECK:STDOUT: 30\n// CHECK:STDOUT: 210\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as MulWith(i32) where .Result = A {\n  fn Op[self: Self](rhs: i32) -> A { return {.n = self.n * rhs}; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 5};\n  a = a * 2;\n  Print(\"{0}\", a.n);\n  a *= 3;\n  Print(\"{0}\", a.n);\n  Print(\"{0}\", (a * 7).n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/02163cf92aea19e124c4a5838dae8f0ed340fbfa",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\nclass Cell(T:! type) {\n  fn Create(x: T) -> Cell(T) { return { .data = x }; }\n\n  fn Get[self: Self]() -> T {\n    return self.data;\n  }\n  fn Put[addr self: Self*](x: T) {\n    (*self).data = x;\n  }\n  fn Update[addr self: Self*, U:! ImplicitAs(T)](x: U) {\n    (*self).data = x;\n  }\n  fn CreateOther[self: Self, U:! type](x: U) -> Cell(U) {\n    return {.data = x};\n  }\n  var data: T;\n}\n\nclass Integer {\n  var int: i32;\n}\n\nfn Main() -> i32 {\n  var i: Integer = {.int = 1};\n  var c: Cell(Integer) = Cell(Integer).Create(i); // c contains 1\n  i = {.int = 2};\n  var j: Integer = c.Get(); // j == 1\n  c.Put(i);    // c contains 2\n  c.Update(j); // c contains 1\n  var d: Cell(Integer) = c.CreateOther(i); // d contains 2\n  return c.data.int + d.data.int;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0234ac9a0b945c8a32fc87ee33f9a6d8f9933019",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Bad[T:! type](x: {.a: i32, .b: T}) {}\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_implicit_conversion_extra_field.carbon:[[@LINE+1]]: mismatch in field names, source field `c` not in destination type `{.a: i32, .b: T}`\n  Bad({.b = 5, .a = 7, .c = 2});\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/023877f085e3eedd9a0f13951f04859de07944e9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var (x: auto, y: [i32;]) = (42, (0, 1));\n  var index: i32 = 1;\n  y[index] = 0;\n  return y[0] + y[1];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0272d8c7b9a7495efe6a19e9e814ecbe55823213",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface X { fn F(); }\nimpl i32 as X { fn F() {} }\n\nfn G[T:! X](v: T) -> type {\n  v.F();\n  return i32;\n}\n\nfn Main() -> i32 {\n  var v: G(0) = 0;\n  return v;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/03a61af13df6ab601a52a1784995ad7b84d04555",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32;\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/03f031da904f8bb48412e82acaa77957fde2445b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: ab.a: 2\n// CHECK:STDOUT: ab.b: 1\n// CHECK:STDOUT: ba.a: 2\n// CHECK:STDOUT: ba.b: 1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nalias AB = {.a: i32, .b: i32};\nalias BA = {.b: i32, .a: i32};\n\nfn Main() -> i32 {\n  var ab: AB = {.b = 1, .a = 2};\n  var ba: BA = ab;\n  Print(\"ab.a: {0}\", ab.a);\n  Print(\"ab.b: {0}\", ab.b);\n  Print(\"ba.a: {0}\", ba.a);\n  Print(\"ba.b: {0}\", ba.b);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0444b366b646a800d860d362876dec36afb41e42",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: DESTRUCTOR A 0\n// CHECK:STDOUT: DESTRUCTOR A 1\n// CHECK:STDOUT: DESTRUCTOR A 2\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\n\nclass A{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR A {0}\",self.n);\n    }\n    var n: i32;\n}\n\nfn Main() -> i32 {\n  var a1: A = {.n = 2};\n  var a: array(A, 2) = ({.n = 1},{.n = 0});\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/048e2bfcc725778f118b704acf2679b712bc6ded",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nchoice AB {\n  A(),\n  B()\n}\n\nfn F() -> AB { return AB.A(); }\n\nfn Main() -> i32 {\n  // This is T9 from http://moscova.inria.fr/~maranget/papers/warn/warn014.html\n  // Note, this match is exhaustive, but it exceeds our depth limit.\n  match ((F(), F(), F(), F(), F(), F(), F(), F(), F())) {\n    case (AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 0; }\n    case (AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B()) => { return 1; }\n    case (_: AB,  AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 2; }\n    case (_: AB,  AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B()) => { return 3; }\n    case (_: AB,  _: AB,  AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 4; }\n    case (_: AB,  _: AB,  AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B()) => { return 5; }\n    case (_: AB,  _: AB,  _: AB,  AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 6; }\n    case (_: AB,  _: AB,  _: AB,  AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B()) => { return 7; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 8; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.B(), AB.B(), AB.B(), AB.B()) => { return 9; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.A(), AB.A(), AB.A(), AB.A()) => { return 10; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.B(), AB.B(), AB.B()) => { return 11; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.A(), AB.A(), AB.A()) => { return 12; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.B(), AB.B()) => { return 13; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.A(), AB.A()) => { return 14; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.B()) => { return 15; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.A()) => { return 16; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B()) => { return 17; }\n  }\n// CHECK:STDERR: COMPILATION ERROR: fail_exhaustive_exponential_series_t.carbon:[[@LINE+1]]: non-exhaustive match may allow control-flow to reach the end of a function that provides a `->` return type\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/068ac29021d30e21dc976177ae56f68096da6740",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn ReturnIndirectly[T:! type](direct: bool, x: T) -> type {\n  if (direct) {\n    return T;\n  } else {\n    return ReturnIndirectly(true, x);\n  }\n}\n\nfn Main() -> ReturnIndirectly(false, 0) {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/06c71952ad52d77790a1a5eb631eaa0759800fec",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: result: 0\n\npackage Foo;\nclass X {\n  fn F[self: Self]() -> i32 { return self.n; }\n  var n: i32;\n}\nfn Main() -> i32 {\n  var v: X = {.n = 1};\n  let p: X* = &v;\n  Print(\"{0}\", p->n);\n  Print(\"{0}\", p->(X.n));\n  Print(\"{0}\", p->F());\n  Print(\"{0}\", p->(X.F)());\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/078ec0d032fa51fabffef18fc82712e9536b013e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface ManyTypes {\n  let T0:! type;\n  let T1:! type;\n  let T2:! type;\n  let T3:! type;\n  let T4:! type;\n  let T5:! type;\n  let T6:! type;\n  let T7:! type;\n  let T8:! type;\n  let T9:! type;\n}\n\nfn F[\n  M:! ManyTypes where\n    .T0 = .T1 and\n    .T1 = .T2 and\n    .T2 = .T3 and\n    .T3 = .T4 and\n    .T4 = .T5 and\n    .T5 = .T6 and\n    .T6 = .T7 and\n    .T7 = .T8 and\n    .T8 = .T9 and\n    // CHECK:STDERR: COMPILATION ERROR: fail_rewrite_cycle.carbon:[[@LINE+1]]: rewrite of (M).(ManyTypes.T4) applies within its own resolved expansion of (M).(ManyTypes.T4)\n    .T9 = .T0]() {}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/07b0e6716d0adf617012146642d9cba39b9b006b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn ReturnSecond(_: i32, x: i32) -> i32 {\n  return x;\n}\n\nfn Main() -> i32 {\n  return ReturnSecond(1, 0);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/081d7c4effd1e9cc6129090e3c831e1af2633e62",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: -2\n\npackage ExplorerTest;\n\nfn apply[T:! type, U:! type](f: __Fn (T) -> U, x: T) -> U {\n  return f(x);\n}\n\nfn positive(x: bool) -> i32 {\n  if (x) {\n    return 2;\n  } else {\n    return -2;\n  }\n}\n\nfn Main() -> i32 {\n  return apply(positive, false);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0831e49d5a00cd7ae6512b7cd8f782c1ed305fa5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nchoice AB {\n  A(),\n  B()\n}\n\nfn F() -> AB { return AB.A(); }\n\nfn Main() -> i32 {\n  match ((F(), F(), F(), F(), F(), F(), F(), F())) {\n    case (AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 0; }\n    case (AB.B(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 1; }\n    case (_: AB,  AB.B(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 2; }\n    case (_: AB,  _: AB,  AB.B(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 3; }\n    case (_: AB,  _: AB,  _: AB,  AB.B(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 4; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.A(), AB.A(), AB.A()) => { return 5; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.A(), AB.A()) => { return 6; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.A()) => { return 7; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B()) => { return 8; }\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/083cd63392060ddfbc062ce0ba14a7ac89441a1f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: c.Foo(): 1\n// CHECK:STDOUT: d.Foo(): 2\n// CHECK:STDOUT: e.Foo(): 3\n// CHECK:STDOUT: (*dp).Foo(): 3\n// CHECK:STDOUT: (*dc).Foo(): 3\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class C {\n  var value_c: i32;\n  virtual fn Foo[self: Self]() -> i32 {\n    return self.value_c;\n  }\n}\n\nbase class D {\n  extend base: C;\n  var value_d: i32;\n  impl fn Foo[self: Self]() -> i32 {\n    return self.value_d;\n  }\n}\n\nclass E {\n  extend base: D;\n  var value_e: i32;\n  impl fn Foo[self: Self]() -> i32 {\n    return self.value_e;\n  }\n}\n\nfn Main() -> i32 {\n  var c: C = {.value_c = 1};\n  Print(\"c.Foo(): {0}\", c.Foo());\n  var d: D = {.value_d = 2, .base = {.value_c = 1}};\n  Print(\"d.Foo(): {0}\", d.Foo());\n  var e: E = {.value_e = 3, .base={.value_d = 2, .base = {.value_c = 1}}};\n  Print(\"e.Foo(): {0}\", e.Foo());\n  var dp: D* = &e;\n  Print(\"(*dp).Foo(): {0}\", (*dp).Foo());\n  var dc: C* = &e;\n  Print(\"(*dc).Foo(): {0}\", (*dc).Foo());\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0900a9afaef22b798df75b576e8096343a98903a",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// Test mutation of a global variable.\n\nvar zero: i32 = 1;\n\nfn Main() -> i32 {\n  zero = 0;\n  return zero;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/09762ec95a5e7e5a232b735f95e808da510678fd",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface GetX {\n  fn DoIt[self: Self]() -> i32;\n}\n\nimpl forall [template T:! type] T as GetX {\n  fn DoIt[self: Self]() -> i32 { return self.x; }\n}\n\nclass C {\n  var x: i32;\n}\n\nfn Main() -> i32 {\n  var a: auto = {.x = 1, .y = 2};\n  var b: C = {.x = 3};\n  Print(\"{0}\", a.(GetX.DoIt)());\n  Print(\"{0}\", b.(GetX.DoIt)());\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0c1db2e8ec3df9d6adf52c88ba67333e2059da97",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 526\n\npackage ExplorerTest;\n\ninterface A { fn F() -> i32; fn G() -> i32; }\ninterface B { fn H() -> i32; }\n\nfn Get1[T:! A & B](n: T) -> i32 { return n.F() + n.H(); }\nfn Get2[T:! B & A](n: T) -> i32 { return n.G(); }\nfn Get3[T:! B & A & A & B & A](n: T) -> i32 { return n.G() + n.H(); }\n\nimpl i32 as A {\n  fn F() -> i32 { return 1; }\n  fn G() -> i32 { return 2; }\n}\nimpl i32 as B {\n  fn H() -> i32 { return 4; }\n}\n\nfn Main() -> i32 {\n  var z: i32 = 0;\n  return Get1(z) * 100 + Get2(z) * 10 + Get3(z);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0ce1b0382ddf1eaf0a21e39a1932936edd0c7b63",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage Foo;\nclass X {\n  fn F[self: Self](o: Self) -> Self { return {.n = self.n + o.n}; }\n  var n: i32;\n}\nfn Main() -> i32 {\n  var v: X = {.n = 1};\n  var w: X = {.n = 2};\n  return v.(X.F)(w).(X.n);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0d824e8e58e5a28b74bfde959ca83df292a33702",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Vector {\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: i32) -> Self;\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  extend impl as Vector {\n    fn Add[self: Point](b: Point) -> Point {\n      return {.x = self.x + b.x, .y = self.y + b.y};\n    }\n    fn Scale[self: Point](v: i32) -> Point {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n  }\n}\n\nfn AddAndScaleGeneric[T:! Vector](a: T, b: T, s: i32) -> T {\n  var m: __Fn(T)->T = a.Add;\n  var n: __Fn(i32)->T = m(b).Scale;\n  return n(s);\n}\n\nfn Main() -> i32 {\n  var a: Point = {.x = 1, .y = 1};\n  var b: Point = {.x = 2, .y = 3};\n  var p: Point = AddAndScaleGeneric(a, b, 5);\n  return p.x - 15;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0d9b1f8863ca4b08680e246aeb58b12737afc902",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: strings less: 1\n// CHECK:STDOUT: ints less: 0\n// CHECK:STDOUT: strings less eq: 1\n// CHECK:STDOUT: ints less eq: 1\n// CHECK:STDOUT: strings greater: 0\n// CHECK:STDOUT: ints greater: 0\n// CHECK:STDOUT: strings greater eq: 0\n// CHECK:STDOUT: ints greater eq: 1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  Print(\"strings less: {0}\", if \"hello\" < \"world\" then 1 else 0);\n  Print(\"ints less: {0}\", if 1 < 1 then 1 else 0);\n  Print(\"strings less eq: {0}\", if \"hello\" <= \"world\" then 1 else 0);\n  Print(\"ints less eq: {0}\", if 1 <= 1 then 1 else 0);\n  Print(\"strings greater: {0}\", if \"hello\" > \"world\" then 1 else 0);\n  Print(\"ints greater: {0}\", if 1 > 1 then 1 else 0);\n  Print(\"strings greater eq: {0}\", if \"hello\" >= \"world\" then 1 else 0);\n  Print(\"ints greater eq: {0}\", if 1 >= 1 then 1 else 0);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0dc65251b81300d504287a2f7be97054bd22d386",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nnamespace N;\nfn N.F() {}\n\nalias A = N;\nalias B = A;\nalias C = B;\n\nfn Main() -> i32 {\n  C.F();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/0fc717e2905c26bce32a4591acdd0f46859765a2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\npackage ExplorerTest;\n\n__mixin M1 {\n  fn F1[self: Self](x: Self) -> Self{\n     return x;\n  }\n  // CHECK:STDERR: COMPILATION ERROR: fail_circular_mixing.carbon:[[@LINE+1]]: 'M3' has not been declared yet\n  __mix M3;\n}\n\n__mixin M2 {\n  fn F2() {\n  }\n  __mix M1;\n}\n\n__mixin M3 {\n  __mix M2;\n  fn F3() {\n  }\n}\n\nclass C {\n  __mix M2;\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/10204d82b32ad9dc256b595048de9efabd93067f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass C(T:! type) {}\n\nfn F(T:! type) -> type {\n  return C(T);\n}\n\nfn Main() -> i32 {\n  var v: F(i32) = {};\n  var w: C(i32) = v;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/11253cbc5df4b6b891cc68ac943599555d3e30dc",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn DoNothing() {\n  // Empty block\n}\n\nfn Main() -> i32 {\n  var x: i32 = 0;\n  DoNothing();\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/12b56f338f82115bc9733846f50bc5863ca3fd9c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var s: String = '''filetype\n    A \"block\" \"\"string\"\" literal\n      with file type indicator.\n    ''';\n  if (s == \"A \\\"block\\\" \\\"\\\"string\\\"\\\" literal\\n  with file type indicator.\\n\") {\n    return 0;\n  } else {\n    return 1;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/12c9b3f16c56bbb271111f4bdc8a2401dab16154",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn CompareStr(s: String) -> i32 {\n  if (s == ##\"str\"##) {\n    return 0;\n  }\n  return 1;\n}\n\nfn Main() -> i32 {\n  return CompareStr(#####\"str\"#####);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/138a0e4547e111ad5cc545e9b19a1e430348636b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\nimpl package ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: RUNTIME ERROR: fail_index_empty.carbon:[[@LINE+1]]: Invalid `{}` in `Print: {}`\n  Print(\"Print: {}\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/13f9d954261112e0d9131eb97327515395550d00",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn add1(x: i32) -> i32 {\n  return x + 1;\n}\n\nfn Main() -> i32 {\n  var f: __Fn(i32)->i32 = add1;\n  return f(-1);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1551a409e456b8102c5b44313303aad008b2a06d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface IFace {\n  // CHECK:STDERR: COMPILATION ERROR: fail_use_assoc_const_before_decl.carbon:[[@LINE+1]]: 'C' has not been declared yet\n  let B:! C;\n  let C:! IFace;\n}\n\nfn Main() -> i32 {\n  // return T;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/155ec88a933f5a3ae411ee810eb89f5631bff2d5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nnamespace N;\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/15a7fdcf1eda6e722c03d2cccbc93ddf75681128",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: (*c).a: 1\n// CHECK:STDOUT: (*c).Foo(): 1\n// CHECK:STDOUT: (*c).Bar(): 1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class C {\n  var a: i32;\n  fn Foo[self: Self]() -> i32 {\n    return 1;\n  }\n  fn Bar() -> i32 {\n    return 1;\n  }\n}\n\nclass D {\n  extend base: C;\n  var b: i32;\n  fn Foo[self: Self]() -> i32 {\n    return 2;\n  }\n  fn Bar() -> i32 {\n    return 2;\n  }\n}\n\nfn Main() -> i32 {\n  var d: D = { .base = {.a = 1}, .b = 2 };\n  var c: C* = &d;\n  Print(\"(*c).a: {0}\", (*c).a);\n  Print(\"(*c).Foo(): {0}\", (*c).Foo());\n  Print(\"(*c).Bar(): {0}\", (*c).Bar());\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/162348262c5e2797cf53a49adec2c1df056268d2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32;\n  // CHECK:STDERR: COMPILATION ERROR: fail_rhs_def.carbon:[[@LINE+1]]: use of uninitialized variable x\n  var y: i32 = x;\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/16fb4fcee5f2fbd4b5b4e65358ab00e800f67db9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Number {\n  fn Zero() -> Self;\n  fn Add[self: Self](other: Self) -> Self;\n}\n\nclass Point(T:! Number) {\n  var x: T;\n  var y: T;\n}\n\nimpl i32 as Number {\n  fn Zero() -> i32 { return 0; }\n  fn Add[self: i32](other: i32) -> i32 { return self + other; }\n}\n\nimpl forall [U:! Number] Point(U) as Number {\n  fn Zero() -> Point(U) { return {.x = U.Zero(), .y = U.Zero() }; }\n  fn Add[self: Point(U)](other: Point(U)) -> Point(U) {\n    return {.x = self.x.Add(other.x), .y = self.y.Add(other.y)};\n  }\n}\n\nfn Sum[E:! Number](x: E, y: E) -> E {\n  var total: E = E.Zero();\n  total = total.Add(x);\n  total = total.Add(y);\n  return total;\n}\n\nfn SumPoints[E:! Number](p: Point(E), q: Point(E)) -> Point(E) {\n  return Sum(p, q);\n}\n\nfn Main() -> i32 {\n  var p: Point(i32) = {.x = 1, .y = 2};\n  var q: Point(i32) = {.x = 4, .y = 3};\n  var r: Point(i32) = SumPoints(p, q);\n  return r.x - r.y;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/17261c3182bd1de4382f0d3fef3917a949c36e32",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// This doesn't check trace output because it's too slow with it.\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\ninterface ManyTypes {\n  let T0:! type;\n  let T1:! type;\n  let T2:! type;\n  let T3:! type;\n  let T4:! type;\n  let T5:! type;\n  let T6:! type;\n  let T7:! type;\n}\n\ninterface Splat { fn Op(n: i32) -> Self; }\nimpl i32 as Splat {\n  fn Op(n: i32) -> Self { return n; }\n}\nimpl forall [T:! Splat] (T, T, T) as Splat {\n  fn Op(n: i32) -> Self {\n    let v: T = T.Op(n);\n    return (v, v, v);\n  }\n}\n\nfn CallSplat(T:! Splat, n: i32) -> T { return T.Op(n); }\n\nfn DoSplat(\n    M:! ManyTypes where\n      .T0 = (.T1, .T1, .T1) and\n      .T1 = (.T2, .T2, .T2) and\n      .T2 = (.T3, .T3, .T3) and\n      .T3 = (.T4, .T4, .T4) and\n      .T4 = (.T5, .T5, .T5) and\n      .T5 = (.T6, .T6, .T6) and\n      .T6 = (.T7, .T7, .T7) and\n      .T7 = i32,\n    n: M.T7) -> M.T0 {\n  return CallSplat(M.T0, n);\n}\n\ninterface First { fn Op[self: Self]() -> i32; }\nimpl i32 as First {\n  fn Op[self: Self]() -> i32 { return self; }\n}\nimpl forall [T:! First] (T, T, T) as First {\n  fn Op[self: Self]() -> i32 {\n    let (a: T, b: T, c: T) = self;\n    return a.Op();\n  }\n}\n\nfn DoFirst(\n    M:! ManyTypes where\n      .T7 = i32 and\n      .T6 = (.T7, .T7, .T7) and\n      .T5 = (.T6, .T6, .T6) and\n      .T4 = (.T5, .T5, .T5) and\n      .T3 = (.T4, .T4, .T4) and\n      .T2 = (.T3, .T3, .T3) and\n      .T1 = (.T2, .T2, .T2) and\n      .T0 = (.T1, .T1, .T1),\n    v: M.T0) -> M.T7 {\n  return v.(First.Op)();\n}\n\nclass C {\n  extend impl as ManyTypes where\n      .T3 = (.T4, .T4, .T4) and\n      .T1 = (.T2, .T2, .T2) and\n      .T4 = (.T5, .T5, .T5) and\n      .T6 = (.T7, .T7, .T7) and\n      .T2 = (.T3, .T3, .T3) and\n      .T7 = i32 and\n      .T5 = (.T6, .T6, .T6) and\n      .T0 = (.T1, .T1, .T1) {}\n}\n\nfn Main() -> i32 {\n  return DoFirst(C, DoSplat(C, 1));\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/17dc6eb1bbb8fd9671f46aa63924cf1a76837a2c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 1: 1\n// CHECK:STDOUT: 2: 2\n// CHECK:STDOUT: 3: 3\n// CHECK:STDOUT: 4: 4\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A {\n  var n: i32;\n  impl as ImplicitAs(i32) {\n    fn Convert[self: Self]() -> i32 { return self.n; }\n  }\n}\nimpl i32 as ImplicitAs(A) {\n  fn Convert[self: Self]() -> A { return {.n = self}; }\n}\n\nfn Main() -> i32 {\n  var arr1: array(i32, 2) = (1, 2 as A);\n  Print(\"1: {0}\", arr1[0]);\n  Print(\"2: {0}\", arr1[1]);\n\n  var arr2: array(A, 2) = (3, 4 as A);\n  Print(\"3: {0}\", arr2[0].n);\n  Print(\"4: {0}\", arr2[1].n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/184c236354c35072383945d9e6bdf0c005b5d20e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n\n  fn GetX[self: Point]() -> i32 {\n    return self.x;\n  }\n\n  fn GetXY[self: Point]() -> (i32, i32) {\n    return (self.GetX(), self.y);\n  }\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  return p.GetXY()[0];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/18909d083c5867fc03a952211bd61ca688bb908e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface Container {\n  let Element:! type;\n  fn Front[self: Self]() -> Element;\n}\n\nfn A[T:! Container where .Element = i32](x: T) -> T.Element {\n  return x.Front();\n}\n\nfn B[T:! Container](x: T) -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_missing_rewrite.carbon:[[@LINE+1]]: constraint requires that (T).(Container.Element) (with value (T).(Container.Element)) == i32, which is not known to be true\n  return A(x);\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1986b4fb3bc5c60ad5f4faa1b8003beb70a7ece8",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var (x: i32, y: i32);\n  x = 1;\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1a5c8022aeb946ee3551e569dad4ed36cdbcd44f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: A\n// CHECK:STDOUT: c.a: 1\n// CHECK:STDOUT: c.b: 2\n// CHECK:STDOUT: c.c: 3\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class A {\n  fn FunctionA() {}\n  var a: i32;\n  var aa: String;\n}\n\nbase class B {\n  extend base: A;\n  fn FunctionB() {}\n  var b: i32;\n}\n\nclass C {\n  extend base: B;\n  fn FunctionC() {}\n  var c: i32;\n}\n\nfn Main() -> i32 {\n  var c: C = {.base={.base={.aa=\"A\", .a=1}, .b=2, }, .c=3};\n  c.FunctionA();\n  c.FunctionB();\n  c.FunctionC();\n  Print(c.aa);\n  Print(\"c.a: {0}\", c.a);\n  Print(\"c.b: {0}\", c.b);\n  Print(\"c.c: {0}\", c.c);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1afe54e48b1e5bcdd7c8949513e0b2a3fbde1a65",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Print: {0}\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  Print(\"Print: {{0}\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1b85cf86024d9fcfe011f6998861b289aac97e60",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Allocate D\n// CHECK:STDOUT: DESTRUCTOR B\n// CHECK:STDOUT: DESTRUCTOR A\n// CHECK:STDOUT: DESTRUCTOR D\n// CHECK:STDOUT: DESTRUCTOR C\n// CHECK:STDOUT: Delete B from A*\n// CHECK:STDOUT: DESTRUCTOR B\n// CHECK:STDOUT: DESTRUCTOR A\n// CHECK:STDOUT: Delete D from C*\n// CHECK:STDOUT: DESTRUCTOR D\n// CHECK:STDOUT: DESTRUCTOR C\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class A {\n  virtual destructor[self: Self] {\n    Print(\"DESTRUCTOR A\");\n  }\n}\n\nclass B {\n  extend base: A;\n  fn Create() -> Self{\n    return {.base={}};\n  }\n  impl destructor[self: Self] {\n    Print(\"DESTRUCTOR B\");\n  }\n}\n\nbase class C {\n  virtual destructor[self: Self] {\n    Print(\"DESTRUCTOR C\");\n  }\n}\n\nclass D {\n  extend base: C;\n  fn Create() -> Self{\n    return {.base={}, .d_pa=heap.New(B.Create())};\n  }\n  impl destructor[self: Self] {\n    Print(\"DESTRUCTOR D\");\n  }\n  var d_pa: A*;\n}\n\nfn Main() -> i32 {\n  Print(\"Allocate D\");\n  var pd: D* = heap.New(D.Create());\n  var pc: C* = pd;\n\n  Print(\"Delete B from A*\");\n  heap.Delete(pd->d_pa);\n\n  Print(\"Delete D from C*\");\n  heap.Delete(pc);\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1baac08b0dfe6bf0b1157757b14ad4a389ba4693",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_too_many_args.carbon:[[@LINE+1]]: Print takes 1 or 2 arguments, received 5\n  Print(\"too\", \"many\", \"args\", \"to\", \"print\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1be679f324846aca4379ea4939981410425b287f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_assign_to_rval.carbon:[[@LINE+1]]: Only a reference expression can be assigned to, but got `1`\n  1 = 0;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1c56a65ba702fd27f5a72caf9c5e9170312db350",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_size_mismatch.carbon:[[@LINE+1]]: type error in initializer of variable: '(i32, i32, i32)' is not implicitly convertible to 'array(i32, 2)'\n  var x: array(i32, 2) = (0, 1, 2);\n  return x[0];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1c7eed351b92a87b8fd0c60d58e1916f3ae242d6",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 25\n\npackage ExplorerTest;\n\nclass List {\n  choice Node {\n    Nil,\n    Cons(i32, Self*)\n  }\n  var node: Node;\n\n  // Creates a list of `Cons(n, Cons(n - 1, ... Cons(1, Nil) ... ))`.\n  fn Make(n: i32) -> Self {\n    return {\n      .node = if n == 0 then Node.Nil else Node.Cons(n, heap.New(Make(n - 1)))\n    };\n  }\n\n  // Returns the sum of values in the list plus the value of `a`.\n  fn Sum[self: Self](a: i32) -> i32 {\n    match (self.node) {\n      case Node.Nil => { return a; }\n      case Node.Cons(b: i32, rest: Self*) => { return rest->Sum(a + b); }\n    }\n  }\n}\n\nfn Main() -> i32 {\n  var l: List = List.Make(5);\n  return l.Sum(10);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1d35c2bfb3606a1875a7d9218edc05b242cc75aa",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\nfn AddInt(a: i32, b: i32) -> i32 {\n  if (a == b) {\n    returned var ret: i32 = a + b;\n    return var;\n  } else {\n    return a + b;\n  }\n}\n\nfn Main() -> i32 {\n  return AddInt(1, 2);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1e1c015742738ddadeecb98baeb2988e9debfb6f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: i32\n// CHECK:STDOUT: String\n// CHECK:STDOUT: result: 0\n\npackage Testcase;\n\ninterface HasName {\n    let Name:! String;\n}\n\nimpl i32 as HasName where .Name = \"i32\" {}\nimpl String as HasName where .Name = \"String\" {}\n\nfn Main() -> i32 {\n    Print(i32.(HasName.Name));\n    Print(String.(HasName.Name));\n    return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1e55c67e9a55008a70df08daf7964b04102f5dd7",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn add(x: i32, y: i32) -> auto { return x + y; }\n\nfn Main() -> i32 {\n  return add(1, 2) - 3;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/1f6409865ff8ddad8bc5771a00d12932a67fb7dd",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: Integer overflow\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var a: auto = 5 << -1;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/20e03ea11ed959b8d8c2815133dbf0b31e2164c2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage Foo;\ninterface A { fn F() -> i32; }\nclass X {\n  extend impl as A {\n    fn F() -> i32 { return 1; }\n  }\n}\nfn Main() -> i32 {\n  var a: X = {};\n  return a.(A.F)();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2106211513dcb519a34bb65957c8fd0c85f75b16",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  {\n    // CHECK:STDERR: SYNTAX ERROR: fail_block.carbon:[[@LINE+1]]: syntax error, unexpected RETURN, expecting PERIOD or RIGHT_CURLY_BRACE\n    return 0;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/219513dc72d769293ba33b019ebd2282b7833404",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nchoice AB {\n  A(),\n  B()\n}\n\nfn F() -> AB { return AB.A(); }\n\nfn Main() -> i32 {\n  // This is T8 from http://moscova.inria.fr/~maranget/papers/warn/warn014.html\n  match ((F(), F(), F(), F(), F(), F(), F(), F())) {\n    case (AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 0; }\n    case (AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B()) => { return 1; }\n    case (_: AB,  AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 2; }\n    case (_: AB,  AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B()) => { return 3; }\n    case (_: AB,  _: AB,  AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 4; }\n    case (_: AB,  _: AB,  AB.B(), AB.B(), AB.B(), AB.B(), AB.B(), AB.B()) => { return 5; }\n    case (_: AB,  _: AB,  _: AB,  AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 6; }\n    case (_: AB,  _: AB,  _: AB,  AB.B(), AB.B(), AB.B(), AB.B(), AB.B()) => { return 7; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  AB.A(), AB.A(), AB.A(), AB.A()) => { return 8; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.B(), AB.B(), AB.B()) => { return 9; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.A(), AB.A(), AB.A()) => { return 10; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.B(), AB.B()) => { return 11; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.A(), AB.A()) => { return 12; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.B()) => { return 13; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.A()) => { return 14; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B()) => { return 15; }\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2268ee6ebd54f257f7fe853a15c6ef7785108cea",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  var x: i32;\n  var y: i32;\n}\n\nvar p: Point = {.x = 1, .y = 2};\n\nfn Main() -> i32 {\n  return p.y - p.x - 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/228ce64e3803e722ecf32dc43b499d6726756daf",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 7\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: 0\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as ModWith(i32) where .Result = A {\n  fn Op[self: Self](rhs: i32) -> A { return {.n = self.n % rhs}; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 15};\n  a = a % 8;\n  Print(\"{0}\", a.n);\n  a %= 4;\n  Print(\"{0}\", a.n);\n  Print(\"{0}\", (a % 3).n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2335a5e08cccb3045cf4b8bc8e68feb442d2324f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: This SHOULD fail but doesn't presently.\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nimport ExplorerTest library \"Nonexistent\";\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/236e8e31b5787b58b23bb57e00b101f89e8535b0",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass A {}\n\nfn Main() -> i32 {\n  var a: A = {};\n  // CHECK:STDERR: COMPILATION ERROR: fail_no_mul.carbon:[[@LINE+2]]: type error in `*`:\n  // CHECK:STDERR: could not find implementation of interface MulWith(U = i32) for class A\n  a * 1;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2379517a82b1d7db9c20bb4922230d42bbffa68a",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32;\n  x = 1;\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2394164e5f5c1d546a3da770f5b6e05994f3a30f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: 2\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class A {\n  var a: i32;\n}\n\nbase class B {\n  extend base: A;\n  var b: i32;\n}\n\nclass C {\n  extend base: B;\n  var c: i32;\n}\n\nfn Main() -> i32 {\n  var c: C = {.base = {.base = {.a = 1}, .b = 2}, .c = 3};\n  let (pa: A*, pb: B*, pc: C*) = (&c, &c, &c);\n  Print(\"{0}\", pa->a);\n  Print(\"{0}\", pb->b);\n  Print(\"{0}\", pc->c);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/241b6bbd6226547b2428d4a5cb71fed63597659d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nchoice Ints {\n  None,\n  One(i32),\n  Two(i32, i32)\n}\n\nfn Main() -> i32 {\n  let (var Ints.Two(a1: auto, var a2: auto),\n       ((b: auto, var c: auto), var (d: auto, e: auto))) =\n      (Ints.Two(1, 10), ((2, 3), (4, 5)));\n  a1 = 0;\n  a2 = 0;\n  c = 0;\n  d = 0;\n  e = 0;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/24a8948753be6ae079a443e207af49e88785fc27",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass ConvertTo(T:! type) {\n  var v: T;\n  extend impl as ImplicitAs(T) {\n    fn Convert[self: Self]() -> T { return self.v; }\n  }\n}\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_intrinsic_no_convert.carbon:[[@LINE+3]]: type error in __intrinsic_assert argument 0\n  // CHECK:STDERR: expected: bool\n  // CHECK:STDERR: actual: class ConvertTo(T = bool)\n  __intrinsic_assert({.v = true} as ConvertTo(bool), {.v = \"Pass\"} as ConvertTo(String));\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/24f96b44faf9d816c26ec36acd1f5c4562d0f1e9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_destination_not_type.carbon:[[@LINE+1]]: type error in type expression: 'i32' is not implicitly convertible to 'type'\n  return 4 as 7;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2689f156236c25d70a265b1261f8bea8cfef527f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// This doesn't test trace ouptut because it's too slow.\n// AUTOUPDATE\n// CHECK:STDOUT: String list length is: 7\n// CHECK:STDOUT: This is a String Entry 4\n// CHECK:STDOUT: Value 1337\n// CHECK:STDOUT: result: 0\npackage ExplorerTest;\n\nclass Node(T:! type) {\n  fn Create(value: T)-> Node(T) {\n    return {\n      .value = Optional(T).Create(value),\n      .next = Optional(Node(T)*).CreateEmpty(),\n      .prev = Optional(Node(T)*).CreateEmpty()\n    };\n  }\n  fn set_next[addr self: Self*](n: Optional(Node(T)*)) {\n    (*self).next = n;\n  }\n  fn set_prev[addr self: Self*](n: Optional(Node(T)*)) {\n    (*self).prev = n;\n  }\n  var value: Optional(T);\n  var next: Optional(Node(T)*);\n  var prev: Optional(Node(T)*);\n}\n\nclass LinkedList(T:! type) {\n  fn Create() -> LinkedList(T) {\n    return {\n      .head = Optional(Node(T)*).CreateEmpty(),\n      .tail = Optional(Node(T)*).CreateEmpty(),\n      .len = 0\n    };\n  }\n  fn PushBack[addr self: Self*](value:T) {\n    (*self).len = (*self).len + 1;\n    if(not (*self).head.HasValue()) {\n      (*self).head = Optional(Node(T)*).Create(heap.New(Node(T).Create(value)));\n      (*self).tail = (*self).head;\n      return;\n    }\n    var last: Optional(Node(T)*) = (*self).tail;\n    var last_value:Node(T)* = last.Get();\n    var v_wrapped:Optional(Node(T)*) = Optional(Node(T)*).Create(heap.New(Node(T).Create(value)));\n    (*last_value).set_next(v_wrapped);\n    (*v_wrapped.Get()).set_prev(last);\n    (*self).tail = v_wrapped;\n  }\n  fn PushFront[addr self: Self*](value:T) {\n    (*self).len = (*self).len + 1;\n    if(not (*self).head.HasValue()) {\n      (*self).head = Optional(Node(T)*).Create(heap.New(Node(T).Create(value)));\n      (*self).tail = (*self).head;\n      return;\n    }\n    var v_wrapped:Optional(Node(T)*) = Optional(Node(T)*).Create(heap.New(Node(T).Create(value)));\n    var current_head: Optional(Node(T)*) = (*self).head;\n    var current_head_value: Node(T)* = current_head.Get();\n    (*v_wrapped.Get()).set_next(current_head);\n    (*current_head_value).set_prev(v_wrapped);\n    (*self).head = v_wrapped;\n  }\n  fn Clear[addr self: Self*]() {\n    if((*self).len == 0) {\n      return;\n    }\n    var iter: auto = (*self).head;\n    while(iter.HasValue()) {\n      var current: auto = iter;\n      iter = (*iter.Get()).next;\n      heap.Delete(current.Get());\n    }\n    (*self).head = Optional(Node(T)*).CreateEmpty();\n    (*self).tail = Optional(Node(T)*).CreateEmpty();\n    (*self).len = 0;\n  }\n  fn Length[self: Self]() -> i32 {\n    return self.len;\n  }\n  var head: Optional(Node(T)*);\n  var tail: Optional(Node(T)*);\n  var len: i32;\n}\n\n// This function exists as a helper the context of this test case specifically and does not represent\n// the common case for index based lookups in list like structures.\nfn GetListEntryByIndex[T:! type](list: LinkedList(T)*, target_index: i32) -> Optional(T) {\n  let list_length: i32 = (*list).Length();\n  if(target_index > list_length - 1 or target_index < 0) {\n    // Not in possible range\n    return Optional(T).CreateEmpty();\n  }\n  var search_backwards:bool = target_index > list_length / 2;\n  var iter:Optional(Node(T)*) = if search_backwards then (*list).tail else (*list).head;\n  var c:i32 = if search_backwards then list_length -1 else 0;\n  while(c != target_index) {\n    var node: Node(T) = *(iter.Get());\n    if(search_backwards) {\n      c = c - 1;\n      iter = node.prev;\n    } else {\n      iter = node.next;\n      c = c + 1;\n    }\n  }\n\n  return (*(iter.Get())).value;\n}\n\nfn Main() -> i32 {\n  var test_list:auto = LinkedList(String).Create();\n  test_list.PushBack(\"This is a String Entry 0\");\n  test_list.PushBack(\"This is a String Entry 1\");\n  test_list.PushBack(\"This is a String Entry 2\");\n  test_list.PushBack(\"This is a String Entry 3\");\n  test_list.PushBack(\"This is a String Entry 4\");\n  test_list.PushBack(\"This is a String Entry 5\");\n  test_list.PushFront(\"This is a prepended String -1\");\n  Print(\"String list length is: {0}\", test_list.Length());\n  var search_index:i32 = 5;\n  var retrieved_entry: auto = GetListEntryByIndex(&test_list,search_index);\n  if(retrieved_entry.HasValue()) {\n    var retrieved_value:String = retrieved_entry.Get();\n    Print(retrieved_value);\n  } else {\n    Print(\"No entry found in String list for index {0}!\", search_index);\n  }\n  test_list.Clear();\n\n  var second_list: auto = LinkedList(i32*).Create();\n  var number: i32 = 1337;\n  var number_ptr: i32* = &number;\n  second_list.PushBack(number_ptr);\n  var retrieved_ptr:i32* = GetListEntryByIndex(&second_list, 0).Get();\n  var value: i32 = *retrieved_ptr;\n  Print(\"Value {0}\", value);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/283a045fd6c041aa47df273da411d601e7dada48",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 12\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var cond: if true then bool else i32 = true;\n  if (if cond then true else false) {}\n  while (if cond then false else true) {}\n  return if if cond then true or false else false and true\n         then if not cond then 1 + 2 else 3 * 4\n         else if not cond then 5 + 6 else 7 * 8;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/291711a108e2ed04586d978f1ac4a730277ffbb8",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 5\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as ImplicitAs(i32) {\n  fn Convert[self: Self]() -> i32 { return self.n; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 5};\n  return a as i32;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2a9df05598f94d7fefa11dd1451237e8c7b99f60",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 2\n\npackage ExplorerTest;\n\nfn A(b: bool) -> i32 {\n  match (b) {\n    case false => { return 1; }\n    case true => { return 2; }\n  }\n}\n\nfn Main() -> i32 {\n  return A(true);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2b504c78bc414daf63ba4618ebbd36bd92004d6e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Nice!\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var i: i32 = Rand(0, 100);\n  var j: i32 = Rand(0, 100);\n  if (i == j) {\n    Print(\"HALLO WELT\");\n  } else {\n    Print(\"Nice!\");\n  }\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2c05dbcf73a57af47793888b03384cdd43d5c594",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: RUNTIME ERROR: fail_div_by_zero.carbon:[[@LINE+1]]: division by zero\n  var a: auto = 5 / 0;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2d316de15bbe6edbbbeb3bc65e9350a7b53e0abe",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 2\n\npackage Foo;\nfn Main() -> i32 {\n  return {.m = 1, .n = 2}.({.n: i32, .m: i32}.n);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2df8a8f5865c0e813ed26a874c2ea0daf7421086",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: MemberF.F\n// CHECK:STDOUT: ImplF.(HasF.F)\n// CHECK:STDOUT: BothFs.(HasF.F)\n// CHECK:STDOUT: BothFs.F\n// CHECK:STDOUT: BothFs.F\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nchoice ImplKind {\n  Checked,\n  ConstrainedTemplate,\n  UnconstrainedTemplate\n}\n\ninterface CallF(K:! ImplKind) {\n  fn DoIt[self: Self]();\n}\n\ninterface HasF {\n  fn F[self: Self]();\n}\n\nimpl forall [T:! HasF] T as CallF(ImplKind.Checked) {\n  fn DoIt[self: Self]() { self.F(); }\n}\n\nimpl forall [template T:! HasF] T as CallF(ImplKind.ConstrainedTemplate) {\n  fn DoIt[self: Self]() { self.F(); }\n}\n\nimpl forall [template T:! type] T as CallF(ImplKind.UnconstrainedTemplate) {\n  fn DoIt[self: Self]() { self.F(); }\n}\n\nclass MemberF {\n  fn F[self: Self]() { Print(\"MemberF.F\"); }\n}\n\nclass ImplF {}\nimpl ImplF as HasF {\n  fn F[self: Self]() { Print(\"ImplF.(HasF.F)\"); }\n}\n\nclass BothFs {\n  fn F[self: Self]() { Print(\"BothFs.F\"); }\n}\nimpl BothFs as HasF {\n  fn F[self: Self]() { Print(\"BothFs.(HasF.F)\"); }\n}\n\nfn Main() -> i32 {\n  var mem: MemberF = {};\n  var imp: ImplF = {};\n  var both: BothFs = {};\n\n  mem.(CallF(ImplKind.UnconstrainedTemplate).DoIt)();\n\n  imp.(CallF(ImplKind.Checked).DoIt)();\n  // TODO: Should be valid, but currently fails during instantiation.\n  //imp.(CallF(ImplKind.ConstrainedTemplate).DoIt)();\n\n  both.(CallF(ImplKind.Checked).DoIt)();\n  // TODO: Should be rejected, but currently incorrectly accepted.\n  // This line can be deleted once it starts failing; we test that this is\n  // rejected in fail_name_lookup.carbon.\n  both.(CallF(ImplKind.ConstrainedTemplate).DoIt)();\n  both.(CallF(ImplKind.UnconstrainedTemplate).DoIt)();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2e02f9befd32eac2983de14b6ac8cf6cef960b4c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Id(t: type) -> auto { return t; }\n\n// Test non-trivial type expression in variable declaration statement.\n\nfn Main() -> i32 {\n  var x: Id(i32) = 0;\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2e05abea6fd46fc2b5315dca60d3b56e5b407fd4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass Shape {\n  var x: i32;\n}\n\nclass Point {\n\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n\n  fn GetSetX[addr self: Shape*](x: i32) -> i32 {\n    var old: auto = (*self).x;\n    (*self).x = x;\n    return old;\n  }\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  // CHECK:STDERR: COMPILATION ERROR: fail_method_self_type.carbon:[[@LINE+3]]: type error in method access, receiver type\n  // CHECK:STDERR: expected: class Shape\n  // CHECK:STDERR: actual: class Point\n  var x: auto = p.GetSetX(42);\n  if (p.x == 42) {\n    return x;\n  }\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/2e1aea3071937c4307dd48ebb2b1df3bc9e8716f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 12\n\npackage Foo;\ninterface A {\n  fn F[self: Self]() -> i32;\n}\ninterface B {\n  fn G(o: Self) -> i32;\n}\nalias C = A & B;\nclass X {\n  extend impl as A {\n    fn F[self: Self]() -> i32 { return 10 * self.n; }\n  }\n  extend impl as B {\n    fn G(o: Self) -> i32 { return o.n; }\n  }\n  var n: i32;\n}\nfn Main() -> i32 {\n  var v: X = {.n = 1};\n  var w: X = {.n = 2};\n  return v.(C.F)() + X.(C.G)(w);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/300e45006b32eec72e90d33d3cd6685680448957",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\nimpl package ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: RUNTIME ERROR: fail_single_brace.carbon:[[@LINE+1]]: `{` must be followed by a second `{` or index in `{`\n  Print(\"{\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/301dc6263f2a34b4630aa88e940f42acf020f160",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_raw_block_quotes_not_on_own_line.carbon:[[@LINE+1]]: Invalid block string: Should end with triple quotes: error: closing '''\n  var s: String = #'''\n    error: closing '''# is not on its own line.\n  '''#;\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3037fd1afeda607e889fe3e73fb1088d13c9f8bf",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// Check that even generic parameters are looked up in the namespace of an\n// entity.\nnamespace N;\n\ninterface N.Interface {}\n\nclass N.A(T:! Interface) {}\ninterface N.B(T:! Interface) {}\nconstraint N.C(T:! Interface) {}\n__mixin N.D(T:! Interface) {}\nchoice N.E(T:! Interface) {}\nfn N.F[T:! Interface](a: A(T)) {}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/306f80d197d3d627368e752f1ad6aa42d2e89aa6",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: array(array(i32, 3), 2) = ((0, 1, 2), (3, 4, 5));\n  return x[1][2] - 5;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3082cf2a6045d00b6e81d3ae14a3a3d56314b988",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: c.Foo() -> 1\n// CHECK:STDOUT: c.Bar() -> 2\n// CHECK:STDOUT: d.Foo() -> 3\n// CHECK:STDOUT: d.Bar() -> 4\n// CHECK:STDOUT: cc.Foo() -> 3\n// CHECK:STDOUT: cc.Bar() -> 2\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class C {\n  virtual fn Foo[self: Self]() -> i32 {\n    return 1;\n  }\n  fn Bar[self: Self]() -> i32 {\n    return 2;\n  }\n}\n\nclass D {\n  extend base: C;\n  impl fn Foo[self: Self]() -> i32 {\n    return 3;\n  }\n  fn Bar[self: Self]() -> i32 {\n    return 4;\n  }\n}\n\nfn Main() -> i32 {\n  var c: C = {};\n  Print(\"c.Foo() -> {0}\", c.Foo());\n  Print(\"c.Bar() -> {0}\", c.Bar());\n  var d: D = {.base = {}};\n  Print(\"d.Foo() -> {0}\", d.Foo());\n  Print(\"d.Bar() -> {0}\", d.Bar());\n  var cc: C* = &d;\n  Print(\"cc.Foo() -> {0}\", (*cc).Foo());\n  Print(\"cc.Bar() -> {0}\", (*cc).Bar());\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/310b6d61f64901b21169432ef6bbc13a2b602376",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var t: auto = (1, 2);\n  var a: array(i32, 2) = t;\n  return a[0] + a[1];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3116bbbb3bae537a09e62f5c8331a431d6c56b1e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Allocate B\n// CHECK:STDOUT: DESTRUCTOR B\n// CHECK:STDOUT: DESTRUCTOR A\n// CHECK:STDOUT: Delete B\n// CHECK:STDOUT: DESTRUCTOR B\n// CHECK:STDOUT: DESTRUCTOR A\n// CHECK:STDOUT: Return\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n\nbase class A{\n    destructor[self: Self] {\n        Print(\"DESTRUCTOR A\");\n    }\n}\n\nclass B {\n  extend base: A;\n    fn Create() -> Self{\n        return {.base={}};\n    }\n    destructor[self: Self] {\n        Print(\"DESTRUCTOR B\");\n    }\n}\n\nfn Main() -> i32 {\n  Print(\"Allocate B\");\n  var pb: B* = heap.New(B.Create());\n\n  Print(\"Delete B\");\n  heap.Delete(pb);\n\n  Print(\"Return\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3119cacb5f47007660225c4a63a934eff83091a2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Vector {\n  fn Zero() -> Self;\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: i32) -> Self;\n}\n\nclass Point(T:! type) {\n  var x: T;\n  var y: T;\n}\n\nimpl Point(i32) as Vector {\n  // Allowed: `Self` means `Point(i32)` here.\n  fn Zero() -> Self {\n    return {.x = 0, .y = 0};\n  }\n\n  fn Add[self: Self](b: Self) -> Self {\n    return {.x = self.x + b.x, .y = self.y + b.y};\n  }\n\n  fn Scale[self: Self](v: i32) -> Self {\n    return {.x = self.x * v, .y = self.y * v};\n  }\n}\n\nfn AddAndScaleGeneric[T:! Vector](a: T, s: i32) -> T {\n  return a.Add(T.Zero()).Scale(s);\n}\n\nfn Main() -> i32 {\n  var a: Point(i32) = {.x = 2, .y = 1};\n  var p: Point(i32) = AddAndScaleGeneric(a, 5);\n  return p.x - 10;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/317bdb0ba661c19d4be7dc1a9e0eb74529c80bba",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  if (0 == 1) {\n    return 1;\n  } else if (0 == 0) {\n    return 0;\n  }\n\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/31e5d9b3712744f0659429e330ba44958eadce7c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\nimpl package ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: RUNTIME ERROR: fail_index_bounds1.carbon:[[@LINE+1]]: Index invalid with argument count of 1 at offset 12 in `Print: {0} {1}`\n  Print(\"Print: {0} {1}\", 1);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3292cacd15031b51dcfdd4d623e0ef30c66eb86b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n__mixin Operations {\n  fn F[self: Self](x: Self) -> Self{\n     return x;\n  }\n}\n\nclass Point {\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n\n  var x: i32;\n  var y: i32;\n  __mix Operations;\n}\n\nclass Complex {\n  fn Zero() -> Complex {\n    return {.r = 0, .i = 0};\n  }\n\n  var r: i32;\n  var i: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  var c: Complex = {.r = 42, .i = 1};\n  // CHECK:STDERR: COMPILATION ERROR: fail_self_substitution.carbon:[[@LINE+1]]: mismatch in non-deduced types, `class Complex` is not implicitly convertible to `class Point`\n  var p1: Point = p.F(c);\n\n  return p1.x - 42;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/32ffc355b444c61ccd2d80ca466aa47b4f5b4d4b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 12\n\npackage ExplorerTest;\n\ninterface Runnable {\n  fn Run[self: Self]() -> i32;\n}\n\ninterface Walkable {\n  fn Walk[self: Self]() -> i32;\n}\n\nconstraint Traversible {\n  extend Runnable;\n  extend Walkable;\n}\n\nimpl i32 as Traversible {\n  fn Run[self: i32]() -> i32 {\n    return 10 * self;\n  }\n  fn Walk[self: i32]() -> i32 {\n    return self + 1;\n  }\n}\n\nfn Main() -> i32 {\n  var n: i32 = 1;\n  return n.(Runnable.Run)() + n.(Walkable.Walk)();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/33358007d39274e780a256e497695c3fe46f1029",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage Foo;\ninterface A { fn F[self: Self]() -> i32; }\nclass X {\n  extend impl as A {\n    fn F[self: Self]() -> i32 { return 1; }\n  }\n}\nfn Main() -> i32 {\n  var a: X = {};\n  return a.(X.(A.F))();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3476b8646b5b6b64fba9ab4b662850eff9312d41",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// Ensure that we can declare all different kinds of declarations as namespace\n// members.\nnamespace N;\n\n__mixin N.Mixin {}\n\nbase class N.BaseClass {\n  __mix Mixin;\n}\n\nclass N.DerivedClass {\n  extend base: BaseClass;\n}\n\nnamespace N.Inner;\n\nalias N.Inner.InnerClass = DerivedClass;\n\nchoice N.Choice { A, B, C(DerivedClass) }\n\ninterface N.Iface {\n  fn F() -> DerivedClass*;\n}\n\nconstraint N.Constraint {\n  extend Iface;\n}\n\nvar v: N.DerivedClass = {.base = {}};\n\nfn N.F[T:! Constraint]() {\n  var v: Inner.InnerClass = {.base = {}};\n}\n\nimpl i32 as N.Constraint {\n  fn F() -> N.DerivedClass* { return &v; }\n}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/358f451f412939d0e0863704128cbc4756839499",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\nimpl package EmptyIdentifier;\n\nfn A() {\n  // CHECK:STDERR: RUNTIME ERROR: fail_function_recursion.carbon:[[@LINE+1]]: stack overflow: too many interpreter actions on stack\n  A();\n}\n\nfn Main() -> i32 {\n  A();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/37934fb6e5e6d857d3227ea76872ce6a3bc4d630",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  if (0 == 1) {\n    return 1;\n  } else {\n    return 0;\n  }\n\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/37b6c00cc00d3ea562a9a67d365b1617be17cda4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn AddInt(a: i32, b: i32) -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_returned_var_type_mismatch.carbon:[[@LINE+1]]: type of returned var `bool` does not match return type `i32`\n  returned var ret: bool = true;\n  return var;\n}\n\nfn Main() -> i32 {\n  return AddInt(1, 2);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/396c9121839a9d9866282f987fb283fa86556474",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: XYZ: 1\n// CHECK:STDOUT: XY: 1\n// CHECK:STDOUT: XZ: 1\n// CHECK:STDOUT: YZ: 2\n// CHECK:STDOUT: JustX: 1\n// CHECK:STDOUT: JustY: 2\n// CHECK:STDOUT: JustZ: 3\n// CHECK:STDOUT: None: 4\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface A {\n  fn Which() -> i32;\n}\n\ninterface X {}\ninterface Y {}\ninterface Z {}\n\n__match_first {\n  impl forall [T:! X] T as A {\n    fn Which() -> i32 { return 1; }\n  }\n  impl forall [T:! Y] T as A {\n    fn Which() -> i32 { return 2; }\n  }\n  impl forall [T:! Z] T as A {\n    fn Which() -> i32 { return 3; }\n  }\n  impl forall [T:! type] T as A {\n    fn Which() -> i32 { return 4; }\n  }\n}\n\nclass XYZ {}\nclass XY {}\nclass XZ {}\nclass YZ {}\nclass JustX {}\nclass JustY {}\nclass JustZ {}\nclass None {}\n\nimpl XYZ as X & Y & Z {}\nimpl XY as X & Y {}\nimpl XZ as X & Z {}\nimpl YZ as Y & Z {}\nimpl JustX as X {}\nimpl JustY as Y {}\nimpl JustZ as Z {}\n\nfn Main() -> i32 {\n  Print(\"XYZ: {0}\", XYZ.(A.Which)());\n  Print(\"XY: {0}\", XY.(A.Which)());\n  Print(\"XZ: {0}\", XZ.(A.Which)());\n  Print(\"YZ: {0}\", YZ.(A.Which)());\n  Print(\"JustX: {0}\", JustX.(A.Which)());\n  Print(\"JustY: {0}\", JustY.(A.Which)());\n  Print(\"JustZ: {0}\", JustZ.(A.Which)());\n  Print(\"None: {0}\", None.(A.Which)());\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3a414cdb79537ba6113eebe683a258098caebe9c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass C {\n  // CHECK:STDERR: COMPILATION ERROR: fail_member_of_self.carbon:[[@LINE+1]]: incomplete type `class C` used in type of variable\n  var m: Self;\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3abd6729fc8141ee2cf270432da6cfe0bc85c3b6",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Invalid {}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3ade1694dc4a9b14c34f03ad62b68872d22dee82",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn f(x: i32, y: i32) -> i32 { return x + y; }\n\nfn Main() -> i32 {\n  var xy: (i32, i32) = (1, 2);\n  // should fail to type-check\n  // CHECK:STDERR: COMPILATION ERROR: fail_call_with_tuple.carbon:[[@LINE+1]]: wrong number of arguments in function call, expected 2 but got 1\n  return f(xy);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3c57cd00b20c65032e36beeae83dbc34da90d96a",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\nimpl package EmptyIdentifier;\n\nfn Main() -> i32 {\n  while (true) {\n    // Ideally we would hit an OOM here, but it's too difficult to OOM from heap\n    // allocations before hitting max steps. Maybe with string operations we\n    // could trigger actual excessive memory allocations by just doubling the\n    // size of the string each time.\n    // CHECK:STDERR: RUNTIME ERROR: fail_allocate.carbon:[[@LINE+1]]: possible infinite loop: too many interpreter steps executed\n    heap.New((0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0));\n  }\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3cf84352b479800d6fc3cf96f8493945c2211b0f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_raw_block_more_hash_tags_on_left.carbon:[[@LINE+1]]: Unexpected end of file\n  var s: String = ##'''\n    error: there are more #s on the left than the right.\n  '''#;\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3d3543e880e8d01a5f3de62c8e5137fb6cddf741",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 4\n\npackage ExplorerTest;\n\nalias TypeAlias = i32;\n\nfn Main() -> TypeAlias {\n  var n: TypeAlias = 1;\n  var m: i32 = n;\n  var p: i32* = &n;\n  var q: TypeAlias* = &m;\n  return *p + *q + m + n;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/3e2b7a2777680a17f8ee4fdc72e6e2eeccb06bbe",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n__mixin Operations {\n  fn Square[self: Self](x:i32) -> i32{\n    return x * x;\n  }\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  fn DistanceSquare[self: Self](other:Self) -> i32 {\n    return self.Square(self.x - other.x) + self.Square(self.y - other.y);\n  }\n  __mix Operations;\n}\n\nclass Complex {\n  var r: i32;\n  var i: i32;\n  __mix Operations;\n  fn AbsSquare[self: Self]() -> i32 {\n    return self.Square(self.r) + self.Square(self.i);\n  }\n}\n\n\nfn Main() -> i32 {\n  var p1: Point = {.x = 1, .y = 2 };\n  var p2: Point = {.x = 4, .y = 3 };\n  var c: Complex = {.r = 5, .i = 6 };\n  return c.AbsSquare() - p1.DistanceSquare(p2) - 51;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/41de2a58a6891d68e779f2017ef063decc946cd4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass C {\n  // CHECK:STDERR: SYNTAX ERROR: fail_method_self_misspelled.carbon:[[@LINE+1]]: illegal binding pattern in implicit parameter list\n  fn F[addr slef: Self*]() {}\n}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/423c611625411a3e7e1a514f78b3f56d4482852f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n  fn GetX[self: Point]() -> i32 {\n    return self.x;\n  }\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  var f: __Fn() -> i32 = p.GetX;\n  return f();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4250d5daad936e112c495fba82c027d68b64d5af",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\nimpl package ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_intrinsic_too_many_args.carbon:[[@LINE+1]]: Print takes 1 or 2 arguments, received 4\n  __intrinsic_print(\"\", 1, 2, 3);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/43403b1e7abd01b7c671e6defefd7531f5c6702e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: \"HALLO WELT\"\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  Assert(false, \"HALLO WELT\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4340b66cecbff7df2c6932cb03440a29e55bdfd3",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  return p.x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4455db071205f7d5bdb9fc2fae623c64067b42d7",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// Error: Can't use keyword `Self` as the name of a class.\n// CHECK:STDERR: SYNTAX ERROR: fail_class_named_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting identifier or LEFT_PARENTHESIS\nclass Self {\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Self = {.x = 1, .y = 2};\n  return p.y - p.x - 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/47afc3df9dd4fcdebc2c8a1ef7b0dc87435dc016",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n__mixin Mixin {\n  // CHECK:STDERR: COMPILATION ERROR: fail_mix_invalid.carbon:[[@LINE+1]]: Not a valid mixin: `()`\n  __mix ();\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/483ceff680765b8a2c582e18111fe71a754e1844",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Number {\n  fn Zero() -> Self;\n  fn Add[self: Self](other: Self) -> Self;\n}\n\nclass Point(T:! Number) {\n  fn Origin() -> Point(T) {\n    return {.x = T.Zero(), .y = T.Zero()};\n  }\n  var x: T;\n  var y: T;\n}\n\nimpl i32 as Number {\n  fn Zero() -> i32 { return 0; }\n  fn Add[self: i32](other: i32) -> i32 { return self + other; }\n}\n\nfn SumXY[U:! Number](p: Point(U)) -> U {\n  return p.Origin().x.Add(p.y);\n}\n\nfn Main() -> i32 {\n  var p: Point(i32) = {.x = 0, .y = 0};\n  return SumXY(p);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/48b15c4b985c9b46b8e95e3c822ad1f65108ae39",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 5\n\npackage ExplorerTest;\n\nclass A {\n  var n: i32;\n  fn Get[self: Self]() -> i32 { return self.n; }\n}\n\nfn Main() -> i32 {\n  return ({.n = 5} as A).Get();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/48f161ebf1c515fbc92fc959814c40d6394b5360",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var arr: array(i32, 2) = (0, 1);\n  var x: [i32;] = arr;\n  var index: i32 = 1;\n  x[index] = 0;\n  return x[0] + x[1];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/498eecf3c6bcc6332b955ae5c2260a5451e73add",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: T as Iface\n// CHECK:STDOUT: T as Iface\n// CHECK:STDOUT: A as Iface\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface HasType {\n  let AssocType:! type;\n}\n\ninterface Iface {\n  fn F();\n}\n\nimpl forall [T:! HasType where .Self.AssocType impls Iface] T as Iface {\n  fn F() {\n    Print(\"T as Iface\");\n    T.AssocType.(Iface.F)();\n  }\n}\n\nclass A {\n  extend impl as Iface {\n    fn F() { Print(\"A as Iface\"); }\n  }\n}\n\nclass B {\n  extend impl as HasType where .AssocType = A {}\n}\n\nclass C {\n  extend impl as HasType where .AssocType = B {}\n}\n\nfn Main() -> i32 {\n  let c: C = {};\n  c.(Iface.F)();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4a035921222f3bc29547b41d7ba8b6da0d6d1918",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var s: String = #'''\n    A \"block\" \"\"string\"\" literal\n      with indent.\n    '''#;\n  if (s == #\"A \\#\"block\\#\" \\#\"\\#\"string\\#\"\\#\" literal\\#n  with indent.\\#n\"#) {\n    return 0;\n  } else {\n    return 1;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4a2b48d7a92dd98fe609be64224be82772f55d0b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_unimplemented_example.carbon:[[@LINE+1]]: Unimplemented\n  return 1 __unimplemented_example_infix 2;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4a53102a9f8003845552337ac998169e11d09d50",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32 = 0;\n  match (x) {\n    case 1 => {\n      return 1;\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4ab72b4e37f3135ed58cbad67238c92072799757",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// CHECK:STDERR: COMPILATION ERROR: fail_unknown_namespace.carbon:[[@LINE+1]]: name 'N' has not been declared in this scope\nfn N.F() {}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4be506d3d29dbde616deda5b966e460b702d8078",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Interface {}\nimpl {} as Interface {}\nimpl {.x: i32} as Interface {}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4c74c032df7c917af8e4bc833b777bb2bec80211",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass Point {\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_instantiate_non_generic.carbon:[[@LINE+1]]: in call `Point(i32)`, expected callee to be a function, found `type`\n  var p: Point(i32) = Point.Origin();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4ce8273ccba8f2b4cf0d8b721bf35b100e19e0b2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 0: Heap{}, 1: C{}\n// CHECK:STDOUT: Initialize c from reference expression\n// CHECK:STDOUT: 0: Heap{}, 1: C{}\n// CHECK:STDOUT: c destroyed\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass C {\n  destructor[self: Self] {\n    Print(\"c destroyed\");\n  }\n}\n\nfn FromReferenceExpression() {\n  var c_var: C = {};\n  heap.PrintAllocs();\n  Print(\"Initialize c from reference expression\");\n  let c: C = c_var;\n  heap.PrintAllocs();\n}\n\nfn Main() -> i32 {\n  FromReferenceExpression();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4d2449569a2536b234828155b7449ee755d60a1c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_hex_truncated.carbon:[[@LINE+1]]: Invalid escaping in string: \"str\\x\"\n  Print(\"str\\x\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4dd5200e6960e3538c180263762afa41dafd9e85",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass A {}\n\nfn Main() -> i32 {\n  var a: A = {};\n  var b: A* = &a;\n  // CHECK:STDERR: COMPILATION ERROR: fail_invalid_ptr_conversion1.carbon:[[@LINE+1]]: type error in initializer of variable: 'class A*' is not implicitly convertible to 'i32'\n  var c: i32 = b;\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/4f3bfc326a24c79bc61dd3f657879de3c4c92393",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// CHECK:STDERR: COMPILATION ERROR: fail_invalid_fnty.carbon:[[@LINE+2]]: type error in `-`:\n// CHECK:STDERR: could not find implementation of interface Negate for bool\nfn f(g: __Fn(-true) -> true) {\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/50fa09b0616f12e3550c8d8db69371cc2909a299",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 6\n// CHECK:STDOUT: 0\n// CHECK:STDOUT: -1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as BitXorWith(i32) where .Result = A {\n  fn Op[self: Self](rhs: i32) -> A { return {.n = self.n ^ rhs}; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 5};\n  a = a ^ 3;\n  Print(\"{0}\", a.n);\n  a ^= 6;\n  Print(\"{0}\", a.n);\n  Print(\"{0}\", (a ^ -1).n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/51be544495cddd6b63fa15569d1f9c15da88d404",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var s: String = #'''\n    A block string literal\n    \\#'''#\n    '''#;\n  if (s == \"A block string literal\\n'''#\\n\") {\n    return 0;\n  } else {\n    return 1;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/52aef5e56788c511815ca05612341c56cf96bc7c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\ninterface ManyTypes {\n  let T0:! type;\n  let T1:! type;\n  let T2:! type;\n  let T3:! type;\n  let T4:! type;\n  let T5:! type;\n  let T6:! type;\n  let T7:! type;\n  let T8:! type;\n  let T9:! type;\n}\n\nfn F[\n  M:! ManyTypes where\n    .T0 = .T1 and\n    .T1 = .T2 and\n    .T2 = .T3 and\n    .T3 = .T4 and\n    .T4 = .T5 and\n    .T5 = .T6 and\n    .T6 = .T7 and\n    .T7 = .T8 and\n    .T8 = .T9 and\n    .T9 = i32](m: M) -> i32 {\n  var v: M.T0 = 1;\n  return v;\n}\n\nclass C {\n  extend impl as ManyTypes where\n    .T0 = i32 and\n    .T1 = .T0 and\n    .T2 = .T1 and\n    .T3 = .T2 and\n    .T4 = .T3 and\n    .T5 = .T4 and\n    .T6 = .T5 and\n    .T7 = .T6 and\n    .T8 = .T7 and\n    .T9 = .T8 {}\n}\n\nfn Main() -> i32 {\n  var c: C = {};\n  return F(c);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/547ffea2b538ce83c02ff5e112290b3c72f944dc",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point(T:! type) {\n  // Allowed: `Self` means `Point(T)` here.\n  fn Origin(zero: T) -> Self {\n    return {.x = zero, .y = zero};\n  }\n\n  fn GetX[self: Self]() -> T {\n    return self.x;\n  }\n\n  var x: T;\n  var y: T;\n}\n\nfn Main() -> i32 {\n  var p: Point(i32) = Point(i32).Origin(0);\n  return p.GetX();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/54887e4d15dfaada3929936e0a970b82c1dfb62e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass S(T:! type) {}\nclass Z {}\n\nclass Tree(L:! type, R:! type) {}\nclass Leaf {}\n\ninterface Foo(T:! type) {}\n\nimpl forall [U:! type, T:! Foo(Tree(U, U))] S(T) as Foo(U) {}\n\nalias Level1 = Tree(Leaf, Leaf);\nalias Level2 = Tree(Level1, Level1);\nalias Level3 = Tree(Level2, Level2);\nalias Level4 = Tree(Level3, Level3);\nalias Level5 = Tree(Level4, Level4);\n\nimpl Z as Foo(Level5) {}\n\nfn F[T:! Foo(Leaf)](x: T) {}\nfn Main() -> i32 {\n  var n: S(S(S(S(S(Z))))) = {};\n  F(n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/54dab9151ed3293f3aec67e58aa20e26aa632a98",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var v: array(i32, 2);\n  // CHECK:STDERR: COMPILATION ERROR: fail_array.carbon:[[@LINE+1]]: use of uninitialized variable v\n  return v[0];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/54e697b7fd97a4ca280483aac15d69a1fe995994",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass C {\n  fn F() {}\n  fn G[self: Self]() {}\n}\n\nfn ReturnF() -> auto { return C.F; }\n// CHECK:STDERR: COMPILATION ERROR: fail_return_method.carbon:[[@LINE+1]]: member name G can only be used in a member access or alias\nfn ReturnG() -> auto { return C.G; }\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/55bafb0b85e56d740867aa2eced4270cee6022ec",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Initialize c from initializing expression (return <expr>)\n// CHECK:STDOUT: Entering call\n// CHECK:STDOUT: 0: Heap{}, 1: !Uninit<class C>\n// CHECK:STDOUT: Object created, returning\n// CHECK:STDOUT: 0: Heap{}, 1: !Uninit<class C>, 2: C{}\n// CHECK:STDOUT: c destroyed\n// CHECK:STDOUT: 0: Heap{}, 1: C{}, 2: !!C{}\n// CHECK:STDOUT: c destroyed\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass C {\n  destructor[self: Self] {\n    Print(\"c destroyed\");\n  }\n}\n\nfn CallWithReturnExpression() -> C {\n  Print(\"Entering call\");\n  heap.PrintAllocs();\n  var c: C = {};\n  Print(\"Object created, returning\");\n  heap.PrintAllocs();\n  return c;\n}\n\nfn FromInitializingExpression_ReturnExpr() {\n  Print(\"Initialize c from initializing expression (return <expr>)\");\n  var c: C = CallWithReturnExpression();\n  heap.PrintAllocs();\n}\n\nfn Main() -> i32 {\n  FromInitializingExpression_ReturnExpr();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/55cffdb200c153f12a0b584d8f24754b6a5cdbca",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: auto = {.x = 10, .y = 1};\n  var p: i32* = &x.x;\n  *p = 0;\n\n  return x.x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/56aa3535abaf9c5df81b685d1eb0a71f5d80f43c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: DESTRUCTOR A 1\n// CHECK:STDOUT: DESTRUCTOR A 2\n// CHECK:STDOUT: DESTRUCTOR A 3\n// CHECK:STDOUT: DESTRUCTOR A 1\n// CHECK:STDOUT: DESTRUCTOR A 2\n// CHECK:STDOUT: DESTRUCTOR A 3\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nclass A{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR A {0}\",self.n);\n    }\n    var n: i32;\n}\n\nfn Main() -> i32 {\n  var i: i32 = 0;\n  while( i < 2){\n    var a: A = {.n = 3};\n    var b: A = {.n = 2};\n    var c: A = {.n = 1};\n    i = i + 1;\n  }\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5730670e62da8cb89476867288e21c654dcde6e5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var a: i32 = 1;\n  let a_pinned: i32 = a;\n  // OK: Value unused after being mutated.\n  a = 2;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5aa8d527e2f0f75c4013ddde704d0f7f6afa4ad5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn CompareStr(s: String) -> i32 {\n  if (s == ##\"#\"str\"#\"##) {\n    return 0;\n  }\n  return 1;\n}\n\nfn Main() -> i32 {\n  return CompareStr(\"#\\\"str\\\"#\");\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5b0309128112c0a5ac3a2ffcd03a66d062224d48",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// Test a global variable depending on another global.\n\nvar x: i32 = 0;\n\nvar y: i32 = x;\n\nfn Main() -> i32 {\n  return y;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5b19e864b0b73fde9f4ec0903239424fb6c036ca",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32;\n  // CHECK:STDERR: COMPILATION ERROR: fail_compound_assign.carbon:[[@LINE+1]]: use of uninitialized variable x\n  x += 1;\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5b3a56d8084b2c87582aa9cb7f0ff56cfde0f0b5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage Foo;\n\nclass X {\n  fn F[self: Self](o: Self) -> Self { return {.n = self.n + o.n}; }\n  var n: i32;\n}\n\nfn Main() -> i32 {\n  return {.n = 1}.(X.F)({.n = 2}).n;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5bbdca0e72629685bfc1132d00e114960b2fcb82",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn fst[T:! type](x: T, y: T) -> T {\n  return x;\n}\n\nfn Main() -> i32 {\n  return fst(0, 1);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5bd0c3c2901ec5b0052a7a9a76eb84cb611d1c42",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 7\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  return (1 + 2) + 4;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5d0c180874af1a76aaa137f32b3eecedb408ceef",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  if (0 == 0) {\n    if (0 == 1) {\n      return 1;\n    } else {\n      return 0;\n    }\n  }\n\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5d8390990020b1a44590ce1b13c484d1075dc50f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: DESTRUCTOR A 1\n// CHECK:STDOUT: DESTRUCTOR B 2\n// CHECK:STDOUT: DESTRUCTOR A 3\n// CHECK:STDOUT: DESTRUCTOR A 4\n// CHECK:STDOUT: DESTRUCTOR A 5\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nclass A{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR A {0}\",self.n);\n    }\n    fn Create(x: i32) -> A{\n        return {.n = x};\n    }\n    var n: i32;\n}\n\nclass B{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR B {0}\",self.n);\n    }\n    fn Create(x: i32) -> B{\n       return {.n = x, .a1 = A.Create(4),.a2 = A.Create(3) };\n    }\n    var a1: A;\n    var n: i32;\n    var a2: A;\n}\n\n\nfn Main() -> i32 {\n  var a: A = A.Create(5);\n  var b: B = B.Create(2);\n  var c: A = A.Create(1);\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5da086526436d984a0e8b01ca482b178852084e5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\ninterface Frob {\n  let Result:! type;\n  fn F[self: Self]() -> Result;\n}\n\nfn Use[T:! Frob where .Result = .Self](x: T) -> T {\n  var v: T = x.F();\n  return v;\n}\n\nimpl i32 as Frob where .Result = i32 {\n  fn F[self: Self]() -> i32 { return self + 1; }\n}\n\nfn Main() -> i32 {\n  return Use(2);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5dce231f6950396fe0965788b6d8f24cf033b4b4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: auto = 2;\n  while (x != 0) {\n    x = x - 1;\n    continue;\n    x = x + 1;\n  }\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5e45e4e1b479e4388e38277605992ce44cea1e57",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn CompareStr(s: String) -> i32 {\n  if (s == \"str;\\x07\") {\n    return 0;\n  }\n  return 1;\n}\n\nfn Main() -> i32 {\n  return CompareStr(\"\\x73\\x74\\x72\\x3B\\x07\");\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5e968b8fb1b7fa51cea34638d04c2b0c75b3c92f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn CompareStr(s: String) -> i32 {\n  if (s == \"HELLO WORLD!!\") {\n    return 0;\n  }\n  return 1;\n}\n\nfn Main() -> i32 {\n  return CompareStr(\"\\u{0048}\\u{0045}\\u{004C}\\u{004C}\\u{004F} \\u{0057}\\u{004F}\\u{0052}\\u{004C}\\u{0044}\\u{0021}\\u{21}\");\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5f89b222e699d47c8a41bb74abebc81f76578cf0",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 6\n\npackage ExplorerTest;\n\nnamespace N;\n\nfn OuterI32() -> type { return i32; }\nfn One() -> i32 { return 1; }\n\nfn N.I32() -> type { return i32; }\nfn N.Five() -> I32() { return 5; }\nfn N.Six() -> OuterI32() { return Five() + One(); }\n\nfn Main() -> i32 { return N.Six(); }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/5f954e8ee1ace4e6a57d4defefc7d87c30deadbe",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 4\n\npackage ExplorerTest;\n\nfn F[T:! ImplicitAs(type)](x: T) -> type { return x; }\n\nfn Main() -> i32 {\n  var v: (i32, i32) as type = (1, 2);\n  var w: F((i32, i32)) = (3, 4);\n  v = w;\n  return v[1];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6003b3dcd82396edba816e537507a435839fe1f8",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn F() {\n  return;\n}\n\nfn Main() -> i32 {\n  F();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/616631daa1b2f3fb44b606c331569f490f341778",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_octal.carbon:[[@LINE+1]]: Invalid escaping in string: \"str\\01\"\n  Print(\"str\\01\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/631701015ee748a5c3d22fe34412f7b00c32a4af",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var a: [i32;] = ();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6485f068351f2f9eb9124bc4032d5fdad43fc611",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_raw_block_more_hash_tags_on_right.carbon:[[@LINE+1]]: invalid character '\\x23' in source file.\n  var s: String = #'''\n    error: there are more #s on the right than the left.\n  '''##;\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/64cabff382c905a7598bdb67fdc450e7d675a22e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 2\n\npackage ExplorerTest;\n\ninterface Vector {\n  let Dim:! i32;\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  extend impl as Vector where .Dim = 2 {}\n}\n\nfn Main() -> i32 {\n  return Point.(Vector.Dim);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/64d95aad6787b2388d89783f9f19de16ad3bf546",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32 = 2;\n  while (true) {\n    if (x == 0) {\n      break;\n    } else {\n      x = x - 1;\n    }\n  }\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/66400bd8514c00f6cf25eff62d2e48445f57182c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: RUNTIME ERROR: fail_mod_by_zero.carbon:[[@LINE+1]]: division by zero\n  var a: auto = 5 % 0;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6771c2bd2677e585863903ea55026479ccd17870",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass Point {\n  // CHECK:STDERR: COMPILATION ERROR: fail_qualified_method.carbon:[[@LINE+1]]: qualified declaration names are not permitted in this context\n  fn Point.F[self: Self]() {}\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/67aaf0d5127285b5bc7f230c34abeb2f046cc18c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: This SHOULD fail but doesn't presently.\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nimport Nonexistent;\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/68adfc912ab9c22031735ea064b9abfb759e860b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = {.x = 1, .y = 2};\n  return p.y - p.x - 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/68aebf293bd4ae573c514613325fcf490c8d98c4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\n// The bodies of member functions are processed after all immediately enclosing\n// classes, impl declarations, and interfaces.\nclass A {\n  fn F[self: Self]() -> i32 {\n    return G() + self.H();\n  }\n  fn G() -> i32 { return 1; }\n  fn H[self: Self]() -> i32 { return 2; }\n}\n\nfn Main() -> i32 {\n  var a: A = {};\n  return a.F();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/69ae9f5b1bed179e5cccdfb4f7351a3fa7825d46",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// This tests the call-by-value aspect of parameter passing.\n// This makes sure that when the value in `x` dies,\n// it does not cause the value in `a` to also die.\n\nfn f(x: i32) -> i32 {\n  return 0;\n}\n\nfn Main() -> i32 {\n  var a: i32 = 0;\n  var b: i32 = 1;\n  f(a);\n  b = a;\n  return b;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/69bab187ee3bed045d1af0a1325d5daabbfebcb7",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: i32.Hash\n// CHECK:STDOUT: 0\n// CHECK:STDOUT: Potato.(Hashable.Hash)\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: Potato.Hash\n// CHECK:STDOUT: 2\n// CHECK:STDOUT: Potato.Hash\n// CHECK:STDOUT: 2\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Hashable {\n  fn Hash[self: Self]() -> i32;\n}\n\nclass Potato {\n  impl as Hashable {\n    fn Hash[self: Self]() -> i32 {\n      Print(\"Potato.(Hashable.Hash)\");\n      return 1;\n    }\n  }\n\n  fn Hash[self: Self]() -> i32 {\n    Print(\"Potato.Hash\");\n    return 2;\n  }\n}\n\ninterface Maker {\n  let Result:! Hashable;\n  fn Make() -> Result;\n}\n\nimpl i32 as Hashable {\n  fn Hash[self: Self]() -> i32 {\n    Print(\"i32.Hash\");\n    return self;\n  }\n}\n\nfn F[T:! Maker where .Result = i32](x: T) -> i32 {\n  // OK, can treat T.Make() as an i32.\n  return T.Make() + 1;\n}\n\nfn G[T:! Maker](x: T) -> i32 {\n  // OK, Potato.(Hashable.Hash), not Potato.Hash.\n  return T.Make().Hash();\n}\n\nfn H[T:! Maker where .Result = Potato](x: T) -> i32 {\n  // OK, Potato.Hash, not Potato.(Hashable.Hash).\n  return T.Make().Hash();\n}\n\nfn I[T:! Maker where .Result = Potato](x: T) -> i32 {\n  var p: Potato = {};\n  // OK, Potato.Hash, not Potato.(Hashable.Hash), even though we know Potato is\n  // Hashable here.\n  return p.Hash();\n}\n\nclass IntFactory {\n  extend impl as Maker where .Result = i32 {\n    fn Make() -> i32 { return 0; }\n  }\n}\n\nclass PotatoFactory {\n  extend impl as Maker where .Result = Potato {\n    fn Make() -> Potato { return {}; }\n  }\n}\n\nfn Main() -> i32 {\n  var f: IntFactory = {};\n  var g: PotatoFactory = {};\n  Print(\"{0}\", F(f));\n  Print(\"{0}\", G(f));\n  Print(\"{0}\", G(g));\n  Print(\"{0}\", H(g));\n  Print(\"{0}\", I(g));\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6b59783e9131166ae1396039351b8920c1532eda",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var (x: auto, y: auto) = (2, 3);\n  return y - x - 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6bcc2a0c19cfffb661acb141bc57e351b31fe545",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point(T:! type) {\n  fn Origin(zero: T) -> Point(T) {\n    return {.x = zero, .y = zero};\n  }\n\n  fn GetX[self: Point(T)]() -> T {\n    return self.x;\n  }\n\n  var x: T;\n  var y: T;\n}\n\nfn Main() -> i32 {\n  var p: Point(i32) = Point(i32).Origin(0);\n  return p.GetX();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6c0ade4e7511d55f3594435cbab260c61c6eb433",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\npackage ExplorerTest;\n\n__mixin M1 {\n  fn F1[self: Self](x: Self) -> Self{\n     return x;\n  }\n  // CHECK:STDERR: COMPILATION ERROR: fail_recursive_mixing.carbon:[[@LINE+1]]: incomplete mixin `M1` used in mix declaration\n  __mix M1;\n}\n\nclass C {\n  __mix M1;\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6c4ef5a1d954eca2c4076a9ab38c85ed546d7d78",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32{\n  var x: Optional(String) = Optional(String).CreateEmpty();\n  if(x.HasValue()){\n    return -1;\n  }\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6c7a321e86789ab26b7bdb3e5709364a0d4cd686",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 5\n\npackage ExplorerTest;\n\nclass Point(T:! type) {\n  var x: T;\n  var y: T;\n}\n\nfn GetX[T:! type](pt: Point(T)) -> T {\n  return pt.x;\n}\nfn GetY(T:! type, pt: Point(T)) -> T {\n  return pt.y;\n}\n\nfn Main() -> i32 {\n  var p: Point(i32) = {.x = 1, .y = 2};\n  // TODO: Should `GetX({.x = 1, .y = 2})` work? See #1251.\n  return GetX(p) + GetY(i32, {.x = 3, .y = 4});\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6d8712954da7301cf9eba612efb43217ff2c9c9d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage Foo;\nfn F[self: i32]() {}\nfn Main() -> i32 {\n  // TODO: It's unclear whether this is valid per the current rules. See\n  // https://github.com/carbon-language/carbon-lang/pull/1122\n  // CHECK:STDERR: COMPILATION ERROR: fail_qualified_non_member.carbon:[[@LINE+1]]: expected name of instance member or interface member in compound member access, found fn [self: i32]() -> ()\n  42.(F)();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6d9f91f6f40fb8ddf061ae76c5f2beaefe6c8bee",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Foo() -> () {\n  returned var x: () = ();\n  return var;\n}\n\nfn Main() -> i32 {\n  Foo();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6e7b40cf5df2608cac7f3a034875623185812bdc",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface Similar(T:! type) {}\n\nimpl forall [T:! type] T as Similar(T) {}\nimpl forall [T:! type] i32 as Similar(T) {}\n\nfn CheckSimilar[T:! type, U:! Similar(T)](a: T, b: U) {}\n\nfn Main() -> i32 {\n  let n: i32 = 0;\n  CheckSimilar(true, false);\n  CheckSimilar(true, n);\n  // CHECK:STDERR: COMPILATION ERROR: fail_param_interface_in_impl.carbon:[[@LINE+1]]: could not find implementation of interface Similar(T = i32) for bool\n  CheckSimilar(n, false);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6ee7d990d6d84b254f8ff655a2a9061ff87df262",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nvar call_count: i32 = 0;\nfn ReturnTrue() -> bool {\n  call_count = call_count + 1;\n  return true;\n}\n\nfn Main() -> i32 {\n  var result: bool = ReturnTrue() or ReturnTrue();\n  return if result then call_count else -1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6f39466681bb52b19ab384450e0bbb67598fd2ce",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface I {\n  fn F() -> i32;\n  fn M[self: Self]() -> i32;\n}\nclass A {\n  var n: i32;\n  extend impl as I {\n    fn F() -> i32 { return 1; }\n    fn M[self: Self]() -> i32 { return 2; }\n  }\n  fn G[self: Self]() -> i32 { return 3; }\n}\nimpl i32 as I {\n  fn F() -> i32 { return 4; }\n  fn M[self: Self]() -> i32 { return 5; }\n}\n\nalias IF = I.F;\nalias IM = I.M;\nalias AIF = A.(IF);\nalias AIM = A.(IM);\nalias AG = A.G;\nalias i32IF = i32.(IF);\nalias i32IM = i32.(IM);\n\nfn Main() -> i32 {\n  var a: A = {.n = 0};\n  if (A.(IF)() != 1) {\n    return 1;\n  }\n  if (a.(IF)() != 1) {\n    return 2;\n  }\n  if (a.(IM)() != 2) {\n    return 3;\n  }\n  if (a.(A.(IM))() != 2) {\n    return 4;\n  }\n  if (AIF() != 1) {\n    return 5;\n  }\n  if (a.(AIM)() != 2) {\n    return 6;\n  }\n  if (a.(AG)() != 3) {\n    return 7;\n  }\n  if (i32.(IF)() != 4) {\n    return 8;\n  }\n  if (0.(IF)() != 4) {\n    return 9;\n  }\n  if (0.(IM)() != 5) {\n    return 10;\n  }\n  if (0.(i32.(IM))() != 5) {\n    return 11;\n  }\n  if (i32IF() != 4) {\n    return 12;\n  }\n  if (0.(i32IM)() != 5) {\n    return 13;\n  }\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/6f97d913a4f39bd5e8501dec2cc7bcf87e23e9d0",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: H 22\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n\nchoice MyOptionalElement(T:! type) {\n  None(),\n  Element(T)\n}\n\nclass MyOptional(T:! type){\n   fn CreateEmpty() -> MyOptional(T){\n       return { .element = MyOptionalElement(T).None() };\n   }\n   fn Create ( value: T ) -> MyOptional(T){\n       return { .element = MyOptionalElement(T).Element(value) };\n   }\n\n    fn has_value[self: Self] () -> bool{\n        var x: MyOptionalElement(T) = self.element;\n        match(x){\n            case MyOptionalElement(T).None() => { return false; }\n        }\n        return false;\n    }\n\n    fn get[self: Self] () -> T {\n        var x: MyOptionalElement(T) = self.element;\n        match(x){\n            case MyOptionalElement(T).Element( var x: T ) =>{\n                return x;\n            }\n        }\n        // TODO: Mark this as unreachable somehow.\n        return get();\n    }\n\n   var element: MyOptionalElement(T);\n}\n\n\nfn Main() -> i32 {\n  var f: MyOptional(i32) = MyOptional(i32).Create(22);\n  var x: i32 = f.get();\n  Print(\"H {0}\",x);\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/70f5b6fb23691d532301ffb58ab24649f6454d8c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var p: i32* = __intrinsic_new(0);\n  var y: i32 = *p;\n  __intrinsic_delete(p);\n  return y;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/710cfbe95b3fc5a9bb53fce89ef1a0abe2e09e85",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n\n  fn GetSetX[addr self: Point*](x: i32) -> i32 {\n    var old: auto = (*self).x;\n    (*self).x = x;\n    return old;\n  }\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  var x: auto = p.GetSetX(42);\n  if (p.x == 42) {\n    return x;\n  }\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/71a53f6b5ecb6b4368eee4224d614609f4ff4d56",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface I {\n  fn G[self: Self]();\n}\n\nclass C {\n  impl as I {\n    // CHECK:STDERR: COMPILATION ERROR: fail_impl_missing_self.carbon:[[@LINE+3]]: type error in member of implementation\n    // CHECK:STDERR: expected: fn [self: class C]() -> ()\n    // CHECK:STDERR: actual: fn () -> ()\n    fn G() { }\n  }\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/723771f1826c803bbd50afe6e703268a89d6edab",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\n// CHECK:STDERR: SYNTAX ERROR: fail_invalid_char.carbon:[[@LINE+1]]: invalid character '\\xEF' in source file.\n�\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/72a4e959879e3eaffd79dc30af15cb2ada073648",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Has(T:! type) {\n  fn Get() -> T;\n}\nimpl i32 as Has(type) {\n  fn Get() -> type { return Self; }\n}\n\nclass WithType(T:! Has(type)) {\n  fn Get() -> type { return T.Get(); }\n}\n\nfn Main() -> i32 {\n  var v: WithType(i32).Get() = 0;\n  return v;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/73235c4067e2da4fc1dbfe403e2354fd0598b639",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  return p.Origin().x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/7405fcca02b54d584c14af5493adc45467b2fdd9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass C {\n  fn F() {}\n  fn G[self: Self]() {}\n}\n\nfn H[T:! type](x: T) {}\n\nfn Main() -> i32 {\n  H(C.F);\n  // CHECK:STDERR: COMPILATION ERROR: fail_method_deduced.carbon:[[@LINE+1]]: member name G can only be used in a member access or alias\n  H(C.G);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/7471dc3d8630cf15ed61e384f95aeb80117b3e69",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 5\n\npackage ExplorerTest;\n\ninterface A(T:! type) { let AResult:! type; }\ninterface B(T:! type) { let BResult:! A(T); }\ninterface I(T:! type) {\n  let X:! B(T);\n  // The constraints introduced by X should be in scope here.\n  let Y:! X.BResult.AResult;\n}\n\nclass CA {\n  extend impl as A(i32) where .AResult = i32 {}\n}\nclass CB {\n  extend impl as B(i32) where .BResult = CA {}\n}\nclass CI {\n  extend impl as I(i32) where .X = CB and .Y = 5 {}\n}\n\nfn Main() -> i32 {\n  var v: CI = {};\n  return v.(I(i32).Y);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/760ef78e2194d159e3160c5f1ed9c2d14461da19",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 7\n\npackage ExplorerTest;\n\nalias TypeAlias = i32;\n\nfn Function(a: i32, b: TypeAlias) -> i32 { return a + b; }\nfn GenericFunction[T:! type](x: T) -> T { return x; }\n\nalias FunctionAlias = Function;\nalias GenericFunctionAlias = GenericFunction;\n\nfn Main() -> i32 {\n  return FunctionAlias(1, 2) + GenericFunctionAlias(4);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/78280fde00fc74d5293e1df394c1cf6012277f2c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nvar x: i32;\n\nfn Main() -> i32 {\n  x = 1;\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/79189aed1ece423113c07026aa1d7b2c9f79050c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// TODO: Implement this with some kind of reflection?\nimpl {.x: i32, .y: i32} as EqWith(Self) {\n  fn Equal[self: Self](other: Self) -> bool {\n    return self.x == other.x and self.y == other.y;\n  }\n  fn NotEqual[self: Self](other: Self) -> bool {\n    return self.x != other.x or self.y != other.y;\n  }\n}\n\nfn Main() -> i32 {\n  var t1: {.x: i32, .y: i32} = {.x = 5, .y = 2};\n  var t2: {.x: i32,} = {.x = 5,};\n  // CHECK:STDERR: COMPILATION ERROR: fail_equality_type.carbon:[[@LINE+1]]: {.x: i32, .y: i32} is not equality comparable with {.x: i32} (could not find implementation of interface EqWith(U = {.x: i32}) for {.x: i32, .y: i32})\n  if (t1 == t2) {\n    return 1;\n  } else {\n    return 0;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/79df4004383e0a52581c0b97ce9cf662e0032101",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_invalid_integer.carbon:[[@LINE+1]]: Invalid integer literal: 11111111111111111111111111\n  return 11111111111111111111111111;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/7a700c8e06316b9d48f34dcbdd6c79c9ca739570",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nfn map[T:! type](f: __Fn (T) -> T, tuple: (T, T)) -> (T, T) {\n  return (f(tuple[0]), f(tuple[1]));\n}\n\nfn inc(x: i32) -> i32 { return x + 1; }\n\nfn Main() -> i32 {\n  return map(inc, (0, 2))[0];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/7b1de3f5a9e1d40dbd7c4b342ec1da84cceb016f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_unexpected_tuple.carbon:[[@LINE+1]]: didn't expect a tuple\n  var a: (auto,) = 1;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/7c27cb6aeaf045bb89f59207280218ae5712357d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Initialize c1 from initializing expression (returned var)\n// CHECK:STDOUT: Before nested init\n// CHECK:STDOUT: 0: Heap{}, 1: !Uninit<class C>\n// CHECK:STDOUT: Nested call return\n// CHECK:STDOUT: 0: Heap{}, 1: C{}\n// CHECK:STDOUT: First call return\n// CHECK:STDOUT: 0: Heap{}, 1: C{}\n// CHECK:STDOUT: Declaration scope\n// CHECK:STDOUT: 0: Heap{}, 1: C{}\n// CHECK:STDOUT: c destroyed\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass C {\n  destructor[self: Self] {\n    Print(\"c destroyed\");\n  }\n}\n\nfn CallWithReturnedVar2() -> C {\n  Print(\"Before nested init\");\n  heap.PrintAllocs();\n  returned var c: C = {};\n  Print(\"Nested call return\");\n  heap.PrintAllocs();\n  return var;\n}\n\nfn CallWithReturnedVar() -> C {\n  returned var c: C = CallWithReturnedVar2();\n  Print(\"First call return\");\n  heap.PrintAllocs();\n  return var;\n}\n\nfn FromInitializingExpression_ReturnedVar() {\n  Print(\"Initialize c1 from initializing expression (returned var)\");\n  let c: C = CallWithReturnedVar();\n  Print(\"Declaration scope\");\n  heap.PrintAllocs();\n}\n\nfn Main() -> i32 {\n  FromInitializingExpression_ReturnedVar();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/7c829002e321ac8fbc1b7bcc46f58f3032646bfb",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: RUNTIME ERROR: fail_overflow_add.carbon:[[@LINE+1]]: integer overflow\n  var a: auto = 2147483647 + 1;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/7ca9fe97a14160b8620cee481aba4f12ef5e239f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn F() {\n}\n\nfn Main() -> i32 {\n  F();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/7cc77a9919de591289f6f01b7f3df2d2daa58297",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface IFace {}\n\nimpl {.IFace : (type where type == i32 and type == i32 and type == i32, )} as IFace {\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/7f5cf073e6e1bfe73c3256257aa83cffc3456ce5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\nimpl package ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_intrinsic_int_format.carbon:[[@LINE+3]]: type error in Print argument 0\n  // CHECK:STDERR: expected: String\n  // CHECK:STDERR: actual: i32\n  __intrinsic_print(0);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/80e834464c299e6fa3fed5551d31712d4ae0adc2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn F() -> () {\n  // CHECK:STDERR: COMPILATION ERROR: fail_explicit_with_plain_return.carbon:[[@LINE+1]]: return; should provide a return value, to match the function's signature.\n  return;\n}\n\nfn Main() -> i32 {\n  F();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/8232c8a2839a7671df6947987108ae25e6027767",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 42\n\npackage ExplorerTest;\n\nclass A {\n  extend impl as ImplicitAs(i32) {\n    fn Convert[self: Self]() -> i32 { return 42; }\n  }\n}\n\nfn Main() -> i32 {\n  var a: A = {};\n  return a;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/82431aad891633c384f8e3dc8af548420cfc207a",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// Never actually called, so this only tests typechecking and semantic analysis.\nfn F(n: i32, p: i32*, q: i32***) -> i32* {\n  var a: i32 = n * *p;\n  var b: i32 = a*n;\n  *p = b*(*p);\n  **q = p;\n  return **q;\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/827994a1d2fbe88e785e28ac7fe3dc2d8043e8ad",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  // Allowed: `Self` here means `Point`.\n  fn Origin() -> Self {\n    return {.x = 0, .y = 0};\n  }\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  return p.x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/8308e1750041583282a6c913cc4e2c4fb9f48353",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// Test empty parameters and return type\nfn f() { }\n\nfn Main() -> i32 {\n  f();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/83941bf67b0cd2e4d3f7502b2bb40a83889bf78b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\n// CHECK:STDERR: SYNTAX ERROR: fail_missing.carbon:[[@LINE+1]]: syntax error, unexpected FN, expecting PACKAGE\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/83e710c959e54010bceb9b0aad34ded746b6eb2a",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// Test multiple arguments\nfn f(x: i32, y: i32) -> i32 {\n  return x + y;\n}\n\nfn Main() -> i32 {\n  return f(2, 3) - 5;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/842268df9223d721e951b5865fb9d9c684129679",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32 = 0;\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/85017c3fdc47972d87932e4089f349f6c324ece9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\nchoice Opt {\n  None(),\n  Some(i32)\n}\n\nfn A(a: Opt, b: Opt) -> i32 {\n  match ((a, b)) {\n    case (Opt.Some(n: i32), _: auto) => { return n; }\n    case (_: auto, Opt.Some(n: i32)) => { return n; }\n    case (Opt.None(), Opt.None()) => { return 0; }\n  }\n}\n\nfn B(a: Opt, b: Opt) -> i32 {\n  match ((a, b)) {\n    case (Opt.None(), _: auto) => { return 0; }\n    case (Opt.Some(n: i32), Opt.None()) => { return n; }\n    case (Opt.Some(n: i32), Opt.Some(m: i32)) => { return n + m; }\n  }\n}\n\nfn Main() -> i32 {\n  return A(Opt.None(), Opt.Some(1)) + B(Opt.Some(2), Opt.None());\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/85cde7cf9e3e8e282a265f653b60cb0ef60b8b48",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass Point {\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point;\n  if (1 == 0) {\n    p = {.x = 0, .y = 0};\n  }\n  // CHECK:STDERR: RUNTIME ERROR: fail_store_to_uninitialized_class.carbon:[[@LINE+1]]: undefined behavior: store to subobject of uninitialized value Uninit<Placeholder<p>>\n  p.x = 1;\n  p.y = 2;\n  return p.x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/85f4667d9dee7230ec98fd7a1b1c7455a6a4ab5d",
    "content": "\n// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass B {\n  var x: i32;\n\n  fn GetSetX[addr self: Self*](x: i32) -> i32 {\n    var oldX: auto = (*self).x;\n    (*self).x = x;\n    return oldX;\n  }\n}\n\nclass A {\n  var b: B;\n}\n\nfn Main() -> i32 {\n  var b: B = {.x = 0};\n  var a: A = {.b = b};\n  var x: auto = a.b.GetSetX(42);\n  if (a.b.x == 42) {\n    return x;\n  }\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/874eddf3ad6e08849a2214088ee525df154883c6",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: 4\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var a: (i32, i32) = (1, 2);\n  var p: (i32, i32)* = &a;\n\n  a[0] = 3;\n  Print(\"{0}\", (*p)[0]);\n\n  (*p)[1] = 4;\n  Print(\"{0}\", a[1]);\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/877257bc5b2b43345bd445518317b709596eac7c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: 7\n// CHECK:STDOUT: 15\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as BitOrWith(i32) where .Result = A {\n  fn Op[self: Self](rhs: i32) -> A { return {.n = self.n | rhs}; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 1};\n  a = a | 2;\n  Print(\"{0}\", a.n);\n  a |= 5;\n  Print(\"{0}\", a.n);\n  Print(\"{0}\", (a | 12).n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/88031d95585417463e2939d40ff53cc9c8a12221",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nfn IntDiff(a: i32, b: i32) -> i32 {\n  if (a == b) {\n    returned var ret: i32 = a - b;\n    return var;\n  } else {\n    returned var ret2: i32 = b - a;\n    return var;\n  }\n}\n\nfn Main() -> i32 {\n  return IntDiff(1, 2);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/89a6c64c03c3683482810e5362c2417be45ed07c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: RUNTIME ERROR: fail_overflow_multiply.carbon:[[@LINE+1]]: integer overflow\n  var a: auto = 1000000000 * 1000000000;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/89af2ff0da3a9c42a04a7b2b3bbc05755060273d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface Z {\n  fn Zero() -> Self;\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  // `Self` not allowed after `extend impl`.\n  // CHECK:STDERR: SYNTAX ERROR: fail_extend_with_self.carbon:[[@LINE+1]]: syntax error, unexpected SELF, expecting AS\n  extend impl Self as Z {\n    fn Zero() -> Self {\n      return {.x = 0, .y = 0};\n    }\n  }\n}\n\nfn Main() -> i32 {\n  var a: Point = Point.Zero();\n  return p.x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/89fab5bae29d8a674f37cce24cbedeff198cfb5d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: DESTRUCTOR A 1\n// CHECK:STDOUT: DESTRUCTOR A 2\n// CHECK:STDOUT: DESTRUCTOR A 3\n// CHECK:STDOUT: DESTRUCTOR A 4\n// CHECK:STDOUT: DESTRUCTOR A 5\n// CHECK:STDOUT: DESTRUCTOR A 6\n// CHECK:STDOUT: DESTRUCTOR A 7\n// CHECK:STDOUT: DESTRUCTOR A 8\n// CHECK:STDOUT: DESTRUCTOR A 6\n// CHECK:STDOUT: DESTRUCTOR A 7\n// CHECK:STDOUT: DESTRUCTOR A 8\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nclass A{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR A {0}\",self.n);\n    }\n    var n: i32;\n}\n\nfn Main() -> i32 {\n  var i: i32 = 0;\n  while(true){\n      var a: A = {.n = 4};\n      var b: A = {.n = 3};\n      var c: A = {.n = 2};\n      if(true){\n        var a: A = {.n = 1};\n        break;\n      }\n  }\n\n  i = 0;\n  while(i < 2 ){\n    var a: A = {.n = 8};\n    var b: A = {.n = 7};\n    var c: A = {.n = 6};\n    if(i == 0){\n      var a: A = {.n = 5};\n      i = i+1;\n      continue;\n    }\n    i = i+1;\n  }\n\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/8aed12f4aa27c3ac5d1b3703d202428777fe983b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\nimpl package ExplorerTest;\n\ninterface I {}\n\n// CHECK:STDERR: COMPILATION ERROR: fail_call_at_compile_time.carbon:[[@LINE+1]]: Print called before run time\nimpl forall [T:! String] Print(T) as I {}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/8cbe098387a007f60eb4209259915d6d85532fa5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\ninterface A(T:! type) {}\ninterface B {\n  fn F() -> i32;\n}\n\nclass C(T:! type) {}\n\nimpl forall [T:! type] C(T) as A(T) & B {\n  fn F() -> i32 { return 1; }\n}\n\nfn Main() -> i32 {\n  var v: C(i32) = {};\n  return v.(B.F)();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/8e0b56d89ffc8caa0feaf38b36642aea4c1be601",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// TODO: Implement this with some kind of reflection?\nimpl {.x: i32, .y: i32} as EqWith(Self) {\n  fn Equal[self: Self](other: Self) -> bool {\n    return self.x == other.x and self.y == other.y;\n  }\n  fn NotEqual[self: Self](other: Self) -> bool {\n    return self.x != other.x or self.y != other.y;\n  }\n}\n\nfn Main() -> i32 {\n  var t1: {.x: i32, .y: i32} = {.x = 5, .y = 2};\n  var t2: {.x: i32, .y: i32} = {.x = 5, .y = 4};\n  if (t1 == t2) {\n    return 1;\n  } else {\n    return 0;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/8f27934a9f00dec469d67e7336b7d8f52ec4abd6",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 6\n\npackage ExplorerTest;\n\n// The constraint here resolves to:\n//\n//   MulWith(T) where <ConstraintSelf>.(MulWith(T).Result) == <ConstraintSelf>\n//\n// Note in particular that this involves a member of `MulWith(T)`, so we need\n// `T` to have a symbolic identity when checking its own type.\nfn DoMul[T:! MulWith(.Self) where .Result == .Self](x: T, y: T) -> T {\n  return x * y;\n}\n\nfn Main() -> i32 {\n  return DoMul(2, 3);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/8fab0dc50d28280cdeab5def1ae75d70f860a1a7",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nabstract class B {\n}\n\n// CHECK:STDERR: COMPILATION ERROR: fail_instantiate_global_abstract.carbon:[[@LINE+1]]: Cannot instantiate abstract class B\nvar b: B = {};\n\nfn Main() -> i32 {\n    return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/90ce2617c868946d7fa04649195ab1ab5fff4b20",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_block_quotes_not_on_own_line.carbon:[[@LINE+1]]: Invalid block string: Should end with triple quotes: error: closing '''\n  var s: String = '''\n    error: closing ''' is not on its own line.\n  ''';\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/92904c2b09ee456d0d1a2cf3d69dfd26fd190641",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var a: [i32;0] = ();\n  var b: [i32;] = a;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/92b290bf1d1d95e5a7e7813af2199781f92b350e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  returned var x: i32 = 1;\n  if (true) {\n    var x: i32 = 2;\n    return var;\n  }\n  x = 3;\n  return var;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/92b34177d4245d4172436708ba988ac171eb9eb2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Vector {\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: i32) -> Self;\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  extend impl as Vector {\n    fn Add[self: Point](b: Point) -> Point {\n      return {.x = self.x + b.x, .y = self.y + b.y};\n    }\n    fn Scale[self: Point](v: i32) -> Point {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n  }\n}\n\nfn ScaleGeneric[U:! Vector](c: U, s: i32) -> U {\n  return c.Scale(s);\n}\n\nfn AddAndScaleGeneric[T:! Vector](a: T, b: T, s: i32) -> T {\n  return ScaleGeneric(a.Add(b), s);\n}\n\nfn Main() -> i32 {\n  var a: Point = {.x = 1, .y = 1};\n  var b: Point = {.x = 2, .y = 3};\n  var p: Point = AddAndScaleGeneric(a, b, 5);\n  return p.x - 15;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/932e6052bd882919514042cc953293cd63659b5e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass Point(T:! type) {\n  // CHECK:STDERR: COMPILATION ERROR: fail_two_arg_lists.carbon:[[@LINE+1]]: in call `Point(T)(T)`, expected callee to be a function, found `type`\n  fn Origin(zero: T) -> Point(T)(T) {\n    return {.x = zero, .y = zero};\n  }\n\n  fn GetX[self: Point(T)(T)]() -> T {\n    return self.x;\n  }\n\n  var x: T;\n  var y: T;\n}\n\nfn Main() -> i32 {\n  var p: Point(i32) = Point(i32).Origin(0);\n  return p.GetX();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/94a3ce6126281beaf24a4595ac2f27a2c6e04b2d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest library \"Foo\";\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/964b65adb9c33d86539ec025f5cf745e1c4e61e1",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// CHECK:STDERR: COMPILATION ERROR: fail_parameter_type_only.carbon:[[@LINE+1]]: An irrefutable pattern is required, but `i32` is refutable.\nfn f(x: i32, i32) {}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/96656d19f3e5b82f968f3b4282ba524a814595b3",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// CHECK:STDERR: COMPILATION ERROR: fail_dot_self_not_in_scope.carbon:[[@LINE+1]]: could not resolve '.Self'\nfn Main() -> .Self {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/968568fe7d320af2e8e6adfc30e3f81dd2f8818e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32;\n  // CHECK:STDERR: COMPILATION ERROR: fail_increment.carbon:[[@LINE+1]]: use of uninitialized variable x\n  ++x;\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/9706cab087de61b00158e0ac6d755f1352589bdd",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // -2147483648 is unsupported as a literal, but we can do it with a decrement.\n  var low: i32 = -2147483647;\n  low -= 1;\n  var high: i32 = 2147483647;\n  Rand(low, high);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/9745b84a597bf13955fb7d208e94f2795aeb7813",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Foo(n: i32) {\n  Print(\"{0}\", n);\n}\n\nfn Main() -> i32 {\n  var v: {.a: i32, .b: i32} = {.a = 1, .b = 2};\n  let a: i32 = v.a;\n  v.b = 3;\n  Foo(a);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/9787ad2c566323a856a6225b91dbbfbf8e8d3ee8",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 5\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  let n: i32 = 5;\n  return n as i32;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/979f63c217bbde19dd385c49d577dc3090d54317",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 2\n\npackage ExplorerTest;\n\ninterface HasAssoc {\n  let Assoc:! type;\n}\nclass X {\n  impl as HasAssoc where .Assoc = i32 {}\n}\n\nalias WithoutRewrite = HasAssoc where .Assoc == i32;\nalias WithRewrite = HasAssoc where .Assoc = i32;\n\nfn G[T:! WithoutRewrite](x: T) -> i32 {\n  // TODO: We should reject this once `==` isn't applied automatically.\n  var a: T.(WithRewrite.Assoc) = 2;\n  return a;\n}\n\nfn Main() -> i32 {\n  var x: X = {};\n  return G(x);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/98b45893e4f4c1b0a893d2562df5e8559555f223",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 2\n\npackage ExplorerTest;\n\nvar call_count: i32 = 0;\nfn ReturnFalse() -> bool {\n  call_count = call_count + 1;\n  return false;\n}\n\nfn Main() -> i32 {\n  var result: bool = ReturnFalse() or ReturnFalse();\n  return if not result then call_count else -1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/9909b29e2f33447fa30b3b261cc7c672740e1236",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  if (0 == 1) {\n    return 1;\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/9a3f71755e720ffdafd5d7112321c8796d46fc62",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn identFn( x: i32 ) -> i32{\n    return x;\n}\n\nfn Main() -> i32 {\n  var x : i32 = 7 % 2;\n\n\n  if(  x != 1){\n      return 1;\n  }\n  x = (3*3) % 3;\n  if( x != 0){\n      return 2;\n  }\n\n  x = (4+4+4+4) % (2+1);\n  if(  x != 1){\n      return 3;\n  }\n\n  x = 15 % (identFn(2)+1);\n  if( x != 0){\n      return 4;\n  }\n\n  x = -15 % 7;\n  if( x != -1){\n      return 5;\n  }\n\n  x = 15 % -7;\n  if(  x != 1){\n      return 6;\n  }\n\n  x = -15 % -identFn(7);\n  if( x != -1){\n      return 7;\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/9af28460c915ac87c79b91ff233959dc031cf3cc",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Id(t: type) -> auto { return t; }\n\n// Test non-trivial type expression in parameter type.\n\nfn f(x: Id(i32)) -> i32 {\n  return x;\n}\n\nfn Main() -> i32 {\n  return f(0);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/9bfc6a4a473aa74403e38910c8843a87cbee0dd9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 6\n// CHECK:STDOUT: 5\n// CHECK:STDOUT: 6\n// CHECK:STDOUT: 5\n// CHECK:STDOUT: 6\n// CHECK:STDOUT: 5\n// CHECK:STDOUT: 6\n// CHECK:STDOUT: 5\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as Inc {\n  fn Op[addr self: Self*]() { ++self->n; }\n}\nimpl A as Dec {\n  fn Op[addr self: Self*]() { --self->n; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 5};\n  ++a.n;\n  Print(\"{0}\", a.n);\n  --a.n;\n  Print(\"{0}\", a.n);\n  ++a;\n  Print(\"{0}\", a.n);\n  --a;\n  Print(\"{0}\", a.n);\n  a.n.(Inc.Op)();\n  Print(\"{0}\", a.n);\n  a.n.(Dec.Op)();\n  Print(\"{0}\", a.n);\n  a.(Inc.Op)();\n  Print(\"{0}\", a.n);\n  a.(Dec.Op)();\n  Print(\"{0}\", a.n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/9cadde2867b9fe7867d7d217139982632f640cc0",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface FrobWith(T:! type) {}\n\nfn F[T:! FrobWith(.Self),\n     // CHECK:STDERR: COMPILATION ERROR: fail_dot_self_after_scope_2.carbon:[[@LINE+1]]: `.Self` used in type of non-type generic binding `U`\n     U:! .Self]() {\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/9f27297beea402d07125cf1bb0c7081ceb401bb5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: bool: 1\n// CHECK:STDOUT: bool: 1\n// CHECK:STDOUT: bool: 1\n// CHECK:STDOUT: bool: 1\n// CHECK:STDOUT: bool: 1\n// CHECK:STDOUT: bool: 1\n// CHECK:STDOUT: bool: 1\n// CHECK:STDOUT: bool: 1\n// CHECK:STDOUT: string: 1\n// CHECK:STDOUT: string: 1\n// CHECK:STDOUT: string: 1\n// CHECK:STDOUT: string: 1\n// CHECK:STDOUT: string: 1\n// CHECK:STDOUT: string: 1\n// CHECK:STDOUT: string: 1\n// CHECK:STDOUT: string: 1\n// CHECK:STDOUT: int: 1\n// CHECK:STDOUT: int: 1\n// CHECK:STDOUT: int: 1\n// CHECK:STDOUT: int: 1\n// CHECK:STDOUT: int: 1\n// CHECK:STDOUT: int: 1\n// CHECK:STDOUT: int: 1\n// CHECK:STDOUT: int: 1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn CompareEqualValues[T:! EqWith(.Self)](format: String, a: T, b: T) {\n  Print(format, if a == b then 1 else 0);\n  Print(format, if a != b then 0 else 1);\n}\n\nfn CompareDifferentValues[U:! EqWith(.Self)](format: String, a: U, b: U) {\n  Print(format, if a == b then 0 else 1);\n  Print(format, if a != b then 1 else 0);\n}\n\nfn CompareAll[V:! EqWith(.Self)](format: String, a: V, b: V) {\n  CompareEqualValues(format, a, a);\n  CompareEqualValues(format, b, b);\n  CompareDifferentValues(format, a, b);\n  CompareDifferentValues(format, b, a);\n}\n\nfn Main() -> i32 {\n  CompareAll(\"bool: {0}\", false, true);\n  CompareAll(\"string: {0}\", \"hello\", \"world\");\n  CompareAll(\"int: {0}\", 1, 2);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a01f53c98465a54636523de8f520a4a20bdd1403",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Hallo Welt\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32{\n  var x: Optional(String) = Optional(String).Create( \"Hallo Welt\" );\n  if(x.HasValue()){\n    Print(x.Get());\n    return 0;\n  }\n  return -1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a091cfa270edff9d7192eeb8f594ea77b09bba3d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface AddMul {\n  fn Add[self: Self](o: Self) -> Self;\n  fn Mul[self: Self](o: Self) -> Self;\n}\n\nimpl i32 as AddMul {\n  fn Add[self: i32](o: i32) -> i32 {\n    return self + o;\n  }\n  fn Mul[self: i32](o: i32) -> i32 {\n    return self * o;\n  }\n}\n\nclass Holder(T:! AddMul) {\n  var v: T;\n}\n\ninterface Vector(Scalar:! AddMul) {\n  fn Zero() -> Self;\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: Scalar) -> Self;\n  fn Hold[self: Self](v: Scalar) -> Holder(Scalar);\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  extend impl as Vector(i32) {\n    fn Zero() -> Point {\n      return {.x = 0, .y = 0};\n    }\n    fn Add[self: Point](b: Point) -> Point {\n      return {.x = self.x + b.x, .y = self.y + b.y};\n    }\n    fn Scale[self: Point](v: i32) -> Point {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n    fn Hold[self: Point](v: i32) -> Holder(i32) {\n      return {.v = v};\n    }\n  }\n}\n\nfn AddAndScaleGeneric[T:! AddMul, U:! Vector(T)](a: U, s: T) -> U {\n  return a.Add(U.Zero()).Scale(a.Hold(s).v);\n}\n\nfn Main() -> i32 {\n  var a: Point = {.x = 2, .y = 1};\n  var p: Point = AddAndScaleGeneric(a, 5);\n  return p.x - 10;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a0c798f9f52432ff1f72f8aa1ba9f7830a105f09",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 0: Heap{}\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  heap.PrintAllocs();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a13c6779bdbc457a609f9667267beed711896f6f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn CompareStr(s: String) -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_raw_more_hash_tags_on_left.carbon:[[@LINE+2]]: missing closing quote in single-line string: ##\"str\"#) {\n  // CHECK:STDERR:\n  if (s == ##\"str\"#) {\n    return 0;\n  }\n  return 1;\n}\n\nfn Main() -> i32 {\n  return CompareStr(\"str\");\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a1786976927e1d3184a978427bc5bb1cfa7aefa4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn CompareStr(s: String) -> i32 {\n  if (s == \"str\\n\") {\n    return 0;\n  }\n  return 1;\n}\n\nfn Main() -> i32 {\n  return CompareStr(\"str\\n\");\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a1bba96a1c0e17301f64b08c70a3df48170bd730",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nclass A {\n  var n: i32;\n}\nimpl i32 as ImplicitAs(A) {\n  fn Convert[self: Self]() -> A { return {.n = self }; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 0};\n  a = 1;\n  return a.n;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a1f193dcf4589332a9130b6551c1afa7fe79656a",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var (x: i32, y: i32);\n  // CHECK:STDERR: COMPILATION ERROR: fail_while_cond.carbon:[[@LINE+1]]: use of uninitialized variable x\n  while (x == 0) {\n    y = 1;\n  }\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a2cfb003a0e59b4e421af3880c551363b8ff78f0",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Struct OK\n// CHECK:STDOUT: Choice OK\n// CHECK:STDOUT: Class OK\n// CHECK:STDOUT: Interface OK\n// CHECK:STDOUT: Constraint OK\n// CHECK:STDOUT: result: 0\n\npackage Foo;\n\nchoice Choice { Alternative() }\nclass Class { fn F(n: i32) -> i32 { return n + 1; } }\ninterface Interface { fn G[self: Self]() -> Self; }\ninterface AnotherInterface {}\n\nimpl i32 as Interface { fn G[self: i32]() -> i32 { return self + 1; } }\nimpl i32 as AnotherInterface {}\n\n// TODO: These are intended to be called at compile time. Mark them as\n// constexpr once we have syntax for that.\nfn GetStruct() -> type { return {.n: i32}; }\nfn GetChoice() -> type { return Choice; }\nfn GetClass() -> type { return Class; }\nfn GetInterface() -> type { return Interface; }\nfn GetConstraint() -> type { return Interface & AnotherInterface; }\n\nfn TestStruct() {\n  var s: GetStruct() = {.n = 1};\n  if (s.(GetStruct().n) == 1) {\n    Print(\"Struct OK\");\n  }\n}\n\nfn TestChoice() {\n  var c: GetChoice() = GetChoice().Alternative();\n  match (c) {\n    case GetChoice().Alternative() => {\n      Print(\"Choice OK\");\n    }\n  }\n}\n\nfn TestClass() {\n  if (GetClass().F(1) == 2) {\n    Print(\"Class OK\");\n  }\n}\n\nfn TestInterface() {\n  var n: i32 = 1;\n  if (n.(GetInterface().G)() == 2) {\n    Print(\"Interface OK\");\n  }\n}\n\nfn TestConstraint() {\n  var n: i32 = 1;\n  if (n.(GetConstraint().G)() == 2) {\n    Print(\"Constraint OK\");\n  }\n}\n\nfn Main() -> i32 {\n  TestStruct();\n  TestChoice();\n  TestClass();\n  TestInterface();\n  TestConstraint();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a2de12dcf9c2df7a3ac23b82f802b3d076e6ad86",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// CHECK:STDERR: COMPILATION ERROR: fail_not_type.carbon:[[@LINE+1]]: type error in type expression: 'i32' is not implicitly convertible to 'type'\nfn F[a:! 42]();\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a3cfd48c1f4a33aad9d1552ddbe46d44a2436384",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// The bodies of member functions are processed after all immediately enclosing\n// classes, impl declarations, and interfaces.\nclass A {\n  fn F() -> type {\n    return i32;\n  }\n  // OK, resolves to `A.F`.\n  fn G() -> F() {\n    return 0;\n  }\n\n  // CHECK:STDERR: COMPILATION ERROR: fail_class_fn_use_before_declaration.carbon:[[@LINE+1]]: 'I' has not been declared yet\n  fn H() -> I() {\n    return 0;\n  }\n  fn I() -> type {\n    return i32;\n  }\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a6bf2f116b1e98f7546e9bce3b9d2946d8074aa2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_newline.carbon:[[@LINE+2]]: missing closing quote in single-line string: \"new\n  // CHECK:STDERR:\n  Print(\"new\nline\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a780174f6f7b59148dbb023be4e3659a92541020",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 0: Heap{}, 1: C{}\n// CHECK:STDOUT: Bind from c value expression\n// CHECK:STDOUT: Binding scope end\n// CHECK:STDOUT: c destroyed\n// CHECK:STDOUT: 0: Heap{}, 1: C{}, 2: !!C{}\n// CHECK:STDOUT: c destroyed\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass C {\n  destructor[self: Self] {\n    Print(\"c destroyed\");\n  }\n}\n\nfn CallWithReferenceExpressionBinding(var c: C) {\n  Print(\"Binding scope end\");\n}\n\nfn Main() -> i32 {\n  let c_let: C = {};\n  heap.PrintAllocs();\n\n  Print(\"Bind from c value expression\");\n  CallWithReferenceExpressionBinding(c_let);\n  heap.PrintAllocs();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a8a90bb993589759a112cf567143c47be5a89ac4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: [i32;] = (0, 1);\n  var index: i32 = 1;\n  x[index] = 0;\n  return x[0] + x[1];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a8a999063a872e7de8a55734e0f4a198efeeaafb",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: 2\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: 4\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: 2\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: 4\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass ListElement{\n  fn Create(value: i32)->ListElement{\n    return {\n      .element = Optional(i32).Create(value),\n      .next = Optional(ListElement*).CreateEmpty()\n    };\n  }\n\n  fn set[addr self: Self*] (value: Optional(ListElement*)){\n    (*self).next = value;\n  }\n\n  var element: Optional(i32);\n  var next: Optional(ListElement*);\n}\n\nclass List{\n  fn Create() -> List{\n    return {.next = Optional(ListElement*).CreateEmpty() };\n  }\n  fn insert[addr self: Self*] (value: i32){\n    if( not (*self).next.HasValue() ){\n      (*self).next = Optional(ListElement*).Create( heap.New(ListElement.Create(value)) );\n      return;\n    }\n    var iter: Optional(ListElement*) = (*self).next;\n    var node: auto = (iter.Get());\n    while((*node).next.HasValue()){\n      iter = (*node).next;\n      node = (iter.Get());\n    }\n    var v : ListElement* = iter.Get();\n    var x: Optional(ListElement*) = Optional(ListElement*).Create( heap.New(ListElement.Create(value) ));\n    (*v).set(x);\n  }\n\n  fn print[self: Self] (){\n    var iter: Optional(ListElement*) = self.next;\n    while(iter.HasValue()){\n      var node: auto = *(iter.Get());\n      Print(\"{0}\",node.element.Get());\n      var node_ptr: auto = iter.Get();\n      iter = node.next;\n    }\n  }\n\n  fn clean[addr self: Self*] (){\n    var head: auto = (*self).next;\n    while(head.HasValue()){\n      var tmp: auto = head;\n      head = (*head.Get()).next;\n      heap.Delete(tmp.Get());\n    }\n    (*self).next= Optional(ListElement*).CreateEmpty();\n  }\n\n  var next: Optional(ListElement*);\n}\n\nfn Main() -> i32{\n  var list: List = List.Create();\n  list.insert(1);\n  list.insert(2);\n  list.insert(3);\n  list.insert(4);\n  list.print();\n  list.clean();\n  list.print();\n  list.insert(1);\n  list.insert(2);\n  list.insert(3);\n  list.insert(4);\n  list.print();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a93b46ffd68cc67330744e0ed1099a14bdb56b47",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: 2\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: 4\n// CHECK:STDOUT: 4\n// CHECK:STDOUT: 6\n// CHECK:STDOUT: 5\n// CHECK:STDOUT: 6\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A(T:! type, U:! type) {}\ninterface B(T:! type, U:! type) { fn F(); }\n\nimpl forall [T:! type] A(T, i32) as B(i32, i32) {\n  fn F() { Print(\"1\"); }\n}\nimpl forall [T:! type] A(i32, T) as B(i32, i32) {\n  fn F() { Print(\"2\"); }\n}\n// Intentionally out of order so that explorer can't get the right answer by\n// chance, by just picking the first or last matching impl.\nimpl forall [T:! type] A(i32, i32) as B(i32, T) {\n  fn F() { Print(\"4\"); }\n}\nimpl forall [T:! type] A(i32, i32) as B(T, i32) {\n  fn F() { Print(\"3\"); }\n}\n\nimpl forall [T:! type, U:! type] A(T, i32*) as B(i32*, U) {\n  fn F() { Print(\"5\"); }\n}\nimpl forall [T:! type, U:! type] A(i32*, T) as B(U, i32*) {\n  fn F() { Print(\"6\"); }\n}\n\nfn Main() -> i32 {\n  A((), i32).(B(i32, i32).F)();\n  A(i32, ()).(B(i32, i32).F)();\n  A(i32, i32).(B((), i32).F)();\n  A(i32, i32).(B(i32, ()).F)();\n\n  A(i32, i32).(B(i32, i32).F)();\n\n  A(i32*, i32*).(B(i32, i32*).F)();\n  A(i32*, i32*).(B(i32*, i32).F)();\n  A(i32*, i32*).(B(i32*, i32*).F)();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/a9c4f7786b6b8ba23fa102e8ba2296752120ae84",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage Foo;\ninterface A {\n  fn F[self: Self](o: Self) -> Self;\n}\nclass X {\n  extend impl as A {\n    fn F[self: Self](o: Self) -> Self { return {.n = self.n + o.n}; }\n  }\n  var n: i32;\n}\nfn F[T:! A](v: T, w: T) -> T {\n  return v.(T.(A.F))(w);\n}\nfn Main() -> i32 {\n  var v: X = {.n = 1};\n  var w: X = {.n = 2};\n  return F(v, w).n;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ab1d10a814f9068e09642a678671d76511342dd4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A {\n  class B {}\n  alias C = B;\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ab97f0b738451b9e490d7cadaacc8081ae676240",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: A(T) as B(i32)\n// CHECK:STDOUT: A(T) as B(U)\n// CHECK:STDOUT: A(i32) as B(T)\n// CHECK:STDOUT: A(i32) as B(T)\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A(T:! type) {}\ninterface B(T:! type) {\n  fn F();\n}\n\nimpl forall [T:! type] A(T) as B(i32) {\n  fn F() { Print(\"A(T) as B(i32)\"); }\n}\nimpl forall [T:! type] A(i32) as B(T) {\n  fn F() { Print(\"A(i32) as B(T)\"); }\n}\nimpl forall [T:! type, U:! type] A(T) as B(U) {\n  fn F() { Print(\"A(T) as B(U)\"); }\n}\n\nfn F[T:! B(i32)](x: T) {\n  T.F();\n}\nfn G[T:! B(bool)](x: T) {\n  T.F();\n}\n\nfn Main() -> i32 {\n  let a: A(bool) = {};\n  let b: A(i32) = {};\n  F(a);\n  G(a);\n  F(b);\n  G(b);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ac4a09688df096b7967d347059fe514b011a0c5e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 5\n\npackage ExplorerTest;\n\ninterface HasTypeAndValue {\n  let T:! type;\n  let V:! T;\n}\n\nfn F(X:! HasTypeAndValue where .T = i32 and .V = 5) -> i32 { return X.V; }\n\nimpl i32 as HasTypeAndValue where .T = i32 and .V = 5 {}\n\nfn Main() -> i32 {\n  return F(i32);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ad153a95127f656da230d82cdba152a50f871556",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Vector {\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: i32) -> Self;\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  extend impl as Vector {\n    fn Add[self: Point](b: Point) -> Point {\n      return {.x = self.x + b.x, .y = self.y + b.y};\n    }\n    fn Scale[self: Point](v: i32) -> Point {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n  }\n}\n\nfn AddAndScaleGeneric[T:! Vector](t: (T, T), s: i32) -> T {\n  var m: auto = t[0].Add;\n  var n: auto = m(t[1]).Scale;\n  return n(s);\n}\n\nfn Main() -> i32 {\n  var a: Point = {.x = 1, .y = 1};\n  var b: Point = {.x = 2, .y = 3};\n  var p: Point = AddAndScaleGeneric((a, b), 5);\n  return p.x - 15;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/aedf34fefa255ebc431491de0b68156a724221ae",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Carrot.G\n// CHECK:STDOUT: result: 5\n\npackage ExplorerTest;\n\ninterface Apple(T:! type) {\n  fn F[self: Self]() -> T;\n}\n\ninterface Banana {\n  require Self impls Apple(i32);\n  fn G[self: Self]();\n}\n\nclass Carrot {\n  var n: i32;\n}\n\nimpl Carrot as Apple(i32) {\n  fn F[self: Self]() -> i32 { return self.n; }\n}\n\nimpl Carrot as Banana {\n  fn G[self: Self]() { Print(\"Carrot.G\"); }\n}\n\nfn H[T:! Banana](x: T) -> i32 {\n  x.G();\n  return x.(Apple(i32).F)();\n}\n\nfn Main() -> i32 {\n  var c: Carrot = {.n = 5};\n  return H(c);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/afd20d50d83e001bbd7f6db02ca1e2e0a6d1f309",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// Demonstrate the aliasing behavior of pointers.\n\nfn Main() -> i32 {\n  var p: i32* = heap.New(5);\n  var q: i32* = p;\n  *q = 0;\n  return *p;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b08132223d41827e2b8cd8f849ffb7ac4af4e993",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 20\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var ar: array(i32, 4) = (0, 1,2,3);\n   var count : i32 = 0;\n   for( x: i32 in ar){\n       count = count +1;\n        for( x: i32 in ar){\n            count = count +1;\n        }\n   }\n   return count;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b0a0c7b28dfac0b65bba3cf74ebd1100adf7c0b7",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 4213\n\npackage ExplorerTest;\n\ninterface IntLike {\n  fn Convert[self: Self]() -> i32;\n}\nimpl i32 as IntLike {\n  fn Convert[self: i32]() -> i32 { return self; }\n}\n\nfn add[T:! IntLike](x: {.a: T, .b: ({.m: i32, .n: T}, i32)}) -> i32 {\n  return 1000 * x.a.Convert() + 100 * x.b[0].m + 10 * x.b[0].n.Convert() + x.b[1];\n}\n\nfn Main() -> i32 {\n  return add({.b = ({.n = 1, .m = 2}, 3), .a = 4});\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b0e276497e7036c6b3c90deeff71a055256ed5e3",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n\nfn Main() -> i32 {\n  var ar: array(i32, 0) = () ;\n  var count : i32 = 0;\n  for( x: i32 in ar ){\n      count = 2;\n  }\n  return count;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b1f68671cb99a64e7c35d8453fd1f13759823e49",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: RUNTIME ERROR: fail_overflow_div.carbon:[[@LINE+1]]: integer overflow\n  var a: auto = (-2147483647 -1) /-1;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b3738109fea51776656084b4904eb6161501f39e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_hex_lower.carbon:[[@LINE+1]]: Invalid escaping in string: \"str\\xaa\"\n  Print(\"str\\xaa\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b39d93d15f5f9693f621391de119e616687fbfa3",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  Assert(true, \"HALLO WELT\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b3e6b065765987b63bb992656e202cd2753d579d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn F[T:! type & type](x: T) {}\n\nfn Main() -> i32 {\n  F(0);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b46338342e410d950a63cae90807b22ad2674468",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var t2: {.x: i32, .y: i32} = {.x = 2, .y = 5};\n  t2.y = 3;\n  // 3 - 2 - 1\n  return t2.y - t2.x - 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b4a3cec4308215fd5e3c772c7f3ce019c9c5b026",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: Integer overflow\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var a: auto = 5 >> 75;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b4e1923164eed688e64d926007d332b4d9a7bafb",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn F() -> () {\n  return ();\n}\n\nfn Main() -> i32 {\n  F();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b5025c7140bdccbefb9823d5906815f7aea5f555",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 75\n// CHECK:STDOUT: 100\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Vector {\n  fn Zero() -> Self;\n  fn Add[addr self: Self*](b: Self);\n  fn Scale[addr self: Self*](v: i32);\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  extend impl as Vector {\n    fn Zero() -> Self {\n      return {.x = 1, .y = 1};\n    }\n    fn Add[addr self: Self*](b: Self) {\n      (*self).x = (*self).x + b.x;\n      (*self).y = (*self).y + b.y;\n    }\n    fn Scale[addr self: Self*](v: i32) {\n      (*self).x = (*self).x * v;\n      (*self).y = (*self).y * v;\n    }\n  }\n}\n\nfn AddAndScaleGeneric[T:! Vector](p: T*, s: i32) {\n  (*p).Add(T.Zero());\n  (*p).(Vector.Scale)(s);\n  (*p).(T.(Vector.Scale))(s);\n}\n\nfn Main() -> i32 {\n  var a: Point = {.x = 2, .y = 3};\n  AddAndScaleGeneric(&a, 5);\n  Print(\"{0}\", a.x);\n  Print(\"{0}\", a.y);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b585c712c89adab1146766f73010d48b0a9d9de5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDERR: RUNTIME ERROR: {{.*}}/explorer/data/prelude.carbon:{{.*}}: \"Attempted to unwrap empty Optional\"\n\npackage ExplorerTest;\n\nfn Main() -> i32{\n  var x: Optional(i32) = Optional(i32).CreateEmpty();\n  return x.Get();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b6b53ceb779903ab3b483786d48390423bbbe797",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass C {}\n\n// CHECK:STDERR: COMPILATION ERROR: fail_combine_rhs.carbon:[[@LINE+1]]: expected a constraint in second operand of `&`, found class C\nfn F[T:! type & C]();\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b8695514d6502d5b1b9e09cc61711898dbe1e486",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\ninterface HasAssoc {\n  let Assoc:! type;\n}\nclass X {\n  impl as HasAssoc where .Assoc = i32 {}\n}\n\nfn H[T:! HasAssoc where .Assoc = i32, U:! type where .Self == i32](a: T, b: U) -> i32 {\n  var a: T.((HasAssoc where .Assoc = U).Assoc) = 3;\n  return a;\n}\n\nfn Main() -> i32 {\n  var x: X = {};\n  var y: i32 = 0;\n  return H(x, y);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/b9d290495c4dce17305b5d9d29e2ae54c6242b54",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Class 1\n// CHECK:STDOUT: Class 2\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class C {\n  fn BasePrint(v: i32) {\n    Print(\"Class {0}\", v);\n  }\n  fn Method1[self: Self]() {\n    self.BasePrint(self.value_c);\n  }\n\n  var value_c: i32;\n}\n\nclass D {\n  extend base: C;\n  fn Method2[self: Self]() {\n    self.BasePrint(self.value_d);\n  }\n\n  var value_d: i32;\n}\n\nfn Main() -> i32 {\n  var d: D = {.base = {.value_c = 1}, .value_d = 2};\n  d.Method1();\n  d.Method2();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ba4fa6565defd5cc4b8921ed0d478be330350658",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass Point(T:! type) {\n  var x: T;\n  var y: T;\n}\n\nfn Main() -> i32 {\n  var p: Point(i32) = {.x = 0, .y = 0};\n  // CHECK:STDERR: COMPILATION ERROR: fail_point_equal.carbon:[[@LINE+1]]: type error in initializer of variable: 'class Point(T = i32)' is not implicitly convertible to 'class Point(T = bool)'\n  var q: Point(bool) = p;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ba5b59911968d39433b9003d02e3ff4fa7b4b177",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_tab.carbon:[[@LINE+1]]: Invalid escaping in string: \"new\tline\"\n  Print(\"new\tline\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/bab137edbdcbcf1220dc018b55d49066378523e9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// This declaration is not allowed.\n// CHECK:STDERR: COMPILATION ERROR: fail_separate_decl.carbon:[[@LINE+1]]: Function declaration has deduced return type but no body\nfn ComputeSum(x: i32, y: i32) -> auto;\n\nfn Main() -> i32 {\n  return ComputeSum(1, 2) - 3;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/bb0ee9a7c7f604c41cfef744a974c6603df4b0db",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: array(i32, 2) = (0, 1);\n  // CHECK:STDERR: RUNTIME ERROR: fail_index.carbon:[[@LINE+1]]: index 2 out of range in (0, 1)\n  return x[2];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/bc8de3dd156c3193c1a5209c7023499abe9bbdde",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: (*c1).val: 1\n// CHECK:STDOUT: (*c2).val: 1\n// CHECK:STDOUT: (*d).val: 2\n// CHECK:STDOUT: e.val: 3\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class C {\n  var val: i32;\n}\n\nbase class D {\n  extend base: C;\n  var val: i32;\n}\n\nclass E {\n  extend base: D;\n  var val: i32;\n}\n\nfn Foo(c: C*) -> i32 {\n  return (*c).val;\n}\n\nfn Main() -> i32 {\n  var e: E = { .val = 3, .base = {.val = 2,.base = {.val = 1}}};\n  var d: D* = &e;\n  var c1: C* = &e;\n  var c2: C* = d;\n  Print(\"(*c1).val: {0}\", (*c1).val);\n  Print(\"(*c2).val: {0}\", (*c2).val);\n  Print(\"(*d).val: {0}\", (*d).val);\n  Print(\"e.val: {0}\", e.val);\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/bd4d126e58ef4f15642eeba1d41a830e217a4ad1",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_length_mismatch_with_auto.carbon:[[@LINE+1]]: tuples of different length\n  var a: (auto,) = (1, 2);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/bd5f439085bdf3ab0cbe796b3637cf9139fb1914",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 12345\n\npackage ExplorerTest;\n\nclass Class { var a: i32; }\nclass GenericClass(T:! type) { var a: T; }\ninterface Interface { fn Make() -> Self; }\ninterface GenericInterface(T:! type) { fn Make() -> (Self, T); }\n\nalias ClassAlias = Class;\nalias GenericClassAlias = GenericClass;\nalias ClassSpecializationAlias = GenericClassAlias(i32);\nalias InterfaceAlias = Interface;\nalias GenericInterfaceAlias = GenericInterface;\nalias InterfaceSpecializationAlias = GenericInterfaceAlias(i32);\n\nimpl ClassAlias as InterfaceAlias {\n  fn Make() -> Self { return {.a = 1}; }\n}\nimpl ClassSpecializationAlias as InterfaceSpecializationAlias {\n  fn Make() -> (Self, i32) { return ({.a = 2}, 3); }\n}\nalias S = {.a: i32};\nimpl GenericClassAlias(S) as GenericInterfaceAlias(S) {\n  fn Make() -> (Self, {.a: i32}) { return ({.a = {.a = 4}}, {.a = 5}); }\n}\n\nfn CheckImplementsInterface[T:! Interface](x: T) -> T {\n  return T.Make();\n}\nfn CheckImplementsGenericInterface_i32\n    [T:! GenericInterface(i32)](x: T) -> (T, i32) {\n  return T.Make();\n}\nfn CheckImplementsGenericInterface_struct\n    [T:! GenericInterface(S)](x: T) -> (T, S) {\n  return T.Make();\n}\n\nfn Main() -> i32 {\n  var a: Class = {.a = 0};\n  a = CheckImplementsInterface(a);\n\n  var b: GenericClass(i32) = {.a = 0};\n  var (b2: GenericClass(i32), n: i32) =\n    CheckImplementsGenericInterface_i32(b);\n\n  var c: GenericClass({.a: i32}) = {.a = {.a = 0}};\n  var (c2: GenericClass({.a: i32}), s: S) =\n    CheckImplementsGenericInterface_struct(c);\n\n  return 10000 * a.a + 1000 * b2.a + 100 * n + 10 * c2.a.a + s.a;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/bee65bde4d7da5558b60a5dacb8a5826486b1df2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface FrobWith(T:! type) {}\n\nfn F[T:! FrobWith(.Self)]\n  // CHECK:STDERR: COMPILATION ERROR: fail_dot_self_after_scope.carbon:[[@LINE+1]]: could not resolve '.Self'\n  (U: .Self) {\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/bff4337d7117fd0883b58ac02469d740648a8072",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 8\n// CHECK:STDOUT: 4\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  if (1 << 0 != 1) { return 1; }\n  if (1 << 3 != 8) { return 2; }\n  if (0 << 3 != 0) { return 3; }\n  if (3 << 1 != 6) { return 4; }\n  if (-1 << 2 != -4) { return 5; }\n  if (1 >> 0 != 1) { return 6; }\n  if (1 >> 1 != 0) { return 7; }\n  if (3 >> 1 != 1) { return 8; }\n  if (-1 >> 1 != -1) { return 9; }\n  if (-2 >> 1 != -1) { return 10; }\n\n  var n: i32 = 1;\n  n <<= 3;\n  Print(\"{0}\", n);\n  n >>= 1;\n  Print(\"{0}\", n);\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c07f23f6980fe961e62413e101aa21f1696e3e41",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Before: 1\n// CHECK:STDOUT: Interface: 2\n// CHECK:STDOUT: Op: 3\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass C {\n  var n: i32;\n}\n\nfn Main() -> i32 {\n  var c: C = {.n = 1};\n  Print(\"Before: {0}\", c.n);\n  c.(AssignWith({.n: i32}).Op)({.n = 2});\n  Print(\"Interface: {0}\", c.n);\n  c = {.n = 3};\n  Print(\"Op: {0}\", c.n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c294ac41a73adf8be9ed88cbc20458d7fad20f68",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface HasTypes {\n  let A:! type;\n  let B:! type;\n  let C:! type;\n  let D:! type;\n  let E:! type;\n  let F:! type;\n}\n\ninterface HasParams(A:! type, B:! type, C:! type, D:! type) {\n  let V:! HasTypes;\n}\n\n// Here we discover that there is a rewrite for `HasParams(...).V` only after\n// substitution converts each one to `HasParam(X, X, X, X).V`.\nfn F[X:! (HasTypes & HasParams(.Self, .Self, .Self, .Self)) where\n       .Self impls HasParams(.A, .A, .A, .A) and\n       .Self impls HasParams(.B, .B, .B, .B) and\n       .Self impls HasParams(.C, .C, .C, .C) and\n       .Self impls HasParams(.D, .D, .D, .D) and\n       .Self impls HasParams(.E, .E, .E, .E) and\n       .F = .Self.(HasParams(.E, .E, .E, .E).V).A and\n       .E = .Self.(HasParams(.D, .D, .D, .D).V).A and\n       .D = .Self.(HasParams(.C, .C, .C, .C).V).A and\n       .C = .Self.(HasParams(.B, .B, .B, .B).V).A and\n       .B = .Self.(HasParams(.A, .A, .A, .A).V).A and\n       .A = .Self and .V = .Self](x: X) -> X.F { return x; }\n\nimpl i32 as HasTypes\n  where .A = .B and .B = .C and .C = .D and .D = .E and .E = .F and .F = i32 {}\nimpl i32 as HasParams(i32, i32, i32, i32) where .V = i32 {}\n\nfn Main() -> i32 {\n  return F(0);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c2efeeb24454e0da713af7391d28f6b1f1820d6c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 122\n\npackage ExplorerTest;\n\ninterface A { fn F() -> i32; }\ninterface B { fn F() -> i32; }\n\nimpl i32 as A { fn F() -> i32 { return 1; } }\nimpl i32 as B { fn F() -> i32 { return 2; } }\n\nfn GetAB(T:! B where .Self impls A) -> i32 {\n  return 100 * T.(A.F)() + 10 * T.(B.F)() + T.F();\n}\n\nfn Main() -> i32 {\n  return GetAB(i32);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c3c888581796e961aed506d812407f76c99c1659",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass C {\n  // CHECK:STDERR: COMPILATION ERROR: fail_circular_inheritance.carbon:[[@LINE+4]]: could not find `class C {\n  // CHECK:STDERR: extend base: C;\n  // CHECK:STDERR: }\n  // CHECK:STDERR: `\n  extend base: C;\n}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c42ace6ddd8e547dced2e0ed23181b826788913d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var p: {.x: i32, .y: i32};\n  // CHECK:STDERR: COMPILATION ERROR: fail_struct_member_access.carbon:[[@LINE+1]]: use of uninitialized variable p\n  p.x = p.y;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c4d643c7e8081d02c8467600200be7be29d58d8d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\nclass TypeLike {\n  extend impl as ImplicitAs(type) {\n    fn Convert[self: Self]() -> type { return i32; }\n  }\n  fn Make() -> Self { return {}; }\n}\n\nfn Main() -> TypeLike.Make() {\n  var x: {.a: TypeLike.Make(), .b: TypeLike.Make()} = {.a = 1, .b = 2};\n  return x.a + x.b;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c5cd5cb2197a889e003767ff5c0de2040094ac96",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface Iface {\n  let N:! i32;\n}\n\nfn F(T:! Iface where .N == 5) {}\n\nclass Good {}\nclass Bad {}\nimpl Good as Iface where .N = 5 {}\nimpl Bad as Iface where .N = 4 {}\n\nfn Main() -> i32 {\n  F(Good);\n  // CHECK:STDERR: COMPILATION ERROR: fail_different_value.carbon:[[@LINE+1]]: constraint requires that (T).(Iface.N) (with value 4) == 5, which is not known to be true\n  F(Bad);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c5ec8aaab0717d6b901c8bc42757700a342aaf32",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface Iface {\n  let T:! type;\n  // CHECK:STDERR: COMPILATION ERROR: fail_redefined.carbon:[[@LINE+1]]: Duplicate name `T` also found at fail_redefined.carbon:[[@LINE-1]]\n  let T:! type;\n}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c6812fb07715a0206afeac4ac2275784a158cf63",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn CompareBools(a: bool, b: bool) -> bool {\n  // CHECK:STDERR: SYNTAX ERROR: fail_compare_precedence.carbon:[[@LINE+1]]: syntax error, unexpected EQUAL_EQUAL, expecting SEMICOLON\n  return not a == b;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c855a3994277ba5408dbbadaa49d92b52f2467d2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Vector {\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: i32) -> Self;\n}\n\nclass Point1 {\n  var x: i32;\n  var y: i32;\n  extend impl as Vector {\n    fn Add[self: Point1](b: Point1) -> Point1 {\n      return {.x = self.x + b.x, .y = self.y + b.y};\n    }\n    fn Scale[self: Point1](v: i32) -> Point1 {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n  }\n}\n\nclass Point2 {\n  var x: i32;\n  var y: i32;\n  extend impl as Vector {\n    fn Add[self: Point2](b: Point2) -> Point2 {\n      return {.x = self.x + b.x + 1, .y = self.y + b.y + 1};\n    }\n    fn Scale[self: Point2](v: i32) -> Point2 {\n      return {.x = self.x * v * 2, .y = self.y * v * 2};\n    }\n  }\n}\n\nfn ScaleGeneric[U:! Vector](c: U, s: i32) -> U {\n  return c.Scale(s);\n}\n\nfn AddAndScaleGeneric[T:! Vector, V:! Vector](a: T, b: V, s: i32) -> (T, V) {\n  return (ScaleGeneric(a.Add(a), s),\n  \t  ScaleGeneric(b.Add(b), s));\n}\n\nfn Main() -> i32 {\n  var a: Point1 = {.x = 1, .y = 1};\n  var b: Point2 = {.x = 2, .y = 3};\n  var (p: Point1, q: Point2) = AddAndScaleGeneric(a, b, 5);\n  return q.x - p.x - 40;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c86a4df5e4046b6cffb57a8563514e8ea459147a",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var a: i32 = 1;\n  let a_pinned: i32 = a;\n  let a_pinned2: i32 = a;\n  // OK: Value unused after being mutated.\n  a = 2;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/c8c23b0c0d7655f81ac96fdb089bcb7a82c25950",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var t1: {.x: i32,} = {.x = 5,};\n  var t2: {.x: i32, .y: i32} = {.x = 2, .y = 3,};\n  return t1.x - t2.x - t2.y;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ca5382377576c400f270660fcce6472e8664deb9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn CompareStr(s: String) -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_raw_block_single_line.carbon:[[@LINE+1]]: Invalid block string: Too few lines\n  if (s == #'''raw string literal starting with '''#) {\n    return 0;\n  }\n  return 1;\n}\n\nfn Main() -> i32 {\n  return CompareStr(\"\\\"\\\"raw string literal starting with \\\"\\\"\");\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ca69be54b8273f334ab8c7db0ad454c5ff0291c9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Vector(Scalar:! type) {\n  fn Zero() -> Self;\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: Scalar) -> Self;\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n  extend impl as Vector(i32) {\n    fn Zero() -> Point {\n      return {.x = 0, .y = 0};\n    }\n    fn Add[self: Point](b: Point) -> Point {\n      return {.x = self.x + b.x, .y = self.y + b.y};\n    }\n    fn Scale[self: Point](v: i32) -> Point {\n      return {.x = self.x * v, .y = self.y * v};\n    }\n  }\n}\n\nfn AddAndScaleGeneric[T:! type, U:! Vector(T)](a: U, s: T) -> U {\n  return a.Add(U.Zero()).Scale(s);\n}\n\nfn Main() -> i32 {\n  var a: Point = {.x = 2, .y = 1};\n  var p: Point = AddAndScaleGeneric(a, 5);\n  return p.x - 10;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/cb2c2e620fb2192d723bcecff7a8cadd41775362",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn f(x: i32) -> i32 {\n  return x - 1;\n}\n\nfn Main() -> i32 {\n  return f(1);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/cbd23efc1218cbf81ebdcb503cfeaaf6925c29d2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n\n  // Allowed: `Self` here means `Point`.\n  fn GetX[self: Self]() -> i32 {\n    return self.x;\n  }\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  return p.GetX();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/cbe88d560d36df81f2d7ae7910a44e6926d46f7e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 4\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: 2\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as SubWith(i32) where .Result = A {\n  fn Op[self: Self](rhs: i32) -> A { return {.n = self.n - rhs}; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 5};\n  a = a - 1;\n  Print(\"{0}\", a.n);\n  a -= 1;\n  Print(\"{0}\", a.n);\n  Print(\"{0}\", (a - 1).n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/cc055d77975b79cf9281d71e00182aaeef7ccf1b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  var x: i32;\n  var y: i32;\n}\n\nfn GetX(p: Point) -> i32 {\n  return p.x;\n}\n\nfn Main() -> i32 {\n  return GetX({.x = 1, .y = 2}) - 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/cc2d5a48c731ae4058d884411e7235b2ae4bf829",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn F() {}\nalias A = F;\n\n// CHECK:STDERR: COMPILATION ERROR: fail_wrong_fn_alias_use.carbon:[[@LINE+1]]: alias A cannot be used as a name qualifier\nfn A.Foo() {}\n\nfn Main() -> i32 {\n    return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/cc774069d5739d66235983360e14f8740de6d975",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn BadSimpleMemberAccess[T:! type](a: T) -> T {\n  // CHECK:STDERR: COMPILATION ERROR: fail_field_access_on_generic.carbon:[[@LINE+1]]: member access in unconstrained type\n  return a.x;\n}\n\nfn Main() -> i32 {\n  return BadSimpleMemberAccess(0);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ccaf2f7ac19101566bddd7e0b4bcbb5434a38bf4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nconstraint X {\n  // CHECK:STDERR: COMPILATION ERROR: fail_associated_constant.carbon:[[@LINE+1]]: associated constant not permitted in named constraint\n  let N:! type;\n}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/cd940109a8870955e7eb8e03004304e9dc7fc808",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_invalid_integer_type.carbon:[[@LINE+1]]: Invalid type literal: i11111111111111111111111111\n  var x: i11111111111111111111111111 = 1;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/cded9327e7355942a46c8e25c8328275dbef50bf",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nfn snd[T:! type](x: i32, y: T) -> T {\n  return y;\n}\n\nfn Main() -> i32 {\n  return snd(0, 1);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ce2080f786cedebec8a0147b450b3a9a85365258",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var s: String = #'''\n    A block string literal\n    \\\n    '''#;\n  if (s == \"A block string literal\\n\\\\\\n\") {\n    return 0;\n  } else {\n    return 1;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/cff3eed86965820544d6454ed5d9cf0735a7bf48",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// CHECK:STDERR: COMPILATION ERROR: fail_fn_use_in_return_type.carbon:[[@LINE+1]]: 'F' is not usable until after it has been completely declared\nfn F() -> F() {\n  return type;\n}\n\nfn Main() -> i32 {\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d0d95941336a7a4ac3202f363708dbc685900f64",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var f: __Fn() -> Point = Point.Origin;\n  return f().x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d1ec799a11b9190d5a39b84e45558cba93c31fdd",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface I {}\nimpl i32 as I {}\n\nfn F(A:! i32, B:! i32, C:! i32, D:! i32, E:! i32,\n     T:! I where A == B and C == D and C == E and B == D) {\n  // CHECK:STDERR: COMPILATION ERROR: fail_combine_equality.carbon:[[@LINE+1]]: member access, F not in interface I where T impls interface I and A == B and C == D and C == E and B == D\n  T.F();\n}\n\nfn Main() -> i32 {\n  F(1, 1, 1, 1, 1, i32);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d2a4af5c22209dd1503f38d0a36d75e9b21a8bd4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass Point(T:! type) {\n  fn Create(x: T, y: T) -> Point(T) {\n    return {.x = x, .y = y};\n  }\n\n  var x: T;\n  var y: T;\n}\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_generic_class_arg.carbon:[[@LINE+1]]: wrong number of arguments in function call, expected 1 but got 2\n  var p: Point(i32) = Point(i32, i32).Create(0, 1);\n  return p.x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d3fc2d9df6573461a1ea20c7997f27dfd9f1ee8f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Cell(T:! type) {\n  fn Create(x: T) -> Cell(T) { return { .data = x }; }\n\n  fn Get[self: Self]() -> T {\n    return self.data;\n  }\n  fn Put[addr self: Self*](x: T) {\n    (*self).data = x;\n  }\n  fn CreateOther[self: Self, U:! type](x: U) -> Cell(U) {\n    return {.data = x};\n  }\n  var data: T;\n}\n\nclass Integer {\n  var int: i32;\n}\n\nfn Main() -> i32 {\n  var i: Integer = {.int = 1};\n  var c: Cell(Integer) = Cell(Integer).Create(i);\n  i = {.int = 0};\n  c.Put(i);\n  var j: Integer = c.Get();\n  var d: Cell(Integer) = c.CreateOther(j);\n  return c.data.int + d.data.int;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d533854f44af409027dfc8c1c288f90ebf111192",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var n: i32 = 0;\n  match (n) {\n    case 1 => { return 0; }\n  }\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d5a91fb15ac01afd500538b5679647289146045a",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface GetX {\n  fn DoIt[self: Self]() -> i32;\n}\n\nimpl forall [template T:! type] T as GetX {\n  // CHECK:STDERR: COMPILATION ERROR: fail_no_member.carbon:[[@LINE+1]]: member access, unexpected i32 in self.x\n  fn DoIt[self: Self]() -> i32 { return self.x; }\n}\n\nfn Main() -> i32 {\n  return 0.(GetX.DoIt)();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d5af10d2b47f3859bcc15da85fa3d077b942f43a",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: DESTRUCTOR A 1\n// CHECK:STDOUT: DESTRUCTOR B 2\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nclass A{\n    class B{\n        destructor[self: Self]{\n            Print(\"DESTRUCTOR B {0}\",self.n);\n        }\n        fn Create(x: i32) -> B{\n           return {.n = x };\n        }\n        var n: i32;\n    }\n\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR A {0}\",self.n);\n    }\n    fn Create(x: i32) -> A{\n        return {.n = x, .b = B.Create(2)};\n    }\n    var n: i32;\n    var b : B;\n}\n\nfn Main() -> i32 {\n  var a: A = A.Create(1);\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d5f20d0057317362bc92258e8c06f6b03c2926a4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Destructor A 3\n// CHECK:STDOUT: Destructor A 1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A {\n  var i: i32;\n  destructor[self: Self] {\n    Print(\"Destructor A {0}\", self.i);\n  }\n}\n\nfn Main() -> i32 {\n  var a0: A;\n  var a1: A = {.i = 1};\n  var a2: A;\n  var a3: A = {.i = 3};\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d60be9abac4bd2cb92b3432b7c10771def0c009e",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Hello world!\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var s: auto = \"Hello world!\";\n  Print(s);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d698884570f5265a3cd5ab0b822ed28fba467d13",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn f(x: i32) -> i32 {\n  if (x == 0) {\n    return x;\n  } else {\n    return f(x - 1);\n  }\n}\n\nfn Main() -> i32 {\n  return f(2);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d77e0fdacf1d3d9c711e24c8b088e2da26d98746",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 2\n\npackage ExplorerTest;\n\nvar call_count: i32 = 0;\nfn ReturnTrue() -> bool {\n  call_count = call_count + 1;\n  return true;\n}\n\nfn Main() -> i32 {\n  var result: bool = ReturnTrue() and ReturnTrue();\n  return if result then call_count else -1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d7de67b2375a361719d942f4cf49ea0a9cdf2c45",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nclass Point(T:! type, V:! T) {\n  fn Get[self: Self]() -> T {\n    return V;\n  }\n}\n\nfn F(p: Point(i32, 1)) -> i32 {\n  return p.Get();\n}\n\nfn Main() -> i32 {\n  var v: Point(i32, 1) = {};\n  return F(v);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d81e51e207bd2a4077a15890f337487a93060f7b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Foo(c1): 1\n// CHECK:STDOUT: Foo(c2): 1\n// CHECK:STDOUT: Foo(d): 1\n// CHECK:STDOUT: Foo(&e): 1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class C {\n  var val: i32;\n}\n\nbase class D {\n  extend base: C;\n  var val: i32;\n}\n\nclass E {\n  extend base: D;\n  var val: i32;\n}\n\nfn Foo(c: C*) -> i32 {\n  return (*c).val;\n}\n\nfn Main() -> i32 {\n  var e: E = { .val = 3, .base = {.val = 2,.base = {.val = 1}}};\n  var d: D* = &e;\n  var c1: C* = &e;\n  var c2: C* = d;\n\n  Print(\"Foo(c1): {0}\", Foo(c1));\n  Print(\"Foo(c2): {0}\", Foo(c2));\n  Print(\"Foo(d): {0}\", Foo(d));\n  Print(\"Foo(&e): {0}\", Foo(&e));\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d87e64cb8726f55d05773858cbe6979e550c0f5c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn CompareStr(s: String) -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_raw_more_hash_tags_on_right.carbon:[[@LINE+1]]: invalid character '\\x23' in source file.\n  if (s == \"str\"#) {\n    return 0;\n  }\n  return 1;\n}\n\nfn Main() -> i32 {\n  return CompareStr(\"str\");\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/d967a050c50d0b75e8f64611560b0f221bd9525f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: d.a=1\n// CHECK:STDOUT: d.b=2\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nabstract class C {\n  var a: i32;\n}\n\nclass D {\n  extend base: C;\n  var b: i32;\n}\n\nfn Main() -> i32 {\n  var d: D = { .base = {.a = 1}, .b = 2 };\n  Print(\"d.a={0}\", d.a);\n  Print(\"d.b={0}\", d.b);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/da795d40354dd38e3d00b82c7790eb4d6c8ec2b5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\nclass A(T:! type) {\n  var v: T;\n}\nfn F(T:! type, x: T) -> T {\n  var v: A(T) = {.v = x};\n  return v.v;\n}\nfn Main() -> i32 {\n  return F(i32, 1);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/db5937dfd7d8e43ea817fbcac0b83ad38ccae116",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Vector {\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: i32) -> Self;\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n}\n\nimpl Point as Vector {\n  fn Add[self: Point](b: Point) -> Point {\n    return {.x = self.x + b.x, .y = self.y + b.y};\n  }\n  fn Scale[self: Point](v: i32) -> Point {\n    return {.x = self.x * v, .y = self.y * v};\n  }\n}\n\nfn AddAndScaleGeneric[T:! Vector](a: T, b: T, s: i32) -> T {\n  var m: auto = a.Add;\n  var n: auto = m(b).Scale;\n  return n(s);\n}\n\nfn Main() -> i32 {\n  var a: Point = {.x = 1, .y = 4};\n  var b: Point = {.x = 2, .y = 3};\n  var p: Point = AddAndScaleGeneric(a, b, 5);\n  return p.x - 15;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/dbd0b78b1bfd4878676ac3d882aee2b797d7af15",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: DESTRUCTOR A 1\n// CHECK:STDOUT: DESTRUCTOR A 2\n// CHECK:STDOUT: DESTRUCTOR A 3\n// CHECK:STDOUT: DESTRUCTOR A 4\n// CHECK:STDOUT: DESTRUCTOR A 5\n// CHECK:STDOUT: DESTRUCTOR A 6\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\n\nclass A{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR A {0}\",self.n);\n    }\n    var n: i32;\n}\n\nfn Main() -> i32 {\n  var a: array(A, 2) = ({.n = 6},{.n = 5});\n  var b: array(array(A, 2), 2) = (({.n = 4},{.n = 3}), ({.n = 2},{.n = 1}));\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/dccc5c3818f328ee1fd500f899c37ac0af7b2182",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 5\n// CHECK:STDOUT: 4\n// CHECK:STDOUT: 0\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as BitAndWith(i32) where .Result = A {\n  fn Op[self: Self](rhs: i32) -> A { return {.n = self.n & rhs}; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 13};\n  a = a & 7;\n  Print(\"{0}\", a.n);\n  a &= -2;\n  Print(\"{0}\", a.n);\n  Print(\"{0}\", (a & 3).n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/dcde55e2a4e60d6bf3dd574d15a425e30279d53c",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  if (0 == 1) {\n    return 1;\n  } else if (0 == 2) {\n    return 2;\n  } else {\n    return 0;\n  }\n\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/dd662568f4fe92a74f53b026f11638725f966e0b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  returned var x: i32;\n  x = 1;\n  return var;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/de46bc1199653f93b7db2c1c39e7ca61dfa6b810",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var t: auto = (1, 2, 3, 4);\n  match (t) {\n    case (_: i32, _: auto, x: i32, y: auto) => {\n      return y - x - 1;\n    }\n  }\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e028180f3ba177567c45f5149e96c0313d1b175f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nnamespace A;\nnamespace A.B;\nnamespace A.B.C;\nfn A.B.C.\n  // CHECK:STDERR: COMPILATION ERROR: fail_missing_nested.carbon:[[@LINE+1]]: name 'D' has not been declared in namespace A.B.C\n  D\n  // Don't combine with the previous line. This test is verifying that the\n  // diagnostic points at the right token.\n  .E.F() {}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e03df3e0be45ac48d5ad2d59b67b677678a76de6",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\nchoice A {\n  Value(i32)\n}\n\nimpl i32 as ImplicitAs(A) {\n  fn Convert[self: Self]() -> A { return A.Value(self + 1); }\n}\n\nfn Main() -> i32 {\n  let A.Value(n: i32) = 2;\n  return n;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e0afc6bd74d5718e01a5888df16600e8a4645f63",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\n// TODO: Should this work?\n\npackage ExplorerTest;\n\ninterface Vector {\n  let Dim:! i32;\n}\nimpl (i32, i32, i32) as Vector where .Dim = 3 {}\n\nclass Point(Scalar:! type, Dim:! i32) {}\n\nfn F[Scalar:! type, V:! Vector where .Dim == 3](p: Point(Scalar, V.Dim), v: V) {}\n\nfn G[Scalar:! type](p: Point(Scalar, 3)) {}\nfn H[V:! Vector where .Dim == 3](v: V) {\n  var p: Point(i32, V.Dim) = {};\n  // CHECK:STDERR: COMPILATION ERROR: fail_match_in_deduction.carbon:[[@LINE+1]]: mismatch in non-deduced values, `(V).(Vector.Dim)` != `3`\n  G(p);\n}\n\nfn Main() -> i32 {\n  var p: Point(i32, 3) = {};\n  // Deduce Point(Scalar, V.Dim) from Point(i32, 3).\n  F(p, (0, 0, 0));\n  // Deduce Point(Scalar, 3) from Point(i32, V.Dim).\n  H((0, 0, 0));\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e2c590fff5cd302d986f3fed578e45fa09836052",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: i32.F\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Base {\n  fn F();\n}\n\ninterface Extension {\n  extend Base;\n}\n\nfn F[T:! type where .Self impls Extension](x: T) {\n  x.(Extension.F)();\n}\n\nimpl i32 as Extension {\n  fn F() { Print(\"i32.F\"); }\n}\n\nfn Main() -> i32 {\n  var n: i32 = 0;\n  F(n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e3895b1888cb48ad3ab9c9cd3b78debedb0ad5e9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: 6\n// CHECK:STDOUT: 3\n// CHECK:STDOUT: 1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as DivWith(i32) where .Result = A {\n  fn Op[self: Self](rhs: i32) -> A { return {.n = self.n / rhs}; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 19};\n  a = a / 3;\n  Print(\"{0}\", a.n);\n  a /= 2;\n  Print(\"{0}\", a.n);\n  Print(\"{0}\", (a / 2).n);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e45bda3cd3778f2372ce18cc0d9ff7bbf1f50ba5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n__mixin M1 {\n  fn Scale10[self: Self](x:i32) -> i32{\n     return x * 10;\n  }\n}\n\n__mixin M2 {\n  __mix M1;\n  fn Square[self: Self](x:i32) -> i32{\n    return x * x;\n  }\n}\n\nclass C {\n  __mix M2;\n}\n\nfn Main() -> i32 {\n  var c: C = {};\n  return c.Square(11) - c.Scale10(10) - 21;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e48c19846a9d9a8418fbf4e363eb69d720fdab9d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1234\n\npackage ExplorerTest;\n\ninterface A {\n  fn F() -> i32;\n}\ninterface B {\n  fn F() -> i32;\n  fn G() -> i32;\n}\ninterface C(T:! type) {\n  fn H() -> T;\n}\n\nimpl i32 as A {\n  fn F() -> i32 { return 1; }\n}\n\nimpl i32 as B & C(i32) where .Self impls A {\n  fn F() -> i32 { return 2; }\n  fn G() -> i32 { return 3; }\n  fn H() -> i32 { return 4; }\n}\n\nfn Main() -> i32 {\n  let n: i32 = 0;\n  return n.(A.F)() * 1000 + n.(B.F)() * 100 + n.(B.G)() * 10 + n.(C(i32).H)();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e4b64d16a5d43dc7e5bee135714611d2929364a6",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface Iface {\n  let T:! type;\n}\n\nfn F[T:! Iface where .T == i32](x: T) {}\n\nfn G[U:! Iface where .T == i32](x: U) {\n  F(x);\n}\n\nfn H[V:! Iface](x: V) {\n  // CHECK:STDERR: COMPILATION ERROR: fail_equal_to_dependent_type.carbon:[[@LINE+1]]: constraint requires that (T).(Iface.T) (with value (V).(Iface.T)) == i32, which is not known to be true\n  F(x);\n}\n\nclass Class {\n  extend impl as Iface where .T = i32 {}\n}\n\nfn Main() -> i32 {\n  var x: Class = {};\n  G(x);\n  H(x);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e657c790f4c10f0678e90dc52facef51920a94d3",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nconstraint X {\n  // CHECK:STDERR: COMPILATION ERROR: fail_associated_function.carbon:[[@LINE+1]]: associated function not permitted in named constraint\n  fn F();\n}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e673a37cb310aaa88cbc216044663eb2c49ae76f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var t: (auto, (i32, i32)) = ((1, 2), (3, 4));\n  return t[0][0] + t[1][1] - 5;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e6da0876675b17c319ea55bf19ecbc12b779d3df",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 1133\n\npackage ExplorerTest;\n\ninterface I(T:! type) {\n  fn F[self: Self](t: T, o: Self) -> Self;\n}\n\nclass X(U:! type) {\n  extend impl as I(U) {\n    fn F[self: Self](u: U, o: Self) -> Self { return {.m = u, .n = self.n + o.n}; }\n  }\n  var m: U;\n  var n: i32;\n}\n\nfn Run[V:! type](x: V) -> (V, V, i32, i32) {\n  var v: X(V) = {.m = x, .n = 1};\n  var w: X(V) = {.m = x, .n = 2};\n  // OK, know that `X(V)` implements `I(V)` from the `impl` in the class.\n  var call: X(V) = v.(X(V).(I(V).F))(x, w);\n  return (call.(X(V).m), call.m, call.(X(V).n), call.n);\n}\n\nfn Main() -> i32 {\n  var (a: i32, b: i32, c: i32, d: i32) = Run(1);\n  return a * 1000 + b * 100 + c * 10 + d;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e77f7b118df2a85fa55e8798a40f343b59ceab88",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// CHECK:STDERR: COMPILATION ERROR: fail_impl_as.carbon:[[@LINE+1]]: expected a constraint in impl declaration, found i32\nimpl i32 as i32 {}\n\nfn Main() -> i32 {\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e78aa6328c0b365b87a34a2dd1cb8e5270e04a0b",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass Point {\n  fn Origin() -> Point {\n    return {.x = 0, .y = 0};\n  }\n\n  fn SetX[self: Point](x: i32) {\n    // CHECK:STDERR: COMPILATION ERROR: fail_method_args.carbon:[[@LINE+1]]: Only a reference expression can be assigned to, but got `x`\n    x = 10;\n  }\n\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p: Point = Point.Origin();\n  p.SetX(42);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/e9dff14915dda34282efb04147877d0fc83ba2a0",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn swap[T:! type, U:! type](tuple: (T, U)) -> (U, T) {\n  return (tuple[1], tuple[0]);\n}\n\nfn Main() -> i32 {\n  return swap((0, true))[1];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ea454bd2c8e7219c267ca0b01e27c649999c1451",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass A {\n  fn F[self: Self]() -> i32;\n}\n\nfn Main() -> i32 {\n  var a: A = {};\n  // CHECK:STDERR: RUNTIME ERROR: fail_call_undefined_method.carbon:[[@LINE+1]]: attempt to call function `F` that has not been defined\n  return a.F();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ea82b6f22005103932231c0641c74b125fcc7fb0",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: -6\n\npackage ExplorerTest;\n\nclass A { var n: i32; }\n\nimpl A as BitComplement where .Result = A {\n  fn Op[self: Self]() -> A { return {.n = ^self.n}; }\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 5};\n  a = ^a;\n  return a.n;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/eaa7bb9e4dbf3576f9587cd88b29976ca2024fe6",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: DESTRUCTOR A 1\n// CHECK:STDOUT: DESTRUCTOR A 2\n// CHECK:STDOUT: DESTRUCTOR A 3\n// CHECK:STDOUT: DESTRUCTOR A 4\n// CHECK:STDOUT: result: 2\n\npackage ExplorerTest;\n\nclass A{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR A {0}\",self.n);\n    }\n    var n: i32;\n}\n\nfn ident(x: bool)-> bool{\n    return x;\n}\n\nfn ident_i32(x: i32)-> i32{\n    return x;\n}\n// It should be enforced that different runtime scopes are on the stack.\n//So that it can be tested that the wrong scopes are not removed from the stack.\nfn Main() -> i32 {\n  var i: i32 = 0;\n  var d: A = {.n = 4};\n  if(ident(true)){\n    var a: A = {.n = 3};\n    if(true){\n       var b: A = {.n = 2};\n       ident_i32(2);\n       if(ident_i32(0) == 0){\n         var c: A = {.n = 1};\n         return 2;\n       }\n    }\n  }\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/eaca8f02a5ca41d60a68be9186e5f79538ae2719",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32 = (1);\n  var t2: (i32, i32) = (5, 2);\n  t2[0] = 3;\n  return t2[0] - t2[1] - x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ebb86c45027660ce57bbadede73ab1a5dbc43e35",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\n// CHECK:STDERR: COMPILATION ERROR: fail_nontype_tuple_as_type.carbon:[[@LINE+1]]: type error in type of name binding: '(i32, i32)' is not implicitly convertible to 'type'\nfn F[T:! (i32, i32)](x: T);\n\nfn Main() -> i32;\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ecd12a6a72a7c5cdf93dd9bb7637cb35f65c1d00",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var s: String = '''\n    A \"block\" \"\"string\"\" literal\n      with indent.\n    ''';\n  if (s == \"A \\\"block\\\" \\\"\\\"string\\\"\\\" literal\\n  with indent.\\n\") {\n    return 0;\n  } else {\n    return 1;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ecdb111d6c89a22189b961cb47ab1e73df8ed430",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var v: bool;\n  // CHECK:STDERR: COMPILATION ERROR: fail_if_cond.carbon:[[@LINE+1]]: use of uninitialized variable v\n  return if v then 1 else 2;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ed0769767eea7a7e0ee58d52278417c698605719",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var x: i32;\n  // CHECK:STDERR: COMPILATION ERROR: fail_field_value.carbon:[[@LINE+1]]: use of uninitialized variable x\n  var p: auto = {.x = x,};\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ed28ae6948896b9be69c556380b22f8c6fdee8d1",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDERR: RUNTIME ERROR: <Main()>:0: attempt to call function `Main` that has not been defined\n\npackage ExplorerTest;\n\nfn Main() -> i32;\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ed306e9bbd8d275d000beb5cf551284765c97c23",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var t: auto = 5;\n  match (t) {\n    case x: i32 => {\n      return x - 5;\n    }\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ee45e8d94544f8f79e7b6330365a9426715f47f9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: (*c).a: 1\n// CHECK:STDOUT: Foo(&d): 1\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nbase class C {\n  var a: i32;\n}\n\nclass D {\n  extend base: C;\n}\n\nfn Foo(c: C*) -> i32 {\n  return (*c).a;\n}\n\nfn Main() -> i32 {\n  var d: D = { .base = {.a = 1} };\n  var c: C* = &d;\n  Print(\"(*c).a: {0}\", (*c).a);\n  Print(\"Foo(&d): {0}\", Foo(&d));\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ee8db01890a0f9c520e30f1d75c44efabbbbdb01",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn CompareStr(s: String) -> i32 {\n  if (s == #\"str\"#) {\n    return 0;\n  }\n  return 1;\n}\n\nfn Main() -> i32 {\n  return CompareStr(\"str\");\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/eed2aa2d6ca72b1972eaf2bb206a0591a2ce9a95",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  if (^0 != -1) { return 11; }\n  if (^1 != -2) { return 12; }\n  if (^(-3) != 2) { return 13; }\n\n  if (3 & 6 != 2) { return 21; }\n  if (-1 & 4 != 4) { return 22; }\n  if (-1 & -2 != -2) { return 23; }\n\n  if (1 | 4 != 5) { return 31; }\n  if (5 | 3 != 7) { return 32; }\n  if (-2 | 1 != -1) { return 33; }\n\n  if (1 ^ 4 != 5) { return 41; }\n  if (5 ^ 3 != 6) { return 42; }\n  if (-2 ^ -3 != 3) { return 43; }\n\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/eeea07311e1c93999ce139f71cc5e6be83ae938d",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\n// Test that assignment performs a copy and does not create an alias.\n\nfn Main() -> i32 {\n  var x: i32 = -1;\n  if (true) {\n    var y: i32 = 0;\n    x = y;\n    // y dies here\n  }\n  return x;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/ef87d1f2a1afcc05941ade6a5bd57c9fdea83b34",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface Number {\n  fn Zero() -> Self;\n  fn Add[self: Self](other: Self) -> Self;\n}\n\nclass Point(T:! Number) {\n  fn Origin() -> Point(T) {\n    return {.x = T.Zero(), .y = T.Zero()};\n  }\n  fn Clone[self: Point(T)]() -> Point(T) {\n    return {.x = self.x, .y = self.y};\n  }\n  fn SumXY[self: Point(T)]() -> T {\n    return self.x.Add(self.y);\n  }\n  var x: T;\n  var y: T;\n}\n\nimpl i32 as Number {\n  fn Zero() -> i32 { return 0; }\n  fn Add[self: i32](other: i32) -> i32 { return self + other; }\n}\n\nfn Main() -> i32 {\n  var p: Point(i32) = Point(i32).Origin();\n  return p.Clone().SumXY();\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f0122e82b0498ec11a6a9d68e6de8440d891b272",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: DESTRUCTOR C 1\n// CHECK:STDOUT: DESTRUCTOR B 2\n// CHECK:STDOUT: DESTRUCTOR A 3\n// CHECK:STDOUT: result: 1\n\npackage ExplorerTest;\n\nclass A{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR A {0}\",self.n);\n    }\n    var n: i32;\n}\n\nclass B{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR B {0}\",self.n);\n    }\n    var n: i32;\n}\n\nclass C{\n    destructor[self: Self]{\n        Print(\"DESTRUCTOR C {0}\",self.n);\n    }\n    var n: i32;\n}\n\nfn Main() -> i32 {\n  var a: A = {.n = 3};\n  var b: B = {.n = 2};\n  var c: C = {.n = 1};\n  return 1;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f0457f1e27c67e8425559e6b753cca540cf69f65",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Destructor\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass C {\n  destructor[self: Self] {\n    Print(\"Destructor\");\n  }\n}\n\nfn Main() -> i32 {\n  let c: C = {};\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f0ddb293345e5013757ebfacd7769ef92acd41d4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass C {\n  // CHECK:STDERR: COMPILATION ERROR: fail_use_before_typecheck.carbon:[[@LINE+1]]: incomplete type `class C` used in member access\n  var n: if not C.WrapInStruct() then i32 else {.n: i32};\n  fn WrapInStruct() -> bool { return true; }\n}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f1986481baa957b8dd977f8ca3e8c4107d492799",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nnamespace N;\nnamespace N.M;\nfn N.F() {}\nfn N.M.FM() {}\n\nalias A = N;\nalias AM = N.M;\nalias N.A = N.M;\nalias N.A2 = N;\n\nfn Main() -> i32 {\n  A.F();\n  AM.FM();\n  N.A.FM();\n  A.A2.A2.A2.A2.A2.A2.A2.F();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f19c5bb5147295d791fb5d6899d93ed7a23c072f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Interface: -3\n// CHECK:STDOUT: Op: -3\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var val: i32 = 3;\n  // Make sure that both the interface and operator work with i32. These rely on\n  // builtin arithmetic more directly.\n  Print(\"Interface: {0}\", val.(Negate.Op)());\n  Print(\"Op: {0}\", -val);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f1b24ed86c606cde53c498fc6411053d0ae22ced",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass X(T:! type) {}\n\n// CHECK:STDERR: COMPILATION ERROR: fail_non_type_self.carbon:[[@LINE+1]]: `.Self` used in type of non-type generic binding `T`\nfn F[T:! X(.Self)](x: T) {}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f1d88daac0be722a2a2e6bedd09b39e240043653",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\ninterface X(T:! type) {}\n\ninterface Y(T:! type) {\n    let M:! X(T);\n}\n\ninterface Z {\n  // The `i32 impls X(.Self)` constraint is indirectly required by\n  // specifying that `.M = i32`.\n  let N:! Y(.Self) where i32 impls X(.Self) and .M = i32;\n}\n\nimpl i32 as X(i32) {}\nimpl i32 as Y(i32) where .M = i32 {}\nimpl i32 as Z where .N = i32 {}\n\nfn F[A:! Z](a: A) -> A { return a; }\n\nfn Main() -> i32 {\n  return F(0);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f2b43d44db5dec0cca4bc6fc63f487fabae1b941",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_negative_size.carbon:[[@LINE+1]]: Array size cannot be negative\n  var x: array(i32, -1) = ();\n  return x[0];\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f39ac0d9de634c2a723f879231e77ef600e036d9",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: COMPILATION ERROR: fail_no_impl.carbon:[[@LINE+1]]: i32 is not equality comparable with String (could not find implementation of interface EqWith(U = String) for i32)\n  Print(\"different types equal: {0}\", if 1 == \"1\" then 1 else 0);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f4f4353df90e753e832eb974c782e27dbe6753d4",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  // CHECK:STDERR: SYNTAX ERROR: fail_invalid_escape.carbon:[[@LINE+1]]: Invalid escaping in string: \"str\\e\"\n  Print(\"str\\e\");\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f669b57c4be29746f06e2ad46b428769a791dd07",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nclass C {}\n\n// CHECK:STDERR: SYNTAX ERROR: fail_type_only.carbon:[[@LINE+1]]: syntax error, unexpected RIGHT_SQUARE_BRACKET, expecting COLON\nfn f[x:! i32, addr C]() {}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f71cbd0475ddb41b78a0d439aa78ae1e2eec0df5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\n\n\n\nfn Main() -> i32 {\n  var ar: array(i32, 4) = (0, 1,2,3);\n  var count : i32 = 0;\n  for( x: i32 in ar){\n      count = count +x;\n      if( x == 2){\n        break;\n      }\n  }\n  return count;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f72b3c6b4ade452568f6834dd6e5896d1772ff2f",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: test\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn F() { Print(\"test\"); }\n\nfn Main() -> i32 {\n  var p: auto = heap.New(F);\n  var y: auto = *p;\n  y();\n  heap.Delete(p);\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f72fd742e291347d71ef000e002dc8e8baa13830",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nfn F() {}\n\n// CHECK:STDERR: COMPILATION ERROR: fail_qualifier_not_namespace.carbon:[[@LINE+1]]: fn F cannot be used as a name qualifier\nfn F.G() {}\n\nfn Main() -> i32 {\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f7b8bc9f4b18f013697267cc9c966ae65f4cd7e3",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface Vector {\n  fn Add[self: Self](b: Self) -> Self;\n  fn Scale[self: Self](v: i32) -> Self;\n}\n\nclass Point {\n  var x: i32;\n  var y: i32;\n}\n\n// Error: need to specify which type implementing `Vector` for.\n// CHECK:STDERR: COMPILATION ERROR: fail_external_impl_omit_self.carbon:[[@LINE+1]]: could not resolve 'Self'\nimpl as Vector {\n  fn Add[self: Point](b: Point) -> Point {\n    return {.x = self.x + b.x, .y = self.y + b.y};\n  }\n  fn Scale[self: Point](v: i32) -> Point {\n    return {.x = self.x * v, .y = self.y * v};\n  }\n}\n\nfn AddAndScaleGeneric[T:! Vector](a: T, b: T, s: i32) -> T {\n  var m: auto = a.Add;\n  var n: auto = m(b).Scale;\n  return n(s);\n}\n\nfn Main() -> i32 {\n  var a: Point = {.x = 1, .y = 4};\n  var b: Point = {.x = 2, .y = 3};\n  var p: Point = AddAndScaleGeneric(a, b, 5);\n  return p.x - 15;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f7c747dc5107c73b9c4bfe6f24267f04ba16d129",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: Initialize c from initializing expression (return <expr>)\n// CHECK:STDOUT: 0: Heap{}, 1: !Uninit<class C>, 2: C{}\n// CHECK:STDOUT: Object created, returning\n// CHECK:STDOUT: c destroyed\n// CHECK:STDOUT: 0: Heap{}, 1: C{}, 2: !!C{}\n// CHECK:STDOUT: c destroyed\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass C {\n  destructor[self: Self] {\n    Print(\"c destroyed\");\n  }\n}\n\nfn CallWithReturnExpression() -> C {\n  var c: C = {};\n  heap.PrintAllocs();\n  Print(\"Object created, returning\");\n  return c;\n}\n\nfn FromInitializingExpression_ReturnExpr() {\n  Print(\"Initialize c from initializing expression (return <expr>)\");\n  let c: C = CallWithReturnExpression();\n  heap.PrintAllocs();\n}\n\nfn Main() -> i32 {\n  FromInitializingExpression_ReturnExpr();\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/f91e230199efd6367f8622f5a6eaa54d1d4d8e90",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nvar x: i32 = 0;\n\nfn Main() -> i32 {\n  var x: i32 = 0;\n  return 0;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/fa056963c20a8a8dc279cb2e2a9b769338cc92da",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\ninterface HasThreeTypes {\n  let A:! type;\n  let B:! type;\n  let C:! type;\n}\n\n// CHECK:STDERR: COMPILATION ERROR: fail_incomplete_impl_2.carbon:[[@LINE+1]]: implementation doesn't provide a concrete value for interface HasThreeTypes.C\nimpl i32 as HasThreeTypes where .A = i32 and .B = .C {}\n\nfn Main() -> i32 { return 0; }\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/fa11a132da6f10be8e8aa10cbd25ea5d8107a614",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n\npackage ExplorerTest;\n\nchoice AB {\n  A(),\n  B()\n}\n\nfn F() -> AB { return AB.A(); }\n\nfn Main() -> i32 {\n  // Note, this match is exhaustive, but it exceeds our depth limit.\n  match ((F(), F(), F(), F(), F(), F(), F(), F(), F())) {\n    case (AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 0; }\n    case (AB.B(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 1; }\n    case (_: AB,  AB.B(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 2; }\n    case (_: AB,  _: AB,  AB.B(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 3; }\n    case (_: AB,  _: AB,  _: AB,  AB.B(), AB.A(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 4; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.A(), AB.A(), AB.A(), AB.A()) => { return 5; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.A(), AB.A(), AB.A()) => { return 6; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.A(), AB.A()) => { return 7; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B(), AB.A()) => { return 8; }\n    case (_: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  _: AB,  AB.B()) => { return 9; }\n  }\n// CHECK:STDERR: COMPILATION ERROR: fail_exhaustive_exponential_9x.carbon:[[@LINE+1]]: non-exhaustive match may allow control-flow to reach the end of a function that provides a `->` return type\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/fb4504a84cc35d086689b9f93eb9f365331f4750",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 3\n\npackage ExplorerTest;\n\nfn AddInt(a: i32, b: i32) -> i32 {\n  returned var ret: i32 = a + b;\n  return var;\n}\n\nfn Main() -> i32 {\n  return AddInt(1, 2);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/fbd855380068533d0148c6011a302bf07cae0612",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn id[T:! type](x: T) -> T {\n  return x;\n}\n\nfn Main() -> i32 {\n  return id(0);\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/fc2e6307261474cbadb9046919ff50710904d4d5",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nfn Main() -> i32 {\n  var s: String = '''\n    A block string literal\n    \\'''\n    ''';\n  if (s == \"A block string literal\\n'''\\n\") {\n    return 0;\n  } else {\n    return 1;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/fc927b8e82af4dcdaa2495e28ff7269c43456ff2",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 5\n\npackage ExplorerTest;\n\ninterface ConvertsFromInt {\n  require i32 impls ImplicitAs(Self);\n}\n\nfn ConvertIntTo(T:! ConvertsFromInt, n: i32) -> T {\n  return n;\n}\n\nclass IntHolder {\n  var n: i32;\n}\nimpl i32 as ImplicitAs(IntHolder) {\n  fn Convert[self: Self]() -> IntHolder { return {.n = self}; }\n}\nimpl IntHolder as ConvertsFromInt {}\n\nfn Main() -> i32 {\n  return ConvertIntTo(IntHolder, 5).n;\n}\n"
  },
  {
    "path": "toolchain/check/fuzzer_corpus/fdc040e7e474c3ec5da7044a80e2df6bfcb80917",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// AUTOUPDATE\n// CHECK:STDOUT: result: 0\n\npackage ExplorerTest;\n\nclass Point {\n  var x: i32;\n  var y: i32;\n}\n\nfn Main() -> i32 {\n  var p1: Point = {.x = 1, .y = 2};\n  var p2: auto = p1;\n  p2.x = 3;\n  return p1.x - 1;\n}\n"
  },
  {
    "path": "toolchain/check/generic.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/generic.h\"\n\n#include <utility>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/generic_region_stack.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/subst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/sem_ir/constant.h\"\n#include \"toolchain/sem_ir/generic.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nCARBON_DEFINE_ENUM_MASK_NAMES(DependentInstKind) {\n  CARBON_DEPENDENT_INST_KIND(CARBON_ENUM_MASK_NAME_STRING)\n};\n\nstatic auto MakeSelfSpecificId(Context& context, SemIR::GenericId generic_id)\n    -> SemIR::SpecificId;\n\n// Get the current pending generic. If we have not yet allocated a `GenericId`\n// for it, do so now.\nstatic auto GetOrCreatePendingGeneric(Context& context)\n    -> GenericRegionStack::PendingGeneric {\n  auto pending_generic = context.generic_region_stack().PeekPendingGeneric();\n  if (!pending_generic.generic_id.has_value()) {\n    // Allocate a placeholder generic now to form a generic ID. This generic\n    // will be populated once we reach the end of the generic declaration.\n    pending_generic.generic_id = context.generics().Add(\n        SemIR::Generic{.decl_id = SemIR::InstId::None,\n                       .bindings_id = SemIR::InstBlockId::None,\n                       .self_specific_id = SemIR::SpecificId::None});\n    context.generic_region_stack().SetPendingGenericId(\n        pending_generic.generic_id);\n  }\n  return pending_generic;\n}\n\n// Adds an instruction `generic_inst_id` to the eval block for the current\n// generic region. The instruction `generic_inst_id` is expected to compute the\n// value of the constant described by `const_inst_id` in each specific. Forms\n// and returns a corresponding symbolic constant ID that refers to the\n// substituted value of that instruction in each specific.\nstatic auto AddGenericConstantInstToEvalBlock(\n    Context& context, SemIR::InstId const_inst_id,\n    SemIR::InstId generic_inst_id, SemIR::ConstantDependence dependence)\n    -> SemIR::ConstantId {\n  auto [generic_id, region] = GetOrCreatePendingGeneric(context);\n  auto index = SemIR::GenericInstIndex(\n      region, context.generic_region_stack().PeekEvalBlock().size());\n  context.generic_region_stack().AddInstToEvalBlock(generic_inst_id);\n  return context.constant_values().AddSymbolicConstant(\n      {.inst_id = const_inst_id,\n       .generic_id = generic_id,\n       .index = index,\n       .dependence = dependence});\n}\n\nnamespace {\n// Substitution callbacks to rebuild a generic constant in the eval block for a\n// generic region.\nclass RebuildGenericConstantInEvalBlockCallbacks : public SubstInstCallbacks {\n public:\n  // `context` must not be null.\n  RebuildGenericConstantInEvalBlockCallbacks(Context* context,\n                                             SemIR::LocId loc_id)\n      : SubstInstCallbacks(context),\n        loc_id_(loc_id),\n        constants_in_generic_(\n            context->generic_region_stack().PeekConstantsInGenericMap()) {}\n\n  auto RebuildType(SemIR::TypeInstId type_inst_id) const\n      -> SemIR::TypeId override {\n    // When building instructions in the eval block, form attached types.\n    return context().types().GetTypeIdForTypeConstantId(\n        context().constant_values().GetAttached(type_inst_id));\n  }\n\n  // Check for instructions for which we already have a mapping into the eval\n  // block, and substitute them with the instructions in the eval block.\n  auto Subst(SemIR::InstId& inst_id) -> SubstResult override {\n    auto const_id = context().constant_values().Get(inst_id);\n    if (!const_id.has_value()) {\n      // An unloaded import ref should never contain anything we need to\n      // substitute into. Don't trigger loading it here.\n      CARBON_CHECK(\n          context().insts().Is<SemIR::ImportRefUnloaded>(inst_id),\n          \"Substituting into instruction with invalid constant ID: {0}\",\n          context().insts().Get(inst_id));\n      return SubstResult::FullySubstituted;\n    }\n    if (!context().constant_values().DependsOnGenericParameter(const_id)) {\n      // This instruction doesn't have a symbolic constant value, so can't\n      // contain any bindings that need to be substituted.\n      return SubstResult::FullySubstituted;\n    }\n\n    // If this constant value has a defining instruction in the eval block,\n    // replace the instruction in the body of the generic with the one from the\n    // eval block.\n    if (auto result = constants_in_generic_.Lookup(\n            context().constant_values().GetInstId(const_id))) {\n      inst_id = result.value();\n      return SubstResult::FullySubstituted;\n    }\n\n    return SubstResult::SubstOperands;\n  }\n\n  // Build a new instruction in the eval block corresponding to the given\n  // constant.\n  auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst)\n      -> SemIR::InstId override {\n    auto& orig_symbolic_const = context().constant_values().GetSymbolicConstant(\n        context().constant_values().Get(orig_inst_id));\n    auto const_inst_id = orig_symbolic_const.inst_id;\n    auto dependence = orig_symbolic_const.dependence;\n\n    // We might already have an instruction in the eval block if a transitive\n    // operand of this instruction has the same constant value.\n    auto result = constants_in_generic_.Insert(const_inst_id, [&] {\n      // TODO: Add a function on `Context` to add the instruction without\n      // inserting it into the dependent instructions list or computing a\n      // constant value for it.\n      // TODO: Is the location we pick here always appropriate for the new\n      // instruction?\n      auto inst_id = context().sem_ir().insts().AddInNoBlock(\n          SemIR::LocIdAndInst::UncheckedLoc(loc_id_, new_inst));\n      auto const_id = AddGenericConstantInstToEvalBlock(\n          context(), const_inst_id, inst_id, dependence);\n      context().constant_values().Set(inst_id, const_id);\n      return inst_id;\n    });\n    return result.value();\n  }\n\n  auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId override {\n    auto inst = context().insts().Get(orig_inst_id);\n    CARBON_CHECK(\n        (inst.IsOneOf<SemIR::SymbolicBinding, SemIR::SymbolicBindingPattern>()),\n        \"Instruction {0} has symbolic constant value but no symbolic operands\",\n        inst);\n\n    // Rebuild the instruction anyway so that it's included in the eval block.\n    // TODO: Can we just reuse the instruction in this case?\n    return Rebuild(orig_inst_id, inst);\n  }\n\n private:\n  SemIR::LocId loc_id_;\n  ConstantsInGenericMap& constants_in_generic_;\n};\n\n// Substitution callbacks to rebuild a template action. This rebuilds the action\n// instruction in-place if it needs to be modified.\nclass RebuildTemplateActionInEvalBlockCallbacks final\n    : public RebuildGenericConstantInEvalBlockCallbacks {\n public:\n  // `context` must not be null.\n  RebuildTemplateActionInEvalBlockCallbacks(Context* context,\n                                            SemIR::LocId loc_id,\n                                            SemIR::InstId action_inst_id)\n      : RebuildGenericConstantInEvalBlockCallbacks(context, loc_id),\n        action_inst_id_(action_inst_id) {}\n\n  auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst)\n      -> SemIR::InstId override {\n    if (orig_inst_id == action_inst_id_) {\n      // TODO: We want to ReplaceInstPreservingConstantValue here, but don't\n      // want to evaluate the action to check the value hasn't changed.\n      context().sem_ir().insts().Set(orig_inst_id, new_inst);\n      return orig_inst_id;\n    }\n    return RebuildGenericConstantInEvalBlockCallbacks::Rebuild(orig_inst_id,\n                                                               new_inst);\n  }\n\n  auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId override {\n    if (orig_inst_id == action_inst_id_) {\n      return orig_inst_id;\n    }\n    return RebuildGenericConstantInEvalBlockCallbacks::ReuseUnchanged(\n        orig_inst_id);\n  }\n\n private:\n  SemIR::InstId action_inst_id_;\n};\n}  // namespace\n\n// Adds instructions to compute the substituted version of `type_id` in each\n// specific into the eval block for the current generic region. Returns a\n// symbolic type ID that refers to the substituted type in each specific.\nstatic auto AddGenericTypeToEvalBlock(Context& context, SemIR::LocId loc_id,\n                                      SemIR::TypeId type_id) -> SemIR::TypeId {\n  // Substitute into the type's constant instruction and rebuild it in the eval\n  // block.\n  auto rebuild_generic_constant_callbacks =\n      RebuildGenericConstantInEvalBlockCallbacks(&context, loc_id);\n  auto type_inst_id = SubstInst(context, context.types().GetTypeInstId(type_id),\n                                rebuild_generic_constant_callbacks);\n  return context.types().GetTypeIdForTypeConstantId(\n      context.constant_values().GetAttached(type_inst_id));\n}\n\n// Adds instructions to compute the substituted value of `inst_id` in each\n// specific into the eval block for the current generic region. Returns a\n// symbolic constant instruction ID that refers to the substituted constant\n// value in each specific.\nstatic auto AddGenericConstantToEvalBlock(Context& context,\n                                          SemIR::InstId inst_id)\n    -> SemIR::ConstantId {\n  CARBON_CHECK(context.constant_values().Get(inst_id).is_symbolic(),\n               \"Adding generic constant {0} with non-symbolic value {1}\",\n               context.insts().Get(inst_id),\n               context.constant_values().Get(inst_id));\n\n  // Substitute into the constant value and rebuild it in the eval block if\n  // we've not encountered it before.\n  auto const_inst_id = context.constant_values().GetConstantInstId(inst_id);\n  auto callbacks = RebuildGenericConstantInEvalBlockCallbacks(\n      &context, SemIR::LocId(inst_id));\n  auto new_inst_id = SubstInst(context, const_inst_id, callbacks);\n  CARBON_CHECK(new_inst_id != const_inst_id,\n               \"No substitutions performed for generic constant {0}\",\n               context.insts().Get(inst_id));\n  return context.constant_values().GetAttached(new_inst_id);\n}\n\n// Adds an instruction that performs a template action to the eval block for the\n// generic. The instruction should not yet have been added to any block. The\n// instruction might refer to types and constants that need to be rewritten, so\n// substitute into it first.\nstatic auto AddTemplateActionToEvalBlock(Context& context,\n                                         SemIR::InstId inst_id) -> void {\n  // Substitute into the constant value and rebuild it in the eval block.\n  auto rebuild_template_action_callbacks =\n      RebuildTemplateActionInEvalBlockCallbacks(&context, SemIR::LocId(inst_id),\n                                                inst_id);\n  auto new_inst_id =\n      SubstInst(context, inst_id, rebuild_template_action_callbacks);\n  CARBON_CHECK(new_inst_id == inst_id,\n               \"Substitution changed InstId of template action\");\n  context.generic_region_stack().PeekConstantsInGenericMap().Insert(inst_id,\n                                                                    inst_id);\n\n  // Add the action to the eval block and point its constant value back to its\n  // index within the block.\n  auto [generic_id, region] = GetOrCreatePendingGeneric(context);\n  auto& symbolic_constant = context.constant_values().GetSymbolicConstant(\n      context.constant_values().GetAttached(inst_id));\n  symbolic_constant.generic_id = generic_id;\n  symbolic_constant.index = SemIR::GenericInstIndex(\n      region, context.generic_region_stack().PeekEvalBlock().size());\n  context.generic_region_stack().AddInstToEvalBlock(inst_id);\n}\n\n// Populates a map of constants in a generic from the constants in the\n// declaration region, in preparation for building the definition region.\nstatic auto PopulateConstantsFromDeclaration(\n    Context& context, SemIR::GenericId generic_id,\n    ConstantsInGenericMap& constants_in_generic) {\n  // For the definition region, populate constants from the declaration.\n  auto decl_eval_block = context.inst_blocks().Get(\n      context.generics().Get(generic_id).decl_block_id);\n  constants_in_generic.GrowForInsertCount(decl_eval_block.size());\n  for (auto inst_id : decl_eval_block) {\n    auto const_inst_id = context.constant_values().GetConstantInstId(inst_id);\n    auto result = constants_in_generic.Insert(const_inst_id, inst_id);\n    CARBON_CHECK(result.is_inserted(),\n                 \"Duplicate constant in generic decl eval block: {0}\",\n                 context.insts().Get(const_inst_id));\n  }\n}\n\nauto AttachDependentInstToCurrentGeneric(Context& context,\n                                         DependentInst dependent_inst) -> void {\n  auto [inst_id, dep_kind] = dependent_inst;\n\n  // If we don't have a generic region here, leave the dependent instruction\n  // unattached. This happens for out-of-line redeclarations of members of\n  // dependent scopes:\n  //\n  //   class A(T:! type) {\n  //     fn F();\n  //   }\n  //   // Has generic type and constant value, but no generic region.\n  //   fn A(T:! type).F() {}\n  //\n  // TODO: Copy the attached type and constant value from the previous\n  // declaration in this case instead of attempting to attach the new\n  // declaration to a generic region that we're no longer within.\n  if (context.generic_region_stack().Empty()) {\n    // This should only happen for `*Decl` instructions, never for template\n    // actions.\n    CARBON_CHECK(!dep_kind.HasAnyOf(DependentInstKind::Template));\n    return;\n  }\n\n  context.generic_region_stack().AddDependentInst(dependent_inst.inst_id);\n\n  // If the type is symbolic, replace it with a type specific to this generic.\n  if (dep_kind.HasAnyOf(DependentInstKind::SymbolicType)) {\n    auto inst = context.insts().Get(inst_id);\n    auto type_id = AddGenericTypeToEvalBlock(context, SemIR::LocId(inst_id),\n                                             inst.type_id());\n    // TODO: Eventually, completeness requirements should be modeled as\n    // constraints on the generic rather than properties of the type. For now,\n    // require the transformed type to be complete if the original was.\n    if (context.types().IsComplete(inst.type_id())) {\n      CompleteTypeOrCheckFail(context, type_id);\n    }\n    inst.SetType(type_id);\n    context.sem_ir().insts().Set(inst_id, inst);\n  }\n\n  // If the instruction has a symbolic constant value, then make a note that\n  // we'll need to evaluate this instruction when forming the specific. Update\n  // the constant value of the instruction to refer to the result of that\n  // eventual evaluation.\n  if (dep_kind.HasAnyOf(DependentInstKind::SymbolicConstant)) {\n    // Update the constant value to refer to this generic.\n    context.constant_values().Set(\n        inst_id, AddGenericConstantToEvalBlock(context, inst_id));\n  }\n\n  // If the instruction is a template action, add it directly to this position\n  // in the eval block.\n  if (dep_kind.HasAnyOf(DependentInstKind::Template)) {\n    AddTemplateActionToEvalBlock(context, inst_id);\n  }\n}\n\n// Builds and returns a block of instructions whose constant values need to be\n// evaluated in order to resolve a generic to a specific.\nstatic auto MakeGenericEvalBlock(Context& context) -> SemIR::InstBlockId {\n  return context.inst_blocks().Add(\n      context.generic_region_stack().PeekEvalBlock());\n}\n\n// Builds and returns an eval block, given the list of canonical symbolic\n// constants that the instructions in the eval block should produce. This is\n// used when importing a generic.\nauto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id,\n                             SemIR::GenericInstIndex::Region region,\n                             llvm::ArrayRef<SemIR::InstId> const_ids)\n    -> SemIR::InstBlockId {\n  context.generic_region_stack().Push(\n      {.generic_id = generic_id, .region = region});\n\n  auto& constants_in_generic =\n      context.generic_region_stack().PeekConstantsInGenericMap();\n\n  // For the definition region, populate constants from the declaration.\n  if (region == SemIR::GenericInstIndex::Definition) {\n    PopulateConstantsFromDeclaration(context, generic_id, constants_in_generic);\n  }\n\n  constants_in_generic.GrowForInsertCount(const_ids.size());\n  for (auto [i, inst_id] : llvm::enumerate(const_ids)) {\n    // Build a constant in the inst block.\n    AddGenericConstantToEvalBlock(context, inst_id);\n    CARBON_CHECK(context.generic_region_stack().PeekEvalBlock().size() == i + 1,\n                 \"Produced {0} instructions when importing {1}\",\n                 (context.generic_region_stack().PeekEvalBlock().size() - i),\n                 context.insts().Get(inst_id));\n  }\n\n  auto eval_block_id = MakeGenericEvalBlock(context);\n  context.generic_region_stack().Pop();\n  return eval_block_id;\n}\n\nauto StartGenericDecl(Context& context) -> void {\n  context.generic_region_stack().Push(\n      {.generic_id = SemIR::GenericId::None,\n       .region = SemIR::GenericInstIndex::Declaration});\n}\n\nauto StartGenericDefinition(Context& context, SemIR::GenericId generic_id)\n    -> void {\n  // Push a generic region even if we don't have a generic_id. We might still\n  // have locally-introduced generic parameters to track:\n  //\n  // fn F() {\n  //   let T:! type = i32;\n  //   var x: T;\n  // }\n  context.generic_region_stack().Push(\n      {.generic_id = generic_id,\n       .region = SemIR::GenericInstIndex::Definition});\n  if (generic_id.has_value()) {\n    PopulateConstantsFromDeclaration(\n        context, generic_id,\n        context.generic_region_stack().PeekConstantsInGenericMap());\n  }\n}\n\nauto DiscardGenericDecl(Context& context) -> void {\n  // Unattach any types and constant values we might have created in the\n  // generic.\n  for (auto inst_id : context.generic_region_stack().PeekDependentInsts()) {\n    // Note that `Get` returns an instruction with an unattached type.\n    context.sem_ir().insts().Set(inst_id, context.insts().Get(inst_id));\n    // Note that `Get` returns an unattached constant.\n    context.constant_values().Set(inst_id,\n                                  context.constant_values().Get(inst_id));\n  }\n  // Note that we may leak a GenericId here, if one was allocated.\n  context.generic_region_stack().Pop();\n}\n\nauto BuildGeneric(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId {\n  auto all_bindings =\n      context.scope_stack().compile_time_binding_stack().PeekAllValues();\n\n  if (all_bindings.empty()) {\n    CARBON_CHECK(context.generic_region_stack().PeekEvalBlock().empty(),\n                 \"Have non-empty eval block {0} in declaration {1} but no \"\n                 \"compile time bindings are in scope.\",\n                 context.insts().Get(\n                     context.generic_region_stack().PeekEvalBlock().front()),\n                 context.insts().Get(decl_id));\n    DiscardGenericDecl(context);\n    return SemIR::GenericId::None;\n  }\n\n  // Build the new Generic object. Note that we intentionally do not hold a\n  // persistent reference to it throughout this function, because the `generics`\n  // collection can have items added to it by import resolution while we are\n  // building this generic.\n  auto bindings_id = context.inst_blocks().Add(all_bindings);\n\n  SemIR::Generic generic = {.decl_id = decl_id,\n                            .bindings_id = bindings_id,\n                            .self_specific_id = SemIR::SpecificId::None};\n\n  // Get the generic ID, or allocate one now if we don't have one yet. That\n  // could happen if the eval block is empty.\n  auto generic_id =\n      context.generic_region_stack().PeekPendingGeneric().generic_id;\n  if (!generic_id.has_value()) {\n    CARBON_CHECK(context.generic_region_stack().PeekEvalBlock().empty(),\n                 \"Non-empty eval block but didn't yet allocate a GenericId\");\n    generic_id = context.generics().Add(generic);\n    context.generic_region_stack().SetPendingGenericId(generic_id);\n  } else {\n    CARBON_CHECK(!context.generics().Get(generic_id).decl_id.has_value(),\n                 \"Built generic {0} twice\", generic_id);\n    context.generics().Get(generic_id) = generic;\n  }\n\n  auto self_specific_id = MakeSelfSpecificId(context, generic_id);\n  context.generics().Get(generic_id).self_specific_id = self_specific_id;\n  return generic_id;\n}\n\nauto FinishGenericDecl(Context& context, SemIR::LocId loc_id,\n                       SemIR::GenericId generic_id) -> void {\n  if (!generic_id.has_value()) {\n    return;\n  }\n  auto decl_block_id = MakeGenericEvalBlock(context);\n  context.generic_region_stack().Pop();\n  context.generics().Get(generic_id).decl_block_id = decl_block_id;\n\n  ResolveSpecificDecl(context, loc_id,\n                      context.generics().GetSelfSpecific(generic_id));\n}\n\nauto BuildGenericDecl(Context& context, SemIR::InstId decl_id)\n    -> SemIR::GenericId {\n  SemIR::GenericId generic_id = BuildGeneric(context, decl_id);\n  if (generic_id.has_value()) {\n    FinishGenericDecl(context, SemIR::LocId(decl_id), generic_id);\n  }\n  return generic_id;\n}\n\n// Returns the first difference between the two given eval blocks.\nstatic auto FirstDifferenceBetweenEvalBlocks(\n    Context& context, llvm::ArrayRef<SemIR::InstId> old_eval_block,\n    llvm::ArrayRef<SemIR::InstId> new_eval_block)\n    -> std::pair<SemIR::InstId, SemIR::InstId> {\n  // Check each element of the eval block computes the same unattached constant.\n  for (auto [old_inst_id, new_inst_id] :\n       llvm::zip(old_eval_block, new_eval_block)) {\n    auto old_const_id = context.constant_values().Get(old_inst_id);\n    auto new_const_id = context.constant_values().Get(new_inst_id);\n    if (old_const_id != new_const_id) {\n      if (old_const_id.is_symbolic() && new_const_id.is_symbolic() &&\n          context.constant_values().GetDependence(old_const_id) ==\n              SemIR::ConstantDependence::Template &&\n          context.constant_values().GetDependence(new_const_id) ==\n              SemIR::ConstantDependence::Template &&\n          context.insts().Get(old_inst_id).kind() ==\n              context.insts().Get(new_inst_id).kind()) {\n        // TODO: We don't have a good mechanism to compare template constants\n        // because they canonicalize to themselves, so just assume this is OK.\n        continue;\n      }\n\n      // These constant values differ unexpectedly.\n      return {old_inst_id, new_inst_id};\n    }\n  }\n\n  if (old_eval_block.size() < new_eval_block.size()) {\n    return {SemIR::InstId::None, new_eval_block[old_eval_block.size()]};\n  }\n  if (old_eval_block.size() > new_eval_block.size()) {\n    return {old_eval_block[new_eval_block.size()], SemIR::InstId::None};\n  }\n\n  return {SemIR::InstId::None, SemIR::InstId::None};\n}\n\n// If `constant_id` refers to a symbolic constant within the declaration region\n// of `generic_id`, remap it to refer to the constant value of the corresponding\n// element in the given eval block. Otherwise returns the ID unchanged.\nstatic auto ReattachConstant(Context& context, SemIR::GenericId generic_id,\n                             llvm::ArrayRef<SemIR::InstId> eval_block,\n                             SemIR::ConstantId constant_id)\n    -> SemIR::ConstantId {\n  if (!constant_id.has_value() || !constant_id.is_symbolic()) {\n    return constant_id;\n  }\n\n  auto& symbolic_const =\n      context.constant_values().GetSymbolicConstant(constant_id);\n  if (symbolic_const.generic_id != generic_id) {\n    // Constant doesn't refer into this generic.\n    return constant_id;\n  }\n\n  CARBON_CHECK(\n      symbolic_const.index.region() == SemIR::GenericInstIndex::Declaration,\n      \"Definition region of redeclaration should not be referenced\");\n  return context.constant_values().GetAttached(\n      eval_block[symbolic_const.index.index()]);\n}\n\n// Same as `ReattachConstant` but for a type.\nstatic auto ReattachType(Context& context, SemIR::GenericId generic_id,\n                         llvm::ArrayRef<SemIR::InstId> eval_block,\n                         SemIR::TypeId type_id) -> SemIR::TypeId {\n  return context.types().GetTypeIdForTypeConstantId(ReattachConstant(\n      context, generic_id, eval_block, context.types().GetConstantId(type_id)));\n}\n\nauto FinishGenericRedecl(Context& context, SemIR::GenericId generic_id)\n    -> void {\n  if (!generic_id.has_value()) {\n    DiscardGenericDecl(context);\n    return;\n  }\n\n  // Find the old and new eval blocks.\n  auto old_eval_block_id =\n      context.generics()\n          .Get(generic_id)\n          .GetEvalBlock(SemIR::GenericInstIndex::Declaration);\n  CARBON_CHECK(old_eval_block_id.has_value(),\n               \"Old generic is not fully declared\");\n\n  auto old_eval_block = context.inst_blocks().Get(old_eval_block_id);\n  auto new_eval_block = context.generic_region_stack().PeekEvalBlock();\n\n  // Check the eval blocks are computing the same constants in the same order.\n  // This should always be the case because we have already verified they have\n  // the same parse tree, and the poisoning rules mean that all entities they\n  // refer to are also the same.\n  //\n  // Note that it's OK if the first difference is that an old instruction has no\n  // corresponding new instruction; we wouldn't have used that anyway. This\n  // happens for `ImplDecl`, for which the witness is included in the eval block\n  // of the first declaration.\n  if (auto [old_inst_id, new_inst_id] = FirstDifferenceBetweenEvalBlocks(\n          context, old_eval_block, new_eval_block);\n      new_inst_id.has_value()) {\n    // This shouldn't be possible: we should have already checked that the\n    // syntax of the redeclaration matches the prior declaration, and none of\n    // the name lookups or semantic checks should be allowed to differ between\n    // the two declarations, so we should have built the same eval block as in\n    // the prior declaration.\n    //\n    // However, that isn't a strong enough invariant that it seems appropriate\n    // to CHECK-fail here, so we produce a diagnostic with context.TODO()\n    // instead.\n    //\n    // TODO: Add something like context.UNEXPECTED() instead of using\n    // context.TODO() here because there's not really anything to do.\n    context.TODO(new_inst_id,\n                 \"generic redeclaration differs from previous declaration\");\n    if (old_inst_id.has_value()) {\n      context.TODO(old_inst_id, \"instruction in previous declaration\");\n    }\n    DiscardGenericDecl(context);\n    return;\n  }\n\n  auto redecl_generic_id =\n      context.generic_region_stack().PeekPendingGeneric().generic_id;\n\n  // Reattach any instructions that depend on the redeclaration to instead refer\n  // to the original.\n  for (auto inst_id : context.generic_region_stack().PeekDependentInsts()) {\n    // Reattach the type.\n    auto inst = context.insts().GetWithAttachedType(inst_id);\n    inst.SetType(ReattachType(context, redecl_generic_id, old_eval_block,\n                              inst.type_id()));\n    context.sem_ir().insts().Set(inst_id, inst);\n\n    // Reattach the constant value.\n    context.constant_values().Set(\n        inst_id,\n        ReattachConstant(context, redecl_generic_id, old_eval_block,\n                         context.constant_values().GetAttached(inst_id)));\n  }\n  context.generic_region_stack().Pop();\n}\n\nauto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id)\n    -> void {\n  if (!generic_id.has_value()) {\n    DiscardGenericDecl(context);\n    return;\n  }\n\n  auto definition_block_id = MakeGenericEvalBlock(context);\n  context.generic_region_stack().Pop();\n  context.generics().Get(generic_id).definition_block_id = definition_block_id;\n}\n\nauto ResolveSpecificDecl(Context& context, SemIR::LocId loc_id,\n                         SemIR::SpecificId specific_id) -> void {\n  // If this is the first time we've formed this specific, evaluate its decl\n  // block to form information about the specific.\n  auto& specific = context.specifics().Get(specific_id);\n  if (!specific.decl_block_id.has_value()) {\n    // Set a placeholder value as the decl block ID so we won't attempt to\n    // recursively resolve the same specific.\n    specific.decl_block_id = SemIR::InstBlockId::Empty;\n\n    // TODO: Store in the specific whether the declaration contains any\n    // ErrorInst values.\n    specific.decl_block_id =\n        TryEvalBlockForSpecific(context, loc_id, specific_id,\n                                SemIR::GenericInstIndex::Region::Declaration);\n  }\n}\n\nauto MakeSpecific(Context& context, SemIR::LocId loc_id,\n                  SemIR::GenericId generic_id, SemIR::InstBlockId args_id)\n    -> SemIR::SpecificId {\n  auto specific_id = context.specifics().GetOrAdd(generic_id, args_id);\n  ResolveSpecificDecl(context, loc_id, specific_id);\n  return specific_id;\n}\n\nauto MakeSpecific(Context& context, SemIR::LocId loc_id,\n                  SemIR::GenericId generic_id,\n                  llvm::ArrayRef<SemIR::InstId> args) -> SemIR::SpecificId {\n  auto args_id = context.inst_blocks().AddCanonical(args);\n  return MakeSpecific(context, loc_id, generic_id, args_id);\n}\n\nstatic auto MakeSelfSpecificId(Context& context, SemIR::GenericId generic_id)\n    -> SemIR::SpecificId {\n  if (!generic_id.has_value()) {\n    return SemIR::SpecificId::None;\n  }\n\n  auto& generic = context.generics().Get(generic_id);\n  auto args = context.inst_blocks().Get(generic.bindings_id);\n\n  // Form a canonical argument list for the generic.\n  llvm::SmallVector<SemIR::InstId> arg_ids;\n  arg_ids.reserve(args.size());\n  for (auto arg_id : args) {\n    arg_ids.push_back(context.constant_values().GetConstantInstId(arg_id));\n  }\n  auto args_id = context.inst_blocks().AddCanonical(arg_ids);\n  return context.specifics().GetOrAdd(generic_id, args_id);\n}\n\nauto MakeSelfSpecific(Context& context, SemIR::LocId loc_id,\n                      SemIR::GenericId generic_id) -> SemIR::SpecificId {\n  // Build a corresponding specific.\n  SemIR::SpecificId specific_id = MakeSelfSpecificId(context, generic_id);\n  // TODO: This could be made more efficient. We don't need to perform\n  // substitution here; we know we want identity mappings for all constants and\n  // types. We could also consider not storing the mapping at all in this case.\n  ResolveSpecificDecl(context, loc_id, specific_id);\n  return specific_id;\n}\n\nauto ResolveSpecificDefinition(Context& context, SemIR::LocId loc_id,\n                               SemIR::SpecificId specific_id) -> bool {\n  // TODO: Handle recursive resolution of the same generic definition.\n  auto& specific = context.specifics().Get(specific_id);\n  auto generic_id = specific.generic_id;\n  CARBON_CHECK(generic_id.has_value(), \"Specific with no generic ID\");\n\n  if (!specific.definition_block_id.has_value()) {\n    // Evaluate the eval block for the definition of the generic.\n    auto& generic = context.generics().Get(generic_id);\n    CARBON_CHECK(generic.decl_block_id.has_value(), \"missing declaration\");\n    if (!generic.definition_block_id.has_value()) {\n      // The generic is not defined yet.\n      return false;\n    }\n    // TODO: Store in the specific whether the definition contains any ErrorInst\n    // values.\n    specific.definition_block_id = TryEvalBlockForSpecific(\n        context, loc_id, specific_id, SemIR::GenericInstIndex::Definition);\n  }\n  return true;\n}\n\nauto DiagnoseIfGenericMissingExplicitParameters(\n    Context& context, const SemIR::EntityWithParamsBase& entity_base) -> void {\n  if (!entity_base.implicit_param_patterns_id.has_value() ||\n      entity_base.param_patterns_id.has_value()) {\n    return;\n  }\n\n  CARBON_DIAGNOSTIC(GenericMissingExplicitParameters, Error,\n                    \"expected explicit parameters after implicit parameters\");\n  context.emitter().Emit(entity_base.last_param_node_id,\n                         GenericMissingExplicitParameters);\n}\n\nstatic auto ValidateGenericWithoutAndWithSelfMatch(\n    Context& context, SemIR::GenericId generic_without_self_id,\n    SemIR::GenericId generic_with_self_id,\n    SemIR::SpecificId specific_without_self_id) -> void {\n  CARBON_CHECK(\n      generic_without_self_id.has_value() ==\n          specific_without_self_id.has_value(),\n      \"Have a generic-without-self {0} but no specific-without-self {1} or \"\n      \"vice-versa\",\n      generic_without_self_id, specific_without_self_id);\n\n  CARBON_CHECK(\n      generic_with_self_id.has_value(),\n      \"Missing a generic ID for generic-with-self that should always exist.\");\n  const auto& generic_with_self = context.generics().Get(generic_with_self_id);\n\n  auto generic_with_self_decl = context.insts().Get(generic_with_self.decl_id);\n  CARBON_CHECK(\n      (generic_with_self_decl.IsOneOf<SemIR::InterfaceWithSelfDecl,\n                                      SemIR::NamedConstraintWithSelfDecl>()),\n      \"generic-with-self {0} should be a generic for an \"\n      \"InterfaceWithSelfDecl or NamedConstraintWithSelfDecl, found {1}\",\n      generic_with_self, generic_with_self_decl);\n\n  if (!generic_without_self_id.has_value()) {\n    return;\n  }\n\n  const auto& generic_without_self =\n      context.generics().Get(generic_without_self_id);\n  const auto& specific_without_self =\n      context.specifics().Get(specific_without_self_id);\n\n  CARBON_CHECK(specific_without_self.generic_id == generic_without_self_id,\n               \"specific-without-self {0} is not a specific for the \"\n               \"generic-without-self {1}\",\n               specific_without_self, generic_without_self);\n\n  auto generic_without_self_decl =\n      context.insts().Get(generic_without_self.decl_id);\n\n  CARBON_KIND_SWITCH(generic_without_self_decl) {\n    case CARBON_KIND(SemIR::InterfaceDecl without_self_decl): {\n      auto with_self_decl =\n          generic_with_self_decl.As<SemIR::InterfaceWithSelfDecl>();\n      CARBON_CHECK(\n          without_self_decl.interface_id == with_self_decl.interface_id,\n          \"Found generic-without-self for interface {0}, and generic-with-self \"\n          \"for interface {1}; expected the same interface for both\",\n          context.interfaces().Get(without_self_decl.interface_id),\n          context.interfaces().Get(with_self_decl.interface_id));\n      break;\n    }\n    case CARBON_KIND(SemIR::NamedConstraintDecl without_self_decl): {\n      auto with_self_decl =\n          generic_with_self_decl.As<SemIR::NamedConstraintWithSelfDecl>();\n      CARBON_CHECK(\n          without_self_decl.named_constraint_id ==\n              with_self_decl.named_constraint_id,\n          \"Found generic-without-self for constraint {0}, and \"\n          \"generic-with-self for named constraint {1}; expected the same named \"\n          \"constraint for both\",\n          context.named_constraints().Get(\n              without_self_decl.named_constraint_id),\n          context.named_constraints().Get(with_self_decl.named_constraint_id));\n      break;\n    }\n    default:\n      CARBON_FATAL(\n          \"generic-without-self {0} should be a generic for an InterfaceDecl \"\n          \"or NamedConstraintDecl, found {1}\",\n          generic_without_self, generic_without_self_decl);\n  }\n}\n\nauto MakeSpecificWithInnerSelf(Context& context, SemIR::LocId loc_id,\n                               SemIR::GenericId generic_without_self_id,\n                               SemIR::GenericId generic_with_self_id,\n                               SemIR::SpecificId specific_without_self_id,\n                               SemIR::ConstantId self_facet)\n    -> SemIR::SpecificId {\n  ValidateGenericWithoutAndWithSelfMatch(context, generic_without_self_id,\n                                         generic_with_self_id,\n                                         specific_without_self_id);\n\n  auto outer_args_id =\n      context.specifics().GetArgsOrEmpty(specific_without_self_id);\n  auto outer_args = context.inst_blocks().Get(outer_args_id);\n\n  llvm::SmallVector<SemIR::InstId> args;\n  args.reserve(outer_args.size() + 1);\n  llvm::append_range(args, outer_args);\n\n  if (self_facet == SemIR::ErrorInst::ConstantId) {\n    args.push_back(SemIR::ErrorInst::InstId);\n  } else {\n    auto self_facet_inst_id = context.constant_values().GetInstId(self_facet);\n    CARBON_CHECK(context.types().Is<SemIR::FacetType>(\n        context.insts().Get(self_facet_inst_id).type_id()));\n    args.push_back(self_facet_inst_id);\n  }\n\n  auto specific_id = MakeSpecific(context, loc_id, generic_with_self_id, args);\n  ResolveSpecificDefinition(context, loc_id, specific_id);\n  return specific_id;\n}\n\nauto CopySpecificToGeneric(Context& context, SemIR::LocId loc_id,\n                           SemIR::SpecificId specific_id,\n                           SemIR::GenericId target_generic_id)\n    -> SemIR::SpecificId {\n  if (!specific_id.has_value()) {\n    const auto& target_generic = context.generics().Get(target_generic_id);\n    auto target_bindings =\n        context.inst_blocks().Get(target_generic.bindings_id);\n    CARBON_CHECK(target_bindings.empty());\n    return SemIR::SpecificId::None;\n  }\n\n  const auto& specific = context.specifics().Get(specific_id);\n  auto source_generic_id = specific.generic_id;\n\n  const auto& source_generic = context.generics().Get(source_generic_id);\n  const auto& target_generic = context.generics().Get(target_generic_id);\n  auto source_bindings = context.inst_blocks().Get(source_generic.bindings_id);\n  auto target_bindings = context.inst_blocks().Get(target_generic.bindings_id);\n  for (auto [source, target] :\n       llvm::zip_equal(source_bindings, target_bindings)) {\n    CARBON_CHECK(context.constant_values().Get(source) ==\n                 context.constant_values().Get(target));\n  }\n\n  auto args_id = context.specifics().GetArgsOrEmpty(specific_id);\n  return MakeSpecific(context, loc_id, target_generic_id, args_id);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/generic.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_GENERIC_H_\n#define CARBON_TOOLCHAIN_CHECK_GENERIC_H_\n\n#include \"common/enum_mask_base.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/entity_with_params_base.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Start processing a declaration or definition that might be a generic entity.\nauto StartGenericDecl(Context& context) -> void;\n\n// Start processing a declaration or definition that might be a generic entity.\nauto StartGenericDefinition(Context& context, SemIR::GenericId generic_id)\n    -> void;\n\n#define CARBON_DEPENDENT_INST_KIND(X)                                       \\\n  /* The type of the instruction depends on a checked generic parameter. */ \\\n  X(SymbolicType)                                                           \\\n  /* The constant value of the instruction depends on a checked generic     \\\n   * parameter. */                                                          \\\n  X(SymbolicConstant)                                                       \\\n  X(Template)\n\nCARBON_DEFINE_RAW_ENUM_MASK(DependentInstKind, uint8_t) {\n  CARBON_DEPENDENT_INST_KIND(CARBON_RAW_ENUM_MASK_ENUMERATOR)\n};\n\n// Represents a set of keyword modifiers, using a separate bit per modifier.\nclass DependentInstKind : public CARBON_ENUM_MASK_BASE(DependentInstKind) {\n public:\n  CARBON_DEPENDENT_INST_KIND(CARBON_ENUM_MASK_CONSTANT_DECL)\n};\n\n#define CARBON_DEPENDENT_INST_KIND_WITH_TYPE(X) \\\n  CARBON_ENUM_MASK_CONSTANT_DEFINITION(DependentInstKind, X)\nCARBON_DEPENDENT_INST_KIND(CARBON_DEPENDENT_INST_KIND_WITH_TYPE)\n#undef CARBON_DEPENDENT_INST_KIND_WITH_TYPE\n\n// An instruction that depends on a generic parameter in some way.\nstruct DependentInst {\n  SemIR::InstId inst_id;\n  DependentInstKind kind;\n};\n\n// Attach a dependent instruction to the current generic, updating its type and\n// constant value as necessary.\nauto AttachDependentInstToCurrentGeneric(Context& context,\n                                         DependentInst dependent_inst) -> void;\n\n// Discard the information about the current generic entity. This should be\n// called instead of `FinishGenericDecl` if the corresponding `Generic` object\n// would not actually be used, or when recovering from an error.\nauto DiscardGenericDecl(Context& context) -> void;\n\n// Finish processing a potentially generic declaration and produce a\n// corresponding generic object. Returns SemIR::GenericId::None if this\n// declaration is not actually generic.\nauto BuildGeneric(Context& context, SemIR::InstId decl_id) -> SemIR::GenericId;\n\n// Builds eval block for the declaration.\nauto FinishGenericDecl(Context& context, SemIR::LocId loc_id,\n                       SemIR::GenericId generic_id) -> void;\n\n// BuildGeneric() and FinishGenericDecl() combined. Normally you would call this\n// function unless the caller has work to do between the two steps.\nauto BuildGenericDecl(Context& context, SemIR::InstId decl_id)\n    -> SemIR::GenericId;\n\n// Merge a redeclaration of an entity that might be a generic into the original\n// declaration.\nauto FinishGenericRedecl(Context& context, SemIR::GenericId generic_id) -> void;\n\n// Finish processing a potentially generic definition.\nauto FinishGenericDefinition(Context& context, SemIR::GenericId generic_id)\n    -> void;\n\n// Builds and returns an eval block, given the list of canonical symbolic\n// constants that the instructions in the eval block should produce. This is\n// used when importing a generic.\nauto RebuildGenericEvalBlock(Context& context, SemIR::GenericId generic_id,\n                             SemIR::GenericInstIndex::Region region,\n                             llvm::ArrayRef<SemIR::InstId> const_ids)\n    -> SemIR::InstBlockId;\n\n// Builds a new specific with a given argument list, or finds an existing one if\n// this generic has already been referenced with these arguments. Performs\n// substitution into the declaration, but not the definition, of the generic.\nauto MakeSpecific(Context& context, SemIR::LocId loc_id,\n                  SemIR::GenericId generic_id,\n                  llvm::ArrayRef<SemIR::InstId> args) -> SemIR::SpecificId;\n\n// Builds a new specific or finds an existing one in the case where the argument\n// list has already been converted into an instruction block. `args_id` should\n// be a canonical instruction block referring to constants.\nauto MakeSpecific(Context& context, SemIR::LocId loc_id,\n                  SemIR::GenericId generic_id, SemIR::InstBlockId args_id)\n    -> SemIR::SpecificId;\n\n// Builds the specific that describes how the generic should refer to itself.\n// For example, for a generic `G(T:! type)`, this is the specific `G(T)`. If\n// `generic_id` is `None`, returns `None`.\nauto MakeSelfSpecific(Context& context, SemIR::LocId loc_id,\n                      SemIR::GenericId generic_id) -> SemIR::SpecificId;\n\n// Resolve the declaration of the given specific, by evaluating the eval block\n// of the corresponding generic and storing a corresponding value block in the\n// specific.\nauto ResolveSpecificDecl(Context& context, SemIR::LocId loc_id,\n                         SemIR::SpecificId specific_id) -> void;\n\n// Attempts to resolve the definition of the given specific, by evaluating the\n// eval block of the corresponding generic and storing a corresponding value\n// block in the specific. Returns false if a definition is not available.\nauto ResolveSpecificDefinition(Context& context, SemIR::LocId loc_id,\n                               SemIR::SpecificId specific_id) -> bool;\n\n// Diagnoses if an entity has implicit parameters, indicating it's generic, but\n// is missing explicit parameters.\nauto DiagnoseIfGenericMissingExplicitParameters(\n    Context& context, const SemIR::EntityWithParamsBase& entity_base) -> void;\n\n// Given a generic and specific for an entity, construct the specific for the\n// inner generic-with-self.\n//\n// Interfaces and named constraints each have two generics.\n// * A regular outward facing generic which includes just the generic bindings\n//   as written in the declaration.\n// * An inner generic-with-self which includes an additional generic binding of\n//   the `Self` facet value. Associated entities are located inside this inner\n//   generic-with-self.\n//\n// This function moves from a specific for the outer generic to a specific for\n// the inner generic-with-self. An entity which has no generic bindings will\n// have no outer generic-without-self and thus no specific-without-self, but\n// there is always an inner generic-with-self regardless, because of the\n// additional `Self` binding.\n//\n// If the generic-without-self has its definition completed, the resulting\n// specific will also. Note that during construction of an interface/constraint,\n// the definition cannot be complete yet.\n//\n// TODO: This should take a `diagnoser` parameter which is passed through to\n// MakeSpecific() and TryEvalBlockForSpecific(), so that monomorphization errors\n// get diagnosed to the correct semantic operation, instead of just to specific\n// instantiation.\nauto MakeSpecificWithInnerSelf(Context& context, SemIR::LocId loc_id,\n                               SemIR::GenericId generic_without_self_id,\n                               SemIR::GenericId generic_with_self_id,\n                               SemIR::SpecificId specific_without_self_id,\n                               SemIR::ConstantId self_facet)\n    -> SemIR::SpecificId;\n\n// Copy the arguments of a specific into the context of another generic. The\n// target generic must have the exact same bindings as the specific's generic.\n//\n// TODO: This should take a `diagnoser` parameter which is passed through to\n// MakeSpecific() and TryEvalBlockForSpecific(), so that monomorphization errors\n// get diagnosed to the correct semantic operation, instead of just to specific\n// instantiation.\nauto CopySpecificToGeneric(Context& context, SemIR::LocId loc_id,\n                           SemIR::SpecificId specific_id,\n                           SemIR::GenericId target_generic_id)\n    -> SemIR::SpecificId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_GENERIC_H_\n"
  },
  {
    "path": "toolchain/check/generic_region_stack.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/generic_region_stack.h\"\n\n#include \"common/vlog.h\"\n\nnamespace Carbon::Check {\n\nauto GenericRegionStack::Push(PendingGeneric generic) -> void {\n  CARBON_VLOG(\"GenericRegion Push: {0} {1}\\n\", generic.generic_id,\n              generic.region);\n  pending_generic_ids_.push_back(generic);\n  pending_eval_block_stack_.PushArray();\n  dependent_inst_stack_.PushArray();\n  constants_in_generic_stack_.emplace_back();\n}\n\nauto GenericRegionStack::Pop() -> void {\n  auto pending = pending_generic_ids_.pop_back_val();\n  CARBON_VLOG(\"GenericRegion Pop: {0} {1}\\n\", pending.generic_id,\n              pending.region);\n  pending_eval_block_stack_.PopArray();\n  dependent_inst_stack_.PopArray();\n  constants_in_generic_stack_.pop_back();\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/generic_region_stack.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_GENERIC_REGION_STACK_H_\n#define CARBON_TOOLCHAIN_CHECK_GENERIC_REGION_STACK_H_\n\n#include \"common/array_stack.h\"\n#include \"common/map.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// A map from an instruction ID representing a canonical symbolic constant to an\n// instruction within an eval block of the generic that computes the specific\n// value for that constant.\n//\n// We arbitrarily use a small size of 256 bytes for the map.\n// TODO: Determine a better number based on measurements.\nusing ConstantsInGenericMap = Map<SemIR::InstId, SemIR::InstId, 256>;\n\n// A stack of enclosing regions that might be declaring or defining a generic\n// entity. In such a region, we track the generic constructs that are used, such\n// as symbolic constants and types, and instructions that depend on a template\n// parameter.\n//\n// We split a generic into two regions -- declaration and definition -- because\n// these are in general introduced separately, and substituted into separately.\n// For example, for `class C(T:! type, N:! T) { var x: T; }`, a use such as\n// `C(i32, 0)*` substitutes into just the declaration, whereas a use such as\n// `var x: C(i32, 0) = {.x = 0};` also substitutes into the definition.\nclass GenericRegionStack {\n public:\n  explicit GenericRegionStack(llvm::raw_ostream* vlog_stream)\n      : vlog_stream_(vlog_stream) {\n    // Reserve a large enough stack that we typically won't need to reallocate.\n    constants_in_generic_stack_.reserve(4);\n  }\n\n  struct PendingGeneric {\n    // The generic ID. May not have a value if no ID has been assigned yet.\n    SemIR::GenericId generic_id;\n    // The region of the generic that is being processed.\n    SemIR::GenericInstIndex::Region region;\n  };\n\n  // Pushes a region that might be declaring or defining a generic.\n  auto Push(PendingGeneric generic) -> void;\n\n  // Pops a generic region.\n  auto Pop() -> void;\n\n  // Returns whether the stack is empty.\n  auto Empty() const -> bool { return pending_generic_ids_.empty(); }\n\n  // Sets the GenericId for the currently pending generic, once one has been\n  // allocated.\n  auto SetPendingGenericId(SemIR::GenericId generic_id) -> void {\n    CARBON_CHECK(!pending_generic_ids_.back().generic_id.has_value(),\n                 \"Already have a GenericId for the pending generic\");\n    pending_generic_ids_.back().generic_id = generic_id;\n  }\n\n  // Adds an instruction to the list of instructions whose type or value depends\n  // on something in the current pending generic.\n  auto AddDependentInst(SemIR::InstId inst_id) -> void {\n    CARBON_CHECK(!Empty());\n    dependent_inst_stack_.AppendToTop(inst_id);\n  }\n\n  // Adds an instruction to the eval block for the current pending generic.\n  auto AddInstToEvalBlock(SemIR::InstId inst_id) -> void {\n    CARBON_CHECK(!Empty());\n    pending_eval_block_stack_.AppendToTop(inst_id);\n  }\n\n  // Returns the current pending generic.\n  auto PeekPendingGeneric() const -> PendingGeneric {\n    CARBON_CHECK(!Empty());\n    return pending_generic_ids_.back();\n  }\n\n  // Returns the list of dependent instructions in the current generic region.\n  auto PeekDependentInsts() -> llvm::ArrayRef<SemIR::InstId> {\n    CARBON_CHECK(!Empty());\n    return dependent_inst_stack_.PeekArray();\n  }\n\n  // Returns the contents of the eval block for the current generic region.\n  auto PeekEvalBlock() -> llvm::ArrayRef<SemIR::InstId> {\n    CARBON_CHECK(!Empty());\n    return pending_eval_block_stack_.PeekArray();\n  }\n\n  // Returns the mapping from abstract constant instructions to eval block\n  // instructions for the current generic.\n  auto PeekConstantsInGenericMap() -> ConstantsInGenericMap& {\n    CARBON_CHECK(!Empty());\n    return constants_in_generic_stack_.back();\n  }\n\n  // Runs verification that the processing cleanly finished.\n  auto VerifyOnFinish() const -> void {\n    CARBON_CHECK(pending_generic_ids_.empty(),\n                 \"pending_generic_ids_ still has {0} entries\",\n                 pending_generic_ids_.size());\n  }\n\n private:\n  // Whether to print verbose output.\n  llvm::raw_ostream* vlog_stream_;\n\n  // The IDs of pending generics.\n  llvm::SmallVector<PendingGeneric> pending_generic_ids_;\n\n  // Contents of eval blocks for pending generics.\n  ArrayStack<SemIR::InstId> pending_eval_block_stack_;\n\n  // Instructions that depend on the current generic.\n  ArrayStack<SemIR::InstId> dependent_inst_stack_;\n\n  // Mapping from constant InstIds to the corresponding InstIds in the eval\n  // blocks for each enclosing generic. We reserve this to a suitable size in\n  // the constructor.\n  llvm::SmallVector<ConstantsInGenericMap, 0> constants_in_generic_stack_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_GENERIC_REGION_STACK_H_\n"
  },
  {
    "path": "toolchain/check/global_init.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/global_init.h\"\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/inst.h\"\n\nnamespace Carbon::Check {\n\nauto GlobalInit::Resume() -> void {\n  context_->inst_block_stack().Push(block_id_, block_);\n}\n\nauto GlobalInit::Suspend() -> void {\n  // TODO: Consider splicing together blocks in order to avoid sizable copies\n  // here.\n  auto contents = context_->inst_block_stack().PeekCurrentBlockContents();\n  block_.assign(contents.begin(), contents.end());\n\n  block_id_ = context_->inst_block_stack().PeekOrAdd();\n  context_->inst_block_stack().PopAndDiscard();\n}\n\nauto GlobalInit::Finalize() -> void {\n  // __global_init is only added if there are initialization instructions.\n  if (block_.empty() && block_id_ == SemIR::InstBlockId::GlobalInit) {\n    return;\n  }\n\n  Resume();\n  AddInst<SemIR::Return>(*context_, Parse::NodeId::None, {});\n  // Pop the GlobalInit block here to finalize it.\n  context_->inst_block_stack().Pop();\n\n  auto name_id = context_->sem_ir().identifiers().Add(\"__global_init\");\n  context_->sem_ir().set_global_ctor_id(context_->sem_ir().functions().Add(\n      {{.name_id = SemIR::NameId::ForIdentifier(name_id),\n        .parent_scope_id = SemIR::NameScopeId::Package,\n        .generic_id = SemIR::GenericId::None,\n        .first_param_node_id = Parse::NodeId::None,\n        .last_param_node_id = Parse::NodeId::None,\n        .pattern_block_id = SemIR::InstBlockId::Empty,\n        .implicit_param_patterns_id = SemIR::InstBlockId::None,\n        .param_patterns_id = SemIR::InstBlockId::Empty,\n        .is_extern = false,\n        .extern_library_id = SemIR::LibraryNameId::None,\n        .non_owning_decl_id = SemIR::InstId::None,\n        .first_owning_decl_id = SemIR::InstId::None},\n       {.call_param_patterns_id = SemIR::InstBlockId::Empty,\n        .call_params_id = SemIR::InstBlockId::Empty,\n        .call_param_ranges = SemIR::Function::CallParamIndexRanges::Empty,\n        .return_type_inst_id = SemIR::TypeInstId::None,\n        .return_form_inst_id = SemIR::InstId::None,\n        .return_patterns_id = SemIR::InstBlockId::None,\n        .body_block_ids = {SemIR::InstBlockId::GlobalInit}}}));\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/global_init.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_GLOBAL_INIT_H_\n#define CARBON_TOOLCHAIN_CHECK_GLOBAL_INIT_H_\n\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nclass Context;\n\n// Tracks state for global initialization. Handles should `Resume` when entering\n// an expression that's used for global init, and `Suspend` when the expression\n// is finished. Instructions in the middle will be tracked for the\n// `__global_init` function.\nclass GlobalInit {\n public:\n  explicit GlobalInit(Context* context) : context_(context) {}\n\n  // Resumes adding instructions to global init.\n  auto Resume() -> void;\n\n  // Suspends adding instructions to global init.\n  auto Suspend() -> void;\n\n  // Finalizes the global initialization state, creating `__global_init` if\n  // needed. Only called once at the end of checking.\n  auto Finalize() -> void;\n\n private:\n  // The associated context. Stored for convenience.\n  Context* context_;\n\n  // The currently suspended global init block. The value may change as a result\n  // of control flow in initialization.\n  SemIR::InstBlockId block_id_ = SemIR::InstBlockId::GlobalInit;\n\n  // The contents for the currently suspended global init block.\n  llvm::SmallVector<SemIR::InstId> block_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_GLOBAL_INIT_H_\n"
  },
  {
    "path": "toolchain/check/handle.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_HANDLE_H_\n#define CARBON_TOOLCHAIN_CHECK_HANDLE_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/deferred_definition_worklist.h\"\n#include \"toolchain/check/function.h\"\n#include \"toolchain/parse/node_ids.h\"\n\nnamespace Carbon::Check {\n\n// Parse node handlers. Returns false for unrecoverable errors.\n#define CARBON_PARSE_NODE_KIND(Name) \\\n  auto HandleParseNode(Context& context, Parse::Name##Id node_id) -> bool;\n#include \"toolchain/parse/node_kind.def\"\n\n// Handle suspending the definition of a function. This is used for inline\n// methods, which are processed out of the normal lexical order. This plus\n// HandleFunctionDefinitionResume carry out the same actions as\n// HandleFunctionDefinitionStart, except that the various context stacks are\n// cleared out in between.\nauto HandleFunctionDefinitionSuspend(Context& context,\n                                     Parse::FunctionDefinitionStartId node_id)\n    -> DeferredDefinitionWorklist::SuspendedFunction;\n\n// Handle resuming the definition of a function, after a previous suspension.\nauto HandleFunctionDefinitionResume(\n    Context& context, Parse::FunctionDefinitionStartId node_id,\n    DeferredDefinitionWorklist::SuspendedFunction&& suspended_fn) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_HANDLE_H_\n"
  },
  {
    "path": "toolchain/check/handle_alias.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::AliasIntroducerId /*node_id*/)\n    -> bool {\n  // Aliases can't be generic, but we might have parsed a generic parameter in\n  // their name, so enter a generic scope just in case.\n  StartGenericDecl(context);\n  // Optional modifiers and the name follow.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Alias>();\n  context.decl_name_stack().PushScopeAndStartName();\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::AliasInitializerId /*node_id*/) -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::AliasId /*node_id*/) -> bool {\n  auto [expr_node, expr_id] = context.node_stack().PopExprWithNodeId();\n\n  auto name_context = context.decl_name_stack().FinishName(\n      PopNameComponentWithoutParams(context, Lex::TokenKind::Alias));\n\n  DiscardGenericDecl(context);\n\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Alias>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access);\n\n  auto entity_name_id = context.entity_names().Add(\n      {.name_id = name_context.name_id_for_new_inst(),\n       .parent_scope_id = name_context.parent_scope_id});\n\n  auto alias_type_id = SemIR::TypeId::None;\n  auto alias_value_id = SemIR::InstId::None;\n  if (auto inst = context.insts().TryGetAs<SemIR::NameRef>(expr_id)) {\n    // Pass through name references, albeit changing the name in use.\n    alias_type_id = inst->type_id;\n    alias_value_id = inst->value_id;\n  } else if (auto inst =\n                 context.insts().TryGetAs<SemIR::TypeLiteral>(expr_id)) {\n    // Treat type literals such as `type` or `bool` like name references.\n    alias_type_id = inst->type_id;\n    alias_value_id = inst->value_id;\n  } else {\n    CARBON_DIAGNOSTIC(AliasRequiresNameRef, Error,\n                      \"alias initializer must be a name reference\");\n    context.emitter().Emit(expr_node, AliasRequiresNameRef);\n    alias_type_id = SemIR::ErrorInst::TypeId;\n    alias_value_id = SemIR::ErrorInst::InstId;\n  }\n  auto alias_id =\n      AddInst<SemIR::AliasBinding>(context, name_context.loc_id,\n                                   {.type_id = alias_type_id,\n                                    .entity_name_id = entity_name_id,\n                                    .value_id = alias_value_id});\n\n  // Add the name of the binding to the current scope.\n  context.decl_name_stack().PopScope();\n  context.decl_name_stack().AddNameOrDiagnose(\n      name_context, alias_id, introducer.modifier_set.GetAccessKind());\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_array.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/parse/node_kind.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::ArrayExprOpenParenId /*node_id*/) -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::ArrayExprKeywordId /*node_id*/) -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::ArrayExprCommaId /*node_id*/)\n    -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ArrayExprId node_id) -> bool {\n  auto bound_inst_id = context.node_stack().PopExpr();\n  auto [element_type_node_id, element_type_inst_id] =\n      context.node_stack().PopExprWithNodeId();\n\n  auto element_type =\n      ExprAsType(context, element_type_node_id, element_type_inst_id);\n\n  // The array bound must be a constant. Diagnose this prior to conversion\n  // because conversion to `IntLiteral` will produce a generic \"non-constant\n  // call to compile-time-only function\" error.\n  //\n  // TODO: Should we support runtime-phase bounds in cases such as:\n  //   comptime fn F(n: i32) -> type { return array(i32; n); }\n  if (!context.constant_values().Get(bound_inst_id).is_constant()) {\n    CARBON_DIAGNOSTIC(InvalidArrayExpr, Error, \"array bound is not a constant\");\n    context.emitter().Emit(bound_inst_id, InvalidArrayExpr);\n    context.node_stack().Push(node_id, SemIR::ErrorInst::InstId);\n    return true;\n  }\n\n  bound_inst_id = ConvertToValueOfType(\n      context, SemIR::LocId(bound_inst_id), bound_inst_id,\n      GetSingletonType(context, SemIR::IntLiteralType::TypeInstId));\n  AddInstAndPush<SemIR::ArrayType>(\n      context, node_id,\n      {.type_id = SemIR::TypeType::TypeId,\n       .bound_id = bound_inst_id,\n       .element_type_inst_id = element_type.inst_id});\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_binding_pattern.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <utility>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/interface.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/pattern.h\"\n#include \"toolchain/check/return.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/check/unused.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/pattern.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::UnderscoreNameId node_id)\n    -> bool {\n  context.node_stack().Push(node_id, SemIR::NameId::Underscore);\n  return true;\n}\n\n// Returns the `InstKind` corresponding to the pattern's `NodeKind`.\nstatic auto GetPatternInstKind(Parse::NodeKind node_kind, bool is_ref)\n    -> SemIR::InstKind {\n  switch (node_kind) {\n    case Parse::NodeKind::CompileTimeBindingPattern:\n      return SemIR::InstKind::SymbolicBindingPattern;\n    case Parse::NodeKind::LetBindingPattern:\n      return is_ref ? SemIR::InstKind::RefBindingPattern\n                    : SemIR::InstKind::ValueBindingPattern;\n    case Parse::NodeKind::VarBindingPattern:\n      return SemIR::InstKind::RefBindingPattern;\n    case Parse::NodeKind::FormBindingPattern:\n      return SemIR::InstKind::FormBindingPattern;\n    default:\n      CARBON_FATAL(\"Unexpected node kind: {0}\", node_kind);\n  }\n}\n\n// Returns true if a parameter is valid in the given `introducer_kind`.\nstatic auto IsValidParamForIntroducer(Context& context, Parse::NodeId node_id,\n                                      SemIR::NameId name_id,\n                                      Lex::TokenKind introducer_kind,\n                                      bool is_generic) -> bool {\n  switch (introducer_kind) {\n    case Lex::TokenKind::Fn: {\n      if (context.full_pattern_stack().CurrentKind() ==\n              FullPatternStack::Kind::ImplicitParamList &&\n          !(is_generic || name_id == SemIR::NameId::SelfValue)) {\n        CARBON_DIAGNOSTIC(\n            ImplictParamMustBeConstant, Error,\n            \"implicit parameters of functions must be constant or `self`\");\n        context.emitter().Emit(node_id, ImplictParamMustBeConstant);\n        return false;\n      }\n      // Parameters can have incomplete types in a function declaration, but not\n      // in a function definition. We don't know which kind we have here, so\n      // don't validate it.\n      return true;\n    }\n    case Lex::TokenKind::Choice:\n      if (context.scope_stack().PeekInstId().has_value()) {\n        // We are building a pattern for a choice alternative, not the\n        // choice type itself.\n\n        // Implicit param lists are prevented during parse.\n        CARBON_CHECK(context.full_pattern_stack().CurrentKind() !=\n                         FullPatternStack::Kind::ImplicitParamList,\n                     \"choice alternative with implicit parameters\");\n        // Don't fall through to the `Class` logic for choice alternatives.\n        return true;\n      }\n      [[fallthrough]];\n    case Lex::TokenKind::Class:\n    case Lex::TokenKind::Impl:\n    case Lex::TokenKind::Interface: {\n      if (name_id == SemIR::NameId::SelfValue) {\n        CARBON_DIAGNOSTIC(SelfParameterNotAllowed, Error,\n                          \"`self` parameter only allowed on functions\");\n        context.emitter().Emit(node_id, SelfParameterNotAllowed);\n        return false;\n      }\n      if (!is_generic) {\n        CARBON_DIAGNOSTIC(GenericParamMustBeConstant, Error,\n                          \"parameters of generic types must be constant\");\n        context.emitter().Emit(node_id, GenericParamMustBeConstant);\n        return false;\n      }\n      return true;\n    }\n    default:\n      return true;\n  }\n}\n\nnamespace {\n// Information about the expression in the type position of a binding pattern,\n// i.e. the position following the `:`/`:?`/`:!` separator. Note that this\n// expression may be interpreted as a type or a form, depending on the binding\n// kind.\nstruct BindingPatternTypeInfo {\n  // The parse node representing the expression.\n  Parse::AnyExprId node_id;\n  // The inst representing the converted value of that expression. For a `:?`\n  // binding the expression is converted to type `Core.Form`; otherwise it is\n  // converted to type `type`.\n  SemIR::InstId inst_id;\n  // For a `:?` binding this is the type component of the form denoted by\n  // `inst_id`. Otherwise this is the type denoted by `inst_id`.\n  SemIR::TypeId type_component_id;\n};\n}  // namespace\n\n// Handle the type position of a binding pattern.\nstatic auto HandleAnyBindingPatternType(Context& context,\n                                        Parse::NodeKind node_kind)\n    -> BindingPatternTypeInfo {\n  auto [node_id, original_inst_id] = context.node_stack().PopExprWithNodeId();\n\n  if (node_kind == Parse::FormBindingPattern::Kind) {\n    auto as_form = FormExprAsForm(context, node_id, original_inst_id);\n    return {.node_id = node_id,\n            .inst_id = as_form.form_inst_id,\n            .type_component_id = as_form.type_component_id};\n  } else {\n    auto as_type = ExprAsType(context, node_id, original_inst_id);\n    return {.node_id = node_id,\n            .inst_id = as_type.inst_id,\n            .type_component_id = as_type.type_id};\n  }\n}\n\n// TODO: make this function shorter by factoring pieces out.\nstatic auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,\n                                    Parse::NodeKind node_kind,\n                                    bool is_unused = false) -> bool {\n  auto type_expr = HandleAnyBindingPatternType(context, node_kind);\n  if (context.types()\n          .GetAsInst(type_expr.type_component_id)\n          .Is<SemIR::TypeComponentOf>()) {\n    return context.TODO(node_id, \"Support symbolic form bindings\");\n  }\n\n  SemIR::ExprRegionId type_expr_region_id =\n      EndSubpatternAsExpr(context, type_expr.inst_id);\n\n  // The name in a generic binding may be wrapped in `template`.\n  bool is_generic = node_kind == Parse::NodeKind::CompileTimeBindingPattern;\n  bool is_template =\n      context.node_stack()\n          .PopAndDiscardSoloNodeIdIf<Parse::NodeKind::TemplateBindingName>();\n  // A non-generic template binding is diagnosed by the parser.\n  is_template &= is_generic;\n\n  // The name in a runtime binding may be wrapped in `ref`.\n  bool is_ref =\n      context.node_stack()\n          .PopAndDiscardSoloNodeIdIf<Parse::NodeKind::RefBindingName>();\n\n  SemIR::InstKind pattern_inst_kind = GetPatternInstKind(node_kind, is_ref);\n\n  auto [name_node, name_id] = context.node_stack().PopNameWithNodeId();\n\n  const DeclIntroducerState& introducer =\n      context.decl_introducer_state_stack().innermost();\n\n  auto form_id = pattern_inst_kind == SemIR::FormBindingPattern::Kind\n                     ? context.constant_values().Get(type_expr.inst_id)\n                     : SemIR::ConstantId::None;\n\n  auto make_binding_pattern = [&]() -> SemIR::InstId {\n    // TODO: Eventually the name will need to support associations with other\n    // scopes, but right now we don't support qualified names here.\n    auto phase = BindingPhase::Runtime;\n    if (pattern_inst_kind == SemIR::SymbolicBindingPattern::Kind) {\n      phase = is_template ? BindingPhase::Template : BindingPhase::Symbolic;\n    }\n    auto binding = AddBindingPattern(\n        context, name_node, type_expr_region_id,\n        {.kind = pattern_inst_kind,\n         .type_id = GetPatternType(context, type_expr.type_component_id),\n         .entity_name_id = AddBindingEntityName(context, name_id, form_id,\n                                                is_unused, phase)});\n\n    // TODO: If `is_generic`, then `binding.bind_id is a SymbolicBinding. Subst\n    // the `.Self` of type `type` in the `cast_type_id` type (a `FacetType`)\n    // with the `binding.bind_id` itself, and build a new pattern with that.\n    // This is kind of cyclical. So we need to reuse the EntityNameId, which\n    // will also reuse the CompileTimeBinding for the new SymbolicBinding.\n\n    if (name_id != SemIR::NameId::Underscore) {\n      // Add name to lookup immediately, so it can be used in the rest of the\n      // enclosing pattern.\n      auto name_context =\n          context.decl_name_stack().MakeUnqualifiedName(name_node, name_id);\n      context.decl_name_stack().AddNameOrDiagnose(\n          name_context, binding.bind_id,\n          introducer.modifier_set.GetAccessKind());\n      context.full_pattern_stack().AddBindName(name_id);\n    }\n\n    return binding.pattern_id;\n  };\n\n  auto abstract_diagnostic_context = [&](auto& builder) {\n    CARBON_DIAGNOSTIC(AbstractTypeInVarPattern, Context,\n                      \"binding pattern has abstract type {0} in `var` \"\n                      \"pattern\",\n                      SemIR::TypeId);\n    builder.Context(type_expr.node_id, AbstractTypeInVarPattern,\n                    type_expr.type_component_id);\n  };\n\n  // A `self` binding can only appear in an implicit parameter list.\n  if (name_id == SemIR::NameId::SelfValue &&\n      !context.node_stack().PeekIs(Parse::NodeKind::ImplicitParamListStart)) {\n    CARBON_DIAGNOSTIC(\n        SelfOutsideImplicitParamList, Error,\n        \"`self` can only be declared in an implicit parameter list\");\n    context.emitter().Emit(node_id, SelfOutsideImplicitParamList);\n  }\n\n  if (node_kind == Parse::NodeKind::CompileTimeBindingPattern &&\n      introducer.kind == Lex::TokenKind::Let) {\n    // TODO: We should re-evaluate the contents of the eval block in a\n    // synthesized specific to form these values, in order to propagate the\n    // values.\n    return context.TODO(node_id,\n                        \"local `let :!` bindings are currently unsupported\");\n  }\n\n  // Allocate an instruction of the appropriate kind, linked to the name for\n  // error locations.\n  switch (context.full_pattern_stack().CurrentKind()) {\n    case FullPatternStack::Kind::ImplicitParamList:\n    case FullPatternStack::Kind::ExplicitParamList: {\n      if (!IsValidParamForIntroducer(context, node_id, name_id, introducer.kind,\n                                     is_generic)) {\n        if (name_id != SemIR::NameId::Underscore) {\n          AddNameToLookup(context, name_id, SemIR::ErrorInst::InstId);\n        }\n        // Replace the parameter with `ErrorInst` so that we don't try\n        // constructing a generic based on it.\n        context.node_stack().Push(node_id, SemIR::ErrorInst::InstId);\n        break;\n      }\n\n      // Using `AsConcreteType` here causes `fn F[var self: Self]();`\n      // to fail since `Self` is an incomplete type.\n      if (node_kind == Parse::NodeKind::VarBindingPattern) {\n        auto [unqualified_type_id, qualifiers] =\n            context.types().GetUnqualifiedTypeAndQualifiers(\n                type_expr.type_component_id);\n        if ((qualifiers & SemIR::TypeQualifiers::Partial) !=\n                SemIR::TypeQualifiers::Partial &&\n            context.types().Is<SemIR::ClassType>(unqualified_type_id)) {\n          auto class_type =\n              context.types().GetAs<SemIR::ClassType>(unqualified_type_id);\n          auto& class_info = context.classes().Get(class_type.class_id);\n          if (class_info.inheritance_kind ==\n              SemIR::Class::InheritanceKind::Abstract) {\n            Diagnostics::ContextScope scope(&context.emitter(),\n                                            abstract_diagnostic_context);\n            DiagnoseAbstractClass(context, class_type.class_id,\n                                  /*direct_use=*/true);\n            type_expr.type_component_id = SemIR::ErrorInst::TypeId;\n          }\n        }\n      }\n\n      auto result_inst_id = make_binding_pattern();\n\n      // A binding pattern in a function signature is a `Call` parameter\n      // unless it's nested inside a `var` pattern (because then the\n      // enclosing `var` pattern is), or it's a compile-time binding pattern\n      // (because then it's not passed to the `Call` inst).\n      if (node_kind == Parse::NodeKind::LetBindingPattern ||\n          node_kind == Parse::NodeKind::FormBindingPattern) {\n        auto type_id = context.insts().GetAttachedType(result_inst_id);\n        if (is_ref) {\n          result_inst_id = AddPatternInst<SemIR::RefParamPattern>(\n              context, node_id,\n              {.type_id = type_id, .subpattern_id = result_inst_id});\n        } else if (node_kind == Parse::NodeKind::FormBindingPattern) {\n          result_inst_id = AddPatternInst<SemIR::FormParamPattern>(\n              context, node_id,\n              {.type_id = type_id,\n               .subpattern_id = result_inst_id,\n               .form_id = form_id});\n        } else {\n          result_inst_id = AddPatternInst<SemIR::ValueParamPattern>(\n              context, node_id,\n              {.type_id = type_id, .subpattern_id = result_inst_id});\n        }\n      }\n      context.node_stack().Push(node_id, result_inst_id);\n      break;\n    }\n\n    case FullPatternStack::Kind::NameBindingDecl: {\n      auto incomplete_diagnostic_context = [&](auto& builder) {\n        CARBON_DIAGNOSTIC(IncompleteTypeInBindingDecl, Context,\n                          \"binding pattern has incomplete type {0} in name \"\n                          \"binding declaration\",\n                          InstIdAsType);\n        builder.Context(type_expr.node_id, IncompleteTypeInBindingDecl,\n                        type_expr.inst_id);\n      };\n      if (node_kind == Parse::NodeKind::VarBindingPattern) {\n        if (!RequireConcreteType(\n                context, type_expr.type_component_id, type_expr.node_id,\n                incomplete_diagnostic_context, abstract_diagnostic_context)) {\n          type_expr.type_component_id = SemIR::ErrorInst::TypeId;\n        }\n      } else {\n        if (!RequireCompleteType(context, type_expr.type_component_id,\n                                 type_expr.node_id,\n                                 incomplete_diagnostic_context)) {\n          type_expr.type_component_id = SemIR::ErrorInst::TypeId;\n        }\n      }\n\n      auto binding_pattern_id = make_binding_pattern();\n      if (node_kind == Parse::NodeKind::VarBindingPattern) {\n        CARBON_CHECK(!is_generic);\n\n        if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Returned)) {\n          // TODO: Should we check this for the `var` as a whole, rather than\n          // for the name binding?\n          auto bind_id = context.bind_name_map()\n                             .Lookup(binding_pattern_id)\n                             .value()\n                             .bind_name_id;\n          RegisterReturnedVar(\n              context, introducer.modifier_node_id(ModifierOrder::Decl),\n              type_expr.node_id, type_expr.type_component_id, bind_id, name_id);\n        }\n      }\n      context.node_stack().Push(node_id, binding_pattern_id);\n      break;\n    }\n\n    case FullPatternStack::Kind::NotInEitherParamList:\n      CARBON_FATAL(\"Unreachable\");\n  }\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::LetBindingPatternId node_id)\n    -> bool {\n  return HandleAnyBindingPattern(context, node_id,\n                                 Parse::NodeKind::LetBindingPattern);\n}\n\nauto HandleParseNode(Context& context, Parse::VarBindingPatternId node_id)\n    -> bool {\n  return HandleAnyBindingPattern(context, node_id,\n                                 Parse::NodeKind::VarBindingPattern);\n}\n\nauto HandleParseNode(Context& context, Parse::FormBindingPatternId node_id)\n    -> bool {\n  return HandleAnyBindingPattern(context, node_id,\n                                 Parse::NodeKind::FormBindingPattern);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::CompileTimeBindingPatternStartId /*node_id*/)\n    -> bool {\n  // Make a scope to contain the `.Self` facet value for use in the type of the\n  // compile time binding. This is popped when handling the\n  // CompileTimeBindingPatternId.\n  context.scope_stack().PushForSameRegion();\n\n  // The `.Self` must have a type of `FacetType`, so that it gets wrapped in\n  // `FacetAccessType` when used in a type position, such as in `U:! I(.Self)`.\n  // This allows substitution with other facet values without requiring an\n  // additional `FacetAccessType` to be inserted.\n  auto type_id = GetEmptyFacetType(context);\n\n  MakePeriodSelfFacetValue(context, type_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::CompileTimeBindingPatternId node_id) -> bool {\n  // Pop the `.Self` facet value name introduced by the\n  // CompileTimeBindingPatternStart.\n  context.scope_stack().Pop(/*check_unused=*/true);\n\n  auto node_kind = Parse::NodeKind::CompileTimeBindingPattern;\n  const DeclIntroducerState& introducer =\n      context.decl_introducer_state_stack().innermost();\n  if (introducer.kind == Lex::TokenKind::Let) {\n    // Disallow `let` outside of function and interface definitions.\n    // TODO: Find a less brittle way of doing this. A `scope_inst_id` of `None`\n    // can represent a block scope, but is also used for other kinds of scopes\n    // that aren't necessarily part of a function decl.\n    // We don't need to check if the scope is an interface here as this is\n    // already caught in the parse phase by the separated associated constant\n    // logic.\n    auto scope_inst_id = context.scope_stack().PeekInstId();\n    if (scope_inst_id.has_value()) {\n      auto scope_inst = context.insts().Get(scope_inst_id);\n      if (!scope_inst.Is<SemIR::FunctionDecl>()) {\n        context.TODO(\n            node_id,\n            \"`let` compile time binding outside function or interface\");\n        node_kind = Parse::NodeKind::LetBindingPattern;\n      }\n    }\n  }\n\n  return HandleAnyBindingPattern(context, node_id, node_kind);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::AssociatedConstantNameAndTypeId node_id) -> bool {\n  auto [type_node, parsed_type_id] = context.node_stack().PopExprWithNodeId();\n  auto [cast_type_inst_id, cast_type_id] =\n      ExprAsType(context, type_node, parsed_type_id);\n\n  EndSubpatternAsExpr(context, cast_type_inst_id);\n\n  auto [name_node, name_id] = context.node_stack().PopNameWithNodeId();\n\n  if (name_id == SemIR::NameId::Underscore) {\n    // The action item here may be to document this as not allowed, and\n    // add a proper diagnostic.\n    context.TODO(node_id, \"_ used as associated constant name\");\n  }\n\n  SemIR::AssociatedConstantDecl assoc_const_decl = {\n      .type_id = cast_type_id,\n      .assoc_const_id = SemIR::AssociatedConstantId::None,\n      .decl_block_id = SemIR::InstBlockId::None};\n  auto decl_id =\n      AddPlaceholderInstInNoBlock(context, node_id, assoc_const_decl);\n  assoc_const_decl.assoc_const_id = context.associated_constants().Add(\n      {.name_id = name_id,\n       .parent_scope_id = context.scope_stack().PeekNameScopeId(),\n       .decl_id = decl_id,\n       .default_value_id = SemIR::InstId::None});\n  ReplaceInstBeforeConstantUse(context, decl_id, assoc_const_decl);\n\n  context.node_stack().Push(node_id, decl_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::FieldNameAndTypeId node_id)\n    -> bool {\n  auto [type_node, parsed_type_id] = context.node_stack().PopExprWithNodeId();\n  auto [cast_type_inst_id, cast_type_id] =\n      ExprAsType(context, type_node, parsed_type_id);\n  auto [name_node, name_id] = context.node_stack().PopNameWithNodeId();\n\n  auto parent_class_decl =\n      context.scope_stack().TryGetCurrentScopeAs<SemIR::ClassDecl>();\n  CARBON_CHECK(parent_class_decl);\n  if (!RequireConcreteType(\n          context, cast_type_id, type_node,\n          [&](auto& builder) {\n            CARBON_DIAGNOSTIC(IncompleteTypeInFieldDecl, Context,\n                              \"field has incomplete type {0}\", SemIR::TypeId);\n            builder.Context(type_node, IncompleteTypeInFieldDecl, cast_type_id);\n          },\n          [&](auto& builder) {\n            CARBON_DIAGNOSTIC(AbstractTypeInFieldDecl, Context,\n                              \"field has abstract type {0}\", SemIR::TypeId);\n            builder.Context(type_node, AbstractTypeInFieldDecl, cast_type_id);\n          })) {\n    cast_type_id = SemIR::ErrorInst::TypeId;\n  }\n  if (cast_type_id == SemIR::ErrorInst::TypeId) {\n    cast_type_inst_id = SemIR::ErrorInst::TypeInstId;\n  }\n  auto& class_info = context.classes().Get(parent_class_decl->class_id);\n  auto field_type_id = GetUnboundElementType(\n      context, context.types().GetTypeInstId(class_info.self_type_id),\n      cast_type_inst_id);\n  auto field_id =\n      AddInst<SemIR::FieldDecl>(context, node_id,\n                                {.type_id = field_type_id,\n                                 .name_id = name_id,\n                                 .index = SemIR::ElementIndex::None});\n  context.field_decls_stack().AppendToTop(field_id);\n\n  auto name_context =\n      context.decl_name_stack().MakeUnqualifiedName(node_id, name_id);\n  context.decl_name_stack().AddNameOrDiagnose(\n      name_context, field_id,\n      context.decl_introducer_state_stack()\n          .innermost()\n          .modifier_set.GetAccessKind());\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::RefBindingNameId node_id)\n    -> bool {\n  context.node_stack().Push(node_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::TemplateBindingNameId node_id)\n    -> bool {\n  context.node_stack().Push(node_id);\n  return true;\n}\n\n// Within a pattern with an unused modifier, sets the is_unused on all\n// entity names and also returns whether any names were found. The result\n// is needed to emit a diagnostic when the unused modifier is\n// unnecessary.\nstatic auto MarkPatternUnused(Context& context, SemIR::InstId inst_id) -> bool {\n  bool found_name = false;\n  llvm::SmallVector<SemIR::InstId> worklist;\n  worklist.push_back(inst_id);\n  while (!worklist.empty()) {\n    auto current_inst_id = worklist.pop_back_val();\n    auto inst = context.insts().Get(current_inst_id);\n    CARBON_KIND_SWITCH(inst) {\n      case CARBON_KIND_ANY(SemIR::AnyParamPattern, param): {\n        worklist.push_back(param.subpattern_id);\n        break;\n      }\n      case CARBON_KIND_ANY(SemIR::AnyBindingPattern, bind): {\n        auto& name = context.entity_names().Get(bind.entity_name_id);\n        name.is_unused = true;\n        // We treat `_` as not marking the pattern as unused for the purpose of\n        // deciding whether to issue a warning for `unused` on a pattern that\n        // doesn't contain any bindings. `_` is implicitly unused, so marking it\n        // `unused` is redundant but harmless.\n        if (name.name_id != SemIR::NameId::Underscore) {\n          found_name = true;\n        }\n        break;\n      }\n      case CARBON_KIND(SemIR::TuplePattern tuple): {\n        for (auto elem_id : context.inst_blocks().Get(tuple.elements_id)) {\n          worklist.push_back(elem_id);\n        }\n        break;\n      }\n      case CARBON_KIND(SemIR::VarPattern var): {\n        worklist.push_back(var.subpattern_id);\n        break;\n      }\n      default:\n        break;\n    }\n  }\n  return found_name;\n}\n\nauto HandleParseNode(Context& context, Parse::UnusedPatternId node_id) -> bool {\n  auto [child_node, child_inst_id] =\n      context.node_stack().PopPatternWithNodeId();\n  if (!MarkPatternUnused(context, child_inst_id)) {\n    CARBON_DIAGNOSTIC(UnusedPatternNoBindings, Warning,\n                      \"`unused` modifier on pattern without bindings\");\n    context.emitter().Emit(node_id, UnusedPatternNoBindings);\n  }\n  context.node_stack().Push(node_id, child_inst_id);\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_call_expr.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/sem_ir/expr_info.h\"\n#include \"toolchain/sem_ir/inst.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::CallExprStartId node_id) -> bool {\n  auto name_id = context.node_stack().PopExpr();\n  context.node_stack().Push(node_id, name_id);\n  context.param_and_arg_refs_stack().Push();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::CallExprId node_id) -> bool {\n  // Process the final explicit call argument now, but leave the arguments\n  // block on the stack until the end of this function.\n  context.param_and_arg_refs_stack().EndNoPop(Parse::NodeKind::CallExprStart);\n  auto callee_id = context.node_stack().Pop<Parse::NodeKind::CallExprStart>();\n\n  auto call_id = PerformCall(\n      context, node_id, callee_id,\n      context.param_and_arg_refs_stack().PeekCurrentBlockContents());\n\n  context.param_and_arg_refs_stack().PopAndDiscard();\n  context.node_stack().Push(node_id, call_id);\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_choice.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/decl_name_stack.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/literal.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/unused.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/lex/token_kind.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::ChoiceIntroducerId node_id)\n    -> bool {\n  // This choice is potentially generic.\n  StartGenericDecl(context);\n  // Create an instruction block to hold the instructions created as part of the\n  // choice signature, such as generic parameters.\n  context.inst_block_stack().Push();\n  // There's no modifiers on a choice, but this informs how to typecheck any\n  // generic binding pattern.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Choice>();\n  // Push the bracketing node.\n  context.node_stack().Push(node_id);\n  // The choice's name follows.\n  context.decl_name_stack().PushScopeAndStartName();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ChoiceDefinitionStartId node_id)\n    -> bool {\n  auto name = PopNameComponent(context);\n  auto name_context = context.decl_name_stack().FinishName(name);\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::ChoiceIntroducer>();\n  context.decl_introducer_state_stack().Pop<Lex::TokenKind::Choice>();\n\n  auto decl_block_id = context.inst_block_stack().Pop();\n\n  // Choices create a ClassId, since they ultimately turn into a class with\n  // methods and some builtin impls.\n  auto class_decl = SemIR::ClassDecl{.type_id = SemIR::TypeType::TypeId,\n                                     .class_id = SemIR::ClassId::None,\n                                     .decl_block_id = decl_block_id};\n  auto class_decl_id = AddPlaceholderInst(context, node_id, class_decl);\n\n  context.decl_name_stack().AddNameOrDiagnose(name_context, class_decl_id,\n                                              SemIR::AccessKind::Public);\n\n  // An inst block for the body of the choice.\n  context.inst_block_stack().Push();\n  auto body_block_id = context.inst_block_stack().PeekOrAdd();\n\n  SemIR::Class class_info = {\n      name_context.MakeEntityWithParamsBase(name, class_decl_id,\n                                            /*is_extern=*/false,\n                                            SemIR::LibraryNameId::None),\n      {// `.self_type_id` depends on the ClassType, so is set below.\n       .self_type_id = SemIR::TypeId::None,\n       .inheritance_kind = SemIR::ClassFields::Final,\n       // TODO: Handle the case where there's control flow in the alternatives.\n       // For example:\n       //\n       //   choice C {\n       //     Alt(x: if true then i32 else f64),\n       //   }\n       //\n       // We may need to track a list of instruction blocks here, as we do for a\n       // function.\n       .body_block_id = body_block_id}};\n\n  // This call finishes the GenericDecl, after which we can use the `Self`\n  // specific.\n  class_info.generic_id = BuildGenericDecl(context, class_decl_id);\n  auto self_specific_id =\n      context.generics().GetSelfSpecific(class_info.generic_id);\n\n  class_info.definition_id = class_decl_id;\n  class_info.scope_id = context.name_scopes().Add(\n      class_decl_id, SemIR::NameId::None, class_info.parent_scope_id);\n  class_decl.class_id = context.classes().Add(class_info);\n  if (class_info.has_parameters()) {\n    class_decl.type_id = GetGenericClassType(\n        context, class_decl.class_id, context.scope_stack().PeekSpecificId());\n  }\n\n  ReplaceInstBeforeConstantUse(context, class_decl_id, class_decl);\n\n  // We had to construct the `ClassId` from `Class` in order to build the `Self`\n  // type below. But it needs to be written back to the `Class` in the\n  // ValueStore, not the local variable. This gives a mutable reference to the\n  // `Class` in the ValueStore.\n  SemIR::Class& mut_class = context.classes().Get(class_decl.class_id);\n  // Build the `Self` type using the resulting type constant.\n  auto self_type_id =\n      GetClassType(context, class_decl.class_id, self_specific_id);\n  mut_class.self_type_id = self_type_id;\n\n  // Enter the choice scope.\n  context.scope_stack().PushForEntity(class_decl_id, class_info.scope_id,\n                                      self_specific_id);\n  // Checking the binding pattern for an alternative requires a non-empty stack.\n  // We reuse the Choice token even though we're now checking an alternative\n  // inside the Choice, since there's no better token to use.\n  //\n  //  TODO: The token here is _not_ `Choice` though, we shouldn't need to use\n  //  that here. Either remove the need for a token or find a token (a new\n  //  introducer?) for the alternative to name.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Choice>();\n  StartGenericDefinition(context, class_info.generic_id);\n\n  context.name_scopes().AddRequiredName(\n      class_info.scope_id, SemIR::NameId::SelfType,\n      context.types().GetTypeInstId(self_type_id));\n\n  // Mark the beginning of the choice body.\n  context.node_stack().Push(node_id, class_decl.class_id);\n\n  CARBON_CHECK(context.choice_deferred_bindings().empty(),\n               \"Alternatives left behind in choice_deferred_bindings: {0}\",\n               context.choice_deferred_bindings().size());\n  return true;\n}\n\nstatic auto AddChoiceAlternative(\n    Context& context, Parse::NodeIdOneOf<Parse::ChoiceAlternativeListCommaId,\n                                         Parse::ChoiceDefinitionId>\n                          node_id) -> void {\n  // Note, there is nothing like a ChoiceAlternativeIntroducer node, so no parse\n  // node to pop here.\n  auto name_component = PopNameComponent(context);\n  if (name_component.param_patterns_id == SemIR::InstBlockId::Empty) {\n    // Treat an empty parameter list the same as no parameter list.\n    //\n    // TODO: The current design suggests that we want Foo() to result in a\n    // member function `ChoiceType.Foo()`, and `Foo` to result in a member\n    // constant `ChoiceType.Foo`, but that only one of the two is allowed in a\n    // single choice type. See\n    // https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/sum_types.md#user-defined-sum-types.\n    // For now they are not treated differently and both resolve to a member\n    // constant.\n    context.TODO(name_component.params_loc_id,\n                 \"empty parameter list should make a member function\");\n    name_component.param_patterns_id = SemIR::InstBlockId::None;\n  }\n  if (name_component.param_patterns_id.has_value()) {\n    context.TODO(name_component.params_loc_id,\n                 \"choice alternatives with parameters are not yet supported\");\n    return;\n  }\n  context.choice_deferred_bindings().push_back({node_id, name_component});\n}\n\n// Info about the Choice type, used to construct each alternative member of the\n// class representing the Choice.\nstruct ChoiceInfo {\n  // The `Self` type.\n  SemIR::TypeId self_type_id;\n  // The scope of the class for adding the alternatives to.\n  SemIR::NameScopeId name_scope_id;\n  // A struct type with the same fields as `Self`. Used to construct `Self`.\n  SemIR::TypeId self_struct_type_id;\n  // The type of the discriminant value.\n  SemIR::TypeId discriminant_type_id;\n  int num_alternative_bits;\n};\n\n// Builds a `let` binding for an alternative without parameters as a member of\n// the resulting class for the Choice definition. If the alternative was `Alt`\n// then the binding will be like:\n// ```\n//   let Alt: ChoiceType = <ChoiceType with Alt selected>;\n// ```\nstatic auto MakeLetBinding(Context& context, const ChoiceInfo& choice_info,\n                           int alternative_index,\n                           const Context::ChoiceDeferredBinding& binding)\n    -> void {\n  SemIR::InstId discriminant_value_id = [&] {\n    if (choice_info.num_alternative_bits == 0) {\n      return AddInst(context, binding.node_id,\n                     SemIR::TupleLiteral{\n                         .type_id = GetTupleType(context, {}),\n                         .elements_id = SemIR::InstBlockId::Empty,\n                     });\n    } else {\n      return MakeIntLiteral(context, binding.node_id,\n                            context.ints().Add(alternative_index));\n    }\n  }();\n  discriminant_value_id =\n      ConvertToValueOfType(context, binding.node_id, discriminant_value_id,\n                           choice_info.discriminant_type_id);\n\n  auto self_value_id = ConvertToValueOfType(\n      context, binding.node_id,\n      AddInst(context, binding.node_id,\n              SemIR::StructLiteral{\n                  .type_id = choice_info.self_struct_type_id,\n                  .elements_id =\n                      [&] {\n                        context.inst_block_stack().Push();\n                        context.inst_block_stack().AddInstId(\n                            discriminant_value_id);\n                        return context.inst_block_stack().Pop();\n                      }(),\n              }),\n      choice_info.self_type_id);\n\n  auto entity_name_id = context.entity_names().Add(\n      {.name_id = binding.name_component.name_id,\n       .parent_scope_id = choice_info.name_scope_id});\n  auto bind_name_id = AddInst(context, binding.node_id,\n                              SemIR::ValueBinding{\n                                  .type_id = choice_info.self_type_id,\n                                  .entity_name_id = entity_name_id,\n                                  .value_id = self_value_id,\n                              });\n  context.name_scopes()\n      .Get(choice_info.name_scope_id)\n      .AddRequired({.name_id = binding.name_component.name_id,\n                    .result = SemIR::ScopeLookupResult::MakeFound(\n                        bind_name_id, SemIR::AccessKind::Public)});\n}\n\nauto HandleParseNode(Context& context, Parse::ChoiceDefinitionId node_id)\n    -> bool {\n  // The last alternative may optionally not have a comma after it, in which\n  // case we get here after the last alternative.\n  if (!context.node_stack().PeekIs(Parse::NodeKind::ChoiceDefinitionStart)) {\n    AddChoiceAlternative(context, node_id);\n  }\n\n  auto class_id =\n      context.node_stack().Pop<Parse::NodeKind::ChoiceDefinitionStart>();\n\n  int num_alternatives = context.choice_deferred_bindings().size();\n  int num_alternative_bits = [&] {\n    if (num_alternatives > 1) {\n      return static_cast<int>(ceil(log2(num_alternatives)));\n    } else {\n      return 0;\n    }\n  }();\n\n  SemIR::TypeId discriminant_type_id = [&] {\n    if (num_alternative_bits == 0) {\n      // Even though there's no bits needed, we add an empty field. We want to\n      // prevent constructing the Choice from an empty struct literal instead of\n      // going through an alternative. And in the case there is no alternative,\n      // then there's no way to construct the Choice (which can be a useful\n      // type).\n      //\n      // TODO: Find a way to produce a better diagnostic, and not require an\n      // empty field.\n      return GetTupleType(context, {});\n    } else {\n      return MakeIntType(context, node_id, SemIR::IntKind::Unsigned,\n                         context.ints().Add(num_alternative_bits));\n    }\n  }();\n\n  llvm::SmallVector<SemIR::StructTypeField, 1> struct_type_fields;\n  struct_type_fields.push_back({\n      .name_id = SemIR::NameId::ChoiceDiscriminant,\n      .type_inst_id = context.types().GetTypeInstId(discriminant_type_id),\n  });\n  auto fields_id =\n      context.struct_type_fields().AddCanonical(struct_type_fields);\n  auto choice_witness_id = AddInst(\n      context, node_id,\n      SemIR::CompleteTypeWitness{\n          .type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),\n          .object_repr_type_inst_id = context.types().GetTypeInstId(\n              GetStructType(context, fields_id))});\n  auto& class_info = context.classes().Get(class_id);\n  class_info.complete_type_witness_id = choice_witness_id;\n\n  auto self_struct_type_id = GetStructType(\n      context, context.struct_type_fields().AddCanonical(struct_type_fields));\n\n  for (auto [i, deferred_binding] :\n       llvm::enumerate(context.choice_deferred_bindings())) {\n    // TODO: This requires the class to be complete, but we've not yet called\n    // `FinishGenericDefinition`, so we can't use it as a complete type yet. But\n    // this also potentially adds things to the generic definition, so we can't\n    // call `FinsihGenericDefinition` before this call, either.\n    MakeLetBinding(context,\n                   ChoiceInfo{.self_type_id = class_info.self_type_id,\n                              .name_scope_id = class_info.scope_id,\n                              .self_struct_type_id = self_struct_type_id,\n                              .discriminant_type_id = discriminant_type_id,\n                              .num_alternative_bits = num_alternative_bits},\n                   i, deferred_binding);\n  }\n\n  // The scopes and blocks for the choice itself.\n  context.inst_block_stack().Pop();\n  context.decl_introducer_state_stack().Pop<Lex::TokenKind::Choice>();\n  context.scope_stack().Pop(/*check_unused=*/true);\n  context.decl_name_stack().PopScope();\n\n  FinishGenericDefinition(context, class_info.generic_id);\n\n  context.choice_deferred_bindings().clear();\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::ChoiceAlternativeListCommaId node_id) -> bool {\n  AddChoiceAlternative(context, node_id);\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_class.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <optional>\n#include <tuple>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/class.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/decl_name_stack.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/impl.h\"\n#include \"toolchain/check/import.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/merge.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::ClassIntroducerId node_id)\n    -> bool {\n  // This class is potentially generic.\n  StartGenericDecl(context);\n  // Create an instruction block to hold the instructions created as part of the\n  // class signature, such as generic parameters.\n  context.inst_block_stack().Push();\n  // Push the bracketing node.\n  context.node_stack().Push(node_id);\n  // Optional modifiers and the name follow.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Class>();\n  context.decl_name_stack().PushScopeAndStartName();\n  return true;\n}\n\n// Tries to merge new_class into prev_class_id. Since new_class won't have a\n// definition even if one is upcoming, set is_definition to indicate the planned\n// result.\n//\n// If merging is successful, returns true and may update the previous class.\n// Otherwise, returns false. Prints a diagnostic when appropriate.\nstatic auto MergeClassRedecl(Context& context, Parse::AnyClassDeclId node_id,\n                             SemIR::Class& new_class, bool new_is_definition,\n                             SemIR::ClassId prev_class_id,\n                             SemIR::ImportIRId prev_import_ir_id) -> bool {\n  auto& prev_class = context.classes().Get(prev_class_id);\n  SemIR::LocId prev_loc_id(prev_class.latest_decl_id());\n\n  // Check the generic parameters match, if they were specified.\n  if (!CheckRedeclParamsMatch(context, DeclParams(new_class),\n                              DeclParams(prev_class))) {\n    return false;\n  }\n\n  DiagnoseIfInvalidRedecl(\n      context, Lex::TokenKind::Class, prev_class.name_id,\n      RedeclInfo(new_class, node_id, new_is_definition),\n      RedeclInfo(prev_class, prev_loc_id, prev_class.has_definition_started()),\n      prev_import_ir_id);\n\n  if (new_is_definition && prev_class.has_definition_started()) {\n    // Don't attempt to merge multiple definitions.\n    return false;\n  }\n\n  if (new_is_definition) {\n    prev_class.MergeDefinition(new_class);\n    prev_class.scope_id = new_class.scope_id;\n    prev_class.body_block_id = new_class.body_block_id;\n    prev_class.adapt_id = new_class.adapt_id;\n    prev_class.base_id = new_class.base_id;\n    prev_class.complete_type_witness_id = new_class.complete_type_witness_id;\n  }\n\n  if (prev_import_ir_id.has_value() ||\n      (prev_class.is_extern && !new_class.is_extern)) {\n    prev_class.first_owning_decl_id = new_class.first_owning_decl_id;\n    ReplacePrevInstForMerge(context, new_class.parent_scope_id,\n                            prev_class.name_id, new_class.first_owning_decl_id);\n  }\n  return true;\n}\n\n// Adds the name to name lookup. If there's a conflict, tries to merge. May\n// update class_decl and class_info when merging.\nstatic auto MergeOrAddName(Context& context, Parse::AnyClassDeclId node_id,\n                           const DeclNameStack::NameContext& name_context,\n                           SemIR::InstId class_decl_id,\n                           SemIR::ClassDecl& class_decl,\n                           SemIR::Class& class_info, bool is_definition,\n                           SemIR::AccessKind access_kind) -> void {\n  SemIR::ScopeLookupResult lookup_result =\n      context.decl_name_stack().LookupOrAddName(name_context, class_decl_id,\n                                                access_kind);\n  if (lookup_result.is_poisoned()) {\n    // This is a declaration of a poisoned name.\n    DiagnosePoisonedName(context, name_context.name_id_for_new_inst(),\n                         lookup_result.poisoning_loc_id(), name_context.loc_id);\n    return;\n  }\n\n  if (!lookup_result.is_found()) {\n    return;\n  }\n\n  SemIR::InstId prev_id = lookup_result.target_inst_id();\n\n  auto prev_class_id = SemIR::ClassId::None;\n  auto prev_import_ir_id = SemIR::ImportIRId::None;\n  auto prev = context.insts().Get(prev_id);\n  CARBON_KIND_SWITCH(prev) {\n    case CARBON_KIND(SemIR::ClassDecl class_decl): {\n      prev_class_id = class_decl.class_id;\n      break;\n    }\n    case CARBON_KIND(SemIR::ImportRefLoaded import_ref): {\n      auto import_ir_inst =\n          context.import_ir_insts().Get(import_ref.import_ir_inst_id);\n\n      // Verify the decl so that things like aliases are name conflicts.\n      const auto* import_ir =\n          context.import_irs().Get(import_ir_inst.ir_id()).sem_ir;\n      if (!import_ir->insts().Is<SemIR::ClassDecl>(import_ir_inst.inst_id())) {\n        break;\n      }\n\n      // Use the constant value to get the ID.\n      auto decl_value = context.insts().Get(\n          context.constant_values().GetConstantInstId(prev_id));\n      if (auto class_type = decl_value.TryAs<SemIR::ClassType>()) {\n        prev_class_id = class_type->class_id;\n        prev_import_ir_id = import_ir_inst.ir_id();\n      } else if (auto generic_class_type =\n                     context.types().TryGetAs<SemIR::GenericClassType>(\n                         decl_value.type_id())) {\n        prev_class_id = generic_class_type->class_id;\n        prev_import_ir_id = import_ir_inst.ir_id();\n      }\n      break;\n    }\n    default:\n      break;\n  }\n\n  if (!prev_class_id.has_value()) {\n    // This is a redeclaration of something other than a class.\n    DiagnoseDuplicateName(context, name_context.name_id, name_context.loc_id,\n                          SemIR::LocId(prev_id));\n    return;\n  }\n\n  // TODO: Fix `extern` logic. It doesn't work correctly, but doesn't seem worth\n  // ripping out because existing code may incrementally help.\n  if (MergeClassRedecl(context, node_id, class_info, is_definition,\n                       prev_class_id, prev_import_ir_id)) {\n    // When merging, use the existing entity rather than adding a new one.\n    class_decl.class_id = prev_class_id;\n    class_decl.type_id = prev.type_id();\n    // TODO: Validate that the redeclaration doesn't set an access modifier.\n  }\n}\n\nstatic auto BuildClassDecl(Context& context, Parse::AnyClassDeclId node_id,\n                           bool is_definition)\n    -> std::tuple<SemIR::ClassId, SemIR::InstId> {\n  auto name = PopNameComponent(context);\n  auto name_context = context.decl_name_stack().FinishName(name);\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::ClassIntroducer>();\n\n  // Process modifiers.\n  auto [_, parent_scope_inst] =\n      context.name_scopes().GetInstIfValid(name_context.parent_scope_id);\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Class>();\n  CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);\n  auto always_acceptable_modifiers =\n      KeywordModifierSet::Access | KeywordModifierSet::Extern;\n  LimitModifiersOnDecl(context, introducer,\n                       always_acceptable_modifiers | KeywordModifierSet::Class);\n  if (!is_definition) {\n    LimitModifiersOnNotDefinition(context, introducer,\n                                  always_acceptable_modifiers);\n  }\n  RestrictExternModifierOnDecl(context, introducer, parent_scope_inst,\n                               is_definition);\n\n  bool is_extern = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extern);\n  if (introducer.extern_library.has_value()) {\n    context.TODO(node_id, \"extern library\");\n  }\n  auto inheritance_kind =\n      introducer.modifier_set.ToEnum<SemIR::Class::InheritanceKind>()\n          .Case(KeywordModifierSet::Abstract, SemIR::Class::Abstract)\n          .Case(KeywordModifierSet::Base, SemIR::Class::Base)\n          .Default(SemIR::Class::Final);\n\n  auto decl_block_id = context.inst_block_stack().Pop();\n\n  // Add the class declaration.\n  auto class_decl = SemIR::ClassDecl{.type_id = SemIR::TypeType::TypeId,\n                                     .class_id = SemIR::ClassId::None,\n                                     .decl_block_id = decl_block_id};\n  auto class_decl_id = AddPlaceholderInst(context, node_id, class_decl);\n\n  // TODO: Store state regarding is_extern.\n  SemIR::Class class_info = {\n      name_context.MakeEntityWithParamsBase(name, class_decl_id, is_extern,\n                                            SemIR::LibraryNameId::None),\n      {// `.self_type_id` depends on the ClassType, so is set below.\n       .self_type_id = SemIR::TypeId::None,\n       .inheritance_kind = inheritance_kind}};\n\n  DiagnoseIfGenericMissingExplicitParameters(context, class_info);\n\n  MergeOrAddName(context, node_id, name_context, class_decl_id, class_decl,\n                 class_info, is_definition,\n                 introducer.modifier_set.GetAccessKind());\n\n  // Create a new class if this isn't a valid redeclaration.\n  bool is_new_class = !class_decl.class_id.has_value();\n  if (is_new_class) {\n    // TODO: If this is an invalid redeclaration of a non-class entity or there\n    // was an error in the qualifier, we will have lost track of the class name\n    // here. We should keep track of it even if the name is invalid.\n    class_info.generic_id = BuildGenericDecl(context, class_decl_id);\n    class_decl.class_id = context.classes().Add(class_info);\n    if (class_info.has_parameters()) {\n      class_decl.type_id = GetGenericClassType(\n          context, class_decl.class_id, context.scope_stack().PeekSpecificId());\n    }\n  } else {\n    auto prev_decl_generic_id =\n        context.classes().Get(class_decl.class_id).generic_id;\n    FinishGenericRedecl(context, prev_decl_generic_id);\n  }\n\n  // Write the class ID into the ClassDecl.\n  ReplaceInstBeforeConstantUse(context, class_decl_id, class_decl);\n\n  if (is_new_class) {\n    // TODO: Form this as part of building the definition, not as part of the\n    // declaration.\n    SetClassSelfType(context, class_decl.class_id);\n  }\n\n  if (!is_definition && context.sem_ir().is_impl() && !is_extern) {\n    context.definitions_required_by_decl().push_back(class_decl_id);\n  }\n\n  return {class_decl.class_id, class_decl_id};\n}\n\nauto HandleParseNode(Context& context, Parse::ClassDeclId node_id) -> bool {\n  BuildClassDecl(context, node_id, /*is_definition=*/false);\n  context.decl_name_stack().PopScope();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ClassDefinitionStartId node_id)\n    -> bool {\n  auto [class_id, class_decl_id] =\n      BuildClassDecl(context, node_id, /*is_definition=*/true);\n  auto& class_info = context.classes().Get(class_id);\n  StartClassDefinition(context, class_info, class_decl_id);\n\n  // Enter the class scope.\n  context.scope_stack().PushForEntity(\n      class_decl_id, class_info.scope_id,\n      context.generics().GetSelfSpecific(class_info.generic_id));\n  StartGenericDefinition(context, class_info.generic_id);\n\n  context.inst_block_stack().Push();\n  context.node_stack().Push(node_id, class_id);\n  context.field_decls_stack().PushArray();\n  context.vtable_stack().Push();\n\n  // TODO: Handle the case where there's control flow in the class body. For\n  // example:\n  //\n  //   class C {\n  //     var v: if true then i32 else f64;\n  //   }\n  //\n  // We may need to track a list of instruction blocks here, as we do for a\n  // function.\n  class_info.body_block_id = context.inst_block_stack().PeekOrAdd();\n  return true;\n}\n\n// Diagnoses a class-specific declaration appearing outside a class.\nstatic auto DiagnoseClassSpecificDeclOutsideClass(Context& context,\n                                                  SemIR::LocId loc_id,\n                                                  Lex::TokenKind tok) -> void {\n  CARBON_DIAGNOSTIC(ClassSpecificDeclOutsideClass, Error,\n                    \"`{0}` declaration outside class\", Lex::TokenKind);\n  context.emitter().Emit(loc_id, ClassSpecificDeclOutsideClass, tok);\n}\n\n// Returns the current scope's class declaration, or diagnoses if it isn't a\n// class.\nstatic auto GetCurrentScopeAsClassOrDiagnose(Context& context,\n                                             SemIR::LocId loc_id,\n                                             Lex::TokenKind tok)\n    -> std::optional<SemIR::ClassDecl> {\n  auto class_scope =\n      context.scope_stack().TryGetCurrentScopeAs<SemIR::ClassDecl>();\n  if (!class_scope) {\n    DiagnoseClassSpecificDeclOutsideClass(context, loc_id, tok);\n  }\n  return class_scope;\n}\n\n// Diagnoses a class-specific declaration that is repeated within a class, but\n// is not permitted to be repeated.\nstatic auto DiagnoseClassSpecificDeclRepeated(Context& context,\n                                              SemIR::LocId new_loc_id,\n                                              SemIR::LocId prev_loc_id,\n                                              Lex::TokenKind tok) -> void {\n  CARBON_DIAGNOSTIC(AdaptDeclRepeated, Error,\n                    \"multiple `adapt` declarations in class\");\n  CARBON_DIAGNOSTIC(BaseDeclRepeated, Error,\n                    \"multiple `base` declarations in class; multiple \"\n                    \"inheritance is not permitted\");\n  CARBON_DIAGNOSTIC(ClassSpecificDeclPrevious, Note,\n                    \"previous `{0}` declaration is here\", Lex::TokenKind);\n  CARBON_CHECK(tok == Lex::TokenKind::Adapt || tok == Lex::TokenKind::Base);\n  context.emitter()\n      .Build(new_loc_id, tok == Lex::TokenKind::Adapt ? AdaptDeclRepeated\n                                                      : BaseDeclRepeated)\n      .Note(prev_loc_id, ClassSpecificDeclPrevious, tok)\n      .Emit();\n}\n\nauto HandleParseNode(Context& context, Parse::AdaptIntroducerId /*node_id*/)\n    -> bool {\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Adapt>();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool {\n  auto [adapted_type_node, adapted_type_expr_id] =\n      context.node_stack().PopExprWithNodeId();\n\n  // Process modifiers. `extend` is permitted, no others are allowed.\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Adapt>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Extend);\n\n  auto parent_class_decl =\n      GetCurrentScopeAsClassOrDiagnose(context, node_id, Lex::TokenKind::Adapt);\n  if (!parent_class_decl) {\n    return true;\n  }\n\n  auto& class_info = context.classes().Get(parent_class_decl->class_id);\n  if (class_info.adapt_id.has_value()) {\n    DiagnoseClassSpecificDeclRepeated(context, node_id,\n                                      SemIR::LocId(class_info.adapt_id),\n                                      Lex::TokenKind::Adapt);\n    return true;\n  }\n\n  auto [adapted_type_inst_id, adapted_type_id] =\n      ExprAsType(context, node_id, adapted_type_expr_id);\n  if (!RequireConcreteType(\n          context, adapted_type_id, node_id,\n          [&](auto& builder) {\n            CARBON_DIAGNOSTIC(IncompleteTypeInAdaptDecl, Context,\n                              \"adapted type {0} is an incomplete type\",\n                              InstIdAsType);\n            builder.Context(node_id, IncompleteTypeInAdaptDecl,\n                            adapted_type_inst_id);\n          },\n          [&](auto& builder) {\n            CARBON_DIAGNOSTIC(AbstractTypeInAdaptDecl, Context,\n                              \"adapted type {0} is an abstract type\",\n                              InstIdAsType);\n            builder.Context(node_id, AbstractTypeInAdaptDecl,\n                            adapted_type_inst_id);\n          })) {\n    adapted_type_id = SemIR::ErrorInst::TypeId;\n  }\n  if (adapted_type_id == SemIR::ErrorInst::TypeId) {\n    adapted_type_inst_id = SemIR::ErrorInst::TypeInstId;\n  }\n\n  // Build a SemIR representation for the declaration.\n  class_info.adapt_id = AddInst<SemIR::AdaptDecl>(\n      context, node_id, {.adapted_type_inst_id = adapted_type_inst_id});\n\n  // Extend the class scope with the adapted type's scope if requested.\n  if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {\n    auto& class_scope = context.name_scopes().Get(class_info.scope_id);\n    class_scope.AddExtendedScope({adapted_type_inst_id});\n  }\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::BaseIntroducerId /*node_id*/)\n    -> bool {\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Base>();\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::BaseColonId /*node_id*/)\n    -> bool {\n  return true;\n}\n\nnamespace {\n// Information gathered about a base type specified in a `base` declaration.\nstruct BaseInfo {\n  // A `BaseInfo` representing an erroneous base.\n  static const BaseInfo Error;\n\n  SemIR::TypeId type_id;\n  SemIR::NameScopeId scope_id;\n  SemIR::TypeInstId inst_id;\n};\nconstexpr BaseInfo BaseInfo::Error = {.type_id = SemIR::ErrorInst::TypeId,\n                                      .scope_id = SemIR::NameScopeId::None,\n                                      .inst_id = SemIR::ErrorInst::TypeInstId};\n}  // namespace\n\n// Diagnoses an attempt to derive from a final type.\nstatic auto DiagnoseBaseIsFinal(Context& context, Parse::NodeId node_id,\n                                SemIR::TypeInstId base_type_inst_id) -> void {\n  CARBON_DIAGNOSTIC(BaseIsFinal, Error,\n                    \"deriving from final type {0}; base type must be an \"\n                    \"`abstract` or `base` class\",\n                    InstIdAsType);\n  context.emitter().Emit(node_id, BaseIsFinal, base_type_inst_id);\n}\n\n// Checks that the specified base type is valid.\nstatic auto CheckBaseType(Context& context, Parse::NodeId node_id,\n                          SemIR::InstId base_expr_id) -> BaseInfo {\n  auto [base_type_inst_id, base_type_id] =\n      ExprAsType(context, node_id, base_expr_id);\n  if (base_type_id == SemIR::ErrorInst::TypeId) {\n    return BaseInfo::Error;\n  }\n  if (!RequireCompleteType(context, base_type_id, node_id, [&](auto& builder) {\n        CARBON_DIAGNOSTIC(IncompleteTypeInBaseDecl, Context,\n                          \"base {0} is an incomplete type\", InstIdAsType);\n        builder.Context(node_id, IncompleteTypeInBaseDecl, base_type_inst_id);\n      })) {\n    return BaseInfo::Error;\n  }\n\n  auto class_type = context.types().TryGetAs<SemIR::ClassType>(base_type_id);\n\n  // The base must not be a final class.\n  if (!class_type) {\n    // For now, we treat all types that aren't introduced by a `class`\n    // declaration as being final classes.\n    // TODO: Once we have a better idea of which types are considered to be\n    // classes, produce a better diagnostic for deriving from a non-class type.\n    DiagnoseBaseIsFinal(context, node_id, base_type_inst_id);\n    return BaseInfo::Error;\n  }\n\n  const auto& base_class_info = context.classes().Get(class_type->class_id);\n\n  if (base_class_info.inheritance_kind == SemIR::Class::Final) {\n    DiagnoseBaseIsFinal(context, node_id, base_type_inst_id);\n  }\n\n  CARBON_CHECK(base_class_info.scope_id.has_value(),\n               \"Complete class should have a scope\");\n  return {.type_id = base_type_id,\n          .scope_id = base_class_info.scope_id,\n          .inst_id = base_type_inst_id};\n}\n\nauto HandleParseNode(Context& context, Parse::BaseDeclId node_id) -> bool {\n  auto [base_type_node_id, base_type_expr_id] =\n      context.node_stack().PopExprWithNodeId();\n\n  // Process modifiers. `extend` is required, no others are allowed.\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Base>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Extend);\n  if (!introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {\n    CARBON_DIAGNOSTIC(BaseMissingExtend, Error,\n                      \"missing `extend` before `base` declaration\");\n    context.emitter().Emit(node_id, BaseMissingExtend);\n  }\n\n  auto parent_class_decl =\n      GetCurrentScopeAsClassOrDiagnose(context, node_id, Lex::TokenKind::Base);\n  if (!parent_class_decl) {\n    return true;\n  }\n\n  auto& class_info = context.classes().Get(parent_class_decl->class_id);\n  if (class_info.base_id.has_value()) {\n    DiagnoseClassSpecificDeclRepeated(context, node_id,\n                                      SemIR::LocId(class_info.base_id),\n                                      Lex::TokenKind::Base);\n    return true;\n  }\n\n  if (!context.field_decls_stack().PeekArray().empty()) {\n    // TODO: Add note that includes the first field location as an example.\n    CARBON_DIAGNOSTIC(\n        BaseDeclAfterFieldDecl, Error,\n        \"`base` declaration must appear before field declarations\");\n    context.emitter().Emit(node_id, BaseDeclAfterFieldDecl);\n    return true;\n  }\n\n  auto base_info = CheckBaseType(context, base_type_node_id, base_type_expr_id);\n\n  // TODO: Should we diagnose if there are already any fields?\n\n  // The `base` value in the class scope has an unbound element type. Instance\n  // binding will be performed when it's found by name lookup into an instance.\n  auto field_type_id = GetUnboundElementType(\n      context, context.types().GetTypeInstId(class_info.self_type_id),\n      base_info.inst_id);\n  class_info.base_id =\n      AddInst<SemIR::BaseDecl>(context, node_id,\n                               {.type_id = field_type_id,\n                                .base_type_inst_id = base_info.inst_id,\n                                .index = SemIR::ElementIndex::None});\n\n  if (base_info.type_id != SemIR::ErrorInst::TypeId) {\n    auto base_class_info = context.classes().Get(\n        context.types().GetAs<SemIR::ClassType>(base_info.type_id).class_id);\n    class_info.is_dynamic |= base_class_info.is_dynamic;\n  }\n\n  // Bind the name `base` in the class to the base field.\n  context.decl_name_stack().AddNameOrDiagnose(\n      context.decl_name_stack().MakeUnqualifiedName(node_id,\n                                                    SemIR::NameId::Base),\n      class_info.base_id, introducer.modifier_set.GetAccessKind());\n\n  // Extend the class scope with the base class.\n  if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {\n    auto& class_scope = context.name_scopes().Get(class_info.scope_id);\n    if (base_info.scope_id.has_value()) {\n      class_scope.AddExtendedScope({base_info.inst_id});\n    } else {\n      class_scope.set_has_error();\n    }\n  }\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ClassDefinitionId node_id)\n    -> bool {\n  auto class_id =\n      context.node_stack().Pop<Parse::NodeKind::ClassDefinitionStart>();\n\n  // The class type is now fully defined. Compute its object representation.\n  ComputeClassObjectRepr(context, node_id, class_id,\n                         context.field_decls_stack().PeekArray(),\n                         context.vtable_stack().PeekCurrentBlockContents(),\n                         context.inst_block_stack().PeekCurrentBlockContents());\n\n  context.inst_block_stack().Pop();\n  context.field_decls_stack().PopArray();\n  context.vtable_stack().Pop();\n\n  FinishGenericDefinition(context, context.classes().Get(class_id).generic_id);\n\n  // The decl_name_stack and scopes are popped by `ProcessNodeIds`.\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_codeblock.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/unused.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::CodeBlockStartId node_id)\n    -> bool {\n  context.node_stack().Push(node_id);\n  context.scope_stack().PushForSameRegion();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::CodeBlockId /*node_id*/) -> bool {\n  context.scope_stack().Pop(/*check_unused=*/true);\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::CodeBlockStart>();\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_export.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/decl_name_stack.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/parse/typed_nodes.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::ExportIntroducerId /*node_id*/)\n    -> bool {\n  // Export declarations can't be generic, but we might have parsed a generic\n  // parameter in their name, so enter a generic scope just in case.\n  StartGenericDecl(context);\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Export>();\n  // TODO: Probably need to update DeclNameStack to restrict to only namespaces.\n  context.decl_name_stack().PushScopeAndStartName();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ExportDeclId node_id) -> bool {\n  auto name_context = context.decl_name_stack().FinishName(\n      PopNameComponentWithoutParams(context, Lex::TokenKind::Export));\n  DiscardGenericDecl(context);\n  context.decl_name_stack().PopScope();\n\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Export>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::None);\n\n  if (name_context.state == DeclNameStack::NameContext::State::Error) {\n    // Should already be diagnosed.\n    return true;\n  }\n\n  // Exporting uses the decl name primarily for lookup, so treat poisoning the\n  // same as \"not found\".\n  auto inst_id =\n      name_context.state == DeclNameStack::NameContext::State::Poisoned\n          ? SemIR::InstId::None\n          : name_context.prev_inst_id();\n  if (!inst_id.has_value()) {\n    DiagnoseNameNotFound(context, node_id, name_context.name_id_for_new_inst());\n    return true;\n  }\n\n  auto inst = context.insts().Get(inst_id);\n\n  if (inst.Is<SemIR::ExportDecl>()) {\n    CARBON_DIAGNOSTIC(ExportRedundant, Warning,\n                      \"`export` matches previous `export`\");\n    CARBON_DIAGNOSTIC(ExportPrevious, Note, \"previous `export` here\");\n    context.emitter()\n        .Build(node_id, ExportRedundant)\n        // Use the location of the export itself, not the exported instruction.\n        //\n        // TODO: This construction of a LocId that does not just contain the\n        // InstId prevents GetAbsoluteNodeIdImpl() from seeing the `ExportDecl`\n        // instruction, which prevents it from chasing through it to the entity\n        // being exported. It might be nice to make this more explicit.\n        .Note(context.insts().GetCanonicalLocId(inst_id), ExportPrevious)\n        .Emit();\n    return true;\n  }\n\n  auto import_ref = context.insts().TryGetAs<SemIR::ImportRefLoaded>(inst_id);\n  if (!import_ref) {\n    CARBON_DIAGNOSTIC(ExportNotImportedEntity, Error,\n                      \"only imported entities are valid for `export`\");\n    CARBON_DIAGNOSTIC(ExportNotImportedEntitySource, Note,\n                      \"name is declared here\");\n    context.emitter()\n        .Build(node_id, ExportNotImportedEntity)\n        .Note(inst_id, ExportNotImportedEntitySource)\n        .Emit();\n    return true;\n  }\n\n  auto export_id =\n      AddInst<SemIR::ExportDecl>(context, node_id,\n                                 {.type_id = import_ref->type_id,\n                                  .entity_name_id = import_ref->entity_name_id,\n                                  .value_id = inst_id});\n  context.exports().push_back(export_id);\n\n  // Replace the ImportRef in name lookup, both for the above duplicate\n  // diagnostic and so that cross-package imports can find it easily.\n  auto entity_name = context.entity_names().Get(import_ref->entity_name_id);\n  auto& parent_scope = context.name_scopes().Get(entity_name.parent_scope_id);\n  auto& scope_result =\n      parent_scope.GetEntry(*parent_scope.Lookup(entity_name.name_id)).result;\n  CARBON_CHECK(scope_result.target_inst_id() == inst_id);\n  scope_result = SemIR::ScopeLookupResult::MakeFound(\n      export_id, scope_result.access_kind());\n\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_expr_statement.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/sem_ir/inst.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::ExprStatementId /*node_id*/)\n    -> bool {\n  DiscardExpr(context, context.node_stack().PopExpr());\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_file.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& /*context*/, Parse::FileStartId /*node_id*/)\n    -> bool {\n  // No action to perform.\n  // TODO: We may want to push `FileStart` as a sentinel so that `Peek`s can't\n  // fail.\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::FileEndId /*node_id*/)\n    -> bool {\n  // No action to perform.\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_form_literal.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/parse/node_category.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::RefPrimitiveFormId node_id)\n    -> bool {\n  auto [type_node_id, type_inst_id] = context.node_stack().PopExprWithNodeId();\n  auto type_expr = ExprAsType(context, type_node_id, type_inst_id);\n  auto inst_id =\n      AddInst<SemIR::RefForm>(context, node_id,\n                              {.type_id = SemIR::FormType::TypeId,\n                               .type_component_inst_id = type_expr.inst_id});\n  context.node_stack().Push(node_id, inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ValPrimitiveFormId node_id)\n    -> bool {\n  auto [type_node_id, type_inst_id] = context.node_stack().PopExprWithNodeId();\n  auto type_expr = ExprAsType(context, type_node_id, type_inst_id);\n  auto inst_id =\n      AddInst<SemIR::ValueForm>(context, node_id,\n                                {.type_id = SemIR::FormType::TypeId,\n                                 .type_component_inst_id = type_expr.inst_id});\n  context.node_stack().Push(node_id, inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::VarPrimitiveFormId node_id)\n    -> bool {\n  auto [type_node_id, type_inst_id] = context.node_stack().PopExprWithNodeId();\n  auto type_expr = ExprAsType(context, type_node_id, type_inst_id);\n  auto inst_id =\n      AddInst<SemIR::InitForm>(context, node_id,\n                               {.type_id = SemIR::FormType::TypeId,\n                                .type_component_inst_id = type_expr.inst_id});\n  context.node_stack().Push(node_id, inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::FormLiteralKeywordId /*node_id*/) -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::FormLiteralOpenParenId /*node_id*/) -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::FormLiteralId /*node_id*/)\n    -> bool {\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_function.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <optional>\n#include <utility>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/decl_introducer_state.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/interface.h\"\n#include \"toolchain/check/literal.h\"\n#include \"toolchain/check/merge.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/return.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/check/unused.h\"\n#include \"toolchain/lex/token_kind.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/builtin_function_kind.h\"\n#include \"toolchain/sem_ir/entry_point.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::FunctionIntroducerId node_id)\n    -> bool {\n  // The function is potentially generic.\n  StartGenericDecl(context);\n  // Create an instruction block to hold the instructions created as part of the\n  // function signature, such as parameter and return types.\n  context.inst_block_stack().Push();\n  // Push the bracketing node.\n  context.node_stack().Push(node_id);\n  // Optional modifiers and the name follow.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Fn>();\n  context.decl_name_stack().PushScopeAndStartName();\n  return true;\n}\n\n// Handles a `->` or `->?` return declaration.\nstatic auto HandleReturnDecl(Context& context, Parse::AnyReturnDeclId node_id)\n    -> bool {\n  auto [expr_node_id, expr_inst_id] = context.node_stack().PopExprWithNodeId();\n  Context::FormExpr form_expr = [&]() {\n    if (context.parse_tree().node_kind(node_id) == Parse::ReturnTypeId::Kind) {\n      return ReturnExprAsForm(context, expr_node_id, expr_inst_id);\n    } else {\n      return FormExprAsForm(context, expr_node_id, expr_inst_id);\n    }\n  }();\n  context.PushReturnForm(form_expr);\n  auto return_patterns_id = AddReturnPatterns(context, node_id, form_expr);\n  context.node_stack().Push(node_id, return_patterns_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ReturnTypeId node_id) -> bool {\n  return HandleReturnDecl(context, node_id);\n}\n\nauto HandleParseNode(Context& context, Parse::ReturnFormId node_id) -> bool {\n  return HandleReturnDecl(context, node_id);\n}\n\n// Diagnoses issues with the modifiers, removing modifiers that shouldn't be\n// present.\nstatic auto DiagnoseModifiers(Context& context,\n                              Parse::AnyFunctionDeclId node_id,\n                              DeclIntroducerState& introducer,\n                              bool is_definition,\n                              SemIR::NameScopeId parent_scope_id,\n                              SemIR::InstId parent_scope_inst_id,\n                              std::optional<SemIR::Inst> parent_scope_inst,\n                              SemIR::InstId self_param_id) -> void {\n  CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);\n  LimitModifiersOnDecl(\n      context, introducer,\n      KeywordModifierSet::Access | KeywordModifierSet::Extern |\n          KeywordModifierSet::Export | KeywordModifierSet::Method |\n          KeywordModifierSet::Interface | KeywordModifierSet::Evaluation);\n  RestrictExternModifierOnDecl(context, introducer, parent_scope_inst,\n                               is_definition);\n  CheckMethodModifiersOnFunction(context, introducer, parent_scope_inst_id,\n                                 parent_scope_inst);\n  RequireDefaultFinalOnlyInInterfaces(context, introducer, parent_scope_id);\n\n  if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Interface)) {\n    // TODO: Once we are saving the modifiers for a function, add check that\n    // the function may only be defined if it is marked `default` or `final`.\n    context.TODO(introducer.modifier_node_id(ModifierOrder::Decl),\n                 \"interface modifier\");\n  }\n\n  if (!self_param_id.has_value() &&\n      introducer.modifier_set.HasAnyOf(KeywordModifierSet::Method)) {\n    CARBON_DIAGNOSTIC(VirtualWithoutSelf, Error, \"virtual class function\");\n    context.emitter().Emit(node_id, VirtualWithoutSelf);\n    introducer.modifier_set.Remove(KeywordModifierSet::Method);\n  }\n}\n\n// Returns the virtual-family modifier as an enum.\nstatic auto GetVirtualModifier(const KeywordModifierSet& modifier_set)\n    -> SemIR::Function::VirtualModifier {\n  return modifier_set.ToEnum<SemIR::Function::VirtualModifier>()\n      .Case(KeywordModifierSet::Virtual,\n            SemIR::Function::VirtualModifier::Virtual)\n      .Case(KeywordModifierSet::Abstract,\n            SemIR::Function::VirtualModifier::Abstract)\n      .Case(KeywordModifierSet::Override,\n            SemIR::Function::VirtualModifier::Override)\n      .Default(SemIR::Function::VirtualModifier::None);\n}\n\n// Returns the evaluation modifier as an enum.\nstatic auto GetEvaluationMode(const KeywordModifierSet& modifier_set)\n    -> SemIR::Function::EvaluationMode {\n  return modifier_set.ToEnum<SemIR::Function::EvaluationMode>()\n      .Case(KeywordModifierSet::Eval, SemIR::Function::EvaluationMode::Eval)\n      .Case(KeywordModifierSet::MustEval,\n            SemIR::Function::EvaluationMode::MustEval)\n      .Default(SemIR::Function::EvaluationMode::None);\n}\n\n// Tries to merge new_function into prev_function_id. Since new_function won't\n// have a definition even if one is upcoming, set is_definition to indicate the\n// planned result.\n//\n// If merging is successful, returns true and may update the previous function.\n// Otherwise, returns false. Prints a diagnostic when appropriate.\nstatic auto MergeFunctionRedecl(Context& context,\n                                Parse::AnyFunctionDeclId node_id,\n                                SemIR::Function& new_function,\n                                bool new_is_definition,\n                                SemIR::FunctionId prev_function_id,\n                                SemIR::ImportIRId prev_import_ir_id) -> bool {\n  auto& prev_function = context.functions().Get(prev_function_id);\n\n  if (!CheckFunctionTypeMatches(context, new_function, prev_function)) {\n    return false;\n  }\n\n  DiagnoseIfInvalidRedecl(\n      context, Lex::TokenKind::Fn, prev_function.name_id,\n      RedeclInfo(new_function, node_id, new_is_definition),\n      RedeclInfo(prev_function, SemIR::LocId(prev_function.latest_decl_id()),\n                 prev_function.has_definition_started()),\n      prev_import_ir_id);\n  if (new_is_definition && prev_function.has_definition_started()) {\n    return false;\n  }\n\n  if (!prev_function.first_owning_decl_id.has_value()) {\n    prev_function.first_owning_decl_id = new_function.first_owning_decl_id;\n  }\n  if (new_is_definition) {\n    // Track the signature from the definition, so that IDs in the body\n    // match IDs in the signature.\n    prev_function.MergeDefinition(new_function);\n    prev_function.call_param_patterns_id = new_function.call_param_patterns_id;\n    prev_function.call_params_id = new_function.call_params_id;\n    prev_function.return_type_inst_id = new_function.return_type_inst_id;\n    prev_function.return_form_inst_id = new_function.return_form_inst_id;\n    prev_function.return_patterns_id = new_function.return_patterns_id;\n    prev_function.self_param_id = new_function.self_param_id;\n  }\n  if (prev_import_ir_id.has_value()) {\n    ReplacePrevInstForMerge(context, new_function.parent_scope_id,\n                            prev_function.name_id,\n                            new_function.first_owning_decl_id);\n  }\n  return true;\n}\n\n// Check whether this is a redeclaration, merging if needed.\nstatic auto TryMergeRedecl(Context& context, Parse::AnyFunctionDeclId node_id,\n                           const DeclNameStack::NameContext& name_context,\n                           SemIR::FunctionDecl& function_decl,\n                           SemIR::Function& function_info, bool is_definition)\n    -> void {\n  if (name_context.state == DeclNameStack::NameContext::State::Poisoned) {\n    DiagnosePoisonedName(context, name_context.name_id_for_new_inst(),\n                         name_context.poisoning_loc_id, name_context.loc_id);\n    return;\n  }\n\n  auto prev_id = name_context.prev_inst_id();\n  if (!prev_id.has_value()) {\n    return;\n  }\n\n  auto prev_function_id = SemIR::FunctionId::None;\n  auto prev_type_id = SemIR::TypeId::None;\n  auto prev_import_ir_id = SemIR::ImportIRId::None;\n  CARBON_KIND_SWITCH(context.insts().Get(prev_id)) {\n    case CARBON_KIND(SemIR::AssociatedEntity assoc_entity): {\n      // This is a function in an interface definition scope (see\n      // NameScope::is_interface_definition()).\n      auto function_decl =\n          context.insts().GetAs<SemIR::FunctionDecl>(assoc_entity.decl_id);\n      prev_function_id = function_decl.function_id;\n      prev_type_id = function_decl.type_id;\n      break;\n    }\n    case CARBON_KIND(SemIR::FunctionDecl function_decl): {\n      prev_function_id = function_decl.function_id;\n      prev_type_id = function_decl.type_id;\n      break;\n    }\n    case SemIR::ImportRefLoaded::Kind: {\n      auto import_ir_inst = GetCanonicalImportIRInst(context, prev_id);\n\n      // Verify the decl so that things like aliases are name conflicts.\n      const auto* import_ir =\n          context.import_irs().Get(import_ir_inst.ir_id()).sem_ir;\n      if (!import_ir->insts().Is<SemIR::FunctionDecl>(\n              import_ir_inst.inst_id())) {\n        break;\n      }\n\n      // Use the type to get the ID.\n      if (auto struct_value = context.insts().TryGetAs<SemIR::StructValue>(\n              context.constant_values().GetConstantInstId(prev_id))) {\n        if (auto function_type = context.types().TryGetAs<SemIR::FunctionType>(\n                struct_value->type_id)) {\n          prev_function_id = function_type->function_id;\n          prev_type_id = struct_value->type_id;\n          prev_import_ir_id = import_ir_inst.ir_id();\n        }\n      }\n      break;\n    }\n    default:\n      break;\n  }\n\n  if (!prev_function_id.has_value()) {\n    DiagnoseDuplicateName(context, name_context.name_id, name_context.loc_id,\n                          SemIR::LocId(prev_id));\n    return;\n  }\n\n  if (MergeFunctionRedecl(context, node_id, function_info, is_definition,\n                          prev_function_id, prev_import_ir_id)) {\n    // When merging, use the existing function rather than adding a new one.\n    function_decl.function_id = prev_function_id;\n    function_decl.type_id = prev_type_id;\n  }\n}\n\n// Adds the declaration to name lookup when appropriate.\nstatic auto MaybeAddToNameLookup(Context& context,\n                                 const DeclNameStack::NameContext& name_context,\n                                 const KeywordModifierSet& modifier_set,\n                                 SemIR::NameScopeId parent_scope_id,\n                                 SemIR::InstId decl_id) -> void {\n  if (name_context.state == DeclNameStack::NameContext::State::Poisoned ||\n      name_context.prev_inst_id().has_value()) {\n    return;\n  }\n\n  // At interface scope, a function declaration introduces an associated\n  // function.\n  auto lookup_result_id = decl_id;\n  if (parent_scope_id.has_value() && !name_context.has_qualifiers) {\n    const auto& parent_scope = context.name_scopes().Get(parent_scope_id);\n    if (parent_scope.is_interface_definition()) {\n      auto interface_decl = context.insts().GetAs<SemIR::InterfaceWithSelfDecl>(\n          parent_scope.inst_id());\n      lookup_result_id =\n          BuildAssociatedEntity(context, interface_decl.interface_id, decl_id);\n    }\n  }\n\n  context.decl_name_stack().AddName(name_context, lookup_result_id,\n                                    modifier_set.GetAccessKind());\n}\n\n// Returns whether the given type is `i32`.\nstatic auto IsI32(Context& context, Parse::NodeId node_id,\n                  SemIR::TypeId type_id) -> bool {\n  return type_id == MakeIntType(context, node_id, SemIR::IntKind::Signed,\n                                context.ints().Add(32));\n}\n\n// Returns whether the given parameter list is valid for the entry point\n// function `Main.Run`.\nstatic auto IsValidEntryPointParamList(Context& context, Parse::NodeId node_id,\n                                       SemIR::InstBlockId param_patterns_id)\n    -> bool {\n  if (!param_patterns_id.has_value()) {\n    // Positional parameters for are not supported.\n    return false;\n  }\n\n  for (auto [index, param_pattern_id] :\n       llvm::enumerate(context.inst_blocks().Get(param_patterns_id))) {\n    if (param_pattern_id == SemIR::ErrorInst::InstId) {\n      // Ignore erroneous parameters.\n      continue;\n    }\n\n    auto param =\n        context.insts().TryGetAs<SemIR::ValueParamPattern>(param_pattern_id);\n    if (!param) {\n      // Only value parameters are supported for now.\n      return false;\n    }\n\n    if (param->type_id == SemIR::ErrorInst::TypeId) {\n      // Ignore parameters with erroneous types.\n      continue;\n    }\n\n    auto param_type_inst_id = context.types()\n                                  .GetAs<SemIR::PatternType>(param->type_id)\n                                  .scrutinee_type_inst_id;\n    switch (index) {\n      case 0: {\n        // `argc` should be a 32-bit integer.\n        if (!IsI32(\n                context, node_id,\n                context.types().GetTypeIdForTypeInstId(param_type_inst_id))) {\n          return false;\n        }\n        break;\n      }\n      case 1: {\n        // `argv` should be a pointer.\n        // TODO: Consider checking the pointee type also.\n        if (!context.insts().Is<SemIR::PointerType>(param_type_inst_id)) {\n          return false;\n        }\n        break;\n      }\n      default: {\n        // TODO: Decide whether to allow a third `envp` parameter.\n        return false;\n      }\n    }\n  }\n\n  return true;\n}\n\n// Returns whether the given return type is valid for the entry point\n// function `Main.Run`.\nstatic auto IsValidEntryPointReturnType(Context& context, Parse::NodeId node_id,\n                                        SemIR::TypeId return_type_id) -> bool {\n  // An implicit or explicit return type of `()` is OK.\n  // TODO: Translate this to returning an `i32` with value `0` in lowering.\n  if (!return_type_id.has_value()) {\n    return true;\n  }\n  if (return_type_id == GetTupleType(context, {})) {\n    return true;\n  }\n\n  if (IsI32(context, node_id, return_type_id)) {\n    // Explicit return type of `i32` or an adapter for it is OK.\n    return true;\n  }\n\n  // For now, disallow anything else.\n  // TODO: Decide on valid return types for `Main.Run`. Perhaps we should\n  // have an interface for this.\n  return false;\n}\n\n// If the function is the entry point, do corresponding validation.\nstatic auto ValidateForEntryPoint(Context& context,\n                                  Parse::AnyFunctionDeclId node_id,\n                                  SemIR::FunctionId function_id,\n                                  const SemIR::Function& function_info)\n    -> void {\n  if (!SemIR::IsEntryPoint(context.sem_ir(), function_id)) {\n    return;\n  }\n\n  // TODO: Update this once valid signatures for the entry point are decided.\n  // See https://github.com/carbon-language/carbon-lang/issues/6735\n  if (function_info.implicit_param_patterns_id.has_value() ||\n      !IsValidEntryPointParamList(context, node_id,\n                                  function_info.param_patterns_id)) {\n    CARBON_DIAGNOSTIC(InvalidMainRunParameters, Error,\n                      \"invalid parameters for `Main.Run` function; expected \"\n                      \"`()` or `(argc: i32, argv: Core.Optional(char*)*)`\");\n    context.emitter().Emit(node_id, InvalidMainRunParameters);\n  } else if (!IsValidEntryPointReturnType(\n                 context, node_id,\n                 function_info.GetDeclaredReturnType(context.sem_ir()))) {\n    CARBON_DIAGNOSTIC(InvalidMainRunReturnType, Error,\n                      \"invalid return type for `Main.Run` function; expected \"\n                      \"`fn (...)` or `fn (...) -> i32`\");\n    context.emitter().Emit(node_id, InvalidMainRunReturnType);\n  }\n}\n\nstatic auto IsGenericFunction(Context& context,\n                              SemIR::GenericId function_generic_id,\n                              SemIR::GenericId class_generic_id) -> bool {\n  if (function_generic_id == SemIR::GenericId::None) {\n    return false;\n  }\n\n  if (class_generic_id == SemIR::GenericId::None) {\n    return true;\n  }\n\n  const auto& function_generic = context.generics().Get(function_generic_id);\n  const auto& class_generic = context.generics().Get(class_generic_id);\n\n  auto function_bindings =\n      context.inst_blocks().Get(function_generic.bindings_id);\n  auto class_bindings = context.inst_blocks().Get(class_generic.bindings_id);\n\n  // If the function's bindings are the same size as the class's bindings,\n  // then there are no extra bindings for the function, so it is effectively\n  // non-generic within the scope of a specific of the class.\n  return class_bindings.size() != function_bindings.size();\n}\n\n// Requests a vtable be created when processing a virtual function.\nstatic auto RequestVtableIfVirtual(\n    Context& context, Parse::AnyFunctionDeclId node_id,\n    SemIR::Function::VirtualModifier& virtual_modifier,\n    const std::optional<SemIR::Inst>& parent_scope_inst, SemIR::InstId decl_id,\n    SemIR::GenericId generic_id) -> void {\n  // In order to request a vtable, the function must be virtual, and in a class\n  // scope.\n  if (virtual_modifier == SemIR::Function::VirtualModifier::None ||\n      !parent_scope_inst) {\n    return;\n  }\n  auto class_decl = parent_scope_inst->TryAs<SemIR::ClassDecl>();\n  if (!class_decl) {\n    return;\n  }\n\n  auto& class_info = context.classes().Get(class_decl->class_id);\n  if (virtual_modifier == SemIR::Function::VirtualModifier::Override &&\n      !class_info.base_id.has_value()) {\n    CARBON_DIAGNOSTIC(OverrideWithoutBase, Error,\n                      \"override without base class\");\n    context.emitter().Emit(node_id, OverrideWithoutBase);\n    virtual_modifier = SemIR::Function::VirtualModifier::None;\n    return;\n  }\n\n  if (IsGenericFunction(context, generic_id, class_info.generic_id)) {\n    CARBON_DIAGNOSTIC(GenericVirtual, Error, \"generic virtual function\");\n    context.emitter().Emit(node_id, GenericVirtual);\n    virtual_modifier = SemIR::Function::VirtualModifier::None;\n    return;\n  }\n\n  // TODO: If this is an `impl` function, check there's a matching base\n  // function that's impl or virtual.\n  class_info.is_dynamic = true;\n  context.vtable_stack().AddInstId(decl_id);\n}\n\n// Diagnoses when positional params aren't supported. Reassigns the pattern\n// block if needed.\nstatic auto DiagnosePositionalParams(Context& context,\n                                     SemIR::Function& function_info) -> void {\n  if (function_info.param_patterns_id.has_value()) {\n    return;\n  }\n\n  context.TODO(function_info.latest_decl_id(),\n               \"function with positional parameters\");\n  function_info.param_patterns_id = SemIR::InstBlockId::Empty;\n}\n\n// Build a FunctionDecl describing the signature of a function. This\n// handles the common logic shared by function declaration syntax and function\n// definition syntax.\nstatic auto BuildFunctionDecl(Context& context,\n                              Parse::AnyFunctionDeclId node_id,\n                              bool is_definition)\n    -> std::pair<SemIR::FunctionId, SemIR::InstId> {\n  auto return_patterns_id = SemIR::InstBlockId::None;\n  auto return_type_inst_id = SemIR::TypeInstId::None;\n  auto return_form_inst_id = SemIR::InstId::None;\n  if (auto [return_node, maybe_return_patterns_id] =\n          context.node_stack()\n              .PopWithNodeIdIf<Parse::NodeCategory::ReturnDecl>();\n      maybe_return_patterns_id) {\n    return_patterns_id = *maybe_return_patterns_id;\n    auto return_form = context.PopReturnForm();\n    return_type_inst_id = return_form.type_component_inst_id;\n    return_form_inst_id = return_form.form_inst_id;\n  }\n\n  auto name = PopNameComponent(context, return_patterns_id);\n  auto name_context = context.decl_name_stack().FinishName(name);\n\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::FunctionIntroducer>();\n\n  auto self_param_id =\n      FindSelfPattern(context, name.implicit_param_patterns_id);\n\n  // Process modifiers.\n  auto [parent_scope_inst_id, parent_scope_inst] =\n      context.name_scopes().GetInstIfValid(name_context.parent_scope_id);\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Fn>();\n  DiagnoseModifiers(context, node_id, introducer, is_definition,\n                    name_context.parent_scope_id, parent_scope_inst_id,\n                    parent_scope_inst, self_param_id);\n  bool is_extern = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extern);\n  auto virtual_modifier = GetVirtualModifier(introducer.modifier_set);\n  auto evaluation_mode = GetEvaluationMode(introducer.modifier_set);\n\n  // Add the function declaration.\n  SemIR::FunctionDecl function_decl = {SemIR::TypeId::None,\n                                       SemIR::FunctionId::None,\n                                       context.inst_block_stack().Pop()};\n  auto decl_id = AddPlaceholderInst(context, node_id, function_decl);\n\n  // Build the function entity. This will be merged into an existing function if\n  // there is one, or otherwise added to the function store.\n  auto function_info =\n      SemIR::Function{name_context.MakeEntityWithParamsBase(\n                          name, decl_id, is_extern, introducer.extern_library),\n                      {.call_param_patterns_id = name.call_param_patterns_id,\n                       .call_params_id = name.call_params_id,\n                       .call_param_ranges = name.param_ranges,\n                       .return_type_inst_id = return_type_inst_id,\n                       .return_form_inst_id = return_form_inst_id,\n                       .return_patterns_id = return_patterns_id,\n                       .virtual_modifier = virtual_modifier,\n                       .evaluation_mode = evaluation_mode,\n                       .self_param_id = self_param_id}};\n  if (is_definition) {\n    function_info.definition_id = decl_id;\n  }\n\n  DiagnosePositionalParams(context, function_info);\n\n  TryMergeRedecl(context, node_id, name_context, function_decl, function_info,\n                 is_definition);\n\n  // Create a new function if this isn't a valid redeclaration.\n  if (!function_decl.function_id.has_value()) {\n    if (function_info.is_extern && context.sem_ir().is_impl()) {\n      DiagnoseExternRequiresDeclInApiFile(context, node_id);\n    }\n    function_info.generic_id = BuildGenericDecl(context, decl_id);\n    function_decl.function_id = context.functions().Add(function_info);\n    function_decl.type_id =\n        GetFunctionType(context, function_decl.function_id,\n                        context.scope_stack().PeekSpecificId());\n  } else {\n    auto prev_decl_generic_id =\n        context.functions().Get(function_decl.function_id).generic_id;\n    FinishGenericRedecl(context, prev_decl_generic_id);\n    // TODO: Validate that the redeclaration doesn't set an access modifier.\n  }\n\n  RequestVtableIfVirtual(context, node_id, function_info.virtual_modifier,\n                         parent_scope_inst, decl_id, function_info.generic_id);\n\n  // Write the function ID into the FunctionDecl.\n  ReplaceInstBeforeConstantUse(context, decl_id, function_decl);\n\n  // Diagnose 'definition of `abstract` function' using the canonical Function's\n  // modifiers.\n  if (is_definition &&\n      context.functions().Get(function_decl.function_id).virtual_modifier ==\n          SemIR::Function::VirtualModifier::Abstract) {\n    CARBON_DIAGNOSTIC(DefinedAbstractFunction, Error,\n                      \"definition of `abstract` function\");\n    context.emitter().Emit(LocIdForDiagnostics::TokenOnly(node_id),\n                           DefinedAbstractFunction);\n  }\n\n  // Add to name lookup if needed, now that the decl is built.\n  MaybeAddToNameLookup(context, name_context, introducer.modifier_set,\n                       name_context.parent_scope_id, decl_id);\n\n  ValidateForEntryPoint(context, node_id, function_decl.function_id,\n                        function_info);\n\n  if (!is_definition && context.sem_ir().is_impl() && !is_extern) {\n    context.definitions_required_by_decl().push_back(decl_id);\n  }\n\n  return {function_decl.function_id, decl_id};\n}\n\n// Checks that \"unused\" marker is only used in definitions, and emits a\n// diagnostic for every binding that is marked unused.\nstatic auto CheckUnusedBindingsInPattern(Context& context,\n                                         SemIR::InstId pattern_id) -> void {\n  llvm::SmallVector<SemIR::InstId> work_list;\n  work_list.push_back(pattern_id);\n\n  while (!work_list.empty()) {\n    auto current_id = work_list.pop_back_val();\n    auto inst = context.insts().Get(current_id);\n    CARBON_KIND_SWITCH(inst) {\n      case CARBON_KIND_ANY(SemIR::AnyParamPattern, param): {\n        work_list.push_back(param.subpattern_id);\n        break;\n      }\n      case CARBON_KIND_ANY(SemIR::AnyBindingPattern, bind): {\n        auto& entity_name = context.entity_names().Get(bind.entity_name_id);\n        // We need special treatment for the name \"_\" which is implicitly\n        // unused but actually permitted in declarations.\n        if (entity_name.is_unused &&\n            entity_name.name_id != SemIR::NameId::Underscore) {\n          CARBON_DIAGNOSTIC(UnusedModifierOnDeclaration, Error,\n                            \"`unused` modifier on declaration\");\n          context.emitter().Emit(current_id, UnusedModifierOnDeclaration);\n        }\n        break;\n      }\n      case CARBON_KIND(SemIR::VarPattern var_pattern): {\n        work_list.push_back(var_pattern.subpattern_id);\n        break;\n      }\n      case CARBON_KIND(SemIR::TuplePattern tuple_pattern): {\n        auto elements = context.inst_blocks().Get(tuple_pattern.elements_id);\n        for (auto element_id : llvm::reverse(elements)) {\n          work_list.push_back(element_id);\n        }\n        break;\n      }\n      default:\n        break;\n    }\n  }\n}\n\nstatic auto DiagnoseUnusedMarkersInDeclaration(Context& context,\n                                               SemIR::FunctionId function_id)\n    -> void {\n  const auto& function = context.functions().Get(function_id);\n  if (function.param_patterns_id.has_value()) {\n    for (auto pattern_id :\n         context.inst_blocks().Get(function.param_patterns_id)) {\n      CheckUnusedBindingsInPattern(context, pattern_id);\n    }\n  }\n}\n\nauto HandleParseNode(Context& context, Parse::FunctionDeclId node_id) -> bool {\n  auto [function_id, decl_id] =\n      BuildFunctionDecl(context, node_id, /*is_definition=*/false);\n  DiagnoseUnusedMarkersInDeclaration(context, function_id);\n  context.decl_name_stack().PopScope();\n  return true;\n}\n\n// Processes a function definition after a signature for which we have already\n// built a function ID. This logic is shared between processing regular function\n// definitions and delayed parsing of inline method definitions.\nstatic auto HandleFunctionDefinitionAfterSignature(\n    Context& context, Parse::FunctionDefinitionStartId node_id,\n    SemIR::FunctionId function_id, SemIR::InstId decl_id) -> void {\n  StartFunctionDefinition(context, decl_id, function_id);\n  context.node_stack().Push(node_id, function_id);\n}\n\nauto HandleFunctionDefinitionSuspend(Context& context,\n                                     Parse::FunctionDefinitionStartId node_id)\n    -> DeferredDefinitionWorklist::SuspendedFunction {\n  // Process the declaration portion of the function.\n  auto [function_id, decl_id] =\n      BuildFunctionDecl(context, node_id, /*is_definition=*/true);\n  return {.function_id = function_id,\n          .decl_id = decl_id,\n          .saved_name_state = context.decl_name_stack().Suspend()};\n}\n\nauto HandleFunctionDefinitionResume(\n    Context& context, Parse::FunctionDefinitionStartId node_id,\n    DeferredDefinitionWorklist::SuspendedFunction&& suspended_fn) -> void {\n  context.decl_name_stack().Restore(std::move(suspended_fn.saved_name_state));\n  HandleFunctionDefinitionAfterSignature(\n      context, node_id, suspended_fn.function_id, suspended_fn.decl_id);\n}\n\nauto HandleParseNode(Context& context, Parse::FunctionDefinitionStartId node_id)\n    -> bool {\n  // Process the declaration portion of the function.\n  auto [function_id, decl_id] =\n      BuildFunctionDecl(context, node_id, /*is_definition=*/true);\n  HandleFunctionDefinitionAfterSignature(context, node_id, function_id,\n                                         decl_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::FunctionDefinitionId node_id)\n    -> bool {\n  SemIR::FunctionId function_id =\n      context.node_stack().Pop<Parse::NodeKind::FunctionDefinitionStart>();\n\n  // If the `}` of the function is reachable, reject if we need a return value\n  // and otherwise add an implicit `return;`.\n  if (IsCurrentPositionReachable(context)) {\n    if (context.functions().Get(function_id).return_form_inst_id.has_value()) {\n      CARBON_DIAGNOSTIC(\n          MissingReturnStatement, Error,\n          \"missing `return` at end of function with declared return type\");\n      context.emitter().Emit(LocIdForDiagnostics::TokenOnly(node_id),\n                             MissingReturnStatement);\n    } else {\n      AddReturnCleanupBlock(context, node_id);\n    }\n  }\n\n  FinishFunctionDefinition(context, function_id);\n  context.decl_name_stack().PopScope(/*check_unused=*/true);\n\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::BuiltinFunctionDefinitionStartId node_id) -> bool {\n  // Process the declaration portion of the function.\n  auto [function_id, _] =\n      BuildFunctionDecl(context, node_id, /*is_definition=*/true);\n  context.node_stack().Push(node_id, function_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::BuiltinNameId node_id) -> bool {\n  context.node_stack().Push(node_id);\n  return true;\n}\n\n// Looks up a builtin function kind given its name as a string.\n// TODO: Move this out to another file.\nstatic auto LookupBuiltinFunctionKind(Context& context,\n                                      Parse::BuiltinNameId name_id)\n    -> SemIR::BuiltinFunctionKind {\n  auto builtin_name = context.string_literal_values().Get(\n      context.tokens().GetStringLiteralValue(\n          context.parse_tree().node_token(name_id)));\n  auto kind = SemIR::BuiltinFunctionKind::ForBuiltinName(builtin_name);\n  if (kind == SemIR::BuiltinFunctionKind::None) {\n    CARBON_DIAGNOSTIC(UnknownBuiltinFunctionName, Error,\n                      \"unknown builtin function name \\\"{0}\\\"\", std::string);\n    context.emitter().Emit(name_id, UnknownBuiltinFunctionName,\n                           builtin_name.str());\n  }\n  return kind;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::BuiltinFunctionDefinitionId /*node_id*/) -> bool {\n  auto name_id =\n      context.node_stack().PopForSoloNodeId<Parse::NodeKind::BuiltinName>();\n  auto [fn_node_id, function_id] =\n      context.node_stack()\n          .PopWithNodeId<Parse::NodeKind::BuiltinFunctionDefinitionStart>();\n\n  auto builtin_kind = LookupBuiltinFunctionKind(context, name_id);\n  if (builtin_kind != SemIR::BuiltinFunctionKind::None) {\n    CheckFunctionDefinitionSignature(context, function_id);\n\n    auto& function = context.functions().Get(function_id);\n    if (IsValidBuiltinDeclaration(context, function, builtin_kind)) {\n      function.SetBuiltinFunction(builtin_kind);\n      // Build an empty generic definition if this is a generic builtin.\n      StartGenericDefinition(context, function.generic_id);\n      FinishGenericDefinition(context, function.generic_id);\n    } else {\n      CARBON_DIAGNOSTIC(InvalidBuiltinSignature, Error,\n                        \"invalid signature for builtin function \\\"{0}\\\"\",\n                        std::string);\n      context.emitter().Emit(fn_node_id, InvalidBuiltinSignature,\n                             builtin_kind.name().str());\n    }\n  }\n  context.decl_name_stack().PopScope();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::FunctionTerseDefinitionId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleFunctionTerseDefinition\");\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_if_expr.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/literal.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::IfExprIfId node_id) -> bool {\n  // Alias node_id for if/then/else consistency.\n  auto& if_node = node_id;\n\n  auto [cond_node, cond_value_id] = context.node_stack().PopExprWithNodeId();\n\n  // Convert the condition to `bool`, and branch on it.\n  cond_value_id = ConvertToBoolValue(context, if_node, cond_value_id);\n  context.node_stack().Push(cond_node, cond_value_id);\n  auto then_block_id =\n      AddDominatedBlockAndBranchIf(context, if_node, cond_value_id);\n  auto else_block_id = AddDominatedBlockAndBranch(context, if_node);\n\n  // Start emitting the `then` block.\n  context.inst_block_stack().Pop();\n  context.inst_block_stack().Push(then_block_id);\n  context.region_stack().AddToRegion(then_block_id, node_id);\n\n  context.node_stack().Push(if_node, else_block_id);\n  return true;\n}\n\n// If the operand is an `IntLiteral`, convert it to a suitably-sized `Int` type.\n// TODO: For now we always pick `i32`.\nstatic auto DecayIntLiteralToSizedInt(Context& context, Parse::NodeId node_id,\n                                      SemIR::InstId operand_id)\n    -> SemIR::InstId {\n  if (context.types().GetTypeInstId(\n          context.insts().Get(operand_id).type_id()) ==\n      SemIR::IntLiteralType::TypeInstId) {\n    operand_id = ConvertToValueOfType(\n        context, node_id, operand_id,\n        MakeIntType(context, node_id, SemIR::IntKind::Signed,\n                    context.ints().Add(32)));\n  }\n  return operand_id;\n}\n\nauto HandleParseNode(Context& context, Parse::IfExprThenId node_id) -> bool {\n  auto then_value_id = context.node_stack().PopExpr();\n  auto else_block_id = context.node_stack().Peek<Parse::NodeKind::IfExprIf>();\n\n  // Convert the first operand to a value.\n  then_value_id = ConvertToValueExpr(context, then_value_id);\n  then_value_id = DecayIntLiteralToSizedInt(context, node_id, then_value_id);\n\n  // Start emitting the `else` block.\n  context.inst_block_stack().Push(else_block_id);\n  context.region_stack().AddToRegion(else_block_id, node_id);\n\n  context.node_stack().Push(node_id, then_value_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::IfExprElseId node_id) -> bool {\n  if (!context.scope_stack().IsInFunctionScope()) {\n    return context.TODO(node_id,\n                        \"Control flow expressions are currently only supported \"\n                        \"inside functions.\");\n  }\n  // Alias node_id for if/then/else consistency.\n  auto& else_node = node_id;\n\n  auto else_value_id = context.node_stack().PopExpr();\n  auto then_value_id = context.node_stack().Pop<Parse::NodeKind::IfExprThen>();\n  auto [if_node, _] =\n      context.node_stack().PopWithNodeId<Parse::NodeKind::IfExprIf>();\n  auto cond_value_id = context.node_stack().PopExpr();\n\n  // Convert the `else` value to the `then` value's type, and finish the `else`\n  // block.\n  // TODO: Find a common type, and convert both operands to it instead.\n  auto result_type_id = context.insts().Get(then_value_id).type_id();\n  else_value_id =\n      ConvertToValueOfType(context, else_node, else_value_id, result_type_id);\n\n  // Create a resumption block and branches to it.\n  auto chosen_value_id = AddConvergenceBlockWithArgAndPush(\n      context, if_node, {else_value_id, then_value_id});\n  SetBlockArgResultBeforeConstantUse(context, chosen_value_id, cond_value_id,\n                                     then_value_id, else_value_id);\n\n  // Push the result value.\n  context.node_stack().Push(else_node, chosen_value_id);\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_if_statement.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::IfConditionStartId /*node_id*/) -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::IfConditionId node_id) -> bool {\n  // Convert the condition to `bool`.\n  auto cond_value_id = context.node_stack().PopExpr();\n  cond_value_id = ConvertToBoolValue(context, node_id, cond_value_id);\n\n  // Create the then block and the else block, and branch to the right one. If\n  // there is no `else`, the then block will terminate with a branch to the\n  // else block, which will be reused as the resumption block.\n  auto then_block_id =\n      AddDominatedBlockAndBranchIf(context, node_id, cond_value_id);\n  auto else_block_id = AddDominatedBlockAndBranch(context, node_id);\n\n  // Start emitting the `then` block.\n  context.inst_block_stack().Pop();\n  context.inst_block_stack().Push(then_block_id);\n  context.region_stack().AddToRegion(then_block_id, node_id);\n\n  context.node_stack().Push(node_id, else_block_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::IfStatementElseId node_id)\n    -> bool {\n  auto else_block_id = context.node_stack().Pop<Parse::NodeKind::IfCondition>();\n\n  // Switch to emitting the `else` block.\n  context.inst_block_stack().Push(else_block_id);\n  context.region_stack().AddToRegion(else_block_id, node_id);\n\n  context.node_stack().Push(node_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::IfStatementId node_id) -> bool {\n  switch (auto kind = context.node_stack().PeekNodeKind()) {\n    case Parse::NodeKind::IfCondition: {\n      // Branch from then block to else block, and start emitting the else\n      // block.\n      auto else_block_id =\n          context.node_stack().Pop<Parse::NodeKind::IfCondition>();\n      AddInst<SemIR::Branch>(context, node_id, {.target_id = else_block_id});\n      context.inst_block_stack().Pop();\n      context.inst_block_stack().Push(else_block_id);\n      context.region_stack().AddToRegion(else_block_id, node_id);\n      break;\n    }\n\n    case Parse::NodeKind::IfStatementElse: {\n      // Branch from the then and else blocks to a new resumption block.\n      context.node_stack()\n          .PopAndDiscardSoloNodeId<Parse::NodeKind::IfStatementElse>();\n      AddConvergenceBlockAndPush(context, node_id, /*num_blocks=*/2);\n      break;\n    }\n\n    default: {\n      CARBON_FATAL(\"Unexpected parse node at start of `if`: {0}\", kind);\n    }\n  }\n\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_impl.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <optional>\n#include <utility>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/decl_name_stack.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/impl.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/name_scope.h\"\n#include \"toolchain/check/pattern_match.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/parse/typed_nodes.h\"\n#include \"toolchain/sem_ir/generic.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/specific_interface.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Returns the implicit `Self` type for an `impl` when it's in a `class`\n// declaration.\n//\n// TODO: Mixin scopes also have a default `Self` type.\nstatic auto GetImplDefaultSelfType(Context& context,\n                                   const ClassScope& class_scope)\n    -> SemIR::TypeId {\n  return context.classes().Get(class_scope.class_decl.class_id).self_type_id;\n}\n\nauto HandleParseNode(Context& context, Parse::ImplIntroducerId node_id)\n    -> bool {\n  // This might be a generic impl.\n  StartGenericDecl(context);\n\n  // Create an instruction block to hold the instructions created for the type\n  // and interface.\n  context.inst_block_stack().Push();\n\n  // Push the bracketing node.\n  context.node_stack().Push(node_id);\n\n  // Optional modifiers follow.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Impl>();\n\n  // An impl doesn't have a name per se, but it makes the processing more\n  // consistent to imagine that it does. This also gives us a scope for implicit\n  // parameters.\n  context.decl_name_stack().PushScopeAndStartName();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ForallId /*node_id*/) -> bool {\n  // Push a pattern block for the signature of the `forall`.\n  context.pattern_block_stack().Push();\n  context.full_pattern_stack().PushParameterizedDecl();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ImplTypeAsId node_id) -> bool {\n  auto [self_node, self_id] = context.node_stack().PopExprWithNodeId();\n  auto self_type = ExprAsType(context, self_node, self_id);\n\n  const auto& introducer = context.decl_introducer_state_stack().innermost();\n  if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {\n    // TODO: Also handle the parent scope being a mixin.\n    if (auto class_scope = TryAsClassScope(\n            context, context.decl_name_stack().PeekParentScopeId())) {\n      // If we're not inside a class at all, that will be diagnosed against the\n      // `extend` elsewhere.\n      auto extend_node = introducer.modifier_node_id(ModifierOrder::Extend);\n      CARBON_DIAGNOSTIC(ExtendImplSelfAs, Error,\n                        \"cannot `extend` an `impl` with an explicit self type\");\n      auto diag = context.emitter().Build(extend_node, ExtendImplSelfAs);\n\n      if (self_type.type_id == GetImplDefaultSelfType(context, *class_scope)) {\n        // If the explicit self type is the default, suggest removing it with a\n        // diagnostic, but continue as if no error occurred since the self-type\n        // is semantically valid.\n        CARBON_DIAGNOSTIC(ExtendImplSelfAsDefault, Note,\n                          \"remove the explicit `Self` type here\");\n        diag.Note(self_node, ExtendImplSelfAsDefault);\n        if (self_type.type_id != SemIR::ErrorInst::TypeId) {\n          diag.Emit();\n        }\n      } else if (self_type.type_id != SemIR::ErrorInst::TypeId) {\n        // Otherwise, the self-type is an error.\n        diag.Emit();\n        self_type.inst_id = SemIR::ErrorInst::TypeInstId;\n      }\n    }\n  }\n\n  // Introduce `Self`. Note that we add this name lexically rather than adding\n  // to the `NameScopeId` of the `impl`, because this happens before we enter\n  // the `impl` scope or even identify which `impl` we're declaring.\n  // TODO: Revisit this once #3714 is resolved.\n  AddNameToLookup(context, SemIR::NameId::SelfType, self_type.inst_id);\n  context.node_stack().Push(node_id, self_type.inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ImplDefaultSelfAsId node_id)\n    -> bool {\n  auto self_inst_id = SemIR::TypeInstId::None;\n\n  if (auto class_scope = TryAsClassScope(\n          context, context.decl_name_stack().PeekParentScopeId())) {\n    auto self_type_id = GetImplDefaultSelfType(context, *class_scope);\n    // Build the implicit access to the enclosing `Self`.\n    // TODO: Consider calling `HandleNameAsExpr` to build this implicit `Self`\n    // expression. We've already done the work to check that the enclosing\n    // context is a class and found its `Self`, so additionally performing an\n    // unqualified name lookup would be redundant work, but would avoid\n    // duplicating the handling of the `Self` expression.\n    self_inst_id = AddTypeInst(\n        context, node_id,\n        SemIR::NameRef{\n            .type_id = SemIR::TypeType::TypeId,\n            .name_id = SemIR::NameId::SelfType,\n            .value_id = context.types().GetTypeInstId(self_type_id)});\n  } else {\n    CARBON_DIAGNOSTIC(ImplAsOutsideClass, Error,\n                      \"`impl as` can only be used in a class\");\n    context.emitter().Emit(node_id, ImplAsOutsideClass);\n    self_inst_id = SemIR::ErrorInst::TypeInstId;\n  }\n\n  // There's no need to push `Self` into scope here, because we can find it in\n  // the parent class scope.\n  context.node_stack().Push(node_id, self_inst_id);\n  return true;\n}\n\n// Pops the parameters of an `impl`, forming a `NameComponent` with no\n// associated name that describes them.\nstatic auto PopImplIntroducerAndParamsAsNameComponent(\n    Context& context, Parse::AnyImplDeclId end_of_decl_node_id)\n    -> NameComponent {\n  auto [implicit_params_loc_id, implicit_param_patterns_id] =\n      context.node_stack()\n          .PopWithNodeIdIf<Parse::NodeKind::ImplicitParamList>();\n\n  if (implicit_param_patterns_id) {\n    context.node_stack()\n        .PopAndDiscardSoloNodeId<Parse::NodeKind::ImplicitParamListStart>();\n    // Emit the `forall` match. This shouldn't produce any valid `Call` params,\n    // because `impl`s are never actually called at runtime.\n    auto match_results =\n        CalleePatternMatch(context, *implicit_param_patterns_id,\n                           SemIR::InstBlockId::None, SemIR::InstBlockId::None);\n    CARBON_CHECK(match_results.call_params_id == SemIR::InstBlockId::Empty);\n    CARBON_CHECK(match_results.call_param_patterns_id ==\n                 SemIR::InstBlockId::Empty);\n  }\n\n  Parse::NodeId first_param_node_id =\n      context.node_stack().PopForSoloNodeId<Parse::NodeKind::ImplIntroducer>();\n  // Subtracting 1 since we don't want to include the final `{` or `;` of the\n  // declaration when performing syntactic match.\n  Parse::Tree::PostorderIterator last_param_iter(end_of_decl_node_id);\n  --last_param_iter;\n\n  auto pattern_block_id = SemIR::InstBlockId::None;\n  if (implicit_param_patterns_id) {\n    pattern_block_id = context.pattern_block_stack().Pop();\n    context.full_pattern_stack().PopFullPattern();\n  }\n  return {.name_loc_id = Parse::NodeId::None,\n          .name_id = SemIR::NameId::None,\n          .first_param_node_id = first_param_node_id,\n          .last_param_node_id = *last_param_iter,\n          .implicit_params_loc_id = implicit_params_loc_id,\n          .implicit_param_patterns_id =\n              implicit_param_patterns_id.value_or(SemIR::InstBlockId::None),\n          .params_loc_id = Parse::NodeId::None,\n          .param_patterns_id = SemIR::InstBlockId::None,\n          .call_param_patterns_id = SemIR::InstBlockId::None,\n          .call_params_id = SemIR::InstBlockId::None,\n          .param_ranges = SemIR::Function::CallParamIndexRanges::Empty,\n          .pattern_block_id = pattern_block_id};\n}\n\n// Build an ImplDecl describing the signature of an impl. This handles the\n// common logic shared by impl forward declarations and impl definitions.\nstatic auto BuildImplDecl(Context& context, Parse::AnyImplDeclId node_id)\n    -> std::pair<SemIR::ImplId, SemIR::InstId> {\n  auto [constraint_node, constraint_id] =\n      context.node_stack().PopExprWithNodeId();\n  auto [self_type_node, self_type_inst_id] =\n      context.node_stack().PopWithNodeId<Parse::NodeCategory::ImplAs>();\n  // Pop the `impl` introducer and any `forall` parameters as a \"name\".\n  auto name = PopImplIntroducerAndParamsAsNameComponent(context, node_id);\n  auto decl_block_id = context.inst_block_stack().Pop();\n\n  // Convert the constraint expression to a type.\n  auto [constraint_type_inst_id, constraint_type_id] =\n      ExprAsType(context, constraint_node, constraint_id);\n\n  // Process modifiers.\n  // TODO: Should we somehow permit access specifiers on `impl`s?\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Impl>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::ImplDecl);\n\n  bool is_final = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Final);\n\n  // Finish processing the name, which should be empty, but might have\n  // parameters.\n  auto name_context = context.decl_name_stack().FinishImplName();\n  CARBON_CHECK(name_context.state == DeclNameStack::NameContext::State::Empty);\n\n  // TODO: Check for an orphan `impl`.\n\n  // Add the impl declaration.\n  auto impl_decl_id =\n      AddPlaceholderInst(context, node_id,\n                         SemIR::ImplDecl{.impl_id = SemIR::ImplId::None,\n                                         .decl_block_id = decl_block_id});\n\n  // This requires that the facet type is identified. It returns None if an\n  // error was diagnosed.\n  auto specific_interface = CheckConstraintIsInterface(\n      context, impl_decl_id, self_type_inst_id, constraint_type_inst_id);\n\n  auto impl_id = SemIR::ImplId::None;\n  {\n    SemIR::Impl impl = {name_context.MakeEntityWithParamsBase(\n                            name, impl_decl_id,\n                            /*is_extern=*/false, SemIR::LibraryNameId::None),\n                        {.self_id = self_type_inst_id,\n                         .constraint_id = constraint_type_inst_id,\n                         .interface = specific_interface,\n                         .is_final = is_final}};\n    // There's a bunch of places that may represent a diagnostic that occurred\n    // in checking the impl up to this point, which we consolidate into this\n    // bool. Due to lack of an instruction to set to `ErrorInst`, an\n    // `InterfaceId::None` indicates that the interface could not be identified\n    // and an error was diagnosed.\n    bool impl_had_error =\n        context.types().GetTypeIdForTypeInstId(impl.self_id) ==\n            SemIR::ErrorInst::TypeId ||\n        context.types().GetTypeIdForTypeInstId(impl.constraint_id) ==\n            SemIR::ErrorInst::TypeId ||\n        !impl.interface.interface_id.has_value();\n\n    CARBON_KIND_SWITCH(FindImplId(context, impl)) {\n      case CARBON_KIND(RedeclaredImpl redeclared_impl): {\n        // This is a redeclaration of another impl, now held in `impl_id`.\n        impl_id = redeclared_impl.prev_impl_id;\n\n        // Note that we don't reconstruct the witness for a redeclaration, which\n        // was the instruction that came last in the first declaration's eval\n        // block. And FinishGenericRedecl allows the redecl to have fewer\n        // instructions to support this case.\n        const auto& prev_impl = context.impls().Get(impl_id);\n        FinishGenericRedecl(context, prev_impl.generic_id);\n        break;\n      }\n      case CARBON_KIND(NewImpl new_impl): {\n        // This is a new declaration (possibly with an attached definition).\n        // Create a new `impl_id`, filling the missing generic and witness in\n        // `Impl` structure.\n        impl_had_error |= new_impl.find_had_error;\n\n        impl.generic_id = BuildGeneric(context, impl_decl_id);\n\n        if (impl_had_error) {\n          // If there's any error in the construction of the impl, then the\n          // witness can't be constructed. We set it to `ErrorInst` to make the\n          // impl unusable for impl lookup.\n          impl.witness_id = SemIR::ErrorInst::InstId;\n        } else {\n          context.inst_block_stack().Push();\n          // This makes either a placeholder witness table or a full witness\n          // table. The full witness table is deferred to the impl definition\n          // unless the declaration uses rewrite constraints to set values of\n          // associated constants in the interface.\n          //\n          // The witness instruction contains the SelfSpecific that is\n          // constructed by BuildGeneric(), but the witness and its rewrites\n          // also must be part of the generic eval block by coming before\n          // FinishGenericDecl().\n          impl.witness_id = AddImplWitnessForDeclaration(\n              context, node_id, impl,\n              context.generics().GetSelfSpecific(impl.generic_id));\n          impl.witness_block_id = context.inst_block_stack().Pop();\n        }\n\n        FinishGenericDecl(context, node_id, impl.generic_id);\n\n        auto extend_node = introducer.modifier_node_id(ModifierOrder::Extend);\n        impl_id = AddImpl(context, impl, new_impl.lookup_bucket, extend_node,\n                          name.implicit_params_loc_id);\n      }\n    }\n  }\n\n  // `FindImplId` returned an existing ImplId, or we added a new id with\n  // `AddImpl` above. Write that ImplId into the ImplDecl instruction and finish\n  // it.\n  auto impl_decl = context.insts().GetAs<SemIR::ImplDecl>(impl_decl_id);\n  impl_decl.impl_id = impl_id;\n  ReplaceInstBeforeConstantUse(context, impl_decl_id, impl_decl);\n\n  return {impl_id, impl_decl_id};\n}\n\nauto HandleParseNode(Context& context, Parse::ImplDeclId node_id) -> bool {\n  auto [impl_id, impl_decl_id] = BuildImplDecl(context, node_id);\n  auto& impl = context.impls().Get(impl_id);\n\n  context.decl_name_stack().PopScope();\n\n  // Impl definitions are required in the same file as the declaration. We skip\n  // this requirement if we've already issued an invalid redeclaration error, or\n  // there is an error that would prevent the impl from being legal to define.\n  if (impl.witness_id != SemIR::ErrorInst::InstId) {\n    context.definitions_required_by_decl().push_back(impl_decl_id);\n  }\n\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ImplDefinitionStartId node_id)\n    -> bool {\n  auto [impl_id, impl_decl_id] = BuildImplDecl(context, node_id);\n  auto& impl = context.impls().Get(impl_id);\n\n  CheckRequireDeclsSatisfied(context, node_id, impl);\n\n  CARBON_CHECK(!impl.has_definition_started());\n  impl.definition_id = impl_decl_id;\n  impl.scope_id =\n      context.name_scopes().Add(impl_decl_id, SemIR::NameId::None,\n                                context.decl_name_stack().PeekParentScopeId());\n\n  context.scope_stack().PushForEntity(\n      impl_decl_id, impl.scope_id,\n      context.generics().GetSelfSpecific(impl.generic_id));\n  StartGenericDefinition(context, impl.generic_id);\n  ImplWitnessStartDefinition(context, impl);\n  context.inst_block_stack().Push();\n  context.node_stack().Push(node_id, impl_id);\n\n  // TODO: Handle the case where there's control flow in the impl body. For\n  // example:\n  //\n  //   impl C as I {\n  //     fn F() -> if true then i32 else f64;\n  //   }\n  //\n  // We may need to track a list of instruction blocks here, as we do for a\n  // function.\n  impl.body_block_id = context.inst_block_stack().PeekOrAdd();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ImplDefinitionId /*node_id*/)\n    -> bool {\n  auto impl_id =\n      context.node_stack().Pop<Parse::NodeKind::ImplDefinitionStart>();\n  auto& impl = context.impls().Get(impl_id);\n\n  FinishImplWitness(context, impl);\n\n  impl.defined = true;\n  FinishGenericDefinition(context, impl.generic_id);\n\n  context.inst_block_stack().Pop();\n  // The decl_name_stack and scopes are popped by `ProcessNodeIds`.\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_import_and_package.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/decl_introducer_state.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/modifiers.h\"\n\nnamespace Carbon::Check {\n\n// `import` and `package` are structured by parsing. As a consequence, no\n// checking logic is needed here.\n\nauto HandleParseNode(Context& context, Parse::ImportIntroducerId /*node_id*/)\n    -> bool {\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Import>();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ImportDeclId /*node_id*/)\n    -> bool {\n  context.node_stack().PopIf<SemIR::LibraryNameId>();\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Import>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Export);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::LibraryIntroducerId /*node_id*/)\n    -> bool {\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Library>();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::LibraryDeclId /*node_id*/)\n    -> bool {\n  context.node_stack().PopIf<SemIR::LibraryNameId>();\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Library>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Impl);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PackageIntroducerId /*node_id*/)\n    -> bool {\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Package>();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PackageDeclId /*node_id*/)\n    -> bool {\n  context.node_stack().PopIf<SemIR::LibraryNameId>();\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Package>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Impl);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::LibrarySpecifierId /*node_id*/)\n    -> bool {\n  CARBON_CHECK(context.node_stack().PeekIs<SemIR::LibraryNameId>());\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::IdentifierPackageNameId /*node_id*/) -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::CorePackageNameId /*node_id*/)\n    -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::CppPackageNameId /*node_id*/)\n    -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::LibraryNameId node_id) -> bool {\n  // This is discarded in this file's uses, but is used by modifiers for `extern\n  // library`.\n  auto literal_id = context.tokens().GetStringLiteralValue(\n      context.parse_tree().node_token(node_id));\n  context.node_stack().Push(\n      node_id, SemIR::LibraryNameId::ForStringLiteralValueId(literal_id));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::DefaultLibraryId node_id)\n    -> bool {\n  context.node_stack().Push(node_id, SemIR::LibraryNameId::Default);\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::InlineImportSpecifierId /*node_id*/) -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::InlineImportBodyId /*node_id*/) -> bool {\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_index.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <optional>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/literal.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/operator.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/sem_ir/expr_info.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& /*context*/, Parse::IndexExprStartId /*node_id*/)\n    -> bool {\n  // Leave the expression on the stack for IndexExpr.\n  return true;\n}\n\n// Performs an index with base expression `operand_inst_id` and\n// `operand_type_id` for types that are not an array. This checks if\n// the base expression implements the `IndexWith` interface; if so, uses the\n// `At` associative method, otherwise prints a diagnostic.\nstatic auto PerformIndexWith(Context& context, Parse::NodeId node_id,\n                             SemIR::InstId operand_inst_id,\n                             SemIR::InstId index_inst_id) -> SemIR::InstId {\n  SemIR::InstId args[] = {context.types().GetTypeInstId(\n      context.insts().Get(index_inst_id).type_id())};\n  Operator op{.interface_name = CoreIdentifier::IndexWith,\n              .interface_args_ref = args,\n              .op_name = CoreIdentifier::At};\n  return BuildBinaryOperator(context, node_id, op, operand_inst_id,\n                             index_inst_id);\n}\n\nauto HandleParseNode(Context& context, Parse::IndexExprId node_id) -> bool {\n  auto index_inst_id = context.node_stack().PopExpr();\n  auto operand_inst_id = context.node_stack().PopExpr();\n  operand_inst_id = ConvertToValueOrRefExpr(context, operand_inst_id);\n  auto operand_inst = context.insts().Get(operand_inst_id);\n  auto operand_type_id = operand_inst.type_id();\n\n  CARBON_KIND_SWITCH(context.types().GetAsInst(operand_type_id)) {\n    case CARBON_KIND(SemIR::ArrayType array_type): {\n      auto cast_index_id = ConvertToValueOfType(\n          context, SemIR::LocId(index_inst_id), index_inst_id,\n          // TODO: Replace this with impl lookup rather than hardcoding `i32`.\n          MakeIntType(context, node_id, SemIR::IntKind::Signed,\n                      context.ints().Add(32)));\n      auto array_cat =\n          SemIR::GetExprCategory(context.sem_ir(), operand_inst_id);\n      if (array_cat == SemIR::ExprCategory::Value) {\n        // If the operand is an array value, convert it to an ephemeral\n        // reference to an array so we can perform a primitive indexing into it.\n        operand_inst_id = AddInst<SemIR::ValueAsRef>(\n            context, node_id,\n            {.type_id = operand_type_id, .value_id = operand_inst_id});\n      }\n      // Constant evaluation will perform a bounds check on this array indexing\n      // if the index is constant.\n      auto elem_id = AddInst<SemIR::ArrayIndex>(\n          context, node_id,\n          {.type_id = context.types().GetTypeIdForTypeInstId(\n               array_type.element_type_inst_id),\n           .array_id = operand_inst_id,\n           .index_id = cast_index_id});\n      if (array_cat != SemIR::ExprCategory::DurableRef) {\n        // Indexing a durable reference gives a durable reference expression.\n        // Indexing anything else gives a value expression.\n        // TODO: This should be replaced by a choice between using `IndexWith`\n        // and `IndirectIndexWith`.\n        elem_id = ConvertToValueExpr(context, elem_id);\n      }\n      context.node_stack().Push(node_id, elem_id);\n      return true;\n    }\n\n    default: {\n      auto elem_id =\n          PerformIndexWith(context, node_id, operand_inst_id, index_inst_id);\n      context.node_stack().Push(node_id, elem_id);\n      return true;\n    }\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_interface.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <tuple>\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/interface.h\"\n#include \"toolchain/check/merge.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/sem_ir/entity_with_params_base.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/interface.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::InterfaceIntroducerId node_id)\n    -> bool {\n  // This interface is potentially generic.\n  StartGenericDecl(context);\n  // Create an instruction block to hold the instructions created as part of the\n  // interface signature, such as generic parameters.\n  context.inst_block_stack().Push();\n  // Optional modifiers and the name follow.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Interface>();\n  context.decl_name_stack().PushScopeAndStartName();\n\n  // Push the bracketing node.\n  context.node_stack().Push(node_id);\n  return true;\n}\n\nstatic auto BuildInterfaceDecl(Context& context,\n                               Parse::AnyInterfaceDeclId node_id,\n                               bool is_definition)\n    -> std::tuple<SemIR::InterfaceId, SemIR::InstId> {\n  auto name = PopNameComponent(context);\n  auto name_context = context.decl_name_stack().FinishName(name);\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::InterfaceIntroducer>();\n\n  // Process modifiers.\n  auto [_, parent_scope_inst] =\n      context.name_scopes().GetInstIfValid(name_context.parent_scope_id);\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Interface>();\n  CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access);\n\n  auto decl_block_id = context.inst_block_stack().Pop();\n\n  // Add the interface declaration.\n  auto interface_decl = SemIR::InterfaceDecl{\n      SemIR::TypeType::TypeId, SemIR::InterfaceId::None, decl_block_id};\n  auto decl_inst_id = AddPlaceholderInst(context, node_id, interface_decl);\n\n  SemIR::Interface interface_info = {name_context.MakeEntityWithParamsBase(\n      name, decl_inst_id, /*is_extern=*/false, SemIR::LibraryNameId::None)};\n\n  DiagnoseIfGenericMissingExplicitParameters(context, interface_info);\n\n  // Check whether this is a redeclaration.\n  SemIR::ScopeLookupResult lookup_result =\n      context.decl_name_stack().LookupOrAddName(\n          name_context, decl_inst_id, introducer.modifier_set.GetAccessKind());\n  if (auto existing_decl = TryGetExistingDecl(context, name, lookup_result,\n                                              interface_info, is_definition)) {\n    auto existing_interface_decl = existing_decl->As<SemIR::InterfaceDecl>();\n    interface_decl.interface_id = existing_interface_decl.interface_id;\n    interface_decl.type_id = existing_interface_decl.type_id;\n    // TODO: If the new declaration is a definition, keep its parameter\n    // and implicit parameter lists rather than the ones from the\n    // previous declaration.\n\n    auto prev_decl_generic_id =\n        context.interfaces().Get(interface_decl.interface_id).generic_id;\n    FinishGenericRedecl(context, prev_decl_generic_id);\n  } else {\n    // Create a new interface if this isn't a valid redeclaration.\n    interface_info.generic_id = BuildGenericDecl(context, decl_inst_id);\n    interface_decl.interface_id = context.interfaces().Add(interface_info);\n    if (interface_info.has_parameters()) {\n      interface_decl.type_id =\n          GetGenericInterfaceType(context, interface_decl.interface_id,\n                                  context.scope_stack().PeekSpecificId());\n    }\n  }\n\n  // Write the interface ID into the InterfaceDecl.\n  ReplaceInstBeforeConstantUse(context, decl_inst_id, interface_decl);\n\n  return {interface_decl.interface_id, decl_inst_id};\n}\n\nauto HandleParseNode(Context& context, Parse::InterfaceDeclId node_id) -> bool {\n  BuildInterfaceDecl(context, node_id, /*is_definition=*/false);\n  context.decl_name_stack().PopScope();\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::InterfaceDefinitionStartId node_id) -> bool {\n  auto [interface_id, decl_inst_id] =\n      BuildInterfaceDecl(context, node_id, /*is_definition=*/true);\n  auto& interface_info = context.interfaces().Get(interface_id);\n\n  // Track that this declaration is the definition.\n  CARBON_CHECK(!interface_info.has_definition_started(),\n               \"Can't merge with defined interfaces.\");\n  interface_info.definition_id = decl_inst_id;\n  interface_info.scope_without_self_id = context.name_scopes().Add(\n      decl_inst_id, SemIR::NameId::None, interface_info.parent_scope_id);\n\n  // Start the definition of interface-without-self.\n  StartGenericDefinition(context, interface_info.generic_id);\n\n  context.inst_block_stack().Push();\n\n  // Enter the interface-without-self scope, which is used for the Self\n  // instruction, since it needs to reference the interface (without-self)\n  // generic. Self can't reference the interface-with-self generic since it's a\n  // parameter to the generic.\n  context.scope_stack().PushForEntity(\n      decl_inst_id, interface_info.scope_without_self_id,\n      context.generics().GetSelfSpecific(interface_info.generic_id));\n\n  // Declare and introduce `Self`. We model `Self` as a symbolic binding whose\n  // type is the interface, excluding any other interfaces mentioned by\n  // `require` declarations.\n  //\n  // This is an instruction in the interface-without-self so that we can apply a\n  // SpecificInterface to it, and get the inner `Self` as modified by any\n  // enclosing specific.\n  SemIR::TypeId self_type_id = GetInterfaceType(\n      context, interface_id,\n      context.generics().GetSelfSpecific(interface_info.generic_id));\n  interface_info.self_param_id = AddSelfSymbolicBindingToScope(\n      context, node_id, self_type_id, interface_info.scope_without_self_id,\n      /*is_template=*/false);\n\n  // Start the declaration of interface-with-self.\n  StartGenericDecl(context);\n\n  // Push `Self` as a parameter of the interface-with-self.\n  context.scope_stack().PushCompileTimeBinding(interface_info.self_param_id);\n\n  // Add the interface-with-self declaration and build the generic for it. This\n  // captures the `interface_info.self_param_id` as a parameter of the generic.\n  auto interface_with_self_decl =\n      SemIR::InterfaceWithSelfDecl{.interface_id = interface_id};\n  auto decl_with_self_inst_id =\n      AddPlaceholderInst(context, node_id, interface_with_self_decl);\n  auto generic_with_self_id = BuildGenericDecl(context, decl_with_self_inst_id);\n  interface_info.generic_with_self_id = generic_with_self_id;\n  ReplaceInstBeforeConstantUse(context, decl_with_self_inst_id,\n                               interface_with_self_decl);\n\n  interface_info.scope_with_self_id =\n      context.name_scopes().Add(decl_with_self_inst_id, SemIR::NameId::None,\n                                interface_info.scope_without_self_id);\n  // Set on the name scope that `M` is replaced by `Self.M`.\n  context.name_scopes()\n      .Get(interface_info.scope_with_self_id)\n      .set_is_interface_definition();\n\n  // Start the definition of interface-with-self.\n  StartGenericDefinition(context, interface_info.generic_with_self_id);\n\n  // Enter a scope for the interace-with-self.\n  context.scope_stack().PushForEntity(\n      decl_with_self_inst_id, interface_info.scope_with_self_id,\n      context.generics().GetSelfSpecific(interface_info.generic_with_self_id));\n\n  interface_info.body_block_without_self_id =\n      context.inst_block_stack().PeekOrAdd();\n\n  context.inst_block_stack().Push();\n  context.require_impls_stack().PushArray();\n  // We use the arg stack to build the witness table type.\n  context.args_type_info_stack().Push();\n\n  // TODO: Handle the case where there's control flow in the interface body. For\n  // example:\n  //\n  //   interface C {\n  //     let v: if true then i32 else f64;\n  //   }\n  //\n  // We may need to track a list of instruction blocks here, as we do for a\n  // function.\n  interface_info.body_block_with_self_id =\n      context.inst_block_stack().PeekOrAdd();\n\n  context.node_stack().Push(node_id, interface_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::InterfaceDefinitionId /*node_id*/)\n    -> bool {\n  auto interface_id =\n      context.node_stack().Pop<Parse::NodeKind::InterfaceDefinitionStart>();\n  // Pop the body_block_with_self.\n  context.inst_block_stack().Pop();\n  auto associated_entities_id = context.args_type_info_stack().Pop();\n\n  auto require_impls_block_id = context.require_impls_blocks().Add(\n      context.require_impls_stack().PeekArray());\n  context.require_impls_stack().PopArray();\n\n  auto& interface_info = context.interfaces().Get(interface_id);\n  if (!interface_info.associated_entities_id.has_value()) {\n    interface_info.require_impls_block_id = require_impls_block_id;\n    // This marks the interface type as fully defined.\n    interface_info.associated_entities_id = associated_entities_id;\n  }\n\n  // Finish the definition of interface-with-self.\n  FinishGenericDefinition(context, interface_info.generic_with_self_id);\n\n  // Pop the body_block_without_self.\n  context.inst_block_stack().Pop();\n\n  // Finish the definition of interface-without-self.\n  FinishGenericDefinition(context, interface_info.generic_id);\n\n  // The decl_name_stack and scopes are popped by `ProcessNodeIds`.\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_lambda.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::LambdaIntroducerId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleLambdaIntroducer\");\n}\n\nauto HandleParseNode(Context& context, Parse::LambdaId node_id) -> bool {\n  return context.TODO(node_id, \"HandleLambda\");\n}\n\nauto HandleParseNode(Context& context, Parse::TerseBodyArrowId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleTerseBodyArrow\");\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_let_and_var.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <optional>\n\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/check/decl_introducer_state.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/interface.h\"\n#include \"toolchain/check/keyword_modifier_set.h\"\n#include \"toolchain/check/member_access.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/pattern.h\"\n#include \"toolchain/check/pattern_match.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/lex/token_kind.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/parse/node_kind.h\"\n#include \"toolchain/parse/typed_nodes.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/pattern.h\"\n#include \"toolchain/sem_ir/type.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Handles the end of the declaration region of an associated constant. This is\n// called at the `=` or the `;` of the declaration, whichever comes first.\nstatic auto EndAssociatedConstantDeclRegion(Context& context,\n                                            SemIR::InterfaceId interface_id)\n    -> void {\n  // Peek the pattern. For a valid associated constant, the corresponding\n  // instruction will be an `AssociatedConstantDecl` instruction.\n  auto decl_id = context.node_stack().PeekPattern();\n  auto assoc_const_decl =\n      context.insts().GetAs<SemIR::AssociatedConstantDecl>(decl_id);\n  auto& assoc_const =\n      context.associated_constants().Get(assoc_const_decl.assoc_const_id);\n\n  // Build a corresponding associated entity and add it into scope.\n  //\n  // TODO: The instruction is added to the associated constant's decl block.\n  // It probably should be in the interface-with-self body instead.\n  auto assoc_id = BuildAssociatedEntity(context, interface_id, decl_id);\n  auto name_context = context.decl_name_stack().MakeUnqualifiedName(\n      context.node_stack().PeekNodeId(), assoc_const.name_id);\n  auto access_kind = context.decl_introducer_state_stack()\n                         .innermost()\n                         .modifier_set.GetAccessKind();\n  context.decl_name_stack().AddNameOrDiagnose(name_context, assoc_id,\n                                              access_kind);\n}\n\ntemplate <Lex::TokenKind::RawEnumType Kind>\nstatic auto HandleIntroducer(Context& context, Parse::NodeId node_id) -> bool {\n  context.decl_introducer_state_stack().Push<Kind>();\n  // Push a bracketing node and pattern block to establish the pattern context.\n  context.node_stack().Push(node_id);\n  context.pattern_block_stack().Push();\n  context.full_pattern_stack().PushNameBindingDecl();\n  BeginSubpattern(context);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::LetIntroducerId node_id) -> bool {\n  return HandleIntroducer<Lex::TokenKind::Let>(context, node_id);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::AssociatedConstantIntroducerId node_id) -> bool {\n  // Collect the declarations nested in the associated constant in a decl\n  // block. This is popped by FinishAssociatedConstantDecl.\n  context.inst_block_stack().Push();\n  return HandleIntroducer<Lex::TokenKind::Let>(context, node_id);\n}\n\nauto HandleParseNode(Context& context, Parse::VariableIntroducerId node_id)\n    -> bool {\n  return HandleIntroducer<Lex::TokenKind::Var>(context, node_id);\n}\n\nauto HandleParseNode(Context& context, Parse::FieldIntroducerId node_id)\n    -> bool {\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Var>();\n  context.node_stack().Push(node_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::VariablePatternId node_id)\n    -> bool {\n  auto subpattern_id = context.node_stack().PopPattern();\n  auto type_id = context.insts().Get(subpattern_id).type_id();\n\n  if (subpattern_id == SemIR::ErrorInst::InstId) {\n    context.node_stack().Push(node_id, SemIR::ErrorInst::InstId);\n    return true;\n  }\n\n  // In a parameter list, a `var` pattern is always a single `Call` parameter,\n  // even if it contains multiple binding patterns.\n  switch (context.full_pattern_stack().CurrentKind()) {\n    case FullPatternStack::Kind::ExplicitParamList:\n    case FullPatternStack::Kind::ImplicitParamList:\n      subpattern_id = AddPatternInst<SemIR::VarParamPattern>(\n          context, node_id,\n          {.type_id = type_id, .subpattern_id = subpattern_id});\n      break;\n    case FullPatternStack::Kind::NameBindingDecl:\n      break;\n    case FullPatternStack::Kind::NotInEitherParamList:\n      CARBON_FATAL(\"Unreachable\");\n  }\n\n  auto pattern_id = AddPatternInst<SemIR::VarPattern>(\n      context, node_id, {.type_id = type_id, .subpattern_id = subpattern_id});\n  context.node_stack().Push(node_id, pattern_id);\n  return true;\n}\n\n// Handle the end of the full-pattern of a let/var declaration (before the\n// start of the initializer, if any).\nstatic auto EndFullPattern(Context& context) -> void {\n  auto scope_id = context.scope_stack().PeekNameScopeId();\n  if (scope_id.has_value() &&\n      context.name_scopes().Get(scope_id).is_interface_definition()) {\n    // Don't emit NameBindingDecl for an associated constant, because it will\n    // always be empty.\n    context.pattern_block_stack().PopAndDiscard();\n    return;\n  }\n  auto pattern_block_id = context.pattern_block_stack().Pop();\n  AddInst<SemIR::NameBindingDecl>(context, context.node_stack().PeekNodeId(),\n                                  {.pattern_block_id = pattern_block_id});\n\n  // Emit storage for any `var`s in the pattern now.\n  bool returned =\n      context.decl_introducer_state_stack().innermost().modifier_set.HasAnyOf(\n          KeywordModifierSet::Returned);\n  AddPatternVarStorage(context, pattern_block_id, returned);\n}\n\nstatic auto StartPatternInitializer(Context& context) -> bool {\n  if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {\n    context.global_init().Resume();\n  }\n  context.full_pattern_stack().StartPatternInitializer();\n  return true;\n}\n\nstatic auto EndPatternInitializer(Context& context) -> void {\n  if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {\n    context.global_init().Suspend();\n  }\n  context.full_pattern_stack().EndPatternInitializer();\n}\n\nstatic auto HandleInitializer(Context& context, Parse::NodeId node_id) -> bool {\n  EndFullPattern(context);\n  context.node_stack().Push(node_id);\n  StartPatternInitializer(context);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::LetInitializerId node_id)\n    -> bool {\n  return HandleInitializer(context, node_id);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::AssociatedConstantInitializerId node_id) -> bool {\n  auto interface_decl =\n      context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceWithSelfDecl>();\n  EndAssociatedConstantDeclRegion(context, interface_decl.interface_id);\n  return HandleInitializer(context, node_id);\n}\n\nauto HandleParseNode(Context& context, Parse::VariableInitializerId node_id)\n    -> bool {\n  return HandleInitializer(context, node_id);\n}\n\nauto HandleParseNode(Context& context, Parse::FieldInitializerId node_id)\n    -> bool {\n  context.node_stack().Push(node_id);\n  return true;\n}\n\n// Make a default initialization expression for a `var` declaration.\nstatic auto MakeDefaultInit(Context& context, SemIR::LocId loc_id,\n                            SemIR::InstId pattern_id) -> SemIR::InstId {\n  loc_id = context.insts().GetLocIdForDesugaring(loc_id);\n\n  // Extract the matched type from the pattern.\n  //\n  // TODO: Diagnose if the pattern doesn't have a type, for example `var 123;`\n  // or `var a: auto;`.\n  auto pattern_type_id = context.insts().Get(pattern_id).type_id();\n  auto type_inst_id = context.types().GetTypeInstId(\n      SemIR::ExtractScrutineeType(context.sem_ir(), pattern_type_id));\n  if (type_inst_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // Form `Type as Core.DefaultOrUnformed`.\n  auto interface_id =\n      LookupNameInCore(context, loc_id, CoreIdentifier::DefaultOrUnformed);\n  auto interface_type = ExprAsType(context, loc_id, interface_id);\n  auto facet_id = ConvertToValueOfType(context, loc_id, type_inst_id,\n                                       interface_type.type_id);\n\n  // Form a call to `facet.Op()`.\n  auto op_name_id = context.core_identifiers().AddNameId(CoreIdentifier::Op);\n  auto op_id = PerformMemberAccess(context, loc_id, facet_id, op_name_id);\n  return PerformCall(context, loc_id, op_id, {});\n}\n\nnamespace {\n// State from HandleDecl, returned for type-specific handling.\nstruct DeclInfo {\n  // The optional initializer.\n  SemIR::InstId init_id = SemIR::InstId::None;\n  // The pattern. For an associated constant, this is the associated constant\n  // declaration.\n  SemIR::InstId pattern_id = SemIR::InstId::None;\n  DeclIntroducerState introducer = DeclIntroducerState();\n};\n}  // namespace\n\n// Handles common logic for `let` and `var` declarations.\n// TODO: There's still a lot of divergence here, including logic in\n// handle_binding_pattern. These should really be better unified.\ntemplate <const Lex::TokenKind& IntroducerTokenKind,\n          const Parse::NodeKind& IntroducerNodeKind,\n          const Parse::NodeKind& InitializerNodeKind>\nstatic auto HandleDecl(Context& context, Parse::NodeId node_id) -> DeclInfo {\n  DeclInfo decl_info = DeclInfo();\n\n  // Handle the optional initializer.\n  if (context.node_stack().PeekNextIs(InitializerNodeKind)) {\n    decl_info.init_id = context.node_stack().PopExpr();\n    context.node_stack().PopAndDiscardSoloNodeId<InitializerNodeKind>();\n    EndPatternInitializer(context);\n  } else {\n    // For an associated constant declaration, handle the completed declaration\n    // now. We will have done this at the `=` if there was an initializer.\n    if constexpr (IntroducerNodeKind ==\n                  Parse::NodeKind::AssociatedConstantIntroducer) {\n      auto interface_decl =\n          context.scope_stack()\n              .GetCurrentScopeAs<SemIR::InterfaceWithSelfDecl>();\n      EndAssociatedConstantDeclRegion(context, interface_decl.interface_id);\n    }\n\n    EndFullPattern(context);\n\n    // A variable declaration without an explicit initializer is initialized by\n    // calling `(T as Core.DefaultOrUnformed).Op()`.\n    if constexpr (IntroducerNodeKind == Parse::NodeKind::VariableIntroducer) {\n      StartPatternInitializer(context);\n      decl_info.init_id =\n          MakeDefaultInit(context, node_id, context.node_stack().PeekPattern());\n      EndPatternInitializer(context);\n    }\n  }\n  context.full_pattern_stack().PopFullPattern();\n\n  decl_info.pattern_id = context.node_stack().PopPattern();\n\n  context.node_stack().PopAndDiscardSoloNodeId<IntroducerNodeKind>();\n\n  // Process declaration modifiers.\n  // TODO: For a qualified `let` or `var` declaration, this should use the\n  // target scope of the name introduced in the declaration. See #2590.\n  auto parent_scope_inst =\n      context.name_scopes()\n          .GetInstIfValid(context.scope_stack().PeekNameScopeId())\n          .second;\n  decl_info.introducer =\n      context.decl_introducer_state_stack().Pop<IntroducerTokenKind>();\n  CheckAccessModifiersOnDecl(context, decl_info.introducer, parent_scope_inst);\n\n  return decl_info;\n}\n\nauto HandleParseNode(Context& context, Parse::LetDeclId node_id) -> bool {\n  auto decl_info =\n      HandleDecl<Lex::TokenKind::Let, Parse::NodeKind::LetIntroducer,\n                 Parse::NodeKind::LetInitializer>(context, node_id);\n\n  LimitModifiersOnDecl(\n      context, decl_info.introducer,\n      KeywordModifierSet::Access | KeywordModifierSet::Interface);\n\n  // Diagnose interface modifiers given that we're not building an associated\n  // constant. We use this rather than `LimitModifiersOnDecl` to get a more\n  // specific error.\n  RequireDefaultFinalOnlyInInterfaces(context, decl_info.introducer,\n                                      SemIR::NameScopeId::None);\n\n  if (decl_info.init_id.has_value()) {\n    LocalPatternMatch(context, decl_info.pattern_id, decl_info.init_id);\n  } else {\n    CARBON_DIAGNOSTIC(\n        ExpectedInitializerAfterLet, Error,\n        \"expected `=`; `let` declaration must have an initializer\");\n    context.emitter().Emit(LocIdForDiagnostics::TokenOnly(node_id),\n                           ExpectedInitializerAfterLet);\n  }\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::AssociatedConstantDeclId node_id)\n    -> bool {\n  auto decl_info = HandleDecl<Lex::TokenKind::Let,\n                              Parse::NodeKind::AssociatedConstantIntroducer,\n                              Parse::NodeKind::AssociatedConstantInitializer>(\n      context, node_id);\n\n  LimitModifiersOnDecl(\n      context, decl_info.introducer,\n      KeywordModifierSet::Access | KeywordModifierSet::Interface);\n\n  auto interface_scope =\n      context.scope_stack().GetCurrentScopeAs<SemIR::InterfaceWithSelfDecl>();\n  // The `AssociatedConstantDecl` instruction and the corresponding\n  // `AssociatedConstant` entity are built as part of handling the binding\n  // pattern, but we still need to attach the default value, if any is\n  // specified.\n  if (decl_info.pattern_id == SemIR::ErrorInst::InstId) {\n    const auto& interface =\n        context.interfaces().Get(interface_scope.interface_id);\n    context.name_scopes().Get(interface.scope_with_self_id).set_has_error();\n    context.inst_block_stack().Pop();\n    return true;\n  }\n  auto decl = context.insts().GetAs<SemIR::AssociatedConstantDecl>(\n      decl_info.pattern_id);\n\n  if (decl_info.introducer.modifier_set.HasAnyOf(\n          KeywordModifierSet::Interface)) {\n    context.TODO(decl_info.introducer.modifier_node_id(ModifierOrder::Decl),\n                 \"interface modifier\");\n  }\n\n  // If there was an initializer, convert it and store it on the constant.\n  if (decl_info.init_id.has_value()) {\n    // TODO: Diagnose if the `default` modifier was not used.\n    auto default_value_id =\n        ConvertToValueOfType(context, node_id, decl_info.init_id, decl.type_id);\n    auto& assoc_const = context.associated_constants().Get(decl.assoc_const_id);\n    assoc_const.default_value_id = default_value_id;\n  } else {\n    // TODO: Either allow redeclarations of associated constants or diagnose if\n    // the `default` modifier was used.\n  }\n\n  // Store the decl block on the declaration.\n  decl.decl_block_id = context.inst_block_stack().Pop();\n  ReplaceInstPreservingConstantValue(context, decl_info.pattern_id, decl);\n\n  context.inst_block_stack().AddInstId(decl_info.pattern_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::VariableDeclId node_id) -> bool {\n  auto decl_info =\n      HandleDecl<Lex::TokenKind::Var, Parse::NodeKind::VariableIntroducer,\n                 Parse::NodeKind::VariableInitializer>(context, node_id);\n\n  LimitModifiersOnDecl(\n      context, decl_info.introducer,\n      KeywordModifierSet::Access | KeywordModifierSet::Returned);\n\n  LocalPatternMatch(context, decl_info.pattern_id, decl_info.init_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::FieldDeclId node_id) -> bool {\n  if (context.node_stack().PeekNextIs(Parse::NodeKind::FieldInitializer)) {\n    // TODO: In a class scope, we should instead save the initializer\n    // somewhere so that we can use it as a default.\n    context.TODO(node_id, \"Field initializer\");\n    context.node_stack().PopExpr();\n    context.node_stack()\n        .PopAndDiscardSoloNodeId<Parse::NodeKind::FieldInitializer>();\n  }\n\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::FieldIntroducer>();\n  auto parent_scope_inst =\n      context.name_scopes()\n          .GetInstIfValid(context.scope_stack().PeekNameScopeId())\n          .second;\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Var>();\n  CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access);\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_literal.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include <cmath>\n\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/literal.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::BoolLiteralFalseId node_id)\n    -> bool {\n  context.node_stack().Push(\n      node_id, MakeBoolLiteral(context, node_id, SemIR::BoolValue::False));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::BoolLiteralTrueId node_id)\n    -> bool {\n  context.node_stack().Push(\n      node_id, MakeBoolLiteral(context, node_id, SemIR::BoolValue::True));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::CharLiteralId node_id) -> bool {\n  auto value = context.tokens().GetCharLiteralValue(\n      context.parse_tree().node_token(node_id));\n  auto inst_id = AddInst<SemIR::CharLiteralValue>(\n      context, node_id,\n      {.type_id = GetSingletonType(context, SemIR::CharLiteralType::TypeInstId),\n       .value = SemIR::CharId(value.value)});\n  context.node_stack().Push(node_id, inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::IntLiteralId node_id) -> bool {\n  auto int_literal_id = MakeIntLiteral(\n      context, node_id,\n      context.tokens().GetIntLiteral(context.parse_tree().node_token(node_id)));\n  context.node_stack().Push(node_id, int_literal_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::RealLiteralId node_id) -> bool {\n  auto real_id =\n      context.tokens().GetRealLiteral(context.parse_tree().node_token(node_id));\n  AddInstAndPush<SemIR::FloatLiteralValue>(\n      context, node_id,\n      {.type_id =\n           GetSingletonType(context, SemIR::FloatLiteralType::TypeInstId),\n       .real_id = real_id});\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::StringLiteralId node_id) -> bool {\n  auto str_literal_id =\n      MakeStringLiteral(context, node_id,\n                        context.tokens().GetStringLiteralValue(\n                            context.parse_tree().node_token(node_id)));\n  context.node_stack().Push(node_id, str_literal_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::BoolTypeLiteralId node_id)\n    -> bool {\n  auto type_inst_id = MakeBoolTypeLiteral(context, node_id);\n  context.node_stack().Push(node_id, type_inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::CharTypeLiteralId node_id)\n    -> bool {\n  auto type_inst_id = MakeCharTypeLiteral(context, node_id);\n  context.node_stack().Push(node_id, type_inst_id);\n  return true;\n}\n\n// Shared implementation for handling `iN` and `uN` literals.\nstatic auto HandleIntOrUnsignedIntTypeLiteral(Context& context,\n                                              Parse::NodeId node_id,\n                                              SemIR::IntKind int_kind,\n                                              IntId size_id) -> bool {\n  if (!(context.ints().Get(size_id) & 3).isZero()) {\n    CARBON_DIAGNOSTIC(IntWidthNotMultipleOf8, Error,\n                      \"bit width of integer type literal must be a multiple of \"\n                      \"8; use `Core.{0:Int|UInt}({1})` instead\",\n                      Diagnostics::BoolAsSelect, llvm::APSInt);\n    context.emitter().Emit(\n        node_id, IntWidthNotMultipleOf8, int_kind.is_signed(),\n        llvm::APSInt(context.ints().Get(size_id), /*isUnsigned=*/true));\n  }\n  auto type_inst_id = MakeIntTypeLiteral(context, node_id, int_kind, size_id);\n  context.node_stack().Push(node_id, type_inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::IntTypeLiteralId node_id)\n    -> bool {\n  auto tok_id = context.parse_tree().node_token(node_id);\n  auto size_id = context.tokens().GetTypeLiteralSize(tok_id);\n  return HandleIntOrUnsignedIntTypeLiteral(context, node_id,\n                                           SemIR::IntKind::Signed, size_id);\n}\n\nauto HandleParseNode(Context& context, Parse::UnsignedIntTypeLiteralId node_id)\n    -> bool {\n  auto tok_id = context.parse_tree().node_token(node_id);\n  auto size_id = context.tokens().GetTypeLiteralSize(tok_id);\n  return HandleIntOrUnsignedIntTypeLiteral(context, node_id,\n                                           SemIR::IntKind::Unsigned, size_id);\n}\n\nauto HandleParseNode(Context& context, Parse::FloatTypeLiteralId node_id)\n    -> bool {\n  auto tok_id = context.parse_tree().node_token(node_id);\n  auto size_id = context.tokens().GetTypeLiteralSize(tok_id);\n  auto type_inst_id = MakeFloatTypeLiteral(context, node_id, size_id);\n  context.node_stack().Push(node_id, type_inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::StringTypeLiteralId node_id)\n    -> bool {\n  auto type_inst_id = MakeStringTypeLiteral(context, node_id);\n  context.node_stack().Push(node_id, type_inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::TypeTypeLiteralId node_id)\n    -> bool {\n  auto type_inst_id = MakeTypeTypeLiteral(context, node_id);\n  context.node_stack().Push(node_id, type_inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::AutoTypeLiteralId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleAutoTypeLiteral\");\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_loop_statement.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/check/full_pattern_stack.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/member_access.h\"\n#include \"toolchain/check/operator.h\"\n#include \"toolchain/check/pattern.h\"\n#include \"toolchain/check/pattern_match.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/sem_ir/absolute_node_id.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Starts emitting the loop header for a `while`-like looping construct. Returns\n// the loop header block ID.\nstatic auto StartLoopHeader(Context& context, Parse::NodeId node_id)\n    -> SemIR::InstBlockId {\n  // Branch to the loop header block. Note that we create a new block here even\n  // if the current block is empty; this ensures that the loop always has a\n  // preheader block.\n  auto loop_header_id = AddDominatedBlockAndBranch(context, node_id);\n  context.inst_block_stack().Pop();\n\n  // Start emitting the loop header block.\n  context.inst_block_stack().Push(loop_header_id);\n  context.region_stack().AddToRegion(loop_header_id, node_id);\n\n  return loop_header_id;\n}\n\n// Starts emitting the loop body for a `while`-like looping construct. Converts\n// `cond_value_id` to bool and branches to the loop body if it is `true` and to\n// the loop exit if it is `false`.\nstatic auto BranchAndStartLoopBody(Context& context, Parse::NodeId node_id,\n                                   SemIR::InstBlockId loop_header_id,\n                                   SemIR::InstId cond_value_id) -> void {\n  cond_value_id = ConvertToBoolValue(context, node_id, cond_value_id);\n\n  // Branch to either the loop body or the loop exit block.\n  auto loop_body_id =\n      AddDominatedBlockAndBranchIf(context, node_id, cond_value_id);\n  auto loop_exit_id = AddDominatedBlockAndBranch(context, node_id);\n  context.inst_block_stack().Pop();\n\n  // Start emitting the loop body.\n  context.inst_block_stack().Push(loop_body_id);\n  context.region_stack().AddToRegion(loop_body_id, node_id);\n\n  // Allow `break` and `continue` in this scope.\n  context.break_continue_stack().push_back(\n      {.break_target = loop_exit_id, .continue_target = loop_header_id});\n}\n\n// Finishes emitting the body for a `while`-like loop. Adds a back-edge to the\n// loop header, and starts emitting in the loop exit block.\nstatic auto FinishLoopBody(Context& context, Parse::NodeId node_id) -> void {\n  auto blocks = context.break_continue_stack().pop_back_val();\n\n  // Add the loop backedge.\n  AddInst<SemIR::Branch>(context, node_id,\n                         {.target_id = blocks.continue_target});\n  context.inst_block_stack().Pop();\n\n  // Start emitting the loop exit block.\n  context.inst_block_stack().Push(blocks.break_target);\n  context.region_stack().AddToRegion(blocks.break_target, node_id);\n}\n\n// `while`\n// -------\n\nauto HandleParseNode(Context& context, Parse::WhileConditionStartId node_id)\n    -> bool {\n  context.node_stack().Push(node_id, StartLoopHeader(context, node_id));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::WhileConditionId node_id)\n    -> bool {\n  auto cond_value_id = context.node_stack().PopExpr();\n  auto loop_header_id =\n      context.node_stack().Pop<Parse::NodeKind::WhileConditionStart>();\n\n  // Branch to either the loop body or the loop exit block, and start emitting\n  // the loop body.\n  BranchAndStartLoopBody(context, node_id, loop_header_id, cond_value_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::WhileStatementId node_id)\n    -> bool {\n  FinishLoopBody(context, node_id);\n  return true;\n}\n\n// `for`\n// -----\n\nauto HandleParseNode(Context& context, Parse::ForHeaderStartId node_id)\n    -> bool {\n  // Create a nested scope to hold the cursor variable. This is also the lexical\n  // scope that names in the pattern are added to, although they get rebound on\n  // each loop iteration.\n  context.scope_stack().PushForSameRegion();\n\n  // Begin an implicit let declaration context for the pattern.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Let>();\n  context.pattern_block_stack().Push();\n  context.full_pattern_stack().PushNameBindingDecl();\n  BeginSubpattern(context);\n\n  context.node_stack().Push(node_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ForInId node_id) -> bool {\n  auto pattern_block_id = context.pattern_block_stack().Pop();\n  AddInst<SemIR::NameBindingDecl>(context, node_id,\n                                  {.pattern_block_id = pattern_block_id});\n  context.decl_introducer_state_stack().Pop<Lex::TokenKind::Let>();\n  context.full_pattern_stack().StartPatternInitializer();\n  context.node_stack().Push(node_id, pattern_block_id);\n  return true;\n}\n\n// For a value or reference of type `Optional(T)`, call the given accessor.\nstatic auto CallOptionalAccessor(Context& context, Parse::NodeId node_id,\n                                 SemIR::InstId optional_id,\n                                 CoreIdentifier accessor_name)\n    -> SemIR::InstId {\n  auto accessor_name_id = context.core_identifiers().AddNameId(accessor_name);\n  auto accessor_id =\n      PerformMemberAccess(context, node_id, optional_id, accessor_name_id);\n  return PerformCall(context, node_id, accessor_id, {});\n}\n\nauto HandleParseNode(Context& context, Parse::ForHeaderId node_id) -> bool {\n  auto range_id = context.node_stack().PopExpr();\n  auto pattern_block_id = context.node_stack().Pop<Parse::NodeKind::ForIn>();\n  auto pattern_id = context.node_stack().PopPattern();\n  auto start_node_id =\n      context.node_stack().PopForSoloNodeId<Parse::NodeKind::ForHeaderStart>();\n\n  // Convert the range expression to a value or reference so that we can use it\n  // multiple times.\n  // TODO: If this produces a temporary, its lifetime should presumably be\n  // extended to cover the loop body.\n  range_id = ConvertToValueOrRefExpr(context, range_id);\n\n  // Create the cursor variable.\n  // TODO: Produce a custom diagnostic if the range operand can't be used as a\n  // range.\n  // TODO: We need to allocate the `VarStorage` before building the operator.\n  // The current order risks violating the preconditions on `Initialize` and\n  // risks violating the topological ordering of insts.\n  auto cursor_id =\n      BuildUnaryOperator(context, node_id,\n                         {.interface_name = CoreIdentifier::Iterate,\n                          .op_name = CoreIdentifier::NewCursor},\n                         range_id);\n  auto cursor_type_id = context.insts().Get(cursor_id).type_id();\n  auto cursor_var_id = AddInstWithCleanup<SemIR::VarStorage>(\n      context, node_id,\n      {.type_id = cursor_type_id, .pattern_id = SemIR::AbsoluteInstId::None});\n  auto init_id = Initialize(context, node_id, cursor_var_id, cursor_id);\n  AddInst<SemIR::Assign>(context, node_id,\n                         {.lhs_id = cursor_var_id, .rhs_id = init_id});\n\n  // Start emitting the loop header block.\n  auto loop_header_id = StartLoopHeader(context, start_node_id);\n\n  // Call `<range>.(Iterate.Next)(&cursor)`.\n  auto cursor_type_inst_id = context.types().GetTypeInstId(cursor_type_id);\n  auto cursor_addr_id = AddInst<SemIR::AddrOf>(\n      context, node_id,\n      {.type_id = GetPointerType(context, cursor_type_inst_id),\n       .lvalue_id = cursor_var_id});\n  auto element_id =\n      BuildBinaryOperator(context, node_id,\n                          {.interface_name = CoreIdentifier::Iterate,\n                           .op_name = CoreIdentifier::Next},\n                          range_id, cursor_addr_id);\n  // We need to convert away from an initializing expression in order to call\n  // `HasValue` and then separately pattern-match against the element.\n  // TODO: Instead, form a `.Some(pattern_id)` pattern and pattern-match against\n  // that.\n  element_id = ConvertToValueOrRefExpr(context, element_id);\n\n  // Branch to the loop body if the optional element has a value.\n  auto cond_value_id = CallOptionalAccessor(context, node_id, element_id,\n                                            CoreIdentifier::HasValue);\n  BranchAndStartLoopBody(context, node_id, loop_header_id, cond_value_id);\n\n  // The loop pattern's initializer is now complete, and any bindings in it\n  // should be in scope.\n  context.full_pattern_stack().EndPatternInitializer();\n  context.full_pattern_stack().PopFullPattern();\n\n  // Create storage for var patterns now.\n  AddPatternVarStorage(context, pattern_block_id, /*is_returned_var=*/false);\n\n  // Initialize the pattern from `<element>.Get()`.\n  auto element_value_id =\n      CallOptionalAccessor(context, node_id, element_id, CoreIdentifier::Get);\n  LocalPatternMatch(context, pattern_id, element_value_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ForStatementId node_id) -> bool {\n  FinishLoopBody(context, node_id);\n  return true;\n}\n\n// `break`\n// -------\n\nauto HandleParseNode(Context& context, Parse::BreakStatementStartId node_id)\n    -> bool {\n  auto& stack = context.break_continue_stack();\n  if (stack.empty()) {\n    CARBON_DIAGNOSTIC(BreakOutsideLoop, Error,\n                      \"`break` can only be used in a loop\");\n    context.emitter().Emit(node_id, BreakOutsideLoop);\n  } else {\n    AddInst<SemIR::Branch>(context, node_id,\n                           {.target_id = stack.back().break_target});\n  }\n\n  context.inst_block_stack().Pop();\n  context.inst_block_stack().PushUnreachable();\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::BreakStatementId /*node_id*/)\n    -> bool {\n  return true;\n}\n\n// `continue`\n// ----------\n\nauto HandleParseNode(Context& context, Parse::ContinueStatementStartId node_id)\n    -> bool {\n  auto& stack = context.break_continue_stack();\n  if (stack.empty()) {\n    CARBON_DIAGNOSTIC(ContinueOutsideLoop, Error,\n                      \"`continue` can only be used in a loop\");\n    context.emitter().Emit(node_id, ContinueOutsideLoop);\n  } else {\n    AddInst<SemIR::Branch>(context, node_id,\n                           {.target_id = stack.back().continue_target});\n  }\n\n  context.inst_block_stack().Pop();\n  context.inst_block_stack().PushUnreachable();\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::ContinueStatementId /*node_id*/) -> bool {\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_match.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/handle.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::MatchConditionStartId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleMatchConditionStart\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchConditionId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleMatchCondition\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchIntroducerId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleMatchIntroducer\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchStatementStartId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleMatchStatementStart\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchCaseIntroducerId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleMatchCaseIntroducer\");\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::MatchCaseGuardIntroducerId node_id) -> bool {\n  return context.TODO(node_id, \"HandleMatchCaseGuardIntroducer\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchCaseGuardStartId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleMatchCaseGuardStart\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchCaseGuardId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleMatchCaseGuard\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchCaseId node_id) -> bool {\n  return context.TODO(node_id, \"HandleMatchCase\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchDefaultIntroducerId node_id)\n    -> bool {\n  return context.TODO(node_id, \"MatchDefaultIntroducer\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchDefaultId node_id) -> bool {\n  return context.TODO(node_id, \"HandleMatchDefault\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchHandlerStartId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleMatchHandlerStart\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchHandlerId node_id) -> bool {\n  return context.TODO(node_id, \"HandleMatchHandler\");\n}\n\nauto HandleParseNode(Context& context, Parse::MatchStatementId node_id)\n    -> bool {\n  return context.TODO(node_id, \"HandleMatchStatement\");\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_modifier.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/decl_introducer_state.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/lex/token_kind.h\"\n\nnamespace Carbon::Check {\n\nCARBON_DIAGNOSTIC(ModifierPrevious, Note, \"`{0}` previously appeared here\",\n                  Lex::TokenKind);\n\nstatic auto DiagnoseRepeated(Context& context, Parse::NodeId first_node,\n                             Parse::NodeId second_node) -> void {\n  CARBON_DIAGNOSTIC(ModifierRepeated, Error, \"`{0}` repeated on declaration\",\n                    Lex::TokenKind);\n  context.emitter()\n      .Build(second_node, ModifierRepeated, context.token_kind(second_node))\n      .Note(first_node, ModifierPrevious, context.token_kind(first_node))\n      .Emit();\n}\n\nstatic auto DiagnoseNotAllowedWith(Context& context, Parse::NodeId first_node,\n                                   Parse::NodeId second_node) -> void {\n  CARBON_DIAGNOSTIC(ModifierNotAllowedWith, Error,\n                    \"`{0}` not allowed on declaration with `{1}`\",\n                    Lex::TokenKind, Lex::TokenKind);\n  context.emitter()\n      .Build(second_node, ModifierNotAllowedWith,\n             context.token_kind(second_node), context.token_kind(first_node))\n      .Note(first_node, ModifierPrevious, context.token_kind(first_node))\n      .Emit();\n}\n\n// Handles the keyword that starts a modifier. This may a standalone keyword,\n// such as `private`, or the first in a complex modifier, such as `extern` in\n// `extern library ...`. If valid, adds it to the modifier set and returns true.\n// Otherwise, diagnoses and returns false.\nstatic auto HandleModifier(Context& context, Parse::NodeId node_id,\n                           KeywordModifierSet keyword) -> bool {\n  auto& s = context.decl_introducer_state_stack().innermost();\n\n  ModifierOrder order;\n  KeywordModifierSet later_modifiers;\n  if (keyword.HasAnyOf(KeywordModifierSet::Access)) {\n    order = ModifierOrder::Access;\n    later_modifiers = KeywordModifierSet::Extern | KeywordModifierSet::Decl |\n                      KeywordModifierSet::Evaluation;\n  } else if (keyword.HasAnyOf(KeywordModifierSet::Extern)) {\n    order = ModifierOrder::Extern;\n    later_modifiers = KeywordModifierSet::Decl | KeywordModifierSet::Evaluation;\n  } else if (keyword.HasAnyOf(KeywordModifierSet::Extend)) {\n    order = ModifierOrder::Extend;\n    later_modifiers = KeywordModifierSet::Decl;\n  } else if (keyword.HasAnyOf(KeywordModifierSet::Decl)) {\n    order = ModifierOrder::Decl;\n    later_modifiers = KeywordModifierSet::Evaluation;\n  } else if (keyword.HasAnyOf(KeywordModifierSet::Evaluation)) {\n    order = ModifierOrder::Evaluation;\n    later_modifiers = KeywordModifierSet::None;\n  } else {\n    CARBON_FATAL(\"Unexpected modifier keyword.\");\n  }\n\n  auto current_modifier_node_id = s.modifier_node_id(order);\n  if (s.modifier_set.HasAnyOf(keyword)) {\n    DiagnoseRepeated(context, current_modifier_node_id, node_id);\n    return false;\n  }\n  if (current_modifier_node_id.has_value()) {\n    DiagnoseNotAllowedWith(context, current_modifier_node_id, node_id);\n    return false;\n  }\n  if (auto later_modifier_set = s.modifier_set & later_modifiers;\n      !later_modifier_set.empty()) {\n    // At least one later modifier is present. Diagnose using the closest.\n    Parse::NodeId closest_later_modifier = Parse::NodeId::None;\n    for (auto later_order = static_cast<int8_t>(order) + 1;\n         later_order <= static_cast<int8_t>(ModifierOrder::Last);\n         ++later_order) {\n      if (s.ordered_modifier_node_ids[later_order].has_value()) {\n        closest_later_modifier = s.ordered_modifier_node_ids[later_order];\n        break;\n      }\n    }\n    CARBON_CHECK(closest_later_modifier.has_value());\n\n    CARBON_DIAGNOSTIC(ModifierMustAppearBefore, Error,\n                      \"`{0}` must appear before `{1}`\", Lex::TokenKind,\n                      Lex::TokenKind);\n    context.emitter()\n        .Build(node_id, ModifierMustAppearBefore, context.token_kind(node_id),\n               context.token_kind(closest_later_modifier))\n        .Note(closest_later_modifier, ModifierPrevious,\n              context.token_kind(closest_later_modifier))\n        .Emit();\n    return false;\n  }\n\n  s.modifier_set.Add(keyword);\n  s.set_modifier_node_id(order, node_id);\n  return true;\n}\n\n#define CARBON_PARSE_NODE_KIND(Name)\n#define CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Name)                       \\\n  auto HandleParseNode(Context& context, Parse::Name##ModifierId node_id) \\\n      -> bool {                                                           \\\n    HandleModifier(context, node_id, KeywordModifierSet::Name);           \\\n    return true;                                                          \\\n  }\n#include \"toolchain/parse/node_kind.def\"\n\nauto HandleParseNode(Context& context,\n                     Parse::ExternModifierWithLibraryId node_id) -> bool {\n  auto name_literal_id = context.node_stack().Pop<SemIR::LibraryNameId>();\n  if (HandleModifier(context, node_id, KeywordModifierSet::Extern)) {\n    auto& s = context.decl_introducer_state_stack().innermost();\n    s.extern_library = name_literal_id;\n  }\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ExternModifierId node_id)\n    -> bool {\n  return HandleModifier(context, node_id, KeywordModifierSet::Extern);\n}\n\nauto HandleParseNode(Context& context, Parse::ReturnedModifierId node_id)\n    -> bool {\n  return HandleModifier(context, node_id, KeywordModifierSet::Returned);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_name.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/member_access.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/name_ref.h\"\n#include \"toolchain/check/pointer_dereference.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/lex/token_kind.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::MemberAccessExprId node_id)\n    -> bool {\n  auto node_kind = context.node_stack().PeekNodeKind();\n\n  if (node_kind == Parse::NodeKind::ParenExpr) {\n    auto member_expr_id = context.node_stack().PopExpr();\n    auto base_id = context.node_stack().PopExpr();\n    auto member_id =\n        PerformCompoundMemberAccess(context, node_id, base_id, member_expr_id);\n    context.node_stack().Push(node_id, member_id);\n  } else if (node_kind == Parse::NodeKind::IntLiteral) {\n    auto index_inst_id = context.node_stack().PopExpr();\n    auto tuple_inst_id = context.node_stack().PopExpr();\n\n    auto tuple_value_inst_id =\n        PerformTupleAccess(context, node_id, tuple_inst_id, index_inst_id);\n\n    context.node_stack().Push(node_id, tuple_value_inst_id);\n  } else {\n    SemIR::NameId name_id = context.node_stack().PopName();\n    auto base_id = context.node_stack().PopExpr();\n    auto member_id = PerformMemberAccess(context, node_id, base_id, name_id);\n    context.node_stack().Push(node_id, member_id);\n  }\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PointerMemberAccessExprId node_id)\n    -> bool {\n  auto diagnose_not_pointer = [&context,\n                               &node_id](SemIR::TypeId not_pointer_type_id) {\n    // TODO: Pass in the expression we're trying to dereference to produce a\n    // better diagnostic.\n    CARBON_DIAGNOSTIC(ArrowOperatorOfNonPointer, Error,\n                      \"cannot apply `->` operator to non-pointer type {0}\",\n                      SemIR::TypeId);\n\n    auto builder =\n        context.emitter().Build(LocIdForDiagnostics::TokenOnly(node_id),\n                                ArrowOperatorOfNonPointer, not_pointer_type_id);\n    builder.Emit();\n  };\n\n  auto node_kind = context.node_stack().PeekNodeKind();\n\n  if (node_kind == Parse::NodeKind::ParenExpr) {\n    auto member_expr_id = context.node_stack().PopExpr();\n    auto base_id = context.node_stack().PopExpr();\n    auto deref_base_id = PerformPointerDereference(context, node_id, base_id,\n                                                   diagnose_not_pointer);\n    auto member_id = PerformCompoundMemberAccess(context, node_id,\n                                                 deref_base_id, member_expr_id);\n    context.node_stack().Push(node_id, member_id);\n  } else if (node_kind == Parse::NodeKind::IntLiteral) {\n    auto index_inst_id = context.node_stack().PopExpr();\n    auto tuple_pointer_inst_id = context.node_stack().PopExpr();\n    auto tuple_inst_id = PerformPointerDereference(\n        context, node_id, tuple_pointer_inst_id, diagnose_not_pointer);\n    auto tuple_value_inst_id =\n        PerformTupleAccess(context, node_id, tuple_inst_id, index_inst_id);\n\n    context.node_stack().Push(node_id, tuple_value_inst_id);\n  } else {\n    SemIR::NameId name_id = context.node_stack().PopName();\n    auto base_id = context.node_stack().PopExpr();\n    auto deref_base_id = PerformPointerDereference(context, node_id, base_id,\n                                                   diagnose_not_pointer);\n    auto member_id =\n        PerformMemberAccess(context, node_id, deref_base_id, name_id);\n    context.node_stack().Push(node_id, member_id);\n  }\n\n  return true;\n}\n\n// Returns the `NameId` for an identifier node.\nstatic auto GetIdentifierAsNameId(\n    Context& context,\n    Parse::NodeIdOneOf<Parse::IdentifierNameNotBeforeSignatureId,\n                       Parse::IdentifierNameMaybeBeforeSignatureId,\n                       Parse::IdentifierNameExprId>\n        node_id) -> SemIR::NameId {\n  CARBON_CHECK(!context.parse_tree().node_has_error(node_id),\n               \"TODO: Support checking error parse nodes\");\n  auto token = context.parse_tree().node_token(node_id);\n  return SemIR::NameId::ForIdentifier(context.tokens().GetIdentifier(token));\n}\n\n// Handle a name that is used as an expression by performing unqualified name\n// lookup.\nstatic auto HandleNameAsExpr(Context& context, Parse::NodeId node_id,\n                             SemIR::NameId name_id) -> SemIR::InstId {\n  auto result = LookupUnqualifiedName(context, node_id, name_id);\n  return BuildNameRef(context, node_id, name_id,\n                      result.scope_result.target_inst_id(), result.specific_id);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::IdentifierNameNotBeforeSignatureId node_id)\n    -> bool {\n  // The parent is responsible for binding the name.\n  context.node_stack().Push(node_id, GetIdentifierAsNameId(context, node_id));\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::IdentifierNameMaybeBeforeSignatureId node_id)\n    -> bool {\n  // Push a pattern block stack entry to handle the parameter pattern.\n  context.pattern_block_stack().Push();\n  context.full_pattern_stack().PushParameterizedDecl();\n  // The parent is responsible for binding the name.\n  context.node_stack().Push(node_id, GetIdentifierAsNameId(context, node_id));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::IdentifierNameExprId node_id)\n    -> bool {\n  auto name_id = GetIdentifierAsNameId(context, node_id);\n  context.node_stack().Push(node_id,\n                            HandleNameAsExpr(context, node_id, name_id));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::BaseNameId node_id) -> bool {\n  context.node_stack().Push(node_id, SemIR::NameId::Base);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::SelfTypeNameId node_id) -> bool {\n  context.node_stack().Push(node_id, SemIR::NameId::SelfType);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::SelfTypeNameExprId node_id)\n    -> bool {\n  context.node_stack().Push(\n      node_id, HandleNameAsExpr(context, node_id, SemIR::NameId::SelfType));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::SelfValueNameId node_id) -> bool {\n  context.node_stack().Push(node_id, SemIR::NameId::SelfValue);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::SelfValueNameExprId node_id)\n    -> bool {\n  context.node_stack().Push(\n      node_id, HandleNameAsExpr(context, node_id, SemIR::NameId::SelfValue));\n  return true;\n}\n\n// Common logic for name qualifiers.\nstatic auto ApplyNameQualifier(Context& context) -> bool {\n  context.decl_name_stack().ApplyNameQualifier(PopNameComponent(context));\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::IdentifierNameQualifierWithParamsId /*node_id*/)\n    -> bool {\n  return ApplyNameQualifier(context);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::IdentifierNameQualifierWithoutParamsId /*node_id*/)\n    -> bool {\n  return ApplyNameQualifier(context);\n}\n\nauto HandleParseNode(Context& context, Parse::DesignatorExprId node_id)\n    -> bool {\n  SemIR::NameId name_id = context.node_stack().PopName();\n\n  if (name_id == SemIR::NameId::SelfType) {\n    // Look up `.Self`.\n    SemIR::InstId period_self_id =\n        HandleNameAsExpr(context, node_id, SemIR::NameId::PeriodSelf);\n    context.node_stack().Push(node_id, period_self_id);\n  } else {\n    // Otherwise this is `.Member`, so look up `.Self` and then `Member` in\n    // `.Self`.\n    SemIR::InstId period_self_id = SemIR::InstId::None;\n    {\n      // TODO: Instead of annotating the diagnostic, should change\n      // `HandleNameAsExpr` to optionally allow us to produce the diagnostic\n      // instead so we can generate a \"name `.Self` implicitly referenced by\n      // designated expression, but not found\" diagnostic instead of adding a\n      // note to the current \"name `.Self` not found\" message.\n      Diagnostics::AnnotationScope annotate_diagnostics(\n          &context.emitter(), [&](auto& builder) {\n            CARBON_DIAGNOSTIC(\n                NoPeriodSelfForDesignator, Note,\n                \"designator may only be used when `.Self` is in scope\");\n            builder.Note(SemIR::LocId::None, NoPeriodSelfForDesignator);\n          });\n      period_self_id =\n          HandleNameAsExpr(context, node_id, SemIR::NameId::PeriodSelf);\n    }\n    auto member_id =\n        PerformMemberAccess(context, node_id, period_self_id, name_id);\n    context.node_stack().Push(node_id, member_id);\n  }\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PackageExprId node_id) -> bool {\n  AddInstAndPush<SemIR::NameRef>(\n      context, node_id,\n      {.type_id = GetSingletonType(context, SemIR::NamespaceType::TypeInstId),\n       .name_id = SemIR::NameId::PackageKeyword,\n       .value_id = SemIR::Namespace::PackageInstId});\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::CoreNameExprId node_id) -> bool {\n  // TODO: Unqualified lookup will never find anything; perform lookup directly\n  // into file scope.\n  context.node_stack().Push(\n      node_id, HandleNameAsExpr(context, node_id, SemIR::NameId::Core));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::CppNameExprId node_id) -> bool {\n  // TODO: Unqualified lookup will never find anything; perform lookup directly\n  // into file scope.\n  context.node_stack().Push(\n      node_id, HandleNameAsExpr(context, node_id, SemIR::NameId::Cpp));\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_named_constraint.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/interface.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/named_constraint.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context,\n                     Parse::NamedConstraintIntroducerId node_id) -> bool {\n  // This named constraint is potentially generic.\n  StartGenericDecl(context);\n  // Create an instruction block to hold the instructions created as part of the\n  // named constraint signature, such as generic parameters.\n  context.inst_block_stack().Push();\n  // Optional modifiers and the name follow.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Constraint>();\n  context.decl_name_stack().PushScopeAndStartName();\n\n  // Push the bracketing node.\n  context.node_stack().Push(node_id);\n  return true;\n}\n\nstatic auto BuildNamedConstraintDecl(Context& context,\n                                     Parse::AnyNamedConstraintDeclId node_id,\n                                     bool is_definition)\n    -> std::tuple<SemIR::NamedConstraintId, SemIR::InstId> {\n  auto name = PopNameComponent(context);\n  auto name_context = context.decl_name_stack().FinishName(name);\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::NamedConstraintIntroducer>();\n\n  // TODO: PopSoloNodeId(`template`) if it's present, and track that in the\n  // NamedConstraint. Or maybe it should be a modifier, like `abstract class`?\n\n  // Process modifiers.\n  auto [_, parent_scope_inst] =\n      context.name_scopes().GetInstIfValid(name_context.parent_scope_id);\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Constraint>();\n  CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Access);\n\n  auto decl_block_id = context.inst_block_stack().Pop();\n\n  // Add the constraint declaration.\n  auto constraint_decl = SemIR::NamedConstraintDecl{\n      SemIR::TypeType::TypeId, SemIR::NamedConstraintId::None, decl_block_id};\n  auto decl_inst_id = AddPlaceholderInst(context, node_id, constraint_decl);\n\n  SemIR::NamedConstraint constraint_info = {\n      name_context.MakeEntityWithParamsBase(name, decl_inst_id,\n                                            /*is_extern=*/false,\n                                            SemIR::LibraryNameId::None)};\n\n  DiagnoseIfGenericMissingExplicitParameters(context, constraint_info);\n\n  // Check whether this is a redeclaration.\n  SemIR::ScopeLookupResult lookup_result =\n      context.decl_name_stack().LookupOrAddName(\n          name_context, decl_inst_id, introducer.modifier_set.GetAccessKind());\n  if (auto existing_decl = TryGetExistingDecl(context, name, lookup_result,\n                                              constraint_info, is_definition)) {\n    auto existing_constraint_decl =\n        existing_decl->As<SemIR::NamedConstraintDecl>();\n    constraint_decl.named_constraint_id =\n        existing_constraint_decl.named_constraint_id;\n    constraint_decl.type_id = existing_constraint_decl.type_id;\n    // TODO: If the new declaration is a definition, keep its parameter\n    // and implicit parameter lists rather than the ones from the\n    // previous declaration.\n\n    auto prev_decl_generic_id = context.named_constraints()\n                                    .Get(constraint_decl.named_constraint_id)\n                                    .generic_id;\n    FinishGenericRedecl(context, prev_decl_generic_id);\n  } else {\n    // Create a new named constraint if this isn't a valid redeclaration.\n    constraint_info.generic_id = BuildGenericDecl(context, decl_inst_id);\n    constraint_decl.named_constraint_id =\n        context.named_constraints().Add(constraint_info);\n    if (constraint_info.has_parameters()) {\n      constraint_decl.type_id = GetGenericNamedConstraintType(\n          context, constraint_decl.named_constraint_id,\n          context.scope_stack().PeekSpecificId());\n    }\n  }\n\n  // Write the completed NamedConstraintDecl instruction.\n  ReplaceInstBeforeConstantUse(context, decl_inst_id, constraint_decl);\n\n  return {constraint_decl.named_constraint_id, decl_inst_id};\n}\n\nauto HandleParseNode(Context& context, Parse::NamedConstraintDeclId node_id)\n    -> bool {\n  BuildNamedConstraintDecl(context, node_id, /*is_definition=*/false);\n  context.decl_name_stack().PopScope();\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::NamedConstraintDefinitionStartId node_id) -> bool {\n  auto [named_constraint_id, decl_inst_id] =\n      BuildNamedConstraintDecl(context, node_id, /*is_definition=*/true);\n  auto& constraint_info = context.named_constraints().Get(named_constraint_id);\n\n  // TODO: Support for `template constraint`.\n  bool is_template = false;\n\n  // Track that this declaration is the definition.\n  CARBON_CHECK(!constraint_info.has_definition_started(),\n               \"Can't merge with defined named constraints.\");\n  constraint_info.definition_id = decl_inst_id;\n  constraint_info.scope_without_self_id = context.name_scopes().Add(\n      decl_inst_id, SemIR::NameId::None, constraint_info.parent_scope_id);\n\n  StartGenericDefinition(context, constraint_info.generic_id);\n\n  context.inst_block_stack().Push();\n\n  // Enter the constraint-without-self scope, which is used for the Self\n  // instruction, since it needs to reference the constraint (without-self)\n  // generic. Self can't reference the constraint-with-self generic since it's a\n  // parameter to the generic.\n  context.scope_stack().PushForEntity(\n      decl_inst_id, constraint_info.scope_without_self_id,\n      context.generics().GetSelfSpecific(constraint_info.generic_id));\n\n  // Declare and introduce `Self`. We model `Self` as a symbolic binding whose\n  // type is the named constraint, excluding any other interfaces mentioned by\n  // `require` declarations. This makes it an empty facet type.\n  SemIR::TypeId self_type_id = GetNamedConstraintType(\n      context, named_constraint_id,\n      context.generics().GetSelfSpecific(constraint_info.generic_id));\n  constraint_info.self_param_id = AddSelfSymbolicBindingToScope(\n      context, node_id, self_type_id, constraint_info.scope_without_self_id,\n      is_template);\n\n  // Start the declaration of constraint-with-self.\n  StartGenericDecl(context);\n\n  // Push `Self` as a parameter of the constraint-with-self.\n  context.scope_stack().PushCompileTimeBinding(constraint_info.self_param_id);\n\n  // Add the interface-with-self declaration and build the generic for it. This\n  // captures the `interface_info.self_param_id` as a parameter of the generic.\n  auto constraint_with_self_decl = SemIR::NamedConstraintWithSelfDecl{\n      .named_constraint_id = named_constraint_id};\n  auto decl_with_self_inst_id =\n      AddPlaceholderInst(context, node_id, constraint_with_self_decl);\n  auto generic_with_self_id = BuildGenericDecl(context, decl_with_self_inst_id);\n  constraint_info.generic_with_self_id = generic_with_self_id;\n  ReplaceInstBeforeConstantUse(context, decl_with_self_inst_id,\n                               constraint_with_self_decl);\n\n  constraint_info.scope_with_self_id =\n      context.name_scopes().Add(decl_with_self_inst_id, SemIR::NameId::None,\n                                constraint_info.scope_without_self_id);\n\n  // Start the definition of constraint-with-self.\n  StartGenericDefinition(context, constraint_info.generic_with_self_id);\n\n  // Enter a scope for the constraint-with-self.\n  context.scope_stack().PushForEntity(\n      decl_with_self_inst_id, constraint_info.scope_with_self_id,\n      context.generics().GetSelfSpecific(constraint_info.generic_with_self_id));\n\n  constraint_info.body_block_without_self_id =\n      context.inst_block_stack().PeekOrAdd();\n\n  context.inst_block_stack().Push();\n\n  constraint_info.body_block_with_self_id =\n      context.inst_block_stack().PeekOrAdd();\n\n  context.require_impls_stack().PushArray();\n\n  context.node_stack().Push(node_id, named_constraint_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::NamedConstraintDefinitionId /*node_id*/) -> bool {\n  auto named_constraint_id =\n      context.node_stack()\n          .Pop<Parse::NodeKind::NamedConstraintDefinitionStart>();\n  // Pop the body_block_with_self.\n  context.inst_block_stack().Pop();\n\n  auto require_impls_block_id = context.require_impls_blocks().Add(\n      context.require_impls_stack().PeekArray());\n  context.require_impls_stack().PopArray();\n\n  auto& constraint_info = context.named_constraints().Get(named_constraint_id);\n  if (!constraint_info.complete) {\n    constraint_info.require_impls_block_id = require_impls_block_id;\n    // TODO: Do something with `alias` statements in the body of the\n    // constraint.\n    constraint_info.complete = true;\n  }\n\n  // Finish the definition of constraint-with-self.\n  FinishGenericDefinition(context, constraint_info.generic_with_self_id);\n\n  // Pop the body_block_without_self.\n  context.inst_block_stack().Pop();\n\n  // Finish the definition of interfconstraintace-without-self.\n  FinishGenericDefinition(context, constraint_info.generic_id);\n\n  // The decl_name_stack and scopes are popped by `ProcessNodeIds`.\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_namespace.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/decl_introducer_state.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::NamespaceStartId /*node_id*/)\n    -> bool {\n  // Namespaces can't be generic, but we might have parsed a generic parameter\n  // in their name, so enter a generic scope just in case.\n  StartGenericDecl(context);\n  // Optional modifiers and the name follow.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Namespace>();\n  context.decl_name_stack().PushScopeAndStartName();\n  return true;\n}\n\nstatic auto IsNamespaceScope(Context& context, SemIR::NameScopeId name_scope_id)\n    -> bool {\n  auto [_, inst] = context.name_scopes().GetInstIfValid(name_scope_id);\n  return inst && inst->Is<SemIR::Namespace>();\n}\n\nauto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool {\n  auto name_context = context.decl_name_stack().FinishName(\n      PopNameComponentWithoutParams(context, Lex::TokenKind::Namespace));\n\n  DiscardGenericDecl(context);\n\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Namespace>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::None);\n\n  auto namespace_inst = SemIR::Namespace{\n      GetSingletonType(context, SemIR::NamespaceType::TypeInstId),\n      SemIR::NameScopeId::None, SemIR::InstId::None};\n  auto namespace_id = AddPlaceholderInst(context, node_id, namespace_inst);\n\n  SemIR::ScopeLookupResult lookup_result =\n      context.decl_name_stack().LookupOrAddName(name_context, namespace_id,\n                                                SemIR::AccessKind::Public);\n  if (lookup_result.is_poisoned()) {\n    DiagnosePoisonedName(context, name_context.name_id_for_new_inst(),\n                         lookup_result.poisoning_loc_id(), name_context.loc_id);\n  } else if (lookup_result.is_found()) {\n    SemIR::InstId existing_inst_id = lookup_result.target_inst_id();\n    if (auto existing =\n            context.insts().TryGetAs<SemIR::Namespace>(existing_inst_id)) {\n      // If there's a name conflict with a namespace, \"merge\" by using the\n      // previous declaration. Otherwise, diagnose the issue.\n\n      // Point at the other namespace.\n      namespace_inst.name_scope_id = existing->name_scope_id;\n\n      if (context.name_scopes()\n              .Get(existing->name_scope_id)\n              .is_closed_import()) {\n        // The existing name is a package name, so this is a name conflict.\n        DiagnoseDuplicateName(context, name_context.name_id,\n                              name_context.loc_id,\n                              SemIR::LocId(existing_inst_id));\n\n        // Treat this as a local namespace name from now on to avoid further\n        // diagnostics.\n        context.name_scopes()\n            .Get(existing->name_scope_id)\n            .set_is_closed_import(false);\n      } else if (existing->import_id.has_value() &&\n                 !context.insts()\n                      .GetCanonicalLocId(existing_inst_id)\n                      .has_value()) {\n        // When the name conflict is an imported namespace, fill the location ID\n        // so that future diagnostics point at this declaration.\n        SetNamespaceNodeId(context, existing_inst_id, node_id);\n      }\n    } else {\n      DiagnoseDuplicateName(context, name_context.name_id, name_context.loc_id,\n                            SemIR::LocId(existing_inst_id));\n    }\n  }\n\n  // If we weren't able to merge namespaces, add a new name scope. Note this\n  // occurs even for duplicates where we discard the namespace, because we want\n  // to produce a valid constant.\n  if (!namespace_inst.name_scope_id.has_value()) {\n    namespace_inst.name_scope_id = context.name_scopes().Add(\n        namespace_id, name_context.name_id_for_new_inst(),\n        name_context.parent_scope_id);\n    if (!IsNamespaceScope(context, name_context.parent_scope_id)) {\n      CARBON_DIAGNOSTIC(NamespaceDeclNotAtTopLevel, Error,\n                        \"`namespace` declaration not at top level\");\n      context.emitter().Emit(node_id, NamespaceDeclNotAtTopLevel);\n    }\n  }\n\n  ReplaceInstBeforeConstantUse(context, namespace_id, namespace_inst);\n\n  context.decl_name_stack().PopScope();\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_noop.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& /*context*/, Parse::EmptyDeclId /*node_id*/)\n    -> bool {\n  // Empty declarations have no actions associated.\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::InvalidParseId /*node_id*/)\n    -> bool {\n  CARBON_FATAL(\"Unreachable until we support checking error parse nodes\");\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::InvalidParseStartId /*node_id*/) -> bool {\n  CARBON_FATAL(\"Unreachable until we support checking error parse nodes\");\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::InvalidParseSubtreeId /*node_id*/) -> bool {\n  CARBON_FATAL(\"Unreachable until we support checking error parse nodes\");\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::PlaceholderId /*node_id*/)\n    -> bool {\n  CARBON_FATAL(\n      \"Placeholder node should always be replaced before parse completes\");\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_observe.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/parse/node_ids.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::ObserveIntroducerId node_id)\n    -> bool {\n  return context.TODO(node_id, \"ObserveIntroducerId\");\n}\n\nauto HandleParseNode(Context& context, Parse::ObserveEqualEqualId node_id)\n    -> bool {\n  return context.TODO(node_id, \"ObserveEqualEqualId\");\n}\n\nauto HandleParseNode(Context& context, Parse::ObserveImplsId node_id) -> bool {\n  return context.TODO(node_id, \"ObserveImplsId\");\n}\n\nauto HandleParseNode(Context& context, Parse::ObserveDeclId node_id) -> bool {\n  return context.TODO(node_id, \"ObserveDeclId\");\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_operator.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/operator.h\"\n#include \"toolchain/check/pointer_dereference.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/parse/typed_nodes.h\"\n#include \"toolchain/sem_ir/expr_info.h\"\n\nnamespace Carbon::Check {\n\n// Common logic for unary operator handlers.\nstatic auto HandleUnaryOperator(Context& context, Parse::AnyExprId expr_node_id,\n                                CoreIdentifier interface_name) -> bool {\n  auto operand_id = context.node_stack().PopExpr();\n  auto result_id = BuildUnaryOperator(\n      context, expr_node_id, {.interface_name = interface_name}, operand_id);\n  context.node_stack().Push(expr_node_id, result_id);\n  return true;\n}\n\n// Common logic for binary operator handlers.\nstatic auto HandleBinaryOperator(Context& context,\n                                 Parse::AnyExprId expr_node_id,\n                                 CoreIdentifier interface_name,\n                                 CoreIdentifier op_name = CoreIdentifier::Op)\n    -> bool {\n  auto rhs_id = context.node_stack().PopExpr();\n  auto lhs_id = context.node_stack().PopExpr();\n  // All the `*With` binary operator interfaces take a single argument that is\n  // the type of the RHS operand. `as` has different rules and we don't call\n  // this function for it.\n  SemIR::InstId args[] = {\n      context.types().GetTypeInstId(context.insts().Get(rhs_id).type_id())};\n  auto result_id = BuildBinaryOperator(context, expr_node_id,\n                                       {.interface_name = interface_name,\n                                        .interface_args_ref = args,\n                                        .op_name = op_name},\n                                       lhs_id, rhs_id);\n  context.node_stack().Push(expr_node_id, result_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorAmpId node_id)\n    -> bool {\n  // TODO: Facet type intersection may need to be handled directly.\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::BitAndWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorAmpEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id,\n                              CoreIdentifier::BitAndAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::UnsafeModifierId node_id)\n    -> bool {\n  auto [rhs_node, rhs_id] = context.node_stack().PopExprWithNodeId();\n  context.node_stack().Push(node_id, rhs_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorAsId node_id)\n    -> bool {\n  auto [rhs_node, rhs_id] = context.node_stack().PopExprWithNodeId();\n  auto [lhs_node, lhs_id] = context.node_stack().PopExprWithNodeId();\n\n  bool unsafe = context.parse_tree().node_kind(lhs_node) ==\n                Parse::NodeKind::UnsafeModifier;\n\n  auto rhs_type_id = ExprAsType(context, rhs_node, rhs_id).type_id;\n  context.node_stack().Push(\n      node_id,\n      ConvertForExplicitAs(context, node_id, lhs_id, rhs_type_id, unsafe));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorCaretId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::BitXorWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorCaretEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id,\n                              CoreIdentifier::BitXorAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorEqualId node_id)\n    -> bool {\n  // TODO: Switch to using assignment interface for most assignment. Some cases\n  // may need to be handled directly.\n  //\n  //   return HandleBinaryOperator(context, node_id,\n  //                               CoreIdentifier::AssignWith);\n\n  auto [rhs_node, rhs_id] = context.node_stack().PopExprWithNodeId();\n  auto [lhs_node, lhs_id] = context.node_stack().PopExprWithNodeId();\n  if (auto lhs_cat = SemIR::GetExprCategory(context.sem_ir(), lhs_id);\n      lhs_cat != SemIR::ExprCategory::DurableRef &&\n      lhs_cat != SemIR::ExprCategory::Error) {\n    CARBON_DIAGNOSTIC(AssignmentToNonAssignable, Error,\n                      \"expression is not assignable\");\n    context.emitter().Emit(lhs_node, AssignmentToNonAssignable);\n  }\n  // TODO: Destroy the old value before reinitializing. This will require\n  // building the destruction code before we build the RHS subexpression.\n  rhs_id = Initialize(context, node_id, lhs_id, rhs_id);\n  AddInst<SemIR::Assign>(context, node_id,\n                         {.lhs_id = lhs_id, .rhs_id = rhs_id});\n  // We model assignment as an expression, so we need to push a value for\n  // it, even though it doesn't produce a value.\n  // TODO: Consider changing our parse tree to model assignment as a\n  // different kind of statement than an expression statement.\n  context.node_stack().Push(node_id, lhs_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorEqualEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::EqWith,\n                              CoreIdentifier::Equal);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::InfixOperatorExclaimEqualId node_id) -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::EqWith,\n                              CoreIdentifier::NotEqual);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorGreaterId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::OrderedWith,\n                              CoreIdentifier::Greater);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::InfixOperatorGreaterEqualId node_id) -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::OrderedWith,\n                              CoreIdentifier::GreaterOrEquivalent);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::InfixOperatorGreaterGreaterId node_id) -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::RightShiftWith);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::InfixOperatorGreaterGreaterEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id,\n                              CoreIdentifier::RightShiftAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorLessId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::OrderedWith,\n                              CoreIdentifier::Less);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorLessEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::OrderedWith,\n                              CoreIdentifier::LessOrEquivalent);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::InfixOperatorLessEqualGreaterId node_id) -> bool {\n  return context.TODO(node_id, \"remove <=> operator that is not in the design\");\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorLessLessId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::LeftShiftWith);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::InfixOperatorLessLessEqualId node_id) -> bool {\n  return HandleBinaryOperator(context, node_id,\n                              CoreIdentifier::LeftShiftAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorMinusId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::SubWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorMinusEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::SubAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorPercentId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::ModWith);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::InfixOperatorPercentEqualId node_id) -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::ModAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorPipeId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::BitOrWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorPipeEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id,\n                              CoreIdentifier::BitOrAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorPlusId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::AddWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorPlusEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::AddAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorSlashId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::DivWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorSlashEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::DivAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorStarId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::MulWith);\n}\n\nauto HandleParseNode(Context& context, Parse::InfixOperatorStarEqualId node_id)\n    -> bool {\n  return HandleBinaryOperator(context, node_id, CoreIdentifier::MulAssignWith);\n}\n\nauto HandleParseNode(Context& context, Parse::PostfixOperatorStarId node_id)\n    -> bool {\n  auto value_id = context.node_stack().PopExpr();\n  auto inner_type = ExprAsType(context, node_id, value_id);\n  AddInstAndPush<SemIR::PointerType>(\n      context, node_id,\n      {.type_id = SemIR::TypeType::TypeId, .pointee_id = inner_type.inst_id});\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PrefixOperatorAmpId node_id)\n    -> bool {\n  auto value_id = context.node_stack().PopExpr();\n  auto type_id = context.insts().Get(value_id).type_id();\n  // Only durable reference expressions can have their address taken.\n  switch (SemIR::GetExprCategory(context.sem_ir(), value_id)) {\n    case SemIR::ExprCategory::DurableRef:\n    case SemIR::ExprCategory::Error:\n      break;\n    default:\n      CARBON_DIAGNOSTIC(AddrOfNonRef, Error,\n                        \"cannot take the address of non-reference expression\");\n      context.emitter().Emit(LocIdForDiagnostics::TokenOnly(node_id),\n                             AddrOfNonRef);\n      value_id = SemIR::ErrorInst::InstId;\n      break;\n  }\n  // TODO: Preserve spelling of type of operand where possible.\n  auto type_inst_id = context.types().GetTypeInstId(type_id);\n  AddInstAndPush<SemIR::AddrOf>(\n      context, node_id,\n      SemIR::AddrOf{.type_id = GetPointerType(context, type_inst_id),\n                    .lvalue_id = value_id});\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PrefixOperatorCaretId node_id)\n    -> bool {\n  return HandleUnaryOperator(context, node_id, CoreIdentifier::BitComplement);\n}\n\nauto HandleParseNode(Context& context, Parse::PrefixOperatorConstId node_id)\n    -> bool {\n  auto value_id = context.node_stack().PopExpr();\n\n  // `const (const T)` is probably not what the developer intended.\n  // TODO: Detect `const (const T)*` and suggest moving the `*` inside the\n  // parentheses.\n  if (context.insts().Get(value_id).kind() == SemIR::ConstType::Kind) {\n    CARBON_DIAGNOSTIC(RepeatedConst, Warning,\n                      \"`const` applied repeatedly to the same type has no \"\n                      \"additional effect\");\n    context.emitter().Emit(node_id, RepeatedConst);\n  }\n  auto inner_type = ExprAsType(context, node_id, value_id);\n  AddInstAndPush<SemIR::ConstType>(\n      context, node_id,\n      {.type_id = SemIR::TypeType::TypeId, .inner_id = inner_type.inst_id});\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PrefixOperatorMinusId node_id)\n    -> bool {\n  return HandleUnaryOperator(context, node_id, CoreIdentifier::Negate);\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::PrefixOperatorMinusMinusId node_id) -> bool {\n  return HandleUnaryOperator(context, node_id, CoreIdentifier::Dec);\n}\n\nauto HandleParseNode(Context& context, Parse::PrefixOperatorNotId node_id)\n    -> bool {\n  auto value_id = context.node_stack().PopExpr();\n  value_id = ConvertToBoolValue(context, node_id, value_id);\n  AddInstAndPush<SemIR::UnaryOperatorNot>(\n      context, node_id,\n      {.type_id = context.insts().Get(value_id).type_id(),\n       .operand_id = value_id});\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PrefixOperatorPartialId node_id)\n    -> bool {\n  auto value_id = context.node_stack().PopExpr();\n  auto inner_type = ExprAsType(context, node_id, value_id);\n  auto class_type =\n      context.types().TryGetAs<SemIR::ClassType>(inner_type.type_id);\n\n  if (!class_type ||\n      context.classes().Get(class_type->class_id).inheritance_kind ==\n          SemIR::Class::InheritanceKind::Final) {\n    CARBON_DIAGNOSTIC(PartialOnFinal, Error,\n                      \"`partial` applied to final type {0}\", SemIR::TypeId);\n    context.emitter().Emit(node_id, PartialOnFinal, inner_type.type_id);\n  }\n\n  AddInstAndPush<SemIR::PartialType>(\n      context, node_id,\n      {.type_id = SemIR::TypeType::TypeId, .inner_id = inner_type.inst_id});\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PrefixOperatorPlusPlusId node_id)\n    -> bool {\n  return HandleUnaryOperator(context, node_id, CoreIdentifier::Inc);\n}\n\nauto HandleParseNode(Context& context, Parse::PrefixOperatorRefId node_id)\n    -> bool {\n  auto expr_id = context.node_stack().PopExpr();\n  auto ref_id = AddInst<SemIR::RefTagExpr>(\n      context, node_id,\n      {.type_id = context.insts().Get(expr_id).type_id(), .expr_id = expr_id});\n  context.node_stack().Push(node_id, ref_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PrefixOperatorStarId node_id)\n    -> bool {\n  auto base_id = context.node_stack().PopExpr();\n\n  auto deref_base_id = PerformPointerDereference(\n      context, node_id, base_id,\n      [&context, &node_id](SemIR::TypeId not_pointer_type_id) {\n        // TODO: Pass in the expression we're trying to dereference to produce a\n        // better diagnostic.\n        CARBON_DIAGNOSTIC(DerefOfNonPointer, Error,\n                          \"cannot dereference operand of non-pointer type {0}\",\n                          SemIR::TypeId);\n\n        auto builder =\n            context.emitter().Build(LocIdForDiagnostics::TokenOnly(node_id),\n                                    DerefOfNonPointer, not_pointer_type_id);\n\n        // TODO: Check for any facet here, rather than only a type.\n        if (not_pointer_type_id == SemIR::TypeType::TypeId) {\n          CARBON_DIAGNOSTIC(\n              DerefOfType, Note,\n              \"to form a pointer type, write the `*` after the pointee type\");\n          builder.Note(LocIdForDiagnostics::TokenOnly(node_id), DerefOfType);\n        }\n\n        builder.Emit();\n      });\n\n  context.node_stack().Push(node_id, deref_base_id);\n  return true;\n}\n\n// Adds the branch for a short circuit operand.\nstatic auto HandleShortCircuitOperand(Context& context, Parse::NodeId node_id,\n                                      bool is_or) -> bool {\n  // Convert the condition to `bool`.\n  auto [cond_node, cond_value_id] = context.node_stack().PopExprWithNodeId();\n  cond_value_id = ConvertToBoolValue(context, node_id, cond_value_id);\n  auto bool_type_id = context.insts().Get(cond_value_id).type_id();\n\n  // Compute the branch value: the condition for `and`, inverted for `or`.\n  SemIR::InstId branch_value_id =\n      is_or ? AddInst<SemIR::UnaryOperatorNot>(\n                  context, node_id,\n                  {.type_id = bool_type_id, .operand_id = cond_value_id})\n            : cond_value_id;\n  auto short_circuit_result_id = AddInst<SemIR::BoolLiteral>(\n      context, node_id,\n      {.type_id = bool_type_id, .value = SemIR::BoolValue::From(is_or)});\n\n  // Create a block for the right-hand side and for the continuation.\n  auto rhs_block_id =\n      AddDominatedBlockAndBranchIf(context, node_id, branch_value_id);\n  auto end_block_id = AddDominatedBlockAndBranchWithArg(\n      context, node_id, short_circuit_result_id);\n\n  // Push the branch condition and result for use when handling the complete\n  // expression.\n  context.node_stack().Push(cond_node, branch_value_id);\n  context.node_stack().Push(cond_node, short_circuit_result_id);\n\n  // Push the resumption and the right-hand side blocks, and start emitting the\n  // right-hand operand.\n  context.inst_block_stack().Pop();\n  context.inst_block_stack().Push(end_block_id);\n  context.inst_block_stack().Push(rhs_block_id);\n  context.region_stack().AddToRegion(rhs_block_id, node_id);\n\n  // HandleShortCircuitOperator will follow, and doesn't need the operand on the\n  // node stack.\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ShortCircuitOperandAndId node_id)\n    -> bool {\n  return HandleShortCircuitOperand(context, node_id, /*is_or=*/false);\n}\n\nauto HandleParseNode(Context& context, Parse::ShortCircuitOperandOrId node_id)\n    -> bool {\n  return HandleShortCircuitOperand(context, node_id, /*is_or=*/true);\n}\n\n// Short circuit operator handling is uniform because the branching logic\n// occurs during operand handling.\nstatic auto HandleShortCircuitOperator(Context& context, Parse::NodeId node_id)\n    -> bool {\n  if (!context.scope_stack().IsInFunctionScope()) {\n    return context.TODO(node_id,\n                        \"Control flow expressions are currently only supported \"\n                        \"inside functions.\");\n  }\n  auto [rhs_node, rhs_id] = context.node_stack().PopExprWithNodeId();\n  auto short_circuit_result_id = context.node_stack().PopExpr();\n  auto branch_value_id = context.node_stack().PopExpr();\n\n  // The first operand is wrapped in a ShortCircuitOperand, which we\n  // already handled by creating a RHS block and a resumption block, which\n  // are the current block and its enclosing block.\n  rhs_id = ConvertToBoolValue(context, node_id, rhs_id);\n\n  // When the second operand is evaluated, the result of `and` and `or` is\n  // its value.\n  auto resume_block_id = context.inst_block_stack().PeekOrAdd(/*depth=*/1);\n  AddInst<SemIR::BranchWithArg>(\n      context, node_id, {.target_id = resume_block_id, .arg_id = rhs_id});\n  context.inst_block_stack().Pop();\n  context.region_stack().AddToRegion(resume_block_id, node_id);\n\n  // Collect the result from either the first or second operand.\n  auto result_id = AddInst<SemIR::BlockArg>(\n      context, node_id,\n      {.type_id = context.insts().Get(rhs_id).type_id(),\n       .block_id = resume_block_id});\n  SetBlockArgResultBeforeConstantUse(context, result_id, branch_value_id,\n                                     rhs_id, short_circuit_result_id);\n  context.node_stack().Push(node_id, result_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ShortCircuitOperatorAndId node_id)\n    -> bool {\n  return HandleShortCircuitOperator(context, node_id);\n}\n\nauto HandleParseNode(Context& context, Parse::ShortCircuitOperatorOrId node_id)\n    -> bool {\n  return HandleShortCircuitOperator(context, node_id);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_paren_expr.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& /*context*/, Parse::ParenExprStartId /*node_id*/)\n    -> bool {\n  // The open paren is unused.\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ParenExprId node_id) -> bool {\n  // We re-push because the ParenExpr is valid for member expressions, whereas\n  // the child expression might not be.\n  context.node_stack().Push(node_id, context.node_stack().PopExpr());\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_pattern_list.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/pattern.h\"\n#include \"toolchain/check/type.h\"\n\nnamespace Carbon::Check {\n\n// Handle the start of any kind of pattern list.\nstatic auto HandlePatternListStart(Context& context, Parse::NodeId node_id)\n    -> bool {\n  context.node_stack().Push(node_id);\n  context.param_and_arg_refs_stack().Push();\n  BeginSubpattern(context);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ImplicitParamListStartId node_id)\n    -> bool {\n  context.full_pattern_stack().StartImplicitParamList();\n  return HandlePatternListStart(context, node_id);\n}\n\nauto HandleParseNode(Context& context, Parse::TuplePatternStartId node_id)\n    -> bool {\n  return HandlePatternListStart(context, node_id);\n}\n\nauto HandleParseNode(Context& context, Parse::ExplicitParamListStartId node_id)\n    -> bool {\n  context.full_pattern_stack().StartExplicitParamList();\n  return HandlePatternListStart(context, node_id);\n}\n\n// Handle the end of any kind of parameter list (tuple patterns have separate\n// logic).\nstatic auto HandleParamListEnd(Context& context, Parse::NodeId node_id,\n                               Parse::NodeKind start_kind) -> bool {\n  if (context.node_stack().PeekIs(start_kind)) {\n    // End the subpattern started by a trailing comma, or the opening delimiter\n    // of an empty list.\n    EndSubpatternAsNonExpr(context);\n  }\n  // Note the Start node remains on the stack, where the param list handler can\n  // make use of it.\n  auto refs_id = context.param_and_arg_refs_stack().EndAndPop(start_kind);\n  context.node_stack().Push(node_id, refs_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ImplicitParamListId node_id)\n    -> bool {\n  context.full_pattern_stack().EndImplicitParamList();\n  return HandleParamListEnd(context, node_id,\n                            Parse::NodeKind::ImplicitParamListStart);\n}\n\nauto HandleParseNode(Context& context, Parse::ExplicitParamListId node_id)\n    -> bool {\n  context.full_pattern_stack().EndExplicitParamList();\n  return HandleParamListEnd(context, node_id,\n                            Parse::NodeKind::ExplicitParamListStart);\n}\n\nauto HandleParseNode(Context& context, Parse::TuplePatternId node_id) -> bool {\n  if (context.node_stack().PeekIs(Parse::NodeKind::TuplePatternStart)) {\n    // End the subpattern started by a trailing comma, or the opening delimiter\n    // of an empty list.\n    EndSubpatternAsNonExpr(context);\n  }\n  auto refs_id = context.param_and_arg_refs_stack().EndAndPop(\n      Parse::NodeKind::TuplePatternStart);\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::TuplePatternStart>();\n\n  const auto& inst_block = context.inst_blocks().Get(refs_id);\n  llvm::SmallVector<SemIR::InstId> type_inst_ids;\n  type_inst_ids.reserve(inst_block.size());\n  for (auto inst : inst_block) {\n    auto type_id = ExtractScrutineeType(context.sem_ir(),\n                                        context.insts().Get(inst).type_id());\n    type_inst_ids.push_back(context.types().GetTypeInstId(type_id));\n  }\n  auto type_id = GetPatternType(context, GetTupleType(context, type_inst_ids));\n  context.node_stack().Push(\n      node_id,\n      AddPatternInst<SemIR::TuplePattern>(\n          context, node_id, {.type_id = type_id, .elements_id = refs_id}));\n  EndSubpatternAsNonExpr(context);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::PatternListCommaId /*node_id*/)\n    -> bool {\n  context.param_and_arg_refs_stack().ApplyComma();\n  BeginSubpattern(context);\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_require.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/modifiers.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/subst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/named_constraint.h\"\n#include \"toolchain/sem_ir/specific_named_constraint.h\"\n#include \"toolchain/sem_ir/type_iterator.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::RequireIntroducerId node_id)\n    -> bool {\n  // Require decls are always generic, since everything in an `interface` or\n  // `constraint` is generic over `Self`.\n  StartGenericDecl(context);\n\n  // Create an instruction block to hold the instructions created for the type\n  // and constraint.\n  context.inst_block_stack().Push();\n\n  // Optional modifiers follow.\n  context.decl_introducer_state_stack().Push<Lex::TokenKind::Require>();\n\n  auto scope_id = context.scope_stack().PeekNameScopeId();\n  auto scope_inst_id = context.name_scopes().Get(scope_id).inst_id();\n  auto scope_inst = context.insts().Get(scope_inst_id);\n  if (!scope_inst.Is<SemIR::InterfaceWithSelfDecl>() &&\n      !scope_inst.Is<SemIR::NamedConstraintWithSelfDecl>()) {\n    CARBON_DIAGNOSTIC(\n        RequireInWrongScope, Error,\n        \"`require` can only be used in an `interface` or `constraint`\");\n    context.emitter().Emit(node_id, RequireInWrongScope);\n    scope_inst_id = SemIR::ErrorInst::InstId;\n  }\n\n  context.node_stack().Push(node_id, scope_inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::RequireDefaultSelfImplsId node_id)\n    -> bool {\n  auto scope_inst_id =\n      context.node_stack().Peek<Parse::NodeKind::RequireIntroducer>();\n  if (scope_inst_id == SemIR::ErrorInst::InstId) {\n    context.node_stack().Push(node_id, SemIR::ErrorInst::TypeInstId);\n    return true;\n  }\n\n  auto lookup_result =\n      LookupUnqualifiedName(context, node_id, SemIR::NameId::SelfType,\n                            /*required=*/true);\n  auto self_inst_id = lookup_result.scope_result.target_inst_id();\n  auto self_type_id = context.insts().Get(self_inst_id).type_id();\n  if (self_type_id == SemIR::ErrorInst::TypeId) {\n    context.node_stack().Push(node_id, SemIR::ErrorInst::TypeInstId);\n    return true;\n  }\n\n  CARBON_CHECK(context.types().Is<SemIR::FacetType>(self_type_id));\n  // TODO: We could simplify with a call to ExprAsType, like below?\n  auto self_facet_as_type = AddTypeInst<SemIR::FacetAccessType>(\n      context, node_id,\n      {.type_id = SemIR::TypeType::TypeId,\n       .facet_value_inst_id = self_inst_id});\n  context.node_stack().Push(node_id, self_facet_as_type);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::RequireTypeImplsId node_id)\n    -> bool {\n  auto [self_node_id, self_inst_id] = context.node_stack().PopExprWithNodeId();\n  auto self_type = ExprAsType(context, self_node_id, self_inst_id);\n\n  const auto& introducer = context.decl_introducer_state_stack().innermost();\n  if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {\n    if (self_type.type_id != SemIR::ErrorInst::TypeId) {\n      CARBON_DIAGNOSTIC(RequireImplsExtendWithExplicitSelf, Error,\n                        \"`extend require impls` with explicit type\");\n      // TODO: If the explicit self-type matches a lookup of NameId::SelfType,\n      // add a note to the diagnostic: \"remove the explicit `Self` type here\",\n      // and continue without an ErrorInst. See ExtendImplSelfAsDefault.\n      context.emitter().Emit(self_node_id, RequireImplsExtendWithExplicitSelf);\n    }\n    self_type.inst_id = SemIR::ErrorInst::TypeInstId;\n  }\n\n  context.node_stack().Push(node_id, self_type.inst_id);\n  return true;\n}\n\nstatic auto TypeStructureReferencesSelf(\n    Context& context, SemIR::LocId loc_id, SemIR::TypeInstId inst_id,\n    const SemIR::IdentifiedFacetType& identified_facet_type) -> bool {\n  auto find_self = [&](SemIR::TypeIterator& type_iter) -> bool {\n    while (true) {\n      auto step = type_iter.Next();\n      if (step.Is<SemIR::TypeIterator::Step::Done>()) {\n        break;\n      }\n      CARBON_KIND_SWITCH(step.any) {\n        case CARBON_KIND(SemIR::TypeIterator::Step::Error _): {\n          // Don't generate more diagnostics.\n          return true;\n        }\n        case CARBON_KIND(SemIR::TypeIterator::Step::SymbolicBinding bind): {\n          if (context.entity_names().Get(bind.entity_name_id).name_id ==\n              SemIR::NameId::SelfType) {\n            return true;\n          }\n          break;\n        }\n        default:\n          break;\n      }\n    }\n    return false;\n  };\n\n  {\n    SemIR::TypeIterator type_iter(&context.sem_ir());\n    type_iter.Add(context.constant_values().GetConstantTypeInstId(inst_id));\n    if (find_self(type_iter)) {\n      return true;\n    }\n  }\n\n  if (identified_facet_type.required_impls().empty()) {\n    CARBON_DIAGNOSTIC(\n        RequireImplsMissingSelfEmptyFacetType, Error,\n        \"no `Self` reference found in `require` declaration; `Self` must \"\n        \"appear in the self-type or as a generic argument for each required \"\n        \"interface, but no interfaces were found\");\n    context.emitter().Emit(loc_id, RequireImplsMissingSelfEmptyFacetType);\n    return false;\n  }\n\n  bool interfaces_all_reference_self = true;\n  for (auto [_, specific_interface] : identified_facet_type.required_impls()) {\n    SemIR::TypeIterator type_iter(&context.sem_ir());\n    type_iter.Add(specific_interface);\n    if (!find_self(type_iter)) {\n      // TODO: The IdentifiedFacetType loses the location (since it's\n      // canonical), but it would be nice to somehow point this diagnostic at\n      // the particular interface in the facet type that is missing `Self`.\n      CARBON_DIAGNOSTIC(\n          RequireImplsMissingSelf, Error,\n          \"no `Self` reference found in `require` declaration; `Self` must \"\n          \"appear in the self-type or as a generic argument for each required \"\n          \"interface, but found interface `{0}` without a `Self` argument\",\n          SemIR::SpecificInterface);\n      context.emitter().Emit(loc_id, RequireImplsMissingSelf,\n                             specific_interface);\n      interfaces_all_reference_self = false;\n    }\n  }\n  return interfaces_all_reference_self;\n}\n\nstruct ValidateRequireResult {\n  // The TypeId of a FacetType.\n  SemIR::TypeId constraint_type_id;\n  const SemIR::IdentifiedFacetType* identified_facet_type;\n};\n\n// Returns nullopt if a diagnostic has been emitted and the `require` decl is\n// not valid.\nstatic auto ValidateRequire(Context& context, SemIR::LocId loc_id,\n                            SemIR::TypeInstId self_inst_id,\n                            SemIR::InstId constraint_inst_id,\n                            SemIR::InstId scope_inst_id)\n    -> std::optional<ValidateRequireResult> {\n  auto self_constant_value_id = context.constant_values().Get(self_inst_id);\n  auto constraint_constant_value_id =\n      context.constant_values().Get(constraint_inst_id);\n\n  if (self_constant_value_id == SemIR::ErrorInst::ConstantId ||\n      constraint_constant_value_id == SemIR::ErrorInst::ConstantId ||\n      scope_inst_id == SemIR::ErrorInst::InstId) {\n    // An error was already diagnosed, don't diagnose another. We can't build a\n    // useful `require` with an error, it couldn't do anything.\n    return std::nullopt;\n  }\n\n  auto constraint_type_id =\n      SemIR::TypeId::ForTypeConstant(constraint_constant_value_id);\n  auto constraint_facet_type =\n      context.types().TryGetAs<SemIR::FacetType>(constraint_type_id);\n  if (!constraint_facet_type) {\n    CARBON_DIAGNOSTIC(\n        RequireImplsMissingFacetType, Error,\n        \"`require` declaration constrained by a non-facet type; \"\n        \"expected an `interface` or `constraint` name after `impls`\");\n    context.emitter().Emit(constraint_inst_id, RequireImplsMissingFacetType);\n    // Can't continue without a constraint to use.\n    return std::nullopt;\n  }\n\n  if (auto named_constraint =\n          context.insts().TryGetAs<SemIR::NamedConstraintWithSelfDecl>(\n              scope_inst_id)) {\n    const auto& constraint_facet_type_info =\n        context.facet_types().Get(constraint_facet_type->facet_type_id);\n    // TODO: Handle other impls named constraints for the\n    // RequireImplsReferenceCycle diagnostic.\n    if (constraint_facet_type_info.other_requirements) {\n      context.TODO(constraint_inst_id,\n                   \"facet type has constraints that we don't handle yet\");\n      return std::nullopt;\n    }\n    auto named_constraints = llvm::concat<const SemIR::SpecificNamedConstraint>(\n        constraint_facet_type_info.extend_named_constraints,\n        constraint_facet_type_info.self_impls_named_constraints);\n    for (auto c : named_constraints) {\n      if (c.named_constraint_id == named_constraint->named_constraint_id) {\n        const auto& named_constraint =\n            context.named_constraints().Get(c.named_constraint_id);\n        CARBON_DIAGNOSTIC(RequireImplsReferenceCycle, Error,\n                          \"facet type in `require` declaration refers to the \"\n                          \"named constraint `{0}` from within its definition\",\n                          SemIR::NameId);\n        context.emitter().Emit(constraint_inst_id, RequireImplsReferenceCycle,\n                               named_constraint.name_id);\n        return std::nullopt;\n      }\n    }\n  }\n\n  auto identified_facet_type_id = RequireIdentifiedFacetType(\n      context, SemIR::LocId(constraint_inst_id), self_constant_value_id,\n      *constraint_facet_type, [&](auto& builder) {\n        CARBON_DIAGNOSTIC(\n            RequireImplsUnidentifiedFacetType, Context,\n            \"facet type {0} cannot be identified in `require` declaration\",\n            InstIdAsType);\n        builder.Context(constraint_inst_id, RequireImplsUnidentifiedFacetType,\n                        constraint_inst_id);\n      });\n  if (!identified_facet_type_id.has_value()) {\n    // The constraint can't be used. A diagnostic was emitted by\n    // RequireIdentifiedFacetType().\n    return std::nullopt;\n  }\n  const auto& identified =\n      context.identified_facet_types().Get(identified_facet_type_id);\n\n  if (!TypeStructureReferencesSelf(context, loc_id, self_inst_id, identified)) {\n    return std::nullopt;\n  }\n\n  return ValidateRequireResult{.constraint_type_id = constraint_type_id,\n                               .identified_facet_type = &identified};\n}\n\nauto HandleParseNode(Context& context, Parse::RequireDeclId node_id) -> bool {\n  auto [constraint_node_id, constraint_inst_id] =\n      context.node_stack().PopExprWithNodeId();\n  auto [self_node_id, self_inst_id] =\n      context.node_stack().PopWithNodeId<Parse::NodeCategory::RequireImpls>();\n\n  auto decl_block_id = context.inst_block_stack().Pop();\n\n  // Process modifiers.\n  auto introducer =\n      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Require>();\n  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::Extend);\n  bool extend = introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend);\n\n  auto scope_inst_id =\n      context.node_stack().Pop<Parse::NodeKind::RequireIntroducer>();\n\n  auto validated = ValidateRequire(context, node_id, self_inst_id,\n                                   constraint_inst_id, scope_inst_id);\n  if (!validated) {\n    // In an `extend` decl, errors get propagated into the parent scope just as\n    // names do.\n    if (extend) {\n      auto scope_id = context.scope_stack().PeekNameScopeId();\n      context.name_scopes().Get(scope_id).set_has_error();\n    }\n    DiscardGenericDecl(context);\n    return true;\n  }\n\n  auto [constraint_type_id, identified_facet_type] = *validated;\n  if (identified_facet_type->required_impls().empty()) {\n    // A `require T impls type` adds no actual constraints, so nothing to do.\n    // This is not an error though.\n    DiscardGenericDecl(context);\n    return true;\n  }\n\n  auto require_impls_decl =\n      SemIR::RequireImplsDecl{// To be filled in after.\n                              .require_impls_id = SemIR::RequireImplsId::None,\n                              .decl_block_id = decl_block_id};\n  auto decl_id = AddPlaceholderInst(context, node_id, require_impls_decl);\n  auto require_impls_id = context.require_impls().Add(\n      {.self_id = self_inst_id,\n       .facet_type_inst_id =\n           context.types().GetAsTypeInstId(constraint_inst_id),\n       .extend_self = extend,\n       .decl_id = decl_id,\n       .parent_scope_id = context.scope_stack().PeekNameScopeId(),\n       .generic_id = BuildGenericDecl(context, decl_id)});\n\n  require_impls_decl.require_impls_id = require_impls_id;\n  ReplaceInstBeforeConstantUse(context, decl_id, require_impls_decl);\n\n  // We look for a complete type after BuildGenericDecl, so that the resulting\n  // RequireCompleteType instruction is part of the enclosing interface or named\n  // constraint generic definition. Then requiring enclosing entity to be\n  // complete will resolve that definition (via ResolveSpecificDefinition()) and\n  // also construct a specific for the `constraint_inst_id`, finding any\n  // monomorphization errors that result.\n  if (extend) {\n    if (!RequireCompleteType(\n            context, constraint_type_id, SemIR::LocId(constraint_inst_id),\n            [&](auto& builder) {\n              CARBON_DIAGNOSTIC(RequireImplsIncompleteFacetType, Context,\n                                \"`extend require` of incomplete facet type {0}\",\n                                InstIdAsType);\n              builder.Context(constraint_inst_id,\n                              RequireImplsIncompleteFacetType,\n                              constraint_inst_id);\n            })) {\n      return true;\n    }\n\n    // The extended scope instruction must be part of the enclosing scope (and\n    // generic). A specific for the enclosing scope will be applied to it when\n    // using the instruction later. To do so, we wrap the constraint facet type\n    // it in a SpecificConstant, which preserves the require declaration's\n    // specific along with the facet type.\n    //\n    // TODO: Remove the separate generic for each require decl, then we don't\n    // need a SpecificConstant anymore, as the constraint_inst_id will already\n    // be in the generic of the interface-with-self.\n    auto self_specific_id = context.generics().GetSelfSpecific(\n        context.require_impls().Get(require_impls_id).generic_id);\n    auto constraint_id_in_self_specific = AddTypeInst<SemIR::SpecificConstant>(\n        context, node_id,\n        {.type_id = SemIR::TypeType::TypeId,\n         .inst_id = constraint_inst_id,\n         .specific_id = self_specific_id});\n    auto enclosing_scope_id = context.scope_stack().PeekNameScopeId();\n    auto& enclosing_scope = context.name_scopes().Get(enclosing_scope_id);\n    enclosing_scope.AddExtendedScope(constraint_id_in_self_specific);\n  }\n\n  context.require_impls_stack().AppendToTop(require_impls_id);\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_return_statement.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/return.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::ReturnStatementStartId node_id)\n    -> bool {\n  // No action, just a bracketing node.\n  context.node_stack().Push(node_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ReturnVarModifierId node_id)\n    -> bool {\n  // No action, just a bracketing node.\n  context.node_stack().Push(node_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::ReturnStatementId node_id)\n    -> bool {\n  switch (context.node_stack().PeekNodeKind()) {\n    case Parse::NodeKind::ReturnStatementStart:\n      // This is a `return;` statement.\n      context.node_stack()\n          .PopAndDiscardSoloNodeId<Parse::NodeKind::ReturnStatementStart>();\n      BuildReturnWithNoExpr(context, node_id);\n      break;\n\n    case Parse::NodeKind::ReturnVarModifier:\n      // This is a `return var;` statement.\n      context.node_stack()\n          .PopAndDiscardSoloNodeId<Parse::NodeKind::ReturnVarModifier>();\n      context.node_stack()\n          .PopAndDiscardSoloNodeId<Parse::NodeKind::ReturnStatementStart>();\n      BuildReturnVar(context, node_id);\n      break;\n\n    default:\n      // This is a `return <expression>;` statement.\n      auto expr_id = context.node_stack().PopExpr();\n      context.node_stack()\n          .PopAndDiscardSoloNodeId<Parse::NodeKind::ReturnStatementStart>();\n      BuildReturnWithExpr(context, node_id, expr_id);\n      break;\n  }\n\n  // Switch to a new, unreachable, empty instruction block. This typically won't\n  // contain any semantics IR, but it can do if there are statements following\n  // the `return` statement.\n  context.inst_block_stack().Pop();\n  context.inst_block_stack().PushUnreachable();\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_struct.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"common/map.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/unused.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::StructLiteralStartId node_id)\n    -> bool {\n  context.scope_stack().PushForSameRegion();\n  context.node_stack().Push(node_id);\n  context.struct_type_fields_stack().PushArray();\n  context.param_and_arg_refs_stack().Push();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::StructTypeLiteralStartId node_id)\n    -> bool {\n  context.scope_stack().PushForSameRegion();\n  context.node_stack().Push(node_id);\n  context.struct_type_fields_stack().PushArray();\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::StructFieldDesignatorId /*node_id*/) -> bool {\n  // This leaves the designated name on top because the `.` isn't interesting.\n  CARBON_CHECK(context.node_stack().PeekIs<SemIR::NameId>());\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::StructLiteralCommaId /*node_id*/)\n    -> bool {\n  context.param_and_arg_refs_stack().ApplyComma();\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/,\n                     Parse::StructTypeLiteralCommaId /*node_id*/) -> bool {\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::StructLiteralFieldId node_id)\n    -> bool {\n  auto value_inst_id = context.node_stack().PopExpr();\n  // Get the name while leaving it on the stack.\n  auto name_id = context.node_stack().Peek<Parse::NodeCategory::MemberName>();\n\n  // Store the name for the type.\n  auto value_type_inst_id = context.types().GetTypeInstId(\n      context.insts().Get(value_inst_id).type_id());\n  context.struct_type_fields_stack().AppendToTop(\n      {.name_id = name_id, .type_inst_id = value_type_inst_id});\n\n  // Push the value back on the stack as an argument.\n  context.node_stack().Push(node_id, value_inst_id);\n  return true;\n}\n\nauto HandleParseNode(Context& context,\n                     Parse::StructTypeLiteralFieldId /*node_id*/) -> bool {\n  auto [type_node, type_id] = context.node_stack().PopExprWithNodeId();\n  auto cast_type_inst_id = ExprAsType(context, type_node, type_id).inst_id;\n  // Get the name while leaving it on the stack.\n  auto name_id = context.node_stack().Peek<Parse::NodeCategory::MemberName>();\n\n  context.struct_type_fields_stack().AppendToTop(\n      {.name_id = name_id, .type_inst_id = cast_type_inst_id});\n  return true;\n}\n\n// Diagnoses and returns true if there's a duplicate name.\nstatic auto DiagnoseDuplicateNames(\n    Context& context, llvm::ArrayRef<Parse::NodeId> field_name_nodes,\n    llvm::ArrayRef<SemIR::StructTypeField> fields, bool is_struct_type_literal)\n    -> bool {\n  Map<SemIR::NameId, Parse::NodeId> names;\n  for (auto [field_name_node, field] :\n       llvm::zip_equal(field_name_nodes, fields)) {\n    auto result = names.Insert(field.name_id, field_name_node);\n    if (!result.is_inserted()) {\n      CARBON_DIAGNOSTIC(StructNameDuplicate, Error,\n                        \"duplicated field name `{1}` in \"\n                        \"{0:struct type literal|struct literal}\",\n                        Diagnostics::BoolAsSelect, SemIR::NameId);\n      CARBON_DIAGNOSTIC(StructNamePrevious, Note,\n                        \"field with the same name here\");\n      context.emitter()\n          .Build(result.value(), StructNameDuplicate, is_struct_type_literal,\n                 field.name_id)\n          .Note(field_name_node, StructNamePrevious)\n          .Emit();\n      return true;\n    }\n  }\n  return false;\n}\n\n// Pops the names of each field from the stack. These will have been left while\n// handling struct fields.\nstatic auto PopFieldNameNodes(Context& context, size_t field_count)\n    -> llvm::SmallVector<Parse::NodeId> {\n  llvm::SmallVector<Parse::NodeId> nodes;\n  nodes.reserve(field_count);\n  while (true) {\n    auto [name_node, _] =\n        context.node_stack().PopWithNodeIdIf<Parse::NodeCategory::MemberName>();\n    if (name_node.has_value()) {\n      nodes.push_back(name_node);\n    } else {\n      break;\n    }\n  }\n  CARBON_CHECK(nodes.size() == field_count, \"Found {0} names, expected {1}\",\n               nodes.size(), field_count);\n  return nodes;\n}\n\nauto HandleParseNode(Context& context, Parse::StructLiteralId node_id) -> bool {\n  if (!context.node_stack().PeekIs(Parse::NodeCategory::MemberName)) {\n    // Remove the last parameter from the node stack before collecting names.\n    context.param_and_arg_refs_stack().EndNoPop(\n        Parse::NodeKind::StructLiteralStart);\n  }\n\n  auto fields = context.struct_type_fields_stack().PeekArray();\n  llvm::SmallVector<Parse::NodeId> field_name_nodes =\n      PopFieldNameNodes(context, fields.size());\n\n  auto elements_id = context.param_and_arg_refs_stack().EndAndPop(\n      Parse::NodeKind::StructLiteralStart);\n\n  context.scope_stack().Pop(/*check_unused=*/true);\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::StructLiteralStart>();\n\n  if (DiagnoseDuplicateNames(context, field_name_nodes, fields,\n                             /*is_struct_type_literal=*/false)) {\n    context.node_stack().Push(node_id, SemIR::ErrorInst::InstId);\n  } else {\n    auto type_id = GetStructType(\n        context, context.struct_type_fields().AddCanonical(fields));\n\n    auto value_id = AddInst<SemIR::StructLiteral>(\n        context, node_id, {.type_id = type_id, .elements_id = elements_id});\n    context.node_stack().Push(node_id, value_id);\n  }\n\n  context.struct_type_fields_stack().PopArray();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::StructTypeLiteralId node_id)\n    -> bool {\n  auto fields = context.struct_type_fields_stack().PeekArray();\n  llvm::SmallVector<Parse::NodeId> field_name_nodes =\n      PopFieldNameNodes(context, fields.size());\n\n  context.scope_stack().Pop(/*check_unused=*/true);\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::StructTypeLiteralStart>();\n\n  if (DiagnoseDuplicateNames(context, field_name_nodes, fields,\n                             /*is_struct_type_literal=*/true)) {\n    context.node_stack().Push(node_id, SemIR::ErrorInst::InstId);\n  } else {\n    auto fields_id = context.struct_type_fields().AddCanonical(fields);\n    AddInstAndPush<SemIR::StructType>(\n        context, node_id,\n        {.type_id = SemIR::TypeType::TypeId, .fields_id = fields_id});\n  }\n\n  context.struct_type_fields_stack().PopArray();\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_tuple_literal.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/type.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::TupleLiteralStartId node_id)\n    -> bool {\n  context.node_stack().Push(node_id);\n  context.param_and_arg_refs_stack().Push();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::TupleLiteralCommaId /*node_id*/)\n    -> bool {\n  context.param_and_arg_refs_stack().ApplyComma();\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::TupleLiteralId node_id) -> bool {\n  auto refs_id = context.param_and_arg_refs_stack().EndAndPop(\n      Parse::NodeKind::TupleLiteralStart);\n\n  context.node_stack()\n      .PopAndDiscardSoloNodeId<Parse::NodeKind::TupleLiteralStart>();\n  const auto& inst_block = context.inst_blocks().Get(refs_id);\n  llvm::SmallVector<SemIR::InstId> type_inst_ids;\n  type_inst_ids.reserve(inst_block.size());\n  for (auto inst : inst_block) {\n    type_inst_ids.push_back(\n        context.types().GetTypeInstId(context.insts().Get(inst).type_id()));\n  }\n  auto type_id = GetTupleType(context, type_inst_ids);\n\n  auto value_id = AddInst<SemIR::TupleLiteral>(\n      context, node_id, {.type_id = type_id, .elements_id = refs_id});\n  context.node_stack().Push(node_id, value_id);\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/handle_where.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/unused.h\"\n#include \"toolchain/sem_ir/facet_type_info.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {\n  // The expression at the top of the stack represents a constraint type that\n  // is being modified by the `where` operator. It would be `MyInterface` in\n  // `MyInterface where .Member = i32`.\n  auto [self_node, self_id] = context.node_stack().PopExprWithNodeId();\n  auto self_with_constraints_type_id =\n      ExprAsType(context, self_node, self_id).type_id;\n  // Only facet types may have `where` restrictions.\n  if (!context.types().IsFacetTypeOrError(self_with_constraints_type_id)) {\n    CARBON_DIAGNOSTIC(WhereOnNonFacetType, Error,\n                      \"left argument of `where` operator must be a facet type\");\n    context.emitter().Emit(self_node, WhereOnNonFacetType);\n    self_with_constraints_type_id = SemIR::ErrorInst::TypeId;\n  }\n\n  // Strip off any constraints provided by a `WhereExpr` from the `Self` facet\n  // type. For a facet type like `I & J where .X = .Y`, this will reduce it down\n  // to just `I & J`.\n  //\n  // Any references to `.Self` in constraints for the current `WhereExpr` will\n  // not see constraints in the `Self` facet type, but they will resolve to\n  // values through the constraints explicitly when they are combined together.\n  auto self_without_constraints_type_id = self_with_constraints_type_id;\n  if (auto facet_type = context.types().TryGetAs<SemIR::FacetType>(\n          self_without_constraints_type_id)) {\n    const auto& info = context.facet_types().Get(facet_type->facet_type_id);\n    auto stripped_info =\n        SemIR::FacetTypeInfo{.extend_constraints = info.extend_constraints};\n    stripped_info.Canonicalize();\n    self_without_constraints_type_id = GetFacetType(context, stripped_info);\n  }\n\n  // Introduce a name scope so that we can remove the `.Self` entry we are\n  // adding to name lookup at the end of the `where` expression.\n  context.scope_stack().PushForSameRegion();\n  // Introduce `.Self` as a symbolic binding. Its type is the value of the\n  // expression to the left of `where`, so `MyInterface` in the example above.\n  auto period_self_inst_id =\n      MakePeriodSelfFacetValue(context, self_without_constraints_type_id);\n\n  // Save the `.Self` symbolic binding on the node stack. It will become the\n  // first argument to the `WhereExpr` instruction.\n  context.node_stack().Push(node_id, period_self_inst_id);\n\n  // Going to put each requirement on `args_type_info_stack`, so we can have an\n  // inst block with the varying number of requirements but keeping other\n  // instructions on the current inst block from the `inst_block_stack()`.\n  context.args_type_info_stack().Push();\n\n  // Pass along all the constraints from the base facet type to be added to the\n  // resulting facet type.\n  context.args_type_info_stack().AddInstId(\n      AddInstInNoBlock<SemIR::RequirementBaseFacetType>(\n          context, SemIR::LocId(node_id),\n          {.base_type_inst_id =\n               context.types().GetTypeInstId(self_with_constraints_type_id)}));\n\n  // Add a context stack for tracking rewrite constraints, that will be used to\n  // allow later constraints to read from them eagerly.\n  context.rewrites_stack().emplace_back();\n\n  // Make rewrite constraints from the self facet type available immediately to\n  // expressions in rewrite constraints for this `where` expression.\n  if (auto self_facet_type = context.types().TryGetAs<SemIR::FacetType>(\n          self_with_constraints_type_id)) {\n    const auto& base_facet_type_info =\n        context.facet_types().Get(self_facet_type->facet_type_id);\n    for (const auto& rewrite : base_facet_type_info.rewrite_constraints) {\n      if (rewrite.lhs_id != SemIR::ErrorInst::InstId) {\n        context.rewrites_stack().back().Insert(\n            context.constant_values().Get(\n                GetImplWitnessAccessWithoutSubstitution(context,\n                                                        rewrite.lhs_id)),\n            rewrite.rhs_id);\n      }\n    }\n  }\n\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::RequirementEqualId node_id)\n    -> bool {\n  auto [rhs_node, rhs_id] = context.node_stack().PopExprWithNodeId();\n  auto lhs_id = context.node_stack().PopExpr();\n\n  // Convert rhs to type of lhs.\n  auto lhs_type_id = context.insts().Get(lhs_id).type_id();\n  if (lhs_type_id.is_symbolic()) {\n    // If the type of the associated constant is symbolic, we defer conversion\n    // until the constraint is resolved, in case it depends on `Self` (which\n    // will now be a reference to `.Self`).\n    // For now we convert to a value expression eagerly because otherwise we'll\n    // often be unable to constant-evaluate the enclosing `where` expression.\n    // TODO: Perform the conversion symbolically and add an implicit constraint\n    // that this conversion is valid and produces a constant.\n    rhs_id = ConvertToValueExpr(context, rhs_id);\n  } else {\n    rhs_id = ConvertToValueOfType(context, rhs_node, rhs_id,\n                                  context.insts().Get(lhs_id).type_id());\n  }\n\n  // Build up the list of arguments for the `WhereExpr` inst.\n  context.args_type_info_stack().AddInstId(\n      AddInstInNoBlock<SemIR::RequirementRewrite>(\n          context, node_id, {.lhs_id = lhs_id, .rhs_id = rhs_id}));\n\n  if (lhs_id != SemIR::ErrorInst::InstId) {\n    // Track the value of the rewrite so further constraints can use it\n    // immediately, before they are evaluated. This happens directly where the\n    // `ImplWitnessAccess` that refers to the rewrite constraint would have been\n    // created, and the value of the constraint will be used instead.\n    context.rewrites_stack().back().Insert(\n        context.constant_values().Get(\n            GetImplWitnessAccessWithoutSubstitution(context, lhs_id)),\n        rhs_id);\n  }\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::RequirementEqualEqualId node_id)\n    -> bool {\n  auto rhs = context.node_stack().PopExpr();\n  auto lhs = context.node_stack().PopExpr();\n  // TODO: Type check lhs and rhs are comparable.\n  // TODO: Require that at least one side uses a designator.\n\n  // Build up the list of arguments for the `WhereExpr` inst.\n  context.args_type_info_stack().AddInstId(\n      AddInstInNoBlock<SemIR::RequirementEquivalent>(\n          context, node_id, {.lhs_id = lhs, .rhs_id = rhs}));\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::RequirementImplsId node_id)\n    -> bool {\n  auto [rhs_node, rhs_id] = context.node_stack().PopExprWithNodeId();\n  auto [lhs_node, lhs_id] = context.node_stack().PopExprWithNodeId();\n\n  // Check lhs is a facet and rhs is a facet type.\n  auto lhs_as_type = ExprAsType(context, lhs_node, lhs_id);\n  auto rhs_as_type = ExprAsType(context, rhs_node, rhs_id);\n  if (rhs_as_type.type_id != SemIR::ErrorInst::TypeId &&\n      !context.types().IsFacetType(rhs_as_type.type_id)) {\n    CARBON_DIAGNOSTIC(\n        ImplsOnNonFacetType, Error,\n        \"right argument of `impls` requirement must be a facet type\");\n    context.emitter().Emit(rhs_node, ImplsOnNonFacetType);\n    rhs_as_type.inst_id = SemIR::ErrorInst::TypeInstId;\n  }\n  // TODO: Require that at least one side uses a designator.\n  // TODO: For things like `HashSet(.T) as type`, add an implied constraint\n  // that `.T impls Hash`.\n\n  // Build up the list of arguments for the `WhereExpr` inst.\n  context.args_type_info_stack().AddInstId(\n      AddInstInNoBlock<SemIR::RequirementImpls>(\n          context, node_id,\n          {.lhs_id = lhs_as_type.inst_id, .rhs_id = rhs_as_type.inst_id}));\n  return true;\n}\n\nauto HandleParseNode(Context& /*context*/, Parse::RequirementAndId /*node_id*/)\n    -> bool {\n  // Nothing to do.\n  return true;\n}\n\nauto HandleParseNode(Context& context, Parse::WhereExprId node_id) -> bool {\n  context.rewrites_stack().pop_back();\n  // Remove `PeriodSelf` from name lookup, undoing the `Push` done for the\n  // `WhereOperand`.\n  context.scope_stack().Pop(/*check_unused=*/true);\n  SemIR::InstId period_self_id =\n      context.node_stack().Pop<Parse::NodeKind::WhereOperand>();\n  SemIR::InstBlockId requirements_id = context.args_type_info_stack().Pop();\n  AddInstAndPush<SemIR::WhereExpr>(context, node_id,\n                                   {.type_id = SemIR::TypeType::TypeId,\n                                    .period_self_id = period_self_id,\n                                    .requirements_id = requirements_id});\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/impl.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/impl.h\"\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/deduce.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/function.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/impl_lookup.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/interface.h\"\n#include \"toolchain/check/merge.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/name_scope.h\"\n#include \"toolchain/check/thunk.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/check/type_structure.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/sem_ir/generic.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/impl.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Adds the location of the associated function to a diagnostic.\nstatic auto NoteAssociatedFunction(Context& context, DiagnosticBuilder& builder,\n                                   SemIR::FunctionId function_id) -> void {\n  CARBON_DIAGNOSTIC(AssociatedFunctionHere, Note,\n                    \"associated function {0} declared here\", SemIR::NameId);\n  const auto& function = context.functions().Get(function_id);\n  builder.Note(function.latest_decl_id(), AssociatedFunctionHere,\n               function.name_id);\n}\n\nauto CheckAssociatedFunctionImplementation(\n    Context& context, SemIR::FunctionType interface_function_type,\n    SemIR::SpecificId enclosing_specific_id, SemIR::InstId impl_decl_id,\n    bool defer_thunk_definition) -> SemIR::InstId {\n  auto impl_function_decl =\n      context.insts().TryGetAs<SemIR::FunctionDecl>(impl_decl_id);\n  if (!impl_function_decl) {\n    if (impl_decl_id != SemIR::ErrorInst::InstId) {\n      CARBON_DIAGNOSTIC(ImplFunctionWithNonFunction, Error,\n                        \"associated function {0} implemented by non-function\",\n                        SemIR::NameId);\n      auto builder = context.emitter().Build(\n          impl_decl_id, ImplFunctionWithNonFunction,\n          context.functions().Get(interface_function_type.function_id).name_id);\n      NoteAssociatedFunction(context, builder,\n                             interface_function_type.function_id);\n      builder.Emit();\n    }\n\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // Map from the specific for the function type to the specific for the\n  // function signature. The function signature may have additional generic\n  // parameters.\n  auto interface_function_specific_id =\n      GetSelfSpecificForInterfaceMemberWithSelfType(\n          context, SemIR::LocId(impl_decl_id),\n          interface_function_type.specific_id,\n          context.functions()\n              .Get(interface_function_type.function_id)\n              .generic_id,\n          enclosing_specific_id);\n\n  return BuildThunk(context, interface_function_type.function_id,\n                    interface_function_specific_id, impl_decl_id,\n                    defer_thunk_definition);\n}\n\n// Returns true if impl redeclaration parameters match.\nstatic auto CheckImplRedeclParamsMatch(Context& context,\n                                       const SemIR::Impl& new_impl,\n                                       SemIR::ImplId prev_impl_id) -> bool {\n  auto& prev_impl = context.impls().Get(prev_impl_id);\n\n  // If the parameters aren't the same, then this is not a redeclaration of this\n  // `impl`. Keep looking for a prior declaration without issuing a diagnostic.\n  if (!CheckRedeclParamsMatch(context, DeclParams(new_impl),\n                              DeclParams(prev_impl), SemIR::SpecificId::None,\n                              /*diagnose=*/false, /*check_syntax=*/true,\n                              /*check_self=*/true)) {\n    // NOLINTNEXTLINE(readability-simplify-boolean-expr)\n    return false;\n  }\n  return true;\n}\n\n// Returns whether an impl can be redeclared. For example, defined impls\n// cannot be redeclared.\nstatic auto IsValidImplRedecl(Context& context, const SemIR::Impl& new_impl,\n                              SemIR::ImplId prev_impl_id) -> bool {\n  auto& prev_impl = context.impls().Get(prev_impl_id);\n\n  // TODO: Following #3763, disallow redeclarations in different scopes.\n\n  // Following #4672, disallowing defining non-extern declarations in another\n  // file.\n  if (auto import_ref =\n          context.insts().TryGetAs<SemIR::AnyImportRef>(prev_impl.self_id)) {\n    // TODO: Handle extern.\n    CARBON_DIAGNOSTIC(RedeclImportedImpl, Error,\n                      \"redeclaration of imported impl\");\n    // TODO: Note imported declaration\n    context.emitter().Emit(new_impl.latest_decl_id(), RedeclImportedImpl);\n    return false;\n  }\n\n  if (prev_impl.has_definition_started()) {\n    // Impls aren't merged in order to avoid generic region lookup into a\n    // mismatching table.\n    CARBON_DIAGNOSTIC(ImplRedefinition, Error,\n                      \"redefinition of `impl {0} as {1}`\", InstIdAsRawType,\n                      InstIdAsRawType);\n    CARBON_DIAGNOSTIC(ImplPreviousDefinition, Note,\n                      \"previous definition was here\");\n    context.emitter()\n        .Build(new_impl.latest_decl_id(), ImplRedefinition, new_impl.self_id,\n               new_impl.constraint_id)\n        .Note(prev_impl.definition_id, ImplPreviousDefinition)\n        .Emit();\n    return false;\n  }\n\n  // TODO: Only allow redeclaration in a match_first/impl_priority block.\n\n  return true;\n}\n\n// Looks for any unused generic bindings. If one is found, it is diagnosed and\n// false is returned.\nstatic auto VerifyAllGenericBindingsUsed(Context& context, SemIR::LocId loc_id,\n                                         SemIR::LocId implicit_params_loc_id,\n                                         SemIR::Impl& impl) -> bool {\n  if (impl.witness_id == SemIR::ErrorInst::InstId) {\n    return true;\n  }\n  if (!impl.generic_id.has_value()) {\n    return true;\n  }\n\n  if (impl.implicit_param_patterns_id.has_value()) {\n    for (auto inst_id :\n         context.inst_blocks().Get(impl.implicit_param_patterns_id)) {\n      if (inst_id == SemIR::ErrorInst::InstId) {\n        // An error was already diagnosed for a generic binding.\n        return true;\n      }\n    }\n  }\n\n  auto deduced_specific_id = DeduceImplArguments(\n      context, loc_id, impl, context.constant_values().Get(impl.self_id),\n      impl.interface.specific_id);\n  if (deduced_specific_id.has_value()) {\n    // Deduction succeeded, all bindings were used.\n    return true;\n  }\n\n  CARBON_DIAGNOSTIC(ImplUnusedBinding, Error,\n                    \"`impl` with unused generic binding\");\n  // TODO: This location may be incorrect, the binding may be inherited\n  // from an outer declaration. It would be nice to get the particular\n  // binding that was undeducible back from DeduceImplArguments here and\n  // use that.\n  auto diag_loc_id =\n      implicit_params_loc_id.has_value() ? implicit_params_loc_id : loc_id;\n  context.emitter().Emit(diag_loc_id, ImplUnusedBinding);\n  return false;\n}\n\n// Apply an `extend impl` declaration by extending the parent scope with the\n// `impl`. If there's an error it is diagnosed and false is returned.\nstatic auto ApplyExtendImplAs(Context& context, SemIR::LocId loc_id,\n                              const SemIR::Impl& impl,\n                              Parse::NodeId extend_node,\n                              SemIR::LocId implicit_params_loc_id) -> bool {\n  auto parent_scope_id = context.decl_name_stack().PeekParentScopeId();\n\n  // TODO: Also handle the parent scope being a mixin.\n  auto class_scope = TryAsClassScope(context, parent_scope_id);\n  if (!class_scope) {\n    if (impl.witness_id != SemIR::ErrorInst::InstId) {\n      CARBON_DIAGNOSTIC(\n          ExtendImplOutsideClass, Error,\n          \"`extend impl` can only be used in an interface or class\");\n      context.emitter().Emit(loc_id, ExtendImplOutsideClass);\n    }\n    return false;\n  }\n\n  auto& parent_scope = *class_scope->name_scope;\n\n  // An error was already diagnosed, but this is `extend impl as` inside a\n  // class, so propagate the error into the enclosing class scope.\n  if (impl.witness_id == SemIR::ErrorInst::InstId) {\n    parent_scope.set_has_error();\n    return false;\n  }\n\n  if (implicit_params_loc_id.has_value()) {\n    CARBON_DIAGNOSTIC(ExtendImplForall, Error,\n                      \"cannot `extend` a parameterized `impl`\");\n    context.emitter().Emit(extend_node, ExtendImplForall);\n    parent_scope.set_has_error();\n    return false;\n  }\n\n  if (!RequireCompleteType(\n          context, context.types().GetTypeIdForTypeInstId(impl.constraint_id),\n          SemIR::LocId(impl.constraint_id), [&](auto& builder) {\n            CARBON_DIAGNOSTIC(ExtendImplAsIncomplete, Context,\n                              \"`extend impl as` incomplete facet type {0}\",\n                              InstIdAsType);\n            builder.Context(impl.latest_decl_id(), ExtendImplAsIncomplete,\n                            impl.constraint_id);\n          })) {\n    parent_scope.set_has_error();\n    return false;\n  }\n\n  if (!impl.generic_id.has_value()) {\n    parent_scope.AddExtendedScope(impl.constraint_id);\n  } else {\n    // The extended scope instruction must be part of the enclosing scope (and\n    // generic). A specific for the enclosing scope will be applied to it when\n    // using the instruction later. To do so, we wrap the constraint facet type\n    // it in a SpecificConstant, which preserves the impl declaration's\n    // specific along with the facet type.\n    auto constraint_id_in_self_specific = AddTypeInst<SemIR::SpecificConstant>(\n        context, SemIR::LocId(impl.constraint_id),\n        {.type_id = SemIR::TypeType::TypeId,\n         .inst_id = impl.constraint_id,\n         .specific_id = context.generics().GetSelfSpecific(impl.generic_id)});\n    parent_scope.AddExtendedScope(constraint_id_in_self_specific);\n  }\n  return true;\n}\n\nauto FindImplId(Context& context, const SemIR::Impl& query_impl)\n    -> std::variant<RedeclaredImpl, NewImpl> {\n  // Look for an existing matching declaration.\n  auto lookup_bucket_ref = context.impls().GetOrAddLookupBucket(query_impl);\n  // TODO: Detect two impl declarations with the same self type and interface,\n  // and issue an error if they don't match.\n  for (auto prev_impl_id : lookup_bucket_ref) {\n    if (CheckImplRedeclParamsMatch(context, query_impl, prev_impl_id)) {\n      if (IsValidImplRedecl(context, query_impl, prev_impl_id)) {\n        return RedeclaredImpl{.prev_impl_id = prev_impl_id};\n      } else {\n        // IsValidImplRedecl() has issued a diagnostic, take care to avoid\n        // generating more diagnostics for this declaration.\n        return NewImpl{.lookup_bucket = lookup_bucket_ref,\n                       .find_had_error = true};\n      }\n      break;\n    }\n  }\n\n  return NewImpl{.lookup_bucket = lookup_bucket_ref, .find_had_error = false};\n}\n\n// Sets the `ImplId` in the `ImplWitnessTable`.\nstatic auto AssignImplIdInWitness(Context& context, SemIR::ImplId impl_id,\n                                  SemIR::InstId witness_id) -> void {\n  if (witness_id == SemIR::ErrorInst::InstId) {\n    return;\n  }\n  auto witness = context.insts().GetAs<SemIR::ImplWitness>(witness_id);\n  auto witness_table =\n      context.insts().GetAs<SemIR::ImplWitnessTable>(witness.witness_table_id);\n  witness_table.impl_id = impl_id;\n  // Note: The `ImplWitnessTable` instruction is `Unique`, so while this marks\n  // the instruction as being a dependent instruction of a generic impl, it will\n  // not be substituted into the eval block.\n  ReplaceInstBeforeConstantUse(context, witness.witness_table_id,\n                               witness_table);\n}\n\nauto AddImpl(Context& context, const SemIR::Impl& impl,\n             SemIR::ImplStore::LookupBucketRef lookup_bucket,\n             Parse::NodeId extend_node, SemIR::LocId implicit_params_loc_id)\n    -> SemIR::ImplId {\n  auto impl_decl_id = impl.latest_decl_id();\n\n  // From here on, use the `Impl` from the `ImplStore` instead of `impl` in\n  // order to make and see any changes to the `Impl`.\n  auto impl_id = context.impls().Add(impl);\n  lookup_bucket.push_back(impl_id);\n  AssignImplIdInWitness(context, impl_id, impl.witness_id);\n\n  auto& stored_impl = context.impls().Get(impl_id);\n\n  // Look to see if there are any generic bindings on the `impl` declaration\n  // that are not deducible. If so, and the `impl` does not actually use all\n  // its generic bindings, and will never be matched. This should be\n  // diagnossed to the user.\n  if (!VerifyAllGenericBindingsUsed(context, SemIR::LocId(impl_decl_id),\n                                    implicit_params_loc_id, stored_impl)) {\n    FillImplWitnessWithErrors(context, stored_impl);\n  }\n\n  if (extend_node.has_value()) {\n    if (!ApplyExtendImplAs(context, SemIR::LocId(impl_decl_id), stored_impl,\n                           extend_node, implicit_params_loc_id)) {\n      FillImplWitnessWithErrors(context, stored_impl);\n    }\n  }\n\n  return impl_id;\n}\n\n// Returns whether the `LookupImplWitness` of `witness_id` matches `interface`.\nstatic auto WitnessQueryMatchesInterface(\n    Context& context, SemIR::InstId witness_id,\n    const SemIR::SpecificInterface& interface) -> bool {\n  auto lookup = context.insts().GetAs<SemIR::LookupImplWitness>(witness_id);\n  return interface ==\n         context.specific_interfaces().Get(lookup.query_specific_interface_id);\n}\n\nauto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,\n                                  const SemIR::Impl& impl,\n                                  SemIR::SpecificId self_specific_id)\n    -> SemIR::InstId {\n  auto facet_type_id =\n      context.types().GetTypeIdForTypeInstId(impl.constraint_id);\n  CARBON_CHECK(facet_type_id != SemIR::ErrorInst::TypeId);\n  auto facet_type = context.types().GetAs<SemIR::FacetType>(facet_type_id);\n  const auto& facet_type_info =\n      context.facet_types().Get(facet_type.facet_type_id);\n\n  // An iterator over the rewrite_constraints where the LHS of the rewrite names\n  // a member of the `impl.interface`. This filters out rewrites of names\n  // from other interfaces, as they do not set values in the witness table.\n  auto rewrites_into_interface_to_witness = llvm::make_filter_range(\n      facet_type_info.rewrite_constraints,\n      [&](const SemIR::FacetTypeInfo::RewriteConstraint& rewrite) {\n        auto access = context.insts().GetAs<SemIR::ImplWitnessAccess>(\n            GetImplWitnessAccessWithoutSubstitution(context, rewrite.lhs_id));\n        return WitnessQueryMatchesInterface(context, access.witness_id,\n                                            impl.interface);\n      });\n\n  if (rewrites_into_interface_to_witness.empty()) {\n    // The witness table is not needed until the definition. Make a placeholder\n    // for the declaration.\n    auto witness_table_inst_id = AddInst<SemIR::ImplWitnessTable>(\n        context, loc_id,\n        {.elements_id = context.inst_blocks().AddPlaceholder(),\n         .impl_id = SemIR::ImplId::None});\n    return AddInst<SemIR::ImplWitness>(\n        context, loc_id,\n        {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),\n         .witness_table_id = witness_table_inst_id,\n         .specific_id = self_specific_id});\n  }\n\n  const auto& interface = context.interfaces().Get(impl.interface.interface_id);\n  if (!interface.is_complete()) {\n    // This is a declaration with rewrite constraints into `.Self`, but the\n    // interface is not complete. Those rewrites have already been diagnosed as\n    // an error in their member access.\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto assoc_entities =\n      context.inst_blocks().Get(interface.associated_entities_id);\n  // TODO: When this function is used for things other than just impls, may want\n  // to only load the specific associated entities that are mentioned in rewrite\n  // rules.\n  for (auto decl_id : assoc_entities) {\n    LoadImportRef(context, decl_id);\n  }\n\n  SemIR::InstId witness_inst_id = SemIR::InstId::None;\n  llvm::MutableArrayRef<SemIR::InstId> table;\n  {\n    auto elements_id =\n        context.inst_blocks().AddUninitialized(assoc_entities.size());\n    table = context.inst_blocks().GetMutable(elements_id);\n    for (auto& uninit : table) {\n      uninit = SemIR::InstId::ImplWitnessTablePlaceholder;\n    }\n\n    auto witness_table_inst_id = AddInst<SemIR::ImplWitnessTable>(\n        context, loc_id,\n        {.elements_id = elements_id, .impl_id = SemIR::ImplId::None});\n\n    witness_inst_id = AddInst<SemIR::ImplWitness>(\n        context, loc_id,\n        {.type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),\n         .witness_table_id = witness_table_inst_id,\n         .specific_id = self_specific_id});\n  }\n\n  for (auto rewrite : rewrites_into_interface_to_witness) {\n    auto access = context.insts().GetAs<SemIR::ImplWitnessAccess>(\n        GetImplWitnessAccessWithoutSubstitution(context, rewrite.lhs_id));\n    auto& table_entry = table[access.index.index];\n    if (table_entry == SemIR::ErrorInst::InstId) {\n      // Don't overwrite an error value. This prioritizes not generating\n      // multiple errors for one associated constant over picking a value\n      // for it to use to attempt recovery.\n      continue;\n    }\n    auto rewrite_inst_id = rewrite.rhs_id;\n    if (rewrite_inst_id == SemIR::ErrorInst::InstId) {\n      table_entry = SemIR::ErrorInst::InstId;\n      continue;\n    }\n\n    auto decl_id = context.constant_values().GetConstantInstId(\n        assoc_entities[access.index.index]);\n    CARBON_CHECK(decl_id.has_value(), \"Non-constant associated entity\");\n    if (decl_id == SemIR::ErrorInst::InstId) {\n      table_entry = SemIR::ErrorInst::InstId;\n      continue;\n    }\n\n    auto assoc_constant_decl =\n        context.insts().TryGetAs<SemIR::AssociatedConstantDecl>(decl_id);\n    if (!assoc_constant_decl) {\n      auto type_id = context.insts().Get(decl_id).type_id();\n      auto type_inst = context.types().GetAsInst(type_id);\n      auto fn_type = type_inst.As<SemIR::FunctionType>();\n      const auto& fn = context.functions().Get(fn_type.function_id);\n      CARBON_DIAGNOSTIC(RewriteForAssociatedFunction, Error,\n                        \"rewrite specified for associated function {0}\",\n                        SemIR::NameId);\n      context.emitter().Emit(impl.constraint_id, RewriteForAssociatedFunction,\n                             fn.name_id);\n      table_entry = SemIR::ErrorInst::InstId;\n      continue;\n    }\n\n    // FacetTypes resolution disallows two rewrites to the same associated\n    // constant, so we won't ever have a facet write twice to the same position\n    // in the witness table.\n    CARBON_CHECK(table_entry == SemIR::InstId::ImplWitnessTablePlaceholder);\n\n    // If the associated constant has a symbolic type, convert the rewrite\n    // value to that type now we know the value of `Self`.\n    SemIR::TypeId assoc_const_type_id = assoc_constant_decl->type_id;\n    if (assoc_const_type_id.is_symbolic()) {\n      auto self_facet = GetConstantFacetValueForType(context, impl.self_id);\n      auto interface_with_self_specific_id = MakeSpecificWithInnerSelf(\n          context, loc_id, interface.generic_id, interface.generic_with_self_id,\n          impl.interface.specific_id, self_facet);\n\n      // Get the type of the associated constant in this interface with this\n      // value for `Self`.\n      assoc_const_type_id = GetTypeForSpecificAssociatedEntity(\n          context, interface_with_self_specific_id, decl_id);\n      // Perform the conversion of the value to the type. We skipped this when\n      // forming the facet type because the type of the associated constant\n      // was symbolic.\n      auto converted_inst_id =\n          ConvertToValueOfType(context, SemIR::LocId(impl.constraint_id),\n                               rewrite_inst_id, assoc_const_type_id);\n      // Canonicalize the converted constant value.\n      converted_inst_id =\n          context.constant_values().GetConstantInstId(converted_inst_id);\n      // The result of conversion can be non-constant even if the original\n      // value was constant.\n      if (converted_inst_id.has_value()) {\n        rewrite_inst_id = converted_inst_id;\n      } else {\n        const auto& assoc_const = context.associated_constants().Get(\n            assoc_constant_decl->assoc_const_id);\n        CARBON_DIAGNOSTIC(\n            AssociatedConstantNotConstantAfterConversion, Error,\n            \"associated constant {0} given value {1} that is not constant \"\n            \"after conversion to {2}\",\n            SemIR::NameId, InstIdAsConstant, SemIR::TypeId);\n        context.emitter().Emit(\n            impl.constraint_id, AssociatedConstantNotConstantAfterConversion,\n            assoc_const.name_id, rewrite_inst_id, assoc_const_type_id);\n        rewrite_inst_id = SemIR::ErrorInst::InstId;\n      }\n    }\n\n    CARBON_CHECK(rewrite_inst_id == context.constant_values().GetConstantInstId(\n                                        rewrite_inst_id),\n                 \"Rewritten value for associated constant is not canonical.\");\n\n    table_entry = AddInst<SemIR::ImplWitnessAssociatedConstant>(\n        context, loc_id,\n        {.type_id = context.insts().Get(rewrite_inst_id).type_id(),\n         .inst_id = rewrite_inst_id});\n  }\n  return witness_inst_id;\n}\n\nauto ImplWitnessStartDefinition(Context& context, SemIR::Impl& impl) -> void {\n  CARBON_CHECK(impl.is_being_defined());\n  CARBON_CHECK(impl.witness_id.has_value());\n  if (impl.witness_id == SemIR::ErrorInst::InstId) {\n    return;\n  }\n\n  {\n    if (!RequireCompleteType(\n            context, context.types().GetTypeIdForTypeInstId(impl.constraint_id),\n            SemIR::LocId(impl.constraint_id), [&](auto& builder) {\n              CARBON_DIAGNOSTIC(\n                  ImplAsIncompleteFacetTypeDefinition, Context,\n                  \"definition of impl as incomplete facet type {0}\",\n                  InstIdAsType);\n              builder.Context(SemIR::LocId(impl.latest_decl_id()),\n                              ImplAsIncompleteFacetTypeDefinition,\n                              impl.constraint_id);\n            })) {\n      FillImplWitnessWithErrors(context, impl);\n      return;\n    }\n  }\n\n  const auto& interface = context.interfaces().Get(impl.interface.interface_id);\n\n  auto assoc_entities =\n      context.inst_blocks().Get(interface.associated_entities_id);\n  for (auto decl_id : assoc_entities) {\n    LoadImportRef(context, decl_id);\n  }\n\n  auto witness = context.insts().GetAs<SemIR::ImplWitness>(impl.witness_id);\n  auto witness_table =\n      context.insts().GetAs<SemIR::ImplWitnessTable>(witness.witness_table_id);\n  auto witness_block =\n      context.inst_blocks().GetMutable(witness_table.elements_id);\n\n  // The impl declaration may have created a placeholder witness table, or a\n  // full witness table. We can detect that the witness table is a placeholder\n  // table if it's not the `Empty` id, but it is empty still. If it was a\n  // placeholder, we can replace the placeholder here with a table of the proper\n  // size, since the interface must be complete for the impl definition.\n  bool witness_table_is_placeholder =\n      witness_table.elements_id != SemIR::InstBlockId::Empty &&\n      witness_block.empty();\n  if (witness_table_is_placeholder) {\n    // TODO: Since our `empty_table` repeats the same value throughout, we could\n    // skip an allocation here if there was a `ReplacePlaceholder` function that\n    // took a size and value instead of an array of values.\n    llvm::SmallVector<SemIR::InstId> empty_table(\n        assoc_entities.size(), SemIR::InstId::ImplWitnessTablePlaceholder);\n    context.inst_blocks().ReplacePlaceholder(witness_table.elements_id,\n                                             empty_table);\n    witness_block = context.inst_blocks().GetMutable(witness_table.elements_id);\n  }\n\n  // Check we have a value for all non-function associated constants in the\n  // witness.\n  for (auto [assoc_entity, witness_value] :\n       llvm::zip_equal(assoc_entities, witness_block)) {\n    auto decl_id = context.constant_values().GetConstantInstId(assoc_entity);\n    CARBON_CHECK(decl_id.has_value(), \"Non-constant associated entity\");\n    if (auto decl =\n            context.insts().TryGetAs<SemIR::AssociatedConstantDecl>(decl_id)) {\n      if (witness_value == SemIR::InstId::ImplWitnessTablePlaceholder) {\n        CARBON_DIAGNOSTIC(ImplAssociatedConstantNeedsValue, Error,\n                          \"associated constant {0} not given a value in impl \"\n                          \"of interface {1}\",\n                          SemIR::NameId, SemIR::NameId);\n        CARBON_DIAGNOSTIC(AssociatedConstantHere, Note,\n                          \"associated constant declared here\");\n        context.emitter()\n            .Build(impl.definition_id, ImplAssociatedConstantNeedsValue,\n                   context.associated_constants()\n                       .Get(decl->assoc_const_id)\n                       .name_id,\n                   interface.name_id)\n            .Note(assoc_entity, AssociatedConstantHere)\n            .Emit();\n\n        witness_value = SemIR::ErrorInst::InstId;\n      }\n    }\n  }\n}\n\n// Adds functions to the witness that the specified impl implements the given\n// interface.\nauto FinishImplWitness(Context& context, const SemIR::Impl& impl) -> void {\n  CARBON_CHECK(impl.is_being_defined());\n  CARBON_CHECK(impl.witness_id.has_value());\n  if (impl.witness_id == SemIR::ErrorInst::InstId) {\n    return;\n  }\n  auto witness = context.insts().GetAs<SemIR::ImplWitness>(impl.witness_id);\n  auto witness_table =\n      context.insts().GetAs<SemIR::ImplWitnessTable>(witness.witness_table_id);\n  auto witness_block =\n      context.inst_blocks().GetMutable(witness_table.elements_id);\n  auto& impl_scope = context.name_scopes().Get(impl.scope_id);\n  const auto& interface = context.interfaces().Get(impl.interface.interface_id);\n  auto assoc_entities =\n      context.inst_blocks().Get(interface.associated_entities_id);\n  llvm::SmallVector<SemIR::InstId> used_decl_ids;\n\n  auto self_facet = GetConstantFacetValueForTypeAndInterface(\n      context, impl.self_id, impl.interface, impl.witness_id);\n  auto interface_with_self_specific_id = MakeSpecificWithInnerSelf(\n      context, SemIR::LocId(impl.definition_id), interface.generic_id,\n      interface.generic_with_self_id, impl.interface.specific_id, self_facet);\n\n  for (auto [assoc_entity, witness_value] :\n       llvm::zip_equal(assoc_entities, witness_block)) {\n    auto decl_id =\n        context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(\n            context.sem_ir(), interface_with_self_specific_id, assoc_entity));\n    CARBON_CHECK(decl_id.has_value(), \"Non-constant associated entity\");\n    auto decl = context.insts().Get(decl_id);\n    CARBON_KIND_SWITCH(decl) {\n      case CARBON_KIND(SemIR::StructValue struct_value): {\n        if (struct_value.type_id == SemIR::ErrorInst::TypeId) {\n          witness_value = SemIR::ErrorInst::InstId;\n          break;\n        }\n        auto type_inst = context.types().GetAsInst(struct_value.type_id);\n        auto fn_type = type_inst.TryAs<SemIR::FunctionType>();\n        if (!fn_type) {\n          CARBON_FATAL(\"Unexpected type: {0}\", type_inst);\n        }\n        auto& fn = context.functions().Get(fn_type->function_id);\n        auto lookup_result =\n            LookupNameInExactScope(context, SemIR::LocId(decl_id), fn.name_id,\n                                   impl.scope_id, impl_scope);\n        if (lookup_result.is_found()) {\n          used_decl_ids.push_back(lookup_result.target_inst_id());\n          witness_value = CheckAssociatedFunctionImplementation(\n              context, *fn_type,\n              context.generics().GetSelfSpecific(impl.generic_id),\n              lookup_result.target_inst_id(),\n              /*defer_thunk_definition=*/true);\n        } else {\n          CARBON_DIAGNOSTIC(\n              ImplMissingFunction, Error,\n              \"missing implementation of {0} in impl of interface {1}\",\n              SemIR::NameId, SemIR::NameId);\n          auto builder =\n              context.emitter().Build(impl.definition_id, ImplMissingFunction,\n                                      fn.name_id, interface.name_id);\n          NoteAssociatedFunction(context, builder, fn_type->function_id);\n          builder.Emit();\n\n          witness_value = SemIR::ErrorInst::InstId;\n        }\n        break;\n      }\n      case SemIR::AssociatedConstantDecl::Kind: {\n        // These are set to their final values already.\n        break;\n      }\n      default:\n        CARBON_CHECK(decl_id == SemIR::ErrorInst::InstId,\n                     \"Unexpected kind of associated entity {0}\", decl);\n        witness_value = SemIR::ErrorInst::InstId;\n        break;\n    }\n  }\n\n  // TODO: Diagnose if any declarations in the impl are not in used_decl_ids.\n}\n\nauto CheckRequireDeclsSatisfied(Context& context, SemIR::LocId loc_id,\n                                SemIR::Impl& impl) -> void {\n  if (impl.witness_id == SemIR::ErrorInst::InstId) {\n    return;\n  }\n\n  const auto& interface = context.interfaces().Get(impl.interface.interface_id);\n  if (!interface.is_complete()) {\n    // This will be diagnosed later. We check for required decls before starting\n    // the definition to avoid inserting these lookups into the definition, as\n    // the lookups can end up looking for the impl being defined, which creates\n    // a cycle.\n    return;\n  }\n\n  auto require_ids =\n      context.require_impls_blocks().Get(interface.require_impls_block_id);\n  if (require_ids.empty()) {\n    return;\n  }\n\n  // Make a facet value for the self type.\n  auto self_facet = GetConstantFacetValueForType(context, impl.self_id);\n  auto interface_with_self_specific_id = MakeSpecificWithInnerSelf(\n      context, loc_id, interface.generic_id, interface.generic_with_self_id,\n      impl.interface.specific_id, self_facet);\n\n  for (auto require_id : require_ids) {\n    const auto& require = context.require_impls().Get(require_id);\n\n    // Each require is in its own generic, with no additional bindings and no\n    // definition, so that they can have their specifics independently\n    // instantiated.\n    auto require_specific_id = CopySpecificToGeneric(\n        context, SemIR::LocId(require.decl_id), interface_with_self_specific_id,\n        require.generic_id);\n    auto self_const_id = GetConstantValueInSpecific(\n        context.sem_ir(), require_specific_id, require.self_id);\n    auto facet_type_const_id = GetConstantValueInSpecific(\n        context.sem_ir(), require_specific_id, require.facet_type_inst_id);\n    if (self_const_id == SemIR::ErrorInst::ConstantId ||\n        facet_type_const_id == SemIR::ErrorInst::ConstantId) {\n      FillImplWitnessWithErrors(context, impl);\n      break;\n    }\n\n    auto result =\n        LookupImplWitness(context, loc_id, self_const_id, facet_type_const_id);\n    // TODO: If the facet type contains 2 interfaces, and one is not `impl`ed,\n    // it would be nice to diagnose which one was not `impl`ed, but that\n    // requires LookupImplWitness to return a partial result, or take a\n    // diagnostic lambda or something.\n    if (!result.has_value()) {\n      auto facet_type_inst_id =\n          context.constant_values().GetInstId(facet_type_const_id);\n\n      if (!result.has_error_value() &&\n          facet_type_inst_id != SemIR::ErrorInst::InstId) {\n        CARBON_DIAGNOSTIC(RequireImplsNotImplemented, Error,\n                          \"interface `{0}` being implemented requires that {1} \"\n                          \"implements {2}\",\n                          SemIR::SpecificInterface, SemIR::TypeId,\n                          SemIR::FacetTypeId);\n        context.emitter().Emit(\n            loc_id, RequireImplsNotImplemented, impl.interface,\n            context.types().GetTypeIdForTypeConstantId(self_const_id),\n            context.insts()\n                .GetAs<SemIR::FacetType>(facet_type_inst_id)\n                .facet_type_id);\n      }\n    }\n    if (!result.has_value() || result.has_error_value()) {\n      FillImplWitnessWithErrors(context, impl);\n      break;\n    }\n  }\n}\n\nauto FillImplWitnessWithErrors(Context& context, SemIR::Impl& impl) -> void {\n  if (impl.witness_id == SemIR::ErrorInst::InstId) {\n    return;\n  }\n  auto witness = context.insts().GetAs<SemIR::ImplWitness>(impl.witness_id);\n  auto witness_table =\n      context.insts().GetAs<SemIR::ImplWitnessTable>(witness.witness_table_id);\n  auto witness_block =\n      context.inst_blocks().GetMutable(witness_table.elements_id);\n  for (auto& elem : witness_block) {\n    if (elem == SemIR::InstId::ImplWitnessTablePlaceholder) {\n      elem = SemIR::ErrorInst::InstId;\n    }\n  }\n  impl.witness_id = SemIR::ErrorInst::InstId;\n}\n\nauto IsImplEffectivelyFinal(Context& context, const SemIR::Impl& impl) -> bool {\n  return impl.is_final ||\n         (context.constant_values().Get(impl.self_id).is_concrete() &&\n          context.constant_values().Get(impl.constraint_id).is_concrete());\n}\n\nauto CheckConstraintIsInterface(Context& context, SemIR::InstId impl_decl_id,\n                                SemIR::InstId self_id,\n                                SemIR::TypeInstId constraint_id)\n    -> SemIR::SpecificInterface {\n  auto facet_type_as_type_id =\n      context.types().GetTypeIdForTypeInstId(constraint_id);\n  if (facet_type_as_type_id == SemIR::ErrorInst::TypeId) {\n    return SemIR::SpecificInterface::None;\n  }\n  auto facet_type =\n      context.types().TryGetAs<SemIR::FacetType>(facet_type_as_type_id);\n  if (!facet_type) {\n    CARBON_DIAGNOSTIC(ImplAsNonFacetType, Error, \"impl as non-facet type {0}\",\n                      InstIdAsType);\n    context.emitter().Emit(impl_decl_id, ImplAsNonFacetType, constraint_id);\n    return SemIR::SpecificInterface::None;\n  }\n\n  auto identified_id = RequireIdentifiedFacetType(\n      context, SemIR::LocId(constraint_id),\n      context.constant_values().Get(self_id), *facet_type, [&](auto& builder) {\n        CARBON_DIAGNOSTIC(ImplOfUnidentifiedFacetType, Context,\n                          \"facet type {0} cannot be identified in `impl as`\",\n                          InstIdAsType);\n        builder.Context(impl_decl_id, ImplOfUnidentifiedFacetType,\n                        constraint_id);\n      });\n  if (!identified_id.has_value()) {\n    return SemIR::SpecificInterface::None;\n  }\n  const auto& identified = context.identified_facet_types().Get(identified_id);\n  if (!identified.is_valid_impl_as_target()) {\n    CARBON_DIAGNOSTIC(ImplOfNotOneInterface, Error,\n                      \"impl as {0} interfaces, expected 1\", int);\n    context.emitter().Emit(impl_decl_id, ImplOfNotOneInterface,\n                           identified.num_interfaces_to_impl());\n    return SemIR::SpecificInterface::None;\n  }\n  return identified.impl_as_target_interface();\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/impl.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_IMPL_H_\n#define CARBON_TOOLCHAIN_CHECK_IMPL_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nstruct RedeclaredImpl {\n  // The previous Impl which the query Impl is redeclaring.\n  SemIR::ImplId prev_impl_id;\n};\nstruct NewImpl {\n  // The lookup bucket for the query Impl where it should be added once an\n  // ImplId is known.\n  SemIR::ImplStore::LookupBucketRef lookup_bucket;\n  // Indicates the query Impl is not a redeclaration but an error was diagnosed.\n  // The caller should avoid diagnosing more errors in the query impl.\n  bool find_had_error;\n};\n\n// Finds an existing impl if the `query_impl` is a redeclaration, and returns\n// its `ImplId`. This ensures all (valid) redeclarations share the same\n// `ImplId`. Otherwise, returns the bucket where a new `ImplId` should be added.\nauto FindImplId(Context& context, const SemIR::Impl& query_impl)\n    -> std::variant<RedeclaredImpl, NewImpl>;\n\n// Adds an impl to the ImplStore, and returns a new `ImplId`.\n//\n// If the impl is modified with `extend` then the parent's scope is extended\n// with it.\nauto AddImpl(Context& context, const SemIR::Impl& impl,\n             SemIR::ImplStore::LookupBucketRef lookup_bucket,\n             Parse::NodeId extend_node, SemIR::LocId implicit_params_loc_id)\n    -> SemIR::ImplId;\n\n// Creates and returns an impl witness instruction for an impl declaration.\n//\n// If there are no rewrites into a name of the interface being implemented, a\n// placeholder witness table is created, to be replaced in the impl definition.\n//\n// Adds and returns an `ImplWitness` instruction (created with location set to\n// `loc_id`) that shows the \"`Self` type\" (from a facet in `impl.self_id`)\n// implements an identified interface (from a facet type in\n// `impl.constraint_id`). This witness reflects the values assigned to\n// associated constant members of that interface by rewrite constraints in the\n// constraint facet type. `self_specific_id` will be the `specific_id` of the\n// resulting witness.\nauto AddImplWitnessForDeclaration(Context& context, SemIR::LocId loc_id,\n                                  const SemIR::Impl& impl,\n                                  SemIR::SpecificId self_specific_id)\n    -> SemIR::InstId;\n\n// Update `impl`'s witness at the start of a definition.\nauto ImplWitnessStartDefinition(Context& context, SemIR::Impl& impl) -> void;\n\n// Adds the function members to the witness for `impl`.\nauto FinishImplWitness(Context& context, const SemIR::Impl& impl_id) -> void;\n\n// Checks that any `require` declarations in the interface being implemented by\n// `impl` are satisfied. Otherwise, a diagnostic is issued and the `impl` is\n// made invalid.\nauto CheckRequireDeclsSatisfied(Context& context, SemIR::LocId loc_id,\n                                SemIR::Impl& impl) -> void;\n\n// Sets all unset members of the witness for `impl` to the error instruction and\n// sets the witness id in the `Impl` to an error.\nauto FillImplWitnessWithErrors(Context& context, SemIR::Impl& impl) -> void;\n\n// Returns whether the impl is either `final` explicitly, or implicitly due to\n// being concrete.\nauto IsImplEffectivelyFinal(Context& context, const SemIR::Impl& impl) -> bool;\n\n// Checks that `impl_function_id` is a valid implementation of the function\n// described in the interface as `interface_function_id`. Returns the value to\n// put into the corresponding slot in the witness table, which can be\n// `ErrorInst::InstId` if the function is not usable.\nauto CheckAssociatedFunctionImplementation(\n    Context& context, SemIR::FunctionType interface_function_type,\n    SemIR::SpecificId enclosing_specific_id, SemIR::InstId impl_decl_id,\n    bool defer_thunk_definition) -> SemIR::InstId;\n\n// Checks that the constraint specified for the impl is valid and identified.\n// Returns the interface that the impl implements. On error, issues a diagnostic\n// and returns `None`.\nauto CheckConstraintIsInterface(Context& context, SemIR::InstId impl_decl_id,\n                                SemIR::InstId self_id,\n                                SemIR::TypeInstId constraint_id)\n    -> SemIR::SpecificInterface;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_IMPL_H_\n"
  },
  {
    "path": "toolchain/check/impl_lookup.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/impl_lookup.h\"\n\n#include <algorithm>\n#include <functional>\n#include <utility>\n#include <variant>\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/cpp/impl_lookup.h\"\n#include \"toolchain/check/custom_witness.h\"\n#include \"toolchain/check/deduce.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/impl.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/subst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/check/type_structure.h\"\n#include \"toolchain/sem_ir/facet_type_info.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/impl.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Returns IRs which are allowed to define an `impl` involving the arguments.\n// This is limited by the orphan rule.\nstatic auto FindAssociatedImportIRs(\n    Context& context, SemIR::ConstantId query_self_const_id,\n    SemIR::SpecificInterface query_specific_interface)\n    -> llvm::SmallVector<SemIR::ImportIRId> {\n  llvm::SmallVector<SemIR::ImportIRId> result;\n\n  // Add an entity to our result.\n  auto add_entity = [&](const SemIR::EntityWithParamsBase& entity) {\n    // We will look for impls in the import IR associated with the first owning\n    // declaration.\n    auto decl_id = entity.first_owning_decl_id;\n    if (!decl_id.has_value()) {\n      return;\n    }\n\n    auto import_ir_inst = GetCanonicalImportIRInst(context, decl_id);\n    const auto* sem_ir = &context.sem_ir();\n    if (import_ir_inst.ir_id().has_value()) {\n      sem_ir = context.import_irs().Get(import_ir_inst.ir_id()).sem_ir;\n    }\n\n    // For an instruction imported from C++, `GetCanonicalImportIRInst` returns\n    // the final Carbon import instruction, so go one extra step to check for a\n    // C++ import.\n    if (auto import_ir_inst_id =\n            sem_ir->insts().GetImportSource(import_ir_inst.inst_id());\n        import_ir_inst_id.has_value()) {\n      result.push_back(\n          sem_ir->import_ir_insts().Get(import_ir_inst_id).ir_id());\n    } else if (import_ir_inst.ir_id().has_value()) {\n      result.push_back(import_ir_inst.ir_id());\n    }\n  };\n\n  llvm::SmallVector<SemIR::InstId> worklist;\n\n  // Push the contents of an instruction block onto our worklist.\n  auto push_block = [&](SemIR::InstBlockId block_id) {\n    if (block_id.has_value()) {\n      llvm::append_range(worklist, context.inst_blocks().Get(block_id));\n    }\n  };\n\n  // Add the arguments of a specific to the worklist.\n  auto push_args = [&](SemIR::SpecificId specific_id) {\n    if (specific_id.has_value()) {\n      push_block(context.specifics().Get(specific_id).args_id);\n    }\n  };\n\n  worklist.push_back(context.constant_values().GetInstId(query_self_const_id));\n  add_entity(context.interfaces().Get(query_specific_interface.interface_id));\n  push_args(query_specific_interface.specific_id);\n\n  while (!worklist.empty()) {\n    auto inst_id = worklist.pop_back_val();\n\n    // Visit the operands of the constant.\n    auto inst = context.insts().Get(inst_id);\n    for (auto arg : {inst.arg0_and_kind(), inst.arg1_and_kind()}) {\n      CARBON_KIND_SWITCH(arg) {\n        case CARBON_KIND(SemIR::InstId inst_id): {\n          if (inst_id.has_value()) {\n            worklist.push_back(inst_id);\n          }\n          break;\n        }\n        case CARBON_KIND(SemIR::TypeInstId inst_id): {\n          if (inst_id.has_value()) {\n            worklist.push_back(inst_id);\n          }\n          break;\n        }\n        case CARBON_KIND(SemIR::InstBlockId inst_block_id): {\n          push_block(inst_block_id);\n          break;\n        }\n        case CARBON_KIND(SemIR::ClassId class_id): {\n          add_entity(context.classes().Get(class_id));\n          break;\n        }\n        case CARBON_KIND(SemIR::InterfaceId interface_id): {\n          add_entity(context.interfaces().Get(interface_id));\n          break;\n        }\n        case CARBON_KIND(SemIR::FacetTypeId facet_type_id): {\n          const auto& facet_type_info =\n              context.facet_types().Get(facet_type_id);\n          for (const auto& impl : facet_type_info.extend_constraints) {\n            add_entity(context.interfaces().Get(impl.interface_id));\n            push_args(impl.specific_id);\n          }\n          for (const auto& impl : facet_type_info.self_impls_constraints) {\n            add_entity(context.interfaces().Get(impl.interface_id));\n            push_args(impl.specific_id);\n          }\n          break;\n        }\n        case CARBON_KIND(SemIR::FunctionId function_id): {\n          add_entity(context.functions().Get(function_id));\n          break;\n        }\n        case CARBON_KIND(SemIR::SpecificId specific_id): {\n          push_args(specific_id);\n          break;\n        }\n        default: {\n          break;\n        }\n      }\n    }\n  }\n\n  // Deduplicate.\n  llvm::sort(result, [](SemIR::ImportIRId a, SemIR::ImportIRId b) {\n    return a.index < b.index;\n  });\n  result.erase(llvm::unique(result), result.end());\n\n  return result;\n}\n\n// Returns true if a cycle was found and diagnosed.\nstatic auto FindAndDiagnoseImplLookupCycle(\n    Context& context,\n    const llvm::SmallVector<Context::ImplLookupStackEntry>& stack,\n    SemIR::LocId loc_id, SemIR::ConstantId query_self_const_id,\n    SemIR::ConstantId query_facet_type_const_id) -> bool {\n  // Deduction of the interface parameters can do further impl lookups, and we\n  // need to ensure we terminate.\n  //\n  // https://docs.carbon-lang.dev/docs/design/generics/details.html#acyclic-rule\n  // - We look for violations of the acyclic rule by seeing if a previous lookup\n  //   had all the same type inputs.\n  // - The `query_facet_type_const_id` encodes the entire facet type being\n  //   looked up, including any specific parameters for a generic interface.\n  //\n  // TODO: Implement the termination rule, which requires looking at the\n  // complexity of the types on the top of (or throughout?) the stack:\n  // https://docs.carbon-lang.dev/docs/design/generics/details.html#termination-rule\n  for (auto [i, entry] : llvm::enumerate(stack)) {\n    if (entry.query_self_const_id == query_self_const_id &&\n        entry.query_facet_type_const_id == query_facet_type_const_id) {\n      auto facet_type_type_id =\n          context.types().GetTypeIdForTypeConstantId(query_facet_type_const_id);\n      CARBON_DIAGNOSTIC(ImplLookupCycle, Error,\n                        \"cycle found in search for impl of {0} for type {1}\",\n                        SemIR::TypeId, SemIR::TypeId);\n      auto builder = context.emitter().Build(\n          loc_id, ImplLookupCycle, facet_type_type_id,\n          context.types().GetTypeIdForTypeConstantId(query_self_const_id));\n      for (const auto& active_entry : llvm::drop_begin(stack, i)) {\n        if (active_entry.impl_loc.has_value()) {\n          CARBON_DIAGNOSTIC(ImplLookupCycleNote, Note,\n                            \"determining if this impl clause matches\", );\n          builder.Note(active_entry.impl_loc, ImplLookupCycleNote);\n        }\n      }\n      builder.Emit();\n      return true;\n    }\n  }\n  return false;\n}\n\nstruct RequiredImplsFromConstraint {\n  llvm::ArrayRef<SemIR::IdentifiedFacetType::RequiredImpl> req_impls;\n  bool other_requirements;\n};\n\n// Gets the set of `SpecificInterface`s that are required by a facet type\n// (as a constant value), and any special requirements.\nstatic auto GetRequiredImplsFromConstraint(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::ConstantId query_self_const_id,\n    SemIR::ConstantId query_facet_type_const_id)\n    -> std::optional<RequiredImplsFromConstraint> {\n  auto facet_type_inst_id =\n      context.constant_values().GetInstId(query_facet_type_const_id);\n  auto facet_type_inst =\n      context.insts().GetAs<SemIR::FacetType>(facet_type_inst_id);\n  const auto& facet_type_info =\n      context.facet_types().Get(facet_type_inst.facet_type_id);\n\n  auto identified_id = RequireIdentifiedFacetType(\n      context, loc_id, query_self_const_id, facet_type_inst,\n      [&](auto& builder) {\n        CARBON_DIAGNOSTIC(ImplLookupInUnidentifiedFacetType, Context,\n                          \"facet type {0} can not be identified\", InstIdAsType);\n        builder.Context(loc_id, ImplLookupInUnidentifiedFacetType,\n                        facet_type_inst_id);\n      });\n  if (!identified_id.has_value()) {\n    return std::nullopt;\n  }\n  return {\n      {.req_impls =\n           context.identified_facet_types().Get(identified_id).required_impls(),\n       .other_requirements = facet_type_info.other_requirements}};\n}\n\nstatic auto GetWitnessIdForImpl(Context& context, SemIR::LocId loc_id,\n                                bool query_is_concrete,\n                                SemIR::ConstantId query_self_const_id,\n                                const SemIR::SpecificInterface& interface,\n                                const SemIR::Impl& impl)\n    -> EvalImplLookupResult {\n  // The impl may have generic arguments, in which case we need to deduce them\n  // to find what they are given the specific type and interface query. We use\n  // that specific to map values in the impl to the deduced values.\n  auto specific_id = SemIR::SpecificId::None;\n  if (impl.generic_id.has_value()) {\n    specific_id = DeduceImplArguments(\n        context, loc_id, impl, query_self_const_id, interface.specific_id);\n    if (!specific_id.has_value()) {\n      return EvalImplLookupResult::MakeNone();\n    }\n  }\n\n  // The self type of the impl must match the type in the query, or this is an\n  // `impl T as ...` for some other type `T` and should not be considered.\n  auto noncanonical_deduced_self_const_id = SemIR::GetConstantValueInSpecific(\n      context.sem_ir(), specific_id, impl.self_id);\n\n  // In a generic `impl forall` the self type can be a FacetAccessType, which\n  // will not be the same constant value as a query facet value. We move through\n  // to the facet value here, and if the query was a FacetAccessType we did the\n  // same there so they still match.\n  auto deduced_self_const_id =\n      GetCanonicalFacetOrTypeValue(context, noncanonical_deduced_self_const_id);\n  if (query_self_const_id != deduced_self_const_id) {\n    return EvalImplLookupResult::MakeNone();\n  }\n\n  // The impl's constraint is a facet type which it is implementing for the self\n  // type: the `I` in `impl ... as I`. The deduction step may be unable to be\n  // fully applied to the types in the constraint and result in an error here,\n  // in which case it does not match the query.\n  auto deduced_constraint_id =\n      context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(\n          context.sem_ir(), specific_id, impl.constraint_id));\n  if (deduced_constraint_id == SemIR::ErrorInst::InstId) {\n    return EvalImplLookupResult::MakeNone();\n  }\n\n  auto deduced_constraint_facet_type_id =\n      context.insts()\n          .GetAs<SemIR::FacetType>(deduced_constraint_id)\n          .facet_type_id;\n  const auto& deduced_constraint_facet_type_info =\n      context.facet_types().Get(deduced_constraint_facet_type_id);\n  CARBON_CHECK(deduced_constraint_facet_type_info.extend_constraints.size() ==\n               1);\n\n  if (deduced_constraint_facet_type_info.other_requirements) {\n    return EvalImplLookupResult::MakeNone();\n  }\n\n  // The specifics in the queried interface must match the deduced specifics in\n  // the impl's constraint facet type.\n  auto impl_interface_specific_id =\n      deduced_constraint_facet_type_info.extend_constraints[0].specific_id;\n  auto query_interface_specific_id = interface.specific_id;\n  if (impl_interface_specific_id != query_interface_specific_id) {\n    return EvalImplLookupResult::MakeNone();\n  }\n\n  LoadImportRef(context, impl.witness_id);\n  if (specific_id.has_value()) {\n    // If the impl definition can be resolved, eval will do it immediately;\n    // otherwise, it can be resolved by further specialization. This is used to\n    // resolve dependency chains when `MakeFinal` is returned without a concrete\n    // definition; particularly final impls with symbolic constants.\n    AddInstInNoBlock(\n        context, loc_id,\n        SemIR::RequireSpecificDefinition{\n            .type_id = GetSingletonType(\n                context, SemIR::RequireSpecificDefinitionType::TypeInstId),\n            .specific_id = specific_id});\n  }\n\n  if (query_is_concrete || impl.is_final) {\n    // TODO: These final results should be cached somehow. Positive (non-None)\n    // results could be cached globally, as they can not change. But\n    // negative results can change after a final impl is written, so\n    // they can only be cached in a limited way, or the cache needs to\n    // be invalidated by writing a final impl that would match.\n    return EvalImplLookupResult::MakeFinal(\n        context.constant_values().GetInstId(SemIR::GetConstantValueInSpecific(\n            context.sem_ir(), specific_id, impl.witness_id)));\n  } else {\n    return EvalImplLookupResult::MakeNonFinal();\n  }\n}\n\n// Finds a lookup result from `query_self_inst_id` if it is a facet value that\n// names the query interface in its facet type. Note that `query_self_inst_id`\n// is allowed to be a non-canonical facet value in order to find a concrete\n// witness, so it's not referenced as a constant value.\nstatic auto LookupImplWitnessInSelfFacetValue(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::InstId self_facet_value_inst_id,\n    SemIR::SpecificInterface query_specific_interface) -> EvalImplLookupResult {\n  auto facet_type = context.types().TryGetAs<SemIR::FacetType>(\n      context.insts().Get(self_facet_value_inst_id).type_id());\n  if (!facet_type) {\n    return EvalImplLookupResult::MakeNone();\n  }\n\n  auto self_facet_value_const_id =\n      context.constant_values().Get(self_facet_value_inst_id);\n\n  // The position of the interface in `required_impls()` is also the\n  // position of the witness for that interface in `FacetValue`. The\n  // `FacetValue` witnesses are the output of an impl lookup, which finds and\n  // returns witnesses in the same order.\n  auto identified_id = RequireIdentifiedFacetType(\n      context, loc_id, self_facet_value_const_id, *facet_type,\n      [&](auto& builder) {\n        CARBON_DIAGNOSTIC(ImplLookupInUnidentifiedFacetTypeOfQuerySelf, Context,\n                          \"facet type of value {0} can not be identified\",\n                          InstIdAsType);\n        builder.Context(loc_id, ImplLookupInUnidentifiedFacetTypeOfQuerySelf,\n                        self_facet_value_inst_id);\n      });\n  if (!identified_id.has_value()) {\n    return EvalImplLookupResult::MakeNone();\n  }\n  auto facet_type_req_impls = llvm::enumerate(\n      context.identified_facet_types().Get(identified_id).required_impls());\n  auto it = llvm::find_if(facet_type_req_impls, [&](auto e) {\n    auto [req_self, req_specific_interface] = e.value();\n    // The `self_facet_value_inst_id` in eval is a canonicalized facet value, as\n    // is the self in the identified facet type.\n    return req_self == self_facet_value_const_id &&\n           req_specific_interface == query_specific_interface;\n  });\n  if (it == facet_type_req_impls.end()) {\n    return EvalImplLookupResult::MakeNone();\n  }\n  auto index = (*it).index();\n\n  if (auto facet_value = context.insts().TryGetAs<SemIR::FacetValue>(\n          self_facet_value_inst_id)) {\n    auto witness_id =\n        context.inst_blocks().Get(facet_value->witnesses_block_id)[index];\n    if (context.insts().Is<SemIR::ImplWitness>(witness_id)) {\n      return EvalImplLookupResult::MakeFinal(witness_id);\n    }\n  }\n  return EvalImplLookupResult::MakeNonFinal();\n}\n\n// Substitutes witnesess in place of `LookupImplWitness` queries into `.Self`,\n// when the witness is for the same interface as the one `.Self` is referring\n// to.\n//\n// This allows access to the `FacetType` and its constraints from the witness,\n// and allows `ImplWitnessAccess` instructions to be immediately resolved to a\n// more specific value when possible.\nclass SubstWitnessesCallbacks : public SubstInstCallbacks {\n public:\n  // `context` must not be null.\n  explicit SubstWitnessesCallbacks(\n      Context* context, SemIR::LocId loc_id,\n      SemIR::ConstantId query_self_const_id,\n      llvm::ArrayRef<SemIR::IdentifiedFacetType::RequiredImpl> req_impls,\n      llvm::ArrayRef<SemIR::InstId> witness_inst_ids)\n      : SubstInstCallbacks(context),\n        loc_id_(loc_id),\n        canonical_query_self_const_id_(\n            GetCanonicalFacetOrTypeValue(*context, query_self_const_id)),\n        req_impls_(req_impls),\n        witness_inst_ids_(witness_inst_ids) {}\n\n  auto Subst(SemIR::InstId& inst_id) -> SubstResult override {\n    // `FacetType` can be concrete even when it has rewrite constraints that\n    // have a symbolic dependency on `.Self`. See use of\n    // `GetConstantValueIgnoringPeriodSelf` in eval. So in order to recurse into\n    // `FacetType` we must check for it before the `is_concrete` early return.\n    if (context().insts().Is<SemIR::FacetType>(inst_id)) {\n      ++facet_type_depth_;\n      return SubstOperands;\n    }\n\n    if (context().constant_values().Get(inst_id).is_concrete()) {\n      return FullySubstituted;\n    }\n\n    auto access = context().insts().TryGetAs<SemIR::ImplWitnessAccess>(inst_id);\n    if (!access) {\n      return SubstOperands;\n    }\n\n    auto lookup =\n        context().insts().GetAs<SemIR::LookupImplWitness>(access->witness_id);\n    auto bind_name = context().insts().TryGetAs<SemIR::SymbolicBinding>(\n        lookup.query_self_inst_id);\n    if (!bind_name) {\n      return SubstOperands;\n    }\n\n    const auto& self_entity_name =\n        context().entity_names().Get(bind_name->entity_name_id);\n    if (self_entity_name.name_id != SemIR::NameId::PeriodSelf) {\n      return SubstOperands;\n    }\n\n    // TODO: Once we are numbering `EntityName`, (see the third model in\n    // https://docs.google.com/document/d/1Yt-i5AmF76LSvD4TrWRIAE_92kii6j5yFiW-S7ahzlg/edit?tab=t.0#heading=h.7urbxcq23olv)\n    // then verify that the index here is equal to the `facet_type_depth_`,\n    // which would mean that it is a reference to the top-level `Self`, which is\n    // being replaced with the impl lookup query self facet value (and then we\n    // use the witness derived from it).\n    //\n    // For now, we only substitute if depth == 0, which is incorrect inside\n    // nested facet types, as it can miss references in specifics up to the top\n    // level facet value.\n    if (facet_type_depth_ > 0) {\n      return SubstOperands;\n    }\n\n    auto witness_id =\n        FindWitnessForInterface(lookup.query_specific_interface_id);\n    if (!witness_id.has_value()) {\n      return SubstOperands;\n    }\n\n    inst_id = RebuildNewInst(\n        context().insts().GetLocIdForDesugaring(loc_id_),\n        SemIR::ImplWitnessAccess{.type_id = GetSingletonType(\n                                     context(), SemIR::WitnessType::TypeInstId),\n                                 .witness_id = witness_id,\n                                 .index = access->index});\n    // Once we replace a witness, we either have a concrete value or some\n    // reference to an associated constant that came from the witness's facet\n    // type. We don't want to substitute into the witness's facet type, so we\n    // don't recurse on whatever came from the witness.\n    return FullySubstituted;\n  }\n\n  auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst)\n      -> SemIR::InstId override {\n    if (context().insts().Is<SemIR::FacetType>(orig_inst_id)) {\n      --facet_type_depth_;\n    }\n    return RebuildNewInst(loc_id_, new_inst);\n  }\n\n  auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId override {\n    if (context().insts().Is<SemIR::FacetType>(orig_inst_id)) {\n      --facet_type_depth_;\n    }\n    return orig_inst_id;\n  }\n\n private:\n  auto FindWitnessForInterface(SemIR::SpecificInterfaceId specific_interface_id)\n      -> SemIR::InstId {\n    auto lookup_query_interface =\n        context().specific_interfaces().Get(specific_interface_id);\n    for (auto [req_impl, witness_inst_id] :\n         llvm::zip_equal(req_impls_, witness_inst_ids_)) {\n      auto [req_self, req_interface] = req_impl;\n      // The `LookupImplWitness` is for `.Self`, so if the witness is for some\n      // type other than the query self, we can't use it for `.Self`.\n      if (req_self != canonical_query_self_const_id_) {\n        continue;\n      }\n      // If the `LookupImplWitness` for `.Self` is not looking for the same\n      // interface as we have a witness for, this is not the right witness to\n      // use to replace the lookup for `.Self`.\n      if (req_interface.interface_id != lookup_query_interface.interface_id) {\n        continue;\n      }\n      return witness_inst_id;\n    }\n    return SemIR::InstId::None;\n  }\n\n  SemIR::LocId loc_id_;\n  SemIR::ConstantId canonical_query_self_const_id_;\n  llvm::ArrayRef<SemIR::IdentifiedFacetType::RequiredImpl> req_impls_;\n  llvm::ArrayRef<SemIR::InstId> witness_inst_ids_;\n  int facet_type_depth_ = 0;\n};\n\nstatic auto VerifyQueryFacetTypeConstraints(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::ConstantId query_self_const_id,\n    SemIR::ConstantId query_facet_type_const_id,\n    llvm::ArrayRef<SemIR::IdentifiedFacetType::RequiredImpl> req_impls,\n    llvm::ArrayRef<SemIR::InstId> witness_inst_ids) -> bool {\n  SemIR::InstId query_facet_type_inst_id =\n      context.constant_values().GetInstId(query_facet_type_const_id);\n\n  CARBON_CHECK(context.insts().Is<SemIR::FacetType>(query_facet_type_inst_id));\n\n  const auto& facet_type_info = context.facet_types().Get(\n      context.insts()\n          .GetAs<SemIR::FacetType>(query_facet_type_inst_id)\n          .facet_type_id);\n\n  if (!facet_type_info.rewrite_constraints.empty()) {\n    auto callbacks = SubstWitnessesCallbacks(\n        &context, loc_id, query_self_const_id, req_impls, witness_inst_ids);\n\n    for (const auto& rewrite : facet_type_info.rewrite_constraints) {\n      auto lhs_id = SubstInst(context, rewrite.lhs_id, callbacks);\n      auto rhs_id = SubstInst(context, rewrite.rhs_id, callbacks);\n      if (lhs_id != rhs_id) {\n        // TODO: Provide a diagnostic note and location for which rewrite\n        // constraint was not satisfied, if a diagnostic is going to be\n        // displayed for the LookupImplWitessFailure. This will require plumbing\n        // through a callback that lets us add a Note to another diagnostic.\n        return false;\n      }\n    }\n  }\n\n  // TODO: Validate that the witnesses satisfy the other requirements in the\n  // `facet_type_info`.\n\n  return true;\n}\n\n// Begin a search for an impl declaration matching the query. We do this by\n// creating an LookupImplWitness instruction and evaluating. If it's able to\n// find a final concrete impl, then it will evaluate to that `ImplWitness` but\n// if not, it will evaluate to itself as a symbolic witness to be further\n// evaluated with a more specific query when building a specific for the generic\n// context the query came from.\nstatic auto GetOrAddLookupImplWitness(Context& context, SemIR::LocId loc_id,\n                                      SemIR::ConstantId query_self_const_id,\n                                      SemIR::SpecificInterface interface)\n    -> SemIR::InstId {\n  auto witness_const_id = EvalOrAddInst(\n      context, context.insts().GetLocIdForDesugaring(loc_id),\n      SemIR::LookupImplWitness{\n          .type_id = GetSingletonType(context, SemIR::WitnessType::TypeInstId),\n          .query_self_inst_id =\n              context.constant_values().GetInstId(query_self_const_id),\n          .query_specific_interface_id =\n              context.specific_interfaces().Add(interface),\n      });\n  // We use a NotConstant result from eval to communicate back an impl\n  // lookup failure. See `EvalConstantInst()` for `LookupImplWitness`.\n  if (!witness_const_id.is_constant()) {\n    return SemIR::InstId::None;\n  }\n  return context.constant_values().GetInstId(witness_const_id);\n}\n\nauto LookupImplWitness(Context& context, SemIR::LocId loc_id,\n                       SemIR::ConstantId query_self_const_id,\n                       SemIR::ConstantId query_facet_type_const_id)\n    -> SemIR::InstBlockIdOrError {\n  if (query_self_const_id == SemIR::ErrorInst::ConstantId ||\n      query_facet_type_const_id == SemIR::ErrorInst::ConstantId) {\n    return SemIR::InstBlockIdOrError::MakeError();\n  }\n\n  {\n    // The query self value is a type value or a facet value.\n    auto query_self_type_id =\n        context.insts()\n            .Get(context.constant_values().GetInstId(query_self_const_id))\n            .type_id();\n    CARBON_CHECK((context.types().IsOneOf<SemIR::TypeType, SemIR::FacetType>(\n        query_self_type_id)));\n    // The query facet type value is indeed a facet type.\n    CARBON_CHECK(context.insts().Is<SemIR::FacetType>(\n        context.constant_values().GetInstId(query_facet_type_const_id)));\n  }\n\n  auto req_impls_from_constraint = GetRequiredImplsFromConstraint(\n      context, loc_id, query_self_const_id, query_facet_type_const_id);\n  if (!req_impls_from_constraint) {\n    return SemIR::InstBlockIdOrError::MakeError();\n  }\n  auto [req_impls, other_requirements] = *req_impls_from_constraint;\n  if (other_requirements) {\n    // TODO: Remove this when other requirements go away.\n    return SemIR::InstBlockId::None;\n  }\n  if (req_impls.empty()) {\n    return SemIR::InstBlockId::Empty;\n  }\n\n  if (FindAndDiagnoseImplLookupCycle(context, context.impl_lookup_stack(),\n                                     loc_id, query_self_const_id,\n                                     query_facet_type_const_id)) {\n    return SemIR::InstBlockIdOrError::MakeError();\n  }\n\n  auto& stack = context.impl_lookup_stack();\n  stack.push_back({\n      .query_self_const_id = query_self_const_id,\n      .query_facet_type_const_id = query_facet_type_const_id,\n  });\n  // We need to find a witness for each self+interface pair in `req_impls`.\n  //\n  // Every consumer of a facet type needs to agree on the order of interfaces\n  // used for its witnesses, which is done by following the order in the\n  // IdentifiedFacetType.\n  llvm::SmallVector<SemIR::InstId> result_witness_ids;\n  for (const auto& req_impl : req_impls) {\n    // TODO: Since both `interfaces` and `query_self_const_id` are sorted lists,\n    // do an O(N+M) merge instead of O(N*M) nested loops.\n    auto result_witness_id =\n        GetOrAddLookupImplWitness(context, loc_id, req_impl.self_facet_value,\n                                  req_impl.specific_interface);\n    if (result_witness_id.has_value()) {\n      result_witness_ids.push_back(result_witness_id);\n    } else {\n      // At least one queried interface in the facet type has no witness for the\n      // given type, we can stop looking for more.\n      break;\n    }\n  }\n  stack.pop_back();\n\n  // All interfaces in the query facet type must have been found to be available\n  // through some impl, or directly on the value's facet type if\n  // `query_self_const_id` is a facet value.\n  if (result_witness_ids.size() != req_impls.size()) {\n    return SemIR::InstBlockId::None;\n  }\n\n  // Verify rewrite constraints in the query constraint are satisfied after\n  // applying the rewrites from the found witnesses.\n  if (!VerifyQueryFacetTypeConstraints(context, loc_id, query_self_const_id,\n                                       query_facet_type_const_id, req_impls,\n                                       result_witness_ids)) {\n    return SemIR::InstBlockId::None;\n  }\n\n  return context.inst_blocks().AddCanonical(result_witness_ids);\n}\n\n// Returns whether the query is concrete, it is false if the self type or\n// interface specifics have a symbolic dependency.\nstatic auto QueryIsConcrete(Context& context, SemIR::ConstantId self_const_id,\n                            const SemIR::SpecificInterface& specific_interface)\n    -> bool {\n  if (!self_const_id.is_concrete()) {\n    return false;\n  }\n  if (!specific_interface.specific_id.has_value()) {\n    return true;\n  }\n  auto args_id =\n      context.specifics().Get(specific_interface.specific_id).args_id;\n  for (auto inst_id : context.inst_blocks().Get(args_id)) {\n    if (!context.constant_values().Get(inst_id).is_concrete()) {\n      return false;\n    }\n  }\n  return true;\n}\n\nnamespace {\n// A class to filter imported impls based on whether they could possibly match a\n// query, prior to importing them. For now we only consider impls that are for\n// an interface that's being queried.\n//\n// TODO: There's a lot more we could do to filter out impls that can't possibly\n// match.\nclass ImportImplFilter {\n public:\n  explicit ImportImplFilter(Context& context, SemIR::ImportIRId import_ir_id,\n                            SemIR::SpecificInterface interface)\n      : context_(&context),\n        interface_id_(interface.interface_id),\n        import_ir_id_(import_ir_id),\n        import_ir_(context_->import_irs().Get(import_ir_id).sem_ir),\n        cached_import_interface_id_(SemIR::InterfaceId::None) {}\n\n  // Returns whether the given impl is potentially relevant for the current\n  // query.\n  auto IsRelevantImpl(SemIR::ImplId import_impl_id) -> bool {\n    auto impl_interface_id =\n        import_ir_->impls().Get(import_impl_id).interface.interface_id;\n    if (!impl_interface_id.has_value()) {\n      // This indicates that an error occurred when type-checking the impl.\n      // TODO: Use an explicit error value for this rather than None.\n      return false;\n    }\n    return IsRelevantInterface(impl_interface_id);\n  }\n\n private:\n  // Returns whether an impl for the given interface might be relevant to the\n  // current query.\n  auto IsRelevantInterface(SemIR::InterfaceId import_interface_id) -> bool {\n    if (!cached_import_interface_id_.has_value()) {\n      if (IsSameInterface(import_interface_id, interface_id_)) {\n        cached_import_interface_id_ = import_interface_id;\n        return true;\n      }\n    } else if (cached_import_interface_id_ == import_interface_id) {\n      return true;\n    }\n    return false;\n  }\n\n  // Returns whether the given interfaces from two different IRs are the same.\n  auto IsSameInterface(SemIR::InterfaceId import_interface_id,\n                       SemIR::InterfaceId local_interface_id) -> bool {\n    // The names must be the same.\n    if (import_ir_->names().GetAsStringIfIdentifier(\n            import_ir_->interfaces().Get(import_interface_id).name_id) !=\n        context_->names().GetAsStringIfIdentifier(\n            context_->interfaces().Get(local_interface_id).name_id)) {\n      return false;\n    }\n    // Compare the interfaces themselves.\n    // TODO: Should we check the scope of the interface before doing this?\n    auto local_version_of_import_interface_id =\n        ImportInterface(*context_, import_ir_id_, import_interface_id);\n    return local_version_of_import_interface_id == local_interface_id;\n  }\n\n  Context* context_;\n  // The interface being looked up.\n  SemIR::InterfaceId interface_id_;\n  // The IR that we are currently importing impls from.\n  SemIR::ImportIRId import_ir_id_;\n  const SemIR::File* import_ir_;\n  // The interface ID of `interface_id_` in `import_ir_`, if known.\n  SemIR::InterfaceId cached_import_interface_id_;\n};\n}  // namespace\n\nstruct CandidateImpl {\n  const SemIR::Impl* impl;\n\n  // Used for sorting the candidates to find the most-specialized match.\n  TypeStructure type_structure;\n};\n\nstruct CandidateImpls {\n  llvm::SmallVector<CandidateImpl> impls;\n  bool consider_cpp_candidates = false;\n};\n\n// Returns the list of candidates impls for lookup to select from.\nstatic auto CollectCandidateImplsForQuery(\n    Context& context, bool final_only, SemIR::ConstantId query_self_const_id,\n    const TypeStructure& query_type_structure,\n    SemIR::SpecificInterface& query_specific_interface) -> CandidateImpls {\n  CandidateImpls candidates;\n\n  auto import_irs = FindAssociatedImportIRs(context, query_self_const_id,\n                                            query_specific_interface);\n\n  for (auto import_ir_id : import_irs) {\n    // If `Cpp` is an associated package, then we'll instead look for C++\n    // operator overloads for certain well-known interfaces.\n    if (import_ir_id == SemIR::ImportIRId::Cpp) {\n      candidates.consider_cpp_candidates = true;\n      continue;\n    }\n\n    // Instead of importing all impls, only import ones that are in some way\n    // connected to this query.\n    ImportImplFilter filter(context, import_ir_id, query_specific_interface);\n    for (auto [import_impl_id, _] :\n         context.import_irs().Get(import_ir_id).sem_ir->impls().enumerate()) {\n      if (filter.IsRelevantImpl(import_impl_id)) {\n        // TODO: Track the relevant impls and only consider those ones and any\n        // local impls, rather than looping over all impls below.\n        ImportImpl(context, import_ir_id, import_impl_id);\n      }\n    }\n  }\n\n  for (auto [id, impl] : context.impls().enumerate()) {\n    CARBON_CHECK(impl.witness_id.has_value());\n\n    if (final_only && !IsImplEffectivelyFinal(context, impl)) {\n      continue;\n    }\n\n    // If the impl's interface_id differs from the query, then this impl can\n    // not possibly provide the queried interface.\n    if (impl.interface.interface_id != query_specific_interface.interface_id) {\n      continue;\n    }\n\n    // When the impl's interface_id matches, but the interface is generic, the\n    // impl may or may not match based on restrictions in the generic\n    // parameters of the impl.\n    //\n    // As a shortcut, if the impl's constraint is not symbolic (does not\n    // depend on any generic parameters), then we can determine whether we match\n    // by looking if the specific ids match exactly.\n    auto impl_interface_const_id =\n        context.constant_values().Get(impl.constraint_id);\n    if (!impl_interface_const_id.is_symbolic() &&\n        impl.interface.specific_id != query_specific_interface.specific_id) {\n      continue;\n    }\n\n    // Build the type structure used for choosing the best the candidate.\n    auto type_structure =\n        BuildTypeStructure(context, impl.self_id, impl.interface);\n    if (!type_structure) {\n      continue;\n    }\n    // TODO: We can skip the comparison here if the `impl_interface_const_id` is\n    // not symbolic, since when the interface and specific ids match, and they\n    // aren't symbolic, the structure will be identical.\n    if (!query_type_structure.CompareStructure(\n            TypeStructure::CompareTest::IsEqualToOrMoreSpecificThan,\n            *type_structure)) {\n      continue;\n    }\n\n    candidates.impls.push_back({&impl, std::move(*type_structure)});\n  }\n\n  auto compare = [](auto& lhs, auto& rhs) -> bool {\n    return lhs.type_structure < rhs.type_structure;\n  };\n  // Stable sort is used so that impls that are seen first are preferred when\n  // they have an equal priority ordering.\n  // TODO: Allow Carbon code to provide a priority ordering explicitly. For\n  // now they have all the same priority, so the priority is the order in\n  // which they are found in code.\n  llvm::stable_sort(candidates.impls, compare);\n\n  return candidates;\n}\n\n// Record the query which found a final impl witness. It's illegal to\n// write a final impl afterward that would match the same query.\nstatic auto PoisonImplLookupQuery(Context& context, SemIR::LocId loc_id,\n                                  EvalImplLookupMode mode,\n                                  SemIR::LookupImplWitness eval_query,\n                                  const EvalImplLookupResult& result,\n                                  const SemIR::Impl& impl) -> void {\n  if (mode == EvalImplLookupMode::RecheckPoisonedLookup) {\n    return;\n  }\n  if (!result.has_final_value()) {\n    return;\n  }\n  // If the impl was effectively final, then we don't need to poison here. A\n  // change of query result will already be diagnosed at the point where the\n  // new impl decl was written that changes the result.\n  if (IsImplEffectivelyFinal(context, impl)) {\n    return;\n  }\n  context.poisoned_concrete_impl_lookup_queries().push_back(\n      {.loc_id = loc_id,\n       .query = eval_query,\n       .impl_witness = result.final_witness()});\n}\n\nauto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,\n                                 SemIR::LookupImplWitness eval_query,\n                                 SemIR::InstId self_facet_value_inst_id,\n                                 EvalImplLookupMode mode)\n    -> EvalImplLookupResult {\n  auto query_specific_interface =\n      context.specific_interfaces().Get(eval_query.query_specific_interface_id);\n\n  // Ensure specifics don't substitute in weird things for the query self.\n  CARBON_CHECK(context.types().IsFacetType(\n      context.insts().Get(eval_query.query_self_inst_id).type_id()));\n  SemIR::ConstantId query_self_const_id =\n      context.constant_values().Get(eval_query.query_self_inst_id);\n\n  auto facet_lookup_result = LookupImplWitnessInSelfFacetValue(\n      context, loc_id, self_facet_value_inst_id, query_specific_interface);\n  if (facet_lookup_result.has_final_value()) {\n    return facet_lookup_result;\n  }\n\n  // If the self type is a facet that provides a witness, then we are in an\n  // `interface` or an `impl`. In both cases, we don't want to do any impl\n  // lookups. The query will eventually resolve to a concrete witness when it\n  // can get it from the self facet value, when it has a specific applied in the\n  // future.\n  //\n  // In particular, this avoids a LookupImplWitness instruction in the eval\n  // block of an impl declaration from doing impl lookup. Specifically the\n  // lookup of the implicit .Self in `impl ... where .X`. If it does impl lookup\n  // when the eval block is run, it finds the same `impl`, tries to build a\n  // specific from it, which runs the eval block, creating a recursive loop that\n  // crashes.\n  if (facet_lookup_result.has_value()) {\n    if (auto bind = context.insts().TryGetAs<SemIR::SymbolicBinding>(\n            eval_query.query_self_inst_id)) {\n      const auto& entity = context.entity_names().Get(bind->entity_name_id);\n      if (entity.name_id == SemIR::NameId::PeriodSelf ||\n          entity.name_id == SemIR::NameId::SelfType) {\n        return facet_lookup_result;\n      }\n    }\n  }\n\n  auto query_type_structure = BuildTypeStructure(\n      context, context.constant_values().GetInstId(query_self_const_id),\n      query_specific_interface);\n  if (!query_type_structure) {\n    return EvalImplLookupResult::MakeNone();\n  }\n\n  // Check to see if this result is in the cache. But skip the cache if we're\n  // re-checking a poisoned result and need to redo the lookup.\n  auto impl_lookup_cache_key = Context::ImplLookupCacheKey{\n      query_self_const_id, eval_query.query_specific_interface_id};\n  if (mode != EvalImplLookupMode::RecheckPoisonedLookup) {\n    if (auto result =\n            context.impl_lookup_cache().Lookup(impl_lookup_cache_key)) {\n      return EvalImplLookupResult::MakeFinal(result.value());\n    }\n  }\n\n  // If the self value is a (symbolic) facet value that has a symbolic witness,\n  // then we don't need to do impl lookup, except that we want to find any final\n  // impls to return a concrete witness if possible. So we limit the query to\n  // final impls only in that case. Note as in the CHECK above, the query can\n  // not be concrete in this case, so only final impls can produce a concrete\n  // witness for this query.\n  auto candidates = CollectCandidateImplsForQuery(\n      context, facet_lookup_result.has_value(), query_self_const_id,\n      *query_type_structure, query_specific_interface);\n\n  bool query_is_concrete =\n      QueryIsConcrete(context, query_self_const_id, query_specific_interface);\n  CARBON_CHECK(!query_is_concrete || !facet_lookup_result.has_value(),\n               \"Non-concrete facet lookup value for concrete query\");\n\n  // Perform a lookup for an `impl` that matches the query. If we don't find a\n  // final impl, the self value may still have been a facet that provides a\n  // symbolic witness in the `facet_lookup_result`, which we want to fall back\n  // to. It records that an `impl` will exist for the query, but is yet unknown.\n\n  struct LookupResult {\n    EvalImplLookupResult result;\n    const TypeStructure* impl_type_structure = nullptr;\n    SemIR::LocId impl_loc_id = SemIR::LocId::None;\n  };\n\n  LookupResult lookup_result = {.result = facet_lookup_result};\n\n  auto core_interface =\n      GetCoreInterface(context, query_specific_interface.interface_id);\n\n  // Consider a custom witness for core interfaces.\n  // TODO: This needs to expand to more interfaces, and we might want to have\n  // that dispatch in custom_witness.cpp instead of here.\n  bool used_custom_witness = false;\n  if (auto witness_id = LookupCustomWitness(\n          context, loc_id, core_interface, query_self_const_id,\n          eval_query.query_specific_interface_id)) {\n    if (witness_id->has_value()) {\n      lookup_result = {.result = EvalImplLookupResult::MakeFinal(*witness_id)};\n    } else {\n      lookup_result = {.result = EvalImplLookupResult::MakeNonFinal()};\n    }\n    used_custom_witness = true;\n  }\n\n  // Only consider candidates when a custom witness didn't apply.\n  if (!used_custom_witness) {\n    for (const auto& candidate : candidates.impls) {\n      const auto& impl = *candidate.impl;\n\n      // In deferred lookup for a symbolic impl witness, while building a\n      // specific, there may be no stack yet as this may be the first lookup. If\n      // further lookups are started as a result in deduce, they will build the\n      // stack.\n      if (!context.impl_lookup_stack().empty()) {\n        context.impl_lookup_stack().back().impl_loc = impl.definition_id;\n      }\n\n      auto result = GetWitnessIdForImpl(context, loc_id, query_is_concrete,\n                                        query_self_const_id,\n                                        query_specific_interface, impl);\n      if (result.has_value()) {\n        PoisonImplLookupQuery(context, loc_id, mode, eval_query, result, impl);\n        lookup_result = {.result = result,\n                         .impl_type_structure = &candidate.type_structure,\n                         .impl_loc_id = SemIR::LocId(impl.definition_id)};\n        break;\n      }\n    }\n  }\n\n  if (query_is_concrete && candidates.consider_cpp_candidates &&\n      core_interface != CoreInterface::Unknown) {\n    // Also check for a C++ candidate that is a better match than whatever\n    // `impl` we may have found in Carbon.\n    auto cpp_witness_id = LookupCppImpl(\n        context, loc_id, core_interface, query_self_const_id,\n        eval_query.query_specific_interface_id,\n        lookup_result.impl_type_structure, lookup_result.impl_loc_id);\n    if (cpp_witness_id.has_value()) {\n      lookup_result = {.result =\n                           EvalImplLookupResult::MakeFinal(cpp_witness_id)};\n    }\n  }\n\n  if (mode != EvalImplLookupMode::RecheckPoisonedLookup &&\n      lookup_result.result.has_final_value()) {\n    context.impl_lookup_cache().Insert(impl_lookup_cache_key,\n                                       lookup_result.result.final_witness());\n  }\n  return lookup_result.result;\n}\n\nauto LookupMatchesImpl(Context& context, SemIR::LocId loc_id,\n                       SemIR::ConstantId query_self_const_id,\n                       SemIR::SpecificInterface query_specific_interface,\n                       SemIR::ImplId target_impl) -> bool {\n  if (query_self_const_id == SemIR::ErrorInst::ConstantId) {\n    return false;\n  }\n  auto result = GetWitnessIdForImpl(\n      context, loc_id, /*query_is_concrete=*/false, query_self_const_id,\n      query_specific_interface, context.impls().Get(target_impl));\n  return result.has_value();\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/impl_lookup.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_IMPL_LOOKUP_H_\n#define CARBON_TOOLCHAIN_CHECK_IMPL_LOOKUP_H_\n\n#include <variant>\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Looks up the witnesses to use for a type value or facet value, and a facet\n// type naming a set of interfaces required to be implemented for that type, as\n// well as possible constraints on those interfaces.\n//\n// N.B. In the future, `TypeType` will become a facet type, at which point type\n// values will also be facet values.\n//\n// The return value is one of:\n// - An InstBlockId value, containing an `ImplWitness` instruction for each\n//   required interface in the `query_facet_type_const_id`. This verifies the\n//   facet type is satisfied for the type in `type_const_id`, and provides a\n//   witness for accessing the impl of each interface.\n//\n// - `InstBlockId::None`, indicating lookup failed for at least one required\n//   interface in the `query_facet_type_const_id`. The facet type is not\n//   satisfied for the type in `type_const_id`. This represents lookup failure,\n//   but is not an error, so no diagnostic is emitted.\n//\n// - An error value, indicating the program is invalid and a diagonstic has been\n//   produced, either in this function or before.\nauto LookupImplWitness(Context& context, SemIR::LocId loc_id,\n                       SemIR::ConstantId query_self_const_id,\n                       SemIR::ConstantId query_facet_type_const_id)\n    -> SemIR::InstBlockIdOrError;\n\n// Returns whether the query matches against the given impl. This is like a\n// `LookupImplWitness` operation but for a single interface, and against only\n// the single impl.\nauto LookupMatchesImpl(Context& context, SemIR::LocId loc_id,\n                       SemIR::ConstantId query_self_const_id,\n                       SemIR::SpecificInterface query_specific_interface,\n                       SemIR::ImplId target_impl) -> bool;\n\n// The result of EvalLookupSingleImplWitness(). It can be one of:\n// - No value. Lookup failed to find an impl declaration.\n// - An effectively final value. Lookup found either a concrete impl or a\n//   `final` impl declaration; both can be used definitely. A witness is\n//   available.\n// - A non-`final` symbolic value. Lookup found an impl, but it is not returned\n//   since lookup will need to be done again with a more specific query to look\n//   for specializations.\nclass [[nodiscard]] EvalImplLookupResult {\n public:\n  static auto MakeNone() -> EvalImplLookupResult {\n    return EvalImplLookupResult(FoundNone());\n  }\n  static auto MakeFinal(SemIR::InstId inst_id) -> EvalImplLookupResult {\n    return EvalImplLookupResult(inst_id);\n  }\n  static auto MakeNonFinal() -> EvalImplLookupResult {\n    return EvalImplLookupResult(FoundNonFinalImpl());\n  }\n\n  // True if an impl declaration was found, either effectively final or\n  // symbolic.\n  auto has_value() const -> bool {\n    return !std::holds_alternative<FoundNone>(value_);\n  }\n\n  // True if there is an effectively final witness in the result. If false, and\n  // `has_value()` is true, it means an impl was found that's not effectively\n  // final, and a further more specific query will need to be done.\n  auto has_final_value() const -> bool {\n    return std::holds_alternative<SemIR::InstId>(value_);\n  }\n\n  // Returns the witness id for an effectively final value's impl declaration.\n  // Only valid to call if `has_final_value` is true.\n  auto final_witness() const -> SemIR::InstId {\n    return std::get<SemIR::InstId>(value_);\n  }\n\n private:\n  struct FoundNone {};\n  struct FoundNonFinalImpl {};\n  using Value = std::variant<SemIR::InstId, FoundNone, FoundNonFinalImpl>;\n\n  explicit EvalImplLookupResult(Value value) : value_(value) {}\n\n  Value value_;\n};\n\n// The kind of impl lookup being performed by a call to\n// `EvalLookupSingleImplWitness`.\nenum class EvalImplLookupMode {\n  // This is a regular impl lookup performed during check. If we produce a final\n  // witness value that uses a specializable impl, the query will be poisoned so\n  // that we will recheck it at the end of the compilation.\n  Normal,\n  // This is a re-check of a poisoned lookup being performed at the end of a\n  // file. This disables any caching of lookup results for this query and redoes\n  // the impl lookup.\n  RecheckPoisonedLookup,\n};\n\n// Looks for a witness instruction of an impl declaration for a query consisting\n// of a type value or facet value, and a single interface. This is for eval to\n// execute lookup via the LookupImplWitness instruction. It does not consider\n// the self facet value for finding a witness, since LookupImplWitness() would\n// have found that and not caused us to defer lookup to here.\nauto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,\n                                 SemIR::LookupImplWitness eval_query,\n                                 SemIR::InstId self_facet_value_inst_id,\n                                 EvalImplLookupMode mode)\n    -> EvalImplLookupResult;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_IMPL_LOOKUP_H_\n"
  },
  {
    "path": "toolchain/check/impl_validation.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/impl_validation.h\"\n\n#include <utility>\n\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/STLExtras.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/impl_lookup.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/type_structure.h\"\n#include \"toolchain/sem_ir/entity_with_params_base.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/type_iterator.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nnamespace {\n\n// All information about a `SemIR::Impl` needed for validation.\nstruct ImplInfo {\n  SemIR::ImplId impl_id;\n  bool is_final;\n  SemIR::InstId witness_id;\n  SemIR::TypeInstId self_id;\n  SemIR::InstId latest_decl_id;\n  SemIR::SpecificInterface interface;\n  // Whether the `impl` decl was imported or from the local file.\n  bool is_local;\n  // If imported, the IR from which the `impl` decl was imported.\n  SemIR::ImportIRId ir_id;\n  std::optional<TypeStructure> type_structure;\n};\n\n}  // namespace\n\nstatic auto GetIRId(Context& context, SemIR::InstId owning_inst_id)\n    -> SemIR::ImportIRId {\n  if (!owning_inst_id.has_value()) {\n    return SemIR::ImportIRId::None;\n  }\n  return GetCanonicalImportIRInst(context, owning_inst_id).ir_id();\n}\n\n// Returns if `owning_inst_id` is from the current file. This does not count an\n// api and impl file as the same file.\nstatic auto IsSameFile(Context& context, SemIR::InstId owning_inst_id) -> bool {\n  if (!owning_inst_id.has_value()) {\n    return false;\n  }\n  auto ir_id = GetCanonicalImportIRInst(context, owning_inst_id).ir_id();\n  return !ir_id.has_value();\n}\n\n// Returns if `owning_inst_id` is from the current library. This does count api\n// and impl files as the same library.\nstatic auto IsSameLibrary(Context& context, SemIR::InstId owning_inst_id)\n    -> bool {\n  if (!owning_inst_id.has_value()) {\n    return false;\n  }\n  auto ir_id = GetCanonicalImportIRInst(context, owning_inst_id).ir_id();\n  if (!ir_id.has_value()) {\n    return true;\n  }\n  if (const auto* api =\n          context.import_irs().Get(SemIR::ImportIRId::ApiForImpl).sem_ir) {\n    auto& ir = context.import_irs().Get(ir_id);\n    return ir.sem_ir == api;\n  }\n  return false;\n}\n\nstatic auto GetImplInfo(Context& context, SemIR::ImplId impl_id) -> ImplInfo {\n  const auto& impl = context.impls().Get(impl_id);\n  auto ir_id = GetIRId(context, impl.first_owning_decl_id);\n  return {.impl_id = impl_id,\n          .is_final = impl.is_final,\n          .witness_id = impl.witness_id,\n          .self_id = impl.self_id,\n          .latest_decl_id = impl.latest_decl_id(),\n          .interface = impl.interface,\n          .is_local = !ir_id.has_value(),\n          .ir_id = ir_id,\n          .type_structure =\n              BuildTypeStructure(context, impl.self_id, impl.interface)};\n}\n\n// A final impl must be in the same file as either its root self type or the\n// interface in its constraint.\n//\n// Returns true if an error was diagnosed.\nstatic auto DiagnoseFinalImplNotInSameFileAsRootSelfTypeOrInterface(\n    Context& context, const ImplInfo& impl, SemIR::ImportIRId interface_ir_id)\n    -> bool {\n  bool self_type_same_file = false;\n\n  auto type_iter = SemIR::TypeIterator(&context.sem_ir());\n  type_iter.Add(impl.self_id);\n  auto step = type_iter.Next();\n\n  using Step = SemIR::TypeIterator::Step;\n  CARBON_KIND_SWITCH(step.any) {\n    case CARBON_KIND(Step::ClassStart start): {\n      auto inst_id = context.classes().Get(start.class_id).definition_id;\n      if (IsSameFile(context, inst_id)) {\n        self_type_same_file = true;\n      }\n      break;\n    }\n    case CARBON_KIND(Step::ClassStartOnly start): {\n      auto inst_id = context.classes().Get(start.class_id).definition_id;\n      if (IsSameFile(context, inst_id)) {\n        self_type_same_file = true;\n      }\n      break;\n    }\n\n    case CARBON_KIND(Step::Done _): {\n      CARBON_FATAL(\"self type is empty?\");\n    }\n\n    default:\n      break;\n  }\n\n  bool interface_same_file = !interface_ir_id.has_value();\n\n  if (!self_type_same_file && !interface_same_file) {\n    CARBON_DIAGNOSTIC(FinalImplInvalidFile, Error,\n                      \"`final impl` found in file that does not contain \"\n                      \"the root self type nor the interface definition\");\n    context.emitter().Emit(impl.latest_decl_id, FinalImplInvalidFile);\n    return true;\n  }\n\n  return false;\n}\n\nstatic auto DiagnoseOrphanImpl(Context& context, const ImplInfo& impl,\n                               SemIR::ImportIRId interface_ir_id) -> bool {\n  // If the interface is defined in this file, then the impl is not an orphan.\n  if (!interface_ir_id.has_value()) {\n    return true;\n  }\n\n  // Look for a class in the self type, or the interface specific, that is from\n  // this file to show the impl is not an orphan.\n  auto type_iter = SemIR::TypeIterator(&context.sem_ir());\n  type_iter.Add(impl.self_id);\n  type_iter.Add(impl.interface);\n\n  for (auto done = false; !done;) {\n    auto step = type_iter.Next();\n\n    using Step = SemIR::TypeIterator::Step;\n    CARBON_KIND_SWITCH(step.any) {\n      case CARBON_KIND(Step::ClassStart start): {\n        auto inst_id = context.classes().Get(start.class_id).definition_id;\n        if (IsSameLibrary(context, inst_id)) {\n          return true;\n        }\n        break;\n      }\n      case CARBON_KIND(Step::ClassStartOnly start): {\n        auto inst_id = context.classes().Get(start.class_id).definition_id;\n        if (IsSameLibrary(context, inst_id)) {\n          return true;\n        }\n        break;\n      }\n      case CARBON_KIND(Step::ConcreteType type): {\n        // These are found in a specific when a `GenericClass`, a\n        // `GenericInterface` or a `GenericNamedConstraint` appears. The generic\n        // instruction itself is evaluated to a callable StructValue in the\n        // type, but the specific also contains the callable's type which is one\n        // of these.\n        CARBON_KIND_SWITCH(context.types().GetAsInst(type.type_id)) {\n          case CARBON_KIND(SemIR::GenericClassType class_type): {\n            auto class_id = class_type.class_id;\n            auto inst_id = context.classes().Get(class_id).definition_id;\n            if (IsSameLibrary(context, inst_id)) {\n              return true;\n            }\n            break;\n          }\n          case CARBON_KIND(SemIR::GenericInterfaceType interface_type): {\n            auto interface_id = interface_type.interface_id;\n            auto inst_id = context.interfaces().Get(interface_id).definition_id;\n            if (IsSameLibrary(context, inst_id)) {\n              return true;\n            }\n            break;\n          }\n          case CARBON_KIND(SemIR::GenericNamedConstraintType constraint_type): {\n            auto constraint_id = constraint_type.named_constraint_id;\n            auto inst_id =\n                context.named_constraints().Get(constraint_id).definition_id;\n            if (IsSameLibrary(context, inst_id)) {\n              return true;\n            }\n            break;\n          }\n          default:\n            break;\n        }\n        break;\n      }\n\n      case CARBON_KIND(Step::Done _): {\n        done = true;\n        break;\n      }\n\n      default:\n        break;\n    }\n  }\n\n  CARBON_DIAGNOSTIC(ImplIsOrphan, Error,\n                    \"orphan `impl` found; something in the self-type or \"\n                    \"constraint must be defined in the same file\");\n  context.emitter().Emit(impl.latest_decl_id, ImplIsOrphan);\n  return false;\n}\n\n// The type structure each non-final `impl` must differ from all other non-final\n// `impl` for the same interface visible from the file.\n//\n// Returns true if an error was diagnosed.\nstatic auto DiagnoseNonFinalImplsWithSameTypeStructure(Context& context,\n                                                       const ImplInfo& impl_a,\n                                                       const ImplInfo& impl_b)\n    -> bool {\n  if (impl_a.type_structure == impl_b.type_structure) {\n    CARBON_DIAGNOSTIC(ImplNonFinalSameTypeStructure, Error,\n                      \"found non-final `impl` with the same type \"\n                      \"structure as another non-final `impl`\");\n    auto builder = context.emitter().Build(impl_b.latest_decl_id,\n                                           ImplNonFinalSameTypeStructure);\n    CARBON_DIAGNOSTIC(ImplNonFinalSameTypeStructureNote, Note,\n                      \"other `impl` here\");\n    builder.Note(impl_a.latest_decl_id, ImplNonFinalSameTypeStructureNote);\n    builder.Emit();\n    return true;\n  }\n\n  return false;\n}\n\n// An impl's self type and constraint can not match (as a lookup query)\n// against any final impl, or it would never be used instead of that\n// final impl.\n//\n// Returns true if an error was diagnosed.\nstatic auto DiagnoseUnmatchableNonFinalImplWithFinalImpl(Context& context,\n                                                         const ImplInfo& impl_a,\n                                                         const ImplInfo& impl_b)\n    -> bool {\n  auto diagnose_unmatchable_impl = [&](const ImplInfo& query_impl,\n                                       const ImplInfo& final_impl) -> bool {\n    if (LookupMatchesImpl(context, SemIR::LocId(query_impl.latest_decl_id),\n                          context.constant_values().Get(query_impl.self_id),\n                          query_impl.interface, final_impl.impl_id)) {\n      CARBON_DIAGNOSTIC(ImplFinalOverlapsNonFinal, Error,\n                        \"`impl` will never be used\");\n      auto builder = context.emitter().Build(query_impl.latest_decl_id,\n                                             ImplFinalOverlapsNonFinal);\n      CARBON_DIAGNOSTIC(\n          ImplFinalOverlapsNonFinalNote, Note,\n          \"`final impl` declared here would always be used instead\");\n      builder.Note(final_impl.latest_decl_id, ImplFinalOverlapsNonFinalNote);\n      builder.Emit();\n      return true;\n    }\n    return false;\n  };\n\n  CARBON_CHECK(impl_a.is_final || impl_b.is_final);\n\n  if (impl_b.is_final) {\n    return diagnose_unmatchable_impl(impl_a, impl_b);\n  } else {\n    return diagnose_unmatchable_impl(impl_b, impl_a);\n  }\n}\n\n// Final impls that overlap in their type structure must be in the\n// same file.\n//\n// Returns true if an error was diagnosed.\nstatic auto DiagnoseFinalImplsOverlapInDifferentFiles(Context& context,\n                                                      const ImplInfo& impl_a,\n                                                      const ImplInfo& impl_b)\n    -> bool {\n  if (impl_a.ir_id != impl_b.ir_id) {\n    CARBON_DIAGNOSTIC(\n        FinalImplOverlapsDifferentFile, Error,\n        \"`final impl` overlaps with `final impl` from another file\");\n    CARBON_DIAGNOSTIC(FinalImplOverlapsDifferentFileNote, Note,\n                      \"imported `final impl` here\");\n    if (impl_a.is_local) {\n      auto builder = context.emitter().Build(impl_a.latest_decl_id,\n                                             FinalImplOverlapsDifferentFile);\n      builder.Note(impl_b.latest_decl_id, FinalImplOverlapsDifferentFileNote);\n      builder.Emit();\n    } else {\n      auto builder = context.emitter().Build(impl_b.latest_decl_id,\n                                             FinalImplOverlapsDifferentFile);\n      builder.Note(impl_a.latest_decl_id, FinalImplOverlapsDifferentFileNote);\n      builder.Emit();\n    }\n    return true;\n  }\n\n  return false;\n}\n\n// Two final impls in the same file can not overlap in their type\n// structure if they are not in the same match_first block.\n//\n// TODO: Support for match_first needed here when they exist in the\n// toolchain.\n//\n// Returns true if an error was diagnosed.\nstatic auto DiagnoseFinalImplsOverlapOutsideMatchFirst(Context& context,\n                                                       const ImplInfo& impl_a,\n                                                       const ImplInfo& impl_b)\n    -> bool {\n  if (impl_a.is_local && impl_b.is_local) {\n    CARBON_DIAGNOSTIC(FinalImplOverlapsSameFile, Error,\n                      \"`final impl` overlaps with `final impl` from same file \"\n                      \"outside a `match_first` block\");\n    auto builder = context.emitter().Build(impl_b.latest_decl_id,\n                                           FinalImplOverlapsSameFile);\n    CARBON_DIAGNOSTIC(FinalImplOverlapsSameFileNote, Note,\n                      \"other `final impl` here\");\n    builder.Note(impl_a.latest_decl_id, FinalImplOverlapsSameFileNote);\n    builder.Emit();\n    return true;\n  }\n\n  return false;\n}\n\nstatic auto ValidateImplsForInterface(Context& context,\n                                      llvm::ArrayRef<ImplInfo> impls) -> void {\n  // All `impl`s we look at here have the same `InterfaceId` (though different\n  // `SpecificId`s in their `SpecificInterface`s). So we can grab the\n  // `ImportIRId` for the interface a single time up front.\n  auto interface_decl_id = context.interfaces()\n                               .Get(impls[0].interface.interface_id)\n                               .first_owning_decl_id;\n  auto interface_ir_id = GetIRId(context, interface_decl_id);\n\n  for (const auto& impl : impls) {\n    if (impl.is_final && impl.is_local) {\n      // =======================================================================\n      /// Rules for an individual final impl.\n      // =======================================================================\n      DiagnoseFinalImplNotInSameFileAsRootSelfTypeOrInterface(context, impl,\n                                                              interface_ir_id);\n    } else if (impl.is_local) {\n      DiagnoseOrphanImpl(context, impl, interface_ir_id);\n    }\n  }\n\n  // TODO: We should revisit this and look for a way to do these checks in less\n  // than quadratic time. From @zygoloid: Possibly by converting the set of\n  // impls into a decision tree.\n  //\n  // For each impl, we compare it pair-wise which each impl found before it, so\n  // that diagnostics are attached to the later impl, as the earlier impl on its\n  // own does not generate a diagnostic.\n  size_t num_impls = impls.size();\n  for (auto [split_point, impl_b] : llvm::drop_begin(llvm::enumerate(impls))) {\n    // Prevent diagnosing the same error multiple times for the same `impl_b`\n    // against different impls before it. But still ensure we do give one of\n    // each diagnostic when they are different errors.\n    bool did_diagnose_non_final_impls_with_same_type_structure = false;\n    bool did_diagnose_unmatchable_non_final_impl_with_final_impl = false;\n    bool did_diagnose_final_impls_overlap_in_different_files = false;\n    bool did_diagnose_final_impls_overlap_outside_match_first = false;\n\n    auto impls_before = llvm::drop_end(impls, num_impls - split_point);\n    for (const auto& impl_a : impls_before) {\n      // Don't diagnose structures that contain errors.\n      if (!impl_a.type_structure || !impl_b.type_structure) {\n        continue;\n      }\n\n      // Only enforce rules when at least one of the impls was written in this\n      // file.\n      if (!impl_a.is_local && !impl_b.is_local) {\n        continue;\n      }\n\n      if (!impl_a.is_final && !impl_b.is_final) {\n        // =====================================================================\n        // Rules between two non-final impls.\n        // =====================================================================\n        if (!did_diagnose_non_final_impls_with_same_type_structure) {\n          // Two impls in separate files will need to have some different\n          // concrete element in their type structure, as enforced by the orphan\n          // rule. So we don't need to check against non-local impls.\n          if (impl_a.is_local && impl_b.is_local) {\n            if (DiagnoseNonFinalImplsWithSameTypeStructure(context, impl_a,\n                                                           impl_b)) {\n              // The same final `impl_a` may overlap with multiple `impl_b`s,\n              // and we want to diagnose each `impl_b`.\n              did_diagnose_non_final_impls_with_same_type_structure = true;\n            }\n          }\n        }\n      } else if (!impl_a.is_final || !impl_b.is_final) {\n        // =====================================================================\n        // Rules between final impl and non-final impl.\n        // =====================================================================\n        if (!did_diagnose_unmatchable_non_final_impl_with_final_impl) {\n          if (DiagnoseUnmatchableNonFinalImplWithFinalImpl(context, impl_a,\n                                                           impl_b)) {\n            did_diagnose_unmatchable_non_final_impl_with_final_impl = true;\n          }\n        }\n      } else if (impl_a.type_structure->CompareStructure(\n                     TypeStructure::CompareTest::HasOverlap,\n                     *impl_b.type_structure)) {\n        // =====================================================================\n        // Rules between two overlapping final impls.\n        // =====================================================================\n        CARBON_CHECK(impl_a.is_final && impl_b.is_final);\n        if (!did_diagnose_final_impls_overlap_in_different_files) {\n          if (DiagnoseFinalImplsOverlapInDifferentFiles(context, impl_a,\n                                                        impl_b)) {\n            did_diagnose_final_impls_overlap_in_different_files = true;\n          }\n        }\n        if (!did_diagnose_final_impls_overlap_outside_match_first) {\n          if (DiagnoseFinalImplsOverlapOutsideMatchFirst(context, impl_a,\n                                                         impl_b)) {\n            did_diagnose_final_impls_overlap_outside_match_first = true;\n          }\n        }\n      }\n    }\n  }\n}\n\n// For each `impl` seen in this file, ensure that we import every available\n// `final impl` for the same interface, so that we can to check for\n// diagnostics about the relationship between them and the `impl`s in this\n// file.\nstatic auto ImportFinalImplsWithImplInFile(Context& context) -> void {\n  struct InterfaceToImport {\n    SemIR::ImportIRId ir_id;\n    SemIR::InterfaceId interface_id;\n\n    constexpr auto operator==(const InterfaceToImport& rhs) const\n        -> bool = default;\n    constexpr auto operator<=>(const InterfaceToImport& rhs) const -> auto {\n      if (ir_id != rhs.ir_id) {\n        return ir_id.index <=> rhs.ir_id.index;\n      }\n      return interface_id.index <=> rhs.interface_id.index;\n    }\n  };\n\n  llvm::SmallVector<InterfaceToImport> interfaces_to_import;\n  for (const auto& impl : context.impls().values()) {\n    if (impl.witness_id == SemIR::ErrorInst::InstId) {\n      continue;\n    }\n    auto impl_import_ir_id = GetIRId(context, impl.first_owning_decl_id);\n    if (impl_import_ir_id.has_value()) {\n      // Only import `impl`s of interfaces for which there is a local `impl` of\n      // that that interface.\n      continue;\n    }\n\n    auto interface_id = impl.interface.interface_id;\n    const auto& interface = context.interfaces().Get(interface_id);\n    if (!interface.first_owning_decl_id.has_value()) {\n      continue;\n    }\n    const auto& import_ir_inst =\n        GetCanonicalImportIRInst(context, interface.first_owning_decl_id);\n    if (!import_ir_inst.ir_id().has_value()) {\n      continue;\n    }\n    interfaces_to_import.push_back(\n        {.ir_id = import_ir_inst.ir_id(),\n         .interface_id =\n             context.import_irs()\n                 .Get(import_ir_inst.ir_id())\n                 .sem_ir->insts()\n                 .GetAs<SemIR::InterfaceDecl>(import_ir_inst.inst_id())\n                 .interface_id});\n  }\n\n  llvm::sort(interfaces_to_import);\n  llvm::unique(interfaces_to_import);\n\n  struct ImplToImport {\n    SemIR::ImportIRId ir_id;\n    SemIR::ImplId import_impl_id;\n\n    constexpr auto operator==(const ImplToImport& rhs) const -> bool = default;\n    constexpr auto operator<=>(const ImplToImport& rhs) const -> auto {\n      if (ir_id != rhs.ir_id) {\n        return ir_id.index <=> rhs.ir_id.index;\n      }\n      return import_impl_id.index <=> rhs.import_impl_id.index;\n    }\n  };\n\n  llvm::SmallVector<ImplToImport> impls_to_import;\n  for (auto [ir_id, interface_id] : interfaces_to_import) {\n    const SemIR::File& sem_ir = *context.import_irs().Get(ir_id).sem_ir;\n    for (auto [impl_id, impl] : sem_ir.impls().enumerate()) {\n      if (impl.is_final && impl.interface.interface_id == interface_id) {\n        impls_to_import.push_back({.ir_id = ir_id, .import_impl_id = impl_id});\n      }\n    }\n  }\n\n  llvm::sort(impls_to_import);\n  llvm::unique(impls_to_import);\n\n  for (auto [ir_id, import_impl_id] : impls_to_import) {\n    ImportImpl(context, ir_id, import_impl_id);\n  }\n}\n\nauto ValidateImplsInFile(Context& context) -> void {\n  ImportFinalImplsWithImplInFile(context);\n\n  // Collect all of the impls sorted into contiguous segments by their\n  // interface. We only need to compare impls within each such segment. We don't\n  // keep impls with an Error in them, as they may be missing other values\n  // needed to check the diagnostics and they already have a diagnostic printed\n  // about them anyhow. We also verify the impl has an `InterfaceId` since it\n  // can be missing, in which case a diagnostic would have been generated\n  // already as well.\n  llvm::SmallVector<ImplInfo> impl_ids_by_interface(llvm::map_range(\n      llvm::make_filter_range(\n          context.impls().enumerate(),\n          [](std::pair<SemIR::ImplId, const SemIR::Impl&> pair) {\n            return pair.second.witness_id != SemIR::ErrorInst::InstId &&\n                   pair.second.interface.interface_id.has_value();\n          }),\n      [&](std::pair<SemIR::ImplId, const SemIR::Impl&> pair) {\n        return GetImplInfo(context, pair.first);\n      }));\n  llvm::stable_sort(impl_ids_by_interface, [](const ImplInfo& lhs,\n                                              const ImplInfo& rhs) {\n    return lhs.interface.interface_id.index < rhs.interface.interface_id.index;\n  });\n\n  const auto* it = impl_ids_by_interface.begin();\n  while (it != impl_ids_by_interface.end()) {\n    const auto* segment_begin = it;\n    auto begin_interface_id = segment_begin->interface.interface_id;\n    do {\n      ++it;\n    } while (it != impl_ids_by_interface.end() &&\n             it->interface.interface_id == begin_interface_id);\n    const auto* segment_end = it;\n\n    ValidateImplsForInterface(context, {segment_begin, segment_end});\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/impl_validation.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_IMPL_VALIDATION_H_\n#define CARBON_TOOLCHAIN_CHECK_IMPL_VALIDATION_H_\n\n#include \"toolchain/check/context.h\"\n\nnamespace Carbon::Check {\n\n// Called after typechecking the full file to diagnose any `impl` declarations\n// that are invalid because they are in wrong file or overlap with other `impl`\n// declarations incorrectly.\nauto ValidateImplsInFile(Context& context) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_IMPL_VALIDATION_H_\n"
  },
  {
    "path": "toolchain/check/import.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/import.h\"\n\n#include <optional>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/map.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/merge.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/file.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/import_ir.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Returns name information for an EntityWithParamsBase.\ntemplate <typename T>\nstatic auto GetImportNameForEntity(const T& entity)\n    -> std::pair<SemIR::NameId, SemIR::NameScopeId> {\n  return {entity.name_id, entity.parent_scope_id};\n}\ntemplate <>\nauto GetImportNameForEntity(const SemIR::NameScope& entity)\n    -> std::pair<SemIR::NameId, SemIR::NameScopeId> {\n  return {entity.name_id(), entity.parent_scope_id()};\n}\n\n// Returns name information for the entity, corresponding to IDs in the import\n// IR rather than the current IR.\nstatic auto GetImportName(const SemIR::File& import_sem_ir,\n                          SemIR::Inst import_inst)\n    -> std::pair<SemIR::NameId, SemIR::NameScopeId> {\n  CARBON_KIND_SWITCH(import_inst) {\n    case SemIR::AliasBinding::Kind:\n    case SemIR::RefBinding::Kind:\n    case SemIR::SymbolicBinding::Kind:\n    case SemIR::ValueBinding::Kind:\n    case SemIR::ExportDecl::Kind: {\n      auto bind_inst = import_inst.As<SemIR::AnyBindingOrExportDecl>();\n      return GetImportNameForEntity(\n          import_sem_ir.entity_names().Get(bind_inst.entity_name_id));\n    }\n\n    case CARBON_KIND(SemIR::ClassDecl class_decl): {\n      return GetImportNameForEntity(\n          import_sem_ir.classes().Get(class_decl.class_id));\n    }\n\n    case CARBON_KIND(SemIR::FunctionDecl function_decl): {\n      return GetImportNameForEntity(\n          import_sem_ir.functions().Get(function_decl.function_id));\n    }\n\n    case CARBON_KIND(SemIR::InterfaceDecl interface_decl): {\n      return GetImportNameForEntity(\n          import_sem_ir.interfaces().Get(interface_decl.interface_id));\n    }\n\n    case CARBON_KIND(SemIR::Namespace ns): {\n      return GetImportNameForEntity(\n          import_sem_ir.name_scopes().Get(ns.name_scope_id));\n    }\n\n    case CARBON_KIND(SemIR::NamedConstraintDecl named_constraint_decl): {\n      return GetImportNameForEntity(import_sem_ir.named_constraints().Get(\n          named_constraint_decl.named_constraint_id));\n    }\n\n    default:\n      CARBON_FATAL(\"Unsupported export kind: {0}\", import_inst);\n  }\n}\n\n// Translate the name to the current IR. It will usually be an identifier, but\n// could also be a builtin name ID which is equivalent cross-IR.\nstatic auto CopyNameFromImportIR(Context& context,\n                                 const SemIR::File& import_sem_ir,\n                                 SemIR::NameId import_name_id)\n    -> SemIR::NameId {\n  if (auto import_identifier_id = import_name_id.AsIdentifierId();\n      import_identifier_id.has_value()) {\n    auto name = import_sem_ir.identifiers().Get(import_identifier_id);\n    return SemIR::NameId::ForIdentifier(context.identifiers().Add(name));\n  }\n  return import_name_id;\n}\n\n// Returns the LocIdAndInst for the namespace.\nstatic auto MakeImportedNamespaceLocIdAndInst(Context& context,\n                                              SemIR::InstId import_id,\n                                              SemIR::Namespace namespace_inst)\n    -> SemIR::LocIdAndInst {\n  if (!import_id.has_value()) {\n    // TODO: Associate the namespace with a proper location. This is related to:\n    // https://github.com/carbon-language/carbon-lang/issues/4666.\n    return SemIR::LocIdAndInst::NoLoc(namespace_inst);\n  }\n\n  // If the import was itself imported, use its location.\n  if (auto import_ir_inst_id = context.insts().GetImportSource(import_id);\n      import_ir_inst_id.has_value()) {\n    return MakeImportedLocIdAndInst(context, import_ir_inst_id, namespace_inst);\n  }\n\n  // Otherwise we should have a node location for some kind of namespace\n  // declaration in the current file.\n  SemIR::LocId import_loc_id = context.insts().GetCanonicalLocId(import_id);\n  switch (import_loc_id.kind()) {\n    case SemIR::LocId::Kind::NodeId:\n      return SemIR::LocIdAndInst(context.parse_tree().As<Parse::AnyNamespaceId>(\n                                     import_loc_id.node_id()),\n                                 namespace_inst);\n    case SemIR::LocId::Kind::None:\n      // TODO: Either document the use-case for this, or require a location.\n      return SemIR::LocIdAndInst::NoLoc(namespace_inst);\n    case SemIR::LocId::Kind::ImportIRInstId:\n    case SemIR::LocId::Kind::InstId:\n      CARBON_FATAL(\"Unexpected LocId kind\");\n  }\n}\n\nauto AddImportNamespace(Context& context, SemIR::TypeId namespace_type_id,\n                        SemIR::NameId name_id,\n                        SemIR::NameScopeId parent_scope_id,\n                        SemIR::InstId import_id) -> AddImportNamespaceResult {\n  auto namespace_inst =\n      SemIR::Namespace{.type_id = namespace_type_id,\n                       .name_scope_id = SemIR::NameScopeId::None,\n                       .import_id = import_id};\n  auto namespace_inst_and_loc =\n      MakeImportedNamespaceLocIdAndInst(context, import_id, namespace_inst);\n  AddImportNamespaceResult result = {\n      .name_scope_id = SemIR::NameScopeId::None,\n      .inst_id =\n          AddPlaceholderImportedInstInNoBlock(context, namespace_inst_and_loc)};\n  namespace_inst.name_scope_id =\n      context.name_scopes().Add(result.inst_id, name_id, parent_scope_id);\n  result.name_scope_id = namespace_inst.name_scope_id;\n  ReplaceInstBeforeConstantUse(context, result.inst_id, namespace_inst);\n  return result;\n}\n\nauto AddImportNamespaceToScope(\n    Context& context, SemIR::TypeId namespace_type_id, SemIR::NameId name_id,\n    SemIR::NameScopeId parent_scope_id, bool diagnose_duplicate_namespace,\n    llvm::function_ref<SemIR::InstId()> make_import_id)\n    -> AddImportNamespaceToScopeResult {\n  auto& parent_scope = context.name_scopes().Get(parent_scope_id);\n  auto [inserted, entry_id] = parent_scope.LookupOrAdd(\n      name_id,\n      // This InstId is temporary and would be overridden if used.\n      SemIR::InstId::None, SemIR::AccessKind::Public);\n  if (!inserted) {\n    const auto& prev_entry = parent_scope.GetEntry(entry_id);\n    if (!prev_entry.result.is_poisoned()) {\n      auto prev_inst_id = prev_entry.result.target_inst_id();\n      if (auto namespace_inst =\n              context.insts().TryGetAs<SemIR::Namespace>(prev_inst_id)) {\n        if (diagnose_duplicate_namespace) {\n          auto import_id = make_import_id();\n          CARBON_CHECK(import_id.has_value());\n          // TODO: Pass the import package name location instead of the import\n          // id to get more accurate location.\n          DiagnoseDuplicateName(context, name_id, SemIR::LocId(import_id),\n                                SemIR::LocId(prev_inst_id));\n        }\n        return {.add_result = {.name_scope_id = namespace_inst->name_scope_id,\n                               .inst_id = prev_inst_id},\n                .is_duplicate_of_namespace_in_current_package = true};\n      }\n    }\n  }\n\n  auto import_id = make_import_id();\n  CARBON_CHECK(import_id.has_value());\n\n  AddImportNamespaceToScopeResult result = {\n      .add_result = AddImportNamespace(context, namespace_type_id, name_id,\n                                       parent_scope_id, import_id),\n      .is_duplicate_of_namespace_in_current_package = false};\n\n  // Diagnose if there's a name conflict, but still produce the namespace to\n  // supersede the name conflict in order to avoid repeat diagnostics. Names\n  // are poisoned optimistically by name lookup before checking for imports,\n  // so we may be overwriting a poisoned entry here.\n  auto& lookup_result = parent_scope.GetEntry(entry_id).result;\n  if (!lookup_result.is_poisoned() && !inserted) {\n    // TODO: Pass the import namespace name location instead of the namespace\n    // id to get more accurate location.\n    DiagnoseDuplicateName(context, name_id,\n                          SemIR::LocId(result.add_result.inst_id),\n                          SemIR::LocId(lookup_result.target_inst_id()));\n  }\n  lookup_result = SemIR::ScopeLookupResult::MakeFound(\n      result.add_result.inst_id, SemIR::AccessKind::Public);\n  return result;\n}\n\n// Adds a copied namespace to the cache.\nstatic auto CacheCopiedNamespace(\n    Map<SemIR::NameScopeId, SemIR::NameScopeId>& copied_namespaces,\n    SemIR::NameScopeId import_scope_id, SemIR::NameScopeId to_scope_id)\n    -> void {\n  auto result = copied_namespaces.Insert(import_scope_id, to_scope_id);\n  CARBON_CHECK(result.is_inserted() || result.value() == to_scope_id,\n               \"Copy result for namespace changed from {0} to {1}\",\n               import_scope_id, to_scope_id);\n}\n\n// Copies a namespace from the import IR, returning its ID. This may diagnose\n// name conflicts, but that won't change the result because namespaces supersede\n// other names in conflicts. The bool on return is true if there was a name\n// conflict. copied_namespaces is optional.\nstatic auto CopySingleNameScopeFromImportIR(\n    Context& context, SemIR::TypeId namespace_type_id,\n    Map<SemIR::NameScopeId, SemIR::NameScopeId>* copied_namespaces,\n    SemIR::ImportIRId ir_id, SemIR::InstId import_inst_id,\n    SemIR::NameScopeId import_scope_id, SemIR::NameScopeId parent_scope_id,\n    SemIR::NameId name_id) -> AddImportNamespaceToScopeResult {\n  // Produce the namespace for the entry.\n  auto make_import_id = [&]() {\n    auto entity_name_id = context.entity_names().Add(\n        {.name_id = name_id, .parent_scope_id = parent_scope_id});\n    auto import_ir_inst_id = context.import_ir_insts().Add(\n        SemIR::ImportIRInst(ir_id, import_inst_id));\n    auto inst_id = AddInstInNoBlock(\n        context, MakeImportedLocIdAndInst<SemIR::ImportRefLoaded>(\n                     context, import_ir_inst_id,\n                     {.type_id = namespace_type_id,\n                      .import_ir_inst_id = import_ir_inst_id,\n                      .entity_name_id = entity_name_id}));\n    context.imports().push_back(inst_id);\n    return inst_id;\n  };\n  AddImportNamespaceToScopeResult result = AddImportNamespaceToScope(\n      context, namespace_type_id, name_id, parent_scope_id,\n      /*diagnose_duplicate_namespace=*/false, make_import_id);\n\n  auto namespace_const_id =\n      context.constant_values().Get(result.add_result.inst_id);\n  context\n      .import_ir_constant_values()[context.sem_ir().import_irs().GetRawIndex(\n          ir_id)]\n      .Set(import_inst_id, namespace_const_id);\n\n  if (copied_namespaces) {\n    CacheCopiedNamespace(*copied_namespaces, import_scope_id,\n                         result.add_result.name_scope_id);\n  }\n  return result;\n}\n\n// Copies ancestor name scopes from the import IR. Handles the parent traversal.\n// Returns the NameScope corresponding to the copied import_parent_scope_id.\nstatic auto CopyAncestorNameScopesFromImportIR(\n    Context& context, SemIR::TypeId namespace_type_id,\n    const SemIR::File& import_sem_ir, SemIR::ImportIRId ir_id,\n    SemIR::NameScopeId import_parent_scope_id,\n    Map<SemIR::NameScopeId, SemIR::NameScopeId>& copied_namespaces)\n    -> SemIR::NameScopeId {\n  // Package-level names don't need work.\n  if (import_parent_scope_id == SemIR::NameScopeId::Package) {\n    return import_parent_scope_id;\n  }\n\n  // The scope to add namespaces to. Note this may change while looking at\n  // parent scopes, if we encounter a namespace that's already added.\n  auto scope_cursor = SemIR::NameScopeId::Package;\n\n  // Build a stack of ancestor namespace names, with the immediate parent first.\n  llvm::SmallVector<SemIR::NameScopeId> new_namespaces;\n  while (import_parent_scope_id != SemIR::NameScopeId::Package) {\n    // If the namespace was already copied, reuse the results.\n    if (auto result = copied_namespaces.Lookup(import_parent_scope_id)) {\n      // We inject names at the provided scope, and don't need to keep\n      // traversing parents.\n      scope_cursor = result.value();\n      break;\n    }\n\n    // The namespace hasn't been copied yet, so add it to our list.\n    const auto& scope = import_sem_ir.name_scopes().Get(import_parent_scope_id);\n    auto scope_inst =\n        import_sem_ir.insts().GetAs<SemIR::Namespace>(scope.inst_id());\n    new_namespaces.push_back(scope_inst.name_scope_id);\n    import_parent_scope_id = scope.parent_scope_id();\n  }\n\n  // Add ancestor namespace names, starting with the outermost.\n  for (auto import_scope_id : llvm::reverse(new_namespaces)) {\n    const auto& import_scope = import_sem_ir.name_scopes().Get(import_scope_id);\n    auto name_id =\n        CopyNameFromImportIR(context, import_sem_ir, import_scope.name_id());\n    scope_cursor =\n        CopySingleNameScopeFromImportIR(\n            context, namespace_type_id, &copied_namespaces, ir_id,\n            import_scope.inst_id(), import_scope_id, scope_cursor, name_id)\n            .add_result.name_scope_id;\n  }\n\n  return scope_cursor;\n}\n\n// Imports the function if it's a non-owning declaration with the current file\n// as owner.\nstatic auto LoadImportForOwningFunction(Context& context,\n                                        const SemIR::File& import_sem_ir,\n                                        const SemIR::Function& function,\n                                        SemIR::InstId import_ref) {\n  if (!function.extern_library_id.has_value()) {\n    return;\n  }\n  CARBON_CHECK(function.is_extern && \"Expected extern functions\");\n  auto lib_id = function.extern_library_id;\n  bool is_lib_default = lib_id == SemIR::LibraryNameId::Default;\n\n  auto current_id = context.sem_ir().library_id();\n  bool is_current_default = current_id == SemIR::LibraryNameId::Default;\n\n  if (is_lib_default == is_current_default) {\n    if (is_lib_default) {\n      // Both libraries are default, import ref.\n      LoadImportRef(context, import_ref);\n    } else {\n      // Both libraries are non-default: check if they're the same named\n      // library, import ref if yes.\n      auto str_owner_library = context.string_literal_values().Get(\n          current_id.AsStringLiteralValueId());\n      auto str_decl_library = import_sem_ir.string_literal_values().Get(\n          lib_id.AsStringLiteralValueId());\n      if (str_owner_library == str_decl_library) {\n        LoadImportRef(context, import_ref);\n      }\n    }\n  }\n}\n\n// Adds an ImportRef for an entity, handling merging if needed.\nstatic auto AddImportRefOrMerge(Context& context, SemIR::ImportIRId ir_id,\n                                const SemIR::File& import_sem_ir,\n                                SemIR::InstId import_inst_id,\n                                SemIR::NameScopeId parent_scope_id,\n                                SemIR::NameId name_id) -> void {\n  // Leave a placeholder that the inst comes from the other IR.\n  auto& parent_scope = context.name_scopes().Get(parent_scope_id);\n  auto [inserted, entry_id] = parent_scope.LookupOrAdd(\n      name_id,\n      // This InstId is temporary and would be overridden if used.\n      SemIR::InstId::None, SemIR::AccessKind::Public);\n  auto& entry = parent_scope.GetEntry(entry_id);\n  if (inserted) {\n    auto entity_name_id = context.entity_names().Add(\n        {.name_id = name_id, .parent_scope_id = parent_scope_id});\n    auto import_ref = AddImportRef(\n        context, SemIR::ImportIRInst(ir_id, import_inst_id), entity_name_id);\n    entry.result = SemIR::ScopeLookupResult::MakeFound(\n        import_ref, SemIR::AccessKind::Public);\n\n    // Import references for non-owning declarations that match current library.\n    if (auto function_decl =\n            import_sem_ir.insts().TryGetAs<SemIR::FunctionDecl>(\n                import_inst_id)) {\n      LoadImportForOwningFunction(\n          context, import_sem_ir,\n          import_sem_ir.functions().Get(function_decl->function_id),\n          import_ref);\n    }\n    return;\n  }\n\n  auto inst_id = entry.result.target_inst_id();\n  auto prev_ir_inst = GetCanonicalImportIRInst(context, inst_id);\n  VerifySameCanonicalImportIRInst(context, name_id, inst_id, prev_ir_inst,\n                                  ir_id, &import_sem_ir, import_inst_id);\n}\n\nnamespace {\n// A scope in the API file that still needs to be copied to the implementation\n// file. Only used for API file imports.\nstruct TodoScope {\n  // The scope's instruction in the API file.\n  SemIR::InstId api_inst_id;\n  // The scope in the API file.\n  SemIR::NameScopeId api_scope_id;\n  // The already-translated scope name in the implementation file.\n  SemIR::NameId impl_name_id;\n  // The already-copied parent scope in the implementation file.\n  SemIR::NameScopeId impl_parent_scope_id;\n};\n}  // namespace\n\n// Adds an ImportRef to a name scope.\nstatic auto AddScopedImportRef(Context& context,\n                               SemIR::NameScopeId parent_scope_id,\n                               SemIR::NameScope& parent_scope,\n                               SemIR::NameId name_id,\n                               SemIR::ImportIRInst import_inst,\n                               SemIR::AccessKind access_kind) -> SemIR::InstId {\n  // Add an ImportRef for other instructions.\n  auto impl_entity_name_id = context.entity_names().Add(\n      {.name_id = name_id, .parent_scope_id = parent_scope_id});\n  auto import_ref_id = AddImportRef(context, import_inst, impl_entity_name_id);\n  parent_scope.AddRequired({.name_id = name_id,\n                            .result = SemIR::ScopeLookupResult::MakeFound(\n                                import_ref_id, access_kind)});\n  return import_ref_id;\n}\n\n// Imports entries in a specific scope into the current file.\nstatic auto ImportScopeFromApiFile(Context& context,\n                                   const SemIR::File& api_sem_ir,\n                                   SemIR::NameScopeId api_scope_id,\n                                   SemIR::NameScopeId impl_scope_id,\n                                   llvm::SmallVector<TodoScope>& todo_scopes)\n    -> void {\n  const auto& api_scope = api_sem_ir.name_scopes().Get(api_scope_id);\n  auto& impl_scope = context.name_scopes().Get(impl_scope_id);\n\n  for (const auto& api_entry : api_scope.entries()) {\n    if (api_entry.result.is_poisoned()) {\n      continue;\n    }\n    auto impl_name_id =\n        CopyNameFromImportIR(context, api_sem_ir, api_entry.name_id);\n    if (auto ns = api_sem_ir.insts().TryGetAs<SemIR::Namespace>(\n            api_entry.result.target_inst_id())) {\n      // Ignore cross-package imports. These will be handled through\n      // ImportLibrariesFromOtherPackage.\n      if (api_scope_id == SemIR::NameScopeId::Package) {\n        const auto& ns_scope = api_sem_ir.name_scopes().Get(ns->name_scope_id);\n        if (!ns_scope.import_ir_scopes().empty()) {\n          continue;\n        }\n      }\n\n      // Namespaces will be recursed into. Name scope creation is delayed in\n      // order to avoid invalidating api_scope/impl_scope.\n      todo_scopes.push_back({.api_inst_id = api_entry.result.target_inst_id(),\n                             .api_scope_id = ns->name_scope_id,\n                             .impl_name_id = impl_name_id,\n                             .impl_parent_scope_id = impl_scope_id});\n    } else {\n      // Add an ImportRef for other instructions.\n      AddScopedImportRef(context, impl_scope_id, impl_scope, impl_name_id,\n                         SemIR::ImportIRInst(SemIR::ImportIRId::ApiForImpl,\n                                             api_entry.result.target_inst_id()),\n                         api_entry.result.access_kind());\n    }\n  }\n}\n\nauto ImportApiFile(Context& context, SemIR::TypeId namespace_type_id,\n                   const SemIR::File& api_sem_ir) -> void {\n  context.import_ir_constant_values()[SemIR::ImportIRId::ApiForImpl.index].Set(\n      SemIR::Namespace::PackageInstId,\n      context.constant_values().Get(SemIR::Namespace::PackageInstId));\n\n  llvm::SmallVector<TodoScope> todo_scopes = {};\n  ImportScopeFromApiFile(context, api_sem_ir, SemIR::NameScopeId::Package,\n                         SemIR::NameScopeId::Package, todo_scopes);\n  while (!todo_scopes.empty()) {\n    auto todo_scope = todo_scopes.pop_back_val();\n    auto impl_scope_id =\n        CopySingleNameScopeFromImportIR(\n            context, namespace_type_id, /*copied_namespaces=*/nullptr,\n            SemIR::ImportIRId::ApiForImpl, todo_scope.api_inst_id,\n            todo_scope.api_scope_id, todo_scope.impl_parent_scope_id,\n            todo_scope.impl_name_id)\n            .add_result.name_scope_id;\n    ImportScopeFromApiFile(context, api_sem_ir, todo_scope.api_scope_id,\n                           impl_scope_id, todo_scopes);\n  }\n}\n\nauto ImportLibrariesFromCurrentPackage(\n    Context& context, SemIR::TypeId namespace_type_id,\n    llvm::ArrayRef<SemIR::ImportIR> import_irs) -> void {\n  for (auto import_ir : import_irs) {\n    auto ir_id = AddImportIR(context, import_ir);\n\n    context\n        .import_ir_constant_values()[context.sem_ir().import_irs().GetRawIndex(\n            ir_id)]\n        .Set(SemIR::Namespace::PackageInstId,\n             context.constant_values().Get(SemIR::Namespace::PackageInstId));\n\n    for (const auto import_inst_id :\n         import_ir.sem_ir->inst_blocks().Get(SemIR::InstBlockId::Exports)) {\n      auto import_inst = import_ir.sem_ir->insts().Get(import_inst_id);\n      auto [import_name_id, import_parent_scope_id] =\n          GetImportName(*import_ir.sem_ir, import_inst);\n\n      Map<SemIR::NameScopeId, SemIR::NameScopeId> copied_namespaces;\n\n      auto name_id =\n          CopyNameFromImportIR(context, *import_ir.sem_ir, import_name_id);\n      SemIR::NameScopeId parent_scope_id = CopyAncestorNameScopesFromImportIR(\n          context, namespace_type_id, *import_ir.sem_ir, ir_id,\n          import_parent_scope_id, copied_namespaces);\n\n      if (auto import_namespace_inst = import_inst.TryAs<SemIR::Namespace>()) {\n        // Namespaces are always imported because they're essential for\n        // qualifiers, and the type is simple.\n        CopySingleNameScopeFromImportIR(\n            context, namespace_type_id, &copied_namespaces, ir_id,\n            import_inst_id, import_namespace_inst->name_scope_id,\n            parent_scope_id, name_id);\n      } else {\n        AddImportRefOrMerge(context, ir_id, *import_ir.sem_ir, import_inst_id,\n                            parent_scope_id, name_id);\n      }\n    }\n\n    // If an import of the current package caused an error for the imported\n    // file, it transitively affects the current file too.\n    if (import_ir.sem_ir->name_scopes()\n            .Get(SemIR::NameScopeId::Package)\n            .has_error()) {\n      context.name_scopes().Get(SemIR::NameScopeId::Package).set_has_error();\n    }\n  }\n}\n\nauto ImportLibrariesFromOtherPackage(Context& context,\n                                     SemIR::TypeId namespace_type_id,\n                                     SemIR::InstId import_decl_id,\n                                     PackageNameId package_id,\n                                     llvm::ArrayRef<SemIR::ImportIR> import_irs,\n                                     bool has_load_error) -> void {\n  CARBON_CHECK(has_load_error || !import_irs.empty(),\n               \"There should be either a load error or at least one IR.\");\n\n  auto name_id = SemIR::NameId::ForPackageName(package_id);\n\n  AddImportNamespaceToScopeResult result = AddImportNamespaceToScope(\n      context, namespace_type_id, name_id, SemIR::NameScopeId::Package,\n      /*diagnose_duplicate_namespace=*/true, [&] { return import_decl_id; });\n  auto namespace_const_id =\n      context.constant_values().Get(result.add_result.inst_id);\n\n  auto& scope = context.name_scopes().Get(result.add_result.name_scope_id);\n  scope.set_is_closed_import(\n      !result.is_duplicate_of_namespace_in_current_package);\n  for (auto import_ir : import_irs) {\n    auto ir_id = AddImportIR(context, import_ir);\n    scope.AddImportIRScope({ir_id, SemIR::NameScopeId::Package});\n    context\n        .import_ir_constant_values()[context.sem_ir().import_irs().GetRawIndex(\n            ir_id)]\n        .Set(SemIR::Namespace::PackageInstId, namespace_const_id);\n  }\n  if (has_load_error) {\n    scope.set_has_error();\n  }\n}\n\n// Looks up a name in a scope imported from another package. An `identifier` is\n// provided if `name_id` corresponds to an identifier in the current file;\n// otherwise, `name_id` is file-agnostic and can be used directly.\nstatic auto LookupNameInImport(const SemIR::File& import_ir,\n                               SemIR::NameScopeId import_scope_id,\n                               SemIR::NameId name_id,\n                               llvm::StringRef identifier)\n    -> const Carbon::SemIR::NameScope::Entry* {\n  // Determine the NameId in the import IR.\n  SemIR::NameId import_name_id = name_id;\n  if (!identifier.empty()) {\n    auto import_identifier_id = import_ir.identifiers().Lookup(identifier);\n    if (!import_identifier_id.has_value()) {\n      // Name doesn't exist in the import IR.\n      return nullptr;\n    }\n    import_name_id = SemIR::NameId::ForIdentifier(import_identifier_id);\n  }\n\n  // Look up the name in the import scope.\n  const auto& import_scope = import_ir.name_scopes().Get(import_scope_id);\n  auto import_scope_entry_id = import_scope.Lookup(import_name_id);\n  if (!import_scope_entry_id) {\n    // Name doesn't exist in the import scope.\n    return nullptr;\n  }\n\n  const auto& import_scope_entry =\n      import_scope.GetEntry(*import_scope_entry_id);\n\n  if (import_scope_entry.result.access_kind() != SemIR::AccessKind::Public) {\n    // Ignore cross-package non-public names.\n    return nullptr;\n  }\n\n  return &import_scope_entry;\n}\n\n// Adds a namespace that points to one in another package.\nstatic auto AddNamespaceFromOtherPackage(Context& context,\n                                         SemIR::ImportIRId import_ir_id,\n                                         SemIR::InstId import_inst_id,\n                                         SemIR::Namespace import_ns,\n                                         SemIR::NameScopeId parent_scope_id,\n                                         SemIR::NameId name_id)\n    -> SemIR::InstId {\n  auto namespace_type_id =\n      GetSingletonType(context, SemIR::NamespaceType::TypeInstId);\n  AddImportNamespaceToScopeResult result = CopySingleNameScopeFromImportIR(\n      context, namespace_type_id, /*copied_namespaces=*/nullptr, import_ir_id,\n      import_inst_id, import_ns.name_scope_id, parent_scope_id, name_id);\n  auto& scope = context.name_scopes().Get(result.add_result.name_scope_id);\n  scope.set_is_closed_import(\n      !result.is_duplicate_of_namespace_in_current_package);\n  scope.AddImportIRScope({import_ir_id, import_ns.name_scope_id});\n  return result.add_result.inst_id;\n}\n\nauto ImportNameFromOtherPackage(\n    Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id,\n    llvm::ArrayRef<std::pair<SemIR::ImportIRId, SemIR::NameScopeId>>\n        import_ir_scopes,\n    SemIR::NameId name_id) -> SemIR::InstId {\n  // If the name is an identifier, get the string first so that it can be shared\n  // when there are multiple IRs.\n  llvm::StringRef identifier;\n  if (auto identifier_id = name_id.AsIdentifierId();\n      identifier_id.has_value()) {\n    identifier = context.identifiers().Get(identifier_id);\n    CARBON_CHECK(!identifier.empty());\n  }\n\n  // Annotate diagnostics as occurring during this name lookup.\n  Diagnostics::AnnotationScope annotate_diagnostics(\n      &context.emitter(), [&](auto& builder) {\n        CARBON_DIAGNOSTIC(InNameLookup, Note, \"in name lookup for `{0}`\",\n                          SemIR::NameId);\n        builder.Note(loc_id, InNameLookup, name_id);\n      });\n\n  // Although we track the result here and look in each IR, we pretty much use\n  // the first result.\n  auto result_id = SemIR::InstId::None;\n  // The canonical IR and inst_id for where `result_id` came from, which may be\n  // indirectly imported. This is only resolved on a conflict, when it can be\n  // used to determine the conflict is actually the same instruction.\n  std::optional<SemIR::ImportIRInst> canonical_result_inst;\n\n  for (auto [import_ir_id, import_scope_id] : import_ir_scopes) {\n    auto& import_ir = context.import_irs().Get(import_ir_id);\n\n    const auto* import_scope_entry = LookupNameInImport(\n        *import_ir.sem_ir, import_scope_id, name_id, identifier);\n    if (!import_scope_entry || !import_scope_entry->result.is_found()) {\n      continue;\n    }\n    SemIR::InstId import_scope_inst_id =\n        import_scope_entry->result.target_inst_id();\n    auto import_inst = import_ir.sem_ir->insts().Get(import_scope_inst_id);\n    if (import_inst.Is<SemIR::AnyImportRef>()) {\n      // This entity was added to name lookup by using an import, and is not\n      // exported.\n      continue;\n    }\n\n    // Add the first result found.\n    if (!result_id.has_value()) {\n      // If the imported instruction is a namespace, we add it directly instead\n      // of as an ImportRef.\n      if (auto import_ns = import_inst.TryAs<SemIR::Namespace>()) {\n        result_id = AddNamespaceFromOtherPackage(context, import_ir_id,\n                                                 import_scope_inst_id,\n                                                 *import_ns, scope_id, name_id);\n      } else {\n        result_id = AddScopedImportRef(\n            context, scope_id, context.name_scopes().Get(scope_id), name_id,\n            SemIR::ImportIRInst(import_ir_id, import_scope_inst_id),\n            SemIR::AccessKind::Public);\n        LoadImportRef(context, result_id);\n      }\n      continue;\n    }\n\n    // When namespaces collide between files, merge lookup in the scopes.\n    if (auto import_ns = import_inst.TryAs<SemIR::Namespace>()) {\n      if (auto ns = context.insts().TryGetAs<SemIR::Namespace>(result_id)) {\n        auto& name_scope = context.name_scopes().Get(ns->name_scope_id);\n        name_scope.AddImportIRScope({import_ir_id, import_ns->name_scope_id});\n        continue;\n      }\n    }\n\n    // When there's a name collision, they need to either be the same canonical\n    // instruction, or we'll diagnose.\n    if (!canonical_result_inst) {\n      canonical_result_inst = GetCanonicalImportIRInst(context, result_id);\n    }\n    VerifySameCanonicalImportIRInst(context, name_id, result_id,\n                                    *canonical_result_inst, import_ir_id,\n                                    import_ir.sem_ir, import_scope_inst_id);\n  }\n\n  return result_id;\n}\n\n// Returns whether a parse node associated with an imported instruction of kind\n// `imported_kind` is usable as the location of a corresponding local\n// instruction of kind `local_kind`.\nstatic auto HasCompatibleImportedNodeKind(SemIR::InstKind imported_kind,\n                                          SemIR::InstKind local_kind) -> bool {\n  if (imported_kind == local_kind) {\n    return true;\n  }\n  if (imported_kind == SemIR::ImportDecl::Kind &&\n      local_kind == SemIR::Namespace::Kind) {\n    static_assert(\n        std::is_convertible_v<decltype(SemIR::ImportDecl::Kind)::TypedNodeId,\n                              decltype(SemIR::Namespace::Kind)::TypedNodeId>);\n    return true;\n  }\n  return false;\n}\n\nnamespace Internal {\n\nauto CheckCompatibleImportedNodeKind(Context& context,\n                                     SemIR::ImportIRInstId imported_loc_id,\n                                     SemIR::InstKind kind) -> void {\n  auto& import_ir_inst = context.import_ir_insts().Get(imported_loc_id);\n  if (import_ir_inst.ir_id() == SemIR::ImportIRId::Cpp) {\n    // We don't require a matching node kind if the location is in C++, because\n    // there isn't a node.\n    return;\n  }\n  const auto* import_ir =\n      context.import_irs().Get(import_ir_inst.ir_id()).sem_ir;\n  auto imported_kind = import_ir->insts().Get(import_ir_inst.inst_id()).kind();\n  CARBON_CHECK(\n      HasCompatibleImportedNodeKind(imported_kind, kind),\n      \"Node of kind {0} created with location of imported node of kind {1}\",\n      kind, imported_kind);\n}\n\n}  // namespace Internal\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/import.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_IMPORT_H_\n#define CARBON_TOOLCHAIN_CHECK_IMPORT_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/file.h\"\n\nnamespace Carbon::Check {\n\nstruct AddImportNamespaceResult {\n  // The namespace scope id.\n  SemIR::NameScopeId name_scope_id;\n\n  // The namespace instruction id.\n  SemIR::InstId inst_id;\n};\n\n// Adds a namespace to the IR. Associates the namespace with the import referred\n// in `import_id`, if any. Do not try to add the namespace `name_id` to the\n// scope and don't check if it already exists. Used when the name is added\n// afterwards.\nauto AddImportNamespace(Context& context, SemIR::TypeId namespace_type_id,\n                        SemIR::NameId name_id,\n                        SemIR::NameScopeId parent_scope_id,\n                        SemIR::InstId import_id) -> AddImportNamespaceResult;\n\nstruct AddImportNamespaceToScopeResult {\n  AddImportNamespaceResult add_result;\n\n  // When trying to add the namespace name, whether it already exists and refers\n  // to a namespace.\n  bool is_duplicate_of_namespace_in_current_package = false;\n};\n\n// Adds a namespace to the IR. Associates the namespace with the import returned\n// from `make_import_id`, which must return a value. Tries to add the namespace\n// `name_id` to the scope. If the name already exists, diagnose only if\n// `diagnose_duplicate_namespace` is true or if it doesn't refer to a namespace.\n// `diagnose_duplicate_namespace` is used when handling a cross-package import,\n// where an existing namespace is in the current package and the new namespace\n// is a different package.\nauto AddImportNamespaceToScope(\n    Context& context, SemIR::TypeId namespace_type_id, SemIR::NameId name_id,\n    SemIR::NameScopeId parent_scope_id, bool diagnose_duplicate_namespace,\n    llvm::function_ref<SemIR::InstId()> make_import_id)\n    -> AddImportNamespaceToScopeResult;\n\n// Imports the API file's name lookup information into a corresponding\n// implementation file. Only information for the current package will be copied;\n// information for other packages should be handled through\n// ImportLibrariesFromOtherPackage.\nauto ImportApiFile(Context& context, SemIR::TypeId namespace_type_id,\n                   const SemIR::File& api_sem_ir) -> void;\n\n// Add the current package's imports to name lookup. This pulls in all names;\n// conflicts for things such as `package.a.b.c` will be flagged even though they\n// are several layers deep.\nauto ImportLibrariesFromCurrentPackage(\n    Context& context, SemIR::TypeId namespace_type_id,\n    llvm::ArrayRef<SemIR::ImportIR> import_irs) -> void;\n\n// Adds another package's imports to name lookup. This only adds the package\n// name to lookup, so that `package.ImportedPackage` will resolve, and will\n// provide a name scope that can be used for further qualified name lookups.\n//\n// import_irs may be empty. has_load_error is used to indicate if any library in\n// the package failed to import correctly.\nauto ImportLibrariesFromOtherPackage(Context& context,\n                                     SemIR::TypeId namespace_type_id,\n                                     SemIR::InstId import_decl_id,\n                                     PackageNameId package_id,\n                                     llvm::ArrayRef<SemIR::ImportIR> import_irs,\n                                     bool has_load_error) -> void;\n\n// Given a name scope that corresponds to another package (having one or more\n// `import_irs`), looks for the name in imports. Name resolution results are\n// added to the scope, and the `InstId` (possibly `None`) is returned.\n//\n// In general, this will add an `ImportRef` and load it; it's never left\n// unloaded because the result is expected to be immediately used. Namespaces\n// will be directly produced, similar to how they function for imports from the\n// current package. Conflicts will be resolved and diagnosed.\n//\n// Arguments are all in the context of the current IR. Scope lookup is expected\n// to be resolved first.\nauto ImportNameFromOtherPackage(\n    Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id,\n    llvm::ArrayRef<std::pair<SemIR::ImportIRId, SemIR::NameScopeId>>\n        import_ir_scopes,\n    SemIR::NameId name_id) -> SemIR::InstId;\n\nnamespace Internal {\n\n// Checks that the provided imported location has a node kind that is\n// compatible with that of the given instruction.\nauto CheckCompatibleImportedNodeKind(Context& context,\n                                     SemIR::ImportIRInstId imported_loc_id,\n                                     SemIR::InstKind kind) -> void;\n}  // namespace Internal\n\n// Returns a LocIdAndInst for an instruction with an imported location. Checks\n// that the imported location is compatible with the kind of instruction being\n// created.\ntemplate <typename InstT>\n  requires SemIR::Internal::HasNodeId<InstT>\nauto MakeImportedLocIdAndInst(Context& context,\n                              SemIR::ImportIRInstId imported_loc_id, InstT inst)\n    -> SemIR::LocIdAndInst {\n  if constexpr (!SemIR::Internal::HasUntypedNodeId<InstT>) {\n    Internal::CheckCompatibleImportedNodeKind(context, imported_loc_id,\n                                              InstT::Kind);\n  }\n  return SemIR::LocIdAndInst::UncheckedLoc(SemIR::LocId(imported_loc_id), inst);\n}\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_IMPORT_H_\n"
  },
  {
    "path": "toolchain/check/import_ref.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/import_ref.h\"\n\n#include <array>\n#include <optional>\n#include <tuple>\n#include <type_traits>\n#include <utility>\n\n#include \"common/check.h\"\n#include \"common/growing_range.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/base/shared_value_stores.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/import.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/constant.h\"\n#include \"toolchain/sem_ir/file.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/impl.h\"\n#include \"toolchain/sem_ir/import_ir.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/inst_categories.h\"\n#include \"toolchain/sem_ir/inst_kind.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/specific_interface.h\"\n#include \"toolchain/sem_ir/specific_named_constraint.h\"\n#include \"toolchain/sem_ir/type_info.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Adds the ImportIR, excluding the update to the check_ir_map.\nstatic auto InternalAddImportIR(Context& context, SemIR::ImportIR import_ir)\n    -> SemIR::ImportIRId {\n  context.import_ir_constant_values().push_back(SemIR::ConstantValueStore(\n      SemIR::ConstantId::None,\n      import_ir.sem_ir ? &import_ir.sem_ir->insts() : nullptr));\n  return context.import_irs().Add(import_ir);\n}\n\n// Adds a special-cased IR and verifies it received the correct ID.\nstatic auto SetSpecialImportIR(Context& context, SemIR::ImportIR import_ir,\n                               SemIR::ImportIRId expected_import_ir_id)\n    -> void {\n  auto ir_id = SemIR::ImportIRId::None;\n  if (import_ir.sem_ir != nullptr) {\n    ir_id = AddImportIR(context, import_ir);\n  } else {\n    // We don't have a check_ir_id, so add without touching check_ir_map.\n    context.import_ir_constant_values().push_back(\n        SemIR::ConstantValueStore(SemIR::ConstantValueStore::Unusable));\n    ir_id = context.import_irs().Add(import_ir);\n  }\n  CARBON_CHECK(ir_id == expected_import_ir_id,\n               \"Actual ImportIRId ({0}) != Expected ImportIRId ({1})\", ir_id,\n               expected_import_ir_id);\n}\n\nauto SetSpecialImportIRs(Context& context, SemIR::ImportIR import_ir) -> void {\n  SetSpecialImportIR(context, import_ir, SemIR::ImportIRId::ApiForImpl);\n  SetSpecialImportIR(context,\n                     {.decl_id = SemIR::InstId::None, .is_export = false},\n                     SemIR::ImportIRId::Cpp);\n}\n\nauto AddImportIR(Context& context, SemIR::ImportIR import_ir)\n    -> SemIR::ImportIRId {\n  auto& ir_id = context.check_ir_map().Get(import_ir.sem_ir->check_ir_id());\n  if (!ir_id.has_value()) {\n    // Note this updates check_ir_map.\n    ir_id = InternalAddImportIR(context, import_ir);\n  } else if (import_ir.is_export) {\n    // We're processing an `export import`. In case the IR was indirectly added\n    // as a non-export, mark it as an export.\n    context.import_irs().Get(ir_id).is_export = true;\n  }\n  return ir_id;\n}\n\nauto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst,\n                  SemIR::EntityNameId entity_name_id =\n                      SemIR::EntityNameId::None) -> SemIR::InstId {\n  auto import_ir_inst_id = context.import_ir_insts().Add(import_ir_inst);\n  auto import_ref_id = AddPlaceholderImportedInstInNoBlock(\n      context,\n      MakeImportedLocIdAndInst(\n          context, import_ir_inst_id,\n          SemIR::ImportRefUnloaded{.import_ir_inst_id = import_ir_inst_id,\n                                   .entity_name_id = entity_name_id}));\n  return import_ref_id;\n}\n\nstatic auto GetCanonicalImportIRInst(Context& context,\n                                     const SemIR::File* target_ir,\n                                     SemIR::InstId target_inst_id)\n    -> SemIR::ImportIRInst {\n  auto [canonical_ir, canonical_inst_id] =\n      GetCanonicalFileAndInstId(target_ir, target_inst_id);\n\n  auto ir_id = SemIR::ImportIRId::None;\n  if (canonical_ir != &context.sem_ir()) {\n    // This uses AddImportIR in case it was indirectly found, which can\n    // happen with two or more steps of exports.\n    ir_id = AddImportIR(context, {.decl_id = SemIR::InstId::None,\n                                  .is_export = false,\n                                  .sem_ir = canonical_ir});\n  }\n  return SemIR::ImportIRInst(ir_id, canonical_inst_id);\n}\n\nauto GetCanonicalImportIRInst(Context& context, SemIR::InstId inst_id)\n    -> SemIR::ImportIRInst {\n  return GetCanonicalImportIRInst(context, &context.sem_ir(), inst_id);\n}\n\nauto VerifySameCanonicalImportIRInst(Context& context, SemIR::NameId name_id,\n                                     SemIR::InstId prev_id,\n                                     SemIR::ImportIRInst prev_import_ir_inst,\n                                     SemIR::ImportIRId new_ir_id,\n                                     const SemIR::File* new_import_ir,\n                                     SemIR::InstId new_inst_id) -> void {\n  auto new_import_ir_inst =\n      GetCanonicalImportIRInst(context, new_import_ir, new_inst_id);\n  if (new_import_ir_inst == prev_import_ir_inst) {\n    return;\n  }\n  auto conflict_id =\n      AddImportRef(context, SemIR::ImportIRInst(new_ir_id, new_inst_id));\n  // TODO: Pass the imported name location instead of the conflict id.\n  DiagnoseDuplicateName(context, name_id, SemIR::LocId(conflict_id),\n                        SemIR::LocId(prev_id));\n}\n\nnamespace {\n// A context within which we are performing an import. Tracks information about\n// the source and destination. This provides a restricted interface compared to\n// ImportResolver: in particular, it does not have access to a work list.\n// Therefore code that accepts an ImportContext is unable to enqueue new work.\nclass ImportContext {\n public:\n  // `context` must not be null.\n  explicit ImportContext(Context* context, SemIR::ImportIRId import_ir_id)\n      : context_(context),\n        import_ir_id_(import_ir_id),\n        import_ir_(*context_->import_irs().Get(import_ir_id).sem_ir) {}\n\n  // Returns the file we are importing from.\n  auto import_ir() -> const SemIR::File& { return import_ir_; }\n\n  // Accessors into value stores of the file we are importing from.\n  auto import_associated_constants() -> const SemIR::AssociatedConstantStore& {\n    return import_ir().associated_constants();\n  }\n  auto import_classes() -> const SemIR::ClassStore& {\n    return import_ir().classes();\n  }\n  auto import_vtables() -> const SemIR::VtableStore& {\n    return import_ir().vtables();\n  }\n  auto import_constant_values() -> const SemIR::ConstantValueStore& {\n    return import_ir().constant_values();\n  }\n  auto import_entity_names() -> const SemIR::EntityNameStore& {\n    return import_ir().entity_names();\n  }\n  auto import_facet_types() -> const SemIR::FacetTypeInfoStore& {\n    return import_ir().facet_types();\n  }\n  auto import_functions() -> const SemIR::FunctionStore& {\n    return import_ir().functions();\n  }\n  auto import_generics() -> const SemIR::GenericStore& {\n    return import_ir().generics();\n  }\n  auto import_identifiers() -> const SharedValueStores::IdentifierStore& {\n    return import_ir().identifiers();\n  }\n  auto import_impls() -> const SemIR::ImplStore& { return import_ir().impls(); }\n  auto import_inst_blocks() -> const SemIR::InstBlockStore& {\n    return import_ir().inst_blocks();\n  }\n  auto import_insts() -> const SemIR::InstStore& { return import_ir().insts(); }\n  auto import_interfaces() -> const SemIR::InterfaceStore& {\n    return import_ir().interfaces();\n  }\n  auto import_named_constraints() -> const SemIR::NamedConstraintStore& {\n    return import_ir().named_constraints();\n  }\n  auto import_ints() -> const SharedValueStores::IntStore& {\n    return import_ir().ints();\n  }\n  auto import_name_scopes() -> const SemIR::NameScopeStore& {\n    return import_ir().name_scopes();\n  }\n  auto import_require_impls() -> const SemIR::RequireImplsStore& {\n    return import_ir().require_impls();\n  }\n  auto import_require_impls_blocks() -> const SemIR::RequireImplsBlockStore& {\n    return import_ir().require_impls_blocks();\n  }\n  auto import_specifics() -> const SemIR::SpecificStore& {\n    return import_ir().specifics();\n  }\n  auto import_specific_interfaces() -> const SemIR::SpecificInterfaceStore& {\n    return import_ir().specific_interfaces();\n  }\n  auto import_string_literal_values()\n      -> const SharedValueStores::StringLiteralStore& {\n    return import_ir().string_literal_values();\n  }\n  auto import_struct_type_fields() -> const SemIR::StructTypeFieldsStore& {\n    return import_ir().struct_type_fields();\n  }\n  auto import_types() -> const SemIR::TypeStore& { return import_ir().types(); }\n\n  // Returns the local file's import ID for the IR we are importing from.\n  auto import_ir_id() -> SemIR::ImportIRId { return import_ir_id_; }\n\n  // A value store for local constant values of imported instructions. This maps\n  // from `InstId`s in the import IR to corresponding `ConstantId`s in the local\n  // IR.\n  auto local_constant_values_for_import_insts() -> SemIR::ConstantValueStore& {\n    auto index = local_ir().import_irs().GetRawIndex(import_ir_id_);\n    return local_context().import_ir_constant_values()[index];\n  }\n\n  // Returns the file we are importing into.\n  auto local_ir() -> SemIR::File& { return context_->sem_ir(); }\n\n  // Returns the type-checking context we are importing into.\n  auto local_context() -> Context& { return *context_; }\n\n  // Accessors into value stores of the file we are importing into.\n  auto local_associated_constants() -> SemIR::AssociatedConstantStore& {\n    return local_ir().associated_constants();\n  }\n  auto local_classes() -> SemIR::ClassStore& { return local_ir().classes(); }\n  auto local_vtables() -> SemIR::VtableStore& { return local_ir().vtables(); }\n  auto local_constant_values() -> SemIR::ConstantValueStore& {\n    return local_ir().constant_values();\n  }\n  auto local_entity_names() -> SemIR::EntityNameStore& {\n    return local_ir().entity_names();\n  }\n  auto local_facet_types() -> SemIR::FacetTypeInfoStore& {\n    return local_ir().facet_types();\n  }\n  auto local_functions() -> SemIR::FunctionStore& {\n    return local_ir().functions();\n  }\n  auto local_generics() -> SemIR::GenericStore& {\n    return local_ir().generics();\n  }\n  auto local_identifiers() -> SharedValueStores::IdentifierStore& {\n    return local_ir().identifiers();\n  }\n  auto local_impls() -> SemIR::ImplStore& { return local_ir().impls(); }\n  auto local_import_ir_insts() -> SemIR::ImportIRInstStore& {\n    return local_ir().import_ir_insts();\n  }\n  auto local_inst_blocks() -> SemIR::InstBlockStore& {\n    return local_ir().inst_blocks();\n  }\n  auto local_insts() -> SemIR::InstStore& { return local_ir().insts(); }\n  auto local_interfaces() -> SemIR::InterfaceStore& {\n    return local_ir().interfaces();\n  }\n  auto local_named_constraints() -> SemIR::NamedConstraintStore& {\n    return local_ir().named_constraints();\n  }\n  auto local_ints() -> SharedValueStores::IntStore& {\n    return local_ir().ints();\n  }\n  auto local_name_scopes() -> SemIR::NameScopeStore& {\n    return local_ir().name_scopes();\n  }\n  auto local_require_impls() -> SemIR::RequireImplsStore& {\n    return local_ir().require_impls();\n  }\n  auto local_require_impls_blocks() -> SemIR::RequireImplsBlockStore& {\n    return local_ir().require_impls_blocks();\n  }\n  auto local_specifics() -> SemIR::SpecificStore& {\n    return local_ir().specifics();\n  }\n  auto local_specific_interfaces() -> SemIR::SpecificInterfaceStore& {\n    return local_ir().specific_interfaces();\n  }\n  auto local_string_literal_values() -> SharedValueStores::StringLiteralStore& {\n    return local_ir().string_literal_values();\n  }\n  auto local_struct_type_fields() -> SemIR::StructTypeFieldsStore& {\n    return local_ir().struct_type_fields();\n  }\n  auto local_types() -> SemIR::TypeStore& { return local_ir().types(); }\n\n private:\n  Context* context_;\n  SemIR::ImportIRId import_ir_id_;\n  const SemIR::File& import_ir_;\n};\n\n// Resolves an instruction from an imported IR into a constant referring to the\n// current IR.\n//\n// Calling Resolve on an instruction operates in an iterative manner, tracking\n// Work items on work_stack_. At a high level, the loop is:\n//\n// 1. If a constant value is already known for the work item and was not set by\n//    this work item, it's considered resolved.\n//    - The constant check avoids performance costs of deduplication on add.\n//    - If we've processed this work item before, then we now process it again.\n//      It didn't complete last time, even though we have a constant value\n//      already.\n//\n// 2. Resolve the instruction (TryResolveInst/TryResolveTypedInst). This is done\n//    in three phases. The first and second phases can add work to the worklist\n//    and end in a retry, in which case those phases will be rerun once the\n//    added work is done. The rerun cannot also end in a retry, so this results\n//    in at most three calls, but in practice one or two calls is almost always\n//    sufficient. Due to the chance of a second or third call to TryResolveInst,\n//    it's important to only perform expensive work once, even when the same\n//    phase is rerun.\n//\n//    - First phase:\n//      - Gather all input constants necessary to form the constant value of the\n//        instruction. Gathering constants directly adds unresolved values to\n//        work_stack_.\n//      - If HasNewWork() reports that any work was added, then return Retry():\n//        this instruction needs another call to complete. Gather the\n//        now-resolved constants and continue to the next step once the retry\n//        happens.\n//\n//    - Second phase:\n//      - Build the constant value of the instruction.\n//      - Gather all input constants necessary to finish importing the\n//        instruction. This is only necessary for instructions like classes that\n//        can be forward-declared. For these instructions, we first import the\n//        constant value and then later import the rest of the declaration in\n//        order to break cycles.\n//      - If HasNewWork() reports that any work was added, then return\n//        Retry(constant_value): this instruction needs another call to\n//        complete.  Gather the now-resolved constants and continue to the next\n//        step once the retry happens.\n//\n//    - Third phase:\n//      - After the second phase, the constant value for the instruction is\n//        already set, and will be passed back into TryResolve*Inst on retry. It\n//        should not be created again.\n//      - Fill in any remaining information to complete the import of the\n//        instruction. For example, when importing a class declaration, build\n//        the class scope and information about the definition.\n//      - Return Done() to finish the resolution process. This will cause the\n//        Resolve loop to set a constant value if we didn't retry at the end of\n//        the second phase.\n//\n//    In the common case where the second phase cannot add new work (because the\n//    inst doesn't represent a declaration of an entity that can be forward\n//    declared), the second and third phases are usually expressed as a call to\n//    ResolveResult::Deduplicated or ResolveResult::Unique.\n//\n// 3. If resolve didn't return Retry(), pop the work. Otherwise, it needs to\n//    remain, and may no longer be at the top of the stack; update the state of\n//    the work item to track what work still needs to be done.\n//\n// The same instruction can be enqueued for resolution multiple times. However,\n// we will only reach the second phase once: once a constant value is set, only\n// the resolution step that set it will retry.\n//\n// TODO: Fix class `extern` handling and merging, rewrite tests.\n// - check/testdata/class/cross_package_import.carbon\n// - check/testdata/class/extern.carbon\n// TODO: Fix function `extern` handling and merging, rewrite tests.\n// - check/testdata/function/declaration/import.carbon\n// - check/testdata/packages/cross_package_import.carbon\nclass ImportRefResolver : public ImportContext {\n public:\n  // `context` must not be null.\n  explicit ImportRefResolver(Context* context, SemIR::ImportIRId import_ir_id)\n      : ImportContext(context, import_ir_id) {}\n\n  // Iteratively resolves an imported instruction's inner references until a\n  // constant ID referencing the current IR is produced. See the class comment\n  // for more details.\n  auto Resolve(SemIR::InstId inst_id) -> SemIR::ConstantId;\n\n  // Wraps constant evaluation with logic to handle constants.\n  auto ResolveConstant(SemIR::ConstantId import_const_id) -> SemIR::ConstantId;\n\n  // Wraps constant evaluation with logic to handle types.\n  auto ResolveType(SemIR::TypeId import_type_id) -> SemIR::TypeId;\n\n  // Returns true if new unresolved constants were found as part of this\n  // `Resolve` step.\n  auto HasNewWork() -> bool;\n\n  // Pushes a specific onto the work stack. This will only process when the\n  // current instruction is done, and does not count towards `HasNewWork`. We\n  // add specifics this way because some instructions (e.g. `FacetTypeInfo`) can\n  // add multiple specifics.\n  //\n  // The insert may do extra work moving already-added work on the work stack,\n  // but that is expected to be okay because the common cases are 0 or 1\n  // specifics being added. If this ends up showing up in profiles, potentially\n  // due to vector growth, it may be worth revisiting.\n  auto PushSpecific(SemIR::SpecificId import_id, SemIR::SpecificId local_id)\n      -> void;\n\n  // Returns the ConstantId for an InstId. Adds unresolved constants to\n  // work_stack_.\n  auto GetLocalConstantValueOrPush(SemIR::InstId inst_id) -> SemIR::ConstantId;\n\n private:\n  // An instruction to import.\n  struct InstWork {\n    // The instruction to work on.\n    SemIR::InstId inst_id;\n    // Whether this work item set the constant value for the instruction and\n    // requested a retry.\n    bool retry_with_constant_value = false;\n  };\n\n  // A generic to import.\n  struct GenericWork {\n    SemIR::GenericId import_id;\n    SemIR::GenericId local_id;\n  };\n\n  // A specific to import.\n  struct SpecificWork {\n    SemIR::SpecificId import_id;\n    SemIR::SpecificId local_id;\n  };\n\n  // The constant found by FindResolvedConstId.\n  struct ResolvedConstId {\n    // The constant for the instruction. `None` if not yet resolved.\n    SemIR::ConstantId const_id = SemIR::ConstantId::None;\n\n    // Instructions which are indirect but equivalent to the current instruction\n    // being resolved, and should have their constant set to the same. Empty\n    // when `const_id` has a value.\n    llvm::SmallVector<SemIR::ImportIRInst> indirect_insts = {};\n  };\n\n  // Looks to see if an instruction has been resolved. If a constant is only\n  // found indirectly, sets the constant for any indirect steps that don't\n  // already have the constant. If a constant isn't found, returns the indirect\n  // instructions so that they can have the resolved constant assigned later.\n  auto FindResolvedConstId(SemIR::InstId inst_id) -> ResolvedConstId;\n\n  // Sets a resolved constant into the current and indirect instructions.\n  auto SetResolvedConstId(SemIR::InstId inst_id,\n                          llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,\n                          SemIR::ConstantId const_id) -> void;\n\n  llvm::SmallVector<std::variant<InstWork, GenericWork, SpecificWork>>\n      work_stack_;\n  // The size of work_stack_ at the start of resolving the current instruction.\n  size_t initial_work_ = 0;\n};\n}  // namespace\n\n// Wrapper for `AddImportRef` that provides the `import_ir_id`.\nstatic auto AddImportRef(ImportContext& context, SemIR::InstId inst_id,\n                         SemIR::EntityNameId entity_name_id =\n                             SemIR::EntityNameId::None) -> SemIR::InstId {\n  if (!inst_id.has_value()) {\n    return SemIR::InstId::None;\n  }\n  return AddImportRef(context.local_context(),\n                      SemIR::ImportIRInst(context.import_ir_id(), inst_id),\n                      entity_name_id);\n}\n\n// Handles setting a constant on instructions related to an import.\nstatic auto SetIndirectConstantValues(\n    Context& context, llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,\n    SemIR::ConstantId constant_id) -> void {\n  for (const auto& import_ir_inst : indirect_insts) {\n    auto ir_index =\n        context.sem_ir().import_irs().GetRawIndex(import_ir_inst.ir_id());\n    context.import_ir_constant_values()[ir_index].Set(import_ir_inst.inst_id(),\n                                                      constant_id);\n  }\n}\n\n// Adds an import_ref instruction for an instruction that we have already loaded\n// from an imported IR, with a known constant value. This is useful when the\n// instruction has a symbolic constant value, in order to produce an instruction\n// that holds that symbolic constant.\nstatic auto AddLoadedImportRef(ImportContext& context,\n                               SemIR::TypeId local_type_id,\n                               SemIR::InstId import_inst_id,\n                               SemIR::ConstantId local_const_id)\n    -> SemIR::InstId {\n  auto import_ir_inst_id = context.local_import_ir_insts().Add(\n      SemIR::ImportIRInst(context.import_ir_id(), import_inst_id));\n  SemIR::ImportRefLoaded inst = {.type_id = local_type_id,\n                                 .import_ir_inst_id = import_ir_inst_id,\n                                 .entity_name_id = SemIR::EntityNameId::None};\n  auto inst_id = AddPlaceholderImportedInstInNoBlock(\n      context.local_context(),\n      MakeImportedLocIdAndInst(context.local_context(), import_ir_inst_id,\n                               inst));\n\n  context.local_constant_values().Set(inst_id, local_const_id);\n  context.local_constant_values_for_import_insts().Set(import_inst_id,\n                                                       local_const_id);\n  return inst_id;\n}\n\n// Like `AddLoadedImportRef`, but only for types, and returns a `TypeInstId`.\nstatic auto AddLoadedImportRefForType(ImportContext& context,\n                                      SemIR::TypeInstId import_inst_id,\n                                      SemIR::ConstantId local_const_id)\n    -> SemIR::TypeInstId {\n  return context.local_types().GetAsTypeInstId(AddLoadedImportRef(\n      context, SemIR::TypeType::TypeId, import_inst_id, local_const_id));\n}\n\nstatic auto AddImportIRInst(ImportContext& context, SemIR::InstId inst_id)\n    -> SemIR::ImportIRInstId {\n  return context.local_import_ir_insts().Add(\n      SemIR::ImportIRInst(context.import_ir_id(), inst_id));\n}\n\n// Computes, sets, and returns the constant value for an instruction.\nstatic auto SetConstantValue(Context& context, SemIR::InstId inst_id,\n                             SemIR::Inst inst) -> SemIR::ConstantId {\n  auto const_id = TryEvalInstUnsafe(context, inst_id, inst);\n  if (const_id.is_constant()) {\n    CARBON_VLOG_TO(context.vlog_stream(), \"Constant: {0} -> {1}\\n\", inst,\n                   context.constant_values().GetInstId(const_id));\n  }\n  context.constant_values().Set(inst_id, const_id);\n  return const_id;\n}\n\n// Adds an imported instruction without setting its constant value. The\n// instruction should later be updated by either `SetConstantValue` or\n// `ReplacePlaceholderImportedInst`.\ntemplate <typename InstT>\nstatic auto AddPlaceholderImportedInst(ImportContext& context,\n                                       SemIR::InstId import_inst_id, InstT inst)\n    -> SemIR::InstId {\n  auto import_ir_inst_id = AddImportIRInst(context, import_inst_id);\n  return AddPlaceholderImportedInstInNoBlock(\n      context.local_context(),\n      MakeImportedLocIdAndInst(context.local_context(), import_ir_inst_id,\n                               inst));\n}\n\n// Replace an imported instruction that was added by\n// `AddPlaceholderImportedInst` with a new instruction. Computes, sets, and\n// returns the new constant value.\nstatic auto ReplacePlaceholderImportedInst(ImportContext& context,\n                                           SemIR::InstId inst_id,\n                                           SemIR::Inst inst)\n    -> SemIR::ConstantId {\n  CARBON_VLOG_TO(context.local_context().vlog_stream(),\n                 \"ReplaceImportedInst: {0} -> {1}\\n\", inst_id, inst);\n  context.local_insts().Set(inst_id, inst);\n\n  CARBON_CHECK(context.local_constant_values().Get(inst_id) ==\n               SemIR::ConstantId::None);\n  return SetConstantValue(context.local_context(), inst_id, inst);\n}\n\n// Returns the ConstantId for an InstId. Adds unresolved constants to\n// the resolver's work stack.\nstatic auto GetLocalConstantId(ImportRefResolver& resolver,\n                               SemIR::InstId inst_id) -> SemIR::ConstantId {\n  return resolver.GetLocalConstantValueOrPush(inst_id);\n}\n\n// Returns the ConstantId for an imported ConstantId. Adds unresolved\n// constants to the resolver's work stack.\nstatic auto GetLocalConstantId(ImportRefResolver& resolver,\n                               SemIR::ConstantId const_id)\n    -> SemIR::ConstantId {\n  return GetLocalConstantId(\n      resolver, GetInstWithConstantValue(resolver.import_ir(), const_id));\n}\n\n// Returns the local constant InstId for an imported InstId.\nstatic auto GetLocalConstantInstId(ImportRefResolver& resolver,\n                                   SemIR::InstId inst_id) -> SemIR::InstId {\n  auto const_id = GetLocalConstantId(resolver, inst_id);\n  return resolver.local_constant_values().GetInstIdIfValid(const_id);\n}\n\n// Returns the local constant InstId for an imported InstId.\nstatic auto GetLocalTypeInstId(ImportRefResolver& resolver,\n                               SemIR::TypeInstId inst_id) -> SemIR::TypeInstId {\n  // The input instruction is a TypeInstId, and import does not change the type\n  // of instructions, so the result is also a valid TypeInstId.\n  return SemIR::TypeInstId::UnsafeMake(\n      GetLocalConstantInstId(resolver, inst_id));\n}\n\n// Returns the ConstantId for a TypeId. Adds unresolved constants to\n// work_stack_.\nstatic auto GetLocalConstantId(ImportRefResolver& resolver,\n                               SemIR::TypeId type_id) -> SemIR::ConstantId {\n  return GetLocalConstantId(resolver,\n                            resolver.import_types().GetConstantId(type_id));\n}\n\n// Translates a NameId from the import IR to a local NameId.\n//\n// No new work is generated by calling this function.\nstatic auto GetLocalNameId(ImportContext& context, SemIR::NameId import_name_id)\n    -> SemIR::NameId {\n  if (auto ident_id = import_name_id.AsIdentifierId(); ident_id.has_value()) {\n    return SemIR::NameId::ForIdentifier(context.local_identifiers().Add(\n        context.import_identifiers().Get(ident_id)));\n  }\n  return import_name_id;\n}\n\n// Returns the id for a local symbolic EntityName from an imported one,\n// preserving only the `NameId`, the `CompileTimeBindIndex`, and whether it is a\n// template. Other parts of the EntityName are not kept and are not considered\n// part of the canonical EntityName (even if they are present there).\n//\n// No new work is generated by calling this function.\nstatic auto GetLocalSymbolicEntityNameId(\n    ImportContext& context, SemIR::EntityNameId import_entity_name_id)\n    -> SemIR::EntityNameId {\n  const auto& import_entity_name =\n      context.import_entity_names().Get(import_entity_name_id);\n  auto name_id = GetLocalNameId(context, import_entity_name.name_id);\n  return context.local_entity_names().AddSymbolicBindingName(\n      name_id, SemIR::NameScopeId::None, import_entity_name.bind_index(),\n      import_entity_name.is_template, import_entity_name.is_unused);\n}\n\n// Gets the local constant values corresponding to an imported inst block.\nstatic auto GetLocalInstBlockContents(ImportRefResolver& resolver,\n                                      SemIR::InstBlockId import_block_id)\n    -> llvm::SmallVector<SemIR::InstId> {\n  llvm::SmallVector<SemIR::InstId> inst_ids;\n  if (!import_block_id.has_value() ||\n      import_block_id == SemIR::InstBlockId::Empty) {\n    return inst_ids;\n  }\n\n  // Import all the values in the block.\n  auto import_block = resolver.import_inst_blocks().Get(import_block_id);\n  inst_ids.reserve(import_block.size());\n  for (auto import_inst_id : import_block) {\n    inst_ids.push_back(GetLocalConstantInstId(resolver, import_inst_id));\n  }\n\n  return inst_ids;\n}\n\n// Gets a local canonical instruction block ID corresponding to an imported inst\n// block whose contents were already imported, for example by\n// GetLocalInstBlockContents.\nstatic auto GetLocalCanonicalInstBlockId(ImportContext& context,\n                                         SemIR::InstBlockId import_block_id,\n                                         llvm::ArrayRef<SemIR::InstId> contents)\n    -> SemIR::InstBlockId {\n  if (!import_block_id.has_value()) {\n    return SemIR::InstBlockId::None;\n  }\n  return context.local_inst_blocks().AddCanonical(contents);\n}\n\n// Imports the RequireImplsDecl instructions for each RequireImplsId in the\n// block, and gets the local RequireImplsIds from them. The returned vector is\n// only complete if there is no more work to do in the resolver on return.\nstatic auto GetLocalRequireImplsBlockContents(\n    ImportRefResolver& resolver, SemIR::RequireImplsBlockId import_block_id)\n    -> llvm::SmallVector<SemIR::RequireImplsId> {\n  llvm::SmallVector<SemIR::RequireImplsId> require_decl_ids;\n  if (!import_block_id.has_value() ||\n      import_block_id == SemIR::RequireImplsBlockId::Empty) {\n    return require_decl_ids;\n  }\n\n  // Import the RequireImplsDecl for each RequireImpls in the block.\n  auto import_block =\n      resolver.import_require_impls_blocks().Get(import_block_id);\n  require_decl_ids.reserve(import_block.size());\n  for (auto import_require_impls_id : import_block) {\n    const auto& import_require =\n        resolver.import_require_impls().Get(import_require_impls_id);\n    auto local_decl_id =\n        GetLocalConstantInstId(resolver, import_require.decl_id);\n    // If `local_decl_id` is None, the resolver will have more work to do, and\n    // we will call this function to try get all the decl instructions again.\n    if (local_decl_id.has_value()) {\n      // Importing the RequireImplsDecl instruction in `local_decl_id` also\n      // imported the RequireImpls structure that it points to through the\n      // RequireImplsId.\n      require_decl_ids.push_back(\n          resolver.local_insts()\n              .GetAs<SemIR::RequireImplsDecl>(local_decl_id)\n              .require_impls_id);\n    }\n  }\n\n  return require_decl_ids;\n}\n\n// Gets the local block of RequireImplsIds from the imported block. Only valid\n// to call once there is no more work to do after the call to\n// GetLocalRequireImplsBlockContents().\nstatic auto GetLocalCanonicalRequireImplsBlockId(\n    ImportContext& context, SemIR::RequireImplsBlockId import_block_id,\n    llvm::ArrayRef<SemIR::RequireImplsId> contents)\n    -> SemIR::RequireImplsBlockId {\n  if (!import_block_id.has_value()) {\n    return SemIR::RequireImplsBlockId::None;\n  }\n  return context.local_require_impls_blocks().Add(contents);\n}\n\n// Gets a local instruction block containing ImportRefs referring to the\n// instructions in the specified imported instruction block.\nstatic auto GetLocalImportRefInstBlock(ImportContext& context,\n                                       SemIR::InstBlockId import_inst_block_id)\n    -> SemIR::InstBlockId {\n  llvm::SmallVector<SemIR::InstId> elements;\n  auto import_elements = context.import_inst_blocks().Get(import_inst_block_id);\n  elements.reserve(import_elements.size());\n  for (auto element : import_elements) {\n    elements.push_back(AddImportRef(context, element));\n  }\n  return context.local_inst_blocks().Add(elements);\n}\n\n// Gets an incomplete local version of an imported generic. Most fields are\n// set in the third phase.\nstatic auto ImportIncompleteGeneric(ImportContext& context,\n                                    SemIR::InstId decl_id,\n                                    SemIR::GenericId generic_id)\n    -> SemIR::GenericId {\n  if (!generic_id.has_value()) {\n    return SemIR::GenericId::None;\n  }\n\n  return context.local_generics().Add(\n      {.decl_id = decl_id,\n       .bindings_id = SemIR::InstBlockId::None,\n       .self_specific_id = SemIR::SpecificId::None});\n}\n\nnamespace {\n// Local information associated with an imported generic.\nstruct GenericData {\n  struct Binding {\n    // The attached type's constant, which may differ from the type on the\n    // constant. This needs to be preserved for the ImportRef.\n    SemIR::ConstantId type_constant_id;\n    SemIR::ConstantId inst_constant_id;\n  };\n  llvm::SmallVector<Binding> bindings;\n\n  llvm::SmallVector<SemIR::InstId> decl_block;\n};\n}  // namespace\n\n// Gets a local version of the data associated with a generic. This is processed\n// through `ResolveResult::FinishGenericOrDone`.\nstatic auto GetLocalGenericData(ImportRefResolver& resolver,\n                                SemIR::GenericId import_generic_id)\n    -> GenericData {\n  GenericData generic_data;\n  if (import_generic_id.has_value()) {\n    const auto& import_generic =\n        resolver.import_generics().Get(import_generic_id);\n\n    if (import_generic.bindings_id.has_value()) {\n      auto import_bindings =\n          resolver.import_inst_blocks().Get(import_generic.bindings_id);\n      generic_data.bindings.reserve(import_bindings.size());\n      for (auto import_inst_id : import_bindings) {\n        generic_data.bindings.push_back(\n            {.type_constant_id = GetLocalConstantId(\n                 resolver,\n                 resolver.import_insts().GetAttachedType(import_inst_id)),\n             .inst_constant_id = GetLocalConstantId(resolver, import_inst_id)});\n      }\n    }\n\n    generic_data.decl_block =\n        GetLocalInstBlockContents(resolver, import_generic.decl_block_id);\n  }\n  return generic_data;\n}\n\n// Rebuilds an eval block and sets locations.\n// TODO: Import the generic eval block rather than calling\n// RebuildGenericEvalBlock to rebuild it.\nstatic auto ResolveLocalEvalBlock(ImportContext& context,\n                                  SemIR::InstBlockId import_block_id,\n                                  llvm::ArrayRef<SemIR::InstId> local_block,\n                                  SemIR::GenericId generic_id,\n                                  SemIR::GenericInstIndex::Region region)\n    -> SemIR::InstBlockId {\n  auto eval_block_id = RebuildGenericEvalBlock(context.local_context(),\n                                               generic_id, region, local_block);\n\n  // Set the locations of the instructions in the inst block to match those of\n  // the imported instructions.\n  for (auto [import_inst_id, local_inst_id] :\n       llvm::zip_equal(context.import_inst_blocks().Get(import_block_id),\n                       context.local_inst_blocks().Get(eval_block_id))) {\n    auto import_ir_inst_id = AddImportIRInst(context, import_inst_id);\n    context.local_insts().SetLocId(local_inst_id, import_ir_inst_id);\n  }\n  return eval_block_id;\n}\n\n// Adds the given local generic data to the given generic. This should only be\n// called by `ResolveResult`.\nstatic auto SetGenericDataForResolveResult(ImportContext& context,\n                                           SemIR::GenericId import_generic_id,\n                                           SemIR::GenericId new_generic_id,\n                                           const GenericData& generic_data)\n    -> void {\n  if (!import_generic_id.has_value()) {\n    return;\n  }\n\n  const auto& import_generic = context.import_generics().Get(import_generic_id);\n  auto& new_generic = context.local_generics().Get(new_generic_id);\n\n  auto import_bindings =\n      context.import_inst_blocks().Get(import_generic.bindings_id);\n  llvm::SmallVector<SemIR::InstId> new_bindings;\n  new_bindings.reserve(import_bindings.size());\n  for (auto [import_binding_id, binding] :\n       llvm::zip_equal(import_bindings, generic_data.bindings)) {\n    auto local_type_id = context.local_types().GetTypeIdForTypeConstantId(\n        binding.type_constant_id);\n    new_bindings.push_back(AddLoadedImportRef(\n        context, local_type_id, import_binding_id, binding.inst_constant_id));\n  }\n  new_generic.bindings_id = context.local_inst_blocks().Add(new_bindings);\n\n  new_generic.decl_block_id = ResolveLocalEvalBlock(\n      context, import_generic.decl_block_id, generic_data.decl_block,\n      new_generic_id, SemIR::GenericInstIndex::Region::Declaration);\n}\n\n// Gets a local constant value corresponding to an imported generic ID. May\n// add work to the work stack and return `None`.\nstatic auto GetLocalConstantId(ImportRefResolver& resolver,\n                               SemIR::GenericId generic_id)\n    -> SemIR::ConstantId {\n  if (!generic_id.has_value()) {\n    return SemIR::ConstantId::None;\n  }\n  auto import_decl_inst_id = resolver.import_generics().Get(generic_id).decl_id;\n  auto import_decl_inst =\n      resolver.import_insts().GetWithAttachedType(import_decl_inst_id);\n  if (import_decl_inst.IsOneOf<SemIR::ImplDecl, SemIR::InterfaceWithSelfDecl,\n                               SemIR::NamedConstraintWithSelfDecl,\n                               SemIR::RequireImplsDecl>()) {\n    // For these decl types, the imported entity can be found via the\n    // declaration's operands.\n    return GetLocalConstantId(resolver, import_decl_inst_id);\n  }\n  // For all other kinds of declaration, the imported entity can be found via\n  // the type of the declaration.\n  CARBON_CHECK(import_decl_inst.type_id().has_value());\n  return GetLocalConstantId(resolver, import_decl_inst.type_id());\n}\n\n// Gets a local generic ID given the corresponding local constant ID returned\n// by GetLocalConstantId for the imported generic. Does not add any new work.\nstatic auto GetLocalGenericId(ImportContext& context,\n                              SemIR::ConstantId local_const_id)\n    -> SemIR::GenericId {\n  if (!local_const_id.has_value()) {\n    return SemIR::GenericId::None;\n  }\n  auto inst = context.local_insts().Get(\n      context.local_constant_values().GetInstId(local_const_id));\n  CARBON_KIND_SWITCH(inst) {\n    case CARBON_KIND(SemIR::FunctionType fn_type): {\n      return context.local_functions().Get(fn_type.function_id).generic_id;\n    }\n    case CARBON_KIND(SemIR::GenericClassType class_type): {\n      return context.local_classes().Get(class_type.class_id).generic_id;\n    }\n    case CARBON_KIND(SemIR::GenericInterfaceType interface_type): {\n      return context.local_interfaces()\n          .Get(interface_type.interface_id)\n          .generic_id;\n    }\n    case CARBON_KIND(SemIR::GenericNamedConstraintType constraint_type): {\n      return context.local_named_constraints()\n          .Get(constraint_type.named_constraint_id)\n          .generic_id;\n    }\n    case CARBON_KIND(SemIR::ImplDecl impl_decl): {\n      return context.local_impls().Get(impl_decl.impl_id).generic_id;\n    }\n    case CARBON_KIND(SemIR::InterfaceWithSelfDecl interface_with_self_decl): {\n      return context.local_interfaces()\n          .Get(interface_with_self_decl.interface_id)\n          .generic_with_self_id;\n    }\n    case CARBON_KIND(\n        SemIR::NamedConstraintWithSelfDecl constraint_with_self_decl): {\n      return context.local_named_constraints()\n          .Get(constraint_with_self_decl.named_constraint_id)\n          .generic_with_self_id;\n    }\n    case CARBON_KIND(SemIR::RequireImplsDecl require_decl): {\n      return context.local_require_impls()\n          .Get(require_decl.require_impls_id)\n          .generic_id;\n    }\n    default: {\n      CARBON_FATAL(\"Unexpected inst for generic declaration: {0}\", inst);\n    }\n  }\n}\n\nnamespace {\n// Local information associated with an imported specific.\nstruct SpecificData {\n  SemIR::ConstantId generic_const_id;\n  llvm::SmallVector<SemIR::InstId> args;\n};\n}  // namespace\n\n// Gets local information about an imported specific.\nstatic auto GetLocalSpecificData(ImportRefResolver& resolver,\n                                 SemIR::SpecificId specific_id)\n    -> SpecificData {\n  if (!specific_id.has_value()) {\n    return {.generic_const_id = SemIR::ConstantId::None, .args = {}};\n  }\n\n  const auto& specific = resolver.import_specifics().Get(specific_id);\n  return {\n      .generic_const_id = GetLocalConstantId(resolver, specific.generic_id),\n      .args = GetLocalInstBlockContents(resolver, specific.args_id),\n  };\n}\n\n// True for an already-imported specific.\nstatic auto IsSpecificImported(const SemIR::Specific& import_specific,\n                               const SemIR::Specific& local_specific) -> bool {\n  return local_specific.decl_block_id.has_value() &&\n         (local_specific.definition_block_id.has_value() ||\n          !import_specific.definition_block_id.has_value());\n}\n\n// Gets a local specific whose data was already imported by\n// GetLocalSpecificData. This can add work through `PushSpecific`, but callers\n// shouldn't need to consider that because specifics are processed after the\n// current instruction.\n//\n// `local_generic_id` is provided when this is used for a generic's `self`\n// specific, where `GetLocalGenericId` won't work because `generic_const_id` can\n// be `TypeType`.\nstatic auto GetOrAddLocalSpecific(\n    ImportRefResolver& resolver, SemIR::SpecificId import_specific_id,\n    const SpecificData& data,\n    SemIR::GenericId local_generic_id = SemIR::GenericId::None)\n    -> SemIR::SpecificId {\n  if (!import_specific_id.has_value()) {\n    return SemIR::SpecificId::None;\n  }\n\n  // Form a corresponding local specific ID.\n  const auto& import_specific =\n      resolver.import_specifics().Get(import_specific_id);\n  if (!local_generic_id.has_value()) {\n    local_generic_id = GetLocalGenericId(resolver, data.generic_const_id);\n  }\n  auto args_id = GetLocalCanonicalInstBlockId(resolver, import_specific.args_id,\n                                              data.args);\n\n  // Get the specific.\n  auto local_specific_id =\n      resolver.local_specifics().GetOrAdd(local_generic_id, args_id);\n\n  if (!IsSpecificImported(import_specific,\n                          resolver.local_specifics().Get(local_specific_id))) {\n    // Enqueue the specific to fill in remaining fields.\n    resolver.PushSpecific(import_specific_id, local_specific_id);\n  }\n  return local_specific_id;\n}\n\n// Given a generic that's gone through the initial setup with `GenericData`,\n// finish the import.\nstatic auto TryFinishGeneric(ImportRefResolver& resolver,\n                             SemIR::GenericId import_generic_id,\n                             SemIR::GenericId local_generic_id) -> bool {\n  const auto& import_generic =\n      resolver.import_generics().Get(import_generic_id);\n\n  auto specific_data =\n      GetLocalSpecificData(resolver, import_generic.self_specific_id);\n  llvm::SmallVector<SemIR::InstId> definition_block;\n  if (import_generic.definition_block_id.has_value()) {\n    definition_block =\n        GetLocalInstBlockContents(resolver, import_generic.definition_block_id);\n  }\n\n  if (resolver.HasNewWork()) {\n    return false;\n  }\n\n  auto& local_generic = resolver.local_generics().Get(local_generic_id);\n  CARBON_CHECK(!local_generic.self_specific_id.has_value(),\n               \"Currently assuming we can't find a GenericId multiple ways\");\n\n  local_generic.self_specific_id =\n      GetOrAddLocalSpecific(resolver, import_generic.self_specific_id,\n                            specific_data, local_generic_id);\n\n  if (import_generic.definition_block_id.has_value()) {\n    local_generic.definition_block_id = ResolveLocalEvalBlock(\n        resolver, import_generic.definition_block_id, definition_block,\n        local_generic_id, SemIR::GenericInstIndex::Region::Definition);\n  }\n  return true;\n}\n\n// Given a specific that's gone through the initial setup with `SpecificData`,\n// finish the import.\nstatic auto TryFinishSpecific(ImportRefResolver& resolver,\n                              SemIR::SpecificId import_specific_id,\n                              SemIR::SpecificId local_specific_id) -> bool {\n  const auto& import_specific =\n      resolver.import_specifics().Get(import_specific_id);\n  auto& local_specific = resolver.local_specifics().Get(local_specific_id);\n\n  if (IsSpecificImported(import_specific, local_specific)) {\n    return true;\n  }\n\n  llvm::SmallVector<SemIR::InstId> decl_block;\n  if (!local_specific.decl_block_id.has_value()) {\n    decl_block =\n        GetLocalInstBlockContents(resolver, import_specific.decl_block_id);\n  }\n  auto definition_block =\n      GetLocalInstBlockContents(resolver, import_specific.definition_block_id);\n\n  if (resolver.HasNewWork()) {\n    return false;\n  }\n\n  if (!local_specific.decl_block_id.has_value()) {\n    local_specific.decl_block_id = GetLocalCanonicalInstBlockId(\n        resolver, import_specific.decl_block_id, decl_block);\n  }\n  local_specific.definition_block_id = GetLocalCanonicalInstBlockId(\n      resolver, import_specific.definition_block_id, definition_block);\n  return true;\n}\n\nnamespace {\nstruct SpecificInterfaceData {\n  SemIR::ConstantId interface_const_id;\n  SpecificData specific_data;\n};\n}  // namespace\n\nstatic auto GetLocalSpecificInterfaceData(\n    ImportRefResolver& resolver, SemIR::SpecificInterface import_interface)\n    -> SpecificInterfaceData {\n  SemIR::ConstantId interface_const_id = SemIR::ConstantId::None;\n  if (import_interface.interface_id.has_value()) {\n    interface_const_id =\n        GetLocalConstantId(resolver, resolver.import_interfaces()\n                                         .Get(import_interface.interface_id)\n                                         .first_owning_decl_id);\n  }\n  return {.interface_const_id = interface_const_id,\n          .specific_data =\n              GetLocalSpecificData(resolver, import_interface.specific_id)};\n}\n\nstatic auto GetLocalSpecificInterface(\n    ImportRefResolver& resolver,\n    SemIR::SpecificInterface import_specific_interface,\n    SpecificInterfaceData interface_data) -> SemIR::SpecificInterface {\n  if (!interface_data.interface_const_id.has_value()) {\n    return SemIR::SpecificInterface::None;\n  }\n  // Find the corresponding interface type. For a non-generic interface,\n  // this is the type of the interface declaration. For a generic interface,\n  // build a interface type referencing this specialization of the generic\n  // interface.\n  auto interface_const_inst =\n      resolver.local_insts().Get(resolver.local_constant_values().GetInstId(\n          interface_data.interface_const_id));\n  if (auto facet_type = interface_const_inst.TryAs<SemIR::FacetType>()) {\n    const SemIR::FacetTypeInfo& new_facet_type_info =\n        resolver.local_facet_types().Get(facet_type->facet_type_id);\n    return std::get<SemIR::SpecificInterface>(\n        *new_facet_type_info.TryAsSingleExtend());\n  } else {\n    auto generic_interface_type =\n        resolver.local_types().GetAs<SemIR::GenericInterfaceType>(\n            interface_const_inst.type_id());\n    auto specific_id =\n        GetOrAddLocalSpecific(resolver, import_specific_interface.specific_id,\n                              interface_data.specific_data);\n    return {generic_interface_type.interface_id, specific_id};\n  }\n}\n\nnamespace {\nstruct SpecificNamedConstraintData {\n  SemIR::ConstantId constraint_const_id;\n  SpecificData specific_data;\n};\n}  // namespace\n\nstatic auto GetLocalSpecificNamedConstraintData(\n    ImportRefResolver& resolver,\n    SemIR::SpecificNamedConstraint import_constraint)\n    -> SpecificNamedConstraintData {\n  SemIR::ConstantId constraint_const_id = SemIR::ConstantId::None;\n  if (import_constraint.named_constraint_id.has_value()) {\n    constraint_const_id = GetLocalConstantId(\n        resolver, resolver.import_named_constraints()\n                      .Get(import_constraint.named_constraint_id)\n                      .first_owning_decl_id);\n  }\n  return {.constraint_const_id = constraint_const_id,\n          .specific_data =\n              GetLocalSpecificData(resolver, import_constraint.specific_id)};\n}\n\nstatic auto GetLocalSpecificNamedConstraint(\n    ImportRefResolver& resolver,\n    SemIR::SpecificNamedConstraint import_specific_constraint,\n    SpecificNamedConstraintData constraint_data)\n    -> SemIR::SpecificNamedConstraint {\n  if (!constraint_data.constraint_const_id.has_value()) {\n    return SemIR::SpecificNamedConstraint::None;\n  }\n  // Find the corresponding named constraint type. For a non-generic constraint,\n  // this is the type of the named constraint declaration. For a generic\n  // constraint, build a named constraint type referencing this specialization\n  // of the generic named constraint.\n  auto constraint_const_inst =\n      resolver.local_insts().Get(resolver.local_constant_values().GetInstId(\n          constraint_data.constraint_const_id));\n  if (auto facet_type = constraint_const_inst.TryAs<SemIR::FacetType>()) {\n    const SemIR::FacetTypeInfo& new_facet_type_info =\n        resolver.local_facet_types().Get(facet_type->facet_type_id);\n    return std::get<SemIR::SpecificNamedConstraint>(\n        *new_facet_type_info.TryAsSingleExtend());\n  } else {\n    auto generic_constraint_type =\n        resolver.local_types().GetAs<SemIR::GenericNamedConstraintType>(\n            constraint_const_inst.type_id());\n    auto specific_id =\n        GetOrAddLocalSpecific(resolver, import_specific_constraint.specific_id,\n                              constraint_data.specific_data);\n    return {generic_constraint_type.named_constraint_id, specific_id};\n  }\n}\n\nstatic auto GetLocalNameScopeIdImpl(ImportRefResolver& resolver,\n                                    SemIR::ConstantId const_id)\n    -> SemIR::NameScopeId {\n  if (!const_id.has_value()) {\n    return SemIR::NameScopeId::None;\n  }\n\n  auto const_inst_id = resolver.local_constant_values().GetInstId(const_id);\n  auto name_scope_inst = resolver.local_insts().Get(const_inst_id);\n  CARBON_KIND_SWITCH(name_scope_inst) {\n    case CARBON_KIND(SemIR::Namespace inst): {\n      return inst.name_scope_id;\n    }\n    case CARBON_KIND(SemIR::ClassType inst): {\n      return resolver.local_classes().Get(inst.class_id).scope_id;\n    }\n    case CARBON_KIND(SemIR::FacetType inst): {\n      const SemIR::FacetTypeInfo& facet_type_info =\n          resolver.local_facet_types().Get(inst.facet_type_id);\n      if (auto single = facet_type_info.TryAsSingleExtend()) {\n        // This is the facet type produced by an interface or named constraint\n        // declaration.\n        CARBON_KIND_SWITCH(*single) {\n          case CARBON_KIND(SemIR::SpecificInterface interface): {\n            return resolver.local_interfaces()\n                .Get(interface.interface_id)\n                .scope_without_self_id;\n          }\n          case CARBON_KIND(SemIR::SpecificNamedConstraint constraint): {\n            return resolver.local_named_constraints()\n                .Get(constraint.named_constraint_id)\n                .scope_without_self_id;\n          }\n        }\n      }\n      break;\n    }\n    case CARBON_KIND(SemIR::ImplDecl inst): {\n      return resolver.local_impls().Get(inst.impl_id).scope_id;\n    }\n    case CARBON_KIND(SemIR::InterfaceWithSelfDecl interface_with_self): {\n      return resolver.local_interfaces()\n          .Get(interface_with_self.interface_id)\n          .scope_with_self_id;\n    }\n    case CARBON_KIND(SemIR::NamedConstraintWithSelfDecl constraint_with_self): {\n      return resolver.local_named_constraints()\n          .Get(constraint_with_self.named_constraint_id)\n          .scope_with_self_id;\n    }\n    case SemIR::StructValue::Kind: {\n      auto type_inst =\n          resolver.local_types().GetAsInst(name_scope_inst.type_id());\n      CARBON_KIND_SWITCH(type_inst) {\n        case CARBON_KIND(SemIR::GenericClassType inst): {\n          return resolver.local_classes().Get(inst.class_id).scope_id;\n        }\n        case CARBON_KIND(SemIR::GenericInterfaceType inst): {\n          return resolver.local_interfaces()\n              .Get(inst.interface_id)\n              .scope_without_self_id;\n        }\n        case CARBON_KIND(SemIR::GenericNamedConstraintType inst): {\n          return resolver.local_named_constraints()\n              .Get(inst.named_constraint_id)\n              .scope_without_self_id;\n        }\n        default: {\n          break;\n        }\n      }\n      break;\n    }\n    default: {\n      if (const_inst_id == SemIR::ErrorInst::InstId) {\n        return SemIR::NameScopeId::None;\n      }\n      break;\n    }\n  }\n  CARBON_FATAL(\"Unexpected instruction kind for name scope: {0}\",\n               name_scope_inst);\n}\n\n// Translates a NameScopeId from the import IR to a local NameScopeId. Adds\n// unresolved constants to the resolver's work stack.\nstatic auto GetLocalNameScopeId(ImportRefResolver& resolver,\n                                SemIR::NameScopeId name_scope_id)\n    -> SemIR::NameScopeId {\n  // Get the instruction that created the scope.\n  auto [inst_id, inst] =\n      resolver.import_name_scopes().GetInstIfValid(name_scope_id);\n  if (!inst) {\n    // Map scopes that aren't associated with an instruction to `None`. For now,\n    // such scopes aren't used, and we don't have a good way to remap them.\n    return SemIR::NameScopeId::None;\n  }\n\n  // Get the constant value for the scope.\n  auto const_id = GetLocalConstantId(resolver, inst_id);\n  if (!const_id.has_value()) {\n    return SemIR::NameScopeId::None;\n  }\n  auto result = GetLocalNameScopeIdImpl(resolver, const_id);\n  CARBON_CHECK(result.has_value());\n  return result;\n}\n\n// Given an imported entity base, returns an incomplete, local version of it.\n//\n// Most fields are set in the third phase once they're imported. Import enough\n// of the parameter lists that we know whether this interface is a generic\n// interface and can build the right constant value for it.\n//\n// TODO: Support extern.\nstatic auto GetIncompleteLocalEntityBase(\n    ImportContext& context, SemIR::InstId decl_id,\n    const SemIR::EntityWithParamsBase& import_base)\n    -> SemIR::EntityWithParamsBase {\n  // Translate the extern_library_id if present.\n  auto extern_library_id = SemIR::LibraryNameId::None;\n  if (import_base.extern_library_id.has_value()) {\n    if (import_base.extern_library_id.index >= 0) {\n      auto val = context.import_string_literal_values().Get(\n          import_base.extern_library_id.AsStringLiteralValueId());\n      extern_library_id = SemIR::LibraryNameId::ForStringLiteralValueId(\n          context.local_string_literal_values().Add(val));\n    } else {\n      extern_library_id = import_base.extern_library_id;\n    }\n  }\n\n  return {\n      .name_id = GetLocalNameId(context, import_base.name_id),\n      .parent_scope_id = SemIR::NameScopeId::None,\n      .generic_id =\n          ImportIncompleteGeneric(context, decl_id, import_base.generic_id),\n      .first_param_node_id = Parse::NodeId::None,\n      .last_param_node_id = Parse::NodeId::None,\n      .pattern_block_id = SemIR::InstBlockId::None,\n      .implicit_param_patterns_id =\n          import_base.implicit_param_patterns_id.has_value()\n              ? SemIR::InstBlockId::Empty\n              : SemIR::InstBlockId::None,\n      .param_patterns_id = import_base.param_patterns_id.has_value()\n                               ? SemIR::InstBlockId::Empty\n                               : SemIR::InstBlockId::None,\n      .is_extern = import_base.is_extern,\n      .extern_library_id = extern_library_id,\n      .non_owning_decl_id = import_base.non_owning_decl_id.has_value()\n                                ? decl_id\n                                : SemIR::InstId::None,\n      .first_owning_decl_id = import_base.first_owning_decl_id.has_value()\n                                  ? decl_id\n                                  : SemIR::InstId::None,\n  };\n}\n\n// Adds ImportRefUnloaded entries for members of the imported scope, for name\n// lookup.\nstatic auto AddNameScopeImportRefs(ImportContext& context,\n                                   const SemIR::NameScope& import_scope,\n                                   SemIR::NameScope& new_scope) -> void {\n  for (auto entry : import_scope.entries()) {\n    SemIR::ScopeLookupResult result = entry.result;\n    if (result.is_poisoned()) {\n      continue;\n    }\n    auto ref_id = AddImportRef(context, result.target_inst_id());\n    new_scope.AddRequired({.name_id = GetLocalNameId(context, entry.name_id),\n                           .result = SemIR::ScopeLookupResult::MakeFound(\n                               ref_id, result.access_kind())});\n  }\n  for (auto scope_inst_id : import_scope.extended_scopes()) {\n    new_scope.AddExtendedScope(AddImportRef(context, scope_inst_id));\n  }\n}\n\n// Given a block ID for a list of associated entities of a witness, returns a\n// version localized to the current IR.\nstatic auto AddAssociatedEntities(ImportContext& context,\n                                  SemIR::NameScopeId local_name_scope_id,\n                                  SemIR::InstBlockId associated_entities_id)\n    -> SemIR::InstBlockId {\n  if (associated_entities_id == SemIR::InstBlockId::Empty) {\n    return SemIR::InstBlockId::Empty;\n  }\n  auto associated_entities =\n      context.import_inst_blocks().Get(associated_entities_id);\n  llvm::SmallVector<SemIR::InstId> new_associated_entities;\n  new_associated_entities.reserve(associated_entities.size());\n  for (auto inst_id : associated_entities) {\n    // Determine the name of the associated entity, by switching on its kind.\n    SemIR::NameId import_name_id = SemIR::NameId::None;\n    if (auto assoc_const_decl =\n            context.import_insts().TryGetAs<SemIR::AssociatedConstantDecl>(\n                inst_id)) {\n      const auto& assoc_const = context.import_associated_constants().Get(\n          assoc_const_decl->assoc_const_id);\n      import_name_id = assoc_const.name_id;\n    } else if (auto function_decl =\n                   context.import_insts().TryGetAs<SemIR::FunctionDecl>(\n                       inst_id)) {\n      const auto& function =\n          context.import_functions().Get(function_decl->function_id);\n      import_name_id = function.name_id;\n    } else if (auto import_ref =\n                   context.import_insts().TryGetAs<SemIR::AnyImportRef>(\n                       inst_id)) {\n      import_name_id =\n          context.import_entity_names().Get(import_ref->entity_name_id).name_id;\n    } else {\n      // We don't need `GetWithAttachedType` here because we don't access the\n      // type.\n      CARBON_FATAL(\"Unhandled associated entity kind: {0}\",\n                   context.import_insts().Get(inst_id).kind());\n    }\n    auto name_id = GetLocalNameId(context, import_name_id);\n    auto entity_name_id = context.local_entity_names().Add(\n        {.name_id = name_id, .parent_scope_id = local_name_scope_id});\n    new_associated_entities.push_back(\n        AddImportRef(context, inst_id, entity_name_id));\n  }\n  return context.local_inst_blocks().Add(new_associated_entities);\n}\n\nnamespace {\nnamespace Internal {\n// Internal concept for instruction kinds that produce unique constants.\ntemplate <typename InstT>\nconcept HasUniqueConstantKind =\n    InstT::Kind.constant_kind() == SemIR::InstConstantKind::AlwaysUnique ||\n    InstT::Kind.constant_kind() == SemIR::InstConstantKind::ConditionalUnique;\n}  // namespace Internal\n\n// The result of attempting to resolve an imported instruction to a constant.\nstruct ResolveResult {\n  // The new constant value, if known.\n  SemIR::ConstantId const_id;\n  // Newly created declaration whose value is being resolved, if any.\n  SemIR::InstId decl_id = SemIR::InstId::None;\n  // Whether resolution has been attempted once and needs to be retried.\n  bool retry = false;\n\n  // If a generic needs to be resolved, the generic information.\n  struct ResolveGeneric {\n    SemIR::GenericId import_generic_id = SemIR::GenericId::None;\n    SemIR::GenericId local_generic_id = SemIR::GenericId::None;\n  };\n  std::array<ResolveGeneric, 2> resolve_generic;\n\n  // Produces a resolve result that tries resolving this instruction again. If\n  // `const_id` is specified, then this is the end of the second phase, and the\n  // constant value will be passed to the next resolution attempt. Otherwise,\n  // this is the end of the first phase.\n  static auto Retry(SemIR::ConstantId const_id = SemIR::ConstantId::None,\n                    SemIR::InstId decl_id = SemIR::InstId::None)\n      -> ResolveResult {\n    return {.const_id = const_id, .decl_id = decl_id, .retry = true};\n  }\n\n  // Produces a resolve result that provides the given constant value. Requires\n  // that there is no new work.\n  static auto Done(SemIR::ConstantId const_id,\n                   SemIR::InstId decl_id = SemIR::InstId::None)\n      -> ResolveResult {\n    return {.const_id = const_id, .decl_id = decl_id};\n  }\n\n  // Produces a resolve result that provides the given constant value. Retries\n  // instead if work has been added.\n  static auto RetryOrDone(ImportRefResolver& resolver,\n                          SemIR::ConstantId const_id) -> ResolveResult {\n    if (resolver.HasNewWork()) {\n      return Retry();\n    }\n    return Done(const_id);\n  }\n\n  // If there's no generic, this is equivalent to `Done`. If there is a generic,\n  // it's still done, but the fetched generic data is processed and the generic\n  // is enqueued for further work.\n  //\n  // It's not valid to have a generic-with-self but no base generic.\n  static auto FinishGenericOrDone(ImportRefResolver& resolver,\n                                  SemIR::ConstantId const_id,\n                                  SemIR::InstId decl_id,\n                                  SemIR::GenericId import_generic_id,\n                                  SemIR::GenericId local_generic_id,\n                                  GenericData generic_data) -> ResolveResult {\n    auto result = Done(const_id, decl_id);\n    if (import_generic_id.has_value()) {\n      SetGenericDataForResolveResult(resolver, import_generic_id,\n                                     local_generic_id, generic_data);\n      result.resolve_generic[0].import_generic_id = import_generic_id;\n      result.resolve_generic[0].local_generic_id = local_generic_id;\n    }\n    return result;\n  }\n\n  // Adds `inst` to the local context as a deduplicated constant and returns a\n  // successful `ResolveResult`. Requires that there is no new work.\n  //\n  // This implements phases 2 and 3 of resolving the inst (as described on\n  // `ImportRefResolver`) for the common case where those phases are combined.\n  // Cases where that isn't applicable should instead use\n  // `AddPlaceholderImportedInst` and `ReplacePlaceholderImportedInst`.\n  //\n  // This should not be used for instructions that represent declarations, or\n  // other instructions with `constant_kind == InstConstantKind::Unique`,\n  // because they should not be deduplicated.\n  template <typename InstT>\n    requires(!Internal::HasUniqueConstantKind<InstT>)\n  static auto Deduplicated(ImportRefResolver& resolver, InstT inst)\n      -> ResolveResult {\n    CARBON_CHECK(!resolver.HasNewWork());\n    // AddImportedConstant produces an unattached constant, so its type must\n    // be unattached as well.\n    inst.type_id = resolver.local_types().GetUnattachedType(inst.type_id);\n    auto const_id = AddImportedConstant(resolver.local_context(), inst);\n    CARBON_CHECK(const_id.is_constant(), \"{0} is not constant\", inst);\n    return Done(const_id);\n  }\n\n  // Adds `inst` to the local context as a unique constant and returns a\n  // successful `ResolveResult`. `import_inst_id` is the corresponding inst ID\n  // in the local context. Requires that there is no new work.\n  //\n  // This implements phases 2 and 3 of resolving the inst (as described on\n  // `ImportRefResolver`) for the common case where those phases are combined.\n  // Cases where that isn't applicable should instead use\n  // `AddPlaceholderImportedInst` and `ReplacePlaceholderImportedInst`.\n  //\n  // This should only be used for instructions that represent declarations, or\n  // other instructions with `constant_kind == InstConstantKind::Unique`,\n  // because it does not perform deduplication.\n  template <typename InstT>\n    requires Internal::HasUniqueConstantKind<InstT>\n  static auto Unique(ImportRefResolver& resolver, SemIR::InstId import_inst_id,\n                     InstT inst) -> ResolveResult {\n    CARBON_CHECK(!resolver.HasNewWork());\n    auto inst_id = AddPlaceholderImportedInst(resolver, import_inst_id, inst);\n    auto const_id = SetConstantValue(resolver.local_context(), inst_id, inst);\n    CARBON_CHECK(const_id.is_constant(), \"{0} is not constant\", inst);\n    return Done(const_id, inst_id);\n  }\n};\n}  // namespace\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::AdaptDecl inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  auto adapted_type_const_id =\n      GetLocalConstantId(resolver, inst.adapted_type_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto adapted_type_inst_id = AddLoadedImportRefForType(\n      resolver, inst.adapted_type_inst_id, adapted_type_const_id);\n\n  // Create a corresponding instruction to represent the declaration.\n  return ResolveResult::Unique<SemIR::AdaptDecl>(\n      resolver, import_inst_id, {.adapted_type_inst_id = adapted_type_inst_id});\n}\n\ntemplate <typename ParamPatternT>\n  requires SemIR::Internal::HasInstCategory<SemIR::AnyParamPattern,\n                                            ParamPatternT>\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver, ParamPatternT inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  auto subpattern_id = GetLocalConstantInstId(resolver, inst.subpattern_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Unique<ParamPatternT>(\n      resolver, import_inst_id,\n      {.type_id =\n           resolver.local_types().GetTypeIdForTypeConstantId(type_const_id),\n       .subpattern_id = subpattern_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ArrayType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto element_type_inst_id =\n      GetLocalTypeInstId(resolver, inst.element_type_inst_id);\n  auto bound_id = GetLocalConstantInstId(resolver, inst.bound_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::ArrayType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .bound_id = bound_id,\n                 .element_type_inst_id = element_type_inst_id});\n}\n\nstatic auto ImportAssociatedConstant(\n    ImportContext& context, const SemIR::AssociatedConstant& import_assoc_const,\n    SemIR::TypeId type_id)\n    -> std::pair<SemIR::AssociatedConstantId, SemIR::ConstantId> {\n  SemIR::AssociatedConstantDecl assoc_const_decl = {\n      .type_id = type_id,\n      .assoc_const_id = SemIR::AssociatedConstantId::None,\n      .decl_block_id = SemIR::InstBlockId::Empty};\n  auto assoc_const_decl_id = AddPlaceholderImportedInst(\n      context, import_assoc_const.decl_id, assoc_const_decl);\n  assoc_const_decl.assoc_const_id = context.local_associated_constants().Add({\n      .name_id = GetLocalNameId(context, import_assoc_const.name_id),\n      .parent_scope_id = SemIR::NameScopeId::None,\n      .decl_id = assoc_const_decl_id,\n      .default_value_id =\n          import_assoc_const.default_value_id.has_value()\n              ? AddImportRef(context, import_assoc_const.default_value_id)\n              : SemIR::InstId::None,\n  });\n\n  // Write the associated constant ID into the AssociatedConstantDecl.\n  auto const_id = ReplacePlaceholderImportedInst(context, assoc_const_decl_id,\n                                                 assoc_const_decl);\n  return {assoc_const_decl.assoc_const_id, const_id};\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::AssociatedConstantDecl inst,\n                                SemIR::ConstantId const_id) -> ResolveResult {\n  const auto& import_assoc_const =\n      resolver.import_associated_constants().Get(inst.assoc_const_id);\n\n  SemIR::AssociatedConstantId assoc_const_id =\n      SemIR::AssociatedConstantId::None;\n  if (!const_id.has_value()) {\n    // In the first phase, import the type of the associated constant.\n    auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n    if (resolver.HasNewWork()) {\n      return ResolveResult::Retry();\n    }\n\n    // In the second phase, create the associated constant and its declaration.\n    auto type_id =\n        resolver.local_types().GetTypeIdForTypeConstantId(type_const_id);\n    std::tie(assoc_const_id, const_id) =\n        ImportAssociatedConstant(resolver, import_assoc_const, type_id);\n  } else {\n    // In the third phase, compute the associated constant ID from the constant\n    // value of the declaration.\n    assoc_const_id =\n        resolver.local_insts()\n            .GetAs<SemIR::AssociatedConstantDecl>(\n                resolver.local_constant_values().GetInstId(const_id))\n            .assoc_const_id;\n  }\n\n  // Load the values to populate the entity with.\n  auto parent_scope_id =\n      GetLocalNameScopeId(resolver, import_assoc_const.parent_scope_id);\n  auto& new_assoc_const =\n      resolver.local_associated_constants().Get(assoc_const_id);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry(const_id, new_assoc_const.decl_id);\n  }\n\n  // Populate the entity.\n  new_assoc_const.parent_scope_id = parent_scope_id;\n  return ResolveResult::Done(const_id, new_assoc_const.decl_id);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::AssociatedEntity inst) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  // Add a lazy reference to the target declaration.\n  auto decl_id = AddImportRef(resolver, inst.decl_id);\n\n  return ResolveResult::Deduplicated<SemIR::AssociatedEntity>(\n      resolver, {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(\n                     type_const_id),\n                 .index = inst.index,\n                 .decl_id = decl_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::AssociatedEntityType inst)\n    -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto data =\n      GetLocalSpecificInterfaceData(resolver, inst.GetSpecificInterface());\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto specific_interface =\n      GetLocalSpecificInterface(resolver, inst.GetSpecificInterface(), data);\n  return ResolveResult::Deduplicated<SemIR::AssociatedEntityType>(\n      resolver,\n      {.type_id = SemIR::TypeType::TypeId,\n       .interface_id = specific_interface.interface_id,\n       .interface_without_self_specific_id = specific_interface.specific_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::BaseDecl inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  auto base_type_const_id =\n      GetLocalConstantId(resolver, inst.base_type_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto base_type_inst_id = AddLoadedImportRefForType(\n      resolver, inst.base_type_inst_id, base_type_const_id);\n\n  // Create a corresponding instruction to represent the declaration.\n  return ResolveResult::Unique<SemIR::BaseDecl>(\n      resolver, import_inst_id,\n      {.type_id =\n           resolver.local_types().GetTypeIdForTypeConstantId(type_const_id),\n       .base_type_inst_id = base_type_inst_id,\n       .index = inst.index});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::AliasBinding inst) -> ResolveResult {\n  auto value_id = GetLocalConstantId(resolver, inst.value_id);\n  return ResolveResult::RetryOrDone(resolver, value_id);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::SymbolicBinding inst) -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto entity_name_id =\n      GetLocalSymbolicEntityNameId(resolver, inst.entity_name_id);\n  return ResolveResult::Deduplicated<SemIR::SymbolicBinding>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .entity_name_id = entity_name_id,\n       .value_id = SemIR::InstId::None});\n}\n\ntemplate <typename BindingPatternT>\n  requires SemIR::Internal::HasInstCategory<SemIR::AnyBindingPattern,\n                                            BindingPatternT>\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                BindingPatternT inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  const auto& import_entity_name =\n      resolver.import_entity_names().Get(inst.entity_name_id);\n  auto parent_scope_id =\n      GetLocalNameScopeId(resolver, import_entity_name.parent_scope_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto name_id = GetLocalNameId(resolver, import_entity_name.name_id);\n  auto entity_name_id = resolver.local_entity_names().Add(\n      {.name_id = name_id,\n       .parent_scope_id = parent_scope_id,\n       .bind_index_value = import_entity_name.bind_index().index,\n       .is_template = import_entity_name.is_template});\n  return ResolveResult::Unique<BindingPatternT>(\n      resolver, import_inst_id,\n      {.type_id =\n           resolver.local_types().GetTypeIdForTypeConstantId(type_const_id),\n       .entity_name_id = entity_name_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::BoolLiteral inst) -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::BoolType::TypeInstId);\n\n  CARBON_CHECK(!resolver.HasNewWork());\n\n  return ResolveResult::Deduplicated<SemIR::BoolLiteral>(\n      resolver, {.type_id = GetSingletonType(resolver.local_context(),\n                                             SemIR::BoolType::TypeInstId),\n                 .value = inst.value});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::BoundMethod inst) -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::BoundMethodType::TypeInstId);\n  auto object_id = GetLocalConstantInstId(resolver, inst.object_id);\n  auto function_decl_id =\n      GetLocalConstantInstId(resolver, inst.function_decl_id);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::BoundMethod>(\n      resolver,\n      {.type_id = GetSingletonType(resolver.local_context(),\n                                   SemIR::BoundMethodType::TypeInstId),\n       .object_id = object_id,\n       .function_decl_id = function_decl_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver, SemIR::Call inst)\n    -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  auto callee_id = GetLocalConstantInstId(resolver, inst.callee_id);\n  auto args = GetLocalInstBlockContents(resolver, inst.args_id);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::Call>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .callee_id = callee_id,\n       .args_id = GetLocalCanonicalInstBlockId(resolver, inst.args_id, args)});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::CharLiteralValue inst) -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::CharLiteralType::TypeInstId);\n\n  CARBON_CHECK(!resolver.HasNewWork());\n\n  return ResolveResult::Deduplicated<SemIR::CharLiteralValue>(\n      resolver,\n      {.type_id = GetSingletonType(resolver.local_context(),\n                                   SemIR::CharLiteralType::TypeInstId),\n       .value = inst.value});\n}\n\nstatic auto AddPlaceholderNameScope(ImportContext& context)\n    -> SemIR::NameScopeId {\n  return context.local_name_scopes().Add(\n      SemIR::InstId::None, SemIR::NameId::None, SemIR::NameScopeId::None);\n}\n\n// Makes an incomplete class. This is necessary even with classes with a\n// complete declaration, because things such as `Self` may refer back to the\n// type.\nstatic auto ImportIncompleteClass(ImportContext& context,\n                                  const SemIR::Class& import_class,\n                                  SemIR::SpecificId enclosing_specific_id)\n    -> std::pair<SemIR::ClassId, SemIR::ConstantId> {\n  SemIR::ClassDecl class_decl = {.type_id = SemIR::TypeType::TypeId,\n                                 .class_id = SemIR::ClassId::None,\n                                 .decl_block_id = SemIR::InstBlockId::Empty};\n  auto class_decl_id = AddPlaceholderImportedInst(\n      context, import_class.latest_decl_id(), class_decl);\n  // Regardless of whether ClassDecl is a complete type, we first need an\n  // incomplete type so that any references have something to point at.\n  class_decl.class_id = context.local_classes().Add(\n      {GetIncompleteLocalEntityBase(context, class_decl_id, import_class),\n       {.self_type_id = SemIR::TypeId::None,\n        .inheritance_kind = import_class.inheritance_kind,\n        .is_dynamic = import_class.is_dynamic,\n        .scope_id = import_class.is_complete()\n                        ? AddPlaceholderNameScope(context)\n                        : SemIR::NameScopeId::None}});\n\n  if (import_class.has_parameters()) {\n    class_decl.type_id = GetGenericClassType(\n        context.local_context(), class_decl.class_id, enclosing_specific_id);\n  }\n\n  // Write the class ID into the ClassDecl.\n  auto self_const_id =\n      ReplacePlaceholderImportedInst(context, class_decl_id, class_decl);\n  return {class_decl.class_id, self_const_id};\n}\n\nstatic auto InitializeNameScopeAndImportRefs(\n    ImportContext& context, const SemIR::NameScope& import_scope,\n    SemIR::NameScope& new_scope, SemIR::InstId decl_id, SemIR::NameId name_id,\n    SemIR::NameScopeId parent_scope_id) {\n  new_scope.Set(decl_id, name_id, parent_scope_id);\n  AddNameScopeImportRefs(context, import_scope, new_scope);\n}\n\n// Fills out the class definition for an incomplete class.\nstatic auto ImportClassDefinition(ImportContext& context,\n                                  const SemIR::Class& import_class,\n                                  SemIR::Class& new_class,\n                                  SemIR::InstId complete_type_witness_id,\n                                  SemIR::InstId base_id, SemIR::InstId adapt_id,\n                                  SemIR::InstId vtable_decl_id) -> void {\n  new_class.definition_id = new_class.first_owning_decl_id;\n\n  new_class.complete_type_witness_id = complete_type_witness_id;\n\n  auto& new_scope = context.local_name_scopes().Get(new_class.scope_id);\n  const auto& import_scope =\n      context.import_name_scopes().Get(import_class.scope_id);\n\n  // Push a block so that we can add scoped instructions to it.\n  context.local_context().inst_block_stack().Push();\n  InitializeNameScopeAndImportRefs(\n      context, import_scope, new_scope, new_class.first_owning_decl_id,\n      SemIR::NameId::None, new_class.parent_scope_id);\n  new_class.body_block_id = context.local_context().inst_block_stack().Pop();\n\n  if (import_class.base_id.has_value()) {\n    new_class.base_id = base_id;\n  }\n  if (import_class.adapt_id.has_value()) {\n    new_class.adapt_id = adapt_id;\n  }\n  if (import_class.vtable_decl_id.has_value()) {\n    new_class.vtable_decl_id = vtable_decl_id;\n  }\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ClassDecl inst,\n                                SemIR::ConstantId class_const_id)\n    -> ResolveResult {\n  // TODO: The handling of interfaces repeats a lot with the handling of\n  // classes, and will likely also be repeated for named constraints and\n  // choice types. Factor out some of this functionality.\n  const auto& import_class = resolver.import_classes().Get(inst.class_id);\n\n  SemIR::ClassId class_id = SemIR::ClassId::None;\n  if (!class_const_id.has_value()) {\n    auto import_specific_id = SemIR::SpecificId::None;\n    if (auto import_generic_class_type =\n            resolver.import_types().TryGetAs<SemIR::GenericClassType>(\n                inst.type_id)) {\n      import_specific_id = import_generic_class_type->enclosing_specific_id;\n    }\n    auto specific_data = GetLocalSpecificData(resolver, import_specific_id);\n    if (resolver.HasNewWork()) {\n      // This is the end of the first phase. Don't make a new class yet if\n      // we already have new work.\n      return ResolveResult::Retry();\n    }\n\n    // On the second phase, create a forward declaration of the class for any\n    // recursive references.\n    auto enclosing_specific_id =\n        GetOrAddLocalSpecific(resolver, import_specific_id, specific_data);\n    std::tie(class_id, class_const_id) =\n        ImportIncompleteClass(resolver, import_class, enclosing_specific_id);\n  } else {\n    // On the third phase, compute the class ID from the constant\n    // value of the declaration.\n    auto class_const_inst = resolver.local_insts().Get(\n        resolver.local_constant_values().GetInstId(class_const_id));\n    if (auto class_type = class_const_inst.TryAs<SemIR::ClassType>()) {\n      class_id = class_type->class_id;\n    } else {\n      auto generic_class_type =\n          resolver.local_types().GetAs<SemIR::GenericClassType>(\n              class_const_inst.type_id());\n      class_id = generic_class_type.class_id;\n    }\n  }\n\n  // Load constants for the definition.\n  auto parent_scope_id =\n      GetLocalNameScopeId(resolver, import_class.parent_scope_id);\n  auto implicit_param_patterns = GetLocalInstBlockContents(\n      resolver, import_class.implicit_param_patterns_id);\n  auto param_patterns =\n      GetLocalInstBlockContents(resolver, import_class.param_patterns_id);\n  auto generic_data = GetLocalGenericData(resolver, import_class.generic_id);\n  auto self_const_id = GetLocalConstantId(resolver, import_class.self_type_id);\n  auto complete_type_witness_const_id =\n      import_class.complete_type_witness_id.has_value()\n          ? GetLocalConstantId(resolver, import_class.complete_type_witness_id)\n          : SemIR::ConstantId::None;\n  auto base_id = import_class.base_id.has_value()\n                     ? GetLocalConstantInstId(resolver, import_class.base_id)\n                     : SemIR::InstId::None;\n  auto adapt_id = import_class.adapt_id.has_value()\n                      ? GetLocalConstantInstId(resolver, import_class.adapt_id)\n                      : SemIR::InstId::None;\n  auto vtable_decl_id =\n      import_class.vtable_decl_id.has_value()\n          ? AddImportRef(resolver, import_class.vtable_decl_id)\n          : SemIR::InstId::None;\n  auto& new_class = resolver.local_classes().Get(class_id);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry(class_const_id, new_class.first_decl_id());\n  }\n\n  new_class.parent_scope_id = parent_scope_id;\n  new_class.implicit_param_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_class.implicit_param_patterns_id,\n      implicit_param_patterns);\n  new_class.param_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_class.param_patterns_id, param_patterns);\n  new_class.self_type_id =\n      resolver.local_types().GetTypeIdForTypeConstantId(self_const_id);\n\n  if (import_class.is_complete()) {\n    auto complete_type_witness_id = AddLoadedImportRef(\n        resolver,\n        GetSingletonType(resolver.local_context(),\n                         SemIR::WitnessType::TypeInstId),\n        import_class.complete_type_witness_id, complete_type_witness_const_id);\n    ImportClassDefinition(resolver, import_class, new_class,\n                          complete_type_witness_id, base_id, adapt_id,\n                          vtable_decl_id);\n  }\n\n  return ResolveResult::FinishGenericOrDone(\n      resolver, class_const_id, new_class.first_decl_id(),\n      import_class.generic_id, new_class.generic_id, generic_data);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ClassType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto class_const_id = GetLocalConstantId(\n      resolver,\n      resolver.import_classes().Get(inst.class_id).first_owning_decl_id);\n  if (class_const_id == SemIR::ErrorInst::ConstantId) {\n    // TODO: It should be possible to remove this once C++ imports work.\n    return ResolveResult::Done(class_const_id);\n  }\n\n  auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  // Find the corresponding class type. For a non-generic class, this is the\n  // type of the class declaration. For a generic class, build a class type\n  // referencing this specialization of the generic class.\n  auto class_const_inst = resolver.local_insts().Get(\n      resolver.local_constant_values().GetInstId(class_const_id));\n  if (class_const_inst.Is<SemIR::ClassType>()) {\n    return ResolveResult::Done(class_const_id);\n  } else {\n    auto generic_class_type =\n        resolver.local_types().GetAs<SemIR::GenericClassType>(\n            class_const_inst.type_id());\n    auto specific_id =\n        GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data);\n    return ResolveResult::Deduplicated<SemIR::ClassType>(\n        resolver, {.type_id = SemIR::TypeType::TypeId,\n                   .class_id = generic_class_type.class_id,\n                   .specific_id = specific_id});\n  }\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::CompleteTypeWitness inst)\n    -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::WitnessType::TypeInstId);\n  auto object_repr_type_inst_id =\n      GetLocalTypeInstId(resolver, inst.object_repr_type_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n  return ResolveResult::Deduplicated<SemIR::CompleteTypeWitness>(\n      resolver, {.type_id = GetSingletonType(resolver.local_context(),\n                                             SemIR::WitnessType::TypeInstId),\n                 .object_repr_type_inst_id = object_repr_type_inst_id});\n}\n\ntemplate <typename InstT>\n  requires SemIR::Internal::HasInstCategory<SemIR::AnyQualifiedType, InstT>\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver, InstT inst)\n    -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto inner_id = GetLocalTypeInstId(resolver, inst.inner_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n  return ResolveResult::Deduplicated<InstT>(\n      resolver, {.type_id = SemIR::TypeType::TypeId, .inner_id = inner_id});\n}\n\nstatic auto HandleUnsupportedCppOverloadSet(ImportRefResolver& resolver,\n                                            SemIR::CppOverloadSetId id) {\n  // Supporting C++ overload resolution of imported functions is a large task,\n  // which might require serializing and deserializing AST for using decl ids,\n  // using modules and/or linking ASTs.\n  resolver.local_context().TODO(\n      SemIR::LocId::None,\n      llvm::formatv(\n          \"Unsupported: Importing C++ function `{0}` indirectly\",\n          resolver.import_ir().names().GetAsStringIfIdentifier(\n              resolver.import_ir().cpp_overload_sets().Get(id).name_id)));\n  return ResolveResult::Done(SemIR::ErrorInst::ConstantId,\n                             SemIR::ErrorInst::InstId);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::CppOverloadSetType inst)\n    -> ResolveResult {\n  return HandleUnsupportedCppOverloadSet(resolver, inst.overload_set_id);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::CppOverloadSetValue inst)\n    -> ResolveResult {\n  return HandleUnsupportedCppOverloadSet(resolver, inst.overload_set_id);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::CustomWitness inst) -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::WitnessType::TypeInstId);\n\n  auto elements = GetLocalInstBlockContents(resolver, inst.elements_id);\n  const auto& import_specific_interface =\n      resolver.import_specific_interfaces().Get(\n          inst.query_specific_interface_id);\n  auto data =\n      GetLocalSpecificInterfaceData(resolver, import_specific_interface);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto elements_id =\n      GetLocalCanonicalInstBlockId(resolver, inst.elements_id, elements);\n  auto specific_interface =\n      GetLocalSpecificInterface(resolver, import_specific_interface, data);\n  auto query_specific_interface_id =\n      resolver.local_specific_interfaces().Add(specific_interface);\n\n  return ResolveResult::Deduplicated<SemIR::CustomWitness>(\n      resolver, {.type_id = GetSingletonType(resolver.local_context(),\n                                             SemIR::WitnessType::TypeInstId),\n                 .elements_id = elements_id,\n                 .query_specific_interface_id = query_specific_interface_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ExportDecl inst) -> ResolveResult {\n  auto value_id = GetLocalConstantId(resolver, inst.value_id);\n  return ResolveResult::RetryOrDone(resolver, value_id);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FieldDecl inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  auto const_id = GetLocalConstantId(resolver, inst.type_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n  return ResolveResult::Unique<SemIR::FieldDecl>(\n      resolver, import_inst_id,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(const_id),\n       .name_id = GetLocalNameId(resolver, inst.name_id),\n       .index = inst.index});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FloatLiteralValue inst)\n    -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::FloatLiteralType::TypeInstId);\n\n  CARBON_CHECK(!resolver.HasNewWork());\n\n  auto real_id = resolver.local_ir().reals().Add(\n      resolver.import_ir().reals().Get(inst.real_id));\n\n  return ResolveResult::Deduplicated<SemIR::FloatLiteralValue>(\n      resolver,\n      {.type_id = GetSingletonType(resolver.local_context(),\n                                   SemIR::FloatLiteralType::TypeInstId),\n       .real_id = real_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FloatType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto bit_width_id = GetLocalConstantInstId(resolver, inst.bit_width_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::FloatType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .bit_width_id = bit_width_id,\n                 .float_kind = inst.float_kind});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FloatValue inst) -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto float_id = resolver.local_ir().floats().Add(\n      resolver.import_ir().floats().Get(inst.float_id));\n\n  return ResolveResult::Deduplicated<SemIR::FloatValue>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .float_id = float_id});\n}\n\n// Make a declaration of a function. This is done as a separate step from\n// importing the function declaration in order to resolve cycles.\nstatic auto ImportFunctionDecl(ImportContext& context,\n                               const SemIR::Function& import_function,\n                               SemIR::SpecificId specific_id)\n    -> std::pair<SemIR::FunctionId, SemIR::ConstantId> {\n  SemIR::FunctionDecl function_decl = {\n      .type_id = SemIR::TypeId::None,\n      .function_id = SemIR::FunctionId::None,\n      .decl_block_id = SemIR::InstBlockId::Empty};\n  auto function_decl_id = AddPlaceholderImportedInst(\n      context, import_function.first_decl_id(), function_decl);\n\n  // Start with an incomplete function.\n  function_decl.function_id = context.local_functions().Add(\n      {GetIncompleteLocalEntityBase(context, function_decl_id, import_function),\n       {.call_param_patterns_id = SemIR::InstBlockId::None,\n        .call_params_id = SemIR::InstBlockId::None,\n        .call_param_ranges = import_function.call_param_ranges,\n        .return_type_inst_id = SemIR::TypeInstId::None,\n        .return_form_inst_id = SemIR::InstId::None,\n        .return_patterns_id = SemIR::InstBlockId::None,\n        .virtual_modifier = import_function.virtual_modifier,\n        .virtual_index = import_function.virtual_index,\n        .evaluation_mode = import_function.evaluation_mode}});\n\n  // Directly add the function type constant. Don't use `GetFunctionType`\n  // because that will evaluate the function type, which we can't do if the\n  // specific's value block is still pending.\n  auto type_const_id = AddImportedConstant(\n      context.local_context(),\n      SemIR::FunctionType{.type_id = SemIR::TypeType::TypeId,\n                          .function_id = function_decl.function_id,\n                          .specific_id = specific_id});\n  function_decl.type_id =\n      context.local_types().GetTypeIdForTypeConstantId(type_const_id);\n\n  // Write the function ID and type into the FunctionDecl.\n  auto function_const_id =\n      ReplacePlaceholderImportedInst(context, function_decl_id, function_decl);\n  return {function_decl.function_id, function_const_id};\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FunctionDecl inst,\n                                SemIR::ConstantId function_const_id)\n    -> ResolveResult {\n  const auto& import_function =\n      resolver.import_functions().Get(inst.function_id);\n\n  SemIR::FunctionId function_id = SemIR::FunctionId::None;\n  if (!function_const_id.has_value()) {\n    auto import_specific_id = resolver.import_types()\n                                  .GetAs<SemIR::FunctionType>(inst.type_id)\n                                  .specific_id;\n    auto specific_data = GetLocalSpecificData(resolver, import_specific_id);\n    if (resolver.HasNewWork()) {\n      // This is the end of the first phase. Don't make a new function yet if\n      // we already have new work.\n      return ResolveResult::Retry();\n    }\n\n    // On the second phase, create a forward declaration of the function.\n    auto specific_id =\n        GetOrAddLocalSpecific(resolver, import_specific_id, specific_data);\n    std::tie(function_id, function_const_id) =\n        ImportFunctionDecl(resolver, import_function, specific_id);\n  } else {\n    // On the third phase, compute the function ID from the constant value of\n    // the declaration.\n    auto function_const_inst = resolver.local_insts().Get(\n        resolver.local_constant_values().GetInstId(function_const_id));\n    auto function_type = resolver.local_types().GetAs<SemIR::FunctionType>(\n        function_const_inst.type_id());\n    function_id = function_type.function_id;\n  }\n\n  auto call_param_patterns = GetLocalInstBlockContents(\n      resolver, import_function.call_param_patterns_id);\n  auto return_type_const_id = SemIR::ConstantId::None;\n  if (import_function.return_type_inst_id.has_value()) {\n    return_type_const_id =\n        GetLocalConstantId(resolver, import_function.return_type_inst_id);\n  }\n  auto return_form_const_id = SemIR::ConstantId::None;\n  if (import_function.return_form_inst_id.has_value()) {\n    return_form_const_id =\n        GetLocalConstantId(resolver, import_function.return_form_inst_id);\n  }\n  auto parent_scope_id =\n      GetLocalNameScopeId(resolver, import_function.parent_scope_id);\n  auto implicit_param_patterns = GetLocalInstBlockContents(\n      resolver, import_function.implicit_param_patterns_id);\n  auto param_patterns =\n      GetLocalInstBlockContents(resolver, import_function.param_patterns_id);\n  auto generic_data = GetLocalGenericData(resolver, import_function.generic_id);\n  auto self_param_id =\n      GetLocalConstantInstId(resolver, import_function.self_param_id);\n  auto return_patterns =\n      GetLocalInstBlockContents(resolver, import_function.return_patterns_id);\n  auto& new_function = resolver.local_functions().Get(function_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry(function_const_id,\n                                new_function.first_decl_id());\n  }\n\n  // Add the function declaration.\n  new_function.call_param_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_function.call_param_patterns_id, call_param_patterns);\n  new_function.parent_scope_id = parent_scope_id;\n  new_function.implicit_param_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_function.implicit_param_patterns_id,\n      implicit_param_patterns);\n  new_function.self_param_id = self_param_id;\n  new_function.param_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_function.param_patterns_id, param_patterns);\n  new_function.return_type_inst_id = SemIR::TypeInstId::None;\n  if (import_function.return_type_inst_id.has_value()) {\n    new_function.return_type_inst_id = AddLoadedImportRefForType(\n        resolver, import_function.return_type_inst_id, return_type_const_id);\n  }\n  new_function.return_form_inst_id = SemIR::InstId::None;\n  if (import_function.return_form_inst_id.has_value()) {\n    new_function.return_form_inst_id = AddLoadedImportRef(\n        resolver, SemIR::FormType::TypeId, import_function.return_form_inst_id,\n        return_form_const_id);\n  }\n  new_function.return_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_function.return_patterns_id, return_patterns);\n  if (import_function.definition_id.has_value()) {\n    new_function.definition_id = new_function.first_owning_decl_id;\n  }\n\n  switch (import_function.special_function_kind) {\n    case SemIR::Function::SpecialFunctionKind::None: {\n      break;\n    }\n    case SemIR::Function::SpecialFunctionKind::Builtin: {\n      new_function.SetBuiltinFunction(import_function.builtin_function_kind());\n      break;\n    }\n    case SemIR::Function::SpecialFunctionKind::CoreWitness: {\n      new_function.SetCoreWitness();\n      break;\n    }\n    case SemIR::Function::SpecialFunctionKind::Thunk: {\n      auto entity_name_id = resolver.local_entity_names().AddCanonical(\n          {.name_id = new_function.name_id,\n           .parent_scope_id = new_function.parent_scope_id});\n      new_function.SetThunk(AddImportRef(\n          resolver, import_function.thunk_decl_id(), entity_name_id));\n      break;\n    }\n    case SemIR::Function::SpecialFunctionKind::HasCppThunk: {\n      resolver.local_context().TODO(SemIR::LocId::None,\n                                    \"Unsupported: Importing C++ functions that \"\n                                    \"require thunks indirectly\");\n    }\n  }\n\n  return ResolveResult::FinishGenericOrDone(\n      resolver, function_const_id, new_function.first_decl_id(),\n      import_function.generic_id, new_function.generic_id, generic_data);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::VtableDecl inst) -> ResolveResult {\n  const auto& import_vtable = resolver.import_vtables().Get(inst.vtable_id);\n  auto class_const_id =\n      GetLocalConstantId(resolver, resolver.import_classes()\n                                       .Get(import_vtable.class_id)\n                                       .first_owning_decl_id);\n  auto class_const_inst = resolver.local_insts().Get(\n      resolver.local_constant_values().GetInstId(class_const_id));\n\n  // TODO: Ensure the vtable is only imported once, in eg: if there's distinct\n  // vtable constants (imported from multiple libraries using the vtable) that\n  // refer to the same vtable, the vtable should still be singular.\n  auto virtual_functions =\n      resolver.import_inst_blocks().Get(import_vtable.virtual_functions_id);\n\n  llvm::SmallVector<SemIR::InstId> lazy_virtual_functions;\n  lazy_virtual_functions.reserve(virtual_functions.size());\n  for (auto vtable_entry_id : virtual_functions) {\n    auto local_attached_constant_id =\n        GetLocalConstantId(resolver, vtable_entry_id);\n    lazy_virtual_functions.push_back(\n        resolver.local_constant_values().GetInstIdIfValid(\n            local_attached_constant_id));\n  }\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  for (auto [import_vtable_entry_inst_id, local_vtable_entry_inst_id] :\n       llvm::zip_equal(virtual_functions, lazy_virtual_functions)) {\n    // Use LoadedImportRef for imported symbolic constant vtable entries so they\n    // can carry attached constants necessary for applying specifics to these\n    // constants when they are used.\n    auto local_attached_constant_id =\n        resolver.local_constant_values().GetAttached(\n            local_vtable_entry_inst_id);\n    if (local_attached_constant_id.is_symbolic()) {\n      local_vtable_entry_inst_id = AddLoadedImportRef(\n          resolver,\n          GetSingletonType(resolver.local_context(),\n                           SemIR::SpecificFunctionType::TypeInstId),\n          import_vtable_entry_inst_id, local_attached_constant_id);\n    }\n  }\n\n  auto class_id = SemIR::ClassId::None;\n  if (class_const_inst.Is<SemIR::ClassType>()) {\n    class_id = class_const_inst.As<SemIR::ClassType>().class_id;\n  } else {\n    auto generic_class_type =\n        resolver.local_types().GetAs<SemIR::GenericClassType>(\n            class_const_inst.type_id());\n    class_id = generic_class_type.class_id;\n  }\n\n  auto new_vtable_id = resolver.local_vtables().Add(\n      {{.class_id = class_id,\n        .virtual_functions_id =\n            resolver.local_inst_blocks().Add(lazy_virtual_functions)}});\n\n  return ResolveResult::Deduplicated<SemIR::VtableDecl>(\n      resolver, {.type_id = GetPointerType(resolver.local_context(),\n                                           SemIR::VtableType::TypeInstId),\n                 .vtable_id = new_vtable_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::VtablePtr inst) -> ResolveResult {\n  auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);\n\n  auto vtable_const_id = GetLocalConstantId(\n      resolver, resolver.import_classes()\n                    .Get(resolver.import_vtables().Get(inst.vtable_id).class_id)\n                    .vtable_decl_id);\n  auto vtable_const_inst = resolver.local_insts().Get(\n      resolver.local_constant_values().GetInstId(vtable_const_id));\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::VtablePtr>(\n      resolver,\n      {.type_id = GetPointerType(resolver.local_context(),\n                                 SemIR::VtableType::TypeInstId),\n       .vtable_id = vtable_const_inst.As<SemIR::VtableDecl>().vtable_id,\n       .specific_id =\n           GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data)});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FunctionType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto fn_val_id = GetLocalConstantInstId(\n      resolver,\n      resolver.import_functions().Get(inst.function_id).first_decl_id());\n\n  auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n  auto fn_type_id = resolver.local_insts().Get(fn_val_id).type_id();\n  return ResolveResult::Deduplicated<SemIR::FunctionType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .function_id = resolver.local_types()\n                                    .GetAs<SemIR::FunctionType>(fn_type_id)\n                                    .function_id,\n                 .specific_id = GetOrAddLocalSpecific(\n                     resolver, inst.specific_id, specific_data)});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FunctionTypeWithSelfType inst)\n    -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto interface_function_type_id =\n      GetLocalTypeInstId(resolver, inst.interface_function_type_id);\n  auto self_id = GetLocalConstantInstId(resolver, inst.self_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::FunctionTypeWithSelfType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .interface_function_type_id = interface_function_type_id,\n                 .self_id = self_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::GenericClassType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto class_val_id = GetLocalConstantInstId(\n      resolver,\n      resolver.import_classes().Get(inst.class_id).first_owning_decl_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n  auto class_val = resolver.local_insts().Get(class_val_id);\n  CARBON_CHECK(\n      resolver.local_types().Is<SemIR::GenericClassType>(class_val.type_id()));\n  return ResolveResult::Done(\n      resolver.local_types().GetConstantId(class_val.type_id()));\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::GenericInterfaceType inst)\n    -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto interface_val_id = GetLocalConstantInstId(\n      resolver,\n      resolver.import_interfaces().Get(inst.interface_id).first_owning_decl_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n  auto interface_val = resolver.local_insts().Get(interface_val_id);\n  CARBON_CHECK(resolver.local_types().Is<SemIR::GenericInterfaceType>(\n      interface_val.type_id()));\n  return ResolveResult::Done(\n      resolver.local_types().GetConstantId(interface_val.type_id()));\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::GenericNamedConstraintType inst)\n    -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto constraint_val_id =\n      GetLocalConstantInstId(resolver, resolver.import_named_constraints()\n                                           .Get(inst.named_constraint_id)\n                                           .first_owning_decl_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n  auto constraint_val = resolver.local_insts().Get(constraint_val_id);\n  CARBON_CHECK(resolver.local_types().Is<SemIR::GenericNamedConstraintType>(\n      constraint_val.type_id()));\n  return ResolveResult::Done(\n      resolver.local_types().GetConstantId(constraint_val.type_id()));\n}\n\n// Make a declaration of an impl. This is done as a separate step from\n// importing the impl definition in order to resolve cycles.\nstatic auto ImportImplDecl(ImportContext& context,\n                           const SemIR::Impl& import_impl,\n                           SemIR::InstId witness_id)\n    -> std::pair<SemIR::ImplId, SemIR::ConstantId> {\n  SemIR::ImplDecl impl_decl = {.impl_id = SemIR::ImplId::None,\n                               .decl_block_id = SemIR::InstBlockId::Empty};\n  auto impl_decl_id = AddPlaceholderImportedInst(\n      context, import_impl.latest_decl_id(), impl_decl);\n  impl_decl.impl_id = context.local_impls().Add(\n      {GetIncompleteLocalEntityBase(context, impl_decl_id, import_impl),\n       {.self_id = SemIR::TypeInstId::None,\n        .constraint_id = SemIR::TypeInstId::None,\n        .interface = SemIR::SpecificInterface::None,\n        .witness_id = witness_id,\n        .scope_id = import_impl.is_complete() ? AddPlaceholderNameScope(context)\n                                              : SemIR::NameScopeId::None,\n        .is_final = import_impl.is_final}});\n\n  // Write the impl ID into the ImplDecl.\n  auto impl_const_id =\n      ReplacePlaceholderImportedInst(context, impl_decl_id, impl_decl);\n  return {impl_decl.impl_id, impl_const_id};\n}\n\n// Imports the definition of an impl.\nstatic auto ImportImplDefinition(ImportContext& context,\n                                 const SemIR::Impl& import_impl,\n                                 SemIR::Impl& new_impl) -> void {\n  new_impl.definition_id = new_impl.first_owning_decl_id;\n  new_impl.defined = true;\n\n  if (import_impl.scope_id.has_value()) {\n    auto& new_scope = context.local_name_scopes().Get(new_impl.scope_id);\n    new_scope.Set(new_impl.first_owning_decl_id, SemIR::NameId::None,\n                  new_impl.parent_scope_id);\n    // Import the contents of the definition scope, if we might need it. Name\n    // lookup is never performed into this scope by a user of the impl, so\n    // this is only necessary in the same library that defined the impl, in\n    // order to support defining members of the impl out of line in the impl\n    // file when the impl is defined in the API file.\n    // TODO: Check to see if this impl is owned by the API file, rather than\n    // merely being imported into it.\n    if (context.import_ir_id() == SemIR::ImportIRId::ApiForImpl) {\n      const auto& import_scope =\n          context.import_name_scopes().Get(import_impl.scope_id);\n\n      // Push a block so that we can add scoped instructions to it.\n      context.local_context().inst_block_stack().Push();\n      AddNameScopeImportRefs(context, import_scope, new_scope);\n      new_impl.body_block_id = context.local_context().inst_block_stack().Pop();\n    }\n  }\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ImplDecl inst,\n                                SemIR::ConstantId impl_const_id)\n    -> ResolveResult {\n  // TODO: This duplicates a lot of the handling of interfaces, classes, and\n  // functions. Factor out the commonality.\n  const auto& import_impl = resolver.import_impls().Get(inst.impl_id);\n  auto specific_interface_data =\n      GetLocalSpecificInterfaceData(resolver, import_impl.interface);\n  SemIR::ImplId impl_id = SemIR::ImplId::None;\n  if (!impl_const_id.has_value()) {\n    if (resolver.HasNewWork()) {\n      // This is the end of the first phase. Don't make a new impl yet if we\n      // already have new work.\n      return ResolveResult::Retry();\n    }\n\n    // On the second phase, create a forward declaration of the impl for any\n    // recursive references.\n    auto witness_id = AddImportRef(resolver, import_impl.witness_id);\n    std::tie(impl_id, impl_const_id) =\n        ImportImplDecl(resolver, import_impl, witness_id);\n  } else {\n    // On the third phase, compute the impl ID from the \"constant value\" of\n    // the declaration, which is a reference to the created ImplDecl.\n    auto impl_const_inst = resolver.local_insts().GetAs<SemIR::ImplDecl>(\n        resolver.local_constant_values().GetInstId(impl_const_id));\n    impl_id = impl_const_inst.impl_id;\n  }\n\n  // Load constants for the definition.\n  auto parent_scope_id =\n      GetLocalNameScopeId(resolver, import_impl.parent_scope_id);\n  auto implicit_param_patterns = GetLocalInstBlockContents(\n      resolver, import_impl.implicit_param_patterns_id);\n  auto generic_data = GetLocalGenericData(resolver, import_impl.generic_id);\n  auto self_const_id = GetLocalConstantId(resolver, import_impl.self_id);\n  auto constraint_const_id =\n      GetLocalConstantId(resolver, import_impl.constraint_id);\n  auto& new_impl = resolver.local_impls().Get(impl_id);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry(impl_const_id, new_impl.first_decl_id());\n  }\n\n  new_impl.parent_scope_id = parent_scope_id;\n  new_impl.implicit_param_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_impl.implicit_param_patterns_id,\n      implicit_param_patterns);\n\n  // Create instructions for self and constraint to hold the symbolic constant\n  // value for a generic impl.\n  new_impl.self_id =\n      AddLoadedImportRefForType(resolver, import_impl.self_id, self_const_id);\n  new_impl.constraint_id = AddLoadedImportRefForType(\n      resolver, import_impl.constraint_id, constraint_const_id);\n  new_impl.interface = GetLocalSpecificInterface(\n      resolver, import_impl.interface, specific_interface_data);\n  // Create a local IdentifiedFacetType for the imported facet type, since impl\n  // declarations always identify the facet type.\n  if (auto facet_type = resolver.local_insts().TryGetAs<SemIR::FacetType>(\n          resolver.local_constant_values().GetInstId(constraint_const_id))) {\n    // Lookups later will be with the unattached constant, whereas\n    // GetLocalConstantId gave us an attached constant.\n    auto unattached_self_const_id =\n        resolver.local_constant_values().GetUnattachedConstant(self_const_id);\n    RequireIdentifiedFacetType(\n        resolver.local_context(), SemIR::LocId::None, unattached_self_const_id,\n        *facet_type, []([[maybe_unused]] auto& builder) {\n          CARBON_FATAL(\"Imported impl constraint can't be identified\");\n        });\n  }\n  if (import_impl.is_complete()) {\n    ImportImplDefinition(resolver, import_impl, new_impl);\n  }\n\n  // If the `impl` is declared in the API file corresponding to the current\n  // file, add this to impl lookup so that it can be found by redeclarations\n  // in the current file.\n  if (resolver.import_ir_id() == SemIR::ImportIRId::ApiForImpl) {\n    resolver.local_impls().GetOrAddLookupBucket(new_impl).push_back(impl_id);\n  }\n\n  return ResolveResult::FinishGenericOrDone(\n      resolver, impl_const_id, new_impl.first_decl_id(), import_impl.generic_id,\n      new_impl.generic_id, generic_data);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::RequireImplsDecl inst,\n                                SemIR::ConstantId require_decl_const_id)\n    -> ResolveResult {\n  const auto& import_require =\n      resolver.import_require_impls().Get(inst.require_impls_id);\n\n  auto require_decl_id = SemIR::InstId::None;\n  auto require_impls_id = SemIR::RequireImplsId::None;\n  if (!require_decl_const_id.has_value()) {\n    // Phase one: Make the decl and structure with placeholder values to be\n    // filled in. Begin the generic so instructions can be attached to it.\n    SemIR::RequireImplsDecl require_decl = {\n        .require_impls_id = SemIR::RequireImplsId::None,\n        .decl_block_id = SemIR::InstBlockId::Empty};\n    auto require_decl_id = AddPlaceholderImportedInst(\n        resolver, import_require.decl_id, require_decl);\n    require_impls_id = resolver.local_require_impls().Add(\n        {.self_id = SemIR::TypeInstId::None,\n         .facet_type_inst_id = SemIR::TypeInstId::None,\n         .decl_id = require_decl_id,\n         .parent_scope_id = SemIR::NameScopeId::None,\n         .generic_id = ImportIncompleteGeneric(resolver, require_decl_id,\n                                               import_require.generic_id)});\n\n    // Write the RequireImplsId into the RequireImplsDecl.\n    require_decl.require_impls_id = require_impls_id;\n    require_decl_const_id =\n        ReplacePlaceholderImportedInst(resolver, require_decl_id, require_decl);\n  } else {\n    // Phase two: Get the `require_decl_id` and `require_impls_id` from the\n    // RequireImplsDecl constructed in phase one.\n    require_decl_id =\n        resolver.local_constant_values().GetInstId(require_decl_const_id);\n    require_impls_id = resolver.local_insts()\n                           .GetAs<SemIR::RequireImplsDecl>(require_decl_id)\n                           .require_impls_id;\n  }\n\n  // Load dependent constants.\n  auto parent_scope_id =\n      GetLocalNameScopeId(resolver, import_require.parent_scope_id);\n  auto generic_data = GetLocalGenericData(resolver, import_require.generic_id);\n  auto self_const_id = GetLocalConstantId(resolver, import_require.self_id);\n  auto facet_type_const_id =\n      GetLocalConstantId(resolver, import_require.facet_type_inst_id);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry(require_decl_const_id, require_decl_id);\n  }\n\n  // Fill in the RequireImpls structure.\n  auto& new_require = resolver.local_require_impls().Get(require_impls_id);\n  new_require.self_id = AddLoadedImportRefForType(\n      resolver, import_require.self_id, self_const_id);\n  new_require.facet_type_inst_id = AddLoadedImportRefForType(\n      resolver, import_require.facet_type_inst_id, facet_type_const_id);\n  new_require.extend_self = import_require.extend_self;\n  new_require.parent_scope_id = parent_scope_id;\n\n  return ResolveResult::FinishGenericOrDone(\n      resolver, require_decl_const_id, require_decl_id,\n      import_require.generic_id, new_require.generic_id, generic_data);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ImportRefLoaded /*inst*/,\n                                SemIR::InstId inst_id) -> ResolveResult {\n  // Return the constant for the instruction of the imported constant.\n  auto constant_id = resolver.import_constant_values().Get(inst_id);\n  CARBON_CHECK(constant_id.has_value(),\n               \"Loaded import ref has no constant value\");\n  if (!constant_id.is_constant()) {\n    resolver.local_context().TODO(\n        inst_id, \"Non-constant ImportRefLoaded (comes up with var)\");\n    return ResolveResult::Done(constant_id);\n  }\n\n  auto new_constant_id = GetLocalConstantId(resolver, constant_id);\n  return ResolveResult::RetryOrDone(resolver, new_constant_id);\n}\n\n// Make a declaration of an interface. This is done as a separate step from\n// importing the interface definition in order to resolve cycles.\nstatic auto ImportInterfaceDecl(ImportContext& context,\n                                const SemIR::Interface& import_interface,\n                                SemIR::SpecificId enclosing_specific_id)\n    -> std::pair<SemIR::InterfaceId, SemIR::ConstantId> {\n  SemIR::InterfaceDecl interface_decl = {\n      .type_id = SemIR::TypeType::TypeId,\n      .interface_id = SemIR::InterfaceId::None,\n      .decl_block_id = SemIR::InstBlockId::Empty};\n  auto interface_decl_id = AddPlaceholderImportedInst(\n      context, import_interface.first_owning_decl_id, interface_decl);\n\n  // Start with an incomplete interface.\n  //\n  // The generic_with_self_id is constructed by the InterfaceWithSelfDecl\n  // instruction inside the InterfaceDecl's body.\n  interface_decl.interface_id = context.local_interfaces().Add(\n      {GetIncompleteLocalEntityBase(context, interface_decl_id,\n                                    import_interface),\n       {.scope_without_self_id = import_interface.is_complete()\n                                     ? AddPlaceholderNameScope(context)\n                                     : SemIR::NameScopeId::None,\n        .scope_with_self_id = import_interface.is_complete()\n                                  ? AddPlaceholderNameScope(context)\n                                  : SemIR::NameScopeId::None}});\n\n  if (import_interface.has_parameters()) {\n    interface_decl.type_id = GetGenericInterfaceType(\n        context.local_context(), interface_decl.interface_id,\n        enclosing_specific_id);\n  }\n\n  // Write the interface ID into the InterfaceDecl.\n  auto interface_const_id = ReplacePlaceholderImportedInst(\n      context, interface_decl_id, interface_decl);\n  return {interface_decl.interface_id, interface_const_id};\n}\n\n// Imports the definition for an interface that has been imported as a forward\n// declaration.\nstatic auto ImportInterfaceDefinition(ImportContext& context,\n                                      const SemIR::Interface& import_interface,\n                                      SemIR::Interface& new_interface,\n                                      SemIR::InstId self_param_id) -> void {\n  auto& new_scope =\n      context.local_name_scopes().Get(new_interface.scope_without_self_id);\n  const auto& import_scope =\n      context.import_name_scopes().Get(import_interface.scope_without_self_id);\n\n  // Push a block so that we can add scoped instructions to it.\n  context.local_context().inst_block_stack().Push();\n  InitializeNameScopeAndImportRefs(\n      context, import_scope, new_scope, new_interface.first_owning_decl_id,\n      SemIR::NameId::None, new_interface.parent_scope_id);\n  new_interface.body_block_without_self_id =\n      context.local_context().inst_block_stack().Pop();\n  new_interface.self_param_id = self_param_id;\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::InterfaceDecl inst,\n                                SemIR::ConstantId interface_const_id)\n    -> ResolveResult {\n  const auto& import_interface =\n      resolver.import_interfaces().Get(inst.interface_id);\n\n  auto interface_id = SemIR::InterfaceId::None;\n  if (!interface_const_id.has_value()) {\n    auto import_specific_id = SemIR::SpecificId::None;\n    if (auto import_generic_interface_type =\n            resolver.import_types().TryGetAs<SemIR::GenericInterfaceType>(\n                inst.type_id)) {\n      import_specific_id = import_generic_interface_type->enclosing_specific_id;\n    }\n    auto specific_data = GetLocalSpecificData(resolver, import_specific_id);\n    if (resolver.HasNewWork()) {\n      // This is the end of the first phase. Don't make a new interface yet if\n      // we already have new work.\n      return ResolveResult::Retry();\n    }\n\n    // On the second phase, create a forward declaration of the interface.\n    auto enclosing_specific_id =\n        GetOrAddLocalSpecific(resolver, import_specific_id, specific_data);\n    std::tie(interface_id, interface_const_id) =\n        ImportInterfaceDecl(resolver, import_interface, enclosing_specific_id);\n  } else {\n    // On the third phase, compute the interface ID from the constant value of\n    // the declaration.\n    auto interface_const_inst = resolver.local_insts().Get(\n        resolver.local_constant_values().GetInstId(interface_const_id));\n    if (auto facet_type = interface_const_inst.TryAs<SemIR::FacetType>()) {\n      const SemIR::FacetTypeInfo& facet_type_info =\n          resolver.local_facet_types().Get(facet_type->facet_type_id);\n      auto single = facet_type_info.TryAsSingleExtend();\n      CARBON_CHECK(single);\n      interface_id = std::get<SemIR::SpecificInterface>(*single).interface_id;\n    } else {\n      auto generic_interface_type =\n          resolver.local_types().GetAs<SemIR::GenericInterfaceType>(\n              interface_const_inst.type_id());\n      interface_id = generic_interface_type.interface_id;\n    }\n  }\n\n  auto parent_scope_id =\n      GetLocalNameScopeId(resolver, import_interface.parent_scope_id);\n  auto implicit_param_patterns = GetLocalInstBlockContents(\n      resolver, import_interface.implicit_param_patterns_id);\n  auto param_patterns =\n      GetLocalInstBlockContents(resolver, import_interface.param_patterns_id);\n  auto generic_data =\n      GetLocalGenericData(resolver, import_interface.generic_id);\n  auto require_impls = GetLocalRequireImplsBlockContents(\n      resolver, import_interface.require_impls_block_id);\n\n  std::optional<SemIR::InstId> self_param_id;\n  if (import_interface.is_complete()) {\n    // Note the TODO on ResolveLocalEvalBlock, the generic eval block is rebuilt\n    // instead of being imported. When it's imported maybe this should be an\n    // ImportRef?\n    self_param_id =\n        GetLocalConstantInstId(resolver, import_interface.self_param_id);\n\n    // Importing the `generic_with_self_id` imports the InterfaceWithSelfDecl\n    // which sets the associated constants in the interface (if it's complete)\n    // which marks the local interface as complete. The InterfaceWithSelfDecl\n    // also sets the `generic_with_self_id` field  on the local interface.\n    GetLocalConstantId(resolver, import_interface.generic_with_self_id);\n  }\n  auto& new_interface = resolver.local_interfaces().Get(interface_id);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry(interface_const_id,\n                                new_interface.first_decl_id());\n  }\n\n  new_interface.parent_scope_id = parent_scope_id;\n  new_interface.implicit_param_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_interface.implicit_param_patterns_id,\n      implicit_param_patterns);\n  new_interface.param_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_interface.param_patterns_id, param_patterns);\n  new_interface.require_impls_block_id = GetLocalCanonicalRequireImplsBlockId(\n      resolver, import_interface.require_impls_block_id, require_impls);\n\n  if (import_interface.is_complete()) {\n    CARBON_CHECK(self_param_id);\n    ImportInterfaceDefinition(resolver, import_interface, new_interface,\n                              *self_param_id);\n  }\n\n  // The interface's `generic_with_self_id` is filled out and finished by\n  // importing the InterfaceWithSelfDecl instruction which we find inside the\n  // InterfaceDecl.\n  return ResolveResult::FinishGenericOrDone(\n      resolver, interface_const_id, new_interface.first_decl_id(),\n      import_interface.generic_id, new_interface.generic_id, generic_data);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::InterfaceWithSelfDecl inst,\n                                SemIR::ConstantId const_id) -> ResolveResult {\n  auto interface_const_id = GetLocalConstantId(\n      resolver,\n      resolver.import_interfaces().Get(inst.interface_id).first_owning_decl_id);\n\n  // These are set differently in each phase.\n  auto decl_id = SemIR::InstId::None;\n  auto local_interface_id = SemIR::InterfaceId::None;\n  auto generic_with_self_id = SemIR::GenericId::None;\n\n  // Note that InterfaceWithSelfDecl always occurs inside an InterfaceDecl, so\n  // the import here can rely on the `Interface` already existing.\n\n  auto import_generic_with_self_id =\n      resolver.import_interfaces().Get(inst.interface_id).generic_with_self_id;\n\n  if (!const_id.has_value()) {\n    if (resolver.HasNewWork()) {\n      // This is the end of the first phase. Don't make a new generic yet if we\n      // already have new work.\n      return ResolveResult::Retry();\n    }\n\n    // Get the local interface ID from the constant value of the interface decl,\n    // which is either a GenericInterfaceType (if generic) or a FacetType (if\n    // not).\n    auto interface_const_inst_id =\n        resolver.local_constant_values().GetInstId(interface_const_id);\n    if (auto struct_value = resolver.local_insts().TryGetAs<SemIR::StructValue>(\n            interface_const_inst_id)) {\n      auto generic_interface_type =\n          resolver.local_types().GetAs<SemIR::GenericInterfaceType>(\n              struct_value->type_id);\n      local_interface_id = generic_interface_type.interface_id;\n    } else {\n      auto local_facet_type = resolver.local_insts().GetAs<SemIR::FacetType>(\n          interface_const_inst_id);\n      const auto& local_facet_type_info =\n          resolver.local_facet_types().Get(local_facet_type.facet_type_id);\n      auto single_interface = *local_facet_type_info.TryAsSingleExtend();\n      CARBON_KIND_SWITCH(single_interface) {\n        case CARBON_KIND(SemIR::SpecificInterface specific_interface): {\n          local_interface_id = specific_interface.interface_id;\n          break;\n        }\n        case CARBON_KIND(SemIR::SpecificNamedConstraint _): {\n          CARBON_FATAL(\n              \"Unexpected NamedConstraint in InterfaceDecl value's facet type\");\n        }\n      }\n    }\n\n    // On the second phase, create a local decl instruction with a local generic\n    // ID. Store that generic ID in the local interface.\n    const auto& import_generic =\n        resolver.import_generics().Get(import_generic_with_self_id);\n\n    SemIR::InterfaceWithSelfDecl interface_with_self_decl = {\n        .interface_id = SemIR::InterfaceId::None};\n    decl_id = AddPlaceholderImportedInst(resolver, import_generic.decl_id,\n                                         interface_with_self_decl);\n    generic_with_self_id =\n        ImportIncompleteGeneric(resolver, decl_id, import_generic_with_self_id);\n    interface_with_self_decl.interface_id = local_interface_id;\n    const_id = ReplacePlaceholderImportedInst(resolver, decl_id,\n                                              interface_with_self_decl);\n\n    resolver.local_interfaces().Get(local_interface_id).generic_with_self_id =\n        generic_with_self_id;\n  } else {\n    // On the third phase, get the interface, decl and generic IDs from the\n    // constant value of the decl (which is itself) from the second phase.\n    auto decl = resolver.local_insts().GetAs<SemIR::InterfaceWithSelfDecl>(\n        resolver.local_constant_values().GetInstId(const_id));\n    local_interface_id = decl.interface_id;\n    generic_with_self_id = resolver.local_interfaces()\n                               .Get(local_interface_id)\n                               .generic_with_self_id;\n    decl_id = resolver.local_generics().Get(generic_with_self_id).decl_id;\n  }\n\n  auto generic_with_self_data =\n      GetLocalGenericData(resolver, import_generic_with_self_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry(const_id, decl_id);\n  }\n\n  auto& local_interface = resolver.local_interfaces().Get(\n      resolver.local_insts()\n          .GetAs<SemIR::InterfaceWithSelfDecl>(decl_id)\n          .interface_id);\n  const auto& import_interface =\n      resolver.import_interfaces().Get(inst.interface_id);\n\n  auto& new_scope =\n      resolver.local_name_scopes().Get(local_interface.scope_with_self_id);\n  const auto& import_scope =\n      resolver.import_name_scopes().Get(import_interface.scope_with_self_id);\n\n  // Push a block so that we can add scoped instructions to it.\n  resolver.local_context().inst_block_stack().Push();\n  InitializeNameScopeAndImportRefs(resolver, import_scope, new_scope, decl_id,\n                                   SemIR::NameId::None,\n                                   local_interface.scope_without_self_id);\n  new_scope.set_is_interface_definition();\n  local_interface.associated_entities_id =\n      AddAssociatedEntities(resolver, local_interface.scope_with_self_id,\n                            import_interface.associated_entities_id);\n  local_interface.body_block_with_self_id =\n      resolver.local_context().inst_block_stack().Pop();\n\n  return ResolveResult::FinishGenericOrDone(\n      resolver, const_id, decl_id, import_generic_with_self_id,\n      generic_with_self_id, generic_with_self_data);\n}\n\n// Make a declaration of a named constraint. This is done as a separate step\n// from importing the constraint definition in order to resolve cycles.\nstatic auto ImportNamedConstraintDecl(\n    ImportContext& context,\n    const SemIR::NamedConstraint& import_named_constraint,\n    SemIR::SpecificId enclosing_specific_id)\n    -> std::pair<SemIR::NamedConstraintId, SemIR::ConstantId> {\n  SemIR::NamedConstraintDecl named_constraint_decl = {\n      .type_id = SemIR::TypeType::TypeId,\n      .named_constraint_id = SemIR::NamedConstraintId::None,\n      .decl_block_id = SemIR::InstBlockId::Empty};\n  auto named_constraint_decl_id = AddPlaceholderImportedInst(\n      context, import_named_constraint.first_owning_decl_id,\n      named_constraint_decl);\n\n  // Start with an incomplete named constraint.\n  //\n  // The generic_with_self_id is constructed by the NamedConstraintWithSelfDecl\n  // instruction inside the NamedConstraintDecl's body.\n  named_constraint_decl.named_constraint_id =\n      context.local_named_constraints().Add(\n          {GetIncompleteLocalEntityBase(context, named_constraint_decl_id,\n                                        import_named_constraint),\n           {.scope_without_self_id = import_named_constraint.is_complete()\n                                         ? AddPlaceholderNameScope(context)\n                                         : SemIR::NameScopeId::None,\n            .scope_with_self_id = import_named_constraint.is_complete()\n                                      ? AddPlaceholderNameScope(context)\n                                      : SemIR::NameScopeId::None}});\n\n  if (import_named_constraint.has_parameters()) {\n    named_constraint_decl.type_id = GetGenericNamedConstraintType(\n        context.local_context(), named_constraint_decl.named_constraint_id,\n        enclosing_specific_id);\n  }\n\n  // Write the named constraint ID into the NameConstraintDecl.\n  auto interface_const_id = ReplacePlaceholderImportedInst(\n      context, named_constraint_decl_id, named_constraint_decl);\n  return {named_constraint_decl.named_constraint_id, interface_const_id};\n}\n\n// Imports the definition for a named constraint that has been imported as a\n// forward declaration.\nstatic auto ImportNamedConstraintDefinition(\n    ImportContext& context,\n    const SemIR::NamedConstraint& import_named_constraint,\n    SemIR::NamedConstraint& new_named_constraint, SemIR::InstId self_param_id)\n    -> void {\n  auto& new_scope = context.local_name_scopes().Get(\n      new_named_constraint.scope_without_self_id);\n  const auto& import_scope = context.import_name_scopes().Get(\n      import_named_constraint.scope_without_self_id);\n\n  // Push a block so that we can add scoped instructions to it.\n  context.local_context().inst_block_stack().Push();\n  InitializeNameScopeAndImportRefs(context, import_scope, new_scope,\n                                   new_named_constraint.first_owning_decl_id,\n                                   SemIR::NameId::None,\n                                   new_named_constraint.parent_scope_id);\n  new_named_constraint.body_block_without_self_id =\n      context.local_context().inst_block_stack().Pop();\n  new_named_constraint.self_param_id = self_param_id;\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::NamedConstraintDecl inst,\n                                SemIR::ConstantId named_constraint_const_id)\n    -> ResolveResult {\n  const auto& import_named_constraint =\n      resolver.import_named_constraints().Get(inst.named_constraint_id);\n\n  auto named_constraint_id = SemIR::NamedConstraintId::None;\n  if (!named_constraint_const_id.has_value()) {\n    auto import_specific_id = SemIR::SpecificId::None;\n    if (auto import_generic_named_constraint_type =\n            resolver.import_types().TryGetAs<SemIR::GenericNamedConstraintType>(\n                inst.type_id)) {\n      import_specific_id =\n          import_generic_named_constraint_type->enclosing_specific_id;\n    }\n    auto specific_data = GetLocalSpecificData(resolver, import_specific_id);\n    if (resolver.HasNewWork()) {\n      // This is the end of the first phase. Don't make a new interface yet if\n      // we already have new work.\n      return ResolveResult::Retry();\n    }\n\n    // On the second phase, create a forward declaration of the interface.\n    auto enclosing_specific_id =\n        GetOrAddLocalSpecific(resolver, import_specific_id, specific_data);\n    std::tie(named_constraint_id, named_constraint_const_id) =\n        ImportNamedConstraintDecl(resolver, import_named_constraint,\n                                  enclosing_specific_id);\n  } else {\n    // On the third phase, compute the interface ID from the constant value of\n    // the declaration.\n    auto named_constraint_const_inst = resolver.local_insts().Get(\n        resolver.local_constant_values().GetInstId(named_constraint_const_id));\n    if (auto facet_type =\n            named_constraint_const_inst.TryAs<SemIR::FacetType>()) {\n      const SemIR::FacetTypeInfo& facet_type_info =\n          resolver.local_facet_types().Get(facet_type->facet_type_id);\n      auto single = facet_type_info.TryAsSingleExtend();\n      CARBON_CHECK(single);\n      named_constraint_id =\n          std::get<SemIR::SpecificNamedConstraint>(*single).named_constraint_id;\n    } else {\n      auto generic_named_constraint_type =\n          resolver.local_types().GetAs<SemIR::GenericNamedConstraintType>(\n              named_constraint_const_inst.type_id());\n      named_constraint_id = generic_named_constraint_type.named_constraint_id;\n    }\n  }\n\n  auto parent_scope_id =\n      GetLocalNameScopeId(resolver, import_named_constraint.parent_scope_id);\n  auto implicit_param_patterns = GetLocalInstBlockContents(\n      resolver, import_named_constraint.implicit_param_patterns_id);\n  auto param_patterns = GetLocalInstBlockContents(\n      resolver, import_named_constraint.param_patterns_id);\n  auto generic_data =\n      GetLocalGenericData(resolver, import_named_constraint.generic_id);\n  auto require_impls = GetLocalRequireImplsBlockContents(\n      resolver, import_named_constraint.require_impls_block_id);\n\n  std::optional<SemIR::InstId> self_param_id;\n  if (import_named_constraint.is_complete()) {\n    self_param_id =\n        GetLocalConstantInstId(resolver, import_named_constraint.self_param_id);\n\n    // Importing the `generic_with_self_id` imports the\n    // NamedConstraintWithSelfDecl which (if it's complete) marks the local\n    // named constraint as complete. The NamedConstraintWithSelfDecl also sets\n    // the `generic_with_self_id` field  on the local interface.\n    GetLocalConstantId(resolver, import_named_constraint.generic_with_self_id);\n  }\n  auto& new_named_constraint =\n      resolver.local_named_constraints().Get(named_constraint_id);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry(named_constraint_const_id,\n                                new_named_constraint.first_decl_id());\n  }\n\n  new_named_constraint.parent_scope_id = parent_scope_id;\n  new_named_constraint.implicit_param_patterns_id =\n      GetLocalCanonicalInstBlockId(\n          resolver, import_named_constraint.implicit_param_patterns_id,\n          implicit_param_patterns);\n  new_named_constraint.param_patterns_id = GetLocalCanonicalInstBlockId(\n      resolver, import_named_constraint.param_patterns_id, param_patterns);\n  new_named_constraint.require_impls_block_id =\n      GetLocalCanonicalRequireImplsBlockId(\n          resolver, import_named_constraint.require_impls_block_id,\n          require_impls);\n\n  if (import_named_constraint.is_complete()) {\n    CARBON_CHECK(self_param_id);\n    ImportNamedConstraintDefinition(resolver, import_named_constraint,\n                                    new_named_constraint, *self_param_id);\n  }\n\n  // The named constraint's `generic_with_self_id` is filled out and finished by\n  // importing the NamedConstraintWithSelfDecl instruction which we find inside\n  // the NamedConstraintDecl.\n  return ResolveResult::FinishGenericOrDone(\n      resolver, named_constraint_const_id, new_named_constraint.first_decl_id(),\n      import_named_constraint.generic_id, new_named_constraint.generic_id,\n      generic_data);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::NamedConstraintWithSelfDecl inst,\n                                SemIR::ConstantId const_id) -> ResolveResult {\n  auto constraint_const_id =\n      GetLocalConstantId(resolver, resolver.import_named_constraints()\n                                       .Get(inst.named_constraint_id)\n                                       .first_owning_decl_id);\n\n  // These are set differently in each phase.\n  auto decl_id = SemIR::InstId::None;\n  auto local_constraint_id = SemIR::NamedConstraintId::None;\n  auto generic_with_self_id = SemIR::GenericId::None;\n\n  // Note that NamedConstraintWithSelfDecl always occurs inside an\n  // NamedConstraintDecl, so the import here can rely on the `NamedConstraint`\n  // already existing.\n\n  auto import_generic_with_self_id = resolver.import_named_constraints()\n                                         .Get(inst.named_constraint_id)\n                                         .generic_with_self_id;\n\n  if (!const_id.has_value()) {\n    if (resolver.HasNewWork()) {\n      // This is the end of the first phase. Don't make a new generic yet if we\n      // already have new work.\n      return ResolveResult::Retry();\n    }\n\n    // Get the local named constraint ID from the constant value of the named\n    // constraint decl, which is either a GenericNamedConstraintType (if\n    // generic) or a FacetType (if not).\n    auto constraint_const_inst_id =\n        resolver.local_constant_values().GetInstId(constraint_const_id);\n    if (auto struct_value = resolver.local_insts().TryGetAs<SemIR::StructValue>(\n            constraint_const_inst_id)) {\n      auto generic_constraint_type =\n          resolver.local_types().GetAs<SemIR::GenericNamedConstraintType>(\n              struct_value->type_id);\n      local_constraint_id = generic_constraint_type.named_constraint_id;\n    } else {\n      auto local_facet_type = resolver.local_insts().GetAs<SemIR::FacetType>(\n          constraint_const_inst_id);\n      const auto& local_facet_type_info =\n          resolver.local_facet_types().Get(local_facet_type.facet_type_id);\n      auto single_interface = *local_facet_type_info.TryAsSingleExtend();\n      CARBON_KIND_SWITCH(single_interface) {\n        case CARBON_KIND(SemIR::SpecificNamedConstraint specific_constraint): {\n          local_constraint_id = specific_constraint.named_constraint_id;\n          break;\n        }\n        case CARBON_KIND(SemIR::SpecificInterface _): {\n          CARBON_FATAL(\n              \"Unexpected Interface in NamedConstraintDecl value's facet type\");\n        }\n      }\n    }\n\n    // On the second phase, create a local decl instruction with a local generic\n    // ID. Store that generic ID in the local interface.\n    const auto& import_generic =\n        resolver.import_generics().Get(import_generic_with_self_id);\n\n    SemIR::NamedConstraintWithSelfDecl constraint_with_self_decl = {\n        .named_constraint_id = SemIR::NamedConstraintId::None};\n    decl_id = AddPlaceholderImportedInst(resolver, import_generic.decl_id,\n                                         constraint_with_self_decl);\n    generic_with_self_id =\n        ImportIncompleteGeneric(resolver, decl_id, import_generic_with_self_id);\n    constraint_with_self_decl.named_constraint_id = local_constraint_id;\n    const_id = ReplacePlaceholderImportedInst(resolver, decl_id,\n                                              constraint_with_self_decl);\n\n    resolver.local_named_constraints()\n        .Get(local_constraint_id)\n        .generic_with_self_id = generic_with_self_id;\n  } else {\n    // On the third phase, get the interface, decl and generic IDs from the\n    // constant value of the decl (which is itself) from the second phase.\n    auto decl =\n        resolver.local_insts().GetAs<SemIR::NamedConstraintWithSelfDecl>(\n            resolver.local_constant_values().GetInstId(const_id));\n    local_constraint_id = decl.named_constraint_id;\n    generic_with_self_id = resolver.local_named_constraints()\n                               .Get(local_constraint_id)\n                               .generic_with_self_id;\n    decl_id = resolver.local_generics().Get(generic_with_self_id).decl_id;\n  }\n\n  auto generic_with_self_data =\n      GetLocalGenericData(resolver, import_generic_with_self_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry(const_id, decl_id);\n  }\n\n  auto& local_constraint = resolver.local_named_constraints().Get(\n      resolver.local_insts()\n          .GetAs<SemIR::NamedConstraintWithSelfDecl>(decl_id)\n          .named_constraint_id);\n  const auto& import_constraint =\n      resolver.import_named_constraints().Get(inst.named_constraint_id);\n\n  auto& new_scope =\n      resolver.local_name_scopes().Get(local_constraint.scope_with_self_id);\n  const auto& import_scope =\n      resolver.import_name_scopes().Get(import_constraint.scope_with_self_id);\n\n  // Push a block so that we can add scoped instructions to it.\n  resolver.local_context().inst_block_stack().Push();\n  InitializeNameScopeAndImportRefs(resolver, import_scope, new_scope, decl_id,\n                                   SemIR::NameId::None,\n                                   local_constraint.scope_without_self_id);\n  local_constraint.complete = import_constraint.complete;\n  local_constraint.body_block_with_self_id =\n      resolver.local_context().inst_block_stack().Pop();\n\n  return ResolveResult::FinishGenericOrDone(\n      resolver, const_id, decl_id, import_generic_with_self_id,\n      generic_with_self_id, generic_with_self_data);\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FacetAccessType inst) -> ResolveResult {\n  auto facet_value_inst_id =\n      GetLocalConstantInstId(resolver, inst.facet_value_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::FacetAccessType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .facet_value_inst_id = facet_value_inst_id});\n}\n\n// Collects and assigns constants for a `FacetTypeInfo`. Discards constants when\n// `local_facet_type_info` is null.\nstatic auto ResolveFacetTypeInfo(\n    ImportRefResolver& resolver,\n    const SemIR::FacetTypeInfo& import_facet_type_info,\n    SemIR::FacetTypeInfo* local_facet_type_info) -> void {\n  if (local_facet_type_info) {\n    local_facet_type_info->extend_constraints.reserve(\n        import_facet_type_info.extend_constraints.size());\n  }\n  for (auto interface : import_facet_type_info.extend_constraints) {\n    auto data = GetLocalSpecificInterfaceData(resolver, interface);\n    if (local_facet_type_info) {\n      local_facet_type_info->extend_constraints.push_back(\n          GetLocalSpecificInterface(resolver, interface, data));\n    }\n  }\n\n  if (local_facet_type_info) {\n    local_facet_type_info->self_impls_constraints.reserve(\n        import_facet_type_info.self_impls_constraints.size());\n  }\n  for (auto interface : import_facet_type_info.self_impls_constraints) {\n    auto data = GetLocalSpecificInterfaceData(resolver, interface);\n    if (local_facet_type_info) {\n      local_facet_type_info->self_impls_constraints.push_back(\n          GetLocalSpecificInterface(resolver, interface, data));\n    }\n  }\n\n  if (local_facet_type_info) {\n    local_facet_type_info->extend_named_constraints.reserve(\n        import_facet_type_info.extend_named_constraints.size());\n  }\n  for (auto constraint : import_facet_type_info.extend_named_constraints) {\n    auto data = GetLocalSpecificNamedConstraintData(resolver, constraint);\n    if (local_facet_type_info) {\n      local_facet_type_info->extend_named_constraints.push_back(\n          GetLocalSpecificNamedConstraint(resolver, constraint, data));\n    }\n  }\n\n  if (local_facet_type_info) {\n    local_facet_type_info->self_impls_named_constraints.reserve(\n        import_facet_type_info.self_impls_named_constraints.size());\n  }\n  for (auto constraint : import_facet_type_info.self_impls_named_constraints) {\n    auto data = GetLocalSpecificNamedConstraintData(resolver, constraint);\n    if (local_facet_type_info) {\n      local_facet_type_info->self_impls_named_constraints.push_back(\n          GetLocalSpecificNamedConstraint(resolver, constraint, data));\n    }\n  }\n\n  if (local_facet_type_info) {\n    local_facet_type_info->rewrite_constraints.reserve(\n        import_facet_type_info.rewrite_constraints.size());\n  }\n  for (auto rewrite : import_facet_type_info.rewrite_constraints) {\n    auto lhs_id = GetLocalConstantInstId(resolver, rewrite.lhs_id);\n    auto rhs_id = GetLocalConstantInstId(resolver, rewrite.rhs_id);\n    if (local_facet_type_info) {\n      local_facet_type_info->rewrite_constraints.push_back(\n          {.lhs_id = lhs_id, .rhs_id = rhs_id});\n    }\n  }\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FacetType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n\n  const SemIR::FacetTypeInfo& import_facet_type_info =\n      resolver.import_facet_types().Get(inst.facet_type_id);\n  // Ensure values are imported, but discard them to avoid allocations.\n  ResolveFacetTypeInfo(resolver, import_facet_type_info,\n                       /*local_facet_type_info=*/nullptr);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  SemIR::FacetTypeInfo local_facet_type_info = {\n      // TODO: Also process the other requirements.\n      .other_requirements = import_facet_type_info.other_requirements};\n  // Re-resolve and add values to the local `FacetTypeInfo`.\n  ResolveFacetTypeInfo(resolver, import_facet_type_info,\n                       &local_facet_type_info);\n\n  SemIR::FacetTypeId facet_type_id =\n      resolver.local_facet_types().Add(std::move(local_facet_type_info));\n  return ResolveResult::Deduplicated<SemIR::FacetType>(\n      resolver,\n      {.type_id = SemIR::TypeType::TypeId, .facet_type_id = facet_type_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::FacetValue inst) -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  auto type_inst_id = GetLocalTypeInstId(resolver, inst.type_inst_id);\n  auto witnesses = GetLocalInstBlockContents(resolver, inst.witnesses_block_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto witnesses_block_id = SemIR::InstBlockId::None;\n  if (inst.witnesses_block_id.has_value()) {\n    witnesses_block_id =\n        AddCanonicalWitnessesBlock(resolver.local_ir(), witnesses);\n  }\n\n  return ResolveResult::Deduplicated<SemIR::FacetValue>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .type_inst_id = type_inst_id,\n       .witnesses_block_id = witnesses_block_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::LookupImplWitness inst)\n    -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::WitnessType::TypeInstId);\n\n  auto query_self_inst_id =\n      GetLocalConstantInstId(resolver, inst.query_self_inst_id);\n\n  const auto& import_specific_interface =\n      resolver.import_specific_interfaces().Get(\n          inst.query_specific_interface_id);\n  auto data =\n      GetLocalSpecificInterfaceData(resolver, import_specific_interface);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto specific_interface =\n      GetLocalSpecificInterface(resolver, import_specific_interface, data);\n  auto query_specific_interface_id =\n      resolver.local_specific_interfaces().Add(specific_interface);\n  return ResolveResult::Deduplicated<SemIR::LookupImplWitness>(\n      resolver, {.type_id = GetSingletonType(resolver.local_context(),\n                                             SemIR::WitnessType::TypeInstId),\n                 .query_self_inst_id = query_self_inst_id,\n                 .query_specific_interface_id = query_specific_interface_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ImplWitness inst) -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::WitnessType::TypeInstId);\n\n  auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);\n  auto witness_table_id =\n      GetLocalConstantInstId(resolver, inst.witness_table_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto specific_id =\n      GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data);\n  return ResolveResult::Deduplicated<SemIR::ImplWitness>(\n      resolver, {.type_id = GetSingletonType(resolver.local_context(),\n                                             SemIR::WitnessType::TypeInstId),\n                 .witness_table_id = witness_table_id,\n                 .specific_id = specific_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ImplWitnessAccess inst)\n    -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  auto witness_id = GetLocalConstantInstId(resolver, inst.witness_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::ImplWitnessAccess>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .witness_id = witness_id,\n       .index = inst.index});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ImplWitnessTable inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  const auto& import_impl = resolver.import_impls().Get(inst.impl_id);\n  auto import_decl_inst_id = import_impl.first_decl_id();\n  auto local_decl_inst_id =\n      GetLocalConstantInstId(resolver, import_decl_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto impl_decl =\n      resolver.local_insts().GetAs<SemIR::ImplDecl>(local_decl_inst_id);\n  auto impl_id = impl_decl.impl_id;\n  auto elements_id = GetLocalImportRefInstBlock(resolver, inst.elements_id);\n\n  // Create a corresponding instruction to represent the table.\n  return ResolveResult::Unique<SemIR::ImplWitnessTable>(\n      resolver, import_inst_id,\n      {.elements_id = elements_id, .impl_id = impl_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::InitForm inst) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  auto type_component_const_id =\n      GetLocalConstantId(resolver, inst.type_component_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n  return ResolveResult::Deduplicated<SemIR::InitForm>(\n      resolver,\n      SemIR::InitForm{\n          .type_id =\n              resolver.local_types().GetTypeIdForTypeConstantId(type_const_id),\n          .type_component_inst_id = resolver.local_types().GetTypeInstId(\n              resolver.local_types().GetTypeIdForTypeConstantId(\n                  type_component_const_id))});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::IntValue inst) -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  // We can directly reuse the value IDs across file IRs. Otherwise, we need\n  // to add a new canonical int in this IR.\n  auto int_id = inst.int_id.is_embedded_value()\n                    ? inst.int_id\n                    : resolver.local_ints().AddSigned(\n                          resolver.import_ints().Get(inst.int_id));\n\n  return ResolveResult::Deduplicated<SemIR::IntValue>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .int_id = int_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::IntType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto bit_width_id = GetLocalConstantInstId(resolver, inst.bit_width_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::IntType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .int_kind = inst.int_kind,\n                 .bit_width_id = bit_width_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::Namespace inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  const auto& name_scope =\n      resolver.import_name_scopes().Get(inst.name_scope_id);\n  // A package from a different file becomes a child of the package here, as it\n  // would be if it were imported.\n  auto parent_scope_id =\n      inst.name_scope_id == SemIR::NameScopeId::Package\n          ? SemIR::NameScopeId::Package\n          : GetLocalNameScopeId(resolver, name_scope.parent_scope_id());\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto namespace_type_id = GetSingletonType(resolver.local_context(),\n                                            SemIR::NamespaceType::TypeInstId);\n  auto namespace_decl =\n      SemIR::Namespace{.type_id = namespace_type_id,\n                       .name_scope_id = SemIR::NameScopeId::None,\n                       .import_id = SemIR::AbsoluteInstId::None};\n  auto inst_id =\n      AddPlaceholderImportedInst(resolver, import_inst_id, namespace_decl);\n\n  auto name_id = GetLocalNameId(resolver, name_scope.name_id());\n  namespace_decl.name_scope_id =\n      resolver.local_name_scopes().Add(inst_id, name_id, parent_scope_id);\n  // Namespaces from this package are eagerly imported, so anything we load here\n  // must be a closed import.\n  resolver.local_name_scopes()\n      .Get(namespace_decl.name_scope_id)\n      .set_is_closed_import(true);\n  auto namespace_const_id =\n      ReplacePlaceholderImportedInst(resolver, inst_id, namespace_decl);\n  return {.const_id = namespace_const_id};\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::PatternType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto scrutinee_type_inst_id =\n      GetLocalTypeInstId(resolver, inst.scrutinee_type_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::PatternType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .scrutinee_type_inst_id = scrutinee_type_inst_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::PointerType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto pointee_id = GetLocalTypeInstId(resolver, inst.pointee_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::PointerType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId, .pointee_id = pointee_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::RefForm inst) -> ResolveResult {\n  auto type_component_inst_id =\n      GetLocalConstantId(resolver, inst.type_component_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::RefForm>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .type_component_inst_id = resolver.local_types().GetTypeInstId(\n                     resolver.local_types().GetTypeIdForTypeConstantId(\n                         type_component_inst_id))});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::RequireCompleteType inst)\n    -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::WitnessType::TypeInstId);\n\n  auto complete_type_inst_id =\n      GetLocalTypeInstId(resolver, inst.complete_type_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::RequireCompleteType>(\n      resolver, {.type_id = GetSingletonType(resolver.local_context(),\n                                             SemIR::WitnessType::TypeInstId),\n                 .complete_type_inst_id = complete_type_inst_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::RequireSpecificDefinition inst)\n    -> ResolveResult {\n  CARBON_CHECK(resolver.import_types().GetTypeInstId(inst.type_id) ==\n               SemIR::RequireSpecificDefinitionType::TypeInstId);\n\n  auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);\n\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto specific_id =\n      GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data);\n\n  return ResolveResult::Deduplicated<SemIR::RequireSpecificDefinition>(\n      resolver, {.type_id = GetSingletonType(\n                     resolver.local_context(),\n                     SemIR::RequireSpecificDefinitionType::TypeInstId),\n                 .specific_id = specific_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::ReturnSlotPattern inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Unique<SemIR::ReturnSlotPattern>(\n      resolver, import_inst_id,\n      {.type_id =\n           resolver.local_types().GetTypeIdForTypeConstantId(type_const_id),\n       .type_inst_id = SemIR::TypeInstId::None});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::SpecificFunction inst) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  auto callee_id = GetLocalConstantInstId(resolver, inst.callee_id);\n  auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto type_id =\n      resolver.local_types().GetTypeIdForTypeConstantId(type_const_id);\n  auto specific_id =\n      GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data);\n  return ResolveResult::Deduplicated<SemIR::SpecificFunction>(\n      resolver,\n      {.type_id = type_id, .callee_id = callee_id, .specific_id = specific_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::SpecificImplFunction inst)\n    -> ResolveResult {\n  auto callee_id = GetLocalConstantInstId(resolver, inst.callee_id);\n  auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto type_id = GetSingletonType(resolver.local_context(),\n                                  SemIR::SpecificFunctionType::TypeInstId);\n  auto specific_id =\n      GetOrAddLocalSpecific(resolver, inst.specific_id, specific_data);\n  return ResolveResult::Deduplicated<SemIR::SpecificImplFunction>(\n      resolver,\n      {.type_id = type_id, .callee_id = callee_id, .specific_id = specific_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::StructAccess inst) -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  auto struct_id = GetLocalConstantInstId(resolver, inst.struct_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  // A `struct_access` constant requires its struct operand to have a complete\n  // type.\n  CompleteTypeOrCheckFail(resolver.local_context(),\n                          resolver.local_insts().Get(struct_id).type_id());\n\n  return ResolveResult::Deduplicated<SemIR::StructAccess>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .struct_id = struct_id,\n       .index = inst.index});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::StructType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto orig_fields = resolver.import_struct_type_fields().Get(inst.fields_id);\n  llvm::SmallVector<SemIR::TypeInstId> field_type_inst_ids;\n  field_type_inst_ids.reserve(orig_fields.size());\n  for (auto field : orig_fields) {\n    field_type_inst_ids.push_back(\n        GetLocalTypeInstId(resolver, field.type_inst_id));\n  }\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  // Prepare a vector of fields for GetStructType.\n  llvm::SmallVector<SemIR::StructTypeField> new_fields;\n  new_fields.reserve(orig_fields.size());\n  for (auto [orig_field, field_type_inst_id] :\n       llvm::zip_equal(orig_fields, field_type_inst_ids)) {\n    auto name_id = GetLocalNameId(resolver, orig_field.name_id);\n    new_fields.push_back(\n        {.name_id = name_id, .type_inst_id = field_type_inst_id});\n  }\n\n  return ResolveResult::Deduplicated<SemIR::StructType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .fields_id = resolver.local_struct_type_fields().AddCanonical(\n                     new_fields)});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::StructValue inst) -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  auto elems = GetLocalInstBlockContents(resolver, inst.elements_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::StructValue>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .elements_id =\n           GetLocalCanonicalInstBlockId(resolver, inst.elements_id, elems)});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::SymbolicBindingType inst)\n    -> ResolveResult {\n  auto facet_value_inst_id =\n      GetLocalConstantInstId(resolver, inst.facet_value_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  auto entity_name_id =\n      GetLocalSymbolicEntityNameId(resolver, inst.entity_name_id);\n  return ResolveResult::Deduplicated<SemIR::SymbolicBindingType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .entity_name_id = entity_name_id,\n                 .facet_value_inst_id = facet_value_inst_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::TupleAccess inst) -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  auto tuple_id = GetLocalConstantInstId(resolver, inst.tuple_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  // A `tuple_access` constant requires its struct operand to have a complete\n  // type.\n  CompleteTypeOrCheckFail(resolver.local_context(),\n                          resolver.local_insts().Get(tuple_id).type_id());\n\n  return ResolveResult::Deduplicated<SemIR::TupleAccess>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .tuple_id = tuple_id,\n       .index = inst.index});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::TuplePattern inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  auto elements = GetLocalInstBlockContents(resolver, inst.elements_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Unique<SemIR::TuplePattern>(\n      resolver, import_inst_id,\n      {.type_id =\n           resolver.local_types().GetTypeIdForTypeConstantId(type_const_id),\n       .elements_id =\n           GetLocalCanonicalInstBlockId(resolver, inst.elements_id, elements)});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::TupleType inst) -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n\n  auto orig_type_inst_ids =\n      resolver.import_inst_blocks().Get(inst.type_elements_id);\n  // TODO: It might be nice to make the `InstBlock` in `TupleType` record in the\n  // type system that its holding `TypeInstId` elements.\n  llvm::SmallVector<SemIR::InstId> type_inst_ids;\n  type_inst_ids.reserve(orig_type_inst_ids.size());\n  for (auto elem_type_inst_id :\n       resolver.import_ir().types().GetBlockAsTypeInstIds(orig_type_inst_ids)) {\n    type_inst_ids.push_back(GetLocalTypeInstId(resolver, elem_type_inst_id));\n  }\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::TupleType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .type_elements_id = GetLocalCanonicalInstBlockId(\n                     resolver, inst.type_elements_id, type_inst_ids)});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::TupleValue inst) -> ResolveResult {\n  auto type_id = GetLocalConstantId(resolver, inst.type_id);\n  auto elems = GetLocalInstBlockContents(resolver, inst.elements_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::TupleValue>(\n      resolver,\n      {.type_id = resolver.local_types().GetTypeIdForTypeConstantId(type_id),\n       .elements_id =\n           GetLocalCanonicalInstBlockId(resolver, inst.elements_id, elems)});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::UnboundElementType inst)\n    -> ResolveResult {\n  CARBON_CHECK(inst.type_id == SemIR::TypeType::TypeId);\n  auto class_const_inst_id =\n      GetLocalTypeInstId(resolver, inst.class_type_inst_id);\n  auto elem_const_inst_id =\n      GetLocalTypeInstId(resolver, inst.element_type_inst_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Deduplicated<SemIR::UnboundElementType>(\n      resolver, {.type_id = SemIR::TypeType::TypeId,\n                 .class_type_inst_id = class_const_inst_id,\n                 .element_type_inst_id = elem_const_inst_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::VarPattern inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  auto subpattern_id = GetLocalConstantInstId(resolver, inst.subpattern_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Unique<SemIR::VarPattern>(\n      resolver, import_inst_id,\n      {.type_id =\n           resolver.local_types().GetTypeIdForTypeConstantId(type_const_id),\n       .subpattern_id = subpattern_id});\n}\n\nstatic auto TryResolveTypedInst(ImportRefResolver& resolver,\n                                SemIR::VarStorage inst,\n                                SemIR::InstId import_inst_id) -> ResolveResult {\n  auto type_const_id = GetLocalConstantId(resolver, inst.type_id);\n  auto pattern_id = GetLocalConstantInstId(resolver, inst.pattern_id);\n  if (resolver.HasNewWork()) {\n    return ResolveResult::Retry();\n  }\n\n  return ResolveResult::Unique<SemIR::VarStorage>(\n      resolver, import_inst_id,\n      {.type_id =\n           resolver.local_types().GetTypeIdForTypeConstantId(type_const_id),\n       .pattern_id = pattern_id});\n}\n\n// Tries to resolve the InstId, returning a canonical constant when ready, or\n// `None` if more has been added to the stack. This is the same as\n// TryResolveInst, except that it may resolve symbolic constants as canonical\n// constants instead of as constants associated with a particular generic.\nstatic auto TryResolveInstCanonical(ImportRefResolver& resolver,\n                                    SemIR::InstId inst_id,\n                                    SemIR::ConstantId const_id)\n    -> ResolveResult {\n  // These instruction types are imported across multiple phases to arrive at\n  // their constant value. We can't just import their constant value instruction\n  // directly.\n  auto untyped_inst = resolver.import_insts().GetWithAttachedType(inst_id);\n  CARBON_KIND_SWITCH(untyped_inst) {\n    case CARBON_KIND(SemIR::AssociatedConstantDecl inst): {\n      return TryResolveTypedInst(resolver, inst, const_id);\n    }\n    case CARBON_KIND(SemIR::ClassDecl inst): {\n      return TryResolveTypedInst(resolver, inst, const_id);\n    }\n    case CARBON_KIND(SemIR::FunctionDecl inst): {\n      return TryResolveTypedInst(resolver, inst, const_id);\n    }\n    case CARBON_KIND(SemIR::ImplDecl inst): {\n      return TryResolveTypedInst(resolver, inst, const_id);\n    }\n    case CARBON_KIND(SemIR::InterfaceDecl inst): {\n      return TryResolveTypedInst(resolver, inst, const_id);\n    }\n    case CARBON_KIND(SemIR::InterfaceWithSelfDecl inst): {\n      return TryResolveTypedInst(resolver, inst, const_id);\n    }\n    case CARBON_KIND(SemIR::NamedConstraintDecl inst): {\n      return TryResolveTypedInst(resolver, inst, const_id);\n    }\n    case CARBON_KIND(SemIR::NamedConstraintWithSelfDecl inst): {\n      return TryResolveTypedInst(resolver, inst, const_id);\n    }\n    case CARBON_KIND(SemIR::RequireImplsDecl inst): {\n      return TryResolveTypedInst(resolver, inst, const_id);\n    }\n    default:\n      break;\n  }\n\n  // Other instructions are imported in a single phase (once their dependencies\n  // are all imported).\n  CARBON_CHECK(!const_id.has_value());\n\n  auto inst_constant_id = resolver.import_constant_values().Get(inst_id);\n  if (!inst_constant_id.is_constant()) {\n    // TODO: Import of non-constant BindNames happens when importing `let`\n    // declarations.\n    CARBON_CHECK(resolver.import_insts().Is<SemIR::AnyBinding>(inst_id),\n                 \"TryResolveInst on non-constant instruction {0}\", inst_id);\n    return ResolveResult::Done(SemIR::ConstantId::NotConstant);\n  }\n\n  // Import the canonical constant value instruction for `inst_id` directly. We\n  // don't try to import the non-canonical `inst_id`.\n  auto constant_inst_id =\n      resolver.import_constant_values().GetInstId(inst_constant_id);\n  CARBON_DCHECK(resolver.import_constant_values().GetConstantInstId(\n                    constant_inst_id) == constant_inst_id,\n                \"Constant value of constant instruction should refer to \"\n                \"the same instruction\");\n\n  if (SemIR::IsSingletonInstId(constant_inst_id)) {\n    // Constants for builtins can be directly copied.\n    return ResolveResult::Done(\n        resolver.local_constant_values().Get(constant_inst_id));\n  }\n\n  auto untyped_constant_inst =\n      resolver.import_insts().GetWithAttachedType(constant_inst_id);\n  CARBON_KIND_SWITCH(untyped_constant_inst) {\n    case CARBON_KIND(SemIR::AdaptDecl inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::ArrayType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::AssociatedEntity inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::AssociatedEntityType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::BaseDecl inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::AliasBinding inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::SymbolicBinding inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::BoolLiteral inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::BoundMethod inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::Call inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::CharLiteralValue inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::ClassType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::CompleteTypeWitness inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::ConstType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::CppOverloadSetType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::CppOverloadSetValue inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::CustomWitness inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::ExportDecl inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::FacetAccessType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::FacetType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::FacetValue inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::FieldDecl inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::FloatLiteralValue inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::FloatType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::FloatValue inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::FunctionType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::FunctionTypeWithSelfType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::GenericClassType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::GenericInterfaceType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::GenericNamedConstraintType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::LookupImplWitness inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::ImplWitness inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::ImplWitnessAccess inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::ImplWitnessTable inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::ImportRefLoaded inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::InitForm inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::IntValue inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::IntType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::MaybeUnformedType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::Namespace inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::OutParamPattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::PartialType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::PatternType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::PointerType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::RefBindingPattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::RefForm inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::RefParamPattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::RequireCompleteType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::RequireSpecificDefinition inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::ReturnSlotPattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::SpecificFunction inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::SpecificImplFunction inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::StructAccess inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::StructType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::StructValue inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::SymbolicBindingPattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::SymbolicBindingType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::TupleAccess inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::TuplePattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::TupleType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::TupleValue inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::UnboundElementType inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::ValueBindingPattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::ValueParamPattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::VarParamPattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::VarPattern inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::VarStorage inst): {\n      return TryResolveTypedInst(resolver, inst, constant_inst_id);\n    }\n    case CARBON_KIND(SemIR::VtableDecl inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    case CARBON_KIND(SemIR::VtablePtr inst): {\n      return TryResolveTypedInst(resolver, inst);\n    }\n    default:\n      // Found a canonical instruction which needs to be resolved, but which is\n      // not yet handled.\n      //\n      // TODO: Could we turn this into a compile-time error?\n      CARBON_FATAL(\n          \"Missing case in TryResolveInstCanonical for instruction kind {0}\",\n          untyped_constant_inst.kind());\n  }\n}\n\n// Tries to resolve the InstId, returning a constant when ready, or `None` if\n// more has been added to the stack. A similar API is followed for all\n// following TryResolveTypedInst helper functions.\n//\n// `const_id` is `None` unless we've tried to resolve this instruction\n// before, in which case it's the previous result.\n//\n// TODO: Error is returned when support is missing, but that should go away.\nstatic auto TryResolveInst(ImportRefResolver& resolver, SemIR::InstId inst_id,\n                           SemIR::ConstantId const_id) -> ResolveResult {\n  auto inst_const_id = resolver.import_constant_values().GetAttached(inst_id);\n  if (!inst_const_id.has_value() || !inst_const_id.is_symbolic()) {\n    return TryResolveInstCanonical(resolver, inst_id, const_id);\n  }\n\n  // Try to import the generic. This might add new work.\n  const auto& symbolic_const =\n      resolver.import_constant_values().GetSymbolicConstant(inst_const_id);\n  auto generic_const_id =\n      GetLocalConstantId(resolver, symbolic_const.generic_id);\n\n  auto inner_const_id = SemIR::ConstantId::None;\n  if (const_id.has_value()) {\n    // For the third phase, extract the constant value that\n    // TryResolveInstCanonical produced previously.\n    inner_const_id = resolver.local_constant_values().GetAttached(\n        resolver.local_constant_values().GetSymbolicConstant(const_id).inst_id);\n  }\n\n  // Import the constant and rebuild the symbolic constant data.\n  auto result = TryResolveInstCanonical(resolver, inst_id, inner_const_id);\n  if (!result.const_id.has_value()) {\n    // First phase: TryResolveInstCanoncial needs a retry.\n    return result;\n  }\n\n  if (!const_id.has_value()) {\n    // Second phase: we have created an unattached constant. Create a\n    // corresponding attached constant.\n    if (symbolic_const.generic_id.has_value()) {\n      result.const_id = resolver.local_constant_values().AddSymbolicConstant(\n          {.inst_id =\n               resolver.local_constant_values().GetInstId(result.const_id),\n           .generic_id = GetLocalGenericId(resolver, generic_const_id),\n           .index = symbolic_const.index,\n           .dependence = symbolic_const.dependence});\n      if (result.decl_id.has_value()) {\n        // Overwrite the unattached symbolic constant given initially to the\n        // declaration with its final attached symbolic value.\n        resolver.local_constant_values().Set(result.decl_id, result.const_id);\n      }\n    }\n  } else {\n    // Third phase: perform a consistency check and produce the constant we\n    // created in the second phase.\n    CARBON_CHECK(result.const_id == inner_const_id,\n                 \"Constant value changed in third phase.\");\n    result.const_id = const_id;\n  }\n\n  return result;\n}\n\nauto ImportRefResolver::Resolve(SemIR::InstId inst_id) -> SemIR::ConstantId {\n  work_stack_.push_back(InstWork{.inst_id = inst_id});\n  while (!work_stack_.empty()) {\n    auto work_variant = work_stack_.back();\n    CARBON_KIND_SWITCH(work_variant) {\n      case CARBON_KIND(InstWork work): {\n        CARBON_CHECK(work.inst_id.has_value());\n\n        // Step 1: check for a constant value.\n        auto existing = FindResolvedConstId(work.inst_id);\n        if (existing.const_id.has_value() && !work.retry_with_constant_value) {\n          work_stack_.pop_back();\n          continue;\n        }\n\n        // Step 2: resolve the instruction.\n        initial_work_ = work_stack_.size();\n        auto result = TryResolveInst(*this, work.inst_id, existing.const_id);\n        CARBON_CHECK(!HasNewWork() || result.retry);\n\n        CARBON_CHECK(!existing.const_id.has_value() ||\n                         existing.const_id == result.const_id,\n                     \"Constant value changed in third phase.\");\n        if (!existing.const_id.has_value()) {\n          SetResolvedConstId(work.inst_id, existing.indirect_insts,\n                             result.const_id);\n        }\n\n        // Step 3: pop or retry.\n        if (result.retry) {\n          std::get<InstWork>(work_stack_[initial_work_ - 1])\n              .retry_with_constant_value = result.const_id.has_value();\n        } else {\n          work_stack_.pop_back();\n\n          for (const auto& resolve : result.resolve_generic) {\n            if (resolve.import_generic_id.has_value()) {\n              work_stack_.push_back(\n                  GenericWork{.import_id = resolve.import_generic_id,\n                              .local_id = resolve.local_generic_id});\n            }\n          }\n        }\n        break;\n      }\n      case CARBON_KIND(GenericWork generic_work): {\n        // Generics may require 2 steps to finish, similar to step 2 and step 3\n        // of instructions.\n        initial_work_ = work_stack_.size();\n        if (TryFinishGeneric(*this, generic_work.import_id,\n                             generic_work.local_id)) {\n          work_stack_.pop_back();\n        }\n        break;\n      }\n      case CARBON_KIND(SpecificWork specific_work): {\n        // Specifics may require 2 steps to finish, similar to step 2 and step 3\n        // of instructions.\n        initial_work_ = work_stack_.size();\n        if (TryFinishSpecific(*this, specific_work.import_id,\n                              specific_work.local_id)) {\n          work_stack_.pop_back();\n        }\n        break;\n      }\n    }\n  }\n  auto constant_id =\n      local_constant_values_for_import_insts().GetAttached(inst_id);\n  CARBON_CHECK(constant_id.has_value());\n  return constant_id;\n}\n\nauto ImportRefResolver::ResolveConstant(SemIR::ConstantId import_const_id)\n    -> SemIR::ConstantId {\n  return Resolve(GetInstWithConstantValue(import_ir(), import_const_id));\n}\n\nauto ImportRefResolver::ResolveType(SemIR::TypeId import_type_id)\n    -> SemIR::TypeId {\n  if (!import_type_id.has_value()) {\n    return import_type_id;\n  }\n\n  auto import_type_const_id = import_ir().types().GetConstantId(import_type_id);\n  CARBON_CHECK(import_type_const_id.has_value());\n\n  if (auto import_type_inst_id = import_ir().types().GetAsTypeInstId(\n          import_ir().constant_values().GetInstId(import_type_const_id));\n      SemIR::IsSingletonInstId(import_type_inst_id)) {\n    // Builtins don't require constant resolution; we can use them directly.\n    return GetSingletonType(local_context(), import_type_inst_id);\n  } else {\n    return local_types().GetTypeIdForTypeConstantId(\n        ResolveConstant(import_type_id.AsConstantId()));\n  }\n}\n\nauto ImportRefResolver::HasNewWork() -> bool {\n  CARBON_CHECK(initial_work_ <= work_stack_.size(), \"Work shouldn't decrease\");\n  return initial_work_ < work_stack_.size();\n}\n\nauto ImportRefResolver::PushSpecific(SemIR::SpecificId import_id,\n                                     SemIR::SpecificId local_id) -> void {\n  // Insert before the current instruction.\n  work_stack_.insert(\n      work_stack_.begin() + initial_work_ - 1,\n      SpecificWork{.import_id = import_id, .local_id = local_id});\n  ++initial_work_;\n}\n\nauto ImportRefResolver::GetLocalConstantValueOrPush(SemIR::InstId inst_id)\n    -> SemIR::ConstantId {\n  if (!inst_id.has_value()) {\n    return SemIR::ConstantId::None;\n  }\n  auto const_id = local_constant_values_for_import_insts().GetAttached(inst_id);\n  if (!const_id.has_value()) {\n    work_stack_.push_back(InstWork{.inst_id = inst_id});\n  }\n  return const_id;\n}\n\nauto ImportRefResolver::FindResolvedConstId(SemIR::InstId inst_id)\n    -> ResolvedConstId {\n  ResolvedConstId result;\n\n  if (auto existing_const_id =\n          local_constant_values_for_import_insts().GetAttached(inst_id);\n      existing_const_id.has_value()) {\n    result.const_id = existing_const_id;\n    return result;\n  }\n\n  const auto* cursor_ir = &import_ir();\n  auto cursor_inst_id = inst_id;\n\n  while (true) {\n    auto import_ir_inst_id = cursor_ir->insts().GetImportSource(cursor_inst_id);\n    if (!import_ir_inst_id.has_value()) {\n      return result;\n    }\n    auto ir_inst = cursor_ir->import_ir_insts().Get(import_ir_inst_id);\n    if (ir_inst.ir_id() == SemIR::ImportIRId::Cpp) {\n      local_context().TODO(SemIR::LocId::None,\n                           \"Unsupported: Importing C++ indirectly\");\n      SetResolvedConstId(inst_id, result.indirect_insts,\n                         SemIR::ErrorInst::ConstantId);\n      result.const_id = SemIR::ErrorInst::ConstantId;\n      result.indirect_insts.clear();\n      return result;\n    }\n\n    const auto* prev_ir = cursor_ir;\n    auto prev_inst_id = cursor_inst_id;\n\n    cursor_ir = cursor_ir->import_irs().Get(ir_inst.ir_id()).sem_ir;\n    auto cursor_ir_id =\n        AddImportIR(local_context(), {.decl_id = SemIR::InstId::None,\n                                      .is_export = false,\n                                      .sem_ir = cursor_ir});\n    cursor_inst_id = ir_inst.inst_id();\n\n    CARBON_CHECK(cursor_ir != prev_ir || cursor_inst_id != prev_inst_id, \"{0}\",\n                 cursor_ir->insts().Get(cursor_inst_id));\n\n    if (auto const_id =\n            local_context()\n                .import_ir_constant_values()\n                    [local_ir().import_irs().GetRawIndex(cursor_ir_id)]\n                .GetAttached(cursor_inst_id);\n        const_id.has_value()) {\n      SetResolvedConstId(inst_id, result.indirect_insts, const_id);\n      result.const_id = const_id;\n      result.indirect_insts.clear();\n      return result;\n    } else {\n      result.indirect_insts.push_back(\n          SemIR::ImportIRInst(cursor_ir_id, cursor_inst_id));\n    }\n  }\n}\n\nauto ImportRefResolver::SetResolvedConstId(\n    SemIR::InstId inst_id, llvm::ArrayRef<SemIR::ImportIRInst> indirect_insts,\n    SemIR::ConstantId const_id) -> void {\n  local_constant_values_for_import_insts().Set(inst_id, const_id);\n  SetIndirectConstantValues(local_context(), indirect_insts, const_id);\n}\n\n// Returns a list of ImportIRInsts equivalent to the ImportRef currently being\n// loaded (including the one pointed at directly by the ImportRef), and the\n// final instruction's type ID.\n//\n// This addresses cases where an ImportRefUnloaded may point at another\n// ImportRefUnloaded. The ImportRefResolver requires a SemIR with a\n// constant-evaluated version of the instruction to work with.\nstatic auto GetInstForLoad(Context& context,\n                           SemIR::ImportIRInstId import_ir_inst_id)\n    -> std::pair<llvm::SmallVector<SemIR::ImportIRInst>, SemIR::TypeId> {\n  std::pair<llvm::SmallVector<SemIR::ImportIRInst>, SemIR::TypeId> result = {\n      {}, SemIR::TypeId::None};\n  auto& [import_ir_insts, type_id] = result;\n\n  auto import_ir_inst = context.import_ir_insts().Get(import_ir_inst_id);\n  // The first ImportIRInst is added directly because the IR doesn't need to be\n  // localized.\n  import_ir_insts.push_back(import_ir_inst);\n  const auto* cursor_ir =\n      context.import_irs().Get(import_ir_inst.ir_id()).sem_ir;\n\n  while (true) {\n    auto cursor_inst =\n        cursor_ir->insts().GetWithAttachedType(import_ir_inst.inst_id());\n\n    auto import_ref = cursor_inst.TryAs<SemIR::ImportRefUnloaded>();\n    if (!import_ref) {\n      type_id = cursor_inst.type_id();\n      return result;\n    }\n\n    import_ir_inst =\n        cursor_ir->import_ir_insts().Get(import_ref->import_ir_inst_id);\n    cursor_ir = cursor_ir->import_irs().Get(import_ir_inst.ir_id()).sem_ir;\n    import_ir_insts.push_back(SemIR::ImportIRInst(\n        AddImportIR(context, {.decl_id = SemIR::InstId::None,\n                              .is_export = false,\n                              .sem_ir = cursor_ir}),\n        import_ir_inst.inst_id()));\n  }\n}\n\nauto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void {\n  auto inst = context.insts().TryGetAs<SemIR::ImportRefUnloaded>(inst_id);\n  if (!inst) {\n    return;\n  }\n\n  auto [indirect_insts, load_type_id] =\n      GetInstForLoad(context, inst->import_ir_inst_id);\n\n  // The last indirect instruction is the one to resolve. Pop it here because\n  // Resolve will assign the constant.\n  auto load_ir_inst = indirect_insts.pop_back_val();\n  ImportRefResolver resolver(&context, load_ir_inst.ir_id());\n\n  // Loading an import ref creates local constants from the import ones, but\n  // shouldn't be generating novel instructions in the semir as a side effect of\n  // that process. Doing so in a generic context would also cause them to end up\n  // in the eval block, which would be doubly wrong.\n  context.inst_block_stack().Push();\n\n  auto type_id = resolver.ResolveType(load_type_id);\n  auto constant_id = resolver.Resolve(load_ir_inst.inst_id());\n\n  CARBON_CHECK(\n      context.inst_block_stack().PeekCurrentBlockContents().empty(),\n      \"Importing an instruction shouldn't add new instructions to the \"\n      \"local inst block. Found {0} new instructions, first is {1}: {2}.\",\n      context.inst_block_stack().PeekCurrentBlockContents().size(),\n      context.inst_block_stack().PeekCurrentBlockContents().front(),\n      context.insts().Get(\n          context.inst_block_stack().PeekCurrentBlockContents().front()));\n  context.inst_block_stack().PopAndDiscard();\n\n  // Replace the ImportRefUnloaded instruction with ImportRefLoaded. This\n  // doesn't use ReplacePlaceholderImportedInst because it would trigger\n  // TryEvalInst, which we want to avoid with ImportRefs.\n  context.sem_ir().insts().Set(\n      inst_id,\n      SemIR::ImportRefLoaded{.type_id = type_id,\n                             .import_ir_inst_id = inst->import_ir_inst_id,\n                             .entity_name_id = inst->entity_name_id});\n\n  // Store the constant for both the ImportRefLoaded and indirect instructions.\n  context.constant_values().Set(inst_id, constant_id);\n  SetIndirectConstantValues(context, indirect_insts, constant_id);\n}\n\nauto ImportImplsFromApiFile(Context& context) -> void {\n  SemIR::ImportIRId import_ir_id = SemIR::ImportIRId::ApiForImpl;\n  auto& import_ir = context.import_irs().Get(import_ir_id);\n  if (!import_ir.sem_ir) {\n    return;\n  }\n\n  for (auto [impl_id, _] : import_ir.sem_ir->impls().enumerate()) {\n    // Resolve the imported impl to a local impl ID.\n    ImportImpl(context, import_ir_id, impl_id);\n  }\n}\n\nauto ImportImpl(Context& context, SemIR::ImportIRId import_ir_id,\n                SemIR::ImplId impl_id) -> void {\n  ImportRefResolver resolver(&context, import_ir_id);\n  resolver.Resolve(resolver.import_impls().Get(impl_id).first_decl_id());\n}\n\nauto ImportInterface(Context& context, SemIR::ImportIRId import_ir_id,\n                     SemIR::InterfaceId interface_id) -> SemIR::InterfaceId {\n  ImportRefResolver resolver(&context, import_ir_id);\n  auto local_id = resolver.Resolve(\n      resolver.import_interfaces().Get(interface_id).first_decl_id());\n  auto local_inst =\n      context.insts().Get(context.constant_values().GetInstId(local_id));\n\n  // A non-generic interface will import as a facet type for that single\n  // interface.\n  if (auto facet_type = local_inst.TryAs<SemIR::FacetType>()) {\n    auto single = context.facet_types()\n                      .Get(facet_type->facet_type_id)\n                      .TryAsSingleExtend();\n    CARBON_CHECK(single,\n                 \"Importing an interface didn't produce a single interface\");\n    return std::get<SemIR::SpecificInterface>(*single).interface_id;\n  }\n\n  // A generic interface will import as a constant of generic interface type.\n  auto generic_interface_type =\n      context.types().GetAs<SemIR::GenericInterfaceType>(local_inst.type_id());\n  return generic_interface_type.interface_id;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/import_ref.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_IMPORT_REF_H_\n#define CARBON_TOOLCHAIN_CHECK_IMPORT_REF_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/file.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Sets the IRs for `ImportIRId::ApiForImpl` from `import_ir`, and\n// `ImportIRId::Cpp` from defaults. Should be called before `AddImportIR` in\n// order to ensure the correct IDs are assigned.\nauto SetSpecialImportIRs(Context& context, SemIR::ImportIR import_ir) -> void;\n\n// Adds an ImportIR, returning the ID. May use an existing ID if already added.\nauto AddImportIR(Context& context, SemIR::ImportIR import_ir)\n    -> SemIR::ImportIRId;\n\n// Adds an import_ref instruction for the specified instruction in the\n// specified IR. The import_ref is initially marked as unused.\nauto AddImportRef(Context& context, SemIR::ImportIRInst import_ir_inst,\n                  SemIR::EntityNameId entity_name_id) -> SemIR::InstId;\n\n// Returns the canonical IR inst for an entity. Returns an `ImportIRInst` with\n// a `None` ir_id for an entity that was not imported. This may add an\n// `ImportIR` if it finds an indirectly referenced `File` that hasn't previously\n// been found.\nauto GetCanonicalImportIRInst(Context& context, SemIR::InstId inst_id)\n    -> SemIR::ImportIRInst;\n\n// Verifies a new instruction is the same as a previous instruction.\n// prev_import_ir_inst should come from GetCanonicalImportIRInst.\nauto VerifySameCanonicalImportIRInst(Context& context, SemIR::NameId name_id,\n                                     SemIR::InstId prev_id,\n                                     SemIR::ImportIRInst prev_import_ir_inst,\n                                     SemIR::ImportIRId new_ir_id,\n                                     const SemIR::File* new_import_ir,\n                                     SemIR::InstId new_inst_id) -> void;\n\n// If the passed in instruction ID is an ImportRefUnloaded, turns it into an\n// ImportRefLoaded for use.\nauto LoadImportRef(Context& context, SemIR::InstId inst_id) -> void;\n\n// Load all impls declared in the api file corresponding to this impl file.\nauto ImportImplsFromApiFile(Context& context) -> void;\n\n// Load an impl that is declared in an imported IR.\nauto ImportImpl(Context& context, SemIR::ImportIRId import_ir_id,\n                SemIR::ImplId impl_id) -> void;\n\n// Load an interface that is declared in an imported IR.\nauto ImportInterface(Context& context, SemIR::ImportIRId import_ir_id,\n                     SemIR::InterfaceId interface_id) -> SemIR::InterfaceId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_IMPORT_REF_H_\n"
  },
  {
    "path": "toolchain/check/inst.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/inst.h\"\n\n#include \"common/vlog.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/sem_ir/constant.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst_kind.h\"\n\nnamespace Carbon::Check {\n\n// Finish producing an instruction. Set its constant value, and register it in\n// any applicable instruction lists.\nstatic auto FinishInst(Context& context, SemIR::InstId inst_id,\n                       SemIR::Inst inst) -> void {\n  DependentInstKind dep_kind = DependentInstKind::None;\n\n  // If the instruction has a symbolic constant type, track that we need to\n  // substitute into it.\n  if (context.constant_values().DependsOnGenericParameter(\n          context.types().GetConstantId(inst.type_id()))) {\n    dep_kind.Add(DependentInstKind::SymbolicType);\n  }\n\n  // If the instruction has a constant value, compute it.\n  auto const_id = TryEvalInstUnsafe(context, inst_id, inst);\n  context.constant_values().Set(inst_id, const_id);\n  if (const_id.is_constant()) {\n    CARBON_VLOG_TO(context.vlog_stream(), \"Constant: {0} -> {1}\\n\", inst,\n                   context.constant_values().GetInstId(const_id));\n\n    // If the constant value is symbolic, track that we need to substitute into\n    // it.\n    if (context.constant_values().DependsOnGenericParameter(const_id)) {\n      dep_kind.Add(DependentInstKind::SymbolicConstant);\n    }\n  }\n\n  // Template-dependent instructions are handled separately by\n  // `AddDependentActionInst`.\n  CARBON_CHECK(\n      inst.kind().constant_kind() != SemIR::InstConstantKind::InstAction,\n      \"Use AddDependentActionInst to add an action instruction\");\n\n  // Keep track of dependent instructions.\n  if (!dep_kind.empty()) {\n    AttachDependentInstToCurrentGeneric(context,\n                                        {.inst_id = inst_id, .kind = dep_kind});\n  }\n}\n\nauto AddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId {\n  auto inst_id = AddInstInNoBlock(context, loc_id_and_inst);\n  context.inst_block_stack().AddInstId(inst_id);\n  return inst_id;\n}\n\nauto AddInstInNoBlock(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId {\n  auto inst_id = context.sem_ir().insts().AddInNoBlock(loc_id_and_inst);\n  CARBON_VLOG_TO(context.vlog_stream(), \"AddInst: {0}\\n\", loc_id_and_inst.inst);\n  FinishInst(context, inst_id, loc_id_and_inst.inst);\n  return inst_id;\n}\n\nauto AddDependentActionInst(Context& context,\n                            SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId {\n  auto inst_id = context.sem_ir().insts().AddInNoBlock(loc_id_and_inst);\n  CARBON_VLOG_TO(context.vlog_stream(), \"AddDependentActionInst: {0}\\n\",\n                 loc_id_and_inst.inst);\n\n  // Set the constant value of this instruction to point back to itself.\n  auto const_id = context.constant_values().AddSymbolicConstant(\n      {.inst_id = inst_id,\n       .generic_id = SemIR::GenericId::None,\n       .index = SemIR::GenericInstIndex::None,\n       .dependence = SemIR::ConstantDependence::Template});\n  context.constant_values().Set(inst_id, const_id);\n\n  // Register the instruction to be added to the eval block.\n  AttachDependentInstToCurrentGeneric(\n      context, {.inst_id = inst_id, .kind = DependentInstKind::Template});\n  return inst_id;\n}\n\nauto AddPatternInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId {\n  auto type_id = loc_id_and_inst.inst.type_id();\n  CARBON_CHECK(type_id == SemIR::ErrorInst::TypeId ||\n               context.types().Is<SemIR::PatternType>(type_id));\n  auto inst_id = AddInstInNoBlock(context, loc_id_and_inst);\n  context.pattern_block_stack().AddInstId(inst_id);\n  return inst_id;\n}\n\nauto GetOrAddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId {\n  CARBON_CHECK(!loc_id_and_inst.inst.kind().has_cleanup());\n\n  auto handle_constant_id = [&](SemIR::ConstantId const_id) -> SemIR::InstId {\n    CARBON_CHECK(const_id.has_value());\n\n    // If we didn't produce a constant value for the instruction, we have to add\n    // the instruction.\n    if (!const_id.is_constant()) {\n      return SemIR::InstId::None;\n    }\n\n    if (const_id.is_symbolic()) {\n      // TODO: Only add this instruction to the eval block, and don't\n      // re-evaluate it.\n      return AddInst(context, loc_id_and_inst);\n    }\n\n    CARBON_VLOG_TO(context.vlog_stream(), \"GetOrAddInst: constant: {0}\\n\",\n                   loc_id_and_inst.inst);\n    return context.constant_values().GetInstId(const_id);\n  };\n\n  // If the instruction is from desugaring, produce its constant value instead\n  // if possible.\n  if (loc_id_and_inst.loc_id.is_desugared()) {\n    switch (loc_id_and_inst.inst.kind().constant_needs_inst_id()) {\n      case SemIR::InstConstantNeedsInstIdKind::No: {\n        // Evaluation doesn't need an InstId. Just do it.\n        auto const_id = TryEvalInstUnsafe(context, SemIR::InstId::None,\n                                          loc_id_and_inst.inst);\n        if (auto result_inst_id = handle_constant_id(const_id);\n            result_inst_id.has_value()) {\n          return result_inst_id;\n        }\n        break;\n      }\n\n      case SemIR::InstConstantNeedsInstIdKind::DuringEvaluation: {\n        // Evaluation temporarily needs an InstId. Add one for now.\n        auto inst_id = AddInstInNoBlock(context, loc_id_and_inst);\n        auto const_id = context.constant_values().Get(inst_id);\n        if (auto result_inst_id = handle_constant_id(const_id);\n            result_inst_id.has_value()) {\n          // TODO: We didn't end up needing the `inst_id` instruction. Consider\n          // removing it from `insts` if it's still the most recently added\n          // instruction.\n          CARBON_CHECK(result_inst_id != inst_id);\n          return result_inst_id;\n        }\n        context.inst_block_stack().AddInstId(inst_id);\n        return inst_id;\n      }\n\n      case SemIR::InstConstantNeedsInstIdKind::Permanent: {\n        // Evaluation needs a permanent InstId. Add the instruction.\n        break;\n      }\n    }\n  }\n\n  // TODO: For an implicit instruction, this reattempts evaluation.\n  return AddInst(context, loc_id_and_inst);\n}\n\nauto EvalOrAddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::ConstantId {\n  CARBON_CHECK(!loc_id_and_inst.inst.kind().has_cleanup());\n\n  switch (loc_id_and_inst.inst.kind().constant_needs_inst_id()) {\n    case SemIR::InstConstantNeedsInstIdKind::No: {\n      // Evaluation doesn't need an InstId. Just do it.\n      return TryEvalInstUnsafe(context, SemIR::InstId::None,\n                               loc_id_and_inst.inst);\n    }\n\n    case SemIR::InstConstantNeedsInstIdKind::DuringEvaluation: {\n      // Evaluation temporarily needs an InstId. Add one for now.\n      auto inst_id = AddInstInNoBlock(context, loc_id_and_inst);\n      // TODO: Consider removing `inst_id` from `insts` if it's still the most\n      // recently added instruction.\n      return context.constant_values().Get(inst_id);\n    }\n\n    case SemIR::InstConstantNeedsInstIdKind::Permanent: {\n      // Evaluation needs a permanent InstId. Add the instruction.\n      auto inst_id = AddInst(context, loc_id_and_inst);\n      return context.constant_values().Get(inst_id);\n    }\n  }\n}\n\nauto AddPlaceholderInstInNoBlock(Context& context,\n                                 SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId {\n  auto inst_id = context.sem_ir().insts().AddInNoBlock(loc_id_and_inst);\n  CARBON_VLOG_TO(context.vlog_stream(), \"AddPlaceholderInst: {0}\\n\",\n                 loc_id_and_inst.inst);\n  context.constant_values().Set(inst_id, SemIR::ConstantId::None);\n  return inst_id;\n}\n\nauto AddPlaceholderImportedInstInNoBlock(Context& context,\n                                         SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId {\n  auto inst_id = AddPlaceholderInstInNoBlock(context, loc_id_and_inst);\n  context.imports().push_back(inst_id);\n  return inst_id;\n}\n\nauto AddPlaceholderInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId {\n  auto inst_id = AddPlaceholderInstInNoBlock(context, loc_id_and_inst);\n  context.inst_block_stack().AddInstId(inst_id);\n  return inst_id;\n}\n\nauto ReplaceLocIdAndInstBeforeConstantUse(Context& context,\n                                          SemIR::InstId inst_id,\n                                          SemIR::LocIdAndInst loc_id_and_inst)\n    -> void {\n  context.sem_ir().insts().SetLocIdAndInst(inst_id, loc_id_and_inst);\n  CARBON_VLOG_TO(context.vlog_stream(), \"ReplaceInst: {0} -> {1}\\n\", inst_id,\n                 loc_id_and_inst.inst);\n  FinishInst(context, inst_id, loc_id_and_inst.inst);\n}\n\nauto ReplaceInstBeforeConstantUse(Context& context, SemIR::InstId inst_id,\n                                  SemIR::Inst inst) -> void {\n  context.sem_ir().insts().Set(inst_id, inst);\n  CARBON_VLOG_TO(context.vlog_stream(), \"ReplaceInst: {0} -> {1}\\n\", inst_id,\n                 inst);\n  FinishInst(context, inst_id, inst);\n}\n\nauto ReplaceInstPreservingConstantValue(Context& context, SemIR::InstId inst_id,\n                                        SemIR::Inst inst) -> void {\n  // Check that the type didn't change: a change of type will change the\n  // constant value. Replace the type with the attached type.\n  auto old_type_id = context.insts().GetAttachedType(inst_id);\n  CARBON_CHECK(context.types().GetUnattachedType(old_type_id) == inst.type_id(),\n               \"Given wrong type for replacement instruction\");\n  inst.SetType(old_type_id);\n\n  // Update the instruction.\n  context.sem_ir().insts().Set(inst_id, inst);\n  CARBON_VLOG_TO(context.vlog_stream(), \"ReplaceInst: {0} -> {1}\\n\", inst_id,\n                 inst);\n\n  // Check the constant value didn't change.\n  auto old_const_id = context.constant_values().Get(inst_id);\n  auto new_const_id = TryEvalInstUnsafe(context, inst_id, inst);\n  CARBON_CHECK(old_const_id == new_const_id);\n}\n\nauto SetNamespaceNodeId(Context& context, SemIR::InstId inst_id,\n                        Parse::NodeId node_id) -> void {\n  context.sem_ir().insts().SetLocId(inst_id, SemIR::LocId(node_id));\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/inst.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_INST_H_\n#define CARBON_TOOLCHAIN_CHECK_INST_H_\n\n#include <concepts>\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n\nnamespace Carbon::Check {\n\n// Adds an instruction to the current block, returning the produced ID.\nauto AddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId;\n\n// Convenience for AddInst with typed nodes.\n//\n// As a safety check, prevent use with storage insts (see `AddInstWithCleanup`).\ntemplate <typename InstT, typename LocT>\n  requires(!InstT::Kind.has_cleanup() &&\n           std::convertible_to<LocT, SemIR::LocId>)\nauto AddInst(Context& context, LocT loc, InstT inst) -> SemIR::InstId {\n  return AddInst(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n// Like AddInst, but for instructions with a type_id of `TypeType`, which is\n// encoded in the return type of `TypeInstId`.\ninline auto AddTypeInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::TypeInstId {\n  return context.types().GetAsTypeInstId(AddInst(context, loc_id_and_inst));\n}\n\ntemplate <typename InstT, typename LocT>\n  requires(!InstT::Kind.has_cleanup() &&\n           std::convertible_to<LocT, SemIR::LocId>)\nauto AddTypeInst(Context& context, LocT loc, InstT inst) -> SemIR::TypeInstId {\n  return AddTypeInst(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n// Pushes a parse tree node onto the stack, storing the SemIR::Inst as the\n// result.\n//\n// As a safety check, prevent use with storage insts (see `AddInstWithCleanup`).\ntemplate <typename InstT>\n  requires(SemIR::Internal::HasNodeId<InstT> && !InstT::Kind.has_cleanup())\nauto AddInstAndPush(Context& context,\n                    typename decltype(InstT::Kind)::TypedNodeId node_id,\n                    InstT inst) -> void {\n  context.node_stack().Push(node_id, AddInst(context, node_id, inst));\n}\n\n// Adds an instruction in no block, returning the produced ID. Should be used\n// rarely.\nauto AddInstInNoBlock(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId;\n\n// Convenience for AddInstInNoBlock with typed nodes.\n//\n// As a safety check, prevent use with storage insts (see `AddInstWithCleanup`).\ntemplate <typename InstT, typename LocT>\n  requires(!InstT::Kind.has_cleanup() &&\n           std::convertible_to<LocT, SemIR::LocId>)\nauto AddInstInNoBlock(Context& context, LocT loc, InstT inst) -> SemIR::InstId {\n  return AddInstInNoBlock(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n// If the instruction has a desugared location and a constant value, returns\n// the constant value's instruction ID. Otherwise, same as AddInst.\nauto GetOrAddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId;\n\n// Convenience for GetOrAddInst with typed nodes.\n//\n// As a safety check, prevent use with storage insts (see `AddInstWithCleanup`).\ntemplate <typename InstT, typename LocT>\n  requires(!InstT::Kind.has_cleanup() &&\n           std::convertible_to<LocT, SemIR::LocId>)\nauto GetOrAddInst(Context& context, LocT loc, InstT inst) -> SemIR::InstId {\n  return GetOrAddInst(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n// Evaluate the given instruction, and returns the corresponding constant value.\n// Adds the instruction to the current block if it might be referenced by its\n// constant value; otherwise, does not add the instruction to an instruction\n// block.\nauto EvalOrAddInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::ConstantId;\n\n// Convenience for EvalOrAddInst with typed nodes.\n//\n// As a safety check, prevent use with storage insts (see `AddInstWithCleanup`).\ntemplate <typename InstT, typename LocT>\n  requires(!InstT::Kind.has_cleanup() &&\n           std::convertible_to<LocT, SemIR::LocId>)\nauto EvalOrAddInst(Context& context, LocT loc, InstT inst)\n    -> SemIR::ConstantId {\n  return EvalOrAddInst(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n// Adds an instruction and enqueues it to be added to the eval block of the\n// enclosing generic, returning the produced ID. The instruction is expected to\n// be a dependent template instantiation action.\nauto AddDependentActionInst(Context& context,\n                            SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId;\n\n// Convenience wrapper for AddDependentActionInst.\ntemplate <typename InstT, typename LocT>\n  requires std::convertible_to<LocT, SemIR::LocId>\nauto AddDependentActionInst(Context& context, LocT loc, InstT inst)\n    -> SemIR::InstId {\n  return AddDependentActionInst(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n// Like AddDependentActionInst, but for instructions with a type_id of\n// `TypeType`, which is encoded in the return type of `TypeInstId`.\ntemplate <typename InstT, typename LocT>\n  requires std::convertible_to<LocT, SemIR::LocId>\nauto AddDependentActionTypeInst(Context& context, LocT loc, InstT inst)\n    -> SemIR::TypeInstId {\n  return context.types().GetAsTypeInstId(\n      AddDependentActionInst(context, loc, inst));\n}\n\n// Adds an instruction to the current pattern block, returning the produced\n// ID.\n// TODO: Is it possible to remove this and pattern_block_stack, now that\n// we have BeginSubpattern etc. instead?\nauto AddPatternInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId;\n\n// Convenience for AddPatternInst with typed nodes.\n//\n// As a safety check, prevent use with storage insts (see `AddInstWithCleanup`).\ntemplate <typename InstT, typename LocT>\n  requires(!InstT::Kind.has_cleanup() &&\n           std::convertible_to<LocT, SemIR::LocId>)\nauto AddPatternInst(Context& context, LocT loc, InstT inst) -> SemIR::InstId {\n  return AddPatternInst(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n// Adds an instruction to the current block, returning the produced ID. The\n// instruction is a placeholder that is expected to be replaced by\n// `ReplaceInstBeforeConstantUse`.\nauto AddPlaceholderInst(Context& context, SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId;\n\n// Convenience for AddPlaceholderInst with typed nodes.\n//\n// As a safety check, prevent use with storage insts (see `AddInstWithCleanup`).\ntemplate <typename InstT, typename LocT>\n  requires(!InstT::Kind.has_cleanup())\nauto AddPlaceholderInst(Context& context, LocT loc, InstT inst)\n    -> SemIR::InstId {\n  return AddPlaceholderInst(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n// Adds an instruction in no block, returning the produced ID. Should be used\n// rarely. The instruction is a placeholder that is expected to be replaced by\n// `ReplaceInstBeforeConstantUse`.\nauto AddPlaceholderInstInNoBlock(Context& context,\n                                 SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId;\n\n// Convenience for AddPlaceholderInstInNoBlock with typed nodes.\n//\n// As a safety check, prevent use with storage insts (see `AddInstWithCleanup`).\ntemplate <typename InstT, typename LocT>\n  requires(!InstT::Kind.has_cleanup() &&\n           std::convertible_to<LocT, SemIR::LocId>)\nauto AddPlaceholderInstInNoBlock(Context& context, LocT loc, InstT inst)\n    -> SemIR::InstId {\n  return AddPlaceholderInstInNoBlock(context, SemIR::LocIdAndInst(loc, inst));\n}\n\n// Similar to `AddPlaceholderInstInNoBlock`, but also tracks the instruction as\n// an import.\nauto AddPlaceholderImportedInstInNoBlock(Context& context,\n                                         SemIR::LocIdAndInst loc_id_and_inst)\n    -> SemIR::InstId;\n\n// Replaces the instruction at `inst_id` with `loc_id_and_inst`. The\n// instruction is required to not have been used in any constant evaluation,\n// either because it's newly created and entirely unused, or because it's only\n// used in a position that constant evaluation ignores, such as a return slot.\nauto ReplaceLocIdAndInstBeforeConstantUse(Context& context,\n                                          SemIR::InstId inst_id,\n                                          SemIR::LocIdAndInst loc_id_and_inst)\n    -> void;\n\n// Replaces the instruction at `inst_id` with `inst`, not affecting location.\n// The instruction is required to not have been used in any constant\n// evaluation, either because it's newly created and entirely unused, or\n// because it's only used in a position that constant evaluation ignores, such\n// as a return slot.\nauto ReplaceInstBeforeConstantUse(Context& context, SemIR::InstId inst_id,\n                                  SemIR::Inst inst) -> void;\n\n// Replaces the instruction at `inst_id` with `inst`, not affecting location.\n// The instruction is required to not change its constant value.\nauto ReplaceInstPreservingConstantValue(Context& context, SemIR::InstId inst_id,\n                                        SemIR::Inst inst) -> void;\n\n// Sets only the parse node of an instruction. This is only used when setting\n// the parse node of an imported namespace. Versus\n// ReplaceInstBeforeConstantUse, it is safe to use after the namespace is used\n// in constant evaluation. It's exposed this way mainly so that `insts()` can\n// remain const.\nauto SetNamespaceNodeId(Context& context, SemIR::InstId inst_id,\n                        Parse::NodeId node_id) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_INST_H_\n"
  },
  {
    "path": "toolchain/check/inst_block_stack.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/inst_block_stack.h\"\n\n#include \"common/vlog.h\"\n#include \"llvm/ADT/STLExtras.h\"\n#include \"llvm/ADT/StringExtras.h\"\n\nnamespace Carbon::Check {\n\nauto InstBlockStack::Push(SemIR::InstBlockId id) -> void {\n  CARBON_VLOG(\"{0} Push {1}\\n\", name_, id_stack_.size());\n  CARBON_CHECK(id_stack_.size() < (1 << 20),\n               \"Excessive stack size: likely infinite loop\");\n  id_stack_.push_back(id);\n  insts_stack_.PushArray();\n}\n\nauto InstBlockStack::Push(SemIR::InstBlockId id,\n                          llvm::ArrayRef<SemIR::InstId> inst_ids) -> void {\n  Push(id);\n  insts_stack_.AppendToTop(inst_ids);\n}\n\nauto InstBlockStack::PeekOrAdd(int depth) -> SemIR::InstBlockId {\n  CARBON_CHECK(static_cast<int>(id_stack_.size()) > depth, \"no such block\");\n  int index = id_stack_.size() - depth - 1;\n  auto& slot = id_stack_[index];\n  if (!slot.has_value()) {\n    slot = sem_ir_->inst_blocks().AddPlaceholder();\n  }\n  return slot;\n}\n\nauto InstBlockStack::Pop() -> SemIR::InstBlockId {\n  CARBON_CHECK(!empty(), \"no current block\");\n  auto id = id_stack_.pop_back_val();\n  auto insts = insts_stack_.PeekArray();\n\n  // Finalize the block.\n  if (!insts.empty() && id != SemIR::InstBlockId::Unreachable) {\n    if (id.has_value()) {\n      sem_ir_->inst_blocks().ReplacePlaceholder(id, insts);\n    } else {\n      id = sem_ir_->inst_blocks().Add(insts);\n    }\n  }\n\n  insts_stack_.PopArray();\n\n  CARBON_VLOG(\"{0} Pop {1}: {2}\\n\", name_, id_stack_.size(), id);\n  return id.has_value() ? id : SemIR::InstBlockId::Empty;\n}\n\nauto InstBlockStack::PopAndDiscard() -> void {\n  CARBON_CHECK(!empty(), \"no current block\");\n  id_stack_.pop_back();\n  insts_stack_.PopArray();\n  CARBON_VLOG(\"{0} PopAndDiscard {1}\\n\", name_, id_stack_.size());\n}\n\nauto InstBlockStack::PrintForStackDump(int indent,\n                                       llvm::raw_ostream& output) const\n    -> void {\n  output.indent(indent);\n  output << name_ << \":\\n\";\n  for (const auto& [i, id] : llvm::enumerate(id_stack_)) {\n    output.indent(indent + 2);\n    output << i << \".\\t\" << id << \"\\t{\";\n    llvm::ListSeparator sep;\n    for (auto id : insts_stack_.PeekArrayAt(i)) {\n      output << sep << id;\n    }\n    output << \"}\\n\";\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/inst_block_stack.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_INST_BLOCK_STACK_H_\n#define CARBON_TOOLCHAIN_CHECK_INST_BLOCK_STACK_H_\n\n#include \"common/array_stack.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/sem_ir/file.h\"\n\nnamespace Carbon::Check {\n\n// A stack of instruction blocks that are currently being constructed in a\n// Context. The contents of the instruction blocks are stored here until the\n// instruction block is popped from the stack, at which point they are\n// transferred into the SemIR::File for long-term storage.\n//\n// All pushes and pops will be vlogged.\nclass InstBlockStack {\n public:\n  explicit InstBlockStack(llvm::StringLiteral name, SemIR::File& sem_ir,\n                          llvm::raw_ostream* vlog_stream)\n      : name_(name), sem_ir_(&sem_ir), vlog_stream_(vlog_stream) {}\n\n  // Pushes an existing instruction block.\n  auto Push(SemIR::InstBlockId id) -> void;\n\n  // Pushes an existing instruction block with a set of instructions.\n  auto Push(SemIR::InstBlockId id, llvm::ArrayRef<SemIR::InstId> inst_ids)\n      -> void;\n\n  // Pushes a new instruction block. It will be `None` unless PeekOrAdd is\n  // called in order to support lazy allocation.\n  auto Push() -> void { Push(SemIR::InstBlockId::None); }\n\n  // Pushes a new unreachable code block.\n  auto PushUnreachable() -> void { Push(SemIR::InstBlockId::Unreachable); }\n\n  // Returns the ID of the top instruction block, allocating one if necessary.\n  // If `depth` is specified, returns the instruction block at `depth` levels\n  // from the top of the stack instead of the top block, where the top block is\n  // at depth 0.\n  auto PeekOrAdd(int depth = 0) -> SemIR::InstBlockId;\n\n  // Pops the top instruction block. This will never return `None`; `Empty` is\n  // returned if one wasn't allocated.\n  auto Pop() -> SemIR::InstBlockId;\n\n  // Pops the top instruction block, and discards it if it hasn't had an ID\n  // allocated.\n  auto PopAndDiscard() -> void;\n\n  // Adds the given instruction ID to the block at the top of the stack.\n  auto AddInstId(SemIR::InstId inst_id) -> void {\n    CARBON_CHECK(!empty(), \"{0} has no current block\", name_);\n    insts_stack_.AppendToTop(inst_id);\n  }\n\n  // Returns whether the current block is statically reachable.\n  auto is_current_block_reachable() -> bool {\n    return id_stack_.back() != SemIR::InstBlockId::Unreachable;\n  }\n\n  // Returns a view of the contents of the top instruction block on the stack.\n  auto PeekCurrentBlockContents() const -> llvm::ArrayRef<SemIR::InstId> {\n    CARBON_CHECK(!empty(), \"no current block\");\n    return insts_stack_.PeekArray();\n  }\n\n  // Prints the stack for a stack dump.\n  auto PrintForStackDump(int indent, llvm::raw_ostream& output) const -> void;\n\n  // Runs verification that the processing cleanly finished.\n  auto VerifyOnFinish() const -> void {\n    CARBON_CHECK(empty(), \"{0} still has {1} entries\", name_, id_stack_.size());\n  }\n\n  auto empty() const -> bool { return id_stack_.empty(); }\n\n private:\n  // A name for debugging.\n  llvm::StringLiteral name_;\n\n  // The underlying SemIR::File instance. Always non-null.\n  SemIR::File* sem_ir_;\n\n  // Whether to print verbose output.\n  llvm::raw_ostream* vlog_stream_;\n\n  // The stack of block IDs. A value if allocated, `None` if no block has been\n  // allocated, or `Unreachable` if this block is known to be unreachable.\n  llvm::SmallVector<SemIR::InstBlockId> id_stack_;\n\n  // The stack of insts in each block.\n  ArrayStack<SemIR::InstId> insts_stack_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_INST_BLOCK_STACK_H_\n"
  },
  {
    "path": "toolchain/check/interface.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/interface.h\"\n\n#include <algorithm>\n#include <cstddef>\n\n#include \"common/concepts.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/merge.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/sem_ir/entity_with_params_base.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id,\n                           SemIR::InstId decl_id) -> SemIR::InstId {\n  auto& interface_info = context.interfaces().Get(interface_id);\n  if (!interface_info.is_being_defined()) {\n    // This should only happen if the interface is erroneously defined more than\n    // once.\n    // TODO: Find a way to CHECK this.\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // This associated entity is being declared as a member of an interface. We\n  // use the self-specific of the interface-without-self as the AssociatedEntity\n  // names the externally facing SpecificInterface (without self).\n  auto interface_without_self_specific_id =\n      context.generics().GetSelfSpecific(interface_info.generic_id);\n\n  // Register this declaration as declaring an associated entity.\n  auto index = SemIR::ElementIndex(\n      context.args_type_info_stack().PeekCurrentBlockContents().size());\n  context.args_type_info_stack().AddInstId(decl_id);\n\n  // Name lookup for the declaration's name should name the associated entity,\n  // not the declaration itself.\n  auto type_id = GetAssociatedEntityType(context, interface_id,\n                                         interface_without_self_specific_id);\n  return AddInst<SemIR::AssociatedEntity>(\n      context, SemIR::LocId(decl_id),\n      {.type_id = type_id, .index = index, .decl_id = decl_id});\n}\n\nauto GetSelfSpecificForInterfaceMemberWithSelfType(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::SpecificId interface_with_self_specific_id,\n    SemIR::GenericId generic_id, SemIR::SpecificId enclosing_specific_id)\n    -> SemIR::SpecificId {\n  const auto& generic = context.generics().Get(generic_id);\n  auto self_specific_args = context.inst_blocks().Get(\n      context.specifics().Get(generic.self_specific_id).args_id);\n\n  auto arg_ids = llvm::SmallVector<SemIR::InstId>(context.inst_blocks().Get(\n      context.specifics().GetArgsOrEmpty(interface_with_self_specific_id)));\n\n  // Determine the number of specific arguments that enclose the point where\n  // this self specific will be used from. In an impl, this will be the number\n  // of parameters that the impl has.\n  int num_enclosing_specific_args =\n      context.inst_blocks()\n          .Get(context.specifics().GetArgsOrEmpty(enclosing_specific_id))\n          .size();\n  // The index of each remaining generic parameter is adjusted to match the\n  // numbering at the point where the self specific is used.\n  int index_delta = num_enclosing_specific_args - arg_ids.size();\n\n  // Take any trailing argument values from the self specific.\n  // TODO: If these refer to outer arguments, for example in their types, we may\n  // need to perform extra substitutions here.\n  for (auto arg_id : self_specific_args.drop_front(arg_ids.size())) {\n    auto new_arg_id = context.constant_values().GetConstantInstId(arg_id);\n    if (index_delta) {\n      // If this parameter would have a new index in the context described by\n      // `enclosing_specific_id`, form a new binding with an adjusted index.\n      auto bind_name = context.insts().GetAs<SemIR::SymbolicBinding>(\n          context.constant_values().GetConstantInstId(arg_id));\n      auto entity_name = context.entity_names().Get(bind_name.entity_name_id);\n      entity_name.bind_index_value += index_delta;\n      CARBON_CHECK(entity_name.bind_index_value >= 0);\n      bind_name.entity_name_id =\n          context.entity_names().AddCanonical(entity_name);\n      new_arg_id =\n          context.constant_values().GetInstId(TryEvalInst(context, bind_name));\n    }\n    arg_ids.push_back(new_arg_id);\n  }\n\n  return MakeSpecific(context, loc_id, generic_id, arg_ids);\n}\n\nauto GetTypeForSpecificAssociatedEntity(\n    Context& context, SemIR::SpecificId interface_with_self_specific_id,\n    SemIR::InstId decl_id) -> SemIR::TypeId {\n  auto decl_constant_inst_id =\n      context.constant_values().GetConstantInstId(decl_id);\n  if (decl_constant_inst_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ErrorInst::TypeId;\n  }\n\n  auto decl = context.insts().Get(decl_constant_inst_id);\n  if (auto assoc_const = decl.TryAs<SemIR::AssociatedConstantDecl>()) {\n    return SemIR::GetTypeOfInstInSpecific(\n        context.sem_ir(), interface_with_self_specific_id, decl_id);\n  }\n\n  if (auto fn = context.types().TryGetAs<SemIR::FunctionType>(decl.type_id())) {\n    // Form the type of the function within the interface, and attach the `Self`\n    // type.\n    auto interface_fn_type_id = SemIR::GetTypeOfInstInSpecific(\n        context.sem_ir(), interface_with_self_specific_id, decl_id);\n    auto self_facet_id = context.inst_blocks()\n                             .Get(context.specifics().GetArgsOrEmpty(\n                                 interface_with_self_specific_id))\n                             .back();\n    return GetFunctionTypeWithSelfType(\n        context, context.types().GetTypeInstId(interface_fn_type_id),\n        self_facet_id);\n  }\n\n  CARBON_FATAL(\"Unexpected kind for associated constant {0}\", decl);\n}\n\nauto AddSelfSymbolicBindingToScope(Context& context,\n                                   SemIR::LocId definition_loc_id,\n                                   SemIR::TypeId type_id,\n                                   SemIR::NameScopeId scope_id,\n                                   bool is_template) -> SemIR::InstId {\n  auto entity_name_id = context.entity_names().AddSymbolicBindingName(\n      SemIR::NameId::SelfType, scope_id,\n      context.scope_stack().AddCompileTimeBinding(), is_template,\n      /*is_unused=*/false);\n  // Because there is no equivalent non-symbolic value, we use `None` as\n  // the `value_id` on the `SymbolicBinding`.\n  auto self_param_inst_id =\n      AddInst<SemIR::SymbolicBinding>(context, definition_loc_id,\n                                      {.type_id = type_id,\n                                       .entity_name_id = entity_name_id,\n                                       .value_id = SemIR::InstId::None});\n  context.name_scopes().AddRequiredName(scope_id, SemIR::NameId::SelfType,\n                                        self_param_inst_id);\n  return self_param_inst_id;\n}\n\ntemplate <typename EntityT>\n  requires std::same_as<EntityT, SemIR::Interface>\nstatic auto TryGetEntity(Context& context, SemIR::Inst inst)\n    -> const SemIR::EntityWithParamsBase* {\n  if (auto decl = inst.TryAs<SemIR::InterfaceDecl>()) {\n    return &context.interfaces().Get(decl->interface_id);\n  } else {\n    return nullptr;\n  }\n}\n\ntemplate <typename EntityT>\n  requires std::same_as<EntityT, SemIR::NamedConstraint>\nstatic auto TryGetEntity(Context& context, SemIR::Inst inst)\n    -> const SemIR::EntityWithParamsBase* {\n  if (auto decl = inst.TryAs<SemIR::NamedConstraintDecl>()) {\n    return &context.named_constraints().Get(decl->named_constraint_id);\n  } else {\n    return nullptr;\n  }\n}\n\ntemplate <typename EntityT>\n  requires std::same_as<EntityT, SemIR::Interface>\nstatic constexpr auto DeclTokenKind() -> Lex::TokenKind {\n  return Lex::TokenKind::Interface;\n}\n\ntemplate <typename EntityT>\n  requires std::same_as<EntityT, SemIR::NamedConstraint>\nstatic constexpr auto DeclTokenKind() -> Lex::TokenKind {\n  return Lex::TokenKind::Constraint;\n}\n\ntemplate <typename EntityT>\n  requires SameAsOneOf<EntityT, SemIR::Interface, SemIR::NamedConstraint>\nauto TryGetExistingDecl(Context& context, const NameComponent& name,\n                        SemIR::ScopeLookupResult lookup_result,\n                        const EntityT& entity, bool is_definition)\n    -> std::optional<SemIR::Inst> {\n  if (lookup_result.is_poisoned()) {\n    // This is a declaration of a poisoned name.\n    DiagnosePoisonedName(context, name.name_id,\n                         lookup_result.poisoning_loc_id(), name.name_loc_id);\n    return std::nullopt;\n  }\n\n  if (!lookup_result.is_found()) {\n    return std::nullopt;\n  }\n\n  SemIR::InstId existing_id = lookup_result.target_inst_id();\n  SemIR::Inst existing_decl_inst = context.insts().Get(existing_id);\n  const auto* existing_decl_entity =\n      TryGetEntity<EntityT>(context, existing_decl_inst);\n  if (!existing_decl_entity) {\n    // This is a redeclaration with a different entity kind.\n    DiagnoseDuplicateName(context, name.name_id, name.name_loc_id,\n                          SemIR::LocId(existing_id));\n    return std::nullopt;\n  }\n\n  if (!CheckRedeclParamsMatch(\n          context,\n          DeclParams(SemIR::LocId(entity.latest_decl_id()),\n                     name.first_param_node_id, name.last_param_node_id,\n                     name.implicit_param_patterns_id, name.param_patterns_id),\n          DeclParams(*existing_decl_entity))) {\n    // Mismatch is diagnosed already if found.\n    return std::nullopt;\n  }\n\n  // TODO: This should be refactored a little, particularly for\n  // prev_import_ir_id. See similar logic for classes and functions, which\n  // might also be refactored to merge.\n  DiagnoseIfInvalidRedecl(\n      context, DeclTokenKind<EntityT>(), existing_decl_entity->name_id,\n      RedeclInfo(entity, SemIR::LocId(entity.latest_decl_id()), is_definition),\n      RedeclInfo(*existing_decl_entity,\n                 SemIR::LocId(existing_decl_entity->latest_decl_id()),\n                 existing_decl_entity->has_definition_started()),\n      /*prev_import_ir_id=*/SemIR::ImportIRId::None);\n\n  if (is_definition && existing_decl_entity->has_definition_started()) {\n    // DiagnoseIfInvalidRedecl would diagnose an error in this case, since we'd\n    // have two definitions. Given the declaration parts of the definitions\n    // match, we would be able to use the prior declaration for error recovery,\n    // except that having two definitions causes larger problems for generics.\n    // All interfaces (and named constraints) are generic with an implicit Self\n    // compile time binding.\n    return std::nullopt;\n  }\n\n  // This is a matching redeclaration of an existing entity of the same type.\n  return existing_decl_inst;\n}\n\ntemplate auto TryGetExistingDecl(Context& context, const NameComponent& name,\n                                 SemIR::ScopeLookupResult lookup_result,\n                                 const SemIR::Interface& entity,\n                                 bool is_definition)\n    -> std::optional<SemIR::Inst>;\ntemplate auto TryGetExistingDecl(Context& context, const NameComponent& name,\n                                 SemIR::ScopeLookupResult lookup_result,\n                                 const SemIR::NamedConstraint& entity,\n                                 bool is_definition)\n    -> std::optional<SemIR::Inst>;\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/interface.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_INTERFACE_H_\n#define CARBON_TOOLCHAIN_CHECK_INTERFACE_H_\n\n#include <optional>\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/decl_name_stack.h\"\n#include \"toolchain/check/name_component.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/entity_with_params_base.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Builds and returns an associated entity for `interface_id` corresponding to\n// the declaration `decl_id`, which can be an associated function or an\n// associated constant. Registers the associated entity in the list for the\n// interface.\nauto BuildAssociatedEntity(Context& context, SemIR::InterfaceId interface_id,\n                           SemIR::InstId decl_id) -> SemIR::InstId;\n\n// Gets the self specific of a generic declaration that is an interface member,\n// given a specific for the interface plus a type to use as `Self`.\nauto GetSelfSpecificForInterfaceMemberWithSelfType(\n    Context& context, SemIR::LocId loc_id,\n    SemIR::SpecificId interface_with_self_specific_id,\n    SemIR::GenericId generic_id, SemIR::SpecificId enclosing_specific_id)\n    -> SemIR::SpecificId;\n\n// Gets the type of the specified associated entity, given the specific for the\n// interface and the type of `Self`.\nauto GetTypeForSpecificAssociatedEntity(\n    Context& context, SemIR::SpecificId interface_with_self_specific_id,\n    SemIR::InstId decl_id) -> SemIR::TypeId;\n\n// Creates a symbolic binding for `Self` of type `type_id` in the scope of\n// `scope_id`.\n//\n// Returns the symbolic binding instruction.\nauto AddSelfSymbolicBindingToScope(Context& context,\n                                   SemIR::LocId definition_loc_id,\n                                   SemIR::TypeId type_id,\n                                   SemIR::NameScopeId scope_id,\n                                   bool is_template) -> SemIR::InstId;\n\n// Given a search result `lookup_result` for `name`, returns the previous valid\n// declaration of `name` if there is one. The `entity` is a new decl of the same\n// `name`, and the existing decl need to be of the same entity type. Otherwise,\n// produces diagnostics if needed and returns nullopt.\ntemplate <typename EntityT>\n  requires SameAsOneOf<EntityT, SemIR::Interface, SemIR::NamedConstraint>\nauto TryGetExistingDecl(Context& context, const NameComponent& name,\n                        SemIR::ScopeLookupResult lookup_result,\n                        const EntityT& entity, bool is_definition)\n    -> std::optional<SemIR::Inst>;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_INTERFACE_H_\n"
  },
  {
    "path": "toolchain/check/keyword_modifier_set.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/keyword_modifier_set.h\"\n\nnamespace Carbon::Check {\n\nCARBON_DEFINE_ENUM_MASK_NAMES(KeywordModifierSet) {\n  CARBON_KEYWORD_MODIFIER_SET(CARBON_ENUM_MASK_NAME_STRING)\n};\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/keyword_modifier_set.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_\n#define CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_\n\n#include <optional>\n\n#include \"common/enum_mask_base.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n\nnamespace Carbon::Check {\n\n// The order of modifiers. Each of these corresponds to a group on\n// KeywordModifierSet, and can be used as an array index.\nenum class ModifierOrder : int8_t {\n  Access,\n  Extern,\n  Extend,\n  Decl,\n  Evaluation,\n  Last = Evaluation\n};\n\n// A single X-macro to cover modifier groups. These are split out to make groups\n// clearer.\n#define CARBON_KEYWORD_MODIFIER_SET(X)                                       \\\n  /* At most one of these access modifiers allowed for a given declaration,  \\\n   * and if present it must be first. */                                     \\\n  X(Private)                                                                 \\\n  X(Protected)                                                               \\\n                                                                             \\\n  /* Extern is standalone. */                                                \\\n  X(Extern)                                                                  \\\n                                                                             \\\n  /* Extend can be combined with Final, but no others in the group below. */ \\\n  X(Extend)                                                                  \\\n                                                                             \\\n  /* At most one of these declaration modifiers allowed for a given          \\\n   * declaration. */                                                         \\\n  X(Abstract)                                                                \\\n  X(Base)                                                                    \\\n  X(Default)                                                                 \\\n  X(Export)                                                                  \\\n  X(Final)                                                                   \\\n  X(Impl)                                                                    \\\n  X(Override)                                                                \\\n  X(Returned)                                                                \\\n  X(Virtual)                                                                 \\\n                                                                             \\\n  /* Eval and MustEval are mutually exclusive. */                            \\\n  X(Eval)                                                                    \\\n  X(MustEval)\n\n// We expect this to grow, so are using a bigger size than needed.\nCARBON_DEFINE_RAW_ENUM_MASK(KeywordModifierSet, uint32_t) {\n  CARBON_KEYWORD_MODIFIER_SET(CARBON_RAW_ENUM_MASK_ENUMERATOR)\n};\n\n// Represents a set of keyword modifiers, using a separate bit per modifier.\nclass KeywordModifierSet : public CARBON_ENUM_MASK_BASE(KeywordModifierSet) {\n public:\n  CARBON_KEYWORD_MODIFIER_SET(CARBON_ENUM_MASK_CONSTANT_DECL)\n\n  // Sets of modifiers.\n  static const KeywordModifierSet Access;\n  static const KeywordModifierSet Class;\n  static const KeywordModifierSet Method;\n  static const KeywordModifierSet ImplDecl;\n  static const KeywordModifierSet Interface;\n  static const KeywordModifierSet Evaluation;\n  static const KeywordModifierSet Decl;\n\n  // Return a builder that returns the new enumeration type once a series of\n  // mapping `Case`s and a final `Default` are provided. For example:\n  //   ```\n  //   auto e = set.ToEnum<SomeEnum>()\n  //                .Case(KeywordModifierSet::A, SomeEnum::A)\n  //                .Case(KeywordModifierSet::B, SomeEnum::B)\n  //                .Default(SomeEnum::DefaultValue);\n  //   ```\n  template <typename T>\n  auto ToEnum() const -> auto {\n    class Converter {\n     public:\n      explicit Converter(const KeywordModifierSet& set) : set_(set) {}\n\n      auto Case(KeywordModifierSet other, T result) -> Converter& {\n        if (set_.HasAnyOf(other)) {\n          result_ = result;\n        }\n        return *this;\n      }\n\n      auto Default(T default_value) -> T {\n        if (result_) {\n          return *result_;\n        }\n        return default_value;\n      }\n\n     private:\n      const KeywordModifierSet& set_;\n      std::optional<T> result_;\n    };\n    return Converter(*this);\n  }\n\n  // Returns the access kind from modifiers.\n  auto GetAccessKind() const -> SemIR::AccessKind {\n    if (HasAnyOf(KeywordModifierSet::Protected)) {\n      return SemIR::AccessKind::Protected;\n    }\n    if (HasAnyOf(KeywordModifierSet::Private)) {\n      return SemIR::AccessKind::Private;\n    }\n    return SemIR::AccessKind::Public;\n  }\n};\n\n#define CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE(X) \\\n  CARBON_ENUM_MASK_CONSTANT_DEFINITION(KeywordModifierSet, X)\nCARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE)\n#undef CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE\n\ninline constexpr KeywordModifierSet KeywordModifierSet::Access(Private |\n                                                               Protected);\ninline constexpr KeywordModifierSet KeywordModifierSet::Class(Abstract | Base);\ninline constexpr KeywordModifierSet KeywordModifierSet::Method(Abstract |\n                                                               Override |\n                                                               Virtual);\ninline constexpr KeywordModifierSet KeywordModifierSet::ImplDecl(Extend |\n                                                                 Final);\ninline constexpr KeywordModifierSet KeywordModifierSet::Interface(Default |\n                                                                  Final);\ninline constexpr KeywordModifierSet KeywordModifierSet::Decl(Class | Method |\n                                                             Impl | Interface |\n                                                             Export | Returned);\ninline constexpr KeywordModifierSet KeywordModifierSet::Evaluation(Eval |\n                                                                   MustEval);\n\n// TODO: This and the ordering checking logic in handle_modifiers.cpp are\n// becoming unwieldy. Find a better representation.\nstatic_assert(\n    !KeywordModifierSet::Access.HasAnyOf(KeywordModifierSet::Extern) &&\n        !(KeywordModifierSet::Access | KeywordModifierSet::Extern |\n          KeywordModifierSet::Extend)\n             .HasAnyOf(KeywordModifierSet::Decl) &&\n        !(KeywordModifierSet::Access | KeywordModifierSet::Extern |\n          KeywordModifierSet::Decl)\n             .HasAnyOf(KeywordModifierSet::Evaluation),\n    \"Order-related sets must not overlap\");\n\n#define CARBON_KEYWORD_MODIFIER_SET_IN_GROUP(Modifier)                     \\\n  static_assert((KeywordModifierSet::Access | KeywordModifierSet::Extern | \\\n                 KeywordModifierSet::Extend | KeywordModifierSet::Decl |   \\\n                 KeywordModifierSet::Evaluation)                           \\\n                    .HasAnyOf(KeywordModifierSet::Modifier),               \\\n                \"Modifier missing from all modifier sets: \" #Modifier);\nCARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_IN_GROUP)\n#undef CARBON_KEYWORD_MODIFIER_SET_IN_GROUP\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_KEYWORD_MODIFIER_SET_H_\n"
  },
  {
    "path": "toolchain/check/lexical_lookup.h",
    "content": "\n// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_LEXICAL_LOOKUP_H_\n#define CARBON_TOOLCHAIN_CHECK_LEXICAL_LOOKUP_H_\n\n#include \"toolchain/base/canonical_value_store.h\"\n#include \"toolchain/base/shared_value_stores.h\"\n#include \"toolchain/base/value_ids.h\"\n#include \"toolchain/check/scope_index.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Manages lexical lookup information for NameIds.\n//\n// Values are a stack of name lookup results in the ancestor scopes. This offers\n// constant-time lookup of names, regardless of how many scopes exist between\n// the name declaration and reference. The corresponding scope for each lookup\n// result is tracked, so that lexical lookup results can be interleaved with\n// lookup results from non-lexical scopes such as classes.\nclass LexicalLookup {\n public:\n  // A lookup result.\n  struct Result {\n    // The instruction that was added to lookup.\n    SemIR::InstId inst_id;\n    // The scope in which the instruction was added.\n    ScopeIndex scope_index;\n    // Whether the name was declared in a reachable position.\n    bool is_decl_reachable = true;\n    // The location of the first use of the name, if any.\n    SemIR::LocId use_loc_id = SemIR::LocId::None;\n  };\n\n  // A lookup result that has been temporarily removed from scope.\n  struct SuspendedResult {\n    // The lookup index. This is notionally a size_t, but is stored in 32 bits\n    // to keep this type small, which helps to keep SuspendedFunctions small.\n    uint32_t index;\n    // The lookup result.\n    SemIR::InstId inst_id;\n    // Whether the name was declared in a reachable position.\n    bool is_decl_reachable;\n    // The location of the first use of the name, if any.\n    SemIR::LocId use_loc_id;\n  };\n\n  explicit LexicalLookup(const SharedValueStores::IdentifierStore& identifiers)\n      : lookup_(identifiers.size() + SemIR::NameId::NonIndexValueCount) {}\n\n  // Returns the lexical lookup results for a name.\n  auto Get(SemIR::NameId name_id) -> llvm::SmallVector<Result, 2>& {\n    auto index = GetLookupIndex(name_id);\n    CARBON_CHECK(\n        index < lookup_.size(),\n        \"An identifier was added after the Context was initialized. Currently, \"\n        \"we expect that new identifiers will never be used with lexical lookup \"\n        \"(they're added for things like detecting name collisions in imports). \"\n        \"That might change with metaprogramming: if it does, we may need to \"\n        \"start resizing `lookup_`, either on each identifier addition or in \"\n        \"Get` where this CHECK currently fires.\");\n    return lookup_[index];\n  }\n\n  // Temporarily remove the top lookup result for `name_id` from scope.\n  auto Suspend(SemIR::NameId name_id) -> SuspendedResult {\n    auto index = GetLookupIndex(name_id);\n    auto& results = lookup_[index];\n    CARBON_CHECK(!results.empty(), \"Suspending a nonexistent result for {0}.\",\n                 name_id);\n    CARBON_CHECK(index <= std::numeric_limits<uint32_t>::max(),\n                 \"Unexpectedly large index {0} for name ID\", index);\n    auto result = results.pop_back_val();\n    return {.index = static_cast<uint32_t>(index),\n            .inst_id = result.inst_id,\n            .is_decl_reachable = result.is_decl_reachable,\n            .use_loc_id = result.use_loc_id};\n  }\n\n  // Restore a previously-suspended lookup result.\n  auto Restore(SuspendedResult sus, ScopeIndex index) -> void {\n    lookup_[sus.index].push_back({.inst_id = sus.inst_id,\n                                  .scope_index = index,\n                                  .is_decl_reachable = sus.is_decl_reachable,\n                                  .use_loc_id = sus.use_loc_id});\n  }\n\n private:\n  // Get the index at which the specified name is stored in `lookup_`.\n  auto GetLookupIndex(SemIR::NameId name_id) -> size_t {\n    return static_cast<ssize_t>(name_id.index) +\n           SemIR::NameId::NonIndexValueCount;\n  }\n\n  // Maps identifiers to name lookup results.\n  //\n  // The outer size of `0` is used because it's resized once on construction,\n  // and will rarely fit on the stack. The inner size of `2` is used because\n  // most entries will only have zero or one results.\n  //\n  // TODO: Consider TinyPtrVector<Result> or similar. For now, use a small size\n  // of 2 to cover the common case.\n  llvm::SmallVector<llvm::SmallVector<Result, 2>, 0> lookup_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_LEXICAL_LOOKUP_H_\n"
  },
  {
    "path": "toolchain/check/literal.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/literal.h\"\n\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/diagnostic.h\"\n#include \"toolchain/lex/token_info.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Adds a TypeLiteral instruction to represent a syntactic type literal.\nstatic auto MakeTypeLiteral(Context& context, SemIR::LocId loc_id,\n                            SemIR::InstId value_id) -> SemIR::TypeInstId {\n  auto type_inst_id = ExprAsType(context, loc_id, value_id).inst_id;\n  return AddTypeInst<SemIR::TypeLiteral>(\n      context, loc_id,\n      {.type_id = SemIR::TypeType::TypeId, .value_id = type_inst_id});\n}\n\nauto MakeTypeTypeLiteral(Context& context, Parse::NodeId node_id)\n    -> SemIR::TypeInstId {\n  return MakeTypeLiteral(context, node_id, SemIR::TypeType::TypeInstId);\n}\n\nauto MakeBoolTypeLiteral(Context& context, Parse::NodeId node_id)\n    -> SemIR::TypeInstId {\n  auto desugared_loc_id = SemIR::LocId(node_id).AsDesugared();\n  auto inst_id =\n      LookupNameInCore(context, desugared_loc_id, CoreIdentifier::Bool);\n  inst_id = PerformCall(context, desugared_loc_id, inst_id, {});\n  return MakeTypeLiteral(context, node_id, inst_id);\n}\n\nauto MakeBoolLiteral(Context& context, SemIR::LocId loc_id,\n                     SemIR::BoolValue value) -> SemIR::InstId {\n  return AddInst<SemIR::BoolLiteral>(\n      context, loc_id,\n      {.type_id = GetSingletonType(context, SemIR::BoolType::TypeInstId),\n       .value = value});\n}\n\nauto MakeIntLiteral(Context& context, Parse::NodeId node_id, IntId int_id)\n    -> SemIR::InstId {\n  return AddInst<SemIR::IntValue>(\n      context, node_id,\n      {.type_id = GetSingletonType(context, SemIR::IntLiteralType::TypeInstId),\n       .int_id = int_id});\n}\n\n// Returns an instruction with the given constant integer value.\nstatic auto GetOrAddIntValue(Context& context, SemIR::LocId loc_id,\n                             IntId int_id) -> SemIR::InstId {\n  return GetOrAddInst<SemIR::IntValue>(\n      context, loc_id,\n      {.type_id = GetSingletonType(context, SemIR::IntLiteralType::TypeInstId),\n       .int_id = int_id});\n}\n\nauto MakeCharTypeLiteral(Context& context, Parse::NodeId node_id)\n    -> SemIR::TypeInstId {\n  auto inst_id = LookupNameInCore(context, node_id, CoreIdentifier::Char);\n  return MakeTypeLiteral(context, node_id, inst_id);\n}\n\n// Returns an instruction representing the type `iN` or `uN`.\nstatic auto GetOrAddIntTypeInst(Context& context, SemIR::LocId loc_id,\n                                SemIR::IntKind int_kind, IntId size_id)\n    -> SemIR::InstId {\n  auto width_id = GetOrAddIntValue(context, loc_id, size_id);\n  auto fn_inst_id = LookupNameInCore(context, loc_id,\n                                     int_kind == SemIR::IntKind::Signed\n                                         ? CoreIdentifier::Int\n                                         : CoreIdentifier::UInt);\n  return PerformCall(context, loc_id, fn_inst_id, {width_id});\n}\n\nauto MakeIntTypeLiteral(Context& context, Parse::NodeId node_id,\n                        SemIR::IntKind int_kind, IntId size_id)\n    -> SemIR::TypeInstId {\n  auto desugared_loc_id = SemIR::LocId(node_id).AsDesugared();\n  auto type_inst_id =\n      GetOrAddIntTypeInst(context, desugared_loc_id, int_kind, size_id);\n  return MakeTypeLiteral(context, node_id, type_inst_id);\n}\n\nauto MakeIntType(Context& context, Parse::NodeId node_id,\n                 SemIR::IntKind int_kind, IntId size_id) -> SemIR::TypeId {\n  auto desugared_loc_id = SemIR::LocId(node_id).AsDesugared();\n  auto type_inst_id =\n      GetOrAddIntTypeInst(context, desugared_loc_id, int_kind, size_id);\n  return ExprAsType(context, node_id, type_inst_id).type_id;\n}\n\nauto MakeFloatTypeLiteral(Context& context, Parse::NodeId node_id,\n                          IntId size_id) -> SemIR::TypeInstId {\n  auto desugared_loc_id = SemIR::LocId(node_id).AsDesugared();\n  auto width_id = GetOrAddIntValue(context, desugared_loc_id, size_id);\n  auto fn_inst_id =\n      LookupNameInCore(context, desugared_loc_id, CoreIdentifier::Float);\n  auto call_id = PerformCall(context, desugared_loc_id, fn_inst_id, {width_id});\n  return MakeTypeLiteral(context, node_id, call_id);\n}\n\nnamespace {\n// The extracted representation of the type `Core.String`.\nstruct StringRepr {\n  SemIR::TypeId ptr_field_type_id;\n  SemIR::TypeId size_field_type_id;\n  SemIR::TypeStore::IntTypeInfo size_field_type_info;\n};\n}  // namespace\n\n// Extracts information about the representation of the `Core.String` type\n// necessary for building a string literal.\nstatic auto GetStringLiteralRepr(Context& context, SemIR::LocId loc_id,\n                                 SemIR::TypeId type_id)\n    -> std::optional<StringRepr> {\n  // The object representation should be a struct type.\n  auto object_repr_id = context.types().GetObjectRepr(type_id);\n  auto struct_repr =\n      context.types().TryGetAs<SemIR::StructType>(object_repr_id);\n  if (!struct_repr) {\n    return std::nullopt;\n  }\n\n  // The struct should have two fields.\n  auto fields = context.struct_type_fields().Get(struct_repr->fields_id);\n  if (fields.size() != 2) {\n    return std::nullopt;\n  }\n\n  // The first field should be a pointer to 8-bit integers.\n  auto ptr_type =\n      context.insts().TryGetAs<SemIR::PointerType>(fields[0].type_inst_id);\n  if (!ptr_type) {\n    return std::nullopt;\n  }\n  auto pointee_type_id =\n      context.types().GetTypeIdForTypeInstId(ptr_type->pointee_id);\n  if (!TryToCompleteType(context, pointee_type_id, loc_id)) {\n    return std::nullopt;\n  }\n  auto elem_type_info = context.types().TryGetIntTypeInfo(pointee_type_id);\n  if (!elem_type_info || context.ints().Get(elem_type_info->bit_width) != 8) {\n    return std::nullopt;\n  }\n\n  // The second field should be an integer type.\n  auto size_field_type_id =\n      context.types().GetTypeIdForTypeInstId(fields[1].type_inst_id);\n  auto size_type_info = context.types().TryGetIntTypeInfo(size_field_type_id);\n  if (!size_type_info) {\n    return std::nullopt;\n  }\n\n  return StringRepr{.ptr_field_type_id = context.types().GetTypeIdForTypeInstId(\n                        fields[0].type_inst_id),\n                    .size_field_type_id = size_field_type_id,\n                    .size_field_type_info = *size_type_info};\n}\n\nauto MakeStringLiteral(Context& context, Parse::StringLiteralId node_id,\n                       StringLiteralValueId value_id) -> SemIR::InstId {\n  auto str_type = MakeStringType(context, SemIR::LocId(node_id).AsDesugared());\n  if (!RequireCompleteType(\n          context, str_type.type_id, node_id, [&](auto& builder) {\n            CARBON_DIAGNOSTIC(StringLiteralTypeIncomplete, Context,\n                              \"type {0} is incomplete\", InstIdAsType);\n            builder.Context(node_id, StringLiteralTypeIncomplete,\n                            str_type.inst_id);\n          })) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto repr = GetStringLiteralRepr(context, node_id, str_type.type_id);\n  if (!repr) {\n    if (str_type.type_id != SemIR::ErrorInst::TypeId) {\n      CARBON_DIAGNOSTIC(StringLiteralTypeUnexpected, Error,\n                        \"unexpected representation for type {0}\", InstIdAsType);\n      context.emitter().Emit(node_id, StringLiteralTypeUnexpected,\n                             str_type.inst_id);\n    }\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // The pointer field is a `StringLiteral` object.\n  // TODO: Perhaps `StringLiteral` should instead produce a durable reference,\n  // and we should take its address here?\n  auto ptr_value_id = AddInst<SemIR::StringLiteral>(\n      context, node_id,\n      {.type_id = repr->ptr_field_type_id, .string_literal_id = value_id});\n\n  // The size field is an integer literal.\n  auto size = context.string_literal_values().Get(value_id).size();\n  if (repr->size_field_type_info.bit_width.has_value()) {\n    // Check that the size value fits in the size field.\n    auto width = context.ints()\n                     .Get(repr->size_field_type_info.bit_width)\n                     .getLimitedValue();\n    if (repr->size_field_type_info.is_signed ? !llvm::isIntN(width, size)\n                                             : !llvm::isUIntN(width, size)) {\n      CARBON_DIAGNOSTIC(StringLiteralTooLong, Error,\n                        \"string literal is too long\");\n      context.emitter().Emit(node_id, StringLiteralTooLong);\n      return SemIR::ErrorInst::InstId;\n    }\n  }\n  auto size_value_id =\n      AddInst<SemIR::IntValue>(context, node_id,\n                               {.type_id = repr->size_field_type_id,\n                                .int_id = context.ints().Add(size)});\n\n  // Build the representation struct.\n  auto elements_id = context.inst_blocks().Add({ptr_value_id, size_value_id});\n  return AddInst<SemIR::StructValue>(\n      context, node_id,\n      {.type_id = str_type.type_id, .elements_id = elements_id});\n}\n\n// Returns an instruction with the value `str`.\nstatic auto GetOrAddStringTypeInst(Context& context, SemIR::LocId loc_id)\n    -> SemIR::InstId {\n  return LookupNameInCore(context, loc_id, CoreIdentifier::String);\n}\n\nauto MakeStringTypeLiteral(Context& context, Parse::StringTypeLiteralId node_id)\n    -> SemIR::TypeInstId {\n  auto inst_id = GetOrAddStringTypeInst(context, node_id);\n  return MakeTypeLiteral(context, node_id, inst_id);\n}\n\nauto MakeStringType(Context& context, SemIR::LocId loc_id) -> TypeExpr {\n  auto type_inst_id = GetOrAddStringTypeInst(context, loc_id);\n  return ExprAsType(context, loc_id, type_inst_id);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/literal.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_LITERAL_H_\n#define CARBON_TOOLCHAIN_CHECK_LITERAL_H_\n\n#include \"toolchain/base/value_ids.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/lex/token_info.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Forms a TypeType for a `type` literal.\nauto MakeTypeTypeLiteral(Context& context, Parse::NodeId node_id)\n    -> SemIR::TypeInstId;\n\n// Forms a boolean type for a `bool` literal.\nauto MakeBoolTypeLiteral(Context& context, Parse::NodeId node_id)\n    -> SemIR::TypeInstId;\n\n// Forms a BoolLiteral instruction with the given value and returns it.\nauto MakeBoolLiteral(Context& context, SemIR::LocId loc_id,\n                     SemIR::BoolValue value) -> SemIR::InstId;\n\n// Forms an IntValue instruction with type `IntLiteral` for a given literal\n// integer value, which is assumed to be unsigned.\nauto MakeIntLiteral(Context& context, Parse::NodeId node_id, IntId int_id)\n    -> SemIR::InstId;\n\n// Forms a char type expression for `char` literal.\nauto MakeCharTypeLiteral(Context& context, Parse::NodeId node_id)\n    -> SemIR::TypeInstId;\n\n// Forms an integer type expression for either an `iN` or `uN` literal.\nauto MakeIntTypeLiteral(Context& context, Parse::NodeId node_id,\n                        SemIR::IntKind int_kind, IntId size_id)\n    -> SemIR::TypeInstId;\n\n// Forms an integer type of the specified kind and bit-width.\nauto MakeIntType(Context& context, Parse::NodeId node_id,\n                 SemIR::IntKind int_kind, IntId size_id) -> SemIR::TypeId;\n\n// Forms a floating point type expression for `fN` literal.\nauto MakeFloatTypeLiteral(Context& context, Parse::NodeId node_id,\n                          IntId size_id) -> SemIR::TypeInstId;\n\n// Forms a string literal value instruction for a given string literal.\nauto MakeStringLiteral(Context& context, Parse::StringLiteralId node_id,\n                       StringLiteralValueId value_id) -> SemIR::InstId;\n\n// Forms a string literal type expression for a `str` literal.\nauto MakeStringTypeLiteral(Context& context, Parse::StringTypeLiteralId node_id)\n    -> SemIR::TypeInstId;\n\n// Forms a string type.\nauto MakeStringType(Context& context, SemIR::LocId loc_id) -> TypeExpr;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_LITERAL_H_\n"
  },
  {
    "path": "toolchain/check/member_access.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/member_access.h\"\n\n#include <optional>\n\n#include \"llvm/ADT/STLExtras.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/action.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/impl_lookup.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/interface.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/emitter.h\"\n#include \"toolchain/sem_ir/expr_info.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/generic.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/specific_interface.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Returns the index of the specified class element within the class's\n// representation.\nstatic auto GetClassElementIndex(Context& context, SemIR::InstId element_id)\n    -> SemIR::ElementIndex {\n  auto element_inst = context.insts().Get(element_id);\n  if (auto field = element_inst.TryAs<SemIR::FieldDecl>()) {\n    return field->index;\n  }\n  if (auto base = element_inst.TryAs<SemIR::BaseDecl>()) {\n    return base->index;\n  }\n  CARBON_FATAL(\"Unexpected value {0} in class element name\", element_inst);\n}\n\n// Returns whether `function_id` is an instance method: in other words, whether\n// it has an implicit `self` parameter.\nstatic auto IsInstanceMethod(const SemIR::File& sem_ir,\n                             SemIR::FunctionId function_id) -> bool {\n  const auto& function = sem_ir.functions().Get(function_id);\n  return function.self_param_id.has_value();\n}\n\n// For callee functions which are instance methods, returns the `self_id` (which\n// may be `None`). This may be an instance method either because it's a Carbon\n// instance method or because it's a C++ overload set that might contain an\n// instance method.\nstatic auto GetSelfIfInstanceMethod(const SemIR::File& sem_ir,\n                                    const SemIR::Callee& callee)\n    -> std::optional<SemIR::InstId> {\n  CARBON_KIND_SWITCH(callee) {\n    case CARBON_KIND(SemIR::CalleeFunction fn): {\n      if (IsInstanceMethod(sem_ir, fn.function_id)) {\n        return fn.self_id;\n      }\n      return std::nullopt;\n    }\n    case CARBON_KIND(SemIR::CalleeCppOverloadSet overload): {\n      // For now, treat all C++ overload sets as potentially containing instance\n      // methods. Overload resolution will handle the case where we actually\n      // found a static method.\n      // TODO: Consider returning `None` if there are no non-instance methods\n      // in the overload set. This would cause us to reject\n      // `instance.(Class.StaticMethod)()` like we do in pure Carbon code.\n      return overload.self_id;\n    }\n\n    case CARBON_KIND(SemIR::CalleeError _): {\n      return std::nullopt;\n    }\n    case CARBON_KIND(SemIR::CalleeNonFunction _): {\n      return std::nullopt;\n    }\n  }\n}\n\n// Return whether `type_id`, the type of an associated entity, is for an\n// instance member (currently true only for instance methods).\nstatic auto IsInstanceType(Context& context, SemIR::TypeId type_id) -> bool {\n  if (auto function_type =\n          context.types().TryGetAs<SemIR::FunctionType>(type_id)) {\n    return IsInstanceMethod(context.sem_ir(), function_type->function_id);\n  }\n  return false;\n}\n\nauto GetHighestAllowedAccess(Context& context, SemIR::LocId loc_id,\n                             SemIR::ConstantId name_scope_const_id)\n    -> SemIR::AccessKind {\n  SemIR::ScopeLookupResult lookup_result =\n      LookupUnqualifiedName(context, loc_id, SemIR::NameId::SelfType,\n                            /*required=*/false)\n          .scope_result;\n  CARBON_CHECK(!lookup_result.is_poisoned());\n  if (!lookup_result.is_found()) {\n    return SemIR::AccessKind::Public;\n  }\n\n  // TODO: Support other types for `Self`.\n  auto self_class_type = context.insts().TryGetAs<SemIR::ClassType>(\n      lookup_result.target_inst_id());\n  if (!self_class_type) {\n    return SemIR::AccessKind::Public;\n  }\n\n  auto self_class_info = context.classes().Get(self_class_type->class_id);\n\n  // TODO: Support other types.\n  if (auto class_type = context.insts().TryGetAs<SemIR::ClassType>(\n          context.constant_values().GetInstId(name_scope_const_id))) {\n    auto class_info = context.classes().Get(class_type->class_id);\n\n    if (self_class_info.self_type_id == class_info.self_type_id) {\n      return SemIR::AccessKind::Private;\n    }\n\n    // If the `type_id` of `Self` does not match with the one we're currently\n    // accessing, try checking if this class is of the parent type of `Self`.\n    if (auto base_type_id = self_class_info.GetBaseType(\n            context.sem_ir(), self_class_type->specific_id);\n        base_type_id.has_value()) {\n      if (context.types().GetConstantId(base_type_id) == name_scope_const_id) {\n        return SemIR::AccessKind::Protected;\n      }\n      // TODO: Also check whether this base class has a base class of its own.\n    } else if (auto adapt_type_id = self_class_info.GetAdaptedType(\n                   context.sem_ir(), self_class_type->specific_id);\n               adapt_type_id.has_value()) {\n      if (context.types().GetConstantId(adapt_type_id) == name_scope_const_id) {\n        // TODO: Should we be allowed to access protected fields of a type we\n        // are adapting? The design doesn't allow this.\n        return SemIR::AccessKind::Protected;\n      }\n    }\n  }\n\n  return SemIR::AccessKind::Public;\n}\n\n// Returns whether `scope` is a scope for which impl lookup should be performed\n// if we find an associated entity.\nstatic auto ScopeNeedsImplLookup(Context& context,\n                                 SemIR::ConstantId name_scope_const_id)\n    -> bool {\n  SemIR::InstId inst_id =\n      context.constant_values().GetInstId(name_scope_const_id);\n  CARBON_CHECK(inst_id.has_value());\n  SemIR::Inst inst = context.insts().Get(inst_id);\n\n  if (inst.Is<SemIR::FacetType>()) {\n    // Don't perform impl lookup if an associated entity is named as a member of\n    // a facet type.\n    return false;\n  }\n  if (inst.Is<SemIR::Namespace>()) {\n    // Don't perform impl lookup if an associated entity is named as a namespace\n    // member.\n    // TODO: This case is not yet listed in the design.\n    return false;\n  }\n  // Any other kind of scope is assumed to be a type that implements the\n  // interface containing the associated entity, and impl lookup is performed.\n  return true;\n}\n\nstatic auto AccessMemberOfImplWitness(\n    Context& context, SemIR::LocId loc_id, SemIR::InstId witness_id,\n    SemIR::SpecificId interface_with_self_specific_id, SemIR::InstId member_id)\n    -> SemIR::InstId {\n  auto member_value_id = context.constant_values().GetConstantInstId(member_id);\n  if (!member_value_id.has_value()) {\n    if (member_value_id != SemIR::ErrorInst::InstId) {\n      context.TODO(member_id, \"non-constant associated entity\");\n    }\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto assoc_entity =\n      context.insts().TryGetAs<SemIR::AssociatedEntity>(member_value_id);\n  if (!assoc_entity) {\n    context.TODO(member_id, \"unexpected value for associated entity\");\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // Substitute the interface specific and `Self` type into the type of the\n  // associated entity to find the type of the member access.\n  LoadImportRef(context, assoc_entity->decl_id);\n  auto assoc_type_id = GetTypeForSpecificAssociatedEntity(\n      context, interface_with_self_specific_id, assoc_entity->decl_id);\n\n  return GetOrAddInst<SemIR::ImplWitnessAccess>(context, loc_id,\n                                                {.type_id = assoc_type_id,\n                                                 .witness_id = witness_id,\n                                                 .index = assoc_entity->index});\n}\n\n// For an impl lookup query with a single interface in it, we can convert the\n// result to a single witness InstId.\n//\n// This CHECKs that the result (and thus the query) was a single interface. This\n// generally only makes sense in member access, where the lookup query's\n// interface is found through name lookup, and we don't have an arbitrary\n// `FacetType`.\nstatic auto GetWitnessFromSingleImplLookupResult(\n    Context& context, SemIR::InstBlockIdOrError lookup_result)\n    -> SemIR::InstId {\n  auto witness_id = SemIR::InstId::None;\n  if (lookup_result.has_error_value()) {\n    witness_id = SemIR::ErrorInst::InstId;\n  } else {\n    auto witnesses = context.inst_blocks().Get(lookup_result.inst_block_id());\n    CARBON_CHECK(witnesses.size() == 1);\n    witness_id = witnesses[0];\n  }\n  return witness_id;\n}\n\n// Performs impl lookup for a member name expression. This finds the relevant\n// impl witness and extracts the corresponding impl member.\nstatic auto PerformImplLookup(\n    Context& context, SemIR::LocId loc_id, SemIR::ConstantId type_const_id,\n    SemIR::AssociatedEntityType assoc_type, SemIR::InstId member_id,\n    bool diagnose = true,\n    DiagnosticContextFn missing_impl_diagnostic_context = nullptr)\n    -> SemIR::InstId {\n  auto self_type_id = context.types().GetTypeIdForTypeConstantId(type_const_id);\n  // TODO: Avoid forming and then immediately decomposing a `FacetType` here.\n  auto interface_type_id =\n      GetInterfaceType(context, assoc_type.interface_id,\n                       assoc_type.interface_without_self_specific_id);\n  auto lookup_result = LookupImplWitness(context, loc_id, type_const_id,\n                                         interface_type_id.AsConstantId());\n  if (!lookup_result.has_value()) {\n    if (diagnose) {\n      if (missing_impl_diagnostic_context) {\n        Diagnostics::ContextScope scope(&context.emitter(),\n                                        missing_impl_diagnostic_context);\n        // TODO: Pass in the expression whose type we are printing.\n        CARBON_DIAGNOSTIC(MissingImplInMemberAccessInContext, Error,\n                          \"type {1} does not implement interface {0}\",\n                          SemIR::TypeId, SemIR::TypeId);\n        context.emitter().Emit(loc_id, MissingImplInMemberAccessInContext,\n                               interface_type_id, self_type_id);\n      } else {\n        // TODO: Pass in the expression whose type we are printing.\n        CARBON_DIAGNOSTIC(MissingImplInMemberAccess, Error,\n                          \"cannot access member of interface {0} in type {1} \"\n                          \"that does not implement that interface\",\n                          SemIR::TypeId, SemIR::TypeId);\n        context.emitter().Emit(loc_id, MissingImplInMemberAccess,\n                               interface_type_id, self_type_id);\n      }\n    }\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto witness_id =\n      GetWitnessFromSingleImplLookupResult(context, lookup_result);\n\n  auto self_facet = GetConstantFacetValueForTypeAndInterface(\n      context, context.types().GetTypeInstId(self_type_id),\n      assoc_type.GetSpecificInterface(), witness_id);\n  const auto& interface = context.interfaces().Get(assoc_type.interface_id);\n  auto interface_with_self_specific_id = MakeSpecificWithInnerSelf(\n      context, loc_id, interface.generic_id, interface.generic_with_self_id,\n      assoc_type.interface_without_self_specific_id, self_facet);\n  return AccessMemberOfImplWitness(context, loc_id, witness_id,\n                                   interface_with_self_specific_id, member_id);\n}\n\n// Performs a member name lookup into the specified scope, including performing\n// impl lookup if necessary. If the scope result is `None`, assume an error has\n// already been diagnosed, and return `ErrorInst`.\nstatic auto LookupMemberNameInScope(Context& context, SemIR::LocId loc_id,\n                                    SemIR::InstId base_id,\n                                    SemIR::NameId name_id,\n                                    SemIR::ConstantId name_scope_const_id,\n                                    llvm::ArrayRef<LookupScope> lookup_scopes,\n                                    bool lookup_in_type_of_base, bool required)\n    -> SemIR::InstId {\n  AccessInfo access_info = {\n      .constant_id = name_scope_const_id,\n      .highest_allowed_access =\n          GetHighestAllowedAccess(context, loc_id, name_scope_const_id),\n  };\n  LookupResult result = LookupQualifiedName(\n      context, loc_id, name_id, lookup_scopes, required, access_info);\n\n  if (!result.scope_result.is_found()) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // TODO: This duplicates the work that HandleNameAsExpr does. Factor this out.\n  auto type_id =\n      SemIR::GetTypeOfInstInSpecific(context.sem_ir(), result.specific_id,\n                                     result.scope_result.target_inst_id());\n  CARBON_CHECK(type_id.has_value(), \"Missing type for member {0}\",\n               context.insts().Get(result.scope_result.target_inst_id()));\n\n  // If the named entity has a constant value that depends on its specific,\n  // store the specific too.\n  if (result.specific_id.has_value() &&\n      context.constant_values()\n          .Get(result.scope_result.target_inst_id())\n          .is_symbolic()) {\n    result.scope_result = SemIR::ScopeLookupResult::MakeFound(\n        GetOrAddInst<SemIR::SpecificConstant>(\n            context, loc_id,\n            {.type_id = type_id,\n             .inst_id = result.scope_result.target_inst_id(),\n             .specific_id = result.specific_id}),\n        SemIR::AccessKind::Public);\n  }\n\n  // TODO: Use a different kind of instruction that also references the\n  // `base_id` so that `SemIR` consumers can find it.\n  auto member_id = GetOrAddInst<SemIR::NameRef>(\n      context, loc_id,\n      {.type_id = type_id,\n       .name_id = name_id,\n       .value_id = result.scope_result.target_inst_id()});\n\n  // If member name lookup finds an associated entity name, and the scope is not\n  // a facet type, perform impl lookup.\n  //\n  // TODO: We need to do this as part of searching extended scopes, because a\n  // lookup that finds an associated entity and also finds the corresponding\n  // impl member is not supposed to be treated as ambiguous.\n  if (auto assoc_type =\n          context.types().TryGetAs<SemIR::AssociatedEntityType>(type_id)) {\n    if (lookup_in_type_of_base) {\n      auto base_type_id = context.insts().Get(base_id).type_id();\n      member_id = PerformImplLookup(context, loc_id,\n                                    context.types().GetConstantId(base_type_id),\n                                    *assoc_type, member_id);\n    } else if (ScopeNeedsImplLookup(context, name_scope_const_id)) {\n      // Handles `T.F` where `T` is a type extending an interface containing\n      // `F`.\n      member_id = PerformImplLookup(context, loc_id, name_scope_const_id,\n                                    *assoc_type, member_id);\n    }\n  }\n\n  if (!context.rewrites_stack().empty()) {\n    if (auto access =\n            context.insts().TryGetAs<SemIR::ImplWitnessAccess>(member_id)) {\n      if (auto result = context.rewrites_stack().back().Lookup(\n              context.constant_values().Get(member_id))) {\n        return GetOrAddInst<SemIR::ImplWitnessAccessSubstituted>(\n            context, loc_id,\n            {.type_id = access->type_id,\n             .impl_witness_access_id = member_id,\n             .value_id = result.value()});\n      }\n    }\n  }\n\n  return member_id;\n}\n\n// Performs the instance binding step in member access. If the found member is a\n// field, forms a class member access. If the found member is an instance\n// method, forms a bound method. Otherwise, the member is returned unchanged.\nstatic auto PerformInstanceBinding(Context& context, SemIR::LocId loc_id,\n                                   SemIR::InstId base_id,\n                                   SemIR::InstId member_id) -> SemIR::InstId {\n  // If the member is a function, check whether it's an instance method.\n  if (auto self_id = GetSelfIfInstanceMethod(\n          context.sem_ir(), SemIR::GetCallee(context.sem_ir(), member_id))) {\n    if (self_id->has_value()) {\n      // Found an already-bound method.\n      return member_id;\n    }\n\n    return GetOrAddInst<SemIR::BoundMethod>(\n        context, loc_id,\n        {.type_id =\n             GetSingletonType(context, SemIR::BoundMethodType::TypeInstId),\n         .object_id = base_id,\n         .function_decl_id = member_id});\n  }\n\n  // Otherwise, if it's a field, form a class element access.\n  if (auto unbound_element_type =\n          context.types().TryGetAs<SemIR::UnboundElementType>(\n              context.insts().Get(member_id).type_id())) {\n    // Convert the base to the type of the element if necessary.\n    base_id = ConvertToValueOrRefOfType(\n        context, loc_id, base_id,\n        context.types().GetTypeIdForTypeInstId(\n            unbound_element_type->class_type_inst_id));\n\n    // Find the specified element, which could be either a field or a base\n    // class, and build an element access expression.\n    auto element_id = context.constant_values().GetConstantInstId(member_id);\n    CARBON_CHECK(element_id.has_value(),\n                 \"Non-constant value {0} of unbound element type\",\n                 context.insts().Get(member_id));\n    auto index = GetClassElementIndex(context, element_id);\n    auto access_id = GetOrAddInst<SemIR::ClassElementAccess>(\n        context, loc_id,\n        {.type_id = context.types().GetTypeIdForTypeInstId(\n             unbound_element_type->element_type_inst_id),\n         .base_id = base_id,\n         .index = index});\n    if (SemIR::GetExprCategory(context.sem_ir(), base_id) ==\n            SemIR::ExprCategory::Value &&\n        SemIR::GetExprCategory(context.sem_ir(), access_id) !=\n            SemIR::ExprCategory::Value) {\n      // Class element access on a value expression produces an ephemeral\n      // reference if the class's value representation is a pointer to the\n      // object representation. Add a value acquisition in that case so that the\n      // expression category of the result matches the expression category\n      // of the base.\n      access_id = ConvertToValueExpr(context, access_id);\n    }\n    return access_id;\n  }\n\n  // Not an instance member: no instance binding.\n  return member_id;\n}\n\n// Validates that the index (required to be an IntValue) is valid within the\n// tuple size. Returns the index on success, or nullptr on failure.\nstatic auto ValidateTupleIndex(Context& context, SemIR::LocId loc_id,\n                               SemIR::InstId operand_inst_id,\n                               SemIR::IntValue index_inst, int size)\n    -> std::optional<llvm::APInt> {\n  llvm::APInt index_val = context.ints().Get(index_inst.int_id);\n  if (index_val.uge(size)) {\n    CARBON_DIAGNOSTIC(TupleIndexOutOfBounds, Error,\n                      \"tuple element index `{0}` is past the end of type {1}\",\n                      TypedInt, TypeOfInstId);\n    context.emitter().Emit(loc_id, TupleIndexOutOfBounds,\n                           {.type = index_inst.type_id, .value = index_val},\n                           operand_inst_id);\n    return std::nullopt;\n  }\n  return index_val;\n}\n\nauto PerformMemberAccess(Context& context, SemIR::LocId loc_id,\n                         SemIR::InstId base_id, SemIR::NameId name_id,\n                         bool required) -> SemIR::InstId {\n  // TODO: Member access for dependent member names is supposed to perform a\n  // lookup in both the template definition context and the template\n  // instantiation context, and reject if both succeed but find different\n  // things.\n  if (required) {\n    return HandleAction<SemIR::AccessMemberAction>(\n        context, loc_id,\n        {.type_id = GetSingletonType(context, SemIR::InstType::TypeInstId),\n         .base_id = base_id,\n         .name_id = name_id});\n  } else {\n    return HandleAction<SemIR::AccessOptionalMemberAction>(\n        context, loc_id,\n        {.type_id = GetSingletonType(context, SemIR::InstType::TypeInstId),\n         .base_id = base_id,\n         .name_id = name_id});\n  }\n}\n\n// Common logic for `AccessMemberAction` and `AccessOptionalMemberAction`.\nstatic auto PerformActionHelper(Context& context, SemIR::LocId loc_id,\n                                SemIR::InstId base_id, SemIR::NameId name_id,\n                                bool required) -> SemIR::InstId {\n  // Unwrap the facet value in `base_id` if possible.\n  if (auto facet_value = TryGetCanonicalFacetValue(context, base_id);\n      facet_value.has_value()) {\n    base_id = facet_value;\n  }\n\n  // If the base is a name scope, such as a class or namespace, perform lookup\n  // into that scope.\n  if (auto base_const_id = context.constant_values().Get(base_id);\n      base_const_id.is_constant()) {\n    llvm::SmallVector<LookupScope> lookup_scopes;\n    if (AppendLookupScopesForConstant(context, loc_id, base_const_id,\n                                      base_const_id, &lookup_scopes)) {\n      return LookupMemberNameInScope(\n          context, loc_id, base_id, name_id, base_const_id, lookup_scopes,\n          /*lookup_in_type_of_base=*/false, required);\n    }\n\n    // If the base is a facet (a symbolic name scope), perform lookup into its\n    // facet type.\n    //\n    // TODO: According to the design, this should just lookup directly in the\n    // `base_id` (as part the class case above), as the `base_id` facet should\n    // have member names that directly name members of the `impl`.\n    auto base_type_id = context.insts().Get(base_id).type_id();\n    if (context.types().Is<SemIR::FacetType>(base_type_id)) {\n      // Name lookup into a facet requires the facet type to be complete, so\n      // that any names available through the facet type are known for the\n      // facet.\n      //\n      // TODO: This should be part of AppendLookupScopesForConstant when we do\n      // lookup on the facet directly instead of the facet type. For now it's\n      // here to provide a better diagnostic than what we get when looking for\n      // scopes directly on the facet type.\n      if (!RequireCompleteType(\n              context, base_type_id, SemIR::LocId(base_id), [&](auto& builder) {\n                CARBON_DIAGNOSTIC(\n                    IncompleteTypeInMemberAccessOfFacet, Context,\n                    \"member access into facet of incomplete type {0}\",\n                    SemIR::TypeId);\n                builder.Context(base_id, IncompleteTypeInMemberAccessOfFacet,\n                                base_type_id);\n              })) {\n        // If the scope is invalid in AppendLookupScopesForConstant we still\n        // return true and proceed with lookup, just ignoring that scope.\n        // Match behaviour here for when this moves into\n        // AppendLookupScopesForConstant.\n        base_type_id = SemIR::ErrorInst::TypeId;\n      }\n\n      auto base_type_const_id = context.types().GetConstantId(base_type_id);\n      llvm::SmallVector<LookupScope> lookup_scopes;\n      if (AppendLookupScopesForConstant(context, loc_id, base_type_const_id,\n                                        base_const_id, &lookup_scopes)) {\n        // The name scope constant needs to be a type, but is currently a\n        // FacetType, so perform `as type` to get a FacetAccessType.\n        auto base_as_type = ExprAsType(context, loc_id, base_id);\n        base_type_const_id =\n            context.types().GetConstantId(base_as_type.type_id);\n        return LookupMemberNameInScope(context, loc_id, base_id, name_id,\n                                       base_type_const_id, lookup_scopes,\n                                       /*lookup_in_type_of_base=*/false,\n                                       required);\n      }\n    }\n  }\n\n  // Otherwise, handle `x.F` by performing lookup into the type of `x` (where\n  // `x` is `base_id`).\n  auto base_type_id = context.insts().Get(base_id).type_id();\n\n  // Require a complete type explicitly. Materializing a temporary will too, but\n  // we can produce a better diagnostic here with context about what operation\n  // is being done (member access) that requires the complete type.\n  //\n  // TODO: ConvertToValueOrRefExpr could take context about the operation being\n  // done to give a better error than \"invalid use of\" an incomplete type?\n  if (!RequireCompleteType(\n          context, base_type_id, SemIR::LocId(base_id), [&](auto& builder) {\n            CARBON_DIAGNOSTIC(\n                IncompleteTypeInMemberAccess, Context,\n                \"member access into object of incomplete type {0}\",\n                TypeOfInstId);\n            builder.Context(base_id, IncompleteTypeInMemberAccess, base_id);\n          })) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // Materialize a temporary for the base expression if necessary.\n  base_id = ConvertToValueOrRefExpr(context, base_id);\n  base_type_id = context.insts().Get(base_id).type_id();\n\n  auto lookup_const_id = context.types().GetConstantId(base_type_id);\n\n  // TODO: If the type is a facet, we look through it into the facet's type (a\n  // FacetType) for names. According to the design, we shouldn't need to do\n  // this, as the facet should have member names that directly name members of\n  // the `impl`.\n  auto base_type_as_facet = GetCanonicalFacetOrTypeValue(\n      context, context.types().GetTypeInstId(base_type_id));\n  auto base_type_facet_type_id =\n      context.insts().Get(base_type_as_facet).type_id();\n  if (context.types().Is<SemIR::FacetType>(base_type_facet_type_id)) {\n    lookup_const_id = context.types().GetConstantId(base_type_facet_type_id);\n  }\n\n  // Perform lookup into the base type.\n  llvm::SmallVector<LookupScope> lookup_scopes;\n  if (AppendLookupScopesForConstant(\n          context, loc_id, lookup_const_id,\n          // The `self_type_const_id` should be the type of `base_id` even if\n          // it's a facet.\n          //\n          // TODO: This can be replaced with `lookup_const_id` once we stop\n          // having to look through the facet at its type for the scope.\n          context.types().GetConstantId(base_type_id), &lookup_scopes)) {\n    auto member_id = LookupMemberNameInScope(\n        context, loc_id, base_id, name_id, lookup_const_id, lookup_scopes,\n        /*lookup_in_type_of_base=*/true, required);\n\n    // Perform instance binding if we found an instance member.\n    member_id = PerformInstanceBinding(context, loc_id, base_id, member_id);\n\n    return member_id;\n  }\n\n  // The base type is not a name scope. Try some fallback options.\n  if (auto struct_type = context.insts().TryGetAs<SemIR::StructType>(\n          context.types().GetTypeInstId(base_type_id))) {\n    // TODO: Do we need to optimize this with a lookup table for O(1)?\n    for (auto [i, field] : llvm::enumerate(\n             context.struct_type_fields().Get(struct_type->fields_id))) {\n      if (name_id == field.name_id) {\n        // TODO: Model this as producing a lookup result, and do instance\n        // binding separately. Perhaps a struct type should be a name scope.\n        return GetOrAddInst<SemIR::StructAccess>(\n            context, loc_id,\n            {.type_id =\n                 context.types().GetTypeIdForTypeInstId(field.type_inst_id),\n             .struct_id = base_id,\n             .index = SemIR::ElementIndex(i)});\n      }\n    }\n    if (required) {\n      CARBON_DIAGNOSTIC(QualifiedExprNameNotFound, Error,\n                        \"type {0} does not have a member `{1}`\", TypeOfInstId,\n                        SemIR::NameId);\n      context.emitter().Emit(loc_id, QualifiedExprNameNotFound, base_id,\n                             name_id);\n      return SemIR::ErrorInst::InstId;\n    } else {\n      return SemIR::InstId::None;\n    }\n  }\n\n  if (base_type_id != SemIR::ErrorInst::TypeId) {\n    CARBON_DIAGNOSTIC(QualifiedExprUnsupported, Error,\n                      \"type {0} does not support qualified expressions\",\n                      TypeOfInstId);\n    context.emitter().Emit(loc_id, QualifiedExprUnsupported, base_id);\n  }\n  return SemIR::ErrorInst::InstId;\n}\n\nauto PerformAction(Context& context, SemIR::LocId loc_id,\n                   SemIR::AccessMemberAction action) -> SemIR::InstId {\n  return PerformActionHelper(context, loc_id, action.base_id, action.name_id,\n                             /*required=*/true);\n}\n\nauto PerformAction(Context& context, SemIR::LocId loc_id,\n                   SemIR::AccessOptionalMemberAction action) -> SemIR::InstId {\n  return PerformActionHelper(context, loc_id, action.base_id, action.name_id,\n                             /*required=*/false);\n}\n\n// Logic shared by GetAssociatedValue() and PerformCompoundMemberAccess().\nstatic auto GetAssociatedValueImpl(Context& context, SemIR::LocId loc_id,\n                                   SemIR::InstId base_id,\n                                   const SemIR::AssociatedEntity& assoc_entity,\n                                   SemIR::SpecificInterface specific_interface)\n    -> SemIR::InstId {\n  // Convert to the interface type of the associated member, to get a facet\n  // value.\n  auto interface_type_id = GetInterfaceType(\n      context, specific_interface.interface_id, specific_interface.specific_id);\n  auto self_facet_inst_id =\n      ConvertToValueOfType(context, loc_id, base_id, interface_type_id);\n  if (self_facet_inst_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto self_facet_const_id = context.constant_values().Get(self_facet_inst_id);\n\n  // TODO: We should be able to lookup constant associated values from runtime\n  // facet values by using their FacetType only, but we assume constant values\n  // for impl lookup at the moment.\n  if (!self_facet_const_id.is_constant()) {\n    context.TODO(loc_id, \"associated value lookup on runtime facet value\");\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // TODO: If `ConvertToValueOfType` returned a `FacetValue`, we already got a\n  // witness for this interface there. We don't need to do both a\n  // ConvertToValueOfType and LookupImplWitness, that is redundant. Since we\n  // want to do LookupImplWitness unconditionally (eg. if `base_id` has exactly\n  // the right FacetType already), can we drop the ConvertToValueOfType step?\n  auto lookup_result = LookupImplWitness(\n      context, loc_id, self_facet_const_id,\n      EvalOrAddInst(\n          context, loc_id,\n          FacetTypeFromInterface(context, specific_interface.interface_id,\n                                 specific_interface.specific_id)));\n  CARBON_CHECK(lookup_result.has_value());\n  auto witness_id =\n      GetWitnessFromSingleImplLookupResult(context, lookup_result);\n\n  const auto& interface =\n      context.interfaces().Get(specific_interface.interface_id);\n\n  auto interface_with_self_specific_id = MakeSpecificWithInnerSelf(\n      context, loc_id, interface.generic_id, interface.generic_with_self_id,\n      specific_interface.specific_id, self_facet_const_id);\n\n  // Before we can access the element of the witness, we need to figure out\n  // the type of that element. It depends on the self type and the specific\n  // interface.\n  auto assoc_type_id = GetTypeForSpecificAssociatedEntity(\n      context, interface_with_self_specific_id, assoc_entity.decl_id);\n  // Now that we have the witness, an index into it, and the type of the\n  // result, return the element of the witness.\n  return GetOrAddInst<SemIR::ImplWitnessAccess>(context, loc_id,\n                                                {.type_id = assoc_type_id,\n                                                 .witness_id = witness_id,\n                                                 .index = assoc_entity.index});\n}\n\nauto GetAssociatedValue(Context& context, SemIR::LocId loc_id,\n                        SemIR::InstId base_id,\n                        SemIR::ConstantId assoc_entity_const_id,\n                        SemIR::SpecificInterface specific_interface)\n    -> SemIR::InstId {\n  // TODO: This function shares a code with PerformCompoundMemberAccess(),\n  // it would be nice to reduce the duplication.\n\n  auto value_inst_id =\n      context.constant_values().GetInstId(assoc_entity_const_id);\n  auto assoc_entity =\n      context.insts().GetAs<SemIR::AssociatedEntity>(value_inst_id);\n  auto decl_id = assoc_entity.decl_id;\n  LoadImportRef(context, decl_id);\n\n  return GetAssociatedValueImpl(context, loc_id, base_id, assoc_entity,\n                                specific_interface);\n}\n\nauto PerformCompoundMemberAccess(\n    Context& context, SemIR::LocId loc_id, SemIR::InstId base_id,\n    SemIR::InstId member_expr_id, bool diagnose,\n    DiagnosticContextFn missing_impl_diagnostic_context) -> SemIR::InstId {\n  auto base_type_id = context.insts().Get(base_id).type_id();\n  auto base_type_const_id = context.types().GetConstantId(base_type_id);\n\n  auto member_id = member_expr_id;\n  auto member = context.insts().Get(member_id);\n\n  // If the member expression names an associated entity, impl lookup is always\n  // performed using the type of the base expression.\n  if (auto assoc_type = context.types().TryGetAs<SemIR::AssociatedEntityType>(\n          member.type_id())) {\n    // Step 1: figure out the type of the associated entity from the interface.\n\n    auto value_inst_id = context.constant_values().GetConstantInstId(member_id);\n    // TODO: According to\n    // https://docs.carbon-lang.dev/docs/design/expressions/member_access.html#member-resolution\n    // > For a compound member access, the second operand is evaluated as a\n    // > compile-time constant to determine the member being accessed. The\n    // > evaluation is required to succeed [...]\n    if (!value_inst_id.has_value()) {\n      context.TODO(loc_id, \"Non-constant associated entity value\");\n      return SemIR::ErrorInst::InstId;\n    }\n    auto assoc_entity =\n        context.insts().GetAs<SemIR::AssociatedEntity>(value_inst_id);\n    auto decl_id = assoc_entity.decl_id;\n    LoadImportRef(context, decl_id);\n    auto decl_value_id = context.constant_values().GetConstantInstId(decl_id);\n    auto decl_type_id = context.insts().Get(decl_value_id).type_id();\n\n    if (IsInstanceType(context, decl_type_id)) {\n      // Step 2a: For instance methods, lookup the impl of the interface for\n      // this type and get the method.\n      member_id = PerformImplLookup(context, loc_id, base_type_const_id,\n                                    *assoc_type, member_id, diagnose,\n                                    missing_impl_diagnostic_context);\n      // Next we will perform instance binding.\n    } else {\n      // Step 2b: For non-instance methods and associated constants, we access\n      // the value of the associated constant, and don't do any instance\n      // binding.\n      return GetAssociatedValueImpl(context, loc_id, base_id, assoc_entity,\n                                    assoc_type->GetSpecificInterface());\n    }\n  }\n\n  // Perform instance binding if we found an instance member.\n  member_id = PerformInstanceBinding(context, loc_id, base_id, member_id);\n\n  // If we didn't perform impl lookup or instance binding, that's an error\n  // because the base expression is not used for anything.\n  if (member_id == member_expr_id &&\n      member.type_id() != SemIR::ErrorInst::TypeId) {\n    // As a special case, an integer-valued expression can be used as a member\n    // name when indexing a tuple.\n    if (context.insts().Is<SemIR::TupleType>(\n            context.constant_values().GetInstId(base_type_const_id))) {\n      return PerformTupleAccess(context, loc_id, base_id, member_expr_id);\n    }\n\n    CARBON_DIAGNOSTIC(CompoundMemberAccessDoesNotUseBase, Error,\n                      \"member name of type {0} in compound member access is \"\n                      \"not an instance member or an interface member\",\n                      TypeOfInstId);\n    context.emitter().Emit(loc_id, CompoundMemberAccessDoesNotUseBase,\n                           member_id);\n  }\n\n  return member_id;\n}\n\nauto PerformTupleAccess(Context& context, SemIR::LocId loc_id,\n                        SemIR::InstId tuple_inst_id,\n                        SemIR::InstId index_inst_id) -> SemIR::InstId {\n  tuple_inst_id = ConvertToValueOrRefExpr(context, tuple_inst_id);\n  auto tuple_type_id = context.insts().Get(tuple_inst_id).type_id();\n\n  auto tuple_type = context.types().TryGetAs<SemIR::TupleType>(tuple_type_id);\n  if (!tuple_type) {\n    CARBON_DIAGNOSTIC(TupleIndexOnANonTupleType, Error,\n                      \"type {0} does not support tuple indexing; only \"\n                      \"tuples can be indexed that way\",\n                      TypeOfInstId);\n    context.emitter().Emit(loc_id, TupleIndexOnANonTupleType, tuple_inst_id);\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto diag_non_constant_index = [&] {\n    // TODO: Decide what to do if the index is a symbolic constant.\n    CARBON_DIAGNOSTIC(TupleIndexNotConstant, Error,\n                      \"tuple index must be a constant\");\n    context.emitter().Emit(loc_id, TupleIndexNotConstant);\n    return SemIR::ErrorInst::InstId;\n  };\n  // Diagnose a non-constant index prior to conversion to IntLiteral, because\n  // the conversion will fail if the index is not constant.\n  if (!context.constant_values().Get(index_inst_id).is_concrete()) {\n    return diag_non_constant_index();\n  }\n\n  SemIR::TypeId element_type_id = SemIR::ErrorInst::TypeId;\n  index_inst_id = ConvertToValueOfType(\n      context, SemIR::LocId(index_inst_id), index_inst_id,\n      GetSingletonType(context, SemIR::IntLiteralType::TypeInstId));\n  auto index_const_id = context.constant_values().Get(index_inst_id);\n  if (index_const_id == SemIR::ErrorInst::ConstantId) {\n    return SemIR::ErrorInst::InstId;\n  } else if (!index_const_id.is_concrete()) {\n    return diag_non_constant_index();\n  }\n\n  auto index_literal = context.insts().GetAs<SemIR::IntValue>(\n      context.constant_values().GetInstId(index_const_id));\n  auto type_block = context.inst_blocks().Get(tuple_type->type_elements_id);\n  std::optional<llvm::APInt> index_val = ValidateTupleIndex(\n      context, loc_id, tuple_inst_id, index_literal, type_block.size());\n  if (!index_val) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // TODO: Handle the case when `index_val->getZExtValue()` has too many bits.\n  element_type_id = context.types().GetTypeIdForTypeInstId(\n      type_block[index_val->getZExtValue()]);\n  auto tuple_index = SemIR::ElementIndex(index_val->getZExtValue());\n\n  return GetOrAddInst<SemIR::TupleAccess>(context, loc_id,\n                                          {.type_id = element_type_id,\n                                           .tuple_id = tuple_inst_id,\n                                           .index = tuple_index});\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/member_access.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_MEMBER_ACCESS_H_\n#define CARBON_TOOLCHAIN_CHECK_MEMBER_ACCESS_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Returns the highest allowed access for members of `name_scope_const_id`. For\n// example, if this returns `Protected` then only `Public` and `Protected`\n// accesses are allowed -- not `Private`.\nauto GetHighestAllowedAccess(Context& context, SemIR::LocId loc_id,\n                             SemIR::ConstantId name_scope_const_id)\n    -> SemIR::AccessKind;\n\n// Creates SemIR to perform a member access with base expression `base_id` and\n// member name `name_id`. When `required`, failing to find the name is a\n// diagnosed error; otherwise, `None` is returned. Returns the result of the\n// access.\nauto PerformMemberAccess(Context& context, SemIR::LocId loc_id,\n                         SemIR::InstId base_id, SemIR::NameId name_id,\n                         bool required = true) -> SemIR::InstId;\n\n// Creates SemIR to perform a compound member access with base expression\n// `base_id` and member name expression `member_expr_id`. Returns the result of\n// the access. If specified, `missing_impl_diagnostic_context()` is used to\n// provide context for the error diagnostic when impl binding fails due to a\n// missing `impl`.\n//\n// On failure, an ErrorInst is returned and a diagnostic is produced unless\n// `diagnose` is false. It is incorrect to specify `diagnose` as false if the\n// resulting ErrorInst may appear in the produced SemIR.\nauto PerformCompoundMemberAccess(\n    Context& context, SemIR::LocId loc_id, SemIR::InstId base_id,\n    SemIR::InstId member_expr_id, bool diagnose = true,\n    DiagnosticContextFn missing_impl_diagnostic_context = nullptr)\n    -> SemIR::InstId;\n\n// Finds the value of an associated entity (given by assoc_entity_inst_id, a\n// member of the interface given by interface_type_id) associated with a type or\n// facet (given by base_id). Never does instance binding.\nauto GetAssociatedValue(Context& context, SemIR::LocId loc_id,\n                        SemIR::InstId base_id,\n                        SemIR::ConstantId assoc_entity_const_id,\n                        SemIR::SpecificInterface interface) -> SemIR::InstId;\n\n// Creates SemIR to perform a tuple index with base expression `tuple_inst_id`\n// and index expression `index_inst_id`. Returns the result of the access.\nauto PerformTupleAccess(Context& context, SemIR::LocId loc_id,\n                        SemIR::InstId tuple_inst_id,\n                        SemIR::InstId index_inst_id) -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_MEMBER_ACCESS_H_\n"
  },
  {
    "path": "toolchain/check/merge.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/merge.h\"\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/import.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nCARBON_DIAGNOSTIC(RedeclPrevDecl, Note, \"previously declared here\");\n\n// Diagnoses a redeclaration which is redundant.\nstatic auto DiagnoseRedundant(Context& context, Lex::TokenKind decl_kind,\n                              SemIR::NameId name_id, SemIR::LocId new_loc_id,\n                              SemIR::LocId prev_loc_id) -> void {\n  CARBON_DIAGNOSTIC(RedeclRedundant, Error,\n                    \"redeclaration of `{0} {1}` is redundant\", Lex::TokenKind,\n                    SemIR::NameId);\n  context.emitter()\n      .Build(new_loc_id, RedeclRedundant, decl_kind, name_id)\n      .Note(prev_loc_id, RedeclPrevDecl)\n      .Emit();\n}\n\n// Diagnoses a redefinition.\nstatic auto DiagnoseRedef(Context& context, Lex::TokenKind decl_kind,\n                          SemIR::NameId name_id, SemIR::LocId new_loc_id,\n                          SemIR::LocId prev_loc_id) -> void {\n  CARBON_DIAGNOSTIC(RedeclRedef, Error, \"redefinition of `{0} {1}`\",\n                    Lex::TokenKind, SemIR::NameId);\n  CARBON_DIAGNOSTIC(RedeclPrevDef, Note, \"previously defined here\");\n  context.emitter()\n      .Build(new_loc_id, RedeclRedef, decl_kind, name_id)\n      .Note(prev_loc_id, RedeclPrevDef)\n      .Emit();\n}\n\n// Diagnoses an `extern` versus non-`extern` mismatch.\nstatic auto DiagnoseExternMismatch(Context& context, Lex::TokenKind decl_kind,\n                                   SemIR::NameId name_id,\n                                   SemIR::LocId new_loc_id,\n                                   SemIR::LocId prev_loc_id) -> void {\n  CARBON_DIAGNOSTIC(RedeclExternMismatch, Error,\n                    \"redeclarations of `{0} {1}` must match use of `extern`\",\n                    Lex::TokenKind, SemIR::NameId);\n  context.emitter()\n      .Build(new_loc_id, RedeclExternMismatch, decl_kind, name_id)\n      .Note(prev_loc_id, RedeclPrevDecl)\n      .Emit();\n}\n\n// Diagnoses `extern library` declared in a library importing the owned entity.\nstatic auto DiagnoseExternLibraryInImporter(Context& context,\n                                            Lex::TokenKind decl_kind,\n                                            SemIR::NameId name_id,\n                                            SemIR::LocId new_loc_id,\n                                            SemIR::LocId prev_loc_id) -> void {\n  CARBON_DIAGNOSTIC(ExternLibraryInImporter, Error,\n                    \"cannot declare imported `{0} {1}` as `extern library`\",\n                    Lex::TokenKind, SemIR::NameId);\n  context.emitter()\n      .Build(new_loc_id, ExternLibraryInImporter, decl_kind, name_id)\n      .Note(prev_loc_id, RedeclPrevDecl)\n      .Emit();\n}\n\n// Diagnoses `extern library` pointing to the wrong library.\nstatic auto DiagnoseExternLibraryIncorrect(Context& context,\n                                           SemIR::LocId new_loc_id,\n                                           SemIR::LocId prev_loc_id) -> void {\n  CARBON_DIAGNOSTIC(\n      ExternLibraryIncorrect, Error,\n      \"declaration in {0} doesn't match `extern library` declaration\",\n      SemIR::LibraryNameId);\n  CARBON_DIAGNOSTIC(ExternLibraryExpected, Note,\n                    \"previously declared with `extern library` here\");\n  context.emitter()\n      .Build(new_loc_id, ExternLibraryIncorrect, context.sem_ir().library_id())\n      .Note(prev_loc_id, ExternLibraryExpected)\n      .Emit();\n}\n\nauto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIR::LocId loc_id)\n    -> void {\n  CARBON_DIAGNOSTIC(\n      ExternRequiresDeclInApiFile, Error,\n      \"`extern` entities must have a declaration in the API file\");\n  context.emitter().Emit(loc_id, ExternRequiresDeclInApiFile);\n}\n\nauto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,\n                             SemIR::NameId name_id, RedeclInfo new_decl,\n                             RedeclInfo prev_decl,\n                             SemIR::ImportIRId import_ir_id) -> void {\n  if (!import_ir_id.has_value()) {\n    // Check for disallowed redeclarations in the same file.\n    if (!new_decl.is_definition) {\n      DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc_id,\n                        prev_decl.loc_id);\n      return;\n    }\n    if (prev_decl.is_definition) {\n      DiagnoseRedef(context, decl_kind, name_id, new_decl.loc_id,\n                    prev_decl.loc_id);\n      return;\n    }\n    if (prev_decl.is_extern != new_decl.is_extern) {\n      DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc_id,\n                             prev_decl.loc_id);\n      return;\n    }\n    return;\n  }\n\n  if (import_ir_id == SemIR::ImportIRId::ApiForImpl) {\n    // Check for disallowed redeclarations in the same library. Note that a\n    // forward declaration in the impl is allowed.\n    if (prev_decl.is_definition) {\n      if (new_decl.is_definition) {\n        DiagnoseRedef(context, decl_kind, name_id, new_decl.loc_id,\n                      prev_decl.loc_id);\n      } else {\n        DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc_id,\n                          prev_decl.loc_id);\n      }\n      return;\n    }\n    if (prev_decl.is_extern != new_decl.is_extern) {\n      DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc_id,\n                             prev_decl.loc_id);\n      return;\n    }\n    return;\n  }\n\n  // Check for disallowed redeclarations cross-library.\n  if (new_decl.is_extern && context.sem_ir().is_impl()) {\n    // We continue after issuing the \"missing API declaration\" diagnostic,\n    // because it may still be helpful to note other issues with the\n    // declarations.\n    DiagnoseExternRequiresDeclInApiFile(context, new_decl.loc_id);\n  }\n  if (prev_decl.is_extern != new_decl.is_extern) {\n    DiagnoseExternMismatch(context, decl_kind, name_id, new_decl.loc_id,\n                           prev_decl.loc_id);\n    return;\n  }\n  if (!prev_decl.extern_library_id.has_value()) {\n    if (new_decl.extern_library_id.has_value()) {\n      DiagnoseExternLibraryInImporter(context, decl_kind, name_id,\n                                      new_decl.loc_id, prev_decl.loc_id);\n    } else {\n      DiagnoseRedundant(context, decl_kind, name_id, new_decl.loc_id,\n                        prev_decl.loc_id);\n    }\n    return;\n  }\n  if (prev_decl.extern_library_id != SemIR::LibraryNameId::Error &&\n      prev_decl.extern_library_id != context.sem_ir().library_id()) {\n    DiagnoseExternLibraryIncorrect(context, new_decl.loc_id, prev_decl.loc_id);\n    return;\n  }\n}\n\nauto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id,\n                             SemIR::NameId name_id, SemIR::InstId new_inst_id)\n    -> void {\n  auto& scope = context.name_scopes().Get(scope_id);\n  auto entry_id = scope.Lookup(name_id);\n  if (entry_id) {\n    auto& result = scope.GetEntry(*entry_id).result;\n    result = SemIR::ScopeLookupResult::MakeWrappedLookupResult(\n        new_inst_id, result.access_kind());\n  }\n}\n\n// Returns true if there was an error in declaring the entity, which will have\n// previously been diagnosed.\nstatic auto EntityHasParamError(Context& context, const DeclParams& info)\n    -> bool {\n  for (auto param_patterns_id :\n       {info.implicit_param_patterns_id, info.param_patterns_id}) {\n    if (param_patterns_id.has_value() &&\n        param_patterns_id != SemIR::InstBlockId::Empty) {\n      for (auto param_id : context.inst_blocks().Get(param_patterns_id)) {\n        if (context.insts().Get(param_id).type_id() ==\n            SemIR::ErrorInst::TypeId) {\n          return true;\n        }\n      }\n    }\n  }\n  return false;\n}\n\n// Returns false if a param differs for a redeclaration. The caller is expected\n// to provide a diagnostic.\nstatic auto CheckRedeclParam(Context& context, bool is_implicit_param,\n                             int32_t param_index,\n                             SemIR::InstId orig_new_param_pattern_id,\n                             SemIR::InstId orig_prev_param_pattern_id,\n                             SemIR::SpecificId prev_specific_id, bool diagnose,\n                             bool check_syntax, bool check_self) -> bool {\n  // TODO: Consider differentiating between type and name mistakes. For now,\n  // taking the simpler approach because I also think we may want to refactor\n  // params.\n  CARBON_DIAGNOSTIC(\n      RedeclParamPrevious, Note,\n      \"previous declaration's corresponding {0:implicit |}parameter here\",\n      Diagnostics::BoolAsSelect);\n  auto emit_diagnostic = [&]() {\n    if (!diagnose) {\n      return;\n    }\n    CARBON_DIAGNOSTIC(RedeclParamDiffers, Error,\n                      \"redeclaration differs at {0:implicit |}parameter {1}\",\n                      Diagnostics::BoolAsSelect, int32_t);\n    context.emitter()\n        .Build(orig_new_param_pattern_id, RedeclParamDiffers, is_implicit_param,\n               param_index + 1)\n        .Note(orig_prev_param_pattern_id, RedeclParamPrevious,\n              is_implicit_param)\n        .Emit();\n  };\n\n  struct PatternPair {\n    SemIR::InstId prev_id;\n    SemIR::InstId new_id;\n  };\n\n  llvm::SmallVector<PatternPair, 1> pattern_stack;\n\n  pattern_stack.push_back({.prev_id = orig_prev_param_pattern_id,\n                           .new_id = orig_new_param_pattern_id});\n\n  do {\n    auto patterns = pattern_stack.pop_back_val();\n    auto new_param_pattern = context.insts().Get(patterns.new_id);\n    auto prev_param_pattern = context.insts().Get(patterns.prev_id);\n    if (new_param_pattern.kind() != prev_param_pattern.kind()) {\n      emit_diagnostic();\n      return false;\n    }\n\n    CARBON_KIND_SWITCH(new_param_pattern) {\n      case CARBON_KIND_ANY(SemIR::AnyParamPattern, new_any_param_pattern): {\n        auto prev_any_param_pattern =\n            prev_param_pattern.As<SemIR::AnyParamPattern>();\n        pattern_stack.push_back(\n            {.prev_id = prev_any_param_pattern.subpattern_id,\n             .new_id = new_any_param_pattern.subpattern_id});\n        break;\n      }\n      case CARBON_KIND(SemIR::VarPattern new_var_pattern): {\n        auto prev_var_pattern = prev_param_pattern.As<SemIR::VarPattern>();\n        pattern_stack.push_back({.prev_id = prev_var_pattern.subpattern_id,\n                                 .new_id = new_var_pattern.subpattern_id});\n        break;\n      }\n      case CARBON_KIND_ANY(SemIR::AnyBindingPattern, new_any_binding_pattern): {\n        auto prev_any_binding_pattern =\n            prev_param_pattern.As<SemIR::AnyBindingPattern>();\n        auto new_name_id = context.entity_names()\n                               .Get(new_any_binding_pattern.entity_name_id)\n                               .name_id;\n        auto prev_name_id = context.entity_names()\n                                .Get(prev_any_binding_pattern.entity_name_id)\n                                .name_id;\n\n        if (!check_self && new_name_id == SemIR::NameId::SelfValue &&\n            prev_name_id == SemIR::NameId::SelfValue) {\n          break;\n        }\n\n        auto prev_param_type_id = SemIR::GetTypeOfInstInSpecific(\n            context.sem_ir(), prev_specific_id, patterns.prev_id);\n        if (!context.types().AreEqualAcrossDeclarations(\n                new_param_pattern.type_id(), prev_param_type_id)) {\n          if (!diagnose) {\n            return false;\n          }\n          CARBON_DIAGNOSTIC(\n              RedeclParamDiffersType, Error,\n              \"type {3} of {0:implicit |}parameter {1} in \"\n              \"redeclaration differs from previous parameter type {2}\",\n              Diagnostics::BoolAsSelect, int32_t, SemIR::TypeId, SemIR::TypeId);\n          context.emitter()\n              .Build(orig_new_param_pattern_id, RedeclParamDiffersType,\n                     is_implicit_param, param_index + 1, prev_param_type_id,\n                     new_param_pattern.type_id())\n              .Note(orig_prev_param_pattern_id, RedeclParamPrevious,\n                    is_implicit_param)\n              .Emit();\n          return false;\n        }\n\n        if (check_syntax && new_name_id != prev_name_id) {\n          emit_diagnostic();\n          return false;\n        }\n        break;\n      }\n      default: {\n        CARBON_FATAL(\"Unexpected inst kind in parameter pattern: {0}\",\n                     new_param_pattern.kind());\n      }\n    }\n  } while (!pattern_stack.empty());\n\n  return true;\n}\n\n// Returns false if the param refs differ for a redeclaration.\nstatic auto CheckRedeclParams(Context& context, SemIR::LocId new_decl_loc_id,\n                              SemIR::InstBlockId new_param_patterns_id,\n                              SemIR::LocId prev_decl_loc_id,\n                              SemIR::InstBlockId prev_param_patterns_id,\n                              bool is_implicit_param,\n                              SemIR::SpecificId prev_specific_id, bool diagnose,\n                              bool check_syntax, bool check_self) -> bool {\n  // This will often occur for empty params.\n  if (new_param_patterns_id == prev_param_patterns_id) {\n    return true;\n  }\n\n  // If exactly one of the parameter lists was present, they differ.\n  if (new_param_patterns_id.has_value() != prev_param_patterns_id.has_value()) {\n    if (!diagnose) {\n      return false;\n    }\n    CARBON_DIAGNOSTIC(RedeclParamListDiffers, Error,\n                      \"redeclaration differs because of \"\n                      \"{1:|missing }{0:implicit |}parameter list\",\n                      Diagnostics::BoolAsSelect, Diagnostics::BoolAsSelect);\n    CARBON_DIAGNOSTIC(RedeclParamListPrevious, Note,\n                      \"previously declared \"\n                      \"{1:with|without} {0:implicit |}parameter list\",\n                      Diagnostics::BoolAsSelect, Diagnostics::BoolAsSelect);\n    context.emitter()\n        .Build(new_decl_loc_id, RedeclParamListDiffers, is_implicit_param,\n               new_param_patterns_id.has_value())\n        .Note(prev_decl_loc_id, RedeclParamListPrevious, is_implicit_param,\n              prev_param_patterns_id.has_value())\n        .Emit();\n    return false;\n  }\n\n  CARBON_CHECK(new_param_patterns_id.has_value() &&\n               prev_param_patterns_id.has_value());\n  const auto new_param_pattern_ids =\n      context.inst_blocks().Get(new_param_patterns_id);\n  const auto prev_param_pattern_ids =\n      context.inst_blocks().Get(prev_param_patterns_id);\n  if (new_param_pattern_ids.size() != prev_param_pattern_ids.size()) {\n    if (!diagnose) {\n      return false;\n    }\n    CARBON_DIAGNOSTIC(\n        RedeclParamCountDiffers, Error,\n        \"redeclaration differs because of {0:implicit |}parameter count of {1}\",\n        Diagnostics::BoolAsSelect, int32_t);\n    CARBON_DIAGNOSTIC(\n        RedeclParamCountPrevious, Note,\n        \"previously declared with {0:implicit |}parameter count of {1}\",\n        Diagnostics::BoolAsSelect, int32_t);\n    context.emitter()\n        .Build(new_decl_loc_id, RedeclParamCountDiffers, is_implicit_param,\n               new_param_pattern_ids.size())\n        .Note(prev_decl_loc_id, RedeclParamCountPrevious, is_implicit_param,\n              prev_param_pattern_ids.size())\n        .Emit();\n    return false;\n  }\n  for (auto [index, new_param_pattern_id, prev_param_pattern_id] :\n       llvm::enumerate(new_param_pattern_ids, prev_param_pattern_ids)) {\n    if (!CheckRedeclParam(context, is_implicit_param, index,\n                          new_param_pattern_id, prev_param_pattern_id,\n                          prev_specific_id, diagnose, check_syntax,\n                          check_self)) {\n      return false;\n    }\n  }\n  return true;\n}\n\n// Returns true if the two nodes represent the same syntax.\n// TODO: Detect raw identifiers (will require token changes).\nstatic auto IsNodeSyntaxEqual(Context& context, Parse::NodeId new_node_id,\n                              Parse::NodeId prev_node_id) -> bool {\n  if (context.parse_tree().node_kind(new_node_id) !=\n      context.parse_tree().node_kind(prev_node_id)) {\n    return false;\n  }\n\n  // TODO: Should there be a trivial way to check if we need to check spellings?\n  // Identifiers and literals need their text checked for cross-file matching,\n  // but not intra-file. Keywords and operators shouldn't need the token text\n  // examined at all.\n  auto new_spelling = context.tokens().GetTokenText(\n      context.parse_tree().node_token(new_node_id));\n  auto prev_spelling = context.tokens().GetTokenText(\n      context.parse_tree().node_token(prev_node_id));\n  return new_spelling == prev_spelling;\n}\n\n// Returns false if redeclaration parameter syntax doesn't match.\nstatic auto CheckRedeclParamSyntax(Context& context,\n                                   Parse::NodeId new_first_param_node_id,\n                                   Parse::NodeId new_last_param_node_id,\n                                   Parse::NodeId prev_first_param_node_id,\n                                   Parse::NodeId prev_last_param_node_id,\n                                   bool diagnose) -> bool {\n  // Parse nodes may not always be available to compare.\n  // TODO: Support cross-file syntax checks. Right now imports provide\n  // `NodeId::None`, and we'll need to follow the declaration to its original\n  // file to get the parse tree.\n  if (!new_first_param_node_id.has_value() ||\n      !prev_first_param_node_id.has_value()) {\n    return true;\n  }\n  CARBON_CHECK(new_last_param_node_id.has_value(),\n               \"new_last_param_node_id.has_value should match \"\n               \"new_first_param_node_id.has_value\");\n  CARBON_CHECK(prev_last_param_node_id.has_value(),\n               \"prev_last_param_node_id.has_value should match \"\n               \"prev_first_param_node_id.has_value\");\n  Parse::Tree::PostorderIterator new_iter(new_first_param_node_id);\n  Parse::Tree::PostorderIterator new_end(new_last_param_node_id);\n  Parse::Tree::PostorderIterator prev_iter(prev_first_param_node_id);\n  Parse::Tree::PostorderIterator prev_end(prev_last_param_node_id);\n  // Done when one past the last node to check.\n  ++new_end;\n  ++prev_end;\n\n  // Compare up to the shortest length.\n  for (; new_iter != new_end && prev_iter != prev_end;\n       ++new_iter, ++prev_iter) {\n    auto new_node_id = *new_iter;\n    auto new_node_kind = context.parse_tree().node_kind(new_node_id);\n    // Skip over \"unused\" markers.\n    if (new_node_kind == Parse::NodeKind::UnusedPattern) {\n      ++new_iter;\n      new_node_id = *new_iter;\n      new_node_kind = context.parse_tree().node_kind(new_node_id);\n    }\n    auto prev_node_id = *prev_iter;\n    auto prev_node_kind = context.parse_tree().node_kind(prev_node_id);\n    if (prev_node_kind == Parse::NodeKind::UnusedPattern) {\n      ++prev_iter;\n      prev_node_id = *prev_iter;\n      prev_node_kind = context.parse_tree().node_kind(prev_node_id);\n    }\n    if (!IsNodeSyntaxEqual(context, new_node_id, prev_node_id)) {\n      // Skip difference if it is `Self as` vs. `as` in an `impl` declaration.\n      // https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p3763.md#redeclarations\n      if (new_node_kind == Parse::NodeKind::ImplDefaultSelfAs &&\n          prev_node_kind == Parse::NodeKind::SelfTypeNameExpr &&\n          context.parse_tree().node_kind(prev_iter[1]) ==\n              Parse::NodeKind::ImplTypeAs) {\n        ++prev_iter;\n        continue;\n      }\n      if (prev_node_kind == Parse::NodeKind::ImplDefaultSelfAs &&\n          new_node_kind == Parse::NodeKind::SelfTypeNameExpr &&\n          context.parse_tree().node_kind(new_iter[1]) ==\n              Parse::NodeKind::ImplTypeAs) {\n        ++new_iter;\n        continue;\n      }\n      if (!diagnose) {\n        return false;\n      }\n      CARBON_DIAGNOSTIC(RedeclParamSyntaxDiffers, Error,\n                        \"redeclaration syntax differs here\");\n      CARBON_DIAGNOSTIC(RedeclParamSyntaxPrevious, Note,\n                        \"comparing with previous declaration here\");\n      context.emitter()\n          .Build(new_node_id, RedeclParamSyntaxDiffers)\n          .Note(prev_node_id, RedeclParamSyntaxPrevious)\n          .Emit();\n      return false;\n    }\n  }\n  // The prefixes are the same, but the lengths may still be different. This is\n  // only relevant for `impl` declarations where the final bracketing node is\n  // not included in the range of nodes being compared, and in those cases\n  // `diagnose` is false.\n  if (new_iter != new_end) {\n    CARBON_CHECK(!diagnose);\n    return false;\n  } else if (prev_iter != prev_end) {\n    CARBON_CHECK(!diagnose);\n    return false;\n  }\n\n  return true;\n}\n\nauto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity,\n                            const DeclParams& prev_entity,\n                            SemIR::SpecificId prev_specific_id, bool diagnose,\n                            bool check_syntax, bool check_self) -> bool {\n  if (EntityHasParamError(context, new_entity) ||\n      EntityHasParamError(context, prev_entity)) {\n    return false;\n  }\n  if (!CheckRedeclParams(\n          context, new_entity.loc_id, new_entity.implicit_param_patterns_id,\n          prev_entity.loc_id, prev_entity.implicit_param_patterns_id,\n          /*is_implicit_param=*/true, prev_specific_id, diagnose, check_syntax,\n          check_self)) {\n    return false;\n  }\n  // Don't forward `check_self` here because it's extra cost, and `self` is only\n  // allowed in implicit params.\n  if (!CheckRedeclParams(context, new_entity.loc_id,\n                         new_entity.param_patterns_id, prev_entity.loc_id,\n                         prev_entity.param_patterns_id,\n                         /*is_implicit_param=*/false, prev_specific_id,\n                         diagnose, check_syntax, /*check_self=*/true)) {\n    return false;\n  }\n  if (check_syntax &&\n      !CheckRedeclParamSyntax(context, new_entity.first_param_node_id,\n                              new_entity.last_param_node_id,\n                              prev_entity.first_param_node_id,\n                              prev_entity.last_param_node_id, diagnose)) {\n    return false;\n  }\n  return true;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/merge.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_MERGE_H_\n#define CARBON_TOOLCHAIN_CHECK_MERGE_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/subst.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Diagnoses an `extern` declaration that was not preceded by a declaration in\n// the API file.\nauto DiagnoseExternRequiresDeclInApiFile(Context& context, SemIR::LocId loc_id)\n    -> void;\n\n// Information on new and previous declarations for DiagnoseIfInvalidRedecl.\nstruct RedeclInfo {\n  explicit RedeclInfo(const SemIR::EntityWithParamsBase& params,\n                      SemIR::LocId loc_id, bool is_definition)\n      : loc_id(loc_id),\n        is_definition(is_definition),\n        is_extern(params.is_extern),\n        extern_library_id(params.extern_library_id) {}\n\n  // The associated diagnostic location.\n  SemIR::LocId loc_id;\n  // True if a definition.\n  bool is_definition;\n  // True if an `extern` declaration.\n  bool is_extern;\n  // The library name in `extern library`, or `None` if not present.\n  SemIR::LibraryNameId extern_library_id;\n};\n\n// Checks for various invalid redeclarations. This can emit diagnostics.\n// However, merging is still often appropriate for error recovery, so this\n// doesn't return whether a diagnostic occurred.\n//\n// The kinds of things this verifies are:\n// - A declaration is not redundant.\n// - A definition doesn't redefine a prior definition.\n// - The use of `extern` is consistent within a library.\n// - Multiple libraries do not declare non-`extern`.\nauto DiagnoseIfInvalidRedecl(Context& context, Lex::TokenKind decl_kind,\n                             SemIR::NameId name_id, RedeclInfo new_decl,\n                             RedeclInfo prev_decl,\n                             SemIR::ImportIRId prev_import_ir_id) -> void;\n\n// When the prior name lookup result is an import and we are successfully\n// merging, replace the name lookup result with the reference in the current\n// file.\nauto ReplacePrevInstForMerge(Context& context, SemIR::NameScopeId scope_id,\n                             SemIR::NameId name_id, SemIR::InstId new_inst_id)\n    -> void;\n\n// Information about the parameters of a declaration, which is common across\n// different kinds of entity such as classes and functions.\nstruct DeclParams {\n  explicit DeclParams(const SemIR::EntityWithParamsBase& base)\n      : loc_id(base.latest_decl_id()),\n        first_param_node_id(base.first_param_node_id),\n        last_param_node_id(base.last_param_node_id),\n        implicit_param_patterns_id(base.implicit_param_patterns_id),\n        param_patterns_id(base.param_patterns_id) {}\n\n  DeclParams(SemIR::LocId loc_id, Parse::NodeId first_param_node_id,\n             Parse::NodeId last_param_node_id,\n             SemIR::InstBlockId implicit_param_patterns_id,\n             SemIR::InstBlockId param_patterns_id)\n      : loc_id(loc_id),\n        first_param_node_id(first_param_node_id),\n        last_param_node_id(last_param_node_id),\n        implicit_param_patterns_id(implicit_param_patterns_id),\n        param_patterns_id(param_patterns_id) {}\n\n  // The location of the declaration of the entity.\n  SemIR::LocId loc_id;\n\n  // Parse tree bounds for the parameters, including both implicit and explicit\n  // parameters. These will be compared to match between declaration and\n  // definition.\n  Parse::NodeId first_param_node_id;\n  Parse::NodeId last_param_node_id;\n\n  // The implicit parameters of the entity. Can be `None` if there is no\n  // implicit parameter list.\n  SemIR::InstBlockId implicit_param_patterns_id;\n  // The explicit parameters of the entity. Can be `None` if there is no\n  // explicit parameter list.\n  SemIR::InstBlockId param_patterns_id;\n};\n\n// Checks that the parameters in a redeclaration of an entity match the\n// parameters in the prior declaration. If not, produces a diagnostic if\n// `diagnose` is true, and returns false.\nauto CheckRedeclParamsMatch(Context& context, const DeclParams& new_entity,\n                            const DeclParams& prev_entity,\n                            SemIR::SpecificId prev_specific_id, bool diagnose,\n                            bool check_syntax, bool check_self) -> bool;\n\ninline auto CheckRedeclParamsMatch(Context& context,\n                                   const DeclParams& new_entity,\n                                   const DeclParams& prev_entity) -> bool {\n  return CheckRedeclParamsMatch(context, new_entity, prev_entity,\n                                SemIR::SpecificId::None, /*diagnose=*/true,\n                                /*check_syntax=*/true, /*check_self=*/true);\n}\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_MERGE_H_\n"
  },
  {
    "path": "toolchain/check/modifiers.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/modifiers.h\"\n\n#include <optional>\n\n#include \"toolchain/check/decl_introducer_state.h\"\n\nnamespace Carbon::Check {\n\n// Builds the diagnostic for DiagnoseNotAllowed.\ntemplate <typename... TokenKinds>\nstatic auto StartDiagnoseNotAllowed(\n    Context& context,\n    const Diagnostics::DiagnosticBase<TokenKinds...>& diagnostic_base,\n    Parse::NodeId modifier_node, Lex::TokenKind declaration_kind)\n    -> DiagnosticBuilder {\n  if constexpr (sizeof...(TokenKinds) == 0) {\n    return context.emitter().Build(modifier_node, diagnostic_base);\n  } else if constexpr (sizeof...(TokenKinds) == 1) {\n    return context.emitter().Build(modifier_node, diagnostic_base,\n                                   context.token_kind(modifier_node));\n  } else {\n    static_assert(sizeof...(TokenKinds) == 2);\n    return context.emitter().Build(modifier_node, diagnostic_base,\n                                   context.token_kind(modifier_node),\n                                   declaration_kind);\n  }\n}\n\n// Diagnoses that a modifier wasn't allowed. Handles adding context when\n// possible.\n//\n// The diagnostic can take up to two TokenKinds: the modifier kind, and the\n// declaration kind.\ntemplate <typename... TokenKinds>\nstatic auto DiagnoseNotAllowed(\n    Context& context,\n    const Diagnostics::DiagnosticBase<TokenKinds...>& diagnostic_base,\n    Parse::NodeId modifier_node, Lex::TokenKind decl_kind,\n    SemIR::LocId context_loc_id) -> void {\n  auto diag = StartDiagnoseNotAllowed(context, diagnostic_base, modifier_node,\n                                      decl_kind);\n  if (context_loc_id.has_value()) {\n    CARBON_DIAGNOSTIC(ModifierNotInContext, Note, \"containing definition here\");\n    diag.Note(context_loc_id, ModifierNotInContext);\n  }\n  diag.Emit();\n}\n\n// Returns the KeywordModifierSet corresponding to the ModifierOrder entry.\nstatic auto ModifierOrderAsSet(ModifierOrder order) -> KeywordModifierSet {\n  switch (order) {\n    case ModifierOrder::Access:\n      return KeywordModifierSet::Access;\n    case ModifierOrder::Extern:\n      return KeywordModifierSet::Extern;\n    case ModifierOrder::Extend:\n      return KeywordModifierSet::Extend;\n    case ModifierOrder::Decl:\n      return KeywordModifierSet::Decl;\n    case ModifierOrder::Evaluation:\n      return KeywordModifierSet::Evaluation;\n  }\n}\n\n// Like `LimitModifiersOnDecl`, except says which modifiers are forbidden, and a\n// `context_string` (and optional `context_loc_id`) specifying the context in\n// which those modifiers are forbidden.\n//\n// See DiagnoseNotAllowed for details regarding diagnostic_base.\ntemplate <typename DiagnosticBaseT>\nstatic auto ForbidModifiersOnDecl(\n    Context& context, const DiagnosticBaseT& diagnostic_base,\n    DeclIntroducerState& introducer, KeywordModifierSet forbidden,\n    SemIR::LocId context_loc_id = SemIR::LocId::None) -> void {\n  auto not_allowed = introducer.modifier_set & forbidden;\n  if (not_allowed.empty()) {\n    return;\n  }\n\n  for (auto order_index = 0;\n       order_index <= static_cast<int8_t>(ModifierOrder::Last); ++order_index) {\n    auto order = static_cast<ModifierOrder>(order_index);\n    if (not_allowed.HasAnyOf(ModifierOrderAsSet(order))) {\n      DiagnoseNotAllowed(context, diagnostic_base,\n                         introducer.modifier_node_id(order), introducer.kind,\n                         context_loc_id);\n      introducer.set_modifier_node_id(order, Parse::NodeId::None);\n    }\n  }\n\n  introducer.modifier_set.Remove(forbidden);\n}\n\nauto LimitModifiersOnDecl(Context& context, DeclIntroducerState& introducer,\n                          KeywordModifierSet allowed) -> void {\n  CARBON_DIAGNOSTIC(ModifierNotAllowedOnDeclaration, Error,\n                    \"`{0}` not allowed on `{1}` declaration\", Lex::TokenKind,\n                    Lex::TokenKind);\n  ForbidModifiersOnDecl(context, ModifierNotAllowedOnDeclaration, introducer,\n                        ~allowed);\n}\n\nauto LimitModifiersOnNotDefinition(Context& context,\n                                   DeclIntroducerState& introducer,\n                                   KeywordModifierSet allowed) -> void {\n  CARBON_DIAGNOSTIC(\n      ModifierOnlyAllowedOnDefinition, Error,\n      \"`{0}` not allowed on `{1}` forward declaration, only definition\",\n      Lex::TokenKind, Lex::TokenKind);\n  ForbidModifiersOnDecl(context, ModifierOnlyAllowedOnDefinition, introducer,\n                        ~allowed);\n}\n\nauto CheckAccessModifiersOnDecl(Context& context,\n                                DeclIntroducerState& introducer,\n                                std::optional<SemIR::Inst> parent_scope_inst)\n    -> void {\n  CARBON_DIAGNOSTIC(ModifierProtectedNotAllowed, Error,\n                    \"`protected` not allowed; requires class scope\");\n  if (parent_scope_inst) {\n    if (parent_scope_inst->Is<SemIR::Namespace>()) {\n      // TODO: This assumes that namespaces can only be declared at file scope.\n      // If we add support for non-file-scope namespaces, we will need to check\n      // the parents of the target scope to determine whether we're at file\n      // scope.\n      ForbidModifiersOnDecl(context, ModifierProtectedNotAllowed, introducer,\n                            KeywordModifierSet::Protected);\n      return;\n    }\n\n    if (parent_scope_inst->Is<SemIR::ClassDecl>()) {\n      // Both `private` and `protected` allowed in a class definition.\n      return;\n    }\n  }\n\n  // Otherwise neither `private` nor `protected` allowed.\n  ForbidModifiersOnDecl(context, ModifierProtectedNotAllowed, introducer,\n                        KeywordModifierSet::Protected);\n\n  CARBON_DIAGNOSTIC(ModifierPrivateNotAllowed, Error,\n                    \"`private` not allowed; requires class or file scope\");\n  ForbidModifiersOnDecl(context, ModifierPrivateNotAllowed, introducer,\n                        KeywordModifierSet::Private);\n}\n\nauto CheckMethodModifiersOnFunction(\n    Context& context, DeclIntroducerState& introducer,\n    SemIR::InstId parent_scope_inst_id,\n    std::optional<SemIR::Inst> parent_scope_inst) -> void {\n  if (parent_scope_inst) {\n    if (auto class_decl = parent_scope_inst->TryAs<SemIR::ClassDecl>()) {\n      auto inheritance_kind =\n          context.classes().Get(class_decl->class_id).inheritance_kind;\n      if (inheritance_kind == SemIR::Class::Final) {\n        CARBON_DIAGNOSTIC(\n            ModifierVirtualNotAllowed, Error,\n            \"`virtual` not allowed; requires `abstract` or `base` class scope\");\n        ForbidModifiersOnDecl(context, ModifierVirtualNotAllowed, introducer,\n                              KeywordModifierSet::Virtual,\n                              SemIR::LocId(parent_scope_inst_id));\n      }\n      if (inheritance_kind != SemIR::Class::Abstract) {\n        CARBON_DIAGNOSTIC(\n            ModifierAbstractNotAllowed, Error,\n            \"`abstract` not allowed; requires `abstract` class scope\");\n        ForbidModifiersOnDecl(context, ModifierAbstractNotAllowed, introducer,\n                              KeywordModifierSet::Abstract,\n                              SemIR::LocId(parent_scope_inst_id));\n      }\n      return;\n    }\n  }\n\n  CARBON_DIAGNOSTIC(ModifierRequiresClass, Error,\n                    \"`{0}` not allowed; requires class scope\", Lex::TokenKind);\n  ForbidModifiersOnDecl(context, ModifierRequiresClass, introducer,\n                        KeywordModifierSet::Method);\n}\n\nauto RestrictExternModifierOnDecl(Context& context,\n                                  DeclIntroducerState& introducer,\n                                  std::optional<SemIR::Inst> parent_scope_inst,\n                                  bool is_definition) -> void {\n  if (!introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extern)) {\n    return;\n  }\n\n  if (parent_scope_inst && !parent_scope_inst->Is<SemIR::Namespace>()) {\n    CARBON_DIAGNOSTIC(ModifierExternNotAllowed, Error,\n                      \"`{0}` not allowed; requires file or namespace scope\",\n                      Lex::TokenKind);\n    ForbidModifiersOnDecl(context, ModifierExternNotAllowed, introducer,\n                          KeywordModifierSet::Extern);\n    // Treat as unset.\n    introducer.extern_library = SemIR::LibraryNameId::None;\n    return;\n  }\n\n  if (introducer.extern_library == context.sem_ir().library_id()) {\n    // This prints an error for `extern library`, but doesn't drop it because we\n    // assume there is some other, correct value that we just don't know here.\n    CARBON_DIAGNOSTIC(ExternLibraryIsCurrentLibrary, Error,\n                      \"`extern library` cannot specify the current library\");\n    context.emitter().Emit(introducer.modifier_node_id(ModifierOrder::Extern),\n                           ExternLibraryIsCurrentLibrary);\n    introducer.extern_library = SemIR::LibraryNameId::Error;\n    // Right now this can produce both this and the below diagnostic.\n  }\n\n  if (is_definition && introducer.extern_library.has_value()) {\n    CARBON_DIAGNOSTIC(ExternLibraryOnDefinition, Error,\n                      \"a library cannot be provided for an `extern` modifier \"\n                      \"on a definition\");\n    context.emitter().Emit(introducer.modifier_node_id(ModifierOrder::Extern),\n                           ExternLibraryOnDefinition);\n  }\n}\n\nauto RequireDefaultFinalOnlyInInterfaces(Context& context,\n                                         DeclIntroducerState& introducer,\n                                         SemIR::NameScopeId parent_scope_id)\n    -> void {\n  if (parent_scope_id.has_value() &&\n      context.name_scopes().Get(parent_scope_id).is_interface_definition()) {\n    // Both `default` and `final` allowed in an interface definition.\n    return;\n  }\n  CARBON_DIAGNOSTIC(ModifierRequiresInterface, Error,\n                    \"`{0}` not allowed; requires interface scope\",\n                    Lex::TokenKind);\n  ForbidModifiersOnDecl(context, ModifierRequiresInterface, introducer,\n                        KeywordModifierSet::Interface);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/modifiers.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_MODIFIERS_H_\n#define CARBON_TOOLCHAIN_CHECK_MODIFIERS_H_\n\n#include \"toolchain/check/context.h\"\n\nnamespace Carbon::Check {\n\n// Reports a diagnostic if access control modifiers on this are not allowed for\n// a declaration in `parent_scope_inst`, and updates `introducer`.\n//\n// `parent_scope_inst` may be nullopt for a declaration in a block scope.\nauto CheckAccessModifiersOnDecl(Context& context,\n                                DeclIntroducerState& introducer,\n                                std::optional<SemIR::Inst> parent_scope_inst)\n    -> void;\n\n// Reports a diagnostic if the method function modifiers `abstract`, `virtual`,\n// or `impl` are present but not permitted on a function declaration in\n// `parent_scope_inst`.\n//\n// `parent_scope_inst` may be nullopt for a declaration in a block scope.\nauto CheckMethodModifiersOnFunction(\n    Context& context, DeclIntroducerState& introducer,\n    SemIR::InstId parent_scope_inst_id,\n    std::optional<SemIR::Inst> parent_scope_inst) -> void;\n\n// Reports a diagnostic (using `decl_kind`) if modifiers on this declaration are\n// not in `allowed`. Updates `introducer`.\nauto LimitModifiersOnDecl(Context& context, DeclIntroducerState& introducer,\n                          KeywordModifierSet allowed) -> void;\n\nauto LimitModifiersOnNotDefinition(Context& context,\n                                   DeclIntroducerState& introducer,\n                                   KeywordModifierSet allowed) -> void;\n\n// Restricts the `extern` modifier to only be used on namespace-scoped\n// declarations. Diagnoses and cleans up:\n// - `extern library` on a definition.\n// - `extern` on a scoped entity.\n//\n// `parent_scope_inst` may be nullopt for a declaration in a block scope.\nauto RestrictExternModifierOnDecl(Context& context,\n                                  DeclIntroducerState& introducer,\n                                  std::optional<SemIR::Inst> parent_scope_inst,\n                                  bool is_definition) -> void;\n\n// Report a diagonostic if `default` and `final` modifiers are used on\n// declarations where they are not allowed. Right now they are only allowed\n// inside interfaces.\n//\n// `parent_scope_id` may be None for a declaration in a block scope.\nauto RequireDefaultFinalOnlyInInterfaces(Context& context,\n                                         DeclIntroducerState& introducer,\n                                         SemIR::NameScopeId parent_scope_id)\n    -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_MODIFIERS_H_\n"
  },
  {
    "path": "toolchain/check/name_component.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/name_component.h\"\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/pattern_match.h\"\n\nnamespace Carbon::Check {\n\nauto PopNameComponent(Context& context, SemIR::InstBlockId return_patterns_id)\n    -> NameComponent {\n  Parse::NodeId first_param_node_id = Parse::NoneNodeId();\n  Parse::NodeId last_param_node_id = Parse::NoneNodeId();\n\n  // Explicit params.\n  auto [params_node_id, param_patterns_id] =\n      context.node_stack()\n          .PopWithNodeIdIf<Parse::NodeKind::ExplicitParamList>();\n  if (param_patterns_id) {\n    first_param_node_id =\n        context.node_stack()\n            .PopForSoloNodeId<Parse::NodeKind::ExplicitParamListStart>();\n    last_param_node_id = params_node_id;\n  } else {\n    param_patterns_id = SemIR::InstBlockId::None;\n  }\n\n  // Implicit params.\n  auto [implicit_params_node_id, implicit_param_patterns_id] =\n      context.node_stack()\n          .PopWithNodeIdIf<Parse::NodeKind::ImplicitParamList>();\n  if (implicit_param_patterns_id) {\n    // Implicit params always come before explicit params.\n    first_param_node_id =\n        context.node_stack()\n            .PopForSoloNodeId<Parse::NodeKind::ImplicitParamListStart>();\n    // Only use the end of implicit params if there weren't explicit params.\n    if (!last_param_node_id.has_value()) {\n      last_param_node_id = implicit_params_node_id;\n    }\n  } else {\n    implicit_param_patterns_id = SemIR::InstBlockId::None;\n  }\n\n  auto call_param_patterns_id = SemIR::InstBlockId::None;\n  auto call_params_id = SemIR::InstBlockId::None;\n  auto param_ranges = SemIR::Function::CallParamIndexRanges::Empty;\n  auto pattern_block_id = SemIR::InstBlockId::None;\n  if (param_patterns_id->has_value() ||\n      implicit_param_patterns_id->has_value() ||\n      (!context.inst_blocks().GetOrEmpty(return_patterns_id).empty())) {\n    auto results = CalleePatternMatch(context, *implicit_param_patterns_id,\n                                      *param_patterns_id, return_patterns_id);\n    call_param_patterns_id = results.call_param_patterns_id;\n    call_params_id = results.call_params_id;\n    param_ranges = results.param_ranges;\n    pattern_block_id = context.pattern_block_stack().Pop();\n    context.full_pattern_stack().PopFullPattern();\n  }\n\n  auto [name_loc_id, name_id] =\n      context.node_stack().PopWithNodeId<Parse::NodeCategory::NonExprName>();\n\n  return {\n      .name_loc_id = name_loc_id,\n      .name_id = name_id,\n      .first_param_node_id = first_param_node_id,\n      .last_param_node_id = last_param_node_id,\n      .implicit_params_loc_id = implicit_params_node_id,\n      .implicit_param_patterns_id = *implicit_param_patterns_id,\n      .params_loc_id = params_node_id,\n      .param_patterns_id = *param_patterns_id,\n      .call_param_patterns_id = call_param_patterns_id,\n      .call_params_id = call_params_id,\n      .param_ranges = param_ranges,\n      .pattern_block_id = pattern_block_id,\n  };\n}\n\n// Pop the name of a declaration from the node stack, and diagnose if it has\n// parameters.\nauto PopNameComponentWithoutParams(Context& context, Lex::TokenKind introducer)\n    -> NameComponent {\n  NameComponent name = PopNameComponent(context);\n  if (name.call_params_id.has_value()) {\n    CARBON_DIAGNOSTIC(UnexpectedDeclNameParams, Error,\n                      \"`{0}` declaration cannot have parameters\",\n                      Lex::TokenKind);\n    // Point to the lexically first parameter list in the diagnostic.\n    context.emitter().Emit(name.implicit_param_patterns_id.has_value()\n                               ? name.implicit_params_loc_id\n                               : name.params_loc_id,\n                           UnexpectedDeclNameParams, introducer);\n\n    name.call_params_id = SemIR::InstBlockId::None;\n  }\n  return name;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/name_component.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_NAME_COMPONENT_H_\n#define CARBON_TOOLCHAIN_CHECK_NAME_COMPONENT_H_\n\n#include \"toolchain/check/node_stack.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nclass Context;\n\n// A component in a declaration name, such as `C[T:! type](N:! T)` in\n// `fn C[T:! type](N:! T).F() {}`.\nstruct NameComponent {\n  // The name of the declaration.\n  Parse::NodeId name_loc_id;\n  SemIR::NameId name_id;\n\n  // Parse tree bounds for the parameters, including both implicit and explicit\n  // parameters. These will be compared to match between declaration and\n  // definition.\n  Parse::NodeId first_param_node_id;\n  Parse::NodeId last_param_node_id;\n\n  // The implicit parameter list.\n  Parse::NodeId implicit_params_loc_id;\n  SemIR::InstBlockId implicit_param_patterns_id;\n\n  // The explicit parameter list.\n  Parse::NodeId params_loc_id;\n  SemIR::InstBlockId param_patterns_id;\n\n  // The `Call` parameters of the entity, if it's a function (see the\n  // corresponding members of SemIR::FunctionFields and\n  // SemIR::EntityWithParamsBase).\n  SemIR::InstBlockId call_param_patterns_id;\n  SemIR::InstBlockId call_params_id;\n  SemIR::Function::CallParamIndexRanges param_ranges;\n\n  // The pattern block.\n  SemIR::InstBlockId pattern_block_id;\n};\n\n// Pops a name component from the node stack (and pattern block stack, if it has\n// parameters).\nauto PopNameComponent(Context& context, SemIR::InstBlockId return_patterns_id =\n                                            SemIR::InstBlockId::None)\n    -> NameComponent;\n\n// Equivalent to PopNameComponent, but also diagnoses if the name component has\n// parameters.\nauto PopNameComponentWithoutParams(Context& context, Lex::TokenKind introducer)\n    -> NameComponent;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_NAME_COMPONENT_H_\n"
  },
  {
    "path": "toolchain/check/name_lookup.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/name_lookup.h\"\n\n#include <optional>\n\n#include \"common/raw_string_ostream.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/cpp/import.h\"\n#include \"toolchain/check/facet_type.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/import.h\"\n#include \"toolchain/check/import_ref.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/member_access.h\"\n#include \"toolchain/check/subst.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/check/type_completion.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/sem_ir/generic.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n\nnamespace Carbon::Check {\n\nauto AddNameToLookup(Context& context, SemIR::NameId name_id,\n                     SemIR::InstId target_id, ScopeIndex scope_index) -> void {\n  if (auto existing = context.scope_stack().LookupOrAddName(\n          name_id, target_id, scope_index, IsCurrentPositionReachable(context));\n      existing.has_value()) {\n    // TODO: Add coverage to this use case and use the location of the name\n    // instead of the target.\n    DiagnoseDuplicateName(context, name_id, SemIR::LocId(target_id),\n                          SemIR::LocId(existing));\n  }\n}\n\nauto LookupNameInDecl(Context& context, SemIR::LocId loc_id,\n                      SemIR::NameId name_id, SemIR::NameScopeId scope_id,\n                      ScopeIndex scope_index) -> SemIR::ScopeLookupResult {\n  if (!scope_id.has_value()) {\n    // Look for a name in the specified scope or a scope nested within it only.\n    // There are two cases where the name would be in an outer scope:\n    //\n    //  - The name is the sole component of the declared name:\n    //\n    //    class A;\n    //    fn F() {\n    //      class A;\n    //    }\n    //\n    //    In this case, the inner A is not the same class as the outer A, so\n    //    lookup should not find the outer A.\n    //\n    //  - The name is a qualifier of some larger declared name:\n    //\n    //    class A { class B; }\n    //    fn F() {\n    //      class A.B {}\n    //    }\n    //\n    //    In this case, we're not in the correct scope to define a member of\n    //    class A, so we should reject, and we achieve this by not finding the\n    //    name A from the outer scope.\n    //\n    // There is also one case where the name would be in an inner scope:\n    //\n    //  - The name is redeclared by a parameter of the same entity:\n    //\n    //    fn F() {\n    //      class C(C:! type);\n    //    }\n    //\n    // In this case, the class C is not a redeclaration of its parameter, but\n    // we find the parameter in order to diagnose a redeclaration error.\n    return SemIR::ScopeLookupResult::MakeWrappedLookupResult(\n        context.scope_stack().LookupInLexicalScopesWithin(\n            name_id, scope_index, /*use_loc_id=*/SemIR::LocId::None,\n            /*is_reachable=*/true),\n        SemIR::AccessKind::Public);\n  } else {\n    // We do not look into `extend`ed scopes here. A qualified name in a\n    // declaration must specify the exact scope in which the name was originally\n    // introduced:\n    //\n    //    base class A { fn F(); }\n    //    class B { extend base: A; }\n    //\n    //    // Error, no `F` in `B`.\n    //    fn B.F() {}\n    return LookupNameInExactScope(context, loc_id, name_id, scope_id,\n                                  context.name_scopes().Get(scope_id),\n                                  /*is_being_declared=*/true);\n  }\n}\n\nauto LookupUnqualifiedName(Context& context, SemIR::LocId loc_id,\n                           SemIR::NameId name_id, bool required)\n    -> LookupResult {\n  // TODO: Check for shadowed lookup results.\n\n  // Find the results from ancestor lexical scopes. These will be combined with\n  // results from non-lexical scopes such as namespaces and classes.\n  auto [lexical_result, non_lexical_scopes] =\n      context.scope_stack().LookupInLexicalScopes(\n          name_id, loc_id, IsCurrentPositionReachable(context));\n\n  // Walk the non-lexical scopes and perform lookups into each of them.\n  for (auto [index, lookup_scope_id, specific_id] :\n       llvm::reverse(non_lexical_scopes)) {\n    if (auto non_lexical_result = LookupQualifiedName(\n            context, loc_id, name_id,\n            LookupScope{.name_scope_id = lookup_scope_id,\n                        .specific_id = specific_id,\n                        // A non-lexical lookup does not know what `Self` will\n                        // be; it remains symbolic if needed.\n                        .self_const_id = SemIR::ConstantId::None},\n            /*required=*/false);\n        non_lexical_result.scope_result.is_found()) {\n      // In an interface definition, replace associated entity `M` with\n      // `Self.M` (where the `Self` is the `Self` of the interface).\n      const auto& scope = context.name_scopes().Get(lookup_scope_id);\n      if (scope.is_interface_definition()) {\n        SemIR::InstId target_inst_id =\n            non_lexical_result.scope_result.target_inst_id();\n        if (auto assoc_type =\n                context.types().TryGetAs<SemIR::AssociatedEntityType>(\n                    SemIR::GetTypeOfInstInSpecific(\n                        context.sem_ir(), non_lexical_result.specific_id,\n                        target_inst_id))) {\n          auto interface_decl =\n              context.insts().GetAs<SemIR::InterfaceWithSelfDecl>(\n                  scope.inst_id());\n          const auto& interface =\n              context.interfaces().Get(interface_decl.interface_id);\n          SemIR::InstId result_inst_id = GetAssociatedValue(\n              context, loc_id, interface.self_param_id,\n              SemIR::GetConstantValueInSpecific(context.sem_ir(),\n                                                non_lexical_result.specific_id,\n                                                target_inst_id),\n              assoc_type->GetSpecificInterface());\n          non_lexical_result = {\n              .specific_id = SemIR::SpecificId::None,\n              .scope_result = SemIR::ScopeLookupResult::MakeFound(\n                  result_inst_id,\n                  non_lexical_result.scope_result.access_kind())};\n        }\n      }\n      return non_lexical_result;\n    }\n  }\n\n  if (lexical_result == SemIR::InstId::InitTombstone) {\n    CARBON_DIAGNOSTIC(UsedBeforeInitialization, Error,\n                      \"`{0}` used before initialization\", SemIR::NameId);\n    context.emitter().Emit(loc_id, UsedBeforeInitialization, name_id);\n    return {.specific_id = SemIR::SpecificId::None,\n            .scope_result = SemIR::ScopeLookupResult::MakeError()};\n  }\n\n  if (lexical_result.has_value()) {\n    // A lexical scope never needs an associated specific. If there's a\n    // lexically enclosing generic, then it also encloses the point of use of\n    // the name.\n    return {.specific_id = SemIR::SpecificId::None,\n            .scope_result = SemIR::ScopeLookupResult::MakeFound(\n                lexical_result, SemIR::AccessKind::Public)};\n  }\n\n  // We didn't find anything at all.\n  if (required) {\n    DiagnoseNameNotFound(context, loc_id, name_id);\n  }\n\n  // TODO: Should this return MakeNotFound if `required` is false, so that\n  // `is_found()` would be false?\n  return {.specific_id = SemIR::SpecificId::None,\n          .scope_result = SemIR::ScopeLookupResult::MakeError()};\n}\n\nauto LookupNameInExactScope(Context& context, SemIR::LocId loc_id,\n                            SemIR::NameId name_id, SemIR::NameScopeId scope_id,\n                            SemIR::NameScope& scope, bool is_being_declared)\n    -> SemIR::ScopeLookupResult {\n  if (auto entry_id = is_being_declared\n                          ? scope.Lookup(name_id)\n                          : scope.LookupOrPoison(loc_id, name_id)) {\n    auto lookup_result = scope.GetEntry(*entry_id).result;\n    if (!lookup_result.is_poisoned()) {\n      LoadImportRef(context, lookup_result.target_inst_id());\n    }\n    return lookup_result;\n  }\n\n  if (!scope.import_ir_scopes().empty()) {\n    // TODO: Enforce other access modifiers for imports.\n    return SemIR::ScopeLookupResult::MakeWrappedLookupResult(\n        ImportNameFromOtherPackage(context, loc_id, scope_id,\n                                   scope.import_ir_scopes(), name_id),\n        SemIR::AccessKind::Public);\n  }\n\n  if (scope.is_cpp_scope()) {\n    return ImportNameFromCpp(context, loc_id, scope_id, name_id);\n  }\n\n  return SemIR::ScopeLookupResult::MakeNotFound();\n}\n\n// Prints diagnostics on invalid qualified name access.\nstatic auto DiagnoseInvalidQualifiedNameAccess(\n    Context& context, SemIR::LocId loc_id, SemIR::LocId member_loc_id,\n    SemIR::NameId name_id, SemIR::AccessKind access_kind, bool is_parent_access,\n    AccessInfo access_info) -> void {\n  auto class_type = context.insts().TryGetAs<SemIR::ClassType>(\n      context.constant_values().GetInstId(access_info.constant_id));\n  if (!class_type) {\n    return;\n  }\n\n  // TODO: Support scoped entities other than just classes.\n  const auto& class_info = context.classes().Get(class_type->class_id);\n\n  auto parent_type_id = class_info.self_type_id;\n\n  if (access_kind == SemIR::AccessKind::Private && is_parent_access) {\n    if (auto base_type_id =\n            class_info.GetBaseType(context.sem_ir(), class_type->specific_id);\n        base_type_id.has_value()) {\n      parent_type_id = base_type_id;\n    } else if (auto adapted_type_id = class_info.GetAdaptedType(\n                   context.sem_ir(), class_type->specific_id);\n               adapted_type_id.has_value()) {\n      parent_type_id = adapted_type_id;\n    } else {\n      CARBON_FATAL(\"Expected parent for parent access\");\n    }\n  }\n\n  CARBON_DIAGNOSTIC(\n      ClassInvalidMemberAccess, Error,\n      \"cannot access {0:private|protected} member `{1}` of type {2}\",\n      Diagnostics::BoolAsSelect, SemIR::NameId, SemIR::TypeId);\n  CARBON_DIAGNOSTIC(ClassMemberDeclaration, Note, \"declared here\");\n  context.emitter()\n      .Build(loc_id, ClassInvalidMemberAccess,\n             access_kind == SemIR::AccessKind::Private, name_id, parent_type_id)\n      .Note(member_loc_id, ClassMemberDeclaration)\n      .Emit();\n}\n\n// Returns whether the access is prohibited by the access modifiers.\nstatic auto IsAccessProhibited(std::optional<AccessInfo> access_info,\n                               SemIR::AccessKind access_kind,\n                               bool is_parent_access) -> bool {\n  if (!access_info) {\n    return false;\n  }\n\n  switch (access_kind) {\n    case SemIR::AccessKind::Public:\n      return false;\n    case SemIR::AccessKind::Protected:\n      return access_info->highest_allowed_access == SemIR::AccessKind::Public;\n    case SemIR::AccessKind::Private:\n      return access_info->highest_allowed_access !=\n                 SemIR::AccessKind::Private ||\n             is_parent_access;\n  }\n}\n\nauto CheckAccess(Context& context, SemIR::LocId loc_id,\n                 SemIR::LocId member_loc_id, SemIR::NameId name_id,\n                 SemIR::AccessKind access_kind, bool is_parent_access,\n                 AccessInfo access_info) -> void {\n  if (IsAccessProhibited(access_info, access_kind, is_parent_access)) {\n    DiagnoseInvalidQualifiedNameAccess(context, loc_id, member_loc_id, name_id,\n                                       access_kind, is_parent_access,\n                                       access_info);\n  }\n}\n\n// Information regarding a prohibited access.\nstruct ProhibitedAccessInfo {\n  // The resulting inst of the lookup.\n  SemIR::InstId scope_result_id;\n  // The access kind of the lookup.\n  SemIR::AccessKind access_kind;\n  // If the lookup is from an extended scope. For example, if this is a base\n  // class member access from a class that extends it.\n  bool is_parent_access;\n};\n\nstatic auto GetSelfFacetForInterfaceFromLookupSelfType(\n    Context& context, const SemIR::GenericId generic_with_self_id,\n    SemIR::ConstantId self_type_const_id) -> SemIR::ConstantId {\n  if (!self_type_const_id.has_value()) {\n    // In a lookup into a non-lexical scope, there is no self-type from the\n    // lookup for the interface-with-self specific. So the self-type we use is\n    // the abstract symbolic Self from the self specific of the\n    // interface-with-self.\n    auto self_specific_args_id = context.specifics().GetArgsOrEmpty(\n        context.generics().GetSelfSpecific(generic_with_self_id));\n    auto self_specific_args = context.inst_blocks().Get(self_specific_args_id);\n    return context.constant_values().Get(self_specific_args.back());\n  }\n\n  if (context.insts().Is<SemIR::FacetType>(\n          context.constant_values().GetInstId(self_type_const_id))) {\n    // We are looking directly in a facet type, like `I.F` for an interface `I`,\n    // which means there is no self-type from the lookup for the\n    // interface-with-self specific. So the self-type we use is the abstract\n    // symbolic Self from the self specific of the interface-with-self.\n    auto self_specific_args_id = context.specifics().GetArgsOrEmpty(\n        context.generics().GetSelfSpecific(generic_with_self_id));\n    auto self_specific_args = context.inst_blocks().Get(self_specific_args_id);\n    return context.constant_values().Get(self_specific_args.back());\n  }\n\n  // Extended name lookup into a type, like `x.F`, can find a facet\n  // type extended scope from the type of `x`. The type of `x` maybe a\n  // facet converted to a type, so drop the `as type` conversion if\n  // so.\n  auto canonical_facet_or_type =\n      GetCanonicalFacetOrTypeValue(context, self_type_const_id);\n\n  auto type_of_canonical_facet_or_type =\n      context.insts()\n          .Get(context.constant_values().GetInstId(canonical_facet_or_type))\n          .type_id();\n  if (type_of_canonical_facet_or_type == SemIR::TypeType::TypeId) {\n    // If we still have a type, turn it into a facet for use in the\n    // interface-with-self specific.\n    return GetConstantFacetValueForType(\n        context, context.types().GetAsTypeInstId(\n                     context.constant_values().GetInstId(self_type_const_id)));\n  }\n\n  // We have a facet for the self-type (or perhaps an ErrorInst), which we can\n  // use directly in the interface-with-self specific.\n  return canonical_facet_or_type;\n}\n\nauto AppendLookupScopesForConstant(Context& context, SemIR::LocId loc_id,\n                                   SemIR::ConstantId lookup_const_id,\n                                   SemIR::ConstantId self_type_const_id,\n                                   llvm::SmallVector<LookupScope>* scopes)\n    -> bool {\n  auto lookup_inst_id = context.constant_values().GetInstId(lookup_const_id);\n  auto lookup = context.insts().Get(lookup_inst_id);\n\n  if (auto ns = lookup.TryAs<SemIR::Namespace>()) {\n    scopes->push_back(LookupScope{.name_scope_id = ns->name_scope_id,\n                                  .specific_id = SemIR::SpecificId::None,\n                                  .self_const_id = SemIR::ConstantId::None});\n    return true;\n  }\n  if (auto class_ty = lookup.TryAs<SemIR::ClassType>()) {\n    // TODO: Allow name lookup into classes that are being defined even if they\n    // are not complete.\n    RequireCompleteType(\n        context, context.types().GetTypeIdForTypeConstantId(lookup_const_id),\n        loc_id, [&](auto& builder) {\n          CARBON_DIAGNOSTIC(QualifiedExprInIncompleteClassScope, Context,\n                            \"member access into incomplete class {0}\",\n                            InstIdAsType);\n          builder.Context(loc_id, QualifiedExprInIncompleteClassScope,\n                          lookup_inst_id);\n        });\n    auto& class_info = context.classes().Get(class_ty->class_id);\n    scopes->push_back(LookupScope{.name_scope_id = class_info.scope_id,\n                                  .specific_id = class_ty->specific_id,\n                                  .self_const_id = self_type_const_id});\n    return true;\n  }\n  // Extended scopes may point to a FacetType.\n  if (auto facet_type = lookup.TryAs<SemIR::FacetType>()) {\n    // TODO: Allow name lookup into facet types that are being defined even if\n    // they are not complete.\n    if (RequireCompleteType(\n            context,\n            context.types().GetTypeIdForTypeConstantId(lookup_const_id), loc_id,\n            [&](auto& builder) {\n              CARBON_DIAGNOSTIC(\n                  QualifiedExprInIncompleteFacetTypeScope, Context,\n                  \"member access into incomplete facet type {0}\", InstIdAsType);\n              builder.Context(loc_id, QualifiedExprInIncompleteFacetTypeScope,\n                              lookup_inst_id);\n            })) {\n      auto facet_type_info =\n          context.facet_types().Get(facet_type->facet_type_id);\n      // Name lookup into \"extend\" constraints but not \"self impls\" constraints.\n      for (const auto& extend : facet_type_info.extend_constraints) {\n        auto& interface = context.interfaces().Get(extend.interface_id);\n\n        // We need to build the inner interface-with-self specific. To do that\n        // we need to determine the self facet value to use.\n        auto self_facet = GetSelfFacetForInterfaceFromLookupSelfType(\n            context, interface.generic_with_self_id, self_type_const_id);\n        auto interface_with_self_specific_id = MakeSpecificWithInnerSelf(\n            context, loc_id, interface.generic_id,\n            interface.generic_with_self_id, extend.specific_id, self_facet);\n\n        scopes->push_back({.name_scope_id = interface.scope_with_self_id,\n                           .specific_id = interface_with_self_specific_id,\n                           .self_const_id = self_type_const_id});\n      }\n      for (const auto& extend : facet_type_info.extend_named_constraints) {\n        auto& constraint =\n            context.named_constraints().Get(extend.named_constraint_id);\n\n        // We need to build the inner constraint-with-self specific. To do that\n        // we need to determine the self facet value to use.\n        auto self_facet = GetSelfFacetForInterfaceFromLookupSelfType(\n            context, constraint.generic_with_self_id, self_type_const_id);\n        auto constraint_with_self_specific_id = MakeSpecificWithInnerSelf(\n            context, loc_id, constraint.generic_id,\n            constraint.generic_with_self_id, extend.specific_id, self_facet);\n\n        scopes->push_back({.name_scope_id = constraint.scope_with_self_id,\n                           .specific_id = constraint_with_self_specific_id,\n                           .self_const_id = self_type_const_id});\n      }\n    } else {\n      // Lookup into this scope should fail without producing an error since\n      // `RequireCompleteFacetType` has already issued a diagnostic.\n      scopes->push_back(LookupScope{.name_scope_id = SemIR::NameScopeId::None,\n                                    .specific_id = SemIR::SpecificId::None,\n                                    .self_const_id = SemIR::ConstantId::None});\n    }\n    return true;\n  }\n  if (lookup_const_id == SemIR::ErrorInst::ConstantId) {\n    // Lookup into this scope should fail without producing an error.\n    scopes->push_back(LookupScope{.name_scope_id = SemIR::NameScopeId::None,\n                                  .specific_id = SemIR::SpecificId::None,\n                                  .self_const_id = SemIR::ConstantId::None});\n    return true;\n  }\n  // TODO: Per the design, if `base_id` is any kind of type, then lookup should\n  // treat it as a name scope, even if it doesn't have members. For example,\n  // `(i32*).X` should fail because there's no name `X` in `i32*`, not because\n  // there's no name `X` in `type`.\n  return false;\n}\n\n// Prints a diagnostic for a missing qualified name.\nstatic auto DiagnoseMemberNameNotFound(\n    Context& context, SemIR::LocId loc_id, SemIR::NameId name_id,\n    llvm::ArrayRef<LookupScope> lookup_scopes) -> void {\n  if (lookup_scopes.size() == 1 &&\n      lookup_scopes.front().name_scope_id.has_value()) {\n    if (auto specific_id = lookup_scopes.front().specific_id;\n        specific_id.has_value()) {\n      CARBON_DIAGNOSTIC(MemberNameNotFoundInSpecificScope, Error,\n                        \"member name `{0}` not found in {1}\", SemIR::NameId,\n                        SemIR::SpecificId);\n      context.emitter().Emit(loc_id, MemberNameNotFoundInSpecificScope, name_id,\n                             specific_id);\n    } else {\n      auto scope_inst_id = context.name_scopes()\n                               .Get(lookup_scopes.front().name_scope_id)\n                               .inst_id();\n      CARBON_DIAGNOSTIC(MemberNameNotFoundInInstScope, Error,\n                        \"member name `{0}` not found in {1}\", SemIR::NameId,\n                        InstIdAsType);\n      context.emitter().Emit(loc_id, MemberNameNotFoundInInstScope, name_id,\n                             scope_inst_id);\n    }\n    return;\n  }\n\n  CARBON_DIAGNOSTIC(MemberNameNotFound, Error, \"member name `{0}` not found\",\n                    SemIR::NameId);\n  context.emitter().Emit(loc_id, MemberNameNotFound, name_id);\n}\n\nauto LookupQualifiedName(Context& context, SemIR::LocId loc_id,\n                         SemIR::NameId name_id,\n                         llvm::ArrayRef<LookupScope> lookup_scopes,\n                         bool required, std::optional<AccessInfo> access_info)\n    -> LookupResult {\n  llvm::SmallVector<LookupScope> scopes(lookup_scopes);\n\n  // TODO: Support reporting of multiple prohibited access.\n  llvm::SmallVector<ProhibitedAccessInfo> prohibited_accesses;\n\n  LookupResult result = {\n      .specific_id = SemIR::SpecificId::None,\n      .scope_result = SemIR::ScopeLookupResult::MakeNotFound()};\n  auto parent_const_id = SemIR::ConstantId::None;\n  bool has_error = false;\n  bool is_parent_access = false;\n\n  // Walk this scope and, if nothing is found here, the scopes it extends.\n  while (!scopes.empty()) {\n    auto [scope_id, specific_id, self_const_id] = scopes.pop_back_val();\n    if (!scope_id.has_value()) {\n      has_error = true;\n      continue;\n    }\n    auto& name_scope = context.name_scopes().Get(scope_id);\n    has_error |= name_scope.has_error();\n\n    const SemIR::ScopeLookupResult scope_result =\n        LookupNameInExactScope(context, loc_id, name_id, scope_id, name_scope);\n    SemIR::AccessKind access_kind = scope_result.access_kind();\n\n    if (is_parent_access && scope_result.is_found() &&\n        !access_info.has_value()) {\n      access_info =\n          AccessInfo{.constant_id = parent_const_id,\n                     .highest_allowed_access = SemIR::AccessKind::Protected};\n    }\n\n    auto is_access_prohibited =\n        IsAccessProhibited(access_info, access_kind, is_parent_access);\n\n    // Keep track of prohibited accesses, this will be useful for reporting\n    // multiple prohibited accesses if we can't find a suitable lookup.\n    if (is_access_prohibited) {\n      prohibited_accesses.push_back({\n          .scope_result_id = scope_result.target_inst_id(),\n          .access_kind = access_kind,\n          .is_parent_access = is_parent_access,\n      });\n    }\n\n    if (!scope_result.is_found() || is_access_prohibited) {\n      // If nothing is found in this scope or if we encountered an invalid\n      // access, look in its extended scopes.\n      const auto& extended = name_scope.extended_scopes();\n      scopes.reserve(scopes.size() + extended.size());\n      for (auto extended_id : llvm::reverse(extended)) {\n        // Substitute into the constant describing the extended scope to\n        // determine its corresponding specific.\n        CARBON_CHECK(extended_id.has_value());\n        LoadImportRef(context, extended_id);\n        SemIR::ConstantId const_id = GetConstantValueInSpecific(\n            context.sem_ir(), specific_id, extended_id);\n        if (!AppendLookupScopesForConstant(context, loc_id, const_id,\n                                           self_const_id, &scopes)) {\n          // TODO: Handle case where we have a symbolic type and instead should\n          // look in its type.\n        }\n      }\n      is_parent_access |= !extended.empty();\n      parent_const_id = context.constant_values().Get(name_scope.inst_id());\n      continue;\n    }\n\n    // If this is our second lookup result, diagnose an ambiguity.\n    if (result.scope_result.is_found()) {\n      CARBON_DIAGNOSTIC(\n          NameAmbiguousDueToExtend, Error,\n          \"ambiguous use of name `{0}` found in multiple extended scopes\",\n          SemIR::NameId);\n      context.emitter().Emit(loc_id, NameAmbiguousDueToExtend, name_id);\n      // TODO: Add notes pointing to the scopes.\n      return {.specific_id = SemIR::SpecificId::None,\n              .scope_result = SemIR::ScopeLookupResult::MakeError()};\n    }\n\n    result.scope_result = scope_result;\n    result.specific_id = specific_id;\n  }\n\n  if ((!prohibited_accesses.empty() || required) &&\n      !result.scope_result.is_found()) {\n    if (!has_error) {\n      if (prohibited_accesses.empty()) {\n        DiagnoseMemberNameNotFound(context, loc_id, name_id, lookup_scopes);\n      } else {\n        //  TODO: We should report multiple prohibited accesses in case we don't\n        //  find a valid lookup. Reporting the last one should suffice for now.\n        auto [scope_result_id, access_kind, is_parent_access] =\n            prohibited_accesses.back();\n\n        // Note, `access_info` is guaranteed to have a value here, since\n        // `prohibited_accesses` is non-empty.\n        DiagnoseInvalidQualifiedNameAccess(\n            context, loc_id, SemIR::LocId(scope_result_id), name_id,\n            access_kind, is_parent_access, *access_info);\n      }\n    }\n\n    CARBON_CHECK(!result.scope_result.is_poisoned());\n    return {.specific_id = SemIR::SpecificId::None,\n            .scope_result = SemIR::ScopeLookupResult::MakeError()};\n  }\n\n  return result;\n}\n\n// Returns a `Core.<qualifiers>` name for diagnostics.\nstatic auto GetCoreQualifiedName(llvm::ArrayRef<CoreIdentifier> qualifiers)\n    -> std::string {\n  RawStringOstream str;\n  str << \"Core\";\n  for (auto qualifier : qualifiers) {\n    str << \".\" << qualifier;\n  }\n  return str.TakeStr();\n}\n\n// Returns the scope of the Core package, or `None` if it's not found.\n//\n// TODO: Consider tracking the Core package in SemIR so we don't need to use\n// name lookup to find it.\nstatic auto GetCorePackage(Context& context, SemIR::LocId loc_id,\n                           llvm::ArrayRef<CoreIdentifier> qualifiers)\n    -> SemIR::NameScopeId {\n  if (context.name_scopes().IsCorePackage(SemIR::NameScopeId::Package)) {\n    return SemIR::NameScopeId::Package;\n  }\n\n  // Look up `package.Core`.\n  auto core_scope_result = LookupNameInExactScope(\n      context, loc_id, SemIR::NameId::Core, SemIR::NameScopeId::Package,\n      context.name_scopes().Get(SemIR::NameScopeId::Package));\n  if (core_scope_result.is_found()) {\n    // We expect it to be a namespace.\n    if (auto namespace_inst = context.insts().TryGetAs<SemIR::Namespace>(\n            core_scope_result.target_inst_id())) {\n      // TODO: Decide whether to allow the case where `Core` is not a package.\n      return namespace_inst->name_scope_id;\n    }\n  }\n\n  CARBON_DIAGNOSTIC(\n      CoreNotFound, Error,\n      \"`{0}` implicitly referenced here, but package `Core` not found\",\n      std::string);\n  context.emitter().Emit(loc_id, CoreNotFound,\n                         GetCoreQualifiedName(qualifiers));\n  return SemIR::NameScopeId::None;\n}\n\nauto LookupNameInCore(Context& context, SemIR::LocId loc_id,\n                      llvm::ArrayRef<CoreIdentifier> qualifiers)\n    -> SemIR::InstId {\n  CARBON_CHECK(!qualifiers.empty());\n\n  auto core_package_id = GetCorePackage(context, loc_id, qualifiers);\n  if (!core_package_id.has_value()) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  auto inst_id = SemIR::InstId::None;\n  for (auto qualifier : qualifiers) {\n    auto name_id = context.core_identifiers().AddNameId(qualifier);\n\n    auto scope_id = SemIR::NameScopeId::None;\n    if (inst_id.has_value()) {\n      auto namespace_inst = context.insts().TryGetAs<SemIR::Namespace>(inst_id);\n      if (namespace_inst) {\n        scope_id = namespace_inst->name_scope_id;\n      }\n    } else {\n      scope_id = core_package_id;\n    }\n\n    auto scope_result =\n        scope_id.has_value()\n            ? LookupNameInExactScope(context, loc_id, name_id, scope_id,\n                                     context.name_scopes().Get(scope_id))\n            : SemIR::ScopeLookupResult::MakeNotFound();\n    if (!scope_result.is_found()) {\n      CARBON_DIAGNOSTIC(CoreNameNotFound, Error,\n                        \"name `{0}` implicitly referenced here, but not found\",\n                        std::string);\n      context.emitter().Emit(loc_id, CoreNameNotFound,\n                             GetCoreQualifiedName(qualifiers));\n      return SemIR::ErrorInst::InstId;\n    }\n\n    // Look through import_refs and aliases.\n    inst_id = context.constant_values().GetConstantInstId(\n        scope_result.target_inst_id());\n  }\n\n  return inst_id;\n}\n\nauto DiagnoseDuplicateName(Context& context, SemIR::NameId name_id,\n                           SemIR::LocId dup_def, SemIR::LocId prev_def)\n    -> void {\n  CARBON_DIAGNOSTIC(NameDeclDuplicate, Error,\n                    \"duplicate name `{0}` being declared in the same scope\",\n                    SemIR::NameId);\n  CARBON_DIAGNOSTIC(NameDeclPrevious, Note, \"name is previously declared here\");\n  context.emitter()\n      .Build(dup_def, NameDeclDuplicate, name_id)\n      .Note(prev_def, NameDeclPrevious)\n      .Emit();\n}\n\nauto DiagnosePoisonedName(Context& context, SemIR::NameId name_id,\n                          SemIR::LocId poisoning_loc_id,\n                          SemIR::LocId decl_name_loc_id) -> void {\n  CARBON_CHECK(poisoning_loc_id.has_value(),\n               \"Trying to diagnose poisoned name with no poisoning location\");\n  CARBON_DIAGNOSTIC(NameUseBeforeDecl, Error,\n                    \"name `{0}` used before it was declared\", SemIR::NameId);\n  CARBON_DIAGNOSTIC(NameUseBeforeDeclNote, Note, \"declared here\");\n  context.emitter()\n      .Build(poisoning_loc_id, NameUseBeforeDecl, name_id)\n      .Note(decl_name_loc_id, NameUseBeforeDeclNote)\n      .Emit();\n}\n\nauto DiagnoseNameNotFound(Context& context, SemIR::LocId loc_id,\n                          SemIR::NameId name_id) -> void {\n  CARBON_DIAGNOSTIC(NameNotFound, Error, \"name `{0}` not found\", SemIR::NameId);\n  context.emitter().Emit(loc_id, NameNotFound, name_id);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/name_lookup.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_NAME_LOOKUP_H_\n#define CARBON_TOOLCHAIN_CHECK_NAME_LOOKUP_H_\n\n#include \"llvm/ADT/ArrayRef.h\"\n#include \"llvm/ADT/StringRef.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Information about a scope in which we can perform name lookup.\nstruct LookupScope {\n  // The name scope in which names are searched.\n  SemIR::NameScopeId name_scope_id;\n  // The specific for the name scope, or `None` if the name scope is not\n  // defined by a generic or we should perform lookup into the generic itself.\n  SemIR::SpecificId specific_id;\n  // The self-type where lookup is happening when the lookup is for a member\n  // access.\n  SemIR::ConstantId self_const_id;\n};\n\n// A result produced by name lookup.\nstruct LookupResult {\n  // The specific in which the lookup result was found. `None` if the result\n  // was not found in a specific.\n  SemIR::SpecificId specific_id;\n\n  // The result from the lookup in the scope.\n  SemIR::ScopeLookupResult scope_result;\n};\n\n// Information about an access.\nstruct AccessInfo {\n  // The constant being accessed.\n  SemIR::ConstantId constant_id;\n\n  // The highest allowed access for a lookup. For example, `Protected` allows\n  // access to `Public` and `Protected` names, but not `Private`.\n  SemIR::AccessKind highest_allowed_access;\n};\n\n// Adds a name to name lookup. Prints a diagnostic for name conflicts. If\n// specified, `scope_index` specifies which lexical scope the name is inserted\n// into, otherwise the name is inserted into the current scope.\nauto AddNameToLookup(Context& context, SemIR::NameId name_id,\n                     SemIR::InstId target_id,\n                     ScopeIndex scope_index = ScopeIndex::None) -> void;\n\n// Performs name lookup in a specified scope for a name appearing in a\n// declaration. If scope_id is `None`, performs lookup into the lexical scope\n// specified by scope_index instead.\nauto LookupNameInDecl(Context& context, SemIR::LocId loc_id,\n                      SemIR::NameId name_id, SemIR::NameScopeId scope_id,\n                      ScopeIndex scope_index) -> SemIR::ScopeLookupResult;\n\n// Performs an unqualified name lookup, returning the referenced `InstId`.\nauto LookupUnqualifiedName(Context& context, SemIR::LocId loc_id,\n                           SemIR::NameId name_id, bool required = true)\n    -> LookupResult;\n\n// Performs a name lookup in a specified scope, returning the referenced\n// `InstId`. Does not look into extended scopes. Returns `InstId::None` if the\n// name is not found.\n//\n// If `is_being_declared` is false, then this is a regular name lookup, and\n// the name will be poisoned if not found so that later lookups will fail; a\n// poisoned name will be treated as if it is not declared. Otherwise, this is\n// a lookup for a name being declared, so the name will not be poisoned, but\n// poison will be returned if it's already been looked up.\n//\n// If `name_id` is not an identifier, the name will not be poisoned.\nauto LookupNameInExactScope(Context& context, SemIR::LocId loc_id,\n                            SemIR::NameId name_id, SemIR::NameScopeId scope_id,\n                            SemIR::NameScope& scope,\n                            bool is_being_declared = false)\n    -> SemIR::ScopeLookupResult;\n\n// Appends the lookup scopes corresponding to `lookup_const_id` to `*scopes`.\n//\n// The `self_type_const_id` is the self-type that we are looking for a name in,\n// and which is passed through to extended scopes. It may be a facet or a value\n// of type `type`. Some extended scopes have a symbolic `Self` internally which\n// needs to know the self-type in order to produce a correct specific scope in\n// the result.\n//\n// Returns `false` if not a scope. On invalid scopes, prints a diagnostic, but\n// still updates `*scopes` and returns `true`.\nauto AppendLookupScopesForConstant(Context& context, SemIR::LocId loc_id,\n                                   SemIR::ConstantId lookup_const_id,\n                                   SemIR::ConstantId self_type_const_id,\n                                   llvm::SmallVector<LookupScope>* scopes)\n    -> bool;\n\n// Performs a qualified name lookup in a specified scopes and in scopes that\n// they extend, returning the referenced `InstId`.\nauto LookupQualifiedName(Context& context, SemIR::LocId loc_id,\n                         SemIR::NameId name_id,\n                         llvm::ArrayRef<LookupScope> lookup_scopes,\n                         bool required = true,\n                         std::optional<AccessInfo> access_info = std::nullopt)\n    -> LookupResult;\n\n// Returns the `InstId` corresponding to a qualified name in the `Core` package,\n// or BuiltinErrorInst if not found.\nauto LookupNameInCore(Context& context, SemIR::LocId loc_id,\n                      llvm::ArrayRef<CoreIdentifier> qualifiers)\n    -> SemIR::InstId;\n\n// Returns the `InstId` corresponding to a name in the `Core`, or\n// BuiltinErrorInst if not found.\ninline auto LookupNameInCore(Context& context, SemIR::LocId loc_id,\n                             CoreIdentifier identifier) -> SemIR::InstId {\n  return LookupNameInCore(context, loc_id, llvm::ArrayRef{identifier});\n}\n\n// Checks whether a name is accessible in the given access context. Produces a\n// diagnostic if not.\nauto CheckAccess(Context& context, SemIR::LocId loc_id,\n                 SemIR::LocId member_loc_id, SemIR::NameId name_id,\n                 SemIR::AccessKind access_kind, bool is_parent_access,\n                 AccessInfo access_info) -> void;\n\n// Prints a diagnostic for a duplicate name.\nauto DiagnoseDuplicateName(Context& context, SemIR::NameId name_id,\n                           SemIR::LocId dup_def, SemIR::LocId prev_def) -> void;\n\n// Prints a diagnostic for a poisoned name when it's later declared.\nauto DiagnosePoisonedName(Context& context, SemIR::NameId name_id,\n                          SemIR::LocId poisoning_loc_id,\n                          SemIR::LocId decl_name_loc_id) -> void;\n\n// Prints a diagnostic for a missing name.\nauto DiagnoseNameNotFound(Context& context, SemIR::LocId loc_id,\n                          SemIR::NameId name_id) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_NAME_LOOKUP_H_\n"
  },
  {
    "path": "toolchain/check/name_ref.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/name_ref.h\"\n\n#include \"toolchain/check/inst.h\"\n\nnamespace Carbon::Check {\n\nauto BuildNameRef(Context& context, SemIR::LocId loc_id, SemIR::NameId name_id,\n                  SemIR::InstId inst_id, SemIR::SpecificId specific_id)\n    -> SemIR::InstId {\n  auto type_id =\n      SemIR::GetTypeOfInstInSpecific(context.sem_ir(), specific_id, inst_id);\n  CARBON_CHECK(type_id.has_value(), \"Missing type for {0}\",\n               context.insts().Get(inst_id));\n\n  // If the named entity has a constant value that depends on its specific,\n  // store the specific too.\n  if (specific_id.has_value() &&\n      context.constant_values().Get(inst_id).is_symbolic()) {\n    inst_id = AddInst<SemIR::SpecificConstant>(\n        context, loc_id,\n        {.type_id = type_id, .inst_id = inst_id, .specific_id = specific_id});\n  }\n\n  return AddInst<SemIR::NameRef>(\n      context, loc_id,\n      {.type_id = type_id, .name_id = name_id, .value_id = inst_id});\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/name_ref.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_NAME_REF_H_\n#define CARBON_TOOLCHAIN_CHECK_NAME_REF_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Builds a reference to the given name, which has already been resolved to\n// `inst_id` within `specific_id`.\nauto BuildNameRef(Context& context, SemIR::LocId loc_id, SemIR::NameId name_id,\n                  SemIR::InstId inst_id, SemIR::SpecificId specific_id)\n    -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_NAME_REF_H_\n"
  },
  {
    "path": "toolchain/check/name_scope.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/name_scope.h\"\n\nnamespace Carbon::Check {\n\nauto TryAsClassScope(Context& context, SemIR::NameScopeId scope_id)\n    -> std::optional<ClassScope> {\n  if (!scope_id.has_value()) {\n    return std::nullopt;\n  }\n  auto& scope = context.name_scopes().Get(scope_id);\n  if (!scope.inst_id().has_value()) {\n    return std::nullopt;\n  }\n  auto class_decl = context.insts().TryGetAs<SemIR::ClassDecl>(scope.inst_id());\n  if (!class_decl) {\n    return std::nullopt;\n  }\n  return {{.class_decl = *class_decl, .name_scope = &scope}};\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/name_scope.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_NAME_SCOPE_H_\n#define CARBON_TOOLCHAIN_CHECK_NAME_SCOPE_H_\n\n#include <optional>\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nstruct ClassScope {\n  SemIR::ClassDecl class_decl;\n  SemIR::NameScope* name_scope;\n};\n\n// If the specified name scope corresponds to a class, returns the corresponding\n// class declaration.\nauto TryAsClassScope(Context& context, SemIR::NameScopeId scope_id)\n    -> std::optional<ClassScope>;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_NAME_SCOPE_H_\n"
  },
  {
    "path": "toolchain/check/node_id_traversal.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/node_id_traversal.h\"\n\n#include <optional>\n#include <utility>\n#include <variant>\n\n#include \"toolchain/check/deferred_definition_worklist.h\"\n#include \"toolchain/check/handle.h\"\n#include \"toolchain/check/thunk.h\"\n\nnamespace Carbon::Check {\n\nNodeIdTraversal::NodeIdTraversal(Context* context)\n    : context_(context),\n      next_deferred_definition_(&context->parse_tree()),\n      worklist_(&context->deferred_definition_worklist()) {\n  auto range = context->parse_tree().postorder();\n  chunks_.push_back({.it = range.begin(),\n                     .end = range.end(),\n                     .next_definition = Parse::DeferredDefinitionIndex::None});\n}\n\nauto NodeIdTraversal::Next() -> std::optional<Parse::NodeId> {\n  while (true) {\n    // If we're checking deferred definitions, find the next definition we\n    // should check, restore its suspended state, and add a corresponding\n    // `Chunk` to the top of the chunk list.\n    if (chunks_.back().checking_deferred_definitions) {\n      if (chunks_.back().next_worklist_index < worklist().size()) {\n        std::visit([&](auto& task) { PerformTask(std::move(task)); },\n                   worklist()[chunks_.back().next_worklist_index++]);\n        continue;\n      }\n\n      // Worklist is empty: discard the worklist items associated with this\n      // chunk, and leave the scope.\n      worklist().truncate(chunks_.back().first_worklist_index);\n      // We reach here when\n      // `DeferredDefinitionScope::SuspendFinishedScopeAndPush` returns\n      // `NonNestedWithWork`. In this case it's our responsibility to pop the\n      // scope left behind by the `Handle*Definition` function for the\n      // non-nested definition.\n      context_->decl_name_stack().PopScope();\n      chunks_.back().checking_deferred_definitions = false;\n    }\n\n    // If we're not checking deferred definitions, produce the next parse node\n    // for this chunk. If we've run out of parse nodes, we're done with this\n    // chunk of the parse tree.\n    if (chunks_.back().it == chunks_.back().end) {\n      auto old_chunk = chunks_.pop_back_val();\n\n      // If we're out of chunks, then we're done entirely.\n      if (chunks_.empty()) {\n        worklist().VerifyEmpty();\n        return std::nullopt;\n      }\n\n      next_deferred_definition_.SkipTo(old_chunk.next_definition);\n      continue;\n    }\n\n    auto node_id = *chunks_.back().it;\n\n    // If we've reached the start of a deferred definition, skip to the end of\n    // it, and track that we need to check it later.\n    if (node_id == next_deferred_definition_.start_id()) {\n      const auto& definition_info =\n          context_->parse_tree().deferred_definitions().Get(\n              next_deferred_definition_.index());\n      worklist().SuspendFunctionAndPush(next_deferred_definition_.index(), [&] {\n        return HandleFunctionDefinitionSuspend(*context_,\n                                               definition_info.start_id);\n      });\n\n      // Continue type-checking the parse tree after the end of the definition.\n      chunks_.back().it =\n          Parse::Tree::PostorderIterator(definition_info.definition_id) + 1;\n      next_deferred_definition_.SkipTo(definition_info.next_definition_index);\n      continue;\n    }\n\n    ++chunks_.back().it;\n    return node_id;\n  }\n}\n\n// Determines whether this node kind is the start of a deferred definition\n// scope.\nstatic auto IsStartOfDeferredDefinitionScope(Parse::NodeKind kind) -> bool {\n  switch (kind) {\n    case Parse::NodeKind::ClassDefinitionStart:\n    case Parse::NodeKind::ImplDefinitionStart:\n    case Parse::NodeKind::InterfaceDefinitionStart:\n    case Parse::NodeKind::NamedConstraintDefinitionStart:\n      // TODO: Mixins.\n      return true;\n    default:\n      return false;\n  }\n}\n\n// Determines whether this node kind is the end of a deferred definition scope.\nstatic auto IsEndOfDeferredDefinitionScope(Parse::NodeKind kind) -> bool {\n  switch (kind) {\n    case Parse::NodeKind::ClassDefinition:\n    case Parse::NodeKind::ImplDefinition:\n    case Parse::NodeKind::InterfaceDefinition:\n    case Parse::NodeKind::NamedConstraintDefinition:\n      // TODO: Mixins.\n      return true;\n    default:\n      return false;\n  }\n}\n\n// TODO: Investigate factoring out `IsStartOfDeferredDefinitionScope` and\n// `IsEndOfDeferredDefinitionScope` in order to make `NodeIdTraversal`\n// reusable.\nauto NodeIdTraversal::Handle(Parse::NodeKind parse_kind) -> void {\n  // When we reach the start of a deferred definition scope, add a task to the\n  // worklist to check future skipped definitions in the new context.\n  if (IsStartOfDeferredDefinitionScope(parse_kind)) {\n    worklist().PushEnterDeferredDefinitionScope(*context_);\n  }\n\n  // When we reach the end of a deferred definition scope, add a task to the\n  // worklist to leave the scope. If this is not a nested scope, start\n  // checking the deferred definitions now.\n  if (IsEndOfDeferredDefinitionScope(parse_kind)) {\n    auto scope_kind = worklist().SuspendFinishedScopeAndPush(*context_);\n\n    // If we have deferred tasks in this scope, perform them next.\n    if (scope_kind ==\n        DeferredDefinitionWorklist::FinishedScopeKind::NonNestedWithWork) {\n      chunks_.back().checking_deferred_definitions = true;\n      chunks_.back().next_worklist_index = chunks_.back().first_worklist_index;\n    }\n  }\n}\n\nauto NodeIdTraversal::PerformTask(\n    DeferredDefinitionWorklist::EnterNestedDeferredDefinitionScope&& enter)\n    -> void {\n  CARBON_CHECK(enter.suspended_name,\n               \"Entering a scope with no suspension information.\");\n  context_->decl_name_stack().Restore(std::move(*enter.suspended_name));\n}\n\nauto NodeIdTraversal::PerformTask(\n    DeferredDefinitionWorklist::LeaveNestedDeferredDefinitionScope&& /*leave*/)\n    -> void {\n  context_->decl_name_stack().PopScope();\n}\n\nauto NodeIdTraversal::PerformTask(\n    DeferredDefinitionWorklist::CheckSkippedDefinition&& parse_definition)\n    -> void {\n  auto& [definition_index, suspended_fn] = parse_definition;\n  const auto& definition_info =\n      context_->parse_tree().deferred_definitions().Get(definition_index);\n  HandleFunctionDefinitionResume(*context_, definition_info.start_id,\n                                 std::move(suspended_fn));\n  auto range = Parse::Tree::PostorderIterator::MakeRange(\n      definition_info.start_id, definition_info.definition_id);\n  chunks_.push_back({.it = range.begin() + 1,\n                     .end = range.end(),\n                     .next_definition = next_deferred_definition_.index(),\n                     .checking_deferred_definitions = false,\n                     .first_worklist_index = worklist().size(),\n                     .next_worklist_index = worklist().size()});\n  ++definition_index.index;\n  next_deferred_definition_.SkipTo(definition_index);\n}\n\nauto NodeIdTraversal::PerformTask(\n    DeferredDefinitionWorklist::DefineThunk&& define_thunk) -> void {\n  BuildThunkDefinition(*context_, std::move(define_thunk));\n}\n\nNodeIdTraversal::NextDeferredDefinitionCache::NextDeferredDefinitionCache(\n    const Parse::Tree* tree)\n    : tree_(tree) {\n  SkipTo(Parse::DeferredDefinitionIndex(0));\n}\n\n// Set the specified deferred definition index as being the next one that\n// will be encountered.\nauto NodeIdTraversal::NextDeferredDefinitionCache::SkipTo(\n    Parse::DeferredDefinitionIndex next_index) -> void {\n  index_ = next_index;\n  if (static_cast<size_t>(index_.index) ==\n      tree_->deferred_definitions().size()) {\n    start_id_ = Parse::NodeId::None;\n  } else {\n    start_id_ = tree_->deferred_definitions().Get(index_).start_id;\n  }\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/node_id_traversal.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_NODE_ID_TRAVERSAL_H_\n#define CARBON_TOOLCHAIN_CHECK_NODE_ID_TRAVERSAL_H_\n\n#include \"common/ostream.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/deferred_definition_worklist.h\"\n#include \"toolchain/parse/tree.h\"\n\nnamespace Carbon::Check {\n\n// A traversal of the node IDs in the parse tree, in the order in which we need\n// to check them.\nclass NodeIdTraversal {\n public:\n  // `context` must not be null.\n  explicit NodeIdTraversal(Context* context);\n\n  // Finds the next `NodeId` to type-check. Returns nullopt if the traversal is\n  // complete.\n  auto Next() -> std::optional<Parse::NodeId>;\n\n  // Performs any processing necessary after we type-check a node.\n  auto Handle(Parse::NodeKind parse_kind) -> void;\n\n private:\n  // State used to track the next deferred function definition that we will\n  // encounter and need to reorder.\n  class NextDeferredDefinitionCache {\n   public:\n    explicit NextDeferredDefinitionCache(const Parse::Tree* tree);\n\n    // Set the specified deferred definition index as being the next one that\n    // will be encountered.\n    auto SkipTo(Parse::DeferredDefinitionIndex next_index) -> void;\n\n    // Returns the index of the next deferred definition to be encountered.\n    auto index() const -> Parse::DeferredDefinitionIndex { return index_; }\n\n    // Returns the ID of the start node of the next deferred definition.\n    auto start_id() const -> Parse::NodeId { return start_id_; }\n\n   private:\n    const Parse::Tree* tree_;\n    Parse::DeferredDefinitionIndex index_ =\n        Parse::DeferredDefinitionIndex::None;\n    Parse::NodeId start_id_ = Parse::NodeId::None;\n  };\n\n  // A chunk of the parse tree that we need to type-check.\n  struct Chunk {\n    Parse::Tree::PostorderIterator it;\n    Parse::Tree::PostorderIterator end;\n    // The next definition that will be encountered after this chunk completes.\n    Parse::DeferredDefinitionIndex next_definition;\n    // Whether we are currently checking deferred definitions, rather than the\n    // tokens of this chunk. If so, we'll pull tasks off `worklist` and execute\n    // them until we're done with this batch of deferred definitions. Otherwise,\n    // we'll pull node IDs from `*it` until it reaches `end`.\n    bool checking_deferred_definitions = false;\n    // If we're checking deferred definitions, the index of the first task to\n    // execute from `worklist`.\n    size_t first_worklist_index;\n    // If we're checking deferred definitions, the index of the next task to\n    // execute from `worklist`.\n    size_t next_worklist_index;\n  };\n\n  auto worklist() -> DeferredDefinitionWorklist& { return *worklist_; }\n\n  // Re-enter a nested deferred definition scope.\n  auto PerformTask(\n      DeferredDefinitionWorklist::EnterNestedDeferredDefinitionScope&& enter)\n      -> void;\n\n  // Leave a nested deferred definition scope.\n  auto PerformTask(\n      DeferredDefinitionWorklist::LeaveNestedDeferredDefinitionScope&& leave)\n      -> void;\n\n  // Resume checking a deferred definition.\n  auto PerformTask(\n      DeferredDefinitionWorklist::CheckSkippedDefinition&& parse_definition)\n      -> void;\n\n  // Define a thunk.\n  auto PerformTask(DeferredDefinitionWorklist::DefineThunk&& define_thunk)\n      -> void;\n\n  Context* context_;\n  NextDeferredDefinitionCache next_deferred_definition_;\n  DeferredDefinitionWorklist* worklist_;\n  llvm::SmallVector<Chunk> chunks_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_NODE_ID_TRAVERSAL_H_\n"
  },
  {
    "path": "toolchain/check/node_stack.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/node_stack.h\"\n\n#include \"llvm/ADT/STLExtras.h\"\n\nnamespace Carbon::Check {\n\nauto NodeStack::PrintForStackDump(int indent, llvm::raw_ostream& output) const\n    -> void {\n  auto print_id = [&]<Id::Kind Kind>(Id id) {\n    if constexpr (Kind == Id::Kind::None) {\n      output << \"no value\";\n    } else if constexpr (Kind == Id::Kind::Invalid) {\n      CARBON_FATAL(\"Should not be in node stack\");\n    } else {\n      output << id.As<Kind>();\n    }\n  };\n\n  output.indent(indent);\n  output << \"NodeStack:\\n\";\n  for (auto [i, entry] : llvm::enumerate(stack_)) {\n    auto node_kind = parse_tree_->node_kind(entry.node_id);\n    output.indent(indent + 2);\n    output << i << \". \" << node_kind << \": \";\n    switch (node_kind) {\n#define CARBON_PARSE_NODE_KIND(Kind)                                        \\\n  case Parse::NodeKind::Kind:                                               \\\n    print_id.operator()<NodeKindToIdKind(Parse::NodeKind::Kind)>(entry.id); \\\n    break;\n#include \"toolchain/parse/node_kind.def\"\n    }\n    output << \"\\n\";\n  }\n}\n\nauto NodeStack::CheckIdKindTable() -> void {\n#define CARBON_PARSE_NODE_KIND(Name)                                     \\\n  {                                                                      \\\n    constexpr auto from_category =                                       \\\n        NodeCategoryToIdKind(Parse::Name::Kind.category(), true);        \\\n    constexpr auto from_kind =                                           \\\n        NodeKindToIdKindSpecialCases(Parse::Name::Kind);                 \\\n    static_assert(from_category || from_kind,                            \\\n                  \"Id::Kind not specified for \" #Name                    \\\n                  \"; add to NodeStack::NodeKindToIdKindSpecialCases or \" \\\n                  \"specify a node category in typed_nodes.h\");           \\\n    static_assert(!from_category || !from_kind,                          \\\n                  \"Special case Id::Kind specified for \" #Name           \\\n                  \", but node category has an Id::Kind; remove from \"    \\\n                  \"NodeStack::NodeKindToIdKindSpecialCases\");            \\\n  }\n#include \"toolchain/parse/node_kind.def\"\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/node_stack.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_NODE_STACK_H_\n#define CARBON_TOOLCHAIN_CHECK_NODE_STACK_H_\n\n#include \"common/vlog.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/parse/node_kind.h\"\n#include \"toolchain/parse/tree.h\"\n#include \"toolchain/parse/typed_nodes.h\"\n#include \"toolchain/sem_ir/id_kind.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// A non-discriminated union of ID types.\nclass IdUnion {\n public:\n  // The default constructor forms a `None` ID.\n  explicit constexpr IdUnion() : index(AnyIdBase::NoneIndex) {}\n\n  template <typename IdT>\n    requires SemIR::IdKind::Contains<IdT>\n  explicit constexpr IdUnion(IdT id) : index(id.index) {}\n\n  using Kind = SemIR::IdKind::RawEnumType;\n\n  // Returns the ID given its type.\n  template <typename IdT>\n    requires SemIR::IdKind::Contains<IdT>\n  constexpr auto As() const -> IdT {\n    return IdT(index);\n  }\n\n  // Returns the ID given its kind.\n  template <SemIR::IdKind::RawEnumType K>\n  constexpr auto As() const -> SemIR::IdKind::TypeFor<K> {\n    return As<SemIR::IdKind::TypeFor<K>>();\n  }\n\n  // Translates an ID type to the enum ID kind. Returns `None` if `IdT` isn't\n  // a type that can be stored in this union.\n  template <typename IdT>\n  static constexpr auto KindFor() -> Kind {\n    return SemIR::IdKind::For<IdT>;\n  }\n\n private:\n  decltype(AnyIdBase::index) index;\n};\n\n// The stack of parse nodes representing the current state of a Check::Context.\n// Each parse node can have an associated id of some kind (instruction,\n// instruction block, function, class, ...).\n//\n// All pushes and pops will be vlogged.\n//\n// Pop APIs will run basic verification:\n//\n// - If receiving a Parse::NodeKind, verify that the node_id being popped has\n//   that kind. Similarly, if receiving a Parse::NodeCategory, make sure the\n//   of the popped node_id overlaps that category.\n// - Validates the kind of id data in the node based on the kind or category of\n//   the node_id.\n//\n// These should be assumed API constraints unless otherwise mentioned on a\n// method. The main exception is PopAndIgnore, which doesn't do verification.\nclass NodeStack {\n public:\n  explicit NodeStack(const Parse::Tree& parse_tree,\n                     llvm::raw_ostream* vlog_stream)\n      : parse_tree_(&parse_tree), vlog_stream_(vlog_stream) {}\n\n  // Pushes a solo parse tree node onto the stack. Used when there is no\n  // IR generated by the node.\n  auto Push(Parse::NodeId node_id) -> void {\n    auto kind = parse_tree_->node_kind(node_id);\n    CARBON_CHECK(NodeKindToIdKind(kind) == Id::Kind::None,\n                 \"Parse kind expects an Id: {0}\", kind);\n    CARBON_VLOG(\"Node Push {0}: {1} -> <none>\\n\", stack_.size(), kind);\n    CARBON_CHECK(stack_.size() < (1 << 20),\n                 \"Excessive stack size: likely infinite loop\");\n    stack_.push_back({.node_id = node_id, .id = Id()});\n  }\n\n  // Pushes a parse tree node onto the stack with an ID.\n  template <typename IdT>\n  auto Push(Parse::NodeId node_id, IdT id) -> void {\n    auto kind = parse_tree_->node_kind(node_id);\n    CARBON_CHECK(NodeKindToIdKind(kind) == Id::KindFor<IdT>(),\n                 \"Parse kind expected a different IdT: {0} -> {1}\\n\", kind, id);\n    CARBON_CHECK(id.has_value(), \"Push called with `None` id: {0}\",\n                 parse_tree_->node_kind(node_id));\n    CARBON_VLOG(\"Node Push {0}: {1} -> {2}\\n\", stack_.size(), kind, id);\n    CARBON_CHECK(stack_.size() < (1 << 20),\n                 \"Excessive stack size: likely infinite loop\");\n    stack_.push_back({.node_id = node_id, .id = Id(id)});\n  }\n\n  // TODO: Most parse nodes don't know about TypeInstId, so downgrade TypeInstId\n  // to InstId to match expectations. We should teach parse nodes that will\n  // receive a TypeInstId to expect it, and this function can go away.\n  auto Push(Parse::NodeId node_id, SemIR::TypeInstId id) -> void {\n    auto kind = parse_tree_->node_kind(node_id);\n    if (NodeKindToIdKind(kind) == Id::KindFor<SemIR::InstId>()) {\n      Push<SemIR::InstId>(node_id, id);\n    } else {\n      Push<SemIR::TypeInstId>(node_id, id);\n    }\n  }\n\n  // Returns whether there is a node of the specified kind on top of the stack.\n  auto PeekIs(Parse::NodeKind kind) const -> bool {\n    return !stack_.empty() && PeekNodeKind() == kind;\n  }\n\n  // Returns whether the node on the top of the stack has an overlapping\n  // category.\n  auto PeekIs(Parse::NodeCategory category) const -> bool {\n    return !stack_.empty() && PeekNodeKind().category().HasAnyOf(category);\n  }\n\n  // Returns whether there is a node with the corresponding ID on top of the\n  // stack.\n  template <typename IdT>\n  auto PeekIs() const -> bool {\n    return !stack_.empty() &&\n           NodeKindToIdKind(PeekNodeKind()) == Id::KindFor<IdT>();\n  }\n\n  // Returns whether the *next* node on the stack is a given kind. This doesn't\n  // have the breadth of support versus other Peek functions because it's\n  // expected to be used in narrow circumstances when determining how to treat\n  // the *current* top of the stack.\n  auto PeekNextIs(Parse::NodeKind kind) const -> bool {\n    CARBON_CHECK(stack_.size() >= 2);\n    return parse_tree_->node_kind(stack_[stack_.size() - 2].node_id) == kind;\n  }\n\n  // Pops the top of the stack without any verification.\n  auto PopAndIgnore() -> void {\n    Entry back = stack_.pop_back_val();\n    CARBON_VLOG(\"Node Pop {0}: {1} -> <ignored>\\n\", stack_.size(),\n                parse_tree_->node_kind(back.node_id));\n  }\n\n  // Pops the top of the stack and returns the node_id.\n  template <const Parse::NodeKind& RequiredParseKind>\n  auto PopForSoloNodeId() -> Parse::NodeIdForKind<RequiredParseKind> {\n    Entry back = PopEntry<SemIR::InstId>();\n    RequireIdKind(RequiredParseKind, Id::Kind::None);\n    return parse_tree_->As<Parse::NodeIdForKind<RequiredParseKind>>(\n        back.node_id);\n  }\n\n  // Pops the top of the stack if it is the given kind, and returns the\n  // node_id. Otherwise, returns std::nullopt.\n  template <const Parse::NodeKind& RequiredParseKind>\n  auto PopForSoloNodeIdIf()\n      -> std::optional<Parse::NodeIdForKind<RequiredParseKind>> {\n    if (PeekIs(RequiredParseKind)) {\n      return PopForSoloNodeId<RequiredParseKind>();\n    }\n    return std::nullopt;\n  }\n\n  // Pops the top of the stack.\n  template <const Parse::NodeKind& RequiredParseKind>\n  auto PopAndDiscardSoloNodeId() -> void {\n    PopForSoloNodeId<RequiredParseKind>();\n  }\n\n  // Pops the top of the stack if it is the given kind. Returns `true` if a node\n  // was popped.\n  template <const Parse::NodeKind& RequiredParseKind>\n  auto PopAndDiscardSoloNodeIdIf() -> bool {\n    if (!PeekIs(RequiredParseKind)) {\n      return false;\n    }\n    PopForSoloNodeId<RequiredParseKind>();\n    return true;\n  }\n\n  // Pops an expression from the top of the stack and returns the node_id and\n  // the ID.\n  auto PopExprWithNodeId() -> std::pair<Parse::AnyExprId, SemIR::InstId>;\n\n  // Pops a pattern from the top of the stack and returns the node_id and\n  // the ID.\n  auto PopPatternWithNodeId() -> std::pair<Parse::NodeId, SemIR::InstId> {\n    return PopWithNodeId<SemIR::InstId>();\n  }\n\n  // Pops a name from the top of the stack and returns the node_id and\n  // the ID.\n  auto PopNameWithNodeId() -> std::pair<Parse::NodeId, SemIR::NameId> {\n    return PopWithNodeId<SemIR::NameId>();\n  }\n\n  // Pops the top of the stack and returns the node_id and the ID.\n  template <const Parse::NodeKind& RequiredParseKind>\n  auto PopWithNodeId() -> auto {\n    auto id = Peek<RequiredParseKind>();\n    auto node_id = parse_tree_->As<Parse::NodeIdForKind<RequiredParseKind>>(\n        stack_.pop_back_val().node_id);\n    return std::make_pair(node_id, id);\n  }\n\n  // Pops the top of the stack and returns the node_id and the ID.\n  template <Parse::NodeCategory::RawEnumType RequiredParseCategory>\n  auto PopWithNodeId() -> auto {\n    auto id = Peek<RequiredParseCategory>();\n    auto node_id =\n        parse_tree_->As<Parse::NodeIdInCategory<RequiredParseCategory>>(\n            stack_.pop_back_val().node_id);\n    return std::make_pair(node_id, id);\n  }\n\n  // Pops an expression from the top of the stack and returns the ID.\n  // Expressions always map Parse::NodeCategory::Expr nodes to SemIR::InstId.\n  auto PopExpr() -> SemIR::InstId { return PopExprWithNodeId().second; }\n\n  // Pops a pattern from the top of the stack and returns the ID.\n  // Patterns map multiple Parse::NodeKinds to SemIR::InstId always.\n  // TODO: TuplePatterns store an InstBlockId instead and must be dealt with as\n  // a special case before calling this function.\n  auto PopPattern() -> SemIR::InstId { return PopPatternWithNodeId().second; }\n\n  // Pops a name from the top of the stack and returns the ID.\n  auto PopName() -> SemIR::NameId { return PopNameWithNodeId().second; }\n\n  // Pops the top of the stack and returns the ID.\n  template <const Parse::NodeKind& RequiredParseKind>\n  auto Pop() -> auto {\n    return PopWithNodeId<RequiredParseKind>().second;\n  }\n\n  // Pops the top of the stack and returns the ID.\n  template <Parse::NodeCategory::RawEnumType RequiredParseCategory>\n  auto Pop() -> auto {\n    return PopWithNodeId<RequiredParseCategory>().second;\n  }\n\n  // Pops the top of the stack and returns the ID.\n  template <typename IdT>\n  auto Pop() -> IdT {\n    return PopWithNodeId<IdT>().second;\n  }\n\n  // Pops the top of the stack if it has the given kind, and returns the ID.\n  // Otherwise returns std::nullopt.\n  template <const Parse::NodeKind& RequiredParseKind>\n  auto PopIf() -> std::optional<decltype(Pop<RequiredParseKind>())> {\n    if (PeekIs(RequiredParseKind)) {\n      return Pop<RequiredParseKind>();\n    }\n    return std::nullopt;\n  }\n\n  // Pops the top of the stack if it has the given category, and returns the ID.\n  // Otherwise returns std::nullopt.\n  template <Parse::NodeCategory::RawEnumType RequiredParseCategory>\n  auto PopIf() -> std::optional<decltype(Pop<RequiredParseCategory>())> {\n    if (PeekIs(RequiredParseCategory)) {\n      return Pop<RequiredParseCategory>();\n    }\n    return std::nullopt;\n  }\n\n  // Pops the top of the stack if it has the given category, and returns the ID.\n  // Otherwise returns std::nullopt.\n  template <typename IdT>\n  auto PopIf() -> std::optional<IdT> {\n    if (PeekIs<IdT>()) {\n      return Pop<IdT>();\n    }\n    return std::nullopt;\n  }\n\n  // Pops the top of the stack and returns the node_id and the ID if it is\n  // of the specified kind.\n  template <const Parse::NodeKind& RequiredParseKind>\n  auto PopWithNodeIdIf() -> std::pair<Parse::NodeIdForKind<RequiredParseKind>,\n                                      decltype(PopIf<RequiredParseKind>())> {\n    if (!PeekIs(RequiredParseKind)) {\n      return {Parse::NodeId::None, std::nullopt};\n    }\n    return PopWithNodeId<RequiredParseKind>();\n  }\n\n  // Pops the top of the stack and returns the node_id and the ID if it is\n  // of the specified category.\n  template <Parse::NodeCategory::RawEnumType RequiredParseCategory>\n  auto PopWithNodeIdIf()\n      -> std::pair<Parse::NodeIdInCategory<RequiredParseCategory>,\n                   decltype(PopIf<RequiredParseCategory>())> {\n    if (!PeekIs(RequiredParseCategory)) {\n      return {Parse::NodeId::None, std::nullopt};\n    }\n    return PopWithNodeId<RequiredParseCategory>();\n  }\n\n  // Peeks at the parse node of the top of the node stack.\n  auto PeekNodeId() const -> Parse::NodeId { return stack_.back().node_id; }\n\n  // Peeks at the kind of the parse node of the top of the node stack.\n  auto PeekNodeKind() const -> Parse::NodeKind {\n    return parse_tree_->node_kind(PeekNodeId());\n  }\n\n  // Peeks at the ID associated with the top of the name stack.\n  template <const Parse::NodeKind& RequiredParseKind>\n  auto Peek() const -> auto {\n    Entry back = stack_.back();\n    CARBON_CHECK(RequiredParseKind == parse_tree_->node_kind(back.node_id),\n                 \"Expected {0}, found {1}\", RequiredParseKind,\n                 parse_tree_->node_kind(back.node_id));\n    constexpr Id::Kind RequiredIdKind = NodeKindToIdKind(RequiredParseKind);\n    return Peek<RequiredIdKind>();\n  }\n\n  // Peeks at the ID associated with the top of the name stack.\n  template <Parse::NodeCategory::RawEnumType RequiredParseCategory>\n  auto Peek() const -> auto {\n    Entry back = stack_.back();\n    RequireParseCategory<RequiredParseCategory>(back.node_id);\n    constexpr std::optional<Id::Kind> RequiredIdKind =\n        NodeCategoryToIdKind(RequiredParseCategory, false);\n    static_assert(RequiredIdKind.has_value());\n    return Peek<*RequiredIdKind>();\n  }\n\n  // Peeks at the ID associated with the pattern at the top of the stack.\n  // Patterns map multiple Parse::NodeKinds to SemIR::InstId always.\n  // TODO: TuplePatterns store an InstBlockId instead and must be dealt with as\n  // a special case before calling this function.\n  auto PeekPattern() const -> SemIR::InstId;\n\n  // Prints the stack for a stack dump.\n  auto PrintForStackDump(int indent, llvm::raw_ostream& output) const -> void;\n\n  auto empty() const -> bool { return stack_.empty(); }\n  auto size() const -> size_t { return stack_.size(); }\n\n private:\n  // An ID that can be associated with a parse node.\n  //\n  // Each parse node kind has a corresponding Id::Kind indicating which kind of\n  // ID is stored, computed by NodeKindToIdKind. Id::Kind::None indicates\n  // that the parse node has no associated ID, in which case the *SoloNodeId\n  // functions should be used to push and pop it. Id::Kind::Invalid indicates\n  // that the parse node should not appear in the node stack at all.\n  using Id = IdUnion;\n\n  // An entry in stack_.\n  struct Entry {\n    // The parse node associated with the stack entry.\n    Parse::NodeId node_id;\n\n    // The ID associated with this parse node. The kind of ID is determined by\n    // the kind of the parse node, so a separate discriminiator is not needed.\n    Id id;\n  };\n  static_assert(sizeof(Entry) == 8, \"Unexpected Entry size\");\n\n  // Translate a parse node category to the enum ID kind it should always\n  // provide, if it is consistent.\n  static constexpr auto NodeCategoryToIdKind(Parse::NodeCategory category,\n                                             bool for_node_kind)\n      -> std::optional<Id::Kind> {\n    std::optional<Id::Kind> result;\n    auto set_id_if_category_is = [&](Parse::NodeCategory cat, Id::Kind kind) {\n      if (category.HasAnyOf(cat)) {\n        // Check for no consistent Id::Kind due to category with multiple bits\n        // set. When computing the Id::Kind for a node kind, a partial category\n        // match is OK, so long as we don't match two inconsistent categories.\n        // When computing the Id::Kind for a category query, the query can't\n        // have any extra bits set or we could be popping a node that is not in\n        // this category.\n        if (for_node_kind ? result.has_value() : category.HasAnyOf(~cat)) {\n          result = Id::Kind::Invalid;\n        } else {\n          result = kind;\n        }\n      }\n    };\n\n    set_id_if_category_is(Parse::NodeCategory::Pattern,\n                          Id::KindFor<SemIR::InstId>());\n    set_id_if_category_is(Parse::NodeCategory::Expr,\n                          Id::KindFor<SemIR::InstId>());\n    set_id_if_category_is(\n        Parse::NodeCategory::MemberName | Parse::NodeCategory::NonExprName,\n        Id::KindFor<SemIR::NameId>());\n    set_id_if_category_is(Parse::NodeCategory::ImplAs,\n                          Id::KindFor<SemIR::TypeInstId>());\n    set_id_if_category_is(Parse::NodeCategory::RequireImpls,\n                          Id::KindFor<SemIR::TypeInstId>());\n    set_id_if_category_is(Parse::NodeCategory::Decl |\n                              Parse::NodeCategory::Statement |\n                              Parse::NodeCategory::Modifier,\n                          Id::Kind::None);\n    set_id_if_category_is(Parse::NodeCategory::ReturnDecl,\n                          Id::KindFor<SemIR::InstBlockId>());\n    return result;\n  }\n\n  // Translate a parse node kind to the enum ID kind it should always\n  // provide, for the cases where this is not known from the category.\n  static constexpr auto NodeKindToIdKindSpecialCases(Parse::NodeKind node_kind)\n      -> std::optional<Id::Kind> {\n    switch (node_kind) {\n      case Parse::NodeKind::CallExprStart:\n      case Parse::NodeKind::FieldNameAndType:\n      case Parse::NodeKind::IfExprThen:\n      case Parse::NodeKind::RequireIntroducer:\n      case Parse::NodeKind::ShortCircuitOperandAnd:\n      case Parse::NodeKind::ShortCircuitOperandOr:\n      case Parse::NodeKind::StructLiteralField:\n      case Parse::NodeKind::WhereOperand:\n        return Id::KindFor<SemIR::InstId>();\n      case Parse::NodeKind::ExplicitParamList:\n      case Parse::NodeKind::ForIn:\n      case Parse::NodeKind::IfCondition:\n      case Parse::NodeKind::IfExprIf:\n      case Parse::NodeKind::ImplicitParamList:\n      case Parse::NodeKind::WhileConditionStart:\n        return Id::KindFor<SemIR::InstBlockId>();\n      case Parse::NodeKind::FunctionDefinitionStart:\n      case Parse::NodeKind::BuiltinFunctionDefinitionStart:\n        return Id::KindFor<SemIR::FunctionId>();\n      case Parse::NodeKind::ChoiceDefinitionStart:\n        // TODO: Should we have a separate SemIR::ChoiceId?\n      case Parse::NodeKind::ClassDefinitionStart:\n        return Id::KindFor<SemIR::ClassId>();\n      case Parse::NodeKind::InterfaceDefinitionStart:\n        return Id::KindFor<SemIR::InterfaceId>();\n      case Parse::NodeKind::ImplDefinitionStart:\n        return Id::KindFor<SemIR::ImplId>();\n      case Parse::NodeKind::NamedConstraintDefinitionStart:\n        return Id::KindFor<SemIR::NamedConstraintId>();\n      case Parse::NodeKind::SelfTypeName:\n      case Parse::NodeKind::SelfValueName:\n        return Id::KindFor<SemIR::NameId>();\n      case Parse::NodeKind::DefaultLibrary:\n      case Parse::NodeKind::LibraryName:\n        return Id::KindFor<SemIR::LibraryNameId>();\n      case Parse::NodeKind::AssociatedConstantInitializer:\n      case Parse::NodeKind::AssociatedConstantIntroducer:\n      case Parse::NodeKind::BuiltinName:\n      case Parse::NodeKind::ChoiceIntroducer:\n      case Parse::NodeKind::ClassIntroducer:\n      case Parse::NodeKind::CodeBlockStart:\n      case Parse::NodeKind::ExplicitParamListStart:\n      case Parse::NodeKind::FieldInitializer:\n      case Parse::NodeKind::FieldIntroducer:\n      case Parse::NodeKind::ForHeaderStart:\n      case Parse::NodeKind::FunctionIntroducer:\n      case Parse::NodeKind::IfStatementElse:\n      case Parse::NodeKind::ImplicitParamListStart:\n      case Parse::NodeKind::ImplIntroducer:\n      case Parse::NodeKind::InterfaceIntroducer:\n      case Parse::NodeKind::LambdaIntroducer:\n      case Parse::NodeKind::LetInitializer:\n      case Parse::NodeKind::LetIntroducer:\n      case Parse::NodeKind::NamedConstraintIntroducer:\n      case Parse::NodeKind::ObserveIntroducer:\n      case Parse::NodeKind::RefBindingName:\n      case Parse::NodeKind::ReturnStatementStart:\n      case Parse::NodeKind::StructLiteralStart:\n      case Parse::NodeKind::StructTypeLiteralField:\n      case Parse::NodeKind::StructTypeLiteralStart:\n      case Parse::NodeKind::TemplateBindingName:\n      case Parse::NodeKind::TupleLiteralStart:\n      case Parse::NodeKind::TuplePatternStart:\n      case Parse::NodeKind::VariableInitializer:\n      case Parse::NodeKind::VariableIntroducer:\n        return Id::Kind::None;\n      case Parse::NodeKind::AdaptIntroducer:\n      case Parse::NodeKind::AliasInitializer:\n      case Parse::NodeKind::AliasIntroducer:\n      case Parse::NodeKind::ArrayExprComma:\n      case Parse::NodeKind::ArrayExprKeyword:\n      case Parse::NodeKind::ArrayExprOpenParen:\n      case Parse::NodeKind::BaseColon:\n      case Parse::NodeKind::BaseIntroducer:\n      case Parse::NodeKind::BreakStatementStart:\n      case Parse::NodeKind::ChoiceAlternativeListComma:\n      case Parse::NodeKind::CodeBlock:\n      case Parse::NodeKind::CompileTimeBindingPatternStart:\n      case Parse::NodeKind::ContinueStatementStart:\n      case Parse::NodeKind::CorePackageName:\n      case Parse::NodeKind::CppPackageName:\n      case Parse::NodeKind::ExportIntroducer:\n      case Parse::NodeKind::FileEnd:\n      case Parse::NodeKind::FileStart:\n      case Parse::NodeKind::ForHeader:\n      case Parse::NodeKind::Forall:\n      case Parse::NodeKind::FormLiteralKeyword:\n      case Parse::NodeKind::FormLiteralOpenParen:\n      case Parse::NodeKind::IdentifierNameQualifierWithParams:\n      case Parse::NodeKind::IdentifierNameQualifierWithoutParams:\n      case Parse::NodeKind::IdentifierPackageName:\n      case Parse::NodeKind::IfConditionStart:\n      case Parse::NodeKind::ImportIntroducer:\n      case Parse::NodeKind::IndexExprStart:\n      case Parse::NodeKind::InvalidParseStart:\n      case Parse::NodeKind::LibraryIntroducer:\n      case Parse::NodeKind::LibrarySpecifier:\n      case Parse::NodeKind::InlineImportSpecifier:\n      case Parse::NodeKind::InlineImportBody:\n      case Parse::NodeKind::MatchCase:\n      case Parse::NodeKind::MatchCaseGuard:\n      case Parse::NodeKind::MatchCaseGuardIntroducer:\n      case Parse::NodeKind::MatchCaseGuardStart:\n      case Parse::NodeKind::MatchCaseIntroducer:\n      case Parse::NodeKind::MatchCondition:\n      case Parse::NodeKind::MatchConditionStart:\n      case Parse::NodeKind::MatchDefault:\n      case Parse::NodeKind::MatchDefaultIntroducer:\n      case Parse::NodeKind::MatchHandlerStart:\n      case Parse::NodeKind::MatchHandler:\n      case Parse::NodeKind::MatchIntroducer:\n      case Parse::NodeKind::MatchStatementStart:\n      case Parse::NodeKind::NamespaceStart:\n      case Parse::NodeKind::ObserveEqualEqual:\n      case Parse::NodeKind::ObserveImpls:\n      case Parse::NodeKind::PackageIntroducer:\n      case Parse::NodeKind::ParenExprStart:\n      case Parse::NodeKind::PatternListComma:\n      case Parse::NodeKind::Placeholder:\n      case Parse::NodeKind::RequirementAnd:\n      case Parse::NodeKind::RequirementEqual:\n      case Parse::NodeKind::RequirementEqualEqual:\n      case Parse::NodeKind::RequirementImpls:\n      case Parse::NodeKind::StructLiteralComma:\n      case Parse::NodeKind::StructFieldDesignator:\n      case Parse::NodeKind::StructTypeLiteralComma:\n      case Parse::NodeKind::TerseBodyArrow:\n      case Parse::NodeKind::TupleLiteralComma:\n      case Parse::NodeKind::WhileCondition:\n        return Id::Kind::Invalid;\n      default:\n        // In this case, the kind must be determinable from the category, or we\n        // will produce a build error.\n        return std::nullopt;\n    }\n  }\n\n  using IdKindTableType = std::array<Id::Kind, Parse::NodeKind::ValidCount>;\n\n  // Lookup table to implement `NodeKindToIdKind`. Initialized to the\n  // return value of `ComputeIdKindTable()`.\n  static const IdKindTableType IdKindTable;\n\n  static consteval auto ComputeIdKindTable() -> IdKindTableType {\n    IdKindTableType table = {};\n\n    auto to_id_kind =\n        [](const Parse::NodeKind::Definition& node_kind) -> Id::Kind {\n      if (auto from_category =\n              NodeCategoryToIdKind(node_kind.category(), true)) {\n        return *from_category;\n      }\n      // Assume any node kind that doesn't have an ID kind from its category nor\n      // a special case can't appear on the stack just so we can build a table\n      // and avoid follow-on errors. We'll enforce at compile time that a value\n      // is actually specified in CheckIdKindTable.\n      return NodeKindToIdKindSpecialCases(node_kind).value_or(\n          Id::Kind::Invalid);\n    };\n\n#define CARBON_PARSE_NODE_KIND(Name) \\\n  table[Parse::Name::Kind.AsInt()] = to_id_kind(Parse::Name::Kind);\n#include \"toolchain/parse/node_kind.def\"\n\n    return table;\n  }\n\n  // Check that an Id::Kind is specified for every node kind.\n  static auto CheckIdKindTable() -> void;\n\n  // Translate a parse node kind to the enum ID kind it should always provide.\n  static constexpr auto NodeKindToIdKind(Parse::NodeKind kind) -> Id::Kind {\n    return IdKindTable[kind.AsInt()];\n  }\n\n  // Peeks at the ID associated with the top of the name stack.\n  template <Id::Kind RequiredIdKind>\n  auto Peek() const -> auto {\n    Id id = stack_.back().id;\n    return id.As<RequiredIdKind>();\n  }\n\n  // Pops an entry.\n  template <typename IdT>\n  auto PopEntry() -> Entry {\n    Entry back = stack_.pop_back_val();\n    CARBON_VLOG(\"Node Pop {0}: {1} -> {2}\\n\", stack_.size(),\n                parse_tree_->node_kind(back.node_id),\n                back.id.template As<IdT>());\n    return back;\n  }\n\n  // Pops the top of the stack and returns the node_id and the ID.\n  template <typename IdT>\n  auto PopWithNodeId() -> std::pair<Parse::NodeId, IdT> {\n    Entry back = PopEntry<IdT>();\n    RequireIdKind(parse_tree_->node_kind(back.node_id), Id::KindFor<IdT>());\n    return {back.node_id, back.id.template As<IdT>()};\n  }\n\n  // Require a Parse::NodeKind be mapped to a particular Id::Kind.\n  auto RequireIdKind(Parse::NodeKind parse_kind, Id::Kind id_kind) const\n      -> void {\n    CARBON_CHECK(NodeKindToIdKind(parse_kind) == id_kind,\n                 \"Unexpected Id::Kind mapping for {0}: expected {1}, found {2}\",\n                 parse_kind, SemIR::IdKind(id_kind),\n                 SemIR::IdKind(NodeKindToIdKind(parse_kind)));\n  }\n\n  // Require an entry to have the given Parse::NodeCategory.\n  template <Parse::NodeCategory::RawEnumType RequiredParseCategory>\n  auto RequireParseCategory(Parse::NodeId node_id) const -> void {\n    auto kind = parse_tree_->node_kind(node_id);\n    CARBON_CHECK(kind.category().HasAnyOf(RequiredParseCategory),\n                 \"Expected {0}, found {1} with category {2}\",\n                 RequiredParseCategory, kind, kind.category());\n  }\n\n  // The file's parse tree.\n  const Parse::Tree* parse_tree_;\n\n  // Whether to print verbose output.\n  llvm::raw_ostream* vlog_stream_;\n\n  // The actual stack.\n  // PushEntry and PopEntry control modification in order to centralize\n  // vlogging.\n  llvm::SmallVector<Entry> stack_;\n};\n\ninline constexpr NodeStack::IdKindTableType NodeStack::IdKindTable =\n    ComputeIdKindTable();\n\ninline auto NodeStack::PopExprWithNodeId()\n    -> std::pair<Parse::AnyExprId, SemIR::InstId> {\n  return PopWithNodeId<Parse::NodeCategory::Expr>();\n}\n\ninline auto NodeStack::PeekPattern() const -> SemIR::InstId {\n  return Peek<Id::KindFor<SemIR::InstId>()>();\n}\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_NODE_STACK_H_\n"
  },
  {
    "path": "toolchain/check/operator.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/operator.h\"\n\n#include <optional>\n\n#include \"toolchain/check/call.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/cpp/call.h\"\n#include \"toolchain/check/cpp/operators.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/member_access.h\"\n#include \"toolchain/check/name_lookup.h\"\n#include \"toolchain/sem_ir/class.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/name_scope.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\n// Returns the `Op` function for the specified operator.\nstatic auto GetOperatorOpFunction(Context& context, SemIR::LocId loc_id,\n                                  Operator op) -> SemIR::InstId {\n  auto implicit_loc_id = context.insts().GetLocIdForDesugaring(loc_id);\n\n  // Look up the interface, and pass it any generic arguments.\n  // TODO: Improve diagnostics when the found `interface_id` isn't callable.\n  auto interface_id =\n      LookupNameInCore(context, implicit_loc_id, op.interface_name);\n  if (!op.interface_args_ref.empty()) {\n    interface_id = PerformCall(context, implicit_loc_id, interface_id,\n                               op.interface_args_ref);\n  }\n\n  // Look up the interface member.\n  auto op_name_id = context.core_identifiers().AddNameId(op.op_name);\n  return PerformMemberAccess(context, implicit_loc_id, interface_id,\n                             op_name_id);\n}\n\n// Returns whether the instruction is a C++ class type. Assumes the argument is\n// in canonical form and does not look through the constant value.\nstatic auto IsCppClassType(Context& context, SemIR::InstId inst_id) -> bool {\n  auto class_type = context.insts().TryGetAs<SemIR::ClassType>(inst_id);\n  if (!class_type) {\n    // Not a class.\n    return false;\n  }\n\n  SemIR::NameScopeId class_scope_id =\n      context.classes().Get(class_type->class_id).scope_id;\n  return class_scope_id.has_value() &&\n         context.name_scopes().Get(class_scope_id).is_cpp_scope();\n}\n\n// Returns whether the instruction is a value of C++ class type.\nstatic auto HasCppClassType(Context& context, SemIR::InstId inst_id) -> bool {\n  return IsCppClassType(context, context.types().GetTypeInstId(\n                                     context.insts().Get(inst_id).type_id()));\n}\n\nauto BuildUnaryOperator(Context& context, SemIR::LocId loc_id, Operator op,\n                        SemIR::InstId operand_id, bool diagnose,\n                        DiagnosticContextFn missing_impl_diagnostic_context)\n    -> SemIR::InstId {\n  if (operand_id == SemIR::ErrorInst::InstId) {\n    // Exit early for errors, which prevent forming an `Op` function.\n    return SemIR::ErrorInst::InstId;\n  }\n\n  SemIR::InstId op_fn_id = SemIR::InstId::None;\n\n  // For unary operators with a C++ class as the operand, try to import and call\n  // the C++ operator.\n  // TODO: Change impl lookup instead. See\n  // https://github.com/carbon-language/carbon-lang/blob/db0a00d713015436844c55e7ac190a0f95556499/toolchain/check/operator.cpp#L76\n  if (HasCppClassType(context, operand_id) ||\n      llvm::any_of(op.interface_args_ref, [&](SemIR::InstId arg_id) {\n        return IsCppClassType(context, arg_id);\n      })) {\n    op_fn_id = LookupCppOperator(context, loc_id, op, {operand_id});\n\n    // If C++ operator lookup found a non-method operator, call it with one call\n    // argument. Otherwise fall through to call it with a self argument.\n    if (op_fn_id.has_value() && !IsCppOperatorMethod(context, op_fn_id)) {\n      return PerformCall(context, loc_id, op_fn_id, {operand_id},\n                         /*is_operator_syntax=*/true);\n    }\n  }\n\n  if (!op_fn_id.has_value()) {\n    // Look up the operator function.\n    op_fn_id = GetOperatorOpFunction(context, loc_id, op);\n  }\n\n  // Form `operand.(Op)`.\n  auto bound_op_id =\n      PerformCompoundMemberAccess(context, loc_id, operand_id, op_fn_id,\n                                  diagnose, missing_impl_diagnostic_context);\n  if (bound_op_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // Form `bound_op()`.\n  return PerformCall(context, loc_id, bound_op_id, {},\n                     /*is_operator_syntax=*/true);\n}\n\nauto BuildBinaryOperator(Context& context, SemIR::LocId loc_id, Operator op,\n                         SemIR::InstId lhs_id, SemIR::InstId rhs_id,\n                         bool diagnose,\n                         DiagnosticContextFn missing_impl_diagnostic_context)\n    -> SemIR::InstId {\n  if (lhs_id == SemIR::ErrorInst::InstId) {\n    // Exit early for errors, which prevent forming an `Op` function.\n    return SemIR::ErrorInst::InstId;\n  }\n\n  SemIR::InstId op_fn_id = SemIR::InstId::None;\n\n  // For binary operators with a C++ class as at least one of the operands, try\n  // to import and call the C++ operator.\n  // TODO: Instead of hooking this here, change impl lookup, so that a generic\n  // constraint such as `T:! Core.Add` is satisfied by C++ class types that are\n  // addable. See\n  // https://github.com/carbon-language/carbon-lang/pull/5996/files/5d01fa69511b76f87efbc0387f5e40abcf4c911a#r2308666348\n  // and\n  // https://github.com/carbon-language/carbon-lang/pull/5996/files/5d01fa69511b76f87efbc0387f5e40abcf4c911a#r2308664536\n  if (HasCppClassType(context, lhs_id) || HasCppClassType(context, rhs_id) ||\n      llvm::any_of(op.interface_args_ref, [&](SemIR::InstId arg_id) {\n        return IsCppClassType(context, arg_id);\n      })) {\n    op_fn_id = LookupCppOperator(context, loc_id, op, {lhs_id, rhs_id});\n\n    // If C++ operator lookup found a non-method operator, call it with two call\n    // arguments. Otherwise fall through to call it with a self argument and one\n    // call argument.\n    if (op_fn_id.has_value() && !IsCppOperatorMethod(context, op_fn_id)) {\n      return PerformCall(context, loc_id, op_fn_id, {lhs_id, rhs_id},\n                         /*is_operator_syntax=*/true);\n    }\n  }\n\n  if (!op_fn_id.has_value()) {\n    // Look up the operator function.\n    op_fn_id = GetOperatorOpFunction(context, loc_id, op);\n  }\n\n  // Form `lhs.(Op)`.\n  auto bound_op_id =\n      PerformCompoundMemberAccess(context, loc_id, lhs_id, op_fn_id, diagnose,\n                                  missing_impl_diagnostic_context);\n  if (bound_op_id == SemIR::ErrorInst::InstId) {\n    return SemIR::ErrorInst::InstId;\n  }\n\n  // Form `bound_op(rhs)`.\n  return PerformCall(context, loc_id, bound_op_id, {rhs_id},\n                     /*is_operator_syntax=*/true);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/operator.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_OPERATOR_H_\n#define CARBON_TOOLCHAIN_CHECK_OPERATOR_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/core_identifier.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nstruct Operator {\n  CoreIdentifier interface_name;\n  llvm::ArrayRef<SemIR::InstId> interface_args_ref = {};\n  CoreIdentifier op_name = CoreIdentifier::Op;\n};\n\n// Checks and builds SemIR for a unary operator expression. For example,\n// `*operand` or `operand*`.\n//\n// On failure, an ErrorInst is returned and a diagnostic is produced unless\n// `diagnose` is false. It is incorrect to specify `diagnose` as false if the\n// resulting ErrorInst may appear in the produced SemIR.\n//\n// If specified, `missing_impl_diagnostic_context` is used to provide context\n// for the diagnostic if the impl lookup for the operator fails.\nauto BuildUnaryOperator(Context& context, SemIR::LocId loc_id, Operator op,\n                        SemIR::InstId operand_id, bool diagnose = true,\n                        DiagnosticContextFn missing_impl_diagnostic_context =\n                            nullptr) -> SemIR::InstId;\n\n// Checks and builds SemIR for a binary operator expression. For example,\n// `lhs_id * rhs_id`.\n//\n// // On failure, an ErrorInst is returned and a diagnostic is produced unless\n// `diagnose` is false. It is incorrect to specify `diagnose` as false if the\n// resulting ErrorInst may appear in the produced SemIR.\n//\n// If specified, `missing_impl_diagnostic_context` is used to provide context\n// for the diagnostic if the impl lookup for the operator fails.\nauto BuildBinaryOperator(\n    Context& context, SemIR::LocId loc_id, Operator op, SemIR::InstId lhs_id,\n    SemIR::InstId rhs_id, bool diagnose = true,\n    DiagnosticContextFn missing_impl_diagnostic_context = nullptr)\n    -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_OPERATOR_H_\n"
  },
  {
    "path": "toolchain/check/param_and_arg_refs_stack.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_PARAM_AND_ARG_REFS_STACK_H_\n#define CARBON_TOOLCHAIN_CHECK_PARAM_AND_ARG_REFS_STACK_H_\n\n#include \"common/check.h\"\n#include \"toolchain/check/inst_block_stack.h\"\n#include \"toolchain/check/node_stack.h\"\n\nnamespace Carbon::Check {\n\n// The stack of instruction blocks being used for per-element tracking of\n// instructions in parameter and argument instruction blocks. Versus\n// InstBlockStack, an element will have 1 or more instructions in blocks in\n// InstBlockStack, but only ever 1 instruction in blocks here. The result is\n// typically referred to as \"param_refs\" or \"arg_refs\".\nclass ParamAndArgRefsStack {\n public:\n  explicit ParamAndArgRefsStack(SemIR::File& sem_ir,\n                                llvm::raw_ostream* vlog_stream,\n                                NodeStack& node_stack)\n      : node_stack_(&node_stack),\n        stack_(\"param_and_arg_refs_stack\", sem_ir, vlog_stream) {}\n\n  // Starts handling parameters or arguments.\n  auto Push() -> void { stack_.Push(); }\n\n  // On a comma, pushes the most recent instruction, becoming param or arg ref.\n  // This also pops the NodeStack, meaning its top will remain start_kind.\n  auto ApplyComma() -> void {\n    // Support expressions, parameters, and other nodes like\n    // `StructLiteralField` that produce InstIds.\n    stack_.AddInstId(node_stack_->Pop<SemIR::InstId>());\n  }\n\n  // Detects whether there's an entry to push from the end of a parameter or\n  // argument list, and if so, moves it to the current parameter or argument\n  // list. Does not pop the list. `start_kind` is the node kind at the start\n  // of the parameter or argument list, and will be at the top of the parse node\n  // stack when this function returns.\n  auto EndNoPop(Parse::NodeKind start_kind) -> void {\n    if (!node_stack_->PeekIs(start_kind)) {\n      // Support expressions, parameters, and other nodes like\n      // `StructLiteralField` that produce InstIds.\n      stack_.AddInstId(node_stack_->Pop<SemIR::InstId>());\n    }\n  }\n\n  // Pops the current parameter or argument list. Should only be called after\n  // `EndNoPop`.\n  auto Pop() -> SemIR::InstBlockId { return stack_.Pop(); }\n\n  // Detects whether there's an entry to push. Pops and returns the argument\n  // list. This is the same as `EndNoPop` followed by `Pop`.\n  auto EndAndPop(Parse::NodeKind start_kind) -> SemIR::InstBlockId {\n    EndNoPop(start_kind);\n    return Pop();\n  }\n\n  // Pops the top instruction block, and discards it if it hasn't had an ID\n  // allocated.\n  auto PopAndDiscard() -> void { stack_.PopAndDiscard(); }\n\n  // Returns a view of the contents of the top instruction block on the stack.\n  auto PeekCurrentBlockContents() -> llvm::ArrayRef<SemIR::InstId> {\n    return stack_.PeekCurrentBlockContents();\n  }\n\n  // Runs verification that the processing cleanly finished.\n  auto VerifyOnFinish() const -> void { stack_.VerifyOnFinish(); }\n\n  // Prints the stack for a stack dump.\n  auto PrintForStackDump(int indent, llvm::raw_ostream& output) const -> void {\n    stack_.PrintForStackDump(indent, output);\n  }\n\n private:\n  // The node stack is manipulated when adding refs.\n  NodeStack* node_stack_;\n\n  // The refs stack.\n  InstBlockStack stack_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_PARAM_AND_ARG_REFS_STACK_H_\n"
  },
  {
    "path": "toolchain/check/pattern.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/pattern.h\"\n\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/check/return.h\"\n#include \"toolchain/check/type.h\"\n\nnamespace Carbon::Check {\n\nauto BeginSubpattern(Context& context) -> void {\n  context.inst_block_stack().Push();\n  context.region_stack().PushRegion(context.inst_block_stack().PeekOrAdd());\n}\n\nauto EndSubpatternAsExpr(Context& context, SemIR::InstId result_id)\n    -> SemIR::ExprRegionId {\n  if (context.region_stack().PeekRegion().size() > 1) {\n    // End the exit block with a branch to a successor block, whose contents\n    // will be determined later.\n    AddInst(context,\n            SemIR::LocIdAndInst::NoLoc<SemIR::Branch>(\n                {.target_id = context.inst_blocks().AddPlaceholder()}));\n  } else {\n    // This single-block region will be inserted as a SpliceBlock, so we don't\n    // need control flow out of it.\n  }\n  auto block_id = context.inst_block_stack().Pop();\n  CARBON_CHECK(block_id == context.region_stack().PeekRegion().back());\n\n  // TODO: Is it possible to validate that this region is genuinely\n  // single-entry, single-exit?\n  return context.sem_ir().expr_regions().Add(\n      {.block_ids = context.region_stack().PopRegion(),\n       .result_id = result_id});\n}\n\nauto EndSubpatternAsNonExpr(Context& context) -> void {\n  auto block_id = context.inst_block_stack().Pop();\n  CARBON_CHECK(block_id == context.region_stack().PeekRegion().back());\n  CARBON_CHECK(context.region_stack().PeekRegion().size() == 1);\n  CARBON_CHECK(context.inst_blocks().Get(block_id).empty());\n  context.region_stack().PopAndDiscardRegion();\n}\n\nauto AddBindingEntityName(Context& context, SemIR::NameId name_id,\n                          SemIR::ConstantId form_id, bool is_unused,\n                          BindingPhase phase) -> SemIR::EntityNameId {\n  SemIR::EntityName entity_name = {\n      .name_id = name_id,\n      .parent_scope_id = context.scope_stack().PeekNameScopeId(),\n      .is_unused = is_unused || name_id == SemIR::NameId::Underscore};\n  if (phase != BindingPhase::Runtime) {\n    entity_name.bind_index_value =\n        context.scope_stack().AddCompileTimeBinding().index;\n    entity_name.is_template = phase == BindingPhase::Template;\n  }\n  entity_name.form_id = form_id;\n  return context.entity_names().Add(entity_name);\n}\n\nauto AddBindingPattern(Context& context, SemIR::LocId name_loc,\n                       SemIR::ExprRegionId type_region_id,\n                       SemIR::AnyBindingPattern pattern) -> BindingPatternInfo {\n  SemIR::InstKind bind_name_kind;\n  switch (pattern.kind) {\n    case SemIR::InstKind::FormBindingPattern:\n      bind_name_kind = SemIR::InstKind::FormBinding;\n      break;\n    case SemIR::InstKind::RefBindingPattern:\n      bind_name_kind = SemIR::InstKind::RefBinding;\n      break;\n    case SemIR::InstKind::SymbolicBindingPattern:\n      bind_name_kind = SemIR::InstKind::SymbolicBinding;\n      break;\n    case SemIR::InstKind::ValueBindingPattern:\n      bind_name_kind = SemIR::InstKind::ValueBinding;\n      break;\n    default:\n      CARBON_FATAL(\"pattern_kind {0} is not a binding pattern kind\",\n                   pattern.kind);\n  }\n  auto type_id = SemIR::ExtractScrutineeType(context.sem_ir(), pattern.type_id);\n\n  auto bind_id = AddInstInNoBlock(\n      context,\n      SemIR::LocIdAndInst::UncheckedLoc(\n          name_loc, SemIR::AnyBinding{.kind = bind_name_kind,\n                                      .type_id = type_id,\n                                      .entity_name_id = pattern.entity_name_id,\n                                      .value_id = SemIR::InstId::None}));\n\n  auto binding_pattern_id = AddPatternInst(\n      context, SemIR::LocIdAndInst::UncheckedLoc(name_loc, pattern));\n\n  if (pattern.kind == SemIR::SymbolicBindingPattern::Kind) {\n    context.scope_stack().PushCompileTimeBinding(bind_id);\n  }\n\n  bool inserted =\n      context.bind_name_map()\n          .Insert(binding_pattern_id, {.bind_name_id = bind_id,\n                                       .type_expr_region_id = type_region_id})\n          .is_inserted();\n  CARBON_CHECK(inserted);\n  return {.pattern_id = binding_pattern_id, .bind_id = bind_id};\n}\n\n// Returns a VarStorage inst for the given `var` pattern. If the pattern\n// is the body of a returned var, this reuses the return parameter, and\n// otherwise it adds a new inst.\nstatic auto GetOrAddVarStorage(Context& context, SemIR::InstId var_pattern_id,\n                               bool is_returned_var) -> SemIR::InstId {\n  if (is_returned_var) {\n    if (auto return_param_id =\n            GetReturnedVarParam(context, GetCurrentFunctionForReturn(context));\n        return_param_id.has_value()) {\n      return return_param_id;\n    }\n  }\n  auto pattern = context.insts().GetWithLocId(var_pattern_id);\n\n  return AddInstWithCleanup(\n      context, pattern.loc_id,\n      SemIR::VarStorage{.type_id = ExtractScrutineeType(context.sem_ir(),\n                                                        pattern.inst.type_id()),\n                        .pattern_id = var_pattern_id});\n}\n\nauto AddPatternVarStorage(Context& context, SemIR::InstBlockId pattern_block_id,\n                          bool is_returned_var) -> void {\n  // We need to emit the VarStorage insts early, because they may be output\n  // arguments for the initializer. However, we can't emit them when we emit\n  // the corresponding `VarPattern`s because they're part of the pattern match,\n  // not part of the pattern.\n  // TODO: Find a way to do this without walking the whole pattern block.\n  for (auto inst_id : context.inst_blocks().Get(pattern_block_id)) {\n    if (context.insts().Is<SemIR::VarPattern>(inst_id)) {\n      context.var_storage_map().Insert(\n          inst_id, GetOrAddVarStorage(context, inst_id, is_returned_var));\n    }\n  }\n}\n\nauto AddParamPattern(Context& context, SemIR::LocId loc_id,\n                     SemIR::NameId name_id,\n                     SemIR::ExprRegionId type_expr_region_id,\n                     SemIR::TypeId type_id, bool is_ref) -> SemIR::InstId {\n  const auto& binding_pattern_kind = is_ref ? SemIR::RefBindingPattern::Kind\n                                            : SemIR::ValueBindingPattern::Kind;\n  auto entity_name_id =\n      AddBindingEntityName(context, name_id,\n                           /*form_id=*/SemIR::ConstantId::None,\n                           /*is_unused=*/false,\n                           /*phase=*/BindingPhase::Runtime);\n  SemIR::InstId pattern_id =\n      AddBindingPattern(context, loc_id, type_expr_region_id,\n                        {.kind = binding_pattern_kind,\n                         .type_id = GetPatternType(context, type_id),\n                         .entity_name_id = entity_name_id})\n          .pattern_id;\n\n  const auto& param_pattern_kind =\n      is_ref ? SemIR::RefParamPattern::Kind : SemIR::ValueParamPattern::Kind;\n  pattern_id = AddPatternInst(\n      context,\n      SemIR::LocIdAndInst::UncheckedLoc(\n          loc_id, SemIR::AnyParamPattern{\n                      .kind = param_pattern_kind,\n                      .type_id = context.insts().Get(pattern_id).type_id(),\n                      .subpattern_id = pattern_id,\n                      .form_id = SemIR::ConstantId::None}));\n\n  return pattern_id;\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/pattern.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_PATTERN_H_\n#define CARBON_TOOLCHAIN_CHECK_PATTERN_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Marks the start of a region of insts in a pattern context that might\n// represent an expression or a pattern. Typically this is called when\n// handling a parse node that can immediately precede a subpattern (such\n// as `let` or a `,` in a pattern list), and the handler for the subpattern\n// node makes the matching `EndSubpatternAs*` call.\nauto BeginSubpattern(Context& context) -> void;\n\n// Ends a region started by BeginSubpattern (in stack order), treating it as\n// an expression with the given result, and returns the ID of the region. The\n// region will not yet have any control-flow edges into or out of it.\nauto EndSubpatternAsExpr(Context& context, SemIR::InstId result_id)\n    -> SemIR::ExprRegionId;\n\n// Ends a region started by BeginSubpattern (in stack order), asserting that\n// it had no expression content.\nauto EndSubpatternAsNonExpr(Context& context) -> void;\n\n// Information about a created binding pattern.\nstruct BindingPatternInfo {\n  SemIR::InstId pattern_id;\n  SemIR::InstId bind_id;\n};\n\n// TODO: Add EndSubpatternAsPattern, when needed.\n\n// The phase of a binding pattern.\nenum class BindingPhase { Template, Symbolic, Runtime };\n\n// Creates an entity name for a binding pattern with the given properties.\nauto AddBindingEntityName(Context& context, SemIR::NameId name_id,\n                          SemIR::ConstantId form_id, bool is_unused,\n                          BindingPhase phase) -> SemIR::EntityNameId;\n\n// Creates a binding pattern and the associated binding inst, and returns their\n// IDs. `type_region_id` is the region representing the binding's type\n// expression.\nauto AddBindingPattern(Context& context, SemIR::LocId name_loc,\n                       SemIR::ExprRegionId type_region_id,\n                       SemIR::AnyBindingPattern pattern) -> BindingPatternInfo;\n\n// Creates storage for `var` patterns nested within the given pattern at the\n// current location in the output SemIR. For a `returned var`, this\n// reuses the function's return slot when present.\nauto AddPatternVarStorage(Context& context, SemIR::InstBlockId pattern_block_id,\n                          bool is_returned_var) -> void;\n\n// Adds a parameter pattern with the specified name and type information. The\n// pattern emulates `x: T` or `ref x: T` depending on the value of\n// `is_ref` (`var x: T` is not supported). This only sets up the parameter\n// pattern, binding pattern and type; callers are expected to add the returned\n// parameter pattern instruction to appropriate blocks. This is used when\n// generating functions, rather than processing a user-authored declaration.\nauto AddParamPattern(Context& context, SemIR::LocId loc_id,\n                     SemIR::NameId name_id,\n                     SemIR::ExprRegionId type_expr_region_id,\n                     SemIR::TypeId type_id, bool is_ref) -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_PATTERN_H_\n"
  },
  {
    "path": "toolchain/check/pattern_match.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/pattern_match.h\"\n\n#include <functional>\n#include <utility>\n#include <vector>\n\n#include \"llvm/ADT/STLExtras.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/pattern.h\"\n#include \"toolchain/check/type.h\"\n#include \"toolchain/diagnostics/format_providers.h\"\n#include \"toolchain/sem_ir/expr_info.h\"\n#include \"toolchain/sem_ir/pattern.h\"\n\nnamespace Carbon::Check {\n\nnamespace {\n\n// Selects between the different kinds of pattern matching.\nenum class MatchKind : uint8_t {\n  // Caller pattern matching occurs on the caller side of a function call, and\n  // is responsible for matching the argument expression against the portion\n  // of the pattern above the ParamPattern insts.\n  Caller,\n\n  // Callee pattern matching occurs in the function decl block, and is\n  // responsible for matching the function's calling-convention parameters\n  // against the portion of the pattern below the ParamPattern insts.\n  Callee,\n\n  // Local pattern matching is pattern matching outside of a function call,\n  // such as in a let/var declaration.\n  Local,\n};\n\n// The collected state of a pattern-matching operation.\nclass MatchContext {\n public:\n  struct WorkItem : Printable<WorkItem> {\n    SemIR::InstId pattern_id;\n    // `None` when processing the callee side.\n    SemIR::InstId scrutinee_id;\n\n    // If true, disables diagnostics that would otherwise require scrutinee_id\n    // to be tagged with `ref`. Only affects caller pattern matching.\n    bool allow_unmarked_ref = false;\n    auto Print(llvm::raw_ostream& out) const -> void {\n      out << \"{pattern_id: \" << pattern_id << \", scrutinee_id: \" << scrutinee_id\n          << \", allow_unmarked_ref = \" << allow_unmarked_ref << \"}\";\n    }\n  };\n\n  // Constructs a MatchContext. If `callee_specific_id` is not `None`, this\n  // pattern match operation is part of implementing the signature of the given\n  // specific.\n  explicit MatchContext(MatchKind kind, SemIR::SpecificId callee_specific_id =\n                                            SemIR::SpecificId::None)\n      : kind_(kind), callee_specific_id_(callee_specific_id) {}\n\n  // Adds a work item to the stack.\n  auto AddWork(WorkItem work_item) -> void { stack_.push_back(work_item); }\n\n  // Processes all work items on the stack.\n  auto DoWork(Context& context) -> void;\n\n  // Returns an inst block of references to all the emitted `Call` arguments.\n  // Can only be called once, at the end of Caller pattern matching.\n  auto CallerResults(Context& context) && -> SemIR::InstBlockId;\n\n  // Returns an inst block of references to all the emitted `Call` params,\n  // and an inst block of references to the `Call` param patterns they were\n  // emitted to match. Can only be called once, at the end of Callee pattern\n  // matching.\n  struct ParamsAndPatterns {\n    SemIR::InstBlockId call_param_patterns_id;\n    SemIR::InstBlockId call_params_id;\n  };\n  auto CalleeResults(Context& context) && -> ParamsAndPatterns;\n\n  // Returns the number of call parameters that have been emitted so far.\n  auto param_count() -> int { return call_params_.size(); }\n  ~MatchContext();\n\n private:\n  // Emits the pattern-match insts necessary to match the pattern inst\n  // `entry.pattern_id` against the scrutinee value `entry.scrutinee_id`, and\n  // adds to `stack_` any work necessary to traverse into its subpatterns. This\n  // behavior is contingent on the kind of match being performed, as indicated\n  // by kind_`. For example, when performing a callee pattern match, this does\n  // not emit insts for patterns on the caller side. However, it still traverses\n  // into subpatterns if any of their descendants might emit insts.\n  // TODO: Require that `entry.scrutinee_id` is valid if and only if insts\n  // should be emitted, once we start emitting `Param` insts in the\n  // `ParamPattern` case.\n  auto EmitPatternMatch(Context& context, MatchContext::WorkItem entry) -> void;\n\n  // Implementations of `EmitPatternMatch` for particular pattern inst kinds.\n  auto DoEmitPatternMatch(Context& context,\n                          SemIR::AnyBindingPattern binding_pattern,\n                          WorkItem entry) -> void;\n  auto DoEmitPatternMatch(Context& context,\n                          SemIR::AnyParamPattern param_pattern, WorkItem entry)\n      -> void;\n  auto DoEmitPatternMatch(Context& context,\n                          SemIR::ReturnSlotPattern return_slot_pattern,\n                          WorkItem entry) -> void;\n  auto DoEmitPatternMatch(Context& context, SemIR::VarPattern var_pattern,\n                          WorkItem entry) -> void;\n  auto DoEmitPatternMatch(Context& context, SemIR::TuplePattern tuple_pattern,\n                          WorkItem entry) -> void;\n\n  // Performs the core logic of matching a variable pattern whose type is\n  // `pattern_type_id`, but returns the scrutinee that its subpattern should be\n  // matched with, rather than pushing it onto the worklist. This is factored\n  // out so it can be reused when handling a `FormBindingPattern` or\n  // `FormParamPattern` with an initializing form.\n  auto DoEmitVarPatternMatchImpl(Context& context,\n                                 SemIR::TypeId pattern_type_id,\n                                 WorkItem entry) const -> SemIR::InstId;\n\n  // The stack of work to be processed.\n  llvm::SmallVector<WorkItem> stack_;\n\n  // The in-progress contents of the `Call` arguments block. This is populated\n  // only when kind_ is Caller.\n  llvm::SmallVector<SemIR::InstId> call_args_;\n\n  // The in-progress contents of the `Call` parameters block. This is populated\n  // only when kind_ is Callee.\n  llvm::SmallVector<SemIR::InstId> call_params_;\n\n  // The in-progress contents of the `Call` parameter patterns block. This is\n  // populated only when kind_ is Callee.\n  llvm::SmallVector<SemIR::InstId> call_param_patterns_;\n\n  // The kind of pattern match being performed.\n  MatchKind kind_;\n\n  // The SpecificId of the function being called (if any).\n  SemIR::SpecificId callee_specific_id_;\n};\n\n}  // namespace\n\nauto MatchContext::DoWork(Context& context) -> void {\n  while (!stack_.empty()) {\n    EmitPatternMatch(context, stack_.pop_back_val());\n  }\n}\n\nauto MatchContext::CallerResults(Context& context) && -> SemIR::InstBlockId {\n  CARBON_CHECK(kind_ == MatchKind::Caller);\n  auto block_id = context.inst_blocks().Add(call_args_);\n  call_args_.clear();\n  return block_id;\n}\n\nauto MatchContext::CalleeResults(Context& context) && -> ParamsAndPatterns {\n  CARBON_CHECK(kind_ == MatchKind::Callee);\n  CARBON_CHECK(call_params_.size() == call_param_patterns_.size());\n  auto call_param_patterns_id = context.inst_blocks().Add(call_param_patterns_);\n  call_param_patterns_.clear();\n  auto call_params_id = context.inst_blocks().Add(call_params_);\n  call_params_.clear();\n  return {.call_param_patterns_id = call_param_patterns_id,\n          .call_params_id = call_params_id};\n}\n\nMatchContext::~MatchContext() {\n  CARBON_CHECK(call_args_.empty() && call_params_.empty() &&\n                   call_param_patterns_.empty(),\n               \"Unhandled pattern matching outputs. call_args_.size(): {0}, \"\n               \"call_params_.size(): {1}, call_param_patterns_.size(): {2}\",\n               call_args_.size(), call_params_.size(),\n               call_param_patterns_.size());\n}\n\n// Inserts the given region into the current code block. If the region\n// consists of a single block, this will be implemented as a `splice_block`\n// inst. Otherwise, this will end the current block with a branch to the entry\n// block of the region, and add future insts to a new block which is the\n// immediate successor of the region's exit block. As a result, this cannot be\n// called more than once for the same region.\nstatic auto InsertHere(Context& context, SemIR::ExprRegionId region_id)\n    -> SemIR::InstId {\n  auto region = context.sem_ir().expr_regions().Get(region_id);\n  auto exit_block = context.inst_blocks().Get(region.block_ids.back());\n  if (region.block_ids.size() == 1) {\n    // TODO: Is it possible to avoid leaving an \"orphan\" block in the IR in the\n    // first two cases?\n    if (exit_block.empty()) {\n      return region.result_id;\n    }\n    if (exit_block.size() == 1) {\n      context.inst_block_stack().AddInstId(exit_block.front());\n      return region.result_id;\n    }\n    return AddInst<SemIR::SpliceBlock>(\n        context, SemIR::LocId(region.result_id),\n        {.type_id = context.insts().Get(region.result_id).type_id(),\n         .block_id = region.block_ids.front(),\n         .result_id = region.result_id});\n  }\n  if (context.region_stack().empty()) {\n    context.TODO(region.result_id,\n                 \"Control flow expressions are currently only supported inside \"\n                 \"functions.\");\n    return SemIR::ErrorInst::InstId;\n  }\n  AddInst(context, SemIR::LocIdAndInst::NoLoc<SemIR::Branch>(\n                       {.target_id = region.block_ids.front()}));\n  context.inst_block_stack().Pop();\n  // TODO: this will cumulatively cost O(MN) running time for M blocks\n  // at the Nth level of the stack. Figure out how to do better.\n  context.region_stack().AddToRegion(region.block_ids);\n  auto resume_with_block_id =\n      context.insts().GetAs<SemIR::Branch>(exit_block.back()).target_id;\n  CARBON_CHECK(context.inst_blocks().GetOrEmpty(resume_with_block_id).empty());\n  context.inst_block_stack().Push(resume_with_block_id);\n  context.region_stack().AddToRegion(resume_with_block_id,\n                                     SemIR::LocId(region.result_id));\n  return region.result_id;\n}\n\n// Returns the kind of conversion to perform on the scrutinee when matching the\n// given pattern.\nstatic auto ConversionKindFor(Context& context, SemIR::Inst pattern,\n                              MatchContext::WorkItem entry)\n    -> ConversionTarget::Kind {\n  CARBON_KIND_SWITCH(pattern) {\n    case SemIR::OutParamPattern::Kind:\n    case SemIR::VarParamPattern::Kind:\n      return ConversionTarget::NoOp;\n    case SemIR::RefBindingPattern::Kind:\n      return ConversionTarget::DurableRef;\n    case SemIR::RefParamPattern::Kind:\n      return entry.allow_unmarked_ref ? ConversionTarget::UnmarkedRefParam\n                                      : ConversionTarget::RefParam;\n    case SemIR::SymbolicBindingPattern::Kind:\n    case SemIR::ValueBindingPattern::Kind:\n    case SemIR::ValueParamPattern::Kind:\n      return ConversionTarget::Value;\n    case CARBON_KIND(SemIR::FormBindingPattern form_binding_pattern): {\n      auto form_id = context.entity_names()\n                         .Get(form_binding_pattern.entity_name_id)\n                         .form_id;\n      auto form_inst_id = context.constant_values().GetInstId(form_id);\n      auto form_inst = context.insts().Get(form_inst_id);\n\n      switch (form_inst.kind()) {\n        case SemIR::InitForm::Kind:\n          context.TODO(entry.pattern_id, \"Support local initializing forms\");\n          [[fallthrough]];\n        case SemIR::RefForm::Kind:\n          return ConversionTarget::DurableRef;\n        case SemIR::SymbolicBinding::Kind:\n          context.TODO(entry.pattern_id, \"Support symbolic form bindings\");\n          [[fallthrough]];\n        case SemIR::ValueForm::Kind:\n          return ConversionTarget::Value;\n        default:\n          CARBON_FATAL(\"Unexpected form {0}\", form_inst);\n      }\n    }\n    case CARBON_KIND(SemIR::FormParamPattern form_param_pattern): {\n      auto form_inst_id =\n          context.constant_values().GetInstId(form_param_pattern.form_id);\n      auto form_inst = context.insts().Get(form_inst_id);\n\n      switch (form_inst.kind()) {\n        case SemIR::InitForm::Kind:\n          return ConversionTarget::NoOp;\n        case SemIR::RefForm::Kind:\n          // TODO: Figure out rules for when the argument must have a `ref` tag.\n          return entry.allow_unmarked_ref ? ConversionTarget::UnmarkedRefParam\n                                          : ConversionTarget::RefParam;\n        case SemIR::SymbolicBinding::Kind:\n          context.TODO(entry.pattern_id, \"Support symbolic form params\");\n          [[fallthrough]];\n        case SemIR::ErrorInst::Kind:\n        case SemIR::ValueForm::Kind:\n          return ConversionTarget::Value;\n        default:\n          CARBON_FATAL(\"Unexpected form {0}\", form_inst);\n      }\n    }\n    default:\n      CARBON_FATAL(\"Unexpected pattern kind in {0}\", pattern);\n  }\n}\n\nauto MatchContext::DoEmitPatternMatch(Context& context,\n                                      SemIR::AnyBindingPattern binding_pattern,\n                                      MatchContext::WorkItem entry) -> void {\n  if (kind_ == MatchKind::Caller) {\n    CARBON_CHECK(\n        binding_pattern.kind == SemIR::SymbolicBindingPattern::Kind,\n        \"Found named runtime binding pattern during caller pattern match\");\n    return;\n  }\n  // We're logically consuming this map entry, so we invalidate it in order\n  // to avoid accidentally consuming it twice.\n  auto [bind_name_id, type_expr_region_id] =\n      std::exchange(context.bind_name_map().Lookup(entry.pattern_id).value(),\n                    {.bind_name_id = SemIR::InstId::None,\n                     .type_expr_region_id = SemIR::ExprRegionId::None});\n  if (type_expr_region_id.has_value()) {\n    InsertHere(context, type_expr_region_id);\n  }\n  auto value_id = SemIR::InstId::None;\n  if (kind_ == MatchKind::Local) {\n    auto conversion_kind = ConversionKindFor(context, binding_pattern, entry);\n\n    if (!bind_name_id.has_value()) {\n      // TODO: Is this appropriate, or should we perform a conversion based on\n      // whether the `_` binding is a value or ref binding first, and then\n      // separately discard the initializer for a `_` binding?\n      conversion_kind = ConversionTarget::Discarded;\n    }\n    value_id =\n        Convert(context, SemIR::LocId(entry.scrutinee_id), entry.scrutinee_id,\n                {.kind = conversion_kind,\n                 .type_id = context.insts().Get(bind_name_id).type_id()});\n  } else {\n    // In a function call, conversion is handled while matching the enclosing\n    // `*ParamPattern`.\n    value_id = entry.scrutinee_id;\n  }\n  if (bind_name_id.has_value()) {\n    auto bind_name = context.insts().GetAs<SemIR::AnyBinding>(bind_name_id);\n    CARBON_CHECK(!bind_name.value_id.has_value());\n    bind_name.value_id = value_id;\n    ReplaceInstBeforeConstantUse(context, bind_name_id, bind_name);\n    context.inst_block_stack().AddInstId(bind_name_id);\n  }\n}\n\n// Returns the inst kind to use for the parameter corresponding to the given\n// parameter pattern.\nstatic auto ParamKindFor(Context& context, SemIR::Inst param_pattern,\n                         MatchContext::WorkItem entry) -> SemIR::InstKind {\n  CARBON_KIND_SWITCH(param_pattern) {\n    case SemIR::OutParamPattern::Kind:\n      return SemIR::OutParam::Kind;\n    case SemIR::RefParamPattern::Kind:\n    case SemIR::VarParamPattern::Kind:\n      return SemIR::RefParam::Kind;\n    case SemIR::ValueParamPattern::Kind:\n      return SemIR::ValueParam::Kind;\n    case CARBON_KIND(SemIR::FormParamPattern form_param_pattern): {\n      auto form_inst_id =\n          context.constant_values().GetInstId(form_param_pattern.form_id);\n      auto form_inst = context.insts().Get(form_inst_id);\n      switch (form_inst.kind()) {\n        case SemIR::InitForm::Kind:\n        case SemIR::RefForm::Kind:\n          return SemIR::RefParam::Kind;\n        case SemIR::SymbolicBinding::Kind:\n          context.TODO(entry.pattern_id, \"Support symbolic form params\");\n          [[fallthrough]];\n        case SemIR::ErrorInst::Kind:\n        case SemIR::ValueForm::Kind:\n          return SemIR::ValueParam::Kind;\n        default:\n          CARBON_FATAL(\"Unexpected form {0}\", form_inst);\n      }\n    }\n    default:\n      CARBON_FATAL(\"Unexpected param pattern kind: {0}\", param_pattern);\n  }\n}\n\nauto MatchContext::DoEmitPatternMatch(Context& context,\n                                      SemIR::AnyParamPattern param_pattern,\n                                      WorkItem entry) -> void {\n  // If the form is initializing, match this as a `VarPattern` before matching\n  // it as a parameter pattern.\n  if (param_pattern.kind == SemIR::FormParamPattern::Kind) {\n    auto form_inst_id =\n        context.constant_values().GetInstId(param_pattern.form_id);\n    if (context.insts().Get(form_inst_id).kind() == SemIR::InitForm::Kind) {\n      auto new_scrutinee_id =\n          DoEmitVarPatternMatchImpl(context, param_pattern.type_id, entry);\n      entry.scrutinee_id = new_scrutinee_id;\n    }\n  }\n\n  switch (kind_) {\n    case MatchKind::Caller: {\n      CARBON_CHECK(entry.scrutinee_id.has_value());\n      if (entry.scrutinee_id == SemIR::ErrorInst::InstId) {\n        call_args_.push_back(SemIR::ErrorInst::InstId);\n      } else {\n        auto scrutinee_type_id = ExtractScrutineeType(\n            context.sem_ir(),\n            SemIR::GetTypeOfInstInSpecific(\n                context.sem_ir(), callee_specific_id_, entry.pattern_id));\n        call_args_.push_back(Convert(\n            context, SemIR::LocId(entry.scrutinee_id), entry.scrutinee_id,\n            {.kind = ConversionKindFor(context, param_pattern, entry),\n             .type_id = scrutinee_type_id}));\n      }\n      // Do not traverse farther, because the caller side of the pattern\n      // ends here.\n      break;\n    }\n    case MatchKind::Callee: {\n      SemIR::AnyParam param = {\n          .kind = ParamKindFor(context, param_pattern, entry),\n          .type_id =\n              ExtractScrutineeType(context.sem_ir(), param_pattern.type_id),\n          .index = SemIR::CallParamIndex(call_params_.size()),\n          .pretty_name_id = SemIR::GetPrettyNameFromPatternId(\n              context.sem_ir(), entry.pattern_id)};\n      auto param_id =\n          AddInst(context, SemIR::LocIdAndInst::UncheckedLoc(\n                               SemIR::LocId(entry.pattern_id), param));\n      AddWork({.pattern_id = param_pattern.subpattern_id,\n               .scrutinee_id = param_id});\n      call_params_.push_back(param_id);\n      call_param_patterns_.push_back(entry.pattern_id);\n      break;\n    }\n    case MatchKind::Local: {\n      CARBON_FATAL(\"Found ValueParamPattern during local pattern match\");\n    }\n  }\n}\n\nauto MatchContext::DoEmitPatternMatch(\n    Context& context, SemIR::ReturnSlotPattern return_slot_pattern,\n    WorkItem entry) -> void {\n  CARBON_CHECK(kind_ == MatchKind::Callee);\n  auto type_id =\n      ExtractScrutineeType(context.sem_ir(), return_slot_pattern.type_id);\n  auto return_slot_id = AddInst<SemIR::ReturnSlot>(\n      context, SemIR::LocId(entry.pattern_id),\n      {.type_id = type_id,\n       .type_inst_id = context.types().GetTypeInstId(type_id),\n       .storage_id = entry.scrutinee_id});\n  bool already_in_lookup =\n      context.scope_stack()\n          .LookupOrAddName(SemIR::NameId::ReturnSlot, return_slot_id)\n          .has_value();\n  CARBON_CHECK(!already_in_lookup);\n}\n\nauto MatchContext::DoEmitPatternMatch(Context& context,\n                                      SemIR::VarPattern var_pattern,\n                                      WorkItem entry) -> void {\n  auto new_scrutinee_id =\n      DoEmitVarPatternMatchImpl(context, var_pattern.type_id, entry);\n  AddWork({.pattern_id = var_pattern.subpattern_id,\n           .scrutinee_id = new_scrutinee_id});\n}\n\nauto MatchContext::DoEmitVarPatternMatchImpl(Context& context,\n                                             SemIR::TypeId pattern_type_id,\n                                             WorkItem entry) const\n    -> SemIR::InstId {\n  auto storage_id = SemIR::InstId::None;\n  switch (kind_) {\n    case MatchKind::Callee: {\n      // We're emitting pattern-match IR for the callee, but we're still on\n      // the caller side of the pattern, so we traverse without emitting any\n      // insts.\n      return SemIR::InstId::None;\n    }\n    case MatchKind::Local: {\n      // In a `var`/`let` declaration, the `VarStorage` inst is created before\n      // we start pattern matching.\n      auto lookup_result = context.var_storage_map().Lookup(entry.pattern_id);\n      CARBON_CHECK(lookup_result);\n      storage_id = lookup_result.value();\n      break;\n    }\n    case MatchKind::Caller: {\n      storage_id = AddInst<SemIR::TemporaryStorage>(\n          context, SemIR::LocId(entry.pattern_id),\n          {.type_id = ExtractScrutineeType(context.sem_ir(), pattern_type_id)});\n      CARBON_CHECK(entry.scrutinee_id.has_value());\n      break;\n    }\n  }\n  // TODO: Find a more efficient way to put these insts in the global_init\n  // block (or drop the distinction between the global_init block and the\n  // file scope?)\n  if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {\n    context.global_init().Resume();\n  }\n  if (entry.scrutinee_id.has_value()) {\n    auto init_id = Initialize(context, SemIR::LocId(entry.pattern_id),\n                              storage_id, entry.scrutinee_id);\n    // If we created a `TemporaryStorage` to hold the var, create a\n    // corresponding `Temporary` to model that its initialization is complete.\n    // TODO: If the subpattern is a binding, we may want to destroy the\n    // parameter variable in the callee instead of the caller so that we can\n    // support destructive move from it.\n    if (kind_ == MatchKind::Caller) {\n      storage_id = AddInstWithCleanup<SemIR::Temporary>(\n          context, SemIR::LocId(entry.pattern_id),\n          {.type_id = context.insts().Get(storage_id).type_id(),\n           .storage_id = storage_id,\n           .init_id = init_id});\n    } else {\n      // TODO: Consider using different instruction kinds for assignment\n      // versus initialization.\n      AddInst<SemIR::Assign>(context, SemIR::LocId(entry.pattern_id),\n                             {.lhs_id = storage_id, .rhs_id = init_id});\n    }\n  }\n  if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {\n    context.global_init().Suspend();\n  }\n  return storage_id;\n}\n\nauto MatchContext::DoEmitPatternMatch(Context& context,\n                                      SemIR::TuplePattern tuple_pattern,\n                                      WorkItem entry) -> void {\n  if (tuple_pattern.type_id == SemIR::ErrorInst::TypeId) {\n    return;\n  }\n  auto subpattern_ids = context.inst_blocks().Get(tuple_pattern.elements_id);\n  auto add_all_subscrutinees =\n      [&](llvm::ArrayRef<SemIR::InstId> subscrutinee_ids) {\n        for (auto [subpattern_id, subscrutinee_id] :\n             llvm::reverse(llvm::zip_equal(subpattern_ids, subscrutinee_ids))) {\n          AddWork(\n              {.pattern_id = subpattern_id, .scrutinee_id = subscrutinee_id});\n        }\n      };\n  if (!entry.scrutinee_id.has_value()) {\n    CARBON_CHECK(kind_ == MatchKind::Callee);\n    // If we don't have a scrutinee yet, we're still on the caller side of the\n    // pattern, so the subpatterns don't have a scrutinee either.\n    for (auto subpattern_id : llvm::reverse(subpattern_ids)) {\n      AddWork(\n          {.pattern_id = subpattern_id, .scrutinee_id = SemIR::InstId::None});\n    }\n    return;\n  }\n  auto scrutinee = context.insts().GetWithLocId(entry.scrutinee_id);\n  if (auto scrutinee_literal = scrutinee.inst.TryAs<SemIR::TupleLiteral>()) {\n    auto subscrutinee_ids =\n        context.inst_blocks().Get(scrutinee_literal->elements_id);\n    if (subscrutinee_ids.size() != subpattern_ids.size()) {\n      CARBON_DIAGNOSTIC(TuplePatternSizeDoesntMatchLiteral, Error,\n                        \"tuple pattern expects {0} element{0:s}, but tuple \"\n                        \"literal has {1}\",\n                        Diagnostics::IntAsSelect, Diagnostics::IntAsSelect);\n      context.emitter().Emit(entry.pattern_id,\n                             TuplePatternSizeDoesntMatchLiteral,\n                             subpattern_ids.size(), subscrutinee_ids.size());\n      return;\n    }\n    add_all_subscrutinees(subscrutinee_ids);\n    return;\n  }\n\n  auto tuple_type_id =\n      ExtractScrutineeType(context.sem_ir(), tuple_pattern.type_id);\n  auto converted_scrutinee_id =\n      ConvertToValueOrRefOfType(context, SemIR::LocId(entry.pattern_id),\n                                entry.scrutinee_id, tuple_type_id);\n  if (auto scrutinee_value =\n          context.insts().TryGetAs<SemIR::TupleValue>(converted_scrutinee_id)) {\n    add_all_subscrutinees(\n        context.inst_blocks().Get(scrutinee_value->elements_id));\n    return;\n  }\n\n  auto tuple_type = context.types().GetAs<SemIR::TupleType>(tuple_type_id);\n  auto element_type_inst_ids =\n      context.inst_blocks().Get(tuple_type.type_elements_id);\n  llvm::SmallVector<SemIR::InstId> subscrutinee_ids;\n  subscrutinee_ids.reserve(element_type_inst_ids.size());\n  for (auto [i, element_type_id] : llvm::enumerate(\n           context.types().GetBlockAsTypeIds(element_type_inst_ids))) {\n    subscrutinee_ids.push_back(\n        AddInst<SemIR::TupleAccess>(context, scrutinee.loc_id,\n                                    {.type_id = element_type_id,\n                                     .tuple_id = converted_scrutinee_id,\n                                     .index = SemIR::ElementIndex(i)}));\n  }\n  add_all_subscrutinees(subscrutinee_ids);\n}\n\nauto MatchContext::EmitPatternMatch(Context& context,\n                                    MatchContext::WorkItem entry) -> void {\n  if (entry.pattern_id == SemIR::ErrorInst::InstId) {\n    return;\n  }\n  Diagnostics::AnnotationScope annotate_diagnostics(\n      &context.emitter(), [&](auto& builder) {\n        if (kind_ == MatchKind::Caller) {\n          CARBON_DIAGNOSTIC(InCallToFunctionParam, Note,\n                            \"initializing function parameter\");\n          builder.Note(entry.pattern_id, InCallToFunctionParam);\n        }\n      });\n  auto pattern = context.insts().Get(entry.pattern_id);\n  CARBON_KIND_SWITCH(pattern) {\n    case CARBON_KIND_ANY(SemIR::AnyBindingPattern, any_binding_pattern): {\n      DoEmitPatternMatch(context, any_binding_pattern, entry);\n      break;\n    }\n    case CARBON_KIND_ANY(SemIR::AnyParamPattern, any_param_pattern): {\n      DoEmitPatternMatch(context, any_param_pattern, entry);\n      break;\n    }\n    case CARBON_KIND(SemIR::ReturnSlotPattern return_slot_pattern): {\n      DoEmitPatternMatch(context, return_slot_pattern, entry);\n      break;\n    }\n    case CARBON_KIND(SemIR::VarPattern var_pattern): {\n      DoEmitPatternMatch(context, var_pattern, entry);\n      break;\n    }\n    case CARBON_KIND(SemIR::TuplePattern tuple_pattern): {\n      DoEmitPatternMatch(context, tuple_pattern, entry);\n      break;\n    }\n    default: {\n      CARBON_FATAL(\"Inst kind not handled: {0}\", pattern.kind());\n    }\n  }\n}\n\nauto CalleePatternMatch(Context& context,\n                        SemIR::InstBlockId implicit_param_patterns_id,\n                        SemIR::InstBlockId param_patterns_id,\n                        SemIR::InstBlockId return_patterns_id)\n    -> CalleePatternMatchResults {\n  if (!return_patterns_id.has_value() && !param_patterns_id.has_value() &&\n      !implicit_param_patterns_id.has_value()) {\n    return {.call_param_patterns_id = SemIR::InstBlockId::None,\n            .call_params_id = SemIR::InstBlockId::None,\n            .param_ranges = SemIR::Function::CallParamIndexRanges::Empty};\n  }\n\n  MatchContext match(MatchKind::Callee);\n\n  // We add work to the stack in reverse so that the results will be produced\n  // in the original order.\n  if (implicit_param_patterns_id.has_value()) {\n    for (SemIR::InstId inst_id :\n         llvm::reverse(context.inst_blocks().Get(implicit_param_patterns_id))) {\n      match.AddWork(\n          {.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::None});\n    }\n  }\n  match.DoWork(context);\n  auto implicit_end = SemIR::CallParamIndex(match.param_count());\n\n  if (param_patterns_id.has_value()) {\n    for (SemIR::InstId inst_id :\n         llvm::reverse(context.inst_blocks().Get(param_patterns_id))) {\n      match.AddWork(\n          {.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::None});\n    }\n  }\n  match.DoWork(context);\n  auto explicit_end = SemIR::CallParamIndex(match.param_count());\n\n  for (auto return_pattern_id :\n       context.inst_blocks().GetOrEmpty(return_patterns_id)) {\n    match.AddWork(\n        {.pattern_id = return_pattern_id, .scrutinee_id = SemIR::InstId::None});\n  }\n  match.DoWork(context);\n  auto return_end = SemIR::CallParamIndex(match.param_count());\n\n  match.DoWork(context);\n  auto blocks = std::move(match).CalleeResults(context);\n  return {.call_param_patterns_id = blocks.call_param_patterns_id,\n          .call_params_id = blocks.call_params_id,\n          .param_ranges = {implicit_end, explicit_end, return_end}};\n}\n\nauto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,\n                        SemIR::InstId self_pattern_id,\n                        SemIR::InstBlockId param_patterns_id,\n                        SemIR::InstBlockId return_patterns_id,\n                        SemIR::InstId self_arg_id,\n                        llvm::ArrayRef<SemIR::InstId> arg_refs,\n                        llvm::ArrayRef<SemIR::InstId> return_arg_ids,\n                        bool is_operator_syntax) -> SemIR::InstBlockId {\n  MatchContext match(MatchKind::Caller, specific_id);\n\n  auto return_patterns = context.inst_blocks().GetOrEmpty(return_patterns_id);\n  // Track the return storage, if present.\n  for (auto [return_pattern_id, return_arg_id] :\n       llvm::zip_equal(return_patterns, return_arg_ids)) {\n    if (return_arg_id.has_value()) {\n      match.AddWork(\n          {.pattern_id = return_pattern_id, .scrutinee_id = return_arg_id});\n    } else {\n      CARBON_CHECK(return_arg_ids.size() == 1,\n                   \"TODO: do the match even if return_arg_id is None, so that \"\n                   \"subsequent args are at the right index in the arg block\");\n    }\n  }\n\n  // Check type conversions per-element.\n  for (auto [arg_id, param_pattern_id] : llvm::reverse(llvm::zip_equal(\n           arg_refs, context.inst_blocks().GetOrEmpty(param_patterns_id)))) {\n    match.AddWork({.pattern_id = param_pattern_id,\n                   .scrutinee_id = arg_id,\n                   .allow_unmarked_ref = is_operator_syntax});\n  }\n\n  if (self_pattern_id.has_value()) {\n    match.AddWork({.pattern_id = self_pattern_id,\n                   .scrutinee_id = self_arg_id,\n                   .allow_unmarked_ref = true});\n  }\n\n  match.DoWork(context);\n  return std::move(match).CallerResults(context);\n}\n\nauto LocalPatternMatch(Context& context, SemIR::InstId pattern_id,\n                       SemIR::InstId scrutinee_id) -> void {\n  MatchContext match(MatchKind::Local);\n  match.AddWork({.pattern_id = pattern_id, .scrutinee_id = scrutinee_id});\n  match.DoWork(context);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/pattern_match.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_PATTERN_MATCH_H_\n#define CARBON_TOOLCHAIN_CHECK_PATTERN_MATCH_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/function.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// TODO: Find a better place for this overview, once it has stabilized.\n//\n// The signature pattern of a function call is matched partially by the caller\n// and partially by the callee. `ParamPattern` insts mark the boundary\n// between the two: pattern insts that are descendants of a `ParamPattern`\n// are matched by the callee, and pattern insts that have a `ParamPattern`\n// as a descendant are matched by the caller.\n\n// Emits the pattern-match IR for the declaration of a parameterized entity with\n// the given implicit and explicit parameter patterns, and the given return\n// patterns (any of which may be `None` if not applicable). This IR performs the\n// callee side of pattern matching, starting at the `ParamPattern` insts, and\n// matching them against the corresponding `Call` parameters (see\n// entity_with_params_base.h for the definition of that term).\n// Returns the IDs of inst blocks consisting of references to the `Call`\n// parameter patterns and `Call` parameters of the function, as well as\n// the implicit, explicit, and return index ranges of those blocks.\nstruct CalleePatternMatchResults {\n  SemIR::InstBlockId call_param_patterns_id;\n  SemIR::InstBlockId call_params_id;\n\n  SemIR::Function::CallParamIndexRanges param_ranges;\n};\nauto CalleePatternMatch(Context& context,\n                        SemIR::InstBlockId implicit_param_patterns_id,\n                        SemIR::InstBlockId param_patterns_id,\n                        SemIR::InstBlockId return_patterns_id)\n    -> CalleePatternMatchResults;\n\n// Emits the pattern-match IR for matching the given arguments with the given\n// parameter patterns, and returns an inst block of the arguments that should\n// be passed to the `Call` inst. `is_operator_syntax` indicates that this call\n// was generated from an operator rather than from function call syntax, so\n// arguments to `ref` parameters aren't required to have `ref` tags.\nauto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,\n                        SemIR::InstId self_pattern_id,\n                        SemIR::InstBlockId param_patterns_id,\n                        SemIR::InstBlockId return_patterns_id,\n                        SemIR::InstId self_arg_id,\n                        llvm::ArrayRef<SemIR::InstId> arg_refs,\n                        llvm::ArrayRef<SemIR::InstId> return_arg_ids,\n                        bool is_operator_syntax) -> SemIR::InstBlockId;\n\n// Emits the pattern-match IR for a local pattern matching operation with the\n// given pattern and scrutinee.\nauto LocalPatternMatch(Context& context, SemIR::InstId pattern_id,\n                       SemIR::InstId scrutinee_id) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_PATTERN_MATCH_H_\n"
  },
  {
    "path": "toolchain/check/pending_block.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_PENDING_BLOCK_H_\n#define CARBON_TOOLCHAIN_CHECK_PENDING_BLOCK_H_\n\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n\nnamespace Carbon::Check {\n\n// A block of code that contains pending instructions that might be needed but\n// that haven't been inserted yet.\nclass PendingBlock {\n public:\n  // `context` must not be null.\n  explicit PendingBlock(Context* context) : context_(context) {}\n\n  PendingBlock(const PendingBlock&) = delete;\n  auto operator=(const PendingBlock&) -> PendingBlock& = delete;\n\n  // A scope in which we will tentatively add instructions to a pending block.\n  // If we leave the scope without inserting or merging the block, instructions\n  // added after this point will be removed again.\n  class DiscardUnusedInstsScope {\n   public:\n    // If `block` is not null, enters the scope. If `block` is null, this object\n    // has no effect.\n    explicit DiscardUnusedInstsScope(PendingBlock* block)\n        : block_(block), size_(block ? block->insts_.size() : 0) {}\n    ~DiscardUnusedInstsScope() {\n      if (block_ && block_->insts_.size() > size_) {\n        block_->insts_.truncate(size_);\n      }\n    }\n\n   private:\n    PendingBlock* block_;\n    size_t size_;\n  };\n\n  template <typename InstT, typename LocT>\n    requires(std::convertible_to<LocT, SemIR::LocId>)\n  auto AddInst(LocT loc_id, InstT inst) -> SemIR::InstId {\n    auto inst_id = AddInstInNoBlock(*context_, loc_id, inst);\n    insts_.push_back(inst_id);\n    return inst_id;\n  }\n\n  template <typename InstT, typename LocT>\n    requires(std::convertible_to<LocT, SemIR::LocId>)\n  auto AddInstWithCleanup(LocT loc_id, InstT inst) -> SemIR::InstId {\n    auto inst_id = AddInstWithCleanupInNoBlock(*context_, loc_id, inst);\n    insts_.push_back(inst_id);\n    return inst_id;\n  }\n\n  // Insert the pending block of code at the current position.\n  auto InsertHere() -> void {\n    for (auto id : insts_) {\n      context_->inst_block_stack().AddInstId(id);\n    }\n    insts_.clear();\n  }\n\n  // Replace the instruction at target_id with the instructions in this block.\n  // The new value for target_id should be value_id. Returns the InstId that\n  // should be used to refer to the result from now on. value_id must precede\n  // target_id, or be the last ID in this block, in order to preserve the\n  // property that SemIR is topologically sorted.\n  //\n  // TODO: we could also allow value_id to be one of the other insts in this\n  // block, but that would be costlier to enforce.\n  auto MergeReplacing(SemIR::InstId target_id, SemIR::InstId value_id)\n      -> SemIR::InstId {\n    CARBON_CHECK(target_id != value_id);\n\n    // TODO: consider adding an end-of-phase check that the SemIR::File is in\n    // SSA form, and dropping this check and the ordering preconditions here and\n    // on Initialize.\n    CARBON_CHECK(value_id.index <= target_id.index ||\n                     (!insts_.empty() && insts_.back() == value_id),\n                 \"Splice would break topological sorting of insts\");\n    SemIR::LocIdAndInst value = context_->insts().GetWithLocId(value_id);\n\n    auto result_id = value_id;\n    if (insts_.size() == 1 && insts_[0] == value_id) {\n      // The block is {value_id}. Replace `target_id` with the instruction\n      // referred to by `value_id`. This is intended to be the common case.\n      result_id = target_id;\n    } else {\n      // Anything else: splice it into the IR, replacing `target_id`. This\n      // includes empty blocks, which `Add` handles.\n      value.inst =\n          SemIR::SpliceBlock{.type_id = value.inst.type_id(),\n                             .block_id = context_->inst_blocks().Add(insts_),\n                             .result_id = value_id};\n    }\n\n    ReplaceLocIdAndInstBeforeConstantUse(*context_, target_id, value);\n\n    // Prepare to stash more pending instructions.\n    insts_.clear();\n    return result_id;\n  }\n\n private:\n  Context* context_;\n  llvm::SmallVector<SemIR::InstId> insts_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_PENDING_BLOCK_H_\n"
  },
  {
    "path": "toolchain/check/pointer_dereference.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/pointer_dereference.h\"\n\n#include \"llvm/ADT/STLFunctionalExtras.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nauto PerformPointerDereference(\n    Context& context, SemIR::LocId loc_id, SemIR::InstId base_id,\n    llvm::function_ref<auto(SemIR::TypeId not_pointer_type_id)->void>\n        diagnose_not_pointer) -> SemIR::InstId {\n  // TODO: Once we have a finalized design for a pointer interface, use\n  //\n  //   HandleUnaryOperator(context, loc_id, {\"Pointer\", \"Dereference\"});\n  //\n  // to convert to a pointer value.\n  base_id = ConvertToValueExpr(context, base_id);\n  auto type_id = context.types().GetUnqualifiedType(\n      context.insts().Get(base_id).type_id());\n  auto result_type_id = SemIR::ErrorInst::TypeId;\n  if (auto pointer_type =\n          context.types().TryGetAs<SemIR::PointerType>(type_id)) {\n    result_type_id =\n        context.types().GetTypeIdForTypeInstId(pointer_type->pointee_id);\n  } else if (type_id != SemIR::ErrorInst::TypeId) {\n    diagnose_not_pointer(type_id);\n  }\n  return AddInst<SemIR::Deref>(\n      context, loc_id, {.type_id = result_type_id, .pointer_id = base_id});\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/pointer_dereference.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_POINTER_DEREFERENCE_H_\n#define CARBON_TOOLCHAIN_CHECK_POINTER_DEREFERENCE_H_\n\n#include \"llvm/ADT/STLFunctionalExtras.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/parse/node_ids.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Creates SemIR to perform a pointer dereference with base expression\n// `base_id`. Returns the result of the access.\nauto PerformPointerDereference(\n    Context& context, SemIR::LocId loc_id, SemIR::InstId base_i,\n    llvm::function_ref<auto(SemIR::TypeId not_pointer_type_id)->void>\n        diagnose_not_pointer) -> SemIR::InstId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_POINTER_DEREFERENCE_H_\n"
  },
  {
    "path": "toolchain/check/region_stack.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_REGION_STACK_H_\n#define CARBON_TOOLCHAIN_CHECK_REGION_STACK_H_\n\n#include <utility>\n\n#include \"common/array_stack.h\"\n#include \"toolchain/check/diagnostic_helpers.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Provides a stack of single-entry regions being built.\nclass RegionStack {\n public:\n  // A callback for Context::TODO.\n  using TodoFn = std::function<auto(SemIR::LocId, std::string)->void>;\n\n  explicit RegionStack(TodoFn todo_fn) : todo_fn_(std::move(todo_fn)) {}\n\n  // Mark the start of a new single-entry region with the given entry block.\n  auto PushRegion(SemIR::InstBlockId entry_block_id) -> void {\n    stack_.PushArray();\n    stack_.AppendToTop(entry_block_id);\n  }\n\n  // Add `block_id` to the most recently pushed single-entry region. To preserve\n  // the single-entry property, `block_id` must not be directly reachable from\n  // any block outside the region. To ensure the region's blocks are in lexical\n  // order, this should be called when the first parse node associated with this\n  // block is handled, or as close as possible.\n  auto AddToRegion(SemIR::InstBlockId block_id, SemIR::LocId loc_id) -> void {\n    if (stack_.empty()) {\n      todo_fn_(loc_id,\n               \"Control flow expressions are currently only supported inside \"\n               \"functions.\");\n      return;\n    }\n    if (block_id == SemIR::InstBlockId::Unreachable) {\n      return;\n    }\n\n    stack_.AppendToTop(block_id);\n  }\n\n  // Adds multiple blocks at once. The caller is responsible for validating that\n  // each block is reachable.\n  auto AddToRegion(llvm::ArrayRef<SemIR::InstBlockId> block_ids) -> void {\n    stack_.AppendToTop(block_ids);\n  }\n\n  // Complete creation of the most recently pushed single-entry region, and\n  // return a list of its blocks.\n  auto PopRegion() -> llvm::SmallVector<SemIR::InstBlockId> {\n    llvm::SmallVector<SemIR::InstBlockId> result(stack_.PeekArray());\n    stack_.PopArray();\n    return result;\n  }\n\n  // Pops a region, and does not return its contents.\n  auto PopAndDiscardRegion() -> void { stack_.PopArray(); }\n\n  // Returns the top-most region.\n  auto PeekRegion() -> llvm::ArrayRef<SemIR::InstBlockId> {\n    return stack_.PeekArray();\n  }\n\n  // Runs verification that the processing cleanly finished.\n  auto VerifyOnFinish() const -> void {\n    CARBON_CHECK(stack_.empty(), \"region_stack still has {0} entries\",\n                 stack_.all_values_size());\n  }\n\n  // Returns true if any regions have been added.\n  auto empty() -> bool { return stack_.empty(); }\n\n private:\n  TodoFn todo_fn_;\n\n  ArrayStack<SemIR::InstBlockId> stack_;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_REGION_STACK_H_\n"
  },
  {
    "path": "toolchain/check/return.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/return.h\"\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/control_flow.h\"\n#include \"toolchain/check/convert.h\"\n#include \"toolchain/check/inst.h\"\n\nnamespace Carbon::Check {\n\n// Gets the function that lexically encloses the current location.\nauto GetCurrentFunctionForReturn(Context& context) -> SemIR::Function& {\n  CARBON_CHECK(context.scope_stack().IsInFunctionScope(),\n               \"Handling return but not in a function\");\n  auto decl_id = context.scope_stack().GetReturnScopeDeclId();\n  auto function_id =\n      context.insts().GetAs<SemIR::FunctionDecl>(decl_id).function_id;\n  return context.functions().Get(function_id);\n}\n\nauto GetReturnedVarParam(Context& context, const SemIR::Function& function)\n    -> SemIR::InstId {\n  auto return_form_id = function.GetDeclaredReturnForm(context.sem_ir());\n  if (auto return_form =\n          context.insts().TryGetAsIfValid<SemIR::InitForm>(return_form_id)) {\n    auto call_params = context.inst_blocks().Get(function.call_params_id);\n    CARBON_CHECK(function.call_param_ranges.return_size() == 1);\n    auto return_param_id =\n        call_params[function.call_param_ranges.return_begin().index];\n    auto return_type_id = context.insts().Get(return_param_id).type_id();\n    if (SemIR::InitRepr::ForType(context.sem_ir(), return_type_id)\n            .MightBeInPlace()) {\n      return return_param_id;\n    }\n  }\n  return SemIR::InstId::None;\n}\n\n// Gets the currently in scope `returned var` binding, if any, that would be\n// returned by a `return var;`.\nstatic auto GetCurrentReturnedVar(Context& context) -> SemIR::InstId {\n  CARBON_CHECK(context.scope_stack().IsInFunctionScope(),\n               \"Handling return but not in a function\");\n  return context.scope_stack().GetReturnedVar();\n}\n\n// Produces a note that the given function has no explicit return type.\nstatic auto NoteNoReturnTypeProvided(DiagnosticBuilder& diag,\n                                     const SemIR::Function& function) {\n  CARBON_DIAGNOSTIC(ReturnTypeOmittedNote, Note,\n                    \"there was no return type provided\");\n  diag.Note(function.latest_decl_id(), ReturnTypeOmittedNote);\n}\n\n// Produces a note describing the return type of the given function, which\n// must be a function whose definition is currently being checked.\nstatic auto NoteReturnType(DiagnosticBuilder& diag,\n                           const SemIR::Function& function) {\n  CARBON_DIAGNOSTIC(ReturnTypeHereNote, Note, \"return type of function is {0}\",\n                    InstIdAsType);\n  diag.Note(function.return_type_inst_id, ReturnTypeHereNote,\n            function.return_type_inst_id);\n}\n\n// Produces a note pointing at the currently in scope `returned var`.\nstatic auto NoteReturnedVar(DiagnosticBuilder& diag,\n                            SemIR::InstId returned_var_id) {\n  CARBON_DIAGNOSTIC(ReturnedVarHere, Note, \"`returned var` was declared here\");\n  diag.Note(returned_var_id, ReturnedVarHere);\n}\n\nauto RegisterReturnedVar(Context& context, Parse::NodeId returned_node,\n                         Parse::NodeId type_node, SemIR::TypeId type_id,\n                         SemIR::InstId bind_id, SemIR::NameId name_id) -> void {\n  auto& function = GetCurrentFunctionForReturn(context);\n  auto return_type_id = function.GetDeclaredReturnType(context.sem_ir());\n\n  // A `returned var` requires an explicit return type.\n  if (!return_type_id.has_value()) {\n    CARBON_DIAGNOSTIC(ReturnedVarWithNoReturnType, Error,\n                      \"cannot declare a `returned var` in this function\");\n    auto diag =\n        context.emitter().Build(returned_node, ReturnedVarWithNoReturnType);\n    NoteNoReturnTypeProvided(diag, function);\n    diag.Emit();\n    return;\n  }\n\n  // The declared type of the var must match the return type of the function.\n  if (return_type_id != type_id) {\n    CARBON_DIAGNOSTIC(ReturnedVarWrongType, Error,\n                      \"type {0} of `returned var` does not match \"\n                      \"return type of enclosing function\",\n                      SemIR::TypeId);\n    auto diag =\n        context.emitter().Build(type_node, ReturnedVarWrongType, type_id);\n    NoteReturnType(diag, function);\n    diag.Emit();\n  }\n\n  auto form_inst_id = function.GetDeclaredReturnForm(context.sem_ir());\n  if (!context.insts().Is<SemIR::InitForm>(form_inst_id)) {\n    CARBON_DIAGNOSTIC(ReturnedVarNotInit, Error,\n                      \"`returned var` declaration in function with \"\n                      \"non-initializing return form\");\n    auto diag = context.emitter().Build(returned_node, ReturnedVarNotInit);\n    CARBON_DIAGNOSTIC(ReturnFormHereNote, Note, \"return form declared here\");\n    diag.Note(function.return_form_inst_id, ReturnFormHereNote);\n    diag.Emit();\n  }\n\n  auto existing_id =\n      context.scope_stack().SetReturnedVarOrGetExisting(bind_id, name_id);\n  if (existing_id.has_value()) {\n    CARBON_DIAGNOSTIC(ReturnedVarShadowed, Error,\n                      \"cannot declare a `returned var` in the scope of \"\n                      \"another `returned var`\");\n    auto diag = context.emitter().Build(bind_id, ReturnedVarShadowed);\n    NoteReturnedVar(diag, existing_id);\n    diag.Emit();\n  }\n}\n\nauto BuildReturnWithNoExpr(Context& context, SemIR::LocId loc_id) -> void {\n  const auto& function = GetCurrentFunctionForReturn(context);\n  auto return_type_id = function.GetDeclaredReturnType(context.sem_ir());\n\n  if (return_type_id.has_value()) {\n    CARBON_DIAGNOSTIC(ReturnStatementMissingExpr, Error,\n                      \"missing return value\");\n    auto diag = context.emitter().Build(loc_id, ReturnStatementMissingExpr);\n    NoteReturnType(diag, function);\n    diag.Emit();\n  }\n\n  AddReturnCleanupBlock(context, loc_id);\n}\n\nauto BuildReturnWithExpr(Context& context, SemIR::LocId loc_id,\n                         SemIR::InstId expr_id) -> void {\n  const auto& function = GetCurrentFunctionForReturn(context);\n  auto returned_var_id = GetCurrentReturnedVar(context);\n  auto out_param_id = SemIR::InstId::None;\n\n  auto return_type_id = SemIR::TypeId::None;\n  if (function.return_type_inst_id.has_value()) {\n    return_type_id =\n        context.types().GetTypeIdForTypeInstId(function.return_type_inst_id);\n  }\n  if (!return_type_id.has_value()) {\n    CARBON_DIAGNOSTIC(\n        ReturnStatementDisallowExpr, Error,\n        \"no return expression should be provided in this context\");\n    auto diag = context.emitter().Build(loc_id, ReturnStatementDisallowExpr);\n    NoteNoReturnTypeProvided(diag, function);\n    diag.Emit();\n    expr_id = SemIR::ErrorInst::InstId;\n  } else if (returned_var_id.has_value()) {\n    CARBON_DIAGNOSTIC(\n        ReturnExprWithReturnedVar, Error,\n        \"can only `return var;` in the scope of a `returned var`\");\n    auto diag = context.emitter().Build(loc_id, ReturnExprWithReturnedVar);\n    NoteReturnedVar(diag, returned_var_id);\n    diag.Emit();\n    expr_id = SemIR::ErrorInst::InstId;\n  } else if (!SemIR::InitRepr::ForType(context.sem_ir(), return_type_id)\n                  .is_valid() ||\n             return_type_id == SemIR::ErrorInst::TypeId) {\n    // We already diagnosed that the return type is invalid. Don't try to\n    // convert to it.\n    expr_id = SemIR::ErrorInst::InstId;\n  } else {\n    auto return_form =\n        context.insts().Get(function.GetDeclaredReturnForm(context.sem_ir()));\n    CARBON_KIND_SWITCH(return_form) {\n      case CARBON_KIND(SemIR::InitForm _): {\n        auto call_params = context.inst_blocks().Get(\n            GetCurrentFunctionForReturn(context).call_params_id);\n        CARBON_CHECK(function.call_param_ranges.return_size() == 1);\n        out_param_id =\n            call_params[function.call_param_ranges.return_begin().index];\n        CARBON_CHECK(out_param_id.has_value());\n        expr_id = Initialize(context, loc_id, out_param_id, expr_id,\n                             /*for_return=*/true);\n        if (!SemIR::InitRepr::ForType(context.sem_ir(), return_type_id)\n                 .MightBeInPlace()) {\n          out_param_id = SemIR::InstId::None;\n        }\n        break;\n      }\n      case CARBON_KIND(SemIR::RefForm ref_form): {\n        expr_id = Convert(\n            context, loc_id, expr_id,\n            ConversionTarget{.kind = ConversionTarget::DurableRef,\n                             .type_id = context.types().GetTypeIdForTypeInstId(\n                                 ref_form.type_component_inst_id)});\n        break;\n      }\n      default:\n        CARBON_FATAL(\"Unexpected inst kind: {0}\", return_form);\n    }\n  }\n\n  AddReturnCleanupBlockWithExpr(context, loc_id,\n                                {.expr_id = expr_id, .dest_id = out_param_id});\n}\n\nauto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id)\n    -> void {\n  const auto& function = GetCurrentFunctionForReturn(context);\n  auto returned_var_id = GetCurrentReturnedVar(context);\n\n  if (!returned_var_id.has_value()) {\n    CARBON_DIAGNOSTIC(ReturnVarWithNoReturnedVar, Error,\n                      \"`return var;` with no `returned var` in scope\");\n    context.emitter().Emit(node_id, ReturnVarWithNoReturnedVar);\n    returned_var_id = SemIR::ErrorInst::InstId;\n  }\n\n  auto return_param_id = GetReturnedVarParam(context, function);\n  if (!return_param_id.has_value()) {\n    // If we don't have a return slot, we're returning by value. Convert to a\n    // value expression.\n    returned_var_id = ConvertToValueExpr(context, returned_var_id);\n  }\n\n  AddReturnCleanupBlockWithExpr(\n      context, node_id,\n      {.expr_id = returned_var_id, .dest_id = return_param_id});\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/return.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_RETURN_H_\n#define CARBON_TOOLCHAIN_CHECK_RETURN_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/parse/node_ids.h\"\n\nnamespace Carbon::Check {\n\n// Gets the function that a `return` statement in the current context would\n// return from.\nauto GetCurrentFunctionForReturn(Context& context) -> SemIR::Function&;\n\n// Gets the return parameter corresponding to `function`'s `returned var`.\n// Returns None if the `returned var` doesn't correspond to a return parameter\n// (e.g. because it doesn't have an in-place init representation).\nauto GetReturnedVarParam(Context& context, const SemIR::Function& function)\n    -> SemIR::InstId;\n\n// Checks a `returned var` binding and registers it as the current `returned\n// var` in this scope.\nauto RegisterReturnedVar(Context& context, Parse::NodeId returned_node,\n                         Parse::NodeId type_node, SemIR::TypeId type_id,\n                         SemIR::InstId bind_id, SemIR::NameId name_id) -> void;\n\n// Checks and builds SemIR for a `return;` statement.\nauto BuildReturnWithNoExpr(Context& context, SemIR::LocId loc_id) -> void;\n\n// Checks and builds SemIR for a `return <expression>;` statement.\nauto BuildReturnWithExpr(Context& context, SemIR::LocId loc_id,\n                         SemIR::InstId expr_id) -> void;\n\n// Checks and builds SemIR for a `return var;` statement.\nauto BuildReturnVar(Context& context, Parse::ReturnStatementId node_id) -> void;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_RETURN_H_\n"
  },
  {
    "path": "toolchain/check/scope_index.h",
    "content": "\n// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_SCOPE_INDEX_H_\n#define CARBON_TOOLCHAIN_CHECK_SCOPE_INDEX_H_\n\n#include \"toolchain/base/index_base.h\"\n\nnamespace Carbon::Check {\n\n// An index for a pushed scope. This may correspond to a permanent scope with a\n// corresponding `NameScope`, in which case a different index will be assigned\n// each time the scope is entered. Alternatively, it may be a temporary scope\n// such as is created for a block, and will only be entered once.\n//\n// `ScopeIndex` values are comparable. Lower `ScopeIndex` values correspond to\n// scopes entered earlier in the file.\nstruct ScopeIndex : public IndexBase<ScopeIndex> {\n  static constexpr llvm::StringLiteral Label = \"scope\";\n  static const ScopeIndex Package;\n\n  using IndexBase::IndexBase;\n};\n\ninline constexpr ScopeIndex ScopeIndex::Package = ScopeIndex(0);\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_SCOPE_INDEX_H_\n"
  },
  {
    "path": "toolchain/check/scope_stack.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/scope_stack.h\"\n\n#include <utility>\n\n#include \"common/check.h\"\n#include \"toolchain/check/context.h\"\n#include \"toolchain/check/unused.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nScopeStack::ScopeStack(Context& context)\n    : context_(&context),\n      lexical_lookup_(context.sem_ir().identifiers()),\n      full_pattern_stack_(&lexical_lookup_) {}\n\nauto ScopeStack::sem_ir() const -> const SemIR::File& {\n  return context_->sem_ir();\n}\n\nauto ScopeStack::VerifyOnFinish() const -> void {\n  CARBON_CHECK(return_scope_stack_.empty(), \"{0}\", return_scope_stack_.size());\n  CARBON_CHECK(break_continue_stack_.empty(), \"{0}\",\n               break_continue_stack_.size());\n  CARBON_CHECK(scope_stack_.empty(), \"{0}\", scope_stack_.size());\n  CARBON_CHECK(destroy_id_stack_.empty(), \"{0}\",\n               destroy_id_stack_.all_values_size());\n  CARBON_CHECK(non_lexical_scope_stack_.empty(), \"{0}\",\n               non_lexical_scope_stack_.size());\n  CARBON_CHECK(compile_time_binding_stack_.empty(), \"{0}\",\n               compile_time_binding_stack_.all_values_size());\n  full_pattern_stack_.VerifyOnFinish();\n}\n\nauto ScopeStack::VerifyNextCompileTimeBindIndex(llvm::StringLiteral label,\n                                                const ScopeStackEntry& scope)\n    -> void {\n  CARBON_CHECK(\n      static_cast<int32_t>(compile_time_binding_stack_.all_values_size()) ==\n          scope.next_compile_time_bind_index.index,\n      \"Wrong number of entries in compile-time binding stack after {0}: have \"\n      \"{1}, expected {2}\",\n      label, compile_time_binding_stack_.all_values_size(),\n      scope.next_compile_time_bind_index.index);\n}\n\nauto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,\n                      SemIR::SpecificId specific_id,\n                      bool lexical_lookup_has_load_error) -> void {\n  // If this scope doesn't have a specific of its own, it lives in the enclosing\n  // scope's specific, if any.\n  auto enclosing_specific_id = specific_id;\n  if (!specific_id.has_value() && !scope_stack_.empty()) {\n    enclosing_specific_id = PeekSpecificId();\n  }\n\n  compile_time_binding_stack_.PushArray();\n  scope_stack_.push_back(\n      {.index = next_scope_index_,\n       .scope_inst_id = scope_inst_id,\n       .scope_id = scope_id,\n       .specific_id = enclosing_specific_id,\n       .next_compile_time_bind_index = SemIR::CompileTimeBindIndex(\n           compile_time_binding_stack_.all_values_size()),\n       .lexical_lookup_has_load_error =\n           LexicalLookupHasLoadError() || lexical_lookup_has_load_error});\n  if (scope_stack_.back().is_lexical_scope()) {\n    // For lexical lookups, unqualified lookup doesn't know how to find the\n    // associated specific, so if we start adding lexical scopes associated with\n    // specifics, we'll need to somehow track them in lookup.\n    CARBON_CHECK(!specific_id.has_value(),\n                 \"Lexical scope should not have an associated specific.\");\n  } else {\n    non_lexical_scope_stack_.push_back({.scope_index = next_scope_index_,\n                                        .name_scope_id = scope_id,\n                                        .specific_id = enclosing_specific_id});\n  }\n\n  // TODO: Handle this case more gracefully.\n  CARBON_CHECK(next_scope_index_.index != std::numeric_limits<int32_t>::max(),\n               \"Ran out of scopes\");\n  ++next_scope_index_.index;\n\n  VerifyNextCompileTimeBindIndex(\"Push\", scope_stack_.back());\n}\n\nauto ScopeStack::PushForDeclName() -> void {\n  Push(SemIR::InstId::None, SemIR::NameScopeId::None, SemIR::SpecificId::None,\n       /*lexical_lookup_has_load_error=*/false);\n  MarkNestingIfInReturnScope();\n}\n\nauto ScopeStack::PushForEntity(SemIR::InstId scope_inst_id,\n                               SemIR::NameScopeId scope_id,\n                               SemIR::SpecificId specific_id,\n                               bool lexical_lookup_has_load_error) -> void {\n  CARBON_CHECK(scope_inst_id.has_value());\n  CARBON_DCHECK(!sem_ir().insts().Is<SemIR::FunctionDecl>(scope_inst_id));\n  Push(scope_inst_id, scope_id, specific_id, lexical_lookup_has_load_error);\n  MarkNestingIfInReturnScope();\n}\n\nauto ScopeStack::PushForSameRegion() -> void {\n  Push(SemIR::InstId::None, SemIR::NameScopeId::None, SemIR::SpecificId::None,\n       /*lexical_lookup_has_load_error=*/false);\n}\n\nauto ScopeStack::PushForFunctionBody(SemIR::InstId scope_inst_id) -> void {\n  CARBON_DCHECK(sem_ir().insts().Is<SemIR::FunctionDecl>(scope_inst_id));\n  Push(scope_inst_id, SemIR::NameScopeId::None, SemIR::SpecificId::None,\n       /*lexical_lookup_has_load_error=*/false);\n\n  return_scope_stack_.push_back({.decl_id = scope_inst_id});\n  destroy_id_stack_.PushArray();\n}\n\nauto ScopeStack::Pop(bool check_unused) -> void {\n  auto scope = scope_stack_.pop_back_val();\n\n  // TODO: Multiple diagnostics on same line has non-deterministic order.\n  // Add second sort key in diagnostics sorting.\n  scope.names.ForEach([&, check_unused](SemIR::NameId name_id) {\n    auto& lexical_results = lexical_lookup_.Get(name_id);\n    CARBON_CHECK(lexical_results.back().scope_index == scope.index,\n                 \"Inconsistent scope index for name {0}\", name_id);\n    if (check_unused) {\n      CheckUnusedBinding(*context_, name_id, lexical_results.back());\n    }\n    lexical_results.pop_back();\n  });\n\n  if (!scope.is_lexical_scope()) {\n    CARBON_CHECK(non_lexical_scope_stack_.back().scope_index == scope.index);\n    non_lexical_scope_stack_.pop_back();\n  }\n\n  if (!return_scope_stack_.empty()) {\n    if (scope.has_returned_var) {\n      CARBON_CHECK(return_scope_stack_.back().returned_var.has_value());\n      return_scope_stack_.back().returned_var = SemIR::InstId::None;\n    }\n\n    if (return_scope_stack_.back().decl_id == scope.scope_inst_id) {\n      // Leaving the function scope.\n      return_scope_stack_.pop_back();\n      destroy_id_stack_.PopArray();\n    } else if (return_scope_stack_.back().nested_scope_index == scope.index) {\n      // Returned to a function scope from a non-function nested entity scope.\n      return_scope_stack_.back().nested_scope_index = ScopeIndex::None;\n    }\n  } else {\n    CARBON_CHECK(!scope.has_returned_var);\n  }\n\n  VerifyNextCompileTimeBindIndex(\"Pop\", scope);\n  compile_time_binding_stack_.PopArray();\n}\n\nauto ScopeStack::PopTo(ScopeIndex index, bool check_unused) -> void {\n  while (PeekIndex() > index) {\n    Pop(check_unused);\n  }\n  CARBON_CHECK(PeekIndex() == index,\n               \"Scope index {0} does not enclose the current scope {1}\", index,\n               PeekIndex());\n}\n\nauto ScopeStack::MarkUsed(SemIR::NameId name_id, SemIR::LocId loc_id,\n                          bool is_reachable) -> void {\n  auto& lexical_results = lexical_lookup_.Get(name_id);\n  if (lexical_results.empty()) {\n    return;\n  }\n  auto& result = lexical_results.back();\n  if (result.use_loc_id.has_value()) {\n    return;\n  }\n\n  // Determine if we should set use_loc_id.\n  if (result.inst_id.has_value() &&\n      result.inst_id != SemIR::InstId::InitTombstone) {\n    if (auto binding =\n            context_->insts().TryGetAs<SemIR::AnyBinding>(result.inst_id)) {\n      const auto& entity_name =\n          context_->entity_names().Get(binding->entity_name_id);\n      if (entity_name.is_unused && !is_reachable) {\n        return;\n      }\n    }\n  }\n  // For non-bindings (like namespaces), we just mark them as used.\n  // If the instruction is not valid (e.g. InitTombstone), we mark it as used\n  // to avoid spurious \"unused\" warnings, assuming the invalid state will be\n  // diagnosed elsewhere (e.g. used before init).\n  result.use_loc_id = loc_id;\n}\n\nauto ScopeStack::LookupInLexicalScopesWithin(SemIR::NameId name_id,\n                                             ScopeIndex scope_index,\n                                             SemIR::LocId use_loc_id,\n                                             bool is_reachable)\n    -> SemIR::InstId {\n  llvm::ArrayRef<LexicalLookup::Result> lexical_results =\n      lexical_lookup_.Get(name_id);\n  if (lexical_results.empty()) {\n    return SemIR::InstId::None;\n  }\n\n  auto result = lexical_results.back();\n  if (result.scope_index < scope_index) {\n    return SemIR::InstId::None;\n  }\n\n  if (use_loc_id.has_value()) {\n    MarkUsed(name_id, use_loc_id, is_reachable);\n  }\n  return result.inst_id;\n}\n\nauto ScopeStack::LookupInLexicalScopes(SemIR::NameId name_id,\n                                       SemIR::LocId use_loc_id,\n                                       bool is_reachable)\n    -> std::pair<SemIR::InstId, llvm::ArrayRef<NonLexicalScope>> {\n  // Find the results from lexical scopes. These will be combined with results\n  // from non-lexical scopes such as namespaces and classes.\n  llvm::ArrayRef<LexicalLookup::Result> lexical_results =\n      lexical_lookup_.Get(name_id);\n\n  // If we have no lexical results, check all non-lexical scopes.\n  if (lexical_results.empty()) {\n    return {LexicalLookupHasLoadError() ? SemIR::ErrorInst::InstId\n                                        : SemIR::InstId::None,\n            non_lexical_scope_stack_};\n  }\n\n  if (use_loc_id.has_value()) {\n    MarkUsed(name_id, use_loc_id, is_reachable);\n  }\n  // Find the first non-lexical scope that is within the scope of the lexical\n  // lookup result.\n  auto* first_non_lexical_scope = llvm::lower_bound(\n      non_lexical_scope_stack_, lexical_results.back().scope_index,\n      [](const NonLexicalScope& scope, ScopeIndex index) {\n        return scope.scope_index < index;\n      });\n  return {\n      lexical_results.back().inst_id,\n      llvm::ArrayRef(first_non_lexical_scope, non_lexical_scope_stack_.end())};\n}\n\nauto ScopeStack::LookupOrAddName(SemIR::NameId name_id, SemIR::InstId target_id,\n                                 ScopeIndex scope_index, bool is_decl_reachable)\n    -> SemIR::InstId {\n  // Find the corresponding scope depth.\n  //\n  // TODO: Consider passing in the depth rather than performing a scan for it.\n  // We only do this scan when declaring an entity such as a class within a\n  // function, so it should be relatively rare, but it's still not necesasry to\n  // recompute this.\n  int scope_depth = scope_stack_.size() - 1;\n  if (scope_index.has_value()) {\n    scope_depth =\n        llvm::lower_bound(scope_stack_, scope_index,\n                          [](const ScopeStackEntry& entry, ScopeIndex index) {\n                            return entry.index < index;\n                          }) -\n        scope_stack_.begin();\n    CARBON_CHECK(scope_stack_[scope_depth].index == scope_index,\n                 \"Declaring name in scope that has already ended\");\n  } else {\n    scope_index = scope_stack_[scope_depth].index;\n  }\n\n  // If this name has already been declared in this scope or an inner scope,\n  // return the existing result.\n  auto& lexical_results = lexical_lookup_.Get(name_id);\n  if (!lexical_results.empty() &&\n      lexical_results.back().scope_index >= scope_index) {\n    return lexical_results.back().inst_id;\n  }\n\n  // Add the name into the scope.\n  bool inserted = scope_stack_[scope_depth].names.Insert(name_id).is_inserted();\n  CARBON_CHECK(inserted, \"Name in scope but not in lexical lookups\");\n  ++scope_stack_[scope_depth].num_names;\n\n  // Add a corresponding lexical lookup result.\n  lexical_results.push_back({.inst_id = target_id,\n                             .scope_index = scope_index,\n                             .is_decl_reachable = is_decl_reachable,\n                             .use_loc_id = SemIR::LocId::None});\n  return SemIR::InstId::None;\n}\n\nauto ScopeStack::SetReturnedVarOrGetExisting(SemIR::InstId inst_id,\n                                             SemIR::NameId name_id)\n    -> SemIR::InstId {\n  CARBON_CHECK(!return_scope_stack_.empty(), \"`returned var` in no function\");\n  auto& return_scope = return_scope_stack_.back();\n  if (return_scope.returned_var.has_value()) {\n    return return_scope.returned_var;\n  }\n\n  return_scope.returned_var = inst_id;\n  CARBON_CHECK(!scope_stack_.back().has_returned_var,\n               \"Scope has returned var but none is set\");\n  if (inst_id.has_value()) {\n    scope_stack_.back().has_returned_var = true;\n    MarkUsed(name_id, SemIR::LocId(inst_id),\n             context_->inst_block_stack().is_current_block_reachable());\n  }\n  return SemIR::InstId::None;\n}\n\nauto ScopeStack::Suspend() -> SuspendedScope {\n  CARBON_CHECK(!scope_stack_.empty(), \"No scope to suspend\");\n  SuspendedScope result = {.entry = scope_stack_.pop_back_val(),\n                           .suspended_items = {}};\n  if (!result.entry.is_lexical_scope()) {\n    non_lexical_scope_stack_.pop_back();\n  }\n  auto peek_compile_time_bindings = compile_time_binding_stack_.PeekArray();\n  result.suspended_items.reserve(result.entry.num_names +\n                                 peek_compile_time_bindings.size());\n\n  result.entry.names.ForEach([&](SemIR::NameId name_id) {\n    auto suspended = lexical_lookup_.Suspend(name_id);\n    CARBON_CHECK(suspended.index !=\n                 SuspendedScope::ScopeItem::IndexForCompileTimeBinding);\n    result.suspended_items.push_back(\n        {.index = suspended.index,\n         .inst_id = suspended.inst_id,\n         .is_decl_reachable = suspended.is_decl_reachable,\n         .use_loc_id = suspended.use_loc_id});\n  });\n  CARBON_CHECK(static_cast<int>(result.suspended_items.size()) ==\n               result.entry.num_names);\n\n  // Move any compile-time bindings into the suspended scope.\n  for (auto inst_id : peek_compile_time_bindings) {\n    result.suspended_items.push_back(\n        {.index = SuspendedScope::ScopeItem::IndexForCompileTimeBinding,\n         .inst_id = inst_id,\n         .is_decl_reachable = true,\n         .use_loc_id = SemIR::LocId::None});\n  }\n  compile_time_binding_stack_.PopArray();\n\n  // This would be easy to support if we had a need, but currently we do not.\n  CARBON_CHECK(!result.entry.has_returned_var,\n               \"Should not suspend a scope with a returned var.\");\n  return result;\n}\n\nauto ScopeStack::Restore(SuspendedScope&& scope) -> void {\n  compile_time_binding_stack_.PushArray();\n  for (auto item : scope.suspended_items) {\n    if (item.index == SuspendedScope::ScopeItem::IndexForCompileTimeBinding) {\n      compile_time_binding_stack_.AppendToTop(item.inst_id);\n    } else {\n      lexical_lookup_.Restore({.index = item.index,\n                               .inst_id = item.inst_id,\n                               .is_decl_reachable = item.is_decl_reachable,\n                               .use_loc_id = item.use_loc_id},\n                              scope.entry.index);\n    }\n  }\n\n  VerifyNextCompileTimeBindIndex(\"Restore\", scope.entry);\n\n  if (!scope.entry.is_lexical_scope()) {\n    non_lexical_scope_stack_.push_back(\n        {.scope_index = scope.entry.index,\n         .name_scope_id = scope.entry.scope_id,\n         .specific_id = scope.entry.specific_id});\n  }\n  scope_stack_.push_back(std::move(scope.entry));\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/scope_stack.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_SCOPE_STACK_H_\n#define CARBON_TOOLCHAIN_CHECK_SCOPE_STACK_H_\n\n#include \"common/array_stack.h\"\n#include \"common/move_only.h\"\n#include \"common/set.h\"\n#include \"llvm/ADT/SmallVector.h\"\n#include \"toolchain/check/full_pattern_stack.h\"\n#include \"toolchain/check/lexical_lookup.h\"\n#include \"toolchain/check/scope_index.h\"\n#include \"toolchain/sem_ir/file.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\nclass Context;\n\n// A stack of lexical and semantic scopes that we are currently performing\n// checking within.\nclass ScopeStack {\n public:\n  explicit ScopeStack(Context& context);\n\n  // A scope in which `break` and `continue` can be used.\n  struct BreakContinueScope {\n    SemIR::InstBlockId break_target;\n    SemIR::InstBlockId continue_target;\n  };\n\n  // A non-lexical scope in which unqualified lookup may be required.\n  struct NonLexicalScope {\n    // The index of the scope in the scope stack.\n    ScopeIndex scope_index;\n\n    // The corresponding name scope.\n    SemIR::NameScopeId name_scope_id;\n\n    // The corresponding specific.\n    SemIR::SpecificId specific_id;\n  };\n\n  // Information about a scope that has been temporarily removed from the stack.\n  // This type is large, so moves of this type should be avoided.\n  struct SuspendedScope;\n\n  // Pushes a scope for a declaration name's parameters.\n  auto PushForDeclName() -> void;\n\n  // Pushes a non-function entity scope. Functions must use\n  // `PushForFunctionBody` instead.\n  auto PushForEntity(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,\n                     SemIR::SpecificId specific_id,\n                     bool lexical_lookup_has_load_error = false) -> void;\n\n  // Pushes a scope which should be in the same region as the current scope.\n  // These can be in a function without breaking `return` scoping. For example,\n  // this is used by struct literals and code blocks.\n  auto PushForSameRegion() -> void;\n\n  // Pushes a function scope.\n  auto PushForFunctionBody(SemIR::InstId scope_inst_id) -> void;\n\n  // Pops the top scope from scope_stack_. Removes names from lexical_lookup_.\n  // If `check_unused` is set, checks and emits diagnostics for unused names.\n  auto Pop(bool check_unused = false) -> void;\n\n  // Pops the top scope from scope_stack_ if it contains no names.\n  auto PopIfEmpty(bool check_unused = false) -> void {\n    if (scope_stack_.back().num_names == 0) {\n      Pop(check_unused);\n    }\n  }\n\n  // Pops scopes until we return to the specified scope index.\n  auto PopTo(ScopeIndex index, bool check_unused = false) -> void;\n\n  // Returns the scope index associated with the current scope.\n  auto PeekIndex() const -> ScopeIndex { return Peek().index; }\n\n  // Returns the name scope associated with the current lexical scope, if any.\n  auto PeekNameScopeId() const -> SemIR::NameScopeId { return Peek().scope_id; }\n\n  // Returns the instruction associated with the current scope, or `None` if\n  // there is no such instruction, such as for a block scope.\n  auto PeekInstId() const -> SemIR::InstId { return Peek().scope_inst_id; }\n\n  // Returns the specific associated with the innermost enclosing scope that is\n  // associated with a specific. This will generally be the self specific of the\n  // innermost enclosing generic, as there is no way to enter any other specific\n  // scope.\n  auto PeekSpecificId() const -> SemIR::SpecificId {\n    return Peek().specific_id;\n  }\n\n  // Returns true if the current scope is inside a function scope (either the\n  // scope itself, or a lexical scope), without an intervening entity scope.\n  auto IsInFunctionScope() const -> bool {\n    return !return_scope_stack_.empty() &&\n           !return_scope_stack_.back().nested_scope_index.has_value();\n  }\n\n  // Returns the current scope, if it is of the specified kind. Otherwise,\n  // returns nullopt.\n  template <typename InstT>\n  auto TryGetCurrentScopeAs() -> std::optional<InstT> {\n    auto inst_id = PeekInstId();\n    if (!inst_id.has_value()) {\n      return std::nullopt;\n    }\n    return sem_ir().insts().TryGetAs<InstT>(inst_id);\n  }\n\n  // Returns the current scope, assuming it is of the specified kind.\n  // Check-fails if there is no instruction for a current scope, or the scope is\n  // of a different kind.\n  template <typename InstT>\n  auto GetCurrentScopeAs() -> InstT {\n    auto inst_id = PeekInstId();\n    CARBON_CHECK(inst_id.has_value());\n    return sem_ir().insts().GetAs<InstT>(inst_id);\n  }\n\n  // If there is no `returned var` in scope, sets the given instruction to be\n  // the current `returned var` and returns an `None`. If there\n  // is already a `returned var`, returns it instead.\n  auto SetReturnedVarOrGetExisting(SemIR::InstId inst_id, SemIR::NameId name_id)\n      -> SemIR::InstId;\n\n  // Returns the `returned var` instruction that's currently in scope, or `None`\n  // if there isn't one.\n  auto GetReturnedVar() -> SemIR::InstId {\n    CARBON_CHECK(IsInFunctionScope(), \"Handling return but not in a function\");\n    return return_scope_stack_.back().returned_var;\n  }\n\n  // Returns the decl ID for the current return scope.\n  auto GetReturnScopeDeclId() -> SemIR::InstId {\n    CARBON_CHECK(IsInFunctionScope(), \"Handling return but not in a function\");\n    return return_scope_stack_.back().decl_id;\n  }\n\n  // Looks up the name `name_id` in the current scope and enclosing scopes, but\n  // do not look past `scope_index`. Returns the existing lookup result, if any.\n  // If `use_loc_id` is specified, the name is marked as used at that location.\n  auto LookupInLexicalScopesWithin(SemIR::NameId name_id,\n                                   ScopeIndex scope_index,\n                                   SemIR::LocId use_loc_id, bool is_reachable)\n      -> SemIR::InstId;\n\n  // Looks up the name `name_id` in the current scope and related lexical\n  // scopes. Returns the innermost lexical lookup result, if any, along with a\n  // list of non-lexical scopes in which lookup should also be performed,\n  // ordered from outermost to innermost. If `use_loc_id` is specified, the\n  // name is marked as used at that location.\n  auto LookupInLexicalScopes(SemIR::NameId name_id, SemIR::LocId use_loc_id,\n                             bool is_reachable)\n      -> std::pair<SemIR::InstId, llvm::ArrayRef<NonLexicalScope>>;\n\n  // Looks up the name `name_id` in the current scope, or in `scope_index` if\n  // specified. Returns the existing instruction if the name is already declared\n  // in that scope or any unfinished scope within it, and otherwise adds the\n  // name with the value `target_id` and returns `None`. `is_decl_reachable`\n  // indicates whether the name was declared in a reachable position.\n  auto LookupOrAddName(SemIR::NameId name_id, SemIR::InstId target_id,\n                       ScopeIndex scope_index = ScopeIndex::None,\n                       bool is_decl_reachable = true) -> SemIR::InstId;\n\n  // Prepares to add a compile-time binding in the current scope, and returns\n  // its index. The added binding must then be pushed using\n  // `PushCompileTimeBinding`.\n  auto AddCompileTimeBinding() -> SemIR::CompileTimeBindIndex {\n    auto index = scope_stack_.back().next_compile_time_bind_index;\n    ++scope_stack_.back().next_compile_time_bind_index.index;\n    return index;\n  }\n\n  // Pushes a compile-time binding into the current scope.\n  auto PushCompileTimeBinding(SemIR::InstId bind_id) -> void {\n    compile_time_binding_stack_.AppendToTop(bind_id);\n  }\n\n  // Temporarily removes the top of the stack and its lexical lookup results.\n  auto Suspend() -> SuspendedScope;\n\n  // Restores a suspended scope stack entry.\n  auto Restore(SuspendedScope&& scope) -> void;\n\n  // Runs verification that the processing cleanly finished.\n  auto VerifyOnFinish() const -> void;\n\n  auto break_continue_stack() -> llvm::SmallVector<BreakContinueScope>& {\n    return break_continue_stack_;\n  }\n\n  auto destroy_id_stack() -> ArrayStack<SemIR::InstId>& {\n    return destroy_id_stack_;\n  }\n\n  auto compile_time_binding_stack() -> ArrayStack<SemIR::InstId>& {\n    return compile_time_binding_stack_;\n  }\n\n  auto full_pattern_stack() -> FullPatternStack& { return full_pattern_stack_; }\n\n private:\n  auto sem_ir() const -> const SemIR::File&;\n\n  auto lexical_lookup() -> LexicalLookup& { return lexical_lookup_; }\n\n  // An entry in scope_stack_.\n  struct ScopeStackEntry : public MoveOnly<ScopeStackEntry> {\n    auto is_lexical_scope() const -> bool { return !scope_id.has_value(); }\n\n    // The sequential index of this scope entry within the file.\n    ScopeIndex index;\n\n    // The instruction associated with this entry, if any. This can be one of:\n    //\n    // - A `ClassDecl`, for a class definition scope.\n    // - A `FunctionDecl`, for the outermost scope in a function\n    //   definition.\n    // - Invalid, for any other scope.\n    SemIR::InstId scope_inst_id;\n\n    // The name scope associated with this entry, if any.\n    SemIR::NameScopeId scope_id;\n\n    // The specific associated with this entry, if any.\n    SemIR::SpecificId specific_id;\n\n    // The next compile-time binding index to allocate in this scope.\n    SemIR::CompileTimeBindIndex next_compile_time_bind_index;\n\n    // Whether lexical_lookup_ has load errors from this scope or an ancestor\n    // scope.\n    bool lexical_lookup_has_load_error;\n\n    // Whether a `returned var` was introduced in this scope, and needs to be\n    // unregistered when the scope ends.\n    bool has_returned_var = false;\n\n    // Whether there are any ids in the `names` set.\n    int num_names = 0;\n\n    // Names which are registered with lexical_lookup_, and will need to be\n    // unregistered when the scope ends.\n    Set<SemIR::NameId> names = {};\n  };\n\n  // A scope in which `return` can be used.\n  struct ReturnScope {\n    // The `FunctionDecl`.\n    SemIR::InstId decl_id;\n\n    // The value corresponding to the current `returned var`, if any. Will be\n    // set and unset as `returned var`s are declared and go out of scope.\n    SemIR::InstId returned_var = SemIR::InstId::None;\n\n    // When a nested scope interrupts a return scope, this is the index of the\n    // outermost interrupting scope (the one closest to the function scope).\n    // This can then be used to determine whether we're actually inside the most\n    // recent `ReturnScope`, or inside a different entity scope.\n    //\n    // This won't be set for functions directly inside functions, because they\n    // will have their own `ReturnScope`.\n\n    // For example, when a `class` is inside a `fn`, it interrupts the function\n    // body by setting this on `PushEntity`; `Pop` will set it back to `None`.\n    ScopeIndex nested_scope_index = ScopeIndex::None;\n  };\n\n  // Pushes a scope onto scope_stack_. NameScopeId::None is used for new scopes.\n  // lexical_lookup_has_load_error is used to limit diagnostics when a given\n  // namespace may contain a mix of both successful and failed name imports.\n  auto Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,\n            SemIR::SpecificId specific_id, bool lexical_lookup_has_load_error)\n      -> void;\n\n  auto Peek() const -> const ScopeStackEntry& { return scope_stack_.back(); }\n\n  // Returns whether lexical lookup currently has any load errors.\n  auto LexicalLookupHasLoadError() const -> bool {\n    return !scope_stack_.empty() &&\n           scope_stack_.back().lexical_lookup_has_load_error;\n  }\n\n  // If inside a return scope, marks a nested scope (see `nested_scope_index`).\n  // Called after pushing the new scope.\n  auto MarkNestingIfInReturnScope() -> void {\n    if (!return_scope_stack_.empty() &&\n        !return_scope_stack_.back().nested_scope_index.has_value()) {\n      return_scope_stack_.back().nested_scope_index = scope_stack_.back().index;\n    }\n  }\n\n  // Marks the name `name_id` as used at the given location.\n  auto MarkUsed(SemIR::NameId name_id, SemIR::LocId loc_id, bool is_reachable)\n      -> void;\n\n  // Checks that the provided scope's `next_compile_time_bind_index` matches the\n  // full size of the current `compile_time_binding_stack_`. The values should\n  // always match, and this is used to validate the correspondence during\n  // significant changes.\n  auto VerifyNextCompileTimeBindIndex(llvm::StringLiteral label,\n                                      const ScopeStackEntry& scope) -> void;\n\n  // Context, used only for checks and emitting diagnostics.\n  Context* context_;\n\n  // A stack of scopes from which we can `return`.\n  llvm::SmallVector<ReturnScope> return_scope_stack_;\n\n  // A stack of `break` and `continue` targets.\n  llvm::SmallVector<BreakContinueScope> break_continue_stack_;\n\n  // A stack for scope context.\n  llvm::SmallVector<ScopeStackEntry> scope_stack_;\n\n  // A stack of instances to destroy. This only has entries inside of function\n  // bodies, where destruction on scope exit is required.\n  ArrayStack<SemIR::InstId> destroy_id_stack_;\n\n  // Information about non-lexical scopes. This is a subset of the entries and\n  // the information in scope_stack_.\n  llvm::SmallVector<NonLexicalScope> non_lexical_scope_stack_;\n\n  // A stack of the current compile time bindings.\n  ArrayStack<SemIR::InstId> compile_time_binding_stack_;\n\n  // The index of the next scope that will be pushed onto scope_stack_. The\n  // first is always the package scope.\n  ScopeIndex next_scope_index_ = ScopeIndex::Package;\n\n  // Tracks lexical lookup results.\n  LexicalLookup lexical_lookup_;\n\n  // Stack of full-patterns currently being checked.\n  FullPatternStack full_pattern_stack_;\n};\n\nstruct ScopeStack::SuspendedScope : public MoveOnly<SuspendedScope> {\n  // An item that was suspended within this scope. This represents either a\n  // lexical lookup entry in this scope, or a compile time binding entry in this\n  // scope.\n  //\n  // TODO: For compile-time bindings, the common case is that they will both\n  // have a suspended lexical lookup entry and a suspended compile time binding\n  // entry. We should be able to store that as a single ScopeItem rather than\n  // two.\n  struct ScopeItem {\n    static constexpr uint32_t IndexForCompileTimeBinding = -1;\n\n    // The scope index for a LexicalLookup::SuspendedResult, or\n    // CompileTimeBindingIndex for a suspended compile time binding.\n    uint32_t index;\n    // The instruction within the scope.\n    SemIR::InstId inst_id;\n    // Whether the name was declared in a reachable position.\n    bool is_decl_reachable;\n    // The location of the first use of the name, if any.\n    SemIR::LocId use_loc_id;\n  };\n\n  // The suspended scope stack entry.\n  ScopeStackEntry entry;\n  // The list of items that were within this scope when it was suspended. The\n  // inline size is an attempt to keep the size of a `SuspendedFunction`\n  // reasonable while avoiding heap allocations most of the time.\n  llvm::SmallVector<ScopeItem, 8> suspended_items;\n};\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_SCOPE_STACK_H_\n"
  },
  {
    "path": "toolchain/check/subst.cpp",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#include \"toolchain/check/subst.h\"\n\n#include \"toolchain/base/kind_switch.h\"\n#include \"toolchain/check/eval.h\"\n#include \"toolchain/check/generic.h\"\n#include \"toolchain/check/inst.h\"\n#include \"toolchain/sem_ir/copy_on_write_block.h\"\n#include \"toolchain/sem_ir/ids.h\"\n#include \"toolchain/sem_ir/inst.h\"\n#include \"toolchain/sem_ir/typed_insts.h\"\n\nnamespace Carbon::Check {\n\nauto SubstInstCallbacks::RebuildType(SemIR::TypeInstId type_inst_id) const\n    -> SemIR::TypeId {\n  return context().types().GetTypeIdForTypeInstId(type_inst_id);\n}\n\nauto SubstInstCallbacks::RebuildNewInst(SemIR::LocId loc_id,\n                                        SemIR::Inst new_inst) const\n    -> SemIR::InstId {\n  auto const_id = EvalOrAddInst(\n      context(), SemIR::LocIdAndInst::UncheckedLoc(loc_id, new_inst));\n  CARBON_CHECK(const_id.has_value(),\n               \"Substitution into constant produced non-constant\");\n  CARBON_CHECK(const_id.is_constant(),\n               \"Substitution into constant produced runtime value\");\n  return context().constant_values().GetInstId(const_id);\n}\n\nnamespace {\n\n// Information about an instruction that we are substituting into.\nstruct WorklistItem {\n  // The instruction that we are substituting into.\n  SemIR::InstId inst_id;\n  // Whether the operands of this instruction have been added to the worklist.\n  bool is_expanded : 1;\n  // Whether the instruction was subst'd and re-added to the worklist.\n  bool is_repeated : 1;\n  // The index of the worklist item to process after we finish updating this\n  // one. For the final child of an instruction, this is the parent. For any\n  // other child, this is the index of the next child of the parent. For the\n  // root, this is -1.\n  int next_index : 31;\n};\n\n// A list of instructions that we're currently in the process of substituting\n// into. For details of the algorithm used here, see `SubstConstant`.\nclass Worklist {\n public:\n  explicit Worklist(SemIR::InstId root_id) {\n    worklist_.push_back({.inst_id = root_id,\n                         .is_expanded = false,\n                         .is_repeated = false,\n                         .next_index = -1});\n  }\n\n  auto operator[](int index) -> WorklistItem& { return worklist_[index]; }\n  auto size() -> int { return worklist_.size(); }\n  auto back() -> WorklistItem& { return worklist_.back(); }\n\n  auto Push(SemIR::InstId inst_id) -> void {\n    CARBON_CHECK(inst_id.has_value());\n    worklist_.push_back({.inst_id = inst_id,\n                         .is_expanded = false,\n                         .is_repeated = false,\n                         .next_index = static_cast<int>(worklist_.size() + 1)});\n    CARBON_CHECK(worklist_.back().next_index > 0, \"Constant too large.\");\n  }\n  auto Pop() -> SemIR::InstId { return worklist_.pop_back_val().inst_id; }\n\n private:\n  // Constants can get pretty large, so use a large worklist. This should be\n  // about 4KiB, which should be small enough to comfortably fit on the stack,\n  // but large enough that it's unlikely that we'll need a heap allocation.\n  llvm::SmallVector<WorklistItem, 512> worklist_;\n};\n\n}  // namespace\n\n// Pushes the specified operand onto the worklist.\nstatic auto PushOperand(Context& context, Worklist& worklist,\n                        SemIR::Inst::ArgAndKind arg) -> void {\n  auto push_block = [&](SemIR::InstBlockId block_id) {\n    for (auto inst_id :\n         context.inst_blocks().Get(SemIR::InstBlockId(block_id))) {\n      worklist.Push(inst_id);\n    }\n  };\n\n  auto push_specific = [&](SemIR::SpecificId specific_id) {\n    if (specific_id.has_value()) {\n      push_block(context.specifics().Get(specific_id).args_id);\n    }\n  };\n\n  CARBON_KIND_SWITCH(arg) {\n    case CARBON_KIND(SemIR::InstId inst_id): {\n      if (inst_id.has_value()) {\n        worklist.Push(inst_id);\n      }\n      break;\n    }\n    case CARBON_KIND(SemIR::TypeInstId inst_id): {\n      if (inst_id.has_value()) {\n        worklist.Push(inst_id);\n      }\n      break;\n    }\n    case CARBON_KIND(SemIR::InstBlockId inst_block_id): {\n      push_block(inst_block_id);\n      break;\n    }\n    case CARBON_KIND(SemIR::StructTypeFieldsId fields_id): {\n      for (auto field : context.struct_type_fields().Get(fields_id)) {\n        worklist.Push(field.type_inst_id);\n      }\n      break;\n    }\n    case CARBON_KIND(SemIR::SpecificId specific_id): {\n      push_specific(specific_id);\n      break;\n    }\n    case CARBON_KIND(SemIR::SpecificInterfaceId interface_id): {\n      auto interface = context.specific_interfaces().Get(interface_id);\n      push_specific(interface.specific_id);\n      break;\n    }\n    case CARBON_KIND(SemIR::FacetTypeId facet_type_id): {\n      const auto& facet_type_info = context.facet_types().Get(facet_type_id);\n      for (auto interface : facet_type_info.extend_constraints) {\n        push_specific(interface.specific_id);\n      }\n      for (auto interface : facet_type_info.self_impls_constraints) {\n        push_specific(interface.specific_id);\n      }\n      for (auto interface : facet_type_info.extend_named_constraints) {\n        push_specific(interface.specific_id);\n      }\n      for (auto interface : facet_type_info.self_impls_named_constraints) {\n        push_specific(interface.specific_id);\n      }\n      for (auto rewrite : facet_type_info.rewrite_constraints) {\n        worklist.Push(rewrite.lhs_id);\n        worklist.Push(rewrite.rhs_id);\n      }\n      // TODO: Process other requirements as well.\n      break;\n    }\n    default:\n      break;\n  }\n}\n\n// Converts the operands of this instruction into `InstId`s and pushes them onto\n// the worklist.\nstatic auto ExpandOperands(Context& context, Worklist& worklist,\n                           SemIR::InstId inst_id) -> void {\n  auto inst = context.insts().Get(inst_id);\n  if (inst.type_id().has_value()) {\n    worklist.Push(context.types().GetTypeInstId(inst.type_id()));\n  }\n  PushOperand(context, worklist, inst.arg0_and_kind());\n  PushOperand(context, worklist, inst.arg1_and_kind());\n}\n\n// Pops the specified operand from the worklist and returns it.\nstatic auto PopOperand(Context& context, Worklist& worklist,\n                       SemIR::Inst::ArgAndKind arg) -> int32_t {\n  auto pop_block_id = [&](SemIR::InstBlockId old_inst_block_id) {\n    auto size = context.inst_blocks().Get(old_inst_block_id).size();\n    SemIR::CopyOnWriteInstBlock new_inst_block(&context.sem_ir(),\n                                               old_inst_block_id);\n    for (auto i : llvm::reverse(llvm::seq(size))) {\n      new_inst_block.Set(i, worklist.Pop());\n    }\n    return new_inst_block.GetCanonical();\n  };\n\n  auto pop_specific = [&](SemIR::SpecificId specific_id) {\n    if (!specific_id.has_value()) {\n      return specific_id;\n    }\n    auto& specific = context.specifics().Get(specific_id);\n    auto args_id = pop_block_id(specific.args_id);\n    return context.specifics().GetOrAdd(specific.generic_id, args_id);\n  };\n\n  CARBON_KIND_SWITCH(arg) {\n    case CARBON_KIND(SemIR::InstId inst_id): {\n      if (!inst_id.has_value()) {\n        return arg.value();\n      }\n      return worklist.Pop().index;\n    }\n    case CARBON_KIND(SemIR::TypeInstId inst_id): {\n      if (!inst_id.has_value()) {\n        return arg.value();\n      }\n      return worklist.Pop().index;\n    }\n    case CARBON_KIND(SemIR::InstBlockId inst_block_id): {\n      return pop_block_id(inst_block_id).index;\n    }\n    case CARBON_KIND(SemIR::StructTypeFieldsId old_fields_id): {\n      auto old_fields = context.struct_type_fields().Get(old_fields_id);\n      SemIR::CopyOnWriteStructTypeFieldsBlock new_fields(&context.sem_ir(),\n                                                         old_fields_id);\n      for (auto i : llvm::reverse(llvm::seq(old_fields.size()))) {\n        new_fields.Set(\n            i,\n            {.name_id = old_fields[i].name_id,\n             .type_inst_id = context.types().GetAsTypeInstId(worklist.Pop())});\n      }\n      return new_fields.GetCanonical().index;\n    }\n    case CARBON_KIND(SemIR::SpecificId specific_id): {\n      return pop_specific(specific_id).index;\n    }\n    case CARBON_KIND(SemIR::SpecificInterfaceId interface_id): {\n      auto interface = context.specific_interfaces().Get(interface_id);\n      auto specific_id = pop_specific(interface.specific_id);\n      return context.specific_interfaces()\n          .Add({\n              .interface_id = interface.interface_id,\n              .specific_id = specific_id,\n          })\n          .index;\n    }\n    case CARBON_KIND(SemIR::FacetTypeId facet_type_id): {\n      const auto& old_facet_type_info =\n          context.facet_types().Get(facet_type_id);\n      SemIR::FacetTypeInfo new_facet_type_info = {\n          .other_requirements = old_facet_type_info.other_requirements};\n      // Since these were added to a stack, we get them back in reverse order.\n      new_facet_type_info.rewrite_constraints.resize(\n          old_facet_type_info.rewrite_constraints.size(),\n          SemIR::FacetTypeInfo::RewriteConstraint::None);\n      for (auto& new_constraint :\n           llvm::reverse(new_facet_type_info.rewrite_constraints)) {\n        auto rhs_id = worklist.Pop();\n        auto lhs_id = worklist.Pop();\n        new_constraint = {.lhs_id = lhs_id, .rhs_id = rhs_id};\n      }\n      new_facet_type_info.self_impls_named_constraints.resize(\n          old_facet_type_info.self_impls_named_constraints.size(),\n          SemIR::SpecificNamedConstraint::None);\n      for (auto [old_constraint, new_constraint] :\n           llvm::reverse(llvm::zip_equal(\n               old_facet_type_info.self_impls_named_constraints,\n               new_facet_type_info.self_impls_named_constraints))) {\n        new_constraint = {\n            .named_constraint_id = old_constraint.named_constraint_id,\n            .specific_id = pop_specific(old_constraint.specific_id)};\n      }\n      new_facet_type_info.extend_named_constraints.resize(\n          old_facet_type_info.extend_named_constraints.size(),\n          SemIR::SpecificNamedConstraint::None);\n      for (auto [old_constraint, new_constraint] : llvm::reverse(\n               llvm::zip_equal(old_facet_type_info.extend_named_constraints,\n                               new_facet_type_info.extend_named_constraints))) {\n        new_constraint = {\n            .named_constraint_id = old_constraint.named_constraint_id,\n            .specific_id = pop_specific(old_constraint.specific_id)};\n      }\n      new_facet_type_info.self_impls_constraints.resize(\n          old_facet_type_info.self_impls_constraints.size(),\n          SemIR::SpecificInterface::None);\n      for (auto [old_constraint, new_constraint] : llvm::reverse(\n               llvm::zip_equal(old_facet_type_info.self_impls_constraints,\n                               new_facet_type_info.self_impls_constraints))) {\n        new_constraint = {\n            .interface_id = old_constraint.interface_id,\n            .specific_id = pop_specific(old_constraint.specific_id)};\n      }\n      new_facet_type_info.extend_constraints.resize(\n          old_facet_type_info.extend_constraints.size(),\n          SemIR::SpecificInterface::None);\n      for (auto [old_constraint, new_constraint] : llvm::reverse(\n               llvm::zip_equal(old_facet_type_info.extend_constraints,\n                               new_facet_type_info.extend_constraints))) {\n        new_constraint = {\n            .interface_id = old_constraint.interface_id,\n            .specific_id = pop_specific(old_constraint.specific_id)};\n      }\n      new_facet_type_info.Canonicalize();\n      return context.facet_types().Add(new_facet_type_info).index;\n    }\n    default:\n      return arg.value();\n  }\n}\n\n// Pops the operands of the specified instruction off the worklist and rebuilds\n// the instruction with the updated operands if it has changed.\nstatic auto Rebuild(Context& context, Worklist& worklist, SemIR::InstId inst_id,\n                    SubstInstCallbacks& callbacks) -> SemIR::InstId {\n  auto inst = context.insts().Get(inst_id);\n\n  // Note that we pop in reverse order because we pushed them in forwards order.\n  int32_t arg1 = PopOperand(context, worklist, inst.arg1_and_kind());\n  int32_t arg0 = PopOperand(context, worklist, inst.arg0_and_kind());\n  auto type_id = inst.type_id().has_value()\n                     ? callbacks.RebuildType(\n                           context.types().GetAsTypeInstId(worklist.Pop()))\n                     : SemIR::TypeId::None;\n  if (type_id == inst.type_id() && arg0 == inst.arg0() && arg1 == inst.arg1()) {\n    return callbacks.ReuseUnchanged(inst_id);\n  }\n\n  // TODO: Do we need to require this type to be complete?\n  inst.SetType(type_id);\n  inst.SetArgs(arg0, arg1);\n  return callbacks.Rebuild(inst_id, inst);\n}\n\nauto SubstInst(Context& context, SemIR::InstId inst_id,\n               SubstInstCallbacks& callbacks) -> SemIR::InstId {\n  Worklist worklist(inst_id);\n\n  // For each instruction that forms part of the constant, we will visit it\n  // twice:\n  //\n  // - First, we visit it with `is_expanded == false`, we add all of its\n  //   operands onto the worklist, and process them by following this same\n  //   process.\n  // - Then, once all operands are processed, we visit the instruction with\n  //   `is_expanded == true`, pop the operands back off the worklist, and if any\n  //   of them changed, rebuild this instruction.\n  //\n  // The second step is skipped if we can detect in the first step that the\n  // instruction will not need to be rebuilt.\n  int index = 0;\n  while (index != -1) {\n    auto& item = worklist[index];\n\n    if (item.is_expanded) {\n      // Rebuild this item if necessary. Note that this might pop items from the\n      // worklist but does not reallocate, so does not invalidate `item`.\n      auto old_inst_id = std::exchange(\n          item.inst_id, Rebuild(context, worklist, item.inst_id, callbacks));\n      if (item.is_repeated && old_inst_id != item.inst_id) {\n        // SubstOperandsAndRetry was returned for the item, and the instruction\n        // was rebuilt from new operands, so go through Subst() again. Note that\n        // we've already called Rebuild so we don't want to leave this item as\n        // repeated, and call back to ReuseUnchanged for it again later unless\n        // the next call to Subst() asks for that.\n        item.is_expanded = false;\n        item.is_repeated = false;\n      } else {\n        index = item.next_index;\n        continue;\n      }\n    }\n\n    if (item.is_repeated) {\n      // SubstAgain was returned for the item, and the result of that Subst() is\n      // at the back of the worklist, which we pop. Note that popping from the\n      // worklist does not reallocate, so does not invalidate `item`.\n      //\n      // When Subst returns SubstAgain, we must call back to Rebuild or\n      // ReuseUnchanged for that work item.\n      item.inst_id = callbacks.ReuseUnchanged(worklist.Pop());\n      index = item.next_index;\n      continue;\n    }\n\n    switch (callbacks.Subst(item.inst_id)) {\n      case SubstInstCallbacks::SubstResult::FullySubstituted:\n        // If any instruction is an ErrorInst, combining it into another\n        // instruction will also produce an ErrorInst, so shortcut out here to\n        // save wasted work.\n        if (item.inst_id == SemIR::ErrorInst::InstId) {\n          return SemIR::ErrorInst::InstId;\n        }\n        index = item.next_index;\n        continue;\n      case SubstInstCallbacks::SubstResult::SubstAgain: {\n        item.is_repeated = true;\n\n        // This modifies `worklist` which invalidates `item`.\n        worklist.Push(item.inst_id);\n        worklist.back().next_index = index;\n        index = worklist.size() - 1;\n        continue;\n      }\n      case SubstInstCallbacks::SubstResult::SubstOperands:\n        break;\n      case SubstInstCallbacks::SubstResult::SubstOperandsAndRetry:\n        item.is_repeated = true;\n        break;\n    }\n\n    // Extract the operands of this item into the worklist. Note that this\n    // modifies the worklist, so it's not safe to use `item` after\n    // `ExpandOperands` returns.\n    item.is_expanded = true;\n    int first_operand = worklist.size();\n    int next_index = item.next_index;\n    ExpandOperands(context, worklist, item.inst_id);\n\n    // If there are any operands, go and update them before rebuilding this\n    // item.\n    if (worklist.size() > first_operand) {\n      worklist.back().next_index = index;\n      index = first_operand;\n    } else {\n      // No need to rebuild this instruction: its operands can't be changed by\n      // substitution because it has none.\n      item.inst_id = callbacks.ReuseUnchanged(item.inst_id);\n      index = next_index;\n    }\n  }\n\n  CARBON_CHECK(worklist.size() == 1,\n               \"Unexpected data left behind in work list\");\n  return worklist.back().inst_id;\n}\n\nauto SubstInst(Context& context, SemIR::TypeInstId inst_id,\n               SubstInstCallbacks& callbacks) -> SemIR::TypeInstId {\n  return context.types().GetAsTypeInstId(\n      SubstInst(context, static_cast<SemIR::InstId>(inst_id), callbacks));\n}\n\nnamespace {\n// Callbacks for performing substitution of a set of Substitutions into a\n// symbolic constant.\nclass SubstConstantCallbacks final : public SubstInstCallbacks {\n public:\n  // `context` must not be null.\n  SubstConstantCallbacks(Context* context, SemIR::LocId loc_id,\n                         Substitutions substitutions)\n      : SubstInstCallbacks(context),\n        loc_id_(loc_id),\n        substitutions_(substitutions) {}\n\n  // Applies the given Substitutions to an instruction, in order to replace\n  // SymbolicBinding instructions with the value of the binding.\n  auto Subst(SemIR::InstId& inst_id) -> SubstResult override {\n    if (context().constant_values().Get(inst_id).is_concrete()) {\n      // This instruction is a concrete constant, so can't contain any\n      // bindings that need to be substituted.\n      return SubstResult::FullySubstituted;\n    }\n\n    // A symbolic binding `as type` contains the EntityNameId of that symbolic\n    // binding. If it matches a substitution, then we want to point the\n    // EntityNameId to the substitution facet value.\n    if (auto bind =\n            context().insts().TryGetAs<SemIR::SymbolicBindingType>(inst_id)) {\n      auto& entity_name = context().entity_names().Get(bind->entity_name_id);\n\n      for (auto [bind_index, replacement_id] : substitutions_) {\n        if (entity_name.bind_index() == bind_index) {\n          auto replacement_inst_id =\n              context().constant_values().GetInstId(replacement_id);\n          inst_id = RebuildNewInst<SemIR::FacetAccessType>(\n              loc_id_, {\n                           .type_id = SemIR::TypeType::TypeId,\n                           .facet_value_inst_id = replacement_inst_id,\n                       });\n          return SubstResult::FullySubstituted;\n        }\n      }\n    }\n\n    auto entity_name_id = SemIR::EntityNameId::None;\n    if (auto bind =\n            context().insts().TryGetAs<SemIR::SymbolicBinding>(inst_id)) {\n      entity_name_id = bind->entity_name_id;\n    } else if (auto bind =\n                   context().insts().TryGetAs<SemIR::SymbolicBindingPattern>(\n                       inst_id)) {\n      entity_name_id = bind->entity_name_id;\n    } else {\n      return SubstResult::SubstOperands;\n    }\n\n    auto& entity_name = context().entity_names().Get(entity_name_id);\n\n    // This is a symbolic binding. Check if we're substituting it.\n    // TODO: Consider building a hash map for substitutions. We might have a\n    // lot of them.\n    for (auto [bind_index, replacement_id] : substitutions_) {\n      if (entity_name.bind_index() == bind_index) {\n        // This is the binding we're replacing. Perform substitution.\n        inst_id = context().constant_values().GetInstId(replacement_id);\n        return SubstResult::FullySubstituted;\n      }\n    }\n\n    // If it's not being substituted, we still need to look through it, as we\n    // may need to substitute into its type (a `FacetType`, with one or more\n    // `SpecificInterfaces` within).\n    return SubstResult::SubstOperands;\n  }\n\n  // Rebuilds an instruction by building a new constant.\n  auto Rebuild(SemIR::InstId /*old_inst_id*/, SemIR::Inst new_inst)\n      -> SemIR::InstId override {\n    return RebuildNewInst(loc_id_, new_inst);\n  }\n\n private:\n  SemIR::LocId loc_id_;\n  Substitutions substitutions_;\n};\n}  // namespace\n\nauto SubstConstant(Context& context, SemIR::LocId loc_id,\n                   SemIR::ConstantId const_id, Substitutions substitutions)\n    -> SemIR::ConstantId {\n  CARBON_CHECK(const_id.is_constant(), \"Substituting into non-constant\");\n\n  if (substitutions.empty()) {\n    // Nothing to substitute.\n    return const_id;\n  }\n\n  if (!const_id.is_symbolic()) {\n    // A concrete constant can't contain a reference to a symbolic binding.\n    return const_id;\n  }\n\n  auto callbacks = SubstConstantCallbacks(&context, loc_id, substitutions);\n  auto subst_inst_id = SubstInst(\n      context, context.constant_values().GetInstId(const_id), callbacks);\n  return context.constant_values().Get(subst_inst_id);\n}\n\n}  // namespace Carbon::Check\n"
  },
  {
    "path": "toolchain/check/subst.h",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n\n#ifndef CARBON_TOOLCHAIN_CHECK_SUBST_H_\n#define CARBON_TOOLCHAIN_CHECK_SUBST_H_\n\n#include \"toolchain/check/context.h\"\n#include \"toolchain/sem_ir/ids.h\"\n\nnamespace Carbon::Check {\n\n// Callbacks used by SubstInst to recursively substitute into and rebuild an\n// instruction.\nclass SubstInstCallbacks {\n public:\n  explicit SubstInstCallbacks(Context* context) : context_(context) {}\n\n  auto context() const -> Context& { return *context_; }\n\n  // How further substitution should or should not be applied to the instruction\n  // after Subst is done.\n  //\n  // Rebuild or ReuseUnchaged will always be called when SubstAgain or\n  // SubstOperands is returned, after processing anything inside the instruction\n  // after Subst.\n  enum SubstResult {\n    // Don't substitute into the operands of the instruction.\n    FullySubstituted,\n    // Attempt to substitute into the operands of the instruction.\n    SubstOperands,\n    // Attempt to substitute again on the resulting instruction, acting like\n    // recursion on the instruction itself.\n    SubstAgain,\n    // Attempt to substitute into the operands of the instruction. If the InstId\n    // returned from Rebuild or ReuseUnchanged differs from the input (typically\n    // because some operand in the instruction changed), then the new\n    // instruction will be given to `Subst` again afterward. This allows for the\n    // uncommon case of substituting from the inside out.\n    SubstOperandsAndRetry,\n  };\n\n  // Performs any needed substitution into an instruction. The instruction ID\n  // should be updated as necessary to represent the new instruction.\n  //\n  // Return FullySubstituted if the resulting instruction ID is\n  // fully-substituted. Return SubstOperands if substitution may be needed into\n  // operands of the instruction, or SubstAgain if the replaced instruction\n  // itself should have substitution applied to it again. Return\n  // SubstOperandsAndRetry to recurse on the instructions operands and then\n  // substitute the resulting instruction afterward, if the instruction is\n  // replaced by a new one (typically due to Rebuild when the operands changed).\n  //\n  // When SubstOperands, SubstAgain, or SubstOperandsAndRetry is returned, it\n  // results in a call back to Rebuild or ReuseUnchanged when that instruction's\n  // substitution step is complete.\n  virtual auto Subst(SemIR::InstId& inst_id) -> SubstResult = 0;\n\n  // Rebuilds the type of an instruction from the substituted type instruction.\n  // By default this builds the unattached type described by the given type ID.\n  virtual auto RebuildType(SemIR::TypeInstId type_inst_id) const\n      -> SemIR::TypeId;\n\n  // Rebuilds an instruction whose operands were changed by substitution.\n  // `orig_inst_id` is the instruction prior to substitution, and `new_inst` is\n  // the substituted instruction. Returns the new instruction ID to use to refer\n  // to `new_inst`.\n  virtual auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst)\n      -> SemIR::InstId = 0;\n\n  // Performs any work needed when no substitutions were performed into an\n  // instruction for which `Subst` returned `false`. Provides an opportunity to\n  // perform any necessary updates to the instruction beyond updating its\n  // operands. Returns the new instruction ID to use to refer to `orig_inst_id`.\n  virtual auto ReuseUnchanged(SemIR::InstId orig_inst_id) -> SemIR::InstId {\n    return orig_inst_id;\n  }\n\n  // Builds a new constant by evaluating `new_inst`, and returns its `InstId`.\n  //\n  // This can be used to implement `Rebuild` in straightforward cases.\n  auto RebuildNewInst(SemIR::LocId loc_id, SemIR::Inst new_inst) const\n      -> SemIR::InstId;\n\n  template <typename InstT>\n  auto RebuildNewInst(SemIR::LocId loc_id, InstT new_inst) const\n      -> SemIR::InstId {\n    return RebuildNewInst(loc_id, static_cast<SemIR::Inst>(new_inst));\n  }\n\n private:\n  Context* context_;\n};\n\n// Performs substitution into `inst_id` and its operands recursively, using\n// `callbacks` to process each instruction. For each instruction encountered,\n// calls `Subst` to perform substitution on that instruction.\nauto SubstInst(Context& context, SemIR::InstId inst_id,\n               SubstInstCallbacks& callbacks) -> SemIR::InstId;\nauto SubstInst(Context& context, SemIR::TypeInstId inst_id,\n               SubstInstCallbacks& callbacks) -> SemIR::TypeInstId;\n\n// A substitution that is being performed.\nstruct Substitution {\n  // The index of a `SymbolicBinding` instruction that is being replaced.\n  SemIR::CompileTimeBindIndex bind_id;\n  // The replacement constant value to substitute.\n  SemIR::ConstantId replacement_id;\n};\n\nusing Substitutions = llvm::ArrayRef<Substitution>;\n\n// Replaces the `SymbolicBinding` instruction `bind_id` with `replacement_id`\n// throughout the constant `const_id`, and returns the substituted value.\nauto SubstConstant(Context& context, SemIR::LocId loc_id,\n                   SemIR::ConstantId const_id, Substitutions substitutions)\n    -> SemIR::ConstantId;\n\n}  // namespace Carbon::Check\n\n#endif  // CARBON_TOOLCHAIN_CHECK_SUBST_H_\n"
  },
  {
    "path": "toolchain/check/testdata/alias/basics.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/alias/basics.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/basics.carbon\n\n// --- alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {};\n\n//@dump-sem-ir-begin\nalias c = C;\n//@dump-sem-ir-end\n\nlet l: c = {};\n\n// --- alias_of_alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\n//@dump-sem-ir-begin\nalias a = C;\nalias b = a;\nalias c = b;\nlet d: c = {};\n//@dump-sem-ir-end\n\n// --- fail_control_flow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_control_flow.carbon:[[@LINE+8]]:11: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n// CHECK:STDERR: alias a = true or false;\n// CHECK:STDERR:           ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_control_flow.carbon:[[@LINE+4]]:11: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n// CHECK:STDERR: alias a = true or false;\n// CHECK:STDERR:           ^~~~~~~~~~~~~\n// CHECK:STDERR:\nalias a = true or false;\n\n// --- fail_name_conflict.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nalias a = C;\n// CHECK:STDERR: fail_name_conflict.carbon:[[@LINE+7]]:5: error: duplicate name `a` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: var a: C = {};\n// CHECK:STDERR:     ^\n// CHECK:STDERR: fail_name_conflict.carbon:[[@LINE-4]]:7: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: alias a = C;\n// CHECK:STDERR:       ^\n// CHECK:STDERR:\nvar a: C = {};\n\nvar b: C = {};\n// CHECK:STDERR: fail_name_conflict.carbon:[[@LINE+7]]:7: error: duplicate name `b` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: alias b = C;\n// CHECK:STDERR:       ^\n// CHECK:STDERR: fail_name_conflict.carbon:[[@LINE-4]]:5: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: var b: C = {};\n// CHECK:STDERR:     ^\n// CHECK:STDERR:\nalias b = C;\n\n// --- fail_not_constant.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nvar a: () = ();\nvar b: ()* = &a;\n\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE+4]]:11: error: alias initializer must be a name reference [AliasRequiresNameRef]\n// CHECK:STDERR: alias c = *b;\n// CHECK:STDERR:           ^~\n// CHECK:STDERR:\nalias c = *b;\n\n// --- fail_params.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_params.carbon:[[@LINE+8]]:8: error: `alias` declaration cannot have parameters [UnexpectedDeclNameParams]\n// CHECK:STDERR: alias A(T:! type) = T*;\n// CHECK:STDERR:        ^~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_params.carbon:[[@LINE+4]]:21: error: alias initializer must be a name reference [AliasRequiresNameRef]\n// CHECK:STDERR: alias A(T:! type) = T*;\n// CHECK:STDERR:                     ^~\n// CHECK:STDERR:\nalias A(T:! type) = T*;\n\n// --- fail_modifiers.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class {}\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+25]]:10: error: `base` not allowed on declaration with `abstract` [ModifierNotAllowedWith]\n// CHECK:STDERR: abstract base default final alias A = Class;\n// CHECK:STDERR:          ^~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+22]]:1: note: `abstract` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: abstract base default final alias A = Class;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+18]]:15: error: `default` not allowed on declaration with `abstract` [ModifierNotAllowedWith]\n// CHECK:STDERR: abstract base default final alias A = Class;\n// CHECK:STDERR:               ^~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+15]]:1: note: `abstract` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: abstract base default final alias A = Class;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:23: error: `final` not allowed on declaration with `abstract` [ModifierNotAllowedWith]\n// CHECK:STDERR: abstract base default final alias A = Class;\n// CHECK:STDERR:                       ^~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+8]]:1: note: `abstract` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: abstract base default final alias A = Class;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `alias` declaration [ModifierNotAllowedOnDeclaration]\n// CHECK:STDERR: abstract base default final alias A = Class;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nabstract base default final alias A = Class;\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `impl` not allowed on `alias` declaration [ModifierNotAllowedOnDeclaration]\n// CHECK:STDERR: impl alias B = Class;\n// CHECK:STDERR: ^~~~\n// CHECK:STDERR:\nimpl alias B = Class;\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `extern` not allowed on `alias` declaration [ModifierNotAllowedOnDeclaration]\n// CHECK:STDERR: extern alias C = Class;\n// CHECK:STDERR: ^~~~~~\n// CHECK:STDERR:\nextern alias C = Class;\n\n// CHECK:STDOUT: --- alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c: type = alias_binding c, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- alias_of_alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %a: type = alias_binding a, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %a.ref: type = name_ref a, %a [concrete = constants.%C]\n// CHECK:STDOUT:   %b: type = alias_binding b, %a [concrete = constants.%C]\n// CHECK:STDOUT:   %b.ref: type = name_ref b, %b [concrete = constants.%C]\n// CHECK:STDOUT:   %c: type = alias_binding c, %b [concrete = constants.%C]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type = value_binding_pattern d [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.ref: type = name_ref c, %c [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc10_13.1: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc10_13.2: init %C to %.loc10_13.1 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc10_13.3: init %C = converted @__global_init.%.loc10, %.loc10_13.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc10_13.4: ref %C = temporary %.loc10_13.1, %.loc10_13.3\n// CHECK:STDOUT:   %.loc10_13.5: %C = acquire_value %.loc10_13.4\n// CHECK:STDOUT:   %d: %C = value_binding d, %.loc10_13.5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/alias/builtins.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/alias/builtins.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/builtins.carbon\n\n// --- i32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nalias a = i32;\n//@dump-sem-ir-end\n\n// --- bool.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nalias b = bool;\n//@dump-sem-ir-end\n\n// --- fail_bool_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_bool_value.carbon:[[@LINE+4]]:11: error: alias initializer must be a name reference [AliasRequiresNameRef]\n// CHECK:STDERR: alias a = false;\n// CHECK:STDERR:           ^~~~~\n// CHECK:STDERR:\nalias a = false;\n\n// This fails silently due to the above diagnostic.\nlet a_test: bool = a;\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- i32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %a: type = alias_binding a, constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- bool.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %.loc5: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:   %b: type = alias_binding b, bool [concrete = bool]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_bool_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:   %a: <error> = alias_binding a, <error> [concrete = <error>]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a_test.patt: %pattern_type.831 = value_binding_pattern a_test [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc12: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:   %a_test: bool = value_binding a_test, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: <error> = name_ref a, file.%a [concrete = <error>]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/alias/export_name.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/alias/export_name.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/export_name.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\n// --- export.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"base\";\n\nexport D;\n\n// --- export_orig.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"base\";\n\nexport C;\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- use_export.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"export\";\n\nvar d: D = {};\n\n// --- fail_orig_name_not_in_export.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"export\";\n\n// CHECK:STDERR: fail_orig_name_not_in_export.carbon:[[@LINE+4]]:8: error: name `C` not found [NameNotFound]\n// CHECK:STDERR: var c: C = {};\n// CHECK:STDERR:        ^\n// CHECK:STDERR:\nvar c: C = {};\n\n// --- indirect_compat.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"export\";\nimport library \"export_orig\";\n\nvar c: C = {};\nvar d: D* = &c;\n\n// CHECK:STDOUT: --- base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- export.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//base, C, unloaded\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//base, D, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//base, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//base, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %D: type = export D, imports.%Main.D [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"base.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- export_orig.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//base, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.D = import_ref Main//base, D, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//base, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//base, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C: type = export C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"base.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_export.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//export, D, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8db: <witness> = import_ref Main//export, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.a60 = import_ref Main//export, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %C = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C]\n// CHECK:STDOUT:   %d: ref %C = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"export.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a60\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc6_13.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc6_13.2: init %C to file.%d.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc6_1: init %C = converted %.loc6_13.1, %.loc6_13.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%d.var, %.loc6_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_orig_name_not_in_export.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.D = import_ref Main//export, D, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = <poisoned>\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: <error> = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: <error> = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref <error> = var %c.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %C.ref: <error> = name_ref C, <error> [concrete = <error>]\n// CHECK:STDOUT:   %c: ref <error> = ref_binding c, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   assign file.%c.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- indirect_compat.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of file.%c.var [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.411: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.ed9: %ptr.as.Copy.impl.Op.type.411 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.259: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.64b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.259, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.bound: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.ed9 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.ed9, @ptr.as.Copy.impl.Op(%C) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//export, D, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//export_orig, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8db: <witness> = import_ref Main//export_orig, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.a60 = import_ref Main//export_orig, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.7c7 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.506 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.506 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %ptr.31e = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %ptr [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr: type = ptr_type %D.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %ptr.31e = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"export_orig.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a60\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7_13.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc7_13.2: init %C to file.%c.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc7_1: init %C = converted %.loc7_13.1, %.loc7_13.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%c.var, %.loc7_1\n// CHECK:STDOUT:   %c.ref: ref %C = name_ref c, file.%c [concrete = file.%c.var]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of %c.ref [concrete = constants.%addr]\n// CHECK:STDOUT:   %impl.elem0: %.64b = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9]\n// CHECK:STDOUT:   %bound_method.loc8_13.1: <bound method> = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_13.2: <bound method> = bound_method %addr, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.31e = call %bound_method.loc8_13.2(%addr) [concrete = constants.%addr]\n// CHECK:STDOUT:   assign file.%d.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/alias/import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/alias/import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/import.carbon\n\n// --- class1.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nalias c_alias = C;\n\nvar a: C*;\n\n// --- class2.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"class1\";\n\nalias c_alias_alias = c_alias;\n\nvar b: c_alias*;\n\n// --- class3.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"class2\";\n\nvar c: c_alias_alias*;\n\n// --- var1.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nvar a: () = ();\n\nalias a_alias = a;\n\n// --- var2.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"var1\";\n\nalias a_alias_alias = a_alias;\n\nvar b: () = a_alias;\n\n// --- var3.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"var2\";\n\nvar c: () = a_alias_alias;\n\n// CHECK:STDOUT: --- class1.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.910: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%ptr) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.7ef: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%ptr) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.b07: %T.as.DefaultOrUnformed.impl.Op.type.7ef = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %ptr, (%DefaultOrUnformed.impl_witness.910) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.b07, @T.as.DefaultOrUnformed.impl.Op(%ptr) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .c_alias = %c_alias\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref.loc6: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c_alias: type = alias_binding c_alias, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.506 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.506 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %ptr = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %ptr [concrete = constants.%ptr] {\n// CHECK:STDOUT:     %C.ref.loc8: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr: type = ptr_type %C.ref.loc8 [concrete = constants.%ptr]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %ptr = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%ptr, (constants.%DefaultOrUnformed.impl_witness.910) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc8_10.1: %DefaultOrUnformed.type = converted constants.%ptr, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc8_10.1 [concrete = constants.%ptr]\n// CHECK:STDOUT:   %.loc8_10.2: type = converted %.loc8_10.1, %as_type [concrete = constants.%ptr]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.b07, @T.as.DefaultOrUnformed.impl.Op(constants.%ptr) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %ptr = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign file.%a.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- class2.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.20b: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%ptr) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.7ef: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%ptr) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.b07: %T.as.DefaultOrUnformed.impl.Op.type.7ef = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %ptr, (%DefaultOrUnformed.impl_witness.20b) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.b07, @T.as.DefaultOrUnformed.impl.Op(%ptr) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//class1, C, unloaded\n// CHECK:STDOUT:   %Main.c_alias: type = import_ref Main//class1, c_alias, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.a = import_ref Main//class1, a, unloaded\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//class1, loc4_10, loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//class1, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Main.import_ref.dee: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Main//class1, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Main.import_ref.dee), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .c_alias = imports.%Main.c_alias\n// CHECK:STDOUT:     .a = imports.%Main.a\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .c_alias_alias = %c_alias_alias\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %c_alias.ref.loc6: type = name_ref c_alias, imports.%Main.c_alias [concrete = constants.%C]\n// CHECK:STDOUT:   %c_alias_alias: type = alias_binding c_alias_alias, imports.%Main.c_alias [concrete = constants.%C]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.506 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.506 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %ptr = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %ptr [concrete = constants.%ptr] {\n// CHECK:STDOUT:     %c_alias.ref.loc8: type = name_ref c_alias, imports.%Main.c_alias [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr: type = ptr_type %c_alias.ref.loc8 [concrete = constants.%ptr]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %ptr = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"class1.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%ptr, (constants.%DefaultOrUnformed.impl_witness.20b) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc8_16.1: %DefaultOrUnformed.type = converted constants.%ptr, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc8_16.1 [concrete = constants.%ptr]\n// CHECK:STDOUT:   %.loc8_16.2: type = converted %.loc8_16.1, %as_type [concrete = constants.%ptr]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.b07, @T.as.DefaultOrUnformed.impl.Op(constants.%ptr) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %ptr = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign file.%b.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- class3.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.910: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%ptr) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.7ef: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%ptr) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.b07: %T.as.DefaultOrUnformed.impl.Op.type.7ef = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %ptr, (%DefaultOrUnformed.impl_witness.910) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.b07, @T.as.DefaultOrUnformed.impl.Op(%ptr) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.c_alias_alias: type = import_ref Main//class2, c_alias_alias, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.b = import_ref Main//class2, b, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8db: <witness> = import_ref Main//class2, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.a60 = import_ref Main//class2, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .c_alias_alias = imports.%Main.c_alias_alias\n// CHECK:STDOUT:     .b = imports.%Main.b\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.506 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.506 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %ptr = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6: type = splice_block %ptr [concrete = constants.%ptr] {\n// CHECK:STDOUT:     %c_alias_alias.ref: type = name_ref c_alias_alias, imports.%Main.c_alias_alias [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr: type = ptr_type %c_alias_alias.ref [concrete = constants.%ptr]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %ptr = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"class2.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a60\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%ptr, (constants.%DefaultOrUnformed.impl_witness.910) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc6_22.1: %DefaultOrUnformed.type = converted constants.%ptr, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc6_22.1 [concrete = constants.%ptr]\n// CHECK:STDOUT:   %.loc6_22.2: type = converted %.loc6_22.1, %as_type [concrete = constants.%ptr]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.b07, @T.as.DefaultOrUnformed.impl.Op(constants.%ptr) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %ptr = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign file.%c.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- var1.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .a_alias = %a_alias\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_9.1: type = splice_block %.loc4_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc4_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc4_9.3: type = converted %.loc4_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_tuple.type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   %a.ref: ref %empty_tuple.type = name_ref a, %a [concrete = %a.var]\n// CHECK:STDOUT:   %a_alias: ref %empty_tuple.type = alias_binding a_alias, %a [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc4_14.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc4_14.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc4_1: init %empty_tuple.type = converted %.loc4_14.1, %.loc4_14.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   assign file.%a.var, %.loc4_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- var2.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.a = import_ref Main//var1, a, unloaded\n// CHECK:STDOUT:   %Main.a_alias: ref %empty_tuple.type = import_ref Main//var1, a_alias, loaded [concrete = %a.var]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.patt: %pattern_type = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:   %a.var_patt: %pattern_type = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var %a.var_patt [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .a = imports.%Main.a\n// CHECK:STDOUT:     .a_alias = imports.%Main.a_alias\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .a_alias_alias = %a_alias_alias\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %a_alias.ref: ref %empty_tuple.type = name_ref a_alias, imports.%Main.a_alias [concrete = imports.%a.var]\n// CHECK:STDOUT:   %a_alias_alias: ref %empty_tuple.type = alias_binding a_alias_alias, imports.%Main.a_alias [concrete = imports.%a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %empty_tuple.type = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8_9.1: type = splice_block %.loc8_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc8_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc8_9.3: type = converted %.loc8_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %empty_tuple.type = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a_alias.ref: ref %empty_tuple.type = name_ref a_alias, imports.%Main.a_alias [concrete = imports.%a.var]\n// CHECK:STDOUT:   %.loc8_13: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc8_1: init %empty_tuple.type = converted %a_alias.ref, %.loc8_13 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   assign file.%b.var, %.loc8_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- var3.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.a_alias_alias: ref %empty_tuple.type = import_ref Main//var2, a_alias_alias, loaded [concrete = %a.var]\n// CHECK:STDOUT:   %Main.b = import_ref Main//var2, b, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.patt: %pattern_type = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:   %a.var_patt: %pattern_type = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var %a.var_patt [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .a_alias_alias = imports.%Main.a_alias_alias\n// CHECK:STDOUT:     .b = imports.%Main.b\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %empty_tuple.type = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %empty_tuple.type = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a_alias_alias.ref: ref %empty_tuple.type = name_ref a_alias_alias, imports.%Main.a_alias_alias [concrete = imports.%a.var]\n// CHECK:STDOUT:   %.loc6_13: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_1: init %empty_tuple.type = converted %a_alias_alias.ref, %.loc6_13 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   assign file.%c.var, %.loc6_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/alias/import_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/alias/import_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/import_access.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nclass C {}\nprivate alias A = C;\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- def.impl.carbon\n\nimpl package Test library \"[[@TEST_NAME]]\";\n\nvar inst: A = {};\n\n// --- fail_local_def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nimport library \"def\";\n\n// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:11: error: name `A` not found [NameNotFound]\n// CHECK:STDERR: var inst: A = {};\n// CHECK:STDERR:           ^\n// CHECK:STDERR:\nvar inst: A = {};\n\n// --- fail_other_def.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nimport Test library \"def\";\n\n// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:11: error: member name `A` not found in `Test` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: var inst: Test.A = {};\n// CHECK:STDERR:           ^~~~~~\n// CHECK:STDERR:\nvar inst: Test.A = {};\n\n// CHECK:STDOUT: --- def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .A [private] = %A\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %A: type = alias_binding A, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- def.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test.C = import_ref Test//def, C, unloaded\n// CHECK:STDOUT:   %Test.A: type = import_ref Test//def, A, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Test.import_ref.8f2: <witness> = import_ref Test//def, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Test.import_ref.c8c = import_ref Test//def, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Test.C\n// CHECK:STDOUT:     .A [private] = imports.%Test.A\n// CHECK:STDOUT:     .inst = %inst\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %inst.patt: %pattern_type = ref_binding_pattern inst [concrete]\n// CHECK:STDOUT:     %inst.var_patt: %pattern_type = var_pattern %inst.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.var: ref %C = var %inst.var_patt [concrete]\n// CHECK:STDOUT:   %A.ref: type = name_ref A, imports.%Test.A [concrete = constants.%C]\n// CHECK:STDOUT:   %inst: ref %C = ref_binding inst, %inst.var [concrete = %inst.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"def.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Test.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Test.import_ref.c8c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc4_16.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc4_16.2: init %C to file.%inst.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc4_1: init %C = converted %.loc4_16.1, %.loc4_16.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%inst.var, %.loc4_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_local_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test.C = import_ref Test//def, C, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Test.C\n// CHECK:STDOUT:     .A = <poisoned>\n// CHECK:STDOUT:     .inst = %inst\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %inst.patt: <error> = ref_binding_pattern inst [concrete]\n// CHECK:STDOUT:     %inst.var_patt: <error> = var_pattern %inst.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.var: ref <error> = var %inst.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %A.ref: <error> = name_ref A, <error> [concrete = <error>]\n// CHECK:STDOUT:   %inst: ref <error> = ref_binding inst, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   assign file.%inst.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_other_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test: <namespace> = namespace file.%Test.import, [concrete] {\n// CHECK:STDOUT:     .A = <poisoned>\n// CHECK:STDOUT:     import Test//def\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Test = imports.%Test\n// CHECK:STDOUT:     .inst = %inst\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %inst.patt: <error> = ref_binding_pattern inst [concrete]\n// CHECK:STDOUT:     %inst.var_patt: <error> = var_pattern %inst.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.var: ref <error> = var %inst.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.1: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:     %Test.ref: <namespace> = name_ref Test, imports.%Test [concrete = imports.%Test]\n// CHECK:STDOUT:     %A.ref: <error> = name_ref A, <error> [concrete = <error>]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst: ref <error> = ref_binding inst, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   assign file.%inst.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/alias/import_order.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/alias/import_order.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/import_order.carbon\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C { var v: (); }\nalias a = C;\nalias b = a;\nalias c = b;\nalias d = c;\n\n// --- b.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\n\n// Access imports in reverse order of export.\nvar d_val: d = {.v = ()};\nvar c_val: c = {.v = d_val.v};\nvar b_val: b = {.v = c_val.v};\nvar a_val: a = {.v = b_val.v};\n\n// CHECK:STDOUT: --- a.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %struct_type.v: type = struct_type {.v: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.v [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %a: type = alias_binding a, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %a.ref: type = name_ref a, %a [concrete = constants.%C]\n// CHECK:STDOUT:   %b: type = alias_binding b, %a [concrete = constants.%C]\n// CHECK:STDOUT:   %b.ref: type = name_ref b, %b [concrete = constants.%C]\n// CHECK:STDOUT:   %c: type = alias_binding c, %b [concrete = constants.%C]\n// CHECK:STDOUT:   %c.ref: type = name_ref c, %c [concrete = constants.%C]\n// CHECK:STDOUT:   %d: type = alias_binding d, %c [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %.loc4_19.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc4_19.2: type = converted %.loc4_19.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   %.loc4_16: %C.elem = field_decl v, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.v [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .v = %.loc4_16\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- b.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %struct_type.v: type = struct_type {.v: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.v [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct.5f2: %struct_type.v = struct_value (%empty_tuple) [concrete]\n// CHECK:STDOUT:   %.cad: ref %empty_tuple.type = class_element_access file.%d_val.var, element0 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value (%empty_tuple) [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %struct.d07: %struct_type.v = struct_value (%.cad) [concrete]\n// CHECK:STDOUT:   %.da4: ref %empty_tuple.type = class_element_access file.%c_val.var, element0 [concrete]\n// CHECK:STDOUT:   %struct.f0b: %struct_type.v = struct_value (%.da4) [concrete]\n// CHECK:STDOUT:   %.0f2: ref %empty_tuple.type = class_element_access file.%b_val.var, element0 [concrete]\n// CHECK:STDOUT:   %struct.938: %struct_type.v = struct_value (%.0f2) [concrete]\n// CHECK:STDOUT:   %.851: ref %empty_tuple.type = class_element_access file.%a_val.var, element0 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//a, C, unloaded\n// CHECK:STDOUT:   %Main.a: type = import_ref Main//a, a, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.b: type = import_ref Main//a, b, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.c: type = import_ref Main//a, c, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.d: type = import_ref Main//a, d, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.146: <witness> = import_ref Main//a, loc4_22, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.d43: %C.elem = import_ref Main//a, loc4_16, loaded [concrete = %.c09]\n// CHECK:STDOUT:   %.c09: %C.elem = field_decl v, element0 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .a = imports.%Main.a\n// CHECK:STDOUT:     .b = imports.%Main.b\n// CHECK:STDOUT:     .c = imports.%Main.c\n// CHECK:STDOUT:     .d = imports.%Main.d\n// CHECK:STDOUT:     .d_val = %d_val\n// CHECK:STDOUT:     .c_val = %c_val\n// CHECK:STDOUT:     .b_val = %b_val\n// CHECK:STDOUT:     .a_val = %a_val\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d_val.patt: %pattern_type = ref_binding_pattern d_val [concrete]\n// CHECK:STDOUT:     %d_val.var_patt: %pattern_type = var_pattern %d_val.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d_val.var: ref %C = var %d_val.var_patt [concrete]\n// CHECK:STDOUT:   %d.ref: type = name_ref d, imports.%Main.d [concrete = constants.%C]\n// CHECK:STDOUT:   %d_val: ref %C = ref_binding d_val, %d_val.var [concrete = %d_val.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c_val.patt: %pattern_type = ref_binding_pattern c_val [concrete]\n// CHECK:STDOUT:     %c_val.var_patt: %pattern_type = var_pattern %c_val.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c_val.var: ref %C = var %c_val.var_patt [concrete]\n// CHECK:STDOUT:   %c.ref: type = name_ref c, imports.%Main.c [concrete = constants.%C]\n// CHECK:STDOUT:   %c_val: ref %C = ref_binding c_val, %c_val.var [concrete = %c_val.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b_val.patt: %pattern_type = ref_binding_pattern b_val [concrete]\n// CHECK:STDOUT:     %b_val.var_patt: %pattern_type = var_pattern %b_val.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b_val.var: ref %C = var %b_val.var_patt [concrete]\n// CHECK:STDOUT:   %b.ref: type = name_ref b, imports.%Main.b [concrete = constants.%C]\n// CHECK:STDOUT:   %b_val: ref %C = ref_binding b_val, %b_val.var [concrete = %b_val.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a_val.patt: %pattern_type = ref_binding_pattern a_val [concrete]\n// CHECK:STDOUT:     %a_val.var_patt: %pattern_type = var_pattern %a_val.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a_val.var: ref %C = var %a_val.var_patt [concrete]\n// CHECK:STDOUT:   %a.ref: type = name_ref a, imports.%Main.a [concrete = constants.%C]\n// CHECK:STDOUT:   %a_val: ref %C = ref_binding a_val, %a_val.var [concrete = %a_val.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.146\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT:   .v = imports.%Main.import_ref.d43\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7_23.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc7_24.1: %struct_type.v = struct_literal (%.loc7_23.1) [concrete = constants.%struct.5f2]\n// CHECK:STDOUT:   %.loc7_24.2: ref %empty_tuple.type = class_element_access file.%d_val.var, element0 [concrete = constants.%.cad]\n// CHECK:STDOUT:   %.loc7_23.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc7_24.3: init %empty_tuple.type = converted %.loc7_23.1, %.loc7_23.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc7_24.4: init %C to file.%d_val.var = class_init (%.loc7_24.3) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc7_1: init %C = converted %.loc7_24.1, %.loc7_24.4 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%d_val.var, %.loc7_1\n// CHECK:STDOUT:   %d_val.ref: ref %C = name_ref d_val, file.%d_val [concrete = file.%d_val.var]\n// CHECK:STDOUT:   %v.ref.loc8: %C.elem = name_ref v, imports.%Main.import_ref.d43 [concrete = imports.%.c09]\n// CHECK:STDOUT:   %.loc8_27.1: ref %empty_tuple.type = class_element_access %d_val.ref, element0 [concrete = constants.%.cad]\n// CHECK:STDOUT:   %.loc8_29.1: %struct_type.v = struct_literal (%.loc8_27.1) [concrete = constants.%struct.d07]\n// CHECK:STDOUT:   %.loc8_29.2: ref %empty_tuple.type = class_element_access file.%c_val.var, element0 [concrete = constants.%.da4]\n// CHECK:STDOUT:   %.loc8_27.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc8_29.3: init %empty_tuple.type = converted %.loc8_27.1, %.loc8_27.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc8_29.4: init %C to file.%c_val.var = class_init (%.loc8_29.3) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc8_1: init %C = converted %.loc8_29.1, %.loc8_29.4 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%c_val.var, %.loc8_1\n// CHECK:STDOUT:   %c_val.ref: ref %C = name_ref c_val, file.%c_val [concrete = file.%c_val.var]\n// CHECK:STDOUT:   %v.ref.loc9: %C.elem = name_ref v, imports.%Main.import_ref.d43 [concrete = imports.%.c09]\n// CHECK:STDOUT:   %.loc9_27.1: ref %empty_tuple.type = class_element_access %c_val.ref, element0 [concrete = constants.%.da4]\n// CHECK:STDOUT:   %.loc9_29.1: %struct_type.v = struct_literal (%.loc9_27.1) [concrete = constants.%struct.f0b]\n// CHECK:STDOUT:   %.loc9_29.2: ref %empty_tuple.type = class_element_access file.%b_val.var, element0 [concrete = constants.%.0f2]\n// CHECK:STDOUT:   %.loc9_27.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_29.3: init %empty_tuple.type = converted %.loc9_27.1, %.loc9_27.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_29.4: init %C to file.%b_val.var = class_init (%.loc9_29.3) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_1: init %C = converted %.loc9_29.1, %.loc9_29.4 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%b_val.var, %.loc9_1\n// CHECK:STDOUT:   %b_val.ref: ref %C = name_ref b_val, file.%b_val [concrete = file.%b_val.var]\n// CHECK:STDOUT:   %v.ref.loc10: %C.elem = name_ref v, imports.%Main.import_ref.d43 [concrete = imports.%.c09]\n// CHECK:STDOUT:   %.loc10_27.1: ref %empty_tuple.type = class_element_access %b_val.ref, element0 [concrete = constants.%.0f2]\n// CHECK:STDOUT:   %.loc10_29.1: %struct_type.v = struct_literal (%.loc10_27.1) [concrete = constants.%struct.938]\n// CHECK:STDOUT:   %.loc10_29.2: ref %empty_tuple.type = class_element_access file.%a_val.var, element0 [concrete = constants.%.851]\n// CHECK:STDOUT:   %.loc10_27.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc10_29.3: init %empty_tuple.type = converted %.loc10_27.1, %.loc10_27.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc10_29.4: init %C to file.%a_val.var = class_init (%.loc10_29.3) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc10_1: init %C = converted %.loc10_29.1, %.loc10_29.4 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%a_val.var, %.loc10_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/alias/in_namespace.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/alias/in_namespace.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/in_namespace.carbon\n\n// --- in_namespace.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C { var v: (); }\n\n//@dump-sem-ir-begin\nnamespace NS;\nalias NS.a = C;\n//@dump-sem-ir-end\n\nlet b: NS.a = {.v = ()};\n\nfn F() -> NS.a {\n  return {.v = ()};\n}\n\n// --- fail_local_in_namespace.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nnamespace NS;\n\nfn F() -> {} {\n  // CHECK:STDERR: fail_local_in_namespace.carbon:[[@LINE+8]]:9: error: name `NS` not found [NameNotFound]\n  // CHECK:STDERR:   alias NS.a = {};\n  // CHECK:STDERR:         ^~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_local_in_namespace.carbon:[[@LINE+4]]:16: error: alias initializer must be a name reference [AliasRequiresNameRef]\n  // CHECK:STDERR:   alias NS.a = {};\n  // CHECK:STDERR:                ^~\n  // CHECK:STDERR:\n  alias NS.a = {};\n  // CHECK:STDERR: fail_local_in_namespace.carbon:[[@LINE+4]]:10: error: member name `a` not found in `NS` [MemberNameNotFoundInInstScope]\n  // CHECK:STDERR:   return NS.a;\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR:\n  return NS.a;\n}\n\n// CHECK:STDOUT: --- in_namespace.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %NS: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = <poisoned>\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %a: type = alias_binding a, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/alias/local.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/alias/local.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/local.carbon\n\n// --- local.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() -> () {\n  var a: () = ();\n  //@dump-sem-ir-begin\n  alias b = a;\n  //@dump-sem-ir-end\n  return b;\n}\n\n// CHECK:STDOUT: --- local.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %a.ref: ref %empty_tuple.type = name_ref a, %a\n// CHECK:STDOUT:   %b: ref %empty_tuple.type = alias_binding b, %a\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/alias/preserve_in_type_printing.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/alias/preserve_in_type_printing.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/alias/preserve_in_type_printing.carbon\n\n// --- fail_alias_nested_in_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias A = C;\n\n// The diagnostics below should refer to `A`, not `C`.\n\n// CHECK:STDERR: fail_alias_nested_in_type.carbon:[[@LINE+7]]:15: error: missing return value [ReturnStatementMissingExpr]\n// CHECK:STDERR: fn F() -> A { return; }\n// CHECK:STDERR:               ^~~~~~~\n// CHECK:STDERR: fail_alias_nested_in_type.carbon:[[@LINE+4]]:11: note: return type of function is `A` [ReturnTypeHereNote]\n// CHECK:STDERR: fn F() -> A { return; }\n// CHECK:STDERR:           ^\n// CHECK:STDERR:\nfn F() -> A { return; }\n// CHECK:STDERR: fail_alias_nested_in_type.carbon:[[@LINE+7]]:16: error: missing return value [ReturnStatementMissingExpr]\n// CHECK:STDERR: fn G() -> A* { return; }\n// CHECK:STDERR:                ^~~~~~~\n// CHECK:STDERR: fail_alias_nested_in_type.carbon:[[@LINE+4]]:11: note: return type of function is `A*` [ReturnTypeHereNote]\n// CHECK:STDERR: fn G() -> A* { return; }\n// CHECK:STDERR:           ^~\n// CHECK:STDERR:\nfn G() -> A* { return; }\n// CHECK:STDERR: fail_alias_nested_in_type.carbon:[[@LINE+7]]:22: error: missing return value [ReturnStatementMissingExpr]\n// CHECK:STDERR: fn H() -> const A* { return; }\n// CHECK:STDERR:                      ^~~~~~~\n// CHECK:STDERR: fail_alias_nested_in_type.carbon:[[@LINE+4]]:11: note: return type of function is `const A*` [ReturnTypeHereNote]\n// CHECK:STDERR: fn H() -> const A* { return; }\n// CHECK:STDERR:           ^~~~~~~~\n// CHECK:STDERR:\nfn H() -> const A* { return; }\n// CHECK:STDERR: fail_alias_nested_in_type.carbon:[[@LINE+7]]:26: error: missing return value [ReturnStatementMissingExpr]\n// CHECK:STDERR: fn I() -> array(A, 42) { return; }\n// CHECK:STDERR:                          ^~~~~~~\n// CHECK:STDERR: fail_alias_nested_in_type.carbon:[[@LINE+4]]:11: note: return type of function is `array(A, 42)` [ReturnTypeHereNote]\n// CHECK:STDERR: fn I() -> array(A, 42) { return; }\n// CHECK:STDERR:           ^~~~~~~~~~~~\n// CHECK:STDERR:\nfn I() -> array(A, 42) { return; }\n"
  },
  {
    "path": "toolchain/check/testdata/array/basics.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/array/basics.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/array/basics.carbon\n\n// --- assign_var.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nvar a: ((), (), ());\n//@dump-sem-ir-begin\nvar b: array((), 3) = a;\n//@dump-sem-ir-end\n\n// --- assign_arity.carbon\n\nvar a0: array((), 0) = ();\nvar a1: array((), 1) = ((),);\nvar a2: array((), 2) = ((), ());\n\n// --- array_in_place.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F() -> (C, C, C);\n\nfn G() {\n  //@dump-sem-ir-begin\n  var unused v: array((C, C, C), 2) = (F(), F());\n  //@dump-sem-ir-end\n}\n\n// --- array_vs_tuple.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn G() {\n  // These should have two different constant values.\n  //@dump-sem-ir-begin\n  var unused a: array((), 3);\n  var unused b: ((), (), ());\n  //@dump-sem-ir-end\n}\n\n// --- assign_return_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() -> ((),) { return ((),); }\n\nfn Run() {\n  //@dump-sem-ir-begin\n  var unused t: array((), 1) = F();\n  //@dump-sem-ir-end\n}\n\n// --- nine_elements.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nvar a: ((), (), (), (), (), (), (), (), ()) =\n    ((), (), (), (), (), (), (), (), ());\n\n// Regression test for APInt handling.\n//@dump-sem-ir-begin\nvar b: array((), 9) = a;\n//@dump-sem-ir-end\n\n// --- fail_incomplete_element.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Incomplete;\n\n// CHECK:STDERR: fail_incomplete_element.carbon:[[@LINE+7]]:8: error: binding pattern has incomplete type `array(Incomplete, 1)` in name binding declaration [IncompleteTypeInBindingDecl]\n// CHECK:STDERR: var a: array(Incomplete, 1);\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_incomplete_element.carbon:[[@LINE-5]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class Incomplete;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar a: array(Incomplete, 1);\n\nvar p: Incomplete* = &a[0];\n\n// --- fail_invalid_element.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_invalid_element.carbon:[[@LINE+7]]:14: error: cannot implicitly convert non-type value of type `Core.IntLiteral` to `type` [ConversionFailureNonTypeToFacet]\n// CHECK:STDERR: var a: array(1, 1);\n// CHECK:STDERR:              ^\n// CHECK:STDERR: fail_invalid_element.carbon:[[@LINE+4]]:14: note: type `Core.IntLiteral` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var a: array(1, 1);\n// CHECK:STDERR:              ^\n// CHECK:STDERR:\nvar a: array(1, 1);\n\n// CHECK:STDOUT: --- assign_var.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_tuple.type, %empty_tuple.type, %empty_tuple.type) [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3, %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.035: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %tuple.elem0: ref %empty_tuple.type = tuple_access file.%a.var, element0 [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %tuple.elem1: ref %empty_tuple.type = tuple_access file.%a.var, element1 [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %tuple.elem2: ref %empty_tuple.type = tuple_access file.%a.var, element2 [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%empty_tuple, %empty_tuple, %empty_tuple) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.035 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.035 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %array_type = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_19: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %.loc6_15.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:     %.loc6_15.2: type = converted %.loc6_15.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %array_type: type = array_type %int_3, %.loc6_15.2 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %array_type = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %a.ref: ref %tuple.type = name_ref a, file.%a [concrete = file.%a.var]\n// CHECK:STDOUT:   %tuple.elem0: ref %empty_tuple.type = tuple_access %a.ref, element0 [concrete = constants.%tuple.elem0]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc6_23.1: ref %empty_tuple.type = array_index file.%b.var, %int_0\n// CHECK:STDOUT:   %.loc6_23.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_23.3: init %empty_tuple.type = converted %tuple.elem0, %.loc6_23.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem1: ref %empty_tuple.type = tuple_access %a.ref, element1 [concrete = constants.%tuple.elem1]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %.loc6_23.4: ref %empty_tuple.type = array_index file.%b.var, %int_1\n// CHECK:STDOUT:   %.loc6_23.5: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_23.6: init %empty_tuple.type = converted %tuple.elem1, %.loc6_23.5 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem2: ref %empty_tuple.type = tuple_access %a.ref, element2 [concrete = constants.%tuple.elem2]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:   %.loc6_23.7: ref %empty_tuple.type = array_index file.%b.var, %int_2\n// CHECK:STDOUT:   %.loc6_23.8: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_23.9: init %empty_tuple.type = converted %tuple.elem2, %.loc6_23.8 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_23.10: init %array_type to file.%b.var = array_init (%.loc6_23.3, %.loc6_23.6, %.loc6_23.9) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc6_1: init %array_type = converted %a.ref, %.loc6_23.10 [concrete = constants.%array]\n// CHECK:STDOUT:   assign file.%b.var, %.loc6_1\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- array_in_place.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %tuple.type.ff9: type = tuple_type (type, type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.ff9 = tuple_value (%C, %C, %C) [concrete]\n// CHECK:STDOUT:   %tuple.type.e56: type = tuple_type (%C, %C, %C) [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_2, %tuple.type.e56 [concrete]\n// CHECK:STDOUT:   %pattern_type.709: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %tuple.type.708: type = tuple_type (%tuple.type.e56, %tuple.type.e56) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.709 = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.709 = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %array_type = var %v.var_patt\n// CHECK:STDOUT:   %F.ref.loc10_40: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc10_48.1: ref %tuple.type.e56 = splice_block %.loc10_48.6 {\n// CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:     %.loc10_48.6: ref %tuple.type.e56 = array_index %v.var, %int_0\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.call.loc10_42: init %tuple.type.e56 to %.loc10_48.1 = call %F.ref.loc10_40()\n// CHECK:STDOUT:   %F.ref.loc10_45: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc10_48.2: ref %tuple.type.e56 = splice_block %.loc10_48.5 {\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:     %.loc10_48.5: ref %tuple.type.e56 = array_index %v.var, %int_1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.call.loc10_47: init %tuple.type.e56 to %.loc10_48.2 = call %F.ref.loc10_45()\n// CHECK:STDOUT:   %.loc10_48.3: %tuple.type.708 = tuple_literal (%F.call.loc10_42, %F.call.loc10_47)\n// CHECK:STDOUT:   %.loc10_48.4: init %array_type to %v.var = array_init (%F.call.loc10_42, %F.call.loc10_47)\n// CHECK:STDOUT:   %.loc10_3: init %array_type = converted %.loc10_48.3, %.loc10_48.4\n// CHECK:STDOUT:   assign %v.var, %.loc10_3\n// CHECK:STDOUT:   %.loc10_35: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %C.ref.loc10_24: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %C.ref.loc10_27: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %C.ref.loc10_30: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc10_31.1: %tuple.type.ff9 = tuple_literal (%C.ref.loc10_24, %C.ref.loc10_27, %C.ref.loc10_30) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:     %.loc10_31.2: type = converted %.loc10_31.1, constants.%tuple.type.e56 [concrete = constants.%tuple.type.e56]\n// CHECK:STDOUT:     %array_type: type = array_type %int_2, %.loc10_31.2 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %array_type = ref_binding v, %v.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %v.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%v.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- array_vs_tuple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3, %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.035: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.924: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%array_type) [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.86d: %DefaultOrUnformed.type = facet_value %array_type, (%DefaultOrUnformed.impl_witness.924) [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_tuple.type, %empty_tuple.type, %empty_tuple.type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type = tuple_value (%empty_tuple, %empty_tuple, %empty_tuple) [concrete]\n// CHECK:STDOUT:   %pattern_type.8c1: type = pattern_type %tuple.type [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.032: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%tuple.type) [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.1ea: %DefaultOrUnformed.type = facet_value %tuple.type, (%DefaultOrUnformed.impl_witness.032) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc8 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc7 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.035 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.035 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %array_type = var %a.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc7: %DefaultOrUnformed.type = facet_value constants.%array_type, (constants.%DefaultOrUnformed.impl_witness.924) [concrete = constants.%DefaultOrUnformed.facet.86d]\n// CHECK:STDOUT:   %.loc7_29.1: %DefaultOrUnformed.type = converted constants.%array_type, %DefaultOrUnformed.facet.loc7 [concrete = constants.%DefaultOrUnformed.facet.86d]\n// CHECK:STDOUT:   %as_type.loc7: type = facet_access_type %.loc7_29.1 [concrete = constants.%array_type]\n// CHECK:STDOUT:   %.loc7_29.2: type = converted %.loc7_29.1, %as_type.loc7 [concrete = constants.%array_type]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %.loc7_3: ref %array_type = splice_block %a.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc7: init %array_type to %.loc7_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.1()\n// CHECK:STDOUT:   assign %a.var, %T.as.DefaultOrUnformed.impl.Op.call.loc7\n// CHECK:STDOUT:   %.loc7_28: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %.loc7_24.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:     %.loc7_24.2: type = converted %.loc7_24.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %array_type: type = array_type %int_3, %.loc7_24.2 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %array_type = ref_binding a, %a.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.8c1 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.8c1 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %tuple.type = var %b.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc8: %DefaultOrUnformed.type = facet_value constants.%tuple.type, (constants.%DefaultOrUnformed.impl_witness.032) [concrete = constants.%DefaultOrUnformed.facet.1ea]\n// CHECK:STDOUT:   %.loc8_29.1: %DefaultOrUnformed.type = converted constants.%tuple.type, %DefaultOrUnformed.facet.loc8 [concrete = constants.%DefaultOrUnformed.facet.1ea]\n// CHECK:STDOUT:   %as_type.loc8: type = facet_access_type %.loc8_29.1 [concrete = constants.%tuple.type]\n// CHECK:STDOUT:   %.loc8_29.2: type = converted %.loc8_29.1, %as_type.loc8 [concrete = constants.%tuple.type]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %.loc8_3: ref %tuple.type = splice_block %b.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc8: init %tuple.type to %.loc8_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.2()\n// CHECK:STDOUT:   assign %b.var, %T.as.DefaultOrUnformed.impl.Op.call.loc8\n// CHECK:STDOUT:   %.loc8_28.1: type = splice_block %.loc8_28.6 [concrete = constants.%tuple.type] {\n// CHECK:STDOUT:     %.loc8_19: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc8_23: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc8_27: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc8_28.2: %tuple.type = tuple_literal (%.loc8_19, %.loc8_23, %.loc8_27) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc8_28.3: type = converted constants.%empty_tuple, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc8_28.4: type = converted constants.%empty_tuple, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc8_28.5: type = converted constants.%empty_tuple, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc8_28.6: type = converted %.loc8_28.2, constants.%tuple.type [concrete = constants.%tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %tuple.type = ref_binding b, %b.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc8: <bound method> = bound_method %b.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc8: init %empty_tuple.type = call %Destroy.Op.bound.loc8(%b.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc7: <bound method> = bound_method %a.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc7: init %empty_tuple.type = call %Destroy.Op.bound.loc7(%a.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc8(%self.param: ref %tuple.type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc7(%self.param: ref %array_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- assign_return_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_tuple.type) [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_1, %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%empty_tuple) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc8_34 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc8_3 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %t.patt: %pattern_type.fe8 = ref_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.var_patt: %pattern_type.fe8 = var_pattern %t.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %t.var: ref %array_type = var %t.var_patt\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: init %tuple.type = call %F.ref()\n// CHECK:STDOUT:   %.loc8_34.1: ref %tuple.type = temporary_storage\n// CHECK:STDOUT:   %.loc8_34.2: ref %tuple.type = temporary %.loc8_34.1, %F.call\n// CHECK:STDOUT:   %tuple.elem0: ref %empty_tuple.type = tuple_access %.loc8_34.2, element0\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc8_34.3: ref %empty_tuple.type = array_index %t.var, %int_0\n// CHECK:STDOUT:   %.loc8_34.4: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc8_34.5: init %empty_tuple.type = converted %tuple.elem0, %.loc8_34.4 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc8_34.6: init %array_type to %t.var = array_init (%.loc8_34.5) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc8_3: init %array_type = converted %F.call, %.loc8_34.6 [concrete = constants.%array]\n// CHECK:STDOUT:   assign %t.var, %.loc8_3\n// CHECK:STDOUT:   %.loc8_28: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %.loc8_24.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:     %.loc8_24.2: type = converted %.loc8_24.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %array_type: type = array_type %int_1, %.loc8_24.2 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %t: ref %array_type = ref_binding t, %t.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc8_34: <bound method> = bound_method %.loc8_34.2, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc8_34: init %empty_tuple.type = call %Destroy.Op.bound.loc8_34(%.loc8_34.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc8_3: <bound method> = bound_method %t.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc8_3: init %empty_tuple.type = call %Destroy.Op.bound.loc8_3(%t.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc8_34(%self.param: ref %tuple.type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc8_3(%self.param: ref %array_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- nine_elements.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_tuple.type, %empty_tuple.type, %empty_tuple.type, %empty_tuple.type, %empty_tuple.type, %empty_tuple.type, %empty_tuple.type, %empty_tuple.type, %empty_tuple.type) [concrete]\n// CHECK:STDOUT:   %tuple.elem0: ref %empty_tuple.type = tuple_access file.%a.var, element0 [concrete]\n// CHECK:STDOUT:   %tuple.elem1: ref %empty_tuple.type = tuple_access file.%a.var, element1 [concrete]\n// CHECK:STDOUT:   %tuple.elem2: ref %empty_tuple.type = tuple_access file.%a.var, element2 [concrete]\n// CHECK:STDOUT:   %tuple.elem3: ref %empty_tuple.type = tuple_access file.%a.var, element3 [concrete]\n// CHECK:STDOUT:   %tuple.elem4: ref %empty_tuple.type = tuple_access file.%a.var, element4 [concrete]\n// CHECK:STDOUT:   %tuple.elem5: ref %empty_tuple.type = tuple_access file.%a.var, element5 [concrete]\n// CHECK:STDOUT:   %tuple.elem6: ref %empty_tuple.type = tuple_access file.%a.var, element6 [concrete]\n// CHECK:STDOUT:   %tuple.elem7: ref %empty_tuple.type = tuple_access file.%a.var, element7 [concrete]\n// CHECK:STDOUT:   %tuple.elem8: ref %empty_tuple.type = tuple_access file.%a.var, element8 [concrete]\n// CHECK:STDOUT:   %int_9: Core.IntLiteral = int_value 9 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_9, %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.3db: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %int_6: Core.IntLiteral = int_value 6 [concrete]\n// CHECK:STDOUT:   %int_7: Core.IntLiteral = int_value 7 [concrete]\n// CHECK:STDOUT:   %int_8: Core.IntLiteral = int_value 8 [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple, %empty_tuple) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.3db = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.3db = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %array_type = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %.loc9_19: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %.loc9_15.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %int_9: Core.IntLiteral = int_value 9 [concrete = constants.%int_9]\n// CHECK:STDOUT:     %.loc9_15.2: type = converted %.loc9_15.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %array_type: type = array_type %int_9, %.loc9_15.2 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %array_type = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %a.ref: ref %tuple.type = name_ref a, file.%a [concrete = file.%a.var]\n// CHECK:STDOUT:   %tuple.elem0.loc9: ref %empty_tuple.type = tuple_access %a.ref, element0 [concrete = constants.%tuple.elem0]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc9_23.1: ref %empty_tuple.type = array_index file.%b.var, %int_0\n// CHECK:STDOUT:   %.loc9_23.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.3: init %empty_tuple.type = converted %tuple.elem0.loc9, %.loc9_23.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem1.loc9: ref %empty_tuple.type = tuple_access %a.ref, element1 [concrete = constants.%tuple.elem1]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %.loc9_23.4: ref %empty_tuple.type = array_index file.%b.var, %int_1\n// CHECK:STDOUT:   %.loc9_23.5: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.6: init %empty_tuple.type = converted %tuple.elem1.loc9, %.loc9_23.5 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem2.loc9: ref %empty_tuple.type = tuple_access %a.ref, element2 [concrete = constants.%tuple.elem2]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:   %.loc9_23.7: ref %empty_tuple.type = array_index file.%b.var, %int_2\n// CHECK:STDOUT:   %.loc9_23.8: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.9: init %empty_tuple.type = converted %tuple.elem2.loc9, %.loc9_23.8 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem3.loc9: ref %empty_tuple.type = tuple_access %a.ref, element3 [concrete = constants.%tuple.elem3]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:   %.loc9_23.10: ref %empty_tuple.type = array_index file.%b.var, %int_3\n// CHECK:STDOUT:   %.loc9_23.11: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.12: init %empty_tuple.type = converted %tuple.elem3.loc9, %.loc9_23.11 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem4.loc9: ref %empty_tuple.type = tuple_access %a.ref, element4 [concrete = constants.%tuple.elem4]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4]\n// CHECK:STDOUT:   %.loc9_23.13: ref %empty_tuple.type = array_index file.%b.var, %int_4\n// CHECK:STDOUT:   %.loc9_23.14: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.15: init %empty_tuple.type = converted %tuple.elem4.loc9, %.loc9_23.14 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem5.loc9: ref %empty_tuple.type = tuple_access %a.ref, element5 [concrete = constants.%tuple.elem5]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5]\n// CHECK:STDOUT:   %.loc9_23.16: ref %empty_tuple.type = array_index file.%b.var, %int_5\n// CHECK:STDOUT:   %.loc9_23.17: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.18: init %empty_tuple.type = converted %tuple.elem5.loc9, %.loc9_23.17 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem6.loc9: ref %empty_tuple.type = tuple_access %a.ref, element6 [concrete = constants.%tuple.elem6]\n// CHECK:STDOUT:   %int_6: Core.IntLiteral = int_value 6 [concrete = constants.%int_6]\n// CHECK:STDOUT:   %.loc9_23.19: ref %empty_tuple.type = array_index file.%b.var, %int_6\n// CHECK:STDOUT:   %.loc9_23.20: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.21: init %empty_tuple.type = converted %tuple.elem6.loc9, %.loc9_23.20 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem7.loc9: ref %empty_tuple.type = tuple_access %a.ref, element7 [concrete = constants.%tuple.elem7]\n// CHECK:STDOUT:   %int_7: Core.IntLiteral = int_value 7 [concrete = constants.%int_7]\n// CHECK:STDOUT:   %.loc9_23.22: ref %empty_tuple.type = array_index file.%b.var, %int_7\n// CHECK:STDOUT:   %.loc9_23.23: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.24: init %empty_tuple.type = converted %tuple.elem7.loc9, %.loc9_23.23 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem8.loc9: ref %empty_tuple.type = tuple_access %a.ref, element8 [concrete = constants.%tuple.elem8]\n// CHECK:STDOUT:   %int_8: Core.IntLiteral = int_value 8 [concrete = constants.%int_8]\n// CHECK:STDOUT:   %.loc9_23.25: ref %empty_tuple.type = array_index file.%b.var, %int_8\n// CHECK:STDOUT:   %.loc9_23.26: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.27: init %empty_tuple.type = converted %tuple.elem8.loc9, %.loc9_23.26 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_23.28: init %array_type to file.%b.var = array_init (%.loc9_23.3, %.loc9_23.6, %.loc9_23.9, %.loc9_23.12, %.loc9_23.15, %.loc9_23.18, %.loc9_23.21, %.loc9_23.24, %.loc9_23.27) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc9_1: init %array_type = converted %a.ref, %.loc9_23.28 [concrete = constants.%array]\n// CHECK:STDOUT:   assign file.%b.var, %.loc9_1\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/array/bound_values.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/array/bound_values.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/array/bound_values.carbon\n\n// --- addition.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nvar a:\n//@dump-sem-ir-begin\n    array(i32, 1 + 2)\n//@dump-sem-ir-end\n    = (1, 2, 3);\nlet b: array(i32, 3)* = &a;\n\n// --- unsigned.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nvar a:\n//@dump-sem-ir-begin\n    array(i32, 3 as u32)\n//@dump-sem-ir-end\n    = (1, 2, 3);\nlet b: array(i32, 3)* = &a;\n\n// --- fail_negative.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_negative.carbon:[[@LINE+4]]:19: error: array bound of -1 is negative [ArrayBoundNegative]\n// CHECK:STDERR: var a: array(i32, -1);\n// CHECK:STDERR:                   ^~\n// CHECK:STDERR:\nvar a: array(i32, -1);\n\n// --- fail_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_overflow.carbon:[[@LINE+4]]:19: error: array bound of 39999999999999999993 is too large [ArrayBoundTooLarge]\n// CHECK:STDERR: var a: array(i32, 39999999999999999993);\n// CHECK:STDERR:                   ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar a: array(i32, 39999999999999999993);\n\n// --- fail_invalid_type_with_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_invalid_type_with_overflow.carbon:[[@LINE+7]]:14: error: cannot implicitly convert non-type value of type `Core.IntLiteral` to `type` [ConversionFailureNonTypeToFacet]\n// CHECK:STDERR: var b: array(1, 39999999999999999993);\n// CHECK:STDERR:              ^\n// CHECK:STDERR: fail_invalid_type_with_overflow.carbon:[[@LINE+4]]:14: note: type `Core.IntLiteral` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var b: array(1, 39999999999999999993);\n// CHECK:STDERR:              ^\n// CHECK:STDERR:\nvar b: array(1, 39999999999999999993);\n\n// CHECK:STDOUT: --- addition.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %AddWith.type.4c0: type = facet_type <@AddWith, @AddWith(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %AddWith.impl_witness: <witness> = impl_witness imports.%AddWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %AddWith.facet: %AddWith.type.4c0 = facet_value Core.IntLiteral, (%AddWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type.900: type = fn_type @AddWith.WithSelf.Op, @AddWith.WithSelf(Core.IntLiteral, %AddWith.facet) [concrete]\n// CHECK:STDOUT:   %.302: type = fn_type_with_self_type %AddWith.WithSelf.Op.type.900, %AddWith.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.AddWith.impl.Op.type: type = fn_type @Core.IntLiteral.as.AddWith.impl.Op [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.AddWith.impl.Op: %Core.IntLiteral.as.AddWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.AddWith.impl.Op.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.AddWith.impl.Op [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.abd = import_ref Core//prelude/operators/arithmetic, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.8dd: %Core.IntLiteral.as.AddWith.impl.Op.type = import_ref Core//prelude/operators/arithmetic, loc{{\\d+_\\d+}}, loaded [concrete = constants.%Core.IntLiteral.as.AddWith.impl.Op]\n// CHECK:STDOUT:   %AddWith.impl_witness_table = impl_witness_table (%Core.import_ref.abd, %Core.import_ref.8dd), @Core.IntLiteral.as.AddWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %.loc6_21: type = splice_block %array_type.loc6 [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %impl.elem1: %.302 = impl_witness_access constants.%AddWith.impl_witness, element1 [concrete = constants.%Core.IntLiteral.as.AddWith.impl.Op]\n// CHECK:STDOUT:     %bound_method: <bound method> = bound_method %int_1, %impl.elem1 [concrete = constants.%Core.IntLiteral.as.AddWith.impl.Op.bound]\n// CHECK:STDOUT:     %Core.IntLiteral.as.AddWith.impl.Op.call: init Core.IntLiteral = call %bound_method(%int_1, %int_2) [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc6_18.1: Core.IntLiteral = value_of_initializer %Core.IntLiteral.as.AddWith.impl.Op.call [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc6_18.2: Core.IntLiteral = converted %Core.IntLiteral.as.AddWith.impl.Op.call, %.loc6_18.1 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %array_type.loc6: type = array_type %.loc6_18.2, %i32.loc6 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- unsigned.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]\n// CHECK:STDOUT:   %As.type.346: type = facet_type <@As, @As(%u32)> [concrete]\n// CHECK:STDOUT:   %To.fe9: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.type.2b1: type = fn_type @Core.IntLiteral.as.As.impl.Convert, @Core.IntLiteral.as.As.impl(%To.fe9) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.979: %Core.IntLiteral.as.As.impl.Convert.type.2b1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %From.fe9: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %As.impl_witness.e1d: <witness> = impl_witness imports.%As.impl_witness_table.7eb, @Core.IntLiteral.as.As.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.type.3e7: type = fn_type @Core.IntLiteral.as.As.impl.Convert, @Core.IntLiteral.as.As.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.bbd: %Core.IntLiteral.as.As.impl.Convert.type.3e7 = struct_value () [concrete]\n// CHECK:STDOUT:   %As.facet: %As.type.346 = facet_value Core.IntLiteral, (%As.impl_witness.e1d) [concrete]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.89a: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%u32, %As.facet) [concrete]\n// CHECK:STDOUT:   %.1a4: type = fn_type_with_self_type %As.WithSelf.Convert.type.89a, %As.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.bound: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.As.impl.Convert.bbd [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.As.impl.Convert.bbd, @Core.IntLiteral.as.As.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.d64: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.As.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.d14: %u32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %UInt.as.ImplicitAs.impl.Convert.type.7f8: type = fn_type @UInt.as.ImplicitAs.impl.Convert.1, @UInt.as.ImplicitAs.impl.607(%From.fe9) [symbolic]\n// CHECK:STDOUT:   %UInt.as.ImplicitAs.impl.Convert.0ea: %UInt.as.ImplicitAs.impl.Convert.type.7f8 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.895: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.493, @UInt.as.ImplicitAs.impl.607(%int_32) [concrete]\n// CHECK:STDOUT:   %UInt.as.ImplicitAs.impl.Convert.type.543: type = fn_type @UInt.as.ImplicitAs.impl.Convert.1, @UInt.as.ImplicitAs.impl.607(%int_32) [concrete]\n// CHECK:STDOUT:   %UInt.as.ImplicitAs.impl.Convert.342: %UInt.as.ImplicitAs.impl.Convert.type.543 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.2c6: %ImplicitAs.type.139 = facet_value %u32, (%ImplicitAs.impl_witness.895) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.70d: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet.2c6) [concrete]\n// CHECK:STDOUT:   %.044: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.70d, %ImplicitAs.facet.2c6 [concrete]\n// CHECK:STDOUT:   %UInt.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_3.d14, %UInt.as.ImplicitAs.impl.Convert.342 [concrete]\n// CHECK:STDOUT:   %UInt.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %UInt.as.ImplicitAs.impl.Convert.342, @UInt.as.ImplicitAs.impl.Convert.1(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.c86: <bound method> = bound_method %int_3.d14, %UInt.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.600: @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert.type (%Core.IntLiteral.as.As.impl.Convert.type.2b1) = import_ref Core//prelude/types/uint, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert (constants.%Core.IntLiteral.as.As.impl.Convert.979)]\n// CHECK:STDOUT:   %As.impl_witness_table.7eb = impl_witness_table (%Core.import_ref.600), @Core.IntLiteral.as.As.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.483: @UInt.as.ImplicitAs.impl.607.%UInt.as.ImplicitAs.impl.Convert.type (%UInt.as.ImplicitAs.impl.Convert.type.7f8) = import_ref Core//prelude/types/uint, loc{{\\d+_\\d+}}, loaded [symbolic = @UInt.as.ImplicitAs.impl.607.%UInt.as.ImplicitAs.impl.Convert (constants.%UInt.as.ImplicitAs.impl.Convert.0ea)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.493 = impl_witness_table (%Core.import_ref.483), @UInt.as.ImplicitAs.impl.607 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %.loc6_24: type = splice_block %array_type.loc6 [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %int_3.loc6: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %u32: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:     %impl.elem0.loc6_18.1: %.1a4 = impl_witness_access constants.%As.impl_witness.e1d, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bbd]\n// CHECK:STDOUT:     %bound_method.loc6_18.1: <bound method> = bound_method %int_3.loc6, %impl.elem0.loc6_18.1 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn.loc6_18.1: <specific function> = specific_function %impl.elem0.loc6_18.1, @Core.IntLiteral.as.As.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_18.2: <bound method> = bound_method %int_3.loc6, %specific_fn.loc6_18.1 [concrete = constants.%bound_method.d64]\n// CHECK:STDOUT:     %Core.IntLiteral.as.As.impl.Convert.call: init %u32 = call %bound_method.loc6_18.2(%int_3.loc6) [concrete = constants.%int_3.d14]\n// CHECK:STDOUT:     %.loc6_18.1: %u32 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_3.d14]\n// CHECK:STDOUT:     %.loc6_18.2: %u32 = converted %int_3.loc6, %.loc6_18.1 [concrete = constants.%int_3.d14]\n// CHECK:STDOUT:     %impl.elem0.loc6_18.2: %.044 = impl_witness_access constants.%ImplicitAs.impl_witness.895, element0 [concrete = constants.%UInt.as.ImplicitAs.impl.Convert.342]\n// CHECK:STDOUT:     %bound_method.loc6_18.3: <bound method> = bound_method %.loc6_18.2, %impl.elem0.loc6_18.2 [concrete = constants.%UInt.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn.loc6_18.2: <specific function> = specific_function %impl.elem0.loc6_18.2, @UInt.as.ImplicitAs.impl.Convert.1(constants.%int_32) [concrete = constants.%UInt.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_18.4: <bound method> = bound_method %.loc6_18.2, %specific_fn.loc6_18.2 [concrete = constants.%bound_method.c86]\n// CHECK:STDOUT:     %UInt.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method.loc6_18.4(%.loc6_18.2) [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc6_18.3: Core.IntLiteral = value_of_initializer %UInt.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc6_18.4: Core.IntLiteral = converted %.loc6_18.2, %.loc6_18.3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %array_type.loc6: type = array_type %.loc6_18.4, %i32.loc6 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/array/element_mismatches.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/array/element_mismatches.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/array/element_mismatches.carbon\n\n// --- fail_arg_wrong_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// CHECK:STDERR: fail_arg_wrong_type.carbon:[[@LINE+7]]:22: error: cannot implicitly convert expression of type `()` to `C` [ConversionFailure]\n// CHECK:STDERR: var a: array(C, 3) = ({}, (), true);\n// CHECK:STDERR:                      ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_arg_wrong_type.carbon:[[@LINE+4]]:22: note: type `()` does not implement interface `Core.ImplicitAs(C)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var a: array(C, 3) = ({}, (), true);\n// CHECK:STDERR:                      ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar a: array(C, 3) = ({}, (), true);\n\n// --- fail_var_wrong_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nclass D {}\n\nvar a: (D, C, D);\n// CHECK:STDERR: fail_var_wrong_type.carbon:[[@LINE+7]]:22: error: cannot implicitly convert expression of type `D` to `C` [ConversionFailure]\n// CHECK:STDERR: var b: array(C, 3) = a;\n// CHECK:STDERR:                      ^\n// CHECK:STDERR: fail_var_wrong_type.carbon:[[@LINE+4]]:22: note: type `D` does not implement interface `Core.ImplicitAs(C)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var b: array(C, 3) = a;\n// CHECK:STDERR:                      ^\n// CHECK:STDERR:\nvar b: array(C, 3) = a;\n\nvar c: (C, D, D);\n// CHECK:STDERR: fail_var_wrong_type.carbon:[[@LINE+7]]:22: error: cannot copy value of type `C` [CopyOfUncopyableType]\n// CHECK:STDERR: var d: array(C, 3) = c;\n// CHECK:STDERR:                      ^\n// CHECK:STDERR: fail_var_wrong_type.carbon:[[@LINE+4]]:22: note: type `C` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var d: array(C, 3) = c;\n// CHECK:STDERR:                      ^\n// CHECK:STDERR:\nvar d: array(C, 3) = c;\n\n// --- fail_arg_too_short.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// CHECK:STDERR: fail_arg_too_short.carbon:[[@LINE+4]]:22: error: cannot initialize array of 3 elements from 2 initializers [ArrayInitFromLiteralArgCountMismatch]\n// CHECK:STDERR: var a: array(C, 3) = ({}, {});\n// CHECK:STDERR:                      ^~~~~~~~\n// CHECK:STDERR:\nvar a: array(C, 3) = ({}, {});\n\n// --- fail_var_too_short.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nvar a: (C, C);\n// CHECK:STDERR: fail_var_too_short.carbon:[[@LINE+4]]:22: error: cannot initialize array of 3 elements from tuple with 2 elements [ArrayInitFromExprArgCountMismatch]\n// CHECK:STDERR: var b: array(C, 3) = a;\n// CHECK:STDERR:                      ^\n// CHECK:STDERR:\nvar b: array(C, 3) = a;\n\n// --- fail_arg_too_long.carbon\n\n// CHECK:STDERR: fail_arg_too_long.carbon:[[@LINE+4]]:23: error: cannot initialize array of 1 element from 3 initializers [ArrayInitFromLiteralArgCountMismatch]\n// CHECK:STDERR: var a: array((), 1) = ((), (), ());\n// CHECK:STDERR:                       ^~~~~~~~~~~~\n// CHECK:STDERR:\nvar a: array((), 1) = ((), (), ());\n"
  },
  {
    "path": "toolchain/check/testdata/array/import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/array/import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/array/import.carbon\n\n// --- library.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() -> array(i32, 42);\n\n// --- user.carbon\n\nimport library \"library\";\n\nfn G(n: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return F()[n];\n  //@dump-sem-ir-end\n}\n\n// --- fail_todo_symbolic_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let value:! array(i32, 1);\n}\n\nclass C {}\n\n// CHECK:STDERR: fail_todo_symbolic_decl.carbon:[[@LINE+4]]:28: error: expression is runtime; expected constant [EvalRequiresConstantValue]\n// CHECK:STDERR: impl C as I where .value = (1,) {}\n// CHECK:STDERR:                            ^~~~\n// CHECK:STDERR:\nimpl C as I where .value = (1,) {}\n\n// --- fail_todo_import_symbolic_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"symbolic_decl\";\n\nfn F() -> array(i32, 1) {\n  //@dump-sem-ir-begin\n  // CHECK:STDERR: fail_todo_import_symbolic_decl.carbon:[[@LINE+4]]:11: error: cannot convert type `C` into type implementing `I` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   return (C as I).value;\n  // CHECK:STDERR:           ^~~~~~\n  // CHECK:STDERR:\n  return (C as I).value;\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- user.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_42: Core.IntLiteral = int_value 42 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_42, %i32 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//library, F, loaded [concrete = constants.%F]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%n.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, imports.%Main.F [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc6_12.1: ref %array_type = temporary_storage\n// CHECK:STDOUT:   %F.call: init %array_type to %.loc6_12.1 = call %F.ref()\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %.loc6_12.2: ref %array_type = temporary %.loc6_12.1, %F.call\n// CHECK:STDOUT:   %.loc6_15.1: ref %i32 = array_index %.loc6_12.2, %n.ref\n// CHECK:STDOUT:   %.loc6_15.2: %i32 = acquire_value %.loc6_15.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc6_15.1: <bound method> = bound_method %.loc6_15.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_15.2: <bound method> = bound_method %.loc6_15.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_15.2(%.loc6_15.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc6_12.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc6_12.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_import_symbolic_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_1, %i32 [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.I: type = import_ref Main//symbolic_decl, I, loaded [concrete = constants.%I.type]\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//symbolic_decl, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> out %return.param: %array_type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %I.ref: type = name_ref I, imports.%Main.I [concrete = constants.%I.type]\n// CHECK:STDOUT:   %value.ref: <error> = name_ref value, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error> to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/array/index_not_literal.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/array/index_not_literal.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/array/index_not_literal.carbon\n\n// --- function_param.carbon\n\nfn F(arr: array(i32, 3), i: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return arr[i];\n  //@dump-sem-ir-end\n}\n\nfn G() -> i32 {\n  //@dump-sem-ir-begin\n  return F((1, 2, 3), 1);\n  //@dump-sem-ir-end\n}\n\n// --- index_non_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(a: array({}, 3)) -> {} {\n  //@dump-sem-ir-begin\n  return a[{.index = 2}.index];\n  //@dump-sem-ir-end\n}\n\n// --- fail_out_of_bound_non_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(a: array({}, 3)) -> {} {\n  // CHECK:STDERR: fail_out_of_bound_non_literal.carbon:[[@LINE+4]]:12: error: array index `3` is past the end of type `array({}, 3)` [ArrayIndexOutOfBounds]\n  // CHECK:STDERR:   return a[{.index = 3}.index];\n  // CHECK:STDERR:            ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return a[{.index = 3}.index];\n}\n\n// CHECK:STDOUT: --- function_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.type.37f: type = tuple_type (Core.IntLiteral, Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.2d5: %tuple.type.37f = tuple_value (%int_1.5b8, %int_2.ecc, %int_3.1ba) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%int_1.5d2, %int_2.ef8, %int_3.822) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%arr.param: %array_type, %i.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %arr.ref: %array_type = name_ref arr, %arr\n// CHECK:STDOUT:   %i.ref: %i32 = name_ref i, %i\n// CHECK:STDOUT:   %.loc4_15.1: ref %array_type = value_as_ref %arr.ref\n// CHECK:STDOUT:   %.loc4_15.2: ref %i32 = array_index %.loc4_15.1, %i.ref\n// CHECK:STDOUT:   %.loc4_15.3: %i32 = acquire_value %.loc4_15.2\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc4_15.1: <bound method> = bound_method %.loc4_15.3, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc4_15.2: <bound method> = bound_method %.loc4_15.3, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc4_15.2(%.loc4_15.3)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %int_1.loc10_13: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2.loc10_16: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %.loc10_20.1: %tuple.type.37f = tuple_literal (%int_1.loc10_13, %int_2.loc10_16, %int_3) [concrete = constants.%tuple.2d5]\n// CHECK:STDOUT:   %int_1.loc10_23: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc10_20.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc10_20.1: <bound method> = bound_method %int_1.loc10_13, %impl.elem0.loc10_20.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc10_20.1: <specific function> = specific_function %impl.elem0.loc10_20.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_20.2: <bound method> = bound_method %int_1.loc10_13, %specific_fn.loc10_20.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_20.1: init %i32 = call %bound_method.loc10_20.2(%int_1.loc10_13) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc10_20.2: init %i32 = converted %int_1.loc10_13, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_20.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc10_20.3: ref %array_type = temporary_storage\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc10_20.4: ref %i32 = array_index %.loc10_20.3, %int_0\n// CHECK:STDOUT:   %.loc10_20.5: init %i32 to %.loc10_20.4 = in_place_init %.loc10_20.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc10_20.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc10_20.3: <bound method> = bound_method %int_2.loc10_16, %impl.elem0.loc10_20.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc10_20.2: <specific function> = specific_function %impl.elem0.loc10_20.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_20.4: <bound method> = bound_method %int_2.loc10_16, %specific_fn.loc10_20.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_20.2: init %i32 = call %bound_method.loc10_20.4(%int_2.loc10_16) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc10_20.6: init %i32 = converted %int_2.loc10_16, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_20.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %int_1.loc10_20: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc10_20.7: ref %i32 = array_index %.loc10_20.3, %int_1.loc10_20\n// CHECK:STDOUT:   %.loc10_20.8: init %i32 to %.loc10_20.7 = in_place_init %.loc10_20.6 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %impl.elem0.loc10_20.3: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc10_20.5: <bound method> = bound_method %int_3, %impl.elem0.loc10_20.3 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:   %specific_fn.loc10_20.3: <specific function> = specific_function %impl.elem0.loc10_20.3, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_20.6: <bound method> = bound_method %int_3, %specific_fn.loc10_20.3 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_20.3: init %i32 = call %bound_method.loc10_20.6(%int_3) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc10_20.9: init %i32 = converted %int_3, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_20.3 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %int_2.loc10_20: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc10_20.10: ref %i32 = array_index %.loc10_20.3, %int_2.loc10_20\n// CHECK:STDOUT:   %.loc10_20.11: init %i32 to %.loc10_20.10 = in_place_init %.loc10_20.9 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc10_20.12: init %array_type to %.loc10_20.3 = array_init (%.loc10_20.5, %.loc10_20.8, %.loc10_20.11) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc10_20.13: init %array_type = converted %.loc10_20.1, %.loc10_20.12 [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc10_20.14: ref %array_type = temporary %.loc10_20.3, %.loc10_20.13\n// CHECK:STDOUT:   %.loc10_20.15: %array_type = acquire_value %.loc10_20.14\n// CHECK:STDOUT:   %impl.elem0.loc10_23: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc10_23.1: <bound method> = bound_method %int_1.loc10_23, %impl.elem0.loc10_23 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc10_23: <specific function> = specific_function %impl.elem0.loc10_23, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_23.2: <bound method> = bound_method %int_1.loc10_23, %specific_fn.loc10_23 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_23: init %i32 = call %bound_method.loc10_23.2(%int_1.loc10_23) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc10_23.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_23 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc10_23.2: %i32 = converted %int_1.loc10_23, %.loc10_23.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.ref(%.loc10_20.15, %.loc10_23.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc10_20.14, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc10_20.14)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- index_non_literal.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3, %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.index: type = struct_type {.index: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.index = struct_value (%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %array_type) -> out %return.param: %empty_struct_type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %array_type = name_ref a, %a\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc6_23.1: %struct_type.index = struct_literal (%int_2) [concrete = constants.%struct]\n// CHECK:STDOUT:   %struct: %struct_type.index = struct_value (%int_2) [concrete = constants.%struct]\n// CHECK:STDOUT:   %.loc6_23.2: %struct_type.index = converted %.loc6_23.1, %struct [concrete = constants.%struct]\n// CHECK:STDOUT:   %.loc6_24.1: Core.IntLiteral = struct_access %.loc6_23.2, element0 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc6_24.1: <bound method> = bound_method %.loc6_24.1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_24.2: <bound method> = bound_method %.loc6_24.1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc6_24.2(%.loc6_24.1) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc6_24.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc6_24.3: %i32 = converted %.loc6_24.1, %.loc6_24.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc6_30.1: ref %array_type = value_as_ref %a.ref\n// CHECK:STDOUT:   %.loc6_30.2: ref %empty_struct_type = array_index %.loc6_30.1, %.loc6_24.3\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc6_30.3: %empty_struct_type = converted %.loc6_30.2, %empty_struct [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc6_30.4: init %empty_struct_type = struct_init () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc6_31: init %empty_struct_type = converted %.loc6_30.3, %.loc6_30.4 [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   return %.loc6_31\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/array/init_dependent_bound.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/array/init_dependent_bound.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/array/init_dependent_bound.carbon\n\n// --- generic_empty.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn G(T:! type) {\n  // We can initialize this without knowing T.\n  //@dump-sem-ir-begin\n  var unused arr: array(T, 0) = ();\n  //@dump-sem-ir-end\n}\n\nclass C {}\n\nfn H() {\n  G(C);\n}\n\n// --- fail_init_dependent_bound.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(N:! i32) {\n  // CHECK:STDERR: fail_init_dependent_bound.carbon:[[@LINE+4]]:35: error: cannot initialize array with dependent bound from a list of initializers [ArrayInitDependentBound]\n  // CHECK:STDERR:   var unused arr: array(i32, N) = (1, 2, 3);\n  // CHECK:STDERR:                                   ^~~~~~~~~\n  // CHECK:STDERR:\n  var unused arr: array(i32, N) = (1, 2, 3);\n}\n\n// --- fail_todo_init_template_dependent_bound.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: This should be valid.\nfn G(template N:! i32) {\n  //@dump-sem-ir-begin\n  // CHECK:STDERR: fail_todo_init_template_dependent_bound.carbon:[[@LINE+4]]:19: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   var unused arr: array(i32, N) = (1, 2, 3);\n  // CHECK:STDERR:                   ^~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused arr: array(i32, N) = (1, 2, 3);\n  //@dump-sem-ir-end\n}\n\nfn H() { G(3); }\n\n// CHECK:STDOUT: --- generic_empty.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %array_type.1b3: type = array_type %int_0, %T [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.1b3 [symbolic]\n// CHECK:STDOUT:   %pattern_type.bd6: type = pattern_type %array_type.1b3 [symbolic]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %array.ca4: %array_type.1b3 = tuple_value () [symbolic]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %array_type.1b3, @Destroy [symbolic]\n// CHECK:STDOUT:   %Destroy.facet.15e: %Destroy.type = facet_value %array_type.1b3, (%Destroy.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.427: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.15e) [symbolic]\n// CHECK:STDOUT:   %.6d6: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.427, %Destroy.facet.15e [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.6d6 = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Destroy.WithSelf.Op(%Destroy.facet.15e) [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %array_type.70a: type = array_type %int_0, %C [concrete]\n// CHECK:STDOUT:   %complete_type.95b: <witness> = complete_type_witness %array_type.70a [concrete]\n// CHECK:STDOUT:   %pattern_type.f2c: type = pattern_type %array_type.70a [concrete]\n// CHECK:STDOUT:   %array.40f: %array_type.70a = tuple_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %custom_witness.8d7: <witness> = custom_witness (%Destroy.Op), @Destroy [concrete]\n// CHECK:STDOUT:   %Destroy.facet.00d: %Destroy.type = facet_value %array_type.70a, (%custom_witness.8d7) [concrete]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.ed3: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.00d) [concrete]\n// CHECK:STDOUT:   %.23f: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.ed3, %Destroy.facet.00d [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%T.loc4_6.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %array_type.loc7_29.2: type = array_type constants.%int_0, %T.loc4_6.1 [symbolic = %array_type.loc7_29.2 (constants.%array_type.1b3)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc7_29.2 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %array_type.loc7_29.2 [symbolic = %pattern_type (constants.%pattern_type.bd6)]\n// CHECK:STDOUT:   %array: @G.%array_type.loc7_29.2 (%array_type.1b3) = tuple_value () [symbolic = %array (constants.%array.ca4)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %array_type.loc7_29.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %array_type.loc7_29.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.15e)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [symbolic = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.427)]\n// CHECK:STDOUT:   %.loc7_3.2: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %Destroy.facet [symbolic = %.loc7_3.2 (constants.%.6d6)]\n// CHECK:STDOUT:   %impl.elem0.loc7_3.2: @G.%.loc7_3.2 (%.6d6) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc7_3.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc7_3.2: <specific function> = specific_impl_function %impl.elem0.loc7_3.2, @Destroy.WithSelf.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc7_3.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %arr.patt: @G.%pattern_type (%pattern_type.bd6) = ref_binding_pattern arr [concrete]\n// CHECK:STDOUT:       %arr.var_patt: @G.%pattern_type (%pattern_type.bd6) = var_pattern %arr.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %arr.var: ref @G.%array_type.loc7_29.2 (%array_type.1b3) = var %arr.var_patt\n// CHECK:STDOUT:     %.loc7_34.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_34.2: init @G.%array_type.loc7_29.2 (%array_type.1b3) to %arr.var = array_init () [symbolic = %array (constants.%array.ca4)]\n// CHECK:STDOUT:     %.loc7_3.1: init @G.%array_type.loc7_29.2 (%array_type.1b3) = converted %.loc7_34.1, %.loc7_34.2 [symbolic = %array (constants.%array.ca4)]\n// CHECK:STDOUT:     assign %arr.var, %.loc7_3.1\n// CHECK:STDOUT:     %.loc7_29: type = splice_block %array_type.loc7_29.1 [symbolic = %array_type.loc7_29.2 (constants.%array_type.1b3)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:       %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:       %array_type.loc7_29.1: type = array_type %int_0, %T.ref [symbolic = %array_type.loc7_29.2 (constants.%array_type.1b3)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %arr: ref @G.%array_type.loc7_29.2 (%array_type.1b3) = ref_binding arr, %arr.var\n// CHECK:STDOUT:     %impl.elem0.loc7_3.1: @G.%.loc7_3.2 (%.6d6) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc7_3.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %bound_method.loc7_3.1: <bound method> = bound_method %arr.var, %impl.elem0.loc7_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc7_3.1: <specific function> = specific_impl_function %impl.elem0.loc7_3.1, @Destroy.WithSelf.Op(constants.%Destroy.facet.15e) [symbolic = %specific_impl_fn.loc7_3.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %bound_method.loc7_3.2: <bound method> = bound_method %arr.var, %specific_impl_fn.loc7_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call: init %empty_tuple.type = call %bound_method.loc7_3.2(%arr.var)\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type.70a) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%C) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%C\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %array_type.loc7_29.2 => constants.%array_type.70a\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.95b\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.f2c\n// CHECK:STDOUT:   %array => constants.%array.40f\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%custom_witness.8d7\n// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.00d\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type => constants.%Destroy.WithSelf.Op.type.ed3\n// CHECK:STDOUT:   %.loc7_3.2 => constants.%.23f\n// CHECK:STDOUT:   %impl.elem0.loc7_3.2 => constants.%Destroy.Op\n// CHECK:STDOUT:   %specific_impl_fn.loc7_3.2 => constants.%Destroy.Op\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_init_template_dependent_bound.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %N.5de: %i32 = symbolic_binding N, 0, template [template]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (Core.IntLiteral, Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type = tuple_value (%int_1, %int_2, %int_3.1ba) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %From: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.2ed: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%From) [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.d29: %Int.as.ImplicitAs.impl.Convert.type.2ed = struct_value () [symbolic]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.640: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.ea2, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.240: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.dd4: %Int.as.ImplicitAs.impl.Convert.type.240 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.290: %ImplicitAs.type.139 = facet_value %i32, (%ImplicitAs.impl_witness.640) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.462: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet.290) [concrete]\n// CHECK:STDOUT:   %.0a7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.462, %ImplicitAs.facet.290 [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_3.822, %Int.as.ImplicitAs.impl.Convert.dd4 [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Int.as.ImplicitAs.impl.Convert.dd4, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.17a: <bound method> = bound_method %int_3.822, %Int.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %inst.splice_block: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.3e5: Core.IntLiteral = splice_block %.502 [concrete = %int_3.1ba] {\n// CHECK:STDOUT:       %impl.elem0: %.0a7 = impl_witness_access %ImplicitAs.impl_witness.640, element0 [concrete = %Int.as.ImplicitAs.impl.Convert.dd4]\n// CHECK:STDOUT:       %bound_method.372: <bound method> = bound_method %int_3.822, %impl.elem0 [concrete = %Int.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:       %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete = %Int.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.28e: <bound method> = bound_method %int_3.822, %specific_fn [concrete = %bound_method.17a]\n// CHECK:STDOUT:       %Int.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method.28e(%int_3.822) [concrete = %int_3.1ba]\n// CHECK:STDOUT:       %.14d: Core.IntLiteral = value_of_initializer %Int.as.ImplicitAs.impl.Convert.call [concrete = %int_3.1ba]\n// CHECK:STDOUT:       %.502: Core.IntLiteral = converted %int_3.822, %.14d [concrete = %int_3.1ba]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.0bc: @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert.type (%Int.as.ImplicitAs.impl.Convert.type.2ed) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert (constants.%Int.as.ImplicitAs.impl.Convert.d29)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.ea2 = impl_witness_table (%Core.import_ref.0bc), @Int.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%N.loc5_15.2: %i32) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %.loc11_30.2: <instruction> = convert_to_value_action %N.ref, Core.IntLiteral [template]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %arr.patt: <error> = ref_binding_pattern arr [concrete]\n// CHECK:STDOUT:       %arr.var_patt: <error> = var_pattern %arr.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %arr.var: ref <error> = var %arr.var_patt [concrete = <error>]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc11_43: %tuple.type = tuple_literal (%int_1, %int_2, %int_3) [concrete = constants.%tuple]\n// CHECK:STDOUT:     assign %arr.var, <error>\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %arr: ref <error> = ref_binding arr, <error> [concrete = <error>]\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%N.5de) {\n// CHECK:STDOUT:   %N.loc5_15.1 => constants.%N.5de\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%int_3.822) {\n// CHECK:STDOUT:   %N.loc5_15.1 => constants.%int_3.822\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %.loc11_30.2 => constants.%inst.splice_block\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/as/adapter_conversion.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/as/adapter_conversion.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/as/adapter_conversion.carbon\n\n// --- adapt_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  var x: i32;\n  var y: i32;\n\n  fn Make() -> A {\n    return {.x = 1, .y = 2};\n  }\n}\n\nclass B {\n  adapt A;\n}\n\nvar a_ref: A = {.x = 1, .y = 2};\nlet a_val: A = a_ref;\n\n// An `as` conversion to an adapter type preserves the expression category.\n//@dump-sem-ir-begin\nlet b_val: B = a_val as B;\nlet b_ptr: B* = &(a_ref as B);\n\nvar b_factory: B = A.Make() as B;\n//@dump-sem-ir-end\n\n// --- adapt_i32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  adapt i32;\n}\n\n//@dump-sem-ir-begin\nlet a: A = (1 as i32) as A;\nlet n: i32 = a as i32;\n//@dump-sem-ir-end\n\n// --- multi_level_adapt.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A { adapt {}; }\nclass B { adapt A; }\nclass C { adapt B; }\nclass D { adapt C; }\n\n//@dump-sem-ir-begin\nlet d: D = {} as D;\n//@dump-sem-ir-end\n\n\n// --- init_class_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  var x: i32;\n  var y: i32;\n}\n\nclass B {\n  adapt A;\n}\n\n//@dump-sem-ir-begin\nlet b_value: B = ({.x = 1, .y = 2} as A) as B;\n//@dump-sem-ir-end\n\n// --- init_class_variable.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  var x: i32;\n  var y: i32;\n}\n\nclass B {\n  adapt A;\n}\n\nvar b_init: B = ({.x = 1, .y = 2} as A) as B;\n\n// --- init_tuple_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Noncopyable {\n  // TODO: Ensure this remains non-copyable once we have rules for class copyability.\n}\n\nclass A {\n  adapt ({}, Noncopyable);\n}\n\nfn F(a: A) {\n  //@dump-sem-ir-begin\n  let unused a_value: A = (a as ({}, Noncopyable)) as A;\n  //@dump-sem-ir-end\n}\n\n// --- fail_init_tuple_variable.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Noncopyable {\n  // TODO: Ensure this remains non-copyable once we have rules for class copyability.\n}\n\nclass A {\n  adapt ({}, Noncopyable);\n}\n\nfn F(a: A) {\n  // TODO: Here, we treat `a as (i32, Noncopyable)` as a value expression, not an\n  // initializing expression, so `(...) as A` is a value expression too, requiring\n  // a copy to perform initialization. It's not clear whether that is the right\n  // behavior.\n\n  // CHECK:STDERR: fail_init_tuple_variable.carbon:[[@LINE+10]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]\n  // CHECK:STDERR:   var unused a_init: A = (a as ({}, Noncopyable)) as A;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_init_tuple_variable.carbon:[[@LINE+7]]:3: note: type `Noncopyable` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var unused a_init: A = (a as ({}, Noncopyable)) as A;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_init_tuple_variable.carbon:[[@LINE+4]]:26: note: in copy of `A` [InCopy]\n  // CHECK:STDERR:   var unused a_init: A = (a as ({}, Noncopyable)) as A;\n  // CHECK:STDERR:                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused a_init: A = (a as ({}, Noncopyable)) as A;\n}\n\n// --- fail_adapt_init_from_struct.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  var x: ();\n}\n\nclass B {\n  adapt A;\n}\n\n// We do not try to implicitly convert from the first operand of `as` to the\n// adapted type of the second operand.\n\n// CHECK:STDERR: fail_adapt_init_from_struct.carbon:[[@LINE+7]]:12: error: cannot convert expression of type `{.x: ()}` to `B` with `as` [ConversionFailure]\n// CHECK:STDERR: var b: B = {.x = ()} as B;\n// CHECK:STDERR:            ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_adapt_init_from_struct.carbon:[[@LINE+4]]:12: note: type `{.x: ()}` does not implement interface `Core.As(B)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var b: B = {.x = ()} as B;\n// CHECK:STDERR:            ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar b: B = {.x = ()} as B;\n\n// CHECK:STDOUT: --- adapt_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %A.Make.type: type = fn_type @A.Make [concrete]\n// CHECK:STDOUT:   %A.Make: %A.Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %ptr.27c: type = ptr_type %B [concrete]\n// CHECK:STDOUT:   %pattern_type.191: type = pattern_type %ptr.27c [concrete]\n// CHECK:STDOUT:   %a_ref.var: ref %B = var file.%a_ref.var_patt [concrete]\n// CHECK:STDOUT:   %addr: %ptr.27c = addr_of %a_ref.var [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b_val.patt: %pattern_type.1f4 = value_binding_pattern b_val [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.ref.loc22: type = name_ref B, %B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %b_val: %B = value_binding b_val, @__global_init.%.loc22_22.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b_ptr.patt: %pattern_type.191 = value_binding_pattern b_ptr [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc23: type = splice_block %ptr [concrete = constants.%ptr.27c] {\n// CHECK:STDOUT:     %B.ref.loc23: type = name_ref B, %B.decl [concrete = constants.%B]\n// CHECK:STDOUT:     %ptr: type = ptr_type %B.ref.loc23 [concrete = constants.%ptr.27c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b_ptr: %ptr.27c = value_binding b_ptr, @__global_init.%addr\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b_factory.patt: %pattern_type.1f4 = ref_binding_pattern b_factory [concrete]\n// CHECK:STDOUT:     %b_factory.var_patt: %pattern_type.1f4 = var_pattern %b_factory.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b_factory.var: ref %B = var %b_factory.var_patt [concrete]\n// CHECK:STDOUT:   %B.ref.loc25: type = name_ref B, %B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %b_factory: ref %B = ref_binding b_factory, %b_factory.var [concrete = %b_factory.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %a_val.ref: %A = name_ref a_val, file.%a_val\n// CHECK:STDOUT:   %B.ref.loc22: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc22_22.1: %B = as_compatible %a_val.ref\n// CHECK:STDOUT:   %.loc22_22.2: %B = converted %a_val.ref, %.loc22_22.1\n// CHECK:STDOUT:   %a_ref.ref.loc23: ref %A = name_ref a_ref, file.%a_ref [concrete = file.%a_ref.var]\n// CHECK:STDOUT:   %B.ref.loc23: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc23_25.1: ref %B = as_compatible %a_ref.ref.loc23 [concrete = constants.%a_ref.var]\n// CHECK:STDOUT:   %.loc23_25.2: ref %B = converted %a_ref.ref.loc23, %.loc23_25.1 [concrete = constants.%a_ref.var]\n// CHECK:STDOUT:   %addr: %ptr.27c = addr_of %.loc23_25.2 [concrete = constants.%addr]\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %Make.ref: %A.Make.type = name_ref Make, @A.%A.Make.decl [concrete = constants.%A.Make]\n// CHECK:STDOUT:   %.loc25_1: ref %B = splice_block file.%b_factory.var [concrete = file.%b_factory.var] {}\n// CHECK:STDOUT:   %A.Make.call: init %A to %.loc25_1 = call %Make.ref()\n// CHECK:STDOUT:   %B.ref.loc25: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc25_29.1: init %B = as_compatible %A.Make.call\n// CHECK:STDOUT:   %.loc25_29.2: init %B = converted %A.Make.call, %.loc25_29.1\n// CHECK:STDOUT:   assign file.%b_factory.var, %.loc25_29.2\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- adapt_i32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %As.type.047: type = facet_type <@As, @As(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.type.09e: type = fn_type @Core.IntLiteral.as.As.impl.Convert, @Core.IntLiteral.as.As.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.dbe: %Core.IntLiteral.as.As.impl.Convert.type.09e = struct_value () [symbolic]\n// CHECK:STDOUT:   %As.impl_witness.ab6: <witness> = impl_witness imports.%As.impl_witness_table.9fc, @Core.IntLiteral.as.As.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.type.8ec: type = fn_type @Core.IntLiteral.as.As.impl.Convert, @Core.IntLiteral.as.As.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.29b: %Core.IntLiteral.as.As.impl.Convert.type.8ec = struct_value () [concrete]\n// CHECK:STDOUT:   %As.facet: %As.type.047 = facet_value Core.IntLiteral, (%As.impl_witness.ab6) [concrete]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.e5b: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%i32, %As.facet) [concrete]\n// CHECK:STDOUT:   %.9ed: type = fn_type_with_self_type %As.WithSelf.Convert.type.e5b, %As.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.As.impl.Convert.29b [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.As.impl.Convert.29b, @Core.IntLiteral.as.As.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.As.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_1.360: %A = int_value 1 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.ca0: @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert.type (%Core.IntLiteral.as.As.impl.Convert.type.09e) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert (constants.%Core.IntLiteral.as.As.impl.Convert.dbe)]\n// CHECK:STDOUT:   %As.impl_witness_table.9fc = impl_witness_table (%Core.import_ref.ca0), @Core.IntLiteral.as.As.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1ab = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.ref: type = name_ref A, %A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %a: %A = value_binding a, @__global_init.%.loc9_23.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %n: %i32 = value_binding n, @__global_init.%.loc10_16.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %i32.loc9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0: %.9ed = impl_witness_access constants.%As.impl_witness.ab6, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.29b]\n// CHECK:STDOUT:   %bound_method.loc9_15.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.As.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_15.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call: init %i32 = call %bound_method.loc9_15.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc9_15.1: %i32 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc9_15.2: %i32 = converted %int_1, %.loc9_15.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc9_23.1: %A = as_compatible %.loc9_15.2 [concrete = constants.%int_1.360]\n// CHECK:STDOUT:   %.loc9_23.2: %A = converted %.loc9_15.2, %.loc9_23.1 [concrete = constants.%int_1.360]\n// CHECK:STDOUT:   %a.ref: %A = name_ref a, file.%a\n// CHECK:STDOUT:   %i32.loc10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc10_16.1: %i32 = as_compatible %a.ref\n// CHECK:STDOUT:   %.loc10_16.2: %i32 = converted %a.ref, %.loc10_16.1\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- multi_level_adapt.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %D.val: %D = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type = value_binding_pattern d [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.ref: type = name_ref D, %D.decl [concrete = constants.%D]\n// CHECK:STDOUT:   %d: %D = value_binding d, @__global_init.%.loc10_15.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc10_13: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc10_15.1: %D = as_compatible %empty_struct [concrete = constants.%D.val]\n// CHECK:STDOUT:   %.loc10_15.2: %D = converted %.loc10_13, %.loc10_15.1 [concrete = constants.%D.val]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- init_class_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.x.y.4cf: type = struct_type {.x: Core.IntLiteral, .y: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.x.y.4cf = struct_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %A.val: %A = struct_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %B.val: %B = struct_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b_value.patt: %pattern_type.1f4 = value_binding_pattern b_value [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.ref: type = name_ref B, %B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc14_42.1: ref %B = temporary @__global_init.%.loc14_34.3, @__global_init.%.loc14_42.2\n// CHECK:STDOUT:   %.loc14_42.2: %B = acquire_value %.loc14_42.1\n// CHECK:STDOUT:   %b_value: %B = value_binding b_value, %.loc14_42.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc14_34.1: %struct_type.x.y.4cf = struct_literal (%int_1, %int_2) [concrete = constants.%struct]\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %impl.elem0.loc14_34.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc14_34.1: <bound method> = bound_method %int_1, %impl.elem0.loc14_34.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc14_34.1: <specific function> = specific_function %impl.elem0.loc14_34.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_34.2: <bound method> = bound_method %int_1, %specific_fn.loc14_34.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_34.1: init %i32 = call %bound_method.loc14_34.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc14_34.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_34.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc14_34.3: ref %A = temporary_storage\n// CHECK:STDOUT:   %.loc14_34.4: ref %i32 = class_element_access %.loc14_34.3, element0\n// CHECK:STDOUT:   %.loc14_34.5: init %i32 to %.loc14_34.4 = in_place_init %.loc14_34.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc14_34.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc14_34.3: <bound method> = bound_method %int_2, %impl.elem0.loc14_34.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc14_34.2: <specific function> = specific_function %impl.elem0.loc14_34.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_34.4: <bound method> = bound_method %int_2, %specific_fn.loc14_34.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_34.2: init %i32 = call %bound_method.loc14_34.4(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc14_34.6: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_34.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc14_34.7: ref %i32 = class_element_access %.loc14_34.3, element1\n// CHECK:STDOUT:   %.loc14_34.8: init %i32 to %.loc14_34.7 = in_place_init %.loc14_34.6 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc14_34.9: init %A to %.loc14_34.3 = class_init (%.loc14_34.5, %.loc14_34.8) [concrete = constants.%A.val]\n// CHECK:STDOUT:   %.loc14_36: init %A = converted %.loc14_34.1, %.loc14_34.9 [concrete = constants.%A.val]\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc14_42.1: init %B = as_compatible %.loc14_36 [concrete = constants.%B.val]\n// CHECK:STDOUT:   %.loc14_42.2: init %B = converted %.loc14_36, %.loc14_42.1 [concrete = constants.%B.val]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- init_tuple_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Noncopyable: type = class_type @Noncopyable [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.c8c: type = tuple_type (%empty_struct_type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.c8c = tuple_value (%empty_struct, %Noncopyable) [concrete]\n// CHECK:STDOUT:   %tuple.type.037: type = tuple_type (%empty_struct_type, %Noncopyable) [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %A [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %A) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a_value.patt: %pattern_type = value_binding_pattern a_value [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.ref: %A = name_ref a, %a\n// CHECK:STDOUT:   %.loc14_35: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Noncopyable.ref: type = name_ref Noncopyable, file.%Noncopyable.decl [concrete = constants.%Noncopyable]\n// CHECK:STDOUT:   %.loc14_49.1: %tuple.type.c8c = tuple_literal (%.loc14_35, %Noncopyable.ref) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %.loc14_49.2: type = converted constants.%empty_struct, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %.loc14_49.3: type = converted %.loc14_49.1, constants.%tuple.type.037 [concrete = constants.%tuple.type.037]\n// CHECK:STDOUT:   %.loc14_30.1: %tuple.type.037 = as_compatible %a.ref\n// CHECK:STDOUT:   %.loc14_30.2: %tuple.type.037 = converted %a.ref, %.loc14_30.1\n// CHECK:STDOUT:   %A.ref.loc14_55: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc14_52.1: %A = as_compatible %.loc14_30.2\n// CHECK:STDOUT:   %.loc14_52.2: %A = converted %.loc14_30.2, %.loc14_52.1\n// CHECK:STDOUT:   %A.ref.loc14_23: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %a_value: %A = value_binding a_value, %.loc14_52.2\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/as/basics.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/as/basics.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/as/basics.carbon\n\n// --- simple_as.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Main() -> {.x: (), .y: ()} {\n//@dump-sem-ir-begin\n  return {.y = (), .x = ()} as {.x: (), .y: ()};\n//@dump-sem-ir-end\n}\n\n// --- as_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nlet t: type = ({}, {}) as type;\n//@dump-sem-ir-end\n\n// --- as_tuple.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {\n  // ...\n}\n\nfn Make() -> X;\n\nfn Let() {\n  // This should create value bindings for both tuple elements.\n  //@dump-sem-ir-begin\n  let unused a: (X, X) = (Make(), Make()) as (X, X);\n  //@dump-sem-ir-end\n}\n\nfn Var() {\n  // This should initialize both tuple elements in place.\n  //@dump-sem-ir-begin\n  var unused b: (X, X) = (Make(), Make()) as (X, X);\n  //@dump-sem-ir-end\n}\n\n// --- identity.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {\n  // ...\n}\n\nfn Value(n: X) {\n  //@dump-sem-ir-begin\n  let unused m: X = n as X;\n  //@dump-sem-ir-end\n}\n\nfn Reference(p: X*) {\n  //@dump-sem-ir-begin\n  let unused q: X* = &(*p as X);\n  //@dump-sem-ir-end\n}\n\nfn Make() -> X;\n\nfn Initializing() {\n  //@dump-sem-ir-begin\n  var unused x: X = (Make() as X);\n  //@dump-sem-ir-end\n}\n\n// --- overloaded.carbon\n\nclass X {\n  var x: ();\n}\n\nclass Y {\n  var y: ();\n}\n\nimpl Y as Core.As(X) {\n  fn Convert[self: Y]() -> X { return {.x = self.y}; }\n}\n\nimpl X as Core.As(Y) {\n  fn Convert[self: X]() -> Y { return {.y = self.x}; }\n}\n\n//@dump-sem-ir-begin\nlet n: Y = ({.x = ()} as X) as Y;\n//@dump-sem-ir-end\n\n// --- fail_no_conversion.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+7]]:13: error: cannot convert expression of type `Core.IntLiteral` to `{}` with `as` [ConversionFailure]\n// CHECK:STDERR: let a: {} = 1 as {};\n// CHECK:STDERR:             ^~~~~~~\n// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+4]]:13: note: type `Core.IntLiteral` does not implement interface `Core.As({})` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: let a: {} = 1 as {};\n// CHECK:STDERR:             ^~~~~~~\n// CHECK:STDERR:\nlet a: {} = 1 as {};\n\n// --- fail_not_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_not_type.carbon:[[@LINE+7]]:32: error: cannot implicitly convert non-type value of type `{.x: ()}` to `type` [ConversionFailureNonTypeToFacet]\n// CHECK:STDERR: let n: {.x: ()} = {.x = ()} as {.x = ()};\n// CHECK:STDERR:                                ^~~~~~~~~\n// CHECK:STDERR: fail_not_type.carbon:[[@LINE+4]]:32: note: type `{.x: ()}` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: let n: {.x: ()} = {.x = ()} as {.x = ()};\n// CHECK:STDERR:                                ^~~~~~~~~\n// CHECK:STDERR:\nlet n: {.x: ()} = {.x = ()} as {.x = ()};\n\n// CHECK:STDOUT: --- simple_as.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct_type.x.y: type = struct_type {.x: %empty_tuple.type, .y: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %struct_type.y.x: type = struct_type {.y: %empty_tuple.type, .x: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %struct.f76: %struct_type.y.x = struct_value (%empty_tuple, %empty_tuple) [concrete]\n// CHECK:STDOUT:   %struct.005: %struct_type.x.y = struct_value (%empty_tuple, %empty_tuple) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() -> out %return.param: %struct_type.x.y {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc6_17: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_26: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_27.1: %struct_type.y.x = struct_literal (%.loc6_17, %.loc6_26) [concrete = constants.%struct.f76]\n// CHECK:STDOUT:   %.loc6_38.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_38.2: type = converted %.loc6_38.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   %.loc6_46.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_46.2: type = converted %.loc6_46.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   %struct_type.x.y.loc6: type = struct_type {.x: %empty_tuple.type, .y: %empty_tuple.type} [concrete = constants.%struct_type.x.y]\n// CHECK:STDOUT:   %empty_tuple.loc6_26: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_27.2: %empty_tuple.type = converted %.loc6_26, %empty_tuple.loc6_26 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %empty_tuple.loc6_17: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_27.3: %empty_tuple.type = converted %.loc6_17, %empty_tuple.loc6_17 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %struct: %struct_type.x.y = struct_value (%.loc6_27.2, %.loc6_27.3) [concrete = constants.%struct.005]\n// CHECK:STDOUT:   %.loc6_29.1: %struct_type.x.y = converted %.loc6_27.1, %struct [concrete = constants.%struct.005]\n// CHECK:STDOUT:   %.loc6_29.2: %empty_tuple.type = struct_access %.loc6_29.1, element0 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_29.3: ref %empty_tuple.type = struct_access %return.param, element0\n// CHECK:STDOUT:   %.loc6_29.4: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_29.5: init %empty_tuple.type = converted %.loc6_29.2, %.loc6_29.4 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_29.6: %empty_tuple.type = struct_access %.loc6_29.1, element1 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_29.7: ref %empty_tuple.type = struct_access %return.param, element1\n// CHECK:STDOUT:   %.loc6_29.8: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_29.9: init %empty_tuple.type = converted %.loc6_29.6, %.loc6_29.8 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_29.10: init %struct_type.x.y to %return.param = struct_init (%.loc6_29.5, %.loc6_29.9) [concrete = constants.%struct.005]\n// CHECK:STDOUT:   %.loc6_48: init %struct_type.x.y = converted %.loc6_29.1, %.loc6_29.10 [concrete = constants.%struct.005]\n// CHECK:STDOUT:   return %.loc6_48 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- as_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.b6b: type = tuple_type (%empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.b6b = tuple_value (%empty_struct, %empty_struct) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %t.patt: %pattern_type = value_binding_pattern t [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc5: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   %t: type = value_binding t, @__global_init.%.loc5_24.3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc5_17: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc5_21: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc5_22: %tuple.type.b6b = tuple_literal (%.loc5_17, %.loc5_21) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %.loc5_27: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   %.loc5_24.1: type = converted constants.%empty_struct, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %.loc5_24.2: type = converted constants.%empty_struct, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %.loc5_24.3: type = converted %.loc5_22, constants.%tuple.type.b6b [concrete = constants.%tuple.type.b6b]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- as_tuple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%X, %X) [concrete]\n// CHECK:STDOUT:   %tuple.type.2de: type = tuple_type (%X, %X) [concrete]\n// CHECK:STDOUT:   %pattern_type.e9d: type = pattern_type %tuple.type.2de [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc13 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc20 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Let() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.e9d = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Make.ref.loc13_27: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %.loc13_32.1: ref %X = temporary_storage\n// CHECK:STDOUT:   %Make.call.loc13_32: init %X to %.loc13_32.1 = call %Make.ref.loc13_27()\n// CHECK:STDOUT:   %Make.ref.loc13_35: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %.loc13_40.1: ref %X = temporary_storage\n// CHECK:STDOUT:   %Make.call.loc13_40: init %X to %.loc13_40.1 = call %Make.ref.loc13_35()\n// CHECK:STDOUT:   %.loc13_41.1: %tuple.type.2de = tuple_literal (%Make.call.loc13_32, %Make.call.loc13_40)\n// CHECK:STDOUT:   %X.ref.loc13_47: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %X.ref.loc13_50: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc13_51.1: %tuple.type.24b = tuple_literal (%X.ref.loc13_47, %X.ref.loc13_50) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %.loc13_51.2: type = converted %.loc13_51.1, constants.%tuple.type.2de [concrete = constants.%tuple.type.2de]\n// CHECK:STDOUT:   %.loc13_22.1: type = splice_block %.loc13_22.3 [concrete = constants.%tuple.type.2de] {\n// CHECK:STDOUT:     %X.ref.loc13_18: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %X.ref.loc13_21: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %.loc13_22.2: %tuple.type.24b = tuple_literal (%X.ref.loc13_18, %X.ref.loc13_21) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc13_22.3: type = converted %.loc13_22.2, constants.%tuple.type.2de [concrete = constants.%tuple.type.2de]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc13_32.2: ref %X = temporary %.loc13_32.1, %Make.call.loc13_32\n// CHECK:STDOUT:   %.loc13_32.3: %X = acquire_value %.loc13_32.2\n// CHECK:STDOUT:   %.loc13_40.2: ref %X = temporary %.loc13_40.1, %Make.call.loc13_40\n// CHECK:STDOUT:   %.loc13_40.3: %X = acquire_value %.loc13_40.2\n// CHECK:STDOUT:   %tuple: %tuple.type.2de = tuple_value (%.loc13_32.3, %.loc13_40.3)\n// CHECK:STDOUT:   %.loc13_41.2: %tuple.type.2de = converted %.loc13_41.1, %tuple\n// CHECK:STDOUT:   %a: %tuple.type.2de = value_binding a, %.loc13_41.2\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13_40: <bound method> = bound_method %.loc13_40.2, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc13_40: init %empty_tuple.type = call %Destroy.Op.bound.loc13_40(%.loc13_40.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13_32: <bound method> = bound_method %.loc13_32.2, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc13_32: init %empty_tuple.type = call %Destroy.Op.bound.loc13_32(%.loc13_32.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc13(%self.param: ref %X) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Var() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.e9d = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.e9d = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %tuple.type.2de = var %b.var_patt\n// CHECK:STDOUT:   %Make.ref.loc20_27: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %tuple.elem0: ref %X = tuple_access %b.var, element0\n// CHECK:STDOUT:   %Make.call.loc20_32: init %X to %tuple.elem0 = call %Make.ref.loc20_27()\n// CHECK:STDOUT:   %Make.ref.loc20_35: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %tuple.elem1: ref %X = tuple_access %b.var, element1\n// CHECK:STDOUT:   %Make.call.loc20_40: init %X to %tuple.elem1 = call %Make.ref.loc20_35()\n// CHECK:STDOUT:   %.loc20_41.1: %tuple.type.2de = tuple_literal (%Make.call.loc20_32, %Make.call.loc20_40)\n// CHECK:STDOUT:   %X.ref.loc20_47: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %X.ref.loc20_50: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc20_51.1: %tuple.type.24b = tuple_literal (%X.ref.loc20_47, %X.ref.loc20_50) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %.loc20_51.2: type = converted %.loc20_51.1, constants.%tuple.type.2de [concrete = constants.%tuple.type.2de]\n// CHECK:STDOUT:   %.loc20_41.2: init %tuple.type.2de to %b.var = tuple_init (%Make.call.loc20_32, %Make.call.loc20_40)\n// CHECK:STDOUT:   %.loc20_3: init %tuple.type.2de = converted %.loc20_41.1, %.loc20_41.2\n// CHECK:STDOUT:   assign %b.var, %.loc20_3\n// CHECK:STDOUT:   %.loc20_22.1: type = splice_block %.loc20_22.3 [concrete = constants.%tuple.type.2de] {\n// CHECK:STDOUT:     %X.ref.loc20_18: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %X.ref.loc20_21: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %.loc20_22.2: %tuple.type.24b = tuple_literal (%X.ref.loc20_18, %X.ref.loc20_21) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc20_22.3: type = converted %.loc20_22.2, constants.%tuple.type.2de [concrete = constants.%tuple.type.2de]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %tuple.type.2de = ref_binding b, %b.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %b.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%b.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc20(%self.param: ref %tuple.type.2de) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- identity.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %pattern_type.05f: type = pattern_type %X [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %ptr.2a9: type = ptr_type %X [concrete]\n// CHECK:STDOUT:   %pattern_type.37f: type = pattern_type %ptr.2a9 [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Value(%n.param: %X) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %m.patt: %pattern_type.05f = value_binding_pattern m [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %n.ref: %X = name_ref n, %n\n// CHECK:STDOUT:   %X.ref.loc10_26: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %X.ref.loc10_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %m: %X = value_binding m, %n.ref\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Reference(%p.param: %ptr.2a9) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %q.patt: %pattern_type.37f = value_binding_pattern q [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %p.ref: %ptr.2a9 = name_ref p, %p\n// CHECK:STDOUT:   %.loc16_24: ref %X = deref %p.ref\n// CHECK:STDOUT:   %X.ref.loc16_30: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %addr: %ptr.2a9 = addr_of %.loc16_24\n// CHECK:STDOUT:   %.loc16_18: type = splice_block %ptr.loc16 [concrete = constants.%ptr.2a9] {\n// CHECK:STDOUT:     %X.ref.loc16_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %ptr.loc16: type = ptr_type %X.ref.loc16_17 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %q: %ptr.2a9 = value_binding q, %addr\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Initializing() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.05f = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type.05f = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %X = var %x.var_patt\n// CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %.loc24: ref %X = splice_block %x.var {}\n// CHECK:STDOUT:   %Make.call: init %X to %.loc24 = call %Make.ref()\n// CHECK:STDOUT:   %X.ref.loc24_32: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   assign %x.var, %Make.call\n// CHECK:STDOUT:   %X.ref.loc24_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %x: ref %X = ref_binding x, %x.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %x.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%x.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %X) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- overloaded.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %Y: type = class_type @Y [concrete]\n// CHECK:STDOUT:   %pattern_type.77c: type = pattern_type %Y [concrete]\n// CHECK:STDOUT:   %struct.948: %struct_type.x = struct_value (%empty_tuple) [concrete]\n// CHECK:STDOUT:   %X.val: %X = struct_value (%empty_tuple) [concrete]\n// CHECK:STDOUT:   %As.type.d1e: type = facet_type <@As, @As(%Y)> [concrete]\n// CHECK:STDOUT:   %As.impl_witness.e92: <witness> = impl_witness @X.as.As.impl.%As.impl_witness_table [concrete]\n// CHECK:STDOUT:   %X.as.As.impl.Convert.type: type = fn_type @X.as.As.impl.Convert [concrete]\n// CHECK:STDOUT:   %X.as.As.impl.Convert: %X.as.As.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %As.facet.c03: %As.type.d1e = facet_value %X, (%As.impl_witness.e92) [concrete]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.edc: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%Y, %As.facet.c03) [concrete]\n// CHECK:STDOUT:   %.84a: type = fn_type_with_self_type %As.WithSelf.Convert.type.edc, %As.facet.c03 [concrete]\n// CHECK:STDOUT:   %X.as.As.impl.Convert.bound: <bound method> = bound_method %X.val, %X.as.As.impl.Convert [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %n.patt: %pattern_type.77c = value_binding_pattern n [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Y.ref: type = name_ref Y, %Y.decl [concrete = constants.%Y]\n// CHECK:STDOUT:   %.loc19_29.1: ref %Y = temporary @__global_init.%.loc19_29.1, @__global_init.%.loc19_29.2\n// CHECK:STDOUT:   %.loc19_29.2: %Y = acquire_value %.loc19_29.1\n// CHECK:STDOUT:   %n: %Y = value_binding n, %.loc19_29.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc19_20.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc19_21.1: %struct_type.x = struct_literal (%.loc19_20.1) [concrete = constants.%struct.948]\n// CHECK:STDOUT:   %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc19_21.2: ref %X = temporary_storage\n// CHECK:STDOUT:   %.loc19_21.3: ref %empty_tuple.type = class_element_access %.loc19_21.2, element0\n// CHECK:STDOUT:   %.loc19_20.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc19_21.4: init %empty_tuple.type = converted %.loc19_20.1, %.loc19_20.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc19_21.5: init %X to %.loc19_21.2 = class_init (%.loc19_21.4) [concrete = constants.%X.val]\n// CHECK:STDOUT:   %.loc19_23.1: init %X = converted %.loc19_21.1, %.loc19_21.5 [concrete = constants.%X.val]\n// CHECK:STDOUT:   %Y.ref: type = name_ref Y, file.%Y.decl [concrete = constants.%Y]\n// CHECK:STDOUT:   %impl.elem0: %.84a = impl_witness_access constants.%As.impl_witness.e92, element0 [concrete = constants.%X.as.As.impl.Convert]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %.loc19_23.1, %impl.elem0 [concrete = constants.%X.as.As.impl.Convert.bound]\n// CHECK:STDOUT:   %.loc19_29.1: ref %Y = temporary_storage\n// CHECK:STDOUT:   %.loc19_23.2: ref %X = temporary %.loc19_21.2, %.loc19_23.1\n// CHECK:STDOUT:   %.loc19_23.3: %X = acquire_value %.loc19_23.2\n// CHECK:STDOUT:   %X.as.As.impl.Convert.call: init %Y to %.loc19_29.1 = call %bound_method(%.loc19_23.3)\n// CHECK:STDOUT:   %.loc19_29.2: init %Y = converted %.loc19_23.1, %X.as.As.impl.Convert.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/as/const.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/as/const.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/as/const.carbon\n\n// --- add_const.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nfn Init() -> X;\nlet value: X = Init();\nvar reference: X;\nlet ptr: X* = &reference;\n\nfn Use() {\n  // TODO: Should some of these be valid without the `as`?\n  //@dump-sem-ir-begin\n  var unused i: const X = Init() as const X;\n  let unused v: const X = value as const X;\n  let unused a: const X* = &(reference as const X);\n  let unused b: const X* = ptr as const X*;\n  //@dump-sem-ir-end\n}\n\n// --- remove_const.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nfn Init() -> const X;\nlet value: const X = Init();\n\nfn Use() {\n  // TODO: Should some of these be valid without the `as`?\n  //@dump-sem-ir-begin\n  var unused i: X = Init() as X;\n  let unused v: X = value as X;\n  //@dump-sem-ir-end\n}\n\n// --- fail_cannot_remove_const.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nvar reference: const X;\nlet ptr: const X* = &reference;\n\nfn Use() {\n  // CHECK:STDERR: fail_cannot_remove_const.carbon:[[@LINE+7]]:24: error: cannot convert expression of type `const X` to `X` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused a: X* = &(reference as X);\n  // CHECK:STDERR:                        ^~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_const.carbon:[[@LINE+4]]:24: note: type `const X` does not implement interface `Core.As(X)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused a: X* = &(reference as X);\n  // CHECK:STDERR:                        ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused a: X* = &(reference as X);\n  // CHECK:STDERR: fail_cannot_remove_const.carbon:[[@LINE+7]]:22: error: cannot convert expression of type `const X*` to `X*` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused b: X* = ptr as X*;\n  // CHECK:STDERR:                      ^~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_const.carbon:[[@LINE+4]]:22: note: type `const X*` does not implement interface `Core.As(X*)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused b: X* = ptr as X*;\n  // CHECK:STDERR:                      ^~~~~~~~~\n  // CHECK:STDERR:\n  let unused b: X* = ptr as X*;\n}\n\n// --- unsafe_remove_const.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nvar reference: const X;\nlet ptr: const X* = &reference;\n\nfn Use() {\n  //@dump-sem-ir-begin\n  let unused a: X* = &(reference unsafe as X);\n  let unused b: X* = ptr unsafe as X*;\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- add_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %Init.type: type = fn_type @Init [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Init: %Init.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.2a9: type = ptr_type %X [concrete]\n// CHECK:STDOUT:   %const: type = const_type %X [concrete]\n// CHECK:STDOUT:   %pattern_type.c9e: type = pattern_type %const [concrete]\n// CHECK:STDOUT:   %ptr.d4c: type = ptr_type %const [concrete]\n// CHECK:STDOUT:   %pattern_type.bf1: type = pattern_type %ptr.d4c [concrete]\n// CHECK:STDOUT:   %reference.var: ref %const = var file.%reference.var_patt [concrete]\n// CHECK:STDOUT:   %addr.160: %ptr.d4c = addr_of %reference.var [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.c9e = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.c9e = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %const = var %i.var_patt\n// CHECK:STDOUT:   %Init.ref: %Init.type = name_ref Init, file.%Init.decl [concrete = constants.%Init]\n// CHECK:STDOUT:   %.loc14_3: ref %const = splice_block %i.var {}\n// CHECK:STDOUT:   %Init.call: init %X to %.loc14_3 = call %Init.ref()\n// CHECK:STDOUT:   %X.ref.loc14_43: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %const.loc14_37: type = const_type %X.ref.loc14_43 [concrete = constants.%const]\n// CHECK:STDOUT:   %.loc14_34.1: init %const = as_compatible %Init.call\n// CHECK:STDOUT:   %.loc14_34.2: init %const = converted %Init.call, %.loc14_34.1\n// CHECK:STDOUT:   assign %i.var, %.loc14_34.2\n// CHECK:STDOUT:   %.loc14_17: type = splice_block %const.loc14_17 [concrete = constants.%const] {\n// CHECK:STDOUT:     %X.ref.loc14_23: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %const.loc14_17: type = const_type %X.ref.loc14_23 [concrete = constants.%const]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i: ref %const = ref_binding i, %i.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.c9e = value_binding_pattern v [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.ref: %X = name_ref value, file.%value\n// CHECK:STDOUT:   %X.ref.loc15_42: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %const.loc15_36: type = const_type %X.ref.loc15_42 [concrete = constants.%const]\n// CHECK:STDOUT:   %.loc15_33.1: %const = as_compatible %value.ref\n// CHECK:STDOUT:   %.loc15_33.2: %const = converted %value.ref, %.loc15_33.1\n// CHECK:STDOUT:   %.loc15_17: type = splice_block %const.loc15_17 [concrete = constants.%const] {\n// CHECK:STDOUT:     %X.ref.loc15_23: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %const.loc15_17: type = const_type %X.ref.loc15_23 [concrete = constants.%const]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: %const = value_binding v, %.loc15_33.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.bf1 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %reference.ref: ref %X = name_ref reference, file.%reference [concrete = file.%reference.var]\n// CHECK:STDOUT:   %X.ref.loc16_49: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %const.loc16_43: type = const_type %X.ref.loc16_49 [concrete = constants.%const]\n// CHECK:STDOUT:   %.loc16_40.1: ref %const = as_compatible %reference.ref [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %.loc16_40.2: ref %const = converted %reference.ref, %.loc16_40.1 [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %addr: %ptr.d4c = addr_of %.loc16_40.2 [concrete = constants.%addr.160]\n// CHECK:STDOUT:   %.loc16_24: type = splice_block %ptr.loc16 [concrete = constants.%ptr.d4c] {\n// CHECK:STDOUT:     %X.ref.loc16_23: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %const.loc16_17: type = const_type %X.ref.loc16_23 [concrete = constants.%const]\n// CHECK:STDOUT:     %ptr.loc16: type = ptr_type %const.loc16_17 [concrete = constants.%ptr.d4c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: %ptr.d4c = value_binding a, %addr\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.bf1 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.ref: %ptr.2a9 = name_ref ptr, file.%ptr.loc9_5\n// CHECK:STDOUT:   %X.ref.loc17_41: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %const.loc17_35: type = const_type %X.ref.loc17_41 [concrete = constants.%const]\n// CHECK:STDOUT:   %ptr.loc17_42: type = ptr_type %const.loc17_35 [concrete = constants.%ptr.d4c]\n// CHECK:STDOUT:   %.loc17_32.1: %ptr.d4c = as_compatible %ptr.ref\n// CHECK:STDOUT:   %.loc17_32.2: %ptr.d4c = converted %ptr.ref, %.loc17_32.1\n// CHECK:STDOUT:   %.loc17_24: type = splice_block %ptr.loc17_24 [concrete = constants.%ptr.d4c] {\n// CHECK:STDOUT:     %X.ref.loc17_23: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %const.loc17_17: type = const_type %X.ref.loc17_23 [concrete = constants.%const]\n// CHECK:STDOUT:     %ptr.loc17_24: type = ptr_type %const.loc17_17 [concrete = constants.%ptr.d4c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: %ptr.d4c = value_binding b, %.loc17_32.2\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %i.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%i.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %const) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- remove_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %const: type = const_type %X [concrete]\n// CHECK:STDOUT:   %Init.type: type = fn_type @Init [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Init: %Init.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.05f: type = pattern_type %X [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.05f = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.05f = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %X = var %i.var_patt\n// CHECK:STDOUT:   %Init.ref: %Init.type = name_ref Init, file.%Init.decl [concrete = constants.%Init]\n// CHECK:STDOUT:   %.loc12_3: ref %X = splice_block %i.var {}\n// CHECK:STDOUT:   %Init.call: init %const to %.loc12_3 = call %Init.ref()\n// CHECK:STDOUT:   %X.ref.loc12_31: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc12_28.1: init %X = as_compatible %Init.call\n// CHECK:STDOUT:   %.loc12_28.2: init %X = converted %Init.call, %.loc12_28.1\n// CHECK:STDOUT:   assign %i.var, %.loc12_28.2\n// CHECK:STDOUT:   %X.ref.loc12_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %i: ref %X = ref_binding i, %i.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.05f = value_binding_pattern v [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.ref: %const = name_ref value, file.%value\n// CHECK:STDOUT:   %X.ref.loc13_30: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc13_27.1: %X = as_compatible %value.ref\n// CHECK:STDOUT:   %.loc13_27.2: %X = converted %value.ref, %.loc13_27.1\n// CHECK:STDOUT:   %X.ref.loc13_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %v: %X = value_binding v, %.loc13_27.2\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %i.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%i.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %X) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- unsafe_remove_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %const: type = const_type %X [concrete]\n// CHECK:STDOUT:   %ptr.d4c: type = ptr_type %const [concrete]\n// CHECK:STDOUT:   %ptr.2a9: type = ptr_type %X [concrete]\n// CHECK:STDOUT:   %pattern_type.37f: type = pattern_type %ptr.2a9 [concrete]\n// CHECK:STDOUT:   %reference.var: ref %X = var file.%reference.var_patt [concrete]\n// CHECK:STDOUT:   %addr.806: %ptr.2a9 = addr_of %reference.var [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.37f = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %reference.ref: ref %const = name_ref reference, file.%reference [concrete = file.%reference.var]\n// CHECK:STDOUT:   %X.ref.loc11_44: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc11_41.1: ref %X = as_compatible %reference.ref [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %.loc11_41.2: ref %X = converted %reference.ref, %.loc11_41.1 [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %addr: %ptr.2a9 = addr_of %.loc11_41.2 [concrete = constants.%addr.806]\n// CHECK:STDOUT:   %.loc11_18: type = splice_block %ptr.loc11 [concrete = constants.%ptr.2a9] {\n// CHECK:STDOUT:     %X.ref.loc11_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %ptr.loc11: type = ptr_type %X.ref.loc11_17 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: %ptr.2a9 = value_binding a, %addr\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.37f = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.ref: %ptr.d4c = name_ref ptr, file.%ptr.loc7_5\n// CHECK:STDOUT:   %X.ref.loc12_36: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %ptr.loc12_37: type = ptr_type %X.ref.loc12_36 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   %.loc12_33.1: %ptr.2a9 = as_compatible %ptr.ref\n// CHECK:STDOUT:   %.loc12_33.2: %ptr.2a9 = converted %ptr.ref, %.loc12_33.1\n// CHECK:STDOUT:   %.loc12_18: type = splice_block %ptr.loc12_18 [concrete = constants.%ptr.2a9] {\n// CHECK:STDOUT:     %X.ref.loc12_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %ptr.loc12_18: type = ptr_type %X.ref.loc12_17 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: %ptr.2a9 = value_binding b, %.loc12_33.2\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/as/maybe_unformed.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/unformed.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/as/maybe_unformed.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/as/maybe_unformed.carbon\n\n// --- add_unformed.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nvar reference: X;\nlet ptr: X* = &reference;\n\nfn Use() {\n  // TODO: Should some of these be valid without the `as`?\n  //@dump-sem-ir-begin\n  let unused a: Core.MaybeUnformed(X)* = &(reference as Core.MaybeUnformed(X));\n  let unused b: Core.MaybeUnformed(X)* = ptr as Core.MaybeUnformed(X)*;\n  //@dump-sem-ir-end\n}\n\n// --- fail_todo_add_unformed_nonref.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nfn Init() -> X;\nlet value: X = Init();\n\nfn Use() {\n  // TODO: These should probably be valid.\n  //@dump-sem-ir-begin\n  // CHECK:STDERR: fail_todo_add_unformed_nonref.carbon:[[@LINE+7]]:41: error: cannot convert expression of type `X` to `Core.MaybeUnformed(X)` with `as` [ConversionFailure]\n  // CHECK:STDERR:   var unused i: Core.MaybeUnformed(X) = Init() as Core.MaybeUnformed(X);\n  // CHECK:STDERR:                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_add_unformed_nonref.carbon:[[@LINE+4]]:41: note: type `X` does not implement interface `Core.As(Core.MaybeUnformed(X))` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var unused i: Core.MaybeUnformed(X) = Init() as Core.MaybeUnformed(X);\n  // CHECK:STDERR:                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused i: Core.MaybeUnformed(X) = Init() as Core.MaybeUnformed(X);\n  // CHECK:STDERR: fail_todo_add_unformed_nonref.carbon:[[@LINE+7]]:41: error: cannot convert expression of type `X` to `Core.MaybeUnformed(X)` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused v: Core.MaybeUnformed(X) = value as Core.MaybeUnformed(X);\n  // CHECK:STDERR:                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_add_unformed_nonref.carbon:[[@LINE+4]]:41: note: type `X` does not implement interface `Core.As(Core.MaybeUnformed(X))` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused v: Core.MaybeUnformed(X) = value as Core.MaybeUnformed(X);\n  // CHECK:STDERR:                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused v: Core.MaybeUnformed(X) = value as Core.MaybeUnformed(X);\n  //@dump-sem-ir-end\n}\n\n// --- fail_cannot_remove_unformed.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nfn Init() -> Core.MaybeUnformed(X);\nlet value: Core.MaybeUnformed(X) = Init();\nvar reference: Core.MaybeUnformed(X);\nlet ptr: Core.MaybeUnformed(X)* = &reference;\n\nfn Use() {\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+7]]:21: error: cannot convert expression of type `Core.MaybeUnformed(X)` to `X` with `as` [ConversionFailure]\n  // CHECK:STDERR:   var unused i: X = Init() as X;\n  // CHECK:STDERR:                     ^~~~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+4]]:21: note: type `Core.MaybeUnformed(X)` does not implement interface `Core.As(X)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var unused i: X = Init() as X;\n  // CHECK:STDERR:                     ^~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused i: X = Init() as X;\n  // TODO: The diagnostic should explain that the reason we can't perform this\n  // conversion is due to the expression category.\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+7]]:21: error: cannot convert expression of type `Core.MaybeUnformed(X)` to `X` with `unsafe as` [ConversionFailure]\n  // CHECK:STDERR:   var unused j: X = Init() unsafe as X;\n  // CHECK:STDERR:                     ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+4]]:21: note: type `Core.MaybeUnformed(X)` does not implement interface `Core.UnsafeAs(X)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var unused j: X = Init() unsafe as X;\n  // CHECK:STDERR:                     ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused j: X = Init() unsafe as X;\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+7]]:21: error: cannot convert expression of type `Core.MaybeUnformed(X)` to `X` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused v: X = value as X;\n  // CHECK:STDERR:                     ^~~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+4]]:21: note: type `Core.MaybeUnformed(X)` does not implement interface `Core.As(X)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused v: X = value as X;\n  // CHECK:STDERR:                     ^~~~~~~~~~\n  // CHECK:STDERR:\n  let unused v: X = value as X;\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+7]]:24: error: cannot convert expression of type `Core.MaybeUnformed(X)` to `X` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused a: X* = &(reference as X);\n  // CHECK:STDERR:                        ^~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+4]]:24: note: type `Core.MaybeUnformed(X)` does not implement interface `Core.As(X)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused a: X* = &(reference as X);\n  // CHECK:STDERR:                        ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused a: X* = &(reference as X);\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+7]]:22: error: cannot convert expression of type `Core.MaybeUnformed(X)*` to `X*` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused b: X* = ptr as X*;\n  // CHECK:STDERR:                      ^~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_unformed.carbon:[[@LINE+4]]:22: note: type `Core.MaybeUnformed(X)*` does not implement interface `Core.As(X*)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused b: X* = ptr as X*;\n  // CHECK:STDERR:                      ^~~~~~~~~\n  // CHECK:STDERR:\n  let unused b: X* = ptr as X*;\n}\n\n// --- unsafe_remove_unformed.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nfn Init() -> Core.MaybeUnformed(X);\nlet value: Core.MaybeUnformed(X) = Init();\nvar reference: Core.MaybeUnformed(X);\nlet ptr: Core.MaybeUnformed(X)* = &reference;\n\nfn Use() {\n  //@dump-sem-ir-begin\n  let unused v: X = value unsafe as X;\n  let unused a: X* = &(reference unsafe as X);\n  let unused b: X* = ptr unsafe as X*;\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- add_unformed.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %ptr.2a9: type = ptr_type %X [concrete]\n// CHECK:STDOUT:   %MaybeUnformed.type: type = generic_class_type @MaybeUnformed [concrete]\n// CHECK:STDOUT:   %MaybeUnformed.generic: %MaybeUnformed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %MaybeUnformed.b49: type = class_type @MaybeUnformed, @MaybeUnformed(%X) [concrete]\n// CHECK:STDOUT:   %ptr.045: type = ptr_type %MaybeUnformed.b49 [concrete]\n// CHECK:STDOUT:   %pattern_type.396: type = pattern_type %ptr.045 [concrete]\n// CHECK:STDOUT:   %reference.var: ref %MaybeUnformed.b49 = var file.%reference.var_patt [concrete]\n// CHECK:STDOUT:   %addr.25c: %ptr.045 = addr_of %reference.var [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .MaybeUnformed = %Core.MaybeUnformed\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.MaybeUnformed: %MaybeUnformed.type = import_ref Core//prelude/parts/maybe_unformed, MaybeUnformed, loaded [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.396 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %reference.ref: ref %X = name_ref reference, file.%reference [concrete = file.%reference.var]\n// CHECK:STDOUT:   %Core.ref.loc12_57: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %MaybeUnformed.ref.loc12_61: %MaybeUnformed.type = name_ref MaybeUnformed, imports.%Core.MaybeUnformed [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT:   %X.ref.loc12_76: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %MaybeUnformed.loc12_77: type = class_type @MaybeUnformed, @MaybeUnformed(constants.%X) [concrete = constants.%MaybeUnformed.b49]\n// CHECK:STDOUT:   %.loc12_54.1: ref %MaybeUnformed.b49 = as_compatible %reference.ref [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %.loc12_54.2: ref %MaybeUnformed.b49 = converted %reference.ref, %.loc12_54.1 [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %addr: %ptr.045 = addr_of %.loc12_54.2 [concrete = constants.%addr.25c]\n// CHECK:STDOUT:   %.loc12_38: type = splice_block %ptr.loc12 [concrete = constants.%ptr.045] {\n// CHECK:STDOUT:     %Core.ref.loc12_17: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %MaybeUnformed.ref.loc12_21: %MaybeUnformed.type = name_ref MaybeUnformed, imports.%Core.MaybeUnformed [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT:     %X.ref.loc12_36: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %MaybeUnformed.loc12_37: type = class_type @MaybeUnformed, @MaybeUnformed(constants.%X) [concrete = constants.%MaybeUnformed.b49]\n// CHECK:STDOUT:     %ptr.loc12: type = ptr_type %MaybeUnformed.loc12_37 [concrete = constants.%ptr.045]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: %ptr.045 = value_binding a, %addr\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.396 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.ref: %ptr.2a9 = name_ref ptr, file.%ptr.loc7_5\n// CHECK:STDOUT:   %Core.ref.loc13_49: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %MaybeUnformed.ref.loc13_53: %MaybeUnformed.type = name_ref MaybeUnformed, imports.%Core.MaybeUnformed [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT:   %X.ref.loc13_68: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %MaybeUnformed.loc13_69: type = class_type @MaybeUnformed, @MaybeUnformed(constants.%X) [concrete = constants.%MaybeUnformed.b49]\n// CHECK:STDOUT:   %ptr.loc13_70: type = ptr_type %MaybeUnformed.loc13_69 [concrete = constants.%ptr.045]\n// CHECK:STDOUT:   %.loc13_46.1: %ptr.045 = as_compatible %ptr.ref\n// CHECK:STDOUT:   %.loc13_46.2: %ptr.045 = converted %ptr.ref, %.loc13_46.1\n// CHECK:STDOUT:   %.loc13_38: type = splice_block %ptr.loc13_38 [concrete = constants.%ptr.045] {\n// CHECK:STDOUT:     %Core.ref.loc13_17: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %MaybeUnformed.ref.loc13_21: %MaybeUnformed.type = name_ref MaybeUnformed, imports.%Core.MaybeUnformed [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT:     %X.ref.loc13_36: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %MaybeUnformed.loc13_37: type = class_type @MaybeUnformed, @MaybeUnformed(constants.%X) [concrete = constants.%MaybeUnformed.b49]\n// CHECK:STDOUT:     %ptr.loc13_38: type = ptr_type %MaybeUnformed.loc13_37 [concrete = constants.%ptr.045]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: %ptr.045 = value_binding b, %.loc13_46.2\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_add_unformed_nonref.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %Init.type: type = fn_type @Init [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Init: %Init.type = struct_value () [concrete]\n// CHECK:STDOUT:   %MaybeUnformed.type: type = generic_class_type @MaybeUnformed [concrete]\n// CHECK:STDOUT:   %MaybeUnformed.generic: %MaybeUnformed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %MaybeUnformed.b49: type = class_type @MaybeUnformed, @MaybeUnformed(%X) [concrete]\n// CHECK:STDOUT:   %pattern_type.de9: type = pattern_type %MaybeUnformed.b49 [concrete]\n// CHECK:STDOUT:   %As.type.90f: type = generic_interface_type @As [concrete]\n// CHECK:STDOUT:   %As.generic: %As.type.90f = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .MaybeUnformed = %Core.MaybeUnformed\n// CHECK:STDOUT:     .As = %Core.As\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.MaybeUnformed: %MaybeUnformed.type = import_ref Core//prelude/parts/maybe_unformed, MaybeUnformed, loaded [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT:   %Core.As: %As.type.90f = import_ref Core//prelude/parts/as, As, loaded [concrete = constants.%As.generic]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.de9 = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.de9 = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %MaybeUnformed.b49 = var %i.var_patt\n// CHECK:STDOUT:   %Init.ref: %Init.type = name_ref Init, file.%Init.decl [concrete = constants.%Init]\n// CHECK:STDOUT:   %.loc19_46: ref %X = temporary_storage\n// CHECK:STDOUT:   %Init.call: init %X to %.loc19_46 = call %Init.ref()\n// CHECK:STDOUT:   %Core.ref.loc19_51: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %MaybeUnformed.ref.loc19_55: %MaybeUnformed.type = name_ref MaybeUnformed, imports.%Core.MaybeUnformed [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT:   %X.ref.loc19_70: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %MaybeUnformed.loc19_71: type = class_type @MaybeUnformed, @MaybeUnformed(constants.%X) [concrete = constants.%MaybeUnformed.b49]\n// CHECK:STDOUT:   %.loc19_48: %MaybeUnformed.b49 = converted %Init.call, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign %i.var, <error>\n// CHECK:STDOUT:   %.loc19_37: type = splice_block %MaybeUnformed.loc19_37 [concrete = constants.%MaybeUnformed.b49] {\n// CHECK:STDOUT:     %Core.ref.loc19_17: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %MaybeUnformed.ref.loc19_21: %MaybeUnformed.type = name_ref MaybeUnformed, imports.%Core.MaybeUnformed [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT:     %X.ref.loc19_36: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %MaybeUnformed.loc19_37: type = class_type @MaybeUnformed, @MaybeUnformed(constants.%X) [concrete = constants.%MaybeUnformed.b49]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i: ref %MaybeUnformed.b49 = ref_binding i, %i.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.de9 = value_binding_pattern v [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.ref: %X = name_ref value, file.%value\n// CHECK:STDOUT:   %Core.ref.loc27_50: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %MaybeUnformed.ref.loc27_54: %MaybeUnformed.type = name_ref MaybeUnformed, imports.%Core.MaybeUnformed [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT:   %X.ref.loc27_69: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %MaybeUnformed.loc27_70: type = class_type @MaybeUnformed, @MaybeUnformed(constants.%X) [concrete = constants.%MaybeUnformed.b49]\n// CHECK:STDOUT:   %.loc27_47: %MaybeUnformed.b49 = converted %value.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %.loc27_37: type = splice_block %MaybeUnformed.loc27_37 [concrete = constants.%MaybeUnformed.b49] {\n// CHECK:STDOUT:     %Core.ref.loc27_17: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %MaybeUnformed.ref.loc27_21: %MaybeUnformed.type = name_ref MaybeUnformed, imports.%Core.MaybeUnformed [concrete = constants.%MaybeUnformed.generic]\n// CHECK:STDOUT:     %X.ref.loc27_36: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %MaybeUnformed.loc27_37: type = class_type @MaybeUnformed, @MaybeUnformed(constants.%X) [concrete = constants.%MaybeUnformed.b49]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: %MaybeUnformed.b49 = value_binding v, <error> [concrete = <error>]\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %i.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%i.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %MaybeUnformed.b49) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- unsafe_remove_unformed.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %MaybeUnformed.b49: type = class_type @MaybeUnformed, @MaybeUnformed(%X) [concrete]\n// CHECK:STDOUT:   %ptr.045: type = ptr_type %MaybeUnformed.b49 [concrete]\n// CHECK:STDOUT:   %pattern_type.05f: type = pattern_type %X [concrete]\n// CHECK:STDOUT:   %ptr.2a9: type = ptr_type %X [concrete]\n// CHECK:STDOUT:   %pattern_type.37f: type = pattern_type %ptr.2a9 [concrete]\n// CHECK:STDOUT:   %reference.var: ref %X = var file.%reference.var_patt [concrete]\n// CHECK:STDOUT:   %addr.6f7: %ptr.2a9 = addr_of %reference.var [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.05f = value_binding_pattern v [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.ref: %MaybeUnformed.b49 = name_ref value, file.%value\n// CHECK:STDOUT:   %X.ref.loc13_37: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc13_34.1: %X = as_compatible %value.ref\n// CHECK:STDOUT:   %.loc13_34.2: %X = converted %value.ref, %.loc13_34.1\n// CHECK:STDOUT:   %X.ref.loc13_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %v: %X = value_binding v, %.loc13_34.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.37f = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %reference.ref: ref %MaybeUnformed.b49 = name_ref reference, file.%reference [concrete = file.%reference.var]\n// CHECK:STDOUT:   %X.ref.loc14_44: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc14_41.1: ref %X = as_compatible %reference.ref [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %.loc14_41.2: ref %X = converted %reference.ref, %.loc14_41.1 [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %addr: %ptr.2a9 = addr_of %.loc14_41.2 [concrete = constants.%addr.6f7]\n// CHECK:STDOUT:   %.loc14_18: type = splice_block %ptr.loc14 [concrete = constants.%ptr.2a9] {\n// CHECK:STDOUT:     %X.ref.loc14_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %ptr.loc14: type = ptr_type %X.ref.loc14_17 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: %ptr.2a9 = value_binding a, %addr\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.37f = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.ref: %ptr.045 = name_ref ptr, file.%ptr.loc9_5\n// CHECK:STDOUT:   %X.ref.loc15_36: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %ptr.loc15_37: type = ptr_type %X.ref.loc15_36 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   %.loc15_33.1: %ptr.2a9 = as_compatible %ptr.ref\n// CHECK:STDOUT:   %.loc15_33.2: %ptr.2a9 = converted %ptr.ref, %.loc15_33.1\n// CHECK:STDOUT:   %.loc15_18: type = splice_block %ptr.loc15_18 [concrete = constants.%ptr.2a9] {\n// CHECK:STDOUT:     %X.ref.loc15_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %ptr.loc15_18: type = ptr_type %X.ref.loc15_17 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: %ptr.2a9 = value_binding b, %.loc15_33.2\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/as/partial.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/as/partial.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/as/partial.carbon\n\n// --- add_partial.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class X {}\n\nfn Init() -> X;\nlet value: X = Init();\nvar reference: X;\nlet ptr: X* = &reference;\n\nfn Use() {\n  // TODO: Should some of these be valid without the `as`?\n  //@dump-sem-ir-begin\n  var unused i: partial X = Init() as partial X;\n  let unused v: partial X = value as partial X;\n  let unused a: partial X* = &(reference as partial X);\n  let unused b: partial X* = ptr as partial X*;\n  //@dump-sem-ir-end\n}\n\n// --- remove_partial_in_init.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class X {}\n\nfn Init() -> partial X;\n\nfn Use() {\n  //@dump-sem-ir-begin\n  var unused i: X = Init();\n  var unused j: X = Init() as X;\n  var unused k: X = Init() unsafe as X;\n  //@dump-sem-ir-end\n}\n\n// --- fail_cannot_remove_partial.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class X {}\n\nfn Init() -> partial X;\n\nlet value: partial X = Init();\nvar reference: partial X;\nlet ptr: partial X* = &reference;\n\nfn Use() {\n  // CHECK:STDERR: fail_cannot_remove_partial.carbon:[[@LINE+7]]:21: error: cannot convert expression of type `partial X` to `X` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused v: X = value as X;\n  // CHECK:STDERR:                     ^~~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_partial.carbon:[[@LINE+4]]:21: note: type `partial X` does not implement interface `Core.As(X)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused v: X = value as X;\n  // CHECK:STDERR:                     ^~~~~~~~~~\n  // CHECK:STDERR:\n  let unused v: X = value as X;\n  // CHECK:STDERR: fail_cannot_remove_partial.carbon:[[@LINE+7]]:24: error: cannot convert expression of type `partial X` to `X` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused a: X* = &(reference as X);\n  // CHECK:STDERR:                        ^~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_partial.carbon:[[@LINE+4]]:24: note: type `partial X` does not implement interface `Core.As(X)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused a: X* = &(reference as X);\n  // CHECK:STDERR:                        ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused a: X* = &(reference as X);\n  // CHECK:STDERR: fail_cannot_remove_partial.carbon:[[@LINE+7]]:22: error: cannot convert expression of type `partial X*` to `X*` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused b: X* = ptr as X*;\n  // CHECK:STDERR:                      ^~~~~~~~~\n  // CHECK:STDERR: fail_cannot_remove_partial.carbon:[[@LINE+4]]:22: note: type `partial X*` does not implement interface `Core.As(X*)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused b: X* = ptr as X*;\n  // CHECK:STDERR:                      ^~~~~~~~~\n  // CHECK:STDERR:\n  let unused b: X* = ptr as X*;\n}\n\n// --- unsafe_remove_partial.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class X {}\n\nfn Init() -> partial X;\n\nlet value: partial X = Init();\nvar reference: partial X;\nlet ptr: partial X* = &reference;\n\nfn Use() {\n  //@dump-sem-ir-begin\n  let unused v: X = value unsafe as X;\n  let unused a: X* = &(reference unsafe as X);\n  let unused b: X* = ptr unsafe as X*;\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- add_partial.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %Init.type: type = fn_type @Init [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Init: %Init.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.2a9: type = ptr_type %X [concrete]\n// CHECK:STDOUT:   %.4b5: type = partial_type %X [concrete]\n// CHECK:STDOUT:   %pattern_type.bc5: type = pattern_type %.4b5 [concrete]\n// CHECK:STDOUT:   %ptr.314: type = ptr_type %.4b5 [concrete]\n// CHECK:STDOUT:   %pattern_type.408: type = pattern_type %ptr.314 [concrete]\n// CHECK:STDOUT:   %reference.var: ref %.4b5 = var file.%reference.var_patt [concrete]\n// CHECK:STDOUT:   %addr.315: %ptr.314 = addr_of %reference.var [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.bc5 = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.bc5 = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %.4b5 = var %i.var_patt\n// CHECK:STDOUT:   %Init.ref: %Init.type = name_ref Init, file.%Init.decl [concrete = constants.%Init]\n// CHECK:STDOUT:   %.loc14_3: ref %.4b5 = splice_block %i.var {}\n// CHECK:STDOUT:   %Init.call: init %X to %.loc14_3 = call %Init.ref()\n// CHECK:STDOUT:   %X.ref.loc14_47: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc14_39: type = partial_type %X.ref.loc14_47 [concrete = constants.%.4b5]\n// CHECK:STDOUT:   %.loc14_36.1: init %.4b5 = as_compatible %Init.call\n// CHECK:STDOUT:   %.loc14_36.2: init %.4b5 = converted %Init.call, %.loc14_36.1\n// CHECK:STDOUT:   assign %i.var, %.loc14_36.2\n// CHECK:STDOUT:   %.loc14_17.1: type = splice_block %.loc14_17.2 [concrete = constants.%.4b5] {\n// CHECK:STDOUT:     %X.ref.loc14_25: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %.loc14_17.2: type = partial_type %X.ref.loc14_25 [concrete = constants.%.4b5]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i: ref %.4b5 = ref_binding i, %i.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.bc5 = value_binding_pattern v [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.ref: %X = name_ref value, file.%value\n// CHECK:STDOUT:   %X.ref.loc15_46: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc15_38: type = partial_type %X.ref.loc15_46 [concrete = constants.%.4b5]\n// CHECK:STDOUT:   %.loc15_35.1: %.4b5 = as_compatible %value.ref\n// CHECK:STDOUT:   %.loc15_35.2: %.4b5 = converted %value.ref, %.loc15_35.1\n// CHECK:STDOUT:   %.loc15_17.1: type = splice_block %.loc15_17.2 [concrete = constants.%.4b5] {\n// CHECK:STDOUT:     %X.ref.loc15_25: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %.loc15_17.2: type = partial_type %X.ref.loc15_25 [concrete = constants.%.4b5]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: %.4b5 = value_binding v, %.loc15_35.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.408 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %reference.ref: ref %X = name_ref reference, file.%reference [concrete = file.%reference.var]\n// CHECK:STDOUT:   %X.ref.loc16_53: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc16_45: type = partial_type %X.ref.loc16_53 [concrete = constants.%.4b5]\n// CHECK:STDOUT:   %.loc16_42.1: ref %.4b5 = as_compatible %reference.ref [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %.loc16_42.2: ref %.4b5 = converted %reference.ref, %.loc16_42.1 [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %addr: %ptr.314 = addr_of %.loc16_42.2 [concrete = constants.%addr.315]\n// CHECK:STDOUT:   %.loc16_26: type = splice_block %ptr.loc16 [concrete = constants.%ptr.314] {\n// CHECK:STDOUT:     %X.ref.loc16_25: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %.loc16_17: type = partial_type %X.ref.loc16_25 [concrete = constants.%.4b5]\n// CHECK:STDOUT:     %ptr.loc16: type = ptr_type %.loc16_17 [concrete = constants.%ptr.314]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: %ptr.314 = value_binding a, %addr\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.408 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.ref: %ptr.2a9 = name_ref ptr, file.%ptr.loc9_5\n// CHECK:STDOUT:   %X.ref.loc17_45: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc17_37: type = partial_type %X.ref.loc17_45 [concrete = constants.%.4b5]\n// CHECK:STDOUT:   %ptr.loc17_46: type = ptr_type %.loc17_37 [concrete = constants.%ptr.314]\n// CHECK:STDOUT:   %.loc17_34.1: %ptr.314 = as_compatible %ptr.ref\n// CHECK:STDOUT:   %.loc17_34.2: %ptr.314 = converted %ptr.ref, %.loc17_34.1\n// CHECK:STDOUT:   %.loc17_26: type = splice_block %ptr.loc17_26 [concrete = constants.%ptr.314] {\n// CHECK:STDOUT:     %X.ref.loc17_25: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %.loc17_17: type = partial_type %X.ref.loc17_25 [concrete = constants.%.4b5]\n// CHECK:STDOUT:     %ptr.loc17_26: type = ptr_type %.loc17_17 [concrete = constants.%ptr.314]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: %ptr.314 = value_binding b, %.loc17_34.2\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %i.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%i.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %.4b5) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- remove_partial_in_init.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %.4b5: type = partial_type %X [concrete]\n// CHECK:STDOUT:   %Init.type: type = fn_type @Init [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Init: %Init.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.05f: type = pattern_type %X [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.05f = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.05f = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %X = var %i.var_patt\n// CHECK:STDOUT:   %Init.ref.loc10: %Init.type = name_ref Init, file.%Init.decl [concrete = constants.%Init]\n// CHECK:STDOUT:   %.loc10_3.1: ref %X = splice_block %i.var {}\n// CHECK:STDOUT:   %Init.call.loc10: init %.4b5 to %.loc10_3.1 = call %Init.ref.loc10()\n// CHECK:STDOUT:   %.loc10_3.2: init %X = as_compatible %Init.call.loc10\n// CHECK:STDOUT:   %.loc10_3.3: init %X = converted %Init.call.loc10, %.loc10_3.2\n// CHECK:STDOUT:   assign %i.var, %.loc10_3.3\n// CHECK:STDOUT:   %X.ref.loc10: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %i: ref %X = ref_binding i, %i.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %j.patt: %pattern_type.05f = ref_binding_pattern j [concrete]\n// CHECK:STDOUT:     %j.var_patt: %pattern_type.05f = var_pattern %j.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %j.var: ref %X = var %j.var_patt\n// CHECK:STDOUT:   %Init.ref.loc11: %Init.type = name_ref Init, file.%Init.decl [concrete = constants.%Init]\n// CHECK:STDOUT:   %.loc11_3: ref %X = splice_block %j.var {}\n// CHECK:STDOUT:   %Init.call.loc11: init %.4b5 to %.loc11_3 = call %Init.ref.loc11()\n// CHECK:STDOUT:   %X.ref.loc11_31: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc11_28.1: init %X = as_compatible %Init.call.loc11\n// CHECK:STDOUT:   %.loc11_28.2: init %X = converted %Init.call.loc11, %.loc11_28.1\n// CHECK:STDOUT:   assign %j.var, %.loc11_28.2\n// CHECK:STDOUT:   %X.ref.loc11_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %j: ref %X = ref_binding j, %j.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %k.patt: %pattern_type.05f = ref_binding_pattern k [concrete]\n// CHECK:STDOUT:     %k.var_patt: %pattern_type.05f = var_pattern %k.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %k.var: ref %X = var %k.var_patt\n// CHECK:STDOUT:   %Init.ref.loc12: %Init.type = name_ref Init, file.%Init.decl [concrete = constants.%Init]\n// CHECK:STDOUT:   %.loc12_3: ref %X = splice_block %k.var {}\n// CHECK:STDOUT:   %Init.call.loc12: init %.4b5 to %.loc12_3 = call %Init.ref.loc12()\n// CHECK:STDOUT:   %X.ref.loc12_38: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc12_35.1: init %X = as_compatible %Init.call.loc12\n// CHECK:STDOUT:   %.loc12_35.2: init %X = converted %Init.call.loc12, %.loc12_35.1\n// CHECK:STDOUT:   assign %k.var, %.loc12_35.2\n// CHECK:STDOUT:   %X.ref.loc12_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %k: ref %X = ref_binding k, %k.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc12: <bound method> = bound_method %k.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc12: init %empty_tuple.type = call %Destroy.Op.bound.loc12(%k.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc11: <bound method> = bound_method %j.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%j.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10: <bound method> = bound_method %i.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc10: init %empty_tuple.type = call %Destroy.Op.bound.loc10(%i.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %X) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- unsafe_remove_partial.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %.4b5: type = partial_type %X [concrete]\n// CHECK:STDOUT:   %ptr.314: type = ptr_type %.4b5 [concrete]\n// CHECK:STDOUT:   %pattern_type.05f: type = pattern_type %X [concrete]\n// CHECK:STDOUT:   %ptr.2a9: type = ptr_type %X [concrete]\n// CHECK:STDOUT:   %pattern_type.37f: type = pattern_type %ptr.2a9 [concrete]\n// CHECK:STDOUT:   %reference.var: ref %X = var file.%reference.var_patt [concrete]\n// CHECK:STDOUT:   %addr.9cd: %ptr.2a9 = addr_of %reference.var [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.05f = value_binding_pattern v [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.ref: %.4b5 = name_ref value, file.%value\n// CHECK:STDOUT:   %X.ref.loc14_37: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc14_34.1: %X = as_compatible %value.ref\n// CHECK:STDOUT:   %.loc14_34.2: %X = converted %value.ref, %.loc14_34.1\n// CHECK:STDOUT:   %X.ref.loc14_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %v: %X = value_binding v, %.loc14_34.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.37f = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %reference.ref: ref %.4b5 = name_ref reference, file.%reference [concrete = file.%reference.var]\n// CHECK:STDOUT:   %X.ref.loc15_44: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %.loc15_41.1: ref %X = as_compatible %reference.ref [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %.loc15_41.2: ref %X = converted %reference.ref, %.loc15_41.1 [concrete = constants.%reference.var]\n// CHECK:STDOUT:   %addr: %ptr.2a9 = addr_of %.loc15_41.2 [concrete = constants.%addr.9cd]\n// CHECK:STDOUT:   %.loc15_18: type = splice_block %ptr.loc15 [concrete = constants.%ptr.2a9] {\n// CHECK:STDOUT:     %X.ref.loc15_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %ptr.loc15: type = ptr_type %X.ref.loc15_17 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: %ptr.2a9 = value_binding a, %addr\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.37f = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.ref: %ptr.314 = name_ref ptr, file.%ptr.loc10_5\n// CHECK:STDOUT:   %X.ref.loc16_36: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %ptr.loc16_37: type = ptr_type %X.ref.loc16_36 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   %.loc16_33.1: %ptr.2a9 = as_compatible %ptr.ref\n// CHECK:STDOUT:   %.loc16_33.2: %ptr.2a9 = converted %ptr.ref, %.loc16_33.1\n// CHECK:STDOUT:   %.loc16_18: type = splice_block %ptr.loc16_18 [concrete = constants.%ptr.2a9] {\n// CHECK:STDOUT:     %X.ref.loc16_17: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %ptr.loc16_18: type = ptr_type %X.ref.loc16_17 [concrete = constants.%ptr.2a9]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: %ptr.2a9 = value_binding b, %.loc16_33.2\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/as/unsafe_as.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/unformed.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/as/unsafe_as.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/as/unsafe_as.carbon\n\n// --- fail_no_conversion.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {};\nclass B {};\n\nfn Convert(a: A) -> B {\n  // CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+7]]:10: error: cannot convert expression of type `A` to `B` with `unsafe as` [ConversionFailure]\n  // CHECK:STDERR:   return a unsafe as B;\n  // CHECK:STDERR:          ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+4]]:10: note: type `A` does not implement interface `Core.UnsafeAs(B)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return a unsafe as B;\n  // CHECK:STDERR:          ^~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return a unsafe as B;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/as/var_init.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/as/var_init.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/as/var_init.carbon\n\n// --- var_init.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {\n  impl () as Core.ImplicitAs(X) {\n    fn Convert[unused self: ()]() ->  X { return {}; }\n  }\n}\n\nfn Convert(unused t: ()) {\n  //@dump-sem-ir-begin\n  var unused x: X = ();\n  //@dump-sem-ir-end\n}\n\n\n// CHECK:STDOUT: --- var_init.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.062: type = facet_type <@ImplicitAs, @ImplicitAs(%X)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness @empty_tuple.type.as.ImplicitAs.impl.%ImplicitAs.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.05f: type = pattern_type %X [concrete]\n// CHECK:STDOUT:   %empty_tuple.type.as.ImplicitAs.impl.Convert.type: type = fn_type @empty_tuple.type.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %empty_tuple.type.as.ImplicitAs.impl.Convert: %empty_tuple.type.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.062 = facet_value %empty_tuple.type, (%ImplicitAs.impl_witness) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.73b: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%X, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.1bd: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.73b, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %empty_tuple.type.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %empty_tuple, %empty_tuple.type.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Convert(%t.param: %empty_tuple.type) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.05f = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type.05f = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %X = var %x.var_patt\n// CHECK:STDOUT:   %.loc12_22.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %impl.elem0: %.1bd = impl_witness_access constants.%ImplicitAs.impl_witness, element0 [concrete = constants.%empty_tuple.type.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %.loc12_22.1, %impl.elem0 [concrete = constants.%empty_tuple.type.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %.loc12_3.1: ref %X = splice_block %x.var {}\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc12_22.2: %empty_tuple.type = converted %.loc12_22.1, %empty_tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %empty_tuple.type.as.ImplicitAs.impl.Convert.call: init %X to %.loc12_3.1 = call %bound_method(%.loc12_22.2)\n// CHECK:STDOUT:   %.loc12_3.2: init %X = converted %.loc12_22.1, %empty_tuple.type.as.ImplicitAs.impl.Convert.call\n// CHECK:STDOUT:   assign %x.var, %.loc12_3.2\n// CHECK:STDOUT:   %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %x: ref %X = ref_binding x, %x.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %x.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%x.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %X) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/dump_prelude.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// ARGS: compile --phase=check --dump-sem-ir %s\n//\n// NOAUTOUPDATE\n// SET-CHECK-SUBSET\n//\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/dump_prelude.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/dump_prelude.carbon\n\n// CHECK:STDOUT: interface @Copy {\n// CHECK:STDOUT: interface @Destroy {\n// CHECK:STDOUT: fn @MakeInt(%size.param: Core.IntLiteral) -> out %return.param: type = \"int.make_type_signed\";\n"
  },
  {
    "path": "toolchain/check/testdata/basics/dump_sem_ir_ranges.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n//\n// The default behavior should be `--dump-sem-ir-ranges=if-present`, although\n// tests set it to `only`. This explicitly tests the default of the toolchain,\n// not of file_test.\n// ARGS: compile --phase=check --dump-sem-ir %s\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/dump_sem_ir_ranges.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/dump_sem_ir_ranges.carbon\n\n// --- function.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A() {\n  var unused a: () = ();\n}\n\nfn B() -> () {\n  var b: () = ();\n  //@dump-sem-ir-begin\n  b = A();\n  //@dump-sem-ir-end\n  return b;\n}\n\n//@dump-sem-ir-begin\nfn C() -> () {\n  var c: () = ();\n  c = B();\n  return c;\n}\n//@dump-sem-ir-end\n\n// --- class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  fn F();\n\n  //@dump-sem-ir-begin\n  fn G();\n  //@dump-sem-ir-end\n}\n\nclass B {\n  fn H();\n}\n\n//@dump-sem-ir-begin\nclass C {\n  fn I();\n  //@dump-sem-ir-end\n\n  fn J();\n}\n\n// --- call_params.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(a: (), b: (), c: ());\n\nfn A();\nfn B();\nfn C();\n\nfn G() {\n  F(\n    //@dump-sem-ir-begin\n    A(),\n    //@dump-sem-ir-end\n    B(),\n    //@dump-sem-ir-begin\n    C()\n    //@dump-sem-ir-end\n  );\n}\n\n// --- file_without_ranges.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F();\n\n// --- explicit_dump_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@include-in-dumps\n\n// CHECK:STDOUT: --- function.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc17_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc17_12.2: type = converted %.loc17_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc17_12.3: Core.Form = init_form %.loc17_12.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %b.ref.loc11: ref %empty_tuple.type = name_ref b, %b\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.ref()\n// CHECK:STDOUT:   assign %b.ref.loc11, %A.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.cb1 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.cb1 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %empty_tuple.type = var %c.var_patt\n// CHECK:STDOUT:   %.loc18_16.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc18_16.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc18_3: init %empty_tuple.type = converted %.loc18_16.1, %.loc18_16.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   assign %c.var, %.loc18_3\n// CHECK:STDOUT:   %.loc18_11.1: type = splice_block %.loc18_11.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc18_11.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc18_11.3: type = converted %.loc18_11.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %empty_tuple.type = ref_binding c, %c.var\n// CHECK:STDOUT:   %c.ref.loc19: ref %empty_tuple.type = name_ref c, %c\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %B.call: init %empty_tuple.type = call %B.ref()\n// CHECK:STDOUT:   assign %c.ref.loc19, %B.call\n// CHECK:STDOUT:   %c.ref.loc20: ref %empty_tuple.type = name_ref c, %c\n// CHECK:STDOUT:   %.loc20_10: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc20_11: init %empty_tuple.type = converted %c.ref.loc20, %.loc20_10 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %c.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%c.var)\n// CHECK:STDOUT:   return %.loc20_11\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %A.G.type: type = fn_type @A.G [concrete]\n// CHECK:STDOUT:   %A.G: %A.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.I.type: type = fn_type @C.I [concrete]\n// CHECK:STDOUT:   %C.I: %C.I.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %A.G.decl: %A.G.type = fn_decl @A.G [concrete = constants.%A.G] {} {}\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .F = %A.F.decl\n// CHECK:STDOUT:   .G = %A.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %C.I.decl: %C.I.type = fn_decl @C.I [concrete = constants.%C.I] {} {}\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .I = %C.I.decl\n// CHECK:STDOUT:   .J = %C.J.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.G();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.I();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- call_params.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.ref()\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %C.call: init %empty_tuple.type = call %C.ref()\n// CHECK:STDOUT:   %.loc13_7.1: ref %empty_tuple.type = temporary_storage\n// CHECK:STDOUT:   %.loc13_7.2: ref %empty_tuple.type = temporary %.loc13_7.1, %A.call\n// CHECK:STDOUT:   %tuple.loc13: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc13_7.3: %empty_tuple.type = converted %A.call, %tuple.loc13 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %.loc17_7.1: ref %empty_tuple.type = temporary_storage\n// CHECK:STDOUT:   %.loc17_7.2: ref %empty_tuple.type = temporary %.loc17_7.1, %C.call\n// CHECK:STDOUT:   %tuple.loc17: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc17_7.3: %empty_tuple.type = converted %C.call, %tuple.loc17 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %Destroy.Op.bound.loc17: <bound method> = bound_method %.loc17_7.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc17: init %empty_tuple.type = call %Destroy.Op.bound.loc17(%.loc17_7.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13: <bound method> = bound_method %.loc13_7.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc13: init %empty_tuple.type = call %Destroy.Op.bound.loc13(%.loc13_7.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %empty_tuple.type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- file_without_ranges.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- explicit_dump_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/dump_sem_ir_ranges_ignore.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=ignore\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/dump_sem_ir_ranges_ignore.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/dump_sem_ir_ranges_ignore.carbon\n\n// --- with-range.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F();\n//@dump-sem-ir-end\n\n// --- without-range.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F();\n\n// --- explicit_dump_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@include-in-dumps\n\n// CHECK:STDOUT: --- with-range.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- without-range.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- explicit_dump_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/dump_sem_ir_ranges_only.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// This tests `--dump-sem-ir-range=only` behavior, which is set implicitly by\n// file_test.\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/dump_sem_ir_ranges_only.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/dump_sem_ir_ranges_only.carbon\n\n// --- with-range.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F();\n//@dump-sem-ir-end\n\n// --- without-range.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F();\n\n// --- explicit_dump_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@include-in-dumps\n\n// CHECK:STDOUT: --- with-range.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- explicit_dump_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/duplicate_name_same_line.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/duplicate_name_same_line.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/duplicate_name_same_line.carbon\n\nfn A() {\n  if (true) {\n    // This declares `n` in two different scopes, it's just showing the IR\n    // behavior of having both on the same line.\n    //@dump-sem-ir-begin\n    var unused n: () = (); } else { var unused n: () = ();\n    //@dump-sem-ir-end\n  }\n}\n\n// CHECK:STDOUT: --- duplicate_name_same_line.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.then:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %n.patt.loc18_16: %pattern_type.cb1 = ref_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.var_patt.loc18_5: %pattern_type.cb1 = var_pattern %n.patt.loc18_16 [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %n.var.loc18_5: ref %empty_tuple.type = var %n.var_patt.loc18_5\n// CHECK:STDOUT:   %.loc18_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc18_25.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc18_5: init %empty_tuple.type = converted %.loc18_25.1, %.loc18_25.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   assign %n.var.loc18_5, %.loc18_5\n// CHECK:STDOUT:   %.loc18_20.1: type = splice_block %.loc18_20.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc18_20.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc18_20.3: type = converted %.loc18_20.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %n.loc18_16: ref %empty_tuple.type = ref_binding n, %n.var.loc18_5\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.else:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %n.patt.loc18_48: %pattern_type.cb1 = ref_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.var_patt.loc18_37: %pattern_type.cb1 = var_pattern %n.patt.loc18_48 [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %n.var.loc18_37: ref %empty_tuple.type = var %n.var_patt.loc18_37\n// CHECK:STDOUT:   %.loc18_57.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc18_57.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc18_37: init %empty_tuple.type = converted %.loc18_57.1, %.loc18_57.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   assign %n.var.loc18_37, %.loc18_37\n// CHECK:STDOUT:   %.loc18_52.1: type = splice_block %.loc18_52.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc18_52.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc18_52.3: type = converted %.loc18_52.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %n.loc18_48: ref %empty_tuple.type = ref_binding n, %n.var.loc18_37\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.done:\n// CHECK:STDOUT:   %Destroy.Op.bound.loc18_37: <bound method> = bound_method %n.var.loc18_37, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc18_37: init %empty_tuple.type = call %Destroy.Op.bound.loc18_37(%n.var.loc18_37)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc18_5: <bound method> = bound_method %n.var.loc18_5, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc18_5: init %empty_tuple.type = call %Destroy.Op.bound.loc18_5(%n.var.loc18_5)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %empty_tuple.type) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/empty.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/empty.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/empty.carbon\n\n// --- empty.carbon\n\n// --- empty_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n;\n\n// CHECK:STDOUT: --- empty.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- empty_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/include_in_dumps.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// This explicitly excludes some files, then set ranges to `if-present` so that\n// we can see imports (particularly of `impl`s) from files that would be excluded without\n// `//@include-in-dumps`.\n// EXTRA-ARGS: --exclude-dump-file-prefix=exclude/ --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/include_in_dumps.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/include_in_dumps.carbon\n\n// --- exclude/included.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@include-in-dumps\n\ninterface I {}\n\n// --- exclude/included_with_range.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@include-in-dumps\n\n//@dump-sem-ir-begin\ninterface I {\n  fn Op[unused self: Self]();\n}\n//@dump-sem-ir-end\n\nclass C {\n  impl C as I {\n    fn Op[unused self: Self]() {}\n  }\n}\n\n// --- import_included.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"included_with_range\";\n\nfn F(c: C) { c.(I.Op)(); }\n\n// --- exclude/excluded.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\n// --- exclude/excluded_with_range.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\ninterface I {\n  fn Op[unused self: Self]();\n}\n//@dump-sem-ir-end\n\nclass C {\n  impl C as I {\n    fn Op[unused self: Self]() {}\n  }\n}\n\n// --- import_excluded.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"excluded_with_range\";\n\nfn F(c: C) { c.(I.Op)(); }\n\n// CHECK:STDOUT: --- exclude/included.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- exclude/included_with_range.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic]\n// CHECK:STDOUT:   %pattern_type.fa0: type = pattern_type %Self.binding.as_type [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Op.type.71c: type = fn_type @I.WithSelf.Op, @I.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Op.ae1: %I.WithSelf.Op.type.71c = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.Op.decl [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.Op.type.c9a: type = fn_type @I.WithSelf.Op, @I.WithSelf(%I.facet) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.Op.b3e: %I.WithSelf.Op.type.c9a = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %I.WithSelf.Op.decl: @I.WithSelf.%I.WithSelf.Op.type (%I.WithSelf.Op.type.71c) = fn_decl @I.WithSelf.Op [symbolic = @I.WithSelf.%I.WithSelf.Op (constants.%I.WithSelf.Op.ae1)] {\n// CHECK:STDOUT:     %self.patt: @I.WithSelf.Op.%pattern_type (%pattern_type.fa0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: @I.WithSelf.Op.%pattern_type (%pattern_type.fa0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: @I.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc8_22.1: type = splice_block %.loc8_22.2 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)] {\n// CHECK:STDOUT:       %Self.ref: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       %.loc8_22.2: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self: @I.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type) = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, %I.WithSelf.Op.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .Op = @I.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%I.WithSelf.Op.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.Op(@I.%Self: %I.type) {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.fa0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @I.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %I.WithSelf.Op.type => constants.%I.WithSelf.Op.type.71c\n// CHECK:STDOUT:   %I.WithSelf.Op => constants.%I.WithSelf.Op.ae1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.Op(constants.%Self) {\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.fa0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %I.WithSelf.Op.type => constants.%I.WithSelf.Op.type.c9a\n// CHECK:STDOUT:   %I.WithSelf.Op => constants.%I.WithSelf.Op.b3e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.Op(constants.%I.facet) {\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- import_included.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Op.type.f73: type = fn_type @I.WithSelf.Op, @I.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Op.f53: %I.WithSelf.Op.type.f73 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic]\n// CHECK:STDOUT:   %pattern_type.422: type = pattern_type %Self.binding.as_type [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.e26 [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness imports.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.Op.type.537: type = fn_type @I.WithSelf.Op, @I.WithSelf(%I.facet) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.Op.a52: %I.WithSelf.Op.type.537 = struct_value () [concrete]\n// CHECK:STDOUT:   %.c12: type = fn_type_with_self_type %I.WithSelf.Op.type.537, %I.facet [concrete]\n// CHECK:STDOUT:   %C.as.I.impl.Op.type: type = fn_type @C.as.I.impl.Op [concrete]\n// CHECK:STDOUT:   %C.as.I.impl.Op: %C.as.I.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.I: type = import_ref Main//included_with_range, I, loaded [concrete = constants.%I.type]\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//included_with_range, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//included_with_range, loc16_1, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//included_with_range, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.d09: %I.assoc_type = import_ref Main//included_with_range, loc8_29, loaded [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %Main.Op = import_ref Main//included_with_range, Op, unloaded\n// CHECK:STDOUT:   %Main.import_ref.2362f8.2: %I.type = import_ref Main//included_with_range, loc7_13, loaded [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Main.import_ref.c82 = import_ref Main//included_with_range, loc7_13, unloaded\n// CHECK:STDOUT:   %Main.import_ref.e26: @I.WithSelf.%I.WithSelf.Op.type (%I.WithSelf.Op.type.f73) = import_ref Main//included_with_range, loc8_29, loaded [symbolic = @I.WithSelf.%I.WithSelf.Op (constants.%I.WithSelf.Op.f53)]\n// CHECK:STDOUT:   %Main.import_ref.f72: <witness> = import_ref Main//included_with_range, loc13_15, loaded [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %Main.import_ref.61c: type = import_ref Main//included_with_range, loc13_8, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.72a: type = import_ref Main//included_with_range, loc13_13, loaded [concrete = constants.%I.type]\n// CHECK:STDOUT:   %Main.import_ref.4bc: %C.as.I.impl.Op.type = import_ref Main//included_with_range, loc14_32, loaded [concrete = constants.%C.as.I.impl.Op]\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%Main.import_ref.4bc), @C.as.I.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = imports.%Main.I\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.7c7 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I [from \"exclude/included_with_range.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.c82\n// CHECK:STDOUT:   .Op = imports.%Main.import_ref.d09\n// CHECK:STDOUT:   witness = (imports.%Main.Op)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: imports.%Main.import_ref.61c as imports.%Main.import_ref.72a [from \"exclude/included_with_range.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = imports.%Main.import_ref.f72\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"exclude/included_with_range.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %I.ref: type = name_ref I, imports.%Main.I [concrete = constants.%I.type]\n// CHECK:STDOUT:   %Op.ref: %I.assoc_type = name_ref Op, imports.%Main.import_ref.d09 [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %impl.elem0: %.c12 = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%C.as.I.impl.Op]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %c.ref, %impl.elem0\n// CHECK:STDOUT:   %C.as.I.impl.Op.call: init %empty_tuple.type = call %bound_method(%c.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.Op(imports.%Main.import_ref.2362f8.2: %I.type) [from \"exclude/included_with_range.carbon\"] {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.422)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.I.impl.Op [from \"exclude/included_with_range.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %I.WithSelf.Op.type => constants.%I.WithSelf.Op.type.f73\n// CHECK:STDOUT:   %I.WithSelf.Op => constants.%I.WithSelf.Op.f53\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.Op(constants.%Self) {\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.422\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %I.WithSelf.Op.type => constants.%I.WithSelf.Op.type.537\n// CHECK:STDOUT:   %I.WithSelf.Op => constants.%I.WithSelf.Op.a52\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- import_excluded.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Op.type.f73: type = fn_type @I.WithSelf.Op, @I.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Op.f53: %I.WithSelf.Op.type.f73 = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.e26 [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness imports.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.Op.type.537: type = fn_type @I.WithSelf.Op, @I.WithSelf(%I.facet) [concrete]\n// CHECK:STDOUT:   %.c12: type = fn_type_with_self_type %I.WithSelf.Op.type.537, %I.facet [concrete]\n// CHECK:STDOUT:   %C.as.I.impl.Op.type: type = fn_type @C.as.I.impl.Op [concrete]\n// CHECK:STDOUT:   %C.as.I.impl.Op: %C.as.I.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.I: type = import_ref Main//excluded_with_range, I, loaded [concrete = constants.%I.type]\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//excluded_with_range, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.d09: %I.assoc_type = import_ref Main//excluded_with_range, loc6_29, loaded [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %Main.import_ref.e26: @I.WithSelf.%I.WithSelf.Op.type (%I.WithSelf.Op.type.f73) = import_ref Main//excluded_with_range, loc6_29, loaded [symbolic = @I.WithSelf.%I.WithSelf.Op (constants.%I.WithSelf.Op.f53)]\n// CHECK:STDOUT:   %Main.import_ref.4bc: %C.as.I.impl.Op.type = import_ref Main//excluded_with_range, loc12_32, loaded [concrete = constants.%C.as.I.impl.Op]\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%Main.import_ref.4bc), @C.as.I.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = imports.%Main.I\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.7c7 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %I.ref: type = name_ref I, imports.%Main.I [concrete = constants.%I.type]\n// CHECK:STDOUT:   %Op.ref: %I.assoc_type = name_ref Op, imports.%Main.import_ref.d09 [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %impl.elem0: %.c12 = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%C.as.I.impl.Op]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %c.ref, %impl.elem0\n// CHECK:STDOUT:   %C.as.I.impl.Op.call: init %empty_tuple.type = call %bound_method(%c.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/multi_error.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/multi_error.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/multi_error.carbon\n\n// --- fail_multi_error.carbon\n\n// When naming insts, the `error` instruction generated is added for naming.\n// This regression test ensures that reuse of `<error>` in different scopes\n// works.\n\n// CHECK:STDERR: fail_multi_error.carbon:[[@LINE+4]]:8: error: implicit parameters of functions must be constant or `self` [ImplictParamMustBeConstant]\n// CHECK:STDERR: fn Foo[a: ()]();\n// CHECK:STDERR:        ^~~~~\n// CHECK:STDERR:\nfn Foo[a: ()]();\n// CHECK:STDERR: fail_multi_error.carbon:[[@LINE+4]]:8: error: implicit parameters of functions must be constant or `self` [ImplictParamMustBeConstant]\n// CHECK:STDERR: fn Boo[a: ()]() {}\n// CHECK:STDERR:        ^~~~~\n// CHECK:STDERR:\nfn Boo[a: ()]() {}\n\n// CHECK:STDOUT: --- fail_multi_error.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Boo.type: type = fn_type @Boo [concrete]\n// CHECK:STDOUT:   %Boo: %Boo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Boo = %Boo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {} {}\n// CHECK:STDOUT:   %Boo.decl: %Boo.type = fn_decl @Boo [concrete = constants.%Boo] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Boo() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/name_lookup.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/name_lookup.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/name_lookup.carbon\n\n// --- fail_not_found.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Main() {\n  //@dump-sem-ir-begin\n  // CHECK:STDERR: fail_not_found.carbon:[[@LINE+4]]:3: error: name `x` not found [NameNotFound]\n  // CHECK:STDERR:   x;\n  // CHECK:STDERR:   ^\n  // CHECK:STDERR:\n  x;\n  //@dump-sem-ir-end\n}\n\n// --- fail_qualififier_unsupported.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {\n  //@dump-sem-ir-begin\n  // CHECK:STDERR: fail_qualififier_unsupported.carbon:[[@LINE+4]]:3: error: type `bool` does not support qualified expressions [QualifiedExprUnsupported]\n  // CHECK:STDERR:   true.b;\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR:\n  true.b;\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- fail_not_found.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error> [concrete = <error>]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_qualififier_unsupported.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/parens.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/parens.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/parens.carbon\n\nvar a: i32 = (1);\nvar b: i32 = ((2));\n\n// CHECK:STDOUT: --- parens.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.7ce = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %i32 = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %i32.loc14: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %a: ref %i32 = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %i32.loc15: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc14: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc14_1.1: <bound method> = bound_method %int_1, %impl.elem0.loc14 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc14: <specific function> = specific_function %impl.elem0.loc14, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_1.2: <bound method> = bound_method %int_1, %specific_fn.loc14 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14: init %i32 = call %bound_method.loc14_1.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc14: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   assign file.%a.var, %.loc14\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc15: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc15_1.1: <bound method> = bound_method %int_2, %impl.elem0.loc15 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc15: <specific function> = specific_function %impl.elem0.loc15, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_1.2: <bound method> = bound_method %int_2, %specific_fn.loc15 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc15: init %i32 = call %bound_method.loc15_1.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc15: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc15 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   assign file.%b.var, %.loc15\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/raw_identifier.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/raw_identifier.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/raw_identifier.carbon\n\nfn A(n: ()) -> () {\n  return r#n;\n}\n\nfn B(r#n: ()) -> () {\n  return n;\n}\n\nfn C(r#if: ()) -> () {\n  return r#if;\n}\n\n// CHECK:STDOUT: --- raw_identifier.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %n.patt: %pattern_type = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc14_17.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc14_17.2: type = converted %.loc14_17.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc14_17.3: Core.Form = init_form %.loc14_17.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %n.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc14_10.1: type = splice_block %.loc14_10.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc14_10.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc14_10.3: type = converted %.loc14_10.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %n: %empty_tuple.type = value_binding n, %n.param\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param1\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {\n// CHECK:STDOUT:     %n.patt: %pattern_type = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc18_19.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc18_19.2: type = converted %.loc18_19.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc18_19.3: Core.Form = init_form %.loc18_19.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %n.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc18_12.1: type = splice_block %.loc18_12.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc18_12.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc18_12.3: type = converted %.loc18_12.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %n: %empty_tuple.type = value_binding n, %n.param\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param1\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {\n// CHECK:STDOUT:     %if.patt: %pattern_type = value_binding_pattern r#if [concrete]\n// CHECK:STDOUT:     %if.param_patt: %pattern_type = value_param_pattern %if.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc22_20.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc22_20.2: type = converted %.loc22_20.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc22_20.3: Core.Form = init_form %.loc22_20.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %if.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc22_13.1: type = splice_block %.loc22_13.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc22_13.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc22_13.3: type = converted %.loc22_13.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %if: %empty_tuple.type = value_binding r#if, %if.param\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param1\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A(%n.param: %empty_tuple.type) -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %empty_tuple.type = name_ref n, %n\n// CHECK:STDOUT:   %.loc15_10: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc15_13: init %empty_tuple.type = converted %n.ref, %.loc15_10 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   return %.loc15_13\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B(%n.param: %empty_tuple.type) -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %empty_tuple.type = name_ref n, %n\n// CHECK:STDOUT:   %.loc19_10: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc19_11: init %empty_tuple.type = converted %n.ref, %.loc19_10 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   return %.loc19_11\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C(%if.param: %empty_tuple.type) -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %if.ref: %empty_tuple.type = name_ref r#if, %if\n// CHECK:STDOUT:   %.loc23_10: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc23_14: init %empty_tuple.type = converted %if.ref, %.loc23_10 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   return %.loc23_14\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-raw-sem-ir --builtin-sem-ir\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon\n\n// CHECK:STDOUT: ---\n// CHECK:STDOUT: filename:        builtins.carbon\n// CHECK:STDOUT: sem_ir:\n// CHECK:STDOUT:   names:           {}\n// CHECK:STDOUT:   import_irs:\n// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:   import_ir_insts: {}\n// CHECK:STDOUT:   clang_decls:     {}\n// CHECK:STDOUT:   name_scopes:\n// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:   entity_names:    {}\n// CHECK:STDOUT:   cpp_global_vars: {}\n// CHECK:STDOUT:   functions:       {}\n// CHECK:STDOUT:   classes:         {}\n// CHECK:STDOUT:   interfaces:      {}\n// CHECK:STDOUT:   associated_constants: {}\n// CHECK:STDOUT:   impls:           {}\n// CHECK:STDOUT:   generics:        {}\n// CHECK:STDOUT:   specifics:       {}\n// CHECK:STDOUT:   specific_interfaces: {}\n// CHECK:STDOUT:   struct_type_fields:\n// CHECK:STDOUT:     struct_type_fields_empty: {}\n// CHECK:STDOUT:   types:\n// CHECK:STDOUT:     'type(TypeType)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}\n// CHECK:STDOUT:     'type(inst(FormType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}\n// CHECK:STDOUT:     'type(Error)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}\n// CHECK:STDOUT:     'type(inst(NamespaceType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:   facet_types:     {}\n// CHECK:STDOUT:   insts:\n// CHECK:STDOUT:     'inst(TypeType)':  {kind: TypeType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(AutoType)':  {kind: AutoType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(BoolType)':  {kind: BoolType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(BoundMethodType)': {kind: BoundMethodType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(CharLiteralType)': {kind: CharLiteralType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(ErrorInst)': {kind: ErrorInst, type: type(Error)}\n// CHECK:STDOUT:     'inst(FloatLiteralType)': {kind: FloatLiteralType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(FormType)':  {kind: FormType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(InstType)':  {kind: InstType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(IntLiteralType)': {kind: IntLiteralType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(NamespaceType)': {kind: NamespaceType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(RequireSpecificDefinitionType)': {kind: RequireSpecificDefinitionType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(SpecificFunctionType)': {kind: SpecificFunctionType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(VtableType)': {kind: VtableType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(WitnessType)': {kind: WitnessType, type: type(TypeType)}\n// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:   constant_values:\n// CHECK:STDOUT:     values:\n// CHECK:STDOUT:       'inst(TypeType)':  concrete_constant(inst(TypeType))\n// CHECK:STDOUT:       'inst(AutoType)':  concrete_constant(inst(AutoType))\n// CHECK:STDOUT:       'inst(BoolType)':  concrete_constant(inst(BoolType))\n// CHECK:STDOUT:       'inst(BoundMethodType)': concrete_constant(inst(BoundMethodType))\n// CHECK:STDOUT:       'inst(CharLiteralType)': concrete_constant(inst(CharLiteralType))\n// CHECK:STDOUT:       'inst(ErrorInst)': concrete_constant(inst(ErrorInst))\n// CHECK:STDOUT:       'inst(FloatLiteralType)': concrete_constant(inst(FloatLiteralType))\n// CHECK:STDOUT:       'inst(FormType)':  concrete_constant(inst(FormType))\n// CHECK:STDOUT:       'inst(InstType)':  concrete_constant(inst(InstType))\n// CHECK:STDOUT:       'inst(IntLiteralType)': concrete_constant(inst(IntLiteralType))\n// CHECK:STDOUT:       'inst(NamespaceType)': concrete_constant(inst(NamespaceType))\n// CHECK:STDOUT:       'inst(RequireSpecificDefinitionType)': concrete_constant(inst(RequireSpecificDefinitionType))\n// CHECK:STDOUT:       'inst(SpecificFunctionType)': concrete_constant(inst(SpecificFunctionType))\n// CHECK:STDOUT:       'inst(VtableType)': concrete_constant(inst(VtableType))\n// CHECK:STDOUT:       'inst(WitnessType)': concrete_constant(inst(WitnessType))\n// CHECK:STDOUT:       instF:           concrete_constant(instF)\n// CHECK:STDOUT:     symbolic_constants: {}\n// CHECK:STDOUT:   inst_blocks:\n// CHECK:STDOUT:     inst_block_empty: {}\n// CHECK:STDOUT:     exports:         {}\n// CHECK:STDOUT:     generated:       {}\n// CHECK:STDOUT:     imports:         {}\n// CHECK:STDOUT:     global_init:     {}\n// CHECK:STDOUT:     inst_block50000005:\n// CHECK:STDOUT:       0:               instF\n// CHECK:STDOUT:   value_stores:\n// CHECK:STDOUT:     shared_values:\n// CHECK:STDOUT:       ints:            {}\n// CHECK:STDOUT:       reals:           {}\n// CHECK:STDOUT:       floats:          {}\n// CHECK:STDOUT:       identifiers:     {}\n// CHECK:STDOUT:       strings:         {}\n// CHECK:STDOUT: ...\n"
  },
  {
    "path": "toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-raw-sem-ir --builtin-sem-ir\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/raw_sem_ir/cpp_interop.carbon\n\n// --- header.h\n\nstruct X {\n  X* _Nonnull p;\n};\n\nvoid f(X x = {}) {\n}\n\nX* _Nonnull global;\n\n// --- import.carbon\n\nimport Cpp library \"header.h\";\n\nfn G(x: Cpp.X) {\n  Cpp.f();\n  Cpp.f(x);\n  Cpp.f(*Cpp.global);\n}\n\n// CHECK:STDOUT: ---\n// CHECK:STDOUT: filename:        import.carbon\n// CHECK:STDOUT: sem_ir:\n// CHECK:STDOUT:   names:\n// CHECK:STDOUT:     name0:           G\n// CHECK:STDOUT:     name1:           x\n// CHECK:STDOUT:     name2:           X\n// CHECK:STDOUT:     name3:           f\n// CHECK:STDOUT:     name4:           global\n// CHECK:STDOUT:     name5:           p\n// CHECK:STDOUT:     name6:           f__carbon_thunk\n// CHECK:STDOUT:   import_irs:\n// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:   import_ir_insts:\n// CHECK:STDOUT:     import_ir_inst0: {ir_id: import_ir(Cpp), clang_source_loc_id: clang_source_loc50000000}\n// CHECK:STDOUT:     import_ir_inst1: {ir_id: import_ir(Cpp), clang_source_loc_id: clang_source_loc50000001}\n// CHECK:STDOUT:     import_ir_inst2: {ir_id: import_ir(Cpp), clang_source_loc_id: clang_source_loc50000002}\n// CHECK:STDOUT:     import_ir_inst3: {ir_id: import_ir(Cpp), clang_source_loc_id: clang_source_loc50000003}\n// CHECK:STDOUT:     import_ir_inst4: {ir_id: import_ir(Cpp), clang_source_loc_id: clang_source_loc50000004}\n// CHECK:STDOUT:   clang_decls:\n// CHECK:STDOUT:     clang_decl_id50000000: {key: \"<translation unit>\", inst_id: inst50000011}\n// CHECK:STDOUT:     clang_decl_id50000001: {key: \"struct X {}\", inst_id: inst50000014}\n// CHECK:STDOUT:     clang_decl_id50000002: {key: \"X * _Nonnull p\", inst_id: inst50000022}\n// CHECK:STDOUT:     clang_decl_id50000003: {key: {decl: \"void f(X x = {})\", kind: normal, num_params: 0}, inst_id: inst5000002D}\n// CHECK:STDOUT:     clang_decl_id50000004: {key: {decl: \"extern void f__carbon_thunk()\", kind: normal, num_params: 0}, inst_id: inst50000030}\n// CHECK:STDOUT:     clang_decl_id50000005: {key: {decl: \"void f(X x = {})\", kind: normal, num_params: 1}, inst_id: inst5000003B}\n// CHECK:STDOUT:     clang_decl_id50000006: {key: {decl: \"extern void f__carbon_thunk(X * _Nonnull x)\", kind: normal, num_params: 1}, inst_id: inst50000043}\n// CHECK:STDOUT:     clang_decl_id50000007: {key: \"X * _Nonnull global\", inst_id: inst5000004E}\n// CHECK:STDOUT:   name_scopes:\n// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name(Cpp): inst50000011, name0: inst5000001D}}\n// CHECK:STDOUT:     name_scope50000001: {inst: inst50000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name2: inst50000014, name3: inst5000002A, name4: inst5000004E}}\n// CHECK:STDOUT:     name_scope50000002: {inst: inst50000014, parent_scope: name_scope50000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:   entity_names:\n// CHECK:STDOUT:     entity_name50000000: {name: name1, parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name50000001: {name: name1, parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name50000002: {name: name1, parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name50000003: {name: name4, parent_scope: name_scope50000001, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:   cpp_global_vars:\n// CHECK:STDOUT:     cpp_global_var50000000: {key: {entity_name_id: entity_name50000003}, clang_decl_id: clang_decl_id50000007}\n// CHECK:STDOUT:   functions:\n// CHECK:STDOUT:     function50000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block50000007, call_params_id: inst_block50000008, body: [inst_block5000000B]}\n// CHECK:STDOUT:     function50000001: {name: name3, parent_scope: name_scope50000001, call_param_patterns_id: inst_block_empty, call_params_id: inst_block_empty}\n// CHECK:STDOUT:     function50000002: {name: name6, parent_scope: name_scope50000001, call_param_patterns_id: inst_block_empty, call_params_id: inst_block_empty}\n// CHECK:STDOUT:     function50000003: {name: name3, parent_scope: name_scope50000001, call_param_patterns_id: inst_block5000000F, call_params_id: inst_block50000010}\n// CHECK:STDOUT:     function50000004: {name: name6, parent_scope: name_scope50000001, call_param_patterns_id: inst_block50000015, call_params_id: inst_block50000016}\n// CHECK:STDOUT:   classes:\n// CHECK:STDOUT:     class50000000:   {name: name2, parent_scope: name_scope50000001, self_type_id: type(inst50000015), inheritance_kind: Base, is_dynamic: 0, scope_id: name_scope50000002, body_block_id: inst_block5000000C, adapt_id: inst<none>, base_id: inst<none>, complete_type_witness_id: inst50000025, vtable_decl_id: inst<none>}}\n// CHECK:STDOUT:   interfaces:      {}\n// CHECK:STDOUT:   associated_constants: {}\n// CHECK:STDOUT:   impls:           {}\n// CHECK:STDOUT:   generics:        {}\n// CHECK:STDOUT:   specifics:       {}\n// CHECK:STDOUT:   specific_interfaces: {}\n// CHECK:STDOUT:   struct_type_fields:\n// CHECK:STDOUT:     struct_type_fields_empty: {}\n// CHECK:STDOUT:     struct_type_fields50000001:\n// CHECK:STDOUT:       0:               {name_id: name5, type_inst_id: inst50000020}\n// CHECK:STDOUT:     struct_type_fields50000002:\n// CHECK:STDOUT:       0:               {name_id: name5, type_inst_id: inst50000020}\n// CHECK:STDOUT:   types:\n// CHECK:STDOUT:     'type(TypeType)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}\n// CHECK:STDOUT:     'type(inst(FormType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}\n// CHECK:STDOUT:     'type(Error)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}\n// CHECK:STDOUT:     'type(inst(NamespaceType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     'type(inst(InstType))':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000013)}\n// CHECK:STDOUT:     'type(inst50000013)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000013)}\n// CHECK:STDOUT:     'type(inst5000001E)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000013)}\n// CHECK:STDOUT:     'type(inst50000020)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst50000020)}\n// CHECK:STDOUT:     'type(inst(WitnessType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     'type(inst50000027)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst50000027)}\n// CHECK:STDOUT:     'type(inst50000024)':\n// CHECK:STDOUT:       value_repr:      {kind: pointer, type: type(inst50000027)}\n// CHECK:STDOUT:     'type(inst50000015)':\n// CHECK:STDOUT:       value_repr:      {kind: pointer, type: type(inst50000027)}\n// CHECK:STDOUT:     'type(inst50000029)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000013)}\n// CHECK:STDOUT:     'type(inst5000002E)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000013)}\n// CHECK:STDOUT:     'type(inst50000031)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000013)}\n// CHECK:STDOUT:     'type(inst5000003C)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000013)}\n// CHECK:STDOUT:     'type(inst50000044)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000013)}\n// CHECK:STDOUT:   facet_types:     {}\n// CHECK:STDOUT:   insts:\n// CHECK:STDOUT:     'inst(TypeType)':  {kind: TypeType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(AutoType)':  {kind: AutoType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(BoolType)':  {kind: BoolType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(BoundMethodType)': {kind: BoundMethodType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(CharLiteralType)': {kind: CharLiteralType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(ErrorInst)': {kind: ErrorInst, type: type(Error)}\n// CHECK:STDOUT:     'inst(FloatLiteralType)': {kind: FloatLiteralType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(FormType)':  {kind: FormType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(InstType)':  {kind: InstType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(IntLiteralType)': {kind: IntLiteralType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(NamespaceType)': {kind: NamespaceType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(RequireSpecificDefinitionType)': {kind: RequireSpecificDefinitionType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(SpecificFunctionType)': {kind: SpecificFunctionType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(VtableType)': {kind: VtableType, type: type(TypeType)}\n// CHECK:STDOUT:     'inst(WitnessType)': {kind: WitnessType, type: type(TypeType)}\n// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst50000010:    {kind: ImportCppDecl}\n// CHECK:STDOUT:     inst50000011:    {kind: Namespace, arg0: name_scope50000001, arg1: inst50000010, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst50000012:    {kind: NameRef, arg0: name(Cpp), arg1: inst50000011, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst50000013:    {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000014:    {kind: ClassDecl, arg0: class50000000, arg1: inst_block<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000015:    {kind: ClassType, arg0: class50000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000016:    {kind: NameRef, arg0: name2, arg1: inst50000014, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000017:    {kind: PatternType, arg0: inst50000015, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000018:    {kind: ValueBinding, arg0: entity_name50000000, arg1: inst5000001B, type: type(inst50000015)}\n// CHECK:STDOUT:     inst50000019:    {kind: ValueBindingPattern, arg0: entity_name50000000, type: type(inst50000017)}\n// CHECK:STDOUT:     inst5000001A:    {kind: ValueParamPattern, arg0: inst50000019, type: type(inst50000017)}\n// CHECK:STDOUT:     inst5000001B:    {kind: ValueParam, arg0: call_param0, arg1: name1, type: type(inst50000015)}\n// CHECK:STDOUT:     inst5000001C:    {kind: SpliceBlock, arg0: inst_block50000005, arg1: inst50000016, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000001D:    {kind: FunctionDecl, arg0: function50000000, arg1: inst_block5000000A, type: type(inst5000001E)}\n// CHECK:STDOUT:     inst5000001E:    {kind: FunctionType, arg0: function50000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000001F:    {kind: StructValue, arg0: inst_block_empty, type: type(inst5000001E)}\n// CHECK:STDOUT:     inst50000020:    {kind: PointerType, arg0: inst50000015, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000021:    {kind: UnboundElementType, arg0: inst50000015, arg1: inst50000020, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000022:    {kind: FieldDecl, arg0: name5, arg1: element0, type: type(inst50000021)}\n// CHECK:STDOUT:     inst50000023:    {kind: CustomLayoutType, arg0: struct_type_fields50000001, arg1: custom_layout50000001, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000024:    {kind: CustomLayoutType, arg0: struct_type_fields50000002, arg1: custom_layout50000001, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000025:    {kind: CompleteTypeWitness, arg0: inst50000023, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst50000026:    {kind: CompleteTypeWitness, arg0: inst50000024, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst50000027:    {kind: PointerType, arg0: inst50000024, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000028:    {kind: NameRef, arg0: name(Cpp), arg1: inst50000011, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst50000029:    {kind: CppOverloadSetType, arg0: cpp_overload_set50000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000002A:    {kind: CppOverloadSetValue, arg0: cpp_overload_set50000000, type: type(inst50000029)}\n// CHECK:STDOUT:     inst5000002B:    {kind: CppOverloadSetValue, arg0: cpp_overload_set50000000, type: type(inst50000029)}\n// CHECK:STDOUT:     inst5000002C:    {kind: NameRef, arg0: name3, arg1: inst5000002A, type: type(inst50000029)}\n// CHECK:STDOUT:     inst5000002D:    {kind: FunctionDecl, arg0: function50000001, arg1: inst_block_empty, type: type(inst5000002E)}\n// CHECK:STDOUT:     inst5000002E:    {kind: FunctionType, arg0: function50000001, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000002F:    {kind: StructValue, arg0: inst_block_empty, type: type(inst5000002E)}\n// CHECK:STDOUT:     inst50000030:    {kind: FunctionDecl, arg0: function50000002, arg1: inst_block_empty, type: type(inst50000031)}\n// CHECK:STDOUT:     inst50000031:    {kind: FunctionType, arg0: function50000002, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000032:    {kind: StructValue, arg0: inst_block_empty, type: type(inst50000031)}\n// CHECK:STDOUT:     inst50000033:    {kind: Call, arg0: inst50000030, arg1: inst_block_empty, type: type(inst50000013)}\n// CHECK:STDOUT:     inst50000034:    {kind: NameRef, arg0: name(Cpp), arg1: inst50000011, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst50000035:    {kind: NameRef, arg0: name3, arg1: inst5000002A, type: type(inst50000029)}\n// CHECK:STDOUT:     inst50000036:    {kind: NameRef, arg0: name1, arg1: inst50000018, type: type(inst50000015)}\n// CHECK:STDOUT:     inst50000037:    {kind: ValueBinding, arg0: entity_name50000001, arg1: inst5000003A, type: type(inst50000015)}\n// CHECK:STDOUT:     inst50000038:    {kind: ValueBindingPattern, arg0: entity_name50000001, type: type(inst50000017)}\n// CHECK:STDOUT:     inst50000039:    {kind: ValueParamPattern, arg0: inst50000038, type: type(inst50000017)}\n// CHECK:STDOUT:     inst5000003A:    {kind: ValueParam, arg0: call_param0, arg1: name1, type: type(inst50000015)}\n// CHECK:STDOUT:     inst5000003B:    {kind: FunctionDecl, arg0: function50000003, arg1: inst_block50000012, type: type(inst5000003C)}\n// CHECK:STDOUT:     inst5000003C:    {kind: FunctionType, arg0: function50000003, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000003D:    {kind: StructValue, arg0: inst_block_empty, type: type(inst5000003C)}\n// CHECK:STDOUT:     inst5000003E:    {kind: PatternType, arg0: inst50000020, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000003F:    {kind: ValueBinding, arg0: entity_name50000002, arg1: inst50000042, type: type(inst50000020)}\n// CHECK:STDOUT:     inst50000040:    {kind: ValueBindingPattern, arg0: entity_name50000002, type: type(inst5000003E)}\n// CHECK:STDOUT:     inst50000041:    {kind: ValueParamPattern, arg0: inst50000040, type: type(inst5000003E)}\n// CHECK:STDOUT:     inst50000042:    {kind: ValueParam, arg0: call_param0, arg1: name1, type: type(inst50000020)}\n// CHECK:STDOUT:     inst50000043:    {kind: FunctionDecl, arg0: function50000004, arg1: inst_block50000018, type: type(inst50000044)}\n// CHECK:STDOUT:     inst50000044:    {kind: FunctionType, arg0: function50000004, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000045:    {kind: StructValue, arg0: inst_block_empty, type: type(inst50000044)}\n// CHECK:STDOUT:     inst50000046:    {kind: ValueAsRef, arg0: inst50000036, type: type(inst50000015)}\n// CHECK:STDOUT:     inst50000047:    {kind: AddrOf, arg0: inst50000046, type: type(inst50000020)}\n// CHECK:STDOUT:     inst50000048:    {kind: Call, arg0: inst50000043, arg1: inst_block5000001A, type: type(inst50000013)}\n// CHECK:STDOUT:     inst50000049:    {kind: NameRef, arg0: name(Cpp), arg1: inst50000011, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst5000004A:    {kind: NameRef, arg0: name3, arg1: inst5000002A, type: type(inst50000029)}\n// CHECK:STDOUT:     inst5000004B:    {kind: NameRef, arg0: name(Cpp), arg1: inst50000011, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst5000004C:    {kind: RefBindingPattern, arg0: entity_name50000003, type: type(inst5000003E)}\n// CHECK:STDOUT:     inst5000004D:    {kind: VarPattern, arg0: inst5000004C, type: type(inst5000003E)}\n// CHECK:STDOUT:     inst5000004E:    {kind: VarStorage, arg0: inst5000004D, type: type(inst50000020)}\n// CHECK:STDOUT:     inst5000004F:    {kind: NameRef, arg0: name4, arg1: inst5000004E, type: type(inst50000020)}\n// CHECK:STDOUT:     inst50000050:    {kind: AcquireValue, arg0: inst5000004F, type: type(inst50000020)}\n// CHECK:STDOUT:     inst50000051:    {kind: Deref, arg0: inst50000050, type: type(inst50000015)}\n// CHECK:STDOUT:     inst50000052:    {kind: AcquireValue, arg0: inst50000051, type: type(inst50000015)}\n// CHECK:STDOUT:     inst50000053:    {kind: ValueAsRef, arg0: inst50000052, type: type(inst50000015)}\n// CHECK:STDOUT:     inst50000054:    {kind: AddrOf, arg0: inst50000053, type: type(inst50000020)}\n// CHECK:STDOUT:     inst50000055:    {kind: Call, arg0: inst50000043, arg1: inst_block5000001C, type: type(inst50000013)}\n// CHECK:STDOUT:     inst50000056:    {kind: Return}\n// CHECK:STDOUT:   constant_values:\n// CHECK:STDOUT:     values:\n// CHECK:STDOUT:       'inst(TypeType)':  concrete_constant(inst(TypeType))\n// CHECK:STDOUT:       'inst(AutoType)':  concrete_constant(inst(AutoType))\n// CHECK:STDOUT:       'inst(BoolType)':  concrete_constant(inst(BoolType))\n// CHECK:STDOUT:       'inst(BoundMethodType)': concrete_constant(inst(BoundMethodType))\n// CHECK:STDOUT:       'inst(CharLiteralType)': concrete_constant(inst(CharLiteralType))\n// CHECK:STDOUT:       'inst(ErrorInst)': concrete_constant(inst(ErrorInst))\n// CHECK:STDOUT:       'inst(FloatLiteralType)': concrete_constant(inst(FloatLiteralType))\n// CHECK:STDOUT:       'inst(FormType)':  concrete_constant(inst(FormType))\n// CHECK:STDOUT:       'inst(InstType)':  concrete_constant(inst(InstType))\n// CHECK:STDOUT:       'inst(IntLiteralType)': concrete_constant(inst(IntLiteralType))\n// CHECK:STDOUT:       'inst(NamespaceType)': concrete_constant(inst(NamespaceType))\n// CHECK:STDOUT:       'inst(RequireSpecificDefinitionType)': concrete_constant(inst(RequireSpecificDefinitionType))\n// CHECK:STDOUT:       'inst(SpecificFunctionType)': concrete_constant(inst(SpecificFunctionType))\n// CHECK:STDOUT:       'inst(VtableType)': concrete_constant(inst(VtableType))\n// CHECK:STDOUT:       'inst(WitnessType)': concrete_constant(inst(WitnessType))\n// CHECK:STDOUT:       instF:           concrete_constant(instF)\n// CHECK:STDOUT:       inst50000011:    concrete_constant(inst50000011)\n// CHECK:STDOUT:       inst50000012:    concrete_constant(inst50000011)\n// CHECK:STDOUT:       inst50000013:    concrete_constant(inst50000013)\n// CHECK:STDOUT:       inst50000014:    concrete_constant(inst50000015)\n// CHECK:STDOUT:       inst50000015:    concrete_constant(inst50000015)\n// CHECK:STDOUT:       inst50000016:    concrete_constant(inst50000015)\n// CHECK:STDOUT:       inst50000017:    concrete_constant(inst50000017)\n// CHECK:STDOUT:       inst50000019:    concrete_constant(inst50000019)\n// CHECK:STDOUT:       inst5000001A:    concrete_constant(inst5000001A)\n// CHECK:STDOUT:       inst5000001C:    concrete_constant(inst50000015)\n// CHECK:STDOUT:       inst5000001D:    concrete_constant(inst5000001F)\n// CHECK:STDOUT:       inst5000001E:    concrete_constant(inst5000001E)\n// CHECK:STDOUT:       inst5000001F:    concrete_constant(inst5000001F)\n// CHECK:STDOUT:       inst50000020:    concrete_constant(inst50000020)\n// CHECK:STDOUT:       inst50000021:    concrete_constant(inst50000021)\n// CHECK:STDOUT:       inst50000022:    concrete_constant(inst50000022)\n// CHECK:STDOUT:       inst50000023:    concrete_constant(inst50000024)\n// CHECK:STDOUT:       inst50000024:    concrete_constant(inst50000024)\n// CHECK:STDOUT:       inst50000025:    concrete_constant(inst50000026)\n// CHECK:STDOUT:       inst50000026:    concrete_constant(inst50000026)\n// CHECK:STDOUT:       inst50000027:    concrete_constant(inst50000027)\n// CHECK:STDOUT:       inst50000028:    concrete_constant(inst50000011)\n// CHECK:STDOUT:       inst50000029:    concrete_constant(inst50000029)\n// CHECK:STDOUT:       inst5000002A:    concrete_constant(inst5000002B)\n// CHECK:STDOUT:       inst5000002B:    concrete_constant(inst5000002B)\n// CHECK:STDOUT:       inst5000002C:    concrete_constant(inst5000002B)\n// CHECK:STDOUT:       inst5000002D:    concrete_constant(inst5000002F)\n// CHECK:STDOUT:       inst5000002E:    concrete_constant(inst5000002E)\n// CHECK:STDOUT:       inst5000002F:    concrete_constant(inst5000002F)\n// CHECK:STDOUT:       inst50000030:    concrete_constant(inst50000032)\n// CHECK:STDOUT:       inst50000031:    concrete_constant(inst50000031)\n// CHECK:STDOUT:       inst50000032:    concrete_constant(inst50000032)\n// CHECK:STDOUT:       inst50000034:    concrete_constant(inst50000011)\n// CHECK:STDOUT:       inst50000035:    concrete_constant(inst5000002B)\n// CHECK:STDOUT:       inst50000038:    concrete_constant(inst50000038)\n// CHECK:STDOUT:       inst50000039:    concrete_constant(inst50000039)\n// CHECK:STDOUT:       inst5000003B:    concrete_constant(inst5000003D)\n// CHECK:STDOUT:       inst5000003C:    concrete_constant(inst5000003C)\n// CHECK:STDOUT:       inst5000003D:    concrete_constant(inst5000003D)\n// CHECK:STDOUT:       inst5000003E:    concrete_constant(inst5000003E)\n// CHECK:STDOUT:       inst50000040:    concrete_constant(inst50000040)\n// CHECK:STDOUT:       inst50000041:    concrete_constant(inst50000041)\n// CHECK:STDOUT:       inst50000043:    concrete_constant(inst50000045)\n// CHECK:STDOUT:       inst50000044:    concrete_constant(inst50000044)\n// CHECK:STDOUT:       inst50000045:    concrete_constant(inst50000045)\n// CHECK:STDOUT:       inst50000049:    concrete_constant(inst50000011)\n// CHECK:STDOUT:       inst5000004A:    concrete_constant(inst5000002B)\n// CHECK:STDOUT:       inst5000004B:    concrete_constant(inst50000011)\n// CHECK:STDOUT:       inst5000004C:    concrete_constant(inst5000004C)\n// CHECK:STDOUT:       inst5000004D:    concrete_constant(inst5000004D)\n// CHECK:STDOUT:       inst5000004E:    concrete_constant(inst5000004E)\n// CHECK:STDOUT:       inst5000004F:    concrete_constant(inst5000004E)\n// CHECK:STDOUT:     symbolic_constants: {}\n// CHECK:STDOUT:   inst_blocks:\n// CHECK:STDOUT:     inst_block_empty: {}\n// CHECK:STDOUT:     exports:\n// CHECK:STDOUT:       0:               inst5000001D\n// CHECK:STDOUT:     generated:       {}\n// CHECK:STDOUT:     imports:\n// CHECK:STDOUT:       0:               inst50000011\n// CHECK:STDOUT:       1:               inst50000014\n// CHECK:STDOUT:       2:               inst5000002A\n// CHECK:STDOUT:       3:               inst5000002D\n// CHECK:STDOUT:       4:               inst50000030\n// CHECK:STDOUT:       5:               inst5000003B\n// CHECK:STDOUT:       6:               inst50000043\n// CHECK:STDOUT:       7:               inst5000004C\n// CHECK:STDOUT:       8:               inst5000004D\n// CHECK:STDOUT:       9:               inst5000004E\n// CHECK:STDOUT:     global_init:     {}\n// CHECK:STDOUT:     inst_block50000005:\n// CHECK:STDOUT:       0:               inst50000012\n// CHECK:STDOUT:       1:               inst50000016\n// CHECK:STDOUT:     inst_block50000006:\n// CHECK:STDOUT:       0:               inst5000001A\n// CHECK:STDOUT:     inst_block50000007:\n// CHECK:STDOUT:       0:               inst5000001A\n// CHECK:STDOUT:     inst_block50000008:\n// CHECK:STDOUT:       0:               inst5000001B\n// CHECK:STDOUT:     inst_block50000009:\n// CHECK:STDOUT:       0:               inst50000019\n// CHECK:STDOUT:       1:               inst5000001A\n// CHECK:STDOUT:     inst_block5000000A:\n// CHECK:STDOUT:       0:               inst5000001B\n// CHECK:STDOUT:       1:               inst5000001C\n// CHECK:STDOUT:       2:               inst50000018\n// CHECK:STDOUT:     inst_block5000000B:\n// CHECK:STDOUT:       0:               inst50000028\n// CHECK:STDOUT:       1:               inst5000002C\n// CHECK:STDOUT:       2:               inst50000033\n// CHECK:STDOUT:       3:               inst50000034\n// CHECK:STDOUT:       4:               inst50000035\n// CHECK:STDOUT:       5:               inst50000036\n// CHECK:STDOUT:       6:               inst50000046\n// CHECK:STDOUT:       7:               inst50000047\n// CHECK:STDOUT:       8:               inst50000048\n// CHECK:STDOUT:       9:               inst50000049\n// CHECK:STDOUT:       10:              inst5000004A\n// CHECK:STDOUT:       11:              inst5000004B\n// CHECK:STDOUT:       12:              inst5000004F\n// CHECK:STDOUT:       13:              inst50000050\n// CHECK:STDOUT:       14:              inst50000051\n// CHECK:STDOUT:       15:              inst50000052\n// CHECK:STDOUT:       16:              inst50000053\n// CHECK:STDOUT:       17:              inst50000054\n// CHECK:STDOUT:       18:              inst50000055\n// CHECK:STDOUT:       19:              inst50000056\n// CHECK:STDOUT:     inst_block5000000C:\n// CHECK:STDOUT:       0:               inst50000022\n// CHECK:STDOUT:       1:               inst50000023\n// CHECK:STDOUT:       2:               inst50000025\n// CHECK:STDOUT:     inst_block5000000D: {}\n// CHECK:STDOUT:     inst_block5000000E:\n// CHECK:STDOUT:       0:               inst50000039\n// CHECK:STDOUT:     inst_block5000000F:\n// CHECK:STDOUT:       0:               inst50000039\n// CHECK:STDOUT:     inst_block50000010:\n// CHECK:STDOUT:       0:               inst5000003A\n// CHECK:STDOUT:     inst_block50000011:\n// CHECK:STDOUT:       0:               inst50000038\n// CHECK:STDOUT:       1:               inst50000039\n// CHECK:STDOUT:     inst_block50000012:\n// CHECK:STDOUT:       0:               inst5000003A\n// CHECK:STDOUT:       1:               inst50000037\n// CHECK:STDOUT:     inst_block50000013: {}\n// CHECK:STDOUT:     inst_block50000014:\n// CHECK:STDOUT:       0:               inst50000041\n// CHECK:STDOUT:     inst_block50000015:\n// CHECK:STDOUT:       0:               inst50000041\n// CHECK:STDOUT:     inst_block50000016:\n// CHECK:STDOUT:       0:               inst50000042\n// CHECK:STDOUT:     inst_block50000017:\n// CHECK:STDOUT:       0:               inst50000040\n// CHECK:STDOUT:       1:               inst50000041\n// CHECK:STDOUT:     inst_block50000018:\n// CHECK:STDOUT:       0:               inst50000042\n// CHECK:STDOUT:       1:               inst5000003F\n// CHECK:STDOUT:     inst_block50000019:\n// CHECK:STDOUT:       0:               inst50000036\n// CHECK:STDOUT:     inst_block5000001A:\n// CHECK:STDOUT:       0:               inst50000047\n// CHECK:STDOUT:     inst_block5000001B:\n// CHECK:STDOUT:       0:               inst50000052\n// CHECK:STDOUT:     inst_block5000001C:\n// CHECK:STDOUT:       0:               inst50000054\n// CHECK:STDOUT:     inst_block5000001D:\n// CHECK:STDOUT:       0:               instF\n// CHECK:STDOUT:       1:               inst50000010\n// CHECK:STDOUT:       2:               inst5000001D\n// CHECK:STDOUT:   value_stores:\n// CHECK:STDOUT:     shared_values:\n// CHECK:STDOUT:       ints:            {}\n// CHECK:STDOUT:       reals:           {}\n// CHECK:STDOUT:       floats:          {}\n// CHECK:STDOUT:       identifiers:\n// CHECK:STDOUT:         identifier0:     G\n// CHECK:STDOUT:         identifier1:     x\n// CHECK:STDOUT:         identifier2:     X\n// CHECK:STDOUT:         identifier3:     f\n// CHECK:STDOUT:         identifier4:     global\n// CHECK:STDOUT:         identifier5:     p\n// CHECK:STDOUT:         identifier6:     f__carbon_thunk\n// CHECK:STDOUT:       strings:\n// CHECK:STDOUT:         string0:         header.h\n// CHECK:STDOUT: ...\n"
  },
  {
    "path": "toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-raw-sem-ir --no-dump-sem-ir\n//\n// Check that raw IR dumping works as expected.\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/raw_sem_ir/multifile.carbon\n\n// --- a.carbon\npackage A;\n\nfn A() {}\n\n// --- b.carbon\npackage B;\n\nimport A;\n\nfn B() {\n  A.A();\n}\n\n// CHECK:STDOUT: ---\n// CHECK:STDOUT: filename:        a.carbon\n// CHECK:STDOUT: sem_ir:\n// CHECK:STDOUT:   names:\n// CHECK:STDOUT:     name0:           A\n// CHECK:STDOUT:   import_irs:\n// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:   import_ir_insts: {}\n// CHECK:STDOUT:   clang_decls:     {}\n// CHECK:STDOUT:   name_scopes:\n// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst50000010}}\n// CHECK:STDOUT:   entity_names:    {}\n// CHECK:STDOUT:   cpp_global_vars: {}\n// CHECK:STDOUT:   functions:\n// CHECK:STDOUT:     function50000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block_empty, call_params_id: inst_block_empty, body: [inst_block50000006]}\n// CHECK:STDOUT:   classes:         {}\n// CHECK:STDOUT:   interfaces:      {}\n// CHECK:STDOUT:   associated_constants: {}\n// CHECK:STDOUT:   impls:           {}\n// CHECK:STDOUT:   generics:        {}\n// CHECK:STDOUT:   specifics:       {}\n// CHECK:STDOUT:   specific_interfaces: {}\n// CHECK:STDOUT:   struct_type_fields:\n// CHECK:STDOUT:     struct_type_fields_empty: {}\n// CHECK:STDOUT:   types:\n// CHECK:STDOUT:     'type(TypeType)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}\n// CHECK:STDOUT:     'type(inst(FormType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}\n// CHECK:STDOUT:     'type(Error)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}\n// CHECK:STDOUT:     'type(inst(NamespaceType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     'type(inst50000011)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000012)}\n// CHECK:STDOUT:     'type(inst50000012)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000012)}\n// CHECK:STDOUT:   facet_types:     {}\n// CHECK:STDOUT:   insts:\n// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst50000010:    {kind: FunctionDecl, arg0: function50000000, arg1: inst_block_empty, type: type(inst50000011)}\n// CHECK:STDOUT:     inst50000011:    {kind: FunctionType, arg0: function50000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000012:    {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000013:    {kind: StructValue, arg0: inst_block_empty, type: type(inst50000011)}\n// CHECK:STDOUT:     inst50000014:    {kind: Return}\n// CHECK:STDOUT:   constant_values:\n// CHECK:STDOUT:     values:\n// CHECK:STDOUT:       instF:           concrete_constant(instF)\n// CHECK:STDOUT:       inst50000010:    concrete_constant(inst50000013)\n// CHECK:STDOUT:       inst50000011:    concrete_constant(inst50000011)\n// CHECK:STDOUT:       inst50000012:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000013:    concrete_constant(inst50000013)\n// CHECK:STDOUT:     symbolic_constants: {}\n// CHECK:STDOUT:   inst_blocks:\n// CHECK:STDOUT:     inst_block_empty: {}\n// CHECK:STDOUT:     exports:\n// CHECK:STDOUT:       0:               inst50000010\n// CHECK:STDOUT:     generated:       {}\n// CHECK:STDOUT:     imports:         {}\n// CHECK:STDOUT:     global_init:     {}\n// CHECK:STDOUT:     inst_block50000005: {}\n// CHECK:STDOUT:     inst_block50000006:\n// CHECK:STDOUT:       0:               inst50000014\n// CHECK:STDOUT:     inst_block50000007:\n// CHECK:STDOUT:       0:               instF\n// CHECK:STDOUT:       1:               inst50000010\n// CHECK:STDOUT:   value_stores:\n// CHECK:STDOUT:     shared_values:\n// CHECK:STDOUT:       ints:            {}\n// CHECK:STDOUT:       reals:           {}\n// CHECK:STDOUT:       floats:          {}\n// CHECK:STDOUT:       identifiers:\n// CHECK:STDOUT:         identifier0:     A\n// CHECK:STDOUT:       strings:         {}\n// CHECK:STDOUT: ...\n// CHECK:STDOUT: ---\n// CHECK:STDOUT: filename:        b.carbon\n// CHECK:STDOUT: sem_ir:\n// CHECK:STDOUT:   names:\n// CHECK:STDOUT:     name0:           B\n// CHECK:STDOUT:     name1:           A\n// CHECK:STDOUT:   import_irs:\n// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     import_ir70000002: {decl_id: inst70000010, is_export: false}\n// CHECK:STDOUT:   import_ir_insts:\n// CHECK:STDOUT:     import_ir_inst0: {ir_id: import_ir70000002, inst_id: inst50000010}\n// CHECK:STDOUT:     import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000010}\n// CHECK:STDOUT:   clang_decls:     {}\n// CHECK:STDOUT:   name_scopes:\n// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name1: inst70000011, name0: inst70000012}}\n// CHECK:STDOUT:     name_scope70000001: {inst: inst70000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000017}}\n// CHECK:STDOUT:   entity_names:\n// CHECK:STDOUT:     entity_name70000000: {name: name1, parent_scope: name_scope70000001, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:   cpp_global_vars: {}\n// CHECK:STDOUT:   functions:\n// CHECK:STDOUT:     function70000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block_empty, call_params_id: inst_block_empty, body: [inst_block70000006]}\n// CHECK:STDOUT:     function70000001: {name: name1, parent_scope: name_scope70000001, call_param_patterns_id: inst_block_empty}\n// CHECK:STDOUT:   classes:         {}\n// CHECK:STDOUT:   interfaces:      {}\n// CHECK:STDOUT:   associated_constants: {}\n// CHECK:STDOUT:   impls:           {}\n// CHECK:STDOUT:   generics:        {}\n// CHECK:STDOUT:   specifics:       {}\n// CHECK:STDOUT:   specific_interfaces: {}\n// CHECK:STDOUT:   struct_type_fields:\n// CHECK:STDOUT:     struct_type_fields_empty: {}\n// CHECK:STDOUT:   types:\n// CHECK:STDOUT:     'type(TypeType)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}\n// CHECK:STDOUT:     'type(inst(FormType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}\n// CHECK:STDOUT:     'type(Error)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}\n// CHECK:STDOUT:     'type(inst(NamespaceType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     'type(inst70000013)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst70000014)}\n// CHECK:STDOUT:     'type(inst70000014)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst70000014)}\n// CHECK:STDOUT:     'type(inst(InstType))':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst70000014)}\n// CHECK:STDOUT:   facet_types:     {}\n// CHECK:STDOUT:   insts:\n// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst70000010:    {kind: ImportDecl, arg0: name1}\n// CHECK:STDOUT:     inst70000011:    {kind: Namespace, arg0: name_scope70000001, arg1: inst70000010, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst70000012:    {kind: FunctionDecl, arg0: function70000000, arg1: inst_block_empty, type: type(inst70000013)}\n// CHECK:STDOUT:     inst70000013:    {kind: FunctionType, arg0: function70000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst70000014:    {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)}\n// CHECK:STDOUT:     inst70000015:    {kind: StructValue, arg0: inst_block_empty, type: type(inst70000013)}\n// CHECK:STDOUT:     inst70000016:    {kind: NameRef, arg0: name1, arg1: inst70000011, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst70000017:    {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: entity_name70000000, type: type(inst70000019)}\n// CHECK:STDOUT:     inst70000018:    {kind: FunctionDecl, arg0: function70000001, arg1: inst_block_empty, type: type(inst70000019)}\n// CHECK:STDOUT:     inst70000019:    {kind: FunctionType, arg0: function70000001, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst7000001A:    {kind: StructValue, arg0: inst_block_empty, type: type(inst70000019)}\n// CHECK:STDOUT:     inst7000001B:    {kind: NameRef, arg0: name1, arg1: inst70000017, type: type(inst70000019)}\n// CHECK:STDOUT:     inst7000001C:    {kind: Call, arg0: inst7000001B, arg1: inst_block_empty, type: type(inst70000014)}\n// CHECK:STDOUT:     inst7000001D:    {kind: Return}\n// CHECK:STDOUT:   constant_values:\n// CHECK:STDOUT:     values:\n// CHECK:STDOUT:       instF:           concrete_constant(instF)\n// CHECK:STDOUT:       inst70000011:    concrete_constant(inst70000011)\n// CHECK:STDOUT:       inst70000012:    concrete_constant(inst70000015)\n// CHECK:STDOUT:       inst70000013:    concrete_constant(inst70000013)\n// CHECK:STDOUT:       inst70000014:    concrete_constant(inst70000014)\n// CHECK:STDOUT:       inst70000015:    concrete_constant(inst70000015)\n// CHECK:STDOUT:       inst70000016:    concrete_constant(inst70000011)\n// CHECK:STDOUT:       inst70000017:    concrete_constant(inst7000001A)\n// CHECK:STDOUT:       inst70000018:    concrete_constant(inst7000001A)\n// CHECK:STDOUT:       inst70000019:    concrete_constant(inst70000019)\n// CHECK:STDOUT:       inst7000001A:    concrete_constant(inst7000001A)\n// CHECK:STDOUT:       inst7000001B:    concrete_constant(inst7000001A)\n// CHECK:STDOUT:     symbolic_constants: {}\n// CHECK:STDOUT:   inst_blocks:\n// CHECK:STDOUT:     inst_block_empty: {}\n// CHECK:STDOUT:     exports:\n// CHECK:STDOUT:       0:               inst70000012\n// CHECK:STDOUT:     generated:       {}\n// CHECK:STDOUT:     imports:\n// CHECK:STDOUT:       0:               inst70000011\n// CHECK:STDOUT:       1:               inst70000017\n// CHECK:STDOUT:       2:               inst70000018\n// CHECK:STDOUT:     global_init:     {}\n// CHECK:STDOUT:     inst_block70000005: {}\n// CHECK:STDOUT:     inst_block70000006:\n// CHECK:STDOUT:       0:               inst70000016\n// CHECK:STDOUT:       1:               inst7000001B\n// CHECK:STDOUT:       2:               inst7000001C\n// CHECK:STDOUT:       3:               inst7000001D\n// CHECK:STDOUT:     inst_block70000007:\n// CHECK:STDOUT:       0:               instF\n// CHECK:STDOUT:       1:               inst70000010\n// CHECK:STDOUT:       2:               inst70000012\n// CHECK:STDOUT:   value_stores:\n// CHECK:STDOUT:     shared_values:\n// CHECK:STDOUT:       ints:            {}\n// CHECK:STDOUT:       reals:           {}\n// CHECK:STDOUT:       floats:          {}\n// CHECK:STDOUT:       identifiers:\n// CHECK:STDOUT:         identifier0:     B\n// CHECK:STDOUT:         identifier1:     A\n// CHECK:STDOUT:       strings:         {}\n// CHECK:STDOUT: ...\n"
  },
  {
    "path": "toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-raw-sem-ir --dump-sem-ir-ranges=if-present\n//\n// Check that we can combine textual IR and raw IR dumping in one compile.\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/raw_sem_ir/multifile_with_textual_ir.carbon\n\n// --- a.carbon\npackage A;\n\nfn A() {}\n\n// --- b.carbon\npackage B;\n\nimport A;\n\nfn B() {\n  A.A();\n}\n\n// CHECK:STDOUT: ---\n// CHECK:STDOUT: filename:        a.carbon\n// CHECK:STDOUT: sem_ir:\n// CHECK:STDOUT:   names:\n// CHECK:STDOUT:     name0:           A\n// CHECK:STDOUT:   import_irs:\n// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:   import_ir_insts: {}\n// CHECK:STDOUT:   clang_decls:     {}\n// CHECK:STDOUT:   name_scopes:\n// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst50000010}}\n// CHECK:STDOUT:   entity_names:    {}\n// CHECK:STDOUT:   cpp_global_vars: {}\n// CHECK:STDOUT:   functions:\n// CHECK:STDOUT:     function50000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block_empty, call_params_id: inst_block_empty, body: [inst_block50000006]}\n// CHECK:STDOUT:   classes:         {}\n// CHECK:STDOUT:   interfaces:      {}\n// CHECK:STDOUT:   associated_constants: {}\n// CHECK:STDOUT:   impls:           {}\n// CHECK:STDOUT:   generics:        {}\n// CHECK:STDOUT:   specifics:       {}\n// CHECK:STDOUT:   specific_interfaces: {}\n// CHECK:STDOUT:   struct_type_fields:\n// CHECK:STDOUT:     struct_type_fields_empty: {}\n// CHECK:STDOUT:   types:\n// CHECK:STDOUT:     'type(TypeType)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}\n// CHECK:STDOUT:     'type(inst(FormType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}\n// CHECK:STDOUT:     'type(Error)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}\n// CHECK:STDOUT:     'type(inst(NamespaceType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     'type(inst50000011)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000012)}\n// CHECK:STDOUT:     'type(inst50000012)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000012)}\n// CHECK:STDOUT:   facet_types:     {}\n// CHECK:STDOUT:   insts:\n// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst50000010:    {kind: FunctionDecl, arg0: function50000000, arg1: inst_block_empty, type: type(inst50000011)}\n// CHECK:STDOUT:     inst50000011:    {kind: FunctionType, arg0: function50000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000012:    {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000013:    {kind: StructValue, arg0: inst_block_empty, type: type(inst50000011)}\n// CHECK:STDOUT:     inst50000014:    {kind: Return}\n// CHECK:STDOUT:   constant_values:\n// CHECK:STDOUT:     values:\n// CHECK:STDOUT:       instF:           concrete_constant(instF)\n// CHECK:STDOUT:       inst50000010:    concrete_constant(inst50000013)\n// CHECK:STDOUT:       inst50000011:    concrete_constant(inst50000011)\n// CHECK:STDOUT:       inst50000012:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000013:    concrete_constant(inst50000013)\n// CHECK:STDOUT:     symbolic_constants: {}\n// CHECK:STDOUT:   inst_blocks:\n// CHECK:STDOUT:     inst_block_empty: {}\n// CHECK:STDOUT:     exports:\n// CHECK:STDOUT:       0:               inst50000010\n// CHECK:STDOUT:     generated:       {}\n// CHECK:STDOUT:     imports:         {}\n// CHECK:STDOUT:     global_init:     {}\n// CHECK:STDOUT:     inst_block50000005: {}\n// CHECK:STDOUT:     inst_block50000006:\n// CHECK:STDOUT:       0:               inst50000014\n// CHECK:STDOUT:     inst_block50000007:\n// CHECK:STDOUT:       0:               instF\n// CHECK:STDOUT:       1:               inst50000010\n// CHECK:STDOUT:   value_stores:\n// CHECK:STDOUT:     shared_values:\n// CHECK:STDOUT:       ints:            {}\n// CHECK:STDOUT:       reals:           {}\n// CHECK:STDOUT:       floats:          {}\n// CHECK:STDOUT:       identifiers:\n// CHECK:STDOUT:         identifier0:     A\n// CHECK:STDOUT:       strings:         {}\n// CHECK:STDOUT: ...\n// CHECK:STDOUT: --- a.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: ---\n// CHECK:STDOUT: filename:        b.carbon\n// CHECK:STDOUT: sem_ir:\n// CHECK:STDOUT:   names:\n// CHECK:STDOUT:     name0:           B\n// CHECK:STDOUT:     name1:           A\n// CHECK:STDOUT:   import_irs:\n// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     import_ir70000002: {decl_id: inst70000010, is_export: false}\n// CHECK:STDOUT:   import_ir_insts:\n// CHECK:STDOUT:     import_ir_inst0: {ir_id: import_ir70000002, inst_id: inst50000010}\n// CHECK:STDOUT:     import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000010}\n// CHECK:STDOUT:   clang_decls:     {}\n// CHECK:STDOUT:   name_scopes:\n// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name1: inst70000011, name0: inst70000012}}\n// CHECK:STDOUT:     name_scope70000001: {inst: inst70000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000017}}\n// CHECK:STDOUT:   entity_names:\n// CHECK:STDOUT:     entity_name70000000: {name: name1, parent_scope: name_scope70000001, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:   cpp_global_vars: {}\n// CHECK:STDOUT:   functions:\n// CHECK:STDOUT:     function70000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block_empty, call_params_id: inst_block_empty, body: [inst_block70000006]}\n// CHECK:STDOUT:     function70000001: {name: name1, parent_scope: name_scope70000001, call_param_patterns_id: inst_block_empty}\n// CHECK:STDOUT:   classes:         {}\n// CHECK:STDOUT:   interfaces:      {}\n// CHECK:STDOUT:   associated_constants: {}\n// CHECK:STDOUT:   impls:           {}\n// CHECK:STDOUT:   generics:        {}\n// CHECK:STDOUT:   specifics:       {}\n// CHECK:STDOUT:   specific_interfaces: {}\n// CHECK:STDOUT:   struct_type_fields:\n// CHECK:STDOUT:     struct_type_fields_empty: {}\n// CHECK:STDOUT:   types:\n// CHECK:STDOUT:     'type(TypeType)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}\n// CHECK:STDOUT:     'type(inst(FormType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}\n// CHECK:STDOUT:     'type(Error)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}\n// CHECK:STDOUT:     'type(inst(NamespaceType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     'type(inst70000013)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst70000014)}\n// CHECK:STDOUT:     'type(inst70000014)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst70000014)}\n// CHECK:STDOUT:     'type(inst(InstType))':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst70000014)}\n// CHECK:STDOUT:   facet_types:     {}\n// CHECK:STDOUT:   insts:\n// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst70000010:    {kind: ImportDecl, arg0: name1}\n// CHECK:STDOUT:     inst70000011:    {kind: Namespace, arg0: name_scope70000001, arg1: inst70000010, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst70000012:    {kind: FunctionDecl, arg0: function70000000, arg1: inst_block_empty, type: type(inst70000013)}\n// CHECK:STDOUT:     inst70000013:    {kind: FunctionType, arg0: function70000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst70000014:    {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)}\n// CHECK:STDOUT:     inst70000015:    {kind: StructValue, arg0: inst_block_empty, type: type(inst70000013)}\n// CHECK:STDOUT:     inst70000016:    {kind: NameRef, arg0: name1, arg1: inst70000011, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst70000017:    {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: entity_name70000000, type: type(inst70000019)}\n// CHECK:STDOUT:     inst70000018:    {kind: FunctionDecl, arg0: function70000001, arg1: inst_block_empty, type: type(inst70000019)}\n// CHECK:STDOUT:     inst70000019:    {kind: FunctionType, arg0: function70000001, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst7000001A:    {kind: StructValue, arg0: inst_block_empty, type: type(inst70000019)}\n// CHECK:STDOUT:     inst7000001B:    {kind: NameRef, arg0: name1, arg1: inst70000017, type: type(inst70000019)}\n// CHECK:STDOUT:     inst7000001C:    {kind: Call, arg0: inst7000001B, arg1: inst_block_empty, type: type(inst70000014)}\n// CHECK:STDOUT:     inst7000001D:    {kind: Return}\n// CHECK:STDOUT:   constant_values:\n// CHECK:STDOUT:     values:\n// CHECK:STDOUT:       instF:           concrete_constant(instF)\n// CHECK:STDOUT:       inst70000011:    concrete_constant(inst70000011)\n// CHECK:STDOUT:       inst70000012:    concrete_constant(inst70000015)\n// CHECK:STDOUT:       inst70000013:    concrete_constant(inst70000013)\n// CHECK:STDOUT:       inst70000014:    concrete_constant(inst70000014)\n// CHECK:STDOUT:       inst70000015:    concrete_constant(inst70000015)\n// CHECK:STDOUT:       inst70000016:    concrete_constant(inst70000011)\n// CHECK:STDOUT:       inst70000017:    concrete_constant(inst7000001A)\n// CHECK:STDOUT:       inst70000018:    concrete_constant(inst7000001A)\n// CHECK:STDOUT:       inst70000019:    concrete_constant(inst70000019)\n// CHECK:STDOUT:       inst7000001A:    concrete_constant(inst7000001A)\n// CHECK:STDOUT:       inst7000001B:    concrete_constant(inst7000001A)\n// CHECK:STDOUT:     symbolic_constants: {}\n// CHECK:STDOUT:   inst_blocks:\n// CHECK:STDOUT:     inst_block_empty: {}\n// CHECK:STDOUT:     exports:\n// CHECK:STDOUT:       0:               inst70000012\n// CHECK:STDOUT:     generated:       {}\n// CHECK:STDOUT:     imports:\n// CHECK:STDOUT:       0:               inst70000011\n// CHECK:STDOUT:       1:               inst70000017\n// CHECK:STDOUT:       2:               inst70000018\n// CHECK:STDOUT:     global_init:     {}\n// CHECK:STDOUT:     inst_block70000005: {}\n// CHECK:STDOUT:     inst_block70000006:\n// CHECK:STDOUT:       0:               inst70000016\n// CHECK:STDOUT:       1:               inst7000001B\n// CHECK:STDOUT:       2:               inst7000001C\n// CHECK:STDOUT:       3:               inst7000001D\n// CHECK:STDOUT:     inst_block70000007:\n// CHECK:STDOUT:       0:               instF\n// CHECK:STDOUT:       1:               inst70000010\n// CHECK:STDOUT:       2:               inst70000012\n// CHECK:STDOUT:   value_stores:\n// CHECK:STDOUT:     shared_values:\n// CHECK:STDOUT:       ints:            {}\n// CHECK:STDOUT:       reals:           {}\n// CHECK:STDOUT:       floats:          {}\n// CHECK:STDOUT:       identifiers:\n// CHECK:STDOUT:         identifier0:     B\n// CHECK:STDOUT:         identifier1:     A\n// CHECK:STDOUT:       strings:         {}\n// CHECK:STDOUT: ...\n// CHECK:STDOUT: --- b.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %A: <namespace> = namespace file.%A.import, [concrete] {\n// CHECK:STDOUT:     .A = %A.A\n// CHECK:STDOUT:     import A//default\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.A: %A.type = import_ref A//default, A, loaded [concrete = constants.%A]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%A\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.import = import A\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref.loc6_3: <namespace> = name_ref A, imports.%A [concrete = imports.%A]\n// CHECK:STDOUT:   %A.ref.loc6_4: %A.type = name_ref A, imports.%A.A [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.ref.loc6_4()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A [from \"a.carbon\"];\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// EXTRA-ARGS: --dump-raw-sem-ir --no-dump-sem-ir\n//\n// Check that raw IR dumping works as expected.\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/raw_sem_ir/one_file.carbon\n\nfn Foo[T:! type](p: T*) -> (T*, ()) {\n  return (p, ());\n}\n\n// CHECK:STDOUT: ---\n// CHECK:STDOUT: filename:        one_file.carbon\n// CHECK:STDOUT: sem_ir:\n// CHECK:STDOUT:   names:\n// CHECK:STDOUT:     name0:           Foo\n// CHECK:STDOUT:     name1:           T\n// CHECK:STDOUT:     name2:           p\n// CHECK:STDOUT:     name3:           Copy\n// CHECK:STDOUT:     name4:           Op\n// CHECK:STDOUT:     name5:           U\n// CHECK:STDOUT:     name6:           V\n// CHECK:STDOUT:   import_irs:\n// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     import_ir78000002: {decl_id: inst78000010, is_export: false}\n// CHECK:STDOUT:     import_ir78000003: {decl_id: inst78000010, is_export: false}\n// CHECK:STDOUT:     import_ir78000004: {decl_id: inst78000010, is_export: false}\n// CHECK:STDOUT:     import_ir78000005: {decl_id: inst78000010, is_export: false}\n// CHECK:STDOUT:     import_ir78000006: {decl_id: inst78000010, is_export: false}\n// CHECK:STDOUT:     import_ir78000007: {decl_id: inst78000010, is_export: false}\n// CHECK:STDOUT:   import_ir_insts:\n// CHECK:STDOUT:     import_ir_inst0: {ir_id: import_ir78000004, inst_id: inst70000010}\n// CHECK:STDOUT:     import_ir_inst1: {ir_id: import_ir78000004, inst_id: inst70000010}\n// CHECK:STDOUT:     import_ir_inst2: {ir_id: import_ir78000004, inst_id: inst70000015}\n// CHECK:STDOUT:     import_ir_inst3: {ir_id: import_ir78000004, inst_id: inst70000035}\n// CHECK:STDOUT:     import_ir_inst4: {ir_id: import_ir78000004, inst_id: inst7000002D}\n// CHECK:STDOUT:     import_ir_inst5: {ir_id: import_ir78000004, inst_id: inst70000012}\n// CHECK:STDOUT:     import_ir_inst6: {ir_id: import_ir78000004, inst_id: inst7000002D}\n// CHECK:STDOUT:     import_ir_inst7: {ir_id: import_ir78000004, inst_id: inst70000027}\n// CHECK:STDOUT:     import_ir_inst8: {ir_id: import_ir78000004, inst_id: inst70000028}\n// CHECK:STDOUT:     import_ir_inst9: {ir_id: import_ir78000004, inst_id: inst7000001E}\n// CHECK:STDOUT:     import_ir_instA: {ir_id: import_ir78000004, inst_id: inst70000020}\n// CHECK:STDOUT:     import_ir_instB: {ir_id: import_ir78000004, inst_id: inst70000023}\n// CHECK:STDOUT:     import_ir_instC: {ir_id: import_ir78000004, inst_id: inst70000024}\n// CHECK:STDOUT:     import_ir_instD: {ir_id: import_ir78000004, inst_id: inst70000012}\n// CHECK:STDOUT:     import_ir_instE: {ir_id: import_ir78000004, inst_id: inst70000017}\n// CHECK:STDOUT:     import_ir_instF: {ir_id: import_ir78000004, inst_id: inst7000001A}\n// CHECK:STDOUT:     import_ir_inst10: {ir_id: import_ir78000004, inst_id: inst7000001F}\n// CHECK:STDOUT:     import_ir_inst11: {ir_id: import_ir78000004, inst_id: inst70000026}\n// CHECK:STDOUT:     import_ir_inst12: {ir_id: import_ir78000004, inst_id: inst70000031}\n// CHECK:STDOUT:     import_ir_inst13: {ir_id: import_ir78000004, inst_id: inst70000032}\n// CHECK:STDOUT:     import_ir_inst14: {ir_id: import_ir78000004, inst_id: inst70000033}\n// CHECK:STDOUT:     import_ir_inst15: {ir_id: import_ir78000004, inst_id: inst70000012}\n// CHECK:STDOUT:     import_ir_inst16: {ir_id: import_ir78000004, inst_id: inst7000002D}\n// CHECK:STDOUT:     import_ir_inst17: {ir_id: import_ir78000004, inst_id: inst70000072}\n// CHECK:STDOUT:     import_ir_inst18: {ir_id: import_ir78000004, inst_id: inst70000070}\n// CHECK:STDOUT:     import_ir_inst19: {ir_id: import_ir78000004, inst_id: inst70000089}\n// CHECK:STDOUT:     import_ir_inst1A: {ir_id: import_ir78000004, inst_id: inst70000071}\n// CHECK:STDOUT:     import_ir_inst1B: {ir_id: import_ir78000004, inst_id: inst70000089}\n// CHECK:STDOUT:     import_ir_inst1C: {ir_id: import_ir78000004, inst_id: inst70000084}\n// CHECK:STDOUT:     import_ir_inst1D: {ir_id: import_ir78000004, inst_id: inst70000085}\n// CHECK:STDOUT:     import_ir_inst1E: {ir_id: import_ir78000004, inst_id: inst7000007D}\n// CHECK:STDOUT:     import_ir_inst1F: {ir_id: import_ir78000004, inst_id: inst7000007F}\n// CHECK:STDOUT:     import_ir_inst20: {ir_id: import_ir78000004, inst_id: inst70000080}\n// CHECK:STDOUT:     import_ir_inst21: {ir_id: import_ir78000004, inst_id: inst70000081}\n// CHECK:STDOUT:     import_ir_inst22: {ir_id: import_ir78000004, inst_id: inst70000062}\n// CHECK:STDOUT:     import_ir_inst23: {ir_id: import_ir78000004, inst_id: inst70000078}\n// CHECK:STDOUT:     import_ir_inst24: {ir_id: import_ir78000004, inst_id: inst70000079}\n// CHECK:STDOUT:     import_ir_inst25: {ir_id: import_ir78000004, inst_id: inst7000007A}\n// CHECK:STDOUT:     import_ir_inst26: {ir_id: import_ir78000004, inst_id: inst7000007E}\n// CHECK:STDOUT:     import_ir_inst27: {ir_id: import_ir78000004, inst_id: inst70000083}\n// CHECK:STDOUT:     import_ir_inst28: {ir_id: import_ir78000004, inst_id: inst70000093}\n// CHECK:STDOUT:     import_ir_inst29: {ir_id: import_ir78000004, inst_id: inst7000009A}\n// CHECK:STDOUT:     import_ir_inst2A: {ir_id: import_ir78000004, inst_id: inst700000A1}\n// CHECK:STDOUT:     import_ir_inst2B: {ir_id: import_ir78000004, inst_id: inst700000A7}\n// CHECK:STDOUT:     import_ir_inst2C: {ir_id: import_ir78000004, inst_id: inst700000A8}\n// CHECK:STDOUT:     import_ir_inst2D: {ir_id: import_ir78000004, inst_id: inst700000A9}\n// CHECK:STDOUT:     import_ir_inst2E: {ir_id: import_ir78000004, inst_id: inst700000AF}\n// CHECK:STDOUT:     import_ir_inst2F: {ir_id: import_ir78000004, inst_id: inst70000065}\n// CHECK:STDOUT:     import_ir_inst30: {ir_id: import_ir78000004, inst_id: inst7000006B}\n// CHECK:STDOUT:     import_ir_inst31: {ir_id: import_ir78000004, inst_id: inst7000006E}\n// CHECK:STDOUT:     import_ir_inst32: {ir_id: import_ir78000004, inst_id: inst70000062}\n// CHECK:STDOUT:     import_ir_inst33: {ir_id: import_ir78000004, inst_id: inst70000064}\n// CHECK:STDOUT:     import_ir_inst34: {ir_id: import_ir78000004, inst_id: inst70000069}\n// CHECK:STDOUT:     import_ir_inst35: {ir_id: import_ir78000004, inst_id: inst7000006D}\n// CHECK:STDOUT:     import_ir_inst36: {ir_id: import_ir78000004, inst_id: inst70000074}\n// CHECK:STDOUT:     import_ir_inst37: {ir_id: import_ir78000004, inst_id: inst7000008C}\n// CHECK:STDOUT:     import_ir_inst38: {ir_id: import_ir78000004, inst_id: inst7000008D}\n// CHECK:STDOUT:     import_ir_inst39: {ir_id: import_ir78000004, inst_id: inst700000C2}\n// CHECK:STDOUT:     import_ir_inst3A: {ir_id: import_ir78000004, inst_id: inst700000C0}\n// CHECK:STDOUT:     import_ir_inst3B: {ir_id: import_ir78000004, inst_id: inst700000BE}\n// CHECK:STDOUT:     import_ir_inst3C: {ir_id: import_ir78000004, inst_id: inst700000BF}\n// CHECK:STDOUT:     import_ir_inst3D: {ir_id: import_ir78000004, inst_id: inst700000DE}\n// CHECK:STDOUT:     import_ir_inst3E: {ir_id: import_ir78000004, inst_id: inst700000DC}\n// CHECK:STDOUT:     import_ir_inst3F: {ir_id: import_ir78000004, inst_id: inst700000DA}\n// CHECK:STDOUT:     import_ir_inst40: {ir_id: import_ir78000004, inst_id: inst700000DB}\n// CHECK:STDOUT:     import_ir_inst41: {ir_id: import_ir78000004, inst_id: inst700000FA}\n// CHECK:STDOUT:     import_ir_inst42: {ir_id: import_ir78000004, inst_id: inst700000F8}\n// CHECK:STDOUT:     import_ir_inst43: {ir_id: import_ir78000004, inst_id: inst700000F6}\n// CHECK:STDOUT:     import_ir_inst44: {ir_id: import_ir78000004, inst_id: inst700000F7}\n// CHECK:STDOUT:     import_ir_inst45: {ir_id: import_ir78000004, inst_id: inst70000116}\n// CHECK:STDOUT:     import_ir_inst46: {ir_id: import_ir78000004, inst_id: inst70000114}\n// CHECK:STDOUT:     import_ir_inst47: {ir_id: import_ir78000004, inst_id: inst70000112}\n// CHECK:STDOUT:     import_ir_inst48: {ir_id: import_ir78000004, inst_id: inst70000113}\n// CHECK:STDOUT:     import_ir_inst49: {ir_id: import_ir78000004, inst_id: inst70000139}\n// CHECK:STDOUT:     import_ir_inst4A: {ir_id: import_ir78000004, inst_id: inst70000137}\n// CHECK:STDOUT:     import_ir_inst4B: {ir_id: import_ir78000004, inst_id: inst7000014D}\n// CHECK:STDOUT:     import_ir_inst4C: {ir_id: import_ir78000004, inst_id: inst70000138}\n// CHECK:STDOUT:     import_ir_inst4D: {ir_id: import_ir78000004, inst_id: inst70000130}\n// CHECK:STDOUT:     import_ir_inst4E: {ir_id: import_ir78000004, inst_id: inst70000132}\n// CHECK:STDOUT:     import_ir_inst4F: {ir_id: import_ir78000004, inst_id: inst70000135}\n// CHECK:STDOUT:     import_ir_inst50: {ir_id: import_ir78000004, inst_id: inst7000012D}\n// CHECK:STDOUT:     import_ir_inst51: {ir_id: import_ir78000004, inst_id: inst7000012F}\n// CHECK:STDOUT:     import_ir_inst52: {ir_id: import_ir78000004, inst_id: inst70000134}\n// CHECK:STDOUT:     import_ir_inst53: {ir_id: import_ir78000004, inst_id: inst7000013B}\n// CHECK:STDOUT:     import_ir_inst54: {ir_id: import_ir78000004, inst_id: inst7000014D}\n// CHECK:STDOUT:     import_ir_inst55: {ir_id: import_ir78000004, inst_id: inst70000148}\n// CHECK:STDOUT:     import_ir_inst56: {ir_id: import_ir78000004, inst_id: inst70000149}\n// CHECK:STDOUT:     import_ir_inst57: {ir_id: import_ir78000004, inst_id: inst70000141}\n// CHECK:STDOUT:     import_ir_inst58: {ir_id: import_ir78000004, inst_id: inst70000143}\n// CHECK:STDOUT:     import_ir_inst59: {ir_id: import_ir78000004, inst_id: inst70000144}\n// CHECK:STDOUT:     import_ir_inst5A: {ir_id: import_ir78000004, inst_id: inst70000145}\n// CHECK:STDOUT:     import_ir_inst5B: {ir_id: import_ir78000004, inst_id: inst7000012D}\n// CHECK:STDOUT:     import_ir_inst5C: {ir_id: import_ir78000004, inst_id: inst7000013D}\n// CHECK:STDOUT:     import_ir_inst5D: {ir_id: import_ir78000004, inst_id: inst7000013E}\n// CHECK:STDOUT:     import_ir_inst5E: {ir_id: import_ir78000004, inst_id: inst70000142}\n// CHECK:STDOUT:     import_ir_inst5F: {ir_id: import_ir78000004, inst_id: inst70000147}\n// CHECK:STDOUT:     import_ir_inst60: {ir_id: import_ir78000004, inst_id: inst70000150}\n// CHECK:STDOUT:     import_ir_inst61: {ir_id: import_ir78000004, inst_id: inst70000151}\n// CHECK:STDOUT:     import_ir_inst62: {ir_id: import_ir78000004, inst_id: inst70000154}\n// CHECK:STDOUT:     import_ir_inst63: {ir_id: import_ir78000004, inst_id: inst7000015C}\n// CHECK:STDOUT:     import_ir_inst64: {ir_id: import_ir78000004, inst_id: inst7000015A}\n// CHECK:STDOUT:     import_ir_inst65: {ir_id: import_ir78000004, inst_id: inst70000158}\n// CHECK:STDOUT:     import_ir_inst66: {ir_id: import_ir78000004, inst_id: inst70000159}\n// CHECK:STDOUT:     import_ir_inst67: {ir_id: import_ir78000004, inst_id: inst70000175}\n// CHECK:STDOUT:     import_ir_inst68: {ir_id: import_ir78000004, inst_id: inst70000173}\n// CHECK:STDOUT:     import_ir_inst69: {ir_id: import_ir78000004, inst_id: inst70000171}\n// CHECK:STDOUT:     import_ir_inst6A: {ir_id: import_ir78000004, inst_id: inst70000172}\n// CHECK:STDOUT:     import_ir_inst6B: {ir_id: import_ir78000004, inst_id: inst700001AB}\n// CHECK:STDOUT:     import_ir_inst6C: {ir_id: import_ir78000004, inst_id: inst700001A9}\n// CHECK:STDOUT:     import_ir_inst6D: {ir_id: import_ir78000004, inst_id: inst700001C6}\n// CHECK:STDOUT:     import_ir_inst6E: {ir_id: import_ir78000004, inst_id: inst700001AA}\n// CHECK:STDOUT:     import_ir_inst6F: {ir_id: import_ir78000004, inst_id: inst700001C6}\n// CHECK:STDOUT:     import_ir_inst70: {ir_id: import_ir78000004, inst_id: inst700001C1}\n// CHECK:STDOUT:     import_ir_inst71: {ir_id: import_ir78000004, inst_id: inst700001C2}\n// CHECK:STDOUT:     import_ir_inst72: {ir_id: import_ir78000004, inst_id: inst700001BA}\n// CHECK:STDOUT:     import_ir_inst73: {ir_id: import_ir78000004, inst_id: inst700001BC}\n// CHECK:STDOUT:     import_ir_inst74: {ir_id: import_ir78000004, inst_id: inst700001BD}\n// CHECK:STDOUT:     import_ir_inst75: {ir_id: import_ir78000004, inst_id: inst700001BE}\n// CHECK:STDOUT:     import_ir_inst76: {ir_id: import_ir78000004, inst_id: inst7000018C}\n// CHECK:STDOUT:     import_ir_inst77: {ir_id: import_ir78000004, inst_id: inst70000191}\n// CHECK:STDOUT:     import_ir_inst78: {ir_id: import_ir78000004, inst_id: inst700001B3}\n// CHECK:STDOUT:     import_ir_inst79: {ir_id: import_ir78000004, inst_id: inst700001B4}\n// CHECK:STDOUT:     import_ir_inst7A: {ir_id: import_ir78000004, inst_id: inst700001B5}\n// CHECK:STDOUT:     import_ir_inst7B: {ir_id: import_ir78000004, inst_id: inst700001B6}\n// CHECK:STDOUT:     import_ir_inst7C: {ir_id: import_ir78000004, inst_id: inst700001B7}\n// CHECK:STDOUT:     import_ir_inst7D: {ir_id: import_ir78000004, inst_id: inst700001BB}\n// CHECK:STDOUT:     import_ir_inst7E: {ir_id: import_ir78000004, inst_id: inst700001C0}\n// CHECK:STDOUT:     import_ir_inst7F: {ir_id: import_ir78000004, inst_id: inst700001D1}\n// CHECK:STDOUT:     import_ir_inst80: {ir_id: import_ir78000004, inst_id: inst700001D7}\n// CHECK:STDOUT:     import_ir_inst81: {ir_id: import_ir78000004, inst_id: inst700001DA}\n// CHECK:STDOUT:     import_ir_inst82: {ir_id: import_ir78000004, inst_id: inst700001DC}\n// CHECK:STDOUT:     import_ir_inst83: {ir_id: import_ir78000004, inst_id: inst700001DD}\n// CHECK:STDOUT:     import_ir_inst84: {ir_id: import_ir78000004, inst_id: inst700001DE}\n// CHECK:STDOUT:     import_ir_inst85: {ir_id: import_ir78000004, inst_id: inst700001E1}\n// CHECK:STDOUT:     import_ir_inst86: {ir_id: import_ir78000004, inst_id: inst700001EB}\n// CHECK:STDOUT:     import_ir_inst87: {ir_id: import_ir78000004, inst_id: inst700001F1}\n// CHECK:STDOUT:     import_ir_inst88: {ir_id: import_ir78000004, inst_id: inst700001F5}\n// CHECK:STDOUT:     import_ir_inst89: {ir_id: import_ir78000004, inst_id: inst700001F6}\n// CHECK:STDOUT:     import_ir_inst8A: {ir_id: import_ir78000004, inst_id: inst700001F7}\n// CHECK:STDOUT:     import_ir_inst8B: {ir_id: import_ir78000004, inst_id: inst700001FD}\n// CHECK:STDOUT:     import_ir_inst8C: {ir_id: import_ir78000004, inst_id: inst70000194}\n// CHECK:STDOUT:     import_ir_inst8D: {ir_id: import_ir78000004, inst_id: inst7000018E}\n// CHECK:STDOUT:     import_ir_inst8E: {ir_id: import_ir78000004, inst_id: inst700001A4}\n// CHECK:STDOUT:     import_ir_inst8F: {ir_id: import_ir78000004, inst_id: inst700001A6}\n// CHECK:STDOUT:     import_ir_inst90: {ir_id: import_ir78000004, inst_id: inst7000018C}\n// CHECK:STDOUT:     import_ir_inst91: {ir_id: import_ir78000004, inst_id: inst70000191}\n// CHECK:STDOUT:     import_ir_inst92: {ir_id: import_ir78000004, inst_id: inst7000018D}\n// CHECK:STDOUT:     import_ir_inst93: {ir_id: import_ir78000004, inst_id: inst70000193}\n// CHECK:STDOUT:     import_ir_inst94: {ir_id: import_ir78000004, inst_id: inst7000019A}\n// CHECK:STDOUT:     import_ir_inst95: {ir_id: import_ir78000004, inst_id: inst7000019D}\n// CHECK:STDOUT:     import_ir_inst96: {ir_id: import_ir78000004, inst_id: inst700001A1}\n// CHECK:STDOUT:     import_ir_inst97: {ir_id: import_ir78000004, inst_id: inst700001A5}\n// CHECK:STDOUT:     import_ir_inst98: {ir_id: import_ir78000004, inst_id: inst700001AD}\n// CHECK:STDOUT:     import_ir_inst99: {ir_id: import_ir78000004, inst_id: inst700001C9}\n// CHECK:STDOUT:     import_ir_inst9A: {ir_id: import_ir78000004, inst_id: inst700001CA}\n// CHECK:STDOUT:     import_ir_inst9B: {ir_id: import_ir78000004, inst_id: inst70000237}\n// CHECK:STDOUT:     import_ir_inst9C: {ir_id: import_ir78000004, inst_id: inst70000235}\n// CHECK:STDOUT:     import_ir_inst9D: {ir_id: import_ir78000004, inst_id: inst70000256}\n// CHECK:STDOUT:     import_ir_inst9E: {ir_id: import_ir78000004, inst_id: inst70000236}\n// CHECK:STDOUT:     import_ir_inst9F: {ir_id: import_ir78000004, inst_id: inst70000256}\n// CHECK:STDOUT:     import_ir_instA0: {ir_id: import_ir78000004, inst_id: inst70000251}\n// CHECK:STDOUT:     import_ir_instA1: {ir_id: import_ir78000004, inst_id: inst70000252}\n// CHECK:STDOUT:     import_ir_instA2: {ir_id: import_ir78000004, inst_id: inst7000024A}\n// CHECK:STDOUT:     import_ir_instA3: {ir_id: import_ir78000004, inst_id: inst7000024C}\n// CHECK:STDOUT:     import_ir_instA4: {ir_id: import_ir78000004, inst_id: inst7000024D}\n// CHECK:STDOUT:     import_ir_instA5: {ir_id: import_ir78000004, inst_id: inst7000024E}\n// CHECK:STDOUT:     import_ir_instA6: {ir_id: import_ir78000004, inst_id: inst7000020E}\n// CHECK:STDOUT:     import_ir_instA7: {ir_id: import_ir78000004, inst_id: inst70000213}\n// CHECK:STDOUT:     import_ir_instA8: {ir_id: import_ir78000004, inst_id: inst70000218}\n// CHECK:STDOUT:     import_ir_instA9: {ir_id: import_ir78000004, inst_id: inst70000241}\n// CHECK:STDOUT:     import_ir_instAA: {ir_id: import_ir78000004, inst_id: inst70000242}\n// CHECK:STDOUT:     import_ir_instAB: {ir_id: import_ir78000004, inst_id: inst70000243}\n// CHECK:STDOUT:     import_ir_instAC: {ir_id: import_ir78000004, inst_id: inst70000244}\n// CHECK:STDOUT:     import_ir_instAD: {ir_id: import_ir78000004, inst_id: inst70000245}\n// CHECK:STDOUT:     import_ir_instAE: {ir_id: import_ir78000004, inst_id: inst70000246}\n// CHECK:STDOUT:     import_ir_instAF: {ir_id: import_ir78000004, inst_id: inst70000247}\n// CHECK:STDOUT:     import_ir_instB0: {ir_id: import_ir78000004, inst_id: inst7000024B}\n// CHECK:STDOUT:     import_ir_instB1: {ir_id: import_ir78000004, inst_id: inst70000250}\n// CHECK:STDOUT:     import_ir_instB2: {ir_id: import_ir78000004, inst_id: inst70000261}\n// CHECK:STDOUT:     import_ir_instB3: {ir_id: import_ir78000004, inst_id: inst70000266}\n// CHECK:STDOUT:     import_ir_instB4: {ir_id: import_ir78000004, inst_id: inst70000269}\n// CHECK:STDOUT:     import_ir_instB5: {ir_id: import_ir78000004, inst_id: inst7000026B}\n// CHECK:STDOUT:     import_ir_instB6: {ir_id: import_ir78000004, inst_id: inst7000026C}\n// CHECK:STDOUT:     import_ir_instB7: {ir_id: import_ir78000004, inst_id: inst7000026D}\n// CHECK:STDOUT:     import_ir_instB8: {ir_id: import_ir78000004, inst_id: inst70000270}\n// CHECK:STDOUT:     import_ir_instB9: {ir_id: import_ir78000004, inst_id: inst70000278}\n// CHECK:STDOUT:     import_ir_instBA: {ir_id: import_ir78000004, inst_id: inst7000027B}\n// CHECK:STDOUT:     import_ir_instBB: {ir_id: import_ir78000004, inst_id: inst7000027D}\n// CHECK:STDOUT:     import_ir_instBC: {ir_id: import_ir78000004, inst_id: inst7000027E}\n// CHECK:STDOUT:     import_ir_instBD: {ir_id: import_ir78000004, inst_id: inst7000027F}\n// CHECK:STDOUT:     import_ir_instBE: {ir_id: import_ir78000004, inst_id: inst70000282}\n// CHECK:STDOUT:     import_ir_instBF: {ir_id: import_ir78000004, inst_id: inst7000028C}\n// CHECK:STDOUT:     import_ir_instC0: {ir_id: import_ir78000004, inst_id: inst70000292}\n// CHECK:STDOUT:     import_ir_instC1: {ir_id: import_ir78000004, inst_id: inst70000296}\n// CHECK:STDOUT:     import_ir_instC2: {ir_id: import_ir78000004, inst_id: inst70000297}\n// CHECK:STDOUT:     import_ir_instC3: {ir_id: import_ir78000004, inst_id: inst70000298}\n// CHECK:STDOUT:     import_ir_instC4: {ir_id: import_ir78000004, inst_id: inst7000029E}\n// CHECK:STDOUT:     import_ir_instC5: {ir_id: import_ir78000004, inst_id: inst7000021B}\n// CHECK:STDOUT:     import_ir_instC6: {ir_id: import_ir78000004, inst_id: inst70000215}\n// CHECK:STDOUT:     import_ir_instC7: {ir_id: import_ir78000004, inst_id: inst70000210}\n// CHECK:STDOUT:     import_ir_instC8: {ir_id: import_ir78000004, inst_id: inst7000022F}\n// CHECK:STDOUT:     import_ir_instC9: {ir_id: import_ir78000004, inst_id: inst70000231}\n// CHECK:STDOUT:     import_ir_instCA: {ir_id: import_ir78000004, inst_id: inst7000020E}\n// CHECK:STDOUT:     import_ir_instCB: {ir_id: import_ir78000004, inst_id: inst70000213}\n// CHECK:STDOUT:     import_ir_instCC: {ir_id: import_ir78000004, inst_id: inst70000218}\n// CHECK:STDOUT:     import_ir_instCD: {ir_id: import_ir78000004, inst_id: inst7000020F}\n// CHECK:STDOUT:     import_ir_instCE: {ir_id: import_ir78000004, inst_id: inst70000214}\n// CHECK:STDOUT:     import_ir_instCF: {ir_id: import_ir78000004, inst_id: inst7000021A}\n// CHECK:STDOUT:     import_ir_instD0: {ir_id: import_ir78000004, inst_id: inst70000222}\n// CHECK:STDOUT:     import_ir_instD1: {ir_id: import_ir78000004, inst_id: inst70000225}\n// CHECK:STDOUT:     import_ir_instD2: {ir_id: import_ir78000004, inst_id: inst70000228}\n// CHECK:STDOUT:     import_ir_instD3: {ir_id: import_ir78000004, inst_id: inst7000022C}\n// CHECK:STDOUT:     import_ir_instD4: {ir_id: import_ir78000004, inst_id: inst70000230}\n// CHECK:STDOUT:     import_ir_instD5: {ir_id: import_ir78000004, inst_id: inst70000239}\n// CHECK:STDOUT:     import_ir_instD6: {ir_id: import_ir78000004, inst_id: inst70000259}\n// CHECK:STDOUT:     import_ir_instD7: {ir_id: import_ir78000004, inst_id: inst7000025A}\n// CHECK:STDOUT:   clang_decls:     {}\n// CHECK:STDOUT:   name_scopes:\n// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name(Core): inst78000011, name0: inst7800003E}}\n// CHECK:STDOUT:     name_scope78000001: {inst: inst78000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name3: inst7800004E}}\n// CHECK:STDOUT:     name_scope78000002: {inst: inst7800004F, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {name(SelfType): inst7800006A}}\n// CHECK:STDOUT:     name_scope78000003: {inst: inst78000051, parent_scope: name_scope78000002, has_error: false, extended_scopes: [], names: {name4: inst78000053}}\n// CHECK:STDOUT:     name_scope78000004: {inst: inst78000070, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:     name_scope78000005: {inst: inst780000A5, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:     name_scope78000006: {inst: inst780000A9, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:     name_scope78000007: {inst: inst780000AD, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:     name_scope78000008: {inst: inst780000B1, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:     name_scope78000009: {inst: inst780000B5, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:     name_scope7800000A: {inst: inst780000D3, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:     name_scope7800000B: {inst: inst780000D7, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:     name_scope7800000C: {inst: inst780000DB, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:     name_scope7800000D: {inst: inst7800011F, parent_scope: name_scope78000001, has_error: false, extended_scopes: [], names: {}}\n// CHECK:STDOUT:   entity_names:\n// CHECK:STDOUT:     entity_name78000000: {name: name(PeriodSelf), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000001: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000002: {name: name2, parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000003: {name: name3, parent_scope: name_scope78000001, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000004: {name: name(SelfType), parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000005: {name: name4, parent_scope: name_scope78000003, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000006: {name: name(SelfType), parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000007: {name: name(SelfType), parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000008: {name: name(SelfValue), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000009: {name: name(SelfType), parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800000A: {name: name(SelfType), parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800000B: {name: name(SelfType), parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800000C: {name: name(SelfType), parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800000D: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800000E: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800000F: {name: name(SelfValue), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000010: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000011: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000012: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000013: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000014: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000015: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000016: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000017: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000018: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000019: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800001A: {name: name(SelfValue), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800001B: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800001C: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800001D: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800001E: {name: name(SelfValue), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800001F: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000020: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000021: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000022: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000023: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000024: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000025: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000026: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000027: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000028: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000029: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800002A: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800002B: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800002C: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800002D: {name: name(SelfValue), parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800002E: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800002F: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000030: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000031: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000032: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000033: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000034: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000035: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000036: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000037: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000038: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name78000039: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800003A: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800003B: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800003C: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800003D: {name: name6, parent_scope: name_scope<none>, index: 2, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800003E: {name: name5, parent_scope: name_scope<none>, index: 1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:     entity_name7800003F: {name: name1, parent_scope: name_scope<none>, index: 0, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:   cpp_global_vars: {}\n// CHECK:STDOUT:   functions:\n// CHECK:STDOUT:     function78000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block78000011, call_params_id: inst_block78000012, return_type_inst_id: inst78000030, return_form_inst_id: inst78000032, return_patterns_id: inst_block78000010, body: [inst_block78000019]}\n// CHECK:STDOUT:     function78000001: {name: name4, parent_scope: name_scope78000003, call_param_patterns_id: inst_block7800001F, return_type_inst_id: inst78000060, return_form_inst_id: inst78000061, return_patterns_id: inst_block78000021}\n// CHECK:STDOUT:     function78000002: {name: name4, parent_scope: name_scope78000004, call_param_patterns_id: inst_block7800002B, return_type_inst_id: inst78000080, return_form_inst_id: inst78000081, return_patterns_id: inst_block7800002D}\n// CHECK:STDOUT:     function78000003: {name: name4, parent_scope: name_scope78000009, call_param_patterns_id: inst_block78000042, return_type_inst_id: inst780000C8, return_form_inst_id: inst780000C9, return_patterns_id: inst_block78000044}\n// CHECK:STDOUT:     function78000004: {name: name4, parent_scope: name_scope7800000C, call_param_patterns_id: inst_block78000050, return_type_inst_id: inst780000ED, return_form_inst_id: inst780000EE, return_patterns_id: inst_block78000052}\n// CHECK:STDOUT:     function78000005: {name: name4, parent_scope: name_scope7800000D, call_param_patterns_id: inst_block7800006D, return_type_inst_id: inst78000131, return_form_inst_id: inst78000132, return_patterns_id: inst_block7800006F}\n// CHECK:STDOUT:   classes:         {}\n// CHECK:STDOUT:   interfaces:\n// CHECK:STDOUT:     interface78000000: {name: name3, parent_scope: name_scope78000001, require_impls_block_id: require_block_empty}\n// CHECK:STDOUT:   associated_constants: {}\n// CHECK:STDOUT:   impls:\n// CHECK:STDOUT:     impl78000000:    {self: inst7800009B, constraint: inst7800009C, witness: inst7800006F}\n// CHECK:STDOUT:     impl78000001:    {self: inst780000A6, constraint: inst780000A7, witness: inst780000A4}\n// CHECK:STDOUT:     impl78000002:    {self: inst780000AA, constraint: inst780000AB, witness: inst780000A8}\n// CHECK:STDOUT:     impl78000003:    {self: inst780000AE, constraint: inst780000AF, witness: inst780000AC}\n// CHECK:STDOUT:     impl78000004:    {self: inst780000B2, constraint: inst780000B3, witness: inst780000B0}\n// CHECK:STDOUT:     impl78000005:    {self: inst780000BA, constraint: inst780000BB, witness: inst780000B4}\n// CHECK:STDOUT:     impl78000006:    {self: inst780000D4, constraint: inst780000D5, witness: inst780000D2}\n// CHECK:STDOUT:     impl78000007:    {self: inst780000D8, constraint: inst780000D9, witness: inst780000D6}\n// CHECK:STDOUT:     impl78000008:    {self: inst78000111, constraint: inst78000112, witness: inst780000DA}\n// CHECK:STDOUT:     impl78000009:    {self: inst7800015F, constraint: inst78000160, witness: inst7800011E}\n// CHECK:STDOUT:   generics:\n// CHECK:STDOUT:     generic78000000: {decl: inst7800003E, bindings: inst_block78000015, self_specific_id: specific78000000, decl_block_id: inst_block78000017, definition_block_id: inst_block78000091}\n// CHECK:STDOUT:     generic78000001: {decl: inst78000051, bindings: inst_block7800001C, self_specific_id: specific78000001, decl_block_id: inst_block_empty, definition_block_id: inst_block78000026}\n// CHECK:STDOUT:     generic78000002: {decl: inst78000056, bindings: inst_block78000022, self_specific_id: specific78000002, decl_block_id: inst_block78000023, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     generic78000003: {decl: inst78000070, bindings: inst_block78000037, self_specific_id: specific78000004, decl_block_id: inst_block78000039, definition_block_id: inst_block7800003B}\n// CHECK:STDOUT:     generic78000004: {decl: inst78000077, bindings: inst_block7800002E, self_specific_id: specific78000007, decl_block_id: inst_block7800002F, definition_block_id: inst_block78000034}\n// CHECK:STDOUT:     generic78000005: {decl: inst780000B5, bindings: inst_block7800003F, self_specific_id: specific7800000B, decl_block_id: inst_block78000041, definition_block_id: inst_block78000049}\n// CHECK:STDOUT:     generic78000006: {decl: inst780000C0, bindings: inst_block78000045, self_specific_id: specific7800000D, decl_block_id: inst_block78000046, definition_block_id: inst_block_empty}\n// CHECK:STDOUT:     generic78000007: {decl: inst780000DB, bindings: inst_block78000060, self_specific_id: specific7800000E, decl_block_id: inst_block78000064, definition_block_id: inst_block78000066}\n// CHECK:STDOUT:     generic78000008: {decl: inst780000E2, bindings: inst_block78000053, self_specific_id: specific78000011, decl_block_id: inst_block78000055, definition_block_id: inst_block7800005D}\n// CHECK:STDOUT:     generic78000009: {decl: inst7800011F, bindings: inst_block7800007F, self_specific_id: specific78000017, decl_block_id: inst_block78000083, definition_block_id: inst_block78000085}\n// CHECK:STDOUT:     generic7800000A: {decl: inst78000126, bindings: inst_block78000070, self_specific_id: specific7800001A, decl_block_id: inst_block78000072, definition_block_id: inst_block7800007C}\n// CHECK:STDOUT:   specifics:\n// CHECK:STDOUT:     specific78000000: {generic: generic78000000, args: inst_block78000016, decl_block_id: inst_block78000018, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000001: {generic: generic78000001, args: inst_block7800001D, decl_block_id: inst_block_empty, definition_block_id: inst_block7800001E}\n// CHECK:STDOUT:     specific78000002: {generic: generic78000002, args: inst_block7800001D, decl_block_id: inst_block78000024, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000003: {generic: generic78000001, args: inst_block78000025, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000004: {generic: generic78000003, args: inst_block78000028, decl_block_id: inst_block78000029, definition_block_id: inst_block7800002A}\n// CHECK:STDOUT:     specific78000005: {generic: generic78000001, args: inst_block78000028, decl_block_id: inst_block_empty, definition_block_id: inst_block78000030}\n// CHECK:STDOUT:     specific78000006: {generic: generic78000002, args: inst_block78000028, decl_block_id: inst_block78000031, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000007: {generic: generic78000004, args: inst_block78000028, decl_block_id: inst_block78000035, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000008: {generic: generic78000001, args: inst_block78000032, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000009: {generic: generic78000002, args: inst_block78000032, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800000A: {generic: generic78000003, args: inst_block78000038, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800000B: {generic: generic78000005, args: inst_block78000016, decl_block_id: inst_block7800003D, definition_block_id: inst_block78000086}\n// CHECK:STDOUT:     specific7800000C: {generic: generic78000005, args: inst_block78000040, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800000D: {generic: generic78000006, args: inst_block78000016, decl_block_id: inst_block78000047, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800000E: {generic: generic78000007, args: inst_block7800004C, decl_block_id: inst_block7800004E, definition_block_id: inst_block7800004F}\n// CHECK:STDOUT:     specific7800000F: {generic: generic78000001, args: inst_block78000056, decl_block_id: inst_block_empty, definition_block_id: inst_block78000057}\n// CHECK:STDOUT:     specific78000010: {generic: generic78000002, args: inst_block78000056, decl_block_id: inst_block78000058, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000011: {generic: generic78000008, args: inst_block7800004C, decl_block_id: inst_block7800005E, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000012: {generic: generic78000001, args: inst_block78000059, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000013: {generic: generic78000002, args: inst_block78000059, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000014: {generic: generic78000001, args: inst_block7800005B, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000015: {generic: generic78000002, args: inst_block7800005B, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000016: {generic: generic78000007, args: inst_block78000061, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000017: {generic: generic78000009, args: inst_block78000069, decl_block_id: inst_block7800006B, definition_block_id: inst_block7800006C}\n// CHECK:STDOUT:     specific78000018: {generic: generic78000001, args: inst_block78000073, decl_block_id: inst_block_empty, definition_block_id: inst_block78000074}\n// CHECK:STDOUT:     specific78000019: {generic: generic78000002, args: inst_block78000073, decl_block_id: inst_block78000075, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800001A: {generic: generic7800000A, args: inst_block78000069, decl_block_id: inst_block7800007D, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800001B: {generic: generic78000001, args: inst_block78000076, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800001C: {generic: generic78000002, args: inst_block78000076, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800001D: {generic: generic78000001, args: inst_block78000078, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800001E: {generic: generic78000002, args: inst_block78000078, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific7800001F: {generic: generic78000001, args: inst_block7800007A, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000020: {generic: generic78000002, args: inst_block7800007A, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000021: {generic: generic78000009, args: inst_block78000080, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000022: {generic: generic78000005, args: inst_block78000087, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000023: {generic: generic78000001, args: inst_block78000089, decl_block_id: inst_block_empty, definition_block_id: inst_block7800008A}\n// CHECK:STDOUT:     specific78000024: {generic: generic78000001, args: inst_block7800008C, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000025: {generic: generic78000002, args: inst_block78000089, decl_block_id: inst_block7800008D, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:     specific78000026: {generic: generic78000002, args: inst_block7800008C, decl_block_id: inst_block<none>, definition_block_id: inst_block<none>}\n// CHECK:STDOUT:   specific_interfaces:\n// CHECK:STDOUT:     specific_interface78000000: {interface_id: interface78000000, specific_id: specific<none>}\n// CHECK:STDOUT:   struct_type_fields:\n// CHECK:STDOUT:     struct_type_fields_empty: {}\n// CHECK:STDOUT:   types:\n// CHECK:STDOUT:     'type(TypeType)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}\n// CHECK:STDOUT:     'type(inst(FormType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}\n// CHECK:STDOUT:     'type(Error)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}\n// CHECK:STDOUT:     'type(inst(NamespaceType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     'type(inst78000026)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst78000026)}\n// CHECK:STDOUT:     'type(inst7800002D)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst7800002D)}\n// CHECK:STDOUT:     'type(inst78000029)':\n// CHECK:STDOUT:       value_repr:      {kind: pointer, type: type(inst7800002D)}\n// CHECK:STDOUT:     'type(inst7800003F)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst78000026)}\n// CHECK:STDOUT:     'type(symbolic_constant78000003)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(symbolic_constant78000003)}\n// CHECK:STDOUT:     'type(inst(WitnessType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     'type(symbolic_constant78000011)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(symbolic_constant78000011)}\n// CHECK:STDOUT:     'type(symbolic_constant78000009)':\n// CHECK:STDOUT:       value_repr:      {kind: pointer, type: type(symbolic_constant78000011)}\n// CHECK:STDOUT:     'type(symbolic_constant78000004)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(symbolic_constant78000004)}\n// CHECK:STDOUT:     'type(symbolic_constant7800000A)':\n// CHECK:STDOUT:       value_repr:      {kind: pointer, type: type(symbolic_constant78000011)}\n// CHECK:STDOUT:     'type(inst(InstType))':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst78000026)}\n// CHECK:STDOUT:     'type(inst78000050)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst78000050)}\n// CHECK:STDOUT:     'type(inst(SpecificFunctionType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     'type(inst(RequireSpecificDefinitionType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(RequireSpecificDefinitionType))}\n// CHECK:STDOUT:     'type(symbolic_constant78000146)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst78000026)}\n// CHECK:STDOUT:     'type(symbolic_constant7800014A)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst78000026)}\n// CHECK:STDOUT:     'type(inst(BoundMethodType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(BoundMethodType))}\n// CHECK:STDOUT:   facet_types:\n// CHECK:STDOUT:     facet_type78000000: {}\n// CHECK:STDOUT:     facet_type78000001: {extends interface: interface78000000}\n// CHECK:STDOUT:   insts:\n// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst78000010:    {kind: ImportDecl, arg0: name(Core)}\n// CHECK:STDOUT:     inst78000011:    {kind: Namespace, arg0: name_scope78000001, arg1: inst78000010, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst78000012:    {kind: FacetType, arg0: facet_type78000000, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000013:    {kind: SymbolicBinding, arg0: entity_name78000000, arg1: inst<none>, type: type(inst78000012)}\n// CHECK:STDOUT:     inst78000014:    {kind: SymbolicBinding, arg0: entity_name78000000, arg1: inst<none>, type: type(inst78000012)}\n// CHECK:STDOUT:     inst78000015:    {kind: TypeLiteral, arg0: inst(TypeType), type: type(TypeType)}\n// CHECK:STDOUT:     inst78000016:    {kind: PatternType, arg0: inst(TypeType), type: type(TypeType)}\n// CHECK:STDOUT:     inst78000017:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000018:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000019:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800001A:    {kind: SymbolicBindingPattern, arg0: entity_name78000001, type: type(inst78000016)}\n// CHECK:STDOUT:     inst7800001B:    {kind: NameRef, arg0: name1, arg1: inst78000017, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800001C:    {kind: PointerType, arg0: inst7800001B, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800001D:    {kind: PointerType, arg0: inst78000018, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800001E:    {kind: PointerType, arg0: inst78000019, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800001F:    {kind: PatternType, arg0: inst7800001D, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000020:    {kind: ValueBinding, arg0: entity_name78000002, arg1: inst7800003A, type: type(symbolic_constant78000004)}\n// CHECK:STDOUT:     inst78000021:    {kind: ValueBindingPattern, arg0: entity_name78000002, type: type(symbolic_constant78000006)}\n// CHECK:STDOUT:     inst78000022:    {kind: PatternType, arg0: inst7800001E, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000023:    {kind: ValueParamPattern, arg0: inst78000021, type: type(symbolic_constant78000006)}\n// CHECK:STDOUT:     inst78000024:    {kind: NameRef, arg0: name1, arg1: inst78000017, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000025:    {kind: PointerType, arg0: inst78000024, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000026:    {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000027:    {kind: TupleLiteral, arg0: inst_block_empty, type: type(inst78000026)}\n// CHECK:STDOUT:     inst78000028:    {kind: TupleValue, arg0: inst_block_empty, type: type(inst78000026)}\n// CHECK:STDOUT:     inst78000029:    {kind: TupleType, arg0: inst_block7800000A, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800002A:    {kind: TupleLiteral, arg0: inst_block78000009, type: type(inst78000029)}\n// CHECK:STDOUT:     inst7800002B:    {kind: TupleValue, arg0: inst_block7800000B, type: type(inst78000029)}\n// CHECK:STDOUT:     inst7800002C:    {kind: TupleValue, arg0: inst_block7800000C, type: type(inst78000029)}\n// CHECK:STDOUT:     inst7800002D:    {kind: PointerType, arg0: inst78000029, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800002E:    {kind: Converted, arg0: inst78000028, arg1: inst78000026, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800002F:    {kind: TupleType, arg0: inst_block7800000E, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000030:    {kind: Converted, arg0: inst7800002A, arg1: inst7800002F, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000031:    {kind: TupleType, arg0: inst_block7800000F, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000032:    {kind: InitForm, arg0: inst78000030, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000033:    {kind: InitForm, arg0: inst7800002F, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000034:    {kind: InitForm, arg0: inst78000031, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000035:    {kind: PatternType, arg0: inst7800002F, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000036:    {kind: ReturnSlotPattern, arg0: inst78000030, type: type(symbolic_constant7800000E)}\n// CHECK:STDOUT:     inst78000037:    {kind: PatternType, arg0: inst78000031, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000038:    {kind: OutParamPattern, arg0: inst78000036, type: type(symbolic_constant7800000E)}\n// CHECK:STDOUT:     inst78000039:    {kind: SpliceBlock, arg0: inst_block78000005, arg1: inst78000015, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800003A:    {kind: ValueParam, arg0: call_param0, arg1: name2, type: type(symbolic_constant78000004)}\n// CHECK:STDOUT:     inst7800003B:    {kind: SpliceBlock, arg0: inst_block78000007, arg1: inst7800001C, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800003C:    {kind: OutParam, arg0: call_param1, arg1: name(ReturnSlot), type: type(symbolic_constant7800000A)}\n// CHECK:STDOUT:     inst7800003D:    {kind: ReturnSlot, arg0: inst7800002F, arg1: inst7800003C, type: type(symbolic_constant7800000A)}\n// CHECK:STDOUT:     inst7800003E:    {kind: FunctionDecl, arg0: function78000000, arg1: inst_block78000014, type: type(inst7800003F)}\n// CHECK:STDOUT:     inst7800003F:    {kind: FunctionType, arg0: function78000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000040:    {kind: StructValue, arg0: inst_block_empty, type: type(inst7800003F)}\n// CHECK:STDOUT:     inst78000041:    {kind: RequireCompleteType, arg0: inst7800001D, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000042:    {kind: RequireCompleteType, arg0: inst7800001D, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000043:    {kind: RequireCompleteType, arg0: inst7800001E, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000044:    {kind: PointerType, arg0: inst7800002F, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000045:    {kind: RequireCompleteType, arg0: inst7800002F, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000046:    {kind: RequireCompleteType, arg0: inst7800002F, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000047:    {kind: RequireCompleteType, arg0: inst78000031, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000048:    {kind: NameRef, arg0: name2, arg1: inst78000020, type: type(symbolic_constant78000004)}\n// CHECK:STDOUT:     inst78000049:    {kind: TupleLiteral, arg0: inst_block_empty, type: type(inst78000026)}\n// CHECK:STDOUT:     inst7800004A:    {kind: TupleLiteral, arg0: inst_block7800001A, type: type(symbolic_constant7800000A)}\n// CHECK:STDOUT:     inst7800004B:    {kind: RequireCompleteType, arg0: inst7800002F, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800004C:    {kind: TupleAccess, arg0: inst7800003C, arg1: element0, type: type(symbolic_constant78000004)}\n// CHECK:STDOUT:     inst7800004D:    {kind: RequireCompleteType, arg0: inst7800001D, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800004E:    {kind: ImportRefLoaded, arg0: import_ir_inst0, arg1: entity_name78000003, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800004F:    {kind: InterfaceDecl, arg0: interface78000000, arg1: inst_block_empty, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000050:    {kind: FacetType, arg0: facet_type78000001, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000051:    {kind: InterfaceWithSelfDecl, arg0: interface78000000}\n// CHECK:STDOUT:     inst78000052:    {kind: SymbolicBinding, arg0: entity_name78000004, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000053:    {kind: ImportRefLoaded, arg0: import_ir_inst3, arg1: entity_name<none>, type: type(inst7800006B)}\n// CHECK:STDOUT:     inst78000054:    {kind: ImportRefUnloaded, arg0: import_ir_inst4, arg1: entity_name78000005}\n// CHECK:STDOUT:     inst78000055:    {kind: ImportRefLoaded, arg0: import_ir_inst5, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000056:    {kind: FunctionDecl, arg0: function78000001, arg1: inst_block_empty, type: type(symbolic_constant78000015)}\n// CHECK:STDOUT:     inst78000057:    {kind: FunctionType, arg0: function78000001, arg1: specific78000001, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000058:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000015)}\n// CHECK:STDOUT:     inst78000059:    {kind: SymbolicBindingType, arg0: entity_name78000004, arg1: inst78000052, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800005A:    {kind: PatternType, arg0: inst78000059, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800005B:    {kind: ReturnSlotPattern, arg0: inst<none>, type: type(symbolic_constant7800001B)}\n// CHECK:STDOUT:     inst7800005C:    {kind: OutParamPattern, arg0: inst7800005B, type: type(symbolic_constant7800001B)}\n// CHECK:STDOUT:     inst7800005D:    {kind: ValueBindingPattern, arg0: entity_name78000008, type: type(symbolic_constant7800001B)}\n// CHECK:STDOUT:     inst7800005E:    {kind: ValueParamPattern, arg0: inst7800005D, type: type(symbolic_constant7800001B)}\n// CHECK:STDOUT:     inst7800005F:    {kind: InitForm, arg0: inst78000059, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000060:    {kind: ImportRefLoaded, arg0: import_ir_instB, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000061:    {kind: ImportRefLoaded, arg0: import_ir_instC, arg1: entity_name<none>, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000062:    {kind: ImportRefLoaded, arg0: import_ir_instD, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000063:    {kind: SymbolicBinding, arg0: entity_name78000004, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000064:    {kind: SymbolicBindingType, arg0: entity_name78000004, arg1: inst78000063, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000065:    {kind: PatternType, arg0: inst78000064, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000066:    {kind: InitForm, arg0: inst78000064, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000067:    {kind: SymbolicBinding, arg0: entity_name78000004, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000068:    {kind: FunctionType, arg0: function78000001, arg1: specific78000003, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000069:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000029)}\n// CHECK:STDOUT:     inst7800006A:    {kind: ImportRefUnloaded, arg0: import_ir_inst15, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst7800006B:    {kind: AssociatedEntityType, arg0: interface78000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800006C:    {kind: ImportRefLoaded, arg0: import_ir_inst16, arg1: entity_name<none>, type: type(symbolic_constant78000019)}\n// CHECK:STDOUT:     inst7800006D:    {kind: AssociatedEntity, arg0: element0, arg1: inst7800006C, type: type(inst7800006B)}\n// CHECK:STDOUT:     inst7800006E:    {kind: LookupImplWitness, arg0: inst7800001D, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800006F:    {kind: ImportRefUnloaded, arg0: import_ir_inst17, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst78000070:    {kind: ImplDecl, arg0: impl78000000, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst78000071:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000072:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst78000071, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000073:    {kind: ConstType, arg0: inst78000072, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000074:    {kind: ImportRefUnloaded, arg0: import_ir_inst19, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst78000075:    {kind: ImplWitnessTable, arg0: inst_block78000027, arg1: impl78000000}\n// CHECK:STDOUT:     inst78000076:    {kind: ImplWitness, arg0: inst78000075, arg1: specific78000004, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000077:    {kind: FunctionDecl, arg0: function78000002, arg1: inst_block_empty, type: type(symbolic_constant78000031)}\n// CHECK:STDOUT:     inst78000078:    {kind: FunctionType, arg0: function78000002, arg1: specific78000004, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000079:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000031)}\n// CHECK:STDOUT:     inst7800007A:    {kind: PatternType, arg0: inst78000073, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800007B:    {kind: ReturnSlotPattern, arg0: inst<none>, type: type(symbolic_constant78000036)}\n// CHECK:STDOUT:     inst7800007C:    {kind: OutParamPattern, arg0: inst7800007B, type: type(symbolic_constant78000036)}\n// CHECK:STDOUT:     inst7800007D:    {kind: ValueBindingPattern, arg0: entity_name7800000F, type: type(symbolic_constant78000036)}\n// CHECK:STDOUT:     inst7800007E:    {kind: ValueParamPattern, arg0: inst7800007D, type: type(symbolic_constant78000036)}\n// CHECK:STDOUT:     inst7800007F:    {kind: InitForm, arg0: inst78000073, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000080:    {kind: ImportRefLoaded, arg0: import_ir_inst20, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000081:    {kind: ImportRefLoaded, arg0: import_ir_inst21, arg1: entity_name<none>, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000082:    {kind: ImportRefLoaded, arg0: import_ir_inst22, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000083:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000084:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst78000083, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000085:    {kind: ConstType, arg0: inst78000084, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000086:    {kind: PatternType, arg0: inst78000085, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000087:    {kind: InitForm, arg0: inst78000085, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000088:    {kind: LookupImplWitness, arg0: inst78000071, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000089:    {kind: FunctionType, arg0: function78000001, arg1: specific78000005, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800008A:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000045)}\n// CHECK:STDOUT:     inst7800008B:    {kind: FunctionTypeWithSelfType, arg0: inst78000089, arg1: inst78000071, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800008C:    {kind: ImplWitnessAccess, arg0: inst78000088, arg1: element0, type: type(symbolic_constant78000047)}\n// CHECK:STDOUT:     inst7800008D:    {kind: SpecificImplFunction, arg0: inst7800008C, arg1: specific78000006, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst7800008E:    {kind: InitForm, arg0: inst78000072, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst7800008F:    {kind: PatternType, arg0: inst78000072, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000090:    {kind: RequireCompleteType, arg0: inst78000072, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000091:    {kind: RequireCompleteType, arg0: inst78000073, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000092:    {kind: RequireCompleteType, arg0: inst78000085, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000093:    {kind: RequireCompleteType, arg0: inst78000084, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000094:    {kind: LookupImplWitness, arg0: inst78000083, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000095:    {kind: FunctionType, arg0: function78000001, arg1: specific78000008, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000096:    {kind: FunctionTypeWithSelfType, arg0: inst78000095, arg1: inst78000083, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000097:    {kind: ImplWitnessAccess, arg0: inst78000094, arg1: element0, type: type(symbolic_constant78000059)}\n// CHECK:STDOUT:     inst78000098:    {kind: SpecificImplFunction, arg0: inst78000097, arg1: specific78000009, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst78000099:    {kind: PatternType, arg0: inst78000050, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800009A:    {kind: SymbolicBindingPattern, arg0: entity_name78000015, type: type(inst78000099)}\n// CHECK:STDOUT:     inst7800009B:    {kind: ImportRefLoaded, arg0: import_ir_inst30, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800009C:    {kind: ImportRefLoaded, arg0: import_ir_inst31, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800009D:    {kind: ImportRefLoaded, arg0: import_ir_inst32, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst7800009E:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst7800009F:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst7800009E, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000A0:    {kind: ConstType, arg0: inst7800009F, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000A1:    {kind: ImplWitness, arg0: inst78000075, arg1: specific7800000A, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst780000A2:    {kind: FunctionType, arg0: function78000002, arg1: specific7800000A, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000A3:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000064)}\n// CHECK:STDOUT:     inst780000A4:    {kind: ImportRefUnloaded, arg0: import_ir_inst39, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst780000A5:    {kind: ImplDecl, arg0: impl78000001, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst780000A6:    {kind: ImportRefLoaded, arg0: import_ir_inst3B, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000A7:    {kind: ImportRefLoaded, arg0: import_ir_inst3C, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000A8:    {kind: ImportRefUnloaded, arg0: import_ir_inst3D, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst780000A9:    {kind: ImplDecl, arg0: impl78000002, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst780000AA:    {kind: ImportRefLoaded, arg0: import_ir_inst3F, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000AB:    {kind: ImportRefLoaded, arg0: import_ir_inst40, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000AC:    {kind: ImportRefUnloaded, arg0: import_ir_inst41, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst780000AD:    {kind: ImplDecl, arg0: impl78000003, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst780000AE:    {kind: ImportRefLoaded, arg0: import_ir_inst43, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000AF:    {kind: ImportRefLoaded, arg0: import_ir_inst44, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000B0:    {kind: ImportRefUnloaded, arg0: import_ir_inst45, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst780000B1:    {kind: ImplDecl, arg0: impl78000004, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst780000B2:    {kind: ImportRefLoaded, arg0: import_ir_inst47, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000B3:    {kind: ImportRefLoaded, arg0: import_ir_inst48, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000B4:    {kind: ImportRefLoaded, arg0: import_ir_inst49, arg1: entity_name<none>, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst780000B5:    {kind: ImplDecl, arg0: impl78000005, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst780000B6:    {kind: ImportRefUnloaded, arg0: import_ir_inst4B, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst780000B7:    {kind: ImplWitnessTable, arg0: inst_block7800003C, arg1: impl78000005}\n// CHECK:STDOUT:     inst780000B8:    {kind: ImplWitness, arg0: inst780000B7, arg1: specific7800000B, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst780000B9:    {kind: SymbolicBindingPattern, arg0: entity_name78000019, type: type(inst78000016)}\n// CHECK:STDOUT:     inst780000BA:    {kind: ImportRefLoaded, arg0: import_ir_inst4E, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000BB:    {kind: ImportRefLoaded, arg0: import_ir_inst4F, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000BC:    {kind: ImportRefLoaded, arg0: import_ir_inst50, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000BD:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000BE:    {kind: PointerType, arg0: inst780000BD, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000BF:    {kind: ImplWitness, arg0: inst780000B7, arg1: specific7800000C, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst780000C0:    {kind: FunctionDecl, arg0: function78000003, arg1: inst_block_empty, type: type(symbolic_constant78000070)}\n// CHECK:STDOUT:     inst780000C1:    {kind: FunctionType, arg0: function78000003, arg1: specific7800000B, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000C2:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000070)}\n// CHECK:STDOUT:     inst780000C3:    {kind: ReturnSlotPattern, arg0: inst<none>, type: type(symbolic_constant78000074)}\n// CHECK:STDOUT:     inst780000C4:    {kind: OutParamPattern, arg0: inst780000C3, type: type(symbolic_constant78000074)}\n// CHECK:STDOUT:     inst780000C5:    {kind: ValueBindingPattern, arg0: entity_name7800001A, type: type(symbolic_constant78000074)}\n// CHECK:STDOUT:     inst780000C6:    {kind: ValueParamPattern, arg0: inst780000C5, type: type(symbolic_constant78000074)}\n// CHECK:STDOUT:     inst780000C7:    {kind: InitForm, arg0: inst7800001D, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst780000C8:    {kind: ImportRefLoaded, arg0: import_ir_inst59, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000C9:    {kind: ImportRefLoaded, arg0: import_ir_inst5A, arg1: entity_name<none>, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst780000CA:    {kind: ImportRefLoaded, arg0: import_ir_inst5B, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000CB:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000CC:    {kind: PointerType, arg0: inst780000CB, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000CD:    {kind: PatternType, arg0: inst780000CC, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000CE:    {kind: InitForm, arg0: inst780000CC, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst780000CF:    {kind: FunctionType, arg0: function78000003, arg1: specific7800000C, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000D0:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000080)}\n// CHECK:STDOUT:     inst780000D1:    {kind: RequireCompleteType, arg0: inst780000BE, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst780000D2:    {kind: ImportRefUnloaded, arg0: import_ir_inst63, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst780000D3:    {kind: ImplDecl, arg0: impl78000006, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst780000D4:    {kind: ImportRefLoaded, arg0: import_ir_inst65, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000D5:    {kind: ImportRefLoaded, arg0: import_ir_inst66, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000D6:    {kind: ImportRefUnloaded, arg0: import_ir_inst67, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst780000D7:    {kind: ImplDecl, arg0: impl78000007, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst780000D8:    {kind: ImportRefLoaded, arg0: import_ir_inst69, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000D9:    {kind: ImportRefLoaded, arg0: import_ir_inst6A, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000DA:    {kind: ImportRefUnloaded, arg0: import_ir_inst6B, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst780000DB:    {kind: ImplDecl, arg0: impl78000008, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst780000DC:    {kind: SymbolicBinding, arg0: entity_name7800001C, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst780000DD:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst780000DC, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000DE:    {kind: TupleType, arg0: inst_block7800004A, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000DF:    {kind: ImportRefUnloaded, arg0: import_ir_inst6D, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst780000E0:    {kind: ImplWitnessTable, arg0: inst_block7800004B, arg1: impl78000008}\n// CHECK:STDOUT:     inst780000E1:    {kind: ImplWitness, arg0: inst780000E0, arg1: specific7800000E, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst780000E2:    {kind: FunctionDecl, arg0: function78000004, arg1: inst_block_empty, type: type(symbolic_constant78000089)}\n// CHECK:STDOUT:     inst780000E3:    {kind: FunctionType, arg0: function78000004, arg1: specific7800000E, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000E4:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000089)}\n// CHECK:STDOUT:     inst780000E5:    {kind: TupleType, arg0: inst_block7800004D, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000E6:    {kind: TupleValue, arg0: inst_block7800004C, type: type(inst780000E5)}\n// CHECK:STDOUT:     inst780000E7:    {kind: PatternType, arg0: inst780000DE, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000E8:    {kind: ReturnSlotPattern, arg0: inst<none>, type: type(symbolic_constant7800008F)}\n// CHECK:STDOUT:     inst780000E9:    {kind: OutParamPattern, arg0: inst780000E8, type: type(symbolic_constant7800008F)}\n// CHECK:STDOUT:     inst780000EA:    {kind: ValueBindingPattern, arg0: entity_name7800001E, type: type(symbolic_constant7800008F)}\n// CHECK:STDOUT:     inst780000EB:    {kind: ValueParamPattern, arg0: inst780000EA, type: type(symbolic_constant7800008F)}\n// CHECK:STDOUT:     inst780000EC:    {kind: InitForm, arg0: inst780000DE, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst780000ED:    {kind: ImportRefLoaded, arg0: import_ir_inst74, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000EE:    {kind: ImportRefLoaded, arg0: import_ir_inst75, arg1: entity_name<none>, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst780000EF:    {kind: ImportRefLoaded, arg0: import_ir_inst76, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst780000F0:    {kind: ImportRefLoaded, arg0: import_ir_inst77, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst780000F1:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst780000F2:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst780000F1, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000F3:    {kind: SymbolicBinding, arg0: entity_name7800001C, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst780000F4:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst780000F3, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000F5:    {kind: TupleType, arg0: inst_block78000054, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000F6:    {kind: PatternType, arg0: inst780000F5, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000F7:    {kind: InitForm, arg0: inst780000F5, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst780000F8:    {kind: LookupImplWitness, arg0: inst780000DC, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst780000F9:    {kind: FunctionType, arg0: function78000001, arg1: specific7800000F, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000FA:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant780000A3)}\n// CHECK:STDOUT:     inst780000FB:    {kind: FunctionTypeWithSelfType, arg0: inst780000F9, arg1: inst780000DC, type: type(TypeType)}\n// CHECK:STDOUT:     inst780000FC:    {kind: ImplWitnessAccess, arg0: inst780000F8, arg1: element0, type: type(symbolic_constant780000A5)}\n// CHECK:STDOUT:     inst780000FD:    {kind: SpecificImplFunction, arg0: inst780000FC, arg1: specific78000010, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst780000FE:    {kind: InitForm, arg0: inst780000DD, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst780000FF:    {kind: PatternType, arg0: inst780000DD, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000100:    {kind: RequireCompleteType, arg0: inst780000DD, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000101:    {kind: RequireCompleteType, arg0: inst780000DE, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000102:    {kind: RequireCompleteType, arg0: inst780000F5, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000103:    {kind: RequireCompleteType, arg0: inst780000F2, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000104:    {kind: LookupImplWitness, arg0: inst780000F1, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000105:    {kind: FunctionType, arg0: function78000001, arg1: specific78000012, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000106:    {kind: FunctionTypeWithSelfType, arg0: inst78000105, arg1: inst780000F1, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000107:    {kind: ImplWitnessAccess, arg0: inst78000104, arg1: element0, type: type(symbolic_constant780000BD)}\n// CHECK:STDOUT:     inst78000108:    {kind: SpecificImplFunction, arg0: inst78000107, arg1: specific78000013, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst78000109:    {kind: RequireCompleteType, arg0: inst780000F4, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800010A:    {kind: LookupImplWitness, arg0: inst780000F3, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800010B:    {kind: FunctionType, arg0: function78000001, arg1: specific78000014, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800010C:    {kind: FunctionTypeWithSelfType, arg0: inst7800010B, arg1: inst780000F3, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800010D:    {kind: ImplWitnessAccess, arg0: inst7800010A, arg1: element0, type: type(symbolic_constant780000C3)}\n// CHECK:STDOUT:     inst7800010E:    {kind: SpecificImplFunction, arg0: inst7800010D, arg1: specific78000015, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst7800010F:    {kind: SymbolicBindingPattern, arg0: entity_name78000029, type: type(inst78000099)}\n// CHECK:STDOUT:     inst78000110:    {kind: SymbolicBindingPattern, arg0: entity_name7800002A, type: type(inst78000099)}\n// CHECK:STDOUT:     inst78000111:    {kind: ImportRefLoaded, arg0: import_ir_inst8E, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000112:    {kind: ImportRefLoaded, arg0: import_ir_inst8F, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000113:    {kind: ImportRefLoaded, arg0: import_ir_inst90, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000114:    {kind: ImportRefLoaded, arg0: import_ir_inst91, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000115:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000116:    {kind: SymbolicBinding, arg0: entity_name7800001C, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000117:    {kind: TupleValue, arg0: inst_block78000061, type: type(inst780000E5)}\n// CHECK:STDOUT:     inst78000118:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst78000115, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000119:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst78000116, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800011A:    {kind: TupleType, arg0: inst_block78000062, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800011B:    {kind: ImplWitness, arg0: inst780000E0, arg1: specific78000016, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800011C:    {kind: FunctionType, arg0: function78000004, arg1: specific78000016, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800011D:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant780000D4)}\n// CHECK:STDOUT:     inst7800011E:    {kind: ImportRefUnloaded, arg0: import_ir_inst9B, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst7800011F:    {kind: ImplDecl, arg0: impl78000009, arg1: inst_block_empty}\n// CHECK:STDOUT:     inst78000120:    {kind: SymbolicBinding, arg0: entity_name7800002B, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000121:    {kind: SymbolicBindingType, arg0: entity_name7800002B, arg1: inst78000120, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000122:    {kind: TupleType, arg0: inst_block78000067, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000123:    {kind: ImportRefUnloaded, arg0: import_ir_inst9D, arg1: entity_name<none>}\n// CHECK:STDOUT:     inst78000124:    {kind: ImplWitnessTable, arg0: inst_block78000068, arg1: impl78000009}\n// CHECK:STDOUT:     inst78000125:    {kind: ImplWitness, arg0: inst78000124, arg1: specific78000017, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000126:    {kind: FunctionDecl, arg0: function78000005, arg1: inst_block_empty, type: type(symbolic_constant780000DC)}\n// CHECK:STDOUT:     inst78000127:    {kind: FunctionType, arg0: function78000005, arg1: specific78000017, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000128:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant780000DC)}\n// CHECK:STDOUT:     inst78000129:    {kind: TupleType, arg0: inst_block7800006A, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800012A:    {kind: TupleValue, arg0: inst_block78000069, type: type(inst78000129)}\n// CHECK:STDOUT:     inst7800012B:    {kind: PatternType, arg0: inst78000122, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800012C:    {kind: ReturnSlotPattern, arg0: inst<none>, type: type(symbolic_constant780000E2)}\n// CHECK:STDOUT:     inst7800012D:    {kind: OutParamPattern, arg0: inst7800012C, type: type(symbolic_constant780000E2)}\n// CHECK:STDOUT:     inst7800012E:    {kind: ValueBindingPattern, arg0: entity_name7800002D, type: type(symbolic_constant780000E2)}\n// CHECK:STDOUT:     inst7800012F:    {kind: ValueParamPattern, arg0: inst7800012E, type: type(symbolic_constant780000E2)}\n// CHECK:STDOUT:     inst78000130:    {kind: InitForm, arg0: inst78000122, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000131:    {kind: ImportRefLoaded, arg0: import_ir_instA4, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000132:    {kind: ImportRefLoaded, arg0: import_ir_instA5, arg1: entity_name<none>, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000133:    {kind: ImportRefLoaded, arg0: import_ir_instA6, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000134:    {kind: ImportRefLoaded, arg0: import_ir_instA7, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000135:    {kind: ImportRefLoaded, arg0: import_ir_instA8, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000136:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000137:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst78000136, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000138:    {kind: SymbolicBinding, arg0: entity_name7800001C, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000139:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst78000138, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800013A:    {kind: SymbolicBinding, arg0: entity_name7800002B, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst7800013B:    {kind: SymbolicBindingType, arg0: entity_name7800002B, arg1: inst7800013A, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800013C:    {kind: TupleType, arg0: inst_block78000071, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800013D:    {kind: PatternType, arg0: inst7800013C, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800013E:    {kind: InitForm, arg0: inst7800013C, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst7800013F:    {kind: LookupImplWitness, arg0: inst78000120, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000140:    {kind: FunctionType, arg0: function78000001, arg1: specific78000018, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000141:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant780000FB)}\n// CHECK:STDOUT:     inst78000142:    {kind: FunctionTypeWithSelfType, arg0: inst78000140, arg1: inst78000120, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000143:    {kind: ImplWitnessAccess, arg0: inst7800013F, arg1: element0, type: type(symbolic_constant780000FD)}\n// CHECK:STDOUT:     inst78000144:    {kind: SpecificImplFunction, arg0: inst78000143, arg1: specific78000019, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst78000145:    {kind: InitForm, arg0: inst78000121, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst78000146:    {kind: PatternType, arg0: inst78000121, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000147:    {kind: RequireCompleteType, arg0: inst78000121, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000148:    {kind: RequireCompleteType, arg0: inst78000122, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000149:    {kind: RequireCompleteType, arg0: inst7800013C, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800014A:    {kind: RequireCompleteType, arg0: inst78000137, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800014B:    {kind: LookupImplWitness, arg0: inst78000136, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800014C:    {kind: FunctionType, arg0: function78000001, arg1: specific7800001B, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800014D:    {kind: FunctionTypeWithSelfType, arg0: inst7800014C, arg1: inst78000136, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800014E:    {kind: ImplWitnessAccess, arg0: inst7800014B, arg1: element0, type: type(symbolic_constant7800011B)}\n// CHECK:STDOUT:     inst7800014F:    {kind: SpecificImplFunction, arg0: inst7800014E, arg1: specific7800001C, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst78000150:    {kind: RequireCompleteType, arg0: inst78000139, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000151:    {kind: LookupImplWitness, arg0: inst78000138, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000152:    {kind: FunctionType, arg0: function78000001, arg1: specific7800001D, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000153:    {kind: FunctionTypeWithSelfType, arg0: inst78000152, arg1: inst78000138, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000154:    {kind: ImplWitnessAccess, arg0: inst78000151, arg1: element0, type: type(symbolic_constant78000121)}\n// CHECK:STDOUT:     inst78000155:    {kind: SpecificImplFunction, arg0: inst78000154, arg1: specific7800001E, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst78000156:    {kind: RequireCompleteType, arg0: inst7800013B, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000157:    {kind: LookupImplWitness, arg0: inst7800013A, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000158:    {kind: FunctionType, arg0: function78000001, arg1: specific7800001F, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000159:    {kind: FunctionTypeWithSelfType, arg0: inst78000158, arg1: inst7800013A, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800015A:    {kind: ImplWitnessAccess, arg0: inst78000157, arg1: element0, type: type(symbolic_constant78000127)}\n// CHECK:STDOUT:     inst7800015B:    {kind: SpecificImplFunction, arg0: inst7800015A, arg1: specific78000020, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst7800015C:    {kind: SymbolicBindingPattern, arg0: entity_name7800003D, type: type(inst78000099)}\n// CHECK:STDOUT:     inst7800015D:    {kind: SymbolicBindingPattern, arg0: entity_name7800003E, type: type(inst78000099)}\n// CHECK:STDOUT:     inst7800015E:    {kind: SymbolicBindingPattern, arg0: entity_name7800003F, type: type(inst78000099)}\n// CHECK:STDOUT:     inst7800015F:    {kind: ImportRefLoaded, arg0: import_ir_instC8, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000160:    {kind: ImportRefLoaded, arg0: import_ir_instC9, arg1: entity_name<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000161:    {kind: ImportRefLoaded, arg0: import_ir_instCA, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000162:    {kind: ImportRefLoaded, arg0: import_ir_instCB, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000163:    {kind: ImportRefLoaded, arg0: import_ir_instCC, arg1: entity_name<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000164:    {kind: SymbolicBinding, arg0: entity_name78000001, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000165:    {kind: SymbolicBinding, arg0: entity_name7800001C, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000166:    {kind: SymbolicBinding, arg0: entity_name7800002B, arg1: inst<none>, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000167:    {kind: TupleValue, arg0: inst_block78000080, type: type(inst78000129)}\n// CHECK:STDOUT:     inst78000168:    {kind: SymbolicBindingType, arg0: entity_name78000001, arg1: inst78000164, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000169:    {kind: SymbolicBindingType, arg0: entity_name7800001C, arg1: inst78000165, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800016A:    {kind: SymbolicBindingType, arg0: entity_name7800002B, arg1: inst78000166, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800016B:    {kind: TupleType, arg0: inst_block78000081, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800016C:    {kind: ImplWitness, arg0: inst78000124, arg1: specific78000021, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst7800016D:    {kind: FunctionType, arg0: function78000005, arg1: specific78000021, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800016E:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant7800013C)}\n// CHECK:STDOUT:     inst7800016F:    {kind: RequireSpecificDefinition, arg0: specific7800000B, type: type(inst(RequireSpecificDefinitionType))}\n// CHECK:STDOUT:     inst78000170:    {kind: RequireSpecificDefinition, arg0: specific7800000B, type: type(inst(RequireSpecificDefinitionType))}\n// CHECK:STDOUT:     inst78000171:    {kind: RequireSpecificDefinition, arg0: specific78000022, type: type(inst(RequireSpecificDefinitionType))}\n// CHECK:STDOUT:     inst78000172:    {kind: LookupImplWitness, arg0: inst7800001D, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000173:    {kind: LookupImplWitness, arg0: inst7800001E, arg1: specific_interface78000000, type: type(inst(WitnessType))}\n// CHECK:STDOUT:     inst78000174:    {kind: FacetValue, arg0: inst7800001D, arg1: inst_block78000088, type: type(inst78000050)}\n// CHECK:STDOUT:     inst78000175:    {kind: FunctionType, arg0: function78000001, arg1: specific78000023, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000176:    {kind: StructValue, arg0: inst_block_empty, type: type(symbolic_constant78000144)}\n// CHECK:STDOUT:     inst78000177:    {kind: FunctionTypeWithSelfType, arg0: inst78000175, arg1: inst78000174, type: type(TypeType)}\n// CHECK:STDOUT:     inst78000178:    {kind: ImplWitnessAccess, arg0: inst78000172, arg1: element0, type: type(symbolic_constant7800014A)}\n// CHECK:STDOUT:     inst78000179:    {kind: ImplWitnessAccess, arg0: inst78000172, arg1: element0, type: type(symbolic_constant78000146)}\n// CHECK:STDOUT:     inst7800017A:    {kind: FacetValue, arg0: inst7800001E, arg1: inst_block7800008B, type: type(inst78000050)}\n// CHECK:STDOUT:     inst7800017B:    {kind: FunctionType, arg0: function78000001, arg1: specific78000024, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800017C:    {kind: FunctionTypeWithSelfType, arg0: inst7800017B, arg1: inst7800017A, type: type(TypeType)}\n// CHECK:STDOUT:     inst7800017D:    {kind: ImplWitnessAccess, arg0: inst78000173, arg1: element0, type: type(symbolic_constant7800014A)}\n// CHECK:STDOUT:     inst7800017E:    {kind: BoundMethod, arg0: inst78000048, arg1: inst78000178, type: type(inst(BoundMethodType))}\n// CHECK:STDOUT:     inst7800017F:    {kind: SpecificImplFunction, arg0: inst78000178, arg1: specific78000025, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst78000180:    {kind: SpecificImplFunction, arg0: inst78000179, arg1: specific78000025, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst78000181:    {kind: SpecificImplFunction, arg0: inst7800017D, arg1: specific78000026, type: type(inst(SpecificFunctionType))}\n// CHECK:STDOUT:     inst78000182:    {kind: BoundMethod, arg0: inst78000048, arg1: inst7800017F, type: type(inst(BoundMethodType))}\n// CHECK:STDOUT:     inst78000183:    {kind: Call, arg0: inst78000182, arg1: inst_block7800008F, type: type(symbolic_constant78000004)}\n// CHECK:STDOUT:     inst78000184:    {kind: InPlaceInit, arg0: inst78000183, arg1: inst7800004C, type: type(symbolic_constant78000004)}\n// CHECK:STDOUT:     inst78000185:    {kind: TupleAccess, arg0: inst7800003C, arg1: element1, type: type(inst78000026)}\n// CHECK:STDOUT:     inst78000186:    {kind: TupleInit, arg0: inst_block_empty, arg1: inst<none>, type: type(inst78000026)}\n// CHECK:STDOUT:     inst78000187:    {kind: Converted, arg0: inst78000049, arg1: inst78000186, type: type(inst78000026)}\n// CHECK:STDOUT:     inst78000188:    {kind: TupleInit, arg0: inst_block78000090, arg1: inst7800003C, type: type(symbolic_constant7800000A)}\n// CHECK:STDOUT:     inst78000189:    {kind: Converted, arg0: inst7800004A, arg1: inst78000188, type: type(symbolic_constant7800000A)}\n// CHECK:STDOUT:     inst7800018A:    {kind: ReturnExpr, arg0: inst78000189, arg1: inst7800003C}\n// CHECK:STDOUT:   constant_values:\n// CHECK:STDOUT:     values:\n// CHECK:STDOUT:       instF:           concrete_constant(instF)\n// CHECK:STDOUT:       inst78000011:    concrete_constant(inst78000011)\n// CHECK:STDOUT:       inst78000012:    concrete_constant(inst78000012)\n// CHECK:STDOUT:       inst78000013:    symbolic_constant78000000\n// CHECK:STDOUT:       inst78000014:    symbolic_constant78000000\n// CHECK:STDOUT:       inst78000015:    concrete_constant(inst(TypeType))\n// CHECK:STDOUT:       inst78000016:    concrete_constant(inst78000016)\n// CHECK:STDOUT:       inst78000017:    symbolic_constant78000002\n// CHECK:STDOUT:       inst78000018:    symbolic_constant78000001\n// CHECK:STDOUT:       inst78000019:    symbolic_constant78000002\n// CHECK:STDOUT:       inst7800001A:    concrete_constant(inst7800001A)\n// CHECK:STDOUT:       inst7800001B:    symbolic_constant78000002\n// CHECK:STDOUT:       inst7800001C:    symbolic_constant78000004\n// CHECK:STDOUT:       inst7800001D:    symbolic_constant78000003\n// CHECK:STDOUT:       inst7800001E:    symbolic_constant78000004\n// CHECK:STDOUT:       inst7800001F:    symbolic_constant78000005\n// CHECK:STDOUT:       inst78000021:    concrete_constant(inst78000021)\n// CHECK:STDOUT:       inst78000022:    symbolic_constant78000006\n// CHECK:STDOUT:       inst78000023:    concrete_constant(inst78000023)\n// CHECK:STDOUT:       inst78000024:    symbolic_constant78000002\n// CHECK:STDOUT:       inst78000025:    symbolic_constant78000004\n// CHECK:STDOUT:       inst78000026:    concrete_constant(inst78000026)\n// CHECK:STDOUT:       inst78000027:    concrete_constant(inst78000028)\n// CHECK:STDOUT:       inst78000028:    concrete_constant(inst78000028)\n// CHECK:STDOUT:       inst78000029:    concrete_constant(inst78000029)\n// CHECK:STDOUT:       inst7800002A:    symbolic_constant78000008\n// CHECK:STDOUT:       inst7800002B:    symbolic_constant78000007\n// CHECK:STDOUT:       inst7800002C:    symbolic_constant78000008\n// CHECK:STDOUT:       inst7800002D:    concrete_constant(inst7800002D)\n// CHECK:STDOUT:       inst7800002E:    concrete_constant(inst78000026)\n// CHECK:STDOUT:       inst7800002F:    symbolic_constant78000009\n// CHECK:STDOUT:       inst78000030:    symbolic_constant7800000A\n// CHECK:STDOUT:       inst78000031:    symbolic_constant7800000A\n// CHECK:STDOUT:       inst78000032:    symbolic_constant7800000C\n// CHECK:STDOUT:       inst78000033:    symbolic_constant7800000B\n// CHECK:STDOUT:       inst78000034:    symbolic_constant7800000C\n// CHECK:STDOUT:       inst78000035:    symbolic_constant7800000D\n// CHECK:STDOUT:       inst78000036:    concrete_constant(inst78000036)\n// CHECK:STDOUT:       inst78000037:    symbolic_constant7800000E\n// CHECK:STDOUT:       inst78000038:    concrete_constant(inst78000038)\n// CHECK:STDOUT:       inst78000039:    concrete_constant(inst(TypeType))\n// CHECK:STDOUT:       inst7800003B:    symbolic_constant78000004\n// CHECK:STDOUT:       inst7800003E:    concrete_constant(inst78000040)\n// CHECK:STDOUT:       inst7800003F:    concrete_constant(inst7800003F)\n// CHECK:STDOUT:       inst78000040:    concrete_constant(inst78000040)\n// CHECK:STDOUT:       inst78000041:    symbolic_constant78000010\n// CHECK:STDOUT:       inst78000042:    symbolic_constant7800000F\n// CHECK:STDOUT:       inst78000043:    symbolic_constant78000010\n// CHECK:STDOUT:       inst78000044:    symbolic_constant78000011\n// CHECK:STDOUT:       inst78000045:    symbolic_constant78000013\n// CHECK:STDOUT:       inst78000046:    symbolic_constant78000012\n// CHECK:STDOUT:       inst78000047:    symbolic_constant78000013\n// CHECK:STDOUT:       inst78000049:    concrete_constant(inst78000028)\n// CHECK:STDOUT:       inst7800004B:    symbolic_constant78000013\n// CHECK:STDOUT:       inst7800004D:    symbolic_constant78000010\n// CHECK:STDOUT:       inst7800004E:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst7800004F:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst78000050:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst78000051:    concrete_constant(inst78000051)\n// CHECK:STDOUT:       inst78000052:    symbolic_constant78000014\n// CHECK:STDOUT:       inst78000053:    concrete_constant(inst7800006D)\n// CHECK:STDOUT:       inst78000054:    constant<none>\n// CHECK:STDOUT:       inst78000055:    symbolic_constant78000014\n// CHECK:STDOUT:       inst78000056:    symbolic_constant78000017\n// CHECK:STDOUT:       inst78000057:    symbolic_constant78000015\n// CHECK:STDOUT:       inst78000058:    symbolic_constant78000016\n// CHECK:STDOUT:       inst78000059:    symbolic_constant78000018\n// CHECK:STDOUT:       inst7800005A:    symbolic_constant7800001A\n// CHECK:STDOUT:       inst7800005B:    concrete_constant(inst7800005B)\n// CHECK:STDOUT:       inst7800005C:    concrete_constant(inst7800005C)\n// CHECK:STDOUT:       inst7800005D:    concrete_constant(inst7800005D)\n// CHECK:STDOUT:       inst7800005E:    concrete_constant(inst7800005E)\n// CHECK:STDOUT:       inst7800005F:    symbolic_constant7800001C\n// CHECK:STDOUT:       inst78000060:    symbolic_constant78000021\n// CHECK:STDOUT:       inst78000061:    symbolic_constant78000020\n// CHECK:STDOUT:       inst78000062:    symbolic_constant78000014\n// CHECK:STDOUT:       inst78000063:    symbolic_constant78000022\n// CHECK:STDOUT:       inst78000064:    symbolic_constant78000023\n// CHECK:STDOUT:       inst78000065:    symbolic_constant78000024\n// CHECK:STDOUT:       inst78000066:    symbolic_constant78000025\n// CHECK:STDOUT:       inst78000067:    symbolic_constant78000028\n// CHECK:STDOUT:       inst78000068:    symbolic_constant78000029\n// CHECK:STDOUT:       inst78000069:    symbolic_constant7800002A\n// CHECK:STDOUT:       inst7800006A:    constant<none>\n// CHECK:STDOUT:       inst7800006B:    concrete_constant(inst7800006B)\n// CHECK:STDOUT:       inst7800006C:    symbolic_constant78000017\n// CHECK:STDOUT:       inst7800006D:    concrete_constant(inst7800006D)\n// CHECK:STDOUT:       inst7800006E:    symbolic_constant78000142\n// CHECK:STDOUT:       inst7800006F:    constant<none>\n// CHECK:STDOUT:       inst78000070:    concrete_constant(inst78000070)\n// CHECK:STDOUT:       inst78000071:    symbolic_constant7800002B\n// CHECK:STDOUT:       inst78000072:    symbolic_constant7800002C\n// CHECK:STDOUT:       inst78000073:    symbolic_constant7800002D\n// CHECK:STDOUT:       inst78000074:    constant<none>\n// CHECK:STDOUT:       inst78000075:    concrete_constant(inst78000075)\n// CHECK:STDOUT:       inst78000076:    symbolic_constant7800002F\n// CHECK:STDOUT:       inst78000077:    symbolic_constant78000033\n// CHECK:STDOUT:       inst78000078:    symbolic_constant78000031\n// CHECK:STDOUT:       inst78000079:    symbolic_constant78000032\n// CHECK:STDOUT:       inst7800007A:    symbolic_constant78000035\n// CHECK:STDOUT:       inst7800007B:    concrete_constant(inst7800007B)\n// CHECK:STDOUT:       inst7800007C:    concrete_constant(inst7800007C)\n// CHECK:STDOUT:       inst7800007D:    concrete_constant(inst7800007D)\n// CHECK:STDOUT:       inst7800007E:    concrete_constant(inst7800007E)\n// CHECK:STDOUT:       inst7800007F:    symbolic_constant78000037\n// CHECK:STDOUT:       inst78000080:    symbolic_constant7800003E\n// CHECK:STDOUT:       inst78000081:    symbolic_constant7800003D\n// CHECK:STDOUT:       inst78000082:    symbolic_constant7800003C\n// CHECK:STDOUT:       inst78000083:    symbolic_constant7800003F\n// CHECK:STDOUT:       inst78000084:    symbolic_constant78000040\n// CHECK:STDOUT:       inst78000085:    symbolic_constant78000041\n// CHECK:STDOUT:       inst78000086:    symbolic_constant78000042\n// CHECK:STDOUT:       inst78000087:    symbolic_constant78000043\n// CHECK:STDOUT:       inst78000088:    symbolic_constant78000044\n// CHECK:STDOUT:       inst78000089:    symbolic_constant78000045\n// CHECK:STDOUT:       inst7800008A:    symbolic_constant78000046\n// CHECK:STDOUT:       inst7800008B:    symbolic_constant78000047\n// CHECK:STDOUT:       inst7800008C:    symbolic_constant78000048\n// CHECK:STDOUT:       inst7800008D:    symbolic_constant78000049\n// CHECK:STDOUT:       inst7800008E:    symbolic_constant7800004B\n// CHECK:STDOUT:       inst7800008F:    symbolic_constant7800004C\n// CHECK:STDOUT:       inst78000090:    symbolic_constant78000051\n// CHECK:STDOUT:       inst78000091:    symbolic_constant78000053\n// CHECK:STDOUT:       inst78000092:    symbolic_constant78000055\n// CHECK:STDOUT:       inst78000093:    symbolic_constant78000056\n// CHECK:STDOUT:       inst78000094:    symbolic_constant78000057\n// CHECK:STDOUT:       inst78000095:    symbolic_constant78000058\n// CHECK:STDOUT:       inst78000096:    symbolic_constant78000059\n// CHECK:STDOUT:       inst78000097:    symbolic_constant7800005A\n// CHECK:STDOUT:       inst78000098:    symbolic_constant7800005B\n// CHECK:STDOUT:       inst78000099:    concrete_constant(inst78000099)\n// CHECK:STDOUT:       inst7800009A:    concrete_constant(inst7800009A)\n// CHECK:STDOUT:       inst7800009B:    symbolic_constant7800002E\n// CHECK:STDOUT:       inst7800009C:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst7800009D:    symbolic_constant7800003C\n// CHECK:STDOUT:       inst7800009E:    symbolic_constant7800005F\n// CHECK:STDOUT:       inst7800009F:    symbolic_constant78000060\n// CHECK:STDOUT:       inst780000A0:    symbolic_constant78000061\n// CHECK:STDOUT:       inst780000A1:    symbolic_constant78000062\n// CHECK:STDOUT:       inst780000A2:    symbolic_constant78000064\n// CHECK:STDOUT:       inst780000A3:    symbolic_constant78000065\n// CHECK:STDOUT:       inst780000A4:    constant<none>\n// CHECK:STDOUT:       inst780000A5:    concrete_constant(inst780000A5)\n// CHECK:STDOUT:       inst780000A6:    concrete_constant(inst(BoolType))\n// CHECK:STDOUT:       inst780000A7:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst780000A8:    constant<none>\n// CHECK:STDOUT:       inst780000A9:    concrete_constant(inst780000A9)\n// CHECK:STDOUT:       inst780000AA:    concrete_constant(inst(CharLiteralType))\n// CHECK:STDOUT:       inst780000AB:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst780000AC:    constant<none>\n// CHECK:STDOUT:       inst780000AD:    concrete_constant(inst780000AD)\n// CHECK:STDOUT:       inst780000AE:    concrete_constant(inst(FloatLiteralType))\n// CHECK:STDOUT:       inst780000AF:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst780000B0:    constant<none>\n// CHECK:STDOUT:       inst780000B1:    concrete_constant(inst780000B1)\n// CHECK:STDOUT:       inst780000B2:    concrete_constant(inst(IntLiteralType))\n// CHECK:STDOUT:       inst780000B3:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst780000B4:    symbolic_constant7800013E\n// CHECK:STDOUT:       inst780000B5:    concrete_constant(inst780000B5)\n// CHECK:STDOUT:       inst780000B6:    constant<none>\n// CHECK:STDOUT:       inst780000B7:    concrete_constant(inst780000B7)\n// CHECK:STDOUT:       inst780000B8:    symbolic_constant78000067\n// CHECK:STDOUT:       inst780000B9:    concrete_constant(inst780000B9)\n// CHECK:STDOUT:       inst780000BA:    symbolic_constant78000066\n// CHECK:STDOUT:       inst780000BB:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst780000BC:    symbolic_constant7800006B\n// CHECK:STDOUT:       inst780000BD:    symbolic_constant7800006C\n// CHECK:STDOUT:       inst780000BE:    symbolic_constant7800006D\n// CHECK:STDOUT:       inst780000BF:    symbolic_constant7800006E\n// CHECK:STDOUT:       inst780000C0:    symbolic_constant78000072\n// CHECK:STDOUT:       inst780000C1:    symbolic_constant78000070\n// CHECK:STDOUT:       inst780000C2:    symbolic_constant78000071\n// CHECK:STDOUT:       inst780000C3:    concrete_constant(inst780000C3)\n// CHECK:STDOUT:       inst780000C4:    concrete_constant(inst780000C4)\n// CHECK:STDOUT:       inst780000C5:    concrete_constant(inst780000C5)\n// CHECK:STDOUT:       inst780000C6:    concrete_constant(inst780000C6)\n// CHECK:STDOUT:       inst780000C7:    symbolic_constant78000075\n// CHECK:STDOUT:       inst780000C8:    symbolic_constant7800007A\n// CHECK:STDOUT:       inst780000C9:    symbolic_constant78000079\n// CHECK:STDOUT:       inst780000CA:    symbolic_constant7800006B\n// CHECK:STDOUT:       inst780000CB:    symbolic_constant7800007B\n// CHECK:STDOUT:       inst780000CC:    symbolic_constant7800007C\n// CHECK:STDOUT:       inst780000CD:    symbolic_constant7800007D\n// CHECK:STDOUT:       inst780000CE:    symbolic_constant7800007E\n// CHECK:STDOUT:       inst780000CF:    symbolic_constant78000080\n// CHECK:STDOUT:       inst780000D0:    symbolic_constant78000081\n// CHECK:STDOUT:       inst780000D1:    symbolic_constant78000082\n// CHECK:STDOUT:       inst780000D2:    constant<none>\n// CHECK:STDOUT:       inst780000D3:    concrete_constant(inst780000D3)\n// CHECK:STDOUT:       inst780000D4:    concrete_constant(inst(TypeType))\n// CHECK:STDOUT:       inst780000D5:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst780000D6:    constant<none>\n// CHECK:STDOUT:       inst780000D7:    concrete_constant(inst780000D7)\n// CHECK:STDOUT:       inst780000D8:    concrete_constant(inst78000026)\n// CHECK:STDOUT:       inst780000D9:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst780000DA:    constant<none>\n// CHECK:STDOUT:       inst780000DB:    concrete_constant(inst780000DB)\n// CHECK:STDOUT:       inst780000DC:    symbolic_constant78000083\n// CHECK:STDOUT:       inst780000DD:    symbolic_constant78000084\n// CHECK:STDOUT:       inst780000DE:    symbolic_constant78000085\n// CHECK:STDOUT:       inst780000DF:    constant<none>\n// CHECK:STDOUT:       inst780000E0:    concrete_constant(inst780000E0)\n// CHECK:STDOUT:       inst780000E1:    symbolic_constant78000087\n// CHECK:STDOUT:       inst780000E2:    symbolic_constant7800008B\n// CHECK:STDOUT:       inst780000E3:    symbolic_constant78000089\n// CHECK:STDOUT:       inst780000E4:    symbolic_constant7800008A\n// CHECK:STDOUT:       inst780000E5:    concrete_constant(inst780000E5)\n// CHECK:STDOUT:       inst780000E6:    symbolic_constant7800008D\n// CHECK:STDOUT:       inst780000E7:    symbolic_constant7800008E\n// CHECK:STDOUT:       inst780000E8:    concrete_constant(inst780000E8)\n// CHECK:STDOUT:       inst780000E9:    concrete_constant(inst780000E9)\n// CHECK:STDOUT:       inst780000EA:    concrete_constant(inst780000EA)\n// CHECK:STDOUT:       inst780000EB:    concrete_constant(inst780000EB)\n// CHECK:STDOUT:       inst780000EC:    symbolic_constant78000090\n// CHECK:STDOUT:       inst780000ED:    symbolic_constant7800009A\n// CHECK:STDOUT:       inst780000EE:    symbolic_constant78000099\n// CHECK:STDOUT:       inst780000EF:    symbolic_constant78000098\n// CHECK:STDOUT:       inst780000F0:    symbolic_constant78000097\n// CHECK:STDOUT:       inst780000F1:    symbolic_constant7800009B\n// CHECK:STDOUT:       inst780000F2:    symbolic_constant7800009C\n// CHECK:STDOUT:       inst780000F3:    symbolic_constant7800009D\n// CHECK:STDOUT:       inst780000F4:    symbolic_constant7800009E\n// CHECK:STDOUT:       inst780000F5:    symbolic_constant7800009F\n// CHECK:STDOUT:       inst780000F6:    symbolic_constant780000A0\n// CHECK:STDOUT:       inst780000F7:    symbolic_constant780000A1\n// CHECK:STDOUT:       inst780000F8:    symbolic_constant780000A2\n// CHECK:STDOUT:       inst780000F9:    symbolic_constant780000A3\n// CHECK:STDOUT:       inst780000FA:    symbolic_constant780000A4\n// CHECK:STDOUT:       inst780000FB:    symbolic_constant780000A5\n// CHECK:STDOUT:       inst780000FC:    symbolic_constant780000A6\n// CHECK:STDOUT:       inst780000FD:    symbolic_constant780000A7\n// CHECK:STDOUT:       inst780000FE:    symbolic_constant780000A9\n// CHECK:STDOUT:       inst780000FF:    symbolic_constant780000AA\n// CHECK:STDOUT:       inst78000100:    symbolic_constant780000AF\n// CHECK:STDOUT:       inst78000101:    symbolic_constant780000B7\n// CHECK:STDOUT:       inst78000102:    symbolic_constant780000B9\n// CHECK:STDOUT:       inst78000103:    symbolic_constant780000BA\n// CHECK:STDOUT:       inst78000104:    symbolic_constant780000BB\n// CHECK:STDOUT:       inst78000105:    symbolic_constant780000BC\n// CHECK:STDOUT:       inst78000106:    symbolic_constant780000BD\n// CHECK:STDOUT:       inst78000107:    symbolic_constant780000BE\n// CHECK:STDOUT:       inst78000108:    symbolic_constant780000BF\n// CHECK:STDOUT:       inst78000109:    symbolic_constant780000C0\n// CHECK:STDOUT:       inst7800010A:    symbolic_constant780000C1\n// CHECK:STDOUT:       inst7800010B:    symbolic_constant780000C2\n// CHECK:STDOUT:       inst7800010C:    symbolic_constant780000C3\n// CHECK:STDOUT:       inst7800010D:    symbolic_constant780000C4\n// CHECK:STDOUT:       inst7800010E:    symbolic_constant780000C5\n// CHECK:STDOUT:       inst7800010F:    concrete_constant(inst7800010F)\n// CHECK:STDOUT:       inst78000110:    concrete_constant(inst78000110)\n// CHECK:STDOUT:       inst78000111:    symbolic_constant78000086\n// CHECK:STDOUT:       inst78000112:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst78000113:    symbolic_constant78000098\n// CHECK:STDOUT:       inst78000114:    symbolic_constant78000097\n// CHECK:STDOUT:       inst78000115:    symbolic_constant780000CC\n// CHECK:STDOUT:       inst78000116:    symbolic_constant780000CD\n// CHECK:STDOUT:       inst78000117:    symbolic_constant780000CE\n// CHECK:STDOUT:       inst78000118:    symbolic_constant780000CF\n// CHECK:STDOUT:       inst78000119:    symbolic_constant780000D0\n// CHECK:STDOUT:       inst7800011A:    symbolic_constant780000D1\n// CHECK:STDOUT:       inst7800011B:    symbolic_constant780000D2\n// CHECK:STDOUT:       inst7800011C:    symbolic_constant780000D4\n// CHECK:STDOUT:       inst7800011D:    symbolic_constant780000D5\n// CHECK:STDOUT:       inst7800011E:    constant<none>\n// CHECK:STDOUT:       inst7800011F:    concrete_constant(inst7800011F)\n// CHECK:STDOUT:       inst78000120:    symbolic_constant780000D6\n// CHECK:STDOUT:       inst78000121:    symbolic_constant780000D7\n// CHECK:STDOUT:       inst78000122:    symbolic_constant780000D8\n// CHECK:STDOUT:       inst78000123:    constant<none>\n// CHECK:STDOUT:       inst78000124:    concrete_constant(inst78000124)\n// CHECK:STDOUT:       inst78000125:    symbolic_constant780000DA\n// CHECK:STDOUT:       inst78000126:    symbolic_constant780000DE\n// CHECK:STDOUT:       inst78000127:    symbolic_constant780000DC\n// CHECK:STDOUT:       inst78000128:    symbolic_constant780000DD\n// CHECK:STDOUT:       inst78000129:    concrete_constant(inst78000129)\n// CHECK:STDOUT:       inst7800012A:    symbolic_constant780000E0\n// CHECK:STDOUT:       inst7800012B:    symbolic_constant780000E1\n// CHECK:STDOUT:       inst7800012C:    concrete_constant(inst7800012C)\n// CHECK:STDOUT:       inst7800012D:    concrete_constant(inst7800012D)\n// CHECK:STDOUT:       inst7800012E:    concrete_constant(inst7800012E)\n// CHECK:STDOUT:       inst7800012F:    concrete_constant(inst7800012F)\n// CHECK:STDOUT:       inst78000130:    symbolic_constant780000E3\n// CHECK:STDOUT:       inst78000131:    symbolic_constant780000F0\n// CHECK:STDOUT:       inst78000132:    symbolic_constant780000EF\n// CHECK:STDOUT:       inst78000133:    symbolic_constant780000EE\n// CHECK:STDOUT:       inst78000134:    symbolic_constant780000ED\n// CHECK:STDOUT:       inst78000135:    symbolic_constant780000EC\n// CHECK:STDOUT:       inst78000136:    symbolic_constant780000F1\n// CHECK:STDOUT:       inst78000137:    symbolic_constant780000F2\n// CHECK:STDOUT:       inst78000138:    symbolic_constant780000F3\n// CHECK:STDOUT:       inst78000139:    symbolic_constant780000F4\n// CHECK:STDOUT:       inst7800013A:    symbolic_constant780000F5\n// CHECK:STDOUT:       inst7800013B:    symbolic_constant780000F6\n// CHECK:STDOUT:       inst7800013C:    symbolic_constant780000F7\n// CHECK:STDOUT:       inst7800013D:    symbolic_constant780000F8\n// CHECK:STDOUT:       inst7800013E:    symbolic_constant780000F9\n// CHECK:STDOUT:       inst7800013F:    symbolic_constant780000FA\n// CHECK:STDOUT:       inst78000140:    symbolic_constant780000FB\n// CHECK:STDOUT:       inst78000141:    symbolic_constant780000FC\n// CHECK:STDOUT:       inst78000142:    symbolic_constant780000FD\n// CHECK:STDOUT:       inst78000143:    symbolic_constant780000FE\n// CHECK:STDOUT:       inst78000144:    symbolic_constant780000FF\n// CHECK:STDOUT:       inst78000145:    symbolic_constant78000101\n// CHECK:STDOUT:       inst78000146:    symbolic_constant78000102\n// CHECK:STDOUT:       inst78000147:    symbolic_constant78000107\n// CHECK:STDOUT:       inst78000148:    symbolic_constant78000115\n// CHECK:STDOUT:       inst78000149:    symbolic_constant78000117\n// CHECK:STDOUT:       inst7800014A:    symbolic_constant78000118\n// CHECK:STDOUT:       inst7800014B:    symbolic_constant78000119\n// CHECK:STDOUT:       inst7800014C:    symbolic_constant7800011A\n// CHECK:STDOUT:       inst7800014D:    symbolic_constant7800011B\n// CHECK:STDOUT:       inst7800014E:    symbolic_constant7800011C\n// CHECK:STDOUT:       inst7800014F:    symbolic_constant7800011D\n// CHECK:STDOUT:       inst78000150:    symbolic_constant7800011E\n// CHECK:STDOUT:       inst78000151:    symbolic_constant7800011F\n// CHECK:STDOUT:       inst78000152:    symbolic_constant78000120\n// CHECK:STDOUT:       inst78000153:    symbolic_constant78000121\n// CHECK:STDOUT:       inst78000154:    symbolic_constant78000122\n// CHECK:STDOUT:       inst78000155:    symbolic_constant78000123\n// CHECK:STDOUT:       inst78000156:    symbolic_constant78000124\n// CHECK:STDOUT:       inst78000157:    symbolic_constant78000125\n// CHECK:STDOUT:       inst78000158:    symbolic_constant78000126\n// CHECK:STDOUT:       inst78000159:    symbolic_constant78000127\n// CHECK:STDOUT:       inst7800015A:    symbolic_constant78000128\n// CHECK:STDOUT:       inst7800015B:    symbolic_constant78000129\n// CHECK:STDOUT:       inst7800015C:    concrete_constant(inst7800015C)\n// CHECK:STDOUT:       inst7800015D:    concrete_constant(inst7800015D)\n// CHECK:STDOUT:       inst7800015E:    concrete_constant(inst7800015E)\n// CHECK:STDOUT:       inst7800015F:    symbolic_constant780000D9\n// CHECK:STDOUT:       inst78000160:    concrete_constant(inst78000050)\n// CHECK:STDOUT:       inst78000161:    symbolic_constant780000EE\n// CHECK:STDOUT:       inst78000162:    symbolic_constant780000ED\n// CHECK:STDOUT:       inst78000163:    symbolic_constant780000EC\n// CHECK:STDOUT:       inst78000164:    symbolic_constant78000132\n// CHECK:STDOUT:       inst78000165:    symbolic_constant78000133\n// CHECK:STDOUT:       inst78000166:    symbolic_constant78000134\n// CHECK:STDOUT:       inst78000167:    symbolic_constant78000135\n// CHECK:STDOUT:       inst78000168:    symbolic_constant78000136\n// CHECK:STDOUT:       inst78000169:    symbolic_constant78000137\n// CHECK:STDOUT:       inst7800016A:    symbolic_constant78000138\n// CHECK:STDOUT:       inst7800016B:    symbolic_constant78000139\n// CHECK:STDOUT:       inst7800016C:    symbolic_constant7800013A\n// CHECK:STDOUT:       inst7800016D:    symbolic_constant7800013C\n// CHECK:STDOUT:       inst7800016E:    symbolic_constant7800013D\n// CHECK:STDOUT:       inst7800016F:    symbolic_constant78000140\n// CHECK:STDOUT:       inst78000170:    symbolic_constant7800013F\n// CHECK:STDOUT:       inst78000171:    symbolic_constant78000140\n// CHECK:STDOUT:       inst78000172:    symbolic_constant78000141\n// CHECK:STDOUT:       inst78000173:    symbolic_constant78000142\n// CHECK:STDOUT:       inst78000174:    symbolic_constant78000143\n// CHECK:STDOUT:       inst78000175:    symbolic_constant78000144\n// CHECK:STDOUT:       inst78000176:    symbolic_constant78000145\n// CHECK:STDOUT:       inst78000177:    symbolic_constant78000146\n// CHECK:STDOUT:       inst78000178:    symbolic_constant7800014B\n// CHECK:STDOUT:       inst78000179:    symbolic_constant78000147\n// CHECK:STDOUT:       inst7800017A:    symbolic_constant78000148\n// CHECK:STDOUT:       inst7800017B:    symbolic_constant78000149\n// CHECK:STDOUT:       inst7800017C:    symbolic_constant7800014A\n// CHECK:STDOUT:       inst7800017D:    symbolic_constant7800014B\n// CHECK:STDOUT:       inst7800017F:    symbolic_constant7800014D\n// CHECK:STDOUT:       inst78000180:    symbolic_constant7800014C\n// CHECK:STDOUT:       inst78000181:    symbolic_constant7800014D\n// CHECK:STDOUT:       inst78000186:    concrete_constant(inst78000028)\n// CHECK:STDOUT:       inst78000187:    concrete_constant(inst78000028)\n// CHECK:STDOUT:     symbolic_constants:\n// CHECK:STDOUT:       symbolic_constant78000000: {inst: inst78000014, kind: self, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000001: {inst: inst78000018, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000002: {inst: inst78000018, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000003: {inst: inst7800001D, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000004: {inst: inst7800001D, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000005: {inst: inst7800001F, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000006: {inst: inst7800001F, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant78000007: {inst: inst7800002B, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000008: {inst: inst7800002B, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000009: {inst: inst7800002F, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800000A: {inst: inst7800002F, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant7800000B: {inst: inst78000033, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800000C: {inst: inst78000033, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant7800000D: {inst: inst78000035, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800000E: {inst: inst78000035, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant7800000F: {inst: inst78000042, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000010: {inst: inst78000042, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000011: {inst: inst78000044, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000012: {inst: inst78000046, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000013: {inst: inst78000046, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000014: {inst: inst78000052, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000015: {inst: inst78000057, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000016: {inst: inst78000058, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000017: {inst: inst78000058, kind: checked, attached: {generic: generic78000001, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant78000018: {inst: inst78000059, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000019: {inst: inst78000057, kind: checked, attached: {generic: generic78000001, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant7800001A: {inst: inst7800005A, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800001B: {inst: inst7800005A, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant7800001C: {inst: inst7800005F, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800001D: {inst: inst7800005F, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant7800001E: {inst: inst78000059, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant7800001F: {inst: inst78000052, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000020: {inst: inst7800005F, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000021: {inst: inst78000059, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000022: {inst: inst78000052, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000023: {inst: inst78000059, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000024: {inst: inst7800005A, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant78000025: {inst: inst7800005F, kind: checked, attached: {generic: generic78000002, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000026: {inst: inst78000058, kind: checked, attached: {generic: generic78000001, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant78000027: {inst: inst78000052, kind: checked, attached: {generic: generic78000001, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000028: {inst: inst78000052, kind: checked, attached: {generic: generic78000001, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000029: {inst: inst78000057, kind: checked, attached: {generic: generic78000001, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant7800002A: {inst: inst78000058, kind: checked, attached: {generic: generic78000001, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant7800002B: {inst: inst78000071, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800002C: {inst: inst78000072, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800002D: {inst: inst78000073, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800002E: {inst: inst78000073, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant7800002F: {inst: inst78000076, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000030: {inst: inst78000076, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000031: {inst: inst78000078, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000032: {inst: inst78000079, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000033: {inst: inst78000079, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000034: {inst: inst78000078, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000035: {inst: inst7800007A, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000036: {inst: inst7800007A, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000037: {inst: inst7800007F, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000038: {inst: inst7800007F, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant78000039: {inst: inst78000073, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant7800003A: {inst: inst78000072, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant7800003B: {inst: inst78000071, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant7800003C: {inst: inst78000071, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant7800003D: {inst: inst7800007F, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant7800003E: {inst: inst78000073, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant7800003F: {inst: inst78000071, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000040: {inst: inst78000072, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000041: {inst: inst78000073, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant78000042: {inst: inst7800007A, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000043: {inst: inst7800007F, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant78000044: {inst: inst78000088, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000045: {inst: inst78000089, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000046: {inst: inst7800008A, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000047: {inst: inst7800008B, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000048: {inst: inst7800008C, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000049: {inst: inst7800008D, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800004A: {inst: inst7800008D, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def6}}\n// CHECK:STDOUT:       symbolic_constant7800004B: {inst: inst7800008E, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800004C: {inst: inst7800008F, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800004D: {inst: inst7800008C, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def5}}\n// CHECK:STDOUT:       symbolic_constant7800004E: {inst: inst7800008B, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def4}}\n// CHECK:STDOUT:       symbolic_constant7800004F: {inst: inst78000089, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def3}}\n// CHECK:STDOUT:       symbolic_constant78000050: {inst: inst78000088, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant78000051: {inst: inst78000090, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000052: {inst: inst78000090, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000053: {inst: inst78000091, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000054: {inst: inst78000091, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000055: {inst: inst78000091, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000056: {inst: inst78000090, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000057: {inst: inst78000088, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant78000058: {inst: inst78000089, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def3}}\n// CHECK:STDOUT:       symbolic_constant78000059: {inst: inst7800008B, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def4}}\n// CHECK:STDOUT:       symbolic_constant7800005A: {inst: inst7800008C, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def5}}\n// CHECK:STDOUT:       symbolic_constant7800005B: {inst: inst7800008D, kind: checked, attached: {generic: generic78000004, index: generic_inst_in_def6}}\n// CHECK:STDOUT:       symbolic_constant7800005C: {inst: inst78000073, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant7800005D: {inst: inst78000072, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant7800005E: {inst: inst78000071, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant7800005F: {inst: inst78000071, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000060: {inst: inst78000072, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000061: {inst: inst78000073, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant78000062: {inst: inst78000076, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000063: {inst: inst78000079, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000064: {inst: inst78000078, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000065: {inst: inst78000079, kind: checked, attached: {generic: generic78000003, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000066: {inst: inst7800001D, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000067: {inst: inst780000B8, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000068: {inst: inst780000B8, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant78000069: {inst: inst7800001D, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant7800006A: {inst: inst78000018, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant7800006B: {inst: inst78000018, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant7800006C: {inst: inst78000018, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant7800006D: {inst: inst7800001D, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant7800006E: {inst: inst780000B8, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant7800006F: {inst: inst78000042, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant78000070: {inst: inst780000C1, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000071: {inst: inst780000C2, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000072: {inst: inst780000C2, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000073: {inst: inst780000C1, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000074: {inst: inst7800001F, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant78000075: {inst: inst780000C7, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000076: {inst: inst780000C7, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000077: {inst: inst7800001D, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000078: {inst: inst78000018, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000079: {inst: inst780000C7, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant7800007A: {inst: inst7800001D, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant7800007B: {inst: inst78000018, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant7800007C: {inst: inst7800001D, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant7800007D: {inst: inst7800001F, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant7800007E: {inst: inst780000C7, kind: checked, attached: {generic: generic78000006, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant7800007F: {inst: inst780000C2, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000080: {inst: inst780000C1, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000081: {inst: inst780000C2, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000082: {inst: inst78000042, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant78000083: {inst: inst780000DC, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000084: {inst: inst780000DD, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000085: {inst: inst780000DE, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000086: {inst: inst780000DE, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant78000087: {inst: inst780000E1, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000088: {inst: inst780000E1, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant78000089: {inst: inst780000E3, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800008A: {inst: inst780000E4, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800008B: {inst: inst780000E4, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant7800008C: {inst: inst780000E3, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant7800008D: {inst: inst780000E6, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800008E: {inst: inst780000E7, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800008F: {inst: inst780000E7, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant78000090: {inst: inst780000EC, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000091: {inst: inst780000EC, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant78000092: {inst: inst780000DE, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant78000093: {inst: inst780000DD, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000094: {inst: inst780000DC, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant78000095: {inst: inst78000072, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000096: {inst: inst78000071, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000097: {inst: inst780000DC, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000098: {inst: inst78000071, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000099: {inst: inst780000EC, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant7800009A: {inst: inst780000DE, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant7800009B: {inst: inst78000071, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant7800009C: {inst: inst78000072, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant7800009D: {inst: inst780000DC, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant7800009E: {inst: inst780000DD, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant7800009F: {inst: inst780000DE, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant780000A0: {inst: inst780000E7, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant780000A1: {inst: inst780000EC, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant780000A2: {inst: inst780000F8, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000A3: {inst: inst780000F9, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000A4: {inst: inst780000FA, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000A5: {inst: inst780000FB, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000A6: {inst: inst780000FC, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000A7: {inst: inst780000FD, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000A8: {inst: inst780000FD, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def12}}\n// CHECK:STDOUT:       symbolic_constant780000A9: {inst: inst780000FE, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000AA: {inst: inst780000FF, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000AB: {inst: inst780000FC, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def11}}\n// CHECK:STDOUT:       symbolic_constant780000AC: {inst: inst780000FB, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def10}}\n// CHECK:STDOUT:       symbolic_constant780000AD: {inst: inst780000F9, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def9}}\n// CHECK:STDOUT:       symbolic_constant780000AE: {inst: inst780000F8, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def8}}\n// CHECK:STDOUT:       symbolic_constant780000AF: {inst: inst78000100, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000B0: {inst: inst78000100, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def7}}\n// CHECK:STDOUT:       symbolic_constant780000B1: {inst: inst7800008D, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def6}}\n// CHECK:STDOUT:       symbolic_constant780000B2: {inst: inst7800008C, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def5}}\n// CHECK:STDOUT:       symbolic_constant780000B3: {inst: inst7800008B, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def4}}\n// CHECK:STDOUT:       symbolic_constant780000B4: {inst: inst78000089, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def3}}\n// CHECK:STDOUT:       symbolic_constant780000B5: {inst: inst78000088, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant780000B6: {inst: inst78000090, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant780000B7: {inst: inst78000101, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000B8: {inst: inst78000101, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant780000B9: {inst: inst78000101, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant780000BA: {inst: inst78000090, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant780000BB: {inst: inst78000088, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant780000BC: {inst: inst78000089, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def3}}\n// CHECK:STDOUT:       symbolic_constant780000BD: {inst: inst7800008B, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def4}}\n// CHECK:STDOUT:       symbolic_constant780000BE: {inst: inst7800008C, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def5}}\n// CHECK:STDOUT:       symbolic_constant780000BF: {inst: inst7800008D, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def6}}\n// CHECK:STDOUT:       symbolic_constant780000C0: {inst: inst78000100, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def7}}\n// CHECK:STDOUT:       symbolic_constant780000C1: {inst: inst780000F8, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def8}}\n// CHECK:STDOUT:       symbolic_constant780000C2: {inst: inst780000F9, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def9}}\n// CHECK:STDOUT:       symbolic_constant780000C3: {inst: inst780000FB, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def10}}\n// CHECK:STDOUT:       symbolic_constant780000C4: {inst: inst780000FC, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def11}}\n// CHECK:STDOUT:       symbolic_constant780000C5: {inst: inst780000FD, kind: checked, attached: {generic: generic78000008, index: generic_inst_in_def12}}\n// CHECK:STDOUT:       symbolic_constant780000C6: {inst: inst780000DE, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant780000C7: {inst: inst780000DD, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant780000C8: {inst: inst78000072, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant780000C9: {inst: inst780000E6, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant780000CA: {inst: inst780000DC, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant780000CB: {inst: inst78000071, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant780000CC: {inst: inst78000071, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant780000CD: {inst: inst780000DC, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant780000CE: {inst: inst780000E6, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant780000CF: {inst: inst78000072, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant780000D0: {inst: inst780000DD, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant780000D1: {inst: inst780000DE, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant780000D2: {inst: inst780000E1, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant780000D3: {inst: inst780000E4, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant780000D4: {inst: inst780000E3, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant780000D5: {inst: inst780000E4, kind: checked, attached: {generic: generic78000007, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant780000D6: {inst: inst78000120, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000D7: {inst: inst78000121, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000D8: {inst: inst78000122, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000D9: {inst: inst78000122, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl7}}\n// CHECK:STDOUT:       symbolic_constant780000DA: {inst: inst78000125, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000DB: {inst: inst78000125, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl8}}\n// CHECK:STDOUT:       symbolic_constant780000DC: {inst: inst78000127, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000DD: {inst: inst78000128, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000DE: {inst: inst78000128, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant780000DF: {inst: inst78000127, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant780000E0: {inst: inst7800012A, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000E1: {inst: inst7800012B, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000E2: {inst: inst7800012B, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl7}}\n// CHECK:STDOUT:       symbolic_constant780000E3: {inst: inst78000130, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000E4: {inst: inst78000130, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl8}}\n// CHECK:STDOUT:       symbolic_constant780000E5: {inst: inst78000122, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant780000E6: {inst: inst78000121, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant780000E7: {inst: inst78000120, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant780000E8: {inst: inst780000DD, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant780000E9: {inst: inst780000DC, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant780000EA: {inst: inst78000072, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant780000EB: {inst: inst78000071, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant780000EC: {inst: inst78000120, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant780000ED: {inst: inst780000DC, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant780000EE: {inst: inst78000071, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant780000EF: {inst: inst78000130, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl8}}\n// CHECK:STDOUT:       symbolic_constant780000F0: {inst: inst78000122, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant780000F1: {inst: inst78000071, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant780000F2: {inst: inst78000072, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant780000F3: {inst: inst780000DC, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant780000F4: {inst: inst780000DD, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant780000F5: {inst: inst78000120, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant780000F6: {inst: inst78000121, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant780000F7: {inst: inst78000122, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant780000F8: {inst: inst7800012B, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl7}}\n// CHECK:STDOUT:       symbolic_constant780000F9: {inst: inst78000130, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_decl8}}\n// CHECK:STDOUT:       symbolic_constant780000FA: {inst: inst7800013F, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000FB: {inst: inst78000140, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000FC: {inst: inst78000141, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000FD: {inst: inst78000142, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000FE: {inst: inst78000143, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant780000FF: {inst: inst78000144, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000100: {inst: inst78000144, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def18}}\n// CHECK:STDOUT:       symbolic_constant78000101: {inst: inst78000145, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000102: {inst: inst78000146, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000103: {inst: inst78000143, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def17}}\n// CHECK:STDOUT:       symbolic_constant78000104: {inst: inst78000142, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def16}}\n// CHECK:STDOUT:       symbolic_constant78000105: {inst: inst78000140, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def15}}\n// CHECK:STDOUT:       symbolic_constant78000106: {inst: inst7800013F, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def14}}\n// CHECK:STDOUT:       symbolic_constant78000107: {inst: inst78000147, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000108: {inst: inst78000147, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def13}}\n// CHECK:STDOUT:       symbolic_constant78000109: {inst: inst780000FD, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def12}}\n// CHECK:STDOUT:       symbolic_constant7800010A: {inst: inst780000FC, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def11}}\n// CHECK:STDOUT:       symbolic_constant7800010B: {inst: inst780000FB, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def10}}\n// CHECK:STDOUT:       symbolic_constant7800010C: {inst: inst780000F9, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def9}}\n// CHECK:STDOUT:       symbolic_constant7800010D: {inst: inst780000F8, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def8}}\n// CHECK:STDOUT:       symbolic_constant7800010E: {inst: inst78000100, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def7}}\n// CHECK:STDOUT:       symbolic_constant7800010F: {inst: inst7800008D, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def6}}\n// CHECK:STDOUT:       symbolic_constant78000110: {inst: inst7800008C, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def5}}\n// CHECK:STDOUT:       symbolic_constant78000111: {inst: inst7800008B, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def4}}\n// CHECK:STDOUT:       symbolic_constant78000112: {inst: inst78000089, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def3}}\n// CHECK:STDOUT:       symbolic_constant78000113: {inst: inst78000088, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant78000114: {inst: inst78000090, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000115: {inst: inst78000148, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000116: {inst: inst78000148, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000117: {inst: inst78000148, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant78000118: {inst: inst78000090, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant78000119: {inst: inst78000088, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant7800011A: {inst: inst78000089, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def3}}\n// CHECK:STDOUT:       symbolic_constant7800011B: {inst: inst7800008B, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def4}}\n// CHECK:STDOUT:       symbolic_constant7800011C: {inst: inst7800008C, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def5}}\n// CHECK:STDOUT:       symbolic_constant7800011D: {inst: inst7800008D, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def6}}\n// CHECK:STDOUT:       symbolic_constant7800011E: {inst: inst78000100, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def7}}\n// CHECK:STDOUT:       symbolic_constant7800011F: {inst: inst780000F8, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def8}}\n// CHECK:STDOUT:       symbolic_constant78000120: {inst: inst780000F9, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def9}}\n// CHECK:STDOUT:       symbolic_constant78000121: {inst: inst780000FB, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def10}}\n// CHECK:STDOUT:       symbolic_constant78000122: {inst: inst780000FC, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def11}}\n// CHECK:STDOUT:       symbolic_constant78000123: {inst: inst780000FD, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def12}}\n// CHECK:STDOUT:       symbolic_constant78000124: {inst: inst78000147, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def13}}\n// CHECK:STDOUT:       symbolic_constant78000125: {inst: inst7800013F, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def14}}\n// CHECK:STDOUT:       symbolic_constant78000126: {inst: inst78000140, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def15}}\n// CHECK:STDOUT:       symbolic_constant78000127: {inst: inst78000142, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def16}}\n// CHECK:STDOUT:       symbolic_constant78000128: {inst: inst78000143, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def17}}\n// CHECK:STDOUT:       symbolic_constant78000129: {inst: inst78000144, kind: checked, attached: {generic: generic7800000A, index: generic_inst_in_def18}}\n// CHECK:STDOUT:       symbolic_constant7800012A: {inst: inst78000122, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl7}}\n// CHECK:STDOUT:       symbolic_constant7800012B: {inst: inst78000121, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant7800012C: {inst: inst780000DD, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant7800012D: {inst: inst78000072, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant7800012E: {inst: inst7800012A, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant7800012F: {inst: inst78000120, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant78000130: {inst: inst780000DC, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000131: {inst: inst78000071, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000132: {inst: inst78000071, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl0}}\n// CHECK:STDOUT:       symbolic_constant78000133: {inst: inst780000DC, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl1}}\n// CHECK:STDOUT:       symbolic_constant78000134: {inst: inst78000120, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant78000135: {inst: inst7800012A, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl3}}\n// CHECK:STDOUT:       symbolic_constant78000136: {inst: inst78000072, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl4}}\n// CHECK:STDOUT:       symbolic_constant78000137: {inst: inst780000DD, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl5}}\n// CHECK:STDOUT:       symbolic_constant78000138: {inst: inst78000121, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl6}}\n// CHECK:STDOUT:       symbolic_constant78000139: {inst: inst78000122, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl7}}\n// CHECK:STDOUT:       symbolic_constant7800013A: {inst: inst78000125, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_decl8}}\n// CHECK:STDOUT:       symbolic_constant7800013B: {inst: inst78000128, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant7800013C: {inst: inst78000127, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_def0}}\n// CHECK:STDOUT:       symbolic_constant7800013D: {inst: inst78000128, kind: checked, attached: {generic: generic78000009, index: generic_inst_in_def1}}\n// CHECK:STDOUT:       symbolic_constant7800013E: {inst: inst780000B8, kind: checked, attached: {generic: generic78000005, index: generic_inst_in_decl2}}\n// CHECK:STDOUT:       symbolic_constant7800013F: {inst: inst78000170, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000140: {inst: inst78000170, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def2}}\n// CHECK:STDOUT:       symbolic_constant78000141: {inst: inst78000172, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000142: {inst: inst78000172, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def3}}\n// CHECK:STDOUT:       symbolic_constant78000143: {inst: inst78000174, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000144: {inst: inst78000175, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000145: {inst: inst78000176, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000146: {inst: inst78000177, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000147: {inst: inst78000179, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant78000148: {inst: inst78000174, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def4}}\n// CHECK:STDOUT:       symbolic_constant78000149: {inst: inst78000175, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def5}}\n// CHECK:STDOUT:       symbolic_constant7800014A: {inst: inst78000177, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def6}}\n// CHECK:STDOUT:       symbolic_constant7800014B: {inst: inst78000179, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def7}}\n// CHECK:STDOUT:       symbolic_constant7800014C: {inst: inst78000180, kind: checked, attached: null}\n// CHECK:STDOUT:       symbolic_constant7800014D: {inst: inst78000180, kind: checked, attached: {generic: generic78000000, index: generic_inst_in_def8}}\n// CHECK:STDOUT:   inst_blocks:\n// CHECK:STDOUT:     inst_block_empty: {}\n// CHECK:STDOUT:     exports:\n// CHECK:STDOUT:       0:               inst7800003E\n// CHECK:STDOUT:     generated:       {}\n// CHECK:STDOUT:     imports:\n// CHECK:STDOUT:       0:               inst78000011\n// CHECK:STDOUT:       1:               inst7800004E\n// CHECK:STDOUT:       2:               inst7800004F\n// CHECK:STDOUT:       3:               inst78000051\n// CHECK:STDOUT:       4:               inst78000053\n// CHECK:STDOUT:       5:               inst78000054\n// CHECK:STDOUT:       6:               inst78000055\n// CHECK:STDOUT:       7:               inst78000056\n// CHECK:STDOUT:       8:               inst7800005B\n// CHECK:STDOUT:       9:               inst7800005C\n// CHECK:STDOUT:       10:              inst7800005D\n// CHECK:STDOUT:       11:              inst7800005E\n// CHECK:STDOUT:       12:              inst78000060\n// CHECK:STDOUT:       13:              inst78000061\n// CHECK:STDOUT:       14:              inst78000062\n// CHECK:STDOUT:       15:              inst7800006A\n// CHECK:STDOUT:       16:              inst7800006C\n// CHECK:STDOUT:       17:              inst7800006F\n// CHECK:STDOUT:       18:              inst78000070\n// CHECK:STDOUT:       19:              inst78000074\n// CHECK:STDOUT:       20:              inst78000075\n// CHECK:STDOUT:       21:              inst78000077\n// CHECK:STDOUT:       22:              inst7800007B\n// CHECK:STDOUT:       23:              inst7800007C\n// CHECK:STDOUT:       24:              inst7800007D\n// CHECK:STDOUT:       25:              inst7800007E\n// CHECK:STDOUT:       26:              inst78000080\n// CHECK:STDOUT:       27:              inst78000081\n// CHECK:STDOUT:       28:              inst78000082\n// CHECK:STDOUT:       29:              inst7800009A\n// CHECK:STDOUT:       30:              inst7800009B\n// CHECK:STDOUT:       31:              inst7800009C\n// CHECK:STDOUT:       32:              inst7800009D\n// CHECK:STDOUT:       33:              inst780000A4\n// CHECK:STDOUT:       34:              inst780000A5\n// CHECK:STDOUT:       35:              inst780000A6\n// CHECK:STDOUT:       36:              inst780000A7\n// CHECK:STDOUT:       37:              inst780000A8\n// CHECK:STDOUT:       38:              inst780000A9\n// CHECK:STDOUT:       39:              inst780000AA\n// CHECK:STDOUT:       40:              inst780000AB\n// CHECK:STDOUT:       41:              inst780000AC\n// CHECK:STDOUT:       42:              inst780000AD\n// CHECK:STDOUT:       43:              inst780000AE\n// CHECK:STDOUT:       44:              inst780000AF\n// CHECK:STDOUT:       45:              inst780000B0\n// CHECK:STDOUT:       46:              inst780000B1\n// CHECK:STDOUT:       47:              inst780000B2\n// CHECK:STDOUT:       48:              inst780000B3\n// CHECK:STDOUT:       49:              inst780000B4\n// CHECK:STDOUT:       50:              inst780000B5\n// CHECK:STDOUT:       51:              inst780000B6\n// CHECK:STDOUT:       52:              inst780000B7\n// CHECK:STDOUT:       53:              inst780000B9\n// CHECK:STDOUT:       54:              inst780000BA\n// CHECK:STDOUT:       55:              inst780000BB\n// CHECK:STDOUT:       56:              inst780000BC\n// CHECK:STDOUT:       57:              inst780000C0\n// CHECK:STDOUT:       58:              inst780000C3\n// CHECK:STDOUT:       59:              inst780000C4\n// CHECK:STDOUT:       60:              inst780000C5\n// CHECK:STDOUT:       61:              inst780000C6\n// CHECK:STDOUT:       62:              inst780000C8\n// CHECK:STDOUT:       63:              inst780000C9\n// CHECK:STDOUT:       64:              inst780000CA\n// CHECK:STDOUT:       65:              inst780000D2\n// CHECK:STDOUT:       66:              inst780000D3\n// CHECK:STDOUT:       67:              inst780000D4\n// CHECK:STDOUT:       68:              inst780000D5\n// CHECK:STDOUT:       69:              inst780000D6\n// CHECK:STDOUT:       70:              inst780000D7\n// CHECK:STDOUT:       71:              inst780000D8\n// CHECK:STDOUT:       72:              inst780000D9\n// CHECK:STDOUT:       73:              inst780000DA\n// CHECK:STDOUT:       74:              inst780000DB\n// CHECK:STDOUT:       75:              inst780000DF\n// CHECK:STDOUT:       76:              inst780000E0\n// CHECK:STDOUT:       77:              inst780000E2\n// CHECK:STDOUT:       78:              inst780000E8\n// CHECK:STDOUT:       79:              inst780000E9\n// CHECK:STDOUT:       80:              inst780000EA\n// CHECK:STDOUT:       81:              inst780000EB\n// CHECK:STDOUT:       82:              inst780000ED\n// CHECK:STDOUT:       83:              inst780000EE\n// CHECK:STDOUT:       84:              inst780000EF\n// CHECK:STDOUT:       85:              inst780000F0\n// CHECK:STDOUT:       86:              inst7800010F\n// CHECK:STDOUT:       87:              inst78000110\n// CHECK:STDOUT:       88:              inst78000111\n// CHECK:STDOUT:       89:              inst78000112\n// CHECK:STDOUT:       90:              inst78000113\n// CHECK:STDOUT:       91:              inst78000114\n// CHECK:STDOUT:       92:              inst7800011E\n// CHECK:STDOUT:       93:              inst7800011F\n// CHECK:STDOUT:       94:              inst78000123\n// CHECK:STDOUT:       95:              inst78000124\n// CHECK:STDOUT:       96:              inst78000126\n// CHECK:STDOUT:       97:              inst7800012C\n// CHECK:STDOUT:       98:              inst7800012D\n// CHECK:STDOUT:       99:              inst7800012E\n// CHECK:STDOUT:       100:             inst7800012F\n// CHECK:STDOUT:       101:             inst78000131\n// CHECK:STDOUT:       102:             inst78000132\n// CHECK:STDOUT:       103:             inst78000133\n// CHECK:STDOUT:       104:             inst78000134\n// CHECK:STDOUT:       105:             inst78000135\n// CHECK:STDOUT:       106:             inst7800015C\n// CHECK:STDOUT:       107:             inst7800015D\n// CHECK:STDOUT:       108:             inst7800015E\n// CHECK:STDOUT:       109:             inst7800015F\n// CHECK:STDOUT:       110:             inst78000160\n// CHECK:STDOUT:       111:             inst78000161\n// CHECK:STDOUT:       112:             inst78000162\n// CHECK:STDOUT:       113:             inst78000163\n// CHECK:STDOUT:     global_init:     {}\n// CHECK:STDOUT:     inst_block78000005:\n// CHECK:STDOUT:       0:               inst78000013\n// CHECK:STDOUT:       1:               inst78000015\n// CHECK:STDOUT:     inst_block78000006:\n// CHECK:STDOUT:       0:               inst7800001A\n// CHECK:STDOUT:     inst_block78000007:\n// CHECK:STDOUT:       0:               inst7800001B\n// CHECK:STDOUT:       1:               inst7800001C\n// CHECK:STDOUT:     inst_block78000008:\n// CHECK:STDOUT:       0:               inst78000023\n// CHECK:STDOUT:     inst_block78000009:\n// CHECK:STDOUT:       0:               inst78000025\n// CHECK:STDOUT:       1:               inst78000027\n// CHECK:STDOUT:     inst_block7800000A:\n// CHECK:STDOUT:       0:               inst(TypeType)\n// CHECK:STDOUT:       1:               inst78000026\n// CHECK:STDOUT:     inst_block7800000B:\n// CHECK:STDOUT:       0:               inst7800001D\n// CHECK:STDOUT:       1:               inst78000028\n// CHECK:STDOUT:     inst_block7800000C:\n// CHECK:STDOUT:       0:               inst7800001E\n// CHECK:STDOUT:       1:               inst78000028\n// CHECK:STDOUT:     inst_block7800000D:\n// CHECK:STDOUT:       0:               inst7800001D\n// CHECK:STDOUT:       1:               inst7800002E\n// CHECK:STDOUT:     inst_block7800000E:\n// CHECK:STDOUT:       0:               inst7800001D\n// CHECK:STDOUT:       1:               inst78000026\n// CHECK:STDOUT:     inst_block7800000F:\n// CHECK:STDOUT:       0:               inst7800001E\n// CHECK:STDOUT:       1:               inst78000026\n// CHECK:STDOUT:     inst_block78000010:\n// CHECK:STDOUT:       0:               inst78000038\n// CHECK:STDOUT:     inst_block78000011:\n// CHECK:STDOUT:       0:               inst78000023\n// CHECK:STDOUT:       1:               inst78000038\n// CHECK:STDOUT:     inst_block78000012:\n// CHECK:STDOUT:       0:               inst7800003A\n// CHECK:STDOUT:       1:               inst7800003C\n// CHECK:STDOUT:     inst_block78000013:\n// CHECK:STDOUT:       0:               inst7800001A\n// CHECK:STDOUT:       1:               inst78000021\n// CHECK:STDOUT:       2:               inst78000023\n// CHECK:STDOUT:       3:               inst78000036\n// CHECK:STDOUT:       4:               inst78000038\n// CHECK:STDOUT:     inst_block78000014:\n// CHECK:STDOUT:       0:               inst78000024\n// CHECK:STDOUT:       1:               inst78000025\n// CHECK:STDOUT:       2:               inst78000027\n// CHECK:STDOUT:       3:               inst7800002A\n// CHECK:STDOUT:       4:               inst7800002E\n// CHECK:STDOUT:       5:               inst78000030\n// CHECK:STDOUT:       6:               inst78000032\n// CHECK:STDOUT:       7:               inst78000039\n// CHECK:STDOUT:       8:               inst78000017\n// CHECK:STDOUT:       9:               inst7800003A\n// CHECK:STDOUT:       10:              inst7800003B\n// CHECK:STDOUT:       11:              inst78000020\n// CHECK:STDOUT:       12:              inst7800003C\n// CHECK:STDOUT:       13:              inst7800003D\n// CHECK:STDOUT:     inst_block78000015:\n// CHECK:STDOUT:       0:               inst78000017\n// CHECK:STDOUT:     inst_block78000016:\n// CHECK:STDOUT:       0:               inst78000018\n// CHECK:STDOUT:     inst_block78000017:\n// CHECK:STDOUT:       0:               inst78000019\n// CHECK:STDOUT:       1:               inst7800001E\n// CHECK:STDOUT:       2:               inst78000022\n// CHECK:STDOUT:       3:               inst7800002C\n// CHECK:STDOUT:       4:               inst78000031\n// CHECK:STDOUT:       5:               inst78000034\n// CHECK:STDOUT:       6:               inst78000037\n// CHECK:STDOUT:     inst_block78000018:\n// CHECK:STDOUT:       0:               inst78000018\n// CHECK:STDOUT:       1:               inst7800001D\n// CHECK:STDOUT:       2:               inst7800001F\n// CHECK:STDOUT:       3:               inst7800002B\n// CHECK:STDOUT:       4:               inst7800002F\n// CHECK:STDOUT:       5:               inst78000033\n// CHECK:STDOUT:       6:               inst78000035\n// CHECK:STDOUT:     inst_block78000019:\n// CHECK:STDOUT:       0:               inst78000048\n// CHECK:STDOUT:       1:               inst78000049\n// CHECK:STDOUT:       2:               inst7800004A\n// CHECK:STDOUT:       3:               inst78000178\n// CHECK:STDOUT:       4:               inst7800017E\n// CHECK:STDOUT:       5:               inst7800017F\n// CHECK:STDOUT:       6:               inst78000182\n// CHECK:STDOUT:       7:               inst78000183\n// CHECK:STDOUT:       8:               inst7800004C\n// CHECK:STDOUT:       9:               inst78000184\n// CHECK:STDOUT:       10:              inst78000185\n// CHECK:STDOUT:       11:              inst78000186\n// CHECK:STDOUT:       12:              inst78000187\n// CHECK:STDOUT:       13:              inst78000188\n// CHECK:STDOUT:       14:              inst78000189\n// CHECK:STDOUT:       15:              inst7800018A\n// CHECK:STDOUT:     inst_block7800001A:\n// CHECK:STDOUT:       0:               inst78000048\n// CHECK:STDOUT:       1:               inst78000049\n// CHECK:STDOUT:     inst_block7800001B:\n// CHECK:STDOUT:       0:               inst78000054\n// CHECK:STDOUT:     inst_block7800001C:\n// CHECK:STDOUT:       0:               inst78000055\n// CHECK:STDOUT:     inst_block7800001D:\n// CHECK:STDOUT:       0:               inst78000052\n// CHECK:STDOUT:     inst_block7800001E:\n// CHECK:STDOUT:       0:               inst78000052\n// CHECK:STDOUT:       1:               inst78000057\n// CHECK:STDOUT:       2:               inst78000058\n// CHECK:STDOUT:     inst_block7800001F:\n// CHECK:STDOUT:       0:               inst7800005E\n// CHECK:STDOUT:       1:               inst7800005C\n// CHECK:STDOUT:     inst_block78000020:\n// CHECK:STDOUT:       0:               inst7800005E\n// CHECK:STDOUT:     inst_block78000021:\n// CHECK:STDOUT:       0:               inst7800005C\n// CHECK:STDOUT:     inst_block78000022:\n// CHECK:STDOUT:       0:               inst78000062\n// CHECK:STDOUT:     inst_block78000023:\n// CHECK:STDOUT:       0:               inst78000063\n// CHECK:STDOUT:       1:               inst78000064\n// CHECK:STDOUT:       2:               inst78000065\n// CHECK:STDOUT:       3:               inst78000066\n// CHECK:STDOUT:     inst_block78000024:\n// CHECK:STDOUT:       0:               inst78000052\n// CHECK:STDOUT:       1:               inst78000059\n// CHECK:STDOUT:       2:               inst7800005A\n// CHECK:STDOUT:       3:               inst7800005F\n// CHECK:STDOUT:     inst_block78000025:\n// CHECK:STDOUT:       0:               inst78000067\n// CHECK:STDOUT:     inst_block78000026:\n// CHECK:STDOUT:       0:               inst78000067\n// CHECK:STDOUT:       1:               inst78000068\n// CHECK:STDOUT:       2:               inst78000069\n// CHECK:STDOUT:     inst_block78000027:\n// CHECK:STDOUT:       0:               inst78000074\n// CHECK:STDOUT:     inst_block78000028:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:     inst_block78000029:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst78000072\n// CHECK:STDOUT:       2:               inst78000073\n// CHECK:STDOUT:       3:               inst78000076\n// CHECK:STDOUT:     inst_block7800002A:\n// CHECK:STDOUT:       0:               inst78000078\n// CHECK:STDOUT:       1:               inst78000079\n// CHECK:STDOUT:     inst_block7800002B:\n// CHECK:STDOUT:       0:               inst7800007E\n// CHECK:STDOUT:       1:               inst7800007C\n// CHECK:STDOUT:     inst_block7800002C:\n// CHECK:STDOUT:       0:               inst7800007E\n// CHECK:STDOUT:     inst_block7800002D:\n// CHECK:STDOUT:       0:               inst7800007C\n// CHECK:STDOUT:     inst_block7800002E:\n// CHECK:STDOUT:       0:               inst78000082\n// CHECK:STDOUT:     inst_block7800002F:\n// CHECK:STDOUT:       0:               inst78000083\n// CHECK:STDOUT:       1:               inst78000084\n// CHECK:STDOUT:       2:               inst78000085\n// CHECK:STDOUT:       3:               inst78000086\n// CHECK:STDOUT:       4:               inst78000087\n// CHECK:STDOUT:     inst_block78000030:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst78000089\n// CHECK:STDOUT:       2:               inst7800008A\n// CHECK:STDOUT:     inst_block78000031:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst78000072\n// CHECK:STDOUT:       2:               inst7800008F\n// CHECK:STDOUT:       3:               inst7800008E\n// CHECK:STDOUT:     inst_block78000032:\n// CHECK:STDOUT:       0:               inst78000083\n// CHECK:STDOUT:     inst_block78000033:\n// CHECK:STDOUT:       0:               inst78000083\n// CHECK:STDOUT:     inst_block78000034:\n// CHECK:STDOUT:       0:               inst78000092\n// CHECK:STDOUT:       1:               inst78000093\n// CHECK:STDOUT:       2:               inst78000094\n// CHECK:STDOUT:       3:               inst78000095\n// CHECK:STDOUT:       4:               inst78000096\n// CHECK:STDOUT:       5:               inst78000097\n// CHECK:STDOUT:       6:               inst78000098\n// CHECK:STDOUT:     inst_block78000035:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst78000072\n// CHECK:STDOUT:       2:               inst78000073\n// CHECK:STDOUT:       3:               inst7800007A\n// CHECK:STDOUT:       4:               inst7800007F\n// CHECK:STDOUT:     inst_block78000036:\n// CHECK:STDOUT:       0:               inst7800009A\n// CHECK:STDOUT:     inst_block78000037:\n// CHECK:STDOUT:       0:               inst7800009D\n// CHECK:STDOUT:     inst_block78000038:\n// CHECK:STDOUT:       0:               inst7800009E\n// CHECK:STDOUT:     inst_block78000039:\n// CHECK:STDOUT:       0:               inst7800009E\n// CHECK:STDOUT:       1:               inst7800009F\n// CHECK:STDOUT:       2:               inst780000A0\n// CHECK:STDOUT:       3:               inst780000A1\n// CHECK:STDOUT:     inst_block7800003A:\n// CHECK:STDOUT:       0:               inst7800009E\n// CHECK:STDOUT:     inst_block7800003B:\n// CHECK:STDOUT:       0:               inst780000A2\n// CHECK:STDOUT:       1:               inst780000A3\n// CHECK:STDOUT:     inst_block7800003C:\n// CHECK:STDOUT:       0:               inst780000B6\n// CHECK:STDOUT:     inst_block7800003D:\n// CHECK:STDOUT:       0:               inst78000018\n// CHECK:STDOUT:       1:               inst7800001D\n// CHECK:STDOUT:       2:               inst780000B8\n// CHECK:STDOUT:     inst_block7800003E:\n// CHECK:STDOUT:       0:               inst780000B9\n// CHECK:STDOUT:     inst_block7800003F:\n// CHECK:STDOUT:       0:               inst780000BC\n// CHECK:STDOUT:     inst_block78000040:\n// CHECK:STDOUT:       0:               inst780000BD\n// CHECK:STDOUT:     inst_block78000041:\n// CHECK:STDOUT:       0:               inst780000BD\n// CHECK:STDOUT:       1:               inst780000BE\n// CHECK:STDOUT:       2:               inst780000BF\n// CHECK:STDOUT:     inst_block78000042:\n// CHECK:STDOUT:       0:               inst780000C6\n// CHECK:STDOUT:       1:               inst780000C4\n// CHECK:STDOUT:     inst_block78000043:\n// CHECK:STDOUT:       0:               inst780000C6\n// CHECK:STDOUT:     inst_block78000044:\n// CHECK:STDOUT:       0:               inst780000C4\n// CHECK:STDOUT:     inst_block78000045:\n// CHECK:STDOUT:       0:               inst780000CA\n// CHECK:STDOUT:     inst_block78000046:\n// CHECK:STDOUT:       0:               inst780000CB\n// CHECK:STDOUT:       1:               inst780000CC\n// CHECK:STDOUT:       2:               inst780000CD\n// CHECK:STDOUT:       3:               inst780000CE\n// CHECK:STDOUT:     inst_block78000047:\n// CHECK:STDOUT:       0:               inst78000018\n// CHECK:STDOUT:       1:               inst7800001D\n// CHECK:STDOUT:       2:               inst7800001F\n// CHECK:STDOUT:       3:               inst780000C7\n// CHECK:STDOUT:     inst_block78000048:\n// CHECK:STDOUT:       0:               inst780000BD\n// CHECK:STDOUT:     inst_block78000049:\n// CHECK:STDOUT:       0:               inst780000CF\n// CHECK:STDOUT:       1:               inst780000D0\n// CHECK:STDOUT:       2:               inst780000D1\n// CHECK:STDOUT:     inst_block7800004A:\n// CHECK:STDOUT:       0:               inst78000072\n// CHECK:STDOUT:       1:               inst780000DD\n// CHECK:STDOUT:     inst_block7800004B:\n// CHECK:STDOUT:       0:               inst780000DF\n// CHECK:STDOUT:     inst_block7800004C:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst780000DC\n// CHECK:STDOUT:     inst_block7800004D:\n// CHECK:STDOUT:       0:               inst78000050\n// CHECK:STDOUT:       1:               inst78000050\n// CHECK:STDOUT:     inst_block7800004E:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst780000DC\n// CHECK:STDOUT:       2:               inst780000E6\n// CHECK:STDOUT:       3:               inst78000072\n// CHECK:STDOUT:       4:               inst780000DD\n// CHECK:STDOUT:       5:               inst780000DE\n// CHECK:STDOUT:       6:               inst780000E1\n// CHECK:STDOUT:     inst_block7800004F:\n// CHECK:STDOUT:       0:               inst780000E3\n// CHECK:STDOUT:       1:               inst780000E4\n// CHECK:STDOUT:     inst_block78000050:\n// CHECK:STDOUT:       0:               inst780000EB\n// CHECK:STDOUT:       1:               inst780000E9\n// CHECK:STDOUT:     inst_block78000051:\n// CHECK:STDOUT:       0:               inst780000EB\n// CHECK:STDOUT:     inst_block78000052:\n// CHECK:STDOUT:       0:               inst780000E9\n// CHECK:STDOUT:     inst_block78000053:\n// CHECK:STDOUT:       0:               inst780000EF\n// CHECK:STDOUT:       1:               inst780000F0\n// CHECK:STDOUT:     inst_block78000054:\n// CHECK:STDOUT:       0:               inst780000F2\n// CHECK:STDOUT:       1:               inst780000F4\n// CHECK:STDOUT:     inst_block78000055:\n// CHECK:STDOUT:       0:               inst780000F1\n// CHECK:STDOUT:       1:               inst780000F2\n// CHECK:STDOUT:       2:               inst780000F3\n// CHECK:STDOUT:       3:               inst780000F4\n// CHECK:STDOUT:       4:               inst780000F5\n// CHECK:STDOUT:       5:               inst780000F6\n// CHECK:STDOUT:       6:               inst780000F7\n// CHECK:STDOUT:     inst_block78000056:\n// CHECK:STDOUT:       0:               inst780000DC\n// CHECK:STDOUT:     inst_block78000057:\n// CHECK:STDOUT:       0:               inst780000DC\n// CHECK:STDOUT:       1:               inst780000F9\n// CHECK:STDOUT:       2:               inst780000FA\n// CHECK:STDOUT:     inst_block78000058:\n// CHECK:STDOUT:       0:               inst780000DC\n// CHECK:STDOUT:       1:               inst780000DD\n// CHECK:STDOUT:       2:               inst780000FF\n// CHECK:STDOUT:       3:               inst780000FE\n// CHECK:STDOUT:     inst_block78000059:\n// CHECK:STDOUT:       0:               inst780000F1\n// CHECK:STDOUT:     inst_block7800005A:\n// CHECK:STDOUT:       0:               inst780000F1\n// CHECK:STDOUT:     inst_block7800005B:\n// CHECK:STDOUT:       0:               inst780000F3\n// CHECK:STDOUT:     inst_block7800005C:\n// CHECK:STDOUT:       0:               inst780000F3\n// CHECK:STDOUT:     inst_block7800005D:\n// CHECK:STDOUT:       0:               inst78000102\n// CHECK:STDOUT:       1:               inst78000103\n// CHECK:STDOUT:       2:               inst78000104\n// CHECK:STDOUT:       3:               inst78000105\n// CHECK:STDOUT:       4:               inst78000106\n// CHECK:STDOUT:       5:               inst78000107\n// CHECK:STDOUT:       6:               inst78000108\n// CHECK:STDOUT:       7:               inst78000109\n// CHECK:STDOUT:       8:               inst7800010A\n// CHECK:STDOUT:       9:               inst7800010B\n// CHECK:STDOUT:       10:              inst7800010C\n// CHECK:STDOUT:       11:              inst7800010D\n// CHECK:STDOUT:       12:              inst7800010E\n// CHECK:STDOUT:     inst_block7800005E:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst78000072\n// CHECK:STDOUT:       2:               inst780000DC\n// CHECK:STDOUT:       3:               inst780000DD\n// CHECK:STDOUT:       4:               inst780000DE\n// CHECK:STDOUT:       5:               inst780000E7\n// CHECK:STDOUT:       6:               inst780000EC\n// CHECK:STDOUT:     inst_block7800005F:\n// CHECK:STDOUT:       0:               inst78000110\n// CHECK:STDOUT:       1:               inst7800010F\n// CHECK:STDOUT:     inst_block78000060:\n// CHECK:STDOUT:       0:               inst78000113\n// CHECK:STDOUT:       1:               inst78000114\n// CHECK:STDOUT:     inst_block78000061:\n// CHECK:STDOUT:       0:               inst78000115\n// CHECK:STDOUT:       1:               inst78000116\n// CHECK:STDOUT:     inst_block78000062:\n// CHECK:STDOUT:       0:               inst78000118\n// CHECK:STDOUT:       1:               inst78000119\n// CHECK:STDOUT:     inst_block78000063:\n// CHECK:STDOUT:       0:               inst78000115\n// CHECK:STDOUT:       1:               inst78000116\n// CHECK:STDOUT:     inst_block78000064:\n// CHECK:STDOUT:       0:               inst78000115\n// CHECK:STDOUT:       1:               inst78000116\n// CHECK:STDOUT:       2:               inst78000117\n// CHECK:STDOUT:       3:               inst78000118\n// CHECK:STDOUT:       4:               inst78000119\n// CHECK:STDOUT:       5:               inst7800011A\n// CHECK:STDOUT:       6:               inst7800011B\n// CHECK:STDOUT:     inst_block78000065:\n// CHECK:STDOUT:       0:               inst78000115\n// CHECK:STDOUT:       1:               inst78000116\n// CHECK:STDOUT:     inst_block78000066:\n// CHECK:STDOUT:       0:               inst7800011C\n// CHECK:STDOUT:       1:               inst7800011D\n// CHECK:STDOUT:     inst_block78000067:\n// CHECK:STDOUT:       0:               inst78000072\n// CHECK:STDOUT:       1:               inst780000DD\n// CHECK:STDOUT:       2:               inst78000121\n// CHECK:STDOUT:     inst_block78000068:\n// CHECK:STDOUT:       0:               inst78000123\n// CHECK:STDOUT:     inst_block78000069:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst780000DC\n// CHECK:STDOUT:       2:               inst78000120\n// CHECK:STDOUT:     inst_block7800006A:\n// CHECK:STDOUT:       0:               inst78000050\n// CHECK:STDOUT:       1:               inst78000050\n// CHECK:STDOUT:       2:               inst78000050\n// CHECK:STDOUT:     inst_block7800006B:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst780000DC\n// CHECK:STDOUT:       2:               inst78000120\n// CHECK:STDOUT:       3:               inst7800012A\n// CHECK:STDOUT:       4:               inst78000072\n// CHECK:STDOUT:       5:               inst780000DD\n// CHECK:STDOUT:       6:               inst78000121\n// CHECK:STDOUT:       7:               inst78000122\n// CHECK:STDOUT:       8:               inst78000125\n// CHECK:STDOUT:     inst_block7800006C:\n// CHECK:STDOUT:       0:               inst78000127\n// CHECK:STDOUT:       1:               inst78000128\n// CHECK:STDOUT:     inst_block7800006D:\n// CHECK:STDOUT:       0:               inst7800012F\n// CHECK:STDOUT:       1:               inst7800012D\n// CHECK:STDOUT:     inst_block7800006E:\n// CHECK:STDOUT:       0:               inst7800012F\n// CHECK:STDOUT:     inst_block7800006F:\n// CHECK:STDOUT:       0:               inst7800012D\n// CHECK:STDOUT:     inst_block78000070:\n// CHECK:STDOUT:       0:               inst78000133\n// CHECK:STDOUT:       1:               inst78000134\n// CHECK:STDOUT:       2:               inst78000135\n// CHECK:STDOUT:     inst_block78000071:\n// CHECK:STDOUT:       0:               inst78000137\n// CHECK:STDOUT:       1:               inst78000139\n// CHECK:STDOUT:       2:               inst7800013B\n// CHECK:STDOUT:     inst_block78000072:\n// CHECK:STDOUT:       0:               inst78000136\n// CHECK:STDOUT:       1:               inst78000137\n// CHECK:STDOUT:       2:               inst78000138\n// CHECK:STDOUT:       3:               inst78000139\n// CHECK:STDOUT:       4:               inst7800013A\n// CHECK:STDOUT:       5:               inst7800013B\n// CHECK:STDOUT:       6:               inst7800013C\n// CHECK:STDOUT:       7:               inst7800013D\n// CHECK:STDOUT:       8:               inst7800013E\n// CHECK:STDOUT:     inst_block78000073:\n// CHECK:STDOUT:       0:               inst78000120\n// CHECK:STDOUT:     inst_block78000074:\n// CHECK:STDOUT:       0:               inst78000120\n// CHECK:STDOUT:       1:               inst78000140\n// CHECK:STDOUT:       2:               inst78000141\n// CHECK:STDOUT:     inst_block78000075:\n// CHECK:STDOUT:       0:               inst78000120\n// CHECK:STDOUT:       1:               inst78000121\n// CHECK:STDOUT:       2:               inst78000146\n// CHECK:STDOUT:       3:               inst78000145\n// CHECK:STDOUT:     inst_block78000076:\n// CHECK:STDOUT:       0:               inst78000136\n// CHECK:STDOUT:     inst_block78000077:\n// CHECK:STDOUT:       0:               inst78000136\n// CHECK:STDOUT:     inst_block78000078:\n// CHECK:STDOUT:       0:               inst78000138\n// CHECK:STDOUT:     inst_block78000079:\n// CHECK:STDOUT:       0:               inst78000138\n// CHECK:STDOUT:     inst_block7800007A:\n// CHECK:STDOUT:       0:               inst7800013A\n// CHECK:STDOUT:     inst_block7800007B:\n// CHECK:STDOUT:       0:               inst7800013A\n// CHECK:STDOUT:     inst_block7800007C:\n// CHECK:STDOUT:       0:               inst78000149\n// CHECK:STDOUT:       1:               inst7800014A\n// CHECK:STDOUT:       2:               inst7800014B\n// CHECK:STDOUT:       3:               inst7800014C\n// CHECK:STDOUT:       4:               inst7800014D\n// CHECK:STDOUT:       5:               inst7800014E\n// CHECK:STDOUT:       6:               inst7800014F\n// CHECK:STDOUT:       7:               inst78000150\n// CHECK:STDOUT:       8:               inst78000151\n// CHECK:STDOUT:       9:               inst78000152\n// CHECK:STDOUT:       10:              inst78000153\n// CHECK:STDOUT:       11:              inst78000154\n// CHECK:STDOUT:       12:              inst78000155\n// CHECK:STDOUT:       13:              inst78000156\n// CHECK:STDOUT:       14:              inst78000157\n// CHECK:STDOUT:       15:              inst78000158\n// CHECK:STDOUT:       16:              inst78000159\n// CHECK:STDOUT:       17:              inst7800015A\n// CHECK:STDOUT:       18:              inst7800015B\n// CHECK:STDOUT:     inst_block7800007D:\n// CHECK:STDOUT:       0:               inst78000071\n// CHECK:STDOUT:       1:               inst78000072\n// CHECK:STDOUT:       2:               inst780000DC\n// CHECK:STDOUT:       3:               inst780000DD\n// CHECK:STDOUT:       4:               inst78000120\n// CHECK:STDOUT:       5:               inst78000121\n// CHECK:STDOUT:       6:               inst78000122\n// CHECK:STDOUT:       7:               inst7800012B\n// CHECK:STDOUT:       8:               inst78000130\n// CHECK:STDOUT:     inst_block7800007E:\n// CHECK:STDOUT:       0:               inst7800015E\n// CHECK:STDOUT:       1:               inst7800015D\n// CHECK:STDOUT:       2:               inst7800015C\n// CHECK:STDOUT:     inst_block7800007F:\n// CHECK:STDOUT:       0:               inst78000161\n// CHECK:STDOUT:       1:               inst78000162\n// CHECK:STDOUT:       2:               inst78000163\n// CHECK:STDOUT:     inst_block78000080:\n// CHECK:STDOUT:       0:               inst78000164\n// CHECK:STDOUT:       1:               inst78000165\n// CHECK:STDOUT:       2:               inst78000166\n// CHECK:STDOUT:     inst_block78000081:\n// CHECK:STDOUT:       0:               inst78000168\n// CHECK:STDOUT:       1:               inst78000169\n// CHECK:STDOUT:       2:               inst7800016A\n// CHECK:STDOUT:     inst_block78000082:\n// CHECK:STDOUT:       0:               inst78000164\n// CHECK:STDOUT:       1:               inst78000165\n// CHECK:STDOUT:       2:               inst78000166\n// CHECK:STDOUT:     inst_block78000083:\n// CHECK:STDOUT:       0:               inst78000164\n// CHECK:STDOUT:       1:               inst78000165\n// CHECK:STDOUT:       2:               inst78000166\n// CHECK:STDOUT:       3:               inst78000167\n// CHECK:STDOUT:       4:               inst78000168\n// CHECK:STDOUT:       5:               inst78000169\n// CHECK:STDOUT:       6:               inst7800016A\n// CHECK:STDOUT:       7:               inst7800016B\n// CHECK:STDOUT:       8:               inst7800016C\n// CHECK:STDOUT:     inst_block78000084:\n// CHECK:STDOUT:       0:               inst78000164\n// CHECK:STDOUT:       1:               inst78000165\n// CHECK:STDOUT:       2:               inst78000166\n// CHECK:STDOUT:     inst_block78000085:\n// CHECK:STDOUT:       0:               inst7800016D\n// CHECK:STDOUT:       1:               inst7800016E\n// CHECK:STDOUT:     inst_block78000086:\n// CHECK:STDOUT:       0:               inst780000C1\n// CHECK:STDOUT:       1:               inst780000C2\n// CHECK:STDOUT:       2:               inst78000042\n// CHECK:STDOUT:     inst_block78000087:\n// CHECK:STDOUT:       0:               inst78000019\n// CHECK:STDOUT:     inst_block78000088:\n// CHECK:STDOUT:       0:               inst78000172\n// CHECK:STDOUT:     inst_block78000089:\n// CHECK:STDOUT:       0:               inst78000174\n// CHECK:STDOUT:     inst_block7800008A:\n// CHECK:STDOUT:       0:               inst78000174\n// CHECK:STDOUT:       1:               inst78000175\n// CHECK:STDOUT:       2:               inst78000176\n// CHECK:STDOUT:     inst_block7800008B:\n// CHECK:STDOUT:       0:               inst78000173\n// CHECK:STDOUT:     inst_block7800008C:\n// CHECK:STDOUT:       0:               inst7800017A\n// CHECK:STDOUT:     inst_block7800008D:\n// CHECK:STDOUT:       0:               inst78000174\n// CHECK:STDOUT:       1:               inst7800001D\n// CHECK:STDOUT:       2:               inst7800001F\n// CHECK:STDOUT:       3:               inst780000C7\n// CHECK:STDOUT:     inst_block7800008E:\n// CHECK:STDOUT:       0:               inst7800017A\n// CHECK:STDOUT:     inst_block7800008F:\n// CHECK:STDOUT:       0:               inst78000048\n// CHECK:STDOUT:     inst_block78000090:\n// CHECK:STDOUT:       0:               inst78000184\n// CHECK:STDOUT:       1:               inst78000187\n// CHECK:STDOUT:     inst_block78000091:\n// CHECK:STDOUT:       0:               inst78000043\n// CHECK:STDOUT:       1:               inst78000047\n// CHECK:STDOUT:       2:               inst78000171\n// CHECK:STDOUT:       3:               inst78000173\n// CHECK:STDOUT:       4:               inst7800017A\n// CHECK:STDOUT:       5:               inst7800017B\n// CHECK:STDOUT:       6:               inst7800017C\n// CHECK:STDOUT:       7:               inst7800017D\n// CHECK:STDOUT:       8:               inst78000181\n// CHECK:STDOUT:     inst_block78000092:\n// CHECK:STDOUT:       0:               instF\n// CHECK:STDOUT:       1:               inst78000010\n// CHECK:STDOUT:       2:               inst7800003E\n// CHECK:STDOUT:   value_stores:\n// CHECK:STDOUT:     shared_values:\n// CHECK:STDOUT:       ints:            {}\n// CHECK:STDOUT:       reals:           {}\n// CHECK:STDOUT:       floats:          {}\n// CHECK:STDOUT:       identifiers:\n// CHECK:STDOUT:         identifier0:     Foo\n// CHECK:STDOUT:         identifier1:     T\n// CHECK:STDOUT:         identifier2:     p\n// CHECK:STDOUT:         identifier3:     Copy\n// CHECK:STDOUT:         identifier4:     Op\n// CHECK:STDOUT:         identifier5:     U\n// CHECK:STDOUT:         identifier6:     V\n// CHECK:STDOUT:       strings:\n// CHECK:STDOUT:         string0:         prelude\n// CHECK:STDOUT: ...\n"
  },
  {
    "path": "toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// EXTRA-ARGS: --dump-raw-sem-ir --dump-sem-ir-ranges=if-present\n//\n// Check that we can combine textual IR and raw IR dumping in one compile.\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/raw_sem_ir/one_file_with_textual_ir.carbon\n\nfn Foo(n: ()) -> ((), ()) {\n  return (n, ());\n}\n\n// CHECK:STDOUT: ---\n// CHECK:STDOUT: filename:        one_file_with_textual_ir.carbon\n// CHECK:STDOUT: sem_ir:\n// CHECK:STDOUT:   names:\n// CHECK:STDOUT:     name0:           Foo\n// CHECK:STDOUT:     name1:           n\n// CHECK:STDOUT:   import_irs:\n// CHECK:STDOUT:     'import_ir(ApiForImpl)': {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:     'import_ir(Cpp)':  {decl_id: inst<none>, is_export: false}\n// CHECK:STDOUT:   import_ir_insts: {}\n// CHECK:STDOUT:   clang_decls:     {}\n// CHECK:STDOUT:   name_scopes:\n// CHECK:STDOUT:     name_scope0:     {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst5000002A}}\n// CHECK:STDOUT:   entity_names:\n// CHECK:STDOUT:     entity_name50000000: {name: name1, parent_scope: name_scope<none>, index: -1, is_template: 0, is_unused: 0, form: constant<none>}\n// CHECK:STDOUT:   cpp_global_vars: {}\n// CHECK:STDOUT:   functions:\n// CHECK:STDOUT:     function50000000: {name: name0, parent_scope: name_scope0, call_param_patterns_id: inst_block5000000C, call_params_id: inst_block5000000D, return_type_inst_id: inst50000020, return_form_inst_id: inst50000021, return_patterns_id: inst_block5000000B, body: [inst_block50000010]}\n// CHECK:STDOUT:   classes:         {}\n// CHECK:STDOUT:   interfaces:      {}\n// CHECK:STDOUT:   associated_constants: {}\n// CHECK:STDOUT:   impls:           {}\n// CHECK:STDOUT:   generics:        {}\n// CHECK:STDOUT:   specifics:       {}\n// CHECK:STDOUT:   specific_interfaces: {}\n// CHECK:STDOUT:   struct_type_fields:\n// CHECK:STDOUT:     struct_type_fields_empty: {}\n// CHECK:STDOUT:   types:\n// CHECK:STDOUT:     'type(TypeType)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(TypeType)}\n// CHECK:STDOUT:     'type(inst(FormType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(FormType))}\n// CHECK:STDOUT:     'type(Error)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(Error)}\n// CHECK:STDOUT:     'type(inst(NamespaceType))':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     'type(inst50000010)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000010)}\n// CHECK:STDOUT:     'type(inst5000001D)':\n// CHECK:STDOUT:       value_repr:      {kind: copy, type: type(inst5000001D)}\n// CHECK:STDOUT:     'type(inst5000001A)':\n// CHECK:STDOUT:       value_repr:      {kind: pointer, type: type(inst5000001D)}\n// CHECK:STDOUT:     'type(inst5000002B)':\n// CHECK:STDOUT:       value_repr:      {kind: none, type: type(inst50000010)}\n// CHECK:STDOUT:   facet_types:     {}\n// CHECK:STDOUT:   insts:\n// CHECK:STDOUT:     instF:           {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}\n// CHECK:STDOUT:     inst50000010:    {kind: TupleType, arg0: inst_block_empty, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000011:    {kind: TupleLiteral, arg0: inst_block_empty, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000012:    {kind: TupleValue, arg0: inst_block_empty, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000013:    {kind: Converted, arg0: inst50000011, arg1: inst50000010, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000014:    {kind: PatternType, arg0: inst50000010, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000015:    {kind: ValueBinding, arg0: entity_name50000000, arg1: inst50000026, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000016:    {kind: ValueBindingPattern, arg0: entity_name50000000, type: type(inst50000014)}\n// CHECK:STDOUT:     inst50000017:    {kind: ValueParamPattern, arg0: inst50000016, type: type(inst50000014)}\n// CHECK:STDOUT:     inst50000018:    {kind: TupleLiteral, arg0: inst_block_empty, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000019:    {kind: TupleLiteral, arg0: inst_block_empty, type: type(inst50000010)}\n// CHECK:STDOUT:     inst5000001A:    {kind: TupleType, arg0: inst_block50000008, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000001B:    {kind: TupleLiteral, arg0: inst_block50000007, type: type(inst5000001A)}\n// CHECK:STDOUT:     inst5000001C:    {kind: TupleValue, arg0: inst_block50000009, type: type(inst5000001A)}\n// CHECK:STDOUT:     inst5000001D:    {kind: PointerType, arg0: inst5000001A, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000001E:    {kind: Converted, arg0: inst50000012, arg1: inst50000010, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000001F:    {kind: Converted, arg0: inst50000012, arg1: inst50000010, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000020:    {kind: Converted, arg0: inst5000001B, arg1: inst5000001A, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000021:    {kind: InitForm, arg0: inst50000020, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst50000022:    {kind: InitForm, arg0: inst5000001A, type: type(inst(FormType))}\n// CHECK:STDOUT:     inst50000023:    {kind: PatternType, arg0: inst5000001A, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000024:    {kind: ReturnSlotPattern, arg0: inst50000020, type: type(inst50000023)}\n// CHECK:STDOUT:     inst50000025:    {kind: OutParamPattern, arg0: inst50000024, type: type(inst50000023)}\n// CHECK:STDOUT:     inst50000026:    {kind: ValueParam, arg0: call_param0, arg1: name1, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000027:    {kind: SpliceBlock, arg0: inst_block50000005, arg1: inst50000013, type: type(TypeType)}\n// CHECK:STDOUT:     inst50000028:    {kind: OutParam, arg0: call_param1, arg1: name(ReturnSlot), type: type(inst5000001A)}\n// CHECK:STDOUT:     inst50000029:    {kind: ReturnSlot, arg0: inst5000001A, arg1: inst50000028, type: type(inst5000001A)}\n// CHECK:STDOUT:     inst5000002A:    {kind: FunctionDecl, arg0: function50000000, arg1: inst_block5000000F, type: type(inst5000002B)}\n// CHECK:STDOUT:     inst5000002B:    {kind: FunctionType, arg0: function50000000, arg1: specific<none>, type: type(TypeType)}\n// CHECK:STDOUT:     inst5000002C:    {kind: StructValue, arg0: inst_block_empty, type: type(inst5000002B)}\n// CHECK:STDOUT:     inst5000002D:    {kind: NameRef, arg0: name1, arg1: inst50000015, type: type(inst50000010)}\n// CHECK:STDOUT:     inst5000002E:    {kind: TupleLiteral, arg0: inst_block_empty, type: type(inst50000010)}\n// CHECK:STDOUT:     inst5000002F:    {kind: TupleLiteral, arg0: inst_block50000011, type: type(inst5000001A)}\n// CHECK:STDOUT:     inst50000030:    {kind: TupleAccess, arg0: inst50000028, arg1: element0, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000031:    {kind: TupleInit, arg0: inst_block50000012, arg1: inst<none>, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000032:    {kind: Converted, arg0: inst5000002D, arg1: inst50000031, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000033:    {kind: TupleAccess, arg0: inst50000028, arg1: element1, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000034:    {kind: TupleInit, arg0: inst_block_empty, arg1: inst<none>, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000035:    {kind: Converted, arg0: inst5000002E, arg1: inst50000034, type: type(inst50000010)}\n// CHECK:STDOUT:     inst50000036:    {kind: TupleInit, arg0: inst_block50000013, arg1: inst50000028, type: type(inst5000001A)}\n// CHECK:STDOUT:     inst50000037:    {kind: Converted, arg0: inst5000002F, arg1: inst50000036, type: type(inst5000001A)}\n// CHECK:STDOUT:     inst50000038:    {kind: ReturnExpr, arg0: inst50000037, arg1: inst50000028}\n// CHECK:STDOUT:   constant_values:\n// CHECK:STDOUT:     values:\n// CHECK:STDOUT:       instF:           concrete_constant(instF)\n// CHECK:STDOUT:       inst50000010:    concrete_constant(inst50000010)\n// CHECK:STDOUT:       inst50000011:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000012:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000013:    concrete_constant(inst50000010)\n// CHECK:STDOUT:       inst50000014:    concrete_constant(inst50000014)\n// CHECK:STDOUT:       inst50000016:    concrete_constant(inst50000016)\n// CHECK:STDOUT:       inst50000017:    concrete_constant(inst50000017)\n// CHECK:STDOUT:       inst50000018:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000019:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst5000001A:    concrete_constant(inst5000001A)\n// CHECK:STDOUT:       inst5000001B:    concrete_constant(inst5000001C)\n// CHECK:STDOUT:       inst5000001C:    concrete_constant(inst5000001C)\n// CHECK:STDOUT:       inst5000001D:    concrete_constant(inst5000001D)\n// CHECK:STDOUT:       inst5000001E:    concrete_constant(inst50000010)\n// CHECK:STDOUT:       inst5000001F:    concrete_constant(inst50000010)\n// CHECK:STDOUT:       inst50000020:    concrete_constant(inst5000001A)\n// CHECK:STDOUT:       inst50000021:    concrete_constant(inst50000022)\n// CHECK:STDOUT:       inst50000022:    concrete_constant(inst50000022)\n// CHECK:STDOUT:       inst50000023:    concrete_constant(inst50000023)\n// CHECK:STDOUT:       inst50000024:    concrete_constant(inst50000024)\n// CHECK:STDOUT:       inst50000025:    concrete_constant(inst50000025)\n// CHECK:STDOUT:       inst50000027:    concrete_constant(inst50000010)\n// CHECK:STDOUT:       inst5000002A:    concrete_constant(inst5000002C)\n// CHECK:STDOUT:       inst5000002B:    concrete_constant(inst5000002B)\n// CHECK:STDOUT:       inst5000002C:    concrete_constant(inst5000002C)\n// CHECK:STDOUT:       inst5000002E:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000031:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000032:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000034:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000035:    concrete_constant(inst50000012)\n// CHECK:STDOUT:       inst50000036:    concrete_constant(inst5000001C)\n// CHECK:STDOUT:       inst50000037:    concrete_constant(inst5000001C)\n// CHECK:STDOUT:     symbolic_constants: {}\n// CHECK:STDOUT:   inst_blocks:\n// CHECK:STDOUT:     inst_block_empty: {}\n// CHECK:STDOUT:     exports:\n// CHECK:STDOUT:       0:               inst5000002A\n// CHECK:STDOUT:     generated:       {}\n// CHECK:STDOUT:     imports:         {}\n// CHECK:STDOUT:     global_init:     {}\n// CHECK:STDOUT:     inst_block50000005:\n// CHECK:STDOUT:       0:               inst50000011\n// CHECK:STDOUT:       1:               inst50000013\n// CHECK:STDOUT:     inst_block50000006:\n// CHECK:STDOUT:       0:               inst50000017\n// CHECK:STDOUT:     inst_block50000007:\n// CHECK:STDOUT:       0:               inst50000018\n// CHECK:STDOUT:       1:               inst50000019\n// CHECK:STDOUT:     inst_block50000008:\n// CHECK:STDOUT:       0:               inst50000010\n// CHECK:STDOUT:       1:               inst50000010\n// CHECK:STDOUT:     inst_block50000009:\n// CHECK:STDOUT:       0:               inst50000012\n// CHECK:STDOUT:       1:               inst50000012\n// CHECK:STDOUT:     inst_block5000000A:\n// CHECK:STDOUT:       0:               inst5000001E\n// CHECK:STDOUT:       1:               inst5000001F\n// CHECK:STDOUT:     inst_block5000000B:\n// CHECK:STDOUT:       0:               inst50000025\n// CHECK:STDOUT:     inst_block5000000C:\n// CHECK:STDOUT:       0:               inst50000017\n// CHECK:STDOUT:       1:               inst50000025\n// CHECK:STDOUT:     inst_block5000000D:\n// CHECK:STDOUT:       0:               inst50000026\n// CHECK:STDOUT:       1:               inst50000028\n// CHECK:STDOUT:     inst_block5000000E:\n// CHECK:STDOUT:       0:               inst50000016\n// CHECK:STDOUT:       1:               inst50000017\n// CHECK:STDOUT:       2:               inst50000024\n// CHECK:STDOUT:       3:               inst50000025\n// CHECK:STDOUT:     inst_block5000000F:\n// CHECK:STDOUT:       0:               inst50000018\n// CHECK:STDOUT:       1:               inst50000019\n// CHECK:STDOUT:       2:               inst5000001B\n// CHECK:STDOUT:       3:               inst5000001E\n// CHECK:STDOUT:       4:               inst5000001F\n// CHECK:STDOUT:       5:               inst50000020\n// CHECK:STDOUT:       6:               inst50000021\n// CHECK:STDOUT:       7:               inst50000026\n// CHECK:STDOUT:       8:               inst50000027\n// CHECK:STDOUT:       9:               inst50000015\n// CHECK:STDOUT:       10:              inst50000028\n// CHECK:STDOUT:       11:              inst50000029\n// CHECK:STDOUT:     inst_block50000010:\n// CHECK:STDOUT:       0:               inst5000002D\n// CHECK:STDOUT:       1:               inst5000002E\n// CHECK:STDOUT:       2:               inst5000002F\n// CHECK:STDOUT:       3:               inst50000030\n// CHECK:STDOUT:       4:               inst50000031\n// CHECK:STDOUT:       5:               inst50000032\n// CHECK:STDOUT:       6:               inst50000033\n// CHECK:STDOUT:       7:               inst50000034\n// CHECK:STDOUT:       8:               inst50000035\n// CHECK:STDOUT:       9:               inst50000036\n// CHECK:STDOUT:       10:              inst50000037\n// CHECK:STDOUT:       11:              inst50000038\n// CHECK:STDOUT:     inst_block50000011:\n// CHECK:STDOUT:       0:               inst5000002D\n// CHECK:STDOUT:       1:               inst5000002E\n// CHECK:STDOUT:     inst_block50000012: {}\n// CHECK:STDOUT:     inst_block50000013:\n// CHECK:STDOUT:       0:               inst50000032\n// CHECK:STDOUT:       1:               inst50000035\n// CHECK:STDOUT:     inst_block50000014:\n// CHECK:STDOUT:       0:               instF\n// CHECK:STDOUT:       1:               inst5000002A\n// CHECK:STDOUT:   value_stores:\n// CHECK:STDOUT:     shared_values:\n// CHECK:STDOUT:       ints:            {}\n// CHECK:STDOUT:       reals:           {}\n// CHECK:STDOUT:       floats:          {}\n// CHECK:STDOUT:       identifiers:\n// CHECK:STDOUT:         identifier0:     Foo\n// CHECK:STDOUT:         identifier1:     n\n// CHECK:STDOUT:       strings:         {}\n// CHECK:STDOUT: ...\n// CHECK:STDOUT: --- one_file_with_textual_ir.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_tuple.type, %empty_tuple.type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type = tuple_value (%empty_tuple, %empty_tuple) [concrete]\n// CHECK:STDOUT:   %.e3a: Core.Form = init_form %tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.5b8: type = pattern_type %tuple.type [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.cb1 = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.cb1 = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.5b8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.5b8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc16_20: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc16_24: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc16_25.1: %tuple.type = tuple_literal (%.loc16_20, %.loc16_24) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc16_25.2: type = converted constants.%empty_tuple, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc16_25.3: type = converted constants.%empty_tuple, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc16_25.4: type = converted %.loc16_25.1, constants.%tuple.type [concrete = constants.%tuple.type]\n// CHECK:STDOUT:     %.loc16_25.5: Core.Form = init_form %.loc16_25.4 [concrete = constants.%.e3a]\n// CHECK:STDOUT:     %n.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc16_12.1: type = splice_block %.loc16_12.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc16_12.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc16_12.3: type = converted %.loc16_12.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %n: %empty_tuple.type = value_binding n, %n.param\n// CHECK:STDOUT:     %return.param: ref %tuple.type = out_param call_param1\n// CHECK:STDOUT:     %return: ref %tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%n.param: %empty_tuple.type) -> out %return.param: %tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %empty_tuple.type = name_ref n, %n\n// CHECK:STDOUT:   %.loc17_15.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc17_16.1: %tuple.type = tuple_literal (%n.ref, %.loc17_15.1)\n// CHECK:STDOUT:   %tuple.elem0: ref %empty_tuple.type = tuple_access %return.param, element0\n// CHECK:STDOUT:   %.loc17_11: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc17_16.2: init %empty_tuple.type = converted %n.ref, %.loc17_11 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %tuple.elem1: ref %empty_tuple.type = tuple_access %return.param, element1\n// CHECK:STDOUT:   %.loc17_15.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc17_16.3: init %empty_tuple.type = converted %.loc17_15.1, %.loc17_15.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc17_16.4: init %tuple.type to %return.param = tuple_init (%.loc17_16.2, %.loc17_16.3) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %.loc17_17: init %tuple.type = converted %.loc17_16.1, %.loc17_16.4 [concrete = constants.%tuple]\n// CHECK:STDOUT:   return %.loc17_17 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/basics/verbose.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// ARGS: -v compile --phase=check %s\n//\n// Only checks a couple statements in order to minimize manual update churn.\n// To test this file alone, run:\n//   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/basics/verbose.carbon\n// To dump output, run:\n//   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/basics/verbose.carbon\n// NOAUTOUPDATE\n// SET-CHECK-SUBSET\n// CHECK:STDERR: Node Push 0: FunctionIntroducer -> <none>\n// CHECK:STDERR: AddPlaceholderInst: {kind: FunctionDecl, arg0: function<none>, arg1: inst_block_empty}\n// CHECK:STDERR: ReplaceInst: inst{{[0-9A-F]+}} -> {kind: FunctionDecl, arg0: function{{[0-9A-F]+}}, arg1: inst_block_empty, type: type(inst{{[0-9A-F]+}})}\n// CHECK:STDERR: inst_block_stack_ Push 1\n// CHECK:STDERR: AddInst: {kind: Return}\n// CHECK:STDERR: inst_block_stack_ Pop 1: inst_block{{[0-9]+}}\n\nfn Foo() {\n  return;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/bool/eq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/bool/eq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/bool/eq.carbon\n\n// --- builtin_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Eq(a: bool, b: bool) -> bool = \"bool.eq\";\n\nclass C(B:! bool) {}\n\nfn True() -> C(true);\nfn False() -> C(false);\n\n//@dump-sem-ir-begin\nvar a: C(Eq(true, true)) = True();\n//@dump-sem-ir-end\nvar b: C(Eq(true, false)) = False();\nvar c: C(Eq(false, true)) = False();\nvar d: C(Eq(false, false)) = True();\n\n// --- prelude.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(B:! bool) {}\n\nfn True() -> C(true);\nfn False() -> C(false);\n\n//@dump-sem-ir-begin\nvar a: C(true == true) = True();\n//@dump-sem-ir-end\nvar b: C(true == false) = False();\nvar c: C(false == true) = False();\nvar d: C(false == false) = True();\n\n// CHECK:STDOUT: --- builtin_call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Eq.type: type = fn_type @Eq [concrete]\n// CHECK:STDOUT:   %Eq: %Eq.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %C.a23: type = class_type @C, @C(%true) [concrete]\n// CHECK:STDOUT:   %pattern_type.a06: type = pattern_type %C.a23 [concrete]\n// CHECK:STDOUT:   %True.type: type = fn_type @True [concrete]\n// CHECK:STDOUT:   %True: %True.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.a06 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.a06 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %C.a23 = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc12_24.1: type = splice_block %C.loc12 [concrete = constants.%C.a23] {\n// CHECK:STDOUT:     %C.ref.loc12: %C.type = name_ref C, %C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %Eq.ref.loc12: %Eq.type = name_ref Eq, %Eq.decl [concrete = constants.%Eq]\n// CHECK:STDOUT:     %true.loc12_13: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %true.loc12_19: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %Eq.call.loc12: init bool = call %Eq.ref.loc12(%true.loc12_13, %true.loc12_19) [concrete = constants.%true]\n// CHECK:STDOUT:     %.loc12_24.2: bool = value_of_initializer %Eq.call.loc12 [concrete = constants.%true]\n// CHECK:STDOUT:     %.loc12_24.3: bool = converted %Eq.call.loc12, %.loc12_24.2 [concrete = constants.%true]\n// CHECK:STDOUT:     %C.loc12: type = class_type @C, @C(constants.%true) [concrete = constants.%C.a23]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %C.a23 = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %True.ref.loc12: %True.type = name_ref True, file.%True.decl [concrete = constants.%True]\n// CHECK:STDOUT:   %.loc12: ref %C.a23 = splice_block file.%a.var [concrete = file.%a.var] {}\n// CHECK:STDOUT:   %True.call.loc12: init %C.a23 to %.loc12 = call %True.ref.loc12()\n// CHECK:STDOUT:   assign file.%a.var, %True.call.loc12\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- prelude.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %C.a23: type = class_type @C, @C(%true) [concrete]\n// CHECK:STDOUT:   %pattern_type.a06: type = pattern_type %C.a23 [concrete]\n// CHECK:STDOUT:   %True.type: type = fn_type @True [concrete]\n// CHECK:STDOUT:   %True: %True.type = struct_value () [concrete]\n// CHECK:STDOUT:   %EqWith.type.863: type = facet_type <@EqWith, @EqWith(bool)> [concrete]\n// CHECK:STDOUT:   %EqWith.impl_witness: <witness> = impl_witness imports.%EqWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %EqWith.facet: %EqWith.type.863 = facet_value bool, (%EqWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %EqWith.WithSelf.Equal.type.8c0: type = fn_type @EqWith.WithSelf.Equal, @EqWith.WithSelf(bool, %EqWith.facet) [concrete]\n// CHECK:STDOUT:   %.483: type = fn_type_with_self_type %EqWith.WithSelf.Equal.type.8c0, %EqWith.facet [concrete]\n// CHECK:STDOUT:   %bool.as.EqWith.impl.Equal.type: type = fn_type @bool.as.EqWith.impl.Equal [concrete]\n// CHECK:STDOUT:   %bool.as.EqWith.impl.Equal: %bool.as.EqWith.impl.Equal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %bool.as.EqWith.impl.Equal.bound.40b: <bound method> = bound_method %true, %bool.as.EqWith.impl.Equal [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.f73: %bool.as.EqWith.impl.Equal.type = import_ref Core//prelude/operators/comparison, loc{{\\d+_\\d+}}, loaded [concrete = constants.%bool.as.EqWith.impl.Equal]\n// CHECK:STDOUT:   %Core.import_ref.115 = import_ref Core//prelude/operators/comparison, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %EqWith.impl_witness_table = impl_witness_table (%Core.import_ref.f73, %Core.import_ref.115), @bool.as.EqWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.a06 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.a06 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %C.a23 = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_22.1: type = splice_block %C.loc10 [concrete = constants.%C.a23] {\n// CHECK:STDOUT:     %C.ref.loc10: %C.type = name_ref C, %C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %true.loc10_10: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %true.loc10_18: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %impl.elem0.loc10: %.483 = impl_witness_access constants.%EqWith.impl_witness, element0 [concrete = constants.%bool.as.EqWith.impl.Equal]\n// CHECK:STDOUT:     %bound_method.loc10: <bound method> = bound_method %true.loc10_10, %impl.elem0.loc10 [concrete = constants.%bool.as.EqWith.impl.Equal.bound.40b]\n// CHECK:STDOUT:     %bool.as.EqWith.impl.Equal.call.loc10: init bool = call %bound_method.loc10(%true.loc10_10, %true.loc10_18) [concrete = constants.%true]\n// CHECK:STDOUT:     %.loc10_22.2: bool = value_of_initializer %bool.as.EqWith.impl.Equal.call.loc10 [concrete = constants.%true]\n// CHECK:STDOUT:     %.loc10_22.3: bool = converted %bool.as.EqWith.impl.Equal.call.loc10, %.loc10_22.2 [concrete = constants.%true]\n// CHECK:STDOUT:     %C.loc10: type = class_type @C, @C(constants.%true) [concrete = constants.%C.a23]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %C.a23 = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %True.ref.loc10: %True.type = name_ref True, file.%True.decl [concrete = constants.%True]\n// CHECK:STDOUT:   %.loc10: ref %C.a23 = splice_block file.%a.var [concrete = file.%a.var] {}\n// CHECK:STDOUT:   %True.call.loc10: init %C.a23 to %.loc10 = call %True.ref.loc10()\n// CHECK:STDOUT:   assign file.%a.var, %True.call.loc10\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/bool/make_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/bool/make_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/bool/make_type.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Bool() -> type = \"bool.make_type\";\n\n// --- use_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n//@dump-sem-ir-begin\nlet b: Bool() = false;\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- use_types.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Bool: %Bool.type = import_ref Main//types, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc7_13.1: type = splice_block %.loc7_13.3 [concrete = bool] {\n// CHECK:STDOUT:     %Bool.ref: %Bool.type = name_ref Bool, imports.%Main.Bool [concrete = constants.%Bool]\n// CHECK:STDOUT:     %Bool.call: init type = call %Bool.ref() [concrete = bool]\n// CHECK:STDOUT:     %.loc7_13.2: type = value_of_initializer %Bool.call [concrete = bool]\n// CHECK:STDOUT:     %.loc7_13.3: type = converted %Bool.call, %.loc7_13.2 [concrete = bool]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: bool = value_binding b, @__global_init.%false\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/bool/neq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/bool/neq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/bool/neq.carbon\n\n// --- builtin_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Neq(a: bool, b: bool) -> bool = \"bool.neq\";\n\nclass C(B:! bool) {}\n\nfn True() -> C(true);\nfn False() -> C(false);\n\n//@dump-sem-ir-begin\nvar a: C(Neq(true, true)) = False();\n//@dump-sem-ir-end\nvar b: C(Neq(true, false)) = True();\nvar c: C(Neq(false, true)) = True();\nvar d: C(Neq(false, false)) = False();\n\n// --- prelude.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(B:! bool) {}\n\nfn True() -> C(true);\nfn False() -> C(false);\n\n//@dump-sem-ir-begin\nvar a: C(true != true) = False();\n//@dump-sem-ir-end\nvar b: C(true != false) = True();\nvar c: C(false != true) = True();\nvar d: C(false != false) = False();\n\n// CHECK:STDOUT: --- builtin_call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Neq.type: type = fn_type @Neq [concrete]\n// CHECK:STDOUT:   %Neq: %Neq.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %C.082: type = class_type @C, @C(%false) [concrete]\n// CHECK:STDOUT:   %pattern_type.2a5: type = pattern_type %C.082 [concrete]\n// CHECK:STDOUT:   %False.type: type = fn_type @False [concrete]\n// CHECK:STDOUT:   %False: %False.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.2a5 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.2a5 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %C.082 = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc12_25.1: type = splice_block %C.loc12 [concrete = constants.%C.082] {\n// CHECK:STDOUT:     %C.ref.loc12: %C.type = name_ref C, %C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %Neq.ref.loc12: %Neq.type = name_ref Neq, %Neq.decl [concrete = constants.%Neq]\n// CHECK:STDOUT:     %true.loc12_14: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %true.loc12_20: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %Neq.call.loc12: init bool = call %Neq.ref.loc12(%true.loc12_14, %true.loc12_20) [concrete = constants.%false]\n// CHECK:STDOUT:     %.loc12_25.2: bool = value_of_initializer %Neq.call.loc12 [concrete = constants.%false]\n// CHECK:STDOUT:     %.loc12_25.3: bool = converted %Neq.call.loc12, %.loc12_25.2 [concrete = constants.%false]\n// CHECK:STDOUT:     %C.loc12: type = class_type @C, @C(constants.%false) [concrete = constants.%C.082]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %C.082 = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %False.ref.loc12: %False.type = name_ref False, file.%False.decl [concrete = constants.%False]\n// CHECK:STDOUT:   %.loc12: ref %C.082 = splice_block file.%a.var [concrete = file.%a.var] {}\n// CHECK:STDOUT:   %False.call.loc12: init %C.082 to %.loc12 = call %False.ref.loc12()\n// CHECK:STDOUT:   assign file.%a.var, %False.call.loc12\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- prelude.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %C.082: type = class_type @C, @C(%false) [concrete]\n// CHECK:STDOUT:   %pattern_type.2a5: type = pattern_type %C.082 [concrete]\n// CHECK:STDOUT:   %False.type: type = fn_type @False [concrete]\n// CHECK:STDOUT:   %False: %False.type = struct_value () [concrete]\n// CHECK:STDOUT:   %EqWith.type.863: type = facet_type <@EqWith, @EqWith(bool)> [concrete]\n// CHECK:STDOUT:   %EqWith.impl_witness: <witness> = impl_witness imports.%EqWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %EqWith.facet: %EqWith.type.863 = facet_value bool, (%EqWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %EqWith.WithSelf.NotEqual.type.14c: type = fn_type @EqWith.WithSelf.NotEqual, @EqWith.WithSelf(bool, %EqWith.facet) [concrete]\n// CHECK:STDOUT:   %.d13: type = fn_type_with_self_type %EqWith.WithSelf.NotEqual.type.14c, %EqWith.facet [concrete]\n// CHECK:STDOUT:   %bool.as.EqWith.impl.NotEqual.type: type = fn_type @bool.as.EqWith.impl.NotEqual [concrete]\n// CHECK:STDOUT:   %bool.as.EqWith.impl.NotEqual: %bool.as.EqWith.impl.NotEqual.type = struct_value () [concrete]\n// CHECK:STDOUT:   %bool.as.EqWith.impl.NotEqual.bound.a7d: <bound method> = bound_method %true, %bool.as.EqWith.impl.NotEqual [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.093 = import_ref Core//prelude/operators/comparison, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.fb0: %bool.as.EqWith.impl.NotEqual.type = import_ref Core//prelude/operators/comparison, loc{{\\d+_\\d+}}, loaded [concrete = constants.%bool.as.EqWith.impl.NotEqual]\n// CHECK:STDOUT:   %EqWith.impl_witness_table = impl_witness_table (%Core.import_ref.093, %Core.import_ref.fb0), @bool.as.EqWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.2a5 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.2a5 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %C.082 = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_22.1: type = splice_block %C.loc10 [concrete = constants.%C.082] {\n// CHECK:STDOUT:     %C.ref.loc10: %C.type = name_ref C, %C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %true.loc10_10: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %true.loc10_18: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %impl.elem1.loc10: %.d13 = impl_witness_access constants.%EqWith.impl_witness, element1 [concrete = constants.%bool.as.EqWith.impl.NotEqual]\n// CHECK:STDOUT:     %bound_method.loc10: <bound method> = bound_method %true.loc10_10, %impl.elem1.loc10 [concrete = constants.%bool.as.EqWith.impl.NotEqual.bound.a7d]\n// CHECK:STDOUT:     %bool.as.EqWith.impl.NotEqual.call.loc10: init bool = call %bound_method.loc10(%true.loc10_10, %true.loc10_18) [concrete = constants.%false]\n// CHECK:STDOUT:     %.loc10_22.2: bool = value_of_initializer %bool.as.EqWith.impl.NotEqual.call.loc10 [concrete = constants.%false]\n// CHECK:STDOUT:     %.loc10_22.3: bool = converted %bool.as.EqWith.impl.NotEqual.call.loc10, %.loc10_22.2 [concrete = constants.%false]\n// CHECK:STDOUT:     %C.loc10: type = class_type @C, @C(constants.%false) [concrete = constants.%C.082]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %C.082 = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %False.ref.loc10: %False.type = name_ref False, file.%False.decl [concrete = constants.%False]\n// CHECK:STDOUT:   %.loc10: ref %C.082 = splice_block file.%a.var [concrete = file.%a.var] {}\n// CHECK:STDOUT:   %False.call.loc10: init %C.082 to %.loc10 = call %False.ref.loc10()\n// CHECK:STDOUT:   assign file.%a.var, %False.call.loc10\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/char/convert_checked.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/char/convert_checked.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/char/convert_checked.carbon\n\n// --- builtin.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn CharLiteral() -> type = \"char_literal.make_type\";\nfn IntLiteral() -> type = \"int_literal.make_type\";\nfn UInt(n: IntLiteral()) -> type = \"int.make_type_unsigned\";\n\nfn ToChar(c: CharLiteral()) -> UInt(8) = \"char.convert_checked\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"builtin\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"char.convert_checked\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn ToCharBarResultU16(c: CharLiteral()) -> UInt(16) = \"char.convert_checked\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn ToCharBarResultU16(c: CharLiteral()) -> UInt(16) = \"char.convert_checked\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"char.convert_checked\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn ToCharBadResultU9(c: CharLiteral()) -> UInt(9) = \"char.convert_checked\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn ToCharBadResultU9(c: CharLiteral()) -> UInt(9) = \"char.convert_checked\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"char.convert_checked\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn ToCharNoParam() -> UInt(8) = \"char.convert_checked\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn ToCharNoParam() -> UInt(8) = \"char.convert_checked\";\n\n// --- fail_runtime_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"builtin\";\n\nlet c: CharLiteral() = 'a';\n// CHECK:STDERR: fail_runtime_call.carbon:[[@LINE+8]]:18: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let d: UInt(8) = ToChar(c);\n// CHECK:STDERR:                  ^~~~~~~~~\n// CHECK:STDERR: fail_runtime_call.carbon:[[@LINE-6]]:1: in import [InImport]\n// CHECK:STDERR: builtin.carbon:8:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn ToChar(c: CharLiteral()) -> UInt(8) = \"char.convert_checked\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet d: UInt(8) = ToChar(c);\n\n// --- narrow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"builtin\";\n\n//@dump-sem-ir-begin\nlet a: UInt(8) = ToChar('\\0');\nlet b: UInt(8) = ToChar('b');\nlet c: UInt(8) = ToChar('\\u{7F}');\n//@dump-sem-ir-end\n\n// --- fail_size_small.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"builtin\";\n\n// CHECK:STDERR: fail_size_small.carbon:[[@LINE+4]]:18: error: character value U+0080 too large for type `<builtin u8>` [CharTooLargeForType]\n// CHECK:STDERR: let c: UInt(8) = ToChar('\\u{80}');\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet c: UInt(8) = ToChar('\\u{80}');\n\n// --- fail_size_multi_byte.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"builtin\";\n\n// CHECK:STDERR: fail_size_multi_byte.carbon:[[@LINE+4]]:18: error: character value U+1E15 too large for type `<builtin u8>` [CharTooLargeForType]\n// CHECK:STDERR: let c: UInt(8) = ToChar('\\u{1E15}');\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet c: UInt(8) = ToChar('\\u{1E15}');\n\n// CHECK:STDOUT: --- narrow.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %UInt.type: type = fn_type @UInt [concrete]\n// CHECK:STDOUT:   %UInt: %UInt.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_8: Core.IntLiteral = int_value 8 [concrete]\n// CHECK:STDOUT:   %u8.builtin: type = int_type unsigned, %int_8 [concrete]\n// CHECK:STDOUT:   %pattern_type.456: type = pattern_type %u8.builtin [concrete]\n// CHECK:STDOUT:   %ToChar.type: type = fn_type @ToChar [concrete]\n// CHECK:STDOUT:   %ToChar: %ToChar.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.dc9: Core.CharLiteral = char_value U+0000 [concrete]\n// CHECK:STDOUT:   %int_0: %u8.builtin = int_value 0 [concrete]\n// CHECK:STDOUT:   %.711: Core.CharLiteral = char_value U+0062 [concrete]\n// CHECK:STDOUT:   %int_98: %u8.builtin = int_value 98 [concrete]\n// CHECK:STDOUT:   %.e28: Core.CharLiteral = char_value U+007F [concrete]\n// CHECK:STDOUT:   %int_127: %u8.builtin = int_value 127 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.UInt: %UInt.type = import_ref Main//builtin, UInt, loaded [concrete = constants.%UInt]\n// CHECK:STDOUT:   %Main.ToChar: %ToChar.type = import_ref Main//builtin, ToChar, loaded [concrete = constants.%ToChar]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.456 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc6_14.1: type = splice_block %.loc6_14.3 [concrete = constants.%u8.builtin] {\n// CHECK:STDOUT:     %UInt.ref.loc6: %UInt.type = name_ref UInt, imports.%Main.UInt [concrete = constants.%UInt]\n// CHECK:STDOUT:     %int_8.loc6: Core.IntLiteral = int_value 8 [concrete = constants.%int_8]\n// CHECK:STDOUT:     %UInt.call.loc6: init type = call %UInt.ref.loc6(%int_8.loc6) [concrete = constants.%u8.builtin]\n// CHECK:STDOUT:     %.loc6_14.2: type = value_of_initializer %UInt.call.loc6 [concrete = constants.%u8.builtin]\n// CHECK:STDOUT:     %.loc6_14.3: type = converted %UInt.call.loc6, %.loc6_14.2 [concrete = constants.%u8.builtin]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc6_29.1: %u8.builtin = value_of_initializer @__global_init.%ToChar.call.loc6 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc6_29.2: %u8.builtin = converted @__global_init.%ToChar.call.loc6, %.loc6_29.1 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %a: %u8.builtin = value_binding a, %.loc6_29.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.456 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc7_14.1: type = splice_block %.loc7_14.3 [concrete = constants.%u8.builtin] {\n// CHECK:STDOUT:     %UInt.ref.loc7: %UInt.type = name_ref UInt, imports.%Main.UInt [concrete = constants.%UInt]\n// CHECK:STDOUT:     %int_8.loc7: Core.IntLiteral = int_value 8 [concrete = constants.%int_8]\n// CHECK:STDOUT:     %UInt.call.loc7: init type = call %UInt.ref.loc7(%int_8.loc7) [concrete = constants.%u8.builtin]\n// CHECK:STDOUT:     %.loc7_14.2: type = value_of_initializer %UInt.call.loc7 [concrete = constants.%u8.builtin]\n// CHECK:STDOUT:     %.loc7_14.3: type = converted %UInt.call.loc7, %.loc7_14.2 [concrete = constants.%u8.builtin]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc7_28.1: %u8.builtin = value_of_initializer @__global_init.%ToChar.call.loc7 [concrete = constants.%int_98]\n// CHECK:STDOUT:   %.loc7_28.2: %u8.builtin = converted @__global_init.%ToChar.call.loc7, %.loc7_28.1 [concrete = constants.%int_98]\n// CHECK:STDOUT:   %b: %u8.builtin = value_binding b, %.loc7_28.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.456 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc8_14.1: type = splice_block %.loc8_14.3 [concrete = constants.%u8.builtin] {\n// CHECK:STDOUT:     %UInt.ref.loc8: %UInt.type = name_ref UInt, imports.%Main.UInt [concrete = constants.%UInt]\n// CHECK:STDOUT:     %int_8.loc8: Core.IntLiteral = int_value 8 [concrete = constants.%int_8]\n// CHECK:STDOUT:     %UInt.call.loc8: init type = call %UInt.ref.loc8(%int_8.loc8) [concrete = constants.%u8.builtin]\n// CHECK:STDOUT:     %.loc8_14.2: type = value_of_initializer %UInt.call.loc8 [concrete = constants.%u8.builtin]\n// CHECK:STDOUT:     %.loc8_14.3: type = converted %UInt.call.loc8, %.loc8_14.2 [concrete = constants.%u8.builtin]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc8_33.1: %u8.builtin = value_of_initializer @__global_init.%ToChar.call.loc8 [concrete = constants.%int_127]\n// CHECK:STDOUT:   %.loc8_33.2: %u8.builtin = converted @__global_init.%ToChar.call.loc8, %.loc8_33.1 [concrete = constants.%int_127]\n// CHECK:STDOUT:   %c: %u8.builtin = value_binding c, %.loc8_33.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ToChar.ref.loc6: %ToChar.type = name_ref ToChar, imports.%Main.ToChar [concrete = constants.%ToChar]\n// CHECK:STDOUT:   %.loc6: Core.CharLiteral = char_value U+0000 [concrete = constants.%.dc9]\n// CHECK:STDOUT:   %ToChar.call.loc6: init %u8.builtin = call %ToChar.ref.loc6(%.loc6) [concrete = constants.%int_0]\n// CHECK:STDOUT:   %ToChar.ref.loc7: %ToChar.type = name_ref ToChar, imports.%Main.ToChar [concrete = constants.%ToChar]\n// CHECK:STDOUT:   %.loc7: Core.CharLiteral = char_value U+0062 [concrete = constants.%.711]\n// CHECK:STDOUT:   %ToChar.call.loc7: init %u8.builtin = call %ToChar.ref.loc7(%.loc7) [concrete = constants.%int_98]\n// CHECK:STDOUT:   %ToChar.ref.loc8: %ToChar.type = name_ref ToChar, imports.%Main.ToChar [concrete = constants.%ToChar]\n// CHECK:STDOUT:   %.loc8: Core.CharLiteral = char_value U+007F [concrete = constants.%.e28]\n// CHECK:STDOUT:   %ToChar.call.loc8: init %u8.builtin = call %ToChar.ref.loc8(%.loc8) [concrete = constants.%int_127]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/char_literal/make_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/char_literal/make_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/char_literal/make_type.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn CharLiteral() -> type = \"char_literal.make_type\";\n\n// --- use_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n//@dump-sem-ir-begin\nlet ascii_x: CharLiteral() = 'x';\nlet not_7_bit: CharLiteral() = '\\u{80}';\nlet not_8_bit: CharLiteral() = '\\u{1E15}';\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- use_types.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %CharLiteral.type: type = fn_type @CharLiteral [concrete]\n// CHECK:STDOUT:   %CharLiteral: %CharLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.8c6: type = pattern_type Core.CharLiteral [concrete]\n// CHECK:STDOUT:   %.4ac: Core.CharLiteral = char_value U+0078 [concrete]\n// CHECK:STDOUT:   %.ae7: Core.CharLiteral = char_value U+0080 [concrete]\n// CHECK:STDOUT:   %.a81: Core.CharLiteral = char_value U+1E15 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.CharLiteral: %CharLiteral.type = import_ref Main//types, CharLiteral, loaded [concrete = constants.%CharLiteral]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %ascii_x.patt: %pattern_type.8c6 = value_binding_pattern ascii_x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc7_26.1: type = splice_block %.loc7_26.3 [concrete = Core.CharLiteral] {\n// CHECK:STDOUT:     %CharLiteral.ref.loc7: %CharLiteral.type = name_ref CharLiteral, imports.%Main.CharLiteral [concrete = constants.%CharLiteral]\n// CHECK:STDOUT:     %CharLiteral.call.loc7: init type = call %CharLiteral.ref.loc7() [concrete = Core.CharLiteral]\n// CHECK:STDOUT:     %.loc7_26.2: type = value_of_initializer %CharLiteral.call.loc7 [concrete = Core.CharLiteral]\n// CHECK:STDOUT:     %.loc7_26.3: type = converted %CharLiteral.call.loc7, %.loc7_26.2 [concrete = Core.CharLiteral]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ascii_x: Core.CharLiteral = value_binding ascii_x, @__global_init.%.loc7\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %not_7_bit.patt: %pattern_type.8c6 = value_binding_pattern not_7_bit [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc8_28.1: type = splice_block %.loc8_28.3 [concrete = Core.CharLiteral] {\n// CHECK:STDOUT:     %CharLiteral.ref.loc8: %CharLiteral.type = name_ref CharLiteral, imports.%Main.CharLiteral [concrete = constants.%CharLiteral]\n// CHECK:STDOUT:     %CharLiteral.call.loc8: init type = call %CharLiteral.ref.loc8() [concrete = Core.CharLiteral]\n// CHECK:STDOUT:     %.loc8_28.2: type = value_of_initializer %CharLiteral.call.loc8 [concrete = Core.CharLiteral]\n// CHECK:STDOUT:     %.loc8_28.3: type = converted %CharLiteral.call.loc8, %.loc8_28.2 [concrete = Core.CharLiteral]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %not_7_bit: Core.CharLiteral = value_binding not_7_bit, @__global_init.%.loc8\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %not_8_bit.patt: %pattern_type.8c6 = value_binding_pattern not_8_bit [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc9_28.1: type = splice_block %.loc9_28.3 [concrete = Core.CharLiteral] {\n// CHECK:STDOUT:     %CharLiteral.ref.loc9: %CharLiteral.type = name_ref CharLiteral, imports.%Main.CharLiteral [concrete = constants.%CharLiteral]\n// CHECK:STDOUT:     %CharLiteral.call.loc9: init type = call %CharLiteral.ref.loc9() [concrete = Core.CharLiteral]\n// CHECK:STDOUT:     %.loc9_28.2: type = value_of_initializer %CharLiteral.call.loc9 [concrete = Core.CharLiteral]\n// CHECK:STDOUT:     %.loc9_28.3: type = converted %CharLiteral.call.loc9, %.loc9_28.2 [concrete = Core.CharLiteral]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %not_8_bit: Core.CharLiteral = value_binding not_8_bit, @__global_init.%.loc9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7: Core.CharLiteral = char_value U+0078 [concrete = constants.%.4ac]\n// CHECK:STDOUT:   %.loc8: Core.CharLiteral = char_value U+0080 [concrete = constants.%.ae7]\n// CHECK:STDOUT:   %.loc9: Core.CharLiteral = char_value U+1E15 [concrete = constants.%.a81]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/cpp/std/initializer_list/make.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/cpp/std/initializer_list/make.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/cpp/std/initializer_list/make.carbon\n\n// --- valid_pointer_pointer.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass PointerPointer {\n  var start: i32*;\n  var end: i32*;\n}\n\nfn Make(arr: array(i32, 3)) -> PointerPointer = \"cpp.std.initializer_list.make\";\n\n// --- valid_pointer_int.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass PointerInt {\n  var start: i32*;\n  var size: i32;\n}\n\nfn Make(arr: array(i32, 3)) -> PointerInt = \"cpp.std.initializer_list.make\";\n\n// --- imported_from_cpp.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Cpp inline '''\nstruct PointerPointer {\n  int* start;\n  int* end;\n};\n\nstruct PointerInt {\n  int* start;\n  int size;\n};\n''';\n\nfn MakePointerPointer(arr: array(i32, 3)) -> Cpp.PointerPointer = \"cpp.std.initializer_list.make\";\n\nfn MakePointerInt(arr: array(i32, 3)) -> Cpp.PointerInt = \"cpp.std.initializer_list.make\";\n\n// --- fail_incomplete.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass FailIncomplete;\n\n// CHECK:STDERR: fail_incomplete.carbon:[[@LINE+11]]:20: error: function returns incomplete type `FailIncomplete` [IncompleteTypeInFunctionReturnType]\n// CHECK:STDERR: fn Make(n: i32) -> FailIncomplete = \"cpp.std.initializer_list.make\";\n// CHECK:STDERR:                    ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_incomplete.carbon:[[@LINE-5]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class FailIncomplete;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_incomplete.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"cpp.std.initializer_list.make\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Make(n: i32) -> FailIncomplete = \"cpp.std.initializer_list.make\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Make(n: i32) -> FailIncomplete = \"cpp.std.initializer_list.make\";\n\n// --- fail_wrong_arg.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass FailWrongArg {\n  var start: i32*;\n  var end: i32*;\n}\n\n// CHECK:STDERR: fail_wrong_arg.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"cpp.std.initializer_list.make\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Make(n: i32) -> FailWrongArg = \"cpp.std.initializer_list.make\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Make(n: i32) -> FailWrongArg = \"cpp.std.initializer_list.make\";\n\n// --- fail_wrong_arg_count.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass FailWrongArgCount {\n  var start: i32*;\n  var end: i32*;\n}\n\n// CHECK:STDERR: fail_wrong_arg_count.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"cpp.std.initializer_list.make\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Make(arr: array(i32, 3), n: i32) -> FailWrongArgCount = \"cpp.std.initializer_list.make\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Make(arr: array(i32, 3), n: i32) -> FailWrongArgCount = \"cpp.std.initializer_list.make\";\n\n// --- fail_not_a_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_not_a_class.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"cpp.std.initializer_list.make\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Make(arr: array(i32, 3)) -> i32 = \"cpp.std.initializer_list.make\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Make(arr: array(i32, 3)) -> i32 = \"cpp.std.initializer_list.make\";\n\n// --- fail_wrong_field_count.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass FailWrongFieldCount {\n  var start: i32*;\n}\n\n// CHECK:STDERR: fail_wrong_field_count.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"cpp.std.initializer_list.make\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Make(arr: array(i32, 3)) -> FailWrongFieldCount = \"cpp.std.initializer_list.make\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Make(arr: array(i32, 3)) -> FailWrongFieldCount = \"cpp.std.initializer_list.make\";\n\n// --- fail_wrong_first_field.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass FailWrongFirstField {\n  var start: i32;\n  var end: i32;\n}\n\n// CHECK:STDERR: fail_wrong_first_field.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"cpp.std.initializer_list.make\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Make(arr: array(i32, 3)) -> FailWrongFirstField = \"cpp.std.initializer_list.make\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Make(arr: array(i32, 3)) -> FailWrongFirstField = \"cpp.std.initializer_list.make\";\n\n// --- fail_wrong_second_field.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass FailWrongSecondField {\n  var start: i32*;\n  var end: {.a: i32};\n}\n\n// CHECK:STDERR: fail_wrong_second_field.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"cpp.std.initializer_list.make\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Make(arr: array(i32, 3)) -> FailWrongSecondField = \"cpp.std.initializer_list.make\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Make(arr: array(i32, 3)) -> FailWrongSecondField = \"cpp.std.initializer_list.make\";\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/add.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/add.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/add.carbon\n\n// --- float_add.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Add(a: f64, b: f64) -> f64 = \"float.add\";\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> f64 {\n  //@dump-sem-ir-begin\n  return Add(a, b);\n  //@dump-sem-ir-end\n}\n\nvar x: f64 = Add(2.2, 2.3);\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.add\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew(a: f64) -> f64 = \"float.add\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew(a: f64) -> f64 = \"float.add\";\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.add\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: f64, b: f64, c: f64) -> f64 = \"float.add\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: f64, b: f64, c: f64) -> f64 = \"float.add\";\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.add\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn BadReturnType(a: f64, b: f64) -> bool = \"float.add\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn BadReturnType(a: f64, b: f64) -> bool = \"float.add\";\nfn JustRight(a: f64, b: f64) -> f64 = \"float.add\";\n\nfn RuntimeCallIsValidTooFew(a: f64) -> f64 {\n  return TooFew(a);\n}\n\nfn RuntimeCallIsValidTooMany(a: f64, b: f64, c: f64) -> f64 {\n  return TooMany(a, b, c);\n}\n\nfn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {\n  return BadReturnType(a, b);\n}\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Literal() -> type = \"float_literal.make_type\";\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.add\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn AddLiteral(a: Literal(), b: Literal()) -> Literal() = \"float.add\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn AddLiteral(a: Literal(), b: Literal()) -> Literal() = \"float.add\";\n\n// CHECK:STDOUT: --- float_add.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %Add.type: type = fn_type @Add [concrete]\n// CHECK:STDOUT:   %Add: %Add.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: %f64.d77 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Add.ref: %Add.type = name_ref Add, file.%Add.decl [concrete = constants.%Add]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %Add.call: init %f64.d77 = call %Add.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Add.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/add_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/add_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/add_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: f64, b: f64) = \"float.add_assign\";\n\nfn Call(ref a: f64, b: f64) {\n  Builtin(ref a, b);\n}\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.add_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: f64, b: f64) = \"float.add_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: f64, b: f64) = \"float.add_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.add_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: f64, b: f32) = \"float.add_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: f64, b: f32) = \"float.add_assign\";\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Literal() -> type = \"float_literal.make_type\";\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.add_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn LiteralRuntime(ref a: Literal(), b: Literal()) = \"float.add_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn LiteralRuntime(ref a: Literal(), b: Literal()) = \"float.add_assign\";\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/convert_checked.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/convert_checked.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/convert_checked.carbon\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn FloatLiteral() -> type = \"float_literal.make_type\";\n\nfn FloatLiteralToFloatLiteral(a: FloatLiteral()) -> FloatLiteral() =\n    \"float.convert_checked\";\n\n// --- identity_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"literal\";\n\n//@dump-sem-ir-begin\nlet f: FloatLiteral() = FloatLiteralToFloatLiteral(1.0);\n//@dump-sem-ir-end\n\n// --- f64.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nexport import library \"literal\";\n\nfn Float64ToFloat64(a: f64) -> f64 = \"float.convert_checked\";\nfn Float64ToFloatLiteral(a: f64) -> FloatLiteral() = \"float.convert_checked\";\nfn FloatLiteralToFloat64(a: FloatLiteral()) -> f64 = \"float.convert_checked\";\n\n// --- f32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nexport import library \"literal\";\n\nfn Float32ToFloat32(a: f32) -> f32 = \"float.convert_checked\";\nfn Float32ToFloatLiteral(a: f32) -> FloatLiteral() = \"float.convert_checked\";\nfn FloatLiteralToFloat32(a: FloatLiteral()) -> f32 = \"float.convert_checked\";\n\nfn Float32ToFloat64(a: f32) -> f64 = \"float.convert_checked\";\nfn Float64ToFloat32(a: f64) -> f32 = \"float.convert_checked\";\n\n// --- literal_f64.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"f64\";\n\n//@dump-sem-ir-begin\nlet a: f64 = FloatLiteralToFloat64(0.0);\nlet b: f64 = FloatLiteralToFloat64(1.0);\nlet c: f64 = FloatLiteralToFloat64(1.0e308);\n//@dump-sem-ir-end\n\n// --- literal_f32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"f32\";\n\n//@dump-sem-ir-begin\nlet a: f32 = FloatLiteralToFloat32(0.0);\nlet b: f32 = FloatLiteralToFloat32(1.0);\nlet c: f32 = FloatLiteralToFloat32(1.0e38);\n//@dump-sem-ir-end\n\n// --- identity_f64.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"f64\";\n\n//@dump-sem-ir-begin\nlet a: f64 = Float64ToFloat64(0.0);\nlet b: f64 = Float64ToFloat64(1.0);\nlet c: f64 = Float64ToFloat64(1.0e308);\n//@dump-sem-ir-end\n\n// --- identity_f32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"f32\";\n\n//@dump-sem-ir-begin\nlet a: f32 = Float32ToFloat32(0.0);\nlet b: f32 = Float32ToFloat32(1.0);\nlet c: f32 = Float32ToFloat32(1.0e38);\n//@dump-sem-ir-end\n\n// --- truncate.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"f32\";\n\n//@dump-sem-ir-begin\nlet a: f32 = Float64ToFloat32(1.0);\n//@dump-sem-ir-end\n\n// --- fail_truncate_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"f32\";\nimport library \"f64\";\n\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_truncate_overflow.carbon:[[@LINE+4]]:14: error: value 9.9999999999999994E+38 too large for floating-point type `f32` [FloatTooLargeForType]\n// CHECK:STDERR: let a: f32 = Float64ToFloat32(1.0e39);\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet a: f32 = Float64ToFloat32(1.0e39);\n// CHECK:STDERR: fail_truncate_overflow.carbon:[[@LINE+4]]:14: error: value 10*10^38 too large for floating-point type `f32` [FloatLiteralTooLargeForType]\n// CHECK:STDERR: let b: f32 = FloatLiteralToFloat32(1.0e39);\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet b: f32 = FloatLiteralToFloat32(1.0e39);\n// CHECK:STDERR: fail_truncate_overflow.carbon:[[@LINE+4]]:14: error: value 10*10^308 too large for floating-point type `f64` [FloatLiteralTooLargeForType]\n// CHECK:STDERR: let c: f64 = FloatLiteralToFloat64(1.0e309);\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet c: f64 = FloatLiteralToFloat64(1.0e309);\n//@dump-sem-ir-end\n\n// --- extend.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"f32\";\n\n//@dump-sem-ir-begin\nlet a: f64 = Float32ToFloat64(1.0);\nlet b: f64 = Float32ToFloat64(1.0e30);\n//@dump-sem-ir-end\n\n// --- fail_not_constant.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"f64\";\n\n//@dump-sem-ir-begin\nlet not_constant_64: f64 = 0.0;\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE+8]]:33: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let convert_not_constant: f64 = Float64ToFloat64(not_constant_64);\n// CHECK:STDERR:                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE-7]]:1: in import [InImport]\n// CHECK:STDERR: f64.carbon:5:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn Float64ToFloat64(a: f64) -> f64 = \"float.convert_checked\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet convert_not_constant: f64 = Float64ToFloat64(not_constant_64);\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- identity_literal.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %FloatLiteral.type: type = fn_type @FloatLiteral [concrete]\n// CHECK:STDOUT:   %FloatLiteral: %FloatLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dab: type = pattern_type Core.FloatLiteral [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloatLiteral.type: type = fn_type @FloatLiteralToFloatLiteral [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloatLiteral: %FloatLiteralToFloatLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.FloatLiteral: %FloatLiteral.type = import_ref Main//literal, FloatLiteral, loaded [concrete = constants.%FloatLiteral]\n// CHECK:STDOUT:   %Main.FloatLiteralToFloatLiteral: %FloatLiteralToFloatLiteral.type = import_ref Main//literal, FloatLiteralToFloatLiteral, loaded [concrete = constants.%FloatLiteralToFloatLiteral]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type.dab = value_binding_pattern f [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc6_21.1: type = splice_block %.loc6_21.3 [concrete = Core.FloatLiteral] {\n// CHECK:STDOUT:     %FloatLiteral.ref: %FloatLiteral.type = name_ref FloatLiteral, imports.%Main.FloatLiteral [concrete = constants.%FloatLiteral]\n// CHECK:STDOUT:     %FloatLiteral.call: init type = call %FloatLiteral.ref() [concrete = Core.FloatLiteral]\n// CHECK:STDOUT:     %.loc6_21.2: type = value_of_initializer %FloatLiteral.call [concrete = Core.FloatLiteral]\n// CHECK:STDOUT:     %.loc6_21.3: type = converted %FloatLiteral.call, %.loc6_21.2 [concrete = Core.FloatLiteral]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc6_55.1: Core.FloatLiteral = value_of_initializer @__global_init.%FloatLiteralToFloatLiteral.call [concrete = constants.%float]\n// CHECK:STDOUT:   %.loc6_55.2: Core.FloatLiteral = converted @__global_init.%FloatLiteralToFloatLiteral.call, %.loc6_55.1 [concrete = constants.%float]\n// CHECK:STDOUT:   %f: Core.FloatLiteral = value_binding f, %.loc6_55.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %FloatLiteralToFloatLiteral.ref: %FloatLiteralToFloatLiteral.type = name_ref FloatLiteralToFloatLiteral, imports.%Main.FloatLiteralToFloatLiteral [concrete = constants.%FloatLiteralToFloatLiteral]\n// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float]\n// CHECK:STDOUT:   %FloatLiteralToFloatLiteral.call: init Core.FloatLiteral = call %FloatLiteralToFloatLiteral.ref(%float) [concrete = constants.%float]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- literal_f64.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloat64.type: type = fn_type @FloatLiteralToFloat64 [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloat64: %FloatLiteralToFloat64.type = struct_value () [concrete]\n// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]\n// CHECK:STDOUT:   %float.0a8: %f64.d77 = float_value 0 [concrete]\n// CHECK:STDOUT:   %float.6da: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT:   %float.d20: %f64.d77 = float_value 1 [concrete]\n// CHECK:STDOUT:   %float.12a: Core.FloatLiteral = float_literal_value 10e307 [concrete]\n// CHECK:STDOUT:   %float.bde: %f64.d77 = float_value 1.0E+308 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.FloatLiteralToFloat64: %FloatLiteralToFloat64.type = import_ref Main//f64, FloatLiteralToFloat64, loaded [concrete = constants.%FloatLiteralToFloat64]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.0ae = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc6: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc6_39.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call.loc6 [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %.loc6_39.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call.loc6, %.loc6_39.1 [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %a: %f64.d77 = value_binding a, %.loc6_39.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.0ae = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc7: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc7_39.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call.loc7 [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %.loc7_39.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call.loc7, %.loc7_39.1 [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %b: %f64.d77 = value_binding b, %.loc7_39.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.0ae = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc8: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc8_43.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call.loc8 [concrete = constants.%float.bde]\n// CHECK:STDOUT:   %.loc8_43.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call.loc8, %.loc8_43.1 [concrete = constants.%float.bde]\n// CHECK:STDOUT:   %c: %f64.d77 = value_binding c, %.loc8_43.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %FloatLiteralToFloat64.ref.loc6: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]\n// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]\n// CHECK:STDOUT:   %FloatLiteralToFloat64.call.loc6: init %f64.d77 = call %FloatLiteralToFloat64.ref.loc6(%float.loc6) [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %FloatLiteralToFloat64.ref.loc7: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]\n// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.6da]\n// CHECK:STDOUT:   %FloatLiteralToFloat64.call.loc7: init %f64.d77 = call %FloatLiteralToFloat64.ref.loc7(%float.loc7) [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %FloatLiteralToFloat64.ref.loc8: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]\n// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_literal_value 10e307 [concrete = constants.%float.12a]\n// CHECK:STDOUT:   %FloatLiteralToFloat64.call.loc8: init %f64.d77 = call %FloatLiteralToFloat64.ref.loc8(%float.loc8) [concrete = constants.%float.bde]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- literal_f32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %f32.97e: type = class_type @Float, @Float(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32.97e [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloat32.type: type = fn_type @FloatLiteralToFloat32 [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloat32: %FloatLiteralToFloat32.type = struct_value () [concrete]\n// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]\n// CHECK:STDOUT:   %float.4db: %f32.97e = float_value 0 [concrete]\n// CHECK:STDOUT:   %float.6da: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT:   %float.e3b: %f32.97e = float_value 1 [concrete]\n// CHECK:STDOUT:   %float.8d2: Core.FloatLiteral = float_literal_value 10e37 [concrete]\n// CHECK:STDOUT:   %float.520: %f32.97e = float_value 9.99999968E+37 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.FloatLiteralToFloat32: %FloatLiteralToFloat32.type = import_ref Main//f32, FloatLiteralToFloat32, loaded [concrete = constants.%FloatLiteralToFloat32]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.201 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f32.loc6: type = type_literal constants.%f32.97e [concrete = constants.%f32.97e]\n// CHECK:STDOUT:   %.loc6_39.1: %f32.97e = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc6 [concrete = constants.%float.4db]\n// CHECK:STDOUT:   %.loc6_39.2: %f32.97e = converted @__global_init.%FloatLiteralToFloat32.call.loc6, %.loc6_39.1 [concrete = constants.%float.4db]\n// CHECK:STDOUT:   %a: %f32.97e = value_binding a, %.loc6_39.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.201 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f32.loc7: type = type_literal constants.%f32.97e [concrete = constants.%f32.97e]\n// CHECK:STDOUT:   %.loc7_39.1: %f32.97e = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc7 [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %.loc7_39.2: %f32.97e = converted @__global_init.%FloatLiteralToFloat32.call.loc7, %.loc7_39.1 [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %b: %f32.97e = value_binding b, %.loc7_39.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.201 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f32.loc8: type = type_literal constants.%f32.97e [concrete = constants.%f32.97e]\n// CHECK:STDOUT:   %.loc8_42.1: %f32.97e = value_of_initializer @__global_init.%FloatLiteralToFloat32.call.loc8 [concrete = constants.%float.520]\n// CHECK:STDOUT:   %.loc8_42.2: %f32.97e = converted @__global_init.%FloatLiteralToFloat32.call.loc8, %.loc8_42.1 [concrete = constants.%float.520]\n// CHECK:STDOUT:   %c: %f32.97e = value_binding c, %.loc8_42.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %FloatLiteralToFloat32.ref.loc6: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32]\n// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]\n// CHECK:STDOUT:   %FloatLiteralToFloat32.call.loc6: init %f32.97e = call %FloatLiteralToFloat32.ref.loc6(%float.loc6) [concrete = constants.%float.4db]\n// CHECK:STDOUT:   %FloatLiteralToFloat32.ref.loc7: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32]\n// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.6da]\n// CHECK:STDOUT:   %FloatLiteralToFloat32.call.loc7: init %f32.97e = call %FloatLiteralToFloat32.ref.loc7(%float.loc7) [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %FloatLiteralToFloat32.ref.loc8: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32]\n// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_literal_value 10e37 [concrete = constants.%float.8d2]\n// CHECK:STDOUT:   %FloatLiteralToFloat32.call.loc8: init %f32.97e = call %FloatLiteralToFloat32.ref.loc8(%float.loc8) [concrete = constants.%float.520]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- identity_f64.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]\n// CHECK:STDOUT:   %Float64ToFloat64.type: type = fn_type @Float64ToFloat64 [concrete]\n// CHECK:STDOUT:   %Float64ToFloat64: %Float64ToFloat64.type = struct_value () [concrete]\n// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.4a8: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.cb2: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.4a8 = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.cb2) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.a33: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%f64.d77, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.6c5: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.a33, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.8c6: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]\n// CHECK:STDOUT:   %bound_method.f2b: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.0a8: %f64.d77 = float_value 0 [concrete]\n// CHECK:STDOUT:   %float.6da: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.1ed: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239 [concrete]\n// CHECK:STDOUT:   %bound_method.50c: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.d20: %f64.d77 = float_value 1 [concrete]\n// CHECK:STDOUT:   %float.12a: Core.FloatLiteral = float_literal_value 10e307 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.dee: <bound method> = bound_method %float.12a, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239 [concrete]\n// CHECK:STDOUT:   %bound_method.d56: <bound method> = bound_method %float.12a, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.bde: %f64.d77 = float_value 1.0E+308 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Float64ToFloat64: %Float64ToFloat64.type = import_ref Main//f64, Float64ToFloat64, loaded [concrete = constants.%Float64ToFloat64]\n// CHECK:STDOUT:   %Core.import_ref.38a: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f) = import_ref Core//prelude/parts/float, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.38a), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.0ae = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc6: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc6_34.1: %f64.d77 = value_of_initializer @__global_init.%Float64ToFloat64.call.loc6 [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %.loc6_34.2: %f64.d77 = converted @__global_init.%Float64ToFloat64.call.loc6, %.loc6_34.1 [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %a: %f64.d77 = value_binding a, %.loc6_34.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.0ae = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc7: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc7_34.1: %f64.d77 = value_of_initializer @__global_init.%Float64ToFloat64.call.loc7 [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %.loc7_34.2: %f64.d77 = converted @__global_init.%Float64ToFloat64.call.loc7, %.loc7_34.1 [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %b: %f64.d77 = value_binding b, %.loc7_34.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.0ae = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc8: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc8_38.1: %f64.d77 = value_of_initializer @__global_init.%Float64ToFloat64.call.loc8 [concrete = constants.%float.bde]\n// CHECK:STDOUT:   %.loc8_38.2: %f64.d77 = converted @__global_init.%Float64ToFloat64.call.loc8, %.loc8_38.1 [concrete = constants.%float.bde]\n// CHECK:STDOUT:   %c: %f64.d77 = value_binding c, %.loc8_38.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Float64ToFloat64.ref.loc6: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]\n// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]\n// CHECK:STDOUT:   %impl.elem0.loc6: %.6c5 = impl_witness_access constants.%ImplicitAs.impl_witness.cb2, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.239]\n// CHECK:STDOUT:   %bound_method.loc6_31.1: <bound method> = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.8c6]\n// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_31.2: <bound method> = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.f2b]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %f64.d77 = call %bound_method.loc6_31.2(%float.loc6) [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %.loc6_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %.loc6_31.2: %f64.d77 = converted %float.loc6, %.loc6_31.1 [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %Float64ToFloat64.call.loc6: init %f64.d77 = call %Float64ToFloat64.ref.loc6(%.loc6_31.2) [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %Float64ToFloat64.ref.loc7: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]\n// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.6da]\n// CHECK:STDOUT:   %impl.elem0.loc7: %.6c5 = impl_witness_access constants.%ImplicitAs.impl_witness.cb2, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.239]\n// CHECK:STDOUT:   %bound_method.loc7_31.1: <bound method> = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.1ed]\n// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_31.2: <bound method> = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.50c]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f64.d77 = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %.loc7_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %.loc7_31.2: %f64.d77 = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %Float64ToFloat64.call.loc7: init %f64.d77 = call %Float64ToFloat64.ref.loc7(%.loc7_31.2) [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %Float64ToFloat64.ref.loc8: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]\n// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_literal_value 10e307 [concrete = constants.%float.12a]\n// CHECK:STDOUT:   %impl.elem0.loc8: %.6c5 = impl_witness_access constants.%ImplicitAs.impl_witness.cb2, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.239]\n// CHECK:STDOUT:   %bound_method.loc8_31.1: <bound method> = bound_method %float.loc8, %impl.elem0.loc8 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.dee]\n// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_31.2: <bound method> = bound_method %float.loc8, %specific_fn.loc8 [concrete = constants.%bound_method.d56]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %f64.d77 = call %bound_method.loc8_31.2(%float.loc8) [concrete = constants.%float.bde]\n// CHECK:STDOUT:   %.loc8_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%float.bde]\n// CHECK:STDOUT:   %.loc8_31.2: %f64.d77 = converted %float.loc8, %.loc8_31.1 [concrete = constants.%float.bde]\n// CHECK:STDOUT:   %Float64ToFloat64.call.loc8: init %f64.d77 = call %Float64ToFloat64.ref.loc8(%.loc8_31.2) [concrete = constants.%float.bde]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- identity_f32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %f32.97e: type = class_type @Float, @Float(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32.97e [concrete]\n// CHECK:STDOUT:   %Float32ToFloat32.type: type = fn_type @Float32ToFloat32 [concrete]\n// CHECK:STDOUT:   %Float32ToFloat32: %Float32ToFloat32.type = struct_value () [concrete]\n// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.223: type = facet_type <@ImplicitAs, @ImplicitAs(%f32.97e)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.bc6: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.461: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.461 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.223 = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.bc6) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.e4d: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%f32.97e, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.98d: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.e4d, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.c2d: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.577: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.4db: %f32.97e = float_value 0 [concrete]\n// CHECK:STDOUT:   %float.6da: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.c4b: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55 [concrete]\n// CHECK:STDOUT:   %bound_method.57d: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.e3b: %f32.97e = float_value 1 [concrete]\n// CHECK:STDOUT:   %float.8d2: Core.FloatLiteral = float_literal_value 10e37 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.d1f: <bound method> = bound_method %float.8d2, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55 [concrete]\n// CHECK:STDOUT:   %bound_method.bed: <bound method> = bound_method %float.8d2, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.520: %f32.97e = float_value 9.99999968E+37 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Float32ToFloat32: %Float32ToFloat32.type = import_ref Main//f32, Float32ToFloat32, loaded [concrete = constants.%Float32ToFloat32]\n// CHECK:STDOUT:   %Core.import_ref.38a: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f) = import_ref Core//prelude/parts/float, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.38a), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.201 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f32.loc6: type = type_literal constants.%f32.97e [concrete = constants.%f32.97e]\n// CHECK:STDOUT:   %.loc6_34.1: %f32.97e = value_of_initializer @__global_init.%Float32ToFloat32.call.loc6 [concrete = constants.%float.4db]\n// CHECK:STDOUT:   %.loc6_34.2: %f32.97e = converted @__global_init.%Float32ToFloat32.call.loc6, %.loc6_34.1 [concrete = constants.%float.4db]\n// CHECK:STDOUT:   %a: %f32.97e = value_binding a, %.loc6_34.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.201 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f32.loc7: type = type_literal constants.%f32.97e [concrete = constants.%f32.97e]\n// CHECK:STDOUT:   %.loc7_34.1: %f32.97e = value_of_initializer @__global_init.%Float32ToFloat32.call.loc7 [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %.loc7_34.2: %f32.97e = converted @__global_init.%Float32ToFloat32.call.loc7, %.loc7_34.1 [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %b: %f32.97e = value_binding b, %.loc7_34.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.201 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f32.loc8: type = type_literal constants.%f32.97e [concrete = constants.%f32.97e]\n// CHECK:STDOUT:   %.loc8_37.1: %f32.97e = value_of_initializer @__global_init.%Float32ToFloat32.call.loc8 [concrete = constants.%float.520]\n// CHECK:STDOUT:   %.loc8_37.2: %f32.97e = converted @__global_init.%Float32ToFloat32.call.loc8, %.loc8_37.1 [concrete = constants.%float.520]\n// CHECK:STDOUT:   %c: %f32.97e = value_binding c, %.loc8_37.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Float32ToFloat32.ref.loc6: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32]\n// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]\n// CHECK:STDOUT:   %impl.elem0.loc6: %.98d = impl_witness_access constants.%ImplicitAs.impl_witness.bc6, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55]\n// CHECK:STDOUT:   %bound_method.loc6_31.1: <bound method> = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.c2d]\n// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_31.2: <bound method> = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.577]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %f32.97e = call %bound_method.loc6_31.2(%float.loc6) [concrete = constants.%float.4db]\n// CHECK:STDOUT:   %.loc6_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%float.4db]\n// CHECK:STDOUT:   %.loc6_31.2: %f32.97e = converted %float.loc6, %.loc6_31.1 [concrete = constants.%float.4db]\n// CHECK:STDOUT:   %Float32ToFloat32.call.loc6: init %f32.97e = call %Float32ToFloat32.ref.loc6(%.loc6_31.2) [concrete = constants.%float.4db]\n// CHECK:STDOUT:   %Float32ToFloat32.ref.loc7: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32]\n// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.6da]\n// CHECK:STDOUT:   %impl.elem0.loc7: %.98d = impl_witness_access constants.%ImplicitAs.impl_witness.bc6, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55]\n// CHECK:STDOUT:   %bound_method.loc7_31.1: <bound method> = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.c4b]\n// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_31.2: <bound method> = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.57d]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f32.97e = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %.loc7_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %.loc7_31.2: %f32.97e = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %Float32ToFloat32.call.loc7: init %f32.97e = call %Float32ToFloat32.ref.loc7(%.loc7_31.2) [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %Float32ToFloat32.ref.loc8: %Float32ToFloat32.type = name_ref Float32ToFloat32, imports.%Main.Float32ToFloat32 [concrete = constants.%Float32ToFloat32]\n// CHECK:STDOUT:   %float.loc8: Core.FloatLiteral = float_literal_value 10e37 [concrete = constants.%float.8d2]\n// CHECK:STDOUT:   %impl.elem0.loc8: %.98d = impl_witness_access constants.%ImplicitAs.impl_witness.bc6, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55]\n// CHECK:STDOUT:   %bound_method.loc8_31.1: <bound method> = bound_method %float.loc8, %impl.elem0.loc8 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.d1f]\n// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_31.2: <bound method> = bound_method %float.loc8, %specific_fn.loc8 [concrete = constants.%bound_method.bed]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %f32.97e = call %bound_method.loc8_31.2(%float.loc8) [concrete = constants.%float.520]\n// CHECK:STDOUT:   %.loc8_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%float.520]\n// CHECK:STDOUT:   %.loc8_31.2: %f32.97e = converted %float.loc8, %.loc8_31.1 [concrete = constants.%float.520]\n// CHECK:STDOUT:   %Float32ToFloat32.call.loc8: init %f32.97e = call %Float32ToFloat32.ref.loc8(%.loc8_31.2) [concrete = constants.%float.520]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- truncate.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %f32.97e: type = class_type @Float, @Float(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32.97e [concrete]\n// CHECK:STDOUT:   %Float64ToFloat32.type: type = fn_type @Float64ToFloat32 [concrete]\n// CHECK:STDOUT:   %Float64ToFloat32: %Float64ToFloat32.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %float.6da: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.4a8: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.cb2: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.4a8 = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.cb2) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.a33: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%f64.d77, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.6c5: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.a33, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.d20: %f64.d77 = float_value 1 [concrete]\n// CHECK:STDOUT:   %float.e3b: %f32.97e = float_value 1 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Float64ToFloat32: %Float64ToFloat32.type = import_ref Main//f32, Float64ToFloat32, loaded [concrete = constants.%Float64ToFloat32]\n// CHECK:STDOUT:   %Core.import_ref.38a: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f) = import_ref Core//prelude/parts/float, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.38a), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.201 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f32: type = type_literal constants.%f32.97e [concrete = constants.%f32.97e]\n// CHECK:STDOUT:   %.loc6_34.1: %f32.97e = value_of_initializer @__global_init.%Float64ToFloat32.call [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %.loc6_34.2: %f32.97e = converted @__global_init.%Float64ToFloat32.call, %.loc6_34.1 [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %a: %f32.97e = value_binding a, %.loc6_34.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Float64ToFloat32.ref: %Float64ToFloat32.type = name_ref Float64ToFloat32, imports.%Main.Float64ToFloat32 [concrete = constants.%Float64ToFloat32]\n// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.6da]\n// CHECK:STDOUT:   %impl.elem0: %.6c5 = impl_witness_access constants.%ImplicitAs.impl_witness.cb2, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.239]\n// CHECK:STDOUT:   %bound_method.loc6_31.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_31.2: <bound method> = bound_method %float, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc6_31.2(%float) [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %.loc6_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %.loc6_31.2: %f64.d77 = converted %float, %.loc6_31.1 [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %Float64ToFloat32.call: init %f32.97e = call %Float64ToFloat32.ref(%.loc6_31.2) [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_truncate_overflow.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %f32.97e: type = class_type @Float, @Float(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.201: type = pattern_type %f32.97e [concrete]\n// CHECK:STDOUT:   %Float64ToFloat32.type: type = fn_type @Float64ToFloat32 [concrete]\n// CHECK:STDOUT:   %Float64ToFloat32: %Float64ToFloat32.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]\n// CHECK:STDOUT:   %float.cfcfd2.1: Core.FloatLiteral = float_literal_value 10e38 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.4a8: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.cb2: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.4a8 = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.cb2) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.a33: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%f64.d77, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.6c5: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.a33, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.cfcfd2.1, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.cfcfd2.1, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.c37: %f64.d77 = float_value 9.9999999999999994E+38 [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloat32.type: type = fn_type @FloatLiteralToFloat32 [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloat32: %FloatLiteralToFloat32.type = struct_value () [concrete]\n// CHECK:STDOUT:   %float.cfcfd2.2: Core.FloatLiteral = float_literal_value 10e38 [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloat64.type: type = fn_type @FloatLiteralToFloat64 [concrete]\n// CHECK:STDOUT:   %FloatLiteralToFloat64: %FloatLiteralToFloat64.type = struct_value () [concrete]\n// CHECK:STDOUT:   %float.82f: Core.FloatLiteral = float_literal_value 10e308 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.FloatLiteralToFloat32: %FloatLiteralToFloat32.type = import_ref Main//f32, FloatLiteralToFloat32, loaded [concrete = constants.%FloatLiteralToFloat32]\n// CHECK:STDOUT:   %Main.Float64ToFloat32: %Float64ToFloat32.type = import_ref Main//f32, Float64ToFloat32, loaded [concrete = constants.%Float64ToFloat32]\n// CHECK:STDOUT:   %Main.FloatLiteralToFloat64: %FloatLiteralToFloat64.type = import_ref Main//f64, FloatLiteralToFloat64, loaded [concrete = constants.%FloatLiteralToFloat64]\n// CHECK:STDOUT:   %Core.import_ref.38a: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f) = import_ref Core//prelude/parts/float, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.38a), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.201 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f32.loc11: type = type_literal constants.%f32.97e [concrete = constants.%f32.97e]\n// CHECK:STDOUT:   %.loc11_37.1: %f32.97e = value_of_initializer @__global_init.%Float64ToFloat32.call [concrete = <error>]\n// CHECK:STDOUT:   %.loc11_37.2: %f32.97e = converted @__global_init.%Float64ToFloat32.call, %.loc11_37.1 [concrete = <error>]\n// CHECK:STDOUT:   %a: %f32.97e = value_binding a, %.loc11_37.2 [concrete = <error>]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.201 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f32.loc16: type = type_literal constants.%f32.97e [concrete = constants.%f32.97e]\n// CHECK:STDOUT:   %.loc16_42.1: %f32.97e = value_of_initializer @__global_init.%FloatLiteralToFloat32.call [concrete = <error>]\n// CHECK:STDOUT:   %.loc16_42.2: %f32.97e = converted @__global_init.%FloatLiteralToFloat32.call, %.loc16_42.1 [concrete = <error>]\n// CHECK:STDOUT:   %b: %f32.97e = value_binding b, %.loc16_42.2 [concrete = <error>]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.0ae = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc21_43.1: %f64.d77 = value_of_initializer @__global_init.%FloatLiteralToFloat64.call [concrete = <error>]\n// CHECK:STDOUT:   %.loc21_43.2: %f64.d77 = converted @__global_init.%FloatLiteralToFloat64.call, %.loc21_43.1 [concrete = <error>]\n// CHECK:STDOUT:   %c: %f64.d77 = value_binding c, %.loc21_43.2 [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Float64ToFloat32.ref: %Float64ToFloat32.type = name_ref Float64ToFloat32, imports.%Main.Float64ToFloat32 [concrete = constants.%Float64ToFloat32]\n// CHECK:STDOUT:   %float.loc11: Core.FloatLiteral = float_literal_value 10e38 [concrete = constants.%float.cfcfd2.1]\n// CHECK:STDOUT:   %impl.elem0: %.6c5 = impl_witness_access constants.%ImplicitAs.impl_witness.cb2, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.239]\n// CHECK:STDOUT:   %bound_method.loc11_31.1: <bound method> = bound_method %float.loc11, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc11_31.2: <bound method> = bound_method %float.loc11, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc11_31.2(%float.loc11) [concrete = constants.%float.c37]\n// CHECK:STDOUT:   %.loc11_31.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.c37]\n// CHECK:STDOUT:   %.loc11_31.2: %f64.d77 = converted %float.loc11, %.loc11_31.1 [concrete = constants.%float.c37]\n// CHECK:STDOUT:   %Float64ToFloat32.call: init %f32.97e = call %Float64ToFloat32.ref(%.loc11_31.2) [concrete = <error>]\n// CHECK:STDOUT:   %FloatLiteralToFloat32.ref: %FloatLiteralToFloat32.type = name_ref FloatLiteralToFloat32, imports.%Main.FloatLiteralToFloat32 [concrete = constants.%FloatLiteralToFloat32]\n// CHECK:STDOUT:   %float.loc16: Core.FloatLiteral = float_literal_value 10e38 [concrete = constants.%float.cfcfd2.2]\n// CHECK:STDOUT:   %FloatLiteralToFloat32.call: init %f32.97e = call %FloatLiteralToFloat32.ref(%float.loc16) [concrete = <error>]\n// CHECK:STDOUT:   %FloatLiteralToFloat64.ref: %FloatLiteralToFloat64.type = name_ref FloatLiteralToFloat64, imports.%Main.FloatLiteralToFloat64 [concrete = constants.%FloatLiteralToFloat64]\n// CHECK:STDOUT:   %float.loc21: Core.FloatLiteral = float_literal_value 10e308 [concrete = constants.%float.82f]\n// CHECK:STDOUT:   %FloatLiteralToFloat64.call: init %f64.d77 = call %FloatLiteralToFloat64.ref(%float.loc21) [concrete = <error>]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extend.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]\n// CHECK:STDOUT:   %Float32ToFloat64.type: type = fn_type @Float32ToFloat64 [concrete]\n// CHECK:STDOUT:   %Float32ToFloat64: %Float32ToFloat64.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %f32.97e: type = class_type @Float, @Float(%int_32) [concrete]\n// CHECK:STDOUT:   %float.6da: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.223: type = facet_type <@ImplicitAs, @ImplicitAs(%f32.97e)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.bc6: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.461: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.461 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.223 = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.bc6) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.e4d: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%f32.97e, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.98d: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.e4d, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.c4b: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.57d: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.e3b: %f32.97e = float_value 1 [concrete]\n// CHECK:STDOUT:   %float.d20: %f64.d77 = float_value 1 [concrete]\n// CHECK:STDOUT:   %float.c02: Core.FloatLiteral = float_literal_value 10e29 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.9ad: <bound method> = bound_method %float.c02, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55 [concrete]\n// CHECK:STDOUT:   %bound_method.601: <bound method> = bound_method %float.c02, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.7d4: %f32.97e = float_value 1.00000002E+30 [concrete]\n// CHECK:STDOUT:   %float.6a7: %f64.d77 = float_value 1.0000000150474662E+30 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Float32ToFloat64: %Float32ToFloat64.type = import_ref Main//f32, Float32ToFloat64, loaded [concrete = constants.%Float32ToFloat64]\n// CHECK:STDOUT:   %Core.import_ref.38a: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f) = import_ref Core//prelude/parts/float, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.38a), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.0ae = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc6: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc6_34.1: %f64.d77 = value_of_initializer @__global_init.%Float32ToFloat64.call.loc6 [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %.loc6_34.2: %f64.d77 = converted @__global_init.%Float32ToFloat64.call.loc6, %.loc6_34.1 [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %a: %f64.d77 = value_binding a, %.loc6_34.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.0ae = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc7: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc7_37.1: %f64.d77 = value_of_initializer @__global_init.%Float32ToFloat64.call.loc7 [concrete = constants.%float.6a7]\n// CHECK:STDOUT:   %.loc7_37.2: %f64.d77 = converted @__global_init.%Float32ToFloat64.call.loc7, %.loc7_37.1 [concrete = constants.%float.6a7]\n// CHECK:STDOUT:   %b: %f64.d77 = value_binding b, %.loc7_37.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Float32ToFloat64.ref.loc6: %Float32ToFloat64.type = name_ref Float32ToFloat64, imports.%Main.Float32ToFloat64 [concrete = constants.%Float32ToFloat64]\n// CHECK:STDOUT:   %float.loc6: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.6da]\n// CHECK:STDOUT:   %impl.elem0.loc6: %.98d = impl_witness_access constants.%ImplicitAs.impl_witness.bc6, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55]\n// CHECK:STDOUT:   %bound_method.loc6_31.1: <bound method> = bound_method %float.loc6, %impl.elem0.loc6 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.c4b]\n// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_31.2: <bound method> = bound_method %float.loc6, %specific_fn.loc6 [concrete = constants.%bound_method.57d]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %f32.97e = call %bound_method.loc6_31.2(%float.loc6) [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %.loc6_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %.loc6_31.2: %f32.97e = converted %float.loc6, %.loc6_31.1 [concrete = constants.%float.e3b]\n// CHECK:STDOUT:   %Float32ToFloat64.call.loc6: init %f64.d77 = call %Float32ToFloat64.ref.loc6(%.loc6_31.2) [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %Float32ToFloat64.ref.loc7: %Float32ToFloat64.type = name_ref Float32ToFloat64, imports.%Main.Float32ToFloat64 [concrete = constants.%Float32ToFloat64]\n// CHECK:STDOUT:   %float.loc7: Core.FloatLiteral = float_literal_value 10e29 [concrete = constants.%float.c02]\n// CHECK:STDOUT:   %impl.elem0.loc7: %.98d = impl_witness_access constants.%ImplicitAs.impl_witness.bc6, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.e55]\n// CHECK:STDOUT:   %bound_method.loc7_31.1: <bound method> = bound_method %float.loc7, %impl.elem0.loc7 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound.9ad]\n// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_31.2: <bound method> = bound_method %float.loc7, %specific_fn.loc7 [concrete = constants.%bound_method.601]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %f32.97e = call %bound_method.loc7_31.2(%float.loc7) [concrete = constants.%float.7d4]\n// CHECK:STDOUT:   %.loc7_31.1: %f32.97e = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%float.7d4]\n// CHECK:STDOUT:   %.loc7_31.2: %f32.97e = converted %float.loc7, %.loc7_31.1 [concrete = constants.%float.7d4]\n// CHECK:STDOUT:   %Float32ToFloat64.call.loc7: init %f64.d77 = call %Float32ToFloat64.ref.loc7(%.loc7_31.2) [concrete = constants.%float.6a7]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_not_constant.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]\n// CHECK:STDOUT:   %float.1f7: Core.FloatLiteral = float_literal_value 0e-1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.4a8: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.cb2: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.4a8 = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.cb2) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.a33: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%f64.d77, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.6c5: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.a33, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.1f7, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.0a8: %f64.d77 = float_value 0 [concrete]\n// CHECK:STDOUT:   %Float64ToFloat64.type: type = fn_type @Float64ToFloat64 [concrete]\n// CHECK:STDOUT:   %Float64ToFloat64: %Float64ToFloat64.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Float64ToFloat64: %Float64ToFloat64.type = import_ref Main//f64, Float64ToFloat64, loaded [concrete = constants.%Float64ToFloat64]\n// CHECK:STDOUT:   %Core.import_ref.38a: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f) = import_ref Core//prelude/parts/float, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.import_ref.38a), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %not_constant_64.patt: %pattern_type.0ae = value_binding_pattern not_constant_64 [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc6: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %impl.elem0: %.6c5 = impl_witness_access constants.%ImplicitAs.impl_witness.cb2, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.239]\n// CHECK:STDOUT:   %bound_method.loc6_28.1: <bound method> = bound_method @__global_init.%float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_28.2: <bound method> = bound_method @__global_init.%float, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc6_28.2(@__global_init.%float) [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %.loc6_28.1: %f64.d77 = value_of_initializer %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %.loc6_28.2: %f64.d77 = converted @__global_init.%float, %.loc6_28.1 [concrete = constants.%float.0a8]\n// CHECK:STDOUT:   %not_constant_64: %f64.d77 = value_binding not_constant_64, %.loc6_28.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %convert_not_constant.patt: %pattern_type.0ae = value_binding_pattern convert_not_constant [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f64.loc15: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:   %.loc15_65.1: %f64.d77 = value_of_initializer @__global_init.%Float64ToFloat64.call\n// CHECK:STDOUT:   %.loc15_65.2: %f64.d77 = converted @__global_init.%Float64ToFloat64.call, %.loc15_65.1\n// CHECK:STDOUT:   %convert_not_constant: %f64.d77 = value_binding convert_not_constant, %.loc15_65.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 0e-1 [concrete = constants.%float.1f7]\n// CHECK:STDOUT:   %Float64ToFloat64.ref: %Float64ToFloat64.type = name_ref Float64ToFloat64, imports.%Main.Float64ToFloat64 [concrete = constants.%Float64ToFloat64]\n// CHECK:STDOUT:   %not_constant_64.ref: %f64.d77 = name_ref not_constant_64, file.%not_constant_64\n// CHECK:STDOUT:   %Float64ToFloat64.call: init %f64.d77 = call %Float64ToFloat64.ref(%not_constant_64.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/div.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/div.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/div.carbon\n\n// --- float_div.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Div(a: f64, b: f64) -> f64 = \"float.div\";\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> f64 {\n  //@dump-sem-ir-begin\n  return Div(a, b);\n  //@dump-sem-ir-end\n}\n\nvar a: f64 = Div(10.0, 2.5);\nlet b: f64 = Div(1.0, 0.0);\nlet c: f64 = Div(0.0, 0.0);\n\n// --- fail_too_few.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.div\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew(a: f64) -> f64 = \"float.div\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew(a: f64) -> f64 = \"float.div\";\n\nfn RuntimeCallIsValidTooFew(a: f64) -> f64 {\n  return TooFew(a);\n}\n\n// --- fail_too_many.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.div\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: f64, b: f64, c: f64) -> f64 = \"float.div\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: f64, b: f64, c: f64) -> f64 = \"float.div\";\n\nfn RuntimeCallIsValidTooMany(a: f64, b: f64, c: f64) -> f64 {\n  return TooMany(a, b, c);\n}\n\n// --- fail_bad_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.div\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn BadReturnType(a: f64, b: f64) -> bool = \"float.div\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn BadReturnType(a: f64, b: f64) -> bool = \"float.div\";\n\nfn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {\n  return BadReturnType(a, b);\n}\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Literal() -> type = \"float_literal.make_type\";\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.div\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn DivLiteral(a: Literal(), b: Literal()) -> Literal() = \"float.div\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn DivLiteral(a: Literal(), b: Literal()) -> Literal() = \"float.div\";\n\n// CHECK:STDOUT: --- float_div.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %Div.type: type = fn_type @Div [concrete]\n// CHECK:STDOUT:   %Div: %Div.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: %f64.d77 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Div.ref: %Div.type = name_ref Div, file.%Div.decl [concrete = constants.%Div]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %Div.call: init %f64.d77 = call %Div.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Div.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/div_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/div_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/div_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: f64, b: f64) = \"float.div_assign\";\n\nfn Call(ref a: f64, b: f64) {\n  Builtin(ref a, b);\n}\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.div_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: f64, b: f64) = \"float.div_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: f64, b: f64) = \"float.div_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.div_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: f64, b: f32) = \"float.div_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: f64, b: f32) = \"float.div_assign\";\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Literal() -> type = \"float_literal.make_type\";\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.div_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn LiteralRuntime(ref a: Literal(), b: Literal()) = \"float.div_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn LiteralRuntime(ref a: Literal(), b: Literal()) = \"float.div_assign\";\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/eq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/eq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/eq.carbon\n\n// --- float_eq.carbon\n\nfn Eq(a: f64, b: f64) -> bool = \"float.eq\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  true_ as (if Eq(1.0, 1.0) then True else False);\n  false_ as (if Eq(1.0, 2.0) then True else False);\n}\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> bool {\n  //@dump-sem-ir-begin\n  return Eq(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.eq\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn WrongResult(a: f64, b: f64) -> f64 = \"float.eq\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn WrongResult(a: f64, b: f64) -> f64 = \"float.eq\";\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.eq\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Eq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = \"float.eq\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Eq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = \"float.eq\";\n\n// CHECK:STDOUT: --- float_eq.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %Eq.type: type = fn_type @Eq [concrete]\n// CHECK:STDOUT:   %Eq: %Eq.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Eq.ref: %Eq.type = name_ref Eq, file.%Eq.decl [concrete = constants.%Eq]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %Eq.call: init bool = call %Eq.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Eq.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/greater.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/greater.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/greater.carbon\n\n// --- float_greater.carbon\n\nfn Greater(a: f64, b: f64) -> bool = \"float.greater\";\nfn Negate(a: f64) -> f64 = \"float.negate\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  false_ as (if Greater(1.0, 2.0) then True else False);\n  false_ as (if Greater(1.0, 1.0) then True else False);\n  true_ as (if Greater(1.0, 0.0) then True else False);\n  false_ as (if Greater(Negate(1.0), 0.0) then True else False);\n  true_ as (if Greater(0.0, Negate(1.0)) then True else False);\n}\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> bool {\n  //@dump-sem-ir-begin\n  return Greater(a, b);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- float_greater.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %Greater.type: type = fn_type @Greater [concrete]\n// CHECK:STDOUT:   %Greater: %Greater.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Greater.ref: %Greater.type = name_ref Greater, file.%Greater.decl [concrete = constants.%Greater]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %Greater.call: init bool = call %Greater.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Greater.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/greater_eq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/greater_eq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/greater_eq.carbon\n\n// --- float_greater_eq.carbon\n\nfn GreaterEq(a: f64, b: f64) -> bool = \"float.greater_eq\";\nfn Negate(a: f64) -> f64 = \"float.negate\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  false_ as (if GreaterEq(1.0, 2.0) then True else False);\n  true_ as (if GreaterEq(1.0, 1.0) then True else False);\n  true_ as (if GreaterEq(1.0, 0.0) then True else False);\n  false_ as (if GreaterEq(Negate(1.0), 0.0) then True else False);\n  true_ as (if GreaterEq(0.0, Negate(1.0)) then True else False);\n}\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> bool {\n  //@dump-sem-ir-begin\n  return GreaterEq(a, b);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- float_greater_eq.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %GreaterEq.type: type = fn_type @GreaterEq [concrete]\n// CHECK:STDOUT:   %GreaterEq: %GreaterEq.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %GreaterEq.ref: %GreaterEq.type = name_ref GreaterEq, file.%GreaterEq.decl [concrete = constants.%GreaterEq]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %GreaterEq.call: init bool = call %GreaterEq.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %GreaterEq.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/less.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/less.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/less.carbon\n\n// --- float_less.carbon\n\nfn Less(a: f64, b: f64) -> bool = \"float.less\";\nfn Negate(a: f64) -> f64 = \"float.negate\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  true_ as (if Less(1.0, 2.0) then True else False);\n  false_ as (if Less(1.0, 1.0) then True else False);\n  false_ as (if Less(1.0, 0.0) then True else False);\n  true_ as (if Less(Negate(1.0), 0.0) then True else False);\n  false_ as (if Less(0.0, Negate(1.0)) then True else False);\n}\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> bool {\n  //@dump-sem-ir-begin\n  return Less(a, b);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- float_less.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %Less.type: type = fn_type @Less [concrete]\n// CHECK:STDOUT:   %Less: %Less.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Less.ref: %Less.type = name_ref Less, file.%Less.decl [concrete = constants.%Less]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %Less.call: init bool = call %Less.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Less.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/less_eq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/less_eq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/less_eq.carbon\n\n// --- float_less_eq.carbon\n\nfn LessEq(a: f64, b: f64) -> bool = \"float.less_eq\";\nfn Negate(a: f64) -> f64 = \"float.negate\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  true_ as (if LessEq(1.0, 2.0) then True else False);\n  true_ as (if LessEq(1.0, 1.0) then True else False);\n  false_ as (if LessEq(1.0, 0.0) then True else False);\n  true_ as (if LessEq(Negate(1.0), 0.0) then True else False);\n  false_ as (if LessEq(0.0, Negate(1.0)) then True else False);\n}\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> bool {\n  //@dump-sem-ir-begin\n  return LessEq(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.less_eq\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn LessEq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = \"float.less_eq\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn LessEq(a: Core.FloatLiteral(), b: Core.FloatLiteral()) -> bool = \"float.less_eq\";\n\n// CHECK:STDOUT: --- float_less_eq.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %LessEq.type: type = fn_type @LessEq [concrete]\n// CHECK:STDOUT:   %LessEq: %LessEq.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %LessEq.ref: %LessEq.type = name_ref LessEq, file.%LessEq.decl [concrete = constants.%LessEq]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %LessEq.call: init bool = call %LessEq.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %LessEq.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/make_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/make_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/make_type.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Float(size: i32) -> type = \"float.make_type\";\n\n// --- use_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\nvar a: Float(16);\nvar b: Float(32);\nvar c: Float(64);\nvar d: Float(128);\n\nfn GetFloat(dyn_size: i32) -> type {\n  //@dump-sem-ir-begin\n  return Float(dyn_size);\n  //@dump-sem-ir-end\n}\n\n// --- fail_invalid_size.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n// CHECK:STDERR: fail_invalid_size.carbon:[[@LINE+4]]:20: error: unsupported floating-point bit width 931 [CompileTimeFloatBitWidth]\n// CHECK:STDERR: var invalid_float: Float(931);\n// CHECK:STDERR:                    ^~~~~~~~~~\n// CHECK:STDERR:\nvar invalid_float: Float(931);\n\n// --- fail_dyn_size.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\nvar dyn_size: i32 = 64;\n// CHECK:STDERR: fail_dyn_size.carbon:[[@LINE+4]]:10: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n// CHECK:STDERR: var dyn: Float(dyn_size);\n// CHECK:STDERR:          ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar dyn: Float(dyn_size);\n\n// CHECK:STDOUT: --- use_types.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Float.type: type = fn_type @Float [concrete]\n// CHECK:STDOUT:   %Float: %Float.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32.be0: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32.be0) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Float: %Float.type = import_ref Main//types, Float, loaded [concrete = constants.%Float]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @GetFloat(%dyn_size.param: %i32) -> out %return.param: type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Float.ref: %Float.type = name_ref Float, imports.%Main.Float [concrete = constants.%Float]\n// CHECK:STDOUT:   %dyn_size.ref: %i32 = name_ref dyn_size, %dyn_size\n// CHECK:STDOUT:   %Float.call: init type = call %Float.ref(%dyn_size.ref)\n// CHECK:STDOUT:   return %Float.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/mul.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/mul.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/mul.carbon\n\n// --- mul_sub.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mul(a: f64, b: f64) -> f64 = \"float.mul\";\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> f64 {\n  //@dump-sem-ir-begin\n  return Mul(a, b);\n  //@dump-sem-ir-end\n}\n\nvar x: f64 = Mul(2.0, 0.5);\n\n// --- fail_too_few.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.mul\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew(a: f64) -> f64 = \"float.mul\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew(a: f64) -> f64 = \"float.mul\";\n\nfn RuntimeCallIsValidTooFew(a: f64) -> f64 {\n  return TooFew(a);\n}\n\n// --- fail_too_many.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.mul\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: f64, b: f64, c: f64) -> f64 = \"float.mul\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: f64, b: f64, c: f64) -> f64 = \"float.mul\";\n\nfn RuntimeCallIsValidTooMany(a: f64, b: f64, c: f64) -> f64 {\n  return TooMany(a, b, c);\n}\n\n// --- fail_bad_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.mul\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn BadReturnType(a: f64, b: f64) -> bool = \"float.mul\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn BadReturnType(a: f64, b: f64) -> bool = \"float.mul\";\n\nfn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {\n  return BadReturnType(a, b);\n}\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Literal() -> type = \"float_literal.make_type\";\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.mul\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MulLiteral(a: Literal(), b: Literal()) -> Literal() = \"float.mul\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MulLiteral(a: Literal(), b: Literal()) -> Literal() = \"float.mul\";\n\n// CHECK:STDOUT: --- mul_sub.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %Mul.type: type = fn_type @Mul [concrete]\n// CHECK:STDOUT:   %Mul: %Mul.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: %f64.d77 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Mul.ref: %Mul.type = name_ref Mul, file.%Mul.decl [concrete = constants.%Mul]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %Mul.call: init %f64.d77 = call %Mul.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Mul.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/mul_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/mul_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/mul_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: f64, b: f64) = \"float.mul_assign\";\n\nfn Call(ref a: f64, b: f64) {\n  Builtin(ref a, b);\n}\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.mul_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: f64, b: f64) = \"float.mul_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: f64, b: f64) = \"float.mul_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.mul_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: f64, b: f32) = \"float.mul_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: f64, b: f32) = \"float.mul_assign\";\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Literal() -> type = \"float_literal.make_type\";\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.mul_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn LiteralRuntime(ref a: Literal(), b: Literal()) = \"float.mul_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn LiteralRuntime(ref a: Literal(), b: Literal()) = \"float.mul_assign\";\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/negate.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/negate.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/negate.carbon\n\n// --- float_negate.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Negate(a: f64) -> f64 = \"float.negate\";\n\nfn RuntimeCallIsValid(a: f64, unused b: f64) -> f64 {\n  //@dump-sem-ir-begin\n  return Negate(a);\n  //@dump-sem-ir-end\n}\n\nlet a: f64 = Negate(1.5);\n\n// --- fail_too_few.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.negate\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew() -> f64 = \"float.negate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew() -> f64 = \"float.negate\";\n\nfn RuntimeCallIsValidTooFew() -> f64 {\n  return TooFew();\n}\n\n// --- fail_too_many.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.negate\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: f64, b: f64) -> f64 = \"float.negate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: f64, b: f64) -> f64 = \"float.negate\";\n\nfn RuntimeCallIsValidTooMany(a: f64, b: f64) -> f64 {\n  return TooMany(a, b);\n}\n\n// --- fail_bad_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.negate\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn BadReturnType(a: f64) -> bool = \"float.negate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn BadReturnType(a: f64) -> bool = \"float.negate\";\n\nfn RuntimeCallIsValidBadReturnType(a: f64) -> bool {\n  return BadReturnType(a);\n}\n\n// CHECK:STDOUT: --- float_negate.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %Negate.type: type = fn_type @Negate [concrete]\n// CHECK:STDOUT:   %Negate: %Negate.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: %f64.d77 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Negate.ref: %Negate.type = name_ref Negate, file.%Negate.decl [concrete = constants.%Negate]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %Negate.call: init %f64.d77 = call %Negate.ref(%a.ref)\n// CHECK:STDOUT:   return %Negate.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/neq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/neq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/neq.carbon\n\n// --- float_neq.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Neq(a: f64, b: f64) -> bool = \"float.neq\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  true_ as (if Neq(1.0, 2.0) then True else False);\n  false_ as (if Neq(1.0, 1.0) then True else False);\n}\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> bool {\n  //@dump-sem-ir-begin\n  return Neq(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.neq\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn WrongResult(a: f64, b: f64) -> f64 = \"float.neq\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn WrongResult(a: f64, b: f64) -> f64 = \"float.neq\";\n\n// CHECK:STDOUT: --- float_neq.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %Neq.type: type = fn_type @Neq [concrete]\n// CHECK:STDOUT:   %Neq: %Neq.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Neq.ref: %Neq.type = name_ref Neq, file.%Neq.decl [concrete = constants.%Neq]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %Neq.call: init bool = call %Neq.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Neq.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/sub.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/sub.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/sub.carbon\n\n// --- float_sub.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Sub(a: f64, b: f64) -> f64 = \"float.sub\";\n\nfn RuntimeCallIsValid(a: f64, b: f64) -> f64 {\n  //@dump-sem-ir-begin\n  return Sub(a, b);\n  //@dump-sem-ir-end\n}\n\nvar x: f64 = Sub(2.0, 0.5);\n\n// --- fail_too_few.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.sub\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew(a: f64) -> f64 = \"float.sub\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew(a: f64) -> f64 = \"float.sub\";\n\nfn RuntimeCallIsValidTooFew(a: f64) -> f64 {\n  return TooFew(a);\n}\n\n// --- fail_too_many.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.sub\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: f64, b: f64, c: f64) -> f64 = \"float.sub\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: f64, b: f64, c: f64) -> f64 = \"float.sub\";\n\nfn RuntimeCallIsValidTooMany(a: f64, b: f64, c: f64) -> f64 {\n  return TooMany(a, b, c);\n}\n\n// --- fail_bad_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.sub\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn BadReturnType(a: f64, b: f64) -> bool = \"float.sub\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn BadReturnType(a: f64, b: f64) -> bool = \"float.sub\";\n\nfn RuntimeCallIsValidBadReturnType(a: f64, b: f64) -> bool {\n  return BadReturnType(a, b);\n}\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Literal() -> type = \"float_literal.make_type\";\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.sub\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn SubLiteral(a: Literal(), b: Literal()) -> Literal() = \"float.sub\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn SubLiteral(a: Literal(), b: Literal()) -> Literal() = \"float.sub\";\n\n// CHECK:STDOUT: --- float_sub.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %Sub.type: type = fn_type @Sub [concrete]\n// CHECK:STDOUT:   %Sub: %Sub.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %f64.d77, %b.param: %f64.d77) -> out %return.param: %f64.d77 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Sub.ref: %Sub.type = name_ref Sub, file.%Sub.decl [concrete = constants.%Sub]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %f64.d77 = name_ref b, %b\n// CHECK:STDOUT:   %Sub.call: init %f64.d77 = call %Sub.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Sub.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float/sub_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float/sub_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float/sub_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: f64, b: f64) = \"float.sub_assign\";\n\nfn Call(ref a: f64, b: f64) {\n  Builtin(ref a, b);\n}\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.sub_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: f64, b: f64) = \"float.sub_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: f64, b: f64) = \"float.sub_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.sub_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: f64, b: f32) = \"float.sub_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: f64, b: f32) = \"float.sub_assign\";\n\n// --- fail_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Literal() -> type = \"float_literal.make_type\";\n// CHECK:STDERR: fail_literal.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"float.sub_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn LiteralRuntime(ref a: Literal(), b: Literal()) = \"float.sub_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn LiteralRuntime(ref a: Literal(), b: Literal()) = \"float.sub_assign\";\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/float_literal/make_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/float_literal/make_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/float_literal/make_type.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn FloatLiteral() -> type = \"float_literal.make_type\";\n\n// --- use_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n//@dump-sem-ir-begin\nlet f: FloatLiteral() = 1.0;\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- use_types.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %FloatLiteral.type: type = fn_type @FloatLiteral [concrete]\n// CHECK:STDOUT:   %FloatLiteral: %FloatLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dab: type = pattern_type Core.FloatLiteral [concrete]\n// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.FloatLiteral: %FloatLiteral.type = import_ref Main//types, FloatLiteral, loaded [concrete = constants.%FloatLiteral]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type.dab = value_binding_pattern f [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc7_21.1: type = splice_block %.loc7_21.3 [concrete = Core.FloatLiteral] {\n// CHECK:STDOUT:     %FloatLiteral.ref: %FloatLiteral.type = name_ref FloatLiteral, imports.%Main.FloatLiteral [concrete = constants.%FloatLiteral]\n// CHECK:STDOUT:     %FloatLiteral.call: init type = call %FloatLiteral.ref() [concrete = Core.FloatLiteral]\n// CHECK:STDOUT:     %.loc7_21.2: type = value_of_initializer %FloatLiteral.call [concrete = Core.FloatLiteral]\n// CHECK:STDOUT:     %.loc7_21.3: type = converted %FloatLiteral.call, %.loc7_21.2 [concrete = Core.FloatLiteral]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: Core.FloatLiteral = value_binding f, @__global_init.%float\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/form/make_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/form/make_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/form/make_type.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Form() -> type = \"form.make_type\";\n\n// --- use_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n//@dump-sem-ir-begin\nlet f: Form() = form(var ());\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- use_types.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Form.type: type = fn_type @Form [concrete]\n// CHECK:STDOUT:   %Form: %Form.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.13f: type = pattern_type Core.Form [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Form: %Form.type = import_ref Main//types, Form, loaded [concrete = constants.%Form]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type.13f = value_binding_pattern f [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc7_13.1: type = splice_block %.loc7_13.3 [concrete = Core.Form] {\n// CHECK:STDOUT:     %Form.ref: %Form.type = name_ref Form, imports.%Main.Form [concrete = constants.%Form]\n// CHECK:STDOUT:     %Form.call: init type = call %Form.ref() [concrete = Core.Form]\n// CHECK:STDOUT:     %.loc7_13.2: type = value_of_initializer %Form.call [concrete = Core.Form]\n// CHECK:STDOUT:     %.loc7_13.3: type = converted %Form.call, %.loc7_13.2 [concrete = Core.Form]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: Core.Form = value_binding f, @__global_init.%.loc7_22\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7_27.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc7_27.2: type = converted %.loc7_27.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   %.loc7_22: Core.Form = init_form %.loc7_27.2 [concrete = constants.%.262]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/and.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/and.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/and.carbon\n\n// --- int_and.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn And(a: i32, b: i32) -> i32 = \"int.and\";\n\nvar arr: array(i32, And(12, 10));\nlet arr_p: array(i32, 8)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return And(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn And(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.and\";\n\nclass Expect(N:! Core.IntLiteral()) {}\nfn Test(N:! Core.IntLiteral()) -> Expect(N) { return {}; }\n\nfn F() {\n  Test(And(1, 2)) as Expect(0);\n  Test(And(12, 10)) as Expect(8);\n\n  Test(And(1, -1)) as Expect(1);\n  Test(And(-2, -3)) as Expect(-4);\n  // Ensure the sign bit is treated properly even for 64-bit numbers.\n  Test(And(0x7FFF_FFFF_FFFF_FFFF, -3)) as Expect(0x7FFF_FFFF_FFFF_FFFD);\n  Test(And(0x8000_0000_0000_0000, -1)) as Expect(0x8000_0000_0000_0000);\n}\n\n// --- fail_literal_runtime.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn AndLit(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.and\";\n\nfn F(a: Core.IntLiteral()) -> Core.IntLiteral() {\n  // CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE+7]]:10: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   return AndLit(5, a);\n  // CHECK:STDERR:          ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE-6]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn AndLit(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.and\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return AndLit(5, a);\n}\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// Heterogeneous \"and\" is not supported.\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.and\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedAnd1(a: i32, b: Core.IntLiteral()) -> i32 = \"int.and\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedAnd1(a: i32, b: Core.IntLiteral()) -> i32 = \"int.and\";\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.and\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedAnd2(a: Core.IntLiteral(), b: i32) -> i32 = \"int.and\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedAnd2(a: Core.IntLiteral(), b: i32) -> i32 = \"int.and\";\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.and\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedAnd3(a: i32, b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.and\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedAnd3(a: i32, b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.and\";\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.and\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedAnd4(a: Core.IntLiteral(), b: i32) -> Core.IntLiteral() = \"int.and\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedAnd4(a: Core.IntLiteral(), b: i32) -> Core.IntLiteral() = \"int.and\";\n\n// --- fail_runtime_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn And(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.and\";\n\nfn Test(n: Core.IntLiteral()) {\n  // OK\n  And(1, 1);\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   And(n, 1);\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-8]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn And(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.and\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  And(n, 1);\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   And(1, n);\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-16]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn And(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.and\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  And(1, n);\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   And(n, n);\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-24]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn And(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.and\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  And(n, n);\n}\n\n// CHECK:STDOUT: --- int_and.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %And.type: type = fn_type @And [concrete]\n// CHECK:STDOUT:   %And: %And.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %And.ref: %And.type = name_ref And, file.%And.decl [concrete = constants.%And]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %And.call: init %i32 = call %And.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %And.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/and_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/and_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/and_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.and_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.and_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.and_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.and_assign\";\n\n// --- fail_not_ptr.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_not_ptr.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.and_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.and_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.and_assign\";\n\n// TODO: There's a crash bug preventing splitting tests, it'd probably be good\n// to split. (also, look at examples in other files)\n// // --- fail_not_ptr.carbon\n//\n// library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_not_ptr.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.and_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.and_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.and_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/complement.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/complement.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/complement.carbon\n\n// --- int_complement.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Complement(a: i32) -> i32 = \"int.complement\";\nfn And(a: i32, b: i32) -> i32 = \"int.and\";\n\nvar arr: array(i32, And(Complement(0x123456), 0xFFFFFF));\nlet arr_p: array(i32, 0xEDCBA9)* = &arr;\n\nfn RuntimeCallIsValid(a: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Complement(a);\n  //@dump-sem-ir-end\n}\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Complement(a: Core.IntLiteral()) -> Core.IntLiteral() = \"int.complement\";\n\nclass Expect(N:! Core.IntLiteral()) {}\nfn Test(N:! Core.IntLiteral()) -> Expect(N) { return {}; }\n\nfn F() {\n  Test(Complement(0)) as Expect(-1);\n  Test(Complement(1)) as Expect(-2);\n  Test(Complement(-1)) as Expect(0);\n  Test(Complement(-0x7FFF_FFFF_FFFF_FFFF)) as Expect(0x7FFF_FFFF_FFFF_FFFE);\n  Test(Complement(-0x8000_0000_0000_0000)) as Expect(0x7FFF_FFFF_FFFF_FFFF);\n  Test(Complement(0x7FFF_FFFF_FFFF_FFFF)) as Expect(-0x8000_0000_0000_0000);\n  Test(Complement(0x8000_0000_0000_0000)) as Expect(-0x8000_0000_0000_0001);\n}\n\n// --- fail_literal_runtime.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Complement(a: Core.IntLiteral()) -> Core.IntLiteral() = \"int.complement\";\n\nfn F(a: Core.IntLiteral()) -> Core.IntLiteral() {\n  // CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE+7]]:10: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   return Complement(a);\n  // CHECK:STDERR:          ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_literal_runtime.carbon:[[@LINE-6]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn Complement(a: Core.IntLiteral()) -> Core.IntLiteral() = \"int.complement\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return Complement(a);\n}\n\n// CHECK:STDOUT: --- int_complement.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Complement.type: type = fn_type @Complement [concrete]\n// CHECK:STDOUT:   %Complement: %Complement.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Complement.ref: %Complement.type = name_ref Complement, file.%Complement.decl [concrete = constants.%Complement]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %Complement.call: init %i32 = call %Complement.ref(%a.ref)\n// CHECK:STDOUT:   return %Complement.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/convert.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/uint.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/convert.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/convert.carbon\n\n// --- int_ops.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// Size preserving\nfn Int32ToInt32(a: i32) -> i32 = \"int.convert\";\nfn Int32ToUint32(a: i32) -> u32 = \"int.convert\";\nfn Uint32ToInt32(a: u32) -> i32 = \"int.convert\";\nfn Uint32ToUint32(a: u32) -> u32 = \"int.convert\";\nfn IntLiteralToIntLiteral(a: Core.IntLiteral()) -> Core.IntLiteral() = \"int.convert\";\n\n// Narrowing\nfn Int32ToInt16(a: i32) -> i16 = \"int.convert\";\nfn Int32ToUint16(a: i32) -> u16 = \"int.convert\";\nfn Uint32ToInt16(a: u32) -> i16 = \"int.convert\";\nfn Uint32ToUint16(a: u32) -> u16 = \"int.convert\";\nfn IntLiteralToInt16(a: Core.IntLiteral()) -> i16 = \"int.convert\";\nfn IntLiteralToUint16(a: Core.IntLiteral()) -> u16 = \"int.convert\";\n\n// Widening\nfn Int32ToInt64(a: i32) -> i64 = \"int.convert\";\nfn Int32ToUint64(a: i32) -> u64 = \"int.convert\";\nfn Uint32ToInt64(a: u32) -> i64 = \"int.convert\";\nfn Uint32ToUint64(a: u32) -> u64 = \"int.convert\";\nfn Int32ToIntLiteral(a: i32) -> Core.IntLiteral() = \"int.convert\";\nfn Uint32ToIntLiteral(a: u32) -> Core.IntLiteral() = \"int.convert\";\n\n// char conversion\nfn UInt8ToChar(a: u8)   -> u8 = \"int.convert_char\";\nfn UInt16ToChar(a: u16) -> u8 = \"int.convert_char\";\nfn UInt32ToChar(a: u32) -> u8 = \"int.convert_char\";\nfn UInt64ToChar(a: u64) -> u8 = \"int.convert_char\";\n\nclass Expect[T:! type](N:! T) {}\nfn Test[T:! type](N:! T) -> Expect(N) { return {}; }\n\n// --- runtime_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nfn SizePreserving(a: i32) -> u32 {\n  //@dump-sem-ir-begin\n  return Int32ToUint32(a);\n  //@dump-sem-ir-end\n}\n\nfn Narrowing(a: i32) -> i16 {\n  //@dump-sem-ir-begin\n  return Int32ToInt16(a);\n  //@dump-sem-ir-end\n}\n\nfn Widening(a: i32) -> i64 {\n  //@dump-sem-ir-begin\n  return Int32ToInt64(a);\n  //@dump-sem-ir-end\n}\n\n// --- fail_self_test.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nfn F() {\n  // Ensure our testing machinery works.\n  // CHECK:STDERR: fail_self_test.carbon:[[@LINE+7]]:3: error: cannot convert expression of type `Expect(0)` to `Expect(1)` with `as` [ConversionFailure]\n  // CHECK:STDERR:   Test(Int32ToInt32(0)) as Expect(1 as i32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_self_test.carbon:[[@LINE+4]]:3: note: type `Expect(0)` does not implement interface `Core.As(Expect(1))` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   Test(Int32ToInt32(0)) as Expect(1 as i32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Test(Int32ToInt32(0)) as Expect(1 as i32);\n}\n\n// --- identity.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nfn F() {\n  Test(Int32ToInt32(-0x8000_0000)) as Expect(-0x8000_0000 as i32);\n  Test(Int32ToInt32(-1)) as Expect(-1 as i32);\n  Test(Int32ToInt32(0)) as Expect(0 as i32);\n  Test(Int32ToInt32(0x7FFF_FFFF)) as Expect(0x7FFF_FFFF as i32);\n\n  Test(Uint32ToUint32(0)) as Expect(0 as u32);\n  Test(Uint32ToUint32(0x7FFF_FFFF)) as Expect(0x7FFF_FFFF as u32);\n  Test(Uint32ToUint32(0x8000_0000)) as Expect(0x8000_0000 as u32);\n  Test(Uint32ToUint32(0xFFFF_FFFF)) as Expect(0xFFFF_FFFF as u32);\n\n  Test(IntLiteralToIntLiteral(0x1_0000_0000_0000_0000)) as\n      Expect(0x1_0000_0000_0000_0000);\n  Test(IntLiteralToIntLiteral(-1)) as Expect(-1);\n}\n\n// --- same_size.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nfn F() {\n  Test(Int32ToUint32(-0x8000_0000)) as Expect(0x8000_0000 as u32);\n  Test(Int32ToUint32(-1)) as Expect(0xFFFF_FFFF as u32);\n  Test(Int32ToUint32(0)) as Expect(0 as u32);\n  Test(Int32ToUint32(0x7FFF_FFFF)) as Expect(0x7FFF_FFFF as u32);\n\n  Test(Uint32ToInt32(0)) as Expect(0 as i32);\n  Test(Uint32ToInt32(0x7FFF_FFFF)) as Expect(0x7FFF_FFFF as i32);\n  Test(Uint32ToInt32(0x8000_0000)) as Expect(-0x8000_0000 as i32);\n  Test(Uint32ToInt32(0xFFFF_FFFF)) as Expect(-1 as i32);\n}\n\n// --- truncate.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nfn F() {\n  Test(Int32ToInt16(-0x8000_0000)) as Expect(0 as i16);\n  Test(Int32ToInt16(-0x7FFF_EDCC)) as Expect(0x1234 as i16);\n  Test(Int32ToInt16(-0x7FFF_1234)) as Expect(-0x1234 as i16);\n  Test(Int32ToInt16(-0x8000)) as Expect(-0x8000 as i16);\n  Test(Int32ToInt16(-1)) as Expect(-1 as i16);\n  Test(Int32ToInt16(0)) as Expect(0 as i16);\n  Test(Int32ToInt16(0x7FFF)) as Expect(0x7FFF as i16);\n  Test(Int32ToInt16(0xFFFF)) as Expect(-1 as i16);\n  Test(Int32ToInt16(0x7FFF_1234)) as Expect(0x1234 as i16);\n  Test(Int32ToInt16(0x7FFF_EDCC)) as Expect(-0x1234 as i16);\n  Test(Int32ToInt16(0x7FFF_FFFF)) as Expect(-1 as i16);\n\n  Test(Int32ToUint16(-0x8000_0000)) as Expect(0 as u16);\n  Test(Int32ToUint16(-0x7FFF_EDCC)) as Expect(0x1234 as u16);\n  Test(Int32ToUint16(-0x7FFF_1234)) as Expect(0xEDCC as u16);\n  Test(Int32ToUint16(-0x8000)) as Expect(0x8000 as u16);\n  Test(Int32ToUint16(-1)) as Expect(0xFFFF as u16);\n  Test(Int32ToUint16(0)) as Expect(0 as u16);\n  Test(Int32ToUint16(0x7FFF)) as Expect(0x7FFF as u16);\n  Test(Int32ToUint16(0xFFFF)) as Expect(0xFFFF as u16);\n  Test(Int32ToUint16(0x7FFF_1234)) as Expect(0x1234 as u16);\n  Test(Int32ToUint16(0x7FFF_EDCC)) as Expect(0xEDCC as u16);\n  Test(Int32ToUint16(0x7FFF_FFFF)) as Expect(0xFFFF as u16);\n\n  Test(Uint32ToInt16(0x8000_0000)) as Expect(0 as i16);\n  Test(Uint32ToInt16(0xFFFF_1234)) as Expect(0x1234 as i16);\n  Test(Uint32ToInt16(0xFFFF_EDCC)) as Expect(-0x1234 as i16);\n  Test(Uint32ToInt16(0xFFFF_8000)) as Expect(-0x8000 as i16);\n  Test(Uint32ToInt16(0xFFFF_FFFF)) as Expect(-1 as i16);\n  Test(Uint32ToInt16(0)) as Expect(0 as i16);\n  Test(Uint32ToInt16(0x7FFF)) as Expect(0x7FFF as i16);\n  Test(Uint32ToInt16(0xFFFF)) as Expect(-1 as i16);\n  Test(Uint32ToInt16(0x7FFF_1234)) as Expect(0x1234 as i16);\n  Test(Uint32ToInt16(0x7FFF_EDCC)) as Expect(-0x1234 as i16);\n  Test(Uint32ToInt16(0x7FFF_FFFF)) as Expect(-1 as i16);\n\n  Test(Uint32ToUint16(0x8000_0000)) as Expect(0 as u16);\n  Test(Uint32ToUint16(0xFFFF_1234)) as Expect(0x1234 as u16);\n  Test(Uint32ToUint16(0xFFFF_EDCC)) as Expect(0xEDCC as u16);\n  Test(Uint32ToUint16(0xFFFF_8000)) as Expect(0x8000 as u16);\n  Test(Uint32ToUint16(0xFFFF_FFFF)) as Expect(0xFFFF as u16);\n  Test(Uint32ToUint16(0)) as Expect(0 as u16);\n  Test(Uint32ToUint16(0x7FFF)) as Expect(0x7FFF as u16);\n  Test(Uint32ToUint16(0xFFFF)) as Expect(0xFFFF as u16);\n  Test(Uint32ToUint16(0x7FFF_1234)) as Expect(0x1234 as u16);\n  Test(Uint32ToUint16(0x7FFF_EDCC)) as Expect(0xEDCC as u16);\n  Test(Uint32ToUint16(0x7FFF_FFFF)) as Expect(0xFFFF as u16);\n\n  Test(IntLiteralToInt16(0)) as Expect(0 as i16);\n  Test(IntLiteralToInt16(0x7FFF)) as Expect(0x7FFF as i16);\n  Test(IntLiteralToInt16(0x8000)) as Expect(-0x8000 as i16);\n  Test(IntLiteralToInt16(0xFFFF)) as Expect(-1 as i16);\n  Test(IntLiteralToInt16(0x1_2345)) as Expect(0x2345 as i16);\n  Test(IntLiteralToInt16(-1)) as Expect(-1 as i16);\n\n  Test(IntLiteralToUint16(0)) as Expect(0 as u16);\n  Test(IntLiteralToUint16(0x7FFF)) as Expect(0x7FFF as u16);\n  Test(IntLiteralToUint16(0x8000)) as Expect(0x8000 as u16);\n  Test(IntLiteralToUint16(0xFFFF)) as Expect(0xFFFF as u16);\n  Test(IntLiteralToUint16(0x1_2345)) as Expect(0x2345 as u16);\n  Test(IntLiteralToUint16(-1)) as Expect(0xFFFF as u16);\n}\n\n// --- zero_extend.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nfn F() {\n  Test(Uint32ToInt64(0)) as Expect(0 as i64);\n  Test(Uint32ToInt64(0x1234_5678)) as Expect(0x1234_5678 as i64);\n  Test(Uint32ToInt64(0x7FFF_FFFF)) as Expect(0x7FFF_FFFF as i64);\n  Test(Uint32ToInt64(0x8000_0000)) as Expect(0x8000_0000 as i64);\n  Test(Uint32ToInt64(0xFFFF_FFFF)) as Expect(0xFFFF_FFFF as i64);\n\n  Test(Uint32ToUint64(0)) as Expect(0 as u64);\n  Test(Uint32ToUint64(0x1234_5678)) as Expect(0x1234_5678 as u64);\n  Test(Uint32ToUint64(0x7FFF_FFFF)) as Expect(0x7FFF_FFFF as u64);\n  Test(Uint32ToUint64(0x8000_0000)) as Expect(0x8000_0000 as u64);\n  Test(Uint32ToUint64(0xFFFF_FFFF)) as Expect(0xFFFF_FFFF as u64);\n\n  Test(Uint32ToIntLiteral(0x1234_5678)) as Expect(0x1234_5678);\n  Test(Uint32ToIntLiteral(0x8765_4321)) as Expect(0x8765_4321);\n  Test(Uint32ToIntLiteral(0xFFFF_FFFF)) as Expect(0xFFFF_FFFF);\n}\n\n// --- sign_extend.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nfn F() {\n  Test(Int32ToInt64(0)) as Expect(0 as i64);\n  Test(Int32ToInt64(0x1234_5678)) as Expect(0x1234_5678 as i64);\n  Test(Int32ToInt64(0x7FFF_FFFF)) as Expect(0x7FFF_FFFF as i64);\n  Test(Int32ToInt64(-1)) as Expect(-1 as i64);\n\n  Test(Int32ToUint64(0)) as Expect(0 as u64);\n  Test(Int32ToUint64(0x1234_5678)) as Expect(0x1234_5678 as u64);\n  Test(Int32ToUint64(0x7FFF_FFFF)) as Expect(0x7FFF_FFFF as u64);\n  Test(Int32ToUint64(-1)) as Expect(0xFFFF_FFFF_FFFF_FFFF as u64);\n  Test(Int32ToUint64(-0x8000_0000)) as Expect(0xFFFF_FFFF_8000_0000 as u64);\n\n  Test(Int32ToIntLiteral(0x1234_5678)) as Expect(0x1234_5678);\n  Test(Int32ToIntLiteral(-0x1234_5678)) as Expect(-0x1234_5678);\n  Test(Int32ToIntLiteral(-1)) as Expect(-1);\n}\n\n// --- fail_not_constant.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nlet not_constant: Core.IntLiteral() = 0;\n\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE+8]]:33: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let convert_not_constant: i16 = IntLiteralToInt16(not_constant);\n// CHECK:STDERR:                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE-7]]:1: in import [InImport]\n// CHECK:STDERR: int_ops.carbon:16:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn IntLiteralToInt16(a: Core.IntLiteral()) -> i16 = \"int.convert\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet convert_not_constant: i16 = IntLiteralToInt16(not_constant);\n\n\n// --- char_conversion.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nfn F() {\n  // u8 \\u2192 char\n  Test(UInt8ToChar(0x00)) as Expect(0x00 as u8);\n  Test(UInt8ToChar(0x80)) as Expect(0x80 as u8);\n  Test(UInt8ToChar(0xFF)) as Expect(0xFF as u8);\n\n  // u16 \\u2192 i64\n  Test(UInt16ToChar(0x0000)) as Expect(0x00 as u8);\n  Test(UInt16ToChar(0xFF12)) as Expect(0x12 as u8);\n  Test(UInt16ToChar(0xFFFF)) as Expect(0xFF as u8);\n\n  // u32 \\u2192 char\n  Test(UInt32ToChar(0x0000_0000)) as Expect(0x00 as u8);\n  Test(UInt32ToChar(0x8000_0012)) as Expect(0x12 as u8);\n  Test(UInt32ToChar(0xFFFF_FF12)) as Expect(0x12 as u8);\n  Test(UInt32ToChar(0xFFFF_FFFF)) as Expect(0xFF as u8);\n\n  // u64 \\u2192 char\n  Test(UInt64ToChar(0x0)) as Expect(0x00 as u8);\n  Test(UInt64ToChar(0x8000_0000_0000_0012)) as Expect(0x12 as u8);\n  Test(UInt64ToChar(0xFFFF_FFFF_FFFF_FF12)) as Expect(0x12 as u8);\n\n  Test(UInt64ToChar(0xFFFF_FFFF_FFFF_FFFF)) as Expect(0xFF as u8);\n\n}\n\n// CHECK:STDOUT: --- runtime_call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]\n// CHECK:STDOUT:   %Int32ToUint32.type: type = fn_type @Int32ToUint32 [concrete]\n// CHECK:STDOUT:   %Int32ToUint32: %Int32ToUint32.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_16: Core.IntLiteral = int_value 16 [concrete]\n// CHECK:STDOUT:   %i16: type = class_type @Int, @Int(%int_16) [concrete]\n// CHECK:STDOUT:   %Int32ToInt16.type: type = fn_type @Int32ToInt16 [concrete]\n// CHECK:STDOUT:   %Int32ToInt16: %Int32ToInt16.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %i64: type = class_type @Int, @Int(%int_64) [concrete]\n// CHECK:STDOUT:   %Int32ToInt64.type: type = fn_type @Int32ToInt64 [concrete]\n// CHECK:STDOUT:   %Int32ToInt64: %Int32ToInt64.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Int32ToUint32: %Int32ToUint32.type = import_ref Main//int_ops, Int32ToUint32, loaded [concrete = constants.%Int32ToUint32]\n// CHECK:STDOUT:   %Main.Int32ToInt16: %Int32ToInt16.type = import_ref Main//int_ops, Int32ToInt16, loaded [concrete = constants.%Int32ToInt16]\n// CHECK:STDOUT:   %Main.Int32ToInt64: %Int32ToInt64.type = import_ref Main//int_ops, Int32ToInt64, loaded [concrete = constants.%Int32ToInt64]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @SizePreserving(%a.param: %i32) -> out %return.param: %u32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Int32ToUint32.ref: %Int32ToUint32.type = name_ref Int32ToUint32, imports.%Main.Int32ToUint32 [concrete = constants.%Int32ToUint32]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %Int32ToUint32.call: init %u32 = call %Int32ToUint32.ref(%a.ref)\n// CHECK:STDOUT:   return %Int32ToUint32.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Narrowing(%a.param: %i32) -> out %return.param: %i16 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Int32ToInt16.ref: %Int32ToInt16.type = name_ref Int32ToInt16, imports.%Main.Int32ToInt16 [concrete = constants.%Int32ToInt16]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %Int32ToInt16.call: init %i16 = call %Int32ToInt16.ref(%a.ref)\n// CHECK:STDOUT:   return %Int32ToInt16.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Widening(%a.param: %i32) -> out %return.param: %i64 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Int32ToInt64.ref: %Int32ToInt64.type = name_ref Int32ToInt64, imports.%Main.Int32ToInt64 [concrete = constants.%Int32ToInt64]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %Int32ToInt64.call: init %i64 = call %Int32ToInt64.ref(%a.ref)\n// CHECK:STDOUT:   return %Int32ToInt64.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/convert_checked.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/uint.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/convert_checked.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/convert_checked.carbon\n\n// --- int_ops.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn NegateI32(a: i32) -> i32 = \"int.snegate\";\nfn SubI32(a: i32, b: i32) -> i32 = \"int.ssub\";\nfn AddU32(a: u32, b: u32) -> u32 = \"int.uadd\";\nfn IntLiteral() -> type = \"int_literal.make_type\";\n\n// Size preserving\nfn Int32ToInt32(a: i32) -> i32 = \"int.convert_checked\";\nfn Int32ToUint32(a: i32) -> u32 = \"int.convert_checked\";\nfn Uint32ToInt32(a: u32) -> i32 = \"int.convert_checked\";\nfn Uint32ToUint32(a: u32) -> u32 = \"int.convert_checked\";\nfn IntLiteralToIntLiteral(a: IntLiteral()) -> IntLiteral() =\n    \"int.convert_checked\";\n\n// Narrowing\nfn Int32ToInt16(a: i32) -> i16 = \"int.convert_checked\";\nfn Int32ToUint16(a: i32) -> u16 = \"int.convert_checked\";\nfn Uint32ToInt16(a: u32) -> i16 = \"int.convert_checked\";\nfn Uint32ToUint16(a: u32) -> u16 = \"int.convert_checked\";\nfn IntLiteralToInt16(a: IntLiteral()) -> i16 = \"int.convert_checked\";\nfn IntLiteralToUint16(a: IntLiteral()) -> u16 = \"int.convert_checked\";\n\n// Widening\nfn Int32ToInt64(a: i32) -> i64 = \"int.convert_checked\";\nfn Int32ToUint64(a: i32) -> u64 = \"int.convert_checked\";\nfn Uint32ToInt64(a: u32) -> i64 = \"int.convert_checked\";\nfn Uint32ToUint64(a: u32) -> u64 = \"int.convert_checked\";\nfn Int32ToIntLiteral(a: i32) -> IntLiteral() = \"int.convert_checked\";\nfn Uint32ToUintLiteral(a: u32) -> IntLiteral() = \"int.convert_checked\";\n\n// --- runtime_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\n//@dump-sem-ir-begin\nlet SizePreserving: u32 = Int32ToUint32(1);\nlet Narrowing: i16 = Int32ToInt16(1);\nlet Widening: i64 = Int32ToInt64(1);\n//@dump-sem-ir-end\n\n// --- identity.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nlet a: i32 = Int32ToInt32(0);\nlet b: i32 = Int32ToInt32(0x7FFF_FFFF);\nlet c: i32 = Int32ToInt32(SubI32(NegateI32(0x7FFF_FFFF), 1));\nlet d: IntLiteral() = IntLiteralToIntLiteral(Int32ToIntLiteral(NegateI32(1)));\n\n// --- same_size.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nlet max: u32 = Int32ToUint32(0x7FFF_FFFF);\nlet max_roundtrip: i32 = Uint32ToInt32(Int32ToUint32(0x7FFF_FFFF));\n\n// --- truncate.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nlet a: u16 = Int32ToUint16(0);\nlet b: u16 = Int32ToUint16(0xFFFF);\n\nlet c: i16 = Int32ToInt16(0x7FFF);\nlet d: i16 = Int32ToInt16(NegateI32(0x8000));\n\nlet e: u16 = Uint32ToUint16(Int32ToUint32(0));\nlet f: u16 = Uint32ToUint16(Int32ToUint32(0xFFFF));\n\nlet g: i16 = Uint32ToInt16(Int32ToUint32(0));\nlet h: i16 = Uint32ToInt16(Int32ToUint32(0x7FFF));\n\nlet lit_i16_min: i16 = IntLiteralToInt16(Int32ToIntLiteral(NegateI32(0x8000)));\nlet lit_i16_max: i16 = IntLiteralToInt16(Int32ToIntLiteral(0x7FFF));\n\nlet lit_u16_min: u16 = IntLiteralToUint16(Int32ToIntLiteral(0));\nlet lit_u16_max: u16 = IntLiteralToUint16(Int32ToIntLiteral(0xFFFF));\n\n// --- zero_extend.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nlet a: u64 = Uint32ToUint64(Int32ToUint32(0));\nlet b: u64 = Uint32ToUint64(\n  AddU32(\n    AddU32(Int32ToUint32(0x7FFF_FFFF), Int32ToUint32(0x7FFF_FFFF)),\n    Int32ToUint32(1)));\n\nlet c: i64 = Uint32ToInt64(Int32ToUint32(0));\nlet d: i64 = Uint32ToInt64(\n  AddU32(\n    AddU32(Int32ToUint32(0x7FFF_FFFF), Int32ToUint32(0x7FFF_FFFF)),\n    Int32ToUint32(1)));\n\n// --- sign_extend.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nlet a: u64 = Int32ToUint64(0);\nlet b: u64 = Int32ToUint64(0x7FFF_FFFF);\n\nlet c: i64 = Int32ToInt64(SubI32(NegateI32(0x7FFF_FFFF), 1));\nlet d: i64 = Int32ToInt64(0x7FFF_FFFF);\n\n// --- fail_too_large_u32_for_i32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nlet max_plus_one: i32 =\n  // CHECK:STDERR: fail_too_large_u32_for_i32.carbon:[[@LINE+4]]:3: error: integer value 2147483648 too large for type `i32` [IntTooLargeForType]\n  // CHECK:STDERR:   Uint32ToInt32(\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Uint32ToInt32(\n    AddU32(Int32ToUint32(0x7FFF_FFFF),\n           Int32ToUint32(1)));\n\n// --- fail_too_large_i32_for_i16.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\n// CHECK:STDERR: fail_too_large_i32_for_i16.carbon:[[@LINE+4]]:25: error: integer value 32768 too large for type `i16` [IntTooLargeForType]\n// CHECK:STDERR: let max_plus_one: i16 = Int32ToInt16(0x8000);\n// CHECK:STDERR:                         ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet max_plus_one: i16 = Int32ToInt16(0x8000);\n\n// --- fail_too_large_i32_for_u16.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\n// CHECK:STDERR: fail_too_large_i32_for_u16.carbon:[[@LINE+4]]:25: error: integer value 65536 too large for type `u16` [IntTooLargeForType]\n// CHECK:STDERR: let max_plus_one: u16 = Int32ToUint16(0x1_0000);\n// CHECK:STDERR:                         ^~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet max_plus_one: u16 = Int32ToUint16(0x1_0000);\n\n// --- fail_too_large_u32_for_i16.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\n// CHECK:STDERR: fail_too_large_u32_for_i16.carbon:[[@LINE+4]]:25: error: integer value 32768 too large for type `i16` [IntTooLargeForType]\n// CHECK:STDERR: let max_plus_one: i16 = Uint32ToInt16(Int32ToUint32(0x8000));\n// CHECK:STDERR:                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet max_plus_one: i16 = Uint32ToInt16(Int32ToUint32(0x8000));\n\n// --- fail_too_large_u32_for_u16.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\n// CHECK:STDERR: fail_too_large_u32_for_u16.carbon:[[@LINE+4]]:25: error: integer value 65536 too large for type `u16` [IntTooLargeForType]\n// CHECK:STDERR: let max_plus_one: u16 = Uint32ToUint16(Int32ToUint32(0x1_0000));\n// CHECK:STDERR:                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet max_plus_one: u16 = Uint32ToUint16(Int32ToUint32(0x1_0000));\n\n// --- fail_negative_i32_to_u16.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\n// CHECK:STDERR: fail_negative_i32_to_u16.carbon:[[@LINE+4]]:29: error: negative integer value -1 converted to unsigned type `u16` [NegativeIntInUnsignedType]\n// CHECK:STDERR: let minus_one_to_u16: u16 = Int32ToUint16(SubI32(0, 1));\n// CHECK:STDERR:                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet minus_one_to_u16: u16 = Int32ToUint16(SubI32(0, 1));\n\n// --- fail_negative_i32_to_u32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\n// CHECK:STDERR: fail_negative_i32_to_u32.carbon:[[@LINE+4]]:29: error: negative integer value -1 converted to unsigned type `u32` [NegativeIntInUnsignedType]\n// CHECK:STDERR: let minus_one_to_u32: u32 = Int32ToUint32(SubI32(0, 1));\n// CHECK:STDERR:                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet minus_one_to_u32: u32 = Int32ToUint32(SubI32(0, 1));\n\n// --- fail_negative_i32_to_u64.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\n// CHECK:STDERR: fail_negative_i32_to_u64.carbon:[[@LINE+4]]:29: error: negative integer value -1 converted to unsigned type `u64` [NegativeIntInUnsignedType]\n// CHECK:STDERR: let minus_one_to_u64: u64 = Int32ToUint64(SubI32(0, 1));\n// CHECK:STDERR:                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet minus_one_to_u64: u64 = Int32ToUint64(SubI32(0, 1));\n\n// --- fail_too_small_i32_for_i16.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\n// CHECK:STDERR: fail_too_small_i32_for_i16.carbon:[[@LINE+4]]:26: error: integer value -32769 too large for type `i16` [IntTooLargeForType]\n// CHECK:STDERR: let min_minus_one: i16 = Int32ToInt16(NegateI32(0x8001));\n// CHECK:STDERR:                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet min_minus_one: i16 = Int32ToInt16(NegateI32(0x8001));\n\n// --- fail_not_constant.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"int_ops\";\n\nlet not_constant: i32 = 0;\n\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE+8]]:40: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let convert_not_constant_narrow: i16 = Int32ToInt16(not_constant);\n// CHECK:STDERR:                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE-7]]:1: in import [InImport]\n// CHECK:STDERR: int_ops.carbon:18:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn Int32ToInt16(a: i32) -> i16 = \"int.convert_checked\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet convert_not_constant_narrow: i16 = Int32ToInt16(not_constant);\n\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE+8]]:38: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let convert_not_constant_same: i32 = Int32ToInt32(not_constant);\n// CHECK:STDERR:                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE-17]]:1: in import [InImport]\n// CHECK:STDERR: int_ops.carbon:10:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn Int32ToInt32(a: i32) -> i32 = \"int.convert_checked\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet convert_not_constant_same: i32 = Int32ToInt32(not_constant);\n\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE+8]]:39: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let convert_not_constant_widen: i64 = Int32ToInt64(not_constant);\n// CHECK:STDERR:                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_not_constant.carbon:[[@LINE-27]]:1: in import [InImport]\n// CHECK:STDERR: int_ops.carbon:26:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn Int32ToInt64(a: i32) -> i64 = \"int.convert_checked\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet convert_not_constant_widen: i64 = Int32ToInt64(not_constant);\n\n// CHECK:STDOUT: --- runtime_call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.4a9: type = pattern_type %u32 [concrete]\n// CHECK:STDOUT:   %Int32ToUint32.type: type = fn_type @Int32ToUint32 [concrete]\n// CHECK:STDOUT:   %Int32ToUint32: %Int32ToUint32.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cf3: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.255: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.58d: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.e45, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.cf3 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.58d) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.979: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.7c3: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.979, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.47b: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_1.c1d: %u32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_16: Core.IntLiteral = int_value 16 [concrete]\n// CHECK:STDOUT:   %i16: type = class_type @Int, @Int(%int_16) [concrete]\n// CHECK:STDOUT:   %pattern_type.88f: type = pattern_type %i16 [concrete]\n// CHECK:STDOUT:   %Int32ToInt16.type: type = fn_type @Int32ToInt16 [concrete]\n// CHECK:STDOUT:   %Int32ToInt16: %Int32ToInt16.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.c22: %i16 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %i64: type = class_type @Int, @Int(%int_64) [concrete]\n// CHECK:STDOUT:   %pattern_type.a10: type = pattern_type %i64 [concrete]\n// CHECK:STDOUT:   %Int32ToInt64.type: type = fn_type @Int32ToInt64 [concrete]\n// CHECK:STDOUT:   %Int32ToInt64: %Int32ToInt64.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.a95: %i64 = int_value 1 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Int32ToUint32: %Int32ToUint32.type = import_ref Main//int_ops, Int32ToUint32, loaded [concrete = constants.%Int32ToUint32]\n// CHECK:STDOUT:   %Main.Int32ToInt16: %Int32ToInt16.type = import_ref Main//int_ops, Int32ToInt16, loaded [concrete = constants.%Int32ToInt16]\n// CHECK:STDOUT:   %Main.Int32ToInt64: %Int32ToInt64.type = import_ref Main//int_ops, Int32ToInt64, loaded [concrete = constants.%Int32ToInt64]\n// CHECK:STDOUT:   %Core.import_ref.b25: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.255)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.e45 = impl_witness_table (%Core.import_ref.b25), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %SizePreserving.patt: %pattern_type.4a9 = value_binding_pattern SizePreserving [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %u32: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:   %.loc6_42.1: %u32 = value_of_initializer @__global_init.%Int32ToUint32.call [concrete = constants.%int_1.c1d]\n// CHECK:STDOUT:   %.loc6_42.2: %u32 = converted @__global_init.%Int32ToUint32.call, %.loc6_42.1 [concrete = constants.%int_1.c1d]\n// CHECK:STDOUT:   %SizePreserving: %u32 = value_binding SizePreserving, %.loc6_42.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %Narrowing.patt: %pattern_type.88f = value_binding_pattern Narrowing [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i16: type = type_literal constants.%i16 [concrete = constants.%i16]\n// CHECK:STDOUT:   %.loc7_36.1: %i16 = value_of_initializer @__global_init.%Int32ToInt16.call [concrete = constants.%int_1.c22]\n// CHECK:STDOUT:   %.loc7_36.2: %i16 = converted @__global_init.%Int32ToInt16.call, %.loc7_36.1 [concrete = constants.%int_1.c22]\n// CHECK:STDOUT:   %Narrowing: %i16 = value_binding Narrowing, %.loc7_36.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %Widening.patt: %pattern_type.a10 = value_binding_pattern Widening [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i64: type = type_literal constants.%i64 [concrete = constants.%i64]\n// CHECK:STDOUT:   %.loc8_35.1: %i64 = value_of_initializer @__global_init.%Int32ToInt64.call [concrete = constants.%int_1.a95]\n// CHECK:STDOUT:   %.loc8_35.2: %i64 = converted @__global_init.%Int32ToInt64.call, %.loc8_35.1 [concrete = constants.%int_1.a95]\n// CHECK:STDOUT:   %Widening: %i64 = value_binding Widening, %.loc8_35.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Int32ToUint32.ref: %Int32ToUint32.type = name_ref Int32ToUint32, imports.%Main.Int32ToUint32 [concrete = constants.%Int32ToUint32]\n// CHECK:STDOUT:   %int_1.loc6: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc6: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc6_41.1: <bound method> = bound_method %int_1.loc6, %impl.elem0.loc6 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_41.2: <bound method> = bound_method %int_1.loc6, %specific_fn.loc6 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %i32 = call %bound_method.loc6_41.2(%int_1.loc6) [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc6_41.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc6_41.2: %i32 = converted %int_1.loc6, %.loc6_41.1 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %Int32ToUint32.call: init %u32 = call %Int32ToUint32.ref(%.loc6_41.2) [concrete = constants.%int_1.c1d]\n// CHECK:STDOUT:   %Int32ToInt16.ref: %Int32ToInt16.type = name_ref Int32ToInt16, imports.%Main.Int32ToInt16 [concrete = constants.%Int32ToInt16]\n// CHECK:STDOUT:   %int_1.loc7: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc7: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc7_35.1: <bound method> = bound_method %int_1.loc7, %impl.elem0.loc7 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_35.2: <bound method> = bound_method %int_1.loc7, %specific_fn.loc7 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %i32 = call %bound_method.loc7_35.2(%int_1.loc7) [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc7_35.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc7_35.2: %i32 = converted %int_1.loc7, %.loc7_35.1 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %Int32ToInt16.call: init %i16 = call %Int32ToInt16.ref(%.loc7_35.2) [concrete = constants.%int_1.c22]\n// CHECK:STDOUT:   %Int32ToInt64.ref: %Int32ToInt64.type = name_ref Int32ToInt64, imports.%Main.Int32ToInt64 [concrete = constants.%Int32ToInt64]\n// CHECK:STDOUT:   %int_1.loc8: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc8: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc8_34.1: <bound method> = bound_method %int_1.loc8, %impl.elem0.loc8 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_34.2: <bound method> = bound_method %int_1.loc8, %specific_fn.loc8 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %i32 = call %bound_method.loc8_34.2(%int_1.loc8) [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc8_34.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc8_34.2: %i32 = converted %int_1.loc8, %.loc8_34.1 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %Int32ToInt64.call: init %i64 = call %Int32ToInt64.ref(%.loc8_34.2) [concrete = constants.%int_1.a95]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/eq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/eq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/eq.carbon\n\n// --- int_eq.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Eq(a: i32, b: i32) -> bool = \"int.eq\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  true_ as (if Eq(1, 1) then True else False);\n  false_ as (if Eq(1, 2) then True else False);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> bool {\n  //@dump-sem-ir-begin\n  return Eq(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.eq\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn WrongResult(a: i32, b: i32) -> i32 = \"int.eq\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn WrongResult(a: i32, b: i32) -> i32 = \"int.eq\";\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Eq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.eq\";\n\nclass Expect(B:! bool) {}\nfn Test(B:! bool) -> Expect(B) { return {}; }\n\nfn F() {\n  Test(Eq(5, 5)) as Expect(true);\n  Test(Eq(5, 6)) as Expect(false);\n  Test(Eq(-1, -1)) as Expect(true);\n  Test(Eq(-1, 1)) as Expect(false);\n}\n\n// --- mixed.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Eq(a: Core.IntLiteral(), b: i32) -> bool = \"int.eq\";\n\nclass Expect(B:! bool) {}\nfn Test(B:! bool) -> Expect(B) { return {}; }\n\nfn F() {\n  Test(Eq(5, 5)) as Expect(true);\n  Test(Eq(5, 6)) as Expect(false);\n  Test(Eq(-1, -1)) as Expect(true);\n  Test(Eq(-1, 1)) as Expect(false);\n}\n\n// --- fail_runtime_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Eq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.eq\";\n\nfn Test(n: Core.IntLiteral()) {\n  // OK\n  Eq(1, 1);\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   Eq(n, 1);\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-8]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn Eq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.eq\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Eq(n, 1);\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   Eq(1, n);\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-16]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn Eq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.eq\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Eq(1, n);\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   Eq(n, n);\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-24]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn Eq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.eq\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Eq(n, n);\n}\n\n// CHECK:STDOUT: --- int_eq.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Eq.type: type = fn_type @Eq [concrete]\n// CHECK:STDOUT:   %Eq: %Eq.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Eq.ref: %Eq.type = name_ref Eq, file.%Eq.decl [concrete = constants.%Eq]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Eq.call: init bool = call %Eq.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Eq.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/greater.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/greater.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/greater.carbon\n\n// --- int_greater.carbon\n\nfn Greater(a: i32, b: i32) -> bool = \"int.greater\";\nfn Negate(a: i32) -> i32 = \"int.snegate\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  false_ as (if Greater(1, 2) then True else False);\n  false_ as (if Greater(1, 1) then True else False);\n  true_ as (if Greater(1, 0) then True else False);\n  false_ as (if Greater(Negate(1), 0) then True else False);\n  true_ as (if Greater(0, Negate(1)) then True else False);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> bool {\n  //@dump-sem-ir-begin\n  return Greater(a, b);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- int_greater.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Greater.type: type = fn_type @Greater [concrete]\n// CHECK:STDOUT:   %Greater: %Greater.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Greater.ref: %Greater.type = name_ref Greater, file.%Greater.decl [concrete = constants.%Greater]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Greater.call: init bool = call %Greater.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Greater.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/greater_eq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/greater_eq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/greater_eq.carbon\n\n// --- int_greater_eq.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn GreaterEq(a: i32, b: i32) -> bool = \"int.greater_eq\";\nfn Negate(a: i32) -> i32 = \"int.snegate\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  false_ as (if GreaterEq(1, 2) then True else False);\n  true_ as (if GreaterEq(1, 1) then True else False);\n  true_ as (if GreaterEq(1, 0) then True else False);\n  false_ as (if GreaterEq(Negate(1), 0) then True else False);\n  true_ as (if GreaterEq(0, Negate(1)) then True else False);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> bool {\n  //@dump-sem-ir-begin\n  return GreaterEq(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn GreaterEq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.greater_eq\";\n\nclass Expect(B:! bool) {}\nfn Test(B:! bool) -> Expect(B) { return {}; }\n\nfn F() {\n  Test(GreaterEq(5, 5)) as Expect(true);\n  Test(GreaterEq(5, 6)) as Expect(false);\n  Test(GreaterEq(6, 5)) as Expect(true);\n  Test(GreaterEq(-1, -1)) as Expect(true);\n  Test(GreaterEq(-1, 1)) as Expect(false);\n  Test(GreaterEq(1, -1)) as Expect(true);\n}\n\n// --- mixed.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn GreaterEq(a: Core.IntLiteral(), b: i32) -> bool = \"int.greater_eq\";\n\nclass Expect(B:! bool) {}\nfn Test(B:! bool) -> Expect(B) { return {}; }\n\nfn F() {\n  Test(GreaterEq(5, 5)) as Expect(true);\n  Test(GreaterEq(5, 6)) as Expect(false);\n  Test(GreaterEq(6, 5)) as Expect(true);\n  Test(GreaterEq(-1, -1)) as Expect(true);\n  Test(GreaterEq(-1, 1)) as Expect(false);\n  Test(GreaterEq(1, -1)) as Expect(true);\n}\n\n// CHECK:STDOUT: --- int_greater_eq.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %GreaterEq.type: type = fn_type @GreaterEq [concrete]\n// CHECK:STDOUT:   %GreaterEq: %GreaterEq.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %GreaterEq.ref: %GreaterEq.type = name_ref GreaterEq, file.%GreaterEq.decl [concrete = constants.%GreaterEq]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %GreaterEq.call: init bool = call %GreaterEq.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %GreaterEq.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/left_shift.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/uint.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/left_shift.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/left_shift.carbon\n\n// --- i32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Expect(N:! i32) {}\nfn Test(N:! i32) -> Expect(N) { return {}; }\n\nfn LeftShift(a: i32, b: i32) -> i32 = \"int.left_shift\";\n\nfn F() {\n  Test(LeftShift(0, 0)) as Expect(0);\n  Test(LeftShift(0, 1)) as Expect(0);\n  Test(LeftShift(0, 30)) as Expect(0);\n  Test(LeftShift(1, 30)) as Expect(0x4000_0000);\n  Test(LeftShift(5, 2)) as Expect(20);\n  Test(LeftShift(-1, 1)) as Expect(-2);\n  Test(LeftShift(-2, 1)) as Expect(-4);\n  Test(LeftShift(-3, 1)) as Expect(-6);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return LeftShift(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- u32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Expect(N:! u32) {}\nfn Test(N:! u32) -> Expect(N) { return {}; }\n\nfn LeftShift(a: u32, b: i32) -> u32 = \"int.left_shift\";\n\nfn F() {\n  Test(LeftShift(0, 0)) as Expect(0);\n  Test(LeftShift(0, 1)) as Expect(0);\n  Test(LeftShift(0, 30)) as Expect(0);\n  Test(LeftShift(1, 30)) as Expect(0x4000_0000);\n  Test(LeftShift(5, 2)) as Expect(20);\n  Test(LeftShift(0xFFFF_FFFF, 1)) as Expect(0xFFFF_FFFE);\n  Test(LeftShift(0xFFFF_FFFE, 1)) as Expect(0xFFFF_FFFC);\n  Test(LeftShift(0xABCD_EF01, 8)) as Expect(0xCDEF_0100);\n}\n\nfn RuntimeCall(a: u32, b: i32) -> u32 {\n  //@dump-sem-ir-begin\n  return LeftShift(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn LeftShift(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.left_shift\";\n\nclass Expect(N:! Core.IntLiteral()) {}\nfn Test(N:! Core.IntLiteral()) -> Expect(N) { return {}; }\n\nfn F() {\n  // Zero can be shifted by any amount.\n  Test(LeftShift(0, 0)) as Expect(0);\n  Test(LeftShift(0, 0)) as Expect(0);\n  Test(LeftShift(0, 1)) as Expect(0);\n  Test(LeftShift(0, 30)) as Expect(0);\n  Test(LeftShift(0, 1_000_000_000)) as Expect(0);\n\n  // Positive numbers can be shifted.\n  Test(LeftShift(1, 0)) as Expect(1);\n  Test(LeftShift(1, 1)) as Expect(2);\n  Test(LeftShift(2, 1)) as Expect(4);\n  Test(LeftShift(1, 2)) as Expect(4);\n  Test(LeftShift(3, 2)) as Expect(12);\n  Test(LeftShift(1, 30)) as Expect(0x4000_0000);\n  Test(LeftShift(5, 2)) as Expect(20);\n\n  // Negative numbers can be shifted too.\n  Test(LeftShift(-1, 0)) as Expect(-1);\n  Test(LeftShift(-1, 1)) as Expect(-2);\n  Test(LeftShift(-2, 1)) as Expect(-4);\n  Test(LeftShift(-3, 1)) as Expect(-6);\n\n  // Large numbers can be shifted losslessly.\n  Test(LeftShift(0xFFFF_FFFF, 1)) as Expect(0x1_FFFF_FFFE);\n  Test(LeftShift(0xFFFF_FFFE, 1)) as Expect(0x1_FFFF_FFFC);\n  Test(LeftShift(0xABCD_EF01, 8)) as Expect(0xAB_CDEF_0100);\n  Test(LeftShift(0x7FFF_FFFF_FFFF_FFFF, 1)) as Expect(0xFFFF_FFFF_FFFF_FFFE);\n  Test(LeftShift(0xFFFF_FFFF_FFFF_FFFF, 1)) as Expect(0x1_FFFF_FFFF_FFFF_FFFE);\n}\n\n// --- fail_bad_shift.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn LeftShift(a: i32, b: i32) -> i32 = \"int.left_shift\";\nfn LeftShiftLit(a: Core.IntLiteral(), b: i32) -> Core.IntLiteral() = \"int.left_shift\";\n\n// Shift greater than size is disallowed for sized types.\nlet size_1: i32 = LeftShift(1, 31);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:19: error: shift distance >= type width of 32 in `1 << 32` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let size_2: i32 = LeftShift(1, 32);\n// CHECK:STDERR:                   ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet size_2: i32 = LeftShift(1, 32);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:19: error: shift distance >= type width of 32 in `1 << 33` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let size_3: i32 = LeftShift(1, 33);\n// CHECK:STDERR:                   ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet size_3: i32 = LeftShift(1, 33);\n\n// Overflow is allowed if the shift distance is in bounds.\nlet overflow_1: i32 = LeftShift(1000, 31);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:23: error: shift distance >= type width of 32 in `1000 << 32` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let overflow_2: i32 = LeftShift(1000, 32);\n// CHECK:STDERR:                       ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet overflow_2: i32 = LeftShift(1000, 32);\n\n// Oversize shifts aren't allowed even if there's no overflow.\nlet no_overflow_1: i32 = LeftShift(0, 31);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:26: error: shift distance >= type width of 32 in `0 << 32` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let no_overflow_2: i32 = LeftShift(0, 32);\n// CHECK:STDERR:                          ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet no_overflow_2: i32 = LeftShift(0, 32);\n\n// Negative shifts aren't allowed either, even for literals, even if the lhs is zero.\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:21: error: shift distance >= type width of 32 in `1 << -1` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let negative: i32 = LeftShift(1, -1);\n// CHECK:STDERR:                     ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet negative: i32 = LeftShift(1, -1);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:26: error: shift distance >= type width of 32 in `0 << -1` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let negative_zero: i32 = LeftShift(0, -1);\n// CHECK:STDERR:                          ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet negative_zero: i32 = LeftShift(0, -1);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:39: error: shift distance negative in `1 << -1` [CompileTimeShiftNegative]\n// CHECK:STDERR: let negative_lit: Core.IntLiteral() = LeftShiftLit(1, -1);\n// CHECK:STDERR:                                       ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet negative_lit: Core.IntLiteral() = LeftShiftLit(1, -1);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:44: error: shift distance negative in `0 << -1` [CompileTimeShiftNegative]\n// CHECK:STDERR: let negative_lit_zero: Core.IntLiteral() = LeftShiftLit(0, -1);\n// CHECK:STDERR:                                            ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet negative_lit_zero: Core.IntLiteral() = LeftShiftLit(0, -1);\n\n// --- fail_literal_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn LeftShift(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.left_shift\";\n\n// CHECK:STDERR: fail_literal_overflow.carbon:[[@LINE+4]]:16: error: shift distance of 1000000000 would result in an integer whose width is greater than the maximum supported width of 8388608 [CompileTimeUnsizedShiftOutOfRange]\n// CHECK:STDERR: let bad: i32 = LeftShift(1, 1_000_000_000);\n// CHECK:STDERR:                ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet bad: i32 = LeftShift(1, 1_000_000_000);\n\n// CHECK:STDERR: fail_literal_overflow.carbon:[[@LINE+4]]:25: error: shift distance of 1000000000 would result in an integer whose width is greater than the maximum supported width of 8388608 [CompileTimeUnsizedShiftOutOfRange]\n// CHECK:STDERR: let bad_negative: i32 = LeftShift(-1, 1_000_000_000);\n// CHECK:STDERR:                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet bad_negative: i32 = LeftShift(-1, 1_000_000_000);\n\n// --- fail_comp_time_only_shift.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn LeftShiftByLit(a: i32, b: Core.IntLiteral()) -> i32 = \"int.left_shift\";\nfn LeftShiftOfLit(a: Core.IntLiteral(), b: i32) -> Core.IntLiteral() = \"int.left_shift\";\n\nvar a_lit: Core.IntLiteral() = 12;\nvar an_i32: i32 = 34;\n\n// This can't be valid: we don't have a compile-time or runtime integer value for `a_lit`.\n// CHECK:STDERR: fail_comp_time_only_shift.carbon:[[@LINE+7]]:17: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let bad1: i32 = LeftShiftByLit(an_i32, a_lit);\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_comp_time_only_shift.carbon:[[@LINE-10]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn LeftShiftByLit(a: i32, b: Core.IntLiteral()) -> i32 = \"int.left_shift\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet bad1: i32 = LeftShiftByLit(an_i32, a_lit);\n\n// TODO: This could be valid because we don't actually need the return value at runtime.\n// CHECK:STDERR: fail_comp_time_only_shift.carbon:[[@LINE+7]]:31: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let bad2: Core.IntLiteral() = LeftShiftOfLit(a_lit, an_i32);\n// CHECK:STDERR:                               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_comp_time_only_shift.carbon:[[@LINE-19]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn LeftShiftOfLit(a: Core.IntLiteral(), b: i32) -> Core.IntLiteral() = \"int.left_shift\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet bad2: Core.IntLiteral() = LeftShiftOfLit(a_lit, an_i32);\n\n// TODO: This could be valid because the literal argument has a constant value.\n// CHECK:STDERR: fail_comp_time_only_shift.carbon:[[@LINE+7]]:17: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let bad3: i32 = LeftShiftByLit(an_i32, 12);\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_comp_time_only_shift.carbon:[[@LINE-30]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn LeftShiftByLit(a: i32, b: Core.IntLiteral()) -> i32 = \"int.left_shift\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet bad3: i32 = LeftShiftByLit(an_i32, 12);\n\n// TODO: This could be valid because we don't actually need the return value at runtime.\n// CHECK:STDERR: fail_comp_time_only_shift.carbon:[[@LINE+7]]:31: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n// CHECK:STDERR: let bad4: Core.IntLiteral() = LeftShiftOfLit(12, an_i32);\n// CHECK:STDERR:                               ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_comp_time_only_shift.carbon:[[@LINE-39]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n// CHECK:STDERR: fn LeftShiftOfLit(a: Core.IntLiteral(), b: i32) -> Core.IntLiteral() = \"int.left_shift\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet bad4: Core.IntLiteral() = LeftShiftOfLit(12, an_i32);\n\n// CHECK:STDOUT: --- i32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %LeftShift.type: type = fn_type @LeftShift [concrete]\n// CHECK:STDOUT:   %LeftShift: %LeftShift.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %LeftShift.ref: %LeftShift.type = name_ref LeftShift, file.%LeftShift.decl [concrete = constants.%LeftShift]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %LeftShift.call: init %i32 = call %LeftShift.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %LeftShift.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- u32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %LeftShift.type: type = fn_type @LeftShift [concrete]\n// CHECK:STDOUT:   %LeftShift: %LeftShift.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCall(%a.param: %u32, %b.param: %i32) -> out %return.param: %u32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %LeftShift.ref: %LeftShift.type = name_ref LeftShift, file.%LeftShift.decl [concrete = constants.%LeftShift]\n// CHECK:STDOUT:   %a.ref: %u32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %LeftShift.call: init %u32 = call %LeftShift.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %LeftShift.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/left_shift_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/left_shift_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/left_shift_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.left_shift_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\nfn MixedTypes(ref a: i32, b: i64) = \"int.left_shift_assign\";\n\nfn CallMixed(ref a: i32, b: i64) {\n  //@dump-sem-ir-begin\n  MixedTypes(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.left_shift_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.left_shift_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.left_shift_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.left_shift_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.left_shift_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.left_shift_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %i64: type = class_type @Int, @Int(%int_64) [concrete]\n// CHECK:STDOUT:   %MixedTypes.type: type = fn_type @MixedTypes [concrete]\n// CHECK:STDOUT:   %MixedTypes: %MixedTypes.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallMixed(%a.param: ref %i32, %b.param: %i64) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %MixedTypes.ref: %MixedTypes.type = name_ref MixedTypes, file.%MixedTypes.decl [concrete = constants.%MixedTypes]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc16: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i64 = name_ref b, %b\n// CHECK:STDOUT:   %MixedTypes.call: init %empty_tuple.type = call %MixedTypes.ref(%.loc16, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/less.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/less.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/less.carbon\n\n// --- int_less.carbon\n\nfn Less(a: i32, b: i32) -> bool = \"int.less\";\nfn Negate(a: i32) -> i32 = \"int.snegate\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  true_ as (if Less(1, 2) then True else False);\n  false_ as (if Less(1, 1) then True else False);\n  false_ as (if Less(1, 0) then True else False);\n  true_ as (if Less(Negate(1), 0) then True else False);\n  false_ as (if Less(0, Negate(1)) then True else False);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> bool {\n  //@dump-sem-ir-begin\n  return Less(a, b);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- int_less.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Less.type: type = fn_type @Less [concrete]\n// CHECK:STDOUT:   %Less: %Less.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Less.ref: %Less.type = name_ref Less, file.%Less.decl [concrete = constants.%Less]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Less.call: init bool = call %Less.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Less.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/less_eq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/less_eq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/less_eq.carbon\n\n// --- int_less_eq.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn LessEq(a: i32, b: i32) -> bool = \"int.less_eq\";\nfn Negate(a: i32) -> i32 = \"int.snegate\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  true_ as (if LessEq(1, 2) then True else False);\n  true_ as (if LessEq(1, 1) then True else False);\n  false_ as (if LessEq(1, 0) then True else False);\n  true_ as (if LessEq(Negate(1), 0) then True else False);\n  false_ as (if LessEq(0, Negate(1)) then True else False);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> bool {\n  //@dump-sem-ir-begin\n  return LessEq(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn LessEq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.less_eq\";\n\nclass Expect(B:! bool) {}\nfn Test(B:! bool) -> Expect(B) { return {}; }\n\nfn F() {\n  Test(LessEq(5, 5)) as Expect(true);\n  Test(LessEq(5, 6)) as Expect(true);\n  Test(LessEq(6, 5)) as Expect(false);\n  Test(LessEq(-1, -1)) as Expect(true);\n  Test(LessEq(-1, 1)) as Expect(true);\n  Test(LessEq(1, -1)) as Expect(false);\n}\n\n// --- mixed.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn LessEq(a: Core.IntLiteral(), b: i32) -> bool = \"int.less_eq\";\n\nclass Expect(B:! bool) {}\nfn Test(B:! bool) -> Expect(B) { return {}; }\n\nfn F() {\n  Test(LessEq(5, 5)) as Expect(true);\n  Test(LessEq(5, 6)) as Expect(true);\n  Test(LessEq(6, 5)) as Expect(false);\n  Test(LessEq(-1, -1)) as Expect(true);\n  Test(LessEq(-1, 1)) as Expect(true);\n  Test(LessEq(1, -1)) as Expect(false);\n}\n\n// --- fail_runtime_literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn LessEq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.less_eq\";\n\nfn Test(n: Core.IntLiteral()) {\n  // OK\n  LessEq(1, 1);\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   LessEq(n, 1);\n  // CHECK:STDERR:   ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-8]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn LessEq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.less_eq\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  LessEq(n, 1);\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   LessEq(1, n);\n  // CHECK:STDERR:   ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-16]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn LessEq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.less_eq\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  LessEq(1, n);\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   LessEq(n, n);\n  // CHECK:STDERR:   ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_runtime_literal.carbon:[[@LINE-24]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: fn LessEq(a: Core.IntLiteral(), b: Core.IntLiteral()) -> bool = \"int.less_eq\";\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  LessEq(n, n);\n}\n\n// CHECK:STDOUT: --- int_less_eq.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %LessEq.type: type = fn_type @LessEq [concrete]\n// CHECK:STDOUT:   %LessEq: %LessEq.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %LessEq.ref: %LessEq.type = name_ref LessEq, file.%LessEq.decl [concrete = constants.%LessEq]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %LessEq.call: init bool = call %LessEq.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %LessEq.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/make_type_signed.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/make_type_signed.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/make_type_signed.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn IntLiteral() -> type = \"int_literal.make_type\";\nfn Int(n: IntLiteral()) -> type = \"int.make_type_signed\";\n\n// --- use_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\nfn Copy[N:! IntLiteral()](x: Int(N)) -> Int(N) = \"primitive_copy\";\n\nfn F(n: Int(64)) ->\n    //@dump-sem-ir-begin\n    Int(64)\n    //@dump-sem-ir-end\n    {\n  return Copy(n);\n}\n\nfn G(n: Int(13)) ->\n    //@dump-sem-ir-begin\n    Int(13)\n    //@dump-sem-ir-end\n    {\n  return Copy(n);\n}\n\nfn Symbolic(N:! IntLiteral(), x: Int(N)) -> Int(N) {\n  return Copy(x);\n}\n\n// --- import_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\nimport library \"use_types\";\n\nfn UseF(n: Int(64)) -> Int(64) {\n  return F(n);\n}\n\nfn UseG(n: Int(13)) -> Int(13) {\n  return G(n);\n}\n\nfn UseSymbolic(n: Int(24)) -> Int(24) {\n  return Symbolic(24, n);\n}\n\n// --- fail_zero_size.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n// CHECK:STDERR: fail_zero_size.carbon:[[@LINE+4]]:8: error: integer type width of 0 is not positive [IntWidthNotPositive]\n// CHECK:STDERR: var n: Int(0);\n// CHECK:STDERR:        ^~~~~~\n// CHECK:STDERR:\nvar n: Int(0);\n\n// --- fail_negative_size.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\nfn Negate(a: IntLiteral()) -> IntLiteral() = \"int.snegate\";\n\n// CHECK:STDERR: fail_negative_size.carbon:[[@LINE+4]]:8: error: integer type width of -1 is not positive [IntWidthNotPositive]\n// CHECK:STDERR: var n: Int(Negate(1));\n// CHECK:STDERR:        ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar n: Int(Negate(1));\n\n// --- fail_oversized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n// CHECK:STDERR: fail_oversized.carbon:[[@LINE+4]]:8: error: integer type width of 1000000000 is greater than the maximum supported width of 8388608 [IntWidthTooLarge]\n// CHECK:STDERR: var m: Int(1000000000);\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar m: Int(1000000000);\n\n// CHECK:STDOUT: --- use_types.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %i64.builtin: type = int_type signed, %int_64 [concrete]\n// CHECK:STDOUT:   %int_13: Core.IntLiteral = int_value 13 [concrete]\n// CHECK:STDOUT:   %i13.builtin: type = int_type signed, %int_13 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%n.param: %i64.builtin) -> out %return.param: %i64.builtin {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%n.param: %i13.builtin) -> out %return.param: %i13.builtin {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/make_type_unsigned.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/make_type_unsigned.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/make_type_unsigned.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn IntLiteral() -> type = \"int_literal.make_type\";\nfn UInt(n: IntLiteral()) -> type = \"int.make_type_unsigned\";\n\n// --- use_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\nfn Copy[N:! IntLiteral()](x: UInt(N)) -> UInt(N) = \"primitive_copy\";\n\nfn F(n: UInt(64)) ->\n    //@dump-sem-ir-begin\n    UInt(64)\n    //@dump-sem-ir-end\n    {\n  return Copy(n);\n}\n\nfn G(n: UInt(13)) ->\n    //@dump-sem-ir-begin\n    UInt(13)\n    //@dump-sem-ir-end\n    {\n  return Copy(n);\n}\n\nfn Symbolic(N:! IntLiteral(), x: UInt(N)) -> UInt(N)\n    {\n  return Copy(x);\n}\n\n// --- fail_zero_size.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n// CHECK:STDERR: fail_zero_size.carbon:[[@LINE+4]]:8: error: integer type width of 0 is not positive [IntWidthNotPositive]\n// CHECK:STDERR: var n: UInt(0);\n// CHECK:STDERR:        ^~~~~~~\n// CHECK:STDERR:\nvar n: UInt(0);\n\n// --- fail_negative_size.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\nfn Negate(n: i32) -> i32 = \"int.snegate\";\n\n// CHECK:STDERR: fail_negative_size.carbon:[[@LINE+4]]:8: error: integer type width of -1 is not positive [IntWidthNotPositive]\n// CHECK:STDERR: var n: UInt(Negate(1));\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar n: UInt(Negate(1));\n\n// --- fail_oversized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n// CHECK:STDERR: fail_oversized.carbon:[[@LINE+4]]:8: error: integer type width of 1000000000 is greater than the maximum supported width of 8388608 [IntWidthTooLarge]\n// CHECK:STDERR: var m: UInt(1000000000);\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar m: UInt(1000000000);\n\n// CHECK:STDOUT: --- use_types.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %u64.builtin: type = int_type unsigned, %int_64 [concrete]\n// CHECK:STDOUT:   %int_13: Core.IntLiteral = int_value 13 [concrete]\n// CHECK:STDOUT:   %u13.builtin: type = int_type unsigned, %int_13 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%n.param: %u64.builtin) -> out %return.param: %u64.builtin {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%n.param: %u13.builtin) -> out %return.param: %u13.builtin {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/neq.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/neq.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/neq.carbon\n\n// --- int_neq.carbon\n\nfn Neq(a: i32, b: i32) -> bool = \"int.neq\";\n\nclass True {}\nclass False {}\n\nfn F(true_: True, false_: False) {\n  false_ as (if Neq(1, 1) then True else False);\n  true_ as (if Neq(1, 2) then True else False);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> bool {\n  //@dump-sem-ir-begin\n  return Neq(a, b);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- int_neq.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Neq.type: type = fn_type @Neq [concrete]\n// CHECK:STDOUT:   %Neq: %Neq.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Neq.ref: %Neq.type = name_ref Neq, file.%Neq.decl [concrete = constants.%Neq]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Neq.call: init bool = call %Neq.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Neq.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/or.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/or.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/or.carbon\n\n// --- int_or.carbon\n\nfn Or(a: i32, b: i32) -> i32 = \"int.or\";\n\nvar arr: array(i32, Or(12, 10));\nlet arr_p: array(i32, 14)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Or(a, b);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- int_or.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Or.type: type = fn_type @Or [concrete]\n// CHECK:STDOUT:   %Or: %Or.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Or.ref: %Or.type = name_ref Or, file.%Or.decl [concrete = constants.%Or]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Or.call: init %i32 = call %Or.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Or.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/or_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/or_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/or_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.or_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.or_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.or_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.or_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.or_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.or_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.or_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.or_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.or_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.or_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/right_shift.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/uint.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/right_shift.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/right_shift.carbon\n\n// --- i32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Expect(N:! i32) {}\nfn Test(N:! i32) -> Expect(N) { return {}; }\n\nfn RightShift(a: i32, b: i32) -> i32 = \"int.right_shift\";\n\nfn F() {\n  Test(RightShift(0, 31)) as Expect(0);\n  Test(RightShift(1, 31)) as Expect(0);\n  Test(RightShift(1, 0)) as Expect(1);\n  Test(RightShift(1, 2)) as Expect(0);\n  Test(RightShift(22, 2)) as Expect(5);\n  Test(RightShift(-1, 1)) as Expect(-1);\n  Test(RightShift(-2, 1)) as Expect(-1);\n  Test(RightShift(-10, 2)) as Expect(-3);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return RightShift(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- u32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Expect(N:! u32) {}\nfn Test(N:! u32) -> Expect(N) { return {}; }\n\nfn RightShift(a: u32, b: i32) -> u32 = \"int.right_shift\";\n\nfn F() {\n  Test(RightShift(0, 31)) as Expect(0);\n  Test(RightShift(1, 31)) as Expect(0);\n  Test(RightShift(1, 0)) as Expect(1);\n  Test(RightShift(1, 2)) as Expect(0);\n  Test(RightShift(22, 2)) as Expect(5);\n  Test(RightShift(0xFFFF_FFFF, 1)) as Expect(0x7FFF_FFFF);\n  Test(RightShift(0xABCD_EF01, 8)) as Expect(0xAB_CDEF);\n}\n\nfn RuntimeCall(a: u32, b: i32) -> u32 {\n  //@dump-sem-ir-begin\n  return RightShift(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn RightShift(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.right_shift\";\n\nclass Expect(N:! Core.IntLiteral()) {}\nfn Test(N:! Core.IntLiteral()) -> Expect(N) { return {}; }\n\nfn F() {\n  Test(RightShift(0, 31)) as Expect(0);\n  Test(RightShift(1, 31)) as Expect(0);\n  Test(RightShift(1, 0)) as Expect(1);\n  Test(RightShift(1, 2)) as Expect(0);\n  Test(RightShift(22, 2)) as Expect(5);\n  Test(RightShift(-1, 1)) as Expect(-1);\n  Test(RightShift(-2, 1)) as Expect(-1);\n  Test(RightShift(-10, 2)) as Expect(-3);\n  Test(RightShift(0xFFFF_FFFF, 1)) as Expect(0x7FFF_FFFF);\n  Test(RightShift(0xABCD_EF01, 8)) as Expect(0xAB_CDEF);\n\n  Test(RightShift(0x1234_5678, 1_000_000_000)) as Expect(0);\n  Test(RightShift(-0x1234_5678, 1_000_000_000)) as Expect(-1);\n  Test(RightShift(0xFFFF_FFFF_FFFF_FFFF, 1_000_000_000)) as Expect(0);\n  Test(RightShift(0x7FFF_FFFF_FFFF_FFFF, 1_000_000_000)) as Expect(0);\n  Test(RightShift(-0x7FFF_FFFF_FFFF_FFFF, 1_000_000_000)) as Expect(-1);\n  Test(RightShift(-0x8000_0000_0000_0000, 1_000_000_000)) as Expect(-1);\n}\n\n// --- fail_bad_shift.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn RightShift(a: i32, b: i32) -> i32 = \"int.right_shift\";\nfn RightShiftLit(a: Core.IntLiteral(), b: i32) -> Core.IntLiteral() = \"int.right_shift\";\n\n// Shift greater than size is disallowed for sized types.\nlet size_1: i32 = RightShift(1, 31);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:19: error: shift distance >= type width of 32 in `1 >> 32` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let size_2: i32 = RightShift(1, 32);\n// CHECK:STDERR:                   ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet size_2: i32 = RightShift(1, 32);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:19: error: shift distance >= type width of 32 in `1 >> 33` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let size_3: i32 = RightShift(1, 33);\n// CHECK:STDERR:                   ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet size_3: i32 = RightShift(1, 33);\n\n// Negative shifts aren't allowed either, even for literals, even if the lhs is zero.\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:21: error: shift distance >= type width of 32 in `1 >> -1` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let negative: i32 = RightShift(1, -1);\n// CHECK:STDERR:                     ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet negative: i32 = RightShift(1, -1);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:26: error: shift distance >= type width of 32 in `0 >> -1` [CompileTimeShiftOutOfRange]\n// CHECK:STDERR: let negative_zero: i32 = RightShift(0, -1);\n// CHECK:STDERR:                          ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet negative_zero: i32 = RightShift(0, -1);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:39: error: shift distance negative in `1 >> -1` [CompileTimeShiftNegative]\n// CHECK:STDERR: let negative_lit: Core.IntLiteral() = RightShiftLit(1, -1);\n// CHECK:STDERR:                                       ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet negative_lit: Core.IntLiteral() = RightShiftLit(1, -1);\n// CHECK:STDERR: fail_bad_shift.carbon:[[@LINE+4]]:44: error: shift distance negative in `0 >> -1` [CompileTimeShiftNegative]\n// CHECK:STDERR: let negative_lit_zero: Core.IntLiteral() = RightShiftLit(0, -1);\n// CHECK:STDERR:                                            ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet negative_lit_zero: Core.IntLiteral() = RightShiftLit(0, -1);\n\n// CHECK:STDOUT: --- i32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %RightShift.type: type = fn_type @RightShift [concrete]\n// CHECK:STDOUT:   %RightShift: %RightShift.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %RightShift.ref: %RightShift.type = name_ref RightShift, file.%RightShift.decl [concrete = constants.%RightShift]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %RightShift.call: init %i32 = call %RightShift.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %RightShift.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- u32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %RightShift.type: type = fn_type @RightShift [concrete]\n// CHECK:STDOUT:   %RightShift: %RightShift.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCall(%a.param: %u32, %b.param: %i32) -> out %return.param: %u32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %RightShift.ref: %RightShift.type = name_ref RightShift, file.%RightShift.decl [concrete = constants.%RightShift]\n// CHECK:STDOUT:   %a.ref: %u32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %RightShift.call: init %u32 = call %RightShift.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %RightShift.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/right_shift_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/right_shift_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/right_shift_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.right_shift_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\nfn MixedTypes(ref a: i32, b: i64) = \"int.right_shift_assign\";\n\nfn CallMixed(ref a: i32, b: i64) {\n  //@dump-sem-ir-begin\n  MixedTypes(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.right_shift_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.right_shift_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.right_shift_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.right_shift_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.right_shift_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.right_shift_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %i64: type = class_type @Int, @Int(%int_64) [concrete]\n// CHECK:STDOUT:   %MixedTypes.type: type = fn_type @MixedTypes [concrete]\n// CHECK:STDOUT:   %MixedTypes: %MixedTypes.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallMixed(%a.param: ref %i32, %b.param: %i64) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %MixedTypes.ref: %MixedTypes.type = name_ref MixedTypes, file.%MixedTypes.decl [concrete = constants.%MixedTypes]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc16: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i64 = name_ref b, %b\n// CHECK:STDOUT:   %MixedTypes.call: init %empty_tuple.type = call %MixedTypes.ref(%.loc16, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/sadd.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/sadd.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/sadd.carbon\n\n// --- i32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Add(a: i32, b: i32) -> i32 = \"int.sadd\";\n\nclass Expect(N:! i32) {}\nfn Test(N:! i32) -> Expect(N) { return {}; }\n\nfn F() {\n  Test(Add(0, 0)) as Expect(0);\n  Test(Add(1, 2)) as Expect(3);\n  Test(Add(0x7FFF_FFFE, 1)) as Expect(0x7FFF_FFFF);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Add(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Add(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.sadd\";\n\nclass Expect(N:! Core.IntLiteral()) {}\nfn Test(N:! Core.IntLiteral()) -> Expect(N) { return {}; }\n\nfn F() {\n  Test(Add(0, 0)) as Expect(0);\n  Test(Add(1, 2)) as Expect(3);\n\n  // Test some cases that might -- but shouldn't -- overflow.\n  Test(Add(0x7FFF_FFFE, 1)) as Expect(0x7FFF_FFFF);\n  Test(Add(0x7FFF_FFFF, 1)) as Expect(0x8000_0000);\n  Test(Add(0x7FFF_FFFF_FFFF_FFFF, 1)) as Expect(0x8000_0000_0000_0000);\n  Test(Add(0xFFFF_FFFF_FFFF_FFFF, 1)) as Expect(0x1_0000_0000_0000_0000);\n  Test(Add(-0x8000_0000_0000_0000, -1)) as Expect(-0x8000_0000_0000_0001);\n  Test(Add(-0x8000_0000_0000_0000, -0x8000_0000_0000_0000)) as Expect(-0x1_0000_0000_0000_0000);\n}\n\n// --- fail_too_few.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew(a: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew(a: i32) -> i32 = \"int.sadd\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:26: error: name `TooMany` not found [NameNotFound]\n// CHECK:STDERR: var too_many: array(i32, TooMany(1, 2, 3));\n// CHECK:STDERR:                          ^~~~~~~\n// CHECK:STDERR:\nvar too_many: array(i32, TooMany(1, 2, 3));\n\nfn RuntimeCallIsValidTooFew(a: i32) -> i32 {\n  return TooFew(a);\n}\n\n// --- fail_too_many.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: i32, b: i32, c: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: i32, b: i32, c: i32) -> i32 = \"int.sadd\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:33: error: name `BadReturnType` not found [NameNotFound]\n// CHECK:STDERR: var bad_return_type: array(i32, BadReturnType(1, 2));\n// CHECK:STDERR:                                 ^~~~~~~~~~~~~\n// CHECK:STDERR:\nvar bad_return_type: array(i32, BadReturnType(1, 2));\n\nfn RuntimeCallIsValidTooMany(a: i32, b: i32, c: i32) -> i32 {\n  return TooMany(a, b, c);\n}\n\n// --- fail_bad_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn BadReturnType(a: i32, b: i32) -> bool = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn BadReturnType(a: i32, b: i32) -> bool = \"int.sadd\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:25: error: name `TooFew` not found [NameNotFound]\n// CHECK:STDERR: var too_few: array(i32, TooFew(1));\n// CHECK:STDERR:                         ^~~~~~\n// CHECK:STDERR:\nvar too_few: array(i32, TooFew(1));\n\nfn RuntimeCallIsValidBadReturnType(a: i32, b: i32) -> bool {\n  return BadReturnType(a, b);\n}\n\n// --- fail_bad_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_call.carbon:[[@LINE+4]]:26: error: name `JustRight` not found [NameNotFound]\n// CHECK:STDERR: var bad_call: array(i32, JustRight(1, 2, 3));\n// CHECK:STDERR:                          ^~~~~~~~~\n// CHECK:STDERR:\nvar bad_call: array(i32, JustRight(1, 2, 3));\n\n// --- fail_mixed_add.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_mixed_add.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedAdd1(a: i32, b: Core.IntLiteral()) -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedAdd1(a: i32, b: Core.IntLiteral()) -> i32 = \"int.sadd\";\n// CHECK:STDERR: fail_mixed_add.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedAdd2(a: Core.IntLiteral(), b: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedAdd2(a: Core.IntLiteral(), b: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: fail_mixed_add.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedAdd3(a: i32, b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedAdd3(a: i32, b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.sadd\";\n// CHECK:STDERR: fail_mixed_add.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedAdd4(a: Core.IntLiteral(), b: i32) -> Core.IntLiteral() = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedAdd4(a: Core.IntLiteral(), b: i32) -> Core.IntLiteral() = \"int.sadd\";\n\n// --- fail_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Add(a: i32, b: i32) -> i32 = \"int.sadd\";\n\nlet a: i32 = Add(0x7FFFFFFF, 0);\n// CHECK:STDERR: fail_overflow.carbon:[[@LINE+4]]:14: error: integer overflow in calculation `2147483647 + 1` [CompileTimeIntegerOverflow]\n// CHECK:STDERR: let b: i32 = Add(0x7FFFFFFF, 1);\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet b: i32 = Add(0x7FFFFFFF, 1);\n\n// CHECK:STDOUT: --- i32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Add.type: type = fn_type @Add [concrete]\n// CHECK:STDOUT:   %Add: %Add.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Add.ref: %Add.type = name_ref Add, file.%Add.decl [concrete = constants.%Add]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Add.call: init %i32 = call %Add.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Add.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/sadd_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/sadd_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/sadd_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.sadd_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  Builtin(ref a, b);\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.sadd_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.sadd_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.sadd_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.sadd_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.sadd_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.sadd_assign\";\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/sdiv.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/sdiv.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/sdiv.carbon\n\n// --- int_div.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Div(a: i32, b: i32) -> i32 = \"int.sdiv\";\n\nvar arr: array(i32, Div(3, 2));\nlet arr_p: array(i32, 1)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Div(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Div(a: i32, b: i32) -> i32 = \"int.sdiv\";\nfn Sub(a: i32, b: i32) -> i32 = \"int.ssub\";\nfn Negate(a: i32) -> i32 = \"int.snegate\";\n\n// -0x7FFF_FFFF / -1 is OK.\nlet a: i32 = Div(-0x7FFF_FFFF, -1);\n\n// -0x8000_0000 / 1 is OK.\nlet b: i32 = Div(-0x8000_0000, 1);\n\n// -0x8000_0000 / -1 overflows.\n// CHECK:STDERR: fail_overflow.carbon:[[@LINE+4]]:14: error: integer overflow in calculation `-2147483648 / -1` [CompileTimeIntegerOverflow]\n// CHECK:STDERR: let c: i32 = Div(-0x8000_0000, -1);\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet c: i32 = Div(-0x8000_0000, -1);\n\n// --- literal_no_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Div(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.sdiv\";\n\nclass Expect(N:! Core.IntLiteral()) {}\nfn Test(N:! Core.IntLiteral()) -> Expect(N) { return {}; }\n\nfn F() {\n  Test(Div(-0x8000_0000, -1)) as Expect(0x8000_0000);\n  Test(Div(-0x8000_0000_0000_0000, -1)) as Expect(0x8000_0000_0000_0000);\n}\n\n// --- fail_div_by_zero.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Div(a: i32, b: i32) -> i32 = \"int.sdiv\";\nfn DivLit(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.sdiv\";\n\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:14: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let a: i32 = Div(1, 0);\n// CHECK:STDERR:              ^~~~~~~~~\n// CHECK:STDERR:\nlet a: i32 = Div(1, 0);\n\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:14: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let b: i32 = Div(0, 0);\n// CHECK:STDERR:              ^~~~~~~~~\n// CHECK:STDERR:\nlet b: i32 = Div(0, 0);\n\n// IntLiteral allows \"overflow\" by widening its representation, but not overflow to infinity.\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:28: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let c: Core.IntLiteral() = DivLit(1, 0);\n// CHECK:STDERR:                            ^~~~~~~~~~~~\n// CHECK:STDERR:\nlet c: Core.IntLiteral() = DivLit(1, 0);\n\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:28: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let d: Core.IntLiteral() = DivLit(0, 0);\n// CHECK:STDERR:                            ^~~~~~~~~~~~\n// CHECK:STDERR:\nlet d: Core.IntLiteral() = DivLit(0, 0);\n\n// CHECK:STDOUT: --- int_div.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Div.type: type = fn_type @Div [concrete]\n// CHECK:STDOUT:   %Div: %Div.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Div.ref: %Div.type = name_ref Div, file.%Div.decl [concrete = constants.%Div]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Div.call: init %i32 = call %Div.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Div.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/sdiv_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/sdiv_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/sdiv_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.sdiv_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sdiv_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.sdiv_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.sdiv_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sdiv_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.sdiv_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.sdiv_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sdiv_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.sdiv_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.sdiv_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/smod.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/smod.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/smod.carbon\n\n// --- int_div.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mod(a: i32, b: i32) -> i32 = \"int.smod\";\n\nvar arr: array(i32, Mod(5, 3));\nlet arr_p: array(i32, 2)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Mod(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mod(a: i32, b: i32) -> i32 = \"int.smod\";\nfn Sub(a: i32, b: i32) -> i32 = \"int.ssub\";\nfn Negate(a: i32) -> i32 = \"int.snegate\";\n\n// -0x7FFF_FFFF % -1 is OK.\nlet a: i32 = Mod(Negate(0x7FFF_FFFF), Negate(1));\n\n// -0x8000_0000 % 1 is OK.\nlet b: i32 = Mod(Sub(Negate(0x7FFF_FFFF), 1), 1);\n\n// -0x8000_0000 / -1 overflows, so -0x8000_0000 % -1 is disallowed, even though\n// its result is representable.\n// CHECK:STDERR: fail_overflow.carbon:[[@LINE+4]]:14: error: integer overflow in calculation `-2147483648 % -1` [CompileTimeIntegerOverflow]\n// CHECK:STDERR: let c: i32 = Mod(Sub(Negate(0x7FFF_FFFF), 1), Negate(1));\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet c: i32 = Mod(Sub(Negate(0x7FFF_FFFF), 1), Negate(1));\n\n// --- fail_div_by_zero.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mod(a: i32, b: i32) -> i32 = \"int.smod\";\n\n// Remainder of division by zero is not defined.\n\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:14: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let a: i32 = Mod(1, 0);\n// CHECK:STDERR:              ^~~~~~~~~\n// CHECK:STDERR:\nlet a: i32 = Mod(1, 0);\n\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:14: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let b: i32 = Mod(0, 0);\n// CHECK:STDERR:              ^~~~~~~~~\n// CHECK:STDERR:\nlet b: i32 = Mod(0, 0);\n\n// CHECK:STDOUT: --- int_div.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Mod.type: type = fn_type @Mod [concrete]\n// CHECK:STDOUT:   %Mod: %Mod.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Mod.ref: %Mod.type = name_ref Mod, file.%Mod.decl [concrete = constants.%Mod]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Mod.call: init %i32 = call %Mod.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Mod.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/smod_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/smod_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/smod_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.smod_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.smod_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.smod_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.smod_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.smod_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.smod_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.smod_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.smod_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.smod_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.smod_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/smul.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/smul.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/smul.carbon\n\n// --- i32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mul(a: i32, b: i32) -> i32 = \"int.smul\";\n\nclass Expect(N:! i32) {}\nfn Test(N:! i32) -> Expect(N) { return {}; }\n\nfn F() {\n  Test(Mul(0, 0)) as Expect(0);\n  Test(Mul(0, 3)) as Expect(0);\n  Test(Mul(1, 2)) as Expect(2);\n  Test(Mul(3, 2)) as Expect(6);\n  Test(Mul(0x7FFF_FFFF, 1)) as Expect(0x7FFF_FFFF);\n  Test(Mul(0x7FFF_FFFF, -1)) as Expect(-0x7FFF_FFFF);\n}\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Mul(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mul(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.smul\";\n\nclass Expect(N:! Core.IntLiteral()) {}\nfn Test(N:! Core.IntLiteral()) -> Expect(N) { return {}; }\n\nfn F() {\n  Test(Mul(0, 0)) as Expect(0);\n  Test(Mul(0, 3)) as Expect(0);\n  Test(Mul(1, 2)) as Expect(2);\n  Test(Mul(3, 2)) as Expect(6);\n  Test(Mul(0x7FFF_FFFF, 1)) as Expect(0x7FFF_FFFF);\n  Test(Mul(0x7FFF_FFFF, -1)) as Expect(-0x7FFF_FFFF);\n\n  // Test some cases that might -- but shouldn't -- overflow.\n  Test(Mul(0x8000_0000_0000_0000, 1)) as Expect(0x8000_0000_0000_0000);\n  Test(Mul(0x8000_0000_0000_0000, -1)) as Expect(-0x8000_0000_0000_0000);\n  Test(Mul(-0x8000_0000_0000_0000, 1)) as Expect(-0x8000_0000_0000_0000);\n  Test(Mul(-0x8000_0000_0000_0000, -1)) as Expect(0x8000_0000_0000_0000);\n  Test(Mul(-0x8000_0000_0000_0000, -1)) as Expect(0x8000_0000_0000_0000);\n  Test(Mul(-0x8000_0000_0000_0000, -0x8000_0000_0000_0000))\n    as Expect(0x4000_0000_0000_0000_0000_0000_0000_0000);\n}\n\n// --- fail_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mul(a: i32, b: i32) -> i32 = \"int.smul\";\n\nlet a: i32 = Mul(0x7FFF, 0x10000);\n// CHECK:STDERR: fail_overflow.carbon:[[@LINE+4]]:14: error: integer overflow in calculation `32768 * 65536` [CompileTimeIntegerOverflow]\n// CHECK:STDERR: let b: i32 = Mul(0x8000, 0x10000);\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet b: i32 = Mul(0x8000, 0x10000);\n\n// CHECK:STDOUT: --- i32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Mul.type: type = fn_type @Mul [concrete]\n// CHECK:STDOUT:   %Mul: %Mul.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Mul.ref: %Mul.type = name_ref Mul, file.%Mul.decl [concrete = constants.%Mul]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Mul.call: init %i32 = call %Mul.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Mul.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/smul_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/smul_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/smul_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.smul_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.smul_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.smul_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.smul_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.smul_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.smul_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.smul_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.smul_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.smul_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.smul_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/snegate.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/snegate.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/snegate.carbon\n\n// --- int_negate.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Negate(a: i32) -> i32 = \"int.snegate\";\n\nvar arr: array(i32, Negate(Negate(123)));\nlet arr_p: array(i32, 123)* = &arr;\n\nlet n: i32 = Negate(1);\n\nfn RuntimeCallIsValid(a: i32, unused b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Negate(a);\n  //@dump-sem-ir-end\n}\n\n// --- literal.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Negate(a: Core.IntLiteral()) -> Core.IntLiteral() = \"int.snegate\";\nfn Sub(a: Core.IntLiteral(), b: Core.IntLiteral()) -> Core.IntLiteral() = \"int.ssub\";\n\nclass Expect(N:! Core.IntLiteral()) {}\nfn Test(N:! Core.IntLiteral()) -> Expect(N) { return {}; }\n\nfn F() {\n  Test(Negate(0)) as Expect(0);\n  Test(Negate(1)) as Expect(Sub(0, 1));\n  Test(Negate(Sub(0, 0x8000_0000_0000_0000))) as Expect(0x8000_0000_0000_0000);\n}\n\n// --- fail_too_few.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.snegate\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew() -> i32 = \"int.snegate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew() -> i32 = \"int.snegate\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:25: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var too_few: array(i32, TooFew());\n// CHECK:STDERR:                         ^~~~~~~~\n// CHECK:STDERR:\nvar too_few: array(i32, TooFew());\n\nfn RuntimeCallIsValidTooFew() -> i32 {\n  return TooFew();\n}\n\n// --- fail_too_many.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.snegate\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: i32, b: i32) -> i32 = \"int.snegate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: i32, b: i32) -> i32 = \"int.snegate\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:26: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var too_many: array(i32, TooMany(1, 2));\n// CHECK:STDERR:                          ^~~~~~~~~~~~~\n// CHECK:STDERR:\nvar too_many: array(i32, TooMany(1, 2));\n\nfn RuntimeCallIsValidTooMany(a: i32, b: i32) -> i32 {\n  return TooMany(a, b);\n}\n\n// --- fail_bad_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.snegate\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn BadReturnType(a: i32) -> bool = \"int.snegate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn BadReturnType(a: i32) -> bool = \"int.snegate\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:33: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var bad_return_type: array(i32, BadReturnType(1));\n// CHECK:STDERR:                                 ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar bad_return_type: array(i32, BadReturnType(1));\n\nfn RuntimeCallIsValidBadReturnType(a: i32) -> bool {\n  return BadReturnType(a);\n}\n\n// --- fail_bad_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Negate(a: i32) -> i32 = \"int.snegate\";\n\n// CHECK:STDERR: fail_bad_call.carbon:[[@LINE+7]]:26: error: 2 arguments passed to function expecting 1 argument [CallArgCountMismatch]\n// CHECK:STDERR: var bad_call: array(i32, Negate(1, 2));\n// CHECK:STDERR:                          ^~~~~~~~~~~~\n// CHECK:STDERR: fail_bad_call.carbon:[[@LINE-5]]:1: note: calling function declared here [InCallToEntity]\n// CHECK:STDERR: fn Negate(a: i32) -> i32 = \"int.snegate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar bad_call: array(i32, Negate(1, 2));\n\n// --- fail_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Negate(a: i32) -> i32 = \"int.snegate\";\nfn Sub(a: i32, b: i32) -> i32 = \"int.ssub\";\n\n// -(-INT_MAX) is INT_MAX.\nlet a: i32 = Negate(Negate(0x7FFF_FFFF));\n\n// -INT_MIN is too large for i32.\n// CHECK:STDERR: fail_overflow.carbon:[[@LINE+4]]:14: error: integer overflow in negation of -2147483648 [CompileTimeIntegerNegateOverflow]\n// CHECK:STDERR: let b: i32 = Negate(-0x8000_0000);\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet b: i32 = Negate(-0x8000_0000);\n\n// CHECK:STDOUT: --- int_negate.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Negate.type: type = fn_type @Negate [concrete]\n// CHECK:STDOUT:   %Negate: %Negate.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Negate.ref: %Negate.type = name_ref Negate, file.%Negate.decl [concrete = constants.%Negate]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %Negate.call: init %i32 = call %Negate.ref(%a.ref)\n// CHECK:STDOUT:   return %Negate.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/ssub.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/ssub.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/ssub.carbon\n\n// --- int_sub.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Sub(a: i32, b: i32) -> i32 = \"int.ssub\";\n\nvar arr: array(i32, Sub(3, 2));\nlet arr_p: array(i32, 1)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Sub(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Sub(a: i32, b: i32) -> i32 = \"int.ssub\";\n\nlet a: i32 = Sub(0, 0x7FFFFFFF);\nlet b: i32 = Sub(Sub(0, 0x7FFFFFFF), 1);\n// CHECK:STDERR: fail_overflow.carbon:[[@LINE+4]]:14: error: integer overflow in calculation `-2147483647 - 2` [CompileTimeIntegerOverflow]\n// CHECK:STDERR: let c: i32 = Sub(Sub(0, 0x7FFFFFFF), 2);\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet c: i32 = Sub(Sub(0, 0x7FFFFFFF), 2);\n\n// CHECK:STDOUT: --- int_sub.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Sub.type: type = fn_type @Sub [concrete]\n// CHECK:STDOUT:   %Sub: %Sub.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Sub.ref: %Sub.type = name_ref Sub, file.%Sub.decl [concrete = constants.%Sub]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Sub.call: init %i32 = call %Sub.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Sub.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/ssub_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/ssub_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/ssub_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.ssub_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.ssub_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.ssub_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.ssub_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.ssub_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.ssub_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.ssub_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.ssub_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.ssub_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.ssub_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/uadd.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/uadd.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/uadd.carbon\n\n// --- int_add.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Add(a: i32, b: i32) -> i32 = \"int.uadd\";\n\nvar arr: array(i32, Add(1, 2));\nlet arr_p: array(i32, 3)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Add(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_too_few.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.uadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew(a: i32) -> i32 = \"int.uadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew(a: i32) -> i32 = \"int.uadd\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:25: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var too_few: array(i32, TooFew(1));\n// CHECK:STDERR:                         ^~~~~~~~~\n// CHECK:STDERR:\nvar too_few: array(i32, TooFew(1));\n\nfn RuntimeCallIsValidTooFew(a: i32) -> i32 {\n  return TooFew(a);\n}\n\n// --- fail_too_many.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.uadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: i32, b: i32, c: i32) -> i32 = \"int.uadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: i32, b: i32, c: i32) -> i32 = \"int.uadd\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:26: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var too_many: array(i32, TooMany(1, 2, 3));\n// CHECK:STDERR:                          ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar too_many: array(i32, TooMany(1, 2, 3));\n\nfn RuntimeCallIsValidTooMany(a: i32, b: i32, c: i32) -> i32 {\n  return TooMany(a, b, c);\n}\n\n// --- fail_bad_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.uadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn BadReturnType(a: i32, b: i32) -> bool = \"int.uadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn BadReturnType(a: i32, b: i32) -> bool = \"int.uadd\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:33: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var bad_return_type: array(i32, BadReturnType(1, 2));\n// CHECK:STDERR:                                 ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar bad_return_type: array(i32, BadReturnType(1, 2));\n\nfn RuntimeCallIsValidBadReturnType(a: i32, b: i32) -> bool {\n  return BadReturnType(a, b);\n}\n\n// --- fail_bad_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Add(a: i32, b: i32) -> i32 = \"int.uadd\";\n\n// CHECK:STDERR: fail_bad_call.carbon:[[@LINE+7]]:26: error: 3 arguments passed to function expecting 2 arguments [CallArgCountMismatch]\n// CHECK:STDERR: var bad_call: array(i32, Add(1, 2, 3));\n// CHECK:STDERR:                          ^~~~~~~~~~~~\n// CHECK:STDERR: fail_bad_call.carbon:[[@LINE-5]]:1: note: calling function declared here [InCallToEntity]\n// CHECK:STDERR: fn Add(a: i32, b: i32) -> i32 = \"int.uadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar bad_call: array(i32, Add(1, 2, 3));\n\n// --- overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Add(a: i32, b: i32) -> i32 = \"int.uadd\";\n\n// Overflow is OK.\nlet a: i32 = Add(0x7FFFFFFF, 0);\nlet b: i32 = Add(0x7FFFFFFF, 1);\n\n// CHECK:STDOUT: --- int_add.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Add.type: type = fn_type @Add [concrete]\n// CHECK:STDOUT:   %Add: %Add.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Add.ref: %Add.type = name_ref Add, file.%Add.decl [concrete = constants.%Add]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Add.call: init %i32 = call %Add.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Add.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/uadd_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/uadd_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/uadd_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.uadd_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.uadd_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.uadd_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.uadd_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.uadd_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.uadd_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.uadd_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.uadd_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.uadd_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.uadd_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/udiv.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/udiv.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/udiv.carbon\n\n// --- int_div.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Div(a: i32, b: i32) -> i32 = \"int.udiv\";\n\nvar arr: array(i32, Div(3, 2));\nlet arr_p: array(i32, 1)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Div(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Div(a: i32, b: i32) -> i32 = \"int.udiv\";\nfn Sub(a: i32, b: i32) -> i32 = \"int.usub\";\nfn Negate(a: i32) -> i32 = \"int.unegate\";\n\n// -0x7FFF_FFFF / -1 is OK.\nlet a: i32 = Div(Negate(0x7FFF_FFFF), Negate(1));\n\n// -0x8000_0000 / 1 is OK.\nlet b: i32 = Div(Sub(Negate(0x7FFF_FFFF), 1), 1);\n\n// -0x8000_0000 / -1 is OK.\nlet c: i32 = Div(Sub(Negate(0x7FFF_FFFF), 1), Negate(1));\n\n// --- fail_div_by_zero.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Div(a: i32, b: i32) -> i32 = \"int.udiv\";\n\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:14: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let a: i32 = Div(1, 0);\n// CHECK:STDERR:              ^~~~~~~~~\n// CHECK:STDERR:\nlet a: i32 = Div(1, 0);\n\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:14: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let b: i32 = Div(0, 0);\n// CHECK:STDERR:              ^~~~~~~~~\n// CHECK:STDERR:\nlet b: i32 = Div(0, 0);\n\n// CHECK:STDOUT: --- int_div.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Div.type: type = fn_type @Div [concrete]\n// CHECK:STDOUT:   %Div: %Div.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Div.ref: %Div.type = name_ref Div, file.%Div.decl [concrete = constants.%Div]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Div.call: init %i32 = call %Div.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Div.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/udiv_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/udiv_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/udiv_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.udiv_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.udiv_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.udiv_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.udiv_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.udiv_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.udiv_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.udiv_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.udiv_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.udiv_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.udiv_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/umod.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/umod.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/umod.carbon\n\n// --- int_div.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mod(a: i32, b: i32) -> i32 = \"int.umod\";\n\nvar arr: array(i32, Mod(5, 3));\nlet arr_p: array(i32, 2)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Mod(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mod(a: i32, b: i32) -> i32 = \"int.umod\";\nfn Sub(a: i32, b: i32) -> i32 = \"int.usub\";\nfn Negate(a: i32) -> i32 = \"int.unegate\";\n\n// -0x7FFF_FFFF % -1 is OK.\nlet a: i32 = Mod(Negate(0x7FFF_FFFF), Negate(1));\n\n// -0x8000_0000 % 1 is OK.\nlet b: i32 = Mod(Sub(Negate(0x7FFF_FFFF), 1), 1);\n\n// -0x8000_0000 / -1 is OK.\nlet c: i32 = Mod(Sub(Negate(0x7FFF_FFFF), 1), Negate(1));\n\n// --- fail_div_by_zero.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mod(a: i32, b: i32) -> i32 = \"int.umod\";\n\n// Remainder of division by zero is not defined.\n\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:14: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let a: i32 = Mod(1, 0);\n// CHECK:STDERR:              ^~~~~~~~~\n// CHECK:STDERR:\nlet a: i32 = Mod(1, 0);\n\n// CHECK:STDERR: fail_div_by_zero.carbon:[[@LINE+4]]:14: error: division by zero [CompileTimeDivisionByZero]\n// CHECK:STDERR: let b: i32 = Mod(0, 0);\n// CHECK:STDERR:              ^~~~~~~~~\n// CHECK:STDERR:\nlet b: i32 = Mod(0, 0);\n\n// CHECK:STDOUT: --- int_div.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Mod.type: type = fn_type @Mod [concrete]\n// CHECK:STDOUT:   %Mod: %Mod.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Mod.ref: %Mod.type = name_ref Mod, file.%Mod.decl [concrete = constants.%Mod]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Mod.call: init %i32 = call %Mod.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Mod.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/umod_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/umod_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/umod_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.umod_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.umod_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.umod_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.umod_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.umod_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.umod_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.umod_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.umod_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.umod_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.umod_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/umul.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/umul.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/umul.carbon\n\n// --- int_mul.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mul(a: i32, b: i32) -> i32 = \"int.umul\";\n\nvar arr: array(i32, Mul(3, 2));\nlet arr_p: array(i32, 6)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Mul(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Mul(a: i32, b: i32) -> i32 = \"int.umul\";\n\nlet a: i32 = Mul(0x7FFF, 0x10000);\nlet b: i32 = Mul(0x8000, 0x10000);\n\n// CHECK:STDOUT: --- int_mul.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Mul.type: type = fn_type @Mul [concrete]\n// CHECK:STDOUT:   %Mul: %Mul.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Mul.ref: %Mul.type = name_ref Mul, file.%Mul.decl [concrete = constants.%Mul]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Mul.call: init %i32 = call %Mul.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Mul.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/umul_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/umul_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/umul_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.umul_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.umul_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.umul_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.umul_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.umul_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.umul_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.umul_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.umul_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.umul_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.umul_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/unegate.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/unegate.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/unegate.carbon\n\n// --- int_negate.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Negate(a: u32) -> u32 = \"int.unegate\";\n\nvar arr: array(u32, Negate(Negate(123)));\nlet arr_p: array(u32, 123)* = &arr;\n\nlet n: u32 = Negate(1);\n\nfn RuntimeCallIsValid(a: u32, unused b: u32) -> u32 {\n  //@dump-sem-ir-begin\n  return Negate(a);\n  //@dump-sem-ir-end\n}\n\n// --- fail_too_few.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.unegate\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew() -> u32 = \"int.unegate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew() -> u32 = \"int.unegate\";\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+4]]:25: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var too_few: array(u32, TooFew());\n// CHECK:STDERR:                         ^~~~~~~~\n// CHECK:STDERR:\nvar too_few: array(u32, TooFew());\n\nfn RuntimeCallIsValidTooFew() -> u32 {\n  return TooFew();\n}\n\n// --- fail_too_many.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.unegate\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: u32, b: u32) -> u32 = \"int.unegate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: u32, b: u32) -> u32 = \"int.unegate\";\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+4]]:26: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var too_many: array(u32, TooMany(1, 2));\n// CHECK:STDERR:                          ^~~~~~~~~~~~~\n// CHECK:STDERR:\nvar too_many: array(u32, TooMany(1, 2));\n\nfn RuntimeCallIsValidTooMany(a: u32, b: u32) -> u32 {\n  return TooMany(a, b);\n}\n\n// --- fail_bad_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.unegate\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn BadReturnType(a: u32) -> bool = \"int.unegate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn BadReturnType(a: u32) -> bool = \"int.unegate\";\n\n// CHECK:STDERR: fail_bad_return_type.carbon:[[@LINE+4]]:33: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var bad_return_type: array(u32, BadReturnType(1));\n// CHECK:STDERR:                                 ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar bad_return_type: array(u32, BadReturnType(1));\n\nfn RuntimeCallIsValidBadReturnType(a: u32) -> bool {\n  return BadReturnType(a);\n}\n\n// --- fail_bad_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Negate(a: u32) -> u32 = \"int.unegate\";\n\n// CHECK:STDERR: fail_bad_call.carbon:[[@LINE+7]]:26: error: 2 arguments passed to function expecting 1 argument [CallArgCountMismatch]\n// CHECK:STDERR: var bad_call: array(u32, Negate(1, 2));\n// CHECK:STDERR:                          ^~~~~~~~~~~~\n// CHECK:STDERR: fail_bad_call.carbon:[[@LINE-5]]:1: note: calling function declared here [InCallToEntity]\n// CHECK:STDERR: fn Negate(a: u32) -> u32 = \"int.unegate\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar bad_call: array(u32, Negate(1, 2));\n\n// --- overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Negate(a: u32) -> u32 = \"int.unegate\";\n\nclass Expect(N:! u32) {}\nfn Test(N:! u32) -> Expect(N) { return {}; }\n\nfn F() {\n  // -(-INT_MAX) is INT_MAX.\n  Test(Negate(Negate(0x7FFF_FFFF))) as Expect(0x7FFF_FFFF);\n  Test(-(Negate(0x7FFF_FFFF))) as Expect(0x7FFF_FFFF);\n  // -(-(INT_MAX + 1)) is `INT_MAX + 1`.\n  Test(Negate(Negate(0x8000_0000))) as Expect(0x8000_0000);\n  Test(-(Negate(0x8000_0000))) as Expect(0x8000_0000);\n}\n\n// CHECK:STDOUT: --- int_negate.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]\n// CHECK:STDOUT:   %Negate.type: type = fn_type @Negate [concrete]\n// CHECK:STDOUT:   %Negate: %Negate.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %u32, %b.param: %u32) -> out %return.param: %u32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Negate.ref: %Negate.type = name_ref Negate, file.%Negate.decl [concrete = constants.%Negate]\n// CHECK:STDOUT:   %a.ref: %u32 = name_ref a, %a\n// CHECK:STDOUT:   %Negate.call: init %u32 = call %Negate.ref(%a.ref)\n// CHECK:STDOUT:   return %Negate.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/usub.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/usub.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/usub.carbon\n\n// --- int_sub.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Sub(a: i32, b: i32) -> i32 = \"int.usub\";\n\nvar arr: array(i32, Sub(3, 2));\nlet arr_p: array(i32, 1)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Sub(a, b);\n  //@dump-sem-ir-end\n}\n\n// --- overflow.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Sub(a: i32, b: i32) -> i32 = \"int.usub\";\n\nlet a: i32 = Sub(0, 0x7FFFFFFF);\nlet b: i32 = Sub(Sub(0, 0x7FFFFFFF), 1);\nlet c: i32 = Sub(Sub(0, 0x7FFFFFFF), 2);\n\n// CHECK:STDOUT: --- int_sub.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Sub.type: type = fn_type @Sub [concrete]\n// CHECK:STDOUT:   %Sub: %Sub.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Sub.ref: %Sub.type = name_ref Sub, file.%Sub.decl [concrete = constants.%Sub]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Sub.call: init %i32 = call %Sub.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Sub.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/usub_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/usub_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/usub_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.usub_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.usub_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.usub_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.usub_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.usub_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.usub_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.usub_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.usub_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.usub_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.usub_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/xor.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/xor.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/xor.carbon\n\n// --- int_xor.carbon\n\nfn Xor(a: i32, b: i32) -> i32 = \"int.xor\";\n\nvar arr: array(i32, Xor(12, 10));\nlet arr_p: array(i32, 6)* = &arr;\n\nfn RuntimeCallIsValid(a: i32, b: i32) -> i32 {\n  //@dump-sem-ir-begin\n  return Xor(a, b);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- int_xor.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Xor.type: type = fn_type @Xor [concrete]\n// CHECK:STDOUT:   %Xor: %Xor.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCallIsValid(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Xor.ref: %Xor.type = name_ref Xor, file.%Xor.decl [concrete = constants.%Xor]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Xor.call: init %i32 = call %Xor.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Xor.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int/xor_assign.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int/xor_assign.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int/xor_assign.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Builtin(ref a: i32, b: i32) = \"int.xor_assign\";\n\nfn Call(ref a: i32, b: i32) {\n  //@dump-sem-ir-begin\n  Builtin(ref a, b);\n  //@dump-sem-ir-end\n}\n\n// --- fail_unsized.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_unsized.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.xor_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.xor_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Builtin(ref a: Core.IntLiteral(), b: Core.IntLiteral()) = \"int.xor_assign\";\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.xor_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotRef(a: i32, b: i32) = \"int.xor_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotRef(a: i32, b: i32) = \"int.xor_assign\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.xor_assign\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn MixedTypes(ref a: i32, b: i64) = \"int.xor_assign\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MixedTypes(ref a: i32, b: i64) = \"int.xor_assign\";\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Builtin.type: type = fn_type @Builtin [concrete]\n// CHECK:STDOUT:   %Builtin: %Builtin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: ref %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Builtin.ref: %Builtin.type = name_ref Builtin, file.%Builtin.decl [concrete = constants.%Builtin]\n// CHECK:STDOUT:   %a.ref: ref %i32 = name_ref a, %a\n// CHECK:STDOUT:   %.loc8: %i32 = ref_tag %a.ref\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Builtin.call: init %empty_tuple.type = call %Builtin.ref(%.loc8, %b.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/int_literal/make_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/int_literal/make_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/int_literal/make_type.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn IntLiteral() -> type = \"int_literal.make_type\";\n\n// --- use_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\nvar i: IntLiteral();\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/maybe_unformed/make_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/maybe_unformed/make_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/maybe_unformed/make_type.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Make(t: type) -> type = \"maybe_unformed.make_type\";\n\n// --- use_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n//@dump-sem-ir-begin\nfn F(unused b: Make(Make({}))) {}\n//@dump-sem-ir-end\n\n// --- runtime_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"types\";\n\n//@dump-sem-ir-begin\nlet t: type = {};\nlet u: type = Make(t);\n//@dump-sem-ir-end\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"maybe_unformed.make_type\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NoParam() -> type = \"maybe_unformed.make_type\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NoParam() -> type = \"maybe_unformed.make_type\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"maybe_unformed.make_type\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn ColonBangParam(T:! type) -> type = \"maybe_unformed.make_type\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn ColonBangParam(T:! type) -> type = \"maybe_unformed.make_type\";\n\n// CHECK:STDOUT: --- use_types.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %.a8d: type = maybe_unformed_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.2ba: type = maybe_unformed_type %.a8d [concrete]\n// CHECK:STDOUT:   %pattern_type.ce6: type = pattern_type %.2ba [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Make: %Make.type = import_ref Main//types, Make, loaded [concrete = constants.%Make]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.ce6 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.ce6 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %b.param: %.2ba = value_param call_param0\n// CHECK:STDOUT:     %.loc7_29.1: type = splice_block %.loc7_29.3 [concrete = constants.%.2ba] {\n// CHECK:STDOUT:       %Make.ref.loc7_16: %Make.type = name_ref Make, imports.%Main.Make [concrete = constants.%Make]\n// CHECK:STDOUT:       %Make.ref.loc7_21: %Make.type = name_ref Make, imports.%Main.Make [concrete = constants.%Make]\n// CHECK:STDOUT:       %.loc7_27.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc7_27.2: type = converted %.loc7_27.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %Make.call.loc7_28: init type = call %Make.ref.loc7_21(%.loc7_27.2) [concrete = constants.%.a8d]\n// CHECK:STDOUT:       %.loc7_28.1: type = value_of_initializer %Make.call.loc7_28 [concrete = constants.%.a8d]\n// CHECK:STDOUT:       %.loc7_28.2: type = converted %Make.call.loc7_28, %.loc7_28.1 [concrete = constants.%.a8d]\n// CHECK:STDOUT:       %Make.call.loc7_29: init type = call %Make.ref.loc7_16(%.loc7_28.2) [concrete = constants.%.2ba]\n// CHECK:STDOUT:       %.loc7_29.2: type = value_of_initializer %Make.call.loc7_29 [concrete = constants.%.2ba]\n// CHECK:STDOUT:       %.loc7_29.3: type = converted %Make.call.loc7_29, %.loc7_29.2 [concrete = constants.%.2ba]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b: %.2ba = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%b.param: %.2ba) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- runtime_call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Make: %Make.type = import_ref Main//types, Make, loaded [concrete = constants.%Make]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %t.patt: %pattern_type = value_binding_pattern t [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc7_8: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   %.loc7_16: type = converted @__global_init.%.loc7, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %t: type = value_binding t, %.loc7_16\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %u.patt: %pattern_type = value_binding_pattern u [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc8_8: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   %.loc8_21.1: type = value_of_initializer @__global_init.%Make.call\n// CHECK:STDOUT:   %.loc8_21.2: type = converted @__global_init.%Make.call, %.loc8_21.1\n// CHECK:STDOUT:   %u: type = value_binding u, %.loc8_21.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, imports.%Main.Make [concrete = constants.%Make]\n// CHECK:STDOUT:   %t.ref: type = name_ref t, file.%t\n// CHECK:STDOUT:   %Make.call: init type = call %Make.ref(%t.ref)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/no_op.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/no_op.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/no_op.carbon\n\n// --- no_op.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn NoOp() = \"no_op\";\n\nfn F() {\n  //@dump-sem-ir-begin\n  NoOp();\n  //@dump-sem-ir-end\n}\n\n// --- explicit_return.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn NoOp() -> () = \"no_op\";\n\nfn F() {\n  //@dump-sem-ir-begin\n  NoOp();\n  //@dump-sem-ir-end\n}\n\n// --- ignore_args.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn NoOp(x: ()) -> () = \"no_op\";\n\nfn F() {\n  //@dump-sem-ir-begin\n  NoOp(());\n  //@dump-sem-ir-end\n}\n\n// --- assign.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn NoOp() = \"no_op\";\n\n//@dump-sem-ir-begin\nvar x: () = NoOp();\n//@dump-sem-ir-end\n\n// --- fail_signature.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_signature.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"no_op\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NoOp() -> {} = \"no_op\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NoOp() -> {} = \"no_op\";\n\n// CHECK:STDOUT: --- no_op.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %NoOp.type: type = fn_type @NoOp [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %NoOp: %NoOp.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %NoOp.ref: %NoOp.type = name_ref NoOp, file.%NoOp.decl [concrete = constants.%NoOp]\n// CHECK:STDOUT:   %NoOp.call: init %empty_tuple.type = call %NoOp.ref() [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- explicit_return.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %NoOp.type: type = fn_type @NoOp [concrete]\n// CHECK:STDOUT:   %NoOp: %NoOp.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %NoOp.ref: %NoOp.type = name_ref NoOp, file.%NoOp.decl [concrete = constants.%NoOp]\n// CHECK:STDOUT:   %NoOp.call: init %empty_tuple.type = call %NoOp.ref() [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- ignore_args.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %NoOp.type: type = fn_type @NoOp [concrete]\n// CHECK:STDOUT:   %NoOp: %NoOp.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %NoOp.ref: %NoOp.type = name_ref NoOp, file.%NoOp.decl [concrete = constants.%NoOp]\n// CHECK:STDOUT:   %.loc8_9.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc8_9.2: %empty_tuple.type = converted %.loc8_9.1, %empty_tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %NoOp.call: init %empty_tuple.type = call %NoOp.ref(%.loc8_9.2) [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- assign.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %NoOp.type: type = fn_type @NoOp [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %NoOp: %NoOp.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %empty_tuple.type = var %x.var_patt [concrete]\n// CHECK:STDOUT:   %.loc7_9.1: type = splice_block %.loc7_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc7_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_9.3: type = converted %.loc7_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: ref %empty_tuple.type = ref_binding x, %x.var [concrete = %x.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %NoOp.ref: %NoOp.type = name_ref NoOp, file.%NoOp.decl [concrete = constants.%NoOp]\n// CHECK:STDOUT:   %NoOp.call: init %empty_tuple.type = call %NoOp.ref() [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   assign file.%x.var, %NoOp.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/pointer/is_null.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/bool.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/pointer/is_null.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/pointer/is_null.carbon\n\n// --- call_exact.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn MakeUnformed(t: type) -> type = \"maybe_unformed.make_type\";\nfn IsNullEmptyStruct(p: MakeUnformed({}*)) -> bool = \"pointer.is_null\";\nfn IsNullC(p: MakeUnformed(C*)) -> bool = \"pointer.is_null\";\n\n//@dump-sem-ir-begin\nfn TestEmptyStruct(s: MakeUnformed({}*)) -> bool {\n  return IsNullEmptyStruct(s);\n}\n\nfn TestC(c: MakeUnformed(C*)) -> bool {\n  return IsNullC(c);\n}\n//@dump-sem-ir-end\n\n// --- call_generic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn MakeUnformed(t: type) -> type = \"maybe_unformed.make_type\";\nfn IsNull[T:! type](p: MakeUnformed(T*)) -> bool = \"pointer.is_null\";\n\nclass C {}\n\n//@dump-sem-ir-begin\nfn TestEmptyStruct(s: MakeUnformed({}*)) -> bool {\n  return IsNull(s);\n}\n\nfn TestC(c: MakeUnformed(C*)) -> bool {\n  return IsNull(c);\n}\n//@dump-sem-ir-end\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn MakeUnformed(t: type) -> type = \"maybe_unformed.make_type\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"pointer.is_null\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NoParam() -> bool = \"pointer.is_null\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NoParam() -> bool = \"pointer.is_null\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"pointer.is_null\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NoRetType(p: MakeUnformed({}*)) = \"pointer.is_null\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NoRetType(p: MakeUnformed({}*)) = \"pointer.is_null\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"pointer.is_null\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn WrongRetType(p: MakeUnformed({}*)) -> {} = \"pointer.is_null\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn WrongRetType(p: MakeUnformed({}*)) -> {} = \"pointer.is_null\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"pointer.is_null\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NoUnformed(p: {}*) -> bool = \"pointer.is_null\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NoUnformed(p: {}*) -> bool = \"pointer.is_null\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"pointer.is_null\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotPointer(p: MakeUnformed({})) -> bool = \"pointer.is_null\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotPointer(p: MakeUnformed({})) -> bool = \"pointer.is_null\";\n\n// CHECK:STDOUT: --- call_exact.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %MakeUnformed.type: type = fn_type @MakeUnformed [concrete]\n// CHECK:STDOUT:   %MakeUnformed: %MakeUnformed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.b2d: type = maybe_unformed_type %ptr.c28 [concrete]\n// CHECK:STDOUT:   %pattern_type.b42: type = pattern_type %.b2d [concrete]\n// CHECK:STDOUT:   %.f34: Core.Form = init_form bool [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %IsNullEmptyStruct.type: type = fn_type @IsNullEmptyStruct [concrete]\n// CHECK:STDOUT:   %IsNullEmptyStruct: %IsNullEmptyStruct.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %.edf: type = maybe_unformed_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %pattern_type.b78: type = pattern_type %.edf [concrete]\n// CHECK:STDOUT:   %IsNullC.type: type = fn_type @IsNullC [concrete]\n// CHECK:STDOUT:   %IsNullC: %IsNullC.type = struct_value () [concrete]\n// CHECK:STDOUT:   %TestEmptyStruct.type: type = fn_type @TestEmptyStruct [concrete]\n// CHECK:STDOUT:   %TestEmptyStruct: %TestEmptyStruct.type = struct_value () [concrete]\n// CHECK:STDOUT:   %TestC.type: type = fn_type @TestC [concrete]\n// CHECK:STDOUT:   %TestC: %TestC.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %TestEmptyStruct.decl: %TestEmptyStruct.type = fn_decl @TestEmptyStruct [concrete = constants.%TestEmptyStruct] {\n// CHECK:STDOUT:     %s.patt: %pattern_type.b42 = value_binding_pattern s [concrete]\n// CHECK:STDOUT:     %s.param_patt: %pattern_type.b42 = value_param_pattern %s.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc11_45.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc11_45.2: Core.Form = init_form %.loc11_45.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %s.param: %.b2d = value_param call_param0\n// CHECK:STDOUT:     %.loc11_39.1: type = splice_block %.loc11_39.3 [concrete = constants.%.b2d] {\n// CHECK:STDOUT:       %MakeUnformed.ref: %MakeUnformed.type = name_ref MakeUnformed, file.%MakeUnformed.decl [concrete = constants.%MakeUnformed]\n// CHECK:STDOUT:       %.loc11_37: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc11_38: type = converted %.loc11_37, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %ptr: type = ptr_type %.loc11_38 [concrete = constants.%ptr.c28]\n// CHECK:STDOUT:       %MakeUnformed.call: init type = call %MakeUnformed.ref(%ptr) [concrete = constants.%.b2d]\n// CHECK:STDOUT:       %.loc11_39.2: type = value_of_initializer %MakeUnformed.call [concrete = constants.%.b2d]\n// CHECK:STDOUT:       %.loc11_39.3: type = converted %MakeUnformed.call, %.loc11_39.2 [concrete = constants.%.b2d]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %s: %.b2d = value_binding s, %s.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param1\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %TestC.decl: %TestC.type = fn_decl @TestC [concrete = constants.%TestC] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.b78 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.b78 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_34.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc15_34.2: Core.Form = init_form %.loc15_34.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %c.param: %.edf = value_param call_param0\n// CHECK:STDOUT:     %.loc15_28.1: type = splice_block %.loc15_28.3 [concrete = constants.%.edf] {\n// CHECK:STDOUT:       %MakeUnformed.ref: %MakeUnformed.type = name_ref MakeUnformed, file.%MakeUnformed.decl [concrete = constants.%MakeUnformed]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %ptr: type = ptr_type %C.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:       %MakeUnformed.call: init type = call %MakeUnformed.ref(%ptr) [concrete = constants.%.edf]\n// CHECK:STDOUT:       %.loc15_28.2: type = value_of_initializer %MakeUnformed.call [concrete = constants.%.edf]\n// CHECK:STDOUT:       %.loc15_28.3: type = converted %MakeUnformed.call, %.loc15_28.2 [concrete = constants.%.edf]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %.edf = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param1\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @TestEmptyStruct(%s.param: %.b2d) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %IsNullEmptyStruct.ref: %IsNullEmptyStruct.type = name_ref IsNullEmptyStruct, file.%IsNullEmptyStruct.decl [concrete = constants.%IsNullEmptyStruct]\n// CHECK:STDOUT:   %s.ref: %.b2d = name_ref s, %s\n// CHECK:STDOUT:   %IsNullEmptyStruct.call: init bool = call %IsNullEmptyStruct.ref(%s.ref)\n// CHECK:STDOUT:   return %IsNullEmptyStruct.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @TestC(%c.param: %.edf) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %IsNullC.ref: %IsNullC.type = name_ref IsNullC, file.%IsNullC.decl [concrete = constants.%IsNullC]\n// CHECK:STDOUT:   %c.ref: %.edf = name_ref c, %c\n// CHECK:STDOUT:   %IsNullC.call: init bool = call %IsNullC.ref(%c.ref)\n// CHECK:STDOUT:   return %IsNullC.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- call_generic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %MakeUnformed.type: type = fn_type @MakeUnformed [concrete]\n// CHECK:STDOUT:   %MakeUnformed: %MakeUnformed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.f34: Core.Form = init_form bool [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %IsNull.type: type = fn_type @IsNull [concrete]\n// CHECK:STDOUT:   %IsNull: %IsNull.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.b2d: type = maybe_unformed_type %ptr.c28 [concrete]\n// CHECK:STDOUT:   %pattern_type.b42: type = pattern_type %.b2d [concrete]\n// CHECK:STDOUT:   %TestEmptyStruct.type: type = fn_type @TestEmptyStruct [concrete]\n// CHECK:STDOUT:   %TestEmptyStruct: %TestEmptyStruct.type = struct_value () [concrete]\n// CHECK:STDOUT:   %IsNull.specific_fn.34e: <specific function> = specific_function %IsNull, @IsNull(%empty_struct_type) [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %.edf: type = maybe_unformed_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %pattern_type.b78: type = pattern_type %.edf [concrete]\n// CHECK:STDOUT:   %TestC.type: type = fn_type @TestC [concrete]\n// CHECK:STDOUT:   %TestC: %TestC.type = struct_value () [concrete]\n// CHECK:STDOUT:   %IsNull.specific_fn.b1f: <specific function> = specific_function %IsNull, @IsNull(%C) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %TestEmptyStruct.decl: %TestEmptyStruct.type = fn_decl @TestEmptyStruct [concrete = constants.%TestEmptyStruct] {\n// CHECK:STDOUT:     %s.patt: %pattern_type.b42 = value_binding_pattern s [concrete]\n// CHECK:STDOUT:     %s.param_patt: %pattern_type.b42 = value_param_pattern %s.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc10_45.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc10_45.2: Core.Form = init_form %.loc10_45.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %s.param: %.b2d = value_param call_param0\n// CHECK:STDOUT:     %.loc10_39.1: type = splice_block %.loc10_39.3 [concrete = constants.%.b2d] {\n// CHECK:STDOUT:       %MakeUnformed.ref: %MakeUnformed.type = name_ref MakeUnformed, file.%MakeUnformed.decl [concrete = constants.%MakeUnformed]\n// CHECK:STDOUT:       %.loc10_37: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc10_38: type = converted %.loc10_37, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %ptr: type = ptr_type %.loc10_38 [concrete = constants.%ptr.c28]\n// CHECK:STDOUT:       %MakeUnformed.call: init type = call %MakeUnformed.ref(%ptr) [concrete = constants.%.b2d]\n// CHECK:STDOUT:       %.loc10_39.2: type = value_of_initializer %MakeUnformed.call [concrete = constants.%.b2d]\n// CHECK:STDOUT:       %.loc10_39.3: type = converted %MakeUnformed.call, %.loc10_39.2 [concrete = constants.%.b2d]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %s: %.b2d = value_binding s, %s.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param1\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %TestC.decl: %TestC.type = fn_decl @TestC [concrete = constants.%TestC] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.b78 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.b78 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc14_34.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc14_34.2: Core.Form = init_form %.loc14_34.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %c.param: %.edf = value_param call_param0\n// CHECK:STDOUT:     %.loc14_28.1: type = splice_block %.loc14_28.3 [concrete = constants.%.edf] {\n// CHECK:STDOUT:       %MakeUnformed.ref: %MakeUnformed.type = name_ref MakeUnformed, file.%MakeUnformed.decl [concrete = constants.%MakeUnformed]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %ptr: type = ptr_type %C.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:       %MakeUnformed.call: init type = call %MakeUnformed.ref(%ptr) [concrete = constants.%.edf]\n// CHECK:STDOUT:       %.loc14_28.2: type = value_of_initializer %MakeUnformed.call [concrete = constants.%.edf]\n// CHECK:STDOUT:       %.loc14_28.3: type = converted %MakeUnformed.call, %.loc14_28.2 [concrete = constants.%.edf]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %.edf = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param1\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @TestEmptyStruct(%s.param: %.b2d) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %IsNull.ref: %IsNull.type = name_ref IsNull, file.%IsNull.decl [concrete = constants.%IsNull]\n// CHECK:STDOUT:   %s.ref: %.b2d = name_ref s, %s\n// CHECK:STDOUT:   %IsNull.specific_fn: <specific function> = specific_function %IsNull.ref, @IsNull(constants.%empty_struct_type) [concrete = constants.%IsNull.specific_fn.34e]\n// CHECK:STDOUT:   %IsNull.call: init bool = call %IsNull.specific_fn(%s.ref)\n// CHECK:STDOUT:   return %IsNull.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @TestC(%c.param: %.edf) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %IsNull.ref: %IsNull.type = name_ref IsNull, file.%IsNull.decl [concrete = constants.%IsNull]\n// CHECK:STDOUT:   %c.ref: %.edf = name_ref c, %c\n// CHECK:STDOUT:   %IsNull.specific_fn: <specific function> = specific_function %IsNull.ref, @IsNull(constants.%C) [concrete = constants.%IsNull.specific_fn.b1f]\n// CHECK:STDOUT:   %IsNull.call: init bool = call %IsNull.specific_fn(%c.ref)\n// CHECK:STDOUT:   return %IsNull.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/pointer/make_null.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/pointer/make_null.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/pointer/make_null.carbon\n\n// --- call_exact.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn MakeUnformed(t: type) -> type = \"maybe_unformed.make_type\";\nfn MakeNullEmptyStruct() -> MakeUnformed({}*) = \"pointer.make_null\";\nfn MakeNullC() -> MakeUnformed(C*) = \"pointer.make_null\";\n\n//@dump-sem-ir-begin\nlet s: MakeUnformed({}*) = MakeNullEmptyStruct();\nlet c: MakeUnformed(C*) = MakeNullC();\n//@dump-sem-ir-end\n\n// --- call_generic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn MakeUnformed(t: type) -> type = \"maybe_unformed.make_type\";\nfn MakeNull(T:! type) -> MakeUnformed(T*) = \"pointer.make_null\";\n\nclass C {}\n\n//@dump-sem-ir-begin\nlet s: MakeUnformed({}*) = MakeNull({});\nlet c: MakeUnformed(C*) = MakeNull(C);\n//@dump-sem-ir-end\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn MakeUnformed(t: type) -> type = \"maybe_unformed.make_type\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"pointer.make_null\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NoRetType() = \"pointer.make_null\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NoRetType() = \"pointer.make_null\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"pointer.make_null\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NoUnformed() -> {}* = \"pointer.make_null\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NoUnformed() -> {}* = \"pointer.make_null\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"pointer.make_null\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn NotPointer() -> MakeUnformed({}) = \"pointer.make_null\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotPointer() -> MakeUnformed({}) = \"pointer.make_null\";\n\n// CHECK:STDOUT: --- call_exact.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %MakeUnformed.type: type = fn_type @MakeUnformed [concrete]\n// CHECK:STDOUT:   %MakeUnformed: %MakeUnformed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.b2d: type = maybe_unformed_type %ptr.c28 [concrete]\n// CHECK:STDOUT:   %pattern_type.b42: type = pattern_type %.b2d [concrete]\n// CHECK:STDOUT:   %MakeNullEmptyStruct.type: type = fn_type @MakeNullEmptyStruct [concrete]\n// CHECK:STDOUT:   %MakeNullEmptyStruct: %MakeNullEmptyStruct.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %.edf: type = maybe_unformed_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %pattern_type.b78: type = pattern_type %.edf [concrete]\n// CHECK:STDOUT:   %MakeNullC.type: type = fn_type @MakeNullC [concrete]\n// CHECK:STDOUT:   %MakeNullC: %MakeNullC.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %s.patt: %pattern_type.b42 = value_binding_pattern s [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc11_24.1: type = splice_block %.loc11_24.3 [concrete = constants.%.b2d] {\n// CHECK:STDOUT:     %MakeUnformed.ref.loc11: %MakeUnformed.type = name_ref MakeUnformed, %MakeUnformed.decl [concrete = constants.%MakeUnformed]\n// CHECK:STDOUT:     %.loc11_22: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc11_23: type = converted %.loc11_22, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %ptr.loc11: type = ptr_type %.loc11_23 [concrete = constants.%ptr.c28]\n// CHECK:STDOUT:     %MakeUnformed.call.loc11: init type = call %MakeUnformed.ref.loc11(%ptr.loc11) [concrete = constants.%.b2d]\n// CHECK:STDOUT:     %.loc11_24.2: type = value_of_initializer %MakeUnformed.call.loc11 [concrete = constants.%.b2d]\n// CHECK:STDOUT:     %.loc11_24.3: type = converted %MakeUnformed.call.loc11, %.loc11_24.2 [concrete = constants.%.b2d]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc11_48.1: %.b2d = value_of_initializer @__global_init.%MakeNullEmptyStruct.call\n// CHECK:STDOUT:   %.loc11_48.2: %.b2d = converted @__global_init.%MakeNullEmptyStruct.call, %.loc11_48.1\n// CHECK:STDOUT:   %s: %.b2d = value_binding s, %.loc11_48.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.b78 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc12_23.1: type = splice_block %.loc12_23.3 [concrete = constants.%.edf] {\n// CHECK:STDOUT:     %MakeUnformed.ref.loc12: %MakeUnformed.type = name_ref MakeUnformed, %MakeUnformed.decl [concrete = constants.%MakeUnformed]\n// CHECK:STDOUT:     %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr.loc12: type = ptr_type %C.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:     %MakeUnformed.call.loc12: init type = call %MakeUnformed.ref.loc12(%ptr.loc12) [concrete = constants.%.edf]\n// CHECK:STDOUT:     %.loc12_23.2: type = value_of_initializer %MakeUnformed.call.loc12 [concrete = constants.%.edf]\n// CHECK:STDOUT:     %.loc12_23.3: type = converted %MakeUnformed.call.loc12, %.loc12_23.2 [concrete = constants.%.edf]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc12_37.1: %.edf = value_of_initializer @__global_init.%MakeNullC.call\n// CHECK:STDOUT:   %.loc12_37.2: %.edf = converted @__global_init.%MakeNullC.call, %.loc12_37.1\n// CHECK:STDOUT:   %c: %.edf = value_binding c, %.loc12_37.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %MakeNullEmptyStruct.ref: %MakeNullEmptyStruct.type = name_ref MakeNullEmptyStruct, file.%MakeNullEmptyStruct.decl [concrete = constants.%MakeNullEmptyStruct]\n// CHECK:STDOUT:   %MakeNullEmptyStruct.call: init %.b2d = call %MakeNullEmptyStruct.ref()\n// CHECK:STDOUT:   %MakeNullC.ref: %MakeNullC.type = name_ref MakeNullC, file.%MakeNullC.decl [concrete = constants.%MakeNullC]\n// CHECK:STDOUT:   %MakeNullC.call: init %.edf = call %MakeNullC.ref()\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- call_generic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %MakeUnformed.type: type = fn_type @MakeUnformed [concrete]\n// CHECK:STDOUT:   %MakeUnformed: %MakeUnformed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %MakeNull.type: type = fn_type @MakeNull [concrete]\n// CHECK:STDOUT:   %MakeNull: %MakeNull.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.b2d: type = maybe_unformed_type %ptr.c28 [concrete]\n// CHECK:STDOUT:   %pattern_type.b42: type = pattern_type %.b2d [concrete]\n// CHECK:STDOUT:   %MakeNull.specific_fn.4e3: <specific function> = specific_function %MakeNull, @MakeNull(%empty_struct_type) [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %.edf: type = maybe_unformed_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %pattern_type.b78: type = pattern_type %.edf [concrete]\n// CHECK:STDOUT:   %MakeNull.specific_fn.152: <specific function> = specific_function %MakeNull, @MakeNull(%C) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %s.patt: %pattern_type.b42 = value_binding_pattern s [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc10_24.1: type = splice_block %.loc10_24.3 [concrete = constants.%.b2d] {\n// CHECK:STDOUT:     %MakeUnformed.ref.loc10: %MakeUnformed.type = name_ref MakeUnformed, %MakeUnformed.decl [concrete = constants.%MakeUnformed]\n// CHECK:STDOUT:     %.loc10_22: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc10_23: type = converted %.loc10_22, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %ptr.loc10: type = ptr_type %.loc10_23 [concrete = constants.%ptr.c28]\n// CHECK:STDOUT:     %MakeUnformed.call.loc10: init type = call %MakeUnformed.ref.loc10(%ptr.loc10) [concrete = constants.%.b2d]\n// CHECK:STDOUT:     %.loc10_24.2: type = value_of_initializer %MakeUnformed.call.loc10 [concrete = constants.%.b2d]\n// CHECK:STDOUT:     %.loc10_24.3: type = converted %MakeUnformed.call.loc10, %.loc10_24.2 [concrete = constants.%.b2d]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc10_39.1: %.b2d = value_of_initializer @__global_init.%MakeNull.call.loc10\n// CHECK:STDOUT:   %.loc10_39.2: %.b2d = converted @__global_init.%MakeNull.call.loc10, %.loc10_39.1\n// CHECK:STDOUT:   %s: %.b2d = value_binding s, %.loc10_39.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.b78 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc11_23.1: type = splice_block %.loc11_23.3 [concrete = constants.%.edf] {\n// CHECK:STDOUT:     %MakeUnformed.ref.loc11: %MakeUnformed.type = name_ref MakeUnformed, %MakeUnformed.decl [concrete = constants.%MakeUnformed]\n// CHECK:STDOUT:     %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr.loc11: type = ptr_type %C.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:     %MakeUnformed.call.loc11: init type = call %MakeUnformed.ref.loc11(%ptr.loc11) [concrete = constants.%.edf]\n// CHECK:STDOUT:     %.loc11_23.2: type = value_of_initializer %MakeUnformed.call.loc11 [concrete = constants.%.edf]\n// CHECK:STDOUT:     %.loc11_23.3: type = converted %MakeUnformed.call.loc11, %.loc11_23.2 [concrete = constants.%.edf]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc11_37.1: %.edf = value_of_initializer @__global_init.%MakeNull.call.loc11\n// CHECK:STDOUT:   %.loc11_37.2: %.edf = converted @__global_init.%MakeNull.call.loc11, %.loc11_37.1\n// CHECK:STDOUT:   %c: %.edf = value_binding c, %.loc11_37.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %MakeNull.ref.loc10: %MakeNull.type = name_ref MakeNull, file.%MakeNull.decl [concrete = constants.%MakeNull]\n// CHECK:STDOUT:   %.loc10_38: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc10_39: type = converted %.loc10_38, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %MakeNull.specific_fn.loc10: <specific function> = specific_function %MakeNull.ref.loc10, @MakeNull(constants.%empty_struct_type) [concrete = constants.%MakeNull.specific_fn.4e3]\n// CHECK:STDOUT:   %MakeNull.call.loc10: init %.b2d = call %MakeNull.specific_fn.loc10()\n// CHECK:STDOUT:   %MakeNull.ref.loc11: %MakeNull.type = name_ref MakeNull, file.%MakeNull.decl [concrete = constants.%MakeNull]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %MakeNull.specific_fn.loc11: <specific function> = specific_function %MakeNull.ref.loc11, @MakeNull(constants.%C) [concrete = constants.%MakeNull.specific_fn.152]\n// CHECK:STDOUT:   %MakeNull.call.loc11: init %.edf = call %MakeNull.specific_fn.loc11()\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/print/char.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/print/char.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/print/char.carbon\n\nimport Core library \"io\";\n\nfn PrintChar(a: char) -> i32 = \"print.char\";\n\nfn Main() {\n  //@dump-sem-ir-begin\n  PrintChar('1');\n  Core.PrintChar('2');\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- char.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %char: type = class_type @Char [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %PrintChar.type.7fc: type = fn_type @PrintChar.loc15 [concrete]\n// CHECK:STDOUT:   %PrintChar.f2e: %PrintChar.type.7fc = struct_value () [concrete]\n// CHECK:STDOUT:   %.75c: Core.CharLiteral = char_value U+0031 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.d99: type = facet_type <@ImplicitAs, @ImplicitAs(%char)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.158: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.4bc [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.d99 = facet_value Core.CharLiteral, (%ImplicitAs.impl_witness.158) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.95b: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%char, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.734: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.95b, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.CharLiteral.as.ImplicitAs.impl.Convert.type: type = fn_type @Core.CharLiteral.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %Core.CharLiteral.as.ImplicitAs.impl.Convert: %Core.CharLiteral.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Core.CharLiteral.as.ImplicitAs.impl.Convert.bound.75d: <bound method> = bound_method %.75c, %Core.CharLiteral.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %int_49: %char = int_value 49 [concrete]\n// CHECK:STDOUT:   %PrintChar.type.089: type = fn_type @PrintChar.1 [concrete]\n// CHECK:STDOUT:   %PrintChar.d75: %PrintChar.type.089 = struct_value () [concrete]\n// CHECK:STDOUT:   %.f8d: Core.CharLiteral = char_value U+0032 [concrete]\n// CHECK:STDOUT:   %Core.CharLiteral.as.ImplicitAs.impl.Convert.bound.957: <bound method> = bound_method %.f8d, %Core.CharLiteral.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %int_50: %char = int_value 50 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Char = %Core.Char\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .PrintChar = %Core.PrintChar\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//io\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Char: type = import_ref Core//prelude/types/char, Char, loaded [concrete = constants.%char]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.b73: %Core.CharLiteral.as.ImplicitAs.impl.Convert.type = import_ref Core//prelude/types/char, loc{{\\d+_\\d+}}, loaded [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.4bc = impl_witness_table (%Core.import_ref.b73), @Core.CharLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.PrintChar: %PrintChar.type.089 = import_ref Core//io, PrintChar, loaded [concrete = constants.%PrintChar.d75]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %PrintChar.ref.loc19: %PrintChar.type.7fc = name_ref PrintChar, file.%PrintChar.decl [concrete = constants.%PrintChar.f2e]\n// CHECK:STDOUT:   %.loc19_13.1: Core.CharLiteral = char_value U+0031 [concrete = constants.%.75c]\n// CHECK:STDOUT:   %impl.elem0.loc19: %.734 = impl_witness_access constants.%ImplicitAs.impl_witness.158, element0 [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:   %bound_method.loc19: <bound method> = bound_method %.loc19_13.1, %impl.elem0.loc19 [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert.bound.75d]\n// CHECK:STDOUT:   %Core.CharLiteral.as.ImplicitAs.impl.Convert.call.loc19: init %char = call %bound_method.loc19(%.loc19_13.1) [concrete = constants.%int_49]\n// CHECK:STDOUT:   %.loc19_13.2: %char = value_of_initializer %Core.CharLiteral.as.ImplicitAs.impl.Convert.call.loc19 [concrete = constants.%int_49]\n// CHECK:STDOUT:   %.loc19_13.3: %char = converted %.loc19_13.1, %.loc19_13.2 [concrete = constants.%int_49]\n// CHECK:STDOUT:   %PrintChar.call.loc19: init %i32 = call %PrintChar.ref.loc19(%.loc19_13.3)\n// CHECK:STDOUT:   %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %PrintChar.ref.loc20: %PrintChar.type.089 = name_ref PrintChar, imports.%Core.PrintChar [concrete = constants.%PrintChar.d75]\n// CHECK:STDOUT:   %.loc20_18.1: Core.CharLiteral = char_value U+0032 [concrete = constants.%.f8d]\n// CHECK:STDOUT:   %impl.elem0.loc20: %.734 = impl_witness_access constants.%ImplicitAs.impl_witness.158, element0 [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:   %bound_method.loc20: <bound method> = bound_method %.loc20_18.1, %impl.elem0.loc20 [concrete = constants.%Core.CharLiteral.as.ImplicitAs.impl.Convert.bound.957]\n// CHECK:STDOUT:   %Core.CharLiteral.as.ImplicitAs.impl.Convert.call.loc20: init %char = call %bound_method.loc20(%.loc20_18.1) [concrete = constants.%int_50]\n// CHECK:STDOUT:   %.loc20_18.2: %char = value_of_initializer %Core.CharLiteral.as.ImplicitAs.impl.Convert.call.loc20 [concrete = constants.%int_50]\n// CHECK:STDOUT:   %.loc20_18.3: %char = converted %.loc20_18.1, %.loc20_18.2 [concrete = constants.%int_50]\n// CHECK:STDOUT:   %PrintChar.call.loc20: init %i32 = call %PrintChar.ref.loc20(%.loc20_18.3)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/print/int.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/print/int.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/print/int.carbon\n\nimport Core library \"io\";\n\nfn Print(a: i32) = \"print.int\";\n\nfn Main() {\n  //@dump-sem-ir-begin\n  Print(1);\n  Core.Print(2);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- int.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Print.type.543: type = fn_type @Print.loc15 [concrete]\n// CHECK:STDOUT:   %Print.029: %Print.type.543 = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Print.type.6ed: type = fn_type @Print.1 [concrete]\n// CHECK:STDOUT:   %Print.723: %Print.type.6ed = struct_value () [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Print = %Core.Print\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//io\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Print: %Print.type.6ed = import_ref Core//io, Print, loaded [concrete = constants.%Print.723]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Print.ref.loc19: %Print.type.543 = name_ref Print, file.%Print.decl [concrete = constants.%Print.029]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc19: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc19_9.1: <bound method> = bound_method %int_1, %impl.elem0.loc19 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc19: <specific function> = specific_function %impl.elem0.loc19, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc19_9.2: <bound method> = bound_method %int_1, %specific_fn.loc19 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc19: init %i32 = call %bound_method.loc19_9.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc19_9.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc19 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc19_9.2: %i32 = converted %int_1, %.loc19_9.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %Print.call.loc19: init %empty_tuple.type = call %Print.ref.loc19(%.loc19_9.2)\n// CHECK:STDOUT:   %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %Print.ref.loc20: %Print.type.6ed = name_ref Print, imports.%Core.Print [concrete = constants.%Print.723]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc20: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc20_14.1: <bound method> = bound_method %int_2, %impl.elem0.loc20 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc20: <specific function> = specific_function %impl.elem0.loc20, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc20_14.2: <bound method> = bound_method %int_2, %specific_fn.loc20 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc20: init %i32 = call %bound_method.loc20_14.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc20_14.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc20 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc20_14.2: %i32 = converted %int_2, %.loc20_14.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %Print.call.loc20: init %empty_tuple.type = call %Print.ref.loc20(%.loc20_14.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/read/char.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/read/char.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/read/char.carbon\n\n// --- char.carbon\n\nimport Core library \"io\";\n\nfn ReadChar() -> i32 = \"read.char\";\n\nfn Main() {\n  //@dump-sem-ir-begin\n  let unused n: i32 = ReadChar();\n  let unused m: i32 = Core.ReadChar();\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- char.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %ReadChar.type.c36: type = fn_type @ReadChar.loc4 [concrete]\n// CHECK:STDOUT:   %ReadChar.6ad: %ReadChar.type.c36 = struct_value () [concrete]\n// CHECK:STDOUT:   %ReadChar.type.9f3: type = fn_type @ReadChar.1 [concrete]\n// CHECK:STDOUT:   %ReadChar.01f: %ReadChar.type.9f3 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ReadChar = %Core.ReadChar\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//io\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ReadChar: %ReadChar.type.9f3 = import_ref Core//io, ReadChar, loaded [concrete = constants.%ReadChar.01f]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ReadChar.ref.loc8: %ReadChar.type.c36 = name_ref ReadChar, file.%ReadChar.decl [concrete = constants.%ReadChar.6ad]\n// CHECK:STDOUT:   %ReadChar.call.loc8: init %i32 = call %ReadChar.ref.loc8()\n// CHECK:STDOUT:   %i32.loc8: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc8_32.1: %i32 = value_of_initializer %ReadChar.call.loc8\n// CHECK:STDOUT:   %.loc8_32.2: %i32 = converted %ReadChar.call.loc8, %.loc8_32.1\n// CHECK:STDOUT:   %n: %i32 = value_binding n, %.loc8_32.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %m.patt: %pattern_type.7ce = value_binding_pattern m [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %ReadChar.ref.loc9: %ReadChar.type.9f3 = name_ref ReadChar, imports.%Core.ReadChar [concrete = constants.%ReadChar.01f]\n// CHECK:STDOUT:   %ReadChar.call.loc9: init %i32 = call %ReadChar.ref.loc9()\n// CHECK:STDOUT:   %i32.loc9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc9_37.1: %i32 = value_of_initializer %ReadChar.call.loc9\n// CHECK:STDOUT:   %.loc9_37.2: %i32 = converted %ReadChar.call.loc9, %.loc9_37.1\n// CHECK:STDOUT:   %m: %i32 = value_binding m, %.loc9_37.2\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/builtins/type/and.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/builtins/type/and.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/builtins/type/and.carbon\n\n// --- combine_facets.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn TypeAnd(a: type, b: type) -> type = \"type.and\";\n\ninterface I {}\ninterface J {}\n\nfn TakeIJ(unused T:! TypeAnd(I, J)) {}\n\nclass IJ {\n  impl as I {}\n  impl as J {}\n}\n\nfn Call() {\n  TakeIJ(IJ);\n}\n\n// --- fail_combine_facets_bad_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn TypeAnd(a: type, b: type) -> type = \"type.and\";\n\ninterface I {}\ninterface J {}\n\nfn TakeIJ(unused T:! TypeAnd(I, J)) {}\n\nclass JustI {\n  impl as I {}\n}\n\nclass JustJ {\n  impl as J {}\n}\n\nfn Call() {\n  // CHECK:STDERR: fail_combine_facets_bad_call.carbon:[[@LINE+7]]:3: error: cannot convert type `JustI` into type implementing `I & J` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   TakeIJ(JustI);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_combine_facets_bad_call.carbon:[[@LINE-14]]:18: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn TakeIJ(unused T:! TypeAnd(I, J)) {}\n  // CHECK:STDERR:                  ^\n  // CHECK:STDERR:\n  TakeIJ(JustI);\n  // CHECK:STDERR: fail_combine_facets_bad_call.carbon:[[@LINE+7]]:3: error: cannot convert type `JustJ` into type implementing `I & J` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   TakeIJ(JustJ);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_combine_facets_bad_call.carbon:[[@LINE-22]]:18: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn TakeIJ(unused T:! TypeAnd(I, J)) {}\n  // CHECK:STDERR:                  ^\n  // CHECK:STDERR:\n  TakeIJ(JustJ);\n}\n\n// --- fail_bad_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"type.and\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooFew(a: type) -> type = \"type.and\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooFew(a: type) -> type = \"type.and\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"type.and\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn TooMany(a: type, b: type, c: type) -> type = \"type.and\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn TooMany(a: type, b: type, c: type) -> type = \"type.and\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"type.and\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn ParamNotType(a: {}, b: {}) -> type = \"type.and\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn ParamNotType(a: {}, b: {}) -> type = \"type.and\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"type.and\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn ResultNotType(a: type, b: type) -> {} = \"type.and\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn ResultNotType(a: type, b: type) -> {} = \"type.and\";\n\n// CHECK:STDERR: fail_bad_decl.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"type.and\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn ResultNotSpecified(a: type, b: type) = \"type.and\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn ResultNotSpecified(a: type, b: type) = \"type.and\";\n"
  },
  {
    "path": "toolchain/check/testdata/choice/basic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/uint.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/choice/basic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/choice/basic.carbon\n\n// --- no_alternative.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nchoice Never {}\n//@dump-sem-ir-end\n\n// --- one_alternative.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nchoice Always {\n  Sunny\n}\n\nlet mood: Always = Always.Sunny;\n//@dump-sem-ir-end\n\n// --- multiple_alternatives.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nchoice Ordering {\n  Less,\n  Equivalent,\n  Greater,\n  Incomparable\n}\n\nlet less: Ordering = Ordering.Less;\nlet equiv: Ordering = Ordering.Equivalent;\nlet greater: Ordering = Ordering.Greater;\nlet inc: Ordering = Ordering.Incomparable;\n//@dump-sem-ir-end\n\n// --- fail_no_alternative_construct.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nchoice Never {}\n\n// TODO: Can we produce a better diagnostic?\n// CHECK:STDERR: fail_no_alternative_construct.carbon:[[@LINE+4]]:20: error: cannot initialize class with 1 field from struct with 0 fields [StructInitElementCountMismatch]\n// CHECK:STDERR: let never: Never = {};\n// CHECK:STDERR:                    ^~\n// CHECK:STDERR:\nlet never: Never = {};\n\n// CHECK:STDOUT: --- no_alternative.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Never: type = class_type @Never [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %struct_type.discriminant: type = struct_type {.discriminant: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.discriminant [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Never.decl: type = class_decl @Never [concrete = constants.%Never] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Never {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.discriminant [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Never\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- one_alternative.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Always: type = class_type @Always [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %struct_type.discriminant: type = struct_type {.discriminant: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.discriminant [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.discriminant = struct_value (%empty_tuple) [concrete]\n// CHECK:STDOUT:   %Always.val: %Always = struct_value (%empty_tuple) [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Always [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Always.decl: type = class_decl @Always [concrete = constants.%Always] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %mood.patt: %pattern_type = value_binding_pattern mood [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Always.ref: type = name_ref Always, %Always.decl [concrete = constants.%Always]\n// CHECK:STDOUT:   %mood: %Always = value_binding mood, @__global_init.%Sunny.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Always {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.discriminant [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %.loc6_1.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_1.2: %empty_tuple.type = converted %.loc6_1.1, %empty_tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_1.3: %struct_type.discriminant = struct_literal (%.loc6_1.2) [concrete = constants.%struct]\n// CHECK:STDOUT:   %.loc6_1.4: ref %Always = temporary_storage\n// CHECK:STDOUT:   %.loc6_1.5: ref %empty_tuple.type = class_element_access %.loc6_1.4, element0\n// CHECK:STDOUT:   %.loc6_1.6: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_1.7: init %empty_tuple.type = converted %.loc6_1.2, %.loc6_1.6 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc6_1.8: init %Always to %.loc6_1.4 = class_init (%.loc6_1.7) [concrete = constants.%Always.val]\n// CHECK:STDOUT:   %.loc6_1.9: init %Always = converted %.loc6_1.3, %.loc6_1.8 [concrete = constants.%Always.val]\n// CHECK:STDOUT:   %.loc6_1.10: ref %Always = temporary %.loc6_1.4, %.loc6_1.9\n// CHECK:STDOUT:   %.loc6_1.11: %Always = acquire_value %.loc6_1.10\n// CHECK:STDOUT:   %Sunny: %Always = value_binding Sunny, %.loc6_1.11\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Always\n// CHECK:STDOUT:   .Sunny = %Sunny\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Always.ref: type = name_ref Always, file.%Always.decl [concrete = constants.%Always]\n// CHECK:STDOUT:   %Sunny.ref: %Always = name_ref Sunny, @Always.%Sunny\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- multiple_alternatives.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Ordering: type = class_type @Ordering [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %u2: type = class_type @UInt, @UInt(%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %struct_type.discriminant: type = struct_type {.discriminant: %u2} [concrete]\n// CHECK:STDOUT:   %complete_type.de2: <witness> = complete_type_witness %struct_type.discriminant [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.a92: type = facet_type <@ImplicitAs, @ImplicitAs(%u2)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.6a6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.46e: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.6a6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.762: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.899, @Core.IntLiteral.as.ImplicitAs.impl(%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.c8c: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.c8c = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.a92 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.762) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.539: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%u2, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.055: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.539, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.dd9: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %bound_method.f58: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.9fd: %u2 = int_value 0 [concrete]\n// CHECK:STDOUT:   %struct.559: %struct_type.discriminant = struct_value (%int_0.9fd) [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.type.68f: type = fn_type @UInt.as.Copy.impl.Op, @UInt.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.576: %UInt.as.Copy.impl.Op.type.68f = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.a32: <witness> = impl_witness imports.%Copy.impl_witness_table.bd0, @UInt.as.Copy.impl(%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.type.f98: type = fn_type @UInt.as.Copy.impl.Op, @UInt.as.Copy.impl(%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.b2d: %UInt.as.Copy.impl.Op.type.f98 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %u2, (%Copy.impl_witness.a32) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.bd7: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.a82: type = fn_type_with_self_type %Copy.WithSelf.Op.type.bd7, %Copy.facet [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.bound.fba: <bound method> = bound_method %int_0.9fd, %UInt.as.Copy.impl.Op.b2d [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %UInt.as.Copy.impl.Op.b2d, @UInt.as.Copy.impl.Op(%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %bound_method.428: <bound method> = bound_method %int_0.9fd, %UInt.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT:   %Ordering.val.9ea: %Ordering = struct_value (%int_0.9fd) [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.6b7: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed [concrete]\n// CHECK:STDOUT:   %bound_method.a4b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.b2c: %u2 = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct.0ff: %struct_type.discriminant = struct_value (%int_1.b2c) [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.bound.67d: <bound method> = bound_method %int_1.b2c, %UInt.as.Copy.impl.Op.b2d [concrete]\n// CHECK:STDOUT:   %bound_method.8f6: <bound method> = bound_method %int_1.b2c, %UInt.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT:   %Ordering.val.d41: %Ordering = struct_value (%int_1.b2c) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.c76: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed [concrete]\n// CHECK:STDOUT:   %bound_method.c5b: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.788: %u2 = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct.6e6: %struct_type.discriminant = struct_value (%int_2.788) [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.bound.f0c: <bound method> = bound_method %int_2.788, %UInt.as.Copy.impl.Op.b2d [concrete]\n// CHECK:STDOUT:   %bound_method.f1a: <bound method> = bound_method %int_2.788, %UInt.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT:   %Ordering.val.e86: %Ordering = struct_value (%int_2.788) [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.cdf: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed [concrete]\n// CHECK:STDOUT:   %bound_method.898: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.975: %u2 = int_value 3 [concrete]\n// CHECK:STDOUT:   %struct.7bd: %struct_type.discriminant = struct_value (%int_3.975) [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.bound.7b5: <bound method> = bound_method %int_3.975, %UInt.as.Copy.impl.Op.b2d [concrete]\n// CHECK:STDOUT:   %bound_method.824: <bound method> = bound_method %int_3.975, %UInt.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT:   %Ordering.val.a17: %Ordering = struct_value (%int_3.975) [concrete]\n// CHECK:STDOUT:   %pattern_type.a36: type = pattern_type %Ordering [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.741: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.6a6) = import_ref Core//prelude/parts/uint, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.46e)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.899 = impl_witness_table (%Core.import_ref.741), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.c3c: @UInt.as.Copy.impl.%UInt.as.Copy.impl.Op.type (%UInt.as.Copy.impl.Op.type.68f) = import_ref Core//prelude/parts/uint, loc{{\\d+_\\d+}}, loaded [symbolic = @UInt.as.Copy.impl.%UInt.as.Copy.impl.Op (constants.%UInt.as.Copy.impl.Op.576)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.bd0 = impl_witness_table (%Core.import_ref.c3c), @UInt.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Ordering.decl: type = class_decl @Ordering [concrete = constants.%Ordering] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %less.patt: %pattern_type.a36 = value_binding_pattern less [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Ordering.ref.loc11: type = name_ref Ordering, %Ordering.decl [concrete = constants.%Ordering]\n// CHECK:STDOUT:   %less: %Ordering = value_binding less, @__global_init.%Less.ref\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %equiv.patt: %pattern_type.a36 = value_binding_pattern equiv [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Ordering.ref.loc12: type = name_ref Ordering, %Ordering.decl [concrete = constants.%Ordering]\n// CHECK:STDOUT:   %equiv: %Ordering = value_binding equiv, @__global_init.%Equivalent.ref\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %greater.patt: %pattern_type.a36 = value_binding_pattern greater [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Ordering.ref.loc13: type = name_ref Ordering, %Ordering.decl [concrete = constants.%Ordering]\n// CHECK:STDOUT:   %greater: %Ordering = value_binding greater, @__global_init.%Greater.ref\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %inc.patt: %pattern_type.a36 = value_binding_pattern inc [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Ordering.ref.loc14: type = name_ref Ordering, %Ordering.decl [concrete = constants.%Ordering]\n// CHECK:STDOUT:   %inc: %Ordering = value_binding inc, @__global_init.%Incomparable.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Ordering {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.discriminant [concrete = constants.%complete_type.de2]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %impl.elem0.loc5_7.1: %.055 = impl_witness_access constants.%ImplicitAs.impl_witness.762, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed]\n// CHECK:STDOUT:   %bound_method.loc5_7.1: <bound method> = bound_method %int_0, %impl.elem0.loc5_7.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.dd9]\n// CHECK:STDOUT:   %specific_fn.loc5_7.1: <specific function> = specific_function %impl.elem0.loc5_7.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_2.ecc) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc5_7.2: <bound method> = bound_method %int_0, %specific_fn.loc5_7.1 [concrete = constants.%bound_method.f58]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5: init %u2 = call %bound_method.loc5_7.2(%int_0) [concrete = constants.%int_0.9fd]\n// CHECK:STDOUT:   %.loc5_7.1: %u2 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5 [concrete = constants.%int_0.9fd]\n// CHECK:STDOUT:   %.loc5_7.2: %u2 = converted %int_0, %.loc5_7.1 [concrete = constants.%int_0.9fd]\n// CHECK:STDOUT:   %.loc5_7.3: %struct_type.discriminant = struct_literal (%.loc5_7.2) [concrete = constants.%struct.559]\n// CHECK:STDOUT:   %impl.elem0.loc5_7.2: %.a82 = impl_witness_access constants.%Copy.impl_witness.a32, element0 [concrete = constants.%UInt.as.Copy.impl.Op.b2d]\n// CHECK:STDOUT:   %bound_method.loc5_7.3: <bound method> = bound_method %.loc5_7.2, %impl.elem0.loc5_7.2 [concrete = constants.%UInt.as.Copy.impl.Op.bound.fba]\n// CHECK:STDOUT:   %specific_fn.loc5_7.2: <specific function> = specific_function %impl.elem0.loc5_7.2, @UInt.as.Copy.impl.Op(constants.%int_2.ecc) [concrete = constants.%UInt.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc5_7.4: <bound method> = bound_method %.loc5_7.2, %specific_fn.loc5_7.2 [concrete = constants.%bound_method.428]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.call.loc5: init %u2 = call %bound_method.loc5_7.4(%.loc5_7.2) [concrete = constants.%int_0.9fd]\n// CHECK:STDOUT:   %.loc5_7.4: ref %Ordering = temporary_storage\n// CHECK:STDOUT:   %.loc5_7.5: ref %u2 = class_element_access %.loc5_7.4, element0\n// CHECK:STDOUT:   %.loc5_7.6: init %u2 to %.loc5_7.5 = in_place_init %UInt.as.Copy.impl.Op.call.loc5 [concrete = constants.%int_0.9fd]\n// CHECK:STDOUT:   %.loc5_7.7: init %Ordering to %.loc5_7.4 = class_init (%.loc5_7.6) [concrete = constants.%Ordering.val.9ea]\n// CHECK:STDOUT:   %.loc5_7.8: init %Ordering = converted %.loc5_7.3, %.loc5_7.7 [concrete = constants.%Ordering.val.9ea]\n// CHECK:STDOUT:   %.loc5_7.9: ref %Ordering = temporary %.loc5_7.4, %.loc5_7.8\n// CHECK:STDOUT:   %.loc5_7.10: %Ordering = acquire_value %.loc5_7.9\n// CHECK:STDOUT:   %Less: %Ordering = value_binding Less, %.loc5_7.10\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc6_13.1: %.055 = impl_witness_access constants.%ImplicitAs.impl_witness.762, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed]\n// CHECK:STDOUT:   %bound_method.loc6_13.1: <bound method> = bound_method %int_1, %impl.elem0.loc6_13.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.6b7]\n// CHECK:STDOUT:   %specific_fn.loc6_13.1: <specific function> = specific_function %impl.elem0.loc6_13.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_2.ecc) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_13.2: <bound method> = bound_method %int_1, %specific_fn.loc6_13.1 [concrete = constants.%bound_method.a4b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %u2 = call %bound_method.loc6_13.2(%int_1) [concrete = constants.%int_1.b2c]\n// CHECK:STDOUT:   %.loc6_13.1: %u2 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%int_1.b2c]\n// CHECK:STDOUT:   %.loc6_13.2: %u2 = converted %int_1, %.loc6_13.1 [concrete = constants.%int_1.b2c]\n// CHECK:STDOUT:   %.loc6_13.3: %struct_type.discriminant = struct_literal (%.loc6_13.2) [concrete = constants.%struct.0ff]\n// CHECK:STDOUT:   %impl.elem0.loc6_13.2: %.a82 = impl_witness_access constants.%Copy.impl_witness.a32, element0 [concrete = constants.%UInt.as.Copy.impl.Op.b2d]\n// CHECK:STDOUT:   %bound_method.loc6_13.3: <bound method> = bound_method %.loc6_13.2, %impl.elem0.loc6_13.2 [concrete = constants.%UInt.as.Copy.impl.Op.bound.67d]\n// CHECK:STDOUT:   %specific_fn.loc6_13.2: <specific function> = specific_function %impl.elem0.loc6_13.2, @UInt.as.Copy.impl.Op(constants.%int_2.ecc) [concrete = constants.%UInt.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_13.4: <bound method> = bound_method %.loc6_13.2, %specific_fn.loc6_13.2 [concrete = constants.%bound_method.8f6]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.call.loc6: init %u2 = call %bound_method.loc6_13.4(%.loc6_13.2) [concrete = constants.%int_1.b2c]\n// CHECK:STDOUT:   %.loc6_13.4: ref %Ordering = temporary_storage\n// CHECK:STDOUT:   %.loc6_13.5: ref %u2 = class_element_access %.loc6_13.4, element0\n// CHECK:STDOUT:   %.loc6_13.6: init %u2 to %.loc6_13.5 = in_place_init %UInt.as.Copy.impl.Op.call.loc6 [concrete = constants.%int_1.b2c]\n// CHECK:STDOUT:   %.loc6_13.7: init %Ordering to %.loc6_13.4 = class_init (%.loc6_13.6) [concrete = constants.%Ordering.val.d41]\n// CHECK:STDOUT:   %.loc6_13.8: init %Ordering = converted %.loc6_13.3, %.loc6_13.7 [concrete = constants.%Ordering.val.d41]\n// CHECK:STDOUT:   %.loc6_13.9: ref %Ordering = temporary %.loc6_13.4, %.loc6_13.8\n// CHECK:STDOUT:   %.loc6_13.10: %Ordering = acquire_value %.loc6_13.9\n// CHECK:STDOUT:   %Equivalent: %Ordering = value_binding Equivalent, %.loc6_13.10\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc7_10.1: %.055 = impl_witness_access constants.%ImplicitAs.impl_witness.762, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed]\n// CHECK:STDOUT:   %bound_method.loc7_10.1: <bound method> = bound_method %int_2, %impl.elem0.loc7_10.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.c76]\n// CHECK:STDOUT:   %specific_fn.loc7_10.1: <specific function> = specific_function %impl.elem0.loc7_10.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_2.ecc) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_10.2: <bound method> = bound_method %int_2, %specific_fn.loc7_10.1 [concrete = constants.%bound_method.c5b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %u2 = call %bound_method.loc7_10.2(%int_2) [concrete = constants.%int_2.788]\n// CHECK:STDOUT:   %.loc7_10.1: %u2 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%int_2.788]\n// CHECK:STDOUT:   %.loc7_10.2: %u2 = converted %int_2, %.loc7_10.1 [concrete = constants.%int_2.788]\n// CHECK:STDOUT:   %.loc7_10.3: %struct_type.discriminant = struct_literal (%.loc7_10.2) [concrete = constants.%struct.6e6]\n// CHECK:STDOUT:   %impl.elem0.loc7_10.2: %.a82 = impl_witness_access constants.%Copy.impl_witness.a32, element0 [concrete = constants.%UInt.as.Copy.impl.Op.b2d]\n// CHECK:STDOUT:   %bound_method.loc7_10.3: <bound method> = bound_method %.loc7_10.2, %impl.elem0.loc7_10.2 [concrete = constants.%UInt.as.Copy.impl.Op.bound.f0c]\n// CHECK:STDOUT:   %specific_fn.loc7_10.2: <specific function> = specific_function %impl.elem0.loc7_10.2, @UInt.as.Copy.impl.Op(constants.%int_2.ecc) [concrete = constants.%UInt.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_10.4: <bound method> = bound_method %.loc7_10.2, %specific_fn.loc7_10.2 [concrete = constants.%bound_method.f1a]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.call.loc7: init %u2 = call %bound_method.loc7_10.4(%.loc7_10.2) [concrete = constants.%int_2.788]\n// CHECK:STDOUT:   %.loc7_10.4: ref %Ordering = temporary_storage\n// CHECK:STDOUT:   %.loc7_10.5: ref %u2 = class_element_access %.loc7_10.4, element0\n// CHECK:STDOUT:   %.loc7_10.6: init %u2 to %.loc7_10.5 = in_place_init %UInt.as.Copy.impl.Op.call.loc7 [concrete = constants.%int_2.788]\n// CHECK:STDOUT:   %.loc7_10.7: init %Ordering to %.loc7_10.4 = class_init (%.loc7_10.6) [concrete = constants.%Ordering.val.e86]\n// CHECK:STDOUT:   %.loc7_10.8: init %Ordering = converted %.loc7_10.3, %.loc7_10.7 [concrete = constants.%Ordering.val.e86]\n// CHECK:STDOUT:   %.loc7_10.9: ref %Ordering = temporary %.loc7_10.4, %.loc7_10.8\n// CHECK:STDOUT:   %.loc7_10.10: %Ordering = acquire_value %.loc7_10.9\n// CHECK:STDOUT:   %Greater: %Ordering = value_binding Greater, %.loc7_10.10\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %impl.elem0.loc9_1.1: %.055 = impl_witness_access constants.%ImplicitAs.impl_witness.762, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0ed]\n// CHECK:STDOUT:   %bound_method.loc9_1.1: <bound method> = bound_method %int_3, %impl.elem0.loc9_1.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.cdf]\n// CHECK:STDOUT:   %specific_fn.loc9_1.1: <specific function> = specific_function %impl.elem0.loc9_1.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_2.ecc) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_1.2: <bound method> = bound_method %int_3, %specific_fn.loc9_1.1 [concrete = constants.%bound_method.898]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9: init %u2 = call %bound_method.loc9_1.2(%int_3) [concrete = constants.%int_3.975]\n// CHECK:STDOUT:   %.loc9_1.1: %u2 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9 [concrete = constants.%int_3.975]\n// CHECK:STDOUT:   %.loc9_1.2: %u2 = converted %int_3, %.loc9_1.1 [concrete = constants.%int_3.975]\n// CHECK:STDOUT:   %.loc9_1.3: %struct_type.discriminant = struct_literal (%.loc9_1.2) [concrete = constants.%struct.7bd]\n// CHECK:STDOUT:   %impl.elem0.loc9_1.2: %.a82 = impl_witness_access constants.%Copy.impl_witness.a32, element0 [concrete = constants.%UInt.as.Copy.impl.Op.b2d]\n// CHECK:STDOUT:   %bound_method.loc9_1.3: <bound method> = bound_method %.loc9_1.2, %impl.elem0.loc9_1.2 [concrete = constants.%UInt.as.Copy.impl.Op.bound.7b5]\n// CHECK:STDOUT:   %specific_fn.loc9_1.2: <specific function> = specific_function %impl.elem0.loc9_1.2, @UInt.as.Copy.impl.Op(constants.%int_2.ecc) [concrete = constants.%UInt.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_1.4: <bound method> = bound_method %.loc9_1.2, %specific_fn.loc9_1.2 [concrete = constants.%bound_method.824]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.call.loc9: init %u2 = call %bound_method.loc9_1.4(%.loc9_1.2) [concrete = constants.%int_3.975]\n// CHECK:STDOUT:   %.loc9_1.4: ref %Ordering = temporary_storage\n// CHECK:STDOUT:   %.loc9_1.5: ref %u2 = class_element_access %.loc9_1.4, element0\n// CHECK:STDOUT:   %.loc9_1.6: init %u2 to %.loc9_1.5 = in_place_init %UInt.as.Copy.impl.Op.call.loc9 [concrete = constants.%int_3.975]\n// CHECK:STDOUT:   %.loc9_1.7: init %Ordering to %.loc9_1.4 = class_init (%.loc9_1.6) [concrete = constants.%Ordering.val.a17]\n// CHECK:STDOUT:   %.loc9_1.8: init %Ordering = converted %.loc9_1.3, %.loc9_1.7 [concrete = constants.%Ordering.val.a17]\n// CHECK:STDOUT:   %.loc9_1.9: ref %Ordering = temporary %.loc9_1.4, %.loc9_1.8\n// CHECK:STDOUT:   %.loc9_1.10: %Ordering = acquire_value %.loc9_1.9\n// CHECK:STDOUT:   %Incomparable: %Ordering = value_binding Incomparable, %.loc9_1.10\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Ordering\n// CHECK:STDOUT:   .Less = %Less\n// CHECK:STDOUT:   .Equivalent = %Equivalent\n// CHECK:STDOUT:   .Greater = %Greater\n// CHECK:STDOUT:   .Incomparable = %Incomparable\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Ordering.ref.loc11: type = name_ref Ordering, file.%Ordering.decl [concrete = constants.%Ordering]\n// CHECK:STDOUT:   %Less.ref: %Ordering = name_ref Less, @Ordering.%Less\n// CHECK:STDOUT:   %Ordering.ref.loc12: type = name_ref Ordering, file.%Ordering.decl [concrete = constants.%Ordering]\n// CHECK:STDOUT:   %Equivalent.ref: %Ordering = name_ref Equivalent, @Ordering.%Equivalent\n// CHECK:STDOUT:   %Ordering.ref.loc13: type = name_ref Ordering, file.%Ordering.decl [concrete = constants.%Ordering]\n// CHECK:STDOUT:   %Greater.ref: %Ordering = name_ref Greater, @Ordering.%Greater\n// CHECK:STDOUT:   %Ordering.ref.loc14: type = name_ref Ordering, file.%Ordering.decl [concrete = constants.%Ordering]\n// CHECK:STDOUT:   %Incomparable.ref: %Ordering = name_ref Incomparable, @Ordering.%Incomparable\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/choice/generic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/uint.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/choice/generic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/choice/generic.carbon\n\n//@dump-sem-ir-begin\nchoice Always(T:! type) {\n  Sunny\n}\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- generic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Always.type: type = generic_class_type @Always [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Always.generic: %Always.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Always: type = class_type @Always, @Always(%T) [symbolic]\n// CHECK:STDOUT:   %struct_type.discriminant: type = struct_type {.discriminant: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.discriminant [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.discriminant = struct_value (%empty_tuple) [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Always [symbolic]\n// CHECK:STDOUT:   %Always.val: %Always = struct_value (%empty_tuple) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Always.decl: %Always.type = class_decl @Always [concrete = constants.%Always.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc14_19.1: type = splice_block %.loc14_19.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc14_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc14_15.2: type = symbolic_binding T, 0 [symbolic = %T.loc14_15.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Always(%T.loc14_15.2: type) {\n// CHECK:STDOUT:   %T.loc14_15.1: type = symbolic_binding T, 0 [symbolic = %T.loc14_15.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Always: type = class_type @Always, @Always(%T.loc14_15.1) [symbolic = %Always (constants.%Always)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Always [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %Always.val: @Always.%Always (%Always) = struct_value (constants.%empty_tuple) [symbolic = %Always.val (constants.%Always.val)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.discriminant [concrete = constants.%complete_type]\n// CHECK:STDOUT:     %.loc16_1.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc16_1.2: %empty_tuple.type = converted %.loc16_1.1, %empty_tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc16_1.3: %struct_type.discriminant = struct_literal (%.loc16_1.2) [concrete = constants.%struct]\n// CHECK:STDOUT:     %.loc16_1.4: ref @Always.%Always (%Always) = temporary_storage\n// CHECK:STDOUT:     %.loc16_1.5: ref %empty_tuple.type = class_element_access %.loc16_1.4, element0\n// CHECK:STDOUT:     %.loc16_1.6: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc16_1.7: init %empty_tuple.type = converted %.loc16_1.2, %.loc16_1.6 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc16_1.8: init @Always.%Always (%Always) to %.loc16_1.4 = class_init (%.loc16_1.7) [symbolic = %Always.val (constants.%Always.val)]\n// CHECK:STDOUT:     %.loc16_1.9: init @Always.%Always (%Always) = converted %.loc16_1.3, %.loc16_1.8 [symbolic = %Always.val (constants.%Always.val)]\n// CHECK:STDOUT:     %.loc16_1.10: ref @Always.%Always (%Always) = temporary %.loc16_1.4, %.loc16_1.9\n// CHECK:STDOUT:     %.loc16_1.11: @Always.%Always (%Always) = acquire_value %.loc16_1.10\n// CHECK:STDOUT:     %Sunny: @Always.%Always (%Always) = value_binding Sunny, %.loc16_1.11\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Always\n// CHECK:STDOUT:     .Sunny = %Sunny\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Always(constants.%T) {\n// CHECK:STDOUT:   %T.loc14_15.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/choice/params.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/uint.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/choice/params.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/choice/params.carbon\n\n// --- fail_todo_empty_params.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nchoice Always {\n  // CHECK:STDERR: fail_todo_empty_params.carbon:[[@LINE+4]]:8: error: semantics TODO: `empty parameter list should make a member function` [SemanticsTodo]\n  // CHECK:STDERR:   Sunny()\n  // CHECK:STDERR:        ^~\n  // CHECK:STDERR:\n  Sunny()\n}\n\nlet mood: Always = Always.Sunny;\n\n// --- fail_todo_params.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nchoice C {\n  Alt1,\n  // CHECK:STDERR: fail_todo_params.carbon:[[@LINE+4]]:7: error: semantics TODO: `choice alternatives with parameters are not yet supported` [SemanticsTodo]\n  // CHECK:STDERR:   Alt2(a: i32, b: i64),\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Alt2(a: i32, b: i64),\n  Alt3,\n}\n\n// --- fail_todo_generic_params.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nchoice C(T:! type) {\n  // CHECK:STDERR: fail_todo_generic_params.carbon:[[@LINE+4]]:6: error: semantics TODO: `choice alternatives with parameters are not yet supported` [SemanticsTodo]\n  // CHECK:STDERR:   Alt(a: T)\n  // CHECK:STDERR:      ^~~~~~\n  // CHECK:STDERR:\n  Alt(a: T)\n}\n\n// --- fail_todo_self_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nchoice C {\n  // CHECK:STDERR: fail_todo_self_param.carbon:[[@LINE+4]]:6: error: semantics TODO: `choice alternatives with parameters are not yet supported` [SemanticsTodo]\n  // CHECK:STDERR:   Alt(a: Self*)\n  // CHECK:STDERR:      ^~~~~~~~~~\n  // CHECK:STDERR:\n  Alt(a: Self*)\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/abstract/abstract.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/abstract/abstract.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/abstract/abstract.carbon\n\n// --- fail_abstract_field.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nclass Contains {\n  // CHECK:STDERR: fail_abstract_field.carbon:[[@LINE+7]]:10: error: field has abstract type `Abstract` [AbstractTypeInFieldDecl]\n  // CHECK:STDERR:   var a: Abstract;\n  // CHECK:STDERR:          ^~~~~~~~\n  // CHECK:STDERR: fail_abstract_field.carbon:[[@LINE-7]]:1: note: class was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var a: Abstract;\n}\n\n// --- fail_abstract_var.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nfn Var() {\n  // CHECK:STDERR: fail_abstract_var.carbon:[[@LINE+7]]:17: error: binding pattern has abstract type `Abstract` in `var` pattern [AbstractTypeInVarPattern]\n  // CHECK:STDERR:   var unused v: Abstract;\n  // CHECK:STDERR:                 ^~~~~~~~\n  // CHECK:STDERR: fail_abstract_var.carbon:[[@LINE-7]]:1: note: class was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v: Abstract;\n}\n\n// --- fail_abstract_var_function_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\n// CHECK:STDERR: fail_abstract_var_function_param.carbon:[[@LINE+7]]:13: error: binding pattern has abstract type `Abstract` in `var` pattern [AbstractTypeInVarPattern]\n// CHECK:STDERR: fn F(var _: Abstract) {\n// CHECK:STDERR:             ^~~~~~~~\n// CHECK:STDERR: fail_abstract_var_function_param.carbon:[[@LINE-6]]:1: note: class was declared abstract here [ClassAbstractHere]\n// CHECK:STDERR: abstract class Abstract {\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(var _: Abstract) {\n}\n\n// --- abstract_let.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nfn F(a: Abstract) {\n  let unused l: Abstract = a;\n}\n\n// --- fail_abstract_adapter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nclass Adapter {\n  // TODO(#4387): This should probably be valid\n  // CHECK:STDERR: fail_abstract_adapter.carbon:[[@LINE+7]]:3: error: adapted type `Abstract` is an abstract type [AbstractTypeInAdaptDecl]\n  // CHECK:STDERR:   adapt Abstract;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_abstract_adapter.carbon:[[@LINE-8]]:1: note: class was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  adapt Abstract;\n}\n\n// --- define_and_call_abstract_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nfn Param(a: Abstract);\n\nfn Call(p: Abstract) {\n  Param(p);\n}\n\n// --- return_nonabstract_derived.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nclass Derived {\n  extend base: Abstract;\n\n  var d: {};\n}\n\nfn Make() -> Derived {\n  return {.base = {}, .d = {}};\n}\n\n// --- fail_return_abstract.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nclass Derived {\n  extend base: Abstract;\n\n  var d: {};\n}\n\n// CHECK:STDERR: fail_return_abstract.carbon:[[@LINE+7]]:27: error: function returns abstract type `Abstract` [AbstractTypeInFunctionReturnType]\n// CHECK:STDERR: fn Return(a: Abstract) -> Abstract {\n// CHECK:STDERR:                           ^~~~~~~~\n// CHECK:STDERR: fail_return_abstract.carbon:[[@LINE-12]]:1: note: class was declared abstract here [ClassAbstractHere]\n// CHECK:STDERR: abstract class Abstract {\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Return(a: Abstract) -> Abstract {\n  return a;\n}\n\n// --- fail_todo_access_abstract_subobject.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n  var a: {};\n}\n\nclass Derived {\n  extend base: Abstract;\n\n  var d: {};\n}\n\nfn Access(d: Derived) -> {} {\n  // CHECK:STDERR: fail_todo_access_abstract_subobject.carbon:[[@LINE+7]]:10: error: initialization of abstract type `Abstract` [AbstractTypeInInit]\n  // CHECK:STDERR:   return d.base.a;\n  // CHECK:STDERR:          ^~~~~~\n  // CHECK:STDERR: fail_todo_access_abstract_subobject.carbon:[[@LINE-14]]:1: note: class was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return d.base.a;\n}\n\n// --- fail_abstract_let_temporary_struct_literal.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nfn F() {\n  // CHECK:STDERR: fail_abstract_let_temporary_struct_literal.carbon:[[@LINE+7]]:28: error: initialization of abstract type `Abstract` [AbstractTypeInInit]\n  // CHECK:STDERR:   let unused l: Abstract = {};\n  // CHECK:STDERR:                            ^~\n  // CHECK:STDERR: fail_abstract_let_temporary_struct_literal.carbon:[[@LINE-7]]:1: note: class was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused l: Abstract = {};\n}\n\n// --- fail_todo_abstract_let_temporary.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nclass Derived {\n  extend base: Abstract;\n}\n\nfn F() {\n  // TODO: We should be able to construct a temporary `Derived`, and assign it\n  // to the `Abstract` value since `Abstract` and `Derived` have pointer value\n  // representations.\n  //\n  // CHECK:STDERR: fail_todo_abstract_let_temporary.carbon:[[@LINE+7]]:28: error: initialization of abstract type `Abstract` [AbstractTypeInInit]\n  // CHECK:STDERR:   let unused l: Abstract = {.base = {}} as Derived;\n  // CHECK:STDERR:                            ^~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_abstract_let_temporary.carbon:[[@LINE-15]]:1: note: class was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused l: Abstract = {.base = {}} as Derived;\n}\n\n// --- fail_call_abstract_return.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {\n}\n\nfn ReturnAbstract() -> Abstract;\n\nfn CallReturnAbstract() {\n  // CHECK:STDERR: fail_call_abstract_return.carbon:[[@LINE+10]]:3: error: function returns abstract type `Abstract` [AbstractTypeInFunctionReturnType]\n  // CHECK:STDERR:   ReturnAbstract();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_call_abstract_return.carbon:[[@LINE-9]]:1: note: class was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_call_abstract_return.carbon:[[@LINE-9]]:24: note: return type declared here [IncompleteReturnTypeHere]\n  // CHECK:STDERR: fn ReturnAbstract() -> Abstract;\n  // CHECK:STDERR:                        ^~~~~~~~\n  // CHECK:STDERR:\n  ReturnAbstract();\n}\n\n// CHECK:STDOUT: --- fail_abstract_field.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Contains: type = class_type @Contains [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .Contains = %Contains.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %Contains.decl: type = class_decl @Contains [concrete = constants.%Contains] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Contains {\n// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %.loc14: <error> = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [concrete = <error>]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Contains\n// CHECK:STDOUT:   .Abstract = <poisoned>\n// CHECK:STDOUT:   .a = %.loc14\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_var.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Var.type: type = fn_type @Var [concrete]\n// CHECK:STDOUT:   %Var: %Var.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .Var = %Var.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %Var.decl: %Var.type = fn_decl @Var [concrete = constants.%Var] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Var() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: <error> = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: <error> = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref <error> = var %v.var_patt [concrete = <error>]\n// CHECK:STDOUT:   assign %v.var, <error>\n// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %v: ref <error> = ref_binding v, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_var_function_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %_.patt: <error> = ref_binding_pattern _ [concrete]\n// CHECK:STDOUT:     %_.param_patt: <error> = var_param_pattern %_.patt [concrete]\n// CHECK:STDOUT:     %_.var_patt: <error> = var_pattern %_.param_patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %_.param: ref <error> = ref_param call_param0\n// CHECK:STDOUT:     %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %_: ref <error> = ref_binding _, %_.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%_.param: ref <error>) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- abstract_let.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Abstract [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %Abstract = value_param call_param0\n// CHECK:STDOUT:     %Abstract.ref.loc6: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %a: %Abstract = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %Abstract) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %l.patt: %pattern_type = value_binding_pattern l [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.ref: %Abstract = name_ref a, %a\n// CHECK:STDOUT:   %Abstract.ref.loc7: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %l: %Abstract = value_binding l, %a.ref\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_adapter.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Adapter: type = class_type @Adapter [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .Adapter = %Adapter.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %Adapter.decl: type = class_decl @Adapter [concrete = constants.%Adapter] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Adapter {\n// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   adapt_decl <error> [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [concrete = <error>]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Adapter\n// CHECK:STDOUT:   .Abstract = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- define_and_call_abstract_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Abstract [concrete]\n// CHECK:STDOUT:   %Param.type: type = fn_type @Param [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Param: %Param.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Call.type: type = fn_type @Call [concrete]\n// CHECK:STDOUT:   %Call: %Call.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .Param = %Param.decl\n// CHECK:STDOUT:     .Call = %Call.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %Param.decl: %Param.type = fn_decl @Param [concrete = constants.%Param] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %Abstract = value_param call_param0\n// CHECK:STDOUT:     %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %a: %Abstract = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Call.decl: %Call.type = fn_decl @Call [concrete = constants.%Call] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %Abstract = value_param call_param0\n// CHECK:STDOUT:     %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %p: %Abstract = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Param(%a.param: %Abstract);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%p.param: %Abstract) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Param.ref: %Param.type = name_ref Param, file.%Param.decl [concrete = constants.%Param]\n// CHECK:STDOUT:   %p.ref: %Abstract = name_ref p, %p\n// CHECK:STDOUT:   %Param.call: init %empty_tuple.type = call %Param.ref(%p.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- return_nonabstract_derived.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem.032: type = unbound_element_type %Derived, %Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct.a40: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.elem.87e: type = unbound_element_type %Derived, %empty_struct_type [concrete]\n// CHECK:STDOUT:   %struct_type.base.d.be5: type = struct_type {.base: %Abstract, .d: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %complete_type.840: <witness> = complete_type_witness %struct_type.base.d.be5 [concrete]\n// CHECK:STDOUT:   %.d9b: Core.Form = init_form %Derived [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.d.e0f: type = struct_type {.base: %empty_struct_type, .d: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.base.d.e0f = struct_value (%empty_struct.a40, %empty_struct.a40) [concrete]\n// CHECK:STDOUT:   %.ec6: type = partial_type %Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct.8eb: %.ec6 = struct_value () [concrete]\n// CHECK:STDOUT:   %Abstract.val: %Abstract = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.val: %Derived = struct_value (%Abstract.val, %empty_struct.a40) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .Make = %Make.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Make.decl: %Make.type = fn_decl @Make [concrete = constants.%Make] {\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:     %.loc12: Core.Form = init_form %Derived.ref [concrete = constants.%.d9b]\n// CHECK:STDOUT:     %return.param: ref %Derived = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Derived = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %.loc7: %Derived.elem.032 = base_decl %Abstract.ref, element0 [concrete]\n// CHECK:STDOUT:   %.loc9_11.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct.a40]\n// CHECK:STDOUT:   %.loc9_11.2: type = converted %.loc9_11.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %.loc9_8: %Derived.elem.87e = field_decl d, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.d.be5 [concrete = constants.%complete_type.840]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Abstract = <poisoned>\n// CHECK:STDOUT:   .base = %.loc7\n// CHECK:STDOUT:   .d = %.loc9_8\n// CHECK:STDOUT:   extend %Abstract.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Make() -> out %return.param: %Derived {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc13_20.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct.a40]\n// CHECK:STDOUT:   %.loc13_29.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct.a40]\n// CHECK:STDOUT:   %.loc13_30.1: %struct_type.base.d.e0f = struct_literal (%.loc13_20.1, %.loc13_29.1) [concrete = constants.%struct]\n// CHECK:STDOUT:   %.loc13_30.2: ref %.ec6 = class_element_access %return.param, element0\n// CHECK:STDOUT:   %.loc13_20.2: init %.ec6 to %.loc13_30.2 = class_init () [concrete = constants.%empty_struct.8eb]\n// CHECK:STDOUT:   %.loc13_30.3: init %.ec6 = converted %.loc13_20.1, %.loc13_20.2 [concrete = constants.%empty_struct.8eb]\n// CHECK:STDOUT:   %.loc13_30.4: init %Abstract = as_compatible %.loc13_30.3 [concrete = constants.%Abstract.val]\n// CHECK:STDOUT:   %.loc13_30.5: ref %empty_struct_type = class_element_access %return.param, element1\n// CHECK:STDOUT:   %.loc13_29.2: init %empty_struct_type = struct_init () [concrete = constants.%empty_struct.a40]\n// CHECK:STDOUT:   %.loc13_30.6: init %empty_struct_type = converted %.loc13_29.1, %.loc13_29.2 [concrete = constants.%empty_struct.a40]\n// CHECK:STDOUT:   %.loc13_30.7: init %Derived to %return.param = class_init (%.loc13_30.4, %.loc13_30.6) [concrete = constants.%Derived.val]\n// CHECK:STDOUT:   %.loc13_31: init %Derived = converted %.loc13_30.1, %.loc13_30.7 [concrete = constants.%Derived.val]\n// CHECK:STDOUT:   return %.loc13_31 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_return_abstract.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem.032: type = unbound_element_type %Derived, %Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.elem.87e: type = unbound_element_type %Derived, %empty_struct_type [concrete]\n// CHECK:STDOUT:   %struct_type.base.d: type = struct_type {.base: %Abstract, .d: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %complete_type.840: <witness> = complete_type_witness %struct_type.base.d [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Abstract [concrete]\n// CHECK:STDOUT:   %.7d7: Core.Form = init_form %Abstract [concrete]\n// CHECK:STDOUT:   %Return.type: type = fn_type @Return [concrete]\n// CHECK:STDOUT:   %Return: %Return.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .Return = %Return.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Return.decl: %Return.type = fn_decl @Return [concrete = constants.%Return] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Abstract.ref.loc19_27: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %.loc19: Core.Form = init_form %Abstract.ref.loc19_27 [concrete = constants.%.7d7]\n// CHECK:STDOUT:     %a.param: %Abstract = value_param call_param0\n// CHECK:STDOUT:     %Abstract.ref.loc19_14: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %a: %Abstract = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %Abstract = out_param call_param1\n// CHECK:STDOUT:     %return: ref %Abstract = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %.loc7: %Derived.elem.032 = base_decl %Abstract.ref, element0 [concrete]\n// CHECK:STDOUT:   %.loc9_11.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_11.2: type = converted %.loc9_11.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %.loc9_8: %Derived.elem.87e = field_decl d, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.d [concrete = constants.%complete_type.840]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Abstract = <poisoned>\n// CHECK:STDOUT:   .base = %.loc7\n// CHECK:STDOUT:   .d = %.loc9_8\n// CHECK:STDOUT:   extend %Abstract.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Return(%a.param: %Abstract) -> out %return.param: %Abstract {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Abstract = name_ref a, %a\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_access_abstract_subobject.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Abstract.elem: type = unbound_element_type %Abstract, %empty_struct_type [concrete]\n// CHECK:STDOUT:   %struct_type.a.225: type = struct_type {.a: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %complete_type.8c6: <witness> = complete_type_witness %struct_type.a.225 [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem.032: type = unbound_element_type %Derived, %Abstract [concrete]\n// CHECK:STDOUT:   %Derived.elem.87e: type = unbound_element_type %Derived, %empty_struct_type [concrete]\n// CHECK:STDOUT:   %struct_type.base.d.be5: type = struct_type {.base: %Abstract, .d: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %complete_type.840: <witness> = complete_type_witness %struct_type.base.d.be5 [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %.469: Core.Form = init_form %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.a96: type = pattern_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Access.type: type = fn_type @Access [concrete]\n// CHECK:STDOUT:   %Access: %Access.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .Access = %Access.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Access.decl: %Access.type = fn_decl @Access [concrete = constants.%Access] {\n// CHECK:STDOUT:     %d.patt: %pattern_type.9f6 = value_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.param_patt: %pattern_type.9f6 = value_param_pattern %d.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.a96 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.a96 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc13_27.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc13_27.2: type = converted %.loc13_27.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %.loc13_27.3: Core.Form = init_form %.loc13_27.2 [concrete = constants.%.469]\n// CHECK:STDOUT:     %d.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:     %d: %Derived = value_binding d, %d.param\n// CHECK:STDOUT:     %return.param: ref %empty_struct_type = out_param call_param1\n// CHECK:STDOUT:     %return: ref %empty_struct_type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %.loc4_11.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc4_11.2: type = converted %.loc4_11.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %.loc4_8: %Abstract.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.225 [concrete = constants.%complete_type.8c6]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT:   .a = %.loc4_8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %.loc8: %Derived.elem.032 = base_decl %Abstract.ref, element0 [concrete]\n// CHECK:STDOUT:   %.loc10_11.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc10_11.2: type = converted %.loc10_11.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %.loc10_8: %Derived.elem.87e = field_decl d, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.d.be5 [concrete = constants.%complete_type.840]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Abstract = <poisoned>\n// CHECK:STDOUT:   .base = %.loc8\n// CHECK:STDOUT:   .d = %.loc10_8\n// CHECK:STDOUT:   extend %Abstract.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Access(%d.param: %Derived) -> out %return.param: %empty_struct_type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %d.ref: %Derived = name_ref d, %d\n// CHECK:STDOUT:   %base.ref: %Derived.elem.032 = name_ref base, @Derived.%.loc8 [concrete = @Derived.%.loc8]\n// CHECK:STDOUT:   %.loc21: ref %Abstract = class_element_access %d.ref, element0\n// CHECK:STDOUT:   %a.ref: <error> = name_ref a, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_let_temporary_struct_literal.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %l.patt: %pattern_type = value_binding_pattern l [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc14: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %l: %Abstract = value_binding l, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_abstract_let_temporary.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Abstract [concrete]\n// CHECK:STDOUT:   %struct_type.base.709: type = struct_type {.base: %Abstract} [concrete]\n// CHECK:STDOUT:   %complete_type.907: <witness> = complete_type_witness %struct_type.base.709 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct.a40: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.f5e: type = struct_type {.base: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.base.f5e = struct_value (%empty_struct.a40) [concrete]\n// CHECK:STDOUT:   %.ec6: type = partial_type %Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct.8eb: %.ec6 = struct_value () [concrete]\n// CHECK:STDOUT:   %Abstract.val: %Abstract = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.val: %Derived = struct_value (%Abstract.val) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %.loc7: %Derived.elem = base_decl %Abstract.ref, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.709 [concrete = constants.%complete_type.907]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Abstract = <poisoned>\n// CHECK:STDOUT:   .base = %.loc7\n// CHECK:STDOUT:   extend %Abstract.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %l.patt: %pattern_type = value_binding_pattern l [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc22_38.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct.a40]\n// CHECK:STDOUT:   %.loc22_39.1: %struct_type.base.f5e = struct_literal (%.loc22_38.1) [concrete = constants.%struct]\n// CHECK:STDOUT:   %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:   %.loc22_39.2: ref %Derived = temporary_storage\n// CHECK:STDOUT:   %.loc22_39.3: ref %.ec6 = class_element_access %.loc22_39.2, element0\n// CHECK:STDOUT:   %.loc22_38.2: init %.ec6 to %.loc22_39.3 = class_init () [concrete = constants.%empty_struct.8eb]\n// CHECK:STDOUT:   %.loc22_39.4: init %.ec6 = converted %.loc22_38.1, %.loc22_38.2 [concrete = constants.%empty_struct.8eb]\n// CHECK:STDOUT:   %.loc22_39.5: init %Abstract = as_compatible %.loc22_39.4 [concrete = constants.%Abstract.val]\n// CHECK:STDOUT:   %.loc22_39.6: init %Derived to %.loc22_39.2 = class_init (%.loc22_39.5) [concrete = constants.%Derived.val]\n// CHECK:STDOUT:   %.loc22_41: init %Derived = converted %.loc22_39.1, %.loc22_39.6 [concrete = constants.%Derived.val]\n// CHECK:STDOUT:   %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %l: %Abstract = value_binding l, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_call_abstract_return.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.7d7: Core.Form = init_form %Abstract [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Abstract [concrete]\n// CHECK:STDOUT:   %ReturnAbstract.type: type = fn_type @ReturnAbstract [concrete]\n// CHECK:STDOUT:   %ReturnAbstract: %ReturnAbstract.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallReturnAbstract.type: type = fn_type @CallReturnAbstract [concrete]\n// CHECK:STDOUT:   %CallReturnAbstract: %CallReturnAbstract.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:     .ReturnAbstract = %ReturnAbstract.decl\n// CHECK:STDOUT:     .CallReturnAbstract = %CallReturnAbstract.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT:   %ReturnAbstract.decl: %ReturnAbstract.type = fn_decl @ReturnAbstract [concrete = constants.%ReturnAbstract] {\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Abstract.ref: type = name_ref Abstract, file.%Abstract.decl [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %.loc6: Core.Form = init_form %Abstract.ref [concrete = constants.%.7d7]\n// CHECK:STDOUT:     %return.param: ref %Abstract = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Abstract = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallReturnAbstract.decl: %CallReturnAbstract.type = fn_decl @CallReturnAbstract [concrete = constants.%CallReturnAbstract] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ReturnAbstract() -> out %return.param: %Abstract;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallReturnAbstract() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ReturnAbstract.ref: %ReturnAbstract.type = name_ref ReturnAbstract, file.%ReturnAbstract.decl [concrete = constants.%ReturnAbstract]\n// CHECK:STDOUT:   %ReturnAbstract.call: init <error> = call %ReturnAbstract.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/abstract/fail_abstract_in_struct.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/abstract/fail_abstract_in_struct.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/abstract/fail_abstract_in_struct.carbon\n\n// --- fail_abstract_field.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract1 {}\n\nclass Contains {\n  // CHECK:STDERR: fail_abstract_field.carbon:[[@LINE+7]]:10: error: field has abstract type `{.m1: Abstract1}` [AbstractTypeInFieldDecl]\n  // CHECK:STDERR:   var a: {.m1: Abstract1};\n  // CHECK:STDERR:          ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_abstract_field.carbon:[[@LINE-6]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract1 {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var a: {.m1: Abstract1};\n}\n\n// --- fail_abstract_var.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract2 {}\n\n// CHECK:STDERR: fail_abstract_var.carbon:[[@LINE+7]]:8: error: binding pattern has abstract type `{.m2: Abstract2}` in `var` pattern [AbstractTypeInVarPattern]\n// CHECK:STDERR: var v: {.m2: Abstract2};\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_abstract_var.carbon:[[@LINE-5]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n// CHECK:STDERR: abstract class Abstract2 {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar v: {.m2: Abstract2};\n\n// --- fail_todo_abstract_let.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract3 {\n}\n\nfn F(a: Abstract3) {\n  // CHECK:STDERR: fail_todo_abstract_let.carbon:[[@LINE+7]]:36: error: initialization of abstract type `{.m3: Abstract3}` [AbstractTypeInInit]\n  // CHECK:STDERR:   let unused l: {.m3: Abstract3} = {.m3 = a};\n  // CHECK:STDERR:                                    ^~~~~~~~~\n  // CHECK:STDERR: fail_todo_abstract_let.carbon:[[@LINE-7]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract3 {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused l: {.m3: Abstract3} = {.m3 = a};\n}\n\n// --- fail_abstract_twice.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract4 {}\nabstract class Abstract5 {}\n\n// CHECK:STDERR: fail_abstract_twice.carbon:[[@LINE+7]]:9: error: binding pattern has abstract type `{.m4: Abstract4, .m5: Abstract5}` in `var` pattern [AbstractTypeInVarPattern]\n// CHECK:STDERR: var v2: {.m4: Abstract4, .m5: Abstract5};\n// CHECK:STDERR:         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_abstract_twice.carbon:[[@LINE-6]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n// CHECK:STDERR: abstract class Abstract4 {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar v2: {.m4: Abstract4, .m5: Abstract5};\n\n// --- fail_abstract_first.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract6 {}\n\n// CHECK:STDERR: fail_abstract_first.carbon:[[@LINE+7]]:9: error: binding pattern has abstract type `{.m6: Abstract6, .c1: ()}` in `var` pattern [AbstractTypeInVarPattern]\n// CHECK:STDERR: var v3: {.m6: Abstract6, .c1: ()};\n// CHECK:STDERR:         ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_abstract_first.carbon:[[@LINE-5]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n// CHECK:STDERR: abstract class Abstract6 {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar v3: {.m6: Abstract6, .c1: ()};\n\n// --- fail_abstract_second.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract7 {}\n\n// CHECK:STDERR: fail_abstract_second.carbon:[[@LINE+7]]:9: error: binding pattern has abstract type `{.c2: (), .m7: Abstract7}` in `var` pattern [AbstractTypeInVarPattern]\n// CHECK:STDERR: var v4: {.c2: (), .m7: Abstract7};\n// CHECK:STDERR:         ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_abstract_second.carbon:[[@LINE-5]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n// CHECK:STDERR: abstract class Abstract7 {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar v4: {.c2: (), .m7: Abstract7};\n\n// --- lib.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {}\n\n// --- fail_import.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"lib\";\n\n// CHECK:STDERR: fail_import.carbon:[[@LINE+8]]:9: error: binding pattern has abstract type `{.m: Abstract}` in `var` pattern [AbstractTypeInVarPattern]\n// CHECK:STDERR: var v5: {.m: Abstract};\n// CHECK:STDERR:         ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_import.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: lib.carbon:3:1: note: uses class that was declared abstract here [ClassAbstractHere]\n// CHECK:STDERR: abstract class Abstract {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar v5: {.m: Abstract};\n\n// CHECK:STDOUT: --- fail_abstract_field.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract1: type = class_type @Abstract1 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Contains: type = class_type @Contains [concrete]\n// CHECK:STDOUT:   %struct_type.m1.ea7: type = struct_type {.m1: %Abstract1} [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Abstract1 = %Abstract1.decl\n// CHECK:STDOUT:     .Contains = %Contains.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Abstract1.decl: type = class_decl @Abstract1 [concrete = constants.%Abstract1] {} {}\n// CHECK:STDOUT:   %Contains.decl: type = class_decl @Contains [concrete = constants.%Contains] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract1 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Contains {\n// CHECK:STDOUT:   %Abstract1.ref: type = name_ref Abstract1, file.%Abstract1.decl [concrete = constants.%Abstract1]\n// CHECK:STDOUT:   %struct_type.m1: type = struct_type {.m1: %Abstract1} [concrete = constants.%struct_type.m1.ea7]\n// CHECK:STDOUT:   %.loc13: <error> = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [concrete = <error>]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Contains\n// CHECK:STDOUT:   .Abstract1 = <poisoned>\n// CHECK:STDOUT:   .a = %.loc13\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_var.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract2: type = class_type @Abstract2 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %struct_type.m2.779: type = struct_type {.m2: %Abstract2} [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Abstract2 = %Abstract2.decl\n// CHECK:STDOUT:     .v = %v\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Abstract2.decl: type = class_decl @Abstract2 [concrete = constants.%Abstract2] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: <error> = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: <error> = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref <error> = var %v.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.loc12: type = splice_block %struct_type.m2 [concrete = constants.%struct_type.m2.779] {\n// CHECK:STDOUT:     %Abstract2.ref: type = name_ref Abstract2, %Abstract2.decl [concrete = constants.%Abstract2]\n// CHECK:STDOUT:     %struct_type.m2: type = struct_type {.m2: %Abstract2} [concrete = constants.%struct_type.m2.779]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref <error> = ref_binding v, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract2 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   assign file.%v.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_abstract_let.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract3: type = class_type @Abstract3 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7de: type = pattern_type %Abstract3 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.m3.b1b: type = struct_type {.m3: %Abstract3} [concrete]\n// CHECK:STDOUT:   %pattern_type.816: type = pattern_type %struct_type.m3.b1b [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Abstract3 = %Abstract3.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Abstract3.decl: type = class_decl @Abstract3 [concrete = constants.%Abstract3] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7de = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7de = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %Abstract3 = value_param call_param0\n// CHECK:STDOUT:     %Abstract3.ref.loc6: type = name_ref Abstract3, file.%Abstract3.decl [concrete = constants.%Abstract3]\n// CHECK:STDOUT:     %a: %Abstract3 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract3 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %Abstract3) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %l.patt: %pattern_type.816 = value_binding_pattern l [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.ref: %Abstract3 = name_ref a, %a\n// CHECK:STDOUT:   %.loc14_44: %struct_type.m3.b1b = struct_literal (%a.ref)\n// CHECK:STDOUT:   %.loc14_32: type = splice_block %struct_type.m3 [concrete = constants.%struct_type.m3.b1b] {\n// CHECK:STDOUT:     %Abstract3.ref.loc14: type = name_ref Abstract3, file.%Abstract3.decl [concrete = constants.%Abstract3]\n// CHECK:STDOUT:     %struct_type.m3: type = struct_type {.m3: %Abstract3} [concrete = constants.%struct_type.m3.b1b]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %l: %struct_type.m3.b1b = value_binding l, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_twice.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract4: type = class_type @Abstract4 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Abstract5: type = class_type @Abstract5 [concrete]\n// CHECK:STDOUT:   %struct_type.m4.m5.2d0: type = struct_type {.m4: %Abstract4, .m5: %Abstract5} [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Abstract4 = %Abstract4.decl\n// CHECK:STDOUT:     .Abstract5 = %Abstract5.decl\n// CHECK:STDOUT:     .v2 = %v2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Abstract4.decl: type = class_decl @Abstract4 [concrete = constants.%Abstract4] {} {}\n// CHECK:STDOUT:   %Abstract5.decl: type = class_decl @Abstract5 [concrete = constants.%Abstract5] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v2.patt: <error> = ref_binding_pattern v2 [concrete]\n// CHECK:STDOUT:     %v2.var_patt: <error> = var_pattern %v2.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v2.var: ref <error> = var %v2.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.loc13: type = splice_block %struct_type.m4.m5 [concrete = constants.%struct_type.m4.m5.2d0] {\n// CHECK:STDOUT:     %Abstract4.ref: type = name_ref Abstract4, %Abstract4.decl [concrete = constants.%Abstract4]\n// CHECK:STDOUT:     %Abstract5.ref: type = name_ref Abstract5, %Abstract5.decl [concrete = constants.%Abstract5]\n// CHECK:STDOUT:     %struct_type.m4.m5: type = struct_type {.m4: %Abstract4, .m5: %Abstract5} [concrete = constants.%struct_type.m4.m5.2d0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v2: ref <error> = ref_binding v2, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract4 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract5 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   assign file.%v2.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_first.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract6: type = class_type @Abstract6 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct_type.m6.c1.69b: type = struct_type {.m6: %Abstract6, .c1: %empty_tuple.type} [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Abstract6 = %Abstract6.decl\n// CHECK:STDOUT:     .v3 = %v3\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Abstract6.decl: type = class_decl @Abstract6 [concrete = constants.%Abstract6] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v3.patt: <error> = ref_binding_pattern v3 [concrete]\n// CHECK:STDOUT:     %v3.var_patt: <error> = var_pattern %v3.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v3.var: ref <error> = var %v3.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.loc12_33: type = splice_block %struct_type.m6.c1 [concrete = constants.%struct_type.m6.c1.69b] {\n// CHECK:STDOUT:     %Abstract6.ref: type = name_ref Abstract6, %Abstract6.decl [concrete = constants.%Abstract6]\n// CHECK:STDOUT:     %.loc12_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc12_32.2: type = converted %.loc12_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %struct_type.m6.c1: type = struct_type {.m6: %Abstract6, .c1: %empty_tuple.type} [concrete = constants.%struct_type.m6.c1.69b]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v3: ref <error> = ref_binding v3, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract6 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   assign file.%v3.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_second.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract7: type = class_type @Abstract7 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct_type.c2.m7.e94: type = struct_type {.c2: %empty_tuple.type, .m7: %Abstract7} [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Abstract7 = %Abstract7.decl\n// CHECK:STDOUT:     .v4 = %v4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Abstract7.decl: type = class_decl @Abstract7 [concrete = constants.%Abstract7] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v4.patt: <error> = ref_binding_pattern v4 [concrete]\n// CHECK:STDOUT:     %v4.var_patt: <error> = var_pattern %v4.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v4.var: ref <error> = var %v4.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.loc12_33: type = splice_block %struct_type.c2.m7 [concrete = constants.%struct_type.c2.m7.e94] {\n// CHECK:STDOUT:     %.loc12_16.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc12_16.2: type = converted %.loc12_16.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %Abstract7.ref: type = name_ref Abstract7, %Abstract7.decl [concrete = constants.%Abstract7]\n// CHECK:STDOUT:     %struct_type.c2.m7: type = struct_type {.c2: %empty_tuple.type, .m7: %Abstract7} [concrete = constants.%struct_type.c2.m7.e94]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v4: ref <error> = ref_binding v4, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract7 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   assign file.%v4.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- lib.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_import.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %struct_type.m.9e8: type = struct_type {.m: %Abstract} [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Abstract: type = import_ref Main//lib, Abstract, loaded [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//lib, loc3_26, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.141 = import_ref Main//lib, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Abstract = imports.%Main.Abstract\n// CHECK:STDOUT:     .v5 = %v5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v5.patt: <error> = ref_binding_pattern v5 [concrete]\n// CHECK:STDOUT:     %v5.var_patt: <error> = var_pattern %v5.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v5.var: ref <error> = var %v5.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.loc13: type = splice_block %struct_type.m [concrete = constants.%struct_type.m.9e8] {\n// CHECK:STDOUT:     %Abstract.ref: type = name_ref Abstract, imports.%Main.Abstract [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %struct_type.m: type = struct_type {.m: %Abstract} [concrete = constants.%struct_type.m.9e8]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v5: ref <error> = ref_binding v5, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract [from \"lib.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.141\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   assign file.%v5.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/abstract/fail_abstract_in_tuple.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/abstract/fail_abstract_in_tuple.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/abstract/fail_abstract_in_tuple.carbon\n\n// --- fail_abstract_field.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract1 {}\n\nclass Contains {\n  // CHECK:STDERR: fail_abstract_field.carbon:[[@LINE+7]]:10: error: field has abstract type `(Abstract1,)` [AbstractTypeInFieldDecl]\n  // CHECK:STDERR:   var a: (Abstract1,);\n  // CHECK:STDERR:          ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_abstract_field.carbon:[[@LINE-6]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract1 {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var a: (Abstract1,);\n}\n\n// --- fail_abstract_var.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract2 {}\n\nfn Var() {\n  // CHECK:STDERR: fail_abstract_var.carbon:[[@LINE+7]]:17: error: binding pattern has abstract type `(Abstract2,)` in `var` pattern [AbstractTypeInVarPattern]\n  // CHECK:STDERR:   var unused v: (Abstract2,);\n  // CHECK:STDERR:                 ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_abstract_var.carbon:[[@LINE-6]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract2 {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v: (Abstract2,);\n}\n\n// --- fail_todo_abstract_let.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract3 {\n}\n\nfn F(a: Abstract3) {\n  // CHECK:STDERR: fail_todo_abstract_let.carbon:[[@LINE+7]]:32: error: initialization of abstract type `(Abstract3,)` [AbstractTypeInInit]\n  // CHECK:STDERR:   let unused l: (Abstract3,) = (a,);\n  // CHECK:STDERR:                                ^~~~\n  // CHECK:STDERR: fail_todo_abstract_let.carbon:[[@LINE-7]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract3 {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused l: (Abstract3,) = (a,);\n}\n\n// --- fail_abstract_twice.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract4 {}\nabstract class Abstract5 {}\n\nfn Var2() {\n  // CHECK:STDERR: fail_abstract_twice.carbon:[[@LINE+7]]:18: error: binding pattern has abstract type `(Abstract4, Abstract5)` in `var` pattern [AbstractTypeInVarPattern]\n  // CHECK:STDERR:   var unused v2: (Abstract4, Abstract5);\n  // CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_abstract_twice.carbon:[[@LINE-7]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract4 {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v2: (Abstract4, Abstract5);\n}\n\n// --- fail_abstract_first.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract6 {}\n\nfn Var3() {\n  // CHECK:STDERR: fail_abstract_first.carbon:[[@LINE+7]]:18: error: binding pattern has abstract type `(Abstract6, {})` in `var` pattern [AbstractTypeInVarPattern]\n  // CHECK:STDERR:   var unused v3: (Abstract6, {});\n  // CHECK:STDERR:                  ^~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_abstract_first.carbon:[[@LINE-6]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract6 {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v3: (Abstract6, {});\n}\n\n// --- fail_abstract_second.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract7 {}\n\nfn Var4() {\n  // CHECK:STDERR: fail_abstract_second.carbon:[[@LINE+7]]:18: error: binding pattern has abstract type `({}, Abstract7)` in `var` pattern [AbstractTypeInVarPattern]\n  // CHECK:STDERR:   var unused v4: ({}, Abstract7);\n  // CHECK:STDERR:                  ^~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_abstract_second.carbon:[[@LINE-6]]:1: note: uses class that was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract7 {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v4: ({}, Abstract7);\n}\n\n// --- lib.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Abstract {}\n\n// --- fail_import.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"lib\";\n\nfn Var5() {\n  // CHECK:STDERR: fail_import.carbon:[[@LINE+8]]:18: error: binding pattern has abstract type `(Abstract,)` in `var` pattern [AbstractTypeInVarPattern]\n  // CHECK:STDERR:   var unused v5: (Abstract,);\n  // CHECK:STDERR:                  ^~~~~~~~~~~\n  // CHECK:STDERR: fail_import.carbon:[[@LINE-6]]:1: in import [InImport]\n  // CHECK:STDERR: lib.carbon:3:1: note: uses class that was declared abstract here [ClassAbstractHere]\n  // CHECK:STDERR: abstract class Abstract {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v5: (Abstract,);\n}\n\n// CHECK:STDOUT: --- fail_abstract_field.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract1: type = class_type @Abstract1 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Contains: type = class_type @Contains [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.85c = tuple_value (%Abstract1) [concrete]\n// CHECK:STDOUT:   %tuple.type.453: type = tuple_type (%Abstract1) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract1 = %Abstract1.decl\n// CHECK:STDOUT:     .Contains = %Contains.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract1.decl: type = class_decl @Abstract1 [concrete = constants.%Abstract1] {} {}\n// CHECK:STDOUT:   %Contains.decl: type = class_decl @Contains [concrete = constants.%Contains] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract1 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Contains {\n// CHECK:STDOUT:   %Abstract1.ref: type = name_ref Abstract1, file.%Abstract1.decl [concrete = constants.%Abstract1]\n// CHECK:STDOUT:   %.loc13_21.1: %tuple.type.85c = tuple_literal (%Abstract1.ref) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %.loc13_21.2: type = converted %.loc13_21.1, constants.%tuple.type.453 [concrete = constants.%tuple.type.453]\n// CHECK:STDOUT:   %.loc13_8: <error> = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness <error> [concrete = <error>]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Contains\n// CHECK:STDOUT:   .Abstract1 = <poisoned>\n// CHECK:STDOUT:   .a = %.loc13_8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_var.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract2: type = class_type @Abstract2 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Var.type: type = fn_type @Var [concrete]\n// CHECK:STDOUT:   %Var: %Var.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.85c = tuple_value (%Abstract2) [concrete]\n// CHECK:STDOUT:   %tuple.type.d46: type = tuple_type (%Abstract2) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract2 = %Abstract2.decl\n// CHECK:STDOUT:     .Var = %Var.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract2.decl: type = class_decl @Abstract2 [concrete = constants.%Abstract2] {} {}\n// CHECK:STDOUT:   %Var.decl: %Var.type = fn_decl @Var [concrete = constants.%Var] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract2 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Var() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: <error> = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: <error> = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref <error> = var %v.var_patt [concrete = <error>]\n// CHECK:STDOUT:   assign %v.var, <error>\n// CHECK:STDOUT:   %.loc13_28.1: type = splice_block %.loc13_28.3 [concrete = constants.%tuple.type.d46] {\n// CHECK:STDOUT:     %Abstract2.ref: type = name_ref Abstract2, file.%Abstract2.decl [concrete = constants.%Abstract2]\n// CHECK:STDOUT:     %.loc13_28.2: %tuple.type.85c = tuple_literal (%Abstract2.ref) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc13_28.3: type = converted %.loc13_28.2, constants.%tuple.type.d46 [concrete = constants.%tuple.type.d46]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref <error> = ref_binding v, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_abstract_let.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract3: type = class_type @Abstract3 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7de: type = pattern_type %Abstract3 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.85c = tuple_value (%Abstract3) [concrete]\n// CHECK:STDOUT:   %tuple.type.c99: type = tuple_type (%Abstract3) [concrete]\n// CHECK:STDOUT:   %pattern_type.016: type = pattern_type %tuple.type.c99 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract3 = %Abstract3.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract3.decl: type = class_decl @Abstract3 [concrete = constants.%Abstract3] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7de = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7de = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %Abstract3 = value_param call_param0\n// CHECK:STDOUT:     %Abstract3.ref.loc6: type = name_ref Abstract3, file.%Abstract3.decl [concrete = constants.%Abstract3]\n// CHECK:STDOUT:     %a: %Abstract3 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract3 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %Abstract3) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %l.patt: %pattern_type.016 = value_binding_pattern l [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.ref: %Abstract3 = name_ref a, %a\n// CHECK:STDOUT:   %.loc14_35: %tuple.type.c99 = tuple_literal (%a.ref)\n// CHECK:STDOUT:   %.loc14_28.1: type = splice_block %.loc14_28.3 [concrete = constants.%tuple.type.c99] {\n// CHECK:STDOUT:     %Abstract3.ref.loc14: type = name_ref Abstract3, file.%Abstract3.decl [concrete = constants.%Abstract3]\n// CHECK:STDOUT:     %.loc14_28.2: %tuple.type.85c = tuple_literal (%Abstract3.ref.loc14) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc14_28.3: type = converted %.loc14_28.2, constants.%tuple.type.c99 [concrete = constants.%tuple.type.c99]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %l: %tuple.type.c99 = value_binding l, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_twice.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract4: type = class_type @Abstract4 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Abstract5: type = class_type @Abstract5 [concrete]\n// CHECK:STDOUT:   %Var2.type: type = fn_type @Var2 [concrete]\n// CHECK:STDOUT:   %Var2: %Var2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%Abstract4, %Abstract5) [concrete]\n// CHECK:STDOUT:   %tuple.type.fa1: type = tuple_type (%Abstract4, %Abstract5) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract4 = %Abstract4.decl\n// CHECK:STDOUT:     .Abstract5 = %Abstract5.decl\n// CHECK:STDOUT:     .Var2 = %Var2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract4.decl: type = class_decl @Abstract4 [concrete = constants.%Abstract4] {} {}\n// CHECK:STDOUT:   %Abstract5.decl: type = class_decl @Abstract5 [concrete = constants.%Abstract5] {} {}\n// CHECK:STDOUT:   %Var2.decl: %Var2.type = fn_decl @Var2 [concrete = constants.%Var2] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract4 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract5 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Var2() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v2.patt: <error> = ref_binding_pattern v2 [concrete]\n// CHECK:STDOUT:     %v2.var_patt: <error> = var_pattern %v2.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v2.var: ref <error> = var %v2.var_patt [concrete = <error>]\n// CHECK:STDOUT:   assign %v2.var, <error>\n// CHECK:STDOUT:   %.loc14_39.1: type = splice_block %.loc14_39.3 [concrete = constants.%tuple.type.fa1] {\n// CHECK:STDOUT:     %Abstract4.ref: type = name_ref Abstract4, file.%Abstract4.decl [concrete = constants.%Abstract4]\n// CHECK:STDOUT:     %Abstract5.ref: type = name_ref Abstract5, file.%Abstract5.decl [concrete = constants.%Abstract5]\n// CHECK:STDOUT:     %.loc14_39.2: %tuple.type.24b = tuple_literal (%Abstract4.ref, %Abstract5.ref) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc14_39.3: type = converted %.loc14_39.2, constants.%tuple.type.fa1 [concrete = constants.%tuple.type.fa1]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v2: ref <error> = ref_binding v2, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_first.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract6: type = class_type @Abstract6 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Var3.type: type = fn_type @Var3 [concrete]\n// CHECK:STDOUT:   %Var3: %Var3.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.159: type = tuple_type (type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.159 = tuple_value (%Abstract6, %empty_struct) [concrete]\n// CHECK:STDOUT:   %tuple.type.a75: type = tuple_type (%Abstract6, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract6 = %Abstract6.decl\n// CHECK:STDOUT:     .Var3 = %Var3.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract6.decl: type = class_decl @Abstract6 [concrete = constants.%Abstract6] {} {}\n// CHECK:STDOUT:   %Var3.decl: %Var3.type = fn_decl @Var3 [concrete = constants.%Var3] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract6 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Var3() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v3.patt: <error> = ref_binding_pattern v3 [concrete]\n// CHECK:STDOUT:     %v3.var_patt: <error> = var_pattern %v3.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v3.var: ref <error> = var %v3.var_patt [concrete = <error>]\n// CHECK:STDOUT:   assign %v3.var, <error>\n// CHECK:STDOUT:   %.loc13_32.1: type = splice_block %.loc13_32.4 [concrete = constants.%tuple.type.a75] {\n// CHECK:STDOUT:     %Abstract6.ref: type = name_ref Abstract6, file.%Abstract6.decl [concrete = constants.%Abstract6]\n// CHECK:STDOUT:     %.loc13_31: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc13_32.2: %tuple.type.159 = tuple_literal (%Abstract6.ref, %.loc13_31) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc13_32.3: type = converted constants.%empty_struct, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %.loc13_32.4: type = converted %.loc13_32.2, constants.%tuple.type.a75 [concrete = constants.%tuple.type.a75]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v3: ref <error> = ref_binding v3, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_abstract_second.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract7: type = class_type @Abstract7 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Var4.type: type = fn_type @Var4 [concrete]\n// CHECK:STDOUT:   %Var4: %Var4.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.c8c: type = tuple_type (%empty_struct_type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.c8c = tuple_value (%empty_struct, %Abstract7) [concrete]\n// CHECK:STDOUT:   %tuple.type.ff9: type = tuple_type (%empty_struct_type, %Abstract7) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract7 = %Abstract7.decl\n// CHECK:STDOUT:     .Var4 = %Var4.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract7.decl: type = class_decl @Abstract7 [concrete = constants.%Abstract7] {} {}\n// CHECK:STDOUT:   %Var4.decl: %Var4.type = fn_decl @Var4 [concrete = constants.%Var4] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract7 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Var4() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v4.patt: <error> = ref_binding_pattern v4 [concrete]\n// CHECK:STDOUT:     %v4.var_patt: <error> = var_pattern %v4.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v4.var: ref <error> = var %v4.var_patt [concrete = <error>]\n// CHECK:STDOUT:   assign %v4.var, <error>\n// CHECK:STDOUT:   %.loc13_32.1: type = splice_block %.loc13_32.4 [concrete = constants.%tuple.type.ff9] {\n// CHECK:STDOUT:     %.loc13_20: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %Abstract7.ref: type = name_ref Abstract7, file.%Abstract7.decl [concrete = constants.%Abstract7]\n// CHECK:STDOUT:     %.loc13_32.2: %tuple.type.c8c = tuple_literal (%.loc13_20, %Abstract7.ref) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc13_32.3: type = converted constants.%empty_struct, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %.loc13_32.4: type = converted %.loc13_32.2, constants.%tuple.type.ff9 [concrete = constants.%tuple.type.ff9]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v4: ref <error> = ref_binding v4, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- lib.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_import.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Var5.type: type = fn_type @Var5 [concrete]\n// CHECK:STDOUT:   %Var5: %Var5.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.85c = tuple_value (%Abstract) [concrete]\n// CHECK:STDOUT:   %tuple.type.e3a: type = tuple_type (%Abstract) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Abstract: type = import_ref Main//lib, Abstract, loaded [concrete = constants.%Abstract]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//lib, loc3_26, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.141 = import_ref Main//lib, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Abstract = imports.%Main.Abstract\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Var5 = %Var5.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %Var5.decl: %Var5.type = fn_decl @Var5 [concrete = constants.%Var5] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract [from \"lib.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.141\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Var5() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v5.patt: <error> = ref_binding_pattern v5 [concrete]\n// CHECK:STDOUT:     %v5.var_patt: <error> = var_pattern %v5.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v5.var: ref <error> = var %v5.var_patt [concrete = <error>]\n// CHECK:STDOUT:   assign %v5.var, <error>\n// CHECK:STDOUT:   %.loc14_28.1: type = splice_block %.loc14_28.3 [concrete = constants.%tuple.type.e3a] {\n// CHECK:STDOUT:     %Abstract.ref: type = name_ref Abstract, imports.%Main.Abstract [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %.loc14_28.2: %tuple.type.85c = tuple_literal (%Abstract.ref) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc14_28.3: type = converted %.loc14_28.2, constants.%tuple.type.e3a [concrete = constants.%tuple.type.e3a]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v5: ref <error> = ref_binding v5, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/access/access_modifers.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/access/access_modifers.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/access/access_modifers.carbon\n\n// --- fail_private_field_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Circle {\n  private var radius: i32;\n  private let SOME_INTERNAL_CONSTANT: i32 = 5;\n\n  private fn SomeInternalFunction() -> i32 {\n    return 0;\n  }\n\n  fn Make() -> Self {\n    return {.radius = 5};\n  }\n}\n\nfn Run() {\n  let circle: Circle = Circle.Make();\n  // CHECK:STDERR: fail_private_field_access.carbon:[[@LINE+7]]:28: error: cannot access private member `radius` of type `Circle` [ClassInvalidMemberAccess]\n  // CHECK:STDERR:   let unused radius: i32 = circle.radius;\n  // CHECK:STDERR:                            ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_private_field_access.carbon:[[@LINE-17]]:15: note: declared here [ClassMemberDeclaration]\n  // CHECK:STDERR:   private var radius: i32;\n  // CHECK:STDERR:               ^~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused radius: i32 = circle.radius;\n  // CHECK:STDERR: fail_private_field_access.carbon:[[@LINE+7]]:3: error: cannot access private member `radius` of type `Circle` [ClassInvalidMemberAccess]\n  // CHECK:STDERR:   circle.radius = 5;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_private_field_access.carbon:[[@LINE-25]]:15: note: declared here [ClassMemberDeclaration]\n  // CHECK:STDERR:   private var radius: i32;\n  // CHECK:STDERR:               ^~~~~~~~~~~\n  // CHECK:STDERR:\n  circle.radius = 5;\n  // CHECK:STDERR: fail_private_field_access.carbon:[[@LINE+7]]:3: error: cannot access private member `SOME_INTERNAL_CONSTANT` of type `Circle` [ClassInvalidMemberAccess]\n  // CHECK:STDERR:   circle.SOME_INTERNAL_CONSTANT;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_private_field_access.carbon:[[@LINE-32]]:15: note: declared here [ClassMemberDeclaration]\n  // CHECK:STDERR:   private let SOME_INTERNAL_CONSTANT: i32 = 5;\n  // CHECK:STDERR:               ^~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  circle.SOME_INTERNAL_CONSTANT;\n\n  // CHECK:STDERR: fail_private_field_access.carbon:[[@LINE+7]]:3: error: cannot access private member `SomeInternalFunction` of type `Circle` [ClassInvalidMemberAccess]\n  // CHECK:STDERR:   circle.SomeInternalFunction();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_private_field_access.carbon:[[@LINE-39]]:3: note: declared here [ClassMemberDeclaration]\n  // CHECK:STDERR:   private fn SomeInternalFunction() -> i32 {\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  circle.SomeInternalFunction();\n}\n\n// --- fail_protected_field_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  protected var x: i32;\n}\n\nfn Run() {\n  // CHECK:STDERR: fail_protected_field_access.carbon:[[@LINE+7]]:23: error: cannot access protected member `x` of type `A` [ClassInvalidMemberAccess]\n  // CHECK:STDERR:   let unused x: i32 = A.x;\n  // CHECK:STDERR:                       ^~~\n  // CHECK:STDERR: fail_protected_field_access.carbon:[[@LINE-7]]:17: note: declared here [ClassMemberDeclaration]\n  // CHECK:STDERR:   protected var x: i32;\n  // CHECK:STDERR:                 ^~~~~~\n  // CHECK:STDERR:\n  let unused x: i32 = A.x;\n}\n\n// --- instance_private_field_access_on_self.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Circle {\n  private var radius: i32;\n\n  fn GetRadius[self: Self]() -> i32 {\n    return self.radius;\n  }\n\n  private fn SomeInternalFunction() -> i32 {\n    return 0;\n  }\n\n  fn Compute[self: Self]() -> i32 {\n    return self.SomeInternalFunction();\n  }\n}\n\n// --- public_global_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  let x: i32 = 5;\n}\n\nlet x: i32 = A.x;\n\n// --- fail_global_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  protected let x: i32 = 5;\n  private let y: i32 = 5;\n}\n\n// CHECK:STDERR: fail_global_access.carbon:[[@LINE+7]]:14: error: cannot access protected member `x` of type `A` [ClassInvalidMemberAccess]\n// CHECK:STDERR: let x: i32 = A.x;\n// CHECK:STDERR:              ^~~\n// CHECK:STDERR: fail_global_access.carbon:[[@LINE-7]]:17: note: declared here [ClassMemberDeclaration]\n// CHECK:STDERR:   protected let x: i32 = 5;\n// CHECK:STDERR:                 ^\n// CHECK:STDERR:\nlet x: i32 = A.x;\n// CHECK:STDERR: fail_global_access.carbon:[[@LINE+7]]:14: error: cannot access private member `y` of type `A` [ClassInvalidMemberAccess]\n// CHECK:STDERR: let y: i32 = A.y;\n// CHECK:STDERR:              ^~~\n// CHECK:STDERR: fail_global_access.carbon:[[@LINE-14]]:15: note: declared here [ClassMemberDeclaration]\n// CHECK:STDERR:   private let y: i32 = 5;\n// CHECK:STDERR:               ^\n// CHECK:STDERR:\nlet y: i32 = A.y;\n\n// --- self_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {\n  private fn F() {}\n  private fn G() { Self.F(); }\n}\n\n// CHECK:STDOUT: --- fail_private_field_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Circle: type = class_type @Circle [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Circle.elem: type = unbound_element_type %Circle, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %int_5.64b: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.e9d: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_5.0f6: %i32 = int_value 5 [concrete]\n// CHECK:STDOUT:   %Circle.SomeInternalFunction.type: type = fn_type @Circle.SomeInternalFunction [concrete]\n// CHECK:STDOUT:   %Circle.SomeInternalFunction: %Circle.SomeInternalFunction.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.f65: Core.Form = init_form %Circle [concrete]\n// CHECK:STDOUT:   %pattern_type.fcb: type = pattern_type %Circle [concrete]\n// CHECK:STDOUT:   %Circle.Make.type: type = fn_type @Circle.Make [concrete]\n// CHECK:STDOUT:   %Circle.Make: %Circle.Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.radius.251: type = struct_type {.radius: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.5a5: <witness> = complete_type_witness %struct_type.radius.251 [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.897: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.d2e: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %struct_type.radius.f47: type = struct_type {.radius: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.radius.f47 = struct_value (%int_5.64b) [concrete]\n// CHECK:STDOUT:   %Circle.val: %Circle = struct_value (%int_5.0f6) [concrete]\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Circle = %Circle.decl\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Circle.decl: type = class_decl @Circle [concrete = constants.%Circle] {} {}\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Circle {\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %Circle.elem = field_decl radius, element0 [concrete]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %SOME_INTERNAL_CONSTANT.patt: %pattern_type.7ce = value_binding_pattern SOME_INTERNAL_CONSTANT [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc6_45.1: <bound method> = bound_method %int_5, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_45.2: <bound method> = bound_method %int_5, %specific_fn [concrete = constants.%bound_method.e9d]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc6_45.2(%int_5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc6_45.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc6_45.2: %i32 = converted %int_5, %.loc6_45.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %SOME_INTERNAL_CONSTANT: %i32 = value_binding SOME_INTERNAL_CONSTANT, %.loc6_45.2\n// CHECK:STDOUT:   %Circle.SomeInternalFunction.decl: %Circle.SomeInternalFunction.type = fn_decl @Circle.SomeInternalFunction [concrete = constants.%Circle.SomeInternalFunction] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Circle.Make.decl: %Circle.Make.type = fn_decl @Circle.Make [concrete = constants.%Circle.Make] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.fcb = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.fcb = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Circle [concrete = constants.%Circle]\n// CHECK:STDOUT:     %.loc12: Core.Form = init_form %Self.ref [concrete = constants.%.f65]\n// CHECK:STDOUT:     %return.param: ref %Circle = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Circle = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.radius.251 [concrete = constants.%complete_type.5a5]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Circle\n// CHECK:STDOUT:   .radius [private] = %.loc5\n// CHECK:STDOUT:   .SOME_INTERNAL_CONSTANT [private] = %SOME_INTERNAL_CONSTANT\n// CHECK:STDOUT:   .SomeInternalFunction [private] = %Circle.SomeInternalFunction.decl\n// CHECK:STDOUT:   .Make = %Circle.Make.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Circle.SomeInternalFunction() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc9_13.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.897]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_13.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method.d2e]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc9_13.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc9: init %i32 = converted %int_0, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   return %.loc9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Circle.Make() -> out %return.param: %Circle {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %.loc13_24.1: %struct_type.radius.f47 = struct_literal (%int_5) [concrete = constants.%struct]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc13_24.1: <bound method> = bound_method %int_5, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_24.2: <bound method> = bound_method %int_5, %specific_fn [concrete = constants.%bound_method.e9d]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc13_24.2(%int_5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc13_24.2: init %i32 = converted %int_5, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc13_24.3: ref %i32 = class_element_access %return.param, element0\n// CHECK:STDOUT:   %.loc13_24.4: init %i32 to %.loc13_24.3 = in_place_init %.loc13_24.2 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc13_24.5: init %Circle to %return.param = class_init (%.loc13_24.4) [concrete = constants.%Circle.val]\n// CHECK:STDOUT:   %.loc13_25: init %Circle = converted %.loc13_24.1, %.loc13_24.5 [concrete = constants.%Circle.val]\n// CHECK:STDOUT:   return %.loc13_25 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %circle.patt: %pattern_type.fcb = value_binding_pattern circle [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Circle.ref.loc18_24: type = name_ref Circle, file.%Circle.decl [concrete = constants.%Circle]\n// CHECK:STDOUT:   %Make.ref: %Circle.Make.type = name_ref Make, @Circle.%Circle.Make.decl [concrete = constants.%Circle.Make]\n// CHECK:STDOUT:   %.loc18_36.1: ref %Circle = temporary_storage\n// CHECK:STDOUT:   %Circle.Make.call: init %Circle to %.loc18_36.1 = call %Make.ref()\n// CHECK:STDOUT:   %Circle.ref.loc18_15: type = name_ref Circle, file.%Circle.decl [concrete = constants.%Circle]\n// CHECK:STDOUT:   %.loc18_36.2: ref %Circle = temporary %.loc18_36.1, %Circle.Make.call\n// CHECK:STDOUT:   %.loc18_36.3: %Circle = acquire_value %.loc18_36.2\n// CHECK:STDOUT:   %circle: %Circle = value_binding circle, %.loc18_36.3\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %radius.patt: %pattern_type.7ce = value_binding_pattern radius [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %circle.ref.loc26: %Circle = name_ref circle, %circle\n// CHECK:STDOUT:   %radius.ref.loc26: <error> = name_ref radius, <error> [concrete = <error>]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %radius: %i32 = value_binding radius, <error> [concrete = <error>]\n// CHECK:STDOUT:   %circle.ref.loc34: %Circle = name_ref circle, %circle\n// CHECK:STDOUT:   %radius.ref.loc34: <error> = name_ref radius, <error> [concrete = <error>]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   assign %radius.ref.loc34, <error>\n// CHECK:STDOUT:   %circle.ref.loc42: %Circle = name_ref circle, %circle\n// CHECK:STDOUT:   %SOME_INTERNAL_CONSTANT.ref: <error> = name_ref SOME_INTERNAL_CONSTANT, <error> [concrete = <error>]\n// CHECK:STDOUT:   %circle.ref.loc51: %Circle = name_ref circle, %circle\n// CHECK:STDOUT:   %SomeInternalFunction.ref: <error> = name_ref SomeInternalFunction, <error> [concrete = <error>]\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc18_36.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc18_36.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Circle) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_protected_field_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %A.elem: type = unbound_element_type %A, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x [concrete]\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %A.elem = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x [concrete = constants.%complete_type.1ec]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .x [protected] = %.loc5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = value_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error> [concrete = <error>]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %x: %i32 = value_binding x, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- instance_private_field_access_on_self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Circle: type = class_type @Circle [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Circle.elem: type = unbound_element_type %Circle, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.fcb: type = pattern_type %Circle [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Circle.GetRadius.type: type = fn_type @Circle.GetRadius [concrete]\n// CHECK:STDOUT:   %Circle.GetRadius: %Circle.GetRadius.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Circle.SomeInternalFunction.type: type = fn_type @Circle.SomeInternalFunction [concrete]\n// CHECK:STDOUT:   %Circle.SomeInternalFunction: %Circle.SomeInternalFunction.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Circle.Compute.type: type = fn_type @Circle.Compute [concrete]\n// CHECK:STDOUT:   %Circle.Compute: %Circle.Compute.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.radius: type = struct_type {.radius: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.5a5: <witness> = complete_type_witness %struct_type.radius [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Circle = %Circle.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Circle.decl: type = class_decl @Circle [concrete = constants.%Circle] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Circle {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %Circle.elem = field_decl radius, element0 [concrete]\n// CHECK:STDOUT:   %Circle.GetRadius.decl: %Circle.GetRadius.type = fn_decl @Circle.GetRadius [concrete = constants.%Circle.GetRadius] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.fcb = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.fcb = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc7: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: %Circle = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Circle [concrete = constants.%Circle]\n// CHECK:STDOUT:     %self: %Circle = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Circle.SomeInternalFunction.decl: %Circle.SomeInternalFunction.type = fn_decl @Circle.SomeInternalFunction [concrete = constants.%Circle.SomeInternalFunction] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc11: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Circle.Compute.decl: %Circle.Compute.type = fn_decl @Circle.Compute [concrete = constants.%Circle.Compute] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.fcb = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.fcb = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: %Circle = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Circle [concrete = constants.%Circle]\n// CHECK:STDOUT:     %self: %Circle = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.radius [concrete = constants.%complete_type.5a5]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Circle\n// CHECK:STDOUT:   .radius [private] = %.loc5\n// CHECK:STDOUT:   .GetRadius = %Circle.GetRadius.decl\n// CHECK:STDOUT:   .SomeInternalFunction [private] = %Circle.SomeInternalFunction.decl\n// CHECK:STDOUT:   .Compute = %Circle.Compute.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Circle.GetRadius(%self.param: %Circle) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %Circle = name_ref self, %self\n// CHECK:STDOUT:   %radius.ref: %Circle.elem = name_ref radius, @Circle.%.loc5 [concrete = @Circle.%.loc5]\n// CHECK:STDOUT:   %.loc8_16.1: ref %i32 = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc8_16.2: %i32 = acquire_value %.loc8_16.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc8_16.1: <bound method> = bound_method %.loc8_16.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_16.2: <bound method> = bound_method %.loc8_16.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc8_16.2(%.loc8_16.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Circle.SomeInternalFunction() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc12_13.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc12_13.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc12_13.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc12: init %i32 = converted %int_0, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   return %.loc12\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Circle.Compute(%self.param: %Circle) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %Circle = name_ref self, %self\n// CHECK:STDOUT:   %SomeInternalFunction.ref: %Circle.SomeInternalFunction.type = name_ref SomeInternalFunction, @Circle.%Circle.SomeInternalFunction.decl [concrete = constants.%Circle.SomeInternalFunction]\n// CHECK:STDOUT:   %Circle.SomeInternalFunction.call: init %i32 = call %SomeInternalFunction.ref()\n// CHECK:STDOUT:   return %Circle.SomeInternalFunction.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- public_global_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %int_5.64b: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_5.0f6: %i32 = int_value 5 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = value_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %x: %i32 = value_binding x, @__global_init.%x.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = value_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc5_16.1: <bound method> = bound_method %int_5, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc5_16.2: <bound method> = bound_method %int_5, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc5_16.2(%int_5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc5_16.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc5_16.2: %i32 = converted %int_5, %.loc5_16.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %x: %i32 = value_binding x, %.loc5_16.2\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .x = %x\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %x.ref: %i32 = name_ref x, @A.%x\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_global_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %int_5.64b: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_5.0f6: %i32 = int_value 5 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:     .y = %y\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = value_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %x: %i32 = value_binding x, <error> [concrete = <error>]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %y.patt: %pattern_type.7ce = value_binding_pattern y [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32.loc24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %y: %i32 = value_binding y, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = value_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_5.loc5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0.loc5: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc5_26.1: <bound method> = bound_method %int_5.loc5, %impl.elem0.loc5 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc5: <specific function> = specific_function %impl.elem0.loc5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc5_26.2: <bound method> = bound_method %int_5.loc5, %specific_fn.loc5 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5: init %i32 = call %bound_method.loc5_26.2(%int_5.loc5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc5_26.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc5_26.2: %i32 = converted %int_5.loc5, %.loc5_26.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %x: %i32 = value_binding x, %.loc5_26.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %y.patt: %pattern_type.7ce = value_binding_pattern y [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_5.loc6: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0.loc6: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc6_24.1: <bound method> = bound_method %int_5.loc6, %impl.elem0.loc6 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_24.2: <bound method> = bound_method %int_5.loc6, %specific_fn.loc6 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %i32 = call %bound_method.loc6_24.2(%int_5.loc6) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc6_24.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc6_24.2: %i32 = converted %int_5.loc6, %.loc6_24.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %y: %i32 = value_binding y, %.loc6_24.2\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .x [protected] = %x\n// CHECK:STDOUT:   .y [private] = %y\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref.loc16: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error> [concrete = <error>]\n// CHECK:STDOUT:   %A.ref.loc24: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %y.ref: <error> = name_ref y, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- self_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %A.F.type: type = fn_type @A.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %A.F: %A.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.G.type: type = fn_type @A.G [concrete]\n// CHECK:STDOUT:   %A.G: %A.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %A.F.decl: %A.F.type = fn_decl @A.F [concrete = constants.%A.F] {} {}\n// CHECK:STDOUT:   %A.G.decl: %A.G.type = fn_decl @A.G [concrete = constants.%A.G] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .F [private] = %A.F.decl\n// CHECK:STDOUT:   .G [private] = %A.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%A [concrete = constants.%A]\n// CHECK:STDOUT:   %F.ref: %A.F.type = name_ref F, @A.%A.F.decl [concrete = constants.%A.F]\n// CHECK:STDOUT:   %A.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/access/import_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/access/import_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/access/import_access.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nprivate class Def {}\n\n// --- forward_with_def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nprivate class ForwardWithDef;\n\nclass ForwardWithDef {}\n\n// --- forward.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nprivate class Forward;\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- def.impl.carbon\n\nimpl package Test library \"[[@TEST_NAME]]\";\n\nvar c: Def = {};\n\n// --- fail_local_def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nimport library \"def\";\n\n// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:8: error: name `Def` not found [NameNotFound]\n// CHECK:STDERR: var c: Def = {};\n// CHECK:STDERR:        ^~~\n// CHECK:STDERR:\nvar c: Def = {};\n\n// --- fail_other_def.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nimport Test library \"def\";\n\n// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:8: error: member name `Def` not found in `Test` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: var c: Test.Def = {};\n// CHECK:STDERR:        ^~~~~~~~\n// CHECK:STDERR:\nvar c: Test.Def = {};\n\n// --- forward_with_def.impl.carbon\n\nimpl package Test library \"[[@TEST_NAME]]\";\n\nvar c: ForwardWithDef = {};\n\n// --- fail_local_forward_with_def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nimport library \"forward_with_def\";\n\n// CHECK:STDERR: fail_local_forward_with_def.carbon:[[@LINE+4]]:8: error: name `ForwardWithDef` not found [NameNotFound]\n// CHECK:STDERR: var c: ForwardWithDef = {};\n// CHECK:STDERR:        ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar c: ForwardWithDef = {};\n\n// --- fail_other_forward_with_def.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nimport Test library \"forward_with_def\";\n\n// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:8: error: member name `ForwardWithDef` not found in `Test` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: var c: Test.ForwardWithDef = {};\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar c: Test.ForwardWithDef = {};\n\n// --- forward.impl.carbon\n\nimpl package Test library \"[[@TEST_NAME]]\";\n\nfn F(unused c: Forward*) {}\n\nclass Forward {}\n\n// --- fail_local_forward.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nimport library \"forward\";\n\n// CHECK:STDERR: fail_local_forward.carbon:[[@LINE+4]]:16: error: name `Forward` not found [NameNotFound]\n// CHECK:STDERR: fn F(unused c: Forward*) {}\n// CHECK:STDERR:                ^~~~~~~\n// CHECK:STDERR:\nfn F(unused c: Forward*) {}\n\n// --- fail_other_forward.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nimport Test library \"forward\";\n\n// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+4]]:16: error: member name `Forward` not found in `Test` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: fn F(unused c: Test.Forward*) {}\n// CHECK:STDERR:                ^~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused c: Test.Forward*) {}\n\n// --- todo_fail_private_on_redecl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nprivate class Redecl;\n\nprivate class Redecl {}\n\n// CHECK:STDOUT: --- def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Def: type = class_type @Def [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Def [private] = %Def.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Def.decl: type = class_decl @Def [concrete = constants.%Def] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Def {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Def\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- forward_with_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %ForwardWithDef: type = class_type @ForwardWithDef [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .ForwardWithDef [private] = %ForwardWithDef.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ForwardWithDef.decl.loc4: type = class_decl @ForwardWithDef [concrete = constants.%ForwardWithDef] {} {}\n// CHECK:STDOUT:   %ForwardWithDef.decl.loc6: type = class_decl @ForwardWithDef [concrete = constants.%ForwardWithDef] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ForwardWithDef {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%ForwardWithDef\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- forward.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Forward: type = class_type @Forward [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Forward [private] = %Forward.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Forward.decl: type = class_decl @Forward [concrete = constants.%Forward] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Forward;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- def.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Def: type = class_type @Def [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Def [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Def.val: %Def = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test.Def: type = import_ref Test//def, Def, loaded [concrete = constants.%Def]\n// CHECK:STDOUT:   %Test.import_ref.8f2: <witness> = import_ref Test//def, loc4_20, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Test.import_ref.390 = import_ref Test//def, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Def [private] = imports.%Test.Def\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %Def = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %Def.ref: type = name_ref Def, imports.%Test.Def [concrete = constants.%Def]\n// CHECK:STDOUT:   %c: ref %Def = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Def [from \"def.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Test.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Test.import_ref.390\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc4_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc4_15.2: init %Def to file.%c.var = class_init () [concrete = constants.%Def.val]\n// CHECK:STDOUT:   %.loc4_1: init %Def = converted %.loc4_15.1, %.loc4_15.2 [concrete = constants.%Def.val]\n// CHECK:STDOUT:   assign file.%c.var, %.loc4_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_local_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Def = <poisoned>\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: <error> = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: <error> = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref <error> = var %c.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %Def.ref: <error> = name_ref Def, <error> [concrete = <error>]\n// CHECK:STDOUT:   %c: ref <error> = ref_binding c, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   assign file.%c.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_other_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test: <namespace> = namespace file.%Test.import, [concrete] {\n// CHECK:STDOUT:     .Def = <poisoned>\n// CHECK:STDOUT:     import Test//def\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Test = imports.%Test\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: <error> = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: <error> = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref <error> = var %c.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.1: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:     %Test.ref: <namespace> = name_ref Test, imports.%Test [concrete = imports.%Test]\n// CHECK:STDOUT:     %Def.ref: <error> = name_ref Def, <error> [concrete = <error>]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref <error> = ref_binding c, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   assign file.%c.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- forward_with_def.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %ForwardWithDef: type = class_type @ForwardWithDef [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ForwardWithDef [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %ForwardWithDef.val: %ForwardWithDef = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test.ForwardWithDef: type = import_ref Test//forward_with_def, ForwardWithDef, loaded [concrete = constants.%ForwardWithDef]\n// CHECK:STDOUT:   %Test.import_ref.8f2: <witness> = import_ref Test//forward_with_def, loc6_23, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Test.import_ref.623 = import_ref Test//forward_with_def, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .ForwardWithDef [private] = imports.%Test.ForwardWithDef\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %ForwardWithDef = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %ForwardWithDef.ref: type = name_ref ForwardWithDef, imports.%Test.ForwardWithDef [concrete = constants.%ForwardWithDef]\n// CHECK:STDOUT:   %c: ref %ForwardWithDef = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ForwardWithDef [from \"forward_with_def.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Test.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Test.import_ref.623\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc4_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc4_26.2: init %ForwardWithDef to file.%c.var = class_init () [concrete = constants.%ForwardWithDef.val]\n// CHECK:STDOUT:   %.loc4_1: init %ForwardWithDef = converted %.loc4_26.1, %.loc4_26.2 [concrete = constants.%ForwardWithDef.val]\n// CHECK:STDOUT:   assign file.%c.var, %.loc4_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_local_forward_with_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .ForwardWithDef = <poisoned>\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: <error> = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: <error> = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref <error> = var %c.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %ForwardWithDef.ref: <error> = name_ref ForwardWithDef, <error> [concrete = <error>]\n// CHECK:STDOUT:   %c: ref <error> = ref_binding c, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   assign file.%c.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_other_forward_with_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test: <namespace> = namespace file.%Test.import, [concrete] {\n// CHECK:STDOUT:     .ForwardWithDef = <poisoned>\n// CHECK:STDOUT:     import Test//forward_with_def\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Test = imports.%Test\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: <error> = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: <error> = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref <error> = var %c.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.1: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:     %Test.ref: <namespace> = name_ref Test, imports.%Test [concrete = imports.%Test]\n// CHECK:STDOUT:     %ForwardWithDef.ref: <error> = name_ref ForwardWithDef, <error> [concrete = <error>]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref <error> = ref_binding c, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   assign file.%c.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- forward.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Forward: type = class_type @Forward [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %Forward [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test.Forward: type = import_ref Test//forward, Forward, loaded [concrete = constants.%Forward]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Forward [private] = %Forward.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %ptr = value_param call_param0\n// CHECK:STDOUT:     %.loc4: type = splice_block %ptr [concrete = constants.%ptr] {\n// CHECK:STDOUT:       %Forward.ref: type = name_ref Forward, imports.%Test.Forward [concrete = constants.%Forward]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Forward.ref [concrete = constants.%ptr]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %ptr = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Forward.decl: type = class_decl @Forward [concrete = constants.%Forward] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Forward {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Forward\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %ptr) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_local_forward.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Forward = <poisoned>\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: <error> = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: <error> = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: <error> = value_param call_param0\n// CHECK:STDOUT:     %.loc10: type = splice_block %ptr [concrete = <error>] {\n// CHECK:STDOUT:       %Forward.ref: <error> = name_ref Forward, <error> [concrete = <error>]\n// CHECK:STDOUT:       %ptr: type = ptr_type <error> [concrete = <error>]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: <error> = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: <error>) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_other_forward.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test: <namespace> = namespace file.%Test.import, [concrete] {\n// CHECK:STDOUT:     .Forward = <poisoned>\n// CHECK:STDOUT:     import Test//forward\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Test = imports.%Test\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: <error> = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: <error> = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: <error> = value_param call_param0\n// CHECK:STDOUT:     %.loc10: type = splice_block %ptr [concrete = <error>] {\n// CHECK:STDOUT:       %Test.ref: <namespace> = name_ref Test, imports.%Test [concrete = imports.%Test]\n// CHECK:STDOUT:       %Forward.ref: <error> = name_ref Forward, <error> [concrete = <error>]\n// CHECK:STDOUT:       %ptr: type = ptr_type <error> [concrete = <error>]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: <error> = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: <error>) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- todo_fail_private_on_redecl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Redecl: type = class_type @Redecl [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Redecl [private] = %Redecl.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Redecl.decl.loc4: type = class_decl @Redecl [concrete = constants.%Redecl] {} {}\n// CHECK:STDOUT:   %Redecl.decl.loc6: type = class_decl @Redecl [concrete = constants.%Redecl] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Redecl {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Redecl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/access/inheritance_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/access/inheritance_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/access/inheritance_access.carbon\n\n\n// --- instance_protected_field_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Shape {\n  protected var x: i32;\n  protected var y: i32;\n}\n\nclass Circle {\n  extend base: Shape;\n\n  fn GetPosition[self: Self]() -> (i32, i32) {\n    return (self.x, self.y);\n  }\n}\n\n// --- shadowing_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class A {\n  fn F();\n}\n\nbase class B {\n  extend base: A;\n  private fn F() -> i32;\n}\n\nbase class C {\n  extend base: B;\n  fn G[self: Self]() -> () { return self.F(); }\n}\n\n// --- inherited_member_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class A {\n  protected let SOME_CONSTANT: i32 = 5;\n  protected fn SomeProtectedFunction() -> i32 {\n    return 5;\n  }\n}\n\nclass B {\n  extend base: A;\n\n  fn G() -> i32 {\n    return A.SOME_CONSTANT;\n  }\n\n  fn H() -> i32 {\n    return A.SomeProtectedFunction();\n  }\n}\n\n// --- fail_inherited_private_field_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Shape {\n  private var y: i32;\n}\n\nclass Square {\n  extend base: Shape;\n\n  fn GetPosition[self: Self]() -> i32 {\n    // CHECK:STDERR: fail_inherited_private_field_access.carbon:[[@LINE+7]]:12: error: cannot access private member `y` of type `Shape` [ClassInvalidMemberAccess]\n    // CHECK:STDERR:     return self.y;\n    // CHECK:STDERR:            ^~~~~~\n    // CHECK:STDERR: fail_inherited_private_field_access.carbon:[[@LINE-10]]:15: note: declared here [ClassMemberDeclaration]\n    // CHECK:STDERR:   private var y: i32;\n    // CHECK:STDERR:               ^~~~~~\n    // CHECK:STDERR:\n    return self.y;\n  }\n}\n\n// --- noninstance_private_on_self.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  private fn F() {}\n  fn G() {\n    Self.F();\n    F();\n  }\n}\n\n// --- noninstance_protected_on_self.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  protected fn F() {}\n  fn G() {\n    Self.F();\n    F();\n  }\n}\n\n// --- fail_noninstance_private_on_parent_qualified.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class B {\n  private fn F() {}\n}\n\nclass C {\n  extend base: B;\n  // CHECK:STDERR: fail_noninstance_private_on_parent_qualified.carbon:[[@LINE+7]]:12: error: cannot access private member `F` of type `B` [ClassInvalidMemberAccess]\n  // CHECK:STDERR:   fn G() { Self.F(); }\n  // CHECK:STDERR:            ^~~~~~\n  // CHECK:STDERR: fail_noninstance_private_on_parent_qualified.carbon:[[@LINE-8]]:3: note: declared here [ClassMemberDeclaration]\n  // CHECK:STDERR:   private fn F() {}\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  fn G() { Self.F(); }\n}\n\n// --- fail_noninstance_private_on_parent_unqualified.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class A {\n  private fn Fa() {}\n}\n\nbase class B {\n  extend base: A;\n\n  private let SOME_PRIVATE_CONSTANT: i32 = 86;\n  private fn Fb() {}\n}\n\nclass C {\n  extend base: B;\n\n  // CHECK:STDERR: fail_noninstance_private_on_parent_unqualified.carbon:[[@LINE+7]]:27: error: cannot access private member `SOME_PRIVATE_CONSTANT` of type `B` [ClassInvalidMemberAccess]\n  // CHECK:STDERR:   fn G1() -> i32 { return SOME_PRIVATE_CONSTANT; }\n  // CHECK:STDERR:                           ^~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_noninstance_private_on_parent_unqualified.carbon:[[@LINE-10]]:15: note: declared here [ClassMemberDeclaration]\n  // CHECK:STDERR:   private let SOME_PRIVATE_CONSTANT: i32 = 86;\n  // CHECK:STDERR:               ^~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  fn G1() -> i32 { return SOME_PRIVATE_CONSTANT; }\n\n  // CHECK:STDERR: fail_noninstance_private_on_parent_unqualified.carbon:[[@LINE+7]]:13: error: cannot access private member `Fa` of type `A` [ClassInvalidMemberAccess]\n  // CHECK:STDERR:   fn G2() { Fa(); }\n  // CHECK:STDERR:             ^~\n  // CHECK:STDERR: fail_noninstance_private_on_parent_unqualified.carbon:[[@LINE-25]]:3: note: declared here [ClassMemberDeclaration]\n  // CHECK:STDERR:   private fn Fa() {}\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  fn G2() { Fa(); }\n\n  // CHECK:STDERR: fail_noninstance_private_on_parent_unqualified.carbon:[[@LINE+7]]:13: error: cannot access private member `Fb` of type `B` [ClassInvalidMemberAccess]\n  // CHECK:STDERR:   fn G3() { Fb(); }\n  // CHECK:STDERR:             ^~\n  // CHECK:STDERR: fail_noninstance_private_on_parent_unqualified.carbon:[[@LINE-27]]:3: note: declared here [ClassMemberDeclaration]\n  // CHECK:STDERR:   private fn Fb() {}\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  fn G3() { Fb(); }\n}\n\n// --- noninstance_protected_on_parent.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class B {\n  protected fn F() {}\n}\n\nclass C {\n  extend base: B;\n  fn G() { Self.F(); }\n}\n\n// --- fail_non_inherited_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class A {\n  protected let SOME_PROTECTED_CONSTANT: i32 = 5;\n  private let SOME_PRIVATE_CONSTANT: i32 = 5;\n}\n\nbase class Internal {\n  protected let INTERNAL_CONSTANT: i32 = 5;\n}\n\nclass B {\n  private var internal: Internal;\n\n  fn G() -> i32 {\n    // CHECK:STDERR: fail_non_inherited_access.carbon:[[@LINE+7]]:5: error: cannot access private member `SOME_PRIVATE_CONSTANT` of type `A` [ClassInvalidMemberAccess]\n    // CHECK:STDERR:     A.SOME_PRIVATE_CONSTANT;\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_non_inherited_access.carbon:[[@LINE-14]]:15: note: declared here [ClassMemberDeclaration]\n    // CHECK:STDERR:   private let SOME_PRIVATE_CONSTANT: i32 = 5;\n    // CHECK:STDERR:               ^~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    A.SOME_PRIVATE_CONSTANT;\n\n    // CHECK:STDERR: fail_non_inherited_access.carbon:[[@LINE+7]]:12: error: cannot access protected member `SOME_PROTECTED_CONSTANT` of type `A` [ClassInvalidMemberAccess]\n    // CHECK:STDERR:     return A.SOME_PROTECTED_CONSTANT;\n    // CHECK:STDERR:            ^~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_non_inherited_access.carbon:[[@LINE-24]]:17: note: declared here [ClassMemberDeclaration]\n    // CHECK:STDERR:   protected let SOME_PROTECTED_CONSTANT: i32 = 5;\n    // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    return A.SOME_PROTECTED_CONSTANT;\n  }\n\n  fn SomeFunc[self: Self]() -> i32{\n    // CHECK:STDERR: fail_non_inherited_access.carbon:[[@LINE+7]]:12: error: cannot access protected member `INTERNAL_CONSTANT` of type `Internal` [ClassInvalidMemberAccess]\n    // CHECK:STDERR:     return self.internal.INTERNAL_CONSTANT;\n    // CHECK:STDERR:            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_non_inherited_access.carbon:[[@LINE-30]]:17: note: declared here [ClassMemberDeclaration]\n    // CHECK:STDERR:   protected let INTERNAL_CONSTANT: i32 = 5;\n    // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    return self.internal.INTERNAL_CONSTANT;\n  }\n}\n\n// --- fail_compound_member_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class A {\n  private var x: i32;\n}\n\nclass B {\n  extend base: A;\n  fn F[self: Self]() {\n    // CHECK:STDERR: fail_compound_member_access.carbon:[[@LINE+7]]:11: error: cannot access private member `x` of type `A` [ClassInvalidMemberAccess]\n    // CHECK:STDERR:     self.(A.x);\n    // CHECK:STDERR:           ^~~\n    // CHECK:STDERR: fail_compound_member_access.carbon:[[@LINE-9]]:15: note: declared here [ClassMemberDeclaration]\n    // CHECK:STDERR:   private var x: i32;\n    // CHECK:STDERR:               ^~~~~~\n    // CHECK:STDERR:\n    self.(A.x);\n  }\n}\n\n// --- inherited_compound_member_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class A {\n  protected var x: i32;\n}\n\nclass B {\n  extend base: A;\n\n  fn F[self: Self]() {\n    self.(A.x);\n  }\n}\n\n// CHECK:STDOUT: --- instance_protected_field_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Shape: type = class_type @Shape [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Shape.elem: type = unbound_element_type %Shape, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x.y: type = struct_type {.x: %i32, .y: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.70a: <witness> = complete_type_witness %struct_type.x.y [concrete]\n// CHECK:STDOUT:   %Circle: type = class_type @Circle [concrete]\n// CHECK:STDOUT:   %Circle.elem: type = unbound_element_type %Circle, %Shape [concrete]\n// CHECK:STDOUT:   %pattern_type.fcb: type = pattern_type %Circle [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.95a: %tuple.type.24b = tuple_value (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %.f32: Core.Form = init_form %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %pattern_type.511: type = pattern_type %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %Circle.GetPosition.type: type = fn_type @Circle.GetPosition [concrete]\n// CHECK:STDOUT:   %Circle.GetPosition: %Circle.GetPosition.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.490: type = struct_type {.base: %Shape} [concrete]\n// CHECK:STDOUT:   %complete_type.560: <witness> = complete_type_witness %struct_type.base.490 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Shape = %Shape.decl\n// CHECK:STDOUT:     .Circle = %Circle.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Shape.decl: type = class_decl @Shape [concrete = constants.%Shape] {} {}\n// CHECK:STDOUT:   %Circle.decl: type = class_decl @Circle [concrete = constants.%Circle] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Shape {\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %Shape.elem = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc6: %Shape.elem = field_decl y, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x.y [concrete = constants.%complete_type.70a]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Shape\n// CHECK:STDOUT:   .x [protected] = %.loc5\n// CHECK:STDOUT:   .y [protected] = %.loc6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Circle {\n// CHECK:STDOUT:   %Shape.ref: type = name_ref Shape, file.%Shape.decl [concrete = constants.%Shape]\n// CHECK:STDOUT:   %.loc10: %Circle.elem = base_decl %Shape.ref, element0 [concrete]\n// CHECK:STDOUT:   %Circle.GetPosition.decl: %Circle.GetPosition.type = fn_decl @Circle.GetPosition [concrete = constants.%Circle.GetPosition] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.fcb = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.fcb = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.511 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.511 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc12_36: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %i32.loc12_41: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc12_44.1: %tuple.type.24b = tuple_literal (%i32.loc12_36, %i32.loc12_41) [concrete = constants.%tuple.95a]\n// CHECK:STDOUT:     %.loc12_44.2: type = converted %.loc12_44.1, constants.%tuple.type.d07 [concrete = constants.%tuple.type.d07]\n// CHECK:STDOUT:     %.loc12_44.3: Core.Form = init_form %.loc12_44.2 [concrete = constants.%.f32]\n// CHECK:STDOUT:     %self.param: %Circle = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Circle [concrete = constants.%Circle]\n// CHECK:STDOUT:     %self: %Circle = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %tuple.type.d07 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %tuple.type.d07 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.490 [concrete = constants.%complete_type.560]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Circle\n// CHECK:STDOUT:   .Shape = <poisoned>\n// CHECK:STDOUT:   .base = %.loc10\n// CHECK:STDOUT:   .GetPosition = %Circle.GetPosition.decl\n// CHECK:STDOUT:   .x = <poisoned>\n// CHECK:STDOUT:   .y = <poisoned>\n// CHECK:STDOUT:   extend %Shape.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Circle.GetPosition(%self.param: %Circle) -> out %return.param: %tuple.type.d07 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref.loc13_13: %Circle = name_ref self, %self\n// CHECK:STDOUT:   %x.ref: %Shape.elem = name_ref x, @Shape.%.loc5 [concrete = @Shape.%.loc5]\n// CHECK:STDOUT:   %.loc13_17.1: ref %Shape = class_element_access %self.ref.loc13_13, element0\n// CHECK:STDOUT:   %.loc13_17.2: ref %Shape = converted %self.ref.loc13_13, %.loc13_17.1\n// CHECK:STDOUT:   %.loc13_17.3: ref %i32 = class_element_access %.loc13_17.2, element0\n// CHECK:STDOUT:   %self.ref.loc13_21: %Circle = name_ref self, %self\n// CHECK:STDOUT:   %y.ref: %Shape.elem = name_ref y, @Shape.%.loc6 [concrete = @Shape.%.loc6]\n// CHECK:STDOUT:   %.loc13_25.1: ref %Shape = class_element_access %self.ref.loc13_21, element0\n// CHECK:STDOUT:   %.loc13_25.2: ref %Shape = converted %self.ref.loc13_21, %.loc13_25.1\n// CHECK:STDOUT:   %.loc13_25.3: ref %i32 = class_element_access %.loc13_25.2, element1\n// CHECK:STDOUT:   %.loc13_27.1: %tuple.type.d07 = tuple_literal (%.loc13_17.3, %.loc13_25.3)\n// CHECK:STDOUT:   %.loc13_17.4: %i32 = acquire_value %.loc13_17.3\n// CHECK:STDOUT:   %impl.elem0.loc13_17: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc13_17.1: <bound method> = bound_method %.loc13_17.4, %impl.elem0.loc13_17\n// CHECK:STDOUT:   %specific_fn.loc13_17: <specific function> = specific_function %impl.elem0.loc13_17, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_17.2: <bound method> = bound_method %.loc13_17.4, %specific_fn.loc13_17\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc13_17: init %i32 = call %bound_method.loc13_17.2(%.loc13_17.4)\n// CHECK:STDOUT:   %tuple.elem0: ref %i32 = tuple_access %return.param, element0\n// CHECK:STDOUT:   %.loc13_27.2: init %i32 to %tuple.elem0 = in_place_init %Int.as.Copy.impl.Op.call.loc13_17\n// CHECK:STDOUT:   %.loc13_25.4: %i32 = acquire_value %.loc13_25.3\n// CHECK:STDOUT:   %impl.elem0.loc13_25: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc13_25.1: <bound method> = bound_method %.loc13_25.4, %impl.elem0.loc13_25\n// CHECK:STDOUT:   %specific_fn.loc13_25: <specific function> = specific_function %impl.elem0.loc13_25, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_25.2: <bound method> = bound_method %.loc13_25.4, %specific_fn.loc13_25\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc13_25: init %i32 = call %bound_method.loc13_25.2(%.loc13_25.4)\n// CHECK:STDOUT:   %tuple.elem1: ref %i32 = tuple_access %return.param, element1\n// CHECK:STDOUT:   %.loc13_27.3: init %i32 to %tuple.elem1 = in_place_init %Int.as.Copy.impl.Op.call.loc13_25\n// CHECK:STDOUT:   %.loc13_27.4: init %tuple.type.d07 to %return.param = tuple_init (%.loc13_27.2, %.loc13_27.3)\n// CHECK:STDOUT:   %.loc13_28: init %tuple.type.d07 = converted %.loc13_27.1, %.loc13_27.4\n// CHECK:STDOUT:   return %.loc13_28 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- shadowing_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %A.F.type: type = fn_type @A.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %A.F: %A.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.elem: type = unbound_element_type %B, %A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %B.F.type: type = fn_type @B.F [concrete]\n// CHECK:STDOUT:   %B.F: %B.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.5af: type = struct_type {.base: %A} [concrete]\n// CHECK:STDOUT:   %complete_type.0d1: <witness> = complete_type_witness %struct_type.base.5af [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %B [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %C.G.type: type = fn_type @C.G [concrete]\n// CHECK:STDOUT:   %C.G: %C.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.64a: type = struct_type {.base: %B} [concrete]\n// CHECK:STDOUT:   %complete_type.021: <witness> = complete_type_witness %struct_type.base.64a [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %A.F.decl: %A.F.type = fn_decl @A.F [concrete = constants.%A.F] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .F = %A.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc9: %B.elem = base_decl %A.ref, element0 [concrete]\n// CHECK:STDOUT:   %B.F.decl: %B.F.type = fn_decl @B.F [concrete = constants.%B.F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc10: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.5af [concrete = constants.%complete_type.0d1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .F [private] = %B.F.decl\n// CHECK:STDOUT:   extend %A.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc14: %C.elem = base_decl %B.ref, element0 [concrete]\n// CHECK:STDOUT:   %C.G.decl: %C.G.type = fn_decl @C.G [concrete = constants.%C.G] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.7c7 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.7c7 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_26.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc15_26.2: type = converted %.loc15_26.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc15_26.3: Core.Form = init_form %.loc15_26.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %self.param: %C = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %self: %C = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param1\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.64a [concrete = constants.%complete_type.021]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .B = <poisoned>\n// CHECK:STDOUT:   .base = %.loc14\n// CHECK:STDOUT:   .G = %C.G.decl\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend %B.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.F() -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.G(%self.param: %C) -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %C = name_ref self, %self\n// CHECK:STDOUT:   %F.ref: %A.F.type = name_ref F, @A.%A.F.decl [concrete = constants.%A.F]\n// CHECK:STDOUT:   %A.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   return %A.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- inherited_member_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %int_5.64b: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_5.0f6: %i32 = int_value 5 [concrete]\n// CHECK:STDOUT:   %A.SomeProtectedFunction.type: type = fn_type @A.SomeProtectedFunction [concrete]\n// CHECK:STDOUT:   %A.SomeProtectedFunction: %A.SomeProtectedFunction.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.elem: type = unbound_element_type %B, %A [concrete]\n// CHECK:STDOUT:   %B.G.type: type = fn_type @B.G [concrete]\n// CHECK:STDOUT:   %B.G: %B.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B.H.type: type = fn_type @B.H [concrete]\n// CHECK:STDOUT:   %B.H: %B.H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %A} [concrete]\n// CHECK:STDOUT:   %complete_type.0d1: <witness> = complete_type_witness %struct_type.base [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %SOME_CONSTANT.patt: %pattern_type.7ce = value_binding_pattern SOME_CONSTANT [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc5_38.1: <bound method> = bound_method %int_5, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc5_38.2: <bound method> = bound_method %int_5, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc5_38.2(%int_5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc5_38.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc5_38.2: %i32 = converted %int_5, %.loc5_38.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %SOME_CONSTANT: %i32 = value_binding SOME_CONSTANT, %.loc5_38.2\n// CHECK:STDOUT:   %A.SomeProtectedFunction.decl: %A.SomeProtectedFunction.type = fn_decl @A.SomeProtectedFunction [concrete = constants.%A.SomeProtectedFunction] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .SOME_CONSTANT [protected] = %SOME_CONSTANT\n// CHECK:STDOUT:   .SomeProtectedFunction [protected] = %A.SomeProtectedFunction.decl\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc12: %B.elem = base_decl %A.ref, element0 [concrete]\n// CHECK:STDOUT:   %B.G.decl: %B.G.type = fn_decl @B.G [concrete = constants.%B.G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc14: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.H.decl: %B.H.type = fn_decl @B.H [concrete = constants.%B.H] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc18: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base [concrete = constants.%complete_type.0d1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .base = %.loc12\n// CHECK:STDOUT:   .G = %B.G.decl\n// CHECK:STDOUT:   .H = %B.H.decl\n// CHECK:STDOUT:   extend %A.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.SomeProtectedFunction() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc7_13.1: <bound method> = bound_method %int_5, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_13.2: <bound method> = bound_method %int_5, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc7_13.2(%int_5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc7: init %i32 = converted %int_5, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   return %.loc7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %SOME_CONSTANT.ref: %i32 = name_ref SOME_CONSTANT, @A.%SOME_CONSTANT\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc15_13.1: <bound method> = bound_method %SOME_CONSTANT.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_13.2: <bound method> = bound_method %SOME_CONSTANT.ref, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc15_13.2(%SOME_CONSTANT.ref)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.H() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %SomeProtectedFunction.ref: %A.SomeProtectedFunction.type = name_ref SomeProtectedFunction, @A.%A.SomeProtectedFunction.decl [concrete = constants.%A.SomeProtectedFunction]\n// CHECK:STDOUT:   %A.SomeProtectedFunction.call: init %i32 = call %SomeProtectedFunction.ref()\n// CHECK:STDOUT:   return %A.SomeProtectedFunction.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_inherited_private_field_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Shape: type = class_type @Shape [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Shape.elem: type = unbound_element_type %Shape, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.y: type = struct_type {.y: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.0f9: <witness> = complete_type_witness %struct_type.y [concrete]\n// CHECK:STDOUT:   %Square: type = class_type @Square [concrete]\n// CHECK:STDOUT:   %Square.elem: type = unbound_element_type %Square, %Shape [concrete]\n// CHECK:STDOUT:   %pattern_type.1d2: type = pattern_type %Square [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Square.GetPosition.type: type = fn_type @Square.GetPosition [concrete]\n// CHECK:STDOUT:   %Square.GetPosition: %Square.GetPosition.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.490: type = struct_type {.base: %Shape} [concrete]\n// CHECK:STDOUT:   %complete_type.560: <witness> = complete_type_witness %struct_type.base.490 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Shape = %Shape.decl\n// CHECK:STDOUT:     .Square = %Square.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Shape.decl: type = class_decl @Shape [concrete = constants.%Shape] {} {}\n// CHECK:STDOUT:   %Square.decl: type = class_decl @Square [concrete = constants.%Square] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Shape {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %Shape.elem = field_decl y, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.y [concrete = constants.%complete_type.0f9]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Shape\n// CHECK:STDOUT:   .y [private] = %.loc5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Square {\n// CHECK:STDOUT:   %Shape.ref: type = name_ref Shape, file.%Shape.decl [concrete = constants.%Shape]\n// CHECK:STDOUT:   %.loc9: %Square.elem = base_decl %Shape.ref, element0 [concrete]\n// CHECK:STDOUT:   %Square.GetPosition.decl: %Square.GetPosition.type = fn_decl @Square.GetPosition [concrete = constants.%Square.GetPosition] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.1d2 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.1d2 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc11: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: %Square = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Square [concrete = constants.%Square]\n// CHECK:STDOUT:     %self: %Square = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.490 [concrete = constants.%complete_type.560]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Square\n// CHECK:STDOUT:   .Shape = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .GetPosition = %Square.GetPosition.decl\n// CHECK:STDOUT:   .y = <poisoned>\n// CHECK:STDOUT:   extend %Shape.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Square.GetPosition(%self.param: %Square) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %Square = name_ref self, %self\n// CHECK:STDOUT:   %y.ref: <error> = name_ref y, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- noninstance_private_on_self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.G.type: type = fn_type @C.G [concrete]\n// CHECK:STDOUT:   %C.G: %C.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %C.F.decl: %C.F.type = fn_decl @C.F [concrete = constants.%C.F] {} {}\n// CHECK:STDOUT:   %C.G.decl: %C.G.type = fn_decl @C.G [concrete = constants.%C.G] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .F [private] = %C.F.decl\n// CHECK:STDOUT:   .G = %C.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref.loc7: %C.F.type = name_ref F, @C.%C.F.decl [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.call.loc7: init %empty_tuple.type = call %F.ref.loc7()\n// CHECK:STDOUT:   %F.ref.loc8: %C.F.type = name_ref F, @C.%C.F.decl [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.call.loc8: init %empty_tuple.type = call %F.ref.loc8()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- noninstance_protected_on_self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.G.type: type = fn_type @C.G [concrete]\n// CHECK:STDOUT:   %C.G: %C.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %C.F.decl: %C.F.type = fn_decl @C.F [concrete = constants.%C.F] {} {}\n// CHECK:STDOUT:   %C.G.decl: %C.G.type = fn_decl @C.G [concrete = constants.%C.G] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .F [protected] = %C.F.decl\n// CHECK:STDOUT:   .G = %C.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref.loc7: %C.F.type = name_ref F, @C.%C.F.decl [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.call.loc7: init %empty_tuple.type = call %F.ref.loc7()\n// CHECK:STDOUT:   %F.ref.loc8: %C.F.type = name_ref F, @C.%C.F.decl [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.call.loc8: init %empty_tuple.type = call %F.ref.loc8()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_noninstance_private_on_parent_qualified.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.F.type: type = fn_type @B.F [concrete]\n// CHECK:STDOUT:   %B.F: %B.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %B [concrete]\n// CHECK:STDOUT:   %C.G.type: type = fn_type @C.G [concrete]\n// CHECK:STDOUT:   %C.G: %C.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.64a: type = struct_type {.base: %B} [concrete]\n// CHECK:STDOUT:   %complete_type.021: <witness> = complete_type_witness %struct_type.base.64a [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %B.F.decl: %B.F.type = fn_decl @B.F [concrete = constants.%B.F] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .F [private] = %B.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc9: %C.elem = base_decl %B.ref, element0 [concrete]\n// CHECK:STDOUT:   %C.G.decl: %C.G.type = fn_decl @C.G [concrete = constants.%C.G] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.64a [concrete = constants.%complete_type.021]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .B = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .G = %C.G.decl\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend %B.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref: <error> = name_ref F, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_noninstance_private_on_parent_unqualified.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %A.Fa.type: type = fn_type @A.Fa [concrete]\n// CHECK:STDOUT:   %A.Fa: %A.Fa.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.elem: type = unbound_element_type %B, %A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %int_86.bd3: Core.IntLiteral = int_value 86 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_86.bd3, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_86.bd3, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_86.261: %i32 = int_value 86 [concrete]\n// CHECK:STDOUT:   %B.Fb.type: type = fn_type @B.Fb [concrete]\n// CHECK:STDOUT:   %B.Fb: %B.Fb.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.5af: type = struct_type {.base: %A} [concrete]\n// CHECK:STDOUT:   %complete_type.0d1: <witness> = complete_type_witness %struct_type.base.5af [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %B [concrete]\n// CHECK:STDOUT:   %C.G1.type: type = fn_type @C.G1 [concrete]\n// CHECK:STDOUT:   %C.G1: %C.G1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.G2.type: type = fn_type @C.G2 [concrete]\n// CHECK:STDOUT:   %C.G2: %C.G2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.G3.type: type = fn_type @C.G3 [concrete]\n// CHECK:STDOUT:   %C.G3: %C.G3.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.64a: type = struct_type {.base: %B} [concrete]\n// CHECK:STDOUT:   %complete_type.021: <witness> = complete_type_witness %struct_type.base.64a [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %A.Fa.decl: %A.Fa.type = fn_decl @A.Fa [concrete = constants.%A.Fa] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .Fa [private] = %A.Fa.decl\n// CHECK:STDOUT:   .SOME_PRIVATE_CONSTANT = <poisoned>\n// CHECK:STDOUT:   .Fb = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc9: %B.elem = base_decl %A.ref, element0 [concrete]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %SOME_PRIVATE_CONSTANT.patt: %pattern_type.7ce = value_binding_pattern SOME_PRIVATE_CONSTANT [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_86: Core.IntLiteral = int_value 86 [concrete = constants.%int_86.bd3]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc11_44.1: <bound method> = bound_method %int_86, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc11_44.2: <bound method> = bound_method %int_86, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc11_44.2(%int_86) [concrete = constants.%int_86.261]\n// CHECK:STDOUT:   %.loc11_44.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_86.261]\n// CHECK:STDOUT:   %.loc11_44.2: %i32 = converted %int_86, %.loc11_44.1 [concrete = constants.%int_86.261]\n// CHECK:STDOUT:   %SOME_PRIVATE_CONSTANT: %i32 = value_binding SOME_PRIVATE_CONSTANT, %.loc11_44.2\n// CHECK:STDOUT:   %B.Fb.decl: %B.Fb.type = fn_decl @B.Fb [concrete = constants.%B.Fb] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.5af [concrete = constants.%complete_type.0d1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .SOME_PRIVATE_CONSTANT [private] = %SOME_PRIVATE_CONSTANT\n// CHECK:STDOUT:   .Fb [private] = %B.Fb.decl\n// CHECK:STDOUT:   .Fa = <poisoned>\n// CHECK:STDOUT:   extend %A.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc16: %C.elem = base_decl %B.ref, element0 [concrete]\n// CHECK:STDOUT:   %C.G1.decl: %C.G1.type = fn_decl @C.G1 [concrete = constants.%C.G1] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc25: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.G2.decl: %C.G2.type = fn_decl @C.G2 [concrete = constants.%C.G2] {} {}\n// CHECK:STDOUT:   %C.G3.decl: %C.G3.type = fn_decl @C.G3 [concrete = constants.%C.G3] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.64a [concrete = constants.%complete_type.021]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .B = <poisoned>\n// CHECK:STDOUT:   .base = %.loc16\n// CHECK:STDOUT:   .G1 = %C.G1.decl\n// CHECK:STDOUT:   .G2 = %C.G2.decl\n// CHECK:STDOUT:   .G3 = %C.G3.decl\n// CHECK:STDOUT:   .SOME_PRIVATE_CONSTANT = <poisoned>\n// CHECK:STDOUT:   .Fa = <poisoned>\n// CHECK:STDOUT:   .Fb = <poisoned>\n// CHECK:STDOUT:   extend %B.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.Fa() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.Fb() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.G1() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %SOME_PRIVATE_CONSTANT.ref: <error> = name_ref SOME_PRIVATE_CONSTANT, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.G2() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Fa.ref: <error> = name_ref Fa, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.G3() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Fb.ref: <error> = name_ref Fb, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- noninstance_protected_on_parent.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.F.type: type = fn_type @B.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %B.F: %B.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %B [concrete]\n// CHECK:STDOUT:   %C.G.type: type = fn_type @C.G [concrete]\n// CHECK:STDOUT:   %C.G: %C.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.64a: type = struct_type {.base: %B} [concrete]\n// CHECK:STDOUT:   %complete_type.021: <witness> = complete_type_witness %struct_type.base.64a [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %B.F.decl: %B.F.type = fn_decl @B.F [concrete = constants.%B.F] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .F [protected] = %B.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc9: %C.elem = base_decl %B.ref, element0 [concrete]\n// CHECK:STDOUT:   %C.G.decl: %C.G.type = fn_decl @C.G [concrete = constants.%C.G] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.64a [concrete = constants.%complete_type.021]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .B = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .G = %C.G.decl\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend %B.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref: %B.F.type = name_ref F, @B.%B.F.decl [concrete = constants.%B.F]\n// CHECK:STDOUT:   %B.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_non_inherited_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %int_5.64b: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_5.0f6: %i32 = int_value 5 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Internal: type = class_type @Internal [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.elem: type = unbound_element_type %B, %Internal [concrete]\n// CHECK:STDOUT:   %B.G.type: type = fn_type @B.G [concrete]\n// CHECK:STDOUT:   %B.G: %B.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %B.SomeFunc.type: type = fn_type @B.SomeFunc [concrete]\n// CHECK:STDOUT:   %B.SomeFunc: %B.SomeFunc.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.internal.f18: type = struct_type {.internal: %Internal} [concrete]\n// CHECK:STDOUT:   %complete_type.ade: <witness> = complete_type_witness %struct_type.internal.f18 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .Internal = %Internal.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %Internal.decl: type = class_decl @Internal [concrete = constants.%Internal] {} {}\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %SOME_PROTECTED_CONSTANT.patt: %pattern_type.7ce = value_binding_pattern SOME_PROTECTED_CONSTANT [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_5.loc5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0.loc5: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc5_48.1: <bound method> = bound_method %int_5.loc5, %impl.elem0.loc5 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc5: <specific function> = specific_function %impl.elem0.loc5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc5_48.2: <bound method> = bound_method %int_5.loc5, %specific_fn.loc5 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5: init %i32 = call %bound_method.loc5_48.2(%int_5.loc5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc5_48.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc5_48.2: %i32 = converted %int_5.loc5, %.loc5_48.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %SOME_PROTECTED_CONSTANT: %i32 = value_binding SOME_PROTECTED_CONSTANT, %.loc5_48.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %SOME_PRIVATE_CONSTANT.patt: %pattern_type.7ce = value_binding_pattern SOME_PRIVATE_CONSTANT [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_5.loc6: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0.loc6: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc6_44.1: <bound method> = bound_method %int_5.loc6, %impl.elem0.loc6 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_44.2: <bound method> = bound_method %int_5.loc6, %specific_fn.loc6 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %i32 = call %bound_method.loc6_44.2(%int_5.loc6) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc6_44.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc6_44.2: %i32 = converted %int_5.loc6, %.loc6_44.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %SOME_PRIVATE_CONSTANT: %i32 = value_binding SOME_PRIVATE_CONSTANT, %.loc6_44.2\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .SOME_PROTECTED_CONSTANT [protected] = %SOME_PROTECTED_CONSTANT\n// CHECK:STDOUT:   .SOME_PRIVATE_CONSTANT [private] = %SOME_PRIVATE_CONSTANT\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Internal {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %INTERNAL_CONSTANT.patt: %pattern_type.7ce = value_binding_pattern INTERNAL_CONSTANT [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc10_42.1: <bound method> = bound_method %int_5, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_42.2: <bound method> = bound_method %int_5, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc10_42.2(%int_5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc10_42.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc10_42.2: %i32 = converted %int_5, %.loc10_42.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %INTERNAL_CONSTANT: %i32 = value_binding INTERNAL_CONSTANT, %.loc10_42.2\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Internal\n// CHECK:STDOUT:   .INTERNAL_CONSTANT [protected] = %INTERNAL_CONSTANT\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %Internal.ref: type = name_ref Internal, file.%Internal.decl [concrete = constants.%Internal]\n// CHECK:STDOUT:   %.loc14: %B.elem = field_decl internal, element0 [concrete]\n// CHECK:STDOUT:   %B.G.decl: %B.G.type = fn_decl @B.G [concrete = constants.%B.G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.SomeFunc.decl: %B.SomeFunc.type = fn_decl @B.SomeFunc [concrete = constants.%B.SomeFunc] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.1f4 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.1f4 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc36: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: %B = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%B [concrete = constants.%B]\n// CHECK:STDOUT:     %self: %B = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.internal.f18 [concrete = constants.%complete_type.ade]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .Internal = <poisoned>\n// CHECK:STDOUT:   .internal [private] = %.loc14\n// CHECK:STDOUT:   .G = %B.G.decl\n// CHECK:STDOUT:   .SomeFunc = %B.SomeFunc.decl\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref.loc24: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %SOME_PRIVATE_CONSTANT.ref: <error> = name_ref SOME_PRIVATE_CONSTANT, <error> [concrete = <error>]\n// CHECK:STDOUT:   %A.ref.loc33: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %SOME_PROTECTED_CONSTANT.ref: <error> = name_ref SOME_PROTECTED_CONSTANT, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.SomeFunc(%self.param: %B) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %B = name_ref self, %self\n// CHECK:STDOUT:   %internal.ref: %B.elem = name_ref internal, @B.%.loc14 [concrete = @B.%.loc14]\n// CHECK:STDOUT:   %.loc44_16.1: ref %Internal = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc44_16.2: %Internal = acquire_value %.loc44_16.1\n// CHECK:STDOUT:   %INTERNAL_CONSTANT.ref: <error> = name_ref INTERNAL_CONSTANT, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_compound_member_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %A.elem: type = unbound_element_type %A, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.elem: type = unbound_element_type %B, %A [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %B.F.type: type = fn_type @B.F [concrete]\n// CHECK:STDOUT:   %B.F: %B.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.5af: type = struct_type {.base: %A} [concrete]\n// CHECK:STDOUT:   %complete_type.0d1: <witness> = complete_type_witness %struct_type.base.5af [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %A.elem = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x [concrete = constants.%complete_type.1ec]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .x [private] = %.loc5\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc9: %B.elem = base_decl %A.ref, element0 [concrete]\n// CHECK:STDOUT:   %B.F.decl: %B.F.type = fn_decl @B.F [concrete = constants.%B.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.1f4 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.1f4 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %B = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%B [concrete = constants.%B]\n// CHECK:STDOUT:     %self: %B = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.5af [concrete = constants.%complete_type.0d1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .F = %B.F.decl\n// CHECK:STDOUT:   extend %A.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.F(%self.param: %B) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %B = name_ref self, %self\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %x.ref: <error> = name_ref x, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- inherited_compound_member_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %A.elem: type = unbound_element_type %A, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.elem: type = unbound_element_type %B, %A [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %B.F.type: type = fn_type @B.F [concrete]\n// CHECK:STDOUT:   %B.F: %B.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.5af: type = struct_type {.base: %A} [concrete]\n// CHECK:STDOUT:   %complete_type.0d1: <witness> = complete_type_witness %struct_type.base.5af [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %A.elem = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x [concrete = constants.%complete_type.1ec]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .x [protected] = %.loc5\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc9: %B.elem = base_decl %A.ref, element0 [concrete]\n// CHECK:STDOUT:   %B.F.decl: %B.F.type = fn_decl @B.F [concrete = constants.%B.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.1f4 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.1f4 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %B = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%B [concrete = constants.%B]\n// CHECK:STDOUT:     %self: %B = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.5af [concrete = constants.%complete_type.0d1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .F = %B.F.decl\n// CHECK:STDOUT:   extend %A.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.F(%self.param: %B) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %B = name_ref self, %self\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %x.ref: %A.elem = name_ref x, @A.%.loc5 [concrete = @A.%.loc5]\n// CHECK:STDOUT:   %.loc12_9.1: ref %A = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc12_9.2: ref %A = converted %self.ref, %.loc12_9.1\n// CHECK:STDOUT:   %.loc12_9.3: ref %i32 = class_element_access %.loc12_9.2, element0\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/access/method_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/access/method_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/access/method_access.carbon\n\n// --- fail_multiple_bindings.carbon\n\nclass X {\n  fn F[self: Self]();\n}\n\nfn G(x: X) {\n  // TODO: Produce a better diagnostic for this case.\n  // CHECK:STDERR: fail_multiple_bindings.carbon:[[@LINE+4]]:3: error: member name of type `<bound method>` in compound member access is not an instance member or an interface member [CompoundMemberAccessDoesNotUseBase]\n  // CHECK:STDERR:   x.(x.F)();\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  x.(x.F)();\n}\n\n// CHECK:STDOUT: --- fail_multiple_bindings.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %X [concrete]\n// CHECK:STDOUT:   %X.F.type: type = fn_type @X.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %X.F: %X.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .X = %X.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %X.decl: type = class_decl @X [concrete = constants.%X] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %x.patt: %pattern_type = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %X = value_param call_param0\n// CHECK:STDOUT:     %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %x: %X = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @X {\n// CHECK:STDOUT:   %X.F.decl: %X.F.type = fn_decl @X.F [concrete = constants.%X.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %X = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%X [concrete = constants.%X]\n// CHECK:STDOUT:     %self: %X = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%X\n// CHECK:STDOUT:   .F = %X.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @X.F(%self.param: %X);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%x.param: %X) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %x.ref.loc12_3: %X = name_ref x, %x\n// CHECK:STDOUT:   %x.ref.loc12_6: %X = name_ref x, %x\n// CHECK:STDOUT:   %F.ref: %X.F.type = name_ref F, @X.%X.F.decl [concrete = constants.%X.F]\n// CHECK:STDOUT:   %X.F.bound: <bound method> = bound_method %x.ref.loc12_6, %F.ref\n// CHECK:STDOUT:   %X.F.call: init %empty_tuple.type = call %X.F.bound(%x.ref.loc12_6)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/access/todo_access_modifiers.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/access/todo_access_modifiers.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/access/todo_access_modifiers.carbon\n\n// TODO: Test calls to these (member access control is not yet implemented).\nclass Access {\n  private fn F();\n\n  protected fn G();\n\n  private var k: i32;\n\n  protected var l: i32;\n}\n\n// CHECK:STDOUT: --- todo_access_modifiers.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Access: type = class_type @Access [concrete]\n// CHECK:STDOUT:   %Access.F.type: type = fn_type @Access.F [concrete]\n// CHECK:STDOUT:   %Access.F: %Access.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Access.G.type: type = fn_type @Access.G [concrete]\n// CHECK:STDOUT:   %Access.G: %Access.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Access.elem: type = unbound_element_type %Access, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.k.l: type = struct_type {.k: %i32, .l: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.48a: <witness> = complete_type_witness %struct_type.k.l [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Access = %Access.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Access.decl: type = class_decl @Access [concrete = constants.%Access] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Access {\n// CHECK:STDOUT:   %Access.F.decl: %Access.F.type = fn_decl @Access.F [concrete = constants.%Access.F] {} {}\n// CHECK:STDOUT:   %Access.G.decl: %Access.G.type = fn_decl @Access.G [concrete = constants.%Access.G] {} {}\n// CHECK:STDOUT:   %i32.loc21: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc21: %Access.elem = field_decl k, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc23: %Access.elem = field_decl l, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.k.l [concrete = constants.%complete_type.48a]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Access\n// CHECK:STDOUT:   .F [private] = %Access.F.decl\n// CHECK:STDOUT:   .G [protected] = %Access.G.decl\n// CHECK:STDOUT:   .k [private] = %.loc21\n// CHECK:STDOUT:   .l [protected] = %.loc23\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Access.F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Access.G();\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/adapt.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/adapt.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/adapt.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass SomeClass {\n  var a: i32;\n  var b: i32;\n}\n\nclass SomeClassAdapter {\n  adapt SomeClass;\n}\n\nclass StructAdapter {\n  adapt {.a: i32, .b: i32};\n}\n\n// --- fail_not_extend.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Adapted {\n  fn F();\n}\n\nclass AdaptNotExtend {\n  adapt Adapted;\n}\n\nfn F(a: AdaptNotExtend) {\n  // `Adapted` is not extended, so lookup for `F` finds nothing.\n  // CHECK:STDERR: fail_not_extend.carbon:[[@LINE+4]]:3: error: member name `F` not found in `AdaptNotExtend` [MemberNameNotFoundInInstScope]\n  // CHECK:STDERR:   a.F();\n  // CHECK:STDERR:   ^~~\n  // CHECK:STDERR:\n  a.F();\n}\n\n// --- fail_misplaced.carbon\n\nfn F() {\n  // CHECK:STDERR: fail_misplaced.carbon:[[@LINE+4]]:3: error: `adapt` declaration outside class [ClassSpecificDeclOutsideClass]\n  // CHECK:STDERR:   adapt i32;\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR:\n  adapt i32;\n}\n\ninterface I {\n  // CHECK:STDERR: fail_misplaced.carbon:[[@LINE+4]]:3: error: `adapt` declaration outside class [ClassSpecificDeclOutsideClass]\n  // CHECK:STDERR:   adapt i32;\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR:\n  adapt i32;\n}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %SomeClass: type = class_type @SomeClass [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %SomeClass.elem: type = unbound_element_type %SomeClass, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: %i32, .b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.705: <witness> = complete_type_witness %struct_type.a.b [concrete]\n// CHECK:STDOUT:   %SomeClassAdapter: type = class_type @SomeClassAdapter [concrete]\n// CHECK:STDOUT:   %StructAdapter: type = class_type @StructAdapter [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .SomeClass = %SomeClass.decl\n// CHECK:STDOUT:     .SomeClassAdapter = %SomeClassAdapter.decl\n// CHECK:STDOUT:     .StructAdapter = %StructAdapter.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %SomeClass.decl: type = class_decl @SomeClass [concrete = constants.%SomeClass] {} {}\n// CHECK:STDOUT:   %SomeClassAdapter.decl: type = class_decl @SomeClassAdapter [concrete = constants.%SomeClassAdapter] {} {}\n// CHECK:STDOUT:   %StructAdapter.decl: type = class_decl @StructAdapter [concrete = constants.%StructAdapter] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SomeClass {\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %SomeClass.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc6: %SomeClass.elem = field_decl b, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SomeClass\n// CHECK:STDOUT:   .a = %.loc5\n// CHECK:STDOUT:   .b = %.loc6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SomeClassAdapter {\n// CHECK:STDOUT:   %SomeClass.ref: type = name_ref SomeClass, file.%SomeClass.decl [concrete = constants.%SomeClass]\n// CHECK:STDOUT:   adapt_decl %SomeClass.ref [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SomeClassAdapter\n// CHECK:STDOUT:   .SomeClass = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @StructAdapter {\n// CHECK:STDOUT:   %i32.loc14_14: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %i32.loc14_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: %i32, .b: %i32} [concrete = constants.%struct_type.a.b]\n// CHECK:STDOUT:   adapt_decl %struct_type.a.b [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%StructAdapter\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_not_extend.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Adapted: type = class_type @Adapted [concrete]\n// CHECK:STDOUT:   %Adapted.F.type: type = fn_type @Adapted.F [concrete]\n// CHECK:STDOUT:   %Adapted.F: %Adapted.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %AdaptNotExtend: type = class_type @AdaptNotExtend [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %AdaptNotExtend [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Adapted = %Adapted.decl\n// CHECK:STDOUT:     .AdaptNotExtend = %AdaptNotExtend.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Adapted.decl: type = class_decl @Adapted [concrete = constants.%Adapted] {} {}\n// CHECK:STDOUT:   %AdaptNotExtend.decl: type = class_decl @AdaptNotExtend [concrete = constants.%AdaptNotExtend] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %AdaptNotExtend = value_param call_param0\n// CHECK:STDOUT:     %AdaptNotExtend.ref: type = name_ref AdaptNotExtend, file.%AdaptNotExtend.decl [concrete = constants.%AdaptNotExtend]\n// CHECK:STDOUT:     %a: %AdaptNotExtend = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Adapted {\n// CHECK:STDOUT:   %Adapted.F.decl: %Adapted.F.type = fn_decl @Adapted.F [concrete = constants.%Adapted.F] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Adapted\n// CHECK:STDOUT:   .F = %Adapted.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptNotExtend {\n// CHECK:STDOUT:   %Adapted.ref: type = name_ref Adapted, file.%Adapted.decl [concrete = constants.%Adapted]\n// CHECK:STDOUT:   adapt_decl %Adapted.ref [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptNotExtend\n// CHECK:STDOUT:   .Adapted = <poisoned>\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Adapted.F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %AdaptNotExtend) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %AdaptNotExtend = name_ref a, %a\n// CHECK:STDOUT:   %F.ref: <error> = name_ref F, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_misplaced.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/adapt_copy.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/uint.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/adapt_copy.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/adapt_copy.carbon\n\n// TODO: Decide whether an adapter for a copyable type is copyable. As\n// demonstrated in this test, our behavior is currently inconsistent.\n\n// --- fail_adapt_copyable.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass AdaptCopyable {\n  adapt i32;\n}\n\nfn F(c: AdaptCopyable) -> AdaptCopyable {\n  // CHECK:STDERR: fail_adapt_copyable.carbon:[[@LINE+7]]:26: error: cannot copy value of type `AdaptCopyable` [CopyOfUncopyableType]\n  // CHECK:STDERR:   var d: AdaptCopyable = c;\n  // CHECK:STDERR:                          ^\n  // CHECK:STDERR: fail_adapt_copyable.carbon:[[@LINE+4]]:26: note: type `AdaptCopyable` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var d: AdaptCopyable = c;\n  // CHECK:STDERR:                          ^\n  // CHECK:STDERR:\n  var d: AdaptCopyable = c;\n  // CHECK:STDERR: fail_adapt_copyable.carbon:[[@LINE+7]]:10: error: cannot copy value of type `AdaptCopyable` [CopyOfUncopyableType]\n  // CHECK:STDERR:   return d;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR: fail_adapt_copyable.carbon:[[@LINE+4]]:10: note: type `AdaptCopyable` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return d;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR:\n  return d;\n}\n\nfn InTuple(c: (AdaptCopyable, u32)) -> (AdaptCopyable, u32) {\n  // CHECK:STDERR: fail_adapt_copyable.carbon:[[@LINE+7]]:33: error: cannot copy value of type `AdaptCopyable` [CopyOfUncopyableType]\n  // CHECK:STDERR:   var d: (AdaptCopyable, u32) = c;\n  // CHECK:STDERR:                                 ^\n  // CHECK:STDERR: fail_adapt_copyable.carbon:[[@LINE+4]]:33: note: type `AdaptCopyable` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var d: (AdaptCopyable, u32) = c;\n  // CHECK:STDERR:                                 ^\n  // CHECK:STDERR:\n  var d: (AdaptCopyable, u32) = c;\n  // CHECK:STDERR: fail_adapt_copyable.carbon:[[@LINE+7]]:10: error: cannot copy value of type `AdaptCopyable` [CopyOfUncopyableType]\n  // CHECK:STDERR:   return d;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR: fail_adapt_copyable.carbon:[[@LINE+4]]:10: note: type `AdaptCopyable` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return d;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR:\n  return d;\n}\n\n// --- adapt_copyable_tuple.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass AdaptTuple {\n  adapt (i32, i32);\n}\n\nfn F(c: AdaptTuple) -> AdaptTuple {\n  var d: AdaptTuple = c;\n  return d;\n}\n\nfn InTuple(c: (AdaptTuple, u32)) -> (AdaptTuple, u32) {\n  var d: (AdaptTuple, u32) = c;\n  return d;\n}\n\n// --- fail_adapt_not_copyable.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Noncopyable {\n  // TODO: Ensure this remains non-copyable once we have rules for class copyability.\n}\n\nclass AdaptNoncopyable {\n  adapt Noncopyable;\n}\n\nfn G(a: AdaptNoncopyable) -> AdaptNoncopyable {\n  // CHECK:STDERR: fail_adapt_not_copyable.carbon:[[@LINE+7]]:29: error: cannot copy value of type `AdaptNoncopyable` [CopyOfUncopyableType]\n  // CHECK:STDERR:   var b: AdaptNoncopyable = a;\n  // CHECK:STDERR:                             ^\n  // CHECK:STDERR: fail_adapt_not_copyable.carbon:[[@LINE+4]]:29: note: type `AdaptNoncopyable` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var b: AdaptNoncopyable = a;\n  // CHECK:STDERR:                             ^\n  // CHECK:STDERR:\n  var b: AdaptNoncopyable = a;\n  // CHECK:STDERR: fail_adapt_not_copyable.carbon:[[@LINE+7]]:10: error: cannot copy value of type `AdaptNoncopyable` [CopyOfUncopyableType]\n  // CHECK:STDERR:   return b;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR: fail_adapt_not_copyable.carbon:[[@LINE+4]]:10: note: type `AdaptNoncopyable` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return b;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR:\n  return b;\n}\n\n// --- fail_adapt_not_copyable_indirect.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Noncopyable {\n  // TODO: Ensure this remains non-copyable once we have rules for class copyability.\n}\n\nclass AdaptNoncopyableIndirect {\n  adapt (i32, Noncopyable, i32);\n}\n\nfn H(a: AdaptNoncopyableIndirect) -> AdaptNoncopyableIndirect {\n  // CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+10]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]\n  // CHECK:STDERR:   var b: AdaptNoncopyableIndirect = a;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+7]]:3: note: type `Noncopyable` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var b: AdaptNoncopyableIndirect = a;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+4]]:37: note: in copy of `AdaptNoncopyableIndirect` [InCopy]\n  // CHECK:STDERR:   var b: AdaptNoncopyableIndirect = a;\n  // CHECK:STDERR:                                     ^\n  // CHECK:STDERR:\n  var b: AdaptNoncopyableIndirect = a;\n  // CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+10]]:3: error: cannot copy value of type `Noncopyable` [CopyOfUncopyableType]\n  // CHECK:STDERR:   return b;\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+7]]:3: note: type `Noncopyable` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return b;\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_adapt_not_copyable_indirect.carbon:[[@LINE+4]]:10: note: in copy of `AdaptNoncopyableIndirect` [InCopy]\n  // CHECK:STDERR:   return b;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR:\n  return b;\n}\n\n// --- adapt_copyable_struct.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass AdaptStruct {\n  adapt {.e: i32, .f: i32};\n}\n\nfn I(g: AdaptStruct) -> AdaptStruct {\n  var h: AdaptStruct = g;\n  return h;\n}\n\nfn InTuple(c: (AdaptStruct, u32)) -> (AdaptStruct, u32) {\n  var d: (AdaptStruct, u32) = c;\n  return d;\n}\n\n// CHECK:STDOUT: --- fail_adapt_copyable.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %AdaptCopyable: type = class_type @AdaptCopyable [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %pattern_type.e78: type = pattern_type %AdaptCopyable [concrete]\n// CHECK:STDOUT:   %.23e: Core.Form = init_form %AdaptCopyable [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc16 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %UInt.type: type = generic_class_type @UInt [concrete]\n// CHECK:STDOUT:   %UInt.generic: %UInt.type = struct_value () [concrete]\n// CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.fd0: %tuple.type.24b = tuple_value (%AdaptCopyable, %u32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d78: type = tuple_type (%AdaptCopyable, %u32) [concrete]\n// CHECK:STDOUT:   %pattern_type.87f: type = pattern_type %tuple.type.d78 [concrete]\n// CHECK:STDOUT:   %.5d1: Core.Form = init_form %tuple.type.d78 [concrete]\n// CHECK:STDOUT:   %InTuple.type: type = fn_type @InTuple [concrete]\n// CHECK:STDOUT:   %InTuple: %InTuple.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc35 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     .UInt = %Core.UInt\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:   %Core.UInt: %UInt.type = import_ref Core//prelude/parts/uint, UInt, loaded [concrete = constants.%UInt.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .AdaptCopyable = %AdaptCopyable.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .InTuple = %InTuple.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %AdaptCopyable.decl: type = class_decl @AdaptCopyable [concrete = constants.%AdaptCopyable] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.e78 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.e78 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.e78 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.e78 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptCopyable.ref.loc8_27: type = name_ref AdaptCopyable, file.%AdaptCopyable.decl [concrete = constants.%AdaptCopyable]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %AdaptCopyable.ref.loc8_27 [concrete = constants.%.23e]\n// CHECK:STDOUT:     %c.param: %AdaptCopyable = value_param call_param0\n// CHECK:STDOUT:     %AdaptCopyable.ref.loc8_9: type = name_ref AdaptCopyable, file.%AdaptCopyable.decl [concrete = constants.%AdaptCopyable]\n// CHECK:STDOUT:     %c: %AdaptCopyable = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %AdaptCopyable = out_param call_param1\n// CHECK:STDOUT:     %return: ref %AdaptCopyable = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %InTuple.decl: %InTuple.type = fn_decl @InTuple [concrete = constants.%InTuple] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.87f = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.87f = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.87f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.87f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptCopyable.ref.loc27_41: type = name_ref AdaptCopyable, file.%AdaptCopyable.decl [concrete = constants.%AdaptCopyable]\n// CHECK:STDOUT:     %u32.loc27_56: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:     %.loc27_59.1: %tuple.type.24b = tuple_literal (%AdaptCopyable.ref.loc27_41, %u32.loc27_56) [concrete = constants.%tuple.fd0]\n// CHECK:STDOUT:     %.loc27_59.2: type = converted %.loc27_59.1, constants.%tuple.type.d78 [concrete = constants.%tuple.type.d78]\n// CHECK:STDOUT:     %.loc27_59.3: Core.Form = init_form %.loc27_59.2 [concrete = constants.%.5d1]\n// CHECK:STDOUT:     %c.param: %tuple.type.d78 = value_param call_param0\n// CHECK:STDOUT:     %.loc27_34.1: type = splice_block %.loc27_34.3 [concrete = constants.%tuple.type.d78] {\n// CHECK:STDOUT:       %AdaptCopyable.ref.loc27_16: type = name_ref AdaptCopyable, file.%AdaptCopyable.decl [concrete = constants.%AdaptCopyable]\n// CHECK:STDOUT:       %u32.loc27_31: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:       %.loc27_34.2: %tuple.type.24b = tuple_literal (%AdaptCopyable.ref.loc27_16, %u32.loc27_31) [concrete = constants.%tuple.fd0]\n// CHECK:STDOUT:       %.loc27_34.3: type = converted %.loc27_34.2, constants.%tuple.type.d78 [concrete = constants.%tuple.type.d78]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %tuple.type.d78 = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %tuple.type.d78 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %tuple.type.d78 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptCopyable {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   adapt_decl %i32 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%i32.builtin [concrete = constants.%complete_type.f8a]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptCopyable\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %AdaptCopyable) -> out %return.param: %AdaptCopyable {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.e78 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.e78 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %AdaptCopyable = var %d.var_patt\n// CHECK:STDOUT:   %c.ref: %AdaptCopyable = name_ref c, %c\n// CHECK:STDOUT:   assign %d.var, <error>\n// CHECK:STDOUT:   %AdaptCopyable.ref.loc16: type = name_ref AdaptCopyable, file.%AdaptCopyable.decl [concrete = constants.%AdaptCopyable]\n// CHECK:STDOUT:   %d: ref %AdaptCopyable = ref_binding d, %d.var\n// CHECK:STDOUT:   %d.ref: ref %AdaptCopyable = name_ref d, %d\n// CHECK:STDOUT:   %.loc24: %AdaptCopyable = acquire_value %d.ref\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %d.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%d.var)\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc16(%self.param: ref %AdaptCopyable) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InTuple(%c.param: %tuple.type.d78) -> out %return.param: %tuple.type.d78 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.87f = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.87f = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %tuple.type.d78 = var %d.var_patt\n// CHECK:STDOUT:   %c.ref: %tuple.type.d78 = name_ref c, %c\n// CHECK:STDOUT:   %tuple.elem0.loc35: %AdaptCopyable = tuple_access %c.ref, element0\n// CHECK:STDOUT:   assign %d.var, <error>\n// CHECK:STDOUT:   %.loc35_29.1: type = splice_block %.loc35_29.3 [concrete = constants.%tuple.type.d78] {\n// CHECK:STDOUT:     %AdaptCopyable.ref.loc35: type = name_ref AdaptCopyable, file.%AdaptCopyable.decl [concrete = constants.%AdaptCopyable]\n// CHECK:STDOUT:     %u32.loc35: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:     %.loc35_29.2: %tuple.type.24b = tuple_literal (%AdaptCopyable.ref.loc35, %u32.loc35) [concrete = constants.%tuple.fd0]\n// CHECK:STDOUT:     %.loc35_29.3: type = converted %.loc35_29.2, constants.%tuple.type.d78 [concrete = constants.%tuple.type.d78]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %tuple.type.d78 = ref_binding d, %d.var\n// CHECK:STDOUT:   %d.ref: ref %tuple.type.d78 = name_ref d, %d\n// CHECK:STDOUT:   %tuple.elem0.loc43: ref %AdaptCopyable = tuple_access %d.ref, element0\n// CHECK:STDOUT:   %.loc43: %AdaptCopyable = acquire_value %tuple.elem0.loc43\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %d.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%d.var)\n// CHECK:STDOUT:   return <error> to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc35(%self.param: ref %tuple.type.d78) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- adapt_copyable_tuple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %AdaptTuple: type = class_type @AdaptTuple [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.95a: %tuple.type.24b = tuple_value (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %complete_type.65d: <witness> = complete_type_witness %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %pattern_type.6cd: type = pattern_type %AdaptTuple [concrete]\n// CHECK:STDOUT:   %.52a: Core.Form = init_form %AdaptTuple [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc9 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %UInt.type: type = generic_class_type @UInt [concrete]\n// CHECK:STDOUT:   %UInt.generic: %UInt.type = struct_value () [concrete]\n// CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.b75: %tuple.type.24b = tuple_value (%AdaptTuple, %u32) [concrete]\n// CHECK:STDOUT:   %tuple.type.3c7: type = tuple_type (%AdaptTuple, %u32) [concrete]\n// CHECK:STDOUT:   %pattern_type.6f4: type = pattern_type %tuple.type.3c7 [concrete]\n// CHECK:STDOUT:   %.709: Core.Form = init_form %tuple.type.3c7 [concrete]\n// CHECK:STDOUT:   %InTuple.type: type = fn_type @InTuple [concrete]\n// CHECK:STDOUT:   %InTuple: %InTuple.type = struct_value () [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.type.68f: type = fn_type @UInt.as.Copy.impl.Op, @UInt.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.576: %UInt.as.Copy.impl.Op.type.68f = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.514: <witness> = impl_witness imports.%Copy.impl_witness_table.bd0, @UInt.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.type.2fc: type = fn_type @UInt.as.Copy.impl.Op, @UInt.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.c10: %UInt.as.Copy.impl.Op.type.2fc = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.10b: %Copy.type = facet_value %u32, (%Copy.impl_witness.514) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.ad7: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.10b) [concrete]\n// CHECK:STDOUT:   %.38c: type = fn_type_with_self_type %Copy.WithSelf.Op.type.ad7, %Copy.facet.10b [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %UInt.as.Copy.impl.Op.c10, @UInt.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc14 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     .UInt = %Core.UInt\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:   %Core.UInt: %UInt.type = import_ref Core//prelude/parts/uint, UInt, loaded [concrete = constants.%UInt.generic]\n// CHECK:STDOUT:   %Core.import_ref.c3c: @UInt.as.Copy.impl.%UInt.as.Copy.impl.Op.type (%UInt.as.Copy.impl.Op.type.68f) = import_ref Core//prelude/parts/uint, loc{{\\d+_\\d+}}, loaded [symbolic = @UInt.as.Copy.impl.%UInt.as.Copy.impl.Op (constants.%UInt.as.Copy.impl.Op.576)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.bd0 = impl_witness_table (%Core.import_ref.c3c), @UInt.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .AdaptTuple = %AdaptTuple.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .InTuple = %InTuple.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %AdaptTuple.decl: type = class_decl @AdaptTuple [concrete = constants.%AdaptTuple] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.6cd = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.6cd = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.6cd = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.6cd = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptTuple.ref.loc8_24: type = name_ref AdaptTuple, file.%AdaptTuple.decl [concrete = constants.%AdaptTuple]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %AdaptTuple.ref.loc8_24 [concrete = constants.%.52a]\n// CHECK:STDOUT:     %c.param: %AdaptTuple = value_param call_param0\n// CHECK:STDOUT:     %AdaptTuple.ref.loc8_9: type = name_ref AdaptTuple, file.%AdaptTuple.decl [concrete = constants.%AdaptTuple]\n// CHECK:STDOUT:     %c: %AdaptTuple = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %AdaptTuple = out_param call_param1\n// CHECK:STDOUT:     %return: ref %AdaptTuple = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %InTuple.decl: %InTuple.type = fn_decl @InTuple [concrete = constants.%InTuple] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.6f4 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.6f4 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.6f4 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.6f4 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptTuple.ref.loc13_38: type = name_ref AdaptTuple, file.%AdaptTuple.decl [concrete = constants.%AdaptTuple]\n// CHECK:STDOUT:     %u32.loc13_50: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:     %.loc13_53.1: %tuple.type.24b = tuple_literal (%AdaptTuple.ref.loc13_38, %u32.loc13_50) [concrete = constants.%tuple.b75]\n// CHECK:STDOUT:     %.loc13_53.2: type = converted %.loc13_53.1, constants.%tuple.type.3c7 [concrete = constants.%tuple.type.3c7]\n// CHECK:STDOUT:     %.loc13_53.3: Core.Form = init_form %.loc13_53.2 [concrete = constants.%.709]\n// CHECK:STDOUT:     %c.param: %tuple.type.3c7 = value_param call_param0\n// CHECK:STDOUT:     %.loc13_31.1: type = splice_block %.loc13_31.3 [concrete = constants.%tuple.type.3c7] {\n// CHECK:STDOUT:       %AdaptTuple.ref.loc13_16: type = name_ref AdaptTuple, file.%AdaptTuple.decl [concrete = constants.%AdaptTuple]\n// CHECK:STDOUT:       %u32.loc13_28: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:       %.loc13_31.2: %tuple.type.24b = tuple_literal (%AdaptTuple.ref.loc13_16, %u32.loc13_28) [concrete = constants.%tuple.b75]\n// CHECK:STDOUT:       %.loc13_31.3: type = converted %.loc13_31.2, constants.%tuple.type.3c7 [concrete = constants.%tuple.type.3c7]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %tuple.type.3c7 = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %tuple.type.3c7 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %tuple.type.3c7 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptTuple {\n// CHECK:STDOUT:   %i32.loc5_10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %i32.loc5_15: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5_18: %tuple.type.24b = tuple_literal (%i32.loc5_10, %i32.loc5_15) [concrete = constants.%tuple.95a]\n// CHECK:STDOUT:   %.loc5_19: type = converted %.loc5_18, constants.%tuple.type.d07 [concrete = constants.%tuple.type.d07]\n// CHECK:STDOUT:   adapt_decl %.loc5_19 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%tuple.type.d07 [concrete = constants.%complete_type.65d]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptTuple\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %AdaptTuple) -> out %return.param: %AdaptTuple {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.6cd = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.6cd = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %AdaptTuple = var %d.var_patt\n// CHECK:STDOUT:   %c.ref: %AdaptTuple = name_ref c, %c\n// CHECK:STDOUT:   %.loc9_3.1: %tuple.type.d07 = as_compatible %c.ref\n// CHECK:STDOUT:   %tuple.elem0.loc9_3.1: %i32 = tuple_access %.loc9_3.1, element0\n// CHECK:STDOUT:   %impl.elem0.loc9_3.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc9_3.1: <bound method> = bound_method %tuple.elem0.loc9_3.1, %impl.elem0.loc9_3.1\n// CHECK:STDOUT:   %specific_fn.loc9_3.1: <specific function> = specific_function %impl.elem0.loc9_3.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_3.2: <bound method> = bound_method %tuple.elem0.loc9_3.1, %specific_fn.loc9_3.1\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc9_3.1: init %i32 = call %bound_method.loc9_3.2(%tuple.elem0.loc9_3.1)\n// CHECK:STDOUT:   %.loc9_3.2: ref %tuple.type.d07 = as_compatible %d.var\n// CHECK:STDOUT:   %tuple.elem0.loc9_3.2: ref %i32 = tuple_access %.loc9_3.2, element0\n// CHECK:STDOUT:   %.loc9_3.3: init %i32 to %tuple.elem0.loc9_3.2 = in_place_init %Int.as.Copy.impl.Op.call.loc9_3.1\n// CHECK:STDOUT:   %tuple.elem1.loc9_3.1: %i32 = tuple_access %.loc9_3.1, element1\n// CHECK:STDOUT:   %impl.elem0.loc9_3.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc9_3.3: <bound method> = bound_method %tuple.elem1.loc9_3.1, %impl.elem0.loc9_3.2\n// CHECK:STDOUT:   %specific_fn.loc9_3.2: <specific function> = specific_function %impl.elem0.loc9_3.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_3.4: <bound method> = bound_method %tuple.elem1.loc9_3.1, %specific_fn.loc9_3.2\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc9_3.2: init %i32 = call %bound_method.loc9_3.4(%tuple.elem1.loc9_3.1)\n// CHECK:STDOUT:   %tuple.elem1.loc9_3.2: ref %i32 = tuple_access %.loc9_3.2, element1\n// CHECK:STDOUT:   %.loc9_3.4: init %i32 to %tuple.elem1.loc9_3.2 = in_place_init %Int.as.Copy.impl.Op.call.loc9_3.2\n// CHECK:STDOUT:   %.loc9_3.5: init %tuple.type.d07 to %.loc9_3.2 = tuple_init (%.loc9_3.3, %.loc9_3.4)\n// CHECK:STDOUT:   %.loc9_3.6: init %AdaptTuple = as_compatible %.loc9_3.5\n// CHECK:STDOUT:   %.loc9_3.7: init %AdaptTuple = converted %c.ref, %.loc9_3.6\n// CHECK:STDOUT:   assign %d.var, %.loc9_3.7\n// CHECK:STDOUT:   %AdaptTuple.ref.loc9: type = name_ref AdaptTuple, file.%AdaptTuple.decl [concrete = constants.%AdaptTuple]\n// CHECK:STDOUT:   %d: ref %AdaptTuple = ref_binding d, %d.var\n// CHECK:STDOUT:   %d.ref: ref %AdaptTuple = name_ref d, %d\n// CHECK:STDOUT:   %.loc10_11.1: ref %tuple.type.d07 = as_compatible %d.ref\n// CHECK:STDOUT:   %tuple.elem0.loc10_11.1: ref %i32 = tuple_access %.loc10_11.1, element0\n// CHECK:STDOUT:   %.loc10_11.2: %i32 = acquire_value %tuple.elem0.loc10_11.1\n// CHECK:STDOUT:   %impl.elem0.loc10_11.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc10_11.1: <bound method> = bound_method %.loc10_11.2, %impl.elem0.loc10_11.1\n// CHECK:STDOUT:   %specific_fn.loc10_11.1: <specific function> = specific_function %impl.elem0.loc10_11.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_11.2: <bound method> = bound_method %.loc10_11.2, %specific_fn.loc10_11.1\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc10_11.1: init %i32 = call %bound_method.loc10_11.2(%.loc10_11.2)\n// CHECK:STDOUT:   %.loc10_11.3: ref %tuple.type.d07 = as_compatible %return.param\n// CHECK:STDOUT:   %tuple.elem0.loc10_11.2: ref %i32 = tuple_access %.loc10_11.3, element0\n// CHECK:STDOUT:   %.loc10_11.4: init %i32 to %tuple.elem0.loc10_11.2 = in_place_init %Int.as.Copy.impl.Op.call.loc10_11.1\n// CHECK:STDOUT:   %tuple.elem1.loc10_11.1: ref %i32 = tuple_access %.loc10_11.1, element1\n// CHECK:STDOUT:   %.loc10_11.5: %i32 = acquire_value %tuple.elem1.loc10_11.1\n// CHECK:STDOUT:   %impl.elem0.loc10_11.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc10_11.3: <bound method> = bound_method %.loc10_11.5, %impl.elem0.loc10_11.2\n// CHECK:STDOUT:   %specific_fn.loc10_11.2: <specific function> = specific_function %impl.elem0.loc10_11.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_11.4: <bound method> = bound_method %.loc10_11.5, %specific_fn.loc10_11.2\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc10_11.2: init %i32 = call %bound_method.loc10_11.4(%.loc10_11.5)\n// CHECK:STDOUT:   %tuple.elem1.loc10_11.2: ref %i32 = tuple_access %.loc10_11.3, element1\n// CHECK:STDOUT:   %.loc10_11.6: init %i32 to %tuple.elem1.loc10_11.2 = in_place_init %Int.as.Copy.impl.Op.call.loc10_11.2\n// CHECK:STDOUT:   %.loc10_11.7: init %tuple.type.d07 to %.loc10_11.3 = tuple_init (%.loc10_11.4, %.loc10_11.6)\n// CHECK:STDOUT:   %.loc10_11.8: init %AdaptTuple = as_compatible %.loc10_11.7\n// CHECK:STDOUT:   %.loc10_11.9: init %AdaptTuple = converted %d.ref, %.loc10_11.8\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %d.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%d.var)\n// CHECK:STDOUT:   return %.loc10_11.9 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc9(%self.param: ref %AdaptTuple) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InTuple(%c.param: %tuple.type.3c7) -> out %return.param: %tuple.type.3c7 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.6f4 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.6f4 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %tuple.type.3c7 = var %d.var_patt\n// CHECK:STDOUT:   %c.ref: %tuple.type.3c7 = name_ref c, %c\n// CHECK:STDOUT:   %tuple.elem0.loc14_30.1: %AdaptTuple = tuple_access %c.ref, element0\n// CHECK:STDOUT:   %.loc14_30.1: %tuple.type.d07 = as_compatible %tuple.elem0.loc14_30.1\n// CHECK:STDOUT:   %tuple.elem0.loc14_30.2: %i32 = tuple_access %.loc14_30.1, element0\n// CHECK:STDOUT:   %impl.elem0.loc14_30.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc14_30.1: <bound method> = bound_method %tuple.elem0.loc14_30.2, %impl.elem0.loc14_30.1\n// CHECK:STDOUT:   %specific_fn.loc14_30.1: <specific function> = specific_function %impl.elem0.loc14_30.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_30.2: <bound method> = bound_method %tuple.elem0.loc14_30.2, %specific_fn.loc14_30.1\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc14_30.1: init %i32 = call %bound_method.loc14_30.2(%tuple.elem0.loc14_30.2)\n// CHECK:STDOUT:   %tuple.elem0.loc14_30.3: ref %AdaptTuple = tuple_access %d.var, element0\n// CHECK:STDOUT:   %.loc14_30.2: ref %tuple.type.d07 = as_compatible %tuple.elem0.loc14_30.3\n// CHECK:STDOUT:   %tuple.elem0.loc14_30.4: ref %i32 = tuple_access %.loc14_30.2, element0\n// CHECK:STDOUT:   %.loc14_30.3: init %i32 to %tuple.elem0.loc14_30.4 = in_place_init %Int.as.Copy.impl.Op.call.loc14_30.1\n// CHECK:STDOUT:   %tuple.elem1.loc14_30.1: %i32 = tuple_access %.loc14_30.1, element1\n// CHECK:STDOUT:   %impl.elem0.loc14_30.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc14_30.3: <bound method> = bound_method %tuple.elem1.loc14_30.1, %impl.elem0.loc14_30.2\n// CHECK:STDOUT:   %specific_fn.loc14_30.2: <specific function> = specific_function %impl.elem0.loc14_30.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_30.4: <bound method> = bound_method %tuple.elem1.loc14_30.1, %specific_fn.loc14_30.2\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc14_30.2: init %i32 = call %bound_method.loc14_30.4(%tuple.elem1.loc14_30.1)\n// CHECK:STDOUT:   %tuple.elem1.loc14_30.2: ref %i32 = tuple_access %.loc14_30.2, element1\n// CHECK:STDOUT:   %.loc14_30.4: init %i32 to %tuple.elem1.loc14_30.2 = in_place_init %Int.as.Copy.impl.Op.call.loc14_30.2\n// CHECK:STDOUT:   %.loc14_30.5: init %tuple.type.d07 to %.loc14_30.2 = tuple_init (%.loc14_30.3, %.loc14_30.4)\n// CHECK:STDOUT:   %.loc14_30.6: init %AdaptTuple = as_compatible %.loc14_30.5\n// CHECK:STDOUT:   %.loc14_30.7: init %AdaptTuple = converted %tuple.elem0.loc14_30.1, %.loc14_30.6\n// CHECK:STDOUT:   %tuple.elem1.loc14_30.3: %u32 = tuple_access %c.ref, element1\n// CHECK:STDOUT:   %impl.elem0.loc14_30.3: %.38c = impl_witness_access constants.%Copy.impl_witness.514, element0 [concrete = constants.%UInt.as.Copy.impl.Op.c10]\n// CHECK:STDOUT:   %bound_method.loc14_30.5: <bound method> = bound_method %tuple.elem1.loc14_30.3, %impl.elem0.loc14_30.3\n// CHECK:STDOUT:   %specific_fn.loc14_30.3: <specific function> = specific_function %impl.elem0.loc14_30.3, @UInt.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%UInt.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_30.6: <bound method> = bound_method %tuple.elem1.loc14_30.3, %specific_fn.loc14_30.3\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.call.loc14: init %u32 = call %bound_method.loc14_30.6(%tuple.elem1.loc14_30.3)\n// CHECK:STDOUT:   %tuple.elem1.loc14_30.4: ref %u32 = tuple_access %d.var, element1\n// CHECK:STDOUT:   %.loc14_30.8: init %u32 to %tuple.elem1.loc14_30.4 = in_place_init %UInt.as.Copy.impl.Op.call.loc14\n// CHECK:STDOUT:   %.loc14_30.9: init %tuple.type.3c7 to %d.var = tuple_init (%.loc14_30.7, %.loc14_30.8)\n// CHECK:STDOUT:   %.loc14_3: init %tuple.type.3c7 = converted %c.ref, %.loc14_30.9\n// CHECK:STDOUT:   assign %d.var, %.loc14_3\n// CHECK:STDOUT:   %.loc14_26.1: type = splice_block %.loc14_26.3 [concrete = constants.%tuple.type.3c7] {\n// CHECK:STDOUT:     %AdaptTuple.ref.loc14: type = name_ref AdaptTuple, file.%AdaptTuple.decl [concrete = constants.%AdaptTuple]\n// CHECK:STDOUT:     %u32.loc14: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:     %.loc14_26.2: %tuple.type.24b = tuple_literal (%AdaptTuple.ref.loc14, %u32.loc14) [concrete = constants.%tuple.b75]\n// CHECK:STDOUT:     %.loc14_26.3: type = converted %.loc14_26.2, constants.%tuple.type.3c7 [concrete = constants.%tuple.type.3c7]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %tuple.type.3c7 = ref_binding d, %d.var\n// CHECK:STDOUT:   %d.ref: ref %tuple.type.3c7 = name_ref d, %d\n// CHECK:STDOUT:   %tuple.elem0.loc15_10.1: ref %AdaptTuple = tuple_access %d.ref, element0\n// CHECK:STDOUT:   %.loc15_10.1: ref %tuple.type.d07 = as_compatible %tuple.elem0.loc15_10.1\n// CHECK:STDOUT:   %tuple.elem0.loc15_10.2: ref %i32 = tuple_access %.loc15_10.1, element0\n// CHECK:STDOUT:   %.loc15_10.2: %i32 = acquire_value %tuple.elem0.loc15_10.2\n// CHECK:STDOUT:   %impl.elem0.loc15_10.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc15_10.1: <bound method> = bound_method %.loc15_10.2, %impl.elem0.loc15_10.1\n// CHECK:STDOUT:   %specific_fn.loc15_10.1: <specific function> = specific_function %impl.elem0.loc15_10.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_10.2: <bound method> = bound_method %.loc15_10.2, %specific_fn.loc15_10.1\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc15_10.1: init %i32 = call %bound_method.loc15_10.2(%.loc15_10.2)\n// CHECK:STDOUT:   %tuple.elem0.loc15_10.3: ref %AdaptTuple = tuple_access %return.param, element0\n// CHECK:STDOUT:   %.loc15_10.3: ref %tuple.type.d07 = as_compatible %tuple.elem0.loc15_10.3\n// CHECK:STDOUT:   %tuple.elem0.loc15_10.4: ref %i32 = tuple_access %.loc15_10.3, element0\n// CHECK:STDOUT:   %.loc15_10.4: init %i32 to %tuple.elem0.loc15_10.4 = in_place_init %Int.as.Copy.impl.Op.call.loc15_10.1\n// CHECK:STDOUT:   %tuple.elem1.loc15_10.1: ref %i32 = tuple_access %.loc15_10.1, element1\n// CHECK:STDOUT:   %.loc15_10.5: %i32 = acquire_value %tuple.elem1.loc15_10.1\n// CHECK:STDOUT:   %impl.elem0.loc15_10.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc15_10.3: <bound method> = bound_method %.loc15_10.5, %impl.elem0.loc15_10.2\n// CHECK:STDOUT:   %specific_fn.loc15_10.2: <specific function> = specific_function %impl.elem0.loc15_10.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_10.4: <bound method> = bound_method %.loc15_10.5, %specific_fn.loc15_10.2\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc15_10.2: init %i32 = call %bound_method.loc15_10.4(%.loc15_10.5)\n// CHECK:STDOUT:   %tuple.elem1.loc15_10.2: ref %i32 = tuple_access %.loc15_10.3, element1\n// CHECK:STDOUT:   %.loc15_10.6: init %i32 to %tuple.elem1.loc15_10.2 = in_place_init %Int.as.Copy.impl.Op.call.loc15_10.2\n// CHECK:STDOUT:   %.loc15_10.7: init %tuple.type.d07 to %.loc15_10.3 = tuple_init (%.loc15_10.4, %.loc15_10.6)\n// CHECK:STDOUT:   %.loc15_10.8: init %AdaptTuple = as_compatible %.loc15_10.7\n// CHECK:STDOUT:   %.loc15_10.9: init %AdaptTuple = converted %tuple.elem0.loc15_10.1, %.loc15_10.8\n// CHECK:STDOUT:   %tuple.elem1.loc15_10.3: ref %u32 = tuple_access %d.ref, element1\n// CHECK:STDOUT:   %.loc15_10.10: %u32 = acquire_value %tuple.elem1.loc15_10.3\n// CHECK:STDOUT:   %impl.elem0.loc15_10.3: %.38c = impl_witness_access constants.%Copy.impl_witness.514, element0 [concrete = constants.%UInt.as.Copy.impl.Op.c10]\n// CHECK:STDOUT:   %bound_method.loc15_10.5: <bound method> = bound_method %.loc15_10.10, %impl.elem0.loc15_10.3\n// CHECK:STDOUT:   %specific_fn.loc15_10.3: <specific function> = specific_function %impl.elem0.loc15_10.3, @UInt.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%UInt.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_10.6: <bound method> = bound_method %.loc15_10.10, %specific_fn.loc15_10.3\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.call.loc15: init %u32 = call %bound_method.loc15_10.6(%.loc15_10.10)\n// CHECK:STDOUT:   %tuple.elem1.loc15_10.4: ref %u32 = tuple_access %return.param, element1\n// CHECK:STDOUT:   %.loc15_10.11: init %u32 to %tuple.elem1.loc15_10.4 = in_place_init %UInt.as.Copy.impl.Op.call.loc15\n// CHECK:STDOUT:   %.loc15_10.12: init %tuple.type.3c7 to %return.param = tuple_init (%.loc15_10.9, %.loc15_10.11)\n// CHECK:STDOUT:   %.loc15_11: init %tuple.type.3c7 = converted %d.ref, %.loc15_10.12\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %d.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%d.var)\n// CHECK:STDOUT:   return %.loc15_11 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc14(%self.param: ref %tuple.type.3c7) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_adapt_not_copyable.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Noncopyable: type = class_type @Noncopyable [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %AdaptNoncopyable: type = class_type @AdaptNoncopyable [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %pattern_type.92b: type = pattern_type %AdaptNoncopyable [concrete]\n// CHECK:STDOUT:   %.e94: Core.Form = init_form %AdaptNoncopyable [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Noncopyable = %Noncopyable.decl\n// CHECK:STDOUT:     .AdaptNoncopyable = %AdaptNoncopyable.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Noncopyable.decl: type = class_decl @Noncopyable [concrete = constants.%Noncopyable] {} {}\n// CHECK:STDOUT:   %AdaptNoncopyable.decl: type = class_decl @AdaptNoncopyable [concrete = constants.%AdaptNoncopyable] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.92b = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.92b = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.92b = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.92b = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptNoncopyable.ref.loc12_30: type = name_ref AdaptNoncopyable, file.%AdaptNoncopyable.decl [concrete = constants.%AdaptNoncopyable]\n// CHECK:STDOUT:     %.loc12: Core.Form = init_form %AdaptNoncopyable.ref.loc12_30 [concrete = constants.%.e94]\n// CHECK:STDOUT:     %a.param: %AdaptNoncopyable = value_param call_param0\n// CHECK:STDOUT:     %AdaptNoncopyable.ref.loc12_9: type = name_ref AdaptNoncopyable, file.%AdaptNoncopyable.decl [concrete = constants.%AdaptNoncopyable]\n// CHECK:STDOUT:     %a: %AdaptNoncopyable = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %AdaptNoncopyable = out_param call_param1\n// CHECK:STDOUT:     %return: ref %AdaptNoncopyable = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Noncopyable {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Noncopyable\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptNoncopyable {\n// CHECK:STDOUT:   %Noncopyable.ref: type = name_ref Noncopyable, file.%Noncopyable.decl [concrete = constants.%Noncopyable]\n// CHECK:STDOUT:   adapt_decl %Noncopyable.ref [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptNoncopyable\n// CHECK:STDOUT:   .Noncopyable = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%a.param: %AdaptNoncopyable) -> out %return.param: %AdaptNoncopyable {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.92b = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.92b = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %AdaptNoncopyable = var %b.var_patt\n// CHECK:STDOUT:   %a.ref: %AdaptNoncopyable = name_ref a, %a\n// CHECK:STDOUT:   assign %b.var, <error>\n// CHECK:STDOUT:   %AdaptNoncopyable.ref.loc20: type = name_ref AdaptNoncopyable, file.%AdaptNoncopyable.decl [concrete = constants.%AdaptNoncopyable]\n// CHECK:STDOUT:   %b: ref %AdaptNoncopyable = ref_binding b, %b.var\n// CHECK:STDOUT:   %b.ref: ref %AdaptNoncopyable = name_ref b, %b\n// CHECK:STDOUT:   %.loc28: %AdaptNoncopyable = acquire_value %b.ref\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %b.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%b.var)\n// CHECK:STDOUT:   return <error> to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %AdaptNoncopyable) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_adapt_not_copyable_indirect.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Noncopyable: type = class_type @Noncopyable [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %AdaptNoncopyableIndirect: type = class_type @AdaptNoncopyableIndirect [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.ff9: type = tuple_type (type, type, type) [concrete]\n// CHECK:STDOUT:   %tuple.19a: %tuple.type.ff9 = tuple_value (%i32, %Noncopyable, %i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.7f9: type = tuple_type (%i32, %Noncopyable, %i32) [concrete]\n// CHECK:STDOUT:   %complete_type.381: <witness> = complete_type_witness %tuple.type.7f9 [concrete]\n// CHECK:STDOUT:   %pattern_type.ca6: type = pattern_type %AdaptNoncopyableIndirect [concrete]\n// CHECK:STDOUT:   %.ae4: Core.Form = init_form %AdaptNoncopyableIndirect [concrete]\n// CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]\n// CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Noncopyable = %Noncopyable.decl\n// CHECK:STDOUT:     .AdaptNoncopyableIndirect = %AdaptNoncopyableIndirect.decl\n// CHECK:STDOUT:     .H = %H.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Noncopyable.decl: type = class_decl @Noncopyable [concrete = constants.%Noncopyable] {} {}\n// CHECK:STDOUT:   %AdaptNoncopyableIndirect.decl: type = class_decl @AdaptNoncopyableIndirect [concrete = constants.%AdaptNoncopyableIndirect] {} {}\n// CHECK:STDOUT:   %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.ca6 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.ca6 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.ca6 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.ca6 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptNoncopyableIndirect.ref.loc12_38: type = name_ref AdaptNoncopyableIndirect, file.%AdaptNoncopyableIndirect.decl [concrete = constants.%AdaptNoncopyableIndirect]\n// CHECK:STDOUT:     %.loc12: Core.Form = init_form %AdaptNoncopyableIndirect.ref.loc12_38 [concrete = constants.%.ae4]\n// CHECK:STDOUT:     %a.param: %AdaptNoncopyableIndirect = value_param call_param0\n// CHECK:STDOUT:     %AdaptNoncopyableIndirect.ref.loc12_9: type = name_ref AdaptNoncopyableIndirect, file.%AdaptNoncopyableIndirect.decl [concrete = constants.%AdaptNoncopyableIndirect]\n// CHECK:STDOUT:     %a: %AdaptNoncopyableIndirect = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %AdaptNoncopyableIndirect = out_param call_param1\n// CHECK:STDOUT:     %return: ref %AdaptNoncopyableIndirect = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Noncopyable {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Noncopyable\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptNoncopyableIndirect {\n// CHECK:STDOUT:   %i32.loc9_10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %Noncopyable.ref: type = name_ref Noncopyable, file.%Noncopyable.decl [concrete = constants.%Noncopyable]\n// CHECK:STDOUT:   %i32.loc9_28: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc9_31: %tuple.type.ff9 = tuple_literal (%i32.loc9_10, %Noncopyable.ref, %i32.loc9_28) [concrete = constants.%tuple.19a]\n// CHECK:STDOUT:   %.loc9_32: type = converted %.loc9_31, constants.%tuple.type.7f9 [concrete = constants.%tuple.type.7f9]\n// CHECK:STDOUT:   adapt_decl %.loc9_32 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%tuple.type.7f9 [concrete = constants.%complete_type.381]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptNoncopyableIndirect\n// CHECK:STDOUT:   .Noncopyable = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @H(%a.param: %AdaptNoncopyableIndirect) -> out %return.param: %AdaptNoncopyableIndirect {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.ca6 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.ca6 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %AdaptNoncopyableIndirect = var %b.var_patt\n// CHECK:STDOUT:   %a.ref: %AdaptNoncopyableIndirect = name_ref a, %a\n// CHECK:STDOUT:   %.loc23_3.1: %tuple.type.7f9 = as_compatible %a.ref\n// CHECK:STDOUT:   %tuple.elem0.loc23_3.1: %i32 = tuple_access %.loc23_3.1, element0\n// CHECK:STDOUT:   %impl.elem0.loc23: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc23_3.1: <bound method> = bound_method %tuple.elem0.loc23_3.1, %impl.elem0.loc23\n// CHECK:STDOUT:   %specific_fn.loc23: <specific function> = specific_function %impl.elem0.loc23, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc23_3.2: <bound method> = bound_method %tuple.elem0.loc23_3.1, %specific_fn.loc23\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc23: init %i32 = call %bound_method.loc23_3.2(%tuple.elem0.loc23_3.1)\n// CHECK:STDOUT:   %.loc23_3.2: ref %tuple.type.7f9 = as_compatible %b.var\n// CHECK:STDOUT:   %tuple.elem0.loc23_3.2: ref %i32 = tuple_access %.loc23_3.2, element0\n// CHECK:STDOUT:   %.loc23_3.3: init %i32 to %tuple.elem0.loc23_3.2 = in_place_init %Int.as.Copy.impl.Op.call.loc23\n// CHECK:STDOUT:   %tuple.elem1.loc23: %Noncopyable = tuple_access %.loc23_3.1, element1\n// CHECK:STDOUT:   assign %b.var, <error>\n// CHECK:STDOUT:   %AdaptNoncopyableIndirect.ref.loc23: type = name_ref AdaptNoncopyableIndirect, file.%AdaptNoncopyableIndirect.decl [concrete = constants.%AdaptNoncopyableIndirect]\n// CHECK:STDOUT:   %b: ref %AdaptNoncopyableIndirect = ref_binding b, %b.var\n// CHECK:STDOUT:   %b.ref: ref %AdaptNoncopyableIndirect = name_ref b, %b\n// CHECK:STDOUT:   %.loc34_11.1: ref %tuple.type.7f9 = as_compatible %b.ref\n// CHECK:STDOUT:   %tuple.elem0.loc34_11.1: ref %i32 = tuple_access %.loc34_11.1, element0\n// CHECK:STDOUT:   %.loc34_11.2: %i32 = acquire_value %tuple.elem0.loc34_11.1\n// CHECK:STDOUT:   %impl.elem0.loc34: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc34_11.1: <bound method> = bound_method %.loc34_11.2, %impl.elem0.loc34\n// CHECK:STDOUT:   %specific_fn.loc34: <specific function> = specific_function %impl.elem0.loc34, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc34_11.2: <bound method> = bound_method %.loc34_11.2, %specific_fn.loc34\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc34: init %i32 = call %bound_method.loc34_11.2(%.loc34_11.2)\n// CHECK:STDOUT:   %.loc34_11.3: ref %tuple.type.7f9 = as_compatible %return.param\n// CHECK:STDOUT:   %tuple.elem0.loc34_11.2: ref %i32 = tuple_access %.loc34_11.3, element0\n// CHECK:STDOUT:   %.loc34_11.4: init %i32 to %tuple.elem0.loc34_11.2 = in_place_init %Int.as.Copy.impl.Op.call.loc34\n// CHECK:STDOUT:   %tuple.elem1.loc34: ref %Noncopyable = tuple_access %.loc34_11.1, element1\n// CHECK:STDOUT:   %.loc34_11.5: %Noncopyable = acquire_value %tuple.elem1.loc34\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %b.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%b.var)\n// CHECK:STDOUT:   return <error> to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %AdaptNoncopyableIndirect) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- adapt_copyable_struct.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %AdaptStruct: type = class_type @AdaptStruct [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.e.f: type = struct_type {.e: %i32, .f: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.511: <witness> = complete_type_witness %struct_type.e.f [concrete]\n// CHECK:STDOUT:   %pattern_type.341: type = pattern_type %AdaptStruct [concrete]\n// CHECK:STDOUT:   %.8e3: Core.Form = init_form %AdaptStruct [concrete]\n// CHECK:STDOUT:   %I.type: type = fn_type @I [concrete]\n// CHECK:STDOUT:   %I: %I.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc9 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %UInt.type: type = generic_class_type @UInt [concrete]\n// CHECK:STDOUT:   %UInt.generic: %UInt.type = struct_value () [concrete]\n// CHECK:STDOUT:   %u32: type = class_type @UInt, @UInt(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.556: %tuple.type.24b = tuple_value (%AdaptStruct, %u32) [concrete]\n// CHECK:STDOUT:   %tuple.type.691: type = tuple_type (%AdaptStruct, %u32) [concrete]\n// CHECK:STDOUT:   %pattern_type.b13: type = pattern_type %tuple.type.691 [concrete]\n// CHECK:STDOUT:   %.174: Core.Form = init_form %tuple.type.691 [concrete]\n// CHECK:STDOUT:   %InTuple.type: type = fn_type @InTuple [concrete]\n// CHECK:STDOUT:   %InTuple: %InTuple.type = struct_value () [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.type.68f: type = fn_type @UInt.as.Copy.impl.Op, @UInt.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.576: %UInt.as.Copy.impl.Op.type.68f = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.514: <witness> = impl_witness imports.%Copy.impl_witness_table.bd0, @UInt.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.type.2fc: type = fn_type @UInt.as.Copy.impl.Op, @UInt.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.c10: %UInt.as.Copy.impl.Op.type.2fc = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.10b: %Copy.type = facet_value %u32, (%Copy.impl_witness.514) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.ad7: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.10b) [concrete]\n// CHECK:STDOUT:   %.38c: type = fn_type_with_self_type %Copy.WithSelf.Op.type.ad7, %Copy.facet.10b [concrete]\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %UInt.as.Copy.impl.Op.c10, @UInt.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc14 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     .UInt = %Core.UInt\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:   %Core.UInt: %UInt.type = import_ref Core//prelude/parts/uint, UInt, loaded [concrete = constants.%UInt.generic]\n// CHECK:STDOUT:   %Core.import_ref.c3c: @UInt.as.Copy.impl.%UInt.as.Copy.impl.Op.type (%UInt.as.Copy.impl.Op.type.68f) = import_ref Core//prelude/parts/uint, loc{{\\d+_\\d+}}, loaded [symbolic = @UInt.as.Copy.impl.%UInt.as.Copy.impl.Op (constants.%UInt.as.Copy.impl.Op.576)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.bd0 = impl_witness_table (%Core.import_ref.c3c), @UInt.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .AdaptStruct = %AdaptStruct.decl\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .InTuple = %InTuple.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %AdaptStruct.decl: type = class_decl @AdaptStruct [concrete = constants.%AdaptStruct] {} {}\n// CHECK:STDOUT:   %I.decl: %I.type = fn_decl @I [concrete = constants.%I] {\n// CHECK:STDOUT:     %g.patt: %pattern_type.341 = value_binding_pattern g [concrete]\n// CHECK:STDOUT:     %g.param_patt: %pattern_type.341 = value_param_pattern %g.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.341 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.341 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptStruct.ref.loc8_25: type = name_ref AdaptStruct, file.%AdaptStruct.decl [concrete = constants.%AdaptStruct]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %AdaptStruct.ref.loc8_25 [concrete = constants.%.8e3]\n// CHECK:STDOUT:     %g.param: %AdaptStruct = value_param call_param0\n// CHECK:STDOUT:     %AdaptStruct.ref.loc8_9: type = name_ref AdaptStruct, file.%AdaptStruct.decl [concrete = constants.%AdaptStruct]\n// CHECK:STDOUT:     %g: %AdaptStruct = value_binding g, %g.param\n// CHECK:STDOUT:     %return.param: ref %AdaptStruct = out_param call_param1\n// CHECK:STDOUT:     %return: ref %AdaptStruct = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %InTuple.decl: %InTuple.type = fn_decl @InTuple [concrete = constants.%InTuple] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.b13 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.b13 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.b13 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.b13 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptStruct.ref.loc13_39: type = name_ref AdaptStruct, file.%AdaptStruct.decl [concrete = constants.%AdaptStruct]\n// CHECK:STDOUT:     %u32.loc13_52: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:     %.loc13_55.1: %tuple.type.24b = tuple_literal (%AdaptStruct.ref.loc13_39, %u32.loc13_52) [concrete = constants.%tuple.556]\n// CHECK:STDOUT:     %.loc13_55.2: type = converted %.loc13_55.1, constants.%tuple.type.691 [concrete = constants.%tuple.type.691]\n// CHECK:STDOUT:     %.loc13_55.3: Core.Form = init_form %.loc13_55.2 [concrete = constants.%.174]\n// CHECK:STDOUT:     %c.param: %tuple.type.691 = value_param call_param0\n// CHECK:STDOUT:     %.loc13_32.1: type = splice_block %.loc13_32.3 [concrete = constants.%tuple.type.691] {\n// CHECK:STDOUT:       %AdaptStruct.ref.loc13_16: type = name_ref AdaptStruct, file.%AdaptStruct.decl [concrete = constants.%AdaptStruct]\n// CHECK:STDOUT:       %u32.loc13_29: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:       %.loc13_32.2: %tuple.type.24b = tuple_literal (%AdaptStruct.ref.loc13_16, %u32.loc13_29) [concrete = constants.%tuple.556]\n// CHECK:STDOUT:       %.loc13_32.3: type = converted %.loc13_32.2, constants.%tuple.type.691 [concrete = constants.%tuple.type.691]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %tuple.type.691 = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %tuple.type.691 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %tuple.type.691 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptStruct {\n// CHECK:STDOUT:   %i32.loc5_14: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %i32.loc5_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %struct_type.e.f: type = struct_type {.e: %i32, .f: %i32} [concrete = constants.%struct_type.e.f]\n// CHECK:STDOUT:   adapt_decl %struct_type.e.f [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.e.f [concrete = constants.%complete_type.511]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptStruct\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @I(%g.param: %AdaptStruct) -> out %return.param: %AdaptStruct {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %h.patt: %pattern_type.341 = ref_binding_pattern h [concrete]\n// CHECK:STDOUT:     %h.var_patt: %pattern_type.341 = var_pattern %h.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %h.var: ref %AdaptStruct = var %h.var_patt\n// CHECK:STDOUT:   %g.ref: %AdaptStruct = name_ref g, %g\n// CHECK:STDOUT:   %.loc9_3.1: %struct_type.e.f = as_compatible %g.ref\n// CHECK:STDOUT:   %.loc9_3.2: %i32 = struct_access %.loc9_3.1, element0\n// CHECK:STDOUT:   %impl.elem0.loc9_3.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc9_3.1: <bound method> = bound_method %.loc9_3.2, %impl.elem0.loc9_3.1\n// CHECK:STDOUT:   %specific_fn.loc9_3.1: <specific function> = specific_function %impl.elem0.loc9_3.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_3.2: <bound method> = bound_method %.loc9_3.2, %specific_fn.loc9_3.1\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc9_3.1: init %i32 = call %bound_method.loc9_3.2(%.loc9_3.2)\n// CHECK:STDOUT:   %.loc9_3.3: ref %struct_type.e.f = as_compatible %h.var\n// CHECK:STDOUT:   %.loc9_3.4: ref %i32 = struct_access %.loc9_3.3, element0\n// CHECK:STDOUT:   %.loc9_3.5: init %i32 to %.loc9_3.4 = in_place_init %Int.as.Copy.impl.Op.call.loc9_3.1\n// CHECK:STDOUT:   %.loc9_3.6: %i32 = struct_access %.loc9_3.1, element1\n// CHECK:STDOUT:   %impl.elem0.loc9_3.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc9_3.3: <bound method> = bound_method %.loc9_3.6, %impl.elem0.loc9_3.2\n// CHECK:STDOUT:   %specific_fn.loc9_3.2: <specific function> = specific_function %impl.elem0.loc9_3.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_3.4: <bound method> = bound_method %.loc9_3.6, %specific_fn.loc9_3.2\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc9_3.2: init %i32 = call %bound_method.loc9_3.4(%.loc9_3.6)\n// CHECK:STDOUT:   %.loc9_3.7: ref %i32 = struct_access %.loc9_3.3, element1\n// CHECK:STDOUT:   %.loc9_3.8: init %i32 to %.loc9_3.7 = in_place_init %Int.as.Copy.impl.Op.call.loc9_3.2\n// CHECK:STDOUT:   %.loc9_3.9: init %struct_type.e.f to %.loc9_3.3 = struct_init (%.loc9_3.5, %.loc9_3.8)\n// CHECK:STDOUT:   %.loc9_3.10: init %AdaptStruct = as_compatible %.loc9_3.9\n// CHECK:STDOUT:   %.loc9_3.11: init %AdaptStruct = converted %g.ref, %.loc9_3.10\n// CHECK:STDOUT:   assign %h.var, %.loc9_3.11\n// CHECK:STDOUT:   %AdaptStruct.ref.loc9: type = name_ref AdaptStruct, file.%AdaptStruct.decl [concrete = constants.%AdaptStruct]\n// CHECK:STDOUT:   %h: ref %AdaptStruct = ref_binding h, %h.var\n// CHECK:STDOUT:   %h.ref: ref %AdaptStruct = name_ref h, %h\n// CHECK:STDOUT:   %.loc10_11.1: ref %struct_type.e.f = as_compatible %h.ref\n// CHECK:STDOUT:   %.loc10_11.2: ref %i32 = struct_access %.loc10_11.1, element0\n// CHECK:STDOUT:   %.loc10_11.3: %i32 = acquire_value %.loc10_11.2\n// CHECK:STDOUT:   %impl.elem0.loc10_11.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc10_11.1: <bound method> = bound_method %.loc10_11.3, %impl.elem0.loc10_11.1\n// CHECK:STDOUT:   %specific_fn.loc10_11.1: <specific function> = specific_function %impl.elem0.loc10_11.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_11.2: <bound method> = bound_method %.loc10_11.3, %specific_fn.loc10_11.1\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc10_11.1: init %i32 = call %bound_method.loc10_11.2(%.loc10_11.3)\n// CHECK:STDOUT:   %.loc10_11.4: ref %struct_type.e.f = as_compatible %return.param\n// CHECK:STDOUT:   %.loc10_11.5: ref %i32 = struct_access %.loc10_11.4, element0\n// CHECK:STDOUT:   %.loc10_11.6: init %i32 to %.loc10_11.5 = in_place_init %Int.as.Copy.impl.Op.call.loc10_11.1\n// CHECK:STDOUT:   %.loc10_11.7: ref %i32 = struct_access %.loc10_11.1, element1\n// CHECK:STDOUT:   %.loc10_11.8: %i32 = acquire_value %.loc10_11.7\n// CHECK:STDOUT:   %impl.elem0.loc10_11.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc10_11.3: <bound method> = bound_method %.loc10_11.8, %impl.elem0.loc10_11.2\n// CHECK:STDOUT:   %specific_fn.loc10_11.2: <specific function> = specific_function %impl.elem0.loc10_11.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_11.4: <bound method> = bound_method %.loc10_11.8, %specific_fn.loc10_11.2\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc10_11.2: init %i32 = call %bound_method.loc10_11.4(%.loc10_11.8)\n// CHECK:STDOUT:   %.loc10_11.9: ref %i32 = struct_access %.loc10_11.4, element1\n// CHECK:STDOUT:   %.loc10_11.10: init %i32 to %.loc10_11.9 = in_place_init %Int.as.Copy.impl.Op.call.loc10_11.2\n// CHECK:STDOUT:   %.loc10_11.11: init %struct_type.e.f to %.loc10_11.4 = struct_init (%.loc10_11.6, %.loc10_11.10)\n// CHECK:STDOUT:   %.loc10_11.12: init %AdaptStruct = as_compatible %.loc10_11.11\n// CHECK:STDOUT:   %.loc10_11.13: init %AdaptStruct = converted %h.ref, %.loc10_11.12\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %h.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%h.var)\n// CHECK:STDOUT:   return %.loc10_11.13 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc9(%self.param: ref %AdaptStruct) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InTuple(%c.param: %tuple.type.691) -> out %return.param: %tuple.type.691 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.b13 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.b13 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %tuple.type.691 = var %d.var_patt\n// CHECK:STDOUT:   %c.ref: %tuple.type.691 = name_ref c, %c\n// CHECK:STDOUT:   %tuple.elem0.loc14_31.1: %AdaptStruct = tuple_access %c.ref, element0\n// CHECK:STDOUT:   %.loc14_31.1: %struct_type.e.f = as_compatible %tuple.elem0.loc14_31.1\n// CHECK:STDOUT:   %.loc14_31.2: %i32 = struct_access %.loc14_31.1, element0\n// CHECK:STDOUT:   %impl.elem0.loc14_31.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc14_31.1: <bound method> = bound_method %.loc14_31.2, %impl.elem0.loc14_31.1\n// CHECK:STDOUT:   %specific_fn.loc14_31.1: <specific function> = specific_function %impl.elem0.loc14_31.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_31.2: <bound method> = bound_method %.loc14_31.2, %specific_fn.loc14_31.1\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc14_31.1: init %i32 = call %bound_method.loc14_31.2(%.loc14_31.2)\n// CHECK:STDOUT:   %tuple.elem0.loc14_31.2: ref %AdaptStruct = tuple_access %d.var, element0\n// CHECK:STDOUT:   %.loc14_31.3: ref %struct_type.e.f = as_compatible %tuple.elem0.loc14_31.2\n// CHECK:STDOUT:   %.loc14_31.4: ref %i32 = struct_access %.loc14_31.3, element0\n// CHECK:STDOUT:   %.loc14_31.5: init %i32 to %.loc14_31.4 = in_place_init %Int.as.Copy.impl.Op.call.loc14_31.1\n// CHECK:STDOUT:   %.loc14_31.6: %i32 = struct_access %.loc14_31.1, element1\n// CHECK:STDOUT:   %impl.elem0.loc14_31.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc14_31.3: <bound method> = bound_method %.loc14_31.6, %impl.elem0.loc14_31.2\n// CHECK:STDOUT:   %specific_fn.loc14_31.2: <specific function> = specific_function %impl.elem0.loc14_31.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_31.4: <bound method> = bound_method %.loc14_31.6, %specific_fn.loc14_31.2\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc14_31.2: init %i32 = call %bound_method.loc14_31.4(%.loc14_31.6)\n// CHECK:STDOUT:   %.loc14_31.7: ref %i32 = struct_access %.loc14_31.3, element1\n// CHECK:STDOUT:   %.loc14_31.8: init %i32 to %.loc14_31.7 = in_place_init %Int.as.Copy.impl.Op.call.loc14_31.2\n// CHECK:STDOUT:   %.loc14_31.9: init %struct_type.e.f to %.loc14_31.3 = struct_init (%.loc14_31.5, %.loc14_31.8)\n// CHECK:STDOUT:   %.loc14_31.10: init %AdaptStruct = as_compatible %.loc14_31.9\n// CHECK:STDOUT:   %.loc14_31.11: init %AdaptStruct = converted %tuple.elem0.loc14_31.1, %.loc14_31.10\n// CHECK:STDOUT:   %tuple.elem1.loc14_31.1: %u32 = tuple_access %c.ref, element1\n// CHECK:STDOUT:   %impl.elem0.loc14_31.3: %.38c = impl_witness_access constants.%Copy.impl_witness.514, element0 [concrete = constants.%UInt.as.Copy.impl.Op.c10]\n// CHECK:STDOUT:   %bound_method.loc14_31.5: <bound method> = bound_method %tuple.elem1.loc14_31.1, %impl.elem0.loc14_31.3\n// CHECK:STDOUT:   %specific_fn.loc14_31.3: <specific function> = specific_function %impl.elem0.loc14_31.3, @UInt.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%UInt.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_31.6: <bound method> = bound_method %tuple.elem1.loc14_31.1, %specific_fn.loc14_31.3\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.call.loc14: init %u32 = call %bound_method.loc14_31.6(%tuple.elem1.loc14_31.1)\n// CHECK:STDOUT:   %tuple.elem1.loc14_31.2: ref %u32 = tuple_access %d.var, element1\n// CHECK:STDOUT:   %.loc14_31.12: init %u32 to %tuple.elem1.loc14_31.2 = in_place_init %UInt.as.Copy.impl.Op.call.loc14\n// CHECK:STDOUT:   %.loc14_31.13: init %tuple.type.691 to %d.var = tuple_init (%.loc14_31.11, %.loc14_31.12)\n// CHECK:STDOUT:   %.loc14_3: init %tuple.type.691 = converted %c.ref, %.loc14_31.13\n// CHECK:STDOUT:   assign %d.var, %.loc14_3\n// CHECK:STDOUT:   %.loc14_27.1: type = splice_block %.loc14_27.3 [concrete = constants.%tuple.type.691] {\n// CHECK:STDOUT:     %AdaptStruct.ref.loc14: type = name_ref AdaptStruct, file.%AdaptStruct.decl [concrete = constants.%AdaptStruct]\n// CHECK:STDOUT:     %u32.loc14: type = type_literal constants.%u32 [concrete = constants.%u32]\n// CHECK:STDOUT:     %.loc14_27.2: %tuple.type.24b = tuple_literal (%AdaptStruct.ref.loc14, %u32.loc14) [concrete = constants.%tuple.556]\n// CHECK:STDOUT:     %.loc14_27.3: type = converted %.loc14_27.2, constants.%tuple.type.691 [concrete = constants.%tuple.type.691]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %tuple.type.691 = ref_binding d, %d.var\n// CHECK:STDOUT:   %d.ref: ref %tuple.type.691 = name_ref d, %d\n// CHECK:STDOUT:   %tuple.elem0.loc15_10.1: ref %AdaptStruct = tuple_access %d.ref, element0\n// CHECK:STDOUT:   %.loc15_10.1: ref %struct_type.e.f = as_compatible %tuple.elem0.loc15_10.1\n// CHECK:STDOUT:   %.loc15_10.2: ref %i32 = struct_access %.loc15_10.1, element0\n// CHECK:STDOUT:   %.loc15_10.3: %i32 = acquire_value %.loc15_10.2\n// CHECK:STDOUT:   %impl.elem0.loc15_10.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc15_10.1: <bound method> = bound_method %.loc15_10.3, %impl.elem0.loc15_10.1\n// CHECK:STDOUT:   %specific_fn.loc15_10.1: <specific function> = specific_function %impl.elem0.loc15_10.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_10.2: <bound method> = bound_method %.loc15_10.3, %specific_fn.loc15_10.1\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc15_10.1: init %i32 = call %bound_method.loc15_10.2(%.loc15_10.3)\n// CHECK:STDOUT:   %tuple.elem0.loc15_10.2: ref %AdaptStruct = tuple_access %return.param, element0\n// CHECK:STDOUT:   %.loc15_10.4: ref %struct_type.e.f = as_compatible %tuple.elem0.loc15_10.2\n// CHECK:STDOUT:   %.loc15_10.5: ref %i32 = struct_access %.loc15_10.4, element0\n// CHECK:STDOUT:   %.loc15_10.6: init %i32 to %.loc15_10.5 = in_place_init %Int.as.Copy.impl.Op.call.loc15_10.1\n// CHECK:STDOUT:   %.loc15_10.7: ref %i32 = struct_access %.loc15_10.1, element1\n// CHECK:STDOUT:   %.loc15_10.8: %i32 = acquire_value %.loc15_10.7\n// CHECK:STDOUT:   %impl.elem0.loc15_10.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc15_10.3: <bound method> = bound_method %.loc15_10.8, %impl.elem0.loc15_10.2\n// CHECK:STDOUT:   %specific_fn.loc15_10.2: <specific function> = specific_function %impl.elem0.loc15_10.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_10.4: <bound method> = bound_method %.loc15_10.8, %specific_fn.loc15_10.2\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc15_10.2: init %i32 = call %bound_method.loc15_10.4(%.loc15_10.8)\n// CHECK:STDOUT:   %.loc15_10.9: ref %i32 = struct_access %.loc15_10.4, element1\n// CHECK:STDOUT:   %.loc15_10.10: init %i32 to %.loc15_10.9 = in_place_init %Int.as.Copy.impl.Op.call.loc15_10.2\n// CHECK:STDOUT:   %.loc15_10.11: init %struct_type.e.f to %.loc15_10.4 = struct_init (%.loc15_10.6, %.loc15_10.10)\n// CHECK:STDOUT:   %.loc15_10.12: init %AdaptStruct = as_compatible %.loc15_10.11\n// CHECK:STDOUT:   %.loc15_10.13: init %AdaptStruct = converted %tuple.elem0.loc15_10.1, %.loc15_10.12\n// CHECK:STDOUT:   %tuple.elem1.loc15_10.1: ref %u32 = tuple_access %d.ref, element1\n// CHECK:STDOUT:   %.loc15_10.14: %u32 = acquire_value %tuple.elem1.loc15_10.1\n// CHECK:STDOUT:   %impl.elem0.loc15_10.3: %.38c = impl_witness_access constants.%Copy.impl_witness.514, element0 [concrete = constants.%UInt.as.Copy.impl.Op.c10]\n// CHECK:STDOUT:   %bound_method.loc15_10.5: <bound method> = bound_method %.loc15_10.14, %impl.elem0.loc15_10.3\n// CHECK:STDOUT:   %specific_fn.loc15_10.3: <specific function> = specific_function %impl.elem0.loc15_10.3, @UInt.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%UInt.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_10.6: <bound method> = bound_method %.loc15_10.14, %specific_fn.loc15_10.3\n// CHECK:STDOUT:   %UInt.as.Copy.impl.Op.call.loc15: init %u32 = call %bound_method.loc15_10.6(%.loc15_10.14)\n// CHECK:STDOUT:   %tuple.elem1.loc15_10.2: ref %u32 = tuple_access %return.param, element1\n// CHECK:STDOUT:   %.loc15_10.15: init %u32 to %tuple.elem1.loc15_10.2 = in_place_init %UInt.as.Copy.impl.Op.call.loc15\n// CHECK:STDOUT:   %.loc15_10.16: init %tuple.type.691 to %return.param = tuple_init (%.loc15_10.13, %.loc15_10.15)\n// CHECK:STDOUT:   %.loc15_11: init %tuple.type.691 = converted %d.ref, %.loc15_10.16\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %d.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%d.var)\n// CHECK:STDOUT:   return %.loc15_11 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc14(%self.param: ref %tuple.type.691) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/convert_incomplete.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/convert_incomplete.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/convert_incomplete.carbon\n\n// --- already_complete.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Adapter(T:! type) {\n  extend adapt T*;\n}\n\nclass X {}\n\n// Trigger completion of Adapter(X) here.\nvar x: Adapter(X);\n\nfn F(p: Adapter(X)*) {\n  let unused x: X* = *p as X*;\n}\n\n// --- can_be_completed.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Adapter(T:! type) {\n  extend adapt T*;\n}\n\nclass X {}\n\nfn F(p: Adapter(X)*) {\n  // The conversion here triggers completion of Adapter(X)\n  // so we can determine what it adapts.\n  let unused x: X* = *p as X*;\n}\n\n// --- fail_incomplete.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Adapter(T:! type);\n\nclass X {}\n\nfn F(p: Adapter(X)*) {\n  // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+7]]:22: error: cannot convert expression of type `Adapter(X)` to `X*` with `as` [ConversionFailure]\n  // CHECK:STDERR:   let unused x: X* = *p as X*;\n  // CHECK:STDERR:                      ^~~~~~~~\n  // CHECK:STDERR: fail_incomplete.carbon:[[@LINE+4]]:22: note: type `Adapter(X)` does not implement interface `Core.As(X*)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused x: X* = *p as X*;\n  // CHECK:STDERR:                      ^~~~~~~~\n  // CHECK:STDERR:\n  let unused x: X* = *p as X*;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/extend_adapt.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/extend_adapt.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/extend_adapt.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass SomeClassAdapter;\n\nclass SomeClass {\n  var a: i32;\n  var b: i32;\n\n  fn StaticMemberFunction();\n\n  fn AdapterMethod[self: SomeClassAdapter]();\n}\n\nclass SomeClassAdapter {\n  extend adapt SomeClass;\n}\n\nfn TestStaticMemberFunction(a: SomeClassAdapter) {\n  a.StaticMemberFunction();\n}\n\nfn TestAdapterMethod(a: SomeClassAdapter) {\n  a.AdapterMethod();\n}\n\n// --- fail_todo_method_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass SomeClass {\n  fn F[self: Self]();\n}\n\nclass SomeClassAdapter {\n  extend adapt SomeClass;\n}\n\nfn F(a: SomeClassAdapter) {\n  // CHECK:STDERR: fail_todo_method_access.carbon:[[@LINE+10]]:3: error: cannot implicitly convert expression of type `SomeClassAdapter` to `SomeClass` [ConversionFailure]\n  // CHECK:STDERR:   a.F();\n  // CHECK:STDERR:   ^\n  // CHECK:STDERR: fail_todo_method_access.carbon:[[@LINE+7]]:3: note: type `SomeClassAdapter` does not implement interface `Core.ImplicitAs(SomeClass)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   a.F();\n  // CHECK:STDERR:   ^\n  // CHECK:STDERR: fail_todo_method_access.carbon:[[@LINE-14]]:8: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR:   fn F[self: Self]();\n  // CHECK:STDERR:        ^~~~~~~~~~\n  // CHECK:STDERR:\n  a.F();\n}\n\n// --- fail_todo_field_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass SomeClass {\n  var a: i32;\n  var b: i32;\n}\n\nclass SomeClassAdapter {\n  extend adapt SomeClass;\n}\n\nfn F(a: SomeClassAdapter) -> i32 {\n  // CHECK:STDERR: fail_todo_field_access.carbon:[[@LINE+7]]:10: error: cannot implicitly convert expression of type `SomeClassAdapter` to `SomeClass` [ConversionFailure]\n  // CHECK:STDERR:   return a.b;\n  // CHECK:STDERR:          ^~~\n  // CHECK:STDERR: fail_todo_field_access.carbon:[[@LINE+4]]:10: note: type `SomeClassAdapter` does not implement interface `Core.ImplicitAs(SomeClass)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return a.b;\n  // CHECK:STDERR:          ^~~\n  // CHECK:STDERR:\n  return a.b;\n}\n\n// --- fail_todo_adapt_struct.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass StructAdapter {\n  extend adapt {.a: i32, .b: i32};\n}\n\nfn F(a: StructAdapter) -> i32 {\n  // TODO: This should be allowed.\n  // CHECK:STDERR: fail_todo_adapt_struct.carbon:[[@LINE+4]]:10: error: member name `b` not found in `StructAdapter` [MemberNameNotFoundInInstScope]\n  // CHECK:STDERR:   return a.b;\n  // CHECK:STDERR:          ^~~\n  // CHECK:STDERR:\n  return a.b;\n}\n\n// --- fail_todo_adapt_tuple.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass TupleAdapter {\n  extend adapt (i32, i32);\n}\n\nfn F(a: TupleAdapter) -> i32 {\n  // TODO: This should be allowed.\n  // CHECK:STDERR: fail_todo_adapt_tuple.carbon:[[@LINE+4]]:10: error: type `TupleAdapter` does not support tuple indexing; only tuples can be indexed that way [TupleIndexOnANonTupleType]\n  // CHECK:STDERR:   return a.1;\n  // CHECK:STDERR:          ^~~\n  // CHECK:STDERR:\n  return a.1;\n}\n\n// --- fail_adapt_builtin.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn MakeInt(N: Core.IntLiteral()) -> type = \"int.make_type_signed\";\n\nclass IntAdapter {\n  extend adapt MakeInt(32);\n}\n\nfn F(a: IntAdapter) -> i32 {\n  // Builtin types have no member names.\n  // CHECK:STDERR: fail_adapt_builtin.carbon:[[@LINE+4]]:10: error: member name `foo` not found in `IntAdapter` [MemberNameNotFoundInInstScope]\n  // CHECK:STDERR:   return a.foo;\n  // CHECK:STDERR:          ^~~~~\n  // CHECK:STDERR:\n  return a.foo;\n}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %SomeClassAdapter: type = class_type @SomeClassAdapter [concrete]\n// CHECK:STDOUT:   %SomeClass: type = class_type @SomeClass [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %SomeClass.elem: type = unbound_element_type %SomeClass, %i32 [concrete]\n// CHECK:STDOUT:   %SomeClass.StaticMemberFunction.type: type = fn_type @SomeClass.StaticMemberFunction [concrete]\n// CHECK:STDOUT:   %SomeClass.StaticMemberFunction: %SomeClass.StaticMemberFunction.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.31a: type = pattern_type %SomeClassAdapter [concrete]\n// CHECK:STDOUT:   %SomeClass.AdapterMethod.type: type = fn_type @SomeClass.AdapterMethod [concrete]\n// CHECK:STDOUT:   %SomeClass.AdapterMethod: %SomeClass.AdapterMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: %i32, .b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.705: <witness> = complete_type_witness %struct_type.a.b [concrete]\n// CHECK:STDOUT:   %TestStaticMemberFunction.type: type = fn_type @TestStaticMemberFunction [concrete]\n// CHECK:STDOUT:   %TestStaticMemberFunction: %TestStaticMemberFunction.type = struct_value () [concrete]\n// CHECK:STDOUT:   %TestAdapterMethod.type: type = fn_type @TestAdapterMethod [concrete]\n// CHECK:STDOUT:   %TestAdapterMethod: %TestAdapterMethod.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .SomeClassAdapter = %SomeClassAdapter.decl.loc4\n// CHECK:STDOUT:     .SomeClass = %SomeClass.decl\n// CHECK:STDOUT:     .TestStaticMemberFunction = %TestStaticMemberFunction.decl\n// CHECK:STDOUT:     .TestAdapterMethod = %TestAdapterMethod.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %SomeClassAdapter.decl.loc4: type = class_decl @SomeClassAdapter [concrete = constants.%SomeClassAdapter] {} {}\n// CHECK:STDOUT:   %SomeClass.decl: type = class_decl @SomeClass [concrete = constants.%SomeClass] {} {}\n// CHECK:STDOUT:   %SomeClassAdapter.decl.loc15: type = class_decl @SomeClassAdapter [concrete = constants.%SomeClassAdapter] {} {}\n// CHECK:STDOUT:   %TestStaticMemberFunction.decl: %TestStaticMemberFunction.type = fn_decl @TestStaticMemberFunction [concrete = constants.%TestStaticMemberFunction] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.31a = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.31a = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %SomeClassAdapter = value_param call_param0\n// CHECK:STDOUT:     %SomeClassAdapter.ref: type = name_ref SomeClassAdapter, file.%SomeClassAdapter.decl.loc4 [concrete = constants.%SomeClassAdapter]\n// CHECK:STDOUT:     %a: %SomeClassAdapter = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %TestAdapterMethod.decl: %TestAdapterMethod.type = fn_decl @TestAdapterMethod [concrete = constants.%TestAdapterMethod] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.31a = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.31a = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %SomeClassAdapter = value_param call_param0\n// CHECK:STDOUT:     %SomeClassAdapter.ref: type = name_ref SomeClassAdapter, file.%SomeClassAdapter.decl.loc4 [concrete = constants.%SomeClassAdapter]\n// CHECK:STDOUT:     %a: %SomeClassAdapter = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SomeClassAdapter {\n// CHECK:STDOUT:   %SomeClass.ref: type = name_ref SomeClass, file.%SomeClass.decl [concrete = constants.%SomeClass]\n// CHECK:STDOUT:   adapt_decl %SomeClass.ref [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SomeClassAdapter\n// CHECK:STDOUT:   .SomeClass = <poisoned>\n// CHECK:STDOUT:   .StaticMemberFunction = <poisoned>\n// CHECK:STDOUT:   .AdapterMethod = <poisoned>\n// CHECK:STDOUT:   extend %SomeClass.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SomeClass {\n// CHECK:STDOUT:   %i32.loc7: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc7: %SomeClass.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc8: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc8: %SomeClass.elem = field_decl b, element1 [concrete]\n// CHECK:STDOUT:   %SomeClass.StaticMemberFunction.decl: %SomeClass.StaticMemberFunction.type = fn_decl @SomeClass.StaticMemberFunction [concrete = constants.%SomeClass.StaticMemberFunction] {} {}\n// CHECK:STDOUT:   %SomeClass.AdapterMethod.decl: %SomeClass.AdapterMethod.type = fn_decl @SomeClass.AdapterMethod [concrete = constants.%SomeClass.AdapterMethod] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.31a = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.31a = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %SomeClassAdapter = value_param call_param0\n// CHECK:STDOUT:     %SomeClassAdapter.ref: type = name_ref SomeClassAdapter, file.%SomeClassAdapter.decl.loc4 [concrete = constants.%SomeClassAdapter]\n// CHECK:STDOUT:     %self: %SomeClassAdapter = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SomeClass\n// CHECK:STDOUT:   .a = %.loc7\n// CHECK:STDOUT:   .b = %.loc8\n// CHECK:STDOUT:   .StaticMemberFunction = %SomeClass.StaticMemberFunction.decl\n// CHECK:STDOUT:   .SomeClassAdapter = <poisoned>\n// CHECK:STDOUT:   .AdapterMethod = %SomeClass.AdapterMethod.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @SomeClass.StaticMemberFunction();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @SomeClass.AdapterMethod(%self.param: %SomeClassAdapter);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @TestStaticMemberFunction(%a.param: %SomeClassAdapter) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %SomeClassAdapter = name_ref a, %a\n// CHECK:STDOUT:   %StaticMemberFunction.ref: %SomeClass.StaticMemberFunction.type = name_ref StaticMemberFunction, @SomeClass.%SomeClass.StaticMemberFunction.decl [concrete = constants.%SomeClass.StaticMemberFunction]\n// CHECK:STDOUT:   %SomeClass.StaticMemberFunction.call: init %empty_tuple.type = call %StaticMemberFunction.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @TestAdapterMethod(%a.param: %SomeClassAdapter) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %SomeClassAdapter = name_ref a, %a\n// CHECK:STDOUT:   %AdapterMethod.ref: %SomeClass.AdapterMethod.type = name_ref AdapterMethod, @SomeClass.%SomeClass.AdapterMethod.decl [concrete = constants.%SomeClass.AdapterMethod]\n// CHECK:STDOUT:   %SomeClass.AdapterMethod.bound: <bound method> = bound_method %a.ref, %AdapterMethod.ref\n// CHECK:STDOUT:   %SomeClass.AdapterMethod.call: init %empty_tuple.type = call %SomeClass.AdapterMethod.bound(%a.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_method_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %SomeClass: type = class_type @SomeClass [concrete]\n// CHECK:STDOUT:   %pattern_type.ea0: type = pattern_type %SomeClass [concrete]\n// CHECK:STDOUT:   %SomeClass.F.type: type = fn_type @SomeClass.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %SomeClass.F: %SomeClass.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %SomeClassAdapter: type = class_type @SomeClassAdapter [concrete]\n// CHECK:STDOUT:   %pattern_type.31a: type = pattern_type %SomeClassAdapter [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .SomeClass = %SomeClass.decl\n// CHECK:STDOUT:     .SomeClassAdapter = %SomeClassAdapter.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %SomeClass.decl: type = class_decl @SomeClass [concrete = constants.%SomeClass] {} {}\n// CHECK:STDOUT:   %SomeClassAdapter.decl: type = class_decl @SomeClassAdapter [concrete = constants.%SomeClassAdapter] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.31a = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.31a = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %SomeClassAdapter = value_param call_param0\n// CHECK:STDOUT:     %SomeClassAdapter.ref: type = name_ref SomeClassAdapter, file.%SomeClassAdapter.decl [concrete = constants.%SomeClassAdapter]\n// CHECK:STDOUT:     %a: %SomeClassAdapter = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SomeClass {\n// CHECK:STDOUT:   %SomeClass.F.decl: %SomeClass.F.type = fn_decl @SomeClass.F [concrete = constants.%SomeClass.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.ea0 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.ea0 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %SomeClass = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%SomeClass [concrete = constants.%SomeClass]\n// CHECK:STDOUT:     %self: %SomeClass = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SomeClass\n// CHECK:STDOUT:   .F = %SomeClass.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SomeClassAdapter {\n// CHECK:STDOUT:   %SomeClass.ref: type = name_ref SomeClass, file.%SomeClass.decl [concrete = constants.%SomeClass]\n// CHECK:STDOUT:   adapt_decl %SomeClass.ref [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SomeClassAdapter\n// CHECK:STDOUT:   .SomeClass = <poisoned>\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend %SomeClass.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @SomeClass.F(%self.param: %SomeClass);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %SomeClassAdapter) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %SomeClassAdapter = name_ref a, %a\n// CHECK:STDOUT:   %F.ref: %SomeClass.F.type = name_ref F, @SomeClass.%SomeClass.F.decl [concrete = constants.%SomeClass.F]\n// CHECK:STDOUT:   %SomeClass.F.bound: <bound method> = bound_method %a.ref, %F.ref\n// CHECK:STDOUT:   %.loc23: %SomeClass = converted %a.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %SomeClass.F.call: init %empty_tuple.type = call %SomeClass.F.bound(<error>)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_field_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %SomeClass: type = class_type @SomeClass [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %SomeClass.elem: type = unbound_element_type %SomeClass, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: %i32, .b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.705: <witness> = complete_type_witness %struct_type.a.b [concrete]\n// CHECK:STDOUT:   %SomeClassAdapter: type = class_type @SomeClassAdapter [concrete]\n// CHECK:STDOUT:   %pattern_type.31a: type = pattern_type %SomeClassAdapter [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .SomeClass = %SomeClass.decl\n// CHECK:STDOUT:     .SomeClassAdapter = %SomeClassAdapter.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %SomeClass.decl: type = class_decl @SomeClass [concrete = constants.%SomeClass] {} {}\n// CHECK:STDOUT:   %SomeClassAdapter.decl: type = class_decl @SomeClassAdapter [concrete = constants.%SomeClassAdapter] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.31a = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.31a = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc13: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %SomeClassAdapter = value_param call_param0\n// CHECK:STDOUT:     %SomeClassAdapter.ref: type = name_ref SomeClassAdapter, file.%SomeClassAdapter.decl [concrete = constants.%SomeClassAdapter]\n// CHECK:STDOUT:     %a: %SomeClassAdapter = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SomeClass {\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %SomeClass.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc6: %SomeClass.elem = field_decl b, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SomeClass\n// CHECK:STDOUT:   .a = %.loc5\n// CHECK:STDOUT:   .b = %.loc6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SomeClassAdapter {\n// CHECK:STDOUT:   %SomeClass.ref: type = name_ref SomeClass, file.%SomeClass.decl [concrete = constants.%SomeClass]\n// CHECK:STDOUT:   adapt_decl %SomeClass.ref [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SomeClassAdapter\n// CHECK:STDOUT:   .SomeClass = <poisoned>\n// CHECK:STDOUT:   .b = <poisoned>\n// CHECK:STDOUT:   extend %SomeClass.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %SomeClassAdapter) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %SomeClassAdapter = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %SomeClass.elem = name_ref b, @SomeClass.%.loc6 [concrete = @SomeClass.%.loc6]\n// CHECK:STDOUT:   %.loc21_11.1: %SomeClass = converted %a.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %.loc21_11.2: %i32 = class_element_access <error>, element1 [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_adapt_struct.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %StructAdapter: type = class_type @StructAdapter [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: %i32, .b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.705: <witness> = complete_type_witness %struct_type.a.b [concrete]\n// CHECK:STDOUT:   %pattern_type.7d8: type = pattern_type %StructAdapter [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .StructAdapter = %StructAdapter.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %StructAdapter.decl: type = class_decl @StructAdapter [concrete = constants.%StructAdapter] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7d8 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7d8 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %StructAdapter = value_param call_param0\n// CHECK:STDOUT:     %StructAdapter.ref: type = name_ref StructAdapter, file.%StructAdapter.decl [concrete = constants.%StructAdapter]\n// CHECK:STDOUT:     %a: %StructAdapter = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @StructAdapter {\n// CHECK:STDOUT:   %i32.loc5_21: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %i32.loc5_30: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: %i32, .b: %i32} [concrete = constants.%struct_type.a.b]\n// CHECK:STDOUT:   adapt_decl %struct_type.a.b [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%StructAdapter\n// CHECK:STDOUT:   .b = <poisoned>\n// CHECK:STDOUT:   extend %struct_type.a.b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %StructAdapter) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %StructAdapter = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: <error> = name_ref b, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_adapt_tuple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %TupleAdapter: type = class_type @TupleAdapter [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %complete_type.65d: <witness> = complete_type_witness %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %pattern_type.3a8: type = pattern_type %TupleAdapter [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .TupleAdapter = %TupleAdapter.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %TupleAdapter.decl: type = class_decl @TupleAdapter [concrete = constants.%TupleAdapter] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.3a8 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.3a8 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %TupleAdapter = value_param call_param0\n// CHECK:STDOUT:     %TupleAdapter.ref: type = name_ref TupleAdapter, file.%TupleAdapter.decl [concrete = constants.%TupleAdapter]\n// CHECK:STDOUT:     %a: %TupleAdapter = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @TupleAdapter {\n// CHECK:STDOUT:   %i32.loc5_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %i32.loc5_22: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5_25: %tuple.type.24b = tuple_literal (%i32.loc5_17, %i32.loc5_22) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %.loc5_26: type = converted %.loc5_25, constants.%tuple.type.d07 [concrete = constants.%tuple.type.d07]\n// CHECK:STDOUT:   adapt_decl %.loc5_26 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%tuple.type.d07 [concrete = constants.%complete_type.65d]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%TupleAdapter\n// CHECK:STDOUT:   extend %.loc5_26\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %TupleAdapter) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %TupleAdapter = name_ref a, %a\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_adapt_builtin.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %.805: Core.Form = init_form type [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %MakeInt.type: type = fn_type @MakeInt [concrete]\n// CHECK:STDOUT:   %MakeInt: %MakeInt.type = struct_value () [concrete]\n// CHECK:STDOUT:   %IntAdapter: type = class_type @IntAdapter [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %pattern_type.f40: type = pattern_type %IntAdapter [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .MakeInt = %MakeInt.decl\n// CHECK:STDOUT:     .IntAdapter = %IntAdapter.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %MakeInt.decl: %MakeInt.type = fn_decl @MakeInt [concrete = constants.%MakeInt] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = value_binding_pattern N [concrete]\n// CHECK:STDOUT:     %N.param_patt: %pattern_type.dc0 = value_param_pattern %N.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.98f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.98f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_37.1: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc4_37.2: Core.Form = init_form %.loc4_37.1 [concrete = constants.%.805]\n// CHECK:STDOUT:     %N.param: Core.IntLiteral = value_param call_param0\n// CHECK:STDOUT:     %.loc4_31.1: type = splice_block %.loc4_31.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_31.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_31.3: type = converted %IntLiteral.call, %.loc4_31.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N: Core.IntLiteral = value_binding N, %N.param\n// CHECK:STDOUT:     %return.param: ref type = out_param call_param1\n// CHECK:STDOUT:     %return: ref type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %IntAdapter.decl: type = class_decl @IntAdapter [concrete = constants.%IntAdapter] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.f40 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.f40 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc10: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %IntAdapter = value_param call_param0\n// CHECK:STDOUT:     %IntAdapter.ref: type = name_ref IntAdapter, file.%IntAdapter.decl [concrete = constants.%IntAdapter]\n// CHECK:STDOUT:     %a: %IntAdapter = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @IntAdapter {\n// CHECK:STDOUT:   %MakeInt.ref: %MakeInt.type = name_ref MakeInt, file.%MakeInt.decl [concrete = constants.%MakeInt]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]\n// CHECK:STDOUT:   %MakeInt.call: init type = call %MakeInt.ref(%int_32) [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   %.loc7_27.1: type = value_of_initializer %MakeInt.call [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   %.loc7_27.2: type = converted %MakeInt.call, %.loc7_27.1 [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   adapt_decl %.loc7_27.2 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%i32.builtin [concrete = constants.%complete_type.f8a]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%IntAdapter\n// CHECK:STDOUT:   .MakeInt = <poisoned>\n// CHECK:STDOUT:   .foo = <poisoned>\n// CHECK:STDOUT:   extend %.loc7_27.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MakeInt(%N.param: Core.IntLiteral) -> out %return.param: type = \"int.make_type_signed\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %IntAdapter) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %IntAdapter = name_ref a, %a\n// CHECK:STDOUT:   %foo.ref: <error> = name_ref foo, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/fail_adapt_bad_decl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/fail_adapt_bad_decl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/fail_adapt_bad_decl.carbon\n\n// --- fail_not_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Bad {\n  // CHECK:STDERR: fail_not_type.carbon:[[@LINE+7]]:3: error: cannot implicitly convert non-type value of type `Core.IntLiteral` to `type` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   adapt 100;\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR: fail_not_type.carbon:[[@LINE+4]]:3: note: type `Core.IntLiteral` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   adapt 100;\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR:\n  adapt 100;\n}\n\n// CHECK:STDERR: fail_not_type.carbon:[[@LINE+4]]:18: error: member name `F` not found in `Bad` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: fn Use(b: Bad) { b.F(); }\n// CHECK:STDERR:                  ^~~\n// CHECK:STDERR:\nfn Use(b: Bad) { b.F(); }\n\n// --- fail_extend_not_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Bad {\n  // CHECK:STDERR: fail_extend_not_type.carbon:[[@LINE+7]]:3: error: cannot implicitly convert non-type value of type `Core.IntLiteral` to `type` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   extend adapt 100;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_extend_not_type.carbon:[[@LINE+4]]:3: note: type `Core.IntLiteral` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   extend adapt 100;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend adapt 100;\n}\n\n// No diagnostic here, we don't know what names Bad has.\nfn Use(b: Bad) { b.F(); }\n\n// --- fail_repeated.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass MultipleAdapts {\n  adapt ();\n  // CHECK:STDERR: fail_repeated.carbon:[[@LINE+7]]:3: error: multiple `adapt` declarations in class [AdaptDeclRepeated]\n  // CHECK:STDERR:   adapt {};\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_repeated.carbon:[[@LINE-4]]:3: note: previous `adapt` declaration is here [ClassSpecificDeclPrevious]\n  // CHECK:STDERR:   adapt ();\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR:\n  adapt {};\n}\n\nclass MultipleAdaptsSameType {\n  adapt ();\n  // CHECK:STDERR: fail_repeated.carbon:[[@LINE+7]]:3: error: multiple `adapt` declarations in class [AdaptDeclRepeated]\n  // CHECK:STDERR:   adapt ();\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_repeated.carbon:[[@LINE-4]]:3: note: previous `adapt` declaration is here [ClassSpecificDeclPrevious]\n  // CHECK:STDERR:   adapt ();\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR:\n  adapt ();\n}\n\n// --- fail_bad_scope.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_bad_scope.carbon:[[@LINE+4]]:1: error: `adapt` declaration outside class [ClassSpecificDeclOutsideClass]\n// CHECK:STDERR: adapt {};\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR:\nadapt {};\n\ninterface I {\n  // CHECK:STDERR: fail_bad_scope.carbon:[[@LINE+4]]:3: error: `adapt` declaration outside class [ClassSpecificDeclOutsideClass]\n  // CHECK:STDERR:   adapt {};\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR:\n  adapt {};\n}\n\nclass C {\n  interface I {\n    // CHECK:STDERR: fail_bad_scope.carbon:[[@LINE+4]]:5: error: `adapt` declaration outside class [ClassSpecificDeclOutsideClass]\n    // CHECK:STDERR:     adapt {};\n    // CHECK:STDERR:     ^~~~~~~~~\n    // CHECK:STDERR:\n    adapt {};\n  }\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/fail_adapt_bad_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/fail_adapt_bad_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/fail_adapt_bad_type.carbon\n\n// --- fail_incomplete_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Incomplete;\n\nclass AdaptIncomplete {\n  // CHECK:STDERR: fail_incomplete_type.carbon:[[@LINE+7]]:3: error: adapted type `Incomplete` is an incomplete type [IncompleteTypeInAdaptDecl]\n  // CHECK:STDERR:   adapt Incomplete;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_incomplete_type.carbon:[[@LINE-6]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class Incomplete;\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  adapt Incomplete;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/fail_adapt_modifiers.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/fail_adapt_modifiers.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/fail_adapt_modifiers.carbon\n\nclass B {}\n\nclass C1 {\n  // CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:3: error: `private` not allowed on `adapt` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   private adapt B;\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  private adapt B;\n}\n\nclass C2 {\n  // CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:3: error: `abstract` not allowed on `adapt` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   abstract adapt B;\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR:\n  abstract adapt B;\n}\n\nclass C3 {\n  // CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:3: error: `default` not allowed on `adapt` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   default adapt B;\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  default adapt B;\n}\n\nclass C4 {\n  // CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+7]]:10: error: `extend` repeated on declaration [ModifierRepeated]\n  // CHECK:STDERR:   extend extend adapt B;\n  // CHECK:STDERR:          ^~~~~~\n  // CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:3: note: `extend` previously appeared here [ModifierPrevious]\n  // CHECK:STDERR:   extend extend adapt B;\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR:\n  extend extend adapt B;\n}\n\nclass C5 {\n  // CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:3: error: `base` not allowed on `adapt` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   base adapt B;\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR:\n  base adapt B;\n}\n\nclass C6 {\n  // CHECK:STDERR: fail_adapt_modifiers.carbon:[[@LINE+4]]:10: error: `base` not allowed on `adapt` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   extend base adapt B;\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR:\n  extend base adapt B;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/fail_adapt_with_base.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/fail_adapt_with_base.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/fail_adapt_with_base.carbon\nclass Simple {};\nbase class AdaptWithVirtual {\n  virtual fn F[self: Self]();\n  // CHECK:STDERR: fail_adapt_with_base.carbon:[[@LINE+7]]:3: error: adapter with virtual function [AdaptWithVirtual]\n  // CHECK:STDERR:   adapt Simple;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_adapt_with_base.carbon:[[@LINE-4]]:3: note: first virtual function declaration is here [AdaptWithVirtualHere]\n  // CHECK:STDERR:   virtual fn F[self: Self]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  adapt Simple;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/fail_adapt_with_subobjects.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/fail_adapt_with_subobjects.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/fail_adapt_with_subobjects.carbon\n\n// --- fail_adapt_with_base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base {}\n\nclass AdaptWithBase {\n  // CHECK:STDERR: fail_adapt_with_base.carbon:[[@LINE+3]]:3: error: adapter with base class [AdaptWithBase]\n  // CHECK:STDERR:   adapt i32;\n  // CHECK:STDERR:   ^~~~~~~~~~\n  adapt i32;\n  // CHECK:STDERR: fail_adapt_with_base.carbon:[[@LINE+4]]:3: note: `base` declaration is here [AdaptWithBaseHere]\n  // CHECK:STDERR:   extend base: Base;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend base: Base;\n}\n\n// --- fail_adapt_with_fields.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass AdaptWithField {\n  // CHECK:STDERR: fail_adapt_with_fields.carbon:[[@LINE+3]]:3: error: adapter with fields [AdaptWithFields]\n  // CHECK:STDERR:   adapt i32;\n  // CHECK:STDERR:   ^~~~~~~~~~\n  adapt i32;\n  // CHECK:STDERR: fail_adapt_with_fields.carbon:[[@LINE+4]]:7: note: first field declaration is here [AdaptWithFieldHere]\n  // CHECK:STDERR:   var n: i32;\n  // CHECK:STDERR:       ^~~~~~\n  // CHECK:STDERR:\n  var n: i32;\n}\n\nclass AdaptWithFields {\n  // CHECK:STDERR: fail_adapt_with_fields.carbon:[[@LINE+3]]:3: error: adapter with fields [AdaptWithFields]\n  // CHECK:STDERR:   adapt i32;\n  // CHECK:STDERR:   ^~~~~~~~~~\n  adapt i32;\n  // CHECK:STDERR: fail_adapt_with_fields.carbon:[[@LINE+4]]:7: note: first field declaration is here [AdaptWithFieldHere]\n  // CHECK:STDERR:   var a: i32;\n  // CHECK:STDERR:       ^~~~~~\n  // CHECK:STDERR:\n  var a: i32;\n  var b: i32;\n  var c: i32;\n}\n\n// --- fail_adapt_with_base_and_fields.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base {}\n\nclass AdaptWithBaseAndFields {\n  extend base: Base;\n  var n: i32;\n  // CHECK:STDERR: fail_adapt_with_base_and_fields.carbon:[[@LINE+7]]:3: error: adapter with base class [AdaptWithBase]\n  // CHECK:STDERR:   adapt {};\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_adapt_with_base_and_fields.carbon:[[@LINE-5]]:3: note: `base` declaration is here [AdaptWithBaseHere]\n  // CHECK:STDERR:   extend base: Base;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  adapt {};\n}\n\n// CHECK:STDOUT: --- fail_adapt_with_base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %AdaptWithBase: type = class_type @AdaptWithBase [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %AdaptWithBase.elem: type = unbound_element_type %AdaptWithBase, %Base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .AdaptWithBase = %AdaptWithBase.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %AdaptWithBase.decl: type = class_decl @AdaptWithBase [concrete = constants.%AdaptWithBase] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptWithBase {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   adapt_decl %i32 [concrete]\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc15: %AdaptWithBase.elem = base_decl %Base.ref, element<none> [concrete]\n// CHECK:STDOUT:   complete_type_witness = <error>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptWithBase\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc15\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_adapt_with_fields.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %AdaptWithField: type = class_type @AdaptWithField [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %AdaptWithField.elem: type = unbound_element_type %AdaptWithField, %i32 [concrete]\n// CHECK:STDOUT:   %AdaptWithFields: type = class_type @AdaptWithFields [concrete]\n// CHECK:STDOUT:   %AdaptWithFields.elem: type = unbound_element_type %AdaptWithFields, %i32 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .AdaptWithField = %AdaptWithField.decl\n// CHECK:STDOUT:     .AdaptWithFields = %AdaptWithFields.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %AdaptWithField.decl: type = class_decl @AdaptWithField [concrete = constants.%AdaptWithField] {} {}\n// CHECK:STDOUT:   %AdaptWithFields.decl: type = class_decl @AdaptWithFields [concrete = constants.%AdaptWithFields] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptWithField {\n// CHECK:STDOUT:   %i32.loc8: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   adapt_decl %i32.loc8 [concrete]\n// CHECK:STDOUT:   %i32.loc13: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc13: %AdaptWithField.elem = field_decl n, element<none> [concrete]\n// CHECK:STDOUT:   complete_type_witness = <error>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptWithField\n// CHECK:STDOUT:   .n = %.loc13\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptWithFields {\n// CHECK:STDOUT:   %i32.loc20: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   adapt_decl %i32.loc20 [concrete]\n// CHECK:STDOUT:   %i32.loc25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc25: %AdaptWithFields.elem = field_decl a, element<none> [concrete]\n// CHECK:STDOUT:   %i32.loc26: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc26: %AdaptWithFields.elem = field_decl b, element<none> [concrete]\n// CHECK:STDOUT:   %i32.loc27: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc27: %AdaptWithFields.elem = field_decl c, element<none> [concrete]\n// CHECK:STDOUT:   complete_type_witness = <error>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptWithFields\n// CHECK:STDOUT:   .a = %.loc25\n// CHECK:STDOUT:   .b = %.loc26\n// CHECK:STDOUT:   .c = %.loc27\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_adapt_with_base_and_fields.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %AdaptWithBaseAndFields: type = class_type @AdaptWithBaseAndFields [concrete]\n// CHECK:STDOUT:   %AdaptWithBaseAndFields.elem.43f: type = unbound_element_type %AdaptWithBaseAndFields, %Base [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %AdaptWithBaseAndFields.elem.37a: type = unbound_element_type %AdaptWithBaseAndFields, %i32 [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .AdaptWithBaseAndFields = %AdaptWithBaseAndFields.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %AdaptWithBaseAndFields.decl: type = class_decl @AdaptWithBaseAndFields [concrete = constants.%AdaptWithBaseAndFields] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptWithBaseAndFields {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc7: %AdaptWithBaseAndFields.elem.43f = base_decl %Base.ref, element<none> [concrete]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc8: %AdaptWithBaseAndFields.elem.37a = field_decl n, element<none> [concrete]\n// CHECK:STDOUT:   %.loc16_10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc16_11: type = converted %.loc16_10, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   adapt_decl %.loc16_11 [concrete]\n// CHECK:STDOUT:   complete_type_witness = <error>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptWithBaseAndFields\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc7\n// CHECK:STDOUT:   .n = %.loc8\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/adapter/init_adapt.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/adapter/init_adapt.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/adapter/init_adapt.carbon\n\n// --- init_adapt.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  var a: i32;\n  var b: i32;\n}\n\nclass AdaptC {\n  adapt C;\n}\n\nlet a: C = {.a = 1, .b = 2};\n\nlet b: AdaptC = a as AdaptC;\n\nlet c: C = b as C;\n\nfn MakeC() -> C;\n\nfn MakeAdaptC() -> AdaptC;\n\nvar d: AdaptC = MakeC() as AdaptC;\n\nvar e: C = MakeAdaptC() as C;\n\n// --- fail_not_implicit.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  var a: i32;\n  var b: i32;\n}\n\nclass AdaptC {\n  adapt C;\n}\n\nlet a: C = {.a = 1, .b = 2};\n\n// Cannot implicitly convert between a type and an adapter for the type.\n\n// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:17: error: cannot implicitly convert expression of type `C` to `AdaptC` [ConversionFailure]\n// CHECK:STDERR: let b: AdaptC = a;\n// CHECK:STDERR:                 ^\n// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:17: note: type `C` does not implement interface `Core.ImplicitAs(AdaptC)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: let b: AdaptC = a;\n// CHECK:STDERR:                 ^\n// CHECK:STDERR:\nlet b: AdaptC = a;\n\n// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:12: error: cannot implicitly convert expression of type `AdaptC` to `C` [ConversionFailure]\n// CHECK:STDERR: let c: C = b;\n// CHECK:STDERR:            ^\n// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:12: note: type `AdaptC` does not implement interface `Core.ImplicitAs(C)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: let c: C = b;\n// CHECK:STDERR:            ^\n// CHECK:STDERR:\nlet c: C = b;\n\nfn MakeC() -> C;\n\nfn MakeAdaptC() -> AdaptC;\n\n// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `C` to `AdaptC` [ConversionFailure]\n// CHECK:STDERR: var d: AdaptC = MakeC();\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:1: note: type `C` does not implement interface `Core.ImplicitAs(AdaptC)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var d: AdaptC = MakeC();\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR:\nvar d: AdaptC = MakeC();\n\n// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `AdaptC` to `C` [ConversionFailure]\n// CHECK:STDERR: var e: C = MakeAdaptC();\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_not_implicit.carbon:[[@LINE+4]]:1: note: type `AdaptC` does not implement interface `Core.ImplicitAs(C)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var e: C = MakeAdaptC();\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nvar e: C = MakeAdaptC();\n\n// CHECK:STDOUT: --- init_adapt.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.501: type = struct_type {.a: %i32, .b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.705: <witness> = complete_type_witness %struct_type.a.b.501 [concrete]\n// CHECK:STDOUT:   %AdaptC: type = class_type @AdaptC [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.cfd: type = struct_type {.a: Core.IntLiteral, .b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.a.b.cfd = struct_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %pattern_type.507: type = pattern_type %AdaptC [concrete]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %MakeC.type: type = fn_type @MakeC [concrete]\n// CHECK:STDOUT:   %MakeC: %MakeC.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.e6b: Core.Form = init_form %AdaptC [concrete]\n// CHECK:STDOUT:   %MakeAdaptC.type: type = fn_type @MakeAdaptC [concrete]\n// CHECK:STDOUT:   %MakeAdaptC: %MakeAdaptC.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .AdaptC = %AdaptC.decl\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .MakeC = %MakeC.decl\n// CHECK:STDOUT:     .MakeAdaptC = %MakeAdaptC.decl\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:     .e = %e\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %AdaptC.decl: type = class_decl @AdaptC [concrete = constants.%AdaptC] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7c7 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.ref.loc13: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %impl.elem0.loc13_27.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc13_27.1: <bound method> = bound_method @__global_init.%int_1, %impl.elem0.loc13_27.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc13_27.1: <specific function> = specific_function %impl.elem0.loc13_27.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_27.2: <bound method> = bound_method @__global_init.%int_1, %specific_fn.loc13_27.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13_27.1: init %i32 = call %bound_method.loc13_27.2(@__global_init.%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc13_27.1: init %i32 = converted @__global_init.%int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13_27.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc13_27.2: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc13_27.3: ref %i32 = class_element_access %.loc13_27.2, element0\n// CHECK:STDOUT:   %.loc13_27.4: init %i32 to %.loc13_27.3 = in_place_init %.loc13_27.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc13_27.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc13_27.3: <bound method> = bound_method @__global_init.%int_2, %impl.elem0.loc13_27.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc13_27.2: <specific function> = specific_function %impl.elem0.loc13_27.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_27.4: <bound method> = bound_method @__global_init.%int_2, %specific_fn.loc13_27.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13_27.2: init %i32 = call %bound_method.loc13_27.4(@__global_init.%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc13_27.5: init %i32 = converted @__global_init.%int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13_27.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc13_27.6: ref %i32 = class_element_access %.loc13_27.2, element1\n// CHECK:STDOUT:   %.loc13_27.7: init %i32 to %.loc13_27.6 = in_place_init %.loc13_27.5 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc13_27.8: init %C to %.loc13_27.2 = class_init (%.loc13_27.4, %.loc13_27.7) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc13_27.9: init %C = converted @__global_init.%.loc13, %.loc13_27.8 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc13_27.10: ref %C = temporary %.loc13_27.2, %.loc13_27.9\n// CHECK:STDOUT:   %.loc13_27.11: %C = acquire_value %.loc13_27.10\n// CHECK:STDOUT:   %a: %C = value_binding a, %.loc13_27.11\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.507 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %AdaptC.ref.loc15: type = name_ref AdaptC, %AdaptC.decl [concrete = constants.%AdaptC]\n// CHECK:STDOUT:   %b: %AdaptC = value_binding b, @__global_init.%.loc15_19.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.ref.loc17: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c: %C = value_binding c, @__global_init.%.loc17_14.2\n// CHECK:STDOUT:   %MakeC.decl: %MakeC.type = fn_decl @MakeC [concrete = constants.%MakeC] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc19: Core.Form = init_form %C.ref [concrete = constants.%.a69]\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param0\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %MakeAdaptC.decl: %MakeAdaptC.type = fn_decl @MakeAdaptC [concrete = constants.%MakeAdaptC] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.507 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.507 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptC.ref: type = name_ref AdaptC, file.%AdaptC.decl [concrete = constants.%AdaptC]\n// CHECK:STDOUT:     %.loc21: Core.Form = init_form %AdaptC.ref [concrete = constants.%.e6b]\n// CHECK:STDOUT:     %return.param: ref %AdaptC = out_param call_param0\n// CHECK:STDOUT:     %return: ref %AdaptC = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.507 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.507 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %AdaptC = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %AdaptC.ref.loc23: type = name_ref AdaptC, %AdaptC.decl [concrete = constants.%AdaptC]\n// CHECK:STDOUT:   %d: ref %AdaptC = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %e.patt: %pattern_type.7c7 = ref_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.var_patt: %pattern_type.7c7 = var_pattern %e.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e.var: ref %C = var %e.var_patt [concrete]\n// CHECK:STDOUT:   %C.ref.loc25: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %e: ref %C = ref_binding e, %e.var [concrete = %e.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %C.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc6: %C.elem = field_decl b, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b.501 [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .a = %.loc5\n// CHECK:STDOUT:   .b = %.loc6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptC {\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   adapt_decl %C.ref [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b.501 [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptC\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MakeC() -> out %return.param: %C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MakeAdaptC() -> out %return.param: %AdaptC;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc13: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2) [concrete = constants.%struct]\n// CHECK:STDOUT:   %a.ref: %C = name_ref a, file.%a\n// CHECK:STDOUT:   %AdaptC.ref.loc15: type = name_ref AdaptC, file.%AdaptC.decl [concrete = constants.%AdaptC]\n// CHECK:STDOUT:   %.loc15_19.1: %AdaptC = as_compatible %a.ref\n// CHECK:STDOUT:   %.loc15_19.2: %AdaptC = converted %a.ref, %.loc15_19.1\n// CHECK:STDOUT:   %b.ref: %AdaptC = name_ref b, file.%b\n// CHECK:STDOUT:   %C.ref.loc17: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc17_14.1: %C = as_compatible %b.ref\n// CHECK:STDOUT:   %.loc17_14.2: %C = converted %b.ref, %.loc17_14.1\n// CHECK:STDOUT:   %MakeC.ref: %MakeC.type = name_ref MakeC, file.%MakeC.decl [concrete = constants.%MakeC]\n// CHECK:STDOUT:   %.loc23_1: ref %AdaptC = splice_block file.%d.var [concrete = file.%d.var] {}\n// CHECK:STDOUT:   %MakeC.call: init %C to %.loc23_1 = call %MakeC.ref()\n// CHECK:STDOUT:   %AdaptC.ref.loc23: type = name_ref AdaptC, file.%AdaptC.decl [concrete = constants.%AdaptC]\n// CHECK:STDOUT:   %.loc23_25.1: init %AdaptC = as_compatible %MakeC.call\n// CHECK:STDOUT:   %.loc23_25.2: init %AdaptC = converted %MakeC.call, %.loc23_25.1\n// CHECK:STDOUT:   assign file.%d.var, %.loc23_25.2\n// CHECK:STDOUT:   %MakeAdaptC.ref: %MakeAdaptC.type = name_ref MakeAdaptC, file.%MakeAdaptC.decl [concrete = constants.%MakeAdaptC]\n// CHECK:STDOUT:   %.loc25_1: ref %C = splice_block file.%e.var [concrete = file.%e.var] {}\n// CHECK:STDOUT:   %MakeAdaptC.call: init %AdaptC to %.loc25_1 = call %MakeAdaptC.ref()\n// CHECK:STDOUT:   %C.ref.loc25: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc25_25.1: init %C = as_compatible %MakeAdaptC.call\n// CHECK:STDOUT:   %.loc25_25.2: init %C = converted %MakeAdaptC.call, %.loc25_25.1\n// CHECK:STDOUT:   assign file.%e.var, %.loc25_25.2\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_not_implicit.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.501: type = struct_type {.a: %i32, .b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.705: <witness> = complete_type_witness %struct_type.a.b.501 [concrete]\n// CHECK:STDOUT:   %AdaptC: type = class_type @AdaptC [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.cfd: type = struct_type {.a: Core.IntLiteral, .b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.a.b.cfd = struct_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %pattern_type.507: type = pattern_type %AdaptC [concrete]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %MakeC.type: type = fn_type @MakeC [concrete]\n// CHECK:STDOUT:   %MakeC: %MakeC.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.e6b: Core.Form = init_form %AdaptC [concrete]\n// CHECK:STDOUT:   %MakeAdaptC.type: type = fn_type @MakeAdaptC [concrete]\n// CHECK:STDOUT:   %MakeAdaptC: %MakeAdaptC.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .AdaptC = %AdaptC.decl\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .MakeC = %MakeC.decl\n// CHECK:STDOUT:     .MakeAdaptC = %MakeAdaptC.decl\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:     .e = %e\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %AdaptC.decl: type = class_decl @AdaptC [concrete = constants.%AdaptC] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7c7 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.ref.loc13: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %impl.elem0.loc13_27.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc13_27.1: <bound method> = bound_method @__global_init.%int_1, %impl.elem0.loc13_27.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc13_27.1: <specific function> = specific_function %impl.elem0.loc13_27.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_27.2: <bound method> = bound_method @__global_init.%int_1, %specific_fn.loc13_27.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13_27.1: init %i32 = call %bound_method.loc13_27.2(@__global_init.%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc13_27.1: init %i32 = converted @__global_init.%int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13_27.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc13_27.2: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc13_27.3: ref %i32 = class_element_access %.loc13_27.2, element0\n// CHECK:STDOUT:   %.loc13_27.4: init %i32 to %.loc13_27.3 = in_place_init %.loc13_27.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc13_27.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc13_27.3: <bound method> = bound_method @__global_init.%int_2, %impl.elem0.loc13_27.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc13_27.2: <specific function> = specific_function %impl.elem0.loc13_27.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_27.4: <bound method> = bound_method @__global_init.%int_2, %specific_fn.loc13_27.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13_27.2: init %i32 = call %bound_method.loc13_27.4(@__global_init.%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc13_27.5: init %i32 = converted @__global_init.%int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13_27.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc13_27.6: ref %i32 = class_element_access %.loc13_27.2, element1\n// CHECK:STDOUT:   %.loc13_27.7: init %i32 to %.loc13_27.6 = in_place_init %.loc13_27.5 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc13_27.8: init %C to %.loc13_27.2 = class_init (%.loc13_27.4, %.loc13_27.7) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc13_27.9: init %C = converted @__global_init.%.loc13, %.loc13_27.8 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc13_27.10: ref %C = temporary %.loc13_27.2, %.loc13_27.9\n// CHECK:STDOUT:   %.loc13_27.11: %C = acquire_value %.loc13_27.10\n// CHECK:STDOUT:   %a: %C = value_binding a, %.loc13_27.11\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.507 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %AdaptC.ref.loc24: type = name_ref AdaptC, %AdaptC.decl [concrete = constants.%AdaptC]\n// CHECK:STDOUT:   %.loc24: %AdaptC = converted @__global_init.%a.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %b: %AdaptC = value_binding b, <error> [concrete = <error>]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.ref.loc33: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc33: %C = converted @__global_init.%b.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %c: %C = value_binding c, <error> [concrete = <error>]\n// CHECK:STDOUT:   %MakeC.decl: %MakeC.type = fn_decl @MakeC [concrete = constants.%MakeC] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc35: Core.Form = init_form %C.ref [concrete = constants.%.a69]\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param0\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %MakeAdaptC.decl: %MakeAdaptC.type = fn_decl @MakeAdaptC [concrete = constants.%MakeAdaptC] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.507 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.507 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AdaptC.ref: type = name_ref AdaptC, file.%AdaptC.decl [concrete = constants.%AdaptC]\n// CHECK:STDOUT:     %.loc37: Core.Form = init_form %AdaptC.ref [concrete = constants.%.e6b]\n// CHECK:STDOUT:     %return.param: ref %AdaptC = out_param call_param0\n// CHECK:STDOUT:     %return: ref %AdaptC = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.507 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.507 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %AdaptC = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %AdaptC.ref.loc46: type = name_ref AdaptC, %AdaptC.decl [concrete = constants.%AdaptC]\n// CHECK:STDOUT:   %d: ref %AdaptC = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %e.patt: %pattern_type.7c7 = ref_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.var_patt: %pattern_type.7c7 = var_pattern %e.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e.var: ref %C = var %e.var_patt [concrete]\n// CHECK:STDOUT:   %C.ref.loc55: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %e: ref %C = ref_binding e, %e.var [concrete = %e.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %C.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc6: %C.elem = field_decl b, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b.501 [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .a = %.loc5\n// CHECK:STDOUT:   .b = %.loc6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AdaptC {\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   adapt_decl %C.ref [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b.501 [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AdaptC\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MakeC() -> out %return.param: %C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MakeAdaptC() -> out %return.param: %AdaptC;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc13: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2) [concrete = constants.%struct]\n// CHECK:STDOUT:   %a.ref: %C = name_ref a, file.%a\n// CHECK:STDOUT:   %b.ref: %AdaptC = name_ref b, file.%b [concrete = <error>]\n// CHECK:STDOUT:   %MakeC.ref: %MakeC.type = name_ref MakeC, file.%MakeC.decl [concrete = constants.%MakeC]\n// CHECK:STDOUT:   %.loc46_23: ref %C = temporary_storage\n// CHECK:STDOUT:   %MakeC.call: init %C to %.loc46_23 = call %MakeC.ref()\n// CHECK:STDOUT:   %.loc46_1: %AdaptC = converted %MakeC.call, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%d.var, <error>\n// CHECK:STDOUT:   %MakeAdaptC.ref: %MakeAdaptC.type = name_ref MakeAdaptC, file.%MakeAdaptC.decl [concrete = constants.%MakeAdaptC]\n// CHECK:STDOUT:   %.loc55_23: ref %AdaptC = temporary_storage\n// CHECK:STDOUT:   %MakeAdaptC.call: init %AdaptC to %.loc55_23 = call %MakeAdaptC.ref()\n// CHECK:STDOUT:   %.loc55_1: %C = converted %MakeAdaptC.call, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%e.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/basic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/basic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/basic.carbon\n\nclass Class {\n  fn F(n: i32) -> i32 {\n    return n;\n  }\n\n  fn G(n: i32) -> i32;\n\n  var k: i32;\n}\n\nfn Class.G(n: i32) -> i32 {\n  return n;\n}\n\nfn Run() -> i32 {\n  return Class.F(4);\n}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G [concrete]\n// CHECK:STDOUT:   %Class.G: %Class.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.k: type = struct_type {.k: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.954: <witness> = complete_type_witness %struct_type.k [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_4.940: %i32 = int_value 4 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc25_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc25: Core.Form = init_form %i32.loc25_23 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param.loc25: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc25_15: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n.loc25: %i32 = value_binding n, %n.param.loc25\n// CHECK:STDOUT:     %return.param.loc25: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc25: ref %i32 = return_slot %return.param.loc25\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc29: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc16_19: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32.loc16_19 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc16_11: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc20_19: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc20: Core.Form = init_form %i32.loc20_19 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param.loc20: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc20_11: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n.loc20: %i32 = value_binding n, %n.param.loc20\n// CHECK:STDOUT:     %return.param.loc20: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc20: ref %i32 = return_slot %return.param.loc20\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc22: %Class.elem = field_decl k, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.k [concrete = constants.%complete_type.954]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT:   .G = %Class.G.decl\n// CHECK:STDOUT:   .k = %.loc22\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F(%n.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc17_12.1: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc17_12.2: <bound method> = bound_method %n.ref, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc17_12.2(%n.ref)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.G(%n.param.loc25: %i32) -> out %return.param.loc25: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n.loc25\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc26_10.1: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc26_10.2: <bound method> = bound_method %n.ref, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc26_10.2(%n.ref)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc30_18.1: <bound method> = bound_method %int_4, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc30_18.2: <bound method> = bound_method %int_4, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc30_18.2(%int_4) [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc30_18.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc30_18.2: %i32 = converted %int_4, %.loc30_18.1 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %F.ref(%.loc30_18.2)\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/complete_in_member_fn.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/complete_in_member_fn.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/complete_in_member_fn.carbon\n\nclass C {\n  fn F(c: C) -> i32 { return c.a; }\n\n  var a: i32;\n}\n\n// CHECK:STDOUT: --- complete_in_member_fn.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.fd7: <witness> = complete_type_witness %struct_type.a [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %C.F.decl: %C.F.type = fn_decl @C.F [concrete = constants.%C.F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.7c7 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16_17: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc18: %C.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a [concrete = constants.%complete_type.fd7]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT:   .F = %C.F.decl\n// CHECK:STDOUT:   .a = %.loc18\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F(%c.param: %C) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %a.ref: %C.elem = name_ref a, @C.%.loc18 [concrete = @C.%.loc18]\n// CHECK:STDOUT:   %.loc16_31.1: ref %i32 = class_element_access %c.ref, element0\n// CHECK:STDOUT:   %.loc16_31.2: %i32 = acquire_value %.loc16_31.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc16_31.1: <bound method> = bound_method %.loc16_31.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_31.2: <bound method> = bound_method %.loc16_31.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc16_31.2(%.loc16_31.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/cross_package_import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/cross_package_import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/cross_package_import.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- other_define.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// --- other_extern.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nextern class C;\n\n// --- other_conflict.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nfn C() {}\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- define.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Other library \"other_define\";\n\nvar c: Other.C = {};\n\n// --- fail_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Other library \"other_extern\";\n\n// CHECK:STDERR: fail_extern.carbon:[[@LINE+8]]:8: error: binding pattern has incomplete type `C` in name binding declaration [IncompleteTypeInBindingDecl]\n// CHECK:STDERR: var c: Other.C = {};\n// CHECK:STDERR:        ^~~~~~~\n// CHECK:STDERR: fail_extern.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: other_extern.carbon:4:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar c: Other.C = {};\n\n// --- fail_todo_merge_define_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE+8]]:1: in import [InImport]\n// CHECK:STDERR: other_extern.carbon:4:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE+4]]:1: in import [InImport]\n// CHECK:STDERR: other_define.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\nimport Other library \"other_define\";\nimport Other library \"other_extern\";\n\n// CHECK:STDERR: fail_todo_merge_define_extern.carbon:[[@LINE+4]]:8: note: in name lookup for `C` [InNameLookup]\n// CHECK:STDERR: var c: Other.C = {};\n// CHECK:STDERR:        ^~~~~~~\n// CHECK:STDERR:\nvar c: Other.C = {};\n\n// --- fail_conflict.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_conflict.carbon:[[@LINE+8]]:1: in import [InImport]\n// CHECK:STDERR: other_conflict.carbon:4:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: fn C() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_conflict.carbon:[[@LINE+4]]:1: in import [InImport]\n// CHECK:STDERR: other_define.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\nimport Other library \"other_define\";\nimport Other library \"other_conflict\";\n\n// CHECK:STDERR: fail_conflict.carbon:[[@LINE+4]]:8: note: in name lookup for `C` [InNameLookup]\n// CHECK:STDERR: var c: Other.C = {};\n// CHECK:STDERR:        ^~~~~~~\n// CHECK:STDERR:\nvar c: Other.C = {};\n\n// CHECK:STDOUT: --- other_define.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- other_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- other_conflict.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- define.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Other: <namespace> = namespace file.%Other.import, [concrete] {\n// CHECK:STDOUT:     .C = %Other.C\n// CHECK:STDOUT:     import Other//other_define\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Other.C: type = import_ref Other//other_define, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Other.import_ref.8f2: <witness> = import_ref Other//other_define, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Other.import_ref.42d = import_ref Other//other_define, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Other = imports.%Other\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Other.import = import Other\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:     %Other.ref: <namespace> = name_ref Other, imports.%Other [concrete = imports.%Other]\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Other.C [concrete = constants.%C]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"other_define.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Other.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Other.import_ref.42d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc6_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc6_19.2: init %C to file.%c.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc6_1: init %C = converted %.loc6_19.1, %.loc6_19.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%c.var, %.loc6_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Other: <namespace> = namespace file.%Other.import, [concrete] {\n// CHECK:STDOUT:     .C = %Other.C\n// CHECK:STDOUT:     import Other//other_extern\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Other.C: type = import_ref Other//other_extern, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Other = imports.%Other\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Other.import = import Other\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: <error> = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: <error> = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref <error> = var %c.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.loc14: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:     %Other.ref: <namespace> = name_ref Other, imports.%Other [concrete = imports.%Other]\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Other.C [concrete = constants.%C]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref <error> = ref_binding c, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"other_extern.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc14: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   assign file.%c.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_merge_define_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Other: <namespace> = namespace file.%Other.import, [concrete] {\n// CHECK:STDOUT:     .C = %Other.C\n// CHECK:STDOUT:     import Other//other_define\n// CHECK:STDOUT:     import Other//other_extern\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Other.C: type = import_ref Other//other_define, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Other.import_ref.8f2: <witness> = import_ref Other//other_define, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Other.import_ref.42d = import_ref Other//other_define, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Other = imports.%Other\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Other.import = import Other\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc19: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:     %Other.ref: <namespace> = name_ref Other, imports.%Other [concrete = imports.%Other]\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Other.C [concrete = constants.%C]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"other_define.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Other.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Other.import_ref.42d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc19_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc19_19.2: init %C to file.%c.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc19_1: init %C = converted %.loc19_19.1, %.loc19_19.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%c.var, %.loc19_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_conflict.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Other: <namespace> = namespace file.%Other.import, [concrete] {\n// CHECK:STDOUT:     .C = %Other.C\n// CHECK:STDOUT:     import Other//other_define\n// CHECK:STDOUT:     import Other//other_conflict\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Other.C: type = import_ref Other//other_define, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Other.import_ref.8f2: <witness> = import_ref Other//other_define, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Other.import_ref.42d = import_ref Other//other_define, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Other = imports.%Other\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Other.import = import Other\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc19: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:     %Other.ref: <namespace> = name_ref Other, imports.%Other [concrete = imports.%Other]\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Other.C [concrete = constants.%C]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"other_define.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Other.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Other.import_ref.42d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc19_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc19_19.2: init %C to file.%c.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc19_1: init %C = converted %.loc19_19.1, %.loc19_19.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%c.var, %.loc19_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/destroy_calls.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/destroy_calls.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/destroy_calls.carbon\n\n// --- implicit_return.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {}\nclass B {}\nclass C {}\n\n//@dump-sem-ir-begin\nfn F() {\n  var unused a: A = {};\n  var unused b: B = {};\n  var unused c: C = {};\n}\n//@dump-sem-ir-end\n\n// --- nested_scope.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {}\nclass B {}\nclass C {}\n\n//@dump-sem-ir-begin\nfn F() {\n  var unused a: A = {};\n  var unused b: B = {};\n  if (true) {\n    var unused c: C = {};\n  }\n}\n//@dump-sem-ir-end\n\n// --- temp.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A { fn Make() -> A; }\nclass B { fn Make() -> B; }\nclass C { fn Make() -> C; }\n\n//@dump-sem-ir-begin\nfn F() {\n  // TODO: The scoping of these destroy calls is incorrect. Maybe we need to\n  // establish statement scopes?\n  A.Make();\n  B.Make();\n  C.Make();\n}\n//@dump-sem-ir-end\n\n// --- generic_class.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nclass D(template T:! type) {}\n\n//@dump-sem-ir-begin\nfn F() {\n  var unused a: D(C) = {};\n}\n//@dump-sem-ir-end\n\n// --- generic_use_inside_generic.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(template T:! type) {}\n\n//@dump-sem-ir-begin\nfn F(template T:! type) {\n  var unused v: C(T) = {};\n}\n//@dump-sem-ir-end\n\nfn G() { F({}); }\n\n// CHECK:STDOUT: --- implicit_return.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.val: %A = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %B.val: %B = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc12 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc11 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc10 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1ab = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.1ab = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %A = var %a.var_patt\n// CHECK:STDOUT:   %.loc10_22.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc10_22.2: init %A to %a.var = class_init () [concrete = constants.%A.val]\n// CHECK:STDOUT:   %.loc10_3: init %A = converted %.loc10_22.1, %.loc10_22.2 [concrete = constants.%A.val]\n// CHECK:STDOUT:   assign %a.var, %.loc10_3\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %a: ref %A = ref_binding a, %a.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.1f4 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.1f4 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %B = var %b.var_patt\n// CHECK:STDOUT:   %.loc11_22.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc11_22.2: init %B to %b.var = class_init () [concrete = constants.%B.val]\n// CHECK:STDOUT:   %.loc11_3: init %B = converted %.loc11_22.1, %.loc11_22.2 [concrete = constants.%B.val]\n// CHECK:STDOUT:   assign %b.var, %.loc11_3\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %b: ref %B = ref_binding b, %b.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.7c7 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt\n// CHECK:STDOUT:   %.loc12_22.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc12_22.2: init %C to %c.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc12_3: init %C = converted %.loc12_22.1, %.loc12_22.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign %c.var, %.loc12_3\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc12: <bound method> = bound_method %c.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc12: init %empty_tuple.type = call %Destroy.Op.bound.loc12(%c.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc11: <bound method> = bound_method %b.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%b.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10: <bound method> = bound_method %a.var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc10: init %empty_tuple.type = call %Destroy.Op.bound.loc10(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc12(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc11(%self.param: ref %B) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10(%self.param: ref %A) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- nested_scope.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.val: %A = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %B.val: %B = struct_value () [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc13 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc11 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc10 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1ab = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.1ab = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %A = var %a.var_patt\n// CHECK:STDOUT:   %.loc10_22.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc10_22.2: init %A to %a.var = class_init () [concrete = constants.%A.val]\n// CHECK:STDOUT:   %.loc10_3: init %A = converted %.loc10_22.1, %.loc10_22.2 [concrete = constants.%A.val]\n// CHECK:STDOUT:   assign %a.var, %.loc10_3\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %a: ref %A = ref_binding a, %a.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.1f4 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.1f4 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %B = var %b.var_patt\n// CHECK:STDOUT:   %.loc11_22.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc11_22.2: init %B to %b.var = class_init () [concrete = constants.%B.val]\n// CHECK:STDOUT:   %.loc11_3: init %B = converted %.loc11_22.1, %.loc11_22.2 [concrete = constants.%B.val]\n// CHECK:STDOUT:   assign %b.var, %.loc11_3\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %b: ref %B = ref_binding b, %b.var\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:   if %true br !if.then else br !if.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.then:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.7c7 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt\n// CHECK:STDOUT:   %.loc13_24.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc13_24.2: init %C to %c.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc13_5: init %C = converted %.loc13_24.1, %.loc13_24.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign %c.var, %.loc13_5\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var\n// CHECK:STDOUT:   br !if.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.else:\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13: <bound method> = bound_method %c.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc13: init %empty_tuple.type = call %Destroy.Op.bound.loc13(%c.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc11: <bound method> = bound_method %b.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc11: init %empty_tuple.type = call %Destroy.Op.bound.loc11(%b.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10: <bound method> = bound_method %a.var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc10: init %empty_tuple.type = call %Destroy.Op.bound.loc10(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc13(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc11(%self.param: ref %B) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10(%self.param: ref %A) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- temp.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %A.Make.type: type = fn_type @A.Make [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %A.Make: %A.Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.Make.type: type = fn_type @B.Make [concrete]\n// CHECK:STDOUT:   %B.Make: %B.Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.Make.type: type = fn_type @C.Make [concrete]\n// CHECK:STDOUT:   %C.Make: %C.Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc14 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc13 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc12 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %Make.ref.loc12: %A.Make.type = name_ref Make, @A.%A.Make.decl [concrete = constants.%A.Make]\n// CHECK:STDOUT:   %.loc12_10.1: ref %A = temporary_storage\n// CHECK:STDOUT:   %A.Make.call: init %A to %.loc12_10.1 = call %Make.ref.loc12()\n// CHECK:STDOUT:   %.loc12_10.2: ref %A = temporary %.loc12_10.1, %A.Make.call\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %Make.ref.loc13: %B.Make.type = name_ref Make, @B.%B.Make.decl [concrete = constants.%B.Make]\n// CHECK:STDOUT:   %.loc13_10.1: ref %B = temporary_storage\n// CHECK:STDOUT:   %B.Make.call: init %B to %.loc13_10.1 = call %Make.ref.loc13()\n// CHECK:STDOUT:   %.loc13_10.2: ref %B = temporary %.loc13_10.1, %B.Make.call\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Make.ref.loc14: %C.Make.type = name_ref Make, @C.%C.Make.decl [concrete = constants.%C.Make]\n// CHECK:STDOUT:   %.loc14_10.1: ref %C = temporary_storage\n// CHECK:STDOUT:   %C.Make.call: init %C to %.loc14_10.1 = call %Make.ref.loc14()\n// CHECK:STDOUT:   %.loc14_10.2: ref %C = temporary %.loc14_10.1, %C.Make.call\n// CHECK:STDOUT:   %Destroy.Op.bound.loc14: <bound method> = bound_method %.loc14_10.2, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc14: init %empty_tuple.type = call %Destroy.Op.bound.loc14(%.loc14_10.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13: <bound method> = bound_method %.loc13_10.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc13: init %empty_tuple.type = call %Destroy.Op.bound.loc13(%.loc13_10.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc12: <bound method> = bound_method %.loc12_10.2, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc12: init %empty_tuple.type = call %Destroy.Op.bound.loc12(%.loc12_10.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc14(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc13(%self.param: ref %B) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc12(%self.param: ref %A) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- generic_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %D.type: type = generic_class_type @D [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %D.generic: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D.213: type = class_type @D, @D(%C) [concrete]\n// CHECK:STDOUT:   %pattern_type.002: type = pattern_type %D.213 [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %D.val: %D.213 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.002 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.002 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %D.213 = var %a.var_patt\n// CHECK:STDOUT:   %.loc9_25.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_25.2: init %D.213 to %a.var = class_init () [concrete = constants.%D.val]\n// CHECK:STDOUT:   %.loc9_3: init %D.213 = converted %.loc9_25.1, %.loc9_25.2 [concrete = constants.%D.val]\n// CHECK:STDOUT:   assign %a.var, %.loc9_3\n// CHECK:STDOUT:   %.loc9_20: type = splice_block %D [concrete = constants.%D.213] {\n// CHECK:STDOUT:     %D.ref: %D.type = name_ref D, file.%D.decl [concrete = constants.%D.generic]\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %D: type = class_type @D, @D(constants.%C) [concrete = constants.%D.213]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %D.213 = ref_binding a, %a.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %D.213) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- generic_use_inside_generic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [template]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %C.5a3 [template]\n// CHECK:STDOUT:   %pattern_type.3d5: type = pattern_type %C.5a3 [template]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val.8b3: %C.5a3 = struct_value () [template]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %C.5a3, @Destroy [template]\n// CHECK:STDOUT:   %Destroy.facet.472: %Destroy.type = facet_value %C.5a3, (%Destroy.lookup_impl_witness) [template]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.7d1: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.472) [template]\n// CHECK:STDOUT:   %.306: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.7d1, %Destroy.facet.472 [template]\n// CHECK:STDOUT:   %impl.elem0: %.306 = impl_witness_access %Destroy.lookup_impl_witness, element0 [template]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Destroy.WithSelf.Op(%Destroy.facet.472) [template]\n// CHECK:STDOUT:   %C.850: type = class_type @C, @C(%empty_struct_type) [concrete]\n// CHECK:STDOUT:   %pattern_type.526: type = pattern_type %C.850 [concrete]\n// CHECK:STDOUT:   %C.val.09d: %C.850 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %custom_witness.8d7: <witness> = custom_witness (%Destroy.Op), @Destroy [concrete]\n// CHECK:STDOUT:   %Destroy.facet.81b: %Destroy.type = facet_value %C.850, (%custom_witness.8d7) [concrete]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.599: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.81b) [concrete]\n// CHECK:STDOUT:   %.540: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.599, %Destroy.facet.81b [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_19.1: type = splice_block %.loc6_19.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc6_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_15.2: type = symbolic_binding T, 0, template [template = %T.loc6_15.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_15.2: type) {\n// CHECK:STDOUT:   %T.loc6_15.1: type = symbolic_binding T, 0, template [template = %T.loc6_15.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.loc7_20.2: type = class_type @C, @C(%T.loc6_15.1) [template = %C.loc7_20.2 (constants.%C.5a3)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %C.loc7_20.2 [template = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C.loc7_20.2 [template = %pattern_type (constants.%pattern_type.3d5)]\n// CHECK:STDOUT:   %C.val: @F.%C.loc7_20.2 (%C.5a3) = struct_value () [template = %C.val (constants.%C.val.8b3)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %C.loc7_20.2, @Destroy [template = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %C.loc7_20.2, (%Destroy.lookup_impl_witness) [template = %Destroy.facet (constants.%Destroy.facet.472)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [template = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.7d1)]\n// CHECK:STDOUT:   %.loc7_3.2: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %Destroy.facet [template = %.loc7_3.2 (constants.%.306)]\n// CHECK:STDOUT:   %impl.elem0.loc7_3.2: @F.%.loc7_3.2 (%.306) = impl_witness_access %Destroy.lookup_impl_witness, element0 [template = %impl.elem0.loc7_3.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc7_3.2: <specific function> = specific_impl_function %impl.elem0.loc7_3.2, @Destroy.WithSelf.Op(%Destroy.facet) [template = %specific_impl_fn.loc7_3.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %v.patt: @F.%pattern_type (%pattern_type.3d5) = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:       %v.var_patt: @F.%pattern_type (%pattern_type.3d5) = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v.var: ref @F.%C.loc7_20.2 (%C.5a3) = var %v.var_patt\n// CHECK:STDOUT:     %.loc7_25.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc7_25.2: init @F.%C.loc7_20.2 (%C.5a3) to %v.var = class_init () [template = %C.val (constants.%C.val.8b3)]\n// CHECK:STDOUT:     %.loc7_3.1: init @F.%C.loc7_20.2 (%C.5a3) = converted %.loc7_25.1, %.loc7_25.2 [template = %C.val (constants.%C.val.8b3)]\n// CHECK:STDOUT:     assign %v.var, %.loc7_3.1\n// CHECK:STDOUT:     %.loc7_20: type = splice_block %C.loc7_20.1 [template = %C.loc7_20.2 (constants.%C.5a3)] {\n// CHECK:STDOUT:       %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc6_15.2 [template = %T.loc6_15.1 (constants.%T)]\n// CHECK:STDOUT:       %C.loc7_20.1: type = class_type @C, @C(constants.%T) [template = %C.loc7_20.2 (constants.%C.5a3)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v: ref @F.%C.loc7_20.2 (%C.5a3) = ref_binding v, %v.var\n// CHECK:STDOUT:     %impl.elem0.loc7_3.1: @F.%.loc7_3.2 (%.306) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [template = %impl.elem0.loc7_3.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %bound_method.loc7_3.1: <bound method> = bound_method %v.var, %impl.elem0.loc7_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc7_3.1: <specific function> = specific_impl_function %impl.elem0.loc7_3.1, @Destroy.WithSelf.Op(constants.%Destroy.facet.472) [template = %specific_impl_fn.loc7_3.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %bound_method.loc7_3.2: <bound method> = bound_method %v.var, %specific_impl_fn.loc7_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call: init %empty_tuple.type = call %bound_method.loc7_3.2(%v.var)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %C.850) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_15.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %T.loc6_15.1 => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.loc7_20.2 => constants.%C.850\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.526\n// CHECK:STDOUT:   %C.val => constants.%C.val.09d\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%custom_witness.8d7\n// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.81b\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type => constants.%Destroy.WithSelf.Op.type.599\n// CHECK:STDOUT:   %.loc7_3.2 => constants.%.540\n// CHECK:STDOUT:   %impl.elem0.loc7_3.2 => constants.%Destroy.Op\n// CHECK:STDOUT:   %specific_impl_fn.loc7_3.2 => constants.%Destroy.Op\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/export_name.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/export_name.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/export_name.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// --- export.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"base\";\n\nexport C;\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- use_export.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"export\";\n\nvar c: C = {};\n\n// CHECK:STDOUT: --- base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- export.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//base, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//base, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//base, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C: type = export C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"base.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_export.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//export, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8db: <witness> = import_ref Main//export, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.a60 = import_ref Main//export, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"export.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a60\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc6_13.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc6_13.2: init %C to file.%c.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc6_1: init %C = converted %.loc6_13.1, %.loc6_13.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%c.var, %.loc6_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/extern.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/extern.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/extern.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n// --- extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern class C;\n\n// --- extern_decl_copy.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern class C;\n\n// --- def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- fail_decl_fn_in_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern class C;\n// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE+7]]:4: error: cannot declare a member of incomplete class `C` [QualifiedDeclInIncompleteClassScope]\n// CHECK:STDERR: fn C.F();\n// CHECK:STDERR:    ^\n// CHECK:STDERR: fail_decl_fn_in_extern.carbon:[[@LINE-4]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn C.F();\n\n// --- extern_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern class C {}\n\n// --- fail_extern_decl_after_extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern class C;\n// CHECK:STDERR: fail_extern_decl_after_extern_decl.carbon:[[@LINE+7]]:1: error: redeclaration of `class C` is redundant [RedeclRedundant]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_decl_after_extern_decl.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern class C;\n\n// --- fail_decl_after_extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern class C;\n// CHECK:STDERR: fail_decl_after_extern_decl.carbon:[[@LINE+7]]:1: error: redeclaration of `class C` is redundant [RedeclRedundant]\n// CHECK:STDERR: class C;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_decl_after_extern_decl.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nclass C;\n\n// --- fail_extern_member_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  // CHECK:STDERR: fail_extern_member_class.carbon:[[@LINE+4]]:3: error: `extern` not allowed; requires file or namespace scope [ModifierExternNotAllowed]\n  // CHECK:STDERR:   extern class D;\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR:\n  extern class D;\n}\n\n// --- fail_def_after_extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern class C;\n// CHECK:STDERR: fail_def_after_extern_decl.carbon:[[@LINE+7]]:1: error: redeclarations of `class C` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR: fail_def_after_extern_decl.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nclass C {}\n\n// --- fail_extern_decl_after_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n// CHECK:STDERR: fail_extern_decl_after_decl.carbon:[[@LINE+7]]:1: error: redeclaration of `class C` is redundant [RedeclRedundant]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_decl_after_decl.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: class C;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nextern class C;\n\n// --- fail_import_extern_decl_then_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_import_extern_decl_then_decl.carbon:[[@LINE+9]]:1: in import [InImport]\n// CHECK:STDERR: decl.carbon:4:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: class C;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_import_extern_decl_then_decl.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: extern_decl.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimport library \"extern_decl\";\nimport library \"decl\";\n\n// --- fail_import_decl_then_extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_import_decl_then_extern_decl.carbon:[[@LINE+9]]:1: in import [InImport]\n// CHECK:STDERR: extern_decl.carbon:4:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_import_decl_then_extern_decl.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: decl.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: class C;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nimport library \"decl\";\nimport library \"extern_decl\";\n\n// --- fail_import_extern_decl_then_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_import_extern_decl_then_def.carbon:[[@LINE+9]]:1: in import [InImport]\n// CHECK:STDERR: def.carbon:4:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR: fail_import_extern_decl_then_def.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: extern_decl.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimport library \"extern_decl\";\nimport library \"def\";\n\n// --- fail_import_ownership_conflict.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+18]]:1: in import [InImport]\n// CHECK:STDERR: decl.carbon:4:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: class C;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+14]]:1: in import [InImport]\n// CHECK:STDERR: extern_decl.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+9]]:1: in import [InImport]\n// CHECK:STDERR: def.carbon:4:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR: fail_import_ownership_conflict.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: extern_decl.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimport library \"extern_decl\";\nimport library \"decl\";\nimport library \"def\";\n\n// --- fail_todo_import_extern_decl_copy.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE+9]]:1: in import [InImport]\n// CHECK:STDERR: extern_decl_copy.carbon:4:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_todo_import_extern_decl_copy.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: extern_decl.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimport library \"extern_decl\";\nimport library \"extern_decl_copy\";\n\n// --- fail_extern_decl_after_import_extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_decl\";\n\n// CHECK:STDERR: fail_extern_decl_after_import_extern_decl.carbon:[[@LINE+8]]:1: error: redeclaration of `class C` is redundant [RedeclRedundant]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_decl_after_import_extern_decl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_decl.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern class C;\n\n// --- fail_decl_after_import_extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"decl\";\n\n// CHECK:STDERR: fail_decl_after_import_extern_decl.carbon:[[@LINE+8]]:1: error: redeclarations of `class C` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_decl_after_import_extern_decl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: decl.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: class C;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nextern class C;\n\n// --- fail_def_after_import_extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"def\";\n\n// CHECK:STDERR: fail_def_after_import_extern_decl.carbon:[[@LINE+8]]:1: error: redeclarations of `class C` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_def_after_import_extern_decl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: def.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR:\nextern class C;\n\n// --- fail_extern_decl_after_import_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"def\";\n\n// CHECK:STDERR: fail_extern_decl_after_import_def.carbon:[[@LINE+8]]:1: error: redeclarations of `class C` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_decl_after_import_def.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: def.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR:\nextern class C;\n\n// CHECK:STDOUT: --- decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_decl_copy.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_decl_fn_in_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_decl_after_extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc4: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.decl.loc12: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_decl_after_extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl.loc12\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc4: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.decl.loc12: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_member_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .D = %D.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_def_after_extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl.loc12\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc4: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.decl.loc12: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_decl_after_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc4: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.decl.loc12: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_import_extern_decl_then_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//extern_decl, C, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_import_decl_then_extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//decl, C, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_import_extern_decl_then_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//extern_decl, C, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_import_ownership_conflict.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//extern_decl, C, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_import_extern_decl_copy.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//extern_decl, C, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_decl_after_import_extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_decl_after_import_extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_def_after_import_extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//def, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//def, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_decl_after_import_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//def, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//def, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/extern_library.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/extern_library.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/extern_library.carbon\n\n// --- fail_todo.carbon\n\n// CHECK:STDERR: fail_todo.carbon:[[@LINE+4]]:1: error: semantics TODO: `extern library` [SemanticsTodo]\n// CHECK:STDERR: extern library \"foo\" class C;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern library \"foo\" class C;\n\n// CHECK:STDOUT: --- fail_todo.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_compound_type_mismatch.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_compound_type_mismatch.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_compound_type_mismatch.carbon\n\nclass A {\n  var a: i32;\n}\n\nclass B {\n  var b: i32;\n}\n\nfn AccessBInA(a: A) -> i32 {\n  // CHECK:STDERR: fail_compound_type_mismatch.carbon:[[@LINE+7]]:10: error: cannot implicitly convert expression of type `A` to `B` [ConversionFailure]\n  // CHECK:STDERR:   return a.(B.b);\n  // CHECK:STDERR:          ^~~~~~~\n  // CHECK:STDERR: fail_compound_type_mismatch.carbon:[[@LINE+4]]:10: note: type `A` does not implement interface `Core.ImplicitAs(B)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return a.(B.b);\n  // CHECK:STDERR:          ^~~~~~~\n  // CHECK:STDERR:\n  return a.(B.b);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_convert_to_invalid.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_convert_to_invalid.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_convert_to_invalid.carbon\n\nclass C {\n  // CHECK:STDERR: fail_convert_to_invalid.carbon:[[@LINE+4]]:10: error: name `NoSuchType` not found [NameNotFound]\n  // CHECK:STDERR:   var a: NoSuchType;\n  // CHECK:STDERR:          ^~~~~~~~~~\n  // CHECK:STDERR:\n  var a: NoSuchType;\n}\n\nfn Make() -> C {\n  return {.a = ()};\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_error_recovery.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_error_recovery.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_error_recovery.carbon\n\n// --- fail_virtual_fn_in_invalid_context.carbon\n\n// CHECK:STDERR: fail_virtual_fn_in_invalid_context.carbon:[[@LINE+4]]:17: error: name `error_not_found` not found [NameNotFound]\n// CHECK:STDERR: fn F(unused N:! error_not_found) {\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused N:! error_not_found) {\n  base class C {\n    virtual fn Foo[unused self: Self]() {}\n  }\n\n  base class D {\n    extend base: C;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_import_misuses.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_import_misuses.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_import_misuses.carbon\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Empty {\n}\n\nclass Incomplete;\n\n// --- fail_b.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\n\n// CHECK:STDERR: fail_b.carbon:[[@LINE+8]]:1: error: redeclaration of `class Empty` is redundant [RedeclRedundant]\n// CHECK:STDERR: class Empty {\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR: fail_b.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: a.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: class Empty {\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR:\nclass Empty {\n}\n\n// CHECK:STDERR: fail_b.carbon:[[@LINE+8]]:8: error: binding pattern has incomplete type `Incomplete` in name binding declaration [IncompleteTypeInBindingDecl]\n// CHECK:STDERR: var a: Incomplete;\n// CHECK:STDERR:        ^~~~~~~~~~\n// CHECK:STDERR: fail_b.carbon:[[@LINE-16]]:1: in import [InImport]\n// CHECK:STDERR: a.carbon:7:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class Incomplete;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar a: Incomplete;\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_incomplete.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_incomplete.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_incomplete.carbon\n\n// --- fail_forward_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class;\n\n// CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+7]]:4: error: cannot declare a member of incomplete class `Class` [QualifiedDeclInIncompleteClassScope]\n// CHECK:STDERR: fn Class.Function() {}\n// CHECK:STDERR:    ^~~~~\n// CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-5]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class Class;\n// CHECK:STDERR: ^~~~~~~~~~~~\n// CHECK:STDERR:\nfn Class.Function() {}\n\nfn CallClassFunction() {\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+7]]:3: error: member access into incomplete class `Class` [QualifiedExprInIncompleteClassScope]\n  // CHECK:STDERR:   Class.Function();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-15]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class Class;\n  // CHECK:STDERR: ^~~~~~~~~~~~\n  // CHECK:STDERR:\n  Class.Function();\n}\n\n// CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+7]]:17: error: binding pattern has incomplete type `Class` in name binding declaration [IncompleteTypeInBindingDecl]\n// CHECK:STDERR: var global_var: Class;\n// CHECK:STDERR:                 ^~~~~\n// CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-25]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class Class;\n// CHECK:STDERR: ^~~~~~~~~~~~\n// CHECK:STDERR:\nvar global_var: Class;\n\n// CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+7]]:27: error: function returns incomplete type `Class` [IncompleteTypeInFunctionReturnType]\n// CHECK:STDERR: fn ConvertFromStruct() -> Class { return {}; }\n// CHECK:STDERR:                           ^~~~~\n// CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-34]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class Class;\n// CHECK:STDERR: ^~~~~~~~~~~~\n// CHECK:STDERR:\nfn ConvertFromStruct() -> Class { return {}; }\n\nfn G(p: Class*) -> () {\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+7]]:10: error: member access into object of incomplete type `Class` [IncompleteTypeInMemberAccess]\n  // CHECK:STDERR:   return p->n;\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-44]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class Class;\n  // CHECK:STDERR: ^~~~~~~~~~~~\n  // CHECK:STDERR:\n  return p->n;\n}\n\nfn MemberAccess(p: Class*) -> () {\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+7]]:11: error: member access into object of incomplete type `Class` [IncompleteTypeInMemberAccess]\n  // CHECK:STDERR:   return (*p).n;\n  // CHECK:STDERR:           ^~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-55]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class Class;\n  // CHECK:STDERR: ^~~~~~~~~~~~\n  // CHECK:STDERR:\n  return (*p).n;\n}\n\n// CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+7]]:23: error: function returns incomplete type `Class` [IncompleteTypeInFunctionReturnType]\n// CHECK:STDERR: fn Copy(p: Class*) -> Class {\n// CHECK:STDERR:                       ^~~~~\n// CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-65]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class Class;\n// CHECK:STDERR: ^~~~~~~~~~~~\n// CHECK:STDERR:\nfn Copy(p: Class*) -> Class {\n  return *p;\n}\n\nfn Let(p: Class*) {\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+7]]:17: error: binding pattern has incomplete type `Class` in name binding declaration [IncompleteTypeInBindingDecl]\n  // CHECK:STDERR:   let unused c: Class = *p;\n  // CHECK:STDERR:                 ^~~~~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-77]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class Class;\n  // CHECK:STDERR: ^~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused c: Class = *p;\n}\n\nfn TakeIncomplete(c: Class);\n\nfn ReturnIncomplete() -> Class;\n\nfn CallTakeIncomplete(p: Class*) {\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+10]]:18: error: forming value of incomplete type `Class` [IncompleteTypeInValueConversion]\n  // CHECK:STDERR:   TakeIncomplete(*p);\n  // CHECK:STDERR:                  ^~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-92]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class Class;\n  // CHECK:STDERR: ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-11]]:19: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn TakeIncomplete(c: Class);\n  // CHECK:STDERR:                   ^~~~~~~~\n  // CHECK:STDERR:\n  TakeIncomplete(*p);\n\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+10]]:18: error: forming value of incomplete type `Class` [IncompleteTypeInValueConversion]\n  // CHECK:STDERR:   TakeIncomplete({});\n  // CHECK:STDERR:                  ^~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-104]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class Class;\n  // CHECK:STDERR: ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-23]]:19: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn TakeIncomplete(c: Class);\n  // CHECK:STDERR:                   ^~~~~~~~\n  // CHECK:STDERR:\n  TakeIncomplete({});\n}\n\nfn CallReturnIncomplete() {\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE+10]]:3: error: function returns incomplete type `Class` [IncompleteTypeInFunctionReturnType]\n  // CHECK:STDERR:   ReturnIncomplete();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-118]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class Class;\n  // CHECK:STDERR: ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_forward_decl.carbon:[[@LINE-35]]:26: note: return type declared here [IncompleteReturnTypeHere]\n  // CHECK:STDERR: fn ReturnIncomplete() -> Class;\n  // CHECK:STDERR:                          ^~~~~\n  // CHECK:STDERR:\n  ReturnIncomplete();\n}\n\n// --- fail_in_definition.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  // CHECK:STDERR: fail_in_definition.carbon:[[@LINE+7]]:10: error: field has incomplete type `C` [IncompleteTypeInFieldDecl]\n  // CHECK:STDERR:   var c: C;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR: fail_in_definition.carbon:[[@LINE-4]]:1: note: class is incomplete within its definition [ClassIncompleteWithinDefinition]\n  // CHECK:STDERR: class C {\n  // CHECK:STDERR: ^~~~~~~~~\n  // CHECK:STDERR:\n  var c: C;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_init.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_init.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_init.carbon\n\nclass Class {\n  var a: i32;\n  var b: i32;\n}\n\nfn F() {\n  // CHECK:STDERR: fail_init.carbon:[[@LINE+4]]:3: error: cannot initialize class with 2 fields from struct with 1 field [StructInitElementCountMismatch]\n  // CHECK:STDERR:   {.a = 1} as Class;\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR:\n  {.a = 1} as Class;\n  // CHECK:STDERR: fail_init.carbon:[[@LINE+4]]:3: error: missing value for field `b` in struct initialization [StructInitMissingFieldInLiteral]\n  // CHECK:STDERR:   {.a = 1, .c = 2} as Class;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  {.a = 1, .c = 2} as Class;\n  // CHECK:STDERR: fail_init.carbon:[[@LINE+4]]:3: error: cannot initialize class with 2 fields from struct with 3 fields [StructInitElementCountMismatch]\n  // CHECK:STDERR:   {.a = 1, .b = 2, .c = 3} as Class;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  {.a = 1, .b = 2, .c = 3} as Class;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_memaccess_category.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_memaccess_category.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_memaccess_category.carbon\n\nclass A {\n  fn F[ref self: A]();\n}\n\nclass B {\n  var a: A;\n}\n\nfn F(s: {.a: A}, b: B) {\n  // `s` has only a value representation, so this must be invalid.\n  // CHECK:STDERR: fail_memaccess_category.carbon:[[@LINE+7]]:3: error: value expression passed to reference parameter [ValueForRefParam]\n  // CHECK:STDERR:   s.a.F();\n  // CHECK:STDERR:   ^~~\n  // CHECK:STDERR: fail_memaccess_category.carbon:[[@LINE-12]]:8: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR:   fn F[ref self: A]();\n  // CHECK:STDERR:        ^~~~~~~~~~~\n  // CHECK:STDERR:\n  s.a.F();\n\n  // `b` has an object representation for `A`, but this is still invalid for\n  // consistency.\n  // CHECK:STDERR: fail_memaccess_category.carbon:[[@LINE+7]]:3: error: value expression passed to reference parameter [ValueForRefParam]\n  // CHECK:STDERR:   b.a.F();\n  // CHECK:STDERR:   ^~~\n  // CHECK:STDERR: fail_memaccess_category.carbon:[[@LINE-23]]:8: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR:   fn F[ref self: A]();\n  // CHECK:STDERR:        ^~~~~~~~~~~\n  // CHECK:STDERR:\n  b.a.F();\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_member_of_let.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_member_of_let.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_member_of_let.carbon\n\nclass Class {\n  fn F() -> ();\n}\n\n// TODO: Use `:!` here once it is available.\nlet T: type = Class;\n\n// The class name is required to be written in the same way as in the class\n// declaration. An expression that evaluates to the class name is not accepted.\n// CHECK:STDERR: fail_member_of_let.carbon:[[@LINE+7]]:4: error: name qualifiers are only allowed for entities that provide a scope [QualifiedNameInNonScope]\n// CHECK:STDERR: fn T.F() {}\n// CHECK:STDERR:    ^\n// CHECK:STDERR: fail_member_of_let.carbon:[[@LINE-7]]:5: note: referenced non-scope entity declared here [QualifiedNameNonScopeEntity]\n// CHECK:STDERR: let T: type = Class;\n// CHECK:STDERR:     ^\n// CHECK:STDERR:\nfn T.F() {}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_modifiers.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_modifiers.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_modifiers.carbon\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:9: error: `private` repeated on declaration [ModifierRepeated]\n// CHECK:STDERR: private private class DuplicatePrivate;\n// CHECK:STDERR:         ^~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `private` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: private private class DuplicatePrivate;\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nprivate private class DuplicatePrivate;\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `abstract` not allowed on `class` forward declaration, only definition [ModifierOnlyAllowedOnDefinition]\n// CHECK:STDERR: abstract class AbstractDecl;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nabstract class AbstractDecl;\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:9: error: `protected` not allowed on declaration with `private` [ModifierNotAllowedWith]\n// CHECK:STDERR: private protected class TwoAccess;\n// CHECK:STDERR:         ^~~~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `private` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: private protected class TwoAccess;\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nprivate protected class TwoAccess;\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` forward declaration, only definition [ModifierOnlyAllowedOnDefinition]\n// CHECK:STDERR: base class BaseDecl;\n// CHECK:STDERR: ^~~~\n// CHECK:STDERR:\nbase class BaseDecl;\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:10: error: `abstract` repeated on declaration [ModifierRepeated]\n// CHECK:STDERR: abstract abstract class TwoAbstract { }\n// CHECK:STDERR:          ^~~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `abstract` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: abstract abstract class TwoAbstract { }\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nabstract abstract class TwoAbstract { }\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+15]]:19: error: `base` not allowed on declaration with `virtual` [ModifierNotAllowedWith]\n// CHECK:STDERR: protected virtual base class Virtual {}\n// CHECK:STDERR:                   ^~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+12]]:11: note: `virtual` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: protected virtual base class Virtual {}\n// CHECK:STDERR:           ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+8]]:1: error: `protected` not allowed; requires class scope [ModifierProtectedNotAllowed]\n// CHECK:STDERR: protected virtual base class Virtual {}\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:11: error: `virtual` not allowed on `class` declaration [ModifierNotAllowedOnDeclaration]\n// CHECK:STDERR: protected virtual base class Virtual {}\n// CHECK:STDERR:           ^~~~~~~\n// CHECK:STDERR:\nprotected virtual base class Virtual {}\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:10: error: `protected` must appear before `abstract` [ModifierMustAppearBefore]\n// CHECK:STDERR: abstract protected class WrongOrder { }\n// CHECK:STDERR:          ^~~~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `abstract` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: abstract protected class WrongOrder { }\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nabstract protected class WrongOrder { }\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:10: error: `base` not allowed on declaration with `abstract` [ModifierNotAllowedWith]\n// CHECK:STDERR: abstract base class AbstractAndBase {}\n// CHECK:STDERR:          ^~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `abstract` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: abstract base class AbstractAndBase {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nabstract base class AbstractAndBase {}\n\nabstract class AbstractWithDefinition {\n  // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:38: error: definition of `abstract` function [DefinedAbstractFunction]\n  // CHECK:STDERR:   abstract fn F[unused self: Self]() {}\n  // CHECK:STDERR:                                      ^\n  // CHECK:STDERR:\n  abstract fn F[unused self: Self]() {}\n  abstract fn G[unused self: Self]();\n}\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:50: error: definition of `abstract` function [DefinedAbstractFunction]\n// CHECK:STDERR: fn AbstractWithDefinition.G[unused self: Self]() {\n// CHECK:STDERR:                                                  ^\n// CHECK:STDERR:\nfn AbstractWithDefinition.G[unused self: Self]() {\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_redeclaration_scope.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_redeclaration_scope.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_redeclaration_scope.carbon\n\nclass A;\n\nclass X {\n  // OK, a different A.\n  class A { class B; }\n  class A.B {}\n}\n\nclass A { class B; }\n\nclass Y {\n  // CHECK:STDERR: fail_redeclaration_scope.carbon:[[@LINE+4]]:9: error: name `A` not found [NameNotFound]\n  // CHECK:STDERR:   class A.B {}\n  // CHECK:STDERR:         ^\n  // CHECK:STDERR:\n  class A.B {}\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_redefinition.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_redefinition.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_redefinition.carbon\n\nclass Class {\n  fn F();\n  fn H();\n  fn I() {}\n}\n\n// CHECK:STDERR: fail_redefinition.carbon:[[@LINE+7]]:1: error: redefinition of `class Class` [RedeclRedef]\n// CHECK:STDERR: class Class {\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR: fail_redefinition.carbon:[[@LINE-9]]:1: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR: class Class {\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR:\nclass Class {\n  fn G();\n  fn H();\n  fn I() {}\n}\n\nfn Class.F() {}\n// CHECK:STDERR: fail_redefinition.carbon:[[@LINE+4]]:10: error: out-of-line declaration requires a declaration in scoped entity [QualifiedDeclOutsideScopeEntity]\n// CHECK:STDERR: fn Class.G() {}\n// CHECK:STDERR:          ^\n// CHECK:STDERR:\nfn Class.G() {}\nfn Class.H() {}\n// CHECK:STDERR: fail_redefinition.carbon:[[@LINE+7]]:1: error: redefinition of `fn I` [RedeclRedef]\n// CHECK:STDERR: fn Class.I() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redefinition.carbon:[[@LINE-26]]:3: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR:   fn I() {}\n// CHECK:STDERR:   ^~~~~~~~\n// CHECK:STDERR:\nfn Class.I() {}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_scope.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_scope.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_scope.carbon\n\nclass Class {\n  fn F() -> () {\n    return ();\n  }\n}\n\nfn G() -> () {\n  // CHECK:STDERR: fail_scope.carbon:[[@LINE+4]]:10: error: name `F` not found [NameNotFound]\n  // CHECK:STDERR:   return F();\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR:\n  return F();\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/fail_unknown_member.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/fail_unknown_member.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/fail_unknown_member.carbon\n\nclass Class {\n  var n: i32;\n}\n\nfn G(c: Class) -> i32 {\n  // TODO: Mention the scope in which we looked for the name.\n  // CHECK:STDERR: fail_unknown_member.carbon:[[@LINE+4]]:10: error: member name `something` not found in `Class` [MemberNameNotFoundInInstScope]\n  // CHECK:STDERR:   return c.something;\n  // CHECK:STDERR:          ^~~~~~~~~~~\n  // CHECK:STDERR:\n  return c.something;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/field/comp_time_field.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/field/comp_time_field.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/field/comp_time_field.carbon\n\n// --- fail_let.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class {\n  // CHECK:STDERR: fail_let.carbon:[[@LINE+4]]:7: error: semantics TODO: ``let` compile time binding outside function or interface` [SemanticsTodo]\n  // CHECK:STDERR:   let A:! type = Class;\n  // CHECK:STDERR:       ^~~~~~~~\n  // CHECK:STDERR:\n  let A:! type = Class;\n\n  // CHECK:STDERR: fail_let.carbon:[[@LINE+4]]:7: error: semantics TODO: ``let` compile time binding outside function or interface` [SemanticsTodo]\n  // CHECK:STDERR:   let template B:! type = Class;\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let template B:! type = Class;\n}\n\n// --- fail_var.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class {\n  // CHECK:STDERR: fail_var.carbon:[[@LINE+8]]:8: error: expected `:` in field declaration [ExpectedFieldColon]\n  // CHECK:STDERR:   var C:! type = Class;\n  // CHECK:STDERR:        ^~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_var.carbon:[[@LINE+4]]:3: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n  // CHECK:STDERR:   var C:! type = Class;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var C:! type = Class;\n\n  // CHECK:STDERR: fail_var.carbon:[[@LINE+4]]:7: error: expected identifier in field declaration [ExpectedFieldIdentifier]\n  // CHECK:STDERR:   var template D:! type = Class;\n  // CHECK:STDERR:       ^~~~~~~~\n  // CHECK:STDERR:\n  var template D:! type = Class;\n}\n\nvar x: Class = {};\n\n// CHECK:STDOUT: --- fail_let.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %A.patt: %pattern_type = value_binding_pattern A [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.ref.loc9: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %.loc9_11.1: type = splice_block %.loc9_11.2 [concrete = type] {\n// CHECK:STDOUT:     %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.loc9_11.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A: type = value_binding A, %Class.ref.loc9\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %B.patt: %pattern_type = value_binding_pattern B [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.ref.loc15: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %.loc15_20.1: type = splice_block %.loc15_20.2 [concrete = type] {\n// CHECK:STDOUT:     %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.loc15_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B: type = value_binding B, %Class.ref.loc15\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .A = %A\n// CHECK:STDOUT:   .Class = <poisoned>\n// CHECK:STDOUT:   .B = %B\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_var.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   complete_type_witness = invalid\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/field/compound_field.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/field/compound_field.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/field/compound_field.carbon\n\nbase class Base {\n  var a: i32;\n  var b: i32;\n  var c: i32;\n}\n\nclass Derived {\n  extend base: Base;\n\n  var d: i32;\n  var e: i32;\n}\n\nfn AccessDerived(d: Derived) -> i32 {\n  return d.(Derived.d);\n}\n\nfn AccessBase(d: Derived) -> i32 {\n  return d.(Base.b);\n}\n\nfn AccessDerivedIndirect(p: Derived*) -> i32* {\n  return &p->(Derived.d);\n}\n\nfn AccessBaseIndirect(p: Derived*) -> i32* {\n  return &p->(Base.b);\n}\n\n// CHECK:STDOUT: --- compound_field.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.c: type = struct_type {.a: %i32, .b: %i32, .c: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.ebc: <witness> = complete_type_witness %struct_type.a.b.c [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem.029: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %Derived.elem.530: type = unbound_element_type %Derived, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.base.d.e.b4b: type = struct_type {.base: %Base, .d: %i32, .e: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.ea9: <witness> = complete_type_witness %struct_type.base.d.e.b4b [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %AccessDerived.type: type = fn_type @AccessDerived [concrete]\n// CHECK:STDOUT:   %AccessDerived: %AccessDerived.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %AccessBase.type: type = fn_type @AccessBase [concrete]\n// CHECK:STDOUT:   %AccessBase: %AccessBase.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.f74: type = ptr_type %Derived [concrete]\n// CHECK:STDOUT:   %pattern_type.0dd: type = pattern_type %ptr.f74 [concrete]\n// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %.605: Core.Form = init_form %ptr.235 [concrete]\n// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr.235 [concrete]\n// CHECK:STDOUT:   %AccessDerivedIndirect.type: type = fn_type @AccessDerivedIndirect [concrete]\n// CHECK:STDOUT:   %AccessDerivedIndirect: %AccessDerivedIndirect.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.843: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%i32) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.c3c: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%i32) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.011: %ptr.as.Copy.impl.Op.type.c3c = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.a7b: %Copy.type = facet_value %ptr.235, (%Copy.impl_witness.843) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.e01: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.a7b) [concrete]\n// CHECK:STDOUT:   %.a62: type = fn_type_with_self_type %Copy.WithSelf.Op.type.e01, %Copy.facet.a7b [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.011, @ptr.as.Copy.impl.Op(%i32) [concrete]\n// CHECK:STDOUT:   %AccessBaseIndirect.type: type = fn_type @AccessBaseIndirect [concrete]\n// CHECK:STDOUT:   %AccessBaseIndirect: %AccessBaseIndirect.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .AccessDerived = %AccessDerived.decl\n// CHECK:STDOUT:     .AccessBase = %AccessBase.decl\n// CHECK:STDOUT:     .AccessDerivedIndirect = %AccessDerivedIndirect.decl\n// CHECK:STDOUT:     .AccessBaseIndirect = %AccessBaseIndirect.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %AccessDerived.decl: %AccessDerived.type = fn_decl @AccessDerived [concrete = constants.%AccessDerived] {\n// CHECK:STDOUT:     %d.patt: %pattern_type.9f6 = value_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.param_patt: %pattern_type.9f6 = value_param_pattern %d.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc28: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %d.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Derived.ref.loc28: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:     %d: %Derived = value_binding d, %d.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %AccessBase.decl: %AccessBase.type = fn_decl @AccessBase [concrete = constants.%AccessBase] {\n// CHECK:STDOUT:     %d.patt: %pattern_type.9f6 = value_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.param_patt: %pattern_type.9f6 = value_param_pattern %d.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc32: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %d.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:     %d: %Derived = value_binding d, %d.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %AccessDerivedIndirect.decl: %AccessDerivedIndirect.type = fn_decl @AccessDerivedIndirect [concrete = constants.%AccessDerivedIndirect] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.0dd = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.0dd = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.fe8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.fe8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr.loc36_45: type = ptr_type %i32 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:     %.loc36_45: Core.Form = init_form %ptr.loc36_45 [concrete = constants.%.605]\n// CHECK:STDOUT:     %p.param: %ptr.f74 = value_param call_param0\n// CHECK:STDOUT:     %.loc36_36: type = splice_block %ptr.loc36_36 [concrete = constants.%ptr.f74] {\n// CHECK:STDOUT:       %Derived.ref.loc36: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:       %ptr.loc36_36: type = ptr_type %Derived.ref.loc36 [concrete = constants.%ptr.f74]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.f74 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %ptr.235 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.235 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %AccessBaseIndirect.decl: %AccessBaseIndirect.type = fn_decl @AccessBaseIndirect [concrete = constants.%AccessBaseIndirect] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.0dd = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.0dd = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.fe8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.fe8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr.loc40_42: type = ptr_type %i32 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:     %.loc40_42: Core.Form = init_form %ptr.loc40_42 [concrete = constants.%.605]\n// CHECK:STDOUT:     %p.param: %ptr.f74 = value_param call_param0\n// CHECK:STDOUT:     %.loc40_33: type = splice_block %ptr.loc40_33 [concrete = constants.%ptr.f74] {\n// CHECK:STDOUT:       %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:       %ptr.loc40_33: type = ptr_type %Derived.ref [concrete = constants.%ptr.f74]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.f74 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %ptr.235 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.235 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc16: %Base.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc17: %Base.elem = field_decl b, element1 [concrete]\n// CHECK:STDOUT:   %i32.loc18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc18: %Base.elem = field_decl c, element2 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b.c [concrete = constants.%complete_type.ebc]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .a = %.loc16\n// CHECK:STDOUT:   .b = %.loc17\n// CHECK:STDOUT:   .c = %.loc18\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc22: %Derived.elem.029 = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc24: %Derived.elem.530 = field_decl d, element1 [concrete]\n// CHECK:STDOUT:   %i32.loc25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc25: %Derived.elem.530 = field_decl e, element2 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.d.e.b4b [concrete = constants.%complete_type.ea9]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc22\n// CHECK:STDOUT:   .d = %.loc24\n// CHECK:STDOUT:   .e = %.loc25\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @AccessDerived(%d.param: %Derived) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %d.ref.loc29_10: %Derived = name_ref d, %d\n// CHECK:STDOUT:   %Derived.ref.loc29: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:   %d.ref.loc29_20: %Derived.elem.530 = name_ref d, @Derived.%.loc24 [concrete = @Derived.%.loc24]\n// CHECK:STDOUT:   %.loc29_11.1: ref %i32 = class_element_access %d.ref.loc29_10, element1\n// CHECK:STDOUT:   %.loc29_11.2: %i32 = acquire_value %.loc29_11.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc29_11.1: <bound method> = bound_method %.loc29_11.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc29_11.2: <bound method> = bound_method %.loc29_11.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc29_11.2(%.loc29_11.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @AccessBase(%d.param: %Derived) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %d.ref: %Derived = name_ref d, %d\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %b.ref: %Base.elem = name_ref b, @Base.%.loc17 [concrete = @Base.%.loc17]\n// CHECK:STDOUT:   %.loc33_11.1: ref %Base = class_element_access %d.ref, element0\n// CHECK:STDOUT:   %.loc33_11.2: ref %Base = converted %d.ref, %.loc33_11.1\n// CHECK:STDOUT:   %.loc33_11.3: ref %i32 = class_element_access %.loc33_11.2, element1\n// CHECK:STDOUT:   %.loc33_11.4: %i32 = acquire_value %.loc33_11.3\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc33_11.1: <bound method> = bound_method %.loc33_11.4, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc33_11.2: <bound method> = bound_method %.loc33_11.4, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc33_11.2(%.loc33_11.4)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @AccessDerivedIndirect(%p.param: %ptr.f74) -> out %return.param: %ptr.235 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.f74 = name_ref p, %p\n// CHECK:STDOUT:   %Derived.ref.loc37: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:   %d.ref: %Derived.elem.530 = name_ref d, @Derived.%.loc24 [concrete = @Derived.%.loc24]\n// CHECK:STDOUT:   %.loc37_12.1: ref %Derived = deref %p.ref\n// CHECK:STDOUT:   %.loc37_12.2: ref %i32 = class_element_access %.loc37_12.1, element1\n// CHECK:STDOUT:   %addr: %ptr.235 = addr_of %.loc37_12.2\n// CHECK:STDOUT:   %impl.elem0: %.a62 = impl_witness_access constants.%Copy.impl_witness.843, element0 [concrete = constants.%ptr.as.Copy.impl.Op.011]\n// CHECK:STDOUT:   %bound_method.loc37_10.1: <bound method> = bound_method %addr, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%i32) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc37_10.2: <bound method> = bound_method %addr, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.235 = call %bound_method.loc37_10.2(%addr)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @AccessBaseIndirect(%p.param: %ptr.f74) -> out %return.param: %ptr.235 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.f74 = name_ref p, %p\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %b.ref: %Base.elem = name_ref b, @Base.%.loc17 [concrete = @Base.%.loc17]\n// CHECK:STDOUT:   %.loc41_12.1: ref %Derived = deref %p.ref\n// CHECK:STDOUT:   %.loc41_12.2: ref %Base = class_element_access %.loc41_12.1, element0\n// CHECK:STDOUT:   %.loc41_12.3: ref %Base = converted %.loc41_12.1, %.loc41_12.2\n// CHECK:STDOUT:   %.loc41_12.4: ref %i32 = class_element_access %.loc41_12.3, element1\n// CHECK:STDOUT:   %addr: %ptr.235 = addr_of %.loc41_12.4\n// CHECK:STDOUT:   %impl.elem0: %.a62 = impl_witness_access constants.%Copy.impl_witness.843, element0 [concrete = constants.%ptr.as.Copy.impl.Op.011]\n// CHECK:STDOUT:   %bound_method.loc41_10.1: <bound method> = bound_method %addr, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%i32) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc41_10.2: <bound method> = bound_method %addr, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.235 = call %bound_method.loc41_10.2(%addr)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/field/fail_field_modifiers.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/field/fail_field_modifiers.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/field/fail_field_modifiers.carbon\n\nclass Class {\n\n  // CHECK:STDERR: fail_field_modifiers.carbon:[[@LINE+4]]:3: error: `default` not allowed on `var` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   default var j: i32;\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  default var j: i32;\n\n  // CHECK:STDERR: fail_field_modifiers.carbon:[[@LINE+4]]:3: error: `final` not allowed on `var` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   final var k: i32;\n  // CHECK:STDERR:   ^~~~~\n  // CHECK:STDERR:\n  final var k: i32;\n\n  // CHECK:STDERR: fail_field_modifiers.carbon:[[@LINE+4]]:3: error: `default` not allowed; requires interface scope [ModifierRequiresInterface]\n  // CHECK:STDERR:   default let l: i32 = 0;\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  default let l: i32 = 0;\n\n  // CHECK:STDERR: fail_field_modifiers.carbon:[[@LINE+4]]:3: error: `final` not allowed; requires interface scope [ModifierRequiresInterface]\n  // CHECK:STDERR:   final let m: i32 = 1;\n  // CHECK:STDERR:   ^~~~~\n  // CHECK:STDERR:\n  final let m: i32 = 1;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/field/fail_todo_field_initializer.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/field/fail_todo_field_initializer.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/field/fail_todo_field_initializer.carbon\n\nclass Class {\n  // CHECK:STDERR: fail_todo_field_initializer.carbon:[[@LINE+4]]:3: error: semantics TODO: `Field initializer` [SemanticsTodo]\n  // CHECK:STDERR:   var field: i32 = 0;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var field: i32 = 0;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/field/fail_unbound_field.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/field/fail_unbound_field.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/field/fail_unbound_field.carbon\n\nclass Class {\n  var field: i32;\n  fn F() -> i32 {\n    // CHECK:STDERR: fail_unbound_field.carbon:[[@LINE+4]]:12: error: expression cannot be used as a value [UseOfNonExprAsValue]\n    // CHECK:STDERR:     return field;\n    // CHECK:STDERR:            ^~~~~\n    // CHECK:STDERR:\n    return field;\n  }\n\n  fn IsZero() -> bool {\n    // CHECK:STDERR: fail_unbound_field.carbon:[[@LINE+4]]:12: error: cannot access member of interface `Core.EqWith(Core.IntLiteral)` in type `<unbound element of class Class>` that does not implement that interface [MissingImplInMemberAccess]\n    // CHECK:STDERR:     return field == 0;\n    // CHECK:STDERR:            ^~~~~~~~~~\n    // CHECK:STDERR:\n    return field == 0;\n  }\n}\n\nfn G() -> i32 {\n  // CHECK:STDERR: fail_unbound_field.carbon:[[@LINE+4]]:10: error: expression cannot be used as a value [UseOfNonExprAsValue]\n  // CHECK:STDERR:   return Class.field;\n  // CHECK:STDERR:          ^~~~~~~~~~~\n  // CHECK:STDERR:\n  return Class.field;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/field/field_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/field/field_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/field/field_access.carbon\n\nclass Class {\n  var j: i32;\n  var k: i32;\n}\n\nfn Run() {\n  var c: Class;\n  c.j = 1;\n  c.k = 2;\n  var unused cj: i32 = c.j;\n  var unused ck: i32 = c.k;\n}\n\n// CHECK:STDOUT: --- field_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.j.k: type = struct_type {.j: %i32, .k: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.cf7: <witness> = complete_type_witness %struct_type.j.k [concrete]\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.6ca: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.3d0: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.cda: %T.as.DefaultOrUnformed.impl.Op.type.3d0 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %Class, (%DefaultOrUnformed.impl_witness.6ca) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(%Class) [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc25 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc21 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc16: %Class.elem = field_decl j, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc17: %Class.elem = field_decl k, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.j.k [concrete = constants.%complete_type.cf7]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .j = %.loc16\n// CHECK:STDOUT:   .k = %.loc17\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.904 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.904 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %Class = var %c.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%Class, (constants.%DefaultOrUnformed.impl_witness.6ca) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc21_15.1: %DefaultOrUnformed.type = converted constants.%Class, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc21_15.1 [concrete = constants.%Class]\n// CHECK:STDOUT:   %.loc21_15.2: type = converted %.loc21_15.1, %as_type [concrete = constants.%Class]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(constants.%Class) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc21_3: ref %Class = splice_block %c.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %Class to %.loc21_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %c.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %c: ref %Class = ref_binding c, %c.var\n// CHECK:STDOUT:   %c.ref.loc22: ref %Class = name_ref c, %c\n// CHECK:STDOUT:   %j.ref.loc22: %Class.elem = name_ref j, @Class.%.loc16 [concrete = @Class.%.loc16]\n// CHECK:STDOUT:   %.loc22_4: ref %i32 = class_element_access %c.ref.loc22, element0\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc22: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc22_7.1: <bound method> = bound_method %int_1, %impl.elem0.loc22 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc22: <specific function> = specific_function %impl.elem0.loc22, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc22_7.2: <bound method> = bound_method %int_1, %specific_fn.loc22 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc22: init %i32 = call %bound_method.loc22_7.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc22_7: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc22 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   assign %.loc22_4, %.loc22_7\n// CHECK:STDOUT:   %c.ref.loc23: ref %Class = name_ref c, %c\n// CHECK:STDOUT:   %k.ref.loc23: %Class.elem = name_ref k, @Class.%.loc17 [concrete = @Class.%.loc17]\n// CHECK:STDOUT:   %.loc23_4: ref %i32 = class_element_access %c.ref.loc23, element1\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc23: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc23_7.1: <bound method> = bound_method %int_2, %impl.elem0.loc23 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc23: <specific function> = specific_function %impl.elem0.loc23, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc23_7.2: <bound method> = bound_method %int_2, %specific_fn.loc23 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc23: init %i32 = call %bound_method.loc23_7.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc23_7: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc23 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   assign %.loc23_4, %.loc23_7\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %cj.patt: %pattern_type.7ce = ref_binding_pattern cj [concrete]\n// CHECK:STDOUT:     %cj.var_patt: %pattern_type.7ce = var_pattern %cj.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %cj.var: ref %i32 = var %cj.var_patt\n// CHECK:STDOUT:   %c.ref.loc24: ref %Class = name_ref c, %c\n// CHECK:STDOUT:   %j.ref.loc24: %Class.elem = name_ref j, @Class.%.loc16 [concrete = @Class.%.loc16]\n// CHECK:STDOUT:   %.loc24_25.1: ref %i32 = class_element_access %c.ref.loc24, element0\n// CHECK:STDOUT:   %.loc24_25.2: %i32 = acquire_value %.loc24_25.1\n// CHECK:STDOUT:   %impl.elem0.loc24: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc24_25.1: <bound method> = bound_method %.loc24_25.2, %impl.elem0.loc24\n// CHECK:STDOUT:   %specific_fn.loc24: <specific function> = specific_function %impl.elem0.loc24, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc24_25.2: <bound method> = bound_method %.loc24_25.2, %specific_fn.loc24\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc24: init %i32 = call %bound_method.loc24_25.2(%.loc24_25.2)\n// CHECK:STDOUT:   assign %cj.var, %Int.as.Copy.impl.Op.call.loc24\n// CHECK:STDOUT:   %i32.loc24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %cj: ref %i32 = ref_binding cj, %cj.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %ck.patt: %pattern_type.7ce = ref_binding_pattern ck [concrete]\n// CHECK:STDOUT:     %ck.var_patt: %pattern_type.7ce = var_pattern %ck.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ck.var: ref %i32 = var %ck.var_patt\n// CHECK:STDOUT:   %c.ref.loc25: ref %Class = name_ref c, %c\n// CHECK:STDOUT:   %k.ref.loc25: %Class.elem = name_ref k, @Class.%.loc17 [concrete = @Class.%.loc17]\n// CHECK:STDOUT:   %.loc25_25.1: ref %i32 = class_element_access %c.ref.loc25, element1\n// CHECK:STDOUT:   %.loc25_25.2: %i32 = acquire_value %.loc25_25.1\n// CHECK:STDOUT:   %impl.elem0.loc25: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc25_25.1: <bound method> = bound_method %.loc25_25.2, %impl.elem0.loc25\n// CHECK:STDOUT:   %specific_fn.loc25: <specific function> = specific_function %impl.elem0.loc25, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc25_25.2: <bound method> = bound_method %.loc25_25.2, %specific_fn.loc25\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc25: init %i32 = call %bound_method.loc25_25.2(%.loc25_25.2)\n// CHECK:STDOUT:   assign %ck.var, %Int.as.Copy.impl.Op.call.loc25\n// CHECK:STDOUT:   %i32.loc25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %ck: ref %i32 = ref_binding ck, %ck.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc25: <bound method> = bound_method %ck.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc25: init %empty_tuple.type = call %Destroy.Op.bound.loc25(%ck.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc24: <bound method> = bound_method %cj.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc24: init %empty_tuple.type = call %Destroy.Op.bound.loc24(%cj.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc21: <bound method> = bound_method %c.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc21: init %empty_tuple.type = call %Destroy.Op.bound.loc21(%c.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc25(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc21(%self.param: ref %Class) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/field/field_access_in_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/field/field_access_in_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/field/field_access_in_value.carbon\n\nclass Class {\n  var j: i32;\n  var k: i32;\n}\n\nfn Test() {\n  var cv: Class;\n  cv.j = 1;\n  cv.k = 2;\n  let c: Class = cv;\n  var unused cj: i32 = c.j;\n  var unused ck: i32 = c.k;\n}\n\n// CHECK:STDOUT: --- field_access_in_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.j.k: type = struct_type {.j: %i32, .k: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.cf7: <witness> = complete_type_witness %struct_type.j.k [concrete]\n// CHECK:STDOUT:   %Test.type: type = fn_type @Test [concrete]\n// CHECK:STDOUT:   %Test: %Test.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.6ca: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.3d0: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.cda: %T.as.DefaultOrUnformed.impl.Op.type.3d0 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %Class, (%DefaultOrUnformed.impl_witness.6ca) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(%Class) [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc26 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc21 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .Test = %Test.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Test.decl: %Test.type = fn_decl @Test [concrete = constants.%Test] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc16: %Class.elem = field_decl j, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc17: %Class.elem = field_decl k, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.j.k [concrete = constants.%complete_type.cf7]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .j = %.loc16\n// CHECK:STDOUT:   .k = %.loc17\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %cv.patt: %pattern_type.904 = ref_binding_pattern cv [concrete]\n// CHECK:STDOUT:     %cv.var_patt: %pattern_type.904 = var_pattern %cv.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %cv.var: ref %Class = var %cv.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%Class, (constants.%DefaultOrUnformed.impl_witness.6ca) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc21_16.1: %DefaultOrUnformed.type = converted constants.%Class, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc21_16.1 [concrete = constants.%Class]\n// CHECK:STDOUT:   %.loc21_16.2: type = converted %.loc21_16.1, %as_type [concrete = constants.%Class]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(constants.%Class) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc21_3: ref %Class = splice_block %cv.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %Class to %.loc21_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %cv.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %Class.ref.loc21: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %cv: ref %Class = ref_binding cv, %cv.var\n// CHECK:STDOUT:   %cv.ref.loc22: ref %Class = name_ref cv, %cv\n// CHECK:STDOUT:   %j.ref.loc22: %Class.elem = name_ref j, @Class.%.loc16 [concrete = @Class.%.loc16]\n// CHECK:STDOUT:   %.loc22_5: ref %i32 = class_element_access %cv.ref.loc22, element0\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc22: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc22_8.1: <bound method> = bound_method %int_1, %impl.elem0.loc22 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc22: <specific function> = specific_function %impl.elem0.loc22, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc22_8.2: <bound method> = bound_method %int_1, %specific_fn.loc22 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc22: init %i32 = call %bound_method.loc22_8.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc22_8: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc22 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   assign %.loc22_5, %.loc22_8\n// CHECK:STDOUT:   %cv.ref.loc23: ref %Class = name_ref cv, %cv\n// CHECK:STDOUT:   %k.ref.loc23: %Class.elem = name_ref k, @Class.%.loc17 [concrete = @Class.%.loc17]\n// CHECK:STDOUT:   %.loc23_5: ref %i32 = class_element_access %cv.ref.loc23, element1\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc23: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc23_8.1: <bound method> = bound_method %int_2, %impl.elem0.loc23 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc23: <specific function> = specific_function %impl.elem0.loc23, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc23_8.2: <bound method> = bound_method %int_2, %specific_fn.loc23 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc23: init %i32 = call %bound_method.loc23_8.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc23_8: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc23 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   assign %.loc23_5, %.loc23_8\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.904 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %cv.ref.loc24: ref %Class = name_ref cv, %cv\n// CHECK:STDOUT:   %Class.ref.loc24: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %.loc24: %Class = acquire_value %cv.ref.loc24\n// CHECK:STDOUT:   %c: %Class = value_binding c, %.loc24\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %cj.patt: %pattern_type.7ce = ref_binding_pattern cj [concrete]\n// CHECK:STDOUT:     %cj.var_patt: %pattern_type.7ce = var_pattern %cj.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %cj.var: ref %i32 = var %cj.var_patt\n// CHECK:STDOUT:   %c.ref.loc25: %Class = name_ref c, %c\n// CHECK:STDOUT:   %j.ref.loc25: %Class.elem = name_ref j, @Class.%.loc16 [concrete = @Class.%.loc16]\n// CHECK:STDOUT:   %.loc25_25.1: ref %i32 = class_element_access %c.ref.loc25, element0\n// CHECK:STDOUT:   %.loc25_25.2: %i32 = acquire_value %.loc25_25.1\n// CHECK:STDOUT:   %impl.elem0.loc25: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc25_25.1: <bound method> = bound_method %.loc25_25.2, %impl.elem0.loc25\n// CHECK:STDOUT:   %specific_fn.loc25: <specific function> = specific_function %impl.elem0.loc25, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc25_25.2: <bound method> = bound_method %.loc25_25.2, %specific_fn.loc25\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc25: init %i32 = call %bound_method.loc25_25.2(%.loc25_25.2)\n// CHECK:STDOUT:   assign %cj.var, %Int.as.Copy.impl.Op.call.loc25\n// CHECK:STDOUT:   %i32.loc25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %cj: ref %i32 = ref_binding cj, %cj.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %ck.patt: %pattern_type.7ce = ref_binding_pattern ck [concrete]\n// CHECK:STDOUT:     %ck.var_patt: %pattern_type.7ce = var_pattern %ck.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ck.var: ref %i32 = var %ck.var_patt\n// CHECK:STDOUT:   %c.ref.loc26: %Class = name_ref c, %c\n// CHECK:STDOUT:   %k.ref.loc26: %Class.elem = name_ref k, @Class.%.loc17 [concrete = @Class.%.loc17]\n// CHECK:STDOUT:   %.loc26_25.1: ref %i32 = class_element_access %c.ref.loc26, element1\n// CHECK:STDOUT:   %.loc26_25.2: %i32 = acquire_value %.loc26_25.1\n// CHECK:STDOUT:   %impl.elem0.loc26: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc26_25.1: <bound method> = bound_method %.loc26_25.2, %impl.elem0.loc26\n// CHECK:STDOUT:   %specific_fn.loc26: <specific function> = specific_function %impl.elem0.loc26, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc26_25.2: <bound method> = bound_method %.loc26_25.2, %specific_fn.loc26\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc26: init %i32 = call %bound_method.loc26_25.2(%.loc26_25.2)\n// CHECK:STDOUT:   assign %ck.var, %Int.as.Copy.impl.Op.call.loc26\n// CHECK:STDOUT:   %i32.loc26: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %ck: ref %i32 = ref_binding ck, %ck.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc26: <bound method> = bound_method %ck.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc26: init %empty_tuple.type = call %Destroy.Op.bound.loc26(%ck.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc25: <bound method> = bound_method %cj.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc25: init %empty_tuple.type = call %Destroy.Op.bound.loc25(%cj.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc21: <bound method> = bound_method %cv.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc21: init %empty_tuple.type = call %Destroy.Op.bound.loc21(%cv.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc26(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc21(%self.param: ref %Class) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/forward_declared.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/forward_declared.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/forward_declared.carbon\n\nclass Class;\n\nfn F(p: Class*) -> Class* { return p; }\n\n// CHECK:STDOUT: --- forward_declared.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %ptr.8e5: type = ptr_type %Class [concrete]\n// CHECK:STDOUT:   %pattern_type.018: type = pattern_type %ptr.8e5 [concrete]\n// CHECK:STDOUT:   %.c69: Core.Form = init_form %ptr.8e5 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.9d3: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%Class) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.02e: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%Class) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.120: %ptr.as.Copy.impl.Op.type.02e = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.8e5, (%Copy.impl_witness.9d3) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.130: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.370: type = fn_type_with_self_type %Copy.WithSelf.Op.type.130, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.120, @ptr.as.Copy.impl.Op(%Class) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.018 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.018 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.018 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.018 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Class.ref.loc17_20: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     %ptr.loc17_25: type = ptr_type %Class.ref.loc17_20 [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:     %.loc17_25: Core.Form = init_form %ptr.loc17_25 [concrete = constants.%.c69]\n// CHECK:STDOUT:     %p.param: %ptr.8e5 = value_param call_param0\n// CHECK:STDOUT:     %.loc17_14: type = splice_block %ptr.loc17_14 [concrete = constants.%ptr.8e5] {\n// CHECK:STDOUT:       %Class.ref.loc17_9: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:       %ptr.loc17_14: type = ptr_type %Class.ref.loc17_9 [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.8e5 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %ptr.8e5 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.8e5 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%p.param: %ptr.8e5) -> out %return.param: %ptr.8e5 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.8e5 = name_ref p, %p\n// CHECK:STDOUT:   %impl.elem0: %.370 = impl_witness_access constants.%Copy.impl_witness.9d3, element0 [concrete = constants.%ptr.as.Copy.impl.Op.120]\n// CHECK:STDOUT:   %bound_method.loc17_36.1: <bound method> = bound_method %p.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%Class) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc17_36.2: <bound method> = bound_method %p.ref, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.8e5 = call %bound_method.loc17_36.2(%p.ref)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/adapt.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/adapt.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/adapt.carbon\n\n// --- adapt_specific_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(T:! type) {\n  var x: T;\n}\n\nclass Adapter {\n  adapt C(i32);\n}\n\nfn Access(a: Adapter) -> i32 {\n  return (a as C(i32)).x;\n}\n\n// --- import_adapt_specific_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"adapt_specific_type\";\n\nfn ImportedAccess(a: Adapter) -> i32 {\n  return (a as C(i32)).x;\n}\n\n// --- fail_todo_extend_adapt_specific_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(T:! type) {\n  var x: T;\n}\n\nclass Adapter {\n  extend adapt C(i32);\n}\n\nfn Access(a: Adapter) -> i32 {\n  // TODO: This should presumably work, but the design doesn't say how yet.\n  // CHECK:STDERR: fail_todo_extend_adapt_specific_type.carbon:[[@LINE+7]]:10: error: cannot implicitly convert expression of type `Adapter` to `C(i32)` [ConversionFailure]\n  // CHECK:STDERR:   return a.x;\n  // CHECK:STDERR:          ^~~\n  // CHECK:STDERR: fail_todo_extend_adapt_specific_type.carbon:[[@LINE+4]]:10: note: type `Adapter` does not implement interface `Core.ImplicitAs(C(i32))` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return a.x;\n  // CHECK:STDERR:          ^~~\n  // CHECK:STDERR:\n  return a.x;\n}\n\n// --- extend_adapt_specific_type_library.carbon\n\n// TODO: Delete this file and change the next file to instead import the\n// previous file once the previous file can be successfully type-checked.\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(T:! type) {\n  var x: T;\n}\n\nclass Adapter {\n  extend adapt C(i32);\n}\n\n// --- fail_todo_import_extend_adapt_specific_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extend_adapt_specific_type_library\";\n\nfn ImportedAccess(a: Adapter) -> i32 {\n  // TODO: This should presumably work, but the design doesn't say how yet.\n  // CHECK:STDERR: fail_todo_import_extend_adapt_specific_type.carbon:[[@LINE+7]]:10: error: cannot implicitly convert expression of type `Adapter` to `C(i32)` [ConversionFailure]\n  // CHECK:STDERR:   return a.x;\n  // CHECK:STDERR:          ^~~\n  // CHECK:STDERR: fail_todo_import_extend_adapt_specific_type.carbon:[[@LINE+4]]:10: note: type `Adapter` does not implement interface `Core.ImplicitAs(C(i32))` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return a.x;\n  // CHECK:STDERR:          ^~~\n  // CHECK:STDERR:\n  return a.x;\n}\n\n// --- adapt_generic_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Adapter(T:! type) {\n  adapt T;\n}\n\nfn Convert(a: Adapter(i32)) -> i32 {\n  return a as i32;\n}\n\n// --- import_adapt_generic_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"adapt_generic_type\";\n\nfn ImportedConvert(a: Adapter(i32)) -> i32 {\n  return a as i32;\n}\n\nclass C {\n  var n: i32;\n}\n\nfn ImportedConvertLocal(a: Adapter(C)) -> i32 {\n  return (a as C).n;\n}\n\n// CHECK:STDOUT: --- adapt_specific_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T.67d) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67d [symbolic]\n// CHECK:STDOUT:   %C.elem.bd3: type = unbound_element_type %C.5a3, %T.67d [symbolic]\n// CHECK:STDOUT:   %struct_type.x.0c5: type = struct_type {.x: %T.67d} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x.0c5 [symbolic]\n// CHECK:STDOUT:   %Adapter: type = class_type @Adapter [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %C.b13: type = class_type @C, @C(%i32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %C.elem.8f4: type = unbound_element_type %C.b13, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x.ed6: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x.ed6 [concrete]\n// CHECK:STDOUT:   %pattern_type.bf2: type = pattern_type %Adapter [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Access.type: type = fn_type @Access [concrete]\n// CHECK:STDOUT:   %Access: %Access.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Adapter = %Adapter.decl\n// CHECK:STDOUT:     .Access = %Access.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Adapter.decl: type = class_decl @Adapter [concrete = constants.%Adapter] {} {}\n// CHECK:STDOUT:   %Access.decl: %Access.type = fn_decl @Access [concrete = constants.%Access] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.bf2 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.bf2 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc12: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc12: Core.Form = init_form %i32.loc12 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %Adapter = value_param call_param0\n// CHECK:STDOUT:     %Adapter.ref: type = name_ref Adapter, file.%Adapter.decl [concrete = constants.%Adapter]\n// CHECK:STDOUT:     %a: %Adapter = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T.loc4_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_9.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T.loc4_9.1) [symbolic = %C (constants.%C.5a3)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %T.loc4_9.1 [symbolic = %C.elem (constants.%C.elem.bd3)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @C.%T.loc4_9.1 (%T.67d)} [symbolic = %struct_type.x (constants.%struct_type.x.0c5)]\n// CHECK:STDOUT:   %complete_type.loc6_1.2: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_9.2 [symbolic = %T.loc4_9.1 (constants.%T.67d)]\n// CHECK:STDOUT:     %.loc5: @C.%C.elem (%C.elem.bd3) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc6_1.1: <witness> = complete_type_witness constants.%struct_type.x.0c5 [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc6_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .x = %.loc5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Adapter {\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%i32) [concrete = constants.%C.b13]\n// CHECK:STDOUT:   adapt_decl %C [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x.ed6 [concrete = constants.%complete_type.1ec]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Adapter\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Access(%a.param: %Adapter) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Adapter = name_ref a, %a\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %i32.loc13: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%i32) [concrete = constants.%C.b13]\n// CHECK:STDOUT:   %.loc13_13.1: %C.b13 = as_compatible %a.ref\n// CHECK:STDOUT:   %.loc13_13.2: %C.b13 = converted %a.ref, %.loc13_13.1\n// CHECK:STDOUT:   %x.ref: %C.elem.8f4 = name_ref x, @C.%.loc5 [concrete = @C.%.loc5]\n// CHECK:STDOUT:   %.loc13_23.1: ref %i32 = class_element_access %.loc13_13.2, element0\n// CHECK:STDOUT:   %.loc13_23.2: %i32 = acquire_value %.loc13_23.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc13_23.1: <bound method> = bound_method %.loc13_23.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_23.2: <bound method> = bound_method %.loc13_23.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc13_23.2(%.loc13_23.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%i32) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %C => constants.%C.b13\n// CHECK:STDOUT:   %C.elem => constants.%C.elem.8f4\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.ed6\n// CHECK:STDOUT:   %complete_type.loc6_1.2 => constants.%complete_type.1ec\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- import_adapt_specific_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Adapter: type = class_type @Adapter [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %struct_type.x.0c5: type = struct_type {.x: %T.67d} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x.0c5 [symbolic]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T.67d) [symbolic]\n// CHECK:STDOUT:   %C.elem.bd3: type = unbound_element_type %C.5a3, %T.67d [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67d [symbolic]\n// CHECK:STDOUT:   %C.829: type = class_type @C, @C(%i32) [concrete]\n// CHECK:STDOUT:   %struct_type.x.767: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.c07: <witness> = complete_type_witness %struct_type.x.767 [concrete]\n// CHECK:STDOUT:   %C.elem.fd3: type = unbound_element_type %C.829, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.bf2: type = pattern_type %Adapter [concrete]\n// CHECK:STDOUT:   %.4ca: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.501: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %ImportedAccess.type: type = fn_type @ImportedAccess [concrete]\n// CHECK:STDOUT:   %ImportedAccess: %ImportedAccess.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.08e: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.014: %Int.as.Copy.impl.Op.type.08e = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.a2f: <witness> = impl_witness imports.%Copy.impl_witness_table.d6d, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.837: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.2b1: %Int.as.Copy.impl.Op.type.837 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.a2f) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.67d: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.d31: type = fn_type_with_self_type %Copy.WithSelf.Op.type.67d, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.2b1, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: %C.type = import_ref Main//adapt_specific_type, C, loaded [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %Main.Adapter: type = import_ref Main//adapt_specific_type, Adapter, loaded [concrete = constants.%Adapter]\n// CHECK:STDOUT:   %Main.Access = import_ref Main//adapt_specific_type, Access, unloaded\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.7e3: <witness> = import_ref Main//adapt_specific_type, loc6_1, loaded [symbolic = @C.%complete_type (constants.%complete_type.735)]\n// CHECK:STDOUT:   %Main.import_ref.820 = import_ref Main//adapt_specific_type, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.b94: @C.%C.elem (%C.elem.bd3) = import_ref Main//adapt_specific_type, loc5_8, loaded [concrete = %.68d]\n// CHECK:STDOUT:   %Main.import_ref.b3b: type = import_ref Main//adapt_specific_type, loc4_9, loaded [symbolic = @C.%T (constants.%T.67d)]\n// CHECK:STDOUT:   %Main.import_ref.709: <witness> = import_ref Main//adapt_specific_type, loc10_1, loaded [concrete = constants.%complete_type.c07]\n// CHECK:STDOUT:   %Main.import_ref.085 = import_ref Main//adapt_specific_type, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %.68d: @C.%C.elem (%C.elem.bd3) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.ea6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.08e) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.014)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.d6d = impl_witness_table (%Core.import_ref.ea6), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Adapter = imports.%Main.Adapter\n// CHECK:STDOUT:     .Access = imports.%Main.Access\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .ImportedAccess = %ImportedAccess.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %ImportedAccess.decl: %ImportedAccess.type = fn_decl @ImportedAccess [concrete = constants.%ImportedAccess] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.bf2 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.bf2 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.501 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.501 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6: Core.Form = init_form %i32.loc6 [concrete = constants.%.4ca]\n// CHECK:STDOUT:     %a.param: %Adapter = value_param call_param0\n// CHECK:STDOUT:     %Adapter.ref: type = name_ref Adapter, imports.%Main.Adapter [concrete = constants.%Adapter]\n// CHECK:STDOUT:     %a: %Adapter = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Adapter [from \"adapt_specific_type.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.709\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.085\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(imports.%Main.import_ref.b3b: type) [from \"adapt_specific_type.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T) [symbolic = %C (constants.%C.5a3)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %T [symbolic = %C.elem (constants.%C.elem.bd3)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @C.%T (%T.67d)} [symbolic = %struct_type.x (constants.%struct_type.x.0c5)]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.7e3\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.820\n// CHECK:STDOUT:     .x = imports.%Main.import_ref.b94\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImportedAccess(%a.param: %Adapter) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Adapter = name_ref a, %a\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, imports.%Main.C [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %i32.loc7: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%i32) [concrete = constants.%C.829]\n// CHECK:STDOUT:   %.loc7_13.1: %C.829 = as_compatible %a.ref\n// CHECK:STDOUT:   %.loc7_13.2: %C.829 = converted %a.ref, %.loc7_13.1\n// CHECK:STDOUT:   %x.ref: %C.elem.fd3 = name_ref x, imports.%Main.import_ref.b94 [concrete = imports.%.68d]\n// CHECK:STDOUT:   %.loc7_23.1: ref %i32 = class_element_access %.loc7_13.2, element0\n// CHECK:STDOUT:   %.loc7_23.2: %i32 = acquire_value %.loc7_23.1\n// CHECK:STDOUT:   %impl.elem0: %.d31 = impl_witness_access constants.%Copy.impl_witness.a2f, element0 [concrete = constants.%Int.as.Copy.impl.Op.2b1]\n// CHECK:STDOUT:   %bound_method.loc7_23.1: <bound method> = bound_method %.loc7_23.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_23.2: <bound method> = bound_method %.loc7_23.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc7_23.2(%.loc7_23.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T.67d) {\n// CHECK:STDOUT:   %T => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %C => constants.%C.829\n// CHECK:STDOUT:   %C.elem => constants.%C.elem.fd3\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.767\n// CHECK:STDOUT:   %complete_type => constants.%complete_type.c07\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_extend_adapt_specific_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %C.elem.bd3: type = unbound_element_type %C.5a3, %T [symbolic]\n// CHECK:STDOUT:   %struct_type.x.0c5: type = struct_type {.x: %T} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x.0c5 [symbolic]\n// CHECK:STDOUT:   %Adapter: type = class_type @Adapter [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %C.b13: type = class_type @C, @C(%i32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %C.elem.8f4: type = unbound_element_type %C.b13, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x.ed6: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x.ed6 [concrete]\n// CHECK:STDOUT:   %pattern_type.bf2: type = pattern_type %Adapter [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Access.type: type = fn_type @Access [concrete]\n// CHECK:STDOUT:   %Access: %Access.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Adapter = %Adapter.decl\n// CHECK:STDOUT:     .Access = %Access.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Adapter.decl: type = class_decl @Adapter [concrete = constants.%Adapter] {} {}\n// CHECK:STDOUT:   %Access.decl: %Access.type = fn_decl @Access [concrete = constants.%Access] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.bf2 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.bf2 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc12: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %Adapter = value_param call_param0\n// CHECK:STDOUT:     %Adapter.ref: type = name_ref Adapter, file.%Adapter.decl [concrete = constants.%Adapter]\n// CHECK:STDOUT:     %a: %Adapter = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T.loc4_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_9.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T.loc4_9.1) [symbolic = %C (constants.%C.5a3)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %T.loc4_9.1 [symbolic = %C.elem (constants.%C.elem.bd3)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @C.%T.loc4_9.1 (%T)} [symbolic = %struct_type.x (constants.%struct_type.x.0c5)]\n// CHECK:STDOUT:   %complete_type.loc6_1.2: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_9.2 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc5: @C.%C.elem (%C.elem.bd3) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc6_1.1: <witness> = complete_type_witness constants.%struct_type.x.0c5 [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc6_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .x = %.loc5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Adapter {\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%i32) [concrete = constants.%C.b13]\n// CHECK:STDOUT:   adapt_decl %C [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x.ed6 [concrete = constants.%complete_type.1ec]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Adapter\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT:   .x = <poisoned>\n// CHECK:STDOUT:   extend %C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Access(%a.param: %Adapter) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Adapter = name_ref a, %a\n// CHECK:STDOUT:   %x.ref: %C.elem.8f4 = name_ref x, @C.%.loc5 [concrete = @C.%.loc5]\n// CHECK:STDOUT:   %.loc21_11.1: %C.b13 = converted %a.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %.loc21_11.2: %i32 = class_element_access <error>, element0 [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%i32) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %C => constants.%C.b13\n// CHECK:STDOUT:   %C.elem => constants.%C.elem.8f4\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.ed6\n// CHECK:STDOUT:   %complete_type.loc6_1.2 => constants.%complete_type.1ec\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extend_adapt_specific_type_library.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %C.elem.bd3: type = unbound_element_type %C.5a3, %T [symbolic]\n// CHECK:STDOUT:   %struct_type.x.0c5: type = struct_type {.x: %T} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x.0c5 [symbolic]\n// CHECK:STDOUT:   %Adapter: type = class_type @Adapter [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %C.b13: type = class_type @C, @C(%i32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %C.elem.8f4: type = unbound_element_type %C.b13, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x.ed6: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x.ed6 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Adapter = %Adapter.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_13.1: type = splice_block %.loc7_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Adapter.decl: type = class_decl @Adapter [concrete = constants.%Adapter] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc7_9.2: type) {\n// CHECK:STDOUT:   %T.loc7_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc7_9.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T.loc7_9.1) [symbolic = %C (constants.%C.5a3)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %T.loc7_9.1 [symbolic = %C.elem (constants.%C.elem.bd3)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @C.%T.loc7_9.1 (%T)} [symbolic = %struct_type.x (constants.%struct_type.x.0c5)]\n// CHECK:STDOUT:   %complete_type.loc9_1.2: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type.loc9_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc7_9.2 [symbolic = %T.loc7_9.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc8: @C.%C.elem (%C.elem.bd3) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc9_1.1: <witness> = complete_type_witness constants.%struct_type.x.0c5 [symbolic = %complete_type.loc9_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc9_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .x = %.loc8\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Adapter {\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%i32) [concrete = constants.%C.b13]\n// CHECK:STDOUT:   adapt_decl %C [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x.ed6 [concrete = constants.%complete_type.1ec]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Adapter\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT:   extend %C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%i32) {\n// CHECK:STDOUT:   %T.loc7_9.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %C => constants.%C.b13\n// CHECK:STDOUT:   %C.elem => constants.%C.elem.8f4\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.ed6\n// CHECK:STDOUT:   %complete_type.loc9_1.2 => constants.%complete_type.1ec\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_import_extend_adapt_specific_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Adapter: type = class_type @Adapter [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %struct_type.x.0c5: type = struct_type {.x: %T} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x.0c5 [symbolic]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %C.elem.bd3: type = unbound_element_type %C.5a3, %T [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %C.829: type = class_type @C, @C(%i32) [concrete]\n// CHECK:STDOUT:   %struct_type.x.767: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.c07: <witness> = complete_type_witness %struct_type.x.767 [concrete]\n// CHECK:STDOUT:   %C.elem.fd3: type = unbound_element_type %C.829, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.bf2: type = pattern_type %Adapter [concrete]\n// CHECK:STDOUT:   %.4ca: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.501: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %ImportedAccess.type: type = fn_type @ImportedAccess [concrete]\n// CHECK:STDOUT:   %ImportedAccess: %ImportedAccess.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//extend_adapt_specific_type_library, C, unloaded\n// CHECK:STDOUT:   %Main.Adapter: type = import_ref Main//extend_adapt_specific_type_library, Adapter, loaded [concrete = constants.%Adapter]\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.7e3: <witness> = import_ref Main//extend_adapt_specific_type_library, loc9_1, loaded [symbolic = @C.%complete_type (constants.%complete_type.735)]\n// CHECK:STDOUT:   %Main.import_ref.820 = import_ref Main//extend_adapt_specific_type_library, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.b94: @C.%C.elem (%C.elem.bd3) = import_ref Main//extend_adapt_specific_type_library, loc8_8, loaded [concrete = %.68d]\n// CHECK:STDOUT:   %Main.import_ref.b3b: type = import_ref Main//extend_adapt_specific_type_library, loc7_9, loaded [symbolic = @C.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.709: <witness> = import_ref Main//extend_adapt_specific_type_library, loc13_1, loaded [concrete = constants.%complete_type.c07]\n// CHECK:STDOUT:   %Main.import_ref.085 = import_ref Main//extend_adapt_specific_type_library, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.9da228.2: type = import_ref Main//extend_adapt_specific_type_library, loc12_21, loaded [concrete = constants.%C.829]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %.68d: @C.%C.elem (%C.elem.bd3) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Adapter = imports.%Main.Adapter\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .ImportedAccess = %ImportedAccess.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %ImportedAccess.decl: %ImportedAccess.type = fn_decl @ImportedAccess [concrete = constants.%ImportedAccess] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.bf2 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.bf2 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.501 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.501 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6: Core.Form = init_form %i32 [concrete = constants.%.4ca]\n// CHECK:STDOUT:     %a.param: %Adapter = value_param call_param0\n// CHECK:STDOUT:     %Adapter.ref: type = name_ref Adapter, imports.%Main.Adapter [concrete = constants.%Adapter]\n// CHECK:STDOUT:     %a: %Adapter = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Adapter [from \"extend_adapt_specific_type_library.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.709\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.085\n// CHECK:STDOUT:   .x = <poisoned>\n// CHECK:STDOUT:   extend imports.%Main.import_ref.9da228.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(imports.%Main.import_ref.b3b: type) [from \"extend_adapt_specific_type_library.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T) [symbolic = %C (constants.%C.5a3)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %T [symbolic = %C.elem (constants.%C.elem.bd3)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @C.%T (%T)} [symbolic = %struct_type.x (constants.%struct_type.x.0c5)]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.7e3\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.820\n// CHECK:STDOUT:     .x = imports.%Main.import_ref.b94\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImportedAccess(%a.param: %Adapter) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Adapter = name_ref a, %a\n// CHECK:STDOUT:   %x.ref: %C.elem.fd3 = name_ref x, imports.%Main.import_ref.b94 [concrete = imports.%.68d]\n// CHECK:STDOUT:   %.loc15_11.1: %C.829 = converted %a.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %.loc15_11.2: %i32 = class_element_access <error>, element0 [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %C => constants.%C.829\n// CHECK:STDOUT:   %C.elem => constants.%C.elem.fd3\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.767\n// CHECK:STDOUT:   %complete_type => constants.%complete_type.c07\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- adapt_generic_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Adapter.type: type = generic_class_type @Adapter [concrete]\n// CHECK:STDOUT:   %Adapter.generic: %Adapter.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Adapter.562: type = class_type @Adapter, @Adapter(%T.67d) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67d [symbolic]\n// CHECK:STDOUT:   %complete_type.1aa: <witness> = complete_type_witness %T.67d [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Adapter.b1e: type = class_type @Adapter, @Adapter(%i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.1fb: type = pattern_type %Adapter.b1e [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Convert.type: type = fn_type @Convert [concrete]\n// CHECK:STDOUT:   %Convert: %Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %complete_type.1eb: <witness> = complete_type_witness %i32 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Adapter = %Adapter.decl\n// CHECK:STDOUT:     .Convert = %Convert.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Adapter.decl: %Adapter.type = class_decl @Adapter [concrete = constants.%Adapter.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Convert.decl: %Convert.type = fn_decl @Convert [concrete = constants.%Convert] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1fb = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.1fb = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc8_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc8_32: Core.Form = init_form %i32.loc8_32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %Adapter.b1e = value_param call_param0\n// CHECK:STDOUT:     %.loc8_26: type = splice_block %Adapter [concrete = constants.%Adapter.b1e] {\n// CHECK:STDOUT:       %Adapter.ref: %Adapter.type = name_ref Adapter, file.%Adapter.decl [concrete = constants.%Adapter.generic]\n// CHECK:STDOUT:       %i32.loc8_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %Adapter: type = class_type @Adapter, @Adapter(constants.%i32) [concrete = constants.%Adapter.b1e]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %Adapter.b1e = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Adapter(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_15.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %complete_type.loc6_1.2: <witness> = complete_type_witness %T.loc4_15.1 [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.1aa)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_15.2 [symbolic = %T.loc4_15.1 (constants.%T.67d)]\n// CHECK:STDOUT:     adapt_decl %T.ref [concrete]\n// CHECK:STDOUT:     %complete_type.loc6_1.1: <witness> = complete_type_witness constants.%T.67d [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.1aa)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc6_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Adapter.562\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Convert(%a.param: %Adapter.b1e) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Adapter.b1e = name_ref a, %a\n// CHECK:STDOUT:   %i32.loc9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc9_12.1: %i32 = as_compatible %a.ref\n// CHECK:STDOUT:   %.loc9_12.2: %i32 = converted %a.ref, %.loc9_12.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc9_12.1: <bound method> = bound_method %.loc9_12.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_12.2: <bound method> = bound_method %.loc9_12.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc9_12.2(%.loc9_12.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Adapter(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Adapter(constants.%i32) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %complete_type.loc6_1.2 => constants.%complete_type.1eb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- import_adapt_generic_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Adapter.type: type = generic_class_type @Adapter [concrete]\n// CHECK:STDOUT:   %Adapter.generic: %Adapter.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %complete_type.1aa: <witness> = complete_type_witness %T.67d [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67d [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Adapter.b1e: type = class_type @Adapter, @Adapter(%i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.1fb: type = pattern_type %Adapter.b1e [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %ImportedConvert.type: type = fn_type @ImportedConvert [concrete]\n// CHECK:STDOUT:   %ImportedConvert: %ImportedConvert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %complete_type.1eb: <witness> = complete_type_witness %i32 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %Adapter.8a3: type = class_type @Adapter, @Adapter(%C) [concrete]\n// CHECK:STDOUT:   %pattern_type.014: type = pattern_type %Adapter.8a3 [concrete]\n// CHECK:STDOUT:   %ImportedConvertLocal.type: type = fn_type @ImportedConvertLocal [concrete]\n// CHECK:STDOUT:   %ImportedConvertLocal: %ImportedConvertLocal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.53d: <witness> = complete_type_witness %C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Adapter: %Adapter.type = import_ref Main//adapt_generic_type, Adapter, loaded [concrete = constants.%Adapter.generic]\n// CHECK:STDOUT:   %Main.Convert = import_ref Main//adapt_generic_type, Convert, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.80d: <witness> = import_ref Main//adapt_generic_type, loc6_1, loaded [symbolic = @Adapter.%complete_type (constants.%complete_type.1aa)]\n// CHECK:STDOUT:   %Main.import_ref.5a1 = import_ref Main//adapt_generic_type, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3b: type = import_ref Main//adapt_generic_type, loc4_15, loaded [symbolic = @Adapter.%T (constants.%T.67d)]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Adapter = imports.%Main.Adapter\n// CHECK:STDOUT:     .Convert = imports.%Main.Convert\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ImportedConvert = %ImportedConvert.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .ImportedConvertLocal = %ImportedConvertLocal.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %ImportedConvert.decl: %ImportedConvert.type = fn_decl @ImportedConvert [concrete = constants.%ImportedConvert] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1fb = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.1fb = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6_40: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6_40: Core.Form = init_form %i32.loc6_40 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %Adapter.b1e = value_param call_param0\n// CHECK:STDOUT:     %.loc6_34: type = splice_block %Adapter [concrete = constants.%Adapter.b1e] {\n// CHECK:STDOUT:       %Adapter.ref: %Adapter.type = name_ref Adapter, imports.%Main.Adapter [concrete = constants.%Adapter.generic]\n// CHECK:STDOUT:       %i32.loc6_31: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %Adapter: type = class_type @Adapter, @Adapter(constants.%i32) [concrete = constants.%Adapter.b1e]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %Adapter.b1e = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %ImportedConvertLocal.decl: %ImportedConvertLocal.type = fn_decl @ImportedConvertLocal [concrete = constants.%ImportedConvertLocal] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.014 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.014 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc14_43: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %Adapter.8a3 = value_param call_param0\n// CHECK:STDOUT:     %.loc14_37: type = splice_block %Adapter [concrete = constants.%Adapter.8a3] {\n// CHECK:STDOUT:       %Adapter.ref: %Adapter.type = name_ref Adapter, imports.%Main.Adapter [concrete = constants.%Adapter.generic]\n// CHECK:STDOUT:       %C.ref.loc14: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %Adapter: type = class_type @Adapter, @Adapter(constants.%C) [concrete = constants.%Adapter.8a3]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %Adapter.8a3 = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Adapter(imports.%Main.import_ref.b3b: type) [from \"adapt_generic_type.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %T [symbolic = %complete_type (constants.%complete_type.1aa)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.80d\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.5a1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc11: %C.elem = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .n = %.loc11\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImportedConvert(%a.param: %Adapter.b1e) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Adapter.b1e = name_ref a, %a\n// CHECK:STDOUT:   %i32.loc7: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc7_12.1: %i32 = as_compatible %a.ref\n// CHECK:STDOUT:   %.loc7_12.2: %i32 = converted %a.ref, %.loc7_12.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc7_12.1: <bound method> = bound_method %.loc7_12.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_12.2: <bound method> = bound_method %.loc7_12.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc7_12.2(%.loc7_12.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImportedConvertLocal(%a.param: %Adapter.8a3) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Adapter.8a3 = name_ref a, %a\n// CHECK:STDOUT:   %C.ref.loc15: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc15_13.1: %C = as_compatible %a.ref\n// CHECK:STDOUT:   %.loc15_13.2: %C = converted %a.ref, %.loc15_13.1\n// CHECK:STDOUT:   %n.ref: %C.elem = name_ref n, @C.%.loc11 [concrete = @C.%.loc11]\n// CHECK:STDOUT:   %.loc15_18.1: ref %i32 = class_element_access %.loc15_13.2, element0\n// CHECK:STDOUT:   %.loc15_18.2: %i32 = acquire_value %.loc15_18.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc15_18.1: <bound method> = bound_method %.loc15_18.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_18.2: <bound method> = bound_method %.loc15_18.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc15_18.2(%.loc15_18.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Adapter(constants.%T.67d) {\n// CHECK:STDOUT:   %T => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Adapter(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %complete_type => constants.%complete_type.1eb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Adapter(constants.%C) {\n// CHECK:STDOUT:   %T => constants.%C\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.54b\n// CHECK:STDOUT:   %complete_type => constants.%complete_type.53d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/base_is_generic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/base_is_generic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/base_is_generic.carbon\n\n// --- extend_generic_base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base(T:! type) {\n  var x: T;\n}\n\nclass Param {\n  var y: i32;\n}\n\nclass Derived {\n  extend base: Base(Param);\n}\n\nfn DoubleFieldAccess(d: Derived) -> i32 {\n  return d.x.y;\n}\n\n// --- import.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extend_generic_base\";\n\nfn ImportedDoubleFieldAccess(d: Derived) -> i32 {\n  return d.x.y;\n}\n\n// --- fail_todo_extend_symbolic_base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(T:! type) {\n  // CHECK:STDERR: fail_todo_extend_symbolic_base.carbon:[[@LINE+4]]:16: error: deriving from final type `T`; base type must be an `abstract` or `base` class [BaseIsFinal]\n  // CHECK:STDERR:   extend base: T;\n  // CHECK:STDERR:                ^\n  // CHECK:STDERR:\n  extend base: T;\n}\n\nbase class X {\n  fn G() {}\n}\n\nfn F() {\n  C(X).G();\n}\n\n// --- extend_generic_symbolic_base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class X(U:! type) {\n  fn G() -> U { return G(); }\n}\n\nclass C(T:! type) {\n  extend base: X(T);\n}\n\nfn F() {\n  let unused i: i32 = C(i32).G();\n}\n\n\n// --- import_extend_generic_symbolic_base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extend_generic_symbolic_base\";\n\nfn H() {\n  let unused j: i32 = C(i32).G();\n}\n\n// CHECK:STDOUT: --- extend_generic_base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.d0c: type = class_type @Base, @Base(%T.67d) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67d [symbolic]\n// CHECK:STDOUT:   %Base.elem.8ab: type = unbound_element_type %Base.d0c, %T.67d [symbolic]\n// CHECK:STDOUT:   %struct_type.x.0c5: type = struct_type {.x: %T.67d} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x.0c5 [symbolic]\n// CHECK:STDOUT:   %Param: type = class_type @Param [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Param.elem: type = unbound_element_type %Param, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.y: type = struct_type {.y: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.0f9: <witness> = complete_type_witness %struct_type.y [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Base.f8f: type = class_type @Base, @Base(%Param) [concrete]\n// CHECK:STDOUT:   %Base.elem.6d8: type = unbound_element_type %Base.f8f, %Param [concrete]\n// CHECK:STDOUT:   %struct_type.x.d96: type = struct_type {.x: %Param} [concrete]\n// CHECK:STDOUT:   %complete_type.95c: <witness> = complete_type_witness %struct_type.x.d96 [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base.f8f [concrete]\n// CHECK:STDOUT:   %struct_type.base.9a9: type = struct_type {.base: %Base.f8f} [concrete]\n// CHECK:STDOUT:   %complete_type.8de: <witness> = complete_type_witness %struct_type.base.9a9 [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %DoubleFieldAccess.type: type = fn_type @DoubleFieldAccess [concrete]\n// CHECK:STDOUT:   %DoubleFieldAccess: %DoubleFieldAccess.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Param = %Param.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .DoubleFieldAccess = %DoubleFieldAccess.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: %Base.type = class_decl @Base [concrete = constants.%Base.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_21.1: type = splice_block %.loc4_21.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_21.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_17.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Param.decl: type = class_decl @Param [concrete = constants.%Param] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %DoubleFieldAccess.decl: %DoubleFieldAccess.type = fn_decl @DoubleFieldAccess [concrete = constants.%DoubleFieldAccess] {\n// CHECK:STDOUT:     %d.patt: %pattern_type.9f6 = value_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.param_patt: %pattern_type.9f6 = value_param_pattern %d.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %d.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:     %d: %Derived = value_binding d, %d.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(%T.loc4_17.2: type) {\n// CHECK:STDOUT:   %T.loc4_17.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_17.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T.loc4_17.1) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %T.loc4_17.1 [symbolic = %Base.elem (constants.%Base.elem.8ab)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @Base.%T.loc4_17.1 (%T.67d)} [symbolic = %struct_type.x (constants.%struct_type.x.0c5)]\n// CHECK:STDOUT:   %complete_type.loc6_1.2: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_17.2 [symbolic = %T.loc4_17.1 (constants.%T.67d)]\n// CHECK:STDOUT:     %.loc5: @Base.%Base.elem (%Base.elem.8ab) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc6_1.1: <witness> = complete_type_witness constants.%struct_type.x.0c5 [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc6_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Base.d0c\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .x = %.loc5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Param {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc9: %Param.elem = field_decl y, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.y [concrete = constants.%complete_type.0f9]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Param\n// CHECK:STDOUT:   .y = %.loc9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: %Base.type = name_ref Base, file.%Base.decl [concrete = constants.%Base.generic]\n// CHECK:STDOUT:   %Param.ref: type = name_ref Param, file.%Param.decl [concrete = constants.%Param]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(constants.%Param) [concrete = constants.%Base.f8f]\n// CHECK:STDOUT:   %.loc13: %Derived.elem = base_decl %Base, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.9a9 [concrete = constants.%complete_type.8de]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .Param = <poisoned>\n// CHECK:STDOUT:   .base = %.loc13\n// CHECK:STDOUT:   .x = <poisoned>\n// CHECK:STDOUT:   extend %Base\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @DoubleFieldAccess(%d.param: %Derived) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %d.ref: %Derived = name_ref d, %d\n// CHECK:STDOUT:   %x.ref: %Base.elem.6d8 = name_ref x, @Base.%.loc5 [concrete = @Base.%.loc5]\n// CHECK:STDOUT:   %.loc17_11.1: ref %Base.f8f = class_element_access %d.ref, element0\n// CHECK:STDOUT:   %.loc17_11.2: ref %Base.f8f = converted %d.ref, %.loc17_11.1\n// CHECK:STDOUT:   %.loc17_11.3: ref %Param = class_element_access %.loc17_11.2, element0\n// CHECK:STDOUT:   %y.ref: %Param.elem = name_ref y, @Param.%.loc9 [concrete = @Param.%.loc9]\n// CHECK:STDOUT:   %.loc17_13.1: ref %i32 = class_element_access %.loc17_11.3, element0\n// CHECK:STDOUT:   %.loc17_13.2: %i32 = acquire_value %.loc17_13.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc17_13.1: <bound method> = bound_method %.loc17_13.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc17_13.2: <bound method> = bound_method %.loc17_13.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc17_13.2(%.loc17_13.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%Param) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%Param\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.0f9\n// CHECK:STDOUT:   %Base => constants.%Base.f8f\n// CHECK:STDOUT:   %Base.elem => constants.%Base.elem.6d8\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.d96\n// CHECK:STDOUT:   %complete_type.loc6_1.2 => constants.%complete_type.95c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- import.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Param: type = class_type @Param [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.y: type = struct_type {.y: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.09d: <witness> = complete_type_witness %struct_type.y [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %struct_type.x.0c5: type = struct_type {.x: %T.67d} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x.0c5 [symbolic]\n// CHECK:STDOUT:   %Base.d0c: type = class_type @Base, @Base(%T.67d) [symbolic]\n// CHECK:STDOUT:   %Base.elem.8ab: type = unbound_element_type %Base.d0c, %T.67d [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67d [symbolic]\n// CHECK:STDOUT:   %Base.f8f: type = class_type @Base, @Base(%Param) [concrete]\n// CHECK:STDOUT:   %struct_type.x.d96: type = struct_type {.x: %Param} [concrete]\n// CHECK:STDOUT:   %complete_type.95c: <witness> = complete_type_witness %struct_type.x.d96 [concrete]\n// CHECK:STDOUT:   %Base.elem.6d8: type = unbound_element_type %Base.f8f, %Param [concrete]\n// CHECK:STDOUT:   %struct_type.base.9a9: type = struct_type {.base: %Base.f8f} [concrete]\n// CHECK:STDOUT:   %complete_type.8de: <witness> = complete_type_witness %struct_type.base.9a9 [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %.4ca: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.501: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %ImportedDoubleFieldAccess.type: type = fn_type @ImportedDoubleFieldAccess [concrete]\n// CHECK:STDOUT:   %ImportedDoubleFieldAccess: %ImportedDoubleFieldAccess.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Param.elem: type = unbound_element_type %Param, %i32 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.08e: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.014: %Int.as.Copy.impl.Op.type.08e = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.a2f: <witness> = impl_witness imports.%Copy.impl_witness_table.d6d, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.837: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.2b1: %Int.as.Copy.impl.Op.type.837 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.a2f) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.67d: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.d31: type = fn_type_with_self_type %Copy.WithSelf.Op.type.67d, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.2b1, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Base = import_ref Main//extend_generic_base, Base, unloaded\n// CHECK:STDOUT:   %Main.Param = import_ref Main//extend_generic_base, Param, unloaded\n// CHECK:STDOUT:   %Main.Derived: type = import_ref Main//extend_generic_base, Derived, loaded [concrete = constants.%Derived]\n// CHECK:STDOUT:   %Main.DoubleFieldAccess = import_ref Main//extend_generic_base, DoubleFieldAccess, unloaded\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.e8d: <witness> = import_ref Main//extend_generic_base, loc10_1, loaded [concrete = constants.%complete_type.09d]\n// CHECK:STDOUT:   %Main.import_ref.304 = import_ref Main//extend_generic_base, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.0c2: %Param.elem = import_ref Main//extend_generic_base, loc9_8, loaded [concrete = %.e89]\n// CHECK:STDOUT:   %Main.import_ref.7e3: <witness> = import_ref Main//extend_generic_base, loc6_1, loaded [symbolic = @Base.%complete_type (constants.%complete_type.735)]\n// CHECK:STDOUT:   %Main.import_ref.2af = import_ref Main//extend_generic_base, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.568: @Base.%Base.elem (%Base.elem.8ab) = import_ref Main//extend_generic_base, loc5_8, loaded [concrete = %.bef]\n// CHECK:STDOUT:   %Main.import_ref.b3b: type = import_ref Main//extend_generic_base, loc4_17, loaded [symbolic = @Base.%T (constants.%T.67d)]\n// CHECK:STDOUT:   %Main.import_ref.56c: <witness> = import_ref Main//extend_generic_base, loc14_1, loaded [concrete = constants.%complete_type.8de]\n// CHECK:STDOUT:   %Main.import_ref.33c = import_ref Main//extend_generic_base, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.4b4 = import_ref Main//extend_generic_base, loc13_27, unloaded\n// CHECK:STDOUT:   %Main.import_ref.8875f0.2: type = import_ref Main//extend_generic_base, loc13_26, loaded [concrete = constants.%Base.f8f]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %.bef: @Base.%Base.elem (%Base.elem.8ab) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %.e89: %Param.elem = field_decl y, element0 [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.ea6: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.08e) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.014)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.d6d = impl_witness_table (%Core.import_ref.ea6), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Base = imports.%Main.Base\n// CHECK:STDOUT:     .Param = imports.%Main.Param\n// CHECK:STDOUT:     .Derived = imports.%Main.Derived\n// CHECK:STDOUT:     .DoubleFieldAccess = imports.%Main.DoubleFieldAccess\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .ImportedDoubleFieldAccess = %ImportedDoubleFieldAccess.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %ImportedDoubleFieldAccess.decl: %ImportedDoubleFieldAccess.type = fn_decl @ImportedDoubleFieldAccess [concrete = constants.%ImportedDoubleFieldAccess] {\n// CHECK:STDOUT:     %d.patt: %pattern_type.9f6 = value_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.param_patt: %pattern_type.9f6 = value_param_pattern %d.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.501 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.501 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6: Core.Form = init_form %i32 [concrete = constants.%.4ca]\n// CHECK:STDOUT:     %d.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, imports.%Main.Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %d: %Derived = value_binding d, %d.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived [from \"extend_generic_base.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.56c\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.33c\n// CHECK:STDOUT:   .base = imports.%Main.import_ref.4b4\n// CHECK:STDOUT:   .x = <poisoned>\n// CHECK:STDOUT:   extend imports.%Main.import_ref.8875f0.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Param [from \"extend_generic_base.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.e8d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.304\n// CHECK:STDOUT:   .y = imports.%Main.import_ref.0c2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(imports.%Main.import_ref.b3b: type) [from \"extend_generic_base.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %T [symbolic = %Base.elem (constants.%Base.elem.8ab)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @Base.%T (%T.67d)} [symbolic = %struct_type.x (constants.%struct_type.x.0c5)]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.7e3\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.2af\n// CHECK:STDOUT:     .x = imports.%Main.import_ref.568\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImportedDoubleFieldAccess(%d.param: %Derived) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %d.ref: %Derived = name_ref d, %d\n// CHECK:STDOUT:   %x.ref: %Base.elem.6d8 = name_ref x, imports.%Main.import_ref.568 [concrete = imports.%.bef]\n// CHECK:STDOUT:   %.loc7_11.1: ref %Base.f8f = class_element_access %d.ref, element0\n// CHECK:STDOUT:   %.loc7_11.2: ref %Base.f8f = converted %d.ref, %.loc7_11.1\n// CHECK:STDOUT:   %.loc7_11.3: ref %Param = class_element_access %.loc7_11.2, element0\n// CHECK:STDOUT:   %y.ref: %Param.elem = name_ref y, imports.%Main.import_ref.0c2 [concrete = imports.%.e89]\n// CHECK:STDOUT:   %.loc7_13.1: ref %i32 = class_element_access %.loc7_11.3, element0\n// CHECK:STDOUT:   %.loc7_13.2: %i32 = acquire_value %.loc7_13.1\n// CHECK:STDOUT:   %impl.elem0: %.d31 = impl_witness_access constants.%Copy.impl_witness.a2f, element0 [concrete = constants.%Int.as.Copy.impl.Op.2b1]\n// CHECK:STDOUT:   %bound_method.loc7_13.1: <bound method> = bound_method %.loc7_13.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_13.2: <bound method> = bound_method %.loc7_13.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc7_13.2(%.loc7_13.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T.67d) {\n// CHECK:STDOUT:   %T => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%Param) {\n// CHECK:STDOUT:   %T => constants.%Param\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.09d\n// CHECK:STDOUT:   %Base => constants.%Base.f8f\n// CHECK:STDOUT:   %Base.elem => constants.%Base.elem.6d8\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.d96\n// CHECK:STDOUT:   %complete_type => constants.%complete_type.95c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_extend_symbolic_base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %X.G.type: type = fn_type @X.G [concrete]\n// CHECK:STDOUT:   %X.G: %X.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.513: type = class_type @C, @C(%X) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .X = %X.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %X.decl: type = class_decl @X [concrete = constants.%X] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T.loc4_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_9.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_9.2 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc9: <error> = base_decl <error>, element0 [concrete]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness <error> [concrete = <error>]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .base = %.loc9\n// CHECK:STDOUT:     .G = <poisoned>\n// CHECK:STDOUT:     has_error\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @X {\n// CHECK:STDOUT:   %X.G.decl: %X.G.type = fn_decl @X.G [concrete = constants.%X.G] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%X\n// CHECK:STDOUT:   .G = %X.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @X.G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %X.ref: type = name_ref X, file.%X.decl [concrete = constants.%X]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%X) [concrete = constants.%C.513]\n// CHECK:STDOUT:   %G.ref: <error> = name_ref G, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%X) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%X\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extend_generic_symbolic_base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %X.type: type = generic_class_type @X [concrete]\n// CHECK:STDOUT:   %X.generic: %X.type = struct_value () [concrete]\n// CHECK:STDOUT:   %X.03b463.1: type = class_type @X, @X(%U) [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %U [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %U [symbolic]\n// CHECK:STDOUT:   %X.G.type.20eb90.1: type = fn_type @X.G, @X(%U) [symbolic]\n// CHECK:STDOUT:   %X.G.f9f685.1: %X.G.type.20eb90.1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %U [symbolic]\n// CHECK:STDOUT:   %X.G.specific_fn.974: <specific function> = specific_function %X.G.f9f685.1, @X.G(%U) [symbolic]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %X.03b463.2: type = class_type @X, @X(%T) [symbolic]\n// CHECK:STDOUT:   %X.G.type.20eb90.2: type = fn_type @X.G, @X(%T) [symbolic]\n// CHECK:STDOUT:   %X.G.f9f685.2: %X.G.type.20eb90.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.5dd: <witness> = require_complete_type %X.03b463.2 [symbolic]\n// CHECK:STDOUT:   %C.elem.161: type = unbound_element_type %C.5a3, %X.03b463.2 [symbolic]\n// CHECK:STDOUT:   %struct_type.base.a6f: type = struct_type {.base: %X.03b463.2} [symbolic]\n// CHECK:STDOUT:   %complete_type.bec: <witness> = complete_type_witness %struct_type.base.a6f [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %C.b13: type = class_type @C, @C(%i32) [concrete]\n// CHECK:STDOUT:   %X.1bc: type = class_type @X, @X(%i32) [concrete]\n// CHECK:STDOUT:   %X.G.type.f75: type = fn_type @X.G, @X(%i32) [concrete]\n// CHECK:STDOUT:   %X.G.e2a: %X.G.type.f75 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.elem.7f5: type = unbound_element_type %C.b13, %X.1bc [concrete]\n// CHECK:STDOUT:   %struct_type.base.b52: type = struct_type {.base: %X.1bc} [concrete]\n// CHECK:STDOUT:   %complete_type.ab4: <witness> = complete_type_witness %struct_type.base.b52 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %X.G.specific_fn.54d: <specific function> = specific_function %X.G.e2a, @X.G(%i32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .X = %X.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %X.decl: %X.type = class_decl @X [concrete = constants.%X.generic] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_18.1: type = splice_block %.loc4_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc4_14.2: type = symbolic_binding U, 0 [symbolic = %U.loc4_14.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_13.1: type = splice_block %.loc8_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc8_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @X(%U.loc4_14.2: type) {\n// CHECK:STDOUT:   %U.loc4_14.1: type = symbolic_binding U, 0 [symbolic = %U.loc4_14.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.G.type: type = fn_type @X.G, @X(%U.loc4_14.1) [symbolic = %X.G.type (constants.%X.G.type.20eb90.1)]\n// CHECK:STDOUT:   %X.G: @X.%X.G.type (%X.G.type.20eb90.1) = struct_value () [symbolic = %X.G (constants.%X.G.f9f685.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %X.G.decl: @X.%X.G.type (%X.G.type.20eb90.1) = fn_decl @X.G [symbolic = @X.%X.G (constants.%X.G.f9f685.1)] {\n// CHECK:STDOUT:       %return.patt: @X.G.%pattern_type (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @X.G.%pattern_type (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %U.ref: type = name_ref U, @X.%U.loc4_14.2 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:       %.loc5_13.3: Core.Form = init_form %U.ref [symbolic = %.loc5_13.2 (constants.%.184)]\n// CHECK:STDOUT:       %return.param: ref @X.G.%U (%U) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @X.G.%U (%U) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%X.03b463.1\n// CHECK:STDOUT:     .U = <poisoned>\n// CHECK:STDOUT:     .G = %X.G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc8_9.2: type) {\n// CHECK:STDOUT:   %T.loc8_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc8_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.loc9_19.2: type = class_type @X, @X(%T.loc8_9.1) [symbolic = %X.loc9_19.2 (constants.%X.03b463.2)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %X.loc9_19.2 [symbolic = %require_complete (constants.%require_complete.5dd)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T.loc8_9.1) [symbolic = %C (constants.%C.5a3)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %X.loc9_19.2 [symbolic = %C.elem (constants.%C.elem.161)]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: @C.%X.loc9_19.2 (%X.03b463.2)} [symbolic = %struct_type.base (constants.%struct_type.base.a6f)]\n// CHECK:STDOUT:   %complete_type.loc10_1.2: <witness> = complete_type_witness %struct_type.base [symbolic = %complete_type.loc10_1.2 (constants.%complete_type.bec)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %X.ref: %X.type = name_ref X, file.%X.decl [concrete = constants.%X.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc8_9.2 [symbolic = %T.loc8_9.1 (constants.%T)]\n// CHECK:STDOUT:     %X.loc9_19.1: type = class_type @X, @X(constants.%T) [symbolic = %X.loc9_19.2 (constants.%X.03b463.2)]\n// CHECK:STDOUT:     %.loc9: @C.%C.elem (%C.elem.161) = base_decl %X.loc9_19.1, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc10_1.1: <witness> = complete_type_witness constants.%struct_type.base.a6f [symbolic = %complete_type.loc10_1.2 (constants.%complete_type.bec)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc10_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:     .X = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .base = %.loc9\n// CHECK:STDOUT:     .G = <poisoned>\n// CHECK:STDOUT:     extend %X.loc9_19.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @X.G(@X.%U.loc4_14.2: type) {\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:   %.loc5_13.2: Core.Form = init_form %U [symbolic = %.loc5_13.2 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %U [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %U [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %X.G.type: type = fn_type @X.G, @X(%U) [symbolic = %X.G.type (constants.%X.G.type.20eb90.1)]\n// CHECK:STDOUT:   %X.G: @X.G.%X.G.type (%X.G.type.20eb90.1) = struct_value () [symbolic = %X.G (constants.%X.G.f9f685.1)]\n// CHECK:STDOUT:   %X.G.specific_fn.loc5_24.2: <specific function> = specific_function %X.G, @X.G(%U) [symbolic = %X.G.specific_fn.loc5_24.2 (constants.%X.G.specific_fn.974)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @X.G.%U (%U) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc5_24: @X.G.%X.G.type (%X.G.type.20eb90.1) = specific_constant @X.%X.G.decl, @X(constants.%U) [symbolic = %X.G (constants.%X.G.f9f685.1)]\n// CHECK:STDOUT:     %G.ref: @X.G.%X.G.type (%X.G.type.20eb90.1) = name_ref G, %.loc5_24 [symbolic = %X.G (constants.%X.G.f9f685.1)]\n// CHECK:STDOUT:     %X.G.specific_fn.loc5_24.1: <specific function> = specific_function %G.ref, @X.G(constants.%U) [symbolic = %X.G.specific_fn.loc5_24.2 (constants.%X.G.specific_fn.974)]\n// CHECK:STDOUT:     %.loc5_13.1: ref @X.G.%U (%U) = splice_block %return.param {}\n// CHECK:STDOUT:     %X.G.call: init @X.G.%U (%U) to %.loc5_13.1 = call %X.G.specific_fn.loc5_24.1()\n// CHECK:STDOUT:     return %X.G.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.7ce = value_binding_pattern i [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %i32.loc13_25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%i32) [concrete = constants.%C.b13]\n// CHECK:STDOUT:   %.loc13_29: %X.G.type.f75 = specific_constant @X.%X.G.decl, @X(constants.%i32) [concrete = constants.%X.G.e2a]\n// CHECK:STDOUT:   %G.ref: %X.G.type.f75 = name_ref G, %.loc13_29 [concrete = constants.%X.G.e2a]\n// CHECK:STDOUT:   %X.G.specific_fn: <specific function> = specific_function %G.ref, @X.G(constants.%i32) [concrete = constants.%X.G.specific_fn.54d]\n// CHECK:STDOUT:   %X.G.call: init %i32 = call %X.G.specific_fn()\n// CHECK:STDOUT:   %i32.loc13_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc13_32.1: %i32 = value_of_initializer %X.G.call\n// CHECK:STDOUT:   %.loc13_32.2: %i32 = converted %X.G.call, %.loc13_32.1\n// CHECK:STDOUT:   %i: %i32 = value_binding i, %.loc13_32.2\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X(constants.%U) {\n// CHECK:STDOUT:   %U.loc4_14.1 => constants.%U\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.20eb90.1\n// CHECK:STDOUT:   %X.G => constants.%X.G.f9f685.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.G(constants.%U) {\n// CHECK:STDOUT:   %U => constants.%U\n// CHECK:STDOUT:   %.loc5_13.2 => constants.%.184\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.944\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.20eb90.1\n// CHECK:STDOUT:   %X.G => constants.%X.G.f9f685.1\n// CHECK:STDOUT:   %X.G.specific_fn.loc5_24.2 => constants.%X.G.specific_fn.974\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X(constants.%T) {\n// CHECK:STDOUT:   %U.loc4_14.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.20eb90.2\n// CHECK:STDOUT:   %X.G => constants.%X.G.f9f685.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%i32) {\n// CHECK:STDOUT:   %T.loc8_9.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.loc9_19.2 => constants.%X.1bc\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.357\n// CHECK:STDOUT:   %C => constants.%C.b13\n// CHECK:STDOUT:   %C.elem => constants.%C.elem.7f5\n// CHECK:STDOUT:   %struct_type.base => constants.%struct_type.base.b52\n// CHECK:STDOUT:   %complete_type.loc10_1.2 => constants.%complete_type.ab4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X(constants.%i32) {\n// CHECK:STDOUT:   %U.loc4_14.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.f75\n// CHECK:STDOUT:   %X.G => constants.%X.G.e2a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.G(constants.%i32) {\n// CHECK:STDOUT:   %U => constants.%i32\n// CHECK:STDOUT:   %.loc5_13.2 => constants.%.ff5\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7ce\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.f75\n// CHECK:STDOUT:   %X.G => constants.%X.G.e2a\n// CHECK:STDOUT:   %X.G.specific_fn.loc5_24.2 => constants.%X.G.specific_fn.54d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- import_extend_generic_symbolic_base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]\n// CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %X.G.type.20eb90.1: type = fn_type @X.G, @X(%U) [symbolic]\n// CHECK:STDOUT:   %X.G.f9f685.1: %X.G.type.20eb90.1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %U [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %U [symbolic]\n// CHECK:STDOUT:   %X.G.specific_fn.974: <specific function> = specific_function %X.G.f9f685.1, @X.G(%U) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %U [symbolic]\n// CHECK:STDOUT:   %X.03b463.2: type = class_type @X, @X(%T) [symbolic]\n// CHECK:STDOUT:   %X.G.type.20eb90.2: type = fn_type @X.G, @X(%T) [symbolic]\n// CHECK:STDOUT:   %X.G.f9f685.2: %X.G.type.20eb90.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %C.elem.161: type = unbound_element_type %C.5a3, %X.03b463.2 [symbolic]\n// CHECK:STDOUT:   %struct_type.base.a6f: type = struct_type {.base: %X.03b463.2} [symbolic]\n// CHECK:STDOUT:   %complete_type.bec: <witness> = complete_type_witness %struct_type.base.a6f [symbolic]\n// CHECK:STDOUT:   %require_complete.5dd: <witness> = require_complete_type %X.03b463.2 [symbolic]\n// CHECK:STDOUT:   %C.b13: type = class_type @C, @C(%i32) [concrete]\n// CHECK:STDOUT:   %X.1bc: type = class_type @X, @X(%i32) [concrete]\n// CHECK:STDOUT:   %X.G.type.f75: type = fn_type @X.G, @X(%i32) [concrete]\n// CHECK:STDOUT:   %X.G.e2a: %X.G.type.f75 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.elem.7f5: type = unbound_element_type %C.b13, %X.1bc [concrete]\n// CHECK:STDOUT:   %struct_type.base.b52: type = struct_type {.base: %X.1bc} [concrete]\n// CHECK:STDOUT:   %complete_type.ab4: <witness> = complete_type_witness %struct_type.base.b52 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %X.G.specific_fn.54d: <specific function> = specific_function %X.G.e2a, @X.G(%i32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.X = import_ref Main//extend_generic_symbolic_base, X, unloaded\n// CHECK:STDOUT:   %Main.C: %C.type = import_ref Main//extend_generic_symbolic_base, C, loaded [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %Main.F = import_ref Main//extend_generic_symbolic_base, F, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.1: type = import_ref Main//extend_generic_symbolic_base, loc4_14, loaded [symbolic = @X.%U (constants.%U)]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//extend_generic_symbolic_base, loc6_1, loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.5f5 = import_ref Main//extend_generic_symbolic_base, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.940: @X.%X.G.type (%X.G.type.20eb90.1) = import_ref Main//extend_generic_symbolic_base, loc5_15, loaded [symbolic = @X.%X.G (constants.%X.G.f9f685.1)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//extend_generic_symbolic_base, loc4_14, loaded [symbolic = @X.%U (constants.%U)]\n// CHECK:STDOUT:   %Main.import_ref.d67: <witness> = import_ref Main//extend_generic_symbolic_base, loc10_1, loaded [symbolic = @C.%complete_type (constants.%complete_type.bec)]\n// CHECK:STDOUT:   %Main.import_ref.820 = import_ref Main//extend_generic_symbolic_base, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.5a3 = import_ref Main//extend_generic_symbolic_base, loc9_20, unloaded\n// CHECK:STDOUT:   %Main.import_ref.7f62b4.2: type = import_ref Main//extend_generic_symbolic_base, loc9_19, loaded [symbolic = @C.%X (constants.%X.03b463.2)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.3: type = import_ref Main//extend_generic_symbolic_base, loc8_9, loaded [symbolic = @C.%T (constants.%T)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .X = imports.%Main.X\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .H = %H.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(imports.%Main.import_ref.b3bc94.3: type) [from \"extend_generic_symbolic_base.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X: type = class_type @X, @X(%T) [symbolic = %X (constants.%X.03b463.2)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %X [symbolic = %require_complete (constants.%require_complete.5dd)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T) [symbolic = %C (constants.%C.5a3)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %X [symbolic = %C.elem (constants.%C.elem.161)]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: @C.%X (%X.03b463.2)} [symbolic = %struct_type.base (constants.%struct_type.base.a6f)]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.base [symbolic = %complete_type (constants.%complete_type.bec)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.d67\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.820\n// CHECK:STDOUT:     .base = imports.%Main.import_ref.5a3\n// CHECK:STDOUT:     .G = <poisoned>\n// CHECK:STDOUT:     extend imports.%Main.import_ref.7f62b4.2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @X(imports.%Main.import_ref.b3bc94.2: type) [from \"extend_generic_symbolic_base.carbon\"] {\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.G.type: type = fn_type @X.G, @X(%U) [symbolic = %X.G.type (constants.%X.G.type.20eb90.1)]\n// CHECK:STDOUT:   %X.G: @X.%X.G.type (%X.G.type.20eb90.1) = struct_value () [symbolic = %X.G (constants.%X.G.f9f685.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.5f5\n// CHECK:STDOUT:     .G = imports.%Main.import_ref.940\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @H() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %j.patt: %pattern_type.7ce = value_binding_pattern j [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, imports.%Main.C [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %i32.loc7_25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%i32) [concrete = constants.%C.b13]\n// CHECK:STDOUT:   %.loc7_29: %X.G.type.f75 = specific_constant imports.%Main.import_ref.940, @X(constants.%i32) [concrete = constants.%X.G.e2a]\n// CHECK:STDOUT:   %G.ref: %X.G.type.f75 = name_ref G, %.loc7_29 [concrete = constants.%X.G.e2a]\n// CHECK:STDOUT:   %X.G.specific_fn: <specific function> = specific_function %G.ref, @X.G(constants.%i32) [concrete = constants.%X.G.specific_fn.54d]\n// CHECK:STDOUT:   %X.G.call: init %i32 = call %X.G.specific_fn()\n// CHECK:STDOUT:   %i32.loc7_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc7_32.1: %i32 = value_of_initializer %X.G.call\n// CHECK:STDOUT:   %.loc7_32.2: %i32 = converted %X.G.call, %.loc7_32.1\n// CHECK:STDOUT:   %j: %i32 = value_binding j, %.loc7_32.2\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @X.G(imports.%Main.import_ref.b3bc94.1: type) [from \"extend_generic_symbolic_base.carbon\"] {\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:   %.1: Core.Form = init_form %U [symbolic = %.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %U [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %U [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %X.G.type: type = fn_type @X.G, @X(%U) [symbolic = %X.G.type (constants.%X.G.type.20eb90.1)]\n// CHECK:STDOUT:   %X.G: @X.G.%X.G.type (%X.G.type.20eb90.1) = struct_value () [symbolic = %X.G (constants.%X.G.f9f685.1)]\n// CHECK:STDOUT:   %X.G.specific_fn: <specific function> = specific_function %X.G, @X.G(%U) [symbolic = %X.G.specific_fn (constants.%X.G.specific_fn.974)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X(constants.%U) {\n// CHECK:STDOUT:   %U => constants.%U\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.20eb90.1\n// CHECK:STDOUT:   %X.G => constants.%X.G.f9f685.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.G(constants.%U) {\n// CHECK:STDOUT:   %U => constants.%U\n// CHECK:STDOUT:   %.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.944\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.20eb90.1\n// CHECK:STDOUT:   %X.G => constants.%X.G.f9f685.1\n// CHECK:STDOUT:   %X.G.specific_fn => constants.%X.G.specific_fn.974\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X(constants.%T) {\n// CHECK:STDOUT:   %U => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.20eb90.2\n// CHECK:STDOUT:   %X.G => constants.%X.G.f9f685.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X => constants.%X.1bc\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.357\n// CHECK:STDOUT:   %C => constants.%C.b13\n// CHECK:STDOUT:   %C.elem => constants.%C.elem.7f5\n// CHECK:STDOUT:   %struct_type.base => constants.%struct_type.base.b52\n// CHECK:STDOUT:   %complete_type => constants.%complete_type.ab4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X(constants.%i32) {\n// CHECK:STDOUT:   %U => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.f75\n// CHECK:STDOUT:   %X.G => constants.%X.G.e2a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.G(constants.%i32) {\n// CHECK:STDOUT:   %U => constants.%i32\n// CHECK:STDOUT:   %.1 => constants.%.ff5\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7ce\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %X.G.type => constants.%X.G.type.f75\n// CHECK:STDOUT:   %X.G => constants.%X.G.e2a\n// CHECK:STDOUT:   %X.G.specific_fn => constants.%X.G.specific_fn.54d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/basic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/basic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/basic.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nclass Class(T:! Core.Copy) {\n  fn GetAddr[ref self: Self]() -> T* {\n    return &self.k;\n  }\n\n  fn GetValue[self: Self]() -> T {\n    return self.k;\n  }\n\n  var k: T;\n}\n\nclass Declaration(T:! type);\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %pattern_type.893: type = pattern_type %Class [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %ptr.e7d: type = ptr_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.66f: Core.Form = init_form %ptr.e7d [symbolic]\n// CHECK:STDOUT:   %pattern_type.65a: type = pattern_type %ptr.e7d [symbolic]\n// CHECK:STDOUT:   %Class.GetAddr.type: type = fn_type @Class.GetAddr, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %Class.GetAddr: %Class.GetAddr.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Class.GetValue.type: type = fn_type @Class.GetValue, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %Class.GetValue: %Class.GetValue.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %struct_type.k: type = struct_type {.k: %T.binding.as_type} [symbolic]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.k [symbolic]\n// CHECK:STDOUT:   %require_complete.904: <witness> = require_complete_type %Class [symbolic]\n// CHECK:STDOUT:   %require_complete.9dc: <witness> = require_complete_type %ptr.e7d [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %.3a3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.2e7: <witness> = lookup_impl_witness %ptr.e7d, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e7d, (%Copy.lookup_impl_witness.2e7) [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.486: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]\n// CHECK:STDOUT:   %.b63: type = fn_type_with_self_type %Copy.WithSelf.Op.type.486, %Copy.facet [symbolic]\n// CHECK:STDOUT:   %impl.elem0.387: %.b63 = impl_witness_access %Copy.lookup_impl_witness.2e7, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.7f8: <specific function> = specific_impl_function %impl.elem0.387, @Copy.WithSelf.Op(%Copy.facet) [symbolic]\n// CHECK:STDOUT:   %Declaration.type: type = generic_class_type @Declaration [concrete]\n// CHECK:STDOUT:   %Declaration.generic: %Declaration.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_13.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Declaration.decl: %Declaration.type = class_decl @Declaration [concrete = constants.%Declaration.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc17_23.1: type = splice_block %.loc17_23.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc17_23.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc17_19.2: type = symbolic_binding T, 0 [symbolic = %T.loc17_19.1 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc5_13.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.GetAddr.type: type = fn_type @Class.GetAddr, @Class(%T.loc5_13.1) [symbolic = %Class.GetAddr.type (constants.%Class.GetAddr.type)]\n// CHECK:STDOUT:   %Class.GetAddr: @Class.%Class.GetAddr.type (%Class.GetAddr.type) = struct_value () [symbolic = %Class.GetAddr (constants.%Class.GetAddr)]\n// CHECK:STDOUT:   %Class.GetValue.type: type = fn_type @Class.GetValue, @Class(%T.loc5_13.1) [symbolic = %Class.GetValue.type (constants.%Class.GetValue.type)]\n// CHECK:STDOUT:   %Class.GetValue: @Class.%Class.GetValue.type (%Class.GetValue.type) = struct_value () [symbolic = %Class.GetValue (constants.%Class.GetValue)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc5_13.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.loc5_13.1) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem)]\n// CHECK:STDOUT:   %struct_type.k: type = struct_type {.k: @Class.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.k (constants.%struct_type.k)]\n// CHECK:STDOUT:   %complete_type.loc15_1.2: <witness> = complete_type_witness %struct_type.k [symbolic = %complete_type.loc15_1.2 (constants.%complete_type)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Class.GetAddr.decl: @Class.%Class.GetAddr.type (%Class.GetAddr.type) = fn_decl @Class.GetAddr [symbolic = @Class.%Class.GetAddr (constants.%Class.GetAddr)] {\n// CHECK:STDOUT:       %self.patt: @Class.GetAddr.%pattern_type.loc6_18 (%pattern_type.893) = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Class.GetAddr.%pattern_type.loc6_18 (%pattern_type.893) = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @Class.GetAddr.%pattern_type.loc6_32 (%pattern_type.65a) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.GetAddr.%pattern_type.loc6_32 (%pattern_type.65a) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: %Copy.type = name_ref T, @Class.%T.loc5_13.2 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc6_36.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %ptr.loc6_36.2: type = ptr_type %.loc6_36.2 [symbolic = %ptr.loc6_36.1 (constants.%ptr.e7d)]\n// CHECK:STDOUT:       %.loc6_36.3: Core.Form = init_form %ptr.loc6_36.2 [symbolic = %.loc6_36.1 (constants.%.66f)]\n// CHECK:STDOUT:       %self.param: ref @Class.GetAddr.%Class (%Class) = ref_param call_param0\n// CHECK:STDOUT:       %.loc6_24.1: type = splice_block %Self.ref [symbolic = %Class (constants.%Class)] {\n// CHECK:STDOUT:         %.loc6_24.2: type = specific_constant constants.%Class, @Class(constants.%T.035) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc6_24.2 [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: ref @Class.GetAddr.%Class (%Class) = ref_binding self, %self.param\n// CHECK:STDOUT:       %return.param: ref @Class.GetAddr.%ptr.loc6_36.1 (%ptr.e7d) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @Class.GetAddr.%ptr.loc6_36.1 (%ptr.e7d) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Class.GetValue.decl: @Class.%Class.GetValue.type (%Class.GetValue.type) = fn_decl @Class.GetValue [symbolic = @Class.%Class.GetValue (constants.%Class.GetValue)] {\n// CHECK:STDOUT:       %self.patt: @Class.GetValue.%pattern_type.loc10_15 (%pattern_type.893) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Class.GetValue.%pattern_type.loc10_15 (%pattern_type.893) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @Class.GetValue.%pattern_type.loc10_29 (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.GetValue.%pattern_type.loc10_29 (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: %Copy.type = name_ref T, @Class.%T.loc5_13.2 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc10_32.3: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc10_32.4: Core.Form = init_form %.loc10_32.3 [symbolic = %.loc10_32.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:       %self.param: @Class.GetValue.%Class (%Class) = value_param call_param0\n// CHECK:STDOUT:       %.loc10_21.1: type = splice_block %Self.ref [symbolic = %Class (constants.%Class)] {\n// CHECK:STDOUT:         %.loc10_21.2: type = specific_constant constants.%Class, @Class(constants.%T.035) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc10_21.2 [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Class.GetValue.%Class (%Class) = value_binding self, %self.param\n// CHECK:STDOUT:       %return.param: ref @Class.GetValue.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @Class.GetValue.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.ref: %Copy.type = name_ref T, %T.loc5_13.2 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc14_10: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc14_8: @Class.%Class.elem (%Class.elem) = field_decl k, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc15_1.1: <witness> = complete_type_witness constants.%struct_type.k [symbolic = %complete_type.loc15_1.2 (constants.%complete_type)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc15_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .GetAddr = %Class.GetAddr.decl\n// CHECK:STDOUT:     .GetValue = %Class.GetValue.decl\n// CHECK:STDOUT:     .k = %.loc14_8\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Declaration(%T.loc17_19.2: type) {\n// CHECK:STDOUT:   %T.loc17_19.1: type = symbolic_binding T, 0 [symbolic = %T.loc17_19.1 (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.GetAddr(@Class.%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T: %Copy.type = symbolic_binding T, 0 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %pattern_type.loc6_18: type = pattern_type %Class [symbolic = %pattern_type.loc6_18 (constants.%pattern_type.893)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %ptr.loc6_36.1: type = ptr_type %T.binding.as_type [symbolic = %ptr.loc6_36.1 (constants.%ptr.e7d)]\n// CHECK:STDOUT:   %.loc6_36.1: Core.Form = init_form %ptr.loc6_36.1 [symbolic = %.loc6_36.1 (constants.%.66f)]\n// CHECK:STDOUT:   %pattern_type.loc6_32: type = pattern_type %ptr.loc6_36.1 [symbolic = %pattern_type.loc6_32 (constants.%pattern_type.65a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_22: <witness> = require_complete_type %Class [symbolic = %require_complete.loc6_22 (constants.%require_complete.904)]\n// CHECK:STDOUT:   %require_complete.loc6_36: <witness> = require_complete_type %ptr.loc6_36.1 [symbolic = %require_complete.loc6_36 (constants.%require_complete.9dc)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem)]\n// CHECK:STDOUT:   %.loc7_12.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc7_12.1 (constants.%.3a3)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc6_36.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e7)]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc6_36.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.486)]\n// CHECK:STDOUT:   %.loc7_12.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc7_12.2 (constants.%.b63)]\n// CHECK:STDOUT:   %impl.elem0.loc7_12.2: @Class.GetAddr.%.loc7_12.2 (%.b63) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc7_12.2 (constants.%impl.elem0.387)]\n// CHECK:STDOUT:   %specific_impl_fn.loc7_12.2: <specific function> = specific_impl_function %impl.elem0.loc7_12.2, @Copy.WithSelf.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc7_12.2 (constants.%specific_impl_fn.7f8)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: ref @Class.GetAddr.%Class (%Class)) -> out %return.param: @Class.GetAddr.%ptr.loc6_36.1 (%ptr.e7d) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %self.ref: ref @Class.GetAddr.%Class (%Class) = name_ref self, %self\n// CHECK:STDOUT:     %k.ref: @Class.GetAddr.%Class.elem (%Class.elem) = name_ref k, @Class.%.loc14_8 [concrete = @Class.%.loc14_8]\n// CHECK:STDOUT:     %.loc7_17: ref @Class.GetAddr.%T.binding.as_type (%T.binding.as_type) = class_element_access %self.ref, element0\n// CHECK:STDOUT:     %addr: @Class.GetAddr.%ptr.loc6_36.1 (%ptr.e7d) = addr_of %.loc7_17\n// CHECK:STDOUT:     %impl.elem0.loc7_12.1: @Class.GetAddr.%.loc7_12.2 (%.b63) = impl_witness_access constants.%Copy.lookup_impl_witness.2e7, element0 [symbolic = %impl.elem0.loc7_12.2 (constants.%impl.elem0.387)]\n// CHECK:STDOUT:     %bound_method.loc7_12.1: <bound method> = bound_method %addr, %impl.elem0.loc7_12.1\n// CHECK:STDOUT:     %specific_impl_fn.loc7_12.1: <specific function> = specific_impl_function %impl.elem0.loc7_12.1, @Copy.WithSelf.Op(constants.%Copy.facet) [symbolic = %specific_impl_fn.loc7_12.2 (constants.%specific_impl_fn.7f8)]\n// CHECK:STDOUT:     %bound_method.loc7_12.2: <bound method> = bound_method %addr, %specific_impl_fn.loc7_12.1\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Class.GetAddr.%ptr.loc6_36.1 (%ptr.e7d) = call %bound_method.loc7_12.2(%addr)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.GetValue(@Class.%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T: %Copy.type = symbolic_binding T, 0 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %pattern_type.loc10_15: type = pattern_type %Class [symbolic = %pattern_type.loc10_15 (constants.%pattern_type.893)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %.loc10_32.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc10_32.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:   %pattern_type.loc10_29: type = pattern_type %T.binding.as_type [symbolic = %pattern_type.loc10_29 (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc10: <witness> = require_complete_type %Class [symbolic = %require_complete.loc10 (constants.%require_complete.904)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem)]\n// CHECK:STDOUT:   %require_complete.loc11: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc11 (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc11_16.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T [symbolic = %.loc11_16.3 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc11_16.2: @Class.GetValue.%.loc11_16.3 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_16.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc11_16.2: <specific function> = specific_impl_function %impl.elem0.loc11_16.2, @Copy.WithSelf.Op(%T) [symbolic = %specific_impl_fn.loc11_16.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @Class.GetValue.%Class (%Class)) -> out %return.param: @Class.GetValue.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %self.ref: @Class.GetValue.%Class (%Class) = name_ref self, %self\n// CHECK:STDOUT:     %k.ref: @Class.GetValue.%Class.elem (%Class.elem) = name_ref k, @Class.%.loc14_8 [concrete = @Class.%.loc14_8]\n// CHECK:STDOUT:     %.loc11_16.1: ref @Class.GetValue.%T.binding.as_type (%T.binding.as_type) = class_element_access %self.ref, element0\n// CHECK:STDOUT:     %.loc11_16.2: @Class.GetValue.%T.binding.as_type (%T.binding.as_type) = acquire_value %.loc11_16.1\n// CHECK:STDOUT:     %impl.elem0.loc11_16.1: @Class.GetValue.%.loc11_16.3 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc11_16.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc11_16.1: <bound method> = bound_method %.loc11_16.2, %impl.elem0.loc11_16.1\n// CHECK:STDOUT:     %specific_impl_fn.loc11_16.1: <specific function> = specific_impl_function %impl.elem0.loc11_16.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc11_16.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc11_16.2: <bound method> = bound_method %.loc11_16.2, %specific_impl_fn.loc11_16.1\n// CHECK:STDOUT:     %.loc10_32.1: ref @Class.GetValue.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Class.GetValue.%T.binding.as_type (%T.binding.as_type) to %.loc10_32.1 = call %bound_method.loc11_16.2(%.loc11_16.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T.035\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.GetAddr.type => constants.%Class.GetAddr.type\n// CHECK:STDOUT:   %Class.GetAddr => constants.%Class.GetAddr\n// CHECK:STDOUT:   %Class.GetValue.type => constants.%Class.GetValue.type\n// CHECK:STDOUT:   %Class.GetValue => constants.%Class.GetValue\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.67c\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem\n// CHECK:STDOUT:   %struct_type.k => constants.%struct_type.k\n// CHECK:STDOUT:   %complete_type.loc15_1.2 => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.GetAddr(constants.%T.035) {\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %pattern_type.loc6_18 => constants.%pattern_type.893\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %ptr.loc6_36.1 => constants.%ptr.e7d\n// CHECK:STDOUT:   %.loc6_36.1 => constants.%.66f\n// CHECK:STDOUT:   %pattern_type.loc6_32 => constants.%pattern_type.65a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.GetValue(constants.%T.035) {\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %pattern_type.loc10_15 => constants.%pattern_type.893\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %.loc10_32.2 => constants.%.076a48.2\n// CHECK:STDOUT:   %pattern_type.loc10_29 => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Declaration(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc17_19.1 => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/call.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/call.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/call.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class(T:! type, N:! i32) {}\n\nvar a: Class(i32*, 5);\n\n// Requires an implicit conversion to type `type`.\nvar b: Class((), 0);\n\n// --- fail_too_few.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class(T:! type, N:! i32) {}\n\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE+7]]:8: error: 1 argument passed to generic class expecting 2 arguments [CallArgCountMismatch]\n// CHECK:STDERR: var a: Class(i32*);\n// CHECK:STDERR:        ^~~~~~~~~~~\n// CHECK:STDERR: fail_too_few.carbon:[[@LINE-5]]:1: note: calling generic class declared here [InCallToEntity]\n// CHECK:STDERR: class Class(T:! type, N:! i32) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar a: Class(i32*);\n\n// --- fail_too_many.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class(T:! type, N:! i32) {}\n\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE+7]]:8: error: 3 arguments passed to generic class expecting 2 arguments [CallArgCountMismatch]\n// CHECK:STDERR: var a: Class(i32*, 1, 2);\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_too_many.carbon:[[@LINE-5]]:1: note: calling generic class declared here [InCallToEntity]\n// CHECK:STDERR: class Class(T:! type, N:! i32) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar a: Class(i32*, 1, 2);\n\n// --- fail_no_conversion.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class(T:! type, N:! i32) {}\n\n// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+10]]:8: error: cannot implicitly convert non-type value of type `Core.IntLiteral` to `type` [ConversionFailureNonTypeToFacet]\n// CHECK:STDERR: var a: Class(5, i32*);\n// CHECK:STDERR:        ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE+7]]:8: note: type `Core.IntLiteral` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var a: Class(5, i32*);\n// CHECK:STDERR:        ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_no_conversion.carbon:[[@LINE-8]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: class Class(T:! type, N:! i32) {}\n// CHECK:STDERR:             ^\n// CHECK:STDERR:\nvar a: Class(5, i32*);\n\n// --- call_in_nested_return_type.carbon\n\nclass Outer(T:! type) {\n  class Inner(U:! type) {\n    fn A() -> Outer(T) {\n      return {};\n    }\n    fn B() -> Outer(U) {\n      return {};\n    }\n    fn C() -> Inner(T) {\n      return {};\n    }\n    fn D() -> Inner(U) {\n      return {};\n    }\n  }\n}\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.6f3: %i32 = symbolic_binding N, 1 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.e86: type = class_type @Class, @Class(%T, %N.6f3) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %int_5.64b: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.e9d: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_5.0f6: %i32 = int_value 5 [concrete]\n// CHECK:STDOUT:   %Class.ff1: type = class_type @Class, @Class(%ptr.235, %int_5.0f6) [concrete]\n// CHECK:STDOUT:   %pattern_type.d58: type = pattern_type %Class.ff1 [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.77b: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Class.ff1) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.b8a: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Class.ff1) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.090: %T.as.DefaultOrUnformed.impl.Op.type.b8a = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.31a: %DefaultOrUnformed.type = facet_value %Class.ff1, (%DefaultOrUnformed.impl_witness.77b) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.16a: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.090, @T.as.DefaultOrUnformed.impl.Op(%Class.ff1) [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.897: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.d2e: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %Class.7c6: type = class_type @Class, @Class(%empty_tuple.type, %int_0.6a9) [concrete]\n// CHECK:STDOUT:   %pattern_type.a3c: type = pattern_type %Class.7c6 [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.c95: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Class.7c6) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.7ec: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Class.7c6) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.b11: %T.as.DefaultOrUnformed.impl.Op.type.7ec = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.d1f: %DefaultOrUnformed.type = facet_value %Class.7c6, (%DefaultOrUnformed.impl_witness.c95) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.87f: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.b11, @T.as.DefaultOrUnformed.impl.Op(%Class.7c6) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc4_27: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_23.2: %i32 = symbolic_binding N, 1 [symbolic = %N.loc4_23.1 (constants.%N.6f3)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.d58 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.d58 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %Class.ff1 = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_21.1: type = splice_block %Class.loc6 [concrete = constants.%Class.ff1] {\n// CHECK:STDOUT:     %Class.ref.loc6: %Class.type = name_ref Class, %Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr: type = ptr_type %i32 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:     %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:     %impl.elem0.loc6: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc6_21.1: <bound method> = bound_method %int_5, %impl.elem0.loc6 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005]\n// CHECK:STDOUT:     %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_21.2: <bound method> = bound_method %int_5, %specific_fn.loc6 [concrete = constants.%bound_method.e9d]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %i32 = call %bound_method.loc6_21.2(%int_5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:     %.loc6_21.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:     %.loc6_21.3: %i32 = converted %int_5, %.loc6_21.2 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:     %Class.loc6: type = class_type @Class, @Class(constants.%ptr.235, constants.%int_5.0f6) [concrete = constants.%Class.ff1]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %Class.ff1 = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.a3c = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.a3c = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %Class.7c6 = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %.loc9_19.1: type = splice_block %Class.loc9 [concrete = constants.%Class.7c6] {\n// CHECK:STDOUT:     %Class.ref.loc9: %Class.type = name_ref Class, %Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:     %.loc9_15: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:     %.loc9_19.2: type = converted %.loc9_15, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %impl.elem0.loc9: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc9_19.1: <bound method> = bound_method %int_0, %impl.elem0.loc9 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.897]\n// CHECK:STDOUT:     %specific_fn.loc9: <specific function> = specific_function %impl.elem0.loc9, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc9_19.2: <bound method> = bound_method %int_0, %specific_fn.loc9 [concrete = constants.%bound_method.d2e]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9: init %i32 = call %bound_method.loc9_19.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:     %.loc9_19.3: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:     %.loc9_19.4: %i32 = converted %int_0, %.loc9_19.3 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:     %Class.loc9: type = class_type @Class, @Class(constants.%empty_tuple.type, constants.%int_0.6a9) [concrete = constants.%Class.7c6]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %Class.7c6 = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc4_13.2: type, %N.loc4_23.2: %i32) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   %N.loc4_23.1: %i32 = symbolic_binding N, 1 [symbolic = %N.loc4_23.1 (constants.%N.6f3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class.e86\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc6: %DefaultOrUnformed.type = facet_value constants.%Class.ff1, (constants.%DefaultOrUnformed.impl_witness.77b) [concrete = constants.%DefaultOrUnformed.facet.31a]\n// CHECK:STDOUT:   %.loc6_22.1: %DefaultOrUnformed.type = converted constants.%Class.ff1, %DefaultOrUnformed.facet.loc6 [concrete = constants.%DefaultOrUnformed.facet.31a]\n// CHECK:STDOUT:   %as_type.loc6: type = facet_access_type %.loc6_22.1 [concrete = constants.%Class.ff1]\n// CHECK:STDOUT:   %.loc6_22.2: type = converted %.loc6_22.1, %as_type.loc6 [concrete = constants.%Class.ff1]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.1: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.090, @T.as.DefaultOrUnformed.impl.Op(constants.%Class.ff1) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn.16a]\n// CHECK:STDOUT:   %.loc6_1: ref %Class.ff1 = splice_block file.%a.var [concrete = file.%a.var] {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc6: init %Class.ff1 to %.loc6_1 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.1()\n// CHECK:STDOUT:   assign file.%a.var, %T.as.DefaultOrUnformed.impl.Op.call.loc6\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc9: %DefaultOrUnformed.type = facet_value constants.%Class.7c6, (constants.%DefaultOrUnformed.impl_witness.c95) [concrete = constants.%DefaultOrUnformed.facet.d1f]\n// CHECK:STDOUT:   %.loc9_20.1: %DefaultOrUnformed.type = converted constants.%Class.7c6, %DefaultOrUnformed.facet.loc9 [concrete = constants.%DefaultOrUnformed.facet.d1f]\n// CHECK:STDOUT:   %as_type.loc9: type = facet_access_type %.loc9_20.1 [concrete = constants.%Class.7c6]\n// CHECK:STDOUT:   %.loc9_20.2: type = converted %.loc9_20.1, %as_type.loc9 [concrete = constants.%Class.7c6]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.2: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.b11, @T.as.DefaultOrUnformed.impl.Op(constants.%Class.7c6) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn.87f]\n// CHECK:STDOUT:   %.loc9_1: ref %Class.7c6 = splice_block file.%b.var [concrete = file.%b.var] {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc9: init %Class.7c6 to %.loc9_1 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.2()\n// CHECK:STDOUT:   assign file.%b.var, %T.as.DefaultOrUnformed.impl.Op.call.loc9\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T, constants.%N.6f3) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT:   %N.loc4_23.1 => constants.%N.6f3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%ptr.235, constants.%int_5.0f6) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%ptr.235\n// CHECK:STDOUT:   %N.loc4_23.1 => constants.%int_5.0f6\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%empty_tuple.type, constants.%int_0.6a9) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%empty_tuple.type\n// CHECK:STDOUT:   %N.loc4_23.1 => constants.%int_0.6a9\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_too_few.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.6f3: %i32 = symbolic_binding N, 1 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T, %N.6f3) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc4_27: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_23.2: %i32 = symbolic_binding N, 1 [symbolic = %N.loc4_23.1 (constants.%N.6f3)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: <error> = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: <error> = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref <error> = var %a.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.1: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:     %Class.ref: %Class.type = name_ref Class, %Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr: type = ptr_type %i32 [concrete = constants.%ptr]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref <error> = ref_binding a, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc4_13.2: type, %N.loc4_23.2: %i32) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   %N.loc4_23.1: %i32 = symbolic_binding N, 1 [symbolic = %N.loc4_23.1 (constants.%N.6f3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   assign file.%a.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T, constants.%N.6f3) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT:   %N.loc4_23.1 => constants.%N.6f3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_too_many.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.6f3: %i32 = symbolic_binding N, 1 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T, %N.6f3) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc4_27: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_23.2: %i32 = symbolic_binding N, 1 [symbolic = %N.loc4_23.1 (constants.%N.6f3)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: <error> = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: <error> = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref <error> = var %a.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.1: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:     %Class.ref: %Class.type = name_ref Class, %Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr: type = ptr_type %i32 [concrete = constants.%ptr]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref <error> = ref_binding a, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc4_13.2: type, %N.loc4_23.2: %i32) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   %N.loc4_23.1: %i32 = symbolic_binding N, 1 [symbolic = %N.loc4_23.1 (constants.%N.6f3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   assign file.%a.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T, constants.%N.6f3) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT:   %N.loc4_23.1 => constants.%N.6f3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_no_conversion.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.6f3: %i32 = symbolic_binding N, 1 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T, %N.6f3) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc4_27: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_23.2: %i32 = symbolic_binding N, 1 [symbolic = %N.loc4_23.1 (constants.%N.6f3)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: <error> = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: <error> = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref <error> = var %a.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.1: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:     %Class.ref: %Class.type = name_ref Class, %Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:     %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr: type = ptr_type %i32 [concrete = constants.%ptr]\n// CHECK:STDOUT:     %.loc16: type = converted %int_5, <error> [concrete = <error>]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref <error> = ref_binding a, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc4_13.2: type, %N.loc4_23.2: %i32) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   %N.loc4_23.1: %i32 = symbolic_binding N, 1 [symbolic = %N.loc4_23.1 (constants.%N.6f3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   assign file.%a.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T, constants.%N.6f3) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT:   %N.loc4_23.1 => constants.%N.6f3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- call_in_nested_return_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Outer.type: type = generic_class_type @Outer [concrete]\n// CHECK:STDOUT:   %Outer.generic: %Outer.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Outer.387: type = class_type @Outer, @Outer(%T) [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %Inner.type.e0d: type = generic_class_type @Inner, @Outer(%T) [symbolic]\n// CHECK:STDOUT:   %Inner.generic.ada: %Inner.type.e0d = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.e21: type = class_type @Inner, @Inner(%T, %U) [symbolic]\n// CHECK:STDOUT:   %.b11: Core.Form = init_form %Outer.387 [symbolic]\n// CHECK:STDOUT:   %pattern_type.130: type = pattern_type %Outer.387 [symbolic]\n// CHECK:STDOUT:   %Inner.A.type.c2f: type = fn_type @Inner.A, @Inner(%T, %U) [symbolic]\n// CHECK:STDOUT:   %Inner.A.07b: %Inner.A.type.c2f = struct_value () [symbolic]\n// CHECK:STDOUT:   %Outer.d2f: type = class_type @Outer, @Outer(%U) [symbolic]\n// CHECK:STDOUT:   %.a87: Core.Form = init_form %Outer.d2f [symbolic]\n// CHECK:STDOUT:   %pattern_type.760: type = pattern_type %Outer.d2f [symbolic]\n// CHECK:STDOUT:   %Inner.B.type.f42: type = fn_type @Inner.B, @Inner(%T, %U) [symbolic]\n// CHECK:STDOUT:   %Inner.B.b14: %Inner.B.type.f42 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.ddc: type = class_type @Inner, @Inner(%T, %T) [symbolic]\n// CHECK:STDOUT:   %.fdd: Core.Form = init_form %Inner.ddc [symbolic]\n// CHECK:STDOUT:   %pattern_type.81e: type = pattern_type %Inner.ddc [symbolic]\n// CHECK:STDOUT:   %Inner.C.type.912: type = fn_type @Inner.C, @Inner(%T, %U) [symbolic]\n// CHECK:STDOUT:   %Inner.C.125: %Inner.C.type.912 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.223: Core.Form = init_form %Inner.e21 [symbolic]\n// CHECK:STDOUT:   %pattern_type.0d1: type = pattern_type %Inner.e21 [symbolic]\n// CHECK:STDOUT:   %Inner.D.type.cd0: type = fn_type @Inner.D, @Inner(%T, %U) [symbolic]\n// CHECK:STDOUT:   %Inner.D.147: %Inner.D.type.cd0 = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete.448: <witness> = require_complete_type %Outer.387 [symbolic]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Outer.val.ca1: %Outer.387 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.type.26a: type = generic_class_type @Inner, @Outer(%U) [symbolic]\n// CHECK:STDOUT:   %Inner.generic.ddc: %Inner.type.26a = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.ade: <witness> = require_complete_type %Outer.d2f [symbolic]\n// CHECK:STDOUT:   %Outer.val.756: %Outer.d2f = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.A.type.e74: type = fn_type @Inner.A, @Inner(%T, %T) [symbolic]\n// CHECK:STDOUT:   %Inner.A.d94: %Inner.A.type.e74 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.B.type.539: type = fn_type @Inner.B, @Inner(%T, %T) [symbolic]\n// CHECK:STDOUT:   %Inner.B.455: %Inner.B.type.539 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.C.type.4b3: type = fn_type @Inner.C, @Inner(%T, %T) [symbolic]\n// CHECK:STDOUT:   %Inner.C.f04: %Inner.C.type.4b3 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.D.type.d17: type = fn_type @Inner.D, @Inner(%T, %T) [symbolic]\n// CHECK:STDOUT:   %Inner.D.c1c: %Inner.D.type.d17 = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.de9: <witness> = require_complete_type %Inner.ddc [symbolic]\n// CHECK:STDOUT:   %Inner.val.240: %Inner.ddc = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.41c: <witness> = require_complete_type %Inner.e21 [symbolic]\n// CHECK:STDOUT:   %Inner.val.43a: %Inner.e21 = struct_value () [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Outer = %Outer.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Outer.decl: %Outer.type = class_decl @Outer [concrete = constants.%Outer.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc2_17.1: type = splice_block %.loc2_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc2_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc2_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc2_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Outer(%T.loc2_13.2: type) {\n// CHECK:STDOUT:   %T.loc2_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc2_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type: type = generic_class_type @Inner, @Outer(%T.loc2_13.1) [symbolic = %Inner.type (constants.%Inner.type.e0d)]\n// CHECK:STDOUT:   %Inner.generic: @Outer.%Inner.type (%Inner.type.e0d) = struct_value () [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Inner.decl: @Outer.%Inner.type (%Inner.type.e0d) = class_decl @Inner [symbolic = @Outer.%Inner.generic (constants.%Inner.generic.ada)] {\n// CHECK:STDOUT:       %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc3_19.1: type = splice_block %.loc3_19.2 [concrete = type] {\n// CHECK:STDOUT:         %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:         %.loc3_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %U.loc3_15.2: type = symbolic_binding U, 1 [symbolic = %U.loc3_15.1 (constants.%U)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Outer.387\n// CHECK:STDOUT:     .Inner = %Inner.decl\n// CHECK:STDOUT:     .Outer = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Inner(@Outer.%T.loc2_13.2: type, %U.loc3_15.2: type) {\n// CHECK:STDOUT:   %U.loc3_15.1: type = symbolic_binding U, 1 [symbolic = %U.loc3_15.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Inner.A.type: type = fn_type @Inner.A, @Inner(%T, %U.loc3_15.1) [symbolic = %Inner.A.type (constants.%Inner.A.type.c2f)]\n// CHECK:STDOUT:   %Inner.A: @Inner.%Inner.A.type (%Inner.A.type.c2f) = struct_value () [symbolic = %Inner.A (constants.%Inner.A.07b)]\n// CHECK:STDOUT:   %Inner.B.type: type = fn_type @Inner.B, @Inner(%T, %U.loc3_15.1) [symbolic = %Inner.B.type (constants.%Inner.B.type.f42)]\n// CHECK:STDOUT:   %Inner.B: @Inner.%Inner.B.type (%Inner.B.type.f42) = struct_value () [symbolic = %Inner.B (constants.%Inner.B.b14)]\n// CHECK:STDOUT:   %Inner.C.type: type = fn_type @Inner.C, @Inner(%T, %U.loc3_15.1) [symbolic = %Inner.C.type (constants.%Inner.C.type.912)]\n// CHECK:STDOUT:   %Inner.C: @Inner.%Inner.C.type (%Inner.C.type.912) = struct_value () [symbolic = %Inner.C (constants.%Inner.C.125)]\n// CHECK:STDOUT:   %Inner.D.type: type = fn_type @Inner.D, @Inner(%T, %U.loc3_15.1) [symbolic = %Inner.D.type (constants.%Inner.D.type.cd0)]\n// CHECK:STDOUT:   %Inner.D: @Inner.%Inner.D.type (%Inner.D.type.cd0) = struct_value () [symbolic = %Inner.D (constants.%Inner.D.147)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Inner.A.decl: @Inner.%Inner.A.type (%Inner.A.type.c2f) = fn_decl @Inner.A [symbolic = @Inner.%Inner.A (constants.%Inner.A.07b)] {\n// CHECK:STDOUT:       %return.patt: @Inner.A.%pattern_type (%pattern_type.130) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Inner.A.%pattern_type (%pattern_type.130) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Outer.ref: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Outer.%T.loc2_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %Outer.loc4_22.2: type = class_type @Outer, @Outer(constants.%T) [symbolic = %Outer.loc4_22.1 (constants.%Outer.387)]\n// CHECK:STDOUT:       %.loc4_22.2: Core.Form = init_form %Outer.loc4_22.2 [symbolic = %.loc4_22.1 (constants.%.b11)]\n// CHECK:STDOUT:       %return.param: ref @Inner.A.%Outer.loc4_22.1 (%Outer.387) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @Inner.A.%Outer.loc4_22.1 (%Outer.387) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Inner.B.decl: @Inner.%Inner.B.type (%Inner.B.type.f42) = fn_decl @Inner.B [symbolic = @Inner.%Inner.B (constants.%Inner.B.b14)] {\n// CHECK:STDOUT:       %return.patt: @Inner.B.%pattern_type (%pattern_type.760) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Inner.B.%pattern_type (%pattern_type.760) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Outer.ref: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:       %U.ref: type = name_ref U, @Inner.%U.loc3_15.2 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:       %Outer.loc7_22.2: type = class_type @Outer, @Outer(constants.%U) [symbolic = %Outer.loc7_22.1 (constants.%Outer.d2f)]\n// CHECK:STDOUT:       %.loc7_22.2: Core.Form = init_form %Outer.loc7_22.2 [symbolic = %.loc7_22.1 (constants.%.a87)]\n// CHECK:STDOUT:       %return.param: ref @Inner.B.%Outer.loc7_22.1 (%Outer.d2f) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @Inner.B.%Outer.loc7_22.1 (%Outer.d2f) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Inner.C.decl: @Inner.%Inner.C.type (%Inner.C.type.912) = fn_decl @Inner.C [symbolic = @Inner.%Inner.C (constants.%Inner.C.125)] {\n// CHECK:STDOUT:       %return.patt: @Inner.C.%pattern_type (%pattern_type.81e) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Inner.C.%pattern_type (%pattern_type.81e) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc10_15: @Inner.C.%Inner.type (%Inner.type.e0d) = specific_constant @Outer.%Inner.decl, @Outer(constants.%T) [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:       %Inner.ref: @Inner.C.%Inner.type (%Inner.type.e0d) = name_ref Inner, %.loc10_15 [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Outer.%T.loc2_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %Inner.loc10_22.2: type = class_type @Inner, @Inner(constants.%T, constants.%T) [symbolic = %Inner.loc10_22.1 (constants.%Inner.ddc)]\n// CHECK:STDOUT:       %.loc10_22.2: Core.Form = init_form %Inner.loc10_22.2 [symbolic = %.loc10_22.1 (constants.%.fdd)]\n// CHECK:STDOUT:       %return.param: ref @Inner.C.%Inner.loc10_22.1 (%Inner.ddc) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @Inner.C.%Inner.loc10_22.1 (%Inner.ddc) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Inner.D.decl: @Inner.%Inner.D.type (%Inner.D.type.cd0) = fn_decl @Inner.D [symbolic = @Inner.%Inner.D (constants.%Inner.D.147)] {\n// CHECK:STDOUT:       %return.patt: @Inner.D.%pattern_type (%pattern_type.0d1) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Inner.D.%pattern_type (%pattern_type.0d1) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc13_15: @Inner.D.%Inner.type (%Inner.type.e0d) = specific_constant @Outer.%Inner.decl, @Outer(constants.%T) [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:       %Inner.ref: @Inner.D.%Inner.type (%Inner.type.e0d) = name_ref Inner, %.loc13_15 [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:       %U.ref: type = name_ref U, @Inner.%U.loc3_15.2 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:       %Inner.loc13_22.2: type = class_type @Inner, @Inner(constants.%T, constants.%U) [symbolic = %Inner.loc13_22.1 (constants.%Inner.e21)]\n// CHECK:STDOUT:       %.loc13_22.2: Core.Form = init_form %Inner.loc13_22.2 [symbolic = %.loc13_22.1 (constants.%.223)]\n// CHECK:STDOUT:       %return.param: ref @Inner.D.%Inner.loc13_22.1 (%Inner.e21) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @Inner.D.%Inner.loc13_22.1 (%Inner.e21) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Inner.e21\n// CHECK:STDOUT:     .Outer = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .A = %Inner.A.decl\n// CHECK:STDOUT:     .U = <poisoned>\n// CHECK:STDOUT:     .B = %Inner.B.decl\n// CHECK:STDOUT:     .Inner = <poisoned>\n// CHECK:STDOUT:     .C = %Inner.C.decl\n// CHECK:STDOUT:     .D = %Inner.D.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Inner.A(@Outer.%T.loc2_13.2: type, @Inner.%U.loc3_15.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Outer.loc4_22.1: type = class_type @Outer, @Outer(%T) [symbolic = %Outer.loc4_22.1 (constants.%Outer.387)]\n// CHECK:STDOUT:   %.loc4_22.1: Core.Form = init_form %Outer.loc4_22.1 [symbolic = %.loc4_22.1 (constants.%.b11)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Outer.loc4_22.1 [symbolic = %pattern_type (constants.%pattern_type.130)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Outer.loc4_22.1 [symbolic = %require_complete (constants.%require_complete.448)]\n// CHECK:STDOUT:   %Outer.val: @Inner.A.%Outer.loc4_22.1 (%Outer.387) = struct_value () [symbolic = %Outer.val (constants.%Outer.val.ca1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Inner.A.%Outer.loc4_22.1 (%Outer.387) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc5_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc5_15.2: init @Inner.A.%Outer.loc4_22.1 (%Outer.387) to %return.param = class_init () [symbolic = %Outer.val (constants.%Outer.val.ca1)]\n// CHECK:STDOUT:     %.loc5_16: init @Inner.A.%Outer.loc4_22.1 (%Outer.387) = converted %.loc5_15.1, %.loc5_15.2 [symbolic = %Outer.val (constants.%Outer.val.ca1)]\n// CHECK:STDOUT:     return %.loc5_16 to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Inner.B(@Outer.%T.loc2_13.2: type, @Inner.%U.loc3_15.2: type) {\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:   %Outer.loc7_22.1: type = class_type @Outer, @Outer(%U) [symbolic = %Outer.loc7_22.1 (constants.%Outer.d2f)]\n// CHECK:STDOUT:   %.loc7_22.1: Core.Form = init_form %Outer.loc7_22.1 [symbolic = %.loc7_22.1 (constants.%.a87)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Outer.loc7_22.1 [symbolic = %pattern_type (constants.%pattern_type.760)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Outer.loc7_22.1 [symbolic = %require_complete (constants.%require_complete.ade)]\n// CHECK:STDOUT:   %Outer.val: @Inner.B.%Outer.loc7_22.1 (%Outer.d2f) = struct_value () [symbolic = %Outer.val (constants.%Outer.val.756)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Inner.B.%Outer.loc7_22.1 (%Outer.d2f) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc8_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc8_15.2: init @Inner.B.%Outer.loc7_22.1 (%Outer.d2f) to %return.param = class_init () [symbolic = %Outer.val (constants.%Outer.val.756)]\n// CHECK:STDOUT:     %.loc8_16: init @Inner.B.%Outer.loc7_22.1 (%Outer.d2f) = converted %.loc8_15.1, %.loc8_15.2 [symbolic = %Outer.val (constants.%Outer.val.756)]\n// CHECK:STDOUT:     return %.loc8_16 to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Inner.C(@Outer.%T.loc2_13.2: type, @Inner.%U.loc3_15.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Inner.type: type = generic_class_type @Inner, @Outer(%T) [symbolic = %Inner.type (constants.%Inner.type.e0d)]\n// CHECK:STDOUT:   %Inner.generic: @Inner.C.%Inner.type (%Inner.type.e0d) = struct_value () [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:   %Inner.loc10_22.1: type = class_type @Inner, @Inner(%T, %T) [symbolic = %Inner.loc10_22.1 (constants.%Inner.ddc)]\n// CHECK:STDOUT:   %.loc10_22.1: Core.Form = init_form %Inner.loc10_22.1 [symbolic = %.loc10_22.1 (constants.%.fdd)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Inner.loc10_22.1 [symbolic = %pattern_type (constants.%pattern_type.81e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Inner.loc10_22.1 [symbolic = %require_complete (constants.%require_complete.de9)]\n// CHECK:STDOUT:   %Inner.val: @Inner.C.%Inner.loc10_22.1 (%Inner.ddc) = struct_value () [symbolic = %Inner.val (constants.%Inner.val.240)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Inner.C.%Inner.loc10_22.1 (%Inner.ddc) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc11_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc11_15.2: init @Inner.C.%Inner.loc10_22.1 (%Inner.ddc) to %return.param = class_init () [symbolic = %Inner.val (constants.%Inner.val.240)]\n// CHECK:STDOUT:     %.loc11_16: init @Inner.C.%Inner.loc10_22.1 (%Inner.ddc) = converted %.loc11_15.1, %.loc11_15.2 [symbolic = %Inner.val (constants.%Inner.val.240)]\n// CHECK:STDOUT:     return %.loc11_16 to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Inner.D(@Outer.%T.loc2_13.2: type, @Inner.%U.loc3_15.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Inner.type: type = generic_class_type @Inner, @Outer(%T) [symbolic = %Inner.type (constants.%Inner.type.e0d)]\n// CHECK:STDOUT:   %Inner.generic: @Inner.D.%Inner.type (%Inner.type.e0d) = struct_value () [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:   %Inner.loc13_22.1: type = class_type @Inner, @Inner(%T, %U) [symbolic = %Inner.loc13_22.1 (constants.%Inner.e21)]\n// CHECK:STDOUT:   %.loc13_22.1: Core.Form = init_form %Inner.loc13_22.1 [symbolic = %.loc13_22.1 (constants.%.223)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Inner.loc13_22.1 [symbolic = %pattern_type (constants.%pattern_type.0d1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Inner.loc13_22.1 [symbolic = %require_complete (constants.%require_complete.41c)]\n// CHECK:STDOUT:   %Inner.val: @Inner.D.%Inner.loc13_22.1 (%Inner.e21) = struct_value () [symbolic = %Inner.val (constants.%Inner.val.43a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Inner.D.%Inner.loc13_22.1 (%Inner.e21) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc14_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc14_15.2: init @Inner.D.%Inner.loc13_22.1 (%Inner.e21) to %return.param = class_init () [symbolic = %Inner.val (constants.%Inner.val.43a)]\n// CHECK:STDOUT:     %.loc14_16: init @Inner.D.%Inner.loc13_22.1 (%Inner.e21) = converted %.loc14_15.1, %.loc14_15.2 [symbolic = %Inner.val (constants.%Inner.val.43a)]\n// CHECK:STDOUT:     return %.loc14_16 to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%T) {\n// CHECK:STDOUT:   %T.loc2_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.e0d\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.ada\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %U.loc3_15.1 => constants.%U\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.A.type => constants.%Inner.A.type.c2f\n// CHECK:STDOUT:   %Inner.A => constants.%Inner.A.07b\n// CHECK:STDOUT:   %Inner.B.type => constants.%Inner.B.type.f42\n// CHECK:STDOUT:   %Inner.B => constants.%Inner.B.b14\n// CHECK:STDOUT:   %Inner.C.type => constants.%Inner.C.type.912\n// CHECK:STDOUT:   %Inner.C => constants.%Inner.C.125\n// CHECK:STDOUT:   %Inner.D.type => constants.%Inner.D.type.cd0\n// CHECK:STDOUT:   %Inner.D => constants.%Inner.D.147\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.A(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Outer.loc4_22.1 => constants.%Outer.387\n// CHECK:STDOUT:   %.loc4_22.1 => constants.%.b11\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.130\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%U) {\n// CHECK:STDOUT:   %T.loc2_13.1 => constants.%U\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.26a\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.ddc\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.B(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %U => constants.%U\n// CHECK:STDOUT:   %Outer.loc7_22.1 => constants.%Outer.d2f\n// CHECK:STDOUT:   %.loc7_22.1 => constants.%.a87\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.760\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%T, constants.%T) {\n// CHECK:STDOUT:   %U.loc3_15.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.A.type => constants.%Inner.A.type.e74\n// CHECK:STDOUT:   %Inner.A => constants.%Inner.A.d94\n// CHECK:STDOUT:   %Inner.B.type => constants.%Inner.B.type.539\n// CHECK:STDOUT:   %Inner.B => constants.%Inner.B.455\n// CHECK:STDOUT:   %Inner.C.type => constants.%Inner.C.type.4b3\n// CHECK:STDOUT:   %Inner.C => constants.%Inner.C.f04\n// CHECK:STDOUT:   %Inner.D.type => constants.%Inner.D.type.d17\n// CHECK:STDOUT:   %Inner.D => constants.%Inner.D.c1c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.C(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.e0d\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.ada\n// CHECK:STDOUT:   %Inner.loc10_22.1 => constants.%Inner.ddc\n// CHECK:STDOUT:   %.loc10_22.1 => constants.%.fdd\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.81e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.D(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.e0d\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.ada\n// CHECK:STDOUT:   %U => constants.%U\n// CHECK:STDOUT:   %Inner.loc13_22.1 => constants.%Inner.e21\n// CHECK:STDOUT:   %.loc13_22.1 => constants.%.223\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.0d1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/complete_in_conversion.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/complete_in_conversion.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/complete_in_conversion.carbon\n\n// --- fail_derived_to_base.carbon\n\nfn Int(N: Core.IntLiteral()) -> type = \"int.make_type_signed\";\n\nbase class B {}\n\nclass A(N:! i32) {\n  extend base: B;\n\n  var n: Int(N);\n}\n\nfn F(a: A(0)*) {\n  // CHECK:STDERR: fail_derived_to_base.carbon:[[@LINE+7]]:22: error: unable to monomorphize specific `A(0)` [ResolvingSpecificHere]\n  // CHECK:STDERR:   let unused b: B* = a;\n  // CHECK:STDERR:                      ^\n  // CHECK:STDERR: fail_derived_to_base.carbon:[[@LINE-7]]:10: note: integer type width of 0 is not positive [IntWidthNotPositive]\n  // CHECK:STDERR:   var n: Int(N);\n  // CHECK:STDERR:          ^~~~~~\n  // CHECK:STDERR:\n  let unused b: B* = a;\n}\n\n// CHECK:STDOUT: --- fail_derived_to_base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %.805: Core.Form = init_form type [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %Int.type.b3e: type = fn_type @Int.loc2 [concrete]\n// CHECK:STDOUT:   %Int.d6d: %Int.type.b3e = struct_value () [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type.878: type = generic_class_type @Int.1 [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type.878 = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int.1, @Int.1(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.5de: %i32 = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %A.type: type = generic_class_type @A [concrete]\n// CHECK:STDOUT:   %A.generic: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.54d: type = class_type @A, @A(%N.5de) [symbolic]\n// CHECK:STDOUT:   %A.elem.ade: type = unbound_element_type %A.54d, %B [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %From: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.2ed: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%From) [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.d29: %Int.as.ImplicitAs.impl.Convert.type.2ed = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.640: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.ea2, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.240: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.dd4: %Int.as.ImplicitAs.impl.Convert.type.240 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.290: %ImplicitAs.type.139 = facet_value %i32, (%ImplicitAs.impl_witness.640) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.462: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet.290) [concrete]\n// CHECK:STDOUT:   %.0a7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.462, %ImplicitAs.facet.290 [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound.d32: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.dd4 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Int.as.ImplicitAs.impl.Convert.dd4, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.d76: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method.d76(%N.5de) [symbolic]\n// CHECK:STDOUT:   %iN.builtin.f1b: type = int_type signed, %Int.as.ImplicitAs.impl.Convert.call [symbolic]\n// CHECK:STDOUT:   %require_complete.c9d: <witness> = require_complete_type %iN.builtin.f1b [symbolic]\n// CHECK:STDOUT:   %A.elem.a53: type = unbound_element_type %A.54d, %iN.builtin.f1b [symbolic]\n// CHECK:STDOUT:   %struct_type.base.n: type = struct_type {.base: %B, .n: %iN.builtin.f1b} [symbolic]\n// CHECK:STDOUT:   %complete_type.8c7: <witness> = complete_type_witness %struct_type.base.n [symbolic]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.b94: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet.b94) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet.b94 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.d2e: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %A.dc6: type = class_type @A, @A(%int_0.6a9) [concrete]\n// CHECK:STDOUT:   %ptr.0e2: type = ptr_type %A.dc6 [concrete]\n// CHECK:STDOUT:   %pattern_type.f32: type = pattern_type %ptr.0e2 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.27c: type = ptr_type %B [concrete]\n// CHECK:STDOUT:   %pattern_type.191: type = pattern_type %ptr.27c [concrete]\n// CHECK:STDOUT:   %A.elem.665: type = unbound_element_type %A.dc6, %B [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound.564: <bound method> = bound_method %int_0.6a9, %Int.as.ImplicitAs.impl.Convert.dd4 [concrete]\n// CHECK:STDOUT:   %bound_method.77d: <bound method> = bound_method %int_0.6a9, %Int.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Int: %Int.type.878 = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.0bc: @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert.type (%Int.as.ImplicitAs.impl.Convert.type.2ed) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert (constants.%Int.as.ImplicitAs.impl.Convert.d29)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.ea2 = impl_witness_table (%Core.import_ref.0bc), @Int.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Int = %Int.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Int.decl: %Int.type.b3e = fn_decl @Int.loc2 [concrete = constants.%Int.d6d] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = value_binding_pattern N [concrete]\n// CHECK:STDOUT:     %N.param_patt: %pattern_type.dc0 = value_param_pattern %N.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.98f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.98f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc2_33.1: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc2_33.2: Core.Form = init_form %.loc2_33.1 [concrete = constants.%.805]\n// CHECK:STDOUT:     %N.param: Core.IntLiteral = value_param call_param0\n// CHECK:STDOUT:     %.loc2_27.1: type = splice_block %.loc2_27.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc2_27.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc2_27.3: type = converted %IntLiteral.call, %.loc2_27.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N: Core.IntLiteral = value_binding N, %N.param\n// CHECK:STDOUT:     %return.param: ref type = out_param call_param1\n// CHECK:STDOUT:     %return: ref type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %A.decl: %A.type = class_decl @A [concrete = constants.%A.generic] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc6_9.2: %i32 = symbolic_binding N, 0 [symbolic = %N.loc6_9.1 (constants.%N.5de)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.f32 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.f32 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %ptr.0e2 = value_param call_param0\n// CHECK:STDOUT:     %.loc12_13: type = splice_block %ptr.loc12 [concrete = constants.%ptr.0e2] {\n// CHECK:STDOUT:       %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A.generic]\n// CHECK:STDOUT:       %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:       %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:       %bound_method.loc12_12.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:       %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc12_12.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method.d2e]\n// CHECK:STDOUT:       %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc12_12.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:       %.loc12_12.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:       %.loc12_12.2: %i32 = converted %int_0, %.loc12_12.1 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:       %A: type = class_type @A, @A(constants.%int_0.6a9) [concrete = constants.%A.dc6]\n// CHECK:STDOUT:       %ptr.loc12: type = ptr_type %A [concrete = constants.%ptr.0e2]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %ptr.0e2 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .Int = <poisoned>\n// CHECK:STDOUT:   .N = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @A(%N.loc6_9.2: %i32) {\n// CHECK:STDOUT:   %N.loc6_9.1: %i32 = symbolic_binding N, 0 [symbolic = %N.loc6_9.1 (constants.%N.5de)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %A: type = class_type @A, @A(%N.loc6_9.1) [symbolic = %A (constants.%A.54d)]\n// CHECK:STDOUT:   %A.elem.loc7: type = unbound_element_type %A, constants.%B [symbolic = %A.elem.loc7 (constants.%A.elem.ade)]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.loc6_9.1, constants.%Int.as.ImplicitAs.impl.Convert.dd4 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound.d32)]\n// CHECK:STDOUT:   %bound_method.loc9_14.3: <bound method> = bound_method %N.loc6_9.1, constants.%Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic = %bound_method.loc9_14.3 (constants.%bound_method.d76)]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call.loc9_14.2: init Core.IntLiteral = call %bound_method.loc9_14.3(%N.loc6_9.1) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc9_14.2 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:   %iN.builtin: type = int_type signed, %Int.as.ImplicitAs.impl.Convert.call.loc9_14.2 [symbolic = %iN.builtin (constants.%iN.builtin.f1b)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %iN.builtin [symbolic = %require_complete (constants.%require_complete.c9d)]\n// CHECK:STDOUT:   %A.elem.loc9: type = unbound_element_type %A, %iN.builtin [symbolic = %A.elem.loc9 (constants.%A.elem.a53)]\n// CHECK:STDOUT:   %struct_type.base.n: type = struct_type {.base: %B, .n: @A.%iN.builtin (%iN.builtin.f1b)} [symbolic = %struct_type.base.n (constants.%struct_type.base.n)]\n// CHECK:STDOUT:   %complete_type.loc10_1.2: <witness> = complete_type_witness %struct_type.base.n [symbolic = %complete_type.loc10_1.2 (constants.%complete_type.8c7)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:     %.loc7: @A.%A.elem.loc7 (%A.elem.ade) = base_decl %B.ref, element0 [concrete]\n// CHECK:STDOUT:     %Int.ref: %Int.type.b3e = name_ref Int, file.%Int.decl [concrete = constants.%Int.d6d]\n// CHECK:STDOUT:     %N.ref: %i32 = name_ref N, %N.loc6_9.2 [symbolic = %N.loc6_9.1 (constants.%N.5de)]\n// CHECK:STDOUT:     %impl.elem0: %.0a7 = impl_witness_access constants.%ImplicitAs.impl_witness.640, element0 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.dd4]\n// CHECK:STDOUT:     %bound_method.loc9_14.1: <bound method> = bound_method %N.ref, %impl.elem0 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound.d32)]\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Int.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc9_14.2: <bound method> = bound_method %N.ref, %specific_fn [symbolic = %bound_method.loc9_14.3 (constants.%bound_method.d76)]\n// CHECK:STDOUT:     %Int.as.ImplicitAs.impl.Convert.call.loc9_14.1: init Core.IntLiteral = call %bound_method.loc9_14.2(%N.ref) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc9_14.2 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     %.loc9_14.1: Core.IntLiteral = value_of_initializer %Int.as.ImplicitAs.impl.Convert.call.loc9_14.1 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc9_14.2 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     %.loc9_14.2: Core.IntLiteral = converted %N.ref, %.loc9_14.1 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc9_14.2 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     %Int.call: init type = call %Int.ref(%.loc9_14.2) [symbolic = %iN.builtin (constants.%iN.builtin.f1b)]\n// CHECK:STDOUT:     %.loc9_15.1: type = value_of_initializer %Int.call [symbolic = %iN.builtin (constants.%iN.builtin.f1b)]\n// CHECK:STDOUT:     %.loc9_15.2: type = converted %Int.call, %.loc9_15.1 [symbolic = %iN.builtin (constants.%iN.builtin.f1b)]\n// CHECK:STDOUT:     %.loc9_8: @A.%A.elem.loc9 (%A.elem.a53) = field_decl n, element1 [concrete]\n// CHECK:STDOUT:     %complete_type.loc10_1.1: <witness> = complete_type_witness constants.%struct_type.base.n [symbolic = %complete_type.loc10_1.2 (constants.%complete_type.8c7)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc10_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%A.54d\n// CHECK:STDOUT:     .B = <poisoned>\n// CHECK:STDOUT:     .base = %.loc7\n// CHECK:STDOUT:     .Int = <poisoned>\n// CHECK:STDOUT:     .N = <poisoned>\n// CHECK:STDOUT:     .n = %.loc9_8\n// CHECK:STDOUT:     extend %B.ref\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Int.loc2(%N.param: Core.IntLiteral) -> out %return.param: type = \"int.make_type_signed\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %ptr.0e2) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.191 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.ref: %ptr.0e2 = name_ref a, %a\n// CHECK:STDOUT:   %.loc20_18: type = splice_block %ptr.loc20 [concrete = constants.%ptr.27c] {\n// CHECK:STDOUT:     %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:     %ptr.loc20: type = ptr_type %B.ref [concrete = constants.%ptr.27c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc20_22.1: ref %A.dc6 = deref %a.ref\n// CHECK:STDOUT:   %.loc20_22.2: ref %B = class_element_access %.loc20_22.1, element0\n// CHECK:STDOUT:   %addr: %ptr.27c = addr_of %.loc20_22.2\n// CHECK:STDOUT:   %.loc20_22.3: %ptr.27c = converted %a.ref, %addr\n// CHECK:STDOUT:   %b: %ptr.27c = value_binding b, %.loc20_22.3\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%N.5de) {\n// CHECK:STDOUT:   %N.loc6_9.1 => constants.%N.5de\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%int_0.6a9) {\n// CHECK:STDOUT:   %N.loc6_9.1 => constants.%int_0.6a9\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %A => constants.%A.dc6\n// CHECK:STDOUT:   %A.elem.loc7 => constants.%A.elem.665\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound => constants.%Int.as.ImplicitAs.impl.Convert.bound.564\n// CHECK:STDOUT:   %bound_method.loc9_14.3 => constants.%bound_method.77d\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call.loc9_14.2 => constants.%int_0.5c6\n// CHECK:STDOUT:   %iN.builtin => <error>\n// CHECK:STDOUT:   %require_complete => <error>\n// CHECK:STDOUT:   %A.elem.loc9 => <error>\n// CHECK:STDOUT:   %struct_type.base.n => <error>\n// CHECK:STDOUT:   %complete_type.loc10_1.2 => <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/empty_params.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/empty_params.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/empty_params.carbon\n\nclass C[]();\n\n// CHECK:STDOUT: --- empty_params.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/field.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/field.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/field.carbon\n\n// --- field.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nclass Class(T:! type) {\n  var x: T;\n}\n\nfn F(c: Class(i32)) -> i32 {\n  return c.x;\n}\n\nfn G(T:! Core.Copy, c: Class(T)) -> T {\n  return c.x;\n}\n\nfn H(U:! Core.Copy, c: Class(U)) -> U {\n  return c.x;\n}\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- field.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.0db: type = class_type @Class, @Class(%T.67d) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67d [symbolic]\n// CHECK:STDOUT:   %Class.elem.fdf: type = unbound_element_type %Class.0db, %T.67d [symbolic]\n// CHECK:STDOUT:   %struct_type.x.0c5: type = struct_type {.x: %T.67d} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x.0c5 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Class.805: type = class_type @Class, @Class(%i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.1c2: type = pattern_type %Class.805 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %Class.elem.927: type = unbound_element_type %Class.805, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x.ed6: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x.ed6 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58dce0.1: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023143.1: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594c59.1: %.023143.1 = impl_witness_access %Copy.lookup_impl_witness.58dce0.1, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdce5c.1: <specific function> = specific_impl_function %impl.elem0.594c59.1, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %require_complete.67ca8d.1: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Class.3168aa.1: type = class_type @Class, @Class(%T.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %pattern_type.c542f5.1: type = pattern_type %Class.3168aa.1 [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.elem.7657d6.1: type = unbound_element_type %Class.3168aa.1, %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %struct_type.x.8dcd6b.1: type = struct_type {.x: %T.binding.as_type} [symbolic]\n// CHECK:STDOUT:   %complete_type.e78b36.1: <witness> = complete_type_witness %struct_type.x.8dcd6b.1 [symbolic]\n// CHECK:STDOUT:   %require_complete.ae7bfa.1: <witness> = require_complete_type %Class.3168aa.1 [symbolic]\n// CHECK:STDOUT:   %U.035: %Copy.type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %U.binding.as_type.14b: type = symbolic_binding_type U, 0, %U.035 [symbolic]\n// CHECK:STDOUT:   %Class.3168aa.2: type = class_type @Class, @Class(%U.binding.as_type.14b) [symbolic]\n// CHECK:STDOUT:   %pattern_type.c542f5.2: type = pattern_type %Class.3168aa.2 [symbolic]\n// CHECK:STDOUT:   %.076a48.3: Core.Form = init_form %U.binding.as_type.14b [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.3: type = pattern_type %U.binding.as_type.14b [symbolic]\n// CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]\n// CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.67ca8d.2: <witness> = require_complete_type %U.binding.as_type.14b [symbolic]\n// CHECK:STDOUT:   %Class.elem.7657d6.2: type = unbound_element_type %Class.3168aa.2, %U.binding.as_type.14b [symbolic]\n// CHECK:STDOUT:   %struct_type.x.8dcd6b.2: type = struct_type {.x: %U.binding.as_type.14b} [symbolic]\n// CHECK:STDOUT:   %complete_type.e78b36.2: <witness> = complete_type_witness %struct_type.x.8dcd6b.2 [symbolic]\n// CHECK:STDOUT:   %require_complete.ae7bfa.2: <witness> = require_complete_type %Class.3168aa.2 [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58dce0.2: <witness> = lookup_impl_witness %U.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.3: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%U.035) [symbolic]\n// CHECK:STDOUT:   %.023143.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.3, %U.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594c59.2: %.023143.2 = impl_witness_access %Copy.lookup_impl_witness.58dce0.2, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdce5c.2: <specific function> = specific_impl_function %impl.elem0.594c59.2, @Copy.WithSelf.Op(%U.035) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_17.1: type = splice_block %.loc5_17.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc5_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.1c2 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.1c2 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc9_24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc9_24: Core.Form = init_form %i32.loc9_24 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %c.param: %Class.805 = value_param call_param0\n// CHECK:STDOUT:     %.loc9_18: type = splice_block %Class [concrete = constants.%Class.805] {\n// CHECK:STDOUT:       %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:       %i32.loc9_15: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %Class: type = class_type @Class, @Class(constants.%i32) [concrete = constants.%Class.805]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %Class.805 = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %c.patt: @G.%pattern_type.loc13_21 (%pattern_type.c542f5.1) = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: @G.%pattern_type.loc13_21 (%pattern_type.c542f5.1) = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @G.%pattern_type.loc13_34 (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @G.%pattern_type.loc13_34 (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc13_37: %Copy.type = name_ref T, %T.loc13_6.2 [symbolic = %T.loc13_6.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type.loc13_37: type = facet_access_type %T.ref.loc13_37 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc13_37.3: type = converted %T.ref.loc13_37, %T.as_type.loc13_37 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc13_37.4: Core.Form = init_form %.loc13_37.3 [symbolic = %.loc13_37.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:     %.loc13_14: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc13_6.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T.035)]\n// CHECK:STDOUT:     %c.param: @G.%Class.loc13_31.1 (%Class.3168aa.1) = value_param call_param0\n// CHECK:STDOUT:     %.loc13_31.1: type = splice_block %Class.loc13_31.2 [symbolic = %Class.loc13_31.1 (constants.%Class.3168aa.1)] {\n// CHECK:STDOUT:       %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:       %T.ref.loc13_30: %Copy.type = name_ref T, %T.loc13_6.2 [symbolic = %T.loc13_6.1 (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc13_31: type = facet_access_type %T.ref.loc13_30 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc13_31.2: type = converted %T.ref.loc13_30, %T.as_type.loc13_31 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %Class.loc13_31.2: type = class_type @Class, @Class(constants.%T.binding.as_type) [symbolic = %Class.loc13_31.1 (constants.%Class.3168aa.1)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: @G.%Class.loc13_31.1 (%Class.3168aa.1) = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref @G.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @G.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.ce2 = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %c.patt: @H.%pattern_type.loc17_21 (%pattern_type.c542f5.2) = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: @H.%pattern_type.loc17_21 (%pattern_type.c542f5.2) = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @H.%pattern_type.loc17_34 (%pattern_type.9b9f0c.3) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @H.%pattern_type.loc17_34 (%pattern_type.9b9f0c.3) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %U.ref.loc17_37: %Copy.type = name_ref U, %U.loc17_6.2 [symbolic = %U.loc17_6.1 (constants.%U.035)]\n// CHECK:STDOUT:     %U.as_type.loc17_37: type = facet_access_type %U.ref.loc17_37 [symbolic = %U.binding.as_type (constants.%U.binding.as_type.14b)]\n// CHECK:STDOUT:     %.loc17_37.3: type = converted %U.ref.loc17_37, %U.as_type.loc17_37 [symbolic = %U.binding.as_type (constants.%U.binding.as_type.14b)]\n// CHECK:STDOUT:     %.loc17_37.4: Core.Form = init_form %.loc17_37.3 [symbolic = %.loc17_37.2 (constants.%.076a48.3)]\n// CHECK:STDOUT:     %.loc17_14: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc17_6.2: %Copy.type = symbolic_binding U, 0 [symbolic = %U.loc17_6.1 (constants.%U.035)]\n// CHECK:STDOUT:     %c.param: @H.%Class.loc17_31.1 (%Class.3168aa.2) = value_param call_param0\n// CHECK:STDOUT:     %.loc17_31.1: type = splice_block %Class.loc17_31.2 [symbolic = %Class.loc17_31.1 (constants.%Class.3168aa.2)] {\n// CHECK:STDOUT:       %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:       %U.ref.loc17_30: %Copy.type = name_ref U, %U.loc17_6.2 [symbolic = %U.loc17_6.1 (constants.%U.035)]\n// CHECK:STDOUT:       %U.as_type.loc17_31: type = facet_access_type %U.ref.loc17_30 [symbolic = %U.binding.as_type (constants.%U.binding.as_type.14b)]\n// CHECK:STDOUT:       %.loc17_31.2: type = converted %U.ref.loc17_30, %U.as_type.loc17_31 [symbolic = %U.binding.as_type (constants.%U.binding.as_type.14b)]\n// CHECK:STDOUT:       %Class.loc17_31.2: type = class_type @Class, @Class(constants.%U.binding.as_type.14b) [symbolic = %Class.loc17_31.1 (constants.%Class.3168aa.2)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: @H.%Class.loc17_31.1 (%Class.3168aa.2) = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref @H.%U.binding.as_type (%U.binding.as_type.14b) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @H.%U.binding.as_type (%U.binding.as_type.14b) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc5_13.2: type) {\n// CHECK:STDOUT:   %T.loc5_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc5_13.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.loc5_13.1) [symbolic = %Class (constants.%Class.0db)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.loc5_13.1 [symbolic = %Class.elem (constants.%Class.elem.fdf)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @Class.%T.loc5_13.1 (%T.67d)} [symbolic = %struct_type.x (constants.%struct_type.x.0c5)]\n// CHECK:STDOUT:   %complete_type.loc7_1.2: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type.loc7_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc5_13.2 [symbolic = %T.loc5_13.1 (constants.%T.67d)]\n// CHECK:STDOUT:     %.loc6: @Class.%Class.elem (%Class.elem.fdf) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc7_1.1: <witness> = complete_type_witness constants.%struct_type.x.0c5 [symbolic = %complete_type.loc7_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc7_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class.0db\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .x = %.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %Class.805) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %Class.805 = name_ref c, %c\n// CHECK:STDOUT:   %x.ref: %Class.elem.927 = name_ref x, @Class.%.loc6 [concrete = @Class.%.loc6]\n// CHECK:STDOUT:   %.loc10_11.1: ref %i32 = class_element_access %c.ref, element0\n// CHECK:STDOUT:   %.loc10_11.2: %i32 = acquire_value %.loc10_11.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc10_11.1: <bound method> = bound_method %.loc10_11.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_11.2: <bound method> = bound_method %.loc10_11.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc10_11.2(%.loc10_11.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%T.loc13_6.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc13_6.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc13_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %Class.loc13_31.1: type = class_type @Class, @Class(%T.binding.as_type) [symbolic = %Class.loc13_31.1 (constants.%Class.3168aa.1)]\n// CHECK:STDOUT:   %pattern_type.loc13_21: type = pattern_type %Class.loc13_31.1 [symbolic = %pattern_type.loc13_21 (constants.%pattern_type.c542f5.1)]\n// CHECK:STDOUT:   %.loc13_37.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc13_37.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:   %pattern_type.loc13_34: type = pattern_type %T.binding.as_type [symbolic = %pattern_type.loc13_34 (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc13: <witness> = require_complete_type %Class.loc13_31.1 [symbolic = %require_complete.loc13 (constants.%require_complete.ae7bfa.1)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class.loc13_31.1, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem.7657d6.1)]\n// CHECK:STDOUT:   %require_complete.loc14: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc14 (constants.%require_complete.67ca8d.1)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc13_6.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58dce0.1)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.loc13_6.1) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc14_11.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T.loc13_6.1 [symbolic = %.loc14_11.3 (constants.%.023143.1)]\n// CHECK:STDOUT:   %impl.elem0.loc14_11.2: @G.%.loc14_11.3 (%.023143.1) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc14_11.2 (constants.%impl.elem0.594c59.1)]\n// CHECK:STDOUT:   %specific_impl_fn.loc14_11.2: <specific function> = specific_impl_function %impl.elem0.loc14_11.2, @Copy.WithSelf.Op(%T.loc13_6.1) [symbolic = %specific_impl_fn.loc14_11.2 (constants.%specific_impl_fn.bdce5c.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%c.param: @G.%Class.loc13_31.1 (%Class.3168aa.1)) -> out %return.param: @G.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %c.ref: @G.%Class.loc13_31.1 (%Class.3168aa.1) = name_ref c, %c\n// CHECK:STDOUT:     %x.ref: @G.%Class.elem (%Class.elem.7657d6.1) = name_ref x, @Class.%.loc6 [concrete = @Class.%.loc6]\n// CHECK:STDOUT:     %.loc14_11.1: ref @G.%T.binding.as_type (%T.binding.as_type) = class_element_access %c.ref, element0\n// CHECK:STDOUT:     %.loc14_11.2: @G.%T.binding.as_type (%T.binding.as_type) = acquire_value %.loc14_11.1\n// CHECK:STDOUT:     %impl.elem0.loc14_11.1: @G.%.loc14_11.3 (%.023143.1) = impl_witness_access constants.%Copy.lookup_impl_witness.58dce0.1, element0 [symbolic = %impl.elem0.loc14_11.2 (constants.%impl.elem0.594c59.1)]\n// CHECK:STDOUT:     %bound_method.loc14_11.1: <bound method> = bound_method %.loc14_11.2, %impl.elem0.loc14_11.1\n// CHECK:STDOUT:     %specific_impl_fn.loc14_11.1: <specific function> = specific_impl_function %impl.elem0.loc14_11.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc14_11.2 (constants.%specific_impl_fn.bdce5c.1)]\n// CHECK:STDOUT:     %bound_method.loc14_11.2: <bound method> = bound_method %.loc14_11.2, %specific_impl_fn.loc14_11.1\n// CHECK:STDOUT:     %.loc13_37.1: ref @G.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @G.%T.binding.as_type (%T.binding.as_type) to %.loc13_37.1 = call %bound_method.loc14_11.2(%.loc14_11.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @H(%U.loc17_6.2: %Copy.type) {\n// CHECK:STDOUT:   %U.loc17_6.1: %Copy.type = symbolic_binding U, 0 [symbolic = %U.loc17_6.1 (constants.%U.035)]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U.loc17_6.1 [symbolic = %U.binding.as_type (constants.%U.binding.as_type.14b)]\n// CHECK:STDOUT:   %Class.loc17_31.1: type = class_type @Class, @Class(%U.binding.as_type) [symbolic = %Class.loc17_31.1 (constants.%Class.3168aa.2)]\n// CHECK:STDOUT:   %pattern_type.loc17_21: type = pattern_type %Class.loc17_31.1 [symbolic = %pattern_type.loc17_21 (constants.%pattern_type.c542f5.2)]\n// CHECK:STDOUT:   %.loc17_37.2: Core.Form = init_form %U.binding.as_type [symbolic = %.loc17_37.2 (constants.%.076a48.3)]\n// CHECK:STDOUT:   %pattern_type.loc17_34: type = pattern_type %U.binding.as_type [symbolic = %pattern_type.loc17_34 (constants.%pattern_type.9b9f0c.3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc17: <witness> = require_complete_type %Class.loc17_31.1 [symbolic = %require_complete.loc17 (constants.%require_complete.ae7bfa.2)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class.loc17_31.1, %U.binding.as_type [symbolic = %Class.elem (constants.%Class.elem.7657d6.2)]\n// CHECK:STDOUT:   %require_complete.loc18: <witness> = require_complete_type %U.binding.as_type [symbolic = %require_complete.loc18 (constants.%require_complete.67ca8d.2)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %U.loc17_6.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58dce0.2)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%U.loc17_6.1) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.3)]\n// CHECK:STDOUT:   %.loc18_11.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %U.loc17_6.1 [symbolic = %.loc18_11.3 (constants.%.023143.2)]\n// CHECK:STDOUT:   %impl.elem0.loc18_11.2: @H.%.loc18_11.3 (%.023143.2) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc18_11.2 (constants.%impl.elem0.594c59.2)]\n// CHECK:STDOUT:   %specific_impl_fn.loc18_11.2: <specific function> = specific_impl_function %impl.elem0.loc18_11.2, @Copy.WithSelf.Op(%U.loc17_6.1) [symbolic = %specific_impl_fn.loc18_11.2 (constants.%specific_impl_fn.bdce5c.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%c.param: @H.%Class.loc17_31.1 (%Class.3168aa.2)) -> out %return.param: @H.%U.binding.as_type (%U.binding.as_type.14b) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %c.ref: @H.%Class.loc17_31.1 (%Class.3168aa.2) = name_ref c, %c\n// CHECK:STDOUT:     %x.ref: @H.%Class.elem (%Class.elem.7657d6.2) = name_ref x, @Class.%.loc6 [concrete = @Class.%.loc6]\n// CHECK:STDOUT:     %.loc18_11.1: ref @H.%U.binding.as_type (%U.binding.as_type.14b) = class_element_access %c.ref, element0\n// CHECK:STDOUT:     %.loc18_11.2: @H.%U.binding.as_type (%U.binding.as_type.14b) = acquire_value %.loc18_11.1\n// CHECK:STDOUT:     %impl.elem0.loc18_11.1: @H.%.loc18_11.3 (%.023143.2) = impl_witness_access constants.%Copy.lookup_impl_witness.58dce0.2, element0 [symbolic = %impl.elem0.loc18_11.2 (constants.%impl.elem0.594c59.2)]\n// CHECK:STDOUT:     %bound_method.loc18_11.1: <bound method> = bound_method %.loc18_11.2, %impl.elem0.loc18_11.1\n// CHECK:STDOUT:     %specific_impl_fn.loc18_11.1: <specific function> = specific_impl_function %impl.elem0.loc18_11.1, @Copy.WithSelf.Op(constants.%U.035) [symbolic = %specific_impl_fn.loc18_11.2 (constants.%specific_impl_fn.bdce5c.2)]\n// CHECK:STDOUT:     %bound_method.loc18_11.2: <bound method> = bound_method %.loc18_11.2, %specific_impl_fn.loc18_11.1\n// CHECK:STDOUT:     %.loc17_37.1: ref @H.%U.binding.as_type (%U.binding.as_type.14b) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @H.%U.binding.as_type (%U.binding.as_type.14b) to %.loc17_37.1 = call %bound_method.loc18_11.2(%.loc18_11.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%i32) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %Class => constants.%Class.805\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem.927\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.ed6\n// CHECK:STDOUT:   %complete_type.loc7_1.2 => constants.%complete_type.1ec\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T.binding.as_type) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T.binding.as_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.67ca8d.1\n// CHECK:STDOUT:   %Class => constants.%Class.3168aa.1\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem.7657d6.1\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.8dcd6b.1\n// CHECK:STDOUT:   %complete_type.loc7_1.2 => constants.%complete_type.e78b36.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc13_6.1 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %Class.loc13_31.1 => constants.%Class.3168aa.1\n// CHECK:STDOUT:   %pattern_type.loc13_21 => constants.%pattern_type.c542f5.1\n// CHECK:STDOUT:   %.loc13_37.2 => constants.%.076a48.2\n// CHECK:STDOUT:   %pattern_type.loc13_34 => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%U.binding.as_type.14b) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%U.binding.as_type.14b\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.67ca8d.2\n// CHECK:STDOUT:   %Class => constants.%Class.3168aa.2\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem.7657d6.2\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.8dcd6b.2\n// CHECK:STDOUT:   %complete_type.loc7_1.2 => constants.%complete_type.e78b36.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @H(constants.%U.035) {\n// CHECK:STDOUT:   %U.loc17_6.1 => constants.%U.035\n// CHECK:STDOUT:   %U.binding.as_type => constants.%U.binding.as_type.14b\n// CHECK:STDOUT:   %Class.loc17_31.1 => constants.%Class.3168aa.2\n// CHECK:STDOUT:   %pattern_type.loc17_21 => constants.%pattern_type.c542f5.2\n// CHECK:STDOUT:   %.loc17_37.2 => constants.%.076a48.3\n// CHECK:STDOUT:   %pattern_type.loc17_34 => constants.%pattern_type.9b9f0c.3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/generic_vs_params.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/generic_vs_params.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/generic_vs_params.carbon\n\n// --- params.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass NotGenericNoParams {}\nclass NotGenericButParams() {}\nclass GenericAndParams(T:! type) {}\n\nclass C(T:! type) {\n  class GenericNoParams {}\n  class GenericAndParams(U:! type) {}\n}\n\nclass X {}\n\nvar a: NotGenericNoParams = {};\nvar b: NotGenericButParams() = {};\nvar c: GenericAndParams(X) = {};\nvar d: C(X).GenericNoParams = {};\nvar e: C(X).GenericAndParams(X) = {};\n\n// --- fail_non_generic_implicit_params.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_non_generic_implicit_params.carbon:[[@LINE+4]]:9: error: parameters of generic types must be constant [GenericParamMustBeConstant]\n// CHECK:STDERR: class A[T: type]() {}\n// CHECK:STDERR:         ^~~~~~~\n// CHECK:STDERR:\nclass A[T: type]() {}\n\n// --- fail_non_generic_params.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_non_generic_params.carbon:[[@LINE+4]]:9: error: parameters of generic types must be constant [GenericParamMustBeConstant]\n// CHECK:STDERR: class A(T: type) {}\n// CHECK:STDERR:         ^~~~~~~\n// CHECK:STDERR:\nclass A(T: type) {}\n\n// This is testing a use of the invalid type.\nfn F(T:! type) {\n  A(T);\n}\n\n// --- fail_implicit_params_only_empty.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_implicit_params_only_empty.carbon:[[@LINE+4]]:10: error: expected explicit parameters after implicit parameters [GenericMissingExplicitParameters]\n// CHECK:STDERR: class Foo[];\n// CHECK:STDERR:          ^~\n// CHECK:STDERR:\nclass Foo[];\n\n// --- fail_implicit_params_only.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_implicit_params_only.carbon:[[@LINE+4]]:10: error: expected explicit parameters after implicit parameters [GenericMissingExplicitParameters]\n// CHECK:STDERR: class Foo[T:! type];\n// CHECK:STDERR:          ^~~~~~~~~~\n// CHECK:STDERR:\nclass Foo[T:! type];\n\n// CHECK:STDOUT: --- params.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %NotGenericNoParams: type = class_type @NotGenericNoParams [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %NotGenericButParams.type: type = generic_class_type @NotGenericButParams [concrete]\n// CHECK:STDOUT:   %NotGenericButParams.generic: %NotGenericButParams.type = struct_value () [concrete]\n// CHECK:STDOUT:   %NotGenericButParams: type = class_type @NotGenericButParams [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %GenericAndParams.type.fa0: type = generic_class_type @GenericAndParams.loc6 [concrete]\n// CHECK:STDOUT:   %GenericAndParams.generic.e6f: %GenericAndParams.type.fa0 = struct_value () [concrete]\n// CHECK:STDOUT:   %GenericAndParams.2b4: type = class_type @GenericAndParams.loc6, @GenericAndParams.loc6(%T) [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %GenericNoParams.6cf: type = class_type @GenericNoParams, @GenericNoParams(%T) [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %GenericAndParams.type.208: type = generic_class_type @GenericAndParams.loc10, @C(%T) [symbolic]\n// CHECK:STDOUT:   %GenericAndParams.generic.cc2: %GenericAndParams.type.208 = struct_value () [symbolic]\n// CHECK:STDOUT:   %GenericAndParams.015: type = class_type @GenericAndParams.loc10, @GenericAndParams.loc10(%T, %U) [symbolic]\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %pattern_type.673: type = pattern_type %NotGenericNoParams [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %NotGenericNoParams.val: %NotGenericNoParams = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.749: type = pattern_type %NotGenericButParams [concrete]\n// CHECK:STDOUT:   %NotGenericButParams.val: %NotGenericButParams = struct_value () [concrete]\n// CHECK:STDOUT:   %GenericAndParams.d3d: type = class_type @GenericAndParams.loc6, @GenericAndParams.loc6(%X) [concrete]\n// CHECK:STDOUT:   %pattern_type.856: type = pattern_type %GenericAndParams.d3d [concrete]\n// CHECK:STDOUT:   %GenericAndParams.val.835: %GenericAndParams.d3d = struct_value () [concrete]\n// CHECK:STDOUT:   %C.513: type = class_type @C, @C(%X) [concrete]\n// CHECK:STDOUT:   %GenericNoParams.efa: type = class_type @GenericNoParams, @GenericNoParams(%X) [concrete]\n// CHECK:STDOUT:   %GenericAndParams.type.23d: type = generic_class_type @GenericAndParams.loc10, @C(%X) [concrete]\n// CHECK:STDOUT:   %GenericAndParams.generic.fd2: %GenericAndParams.type.23d = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1fb: type = pattern_type %GenericNoParams.efa [concrete]\n// CHECK:STDOUT:   %GenericNoParams.val: %GenericNoParams.efa = struct_value () [concrete]\n// CHECK:STDOUT:   %GenericAndParams.ed1: type = class_type @GenericAndParams.loc10, @GenericAndParams.loc10(%X, %X) [concrete]\n// CHECK:STDOUT:   %pattern_type.1b8: type = pattern_type %GenericAndParams.ed1 [concrete]\n// CHECK:STDOUT:   %GenericAndParams.val.e35: %GenericAndParams.ed1 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .NotGenericNoParams = %NotGenericNoParams.decl\n// CHECK:STDOUT:     .NotGenericButParams = %NotGenericButParams.decl\n// CHECK:STDOUT:     .GenericAndParams = %GenericAndParams.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .X = %X.decl\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:     .e = %e\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %NotGenericNoParams.decl: type = class_decl @NotGenericNoParams [concrete = constants.%NotGenericNoParams] {} {}\n// CHECK:STDOUT:   %NotGenericButParams.decl: %NotGenericButParams.type = class_decl @NotGenericButParams [concrete = constants.%NotGenericButParams.generic] {} {}\n// CHECK:STDOUT:   %GenericAndParams.decl: %GenericAndParams.type.fa0 = class_decl @GenericAndParams.loc6 [concrete = constants.%GenericAndParams.generic.e6f] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_28.1: type = splice_block %.loc6_28.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_28.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_24.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_24.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_13.1: type = splice_block %.loc8_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc8_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %X.decl: type = class_decl @X [concrete = constants.%X] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.673 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.673 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %NotGenericNoParams = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %NotGenericNoParams.ref: type = name_ref NotGenericNoParams, %NotGenericNoParams.decl [concrete = constants.%NotGenericNoParams]\n// CHECK:STDOUT:   %a: ref %NotGenericNoParams = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.749 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.749 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %NotGenericButParams = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %.loc16: type = splice_block %NotGenericButParams [concrete = constants.%NotGenericButParams] {\n// CHECK:STDOUT:     %NotGenericButParams.ref: %NotGenericButParams.type = name_ref NotGenericButParams, %NotGenericButParams.decl [concrete = constants.%NotGenericButParams.generic]\n// CHECK:STDOUT:     %NotGenericButParams: type = class_type @NotGenericButParams [concrete = constants.%NotGenericButParams]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %NotGenericButParams = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.856 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.856 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %GenericAndParams.d3d = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc17: type = splice_block %GenericAndParams.loc17 [concrete = constants.%GenericAndParams.d3d] {\n// CHECK:STDOUT:     %GenericAndParams.ref.loc17: %GenericAndParams.type.fa0 = name_ref GenericAndParams, %GenericAndParams.decl [concrete = constants.%GenericAndParams.generic.e6f]\n// CHECK:STDOUT:     %X.ref.loc17: type = name_ref X, %X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %GenericAndParams.loc17: type = class_type @GenericAndParams.loc6, @GenericAndParams.loc6(constants.%X) [concrete = constants.%GenericAndParams.d3d]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %GenericAndParams.d3d = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.1fb = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.1fb = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %GenericNoParams.efa = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %.loc18_12.1: type = splice_block %GenericNoParams.ref [concrete = constants.%GenericNoParams.efa] {\n// CHECK:STDOUT:     %C.ref.loc18: %C.type = name_ref C, %C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %X.ref.loc18: type = name_ref X, %X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %C.loc18: type = class_type @C, @C(constants.%X) [concrete = constants.%C.513]\n// CHECK:STDOUT:     %.loc18_12.2: type = specific_constant @C.%GenericNoParams.decl, @C(constants.%X) [concrete = constants.%GenericNoParams.efa]\n// CHECK:STDOUT:     %GenericNoParams.ref: type = name_ref GenericNoParams, %.loc18_12.2 [concrete = constants.%GenericNoParams.efa]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %GenericNoParams.efa = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %e.patt: %pattern_type.1b8 = ref_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.var_patt: %pattern_type.1b8 = var_pattern %e.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e.var: ref %GenericAndParams.ed1 = var %e.var_patt [concrete]\n// CHECK:STDOUT:   %.loc19_31: type = splice_block %GenericAndParams.loc19 [concrete = constants.%GenericAndParams.ed1] {\n// CHECK:STDOUT:     %C.ref.loc19: %C.type = name_ref C, %C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %X.ref.loc19_10: type = name_ref X, %X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %C.loc19: type = class_type @C, @C(constants.%X) [concrete = constants.%C.513]\n// CHECK:STDOUT:     %.loc19_12: %GenericAndParams.type.23d = specific_constant @C.%GenericAndParams.decl, @C(constants.%X) [concrete = constants.%GenericAndParams.generic.fd2]\n// CHECK:STDOUT:     %GenericAndParams.ref.loc19: %GenericAndParams.type.23d = name_ref GenericAndParams, %.loc19_12 [concrete = constants.%GenericAndParams.generic.fd2]\n// CHECK:STDOUT:     %X.ref.loc19_30: type = name_ref X, %X.decl [concrete = constants.%X]\n// CHECK:STDOUT:     %GenericAndParams.loc19: type = class_type @GenericAndParams.loc10, @GenericAndParams.loc10(constants.%X, constants.%X) [concrete = constants.%GenericAndParams.ed1]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e: ref %GenericAndParams.ed1 = ref_binding e, %e.var [concrete = %e.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @NotGenericNoParams {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%NotGenericNoParams\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @NotGenericButParams {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%NotGenericButParams\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @GenericAndParams.loc6(%T.loc6_24.2: type) {\n// CHECK:STDOUT:   %T.loc6_24.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_24.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%GenericAndParams.2b4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc8_9.2: type) {\n// CHECK:STDOUT:   %T.loc8_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc8_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %GenericNoParams: type = class_type @GenericNoParams, @GenericNoParams(%T.loc8_9.1) [symbolic = %GenericNoParams (constants.%GenericNoParams.6cf)]\n// CHECK:STDOUT:   %GenericAndParams.type: type = generic_class_type @GenericAndParams.loc10, @C(%T.loc8_9.1) [symbolic = %GenericAndParams.type (constants.%GenericAndParams.type.208)]\n// CHECK:STDOUT:   %GenericAndParams.generic: @C.%GenericAndParams.type (%GenericAndParams.type.208) = struct_value () [symbolic = %GenericAndParams.generic (constants.%GenericAndParams.generic.cc2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %GenericNoParams.decl: type = class_decl @GenericNoParams [symbolic = @C.%GenericNoParams (constants.%GenericNoParams.6cf)] {} {}\n// CHECK:STDOUT:     %GenericAndParams.decl: @C.%GenericAndParams.type (%GenericAndParams.type.208) = class_decl @GenericAndParams.loc10 [symbolic = @C.%GenericAndParams.generic (constants.%GenericAndParams.generic.cc2)] {\n// CHECK:STDOUT:       %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc10_30.1: type = splice_block %.loc10_30.2 [concrete = type] {\n// CHECK:STDOUT:         %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:         %.loc10_30.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %U.loc10_26.2: type = symbolic_binding U, 1 [symbolic = %U.loc10_26.1 (constants.%U)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:     .GenericNoParams = %GenericNoParams.decl\n// CHECK:STDOUT:     .GenericAndParams = %GenericAndParams.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @GenericNoParams(@C.%T.loc8_9.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%GenericNoParams.6cf\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @GenericAndParams.loc10(@C.%T.loc8_9.2: type, %U.loc10_26.2: type) {\n// CHECK:STDOUT:   %U.loc10_26.1: type = symbolic_binding U, 1 [symbolic = %U.loc10_26.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%GenericAndParams.015\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @X {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%X\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc15_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc15_30.2: init %NotGenericNoParams to file.%a.var = class_init () [concrete = constants.%NotGenericNoParams.val]\n// CHECK:STDOUT:   %.loc15_1: init %NotGenericNoParams = converted %.loc15_30.1, %.loc15_30.2 [concrete = constants.%NotGenericNoParams.val]\n// CHECK:STDOUT:   assign file.%a.var, %.loc15_1\n// CHECK:STDOUT:   %.loc16_33.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc16_33.2: init %NotGenericButParams to file.%b.var = class_init () [concrete = constants.%NotGenericButParams.val]\n// CHECK:STDOUT:   %.loc16_1: init %NotGenericButParams = converted %.loc16_33.1, %.loc16_33.2 [concrete = constants.%NotGenericButParams.val]\n// CHECK:STDOUT:   assign file.%b.var, %.loc16_1\n// CHECK:STDOUT:   %.loc17_31.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc17_31.2: init %GenericAndParams.d3d to file.%c.var = class_init () [concrete = constants.%GenericAndParams.val.835]\n// CHECK:STDOUT:   %.loc17_1: init %GenericAndParams.d3d = converted %.loc17_31.1, %.loc17_31.2 [concrete = constants.%GenericAndParams.val.835]\n// CHECK:STDOUT:   assign file.%c.var, %.loc17_1\n// CHECK:STDOUT:   %.loc18_32.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc18_32.2: init %GenericNoParams.efa to file.%d.var = class_init () [concrete = constants.%GenericNoParams.val]\n// CHECK:STDOUT:   %.loc18_1: init %GenericNoParams.efa = converted %.loc18_32.1, %.loc18_32.2 [concrete = constants.%GenericNoParams.val]\n// CHECK:STDOUT:   assign file.%d.var, %.loc18_1\n// CHECK:STDOUT:   %.loc19_36.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc19_36.2: init %GenericAndParams.ed1 to file.%e.var = class_init () [concrete = constants.%GenericAndParams.val.e35]\n// CHECK:STDOUT:   %.loc19_1: init %GenericAndParams.ed1 = converted %.loc19_36.1, %.loc19_36.2 [concrete = constants.%GenericAndParams.val.e35]\n// CHECK:STDOUT:   assign file.%e.var, %.loc19_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericAndParams.loc6(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_24.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericNoParams(constants.%T) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericAndParams.loc10(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %U.loc10_26.1 => constants.%U\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericAndParams.loc6(constants.%X) {\n// CHECK:STDOUT:   %T.loc6_24.1 => constants.%X\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%X) {\n// CHECK:STDOUT:   %T.loc8_9.1 => constants.%X\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %GenericNoParams => constants.%GenericNoParams.efa\n// CHECK:STDOUT:   %GenericAndParams.type => constants.%GenericAndParams.type.23d\n// CHECK:STDOUT:   %GenericAndParams.generic => constants.%GenericAndParams.generic.fd2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericNoParams(constants.%X) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericAndParams.loc10(constants.%X, constants.%X) {\n// CHECK:STDOUT:   %U.loc10_26.1 => constants.%X\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_non_generic_implicit_params.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = generic_class_type @A [concrete]\n// CHECK:STDOUT:   %A.generic: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = class_decl @A [concrete = constants.%A.generic] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_non_generic_params.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = generic_class_type @A [concrete]\n// CHECK:STDOUT:   %A.generic: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = class_decl @A [concrete = constants.%A.generic] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc11_10.1: type = splice_block %.loc11_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc11_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc11_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc11_6.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc11_6.2: type) {\n// CHECK:STDOUT:   %T.loc11_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc11_6.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc11_6.2 [symbolic = %T.loc11_6.1 (constants.%T)]\n// CHECK:STDOUT:     %A: type = class_type @A [concrete = constants.%A]\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc11_6.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_implicit_params_only_empty.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Foo.type: type = generic_class_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo.generic: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Foo;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_implicit_params_only.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type: type = generic_class_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo.generic: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_15.1: type = splice_block %.loc8_15.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_15.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_11.2: type = symbolic_binding T, 0 [symbolic = %T.loc8_11.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo(%T.loc8_11.2: type) {\n// CHECK:STDOUT:   %T.loc8_11.1: type = symbolic_binding T, 0 [symbolic = %T.loc8_11.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_11.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/import.carbon\n\n// --- foo.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class(T:! type);\n\nclass CompleteClass(T:! type) {\n  var n: i32;\n  fn F() -> i32 { return 0; }\n}\n\nfn F() -> CompleteClass(i32);\n\n// --- foo.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nclass Class(T:! type) {\n  var x: T;\n}\n\nfn F() -> CompleteClass(i32) {\n  return {.n = 1};\n}\n\n// --- use_foo.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"foo\";\n\nfn UseMethod() -> i32 {\n  var v: CompleteClass(i32) = F();\n  return v.F();\n}\n\nfn UseField() -> i32 {\n  var v: CompleteClass(i32) = F();\n  return v.n;\n}\n\n// --- fail_generic_arg_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"foo\";\n\nfn Use() {\n  // TODO: Include the generic arguments in the formatted type name.\n  // CHECK:STDERR: fail_generic_arg_mismatch.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `CompleteClass(i32)` to `CompleteClass(i32*)` [ConversionFailure]\n  // CHECK:STDERR:   var unused v: CompleteClass(i32*) = F();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_generic_arg_mismatch.carbon:[[@LINE+4]]:3: note: type `CompleteClass(i32)` does not implement interface `Core.ImplicitAs(CompleteClass(i32*))` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var unused v: CompleteClass(i32*) = F();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v: CompleteClass(i32*) = F();\n}\n\n// --- fail_foo.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_foo.impl.carbon:[[@LINE+8]]:13: error: redeclaration differs at parameter 1 [RedeclParamDiffers]\n// CHECK:STDERR: class Class(U:! type) {\n// CHECK:STDERR:             ^\n// CHECK:STDERR: fail_foo.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: foo.carbon:4:13: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n// CHECK:STDERR: class Class(T:! type);\n// CHECK:STDERR:             ^\n// CHECK:STDERR:\nclass Class(U:! type) {\n  // CHECK:STDERR: fail_foo.impl.carbon:[[@LINE+4]]:10: error: name `T` not found [NameNotFound]\n  // CHECK:STDERR:   var x: T;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR:\n  var x: T;\n}\n\n// CHECK:STDOUT: --- foo.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CompleteClass.type: type = generic_class_type @CompleteClass [concrete]\n// CHECK:STDOUT:   %CompleteClass.generic: %CompleteClass.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CompleteClass.152: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %CompleteClass.elem: type = unbound_element_type %CompleteClass.152, %i32 [symbolic]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.type: type = fn_type @CompleteClass.F, @CompleteClass(%T) [symbolic]\n// CHECK:STDOUT:   %CompleteClass.F: %CompleteClass.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %CompleteClass.d85: type = class_type @CompleteClass, @CompleteClass(%i32) [concrete]\n// CHECK:STDOUT:   %.63d: Core.Form = init_form %CompleteClass.d85 [concrete]\n// CHECK:STDOUT:   %pattern_type.cb5: type = pattern_type %CompleteClass.d85 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .CompleteClass = %CompleteClass.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CompleteClass.decl: %CompleteClass.type = class_decl @CompleteClass [concrete = constants.%CompleteClass.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_25.1: type = splice_block %.loc6_25.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_25.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_21.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_21.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb5 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb5 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %CompleteClass.ref: %CompleteClass.type = name_ref CompleteClass, file.%CompleteClass.decl [concrete = constants.%CompleteClass.generic]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %CompleteClass: type = class_type @CompleteClass, @CompleteClass(constants.%i32) [concrete = constants.%CompleteClass.d85]\n// CHECK:STDOUT:     %.loc11: Core.Form = init_form %CompleteClass [concrete = constants.%.63d]\n// CHECK:STDOUT:     %return.param: ref %CompleteClass.d85 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %CompleteClass.d85 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @CompleteClass(%T.loc6_21.2: type) {\n// CHECK:STDOUT:   %T.loc6_21.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_21.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass: type = class_type @CompleteClass, @CompleteClass(%T.loc6_21.1) [symbolic = %CompleteClass (constants.%CompleteClass.152)]\n// CHECK:STDOUT:   %CompleteClass.elem: type = unbound_element_type %CompleteClass, constants.%i32 [symbolic = %CompleteClass.elem (constants.%CompleteClass.elem)]\n// CHECK:STDOUT:   %CompleteClass.F.type: type = fn_type @CompleteClass.F, @CompleteClass(%T.loc6_21.1) [symbolic = %CompleteClass.F.type (constants.%CompleteClass.F.type)]\n// CHECK:STDOUT:   %CompleteClass.F: @CompleteClass.%CompleteClass.F.type (%CompleteClass.F.type) = struct_value () [symbolic = %CompleteClass.F (constants.%CompleteClass.F)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc7: @CompleteClass.%CompleteClass.elem (%CompleteClass.elem) = field_decl n, element0 [concrete]\n// CHECK:STDOUT:     %CompleteClass.F.decl: @CompleteClass.%CompleteClass.F.type (%CompleteClass.F.type) = fn_decl @CompleteClass.F [symbolic = @CompleteClass.%CompleteClass.F (constants.%CompleteClass.F)] {\n// CHECK:STDOUT:       %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc8_13: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:       %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:       %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.n [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%CompleteClass.152\n// CHECK:STDOUT:     .n = %.loc7\n// CHECK:STDOUT:     .F = %CompleteClass.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CompleteClass.F(@CompleteClass.%T.loc6_21.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:     %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc8_27.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc8_27.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc8_27.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:     %.loc8_27: init %i32 = converted %int_0, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:     return %.loc8_27\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> out %return.param: %CompleteClass.d85;\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_21.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass => constants.%CompleteClass.152\n// CHECK:STDOUT:   %CompleteClass.elem => constants.%CompleteClass.elem\n// CHECK:STDOUT:   %CompleteClass.F.type => constants.%CompleteClass.F.type\n// CHECK:STDOUT:   %CompleteClass.F => constants.%CompleteClass.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass.F(constants.%T) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass(constants.%i32) {\n// CHECK:STDOUT:   %T.loc6_21.1 => constants.%i32\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- foo.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.595: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.595 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3b3: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.ba2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3b3 = struct_value () [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T [symbolic]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: %T} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x [symbolic]\n// CHECK:STDOUT:   %CompleteClass.type: type = generic_class_type @CompleteClass [concrete]\n// CHECK:STDOUT:   %CompleteClass.generic: %CompleteClass.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.n.4d6: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.a68: <witness> = complete_type_witness %struct_type.n.4d6 [concrete]\n// CHECK:STDOUT:   %CompleteClass.152: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic]\n// CHECK:STDOUT:   %CompleteClass.F.type.6b4: type = fn_type @CompleteClass.F, @CompleteClass(%T) [symbolic]\n// CHECK:STDOUT:   %CompleteClass.F.5ed: %CompleteClass.F.type.6b4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %CompleteClass.elem.2b9: type = unbound_element_type %CompleteClass.152, %i32 [symbolic]\n// CHECK:STDOUT:   %CompleteClass.667: type = class_type @CompleteClass, @CompleteClass(%i32) [concrete]\n// CHECK:STDOUT:   %.bdc: Core.Form = init_form %CompleteClass.667 [concrete]\n// CHECK:STDOUT:   %pattern_type.b91: type = pattern_type %CompleteClass.667 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CompleteClass.elem.995: type = unbound_element_type %CompleteClass.667, %i32 [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.type.111: type = fn_type @CompleteClass.F, @CompleteClass(%i32) [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.3a7: %CompleteClass.F.type.111 = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.n.44a: type = struct_type {.n: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.n.44a = struct_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.ea1: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.574: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.4e9, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.dbb: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.022: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.dbb = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.ea1 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.574) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.7cd6: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.d94: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.7cd6, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.022 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.022, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.47b: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %CompleteClass.val: %CompleteClass.667 = struct_value (%int_1.47b) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.CompleteClass: %CompleteClass.type = import_ref Main//foo, CompleteClass, loaded [concrete = constants.%CompleteClass.generic]\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.e6d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.3b3) = import_ref Main//foo, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.ba2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.4e9 = impl_witness_table (%Main.import_ref.e6d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.1: type = import_ref Main//foo, loc4_13, loaded [symbolic = @Class.%T.1 (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//foo, loc6_21, loaded [symbolic = @CompleteClass.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.eb1: <witness> = import_ref Main//foo, loc9_1, loaded [concrete = constants.%complete_type.a68]\n// CHECK:STDOUT:   %Main.import_ref.09e = import_ref Main//foo, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.1bb = import_ref Main//foo, loc7_8, unloaded\n// CHECK:STDOUT:   %Main.import_ref.469 = import_ref Main//foo, loc8_17, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.3: type = import_ref Main//foo, loc6_21, loaded [symbolic = @CompleteClass.%T (constants.%T)]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.595 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .CompleteClass = imports.%Main.CompleteClass\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_19.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_19.2 = import <none>\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4: type = symbolic_binding T, 0 [symbolic = %T.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.b91 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.b91 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %CompleteClass.ref: %CompleteClass.type = name_ref CompleteClass, imports.%Main.CompleteClass [concrete = constants.%CompleteClass.generic]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %CompleteClass: type = class_type @CompleteClass, @CompleteClass(constants.%i32) [concrete = constants.%CompleteClass.667]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %CompleteClass [concrete = constants.%.bdc]\n// CHECK:STDOUT:     %return.param: ref %CompleteClass.667 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %CompleteClass.667 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(imports.%Main.import_ref.b3bc94.1: type) {\n// CHECK:STDOUT:   %T.1: type = symbolic_binding T, 0 [symbolic = %T.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.1) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.1 [symbolic = %Class.elem (constants.%Class.elem)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @Class.%T.1 (%T)} [symbolic = %struct_type.x (constants.%struct_type.x)]\n// CHECK:STDOUT:   %complete_type.loc6_1.2: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4 [symbolic = %T.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc5: @Class.%Class.elem (%Class.elem) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc6_1.1: <witness> = complete_type_witness constants.%struct_type.x [symbolic = %complete_type.loc6_1.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc6_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .x = %.loc5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @CompleteClass(imports.%Main.import_ref.b3bc94.3: type) [from \"foo.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic = %CompleteClass (constants.%CompleteClass.152)]\n// CHECK:STDOUT:   %CompleteClass.elem: type = unbound_element_type %CompleteClass, constants.%i32 [symbolic = %CompleteClass.elem (constants.%CompleteClass.elem.2b9)]\n// CHECK:STDOUT:   %CompleteClass.F.type: type = fn_type @CompleteClass.F, @CompleteClass(%T) [symbolic = %CompleteClass.F.type (constants.%CompleteClass.F.type.6b4)]\n// CHECK:STDOUT:   %CompleteClass.F: @CompleteClass.%CompleteClass.F.type (%CompleteClass.F.type.6b4) = struct_value () [symbolic = %CompleteClass.F (constants.%CompleteClass.F.5ed)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.eb1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.09e\n// CHECK:STDOUT:     .n = imports.%Main.import_ref.1bb\n// CHECK:STDOUT:     .F = imports.%Main.import_ref.469\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CompleteClass.F(imports.%Main.import_ref.b3bc94.2: type) [from \"foo.carbon\"] {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> out %return.param: %CompleteClass.667 [from \"foo.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc9_17.1: %struct_type.n.44a = struct_literal (%int_1) [concrete = constants.%struct]\n// CHECK:STDOUT:   %impl.elem0: %.d94 = impl_witness_access constants.%ImplicitAs.impl_witness.574, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.022]\n// CHECK:STDOUT:   %bound_method.loc9_17.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_17.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc9_17.2(%int_1) [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc9_17.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc9_17.3: ref %i32 = class_element_access %return.param, element0\n// CHECK:STDOUT:   %.loc9_17.4: init %i32 to %.loc9_17.3 = in_place_init %.loc9_17.2 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc9_17.5: init %CompleteClass.667 to %return.param = class_init (%.loc9_17.4) [concrete = constants.%CompleteClass.val]\n// CHECK:STDOUT:   %.loc9_18: init %CompleteClass.667 = converted %.loc9_17.1, %.loc9_17.5 [concrete = constants.%CompleteClass.val]\n// CHECK:STDOUT:   return %.loc9_18 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T) {\n// CHECK:STDOUT:   %T.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass => constants.%CompleteClass.152\n// CHECK:STDOUT:   %CompleteClass.elem => constants.%CompleteClass.elem.2b9\n// CHECK:STDOUT:   %CompleteClass.F.type => constants.%CompleteClass.F.type.6b4\n// CHECK:STDOUT:   %CompleteClass.F => constants.%CompleteClass.F.5ed\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass.F(constants.%T) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass => constants.%CompleteClass.667\n// CHECK:STDOUT:   %CompleteClass.elem => constants.%CompleteClass.elem.995\n// CHECK:STDOUT:   %CompleteClass.F.type => constants.%CompleteClass.F.type.111\n// CHECK:STDOUT:   %CompleteClass.F => constants.%CompleteClass.F.3a7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_foo.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %UseMethod.type: type = fn_type @UseMethod [concrete]\n// CHECK:STDOUT:   %UseMethod: %UseMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CompleteClass.type: type = generic_class_type @CompleteClass [concrete]\n// CHECK:STDOUT:   %CompleteClass.generic: %CompleteClass.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %CompleteClass.152: type = class_type @CompleteClass, @CompleteClass(%T.67d) [symbolic]\n// CHECK:STDOUT:   %CompleteClass.F.type.6b4: type = fn_type @CompleteClass.F, @CompleteClass(%T.67d) [symbolic]\n// CHECK:STDOUT:   %CompleteClass.F.5ed: %CompleteClass.F.type.6b4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %CompleteClass.elem.4f4: type = unbound_element_type %CompleteClass.152, %i32 [symbolic]\n// CHECK:STDOUT:   %CompleteClass.d85: type = class_type @CompleteClass, @CompleteClass(%i32) [concrete]\n// CHECK:STDOUT:   %CompleteClass.elem.2bc: type = unbound_element_type %CompleteClass.d85, %i32 [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.type.942: type = fn_type @CompleteClass.F, @CompleteClass(%i32) [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.456: %CompleteClass.F.type.942 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb5: type = pattern_type %CompleteClass.d85 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.specific_fn: <specific function> = specific_function %CompleteClass.F.456, @CompleteClass.F(%i32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %UseField.type: type = fn_type @UseField [concrete]\n// CHECK:STDOUT:   %UseField: %UseField.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Class = import_ref Main//foo, Class, unloaded\n// CHECK:STDOUT:   %Main.CompleteClass: %CompleteClass.type = import_ref Main//foo, CompleteClass, loaded [concrete = constants.%CompleteClass.generic]\n// CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//foo, F, loaded [concrete = constants.%F]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.1: type = import_ref Main//foo, loc6_21, loaded [symbolic = @CompleteClass.%T (constants.%T.67d)]\n// CHECK:STDOUT:   %Main.import_ref.eb1: <witness> = import_ref Main//foo, loc9_1, loaded [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:   %Main.import_ref.09e = import_ref Main//foo, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.a08: @CompleteClass.%CompleteClass.elem (%CompleteClass.elem.4f4) = import_ref Main//foo, loc7_8, loaded [concrete = %.744]\n// CHECK:STDOUT:   %Main.import_ref.577: @CompleteClass.%CompleteClass.F.type (%CompleteClass.F.type.6b4) = import_ref Main//foo, loc8_17, loaded [symbolic = @CompleteClass.%CompleteClass.F (constants.%CompleteClass.F.5ed)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//foo, loc6_21, loaded [symbolic = @CompleteClass.%T (constants.%T.67d)]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:   %.744: @CompleteClass.%CompleteClass.elem (%CompleteClass.elem.4f4) = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Class = imports.%Main.Class\n// CHECK:STDOUT:     .CompleteClass = imports.%Main.CompleteClass\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .UseMethod = %UseMethod.decl\n// CHECK:STDOUT:     .UseField = %UseField.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %UseMethod.decl: %UseMethod.type = fn_decl @UseMethod [concrete = constants.%UseMethod] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5: Core.Form = init_form %i32.loc5 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %UseField.decl: %UseField.type = fn_decl @UseField [concrete = constants.%UseField] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc10: Core.Form = init_form %i32.loc10 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @CompleteClass(imports.%Main.import_ref.b3bc94.2: type) [from \"foo.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic = %CompleteClass (constants.%CompleteClass.152)]\n// CHECK:STDOUT:   %CompleteClass.elem: type = unbound_element_type %CompleteClass, constants.%i32 [symbolic = %CompleteClass.elem (constants.%CompleteClass.elem.4f4)]\n// CHECK:STDOUT:   %CompleteClass.F.type: type = fn_type @CompleteClass.F, @CompleteClass(%T) [symbolic = %CompleteClass.F.type (constants.%CompleteClass.F.type.6b4)]\n// CHECK:STDOUT:   %CompleteClass.F: @CompleteClass.%CompleteClass.F.type (%CompleteClass.F.type.6b4) = struct_value () [symbolic = %CompleteClass.F (constants.%CompleteClass.F.5ed)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.eb1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.09e\n// CHECK:STDOUT:     .n = imports.%Main.import_ref.a08\n// CHECK:STDOUT:     .F = imports.%Main.import_ref.577\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @UseMethod() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.cb5 = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.cb5 = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %CompleteClass.d85 = var %v.var_patt\n// CHECK:STDOUT:   %F.ref.loc6: %F.type = name_ref F, imports.%Main.F [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc6_3: ref %CompleteClass.d85 = splice_block %v.var {}\n// CHECK:STDOUT:   %F.call: init %CompleteClass.d85 to %.loc6_3 = call %F.ref.loc6()\n// CHECK:STDOUT:   assign %v.var, %F.call\n// CHECK:STDOUT:   %.loc6_27: type = splice_block %CompleteClass [concrete = constants.%CompleteClass.d85] {\n// CHECK:STDOUT:     %CompleteClass.ref: %CompleteClass.type = name_ref CompleteClass, imports.%Main.CompleteClass [concrete = constants.%CompleteClass.generic]\n// CHECK:STDOUT:     %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %CompleteClass: type = class_type @CompleteClass, @CompleteClass(constants.%i32) [concrete = constants.%CompleteClass.d85]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %CompleteClass.d85 = ref_binding v, %v.var\n// CHECK:STDOUT:   %v.ref: ref %CompleteClass.d85 = name_ref v, %v\n// CHECK:STDOUT:   %.loc7: %CompleteClass.F.type.942 = specific_constant imports.%Main.import_ref.577, @CompleteClass(constants.%i32) [concrete = constants.%CompleteClass.F.456]\n// CHECK:STDOUT:   %F.ref.loc7: %CompleteClass.F.type.942 = name_ref F, %.loc7 [concrete = constants.%CompleteClass.F.456]\n// CHECK:STDOUT:   %CompleteClass.F.specific_fn: <specific function> = specific_function %F.ref.loc7, @CompleteClass.F(constants.%i32) [concrete = constants.%CompleteClass.F.specific_fn]\n// CHECK:STDOUT:   %CompleteClass.F.call: init %i32 = call %CompleteClass.F.specific_fn()\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %v.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%v.var)\n// CHECK:STDOUT:   return %CompleteClass.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CompleteClass.F(imports.%Main.import_ref.b3bc94.1: type) [from \"foo.carbon\"] {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F [from \"foo.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %CompleteClass.d85) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @UseField() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.cb5 = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.cb5 = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %CompleteClass.d85 = var %v.var_patt\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, imports.%Main.F [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc11_3: ref %CompleteClass.d85 = splice_block %v.var {}\n// CHECK:STDOUT:   %F.call: init %CompleteClass.d85 to %.loc11_3 = call %F.ref()\n// CHECK:STDOUT:   assign %v.var, %F.call\n// CHECK:STDOUT:   %.loc11_27: type = splice_block %CompleteClass [concrete = constants.%CompleteClass.d85] {\n// CHECK:STDOUT:     %CompleteClass.ref: %CompleteClass.type = name_ref CompleteClass, imports.%Main.CompleteClass [concrete = constants.%CompleteClass.generic]\n// CHECK:STDOUT:     %i32.loc11: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %CompleteClass: type = class_type @CompleteClass, @CompleteClass(constants.%i32) [concrete = constants.%CompleteClass.d85]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %CompleteClass.d85 = ref_binding v, %v.var\n// CHECK:STDOUT:   %v.ref: ref %CompleteClass.d85 = name_ref v, %v\n// CHECK:STDOUT:   %n.ref: %CompleteClass.elem.2bc = name_ref n, imports.%Main.import_ref.a08 [concrete = imports.%.744]\n// CHECK:STDOUT:   %.loc12_11.1: ref %i32 = class_element_access %v.ref, element0\n// CHECK:STDOUT:   %.loc12_11.2: %i32 = acquire_value %.loc12_11.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc12_11.1: <bound method> = bound_method %.loc12_11.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc12_11.2: <bound method> = bound_method %.loc12_11.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc12_11.2(%.loc12_11.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %v.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%v.var)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass(constants.%T.67d) {\n// CHECK:STDOUT:   %T => constants.%T.67d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass => constants.%CompleteClass.152\n// CHECK:STDOUT:   %CompleteClass.elem => constants.%CompleteClass.elem.4f4\n// CHECK:STDOUT:   %CompleteClass.F.type => constants.%CompleteClass.F.type.6b4\n// CHECK:STDOUT:   %CompleteClass.F => constants.%CompleteClass.F.5ed\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass.F(constants.%T.67d) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass => constants.%CompleteClass.d85\n// CHECK:STDOUT:   %CompleteClass.elem => constants.%CompleteClass.elem.2bc\n// CHECK:STDOUT:   %CompleteClass.F.type => constants.%CompleteClass.F.type.942\n// CHECK:STDOUT:   %CompleteClass.F => constants.%CompleteClass.F.456\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass.F(constants.%i32) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_generic_arg_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Use.type: type = fn_type @Use [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Use: %Use.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CompleteClass.type: type = generic_class_type @CompleteClass [concrete]\n// CHECK:STDOUT:   %CompleteClass.generic: %CompleteClass.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.a68: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %CompleteClass.152: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic]\n// CHECK:STDOUT:   %CompleteClass.F.type.6b4: type = fn_type @CompleteClass.F, @CompleteClass(%T) [symbolic]\n// CHECK:STDOUT:   %CompleteClass.F.5ed: %CompleteClass.F.type.6b4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %CompleteClass.elem.2b9: type = unbound_element_type %CompleteClass.152, %i32 [symbolic]\n// CHECK:STDOUT:   %ptr.9e1: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %CompleteClass.582: type = class_type @CompleteClass, @CompleteClass(%ptr.9e1) [concrete]\n// CHECK:STDOUT:   %CompleteClass.elem.166: type = unbound_element_type %CompleteClass.582, %i32 [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.type.160: type = fn_type @CompleteClass.F, @CompleteClass(%ptr.9e1) [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.f06: %CompleteClass.F.type.160 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.a6d: type = pattern_type %CompleteClass.582 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CompleteClass.667: type = class_type @CompleteClass, @CompleteClass(%i32) [concrete]\n// CHECK:STDOUT:   %CompleteClass.elem.995: type = unbound_element_type %CompleteClass.667, %i32 [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.type.111: type = fn_type @CompleteClass.F, @CompleteClass(%i32) [concrete]\n// CHECK:STDOUT:   %CompleteClass.F.3a7: %CompleteClass.F.type.111 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Class = import_ref Main//foo, Class, unloaded\n// CHECK:STDOUT:   %Main.CompleteClass: %CompleteClass.type = import_ref Main//foo, CompleteClass, loaded [concrete = constants.%CompleteClass.generic]\n// CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//foo, F, loaded [concrete = constants.%F]\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.1: type = import_ref Main//foo, loc6_21, loaded [symbolic = @CompleteClass.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.eb1: <witness> = import_ref Main//foo, loc9_1, loaded [concrete = constants.%complete_type.a68]\n// CHECK:STDOUT:   %Main.import_ref.09e = import_ref Main//foo, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.1bb = import_ref Main//foo, loc7_8, unloaded\n// CHECK:STDOUT:   %Main.import_ref.469 = import_ref Main//foo, loc8_17, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//foo, loc6_21, loaded [symbolic = @CompleteClass.%T (constants.%T)]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Class = imports.%Main.Class\n// CHECK:STDOUT:     .CompleteClass = imports.%Main.CompleteClass\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .Use = %Use.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %Use.decl: %Use.type = fn_decl @Use [concrete = constants.%Use] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @CompleteClass(imports.%Main.import_ref.b3bc94.2: type) [from \"foo.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass: type = class_type @CompleteClass, @CompleteClass(%T) [symbolic = %CompleteClass (constants.%CompleteClass.152)]\n// CHECK:STDOUT:   %CompleteClass.elem: type = unbound_element_type %CompleteClass, constants.%i32 [symbolic = %CompleteClass.elem (constants.%CompleteClass.elem.2b9)]\n// CHECK:STDOUT:   %CompleteClass.F.type: type = fn_type @CompleteClass.F, @CompleteClass(%T) [symbolic = %CompleteClass.F.type (constants.%CompleteClass.F.type.6b4)]\n// CHECK:STDOUT:   %CompleteClass.F: @CompleteClass.%CompleteClass.F.type (%CompleteClass.F.type.6b4) = struct_value () [symbolic = %CompleteClass.F (constants.%CompleteClass.F.5ed)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.eb1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.09e\n// CHECK:STDOUT:     .n = imports.%Main.import_ref.1bb\n// CHECK:STDOUT:     .F = imports.%Main.import_ref.469\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.a6d = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.a6d = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %CompleteClass.582 = var %v.var_patt\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, imports.%Main.F [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc14_41: ref %CompleteClass.667 = temporary_storage\n// CHECK:STDOUT:   %F.call: init %CompleteClass.667 to %.loc14_41 = call %F.ref()\n// CHECK:STDOUT:   %.loc14_3: %CompleteClass.582 = converted %F.call, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign %v.var, <error>\n// CHECK:STDOUT:   %.loc14_35: type = splice_block %CompleteClass [concrete = constants.%CompleteClass.582] {\n// CHECK:STDOUT:     %CompleteClass.ref: %CompleteClass.type = name_ref CompleteClass, imports.%Main.CompleteClass [concrete = constants.%CompleteClass.generic]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr: type = ptr_type %i32 [concrete = constants.%ptr.9e1]\n// CHECK:STDOUT:     %CompleteClass: type = class_type @CompleteClass, @CompleteClass(constants.%ptr.9e1) [concrete = constants.%CompleteClass.582]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %CompleteClass.582 = ref_binding v, %v.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %v.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%v.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CompleteClass.F(imports.%Main.import_ref.b3bc94.1: type) [from \"foo.carbon\"] {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F [from \"foo.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %CompleteClass.582) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass => constants.%CompleteClass.152\n// CHECK:STDOUT:   %CompleteClass.elem => constants.%CompleteClass.elem.2b9\n// CHECK:STDOUT:   %CompleteClass.F.type => constants.%CompleteClass.F.type.6b4\n// CHECK:STDOUT:   %CompleteClass.F => constants.%CompleteClass.F.5ed\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass.F(constants.%T) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass(constants.%ptr.9e1) {\n// CHECK:STDOUT:   %T => constants.%ptr.9e1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass => constants.%CompleteClass.582\n// CHECK:STDOUT:   %CompleteClass.elem => constants.%CompleteClass.elem.166\n// CHECK:STDOUT:   %CompleteClass.F.type => constants.%CompleteClass.F.type.160\n// CHECK:STDOUT:   %CompleteClass.F => constants.%CompleteClass.F.f06\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CompleteClass(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CompleteClass => constants.%CompleteClass.667\n// CHECK:STDOUT:   %CompleteClass.elem => constants.%CompleteClass.elem.995\n// CHECK:STDOUT:   %CompleteClass.F.type => constants.%CompleteClass.F.type.111\n// CHECK:STDOUT:   %CompleteClass.F => constants.%CompleteClass.F.3a7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_foo.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type.a9b607.1: type = generic_class_type @Class.1 [concrete]\n// CHECK:STDOUT:   %Class.generic.f12661.1: %Class.type.a9b607.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type.a9b607.2: type = generic_class_type @Class.loc12 [concrete]\n// CHECK:STDOUT:   %Class.generic.f12661.2: %Class.type.a9b607.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.0db33e.2: type = class_type @Class.loc12, @Class.loc12(%U) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Class: %Class.type.a9b607.1 = import_ref Main//foo, Class, loaded [concrete = constants.%Class.generic.f12661.1]\n// CHECK:STDOUT:   %Main.CompleteClass = import_ref Main//foo, CompleteClass, unloaded\n// CHECK:STDOUT:   %Main.F = import_ref Main//foo, F, unloaded\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.b3b: type = import_ref Main//foo, loc4_13, loaded [symbolic = @Class.1.%T (constants.%T)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Class = imports.%Main.Class\n// CHECK:STDOUT:     .CompleteClass = imports.%Main.CompleteClass\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_19.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_19.2 = import <none>\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type.a9b607.2 = class_decl @Class.loc12 [concrete = constants.%Class.generic.f12661.2] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc12_17.1: type = splice_block %.loc12_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc12_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc12_13.2: type = symbolic_binding U, 0 [symbolic = %U.loc12_13.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class.1(imports.%Main.import_ref.b3b: type) [from \"foo.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class.loc12(%U.loc12_13.2: type) {\n// CHECK:STDOUT:   %U.loc12_13.1: type = symbolic_binding U, 0 [symbolic = %U.loc12_13.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: <error> = name_ref T, <error> [concrete = <error>]\n// CHECK:STDOUT:     %.loc17: <error> = field_decl x, element0 [concrete]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness <error> [concrete = <error>]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class.0db33e.2\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .x = %.loc17\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.1(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.loc12(constants.%U) {\n// CHECK:STDOUT:   %U.loc12_13.1 => constants.%U\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/init.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/init.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/init.carbon\n\n// --- from_struct.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class(T:! type) {\n  var k: T;\n}\n\n//@dump-sem-ir-begin\nfn InitFromStructGeneric(T:! Core.Copy, x: T) -> T {\n  var v: Class(T) = {.k = x};\n  return v.k;\n}\n\nfn InitFromStructSpecific(x: i32) -> i32 {\n  var v: Class(i32) = {.k = x};\n  return v.k;\n}\n//@dump-sem-ir-end\n\n// --- adapt.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Adapt(T:! type) {\n  adapt T;\n}\n\n//@dump-sem-ir-begin\nfn InitFromAdaptedGeneric(T:! Core.Copy, x: T) -> T {\n  return (x as Adapt(T)) as T;\n}\n\nfn InitFromAdaptedSpecific(x: i32) -> i32 {\n  return (x as Adapt(i32)) as i32;\n}\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- from_struct.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %InitFromStructGeneric.type: type = fn_type @InitFromStructGeneric [concrete]\n// CHECK:STDOUT:   %InitFromStructGeneric: %InitFromStructGeneric.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Class.316: type = class_type @Class, @Class(%T.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %Class.elem.765: type = unbound_element_type %Class.316, %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %struct_type.k.436: type = struct_type {.k: %T.binding.as_type} [symbolic]\n// CHECK:STDOUT:   %require_complete.ae7: <witness> = require_complete_type %Class.316 [symbolic]\n// CHECK:STDOUT:   %pattern_type.c54: type = pattern_type %Class.316 [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Class.316, @Destroy [symbolic]\n// CHECK:STDOUT:   %Destroy.facet.88b: %Destroy.type = facet_value %Class.316, (%Destroy.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.5c9: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.88b) [symbolic]\n// CHECK:STDOUT:   %.0dd: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.5c9, %Destroy.facet.88b [symbolic]\n// CHECK:STDOUT:   %impl.elem0.799: %.0dd = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.d17: <specific function> = specific_impl_function %impl.elem0.799, @Destroy.WithSelf.Op(%Destroy.facet.88b) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %InitFromStructSpecific.type: type = fn_type @InitFromStructSpecific [concrete]\n// CHECK:STDOUT:   %InitFromStructSpecific: %InitFromStructSpecific.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.805: type = class_type @Class, @Class(%i32) [concrete]\n// CHECK:STDOUT:   %Class.elem.927: type = unbound_element_type %Class.805, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.k.0bf: type = struct_type {.k: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.1c2: type = pattern_type %Class.805 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %InitFromStructGeneric.decl: %InitFromStructGeneric.type = fn_decl @InitFromStructGeneric [concrete = constants.%InitFromStructGeneric] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @InitFromStructGeneric.%pattern_type.loc9 (%pattern_type.9b9f0c.2) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @InitFromStructGeneric.%pattern_type.loc9 (%pattern_type.9b9f0c.2) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @InitFromStructGeneric.%pattern_type.loc9 (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @InitFromStructGeneric.%pattern_type.loc9 (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc9_50: %Copy.type = name_ref T, %T.loc9_26.2 [symbolic = %T.loc9_26.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type.loc9_50: type = facet_access_type %T.ref.loc9_50 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc9_50.3: type = converted %T.ref.loc9_50, %T.as_type.loc9_50 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc9_50.4: Core.Form = init_form %.loc9_50.3 [symbolic = %.loc9_50.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:     %.loc9_34: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9_26.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc9_26.1 (constants.%T.035)]\n// CHECK:STDOUT:     %x.param: @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc9_44.1: type = splice_block %.loc9_44.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref.loc9_44: %Copy.type = name_ref T, %T.loc9_26.2 [symbolic = %T.loc9_26.1 (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc9_44: type = facet_access_type %T.ref.loc9_44 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_44.2: type = converted %T.ref.loc9_44, %T.as_type.loc9_44 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %InitFromStructSpecific.decl: %InitFromStructSpecific.type = fn_decl @InitFromStructSpecific [concrete = constants.%InitFromStructSpecific] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.7ce = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc14_38: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc14: Core.Form = init_form %i32.loc14_38 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %x.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc14_30: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %x: %i32 = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @InitFromStructGeneric(%T.loc9_26.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc9_26.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc9_26.1 (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc9_26.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type.loc9: type = pattern_type %T.binding.as_type [symbolic = %pattern_type.loc9 (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:   %.loc9_50.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc9_50.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc9: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc9 (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Class.loc10_17.2: type = class_type @Class, @Class(%T.binding.as_type) [symbolic = %Class.loc10_17.2 (constants.%Class.316)]\n// CHECK:STDOUT:   %require_complete.loc10: <witness> = require_complete_type %Class.loc10_17.2 [symbolic = %require_complete.loc10 (constants.%require_complete.ae7)]\n// CHECK:STDOUT:   %pattern_type.loc10: type = pattern_type %Class.loc10_17.2 [symbolic = %pattern_type.loc10 (constants.%pattern_type.c54)]\n// CHECK:STDOUT:   %struct_type.k: type = struct_type {.k: @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.k (constants.%struct_type.k.436)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc9_26.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.loc9_26.1) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc10_27: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T.loc9_26.1 [symbolic = %.loc10_27 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc10_27.2: @InitFromStructGeneric.%.loc10_27 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_27.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc10_27.2: <specific function> = specific_impl_function %impl.elem0.loc10_27.2, @Copy.WithSelf.Op(%T.loc9_26.1) [symbolic = %specific_impl_fn.loc10_27.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class.loc10_17.2, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem.765)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Class.loc10_17.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Class.loc10_17.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.88b)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [symbolic = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.5c9)]\n// CHECK:STDOUT:   %.loc10_3.2: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %Destroy.facet [symbolic = %.loc10_3.2 (constants.%.0dd)]\n// CHECK:STDOUT:   %impl.elem0.loc10_3.2: @InitFromStructGeneric.%.loc10_3.2 (%.0dd) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_3.2 (constants.%impl.elem0.799)]\n// CHECK:STDOUT:   %specific_impl_fn.loc10_3.2: <specific function> = specific_impl_function %impl.elem0.loc10_3.2, @Destroy.WithSelf.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc10_3.2 (constants.%specific_impl_fn.d17)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %v.patt: @InitFromStructGeneric.%pattern_type.loc10 (%pattern_type.c54) = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:       %v.var_patt: @InitFromStructGeneric.%pattern_type.loc10 (%pattern_type.c54) = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v.var: ref @InitFromStructGeneric.%Class.loc10_17.2 (%Class.316) = var %v.var_patt\n// CHECK:STDOUT:     %x.ref: @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) = name_ref x, %x\n// CHECK:STDOUT:     %.loc10_28.1: @InitFromStructGeneric.%struct_type.k (%struct_type.k.436) = struct_literal (%x.ref)\n// CHECK:STDOUT:     %impl.elem0.loc10_27.1: @InitFromStructGeneric.%.loc10_27 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc10_27.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc10_27.1: <bound method> = bound_method %x.ref, %impl.elem0.loc10_27.1\n// CHECK:STDOUT:     %specific_impl_fn.loc10_27.1: <specific function> = specific_impl_function %impl.elem0.loc10_27.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc10_27.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc10_27.2: <bound method> = bound_method %x.ref, %specific_impl_fn.loc10_27.1\n// CHECK:STDOUT:     %.loc10_28.2: ref @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) = class_element_access %v.var, element0\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call.loc10: init @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) to %.loc10_28.2 = call %bound_method.loc10_27.2(%x.ref)\n// CHECK:STDOUT:     %.loc10_28.3: init @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) to %.loc10_28.2 = in_place_init %Copy.WithSelf.Op.call.loc10\n// CHECK:STDOUT:     %.loc10_28.4: init @InitFromStructGeneric.%Class.loc10_17.2 (%Class.316) to %v.var = class_init (%.loc10_28.3)\n// CHECK:STDOUT:     %.loc10_3.1: init @InitFromStructGeneric.%Class.loc10_17.2 (%Class.316) = converted %.loc10_28.1, %.loc10_28.4\n// CHECK:STDOUT:     assign %v.var, %.loc10_3.1\n// CHECK:STDOUT:     %.loc10_17.1: type = splice_block %Class.loc10_17.1 [symbolic = %Class.loc10_17.2 (constants.%Class.316)] {\n// CHECK:STDOUT:       %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:       %T.ref.loc10: %Copy.type = name_ref T, %T.loc9_26.2 [symbolic = %T.loc9_26.1 (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc10: type = facet_access_type %T.ref.loc10 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc10_17.2: type = converted %T.ref.loc10, %T.as_type.loc10 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %Class.loc10_17.1: type = class_type @Class, @Class(constants.%T.binding.as_type) [symbolic = %Class.loc10_17.2 (constants.%Class.316)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v: ref @InitFromStructGeneric.%Class.loc10_17.2 (%Class.316) = ref_binding v, %v.var\n// CHECK:STDOUT:     %v.ref: ref @InitFromStructGeneric.%Class.loc10_17.2 (%Class.316) = name_ref v, %v\n// CHECK:STDOUT:     %k.ref: @InitFromStructGeneric.%Class.elem (%Class.elem.765) = name_ref k, @Class.%.loc5 [concrete = @Class.%.loc5]\n// CHECK:STDOUT:     %.loc11_11.1: ref @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) = class_element_access %v.ref, element0\n// CHECK:STDOUT:     %.loc11_11.2: @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) = acquire_value %.loc11_11.1\n// CHECK:STDOUT:     %impl.elem0.loc11: @InitFromStructGeneric.%.loc10_27 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc10_27.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc11_11.1: <bound method> = bound_method %.loc11_11.2, %impl.elem0.loc11\n// CHECK:STDOUT:     %specific_impl_fn.loc11: <specific function> = specific_impl_function %impl.elem0.loc11, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc10_27.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc11_11.2: <bound method> = bound_method %.loc11_11.2, %specific_impl_fn.loc11\n// CHECK:STDOUT:     %.loc9_50.1: ref @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call.loc11: init @InitFromStructGeneric.%T.binding.as_type (%T.binding.as_type) to %.loc9_50.1 = call %bound_method.loc11_11.2(%.loc11_11.2)\n// CHECK:STDOUT:     %impl.elem0.loc10_3.1: @InitFromStructGeneric.%.loc10_3.2 (%.0dd) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_3.2 (constants.%impl.elem0.799)]\n// CHECK:STDOUT:     %bound_method.loc10_3.1: <bound method> = bound_method %v.var, %impl.elem0.loc10_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc10_3.1: <specific function> = specific_impl_function %impl.elem0.loc10_3.1, @Destroy.WithSelf.Op(constants.%Destroy.facet.88b) [symbolic = %specific_impl_fn.loc10_3.2 (constants.%specific_impl_fn.d17)]\n// CHECK:STDOUT:     %bound_method.loc10_3.2: <bound method> = bound_method %v.var, %specific_impl_fn.loc10_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call: init %empty_tuple.type = call %bound_method.loc10_3.2(%v.var)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call.loc11 to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InitFromStructSpecific(%x.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.1c2 = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.1c2 = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %Class.805 = var %v.var_patt\n// CHECK:STDOUT:   %x.ref: %i32 = name_ref x, %x\n// CHECK:STDOUT:   %.loc15_30.1: %struct_type.k.0bf = struct_literal (%x.ref)\n// CHECK:STDOUT:   %impl.elem0.loc15: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc15_29.1: <bound method> = bound_method %x.ref, %impl.elem0.loc15\n// CHECK:STDOUT:   %specific_fn.loc15: <specific function> = specific_function %impl.elem0.loc15, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_29.2: <bound method> = bound_method %x.ref, %specific_fn.loc15\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc15: init %i32 = call %bound_method.loc15_29.2(%x.ref)\n// CHECK:STDOUT:   %.loc15_30.2: ref %i32 = class_element_access %v.var, element0\n// CHECK:STDOUT:   %.loc15_30.3: init %i32 to %.loc15_30.2 = in_place_init %Int.as.Copy.impl.Op.call.loc15\n// CHECK:STDOUT:   %.loc15_30.4: init %Class.805 to %v.var = class_init (%.loc15_30.3)\n// CHECK:STDOUT:   %.loc15_3: init %Class.805 = converted %.loc15_30.1, %.loc15_30.4\n// CHECK:STDOUT:   assign %v.var, %.loc15_3\n// CHECK:STDOUT:   %.loc15_19: type = splice_block %Class [concrete = constants.%Class.805] {\n// CHECK:STDOUT:     %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:     %i32.loc15: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %Class: type = class_type @Class, @Class(constants.%i32) [concrete = constants.%Class.805]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %Class.805 = ref_binding v, %v.var\n// CHECK:STDOUT:   %v.ref: ref %Class.805 = name_ref v, %v\n// CHECK:STDOUT:   %k.ref: %Class.elem.927 = name_ref k, @Class.%.loc5 [concrete = @Class.%.loc5]\n// CHECK:STDOUT:   %.loc16_11.1: ref %i32 = class_element_access %v.ref, element0\n// CHECK:STDOUT:   %.loc16_11.2: %i32 = acquire_value %.loc16_11.1\n// CHECK:STDOUT:   %impl.elem0.loc16: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc16_11.1: <bound method> = bound_method %.loc16_11.2, %impl.elem0.loc16\n// CHECK:STDOUT:   %specific_fn.loc16: <specific function> = specific_function %impl.elem0.loc16, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_11.2: <bound method> = bound_method %.loc16_11.2, %specific_fn.loc16\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc16: init %i32 = call %bound_method.loc16_11.2(%.loc16_11.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %v.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%v.var)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call.loc16\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Class.805) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @InitFromStructGeneric(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc9_26.1 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type.loc9 => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:   %.loc9_50.2 => constants.%.076a48.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- adapt.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Adapt.type: type = generic_class_type @Adapt [concrete]\n// CHECK:STDOUT:   %Adapt.generic: %Adapt.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %InitFromAdaptedGeneric.type: type = fn_type @InitFromAdaptedGeneric [concrete]\n// CHECK:STDOUT:   %InitFromAdaptedGeneric: %InitFromAdaptedGeneric.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Adapt.f64: type = class_type @Adapt, @Adapt(%T.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %require_complete.888: <witness> = require_complete_type %Adapt.f64 [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %InitFromAdaptedSpecific.type: type = fn_type @InitFromAdaptedSpecific [concrete]\n// CHECK:STDOUT:   %InitFromAdaptedSpecific: %InitFromAdaptedSpecific.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Adapt.808: type = class_type @Adapt, @Adapt(%i32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %InitFromAdaptedGeneric.decl: %InitFromAdaptedGeneric.type = fn_decl @InitFromAdaptedGeneric [concrete = constants.%InitFromAdaptedGeneric] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @InitFromAdaptedGeneric.%pattern_type (%pattern_type.9b9f0c.2) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @InitFromAdaptedGeneric.%pattern_type (%pattern_type.9b9f0c.2) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @InitFromAdaptedGeneric.%pattern_type (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @InitFromAdaptedGeneric.%pattern_type (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc9_51: %Copy.type = name_ref T, %T.loc9_27.2 [symbolic = %T.loc9_27.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type.loc9_51: type = facet_access_type %T.ref.loc9_51 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc9_51.3: type = converted %T.ref.loc9_51, %T.as_type.loc9_51 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc9_51.4: Core.Form = init_form %.loc9_51.3 [symbolic = %.loc9_51.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:     %.loc9_35: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9_27.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc9_27.1 (constants.%T.035)]\n// CHECK:STDOUT:     %x.param: @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc9_45.1: type = splice_block %.loc9_45.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref.loc9_45: %Copy.type = name_ref T, %T.loc9_27.2 [symbolic = %T.loc9_27.1 (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc9_45: type = facet_access_type %T.ref.loc9_45 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_45.2: type = converted %T.ref.loc9_45, %T.as_type.loc9_45 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %InitFromAdaptedSpecific.decl: %InitFromAdaptedSpecific.type = fn_decl @InitFromAdaptedSpecific [concrete = constants.%InitFromAdaptedSpecific] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.7ce = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc13_39: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc13: Core.Form = init_form %i32.loc13_39 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %x.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc13_31: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %x: %i32 = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @InitFromAdaptedGeneric(%T.loc9_27.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc9_27.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc9_27.1 (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc9_27.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:   %.loc9_51.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc9_51.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc9: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc9 (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Adapt.loc10_23.2: type = class_type @Adapt, @Adapt(%T.binding.as_type) [symbolic = %Adapt.loc10_23.2 (constants.%Adapt.f64)]\n// CHECK:STDOUT:   %require_complete.loc10: <witness> = require_complete_type %Adapt.loc10_23.2 [symbolic = %require_complete.loc10 (constants.%require_complete.888)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc9_27.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.loc9_27.1) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc10_26.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T.loc9_27.1 [symbolic = %.loc10_26.3 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc10_26.2: @InitFromAdaptedGeneric.%.loc10_26.3 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_26.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc10_26.2: <specific function> = specific_impl_function %impl.elem0.loc10_26.2, @Copy.WithSelf.Op(%T.loc9_27.1) [symbolic = %specific_impl_fn.loc10_26.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) = name_ref x, %x\n// CHECK:STDOUT:     %Adapt.ref: %Adapt.type = name_ref Adapt, file.%Adapt.decl [concrete = constants.%Adapt.generic]\n// CHECK:STDOUT:     %T.ref.loc10_22: %Copy.type = name_ref T, %T.loc9_27.2 [symbolic = %T.loc9_27.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type.loc10_23: type = facet_access_type %T.ref.loc10_22 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc10_23: type = converted %T.ref.loc10_22, %T.as_type.loc10_23 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %Adapt.loc10_23.1: type = class_type @Adapt, @Adapt(constants.%T.binding.as_type) [symbolic = %Adapt.loc10_23.2 (constants.%Adapt.f64)]\n// CHECK:STDOUT:     %.loc10_13.1: @InitFromAdaptedGeneric.%Adapt.loc10_23.2 (%Adapt.f64) = as_compatible %x.ref\n// CHECK:STDOUT:     %.loc10_13.2: @InitFromAdaptedGeneric.%Adapt.loc10_23.2 (%Adapt.f64) = converted %x.ref, %.loc10_13.1\n// CHECK:STDOUT:     %T.ref.loc10_29: %Copy.type = name_ref T, %T.loc9_27.2 [symbolic = %T.loc9_27.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type.loc10_29: type = facet_access_type %T.ref.loc10_29 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc10_29: type = converted %T.ref.loc10_29, %T.as_type.loc10_29 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc10_26.1: @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) = as_compatible %.loc10_13.2\n// CHECK:STDOUT:     %.loc10_26.2: @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) = converted %.loc10_13.2, %.loc10_26.1\n// CHECK:STDOUT:     %impl.elem0.loc10_26.1: @InitFromAdaptedGeneric.%.loc10_26.3 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc10_26.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc10_26.1: <bound method> = bound_method %.loc10_26.2, %impl.elem0.loc10_26.1\n// CHECK:STDOUT:     %specific_impl_fn.loc10_26.1: <specific function> = specific_impl_function %impl.elem0.loc10_26.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc10_26.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc10_26.2: <bound method> = bound_method %.loc10_26.2, %specific_impl_fn.loc10_26.1\n// CHECK:STDOUT:     %.loc9_51.1: ref @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @InitFromAdaptedGeneric.%T.binding.as_type (%T.binding.as_type) to %.loc9_51.1 = call %bound_method.loc10_26.2(%.loc10_26.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InitFromAdaptedSpecific(%x.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %x.ref: %i32 = name_ref x, %x\n// CHECK:STDOUT:   %Adapt.ref: %Adapt.type = name_ref Adapt, file.%Adapt.decl [concrete = constants.%Adapt.generic]\n// CHECK:STDOUT:   %i32.loc14_22: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %Adapt: type = class_type @Adapt, @Adapt(constants.%i32) [concrete = constants.%Adapt.808]\n// CHECK:STDOUT:   %.loc14_13.1: %Adapt.808 = as_compatible %x.ref\n// CHECK:STDOUT:   %.loc14_13.2: %Adapt.808 = converted %x.ref, %.loc14_13.1\n// CHECK:STDOUT:   %i32.loc14_31: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc14_28.1: %i32 = as_compatible %.loc14_13.2\n// CHECK:STDOUT:   %.loc14_28.2: %i32 = converted %.loc14_13.2, %.loc14_28.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc14_28.1: <bound method> = bound_method %.loc14_28.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_28.2: <bound method> = bound_method %.loc14_28.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc14_28.2(%.loc14_28.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @InitFromAdaptedGeneric(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc9_27.1 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:   %.loc9_51.2 => constants.%.076a48.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/member_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/member_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/member_access.carbon\n\n// --- member_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class(T:! Core.Copy) {\n  var x: T;\n\n  fn Get[self: Self]() -> T {\n    //@dump-sem-ir-begin\n    return self.x;\n    //@dump-sem-ir-end\n  }\n\n  fn GetAddr[ref self: Self]() -> T* {\n    //@dump-sem-ir-begin\n    return &self.x;\n    //@dump-sem-ir-end\n  }\n}\n\nfn DirectFieldAccess(x: Class(i32)) -> i32 {\n  //@dump-sem-ir-begin\n  return x.x;\n  //@dump-sem-ir-end\n}\n\nfn MethodCall(x: Class(i32)) -> i32 {\n  //@dump-sem-ir-begin\n  return x.Get();\n  //@dump-sem-ir-end\n}\n\nfn AddrMethodCall(p: Class(i32)*) -> i32 {\n  //@dump-sem-ir-begin\n  return *p->GetAddr();\n  //@dump-sem-ir-end\n}\n\n// --- static_member_fn_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class(T:! type) {\n  fn Make() -> Class(T) { return {}; }\n}\n\nfn StaticMemberFunctionCall(T:! type) -> Class(T) {\n  //@dump-sem-ir-begin\n  return Class(T).Make();\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- member_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.847: type = class_type @Class, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Class.elem.05d: type = unbound_element_type %Class.847, %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.893: type = pattern_type %Class.847 [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Class.Get.type.8ea: type = fn_type @Class.Get, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %Class.Get.7d3: %Class.Get.type.8ea = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.e7d: type = ptr_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.66f: Core.Form = init_form %ptr.e7d [symbolic]\n// CHECK:STDOUT:   %pattern_type.65a: type = pattern_type %ptr.e7d [symbolic]\n// CHECK:STDOUT:   %Class.GetAddr.type.437: type = fn_type @Class.GetAddr, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %Class.GetAddr.7a1: %Class.GetAddr.type.437 = struct_value () [symbolic]\n// CHECK:STDOUT:   %struct_type.x.8dc: type = struct_type {.x: %T.binding.as_type} [symbolic]\n// CHECK:STDOUT:   %complete_type.e78: <witness> = complete_type_witness %struct_type.x.8dc [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.3a3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.2e7: <witness> = lookup_impl_witness %ptr.e7d, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.facet.8e7: %Copy.type = facet_value %ptr.e7d, (%Copy.lookup_impl_witness.2e7) [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.486: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.8e7) [symbolic]\n// CHECK:STDOUT:   %.b63: type = fn_type_with_self_type %Copy.WithSelf.Op.type.486, %Copy.facet.8e7 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.387: %.b63 = impl_witness_access %Copy.lookup_impl_witness.2e7, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.7f8: <specific function> = specific_impl_function %impl.elem0.387, @Copy.WithSelf.Op(%Copy.facet.8e7) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Class.06a: type = class_type @Class, @Class(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %pattern_type.cea: type = pattern_type %Class.06a [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Class.elem.da5: type = unbound_element_type %Class.06a, %i32 [concrete]\n// CHECK:STDOUT:   %Class.Get.type.bea: type = fn_type @Class.Get, @Class(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %Class.Get.275: %Class.Get.type.bea = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.GetAddr.type.d64: type = fn_type @Class.GetAddr, @Class(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %Class.GetAddr.7d7: %Class.GetAddr.type.d64 = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.x.ed6: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x.ed6 [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Class.Get.specific_fn: <specific function> = specific_function %Class.Get.275, @Class.Get(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %ptr.7d6: type = ptr_type %Class.06a [concrete]\n// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %.605: Core.Form = init_form %ptr.235 [concrete]\n// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr.235 [concrete]\n// CHECK:STDOUT:   %Class.GetAddr.specific_fn: <specific function> = specific_function %Class.GetAddr.7d7, @Class.GetAddr(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %complete_type.3d0: <witness> = complete_type_witness %ptr.235 [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.843: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%i32) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.c3c: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%i32) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.011: %ptr.as.Copy.impl.Op.type.c3c = struct_value () [concrete]\n// CHECK:STDOUT:   %.cab: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%i32) [concrete]\n// CHECK:STDOUT:   %Copy.facet.a7b: %Copy.type = facet_value %ptr.235, (%Copy.impl_witness.843) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.e01: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.a7b) [concrete]\n// CHECK:STDOUT:   %.a62: type = fn_type_with_self_type %Copy.WithSelf.Op.type.e01, %Copy.facet.a7b [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.011, @ptr.as.Copy.impl.Op(%i32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc4_13.2: %Copy.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc18_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class.847\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .x = %.loc5_8\n// CHECK:STDOUT:     .Get = %Class.Get.decl\n// CHECK:STDOUT:     .GetAddr = %Class.GetAddr.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.Get(@Class.%T.loc4_13.2: %Copy.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem.05d)]\n// CHECK:STDOUT:   %require_complete.loc9: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc9 (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc9_16.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T [symbolic = %.loc9_16.3 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc9_16.2: @Class.Get.%.loc9_16.3 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_16.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc9_16.2: <specific function> = specific_impl_function %impl.elem0.loc9_16.2, @Copy.WithSelf.Op(%T) [symbolic = %specific_impl_fn.loc9_16.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @Class.Get.%Class (%Class.847)) -> out %return.param: @Class.Get.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %self.ref: @Class.Get.%Class (%Class.847) = name_ref self, %self\n// CHECK:STDOUT:     %x.ref: @Class.Get.%Class.elem (%Class.elem.05d) = name_ref x, @Class.%.loc5_8 [concrete = @Class.%.loc5_8]\n// CHECK:STDOUT:     %.loc9_16.1: ref @Class.Get.%T.binding.as_type (%T.binding.as_type) = class_element_access %self.ref, element0\n// CHECK:STDOUT:     %.loc9_16.2: @Class.Get.%T.binding.as_type (%T.binding.as_type) = acquire_value %.loc9_16.1\n// CHECK:STDOUT:     %impl.elem0.loc9_16.1: @Class.Get.%.loc9_16.3 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc9_16.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc9_16.1: <bound method> = bound_method %.loc9_16.2, %impl.elem0.loc9_16.1\n// CHECK:STDOUT:     %specific_impl_fn.loc9_16.1: <specific function> = specific_impl_function %impl.elem0.loc9_16.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc9_16.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc9_16.2: <bound method> = bound_method %.loc9_16.2, %specific_impl_fn.loc9_16.1\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Class.Get.%T.binding.as_type (%T.binding.as_type) to %.loc7_27.1 = call %bound_method.loc9_16.2(%.loc9_16.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.GetAddr(@Class.%T.loc4_13.2: %Copy.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem.05d)]\n// CHECK:STDOUT:   %.loc15_12.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.binding.as_type) [symbolic = %.loc15_12.1 (constants.%.3a3)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc13_36.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e7)]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc13_36.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.8e7)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.486)]\n// CHECK:STDOUT:   %.loc15_12.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc15_12.2 (constants.%.b63)]\n// CHECK:STDOUT:   %impl.elem0.loc15_12.2: @Class.GetAddr.%.loc15_12.2 (%.b63) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc15_12.2 (constants.%impl.elem0.387)]\n// CHECK:STDOUT:   %specific_impl_fn.loc15_12.2: <specific function> = specific_impl_function %impl.elem0.loc15_12.2, @Copy.WithSelf.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc15_12.2 (constants.%specific_impl_fn.7f8)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: ref @Class.GetAddr.%Class (%Class.847)) -> out %return.param: @Class.GetAddr.%ptr.loc13_36.1 (%ptr.e7d) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %self.ref: ref @Class.GetAddr.%Class (%Class.847) = name_ref self, %self\n// CHECK:STDOUT:     %x.ref: @Class.GetAddr.%Class.elem (%Class.elem.05d) = name_ref x, @Class.%.loc5_8 [concrete = @Class.%.loc5_8]\n// CHECK:STDOUT:     %.loc15_17: ref @Class.GetAddr.%T.binding.as_type (%T.binding.as_type) = class_element_access %self.ref, element0\n// CHECK:STDOUT:     %addr: @Class.GetAddr.%ptr.loc13_36.1 (%ptr.e7d) = addr_of %.loc15_17\n// CHECK:STDOUT:     %impl.elem0.loc15_12.1: @Class.GetAddr.%.loc15_12.2 (%.b63) = impl_witness_access constants.%Copy.lookup_impl_witness.2e7, element0 [symbolic = %impl.elem0.loc15_12.2 (constants.%impl.elem0.387)]\n// CHECK:STDOUT:     %bound_method.loc15_12.1: <bound method> = bound_method %addr, %impl.elem0.loc15_12.1\n// CHECK:STDOUT:     %specific_impl_fn.loc15_12.1: <specific function> = specific_impl_function %impl.elem0.loc15_12.1, @Copy.WithSelf.Op(constants.%Copy.facet.8e7) [symbolic = %specific_impl_fn.loc15_12.2 (constants.%specific_impl_fn.7f8)]\n// CHECK:STDOUT:     %bound_method.loc15_12.2: <bound method> = bound_method %addr, %specific_impl_fn.loc15_12.1\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Class.GetAddr.%ptr.loc13_36.1 (%ptr.e7d) = call %bound_method.loc15_12.2(%addr)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @DirectFieldAccess(%x.param: %Class.06a) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %x.ref.loc22_10: %Class.06a = name_ref x, %x\n// CHECK:STDOUT:   %x.ref.loc22_11: %Class.elem.da5 = name_ref x, @Class.%.loc5_8 [concrete = @Class.%.loc5_8]\n// CHECK:STDOUT:   %.loc22_11.1: ref %i32 = class_element_access %x.ref.loc22_10, element0\n// CHECK:STDOUT:   %.loc22_11.2: %i32 = acquire_value %.loc22_11.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc22_11.1: <bound method> = bound_method %.loc22_11.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc22_11.2: <bound method> = bound_method %.loc22_11.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc22_11.2(%.loc22_11.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MethodCall(%x.param: %Class.06a) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %x.ref: %Class.06a = name_ref x, %x\n// CHECK:STDOUT:   %.loc28: %Class.Get.type.bea = specific_constant @Class.%Class.Get.decl, @Class(constants.%Copy.facet.de4) [concrete = constants.%Class.Get.275]\n// CHECK:STDOUT:   %Get.ref: %Class.Get.type.bea = name_ref Get, %.loc28 [concrete = constants.%Class.Get.275]\n// CHECK:STDOUT:   %Class.Get.bound: <bound method> = bound_method %x.ref, %Get.ref\n// CHECK:STDOUT:   %Class.Get.specific_fn: <specific function> = specific_function %Get.ref, @Class.Get(constants.%Copy.facet.de4) [concrete = constants.%Class.Get.specific_fn]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %x.ref, %Class.Get.specific_fn\n// CHECK:STDOUT:   %Class.Get.call: init %i32 = call %bound_method(%x.ref)\n// CHECK:STDOUT:   return %Class.Get.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @AddrMethodCall(%p.param: %ptr.7d6) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.7d6 = name_ref p, %p\n// CHECK:STDOUT:   %.loc34_12.1: ref %Class.06a = deref %p.ref\n// CHECK:STDOUT:   %.loc34_12.2: %Class.GetAddr.type.d64 = specific_constant @Class.%Class.GetAddr.decl, @Class(constants.%Copy.facet.de4) [concrete = constants.%Class.GetAddr.7d7]\n// CHECK:STDOUT:   %GetAddr.ref: %Class.GetAddr.type.d64 = name_ref GetAddr, %.loc34_12.2 [concrete = constants.%Class.GetAddr.7d7]\n// CHECK:STDOUT:   %Class.GetAddr.bound: <bound method> = bound_method %.loc34_12.1, %GetAddr.ref\n// CHECK:STDOUT:   %Class.GetAddr.specific_fn: <specific function> = specific_function %GetAddr.ref, @Class.GetAddr(constants.%Copy.facet.de4) [concrete = constants.%Class.GetAddr.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc34_22: <bound method> = bound_method %.loc34_12.1, %Class.GetAddr.specific_fn\n// CHECK:STDOUT:   %Class.GetAddr.call: init %ptr.235 = call %bound_method.loc34_22(%.loc34_12.1)\n// CHECK:STDOUT:   %.loc34_22.1: %ptr.235 = value_of_initializer %Class.GetAddr.call\n// CHECK:STDOUT:   %.loc34_22.2: %ptr.235 = converted %Class.GetAddr.call, %.loc34_22.1\n// CHECK:STDOUT:   %.loc34_10.1: ref %i32 = deref %.loc34_22.2\n// CHECK:STDOUT:   %.loc34_10.2: %i32 = acquire_value %.loc34_10.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc34_10.1: <bound method> = bound_method %.loc34_10.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc34_10.2: <bound method> = bound_method %.loc34_10.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc34_10.2(%.loc34_10.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T.035\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.67c\n// CHECK:STDOUT:   %Class => constants.%Class.847\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem.05d\n// CHECK:STDOUT:   %Class.Get.type => constants.%Class.Get.type.8ea\n// CHECK:STDOUT:   %Class.Get => constants.%Class.Get.7d3\n// CHECK:STDOUT:   %Class.GetAddr.type => constants.%Class.GetAddr.type.437\n// CHECK:STDOUT:   %Class.GetAddr => constants.%Class.GetAddr.7a1\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.8dc\n// CHECK:STDOUT:   %complete_type.loc18_1.2 => constants.%complete_type.e78\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.Get(constants.%T.035) {\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %Class => constants.%Class.847\n// CHECK:STDOUT:   %pattern_type.loc7_10 => constants.%pattern_type.893\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %.loc7_27.2 => constants.%.076a48.2\n// CHECK:STDOUT:   %pattern_type.loc7_24 => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.GetAddr(constants.%T.035) {\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %Class => constants.%Class.847\n// CHECK:STDOUT:   %pattern_type.loc13_18 => constants.%pattern_type.893\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %ptr.loc13_36.1 => constants.%ptr.e7d\n// CHECK:STDOUT:   %.loc13_36.1 => constants.%.66f\n// CHECK:STDOUT:   %pattern_type.loc13_32 => constants.%pattern_type.65a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%Copy.facet.de4) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%Copy.facet.de4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T.binding.as_type => constants.%i32\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %Class => constants.%Class.06a\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem.da5\n// CHECK:STDOUT:   %Class.Get.type => constants.%Class.Get.type.bea\n// CHECK:STDOUT:   %Class.Get => constants.%Class.Get.275\n// CHECK:STDOUT:   %Class.GetAddr.type => constants.%Class.GetAddr.type.d64\n// CHECK:STDOUT:   %Class.GetAddr => constants.%Class.GetAddr.7d7\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.ed6\n// CHECK:STDOUT:   %complete_type.loc18_1.2 => constants.%complete_type.1ec\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.Get(constants.%Copy.facet.de4) {\n// CHECK:STDOUT:   %T => constants.%Copy.facet.de4\n// CHECK:STDOUT:   %Class => constants.%Class.06a\n// CHECK:STDOUT:   %pattern_type.loc7_10 => constants.%pattern_type.cea\n// CHECK:STDOUT:   %T.binding.as_type => constants.%i32\n// CHECK:STDOUT:   %.loc7_27.2 => constants.%.ff5\n// CHECK:STDOUT:   %pattern_type.loc7_24 => constants.%pattern_type.7ce\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc7 => constants.%complete_type.1ec\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem.da5\n// CHECK:STDOUT:   %require_complete.loc9 => constants.%complete_type.f8a\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.f17\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.081\n// CHECK:STDOUT:   %.loc9_16.3 => constants.%.8e2\n// CHECK:STDOUT:   %impl.elem0.loc9_16.2 => constants.%Int.as.Copy.impl.Op.664\n// CHECK:STDOUT:   %specific_impl_fn.loc9_16.2 => constants.%Int.as.Copy.impl.Op.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.GetAddr(constants.%Copy.facet.de4) {\n// CHECK:STDOUT:   %T => constants.%Copy.facet.de4\n// CHECK:STDOUT:   %Class => constants.%Class.06a\n// CHECK:STDOUT:   %pattern_type.loc13_18 => constants.%pattern_type.cea\n// CHECK:STDOUT:   %T.binding.as_type => constants.%i32\n// CHECK:STDOUT:   %ptr.loc13_36.1 => constants.%ptr.235\n// CHECK:STDOUT:   %.loc13_36.1 => constants.%.605\n// CHECK:STDOUT:   %pattern_type.loc13_32 => constants.%pattern_type.fe8\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc13_22 => constants.%complete_type.1ec\n// CHECK:STDOUT:   %require_complete.loc13_36 => constants.%complete_type.3d0\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem.da5\n// CHECK:STDOUT:   %.loc15_12.1 => constants.%.cab\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.843\n// CHECK:STDOUT:   %Copy.facet => constants.%Copy.facet.a7b\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.e01\n// CHECK:STDOUT:   %.loc15_12.2 => constants.%.a62\n// CHECK:STDOUT:   %impl.elem0.loc15_12.2 => constants.%ptr.as.Copy.impl.Op.011\n// CHECK:STDOUT:   %specific_impl_fn.loc15_12.2 => constants.%ptr.as.Copy.impl.Op.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- static_member_fn_call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %.6f9: Core.Form = init_form %Class [symbolic]\n// CHECK:STDOUT:   %pattern_type.466: type = pattern_type %Class [symbolic]\n// CHECK:STDOUT:   %Class.Make.type: type = fn_type @Class.Make, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %Class.Make: %Class.Make.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class [symbolic]\n// CHECK:STDOUT:   %Class.Make.specific_fn: <specific function> = specific_function %Class.Make, @Class.Make(%T) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @StaticMemberFunctionCall(%T.loc8_29.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class.loc8_49.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %Class.Make.type: type = fn_type @Class.Make, @Class(%T.loc8_29.1) [symbolic = %Class.Make.type (constants.%Class.Make.type)]\n// CHECK:STDOUT:   %Class.Make: @StaticMemberFunctionCall.%Class.Make.type (%Class.Make.type) = struct_value () [symbolic = %Class.Make (constants.%Class.Make)]\n// CHECK:STDOUT:   %Class.Make.specific_fn.loc10_18.2: <specific function> = specific_function %Class.Make, @Class.Make(%T.loc8_29.1) [symbolic = %Class.Make.specific_fn.loc10_18.2 (constants.%Class.Make.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @StaticMemberFunctionCall.%Class.loc8_49.1 (%Class) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %Class.ref.loc10: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:     %T.ref.loc10: type = name_ref T, %T.loc8_29.2 [symbolic = %T.loc8_29.1 (constants.%T)]\n// CHECK:STDOUT:     %Class.loc10: type = class_type @Class, @Class(constants.%T) [symbolic = %Class.loc8_49.1 (constants.%Class)]\n// CHECK:STDOUT:     %.loc10: @StaticMemberFunctionCall.%Class.Make.type (%Class.Make.type) = specific_constant @Class.%Class.Make.decl, @Class(constants.%T) [symbolic = %Class.Make (constants.%Class.Make)]\n// CHECK:STDOUT:     %Make.ref: @StaticMemberFunctionCall.%Class.Make.type (%Class.Make.type) = name_ref Make, %.loc10 [symbolic = %Class.Make (constants.%Class.Make)]\n// CHECK:STDOUT:     %Class.Make.specific_fn.loc10_18.1: <specific function> = specific_function %Make.ref, @Class.Make(constants.%T) [symbolic = %Class.Make.specific_fn.loc10_18.2 (constants.%Class.Make.specific_fn)]\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %Class.Make.call: init @StaticMemberFunctionCall.%Class.loc8_49.1 (%Class) to %.loc8_49.1 = call %Class.Make.specific_fn.loc10_18.1()\n// CHECK:STDOUT:     return %Class.Make.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @StaticMemberFunctionCall(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_29.1 => constants.%T\n// CHECK:STDOUT:   %Class.loc8_49.1 => constants.%Class\n// CHECK:STDOUT:   %.loc8_49.2 => constants.%.6f9\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.466\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/member_inline.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/member_inline.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/member_inline.carbon\n\n// --- member_inline.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nclass Class(T:! Core.Copy) {\n  fn F(n: T) -> T {\n    return n;\n  }\n\n  fn G[self: Self]() -> T {\n    return self.n;\n  }\n\n  var n: T;\n}\n//@dump-sem-ir-end\n\n// --- fail_member_inline_missing_self_dot.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nclass C(T:! Core.Copy) {\n  fn F() {\n    // CHECK:STDERR: fail_member_inline_missing_self_dot.carbon:[[@LINE+4]]:5: error: expression cannot be used as a value [UseOfNonExprAsValue]\n    // CHECK:STDERR:     data;\n    // CHECK:STDERR:     ^~~~\n    // CHECK:STDERR:\n    data;\n  }\n  var data: {};\n}\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- member_inline.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.893: type = pattern_type %Class [symbolic]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %Class.G: %Class.G.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %T.binding.as_type} [symbolic]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.n [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %require_complete.904: <witness> = require_complete_type %Class [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_13.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc5_13.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F, @Class(%T.loc5_13.1) [symbolic = %Class.F.type (constants.%Class.F.type)]\n// CHECK:STDOUT:   %Class.F: @Class.%Class.F.type (%Class.F.type) = struct_value () [symbolic = %Class.F (constants.%Class.F)]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G, @Class(%T.loc5_13.1) [symbolic = %Class.G.type (constants.%Class.G.type)]\n// CHECK:STDOUT:   %Class.G: @Class.%Class.G.type (%Class.G.type) = struct_value () [symbolic = %Class.G (constants.%Class.G)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc5_13.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.loc5_13.1) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem)]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: @Class.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.n (constants.%struct_type.n)]\n// CHECK:STDOUT:   %complete_type.loc15_1.2: <witness> = complete_type_witness %struct_type.n [symbolic = %complete_type.loc15_1.2 (constants.%complete_type)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Class.F.decl: @Class.%Class.F.type (%Class.F.type) = fn_decl @Class.F [symbolic = @Class.%Class.F (constants.%Class.F)] {\n// CHECK:STDOUT:       %n.patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = value_binding_pattern n [concrete]\n// CHECK:STDOUT:       %n.param_patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref.loc6_17: %Copy.type = name_ref T, @Class.%T.loc5_13.2 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc6_17: type = facet_access_type %T.ref.loc6_17 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc6_17.3: type = converted %T.ref.loc6_17, %T.as_type.loc6_17 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc6_17.4: Core.Form = init_form %.loc6_17.3 [symbolic = %.loc6_17.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:       %n.param: @Class.F.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:       %.loc6_11.1: type = splice_block %.loc6_11.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:         %T.ref.loc6_11: %Copy.type = name_ref T, @Class.%T.loc5_13.2 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:         %T.as_type.loc6_11: type = facet_access_type %T.ref.loc6_11 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:         %.loc6_11.2: type = converted %T.ref.loc6_11, %T.as_type.loc6_11 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %n: @Class.F.%T.binding.as_type (%T.binding.as_type) = value_binding n, %n.param\n// CHECK:STDOUT:       %return.param: ref @Class.F.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @Class.F.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Class.G.decl: @Class.%Class.G.type (%Class.G.type) = fn_decl @Class.G [symbolic = @Class.%Class.G (constants.%Class.G)] {\n// CHECK:STDOUT:       %self.patt: @Class.G.%pattern_type.loc10_8 (%pattern_type.893) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Class.G.%pattern_type.loc10_8 (%pattern_type.893) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @Class.G.%pattern_type.loc10_22 (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.G.%pattern_type.loc10_22 (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: %Copy.type = name_ref T, @Class.%T.loc5_13.2 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc10_25.3: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc10_25.4: Core.Form = init_form %.loc10_25.3 [symbolic = %.loc10_25.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:       %self.param: @Class.G.%Class (%Class) = value_param call_param0\n// CHECK:STDOUT:       %.loc10_14.1: type = splice_block %Self.ref [symbolic = %Class (constants.%Class)] {\n// CHECK:STDOUT:         %.loc10_14.2: type = specific_constant constants.%Class, @Class(constants.%T.035) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc10_14.2 [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Class.G.%Class (%Class) = value_binding self, %self.param\n// CHECK:STDOUT:       %return.param: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.ref: %Copy.type = name_ref T, %T.loc5_13.2 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc14_10: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc14_8: @Class.%Class.elem (%Class.elem) = field_decl n, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc15_1.1: <witness> = complete_type_witness constants.%struct_type.n [symbolic = %complete_type.loc15_1.2 (constants.%complete_type)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc15_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %Class.F.decl\n// CHECK:STDOUT:     .G = %Class.G.decl\n// CHECK:STDOUT:     .n = %.loc14_8\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.F(@Class.%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T: %Copy.type = symbolic_binding T, 0 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:   %.loc6_17.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc6_17.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc7: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T [symbolic = %.loc7 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc7_12.2: @Class.F.%.loc7 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc7_12.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc7_12.2: <specific function> = specific_impl_function %impl.elem0.loc7_12.2, @Copy.WithSelf.Op(%T) [symbolic = %specific_impl_fn.loc7_12.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%n.param: @Class.F.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @Class.F.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %n.ref: @Class.F.%T.binding.as_type (%T.binding.as_type) = name_ref n, %n\n// CHECK:STDOUT:     %impl.elem0.loc7_12.1: @Class.F.%.loc7 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc7_12.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc7_12.1: <bound method> = bound_method %n.ref, %impl.elem0.loc7_12.1\n// CHECK:STDOUT:     %specific_impl_fn.loc7_12.1: <specific function> = specific_impl_function %impl.elem0.loc7_12.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc7_12.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc7_12.2: <bound method> = bound_method %n.ref, %specific_impl_fn.loc7_12.1\n// CHECK:STDOUT:     %.loc6_17.1: ref @Class.F.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Class.F.%T.binding.as_type (%T.binding.as_type) to %.loc6_17.1 = call %bound_method.loc7_12.2(%n.ref)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.G(@Class.%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T: %Copy.type = symbolic_binding T, 0 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %pattern_type.loc10_8: type = pattern_type %Class [symbolic = %pattern_type.loc10_8 (constants.%pattern_type.893)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %.loc10_25.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc10_25.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:   %pattern_type.loc10_22: type = pattern_type %T.binding.as_type [symbolic = %pattern_type.loc10_22 (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc10: <witness> = require_complete_type %Class [symbolic = %require_complete.loc10 (constants.%require_complete.904)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem)]\n// CHECK:STDOUT:   %require_complete.loc11: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc11 (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc11_16.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T [symbolic = %.loc11_16.3 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc11_16.2: @Class.G.%.loc11_16.3 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_16.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc11_16.2: <specific function> = specific_impl_function %impl.elem0.loc11_16.2, @Copy.WithSelf.Op(%T) [symbolic = %specific_impl_fn.loc11_16.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @Class.G.%Class (%Class)) -> out %return.param: @Class.G.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %self.ref: @Class.G.%Class (%Class) = name_ref self, %self\n// CHECK:STDOUT:     %n.ref: @Class.G.%Class.elem (%Class.elem) = name_ref n, @Class.%.loc14_8 [concrete = @Class.%.loc14_8]\n// CHECK:STDOUT:     %.loc11_16.1: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = class_element_access %self.ref, element0\n// CHECK:STDOUT:     %.loc11_16.2: @Class.G.%T.binding.as_type (%T.binding.as_type) = acquire_value %.loc11_16.1\n// CHECK:STDOUT:     %impl.elem0.loc11_16.1: @Class.G.%.loc11_16.3 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc11_16.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc11_16.1: <bound method> = bound_method %.loc11_16.2, %impl.elem0.loc11_16.1\n// CHECK:STDOUT:     %specific_impl_fn.loc11_16.1: <specific function> = specific_impl_function %impl.elem0.loc11_16.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc11_16.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc11_16.2: <bound method> = bound_method %.loc11_16.2, %specific_impl_fn.loc11_16.1\n// CHECK:STDOUT:     %.loc10_25.1: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Class.G.%T.binding.as_type (%T.binding.as_type) to %.loc10_25.1 = call %bound_method.loc11_16.2(%.loc11_16.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T.035\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.F.type => constants.%Class.F.type\n// CHECK:STDOUT:   %Class.F => constants.%Class.F\n// CHECK:STDOUT:   %Class.G.type => constants.%Class.G.type\n// CHECK:STDOUT:   %Class.G => constants.%Class.G\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.67c\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem\n// CHECK:STDOUT:   %struct_type.n => constants.%struct_type.n\n// CHECK:STDOUT:   %complete_type.loc15_1.2 => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.F(constants.%T.035) {\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:   %.loc6_17.2 => constants.%.076a48.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.G(constants.%T.035) {\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %pattern_type.loc10_8 => constants.%pattern_type.893\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %.loc10_25.2 => constants.%.076a48.2\n// CHECK:STDOUT:   %pattern_type.loc10_22 => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_member_inline_missing_self_dot.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %T: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F, @C(%T) [symbolic]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %empty_struct_type [symbolic]\n// CHECK:STDOUT:   %struct_type.data: type = struct_type {.data: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.data [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_9.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc5_9.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc5_9.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F, @C(%T.loc5_9.1) [symbolic = %C.F.type (constants.%C.F.type)]\n// CHECK:STDOUT:   %C.F: @C.%C.F.type (%C.F.type) = struct_value () [symbolic = %C.F (constants.%C.F)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T.loc5_9.1) [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, constants.%empty_struct_type [symbolic = %C.elem (constants.%C.elem)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %C.F.decl: @C.%C.F.type (%C.F.type) = fn_decl @C.F [symbolic = @C.%C.F (constants.%C.F)] {} {}\n// CHECK:STDOUT:     %.loc13_14.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc13_14.2: type = converted %.loc13_14.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %.loc13_11: @C.%C.elem (%C.elem) = field_decl data, element0 [concrete]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.data [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C\n// CHECK:STDOUT:     .F = %C.F.decl\n// CHECK:STDOUT:     .data = %.loc13_11\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @C.F(@C.%T.loc5_9.2: %Copy.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T: %Copy.type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T) [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, constants.%empty_struct_type [symbolic = %C.elem (constants.%C.elem)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %data.ref: @C.F.%C.elem (%C.elem) = name_ref data, @C.%.loc13_11 [concrete = @C.%.loc13_11]\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc5_9.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.F.type => constants.%C.F.type\n// CHECK:STDOUT:   %C.F => constants.%C.F\n// CHECK:STDOUT:   %C => constants.%C\n// CHECK:STDOUT:   %C.elem => constants.%C.elem\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.F(constants.%T) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/member_lookup.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/member_lookup.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/member_lookup.carbon\n\n// --- member_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base(T:! type) {\n  var b: T;\n}\n\nclass Derived(T:! type) {\n  extend base: Base(T);\n  var d: T;\n}\n\nfn AccessDerived[T:! Core.Copy](x: Derived(T)) -> T {\n  //@dump-sem-ir-begin\n  return x.d;\n  //@dump-sem-ir-end\n}\n\nfn AccessBase[T:! Core.Copy](x: Derived(T)) -> T {\n  //@dump-sem-ir-begin\n  return x.b;\n  //@dump-sem-ir-end\n}\n\nfn AccessConcrete(x: Derived(i32)) -> i32 {\n  return x.b;\n}\n\n// --- fail_no_member.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base(T:! type) {\n  var b: T;\n}\n\nclass Derived(T:! type) {\n  extend base: Base(T);\n  var d: T;\n}\n\nfn AccessMissingBase[T:! type](x: Base(T)) -> T {\n  // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Base(T)` [MemberNameNotFoundInSpecificScope]\n  // CHECK:STDERR:   return x.nonesuch;\n  // CHECK:STDERR:          ^~~~~~~~~~\n  // CHECK:STDERR:\n  return x.nonesuch;\n}\n\nfn AccessMissingDerived[T:! type](x: Derived(T)) -> T {\n  // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Derived(T)` [MemberNameNotFoundInSpecificScope]\n  // CHECK:STDERR:   return x.nonesuch;\n  // CHECK:STDERR:          ^~~~~~~~~~\n  // CHECK:STDERR:\n  return x.nonesuch;\n}\n\nfn AccessMissingConcrete(x: Derived(i32)) -> i32 {\n  // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Derived(i32)` [MemberNameNotFoundInSpecificScope]\n  // CHECK:STDERR:   return x.nonesuch;\n  // CHECK:STDERR:          ^~~~~~~~~~\n  // CHECK:STDERR:\n  return x.nonesuch;\n}\n\n// CHECK:STDOUT: --- member_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %Derived.ad7: type = class_type @Derived, @Derived(%T.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %pattern_type.d85: type = pattern_type %Derived.ad7 [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Base.ab3: type = class_type @Base, @Base(%T.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %require_complete.b68: <witness> = require_complete_type %Base.ab3 [symbolic]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Derived.elem.d6f: type = unbound_element_type %Derived.ad7, %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Base.elem.384: type = unbound_element_type %Base.ab3, %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @AccessDerived(%T.loc13_18.2: %Copy.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived.loc13_45.1, %T.binding.as_type [symbolic = %Derived.elem (constants.%Derived.elem.d6f)]\n// CHECK:STDOUT:   %require_complete.loc15: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc15 (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc13_18.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.loc13_18.1) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc15_11.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T.loc13_18.1 [symbolic = %.loc15_11.3 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc15_11.2: @AccessDerived.%.loc15_11.3 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc15_11.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc15_11.2: <specific function> = specific_impl_function %impl.elem0.loc15_11.2, @Copy.WithSelf.Op(%T.loc13_18.1) [symbolic = %specific_impl_fn.loc15_11.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @AccessDerived.%Derived.loc13_45.1 (%Derived.ad7)) -> out %return.param: @AccessDerived.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @AccessDerived.%Derived.loc13_45.1 (%Derived.ad7) = name_ref x, %x\n// CHECK:STDOUT:     %d.ref: @AccessDerived.%Derived.elem (%Derived.elem.d6f) = name_ref d, @Derived.%.loc10 [concrete = @Derived.%.loc10]\n// CHECK:STDOUT:     %.loc15_11.1: ref @AccessDerived.%T.binding.as_type (%T.binding.as_type) = class_element_access %x.ref, element1\n// CHECK:STDOUT:     %.loc15_11.2: @AccessDerived.%T.binding.as_type (%T.binding.as_type) = acquire_value %.loc15_11.1\n// CHECK:STDOUT:     %impl.elem0.loc15_11.1: @AccessDerived.%.loc15_11.3 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc15_11.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc15_11.1: <bound method> = bound_method %.loc15_11.2, %impl.elem0.loc15_11.1\n// CHECK:STDOUT:     %specific_impl_fn.loc15_11.1: <specific function> = specific_impl_function %impl.elem0.loc15_11.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc15_11.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc15_11.2: <bound method> = bound_method %.loc15_11.2, %specific_impl_fn.loc15_11.1\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @AccessDerived.%T.binding.as_type (%T.binding.as_type) to %.loc13_51.1 = call %bound_method.loc15_11.2(%.loc15_11.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @AccessBase(%T.loc19_15.2: %Copy.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T.binding.as_type) [symbolic = %Base (constants.%Base.ab3)]\n// CHECK:STDOUT:   %require_complete.loc21_11: <witness> = require_complete_type %Base [symbolic = %require_complete.loc21_11 (constants.%require_complete.b68)]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %T.binding.as_type [symbolic = %Base.elem (constants.%Base.elem.384)]\n// CHECK:STDOUT:   %require_complete.loc21_13: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc21_13 (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc19_15.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.loc19_15.1) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc21_11.5: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T.loc19_15.1 [symbolic = %.loc21_11.5 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc21_11.2: @AccessBase.%.loc21_11.5 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc21_11.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc21_11.2: <specific function> = specific_impl_function %impl.elem0.loc21_11.2, @Copy.WithSelf.Op(%T.loc19_15.1) [symbolic = %specific_impl_fn.loc21_11.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @AccessBase.%Derived.loc19_42.1 (%Derived.ad7)) -> out %return.param: @AccessBase.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @AccessBase.%Derived.loc19_42.1 (%Derived.ad7) = name_ref x, %x\n// CHECK:STDOUT:     %b.ref: @AccessBase.%Base.elem (%Base.elem.384) = name_ref b, @Base.%.loc5 [concrete = @Base.%.loc5]\n// CHECK:STDOUT:     %.loc21_11.1: ref @AccessBase.%Base (%Base.ab3) = class_element_access %x.ref, element0\n// CHECK:STDOUT:     %.loc21_11.2: ref @AccessBase.%Base (%Base.ab3) = converted %x.ref, %.loc21_11.1\n// CHECK:STDOUT:     %.loc21_11.3: ref @AccessBase.%T.binding.as_type (%T.binding.as_type) = class_element_access %.loc21_11.2, element0\n// CHECK:STDOUT:     %.loc21_11.4: @AccessBase.%T.binding.as_type (%T.binding.as_type) = acquire_value %.loc21_11.3\n// CHECK:STDOUT:     %impl.elem0.loc21_11.1: @AccessBase.%.loc21_11.5 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc21_11.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc21_11.1: <bound method> = bound_method %.loc21_11.4, %impl.elem0.loc21_11.1\n// CHECK:STDOUT:     %specific_impl_fn.loc21_11.1: <specific function> = specific_impl_function %impl.elem0.loc21_11.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc21_11.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc21_11.2: <bound method> = bound_method %.loc21_11.4, %specific_impl_fn.loc21_11.1\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @AccessBase.%T.binding.as_type (%T.binding.as_type) to %.loc19_48.1 = call %bound_method.loc21_11.2(%.loc21_11.4)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AccessDerived(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc13_18.1 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %Derived.loc13_45.1 => constants.%Derived.ad7\n// CHECK:STDOUT:   %pattern_type.loc13_33 => constants.%pattern_type.d85\n// CHECK:STDOUT:   %.loc13_51.2 => constants.%.076a48.2\n// CHECK:STDOUT:   %pattern_type.loc13_48 => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AccessBase(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc19_15.1 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %Derived.loc19_42.1 => constants.%Derived.ad7\n// CHECK:STDOUT:   %pattern_type.loc19_30 => constants.%pattern_type.d85\n// CHECK:STDOUT:   %.loc19_48.2 => constants.%.076a48.2\n// CHECK:STDOUT:   %pattern_type.loc19_45 => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/member_out_of_line.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/member_out_of_line.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/member_out_of_line.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nclass Class(T:! Core.Copy) {\n  fn F(n: T) -> T;\n  fn G[self: Self]() -> T;\n  var n: T;\n}\n\nfn Class(T:! Core.Copy).F(n: T) -> T {\n  return n;\n}\n\nfn Class(T:! Core.Copy).G[self: Self]() -> T {\n  return self.n;\n}\n//@dump-sem-ir-end\n\n// --- nested.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nclass A(T:! type) {\n  class B(_:! T) {\n    fn F[self: Self](a: T);\n  }\n}\n\nfn A(T:! type).B(_:! T).F[unused self: Self](unused a: T) {}\n//@dump-sem-ir-end\n\n// --- fail_mismatched_not_generic_vs_generic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass NotGeneric {\n  fn F();\n}\n\n// CHECK:STDERR: fail_mismatched_not_generic_vs_generic.carbon:[[@LINE+7]]:4: error: redeclaration differs because of parameter list [RedeclParamListDiffers]\n// CHECK:STDERR: fn NotGeneric(unused T:! type).F() {}\n// CHECK:STDERR:    ^~~~~~~~~~\n// CHECK:STDERR: fail_mismatched_not_generic_vs_generic.carbon:[[@LINE-7]]:1: note: previously declared without parameter list [RedeclParamListPrevious]\n// CHECK:STDERR: class NotGeneric {\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn NotGeneric(unused T:! type).F() {}\n\n// --- fail_mismatched_too_few_args.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Generic(unused T:! type) {\n  fn TooFew();\n}\n\n// CHECK:STDERR: fail_mismatched_too_few_args.carbon:[[@LINE+7]]:4: error: redeclaration differs because of parameter count of 0 [RedeclParamCountDiffers]\n// CHECK:STDERR: fn Generic().TooFew() {}\n// CHECK:STDERR:    ^~~~~~~\n// CHECK:STDERR: fail_mismatched_too_few_args.carbon:[[@LINE-7]]:1: note: previously declared with parameter count of 1 [RedeclParamCountPrevious]\n// CHECK:STDERR: class Generic(unused T:! type) {\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Generic().TooFew() {}\n\n// --- fail_mismatched_too_many_args.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Generic(T:! type) {\n  fn TooMany();\n}\n\n// CHECK:STDERR: fail_mismatched_too_many_args.carbon:[[@LINE+7]]:4: error: redeclaration differs because of parameter count of 2 [RedeclParamCountDiffers]\n// CHECK:STDERR: fn Generic(unused T:! type, unused U:! type).TooMany() {}\n// CHECK:STDERR:    ^~~~~~~\n// CHECK:STDERR: fail_mismatched_too_many_args.carbon:[[@LINE-7]]:1: note: previously declared with parameter count of 1 [RedeclParamCountPrevious]\n// CHECK:STDERR: class Generic(T:! type) {\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Generic(unused T:! type, unused U:! type).TooMany() {}\n\n// --- fail_mismatched_wrong_arg_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Generic(unused T:! type) {\n  fn WrongType();\n}\n\n// CHECK:STDERR: fail_mismatched_wrong_arg_type.carbon:[[@LINE+7]]:19: error: type `<pattern for ()>` of parameter 1 in redeclaration differs from previous parameter type `<pattern for type>` [RedeclParamDiffersType]\n// CHECK:STDERR: fn Generic(unused T:! ()).WrongType() {}\n// CHECK:STDERR:                   ^\n// CHECK:STDERR: fail_mismatched_wrong_arg_type.carbon:[[@LINE-7]]:22: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n// CHECK:STDERR: class Generic(unused T:! type) {\n// CHECK:STDERR:                      ^\n// CHECK:STDERR:\nfn Generic(unused T:! ()).WrongType() {}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.893: type = pattern_type %Class [symbolic]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G, @Class(%T.035) [symbolic]\n// CHECK:STDOUT:   %Class.G: %Class.G.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %T.binding.as_type} [symbolic]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.n [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %require_complete.904: <witness> = require_complete_type %Class [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_13.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [symbolic = constants.%Class.F] {\n// CHECK:STDOUT:     %n.patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc11_18: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc11: %Copy.type = symbolic_binding T, 0 [symbolic = @Class.%T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.ref.loc11_36: %Copy.type = name_ref T, %T.loc11 [symbolic = %T.loc6 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type.loc11_36: type = facet_access_type %T.ref.loc11_36 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc11_36.2: type = converted %T.ref.loc11_36, %T.as_type.loc11_36 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc11_36.3: Core.Form = init_form %.loc11_36.2 [symbolic = %.loc6_17.1 (constants.%.076a48.2)]\n// CHECK:STDOUT:     %n.param.loc11: @Class.F.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc11_30.1: type = splice_block %.loc11_30.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref.loc11_30: %Copy.type = name_ref T, %T.loc11 [symbolic = %T.loc6 (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc11_30: type = facet_access_type %T.ref.loc11_30 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc11_30.2: type = converted %T.ref.loc11_30, %T.as_type.loc11_30 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %n.loc11: @Class.F.%T.binding.as_type (%T.binding.as_type) = value_binding n, %n.param.loc11\n// CHECK:STDOUT:     %return.param.loc11: ref @Class.F.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:     %return.loc11: ref @Class.F.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param.loc11\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [symbolic = constants.%Class.G] {\n// CHECK:STDOUT:     %self.patt: @Class.G.%pattern_type.loc7_8 (%pattern_type.893) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: @Class.G.%pattern_type.loc7_8 (%pattern_type.893) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @Class.G.%pattern_type.loc7_22 (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @Class.G.%pattern_type.loc7_22 (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_18: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15: %Copy.type = symbolic_binding T, 0 [symbolic = @Class.%T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.ref.loc15: %Copy.type = name_ref T, %T.loc15 [symbolic = %T.loc7 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type.loc15: type = facet_access_type %T.ref.loc15 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc15_44.2: type = converted %T.ref.loc15, %T.as_type.loc15 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc15_44.3: Core.Form = init_form %.loc15_44.2 [symbolic = %.loc7_25.1 (constants.%.076a48.2)]\n// CHECK:STDOUT:     %self.param.loc15: @Class.G.%Class (%Class) = value_param call_param0\n// CHECK:STDOUT:     %.loc15_33.1: type = splice_block %Self.ref.loc15 [symbolic = %Class (constants.%Class)] {\n// CHECK:STDOUT:       %.loc15_33.2: type = specific_constant constants.%Class, @Class(constants.%T.035) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:       %Self.ref.loc15: type = name_ref Self, %.loc15_33.2 [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self.loc15: @Class.G.%Class (%Class) = value_binding self, %self.param.loc15\n// CHECK:STDOUT:     %return.param.loc15: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:     %return.loc15: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param.loc15\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc5_13.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F, @Class(%T.loc5_13.1) [symbolic = %Class.F.type (constants.%Class.F.type)]\n// CHECK:STDOUT:   %Class.F: @Class.%Class.F.type (%Class.F.type) = struct_value () [symbolic = %Class.F (constants.%Class.F)]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G, @Class(%T.loc5_13.1) [symbolic = %Class.G.type (constants.%Class.G.type)]\n// CHECK:STDOUT:   %Class.G: @Class.%Class.G.type (%Class.G.type) = struct_value () [symbolic = %Class.G (constants.%Class.G)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc5_13.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.loc5_13.1) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem)]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: @Class.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.n (constants.%struct_type.n)]\n// CHECK:STDOUT:   %complete_type.loc9_1.2: <witness> = complete_type_witness %struct_type.n [symbolic = %complete_type.loc9_1.2 (constants.%complete_type)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Class.F.decl: @Class.%Class.F.type (%Class.F.type) = fn_decl @Class.F [symbolic = @Class.%Class.F (constants.%Class.F)] {\n// CHECK:STDOUT:       %n.patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = value_binding_pattern n [concrete]\n// CHECK:STDOUT:       %n.param_patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.F.%pattern_type (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref.loc6_17: %Copy.type = name_ref T, @Class.%T.loc5_13.2 [symbolic = %T.loc6 (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc6_17: type = facet_access_type %T.ref.loc6_17 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc6_17.2: type = converted %T.ref.loc6_17, %T.as_type.loc6_17 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc6_17.3: Core.Form = init_form %.loc6_17.2 [symbolic = %.loc6_17.1 (constants.%.076a48.2)]\n// CHECK:STDOUT:       %n.param.loc6: @Class.F.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:       %.loc6_11.1: type = splice_block %.loc6_11.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:         %T.ref.loc6_11: %Copy.type = name_ref T, @Class.%T.loc5_13.2 [symbolic = %T.loc6 (constants.%T.035)]\n// CHECK:STDOUT:         %T.as_type.loc6_11: type = facet_access_type %T.ref.loc6_11 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:         %.loc6_11.2: type = converted %T.ref.loc6_11, %T.as_type.loc6_11 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %n.loc6: @Class.F.%T.binding.as_type (%T.binding.as_type) = value_binding n, %n.param.loc6\n// CHECK:STDOUT:       %return.param.loc6: ref @Class.F.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:       %return.loc6: ref @Class.F.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param.loc6\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Class.G.decl: @Class.%Class.G.type (%Class.G.type) = fn_decl @Class.G [symbolic = @Class.%Class.G (constants.%Class.G)] {\n// CHECK:STDOUT:       %self.patt: @Class.G.%pattern_type.loc7_8 (%pattern_type.893) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Class.G.%pattern_type.loc7_8 (%pattern_type.893) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @Class.G.%pattern_type.loc7_22 (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.G.%pattern_type.loc7_22 (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref.loc7: %Copy.type = name_ref T, @Class.%T.loc5_13.2 [symbolic = %T.loc7 (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc7: type = facet_access_type %T.ref.loc7 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc7_25.2: type = converted %T.ref.loc7, %T.as_type.loc7 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc7_25.3: Core.Form = init_form %.loc7_25.2 [symbolic = %.loc7_25.1 (constants.%.076a48.2)]\n// CHECK:STDOUT:       %self.param.loc7: @Class.G.%Class (%Class) = value_param call_param0\n// CHECK:STDOUT:       %.loc7_14.1: type = splice_block %Self.ref.loc7 [symbolic = %Class (constants.%Class)] {\n// CHECK:STDOUT:         %.loc7_14.2: type = specific_constant constants.%Class, @Class(constants.%T.035) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:         %Self.ref.loc7: type = name_ref Self, %.loc7_14.2 [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self.loc7: @Class.G.%Class (%Class) = value_binding self, %self.param.loc7\n// CHECK:STDOUT:       %return.param.loc7: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:       %return.loc7: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param.loc7\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.ref: %Copy.type = name_ref T, %T.loc5_13.2 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc8_10: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc8_8: @Class.%Class.elem (%Class.elem) = field_decl n, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc9_1.1: <witness> = complete_type_witness constants.%struct_type.n [symbolic = %complete_type.loc9_1.2 (constants.%complete_type)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc9_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %Class.F.decl\n// CHECK:STDOUT:     .G = %Class.G.decl\n// CHECK:STDOUT:     .n = %.loc8_8\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.F(@Class.%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc6: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc6 (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc6 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:   %.loc6_17.1: Core.Form = init_form %T.binding.as_type [symbolic = %.loc6_17.1 (constants.%.076a48.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc6, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.loc6) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc12: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T.loc6 [symbolic = %.loc12 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc12_10.2: @Class.F.%.loc12 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc12_10.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc12_10.2: <specific function> = specific_impl_function %impl.elem0.loc12_10.2, @Copy.WithSelf.Op(%T.loc6) [symbolic = %specific_impl_fn.loc12_10.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%n.param.loc11: @Class.F.%T.binding.as_type (%T.binding.as_type)) -> out %return.param.loc11: @Class.F.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %n.ref: @Class.F.%T.binding.as_type (%T.binding.as_type) = name_ref n, %n.loc11\n// CHECK:STDOUT:     %impl.elem0.loc12_10.1: @Class.F.%.loc12 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc12_10.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc12_10.1: <bound method> = bound_method %n.ref, %impl.elem0.loc12_10.1\n// CHECK:STDOUT:     %specific_impl_fn.loc12_10.1: <specific function> = specific_impl_function %impl.elem0.loc12_10.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc12_10.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc12_10.2: <bound method> = bound_method %n.ref, %specific_impl_fn.loc12_10.1\n// CHECK:STDOUT:     %.loc11_36.1: ref @Class.F.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param.loc11 {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Class.F.%T.binding.as_type (%T.binding.as_type) to %.loc11_36.1 = call %bound_method.loc12_10.2(%n.ref)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param.loc11\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.G(@Class.%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc7: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc7 (constants.%T.035)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.loc7) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %pattern_type.loc7_8: type = pattern_type %Class [symbolic = %pattern_type.loc7_8 (constants.%pattern_type.893)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc7 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %.loc7_25.1: Core.Form = init_form %T.binding.as_type [symbolic = %.loc7_25.1 (constants.%.076a48.2)]\n// CHECK:STDOUT:   %pattern_type.loc7_22: type = pattern_type %T.binding.as_type [symbolic = %pattern_type.loc7_22 (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc15: <witness> = require_complete_type %Class [symbolic = %require_complete.loc15 (constants.%require_complete.904)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.binding.as_type [symbolic = %Class.elem (constants.%Class.elem)]\n// CHECK:STDOUT:   %require_complete.loc16: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc16 (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc7, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.loc7) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc16_14.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T.loc7 [symbolic = %.loc16_14.3 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc16_14.2: @Class.G.%.loc16_14.3 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_14.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc16_14.2: <specific function> = specific_impl_function %impl.elem0.loc16_14.2, @Copy.WithSelf.Op(%T.loc7) [symbolic = %specific_impl_fn.loc16_14.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param.loc15: @Class.G.%Class (%Class)) -> out %return.param.loc15: @Class.G.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %self.ref: @Class.G.%Class (%Class) = name_ref self, %self.loc15\n// CHECK:STDOUT:     %n.ref: @Class.G.%Class.elem (%Class.elem) = name_ref n, @Class.%.loc8_8 [concrete = @Class.%.loc8_8]\n// CHECK:STDOUT:     %.loc16_14.1: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = class_element_access %self.ref, element0\n// CHECK:STDOUT:     %.loc16_14.2: @Class.G.%T.binding.as_type (%T.binding.as_type) = acquire_value %.loc16_14.1\n// CHECK:STDOUT:     %impl.elem0.loc16_14.1: @Class.G.%.loc16_14.3 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc16_14.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc16_14.1: <bound method> = bound_method %.loc16_14.2, %impl.elem0.loc16_14.1\n// CHECK:STDOUT:     %specific_impl_fn.loc16_14.1: <specific function> = specific_impl_function %impl.elem0.loc16_14.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc16_14.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc16_14.2: <bound method> = bound_method %.loc16_14.2, %specific_impl_fn.loc16_14.1\n// CHECK:STDOUT:     %.loc15_44.1: ref @Class.G.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param.loc15 {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Class.G.%T.binding.as_type (%T.binding.as_type) to %.loc15_44.1 = call %bound_method.loc16_14.2(%.loc16_14.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param.loc15\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T.035\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.F.type => constants.%Class.F.type\n// CHECK:STDOUT:   %Class.F => constants.%Class.F\n// CHECK:STDOUT:   %Class.G.type => constants.%Class.G.type\n// CHECK:STDOUT:   %Class.G => constants.%Class.G\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.67c\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem\n// CHECK:STDOUT:   %struct_type.n => constants.%struct_type.n\n// CHECK:STDOUT:   %complete_type.loc9_1.2 => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.F(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc6 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:   %.loc6_17.1 => constants.%.076a48.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.G(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc7 => constants.%T.035\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %pattern_type.loc7_8 => constants.%pattern_type.893\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %.loc7_25.1 => constants.%.076a48.2\n// CHECK:STDOUT:   %pattern_type.loc7_22 => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- nested.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %A.type: type = generic_class_type @A [concrete]\n// CHECK:STDOUT:   %A.generic: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A: type = class_type @A, @A(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %_: %T = symbolic_binding _, 1 [symbolic]\n// CHECK:STDOUT:   %B.type: type = generic_class_type @B, @A(%T) [symbolic]\n// CHECK:STDOUT:   %B.generic: %B.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %B: type = class_type @B, @B(%T, %_) [symbolic]\n// CHECK:STDOUT:   %pattern_type.830: type = pattern_type %B [symbolic]\n// CHECK:STDOUT:   %B.F.type: type = fn_type @B.F, @B(%T, %_) [symbolic]\n// CHECK:STDOUT:   %B.F: %B.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete.7cc: <witness> = require_complete_type %B [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %A.decl: %A.type = class_decl @A [concrete = constants.%A.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_13.1: type = splice_block %.loc5_13.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc5_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc5_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.F.decl: %B.F.type = fn_decl @B.F [symbolic = constants.%B.F] {\n// CHECK:STDOUT:     %self.patt: @B.F.%pattern_type.loc7_10 (%pattern_type.830) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: @B.F.%pattern_type.loc7_10 (%pattern_type.830) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %a.patt: @B.F.%pattern_type.loc7_22 (%pattern_type.51d) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @B.F.%pattern_type.loc7_22 (%pattern_type.51d) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc11_10.1: type = splice_block %.loc11_10.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc11_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc11: type = symbolic_binding T, 0 [symbolic = @A.%T.loc5_9.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc11_22: type = splice_block %T.ref.loc11_22 [symbolic = @B.%T (constants.%T)] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %T.ref.loc11_22: type = name_ref T, %T.loc11 [symbolic = @B.%T (constants.%T)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %_.loc11: @B.%T (%T) = symbolic_binding _, 1 [symbolic = @B.%_.loc6_11.1 (constants.%_)]\n// CHECK:STDOUT:     %self.param.loc11: @B.F.%B (%B) = value_param call_param0\n// CHECK:STDOUT:     %.loc11_40.1: type = splice_block %Self.ref.loc11 [symbolic = %B (constants.%B)] {\n// CHECK:STDOUT:       %.loc11_40.2: type = specific_constant constants.%B, @B(constants.%T, constants.%_) [symbolic = %B (constants.%B)]\n// CHECK:STDOUT:       %Self.ref.loc11: type = name_ref Self, %.loc11_40.2 [symbolic = %B (constants.%B)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self.loc11: @B.F.%B (%B) = value_binding self, %self.param.loc11\n// CHECK:STDOUT:     %a.param.loc11: @B.F.%T.loc7 (%T) = value_param call_param1\n// CHECK:STDOUT:     %T.ref.loc11_56: type = name_ref T, %T.loc11 [symbolic = %T.loc7 (constants.%T)]\n// CHECK:STDOUT:     %a.loc11: @B.F.%T.loc7 (%T) = value_binding a, %a.param.loc11\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @A(%T.loc5_9.2: type) {\n// CHECK:STDOUT:   %T.loc5_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc5_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %B.type: type = generic_class_type @B, @A(%T.loc5_9.1) [symbolic = %B.type (constants.%B.type)]\n// CHECK:STDOUT:   %B.generic: @A.%B.type (%B.type) = struct_value () [symbolic = %B.generic (constants.%B.generic)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %B.decl: @A.%B.type (%B.type) = class_decl @B [symbolic = @A.%B.generic (constants.%B.generic)] {\n// CHECK:STDOUT:       %_.patt: @B.%pattern_type (%pattern_type.51d) = symbolic_binding_pattern _, 1 [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc6: type = splice_block %T.ref [symbolic = %T (constants.%T)] {\n// CHECK:STDOUT:         <elided>\n// CHECK:STDOUT:         %T.ref: type = name_ref T, @A.%T.loc5_9.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %_.loc6_11.2: @B.%T (%T) = symbolic_binding _, 1 [symbolic = %_.loc6_11.1 (constants.%_)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%A\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @B(@A.%T.loc5_9.2: type, %_.loc6_11.2: @B.%T (%T)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %_.loc6_11.1: @B.%T (%T) = symbolic_binding _, 1 [symbolic = %_.loc6_11.1 (constants.%_)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %B.F.type: type = fn_type @B.F, @B(%T, %_.loc6_11.1) [symbolic = %B.F.type (constants.%B.F.type)]\n// CHECK:STDOUT:   %B.F: @B.%B.F.type (%B.F.type) = struct_value () [symbolic = %B.F (constants.%B.F)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %B.F.decl: @B.%B.F.type (%B.F.type) = fn_decl @B.F [symbolic = @B.%B.F (constants.%B.F)] {\n// CHECK:STDOUT:       %self.patt: @B.F.%pattern_type.loc7_10 (%pattern_type.830) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @B.F.%pattern_type.loc7_10 (%pattern_type.830) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %a.patt: @B.F.%pattern_type.loc7_22 (%pattern_type.51d) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:       %a.param_patt: @B.F.%pattern_type.loc7_22 (%pattern_type.51d) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param.loc7: @B.F.%B (%B) = value_param call_param0\n// CHECK:STDOUT:       %.loc7_16.1: type = splice_block %Self.ref.loc7 [symbolic = %B (constants.%B)] {\n// CHECK:STDOUT:         %.loc7_16.2: type = specific_constant constants.%B, @B(constants.%T, constants.%_) [symbolic = %B (constants.%B)]\n// CHECK:STDOUT:         %Self.ref.loc7: type = name_ref Self, %.loc7_16.2 [symbolic = %B (constants.%B)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self.loc7: @B.F.%B (%B) = value_binding self, %self.param.loc7\n// CHECK:STDOUT:       %a.param.loc7: @B.F.%T.loc7 (%T) = value_param call_param1\n// CHECK:STDOUT:       %T.ref.loc7: type = name_ref T, @A.%T.loc5_9.2 [symbolic = %T.loc7 (constants.%T)]\n// CHECK:STDOUT:       %a.loc7: @B.F.%T.loc7 (%T) = value_binding a, %a.param.loc7\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%B\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %B.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @B.F(@A.%T.loc5_9.2: type, @B.%_.loc6_11.2: @B.%T (%T)) {\n// CHECK:STDOUT:   %T.loc7: type = symbolic_binding T, 0 [symbolic = %T.loc7 (constants.%T)]\n// CHECK:STDOUT:   %_.loc7: @B.F.%T.loc7 (%T) = symbolic_binding _, 1 [symbolic = %_.loc7 (constants.%_)]\n// CHECK:STDOUT:   %B: type = class_type @B, @B(%T.loc7, %_.loc7) [symbolic = %B (constants.%B)]\n// CHECK:STDOUT:   %pattern_type.loc7_10: type = pattern_type %B [symbolic = %pattern_type.loc7_10 (constants.%pattern_type.830)]\n// CHECK:STDOUT:   %pattern_type.loc7_22: type = pattern_type %T.loc7 [symbolic = %pattern_type.loc7_22 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc11_38: <witness> = require_complete_type %B [symbolic = %require_complete.loc11_38 (constants.%require_complete.7cc)]\n// CHECK:STDOUT:   %require_complete.loc11_54: <witness> = require_complete_type %T.loc7 [symbolic = %require_complete.loc11_54 (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param.loc11: @B.F.%B (%B), %a.param.loc11: @B.F.%T.loc7 (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%T) {\n// CHECK:STDOUT:   %T.loc5_9.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %B.type => constants.%B.type\n// CHECK:STDOUT:   %B.generic => constants.%B.generic\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B(constants.%T, constants.%_) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %_.loc6_11.1 => constants.%_\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %B.F.type => constants.%B.F.type\n// CHECK:STDOUT:   %B.F => constants.%B.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.F(constants.%T, constants.%_) {\n// CHECK:STDOUT:   %T.loc7 => constants.%T\n// CHECK:STDOUT:   %_.loc7 => constants.%_\n// CHECK:STDOUT:   %B => constants.%B\n// CHECK:STDOUT:   %pattern_type.loc7_10 => constants.%pattern_type.830\n// CHECK:STDOUT:   %pattern_type.loc7_22 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/member_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/member_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/member_type.carbon\n\n// --- class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Outer(T:! Core.Copy) {\n  class Inner {\n    var n: T;\n  }\n\n  fn F(n: T) -> Inner { return {.n = n}; }\n}\n\nfn Test() -> i32 {\n  var c: Outer(i32).Inner = Outer(i32).F(1);\n  return c.n;\n}\n\n// --- interface.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Outer(T:! type) {\n  interface Inner {\n    fn F[self: Self]() -> T;\n  }\n\n  class C {\n    impl as Inner {\n      fn F[self: C]() -> T { return self.(Inner.F)(); }\n    }\n  }\n}\n\nclass D {\n  impl as Outer(i32).Inner {\n    fn F[self: D]() -> i32;\n  }\n}\n\nfn Test() -> i32 {\n  var c: Outer(i32).C = {};\n  return c.(Outer(i32).Inner.F)();\n}\n\n// CHECK:STDOUT: --- class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Outer.type: type = generic_class_type @Outer [concrete]\n// CHECK:STDOUT:   %Outer.generic: %Outer.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Outer.4b9: type = class_type @Outer, @Outer(%T.035) [symbolic]\n// CHECK:STDOUT:   %Inner.bcf: type = class_type @Inner, @Inner(%T.035) [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Inner.elem.f8d: type = unbound_element_type %Inner.bcf, %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %struct_type.n.47a: type = struct_type {.n: %T.binding.as_type} [symbolic]\n// CHECK:STDOUT:   %complete_type.072: <witness> = complete_type_witness %struct_type.n.47a [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.d79: Core.Form = init_form %Inner.bcf [symbolic]\n// CHECK:STDOUT:   %pattern_type.611: type = pattern_type %Inner.bcf [symbolic]\n// CHECK:STDOUT:   %Outer.F.type.2fb: type = fn_type @Outer.F, @Outer(%T.035) [symbolic]\n// CHECK:STDOUT:   %Outer.F.5e3: %Outer.F.type.2fb = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete.e6c: <witness> = require_complete_type %Inner.bcf [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Test.type: type = fn_type @Test [concrete]\n// CHECK:STDOUT:   %Test: %Test.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Outer.a6c: type = class_type @Outer, @Outer(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %Inner.74c: type = class_type @Inner, @Inner(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %Outer.F.type.20b: type = fn_type @Outer.F, @Outer(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %Outer.F.119: %Outer.F.type.20b = struct_value () [concrete]\n// CHECK:STDOUT:   %Inner.elem.34c: type = unbound_element_type %Inner.74c, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.n.033: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n.033 [concrete]\n// CHECK:STDOUT:   %pattern_type.35b: type = pattern_type %Inner.74c [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.006: <witness> = impl_witness imports.%Copy.impl_witness_table.b6d [concrete]\n// CHECK:STDOUT:   %Copy.facet.cdd: %Copy.type = facet_value Core.IntLiteral, (%Copy.impl_witness.006) [concrete]\n// CHECK:STDOUT:   %.42e: Core.Form = init_form %Inner.74c [concrete]\n// CHECK:STDOUT:   %Outer.F.specific_fn: <specific function> = specific_function %Outer.F.119, @Outer.F(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.bb6 = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Copy.impl_witness_table.b6d = impl_witness_table (%Core.import_ref.bb6), @Core.IntLiteral.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Outer = %Outer.decl\n// CHECK:STDOUT:     .Test = %Test.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Outer.decl: %Outer.type = class_decl @Outer [concrete = constants.%Outer.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T.035)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.decl: %Test.type = fn_decl @Test [concrete = constants.%Test] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc12: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc12: Core.Form = init_form %i32.loc12 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Outer(%T.loc4_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc4_13.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T.035)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner: type = class_type @Inner, @Inner(%T.loc4_13.1) [symbolic = %Inner (constants.%Inner.bcf)]\n// CHECK:STDOUT:   %Outer.F.type: type = fn_type @Outer.F, @Outer(%T.loc4_13.1) [symbolic = %Outer.F.type (constants.%Outer.F.type.2fb)]\n// CHECK:STDOUT:   %Outer.F: @Outer.%Outer.F.type (%Outer.F.type.2fb) = struct_value () [symbolic = %Outer.F (constants.%Outer.F.5e3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Inner.decl: type = class_decl @Inner [symbolic = @Outer.%Inner (constants.%Inner.bcf)] {} {}\n// CHECK:STDOUT:     %Outer.F.decl: @Outer.%Outer.F.type (%Outer.F.type.2fb) = fn_decl @Outer.F [symbolic = @Outer.%Outer.F (constants.%Outer.F.5e3)] {\n// CHECK:STDOUT:       %n.patt: @Outer.F.%pattern_type.loc9_8 (%pattern_type.9b9f0c.2) = value_binding_pattern n [concrete]\n// CHECK:STDOUT:       %n.param_patt: @Outer.F.%pattern_type.loc9_8 (%pattern_type.9b9f0c.2) = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @Outer.F.%pattern_type.loc9_14 (%pattern_type.611) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Outer.F.%pattern_type.loc9_14 (%pattern_type.611) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc9_17.2: type = specific_constant @Outer.%Inner.decl, @Outer(constants.%T.035) [symbolic = %Inner (constants.%Inner.bcf)]\n// CHECK:STDOUT:       %Inner.ref: type = name_ref Inner, %.loc9_17.2 [symbolic = %Inner (constants.%Inner.bcf)]\n// CHECK:STDOUT:       %.loc9_17.3: Core.Form = init_form %Inner.ref [symbolic = %.loc9_17.1 (constants.%.d79)]\n// CHECK:STDOUT:       %n.param: @Outer.F.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:       %.loc9_11.1: type = splice_block %.loc9_11.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:         %T.ref: %Copy.type = name_ref T, @Outer.%T.loc4_13.2 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:         %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:         %.loc9_11.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %n: @Outer.F.%T.binding.as_type (%T.binding.as_type) = value_binding n, %n.param\n// CHECK:STDOUT:       %return.param: ref @Outer.F.%Inner (%Inner.bcf) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @Outer.F.%Inner (%Inner.bcf) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Outer.4b9\n// CHECK:STDOUT:     .Inner = %Inner.decl\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %Outer.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Inner(@Outer.%T.loc4_13.2: %Copy.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T: %Copy.type = symbolic_binding T, 0 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Inner: type = class_type @Inner, @Inner(%T) [symbolic = %Inner (constants.%Inner.bcf)]\n// CHECK:STDOUT:   %Inner.elem: type = unbound_element_type %Inner, %T.binding.as_type [symbolic = %Inner.elem (constants.%Inner.elem.f8d)]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: @Inner.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.n (constants.%struct_type.n.47a)]\n// CHECK:STDOUT:   %complete_type.loc7_3.2: <witness> = complete_type_witness %struct_type.n [symbolic = %complete_type.loc7_3.2 (constants.%complete_type.072)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: %Copy.type = name_ref T, @Outer.%T.loc4_13.2 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc6_12: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc6_10: @Inner.%Inner.elem (%Inner.elem.f8d) = field_decl n, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc7_3.1: <witness> = complete_type_witness constants.%struct_type.n.47a [symbolic = %complete_type.loc7_3.2 (constants.%complete_type.072)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc7_3.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Inner.bcf\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .n = %.loc6_10\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Outer.F(@Outer.%T.loc4_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T: %Copy.type = symbolic_binding T, 0 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type.loc9_8: type = pattern_type %T.binding.as_type [symbolic = %pattern_type.loc9_8 (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:   %Inner: type = class_type @Inner, @Inner(%T) [symbolic = %Inner (constants.%Inner.bcf)]\n// CHECK:STDOUT:   %.loc9_17.1: Core.Form = init_form %Inner [symbolic = %.loc9_17.1 (constants.%.d79)]\n// CHECK:STDOUT:   %pattern_type.loc9_14: type = pattern_type %Inner [symbolic = %pattern_type.loc9_14 (constants.%pattern_type.611)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc9_9: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc9_9 (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %require_complete.loc9_17: <witness> = require_complete_type %Inner [symbolic = %require_complete.loc9_17 (constants.%require_complete.e6c)]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: @Outer.F.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.n (constants.%struct_type.n.47a)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc9_38: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T [symbolic = %.loc9_38 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc9_38.2: @Outer.F.%.loc9_38 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_38.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc9_38.2: <specific function> = specific_impl_function %impl.elem0.loc9_38.2, @Copy.WithSelf.Op(%T) [symbolic = %specific_impl_fn.loc9_38.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%n.param: @Outer.F.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @Outer.F.%Inner (%Inner.bcf) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %n.ref: @Outer.F.%T.binding.as_type (%T.binding.as_type) = name_ref n, %n\n// CHECK:STDOUT:     %.loc9_39.1: @Outer.F.%struct_type.n (%struct_type.n.47a) = struct_literal (%n.ref)\n// CHECK:STDOUT:     %impl.elem0.loc9_38.1: @Outer.F.%.loc9_38 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc9_38.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc9_38.1: <bound method> = bound_method %n.ref, %impl.elem0.loc9_38.1\n// CHECK:STDOUT:     %specific_impl_fn.loc9_38.1: <specific function> = specific_impl_function %impl.elem0.loc9_38.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc9_38.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc9_38.2: <bound method> = bound_method %n.ref, %specific_impl_fn.loc9_38.1\n// CHECK:STDOUT:     %.loc9_39.2: ref @Outer.F.%T.binding.as_type (%T.binding.as_type) = class_element_access %return.param, element0\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Outer.F.%T.binding.as_type (%T.binding.as_type) to %.loc9_39.2 = call %bound_method.loc9_38.2(%n.ref)\n// CHECK:STDOUT:     %.loc9_39.3: init @Outer.F.%T.binding.as_type (%T.binding.as_type) to %.loc9_39.2 = in_place_init %Copy.WithSelf.Op.call\n// CHECK:STDOUT:     %.loc9_39.4: init @Outer.F.%Inner (%Inner.bcf) to %return.param = class_init (%.loc9_39.3)\n// CHECK:STDOUT:     %.loc9_40: init @Outer.F.%Inner (%Inner.bcf) = converted %.loc9_39.1, %.loc9_39.4\n// CHECK:STDOUT:     return %.loc9_40 to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.35b = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.35b = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %Inner.74c = var %c.var_patt\n// CHECK:STDOUT:   %Outer.ref.loc13_29: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:   %i32.loc13_35: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %Copy.facet.loc13_38: %Copy.type = facet_value %i32.loc13_35, (constants.%Copy.impl_witness.f17) [concrete = constants.%Copy.facet.de4]\n// CHECK:STDOUT:   %.loc13_38: %Copy.type = converted %i32.loc13_35, %Copy.facet.loc13_38 [concrete = constants.%Copy.facet.de4]\n// CHECK:STDOUT:   %Outer.loc13_38: type = class_type @Outer, @Outer(constants.%Copy.facet.de4) [concrete = constants.%Outer.a6c]\n// CHECK:STDOUT:   %.loc13_39: %Outer.F.type.20b = specific_constant @Outer.%Outer.F.decl, @Outer(constants.%Copy.facet.de4) [concrete = constants.%Outer.F.119]\n// CHECK:STDOUT:   %F.ref: %Outer.F.type.20b = name_ref F, %.loc13_39 [concrete = constants.%Outer.F.119]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %Copy.facet.loc13_43: %Copy.type = facet_value Core.IntLiteral, (constants.%Copy.impl_witness.006) [concrete = constants.%Copy.facet.cdd]\n// CHECK:STDOUT:   %.loc13_43: %Copy.type = converted Core.IntLiteral, %Copy.facet.loc13_43 [concrete = constants.%Copy.facet.cdd]\n// CHECK:STDOUT:   %Outer.F.specific_fn: <specific function> = specific_function %F.ref, @Outer.F(constants.%Copy.facet.de4) [concrete = constants.%Outer.F.specific_fn]\n// CHECK:STDOUT:   %.loc13_3: ref %Inner.74c = splice_block %c.var {}\n// CHECK:STDOUT:   %impl.elem0.loc13: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc13_42.1: <bound method> = bound_method %int_1, %impl.elem0.loc13 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc13: <specific function> = specific_function %impl.elem0.loc13, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_42.2: <bound method> = bound_method %int_1, %specific_fn.loc13 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc13_42.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc13_42.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc13_42.2: %i32 = converted %int_1, %.loc13_42.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %Outer.F.call: init %Inner.74c to %.loc13_3 = call %Outer.F.specific_fn(%.loc13_42.2)\n// CHECK:STDOUT:   assign %c.var, %Outer.F.call\n// CHECK:STDOUT:   %.loc13_20.1: type = splice_block %Inner.ref [concrete = constants.%Inner.74c] {\n// CHECK:STDOUT:     %Outer.ref.loc13_10: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:     %i32.loc13_16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %Copy.facet.loc13_19: %Copy.type = facet_value %i32.loc13_16, (constants.%Copy.impl_witness.f17) [concrete = constants.%Copy.facet.de4]\n// CHECK:STDOUT:     %.loc13_19: %Copy.type = converted %i32.loc13_16, %Copy.facet.loc13_19 [concrete = constants.%Copy.facet.de4]\n// CHECK:STDOUT:     %Outer.loc13_19: type = class_type @Outer, @Outer(constants.%Copy.facet.de4) [concrete = constants.%Outer.a6c]\n// CHECK:STDOUT:     %.loc13_20.2: type = specific_constant @Outer.%Inner.decl, @Outer(constants.%Copy.facet.de4) [concrete = constants.%Inner.74c]\n// CHECK:STDOUT:     %Inner.ref: type = name_ref Inner, %.loc13_20.2 [concrete = constants.%Inner.74c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %Inner.74c = ref_binding c, %c.var\n// CHECK:STDOUT:   %c.ref: ref %Inner.74c = name_ref c, %c\n// CHECK:STDOUT:   %n.ref: %Inner.elem.34c = name_ref n, @Inner.%.loc6_10 [concrete = @Inner.%.loc6_10]\n// CHECK:STDOUT:   %.loc14_11.1: ref %i32 = class_element_access %c.ref, element0\n// CHECK:STDOUT:   %.loc14_11.2: %i32 = acquire_value %.loc14_11.1\n// CHECK:STDOUT:   %impl.elem0.loc14: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc14_11.1: <bound method> = bound_method %.loc14_11.2, %impl.elem0.loc14\n// CHECK:STDOUT:   %specific_fn.loc14: <specific function> = specific_function %impl.elem0.loc14, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_11.2: <bound method> = bound_method %.loc14_11.2, %specific_fn.loc14\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc14_11.2(%.loc14_11.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %c.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%c.var)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Inner.74c) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T.035\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner => constants.%Inner.bcf\n// CHECK:STDOUT:   %Outer.F.type => constants.%Outer.F.type.2fb\n// CHECK:STDOUT:   %Outer.F => constants.%Outer.F.5e3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%T.035) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.67c\n// CHECK:STDOUT:   %Inner => constants.%Inner.bcf\n// CHECK:STDOUT:   %Inner.elem => constants.%Inner.elem.f8d\n// CHECK:STDOUT:   %struct_type.n => constants.%struct_type.n.47a\n// CHECK:STDOUT:   %complete_type.loc7_3.2 => constants.%complete_type.072\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer.F(constants.%T.035) {\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type.loc9_8 => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:   %Inner => constants.%Inner.bcf\n// CHECK:STDOUT:   %.loc9_17.1 => constants.%.d79\n// CHECK:STDOUT:   %pattern_type.loc9_14 => constants.%pattern_type.611\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%Copy.facet.de4) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%Copy.facet.de4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner => constants.%Inner.74c\n// CHECK:STDOUT:   %Outer.F.type => constants.%Outer.F.type.20b\n// CHECK:STDOUT:   %Outer.F => constants.%Outer.F.119\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%Copy.facet.de4) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%Copy.facet.de4\n// CHECK:STDOUT:   %T.binding.as_type => constants.%i32\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %Inner => constants.%Inner.74c\n// CHECK:STDOUT:   %Inner.elem => constants.%Inner.elem.34c\n// CHECK:STDOUT:   %struct_type.n => constants.%struct_type.n.033\n// CHECK:STDOUT:   %complete_type.loc7_3.2 => constants.%complete_type.54b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer.F(constants.%Copy.facet.de4) {\n// CHECK:STDOUT:   %T => constants.%Copy.facet.de4\n// CHECK:STDOUT:   %T.binding.as_type => constants.%i32\n// CHECK:STDOUT:   %pattern_type.loc9_8 => constants.%pattern_type.7ce\n// CHECK:STDOUT:   %Inner => constants.%Inner.74c\n// CHECK:STDOUT:   %.loc9_17.1 => constants.%.42e\n// CHECK:STDOUT:   %pattern_type.loc9_14 => constants.%pattern_type.35b\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc9_9 => constants.%complete_type.f8a\n// CHECK:STDOUT:   %require_complete.loc9_17 => constants.%complete_type.54b\n// CHECK:STDOUT:   %struct_type.n => constants.%struct_type.n.033\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.f17\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.081\n// CHECK:STDOUT:   %.loc9_38 => constants.%.8e2\n// CHECK:STDOUT:   %impl.elem0.loc9_38.2 => constants.%Int.as.Copy.impl.Op.664\n// CHECK:STDOUT:   %specific_impl_fn.loc9_38.2 => constants.%Int.as.Copy.impl.Op.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Outer.type: type = generic_class_type @Outer [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Outer.generic: %Outer.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Outer.387: type = class_type @Outer, @Outer(%T) [symbolic]\n// CHECK:STDOUT:   %Inner.type.6ef: type = facet_type <@Inner, @Inner(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.d55: %Inner.type.6ef = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.534: type = symbolic_binding_type Self, 1, %Self.d55 [symbolic]\n// CHECK:STDOUT:   %pattern_type.72a: type = pattern_type %Self.binding.as_type.534 [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %Inner.WithSelf.F.type.675: type = fn_type @Inner.WithSelf.F, @Inner.WithSelf(%T, %Self.d55) [symbolic]\n// CHECK:STDOUT:   %Inner.WithSelf.F.06f: %Inner.WithSelf.F.type.675 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.assoc_type.be2: type = assoc_entity_type @Inner, @Inner(%T) [symbolic]\n// CHECK:STDOUT:   %assoc0.058: %Inner.assoc_type.be2 = assoc_entity element0, @Inner.WithSelf.%Inner.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %C.131: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %Inner.impl_witness.eb2: <witness> = impl_witness @C.as.Inner.impl.%Inner.impl_witness_table, @C.as.Inner.impl(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.8b6: <witness> = require_complete_type %Inner.type.6ef [symbolic]\n// CHECK:STDOUT:   %pattern_type.fe7: type = pattern_type %C.131 [symbolic]\n// CHECK:STDOUT:   %C.as.Inner.impl.F.type.72e: type = fn_type @C.as.Inner.impl.F, @C.as.Inner.impl(%T) [symbolic]\n// CHECK:STDOUT:   %C.as.Inner.impl.F.28d: %C.as.Inner.impl.F.type.72e = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.facet.921: %Inner.type.6ef = facet_value %C.131, (%Inner.impl_witness.eb2) [symbolic]\n// CHECK:STDOUT:   %Inner.WithSelf.F.type.704: type = fn_type @Inner.WithSelf.F, @Inner.WithSelf(%T, %Inner.facet.921) [symbolic]\n// CHECK:STDOUT:   %Inner.WithSelf.F.118: %Inner.WithSelf.F.type.704 = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete.4fd: <witness> = require_complete_type %C.131 [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %.1f8: require_specific_def_type = require_specific_def @C.as.Inner.impl(%T) [symbolic]\n// CHECK:STDOUT:   %Inner.lookup_impl_witness: <witness> = lookup_impl_witness %C.131, @Inner, @Inner(%T) [symbolic]\n// CHECK:STDOUT:   %Inner.facet.f78: %Inner.type.6ef = facet_value %C.131, (%Inner.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Inner.WithSelf.F.type.d96: type = fn_type @Inner.WithSelf.F, @Inner.WithSelf(%T, %Inner.facet.f78) [symbolic]\n// CHECK:STDOUT:   %Inner.WithSelf.F.66d: %Inner.WithSelf.F.type.d96 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.29b: type = fn_type_with_self_type %Inner.WithSelf.F.type.d96, %Inner.facet.f78 [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.29b = impl_witness_access %Inner.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Inner.WithSelf.F(%T, %Inner.facet.f78) [symbolic]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Outer.d71: type = class_type @Outer, @Outer(%i32) [concrete]\n// CHECK:STDOUT:   %Inner.type.94a: type = facet_type <@Inner, @Inner(%i32)> [concrete]\n// CHECK:STDOUT:   %C.d3f: type = class_type @C, @C(%i32) [concrete]\n// CHECK:STDOUT:   %Inner.impl_witness.667: <witness> = impl_witness @D.as.Inner.impl.%Inner.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.f19: %Inner.type.94a = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Inner.WithSelf.F.type.74d: type = fn_type @Inner.WithSelf.F, @Inner.WithSelf(%i32, %Self.d55) [symbolic]\n// CHECK:STDOUT:   %Inner.WithSelf.F.b36: %Inner.WithSelf.F.type.74d = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.assoc_type.564: type = assoc_entity_type @Inner, @Inner(%i32) [concrete]\n// CHECK:STDOUT:   %assoc0.958: %Inner.assoc_type.564 = assoc_entity element0, @Inner.WithSelf.%Inner.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %pattern_type.9c8: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %D.as.Inner.impl.F.type: type = fn_type @D.as.Inner.impl.F [concrete]\n// CHECK:STDOUT:   %D.as.Inner.impl.F: %D.as.Inner.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Inner.facet.dc9: %Inner.type.94a = facet_value %D, (%Inner.impl_witness.667) [concrete]\n// CHECK:STDOUT:   %Inner.WithSelf.F.type.6b0: type = fn_type @Inner.WithSelf.F, @Inner.WithSelf(%i32, %Inner.facet.dc9) [concrete]\n// CHECK:STDOUT:   %Inner.WithSelf.F.17e: %Inner.WithSelf.F.type.6b0 = struct_value () [concrete]\n// CHECK:STDOUT:   %Test.type: type = fn_type @Test [concrete]\n// CHECK:STDOUT:   %Test: %Test.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %pattern_type.129: type = pattern_type %C.d3f [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C.d3f = struct_value () [concrete]\n// CHECK:STDOUT:   %Inner.impl_witness.d48: <witness> = impl_witness @C.as.Inner.impl.%Inner.impl_witness_table, @C.as.Inner.impl(%i32) [concrete]\n// CHECK:STDOUT:   %complete_type.087: <witness> = complete_type_witness %Inner.type.94a [concrete]\n// CHECK:STDOUT:   %C.as.Inner.impl.F.type.7ce: type = fn_type @C.as.Inner.impl.F, @C.as.Inner.impl(%i32) [concrete]\n// CHECK:STDOUT:   %C.as.Inner.impl.F.356: %C.as.Inner.impl.F.type.7ce = struct_value () [concrete]\n// CHECK:STDOUT:   %.c0b: require_specific_def_type = require_specific_def @C.as.Inner.impl(%i32) [concrete]\n// CHECK:STDOUT:   %Inner.facet.ac9: %Inner.type.94a = facet_value %C.d3f, (%Inner.impl_witness.d48) [concrete]\n// CHECK:STDOUT:   %Inner.WithSelf.F.type.96b: type = fn_type @Inner.WithSelf.F, @Inner.WithSelf(%i32, %Inner.facet.ac9) [concrete]\n// CHECK:STDOUT:   %Inner.WithSelf.F.4b0: %Inner.WithSelf.F.type.96b = struct_value () [concrete]\n// CHECK:STDOUT:   %.fd6: type = fn_type_with_self_type %Inner.WithSelf.F.type.96b, %Inner.facet.ac9 [concrete]\n// CHECK:STDOUT:   %C.as.Inner.impl.F.specific_fn: <specific function> = specific_function %C.as.Inner.impl.F.356, @C.as.Inner.impl.F(%i32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Outer = %Outer.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .Test = %Test.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Outer.decl: %Outer.type = class_decl @Outer [concrete = constants.%Outer.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %Test.decl: %Test.type = fn_decl @Test [concrete = constants.%Test] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc22: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc22: Core.Form = init_form %i32.loc22 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @Inner(@Outer.%T.loc4_13.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Inner.type: type = facet_type <@Inner, @Inner(%T)> [symbolic = %Inner.type (constants.%Inner.type.6ef)]\n// CHECK:STDOUT:   %Self.loc5_19.2: @Inner.%Inner.type (%Inner.type.6ef) = symbolic_binding Self, 1 [symbolic = %Self.loc5_19.2 (constants.%Self.d55)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc5_19.1: @Inner.%Inner.type (%Inner.type.6ef) = symbolic_binding Self, 1 [symbolic = %Self.loc5_19.2 (constants.%Self.d55)]\n// CHECK:STDOUT:     %Inner.WithSelf.decl = interface_with_self_decl @Inner [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %Inner.WithSelf.F.decl: @Inner.WithSelf.%Inner.WithSelf.F.type (%Inner.WithSelf.F.type.675) = fn_decl @Inner.WithSelf.F [symbolic = @Inner.WithSelf.%Inner.WithSelf.F (constants.%Inner.WithSelf.F.06f)] {\n// CHECK:STDOUT:       %self.patt: @Inner.WithSelf.F.%pattern_type.loc6_10 (%pattern_type.72a) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Inner.WithSelf.F.%pattern_type.loc6_10 (%pattern_type.72a) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @Inner.WithSelf.F.%pattern_type.loc6_24 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Inner.WithSelf.F.%pattern_type.loc6_24 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Outer.%T.loc4_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %.loc6_27.2: Core.Form = init_form %T.ref [symbolic = %.loc6_27.1 (constants.%.184)]\n// CHECK:STDOUT:       %self.param: @Inner.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.534) = value_param call_param0\n// CHECK:STDOUT:       %.loc6_16.1: type = splice_block %.loc6_16.3 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.534)] {\n// CHECK:STDOUT:         %.loc6_16.2: @Inner.WithSelf.F.%Inner.type (%Inner.type.6ef) = specific_constant @Inner.%Self.loc5_19.1, @Inner(constants.%T) [symbolic = %Self (constants.%Self.d55)]\n// CHECK:STDOUT:         %Self.ref: @Inner.WithSelf.F.%Inner.type (%Inner.type.6ef) = name_ref Self, %.loc6_16.2 [symbolic = %Self (constants.%Self.d55)]\n// CHECK:STDOUT:         %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.534)]\n// CHECK:STDOUT:         %.loc6_16.3: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.534)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Inner.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.534) = value_binding self, %self.param\n// CHECK:STDOUT:       %return.param: ref @Inner.WithSelf.F.%T (%T) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @Inner.WithSelf.F.%T (%T) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %assoc0.loc6_28.1: @Inner.WithSelf.%Inner.assoc_type (%Inner.assoc_type.be2) = assoc_entity element0, %Inner.WithSelf.F.decl [symbolic = %assoc0.loc6_28.2 (constants.%assoc0.058)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc5_19.1\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = @Inner.WithSelf.%assoc0.loc6_28.1\n// CHECK:STDOUT:     witness = (@Inner.WithSelf.%Inner.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.Inner.impl(@Outer.%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T) [symbolic = %C (constants.%C.131)]\n// CHECK:STDOUT:   %Inner.type: type = facet_type <@Inner, @Inner(%T)> [symbolic = %Inner.type (constants.%Inner.type.6ef)]\n// CHECK:STDOUT:   %Inner.impl_witness.loc10_19.2: <witness> = impl_witness %Inner.impl_witness_table, @C.as.Inner.impl(%T) [symbolic = %Inner.impl_witness.loc10_19.2 (constants.%Inner.impl_witness.eb2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Inner.type [symbolic = %require_complete (constants.%require_complete.8b6)]\n// CHECK:STDOUT:   %C.as.Inner.impl.F.type: type = fn_type @C.as.Inner.impl.F, @C.as.Inner.impl(%T) [symbolic = %C.as.Inner.impl.F.type (constants.%C.as.Inner.impl.F.type.72e)]\n// CHECK:STDOUT:   %C.as.Inner.impl.F: @C.as.Inner.impl.%C.as.Inner.impl.F.type (%C.as.Inner.impl.F.type.72e) = struct_value () [symbolic = %C.as.Inner.impl.F (constants.%C.as.Inner.impl.F.28d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %Self.ref as %Inner.ref {\n// CHECK:STDOUT:     %C.as.Inner.impl.F.decl: @C.as.Inner.impl.%C.as.Inner.impl.F.type (%C.as.Inner.impl.F.type.72e) = fn_decl @C.as.Inner.impl.F [symbolic = @C.as.Inner.impl.%C.as.Inner.impl.F (constants.%C.as.Inner.impl.F.28d)] {\n// CHECK:STDOUT:       %self.patt: @C.as.Inner.impl.F.%pattern_type.loc11_12 (%pattern_type.fe7) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @C.as.Inner.impl.F.%pattern_type.loc11_12 (%pattern_type.fe7) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @C.as.Inner.impl.F.%pattern_type.loc11_23 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @C.as.Inner.impl.F.%pattern_type.loc11_23 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Outer.%T.loc4_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %.loc11_26.3: Core.Form = init_form %T.ref [symbolic = %.loc11_26.2 (constants.%.184)]\n// CHECK:STDOUT:       %self.param: @C.as.Inner.impl.F.%C (%C.131) = value_param call_param0\n// CHECK:STDOUT:       %.loc11_18.1: type = splice_block %C.ref [symbolic = %C (constants.%C.131)] {\n// CHECK:STDOUT:         %.loc11_18.2: type = specific_constant @Outer.%C.decl, @Outer(constants.%T) [symbolic = %C (constants.%C.131)]\n// CHECK:STDOUT:         %C.ref: type = name_ref C, %.loc11_18.2 [symbolic = %C (constants.%C.131)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @C.as.Inner.impl.F.%C (%C.131) = value_binding self, %self.param\n// CHECK:STDOUT:       %return.param: ref @C.as.Inner.impl.F.%T (%T) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @C.as.Inner.impl.F.%T (%T) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Inner.impl_witness_table = impl_witness_table (%C.as.Inner.impl.F.decl), @C.as.Inner.impl [concrete]\n// CHECK:STDOUT:     %Inner.impl_witness.loc10_19.1: <witness> = impl_witness %Inner.impl_witness_table, @C.as.Inner.impl(constants.%T) [symbolic = %Inner.impl_witness.loc10_19.2 (constants.%Inner.impl_witness.eb2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .C = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %C.as.Inner.impl.F.decl\n// CHECK:STDOUT:     .Inner = <poisoned>\n// CHECK:STDOUT:     witness = %Inner.impl_witness.loc10_19.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @D.as.Inner.impl: %Self.ref as %Inner.ref {\n// CHECK:STDOUT:   %D.as.Inner.impl.F.decl: %D.as.Inner.impl.F.type = fn_decl @D.as.Inner.impl.F [concrete = constants.%D.as.Inner.impl.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9c8 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9c8 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc18: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: %D = value_param call_param0\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %self: %D = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Inner.impl_witness_table = impl_witness_table (%D.as.Inner.impl.F.decl), @D.as.Inner.impl [concrete]\n// CHECK:STDOUT:   %Inner.impl_witness: <witness> = impl_witness %Inner.impl_witness_table [concrete = constants.%Inner.impl_witness.667]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .D = <poisoned>\n// CHECK:STDOUT:   .F = %D.as.Inner.impl.F.decl\n// CHECK:STDOUT:   witness = %Inner.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Outer(%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type: type = facet_type <@Inner, @Inner(%T.loc4_13.1)> [symbolic = %Inner.type (constants.%Inner.type.6ef)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T.loc4_13.1) [symbolic = %C (constants.%C.131)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Inner.decl: type = interface_decl @Inner [symbolic = @Outer.%Inner.type (constants.%Inner.type.6ef)] {} {}\n// CHECK:STDOUT:     %C.decl: type = class_decl @C [symbolic = @Outer.%C (constants.%C.131)] {} {}\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Outer.387\n// CHECK:STDOUT:     .Inner = %Inner.decl\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(@Outer.%T.loc4_13.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     impl_decl @C.as.Inner.impl [concrete] {} {\n// CHECK:STDOUT:       %Self.ref: type = name_ref Self, constants.%C.131 [symbolic = %C (constants.%C.131)]\n// CHECK:STDOUT:       %.loc10: type = specific_constant @Outer.%Inner.decl, @Outer(constants.%T) [symbolic = %Inner.type (constants.%Inner.type.6ef)]\n// CHECK:STDOUT:       %Inner.ref: type = name_ref Inner, %.loc10 [symbolic = %Inner.type (constants.%Inner.type.6ef)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.131\n// CHECK:STDOUT:     .Inner = <poisoned>\n// CHECK:STDOUT:     .C = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   impl_decl @D.as.Inner.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%D [concrete = constants.%D]\n// CHECK:STDOUT:     %Outer.ref: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %Outer: type = class_type @Outer, @Outer(constants.%i32) [concrete = constants.%Outer.d71]\n// CHECK:STDOUT:     %.loc17: type = specific_constant @Outer.%Inner.decl, @Outer(constants.%i32) [concrete = constants.%Inner.type.94a]\n// CHECK:STDOUT:     %Inner.ref: type = name_ref Inner, %.loc17 [concrete = constants.%Inner.type.94a]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT:   .Outer = <poisoned>\n// CHECK:STDOUT:   .D = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Inner.WithSelf.F(@Outer.%T.loc4_13.2: type, @Inner.%Self.loc5_19.1: @Inner.%Inner.type (%Inner.type.6ef)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Inner.type: type = facet_type <@Inner, @Inner(%T)> [symbolic = %Inner.type (constants.%Inner.type.6ef)]\n// CHECK:STDOUT:   %Self: @Inner.WithSelf.F.%Inner.type (%Inner.type.6ef) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.d55)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.534)]\n// CHECK:STDOUT:   %pattern_type.loc6_10: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type.loc6_10 (constants.%pattern_type.72a)]\n// CHECK:STDOUT:   %.loc6_27.1: Core.Form = init_form %T [symbolic = %.loc6_27.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc6_24: type = pattern_type %T [symbolic = %pattern_type.loc6_24 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @Inner.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.534)) -> out %return.param: @Inner.WithSelf.F.%T (%T);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @C.as.Inner.impl.F(@Outer.%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T) [symbolic = %C (constants.%C.131)]\n// CHECK:STDOUT:   %pattern_type.loc11_12: type = pattern_type %C [symbolic = %pattern_type.loc11_12 (constants.%pattern_type.fe7)]\n// CHECK:STDOUT:   %.loc11_26.2: Core.Form = init_form %T [symbolic = %.loc11_26.2 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc11_23: type = pattern_type %T [symbolic = %pattern_type.loc11_23 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc11_16: <witness> = require_complete_type %C [symbolic = %require_complete.loc11_16 (constants.%require_complete.4fd)]\n// CHECK:STDOUT:   %require_complete.loc11_26: <witness> = require_complete_type %T [symbolic = %require_complete.loc11_26 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %Inner.type: type = facet_type <@Inner, @Inner(%T)> [symbolic = %Inner.type (constants.%Inner.type.6ef)]\n// CHECK:STDOUT:   %require_complete.loc11_48: <witness> = require_complete_type %Inner.type [symbolic = %require_complete.loc11_48 (constants.%require_complete.8b6)]\n// CHECK:STDOUT:   %Inner.assoc_type: type = assoc_entity_type @Inner, @Inner(%T) [symbolic = %Inner.assoc_type (constants.%Inner.assoc_type.be2)]\n// CHECK:STDOUT:   %assoc0: @C.as.Inner.impl.F.%Inner.assoc_type (%Inner.assoc_type.be2) = assoc_entity element0, @Inner.WithSelf.%Inner.WithSelf.F.decl [symbolic = %assoc0 (constants.%assoc0.058)]\n// CHECK:STDOUT:   %.loc11_41.1: require_specific_def_type = require_specific_def @C.as.Inner.impl(%T) [symbolic = %.loc11_41.1 (constants.%.1f8)]\n// CHECK:STDOUT:   %Inner.lookup_impl_witness: <witness> = lookup_impl_witness %C, @Inner, @Inner(%T) [symbolic = %Inner.lookup_impl_witness (constants.%Inner.lookup_impl_witness)]\n// CHECK:STDOUT:   %Inner.facet: @C.as.Inner.impl.F.%Inner.type (%Inner.type.6ef) = facet_value %C, (%Inner.lookup_impl_witness) [symbolic = %Inner.facet (constants.%Inner.facet.f78)]\n// CHECK:STDOUT:   %Inner.WithSelf.F.type: type = fn_type @Inner.WithSelf.F, @Inner.WithSelf(%T, %Inner.facet) [symbolic = %Inner.WithSelf.F.type (constants.%Inner.WithSelf.F.type.d96)]\n// CHECK:STDOUT:   %.loc11_41.2: type = fn_type_with_self_type %Inner.WithSelf.F.type, %Inner.facet [symbolic = %.loc11_41.2 (constants.%.29b)]\n// CHECK:STDOUT:   %impl.elem0.loc11_41.2: @C.as.Inner.impl.F.%.loc11_41.2 (%.29b) = impl_witness_access %Inner.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_41.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc11_41.2: <specific function> = specific_impl_function %impl.elem0.loc11_41.2, @Inner.WithSelf.F(%T, %Inner.facet) [symbolic = %specific_impl_fn.loc11_41.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @C.as.Inner.impl.F.%C (%C.131)) -> out %return.param: @C.as.Inner.impl.F.%T (%T) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %self.ref: @C.as.Inner.impl.F.%C (%C.131) = name_ref self, %self\n// CHECK:STDOUT:     %.loc11_43: type = specific_constant @Outer.%Inner.decl, @Outer(constants.%T) [symbolic = %Inner.type (constants.%Inner.type.6ef)]\n// CHECK:STDOUT:     %Inner.ref: type = name_ref Inner, %.loc11_43 [symbolic = %Inner.type (constants.%Inner.type.6ef)]\n// CHECK:STDOUT:     %.loc11_48: @C.as.Inner.impl.F.%Inner.assoc_type (%Inner.assoc_type.be2) = specific_constant @Inner.WithSelf.%assoc0.loc6_28.1, @Inner.WithSelf(constants.%T, constants.%Self.d55) [symbolic = %assoc0 (constants.%assoc0.058)]\n// CHECK:STDOUT:     %F.ref: @C.as.Inner.impl.F.%Inner.assoc_type (%Inner.assoc_type.be2) = name_ref F, %.loc11_48 [symbolic = %assoc0 (constants.%assoc0.058)]\n// CHECK:STDOUT:     %impl.elem0.loc11_41.1: @C.as.Inner.impl.F.%.loc11_41.2 (%.29b) = impl_witness_access constants.%Inner.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_41.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %bound_method.loc11_41: <bound method> = bound_method %self.ref, %impl.elem0.loc11_41.1\n// CHECK:STDOUT:     %specific_impl_fn.loc11_41.1: <specific function> = specific_impl_function %impl.elem0.loc11_41.1, @Inner.WithSelf.F(constants.%T, constants.%Inner.facet.f78) [symbolic = %specific_impl_fn.loc11_41.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %bound_method.loc11_52: <bound method> = bound_method %self.ref, %specific_impl_fn.loc11_41.1\n// CHECK:STDOUT:     %.loc11_26.1: ref @C.as.Inner.impl.F.%T (%T) = splice_block %return.param {}\n// CHECK:STDOUT:     %Inner.WithSelf.F.call: init @C.as.Inner.impl.F.%T (%T) to %.loc11_26.1 = call %bound_method.loc11_52(%self.ref)\n// CHECK:STDOUT:     return %Inner.WithSelf.F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @D.as.Inner.impl.F(%self.param: %D) -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.129 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.129 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C.d3f = var %c.var_patt\n// CHECK:STDOUT:   %.loc23_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc23_26.2: init %C.d3f to %c.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc23_3: init %C.d3f = converted %.loc23_26.1, %.loc23_26.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign %c.var, %.loc23_3\n// CHECK:STDOUT:   %.loc23_20.1: type = splice_block %C.ref [concrete = constants.%C.d3f] {\n// CHECK:STDOUT:     %Outer.ref.loc23: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:     %i32.loc23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %Outer.loc23: type = class_type @Outer, @Outer(constants.%i32) [concrete = constants.%Outer.d71]\n// CHECK:STDOUT:     %.loc23_20.2: type = specific_constant @Outer.%C.decl, @Outer(constants.%i32) [concrete = constants.%C.d3f]\n// CHECK:STDOUT:     %C.ref: type = name_ref C, %.loc23_20.2 [concrete = constants.%C.d3f]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %C.d3f = ref_binding c, %c.var\n// CHECK:STDOUT:   %c.ref: ref %C.d3f = name_ref c, %c\n// CHECK:STDOUT:   %Outer.ref.loc24: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:   %i32.loc24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %Outer.loc24: type = class_type @Outer, @Outer(constants.%i32) [concrete = constants.%Outer.d71]\n// CHECK:STDOUT:   %.loc24_23: type = specific_constant @Outer.%Inner.decl, @Outer(constants.%i32) [concrete = constants.%Inner.type.94a]\n// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, %.loc24_23 [concrete = constants.%Inner.type.94a]\n// CHECK:STDOUT:   %.loc24_29: %Inner.assoc_type.564 = specific_constant @Inner.WithSelf.%assoc0.loc6_28.1, @Inner.WithSelf(constants.%i32, constants.%Self.d55) [concrete = constants.%assoc0.958]\n// CHECK:STDOUT:   %F.ref: %Inner.assoc_type.564 = name_ref F, %.loc24_29 [concrete = constants.%assoc0.958]\n// CHECK:STDOUT:   %impl.elem0: %.fd6 = impl_witness_access constants.%Inner.impl_witness.d48, element0 [concrete = constants.%C.as.Inner.impl.F.356]\n// CHECK:STDOUT:   %bound_method.loc24_11: <bound method> = bound_method %c.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @C.as.Inner.impl.F(constants.%i32) [concrete = constants.%C.as.Inner.impl.F.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc24_33: <bound method> = bound_method %c.ref, %specific_fn\n// CHECK:STDOUT:   %.loc24_10: %C.d3f = acquire_value %c.ref\n// CHECK:STDOUT:   %C.as.Inner.impl.F.call: init %i32 = call %bound_method.loc24_33(%.loc24_10)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %c.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%c.var)\n// CHECK:STDOUT:   return %C.as.Inner.impl.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %C.d3f) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.6ef\n// CHECK:STDOUT:   %C => constants.%C.131\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%T) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.6ef\n// CHECK:STDOUT:   %Self.loc5_19.2 => constants.%Self.d55\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf(constants.%T, constants.%Self.d55) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.6ef\n// CHECK:STDOUT:   %Self => constants.%Self.d55\n// CHECK:STDOUT:   %Inner.WithSelf.F.type => constants.%Inner.WithSelf.F.type.675\n// CHECK:STDOUT:   %Inner.WithSelf.F => constants.%Inner.WithSelf.F.06f\n// CHECK:STDOUT:   %Inner.assoc_type => constants.%Inner.assoc_type.be2\n// CHECK:STDOUT:   %assoc0.loc6_28.2 => constants.%assoc0.058\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf.F(constants.%T, constants.%Self.d55) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.6ef\n// CHECK:STDOUT:   %Self => constants.%Self.d55\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.534\n// CHECK:STDOUT:   %pattern_type.loc6_10 => constants.%pattern_type.72a\n// CHECK:STDOUT:   %.loc6_27.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc6_24 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.Inner.impl(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %C => constants.%C.131\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.6ef\n// CHECK:STDOUT:   %Inner.impl_witness.loc10_19.2 => constants.%Inner.impl_witness.eb2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.8b6\n// CHECK:STDOUT:   %C.as.Inner.impl.F.type => constants.%C.as.Inner.impl.F.type.72e\n// CHECK:STDOUT:   %C.as.Inner.impl.F => constants.%C.as.Inner.impl.F.28d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.Inner.impl.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %C => constants.%C.131\n// CHECK:STDOUT:   %pattern_type.loc11_12 => constants.%pattern_type.fe7\n// CHECK:STDOUT:   %.loc11_26.2 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc11_23 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf(constants.%T, constants.%Inner.facet.921) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.6ef\n// CHECK:STDOUT:   %Self => constants.%Inner.facet.921\n// CHECK:STDOUT:   %Inner.WithSelf.F.type => constants.%Inner.WithSelf.F.type.704\n// CHECK:STDOUT:   %Inner.WithSelf.F => constants.%Inner.WithSelf.F.118\n// CHECK:STDOUT:   %Inner.assoc_type => constants.%Inner.assoc_type.be2\n// CHECK:STDOUT:   %assoc0.loc6_28.2 => constants.%assoc0.058\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf.F(constants.%T, constants.%Inner.facet.921) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.6ef\n// CHECK:STDOUT:   %Self => constants.%Inner.facet.921\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C.131\n// CHECK:STDOUT:   %pattern_type.loc6_10 => constants.%pattern_type.fe7\n// CHECK:STDOUT:   %.loc6_27.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc6_24 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf(constants.%T, constants.%Inner.facet.f78) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.6ef\n// CHECK:STDOUT:   %Self => constants.%Inner.facet.f78\n// CHECK:STDOUT:   %Inner.WithSelf.F.type => constants.%Inner.WithSelf.F.type.d96\n// CHECK:STDOUT:   %Inner.WithSelf.F => constants.%Inner.WithSelf.F.66d\n// CHECK:STDOUT:   %Inner.assoc_type => constants.%Inner.assoc_type.be2\n// CHECK:STDOUT:   %assoc0.loc6_28.2 => constants.%assoc0.058\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf.F(constants.%T, constants.%Inner.facet.f78) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.6ef\n// CHECK:STDOUT:   %Self => constants.%Inner.facet.f78\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C.131\n// CHECK:STDOUT:   %pattern_type.loc6_10 => constants.%pattern_type.fe7\n// CHECK:STDOUT:   %.loc6_27.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc6_24 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%i32) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.94a\n// CHECK:STDOUT:   %C => constants.%C.d3f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%i32) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.94a\n// CHECK:STDOUT:   %Self.loc5_19.2 => constants.%Self.f19\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%i32) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf(constants.%i32, constants.%Self.d55) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.94a\n// CHECK:STDOUT:   %Self => constants.%Self.d55\n// CHECK:STDOUT:   %Inner.WithSelf.F.type => constants.%Inner.WithSelf.F.type.74d\n// CHECK:STDOUT:   %Inner.WithSelf.F => constants.%Inner.WithSelf.F.b36\n// CHECK:STDOUT:   %Inner.assoc_type => constants.%Inner.assoc_type.564\n// CHECK:STDOUT:   %assoc0.loc6_28.2 => constants.%assoc0.958\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf(constants.%i32, constants.%Inner.facet.dc9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.94a\n// CHECK:STDOUT:   %Self => constants.%Inner.facet.dc9\n// CHECK:STDOUT:   %Inner.WithSelf.F.type => constants.%Inner.WithSelf.F.type.6b0\n// CHECK:STDOUT:   %Inner.WithSelf.F => constants.%Inner.WithSelf.F.17e\n// CHECK:STDOUT:   %Inner.assoc_type => constants.%Inner.assoc_type.564\n// CHECK:STDOUT:   %assoc0.loc6_28.2 => constants.%assoc0.958\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf.F(constants.%i32, constants.%Inner.facet.dc9) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.94a\n// CHECK:STDOUT:   %Self => constants.%Inner.facet.dc9\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%D\n// CHECK:STDOUT:   %pattern_type.loc6_10 => constants.%pattern_type.9c8\n// CHECK:STDOUT:   %.loc6_27.1 => constants.%.ff5\n// CHECK:STDOUT:   %pattern_type.loc6_24 => constants.%pattern_type.7ce\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.Inner.impl(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:   %C => constants.%C.d3f\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.94a\n// CHECK:STDOUT:   %Inner.impl_witness.loc10_19.2 => constants.%Inner.impl_witness.d48\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.087\n// CHECK:STDOUT:   %C.as.Inner.impl.F.type => constants.%C.as.Inner.impl.F.type.7ce\n// CHECK:STDOUT:   %C.as.Inner.impl.F => constants.%C.as.Inner.impl.F.356\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf(constants.%i32, constants.%Inner.facet.ac9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.94a\n// CHECK:STDOUT:   %Self => constants.%Inner.facet.ac9\n// CHECK:STDOUT:   %Inner.WithSelf.F.type => constants.%Inner.WithSelf.F.type.96b\n// CHECK:STDOUT:   %Inner.WithSelf.F => constants.%Inner.WithSelf.F.4b0\n// CHECK:STDOUT:   %Inner.assoc_type => constants.%Inner.assoc_type.564\n// CHECK:STDOUT:   %assoc0.loc6_28.2 => constants.%assoc0.958\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.Inner.impl.F(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:   %C => constants.%C.d3f\n// CHECK:STDOUT:   %pattern_type.loc11_12 => constants.%pattern_type.129\n// CHECK:STDOUT:   %.loc11_26.2 => constants.%.ff5\n// CHECK:STDOUT:   %pattern_type.loc11_23 => constants.%pattern_type.7ce\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc11_16 => constants.%complete_type.357\n// CHECK:STDOUT:   %require_complete.loc11_26 => constants.%complete_type.f8a\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.94a\n// CHECK:STDOUT:   %require_complete.loc11_48 => constants.%complete_type.087\n// CHECK:STDOUT:   %Inner.assoc_type => constants.%Inner.assoc_type.564\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.958\n// CHECK:STDOUT:   %.loc11_41.1 => constants.%.c0b\n// CHECK:STDOUT:   %Inner.lookup_impl_witness => constants.%Inner.impl_witness.d48\n// CHECK:STDOUT:   %Inner.facet => constants.%Inner.facet.ac9\n// CHECK:STDOUT:   %Inner.WithSelf.F.type => constants.%Inner.WithSelf.F.type.96b\n// CHECK:STDOUT:   %.loc11_41.2 => constants.%.fd6\n// CHECK:STDOUT:   %impl.elem0.loc11_41.2 => constants.%C.as.Inner.impl.F.356\n// CHECK:STDOUT:   %specific_impl_fn.loc11_41.2 => constants.%C.as.Inner.impl.F.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.WithSelf.F(constants.%i32, constants.%Inner.facet.ac9) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.94a\n// CHECK:STDOUT:   %Self => constants.%Inner.facet.ac9\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C.d3f\n// CHECK:STDOUT:   %pattern_type.loc6_10 => constants.%pattern_type.129\n// CHECK:STDOUT:   %.loc6_27.1 => constants.%.ff5\n// CHECK:STDOUT:   %pattern_type.loc6_24 => constants.%pattern_type.7ce\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/method_deduce.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/method_deduce.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/method_deduce.carbon\n\nclass A {}\nclass B {}\n\nclass Class(T:! type) {\n  fn Get(U:! type) -> (T, U) { return Get(U); }\n  fn GetNoDeduce(x: T, U:! type) -> (T, U) { return GetNoDeduce(x, U); }\n}\n\nfn CallGenericMethod(c: Class(A)) -> (A, B) {\n  return c.Get(B);\n}\n\nfn CallGenericMethodWithNonDeducedParam(c: Class(A)) -> (A, B) {\n  return c.GetNoDeduce({}, B);\n}\n\n// CHECK:STDOUT: --- method_deduce.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.0db: type = class_type @Class, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.4b9: %tuple.type.24b = tuple_value (%T, %U) [symbolic]\n// CHECK:STDOUT:   %tuple.type.a5e: type = tuple_type (%T, %U) [symbolic]\n// CHECK:STDOUT:   %.f18: Core.Form = init_form %tuple.type.a5e [symbolic]\n// CHECK:STDOUT:   %pattern_type.eee: type = pattern_type %tuple.type.a5e [symbolic]\n// CHECK:STDOUT:   %Class.Get.type.ab7: type = fn_type @Class.Get, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %Class.Get.ecd: %Class.Get.type.ab7 = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %Class.GetNoDeduce.type.cf2: type = fn_type @Class.GetNoDeduce, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %Class.GetNoDeduce.1a5: %Class.GetNoDeduce.type.cf2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.220: <witness> = require_complete_type %tuple.type.a5e [symbolic]\n// CHECK:STDOUT:   %Class.Get.specific_fn.f51: <specific function> = specific_function %Class.Get.ecd, @Class.Get(%T, %U) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %Class.GetNoDeduce.specific_fn.710: <specific function> = specific_function %Class.GetNoDeduce.1a5, @Class.GetNoDeduce(%T, %U) [symbolic]\n// CHECK:STDOUT:   %Class.802: type = class_type @Class, @Class(%A) [concrete]\n// CHECK:STDOUT:   %pattern_type.36c: type = pattern_type %Class.802 [concrete]\n// CHECK:STDOUT:   %tuple.5bc: %tuple.type.24b = tuple_value (%A, %B) [concrete]\n// CHECK:STDOUT:   %tuple.type.e87: type = tuple_type (%A, %B) [concrete]\n// CHECK:STDOUT:   %.3aa: Core.Form = init_form %tuple.type.e87 [concrete]\n// CHECK:STDOUT:   %pattern_type.b74: type = pattern_type %tuple.type.e87 [concrete]\n// CHECK:STDOUT:   %CallGenericMethod.type: type = fn_type @CallGenericMethod [concrete]\n// CHECK:STDOUT:   %CallGenericMethod: %CallGenericMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.Get.type.a01: type = fn_type @Class.Get, @Class(%A) [concrete]\n// CHECK:STDOUT:   %Class.Get.5f3: %Class.Get.type.a01 = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.GetNoDeduce.type.902: type = fn_type @Class.GetNoDeduce, @Class(%A) [concrete]\n// CHECK:STDOUT:   %Class.GetNoDeduce.472: %Class.GetNoDeduce.type.902 = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.Get.specific_fn.54d: <specific function> = specific_function %Class.Get.5f3, @Class.Get(%A, %B) [concrete]\n// CHECK:STDOUT:   %CallGenericMethodWithNonDeducedParam.type: type = fn_type @CallGenericMethodWithNonDeducedParam [concrete]\n// CHECK:STDOUT:   %CallGenericMethodWithNonDeducedParam: %CallGenericMethodWithNonDeducedParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %Class.GetNoDeduce.specific_fn.83b: <specific function> = specific_function %Class.GetNoDeduce.472, @Class.GetNoDeduce(%A, %B) [concrete]\n// CHECK:STDOUT:   %A.val: %A = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.f71: <witness> = complete_type_witness %tuple.type.e87 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .CallGenericMethod = %CallGenericMethod.decl\n// CHECK:STDOUT:     .CallGenericMethodWithNonDeducedParam = %CallGenericMethodWithNonDeducedParam.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc18_17.1: type = splice_block %.loc18_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc18_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc18_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc18_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallGenericMethod.decl: %CallGenericMethod.type = fn_decl @CallGenericMethod [concrete = constants.%CallGenericMethod] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.36c = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.36c = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.b74 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.b74 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %A.ref.loc23_39: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:     %B.ref.loc23: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:     %.loc23_43.2: %tuple.type.24b = tuple_literal (%A.ref.loc23_39, %B.ref.loc23) [concrete = constants.%tuple.5bc]\n// CHECK:STDOUT:     %.loc23_43.3: type = converted %.loc23_43.2, constants.%tuple.type.e87 [concrete = constants.%tuple.type.e87]\n// CHECK:STDOUT:     %.loc23_43.4: Core.Form = init_form %.loc23_43.3 [concrete = constants.%.3aa]\n// CHECK:STDOUT:     %c.param: %Class.802 = value_param call_param0\n// CHECK:STDOUT:     %.loc23_32: type = splice_block %Class [concrete = constants.%Class.802] {\n// CHECK:STDOUT:       %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:       %A.ref.loc23_31: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:       %Class: type = class_type @Class, @Class(constants.%A) [concrete = constants.%Class.802]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %Class.802 = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %tuple.type.e87 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %tuple.type.e87 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallGenericMethodWithNonDeducedParam.decl: %CallGenericMethodWithNonDeducedParam.type = fn_decl @CallGenericMethodWithNonDeducedParam [concrete = constants.%CallGenericMethodWithNonDeducedParam] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.36c = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.36c = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.b74 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.b74 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %A.ref.loc27_58: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:     %B.ref.loc27: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:     %.loc27_62.2: %tuple.type.24b = tuple_literal (%A.ref.loc27_58, %B.ref.loc27) [concrete = constants.%tuple.5bc]\n// CHECK:STDOUT:     %.loc27_62.3: type = converted %.loc27_62.2, constants.%tuple.type.e87 [concrete = constants.%tuple.type.e87]\n// CHECK:STDOUT:     %.loc27_62.4: Core.Form = init_form %.loc27_62.3 [concrete = constants.%.3aa]\n// CHECK:STDOUT:     %c.param: %Class.802 = value_param call_param0\n// CHECK:STDOUT:     %.loc27_51: type = splice_block %Class [concrete = constants.%Class.802] {\n// CHECK:STDOUT:       %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:       %A.ref.loc27_50: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:       %Class: type = class_type @Class, @Class(constants.%A) [concrete = constants.%Class.802]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %Class.802 = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %tuple.type.e87 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %tuple.type.e87 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc18_13.2: type) {\n// CHECK:STDOUT:   %T.loc18_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc18_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.Get.type: type = fn_type @Class.Get, @Class(%T.loc18_13.1) [symbolic = %Class.Get.type (constants.%Class.Get.type.ab7)]\n// CHECK:STDOUT:   %Class.Get: @Class.%Class.Get.type (%Class.Get.type.ab7) = struct_value () [symbolic = %Class.Get (constants.%Class.Get.ecd)]\n// CHECK:STDOUT:   %Class.GetNoDeduce.type: type = fn_type @Class.GetNoDeduce, @Class(%T.loc18_13.1) [symbolic = %Class.GetNoDeduce.type (constants.%Class.GetNoDeduce.type.cf2)]\n// CHECK:STDOUT:   %Class.GetNoDeduce: @Class.%Class.GetNoDeduce.type (%Class.GetNoDeduce.type.cf2) = struct_value () [symbolic = %Class.GetNoDeduce (constants.%Class.GetNoDeduce.1a5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Class.Get.decl: @Class.%Class.Get.type (%Class.Get.type.ab7) = fn_decl @Class.Get [symbolic = @Class.%Class.Get (constants.%Class.Get.ecd)] {\n// CHECK:STDOUT:       %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:       %return.patt: @Class.Get.%pattern_type (%pattern_type.eee) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.Get.%pattern_type (%pattern_type.eee) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Class.%T.loc18_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %U.ref.loc19_27: type = name_ref U, %U.loc19_10.2 [symbolic = %U.loc19_10.1 (constants.%U)]\n// CHECK:STDOUT:       %.loc19_28.3: %tuple.type.24b = tuple_literal (%T.ref, %U.ref.loc19_27) [symbolic = %tuple (constants.%tuple.4b9)]\n// CHECK:STDOUT:       %.loc19_28.4: type = converted %.loc19_28.3, constants.%tuple.type.a5e [symbolic = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:       %.loc19_28.5: Core.Form = init_form %.loc19_28.4 [symbolic = %.loc19_28.2 (constants.%.f18)]\n// CHECK:STDOUT:       %.loc19_14.1: type = splice_block %.loc19_14.2 [concrete = type] {\n// CHECK:STDOUT:         %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:         %.loc19_14.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %U.loc19_10.2: type = symbolic_binding U, 1 [symbolic = %U.loc19_10.1 (constants.%U)]\n// CHECK:STDOUT:       %return.param: ref @Class.Get.%tuple.type (%tuple.type.a5e) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @Class.Get.%tuple.type (%tuple.type.a5e) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Class.GetNoDeduce.decl: @Class.%Class.GetNoDeduce.type (%Class.GetNoDeduce.type.cf2) = fn_decl @Class.GetNoDeduce [symbolic = @Class.%Class.GetNoDeduce (constants.%Class.GetNoDeduce.1a5)] {\n// CHECK:STDOUT:       %x.patt: @Class.GetNoDeduce.%pattern_type.loc20_18 (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:       %x.param_patt: @Class.GetNoDeduce.%pattern_type.loc20_18 (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:       %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:       %return.patt: @Class.GetNoDeduce.%pattern_type.loc20_34 (%pattern_type.eee) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.GetNoDeduce.%pattern_type.loc20_34 (%pattern_type.eee) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref.loc20_38: type = name_ref T, @Class.%T.loc18_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %U.ref.loc20_41: type = name_ref U, %U.loc20_24.2 [symbolic = %U.loc20_24.1 (constants.%U)]\n// CHECK:STDOUT:       %.loc20_42.3: %tuple.type.24b = tuple_literal (%T.ref.loc20_38, %U.ref.loc20_41) [symbolic = %tuple (constants.%tuple.4b9)]\n// CHECK:STDOUT:       %.loc20_42.4: type = converted %.loc20_42.3, constants.%tuple.type.a5e [symbolic = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:       %.loc20_42.5: Core.Form = init_form %.loc20_42.4 [symbolic = %.loc20_42.2 (constants.%.f18)]\n// CHECK:STDOUT:       %x.param: @Class.GetNoDeduce.%T (%T) = value_param call_param0\n// CHECK:STDOUT:       %T.ref.loc20_21: type = name_ref T, @Class.%T.loc18_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %x: @Class.GetNoDeduce.%T (%T) = value_binding x, %x.param\n// CHECK:STDOUT:       %.loc20_28.1: type = splice_block %.loc20_28.2 [concrete = type] {\n// CHECK:STDOUT:         %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:         %.loc20_28.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %U.loc20_24.2: type = symbolic_binding U, 1 [symbolic = %U.loc20_24.1 (constants.%U)]\n// CHECK:STDOUT:       %return.param: ref @Class.GetNoDeduce.%tuple.type (%tuple.type.a5e) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @Class.GetNoDeduce.%tuple.type (%tuple.type.a5e) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class.0db\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .Get = %Class.Get.decl\n// CHECK:STDOUT:     .GetNoDeduce = %Class.GetNoDeduce.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.Get(@Class.%T.loc18_13.2: type, %U.loc19_10.2: type) {\n// CHECK:STDOUT:   %U.loc19_10.1: type = symbolic_binding U, 1 [symbolic = %U.loc19_10.1 (constants.%U)]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%T, %U.loc19_10.1) [symbolic = %tuple (constants.%tuple.4b9)]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%T, %U.loc19_10.1) [symbolic = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:   %.loc19_28.2: Core.Form = init_form %tuple.type [symbolic = %.loc19_28.2 (constants.%.f18)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %tuple.type [symbolic = %pattern_type (constants.%pattern_type.eee)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %tuple.type [symbolic = %require_complete (constants.%require_complete.220)]\n// CHECK:STDOUT:   %Class.Get.type: type = fn_type @Class.Get, @Class(%T) [symbolic = %Class.Get.type (constants.%Class.Get.type.ab7)]\n// CHECK:STDOUT:   %Class.Get: @Class.Get.%Class.Get.type (%Class.Get.type.ab7) = struct_value () [symbolic = %Class.Get (constants.%Class.Get.ecd)]\n// CHECK:STDOUT:   %Class.Get.specific_fn.loc19_39.2: <specific function> = specific_function %Class.Get, @Class.Get(%T, %U.loc19_10.1) [symbolic = %Class.Get.specific_fn.loc19_39.2 (constants.%Class.Get.specific_fn.f51)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Class.Get.%tuple.type (%tuple.type.a5e) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc19_39: @Class.Get.%Class.Get.type (%Class.Get.type.ab7) = specific_constant @Class.%Class.Get.decl, @Class(constants.%T) [symbolic = %Class.Get (constants.%Class.Get.ecd)]\n// CHECK:STDOUT:     %Get.ref: @Class.Get.%Class.Get.type (%Class.Get.type.ab7) = name_ref Get, %.loc19_39 [symbolic = %Class.Get (constants.%Class.Get.ecd)]\n// CHECK:STDOUT:     %U.ref.loc19_43: type = name_ref U, %U.loc19_10.2 [symbolic = %U.loc19_10.1 (constants.%U)]\n// CHECK:STDOUT:     %Class.Get.specific_fn.loc19_39.1: <specific function> = specific_function %Get.ref, @Class.Get(constants.%T, constants.%U) [symbolic = %Class.Get.specific_fn.loc19_39.2 (constants.%Class.Get.specific_fn.f51)]\n// CHECK:STDOUT:     %.loc19_28.1: ref @Class.Get.%tuple.type (%tuple.type.a5e) = splice_block %return.param {}\n// CHECK:STDOUT:     %Class.Get.call: init @Class.Get.%tuple.type (%tuple.type.a5e) to %.loc19_28.1 = call %Class.Get.specific_fn.loc19_39.1()\n// CHECK:STDOUT:     return %Class.Get.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.GetNoDeduce(@Class.%T.loc18_13.2: type, %U.loc20_24.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %pattern_type.loc20_18: type = pattern_type %T [symbolic = %pattern_type.loc20_18 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:   %U.loc20_24.1: type = symbolic_binding U, 1 [symbolic = %U.loc20_24.1 (constants.%U)]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%T, %U.loc20_24.1) [symbolic = %tuple (constants.%tuple.4b9)]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%T, %U.loc20_24.1) [symbolic = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:   %.loc20_42.2: Core.Form = init_form %tuple.type [symbolic = %.loc20_42.2 (constants.%.f18)]\n// CHECK:STDOUT:   %pattern_type.loc20_34: type = pattern_type %tuple.type [symbolic = %pattern_type.loc20_34 (constants.%pattern_type.eee)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %Class.GetNoDeduce.type: type = fn_type @Class.GetNoDeduce, @Class(%T) [symbolic = %Class.GetNoDeduce.type (constants.%Class.GetNoDeduce.type.cf2)]\n// CHECK:STDOUT:   %Class.GetNoDeduce: @Class.GetNoDeduce.%Class.GetNoDeduce.type (%Class.GetNoDeduce.type.cf2) = struct_value () [symbolic = %Class.GetNoDeduce (constants.%Class.GetNoDeduce.1a5)]\n// CHECK:STDOUT:   %Class.GetNoDeduce.specific_fn.loc20_53.2: <specific function> = specific_function %Class.GetNoDeduce, @Class.GetNoDeduce(%T, %U.loc20_24.1) [symbolic = %Class.GetNoDeduce.specific_fn.loc20_53.2 (constants.%Class.GetNoDeduce.specific_fn.710)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @Class.GetNoDeduce.%T (%T)) -> out %return.param: @Class.GetNoDeduce.%tuple.type (%tuple.type.a5e) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc20_53: @Class.GetNoDeduce.%Class.GetNoDeduce.type (%Class.GetNoDeduce.type.cf2) = specific_constant @Class.%Class.GetNoDeduce.decl, @Class(constants.%T) [symbolic = %Class.GetNoDeduce (constants.%Class.GetNoDeduce.1a5)]\n// CHECK:STDOUT:     %GetNoDeduce.ref: @Class.GetNoDeduce.%Class.GetNoDeduce.type (%Class.GetNoDeduce.type.cf2) = name_ref GetNoDeduce, %.loc20_53 [symbolic = %Class.GetNoDeduce (constants.%Class.GetNoDeduce.1a5)]\n// CHECK:STDOUT:     %x.ref: @Class.GetNoDeduce.%T (%T) = name_ref x, %x\n// CHECK:STDOUT:     %U.ref.loc20_68: type = name_ref U, %U.loc20_24.2 [symbolic = %U.loc20_24.1 (constants.%U)]\n// CHECK:STDOUT:     %Class.GetNoDeduce.specific_fn.loc20_53.1: <specific function> = specific_function %GetNoDeduce.ref, @Class.GetNoDeduce(constants.%T, constants.%U) [symbolic = %Class.GetNoDeduce.specific_fn.loc20_53.2 (constants.%Class.GetNoDeduce.specific_fn.710)]\n// CHECK:STDOUT:     %.loc20_42.1: ref @Class.GetNoDeduce.%tuple.type (%tuple.type.a5e) = splice_block %return.param {}\n// CHECK:STDOUT:     %Class.GetNoDeduce.call: init @Class.GetNoDeduce.%tuple.type (%tuple.type.a5e) to %.loc20_42.1 = call %Class.GetNoDeduce.specific_fn.loc20_53.1(%x.ref)\n// CHECK:STDOUT:     return %Class.GetNoDeduce.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallGenericMethod(%c.param: %Class.802) -> out %return.param: %tuple.type.e87 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %Class.802 = name_ref c, %c\n// CHECK:STDOUT:   %.loc24: %Class.Get.type.a01 = specific_constant @Class.%Class.Get.decl, @Class(constants.%A) [concrete = constants.%Class.Get.5f3]\n// CHECK:STDOUT:   %Get.ref: %Class.Get.type.a01 = name_ref Get, %.loc24 [concrete = constants.%Class.Get.5f3]\n// CHECK:STDOUT:   %B.ref.loc24: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %Class.Get.specific_fn: <specific function> = specific_function %Get.ref, @Class.Get(constants.%A, constants.%B) [concrete = constants.%Class.Get.specific_fn.54d]\n// CHECK:STDOUT:   %.loc23_43.1: ref %tuple.type.e87 = splice_block %return.param {}\n// CHECK:STDOUT:   %Class.Get.call: init %tuple.type.e87 to %.loc23_43.1 = call %Class.Get.specific_fn()\n// CHECK:STDOUT:   return %Class.Get.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallGenericMethodWithNonDeducedParam(%c.param: %Class.802) -> out %return.param: %tuple.type.e87 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %Class.802 = name_ref c, %c\n// CHECK:STDOUT:   %.loc28_11: %Class.GetNoDeduce.type.902 = specific_constant @Class.%Class.GetNoDeduce.decl, @Class(constants.%A) [concrete = constants.%Class.GetNoDeduce.472]\n// CHECK:STDOUT:   %GetNoDeduce.ref: %Class.GetNoDeduce.type.902 = name_ref GetNoDeduce, %.loc28_11 [concrete = constants.%Class.GetNoDeduce.472]\n// CHECK:STDOUT:   %.loc28_25.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %B.ref.loc28: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %Class.GetNoDeduce.specific_fn: <specific function> = specific_function %GetNoDeduce.ref, @Class.GetNoDeduce(constants.%A, constants.%B) [concrete = constants.%Class.GetNoDeduce.specific_fn.83b]\n// CHECK:STDOUT:   %.loc27_62.1: ref %tuple.type.e87 = splice_block %return.param {}\n// CHECK:STDOUT:   %.loc28_25.2: ref %A = temporary_storage\n// CHECK:STDOUT:   %.loc28_25.3: init %A to %.loc28_25.2 = class_init () [concrete = constants.%A.val]\n// CHECK:STDOUT:   %.loc28_25.4: init %A = converted %.loc28_25.1, %.loc28_25.3 [concrete = constants.%A.val]\n// CHECK:STDOUT:   %.loc28_25.5: ref %A = temporary %.loc28_25.2, %.loc28_25.4\n// CHECK:STDOUT:   %.loc28_25.6: %A = acquire_value %.loc28_25.5\n// CHECK:STDOUT:   %Class.GetNoDeduce.call: init %tuple.type.e87 to %.loc27_62.1 = call %Class.GetNoDeduce.specific_fn(%.loc28_25.6)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc28_25.5, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc28_25.5)\n// CHECK:STDOUT:   return %Class.GetNoDeduce.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %A) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T) {\n// CHECK:STDOUT:   %T.loc18_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.Get.type => constants.%Class.Get.type.ab7\n// CHECK:STDOUT:   %Class.Get => constants.%Class.Get.ecd\n// CHECK:STDOUT:   %Class.GetNoDeduce.type => constants.%Class.GetNoDeduce.type.cf2\n// CHECK:STDOUT:   %Class.GetNoDeduce => constants.%Class.GetNoDeduce.1a5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.Get(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %U.loc19_10.1 => constants.%U\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %tuple => constants.%tuple.4b9\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.a5e\n// CHECK:STDOUT:   %.loc19_28.2 => constants.%.f18\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.eee\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.220\n// CHECK:STDOUT:   %Class.Get.type => constants.%Class.Get.type.ab7\n// CHECK:STDOUT:   %Class.Get => constants.%Class.Get.ecd\n// CHECK:STDOUT:   %Class.Get.specific_fn.loc19_39.2 => constants.%Class.Get.specific_fn.f51\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.GetNoDeduce(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %pattern_type.loc20_18 => constants.%pattern_type.51d\n// CHECK:STDOUT:   %U.loc20_24.1 => constants.%U\n// CHECK:STDOUT:   %tuple => constants.%tuple.4b9\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.a5e\n// CHECK:STDOUT:   %.loc20_42.2 => constants.%.f18\n// CHECK:STDOUT:   %pattern_type.loc20_34 => constants.%pattern_type.eee\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.944\n// CHECK:STDOUT:   %Class.GetNoDeduce.type => constants.%Class.GetNoDeduce.type.cf2\n// CHECK:STDOUT:   %Class.GetNoDeduce => constants.%Class.GetNoDeduce.1a5\n// CHECK:STDOUT:   %Class.GetNoDeduce.specific_fn.loc20_53.2 => constants.%Class.GetNoDeduce.specific_fn.710\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%A) {\n// CHECK:STDOUT:   %T.loc18_13.1 => constants.%A\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.Get.type => constants.%Class.Get.type.a01\n// CHECK:STDOUT:   %Class.Get => constants.%Class.Get.5f3\n// CHECK:STDOUT:   %Class.GetNoDeduce.type => constants.%Class.GetNoDeduce.type.902\n// CHECK:STDOUT:   %Class.GetNoDeduce => constants.%Class.GetNoDeduce.472\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.Get(constants.%A, constants.%B) {\n// CHECK:STDOUT:   %U.loc19_10.1 => constants.%B\n// CHECK:STDOUT:   %T => constants.%A\n// CHECK:STDOUT:   %tuple => constants.%tuple.5bc\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.e87\n// CHECK:STDOUT:   %.loc19_28.2 => constants.%.3aa\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.b74\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f71\n// CHECK:STDOUT:   %Class.Get.type => constants.%Class.Get.type.a01\n// CHECK:STDOUT:   %Class.Get => constants.%Class.Get.5f3\n// CHECK:STDOUT:   %Class.Get.specific_fn.loc19_39.2 => constants.%Class.Get.specific_fn.54d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.GetNoDeduce(constants.%A, constants.%B) {\n// CHECK:STDOUT:   %T => constants.%A\n// CHECK:STDOUT:   %pattern_type.loc20_18 => constants.%pattern_type.1ab\n// CHECK:STDOUT:   %U.loc20_24.1 => constants.%B\n// CHECK:STDOUT:   %tuple => constants.%tuple.5bc\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.e87\n// CHECK:STDOUT:   %.loc20_42.2 => constants.%.3aa\n// CHECK:STDOUT:   %pattern_type.loc20_34 => constants.%pattern_type.b74\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.357\n// CHECK:STDOUT:   %Class.GetNoDeduce.type => constants.%Class.GetNoDeduce.type.902\n// CHECK:STDOUT:   %Class.GetNoDeduce => constants.%Class.GetNoDeduce.472\n// CHECK:STDOUT:   %Class.GetNoDeduce.specific_fn.loc20_53.2 => constants.%Class.GetNoDeduce.specific_fn.83b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/redeclare.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/redeclare.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/redeclare.carbon\n\n// --- valid.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Generic(T:! type);\n\nclass Generic(T:! type) {\n}\n\n// --- fail_mismatch_param_list.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A;\n// CHECK:STDERR: fail_mismatch_param_list.carbon:[[@LINE+7]]:1: error: redeclaration differs because of parameter list [RedeclParamListDiffers]\n// CHECK:STDERR: class A(T:! type) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_mismatch_param_list.carbon:[[@LINE-4]]:1: note: previously declared without parameter list [RedeclParamListPrevious]\n// CHECK:STDERR: class A;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nclass A(T:! type) {}\n\n// --- fail_mismatch_implicit_param_list.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {}\n\nclass B(N:! A);\n// CHECK:STDERR: fail_mismatch_implicit_param_list.carbon:[[@LINE+7]]:1: error: redeclaration differs because of implicit parameter list [RedeclParamListDiffers]\n// CHECK:STDERR: class B[T:! type](N:! T) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_mismatch_implicit_param_list.carbon:[[@LINE-4]]:1: note: previously declared without implicit parameter list [RedeclParamListPrevious]\n// CHECK:STDERR: class B(N:! A);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nclass B[T:! type](N:! T) {}\n\n// --- fail_mismatch_param_count.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {}\n\nclass C(T:! type);\n// CHECK:STDERR: fail_mismatch_param_count.carbon:[[@LINE+7]]:1: error: redeclaration differs because of parameter count of 2 [RedeclParamCountDiffers]\n// CHECK:STDERR: class C(T:! type, U:! A) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_mismatch_param_count.carbon:[[@LINE-4]]:1: note: previously declared with parameter count of 1 [RedeclParamCountPrevious]\n// CHECK:STDERR: class C(T:! type);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nclass C(T:! type, U:! A) {}\n\n// --- fail_mismatch_param_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {}\n\nclass D(T:! type);\n// CHECK:STDERR: fail_mismatch_param_type.carbon:[[@LINE+7]]:9: error: type `<pattern for A>` of parameter 1 in redeclaration differs from previous parameter type `<pattern for type>` [RedeclParamDiffersType]\n// CHECK:STDERR: class D(T:! A) {}\n// CHECK:STDERR:         ^\n// CHECK:STDERR: fail_mismatch_param_type.carbon:[[@LINE-4]]:9: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n// CHECK:STDERR: class D(T:! type);\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nclass D(T:! A) {}\n\n// --- fail_mismatch_param_name.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass E(T:! type);\n// CHECK:STDERR: fail_mismatch_param_name.carbon:[[@LINE+7]]:9: error: redeclaration differs at parameter 1 [RedeclParamDiffers]\n// CHECK:STDERR: class E(U:! type) {}\n// CHECK:STDERR:         ^\n// CHECK:STDERR: fail_mismatch_param_name.carbon:[[@LINE-4]]:9: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n// CHECK:STDERR: class E(T:! type);\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nclass E(U:! type) {}\n\n// CHECK:STDOUT: --- valid.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type: type = generic_class_type @Generic [concrete]\n// CHECK:STDOUT:   %Generic.generic: %Generic.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic: type = class_type @Generic, @Generic(%T) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Generic = %Generic.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Generic.decl.loc4: %Generic.type = class_decl @Generic [concrete = constants.%Generic.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Generic.decl.loc6: %Generic.type = class_decl @Generic [concrete = constants.%Generic.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_19.1: type = splice_block %.loc6_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Generic(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Generic\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_mismatch_param_list.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.f82: type = class_type @A.loc4 [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %A.type: type = generic_class_type @A.loc12 [concrete]\n// CHECK:STDOUT:   %A.generic: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.95c: type = class_type @A.loc12, @A.loc12(%T) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl.loc4: type = class_decl @A.loc4 [concrete = constants.%A.f82] {} {}\n// CHECK:STDOUT:   %A.decl.loc12: %A.type = class_decl @A.loc12 [concrete = constants.%A.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc12_13.1: type = splice_block %.loc12_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc12_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc12_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc12_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A.loc4;\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @A.loc12(%T.loc12_9.2: type) {\n// CHECK:STDOUT:   %T.loc12_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc12_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%A.95c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.loc12(constants.%T) {\n// CHECK:STDOUT:   %T.loc12_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_mismatch_implicit_param_list.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %N.bad: %A = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %B.type.f7e62c.1: type = generic_class_type @B.loc6 [concrete]\n// CHECK:STDOUT:   %B.generic.8bc1c8.1: %B.type.f7e62c.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %N.bd9: %T = symbolic_binding N, 1 [symbolic]\n// CHECK:STDOUT:   %B.type.f7e62c.2: type = generic_class_type @B.loc14 [concrete]\n// CHECK:STDOUT:   %B.generic.8bc1c8.2: %B.type.f7e62c.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %B.87e: type = class_type @B.loc14, @B.loc14(%T, %N.bd9) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl.loc6: %B.type.f7e62c.1 = class_decl @B.loc6 [concrete = constants.%B.generic.8bc1c8.1] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.1ab = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %A.ref [concrete = constants.%A] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc6_9.2: %A = symbolic_binding N, 0 [symbolic = %N.loc6_9.1 (constants.%N.bad)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl.loc14: %B.type.f7e62c.2 = class_decl @B.loc14 [concrete = constants.%B.generic.8bc1c8.2] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %N.patt: @B.loc14.%pattern_type (%pattern_type.51d) = symbolic_binding_pattern N, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc14_13.1: type = splice_block %.loc14_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc14_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc14_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc14_9.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc14_23: type = splice_block %T.ref [symbolic = %T.loc14_9.1 (constants.%T)] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc14_9.2 [symbolic = %T.loc14_9.1 (constants.%T)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc14_19.2: @B.loc14.%T.loc14_9.1 (%T) = symbolic_binding N, 1 [symbolic = %N.loc14_19.1 (constants.%N.bd9)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @B.loc6(%N.loc6_9.2: %A) {\n// CHECK:STDOUT:   %N.loc6_9.1: %A = symbolic_binding N, 0 [symbolic = %N.loc6_9.1 (constants.%N.bad)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @B.loc14(%T.loc14_9.2: type, %N.loc14_19.2: @B.loc14.%T.loc14_9.1 (%T)) {\n// CHECK:STDOUT:   %T.loc14_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc14_9.1 (constants.%T)]\n// CHECK:STDOUT:   %N.loc14_19.1: @B.loc14.%T.loc14_9.1 (%T) = symbolic_binding N, 1 [symbolic = %N.loc14_19.1 (constants.%N.bd9)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc14_9.1 [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%B.87e\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.loc6(constants.%N.bad) {\n// CHECK:STDOUT:   %N.loc6_9.1 => constants.%N.bad\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.loc14(constants.%T, constants.%N.bd9) {\n// CHECK:STDOUT:   %T.loc14_9.1 => constants.%T\n// CHECK:STDOUT:   %N.loc14_19.1 => constants.%N.bd9\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_mismatch_param_count.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type.e297ae.1: type = generic_class_type @C.loc6 [concrete]\n// CHECK:STDOUT:   %C.generic.65f314.1: %C.type.e297ae.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %U: %A = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %C.type.e297ae.2: type = generic_class_type @C.loc14 [concrete]\n// CHECK:STDOUT:   %C.generic.65f314.2: %C.type.e297ae.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.74f: type = class_type @C.loc14, @C.loc14(%T, %U) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .C = %C.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %C.decl.loc6: %C.type.e297ae.1 = class_decl @C.loc6 [concrete = constants.%C.generic.65f314.1] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_13.1: type = splice_block %.loc6_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc14: %C.type.e297ae.2 = class_decl @C.loc14 [concrete = constants.%C.generic.65f314.2] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.1ab = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc14_13.1: type = splice_block %.loc14_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc14_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc14_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc14_9.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc14_23: type = splice_block %A.ref [concrete = constants.%A] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc14_19.2: %A = symbolic_binding U, 1 [symbolic = %U.loc14_19.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C.loc6(%T.loc6_9.2: type) {\n// CHECK:STDOUT:   %T.loc6_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C.loc14(%T.loc14_9.2: type, %U.loc14_19.2: %A) {\n// CHECK:STDOUT:   %T.loc14_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc14_9.1 (constants.%T)]\n// CHECK:STDOUT:   %U.loc14_19.1: %A = symbolic_binding U, 1 [symbolic = %U.loc14_19.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.74f\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.loc6(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.loc14(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc14_9.1 => constants.%T\n// CHECK:STDOUT:   %U.loc14_19.1 => constants.%U\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_mismatch_param_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %D.type.6dc267.1: type = generic_class_type @D.loc6 [concrete]\n// CHECK:STDOUT:   %D.generic.3c4a9e.1: %D.type.6dc267.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %T.bad: %A = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %D.type.6dc267.2: type = generic_class_type @D.loc14 [concrete]\n// CHECK:STDOUT:   %D.generic.3c4a9e.2: %D.type.6dc267.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %D.d48: type = class_type @D.loc14, @D.loc14(%T.bad) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .D = %D.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %D.decl.loc6: %D.type.6dc267.1 = class_decl @D.loc6 [concrete = constants.%D.generic.3c4a9e.1] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_13.1: type = splice_block %.loc6_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl.loc14: %D.type.6dc267.2 = class_decl @D.loc14 [concrete = constants.%D.generic.3c4a9e.2] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.1ab = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc14: type = splice_block %A.ref [concrete = constants.%A] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc14_9.2: %A = symbolic_binding T, 0 [symbolic = %T.loc14_9.1 (constants.%T.bad)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @D.loc6(%T.loc6_9.2: type) {\n// CHECK:STDOUT:   %T.loc6_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @D.loc14(%T.loc14_9.2: %A) {\n// CHECK:STDOUT:   %T.loc14_9.1: %A = symbolic_binding T, 0 [symbolic = %T.loc14_9.1 (constants.%T.bad)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%D.d48\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.loc6(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc6_9.1 => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.loc14(constants.%T.bad) {\n// CHECK:STDOUT:   %T.loc14_9.1 => constants.%T.bad\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_mismatch_param_name.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %E.type.97c458.1: type = generic_class_type @E.loc4 [concrete]\n// CHECK:STDOUT:   %E.generic.e80795.1: %E.type.97c458.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %E.type.97c458.2: type = generic_class_type @E.loc12 [concrete]\n// CHECK:STDOUT:   %E.generic.e80795.2: %E.type.97c458.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %E.421e93.2: type = class_type @E.loc12, @E.loc12(%U) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .E = %E.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %E.decl.loc4: %E.type.97c458.1 = class_decl @E.loc4 [concrete = constants.%E.generic.e80795.1] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %E.decl.loc12: %E.type.97c458.2 = class_decl @E.loc12 [concrete = constants.%E.generic.e80795.2] {\n// CHECK:STDOUT:     %U.patt: %pattern_type = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc12_13.1: type = splice_block %.loc12_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc12_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc12_9.2: type = symbolic_binding U, 0 [symbolic = %U.loc12_9.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @E.loc4(%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T.loc4_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @E.loc12(%U.loc12_9.2: type) {\n// CHECK:STDOUT:   %U.loc12_9.1: type = symbolic_binding U, 0 [symbolic = %U.loc12_9.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%E.421e93.2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @E.loc4(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @E.loc12(constants.%U) {\n// CHECK:STDOUT:   %U.loc12_9.1 => constants.%U\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/self.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/self.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/self.carbon\n\nclass Class(T:! type) {\n  // `Self` is the same as `Class(T)` here.\n  // TODO: Find a better way to test two types are the same.\n  fn MakeSelf() -> Self { return {}; }\n  fn MakeClass() -> Class(T) { return {}; }\n  fn F() {\n    var unused c: Class(T) = MakeSelf();\n    var unused s: Self = MakeClass();\n  }\n}\n\n// CHECK:STDOUT: --- self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %.6f9: Core.Form = init_form %Class [symbolic]\n// CHECK:STDOUT:   %pattern_type.466: type = pattern_type %Class [symbolic]\n// CHECK:STDOUT:   %Class.MakeSelf.type: type = fn_type @Class.MakeSelf, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %Class.MakeSelf: %Class.MakeSelf.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %Class.MakeClass.type: type = fn_type @Class.MakeClass, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %Class.MakeClass: %Class.MakeClass.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class [symbolic]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.val: %Class = struct_value () [symbolic]\n// CHECK:STDOUT:   %Class.MakeSelf.specific_fn: <specific function> = specific_function %Class.MakeSelf, @Class.MakeSelf(%T) [symbolic]\n// CHECK:STDOUT:   %Class.MakeClass.specific_fn: <specific function> = specific_function %Class.MakeClass, @Class.MakeClass(%T) [symbolic]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Class, @Destroy [symbolic]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Class, (%Destroy.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.609: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [symbolic]\n// CHECK:STDOUT:   %.2f5: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.609, %Destroy.facet [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.2f5 = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Destroy.WithSelf.Op(%Destroy.facet) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_17.1: type = splice_block %.loc15_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc15_13.2: type) {\n// CHECK:STDOUT:   %T.loc15_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.MakeSelf.type: type = fn_type @Class.MakeSelf, @Class(%T.loc15_13.1) [symbolic = %Class.MakeSelf.type (constants.%Class.MakeSelf.type)]\n// CHECK:STDOUT:   %Class.MakeSelf: @Class.%Class.MakeSelf.type (%Class.MakeSelf.type) = struct_value () [symbolic = %Class.MakeSelf (constants.%Class.MakeSelf)]\n// CHECK:STDOUT:   %Class.MakeClass.type: type = fn_type @Class.MakeClass, @Class(%T.loc15_13.1) [symbolic = %Class.MakeClass.type (constants.%Class.MakeClass.type)]\n// CHECK:STDOUT:   %Class.MakeClass: @Class.%Class.MakeClass.type (%Class.MakeClass.type) = struct_value () [symbolic = %Class.MakeClass (constants.%Class.MakeClass)]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F, @Class(%T.loc15_13.1) [symbolic = %Class.F.type (constants.%Class.F.type)]\n// CHECK:STDOUT:   %Class.F: @Class.%Class.F.type (%Class.F.type) = struct_value () [symbolic = %Class.F (constants.%Class.F)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Class.MakeSelf.decl: @Class.%Class.MakeSelf.type (%Class.MakeSelf.type) = fn_decl @Class.MakeSelf [symbolic = @Class.%Class.MakeSelf (constants.%Class.MakeSelf)] {\n// CHECK:STDOUT:       %return.patt: @Class.MakeSelf.%pattern_type (%pattern_type.466) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.MakeSelf.%pattern_type (%pattern_type.466) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc18_20.2: type = specific_constant constants.%Class, @Class(constants.%T) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:       %Self.ref: type = name_ref Self, %.loc18_20.2 [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:       %.loc18_20.3: Core.Form = init_form %Self.ref [symbolic = %.loc18_20.1 (constants.%.6f9)]\n// CHECK:STDOUT:       %return.param: ref @Class.MakeSelf.%Class (%Class) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @Class.MakeSelf.%Class (%Class) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Class.MakeClass.decl: @Class.%Class.MakeClass.type (%Class.MakeClass.type) = fn_decl @Class.MakeClass [symbolic = @Class.%Class.MakeClass (constants.%Class.MakeClass)] {\n// CHECK:STDOUT:       %return.patt: @Class.MakeClass.%pattern_type (%pattern_type.466) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Class.MakeClass.%pattern_type (%pattern_type.466) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Class.%T.loc15_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %Class.loc19_28.2: type = class_type @Class, @Class(constants.%T) [symbolic = %Class.loc19_28.1 (constants.%Class)]\n// CHECK:STDOUT:       %.loc19_28.2: Core.Form = init_form %Class.loc19_28.2 [symbolic = %.loc19_28.1 (constants.%.6f9)]\n// CHECK:STDOUT:       %return.param: ref @Class.MakeClass.%Class.loc19_28.1 (%Class) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @Class.MakeClass.%Class.loc19_28.1 (%Class) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Class.F.decl: @Class.%Class.F.type (%Class.F.type) = fn_decl @Class.F [symbolic = @Class.%Class.F (constants.%Class.F)] {} {}\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:     .MakeSelf = %Class.MakeSelf.decl\n// CHECK:STDOUT:     .Class = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .MakeClass = %Class.MakeClass.decl\n// CHECK:STDOUT:     .F = %Class.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.MakeSelf(@Class.%T.loc15_13.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %.loc18_20.1: Core.Form = init_form %Class [symbolic = %.loc18_20.1 (constants.%.6f9)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Class [symbolic = %pattern_type (constants.%pattern_type.466)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %Class.val: @Class.MakeSelf.%Class (%Class) = struct_value () [symbolic = %Class.val (constants.%Class.val)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Class.MakeSelf.%Class (%Class) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc18_35.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc18_35.2: init @Class.MakeSelf.%Class (%Class) to %return.param = class_init () [symbolic = %Class.val (constants.%Class.val)]\n// CHECK:STDOUT:     %.loc18_36: init @Class.MakeSelf.%Class (%Class) = converted %.loc18_35.1, %.loc18_35.2 [symbolic = %Class.val (constants.%Class.val)]\n// CHECK:STDOUT:     return %.loc18_36 to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.MakeClass(@Class.%T.loc15_13.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Class.loc19_28.1: type = class_type @Class, @Class(%T) [symbolic = %Class.loc19_28.1 (constants.%Class)]\n// CHECK:STDOUT:   %.loc19_28.1: Core.Form = init_form %Class.loc19_28.1 [symbolic = %.loc19_28.1 (constants.%.6f9)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Class.loc19_28.1 [symbolic = %pattern_type (constants.%pattern_type.466)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class.loc19_28.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %Class.val: @Class.MakeClass.%Class.loc19_28.1 (%Class) = struct_value () [symbolic = %Class.val (constants.%Class.val)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Class.MakeClass.%Class.loc19_28.1 (%Class) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc19_40.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc19_40.2: init @Class.MakeClass.%Class.loc19_28.1 (%Class) to %return.param = class_init () [symbolic = %Class.val (constants.%Class.val)]\n// CHECK:STDOUT:     %.loc19_41: init @Class.MakeClass.%Class.loc19_28.1 (%Class) = converted %.loc19_40.1, %.loc19_40.2 [symbolic = %Class.val (constants.%Class.val)]\n// CHECK:STDOUT:     return %.loc19_41 to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.F(@Class.%T.loc15_13.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Class.loc21_26.2: type = class_type @Class, @Class(%T) [symbolic = %Class.loc21_26.2 (constants.%Class)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Class.loc21_26.2 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Class.loc21_26.2 [symbolic = %pattern_type (constants.%pattern_type.466)]\n// CHECK:STDOUT:   %Class.MakeSelf.type: type = fn_type @Class.MakeSelf, @Class(%T) [symbolic = %Class.MakeSelf.type (constants.%Class.MakeSelf.type)]\n// CHECK:STDOUT:   %Class.MakeSelf: @Class.F.%Class.MakeSelf.type (%Class.MakeSelf.type) = struct_value () [symbolic = %Class.MakeSelf (constants.%Class.MakeSelf)]\n// CHECK:STDOUT:   %Class.MakeSelf.specific_fn.loc21_30.2: <specific function> = specific_function %Class.MakeSelf, @Class.MakeSelf(%T) [symbolic = %Class.MakeSelf.specific_fn.loc21_30.2 (constants.%Class.MakeSelf.specific_fn)]\n// CHECK:STDOUT:   %Class.MakeClass.type: type = fn_type @Class.MakeClass, @Class(%T) [symbolic = %Class.MakeClass.type (constants.%Class.MakeClass.type)]\n// CHECK:STDOUT:   %Class.MakeClass: @Class.F.%Class.MakeClass.type (%Class.MakeClass.type) = struct_value () [symbolic = %Class.MakeClass (constants.%Class.MakeClass)]\n// CHECK:STDOUT:   %Class.MakeClass.specific_fn.loc22_26.2: <specific function> = specific_function %Class.MakeClass, @Class.MakeClass(%T) [symbolic = %Class.MakeClass.specific_fn.loc22_26.2 (constants.%Class.MakeClass.specific_fn)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Class.loc21_26.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Class.loc21_26.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [symbolic = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.609)]\n// CHECK:STDOUT:   %.loc22_5.2: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %Destroy.facet [symbolic = %.loc22_5.2 (constants.%.2f5)]\n// CHECK:STDOUT:   %impl.elem0.loc22_5.2: @Class.F.%.loc22_5.2 (%.2f5) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc22_5.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc22_5.2: <specific function> = specific_impl_function %impl.elem0.loc22_5.2, @Destroy.WithSelf.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc22_5.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %c.patt: @Class.F.%pattern_type (%pattern_type.466) = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:       %c.var_patt: @Class.F.%pattern_type (%pattern_type.466) = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c.var: ref @Class.F.%Class.loc21_26.2 (%Class) = var %c.var_patt\n// CHECK:STDOUT:     %.loc21_30: @Class.F.%Class.MakeSelf.type (%Class.MakeSelf.type) = specific_constant @Class.%Class.MakeSelf.decl, @Class(constants.%T) [symbolic = %Class.MakeSelf (constants.%Class.MakeSelf)]\n// CHECK:STDOUT:     %MakeSelf.ref: @Class.F.%Class.MakeSelf.type (%Class.MakeSelf.type) = name_ref MakeSelf, %.loc21_30 [symbolic = %Class.MakeSelf (constants.%Class.MakeSelf)]\n// CHECK:STDOUT:     %Class.MakeSelf.specific_fn.loc21_30.1: <specific function> = specific_function %MakeSelf.ref, @Class.MakeSelf(constants.%T) [symbolic = %Class.MakeSelf.specific_fn.loc21_30.2 (constants.%Class.MakeSelf.specific_fn)]\n// CHECK:STDOUT:     %.loc21_5: ref @Class.F.%Class.loc21_26.2 (%Class) = splice_block %c.var {}\n// CHECK:STDOUT:     %Class.MakeSelf.call: init @Class.F.%Class.loc21_26.2 (%Class) to %.loc21_5 = call %Class.MakeSelf.specific_fn.loc21_30.1()\n// CHECK:STDOUT:     assign %c.var, %Class.MakeSelf.call\n// CHECK:STDOUT:     %.loc21_26: type = splice_block %Class.loc21_26.1 [symbolic = %Class.loc21_26.2 (constants.%Class)] {\n// CHECK:STDOUT:       %Class.ref: %Class.type = name_ref Class, file.%Class.decl [concrete = constants.%Class.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Class.%T.loc15_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %Class.loc21_26.1: type = class_type @Class, @Class(constants.%T) [symbolic = %Class.loc21_26.2 (constants.%Class)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: ref @Class.F.%Class.loc21_26.2 (%Class) = ref_binding c, %c.var\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %s.patt: @Class.F.%pattern_type (%pattern_type.466) = ref_binding_pattern s [concrete]\n// CHECK:STDOUT:       %s.var_patt: @Class.F.%pattern_type (%pattern_type.466) = var_pattern %s.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %s.var: ref @Class.F.%Class.loc21_26.2 (%Class) = var %s.var_patt\n// CHECK:STDOUT:     %.loc22_26: @Class.F.%Class.MakeClass.type (%Class.MakeClass.type) = specific_constant @Class.%Class.MakeClass.decl, @Class(constants.%T) [symbolic = %Class.MakeClass (constants.%Class.MakeClass)]\n// CHECK:STDOUT:     %MakeClass.ref: @Class.F.%Class.MakeClass.type (%Class.MakeClass.type) = name_ref MakeClass, %.loc22_26 [symbolic = %Class.MakeClass (constants.%Class.MakeClass)]\n// CHECK:STDOUT:     %Class.MakeClass.specific_fn.loc22_26.1: <specific function> = specific_function %MakeClass.ref, @Class.MakeClass(constants.%T) [symbolic = %Class.MakeClass.specific_fn.loc22_26.2 (constants.%Class.MakeClass.specific_fn)]\n// CHECK:STDOUT:     %.loc22_5.1: ref @Class.F.%Class.loc21_26.2 (%Class) = splice_block %s.var {}\n// CHECK:STDOUT:     %Class.MakeClass.call: init @Class.F.%Class.loc21_26.2 (%Class) to %.loc22_5.1 = call %Class.MakeClass.specific_fn.loc22_26.1()\n// CHECK:STDOUT:     assign %s.var, %Class.MakeClass.call\n// CHECK:STDOUT:     %.loc22_19.1: type = splice_block %Self.ref [symbolic = %Class.loc21_26.2 (constants.%Class)] {\n// CHECK:STDOUT:       %.loc22_19.2: type = specific_constant constants.%Class, @Class(constants.%T) [symbolic = %Class.loc21_26.2 (constants.%Class)]\n// CHECK:STDOUT:       %Self.ref: type = name_ref Self, %.loc22_19.2 [symbolic = %Class.loc21_26.2 (constants.%Class)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %s: ref @Class.F.%Class.loc21_26.2 (%Class) = ref_binding s, %s.var\n// CHECK:STDOUT:     %impl.elem0.loc22_5.1: @Class.F.%.loc22_5.2 (%.2f5) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc22_5.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %bound_method.loc22_5.1: <bound method> = bound_method %s.var, %impl.elem0.loc22_5.1\n// CHECK:STDOUT:     %specific_impl_fn.loc22_5.1: <specific function> = specific_impl_function %impl.elem0.loc22_5.1, @Destroy.WithSelf.Op(constants.%Destroy.facet) [symbolic = %specific_impl_fn.loc22_5.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %bound_method.loc22_5.2: <bound method> = bound_method %s.var, %specific_impl_fn.loc22_5.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call.loc22: init %empty_tuple.type = call %bound_method.loc22_5.2(%s.var)\n// CHECK:STDOUT:     %impl.elem0.loc21: @Class.F.%.loc22_5.2 (%.2f5) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc22_5.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %bound_method.loc21_5.1: <bound method> = bound_method %c.var, %impl.elem0.loc21\n// CHECK:STDOUT:     %specific_impl_fn.loc21: <specific function> = specific_impl_function %impl.elem0.loc21, @Destroy.WithSelf.Op(constants.%Destroy.facet) [symbolic = %specific_impl_fn.loc22_5.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %bound_method.loc21_5.2: <bound method> = bound_method %c.var, %specific_impl_fn.loc21\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call.loc21: init %empty_tuple.type = call %bound_method.loc21_5.2(%c.var)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Class.MakeSelf.type => constants.%Class.MakeSelf.type\n// CHECK:STDOUT:   %Class.MakeSelf => constants.%Class.MakeSelf\n// CHECK:STDOUT:   %Class.MakeClass.type => constants.%Class.MakeClass.type\n// CHECK:STDOUT:   %Class.MakeClass => constants.%Class.MakeClass\n// CHECK:STDOUT:   %Class.F.type => constants.%Class.F.type\n// CHECK:STDOUT:   %Class.F => constants.%Class.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.MakeSelf(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %.loc18_20.1 => constants.%.6f9\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.466\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %Class.val => constants.%Class.val\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.MakeClass(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Class.loc19_28.1 => constants.%Class\n// CHECK:STDOUT:   %.loc19_28.1 => constants.%.6f9\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.466\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %Class.val => constants.%Class.val\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.F(constants.%T) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/generic/stringify.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/generic/stringify.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/generic/stringify.carbon\n\n// --- fail_empty_params.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass NoParams {}\nclass EmptyParams() {}\n\nvar v: NoParams;\n// CHECK:STDERR: fail_empty_params.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `NoParams` to `EmptyParams()` [ConversionFailure]\n// CHECK:STDERR: var w: EmptyParams() = v;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_empty_params.carbon:[[@LINE+4]]:1: note: type `NoParams` does not implement interface `Core.ImplicitAs(EmptyParams())` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var w: EmptyParams() = v;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar w: EmptyParams() = v;\n\n// --- fail_nested.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Outer(T:! type) {\n  class Inner(U:! type) {\n  }\n}\n\nvar v: Outer({}*);\n\n// TODO: It would be nice to include the `Outer({}*).` prefix in the name of `Inner`.\n// CHECK:STDERR: fail_nested.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `Outer({}*)` to `Inner({.a: i32}*)` [ConversionFailure]\n// CHECK:STDERR: var w: Outer({}*).Inner({.a: i32}*) = v;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_nested.carbon:[[@LINE+4]]:1: note: type `Outer({}*)` does not implement interface `Core.ImplicitAs(Inner({.a: i32}*))` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var w: Outer({}*).Inner({.a: i32}*) = v;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar w: Outer({}*).Inner({.a: i32}*) = v;\n\n// --- fail_int_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(N:! i32) {}\n\n// CHECK:STDERR: fail_int_value.carbon:[[@LINE+7]]:1: error: cannot implicitly convert expression of type `()` to `C(123)` [ConversionFailure]\n// CHECK:STDERR: var v: C(123) = ();\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR: fail_int_value.carbon:[[@LINE+4]]:1: note: type `()` does not implement interface `Core.ImplicitAs(C(123))` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: var v: C(123) = ();\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR:\nvar v: C(123) = ();\n\n// --- fail_class_param.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass D {\n  var a: i32;\n  var b: i32;\n}\n\nclass E(F:! D) {}\n\n// CHECK:STDERR: fail_class_param.carbon:[[@LINE+14]]:8: error: argument for generic parameter is not a compile-time constant [CompTimeArgumentNotConstant]\n// CHECK:STDERR: var g: E({.a = 1, .b = 2}) = {} as E({.a = 3, .b = 4} as D);\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_class_param.carbon:[[@LINE-5]]:9: note: initializing generic parameter `F` declared here [InitializingGenericParam]\n// CHECK:STDERR: class E(F:! D) {}\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\n// CHECK:STDERR: fail_class_param.carbon:[[@LINE+7]]:36: error: argument for generic parameter is not a compile-time constant [CompTimeArgumentNotConstant]\n// CHECK:STDERR: var g: E({.a = 1, .b = 2}) = {} as E({.a = 3, .b = 4} as D);\n// CHECK:STDERR:                                    ^~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_class_param.carbon:[[@LINE-12]]:9: note: initializing generic parameter `F` declared here [InitializingGenericParam]\n// CHECK:STDERR: class E(F:! D) {}\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nvar g: E({.a = 1, .b = 2}) = {} as E({.a = 3, .b = 4} as D);\n\n// CHECK:STDOUT: --- fail_empty_params.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %NoParams: type = class_type @NoParams [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %EmptyParams.type: type = generic_class_type @EmptyParams [concrete]\n// CHECK:STDOUT:   %EmptyParams.generic: %EmptyParams.type = struct_value () [concrete]\n// CHECK:STDOUT:   %EmptyParams: type = class_type @EmptyParams [concrete]\n// CHECK:STDOUT:   %pattern_type.8ec: type = pattern_type %NoParams [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.d7c: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%NoParams) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.51c: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%NoParams) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.5bb: %T.as.DefaultOrUnformed.impl.Op.type.51c = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %NoParams, (%DefaultOrUnformed.impl_witness.d7c) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.5bb, @T.as.DefaultOrUnformed.impl.Op(%NoParams) [concrete]\n// CHECK:STDOUT:   %pattern_type.e19: type = pattern_type %EmptyParams [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .NoParams = %NoParams.decl\n// CHECK:STDOUT:     .EmptyParams = %EmptyParams.decl\n// CHECK:STDOUT:     .v = %v\n// CHECK:STDOUT:     .w = %w\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %NoParams.decl: type = class_decl @NoParams [concrete = constants.%NoParams] {} {}\n// CHECK:STDOUT:   %EmptyParams.decl: %EmptyParams.type = class_decl @EmptyParams [concrete = constants.%EmptyParams.generic] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.8ec = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.8ec = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %NoParams = var %v.var_patt [concrete]\n// CHECK:STDOUT:   %NoParams.ref: type = name_ref NoParams, %NoParams.decl [concrete = constants.%NoParams]\n// CHECK:STDOUT:   %v: ref %NoParams = ref_binding v, %v.var [concrete = %v.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %w.patt: %pattern_type.e19 = ref_binding_pattern w [concrete]\n// CHECK:STDOUT:     %w.var_patt: %pattern_type.e19 = var_pattern %w.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %w.var: ref %EmptyParams = var %w.var_patt [concrete]\n// CHECK:STDOUT:   %.loc15: type = splice_block %EmptyParams [concrete = constants.%EmptyParams] {\n// CHECK:STDOUT:     %EmptyParams.ref: %EmptyParams.type = name_ref EmptyParams, %EmptyParams.decl [concrete = constants.%EmptyParams.generic]\n// CHECK:STDOUT:     %EmptyParams: type = class_type @EmptyParams [concrete = constants.%EmptyParams]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %w: ref %EmptyParams = ref_binding w, %w.var [concrete = %w.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @NoParams {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%NoParams\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @EmptyParams {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%EmptyParams\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%NoParams, (constants.%DefaultOrUnformed.impl_witness.d7c) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc7_16.1: %DefaultOrUnformed.type = converted constants.%NoParams, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc7_16.1 [concrete = constants.%NoParams]\n// CHECK:STDOUT:   %.loc7_16.2: type = converted %.loc7_16.1, %as_type [concrete = constants.%NoParams]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.5bb, @T.as.DefaultOrUnformed.impl.Op(constants.%NoParams) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc7_1: ref %NoParams = splice_block file.%v.var [concrete = file.%v.var] {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %NoParams to %.loc7_1 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign file.%v.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %v.ref: ref %NoParams = name_ref v, file.%v [concrete = file.%v.var]\n// CHECK:STDOUT:   %.loc15: %EmptyParams = converted %v.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%w.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_nested.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Outer.type: type = generic_class_type @Outer [concrete]\n// CHECK:STDOUT:   %Outer.generic: %Outer.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Outer.387: type = class_type @Outer, @Outer(%T) [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %Inner.type.e0d: type = generic_class_type @Inner, @Outer(%T) [symbolic]\n// CHECK:STDOUT:   %Inner.generic.ada: %Inner.type.e0d = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.e21: type = class_type @Inner, @Inner(%T, %U) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Outer.b7c: type = class_type @Outer, @Outer(%ptr.c28) [concrete]\n// CHECK:STDOUT:   %Inner.type.cd9: type = generic_class_type @Inner, @Outer(%ptr.c28) [concrete]\n// CHECK:STDOUT:   %Inner.generic.0f6: %Inner.type.cd9 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.acf: type = pattern_type %Outer.b7c [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.8e7: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Outer.b7c) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.e70: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Outer.b7c) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.3a0: %T.as.DefaultOrUnformed.impl.Op.type.e70 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %Outer.b7c, (%DefaultOrUnformed.impl_witness.8e7) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.3a0, @T.as.DefaultOrUnformed.impl.Op(%Outer.b7c) [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %i32} [concrete]\n// CHECK:STDOUT:   %ptr.1bb: type = ptr_type %struct_type.a [concrete]\n// CHECK:STDOUT:   %Inner.304: type = class_type @Inner, @Inner(%ptr.c28, %ptr.1bb) [concrete]\n// CHECK:STDOUT:   %pattern_type.536: type = pattern_type %Inner.304 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Outer = %Outer.decl\n// CHECK:STDOUT:     .v = %v\n// CHECK:STDOUT:     .w = %w\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Outer.decl: %Outer.type = class_decl @Outer [concrete = constants.%Outer.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.acf = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.acf = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %Outer.b7c = var %v.var_patt [concrete]\n// CHECK:STDOUT:   %.loc9_17: type = splice_block %Outer.loc9 [concrete = constants.%Outer.b7c] {\n// CHECK:STDOUT:     %Outer.ref.loc9: %Outer.type = name_ref Outer, %Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:     %.loc9_15: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc9_16: type = converted %.loc9_15, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %ptr.loc9: type = ptr_type %.loc9_16 [concrete = constants.%ptr.c28]\n// CHECK:STDOUT:     %Outer.loc9: type = class_type @Outer, @Outer(constants.%ptr.c28) [concrete = constants.%Outer.b7c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %Outer.b7c = ref_binding v, %v.var [concrete = %v.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %w.patt: %pattern_type.536 = ref_binding_pattern w [concrete]\n// CHECK:STDOUT:     %w.var_patt: %pattern_type.536 = var_pattern %w.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %w.var: ref %Inner.304 = var %w.var_patt [concrete]\n// CHECK:STDOUT:   %.loc19_35: type = splice_block %Inner [concrete = constants.%Inner.304] {\n// CHECK:STDOUT:     %Outer.ref.loc19: %Outer.type = name_ref Outer, %Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:     %.loc19_15: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc19_16: type = converted %.loc19_15, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %ptr.loc19_16: type = ptr_type %.loc19_16 [concrete = constants.%ptr.c28]\n// CHECK:STDOUT:     %Outer.loc19: type = class_type @Outer, @Outer(constants.%ptr.c28) [concrete = constants.%Outer.b7c]\n// CHECK:STDOUT:     %.loc19_18: %Inner.type.cd9 = specific_constant @Outer.%Inner.decl, @Outer(constants.%ptr.c28) [concrete = constants.%Inner.generic.0f6]\n// CHECK:STDOUT:     %Inner.ref: %Inner.type.cd9 = name_ref Inner, %.loc19_18 [concrete = constants.%Inner.generic.0f6]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.a: type = struct_type {.a: %i32} [concrete = constants.%struct_type.a]\n// CHECK:STDOUT:     %ptr.loc19_34: type = ptr_type %struct_type.a [concrete = constants.%ptr.1bb]\n// CHECK:STDOUT:     %Inner: type = class_type @Inner, @Inner(constants.%ptr.c28, constants.%ptr.1bb) [concrete = constants.%Inner.304]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %w: ref %Inner.304 = ref_binding w, %w.var [concrete = %w.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Outer(%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type: type = generic_class_type @Inner, @Outer(%T.loc4_13.1) [symbolic = %Inner.type (constants.%Inner.type.e0d)]\n// CHECK:STDOUT:   %Inner.generic: @Outer.%Inner.type (%Inner.type.e0d) = struct_value () [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Inner.decl: @Outer.%Inner.type (%Inner.type.e0d) = class_decl @Inner [symbolic = @Outer.%Inner.generic (constants.%Inner.generic.ada)] {\n// CHECK:STDOUT:       %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc5_19.1: type = splice_block %.loc5_19.2 [concrete = type] {\n// CHECK:STDOUT:         %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:         %.loc5_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %U.loc5_15.2: type = symbolic_binding U, 1 [symbolic = %U.loc5_15.1 (constants.%U)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Outer.387\n// CHECK:STDOUT:     .Inner = %Inner.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Inner(@Outer.%T.loc4_13.2: type, %U.loc5_15.2: type) {\n// CHECK:STDOUT:   %U.loc5_15.1: type = symbolic_binding U, 1 [symbolic = %U.loc5_15.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Inner.e21\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%Outer.b7c, (constants.%DefaultOrUnformed.impl_witness.8e7) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc9_18.1: %DefaultOrUnformed.type = converted constants.%Outer.b7c, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc9_18.1 [concrete = constants.%Outer.b7c]\n// CHECK:STDOUT:   %.loc9_18.2: type = converted %.loc9_18.1, %as_type [concrete = constants.%Outer.b7c]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.3a0, @T.as.DefaultOrUnformed.impl.Op(constants.%Outer.b7c) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc9_1: ref %Outer.b7c = splice_block file.%v.var [concrete = file.%v.var] {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %Outer.b7c to %.loc9_1 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign file.%v.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %v.ref: ref %Outer.b7c = name_ref v, file.%v [concrete = file.%v.var]\n// CHECK:STDOUT:   %.loc19: %Inner.304 = converted %v.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%w.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %U.loc5_15.1 => constants.%U\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%ptr.c28) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%ptr.c28\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.cd9\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.0f6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%ptr.c28, constants.%ptr.1bb) {\n// CHECK:STDOUT:   %U.loc5_15.1 => constants.%ptr.1bb\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_int_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.5de: %i32 = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.ad6: type = class_type @C, @C(%N.5de) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_123.fff: Core.IntLiteral = int_value 123 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_123.fff, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_123.fff, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_123.f7f: %i32 = int_value 123 [concrete]\n// CHECK:STDOUT:   %C.9a3: type = class_type @C, @C(%int_123.f7f) [concrete]\n// CHECK:STDOUT:   %pattern_type.a2c: type = pattern_type %C.9a3 [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .v = %v\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_9.2: %i32 = symbolic_binding N, 0 [symbolic = %N.loc4_9.1 (constants.%N.5de)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.a2c = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.a2c = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %C.9a3 = var %v.var_patt [concrete]\n// CHECK:STDOUT:   %.loc13_13.1: type = splice_block %C [concrete = constants.%C.9a3] {\n// CHECK:STDOUT:     %C.ref: %C.type = name_ref C, %C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %int_123: Core.IntLiteral = int_value 123 [concrete = constants.%int_123.fff]\n// CHECK:STDOUT:     %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc13_13.1: <bound method> = bound_method %int_123, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc13_13.2: <bound method> = bound_method %int_123, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc13_13.2(%int_123) [concrete = constants.%int_123.f7f]\n// CHECK:STDOUT:     %.loc13_13.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_123.f7f]\n// CHECK:STDOUT:     %.loc13_13.3: %i32 = converted %int_123, %.loc13_13.2 [concrete = constants.%int_123.f7f]\n// CHECK:STDOUT:     %C: type = class_type @C, @C(constants.%int_123.f7f) [concrete = constants.%C.9a3]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %C.9a3 = ref_binding v, %v.var [concrete = %v.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%N.loc4_9.2: %i32) {\n// CHECK:STDOUT:   %N.loc4_9.1: %i32 = symbolic_binding N, 0 [symbolic = %N.loc4_9.1 (constants.%N.5de)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.ad6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc13_18: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc13_1: %C.9a3 = converted %.loc13_18, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%v.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%N.5de) {\n// CHECK:STDOUT:   %N.loc4_9.1 => constants.%N.5de\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%int_123.f7f) {\n// CHECK:STDOUT:   %N.loc4_9.1 => constants.%int_123.f7f\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_class_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %D.elem: type = unbound_element_type %D, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.501: type = struct_type {.a: %i32, .b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.705: <witness> = complete_type_witness %struct_type.a.b.501 [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.9c8: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %F: %D = symbolic_binding F, 0 [symbolic]\n// CHECK:STDOUT:   %E.type: type = generic_class_type @E [concrete]\n// CHECK:STDOUT:   %E.generic: %E.type = struct_value () [concrete]\n// CHECK:STDOUT:   %E: type = class_type @E, @E(%F) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.cfd: type = struct_type {.a: Core.IntLiteral, .b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.4aa: %struct_type.a.b.cfd = struct_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %D.val.525: %D = struct_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %struct.cb7: %struct_type.a.b.cfd = struct_value (%int_3.1ba, %int_4.0c1) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.6d7: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_4.940: %i32 = int_value 4 [concrete]\n// CHECK:STDOUT:   %D.val.659: %D = struct_value (%int_3.822, %int_4.940) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .E = %E.decl\n// CHECK:STDOUT:     .g = %g\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %E.decl: %E.type = class_decl @E [concrete = constants.%E.generic] {\n// CHECK:STDOUT:     %F.patt: %pattern_type.9c8 = symbolic_binding_pattern F, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9: type = splice_block %D.ref [concrete = constants.%D] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %F.loc9_9.2: %D = symbolic_binding F, 0 [symbolic = %F.loc9_9.1 (constants.%F)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %g.patt: <error> = ref_binding_pattern g [concrete]\n// CHECK:STDOUT:     %g.var_patt: <error> = var_pattern %g.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %g.var: ref <error> = var %g.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %.1: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:     %E.ref: %E.type = name_ref E, %E.decl [concrete = constants.%E.generic]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %.loc25_25.1: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2) [concrete = constants.%struct.4aa]\n// CHECK:STDOUT:     %impl.elem0.loc25_25.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc25_25.1: <bound method> = bound_method %int_1, %impl.elem0.loc25_25.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:     %specific_fn.loc25_25.1: <specific function> = specific_function %impl.elem0.loc25_25.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc25_25.2: <bound method> = bound_method %int_1, %specific_fn.loc25_25.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc25_25.1: init %i32 = call %bound_method.loc25_25.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc25_25.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc25_25.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc25_25.3: ref %D = temporary_storage\n// CHECK:STDOUT:     %.loc25_25.4: ref %i32 = class_element_access %.loc25_25.3, element0\n// CHECK:STDOUT:     %.loc25_25.5: init %i32 to %.loc25_25.4 = in_place_init %.loc25_25.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %impl.elem0.loc25_25.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc25_25.3: <bound method> = bound_method %int_2, %impl.elem0.loc25_25.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:     %specific_fn.loc25_25.2: <specific function> = specific_function %impl.elem0.loc25_25.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc25_25.4: <bound method> = bound_method %int_2, %specific_fn.loc25_25.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc25_25.2: init %i32 = call %bound_method.loc25_25.4(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc25_25.6: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc25_25.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc25_25.7: ref %i32 = class_element_access %.loc25_25.3, element1\n// CHECK:STDOUT:     %.loc25_25.8: init %i32 to %.loc25_25.7 = in_place_init %.loc25_25.6 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc25_25.9: init %D to %.loc25_25.3 = class_init (%.loc25_25.5, %.loc25_25.8) [concrete = constants.%D.val.525]\n// CHECK:STDOUT:     %.loc25_26.1: init %D = converted %.loc25_25.1, %.loc25_25.9 [concrete = constants.%D.val.525]\n// CHECK:STDOUT:     %.loc25_26.2: ref %D = temporary %.loc25_25.3, %.loc25_26.1\n// CHECK:STDOUT:     %.loc25_26.3: %D = acquire_value %.loc25_26.2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %g: ref <error> = ref_binding g, <error> [concrete = <error>]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %D.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc6: %D.elem = field_decl b, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b.501 [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT:   .a = %.loc5\n// CHECK:STDOUT:   .b = %.loc6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @E(%F.loc9_9.2: %D) {\n// CHECK:STDOUT:   %F.loc9_9.1: %D = symbolic_binding F, 0 [symbolic = %F.loc9_9.1 (constants.%F)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%E\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc25_31: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %E.ref: %E.type = name_ref E, file.%E.decl [concrete = constants.%E.generic]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]\n// CHECK:STDOUT:   %.loc25_53.1: %struct_type.a.b.cfd = struct_literal (%int_3, %int_4) [concrete = constants.%struct.cb7]\n// CHECK:STDOUT:   %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:   %impl.elem0.loc25_53.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc25_53.1: <bound method> = bound_method %int_3, %impl.elem0.loc25_53.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:   %specific_fn.loc25_53.1: <specific function> = specific_function %impl.elem0.loc25_53.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc25_53.2: <bound method> = bound_method %int_3, %specific_fn.loc25_53.1 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc25_53.1: init %i32 = call %bound_method.loc25_53.2(%int_3) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc25_53.2: init %i32 = converted %int_3, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc25_53.1 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc25_53.3: ref %D = temporary_storage\n// CHECK:STDOUT:   %.loc25_53.4: ref %i32 = class_element_access %.loc25_53.3, element0\n// CHECK:STDOUT:   %.loc25_53.5: init %i32 to %.loc25_53.4 = in_place_init %.loc25_53.2 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %impl.elem0.loc25_53.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc25_53.3: <bound method> = bound_method %int_4, %impl.elem0.loc25_53.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c]\n// CHECK:STDOUT:   %specific_fn.loc25_53.2: <specific function> = specific_function %impl.elem0.loc25_53.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc25_53.4: <bound method> = bound_method %int_4, %specific_fn.loc25_53.2 [concrete = constants.%bound_method.6d7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc25_53.2: init %i32 = call %bound_method.loc25_53.4(%int_4) [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc25_53.6: init %i32 = converted %int_4, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc25_53.2 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc25_53.7: ref %i32 = class_element_access %.loc25_53.3, element1\n// CHECK:STDOUT:   %.loc25_53.8: init %i32 to %.loc25_53.7 = in_place_init %.loc25_53.6 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc25_53.9: init %D to %.loc25_53.3 = class_init (%.loc25_53.5, %.loc25_53.8) [concrete = constants.%D.val.659]\n// CHECK:STDOUT:   %.loc25_55.1: init %D = converted %.loc25_53.1, %.loc25_53.9 [concrete = constants.%D.val.659]\n// CHECK:STDOUT:   %.loc25_55.2: ref %D = temporary %.loc25_53.3, %.loc25_55.1\n// CHECK:STDOUT:   %.loc25_55.3: %D = acquire_value %.loc25_55.2\n// CHECK:STDOUT:   assign file.%g.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @E(constants.%F) {\n// CHECK:STDOUT:   %F.loc9_9.1 => constants.%F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/implicit_import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/implicit_import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/implicit_import.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n// --- basic.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// --- redecl_after_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// --- fail_redecl_after_def.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_redecl_after_def.impl.carbon:[[@LINE+8]]:1: error: redeclaration of `class C` is redundant [RedeclRedundant]\n// CHECK:STDERR: class C;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_redecl_after_def.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: redecl_after_def.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR:\nclass C;\n\n// --- redef_after_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// --- fail_redef_after_def.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_redef_after_def.impl.carbon:[[@LINE+8]]:1: error: redefinition of `class C` [RedeclRedef]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR: fail_redef_after_def.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: redef_after_def.carbon:4:1: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR: class C {}\n// CHECK:STDERR: ^~~~~~~~~\n// CHECK:STDERR:\nclass C {}\n\n// --- def_alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\nalias B = C;\n\n// --- fail_def_alias.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_def_alias.impl.carbon:[[@LINE+8]]:7: error: duplicate name `B` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: class B {}\n// CHECK:STDERR:       ^\n// CHECK:STDERR: fail_def_alias.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: def_alias.carbon:5:7: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: alias B = C;\n// CHECK:STDERR:       ^\n// CHECK:STDERR:\nclass B {}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- basic.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_21.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_21.2 = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- redecl_after_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_redecl_after_def.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//redecl_after_def, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//redecl_after_def, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_32.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_32.2 = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- redef_after_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_redef_after_def.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C.17abfe.1: type = class_type @C.1 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C.17abfe.2: type = class_type @C.loc12 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//redef_after_def, C, loaded [concrete = constants.%C.17abfe.1]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//redef_after_def, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//redef_after_def, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_31.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_31.2 = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C.loc12 [concrete = constants.%C.17abfe.2] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C.1 [from \"redef_after_def.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C.loc12 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C.17abfe.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- def_alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .B = %B\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %B: type = alias_binding B, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_def_alias.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//def_alias, C, unloaded\n// CHECK:STDOUT:   %Main.B: type = import_ref Main//def_alias, B, loaded [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_25.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_25.2 = import <none>\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"def_alias.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/import.carbon\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Empty {\n}\n\nclass Field {\n  var x: i32;\n}\n\nclass ForwardDeclared;\n\nclass ForwardDeclared {\n  fn F[self: Self]();\n  fn G[ref self: Self]();\n}\n\nclass Incomplete;\n\n// --- b.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\n\nfn Run() {\n  var unused a: Empty = {};\n\n  var b: Field = {.x = 1};\n  b.x = 2;\n\n  var c: ForwardDeclared = {};\n  c.F();\n  c.G();\n\n  var unused d: ForwardDeclared* = &c;\n\n  var unused e: Incomplete*;\n}\n\n// CHECK:STDOUT: --- a.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Empty: type = class_type @Empty [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Field: type = class_type @Field [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Field.elem: type = unbound_element_type %Field, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x [concrete]\n// CHECK:STDOUT:   %ForwardDeclared: type = class_type @ForwardDeclared [concrete]\n// CHECK:STDOUT:   %pattern_type.af1: type = pattern_type %ForwardDeclared [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.F.type: type = fn_type @ForwardDeclared.F [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.F: %ForwardDeclared.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.G.type: type = fn_type @ForwardDeclared.G [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.G: %ForwardDeclared.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Incomplete: type = class_type @Incomplete [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Empty = %Empty.decl\n// CHECK:STDOUT:     .Field = %Field.decl\n// CHECK:STDOUT:     .ForwardDeclared = %ForwardDeclared.decl.loc11\n// CHECK:STDOUT:     .Incomplete = %Incomplete.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Empty.decl: type = class_decl @Empty [concrete = constants.%Empty] {} {}\n// CHECK:STDOUT:   %Field.decl: type = class_decl @Field [concrete = constants.%Field] {} {}\n// CHECK:STDOUT:   %ForwardDeclared.decl.loc11: type = class_decl @ForwardDeclared [concrete = constants.%ForwardDeclared] {} {}\n// CHECK:STDOUT:   %ForwardDeclared.decl.loc13: type = class_decl @ForwardDeclared [concrete = constants.%ForwardDeclared] {} {}\n// CHECK:STDOUT:   %Incomplete.decl: type = class_decl @Incomplete [concrete = constants.%Incomplete] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Empty {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Empty\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Field {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc8: %Field.elem = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x [concrete = constants.%complete_type.1ec]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Field\n// CHECK:STDOUT:   .x = %.loc8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ForwardDeclared {\n// CHECK:STDOUT:   %ForwardDeclared.F.decl: %ForwardDeclared.F.type = fn_decl @ForwardDeclared.F [concrete = constants.%ForwardDeclared.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.af1 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.af1 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %ForwardDeclared = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%ForwardDeclared [concrete = constants.%ForwardDeclared]\n// CHECK:STDOUT:     %self: %ForwardDeclared = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ForwardDeclared.G.decl: %ForwardDeclared.G.type = fn_decl @ForwardDeclared.G [concrete = constants.%ForwardDeclared.G] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.af1 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.af1 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: ref %ForwardDeclared = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%ForwardDeclared [concrete = constants.%ForwardDeclared]\n// CHECK:STDOUT:     %self: ref %ForwardDeclared = ref_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%ForwardDeclared\n// CHECK:STDOUT:   .F = %ForwardDeclared.F.decl\n// CHECK:STDOUT:   .G = %ForwardDeclared.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Incomplete;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ForwardDeclared.F(%self.param: %ForwardDeclared);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ForwardDeclared.G(%self.param: ref %ForwardDeclared);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- b.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Empty: type = class_type @Empty [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.37d: type = pattern_type %Empty [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Empty.val: %Empty = struct_value () [concrete]\n// CHECK:STDOUT:   %Field: type = class_type @Field [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.x.767: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.c07: <witness> = complete_type_witness %struct_type.x.767 [concrete]\n// CHECK:STDOUT:   %pattern_type.729: type = pattern_type %Field [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.x.c96: type = struct_type {.x: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.x.c96 = struct_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cf3: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.255: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.58d: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.e45, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.cf3 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.58d) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.979: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.7c3: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.979, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f07: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.307: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.47b: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Field.val: %Field = struct_value (%int_1.47b) [concrete]\n// CHECK:STDOUT:   %Field.elem: type = unbound_element_type %Field, %i32 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.1eb: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4 [concrete]\n// CHECK:STDOUT:   %bound_method.ef3: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.d0d: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.20f323.1: type = class_type @ForwardDeclared.1 [concrete]\n// CHECK:STDOUT:   %pattern_type.af1: type = pattern_type %ForwardDeclared.20f323.1 [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.val: %ForwardDeclared.20f323.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.F.type: type = fn_type @ForwardDeclared.F [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.F: %ForwardDeclared.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.G.type: type = fn_type @ForwardDeclared.G [concrete]\n// CHECK:STDOUT:   %ForwardDeclared.G: %ForwardDeclared.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.006: type = ptr_type %ForwardDeclared.20f323.1 [concrete]\n// CHECK:STDOUT:   %pattern_type.77e: type = pattern_type %ptr.006 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.bef: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%ForwardDeclared.20f323.1) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.5ba: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%ForwardDeclared.20f323.1) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.d3c: %ptr.as.Copy.impl.Op.type.5ba = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.006, (%Copy.impl_witness.bef) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.4e2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.89b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.4e2, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.d3c, @ptr.as.Copy.impl.Op(%ForwardDeclared.20f323.1) [concrete]\n// CHECK:STDOUT:   %Incomplete: type = class_type @Incomplete [concrete]\n// CHECK:STDOUT:   %ptr.8c3: type = ptr_type %Incomplete [concrete]\n// CHECK:STDOUT:   %pattern_type.b98: type = pattern_type %ptr.8c3 [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.fb9: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%ptr.8c3) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.3ad: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%ptr.8c3) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.5f6: %T.as.DefaultOrUnformed.impl.Op.type.3ad = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %ptr.8c3, (%DefaultOrUnformed.impl_witness.fb9) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.5f6, @T.as.DefaultOrUnformed.impl.Op(%ptr.8c3) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc18 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc16 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc12 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.4: type = fn_type @Destroy.Op.loc9 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.4: %Destroy.Op.type.bae255.4 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.5: type = fn_type @Destroy.Op.loc7 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.5: %Destroy.Op.type.bae255.5 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Empty: type = import_ref Main//a, Empty, loaded [concrete = constants.%Empty]\n// CHECK:STDOUT:   %Main.Field: type = import_ref Main//a, Field, loaded [concrete = constants.%Field]\n// CHECK:STDOUT:   %Main.ForwardDeclared: type = import_ref Main//a, ForwardDeclared, loaded [concrete = constants.%ForwardDeclared.20f323.1]\n// CHECK:STDOUT:   %Main.Incomplete: type = import_ref Main//a, Incomplete, loaded [concrete = constants.%Incomplete]\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f24d3.1: <witness> = import_ref Main//a, loc5_1, loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.d52 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.709: <witness> = import_ref Main//a, loc9_1, loaded [concrete = constants.%complete_type.c07]\n// CHECK:STDOUT:   %Main.import_ref.07a = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.df7: %Field.elem = import_ref Main//a, loc8_8, loaded [concrete = %.afd]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.b25: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.255)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.e45 = impl_witness_table (%Core.import_ref.b25), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %.afd: %Field.elem = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %Main.import_ref.8f24d3.2: <witness> = import_ref Main//a, loc16_1, loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.a87cf6.1 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.019: %ForwardDeclared.F.type = import_ref Main//a, loc14_21, loaded [concrete = constants.%ForwardDeclared.F]\n// CHECK:STDOUT:   %Main.import_ref.a45: %ForwardDeclared.G.type = import_ref Main//a, loc15_25, loaded [concrete = constants.%ForwardDeclared.G]\n// CHECK:STDOUT:   %Main.import_ref.8f24d3.3: <witness> = import_ref Main//a, loc16_1, loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.a87cf6.2 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.a44 = import_ref Main//a, loc14_21, unloaded\n// CHECK:STDOUT:   %Main.import_ref.38a = import_ref Main//a, loc15_25, unloaded\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Empty = imports.%Main.Empty\n// CHECK:STDOUT:     .Field = imports.%Main.Field\n// CHECK:STDOUT:     .ForwardDeclared = imports.%Main.ForwardDeclared\n// CHECK:STDOUT:     .Incomplete = imports.%Main.Incomplete\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Empty [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f24d3.1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.d52\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Field [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.709\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.07a\n// CHECK:STDOUT:   .x = imports.%Main.import_ref.df7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ForwardDeclared.1 [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f24d3.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a87cf6.1\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.019\n// CHECK:STDOUT:   .G = imports.%Main.import_ref.a45\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ForwardDeclared.2 [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f24d3.3\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a87cf6.2\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.a44\n// CHECK:STDOUT:   .G = imports.%Main.import_ref.38a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Incomplete [from \"a.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.37d = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.37d = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %Empty = var %a.var_patt\n// CHECK:STDOUT:   %.loc7_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc7_26.2: init %Empty to %a.var = class_init () [concrete = constants.%Empty.val]\n// CHECK:STDOUT:   %.loc7_3: init %Empty = converted %.loc7_26.1, %.loc7_26.2 [concrete = constants.%Empty.val]\n// CHECK:STDOUT:   assign %a.var, %.loc7_3\n// CHECK:STDOUT:   %Empty.ref: type = name_ref Empty, imports.%Main.Empty [concrete = constants.%Empty]\n// CHECK:STDOUT:   %a: ref %Empty = ref_binding a, %a.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.729 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.729 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %Field = var %b.var_patt\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc9_25.1: %struct_type.x.c96 = struct_literal (%int_1) [concrete = constants.%struct]\n// CHECK:STDOUT:   %impl.elem0.loc9: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc9_25.1: <bound method> = bound_method %int_1, %impl.elem0.loc9 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f07]\n// CHECK:STDOUT:   %specific_fn.loc9: <specific function> = specific_function %impl.elem0.loc9, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_25.2: <bound method> = bound_method %int_1, %specific_fn.loc9 [concrete = constants.%bound_method.307]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9: init %i32 = call %bound_method.loc9_25.2(%int_1) [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc9_25.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc9_25.3: ref %i32 = class_element_access %b.var, element0\n// CHECK:STDOUT:   %.loc9_25.4: init %i32 to %.loc9_25.3 = in_place_init %.loc9_25.2 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc9_25.5: init %Field to %b.var = class_init (%.loc9_25.4) [concrete = constants.%Field.val]\n// CHECK:STDOUT:   %.loc9_3: init %Field = converted %.loc9_25.1, %.loc9_25.5 [concrete = constants.%Field.val]\n// CHECK:STDOUT:   assign %b.var, %.loc9_3\n// CHECK:STDOUT:   %Field.ref: type = name_ref Field, imports.%Main.Field [concrete = constants.%Field]\n// CHECK:STDOUT:   %b: ref %Field = ref_binding b, %b.var\n// CHECK:STDOUT:   %b.ref: ref %Field = name_ref b, %b\n// CHECK:STDOUT:   %x.ref: %Field.elem = name_ref x, imports.%Main.import_ref.df7 [concrete = imports.%.afd]\n// CHECK:STDOUT:   %.loc10_4: ref %i32 = class_element_access %b.ref, element0\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc10: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc10_7.1: <bound method> = bound_method %int_2, %impl.elem0.loc10 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.1eb]\n// CHECK:STDOUT:   %specific_fn.loc10: <specific function> = specific_function %impl.elem0.loc10, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_7.2: <bound method> = bound_method %int_2, %specific_fn.loc10 [concrete = constants.%bound_method.ef3]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10: init %i32 = call %bound_method.loc10_7.2(%int_2) [concrete = constants.%int_2.d0d]\n// CHECK:STDOUT:   %.loc10_7: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10 [concrete = constants.%int_2.d0d]\n// CHECK:STDOUT:   assign %.loc10_4, %.loc10_7\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.af1 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.af1 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %ForwardDeclared.20f323.1 = var %c.var_patt\n// CHECK:STDOUT:   %.loc12_29.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc12_29.2: init %ForwardDeclared.20f323.1 to %c.var = class_init () [concrete = constants.%ForwardDeclared.val]\n// CHECK:STDOUT:   %.loc12_3: init %ForwardDeclared.20f323.1 = converted %.loc12_29.1, %.loc12_29.2 [concrete = constants.%ForwardDeclared.val]\n// CHECK:STDOUT:   assign %c.var, %.loc12_3\n// CHECK:STDOUT:   %ForwardDeclared.ref.loc12: type = name_ref ForwardDeclared, imports.%Main.ForwardDeclared [concrete = constants.%ForwardDeclared.20f323.1]\n// CHECK:STDOUT:   %c: ref %ForwardDeclared.20f323.1 = ref_binding c, %c.var\n// CHECK:STDOUT:   %c.ref.loc13: ref %ForwardDeclared.20f323.1 = name_ref c, %c\n// CHECK:STDOUT:   %F.ref: %ForwardDeclared.F.type = name_ref F, imports.%Main.import_ref.019 [concrete = constants.%ForwardDeclared.F]\n// CHECK:STDOUT:   %ForwardDeclared.F.bound: <bound method> = bound_method %c.ref.loc13, %F.ref\n// CHECK:STDOUT:   %.loc13: %ForwardDeclared.20f323.1 = acquire_value %c.ref.loc13\n// CHECK:STDOUT:   %ForwardDeclared.F.call: init %empty_tuple.type = call %ForwardDeclared.F.bound(%.loc13)\n// CHECK:STDOUT:   %c.ref.loc14: ref %ForwardDeclared.20f323.1 = name_ref c, %c\n// CHECK:STDOUT:   %G.ref: %ForwardDeclared.G.type = name_ref G, imports.%Main.import_ref.a45 [concrete = constants.%ForwardDeclared.G]\n// CHECK:STDOUT:   %ForwardDeclared.G.bound: <bound method> = bound_method %c.ref.loc14, %G.ref\n// CHECK:STDOUT:   %ForwardDeclared.G.call: init %empty_tuple.type = call %ForwardDeclared.G.bound(%c.ref.loc14)\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.77e = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.77e = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %ptr.006 = var %d.var_patt\n// CHECK:STDOUT:   %c.ref.loc16: ref %ForwardDeclared.20f323.1 = name_ref c, %c\n// CHECK:STDOUT:   %addr: %ptr.006 = addr_of %c.ref.loc16\n// CHECK:STDOUT:   %impl.elem0.loc16: %.89b = impl_witness_access constants.%Copy.impl_witness.bef, element0 [concrete = constants.%ptr.as.Copy.impl.Op.d3c]\n// CHECK:STDOUT:   %bound_method.loc16_36.1: <bound method> = bound_method %addr, %impl.elem0.loc16\n// CHECK:STDOUT:   %specific_fn.loc16: <specific function> = specific_function %impl.elem0.loc16, @ptr.as.Copy.impl.Op(constants.%ForwardDeclared.20f323.1) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_36.2: <bound method> = bound_method %addr, %specific_fn.loc16\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.006 = call %bound_method.loc16_36.2(%addr)\n// CHECK:STDOUT:   assign %d.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   %.loc16: type = splice_block %ptr.loc16 [concrete = constants.%ptr.006] {\n// CHECK:STDOUT:     %ForwardDeclared.ref.loc16: type = name_ref ForwardDeclared, imports.%Main.ForwardDeclared [concrete = constants.%ForwardDeclared.20f323.1]\n// CHECK:STDOUT:     %ptr.loc16: type = ptr_type %ForwardDeclared.ref.loc16 [concrete = constants.%ptr.006]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %ptr.006 = ref_binding d, %d.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %e.patt: %pattern_type.b98 = ref_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.var_patt: %pattern_type.b98 = var_pattern %e.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e.var: ref %ptr.8c3 = var %e.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%ptr.8c3, (constants.%DefaultOrUnformed.impl_witness.fb9) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc18_28.1: %DefaultOrUnformed.type = converted constants.%ptr.8c3, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc18_28.1 [concrete = constants.%ptr.8c3]\n// CHECK:STDOUT:   %.loc18_28.2: type = converted %.loc18_28.1, %as_type [concrete = constants.%ptr.8c3]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.5f6, @T.as.DefaultOrUnformed.impl.Op(constants.%ptr.8c3) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %ptr.8c3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %e.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %.loc18_27: type = splice_block %ptr.loc18 [concrete = constants.%ptr.8c3] {\n// CHECK:STDOUT:     %Incomplete.ref: type = name_ref Incomplete, imports.%Main.Incomplete [concrete = constants.%Incomplete]\n// CHECK:STDOUT:     %ptr.loc18: type = ptr_type %Incomplete.ref [concrete = constants.%ptr.8c3]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e: ref %ptr.8c3 = ref_binding e, %e.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc18: <bound method> = bound_method %e.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc18: init %empty_tuple.type = call %Destroy.Op.bound.loc18(%e.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc16: <bound method> = bound_method %d.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc16: init %empty_tuple.type = call %Destroy.Op.bound.loc16(%d.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc12: <bound method> = bound_method %c.var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc12: init %empty_tuple.type = call %Destroy.Op.bound.loc12(%c.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc9: <bound method> = bound_method %b.var, constants.%Destroy.Op.651ba6.4\n// CHECK:STDOUT:   %Destroy.Op.call.loc9: init %empty_tuple.type = call %Destroy.Op.bound.loc9(%b.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc7: <bound method> = bound_method %a.var, constants.%Destroy.Op.651ba6.5\n// CHECK:STDOUT:   %Destroy.Op.call.loc7: init %empty_tuple.type = call %Destroy.Op.bound.loc7(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ForwardDeclared.F [from \"a.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ForwardDeclared.G [from \"a.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc18(%self.param: ref %ptr.8c3) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc16(%self.param: ref %ptr.006) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc12(%self.param: ref %ForwardDeclared.20f323.1) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc9(%self.param: ref %Field) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc7(%self.param: ref %Empty) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/import_forward_decl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/import_forward_decl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/import_forward_decl.carbon\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass ForwardDecl;\n\n// --- a.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nclass ForwardDecl {\n}\n\n// CHECK:STDOUT: --- a.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %ForwardDecl: type = class_type @ForwardDecl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ForwardDecl = %ForwardDecl.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ForwardDecl.decl: type = class_decl @ForwardDecl [concrete = constants.%ForwardDecl] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ForwardDecl;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- a.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %ForwardDecl: type = class_type @ForwardDecl [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .ForwardDecl = %ForwardDecl.decl\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_17.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_17.2 = import <none>\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ForwardDecl.decl: type = class_decl @ForwardDecl [concrete = constants.%ForwardDecl] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ForwardDecl {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%ForwardDecl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/import_indirect.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/import_indirect.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/import_indirect.carbon\n\n// Triangle:\n//\n//     a    <-- Define\n//     |\\\n//     | b  <-- Re-export\n//     |/\n//     X    <-- Use both\n//\n// Diamond:\n//\n//     a    <-- Define\n//    / \\\n//   b   c  <-- Re-export\n//    \\ /\n//     X    <-- Use both\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// --- b.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\n\nalias D = C;\n\nvar b_val: C = {};\nvar b_ptr: D* = &b_val;\n\n// --- c.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\n\nalias E = C;\n\nvar c_val: C = {};\nvar c_ptr: E* = &c_val;\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- triangle.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\nimport library \"b\";\n\nvar value: C = {};\nvar ptr: D* = &value;\n\n// --- triangle_reverse.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"b\";\nimport library \"a\";\n\nvar value: C = {};\nvar ptr: D* = &value;\n\n// --- diamond.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"b\";\nimport library \"c\";\n\nvar value: D = {};\nvar ptr: E* = &value;\n\n// --- diamond_reverse.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"c\";\nimport library \"b\";\n\nvar value: D = {};\nvar ptr: E* = &value;\n\n// CHECK:STDOUT: --- a.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- b.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of file.%b_val.var [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.411: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.ed9: %ptr.as.Copy.impl.Op.type.411 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.259: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.64b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.259, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.bound: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.ed9 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.ed9, @ptr.as.Copy.impl.Op(%C) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//a, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//a, loc4_10, loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .b_val = %b_val\n// CHECK:STDOUT:     .b_ptr = %b_ptr\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C.ref.loc6: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b_val.patt: %pattern_type.7c7 = ref_binding_pattern b_val [concrete]\n// CHECK:STDOUT:     %b_val.var_patt: %pattern_type.7c7 = var_pattern %b_val.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b_val.var: ref %C = var %b_val.var_patt [concrete]\n// CHECK:STDOUT:   %C.ref.loc8: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %b_val: ref %C = ref_binding b_val, %b_val.var [concrete = %b_val.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b_ptr.patt: %pattern_type.506 = ref_binding_pattern b_ptr [concrete]\n// CHECK:STDOUT:     %b_ptr.var_patt: %pattern_type.506 = var_pattern %b_ptr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b_ptr.var: ref %ptr.31e = var %b_ptr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc9: type = splice_block %ptr [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, %D [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr: type = ptr_type %D.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b_ptr: ref %ptr.31e = ref_binding b_ptr, %b_ptr.var [concrete = %b_ptr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc8_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc8_17.2: init %C to file.%b_val.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc8_1: init %C = converted %.loc8_17.1, %.loc8_17.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%b_val.var, %.loc8_1\n// CHECK:STDOUT:   %b_val.ref: ref %C = name_ref b_val, file.%b_val [concrete = file.%b_val.var]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of %b_val.ref [concrete = constants.%addr]\n// CHECK:STDOUT:   %impl.elem0: %.64b = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9]\n// CHECK:STDOUT:   %bound_method.loc9_17.1: <bound method> = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_17.2: <bound method> = bound_method %addr, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.31e = call %bound_method.loc9_17.2(%addr) [concrete = constants.%addr]\n// CHECK:STDOUT:   assign file.%b_ptr.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- c.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of file.%c_val.var [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.411: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.ed9: %ptr.as.Copy.impl.Op.type.411 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.259: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.64b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.259, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.bound: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.ed9 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.ed9, @ptr.as.Copy.impl.Op(%C) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//a, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//a, loc4_10, loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .E = %E\n// CHECK:STDOUT:     .c_val = %c_val\n// CHECK:STDOUT:     .c_ptr = %c_ptr\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C.ref.loc6: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %E: type = alias_binding E, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c_val.patt: %pattern_type.7c7 = ref_binding_pattern c_val [concrete]\n// CHECK:STDOUT:     %c_val.var_patt: %pattern_type.7c7 = var_pattern %c_val.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c_val.var: ref %C = var %c_val.var_patt [concrete]\n// CHECK:STDOUT:   %C.ref.loc8: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %c_val: ref %C = ref_binding c_val, %c_val.var [concrete = %c_val.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c_ptr.patt: %pattern_type.506 = ref_binding_pattern c_ptr [concrete]\n// CHECK:STDOUT:     %c_ptr.var_patt: %pattern_type.506 = var_pattern %c_ptr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c_ptr.var: ref %ptr.31e = var %c_ptr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc9: type = splice_block %ptr [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:     %E.ref: type = name_ref E, %E [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr: type = ptr_type %E.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c_ptr: ref %ptr.31e = ref_binding c_ptr, %c_ptr.var [concrete = %c_ptr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc8_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc8_17.2: init %C to file.%c_val.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc8_1: init %C = converted %.loc8_17.1, %.loc8_17.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%c_val.var, %.loc8_1\n// CHECK:STDOUT:   %c_val.ref: ref %C = name_ref c_val, file.%c_val [concrete = file.%c_val.var]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of %c_val.ref [concrete = constants.%addr]\n// CHECK:STDOUT:   %impl.elem0: %.64b = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9]\n// CHECK:STDOUT:   %bound_method.loc9_17.1: <bound method> = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_17.2: <bound method> = bound_method %addr, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.31e = call %bound_method.loc9_17.2(%addr) [concrete = constants.%addr]\n// CHECK:STDOUT:   assign file.%c_ptr.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- triangle.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of file.%value.var [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.411: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.ed9: %ptr.as.Copy.impl.Op.type.411 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.259: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.64b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.259, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.bound: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.ed9 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.ed9, @ptr.as.Copy.impl.Op(%C) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//a, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//b, D, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.b_val = import_ref Main//b, b_val, unloaded\n// CHECK:STDOUT:   %Main.b_ptr = import_ref Main//b, b_ptr, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//a, loc4_10, loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .b_val = imports.%Main.b_val\n// CHECK:STDOUT:     .b_ptr = imports.%Main.b_ptr\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .value = %value\n// CHECK:STDOUT:     .ptr = %ptr.loc8_5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %value.patt: %pattern_type.7c7 = ref_binding_pattern value [concrete]\n// CHECK:STDOUT:     %value.var_patt: %pattern_type.7c7 = var_pattern %value.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.var: ref %C = var %value.var_patt [concrete]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %value: ref %C = ref_binding value, %value.var [concrete = %value.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %ptr.patt: %pattern_type.506 = ref_binding_pattern ptr [concrete]\n// CHECK:STDOUT:     %ptr.var_patt: %pattern_type.506 = var_pattern %ptr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.var: ref %ptr.31e = var %ptr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %ptr.loc8_11 [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr.loc8_11: type = ptr_type %D.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.loc8_5: ref %ptr.31e = ref_binding ptr, %ptr.var [concrete = %ptr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc7_17.2: init %C to file.%value.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc7_1: init %C = converted %.loc7_17.1, %.loc7_17.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%value.var, %.loc7_1\n// CHECK:STDOUT:   %value.ref: ref %C = name_ref value, file.%value [concrete = file.%value.var]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of %value.ref [concrete = constants.%addr]\n// CHECK:STDOUT:   %impl.elem0: %.64b = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9]\n// CHECK:STDOUT:   %bound_method.loc8_15.1: <bound method> = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_15.2: <bound method> = bound_method %addr, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.31e = call %bound_method.loc8_15.2(%addr) [concrete = constants.%addr]\n// CHECK:STDOUT:   assign file.%ptr.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- triangle_reverse.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of file.%value.var [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.411: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.ed9: %ptr.as.Copy.impl.Op.type.411 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.259: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.64b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.259, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.bound: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.ed9 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.ed9, @ptr.as.Copy.impl.Op(%C) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//b, D, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.b_val = import_ref Main//b, b_val, unloaded\n// CHECK:STDOUT:   %Main.b_ptr = import_ref Main//b, b_ptr, unloaded\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//a, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//a, loc4_10, loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .b_val = imports.%Main.b_val\n// CHECK:STDOUT:     .b_ptr = imports.%Main.b_ptr\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .value = %value\n// CHECK:STDOUT:     .ptr = %ptr.loc8_5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %value.patt: %pattern_type.7c7 = ref_binding_pattern value [concrete]\n// CHECK:STDOUT:     %value.var_patt: %pattern_type.7c7 = var_pattern %value.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.var: ref %C = var %value.var_patt [concrete]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %value: ref %C = ref_binding value, %value.var [concrete = %value.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %ptr.patt: %pattern_type.506 = ref_binding_pattern ptr [concrete]\n// CHECK:STDOUT:     %ptr.var_patt: %pattern_type.506 = var_pattern %ptr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.var: ref %ptr.31e = var %ptr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %ptr.loc8_11 [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr.loc8_11: type = ptr_type %D.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.loc8_5: ref %ptr.31e = ref_binding ptr, %ptr.var [concrete = %ptr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc7_17.2: init %C to file.%value.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc7_1: init %C = converted %.loc7_17.1, %.loc7_17.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%value.var, %.loc7_1\n// CHECK:STDOUT:   %value.ref: ref %C = name_ref value, file.%value [concrete = file.%value.var]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of %value.ref [concrete = constants.%addr]\n// CHECK:STDOUT:   %impl.elem0: %.64b = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9]\n// CHECK:STDOUT:   %bound_method.loc8_15.1: <bound method> = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_15.2: <bound method> = bound_method %addr, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.31e = call %bound_method.loc8_15.2(%addr) [concrete = constants.%addr]\n// CHECK:STDOUT:   assign file.%ptr.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- diamond.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of file.%value.var [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.411: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.ed9: %ptr.as.Copy.impl.Op.type.411 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.259: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.64b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.259, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.bound: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.ed9 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.ed9, @ptr.as.Copy.impl.Op(%C) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//b, D, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.b_val = import_ref Main//b, b_val, unloaded\n// CHECK:STDOUT:   %Main.b_ptr = import_ref Main//b, b_ptr, unloaded\n// CHECK:STDOUT:   %Main.E: type = import_ref Main//c, E, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.c_val = import_ref Main//c, c_val, unloaded\n// CHECK:STDOUT:   %Main.c_ptr = import_ref Main//c, c_ptr, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8db: <witness> = import_ref Main//b, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.a60 = import_ref Main//b, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .b_val = imports.%Main.b_val\n// CHECK:STDOUT:     .b_ptr = imports.%Main.b_ptr\n// CHECK:STDOUT:     .E = imports.%Main.E\n// CHECK:STDOUT:     .c_val = imports.%Main.c_val\n// CHECK:STDOUT:     .c_ptr = imports.%Main.c_ptr\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .value = %value\n// CHECK:STDOUT:     .ptr = %ptr.loc8_5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %value.patt: %pattern_type.7c7 = ref_binding_pattern value [concrete]\n// CHECK:STDOUT:     %value.var_patt: %pattern_type.7c7 = var_pattern %value.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.var: ref %C = var %value.var_patt [concrete]\n// CHECK:STDOUT:   %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C]\n// CHECK:STDOUT:   %value: ref %C = ref_binding value, %value.var [concrete = %value.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %ptr.patt: %pattern_type.506 = ref_binding_pattern ptr [concrete]\n// CHECK:STDOUT:     %ptr.var_patt: %pattern_type.506 = var_pattern %ptr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.var: ref %ptr.31e = var %ptr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %ptr.loc8_11 [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:     %E.ref: type = name_ref E, imports.%Main.E [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr.loc8_11: type = ptr_type %E.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.loc8_5: ref %ptr.31e = ref_binding ptr, %ptr.var [concrete = %ptr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"b.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a60\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc7_17.2: init %C to file.%value.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc7_1: init %C = converted %.loc7_17.1, %.loc7_17.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%value.var, %.loc7_1\n// CHECK:STDOUT:   %value.ref: ref %C = name_ref value, file.%value [concrete = file.%value.var]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of %value.ref [concrete = constants.%addr]\n// CHECK:STDOUT:   %impl.elem0: %.64b = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9]\n// CHECK:STDOUT:   %bound_method.loc8_15.1: <bound method> = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_15.2: <bound method> = bound_method %addr, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.31e = call %bound_method.loc8_15.2(%addr) [concrete = constants.%addr]\n// CHECK:STDOUT:   assign file.%ptr.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- diamond_reverse.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of file.%value.var [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.411: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.ed9: %ptr.as.Copy.impl.Op.type.411 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.259: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.64b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.259, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.bound: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.ed9 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.ed9, @ptr.as.Copy.impl.Op(%C) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.E: type = import_ref Main//c, E, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.c_val = import_ref Main//c, c_val, unloaded\n// CHECK:STDOUT:   %Main.c_ptr = import_ref Main//c, c_ptr, unloaded\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//b, D, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.b_val = import_ref Main//b, b_val, unloaded\n// CHECK:STDOUT:   %Main.b_ptr = import_ref Main//b, b_ptr, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8db: <witness> = import_ref Main//b, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   %Main.import_ref.a60 = import_ref Main//b, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .E = imports.%Main.E\n// CHECK:STDOUT:     .c_val = imports.%Main.c_val\n// CHECK:STDOUT:     .c_ptr = imports.%Main.c_ptr\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .b_val = imports.%Main.b_val\n// CHECK:STDOUT:     .b_ptr = imports.%Main.b_ptr\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .value = %value\n// CHECK:STDOUT:     .ptr = %ptr.loc8_5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %value.patt: %pattern_type.7c7 = ref_binding_pattern value [concrete]\n// CHECK:STDOUT:     %value.var_patt: %pattern_type.7c7 = var_pattern %value.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %value.var: ref %C = var %value.var_patt [concrete]\n// CHECK:STDOUT:   %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C]\n// CHECK:STDOUT:   %value: ref %C = ref_binding value, %value.var [concrete = %value.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %ptr.patt: %pattern_type.506 = ref_binding_pattern ptr [concrete]\n// CHECK:STDOUT:     %ptr.var_patt: %pattern_type.506 = var_pattern %ptr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.var: ref %ptr.31e = var %ptr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %ptr.loc8_11 [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:     %E.ref: type = name_ref E, imports.%Main.E [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr.loc8_11: type = ptr_type %E.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ptr.loc8_5: ref %ptr.31e = ref_binding ptr, %ptr.var [concrete = %ptr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"b.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a60\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc7_17.2: init %C to file.%value.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc7_1: init %C = converted %.loc7_17.1, %.loc7_17.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign file.%value.var, %.loc7_1\n// CHECK:STDOUT:   %value.ref: ref %C = name_ref value, file.%value [concrete = file.%value.var]\n// CHECK:STDOUT:   %addr: %ptr.31e = addr_of %value.ref [concrete = constants.%addr]\n// CHECK:STDOUT:   %impl.elem0: %.64b = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9]\n// CHECK:STDOUT:   %bound_method.loc8_15.1: <bound method> = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_15.2: <bound method> = bound_method %addr, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.31e = call %bound_method.loc8_15.2(%addr) [concrete = constants.%addr]\n// CHECK:STDOUT:   assign file.%ptr.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/import_member_cycle.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/import_member_cycle.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/import_member_cycle.carbon\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Cycle {\n  var a: Cycle*;\n}\n\n// --- b.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\n\nfn Run() {\n  var unused a: Cycle*;\n}\n\n// CHECK:STDOUT: --- a.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Cycle: type = class_type @Cycle [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %Cycle [concrete]\n// CHECK:STDOUT:   %Cycle.elem: type = unbound_element_type %Cycle, %ptr [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %ptr} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Cycle = %Cycle.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Cycle.decl: type = class_decl @Cycle [concrete = constants.%Cycle] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Cycle {\n// CHECK:STDOUT:   %Cycle.ref: type = name_ref Cycle, file.%Cycle.decl [concrete = constants.%Cycle]\n// CHECK:STDOUT:   %ptr: type = ptr_type %Cycle.ref [concrete = constants.%ptr]\n// CHECK:STDOUT:   %.loc5: %Cycle.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Cycle\n// CHECK:STDOUT:   .Cycle = <poisoned>\n// CHECK:STDOUT:   .a = %.loc5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- b.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Cycle: type = class_type @Cycle [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %Cycle [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %ptr} [concrete]\n// CHECK:STDOUT:   %complete_type.e68: <witness> = complete_type_witness %struct_type.a [concrete]\n// CHECK:STDOUT:   %pattern_type.e31: type = pattern_type %ptr [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.446: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%ptr) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.4d8: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%ptr) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.1cb: %T.as.DefaultOrUnformed.impl.Op.type.4d8 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %ptr, (%DefaultOrUnformed.impl_witness.446) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.1cb, @T.as.DefaultOrUnformed.impl.Op(%ptr) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Cycle: type = import_ref Main//a, Cycle, loaded [concrete = constants.%Cycle]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.4e3: <witness> = import_ref Main//a, loc6_1, loaded [concrete = constants.%complete_type.e68]\n// CHECK:STDOUT:   %Main.import_ref.fd1 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.465 = import_ref Main//a, loc5_8, unloaded\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Cycle = imports.%Main.Cycle\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Cycle [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.4e3\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.fd1\n// CHECK:STDOUT:   .a = imports.%Main.import_ref.465\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.e31 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.e31 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %ptr = var %a.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%ptr, (constants.%DefaultOrUnformed.impl_witness.446) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc7_23.1: %DefaultOrUnformed.type = converted constants.%ptr, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc7_23.1 [concrete = constants.%ptr]\n// CHECK:STDOUT:   %.loc7_23.2: type = converted %.loc7_23.1, %as_type [concrete = constants.%ptr]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.1cb, @T.as.DefaultOrUnformed.impl.Op(constants.%ptr) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %ptr = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %a.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %.loc7_22: type = splice_block %ptr [concrete = constants.%ptr] {\n// CHECK:STDOUT:     %Cycle.ref: type = name_ref Cycle, imports.%Main.Cycle [concrete = constants.%Cycle]\n// CHECK:STDOUT:     %ptr: type = ptr_type %Cycle.ref [concrete = constants.%ptr]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %ptr = ref_binding a, %a.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %ptr) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/import_struct_cycle.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/import_struct_cycle.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/import_struct_cycle.carbon\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Cycle;\n\nvar a: {.b: Cycle*};\n\nclass Cycle {\n  // The type here is equivalent to the `a` above, but on import can be resolved first.\n  var c: {.b: Cycle*};\n}\n\n// --- b.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\n\nfn Run() {\n  a.b = (*a.b).c.b;\n}\n\n// CHECK:STDOUT: --- a.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Cycle: type = class_type @Cycle [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %Cycle [concrete]\n// CHECK:STDOUT:   %struct_type.b: type = struct_type {.b: %ptr} [concrete]\n// CHECK:STDOUT:   %pattern_type.d79: type = pattern_type %struct_type.b [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.64d: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%struct_type.b) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.d8d: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%struct_type.b) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.654: %T.as.DefaultOrUnformed.impl.Op.type.d8d = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %struct_type.b, (%DefaultOrUnformed.impl_witness.64d) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.654, @T.as.DefaultOrUnformed.impl.Op(%struct_type.b) [concrete]\n// CHECK:STDOUT:   %Cycle.elem: type = unbound_element_type %Cycle, %struct_type.b [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %struct_type.b} [concrete]\n// CHECK:STDOUT:   %complete_type.3fc: <witness> = complete_type_witness %struct_type.c [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Cycle = %Cycle.decl.loc4\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Cycle.decl.loc4: type = class_decl @Cycle [concrete = constants.%Cycle] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.d79 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.d79 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %struct_type.b = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6: type = splice_block %struct_type.b [concrete = constants.%struct_type.b] {\n// CHECK:STDOUT:     %Cycle.ref: type = name_ref Cycle, %Cycle.decl.loc4 [concrete = constants.%Cycle]\n// CHECK:STDOUT:     %ptr: type = ptr_type %Cycle.ref [concrete = constants.%ptr]\n// CHECK:STDOUT:     %struct_type.b: type = struct_type {.b: %ptr} [concrete = constants.%struct_type.b]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %struct_type.b = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   %Cycle.decl.loc8: type = class_decl @Cycle [concrete = constants.%Cycle] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Cycle {\n// CHECK:STDOUT:   %Cycle.ref: type = name_ref Cycle, file.%Cycle.decl.loc4 [concrete = constants.%Cycle]\n// CHECK:STDOUT:   %ptr: type = ptr_type %Cycle.ref [concrete = constants.%ptr]\n// CHECK:STDOUT:   %struct_type.b: type = struct_type {.b: %ptr} [concrete = constants.%struct_type.b]\n// CHECK:STDOUT:   %.loc10: %Cycle.elem = field_decl c, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.c [concrete = constants.%complete_type.3fc]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Cycle\n// CHECK:STDOUT:   .Cycle = <poisoned>\n// CHECK:STDOUT:   .c = %.loc10\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%struct_type.b, (constants.%DefaultOrUnformed.impl_witness.64d) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc6_20.1: %DefaultOrUnformed.type = converted constants.%struct_type.b, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc6_20.1 [concrete = constants.%struct_type.b]\n// CHECK:STDOUT:   %.loc6_20.2: type = converted %.loc6_20.1, %as_type [concrete = constants.%struct_type.b]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.654, @T.as.DefaultOrUnformed.impl.Op(constants.%struct_type.b) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %struct_type.b = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign file.%a.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- b.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Cycle: type = class_type @Cycle [concrete]\n// CHECK:STDOUT:   %ptr.e6c: type = ptr_type %Cycle [concrete]\n// CHECK:STDOUT:   %struct_type.b: type = struct_type {.b: %ptr.e6c} [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %struct_type.b} [concrete]\n// CHECK:STDOUT:   %complete_type.3fc: <witness> = complete_type_witness %struct_type.c [concrete]\n// CHECK:STDOUT:   %pattern_type.d79: type = pattern_type %struct_type.b [concrete]\n// CHECK:STDOUT:   %.c65: ref %ptr.e6c = struct_access imports.%a.var, element0 [concrete]\n// CHECK:STDOUT:   %Cycle.elem: type = unbound_element_type %Cycle, %struct_type.b [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.b7e: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%Cycle) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.6f4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%Cycle) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.7c8: %ptr.as.Copy.impl.Op.type.6f4 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e6c, (%Copy.impl_witness.b7e) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.706: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.e5b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.706, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.7c8, @ptr.as.Copy.impl.Op(%Cycle) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Cycle = import_ref Main//a, Cycle, unloaded\n// CHECK:STDOUT:   %Main.a: ref %struct_type.b = import_ref Main//a, a, loaded [concrete = %a.var]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.741: <witness> = import_ref Main//a, loc11_1, loaded [concrete = constants.%complete_type.3fc]\n// CHECK:STDOUT:   %Main.import_ref.fd1 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.c81: %Cycle.elem = import_ref Main//a, loc10_8, loaded [concrete = %.a9f]\n// CHECK:STDOUT:   %a.patt: %pattern_type.d79 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:   %a.var_patt: %pattern_type.d79 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   %a.var: ref %struct_type.b = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.a9f: %Cycle.elem = field_decl c, element0 [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Cycle = imports.%Main.Cycle\n// CHECK:STDOUT:     .a = imports.%Main.a\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Cycle [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.741\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.fd1\n// CHECK:STDOUT:   .c = imports.%Main.import_ref.c81\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref.loc7_3: ref %struct_type.b = name_ref a, imports.%Main.a [concrete = imports.%a.var]\n// CHECK:STDOUT:   %.loc7_4: ref %ptr.e6c = struct_access %a.ref.loc7_3, element0 [concrete = constants.%.c65]\n// CHECK:STDOUT:   %a.ref.loc7_11: ref %struct_type.b = name_ref a, imports.%Main.a [concrete = imports.%a.var]\n// CHECK:STDOUT:   %.loc7_12.1: ref %ptr.e6c = struct_access %a.ref.loc7_11, element0 [concrete = constants.%.c65]\n// CHECK:STDOUT:   %.loc7_12.2: %ptr.e6c = acquire_value %.loc7_12.1\n// CHECK:STDOUT:   %.loc7_10: ref %Cycle = deref %.loc7_12.2\n// CHECK:STDOUT:   %c.ref: %Cycle.elem = name_ref c, imports.%Main.import_ref.c81 [concrete = imports.%.a9f]\n// CHECK:STDOUT:   %.loc7_15: ref %struct_type.b = class_element_access %.loc7_10, element0\n// CHECK:STDOUT:   %.loc7_17.1: ref %ptr.e6c = struct_access %.loc7_15, element0\n// CHECK:STDOUT:   %.loc7_17.2: %ptr.e6c = acquire_value %.loc7_17.1\n// CHECK:STDOUT:   %impl.elem0: %.e5b = impl_witness_access constants.%Copy.impl_witness.b7e, element0 [concrete = constants.%ptr.as.Copy.impl.Op.7c8]\n// CHECK:STDOUT:   %bound_method.loc7_17.1: <bound method> = bound_method %.loc7_17.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%Cycle) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_17.2: <bound method> = bound_method %.loc7_17.2, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.e6c = call %bound_method.loc7_17.2(%.loc7_17.2)\n// CHECK:STDOUT:   assign %.loc7_4, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/incomplete_ref.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/incomplete_ref.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/incomplete_ref.carbon\n\nclass Class;\n\nclass IncompleteRefSelf {\n  fn F[ref self: Class]();\n}\n\nfn CallIncompleteRefSelf(p: Class*) {\n  p->(IncompleteRefSelf.F)();\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/indirect_import_member.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/indirect_import_member.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/indirect_import_member.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  fn F() {}\n}\n\n// --- b.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nexport import library \"a\";\n\n// --- c.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"b\";\n\nexport C;\n\n// --- d.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nexport import library \"c\";\n\n// --- e.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"c\";\n\nclass D {\n  alias C = package.C;\n}\n\n// --- f.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nexport import library \"e\";\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- use_b.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"b\";\n\nvar x: () = C.F();\n\n// --- use_c.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"c\";\n\nvar x: () = C.F();\n\n// --- use_d.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"d\";\n\nvar x: () = C.F();\n\n// --- use_e.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"e\";\n\nvar x: () = D.C.F();\n\n// --- use_f.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"f\";\n\nvar x: () = D.C.F();\n\n// CHECK:STDOUT: --- a.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %C.F.decl: %C.F.type = fn_decl @C.F [concrete = constants.%C.F] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .F = %C.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- b.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//a, C, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- c.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//a, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//a, loc6_1, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.071 = import_ref Main//a, loc5_10, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C: type = export C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.071\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- d.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//c, C, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- e.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//c, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8db: <witness> = import_ref Main//c, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.a60 = import_ref Main//c, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT:   %Main.import_ref.2b4 = import_ref Main//c, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %package.ref: <namespace> = name_ref package, package [concrete = package]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %C: type = alias_binding C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT:   .C = %C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"c.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a60\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.2b4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- f.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.D = import_ref Main//e, D, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_b.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//a, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//a, loc6_1, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.25c: %C.F.type = import_ref Main//a, loc5_10, loaded [concrete = constants.%C.F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %empty_tuple.type = var %x.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: ref %empty_tuple.type = ref_binding x, %x.var [concrete = %x.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.25c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F [from \"a.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref: %C.F.type = name_ref F, imports.%Main.import_ref.25c [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   assign file.%x.var, %C.F.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_c.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//c, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8db: <witness> = import_ref Main//c, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.a60 = import_ref Main//c, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT:   %Main.import_ref.7e5: %C.F.type = import_ref Main//c, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%C.F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %empty_tuple.type = var %x.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: ref %empty_tuple.type = ref_binding x, %x.var [concrete = %x.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"c.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a60\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.7e5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F [from \"a.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref: %C.F.type = name_ref F, imports.%Main.import_ref.7e5 [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   assign file.%x.var, %C.F.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_d.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//c, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8db: <witness> = import_ref Main//c, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.a60 = import_ref Main//c, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT:   %Main.import_ref.7e5: %C.F.type = import_ref Main//c, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%C.F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %empty_tuple.type = var %x.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: ref %empty_tuple.type = ref_binding x, %x.var [concrete = %x.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"c.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.a60\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.7e5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F [from \"a.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref: %C.F.type = name_ref F, imports.%Main.import_ref.7e5 [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   assign file.%x.var, %C.F.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_e.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//e, D, loaded [concrete = constants.%D]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//e, loc8_1, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.1d5 = import_ref Main//e, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.7a9: type = import_ref Main//e, loc7_9, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f3: <witness> = import_ref Main//e, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.76e = import_ref Main//e, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT:   %Main.import_ref.c63: %C.F.type = import_ref Main//e, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%C.F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %empty_tuple.type = var %x.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: ref %empty_tuple.type = ref_binding x, %x.var [concrete = %x.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D [from \"e.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.1d5\n// CHECK:STDOUT:   .C = imports.%Main.import_ref.7a9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"e.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f3\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.76e\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.c63\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F [from \"a.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.import_ref.7a9 [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref: %C.F.type = name_ref F, imports.%Main.import_ref.c63 [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   assign file.%x.var, %C.F.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_f.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//e, D, loaded [concrete = constants.%D]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//e, loc8_1, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.1d5 = import_ref Main//e, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.7a9: type = import_ref Main//e, loc7_9, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f3: <witness> = import_ref Main//e, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.76e = import_ref Main//e, inst{{[0-9A-F]+}} [indirect], unloaded\n// CHECK:STDOUT:   %Main.import_ref.c63: %C.F.type = import_ref Main//e, inst{{[0-9A-F]+}} [indirect], loaded [concrete = constants.%C.F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %empty_tuple.type = var %x.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: ref %empty_tuple.type = ref_binding x, %x.var [concrete = %x.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D [from \"e.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.1d5\n// CHECK:STDOUT:   .C = imports.%Main.import_ref.7a9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"e.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f3\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.76e\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.c63\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F [from \"a.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.import_ref.7a9 [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref: %C.F.type = name_ref F, imports.%Main.import_ref.c63 [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   assign file.%x.var, %C.F.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/base.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/base.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/base.carbon\n\n// --- base.carbon\npackage Base;\n\nbase class Base {\n  var b: i32;\n}\n\nclass Derived {\n  extend base: Base;\n\n  var d: i32;\n}\n\nfn Make() -> Derived {\n  return {.base = {.b = 4}, .d = 7};\n}\n\nfn Access(d: Derived) -> (i32, i32) {\n  return (d.d, d.base.b);\n}\n\n// --- fail_base_after_field.carbon\npackage BaseAfterField;\n\nbase class Base {\n}\n\nclass Derived {\n  var d: i32;\n\n  // CHECK:STDERR: fail_base_after_field.carbon:[[@LINE+4]]:3: error: `base` declaration must appear before field declarations [BaseDeclAfterFieldDecl]\n  // CHECK:STDERR:   extend base: Base;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend base: Base;\n}\n\n// CHECK:STDOUT: --- base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.b.0a3: type = struct_type {.b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.ba8: <witness> = complete_type_witness %struct_type.b.0a3 [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem.b58: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %Derived.elem.683: type = unbound_element_type %Derived, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.base.d.81a: type = struct_type {.base: %Base, .d: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.3b4: <witness> = complete_type_witness %struct_type.base.d.81a [concrete]\n// CHECK:STDOUT:   %.c4f: Core.Form = init_form %Derived [concrete]\n// CHECK:STDOUT:   %pattern_type.db9: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %struct_type.b.a15: type = struct_type {.b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.a2e: %struct_type.b.a15 = struct_value (%int_4.0c1) [concrete]\n// CHECK:STDOUT:   %int_7.29f: Core.IntLiteral = int_value 7 [concrete]\n// CHECK:STDOUT:   %struct_type.base.d.a20: type = struct_type {.base: %struct_type.b.a15, .d: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.ab7: %struct_type.base.d.a20 = struct_value (%struct.a2e, %int_7.29f) [concrete]\n// CHECK:STDOUT:   %.dfa: type = partial_type %Base [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.6d7: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_4.940: %i32 = int_value 4 [concrete]\n// CHECK:STDOUT:   %struct.5f8: %.dfa = struct_value (%int_4.940) [concrete]\n// CHECK:STDOUT:   %Base.val: %Base = struct_value (%int_4.940) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.1e0: <bound method> = bound_method %int_7.29f, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.bf2: <bound method> = bound_method %int_7.29f, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_7.0b1: %i32 = int_value 7 [concrete]\n// CHECK:STDOUT:   %Derived.val: %Derived = struct_value (%Base.val, %int_7.0b1) [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.95a: %tuple.type.24b = tuple_value (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %.f32: Core.Form = init_form %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %pattern_type.511: type = pattern_type %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %Access.type: type = fn_type @Access [concrete]\n// CHECK:STDOUT:   %Access: %Access.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .Make = %Make.decl\n// CHECK:STDOUT:     .Access = %Access.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Make.decl: %Make.type = fn_decl @Make [concrete = constants.%Make] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.db9 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.db9 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:     %.loc13: Core.Form = init_form %Derived.ref [concrete = constants.%.c4f]\n// CHECK:STDOUT:     %return.param: ref %Derived = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Derived = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Access.decl: %Access.type = fn_decl @Access [concrete = constants.%Access] {\n// CHECK:STDOUT:     %d.patt: %pattern_type.db9 = value_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.param_patt: %pattern_type.db9 = value_param_pattern %d.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.511 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.511 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc17_27: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %i32.loc17_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc17_35.1: %tuple.type.24b = tuple_literal (%i32.loc17_27, %i32.loc17_32) [concrete = constants.%tuple.95a]\n// CHECK:STDOUT:     %.loc17_35.2: type = converted %.loc17_35.1, constants.%tuple.type.d07 [concrete = constants.%tuple.type.d07]\n// CHECK:STDOUT:     %.loc17_35.3: Core.Form = init_form %.loc17_35.2 [concrete = constants.%.f32]\n// CHECK:STDOUT:     %d.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:     %d: %Derived = value_binding d, %d.param\n// CHECK:STDOUT:     %return.param: ref %tuple.type.d07 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %tuple.type.d07 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc4: %Base.elem = field_decl b, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.b.0a3 [concrete = constants.%complete_type.ba8]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .b = %.loc4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc8: %Derived.elem.b58 = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc10: %Derived.elem.683 = field_decl d, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.d.81a [concrete = constants.%complete_type.3b4]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc8\n// CHECK:STDOUT:   .d = %.loc10\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Make() -> out %return.param: %Derived {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]\n// CHECK:STDOUT:   %.loc14_26.1: %struct_type.b.a15 = struct_literal (%int_4) [concrete = constants.%struct.a2e]\n// CHECK:STDOUT:   %int_7: Core.IntLiteral = int_value 7 [concrete = constants.%int_7.29f]\n// CHECK:STDOUT:   %.loc14_35.1: %struct_type.base.d.a20 = struct_literal (%.loc14_26.1, %int_7) [concrete = constants.%struct.ab7]\n// CHECK:STDOUT:   %impl.elem0.loc14_26: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc14_26.1: <bound method> = bound_method %int_4, %impl.elem0.loc14_26 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c]\n// CHECK:STDOUT:   %specific_fn.loc14_26: <specific function> = specific_function %impl.elem0.loc14_26, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_26.2: <bound method> = bound_method %int_4, %specific_fn.loc14_26 [concrete = constants.%bound_method.6d7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_26: init %i32 = call %bound_method.loc14_26.2(%int_4) [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc14_26.2: init %i32 = converted %int_4, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_26 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc14_35.2: ref %.dfa = class_element_access %return.param, element0\n// CHECK:STDOUT:   %.loc14_26.3: ref %i32 = class_element_access %.loc14_35.2, element0\n// CHECK:STDOUT:   %.loc14_26.4: init %i32 to %.loc14_26.3 = in_place_init %.loc14_26.2 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc14_26.5: init %.dfa to %.loc14_35.2 = class_init (%.loc14_26.4) [concrete = constants.%struct.5f8]\n// CHECK:STDOUT:   %.loc14_35.3: init %.dfa = converted %.loc14_26.1, %.loc14_26.5 [concrete = constants.%struct.5f8]\n// CHECK:STDOUT:   %.loc14_35.4: init %Base = as_compatible %.loc14_35.3 [concrete = constants.%Base.val]\n// CHECK:STDOUT:   %impl.elem0.loc14_35: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc14_35.1: <bound method> = bound_method %int_7, %impl.elem0.loc14_35 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.1e0]\n// CHECK:STDOUT:   %specific_fn.loc14_35: <specific function> = specific_function %impl.elem0.loc14_35, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_35.2: <bound method> = bound_method %int_7, %specific_fn.loc14_35 [concrete = constants.%bound_method.bf2]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_35: init %i32 = call %bound_method.loc14_35.2(%int_7) [concrete = constants.%int_7.0b1]\n// CHECK:STDOUT:   %.loc14_35.5: init %i32 = converted %int_7, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_35 [concrete = constants.%int_7.0b1]\n// CHECK:STDOUT:   %.loc14_35.6: ref %i32 = class_element_access %return.param, element1\n// CHECK:STDOUT:   %.loc14_35.7: init %i32 to %.loc14_35.6 = in_place_init %.loc14_35.5 [concrete = constants.%int_7.0b1]\n// CHECK:STDOUT:   %.loc14_35.8: init %Derived to %return.param = class_init (%.loc14_35.4, %.loc14_35.7) [concrete = constants.%Derived.val]\n// CHECK:STDOUT:   %.loc14_36: init %Derived = converted %.loc14_35.1, %.loc14_35.8 [concrete = constants.%Derived.val]\n// CHECK:STDOUT:   return %.loc14_36 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Access(%d.param: %Derived) -> out %return.param: %tuple.type.d07 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %d.ref.loc18_11: %Derived = name_ref d, %d\n// CHECK:STDOUT:   %d.ref.loc18_12: %Derived.elem.683 = name_ref d, @Derived.%.loc10 [concrete = @Derived.%.loc10]\n// CHECK:STDOUT:   %.loc18_12.1: ref %i32 = class_element_access %d.ref.loc18_11, element1\n// CHECK:STDOUT:   %.loc18_12.2: %i32 = acquire_value %.loc18_12.1\n// CHECK:STDOUT:   %d.ref.loc18_16: %Derived = name_ref d, %d\n// CHECK:STDOUT:   %base.ref: %Derived.elem.b58 = name_ref base, @Derived.%.loc8 [concrete = @Derived.%.loc8]\n// CHECK:STDOUT:   %.loc18_17.1: ref %Base = class_element_access %d.ref.loc18_16, element0\n// CHECK:STDOUT:   %.loc18_17.2: %Base = acquire_value %.loc18_17.1\n// CHECK:STDOUT:   %b.ref: %Base.elem = name_ref b, @Base.%.loc4 [concrete = @Base.%.loc4]\n// CHECK:STDOUT:   %.loc18_22.1: ref %i32 = class_element_access %.loc18_17.2, element0\n// CHECK:STDOUT:   %.loc18_22.2: %i32 = acquire_value %.loc18_22.1\n// CHECK:STDOUT:   %.loc18_24.1: %tuple.type.d07 = tuple_literal (%.loc18_12.2, %.loc18_22.2)\n// CHECK:STDOUT:   %impl.elem0.loc18_12: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc18_12.1: <bound method> = bound_method %.loc18_12.2, %impl.elem0.loc18_12\n// CHECK:STDOUT:   %specific_fn.loc18_12: <specific function> = specific_function %impl.elem0.loc18_12, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_12.2: <bound method> = bound_method %.loc18_12.2, %specific_fn.loc18_12\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc18_12: init %i32 = call %bound_method.loc18_12.2(%.loc18_12.2)\n// CHECK:STDOUT:   %tuple.elem0: ref %i32 = tuple_access %return.param, element0\n// CHECK:STDOUT:   %.loc18_24.2: init %i32 to %tuple.elem0 = in_place_init %Int.as.Copy.impl.Op.call.loc18_12\n// CHECK:STDOUT:   %impl.elem0.loc18_22: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc18_22.1: <bound method> = bound_method %.loc18_22.2, %impl.elem0.loc18_22\n// CHECK:STDOUT:   %specific_fn.loc18_22: <specific function> = specific_function %impl.elem0.loc18_22, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_22.2: <bound method> = bound_method %.loc18_22.2, %specific_fn.loc18_22\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc18_22: init %i32 = call %bound_method.loc18_22.2(%.loc18_22.2)\n// CHECK:STDOUT:   %tuple.elem1: ref %i32 = tuple_access %return.param, element1\n// CHECK:STDOUT:   %.loc18_24.3: init %i32 to %tuple.elem1 = in_place_init %Int.as.Copy.impl.Op.call.loc18_22\n// CHECK:STDOUT:   %.loc18_24.4: init %tuple.type.d07 to %return.param = tuple_init (%.loc18_24.2, %.loc18_24.3)\n// CHECK:STDOUT:   %.loc18_25: init %tuple.type.d07 = converted %.loc18_24.1, %.loc18_24.4\n// CHECK:STDOUT:   return %.loc18_25 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_base_after_field.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.d: type = struct_type {.d: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.860: <witness> = complete_type_witness %struct_type.d [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc7: %Derived.elem = field_decl d, element0 [concrete]\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.d [concrete = constants.%complete_type.860]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .d = %.loc7\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/base_field.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/base_field.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/base_field.carbon\n\nbase class Base {\n  var a: i32;\n  var b: i32;\n  var c: i32;\n}\n\nclass Derived {\n  extend base: Base;\n\n  var d: i32;\n  var e: i32;\n}\n\nfn Access(p: Derived*) -> i32* {\n  return &(*p).c;\n}\n\n// CHECK:STDOUT: --- base_field.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.c: type = struct_type {.a: %i32, .b: %i32, .c: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.ebc: <witness> = complete_type_witness %struct_type.a.b.c [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem.029: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %Derived.elem.530: type = unbound_element_type %Derived, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.base.d.e.b4b: type = struct_type {.base: %Base, .d: %i32, .e: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.ea9: <witness> = complete_type_witness %struct_type.base.d.e.b4b [concrete]\n// CHECK:STDOUT:   %ptr.f74: type = ptr_type %Derived [concrete]\n// CHECK:STDOUT:   %pattern_type.0dd: type = pattern_type %ptr.f74 [concrete]\n// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %.605: Core.Form = init_form %ptr.235 [concrete]\n// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr.235 [concrete]\n// CHECK:STDOUT:   %Access.type: type = fn_type @Access [concrete]\n// CHECK:STDOUT:   %Access: %Access.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.843: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%i32) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.c3c: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%i32) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.011: %ptr.as.Copy.impl.Op.type.c3c = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.235, (%Copy.impl_witness.843) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.e01: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.a62: type = fn_type_with_self_type %Copy.WithSelf.Op.type.e01, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.011, @ptr.as.Copy.impl.Op(%i32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .Access = %Access.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Access.decl: %Access.type = fn_decl @Access [concrete = constants.%Access] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.0dd = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.0dd = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.fe8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.fe8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr.loc28_30: type = ptr_type %i32 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:     %.loc28_30: Core.Form = init_form %ptr.loc28_30 [concrete = constants.%.605]\n// CHECK:STDOUT:     %p.param: %ptr.f74 = value_param call_param0\n// CHECK:STDOUT:     %.loc28_21: type = splice_block %ptr.loc28_21 [concrete = constants.%ptr.f74] {\n// CHECK:STDOUT:       %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:       %ptr.loc28_21: type = ptr_type %Derived.ref [concrete = constants.%ptr.f74]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.f74 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %ptr.235 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.235 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc16: %Base.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc17: %Base.elem = field_decl b, element1 [concrete]\n// CHECK:STDOUT:   %i32.loc18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc18: %Base.elem = field_decl c, element2 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b.c [concrete = constants.%complete_type.ebc]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .a = %.loc16\n// CHECK:STDOUT:   .b = %.loc17\n// CHECK:STDOUT:   .c = %.loc18\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc22: %Derived.elem.029 = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc24: %Derived.elem.530 = field_decl d, element1 [concrete]\n// CHECK:STDOUT:   %i32.loc25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc25: %Derived.elem.530 = field_decl e, element2 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.d.e.b4b [concrete = constants.%complete_type.ea9]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc22\n// CHECK:STDOUT:   .d = %.loc24\n// CHECK:STDOUT:   .e = %.loc25\n// CHECK:STDOUT:   .c = <poisoned>\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Access(%p.param: %ptr.f74) -> out %return.param: %ptr.235 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.f74 = name_ref p, %p\n// CHECK:STDOUT:   %.loc29_12: ref %Derived = deref %p.ref\n// CHECK:STDOUT:   %c.ref: %Base.elem = name_ref c, @Base.%.loc18 [concrete = @Base.%.loc18]\n// CHECK:STDOUT:   %.loc29_15.1: ref %Base = class_element_access %.loc29_12, element0\n// CHECK:STDOUT:   %.loc29_15.2: ref %Base = converted %.loc29_12, %.loc29_15.1\n// CHECK:STDOUT:   %.loc29_15.3: ref %i32 = class_element_access %.loc29_15.2, element2\n// CHECK:STDOUT:   %addr: %ptr.235 = addr_of %.loc29_15.3\n// CHECK:STDOUT:   %impl.elem0: %.a62 = impl_witness_access constants.%Copy.impl_witness.843, element0 [concrete = constants.%ptr.as.Copy.impl.Op.011]\n// CHECK:STDOUT:   %bound_method.loc29_10.1: <bound method> = bound_method %addr, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%i32) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc29_10.2: <bound method> = bound_method %addr, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.235 = call %bound_method.loc29_10.2(%addr)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/base_function_unqualified.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/base_function_unqualified.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/base_function_unqualified.carbon\n\nbase class Base {\n  fn F();\n}\n\nclass Derived {\n  extend base: Base;\n\n  fn G() { F(); }\n  fn H();\n}\n\nfn Derived.H() {\n  F();\n}\n\n// CHECK:STDOUT: --- base_function_unqualified.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %Derived.G.type: type = fn_type @Derived.G [concrete]\n// CHECK:STDOUT:   %Derived.G: %Derived.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.H.type: type = fn_type @Derived.H [concrete]\n// CHECK:STDOUT:   %Derived.H: %Derived.H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.5a1: <witness> = complete_type_witness %struct_type.base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Derived.H.decl: %Derived.H.type = fn_decl @Derived.H [concrete = constants.%Derived.H] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type = fn_decl @Base.F [concrete = constants.%Base.F] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .F = %Base.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc20: %Derived.elem = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %Derived.G.decl: %Derived.G.type = fn_decl @Derived.G [concrete = constants.%Derived.G] {} {}\n// CHECK:STDOUT:   %Derived.H.decl: %Derived.H.type = fn_decl @Derived.H [concrete = constants.%Derived.H] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base [concrete = constants.%complete_type.5a1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc20\n// CHECK:STDOUT:   .G = %Derived.G.decl\n// CHECK:STDOUT:   .H = %Derived.H.decl\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Base.F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Derived.G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %Base.F.type = name_ref F, @Base.%Base.F.decl [concrete = constants.%Base.F]\n// CHECK:STDOUT:   %Base.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Derived.H() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %Base.F.type = name_ref F, @Base.%Base.F.decl [concrete = constants.%Base.F]\n// CHECK:STDOUT:   %Base.F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/base_method.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/base_method.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/base_method.carbon\n\nbase class Base {\n  var a: i32;\n\n  fn F[ref self: Self]();\n}\n\nfn Base.F[ref self: Self]() {\n  self.a = 1;\n}\n\nclass Derived {\n  extend base: Base;\n}\n\nfn Call(p: Derived*) {\n  (*p).F();\n}\n\n// CHECK:STDOUT: --- base_method.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.101: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F [concrete]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.fd7: <witness> = complete_type_witness %struct_type.a [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %struct_type.base.27a: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.5a1: <witness> = complete_type_witness %struct_type.base.27a [concrete]\n// CHECK:STDOUT:   %ptr.f74: type = ptr_type %Derived [concrete]\n// CHECK:STDOUT:   %pattern_type.0dd: type = pattern_type %ptr.f74 [concrete]\n// CHECK:STDOUT:   %Call.type: type = fn_type @Call [concrete]\n// CHECK:STDOUT:   %Call: %Call.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .Call = %Call.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type = fn_decl @Base.F [concrete = constants.%Base.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param.loc21: ref %Base = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc21: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self.loc21: ref %Base = ref_binding self, %self.param.loc21\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Call.decl: %Call.type = fn_decl @Call [concrete = constants.%Call] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.0dd = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.0dd = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %ptr.f74 = value_param call_param0\n// CHECK:STDOUT:     %.loc29: type = splice_block %ptr [concrete = constants.%ptr.f74] {\n// CHECK:STDOUT:       %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Derived.ref [concrete = constants.%ptr.f74]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.f74 = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc16: %Base.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type = fn_decl @Base.F [concrete = constants.%Base.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param.loc18: ref %Base = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc18: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self.loc18: ref %Base = ref_binding self, %self.param.loc18\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a [concrete = constants.%complete_type.fd7]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .a = %.loc16\n// CHECK:STDOUT:   .F = %Base.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc26: %Derived.elem = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.27a [concrete = constants.%complete_type.5a1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc26\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Base.F(%self.param.loc21: ref %Base) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: ref %Base = name_ref self, %self.loc21\n// CHECK:STDOUT:   %a.ref: %Base.elem = name_ref a, @Base.%.loc16 [concrete = @Base.%.loc16]\n// CHECK:STDOUT:   %.loc22_7: ref %i32 = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc22_10.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc22_10.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc22_10.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc22_10: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   assign %.loc22_7, %.loc22_10\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%p.param: %ptr.f74) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.f74 = name_ref p, %p\n// CHECK:STDOUT:   %.loc30_4.1: ref %Derived = deref %p.ref\n// CHECK:STDOUT:   %F.ref: %Base.F.type = name_ref F, @Base.%Base.F.decl [concrete = constants.%Base.F]\n// CHECK:STDOUT:   %Base.F.bound: <bound method> = bound_method %.loc30_4.1, %F.ref\n// CHECK:STDOUT:   %.loc30_4.2: ref %Base = class_element_access %.loc30_4.1, element0\n// CHECK:STDOUT:   %.loc30_4.3: ref %Base = converted %.loc30_4.1, %.loc30_4.2\n// CHECK:STDOUT:   %Base.F.call: init %empty_tuple.type = call %Base.F.bound(%.loc30_4.3)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/base_method_qualified.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/base_method_qualified.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/base_method_qualified.carbon\n\nclass Derived;\n\nbase class Base {\n  fn F[self: Self]() -> i32;\n  fn G[self: Derived]() -> i32;\n}\n\nclass Derived {\n  extend base: Base;\n\n  fn F[self: Self]();\n  fn G[self: Self]();\n}\n\nfn Call(a: Derived) -> i32 {\n  return a.(Base.F)();\n}\n\nfn CallIndirect(p: Derived*) -> i32 {\n  return p->(Base.F)();\n}\n\nfn PassDerivedToBase(a: Derived) -> i32 {\n  return a.(Base.G)();\n}\n\nfn PassDerivedToBaseIndirect(p: Derived*) -> i32 {\n  return p->(Base.G)();\n}\n\n// CHECK:STDOUT: --- base_method_qualified.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %pattern_type.101: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F [concrete]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Base.G.type: type = fn_type @Base.G [concrete]\n// CHECK:STDOUT:   %Base.G: %Base.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F [concrete]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.G.type: type = fn_type @Derived.G [concrete]\n// CHECK:STDOUT:   %Derived.G: %Derived.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.27a: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.5a1: <witness> = complete_type_witness %struct_type.base.27a [concrete]\n// CHECK:STDOUT:   %Call.type: type = fn_type @Call [concrete]\n// CHECK:STDOUT:   %Call: %Call.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.f74: type = ptr_type %Derived [concrete]\n// CHECK:STDOUT:   %pattern_type.0dd: type = pattern_type %ptr.f74 [concrete]\n// CHECK:STDOUT:   %CallIndirect.type: type = fn_type @CallIndirect [concrete]\n// CHECK:STDOUT:   %CallIndirect: %CallIndirect.type = struct_value () [concrete]\n// CHECK:STDOUT:   %PassDerivedToBase.type: type = fn_type @PassDerivedToBase [concrete]\n// CHECK:STDOUT:   %PassDerivedToBase: %PassDerivedToBase.type = struct_value () [concrete]\n// CHECK:STDOUT:   %PassDerivedToBaseIndirect.type: type = fn_type @PassDerivedToBaseIndirect [concrete]\n// CHECK:STDOUT:   %PassDerivedToBaseIndirect: %PassDerivedToBaseIndirect.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Derived = %Derived.decl.loc15\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Call = %Call.decl\n// CHECK:STDOUT:     .CallIndirect = %CallIndirect.decl\n// CHECK:STDOUT:     .PassDerivedToBase = %PassDerivedToBase.decl\n// CHECK:STDOUT:     .PassDerivedToBaseIndirect = %PassDerivedToBaseIndirect.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Derived.decl.loc15: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl.loc22: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Call.decl: %Call.type = fn_decl @Call [concrete = constants.%Call] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.9f6 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.9f6 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc29: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, file.%Derived.decl.loc15 [concrete = constants.%Derived]\n// CHECK:STDOUT:     %a: %Derived = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallIndirect.decl: %CallIndirect.type = fn_decl @CallIndirect [concrete = constants.%CallIndirect] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.0dd = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.0dd = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc33_33: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %p.param: %ptr.f74 = value_param call_param0\n// CHECK:STDOUT:     %.loc33_27: type = splice_block %ptr [concrete = constants.%ptr.f74] {\n// CHECK:STDOUT:       %Derived.ref: type = name_ref Derived, file.%Derived.decl.loc15 [concrete = constants.%Derived]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Derived.ref [concrete = constants.%ptr.f74]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.f74 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %PassDerivedToBase.decl: %PassDerivedToBase.type = fn_decl @PassDerivedToBase [concrete = constants.%PassDerivedToBase] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.9f6 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.9f6 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc37: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, file.%Derived.decl.loc15 [concrete = constants.%Derived]\n// CHECK:STDOUT:     %a: %Derived = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %PassDerivedToBaseIndirect.decl: %PassDerivedToBaseIndirect.type = fn_decl @PassDerivedToBaseIndirect [concrete = constants.%PassDerivedToBaseIndirect] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.0dd = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.0dd = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc41_46: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %p.param: %ptr.f74 = value_param call_param0\n// CHECK:STDOUT:     %.loc41_40: type = splice_block %ptr [concrete = constants.%ptr.f74] {\n// CHECK:STDOUT:       %Derived.ref: type = name_ref Derived, file.%Derived.decl.loc15 [concrete = constants.%Derived]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Derived.ref [concrete = constants.%ptr.f74]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.f74 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc23: %Derived.elem = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %Derived.F.decl: %Derived.F.type = fn_decl @Derived.F [concrete = constants.%Derived.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Derived.G.decl: %Derived.G.type = fn_decl @Derived.G [concrete = constants.%Derived.G] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.27a [concrete = constants.%complete_type.5a1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc23\n// CHECK:STDOUT:   .F = %Derived.F.decl\n// CHECK:STDOUT:   .G = %Derived.G.decl\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type = fn_decl @Base.F [concrete = constants.%Base.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc18: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: %Base = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self: %Base = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Base.G.decl: %Base.G.type = fn_decl @Base.G [concrete = constants.%Base.G] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc19: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Derived.ref: type = name_ref Derived, file.%Derived.decl.loc15 [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .F = %Base.F.decl\n// CHECK:STDOUT:   .Derived = <poisoned>\n// CHECK:STDOUT:   .G = %Base.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Base.F(%self.param: %Base) -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Base.G(%self.param: %Derived) -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Derived.F(%self.param: %Derived);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Derived.G(%self.param: %Derived);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: %Derived) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Derived = name_ref a, %a\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %F.ref: %Base.F.type = name_ref F, @Base.%Base.F.decl [concrete = constants.%Base.F]\n// CHECK:STDOUT:   %Base.F.bound: <bound method> = bound_method %a.ref, %F.ref\n// CHECK:STDOUT:   %.loc30_10.1: ref %Base = class_element_access %a.ref, element0\n// CHECK:STDOUT:   %.loc30_10.2: ref %Base = converted %a.ref, %.loc30_10.1\n// CHECK:STDOUT:   %.loc30_10.3: %Base = acquire_value %.loc30_10.2\n// CHECK:STDOUT:   %Base.F.call: init %i32 = call %Base.F.bound(%.loc30_10.3)\n// CHECK:STDOUT:   return %Base.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallIndirect(%p.param: %ptr.f74) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.f74 = name_ref p, %p\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %F.ref: %Base.F.type = name_ref F, @Base.%Base.F.decl [concrete = constants.%Base.F]\n// CHECK:STDOUT:   %.loc34_11.1: ref %Derived = deref %p.ref\n// CHECK:STDOUT:   %Base.F.bound: <bound method> = bound_method %.loc34_11.1, %F.ref\n// CHECK:STDOUT:   %.loc34_11.2: ref %Base = class_element_access %.loc34_11.1, element0\n// CHECK:STDOUT:   %.loc34_11.3: ref %Base = converted %.loc34_11.1, %.loc34_11.2\n// CHECK:STDOUT:   %.loc34_11.4: %Base = acquire_value %.loc34_11.3\n// CHECK:STDOUT:   %Base.F.call: init %i32 = call %Base.F.bound(%.loc34_11.4)\n// CHECK:STDOUT:   return %Base.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @PassDerivedToBase(%a.param: %Derived) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %Derived = name_ref a, %a\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %G.ref: %Base.G.type = name_ref G, @Base.%Base.G.decl [concrete = constants.%Base.G]\n// CHECK:STDOUT:   %Base.G.bound: <bound method> = bound_method %a.ref, %G.ref\n// CHECK:STDOUT:   %Base.G.call: init %i32 = call %Base.G.bound(%a.ref)\n// CHECK:STDOUT:   return %Base.G.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @PassDerivedToBaseIndirect(%p.param: %ptr.f74) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.f74 = name_ref p, %p\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %G.ref: %Base.G.type = name_ref G, @Base.%Base.G.decl [concrete = constants.%Base.G]\n// CHECK:STDOUT:   %.loc42_11.1: ref %Derived = deref %p.ref\n// CHECK:STDOUT:   %Base.G.bound: <bound method> = bound_method %.loc42_11.1, %G.ref\n// CHECK:STDOUT:   %.loc42_11.2: %Derived = acquire_value %.loc42_11.1\n// CHECK:STDOUT:   %Base.G.call: init %i32 = call %Base.G.bound(%.loc42_11.2)\n// CHECK:STDOUT:   return %Base.G.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/base_method_shadow.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/base_method_shadow.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/base_method_shadow.carbon\n\nbase class A {\n  fn F[ref self: Self]();\n}\n\nbase class B {\n  extend base: A;\n  fn F[ref self: Self]();\n}\n\nclass C {\n  extend base: B;\n  fn F[ref self: Self]();\n}\n\nclass D {\n  extend base: B;\n}\n\nfn Call(a: A*, b: B*, c: C*, d: D*) {\n  (*a).F();\n  (*b).F();\n  (*c).F();\n  (*d).F();\n}\n\n// CHECK:STDOUT: --- base_method_shadow.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %A.F.type: type = fn_type @A.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %A.F: %A.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %B.elem: type = unbound_element_type %B, %A [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %B.F.type: type = fn_type @B.F [concrete]\n// CHECK:STDOUT:   %B.F: %B.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.5af: type = struct_type {.base: %A} [concrete]\n// CHECK:STDOUT:   %complete_type.0d1: <witness> = complete_type_witness %struct_type.base.5af [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %B [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.64a: type = struct_type {.base: %B} [concrete]\n// CHECK:STDOUT:   %complete_type.021: <witness> = complete_type_witness %struct_type.base.64a [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %D.elem: type = unbound_element_type %D, %B [concrete]\n// CHECK:STDOUT:   %ptr.643: type = ptr_type %A [concrete]\n// CHECK:STDOUT:   %pattern_type.f29: type = pattern_type %ptr.643 [concrete]\n// CHECK:STDOUT:   %ptr.27c: type = ptr_type %B [concrete]\n// CHECK:STDOUT:   %pattern_type.191: type = pattern_type %ptr.27c [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %ptr.805: type = ptr_type %D [concrete]\n// CHECK:STDOUT:   %pattern_type.415: type = pattern_type %ptr.805 [concrete]\n// CHECK:STDOUT:   %Call.type: type = fn_type @Call [concrete]\n// CHECK:STDOUT:   %Call: %Call.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .Call = %Call.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %Call.decl: %Call.type = fn_decl @Call [concrete = constants.%Call] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.f29 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.f29 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.191 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.191 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %c.patt: %pattern_type.506 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.506 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %d.patt: %pattern_type.415 = value_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.param_patt: %pattern_type.415 = value_param_pattern %d.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %ptr.643 = value_param call_param0\n// CHECK:STDOUT:     %.loc33_13: type = splice_block %ptr.loc33_13 [concrete = constants.%ptr.643] {\n// CHECK:STDOUT:       %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:       %ptr.loc33_13: type = ptr_type %A.ref [concrete = constants.%ptr.643]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %ptr.643 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %ptr.27c = value_param call_param1\n// CHECK:STDOUT:     %.loc33_20: type = splice_block %ptr.loc33_20 [concrete = constants.%ptr.27c] {\n// CHECK:STDOUT:       %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:       %ptr.loc33_20: type = ptr_type %B.ref [concrete = constants.%ptr.27c]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b: %ptr.27c = value_binding b, %b.param\n// CHECK:STDOUT:     %c.param: %ptr.31e = value_param call_param2\n// CHECK:STDOUT:     %.loc33_27: type = splice_block %ptr.loc33_27 [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %ptr.loc33_27: type = ptr_type %C.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %ptr.31e = value_binding c, %c.param\n// CHECK:STDOUT:     %d.param: %ptr.805 = value_param call_param3\n// CHECK:STDOUT:     %.loc33_34: type = splice_block %ptr.loc33_34 [concrete = constants.%ptr.805] {\n// CHECK:STDOUT:       %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:       %ptr.loc33_34: type = ptr_type %D.ref [concrete = constants.%ptr.805]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %d: %ptr.805 = value_binding d, %d.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %A.F.decl: %A.F.type = fn_decl @A.F [concrete = constants.%A.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.1ab = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.1ab = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: ref %A = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%A [concrete = constants.%A]\n// CHECK:STDOUT:     %self: ref %A = ref_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .F = %A.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc20: %B.elem = base_decl %A.ref, element0 [concrete]\n// CHECK:STDOUT:   %B.F.decl: %B.F.type = fn_decl @B.F [concrete = constants.%B.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.1f4 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.1f4 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: ref %B = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%B [concrete = constants.%B]\n// CHECK:STDOUT:     %self: ref %B = ref_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.5af [concrete = constants.%complete_type.0d1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .base = %.loc20\n// CHECK:STDOUT:   .F = %B.F.decl\n// CHECK:STDOUT:   extend %A.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc25: %C.elem = base_decl %B.ref, element0 [concrete]\n// CHECK:STDOUT:   %C.F.decl: %C.F.type = fn_decl @C.F [concrete = constants.%C.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.7c7 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.7c7 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: ref %C = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %self: ref %C = ref_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.64a [concrete = constants.%complete_type.021]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .B = <poisoned>\n// CHECK:STDOUT:   .base = %.loc25\n// CHECK:STDOUT:   .F = %C.F.decl\n// CHECK:STDOUT:   extend %B.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %.loc30: %D.elem = base_decl %B.ref, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.64a [concrete = constants.%complete_type.021]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT:   .B = <poisoned>\n// CHECK:STDOUT:   .base = %.loc30\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend %B.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.F(%self.param: ref %A);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.F(%self.param: ref %B);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F(%self.param: ref %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%a.param: %ptr.643, %b.param: %ptr.27c, %c.param: %ptr.31e, %d.param: %ptr.805) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %ptr.643 = name_ref a, %a\n// CHECK:STDOUT:   %.loc34: ref %A = deref %a.ref\n// CHECK:STDOUT:   %F.ref.loc34: %A.F.type = name_ref F, @A.%A.F.decl [concrete = constants.%A.F]\n// CHECK:STDOUT:   %A.F.bound: <bound method> = bound_method %.loc34, %F.ref.loc34\n// CHECK:STDOUT:   %A.F.call: init %empty_tuple.type = call %A.F.bound(%.loc34)\n// CHECK:STDOUT:   %b.ref: %ptr.27c = name_ref b, %b\n// CHECK:STDOUT:   %.loc35: ref %B = deref %b.ref\n// CHECK:STDOUT:   %F.ref.loc35: %B.F.type = name_ref F, @B.%B.F.decl [concrete = constants.%B.F]\n// CHECK:STDOUT:   %B.F.bound.loc35: <bound method> = bound_method %.loc35, %F.ref.loc35\n// CHECK:STDOUT:   %B.F.call.loc35: init %empty_tuple.type = call %B.F.bound.loc35(%.loc35)\n// CHECK:STDOUT:   %c.ref: %ptr.31e = name_ref c, %c\n// CHECK:STDOUT:   %.loc36: ref %C = deref %c.ref\n// CHECK:STDOUT:   %F.ref.loc36: %C.F.type = name_ref F, @C.%C.F.decl [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.bound: <bound method> = bound_method %.loc36, %F.ref.loc36\n// CHECK:STDOUT:   %C.F.call: init %empty_tuple.type = call %C.F.bound(%.loc36)\n// CHECK:STDOUT:   %d.ref: %ptr.805 = name_ref d, %d\n// CHECK:STDOUT:   %.loc37_4.1: ref %D = deref %d.ref\n// CHECK:STDOUT:   %F.ref.loc37: %B.F.type = name_ref F, @B.%B.F.decl [concrete = constants.%B.F]\n// CHECK:STDOUT:   %B.F.bound.loc37: <bound method> = bound_method %.loc37_4.1, %F.ref.loc37\n// CHECK:STDOUT:   %.loc37_4.2: ref %B = class_element_access %.loc37_4.1, element0\n// CHECK:STDOUT:   %.loc37_4.3: ref %B = converted %.loc37_4.1, %.loc37_4.2\n// CHECK:STDOUT:   %B.F.call.loc37: init %empty_tuple.type = call %B.F.bound.loc37(%.loc37_4.3)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/derived_to_base.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/derived_to_base.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/derived_to_base.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class A {\n  var a: i32;\n}\n\nbase class B {\n  extend base: A;\n  var b: i32;\n}\n\nclass C {\n  extend base: B;\n  var c: i32;\n}\n\n//@dump-sem-ir-begin\nfn ConvertCToB(p: C*) -> B* { return p; }\nfn ConvertBToA(p: B*) -> A* { return p; }\nfn ConvertCToA(p: C*) -> A* { return p; }\n\nfn ConvertValue(c: C) {\n  let unused a: A = c;\n}\n\nfn ConvertRef(c: C*) -> A* {\n  return &(*c as A);\n}\n\nfn ConvertInit() {\n  let unused a: A = {.base = {.base = {.a = 1}, .b = 2}, .c = 3} as C;\n}\n//@dump-sem-ir-end\n\n// --- qualified.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class A {\n}\n\nclass B {\n  extend base: A;\n}\n\nfn TakeConstAPtr(p: const A*);\n\nfn PassNonConstBPtr(p: B*) {\n  //@dump-sem-ir-begin\n  TakeConstAPtr(p);\n  //@dump-sem-ir-end\n}\n\nfn PassConstBPtr(p: const B*) {\n  //@dump-sem-ir-begin\n  TakeConstAPtr(p);\n  //@dump-sem-ir-end\n}\n\n// --- fail_todo_qualified_non_ptr.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class A {\n}\n\nclass B {\n  extend base: A;\n}\n\nfn TakeConstA(p: const A);\n\nfn PassNonConstB(p: B) {\n  //@dump-sem-ir-begin\n  // CHECK:STDERR: fail_todo_qualified_non_ptr.carbon:[[@LINE+10]]:14: error: cannot implicitly convert expression of type `B` to `const A` [ConversionFailure]\n  // CHECK:STDERR:   TakeConstA(p);\n  // CHECK:STDERR:              ^\n  // CHECK:STDERR: fail_todo_qualified_non_ptr.carbon:[[@LINE+7]]:14: note: type `B` does not implement interface `Core.ImplicitAs(const A)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   TakeConstA(p);\n  // CHECK:STDERR:              ^\n  // CHECK:STDERR: fail_todo_qualified_non_ptr.carbon:[[@LINE-10]]:15: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn TakeConstA(p: const A);\n  // CHECK:STDERR:               ^~~~~~~~~~\n  // CHECK:STDERR:\n  TakeConstA(p);\n  //@dump-sem-ir-end\n}\n\nfn PassConstB(p: const B) {\n  //@dump-sem-ir-begin\n  // CHECK:STDERR: fail_todo_qualified_non_ptr.carbon:[[@LINE+10]]:14: error: cannot implicitly convert expression of type `const B` to `const A` [ConversionFailure]\n  // CHECK:STDERR:   TakeConstA(p);\n  // CHECK:STDERR:              ^\n  // CHECK:STDERR: fail_todo_qualified_non_ptr.carbon:[[@LINE+7]]:14: note: type `const B` does not implement interface `Core.ImplicitAs(const A)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   TakeConstA(p);\n  // CHECK:STDERR:              ^\n  // CHECK:STDERR: fail_todo_qualified_non_ptr.carbon:[[@LINE-26]]:15: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn TakeConstA(p: const A);\n  // CHECK:STDERR:               ^~~~~~~~~~\n  // CHECK:STDERR:\n  TakeConstA(p);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %ptr.27c: type = ptr_type %B [concrete]\n// CHECK:STDOUT:   %.d19: Core.Form = init_form %ptr.27c [concrete]\n// CHECK:STDOUT:   %pattern_type.191: type = pattern_type %ptr.27c [concrete]\n// CHECK:STDOUT:   %ConvertCToB.type: type = fn_type @ConvertCToB [concrete]\n// CHECK:STDOUT:   %ConvertCToB: %ConvertCToB.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.672: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%B) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.0fc: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%B) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.20b: %ptr.as.Copy.impl.Op.type.0fc = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.069: %Copy.type = facet_value %ptr.27c, (%Copy.impl_witness.672) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.d34: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.069) [concrete]\n// CHECK:STDOUT:   %.cc8: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d34, %Copy.facet.069 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn.695: <specific function> = specific_function %ptr.as.Copy.impl.Op.20b, @ptr.as.Copy.impl.Op(%B) [concrete]\n// CHECK:STDOUT:   %ptr.643: type = ptr_type %A [concrete]\n// CHECK:STDOUT:   %.ebf: Core.Form = init_form %ptr.643 [concrete]\n// CHECK:STDOUT:   %pattern_type.f29: type = pattern_type %ptr.643 [concrete]\n// CHECK:STDOUT:   %ConvertBToA.type: type = fn_type @ConvertBToA [concrete]\n// CHECK:STDOUT:   %ConvertBToA: %ConvertBToA.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.551: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%A) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.772: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%A) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.510: %ptr.as.Copy.impl.Op.type.772 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.f6a: %Copy.type = facet_value %ptr.643, (%Copy.impl_witness.551) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.f6f: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.f6a) [concrete]\n// CHECK:STDOUT:   %.2f8: type = fn_type_with_self_type %Copy.WithSelf.Op.type.f6f, %Copy.facet.f6a [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn.05b: <specific function> = specific_function %ptr.as.Copy.impl.Op.510, @ptr.as.Copy.impl.Op(%A) [concrete]\n// CHECK:STDOUT:   %ConvertCToA.type: type = fn_type @ConvertCToA [concrete]\n// CHECK:STDOUT:   %ConvertCToA: %ConvertCToA.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %ConvertValue.type: type = fn_type @ConvertValue [concrete]\n// CHECK:STDOUT:   %ConvertValue: %ConvertValue.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %ConvertRef.type: type = fn_type @ConvertRef [concrete]\n// CHECK:STDOUT:   %ConvertRef: %ConvertRef.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ConvertInit.type: type = fn_type @ConvertInit [concrete]\n// CHECK:STDOUT:   %ConvertInit: %ConvertInit.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.a.a6c: type = struct_type {.a: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.48c: %struct_type.a.a6c = struct_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.base.b.bf0: type = struct_type {.base: %struct_type.a.a6c, .b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.ff9: %struct_type.base.b.bf0 = struct_value (%struct.48c, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %struct_type.base.c.136: type = struct_type {.base: %struct_type.base.b.bf0, .c: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.2aa: %struct_type.base.c.136 = struct_value (%struct.ff9, %int_3.1ba) [concrete]\n// CHECK:STDOUT:   %.eaa: type = partial_type %B [concrete]\n// CHECK:STDOUT:   %.157: type = partial_type %A [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct.e01: %.157 = struct_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %A.val: %A = struct_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct.bc2: %.eaa = struct_value (%A.val, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %B.val: %B = struct_value (%A.val, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value (%B.val, %int_3.822) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %ConvertCToB.decl: %ConvertCToB.type = fn_decl @ConvertCToB [concrete = constants.%ConvertCToB] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.506 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.506 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.191 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.191 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:     %ptr.loc19_27: type = ptr_type %B.ref [concrete = constants.%ptr.27c]\n// CHECK:STDOUT:     %.loc19_27: Core.Form = init_form %ptr.loc19_27 [concrete = constants.%.d19]\n// CHECK:STDOUT:     %p.param: %ptr.31e = value_param call_param0\n// CHECK:STDOUT:     %.loc19_20: type = splice_block %ptr.loc19_20 [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %ptr.loc19_20: type = ptr_type %C.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.31e = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %ptr.27c = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.27c = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ConvertBToA.decl: %ConvertBToA.type = fn_decl @ConvertBToA [concrete = constants.%ConvertBToA] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.191 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.191 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.f29 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.f29 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:     %ptr.loc20_27: type = ptr_type %A.ref [concrete = constants.%ptr.643]\n// CHECK:STDOUT:     %.loc20_27: Core.Form = init_form %ptr.loc20_27 [concrete = constants.%.ebf]\n// CHECK:STDOUT:     %p.param: %ptr.27c = value_param call_param0\n// CHECK:STDOUT:     %.loc20_20: type = splice_block %ptr.loc20_20 [concrete = constants.%ptr.27c] {\n// CHECK:STDOUT:       %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:       %ptr.loc20_20: type = ptr_type %B.ref [concrete = constants.%ptr.27c]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.27c = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %ptr.643 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.643 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ConvertCToA.decl: %ConvertCToA.type = fn_decl @ConvertCToA [concrete = constants.%ConvertCToA] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.506 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.506 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.f29 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.f29 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:     %ptr.loc21_27: type = ptr_type %A.ref [concrete = constants.%ptr.643]\n// CHECK:STDOUT:     %.loc21_27: Core.Form = init_form %ptr.loc21_27 [concrete = constants.%.ebf]\n// CHECK:STDOUT:     %p.param: %ptr.31e = value_param call_param0\n// CHECK:STDOUT:     %.loc21_20: type = splice_block %ptr.loc21_20 [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %ptr.loc21_20: type = ptr_type %C.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.31e = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %ptr.643 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.643 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ConvertValue.decl: %ConvertValue.type = fn_decl @ConvertValue [concrete = constants.%ConvertValue] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.7c7 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ConvertRef.decl: %ConvertRef.type = fn_decl @ConvertRef [concrete = constants.%ConvertRef] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.506 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.506 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.f29 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.f29 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %A.ref.loc27: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:     %ptr.loc27_26: type = ptr_type %A.ref.loc27 [concrete = constants.%ptr.643]\n// CHECK:STDOUT:     %.loc27_26: Core.Form = init_form %ptr.loc27_26 [concrete = constants.%.ebf]\n// CHECK:STDOUT:     %c.param: %ptr.31e = value_param call_param0\n// CHECK:STDOUT:     %.loc27_19: type = splice_block %ptr.loc27_19 [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %ptr.loc27_19: type = ptr_type %C.ref [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %ptr.31e = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %ptr.643 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.643 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ConvertInit.decl: %ConvertInit.type = fn_decl @ConvertInit [concrete = constants.%ConvertInit] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ConvertCToB(%p.param: %ptr.31e) -> out %return.param: %ptr.27c {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.31e = name_ref p, %p\n// CHECK:STDOUT:   %.loc19_39.1: ref %C = deref %p.ref\n// CHECK:STDOUT:   %.loc19_39.2: ref %B = class_element_access %.loc19_39.1, element0\n// CHECK:STDOUT:   %addr: %ptr.27c = addr_of %.loc19_39.2\n// CHECK:STDOUT:   %.loc19_39.3: %ptr.27c = converted %p.ref, %addr\n// CHECK:STDOUT:   %impl.elem0: %.cc8 = impl_witness_access constants.%Copy.impl_witness.672, element0 [concrete = constants.%ptr.as.Copy.impl.Op.20b]\n// CHECK:STDOUT:   %bound_method.loc19_39.1: <bound method> = bound_method %.loc19_39.3, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%B) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.695]\n// CHECK:STDOUT:   %bound_method.loc19_39.2: <bound method> = bound_method %.loc19_39.3, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.27c = call %bound_method.loc19_39.2(%.loc19_39.3)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ConvertBToA(%p.param: %ptr.27c) -> out %return.param: %ptr.643 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.27c = name_ref p, %p\n// CHECK:STDOUT:   %.loc20_39.1: ref %B = deref %p.ref\n// CHECK:STDOUT:   %.loc20_39.2: ref %A = class_element_access %.loc20_39.1, element0\n// CHECK:STDOUT:   %addr: %ptr.643 = addr_of %.loc20_39.2\n// CHECK:STDOUT:   %.loc20_39.3: %ptr.643 = converted %p.ref, %addr\n// CHECK:STDOUT:   %impl.elem0: %.2f8 = impl_witness_access constants.%Copy.impl_witness.551, element0 [concrete = constants.%ptr.as.Copy.impl.Op.510]\n// CHECK:STDOUT:   %bound_method.loc20_39.1: <bound method> = bound_method %.loc20_39.3, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%A) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.05b]\n// CHECK:STDOUT:   %bound_method.loc20_39.2: <bound method> = bound_method %.loc20_39.3, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.643 = call %bound_method.loc20_39.2(%.loc20_39.3)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ConvertCToA(%p.param: %ptr.31e) -> out %return.param: %ptr.643 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.31e = name_ref p, %p\n// CHECK:STDOUT:   %.loc21_39.1: ref %C = deref %p.ref\n// CHECK:STDOUT:   %.loc21_39.2: ref %B = class_element_access %.loc21_39.1, element0\n// CHECK:STDOUT:   %.loc21_39.3: ref %A = class_element_access %.loc21_39.2, element0\n// CHECK:STDOUT:   %addr: %ptr.643 = addr_of %.loc21_39.3\n// CHECK:STDOUT:   %.loc21_39.4: %ptr.643 = converted %p.ref, %addr\n// CHECK:STDOUT:   %impl.elem0: %.2f8 = impl_witness_access constants.%Copy.impl_witness.551, element0 [concrete = constants.%ptr.as.Copy.impl.Op.510]\n// CHECK:STDOUT:   %bound_method.loc21_39.1: <bound method> = bound_method %.loc21_39.4, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%A) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.05b]\n// CHECK:STDOUT:   %bound_method.loc21_39.2: <bound method> = bound_method %.loc21_39.4, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.643 = call %bound_method.loc21_39.2(%.loc21_39.4)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ConvertValue(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1ab = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc24_21.1: ref %B = class_element_access %c.ref, element0\n// CHECK:STDOUT:   %.loc24_21.2: ref %A = class_element_access %.loc24_21.1, element0\n// CHECK:STDOUT:   %.loc24_21.3: ref %A = converted %c.ref, %.loc24_21.2\n// CHECK:STDOUT:   %.loc24_21.4: %A = acquire_value %.loc24_21.3\n// CHECK:STDOUT:   %a: %A = value_binding a, %.loc24_21.4\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ConvertRef(%c.param: %ptr.31e) -> out %return.param: %ptr.643 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %ptr.31e = name_ref c, %c\n// CHECK:STDOUT:   %.loc28_12: ref %C = deref %c.ref\n// CHECK:STDOUT:   %A.ref.loc28: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc28_15.1: ref %B = class_element_access %.loc28_12, element0\n// CHECK:STDOUT:   %.loc28_15.2: ref %A = class_element_access %.loc28_15.1, element0\n// CHECK:STDOUT:   %.loc28_15.3: ref %A = converted %.loc28_12, %.loc28_15.2\n// CHECK:STDOUT:   %addr: %ptr.643 = addr_of %.loc28_15.3\n// CHECK:STDOUT:   %impl.elem0: %.2f8 = impl_witness_access constants.%Copy.impl_witness.551, element0 [concrete = constants.%ptr.as.Copy.impl.Op.510]\n// CHECK:STDOUT:   %bound_method.loc28_10.1: <bound method> = bound_method %addr, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%A) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.05b]\n// CHECK:STDOUT:   %bound_method.loc28_10.2: <bound method> = bound_method %addr, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.643 = call %bound_method.loc28_10.2(%addr)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ConvertInit() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1ab = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc32_46.1: %struct_type.a.a6c = struct_literal (%int_1) [concrete = constants.%struct.48c]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc32_55.1: %struct_type.base.b.bf0 = struct_literal (%.loc32_46.1, %int_2) [concrete = constants.%struct.ff9]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %.loc32_64.1: %struct_type.base.c.136 = struct_literal (%.loc32_55.1, %int_3) [concrete = constants.%struct.2aa]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %impl.elem0.loc32_46: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc32_46.1: <bound method> = bound_method %int_1, %impl.elem0.loc32_46 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc32_46: <specific function> = specific_function %impl.elem0.loc32_46, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc32_46.2: <bound method> = bound_method %int_1, %specific_fn.loc32_46 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc32_46: init %i32 = call %bound_method.loc32_46.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc32_46.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc32_46 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc32_64.2: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc32_64.3: ref %.eaa = class_element_access %.loc32_64.2, element0\n// CHECK:STDOUT:   %.loc32_55.2: ref %.157 = class_element_access %.loc32_64.3, element0\n// CHECK:STDOUT:   %.loc32_46.3: ref %i32 = class_element_access %.loc32_55.2, element0\n// CHECK:STDOUT:   %.loc32_46.4: init %i32 to %.loc32_46.3 = in_place_init %.loc32_46.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc32_46.5: init %.157 to %.loc32_55.2 = class_init (%.loc32_46.4) [concrete = constants.%struct.e01]\n// CHECK:STDOUT:   %.loc32_55.3: init %.157 = converted %.loc32_46.1, %.loc32_46.5 [concrete = constants.%struct.e01]\n// CHECK:STDOUT:   %.loc32_55.4: init %A = as_compatible %.loc32_55.3 [concrete = constants.%A.val]\n// CHECK:STDOUT:   %impl.elem0.loc32_55: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc32_55.1: <bound method> = bound_method %int_2, %impl.elem0.loc32_55 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc32_55: <specific function> = specific_function %impl.elem0.loc32_55, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc32_55.2: <bound method> = bound_method %int_2, %specific_fn.loc32_55 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc32_55: init %i32 = call %bound_method.loc32_55.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc32_55.5: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc32_55 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc32_55.6: ref %i32 = class_element_access %.loc32_64.3, element1\n// CHECK:STDOUT:   %.loc32_55.7: init %i32 to %.loc32_55.6 = in_place_init %.loc32_55.5 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc32_55.8: init %.eaa to %.loc32_64.3 = class_init (%.loc32_55.4, %.loc32_55.7) [concrete = constants.%struct.bc2]\n// CHECK:STDOUT:   %.loc32_64.4: init %.eaa = converted %.loc32_55.1, %.loc32_55.8 [concrete = constants.%struct.bc2]\n// CHECK:STDOUT:   %.loc32_64.5: init %B = as_compatible %.loc32_64.4 [concrete = constants.%B.val]\n// CHECK:STDOUT:   %impl.elem0.loc32_64: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc32_64.1: <bound method> = bound_method %int_3, %impl.elem0.loc32_64 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:   %specific_fn.loc32_64: <specific function> = specific_function %impl.elem0.loc32_64, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc32_64.2: <bound method> = bound_method %int_3, %specific_fn.loc32_64 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc32_64: init %i32 = call %bound_method.loc32_64.2(%int_3) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc32_64.6: init %i32 = converted %int_3, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc32_64 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc32_64.7: ref %i32 = class_element_access %.loc32_64.2, element1\n// CHECK:STDOUT:   %.loc32_64.8: init %i32 to %.loc32_64.7 = in_place_init %.loc32_64.6 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc32_64.9: init %C to %.loc32_64.2 = class_init (%.loc32_64.5, %.loc32_64.8) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc32_66.1: init %C = converted %.loc32_64.1, %.loc32_64.9 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc32_66.2: ref %C = temporary %.loc32_64.2, %.loc32_66.1\n// CHECK:STDOUT:   %.loc32_66.3: ref %B = class_element_access %.loc32_66.2, element0\n// CHECK:STDOUT:   %.loc32_66.4: ref %A = class_element_access %.loc32_66.3, element0\n// CHECK:STDOUT:   %.loc32_66.5: ref %A = converted %.loc32_66.1, %.loc32_66.4\n// CHECK:STDOUT:   %.loc32_66.6: %A = acquire_value %.loc32_66.5\n// CHECK:STDOUT:   %a: %A = value_binding a, %.loc32_66.6\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc32_66.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc32_66.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- qualified.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %const.786: type = const_type %A [concrete]\n// CHECK:STDOUT:   %ptr.3bd: type = ptr_type %const.786 [concrete]\n// CHECK:STDOUT:   %TakeConstAPtr.type: type = fn_type @TakeConstAPtr [concrete]\n// CHECK:STDOUT:   %TakeConstAPtr: %TakeConstAPtr.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.27c: type = ptr_type %B [concrete]\n// CHECK:STDOUT:   %const.30c: type = const_type %B [concrete]\n// CHECK:STDOUT:   %ptr.375: type = ptr_type %const.30c [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @PassNonConstBPtr(%p.param: %ptr.27c) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %TakeConstAPtr.ref: %TakeConstAPtr.type = name_ref TakeConstAPtr, file.%TakeConstAPtr.decl [concrete = constants.%TakeConstAPtr]\n// CHECK:STDOUT:   %p.ref: %ptr.27c = name_ref p, %p\n// CHECK:STDOUT:   %.loc15_17.1: ref %B = deref %p.ref\n// CHECK:STDOUT:   %.loc15_17.2: ref %A = class_element_access %.loc15_17.1, element0\n// CHECK:STDOUT:   %addr: %ptr.3bd = addr_of %.loc15_17.2\n// CHECK:STDOUT:   %.loc15_17.3: %ptr.3bd = as_compatible %addr\n// CHECK:STDOUT:   %.loc15_17.4: %ptr.3bd = converted %p.ref, %.loc15_17.3\n// CHECK:STDOUT:   %TakeConstAPtr.call: init %empty_tuple.type = call %TakeConstAPtr.ref(%.loc15_17.4)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @PassConstBPtr(%p.param: %ptr.375) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %TakeConstAPtr.ref: %TakeConstAPtr.type = name_ref TakeConstAPtr, file.%TakeConstAPtr.decl [concrete = constants.%TakeConstAPtr]\n// CHECK:STDOUT:   %p.ref: %ptr.375 = name_ref p, %p\n// CHECK:STDOUT:   %.loc21_17.1: ref %const.30c = deref %p.ref\n// CHECK:STDOUT:   %.loc21_17.2: ref %const.786 = class_element_access %.loc21_17.1, element0\n// CHECK:STDOUT:   %addr: %ptr.3bd = addr_of %.loc21_17.2\n// CHECK:STDOUT:   %.loc21_17.3: %ptr.3bd = converted %p.ref, %addr\n// CHECK:STDOUT:   %TakeConstAPtr.call: init %empty_tuple.type = call %TakeConstAPtr.ref(%.loc21_17.3)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_qualified_non_ptr.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %const.786: type = const_type %A [concrete]\n// CHECK:STDOUT:   %TakeConstA.type: type = fn_type @TakeConstA [concrete]\n// CHECK:STDOUT:   %TakeConstA: %TakeConstA.type = struct_value () [concrete]\n// CHECK:STDOUT:   %const.30c: type = const_type %B [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @PassNonConstB(%p.param: %B) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %TakeConstA.ref: %TakeConstA.type = name_ref TakeConstA, file.%TakeConstA.decl [concrete = constants.%TakeConstA]\n// CHECK:STDOUT:   %p.ref: %B = name_ref p, %p\n// CHECK:STDOUT:   %.loc25: %const.786 = converted %p.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %TakeConstA.call: init %empty_tuple.type = call %TakeConstA.ref(<error>)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @PassConstB(%p.param: %const.30c) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %TakeConstA.ref: %TakeConstA.type = name_ref TakeConstA, file.%TakeConstA.decl [concrete = constants.%TakeConstA]\n// CHECK:STDOUT:   %p.ref: %const.30c = name_ref p, %p\n// CHECK:STDOUT:   %.loc41: %const.786 = converted %p.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %TakeConstA.call: init %empty_tuple.type = call %TakeConstA.ref(<error>)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_base_as_declared_name.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_base_as_declared_name.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_base_as_declared_name.carbon\n\nnamespace N;\n\n// CHECK:STDERR: fail_base_as_declared_name.carbon:[[@LINE+8]]:6: error: `.` should be followed by a name [ExpectedDeclNameAfterPeriod]\n// CHECK:STDERR: fn N.base() {}\n// CHECK:STDERR:      ^~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_base_as_declared_name.carbon:[[@LINE+4]]:6: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n// CHECK:STDERR: fn N.base() {}\n// CHECK:STDERR:      ^~~~\n// CHECK:STDERR:\nfn N.base() {}\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_base_bad_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_base_bad_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_base_bad_type.carbon\n\n// --- fail_derive_from_error.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass DeriveFromError {\n  // CHECK:STDERR: fail_derive_from_error.carbon:[[@LINE+4]]:16: error: name `error` not found [NameNotFound]\n  // CHECK:STDERR:   extend base: error;\n  // CHECK:STDERR:                ^~~~~\n  // CHECK:STDERR:\n  extend base: error;\n}\n\n// This should not produce an error.\nfn AccessMemberWithInvalidBaseError(p: DeriveFromError*) -> i32 { return (*p).n; }\n\n// --- fail_derive_from_non_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass DeriveFromNonType {\n  // CHECK:STDERR: fail_derive_from_non_type.carbon:[[@LINE+7]]:16: error: cannot implicitly convert non-type value of type `Core.IntLiteral` to `type` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   extend base: 32;\n  // CHECK:STDERR:                ^~\n  // CHECK:STDERR: fail_derive_from_non_type.carbon:[[@LINE+4]]:16: note: type `Core.IntLiteral` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   extend base: 32;\n  // CHECK:STDERR:                ^~\n  // CHECK:STDERR:\n  extend base: 32;\n}\n\nfn AccessMemberWithInvalidBasNonType(p: DeriveFromNonType*) -> i32 { return (*p).n; }\n\n// --- fail_derive_from_i32.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass DeriveFromi32 {\n  // CHECK:STDERR: fail_derive_from_i32.carbon:[[@LINE+4]]:16: error: deriving from final type `i32`; base type must be an `abstract` or `base` class [BaseIsFinal]\n  // CHECK:STDERR:   extend base: i32;\n  // CHECK:STDERR:                ^~~\n  // CHECK:STDERR:\n  extend base: i32;\n}\n\n// It's not really important whether this conversion produces an error or not,\n// but it shouldn't crash.\n// CHECK:STDERR: fail_derive_from_i32.carbon:[[@LINE+7]]:53: error: cannot implicitly convert expression of type `DeriveFromi32*` to `i32*` [ConversionFailure]\n// CHECK:STDERR: fn ConvertToBadBasei32(p: DeriveFromi32*) -> i32* { return p; }\n// CHECK:STDERR:                                                     ^~~~~~~~~\n// CHECK:STDERR: fail_derive_from_i32.carbon:[[@LINE+4]]:53: note: type `DeriveFromi32*` does not implement interface `Core.ImplicitAs(i32*)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: fn ConvertToBadBasei32(p: DeriveFromi32*) -> i32* { return p; }\n// CHECK:STDERR:                                                     ^~~~~~~~~\n// CHECK:STDERR:\nfn ConvertToBadBasei32(p: DeriveFromi32*) -> i32* { return p; }\n\n// CHECK:STDERR: fail_derive_from_i32.carbon:[[@LINE+4]]:70: error: member name `n` not found in `DeriveFromi32` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: fn AccessMemberWithInvalidBasei32(p: DeriveFromi32*) -> i32 { return (*p).n; }\n// CHECK:STDERR:                                                                      ^~~~~~\n// CHECK:STDERR:\nfn AccessMemberWithInvalidBasei32(p: DeriveFromi32*) -> i32 { return (*p).n; }\n\n// --- fail_derive_from_tuple.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base {}\n\nclass DeriveFromTuple {\n  // CHECK:STDERR: fail_derive_from_tuple.carbon:[[@LINE+4]]:16: error: deriving from final type `(Base,)`; base type must be an `abstract` or `base` class [BaseIsFinal]\n  // CHECK:STDERR:   extend base: (Base,);\n  // CHECK:STDERR:                ^~~~~~~\n  // CHECK:STDERR:\n  extend base: (Base,);\n}\n\n// CHECK:STDERR: fail_derive_from_tuple.carbon:[[@LINE+7]]:61: error: cannot implicitly convert expression of type `DeriveFromTuple*` to `(Base,)*` [ConversionFailure]\n// CHECK:STDERR: fn ConvertToBadBaseTuple(p: DeriveFromTuple*) -> (Base,)* { return p; }\n// CHECK:STDERR:                                                             ^~~~~~~~~\n// CHECK:STDERR: fail_derive_from_tuple.carbon:[[@LINE+4]]:61: note: type `DeriveFromTuple*` does not implement interface `Core.ImplicitAs((Base,)*)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: fn ConvertToBadBaseTuple(p: DeriveFromTuple*) -> (Base,)* { return p; }\n// CHECK:STDERR:                                                             ^~~~~~~~~\n// CHECK:STDERR:\nfn ConvertToBadBaseTuple(p: DeriveFromTuple*) -> (Base,)* { return p; }\n\nfn AccessMemberWithInvalidBaseTuple(p: DeriveFromTuple*) -> i32 { return (*p).n; }\n\n// --- fail_derive_from_struct.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: Should we allow this?\n// We do allow `{.base = {.a: i32, .b: i32}}`.\nclass DeriveFromStruct {\n  // CHECK:STDERR: fail_derive_from_struct.carbon:[[@LINE+4]]:16: error: deriving from final type `{.a: i32, .b: i32}`; base type must be an `abstract` or `base` class [BaseIsFinal]\n  // CHECK:STDERR:   extend base: {.a: i32, .b: i32};\n  // CHECK:STDERR:                ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend base: {.a: i32, .b: i32};\n}\n\n// CHECK:STDERR: fail_derive_from_struct.carbon:[[@LINE+7]]:74: error: cannot implicitly convert expression of type `DeriveFromStruct*` to `{.a: i32, .b: i32}*` [ConversionFailure]\n// CHECK:STDERR: fn ConvertToBadBaseStruct(p: DeriveFromStruct*) -> {.a: i32, .b: i32}* { return p; }\n// CHECK:STDERR:                                                                          ^~~~~~~~~\n// CHECK:STDERR: fail_derive_from_struct.carbon:[[@LINE+4]]:74: note: type `DeriveFromStruct*` does not implement interface `Core.ImplicitAs({.a: i32, .b: i32}*)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: fn ConvertToBadBaseStruct(p: DeriveFromStruct*) -> {.a: i32, .b: i32}* { return p; }\n// CHECK:STDERR:                                                                          ^~~~~~~~~\n// CHECK:STDERR:\nfn ConvertToBadBaseStruct(p: DeriveFromStruct*) -> {.a: i32, .b: i32}* { return p; }\n\n// It would be OK to reject this if we start actually looking in the struct type.\nfn AccessMemberWithInvalidBaseStruct(p: DeriveFromStruct*) -> i32 { return (*p).n; }\n\n// --- fail_derive_from_incomplete.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE+4]]:1: error: `base` not allowed on `class` forward declaration, only definition [ModifierOnlyAllowedOnDefinition]\n// CHECK:STDERR: base class Incomplete;\n// CHECK:STDERR: ^~~~\n// CHECK:STDERR:\nbase class Incomplete;\n\nclass DeriveFromIncomplete {\n  // CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE+7]]:16: error: base `Incomplete` is an incomplete type [IncompleteTypeInBaseDecl]\n  // CHECK:STDERR:   extend base: Incomplete;\n  // CHECK:STDERR:                ^~~~~~~~~~\n  // CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE-6]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: base class Incomplete;\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend base: Incomplete;\n}\n\n// CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE+7]]:74: error: cannot implicitly convert expression of type `DeriveFromIncomplete*` to `Incomplete*` [ConversionFailure]\n// CHECK:STDERR: fn ConvertToBadBaseIncomplete(p: DeriveFromIncomplete*) -> Incomplete* { return p; }\n// CHECK:STDERR:                                                                          ^~~~~~~~~\n// CHECK:STDERR: fail_derive_from_incomplete.carbon:[[@LINE+4]]:74: note: type `DeriveFromIncomplete*` does not implement interface `Core.ImplicitAs(Incomplete*)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: fn ConvertToBadBaseIncomplete(p: DeriveFromIncomplete*) -> Incomplete* { return p; }\n// CHECK:STDERR:                                                                          ^~~~~~~~~\n// CHECK:STDERR:\nfn ConvertToBadBaseIncomplete(p: DeriveFromIncomplete*) -> Incomplete* { return p; }\n\nfn AccessMemberWithInvalidBaseIncomplete(p: DeriveFromIncomplete*) -> i32 { return (*p).n; }\n\n// --- fail_derive_from_final.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Final {\n  var a: i32;\n}\n\nclass DeriveFromFinal {\n  // CHECK:STDERR: fail_derive_from_final.carbon:[[@LINE+4]]:16: error: deriving from final type `Final`; base type must be an `abstract` or `base` class [BaseIsFinal]\n  // CHECK:STDERR:   extend base: Final;\n  // CHECK:STDERR:                ^~~~~\n  // CHECK:STDERR:\n  extend base: Final;\n}\n\n// For error recovery purposes, we derive from the final type anyway.\nfn ConvertToBadBaseFinal(p: DeriveFromFinal*) -> Final* {\n  return p;\n}\n\nfn AccessMemberWithInvalidBaseFinal_WithMember(p: DeriveFromFinal*) -> i32 {\n  return (*p).a;\n}\n\nfn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 {\n  // CHECK:STDERR: fail_derive_from_final.carbon:[[@LINE+4]]:10: error: member name `b` not found in `DeriveFromFinal` [MemberNameNotFoundInInstScope]\n  // CHECK:STDERR:   return (*p).b;\n  // CHECK:STDERR:          ^~~~~~\n  // CHECK:STDERR:\n  return (*p).b;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_base_method_define.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_base_method_define.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_base_method_define.carbon\n\nbase class B {\n  fn F();\n\n  class C {\n    fn F();\n  }\n}\n\nclass D {\n  extend base: B;\n}\n\n// CHECK:STDERR: fail_base_method_define.carbon:[[@LINE+4]]:6: error: out-of-line declaration requires a declaration in scoped entity [QualifiedDeclOutsideScopeEntity]\n// CHECK:STDERR: fn D.F() {}\n// CHECK:STDERR:      ^\n// CHECK:STDERR:\nfn D.F() {}\n\n// CHECK:STDERR: fail_base_method_define.carbon:[[@LINE+4]]:6: error: name `C` not found [NameNotFound]\n// CHECK:STDERR: fn D.C.F() {}\n// CHECK:STDERR:      ^\n// CHECK:STDERR:\nfn D.C.F() {}\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_base_misplaced.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_base_misplaced.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_base_misplaced.carbon\n\nbase class B {}\n\n// CHECK:STDERR: fail_base_misplaced.carbon:[[@LINE+4]]:1: error: `base` declaration outside class [ClassSpecificDeclOutsideClass]\n// CHECK:STDERR: extend base: B;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextend base: B;\n\nfn F() {\n  // CHECK:STDERR: fail_base_misplaced.carbon:[[@LINE+4]]:3: error: `base` declaration outside class [ClassSpecificDeclOutsideClass]\n  // CHECK:STDERR:   extend base: B;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend base: B;\n}\n\nclass C {\n  fn F() {\n    // CHECK:STDERR: fail_base_misplaced.carbon:[[@LINE+4]]:5: error: `base` declaration outside class [ClassSpecificDeclOutsideClass]\n    // CHECK:STDERR:     extend base: B;\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    extend base: B;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_base_modifiers.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_base_modifiers.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_base_modifiers.carbon\n\nbase class B {}\n\nclass C1 {\n  // CHECK:STDERR: fail_base_modifiers.carbon:[[@LINE+4]]:3: error: `private` not allowed on `base` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   private extend base: B;\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  private extend base: B;\n}\n\nclass C2 {\n  // CHECK:STDERR: fail_base_modifiers.carbon:[[@LINE+8]]:3: error: `abstract` not allowed on `base` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   abstract base: B;\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_base_modifiers.carbon:[[@LINE+4]]:3: error: missing `extend` before `base` declaration [BaseMissingExtend]\n  // CHECK:STDERR:   abstract base: B;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  abstract base: B;\n}\n\nclass C3 {\n  // CHECK:STDERR: fail_base_modifiers.carbon:[[@LINE+4]]:10: error: `default` not allowed on `base` declaration [ModifierNotAllowedOnDeclaration]\n  // CHECK:STDERR:   extend default base: B;\n  // CHECK:STDERR:          ^~~~~~~\n  // CHECK:STDERR:\n  extend default base: B;\n}\n\nclass C4 {\n  // CHECK:STDERR: fail_base_modifiers.carbon:[[@LINE+7]]:10: error: `extend` repeated on declaration [ModifierRepeated]\n  // CHECK:STDERR:   extend extend base: B;\n  // CHECK:STDERR:          ^~~~~~\n  // CHECK:STDERR: fail_base_modifiers.carbon:[[@LINE+4]]:3: note: `extend` previously appeared here [ModifierPrevious]\n  // CHECK:STDERR:   extend extend base: B;\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR:\n  extend extend base: B;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_base_no_extend.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_base_no_extend.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_base_no_extend.carbon\n\nbase class B {}\n\nclass C {\n  // CHECK:STDERR: fail_base_no_extend.carbon:[[@LINE+4]]:3: error: missing `extend` before `base` declaration [BaseMissingExtend]\n  // CHECK:STDERR:   base: B;\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR:\n  base: B;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_base_repeated.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_base_repeated.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_base_repeated.carbon\n\nbase class B1 {}\nbase class B2 {}\n\nclass C {\n  extend base: B1;\n  // CHECK:STDERR: fail_base_repeated.carbon:[[@LINE+7]]:3: error: multiple `base` declarations in class; multiple inheritance is not permitted [BaseDeclRepeated]\n  // CHECK:STDERR:   extend base: B2;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_base_repeated.carbon:[[@LINE-4]]:3: note: previous `base` declaration is here [ClassSpecificDeclPrevious]\n  // CHECK:STDERR:   extend base: B1;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend base: B2;\n}\n\nclass D {\n  // TODO: Consider adding a custom diagnostic for this case.\n  extend base: B1;\n  // CHECK:STDERR: fail_base_repeated.carbon:[[@LINE+7]]:3: error: multiple `base` declarations in class; multiple inheritance is not permitted [BaseDeclRepeated]\n  // CHECK:STDERR:   extend base: B1;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_base_repeated.carbon:[[@LINE-4]]:3: note: previous `base` declaration is here [ClassSpecificDeclPrevious]\n  // CHECK:STDERR:   extend base: B1;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend base: B1;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_base_unbound.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_base_unbound.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_base_unbound.carbon\n\nbase class B {}\n\nclass C {\n  extend base: B;\n}\n\n// CHECK:STDERR: fail_base_unbound.carbon:[[@LINE+4]]:12: error: expression cannot be used as a value [UseOfNonExprAsValue]\n// CHECK:STDERR: let b: B = C.base;\n// CHECK:STDERR:            ^~~~~~\n// CHECK:STDERR:\nlet b: B = C.base;\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_derived_to_base.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_derived_to_base.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_derived_to_base.carbon\n\nbase class A1 {\n  var a: i32;\n}\n\nbase class A2 {\n  var a: i32;\n}\n\nclass B2 {\n  extend base: A2;\n  var b: i32;\n}\n\n// CHECK:STDERR: fail_derived_to_base.carbon:[[@LINE+7]]:38: error: cannot implicitly convert expression of type `B2*` to `A1*` [ConversionFailure]\n// CHECK:STDERR: fn ConvertUnrelated(p: B2*) -> A1* { return p; }\n// CHECK:STDERR:                                      ^~~~~~~~~\n// CHECK:STDERR: fail_derived_to_base.carbon:[[@LINE+4]]:38: note: type `B2*` does not implement interface `Core.ImplicitAs(A1*)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: fn ConvertUnrelated(p: B2*) -> A1* { return p; }\n// CHECK:STDERR:                                      ^~~~~~~~~\n// CHECK:STDERR:\nfn ConvertUnrelated(p: B2*) -> A1* { return p; }\n\nclass Incomplete;\n\n// CHECK:STDERR: fail_derived_to_base.carbon:[[@LINE+7]]:47: error: cannot implicitly convert expression of type `Incomplete*` to `A2*` [ConversionFailure]\n// CHECK:STDERR: fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }\n// CHECK:STDERR:                                               ^~~~~~~~~\n// CHECK:STDERR: fail_derived_to_base.carbon:[[@LINE+4]]:47: note: type `Incomplete*` does not implement interface `Core.ImplicitAs(A2*)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: fn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }\n// CHECK:STDERR:                                               ^~~~~~~~~\n// CHECK:STDERR:\nfn ConvertIncomplete(p: Incomplete*) -> A2* { return p; }\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/fail_extend_cycle.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/fail_extend_cycle.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/fail_extend_cycle.carbon\n\nbase class A {\n}\n\nbase class B {\n  // This ensures that the compiler treats A as complete.\n  extend base: A;\n}\n\n// CHECK:STDERR: fail_extend_cycle.carbon:[[@LINE+7]]:1: error: redefinition of `class A` [RedeclRedef]\n// CHECK:STDERR: base class A {\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extend_cycle.carbon:[[@LINE-11]]:1: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR: base class A {\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nbase class A {\n  extend base: A;\n  // CHECK:STDERR: fail_extend_cycle.carbon:[[@LINE+4]]:10: error: name `C` not found [NameNotFound]\n  // CHECK:STDERR:   var c: C;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR:\n  var c: C;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/import_base.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/import_base.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/import_base.carbon\n\n// --- a.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base {\n  fn F[self: Self]();\n  fn Unused[self: Self]();\n\n  var x: i32;\n  var unused_y: i32;\n}\n\nclass Child {\n  extend base: Base;\n}\n\n// --- b.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\n\nfn Run() {\n  var a: Child = {.base = {.x = 0, .unused_y = 1}};\n  a.x = 2;\n  a.F();\n}\n\n// CHECK:STDOUT: --- a.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %pattern_type.101: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F [concrete]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.Unused.type: type = fn_type @Base.Unused [concrete]\n// CHECK:STDOUT:   %Base.Unused: %Base.Unused.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x.unused_y: type = struct_type {.x: %i32, .unused_y: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.cf1: <witness> = complete_type_witness %struct_type.x.unused_y [concrete]\n// CHECK:STDOUT:   %Child: type = class_type @Child [concrete]\n// CHECK:STDOUT:   %Child.elem: type = unbound_element_type %Child, %Base [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.5a1: <witness> = complete_type_witness %struct_type.base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Child = %Child.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Child.decl: type = class_decl @Child [concrete = constants.%Child] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type = fn_decl @Base.F [concrete = constants.%Base.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Base = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self: %Base = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Base.Unused.decl: %Base.Unused.type = fn_decl @Base.Unused [concrete = constants.%Base.Unused] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Base = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self: %Base = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32.loc8: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc8: %Base.elem = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc9: %Base.elem = field_decl unused_y, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x.unused_y [concrete = constants.%complete_type.cf1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .F = %Base.F.decl\n// CHECK:STDOUT:   .Unused = %Base.Unused.decl\n// CHECK:STDOUT:   .x = %.loc8\n// CHECK:STDOUT:   .unused_y = %.loc9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Child {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc13: %Child.elem = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base [concrete = constants.%complete_type.5a1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Child\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc13\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Base.F(%self.param: %Base);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Base.Unused(%self.param: %Base);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- b.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Child: type = class_type @Child [concrete]\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.x.unused_y.9fc: type = struct_type {.x: %i32, .unused_y: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.2da: <witness> = complete_type_witness %struct_type.x.unused_y.9fc [concrete]\n// CHECK:STDOUT:   %struct_type.base.27a: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.5a1: <witness> = complete_type_witness %struct_type.base.27a [concrete]\n// CHECK:STDOUT:   %pattern_type.454: type = pattern_type %Child [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.x.unused_y.76a: type = struct_type {.x: Core.IntLiteral, .unused_y: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.0bf: %struct_type.x.unused_y.76a = struct_value (%int_0.5c6, %int_1.5b8) [concrete]\n// CHECK:STDOUT:   %struct_type.base.503: type = struct_type {.base: %struct_type.x.unused_y.76a} [concrete]\n// CHECK:STDOUT:   %struct.cb5: %struct_type.base.503 = struct_value (%struct.0bf) [concrete]\n// CHECK:STDOUT:   %.7a5: type = partial_type %Base [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cf3: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.255: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.58d: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.e45, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.cf3 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.58d) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.979: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.7c3: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.979, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.386: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.9f1: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.263: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f07: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4 [concrete]\n// CHECK:STDOUT:   %bound_method.307: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.47b: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct.f56: %.7a5 = struct_value (%int_0.263, %int_1.47b) [concrete]\n// CHECK:STDOUT:   %Base.val: %Base = struct_value (%int_0.263, %int_1.47b) [concrete]\n// CHECK:STDOUT:   %Child.val: %Child = struct_value (%Base.val) [concrete]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %i32 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.1eb: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4 [concrete]\n// CHECK:STDOUT:   %bound_method.ef3: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.d0d: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F [concrete]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Base = import_ref Main//a, Base, unloaded\n// CHECK:STDOUT:   %Main.Child: type = import_ref Main//a, Child, loaded [concrete = constants.%Child]\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//a, loc10_1, loaded [concrete = constants.%complete_type.2da]\n// CHECK:STDOUT:   %Main.import_ref.691 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.062: %Base.F.type = import_ref Main//a, loc5_21, loaded [concrete = constants.%Base.F]\n// CHECK:STDOUT:   %Main.import_ref.7b8 = import_ref Main//a, loc6_26, unloaded\n// CHECK:STDOUT:   %Main.import_ref.183: %Base.elem = import_ref Main//a, loc8_8, loaded [concrete = %.61a]\n// CHECK:STDOUT:   %Main.import_ref.7c0 = import_ref Main//a, loc9_15, unloaded\n// CHECK:STDOUT:   %Main.import_ref.44c: <witness> = import_ref Main//a, loc14_1, loaded [concrete = constants.%complete_type.5a1]\n// CHECK:STDOUT:   %Main.import_ref.d37 = import_ref Main//a, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.4a6 = import_ref Main//a, loc13_20, unloaded\n// CHECK:STDOUT:   %Main.import_ref.bd3719.2: type = import_ref Main//a, loc13_16, loaded [concrete = constants.%Base]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.b25: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.255)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.e45 = impl_witness_table (%Core.import_ref.b25), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %.61a: %Base.elem = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Base = imports.%Main.Base\n// CHECK:STDOUT:     .Child = imports.%Main.Child\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Child [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.44c\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.d37\n// CHECK:STDOUT:   .base = imports.%Main.import_ref.4a6\n// CHECK:STDOUT:   .x = <poisoned>\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend imports.%Main.import_ref.bd3719.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base [from \"a.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.691\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.062\n// CHECK:STDOUT:   .Unused = imports.%Main.import_ref.7b8\n// CHECK:STDOUT:   .x = imports.%Main.import_ref.183\n// CHECK:STDOUT:   .unused_y = imports.%Main.import_ref.7c0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.454 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.454 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %Child = var %a.var_patt\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc7_49.1: %struct_type.x.unused_y.76a = struct_literal (%int_0, %int_1) [concrete = constants.%struct.0bf]\n// CHECK:STDOUT:   %.loc7_50.1: %struct_type.base.503 = struct_literal (%.loc7_49.1) [concrete = constants.%struct.cb5]\n// CHECK:STDOUT:   %impl.elem0.loc7_49.1: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc7_49.1: <bound method> = bound_method %int_0, %impl.elem0.loc7_49.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.386]\n// CHECK:STDOUT:   %specific_fn.loc7_49.1: <specific function> = specific_function %impl.elem0.loc7_49.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_49.2: <bound method> = bound_method %int_0, %specific_fn.loc7_49.1 [concrete = constants.%bound_method.9f1]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_49.1: init %i32 = call %bound_method.loc7_49.2(%int_0) [concrete = constants.%int_0.263]\n// CHECK:STDOUT:   %.loc7_49.2: init %i32 = converted %int_0, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_49.1 [concrete = constants.%int_0.263]\n// CHECK:STDOUT:   %.loc7_50.2: ref %.7a5 = class_element_access %a.var, element0\n// CHECK:STDOUT:   %.loc7_49.3: ref %i32 = class_element_access %.loc7_50.2, element0\n// CHECK:STDOUT:   %.loc7_49.4: init %i32 to %.loc7_49.3 = in_place_init %.loc7_49.2 [concrete = constants.%int_0.263]\n// CHECK:STDOUT:   %impl.elem0.loc7_49.2: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc7_49.3: <bound method> = bound_method %int_1, %impl.elem0.loc7_49.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f07]\n// CHECK:STDOUT:   %specific_fn.loc7_49.2: <specific function> = specific_function %impl.elem0.loc7_49.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_49.4: <bound method> = bound_method %int_1, %specific_fn.loc7_49.2 [concrete = constants.%bound_method.307]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_49.2: init %i32 = call %bound_method.loc7_49.4(%int_1) [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc7_49.5: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_49.2 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc7_49.6: ref %i32 = class_element_access %.loc7_50.2, element1\n// CHECK:STDOUT:   %.loc7_49.7: init %i32 to %.loc7_49.6 = in_place_init %.loc7_49.5 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc7_49.8: init %.7a5 to %.loc7_50.2 = class_init (%.loc7_49.4, %.loc7_49.7) [concrete = constants.%struct.f56]\n// CHECK:STDOUT:   %.loc7_50.3: init %.7a5 = converted %.loc7_49.1, %.loc7_49.8 [concrete = constants.%struct.f56]\n// CHECK:STDOUT:   %.loc7_50.4: init %Base = as_compatible %.loc7_50.3 [concrete = constants.%Base.val]\n// CHECK:STDOUT:   %.loc7_50.5: init %Child to %a.var = class_init (%.loc7_50.4) [concrete = constants.%Child.val]\n// CHECK:STDOUT:   %.loc7_3: init %Child = converted %.loc7_50.1, %.loc7_50.5 [concrete = constants.%Child.val]\n// CHECK:STDOUT:   assign %a.var, %.loc7_3\n// CHECK:STDOUT:   %Child.ref: type = name_ref Child, imports.%Main.Child [concrete = constants.%Child]\n// CHECK:STDOUT:   %a: ref %Child = ref_binding a, %a.var\n// CHECK:STDOUT:   %a.ref.loc8: ref %Child = name_ref a, %a\n// CHECK:STDOUT:   %x.ref: %Base.elem = name_ref x, imports.%Main.import_ref.183 [concrete = imports.%.61a]\n// CHECK:STDOUT:   %.loc8_4.1: ref %Base = class_element_access %a.ref.loc8, element0\n// CHECK:STDOUT:   %.loc8_4.2: ref %Base = converted %a.ref.loc8, %.loc8_4.1\n// CHECK:STDOUT:   %.loc8_4.3: ref %i32 = class_element_access %.loc8_4.2, element0\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc8: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc8_7.1: <bound method> = bound_method %int_2, %impl.elem0.loc8 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.1eb]\n// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_7.2: <bound method> = bound_method %int_2, %specific_fn.loc8 [concrete = constants.%bound_method.ef3]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %i32 = call %bound_method.loc8_7.2(%int_2) [concrete = constants.%int_2.d0d]\n// CHECK:STDOUT:   %.loc8_7: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%int_2.d0d]\n// CHECK:STDOUT:   assign %.loc8_4.3, %.loc8_7\n// CHECK:STDOUT:   %a.ref.loc9: ref %Child = name_ref a, %a\n// CHECK:STDOUT:   %F.ref: %Base.F.type = name_ref F, imports.%Main.import_ref.062 [concrete = constants.%Base.F]\n// CHECK:STDOUT:   %Base.F.bound: <bound method> = bound_method %a.ref.loc9, %F.ref\n// CHECK:STDOUT:   %.loc9_3.1: ref %Base = class_element_access %a.ref.loc9, element0\n// CHECK:STDOUT:   %.loc9_3.2: ref %Base = converted %a.ref.loc9, %.loc9_3.1\n// CHECK:STDOUT:   %.loc9_3.3: %Base = acquire_value %.loc9_3.2\n// CHECK:STDOUT:   %Base.F.call: init %empty_tuple.type = call %Base.F.bound(%.loc9_3.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Base.F [from \"a.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Child) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/inheritance/self_conversion.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/inheritance/self_conversion.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/inheritance/self_conversion.carbon\n\nbase class Base {\n  var a: i32;\n}\n\nclass Derived {\n  extend base: Base;\n\n  fn SelfBase[self: Base]() -> i32;\n  fn RefSelfBase[ref self: Base]();\n}\n\nfn Derived.SelfBase[self: Base]() -> i32 {\n  return self.a;\n}\n\nfn Derived.RefSelfBase[ref self: Base]() {\n  self.a = 1;\n}\n\nfn Call(p: Derived*) -> i32 {\n  (*p).RefSelfBase();\n  return (*p).SelfBase();\n}\n\n// CHECK:STDOUT: --- self_conversion.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.fd7: <witness> = complete_type_witness %struct_type.a [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %pattern_type.101: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Derived.SelfBase.type: type = fn_type @Derived.SelfBase [concrete]\n// CHECK:STDOUT:   %Derived.SelfBase: %Derived.SelfBase.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.RefSelfBase.type: type = fn_type @Derived.RefSelfBase [concrete]\n// CHECK:STDOUT:   %Derived.RefSelfBase: %Derived.RefSelfBase.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.27a: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.5a1: <witness> = complete_type_witness %struct_type.base.27a [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %ptr.f74: type = ptr_type %Derived [concrete]\n// CHECK:STDOUT:   %pattern_type.0dd: type = pattern_type %ptr.f74 [concrete]\n// CHECK:STDOUT:   %Call.type: type = fn_type @Call [concrete]\n// CHECK:STDOUT:   %Call: %Call.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .Call = %Call.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Derived.SelfBase.decl: %Derived.SelfBase.type = fn_decl @Derived.SelfBase [concrete = constants.%Derived.SelfBase] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc26: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc26: Core.Form = init_form %i32.loc26 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc26: %Base = value_param call_param0\n// CHECK:STDOUT:     %Base.ref.loc26: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:     %self.loc26: %Base = value_binding self, %self.param.loc26\n// CHECK:STDOUT:     %return.param.loc26: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc26: ref %i32 = return_slot %return.param.loc26\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Derived.RefSelfBase.decl: %Derived.RefSelfBase.type = fn_decl @Derived.RefSelfBase [concrete = constants.%Derived.RefSelfBase] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param.loc30: ref %Base = ref_param call_param0\n// CHECK:STDOUT:     %Base.ref.loc30: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:     %self.loc30: ref %Base = ref_binding self, %self.param.loc30\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Call.decl: %Call.type = fn_decl @Call [concrete = constants.%Call] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.0dd = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.0dd = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc34_25: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %p.param: %ptr.f74 = value_param call_param0\n// CHECK:STDOUT:     %.loc34_19: type = splice_block %ptr [concrete = constants.%ptr.f74] {\n// CHECK:STDOUT:       %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Derived.ref [concrete = constants.%ptr.f74]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.f74 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc16: %Base.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a [concrete = constants.%complete_type.fd7]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .a = %.loc16\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc20: %Derived.elem = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %Derived.SelfBase.decl: %Derived.SelfBase.type = fn_decl @Derived.SelfBase [concrete = constants.%Derived.SelfBase] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc22: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc22: Core.Form = init_form %i32.loc22 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc22: %Base = value_param call_param0\n// CHECK:STDOUT:     %Base.ref.loc22: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:     %self.loc22: %Base = value_binding self, %self.param.loc22\n// CHECK:STDOUT:     %return.param.loc22: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc22: ref %i32 = return_slot %return.param.loc22\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Derived.RefSelfBase.decl: %Derived.RefSelfBase.type = fn_decl @Derived.RefSelfBase [concrete = constants.%Derived.RefSelfBase] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param.loc23: ref %Base = ref_param call_param0\n// CHECK:STDOUT:     %Base.ref.loc23: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:     %self.loc23: ref %Base = ref_binding self, %self.param.loc23\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.27a [concrete = constants.%complete_type.5a1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc20\n// CHECK:STDOUT:   .SelfBase = %Derived.SelfBase.decl\n// CHECK:STDOUT:   .RefSelfBase = %Derived.RefSelfBase.decl\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Derived.SelfBase(%self.param.loc26: %Base) -> out %return.param.loc26: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %Base = name_ref self, %self.loc26\n// CHECK:STDOUT:   %a.ref: %Base.elem = name_ref a, @Base.%.loc16 [concrete = @Base.%.loc16]\n// CHECK:STDOUT:   %.loc27_14.1: ref %i32 = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc27_14.2: %i32 = acquire_value %.loc27_14.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc27_14.1: <bound method> = bound_method %.loc27_14.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc27_14.2: <bound method> = bound_method %.loc27_14.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc27_14.2(%.loc27_14.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Derived.RefSelfBase(%self.param.loc30: ref %Base) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: ref %Base = name_ref self, %self.loc30\n// CHECK:STDOUT:   %a.ref: %Base.elem = name_ref a, @Base.%.loc16 [concrete = @Base.%.loc16]\n// CHECK:STDOUT:   %.loc31_7: ref %i32 = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc31_10.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc31_10.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc31_10.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc31_10: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   assign %.loc31_7, %.loc31_10\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%p.param: %ptr.f74) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref.loc35: %ptr.f74 = name_ref p, %p\n// CHECK:STDOUT:   %.loc35_4.1: ref %Derived = deref %p.ref.loc35\n// CHECK:STDOUT:   %RefSelfBase.ref: %Derived.RefSelfBase.type = name_ref RefSelfBase, @Derived.%Derived.RefSelfBase.decl [concrete = constants.%Derived.RefSelfBase]\n// CHECK:STDOUT:   %Derived.RefSelfBase.bound: <bound method> = bound_method %.loc35_4.1, %RefSelfBase.ref\n// CHECK:STDOUT:   %.loc35_4.2: ref %Base = class_element_access %.loc35_4.1, element0\n// CHECK:STDOUT:   %.loc35_4.3: ref %Base = converted %.loc35_4.1, %.loc35_4.2\n// CHECK:STDOUT:   %Derived.RefSelfBase.call: init %empty_tuple.type = call %Derived.RefSelfBase.bound(%.loc35_4.3)\n// CHECK:STDOUT:   %p.ref.loc36: %ptr.f74 = name_ref p, %p\n// CHECK:STDOUT:   %.loc36_11.1: ref %Derived = deref %p.ref.loc36\n// CHECK:STDOUT:   %SelfBase.ref: %Derived.SelfBase.type = name_ref SelfBase, @Derived.%Derived.SelfBase.decl [concrete = constants.%Derived.SelfBase]\n// CHECK:STDOUT:   %Derived.SelfBase.bound: <bound method> = bound_method %.loc36_11.1, %SelfBase.ref\n// CHECK:STDOUT:   %.loc36_11.2: ref %Base = class_element_access %.loc36_11.1, element0\n// CHECK:STDOUT:   %.loc36_11.3: ref %Base = converted %.loc36_11.1, %.loc36_11.2\n// CHECK:STDOUT:   %.loc36_11.4: %Base = acquire_value %.loc36_11.3\n// CHECK:STDOUT:   %Derived.SelfBase.call: init %i32 = call %Derived.SelfBase.bound(%.loc36_11.4)\n// CHECK:STDOUT:   return %Derived.SelfBase.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/init.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/init.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/init.carbon\n\nclass Class {\n  var n: i32;\n  var next: Class*;\n}\n\nfn Make(n: i32, next: Class*) -> Class {\n  return {.n = n, .next = next};\n}\n\nfn MakeReorder(n: i32, next: Class*) -> Class {\n  return {.next = next, .n = n};\n}\n\n// CHECK:STDOUT: --- init.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Class.elem.762: type = unbound_element_type %Class, %i32 [concrete]\n// CHECK:STDOUT:   %ptr.8e5: type = ptr_type %Class [concrete]\n// CHECK:STDOUT:   %Class.elem.f74: type = unbound_element_type %Class, %ptr.8e5 [concrete]\n// CHECK:STDOUT:   %struct_type.n.next: type = struct_type {.n: %i32, .next: %ptr.8e5} [concrete]\n// CHECK:STDOUT:   %complete_type.bf0: <witness> = complete_type_witness %struct_type.n.next [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.018: type = pattern_type %ptr.8e5 [concrete]\n// CHECK:STDOUT:   %.cff: Core.Form = init_form %Class [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.9d3: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%Class) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.02e: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%Class) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.120: %ptr.as.Copy.impl.Op.type.02e = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.734: %Copy.type = facet_value %ptr.8e5, (%Copy.impl_witness.9d3) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.130: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.734) [concrete]\n// CHECK:STDOUT:   %.370: type = fn_type_with_self_type %Copy.WithSelf.Op.type.130, %Copy.facet.734 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.120, @ptr.as.Copy.impl.Op(%Class) [concrete]\n// CHECK:STDOUT:   %MakeReorder.type: type = fn_type @MakeReorder [concrete]\n// CHECK:STDOUT:   %MakeReorder: %MakeReorder.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.next.n: type = struct_type {.next: %ptr.8e5, .n: %i32} [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .Make = %Make.decl\n// CHECK:STDOUT:     .MakeReorder = %MakeReorder.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Make.decl: %Make.type = fn_decl @Make [concrete = constants.%Make] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %next.patt: %pattern_type.018 = value_binding_pattern next [concrete]\n// CHECK:STDOUT:     %next.param_patt: %pattern_type.018 = value_param_pattern %next.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.904 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.904 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Class.ref.loc20_34: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     %.loc20_34: Core.Form = init_form %Class.ref.loc20_34 [concrete = constants.%.cff]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %next.param: %ptr.8e5 = value_param call_param1\n// CHECK:STDOUT:     %.loc20_28: type = splice_block %ptr [concrete = constants.%ptr.8e5] {\n// CHECK:STDOUT:       %Class.ref.loc20_23: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Class.ref.loc20_23 [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %next: %ptr.8e5 = value_binding next, %next.param\n// CHECK:STDOUT:     %return.param: ref %Class = out_param call_param2\n// CHECK:STDOUT:     %return: ref %Class = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %MakeReorder.decl: %MakeReorder.type = fn_decl @MakeReorder [concrete = constants.%MakeReorder] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %next.patt: %pattern_type.018 = value_binding_pattern next [concrete]\n// CHECK:STDOUT:     %next.param_patt: %pattern_type.018 = value_param_pattern %next.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.904 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.904 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Class.ref.loc24_41: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     %.loc24_41: Core.Form = init_form %Class.ref.loc24_41 [concrete = constants.%.cff]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %next.param: %ptr.8e5 = value_param call_param1\n// CHECK:STDOUT:     %.loc24_35: type = splice_block %ptr [concrete = constants.%ptr.8e5] {\n// CHECK:STDOUT:       %Class.ref.loc24_30: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Class.ref.loc24_30 [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %next: %ptr.8e5 = value_binding next, %next.param\n// CHECK:STDOUT:     %return.param: ref %Class = out_param call_param2\n// CHECK:STDOUT:     %return: ref %Class = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc16: %Class.elem.762 = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %ptr: type = ptr_type %Class.ref [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:   %.loc17: %Class.elem.f74 = field_decl next, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n.next [concrete = constants.%complete_type.bf0]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .n = %.loc16\n// CHECK:STDOUT:   .Class = <poisoned>\n// CHECK:STDOUT:   .next = %.loc17\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Make(%n.param: %i32, %next.param: %ptr.8e5) -> out %return.param: %Class {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %next.ref: %ptr.8e5 = name_ref next, %next\n// CHECK:STDOUT:   %.loc21_31.1: %struct_type.n.next = struct_literal (%n.ref, %next.ref)\n// CHECK:STDOUT:   %impl.elem0.loc21_16: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc21_16.1: <bound method> = bound_method %n.ref, %impl.elem0.loc21_16\n// CHECK:STDOUT:   %specific_fn.loc21_16: <specific function> = specific_function %impl.elem0.loc21_16, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc21_16.2: <bound method> = bound_method %n.ref, %specific_fn.loc21_16\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc21_16.2(%n.ref)\n// CHECK:STDOUT:   %.loc21_31.2: ref %i32 = class_element_access %return.param, element0\n// CHECK:STDOUT:   %.loc21_31.3: init %i32 to %.loc21_31.2 = in_place_init %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   %impl.elem0.loc21_27: %.370 = impl_witness_access constants.%Copy.impl_witness.9d3, element0 [concrete = constants.%ptr.as.Copy.impl.Op.120]\n// CHECK:STDOUT:   %bound_method.loc21_27.1: <bound method> = bound_method %next.ref, %impl.elem0.loc21_27\n// CHECK:STDOUT:   %specific_fn.loc21_27: <specific function> = specific_function %impl.elem0.loc21_27, @ptr.as.Copy.impl.Op(constants.%Class) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc21_27.2: <bound method> = bound_method %next.ref, %specific_fn.loc21_27\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.8e5 = call %bound_method.loc21_27.2(%next.ref)\n// CHECK:STDOUT:   %.loc21_31.4: ref %ptr.8e5 = class_element_access %return.param, element1\n// CHECK:STDOUT:   %.loc21_31.5: init %ptr.8e5 to %.loc21_31.4 = in_place_init %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   %.loc21_31.6: init %Class to %return.param = class_init (%.loc21_31.3, %.loc21_31.5)\n// CHECK:STDOUT:   %.loc21_32: init %Class = converted %.loc21_31.1, %.loc21_31.6\n// CHECK:STDOUT:   return %.loc21_32 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MakeReorder(%n.param: %i32, %next.param: %ptr.8e5) -> out %return.param: %Class {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %next.ref: %ptr.8e5 = name_ref next, %next\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %.loc25_31.1: %struct_type.next.n = struct_literal (%next.ref, %n.ref)\n// CHECK:STDOUT:   %impl.elem0.loc25_30: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc25_30.1: <bound method> = bound_method %n.ref, %impl.elem0.loc25_30\n// CHECK:STDOUT:   %specific_fn.loc25_30: <specific function> = specific_function %impl.elem0.loc25_30, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc25_30.2: <bound method> = bound_method %n.ref, %specific_fn.loc25_30\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc25_30.2(%n.ref)\n// CHECK:STDOUT:   %.loc25_31.2: ref %i32 = class_element_access %return.param, element1\n// CHECK:STDOUT:   %.loc25_31.3: init %i32 to %.loc25_31.2 = in_place_init %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   %impl.elem0.loc25_19: %.370 = impl_witness_access constants.%Copy.impl_witness.9d3, element0 [concrete = constants.%ptr.as.Copy.impl.Op.120]\n// CHECK:STDOUT:   %bound_method.loc25_19.1: <bound method> = bound_method %next.ref, %impl.elem0.loc25_19\n// CHECK:STDOUT:   %specific_fn.loc25_19: <specific function> = specific_function %impl.elem0.loc25_19, @ptr.as.Copy.impl.Op(constants.%Class) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc25_19.2: <bound method> = bound_method %next.ref, %specific_fn.loc25_19\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.8e5 = call %bound_method.loc25_19.2(%next.ref)\n// CHECK:STDOUT:   %.loc25_31.4: ref %ptr.8e5 = class_element_access %return.param, element0\n// CHECK:STDOUT:   %.loc25_31.5: init %ptr.8e5 to %.loc25_31.4 = in_place_init %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   %.loc25_31.6: init %Class to %return.param = class_init (%.loc25_31.3, %.loc25_31.5)\n// CHECK:STDOUT:   %.loc25_32: init %Class = converted %.loc25_31.1, %.loc25_31.6\n// CHECK:STDOUT:   return %.loc25_32 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/init_as.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/init_as.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/init_as.carbon\n\nclass Class {\n  var a: i32;\n  var b: i32;\n}\n\nfn F() -> i32 {\n  //@dump-sem-ir-begin\n  return ({.a = 1, .b = 2} as Class).a;\n  //@dump-sem-ir-end\n}\n\nfn G() -> i32 {\n  //@dump-sem-ir-begin\n  var v: Class = {.a = 1, .b = 2} as Class;\n  //@dump-sem-ir-end\n  return v.a;\n}\n\n// CHECK:STDOUT: --- init_as.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %i32 [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.cfd: type = struct_type {.a: Core.IntLiteral, .b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.a.b.cfd = struct_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %Class.val: %Class = struct_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc20_26.1: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2) [concrete = constants.%struct]\n// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %impl.elem0.loc20_26.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc20_26.1: <bound method> = bound_method %int_1, %impl.elem0.loc20_26.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc20_26.1: <specific function> = specific_function %impl.elem0.loc20_26.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc20_26.2: <bound method> = bound_method %int_1, %specific_fn.loc20_26.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc20_26.1: init %i32 = call %bound_method.loc20_26.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc20_26.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc20_26.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc20_26.3: ref %Class = temporary_storage\n// CHECK:STDOUT:   %.loc20_26.4: ref %i32 = class_element_access %.loc20_26.3, element0\n// CHECK:STDOUT:   %.loc20_26.5: init %i32 to %.loc20_26.4 = in_place_init %.loc20_26.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc20_26.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc20_26.3: <bound method> = bound_method %int_2, %impl.elem0.loc20_26.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc20_26.2: <specific function> = specific_function %impl.elem0.loc20_26.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc20_26.4: <bound method> = bound_method %int_2, %specific_fn.loc20_26.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc20_26.2: init %i32 = call %bound_method.loc20_26.4(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc20_26.6: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc20_26.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc20_26.7: ref %i32 = class_element_access %.loc20_26.3, element1\n// CHECK:STDOUT:   %.loc20_26.8: init %i32 to %.loc20_26.7 = in_place_init %.loc20_26.6 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc20_26.9: init %Class to %.loc20_26.3 = class_init (%.loc20_26.5, %.loc20_26.8) [concrete = constants.%Class.val]\n// CHECK:STDOUT:   %.loc20_28.1: init %Class = converted %.loc20_26.1, %.loc20_26.9 [concrete = constants.%Class.val]\n// CHECK:STDOUT:   %.loc20_28.2: ref %Class = temporary %.loc20_26.3, %.loc20_28.1\n// CHECK:STDOUT:   %a.ref: %Class.elem = name_ref a, @Class.%.loc14 [concrete = @Class.%.loc14]\n// CHECK:STDOUT:   %.loc20_37.1: ref %i32 = class_element_access %.loc20_28.2, element0\n// CHECK:STDOUT:   %.loc20_37.2: %i32 = acquire_value %.loc20_37.1\n// CHECK:STDOUT:   %impl.elem0.loc20_37: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc20_37.1: <bound method> = bound_method %.loc20_37.2, %impl.elem0.loc20_37\n// CHECK:STDOUT:   %specific_fn.loc20_37: <specific function> = specific_function %impl.elem0.loc20_37, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc20_37.2: <bound method> = bound_method %.loc20_37.2, %specific_fn.loc20_37\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc20_37.2(%.loc20_37.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc20_28.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc20_28.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Class) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.904 = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.904 = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %Class = var %v.var_patt\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc26_33.1: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2) [concrete = constants.%struct]\n// CHECK:STDOUT:   %Class.ref.loc26_38: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %impl.elem0.loc26_33.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc26_33.1: <bound method> = bound_method %int_1, %impl.elem0.loc26_33.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc26_33.1: <specific function> = specific_function %impl.elem0.loc26_33.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc26_33.2: <bound method> = bound_method %int_1, %specific_fn.loc26_33.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc26_33.1: init %i32 = call %bound_method.loc26_33.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc26_33.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc26_33.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc26_3: ref %Class = splice_block %v.var {}\n// CHECK:STDOUT:   %.loc26_33.3: ref %i32 = class_element_access %.loc26_3, element0\n// CHECK:STDOUT:   %.loc26_33.4: init %i32 to %.loc26_33.3 = in_place_init %.loc26_33.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc26_33.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc26_33.3: <bound method> = bound_method %int_2, %impl.elem0.loc26_33.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc26_33.2: <specific function> = specific_function %impl.elem0.loc26_33.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc26_33.4: <bound method> = bound_method %int_2, %specific_fn.loc26_33.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc26_33.2: init %i32 = call %bound_method.loc26_33.4(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc26_33.5: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc26_33.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc26_33.6: ref %i32 = class_element_access %.loc26_3, element1\n// CHECK:STDOUT:   %.loc26_33.7: init %i32 to %.loc26_33.6 = in_place_init %.loc26_33.5 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc26_33.8: init %Class to %.loc26_3 = class_init (%.loc26_33.4, %.loc26_33.7) [concrete = constants.%Class.val]\n// CHECK:STDOUT:   %.loc26_35: init %Class = converted %.loc26_33.1, %.loc26_33.8 [concrete = constants.%Class.val]\n// CHECK:STDOUT:   assign %v.var, %.loc26_35\n// CHECK:STDOUT:   %Class.ref.loc26_10: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %v: ref %Class = ref_binding v, %v.var\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %v.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%v.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/init_nested.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/init_nested.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/init_nested.carbon\n\nclass Inner {\n  var a: i32;\n  var b: i32;\n}\n\nfn MakeInner() -> Inner;\n\nclass Outer {\n  var c: Inner;\n  var d: Inner;\n}\n\nfn MakeOuter() -> Outer {\n  return {.c = MakeInner(), .d = MakeInner()};\n}\n\n// CHECK:STDOUT: --- init_nested.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Inner: type = class_type @Inner [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Inner.elem: type = unbound_element_type %Inner, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: %i32, .b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.705: <witness> = complete_type_witness %struct_type.a.b [concrete]\n// CHECK:STDOUT:   %.413: Core.Form = init_form %Inner [concrete]\n// CHECK:STDOUT:   %pattern_type.84b: type = pattern_type %Inner [concrete]\n// CHECK:STDOUT:   %MakeInner.type: type = fn_type @MakeInner [concrete]\n// CHECK:STDOUT:   %MakeInner: %MakeInner.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Outer: type = class_type @Outer [concrete]\n// CHECK:STDOUT:   %Outer.elem: type = unbound_element_type %Outer, %Inner [concrete]\n// CHECK:STDOUT:   %struct_type.c.d.8f4: type = struct_type {.c: %Inner, .d: %Inner} [concrete]\n// CHECK:STDOUT:   %complete_type.3ed: <witness> = complete_type_witness %struct_type.c.d.8f4 [concrete]\n// CHECK:STDOUT:   %.b00: Core.Form = init_form %Outer [concrete]\n// CHECK:STDOUT:   %pattern_type.9ae: type = pattern_type %Outer [concrete]\n// CHECK:STDOUT:   %MakeOuter.type: type = fn_type @MakeOuter [concrete]\n// CHECK:STDOUT:   %MakeOuter: %MakeOuter.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Inner = %Inner.decl\n// CHECK:STDOUT:     .MakeInner = %MakeInner.decl\n// CHECK:STDOUT:     .Outer = %Outer.decl\n// CHECK:STDOUT:     .MakeOuter = %MakeOuter.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Inner.decl: type = class_decl @Inner [concrete = constants.%Inner] {} {}\n// CHECK:STDOUT:   %MakeInner.decl: %MakeInner.type = fn_decl @MakeInner [concrete = constants.%MakeInner] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.84b = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.84b = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Inner.ref: type = name_ref Inner, file.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:     %.loc20: Core.Form = init_form %Inner.ref [concrete = constants.%.413]\n// CHECK:STDOUT:     %return.param: ref %Inner = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Inner = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Outer.decl: type = class_decl @Outer [concrete = constants.%Outer] {} {}\n// CHECK:STDOUT:   %MakeOuter.decl: %MakeOuter.type = fn_decl @MakeOuter [concrete = constants.%MakeOuter] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.9ae = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.9ae = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Outer.ref: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:     %.loc27: Core.Form = init_form %Outer.ref [concrete = constants.%.b00]\n// CHECK:STDOUT:     %return.param: ref %Outer = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Outer = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Inner {\n// CHECK:STDOUT:   %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc16: %Inner.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %i32.loc17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc17: %Inner.elem = field_decl b, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.b [concrete = constants.%complete_type.705]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Inner\n// CHECK:STDOUT:   .a = %.loc16\n// CHECK:STDOUT:   .b = %.loc17\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Outer {\n// CHECK:STDOUT:   %Inner.ref.loc23: type = name_ref Inner, file.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:   %.loc23: %Outer.elem = field_decl c, element0 [concrete]\n// CHECK:STDOUT:   %Inner.ref.loc24: type = name_ref Inner, file.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:   %.loc24: %Outer.elem = field_decl d, element1 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.c.d.8f4 [concrete = constants.%complete_type.3ed]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Outer\n// CHECK:STDOUT:   .Inner = <poisoned>\n// CHECK:STDOUT:   .c = %.loc23\n// CHECK:STDOUT:   .d = %.loc24\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MakeInner() -> out %return.param: %Inner;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MakeOuter() -> out %return.param: %Outer {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %MakeInner.ref.loc28_16: %MakeInner.type = name_ref MakeInner, file.%MakeInner.decl [concrete = constants.%MakeInner]\n// CHECK:STDOUT:   %.loc28_45.1: ref %Inner = class_element_access %return.param, element0\n// CHECK:STDOUT:   %MakeInner.call.loc28_26: init %Inner to %.loc28_45.1 = call %MakeInner.ref.loc28_16()\n// CHECK:STDOUT:   %MakeInner.ref.loc28_34: %MakeInner.type = name_ref MakeInner, file.%MakeInner.decl [concrete = constants.%MakeInner]\n// CHECK:STDOUT:   %.loc28_45.2: ref %Inner = class_element_access %return.param, element1\n// CHECK:STDOUT:   %MakeInner.call.loc28_44: init %Inner to %.loc28_45.2 = call %MakeInner.ref.loc28_34()\n// CHECK:STDOUT:   %.loc28_45.3: %struct_type.c.d.8f4 = struct_literal (%MakeInner.call.loc28_26, %MakeInner.call.loc28_44)\n// CHECK:STDOUT:   %.loc28_45.4: init %Outer to %return.param = class_init (%MakeInner.call.loc28_26, %MakeInner.call.loc28_44)\n// CHECK:STDOUT:   %.loc28_46: init %Outer = converted %.loc28_45.3, %.loc28_45.4\n// CHECK:STDOUT:   return %.loc28_46 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/local.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/local.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/local.carbon\n\nclass A {\n  fn F() -> i32 {\n    class B {\n      fn Make() -> Self {\n        returned var b: Self = {.n = 1};\n        return var;\n      }\n\n      var n: i32;\n    }\n\n    return B.Make().n;\n  }\n}\n\n// CHECK:STDOUT: --- local.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %A.F.type: type = fn_type @A.F [concrete]\n// CHECK:STDOUT:   %A.F: %A.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %.18e: Core.Form = init_form %B [concrete]\n// CHECK:STDOUT:   %pattern_type.971: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %B.Make.type: type = fn_type @B.Make [concrete]\n// CHECK:STDOUT:   %B.Make: %B.Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B.elem: type = unbound_element_type %B, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.n.033: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n.033 [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.n.44a: type = struct_type {.n: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.n.44a = struct_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %B.val: %B = struct_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %A.F.decl: %A.F.type = fn_decl @A.F [concrete = constants.%A.F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .F = %A.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %B.Make.decl: %B.Make.type = fn_decl @B.Make [concrete = constants.%B.Make] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.971 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.971 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Self.ref.loc18: type = name_ref Self, constants.%B [concrete = constants.%B]\n// CHECK:STDOUT:     %.loc18: Core.Form = init_form %Self.ref.loc18 [concrete = constants.%.18e]\n// CHECK:STDOUT:     %return.param: ref %B = out_param call_param0\n// CHECK:STDOUT:     %return: ref %B = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc23: %B.elem = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n.033 [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .Make = %B.Make.decl\n// CHECK:STDOUT:   .n = %.loc23\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.F() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %B.ref: type = name_ref B, %B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %Make.ref: %B.Make.type = name_ref Make, @B.%B.Make.decl [concrete = constants.%B.Make]\n// CHECK:STDOUT:   %.loc26_19.1: ref %B = temporary_storage\n// CHECK:STDOUT:   %B.Make.call: init %B to %.loc26_19.1 = call %Make.ref()\n// CHECK:STDOUT:   %.loc26_19.2: ref %B = temporary %.loc26_19.1, %B.Make.call\n// CHECK:STDOUT:   %n.ref: %B.elem = name_ref n, @B.%.loc23 [concrete = @B.%.loc23]\n// CHECK:STDOUT:   %.loc26_20.1: ref %i32 = class_element_access %.loc26_19.2, element0\n// CHECK:STDOUT:   %.loc26_20.2: %i32 = acquire_value %.loc26_20.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc26_20.1: <bound method> = bound_method %.loc26_20.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc26_20.2: <bound method> = bound_method %.loc26_20.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc26_20.2(%.loc26_20.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc26_19.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc26_19.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.Make() -> out %return.param: %B {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.971 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.971 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc19_39.1: %struct_type.n.44a = struct_literal (%int_1) [concrete = constants.%struct]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc19_39.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc19_39.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc19_39.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc19_39.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc19_39.3: ref %i32 = class_element_access %return.param, element0\n// CHECK:STDOUT:   %.loc19_39.4: init %i32 to %.loc19_39.3 = in_place_init %.loc19_39.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc19_39.5: init %B to %return.param = class_init (%.loc19_39.4) [concrete = constants.%B.val]\n// CHECK:STDOUT:   %.loc19_18: init %B = converted %.loc19_39.1, %.loc19_39.5 [concrete = constants.%B.val]\n// CHECK:STDOUT:   assign %return.param, %.loc19_18\n// CHECK:STDOUT:   %Self.ref.loc19: type = name_ref Self, constants.%B [concrete = constants.%B]\n// CHECK:STDOUT:   %b: ref %B = ref_binding b, %return.param\n// CHECK:STDOUT:   return %b to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %B) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/method/fail_generic_method.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/method/fail_generic_method.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/method/fail_generic_method.carbon\n\nclass I {}\n\nclass Class(T:! type) {\n  var a: T;\n  fn F[self: Self](n: T);\n}\n\n// TODO: The follow-on errors here aren't great. Investigate whether we can\n// enter the scope anyway if the parameters don't match.\n// CHECK:STDERR: fail_generic_method.carbon:[[@LINE+15]]:17: error: type `<pattern for I>` of parameter 1 in redeclaration differs from previous parameter type `<pattern for type>` [RedeclParamDiffersType]\n// CHECK:STDERR: fn Class(unused N:! I).F[unused self: Self](unused n: T) {}\n// CHECK:STDERR:                 ^\n// CHECK:STDERR: fail_generic_method.carbon:[[@LINE-10]]:13: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n// CHECK:STDERR: class Class(T:! type) {\n// CHECK:STDERR:             ^\n// CHECK:STDERR:\n// CHECK:STDERR: fail_generic_method.carbon:[[@LINE+8]]:39: error: name `Self` not found [NameNotFound]\n// CHECK:STDERR: fn Class(unused N:! I).F[unused self: Self](unused n: T) {}\n// CHECK:STDERR:                                       ^~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_generic_method.carbon:[[@LINE+4]]:55: error: name `T` not found [NameNotFound]\n// CHECK:STDERR: fn Class(unused N:! I).F[unused self: Self](unused n: T) {}\n// CHECK:STDERR:                                                       ^\n// CHECK:STDERR:\nfn Class(unused N:! I).F[unused self: Self](unused n: T) {}\n"
  },
  {
    "path": "toolchain/check/testdata/class/method/fail_method.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/method/fail_method.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/method/fail_method.carbon\n\nclass Class {\n  fn NoSelf();\n  fn WithSelf[self: Class]();\n}\n\nalias A = Class.WithSelf;\n\nfn F(c: Class) {\n  c.NoSelf();\n  c.WithSelf();\n\n  Class.NoSelf();\n  // CHECK:STDERR: fail_method.carbon:[[@LINE+7]]:3: error: missing object argument in method call [MissingObjectInMethodCall]\n  // CHECK:STDERR:   Class.WithSelf();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_method.carbon:[[@LINE-13]]:3: note: calling function declared here [InCallToFunction]\n  // CHECK:STDERR:   fn WithSelf[self: Class]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Class.WithSelf();\n  // CHECK:STDERR: fail_method.carbon:[[@LINE+7]]:3: error: 1 argument passed to function expecting 0 arguments [CallArgCountMismatch]\n  // CHECK:STDERR:   Class.WithSelf(c);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_method.carbon:[[@LINE-21]]:3: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR:   fn WithSelf[self: Class]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Class.WithSelf(c);\n\n  // CHECK:STDERR: fail_method.carbon:[[@LINE+7]]:3: error: missing object argument in method call [MissingObjectInMethodCall]\n  // CHECK:STDERR:   A();\n  // CHECK:STDERR:   ^~~\n  // CHECK:STDERR: fail_method.carbon:[[@LINE-30]]:3: note: calling function declared here [InCallToFunction]\n  // CHECK:STDERR:   fn WithSelf[self: Class]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  A();\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/method/fail_method_modifiers.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/method/fail_method_modifiers.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/method/fail_method_modifiers.carbon\n\nclass FinalClass {\n\n  // CHECK:STDERR: fail_method_modifiers.carbon:[[@LINE+7]]:3: error: `abstract` not allowed; requires `abstract` class scope [ModifierAbstractNotAllowed]\n  // CHECK:STDERR:   abstract fn Abstract[self: Self]();\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR: fail_method_modifiers.carbon:[[@LINE-5]]:1: note: containing definition here [ModifierNotInContext]\n  // CHECK:STDERR: class FinalClass {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  abstract fn Abstract[self: Self]();\n\n  // CHECK:STDERR: fail_method_modifiers.carbon:[[@LINE+7]]:3: error: `virtual` not allowed; requires `abstract` or `base` class scope [ModifierVirtualNotAllowed]\n  // CHECK:STDERR:   virtual fn Virtual[self: Self]();\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_method_modifiers.carbon:[[@LINE-14]]:1: note: containing definition here [ModifierNotInContext]\n  // CHECK:STDERR: class FinalClass {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  virtual fn Virtual[self: Self]();\n}\n\nabstract class AbstractClass {\n\n  // CHECK:STDERR: fail_method_modifiers.carbon:[[@LINE+4]]:3: error: `default` not allowed; requires interface scope [ModifierRequiresInterface]\n  // CHECK:STDERR:   default fn Default[self: Self]();\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  default fn Default[self: Self]();\n\n  // CHECK:STDERR: fail_method_modifiers.carbon:[[@LINE+4]]:3: error: `final` not allowed; requires interface scope [ModifierRequiresInterface]\n  // CHECK:STDERR:   final fn Final[self: Self]();\n  // CHECK:STDERR:   ^~~~~\n  // CHECK:STDERR:\n  final fn Final[self: Self]();\n}\n\nbase class BaseClass {\n\n  // CHECK:STDERR: fail_method_modifiers.carbon:[[@LINE+7]]:3: error: `abstract` not allowed; requires `abstract` class scope [ModifierAbstractNotAllowed]\n  // CHECK:STDERR:   abstract fn Abstract[self: Self]();\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR: fail_method_modifiers.carbon:[[@LINE-5]]:1: note: containing definition here [ModifierNotInContext]\n  // CHECK:STDERR: base class BaseClass {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  abstract fn Abstract[self: Self]();\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/method/fail_method_redefinition.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/method/fail_method_redefinition.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/method/fail_method_redefinition.carbon\n\nclass Class {\n  fn F() {}\n  // CHECK:STDERR: fail_method_redefinition.carbon:[[@LINE+7]]:3: error: redefinition of `fn F` [RedeclRedef]\n  // CHECK:STDERR:   fn F() {}\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR: fail_method_redefinition.carbon:[[@LINE-4]]:3: note: previously defined here [RedeclPrevDef]\n  // CHECK:STDERR:   fn F() {}\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR:\n  fn F() {}\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/method/fail_out_of_line_decl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/method/fail_out_of_line_decl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/method/fail_out_of_line_decl.carbon\n\nclass C {}\n\n// CHECK:STDERR: fail_out_of_line_decl.carbon:[[@LINE+4]]:6: error: out-of-line declaration requires a declaration in scoped entity [QualifiedDeclOutsideScopeEntity]\n// CHECK:STDERR: fn C.F() {}\n// CHECK:STDERR:      ^\n// CHECK:STDERR:\nfn C.F() {}\n"
  },
  {
    "path": "toolchain/check/testdata/class/method/generic_method.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/method/generic_method.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/method/generic_method.carbon\n\nclass Class(T:! type) {\n  var a: T;\n  fn F[self: Self](n: T);\n}\n\nfn Class(T:! type).F[unused self: Self](unused n: T) {}\n\n// CHECK:STDOUT: --- generic_method.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.466: type = pattern_type %Class [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F, @Class(%T) [symbolic]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %T} [symbolic]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [symbolic]\n// CHECK:STDOUT:   %require_complete.43d: <witness> = require_complete_type %Class [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_17.1: type = splice_block %.loc15_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [symbolic = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: @Class.F.%pattern_type.loc17_8 (%pattern_type.466) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: @Class.F.%pattern_type.loc17_8 (%pattern_type.466) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %n.patt: @Class.F.%pattern_type.loc17_20 (%pattern_type.51d) = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: @Class.F.%pattern_type.loc17_20 (%pattern_type.51d) = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc20_14.1: type = splice_block %.loc20_14.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc20_14.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc20: type = symbolic_binding T, 0 [symbolic = @Class.%T.loc15_13.1 (constants.%T)]\n// CHECK:STDOUT:     %self.param.loc20: @Class.F.%Class (%Class) = value_param call_param0\n// CHECK:STDOUT:     %.loc20_35.1: type = splice_block %Self.ref.loc20 [symbolic = %Class (constants.%Class)] {\n// CHECK:STDOUT:       %.loc20_35.2: type = specific_constant constants.%Class, @Class(constants.%T) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:       %Self.ref.loc20: type = name_ref Self, %.loc20_35.2 [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self.loc20: @Class.F.%Class (%Class) = value_binding self, %self.param.loc20\n// CHECK:STDOUT:     %n.param.loc20: @Class.F.%T.loc17 (%T) = value_param call_param1\n// CHECK:STDOUT:     %T.ref.loc20: type = name_ref T, %T.loc20 [symbolic = %T.loc17 (constants.%T)]\n// CHECK:STDOUT:     %n.loc20: @Class.F.%T.loc17 (%T) = value_binding n, %n.param.loc20\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%T.loc15_13.2: type) {\n// CHECK:STDOUT:   %T.loc15_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc15_13.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.loc15_13.1) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %T.loc15_13.1 [symbolic = %Class.elem (constants.%Class.elem)]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F, @Class(%T.loc15_13.1) [symbolic = %Class.F.type (constants.%Class.F.type)]\n// CHECK:STDOUT:   %Class.F: @Class.%Class.F.type (%Class.F.type) = struct_value () [symbolic = %Class.F (constants.%Class.F)]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: @Class.%T.loc15_13.1 (%T)} [symbolic = %struct_type.a (constants.%struct_type.a)]\n// CHECK:STDOUT:   %complete_type.loc18_1.2: <witness> = complete_type_witness %struct_type.a [symbolic = %complete_type.loc18_1.2 (constants.%complete_type)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc15_13.2 [symbolic = %T.loc15_13.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc16: @Class.%Class.elem (%Class.elem) = field_decl a, element0 [concrete]\n// CHECK:STDOUT:     %Class.F.decl: @Class.%Class.F.type (%Class.F.type) = fn_decl @Class.F [symbolic = @Class.%Class.F (constants.%Class.F)] {\n// CHECK:STDOUT:       %self.patt: @Class.F.%pattern_type.loc17_8 (%pattern_type.466) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Class.F.%pattern_type.loc17_8 (%pattern_type.466) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %n.patt: @Class.F.%pattern_type.loc17_20 (%pattern_type.51d) = value_binding_pattern n [concrete]\n// CHECK:STDOUT:       %n.param_patt: @Class.F.%pattern_type.loc17_20 (%pattern_type.51d) = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param.loc17: @Class.F.%Class (%Class) = value_param call_param0\n// CHECK:STDOUT:       %.loc17_14.1: type = splice_block %Self.ref.loc17 [symbolic = %Class (constants.%Class)] {\n// CHECK:STDOUT:         %.loc17_14.2: type = specific_constant constants.%Class, @Class(constants.%T) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:         %Self.ref.loc17: type = name_ref Self, %.loc17_14.2 [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self.loc17: @Class.F.%Class (%Class) = value_binding self, %self.param.loc17\n// CHECK:STDOUT:       %n.param.loc17: @Class.F.%T.loc17 (%T) = value_param call_param1\n// CHECK:STDOUT:       %T.ref.loc17: type = name_ref T, @Class.%T.loc15_13.2 [symbolic = %T.loc17 (constants.%T)]\n// CHECK:STDOUT:       %n.loc17: @Class.F.%T.loc17 (%T) = value_binding n, %n.param.loc17\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type.loc18_1.1: <witness> = complete_type_witness constants.%struct_type.a [symbolic = %complete_type.loc18_1.2 (constants.%complete_type)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc18_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .a = %.loc16\n// CHECK:STDOUT:     .F = %Class.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Class.F(@Class.%T.loc15_13.2: type) {\n// CHECK:STDOUT:   %T.loc17: type = symbolic_binding T, 0 [symbolic = %T.loc17 (constants.%T)]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%T.loc17) [symbolic = %Class (constants.%Class)]\n// CHECK:STDOUT:   %pattern_type.loc17_8: type = pattern_type %Class [symbolic = %pattern_type.loc17_8 (constants.%pattern_type.466)]\n// CHECK:STDOUT:   %pattern_type.loc17_20: type = pattern_type %T.loc17 [symbolic = %pattern_type.loc17_20 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc20_33: <witness> = require_complete_type %Class [symbolic = %require_complete.loc20_33 (constants.%require_complete.43d)]\n// CHECK:STDOUT:   %require_complete.loc20_49: <witness> = require_complete_type %T.loc17 [symbolic = %require_complete.loc20_49 (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param.loc20: @Class.F.%Class (%Class), %n.param.loc20: @Class.F.%T.loc17 (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.944\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %Class.elem => constants.%Class.elem\n// CHECK:STDOUT:   %Class.F.type => constants.%Class.F.type\n// CHECK:STDOUT:   %Class.F => constants.%Class.F\n// CHECK:STDOUT:   %struct_type.a => constants.%struct_type.a\n// CHECK:STDOUT:   %complete_type.loc18_1.2 => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class.F(constants.%T) {\n// CHECK:STDOUT:   %T.loc17 => constants.%T\n// CHECK:STDOUT:   %Class => constants.%Class\n// CHECK:STDOUT:   %pattern_type.loc17_8 => constants.%pattern_type.466\n// CHECK:STDOUT:   %pattern_type.loc17_20 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/method/method.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/method/method.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/method/method.carbon\n\nclass Class {\n  fn F[self: Self]() -> i32;\n  fn G[ref self: Self]() -> i32;\n\n  alias A = F;\n\n  var k: i32;\n}\n\nfn Class.F[self: Self]() -> i32 {\n  return self.k;\n}\n\nfn Call(c: Class) -> i32 {\n  // TODO: The sem-ir for this call doesn't distinguish the `self` argument from\n  // the explicit arguments.\n  return c.F();\n}\n\nfn CallAlias(c: Class) -> i32 {\n  return c.A();\n}\n\nfn CallOnConstBoundMethod() -> i32 {\n  return ({.k = 1} as Class).F();\n}\n\nfn CallWithRef() -> i32 {\n  var c: Class;\n  return c.G();\n}\n\nfn CallFThroughPointer(p: Class*) -> i32 {\n  return (*p).F();\n}\n\nfn CallGThroughPointer(p: Class*) -> i32 {\n  return (*p).G();\n}\n\nfn Make() -> Class;\n\nfn CallFOnInitializingExpr() -> i32 {\n  return Make().F();\n}\n\nfn CallGOnInitializingExpr() -> i32 {\n  return Make().G();\n}\n\n// CHECK:STDOUT: --- method.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G [concrete]\n// CHECK:STDOUT:   %Class.G: %Class.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.k.0bf: type = struct_type {.k: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.954: <witness> = complete_type_witness %struct_type.k.0bf [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Call.type: type = fn_type @Call [concrete]\n// CHECK:STDOUT:   %Call: %Call.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallAlias.type: type = fn_type @CallAlias [concrete]\n// CHECK:STDOUT:   %CallAlias: %CallAlias.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallOnConstBoundMethod.type: type = fn_type @CallOnConstBoundMethod [concrete]\n// CHECK:STDOUT:   %CallOnConstBoundMethod: %CallOnConstBoundMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.k.240: type = struct_type {.k: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.k.240 = struct_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Class.val: %Class = struct_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallWithRef.type: type = fn_type @CallWithRef [concrete]\n// CHECK:STDOUT:   %CallWithRef: %CallWithRef.type = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.6ca: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.3d0: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.cda: %T.as.DefaultOrUnformed.impl.Op.type.3d0 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %Class, (%DefaultOrUnformed.impl_witness.6ca) [concrete]\n// CHECK:STDOUT:   %.cff: Core.Form = init_form %Class [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(%Class) [concrete]\n// CHECK:STDOUT:   %ptr.8e5: type = ptr_type %Class [concrete]\n// CHECK:STDOUT:   %pattern_type.018: type = pattern_type %ptr.8e5 [concrete]\n// CHECK:STDOUT:   %CallFThroughPointer.type: type = fn_type @CallFThroughPointer [concrete]\n// CHECK:STDOUT:   %CallFThroughPointer: %CallFThroughPointer.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallGThroughPointer.type: type = fn_type @CallGThroughPointer [concrete]\n// CHECK:STDOUT:   %CallGThroughPointer: %CallGThroughPointer.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallFOnInitializingExpr.type: type = fn_type @CallFOnInitializingExpr [concrete]\n// CHECK:STDOUT:   %CallFOnInitializingExpr: %CallFOnInitializingExpr.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallGOnInitializingExpr.type: type = fn_type @CallGOnInitializingExpr [concrete]\n// CHECK:STDOUT:   %CallGOnInitializingExpr: %CallGOnInitializingExpr.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .Call = %Call.decl\n// CHECK:STDOUT:     .CallAlias = %CallAlias.decl\n// CHECK:STDOUT:     .CallOnConstBoundMethod = %CallOnConstBoundMethod.decl\n// CHECK:STDOUT:     .CallWithRef = %CallWithRef.decl\n// CHECK:STDOUT:     .CallFThroughPointer = %CallFThroughPointer.decl\n// CHECK:STDOUT:     .CallGThroughPointer = %CallGThroughPointer.decl\n// CHECK:STDOUT:     .Make = %Make.decl\n// CHECK:STDOUT:     .CallFOnInitializingExpr = %CallFOnInitializingExpr.decl\n// CHECK:STDOUT:     .CallGOnInitializingExpr = %CallGOnInitializingExpr.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc24: Core.Form = init_form %i32.loc24 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc24: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc24: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc24: %Class = value_binding self, %self.param.loc24\n// CHECK:STDOUT:     %return.param.loc24: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc24: ref %i32 = return_slot %return.param.loc24\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Call.decl: %Call.type = fn_decl @Call [concrete = constants.%Call] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.904 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.904 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc28: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %c.param: %Class = value_param call_param0\n// CHECK:STDOUT:     %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     %c: %Class = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallAlias.decl: %CallAlias.type = fn_decl @CallAlias [concrete = constants.%CallAlias] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.904 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.904 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc34: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %c.param: %Class = value_param call_param0\n// CHECK:STDOUT:     %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     %c: %Class = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallOnConstBoundMethod.decl: %CallOnConstBoundMethod.type = fn_decl @CallOnConstBoundMethod [concrete = constants.%CallOnConstBoundMethod] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc38: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallWithRef.decl: %CallWithRef.type = fn_decl @CallWithRef [concrete = constants.%CallWithRef] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc42: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallFThroughPointer.decl: %CallFThroughPointer.type = fn_decl @CallFThroughPointer [concrete = constants.%CallFThroughPointer] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.018 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.018 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc47_38: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %p.param: %ptr.8e5 = value_param call_param0\n// CHECK:STDOUT:     %.loc47_32: type = splice_block %ptr [concrete = constants.%ptr.8e5] {\n// CHECK:STDOUT:       %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Class.ref [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.8e5 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallGThroughPointer.decl: %CallGThroughPointer.type = fn_decl @CallGThroughPointer [concrete = constants.%CallGThroughPointer] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.018 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.018 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc51_38: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %p.param: %ptr.8e5 = value_param call_param0\n// CHECK:STDOUT:     %.loc51_32: type = splice_block %ptr [concrete = constants.%ptr.8e5] {\n// CHECK:STDOUT:       %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Class.ref [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.8e5 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Make.decl: %Make.type = fn_decl @Make [concrete = constants.%Make] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.904 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.904 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     %.loc55: Core.Form = init_form %Class.ref [concrete = constants.%.cff]\n// CHECK:STDOUT:     %return.param: ref %Class = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Class = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallFOnInitializingExpr.decl: %CallFOnInitializingExpr.type = fn_decl @CallFOnInitializingExpr [concrete = constants.%CallFOnInitializingExpr] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc57: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallGOnInitializingExpr.decl: %CallGOnInitializingExpr.type = fn_decl @CallGOnInitializingExpr [concrete = constants.%CallGOnInitializingExpr] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc61: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32.loc16 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc16: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc16: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc16: %Class = value_binding self, %self.param.loc16\n// CHECK:STDOUT:     %return.param.loc16: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc16: ref %i32 = return_slot %return.param.loc16\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc17: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: ref %Class = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self: ref %Class = ref_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, %Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %A: %Class.F.type = alias_binding A, %Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc21: %Class.elem = field_decl k, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.k.0bf [concrete = constants.%complete_type.954]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT:   .G = %Class.G.decl\n// CHECK:STDOUT:   .A = %A\n// CHECK:STDOUT:   .k = %.loc21\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F(%self.param.loc24: %Class) -> out %return.param.loc24: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %Class = name_ref self, %self.loc24\n// CHECK:STDOUT:   %k.ref: %Class.elem = name_ref k, @Class.%.loc21 [concrete = @Class.%.loc21]\n// CHECK:STDOUT:   %.loc25_14.1: ref %i32 = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc25_14.2: %i32 = acquire_value %.loc25_14.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc25_14.1: <bound method> = bound_method %.loc25_14.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc25_14.2: <bound method> = bound_method %.loc25_14.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc25_14.2(%.loc25_14.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.G(%self.param: ref %Class) -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call(%c.param: %Class) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %Class = name_ref c, %c\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.bound: <bound method> = bound_method %c.ref, %F.ref\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %Class.F.bound(%c.ref)\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallAlias(%c.param: %Class) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %Class = name_ref c, %c\n// CHECK:STDOUT:   %A.ref: %Class.F.type = name_ref A, @Class.%A [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.bound: <bound method> = bound_method %c.ref, %A.ref\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %Class.F.bound(%c.ref)\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallOnConstBoundMethod() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc39_18.1: %struct_type.k.240 = struct_literal (%int_1) [concrete = constants.%struct]\n// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc39_18.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc39_18.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc39_18.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc39_18.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc39_18.3: ref %Class = temporary_storage\n// CHECK:STDOUT:   %.loc39_18.4: ref %i32 = class_element_access %.loc39_18.3, element0\n// CHECK:STDOUT:   %.loc39_18.5: init %i32 to %.loc39_18.4 = in_place_init %.loc39_18.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc39_18.6: init %Class to %.loc39_18.3 = class_init (%.loc39_18.5) [concrete = constants.%Class.val]\n// CHECK:STDOUT:   %.loc39_20.1: init %Class = converted %.loc39_18.1, %.loc39_18.6 [concrete = constants.%Class.val]\n// CHECK:STDOUT:   %.loc39_20.2: ref %Class = temporary %.loc39_18.3, %.loc39_20.1\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.bound: <bound method> = bound_method %.loc39_20.2, %F.ref\n// CHECK:STDOUT:   %.loc39_20.3: %Class = acquire_value %.loc39_20.2\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %Class.F.bound(%.loc39_20.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc39_20.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc39_20.2)\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Class) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallWithRef() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.904 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.904 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %Class = var %c.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%Class, (constants.%DefaultOrUnformed.impl_witness.6ca) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc43_15.1: %DefaultOrUnformed.type = converted constants.%Class, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc43_15.1 [concrete = constants.%Class]\n// CHECK:STDOUT:   %.loc43_15.2: type = converted %.loc43_15.1, %as_type [concrete = constants.%Class]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(constants.%Class) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc43_3: ref %Class = splice_block %c.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %Class to %.loc43_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %c.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %c: ref %Class = ref_binding c, %c.var\n// CHECK:STDOUT:   %c.ref: ref %Class = name_ref c, %c\n// CHECK:STDOUT:   %G.ref: %Class.G.type = name_ref G, @Class.%Class.G.decl [concrete = constants.%Class.G]\n// CHECK:STDOUT:   %Class.G.bound: <bound method> = bound_method %c.ref, %G.ref\n// CHECK:STDOUT:   %Class.G.call: init %i32 = call %Class.G.bound(%c.ref)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %c.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%c.var)\n// CHECK:STDOUT:   return %Class.G.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallFThroughPointer(%p.param: %ptr.8e5) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.8e5 = name_ref p, %p\n// CHECK:STDOUT:   %.loc48_11.1: ref %Class = deref %p.ref\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.bound: <bound method> = bound_method %.loc48_11.1, %F.ref\n// CHECK:STDOUT:   %.loc48_11.2: %Class = acquire_value %.loc48_11.1\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %Class.F.bound(%.loc48_11.2)\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallGThroughPointer(%p.param: %ptr.8e5) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.8e5 = name_ref p, %p\n// CHECK:STDOUT:   %.loc52: ref %Class = deref %p.ref\n// CHECK:STDOUT:   %G.ref: %Class.G.type = name_ref G, @Class.%Class.G.decl [concrete = constants.%Class.G]\n// CHECK:STDOUT:   %Class.G.bound: <bound method> = bound_method %.loc52, %G.ref\n// CHECK:STDOUT:   %Class.G.call: init %i32 = call %Class.G.bound(%.loc52)\n// CHECK:STDOUT:   return %Class.G.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Make() -> out %return.param: %Class;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallFOnInitializingExpr() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %.loc58_15.1: ref %Class = temporary_storage\n// CHECK:STDOUT:   %Make.call: init %Class to %.loc58_15.1 = call %Make.ref()\n// CHECK:STDOUT:   %.loc58_15.2: ref %Class = temporary %.loc58_15.1, %Make.call\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.bound: <bound method> = bound_method %.loc58_15.2, %F.ref\n// CHECK:STDOUT:   %.loc58_15.3: %Class = acquire_value %.loc58_15.2\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %Class.F.bound(%.loc58_15.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc58_15.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc58_15.2)\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallGOnInitializingExpr() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %.loc62_15.1: ref %Class = temporary_storage\n// CHECK:STDOUT:   %Make.call: init %Class to %.loc62_15.1 = call %Make.ref()\n// CHECK:STDOUT:   %.loc62_15.2: ref %Class = temporary %.loc62_15.1, %Make.call\n// CHECK:STDOUT:   %G.ref: %Class.G.type = name_ref G, @Class.%Class.G.decl [concrete = constants.%Class.G]\n// CHECK:STDOUT:   %Class.G.bound: <bound method> = bound_method %.loc62_15.2, %G.ref\n// CHECK:STDOUT:   %Class.G.call: init %i32 = call %Class.G.bound(%.loc62_15.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc62_15.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc62_15.2)\n// CHECK:STDOUT:   return %Class.G.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/method/static_method.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/method/static_method.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/method/static_method.carbon\n\nclass Class {\n  fn F() -> i32;\n}\n\nfn Run() -> i32 {\n  var c: Class;\n  return c.F();\n}\n\n// CHECK:STDOUT: --- static_method.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.6ca: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.3d0: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.cda: %T.as.DefaultOrUnformed.impl.Op.type.3d0 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %Class, (%DefaultOrUnformed.impl_witness.6ca) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(%Class) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc19: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F() -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.904 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.904 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %Class = var %c.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%Class, (constants.%DefaultOrUnformed.impl_witness.6ca) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc20_15.1: %DefaultOrUnformed.type = converted constants.%Class, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc20_15.1 [concrete = constants.%Class]\n// CHECK:STDOUT:   %.loc20_15.2: type = converted %.loc20_15.1, %as_type [concrete = constants.%Class]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(constants.%Class) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc20_3: ref %Class = splice_block %c.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %Class to %.loc20_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %c.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %c: ref %Class = ref_binding c, %c.var\n// CHECK:STDOUT:   %c.ref: ref %Class = name_ref c, %c\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %F.ref()\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %c.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%c.var)\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Class) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/name_poisoning.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/name_poisoning.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/name_poisoning.carbon\n\n// --- no_poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n// `N.F` uses `N.C` and not `package.C`.\nnamespace N;\nclass N.C {}\nfn N.F(x: C);\n\nfn TestCall(x: N.C) {\n  // `N.F` accepts an `N.C` not a `package.C`.\n  N.F(x);\n}\n\n// --- poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\nnamespace N;\n// Use `package.C` and poison `N.C`.\nfn N.F(x: C);\n\n// --- fail_declare_after_poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\nnamespace N;\n// Use `package.C` and poison `N.C`.\n// CHECK:STDERR: fail_declare_after_poison.carbon:[[@LINE+3]]:11: error: name `C` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: fn N.F(x: C);\n// CHECK:STDERR:           ^\nfn N.F(x: C);\n\n// Failure: `N.C` declared after it was poisoned.\n// CHECK:STDERR: fail_declare_after_poison.carbon:[[@LINE+4]]:9: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: class N.C;\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nclass N.C;\n\n// --- fail_use_poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\nnamespace N;\n// Use `package.C` and poison `N.C`.\nfn N.F1() -> C;\n\n// Use `N.C` which was poisoned and not declared.\n// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:14: error: member name `C` not found in `N` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: fn N.F2() -> N.C;\n// CHECK:STDERR:              ^~~\n// CHECK:STDERR:\nfn N.F2() -> N.C;\n\n// --- fail_use_declaration_after_poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\nnamespace N;\n// Use `package.C` and poison `N.C`.\n// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+3]]:12: error: name `C` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: fn N.F1(x: C);\n// CHECK:STDERR:            ^\nfn N.F1(x: C);\n\n// Failure: N.C declared after it was poisoned.\n// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:9: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: class N.C;\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nclass N.C;\n\n// Failure: `N.C` used after declaration failed.\n// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:12: error: member name `C` not found in `N` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: fn N.F2(x: N.C);\n// CHECK:STDERR:            ^~~\n// CHECK:STDERR:\nfn N.F2(x: N.C);\n\n// --- fail_alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\nnamespace N;\n// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:13: error: name `C` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: alias N.C = C;\n// CHECK:STDERR:             ^\n// CHECK:STDERR: fail_alias.carbon:[[@LINE+4]]:9: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: alias N.C = C;\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nalias N.C = C;\n\n// --- fail_poison_multiple_scopes.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C1;\n\nclass C2 {\n  class C3 {\n    class C4 {\n      // Use `package.C1` and poison:\n      // * `C2.C1`\n      // * `C2.C3.C1`\n      // * `C2.C3.C4.C1`\n      // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+3]]:15: error: name `C1` used before it was declared [NameUseBeforeDecl]\n      // CHECK:STDERR:       fn F(x: C1);\n      // CHECK:STDERR:               ^~\n      fn F(x: C1);\n\n      // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+7]]:13: note: declared here [NameUseBeforeDeclNote]\n      // CHECK:STDERR:       class C1;\n      // CHECK:STDERR:             ^~\n      // CHECK:STDERR:\n      // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-6]]:15: error: name `C1` used before it was declared [NameUseBeforeDecl]\n      // CHECK:STDERR:       fn F(x: C1);\n      // CHECK:STDERR:               ^~\n      class C1;\n    }\n    // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+7]]:11: note: declared here [NameUseBeforeDeclNote]\n    // CHECK:STDERR:     class C1;\n    // CHECK:STDERR:           ^~\n    // CHECK:STDERR:\n    // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-15]]:15: error: name `C1` used before it was declared [NameUseBeforeDecl]\n    // CHECK:STDERR:       fn F(x: C1);\n    // CHECK:STDERR:               ^~\n    class C1;\n  }\n  // CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+4]]:9: note: declared here [NameUseBeforeDeclNote]\n  // CHECK:STDERR:   class C1;\n  // CHECK:STDERR:         ^~\n  // CHECK:STDERR:\n  class C1;\n}\n\n// --- ignored_poison_in_import.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"poison\";\n\n// This doesn't fail.\nclass N.C;\n\n// --- poison.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// TODO: #4622 This should fail since `N.C` was poisoned in the api.\nclass N.C {}\n\n// --- fail_poison_when_lookup_fails.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nnamespace N;\n// `package.C` and `N.C` poisoned when not found.\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+7]]:11: error: name `C` not found [NameNotFound]\n// CHECK:STDERR: fn N.F(x: C);\n// CHECK:STDERR:           ^\n// CHECK:STDERR:\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+3]]:11: error: name `C` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: fn N.F(x: C);\n// CHECK:STDERR:           ^\nfn N.F(x: C);\n\n// TODO: We should ideally only produce one diagnostic here.\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+7]]:7: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: class C;\n// CHECK:STDERR:       ^\n// CHECK:STDERR:\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE-7]]:11: error: name `C` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: fn N.F(x: C);\n// CHECK:STDERR:           ^\nclass C;\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+4]]:9: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: class N.C;\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nclass N.C;\n\n// --- fail_poison_with_lexical_result.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {\n  class C1 {}\n\n  class C2 {\n    // CHECK:STDERR: fail_poison_with_lexical_result.carbon:[[@LINE+3]]:12: error: name `C1` used before it was declared [NameUseBeforeDecl]\n    // CHECK:STDERR:     var v: C1;\n    // CHECK:STDERR:            ^~\n    var v: C1;\n\n    // CHECK:STDERR: fail_poison_with_lexical_result.carbon:[[@LINE+4]]:11: note: declared here [NameUseBeforeDeclNote]\n    // CHECK:STDERR:     class C1;\n    // CHECK:STDERR:           ^~\n    // CHECK:STDERR:\n    class C1;\n  }\n}\n\n// --- fail_declare_data_member_after_poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C1;\n\nclass C2 {\n  // Use `package.C1` and poison `C2.C1`.\n  // CHECK:STDERR: fail_declare_data_member_after_poison.carbon:[[@LINE+3]]:11: error: name `C1` used before it was declared [NameUseBeforeDecl]\n  // CHECK:STDERR:   fn F(x: C1);\n  // CHECK:STDERR:           ^~\n  fn F(x: C1);\n\n  class C2 {}\n  // Failure: `C2.C1` declared after it was poisoned.\n  // CHECK:STDERR: fail_declare_data_member_after_poison.carbon:[[@LINE+4]]:7: note: declared here [NameUseBeforeDeclNote]\n  // CHECK:STDERR:   var C1: C2;\n  // CHECK:STDERR:       ^~~~~~\n  // CHECK:STDERR:\n  var C1: C2;\n}\n\n// --- fail_extend_poison_class_members.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class B {}\n\nclass C {\n  // CHECK:STDERR: fail_extend_poison_class_members.carbon:[[@LINE+3]]:16: error: name `B` used before it was declared [NameUseBeforeDecl]\n  // CHECK:STDERR:   extend base: B;\n  // CHECK:STDERR:                ^\n  extend base: B;\n\n  // CHECK:STDERR: fail_extend_poison_class_members.carbon:[[@LINE+4]]:6: note: declared here [NameUseBeforeDeclNote]\n  // CHECK:STDERR:   fn B();\n  // CHECK:STDERR:      ^\n  // CHECK:STDERR:\n  fn B();\n}\n\n// --- todo_fail_poisoned_name_in_extend.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class B {\n  fn F1();\n}\n\nclass F1 {}\n\nclass C {\n  // Use `package.F1` and poison `C.F1`.\n  fn F2(x: F1);\n\n  // TODO: #4622 This should diagnose since `C.F1` is poisoned.\n  extend base: B;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/nested.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/nested.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/nested.carbon\n\nclass Outer {\n  fn F() {\n    // Outer and Inner are both complete here.\n    var unused o: Outer;\n    var unused i: Inner;\n  }\n\n  class Inner {\n    var pi: Self*;\n    var po: Outer*;\n    var qi: Inner*;\n\n    fn G() {\n      // Outer and Inner are both complete here.\n      var unused o: Outer;\n      var unused i: Inner;\n    }\n  }\n\n  fn H() {\n    // Outer and Inner are both complete here.\n    var unused o: Outer;\n    var unused i: Inner;\n  }\n\n  var po: Self*;\n  var qo: Outer*;\n  var pi: Inner*;\n}\n\nfn F(a: Outer*) {\n  let b: Outer.Inner* = (*a).pi;\n\n  a->po = a;\n  a->qo = a;\n  a->pi = a->pi;\n  b->po = a;\n  b->pi = a->pi;\n  b->qi = a->pi;\n}\n\n// CHECK:STDOUT: --- nested.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Outer: type = class_type @Outer [concrete]\n// CHECK:STDOUT:   %Outer.F.type: type = fn_type @Outer.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Outer.F: %Outer.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Inner: type = class_type @Inner [concrete]\n// CHECK:STDOUT:   %ptr.78a: type = ptr_type %Inner [concrete]\n// CHECK:STDOUT:   %Inner.elem.9c1: type = unbound_element_type %Inner, %ptr.78a [concrete]\n// CHECK:STDOUT:   %ptr.56b: type = ptr_type %Outer [concrete]\n// CHECK:STDOUT:   %Inner.elem.9e0: type = unbound_element_type %Inner, %ptr.56b [concrete]\n// CHECK:STDOUT:   %Inner.G.type: type = fn_type @Inner.G [concrete]\n// CHECK:STDOUT:   %Inner.G: %Inner.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.pi.po.qi: type = struct_type {.pi: %ptr.78a, .po: %ptr.56b, .qi: %ptr.78a} [concrete]\n// CHECK:STDOUT:   %complete_type.486: <witness> = complete_type_witness %struct_type.pi.po.qi [concrete]\n// CHECK:STDOUT:   %Outer.H.type: type = fn_type @Outer.H [concrete]\n// CHECK:STDOUT:   %Outer.H: %Outer.H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Outer.elem.1e5: type = unbound_element_type %Outer, %ptr.56b [concrete]\n// CHECK:STDOUT:   %Outer.elem.6db: type = unbound_element_type %Outer, %ptr.78a [concrete]\n// CHECK:STDOUT:   %struct_type.po.qo.pi: type = struct_type {.po: %ptr.56b, .qo: %ptr.56b, .pi: %ptr.78a} [concrete]\n// CHECK:STDOUT:   %complete_type.c34: <witness> = complete_type_witness %struct_type.po.qo.pi [concrete]\n// CHECK:STDOUT:   %pattern_type.9ae: type = pattern_type %Outer [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.52f: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Outer) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.8b8: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Outer) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.de4: %T.as.DefaultOrUnformed.impl.Op.type.8b8 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.83f: %DefaultOrUnformed.type = facet_value %Outer, (%DefaultOrUnformed.impl_witness.52f) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.a30: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.de4, @T.as.DefaultOrUnformed.impl.Op(%Outer) [concrete]\n// CHECK:STDOUT:   %pattern_type.86a: type = pattern_type %Inner [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.994: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Inner) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.036: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Inner) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.da3: %T.as.DefaultOrUnformed.impl.Op.type.036 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.6ba: %DefaultOrUnformed.type = facet_value %Inner, (%DefaultOrUnformed.impl_witness.994) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.14b: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.da3, @T.as.DefaultOrUnformed.impl.Op(%Inner) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc19 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc18 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cd9: type = pattern_type %ptr.56b [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.565: type = pattern_type %ptr.78a [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.3e0: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%Outer) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.561: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%Outer) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.dc1: %ptr.as.Copy.impl.Op.type.561 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.e2d: %Copy.type = facet_value %ptr.56b, (%Copy.impl_witness.3e0) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.ed5: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.e2d) [concrete]\n// CHECK:STDOUT:   %.be6: type = fn_type_with_self_type %Copy.WithSelf.Op.type.ed5, %Copy.facet.e2d [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn.904: <specific function> = specific_function %ptr.as.Copy.impl.Op.dc1, @ptr.as.Copy.impl.Op(%Outer) [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.044: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%Inner) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.72d: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%Inner) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.8ab: %ptr.as.Copy.impl.Op.type.72d = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.ea8: %Copy.type = facet_value %ptr.78a, (%Copy.impl_witness.044) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.4b9: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.ea8) [concrete]\n// CHECK:STDOUT:   %.b9c: type = fn_type_with_self_type %Copy.WithSelf.Op.type.4b9, %Copy.facet.ea8 [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn.f24: <specific function> = specific_function %ptr.as.Copy.impl.Op.8ab, @ptr.as.Copy.impl.Op(%Inner) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Outer = %Outer.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Outer.decl: type = class_decl @Outer [concrete = constants.%Outer] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.cd9 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.cd9 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %ptr.56b = value_param call_param0\n// CHECK:STDOUT:     %.loc45: type = splice_block %ptr.loc45 [concrete = constants.%ptr.56b] {\n// CHECK:STDOUT:       %Outer.ref.loc45: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:       %ptr.loc45: type = ptr_type %Outer.ref.loc45 [concrete = constants.%ptr.56b]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %ptr.56b = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Outer {\n// CHECK:STDOUT:   %Outer.F.decl: %Outer.F.type = fn_decl @Outer.F [concrete = constants.%Outer.F] {} {}\n// CHECK:STDOUT:   %Inner.decl: type = class_decl @Inner [concrete = constants.%Inner] {} {}\n// CHECK:STDOUT:   %Outer.H.decl: %Outer.H.type = fn_decl @Outer.H [concrete = constants.%Outer.H] {} {}\n// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Outer [concrete = constants.%Outer]\n// CHECK:STDOUT:   %ptr.loc40: type = ptr_type %Self.ref [concrete = constants.%ptr.56b]\n// CHECK:STDOUT:   %.loc40: %Outer.elem.1e5 = field_decl po, element0 [concrete]\n// CHECK:STDOUT:   %Outer.ref: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:   %ptr.loc41: type = ptr_type %Outer.ref [concrete = constants.%ptr.56b]\n// CHECK:STDOUT:   %.loc41: %Outer.elem.1e5 = field_decl qo, element1 [concrete]\n// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, %Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:   %ptr.loc42: type = ptr_type %Inner.ref [concrete = constants.%ptr.78a]\n// CHECK:STDOUT:   %.loc42: %Outer.elem.6db = field_decl pi, element2 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.po.qo.pi [concrete = constants.%complete_type.c34]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Outer\n// CHECK:STDOUT:   .F = %Outer.F.decl\n// CHECK:STDOUT:   .Inner = %Inner.decl\n// CHECK:STDOUT:   .Outer = <poisoned>\n// CHECK:STDOUT:   .H = %Outer.H.decl\n// CHECK:STDOUT:   .po = %.loc40\n// CHECK:STDOUT:   .qo = %.loc41\n// CHECK:STDOUT:   .pi = %.loc42\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Inner {\n// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Inner [concrete = constants.%Inner]\n// CHECK:STDOUT:   %ptr.loc23: type = ptr_type %Self.ref [concrete = constants.%ptr.78a]\n// CHECK:STDOUT:   %.loc23: %Inner.elem.9c1 = field_decl pi, element0 [concrete]\n// CHECK:STDOUT:   %Outer.ref: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:   %ptr.loc24: type = ptr_type %Outer.ref [concrete = constants.%ptr.56b]\n// CHECK:STDOUT:   %.loc24: %Inner.elem.9e0 = field_decl po, element1 [concrete]\n// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, @Outer.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:   %ptr.loc25: type = ptr_type %Inner.ref [concrete = constants.%ptr.78a]\n// CHECK:STDOUT:   %.loc25: %Inner.elem.9c1 = field_decl qi, element2 [concrete]\n// CHECK:STDOUT:   %Inner.G.decl: %Inner.G.type = fn_decl @Inner.G [concrete = constants.%Inner.G] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.pi.po.qi [concrete = constants.%complete_type.486]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Inner\n// CHECK:STDOUT:   .pi = %.loc23\n// CHECK:STDOUT:   .Outer = <poisoned>\n// CHECK:STDOUT:   .po = %.loc24\n// CHECK:STDOUT:   .Inner = <poisoned>\n// CHECK:STDOUT:   .qi = %.loc25\n// CHECK:STDOUT:   .G = %Inner.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Outer.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %o.patt: %pattern_type.9ae = ref_binding_pattern o [concrete]\n// CHECK:STDOUT:     %o.var_patt: %pattern_type.9ae = var_pattern %o.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %o.var: ref %Outer = var %o.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc18: %DefaultOrUnformed.type = facet_value constants.%Outer, (constants.%DefaultOrUnformed.impl_witness.52f) [concrete = constants.%DefaultOrUnformed.facet.83f]\n// CHECK:STDOUT:   %.loc18_24.1: %DefaultOrUnformed.type = converted constants.%Outer, %DefaultOrUnformed.facet.loc18 [concrete = constants.%DefaultOrUnformed.facet.83f]\n// CHECK:STDOUT:   %as_type.loc18: type = facet_access_type %.loc18_24.1 [concrete = constants.%Outer]\n// CHECK:STDOUT:   %.loc18_24.2: type = converted %.loc18_24.1, %as_type.loc18 [concrete = constants.%Outer]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.1: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.de4, @T.as.DefaultOrUnformed.impl.Op(constants.%Outer) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn.a30]\n// CHECK:STDOUT:   %.loc18_5: ref %Outer = splice_block %o.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc18: init %Outer to %.loc18_5 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.1()\n// CHECK:STDOUT:   assign %o.var, %T.as.DefaultOrUnformed.impl.Op.call.loc18\n// CHECK:STDOUT:   %Outer.ref: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:   %o: ref %Outer = ref_binding o, %o.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.86a = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.86a = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %Inner = var %i.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc19: %DefaultOrUnformed.type = facet_value constants.%Inner, (constants.%DefaultOrUnformed.impl_witness.994) [concrete = constants.%DefaultOrUnformed.facet.6ba]\n// CHECK:STDOUT:   %.loc19_24.1: %DefaultOrUnformed.type = converted constants.%Inner, %DefaultOrUnformed.facet.loc19 [concrete = constants.%DefaultOrUnformed.facet.6ba]\n// CHECK:STDOUT:   %as_type.loc19: type = facet_access_type %.loc19_24.1 [concrete = constants.%Inner]\n// CHECK:STDOUT:   %.loc19_24.2: type = converted %.loc19_24.1, %as_type.loc19 [concrete = constants.%Inner]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.2: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.da3, @T.as.DefaultOrUnformed.impl.Op(constants.%Inner) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn.14b]\n// CHECK:STDOUT:   %.loc19_5: ref %Inner = splice_block %i.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc19: init %Inner to %.loc19_5 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.2()\n// CHECK:STDOUT:   assign %i.var, %T.as.DefaultOrUnformed.impl.Op.call.loc19\n// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, @Outer.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:   %i: ref %Inner = ref_binding i, %i.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc19: <bound method> = bound_method %i.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc19: init %empty_tuple.type = call %Destroy.Op.bound.loc19(%i.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc18: <bound method> = bound_method %o.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc18: init %empty_tuple.type = call %Destroy.Op.bound.loc18(%o.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Inner.G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %o.patt: %pattern_type.9ae = ref_binding_pattern o [concrete]\n// CHECK:STDOUT:     %o.var_patt: %pattern_type.9ae = var_pattern %o.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %o.var: ref %Outer = var %o.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc29: %DefaultOrUnformed.type = facet_value constants.%Outer, (constants.%DefaultOrUnformed.impl_witness.52f) [concrete = constants.%DefaultOrUnformed.facet.83f]\n// CHECK:STDOUT:   %.loc29_26.1: %DefaultOrUnformed.type = converted constants.%Outer, %DefaultOrUnformed.facet.loc29 [concrete = constants.%DefaultOrUnformed.facet.83f]\n// CHECK:STDOUT:   %as_type.loc29: type = facet_access_type %.loc29_26.1 [concrete = constants.%Outer]\n// CHECK:STDOUT:   %.loc29_26.2: type = converted %.loc29_26.1, %as_type.loc29 [concrete = constants.%Outer]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.1: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.de4, @T.as.DefaultOrUnformed.impl.Op(constants.%Outer) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn.a30]\n// CHECK:STDOUT:   %.loc29_7: ref %Outer = splice_block %o.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc29: init %Outer to %.loc29_7 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.1()\n// CHECK:STDOUT:   assign %o.var, %T.as.DefaultOrUnformed.impl.Op.call.loc29\n// CHECK:STDOUT:   %Outer.ref: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:   %o: ref %Outer = ref_binding o, %o.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.86a = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.86a = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %Inner = var %i.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc30: %DefaultOrUnformed.type = facet_value constants.%Inner, (constants.%DefaultOrUnformed.impl_witness.994) [concrete = constants.%DefaultOrUnformed.facet.6ba]\n// CHECK:STDOUT:   %.loc30_26.1: %DefaultOrUnformed.type = converted constants.%Inner, %DefaultOrUnformed.facet.loc30 [concrete = constants.%DefaultOrUnformed.facet.6ba]\n// CHECK:STDOUT:   %as_type.loc30: type = facet_access_type %.loc30_26.1 [concrete = constants.%Inner]\n// CHECK:STDOUT:   %.loc30_26.2: type = converted %.loc30_26.1, %as_type.loc30 [concrete = constants.%Inner]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.2: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.da3, @T.as.DefaultOrUnformed.impl.Op(constants.%Inner) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn.14b]\n// CHECK:STDOUT:   %.loc30_7: ref %Inner = splice_block %i.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc30: init %Inner to %.loc30_7 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.2()\n// CHECK:STDOUT:   assign %i.var, %T.as.DefaultOrUnformed.impl.Op.call.loc30\n// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, @Outer.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:   %i: ref %Inner = ref_binding i, %i.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc30: <bound method> = bound_method %i.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc30: init %empty_tuple.type = call %Destroy.Op.bound.loc30(%i.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc29: <bound method> = bound_method %o.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc29: init %empty_tuple.type = call %Destroy.Op.bound.loc29(%o.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Outer.H() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %o.patt: %pattern_type.9ae = ref_binding_pattern o [concrete]\n// CHECK:STDOUT:     %o.var_patt: %pattern_type.9ae = var_pattern %o.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %o.var: ref %Outer = var %o.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc36: %DefaultOrUnformed.type = facet_value constants.%Outer, (constants.%DefaultOrUnformed.impl_witness.52f) [concrete = constants.%DefaultOrUnformed.facet.83f]\n// CHECK:STDOUT:   %.loc36_24.1: %DefaultOrUnformed.type = converted constants.%Outer, %DefaultOrUnformed.facet.loc36 [concrete = constants.%DefaultOrUnformed.facet.83f]\n// CHECK:STDOUT:   %as_type.loc36: type = facet_access_type %.loc36_24.1 [concrete = constants.%Outer]\n// CHECK:STDOUT:   %.loc36_24.2: type = converted %.loc36_24.1, %as_type.loc36 [concrete = constants.%Outer]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.1: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.de4, @T.as.DefaultOrUnformed.impl.Op(constants.%Outer) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn.a30]\n// CHECK:STDOUT:   %.loc36_5: ref %Outer = splice_block %o.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc36: init %Outer to %.loc36_5 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.1()\n// CHECK:STDOUT:   assign %o.var, %T.as.DefaultOrUnformed.impl.Op.call.loc36\n// CHECK:STDOUT:   %Outer.ref: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:   %o: ref %Outer = ref_binding o, %o.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.86a = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.86a = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %Inner = var %i.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc37: %DefaultOrUnformed.type = facet_value constants.%Inner, (constants.%DefaultOrUnformed.impl_witness.994) [concrete = constants.%DefaultOrUnformed.facet.6ba]\n// CHECK:STDOUT:   %.loc37_24.1: %DefaultOrUnformed.type = converted constants.%Inner, %DefaultOrUnformed.facet.loc37 [concrete = constants.%DefaultOrUnformed.facet.6ba]\n// CHECK:STDOUT:   %as_type.loc37: type = facet_access_type %.loc37_24.1 [concrete = constants.%Inner]\n// CHECK:STDOUT:   %.loc37_24.2: type = converted %.loc37_24.1, %as_type.loc37 [concrete = constants.%Inner]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn.2: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.da3, @T.as.DefaultOrUnformed.impl.Op(constants.%Inner) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn.14b]\n// CHECK:STDOUT:   %.loc37_5: ref %Inner = splice_block %i.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call.loc37: init %Inner to %.loc37_5 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn.2()\n// CHECK:STDOUT:   assign %i.var, %T.as.DefaultOrUnformed.impl.Op.call.loc37\n// CHECK:STDOUT:   %Inner.ref: type = name_ref Inner, @Outer.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:   %i: ref %Inner = ref_binding i, %i.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc37: <bound method> = bound_method %i.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc37: init %empty_tuple.type = call %Destroy.Op.bound.loc37(%i.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc36: <bound method> = bound_method %o.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc36: init %empty_tuple.type = call %Destroy.Op.bound.loc36(%o.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc19(%self.param: ref %Inner) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc18(%self.param: ref %Outer) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %ptr.56b) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.565 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.ref.loc46: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %.loc46_26: ref %Outer = deref %a.ref.loc46\n// CHECK:STDOUT:   %pi.ref.loc46: %Outer.elem.6db = name_ref pi, @Outer.%.loc42 [concrete = @Outer.%.loc42]\n// CHECK:STDOUT:   %.loc46_29.1: ref %ptr.78a = class_element_access %.loc46_26, element2\n// CHECK:STDOUT:   %.loc46_21: type = splice_block %ptr.loc46 [concrete = constants.%ptr.78a] {\n// CHECK:STDOUT:     %Outer.ref.loc46: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:     %Inner.ref: type = name_ref Inner, @Outer.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:     %ptr.loc46: type = ptr_type %Inner.ref [concrete = constants.%ptr.78a]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc46_29.2: %ptr.78a = acquire_value %.loc46_29.1\n// CHECK:STDOUT:   %b: %ptr.78a = value_binding b, %.loc46_29.2\n// CHECK:STDOUT:   %a.ref.loc48_3: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %.loc48_4.1: ref %Outer = deref %a.ref.loc48_3\n// CHECK:STDOUT:   %po.ref.loc48: %Outer.elem.1e5 = name_ref po, @Outer.%.loc40 [concrete = @Outer.%.loc40]\n// CHECK:STDOUT:   %.loc48_4.2: ref %ptr.56b = class_element_access %.loc48_4.1, element0\n// CHECK:STDOUT:   %a.ref.loc48_11: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %impl.elem0.loc48: %.be6 = impl_witness_access constants.%Copy.impl_witness.3e0, element0 [concrete = constants.%ptr.as.Copy.impl.Op.dc1]\n// CHECK:STDOUT:   %bound_method.loc48_11.1: <bound method> = bound_method %a.ref.loc48_11, %impl.elem0.loc48\n// CHECK:STDOUT:   %specific_fn.loc48: <specific function> = specific_function %impl.elem0.loc48, @ptr.as.Copy.impl.Op(constants.%Outer) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.904]\n// CHECK:STDOUT:   %bound_method.loc48_11.2: <bound method> = bound_method %a.ref.loc48_11, %specific_fn.loc48\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call.loc48: init %ptr.56b = call %bound_method.loc48_11.2(%a.ref.loc48_11)\n// CHECK:STDOUT:   assign %.loc48_4.2, %ptr.as.Copy.impl.Op.call.loc48\n// CHECK:STDOUT:   %a.ref.loc49_3: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %.loc49_4.1: ref %Outer = deref %a.ref.loc49_3\n// CHECK:STDOUT:   %qo.ref: %Outer.elem.1e5 = name_ref qo, @Outer.%.loc41 [concrete = @Outer.%.loc41]\n// CHECK:STDOUT:   %.loc49_4.2: ref %ptr.56b = class_element_access %.loc49_4.1, element1\n// CHECK:STDOUT:   %a.ref.loc49_11: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %impl.elem0.loc49: %.be6 = impl_witness_access constants.%Copy.impl_witness.3e0, element0 [concrete = constants.%ptr.as.Copy.impl.Op.dc1]\n// CHECK:STDOUT:   %bound_method.loc49_11.1: <bound method> = bound_method %a.ref.loc49_11, %impl.elem0.loc49\n// CHECK:STDOUT:   %specific_fn.loc49: <specific function> = specific_function %impl.elem0.loc49, @ptr.as.Copy.impl.Op(constants.%Outer) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.904]\n// CHECK:STDOUT:   %bound_method.loc49_11.2: <bound method> = bound_method %a.ref.loc49_11, %specific_fn.loc49\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call.loc49: init %ptr.56b = call %bound_method.loc49_11.2(%a.ref.loc49_11)\n// CHECK:STDOUT:   assign %.loc49_4.2, %ptr.as.Copy.impl.Op.call.loc49\n// CHECK:STDOUT:   %a.ref.loc50_3: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %.loc50_4.1: ref %Outer = deref %a.ref.loc50_3\n// CHECK:STDOUT:   %pi.ref.loc50_4: %Outer.elem.6db = name_ref pi, @Outer.%.loc42 [concrete = @Outer.%.loc42]\n// CHECK:STDOUT:   %.loc50_4.2: ref %ptr.78a = class_element_access %.loc50_4.1, element2\n// CHECK:STDOUT:   %a.ref.loc50_11: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %.loc50_12.1: ref %Outer = deref %a.ref.loc50_11\n// CHECK:STDOUT:   %pi.ref.loc50_12: %Outer.elem.6db = name_ref pi, @Outer.%.loc42 [concrete = @Outer.%.loc42]\n// CHECK:STDOUT:   %.loc50_12.2: ref %ptr.78a = class_element_access %.loc50_12.1, element2\n// CHECK:STDOUT:   %.loc50_12.3: %ptr.78a = acquire_value %.loc50_12.2\n// CHECK:STDOUT:   %impl.elem0.loc50: %.b9c = impl_witness_access constants.%Copy.impl_witness.044, element0 [concrete = constants.%ptr.as.Copy.impl.Op.8ab]\n// CHECK:STDOUT:   %bound_method.loc50_12.1: <bound method> = bound_method %.loc50_12.3, %impl.elem0.loc50\n// CHECK:STDOUT:   %specific_fn.loc50: <specific function> = specific_function %impl.elem0.loc50, @ptr.as.Copy.impl.Op(constants.%Inner) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.f24]\n// CHECK:STDOUT:   %bound_method.loc50_12.2: <bound method> = bound_method %.loc50_12.3, %specific_fn.loc50\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call.loc50: init %ptr.78a = call %bound_method.loc50_12.2(%.loc50_12.3)\n// CHECK:STDOUT:   assign %.loc50_4.2, %ptr.as.Copy.impl.Op.call.loc50\n// CHECK:STDOUT:   %b.ref.loc51: %ptr.78a = name_ref b, %b\n// CHECK:STDOUT:   %.loc51_4.1: ref %Inner = deref %b.ref.loc51\n// CHECK:STDOUT:   %po.ref.loc51: %Inner.elem.9e0 = name_ref po, @Inner.%.loc24 [concrete = @Inner.%.loc24]\n// CHECK:STDOUT:   %.loc51_4.2: ref %ptr.56b = class_element_access %.loc51_4.1, element1\n// CHECK:STDOUT:   %a.ref.loc51: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %impl.elem0.loc51: %.be6 = impl_witness_access constants.%Copy.impl_witness.3e0, element0 [concrete = constants.%ptr.as.Copy.impl.Op.dc1]\n// CHECK:STDOUT:   %bound_method.loc51_11.1: <bound method> = bound_method %a.ref.loc51, %impl.elem0.loc51\n// CHECK:STDOUT:   %specific_fn.loc51: <specific function> = specific_function %impl.elem0.loc51, @ptr.as.Copy.impl.Op(constants.%Outer) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.904]\n// CHECK:STDOUT:   %bound_method.loc51_11.2: <bound method> = bound_method %a.ref.loc51, %specific_fn.loc51\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call.loc51: init %ptr.56b = call %bound_method.loc51_11.2(%a.ref.loc51)\n// CHECK:STDOUT:   assign %.loc51_4.2, %ptr.as.Copy.impl.Op.call.loc51\n// CHECK:STDOUT:   %b.ref.loc52: %ptr.78a = name_ref b, %b\n// CHECK:STDOUT:   %.loc52_4.1: ref %Inner = deref %b.ref.loc52\n// CHECK:STDOUT:   %pi.ref.loc52_4: %Inner.elem.9c1 = name_ref pi, @Inner.%.loc23 [concrete = @Inner.%.loc23]\n// CHECK:STDOUT:   %.loc52_4.2: ref %ptr.78a = class_element_access %.loc52_4.1, element0\n// CHECK:STDOUT:   %a.ref.loc52: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %.loc52_12.1: ref %Outer = deref %a.ref.loc52\n// CHECK:STDOUT:   %pi.ref.loc52_12: %Outer.elem.6db = name_ref pi, @Outer.%.loc42 [concrete = @Outer.%.loc42]\n// CHECK:STDOUT:   %.loc52_12.2: ref %ptr.78a = class_element_access %.loc52_12.1, element2\n// CHECK:STDOUT:   %.loc52_12.3: %ptr.78a = acquire_value %.loc52_12.2\n// CHECK:STDOUT:   %impl.elem0.loc52: %.b9c = impl_witness_access constants.%Copy.impl_witness.044, element0 [concrete = constants.%ptr.as.Copy.impl.Op.8ab]\n// CHECK:STDOUT:   %bound_method.loc52_12.1: <bound method> = bound_method %.loc52_12.3, %impl.elem0.loc52\n// CHECK:STDOUT:   %specific_fn.loc52: <specific function> = specific_function %impl.elem0.loc52, @ptr.as.Copy.impl.Op(constants.%Inner) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.f24]\n// CHECK:STDOUT:   %bound_method.loc52_12.2: <bound method> = bound_method %.loc52_12.3, %specific_fn.loc52\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call.loc52: init %ptr.78a = call %bound_method.loc52_12.2(%.loc52_12.3)\n// CHECK:STDOUT:   assign %.loc52_4.2, %ptr.as.Copy.impl.Op.call.loc52\n// CHECK:STDOUT:   %b.ref.loc53: %ptr.78a = name_ref b, %b\n// CHECK:STDOUT:   %.loc53_4.1: ref %Inner = deref %b.ref.loc53\n// CHECK:STDOUT:   %qi.ref: %Inner.elem.9c1 = name_ref qi, @Inner.%.loc25 [concrete = @Inner.%.loc25]\n// CHECK:STDOUT:   %.loc53_4.2: ref %ptr.78a = class_element_access %.loc53_4.1, element2\n// CHECK:STDOUT:   %a.ref.loc53: %ptr.56b = name_ref a, %a\n// CHECK:STDOUT:   %.loc53_12.1: ref %Outer = deref %a.ref.loc53\n// CHECK:STDOUT:   %pi.ref.loc53: %Outer.elem.6db = name_ref pi, @Outer.%.loc42 [concrete = @Outer.%.loc42]\n// CHECK:STDOUT:   %.loc53_12.2: ref %ptr.78a = class_element_access %.loc53_12.1, element2\n// CHECK:STDOUT:   %.loc53_12.3: %ptr.78a = acquire_value %.loc53_12.2\n// CHECK:STDOUT:   %impl.elem0.loc53: %.b9c = impl_witness_access constants.%Copy.impl_witness.044, element0 [concrete = constants.%ptr.as.Copy.impl.Op.8ab]\n// CHECK:STDOUT:   %bound_method.loc53_12.1: <bound method> = bound_method %.loc53_12.3, %impl.elem0.loc53\n// CHECK:STDOUT:   %specific_fn.loc53: <specific function> = specific_function %impl.elem0.loc53, @ptr.as.Copy.impl.Op(constants.%Inner) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.f24]\n// CHECK:STDOUT:   %bound_method.loc53_12.2: <bound method> = bound_method %.loc53_12.3, %specific_fn.loc53\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call.loc53: init %ptr.78a = call %bound_method.loc53_12.2(%.loc53_12.3)\n// CHECK:STDOUT:   assign %.loc53_4.2, %ptr.as.Copy.impl.Op.call.loc53\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/nested_name.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/nested_name.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/nested_name.carbon\n\nclass Outer {\n  class Inner {\n    var n: i32;\n  }\n}\n\nfn F(oi: Outer.Inner) -> i32 {\n  return oi.n;\n}\n\nfn G(o: Outer) {\n  var unused i: o.Inner;\n}\n\n// CHECK:STDOUT: --- nested_name.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Outer: type = class_type @Outer [concrete]\n// CHECK:STDOUT:   %Inner: type = class_type @Inner [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Inner.elem: type = unbound_element_type %Inner, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.86a: type = pattern_type %Inner [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.9ae: type = pattern_type %Outer [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.994: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Inner) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.036: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Inner) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.da3: %T.as.DefaultOrUnformed.impl.Op.type.036 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %Inner, (%DefaultOrUnformed.impl_witness.994) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.da3, @T.as.DefaultOrUnformed.impl.Op(%Inner) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Outer = %Outer.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Outer.decl: type = class_decl @Outer [concrete = constants.%Outer] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %oi.patt: %pattern_type.86a = value_binding_pattern oi [concrete]\n// CHECK:STDOUT:     %oi.param_patt: %pattern_type.86a = value_param_pattern %oi.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc21_26: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %oi.param: %Inner = value_param call_param0\n// CHECK:STDOUT:     %.loc21_15: type = splice_block %Inner.ref [concrete = constants.%Inner] {\n// CHECK:STDOUT:       %Outer.ref: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:       %Inner.ref: type = name_ref Inner, @Outer.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %oi: %Inner = value_binding oi, %oi.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %o.patt: %pattern_type.9ae = value_binding_pattern o [concrete]\n// CHECK:STDOUT:     %o.param_patt: %pattern_type.9ae = value_param_pattern %o.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %o.param: %Outer = value_param call_param0\n// CHECK:STDOUT:     %Outer.ref: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]\n// CHECK:STDOUT:     %o: %Outer = value_binding o, %o.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Outer {\n// CHECK:STDOUT:   %Inner.decl: type = class_decl @Inner [concrete = constants.%Inner] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Outer\n// CHECK:STDOUT:   .Inner = %Inner.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Inner {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc17: %Inner.elem = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Inner\n// CHECK:STDOUT:   .n = %.loc17\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%oi.param: %Inner) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %oi.ref: %Inner = name_ref oi, %oi\n// CHECK:STDOUT:   %n.ref: %Inner.elem = name_ref n, @Inner.%.loc17 [concrete = @Inner.%.loc17]\n// CHECK:STDOUT:   %.loc22_12.1: ref %i32 = class_element_access %oi.ref, element0\n// CHECK:STDOUT:   %.loc22_12.2: %i32 = acquire_value %.loc22_12.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc22_12.1: <bound method> = bound_method %.loc22_12.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc22_12.2: <bound method> = bound_method %.loc22_12.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc22_12.2(%.loc22_12.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%o.param: %Outer) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.86a = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.86a = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %Inner = var %i.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%Inner, (constants.%DefaultOrUnformed.impl_witness.994) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc26_24.1: %DefaultOrUnformed.type = converted constants.%Inner, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc26_24.1 [concrete = constants.%Inner]\n// CHECK:STDOUT:   %.loc26_24.2: type = converted %.loc26_24.1, %as_type [concrete = constants.%Inner]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.da3, @T.as.DefaultOrUnformed.impl.Op(constants.%Inner) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc26_3: ref %Inner = splice_block %i.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %Inner to %.loc26_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %i.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %.loc26_18: type = splice_block %Inner.ref [concrete = constants.%Inner] {\n// CHECK:STDOUT:     %o.ref: %Outer = name_ref o, %o\n// CHECK:STDOUT:     %Inner.ref: type = name_ref Inner, @Outer.%Inner.decl [concrete = constants.%Inner]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i: ref %Inner = ref_binding i, %i.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %i.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%i.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Inner) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/no_definition_in_impl_file.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/no_definition_in_impl_file.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/no_definition_in_impl_file.carbon\n\n// --- decl_in_api_definition_in_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A;\n\n// --- decl_in_api_definition_in_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nclass A;\n\nclass A {}\n\n// --- use_decl_in_api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// --- use_decl_in_api.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nimport library \"decl_in_api_definition_in_impl\";\n\n// --- decl_only_in_api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass B;\n\n// --- decl_only_in_api.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// --- decl_in_api_decl_in_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n// --- fail_decl_in_api_decl_in_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]\n// CHECK:STDERR: class C;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nclass C;\n\n// --- decl_only_in_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// --- fail_decl_only_in_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_decl_only_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]\n// CHECK:STDERR: class D;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nclass D;\n\n// CHECK:STDOUT: --- decl_in_api_definition_in_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_in_api_definition_in_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_46.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_46.2 = import <none>\n// CHECK:STDOUT:   %A.decl.loc4: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %A.decl.loc6: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_decl_in_api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_decl_in_api.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A = import_ref Main//decl_in_api_definition_in_impl, A, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_31.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_31.2 = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_only_in_api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_only_in_api.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.B = import_ref Main//decl_only_in_api, B, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_32.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_32.2 = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_in_api_decl_in_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_decl_in_api_decl_in_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_40.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_40.2 = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_only_in_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_decl_only_in_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_33.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_33.2 = import <none>\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/partial/init.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/partial/init.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/partial/init.carbon\n\n// --- base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base {\n  fn Make() -> partial Self {\n    return {};\n  }\n}\n\nclass Derived {\n  extend base: Base;\n  fn Make() -> Self {\n    //@dump-sem-ir-begin\n    return {.base = Base.Make()};\n    //@dump-sem-ir-end\n  }\n}\n\n// CHECK:STDOUT: --- base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %.7a5: type = partial_type %Base [concrete]\n// CHECK:STDOUT:   %Base.Make.type: type = fn_type @Base.Make [concrete]\n// CHECK:STDOUT:   %Base.Make: %Base.Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %struct_type.base.cad: type = struct_type {.base: %.7a5} [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc11\n// CHECK:STDOUT:   .Make = %Derived.Make.decl\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Derived.Make() -> out %return.param: %Derived {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %Make.ref: %Base.Make.type = name_ref Make, @Base.%Base.Make.decl [concrete = constants.%Base.Make]\n// CHECK:STDOUT:   %.loc14_32.1: ref %.7a5 = class_element_access %return.param, element0\n// CHECK:STDOUT:   %Base.Make.call: init %.7a5 to %.loc14_32.1 = call %Make.ref()\n// CHECK:STDOUT:   %.loc14_32.2: %struct_type.base.cad = struct_literal (%Base.Make.call)\n// CHECK:STDOUT:   %.loc14_32.3: init %Base = as_compatible %Base.Make.call\n// CHECK:STDOUT:   %.loc14_32.4: init %Derived to %return.param = class_init (%.loc14_32.3)\n// CHECK:STDOUT:   %.loc14_33: init %Derived = converted %.loc14_32.2, %.loc14_32.4\n// CHECK:STDOUT:   return %.loc14_33 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/partial/qualifier.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/partial/qualifier.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/partial/qualifier.carbon\n\n// --- base.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nbase class C { }\n\n//@dump-sem-ir-begin\nfn A(p: partial C);\n//@dump-sem-ir-end\n\n// --- abstract.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class C { }\n\n//@dump-sem-ir-begin\nfn A(p: partial C);\n//@dump-sem-ir-end\n\n// --- abstract_var.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class C { }\n\n//@dump-sem-ir-begin\nfn A(var p: partial C);\n//@dump-sem-ir-end\n\n// --- fail_partial_nondynamic.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C { }\n\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_partial_nondynamic.carbon:[[@LINE+4]]:9: error: `partial` applied to final type `C` [PartialOnFinal]\n// CHECK:STDERR: fn G(p: partial C);\n// CHECK:STDERR:         ^~~~~~~~~\n// CHECK:STDERR:\nfn G(p: partial C);\n//@dump-sem-ir-end\n\n// --- fail_partial_final.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base { }\nclass Derived {\n  extend base: Base;\n}\n\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_partial_final.carbon:[[@LINE+4]]:9: error: `partial` applied to final type `Derived` [PartialOnFinal]\n// CHECK:STDERR: fn G(p: partial Derived);\n// CHECK:STDERR:         ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn G(p: partial Derived);\n//@dump-sem-ir-end\n\n// --- fail_partial_decl.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n// TODO: This diagnostic could be more specific - the type might be non-final,\n// but since we only have a declaration, we don't know.\n//@dump-sem-ir-begin\n// applied to final type `C` [PartialOnFinal] CHECK:STDERR: fn G(p: partial C);\n// CHECK:STDERR: fail_partial_decl.carbon:[[@LINE+4]]:9: error: `partial` applied to final type `C` [PartialOnFinal]\n// CHECK:STDERR: fn G(p: partial C);\n// CHECK:STDERR:         ^~~~~~~~~\n// CHECK:STDERR:\nfn G(p: partial C);\n//@dump-sem-ir-end\n\n// --- fail_partial_tuple.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_partial_tuple.carbon:[[@LINE+4]]:9: error: `partial` applied to final type `(C, C)` [PartialOnFinal]\n// CHECK:STDERR: fn G(p: partial (C, C));\n// CHECK:STDERR:         ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn G(p: partial (C, C));\n//@dump-sem-ir-end\n\n// --- fail_partial_struct.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_partial_struct.carbon:[[@LINE+4]]:9: error: `partial` applied to final type `{.x: C}` [PartialOnFinal]\n// CHECK:STDERR: fn G(p: partial {.x: C});\n// CHECK:STDERR:         ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn G(p: partial {.x: C});\n//@dump-sem-ir-end\n\n// --- fail_duplicate.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nbase class C { }\n\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_duplicate.carbon:[[@LINE+4]]:9: error: `partial` applied to final type `partial C` [PartialOnFinal]\n// CHECK:STDERR: fn F(p: partial (partial C));\n// CHECK:STDERR:         ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(p: partial (partial C));\n//@dump-sem-ir-end\n\n// --- fail_convert_to_nonpartial.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nbase class C { }\n\nfn G(p: partial C*) -> C* {\n  // CHECK:STDERR: fail_convert_to_nonpartial.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `partial C*` to `C*` [ConversionFailure]\n  // CHECK:STDERR:   return p;\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_convert_to_nonpartial.carbon:[[@LINE+4]]:3: note: type `partial C*` does not implement interface `Core.ImplicitAs(C*)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return p;\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR:\n  return p;\n}\n\n// --- fail_derive_from_partial.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nbase class C { }\n\nclass Derived {\n  // CHECK:STDERR: fail_derive_from_partial.carbon:[[@LINE+4]]:16: error: deriving from final type `partial C`; base type must be an `abstract` or `base` class [BaseIsFinal]\n  // CHECK:STDERR:   extend base: partial C;\n  // CHECK:STDERR:                ^~~~~~~~~\n  // CHECK:STDERR:\n  extend base: partial C;\n}\n\n// --- fail_todo_partial_template_dependent.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: This should be accepted because `T` might be final once we know what it\n// is.\n\n// CHECK:STDERR: fail_todo_partial_template_dependent.carbon:[[@LINE+4]]:28: error: `partial` applied to final type `T` [PartialOnFinal]\n// CHECK:STDERR: fn G[template T:! type](p: partial T*);\n// CHECK:STDERR:                            ^~~~~~~~~\n// CHECK:STDERR:\nfn G[template T:! type](p: partial T*);\n\n// --- fail_partial_generic.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: Maybe rephrase this to use some common/generic phrasing to refer to the\n// generic type and its requirements, as distinct from the concrete type that\n// might be used here in any specific.\n\n// CHECK:STDERR: fail_partial_generic.carbon:[[@LINE+4]]:19: error: `partial` applied to final type `T` [PartialOnFinal]\n// CHECK:STDERR: fn F[T:! type](p: partial T*);\n// CHECK:STDERR:                   ^~~~~~~~~\n// CHECK:STDERR:\nfn F[T:! type](p: partial T*);\n\n// CHECK:STDOUT: --- base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %.e97: type = partial_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %.e97 [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %.e97 = value_param call_param0\n// CHECK:STDOUT:     %.loc6_9.1: type = splice_block %.loc6_9.2 [concrete = constants.%.e97] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %.loc6_9.2: type = partial_type %C.ref [concrete = constants.%.e97]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %.e97 = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A(%p.param: %.e97);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- abstract.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %.e97: type = partial_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %.e97 [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %.e97 = value_param call_param0\n// CHECK:STDOUT:     %.loc6_9.1: type = splice_block %.loc6_9.2 [concrete = constants.%.e97] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %.loc6_9.2: type = partial_type %C.ref [concrete = constants.%.e97]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %.e97 = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A(%p.param: %.e97);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- abstract_var.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %.e97: type = partial_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %.e97 [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = ref_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = var_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %p.var_patt: %pattern_type = var_pattern %p.param_patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: ref %.e97 = ref_param call_param0\n// CHECK:STDOUT:     %.loc6_13.1: type = splice_block %.loc6_13.2 [concrete = constants.%.e97] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %.loc6_13.2: type = partial_type %C.ref [concrete = constants.%.e97]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: ref %.e97 = ref_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A(%p.param: ref %.e97);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_partial_nondynamic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %.e97: type = partial_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %.e97 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %.e97 = value_param call_param0\n// CHECK:STDOUT:     %.loc10_9.1: type = splice_block %.loc10_9.2 [concrete = constants.%.e97] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %.loc10_9.2: type = partial_type %C.ref [concrete = constants.%.e97]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %.e97 = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %.e97);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_partial_final.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %.d37: type = partial_type %Derived [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %.d37 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %.d37 = value_param call_param0\n// CHECK:STDOUT:     %.loc13_9.1: type = splice_block %.loc13_9.2 [concrete = constants.%.d37] {\n// CHECK:STDOUT:       %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:       %.loc13_9.2: type = partial_type %Derived.ref [concrete = constants.%.d37]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %.d37 = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %.d37);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_partial_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %.e97: type = partial_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %.e97 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %.e97 = value_param call_param0\n// CHECK:STDOUT:     %.loc13_9.1: type = splice_block %.loc13_9.2 [concrete = constants.%.e97] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %.loc13_9.2: type = partial_type %C.ref [concrete = constants.%.e97]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %.e97 = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %.e97);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_partial_tuple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%C, %C) [concrete]\n// CHECK:STDOUT:   %tuple.type.d23: type = tuple_type (%C, %C) [concrete]\n// CHECK:STDOUT:   %.42f: type = partial_type %tuple.type.d23 [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %.42f [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %.42f = value_param call_param0\n// CHECK:STDOUT:     %.loc10_9.1: type = splice_block %.loc10_9.3 [concrete = constants.%.42f] {\n// CHECK:STDOUT:       %C.ref.loc10_18: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %C.ref.loc10_21: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %.loc10_22: %tuple.type.24b = tuple_literal (%C.ref.loc10_18, %C.ref.loc10_21) [concrete = constants.%tuple]\n// CHECK:STDOUT:       %.loc10_9.2: type = converted %.loc10_22, constants.%tuple.type.d23 [concrete = constants.%tuple.type.d23]\n// CHECK:STDOUT:       %.loc10_9.3: type = partial_type %.loc10_9.2 [concrete = constants.%.42f]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %.42f = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %.42f);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_partial_struct.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: %C} [concrete]\n// CHECK:STDOUT:   %.be9: type = partial_type %struct_type.x [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %.be9 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %.be9 = value_param call_param0\n// CHECK:STDOUT:     %.loc10_9.1: type = splice_block %.loc10_9.2 [concrete = constants.%.be9] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %struct_type.x: type = struct_type {.x: %C} [concrete = constants.%struct_type.x]\n// CHECK:STDOUT:       %.loc10_9.2: type = partial_type %struct_type.x [concrete = constants.%.be9]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %.be9 = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %.be9);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_duplicate.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %.e97: type = partial_type %C [concrete]\n// CHECK:STDOUT:   %.d45: type = partial_type %.e97 [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %.d45 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %p.patt: %pattern_type = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %.d45 = value_param call_param0\n// CHECK:STDOUT:     %.loc10_9.1: type = splice_block %.loc10_9.2 [concrete = constants.%.d45] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %.loc10_18: type = partial_type %C.ref [concrete = constants.%.e97]\n// CHECK:STDOUT:       %.loc10_9.2: type = partial_type %.loc10_18 [concrete = constants.%.d45]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %.d45 = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%p.param: %.d45);\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/redeclaration.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/redeclaration.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/redeclaration.carbon\n\nclass Class;\n\nclass Class {\n  fn F[self: Self](b: ());\n}\n\nfn Class.F[unused self: Self](unused b: ()) {}\n\n// CHECK:STDOUT: --- redeclaration.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl.loc15\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl.loc15: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Class.decl.loc17: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.cb1 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.cb1 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param.loc21: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc21: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc21: %Class = value_binding self, %self.param.loc21\n// CHECK:STDOUT:     %b.param.loc21: %empty_tuple.type = value_param call_param1\n// CHECK:STDOUT:     %.loc21_42.1: type = splice_block %.loc21_42.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc21_42.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc21_42.3: type = converted %.loc21_42.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b.loc21: %empty_tuple.type = value_binding b, %b.param.loc21\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.cb1 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.cb1 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param.loc18: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc18: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc18: %Class = value_binding self, %self.param.loc18\n// CHECK:STDOUT:     %b.param.loc18: %empty_tuple.type = value_param call_param1\n// CHECK:STDOUT:     %.loc18_24.1: type = splice_block %.loc18_24.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc18_24.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc18_24.3: type = converted %.loc18_24.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b.loc18: %empty_tuple.type = value_binding b, %b.param.loc18\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F(%self.param.loc21: %Class, %b.param.loc21: %empty_tuple.type) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/redeclaration_introducer.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/redeclaration_introducer.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/redeclaration_introducer.carbon\n\nclass A;\nclass B;\nclass C;\n\nclass A {}\nbase class B {}\nabstract class C {}\n\n// CHECK:STDOUT: --- redeclaration_introducer.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl.loc15\n// CHECK:STDOUT:     .B = %B.decl.loc16\n// CHECK:STDOUT:     .C = %C.decl.loc17\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl.loc15: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl.loc16: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %C.decl.loc17: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %A.decl.loc19: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl.loc20: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %C.decl.loc21: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/reenter_scope.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/reenter_scope.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/reenter_scope.carbon\n\nclass Class {\n  fn F() -> i32;\n  fn G() -> i32;\n}\n\nfn Class.F() -> i32 {\n  Self.G();\n  return G();\n}\n\n// CHECK:STDOUT: --- reenter_scope.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G [concrete]\n// CHECK:STDOUT:   %Class.G: %Class.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc20: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc20: Core.Form = init_form %i32.loc20 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param.loc20: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return.loc20: ref %i32 = return_slot %return.param.loc20\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32.loc16 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param.loc16: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return.loc16: ref %i32 = return_slot %return.param.loc16\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc17: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT:   .G = %Class.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F() -> out %return.param.loc20: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:   %G.ref.loc21: %Class.G.type = name_ref G, @Class.%Class.G.decl [concrete = constants.%Class.G]\n// CHECK:STDOUT:   %Class.G.call.loc21: init %i32 = call %G.ref.loc21()\n// CHECK:STDOUT:   %G.ref.loc22: %Class.G.type = name_ref G, @Class.%Class.G.decl [concrete = constants.%Class.G]\n// CHECK:STDOUT:   %Class.G.call.loc22: init %i32 = call %G.ref.loc22()\n// CHECK:STDOUT:   return %Class.G.call.loc22\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.G() -> out %return.param: %i32;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/reorder.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/reorder.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/reorder.carbon\n\nclass Class {\n  fn G() -> i32 {\n    return Class.F();\n  }\n\n  fn F() -> i32 {\n    return 1;\n  }\n}\n\n// CHECK:STDOUT: --- reorder.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G [concrete]\n// CHECK:STDOUT:   %Class.G: %Class.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc20: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .G = %Class.G.decl\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT:   .Class = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %F.ref()\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc21_13.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc21_13.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc21_13.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc21: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   return %.loc21\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/reorder_qualified.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/reorder_qualified.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/reorder_qualified.carbon\n\nclass A {\n  class B {\n    class C;\n\n    fn BF();\n    var b: i32;\n  }\n\n  class B.C {\n    class D {\n      fn F();\n\n      fn DF();\n      var d: i32;\n    }\n\n    fn D.DF() {\n      // A, B, C, and D are complete here.\n      var unused a: A = {.a = 1};\n      var unused b: B = {.b = 2};\n      var unused c: C = {.c = 3};\n      var unused d: D = {.d = 4};\n\n      // Unqualified lookup looks in all of them.\n      AF();\n      BF();\n      CF();\n      DF();\n    }\n\n    fn CF();\n    var c: i32;\n  }\n\n  fn AF();\n  var a: i32;\n}\n\n// CHECK:STDOUT: --- reorder_qualified.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %B.BF.type: type = fn_type @B.BF [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %B.BF: %B.BF.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %B.elem: type = unbound_element_type %B, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.b.0a3: type = struct_type {.b: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.ba8: <witness> = complete_type_witness %struct_type.b.0a3 [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %D.F.type: type = fn_type @D.F [concrete]\n// CHECK:STDOUT:   %D.F: %D.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D.DF.type: type = fn_type @D.DF [concrete]\n// CHECK:STDOUT:   %D.DF: %D.DF.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D.elem: type = unbound_element_type %D, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.d.b7b: type = struct_type {.d: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.860: <witness> = complete_type_witness %struct_type.d.b7b [concrete]\n// CHECK:STDOUT:   %C.CF.type: type = fn_type @C.CF [concrete]\n// CHECK:STDOUT:   %C.CF: %C.CF.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.c.b66: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.836: <witness> = complete_type_witness %struct_type.c.b66 [concrete]\n// CHECK:STDOUT:   %A.AF.type: type = fn_type @A.AF [concrete]\n// CHECK:STDOUT:   %A.AF: %A.AF.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.elem: type = unbound_element_type %A, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.a.ba9: type = struct_type {.a: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.fd7: <witness> = complete_type_witness %struct_type.a.ba9 [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.a.a6c: type = struct_type {.a: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.48c: %struct_type.a.a6c = struct_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %A.val: %A = struct_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %pattern_type.438: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.b.a15: type = struct_type {.b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.26f: %struct_type.b.a15 = struct_value (%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %B.val: %B = struct_value (%int_2.ef8) [concrete]\n// CHECK:STDOUT:   %pattern_type.d99: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %struct_type.c.5b8: type = struct_type {.c: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.d98: %struct_type.c.5b8 = struct_value (%int_3.1ba) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value (%int_3.822) [concrete]\n// CHECK:STDOUT:   %pattern_type.be4: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %struct_type.d.3ea: type = struct_type {.d: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.5a9: %struct_type.d.3ea = struct_value (%int_4.0c1) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.6d7: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_4.940: %i32 = int_value 4 [concrete]\n// CHECK:STDOUT:   %D.val: %D = struct_value (%int_4.940) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc36 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc35 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc34 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.4: type = fn_type @Destroy.Op.loc33 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.4: %Destroy.Op.type.bae255.4 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %A.AF.decl: %A.AF.type = fn_decl @A.AF [concrete = constants.%A.AF] {} {}\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc50: %A.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a.ba9 [concrete = constants.%complete_type.fd7]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT:   .B = %B.decl\n// CHECK:STDOUT:   .AF = %A.AF.decl\n// CHECK:STDOUT:   .a = %.loc50\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %B.BF.decl: %B.BF.type = fn_decl @B.BF [concrete = constants.%B.BF] {} {}\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc20: %B.elem = field_decl b, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.b.0a3 [concrete = constants.%complete_type.ba8]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .C = %C.decl\n// CHECK:STDOUT:   .BF = %B.BF.decl\n// CHECK:STDOUT:   .b = %.loc20\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .B = <poisoned>\n// CHECK:STDOUT:   .AF = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %D.DF.decl: %D.DF.type = fn_decl @D.DF [concrete = constants.%D.DF] {} {}\n// CHECK:STDOUT:   %C.CF.decl: %C.CF.type = fn_decl @C.CF [concrete = constants.%C.CF] {} {}\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc46: %C.elem = field_decl c, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.c.b66 [concrete = constants.%complete_type.836]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .D = %D.decl\n// CHECK:STDOUT:   .CF = %C.CF.decl\n// CHECK:STDOUT:   .c = %.loc46\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .B = <poisoned>\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT:   .AF = <poisoned>\n// CHECK:STDOUT:   .BF = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %D.F.decl: %D.F.type = fn_decl @D.F [concrete = constants.%D.F] {} {}\n// CHECK:STDOUT:   %D.DF.decl: %D.DF.type = fn_decl @D.DF [concrete = constants.%D.DF] {} {}\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc28: %D.elem = field_decl d, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.d.b7b [concrete = constants.%complete_type.860]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT:   .F = %D.F.decl\n// CHECK:STDOUT:   .DF = %D.DF.decl\n// CHECK:STDOUT:   .d = %.loc28\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .B = <poisoned>\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT:   .D = <poisoned>\n// CHECK:STDOUT:   .AF = <poisoned>\n// CHECK:STDOUT:   .BF = <poisoned>\n// CHECK:STDOUT:   .CF = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.BF();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @D.F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @D.DF() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1ab = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.1ab = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %A = var %a.var_patt\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc33_32.1: %struct_type.a.a6c = struct_literal (%int_1) [concrete = constants.%struct.48c]\n// CHECK:STDOUT:   %impl.elem0.loc33: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc33_32.1: <bound method> = bound_method %int_1, %impl.elem0.loc33 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc33: <specific function> = specific_function %impl.elem0.loc33, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc33_32.2: <bound method> = bound_method %int_1, %specific_fn.loc33 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc33: init %i32 = call %bound_method.loc33_32.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc33_32.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc33 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc33_32.3: ref %i32 = class_element_access %a.var, element0\n// CHECK:STDOUT:   %.loc33_32.4: init %i32 to %.loc33_32.3 = in_place_init %.loc33_32.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc33_32.5: init %A to %a.var = class_init (%.loc33_32.4) [concrete = constants.%A.val]\n// CHECK:STDOUT:   %.loc33_7: init %A = converted %.loc33_32.1, %.loc33_32.5 [concrete = constants.%A.val]\n// CHECK:STDOUT:   assign %a.var, %.loc33_7\n// CHECK:STDOUT:   %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %a: ref %A = ref_binding a, %a.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.438 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.438 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %B = var %b.var_patt\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc34_32.1: %struct_type.b.a15 = struct_literal (%int_2) [concrete = constants.%struct.26f]\n// CHECK:STDOUT:   %impl.elem0.loc34: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc34_32.1: <bound method> = bound_method %int_2, %impl.elem0.loc34 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc34: <specific function> = specific_function %impl.elem0.loc34, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc34_32.2: <bound method> = bound_method %int_2, %specific_fn.loc34 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc34: init %i32 = call %bound_method.loc34_32.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc34_32.2: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc34 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc34_32.3: ref %i32 = class_element_access %b.var, element0\n// CHECK:STDOUT:   %.loc34_32.4: init %i32 to %.loc34_32.3 = in_place_init %.loc34_32.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc34_32.5: init %B to %b.var = class_init (%.loc34_32.4) [concrete = constants.%B.val]\n// CHECK:STDOUT:   %.loc34_7: init %B = converted %.loc34_32.1, %.loc34_32.5 [concrete = constants.%B.val]\n// CHECK:STDOUT:   assign %b.var, %.loc34_7\n// CHECK:STDOUT:   %B.ref: type = name_ref B, @A.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %b: ref %B = ref_binding b, %b.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.d99 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.d99 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %.loc35_32.1: %struct_type.c.5b8 = struct_literal (%int_3) [concrete = constants.%struct.d98]\n// CHECK:STDOUT:   %impl.elem0.loc35: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc35_32.1: <bound method> = bound_method %int_3, %impl.elem0.loc35 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:   %specific_fn.loc35: <specific function> = specific_function %impl.elem0.loc35, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc35_32.2: <bound method> = bound_method %int_3, %specific_fn.loc35 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc35: init %i32 = call %bound_method.loc35_32.2(%int_3) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc35_32.2: init %i32 = converted %int_3, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc35 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc35_32.3: ref %i32 = class_element_access %c.var, element0\n// CHECK:STDOUT:   %.loc35_32.4: init %i32 to %.loc35_32.3 = in_place_init %.loc35_32.2 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc35_32.5: init %C to %c.var = class_init (%.loc35_32.4) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc35_7: init %C = converted %.loc35_32.1, %.loc35_32.5 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign %c.var, %.loc35_7\n// CHECK:STDOUT:   %C.ref: type = name_ref C, @B.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.be4 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.be4 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %D = var %d.var_patt\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]\n// CHECK:STDOUT:   %.loc36_32.1: %struct_type.d.3ea = struct_literal (%int_4) [concrete = constants.%struct.5a9]\n// CHECK:STDOUT:   %impl.elem0.loc36: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc36_32.1: <bound method> = bound_method %int_4, %impl.elem0.loc36 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c]\n// CHECK:STDOUT:   %specific_fn.loc36: <specific function> = specific_function %impl.elem0.loc36, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc36_32.2: <bound method> = bound_method %int_4, %specific_fn.loc36 [concrete = constants.%bound_method.6d7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc36: init %i32 = call %bound_method.loc36_32.2(%int_4) [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc36_32.2: init %i32 = converted %int_4, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc36 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc36_32.3: ref %i32 = class_element_access %d.var, element0\n// CHECK:STDOUT:   %.loc36_32.4: init %i32 to %.loc36_32.3 = in_place_init %.loc36_32.2 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc36_32.5: init %D to %d.var = class_init (%.loc36_32.4) [concrete = constants.%D.val]\n// CHECK:STDOUT:   %.loc36_7: init %D = converted %.loc36_32.1, %.loc36_32.5 [concrete = constants.%D.val]\n// CHECK:STDOUT:   assign %d.var, %.loc36_7\n// CHECK:STDOUT:   %D.ref: type = name_ref D, @C.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:   %d: ref %D = ref_binding d, %d.var\n// CHECK:STDOUT:   %AF.ref: %A.AF.type = name_ref AF, @A.%A.AF.decl [concrete = constants.%A.AF]\n// CHECK:STDOUT:   %A.AF.call: init %empty_tuple.type = call %AF.ref()\n// CHECK:STDOUT:   %BF.ref: %B.BF.type = name_ref BF, @B.%B.BF.decl [concrete = constants.%B.BF]\n// CHECK:STDOUT:   %B.BF.call: init %empty_tuple.type = call %BF.ref()\n// CHECK:STDOUT:   %CF.ref: %C.CF.type = name_ref CF, @C.%C.CF.decl [concrete = constants.%C.CF]\n// CHECK:STDOUT:   %C.CF.call: init %empty_tuple.type = call %CF.ref()\n// CHECK:STDOUT:   %DF.ref: %D.DF.type = name_ref DF, @D.%D.DF.decl [concrete = constants.%D.DF]\n// CHECK:STDOUT:   %D.DF.call: init %empty_tuple.type = call %DF.ref()\n// CHECK:STDOUT:   %Destroy.Op.bound.loc36: <bound method> = bound_method %d.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc36: init %empty_tuple.type = call %Destroy.Op.bound.loc36(%d.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc35: <bound method> = bound_method %c.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc35: init %empty_tuple.type = call %Destroy.Op.bound.loc35(%c.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc34: <bound method> = bound_method %b.var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc34: init %empty_tuple.type = call %Destroy.Op.bound.loc34(%b.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc33: <bound method> = bound_method %a.var, constants.%Destroy.Op.651ba6.4\n// CHECK:STDOUT:   %Destroy.Op.call.loc33: init %empty_tuple.type = call %Destroy.Op.bound.loc33(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.CF();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.AF();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc36(%self.param: ref %D) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc35(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc34(%self.param: ref %B) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc33(%self.param: ref %A) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/scope.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/scope.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/scope.carbon\n\nclass Class {\n  fn F() -> i32 {\n    return 1;\n  }\n\n  fn G() -> i32 {\n    return F();\n  }\n}\n\nfn F() -> i32 {\n  return 2;\n}\n\nfn Run() {\n  var unused a: i32 = F();\n  var unused b: i32 = Class.F();\n}\n\n// CHECK:STDOUT: --- scope.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G [concrete]\n// CHECK:STDOUT:   %Class.G: %Class.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc25: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc20: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT:   .G = %Class.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc17_13.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc17_13.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc17_13.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc17: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   return %.loc17\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %F.ref()\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc26_11.1: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc26_11.2: <bound method> = bound_method %int_2, %specific_fn [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc26_11.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc26: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   return %.loc26\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.7ce = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %i32 = var %a.var_patt\n// CHECK:STDOUT:   %F.ref.loc30: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.ref.loc30()\n// CHECK:STDOUT:   assign %a.var, %F.call\n// CHECK:STDOUT:   %i32.loc30: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %a: ref %i32 = ref_binding a, %a.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt\n// CHECK:STDOUT:   %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:   %F.ref.loc31: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %F.ref.loc31()\n// CHECK:STDOUT:   assign %b.var, %Class.F.call\n// CHECK:STDOUT:   %i32.loc31: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc31: <bound method> = bound_method %b.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc31: init %empty_tuple.type = call %Destroy.Op.bound.loc31(%b.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc30: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc30: init %empty_tuple.type = call %Destroy.Op.bound.loc30(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/self/fail_ref_self.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/self/fail_ref_self.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/self/fail_ref_self.carbon\n\nclass Class {\n  fn F[ref self: Self]();\n}\n\nfn Make() -> Class;\n\nfn F(c: Class, p: Class*) {\n  // CHECK:STDERR: fail_ref_self.carbon:[[@LINE+7]]:3: error: value expression passed to reference parameter [ValueForRefParam]\n  // CHECK:STDERR:   c.F();\n  // CHECK:STDERR:   ^\n  // CHECK:STDERR: fail_ref_self.carbon:[[@LINE-9]]:8: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR:   fn F[ref self: Self]();\n  // CHECK:STDERR:        ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  c.F();\n\n  // This call is OK.\n  (*p).F();\n\n  // So is this one.\n  Make().F();\n}\n\n// CHECK:STDOUT: --- fail_ref_self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.cff: Core.Form = init_form %Class [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.8e5: type = ptr_type %Class [concrete]\n// CHECK:STDOUT:   %pattern_type.018: type = pattern_type %ptr.8e5 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .Make = %Make.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Make.decl: %Make.type = fn_decl @Make [concrete = constants.%Make] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.904 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.904 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     %.loc19: Core.Form = init_form %Class.ref [concrete = constants.%.cff]\n// CHECK:STDOUT:     %return.param: ref %Class = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Class = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.904 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.904 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %p.patt: %pattern_type.018 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.018 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %Class = value_param call_param0\n// CHECK:STDOUT:     %Class.ref.loc21_9: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     %c: %Class = value_binding c, %c.param\n// CHECK:STDOUT:     %p.param: %ptr.8e5 = value_param call_param1\n// CHECK:STDOUT:     %.loc21: type = splice_block %ptr [concrete = constants.%ptr.8e5] {\n// CHECK:STDOUT:       %Class.ref.loc21_19: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Class.ref.loc21_19 [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.8e5 = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: ref %Class = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self: ref %Class = ref_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F(%self.param: ref %Class);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Make() -> out %return.param: %Class;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %Class, %p.param: %ptr.8e5) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %Class = name_ref c, %c\n// CHECK:STDOUT:   %F.ref.loc29: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.bound.loc29: <bound method> = bound_method %c.ref, %F.ref.loc29\n// CHECK:STDOUT:   %Class.F.call.loc29: init %empty_tuple.type = call %Class.F.bound.loc29(<error>)\n// CHECK:STDOUT:   %p.ref: %ptr.8e5 = name_ref p, %p\n// CHECK:STDOUT:   %.loc32: ref %Class = deref %p.ref\n// CHECK:STDOUT:   %F.ref.loc32: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.bound.loc32: <bound method> = bound_method %.loc32, %F.ref.loc32\n// CHECK:STDOUT:   %Class.F.call.loc32: init %empty_tuple.type = call %Class.F.bound.loc32(%.loc32)\n// CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %.loc35_8.1: ref %Class = temporary_storage\n// CHECK:STDOUT:   %Make.call: init %Class to %.loc35_8.1 = call %Make.ref()\n// CHECK:STDOUT:   %.loc35_8.2: ref %Class = temporary %.loc35_8.1, %Make.call\n// CHECK:STDOUT:   %F.ref.loc35: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.bound.loc35: <bound method> = bound_method %.loc35_8.2, %F.ref.loc35\n// CHECK:STDOUT:   %Class.F.call.loc35: init %empty_tuple.type = call %Class.F.bound.loc35(%.loc35_8.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc35_8.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc35_8.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Class) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/self/fail_self.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/self/fail_self.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/self/fail_self.carbon\n\nclass Class {\n  // CHECK:STDERR: fail_self.carbon:[[@LINE+4]]:8: error: `self` can only be declared in an implicit parameter list [SelfOutsideImplicitParamList]\n  // CHECK:STDERR:   fn F(self: Self);\n  // CHECK:STDERR:        ^~~~~~~~~~\n  // CHECK:STDERR:\n  fn F(self: Self);\n\n  fn G() -> Self;\n}\n\n// CHECK:STDERR: fail_self.carbon:[[@LINE+4]]:19: error: `self` can only be declared in an implicit parameter list [SelfOutsideImplicitParamList]\n// CHECK:STDERR: fn Class.F(unused self: Self) {\n// CHECK:STDERR:                   ^~~~~~~~~~\n// CHECK:STDERR:\nfn Class.F(unused self: Self) {\n}\n\nfn Class.G() -> Self {\n  // CHECK:STDERR: fail_self.carbon:[[@LINE+4]]:7: error: `self` can only be declared in an implicit parameter list [SelfOutsideImplicitParamList]\n  // CHECK:STDERR:   var self: Self;\n  // CHECK:STDERR:       ^~~~~~~~~~\n  // CHECK:STDERR:\n  var self: Self;\n  // CHECK:STDERR: fail_self.carbon:[[@LINE+7]]:10: error: cannot copy value of type `Class` [CopyOfUncopyableType]\n  // CHECK:STDERR:   return self;\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR: fail_self.carbon:[[@LINE+4]]:10: note: type `Class` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return self;\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR:\n  return self;\n}\n\nclass WrongSelf {\n  fn F[self: Class]();\n}\n\nfn CallWrongSelf(ws: WrongSelf) {\n  // CHECK:STDERR: fail_self.carbon:[[@LINE+10]]:3: error: cannot implicitly convert expression of type `WrongSelf` to `Class` [ConversionFailure]\n  // CHECK:STDERR:   ws.F();\n  // CHECK:STDERR:   ^~\n  // CHECK:STDERR: fail_self.carbon:[[@LINE+7]]:3: note: type `WrongSelf` does not implement interface `Core.ImplicitAs(Class)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   ws.F();\n  // CHECK:STDERR:   ^~\n  // CHECK:STDERR: fail_self.carbon:[[@LINE-10]]:8: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR:   fn F[self: Class]();\n  // CHECK:STDERR:        ^~~~~~~~~~~\n  // CHECK:STDERR:\n  ws.F();\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/self/fail_self_param.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/self/fail_self_param.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/self/fail_self_param.carbon\n\n// CHECK:STDERR: fail_self_param.carbon:[[@LINE+4]]:9: error: `self` parameter only allowed on functions [SelfParameterNotAllowed]\n// CHECK:STDERR: class C[self:! type](x:! self) {}\n// CHECK:STDERR:         ^~~~~~~~~~~\n// CHECK:STDERR:\nclass C[self:! type](x:! self) {}\nvar v: C(());\n"
  },
  {
    "path": "toolchain/check/testdata/class/self/fail_self_type_member.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/bool.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/self/fail_self_type_member.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/self/fail_self_type_member.carbon\n\nclass Class {\n  var b: bool;\n}\n\nfn F() -> bool {\n  var c1: Class = {.b = true};\n  // CHECK:STDERR: fail_self_type_member.carbon:[[@LINE+8]]:17: error: expected identifier after `.` [ExpectedIdentifierAfterPeriodOrArrow]\n  // CHECK:STDERR:   var c2: Class.Self = c1;\n  // CHECK:STDERR:                 ^~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_self_type_member.carbon:[[@LINE+4]]:17: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n  // CHECK:STDERR:   var c2: Class.Self = c1;\n  // CHECK:STDERR:                 ^~~~\n  // CHECK:STDERR:\n  var c2: Class.Self = c1;\n  return c2.b;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/class/self/raw_self.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/self/raw_self.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/self/raw_self.carbon\n\nclass Class {\n  fn F[ref self: Self](r#self: i32);\n  fn G[self: Self](r#self: i32) -> (i32, i32);\n  var n: i32;\n}\n\nfn Class.F[ref self: Self](r#self: i32) {\n  self.n = r#self;\n}\n\nfn Class.G[self: Self](r#self: i32) -> (i32, i32) {\n  return (self.n, r#self);\n}\n\n// CHECK:STDOUT: --- raw_self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.95a: %tuple.type.24b = tuple_value (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %.f32: Core.Form = init_form %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %pattern_type.511: type = pattern_type %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G [concrete]\n// CHECK:STDOUT:   %Class.G: %Class.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt.loc21_16: %pattern_type.904 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt.loc21_20: %pattern_type.904 = ref_param_pattern %self.patt.loc21_16 [concrete]\n// CHECK:STDOUT:     %self.patt.loc21_28: %pattern_type.7ce = value_binding_pattern r#self [concrete]\n// CHECK:STDOUT:     %self.param_patt.loc21_34: %pattern_type.7ce = value_param_pattern %self.patt.loc21_28 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param.loc21_20: ref %Class = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc21: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc21_16: ref %Class = ref_binding self, %self.param.loc21_20\n// CHECK:STDOUT:     %self.param.loc21_34: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc21: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %self.loc21_28: %i32 = value_binding r#self, %self.param.loc21_34\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %self.patt.loc25_12: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt.loc25_16: %pattern_type.904 = value_param_pattern %self.patt.loc25_12 [concrete]\n// CHECK:STDOUT:     %self.patt.loc25_24: %pattern_type.7ce = value_binding_pattern r#self [concrete]\n// CHECK:STDOUT:     %self.param_patt.loc25_30: %pattern_type.7ce = value_param_pattern %self.patt.loc25_24 [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.511 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.511 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc25_41: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %i32.loc25_46: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc25_49.1: %tuple.type.24b = tuple_literal (%i32.loc25_41, %i32.loc25_46) [concrete = constants.%tuple.95a]\n// CHECK:STDOUT:     %.loc25_49.2: type = converted %.loc25_49.1, constants.%tuple.type.d07 [concrete = constants.%tuple.type.d07]\n// CHECK:STDOUT:     %.loc25_49.3: Core.Form = init_form %.loc25_49.2 [concrete = constants.%.f32]\n// CHECK:STDOUT:     %self.param.loc25_16: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc25: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc25_12: %Class = value_binding self, %self.param.loc25_16\n// CHECK:STDOUT:     %self.param.loc25_30: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc25_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %self.loc25_24: %i32 = value_binding r#self, %self.param.loc25_30\n// CHECK:STDOUT:     %return.param.loc25: ref %tuple.type.d07 = out_param call_param2\n// CHECK:STDOUT:     %return.loc25: ref %tuple.type.d07 = return_slot %return.param.loc25\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt.loc21_16: %pattern_type.904 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt.loc21_20: %pattern_type.904 = ref_param_pattern %self.patt.loc21_16 [concrete]\n// CHECK:STDOUT:     %self.patt.loc21_28: %pattern_type.7ce = value_binding_pattern r#self [concrete]\n// CHECK:STDOUT:     %self.param_patt.loc21_34: %pattern_type.7ce = value_param_pattern %self.patt.loc21_28 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param.loc16_16: ref %Class = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc16: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc16_12: ref %Class = ref_binding self, %self.param.loc16_16\n// CHECK:STDOUT:     %self.param.loc16_30: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %self.loc16_24: %i32 = value_binding r#self, %self.param.loc16_30\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %self.patt.loc25_12: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt.loc25_16: %pattern_type.904 = value_param_pattern %self.patt.loc25_12 [concrete]\n// CHECK:STDOUT:     %self.patt.loc25_24: %pattern_type.7ce = value_binding_pattern r#self [concrete]\n// CHECK:STDOUT:     %self.param_patt.loc25_30: %pattern_type.7ce = value_param_pattern %self.patt.loc25_24 [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.511 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.511 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc17_37: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %i32.loc17_42: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc17_45.1: %tuple.type.24b = tuple_literal (%i32.loc17_37, %i32.loc17_42) [concrete = constants.%tuple.95a]\n// CHECK:STDOUT:     %.loc17_45.2: type = converted %.loc17_45.1, constants.%tuple.type.d07 [concrete = constants.%tuple.type.d07]\n// CHECK:STDOUT:     %.loc17_45.3: Core.Form = init_form %.loc17_45.2 [concrete = constants.%.f32]\n// CHECK:STDOUT:     %self.param.loc17_12: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc17: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc17_8: %Class = value_binding self, %self.param.loc17_12\n// CHECK:STDOUT:     %self.param.loc17_26: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc17_28: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %self.loc17_20: %i32 = value_binding r#self, %self.param.loc17_26\n// CHECK:STDOUT:     %return.param.loc17: ref %tuple.type.d07 = out_param call_param2\n// CHECK:STDOUT:     %return.loc17: ref %tuple.type.d07 = return_slot %return.param.loc17\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc18: %Class.elem = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT:   .G = %Class.G.decl\n// CHECK:STDOUT:   .n = %.loc18\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F(%self.param.loc21_20: ref %Class, %self.param.loc21_34: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref.loc22_3: ref %Class = name_ref self, %self.loc21_16\n// CHECK:STDOUT:   %n.ref: %Class.elem = name_ref n, @Class.%.loc18 [concrete = @Class.%.loc18]\n// CHECK:STDOUT:   %.loc22: ref %i32 = class_element_access %self.ref.loc22_3, element0\n// CHECK:STDOUT:   %self.ref.loc22_12: %i32 = name_ref r#self, %self.loc21_28\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc22_12.1: <bound method> = bound_method %self.ref.loc22_12, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc22_12.2: <bound method> = bound_method %self.ref.loc22_12, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc22_12.2(%self.ref.loc22_12)\n// CHECK:STDOUT:   assign %.loc22, %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.G(%self.param.loc25_16: %Class, %self.param.loc25_30: %i32) -> out %return.param.loc25: %tuple.type.d07 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref.loc26_11: %Class = name_ref self, %self.loc25_12\n// CHECK:STDOUT:   %n.ref: %Class.elem = name_ref n, @Class.%.loc18 [concrete = @Class.%.loc18]\n// CHECK:STDOUT:   %.loc26_15.1: ref %i32 = class_element_access %self.ref.loc26_11, element0\n// CHECK:STDOUT:   %.loc26_15.2: %i32 = acquire_value %.loc26_15.1\n// CHECK:STDOUT:   %self.ref.loc26_19: %i32 = name_ref r#self, %self.loc25_24\n// CHECK:STDOUT:   %.loc26_25.1: %tuple.type.d07 = tuple_literal (%.loc26_15.2, %self.ref.loc26_19)\n// CHECK:STDOUT:   %impl.elem0.loc26_15: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc26_15.1: <bound method> = bound_method %.loc26_15.2, %impl.elem0.loc26_15\n// CHECK:STDOUT:   %specific_fn.loc26_15: <specific function> = specific_function %impl.elem0.loc26_15, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc26_15.2: <bound method> = bound_method %.loc26_15.2, %specific_fn.loc26_15\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc26_15: init %i32 = call %bound_method.loc26_15.2(%.loc26_15.2)\n// CHECK:STDOUT:   %tuple.elem0: ref %i32 = tuple_access %return.param.loc25, element0\n// CHECK:STDOUT:   %.loc26_25.2: init %i32 to %tuple.elem0 = in_place_init %Int.as.Copy.impl.Op.call.loc26_15\n// CHECK:STDOUT:   %impl.elem0.loc26_19: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc26_19.1: <bound method> = bound_method %self.ref.loc26_19, %impl.elem0.loc26_19\n// CHECK:STDOUT:   %specific_fn.loc26_19: <specific function> = specific_function %impl.elem0.loc26_19, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc26_19.2: <bound method> = bound_method %self.ref.loc26_19, %specific_fn.loc26_19\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc26_19: init %i32 = call %bound_method.loc26_19.2(%self.ref.loc26_19)\n// CHECK:STDOUT:   %tuple.elem1: ref %i32 = tuple_access %return.param.loc25, element1\n// CHECK:STDOUT:   %.loc26_25.3: init %i32 to %tuple.elem1 = in_place_init %Int.as.Copy.impl.Op.call.loc26_19\n// CHECK:STDOUT:   %.loc26_25.4: init %tuple.type.d07 to %return.param.loc25 = tuple_init (%.loc26_25.2, %.loc26_25.3)\n// CHECK:STDOUT:   %.loc26_26: init %tuple.type.d07 = converted %.loc26_25.1, %.loc26_25.4\n// CHECK:STDOUT:   return %.loc26_26 to %return.param.loc25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/self/raw_self_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/self/raw_self_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/self/raw_self_type.carbon\n\nclass Class {\n  fn F() {\n    var r#Self: Self*;\n    var unused p: Self* = r#Self;\n  }\n}\n\nclass MemberNamedSelf {\n  class r#Self {}\n\n  fn F(x: Self, y: r#Self);\n}\n\nfn MemberNamedSelf.F(unused x: Self, unused y: r#Self) {}\n\n// CHECK:STDOUT: --- raw_self_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ptr.8e5: type = ptr_type %Class [concrete]\n// CHECK:STDOUT:   %pattern_type.018: type = pattern_type %ptr.8e5 [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.5ad: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%ptr.8e5) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.e77: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%ptr.8e5) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.d9e: %T.as.DefaultOrUnformed.impl.Op.type.e77 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %ptr.8e5, (%DefaultOrUnformed.impl_witness.5ad) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.d9e, @T.as.DefaultOrUnformed.impl.Op(%ptr.8e5) [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.9d3: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%Class) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.02e: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%Class) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.120: %ptr.as.Copy.impl.Op.type.02e = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.8e5, (%Copy.impl_witness.9d3) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.130: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.370: type = fn_type_with_self_type %Copy.WithSelf.Op.type.130, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.120, @ptr.as.Copy.impl.Op(%Class) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %MemberNamedSelf: type = class_type @MemberNamedSelf [concrete]\n// CHECK:STDOUT:   %Self.0d4: type = class_type @Self [concrete]\n// CHECK:STDOUT:   %pattern_type.4b2: type = pattern_type %MemberNamedSelf [concrete]\n// CHECK:STDOUT:   %pattern_type.f56: type = pattern_type %Self.0d4 [concrete]\n// CHECK:STDOUT:   %MemberNamedSelf.F.type: type = fn_type @MemberNamedSelf.F [concrete]\n// CHECK:STDOUT:   %MemberNamedSelf.F: %MemberNamedSelf.F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .MemberNamedSelf = %MemberNamedSelf.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %MemberNamedSelf.decl: type = class_decl @MemberNamedSelf [concrete = constants.%MemberNamedSelf] {} {}\n// CHECK:STDOUT:   %MemberNamedSelf.F.decl: %MemberNamedSelf.F.type = fn_decl @MemberNamedSelf.F [concrete = constants.%MemberNamedSelf.F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.4b2 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.4b2 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %y.patt: %pattern_type.f56 = value_binding_pattern y [concrete]\n// CHECK:STDOUT:     %y.param_patt: %pattern_type.f56 = value_param_pattern %y.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param.loc28: %MemberNamedSelf = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc28_32: type = name_ref Self, constants.%MemberNamedSelf [concrete = constants.%MemberNamedSelf]\n// CHECK:STDOUT:     %x.loc28: %MemberNamedSelf = value_binding x, %x.param.loc28\n// CHECK:STDOUT:     %y.param.loc28: %Self.0d4 = value_param call_param1\n// CHECK:STDOUT:     %Self.ref.loc28_48: type = name_ref r#Self, @MemberNamedSelf.%Self.decl [concrete = constants.%Self.0d4]\n// CHECK:STDOUT:     %y.loc28: %Self.0d4 = value_binding y, %y.param.loc28\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @MemberNamedSelf {\n// CHECK:STDOUT:   %Self.decl: type = class_decl @Self [concrete = constants.%Self.0d4] {} {}\n// CHECK:STDOUT:   %MemberNamedSelf.F.decl: %MemberNamedSelf.F.type = fn_decl @MemberNamedSelf.F [concrete = constants.%MemberNamedSelf.F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.4b2 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.4b2 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %y.patt: %pattern_type.f56 = value_binding_pattern y [concrete]\n// CHECK:STDOUT:     %y.param_patt: %pattern_type.f56 = value_param_pattern %y.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param.loc25: %MemberNamedSelf = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc25_11: type = name_ref Self, constants.%MemberNamedSelf [concrete = constants.%MemberNamedSelf]\n// CHECK:STDOUT:     %x.loc25: %MemberNamedSelf = value_binding x, %x.param.loc25\n// CHECK:STDOUT:     %y.param.loc25: %Self.0d4 = value_param call_param1\n// CHECK:STDOUT:     %Self.ref.loc25_20: type = name_ref r#Self, @MemberNamedSelf.%Self.decl [concrete = constants.%Self.0d4]\n// CHECK:STDOUT:     %y.loc25: %Self.0d4 = value_binding y, %y.param.loc25\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%MemberNamedSelf\n// CHECK:STDOUT:   .r#Self = %Self.decl\n// CHECK:STDOUT:   .F = %MemberNamedSelf.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Self {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Self.0d4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %Self.patt: %pattern_type.018 = ref_binding_pattern r#Self [concrete]\n// CHECK:STDOUT:     %Self.var_patt: %pattern_type.018 = var_pattern %Self.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Self.var: ref %ptr.8e5 = var %Self.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%ptr.8e5, (constants.%DefaultOrUnformed.impl_witness.5ad) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc17_22.1: %DefaultOrUnformed.type = converted constants.%ptr.8e5, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc17_22.1 [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:   %.loc17_22.2: type = converted %.loc17_22.1, %as_type [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.d9e, @T.as.DefaultOrUnformed.impl.Op(constants.%ptr.8e5) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %ptr.8e5 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %Self.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %.loc17_21: type = splice_block %ptr.loc17 [concrete = constants.%ptr.8e5] {\n// CHECK:STDOUT:     %Self.ref.loc17: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %ptr.loc17: type = ptr_type %Self.ref.loc17 [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Self: ref %ptr.8e5 = ref_binding r#Self, %Self.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %p.patt: %pattern_type.018 = ref_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.var_patt: %pattern_type.018 = var_pattern %p.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %p.var: ref %ptr.8e5 = var %p.var_patt\n// CHECK:STDOUT:   %Self.ref.loc18_27: ref %ptr.8e5 = name_ref r#Self, %Self\n// CHECK:STDOUT:   %.loc18_27: %ptr.8e5 = acquire_value %Self.ref.loc18_27\n// CHECK:STDOUT:   %impl.elem0: %.370 = impl_witness_access constants.%Copy.impl_witness.9d3, element0 [concrete = constants.%ptr.as.Copy.impl.Op.120]\n// CHECK:STDOUT:   %bound_method.loc18_27.1: <bound method> = bound_method %.loc18_27, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%Class) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_27.2: <bound method> = bound_method %.loc18_27, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.8e5 = call %bound_method.loc18_27.2(%.loc18_27)\n// CHECK:STDOUT:   assign %p.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   %.loc18_23: type = splice_block %ptr.loc18 [concrete = constants.%ptr.8e5] {\n// CHECK:STDOUT:     %Self.ref.loc18_19: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %ptr.loc18: type = ptr_type %Self.ref.loc18_19 [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %p: ref %ptr.8e5 = ref_binding p, %p.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc18: <bound method> = bound_method %p.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc18: init %empty_tuple.type = call %Destroy.Op.bound.loc18(%p.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc17: <bound method> = bound_method %Self.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc17: init %empty_tuple.type = call %Destroy.Op.bound.loc17(%Self.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %ptr.8e5) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MemberNamedSelf.F(%x.param.loc28: %MemberNamedSelf, %y.param.loc28: %Self.0d4) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/self/self.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/self/self.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/self/self.carbon\n\n// --- self.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class {\n  fn F[self: Self]() -> i32;\n  fn G[ref self: Self]() -> i32;\n\n  var n: i32;\n}\n\nfn Class.F[self: Self]() -> i32 {\n  return self.n;\n}\n\nfn Class.G[ref self: Self]() -> i32 {\n  return self.n;\n}\n\n// --- fail_return_self_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class {\n  // CHECK:STDERR: fail_return_self_value.carbon:[[@LINE+7]]:25: error: cannot implicitly convert non-type value of type `Class` to `type` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   fn F[self: Self]() -> self;\n  // CHECK:STDERR:                         ^~~~\n  // CHECK:STDERR: fail_return_self_value.carbon:[[@LINE+4]]:25: note: type `Class` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   fn F[self: Self]() -> self;\n  // CHECK:STDERR:                         ^~~~\n  // CHECK:STDERR:\n  fn F[self: Self]() -> self;\n}\n\n// CHECK:STDOUT: --- self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.G.type: type = fn_type @Class.G [concrete]\n// CHECK:STDOUT:   %Class.G: %Class.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc11: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc11: Core.Form = init_form %i32.loc11 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc11: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc11: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc11: %Class = value_binding self, %self.param.loc11\n// CHECK:STDOUT:     %return.param.loc11: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc11: ref %i32 = return_slot %return.param.loc11\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc15: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15: Core.Form = init_form %i32.loc15 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc15: ref %Class = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc15: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc15: ref %Class = ref_binding self, %self.param.loc15\n// CHECK:STDOUT:     %return.param.loc15: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc15: ref %i32 = return_slot %return.param.loc15\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5: Core.Form = init_form %i32.loc5 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc5: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc5: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc5: %Class = value_binding self, %self.param.loc5\n// CHECK:STDOUT:     %return.param.loc5: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc5: ref %i32 = return_slot %return.param.loc5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.G.decl: %Class.G.type = fn_decl @Class.G [concrete = constants.%Class.G] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6: Core.Form = init_form %i32.loc6 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc6: ref %Class = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc6: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc6: ref %Class = ref_binding self, %self.param.loc6\n// CHECK:STDOUT:     %return.param.loc6: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc6: ref %i32 = return_slot %return.param.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc8: %Class.elem = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT:   .G = %Class.G.decl\n// CHECK:STDOUT:   .n = %.loc8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F(%self.param.loc11: %Class) -> out %return.param.loc11: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %Class = name_ref self, %self.loc11\n// CHECK:STDOUT:   %n.ref: %Class.elem = name_ref n, @Class.%.loc8 [concrete = @Class.%.loc8]\n// CHECK:STDOUT:   %.loc12_14.1: ref %i32 = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc12_14.2: %i32 = acquire_value %.loc12_14.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc12_14.1: <bound method> = bound_method %.loc12_14.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc12_14.2: <bound method> = bound_method %.loc12_14.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc12_14.2(%.loc12_14.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.G(%self.param.loc15: ref %Class) -> out %return.param.loc15: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: ref %Class = name_ref self, %self.loc15\n// CHECK:STDOUT:   %n.ref: %Class.elem = name_ref n, @Class.%.loc8 [concrete = @Class.%.loc8]\n// CHECK:STDOUT:   %.loc16_14.1: ref %i32 = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc16_14.2: %i32 = acquire_value %.loc16_14.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc16_14.1: <bound method> = bound_method %.loc16_14.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_14.2: <bound method> = bound_method %.loc16_14.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc16_14.2(%.loc16_14.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_return_self_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.ref: %Class = name_ref self, %self\n// CHECK:STDOUT:     %.loc12: type = converted %self.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:     %self.param: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self: %Class = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F(%self.param: %Class) -> <error>;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/self/self_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/self/self_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/self/self_type.carbon\n\nclass Class {\n  fn F[self: Self]() -> i32;\n  fn Make() -> Self {\n    returned var s: Self;\n    s = {.p = &s};\n    return var;\n  }\n  var p: Self*;\n}\n\nfn Class.F[self: Self]() -> i32 {\n  return (*self.p).F();\n}\n\n// CHECK:STDOUT: --- self_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Class.F.type: type = fn_type @Class.F [concrete]\n// CHECK:STDOUT:   %Class.F: %Class.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.cff: Core.Form = init_form %Class [concrete]\n// CHECK:STDOUT:   %Class.Make.type: type = fn_type @Class.Make [concrete]\n// CHECK:STDOUT:   %Class.Make: %Class.Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.8e5: type = ptr_type %Class [concrete]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, %ptr.8e5 [concrete]\n// CHECK:STDOUT:   %struct_type.p: type = struct_type {.p: %ptr.8e5} [concrete]\n// CHECK:STDOUT:   %complete_type.141: <witness> = complete_type_witness %struct_type.p [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.6ca: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.3d0: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%Class) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.cda: %T.as.DefaultOrUnformed.impl.Op.type.3d0 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %Class, (%DefaultOrUnformed.impl_witness.6ca) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(%Class) [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.9d3: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%Class) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.02e: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%Class) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.120: %ptr.as.Copy.impl.Op.type.02e = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.8e5, (%Copy.impl_witness.9d3) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.130: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.370: type = fn_type_with_self_type %Copy.WithSelf.Op.type.130, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.120, @ptr.as.Copy.impl.Op(%Class) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc25: Core.Form = init_form %i32.loc25 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc25: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc25: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc25: %Class = value_binding self, %self.param.loc25\n// CHECK:STDOUT:     %return.param.loc25: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc25: ref %i32 = return_slot %return.param.loc25\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %Class.F.decl: %Class.F.type = fn_decl @Class.F [concrete = constants.%Class.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.904 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.904 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16: Core.Form = init_form %i32.loc16 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param.loc16: %Class = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc16: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %self.loc16: %Class = value_binding self, %self.param.loc16\n// CHECK:STDOUT:     %return.param.loc16: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc16: ref %i32 = return_slot %return.param.loc16\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Class.Make.decl: %Class.Make.type = fn_decl @Class.Make [concrete = constants.%Class.Make] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.904 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.904 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Self.ref.loc17: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:     %.loc17_16.2: Core.Form = init_form %Self.ref.loc17 [concrete = constants.%.cff]\n// CHECK:STDOUT:     %return.param: ref %Class = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Class = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Self.ref: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:   %ptr: type = ptr_type %Self.ref [concrete = constants.%ptr.8e5]\n// CHECK:STDOUT:   %.loc22: %Class.elem = field_decl p, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.p [concrete = constants.%complete_type.141]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .F = %Class.F.decl\n// CHECK:STDOUT:   .Make = %Class.Make.decl\n// CHECK:STDOUT:   .p = %.loc22\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.F(%self.param.loc25: %Class) -> out %return.param.loc25: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %Class = name_ref self, %self.loc25\n// CHECK:STDOUT:   %p.ref: %Class.elem = name_ref p, @Class.%.loc22 [concrete = @Class.%.loc22]\n// CHECK:STDOUT:   %.loc26_16.1: ref %ptr.8e5 = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc26_16.2: %ptr.8e5 = acquire_value %.loc26_16.1\n// CHECK:STDOUT:   %.loc26_11.1: ref %Class = deref %.loc26_16.2\n// CHECK:STDOUT:   %F.ref: %Class.F.type = name_ref F, @Class.%Class.F.decl [concrete = constants.%Class.F]\n// CHECK:STDOUT:   %Class.F.bound: <bound method> = bound_method %.loc26_11.1, %F.ref\n// CHECK:STDOUT:   %.loc26_11.2: %Class = acquire_value %.loc26_11.1\n// CHECK:STDOUT:   %Class.F.call: init %i32 = call %Class.F.bound(%.loc26_11.2)\n// CHECK:STDOUT:   return %Class.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Class.Make() -> out %return.param: %Class {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %s.patt: %pattern_type.904 = ref_binding_pattern s [concrete]\n// CHECK:STDOUT:     %s.var_patt: %pattern_type.904 = var_pattern %s.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%Class, (constants.%DefaultOrUnformed.impl_witness.6ca) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc18_25.1: %DefaultOrUnformed.type = converted constants.%Class, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc18_25.1 [concrete = constants.%Class]\n// CHECK:STDOUT:   %.loc18_25.2: type = converted %.loc18_25.1, %as_type [concrete = constants.%Class]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.cda, @T.as.DefaultOrUnformed.impl.Op(constants.%Class) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc17_16.1: ref %Class = splice_block %return.param {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %Class to %.loc17_16.1 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %return.param, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %Self.ref.loc18: type = name_ref Self, constants.%Class [concrete = constants.%Class]\n// CHECK:STDOUT:   %s: ref %Class = ref_binding s, %return.param\n// CHECK:STDOUT:   %s.ref.loc19_5: ref %Class = name_ref s, %s\n// CHECK:STDOUT:   %s.ref.loc19_16: ref %Class = name_ref s, %s\n// CHECK:STDOUT:   %addr: %ptr.8e5 = addr_of %s.ref.loc19_16\n// CHECK:STDOUT:   %.loc19_17.1: %struct_type.p = struct_literal (%addr)\n// CHECK:STDOUT:   %impl.elem0: %.370 = impl_witness_access constants.%Copy.impl_witness.9d3, element0 [concrete = constants.%ptr.as.Copy.impl.Op.120]\n// CHECK:STDOUT:   %bound_method.loc19_15.1: <bound method> = bound_method %addr, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%Class) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc19_15.2: <bound method> = bound_method %addr, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.8e5 = call %bound_method.loc19_15.2(%addr)\n// CHECK:STDOUT:   %.loc19_17.2: ref %ptr.8e5 = class_element_access %s.ref.loc19_5, element0\n// CHECK:STDOUT:   %.loc19_17.3: init %ptr.8e5 to %.loc19_17.2 = in_place_init %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   %.loc19_17.4: init %Class to %s.ref.loc19_5 = class_init (%.loc19_17.3)\n// CHECK:STDOUT:   %.loc19_7: init %Class = converted %.loc19_17.1, %.loc19_17.4\n// CHECK:STDOUT:   assign %s.ref.loc19_5, %.loc19_7\n// CHECK:STDOUT:   return %s to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/syntactic_merge.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/syntactic_merge.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/syntactic_merge.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nclass Foo(a:! C);\nclass Foo(a:! C) {}\n\nclass Bar(a:! D);\nclass Bar(a:! D) {}\n\n// --- spacing.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nclass Foo [ ] ( a :! C );\nclass Foo[](a:! C) {}\n\n// --- fail_parens.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nclass Foo(a:! C);\n// CHECK:STDERR: fail_parens.carbon:[[@LINE+7]]:15: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: class Foo(a:! (C)) {}\n// CHECK:STDERR:               ^\n// CHECK:STDERR: fail_parens.carbon:[[@LINE-4]]:15: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR: class Foo(a:! C);\n// CHECK:STDERR:               ^\n// CHECK:STDERR:\nclass Foo(a:! (C)) {}\n\n// --- todo_fail_raw_identifier.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nclass Foo(a:! C);\nclass Foo(a:! r#C) {}\n\n// --- two_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nclass Foo(a:! C);\nclass Bar(a:! D);\n\n// --- two_file.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nclass Foo(a:! C) {}\nclass Bar(a:! D) {}\n\n// --- fail_name_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nclass Foo(a:! C);\n// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE+7]]:11: error: redeclaration differs at parameter 1 [RedeclParamDiffers]\n// CHECK:STDERR: class Foo(b:! D) {}\n// CHECK:STDERR:           ^\n// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE-4]]:11: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n// CHECK:STDERR: class Foo(a:! C);\n// CHECK:STDERR:           ^\n// CHECK:STDERR:\nclass Foo(b:! D) {}\n\n// --- fail_alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nclass Foo(a:! C);\n// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:15: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: class Foo(a:! D) {}\n// CHECK:STDERR:               ^\n// CHECK:STDERR: fail_alias.carbon:[[@LINE-4]]:15: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR: class Foo(a:! C);\n// CHECK:STDERR:               ^\n// CHECK:STDERR:\nclass Foo(a:! D) {}\n\n// --- fail_deduced_alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nclass Foo[a:! C]();\n// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE+7]]:15: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: class Foo[a:! D]() {}\n// CHECK:STDERR:               ^\n// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE-4]]:15: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR: class Foo[a:! C]();\n// CHECK:STDERR:               ^\n// CHECK:STDERR:\nclass Foo[a:! D]() {}\n\n// --- alias_two_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nclass Foo(a:! C);\n\n// --- todo_fail_alias_two_file.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nalias D = C;\n\nclass Foo(a:! D) {}\n\n// --- fail_repeat_const.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nclass Foo(a:! const C);\n// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+11]]:15: warning: `const` applied repeatedly to the same type has no additional effect [RepeatedConst]\n// CHECK:STDERR: class Foo(a:! const (const C)) {}\n// CHECK:STDERR:               ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+7]]:21: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: class Foo(a:! const (const C)) {}\n// CHECK:STDERR:                     ^\n// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE-8]]:21: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR: class Foo(a:! const C);\n// CHECK:STDERR:                     ^\n// CHECK:STDERR:\nclass Foo(a:! const (const C)) {}\n\n// --- fail_self_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base {\n  var a: ();\n\n  fn F[ref self: Self]();\n}\n\n// CHECK:STDERR: fail_self_type.carbon:[[@LINE+7]]:21: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: fn Base.F[ref self: Base]() {\n// CHECK:STDERR:                     ^~~~\n// CHECK:STDERR: fail_self_type.carbon:[[@LINE-6]]:18: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR:   fn F[ref self: Self]();\n// CHECK:STDERR:                  ^~~~\n// CHECK:STDERR:\nfn Base.F[ref self: Base]() {\n  self.a = ();\n}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type: type = generic_class_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo.generic: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo: type = class_type @Foo, @Foo(%a) [symbolic]\n// CHECK:STDOUT:   %Bar.type: type = generic_class_type @Bar [concrete]\n// CHECK:STDOUT:   %Bar.generic: %Bar.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Bar: type = class_type @Bar, @Bar(%a) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc7\n// CHECK:STDOUT:     .Bar = %Bar.decl.loc10\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7: type = splice_block %C.ref.loc7 [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc7_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc8: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8: type = splice_block %C.ref.loc8 [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc8: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Bar.decl.loc10: %Bar.type = class_decl @Bar [concrete = constants.%Bar.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc10: type = splice_block %D.ref.loc10 [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref.loc10: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc10_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc10_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Bar.decl.loc11: %Bar.type = class_decl @Bar [concrete = constants.%Bar.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc11: type = splice_block %D.ref.loc11 [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref.loc11: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc11: %C = symbolic_binding a, 0 [symbolic = %a.loc10_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo(%a.loc7_11.2: %C) {\n// CHECK:STDOUT:   %a.loc7_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Bar(%a.loc10_11.2: %C) {\n// CHECK:STDOUT:   %a.loc10_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc10_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Bar\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo(constants.%a) {\n// CHECK:STDOUT:   %a.loc7_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Bar(constants.%a) {\n// CHECK:STDOUT:   %a.loc10_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- spacing.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type: type = generic_class_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo.generic: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo: type = class_type @Foo, @Foo(%a) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %C.ref.loc6 [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref.loc6: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc6_17.2: %C = symbolic_binding a, 0 [symbolic = %a.loc6_17.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7: type = splice_block %C.ref.loc7 [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc7: %C = symbolic_binding a, 0 [symbolic = %a.loc6_17.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo(%a.loc6_17.2: %C) {\n// CHECK:STDOUT:   %a.loc6_17.1: %C = symbolic_binding a, 0 [symbolic = %a.loc6_17.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo(constants.%a) {\n// CHECK:STDOUT:   %a.loc6_17.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_parens.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type.337be0.1: type = generic_class_type @Foo.loc6 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.1: %Foo.type.337be0.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.type.337be0.2: type = generic_class_type @Foo.loc14 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.2: %Foo.type.337be0.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.3958a5.2: type = class_type @Foo.loc14, @Foo.loc14(%a) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type.337be0.1 = class_decl @Foo.loc6 [concrete = constants.%Foo.generic.6e878d.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc6_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc6_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc14: %Foo.type.337be0.2 = class_decl @Foo.loc14 [concrete = constants.%Foo.generic.6e878d.2] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc14: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc14_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc14_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc6(%a.loc6_11.2: %C) {\n// CHECK:STDOUT:   %a.loc6_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc6_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc14(%a.loc14_11.2: %C) {\n// CHECK:STDOUT:   %a.loc14_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc14_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo.3958a5.2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc6(constants.%a) {\n// CHECK:STDOUT:   %a.loc6_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc14(constants.%a) {\n// CHECK:STDOUT:   %a.loc14_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- todo_fail_raw_identifier.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type: type = generic_class_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo.generic: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo: type = class_type @Foo, @Foo(%a) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %C.ref.loc6 [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref.loc6: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc6_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc6_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7: type = splice_block %C.ref.loc7 [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc7: %C = symbolic_binding a, 0 [symbolic = %a.loc6_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo(%a.loc6_11.2: %C) {\n// CHECK:STDOUT:   %a.loc6_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc6_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo(constants.%a) {\n// CHECK:STDOUT:   %a.loc6_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- two_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type: type = generic_class_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo.generic: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Bar.type: type = generic_class_type @Bar [concrete]\n// CHECK:STDOUT:   %Bar.generic: %Bar.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Bar = %Bar.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc7_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Bar.decl: %Bar.type = class_decl @Bar [concrete = constants.%Bar.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8: type = splice_block %D.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc8_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc8_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo(%a.loc7_11.2: %C) {\n// CHECK:STDOUT:   %a.loc7_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Bar(%a.loc8_11.2: %C) {\n// CHECK:STDOUT:   %a.loc8_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc8_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo(constants.%a) {\n// CHECK:STDOUT:   %a.loc7_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Bar(constants.%a) {\n// CHECK:STDOUT:   %a.loc8_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- two_file.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type: type = generic_class_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo.generic: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo: type = class_type @Foo, @Foo(%a) [symbolic]\n// CHECK:STDOUT:   %Bar.type: type = generic_class_type @Bar [concrete]\n// CHECK:STDOUT:   %Bar.generic: %Bar.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Bar: type = class_type @Bar, @Bar(%a) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//two_file, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//two_file, D, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//two_file, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//two_file, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.a7fd84.1: %C = import_ref Main//two_file, loc7_11, loaded [symbolic = @Foo.%a.1 (constants.%a)]\n// CHECK:STDOUT:   %Main.import_ref.a7fd84.2: %C = import_ref Main//two_file, loc8_11, loaded [symbolic = @Bar.%a.1 (constants.%a)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Bar = %Bar.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_24.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_24.2 = import <none>\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc4: %C = symbolic_binding a, 0 [symbolic = %a.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Bar.decl: %Bar.type = class_decl @Bar [concrete = constants.%Bar.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5: type = splice_block %D.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc5: %C = symbolic_binding a, 0 [symbolic = %a.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"two_file.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo(imports.%Main.import_ref.a7fd84.1: %C) {\n// CHECK:STDOUT:   %a.1: %C = symbolic_binding a, 0 [symbolic = %a.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Bar(imports.%Main.import_ref.a7fd84.2: %C) {\n// CHECK:STDOUT:   %a.1: %C = symbolic_binding a, 0 [symbolic = %a.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Bar\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo(constants.%a) {\n// CHECK:STDOUT:   %a.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Bar(constants.%a) {\n// CHECK:STDOUT:   %a.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_name_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type.337be0.1: type = generic_class_type @Foo.loc7 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.1: %Foo.type.337be0.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %b: %C = symbolic_binding b, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type.337be0.2: type = generic_class_type @Foo.loc15 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.2: %Foo.type.337be0.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.3958a5.2: type = class_type @Foo.loc15, @Foo.loc15(%b) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type.337be0.1 = class_decl @Foo.loc7 [concrete = constants.%Foo.generic.6e878d.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc7_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc15: %Foo.type.337be0.2 = class_decl @Foo.loc15 [concrete = constants.%Foo.generic.6e878d.2] {\n// CHECK:STDOUT:     %b.patt: %pattern_type = symbolic_binding_pattern b, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15: type = splice_block %D.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b.loc15_11.2: %C = symbolic_binding b, 0 [symbolic = %b.loc15_11.1 (constants.%b)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc7(%a.loc7_11.2: %C) {\n// CHECK:STDOUT:   %a.loc7_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc15(%b.loc15_11.2: %C) {\n// CHECK:STDOUT:   %b.loc15_11.1: %C = symbolic_binding b, 0 [symbolic = %b.loc15_11.1 (constants.%b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo.3958a5.2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc7(constants.%a) {\n// CHECK:STDOUT:   %a.loc7_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc15(constants.%b) {\n// CHECK:STDOUT:   %b.loc15_11.1 => constants.%b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type.337be0.1: type = generic_class_type @Foo.loc7 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.1: %Foo.type.337be0.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.type.337be0.2: type = generic_class_type @Foo.loc15 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.2: %Foo.type.337be0.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.3958a5.2: type = class_type @Foo.loc15, @Foo.loc15(%a) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type.337be0.1 = class_decl @Foo.loc7 [concrete = constants.%Foo.generic.6e878d.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc7_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc15: %Foo.type.337be0.2 = class_decl @Foo.loc15 [concrete = constants.%Foo.generic.6e878d.2] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15: type = splice_block %D.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc15_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc15_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc7(%a.loc7_11.2: %C) {\n// CHECK:STDOUT:   %a.loc7_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc15(%a.loc15_11.2: %C) {\n// CHECK:STDOUT:   %a.loc15_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc15_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo.3958a5.2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc7(constants.%a) {\n// CHECK:STDOUT:   %a.loc7_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc15(constants.%a) {\n// CHECK:STDOUT:   %a.loc15_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_deduced_alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type.337be0.1: type = generic_class_type @Foo.loc7 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.1: %Foo.type.337be0.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.type.337be0.2: type = generic_class_type @Foo.loc15 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.2: %Foo.type.337be0.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.3958a5.2: type = class_type @Foo.loc15, @Foo.loc15(%a) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type.337be0.1 = class_decl @Foo.loc7 [concrete = constants.%Foo.generic.6e878d.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc7_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc15: %Foo.type.337be0.2 = class_decl @Foo.loc15 [concrete = constants.%Foo.generic.6e878d.2] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15: type = splice_block %D.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc15_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc15_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc7(%a.loc7_11.2: %C) {\n// CHECK:STDOUT:   %a.loc7_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc7_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc15(%a.loc15_11.2: %C) {\n// CHECK:STDOUT:   %a.loc15_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc15_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo.3958a5.2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc7(constants.%a) {\n// CHECK:STDOUT:   %a.loc7_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc15(constants.%a) {\n// CHECK:STDOUT:   %a.loc15_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- alias_two_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type: type = generic_class_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo.generic: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc6_11.2: %C = symbolic_binding a, 0 [symbolic = %a.loc6_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo(%a.loc6_11.2: %C) {\n// CHECK:STDOUT:   %a.loc6_11.1: %C = symbolic_binding a, 0 [symbolic = %a.loc6_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo(constants.%a) {\n// CHECK:STDOUT:   %a.loc6_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- todo_fail_alias_two_file.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type: type = generic_class_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo.generic: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo: type = class_type @Foo, @Foo(%a) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//alias_two_file, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//alias_two_file, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//alias_two_file, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.a7f: %C = import_ref Main//alias_two_file, loc6_11, loaded [symbolic = @Foo.%a.1 (constants.%a)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_30.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_30.2 = import <none>\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %D.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc6: %C = symbolic_binding a, 0 [symbolic = %a.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"alias_two_file.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo(imports.%Main.import_ref.a7f: %C) {\n// CHECK:STDOUT:   %a.1: %C = symbolic_binding a, 0 [symbolic = %a.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo(constants.%a) {\n// CHECK:STDOUT:   %a.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_repeat_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %const: type = const_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %const [concrete]\n// CHECK:STDOUT:   %a: %const = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type.337be0.1: type = generic_class_type @Foo.loc6 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.1: %Foo.type.337be0.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.type.337be0.2: type = generic_class_type @Foo.loc18 [concrete]\n// CHECK:STDOUT:   %Foo.generic.6e878d.2: %Foo.type.337be0.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.e46e8f.2: type = class_type @Foo.loc18, @Foo.loc18(%a) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type.337be0.1 = class_decl @Foo.loc6 [concrete = constants.%Foo.generic.6e878d.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %const [concrete = constants.%const] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %const: type = const_type %C.ref [concrete = constants.%const]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc6_11.2: %const = symbolic_binding a, 0 [symbolic = %a.loc6_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc18: %Foo.type.337be0.2 = class_decl @Foo.loc18 [concrete = constants.%Foo.generic.6e878d.2] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc18: type = splice_block %const.loc18_15 [concrete = constants.%const] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %const.loc18_22: type = const_type %C.ref [concrete = constants.%const]\n// CHECK:STDOUT:       %const.loc18_15: type = const_type %const.loc18_22 [concrete = constants.%const]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc18_11.2: %const = symbolic_binding a, 0 [symbolic = %a.loc18_11.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc6(%a.loc6_11.2: %const) {\n// CHECK:STDOUT:   %a.loc6_11.1: %const = symbolic_binding a, 0 [symbolic = %a.loc6_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Foo.loc18(%a.loc18_11.2: %const) {\n// CHECK:STDOUT:   %a.loc18_11.1: %const = symbolic_binding a, 0 [symbolic = %a.loc18_11.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Foo.e46e8f.2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc6(constants.%a) {\n// CHECK:STDOUT:   %a.loc6_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc18(constants.%a) {\n// CHECK:STDOUT:   %a.loc18_11.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_self_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %Base.F.type.c66019.1: type = fn_type @Base.F.loc7 [concrete]\n// CHECK:STDOUT:   %Base.F.811e28.1: %Base.F.type.c66019.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.a [concrete]\n// CHECK:STDOUT:   %Base.F.type.c66019.2: type = fn_type @Base.F.loc17 [concrete]\n// CHECK:STDOUT:   %Base.F.811e28.2: %Base.F.type.c66019.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type.c66019.2 = fn_decl @Base.F.loc17 [concrete = constants.%Base.F.811e28.2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: ref %Base = ref_param call_param0\n// CHECK:STDOUT:     %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:     %self: ref %Base = ref_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %.loc5_11.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc5_11.2: type = converted %.loc5_11.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   %.loc5_8: %Base.elem = field_decl a, element0 [concrete]\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type.c66019.1 = fn_decl @Base.F.loc7 [concrete = constants.%Base.F.811e28.1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: ref %Base = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self: ref %Base = ref_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.a [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .a = %.loc5_8\n// CHECK:STDOUT:   .F = %Base.F.decl\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Base.F.loc7(%self.param: ref %Base);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Base.F.loc17(%self.param: ref %Base) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: ref %Base = name_ref self, %self\n// CHECK:STDOUT:   %a.ref: %Base.elem = name_ref a, @Base.%.loc5_8 [concrete = @Base.%.loc5_8]\n// CHECK:STDOUT:   %.loc18_7: ref %empty_tuple.type = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc18_13.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc18_13.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc18_10: init %empty_tuple.type = converted %.loc18_13.1, %.loc18_13.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   assign %.loc18_7, %.loc18_10\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/syntactic_merge_literal.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/syntactic_merge_literal.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/syntactic_merge_literal.carbon\n\n// --- int_match.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(a:! i32) {}\nclass D(b:! C(1_000));\nclass D(b:! C(1_000)) {}\n\n// --- fail_int_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(a:! i32) {}\nclass D(b:! C(1000));\n// CHECK:STDERR: fail_int_mismatch.carbon:[[@LINE+7]]:15: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: class D(b:! C(1_000)) {}\n// CHECK:STDERR:               ^~~~~\n// CHECK:STDERR: fail_int_mismatch.carbon:[[@LINE-4]]:15: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR: class D(b:! C(1000));\n// CHECK:STDERR:               ^~~~\n// CHECK:STDERR:\nclass D(b:! C(1_000)) {}\n\n// CHECK:STDOUT: --- int_match.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %a: %i32 = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.ad6: type = class_type @C, @C(%a) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_1000.ff9: Core.IntLiteral = int_value 1000 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1000.ff9, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1000.ff9, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1000.1b6: %i32 = int_value 1000 [concrete]\n// CHECK:STDOUT:   %C.a39: type = class_type @C, @C(%int_1000.1b6) [concrete]\n// CHECK:STDOUT:   %pattern_type.f44: type = pattern_type %C.a39 [concrete]\n// CHECK:STDOUT:   %b: %C.a39 = symbolic_binding b, 0 [symbolic]\n// CHECK:STDOUT:   %D.type: type = generic_class_type @D [concrete]\n// CHECK:STDOUT:   %D.generic: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D, @D(%b) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl.loc5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc4_9.2: %i32 = symbolic_binding a, 0 [symbolic = %a.loc4_9.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl.loc5: %D.type = class_decl @D [concrete = constants.%D.generic] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.f44 = symbolic_binding_pattern b, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_20.1: type = splice_block %C.loc5 [concrete = constants.%C.a39] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref.loc5: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:       %int_1000.loc5: Core.IntLiteral = int_value 1000 [concrete = constants.%int_1000.ff9]\n// CHECK:STDOUT:       %impl.elem0.loc5: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:       %bound_method.loc5_20.1: <bound method> = bound_method %int_1000.loc5, %impl.elem0.loc5 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:       %specific_fn.loc5: <specific function> = specific_function %impl.elem0.loc5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc5_20.2: <bound method> = bound_method %int_1000.loc5, %specific_fn.loc5 [concrete = constants.%bound_method]\n// CHECK:STDOUT:       %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5: init %i32 = call %bound_method.loc5_20.2(%int_1000.loc5) [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %.loc5_20.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5 [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %.loc5_20.3: %i32 = converted %int_1000.loc5, %.loc5_20.2 [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %C.loc5: type = class_type @C, @C(constants.%int_1000.1b6) [concrete = constants.%C.a39]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b.loc5_9.2: %C.a39 = symbolic_binding b, 0 [symbolic = %b.loc5_9.1 (constants.%b)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl.loc6: %D.type = class_decl @D [concrete = constants.%D.generic] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.f44 = symbolic_binding_pattern b, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_20.1: type = splice_block %C.loc6 [concrete = constants.%C.a39] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref.loc6: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:       %int_1000.loc6: Core.IntLiteral = int_value 1000 [concrete = constants.%int_1000.ff9]\n// CHECK:STDOUT:       %impl.elem0.loc6: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:       %bound_method.loc6_20.1: <bound method> = bound_method %int_1000.loc6, %impl.elem0.loc6 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:       %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc6_20.2: <bound method> = bound_method %int_1000.loc6, %specific_fn.loc6 [concrete = constants.%bound_method]\n// CHECK:STDOUT:       %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6: init %i32 = call %bound_method.loc6_20.2(%int_1000.loc6) [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %.loc6_20.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6 [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %.loc6_20.3: %i32 = converted %int_1000.loc6, %.loc6_20.2 [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %C.loc6: type = class_type @C, @C(constants.%int_1000.1b6) [concrete = constants.%C.a39]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b.loc6: %C.a39 = symbolic_binding b, 0 [symbolic = %b.loc5_9.1 (constants.%b)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%a.loc4_9.2: %i32) {\n// CHECK:STDOUT:   %a.loc4_9.1: %i32 = symbolic_binding a, 0 [symbolic = %a.loc4_9.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.ad6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @D(%b.loc5_9.2: %C.a39) {\n// CHECK:STDOUT:   %b.loc5_9.1: %C.a39 = symbolic_binding b, 0 [symbolic = %b.loc5_9.1 (constants.%b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%D\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%a) {\n// CHECK:STDOUT:   %a.loc4_9.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%int_1000.1b6) {\n// CHECK:STDOUT:   %a.loc4_9.1 => constants.%int_1000.1b6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D(constants.%b) {\n// CHECK:STDOUT:   %b.loc5_9.1 => constants.%b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_int_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %a: %i32 = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.ad6: type = class_type @C, @C(%a) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_1000.ff9: Core.IntLiteral = int_value 1000 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1000.ff9, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1000.ff9, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1000.1b6: %i32 = int_value 1000 [concrete]\n// CHECK:STDOUT:   %C.a39: type = class_type @C, @C(%int_1000.1b6) [concrete]\n// CHECK:STDOUT:   %pattern_type.f44: type = pattern_type %C.a39 [concrete]\n// CHECK:STDOUT:   %b: %C.a39 = symbolic_binding b, 0 [symbolic]\n// CHECK:STDOUT:   %D.type.6dc267.1: type = generic_class_type @D.loc5 [concrete]\n// CHECK:STDOUT:   %D.generic.3c4a9e.1: %D.type.6dc267.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %D.type.6dc267.2: type = generic_class_type @D.loc13 [concrete]\n// CHECK:STDOUT:   %D.generic.3c4a9e.2: %D.type.6dc267.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %D.54c2d1.2: type = class_type @D.loc13, @D.loc13(%b) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl.loc5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc4_9.2: %i32 = symbolic_binding a, 0 [symbolic = %a.loc4_9.1 (constants.%a)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl.loc5: %D.type.6dc267.1 = class_decl @D.loc5 [concrete = constants.%D.generic.3c4a9e.1] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.f44 = symbolic_binding_pattern b, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_19.1: type = splice_block %C [concrete = constants.%C.a39] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:       %int_1000: Core.IntLiteral = int_value 1000 [concrete = constants.%int_1000.ff9]\n// CHECK:STDOUT:       %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:       %bound_method.loc5_19.1: <bound method> = bound_method %int_1000, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:       %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc5_19.2: <bound method> = bound_method %int_1000, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:       %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc5_19.2(%int_1000) [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %.loc5_19.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %.loc5_19.3: %i32 = converted %int_1000, %.loc5_19.2 [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %C: type = class_type @C, @C(constants.%int_1000.1b6) [concrete = constants.%C.a39]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b.loc5_9.2: %C.a39 = symbolic_binding b, 0 [symbolic = %b.loc5_9.1 (constants.%b)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl.loc13: %D.type.6dc267.2 = class_decl @D.loc13 [concrete = constants.%D.generic.3c4a9e.2] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.f44 = symbolic_binding_pattern b, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc13_20.1: type = splice_block %C [concrete = constants.%C.a39] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:       %int_1000: Core.IntLiteral = int_value 1000 [concrete = constants.%int_1000.ff9]\n// CHECK:STDOUT:       %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:       %bound_method.loc13_20.1: <bound method> = bound_method %int_1000, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:       %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc13_20.2: <bound method> = bound_method %int_1000, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:       %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc13_20.2(%int_1000) [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %.loc13_20.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %.loc13_20.3: %i32 = converted %int_1000, %.loc13_20.2 [concrete = constants.%int_1000.1b6]\n// CHECK:STDOUT:       %C: type = class_type @C, @C(constants.%int_1000.1b6) [concrete = constants.%C.a39]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b.loc13_9.2: %C.a39 = symbolic_binding b, 0 [symbolic = %b.loc13_9.1 (constants.%b)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%a.loc4_9.2: %i32) {\n// CHECK:STDOUT:   %a.loc4_9.1: %i32 = symbolic_binding a, 0 [symbolic = %a.loc4_9.1 (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.ad6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @D.loc5(%b.loc5_9.2: %C.a39) {\n// CHECK:STDOUT:   %b.loc5_9.1: %C.a39 = symbolic_binding b, 0 [symbolic = %b.loc5_9.1 (constants.%b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @D.loc13(%b.loc13_9.2: %C.a39) {\n// CHECK:STDOUT:   %b.loc13_9.1: %C.a39 = symbolic_binding b, 0 [symbolic = %b.loc13_9.1 (constants.%b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%D.54c2d1.2\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%a) {\n// CHECK:STDOUT:   %a.loc4_9.1 => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%int_1000.1b6) {\n// CHECK:STDOUT:   %a.loc4_9.1 => constants.%int_1000.1b6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.loc5(constants.%b) {\n// CHECK:STDOUT:   %b.loc5_9.1 => constants.%b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.loc13(constants.%b) {\n// CHECK:STDOUT:   %b.loc13_9.1 => constants.%b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/class/virtual_modifiers.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/virtual_modifiers.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/virtual_modifiers.carbon\n\n// --- modifiers.carbon\n\npackage Modifiers;\n\nbase class Base {\n  virtual fn H[self: Self]();\n}\n\nabstract class Abstract {\n  abstract fn J[self: Self]();\n\n  virtual fn K[self: Self]();\n}\n\n// --- override_import.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Modifiers;\n\nclass Derived {\n  extend base: Modifiers.Base;\n  override fn H[self: Self]();\n}\n\nfn Use() {\n  var unused d: Derived = {.base = {}};\n}\n\n// --- todo_fail_later_base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Modifiers;\n\nbase class Derived {\n  virtual fn F[self: Self]();\n  extend base: Modifiers.Base;\n}\n\n// --- init.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Modifiers;\n\nfn F() {\n  var unused v: Modifiers.Base = {};\n}\n\n// --- impl_abstract.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class A1 {\n  virtual fn F[self: Self]();\n}\n\nabstract class A2 {\n  extend base: A1;\n  override fn F[self: Self]();\n}\n\n// --- impl_base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class B1 {\n  virtual fn F[self: Self]();\n}\n\nbase class B2 {\n  extend base: B1;\n  override fn F[self: Self]();\n}\n\nclass C {\n  extend base: B2;\n  override fn F[self: Self]();\n}\n\nfn Use() {\n  var unused b1: B1 = {};\n  var unused b2: B2 = {.base = {}};\n  var unused c: C = {.base = {.base = {}}};\n}\n\n// --- fail_modifiers.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:3: error: override without base class [OverrideWithoutBase]\n  // CHECK:STDERR:   override fn F[self: Self]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  override fn F[self: Self]();\n}\n\n// --- init_members.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base {\n  var m1: i32;\n  var m2: i32;\n\n  virtual fn F[self: Self]();\n}\n\nfn F() {\n  var i: i32 = 3;\n  var b1: Base = {.m2 = i, .m1 = i};\n  var unused b2: Base = {.m2 = 3, .m1 = 5};\n\n  b1.m2 = 4;\n}\n\n// --- fail_impl_without_base_declaration.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base {\n}\n\nclass Derived {\n  extend base: Base;\n  // CHECK:STDERR: fail_impl_without_base_declaration.carbon:[[@LINE+4]]:3: error: override without compatible virtual in base class [OverrideWithoutVirtualInBase]\n  // CHECK:STDERR:   override fn F[self: Self]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  override fn F[self: Self]();\n}\n\n// --- abstract_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class AbstractBase {\n  abstract fn F[self: Self]();\n}\n\nabstract class AbstractIntermediate {\n  extend base: AbstractBase;\n}\n\nclass Derived {\n  extend base: AbstractIntermediate;\n  override fn F[self: Self]();\n}\n\n// --- virtual_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class VirtualBase {\n  virtual fn F[self: Self]();\n}\n\nbase class VirtualIntermediate {\n  extend base: VirtualBase;\n}\n\nclass Derived {\n  extend base: VirtualIntermediate;\n  override fn F[self: Self]();\n}\n\n// --- fail_impl_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base {\n  virtual fn F[self: Self]();\n}\n\nclass Derived {\n  extend base: Base;\n  // CHECK:STDERR: fail_impl_mismatch.carbon:[[@LINE+7]]:3: error: redeclaration differs because of parameter count of 1 [RedeclParamCountDiffers]\n  // CHECK:STDERR:   override fn F[self: Self](v: i32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_impl_mismatch.carbon:[[@LINE-8]]:3: note: previously declared with parameter count of 0 [RedeclParamCountPrevious]\n  // CHECK:STDERR:   virtual fn F[self: Self]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  override fn F[self: Self](v: i32);\n}\n\n// --- fail_todo_impl_conversion.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass T1 {\n}\n\nclass T2 {\n}\n\nimpl T2 as Core.ImplicitAs(T1) {\n  fn Convert[unused self: Self]() -> T1 {\n    return {};\n  }\n}\n\nbase class Base {\n  virtual fn F[self: Self]() -> T1;\n}\n\nclass Derived {\n  extend base: Base;\n  // CHECK:STDERR: fail_todo_impl_conversion.carbon:[[@LINE+7]]:3: error: function redeclaration differs because return type is `T2` [FunctionRedeclReturnTypeDiffers]\n  // CHECK:STDERR:   override fn F[self: Self]() -> T2;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_impl_conversion.carbon:[[@LINE-8]]:3: note: previously declared with return type `T1` [FunctionRedeclReturnTypePrevious]\n  // CHECK:STDERR:   virtual fn F[self: Self]() -> T1;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  override fn F[self: Self]() -> T2;\n}\n\n// --- fail_generic_virtual_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_generic_virtual_decl.carbon:[[@LINE+3]]:1: error: use of undefined generic function [MissingGenericFunctionDefinition]\n// CHECK:STDERR: base class Base(T:! type) {\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\nbase class Base(T:! type) {\n  // CHECK:STDERR: fail_generic_virtual_decl.carbon:[[@LINE+4]]:3: note: generic function declared here [MissingGenericFunctionDefinitionHere]\n  // CHECK:STDERR:   virtual fn F[self: Self]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  virtual fn F[self: Self]();\n}\n\n\n// --- impl_generic_base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass T1 {\n}\n\nbase class Base(T:! type) {\n  virtual fn F[unused self: Self](unused t: T) { }\n}\n\nclass Derived {\n  extend base: Base(T1);\n  override fn F[unused self: Self](unused t: T1) { }\n}\n\n// --- fail_virtual_without_self.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class T1 {\n  // CHECK:STDERR: fail_virtual_without_self.carbon:[[@LINE+4]]:3: error: virtual class function [VirtualWithoutSelf]\n  // CHECK:STDERR:   virtual fn F();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  virtual fn F();\n  // CHECK:STDERR: fail_virtual_without_self.carbon:[[@LINE+4]]:3: error: virtual class function [VirtualWithoutSelf]\n  // CHECK:STDERR:   abstract fn G();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  abstract fn G();\n}\n\nclass T2 {\n  extend base: T1;\n  // CHECK:STDERR: fail_virtual_without_self.carbon:[[@LINE+4]]:3: error: virtual class function [VirtualWithoutSelf]\n  // CHECK:STDERR:   override fn F();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  override fn F();\n}\n\n// --- fail_ref_self_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class T1 {\n  virtual fn F1[self: Self]();\n}\n\nclass T2 {\n  extend base: T1;\n  // CHECK:STDERR: fail_ref_self_mismatch.carbon:[[@LINE+7]]:18: error: redeclaration differs at implicit parameter 1 [RedeclParamDiffers]\n  // CHECK:STDERR:   override fn F1[ref self: Self]();\n  // CHECK:STDERR:                  ^~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_ref_self_mismatch.carbon:[[@LINE-8]]:17: note: previous declaration's corresponding implicit parameter here [RedeclParamPrevious]\n  // CHECK:STDERR:   virtual fn F1[self: Self]();\n  // CHECK:STDERR:                 ^~~~~~~~~~\n  // CHECK:STDERR:\n  override fn F1[ref self: Self]();\n}\n\n// --- fail_generic_virtual.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class T1 {\n  // CHECK:STDERR: fail_generic_virtual.carbon:[[@LINE+4]]:3: error: generic virtual function [GenericVirtual]\n  // CHECK:STDERR:   virtual fn F[self: Self, T:! type]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  virtual fn F[self: Self, T:! type]();\n}\n\n// --- fail_generic_virtual_in_generic_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class T1(T:! type) {\n  // CHECK:STDERR: fail_generic_virtual_in_generic_class.carbon:[[@LINE+4]]:3: error: generic virtual function [GenericVirtual]\n  // CHECK:STDERR:   virtual fn F[self: Self, T:! type]();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  virtual fn F[self: Self, T:! type]();\n}\n\n// --- generic_with_virtual.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class T1(T:! type) {\n  virtual fn F[unused self: Self]() { }\n}\n\n// --- with_dependent_arg.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class T1(T:! type) {\n  virtual fn F[unused self: Self](unused t: T) { }\n}\n\n// --- vtable_import_unneeded.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Modifiers;\n\nfn F(b: Modifiers.Base);\n\n// --- generic_derived_from_nongeneric.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class NonGenericBase {\n  virtual fn F1[unused self: Self]() { }\n  virtual fn F2[unused self: Self]() { }\n}\n\nbase class GenericDerived(T:! type) {\n  extend base: NonGenericBase;\n  override fn F2[unused self: Self]() { }\n  virtual fn F3[unused self: Self]() { }\n}\n\n// --- nongeneric_derived_from_generic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class GenericBase(T:! type) {\n  virtual fn F1[unused self: Self]() { }\n  virtual fn F2[unused self: Self]() { }\n}\n\nclass T1;\n\nbase class NonGenericDerived {\n  extend base: GenericBase(T1);\n  override fn F2[unused self: Self]() { }\n  virtual fn F3[unused self: Self]() { }\n}\n\n// --- impl_generic_specifically.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base(T:! type) {\n  virtual fn F[unused self: Self](unused t: Base(T)*) { }\n}\nclass T1;\nclass D1 {\n  extend base: Base(T1);\n  override fn F[unused self: Self](unused t: Base(T1)*) { }\n}\n\n// --- fail_impl_generic_specifically_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass T1;\nclass T2;\n\nbase class Base(T:! type) {\n  virtual fn F[unused self: Self](unused t: T1*) { }\n}\n\nclass D1 {\n  extend base: Base(T1);\n  // CHECK:STDERR: fail_impl_generic_specifically_mismatch.carbon:[[@LINE+7]]:43: error: type `<pattern for T2*>` of parameter 1 in redeclaration differs from previous parameter type `<pattern for T1*>` [RedeclParamDiffersType]\n  // CHECK:STDERR:   override fn F[unused self: Self](unused t: T2*) { }\n  // CHECK:STDERR:                                           ^~~~~~\n  // CHECK:STDERR: fail_impl_generic_specifically_mismatch.carbon:[[@LINE-8]]:42: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n  // CHECK:STDERR:   virtual fn F[unused self: Self](unused t: T1*) { }\n  // CHECK:STDERR:                                          ^~~~~~\n  // CHECK:STDERR:\n  override fn F[unused self: Self](unused t: T2*) { }\n}\n\n// --- fail_impl_generic_generic_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Base(T:! type) {\n  virtual fn F[unused self: Self](unused t: T*) { }\n}\nclass Derived(T:! type) {\n  extend base: Base(T);\n  // CHECK:STDERR: fail_impl_generic_generic_mismatch.carbon:[[@LINE+7]]:43: error: type `<pattern for T>` of parameter 1 in redeclaration differs from previous parameter type `<pattern for T*>` [RedeclParamDiffersType]\n  // CHECK:STDERR:   override fn F[unused self: Self](unused t: T) { }\n  // CHECK:STDERR:                                           ^~~~\n  // CHECK:STDERR: fail_impl_generic_generic_mismatch.carbon:[[@LINE-7]]:42: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n  // CHECK:STDERR:   virtual fn F[unused self: Self](unused t: T*) { }\n  // CHECK:STDERR:                                          ^~~~~\n  // CHECK:STDERR:\n  override fn F[unused self: Self](unused t: T) { }\n}\n\n// --- impl_generic_generic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Base(T:! type) {\n  virtual fn F[unused self: Self](unused t: T) { }\n}\nclass Derived(T:! type) {\n  extend base: Base(T*);\n  override fn F[unused self: Self](unused t: T*) { }\n}\n\n// --- abstract_generic_undefined.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nabstract class Base(T:! type) {\n  abstract fn F[self: Self]();\n}\n\nclass T1;\n\nclass Derived {\n  extend base: Base(T1);\n  override fn F[unused self: Self]() { }\n}\n\n// --- generic_lib.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class Base(T:! type) {\n  virtual fn F[unused self: Self]() { }\n}\n\n// --- generic_import.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"generic_lib\";\n\nclass T1;\nvar v: Base(T1) = {};\n\n// --- generic_derived_generic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class T1(G1:! type) {\n  virtual fn F[unused self: Self]() { }\n}\n\nclass T2(G2:! type) {\n  extend base: T1(G2);\n}\n\n// --- generic_derived_generic_context.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class T1(G1:! type) {\n  virtual fn F[unused self: Self]() { }\n}\n\nclass T2(G2:! type) {\n  class T3 {\n    extend base : T1(G2);\n  }\n}\n\n\n// CHECK:STDOUT: --- modifiers.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %pattern_type.dec: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %Base.H.type: type = fn_type @Base.H [concrete]\n// CHECK:STDOUT:   %Base.H: %Base.H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %Abstract: type = class_type @Abstract [concrete]\n// CHECK:STDOUT:   %pattern_type.3c9: type = pattern_type %Abstract [concrete]\n// CHECK:STDOUT:   %Abstract.J.type: type = fn_type @Abstract.J [concrete]\n// CHECK:STDOUT:   %Abstract.J: %Abstract.J.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Abstract.K.type: type = fn_type @Abstract.K [concrete]\n// CHECK:STDOUT:   %Abstract.K: %Abstract.K.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Abstract.vtable_decl: ref %ptr = vtable_decl @Abstract.vtable [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Abstract = %Abstract.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Abstract.decl: type = class_decl @Abstract [concrete = constants.%Abstract] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %Base.H.decl: %Base.H.type = fn_decl @Base.H [concrete = constants.%Base.H] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.dec = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.dec = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Base = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self: %Base = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .H = %Base.H.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Abstract {\n// CHECK:STDOUT:   %Abstract.J.decl: %Abstract.J.type = fn_decl @Abstract.J [concrete = constants.%Abstract.J] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.3c9 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.3c9 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Abstract = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Abstract [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %self: %Abstract = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Abstract.K.decl: %Abstract.K.type = fn_decl @Abstract.K [concrete = constants.%Abstract.K] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.3c9 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.3c9 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Abstract = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Abstract [concrete = constants.%Abstract]\n// CHECK:STDOUT:     %self: %Abstract = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr = vtable_decl @Abstract.vtable [concrete = constants.%Abstract.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Abstract\n// CHECK:STDOUT:   .J = %Abstract.J.decl\n// CHECK:STDOUT:   .K = %Abstract.K.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.H.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Abstract.vtable {\n// CHECK:STDOUT:   @Abstract.%Abstract.J.decl\n// CHECK:STDOUT:   @Abstract.%Abstract.K.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @Base.H(%self.param: %Base);\n// CHECK:STDOUT:\n// CHECK:STDOUT: abstract fn @Abstract.J(%self.param: %Abstract);\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @Abstract.K(%self.param: %Abstract);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- override_import.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Derived.H.type: type = fn_type @Derived.H [concrete]\n// CHECK:STDOUT:   %Derived.H: %Derived.H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.H.type: type = fn_type @Base.H [concrete]\n// CHECK:STDOUT:   %Base.H: %Base.H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.96c: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.0e2: <witness> = complete_type_witness %struct_type.base.96c [concrete]\n// CHECK:STDOUT:   %Use.type: type = fn_type @Use [concrete]\n// CHECK:STDOUT:   %Use: %Use.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base.f5e: type = struct_type {.base: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %struct.6b1: %struct_type.base.f5e = struct_value (%empty_struct) [concrete]\n// CHECK:STDOUT:   %.a5d: type = partial_type %Base [concrete]\n// CHECK:STDOUT:   %uninit: %ptr.454 = uninitialized_value [concrete]\n// CHECK:STDOUT:   %struct.4dc: %.a5d = struct_value (%uninit) [concrete]\n// CHECK:STDOUT:   %Base.val: %Base = struct_value (%uninit) [concrete]\n// CHECK:STDOUT:   %Derived.val: %Derived = struct_value (%Base.val) [concrete]\n// CHECK:STDOUT:   %Derived.vtable_ptr: ref %ptr.454 = vtable_ptr @Derived.vtable [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Modifiers: <namespace> = namespace file.%Modifiers.import, [concrete] {\n// CHECK:STDOUT:     .Base = %Modifiers.Base\n// CHECK:STDOUT:     import Modifiers//default\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Modifiers.Base: type = import_ref Modifiers//default, Base, loaded [concrete = constants.%Base]\n// CHECK:STDOUT:   %Modifiers.import_ref.695: ref %ptr.454 = import_ref Modifiers//default, loc6_1, loaded [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:   %Modifiers.import_ref.05e: <witness> = import_ref Modifiers//default, loc6_1, loaded [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   %Modifiers.import_ref.d82 = import_ref Modifiers//default, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Modifiers.import_ref.d40 = import_ref Modifiers//default, loc5_29, unloaded\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Modifiers = imports.%Modifiers\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:     .Use = %Use.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Modifiers.import = import Modifiers\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT:   %Use.decl: %Use.type = fn_decl @Use [concrete = constants.%Use] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Modifiers.ref: <namespace> = name_ref Modifiers, imports.%Modifiers [concrete = imports.%Modifiers]\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, imports.%Modifiers.Base [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc7: %Derived.elem = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %Derived.H.decl: %Derived.H.type = fn_decl @Derived.H [concrete = constants.%Derived.H] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.96c [concrete = constants.%complete_type.0e2]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Modifiers = <poisoned>\n// CHECK:STDOUT:   .base = %.loc7\n// CHECK:STDOUT:   .H = %Derived.H.decl\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base [from \"modifiers.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Modifiers.import_ref.05e\n// CHECK:STDOUT:   vtable_decl = imports.%Modifiers.import_ref.695\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Modifiers.import_ref.d82\n// CHECK:STDOUT:   .H = imports.%Modifiers.import_ref.d40\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   constants.%Base.H\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   @Derived.%Derived.H.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @Derived.H(%self.param: %Derived);\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @Base.H [from \"modifiers.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.9f6 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.9f6 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %Derived = var %d.var_patt\n// CHECK:STDOUT:   %.loc12_37.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc12_38.1: %struct_type.base.f5e = struct_literal (%.loc12_37.1) [concrete = constants.%struct.6b1]\n// CHECK:STDOUT:   %.loc12_38.2: ref %.a5d = class_element_access %d.var, element0\n// CHECK:STDOUT:   %.loc12_37.2: ref %ptr.454 = class_element_access %.loc12_38.2, element0\n// CHECK:STDOUT:   %uninit: %ptr.454 = uninitialized_value [concrete = constants.%uninit]\n// CHECK:STDOUT:   %.loc12_37.3: init %ptr.454 to %.loc12_37.2 = in_place_init %uninit [concrete = constants.%uninit]\n// CHECK:STDOUT:   %.loc12_37.4: init %.a5d to %.loc12_38.2 = class_init (%.loc12_37.3) [concrete = constants.%struct.4dc]\n// CHECK:STDOUT:   %.loc12_38.3: init %.a5d = converted %.loc12_37.1, %.loc12_37.4 [concrete = constants.%struct.4dc]\n// CHECK:STDOUT:   %.loc12_38.4: init %Base = as_compatible %.loc12_38.3 [concrete = constants.%Base.val]\n// CHECK:STDOUT:   %.loc12_38.5: init %Derived to %d.var = class_init (%.loc12_38.4) [concrete = constants.%Derived.val]\n// CHECK:STDOUT:   %Derived.vtable_ptr: ref %ptr.454 = vtable_ptr @Derived.vtable [concrete = constants.%Derived.vtable_ptr]\n// CHECK:STDOUT:   %.loc12_38.6: ref %Base = class_element_access %d.var, element0\n// CHECK:STDOUT:   %.loc12_38.7: ref %ptr.454 = class_element_access %.loc12_38.6, element0\n// CHECK:STDOUT:   %.loc12_38.8: init %ptr.454 to %.loc12_38.7 = in_place_init %Derived.vtable_ptr [concrete = constants.%Derived.vtable_ptr]\n// CHECK:STDOUT:   %.loc12_38.9: init %Derived = update_init %.loc12_38.5, %.loc12_38.8\n// CHECK:STDOUT:   %.loc12_3: init %Derived = converted %.loc12_38.1, %.loc12_38.9\n// CHECK:STDOUT:   assign %d.var, %.loc12_3\n// CHECK:STDOUT:   %Derived.ref: type = name_ref Derived, file.%Derived.decl [concrete = constants.%Derived]\n// CHECK:STDOUT:   %d: ref %Derived = ref_binding d, %d.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %d.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%d.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Derived) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- todo_fail_later_base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F [concrete]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %Base.H.type: type = fn_type @Base.H [concrete]\n// CHECK:STDOUT:   %Base.H: %Base.H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.0e2: <witness> = complete_type_witness %struct_type.base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Modifiers: <namespace> = namespace file.%Modifiers.import, [concrete] {\n// CHECK:STDOUT:     .Base = %Modifiers.Base\n// CHECK:STDOUT:     import Modifiers//default\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Modifiers.Base: type = import_ref Modifiers//default, Base, loaded [concrete = constants.%Base]\n// CHECK:STDOUT:   %Modifiers.import_ref.695: ref %ptr.454 = import_ref Modifiers//default, loc6_1, loaded [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:   %Modifiers.import_ref.05e: <witness> = import_ref Modifiers//default, loc6_1, loaded [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   %Modifiers.import_ref.d82 = import_ref Modifiers//default, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Modifiers.import_ref.d40 = import_ref Modifiers//default, loc5_29, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Modifiers = imports.%Modifiers\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Modifiers.import = import Modifiers\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Derived.F.decl: %Derived.F.type = fn_decl @Derived.F [concrete = constants.%Derived.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Modifiers.ref: <namespace> = name_ref Modifiers, imports.%Modifiers [concrete = imports.%Modifiers]\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, imports.%Modifiers.Base [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc8: %Derived.elem = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base [concrete = constants.%complete_type.0e2]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .F = %Derived.F.decl\n// CHECK:STDOUT:   .Modifiers = <poisoned>\n// CHECK:STDOUT:   .base = %.loc8\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base [from \"modifiers.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Modifiers.import_ref.05e\n// CHECK:STDOUT:   vtable_decl = imports.%Modifiers.import_ref.695\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Modifiers.import_ref.d82\n// CHECK:STDOUT:   .H = imports.%Modifiers.import_ref.d40\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   constants.%Base.H\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   constants.%Base.H\n// CHECK:STDOUT:   @Derived.%Derived.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @Derived.F(%self.param: %Derived);\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @Base.H [from \"modifiers.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- init.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %pattern_type.80f: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.H.type: type = fn_type @Base.H [concrete]\n// CHECK:STDOUT:   %Base.H: %Base.H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %Base.vtable_ptr: ref %ptr.454 = vtable_ptr @Base.vtable [concrete]\n// CHECK:STDOUT:   %Base.val: %Base = struct_value (%Base.vtable_ptr) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Modifiers: <namespace> = namespace file.%Modifiers.import, [concrete] {\n// CHECK:STDOUT:     .Base = %Modifiers.Base\n// CHECK:STDOUT:     import Modifiers//default\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Modifiers.Base: type = import_ref Modifiers//default, Base, loaded [concrete = constants.%Base]\n// CHECK:STDOUT:   %Modifiers.import_ref.695: ref %ptr.454 = import_ref Modifiers//default, loc6_1, loaded [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:   %Modifiers.import_ref.05e: <witness> = import_ref Modifiers//default, loc6_1, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Modifiers.import_ref.d82 = import_ref Modifiers//default, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Modifiers.import_ref.d40 = import_ref Modifiers//default, loc5_29, unloaded\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Modifiers = imports.%Modifiers\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Modifiers.import = import Modifiers\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base [from \"modifiers.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Modifiers.import_ref.05e\n// CHECK:STDOUT:   vtable_decl = imports.%Modifiers.import_ref.695\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Modifiers.import_ref.d82\n// CHECK:STDOUT:   .H = imports.%Modifiers.import_ref.d40\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   constants.%Base.H\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.80f = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.80f = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %Base = var %v.var_patt\n// CHECK:STDOUT:   %.loc7_35.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc7_35.2: ref %ptr.454 = class_element_access %v.var, element0\n// CHECK:STDOUT:   %Base.vtable_ptr: ref %ptr.454 = vtable_ptr @Base.vtable [concrete = constants.%Base.vtable_ptr]\n// CHECK:STDOUT:   %.loc7_35.3: init %ptr.454 to %.loc7_35.2 = in_place_init %Base.vtable_ptr [concrete = constants.%Base.vtable_ptr]\n// CHECK:STDOUT:   %.loc7_35.4: init %Base to %v.var = class_init (%.loc7_35.3) [concrete = constants.%Base.val]\n// CHECK:STDOUT:   %.loc7_3: init %Base = converted %.loc7_35.1, %.loc7_35.4 [concrete = constants.%Base.val]\n// CHECK:STDOUT:   assign %v.var, %.loc7_3\n// CHECK:STDOUT:   %.loc7_26: type = splice_block %Base.ref [concrete = constants.%Base] {\n// CHECK:STDOUT:     %Modifiers.ref: <namespace> = name_ref Modifiers, imports.%Modifiers [concrete = imports.%Modifiers]\n// CHECK:STDOUT:     %Base.ref: type = name_ref Base, imports.%Modifiers.Base [concrete = constants.%Base]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %Base = ref_binding v, %v.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %v.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%v.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @Base.H [from \"modifiers.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Base) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- impl_abstract.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A1: type = class_type @A1 [concrete]\n// CHECK:STDOUT:   %pattern_type.258: type = pattern_type %A1 [concrete]\n// CHECK:STDOUT:   %A1.F.type: type = fn_type @A1.F [concrete]\n// CHECK:STDOUT:   %A1.F: %A1.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %A1.vtable_decl: ref %ptr.454 = vtable_decl @A1.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %A2: type = class_type @A2 [concrete]\n// CHECK:STDOUT:   %A2.elem: type = unbound_element_type %A2, %A1 [concrete]\n// CHECK:STDOUT:   %pattern_type.f23: type = pattern_type %A2 [concrete]\n// CHECK:STDOUT:   %A2.F.type: type = fn_type @A2.F [concrete]\n// CHECK:STDOUT:   %A2.F: %A2.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A2.vtable_decl: ref %ptr.454 = vtable_decl @A2.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %A1} [concrete]\n// CHECK:STDOUT:   %complete_type.0a6: <witness> = complete_type_witness %struct_type.base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A1 = %A1.decl\n// CHECK:STDOUT:     .A2 = %A2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A1.decl: type = class_decl @A1 [concrete = constants.%A1] {} {}\n// CHECK:STDOUT:   %A2.decl: type = class_decl @A2 [concrete = constants.%A2] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A1 {\n// CHECK:STDOUT:   %A1.F.decl: %A1.F.type = fn_decl @A1.F [concrete = constants.%A1.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.258 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.258 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %A1 = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%A1 [concrete = constants.%A1]\n// CHECK:STDOUT:     %self: %A1 = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @A1.vtable [concrete = constants.%A1.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A1\n// CHECK:STDOUT:   .F = %A1.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A2 {\n// CHECK:STDOUT:   %A1.ref: type = name_ref A1, file.%A1.decl [concrete = constants.%A1]\n// CHECK:STDOUT:   %.loc9: %A2.elem = base_decl %A1.ref, element0 [concrete]\n// CHECK:STDOUT:   %A2.F.decl: %A2.F.type = fn_decl @A2.F [concrete = constants.%A2.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.f23 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.f23 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %A2 = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%A2 [concrete = constants.%A2]\n// CHECK:STDOUT:     %self: %A2 = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @A2.vtable [concrete = constants.%A2.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base [concrete = constants.%complete_type.0a6]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A2\n// CHECK:STDOUT:   .A1 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .F = %A2.F.decl\n// CHECK:STDOUT:   extend %A1.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @A1.vtable {\n// CHECK:STDOUT:   @A1.%A1.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @A2.vtable {\n// CHECK:STDOUT:   @A2.%A2.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @A1.F(%self.param: %A1);\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @A2.F(%self.param: %A2);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- impl_base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B1: type = class_type @B1 [concrete]\n// CHECK:STDOUT:   %pattern_type.748: type = pattern_type %B1 [concrete]\n// CHECK:STDOUT:   %B1.F.type: type = fn_type @B1.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %B1.F: %B1.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %B1.vtable_decl: ref %ptr.454 = vtable_decl @B1.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %B2: type = class_type @B2 [concrete]\n// CHECK:STDOUT:   %B2.elem: type = unbound_element_type %B2, %B1 [concrete]\n// CHECK:STDOUT:   %pattern_type.8b5: type = pattern_type %B2 [concrete]\n// CHECK:STDOUT:   %B2.F.type: type = fn_type @B2.F [concrete]\n// CHECK:STDOUT:   %B2.F: %B2.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B2.vtable_decl: ref %ptr.454 = vtable_decl @B2.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.056: type = struct_type {.base: %B1} [concrete]\n// CHECK:STDOUT:   %complete_type.4f8: <witness> = complete_type_witness %struct_type.base.056 [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %B2 [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.vtable_decl: ref %ptr.454 = vtable_decl @C.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.812: type = struct_type {.base: %B2} [concrete]\n// CHECK:STDOUT:   %complete_type.909: <witness> = complete_type_witness %struct_type.base.812 [concrete]\n// CHECK:STDOUT:   %Use.type: type = fn_type @Use [concrete]\n// CHECK:STDOUT:   %Use: %Use.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %B1.vtable_ptr: ref %ptr.454 = vtable_ptr @B1.vtable [concrete]\n// CHECK:STDOUT:   %B1.val.d17: %B1 = struct_value (%B1.vtable_ptr) [concrete]\n// CHECK:STDOUT:   %struct_type.base.f5e: type = struct_type {.base: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %struct.6b1: %struct_type.base.f5e = struct_value (%empty_struct) [concrete]\n// CHECK:STDOUT:   %.5b3: type = partial_type %B1 [concrete]\n// CHECK:STDOUT:   %uninit: %ptr.454 = uninitialized_value [concrete]\n// CHECK:STDOUT:   %struct.571: %.5b3 = struct_value (%uninit) [concrete]\n// CHECK:STDOUT:   %B1.val.fd5: %B1 = struct_value (%uninit) [concrete]\n// CHECK:STDOUT:   %B2.val: %B2 = struct_value (%B1.val.fd5) [concrete]\n// CHECK:STDOUT:   %B2.vtable_ptr: ref %ptr.454 = vtable_ptr @B2.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.a0c: type = struct_type {.base: %struct_type.base.f5e} [concrete]\n// CHECK:STDOUT:   %struct.83e: %struct_type.base.a0c = struct_value (%struct.6b1) [concrete]\n// CHECK:STDOUT:   %.312: type = partial_type %B2 [concrete]\n// CHECK:STDOUT:   %struct.0cd: %.312 = struct_value (%B1.val.fd5) [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value (%B2.val) [concrete]\n// CHECK:STDOUT:   %C.vtable_ptr: ref %ptr.454 = vtable_ptr @C.vtable [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc21 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc20 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc19 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .B1 = %B1.decl\n// CHECK:STDOUT:     .B2 = %B2.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Use = %Use.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %B1.decl: type = class_decl @B1 [concrete = constants.%B1] {} {}\n// CHECK:STDOUT:   %B2.decl: type = class_decl @B2 [concrete = constants.%B2] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Use.decl: %Use.type = fn_decl @Use [concrete = constants.%Use] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B1 {\n// CHECK:STDOUT:   %B1.F.decl: %B1.F.type = fn_decl @B1.F [concrete = constants.%B1.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.748 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.748 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %B1 = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%B1 [concrete = constants.%B1]\n// CHECK:STDOUT:     %self: %B1 = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @B1.vtable [concrete = constants.%B1.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B1\n// CHECK:STDOUT:   .F = %B1.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B2 {\n// CHECK:STDOUT:   %B1.ref: type = name_ref B1, file.%B1.decl [concrete = constants.%B1]\n// CHECK:STDOUT:   %.loc9: %B2.elem = base_decl %B1.ref, element0 [concrete]\n// CHECK:STDOUT:   %B2.F.decl: %B2.F.type = fn_decl @B2.F [concrete = constants.%B2.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.8b5 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.8b5 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %B2 = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%B2 [concrete = constants.%B2]\n// CHECK:STDOUT:     %self: %B2 = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @B2.vtable [concrete = constants.%B2.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.056 [concrete = constants.%complete_type.4f8]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B2\n// CHECK:STDOUT:   .B1 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .F = %B2.F.decl\n// CHECK:STDOUT:   extend %B1.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %B2.ref: type = name_ref B2, file.%B2.decl [concrete = constants.%B2]\n// CHECK:STDOUT:   %.loc14: %C.elem = base_decl %B2.ref, element0 [concrete]\n// CHECK:STDOUT:   %C.F.decl: %C.F.type = fn_decl @C.F [concrete = constants.%C.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.7c7 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.7c7 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %C = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %self: %C = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @C.vtable [concrete = constants.%C.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.812 [concrete = constants.%complete_type.909]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .B2 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc14\n// CHECK:STDOUT:   .F = %C.F.decl\n// CHECK:STDOUT:   extend %B2.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @B1.vtable {\n// CHECK:STDOUT:   @B1.%B1.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @B2.vtable {\n// CHECK:STDOUT:   @B2.%B2.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @C.vtable {\n// CHECK:STDOUT:   @C.%C.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @B1.F(%self.param: %B1);\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @B2.F(%self.param: %B2);\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @C.F(%self.param: %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Use() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b1.patt: %pattern_type.748 = ref_binding_pattern b1 [concrete]\n// CHECK:STDOUT:     %b1.var_patt: %pattern_type.748 = var_pattern %b1.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b1.var: ref %B1 = var %b1.var_patt\n// CHECK:STDOUT:   %.loc19_24.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc19_24.2: ref %ptr.454 = class_element_access %b1.var, element0\n// CHECK:STDOUT:   %B1.vtable_ptr: ref %ptr.454 = vtable_ptr @B1.vtable [concrete = constants.%B1.vtable_ptr]\n// CHECK:STDOUT:   %.loc19_24.3: init %ptr.454 to %.loc19_24.2 = in_place_init %B1.vtable_ptr [concrete = constants.%B1.vtable_ptr]\n// CHECK:STDOUT:   %.loc19_24.4: init %B1 to %b1.var = class_init (%.loc19_24.3) [concrete = constants.%B1.val.d17]\n// CHECK:STDOUT:   %.loc19_3: init %B1 = converted %.loc19_24.1, %.loc19_24.4 [concrete = constants.%B1.val.d17]\n// CHECK:STDOUT:   assign %b1.var, %.loc19_3\n// CHECK:STDOUT:   %B1.ref: type = name_ref B1, file.%B1.decl [concrete = constants.%B1]\n// CHECK:STDOUT:   %b1: ref %B1 = ref_binding b1, %b1.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b2.patt: %pattern_type.8b5 = ref_binding_pattern b2 [concrete]\n// CHECK:STDOUT:     %b2.var_patt: %pattern_type.8b5 = var_pattern %b2.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b2.var: ref %B2 = var %b2.var_patt\n// CHECK:STDOUT:   %.loc20_33.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc20_34.1: %struct_type.base.f5e = struct_literal (%.loc20_33.1) [concrete = constants.%struct.6b1]\n// CHECK:STDOUT:   %.loc20_34.2: ref %.5b3 = class_element_access %b2.var, element0\n// CHECK:STDOUT:   %.loc20_33.2: ref %ptr.454 = class_element_access %.loc20_34.2, element0\n// CHECK:STDOUT:   %uninit.loc20: %ptr.454 = uninitialized_value [concrete = constants.%uninit]\n// CHECK:STDOUT:   %.loc20_33.3: init %ptr.454 to %.loc20_33.2 = in_place_init %uninit.loc20 [concrete = constants.%uninit]\n// CHECK:STDOUT:   %.loc20_33.4: init %.5b3 to %.loc20_34.2 = class_init (%.loc20_33.3) [concrete = constants.%struct.571]\n// CHECK:STDOUT:   %.loc20_34.3: init %.5b3 = converted %.loc20_33.1, %.loc20_33.4 [concrete = constants.%struct.571]\n// CHECK:STDOUT:   %.loc20_34.4: init %B1 = as_compatible %.loc20_34.3 [concrete = constants.%B1.val.fd5]\n// CHECK:STDOUT:   %.loc20_34.5: init %B2 to %b2.var = class_init (%.loc20_34.4) [concrete = constants.%B2.val]\n// CHECK:STDOUT:   %B2.vtable_ptr: ref %ptr.454 = vtable_ptr @B2.vtable [concrete = constants.%B2.vtable_ptr]\n// CHECK:STDOUT:   %.loc20_34.6: ref %B1 = class_element_access %b2.var, element0\n// CHECK:STDOUT:   %.loc20_34.7: ref %ptr.454 = class_element_access %.loc20_34.6, element0\n// CHECK:STDOUT:   %.loc20_34.8: init %ptr.454 to %.loc20_34.7 = in_place_init %B2.vtable_ptr [concrete = constants.%B2.vtable_ptr]\n// CHECK:STDOUT:   %.loc20_34.9: init %B2 = update_init %.loc20_34.5, %.loc20_34.8\n// CHECK:STDOUT:   %.loc20_3: init %B2 = converted %.loc20_34.1, %.loc20_34.9\n// CHECK:STDOUT:   assign %b2.var, %.loc20_3\n// CHECK:STDOUT:   %B2.ref: type = name_ref B2, file.%B2.decl [concrete = constants.%B2]\n// CHECK:STDOUT:   %b2: ref %B2 = ref_binding b2, %b2.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.7c7 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt\n// CHECK:STDOUT:   %.loc21_40.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc21_41.1: %struct_type.base.f5e = struct_literal (%.loc21_40.1) [concrete = constants.%struct.6b1]\n// CHECK:STDOUT:   %.loc21_42.1: %struct_type.base.a0c = struct_literal (%.loc21_41.1) [concrete = constants.%struct.83e]\n// CHECK:STDOUT:   %.loc21_42.2: ref %.312 = class_element_access %c.var, element0\n// CHECK:STDOUT:   %.loc21_41.2: ref %.5b3 = class_element_access %.loc21_42.2, element0\n// CHECK:STDOUT:   %.loc21_40.2: ref %ptr.454 = class_element_access %.loc21_41.2, element0\n// CHECK:STDOUT:   %uninit.loc21: %ptr.454 = uninitialized_value [concrete = constants.%uninit]\n// CHECK:STDOUT:   %.loc21_40.3: init %ptr.454 to %.loc21_40.2 = in_place_init %uninit.loc21 [concrete = constants.%uninit]\n// CHECK:STDOUT:   %.loc21_40.4: init %.5b3 to %.loc21_41.2 = class_init (%.loc21_40.3) [concrete = constants.%struct.571]\n// CHECK:STDOUT:   %.loc21_41.3: init %.5b3 = converted %.loc21_40.1, %.loc21_40.4 [concrete = constants.%struct.571]\n// CHECK:STDOUT:   %.loc21_41.4: init %B1 = as_compatible %.loc21_41.3 [concrete = constants.%B1.val.fd5]\n// CHECK:STDOUT:   %.loc21_41.5: init %.312 to %.loc21_42.2 = class_init (%.loc21_41.4) [concrete = constants.%struct.0cd]\n// CHECK:STDOUT:   %.loc21_42.3: init %.312 = converted %.loc21_41.1, %.loc21_41.5 [concrete = constants.%struct.0cd]\n// CHECK:STDOUT:   %.loc21_42.4: init %B2 = as_compatible %.loc21_42.3 [concrete = constants.%B2.val]\n// CHECK:STDOUT:   %.loc21_42.5: init %C to %c.var = class_init (%.loc21_42.4) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %C.vtable_ptr: ref %ptr.454 = vtable_ptr @C.vtable [concrete = constants.%C.vtable_ptr]\n// CHECK:STDOUT:   %.loc21_42.6: ref %B2 = class_element_access %c.var, element0\n// CHECK:STDOUT:   %.loc21_42.7: ref %B1 = class_element_access %.loc21_42.6, element0\n// CHECK:STDOUT:   %.loc21_42.8: ref %ptr.454 = class_element_access %.loc21_42.7, element0\n// CHECK:STDOUT:   %.loc21_42.9: init %ptr.454 to %.loc21_42.8 = in_place_init %C.vtable_ptr [concrete = constants.%C.vtable_ptr]\n// CHECK:STDOUT:   %.loc21_42.10: init %C = update_init %.loc21_42.5, %.loc21_42.9\n// CHECK:STDOUT:   %.loc21_3: init %C = converted %.loc21_42.1, %.loc21_42.10\n// CHECK:STDOUT:   assign %c.var, %.loc21_3\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc21: <bound method> = bound_method %c.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc21: init %empty_tuple.type = call %Destroy.Op.bound.loc21(%c.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc20: <bound method> = bound_method %b2.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc20: init %empty_tuple.type = call %Destroy.Op.bound.loc20(%b2.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc19: <bound method> = bound_method %b1.var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc19: init %empty_tuple.type = call %Destroy.Op.bound.loc19(%b1.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc21(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc20(%self.param: ref %B2) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc19(%self.param: ref %B1) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_modifiers.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %C.F.decl: %C.F.type = fn_decl @C.F [concrete = constants.%C.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %C = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %self: %C = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .F = %C.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @C.F(%self.param: %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- init_members.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Base.elem: type = unbound_element_type %Base, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.101: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F [concrete]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr.m1.m2: type = struct_type {.<vptr>: %ptr.454, .m1: %i32, .m2: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.cf7: <witness> = complete_type_witness %struct_type.vptr.m1.m2 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %struct_type.m2.m1.68c: type = struct_type {.m2: %i32, .m1: %i32} [concrete]\n// CHECK:STDOUT:   %Base.vtable_ptr: ref %ptr.454 = vtable_ptr @Base.vtable [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %int_5.64b: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %struct_type.m2.m1.5f2: type = struct_type {.m2: Core.IntLiteral, .m1: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.m2.m1.5f2 = struct_value (%int_3.1ba, %int_5.64b) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.e9d: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_5.0f6: %i32 = int_value 5 [concrete]\n// CHECK:STDOUT:   %Base.val: %Base = struct_value (%Base.vtable_ptr, %int_5.0f6, %int_3.822) [concrete]\n// CHECK:STDOUT:   %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.6d7: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_4.940: %i32 = int_value 4 [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc14 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc12 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %Base.elem = field_decl m1, element1 [concrete]\n// CHECK:STDOUT:   %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc6: %Base.elem = field_decl m2, element2 [concrete]\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type = fn_decl @Base.F [concrete = constants.%Base.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Base = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self: %Base = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr.m1.m2 [concrete = constants.%complete_type.cf7]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .m1 = %.loc5\n// CHECK:STDOUT:   .m2 = %.loc6\n// CHECK:STDOUT:   .F = %Base.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @Base.F(%self.param: %Base);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %i.patt: %pattern_type.7ce = ref_binding_pattern i [concrete]\n// CHECK:STDOUT:     %i.var_patt: %pattern_type.7ce = var_pattern %i.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i.var: ref %i32 = var %i.var_patt\n// CHECK:STDOUT:   %int_3.loc12: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %impl.elem0.loc12: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc12_3.1: <bound method> = bound_method %int_3.loc12, %impl.elem0.loc12 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:   %specific_fn.loc12: <specific function> = specific_function %impl.elem0.loc12, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc12_3.2: <bound method> = bound_method %int_3.loc12, %specific_fn.loc12 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc12: init %i32 = call %bound_method.loc12_3.2(%int_3.loc12) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc12: init %i32 = converted %int_3.loc12, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc12 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   assign %i.var, %.loc12\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %i: ref %i32 = ref_binding i, %i.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b1.patt: %pattern_type.101 = ref_binding_pattern b1 [concrete]\n// CHECK:STDOUT:     %b1.var_patt: %pattern_type.101 = var_pattern %b1.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b1.var: ref %Base = var %b1.var_patt\n// CHECK:STDOUT:   %i.ref.loc13_25: ref %i32 = name_ref i, %i\n// CHECK:STDOUT:   %i.ref.loc13_34: ref %i32 = name_ref i, %i\n// CHECK:STDOUT:   %.loc13_35.1: %struct_type.m2.m1.68c = struct_literal (%i.ref.loc13_25, %i.ref.loc13_34)\n// CHECK:STDOUT:   %.loc13_35.2: ref %ptr.454 = class_element_access %b1.var, element0\n// CHECK:STDOUT:   %Base.vtable_ptr.loc13: ref %ptr.454 = vtable_ptr @Base.vtable [concrete = constants.%Base.vtable_ptr]\n// CHECK:STDOUT:   %.loc13_35.3: init %ptr.454 to %.loc13_35.2 = in_place_init %Base.vtable_ptr.loc13 [concrete = constants.%Base.vtable_ptr]\n// CHECK:STDOUT:   %.loc13_34: %i32 = acquire_value %i.ref.loc13_34\n// CHECK:STDOUT:   %impl.elem0.loc13_34: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc13_34.1: <bound method> = bound_method %.loc13_34, %impl.elem0.loc13_34\n// CHECK:STDOUT:   %specific_fn.loc13_34: <specific function> = specific_function %impl.elem0.loc13_34, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_34.2: <bound method> = bound_method %.loc13_34, %specific_fn.loc13_34\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc13_34: init %i32 = call %bound_method.loc13_34.2(%.loc13_34)\n// CHECK:STDOUT:   %.loc13_35.4: ref %i32 = class_element_access %b1.var, element2\n// CHECK:STDOUT:   %.loc13_35.5: init %i32 to %.loc13_35.4 = in_place_init %Int.as.Copy.impl.Op.call.loc13_34\n// CHECK:STDOUT:   %.loc13_25: %i32 = acquire_value %i.ref.loc13_25\n// CHECK:STDOUT:   %impl.elem0.loc13_25: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc13_25.1: <bound method> = bound_method %.loc13_25, %impl.elem0.loc13_25\n// CHECK:STDOUT:   %specific_fn.loc13_25: <specific function> = specific_function %impl.elem0.loc13_25, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_25.2: <bound method> = bound_method %.loc13_25, %specific_fn.loc13_25\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc13_25: init %i32 = call %bound_method.loc13_25.2(%.loc13_25)\n// CHECK:STDOUT:   %.loc13_35.6: ref %i32 = class_element_access %b1.var, element1\n// CHECK:STDOUT:   %.loc13_35.7: init %i32 to %.loc13_35.6 = in_place_init %Int.as.Copy.impl.Op.call.loc13_25\n// CHECK:STDOUT:   %.loc13_35.8: init %Base to %b1.var = class_init (%.loc13_35.3, %.loc13_35.5, %.loc13_35.7)\n// CHECK:STDOUT:   %.loc13_3: init %Base = converted %.loc13_35.1, %.loc13_35.8\n// CHECK:STDOUT:   assign %b1.var, %.loc13_3\n// CHECK:STDOUT:   %Base.ref.loc13: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %b1: ref %Base = ref_binding b1, %b1.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b2.patt: %pattern_type.101 = ref_binding_pattern b2 [concrete]\n// CHECK:STDOUT:     %b2.var_patt: %pattern_type.101 = var_pattern %b2.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b2.var: ref %Base = var %b2.var_patt\n// CHECK:STDOUT:   %int_3.loc14: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %.loc14_42.1: %struct_type.m2.m1.5f2 = struct_literal (%int_3.loc14, %int_5) [concrete = constants.%struct]\n// CHECK:STDOUT:   %.loc14_42.2: ref %ptr.454 = class_element_access %b2.var, element0\n// CHECK:STDOUT:   %Base.vtable_ptr.loc14: ref %ptr.454 = vtable_ptr @Base.vtable [concrete = constants.%Base.vtable_ptr]\n// CHECK:STDOUT:   %.loc14_42.3: init %ptr.454 to %.loc14_42.2 = in_place_init %Base.vtable_ptr.loc14 [concrete = constants.%Base.vtable_ptr]\n// CHECK:STDOUT:   %impl.elem0.loc14_42.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc14_42.1: <bound method> = bound_method %int_5, %impl.elem0.loc14_42.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005]\n// CHECK:STDOUT:   %specific_fn.loc14_42.1: <specific function> = specific_function %impl.elem0.loc14_42.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_42.2: <bound method> = bound_method %int_5, %specific_fn.loc14_42.1 [concrete = constants.%bound_method.e9d]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_42.1: init %i32 = call %bound_method.loc14_42.2(%int_5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc14_42.4: init %i32 = converted %int_5, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_42.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc14_42.5: ref %i32 = class_element_access %b2.var, element2\n// CHECK:STDOUT:   %.loc14_42.6: init %i32 to %.loc14_42.5 = in_place_init %.loc14_42.4 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %impl.elem0.loc14_42.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc14_42.3: <bound method> = bound_method %int_3.loc14, %impl.elem0.loc14_42.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:   %specific_fn.loc14_42.2: <specific function> = specific_function %impl.elem0.loc14_42.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_42.4: <bound method> = bound_method %int_3.loc14, %specific_fn.loc14_42.2 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_42.2: init %i32 = call %bound_method.loc14_42.4(%int_3.loc14) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc14_42.7: init %i32 = converted %int_3.loc14, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14_42.2 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc14_42.8: ref %i32 = class_element_access %b2.var, element1\n// CHECK:STDOUT:   %.loc14_42.9: init %i32 to %.loc14_42.8 = in_place_init %.loc14_42.7 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc14_42.10: init %Base to %b2.var = class_init (%.loc14_42.3, %.loc14_42.6, %.loc14_42.9) [concrete = constants.%Base.val]\n// CHECK:STDOUT:   %.loc14_3: init %Base = converted %.loc14_42.1, %.loc14_42.10 [concrete = constants.%Base.val]\n// CHECK:STDOUT:   assign %b2.var, %.loc14_3\n// CHECK:STDOUT:   %Base.ref.loc14: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %b2: ref %Base = ref_binding b2, %b2.var\n// CHECK:STDOUT:   %b1.ref: ref %Base = name_ref b1, %b1\n// CHECK:STDOUT:   %m2.ref: %Base.elem = name_ref m2, @Base.%.loc6 [concrete = @Base.%.loc6]\n// CHECK:STDOUT:   %.loc16_5: ref %i32 = class_element_access %b1.ref, element2\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]\n// CHECK:STDOUT:   %impl.elem0.loc16: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc16_9.1: <bound method> = bound_method %int_4, %impl.elem0.loc16 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c]\n// CHECK:STDOUT:   %specific_fn.loc16: <specific function> = specific_function %impl.elem0.loc16, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_9.2: <bound method> = bound_method %int_4, %specific_fn.loc16 [concrete = constants.%bound_method.6d7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16: init %i32 = call %bound_method.loc16_9.2(%int_4) [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc16_9: init %i32 = converted %int_4, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   assign %.loc16_5, %.loc16_9\n// CHECK:STDOUT:   %Destroy.Op.bound.loc14: <bound method> = bound_method %b2.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc14: init %empty_tuple.type = call %Destroy.Op.bound.loc14(%b2.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13: <bound method> = bound_method %b1.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc13: init %empty_tuple.type = call %Destroy.Op.bound.loc13(%b1.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc12: <bound method> = bound_method %i.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc12: init %empty_tuple.type = call %Destroy.Op.bound.loc12(%i.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc14(%self.param: ref %Base) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc12(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_without_base_declaration.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F [concrete]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr.base: type = struct_type {.<vptr>: %ptr.454, .base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.8aa: <witness> = complete_type_witness %struct_type.vptr.base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc8: %Derived.elem = base_decl %Base.ref, element1 [concrete]\n// CHECK:STDOUT:   %Derived.F.decl: %Derived.F.type = fn_decl @Derived.F [concrete = constants.%Derived.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr.base [concrete = constants.%complete_type.8aa]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc8\n// CHECK:STDOUT:   .F = %Derived.F.decl\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- abstract_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %AbstractBase: type = class_type @AbstractBase [concrete]\n// CHECK:STDOUT:   %pattern_type.079: type = pattern_type %AbstractBase [concrete]\n// CHECK:STDOUT:   %AbstractBase.F.type: type = fn_type @AbstractBase.F [concrete]\n// CHECK:STDOUT:   %AbstractBase.F: %AbstractBase.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %AbstractBase.vtable_decl: ref %ptr.454 = vtable_decl @AbstractBase.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %AbstractIntermediate: type = class_type @AbstractIntermediate [concrete]\n// CHECK:STDOUT:   %AbstractIntermediate.elem: type = unbound_element_type %AbstractIntermediate, %AbstractBase [concrete]\n// CHECK:STDOUT:   %AbstractIntermediate.vtable_decl: ref %ptr.454 = vtable_decl @AbstractIntermediate.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.48d: type = struct_type {.base: %AbstractBase} [concrete]\n// CHECK:STDOUT:   %complete_type.cae: <witness> = complete_type_witness %struct_type.base.48d [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %AbstractIntermediate [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F [concrete]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.493: type = struct_type {.base: %AbstractIntermediate} [concrete]\n// CHECK:STDOUT:   %complete_type.944: <witness> = complete_type_witness %struct_type.base.493 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .AbstractBase = %AbstractBase.decl\n// CHECK:STDOUT:     .AbstractIntermediate = %AbstractIntermediate.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %AbstractBase.decl: type = class_decl @AbstractBase [concrete = constants.%AbstractBase] {} {}\n// CHECK:STDOUT:   %AbstractIntermediate.decl: type = class_decl @AbstractIntermediate [concrete = constants.%AbstractIntermediate] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AbstractBase {\n// CHECK:STDOUT:   %AbstractBase.F.decl: %AbstractBase.F.type = fn_decl @AbstractBase.F [concrete = constants.%AbstractBase.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.079 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.079 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %AbstractBase = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%AbstractBase [concrete = constants.%AbstractBase]\n// CHECK:STDOUT:     %self: %AbstractBase = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @AbstractBase.vtable [concrete = constants.%AbstractBase.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AbstractBase\n// CHECK:STDOUT:   .F = %AbstractBase.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @AbstractIntermediate {\n// CHECK:STDOUT:   %AbstractBase.ref: type = name_ref AbstractBase, file.%AbstractBase.decl [concrete = constants.%AbstractBase]\n// CHECK:STDOUT:   %.loc9: %AbstractIntermediate.elem = base_decl %AbstractBase.ref, element0 [concrete]\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @AbstractIntermediate.vtable [concrete = constants.%AbstractIntermediate.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.48d [concrete = constants.%complete_type.cae]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%AbstractIntermediate\n// CHECK:STDOUT:   .AbstractBase = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   extend %AbstractBase.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %AbstractIntermediate.ref: type = name_ref AbstractIntermediate, file.%AbstractIntermediate.decl [concrete = constants.%AbstractIntermediate]\n// CHECK:STDOUT:   %.loc13: %Derived.elem = base_decl %AbstractIntermediate.ref, element0 [concrete]\n// CHECK:STDOUT:   %Derived.F.decl: %Derived.F.type = fn_decl @Derived.F [concrete = constants.%Derived.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.493 [concrete = constants.%complete_type.944]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .AbstractIntermediate = <poisoned>\n// CHECK:STDOUT:   .base = %.loc13\n// CHECK:STDOUT:   .F = %Derived.F.decl\n// CHECK:STDOUT:   extend %AbstractIntermediate.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @AbstractBase.vtable {\n// CHECK:STDOUT:   @AbstractBase.%AbstractBase.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @AbstractIntermediate.vtable {\n// CHECK:STDOUT:   constants.%AbstractBase.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   @Derived.%Derived.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: abstract fn @AbstractBase.F(%self.param: %AbstractBase);\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- virtual_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %VirtualBase: type = class_type @VirtualBase [concrete]\n// CHECK:STDOUT:   %pattern_type.012: type = pattern_type %VirtualBase [concrete]\n// CHECK:STDOUT:   %VirtualBase.F.type: type = fn_type @VirtualBase.F [concrete]\n// CHECK:STDOUT:   %VirtualBase.F: %VirtualBase.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %VirtualBase.vtable_decl: ref %ptr.454 = vtable_decl @VirtualBase.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %VirtualIntermediate: type = class_type @VirtualIntermediate [concrete]\n// CHECK:STDOUT:   %VirtualIntermediate.elem: type = unbound_element_type %VirtualIntermediate, %VirtualBase [concrete]\n// CHECK:STDOUT:   %VirtualIntermediate.vtable_decl: ref %ptr.454 = vtable_decl @VirtualIntermediate.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.d36: type = struct_type {.base: %VirtualBase} [concrete]\n// CHECK:STDOUT:   %complete_type.e60: <witness> = complete_type_witness %struct_type.base.d36 [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %VirtualIntermediate [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F [concrete]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.cec: type = struct_type {.base: %VirtualIntermediate} [concrete]\n// CHECK:STDOUT:   %complete_type.4c0: <witness> = complete_type_witness %struct_type.base.cec [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .VirtualBase = %VirtualBase.decl\n// CHECK:STDOUT:     .VirtualIntermediate = %VirtualIntermediate.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %VirtualBase.decl: type = class_decl @VirtualBase [concrete = constants.%VirtualBase] {} {}\n// CHECK:STDOUT:   %VirtualIntermediate.decl: type = class_decl @VirtualIntermediate [concrete = constants.%VirtualIntermediate] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @VirtualBase {\n// CHECK:STDOUT:   %VirtualBase.F.decl: %VirtualBase.F.type = fn_decl @VirtualBase.F [concrete = constants.%VirtualBase.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.012 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.012 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %VirtualBase = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%VirtualBase [concrete = constants.%VirtualBase]\n// CHECK:STDOUT:     %self: %VirtualBase = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @VirtualBase.vtable [concrete = constants.%VirtualBase.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%VirtualBase\n// CHECK:STDOUT:   .F = %VirtualBase.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @VirtualIntermediate {\n// CHECK:STDOUT:   %VirtualBase.ref: type = name_ref VirtualBase, file.%VirtualBase.decl [concrete = constants.%VirtualBase]\n// CHECK:STDOUT:   %.loc9: %VirtualIntermediate.elem = base_decl %VirtualBase.ref, element0 [concrete]\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @VirtualIntermediate.vtable [concrete = constants.%VirtualIntermediate.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.d36 [concrete = constants.%complete_type.e60]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%VirtualIntermediate\n// CHECK:STDOUT:   .VirtualBase = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   extend %VirtualBase.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %VirtualIntermediate.ref: type = name_ref VirtualIntermediate, file.%VirtualIntermediate.decl [concrete = constants.%VirtualIntermediate]\n// CHECK:STDOUT:   %.loc13: %Derived.elem = base_decl %VirtualIntermediate.ref, element0 [concrete]\n// CHECK:STDOUT:   %Derived.F.decl: %Derived.F.type = fn_decl @Derived.F [concrete = constants.%Derived.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.cec [concrete = constants.%complete_type.4c0]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .VirtualIntermediate = <poisoned>\n// CHECK:STDOUT:   .base = %.loc13\n// CHECK:STDOUT:   .F = %Derived.F.decl\n// CHECK:STDOUT:   extend %VirtualIntermediate.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @VirtualBase.vtable {\n// CHECK:STDOUT:   @VirtualBase.%VirtualBase.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @VirtualIntermediate.vtable {\n// CHECK:STDOUT:   constants.%VirtualBase.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   @Derived.%Derived.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @VirtualBase.F(%self.param: %VirtualBase);\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %pattern_type.101: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F [concrete]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F [concrete]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.5a1: <witness> = complete_type_witness %struct_type.base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type = fn_decl @Base.F [concrete = constants.%Base.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Base = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self: %Base = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .F = %Base.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc9: %Derived.elem = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %Derived.F.decl: %Derived.F.type = fn_decl @Derived.F [concrete = constants.%Derived.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %v.patt: %pattern_type.7ce = value_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.param_patt: %pattern_type.7ce = value_param_pattern %v.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:     %v.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %v: %i32 = value_binding v, %v.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base [concrete = constants.%complete_type.5a1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .F = %Derived.F.decl\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   @Derived.%Derived.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @Base.F(%self.param: %Base);\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived, %v.param: %i32);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_impl_conversion.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %T2: type = class_type @T2 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.8c9: type = facet_type <@ImplicitAs, @ImplicitAs(%T1)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness @T2.as.ImplicitAs.impl.%ImplicitAs.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.b8b: type = pattern_type %T2 [concrete]\n// CHECK:STDOUT:   %.a53: Core.Form = init_form %T1 [concrete]\n// CHECK:STDOUT:   %pattern_type.818: type = pattern_type %T1 [concrete]\n// CHECK:STDOUT:   %T2.as.ImplicitAs.impl.Convert.type: type = fn_type @T2.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %T2.as.ImplicitAs.impl.Convert: %T2.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %T1.val: %T1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %pattern_type.101: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F [concrete]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %.c13: Core.Form = init_form %T2 [concrete]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F [concrete]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %Base} [concrete]\n// CHECK:STDOUT:   %complete_type.5a1: <witness> = complete_type_witness %struct_type.base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .T2 = %T2.decl\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT:   %T2.decl: type = class_decl @T2 [concrete = constants.%T2] {} {}\n// CHECK:STDOUT:   impl_decl @T2.as.ImplicitAs.impl [concrete] {} {\n// CHECK:STDOUT:     %T2.ref: type = name_ref T2, file.%T2.decl [concrete = constants.%T2]\n// CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %ImplicitAs.ref: %ImplicitAs.type.cc7 = name_ref ImplicitAs, imports.%Core.ImplicitAs [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:     %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:     %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%T1)> [concrete = constants.%ImplicitAs.type.8c9]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Base.decl: type = class_decl @Base [concrete = constants.%Base] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @T2.as.ImplicitAs.impl: %T2.ref as %ImplicitAs.type {\n// CHECK:STDOUT:   %T2.as.ImplicitAs.impl.Convert.decl: %T2.as.ImplicitAs.impl.Convert.type = fn_decl @T2.as.ImplicitAs.impl.Convert [concrete = constants.%T2.as.ImplicitAs.impl.Convert] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.b8b = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.b8b = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.818 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.818 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:     %.loc11: Core.Form = init_form %T1.ref [concrete = constants.%.a53]\n// CHECK:STDOUT:     %self.param: %T2 = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @T2.as.ImplicitAs.impl.%T2.ref [concrete = constants.%T2]\n// CHECK:STDOUT:     %self: %T2 = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %T1 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %T1 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%T2.as.ImplicitAs.impl.Convert.decl), @T2.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness %ImplicitAs.impl_witness_table [concrete = constants.%ImplicitAs.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .T1 = <poisoned>\n// CHECK:STDOUT:   .Convert = %T2.as.ImplicitAs.impl.Convert.decl\n// CHECK:STDOUT:   witness = %ImplicitAs.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%T1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T2 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%T2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base {\n// CHECK:STDOUT:   %Base.F.decl: %Base.F.type = fn_decl @Base.F [concrete = constants.%Base.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.101 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.101 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.818 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.818 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:     %.loc17: Core.Form = init_form %T1.ref [concrete = constants.%.a53]\n// CHECK:STDOUT:     %self.param: %Base = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Base [concrete = constants.%Base]\n// CHECK:STDOUT:     %self: %Base = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %T1 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %T1 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Base\n// CHECK:STDOUT:   .T1 = <poisoned>\n// CHECK:STDOUT:   .F = %Base.F.decl\n// CHECK:STDOUT:   .T2 = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: type = name_ref Base, file.%Base.decl [concrete = constants.%Base]\n// CHECK:STDOUT:   %.loc21: %Derived.elem = base_decl %Base.ref, element0 [concrete]\n// CHECK:STDOUT:   %Derived.F.decl: %Derived.F.type = fn_decl @Derived.F [concrete = constants.%Derived.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.b8b = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.b8b = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T2.ref: type = name_ref T2, file.%T2.decl [concrete = constants.%T2]\n// CHECK:STDOUT:     %.loc29: Core.Form = init_form %T2.ref [concrete = constants.%.c13]\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %T2 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %T2 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base [concrete = constants.%complete_type.5a1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .base = %.loc21\n// CHECK:STDOUT:   .T2 = <poisoned>\n// CHECK:STDOUT:   .F = %Derived.F.decl\n// CHECK:STDOUT:   extend %Base.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   @Derived.%Derived.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @T2.as.ImplicitAs.impl.Convert(%self.param: %T2) -> out %return.param: %T1 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc12_13.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc12_13.2: init %T1 to %return.param = class_init () [concrete = constants.%T1.val]\n// CHECK:STDOUT:   %.loc12_14: init %T1 = converted %.loc12_13.1, %.loc12_13.2 [concrete = constants.%T1.val]\n// CHECK:STDOUT:   return %.loc12_14 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @Base.F(%self.param: %Base) -> out %return.param: %T1;\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived) -> out %return.param: %T2;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_generic_virtual_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.2f0: type = pattern_type %Base [symbolic]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn: <specific function> = specific_function %Base.F, @Base.F(%T) [symbolic]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: %Base.type = class_decl @Base [concrete = constants.%Base.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_21.1: type = splice_block %.loc7_21.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_21.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_17.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_17.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(%T.loc7_17.2: type) {\n// CHECK:STDOUT:   %T.loc7_17.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_17.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T.loc7_17.1) [symbolic = %Base.F.type (constants.%Base.F.type)]\n// CHECK:STDOUT:   %Base.F: @Base.%Base.F.type (%Base.F.type) = struct_value () [symbolic = %Base.F (constants.%Base.F)]\n// CHECK:STDOUT:   %Base.F.specific_fn.loc13_1.2: <specific function> = specific_function %Base.F, @Base.F(%T.loc7_17.1) [symbolic = %Base.F.specific_fn.loc13_1.2 (constants.%Base.F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.F.decl: @Base.%Base.F.type (%Base.F.type) = fn_decl @Base.F [symbolic = @Base.%Base.F (constants.%Base.F)] {\n// CHECK:STDOUT:       %self.patt: @Base.F.%pattern_type (%pattern_type.2f0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Base.F.%pattern_type (%pattern_type.2f0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Base.F.%Base (%Base) = value_param call_param0\n// CHECK:STDOUT:       %.loc12_22.1: type = splice_block %Self.ref [symbolic = %Base (constants.%Base)] {\n// CHECK:STDOUT:         %.loc12_22.2: type = specific_constant constants.%Base, @Base(constants.%T) [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc12_22.2 [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Base.F.%Base (%Base) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Base.F.specific_fn.loc13_1.1: <specific function> = specific_function %Base.F.decl, @Base.F(constants.%T) [symbolic = %Base.F.specific_fn.loc13_1.2 (constants.%Base.F.specific_fn)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Base\n// CHECK:STDOUT:     .F = %Base.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.specific_fn.loc13_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @Base.F(@Base.%T.loc7_17.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Base [symbolic = %pattern_type (constants.%pattern_type.2f0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @Base.F.%Base (%Base));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_17.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Base => constants.%Base\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.2f0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- impl_generic_base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.d0c: type = class_type @Base, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.2f0: type = pattern_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %Base.F.type.0f1: type = fn_type @Base.F, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F.cd3: %Base.F.type.0f1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.f8c: <specific function> = specific_function %Base.F.cd3, @Base.F(%T) [symbolic]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete.1e0: <witness> = require_complete_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Base.d5d: type = class_type @Base, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.type.cb1: type = fn_type @Base.F, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.eab: %Base.F.type.cb1 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.64f: type = pattern_type %Base.d5d [concrete]\n// CHECK:STDOUT:   %pattern_type.818: type = pattern_type %T1 [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.cd5: <specific function> = specific_function %Base.F.eab, @Base.F(%T1) [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base.d5d [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F [concrete]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.cc2: type = struct_type {.base: %Base.d5d} [concrete]\n// CHECK:STDOUT:   %complete_type.dcb: <witness> = complete_type_witness %struct_type.base.cc2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT:   %Base.decl: %Base.type = class_decl @Base [concrete = constants.%Base.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_21.1: type = splice_block %.loc7_21.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_21.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_17.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_17.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%T1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(%T.loc7_17.2: type) {\n// CHECK:STDOUT:   %T.loc7_17.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_17.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T.loc7_17.1) [symbolic = %Base.F.type (constants.%Base.F.type.0f1)]\n// CHECK:STDOUT:   %Base.F: @Base.%Base.F.type (%Base.F.type.0f1) = struct_value () [symbolic = %Base.F (constants.%Base.F.cd3)]\n// CHECK:STDOUT:   %Base.F.specific_fn.loc9_1.2: <specific function> = specific_function %Base.F, @Base.F(%T.loc7_17.1) [symbolic = %Base.F.specific_fn.loc9_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.F.decl: @Base.%Base.F.type (%Base.F.type.0f1) = fn_decl @Base.F [symbolic = @Base.%Base.F (constants.%Base.F.cd3)] {\n// CHECK:STDOUT:       %self.patt: @Base.F.%pattern_type.loc8_23 (%pattern_type.2f0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Base.F.%pattern_type.loc8_23 (%pattern_type.2f0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: @Base.F.%pattern_type.loc8_42 (%pattern_type.51d) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: @Base.F.%pattern_type.loc8_42 (%pattern_type.51d) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Base.F.%Base (%Base.d0c) = value_param call_param0\n// CHECK:STDOUT:       %.loc8_29.1: type = splice_block %Self.ref [symbolic = %Base (constants.%Base.d0c)] {\n// CHECK:STDOUT:         %.loc8_29.2: type = specific_constant constants.%Base.d0c, @Base(constants.%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc8_29.2 [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Base.F.%Base (%Base.d0c) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: @Base.F.%T (%T) = value_param call_param1\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Base.%T.loc7_17.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %t: @Base.F.%T (%T) = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Base.F.specific_fn.loc9_1.1: <specific function> = specific_function %Base.F.decl, @Base.F(constants.%T) [symbolic = %Base.F.specific_fn.loc9_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Base.d0c\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %Base.F.decl\n// CHECK:STDOUT:     .T1 = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: %Base.type = name_ref Base, file.%Base.decl [concrete = constants.%Base.generic]\n// CHECK:STDOUT:   %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(constants.%T1) [concrete = constants.%Base.d5d]\n// CHECK:STDOUT:   %.loc12: %Derived.elem = base_decl %Base, element0 [concrete]\n// CHECK:STDOUT:   %Derived.F.decl: %Derived.F.type = fn_decl @Derived.F [concrete = constants.%Derived.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %t.patt: %pattern_type.818 = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: %pattern_type.818 = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:     %t.param: %T1 = value_param call_param1\n// CHECK:STDOUT:     %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:     %t: %T1 = value_binding t, %t.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.cc2 [concrete = constants.%complete_type.dcb]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .T1 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc12\n// CHECK:STDOUT:   .F = %Derived.F.decl\n// CHECK:STDOUT:   extend %Base\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.specific_fn.loc9_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   @Derived.%Derived.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @Base.F(@Base.%T.loc7_17.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:   %pattern_type.loc8_23: type = pattern_type %Base [symbolic = %pattern_type.loc8_23 (constants.%pattern_type.2f0)]\n// CHECK:STDOUT:   %pattern_type.loc8_42: type = pattern_type %T [symbolic = %pattern_type.loc8_42 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc8_27: <witness> = require_complete_type %Base [symbolic = %require_complete.loc8_27 (constants.%require_complete.1e0)]\n// CHECK:STDOUT:   %require_complete.loc8_43: <witness> = require_complete_type %T [symbolic = %require_complete.loc8_43 (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @Base.F.%Base (%Base.d0c), %t.param: @Base.F.%T (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived, %t.param: %T1) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_17.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.0f1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.cd3\n// CHECK:STDOUT:   %Base.F.specific_fn.loc9_1.2 => constants.%Base.F.specific_fn.f8c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Base => constants.%Base.d0c\n// CHECK:STDOUT:   %pattern_type.loc8_23 => constants.%pattern_type.2f0\n// CHECK:STDOUT:   %pattern_type.loc8_42 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc8_27 => constants.%require_complete.1e0\n// CHECK:STDOUT:   %require_complete.loc8_43 => constants.%require_complete.944\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T1) {\n// CHECK:STDOUT:   %T.loc7_17.1 => constants.%T1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.cb1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.eab\n// CHECK:STDOUT:   %Base.F.specific_fn.loc9_1.2 => constants.%Base.F.specific_fn.cd5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T1) {\n// CHECK:STDOUT:   %T => constants.%T1\n// CHECK:STDOUT:   %Base => constants.%Base.d5d\n// CHECK:STDOUT:   %pattern_type.loc8_23 => constants.%pattern_type.64f\n// CHECK:STDOUT:   %pattern_type.loc8_42 => constants.%pattern_type.818\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc8_27 => constants.%complete_type.513\n// CHECK:STDOUT:   %require_complete.loc8_43 => constants.%complete_type.357\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_virtual_without_self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F [concrete]\n// CHECK:STDOUT:   %T1.F: %T1.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T1.G.type: type = fn_type @T1.G [concrete]\n// CHECK:STDOUT:   %T1.G: %T1.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %T2: type = class_type @T2 [concrete]\n// CHECK:STDOUT:   %T2.elem: type = unbound_element_type %T2, %T1 [concrete]\n// CHECK:STDOUT:   %T2.F.type: type = fn_type @T2.F [concrete]\n// CHECK:STDOUT:   %T2.F: %T2.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %T1} [concrete]\n// CHECK:STDOUT:   %complete_type.ad3: <witness> = complete_type_witness %struct_type.base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .T2 = %T2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT:   %T2.decl: type = class_decl @T2 [concrete = constants.%T2] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1 {\n// CHECK:STDOUT:   %T1.F.decl: %T1.F.type = fn_decl @T1.F [concrete = constants.%T1.F] {} {}\n// CHECK:STDOUT:   %T1.G.decl: %T1.G.type = fn_decl @T1.G [concrete = constants.%T1.G] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%T1\n// CHECK:STDOUT:   .F = %T1.F.decl\n// CHECK:STDOUT:   .G = %T1.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T2 {\n// CHECK:STDOUT:   %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:   %.loc18: %T2.elem = base_decl %T1.ref, element0 [concrete]\n// CHECK:STDOUT:   %T2.F.decl: %T2.F.type = fn_decl @T2.F [concrete = constants.%T2.F] {} {}\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base [concrete = constants.%complete_type.ad3]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%T2\n// CHECK:STDOUT:   .T1 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc18\n// CHECK:STDOUT:   .F = %T2.F.decl\n// CHECK:STDOUT:   extend %T1.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @T1.F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @T1.G();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @T2.F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_ref_self_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %pattern_type.818: type = pattern_type %T1 [concrete]\n// CHECK:STDOUT:   %T1.F1.type: type = fn_type @T1.F1 [concrete]\n// CHECK:STDOUT:   %T1.F1: %T1.F1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %T1.vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %T2: type = class_type @T2 [concrete]\n// CHECK:STDOUT:   %T2.elem: type = unbound_element_type %T2, %T1 [concrete]\n// CHECK:STDOUT:   %pattern_type.b8b: type = pattern_type %T2 [concrete]\n// CHECK:STDOUT:   %T2.F1.type: type = fn_type @T2.F1 [concrete]\n// CHECK:STDOUT:   %T2.F1: %T2.F1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T2.vtable_decl: ref %ptr.454 = vtable_decl @T2.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %T1} [concrete]\n// CHECK:STDOUT:   %complete_type.ad3: <witness> = complete_type_witness %struct_type.base [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .T2 = %T2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT:   %T2.decl: type = class_decl @T2 [concrete = constants.%T2] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1 {\n// CHECK:STDOUT:   %T1.F1.decl: %T1.F1.type = fn_decl @T1.F1 [concrete = constants.%T1.F1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.818 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.818 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %T1 = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%T1 [concrete = constants.%T1]\n// CHECK:STDOUT:     %self: %T1 = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete = constants.%T1.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%T1\n// CHECK:STDOUT:   .F1 = %T1.F1.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T2 {\n// CHECK:STDOUT:   %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:   %.loc9: %T2.elem = base_decl %T1.ref, element0 [concrete]\n// CHECK:STDOUT:   %T2.F1.decl: %T2.F1.type = fn_decl @T2.F1 [concrete = constants.%T2.F1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.b8b = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.b8b = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: ref %T2 = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%T2 [concrete = constants.%T2]\n// CHECK:STDOUT:     %self: ref %T2 = ref_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @T2.vtable [concrete = constants.%T2.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base [concrete = constants.%complete_type.ad3]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%T2\n// CHECK:STDOUT:   .T1 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .F1 = %T2.F1.decl\n// CHECK:STDOUT:   extend %T1.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @T1.vtable {\n// CHECK:STDOUT:   @T1.%T1.F1.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @T2.vtable {\n// CHECK:STDOUT:   @T2.%T2.F1.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @T1.F1(%self.param: %T1);\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @T2.F1(%self.param: ref %T2);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_generic_virtual.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %pattern_type.818: type = pattern_type %T1 [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F [concrete]\n// CHECK:STDOUT:   %T1.F: %T1.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1 {\n// CHECK:STDOUT:   %T1.F.decl: %T1.F.type = fn_decl @T1.F [concrete = constants.%T1.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.818 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.818 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %T1 = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%T1 [concrete = constants.%T1]\n// CHECK:STDOUT:     %self: %T1 = value_binding self, %self.param\n// CHECK:STDOUT:     %.loc9_32.1: type = splice_block %.loc9_32.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc9_32.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9_28.2: type = symbolic_binding T, 0 [symbolic = %T.loc9_28.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%T1\n// CHECK:STDOUT:   .F = %T1.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @T1.F(%T.loc9_28.2: type) {\n// CHECK:STDOUT:   %T.loc9_28.1: type = symbolic_binding T, 0 [symbolic = %T.loc9_28.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: %T1);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1.F(constants.%T) {\n// CHECK:STDOUT:   %T.loc9_28.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_generic_virtual_in_generic_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T1.type: type = generic_class_type @T1 [concrete]\n// CHECK:STDOUT:   %T1.generic: %T1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T1: type = class_type @T1, @T1(%T.67d) [symbolic]\n// CHECK:STDOUT:   %pattern_type.253: type = pattern_type %T1 [symbolic]\n// CHECK:STDOUT:   %T.091: type = symbolic_binding T, 1 [symbolic]\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%T.67d) [symbolic]\n// CHECK:STDOUT:   %T1.F: %T1.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: %T1.type = class_decl @T1 [concrete = constants.%T1.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @T1(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%T.loc4_15.1) [symbolic = %T1.F.type (constants.%T1.F.type)]\n// CHECK:STDOUT:   %T1.F: @T1.%T1.F.type (%T1.F.type) = struct_value () [symbolic = %T1.F (constants.%T1.F)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T1.F.decl: @T1.%T1.F.type (%T1.F.type) = fn_decl @T1.F [symbolic = @T1.%T1.F (constants.%T1.F)] {\n// CHECK:STDOUT:       %self.patt: @T1.F.%pattern_type (%pattern_type.253) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @T1.F.%pattern_type (%pattern_type.253) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 1 [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @T1.F.%T1 (%T1) = value_param call_param0\n// CHECK:STDOUT:       %.loc9_22.1: type = splice_block %Self.ref [symbolic = %T1 (constants.%T1)] {\n// CHECK:STDOUT:         %.loc9_22.2: type = specific_constant constants.%T1, @T1(constants.%T.67d) [symbolic = %T1 (constants.%T1)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc9_22.2 [symbolic = %T1 (constants.%T1)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @T1.F.%T1 (%T1) = value_binding self, %self.param\n// CHECK:STDOUT:       %.loc9_32.1: type = splice_block %.loc9_32.2 [concrete = type] {\n// CHECK:STDOUT:         %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:         %.loc9_32.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %T.loc9_28.2: type = symbolic_binding T, 1 [symbolic = %T.loc9_28.1 (constants.%T.091)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%T1\n// CHECK:STDOUT:     .F = %T1.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @T1.F(@T1.%T.loc4_15.2: type, %T.loc9_28.2: type) {\n// CHECK:STDOUT:   %T.loc9_22: type = symbolic_binding T, 0 [symbolic = %T.loc9_22 (constants.%T.67d)]\n// CHECK:STDOUT:   %T1: type = class_type @T1, @T1(%T.loc9_22) [symbolic = %T1 (constants.%T1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T1 [symbolic = %pattern_type (constants.%pattern_type.253)]\n// CHECK:STDOUT:   %T.loc9_28.1: type = symbolic_binding T, 1 [symbolic = %T.loc9_28.1 (constants.%T.091)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @T1.F.%T1 (%T1));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1.F(constants.%T.67d, constants.%T.091) {\n// CHECK:STDOUT:   %T.loc9_22 => constants.%T.67d\n// CHECK:STDOUT:   %T1 => constants.%T1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.253\n// CHECK:STDOUT:   %T.loc9_28.1 => constants.%T.091\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- generic_with_virtual.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T1.type: type = generic_class_type @T1 [concrete]\n// CHECK:STDOUT:   %T1.generic: %T1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T1: type = class_type @T1, @T1(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.253: type = pattern_type %T1 [symbolic]\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%T) [symbolic]\n// CHECK:STDOUT:   %T1.F: %T1.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %T1.F.specific_fn: <specific function> = specific_function %T1.F, @T1.F(%T) [symbolic]\n// CHECK:STDOUT:   %T1.vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T1 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: %T1.type = class_decl @T1 [concrete = constants.%T1.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @T1(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%T.loc4_15.1) [symbolic = %T1.F.type (constants.%T1.F.type)]\n// CHECK:STDOUT:   %T1.F: @T1.%T1.F.type (%T1.F.type) = struct_value () [symbolic = %T1.F (constants.%T1.F)]\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2: <specific function> = specific_function %T1.F, @T1.F(%T.loc4_15.1) [symbolic = %T1.F.specific_fn.loc6_1.2 (constants.%T1.F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T1.F.decl: @T1.%T1.F.type (%T1.F.type) = fn_decl @T1.F [symbolic = @T1.%T1.F (constants.%T1.F)] {\n// CHECK:STDOUT:       %self.patt: @T1.F.%pattern_type (%pattern_type.253) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @T1.F.%pattern_type (%pattern_type.253) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @T1.F.%T1 (%T1) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_29.1: type = splice_block %Self.ref [symbolic = %T1 (constants.%T1)] {\n// CHECK:STDOUT:         %.loc5_29.2: type = specific_constant constants.%T1, @T1(constants.%T) [symbolic = %T1 (constants.%T1)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_29.2 [symbolic = %T1 (constants.%T1)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @T1.F.%T1 (%T1) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T1.F.specific_fn.loc6_1.1: <specific function> = specific_function %T1.F.decl, @T1.F(constants.%T) [symbolic = %T1.F.specific_fn.loc6_1.2 (constants.%T1.F.specific_fn)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete = constants.%T1.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%T1\n// CHECK:STDOUT:     .F = %T1.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @T1.vtable {\n// CHECK:STDOUT:   @T1.%T1.F.specific_fn.loc6_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @T1.F(@T1.%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %T1: type = class_type @T1, @T1(%T) [symbolic = %T1 (constants.%T1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T1 [symbolic = %pattern_type (constants.%pattern_type.253)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @T1.F.%T1 (%T1)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type => constants.%T1.F.type\n// CHECK:STDOUT:   %T1.F => constants.%T1.F\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2 => constants.%T1.F.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %T1 => constants.%T1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.253\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- with_dependent_arg.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T1.type: type = generic_class_type @T1 [concrete]\n// CHECK:STDOUT:   %T1.generic: %T1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T1: type = class_type @T1, @T1(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.253: type = pattern_type %T1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%T) [symbolic]\n// CHECK:STDOUT:   %T1.F: %T1.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %T1.F.specific_fn: <specific function> = specific_function %T1.F, @T1.F(%T) [symbolic]\n// CHECK:STDOUT:   %T1.vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete.6d2: <witness> = require_complete_type %T1 [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: %T1.type = class_decl @T1 [concrete = constants.%T1.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @T1(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%T.loc4_15.1) [symbolic = %T1.F.type (constants.%T1.F.type)]\n// CHECK:STDOUT:   %T1.F: @T1.%T1.F.type (%T1.F.type) = struct_value () [symbolic = %T1.F (constants.%T1.F)]\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2: <specific function> = specific_function %T1.F, @T1.F(%T.loc4_15.1) [symbolic = %T1.F.specific_fn.loc6_1.2 (constants.%T1.F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T1.F.decl: @T1.%T1.F.type (%T1.F.type) = fn_decl @T1.F [symbolic = @T1.%T1.F (constants.%T1.F)] {\n// CHECK:STDOUT:       %self.patt: @T1.F.%pattern_type.loc5_23 (%pattern_type.253) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @T1.F.%pattern_type.loc5_23 (%pattern_type.253) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: @T1.F.%pattern_type.loc5_42 (%pattern_type.51d) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: @T1.F.%pattern_type.loc5_42 (%pattern_type.51d) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @T1.F.%T1 (%T1) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_29.1: type = splice_block %Self.ref [symbolic = %T1 (constants.%T1)] {\n// CHECK:STDOUT:         %.loc5_29.2: type = specific_constant constants.%T1, @T1(constants.%T) [symbolic = %T1 (constants.%T1)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_29.2 [symbolic = %T1 (constants.%T1)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @T1.F.%T1 (%T1) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: @T1.F.%T (%T) = value_param call_param1\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @T1.%T.loc4_15.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %t: @T1.F.%T (%T) = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T1.F.specific_fn.loc6_1.1: <specific function> = specific_function %T1.F.decl, @T1.F(constants.%T) [symbolic = %T1.F.specific_fn.loc6_1.2 (constants.%T1.F.specific_fn)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete = constants.%T1.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%T1\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %T1.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @T1.vtable {\n// CHECK:STDOUT:   @T1.%T1.F.specific_fn.loc6_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @T1.F(@T1.%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %T1: type = class_type @T1, @T1(%T) [symbolic = %T1 (constants.%T1)]\n// CHECK:STDOUT:   %pattern_type.loc5_23: type = pattern_type %T1 [symbolic = %pattern_type.loc5_23 (constants.%pattern_type.253)]\n// CHECK:STDOUT:   %pattern_type.loc5_42: type = pattern_type %T [symbolic = %pattern_type.loc5_42 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27: <witness> = require_complete_type %T1 [symbolic = %require_complete.loc5_27 (constants.%require_complete.6d2)]\n// CHECK:STDOUT:   %require_complete.loc5_43: <witness> = require_complete_type %T [symbolic = %require_complete.loc5_43 (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @T1.F.%T1 (%T1), %t.param: @T1.F.%T (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type => constants.%T1.F.type\n// CHECK:STDOUT:   %T1.F => constants.%T1.F\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2 => constants.%T1.F.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %T1 => constants.%T1\n// CHECK:STDOUT:   %pattern_type.loc5_23 => constants.%pattern_type.253\n// CHECK:STDOUT:   %pattern_type.loc5_42 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27 => constants.%require_complete.6d2\n// CHECK:STDOUT:   %require_complete.loc5_43 => constants.%require_complete.944\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- vtable_import_unneeded.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Base: type = class_type @Base [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Base [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Modifiers: <namespace> = namespace file.%Modifiers.import, [concrete] {\n// CHECK:STDOUT:     .Base = %Modifiers.Base\n// CHECK:STDOUT:     import Modifiers//default\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Modifiers.Base: type = import_ref Modifiers//default, Base, loaded [concrete = constants.%Base]\n// CHECK:STDOUT:   %Modifiers.import_ref.d80231.2 = import_ref Modifiers//default, loc6_1, unloaded\n// CHECK:STDOUT:   %Modifiers.import_ref.05e: <witness> = import_ref Modifiers//default, loc6_1, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Modifiers.import_ref.d82 = import_ref Modifiers//default, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Modifiers.import_ref.d40 = import_ref Modifiers//default, loc5_29, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Modifiers = imports.%Modifiers\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Modifiers.import = import Modifiers\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %b.patt: %pattern_type = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %b.param: %Base = value_param call_param0\n// CHECK:STDOUT:     %.loc6: type = splice_block %Base.ref [concrete = constants.%Base] {\n// CHECK:STDOUT:       %Modifiers.ref: <namespace> = name_ref Modifiers, imports.%Modifiers [concrete = imports.%Modifiers]\n// CHECK:STDOUT:       %Base.ref: type = name_ref Base, imports.%Modifiers.Base [concrete = constants.%Base]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b: %Base = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Base [from \"modifiers.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Modifiers.import_ref.05e\n// CHECK:STDOUT:   vtable_decl = imports.%Modifiers.import_ref.d80231.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Modifiers.import_ref.d82\n// CHECK:STDOUT:   .H = imports.%Modifiers.import_ref.d40\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%b.param: %Base);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- generic_derived_from_nongeneric.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %NonGenericBase: type = class_type @NonGenericBase [concrete]\n// CHECK:STDOUT:   %pattern_type.126: type = pattern_type %NonGenericBase [concrete]\n// CHECK:STDOUT:   %NonGenericBase.F1.type: type = fn_type @NonGenericBase.F1 [concrete]\n// CHECK:STDOUT:   %NonGenericBase.F1: %NonGenericBase.F1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %NonGenericBase.F2.type: type = fn_type @NonGenericBase.F2 [concrete]\n// CHECK:STDOUT:   %NonGenericBase.F2: %NonGenericBase.F2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %NonGenericBase.vtable_decl: ref %ptr.454 = vtable_decl @NonGenericBase.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %GenericDerived.type: type = generic_class_type @GenericDerived [concrete]\n// CHECK:STDOUT:   %GenericDerived.generic: %GenericDerived.type = struct_value () [concrete]\n// CHECK:STDOUT:   %GenericDerived: type = class_type @GenericDerived, @GenericDerived(%T) [symbolic]\n// CHECK:STDOUT:   %GenericDerived.elem: type = unbound_element_type %GenericDerived, %NonGenericBase [symbolic]\n// CHECK:STDOUT:   %pattern_type.945: type = pattern_type %GenericDerived [symbolic]\n// CHECK:STDOUT:   %GenericDerived.F2.type: type = fn_type @GenericDerived.F2, @GenericDerived(%T) [symbolic]\n// CHECK:STDOUT:   %GenericDerived.F2: %GenericDerived.F2.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %GenericDerived.F3.type: type = fn_type @GenericDerived.F3, @GenericDerived(%T) [symbolic]\n// CHECK:STDOUT:   %GenericDerived.F3: %GenericDerived.F3.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %GenericDerived.F2.specific_fn: <specific function> = specific_function %GenericDerived.F2, @GenericDerived.F2(%T) [symbolic]\n// CHECK:STDOUT:   %GenericDerived.F3.specific_fn: <specific function> = specific_function %GenericDerived.F3, @GenericDerived.F3(%T) [symbolic]\n// CHECK:STDOUT:   %GenericDerived.vtable_decl: ref %ptr.454 = vtable_decl @GenericDerived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.66e: type = struct_type {.base: %NonGenericBase} [concrete]\n// CHECK:STDOUT:   %complete_type.a92: <witness> = complete_type_witness %struct_type.base.66e [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %GenericDerived [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .NonGenericBase = %NonGenericBase.decl\n// CHECK:STDOUT:     .GenericDerived = %GenericDerived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %NonGenericBase.decl: type = class_decl @NonGenericBase [concrete = constants.%NonGenericBase] {} {}\n// CHECK:STDOUT:   %GenericDerived.decl: %GenericDerived.type = class_decl @GenericDerived [concrete = constants.%GenericDerived.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_31.1: type = splice_block %.loc9_31.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc9_31.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9_27.2: type = symbolic_binding T, 0 [symbolic = %T.loc9_27.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @NonGenericBase {\n// CHECK:STDOUT:   %NonGenericBase.F1.decl: %NonGenericBase.F1.type = fn_decl @NonGenericBase.F1 [concrete = constants.%NonGenericBase.F1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.126 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.126 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %NonGenericBase = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%NonGenericBase [concrete = constants.%NonGenericBase]\n// CHECK:STDOUT:     %self: %NonGenericBase = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %NonGenericBase.F2.decl: %NonGenericBase.F2.type = fn_decl @NonGenericBase.F2 [concrete = constants.%NonGenericBase.F2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.126 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.126 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %NonGenericBase = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%NonGenericBase [concrete = constants.%NonGenericBase]\n// CHECK:STDOUT:     %self: %NonGenericBase = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @NonGenericBase.vtable [concrete = constants.%NonGenericBase.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%NonGenericBase\n// CHECK:STDOUT:   .F1 = %NonGenericBase.F1.decl\n// CHECK:STDOUT:   .F2 = %NonGenericBase.F2.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @GenericDerived(%T.loc9_27.2: type) {\n// CHECK:STDOUT:   %T.loc9_27.1: type = symbolic_binding T, 0 [symbolic = %T.loc9_27.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %GenericDerived: type = class_type @GenericDerived, @GenericDerived(%T.loc9_27.1) [symbolic = %GenericDerived (constants.%GenericDerived)]\n// CHECK:STDOUT:   %GenericDerived.elem: type = unbound_element_type %GenericDerived, constants.%NonGenericBase [symbolic = %GenericDerived.elem (constants.%GenericDerived.elem)]\n// CHECK:STDOUT:   %GenericDerived.F2.type: type = fn_type @GenericDerived.F2, @GenericDerived(%T.loc9_27.1) [symbolic = %GenericDerived.F2.type (constants.%GenericDerived.F2.type)]\n// CHECK:STDOUT:   %GenericDerived.F2: @GenericDerived.%GenericDerived.F2.type (%GenericDerived.F2.type) = struct_value () [symbolic = %GenericDerived.F2 (constants.%GenericDerived.F2)]\n// CHECK:STDOUT:   %GenericDerived.F3.type: type = fn_type @GenericDerived.F3, @GenericDerived(%T.loc9_27.1) [symbolic = %GenericDerived.F3.type (constants.%GenericDerived.F3.type)]\n// CHECK:STDOUT:   %GenericDerived.F3: @GenericDerived.%GenericDerived.F3.type (%GenericDerived.F3.type) = struct_value () [symbolic = %GenericDerived.F3 (constants.%GenericDerived.F3)]\n// CHECK:STDOUT:   %GenericDerived.F2.specific_fn.loc13_1.2: <specific function> = specific_function %GenericDerived.F2, @GenericDerived.F2(%T.loc9_27.1) [symbolic = %GenericDerived.F2.specific_fn.loc13_1.2 (constants.%GenericDerived.F2.specific_fn)]\n// CHECK:STDOUT:   %GenericDerived.F3.specific_fn.loc13_1.2: <specific function> = specific_function %GenericDerived.F3, @GenericDerived.F3(%T.loc9_27.1) [symbolic = %GenericDerived.F3.specific_fn.loc13_1.2 (constants.%GenericDerived.F3.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %NonGenericBase.ref: type = name_ref NonGenericBase, file.%NonGenericBase.decl [concrete = constants.%NonGenericBase]\n// CHECK:STDOUT:     %.loc10: @GenericDerived.%GenericDerived.elem (%GenericDerived.elem) = base_decl %NonGenericBase.ref, element0 [concrete]\n// CHECK:STDOUT:     %GenericDerived.F2.decl: @GenericDerived.%GenericDerived.F2.type (%GenericDerived.F2.type) = fn_decl @GenericDerived.F2 [symbolic = @GenericDerived.%GenericDerived.F2 (constants.%GenericDerived.F2)] {\n// CHECK:STDOUT:       %self.patt: @GenericDerived.F2.%pattern_type (%pattern_type.945) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @GenericDerived.F2.%pattern_type (%pattern_type.945) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @GenericDerived.F2.%GenericDerived (%GenericDerived) = value_param call_param0\n// CHECK:STDOUT:       %.loc11_31.1: type = splice_block %Self.ref [symbolic = %GenericDerived (constants.%GenericDerived)] {\n// CHECK:STDOUT:         %.loc11_31.2: type = specific_constant constants.%GenericDerived, @GenericDerived(constants.%T) [symbolic = %GenericDerived (constants.%GenericDerived)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc11_31.2 [symbolic = %GenericDerived (constants.%GenericDerived)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @GenericDerived.F2.%GenericDerived (%GenericDerived) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %GenericDerived.F3.decl: @GenericDerived.%GenericDerived.F3.type (%GenericDerived.F3.type) = fn_decl @GenericDerived.F3 [symbolic = @GenericDerived.%GenericDerived.F3 (constants.%GenericDerived.F3)] {\n// CHECK:STDOUT:       %self.patt: @GenericDerived.F3.%pattern_type (%pattern_type.945) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @GenericDerived.F3.%pattern_type (%pattern_type.945) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @GenericDerived.F3.%GenericDerived (%GenericDerived) = value_param call_param0\n// CHECK:STDOUT:       %.loc12_30.1: type = splice_block %Self.ref [symbolic = %GenericDerived (constants.%GenericDerived)] {\n// CHECK:STDOUT:         %.loc12_30.2: type = specific_constant constants.%GenericDerived, @GenericDerived(constants.%T) [symbolic = %GenericDerived (constants.%GenericDerived)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc12_30.2 [symbolic = %GenericDerived (constants.%GenericDerived)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @GenericDerived.F3.%GenericDerived (%GenericDerived) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %GenericDerived.F2.specific_fn.loc13_1.1: <specific function> = specific_function %GenericDerived.F2.decl, @GenericDerived.F2(constants.%T) [symbolic = %GenericDerived.F2.specific_fn.loc13_1.2 (constants.%GenericDerived.F2.specific_fn)]\n// CHECK:STDOUT:     %GenericDerived.F3.specific_fn.loc13_1.1: <specific function> = specific_function %GenericDerived.F3.decl, @GenericDerived.F3(constants.%T) [symbolic = %GenericDerived.F3.specific_fn.loc13_1.2 (constants.%GenericDerived.F3.specific_fn)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @GenericDerived.vtable [concrete = constants.%GenericDerived.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.base.66e [concrete = constants.%complete_type.a92]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%GenericDerived\n// CHECK:STDOUT:     .NonGenericBase = <poisoned>\n// CHECK:STDOUT:     .base = %.loc10\n// CHECK:STDOUT:     .F2 = %GenericDerived.F2.decl\n// CHECK:STDOUT:     .F3 = %GenericDerived.F3.decl\n// CHECK:STDOUT:     extend %NonGenericBase.ref\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @NonGenericBase.vtable {\n// CHECK:STDOUT:   @NonGenericBase.%NonGenericBase.F1.decl\n// CHECK:STDOUT:   @NonGenericBase.%NonGenericBase.F2.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @GenericDerived.vtable {\n// CHECK:STDOUT:   constants.%NonGenericBase.F1\n// CHECK:STDOUT:   @GenericDerived.%GenericDerived.F2.specific_fn.loc13_1.1\n// CHECK:STDOUT:   @GenericDerived.%GenericDerived.F3.specific_fn.loc13_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @NonGenericBase.F1(%self.param: %NonGenericBase) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @NonGenericBase.F2(%self.param: %NonGenericBase) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic override fn @GenericDerived.F2(@GenericDerived.%T.loc9_27.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %GenericDerived: type = class_type @GenericDerived, @GenericDerived(%T) [symbolic = %GenericDerived (constants.%GenericDerived)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %GenericDerived [symbolic = %pattern_type (constants.%pattern_type.945)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %GenericDerived [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   override fn(%self.param: @GenericDerived.F2.%GenericDerived (%GenericDerived)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @GenericDerived.F3(@GenericDerived.%T.loc9_27.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %GenericDerived: type = class_type @GenericDerived, @GenericDerived(%T) [symbolic = %GenericDerived (constants.%GenericDerived)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %GenericDerived [symbolic = %pattern_type (constants.%pattern_type.945)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %GenericDerived [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @GenericDerived.F3.%GenericDerived (%GenericDerived)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericDerived(constants.%T) {\n// CHECK:STDOUT:   %T.loc9_27.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %GenericDerived => constants.%GenericDerived\n// CHECK:STDOUT:   %GenericDerived.elem => constants.%GenericDerived.elem\n// CHECK:STDOUT:   %GenericDerived.F2.type => constants.%GenericDerived.F2.type\n// CHECK:STDOUT:   %GenericDerived.F2 => constants.%GenericDerived.F2\n// CHECK:STDOUT:   %GenericDerived.F3.type => constants.%GenericDerived.F3.type\n// CHECK:STDOUT:   %GenericDerived.F3 => constants.%GenericDerived.F3\n// CHECK:STDOUT:   %GenericDerived.F2.specific_fn.loc13_1.2 => constants.%GenericDerived.F2.specific_fn\n// CHECK:STDOUT:   %GenericDerived.F3.specific_fn.loc13_1.2 => constants.%GenericDerived.F3.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericDerived.F2(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %GenericDerived => constants.%GenericDerived\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.945\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericDerived.F3(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %GenericDerived => constants.%GenericDerived\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.945\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- nongeneric_derived_from_generic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %GenericBase.type: type = generic_class_type @GenericBase [concrete]\n// CHECK:STDOUT:   %GenericBase.generic: %GenericBase.type = struct_value () [concrete]\n// CHECK:STDOUT:   %GenericBase.5e3: type = class_type @GenericBase, @GenericBase(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.3f7: type = pattern_type %GenericBase.5e3 [symbolic]\n// CHECK:STDOUT:   %GenericBase.F1.type.c30: type = fn_type @GenericBase.F1, @GenericBase(%T) [symbolic]\n// CHECK:STDOUT:   %GenericBase.F1.5f6: %GenericBase.F1.type.c30 = struct_value () [symbolic]\n// CHECK:STDOUT:   %GenericBase.F2.type.3d4: type = fn_type @GenericBase.F2, @GenericBase(%T) [symbolic]\n// CHECK:STDOUT:   %GenericBase.F2.9ed: %GenericBase.F2.type.3d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %GenericBase.F1.specific_fn.463: <specific function> = specific_function %GenericBase.F1.5f6, @GenericBase.F1(%T) [symbolic]\n// CHECK:STDOUT:   %GenericBase.F2.specific_fn.92d: <specific function> = specific_function %GenericBase.F2.9ed, @GenericBase.F2(%T) [symbolic]\n// CHECK:STDOUT:   %GenericBase.vtable_decl: ref %ptr.454 = vtable_decl @GenericBase.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %GenericBase.5e3 [symbolic]\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %NonGenericDerived: type = class_type @NonGenericDerived [concrete]\n// CHECK:STDOUT:   %GenericBase.52d: type = class_type @GenericBase, @GenericBase(%T1) [concrete]\n// CHECK:STDOUT:   %GenericBase.F1.type.93d: type = fn_type @GenericBase.F1, @GenericBase(%T1) [concrete]\n// CHECK:STDOUT:   %GenericBase.F1.c55: %GenericBase.F1.type.93d = struct_value () [concrete]\n// CHECK:STDOUT:   %GenericBase.F2.type.14d: type = fn_type @GenericBase.F2, @GenericBase(%T1) [concrete]\n// CHECK:STDOUT:   %GenericBase.F2.301: %GenericBase.F2.type.14d = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.889: type = pattern_type %GenericBase.52d [concrete]\n// CHECK:STDOUT:   %GenericBase.F1.specific_fn.9eb: <specific function> = specific_function %GenericBase.F1.c55, @GenericBase.F1(%T1) [concrete]\n// CHECK:STDOUT:   %GenericBase.F2.specific_fn.ed3: <specific function> = specific_function %GenericBase.F2.301, @GenericBase.F2(%T1) [concrete]\n// CHECK:STDOUT:   %NonGenericDerived.elem: type = unbound_element_type %NonGenericDerived, %GenericBase.52d [concrete]\n// CHECK:STDOUT:   %pattern_type.c19: type = pattern_type %NonGenericDerived [concrete]\n// CHECK:STDOUT:   %NonGenericDerived.F2.type: type = fn_type @NonGenericDerived.F2 [concrete]\n// CHECK:STDOUT:   %NonGenericDerived.F2: %NonGenericDerived.F2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %NonGenericDerived.F3.type: type = fn_type @NonGenericDerived.F3 [concrete]\n// CHECK:STDOUT:   %NonGenericDerived.F3: %NonGenericDerived.F3.type = struct_value () [concrete]\n// CHECK:STDOUT:   %NonGenericDerived.vtable_decl: ref %ptr.454 = vtable_decl @NonGenericDerived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.19b: type = struct_type {.base: %GenericBase.52d} [concrete]\n// CHECK:STDOUT:   %complete_type.1f1: <witness> = complete_type_witness %struct_type.base.19b [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .GenericBase = %GenericBase.decl\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .NonGenericDerived = %NonGenericDerived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %GenericBase.decl: %GenericBase.type = class_decl @GenericBase [concrete = constants.%GenericBase.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_28.1: type = splice_block %.loc4_28.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_28.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_24.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_24.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT:   %NonGenericDerived.decl: type = class_decl @NonGenericDerived [concrete = constants.%NonGenericDerived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @GenericBase(%T.loc4_24.2: type) {\n// CHECK:STDOUT:   %T.loc4_24.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_24.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %GenericBase.F1.type: type = fn_type @GenericBase.F1, @GenericBase(%T.loc4_24.1) [symbolic = %GenericBase.F1.type (constants.%GenericBase.F1.type.c30)]\n// CHECK:STDOUT:   %GenericBase.F1: @GenericBase.%GenericBase.F1.type (%GenericBase.F1.type.c30) = struct_value () [symbolic = %GenericBase.F1 (constants.%GenericBase.F1.5f6)]\n// CHECK:STDOUT:   %GenericBase.F2.type: type = fn_type @GenericBase.F2, @GenericBase(%T.loc4_24.1) [symbolic = %GenericBase.F2.type (constants.%GenericBase.F2.type.3d4)]\n// CHECK:STDOUT:   %GenericBase.F2: @GenericBase.%GenericBase.F2.type (%GenericBase.F2.type.3d4) = struct_value () [symbolic = %GenericBase.F2 (constants.%GenericBase.F2.9ed)]\n// CHECK:STDOUT:   %GenericBase.F1.specific_fn.loc7_1.2: <specific function> = specific_function %GenericBase.F1, @GenericBase.F1(%T.loc4_24.1) [symbolic = %GenericBase.F1.specific_fn.loc7_1.2 (constants.%GenericBase.F1.specific_fn.463)]\n// CHECK:STDOUT:   %GenericBase.F2.specific_fn.loc7_1.2: <specific function> = specific_function %GenericBase.F2, @GenericBase.F2(%T.loc4_24.1) [symbolic = %GenericBase.F2.specific_fn.loc7_1.2 (constants.%GenericBase.F2.specific_fn.92d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %GenericBase.F1.decl: @GenericBase.%GenericBase.F1.type (%GenericBase.F1.type.c30) = fn_decl @GenericBase.F1 [symbolic = @GenericBase.%GenericBase.F1 (constants.%GenericBase.F1.5f6)] {\n// CHECK:STDOUT:       %self.patt: @GenericBase.F1.%pattern_type (%pattern_type.3f7) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @GenericBase.F1.%pattern_type (%pattern_type.3f7) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @GenericBase.F1.%GenericBase (%GenericBase.5e3) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_30.1: type = splice_block %Self.ref [symbolic = %GenericBase (constants.%GenericBase.5e3)] {\n// CHECK:STDOUT:         %.loc5_30.2: type = specific_constant constants.%GenericBase.5e3, @GenericBase(constants.%T) [symbolic = %GenericBase (constants.%GenericBase.5e3)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_30.2 [symbolic = %GenericBase (constants.%GenericBase.5e3)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @GenericBase.F1.%GenericBase (%GenericBase.5e3) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %GenericBase.F2.decl: @GenericBase.%GenericBase.F2.type (%GenericBase.F2.type.3d4) = fn_decl @GenericBase.F2 [symbolic = @GenericBase.%GenericBase.F2 (constants.%GenericBase.F2.9ed)] {\n// CHECK:STDOUT:       %self.patt: @GenericBase.F2.%pattern_type (%pattern_type.3f7) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @GenericBase.F2.%pattern_type (%pattern_type.3f7) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @GenericBase.F2.%GenericBase (%GenericBase.5e3) = value_param call_param0\n// CHECK:STDOUT:       %.loc6_30.1: type = splice_block %Self.ref [symbolic = %GenericBase (constants.%GenericBase.5e3)] {\n// CHECK:STDOUT:         %.loc6_30.2: type = specific_constant constants.%GenericBase.5e3, @GenericBase(constants.%T) [symbolic = %GenericBase (constants.%GenericBase.5e3)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc6_30.2 [symbolic = %GenericBase (constants.%GenericBase.5e3)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @GenericBase.F2.%GenericBase (%GenericBase.5e3) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %GenericBase.F1.specific_fn.loc7_1.1: <specific function> = specific_function %GenericBase.F1.decl, @GenericBase.F1(constants.%T) [symbolic = %GenericBase.F1.specific_fn.loc7_1.2 (constants.%GenericBase.F1.specific_fn.463)]\n// CHECK:STDOUT:     %GenericBase.F2.specific_fn.loc7_1.1: <specific function> = specific_function %GenericBase.F2.decl, @GenericBase.F2(constants.%T) [symbolic = %GenericBase.F2.specific_fn.loc7_1.2 (constants.%GenericBase.F2.specific_fn.92d)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @GenericBase.vtable [concrete = constants.%GenericBase.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%GenericBase.5e3\n// CHECK:STDOUT:     .F1 = %GenericBase.F1.decl\n// CHECK:STDOUT:     .F2 = %GenericBase.F2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1;\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @NonGenericDerived {\n// CHECK:STDOUT:   %GenericBase.ref: %GenericBase.type = name_ref GenericBase, file.%GenericBase.decl [concrete = constants.%GenericBase.generic]\n// CHECK:STDOUT:   %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:   %GenericBase: type = class_type @GenericBase, @GenericBase(constants.%T1) [concrete = constants.%GenericBase.52d]\n// CHECK:STDOUT:   %.loc12: %NonGenericDerived.elem = base_decl %GenericBase, element0 [concrete]\n// CHECK:STDOUT:   %NonGenericDerived.F2.decl: %NonGenericDerived.F2.type = fn_decl @NonGenericDerived.F2 [concrete = constants.%NonGenericDerived.F2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.c19 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.c19 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %NonGenericDerived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%NonGenericDerived [concrete = constants.%NonGenericDerived]\n// CHECK:STDOUT:     %self: %NonGenericDerived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %NonGenericDerived.F3.decl: %NonGenericDerived.F3.type = fn_decl @NonGenericDerived.F3 [concrete = constants.%NonGenericDerived.F3] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.c19 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.c19 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %NonGenericDerived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%NonGenericDerived [concrete = constants.%NonGenericDerived]\n// CHECK:STDOUT:     %self: %NonGenericDerived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @NonGenericDerived.vtable [concrete = constants.%NonGenericDerived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.19b [concrete = constants.%complete_type.1f1]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%NonGenericDerived\n// CHECK:STDOUT:   .GenericBase = <poisoned>\n// CHECK:STDOUT:   .T1 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc12\n// CHECK:STDOUT:   .F2 = %NonGenericDerived.F2.decl\n// CHECK:STDOUT:   .F3 = %NonGenericDerived.F3.decl\n// CHECK:STDOUT:   extend %GenericBase\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @GenericBase.vtable {\n// CHECK:STDOUT:   @GenericBase.%GenericBase.F1.specific_fn.loc7_1.1\n// CHECK:STDOUT:   @GenericBase.%GenericBase.F2.specific_fn.loc7_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @NonGenericDerived.vtable {\n// CHECK:STDOUT:   constants.%GenericBase.F1.specific_fn.9eb\n// CHECK:STDOUT:   @NonGenericDerived.%NonGenericDerived.F2.decl\n// CHECK:STDOUT:   @NonGenericDerived.%NonGenericDerived.F3.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @GenericBase.F1(@GenericBase.%T.loc4_24.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %GenericBase: type = class_type @GenericBase, @GenericBase(%T) [symbolic = %GenericBase (constants.%GenericBase.5e3)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %GenericBase [symbolic = %pattern_type (constants.%pattern_type.3f7)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %GenericBase [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @GenericBase.F1.%GenericBase (%GenericBase.5e3)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @GenericBase.F2(@GenericBase.%T.loc4_24.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %GenericBase: type = class_type @GenericBase, @GenericBase(%T) [symbolic = %GenericBase (constants.%GenericBase.5e3)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %GenericBase [symbolic = %pattern_type (constants.%pattern_type.3f7)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %GenericBase [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @GenericBase.F2.%GenericBase (%GenericBase.5e3)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @NonGenericDerived.F2(%self.param: %NonGenericDerived) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: virtual fn @NonGenericDerived.F3(%self.param: %NonGenericDerived) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericBase(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_24.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %GenericBase.F1.type => constants.%GenericBase.F1.type.c30\n// CHECK:STDOUT:   %GenericBase.F1 => constants.%GenericBase.F1.5f6\n// CHECK:STDOUT:   %GenericBase.F2.type => constants.%GenericBase.F2.type.3d4\n// CHECK:STDOUT:   %GenericBase.F2 => constants.%GenericBase.F2.9ed\n// CHECK:STDOUT:   %GenericBase.F1.specific_fn.loc7_1.2 => constants.%GenericBase.F1.specific_fn.463\n// CHECK:STDOUT:   %GenericBase.F2.specific_fn.loc7_1.2 => constants.%GenericBase.F2.specific_fn.92d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericBase.F1(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %GenericBase => constants.%GenericBase.5e3\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.3f7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericBase.F2(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %GenericBase => constants.%GenericBase.5e3\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.3f7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericBase(constants.%T1) {\n// CHECK:STDOUT:   %T.loc4_24.1 => constants.%T1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %GenericBase.F1.type => constants.%GenericBase.F1.type.93d\n// CHECK:STDOUT:   %GenericBase.F1 => constants.%GenericBase.F1.c55\n// CHECK:STDOUT:   %GenericBase.F2.type => constants.%GenericBase.F2.type.14d\n// CHECK:STDOUT:   %GenericBase.F2 => constants.%GenericBase.F2.301\n// CHECK:STDOUT:   %GenericBase.F1.specific_fn.loc7_1.2 => constants.%GenericBase.F1.specific_fn.9eb\n// CHECK:STDOUT:   %GenericBase.F2.specific_fn.loc7_1.2 => constants.%GenericBase.F2.specific_fn.ed3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericBase.F1(constants.%T1) {\n// CHECK:STDOUT:   %T => constants.%T1\n// CHECK:STDOUT:   %GenericBase => constants.%GenericBase.52d\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.889\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.513\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericBase.F2(constants.%T1) {\n// CHECK:STDOUT:   %T => constants.%T1\n// CHECK:STDOUT:   %GenericBase => constants.%GenericBase.52d\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.889\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.513\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- impl_generic_specifically.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.d0c: type = class_type @Base, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.2f0: type = pattern_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %ptr.4b1: type = ptr_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %pattern_type.cf5: type = pattern_type %ptr.4b1 [symbolic]\n// CHECK:STDOUT:   %Base.F.type.0f1: type = fn_type @Base.F, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F.cd3: %Base.F.type.0f1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.f8c: <specific function> = specific_function %Base.F.cd3, @Base.F(%T) [symbolic]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete.1e0: <witness> = require_complete_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %require_complete.3cf: <witness> = require_complete_type %ptr.4b1 [symbolic]\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %D1: type = class_type @D1 [concrete]\n// CHECK:STDOUT:   %Base.d5d: type = class_type @Base, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.type.cb1: type = fn_type @Base.F, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.eab: %Base.F.type.cb1 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.64f: type = pattern_type %Base.d5d [concrete]\n// CHECK:STDOUT:   %ptr.6e0: type = ptr_type %Base.d5d [concrete]\n// CHECK:STDOUT:   %pattern_type.912: type = pattern_type %ptr.6e0 [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.cd5: <specific function> = specific_function %Base.F.eab, @Base.F(%T1) [concrete]\n// CHECK:STDOUT:   %D1.elem: type = unbound_element_type %D1, %Base.d5d [concrete]\n// CHECK:STDOUT:   %pattern_type.7f9: type = pattern_type %D1 [concrete]\n// CHECK:STDOUT:   %D1.F.type: type = fn_type @D1.F [concrete]\n// CHECK:STDOUT:   %D1.F: %D1.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D1.vtable_decl: ref %ptr.454 = vtable_decl @D1.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.cc2: type = struct_type {.base: %Base.d5d} [concrete]\n// CHECK:STDOUT:   %complete_type.dcb: <witness> = complete_type_witness %struct_type.base.cc2 [concrete]\n// CHECK:STDOUT:   %complete_type.96e: <witness> = complete_type_witness %ptr.6e0 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .D1 = %D1.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: %Base.type = class_decl @Base [concrete = constants.%Base.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_21.1: type = splice_block %.loc4_21.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_21.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_17.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT:   %D1.decl: type = class_decl @D1 [concrete = constants.%D1] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(%T.loc4_17.2: type) {\n// CHECK:STDOUT:   %T.loc4_17.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T.loc4_17.1) [symbolic = %Base.F.type (constants.%Base.F.type.0f1)]\n// CHECK:STDOUT:   %Base.F: @Base.%Base.F.type (%Base.F.type.0f1) = struct_value () [symbolic = %Base.F (constants.%Base.F.cd3)]\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2: <specific function> = specific_function %Base.F, @Base.F(%T.loc4_17.1) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.F.decl: @Base.%Base.F.type (%Base.F.type.0f1) = fn_decl @Base.F [symbolic = @Base.%Base.F (constants.%Base.F.cd3)] {\n// CHECK:STDOUT:       %self.patt: @Base.F.%pattern_type.loc5_23 (%pattern_type.2f0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Base.F.%pattern_type.loc5_23 (%pattern_type.2f0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: @Base.F.%pattern_type.loc5_42 (%pattern_type.cf5) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: @Base.F.%pattern_type.loc5_42 (%pattern_type.cf5) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Base.F.%Base.loc5_29 (%Base.d0c) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_29.1: type = splice_block %Self.ref [symbolic = %Base.loc5_29 (constants.%Base.d0c)] {\n// CHECK:STDOUT:         %.loc5_29.2: type = specific_constant constants.%Base.d0c, @Base(constants.%T) [symbolic = %Base.loc5_29 (constants.%Base.d0c)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_29.2 [symbolic = %Base.loc5_29 (constants.%Base.d0c)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Base.F.%Base.loc5_29 (%Base.d0c) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: @Base.F.%ptr.loc5_52.1 (%ptr.4b1) = value_param call_param1\n// CHECK:STDOUT:       %.loc5_52: type = splice_block %ptr.loc5_52.2 [symbolic = %ptr.loc5_52.1 (constants.%ptr.4b1)] {\n// CHECK:STDOUT:         %Base.ref: %Base.type = name_ref Base, file.%Base.decl [concrete = constants.%Base.generic]\n// CHECK:STDOUT:         %T.ref: type = name_ref T, @Base.%T.loc4_17.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:         %Base.loc5_51: type = class_type @Base, @Base(constants.%T) [symbolic = %Base.loc5_29 (constants.%Base.d0c)]\n// CHECK:STDOUT:         %ptr.loc5_52.2: type = ptr_type %Base.loc5_51 [symbolic = %ptr.loc5_52.1 (constants.%ptr.4b1)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %t: @Base.F.%ptr.loc5_52.1 (%ptr.4b1) = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Base.F.specific_fn.loc6_1.1: <specific function> = specific_function %Base.F.decl, @Base.F(constants.%T) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Base.d0c\n// CHECK:STDOUT:     .Base = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %Base.F.decl\n// CHECK:STDOUT:     .T1 = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1;\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D1 {\n// CHECK:STDOUT:   %Base.ref: %Base.type = name_ref Base, file.%Base.decl [concrete = constants.%Base.generic]\n// CHECK:STDOUT:   %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(constants.%T1) [concrete = constants.%Base.d5d]\n// CHECK:STDOUT:   %.loc9: %D1.elem = base_decl %Base, element0 [concrete]\n// CHECK:STDOUT:   %D1.F.decl: %D1.F.type = fn_decl @D1.F [concrete = constants.%D1.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.7f9 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.7f9 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %t.patt: %pattern_type.912 = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: %pattern_type.912 = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %D1 = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%D1 [concrete = constants.%D1]\n// CHECK:STDOUT:     %self: %D1 = value_binding self, %self.param\n// CHECK:STDOUT:     %t.param: %ptr.6e0 = value_param call_param1\n// CHECK:STDOUT:     %.loc10: type = splice_block %ptr [concrete = constants.%ptr.6e0] {\n// CHECK:STDOUT:       %Base.ref: %Base.type = name_ref Base, file.%Base.decl [concrete = constants.%Base.generic]\n// CHECK:STDOUT:       %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:       %Base: type = class_type @Base, @Base(constants.%T1) [concrete = constants.%Base.d5d]\n// CHECK:STDOUT:       %ptr: type = ptr_type %Base [concrete = constants.%ptr.6e0]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %t: %ptr.6e0 = value_binding t, %t.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @D1.vtable [concrete = constants.%D1.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.cc2 [concrete = constants.%complete_type.dcb]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D1\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .T1 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc9\n// CHECK:STDOUT:   .F = %D1.F.decl\n// CHECK:STDOUT:   extend %Base\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.specific_fn.loc6_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @D1.vtable {\n// CHECK:STDOUT:   @D1.%D1.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @Base.F(@Base.%T.loc4_17.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Base.loc5_29: type = class_type @Base, @Base(%T) [symbolic = %Base.loc5_29 (constants.%Base.d0c)]\n// CHECK:STDOUT:   %pattern_type.loc5_23: type = pattern_type %Base.loc5_29 [symbolic = %pattern_type.loc5_23 (constants.%pattern_type.2f0)]\n// CHECK:STDOUT:   %ptr.loc5_52.1: type = ptr_type %Base.loc5_29 [symbolic = %ptr.loc5_52.1 (constants.%ptr.4b1)]\n// CHECK:STDOUT:   %pattern_type.loc5_42: type = pattern_type %ptr.loc5_52.1 [symbolic = %pattern_type.loc5_42 (constants.%pattern_type.cf5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27: <witness> = require_complete_type %Base.loc5_29 [symbolic = %require_complete.loc5_27 (constants.%require_complete.1e0)]\n// CHECK:STDOUT:   %require_complete.loc5_43: <witness> = require_complete_type %ptr.loc5_52.1 [symbolic = %require_complete.loc5_43 (constants.%require_complete.3cf)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @Base.F.%Base.loc5_29 (%Base.d0c), %t.param: @Base.F.%ptr.loc5_52.1 (%ptr.4b1)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @D1.F(%self.param: %D1, %t.param: %ptr.6e0) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.0f1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.cd3\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2 => constants.%Base.F.specific_fn.f8c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Base.loc5_29 => constants.%Base.d0c\n// CHECK:STDOUT:   %pattern_type.loc5_23 => constants.%pattern_type.2f0\n// CHECK:STDOUT:   %ptr.loc5_52.1 => constants.%ptr.4b1\n// CHECK:STDOUT:   %pattern_type.loc5_42 => constants.%pattern_type.cf5\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27 => constants.%require_complete.1e0\n// CHECK:STDOUT:   %require_complete.loc5_43 => constants.%require_complete.3cf\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T1) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%T1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.cb1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.eab\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2 => constants.%Base.F.specific_fn.cd5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T1) {\n// CHECK:STDOUT:   %T => constants.%T1\n// CHECK:STDOUT:   %Base.loc5_29 => constants.%Base.d5d\n// CHECK:STDOUT:   %pattern_type.loc5_23 => constants.%pattern_type.64f\n// CHECK:STDOUT:   %ptr.loc5_52.1 => constants.%ptr.6e0\n// CHECK:STDOUT:   %pattern_type.loc5_42 => constants.%pattern_type.912\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27 => constants.%complete_type.513\n// CHECK:STDOUT:   %require_complete.loc5_43 => constants.%complete_type.96e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_generic_specifically_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %T2: type = class_type @T2 [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.d0c: type = class_type @Base, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.2f0: type = pattern_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %ptr.9ce: type = ptr_type %T1 [concrete]\n// CHECK:STDOUT:   %pattern_type.c16: type = pattern_type %ptr.9ce [concrete]\n// CHECK:STDOUT:   %Base.F.type.0f1: type = fn_type @Base.F, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F.cd3: %Base.F.type.0f1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.f8c: <specific function> = specific_function %Base.F.cd3, @Base.F(%T) [symbolic]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %D1: type = class_type @D1 [concrete]\n// CHECK:STDOUT:   %Base.d5d: type = class_type @Base, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.type.cb1: type = fn_type @Base.F, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.eab: %Base.F.type.cb1 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.64f: type = pattern_type %Base.d5d [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.cd5: <specific function> = specific_function %Base.F.eab, @Base.F(%T1) [concrete]\n// CHECK:STDOUT:   %D1.elem: type = unbound_element_type %D1, %Base.d5d [concrete]\n// CHECK:STDOUT:   %pattern_type.7f9: type = pattern_type %D1 [concrete]\n// CHECK:STDOUT:   %ptr.9f6: type = ptr_type %T2 [concrete]\n// CHECK:STDOUT:   %pattern_type.64c: type = pattern_type %ptr.9f6 [concrete]\n// CHECK:STDOUT:   %D1.F.type: type = fn_type @D1.F [concrete]\n// CHECK:STDOUT:   %D1.F: %D1.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D1.vtable_decl: ref %ptr.454 = vtable_decl @D1.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.cc2: type = struct_type {.base: %Base.d5d} [concrete]\n// CHECK:STDOUT:   %complete_type.dcb: <witness> = complete_type_witness %struct_type.base.cc2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .T2 = %T2.decl\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .D1 = %D1.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT:   %T2.decl: type = class_decl @T2 [concrete = constants.%T2] {} {}\n// CHECK:STDOUT:   %Base.decl: %Base.type = class_decl @Base [concrete = constants.%Base.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_21.1: type = splice_block %.loc7_21.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_21.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_17.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_17.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D1.decl: type = class_decl @D1 [concrete = constants.%D1] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1;\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T2;\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(%T.loc7_17.2: type) {\n// CHECK:STDOUT:   %T.loc7_17.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_17.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T.loc7_17.1) [symbolic = %Base.F.type (constants.%Base.F.type.0f1)]\n// CHECK:STDOUT:   %Base.F: @Base.%Base.F.type (%Base.F.type.0f1) = struct_value () [symbolic = %Base.F (constants.%Base.F.cd3)]\n// CHECK:STDOUT:   %Base.F.specific_fn.loc9_1.2: <specific function> = specific_function %Base.F, @Base.F(%T.loc7_17.1) [symbolic = %Base.F.specific_fn.loc9_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.F.decl: @Base.%Base.F.type (%Base.F.type.0f1) = fn_decl @Base.F [symbolic = @Base.%Base.F (constants.%Base.F.cd3)] {\n// CHECK:STDOUT:       %self.patt: @Base.F.%pattern_type (%pattern_type.2f0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Base.F.%pattern_type (%pattern_type.2f0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: %pattern_type.c16 = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: %pattern_type.c16 = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Base.F.%Base (%Base.d0c) = value_param call_param0\n// CHECK:STDOUT:       %.loc8_29.1: type = splice_block %Self.ref [symbolic = %Base (constants.%Base.d0c)] {\n// CHECK:STDOUT:         %.loc8_29.2: type = specific_constant constants.%Base.d0c, @Base(constants.%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc8_29.2 [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Base.F.%Base (%Base.d0c) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: %ptr.9ce = value_param call_param1\n// CHECK:STDOUT:       %.loc8_47: type = splice_block %ptr [concrete = constants.%ptr.9ce] {\n// CHECK:STDOUT:         %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:         %ptr: type = ptr_type %T1.ref [concrete = constants.%ptr.9ce]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %t: %ptr.9ce = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Base.F.specific_fn.loc9_1.1: <specific function> = specific_function %Base.F.decl, @Base.F(constants.%T) [symbolic = %Base.F.specific_fn.loc9_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Base.d0c\n// CHECK:STDOUT:     .T1 = <poisoned>\n// CHECK:STDOUT:     .F = %Base.F.decl\n// CHECK:STDOUT:     .T2 = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D1 {\n// CHECK:STDOUT:   %Base.ref: %Base.type = name_ref Base, file.%Base.decl [concrete = constants.%Base.generic]\n// CHECK:STDOUT:   %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(constants.%T1) [concrete = constants.%Base.d5d]\n// CHECK:STDOUT:   %.loc12: %D1.elem = base_decl %Base, element0 [concrete]\n// CHECK:STDOUT:   %D1.F.decl: %D1.F.type = fn_decl @D1.F [concrete = constants.%D1.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.7f9 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.7f9 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %t.patt: %pattern_type.64c = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: %pattern_type.64c = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %D1 = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%D1 [concrete = constants.%D1]\n// CHECK:STDOUT:     %self: %D1 = value_binding self, %self.param\n// CHECK:STDOUT:     %t.param: %ptr.9f6 = value_param call_param1\n// CHECK:STDOUT:     %.loc20: type = splice_block %ptr [concrete = constants.%ptr.9f6] {\n// CHECK:STDOUT:       %T2.ref: type = name_ref T2, file.%T2.decl [concrete = constants.%T2]\n// CHECK:STDOUT:       %ptr: type = ptr_type %T2.ref [concrete = constants.%ptr.9f6]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %t: %ptr.9f6 = value_binding t, %t.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @D1.vtable [concrete = constants.%D1.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.cc2 [concrete = constants.%complete_type.dcb]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D1\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .T1 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc12\n// CHECK:STDOUT:   .T2 = <poisoned>\n// CHECK:STDOUT:   .F = %D1.F.decl\n// CHECK:STDOUT:   extend %Base\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.specific_fn.loc9_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @D1.vtable {\n// CHECK:STDOUT:   @D1.%D1.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @Base.F(@Base.%T.loc7_17.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Base [symbolic = %pattern_type (constants.%pattern_type.2f0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Base [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @Base.F.%Base (%Base.d0c), %t.param: %ptr.9ce) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @D1.F(%self.param: %D1, %t.param: %ptr.9f6) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_17.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.0f1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.cd3\n// CHECK:STDOUT:   %Base.F.specific_fn.loc9_1.2 => constants.%Base.F.specific_fn.f8c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Base => constants.%Base.d0c\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.2f0\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T1) {\n// CHECK:STDOUT:   %T.loc7_17.1 => constants.%T1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.cb1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.eab\n// CHECK:STDOUT:   %Base.F.specific_fn.loc9_1.2 => constants.%Base.F.specific_fn.cd5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T1) {\n// CHECK:STDOUT:   %T => constants.%T1\n// CHECK:STDOUT:   %Base => constants.%Base.d5d\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.64f\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.513\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_generic_generic_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.2f0: type = pattern_type %Base [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn: <specific function> = specific_function %Base.F, @Base.F(%T) [symbolic]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete.1e0: <witness> = require_complete_type %Base [symbolic]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %Derived.type: type = generic_class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.generic: %Derived.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived, @Derived(%T) [symbolic]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base [symbolic]\n// CHECK:STDOUT:   %pattern_type.b9d: type = pattern_type %Derived [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F, @Derived(%T) [symbolic]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %Derived.F.specific_fn: <specific function> = specific_function %Derived.F, @Derived.F(%T) [symbolic]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.b5f: type = struct_type {.base: %Base} [symbolic]\n// CHECK:STDOUT:   %complete_type.33f: <witness> = complete_type_witness %struct_type.base.b5f [symbolic]\n// CHECK:STDOUT:   %require_complete.a43: <witness> = require_complete_type %Derived [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: %Base.type = class_decl @Base [concrete = constants.%Base.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_25.1: type = splice_block %.loc4_25.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_25.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_21.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_21.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Derived.decl: %Derived.type = class_decl @Derived [concrete = constants.%Derived.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_19.1: type = splice_block %.loc7_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_15.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_15.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(%T.loc4_21.2: type) {\n// CHECK:STDOUT:   %T.loc4_21.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_21.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T.loc4_21.1) [symbolic = %Base.F.type (constants.%Base.F.type)]\n// CHECK:STDOUT:   %Base.F: @Base.%Base.F.type (%Base.F.type) = struct_value () [symbolic = %Base.F (constants.%Base.F)]\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2: <specific function> = specific_function %Base.F, @Base.F(%T.loc4_21.1) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.F.decl: @Base.%Base.F.type (%Base.F.type) = fn_decl @Base.F [symbolic = @Base.%Base.F (constants.%Base.F)] {\n// CHECK:STDOUT:       %self.patt: @Base.F.%pattern_type.loc5_23 (%pattern_type.2f0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Base.F.%pattern_type.loc5_23 (%pattern_type.2f0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: @Base.F.%pattern_type.loc5_42 (%pattern_type.4f4) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: @Base.F.%pattern_type.loc5_42 (%pattern_type.4f4) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Base.F.%Base (%Base) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_29.1: type = splice_block %Self.ref [symbolic = %Base (constants.%Base)] {\n// CHECK:STDOUT:         %.loc5_29.2: type = specific_constant constants.%Base, @Base(constants.%T) [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_29.2 [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Base.F.%Base (%Base) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: @Base.F.%ptr.loc5_46.1 (%ptr.e8f) = value_param call_param1\n// CHECK:STDOUT:       %.loc5_46: type = splice_block %ptr.loc5_46.2 [symbolic = %ptr.loc5_46.1 (constants.%ptr.e8f)] {\n// CHECK:STDOUT:         %T.ref: type = name_ref T, @Base.%T.loc4_21.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:         %ptr.loc5_46.2: type = ptr_type %T.ref [symbolic = %ptr.loc5_46.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %t: @Base.F.%ptr.loc5_46.1 (%ptr.e8f) = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Base.F.specific_fn.loc6_1.1: <specific function> = specific_function %Base.F.decl, @Base.F(constants.%T) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Base\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %Base.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Derived(%T.loc7_15.2: type) {\n// CHECK:STDOUT:   %T.loc7_15.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_15.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.loc8_22.2: type = class_type @Base, @Base(%T.loc7_15.1) [symbolic = %Base.loc8_22.2 (constants.%Base)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Base.loc8_22.2 [symbolic = %require_complete (constants.%require_complete.1e0)]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived, @Derived(%T.loc7_15.1) [symbolic = %Derived (constants.%Derived)]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base.loc8_22.2 [symbolic = %Derived.elem (constants.%Derived.elem)]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F, @Derived(%T.loc7_15.1) [symbolic = %Derived.F.type (constants.%Derived.F.type)]\n// CHECK:STDOUT:   %Derived.F: @Derived.%Derived.F.type (%Derived.F.type) = struct_value () [symbolic = %Derived.F (constants.%Derived.F)]\n// CHECK:STDOUT:   %Derived.F.specific_fn.loc17_1.2: <specific function> = specific_function %Derived.F, @Derived.F(%T.loc7_15.1) [symbolic = %Derived.F.specific_fn.loc17_1.2 (constants.%Derived.F.specific_fn)]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: @Derived.%Base.loc8_22.2 (%Base)} [symbolic = %struct_type.base (constants.%struct_type.base.b5f)]\n// CHECK:STDOUT:   %complete_type.loc17_1.2: <witness> = complete_type_witness %struct_type.base [symbolic = %complete_type.loc17_1.2 (constants.%complete_type.33f)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.ref: %Base.type = name_ref Base, file.%Base.decl [concrete = constants.%Base.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc7_15.2 [symbolic = %T.loc7_15.1 (constants.%T)]\n// CHECK:STDOUT:     %Base.loc8_22.1: type = class_type @Base, @Base(constants.%T) [symbolic = %Base.loc8_22.2 (constants.%Base)]\n// CHECK:STDOUT:     %.loc8: @Derived.%Derived.elem (%Derived.elem) = base_decl %Base.loc8_22.1, element0 [concrete]\n// CHECK:STDOUT:     %Derived.F.decl: @Derived.%Derived.F.type (%Derived.F.type) = fn_decl @Derived.F [symbolic = @Derived.%Derived.F (constants.%Derived.F)] {\n// CHECK:STDOUT:       %self.patt: @Derived.F.%pattern_type.loc16_24 (%pattern_type.b9d) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Derived.F.%pattern_type.loc16_24 (%pattern_type.b9d) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: @Derived.F.%pattern_type.loc16_43 (%pattern_type.51d) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: @Derived.F.%pattern_type.loc16_43 (%pattern_type.51d) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Derived.F.%Derived (%Derived) = value_param call_param0\n// CHECK:STDOUT:       %.loc16_30.1: type = splice_block %Self.ref [symbolic = %Derived (constants.%Derived)] {\n// CHECK:STDOUT:         %.loc16_30.2: type = specific_constant constants.%Derived, @Derived(constants.%T) [symbolic = %Derived (constants.%Derived)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc16_30.2 [symbolic = %Derived (constants.%Derived)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Derived.F.%Derived (%Derived) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: @Derived.F.%T (%T) = value_param call_param1\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Derived.%T.loc7_15.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %t: @Derived.F.%T (%T) = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Derived.F.specific_fn.loc17_1.1: <specific function> = specific_function %Derived.F.decl, @Derived.F(constants.%T) [symbolic = %Derived.F.specific_fn.loc17_1.2 (constants.%Derived.F.specific_fn)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:     %complete_type.loc17_1.1: <witness> = complete_type_witness constants.%struct_type.base.b5f [symbolic = %complete_type.loc17_1.2 (constants.%complete_type.33f)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc17_1.1\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Derived\n// CHECK:STDOUT:     .Base = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .base = %.loc8\n// CHECK:STDOUT:     .F = %Derived.F.decl\n// CHECK:STDOUT:     extend %Base.loc8_22.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.specific_fn.loc6_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   @Derived.%Derived.F.specific_fn.loc17_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @Base.F(@Base.%T.loc4_21.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:   %pattern_type.loc5_23: type = pattern_type %Base [symbolic = %pattern_type.loc5_23 (constants.%pattern_type.2f0)]\n// CHECK:STDOUT:   %ptr.loc5_46.1: type = ptr_type %T [symbolic = %ptr.loc5_46.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %pattern_type.loc5_42: type = pattern_type %ptr.loc5_46.1 [symbolic = %pattern_type.loc5_42 (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27: <witness> = require_complete_type %Base [symbolic = %require_complete.loc5_27 (constants.%require_complete.1e0)]\n// CHECK:STDOUT:   %require_complete.loc5_43: <witness> = require_complete_type %ptr.loc5_46.1 [symbolic = %require_complete.loc5_43 (constants.%require_complete.ef1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @Base.F.%Base (%Base), %t.param: @Base.F.%ptr.loc5_46.1 (%ptr.e8f)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic override fn @Derived.F(@Derived.%T.loc7_15.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived, @Derived(%T) [symbolic = %Derived (constants.%Derived)]\n// CHECK:STDOUT:   %pattern_type.loc16_24: type = pattern_type %Derived [symbolic = %pattern_type.loc16_24 (constants.%pattern_type.b9d)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:   %require_complete.loc16_46: <witness> = require_complete_type %Base [symbolic = %require_complete.loc16_46 (constants.%require_complete.1e0)]\n// CHECK:STDOUT:   %pattern_type.loc16_43: type = pattern_type %T [symbolic = %pattern_type.loc16_43 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc16_28: <witness> = require_complete_type %Derived [symbolic = %require_complete.loc16_28 (constants.%require_complete.a43)]\n// CHECK:STDOUT:   %require_complete.loc16_44: <witness> = require_complete_type %T [symbolic = %require_complete.loc16_44 (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   override fn(%self.param: @Derived.F.%Derived (%Derived), %t.param: @Derived.F.%T (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_21.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type\n// CHECK:STDOUT:   %Base.F => constants.%Base.F\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2 => constants.%Base.F.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Base => constants.%Base\n// CHECK:STDOUT:   %pattern_type.loc5_23 => constants.%pattern_type.2f0\n// CHECK:STDOUT:   %ptr.loc5_46.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %pattern_type.loc5_42 => constants.%pattern_type.4f4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27 => constants.%require_complete.1e0\n// CHECK:STDOUT:   %require_complete.loc5_43 => constants.%require_complete.ef1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Derived(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_15.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.loc8_22.2 => constants.%Base\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.1e0\n// CHECK:STDOUT:   %Derived => constants.%Derived\n// CHECK:STDOUT:   %Derived.elem => constants.%Derived.elem\n// CHECK:STDOUT:   %Derived.F.type => constants.%Derived.F.type\n// CHECK:STDOUT:   %Derived.F => constants.%Derived.F\n// CHECK:STDOUT:   %Derived.F.specific_fn.loc17_1.2 => constants.%Derived.F.specific_fn\n// CHECK:STDOUT:   %struct_type.base => constants.%struct_type.base.b5f\n// CHECK:STDOUT:   %complete_type.loc17_1.2 => constants.%complete_type.33f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Derived.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Derived => constants.%Derived\n// CHECK:STDOUT:   %pattern_type.loc16_24 => constants.%pattern_type.b9d\n// CHECK:STDOUT:   %Base => constants.%Base\n// CHECK:STDOUT:   %require_complete.loc16_46 => constants.%require_complete.1e0\n// CHECK:STDOUT:   %pattern_type.loc16_43 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc16_28 => constants.%require_complete.a43\n// CHECK:STDOUT:   %require_complete.loc16_44 => constants.%require_complete.944\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- impl_generic_generic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.d0c: type = class_type @Base, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.2f0: type = pattern_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %Base.F.type.0f1: type = fn_type @Base.F, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F.cd3: %Base.F.type.0f1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.f8c: <specific function> = specific_function %Base.F.cd3, @Base.F(%T) [symbolic]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete.1e0: <witness> = require_complete_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %Derived.type: type = generic_class_type @Derived [concrete]\n// CHECK:STDOUT:   %Derived.generic: %Derived.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived, @Derived(%T) [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %Base.f29: type = class_type @Base, @Base(%ptr.e8f) [symbolic]\n// CHECK:STDOUT:   %Base.F.type.c53: type = fn_type @Base.F, @Base(%ptr.e8f) [symbolic]\n// CHECK:STDOUT:   %Base.F.c0a: %Base.F.type.c53 = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.d96: type = pattern_type %Base.f29 [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %Base.F.specific_fn.35d: <specific function> = specific_function %Base.F.c0a, @Base.F(%ptr.e8f) [symbolic]\n// CHECK:STDOUT:   %require_complete.b3c: <witness> = require_complete_type %Base.f29 [symbolic]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base.f29 [symbolic]\n// CHECK:STDOUT:   %pattern_type.b9d: type = pattern_type %Derived [symbolic]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F, @Derived(%T) [symbolic]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %Derived.F.specific_fn: <specific function> = specific_function %Derived.F, @Derived.F(%T) [symbolic]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.aa5: type = struct_type {.base: %Base.f29} [symbolic]\n// CHECK:STDOUT:   %complete_type.8c0: <witness> = complete_type_witness %struct_type.base.aa5 [symbolic]\n// CHECK:STDOUT:   %require_complete.a43: <witness> = require_complete_type %Derived [symbolic]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: %Base.type = class_decl @Base [concrete = constants.%Base.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_25.1: type = splice_block %.loc4_25.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_25.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_21.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_21.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Derived.decl: %Derived.type = class_decl @Derived [concrete = constants.%Derived.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_19.1: type = splice_block %.loc7_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_15.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_15.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(%T.loc4_21.2: type) {\n// CHECK:STDOUT:   %T.loc4_21.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_21.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T.loc4_21.1) [symbolic = %Base.F.type (constants.%Base.F.type.0f1)]\n// CHECK:STDOUT:   %Base.F: @Base.%Base.F.type (%Base.F.type.0f1) = struct_value () [symbolic = %Base.F (constants.%Base.F.cd3)]\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2: <specific function> = specific_function %Base.F, @Base.F(%T.loc4_21.1) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.F.decl: @Base.%Base.F.type (%Base.F.type.0f1) = fn_decl @Base.F [symbolic = @Base.%Base.F (constants.%Base.F.cd3)] {\n// CHECK:STDOUT:       %self.patt: @Base.F.%pattern_type.loc5_23 (%pattern_type.2f0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Base.F.%pattern_type.loc5_23 (%pattern_type.2f0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: @Base.F.%pattern_type.loc5_42 (%pattern_type.51d) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: @Base.F.%pattern_type.loc5_42 (%pattern_type.51d) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Base.F.%Base (%Base.d0c) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_29.1: type = splice_block %Self.ref [symbolic = %Base (constants.%Base.d0c)] {\n// CHECK:STDOUT:         %.loc5_29.2: type = specific_constant constants.%Base.d0c, @Base(constants.%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_29.2 [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Base.F.%Base (%Base.d0c) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: @Base.F.%T (%T) = value_param call_param1\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Base.%T.loc4_21.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %t: @Base.F.%T (%T) = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Base.F.specific_fn.loc6_1.1: <specific function> = specific_function %Base.F.decl, @Base.F(constants.%T) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Base.d0c\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %Base.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Derived(%T.loc7_15.2: type) {\n// CHECK:STDOUT:   %T.loc7_15.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_15.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ptr.loc8_22.2: type = ptr_type %T.loc7_15.1 [symbolic = %ptr.loc8_22.2 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %Base.loc8_23.2: type = class_type @Base, @Base(%ptr.loc8_22.2) [symbolic = %Base.loc8_23.2 (constants.%Base.f29)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Base.loc8_23.2 [symbolic = %require_complete (constants.%require_complete.b3c)]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived, @Derived(%T.loc7_15.1) [symbolic = %Derived (constants.%Derived)]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base.loc8_23.2 [symbolic = %Derived.elem (constants.%Derived.elem)]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F, @Derived(%T.loc7_15.1) [symbolic = %Derived.F.type (constants.%Derived.F.type)]\n// CHECK:STDOUT:   %Derived.F: @Derived.%Derived.F.type (%Derived.F.type) = struct_value () [symbolic = %Derived.F (constants.%Derived.F)]\n// CHECK:STDOUT:   %Derived.F.specific_fn.loc10_1.2: <specific function> = specific_function %Derived.F, @Derived.F(%T.loc7_15.1) [symbolic = %Derived.F.specific_fn.loc10_1.2 (constants.%Derived.F.specific_fn)]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: @Derived.%Base.loc8_23.2 (%Base.f29)} [symbolic = %struct_type.base (constants.%struct_type.base.aa5)]\n// CHECK:STDOUT:   %complete_type.loc10_1.2: <witness> = complete_type_witness %struct_type.base [symbolic = %complete_type.loc10_1.2 (constants.%complete_type.8c0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.ref: %Base.type = name_ref Base, file.%Base.decl [concrete = constants.%Base.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc7_15.2 [symbolic = %T.loc7_15.1 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc8_22.1: type = ptr_type %T.ref [symbolic = %ptr.loc8_22.2 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     %Base.loc8_23.1: type = class_type @Base, @Base(constants.%ptr.e8f) [symbolic = %Base.loc8_23.2 (constants.%Base.f29)]\n// CHECK:STDOUT:     %.loc8: @Derived.%Derived.elem (%Derived.elem) = base_decl %Base.loc8_23.1, element0 [concrete]\n// CHECK:STDOUT:     %Derived.F.decl: @Derived.%Derived.F.type (%Derived.F.type) = fn_decl @Derived.F [symbolic = @Derived.%Derived.F (constants.%Derived.F)] {\n// CHECK:STDOUT:       %self.patt: @Derived.F.%pattern_type.loc9_24 (%pattern_type.b9d) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Derived.F.%pattern_type.loc9_24 (%pattern_type.b9d) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: @Derived.F.%pattern_type.loc9_43 (%pattern_type.4f4) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: @Derived.F.%pattern_type.loc9_43 (%pattern_type.4f4) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Derived.F.%Derived (%Derived) = value_param call_param0\n// CHECK:STDOUT:       %.loc9_30.1: type = splice_block %Self.ref [symbolic = %Derived (constants.%Derived)] {\n// CHECK:STDOUT:         %.loc9_30.2: type = specific_constant constants.%Derived, @Derived(constants.%T) [symbolic = %Derived (constants.%Derived)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc9_30.2 [symbolic = %Derived (constants.%Derived)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Derived.F.%Derived (%Derived) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: @Derived.F.%ptr.loc9_46 (%ptr.e8f) = value_param call_param1\n// CHECK:STDOUT:       %.loc9_47: type = splice_block %ptr.loc9_47 [symbolic = %ptr.loc9_46 (constants.%ptr.e8f)] {\n// CHECK:STDOUT:         %T.ref: type = name_ref T, @Derived.%T.loc7_15.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:         %ptr.loc9_47: type = ptr_type %T.ref [symbolic = %ptr.loc9_46 (constants.%ptr.e8f)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %t: @Derived.F.%ptr.loc9_46 (%ptr.e8f) = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Derived.F.specific_fn.loc10_1.1: <specific function> = specific_function %Derived.F.decl, @Derived.F(constants.%T) [symbolic = %Derived.F.specific_fn.loc10_1.2 (constants.%Derived.F.specific_fn)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:     %complete_type.loc10_1.1: <witness> = complete_type_witness constants.%struct_type.base.aa5 [symbolic = %complete_type.loc10_1.2 (constants.%complete_type.8c0)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc10_1.1\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Derived\n// CHECK:STDOUT:     .Base = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .base = %.loc8\n// CHECK:STDOUT:     .F = %Derived.F.decl\n// CHECK:STDOUT:     extend %Base.loc8_23.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.specific_fn.loc6_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   @Derived.%Derived.F.specific_fn.loc10_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @Base.F(@Base.%T.loc4_21.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:   %pattern_type.loc5_23: type = pattern_type %Base [symbolic = %pattern_type.loc5_23 (constants.%pattern_type.2f0)]\n// CHECK:STDOUT:   %pattern_type.loc5_42: type = pattern_type %T [symbolic = %pattern_type.loc5_42 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27: <witness> = require_complete_type %Base [symbolic = %require_complete.loc5_27 (constants.%require_complete.1e0)]\n// CHECK:STDOUT:   %require_complete.loc5_43: <witness> = require_complete_type %T [symbolic = %require_complete.loc5_43 (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @Base.F.%Base (%Base.d0c), %t.param: @Base.F.%T (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic override fn @Derived.F(@Derived.%T.loc7_15.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived, @Derived(%T) [symbolic = %Derived (constants.%Derived)]\n// CHECK:STDOUT:   %pattern_type.loc9_24: type = pattern_type %Derived [symbolic = %pattern_type.loc9_24 (constants.%pattern_type.b9d)]\n// CHECK:STDOUT:   %ptr.loc9_46: type = ptr_type %T [symbolic = %ptr.loc9_46 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%ptr.loc9_46) [symbolic = %Base (constants.%Base.f29)]\n// CHECK:STDOUT:   %require_complete.loc9_46: <witness> = require_complete_type %Base [symbolic = %require_complete.loc9_46 (constants.%require_complete.b3c)]\n// CHECK:STDOUT:   %pattern_type.loc9_43: type = pattern_type %ptr.loc9_46 [symbolic = %pattern_type.loc9_43 (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc9_28: <witness> = require_complete_type %Derived [symbolic = %require_complete.loc9_28 (constants.%require_complete.a43)]\n// CHECK:STDOUT:   %require_complete.loc9_44: <witness> = require_complete_type %ptr.loc9_46 [symbolic = %require_complete.loc9_44 (constants.%require_complete.ef1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   override fn(%self.param: @Derived.F.%Derived (%Derived), %t.param: @Derived.F.%ptr.loc9_46 (%ptr.e8f)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_21.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.0f1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.cd3\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2 => constants.%Base.F.specific_fn.f8c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Base => constants.%Base.d0c\n// CHECK:STDOUT:   %pattern_type.loc5_23 => constants.%pattern_type.2f0\n// CHECK:STDOUT:   %pattern_type.loc5_42 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27 => constants.%require_complete.1e0\n// CHECK:STDOUT:   %require_complete.loc5_43 => constants.%require_complete.944\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Derived(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_15.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ptr.loc8_22.2 => constants.%ptr.e8f\n// CHECK:STDOUT:   %Base.loc8_23.2 => constants.%Base.f29\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.b3c\n// CHECK:STDOUT:   %Derived => constants.%Derived\n// CHECK:STDOUT:   %Derived.elem => constants.%Derived.elem\n// CHECK:STDOUT:   %Derived.F.type => constants.%Derived.F.type\n// CHECK:STDOUT:   %Derived.F => constants.%Derived.F\n// CHECK:STDOUT:   %Derived.F.specific_fn.loc10_1.2 => constants.%Derived.F.specific_fn\n// CHECK:STDOUT:   %struct_type.base => constants.%struct_type.base.aa5\n// CHECK:STDOUT:   %complete_type.loc10_1.2 => constants.%complete_type.8c0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%ptr.e8f) {\n// CHECK:STDOUT:   %T.loc4_21.1 => constants.%ptr.e8f\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.c53\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.c0a\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2 => constants.%Base.F.specific_fn.35d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%ptr.e8f) {\n// CHECK:STDOUT:   %T => constants.%ptr.e8f\n// CHECK:STDOUT:   %Base => constants.%Base.f29\n// CHECK:STDOUT:   %pattern_type.loc5_23 => constants.%pattern_type.d96\n// CHECK:STDOUT:   %pattern_type.loc5_42 => constants.%pattern_type.4f4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_27 => constants.%require_complete.b3c\n// CHECK:STDOUT:   %require_complete.loc5_43 => constants.%require_complete.ef1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Derived.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Derived => constants.%Derived\n// CHECK:STDOUT:   %pattern_type.loc9_24 => constants.%pattern_type.b9d\n// CHECK:STDOUT:   %ptr.loc9_46 => constants.%ptr.e8f\n// CHECK:STDOUT:   %Base => constants.%Base.f29\n// CHECK:STDOUT:   %require_complete.loc9_46 => constants.%require_complete.b3c\n// CHECK:STDOUT:   %pattern_type.loc9_43 => constants.%pattern_type.4f4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc9_28 => constants.%require_complete.a43\n// CHECK:STDOUT:   %require_complete.loc9_44 => constants.%require_complete.ef1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- abstract_generic_undefined.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base.d0c: type = class_type @Base, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.2f0: type = pattern_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %Base.F.type.0f1: type = fn_type @Base.F, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F.cd3: %Base.F.type.0f1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.f8c: <specific function> = specific_function %Base.F.cd3, @Base.F(%T) [symbolic]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %Derived: type = class_type @Derived [concrete]\n// CHECK:STDOUT:   %Base.d5d: type = class_type @Base, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.type.cb1: type = fn_type @Base.F, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.eab: %Base.F.type.cb1 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.64f: type = pattern_type %Base.d5d [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.cd5: <specific function> = specific_function %Base.F.eab, @Base.F(%T1) [concrete]\n// CHECK:STDOUT:   %Derived.elem: type = unbound_element_type %Derived, %Base.d5d [concrete]\n// CHECK:STDOUT:   %pattern_type.9f6: type = pattern_type %Derived [concrete]\n// CHECK:STDOUT:   %Derived.F.type: type = fn_type @Derived.F [concrete]\n// CHECK:STDOUT:   %Derived.F: %Derived.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Derived.vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base.cc2: type = struct_type {.base: %Base.d5d} [concrete]\n// CHECK:STDOUT:   %complete_type.dcb: <witness> = complete_type_witness %struct_type.base.cc2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .Derived = %Derived.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: %Base.type = class_decl @Base [concrete = constants.%Base.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_25.1: type = splice_block %.loc4_25.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_25.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_21.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_21.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT:   %Derived.decl: type = class_decl @Derived [concrete = constants.%Derived] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(%T.loc4_21.2: type) {\n// CHECK:STDOUT:   %T.loc4_21.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_21.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T.loc4_21.1) [symbolic = %Base.F.type (constants.%Base.F.type.0f1)]\n// CHECK:STDOUT:   %Base.F: @Base.%Base.F.type (%Base.F.type.0f1) = struct_value () [symbolic = %Base.F (constants.%Base.F.cd3)]\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2: <specific function> = specific_function %Base.F, @Base.F(%T.loc4_21.1) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.F.decl: @Base.%Base.F.type (%Base.F.type.0f1) = fn_decl @Base.F [symbolic = @Base.%Base.F (constants.%Base.F.cd3)] {\n// CHECK:STDOUT:       %self.patt: @Base.F.%pattern_type (%pattern_type.2f0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Base.F.%pattern_type (%pattern_type.2f0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Base.F.%Base (%Base.d0c) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_23.1: type = splice_block %Self.ref [symbolic = %Base (constants.%Base.d0c)] {\n// CHECK:STDOUT:         %.loc5_23.2: type = specific_constant constants.%Base.d0c, @Base(constants.%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_23.2 [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Base.F.%Base (%Base.d0c) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Base.F.specific_fn.loc6_1.1: <specific function> = specific_function %Base.F.decl, @Base.F(constants.%T) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Base.d0c\n// CHECK:STDOUT:     .F = %Base.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1;\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Derived {\n// CHECK:STDOUT:   %Base.ref: %Base.type = name_ref Base, file.%Base.decl [concrete = constants.%Base.generic]\n// CHECK:STDOUT:   %T1.ref: type = name_ref T1, file.%T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(constants.%T1) [concrete = constants.%Base.d5d]\n// CHECK:STDOUT:   %.loc11: %Derived.elem = base_decl %Base, element0 [concrete]\n// CHECK:STDOUT:   %Derived.F.decl: %Derived.F.type = fn_decl @Derived.F [concrete = constants.%Derived.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.9f6 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.9f6 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Derived = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Derived [concrete = constants.%Derived]\n// CHECK:STDOUT:     %self: %Derived = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %vtable_decl: ref %ptr.454 = vtable_decl @Derived.vtable [concrete = constants.%Derived.vtable_decl]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.base.cc2 [concrete = constants.%complete_type.dcb]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:   vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Derived\n// CHECK:STDOUT:   .Base = <poisoned>\n// CHECK:STDOUT:   .T1 = <poisoned>\n// CHECK:STDOUT:   .base = %.loc11\n// CHECK:STDOUT:   .F = %Derived.F.decl\n// CHECK:STDOUT:   extend %Base\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.specific_fn.loc6_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Derived.vtable {\n// CHECK:STDOUT:   @Derived.%Derived.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic abstract fn @Base.F(@Base.%T.loc4_21.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Base [symbolic = %pattern_type (constants.%pattern_type.2f0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   abstract fn(%self.param: @Base.F.%Base (%Base.d0c));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_21.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Base => constants.%Base.d0c\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.2f0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T1) {\n// CHECK:STDOUT:   %T.loc4_21.1 => constants.%T1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.cb1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.eab\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2 => constants.%Base.F.specific_fn.cd5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T1) {\n// CHECK:STDOUT:   %T => constants.%T1\n// CHECK:STDOUT:   %Base => constants.%Base.d5d\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.64f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- generic_lib.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.2f0: type = pattern_type %Base [symbolic]\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F: %Base.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn: <specific function> = specific_function %Base.F, @Base.F(%T) [symbolic]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Base [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Base = %Base.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Base.decl: %Base.type = class_decl @Base [concrete = constants.%Base.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_21.1: type = splice_block %.loc4_21.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_21.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_17.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(%T.loc4_17.2: type) {\n// CHECK:STDOUT:   %T.loc4_17.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T.loc4_17.1) [symbolic = %Base.F.type (constants.%Base.F.type)]\n// CHECK:STDOUT:   %Base.F: @Base.%Base.F.type (%Base.F.type) = struct_value () [symbolic = %Base.F (constants.%Base.F)]\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2: <specific function> = specific_function %Base.F, @Base.F(%T.loc4_17.1) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Base.F.decl: @Base.%Base.F.type (%Base.F.type) = fn_decl @Base.F [symbolic = @Base.%Base.F (constants.%Base.F)] {\n// CHECK:STDOUT:       %self.patt: @Base.F.%pattern_type (%pattern_type.2f0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @Base.F.%pattern_type (%pattern_type.2f0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @Base.F.%Base (%Base) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_29.1: type = splice_block %Self.ref [symbolic = %Base (constants.%Base)] {\n// CHECK:STDOUT:         %.loc5_29.2: type = specific_constant constants.%Base, @Base(constants.%T) [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_29.2 [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @Base.F.%Base (%Base) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Base.F.specific_fn.loc6_1.1: <specific function> = specific_function %Base.F.decl, @Base.F(constants.%T) [symbolic = %Base.F.specific_fn.loc6_1.2 (constants.%Base.F.specific_fn)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Base\n// CHECK:STDOUT:     .F = %Base.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   @Base.%Base.F.specific_fn.loc6_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @Base.F(@Base.%T.loc4_17.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Base [symbolic = %pattern_type (constants.%pattern_type.2f0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Base [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @Base.F.%Base (%Base)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type\n// CHECK:STDOUT:   %Base.F => constants.%Base.F\n// CHECK:STDOUT:   %Base.F.specific_fn.loc6_1.2 => constants.%Base.F.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Base => constants.%Base\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.2f0\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- generic_import.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T1: type = class_type @T1 [concrete]\n// CHECK:STDOUT:   %Base.type: type = generic_class_type @Base [concrete]\n// CHECK:STDOUT:   %Base.generic: %Base.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Base.d0c: type = class_type @Base, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F.type.0f1: type = fn_type @Base.F, @Base(%T) [symbolic]\n// CHECK:STDOUT:   %Base.F.cd3: %Base.F.type.0f1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Base.F.specific_fn.f8c: <specific function> = specific_function %Base.F.cd3, @Base.F(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %pattern_type.2f0: type = pattern_type %Base.d0c [symbolic]\n// CHECK:STDOUT:   %Base.d5d: type = class_type @Base, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.type.cb1: type = fn_type @Base.F, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.F.eab: %Base.F.type.cb1 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.64f: type = pattern_type %Base.d5d [concrete]\n// CHECK:STDOUT:   %Base.F.specific_fn.cd5: <specific function> = specific_function %Base.F.eab, @Base.F(%T1) [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %.ae5: ref %ptr.454 = class_element_access file.%v.var, element0 [concrete]\n// CHECK:STDOUT:   %Base.vtable_decl: ref %ptr.454 = vtable_decl @Base.vtable [concrete]\n// CHECK:STDOUT:   %Base.vtable_ptr: ref %ptr.454 = vtable_ptr @Base.vtable, @Base(%T1) [concrete]\n// CHECK:STDOUT:   %Base.val: %Base.d5d = struct_value (%Base.vtable_ptr) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Base: %Base.type = import_ref Main//generic_lib, Base, loaded [concrete = constants.%Base.generic]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.1: type = import_ref Main//generic_lib, loc4_17, loaded [symbolic = @Base.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.462: ref %ptr.454 = import_ref Main//generic_lib, loc6_1, loaded [concrete = constants.%Base.vtable_decl]\n// CHECK:STDOUT:   %Main.import_ref.05e: <witness> = import_ref Main//generic_lib, loc6_1, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.2af = import_ref Main//generic_lib, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.1cf = import_ref Main//generic_lib, loc5_37, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//generic_lib, loc4_17, loaded [symbolic = @Base.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.4f0: <specific function> = import_ref Main//generic_lib, loc6_1, loaded [symbolic = constants.%Base.F.specific_fn.f8c]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Base = imports.%Main.Base\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .v = %v\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %T1.decl: type = class_decl @T1 [concrete = constants.%T1] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.64f = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.64f = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %Base.d5d = var %v.var_patt [concrete]\n// CHECK:STDOUT:   %.loc7: type = splice_block %Base [concrete = constants.%Base.d5d] {\n// CHECK:STDOUT:     %Base.ref: %Base.type = name_ref Base, imports.%Main.Base [concrete = constants.%Base.generic]\n// CHECK:STDOUT:     %T1.ref: type = name_ref T1, %T1.decl [concrete = constants.%T1]\n// CHECK:STDOUT:     %Base: type = class_type @Base, @Base(constants.%T1) [concrete = constants.%Base.d5d]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %Base.d5d = ref_binding v, %v.var [concrete = %v.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @T1;\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Base(imports.%Main.import_ref.b3bc94.2: type) [from \"generic_lib.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type: type = fn_type @Base.F, @Base(%T) [symbolic = %Base.F.type (constants.%Base.F.type.0f1)]\n// CHECK:STDOUT:   %Base.F: @Base.%Base.F.type (%Base.F.type.0f1) = struct_value () [symbolic = %Base.F (constants.%Base.F.cd3)]\n// CHECK:STDOUT:   %Base.F.specific_fn: <specific function> = specific_function %Base.F, @Base.F(%T) [symbolic = %Base.F.specific_fn (constants.%Base.F.specific_fn.f8c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.05e\n// CHECK:STDOUT:     vtable_decl = imports.%Main.import_ref.462\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.2af\n// CHECK:STDOUT:     .F = imports.%Main.import_ref.1cf\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @Base.vtable {\n// CHECK:STDOUT:   imports.%Main.import_ref.4f0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @Base.F(imports.%Main.import_ref.b3bc94.1: type) [from \"generic_lib.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base.d0c)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Base [symbolic = %pattern_type (constants.%pattern_type.2f0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Base [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc7_20.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc7_20.2: ref %ptr.454 = class_element_access file.%v.var, element0 [concrete = constants.%.ae5]\n// CHECK:STDOUT:   %Base.vtable_ptr: ref %ptr.454 = vtable_ptr @Base.vtable, @Base(constants.%T1) [concrete = constants.%Base.vtable_ptr]\n// CHECK:STDOUT:   %.loc7_20.3: init %ptr.454 to %.loc7_20.2 = in_place_init %Base.vtable_ptr [concrete = constants.%Base.vtable_ptr]\n// CHECK:STDOUT:   %.loc7_20.4: init %Base.d5d to file.%v.var = class_init (%.loc7_20.3) [concrete = constants.%Base.val]\n// CHECK:STDOUT:   %.loc7_1: init %Base.d5d = converted %.loc7_20.1, %.loc7_20.4 [concrete = constants.%Base.val]\n// CHECK:STDOUT:   assign file.%v.var, %.loc7_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.0f1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.cd3\n// CHECK:STDOUT:   %Base.F.specific_fn => constants.%Base.F.specific_fn.f8c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %Base => constants.%Base.d0c\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.2f0\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base(constants.%T1) {\n// CHECK:STDOUT:   %T => constants.%T1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Base.F.type => constants.%Base.F.type.cb1\n// CHECK:STDOUT:   %Base.F => constants.%Base.F.eab\n// CHECK:STDOUT:   %Base.F.specific_fn => constants.%Base.F.specific_fn.cd5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Base.F(constants.%T1) {\n// CHECK:STDOUT:   %T => constants.%T1\n// CHECK:STDOUT:   %Base => constants.%Base.d5d\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.64f\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- generic_derived_generic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %G1: type = symbolic_binding G1, 0 [symbolic]\n// CHECK:STDOUT:   %T1.type: type = generic_class_type @T1 [concrete]\n// CHECK:STDOUT:   %T1.generic: %T1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T1.6d4458.1: type = class_type @T1, @T1(%G1) [symbolic]\n// CHECK:STDOUT:   %pattern_type.253617.1: type = pattern_type %T1.6d4458.1 [symbolic]\n// CHECK:STDOUT:   %T1.F.type.e39697.1: type = fn_type @T1.F, @T1(%G1) [symbolic]\n// CHECK:STDOUT:   %T1.F.9b864d.1: %T1.F.type.e39697.1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %T1.F.specific_fn.46dc79.1: <specific function> = specific_function %T1.F.9b864d.1, @T1.F(%G1) [symbolic]\n// CHECK:STDOUT:   %T1.vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete.6d26d2.1: <witness> = require_complete_type %T1.6d4458.1 [symbolic]\n// CHECK:STDOUT:   %G2: type = symbolic_binding G2, 0 [symbolic]\n// CHECK:STDOUT:   %T2.type: type = generic_class_type @T2 [concrete]\n// CHECK:STDOUT:   %T2.generic: %T2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T2: type = class_type @T2, @T2(%G2) [symbolic]\n// CHECK:STDOUT:   %T1.6d4458.2: type = class_type @T1, @T1(%G2) [symbolic]\n// CHECK:STDOUT:   %T1.F.type.e39697.2: type = fn_type @T1.F, @T1(%G2) [symbolic]\n// CHECK:STDOUT:   %T1.F.9b864d.2: %T1.F.type.e39697.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.253617.2: type = pattern_type %T1.6d4458.2 [symbolic]\n// CHECK:STDOUT:   %T1.F.specific_fn.46dc79.2: <specific function> = specific_function %T1.F.9b864d.2, @T1.F(%G2) [symbolic]\n// CHECK:STDOUT:   %require_complete.6d26d2.2: <witness> = require_complete_type %T1.6d4458.2 [symbolic]\n// CHECK:STDOUT:   %T2.elem: type = unbound_element_type %T2, %T1.6d4458.2 [symbolic]\n// CHECK:STDOUT:   %T2.vtable_decl: ref %ptr.454 = vtable_decl @T2.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %T1.6d4458.2} [symbolic]\n// CHECK:STDOUT:   %complete_type.fc6: <witness> = complete_type_witness %struct_type.base [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .T2 = %T2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: %T1.type = class_decl @T1 [concrete = constants.%T1.generic] {\n// CHECK:STDOUT:     %G1.patt: %pattern_type.98f = symbolic_binding_pattern G1, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_20.1: type = splice_block %.loc4_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %G1.loc4_15.2: type = symbolic_binding G1, 0 [symbolic = %G1.loc4_15.1 (constants.%G1)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %T2.decl: %T2.type = class_decl @T2 [concrete = constants.%T2.generic] {\n// CHECK:STDOUT:     %G2.patt: %pattern_type.98f = symbolic_binding_pattern G2, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_15.1: type = splice_block %.loc8_15.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_15.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %G2.loc8_10.2: type = symbolic_binding G2, 0 [symbolic = %G2.loc8_10.1 (constants.%G2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @T1(%G1.loc4_15.2: type) {\n// CHECK:STDOUT:   %G1.loc4_15.1: type = symbolic_binding G1, 0 [symbolic = %G1.loc4_15.1 (constants.%G1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%G1.loc4_15.1) [symbolic = %T1.F.type (constants.%T1.F.type.e39697.1)]\n// CHECK:STDOUT:   %T1.F: @T1.%T1.F.type (%T1.F.type.e39697.1) = struct_value () [symbolic = %T1.F (constants.%T1.F.9b864d.1)]\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2: <specific function> = specific_function %T1.F, @T1.F(%G1.loc4_15.1) [symbolic = %T1.F.specific_fn.loc6_1.2 (constants.%T1.F.specific_fn.46dc79.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T1.F.decl: @T1.%T1.F.type (%T1.F.type.e39697.1) = fn_decl @T1.F [symbolic = @T1.%T1.F (constants.%T1.F.9b864d.1)] {\n// CHECK:STDOUT:       %self.patt: @T1.F.%pattern_type (%pattern_type.253617.1) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @T1.F.%pattern_type (%pattern_type.253617.1) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @T1.F.%T1 (%T1.6d4458.1) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_29.1: type = splice_block %Self.ref [symbolic = %T1 (constants.%T1.6d4458.1)] {\n// CHECK:STDOUT:         %.loc5_29.2: type = specific_constant constants.%T1.6d4458.1, @T1(constants.%G1) [symbolic = %T1 (constants.%T1.6d4458.1)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_29.2 [symbolic = %T1 (constants.%T1.6d4458.1)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @T1.F.%T1 (%T1.6d4458.1) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T1.F.specific_fn.loc6_1.1: <specific function> = specific_function %T1.F.decl, @T1.F(constants.%G1) [symbolic = %T1.F.specific_fn.loc6_1.2 (constants.%T1.F.specific_fn.46dc79.1)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete = constants.%T1.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%T1.6d4458.1\n// CHECK:STDOUT:     .F = %T1.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @T2(%G2.loc8_10.2: type) {\n// CHECK:STDOUT:   %G2.loc8_10.1: type = symbolic_binding G2, 0 [symbolic = %G2.loc8_10.1 (constants.%G2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.loc9_21.2: type = class_type @T1, @T1(%G2.loc8_10.1) [symbolic = %T1.loc9_21.2 (constants.%T1.6d4458.2)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T1.loc9_21.2 [symbolic = %require_complete (constants.%require_complete.6d26d2.2)]\n// CHECK:STDOUT:   %T2: type = class_type @T2, @T2(%G2.loc8_10.1) [symbolic = %T2 (constants.%T2)]\n// CHECK:STDOUT:   %T2.elem: type = unbound_element_type %T2, %T1.loc9_21.2 [symbolic = %T2.elem (constants.%T2.elem)]\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%G2.loc8_10.1) [symbolic = %T1.F.type (constants.%T1.F.type.e39697.2)]\n// CHECK:STDOUT:   %T1.F: @T2.%T1.F.type (%T1.F.type.e39697.2) = struct_value () [symbolic = %T1.F (constants.%T1.F.9b864d.2)]\n// CHECK:STDOUT:   %T1.F.specific_fn.loc10_1.2: <specific function> = specific_function %T1.F, @T1.F(%G2.loc8_10.1) [symbolic = %T1.F.specific_fn.loc10_1.2 (constants.%T1.F.specific_fn.46dc79.2)]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: @T2.%T1.loc9_21.2 (%T1.6d4458.2)} [symbolic = %struct_type.base (constants.%struct_type.base)]\n// CHECK:STDOUT:   %complete_type.loc10_1.2: <witness> = complete_type_witness %struct_type.base [symbolic = %complete_type.loc10_1.2 (constants.%complete_type.fc6)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T1.ref: %T1.type = name_ref T1, file.%T1.decl [concrete = constants.%T1.generic]\n// CHECK:STDOUT:     %G2.ref: type = name_ref G2, %G2.loc8_10.2 [symbolic = %G2.loc8_10.1 (constants.%G2)]\n// CHECK:STDOUT:     %T1.loc9_21.1: type = class_type @T1, @T1(constants.%G2) [symbolic = %T1.loc9_21.2 (constants.%T1.6d4458.2)]\n// CHECK:STDOUT:     %.loc9: @T2.%T2.elem (%T2.elem) = base_decl %T1.loc9_21.1, element0 [concrete]\n// CHECK:STDOUT:     %T1.F.specific_fn.loc10_1.1: <specific function> = specific_function constants.%T1.F.9b864d.2, @T1.F(constants.%G2) [symbolic = %T1.F.specific_fn.loc10_1.2 (constants.%T1.F.specific_fn.46dc79.2)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @T2.vtable [concrete = constants.%T2.vtable_decl]\n// CHECK:STDOUT:     %complete_type.loc10_1.1: <witness> = complete_type_witness constants.%struct_type.base [symbolic = %complete_type.loc10_1.2 (constants.%complete_type.fc6)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc10_1.1\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%T2\n// CHECK:STDOUT:     .T1 = <poisoned>\n// CHECK:STDOUT:     .G2 = <poisoned>\n// CHECK:STDOUT:     .base = %.loc9\n// CHECK:STDOUT:     extend %T1.loc9_21.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @T1.vtable {\n// CHECK:STDOUT:   @T1.%T1.F.specific_fn.loc6_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @T2.vtable {\n// CHECK:STDOUT:   @T2.%T1.F.specific_fn.loc10_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @T1.F(@T1.%G1.loc4_15.2: type) {\n// CHECK:STDOUT:   %G1: type = symbolic_binding G1, 0 [symbolic = %G1 (constants.%G1)]\n// CHECK:STDOUT:   %T1: type = class_type @T1, @T1(%G1) [symbolic = %T1 (constants.%T1.6d4458.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T1 [symbolic = %pattern_type (constants.%pattern_type.253617.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T1 [symbolic = %require_complete (constants.%require_complete.6d26d2.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @T1.F.%T1 (%T1.6d4458.1)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1(constants.%G1) {\n// CHECK:STDOUT:   %G1.loc4_15.1 => constants.%G1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type => constants.%T1.F.type.e39697.1\n// CHECK:STDOUT:   %T1.F => constants.%T1.F.9b864d.1\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2 => constants.%T1.F.specific_fn.46dc79.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1.F(constants.%G1) {\n// CHECK:STDOUT:   %G1 => constants.%G1\n// CHECK:STDOUT:   %T1 => constants.%T1.6d4458.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.253617.1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.6d26d2.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T2(constants.%G2) {\n// CHECK:STDOUT:   %G2.loc8_10.1 => constants.%G2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1(constants.%G2) {\n// CHECK:STDOUT:   %G1.loc4_15.1 => constants.%G2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type => constants.%T1.F.type.e39697.2\n// CHECK:STDOUT:   %T1.F => constants.%T1.F.9b864d.2\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2 => constants.%T1.F.specific_fn.46dc79.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1.F(constants.%G2) {\n// CHECK:STDOUT:   %G1 => constants.%G2\n// CHECK:STDOUT:   %T1 => constants.%T1.6d4458.2\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.253617.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.6d26d2.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- generic_derived_generic_context.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %G1: type = symbolic_binding G1, 0 [symbolic]\n// CHECK:STDOUT:   %T1.type: type = generic_class_type @T1 [concrete]\n// CHECK:STDOUT:   %T1.generic: %T1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T1.6d4458.1: type = class_type @T1, @T1(%G1) [symbolic]\n// CHECK:STDOUT:   %pattern_type.253617.1: type = pattern_type %T1.6d4458.1 [symbolic]\n// CHECK:STDOUT:   %T1.F.type.e39697.1: type = fn_type @T1.F, @T1(%G1) [symbolic]\n// CHECK:STDOUT:   %T1.F.9b864d.1: %T1.F.type.e39697.1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.454: type = ptr_type <vtable> [concrete]\n// CHECK:STDOUT:   %T1.F.specific_fn.46dc79.1: <specific function> = specific_function %T1.F.9b864d.1, @T1.F(%G1) [symbolic]\n// CHECK:STDOUT:   %T1.vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.vptr: type = struct_type {.<vptr>: %ptr.454} [concrete]\n// CHECK:STDOUT:   %complete_type.513: <witness> = complete_type_witness %struct_type.vptr [concrete]\n// CHECK:STDOUT:   %require_complete.6d26d2.1: <witness> = require_complete_type %T1.6d4458.1 [symbolic]\n// CHECK:STDOUT:   %G2: type = symbolic_binding G2, 0 [symbolic]\n// CHECK:STDOUT:   %T2.type: type = generic_class_type @T2 [concrete]\n// CHECK:STDOUT:   %T2.generic: %T2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T2: type = class_type @T2, @T2(%G2) [symbolic]\n// CHECK:STDOUT:   %T3: type = class_type @T3, @T3(%G2) [symbolic]\n// CHECK:STDOUT:   %T1.6d4458.2: type = class_type @T1, @T1(%G2) [symbolic]\n// CHECK:STDOUT:   %T1.F.type.e39697.2: type = fn_type @T1.F, @T1(%G2) [symbolic]\n// CHECK:STDOUT:   %T1.F.9b864d.2: %T1.F.type.e39697.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.253617.2: type = pattern_type %T1.6d4458.2 [symbolic]\n// CHECK:STDOUT:   %T1.F.specific_fn.46dc79.2: <specific function> = specific_function %T1.F.9b864d.2, @T1.F(%G2) [symbolic]\n// CHECK:STDOUT:   %require_complete.6d26d2.2: <witness> = require_complete_type %T1.6d4458.2 [symbolic]\n// CHECK:STDOUT:   %T3.elem: type = unbound_element_type %T3, %T1.6d4458.2 [symbolic]\n// CHECK:STDOUT:   %T3.vtable_decl: ref %ptr.454 = vtable_decl @T3.vtable [concrete]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: %T1.6d4458.2} [symbolic]\n// CHECK:STDOUT:   %complete_type.fc6: <witness> = complete_type_witness %struct_type.base [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .T1 = %T1.decl\n// CHECK:STDOUT:     .T2 = %T2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %T1.decl: %T1.type = class_decl @T1 [concrete = constants.%T1.generic] {\n// CHECK:STDOUT:     %G1.patt: %pattern_type.98f = symbolic_binding_pattern G1, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_20.1: type = splice_block %.loc4_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %G1.loc4_15.2: type = symbolic_binding G1, 0 [symbolic = %G1.loc4_15.1 (constants.%G1)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %T2.decl: %T2.type = class_decl @T2 [concrete = constants.%T2.generic] {\n// CHECK:STDOUT:     %G2.patt: %pattern_type.98f = symbolic_binding_pattern G2, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_15.1: type = splice_block %.loc8_15.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_15.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %G2.loc8_10.2: type = symbolic_binding G2, 0 [symbolic = %G2.loc8_10.1 (constants.%G2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @T1(%G1.loc4_15.2: type) {\n// CHECK:STDOUT:   %G1.loc4_15.1: type = symbolic_binding G1, 0 [symbolic = %G1.loc4_15.1 (constants.%G1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%G1.loc4_15.1) [symbolic = %T1.F.type (constants.%T1.F.type.e39697.1)]\n// CHECK:STDOUT:   %T1.F: @T1.%T1.F.type (%T1.F.type.e39697.1) = struct_value () [symbolic = %T1.F (constants.%T1.F.9b864d.1)]\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2: <specific function> = specific_function %T1.F, @T1.F(%G1.loc4_15.1) [symbolic = %T1.F.specific_fn.loc6_1.2 (constants.%T1.F.specific_fn.46dc79.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T1.F.decl: @T1.%T1.F.type (%T1.F.type.e39697.1) = fn_decl @T1.F [symbolic = @T1.%T1.F (constants.%T1.F.9b864d.1)] {\n// CHECK:STDOUT:       %self.patt: @T1.F.%pattern_type (%pattern_type.253617.1) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @T1.F.%pattern_type (%pattern_type.253617.1) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @T1.F.%T1 (%T1.6d4458.1) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_29.1: type = splice_block %Self.ref [symbolic = %T1 (constants.%T1.6d4458.1)] {\n// CHECK:STDOUT:         %.loc5_29.2: type = specific_constant constants.%T1.6d4458.1, @T1(constants.%G1) [symbolic = %T1 (constants.%T1.6d4458.1)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc5_29.2 [symbolic = %T1 (constants.%T1.6d4458.1)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @T1.F.%T1 (%T1.6d4458.1) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T1.F.specific_fn.loc6_1.1: <specific function> = specific_function %T1.F.decl, @T1.F(constants.%G1) [symbolic = %T1.F.specific_fn.loc6_1.2 (constants.%T1.F.specific_fn.46dc79.1)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @T1.vtable [concrete = constants.%T1.vtable_decl]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%struct_type.vptr [concrete = constants.%complete_type.513]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%T1.6d4458.1\n// CHECK:STDOUT:     .F = %T1.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @T2(%G2.loc8_10.2: type) {\n// CHECK:STDOUT:   %G2.loc8_10.1: type = symbolic_binding G2, 0 [symbolic = %G2.loc8_10.1 (constants.%G2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T3: type = class_type @T3, @T3(%G2.loc8_10.1) [symbolic = %T3 (constants.%T3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T3.decl: type = class_decl @T3 [symbolic = @T2.%T3 (constants.%T3)] {} {}\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%T2\n// CHECK:STDOUT:     .T3 = %T3.decl\n// CHECK:STDOUT:     .T1 = <poisoned>\n// CHECK:STDOUT:     .G2 = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @T3(@T2.%G2.loc8_10.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %G2: type = symbolic_binding G2, 0 [symbolic = %G2 (constants.%G2)]\n// CHECK:STDOUT:   %T1.loc10_24.2: type = class_type @T1, @T1(%G2) [symbolic = %T1.loc10_24.2 (constants.%T1.6d4458.2)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T1.loc10_24.2 [symbolic = %require_complete (constants.%require_complete.6d26d2.2)]\n// CHECK:STDOUT:   %T3: type = class_type @T3, @T3(%G2) [symbolic = %T3 (constants.%T3)]\n// CHECK:STDOUT:   %T3.elem: type = unbound_element_type %T3, %T1.loc10_24.2 [symbolic = %T3.elem (constants.%T3.elem)]\n// CHECK:STDOUT:   %T1.F.type: type = fn_type @T1.F, @T1(%G2) [symbolic = %T1.F.type (constants.%T1.F.type.e39697.2)]\n// CHECK:STDOUT:   %T1.F: @T3.%T1.F.type (%T1.F.type.e39697.2) = struct_value () [symbolic = %T1.F (constants.%T1.F.9b864d.2)]\n// CHECK:STDOUT:   %T1.F.specific_fn.loc11_3.2: <specific function> = specific_function %T1.F, @T1.F(%G2) [symbolic = %T1.F.specific_fn.loc11_3.2 (constants.%T1.F.specific_fn.46dc79.2)]\n// CHECK:STDOUT:   %struct_type.base: type = struct_type {.base: @T3.%T1.loc10_24.2 (%T1.6d4458.2)} [symbolic = %struct_type.base (constants.%struct_type.base)]\n// CHECK:STDOUT:   %complete_type.loc11_3.2: <witness> = complete_type_witness %struct_type.base [symbolic = %complete_type.loc11_3.2 (constants.%complete_type.fc6)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T1.ref: %T1.type = name_ref T1, file.%T1.decl [concrete = constants.%T1.generic]\n// CHECK:STDOUT:     %G2.ref: type = name_ref G2, @T2.%G2.loc8_10.2 [symbolic = %G2 (constants.%G2)]\n// CHECK:STDOUT:     %T1.loc10_24.1: type = class_type @T1, @T1(constants.%G2) [symbolic = %T1.loc10_24.2 (constants.%T1.6d4458.2)]\n// CHECK:STDOUT:     %.loc10: @T3.%T3.elem (%T3.elem) = base_decl %T1.loc10_24.1, element0 [concrete]\n// CHECK:STDOUT:     %T1.F.specific_fn.loc11_3.1: <specific function> = specific_function constants.%T1.F.9b864d.2, @T1.F(constants.%G2) [symbolic = %T1.F.specific_fn.loc11_3.2 (constants.%T1.F.specific_fn.46dc79.2)]\n// CHECK:STDOUT:     %vtable_decl: ref %ptr.454 = vtable_decl @T3.vtable [concrete = constants.%T3.vtable_decl]\n// CHECK:STDOUT:     %complete_type.loc11_3.1: <witness> = complete_type_witness constants.%struct_type.base [symbolic = %complete_type.loc11_3.2 (constants.%complete_type.fc6)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc11_3.1\n// CHECK:STDOUT:     vtable_decl = %vtable_decl\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%T3\n// CHECK:STDOUT:     .T1 = <poisoned>\n// CHECK:STDOUT:     .G2 = <poisoned>\n// CHECK:STDOUT:     .base = %.loc10\n// CHECK:STDOUT:     extend %T1.loc10_24.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @T1.vtable {\n// CHECK:STDOUT:   @T1.%T1.F.specific_fn.loc6_1.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: vtable @T3.vtable {\n// CHECK:STDOUT:   @T3.%T1.F.specific_fn.loc11_3.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic virtual fn @T1.F(@T1.%G1.loc4_15.2: type) {\n// CHECK:STDOUT:   %G1: type = symbolic_binding G1, 0 [symbolic = %G1 (constants.%G1)]\n// CHECK:STDOUT:   %T1: type = class_type @T1, @T1(%G1) [symbolic = %T1 (constants.%T1.6d4458.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T1 [symbolic = %pattern_type (constants.%pattern_type.253617.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T1 [symbolic = %require_complete (constants.%require_complete.6d26d2.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   virtual fn(%self.param: @T1.F.%T1 (%T1.6d4458.1)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1(constants.%G1) {\n// CHECK:STDOUT:   %G1.loc4_15.1 => constants.%G1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type => constants.%T1.F.type.e39697.1\n// CHECK:STDOUT:   %T1.F => constants.%T1.F.9b864d.1\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2 => constants.%T1.F.specific_fn.46dc79.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1.F(constants.%G1) {\n// CHECK:STDOUT:   %G1 => constants.%G1\n// CHECK:STDOUT:   %T1 => constants.%T1.6d4458.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.253617.1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.6d26d2.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T2(constants.%G2) {\n// CHECK:STDOUT:   %G2.loc8_10.1 => constants.%G2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T3(constants.%G2) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1(constants.%G2) {\n// CHECK:STDOUT:   %G1.loc4_15.1 => constants.%G2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T1.F.type => constants.%T1.F.type.e39697.2\n// CHECK:STDOUT:   %T1.F => constants.%T1.F.9b864d.2\n// CHECK:STDOUT:   %T1.F.specific_fn.loc6_1.2 => constants.%T1.F.specific_fn.46dc79.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T1.F(constants.%G2) {\n// CHECK:STDOUT:   %G1 => constants.%G2\n// CHECK:STDOUT:   %T1 => constants.%T1.6d4458.2\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.253617.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.6d26d2.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/const/basics.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/const/basics.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/const/basics.carbon\n\n// --- basic.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n//@dump-sem-ir-begin\nfn A(p: const C**) -> const C** {\n  return p;\n}\n\nfn B(p: const (C*)) -> const (C*) {\n  return p;\n}\n//@dump-sem-ir-end\n\n// --- collapse.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n// OK, `const (const C)` is the same type as `const C`.\n//@dump-sem-ir-begin\n// CHECK:STDERR: collapse.carbon:[[@LINE+4]]:23: warning: `const` applied repeatedly to the same type has no additional effect [RepeatedConst]\n// CHECK:STDERR: fn F(p: const C**) -> const (const C)** {\n// CHECK:STDERR:                       ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(p: const C**) -> const (const C)** {\n  return p;\n}\n//@dump-sem-ir-end\n\n// --- fail_collapse_in_error.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\n\n// CHECK:STDERR: fail_collapse_in_error.carbon:[[@LINE+4]]:9: warning: `const` applied repeatedly to the same type has no additional effect [RepeatedConst]\n// CHECK:STDERR: fn G(p: const (const C)**) -> C** {\n// CHECK:STDERR:         ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn G(p: const (const C)**) -> C** {\n  // CHECK:STDERR: fail_collapse_in_error.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `const C**` to `C**` [ConversionFailure]\n  // CHECK:STDERR:   return p;\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_collapse_in_error.carbon:[[@LINE+4]]:3: note: type `const C**` does not implement interface `Core.ImplicitAs(C**)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return p;\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR:\n  return p;\n}\n\n// --- add_or_remove_while_forming_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nfn TakeValue(unused x: X) {}\nfn TakeConstValue(unused x: const X) {}\n\nfn PassConstValueToValue(a: const X) {\n  TakeValue(a);\n}\n\nfn PassValueToConstValue(a: X) {\n  TakeConstValue(a);\n}\n\nfn PassConstReferenceToValue(p: const X*) {\n  TakeValue(*p);\n}\n\nfn PassReferenceToConstValue(p: X*) {\n  TakeConstValue(*p);\n}\n\n// --- add_or_remove_while_initializing.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {}\n\nvar init_non_const_from_non_const: X = {} as X;\nvar init_non_const_from_const: X = ({} as X) as const X;\nvar init_const_from_non_const: const X = {} as X;\nvar init_const_from_const: const X = ({} as X) as const X;\n\n// --- add_while_forming_reference.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {\n  fn TakeConstSelf[ref self: const Self]();\n}\n\nfn PassReferenceToConstReference(p: X*) {\n  p->TakeConstSelf();\n}\n\n// --- fail_remove_while_forming_reference.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass X {\n  fn TakeSelf[ref self: Self]();\n}\n\nfn PassConstReferenceToReference(p: const X*) {\n  // CHECK:STDERR: fail_remove_while_forming_reference.carbon:[[@LINE+10]]:3: error: cannot implicitly convert expression of type `const X` to `X` [ConversionFailure]\n  // CHECK:STDERR:   p->(X.TakeSelf)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_remove_while_forming_reference.carbon:[[@LINE+7]]:3: note: type `const X` does not implement interface `Core.ImplicitAs(X)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   p->(X.TakeSelf)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_remove_while_forming_reference.carbon:[[@LINE-10]]:15: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR:   fn TakeSelf[ref self: Self]();\n  // CHECK:STDERR:               ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  p->(X.TakeSelf)();\n}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %const.0e5: type = const_type %C [concrete]\n// CHECK:STDOUT:   %ptr.c45: type = ptr_type %const.0e5 [concrete]\n// CHECK:STDOUT:   %ptr.728: type = ptr_type %ptr.c45 [concrete]\n// CHECK:STDOUT:   %pattern_type.559: type = pattern_type %ptr.728 [concrete]\n// CHECK:STDOUT:   %.674: Core.Form = init_form %ptr.728 [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %const.as.Copy.impl.Op.type.5eb: type = fn_type @const.as.Copy.impl.Op, @const.as.Copy.impl(%T.035) [symbolic]\n// CHECK:STDOUT:   %const.as.Copy.impl.Op.cc6: %const.as.Copy.impl.Op.type.5eb = struct_value () [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.795: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%ptr.c45) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.f8c: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%ptr.c45) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.f64: %ptr.as.Copy.impl.Op.type.f8c = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.d1d: %Copy.type = facet_value %ptr.728, (%Copy.impl_witness.795) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.b3a: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.d1d) [concrete]\n// CHECK:STDOUT:   %.53f: type = fn_type_with_self_type %Copy.WithSelf.Op.type.b3a, %Copy.facet.d1d [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn.6a7: <specific function> = specific_function %ptr.as.Copy.impl.Op.f64, @ptr.as.Copy.impl.Op(%ptr.c45) [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %const.8ce: type = const_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %pattern_type.665: type = pattern_type %const.8ce [concrete]\n// CHECK:STDOUT:   %.d7d: Core.Form = init_form %const.8ce [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %Copy.facet.a7f: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.e93: <witness> = impl_witness imports.%Copy.impl_witness_table.a26, @const.as.Copy.impl(%Copy.facet.a7f) [concrete]\n// CHECK:STDOUT:   %const.as.Copy.impl.Op.type.368: type = fn_type @const.as.Copy.impl.Op, @const.as.Copy.impl(%Copy.facet.a7f) [concrete]\n// CHECK:STDOUT:   %const.as.Copy.impl.Op.c19: %const.as.Copy.impl.Op.type.368 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.5cc: %Copy.type = facet_value %const.8ce, (%Copy.impl_witness.e93) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.b95: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.5cc) [concrete]\n// CHECK:STDOUT:   %.21b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.b95, %Copy.facet.5cc [concrete]\n// CHECK:STDOUT:   %const.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %const.as.Copy.impl.Op.c19, @const.as.Copy.impl.Op(%Copy.facet.a7f) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.ae5: @const.as.Copy.impl.%const.as.Copy.impl.Op.type (%const.as.Copy.impl.Op.type.5eb) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @const.as.Copy.impl.%const.as.Copy.impl.Op (constants.%const.as.Copy.impl.Op.cc6)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.a26 = impl_witness_table (%Core.import_ref.ae5), @const.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.559 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.559 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.559 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.559 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc6_29: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %const.loc6_23: type = const_type %C.ref.loc6_29 [concrete = constants.%const.0e5]\n// CHECK:STDOUT:     %ptr.loc6_30: type = ptr_type %const.loc6_23 [concrete = constants.%ptr.c45]\n// CHECK:STDOUT:     %ptr.loc6_31: type = ptr_type %ptr.loc6_30 [concrete = constants.%ptr.728]\n// CHECK:STDOUT:     %.loc6_31: Core.Form = init_form %ptr.loc6_31 [concrete = constants.%.674]\n// CHECK:STDOUT:     %p.param: %ptr.728 = value_param call_param0\n// CHECK:STDOUT:     %.loc6_17: type = splice_block %ptr.loc6_17 [concrete = constants.%ptr.728] {\n// CHECK:STDOUT:       %C.ref.loc6_15: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %const.loc6_9: type = const_type %C.ref.loc6_15 [concrete = constants.%const.0e5]\n// CHECK:STDOUT:       %ptr.loc6_16: type = ptr_type %const.loc6_9 [concrete = constants.%ptr.c45]\n// CHECK:STDOUT:       %ptr.loc6_17: type = ptr_type %ptr.loc6_16 [concrete = constants.%ptr.728]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.728 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %ptr.728 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.728 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.665 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.665 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.665 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.665 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc10_31: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %ptr.loc10_32: type = ptr_type %C.ref.loc10_31 [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:     %const.loc10_24: type = const_type %ptr.loc10_32 [concrete = constants.%const.8ce]\n// CHECK:STDOUT:     %.loc10_24: Core.Form = init_form %const.loc10_24 [concrete = constants.%.d7d]\n// CHECK:STDOUT:     %p.param: %const.8ce = value_param call_param0\n// CHECK:STDOUT:     %.loc10_9: type = splice_block %const.loc10_9 [concrete = constants.%const.8ce] {\n// CHECK:STDOUT:       %C.ref.loc10_16: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %ptr.loc10_17: type = ptr_type %C.ref.loc10_16 [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:       %const.loc10_9: type = const_type %ptr.loc10_17 [concrete = constants.%const.8ce]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %const.8ce = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %const.8ce = out_param call_param1\n// CHECK:STDOUT:     %return: ref %const.8ce = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A(%p.param: %ptr.728) -> out %return.param: %ptr.728 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.728 = name_ref p, %p\n// CHECK:STDOUT:   %impl.elem0: %.53f = impl_witness_access constants.%Copy.impl_witness.795, element0 [concrete = constants.%ptr.as.Copy.impl.Op.f64]\n// CHECK:STDOUT:   %bound_method.loc7_10.1: <bound method> = bound_method %p.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%ptr.c45) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn.6a7]\n// CHECK:STDOUT:   %bound_method.loc7_10.2: <bound method> = bound_method %p.ref, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.728 = call %bound_method.loc7_10.2(%p.ref)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B(%p.param: %const.8ce) -> out %return.param: %const.8ce {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %const.8ce = name_ref p, %p\n// CHECK:STDOUT:   %impl.elem0: %.21b = impl_witness_access constants.%Copy.impl_witness.e93, element0 [concrete = constants.%const.as.Copy.impl.Op.c19]\n// CHECK:STDOUT:   %bound_method.loc11_10.1: <bound method> = bound_method %p.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @const.as.Copy.impl.Op(constants.%Copy.facet.a7f) [concrete = constants.%const.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc11_10.2: <bound method> = bound_method %p.ref, %specific_fn\n// CHECK:STDOUT:   %const.as.Copy.impl.Op.call: init %const.8ce = call %bound_method.loc11_10.2(%p.ref)\n// CHECK:STDOUT:   return %const.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- collapse.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %const.0e5: type = const_type %C [concrete]\n// CHECK:STDOUT:   %ptr.c45: type = ptr_type %const.0e5 [concrete]\n// CHECK:STDOUT:   %ptr.728: type = ptr_type %ptr.c45 [concrete]\n// CHECK:STDOUT:   %pattern_type.559: type = pattern_type %ptr.728 [concrete]\n// CHECK:STDOUT:   %.674: Core.Form = init_form %ptr.728 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.795: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%ptr.c45) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.f8c: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%ptr.c45) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.f64: %ptr.as.Copy.impl.Op.type.f8c = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.728, (%Copy.impl_witness.795) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.b3a: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.53f: type = fn_type_with_self_type %Copy.WithSelf.Op.type.b3a, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.f64, @ptr.as.Copy.impl.Op(%ptr.c45) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.559 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.559 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.559 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.559 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc11_36: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %const.loc11_30: type = const_type %C.ref.loc11_36 [concrete = constants.%const.0e5]\n// CHECK:STDOUT:     %const.loc11_23: type = const_type %const.loc11_30 [concrete = constants.%const.0e5]\n// CHECK:STDOUT:     %ptr.loc11_38: type = ptr_type %const.loc11_23 [concrete = constants.%ptr.c45]\n// CHECK:STDOUT:     %ptr.loc11_39: type = ptr_type %ptr.loc11_38 [concrete = constants.%ptr.728]\n// CHECK:STDOUT:     %.loc11_39: Core.Form = init_form %ptr.loc11_39 [concrete = constants.%.674]\n// CHECK:STDOUT:     %p.param: %ptr.728 = value_param call_param0\n// CHECK:STDOUT:     %.loc11_17: type = splice_block %ptr.loc11_17 [concrete = constants.%ptr.728] {\n// CHECK:STDOUT:       %C.ref.loc11_15: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %const.loc11_9: type = const_type %C.ref.loc11_15 [concrete = constants.%const.0e5]\n// CHECK:STDOUT:       %ptr.loc11_16: type = ptr_type %const.loc11_9 [concrete = constants.%ptr.c45]\n// CHECK:STDOUT:       %ptr.loc11_17: type = ptr_type %ptr.loc11_16 [concrete = constants.%ptr.728]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.728 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %ptr.728 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.728 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%p.param: %ptr.728) -> out %return.param: %ptr.728 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr.728 = name_ref p, %p\n// CHECK:STDOUT:   %impl.elem0: %.53f = impl_witness_access constants.%Copy.impl_witness.795, element0 [concrete = constants.%ptr.as.Copy.impl.Op.f64]\n// CHECK:STDOUT:   %bound_method.loc12_10.1: <bound method> = bound_method %p.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%ptr.c45) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc12_10.2: <bound method> = bound_method %p.ref, %specific_fn\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.728 = call %bound_method.loc12_10.2(%p.ref)\n// CHECK:STDOUT:   return %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/const/import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/const/import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/const/import.carbon\n\n// --- implicit.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F() -> const C;\n\nvar a_ref: const C = F();\nvar a_ptr_ref: const C* = &a_ref;\n\n// --- implicit.impl.carbon\nimpl library \"[[@TEST_NAME]]\";\n\n// Take a reference to avoid unsupported copy logic. This still validates the\n// `const` is handled.\n//@dump-sem-ir-begin\nvar a: const C* = &a_ref;\nvar a_ptr: const C* = a_ptr_ref;\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- implicit.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.48f: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.970: %ptr.as.Copy.impl.Op.type.48f = struct_value () [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %const.0e5: type = const_type %C [concrete]\n// CHECK:STDOUT:   %ptr.c45: type = ptr_type %const.0e5 [concrete]\n// CHECK:STDOUT:   %pattern_type.6eb: type = pattern_type %ptr.c45 [concrete]\n// CHECK:STDOUT:   %pattern_type.03b: type = pattern_type %const.0e5 [concrete]\n// CHECK:STDOUT:   %addr: %ptr.c45 = addr_of imports.%a_ref.var [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.b9c: <witness> = impl_witness imports.%Copy.impl_witness_table.1ed, @ptr.as.Copy.impl(%const.0e5) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.8d3: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%const.0e5) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.09c: %ptr.as.Copy.impl.Op.type.8d3 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.c45, (%Copy.impl_witness.b9c) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.6aa: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.090: type = fn_type_with_self_type %Copy.WithSelf.Op.type.6aa, %Copy.facet [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.bound: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.09c [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.09c, @ptr.as.Copy.impl.Op(%const.0e5) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %addr, %ptr.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//implicit, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.a_ref: ref %const.0e5 = import_ref Main//implicit, a_ref, loaded [concrete = %a_ref.var]\n// CHECK:STDOUT:   %Main.a_ptr_ref: ref %ptr.c45 = import_ref Main//implicit, a_ptr_ref, loaded [concrete = %a_ptr_ref.var]\n// CHECK:STDOUT:   %Main.import_ref.1cc: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.48f) = import_ref Main//implicit, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.970)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.1ed = impl_witness_table (%Main.import_ref.1cc), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %a_ref.patt: %pattern_type.03b = ref_binding_pattern a_ref [concrete]\n// CHECK:STDOUT:   %a_ref.var_patt: %pattern_type.03b = var_pattern %a_ref.patt [concrete]\n// CHECK:STDOUT:   %a_ref.var: ref %const.0e5 = var %a_ref.var_patt [concrete]\n// CHECK:STDOUT:   %a_ptr_ref.patt: %pattern_type.6eb = ref_binding_pattern a_ptr_ref [concrete]\n// CHECK:STDOUT:   %a_ptr_ref.var_patt: %pattern_type.6eb = var_pattern %a_ptr_ref.patt [concrete]\n// CHECK:STDOUT:   %a_ptr_ref.var: ref %ptr.c45 = var %a_ptr_ref.var_patt [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.6eb = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.6eb = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %ptr.c45 = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6: type = splice_block %ptr.loc6 [concrete = constants.%ptr.c45] {\n// CHECK:STDOUT:     %C.ref.loc6: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %const.loc6: type = const_type %C.ref.loc6 [concrete = constants.%const.0e5]\n// CHECK:STDOUT:     %ptr.loc6: type = ptr_type %const.loc6 [concrete = constants.%ptr.c45]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %ptr.c45 = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a_ptr.patt: %pattern_type.6eb = ref_binding_pattern a_ptr [concrete]\n// CHECK:STDOUT:     %a_ptr.var_patt: %pattern_type.6eb = var_pattern %a_ptr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a_ptr.var: ref %ptr.c45 = var %a_ptr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc7: type = splice_block %ptr.loc7 [concrete = constants.%ptr.c45] {\n// CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %const.loc7: type = const_type %C.ref.loc7 [concrete = constants.%const.0e5]\n// CHECK:STDOUT:     %ptr.loc7: type = ptr_type %const.loc7 [concrete = constants.%ptr.c45]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a_ptr: ref %ptr.c45 = ref_binding a_ptr, %a_ptr.var [concrete = %a_ptr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a_ref.ref: ref %const.0e5 = name_ref a_ref, imports.%Main.a_ref [concrete = imports.%a_ref.var]\n// CHECK:STDOUT:   %addr: %ptr.c45 = addr_of %a_ref.ref [concrete = constants.%addr]\n// CHECK:STDOUT:   %impl.elem0.loc6: %.090 = impl_witness_access constants.%Copy.impl_witness.b9c, element0 [concrete = constants.%ptr.as.Copy.impl.Op.09c]\n// CHECK:STDOUT:   %bound_method.loc6_19.1: <bound method> = bound_method %addr, %impl.elem0.loc6 [concrete = constants.%ptr.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %specific_fn.loc6: <specific function> = specific_function %impl.elem0.loc6, @ptr.as.Copy.impl.Op(constants.%const.0e5) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_19.2: <bound method> = bound_method %addr, %specific_fn.loc6 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call.loc6: init %ptr.c45 = call %bound_method.loc6_19.2(%addr) [concrete = constants.%addr]\n// CHECK:STDOUT:   assign file.%a.var, %ptr.as.Copy.impl.Op.call.loc6\n// CHECK:STDOUT:   %a_ptr_ref.ref: ref %ptr.c45 = name_ref a_ptr_ref, imports.%Main.a_ptr_ref [concrete = imports.%a_ptr_ref.var]\n// CHECK:STDOUT:   %.loc7: %ptr.c45 = acquire_value %a_ptr_ref.ref\n// CHECK:STDOUT:   %impl.elem0.loc7: %.090 = impl_witness_access constants.%Copy.impl_witness.b9c, element0 [concrete = constants.%ptr.as.Copy.impl.Op.09c]\n// CHECK:STDOUT:   %bound_method.loc7_23.1: <bound method> = bound_method %.loc7, %impl.elem0.loc7\n// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @ptr.as.Copy.impl.Op(constants.%const.0e5) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_23.2: <bound method> = bound_method %.loc7, %specific_fn.loc7\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call.loc7: init %ptr.c45 = call %bound_method.loc7_23.2(%.loc7)\n// CHECK:STDOUT:   assign file.%a_ptr.var, %ptr.as.Copy.impl.Op.call.loc7\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/deduce/array.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/array.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/array.carbon\n\n// --- type_only.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[T:! type](a: array(T, 3)) -> T { return F(a); }\n\nfn G() -> C {\n  var a: array(C, 3) = ({}, {}, {});\n  return F(a);\n}\n\n// --- bound_only.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[N:! Core.IntLiteral()](unused a: array(C, N)) -> i32 { return N; }\n\nfn G() -> i32 {\n  var a: array(C, 3) = ({}, {}, {});\n  return F(a);\n}\n\n// --- type_and_bound.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[T:! type, N:! Core.IntLiteral()](unused a: array(T, N)) {}\n\nfn G() {\n  var a: array(C, 3) = ({}, {}, {});\n  F(a);\n}\n\n// --- fail_bound_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[T:! type](a: array(T, 2)) -> T { return F(a); }\n\nfn G() -> C {\n  // TODO: We succeed at deducing T here but fail to convert. Is this the right behavior?\n  var a: array(C, 3) = ({}, {}, {});\n  // CHECK:STDERR: fail_bound_mismatch.carbon:[[@LINE+10]]:12: error: cannot implicitly convert expression of type `array(C, 3)` to `array(C, 2)` [ConversionFailure]\n  // CHECK:STDERR:   return F(a);\n  // CHECK:STDERR:            ^\n  // CHECK:STDERR: fail_bound_mismatch.carbon:[[@LINE+7]]:12: note: type `array(C, 3)` does not implement interface `Core.ImplicitAs(array(C, 2))` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return F(a);\n  // CHECK:STDERR:            ^\n  // CHECK:STDERR: fail_bound_mismatch.carbon:[[@LINE-11]]:16: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn F[T:! type](a: array(T, 2)) -> T { return F(a); }\n  // CHECK:STDERR:                ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return F(a);\n}\n\n// --- fail_type_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nclass D {}\n\nfn F[N:! Core.IntLiteral()](unused a: array(C, N)) -> i32 { return N; }\n\nfn G() -> i32 {\n  // TODO: We succeed at deducing N here but fail to convert. Is this the right behavior?\n  var a: array(D, 3) = ({}, {}, {});\n  // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+10]]:12: error: cannot implicitly convert expression of type `array(D, 3)` to `array(C, 3)` [ConversionFailure]\n  // CHECK:STDERR:   return F(a);\n  // CHECK:STDERR:            ^\n  // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE+7]]:12: note: type `array(D, 3)` does not implement interface `Core.ImplicitAs(array(C, 3))` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return F(a);\n  // CHECK:STDERR:            ^\n  // CHECK:STDERR: fail_type_mismatch.carbon:[[@LINE-11]]:36: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn F[N:! Core.IntLiteral()](unused a: array(C, N)) -> i32 { return N; }\n  // CHECK:STDERR:                                    ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return F(a);\n}\n\n// --- fail_bound_type_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[N:! i32](unused a: array(C, N)) -> i32 { return N; }\n\nfn G() -> i32 {\n  var a: array(C, 3) = ({}, {}, {});\n  // TODO: This fails because the array bound in `F` is effectively\n  //   `N.(ImplicitAs(IntLiteral).Convert)()`\n  // which we can't deduce through. We should decide if we want to support\n  // deductions of that form. If not, it'd be nice to diagnose this situation\n  // better.\n  // CHECK:STDERR: fail_bound_type_mismatch.carbon:[[@LINE+7]]:10: error: cannot deduce value for generic parameter `N` [DeductionIncomplete]\n  // CHECK:STDERR:   return F(a);\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR: fail_bound_type_mismatch.carbon:[[@LINE-12]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn F[N:! i32](unused a: array(C, N)) -> i32 { return N; }\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return F(a);\n}\n\n// --- fail_todo_array_length_from_tuple.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[N:! i32](unused a: array(C, N)) {}\n\nfn G() {\n  // TODO: Deduce N as 3 from the tuple's size.\n  //\n  // CHECK:STDERR: fail_todo_array_length_from_tuple.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `N` [DeductionIncomplete]\n  // CHECK:STDERR:   F(({}, {}, {}));\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_array_length_from_tuple.carbon:[[@LINE-8]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn F[N:! i32](unused a: array(C, N)) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  F(({}, {}, {}));\n}\n\n// CHECK:STDOUT: --- type_only.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type.3ec: type = array_type %int_3, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.b3f: type = pattern_type %array_type.3ec [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.3ec [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.643: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %array_type.931: type = array_type %int_3, %C [concrete]\n// CHECK:STDOUT:   %pattern_type.f21: type = pattern_type %array_type.931 [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.8d4: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.8d4 = tuple_value (%empty_struct, %empty_struct, %empty_struct) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %array: %array_type.931 = tuple_value (%C.val, %C.val, %C.val) [concrete]\n// CHECK:STDOUT:   %F.specific_fn.540: <specific function> = specific_function %F, @F(%C) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.c7a: <witness> = complete_type_witness %array_type.931 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type.loc6_16 (%pattern_type.b3f) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type.loc6_16 (%pattern_type.b3f) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc6_32 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc6_32 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc6_35: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc6_35.3: Core.Form = init_form %T.ref.loc6_35 [symbolic = %.loc6_35.2 (constants.%.184)]\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %a.param: @F.%array_type.loc6_29.1 (%array_type.3ec) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_29: type = splice_block %array_type.loc6_29.2 [symbolic = %array_type.loc6_29.1 (constants.%array_type.3ec)] {\n// CHECK:STDOUT:       %T.ref.loc6_25: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:       %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:       %array_type.loc6_29.2: type = array_type %int_3, %T.ref.loc6_25 [symbolic = %array_type.loc6_29.1 (constants.%array_type.3ec)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%array_type.loc6_29.1 (%array_type.3ec) = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref @F.%T.loc6_6.1 (%T) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%T.loc6_6.1 (%T) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc8_11.2: Core.Form = init_form %C.ref.loc8 [concrete = constants.%.a69]\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param0\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_6.2: type) {\n// CHECK:STDOUT:   %T.loc6_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:   %array_type.loc6_29.1: type = array_type constants.%int_3, %T.loc6_6.1 [symbolic = %array_type.loc6_29.1 (constants.%array_type.3ec)]\n// CHECK:STDOUT:   %pattern_type.loc6_16: type = pattern_type %array_type.loc6_29.1 [symbolic = %pattern_type.loc6_16 (constants.%pattern_type.b3f)]\n// CHECK:STDOUT:   %.loc6_35.2: Core.Form = init_form %T.loc6_6.1 [symbolic = %.loc6_35.2 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc6_32: type = pattern_type %T.loc6_6.1 [symbolic = %pattern_type.loc6_32 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc6_29.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %F.specific_fn.loc6_46.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_46.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc6_29.1 (%array_type.3ec)) -> out %return.param: @F.%T.loc6_6.1 (%T) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %a.ref: @F.%array_type.loc6_29.1 (%array_type.3ec) = name_ref a, %a\n// CHECK:STDOUT:     %F.specific_fn.loc6_46.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_46.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:     %.loc6_35.1: ref @F.%T.loc6_6.1 (%T) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) to %.loc6_35.1 = call %F.specific_fn.loc6_46.1(%a.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() -> out %return.param: %C {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.f21 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.f21 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %array_type.931 = var %a.var_patt\n// CHECK:STDOUT:   %.loc9_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_34.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_35.1: %tuple.type.8d4 = tuple_literal (%.loc9_26.1, %.loc9_30.1, %.loc9_34.1) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc9_35.2: ref %C = array_index %a.var, %int_0\n// CHECK:STDOUT:   %.loc9_26.2: init %C to %.loc9_35.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.3: init %C = converted %.loc9_26.1, %.loc9_26.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %.loc9_35.4: ref %C = array_index %a.var, %int_1\n// CHECK:STDOUT:   %.loc9_30.2: init %C to %.loc9_35.4 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.5: init %C = converted %.loc9_30.1, %.loc9_30.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:   %.loc9_35.6: ref %C = array_index %a.var, %int_2\n// CHECK:STDOUT:   %.loc9_34.2: init %C to %.loc9_35.6 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.7: init %C = converted %.loc9_34.1, %.loc9_34.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.8: init %array_type.931 to %a.var = array_init (%.loc9_35.3, %.loc9_35.5, %.loc9_35.7) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc9_3: init %array_type.931 = converted %.loc9_35.1, %.loc9_35.8 [concrete = constants.%array]\n// CHECK:STDOUT:   assign %a.var, %.loc9_3\n// CHECK:STDOUT:   %.loc9_20: type = splice_block %array_type [concrete = constants.%array_type.931] {\n// CHECK:STDOUT:     %C.ref.loc9: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:     %array_type: type = array_type %int_3, %C.ref.loc9 [concrete = constants.%array_type.931]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %array_type.931 = ref_binding a, %a.var\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %a.ref: ref %array_type.931 = name_ref a, %a\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.540]\n// CHECK:STDOUT:   %.loc8_11.1: ref %C = splice_block %return.param {}\n// CHECK:STDOUT:   %.loc10: %array_type.931 = acquire_value %a.ref\n// CHECK:STDOUT:   %F.call: init %C to %.loc8_11.1 = call %F.specific_fn(%.loc10)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return %F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type.931) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%T\n// CHECK:STDOUT:   %array_type.loc6_29.1 => constants.%array_type.3ec\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.b3f\n// CHECK:STDOUT:   %.loc6_35.2 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc6_32 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %F.specific_fn.loc6_46.2 => constants.%F.specific_fn.643\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%C\n// CHECK:STDOUT:   %array_type.loc6_29.1 => constants.%array_type.931\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.f21\n// CHECK:STDOUT:   %.loc6_35.2 => constants.%.a69\n// CHECK:STDOUT:   %pattern_type.loc6_32 => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.c7a\n// CHECK:STDOUT:   %F.specific_fn.loc6_46.2 => constants.%F.specific_fn.540\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- bound_only.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %array_type.c79: type = array_type %N, %C [symbolic]\n// CHECK:STDOUT:   %pattern_type.cc9: type = pattern_type %array_type.c79 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.d0d: <witness> = require_complete_type %array_type.c79 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d6e: <bound method> = bound_method %N, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.7fa: <bound method> = bound_method %N, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.7fa(%N) [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type.931: type = array_type %int_3.1ba, %C [concrete]\n// CHECK:STDOUT:   %pattern_type.f21: type = pattern_type %array_type.931 [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.8d4: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.8d4 = tuple_value (%empty_struct, %empty_struct, %empty_struct) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %array: %array_type.931 = tuple_value (%C.val, %C.val, %C.val) [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_3.1ba) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.c7a: <witness> = complete_type_witness %array_type.931 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type (%pattern_type.cc9) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type (%pattern_type.cc9) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6_55: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc6_26.1: type = splice_block %.loc6_26.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc6_26.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc6_26.3: type = converted %IntLiteral.call, %.loc6_26.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc6_6.2: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc6_6.1 (constants.%N)]\n// CHECK:STDOUT:     %a.param: @F.%array_type.loc6_49.1 (%array_type.c79) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_49: type = splice_block %array_type.loc6_49.2 [symbolic = %array_type.loc6_49.1 (constants.%array_type.c79)] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %N.ref.loc6_48: Core.IntLiteral = name_ref N, %N.loc6_6.2 [symbolic = %N.loc6_6.1 (constants.%N)]\n// CHECK:STDOUT:       %array_type.loc6_49.2: type = array_type %N.ref.loc6_48, %C.ref [symbolic = %array_type.loc6_49.1 (constants.%array_type.c79)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%array_type.loc6_49.1 (%array_type.c79) = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%N.loc6_6.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N.loc6_6.1: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc6_6.1 (constants.%N)]\n// CHECK:STDOUT:   %array_type.loc6_49.1: type = array_type %N.loc6_6.1, constants.%C [symbolic = %array_type.loc6_49.1 (constants.%array_type.c79)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %array_type.loc6_49.1 [symbolic = %pattern_type (constants.%pattern_type.cc9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc6_49.1 [symbolic = %require_complete (constants.%require_complete.d0d)]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.loc6_6.1, constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d6e)]\n// CHECK:STDOUT:   %bound_method.loc6_69.3: <bound method> = bound_method %N.loc6_6.1, constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [symbolic = %bound_method.loc6_69.3 (constants.%bound_method.7fa)]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_69.2: init %i32 = call %bound_method.loc6_69.3(%N.loc6_6.1) [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_69.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc6_49.1 (%array_type.c79)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %N.ref.loc6_68: Core.IntLiteral = name_ref N, %N.loc6_6.2 [symbolic = %N.loc6_6.1 (constants.%N)]\n// CHECK:STDOUT:     %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc6_69.1: <bound method> = bound_method %N.ref.loc6_68, %impl.elem0 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d6e)]\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_69.2: <bound method> = bound_method %N.ref.loc6_68, %specific_fn [symbolic = %bound_method.loc6_69.3 (constants.%bound_method.7fa)]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_69.1: init %i32 = call %bound_method.loc6_69.2(%N.ref.loc6_68) [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_69.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     %.loc6_69: init %i32 = converted %N.ref.loc6_68, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_69.1 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_69.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     return %.loc6_69\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.f21 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.f21 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %array_type.931 = var %a.var_patt\n// CHECK:STDOUT:   %.loc9_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_34.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_35.1: %tuple.type.8d4 = tuple_literal (%.loc9_26.1, %.loc9_30.1, %.loc9_34.1) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc9_35.2: ref %C = array_index %a.var, %int_0\n// CHECK:STDOUT:   %.loc9_26.2: init %C to %.loc9_35.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.3: init %C = converted %.loc9_26.1, %.loc9_26.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %.loc9_35.4: ref %C = array_index %a.var, %int_1\n// CHECK:STDOUT:   %.loc9_30.2: init %C to %.loc9_35.4 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.5: init %C = converted %.loc9_30.1, %.loc9_30.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:   %.loc9_35.6: ref %C = array_index %a.var, %int_2\n// CHECK:STDOUT:   %.loc9_34.2: init %C to %.loc9_35.6 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.7: init %C = converted %.loc9_34.1, %.loc9_34.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.8: init %array_type.931 to %a.var = array_init (%.loc9_35.3, %.loc9_35.5, %.loc9_35.7) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc9_3: init %array_type.931 = converted %.loc9_35.1, %.loc9_35.8 [concrete = constants.%array]\n// CHECK:STDOUT:   assign %a.var, %.loc9_3\n// CHECK:STDOUT:   %.loc9_20: type = splice_block %array_type [concrete = constants.%array_type.931] {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %array_type: type = array_type %int_3, %C.ref [concrete = constants.%array_type.931]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %array_type.931 = ref_binding a, %a.var\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %a.ref: ref %array_type.931 = name_ref a, %a\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%int_3.1ba) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %.loc10: %array_type.931 = acquire_value %a.ref\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%.loc10)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type.931) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%N) {\n// CHECK:STDOUT:   %N.loc6_6.1 => constants.%N\n// CHECK:STDOUT:   %array_type.loc6_49.1 => constants.%array_type.c79\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.cc9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%int_3.1ba) {\n// CHECK:STDOUT:   %N.loc6_6.1 => constants.%int_3.1ba\n// CHECK:STDOUT:   %array_type.loc6_49.1 => constants.%array_type.931\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.f21\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.c7a\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound => constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061\n// CHECK:STDOUT:   %bound_method.loc6_69.3 => constants.%bound_method.fa7\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_69.2 => constants.%int_3.822\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- type_and_bound.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 1 [symbolic]\n// CHECK:STDOUT:   %array_type.6d2: type = array_type %N, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.4d8: type = pattern_type %array_type.6d2 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.6d2 [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type.931: type = array_type %int_3, %C [concrete]\n// CHECK:STDOUT:   %pattern_type.f21: type = pattern_type %array_type.931 [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.8d4: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.8d4 = tuple_value (%empty_struct, %empty_struct, %empty_struct) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %array: %array_type.931 = tuple_value (%C.val, %C.val, %C.val) [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%C, %int_3) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.c7a: <witness> = complete_type_witness %array_type.931 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = symbolic_binding_pattern N, 1 [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type (%pattern_type.4d8) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type (%pattern_type.4d8) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc6_36.1: type = splice_block %.loc6_36.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc6_36.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc6_36.3: type = converted %IntLiteral.call, %.loc6_36.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc6_16.2: Core.IntLiteral = symbolic_binding N, 1 [symbolic = %N.loc6_16.1 (constants.%N)]\n// CHECK:STDOUT:     %a.param: @F.%array_type.loc6_59.1 (%array_type.6d2) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_59: type = splice_block %array_type.loc6_59.2 [symbolic = %array_type.loc6_59.1 (constants.%array_type.6d2)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:       %N.ref: Core.IntLiteral = name_ref N, %N.loc6_16.2 [symbolic = %N.loc6_16.1 (constants.%N)]\n// CHECK:STDOUT:       %array_type.loc6_59.2: type = array_type %N.ref, %T.ref [symbolic = %array_type.loc6_59.1 (constants.%array_type.6d2)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%array_type.loc6_59.1 (%array_type.6d2) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_6.2: type, %N.loc6_16.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %T.loc6_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:   %N.loc6_16.1: Core.IntLiteral = symbolic_binding N, 1 [symbolic = %N.loc6_16.1 (constants.%N)]\n// CHECK:STDOUT:   %array_type.loc6_59.1: type = array_type %N.loc6_16.1, %T.loc6_6.1 [symbolic = %array_type.loc6_59.1 (constants.%array_type.6d2)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %array_type.loc6_59.1 [symbolic = %pattern_type (constants.%pattern_type.4d8)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc6_59.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc6_59.1 (%array_type.6d2)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.f21 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.f21 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %array_type.931 = var %a.var_patt\n// CHECK:STDOUT:   %.loc9_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_34.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_35.1: %tuple.type.8d4 = tuple_literal (%.loc9_26.1, %.loc9_30.1, %.loc9_34.1) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc9_35.2: ref %C = array_index %a.var, %int_0\n// CHECK:STDOUT:   %.loc9_26.2: init %C to %.loc9_35.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.3: init %C = converted %.loc9_26.1, %.loc9_26.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %.loc9_35.4: ref %C = array_index %a.var, %int_1\n// CHECK:STDOUT:   %.loc9_30.2: init %C to %.loc9_35.4 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.5: init %C = converted %.loc9_30.1, %.loc9_30.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:   %.loc9_35.6: ref %C = array_index %a.var, %int_2\n// CHECK:STDOUT:   %.loc9_34.2: init %C to %.loc9_35.6 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.7: init %C = converted %.loc9_34.1, %.loc9_34.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.8: init %array_type.931 to %a.var = array_init (%.loc9_35.3, %.loc9_35.5, %.loc9_35.7) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc9_3: init %array_type.931 = converted %.loc9_35.1, %.loc9_35.8 [concrete = constants.%array]\n// CHECK:STDOUT:   assign %a.var, %.loc9_3\n// CHECK:STDOUT:   %.loc9_20: type = splice_block %array_type [concrete = constants.%array_type.931] {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:     %array_type: type = array_type %int_3, %C.ref [concrete = constants.%array_type.931]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %array_type.931 = ref_binding a, %a.var\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %a.ref: ref %array_type.931 = name_ref a, %a\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C, constants.%int_3) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %.loc10: %array_type.931 = acquire_value %a.ref\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc10)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type.931) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T, constants.%N) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%T\n// CHECK:STDOUT:   %N.loc6_16.1 => constants.%N\n// CHECK:STDOUT:   %array_type.loc6_59.1 => constants.%array_type.6d2\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4d8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C, constants.%int_3) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%C\n// CHECK:STDOUT:   %N.loc6_16.1 => constants.%int_3\n// CHECK:STDOUT:   %array_type.loc6_59.1 => constants.%array_type.931\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.f21\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.c7a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_bound_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %array_type.a0b: type = array_type %int_2, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.b42: type = pattern_type %array_type.a0b [symbolic]\n// CHECK:STDOUT:   %.184347.1: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d1c4.1: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.a0b [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.643: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type.931: type = array_type %int_3, %C [concrete]\n// CHECK:STDOUT:   %pattern_type.f21: type = pattern_type %array_type.931 [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.8d4: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.8d4 = tuple_value (%empty_struct, %empty_struct, %empty_struct) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %array: %array_type.931 = tuple_value (%C.val, %C.val, %C.val) [concrete]\n// CHECK:STDOUT:   %array_type.158: type = array_type %int_2, %C [concrete]\n// CHECK:STDOUT:   %pattern_type.6d3: type = pattern_type %array_type.158 [concrete]\n// CHECK:STDOUT:   %F.specific_fn.540: <specific function> = specific_function %F, @F(%C) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.b8b: <witness> = complete_type_witness %array_type.158 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type.loc6_16 (%pattern_type.b42) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type.loc6_16 (%pattern_type.b42) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc6_32 (%pattern_type.51d1c4.1) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc6_32 (%pattern_type.51d1c4.1) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc6_35: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc6_35.3: Core.Form = init_form %T.ref.loc6_35 [symbolic = %.loc6_35.2 (constants.%.184347.1)]\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %a.param: @F.%array_type.loc6_29.1 (%array_type.a0b) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_29: type = splice_block %array_type.loc6_29.2 [symbolic = %array_type.loc6_29.1 (constants.%array_type.a0b)] {\n// CHECK:STDOUT:       %T.ref.loc6_25: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:       %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:       %array_type.loc6_29.2: type = array_type %int_2, %T.ref.loc6_25 [symbolic = %array_type.loc6_29.1 (constants.%array_type.a0b)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%array_type.loc6_29.1 (%array_type.a0b) = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref @F.%T.loc6_6.1 (%T) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%T.loc6_6.1 (%T) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc8_11.2: Core.Form = init_form %C.ref.loc8 [concrete = constants.%.a69]\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param0\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_6.2: type) {\n// CHECK:STDOUT:   %T.loc6_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:   %array_type.loc6_29.1: type = array_type constants.%int_2, %T.loc6_6.1 [symbolic = %array_type.loc6_29.1 (constants.%array_type.a0b)]\n// CHECK:STDOUT:   %pattern_type.loc6_16: type = pattern_type %array_type.loc6_29.1 [symbolic = %pattern_type.loc6_16 (constants.%pattern_type.b42)]\n// CHECK:STDOUT:   %.loc6_35.2: Core.Form = init_form %T.loc6_6.1 [symbolic = %.loc6_35.2 (constants.%.184347.1)]\n// CHECK:STDOUT:   %pattern_type.loc6_32: type = pattern_type %T.loc6_6.1 [symbolic = %pattern_type.loc6_32 (constants.%pattern_type.51d1c4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc6_29.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %F.specific_fn.loc6_46.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_46.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc6_29.1 (%array_type.a0b)) -> out %return.param: @F.%T.loc6_6.1 (%T) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %a.ref: @F.%array_type.loc6_29.1 (%array_type.a0b) = name_ref a, %a\n// CHECK:STDOUT:     %F.specific_fn.loc6_46.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_46.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:     %.loc6_35.1: ref @F.%T.loc6_6.1 (%T) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) to %.loc6_35.1 = call %F.specific_fn.loc6_46.1(%a.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() -> out %return.param: %C {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.f21 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.f21 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %array_type.931 = var %a.var_patt\n// CHECK:STDOUT:   %.loc10_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc10_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc10_34.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc10_35.1: %tuple.type.8d4 = tuple_literal (%.loc10_26.1, %.loc10_30.1, %.loc10_34.1) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc10_35.2: ref %C = array_index %a.var, %int_0\n// CHECK:STDOUT:   %.loc10_26.2: init %C to %.loc10_35.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc10_35.3: init %C = converted %.loc10_26.1, %.loc10_26.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %.loc10_35.4: ref %C = array_index %a.var, %int_1\n// CHECK:STDOUT:   %.loc10_30.2: init %C to %.loc10_35.4 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc10_35.5: init %C = converted %.loc10_30.1, %.loc10_30.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:   %.loc10_35.6: ref %C = array_index %a.var, %int_2\n// CHECK:STDOUT:   %.loc10_34.2: init %C to %.loc10_35.6 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc10_35.7: init %C = converted %.loc10_34.1, %.loc10_34.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc10_35.8: init %array_type.931 to %a.var = array_init (%.loc10_35.3, %.loc10_35.5, %.loc10_35.7) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc10_3: init %array_type.931 = converted %.loc10_35.1, %.loc10_35.8 [concrete = constants.%array]\n// CHECK:STDOUT:   assign %a.var, %.loc10_3\n// CHECK:STDOUT:   %.loc10_20: type = splice_block %array_type [concrete = constants.%array_type.931] {\n// CHECK:STDOUT:     %C.ref.loc10: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:     %array_type: type = array_type %int_3, %C.ref.loc10 [concrete = constants.%array_type.931]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %array_type.931 = ref_binding a, %a.var\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %a.ref: ref %array_type.931 = name_ref a, %a\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.540]\n// CHECK:STDOUT:   %.loc8_11.1: ref %C = splice_block %return.param {}\n// CHECK:STDOUT:   %.loc21: %array_type.158 = converted %a.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %F.call: init %C to %.loc8_11.1 = call %F.specific_fn(<error>)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return %F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type.931) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%T\n// CHECK:STDOUT:   %array_type.loc6_29.1 => constants.%array_type.a0b\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.b42\n// CHECK:STDOUT:   %.loc6_35.2 => constants.%.184347.1\n// CHECK:STDOUT:   %pattern_type.loc6_32 => constants.%pattern_type.51d1c4.1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %F.specific_fn.loc6_46.2 => constants.%F.specific_fn.643\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%C\n// CHECK:STDOUT:   %array_type.loc6_29.1 => constants.%array_type.158\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.6d3\n// CHECK:STDOUT:   %.loc6_35.2 => constants.%.a69\n// CHECK:STDOUT:   %pattern_type.loc6_32 => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.b8b\n// CHECK:STDOUT:   %F.specific_fn.loc6_46.2 => constants.%F.specific_fn.540\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_type_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %array_type.c79: type = array_type %N, %C [symbolic]\n// CHECK:STDOUT:   %pattern_type.cc9: type = pattern_type %array_type.c79 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.d0d: <witness> = require_complete_type %array_type.c79 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d6e: <bound method> = bound_method %N, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.7fa: <bound method> = bound_method %N, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.7fa(%N) [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type.b6d: type = array_type %int_3.1ba, %D [concrete]\n// CHECK:STDOUT:   %pattern_type.454: type = pattern_type %array_type.b6d [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.8d4: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.8d4 = tuple_value (%empty_struct, %empty_struct, %empty_struct) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %D.val: %D = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %array: %array_type.b6d = tuple_value (%D.val, %D.val, %D.val) [concrete]\n// CHECK:STDOUT:   %array_type.931: type = array_type %int_3.1ba, %C [concrete]\n// CHECK:STDOUT:   %pattern_type.f21: type = pattern_type %array_type.931 [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_3.1ba) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.c7a: <witness> = complete_type_witness %array_type.931 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type (%pattern_type.cc9) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type (%pattern_type.cc9) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc7_55: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc7_26.1: type = splice_block %.loc7_26.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc7_26.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc7_26.3: type = converted %IntLiteral.call, %.loc7_26.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc7_6.2: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc7_6.1 (constants.%N)]\n// CHECK:STDOUT:     %a.param: @F.%array_type.loc7_49.1 (%array_type.c79) = value_param call_param0\n// CHECK:STDOUT:     %.loc7_49: type = splice_block %array_type.loc7_49.2 [symbolic = %array_type.loc7_49.1 (constants.%array_type.c79)] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %N.ref.loc7_48: Core.IntLiteral = name_ref N, %N.loc7_6.2 [symbolic = %N.loc7_6.1 (constants.%N)]\n// CHECK:STDOUT:       %array_type.loc7_49.2: type = array_type %N.ref.loc7_48, %C.ref [symbolic = %array_type.loc7_49.1 (constants.%array_type.c79)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%array_type.loc7_49.1 (%array_type.c79) = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc9: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%N.loc7_6.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N.loc7_6.1: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc7_6.1 (constants.%N)]\n// CHECK:STDOUT:   %array_type.loc7_49.1: type = array_type %N.loc7_6.1, constants.%C [symbolic = %array_type.loc7_49.1 (constants.%array_type.c79)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %array_type.loc7_49.1 [symbolic = %pattern_type (constants.%pattern_type.cc9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc7_49.1 [symbolic = %require_complete (constants.%require_complete.d0d)]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.loc7_6.1, constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d6e)]\n// CHECK:STDOUT:   %bound_method.loc7_69.3: <bound method> = bound_method %N.loc7_6.1, constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [symbolic = %bound_method.loc7_69.3 (constants.%bound_method.7fa)]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_69.2: init %i32 = call %bound_method.loc7_69.3(%N.loc7_6.1) [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_69.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc7_49.1 (%array_type.c79)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %N.ref.loc7_68: Core.IntLiteral = name_ref N, %N.loc7_6.2 [symbolic = %N.loc7_6.1 (constants.%N)]\n// CHECK:STDOUT:     %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc7_69.1: <bound method> = bound_method %N.ref.loc7_68, %impl.elem0 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d6e)]\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc7_69.2: <bound method> = bound_method %N.ref.loc7_68, %specific_fn [symbolic = %bound_method.loc7_69.3 (constants.%bound_method.7fa)]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_69.1: init %i32 = call %bound_method.loc7_69.2(%N.ref.loc7_68) [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_69.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     %.loc7_69: init %i32 = converted %N.ref.loc7_68, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_69.1 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_69.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     return %.loc7_69\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.454 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.454 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %array_type.b6d = var %a.var_patt\n// CHECK:STDOUT:   %.loc11_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc11_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc11_34.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc11_35.1: %tuple.type.8d4 = tuple_literal (%.loc11_26.1, %.loc11_30.1, %.loc11_34.1) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc11_35.2: ref %D = array_index %a.var, %int_0\n// CHECK:STDOUT:   %.loc11_26.2: init %D to %.loc11_35.2 = class_init () [concrete = constants.%D.val]\n// CHECK:STDOUT:   %.loc11_35.3: init %D = converted %.loc11_26.1, %.loc11_26.2 [concrete = constants.%D.val]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %.loc11_35.4: ref %D = array_index %a.var, %int_1\n// CHECK:STDOUT:   %.loc11_30.2: init %D to %.loc11_35.4 = class_init () [concrete = constants.%D.val]\n// CHECK:STDOUT:   %.loc11_35.5: init %D = converted %.loc11_30.1, %.loc11_30.2 [concrete = constants.%D.val]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:   %.loc11_35.6: ref %D = array_index %a.var, %int_2\n// CHECK:STDOUT:   %.loc11_34.2: init %D to %.loc11_35.6 = class_init () [concrete = constants.%D.val]\n// CHECK:STDOUT:   %.loc11_35.7: init %D = converted %.loc11_34.1, %.loc11_34.2 [concrete = constants.%D.val]\n// CHECK:STDOUT:   %.loc11_35.8: init %array_type.b6d to %a.var = array_init (%.loc11_35.3, %.loc11_35.5, %.loc11_35.7) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc11_3: init %array_type.b6d = converted %.loc11_35.1, %.loc11_35.8 [concrete = constants.%array]\n// CHECK:STDOUT:   assign %a.var, %.loc11_3\n// CHECK:STDOUT:   %.loc11_20: type = splice_block %array_type [concrete = constants.%array_type.b6d] {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %array_type: type = array_type %int_3, %D.ref [concrete = constants.%array_type.b6d]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %array_type.b6d = ref_binding a, %a.var\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %a.ref: ref %array_type.b6d = name_ref a, %a\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%int_3.1ba) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %.loc22: %array_type.931 = converted %a.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(<error>)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type.b6d) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%N) {\n// CHECK:STDOUT:   %N.loc7_6.1 => constants.%N\n// CHECK:STDOUT:   %array_type.loc7_49.1 => constants.%array_type.c79\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.cc9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%int_3.1ba) {\n// CHECK:STDOUT:   %N.loc7_6.1 => constants.%int_3.1ba\n// CHECK:STDOUT:   %array_type.loc7_49.1 => constants.%array_type.931\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.f21\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.c7a\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound => constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061\n// CHECK:STDOUT:   %bound_method.loc7_69.3 => constants.%bound_method.fa7\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7_69.2 => constants.%int_3.822\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_bound_type_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N.fe9: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.5de: %i32 = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %From: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.2ed: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%From) [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.d29: %Int.as.ImplicitAs.impl.Convert.type.2ed = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.640: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.ea2, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.240: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.dd4: %Int.as.ImplicitAs.impl.Convert.type.240 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.139 = facet_value %i32, (%ImplicitAs.impl_witness.640) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.462: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.0a7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.462, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.dd4 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Int.as.ImplicitAs.impl.Convert.dd4, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.d76: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method.d76(%N.5de) [symbolic]\n// CHECK:STDOUT:   %array_type.8c3: type = array_type %Int.as.ImplicitAs.impl.Convert.call, %C [symbolic]\n// CHECK:STDOUT:   %pattern_type.0fb: type = pattern_type %array_type.8c3 [symbolic]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.a24: <witness> = require_complete_type %array_type.8c3 [symbolic]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N.fe9) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound: <bound method> = bound_method %N.5de, %Int.as.Copy.impl.Op.664 [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.207: <bound method> = bound_method %N.5de, %Int.as.Copy.impl.Op.specific_fn [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type.931: type = array_type %int_3, %C [concrete]\n// CHECK:STDOUT:   %pattern_type.f21: type = pattern_type %array_type.931 [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.8d4: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %tuple.5c1: %tuple.type.8d4 = tuple_value (%empty_struct, %empty_struct, %empty_struct) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %array: %array_type.931 = tuple_value (%C.val, %C.val, %C.val) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.0bc: @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert.type (%Int.as.ImplicitAs.impl.Convert.type.2ed) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert (constants.%Int.as.ImplicitAs.impl.Convert.d29)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.ea2 = impl_witness_table (%Core.import_ref.0bc), @Int.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type (%pattern_type.0fb) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type (%pattern_type.0fb) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6_41: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6_41: Core.Form = init_form %i32.loc6_41 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc6_10: type = splice_block %i32.loc6_10 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32.loc6_10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc6_6.2: %i32 = symbolic_binding N, 0 [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:     %a.param: @F.%array_type.loc6_35.1 (%array_type.8c3) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_35: type = splice_block %array_type.loc6_35.2 [symbolic = %array_type.loc6_35.1 (constants.%array_type.8c3)] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %N.ref.loc6_34: %i32 = name_ref N, %N.loc6_6.2 [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:       %impl.elem0.loc6_34: %.0a7 = impl_witness_access constants.%ImplicitAs.impl_witness.640, element0 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.dd4]\n// CHECK:STDOUT:       %bound_method.loc6_34.2: <bound method> = bound_method %N.ref.loc6_34, %impl.elem0.loc6_34 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:       %specific_fn.loc6_34: <specific function> = specific_function %impl.elem0.loc6_34, @Int.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Int.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc6_34.3: <bound method> = bound_method %N.ref.loc6_34, %specific_fn.loc6_34 [symbolic = %bound_method.loc6_34.1 (constants.%bound_method.d76)]\n// CHECK:STDOUT:       %Int.as.ImplicitAs.impl.Convert.call.loc6_34.2: init Core.IntLiteral = call %bound_method.loc6_34.3(%N.ref.loc6_34) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc6_34.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %.loc6_34.1: Core.IntLiteral = value_of_initializer %Int.as.ImplicitAs.impl.Convert.call.loc6_34.2 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc6_34.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %.loc6_34.2: Core.IntLiteral = converted %N.ref.loc6_34, %.loc6_34.1 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc6_34.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %array_type.loc6_35.2: type = array_type %.loc6_34.2, %C.ref [symbolic = %array_type.loc6_35.1 (constants.%array_type.8c3)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%array_type.loc6_35.1 (%array_type.8c3) = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%N.loc6_6.2: %i32) {\n// CHECK:STDOUT:   %N.loc6_6.1: %i32 = symbolic_binding N, 0 [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.loc6_6.1, constants.%Int.as.ImplicitAs.impl.Convert.dd4 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:   %bound_method.loc6_34.1: <bound method> = bound_method %N.loc6_6.1, constants.%Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic = %bound_method.loc6_34.1 (constants.%bound_method.d76)]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call.loc6_34.1: init Core.IntLiteral = call %bound_method.loc6_34.1(%N.loc6_6.1) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc6_34.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:   %array_type.loc6_35.1: type = array_type %Int.as.ImplicitAs.impl.Convert.call.loc6_34.1, constants.%C [symbolic = %array_type.loc6_35.1 (constants.%array_type.8c3)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %array_type.loc6_35.1 [symbolic = %pattern_type (constants.%pattern_type.0fb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc6_35.1 [symbolic = %require_complete (constants.%require_complete.a24)]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound: <bound method> = bound_method %N.loc6_6.1, constants.%Int.as.Copy.impl.Op.664 [symbolic = %Int.as.Copy.impl.Op.bound (constants.%Int.as.Copy.impl.Op.bound)]\n// CHECK:STDOUT:   %bound_method.loc6_54.3: <bound method> = bound_method %N.loc6_6.1, constants.%Int.as.Copy.impl.Op.specific_fn [symbolic = %bound_method.loc6_54.3 (constants.%bound_method.207)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc6_35.1 (%array_type.8c3)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %N.ref.loc6_54: %i32 = name_ref N, %N.loc6_6.2 [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:     %impl.elem0.loc6_54: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:     %bound_method.loc6_54.1: <bound method> = bound_method %N.ref.loc6_54, %impl.elem0.loc6_54 [symbolic = %Int.as.Copy.impl.Op.bound (constants.%Int.as.Copy.impl.Op.bound)]\n// CHECK:STDOUT:     %specific_fn.loc6_54: <specific function> = specific_function %impl.elem0.loc6_54, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_54.2: <bound method> = bound_method %N.ref.loc6_54, %specific_fn.loc6_54 [symbolic = %bound_method.loc6_54.3 (constants.%bound_method.207)]\n// CHECK:STDOUT:     %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_54.2(%N.ref.loc6_54) [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:     return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.f21 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.f21 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %array_type.931 = var %a.var_patt\n// CHECK:STDOUT:   %.loc9_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_34.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc9_35.1: %tuple.type.8d4 = tuple_literal (%.loc9_26.1, %.loc9_30.1, %.loc9_34.1) [concrete = constants.%tuple.5c1]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc9_35.2: ref %C = array_index %a.var, %int_0\n// CHECK:STDOUT:   %.loc9_26.2: init %C to %.loc9_35.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.3: init %C = converted %.loc9_26.1, %.loc9_26.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %.loc9_35.4: ref %C = array_index %a.var, %int_1\n// CHECK:STDOUT:   %.loc9_30.2: init %C to %.loc9_35.4 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.5: init %C = converted %.loc9_30.1, %.loc9_30.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2]\n// CHECK:STDOUT:   %.loc9_35.6: ref %C = array_index %a.var, %int_2\n// CHECK:STDOUT:   %.loc9_34.2: init %C to %.loc9_35.6 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.7: init %C = converted %.loc9_34.1, %.loc9_34.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc9_35.8: init %array_type.931 to %a.var = array_init (%.loc9_35.3, %.loc9_35.5, %.loc9_35.7) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc9_3: init %array_type.931 = converted %.loc9_35.1, %.loc9_35.8 [concrete = constants.%array]\n// CHECK:STDOUT:   assign %a.var, %.loc9_3\n// CHECK:STDOUT:   %.loc9_20: type = splice_block %array_type [concrete = constants.%array_type.931] {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:     %array_type: type = array_type %int_3, %C.ref [concrete = constants.%array_type.931]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %array_type.931 = ref_binding a, %a.var\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %a.ref: ref %array_type.931 = name_ref a, %a\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type.931) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%N.5de) {\n// CHECK:STDOUT:   %N.loc6_6.1 => constants.%N.5de\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound => constants.%Int.as.ImplicitAs.impl.Convert.bound\n// CHECK:STDOUT:   %bound_method.loc6_34.1 => constants.%bound_method.d76\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call.loc6_34.1 => constants.%Int.as.ImplicitAs.impl.Convert.call\n// CHECK:STDOUT:   %array_type.loc6_35.1 => constants.%array_type.8c3\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.0fb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_array_length_from_tuple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.5de: %i32 = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %From: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.2ed: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%From) [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.d29: %Int.as.ImplicitAs.impl.Convert.type.2ed = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.640: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.ea2, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.240: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.dd4: %Int.as.ImplicitAs.impl.Convert.type.240 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.139 = facet_value %i32, (%ImplicitAs.impl_witness.640) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.462: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.0a7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.462, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.dd4 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Int.as.ImplicitAs.impl.Convert.dd4, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method(%N.5de) [symbolic]\n// CHECK:STDOUT:   %array_type: type = array_type %Int.as.ImplicitAs.impl.Convert.call, %C [symbolic]\n// CHECK:STDOUT:   %pattern_type.0fb: type = pattern_type %array_type [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.a24: <witness> = require_complete_type %array_type [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%empty_struct_type, %empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type = tuple_value (%empty_struct, %empty_struct, %empty_struct) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.0bc: @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert.type (%Int.as.ImplicitAs.impl.Convert.type.2ed) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert (constants.%Int.as.ImplicitAs.impl.Convert.d29)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.ea2 = impl_witness_table (%Core.import_ref.0bc), @Int.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type (%pattern_type.0fb) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type (%pattern_type.0fb) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_10: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc5_6.2: %i32 = symbolic_binding N, 0 [symbolic = %N.loc5_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:     %a.param: @F.%array_type.loc5_35.1 (%array_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc5_35: type = splice_block %array_type.loc5_35.2 [symbolic = %array_type.loc5_35.1 (constants.%array_type)] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %N.ref: %i32 = name_ref N, %N.loc5_6.2 [symbolic = %N.loc5_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:       %impl.elem0: %.0a7 = impl_witness_access constants.%ImplicitAs.impl_witness.640, element0 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.dd4]\n// CHECK:STDOUT:       %bound_method.loc5_34.2: <bound method> = bound_method %N.ref, %impl.elem0 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:       %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Int.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc5_34.3: <bound method> = bound_method %N.ref, %specific_fn [symbolic = %bound_method.loc5_34.1 (constants.%bound_method)]\n// CHECK:STDOUT:       %Int.as.ImplicitAs.impl.Convert.call.loc5_34.2: init Core.IntLiteral = call %bound_method.loc5_34.3(%N.ref) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc5_34.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %.loc5_34.1: Core.IntLiteral = value_of_initializer %Int.as.ImplicitAs.impl.Convert.call.loc5_34.2 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc5_34.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %.loc5_34.2: Core.IntLiteral = converted %N.ref, %.loc5_34.1 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc5_34.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %array_type.loc5_35.2: type = array_type %.loc5_34.2, %C.ref [symbolic = %array_type.loc5_35.1 (constants.%array_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%array_type.loc5_35.1 (%array_type) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%N.loc5_6.2: %i32) {\n// CHECK:STDOUT:   %N.loc5_6.1: %i32 = symbolic_binding N, 0 [symbolic = %N.loc5_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.loc5_6.1, constants.%Int.as.ImplicitAs.impl.Convert.dd4 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:   %bound_method.loc5_34.1: <bound method> = bound_method %N.loc5_6.1, constants.%Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic = %bound_method.loc5_34.1 (constants.%bound_method)]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call.loc5_34.1: init Core.IntLiteral = call %bound_method.loc5_34.1(%N.loc5_6.1) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc5_34.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:   %array_type.loc5_35.1: type = array_type %Int.as.ImplicitAs.impl.Convert.call.loc5_34.1, constants.%C [symbolic = %array_type.loc5_35.1 (constants.%array_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %array_type.loc5_35.1 [symbolic = %pattern_type (constants.%pattern_type.0fb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc5_35.1 [symbolic = %require_complete (constants.%require_complete.a24)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @F.%array_type.loc5_35.1 (%array_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc17_7: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc17_11: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc17_15: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc17_16: %tuple.type = tuple_literal (%.loc17_7, %.loc17_11, %.loc17_15) [concrete = constants.%tuple]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%N.5de) {\n// CHECK:STDOUT:   %N.loc5_6.1 => constants.%N.5de\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound => constants.%Int.as.ImplicitAs.impl.Convert.bound\n// CHECK:STDOUT:   %bound_method.loc5_34.1 => constants.%bound_method\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call.loc5_34.1 => constants.%Int.as.ImplicitAs.impl.Convert.call\n// CHECK:STDOUT:   %array_type.loc5_35.1 => constants.%array_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.0fb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/deduce/binding_pattern.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/binding_pattern.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/binding_pattern.carbon\n\n// --- fail_incompatible_deduce.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(T:! type) {\n  fn Create(unused value: T) {}\n}\n\nfn F(unused U:! type, V:! type) {\n  // CHECK:STDERR: fail_incompatible_deduce.carbon:[[@LINE+10]]:15: error: cannot implicitly convert expression of type `{}` to `V` [ConversionFailure]\n  // CHECK:STDERR:   C(V).Create({});\n  // CHECK:STDERR:               ^~\n  // CHECK:STDERR: fail_incompatible_deduce.carbon:[[@LINE+7]]:15: note: type `{}` does not implement interface `Core.ImplicitAs(V)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   C(V).Create({});\n  // CHECK:STDERR:               ^~\n  // CHECK:STDERR: fail_incompatible_deduce.carbon:[[@LINE-10]]:20: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR:   fn Create(unused value: T) {}\n  // CHECK:STDERR:                    ^~~~~~~~\n  // CHECK:STDERR:\n  C(V).Create({});\n}\n\n// --- fail_todo_compatible_deduce.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(T:! type) {\n  fn Create(unused value: T) {}\n}\n\n// TODO: This `where` should be sufficient to say that `{} as V` works.\nfn F(unused U:! type, V:! type where {} impls Core.ImplicitAs(.Self)) {\n  // CHECK:STDERR: fail_todo_compatible_deduce.carbon:[[@LINE+10]]:15: error: cannot implicitly convert expression of type `{}` to `V` [ConversionFailure]\n  // CHECK:STDERR:   C(V).Create({});\n  // CHECK:STDERR:               ^~\n  // CHECK:STDERR: fail_todo_compatible_deduce.carbon:[[@LINE+7]]:15: note: type `{}` does not implement interface `Core.ImplicitAs(V)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   C(V).Create({});\n  // CHECK:STDERR:               ^~\n  // CHECK:STDERR: fail_todo_compatible_deduce.carbon:[[@LINE-11]]:20: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR:   fn Create(unused value: T) {}\n  // CHECK:STDERR:                    ^~~~~~~~\n  // CHECK:STDERR:\n  C(V).Create({});\n}\n\n// CHECK:STDOUT: --- fail_incompatible_deduce.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d1c4.1: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %C.Create.type.c11: type = fn_type @C.Create, @C(%T) [symbolic]\n// CHECK:STDOUT:   %C.Create.723: %C.Create.type.c11 = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %V: type = symbolic_binding V, 1 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.ee9: type = class_type @C, @C(%V) [symbolic]\n// CHECK:STDOUT:   %C.Create.type.c3d: type = fn_type @C.Create, @C(%V) [symbolic]\n// CHECK:STDOUT:   %C.Create.b40: %C.Create.type.c3d = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.1fc: <witness> = require_complete_type %C.ee9 [symbolic]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.946: type = pattern_type %V [symbolic]\n// CHECK:STDOUT:   %C.Create.specific_fn: <specific function> = specific_function %C.Create.b40, @C.Create(%V) [symbolic]\n// CHECK:STDOUT:   %require_complete.441: <witness> = require_complete_type %V [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.031: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic]\n// CHECK:STDOUT:   %Self.738: %ImplicitAs.type.031 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.ff3: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b3a: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Dest, %Self.738) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.1de: %ImplicitAs.WithSelf.Convert.type.b3a = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.1e5: type = facet_type <@ImplicitAs, @ImplicitAs(%V)> [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.d88: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%V) [symbolic]\n// CHECK:STDOUT:   %assoc0.3d8: %ImplicitAs.assoc_type.d88 = assoc_entity element0, imports.%Core.import_ref.201 [symbolic]\n// CHECK:STDOUT:   %require_complete.cc6: <witness> = require_complete_type %ImplicitAs.type.1e5 [symbolic]\n// CHECK:STDOUT:   %assoc0.843: %ImplicitAs.assoc_type.ff3 = assoc_entity element0, imports.%Core.import_ref.cc1 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.178: @ImplicitAs.WithSelf.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.ff3) = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%assoc0 (constants.%assoc0.843)]\n// CHECK:STDOUT:   %Core.import_ref.201: @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.type (%ImplicitAs.WithSelf.Convert.type.b3a) = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert (constants.%ImplicitAs.WithSelf.Convert.1de)]\n// CHECK:STDOUT:   %Core.import_ref.cc1 = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %V.patt: %pattern_type.98f = symbolic_binding_pattern V, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_17.1: type = splice_block %.loc8_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc8_13.2: type = symbolic_binding U, 0 [symbolic = %U.loc8_13.1 (constants.%U)]\n// CHECK:STDOUT:     %.loc8_27.1: type = splice_block %.loc8_27.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_27.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %V.loc8_23.2: type = symbolic_binding V, 1 [symbolic = %V.loc8_23.1 (constants.%V)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T.loc4_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.Create.type: type = fn_type @C.Create, @C(%T.loc4_9.1) [symbolic = %C.Create.type (constants.%C.Create.type.c11)]\n// CHECK:STDOUT:   %C.Create: @C.%C.Create.type (%C.Create.type.c11) = struct_value () [symbolic = %C.Create (constants.%C.Create.723)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %C.Create.decl: @C.%C.Create.type (%C.Create.type.c11) = fn_decl @C.Create [symbolic = @C.%C.Create (constants.%C.Create.723)] {\n// CHECK:STDOUT:       %value.patt: @C.Create.%pattern_type (%pattern_type.51d1c4.1) = value_binding_pattern value [concrete]\n// CHECK:STDOUT:       %value.param_patt: @C.Create.%pattern_type (%pattern_type.51d1c4.1) = value_param_pattern %value.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %value.param: @C.Create.%T (%T) = value_param call_param0\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @C.%T.loc4_9.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %value: @C.Create.%T (%T) = value_binding value, %value.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .Create = %C.Create.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @C.Create(@C.%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T [symbolic = %pattern_type (constants.%pattern_type.51d1c4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%value.param: @C.Create.%T (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%U.loc8_13.2: type, %V.loc8_23.2: type) {\n// CHECK:STDOUT:   %U.loc8_13.1: type = symbolic_binding U, 0 [symbolic = %U.loc8_13.1 (constants.%U)]\n// CHECK:STDOUT:   %V.loc8_23.1: type = symbolic_binding V, 1 [symbolic = %V.loc8_23.1 (constants.%V)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.loc19_6.2: type = class_type @C, @C(%V.loc8_23.1) [symbolic = %C.loc19_6.2 (constants.%C.ee9)]\n// CHECK:STDOUT:   %require_complete.loc19_7: <witness> = require_complete_type %C.loc19_6.2 [symbolic = %require_complete.loc19_7 (constants.%require_complete.1fc)]\n// CHECK:STDOUT:   %C.Create.type: type = fn_type @C.Create, @C(%V.loc8_23.1) [symbolic = %C.Create.type (constants.%C.Create.type.c3d)]\n// CHECK:STDOUT:   %C.Create: @F.%C.Create.type (%C.Create.type.c3d) = struct_value () [symbolic = %C.Create (constants.%C.Create.b40)]\n// CHECK:STDOUT:   %C.Create.specific_fn.loc19_7.2: <specific function> = specific_function %C.Create, @C.Create(%V.loc8_23.1) [symbolic = %C.Create.specific_fn.loc19_7.2 (constants.%C.Create.specific_fn)]\n// CHECK:STDOUT:   %require_complete.loc19_16.1: <witness> = require_complete_type %V.loc8_23.1 [symbolic = %require_complete.loc19_16.1 (constants.%require_complete.441)]\n// CHECK:STDOUT:   %ImplicitAs.type.loc19_16.2: type = facet_type <@ImplicitAs, @ImplicitAs(%V.loc8_23.1)> [symbolic = %ImplicitAs.type.loc19_16.2 (constants.%ImplicitAs.type.1e5)]\n// CHECK:STDOUT:   %require_complete.loc19_16.2: <witness> = require_complete_type %ImplicitAs.type.loc19_16.2 [symbolic = %require_complete.loc19_16.2 (constants.%require_complete.cc6)]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%V.loc8_23.1) [symbolic = %ImplicitAs.assoc_type (constants.%ImplicitAs.assoc_type.d88)]\n// CHECK:STDOUT:   %assoc0: @F.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.d88) = assoc_entity element0, imports.%Core.import_ref.201 [symbolic = %assoc0 (constants.%assoc0.3d8)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %V.ref: type = name_ref V, %V.loc8_23.2 [symbolic = %V.loc8_23.1 (constants.%V)]\n// CHECK:STDOUT:     %C.loc19_6.1: type = class_type @C, @C(constants.%V) [symbolic = %C.loc19_6.2 (constants.%C.ee9)]\n// CHECK:STDOUT:     %.loc19_7: @F.%C.Create.type (%C.Create.type.c3d) = specific_constant @C.%C.Create.decl, @C(constants.%V) [symbolic = %C.Create (constants.%C.Create.b40)]\n// CHECK:STDOUT:     %Create.ref: @F.%C.Create.type (%C.Create.type.c3d) = name_ref Create, %.loc19_7 [symbolic = %C.Create (constants.%C.Create.b40)]\n// CHECK:STDOUT:     %.loc19_16.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %C.Create.specific_fn.loc19_7.1: <specific function> = specific_function %Create.ref, @C.Create(constants.%V) [symbolic = %C.Create.specific_fn.loc19_7.2 (constants.%C.Create.specific_fn)]\n// CHECK:STDOUT:     %ImplicitAs.type.loc19_16.1: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%V)> [symbolic = %ImplicitAs.type.loc19_16.2 (constants.%ImplicitAs.type.1e5)]\n// CHECK:STDOUT:     %.loc19_16.2: @F.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.d88) = specific_constant imports.%Core.import_ref.178, @ImplicitAs.WithSelf(constants.%V, constants.%Self.738) [symbolic = %assoc0 (constants.%assoc0.3d8)]\n// CHECK:STDOUT:     %Convert.ref: @F.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.d88) = name_ref Convert, %.loc19_16.2 [symbolic = %assoc0 (constants.%assoc0.3d8)]\n// CHECK:STDOUT:     %.loc19_16.3: @F.%V.loc8_23.1 (%V) = converted %.loc19_16.1, <error> [concrete = <error>]\n// CHECK:STDOUT:     %C.Create.call: init %empty_tuple.type = call %C.Create.specific_fn.loc19_7.1(<error>)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.Create.type => constants.%C.Create.type.c11\n// CHECK:STDOUT:   %C.Create => constants.%C.Create.723\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.Create(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d1c4.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%U, constants.%V) {\n// CHECK:STDOUT:   %U.loc8_13.1 => constants.%U\n// CHECK:STDOUT:   %V.loc8_23.1 => constants.%V\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%V) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%V\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.Create.type => constants.%C.Create.type.c3d\n// CHECK:STDOUT:   %C.Create => constants.%C.Create.b40\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.Create(constants.%V) {\n// CHECK:STDOUT:   %T => constants.%V\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.946\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.441\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_compatible_deduce.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d1c4.1: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %C.Create.type.c11: type = fn_type @C.Create, @C(%T) [symbolic]\n// CHECK:STDOUT:   %C.Create.723: %C.Create.type.c11 = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %.Self.16f: type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.031: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic]\n// CHECK:STDOUT:   %Self.738: %ImplicitAs.type.031 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.ff3: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b3a: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Dest, %Self.738) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.1de: %ImplicitAs.WithSelf.Convert.type.b3a = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.f60: type = facet_type <@ImplicitAs, @ImplicitAs(%.Self.16f)> [symbolic_self]\n// CHECK:STDOUT:   %type_where: type = facet_type <type where TODO> [concrete]\n// CHECK:STDOUT:   %pattern_type.354: type = pattern_type %type_where [concrete]\n// CHECK:STDOUT:   %V: %type_where = symbolic_binding V, 1 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %V.binding.as_type: type = symbolic_binding_type V, 1, %V [symbolic]\n// CHECK:STDOUT:   %C.bca: type = class_type @C, @C(%V.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %C.Create.type.242: type = fn_type @C.Create, @C(%V.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %C.Create.206: %C.Create.type.242 = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.232: <witness> = require_complete_type %C.bca [symbolic]\n// CHECK:STDOUT:   %pattern_type.20b: type = pattern_type %V.binding.as_type [symbolic]\n// CHECK:STDOUT:   %C.Create.specific_fn: <specific function> = specific_function %C.Create.206, @C.Create(%V.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %require_complete.94b: <witness> = require_complete_type %V.binding.as_type [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.ee4: type = facet_type <@ImplicitAs, @ImplicitAs(%V.binding.as_type)> [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.f30: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%V.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %assoc0.a1c: %ImplicitAs.assoc_type.f30 = assoc_entity element0, imports.%Core.import_ref.201 [symbolic]\n// CHECK:STDOUT:   %require_complete.24c: <witness> = require_complete_type %ImplicitAs.type.ee4 [symbolic]\n// CHECK:STDOUT:   %assoc0.843: %ImplicitAs.assoc_type.ff3 = assoc_entity element0, imports.%Core.import_ref.cc1 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.178: @ImplicitAs.WithSelf.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.ff3) = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%assoc0 (constants.%assoc0.843)]\n// CHECK:STDOUT:   %Core.import_ref.201: @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.type (%ImplicitAs.WithSelf.Convert.type.b3a) = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert (constants.%ImplicitAs.WithSelf.Convert.1de)]\n// CHECK:STDOUT:   %Core.import_ref.cc1 = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc4_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %V.patt: %pattern_type.354 = symbolic_binding_pattern V, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_17.1: type = splice_block %.loc9_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.3: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc9_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc9_13.2: type = symbolic_binding U, 0 [symbolic = %U.loc9_13.1 (constants.%U)]\n// CHECK:STDOUT:     %.loc9_32.1: type = splice_block %.loc9_32.2 [concrete = constants.%type_where] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc9_27: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.Self.2: type = symbolic_binding .Self [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %.loc9_39.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %ImplicitAs.ref: %ImplicitAs.type.cc7 = name_ref ImplicitAs, imports.%Core.ImplicitAs [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:       %.Self.ref: type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %ImplicitAs.type.loc9: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%.Self.16f)> [symbolic_self = constants.%ImplicitAs.type.f60]\n// CHECK:STDOUT:       %.loc9_39.2: type = converted %.loc9_39.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %.loc9_32.2: type = where_expr %.Self.2 [concrete = constants.%type_where] {\n// CHECK:STDOUT:         requirement_base_facet_type type\n// CHECK:STDOUT:         requirement_impls %.loc9_39.2, %ImplicitAs.type.loc9\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %V.loc9_23.2: %type_where = symbolic_binding V, 1 [symbolic = %V.loc9_23.1 (constants.%V)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T.loc4_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.Create.type: type = fn_type @C.Create, @C(%T.loc4_9.1) [symbolic = %C.Create.type (constants.%C.Create.type.c11)]\n// CHECK:STDOUT:   %C.Create: @C.%C.Create.type (%C.Create.type.c11) = struct_value () [symbolic = %C.Create (constants.%C.Create.723)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %C.Create.decl: @C.%C.Create.type (%C.Create.type.c11) = fn_decl @C.Create [symbolic = @C.%C.Create (constants.%C.Create.723)] {\n// CHECK:STDOUT:       %value.patt: @C.Create.%pattern_type (%pattern_type.51d1c4.1) = value_binding_pattern value [concrete]\n// CHECK:STDOUT:       %value.param_patt: @C.Create.%pattern_type (%pattern_type.51d1c4.1) = value_param_pattern %value.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %value.param: @C.Create.%T (%T) = value_param call_param0\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @C.%T.loc4_9.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %value: @C.Create.%T (%T) = value_binding value, %value.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .Create = %C.Create.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @C.Create(@C.%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T [symbolic = %pattern_type (constants.%pattern_type.51d1c4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%value.param: @C.Create.%T (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%U.loc9_13.2: type, %V.loc9_23.2: %type_where) {\n// CHECK:STDOUT:   %U.loc9_13.1: type = symbolic_binding U, 0 [symbolic = %U.loc9_13.1 (constants.%U)]\n// CHECK:STDOUT:   %V.loc9_23.1: %type_where = symbolic_binding V, 1 [symbolic = %V.loc9_23.1 (constants.%V)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %V.binding.as_type: type = symbolic_binding_type V, 1, %V.loc9_23.1 [symbolic = %V.binding.as_type (constants.%V.binding.as_type)]\n// CHECK:STDOUT:   %C.loc20_6.2: type = class_type @C, @C(%V.binding.as_type) [symbolic = %C.loc20_6.2 (constants.%C.bca)]\n// CHECK:STDOUT:   %require_complete.loc20_7: <witness> = require_complete_type %C.loc20_6.2 [symbolic = %require_complete.loc20_7 (constants.%require_complete.232)]\n// CHECK:STDOUT:   %C.Create.type: type = fn_type @C.Create, @C(%V.binding.as_type) [symbolic = %C.Create.type (constants.%C.Create.type.242)]\n// CHECK:STDOUT:   %C.Create: @F.%C.Create.type (%C.Create.type.242) = struct_value () [symbolic = %C.Create (constants.%C.Create.206)]\n// CHECK:STDOUT:   %C.Create.specific_fn.loc20_7.2: <specific function> = specific_function %C.Create, @C.Create(%V.binding.as_type) [symbolic = %C.Create.specific_fn.loc20_7.2 (constants.%C.Create.specific_fn)]\n// CHECK:STDOUT:   %require_complete.loc20_16.1: <witness> = require_complete_type %V.binding.as_type [symbolic = %require_complete.loc20_16.1 (constants.%require_complete.94b)]\n// CHECK:STDOUT:   %ImplicitAs.type.loc20_16.2: type = facet_type <@ImplicitAs, @ImplicitAs(%V.binding.as_type)> [symbolic = %ImplicitAs.type.loc20_16.2 (constants.%ImplicitAs.type.ee4)]\n// CHECK:STDOUT:   %require_complete.loc20_16.2: <witness> = require_complete_type %ImplicitAs.type.loc20_16.2 [symbolic = %require_complete.loc20_16.2 (constants.%require_complete.24c)]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%V.binding.as_type) [symbolic = %ImplicitAs.assoc_type (constants.%ImplicitAs.assoc_type.f30)]\n// CHECK:STDOUT:   %assoc0: @F.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.f30) = assoc_entity element0, imports.%Core.import_ref.201 [symbolic = %assoc0 (constants.%assoc0.a1c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %V.ref: %type_where = name_ref V, %V.loc9_23.2 [symbolic = %V.loc9_23.1 (constants.%V)]\n// CHECK:STDOUT:     %V.as_type: type = facet_access_type %V.ref [symbolic = %V.binding.as_type (constants.%V.binding.as_type)]\n// CHECK:STDOUT:     %.loc20_6: type = converted %V.ref, %V.as_type [symbolic = %V.binding.as_type (constants.%V.binding.as_type)]\n// CHECK:STDOUT:     %C.loc20_6.1: type = class_type @C, @C(constants.%V.binding.as_type) [symbolic = %C.loc20_6.2 (constants.%C.bca)]\n// CHECK:STDOUT:     %.loc20_7: @F.%C.Create.type (%C.Create.type.242) = specific_constant @C.%C.Create.decl, @C(constants.%V.binding.as_type) [symbolic = %C.Create (constants.%C.Create.206)]\n// CHECK:STDOUT:     %Create.ref: @F.%C.Create.type (%C.Create.type.242) = name_ref Create, %.loc20_7 [symbolic = %C.Create (constants.%C.Create.206)]\n// CHECK:STDOUT:     %.loc20_16.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %C.Create.specific_fn.loc20_7.1: <specific function> = specific_function %Create.ref, @C.Create(constants.%V.binding.as_type) [symbolic = %C.Create.specific_fn.loc20_7.2 (constants.%C.Create.specific_fn)]\n// CHECK:STDOUT:     %ImplicitAs.type.loc20_16.1: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%V.binding.as_type)> [symbolic = %ImplicitAs.type.loc20_16.2 (constants.%ImplicitAs.type.ee4)]\n// CHECK:STDOUT:     %.loc20_16.2: @F.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.f30) = specific_constant imports.%Core.import_ref.178, @ImplicitAs.WithSelf(constants.%V.binding.as_type, constants.%Self.738) [symbolic = %assoc0 (constants.%assoc0.a1c)]\n// CHECK:STDOUT:     %Convert.ref: @F.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.f30) = name_ref Convert, %.loc20_16.2 [symbolic = %assoc0 (constants.%assoc0.a1c)]\n// CHECK:STDOUT:     %.loc20_16.3: @F.%V.binding.as_type (%V.binding.as_type) = converted %.loc20_16.1, <error> [concrete = <error>]\n// CHECK:STDOUT:     %C.Create.call: init %empty_tuple.type = call %C.Create.specific_fn.loc20_7.1(<error>)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.Create.type => constants.%C.Create.type.c11\n// CHECK:STDOUT:   %C.Create => constants.%C.Create.723\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.Create(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d1c4.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%U, constants.%V) {\n// CHECK:STDOUT:   %U.loc9_13.1 => constants.%U\n// CHECK:STDOUT:   %V.loc9_23.1 => constants.%V\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%V.binding.as_type) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%V.binding.as_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.Create.type => constants.%C.Create.type.242\n// CHECK:STDOUT:   %C.Create => constants.%C.Create.206\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.Create(constants.%V.binding.as_type) {\n// CHECK:STDOUT:   %T => constants.%V.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.20b\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.94b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/deduce/generic_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/generic_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/generic_type.carbon\n\n// --- class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(T:! type) {}\nclass D {}\n\nfn F[T:! type](p: C(T)) -> T { return F(p); }\n\nfn G(p: C(D)) -> D {\n  return F(p);\n}\n\n// --- interface.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass I(T:! type) {}\nclass C {}\n\nfn F[T:! type](p: I(T)) -> C { return F(p); }\n\nfn G(p: I(C)) -> C {\n  return F(p);\n}\n\n// --- nested.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Outer(T:! type) {\n  class Inner(U:! type) {}\n}\n\nclass C {}\nclass D {}\n\n// C++ doesn't permit deducing `T` here because `Outer` might be specialized.\n// But that's not possible in Carbon, so we can deduce `T`.\nfn F[T:! type, U:! type](p: Outer(T).Inner(U)) -> (T, U) { return F(p); }\n\nfn G(p: Outer(C).Inner(D)) -> (C, D) {\n  return F(p);\n}\n\n// --- nontype.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass WithNontype(N:! i32) {}\n\nfn F[N:! i32](unused x: WithNontype(N)) -> i32 { return N; }\n\nfn G() -> i32 {\n  return F({} as WithNontype(0));\n}\n\n// CHECK:STDOUT: --- class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %pattern_type.3d5: type = pattern_type %C.5a3 [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.32c: <witness> = require_complete_type %C.5a3 [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.643: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT:   %C.302: type = class_type @C, @C(%D) [concrete]\n// CHECK:STDOUT:   %pattern_type.a7e: type = pattern_type %C.302 [concrete]\n// CHECK:STDOUT:   %.9a5: Core.Form = init_form %D [concrete]\n// CHECK:STDOUT:   %pattern_type.9c8: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.e8a: <specific function> = specific_function %F, @F(%D) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %p.patt: @F.%pattern_type.loc7_16 (%pattern_type.3d5) = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: @F.%pattern_type.loc7_16 (%pattern_type.3d5) = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc7_25 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc7_25 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc7_28: type = name_ref T, %T.loc7_6.2 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc7_28.3: Core.Form = init_form %T.ref.loc7_28 [symbolic = %.loc7_28.2 (constants.%.184)]\n// CHECK:STDOUT:     %.loc7_10.1: type = splice_block %.loc7_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:     %p.param: @F.%C.loc7_22.1 (%C.5a3) = value_param call_param0\n// CHECK:STDOUT:     %.loc7_22: type = splice_block %C.loc7_22.2 [symbolic = %C.loc7_22.1 (constants.%C.5a3)] {\n// CHECK:STDOUT:       %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:       %T.ref.loc7_21: type = name_ref T, %T.loc7_6.2 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:       %C.loc7_22.2: type = class_type @C, @C(constants.%T) [symbolic = %C.loc7_22.1 (constants.%C.5a3)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: @F.%C.loc7_22.1 (%C.5a3) = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref @F.%T.loc7_6.1 (%T) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%T.loc7_6.1 (%T) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.a7e = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.a7e = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.9c8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.9c8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref.loc9_18: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %.loc9_18.2: Core.Form = init_form %D.ref.loc9_18 [concrete = constants.%.9a5]\n// CHECK:STDOUT:     %p.param: %C.302 = value_param call_param0\n// CHECK:STDOUT:     %.loc9_12: type = splice_block %C [concrete = constants.%C.302] {\n// CHECK:STDOUT:       %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:       %D.ref.loc9_11: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:       %C: type = class_type @C, @C(constants.%D) [concrete = constants.%C.302]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %C.302 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %D = out_param call_param1\n// CHECK:STDOUT:     %return: ref %D = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T.loc4_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc7_6.2: type) {\n// CHECK:STDOUT:   %T.loc7_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:   %C.loc7_22.1: type = class_type @C, @C(%T.loc7_6.1) [symbolic = %C.loc7_22.1 (constants.%C.5a3)]\n// CHECK:STDOUT:   %pattern_type.loc7_16: type = pattern_type %C.loc7_22.1 [symbolic = %pattern_type.loc7_16 (constants.%pattern_type.3d5)]\n// CHECK:STDOUT:   %.loc7_28.2: Core.Form = init_form %T.loc7_6.1 [symbolic = %.loc7_28.2 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc7_25: type = pattern_type %T.loc7_6.1 [symbolic = %pattern_type.loc7_25 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc7_17: <witness> = require_complete_type %C.loc7_22.1 [symbolic = %require_complete.loc7_17 (constants.%require_complete.32c)]\n// CHECK:STDOUT:   %require_complete.loc7_28: <witness> = require_complete_type %T.loc7_6.1 [symbolic = %require_complete.loc7_28 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %F.specific_fn.loc7_39.2: <specific function> = specific_function constants.%F, @F(%T.loc7_6.1) [symbolic = %F.specific_fn.loc7_39.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%p.param: @F.%C.loc7_22.1 (%C.5a3)) -> out %return.param: @F.%T.loc7_6.1 (%T) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %p.ref: @F.%C.loc7_22.1 (%C.5a3) = name_ref p, %p\n// CHECK:STDOUT:     %F.specific_fn.loc7_39.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc7_39.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:     %.loc7_28.1: ref @F.%T.loc7_6.1 (%T) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%T.loc7_6.1 (%T) to %.loc7_28.1 = call %F.specific_fn.loc7_39.1(%p.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %C.302) -> out %return.param: %D {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %p.ref: %C.302 = name_ref p, %p\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%D) [concrete = constants.%F.specific_fn.e8a]\n// CHECK:STDOUT:   %.loc9_18.1: ref %D = splice_block %return.param {}\n// CHECK:STDOUT:   %F.call: init %D to %.loc9_18.1 = call %F.specific_fn(%p.ref)\n// CHECK:STDOUT:   return %F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_6.1 => constants.%T\n// CHECK:STDOUT:   %C.loc7_22.1 => constants.%C.5a3\n// CHECK:STDOUT:   %pattern_type.loc7_16 => constants.%pattern_type.3d5\n// CHECK:STDOUT:   %.loc7_28.2 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc7_25 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc7_17 => constants.%require_complete.32c\n// CHECK:STDOUT:   %require_complete.loc7_28 => constants.%require_complete.944\n// CHECK:STDOUT:   %F.specific_fn.loc7_39.2 => constants.%F.specific_fn.643\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%D) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%D\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%D) {\n// CHECK:STDOUT:   %T.loc7_6.1 => constants.%D\n// CHECK:STDOUT:   %C.loc7_22.1 => constants.%C.302\n// CHECK:STDOUT:   %pattern_type.loc7_16 => constants.%pattern_type.a7e\n// CHECK:STDOUT:   %.loc7_28.2 => constants.%.9a5\n// CHECK:STDOUT:   %pattern_type.loc7_25 => constants.%pattern_type.9c8\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc7_17 => constants.%complete_type\n// CHECK:STDOUT:   %require_complete.loc7_28 => constants.%complete_type\n// CHECK:STDOUT:   %F.specific_fn.loc7_39.2 => constants.%F.specific_fn.e8a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type: type = generic_class_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.3cf: type = class_type @I, @I(%T) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %pattern_type.7be: type = pattern_type %I.3cf [symbolic]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.3cf [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.643: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT:   %I.bce: type = class_type @I, @I(%C) [concrete]\n// CHECK:STDOUT:   %pattern_type.767: type = pattern_type %I.bce [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.540: <specific function> = specific_function %F, @F(%C) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: %I.type = class_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %p.patt: @F.%pattern_type (%pattern_type.7be) = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: @F.%pattern_type (%pattern_type.7be) = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc7_28.2: Core.Form = init_form %C.ref [concrete = constants.%.a69]\n// CHECK:STDOUT:     %.loc7_10.1: type = splice_block %.loc7_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:     %p.param: @F.%I.loc7_22.1 (%I.3cf) = value_param call_param0\n// CHECK:STDOUT:     %.loc7_22: type = splice_block %I.loc7_22.2 [symbolic = %I.loc7_22.1 (constants.%I.3cf)] {\n// CHECK:STDOUT:       %I.ref: %I.type = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc7_6.2 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:       %I.loc7_22.2: type = class_type @I, @I(constants.%T) [symbolic = %I.loc7_22.1 (constants.%I.3cf)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: @F.%I.loc7_22.1 (%I.3cf) = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param1\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.767 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.767 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc9_18: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc9_18.2: Core.Form = init_form %C.ref.loc9_18 [concrete = constants.%.a69]\n// CHECK:STDOUT:     %p.param: %I.bce = value_param call_param0\n// CHECK:STDOUT:     %.loc9_12: type = splice_block %I [concrete = constants.%I.bce] {\n// CHECK:STDOUT:       %I.ref: %I.type = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %C.ref.loc9_11: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %I: type = class_type @I, @I(constants.%C) [concrete = constants.%I.bce]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %I.bce = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param1\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @I(%T.loc4_9.2: type) {\n// CHECK:STDOUT:   %T.loc4_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%I.3cf\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc7_6.2: type) {\n// CHECK:STDOUT:   %T.loc7_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:   %I.loc7_22.1: type = class_type @I, @I(%T.loc7_6.1) [symbolic = %I.loc7_22.1 (constants.%I.3cf)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %I.loc7_22.1 [symbolic = %pattern_type (constants.%pattern_type.7be)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.loc7_22.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %F.specific_fn.loc7_39.2: <specific function> = specific_function constants.%F, @F(%T.loc7_6.1) [symbolic = %F.specific_fn.loc7_39.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%p.param: @F.%I.loc7_22.1 (%I.3cf)) -> out %return.param: %C {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %p.ref: @F.%I.loc7_22.1 (%I.3cf) = name_ref p, %p\n// CHECK:STDOUT:     %F.specific_fn.loc7_39.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc7_39.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:     %.loc7_28.1: ref %C = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init %C to %.loc7_28.1 = call %F.specific_fn.loc7_39.1(%p.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %I.bce) -> out %return.param: %C {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %p.ref: %I.bce = name_ref p, %p\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.540]\n// CHECK:STDOUT:   %.loc9_18.1: ref %C = splice_block %return.param {}\n// CHECK:STDOUT:   %F.call: init %C to %.loc9_18.1 = call %F.specific_fn(%p.ref)\n// CHECK:STDOUT:   return %F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_6.1 => constants.%T\n// CHECK:STDOUT:   %I.loc7_22.1 => constants.%I.3cf\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7be\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %F.specific_fn.loc7_39.2 => constants.%F.specific_fn.643\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%C) {\n// CHECK:STDOUT:   %T.loc4_9.1 => constants.%C\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C) {\n// CHECK:STDOUT:   %T.loc7_6.1 => constants.%C\n// CHECK:STDOUT:   %I.loc7_22.1 => constants.%I.bce\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.767\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT:   %F.specific_fn.loc7_39.2 => constants.%F.specific_fn.540\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- nested.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Outer.type: type = generic_class_type @Outer [concrete]\n// CHECK:STDOUT:   %Outer.generic: %Outer.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Outer.387: type = class_type @Outer, @Outer(%T) [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %Inner.type.e0d: type = generic_class_type @Inner, @Outer(%T) [symbolic]\n// CHECK:STDOUT:   %Inner.generic.ada: %Inner.type.e0d = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.e21: type = class_type @Inner, @Inner(%T, %U) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %require_complete.448: <witness> = require_complete_type %Outer.387 [symbolic]\n// CHECK:STDOUT:   %pattern_type.0d1: type = pattern_type %Inner.e21 [symbolic]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.4b9: %tuple.type.24b = tuple_value (%T, %U) [symbolic]\n// CHECK:STDOUT:   %tuple.type.a5e: type = tuple_type (%T, %U) [symbolic]\n// CHECK:STDOUT:   %.f18: Core.Form = init_form %tuple.type.a5e [symbolic]\n// CHECK:STDOUT:   %pattern_type.eee: type = pattern_type %tuple.type.a5e [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.41c: <witness> = require_complete_type %Inner.e21 [symbolic]\n// CHECK:STDOUT:   %require_complete.220: <witness> = require_complete_type %tuple.type.a5e [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.a54: <specific function> = specific_function %F, @F(%T, %U) [symbolic]\n// CHECK:STDOUT:   %Outer.eed: type = class_type @Outer, @Outer(%C) [concrete]\n// CHECK:STDOUT:   %Inner.type.e8c: type = generic_class_type @Inner, @Outer(%C) [concrete]\n// CHECK:STDOUT:   %Inner.generic.9a9: %Inner.type.e8c = struct_value () [concrete]\n// CHECK:STDOUT:   %Inner.240: type = class_type @Inner, @Inner(%C, %D) [concrete]\n// CHECK:STDOUT:   %pattern_type.204: type = pattern_type %Inner.240 [concrete]\n// CHECK:STDOUT:   %tuple.a0a: %tuple.type.24b = tuple_value (%C, %D) [concrete]\n// CHECK:STDOUT:   %tuple.type.281: type = tuple_type (%C, %D) [concrete]\n// CHECK:STDOUT:   %.eae: Core.Form = init_form %tuple.type.281 [concrete]\n// CHECK:STDOUT:   %pattern_type.881: type = pattern_type %tuple.type.281 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.107: <specific function> = specific_function %F, @F(%C, %D) [concrete]\n// CHECK:STDOUT:   %complete_type.734: <witness> = complete_type_witness %tuple.type.281 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Outer = %Outer.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Outer.decl: %Outer.type = class_decl @Outer [concrete = constants.%Outer.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %p.patt: @F.%pattern_type.loc13_26 (%pattern_type.0d1) = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: @F.%pattern_type.loc13_26 (%pattern_type.0d1) = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc13_48 (%pattern_type.eee) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc13_48 (%pattern_type.eee) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc13_52: type = name_ref T, %T.loc13_6.2 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:     %U.ref.loc13_55: type = name_ref U, %U.loc13_16.2 [symbolic = %U.loc13_16.1 (constants.%U)]\n// CHECK:STDOUT:     %.loc13_56.3: %tuple.type.24b = tuple_literal (%T.ref.loc13_52, %U.ref.loc13_55) [symbolic = %tuple (constants.%tuple.4b9)]\n// CHECK:STDOUT:     %.loc13_56.4: type = converted %.loc13_56.3, constants.%tuple.type.a5e [symbolic = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:     %.loc13_56.5: Core.Form = init_form %.loc13_56.4 [symbolic = %.loc13_56.2 (constants.%.f18)]\n// CHECK:STDOUT:     %.loc13_10.1: type = splice_block %.loc13_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc13_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc13_20.1: type = splice_block %.loc13_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc13_16.2: type = symbolic_binding U, 1 [symbolic = %U.loc13_16.1 (constants.%U)]\n// CHECK:STDOUT:     %p.param: @F.%Inner.loc13_45.1 (%Inner.e21) = value_param call_param0\n// CHECK:STDOUT:     %.loc13_45: type = splice_block %Inner.loc13_45.2 [symbolic = %Inner.loc13_45.1 (constants.%Inner.e21)] {\n// CHECK:STDOUT:       %Outer.ref: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:       %T.ref.loc13_35: type = name_ref T, %T.loc13_6.2 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:       %Outer.loc13_36.2: type = class_type @Outer, @Outer(constants.%T) [symbolic = %Outer.loc13_36.1 (constants.%Outer.387)]\n// CHECK:STDOUT:       %.loc13_37: @F.%Inner.type (%Inner.type.e0d) = specific_constant @Outer.%Inner.decl, @Outer(constants.%T) [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:       %Inner.ref: @F.%Inner.type (%Inner.type.e0d) = name_ref Inner, %.loc13_37 [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:       %U.ref.loc13_44: type = name_ref U, %U.loc13_16.2 [symbolic = %U.loc13_16.1 (constants.%U)]\n// CHECK:STDOUT:       %Inner.loc13_45.2: type = class_type @Inner, @Inner(constants.%T, constants.%U) [symbolic = %Inner.loc13_45.1 (constants.%Inner.e21)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: @F.%Inner.loc13_45.1 (%Inner.e21) = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref @F.%tuple.type (%tuple.type.a5e) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%tuple.type (%tuple.type.a5e) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.204 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.204 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.881 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.881 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc15_32: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %D.ref.loc15_35: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %.loc15_36.2: %tuple.type.24b = tuple_literal (%C.ref.loc15_32, %D.ref.loc15_35) [concrete = constants.%tuple.a0a]\n// CHECK:STDOUT:     %.loc15_36.3: type = converted %.loc15_36.2, constants.%tuple.type.281 [concrete = constants.%tuple.type.281]\n// CHECK:STDOUT:     %.loc15_36.4: Core.Form = init_form %.loc15_36.3 [concrete = constants.%.eae]\n// CHECK:STDOUT:     %p.param: %Inner.240 = value_param call_param0\n// CHECK:STDOUT:     %.loc15_25: type = splice_block %Inner [concrete = constants.%Inner.240] {\n// CHECK:STDOUT:       %Outer.ref: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:       %C.ref.loc15_15: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %Outer: type = class_type @Outer, @Outer(constants.%C) [concrete = constants.%Outer.eed]\n// CHECK:STDOUT:       %.loc15_17: %Inner.type.e8c = specific_constant @Outer.%Inner.decl, @Outer(constants.%C) [concrete = constants.%Inner.generic.9a9]\n// CHECK:STDOUT:       %Inner.ref: %Inner.type.e8c = name_ref Inner, %.loc15_17 [concrete = constants.%Inner.generic.9a9]\n// CHECK:STDOUT:       %D.ref.loc15_24: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:       %Inner: type = class_type @Inner, @Inner(constants.%C, constants.%D) [concrete = constants.%Inner.240]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %Inner.240 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %tuple.type.281 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %tuple.type.281 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Outer(%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type: type = generic_class_type @Inner, @Outer(%T.loc4_13.1) [symbolic = %Inner.type (constants.%Inner.type.e0d)]\n// CHECK:STDOUT:   %Inner.generic: @Outer.%Inner.type (%Inner.type.e0d) = struct_value () [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Inner.decl: @Outer.%Inner.type (%Inner.type.e0d) = class_decl @Inner [symbolic = @Outer.%Inner.generic (constants.%Inner.generic.ada)] {\n// CHECK:STDOUT:       %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc5_19.1: type = splice_block %.loc5_19.2 [concrete = type] {\n// CHECK:STDOUT:         %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:         %.loc5_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %U.loc5_15.2: type = symbolic_binding U, 1 [symbolic = %U.loc5_15.1 (constants.%U)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Outer.387\n// CHECK:STDOUT:     .Inner = %Inner.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Inner(@Outer.%T.loc4_13.2: type, %U.loc5_15.2: type) {\n// CHECK:STDOUT:   %U.loc5_15.1: type = symbolic_binding U, 1 [symbolic = %U.loc5_15.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Inner.e21\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc13_6.2: type, %U.loc13_16.2: type) {\n// CHECK:STDOUT:   %T.loc13_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:   %U.loc13_16.1: type = symbolic_binding U, 1 [symbolic = %U.loc13_16.1 (constants.%U)]\n// CHECK:STDOUT:   %Outer.loc13_36.1: type = class_type @Outer, @Outer(%T.loc13_6.1) [symbolic = %Outer.loc13_36.1 (constants.%Outer.387)]\n// CHECK:STDOUT:   %require_complete.loc13_37: <witness> = require_complete_type %Outer.loc13_36.1 [symbolic = %require_complete.loc13_37 (constants.%require_complete.448)]\n// CHECK:STDOUT:   %Inner.type: type = generic_class_type @Inner, @Outer(%T.loc13_6.1) [symbolic = %Inner.type (constants.%Inner.type.e0d)]\n// CHECK:STDOUT:   %Inner.generic: @F.%Inner.type (%Inner.type.e0d) = struct_value () [symbolic = %Inner.generic (constants.%Inner.generic.ada)]\n// CHECK:STDOUT:   %Inner.loc13_45.1: type = class_type @Inner, @Inner(%T.loc13_6.1, %U.loc13_16.1) [symbolic = %Inner.loc13_45.1 (constants.%Inner.e21)]\n// CHECK:STDOUT:   %pattern_type.loc13_26: type = pattern_type %Inner.loc13_45.1 [symbolic = %pattern_type.loc13_26 (constants.%pattern_type.0d1)]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%T.loc13_6.1, %U.loc13_16.1) [symbolic = %tuple (constants.%tuple.4b9)]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%T.loc13_6.1, %U.loc13_16.1) [symbolic = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:   %.loc13_56.2: Core.Form = init_form %tuple.type [symbolic = %.loc13_56.2 (constants.%.f18)]\n// CHECK:STDOUT:   %pattern_type.loc13_48: type = pattern_type %tuple.type [symbolic = %pattern_type.loc13_48 (constants.%pattern_type.eee)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc13_27: <witness> = require_complete_type %Inner.loc13_45.1 [symbolic = %require_complete.loc13_27 (constants.%require_complete.41c)]\n// CHECK:STDOUT:   %require_complete.loc13_56: <witness> = require_complete_type %tuple.type [symbolic = %require_complete.loc13_56 (constants.%require_complete.220)]\n// CHECK:STDOUT:   %F.specific_fn.loc13_67.2: <specific function> = specific_function constants.%F, @F(%T.loc13_6.1, %U.loc13_16.1) [symbolic = %F.specific_fn.loc13_67.2 (constants.%F.specific_fn.a54)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%p.param: @F.%Inner.loc13_45.1 (%Inner.e21)) -> out %return.param: @F.%tuple.type (%tuple.type.a5e) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %p.ref: @F.%Inner.loc13_45.1 (%Inner.e21) = name_ref p, %p\n// CHECK:STDOUT:     %F.specific_fn.loc13_67.1: <specific function> = specific_function %F.ref, @F(constants.%T, constants.%U) [symbolic = %F.specific_fn.loc13_67.2 (constants.%F.specific_fn.a54)]\n// CHECK:STDOUT:     %.loc13_56.1: ref @F.%tuple.type (%tuple.type.a5e) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%tuple.type (%tuple.type.a5e) to %.loc13_56.1 = call %F.specific_fn.loc13_67.1(%p.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %Inner.240) -> out %return.param: %tuple.type.281 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %p.ref: %Inner.240 = name_ref p, %p\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C, constants.%D) [concrete = constants.%F.specific_fn.107]\n// CHECK:STDOUT:   %.loc15_36.1: ref %tuple.type.281 = splice_block %return.param {}\n// CHECK:STDOUT:   %F.call: init %tuple.type.281 to %.loc15_36.1 = call %F.specific_fn(%p.ref)\n// CHECK:STDOUT:   return %F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.e0d\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.ada\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %U.loc5_15.1 => constants.%U\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc13_6.1 => constants.%T\n// CHECK:STDOUT:   %U.loc13_16.1 => constants.%U\n// CHECK:STDOUT:   %Outer.loc13_36.1 => constants.%Outer.387\n// CHECK:STDOUT:   %require_complete.loc13_37 => constants.%require_complete.448\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.e0d\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.ada\n// CHECK:STDOUT:   %Inner.loc13_45.1 => constants.%Inner.e21\n// CHECK:STDOUT:   %pattern_type.loc13_26 => constants.%pattern_type.0d1\n// CHECK:STDOUT:   %tuple => constants.%tuple.4b9\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.a5e\n// CHECK:STDOUT:   %.loc13_56.2 => constants.%.f18\n// CHECK:STDOUT:   %pattern_type.loc13_48 => constants.%pattern_type.eee\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc13_27 => constants.%require_complete.41c\n// CHECK:STDOUT:   %require_complete.loc13_56 => constants.%require_complete.220\n// CHECK:STDOUT:   %F.specific_fn.loc13_67.2 => constants.%F.specific_fn.a54\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%C) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%C\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.e8c\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.9a9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%C, constants.%D) {\n// CHECK:STDOUT:   %U.loc5_15.1 => constants.%D\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C, constants.%D) {\n// CHECK:STDOUT:   %T.loc13_6.1 => constants.%C\n// CHECK:STDOUT:   %U.loc13_16.1 => constants.%D\n// CHECK:STDOUT:   %Outer.loc13_36.1 => constants.%Outer.eed\n// CHECK:STDOUT:   %require_complete.loc13_37 => constants.%complete_type.357\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.e8c\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.9a9\n// CHECK:STDOUT:   %Inner.loc13_45.1 => constants.%Inner.240\n// CHECK:STDOUT:   %pattern_type.loc13_26 => constants.%pattern_type.204\n// CHECK:STDOUT:   %tuple => constants.%tuple.a0a\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.281\n// CHECK:STDOUT:   %.loc13_56.2 => constants.%.eae\n// CHECK:STDOUT:   %pattern_type.loc13_48 => constants.%pattern_type.881\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc13_27 => constants.%complete_type.357\n// CHECK:STDOUT:   %require_complete.loc13_56 => constants.%complete_type.734\n// CHECK:STDOUT:   %F.specific_fn.loc13_67.2 => constants.%F.specific_fn.107\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- nontype.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N.fe9: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.5de: %i32 = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %WithNontype.type: type = generic_class_type @WithNontype [concrete]\n// CHECK:STDOUT:   %WithNontype.generic: %WithNontype.type = struct_value () [concrete]\n// CHECK:STDOUT:   %WithNontype.205: type = class_type @WithNontype, @WithNontype(%N.5de) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.43d: type = pattern_type %WithNontype.205 [symbolic]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.643: <witness> = require_complete_type %WithNontype.205 [symbolic]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N.fe9) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound.e78: <bound method> = bound_method %N.5de, %Int.as.Copy.impl.Op.664 [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.207: <bound method> = bound_method %N.5de, %Int.as.Copy.impl.Op.specific_fn [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.d2e: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %WithNontype.6bb: type = class_type @WithNontype, @WithNontype(%int_0.6a9) [concrete]\n// CHECK:STDOUT:   %WithNontype.val: %WithNontype.6bb = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7a0: type = pattern_type %WithNontype.6bb [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_0.6a9) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound.06d: <bound method> = bound_method %int_0.6a9, %Int.as.Copy.impl.Op.664 [concrete]\n// CHECK:STDOUT:   %bound_method.5f6: <bound method> = bound_method %int_0.6a9, %Int.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .WithNontype = %WithNontype.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %WithNontype.decl: %WithNontype.type = class_decl @WithNontype [concrete = constants.%WithNontype.generic] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4: type = splice_block %i32 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_19.2: %i32 = symbolic_binding N, 0 [symbolic = %N.loc4_19.1 (constants.%N.5de)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.43d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.43d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6_44: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6_44: Core.Form = init_form %i32.loc6_44 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc6_10: type = splice_block %i32.loc6_10 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32.loc6_10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc6_6.2: %i32 = symbolic_binding N, 0 [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:     %x.param: @F.%WithNontype.loc6_38.1 (%WithNontype.205) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_38: type = splice_block %WithNontype.loc6_38.2 [symbolic = %WithNontype.loc6_38.1 (constants.%WithNontype.205)] {\n// CHECK:STDOUT:       %WithNontype.ref: %WithNontype.type = name_ref WithNontype, file.%WithNontype.decl [concrete = constants.%WithNontype.generic]\n// CHECK:STDOUT:       %N.ref.loc6_37: %i32 = name_ref N, %N.loc6_6.2 [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:       %WithNontype.loc6_38.2: type = class_type @WithNontype, @WithNontype(constants.%N.5de) [symbolic = %WithNontype.loc6_38.1 (constants.%WithNontype.205)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @F.%WithNontype.loc6_38.1 (%WithNontype.205) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @WithNontype(%N.loc4_19.2: %i32) {\n// CHECK:STDOUT:   %N.loc4_19.1: %i32 = symbolic_binding N, 0 [symbolic = %N.loc4_19.1 (constants.%N.5de)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%WithNontype.205\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%N.loc6_6.2: %i32) {\n// CHECK:STDOUT:   %N.loc6_6.1: %i32 = symbolic_binding N, 0 [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:   %WithNontype.loc6_38.1: type = class_type @WithNontype, @WithNontype(%N.loc6_6.1) [symbolic = %WithNontype.loc6_38.1 (constants.%WithNontype.205)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %WithNontype.loc6_38.1 [symbolic = %pattern_type (constants.%pattern_type.43d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %WithNontype.loc6_38.1 [symbolic = %require_complete (constants.%require_complete.643)]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound: <bound method> = bound_method %N.loc6_6.1, constants.%Int.as.Copy.impl.Op.664 [symbolic = %Int.as.Copy.impl.Op.bound (constants.%Int.as.Copy.impl.Op.bound.e78)]\n// CHECK:STDOUT:   %bound_method.loc6_57.3: <bound method> = bound_method %N.loc6_6.1, constants.%Int.as.Copy.impl.Op.specific_fn [symbolic = %bound_method.loc6_57.3 (constants.%bound_method.207)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%WithNontype.loc6_38.1 (%WithNontype.205)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %N.ref.loc6_57: %i32 = name_ref N, %N.loc6_6.2 [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:     %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:     %bound_method.loc6_57.1: <bound method> = bound_method %N.ref.loc6_57, %impl.elem0 [symbolic = %Int.as.Copy.impl.Op.bound (constants.%Int.as.Copy.impl.Op.bound.e78)]\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_57.2: <bound method> = bound_method %N.ref.loc6_57, %specific_fn [symbolic = %bound_method.loc6_57.3 (constants.%bound_method.207)]\n// CHECK:STDOUT:     %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_57.2(%N.ref.loc6_57) [symbolic = %N.loc6_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:     return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc9_13.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %WithNontype.ref: %WithNontype.type = name_ref WithNontype, file.%WithNontype.decl [concrete = constants.%WithNontype.generic]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc9_31.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_31.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method.d2e]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc9_31.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc9_31.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc9_31.2: %i32 = converted %int_0, %.loc9_31.1 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %WithNontype: type = class_type @WithNontype, @WithNontype(constants.%int_0.6a9) [concrete = constants.%WithNontype.6bb]\n// CHECK:STDOUT:   %.loc9_13.2: ref %WithNontype.6bb = temporary_storage\n// CHECK:STDOUT:   %.loc9_13.3: init %WithNontype.6bb to %.loc9_13.2 = class_init () [concrete = constants.%WithNontype.val]\n// CHECK:STDOUT:   %.loc9_15.1: init %WithNontype.6bb = converted %.loc9_13.1, %.loc9_13.3 [concrete = constants.%WithNontype.val]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%int_0.6a9) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %.loc9_15.2: ref %WithNontype.6bb = temporary %.loc9_13.2, %.loc9_15.1\n// CHECK:STDOUT:   %.loc9_15.3: %WithNontype.6bb = acquire_value %.loc9_15.2\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%.loc9_15.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc9_15.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc9_15.2)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %WithNontype.6bb) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WithNontype(constants.%N.5de) {\n// CHECK:STDOUT:   %N.loc4_19.1 => constants.%N.5de\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%N.5de) {\n// CHECK:STDOUT:   %N.loc6_6.1 => constants.%N.5de\n// CHECK:STDOUT:   %WithNontype.loc6_38.1 => constants.%WithNontype.205\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.43d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WithNontype(constants.%int_0.6a9) {\n// CHECK:STDOUT:   %N.loc4_19.1 => constants.%int_0.6a9\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%int_0.6a9) {\n// CHECK:STDOUT:   %N.loc6_6.1 => constants.%int_0.6a9\n// CHECK:STDOUT:   %WithNontype.loc6_38.1 => constants.%WithNontype.6bb\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7a0\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.357\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound => constants.%Int.as.Copy.impl.Op.bound.06d\n// CHECK:STDOUT:   %bound_method.loc6_57.3 => constants.%bound_method.5f6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/deduce/int_float.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/int_float.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/int_float.carbon\n\n// --- int.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[N:! Core.IntLiteral()](unused n: Core.Int(N)) -> Core.IntLiteral() {\n  return N;\n}\n\nfn G(a: i64) -> Core.IntLiteral() {\n  return F(a);\n}\n\n// --- float.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[N:! Core.IntLiteral()](unused n: Core.Float(N)) -> Core.IntLiteral() {\n  return N;\n}\n\nfn G(a: f64) -> Core.IntLiteral() {\n  return F(a);\n}\n\n// CHECK:STDOUT: --- int.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Int: type = class_type @Int, @Int(%N) [symbolic]\n// CHECK:STDOUT:   %pattern_type.764: type = pattern_type %Int [symbolic]\n// CHECK:STDOUT:   %.f7d: Core.Form = init_form Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.901: <witness> = require_complete_type %Int [symbolic]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.98e: <witness> = impl_witness imports.%Copy.impl_witness_table.d8f [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value Core.IntLiteral, (%Copy.impl_witness.98e) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.42e: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.5e6: type = fn_type_with_self_type %Copy.WithSelf.Op.type.42e, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.type: type = fn_type @Core.IntLiteral.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op: %Core.IntLiteral.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.bound.555: <bound method> = bound_method %N, %Core.IntLiteral.as.Copy.impl.Op [symbolic]\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %i64: type = class_type @Int, @Int(%int_64) [concrete]\n// CHECK:STDOUT:   %pattern_type.95b: type = pattern_type %i64 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i64.builtin: type = int_type signed, %int_64 [concrete]\n// CHECK:STDOUT:   %complete_type.4a1: <witness> = complete_type_witness %i64.builtin [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.bound.04a: <bound method> = bound_method %int_64, %Core.IntLiteral.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.66a: %Core.IntLiteral.as.Copy.impl.Op.type = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [concrete = constants.%Core.IntLiteral.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.d8f = impl_witness_table (%Core.import_ref.66a), @Core.IntLiteral.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:     %n.patt: @F.%pattern_type (%pattern_type.764) = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: @F.%pattern_type (%pattern_type.764) = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.dc0 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.dc0 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Core.ref.loc4_55: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %IntLiteral.ref.loc4_59: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:     %IntLiteral.call.loc4_71: init type = call %IntLiteral.ref.loc4_59() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc4_71.1: type = value_of_initializer %IntLiteral.call.loc4_71 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc4_71.2: type = converted %IntLiteral.call.loc4_71, %.loc4_71.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc4_71.3: Core.Form = init_form %.loc4_71.2 [concrete = constants.%.f7d]\n// CHECK:STDOUT:     %.loc4_26.1: type = splice_block %.loc4_26.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Core.ref.loc4_10: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref.loc4_14: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call.loc4_26: init type = call %IntLiteral.ref.loc4_14() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_26.2: type = value_of_initializer %IntLiteral.call.loc4_26 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_26.3: type = converted %IntLiteral.call.loc4_26, %.loc4_26.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_6.2: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:     %n.param: @F.%Int.loc4_49.1 (%Int) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_49: type = splice_block %Int.loc4_49.2 [symbolic = %Int.loc4_49.1 (constants.%Int)] {\n// CHECK:STDOUT:       %Core.ref.loc4_39: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Int.ref: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:       %N.ref.loc4: Core.IntLiteral = name_ref N, %N.loc4_6.2 [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:       %Int.loc4_49.2: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc4_49.1 (constants.%Int)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %n: @F.%Int.loc4_49.1 (%Int) = value_binding n, %n.param\n// CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param call_param1\n// CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.95b = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.95b = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.dc0 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.dc0 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:     %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc8_33.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc8_33.2: type = converted %IntLiteral.call, %.loc8_33.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc8_33.3: Core.Form = init_form %.loc8_33.2 [concrete = constants.%.f7d]\n// CHECK:STDOUT:     %a.param: %i64 = value_param call_param0\n// CHECK:STDOUT:     %i64: type = type_literal constants.%i64 [concrete = constants.%i64]\n// CHECK:STDOUT:     %a: %i64 = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param call_param1\n// CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%N.loc4_6.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N.loc4_6.1: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:   %Int.loc4_49.1: type = class_type @Int, @Int(%N.loc4_6.1) [symbolic = %Int.loc4_49.1 (constants.%Int)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Int.loc4_49.1 [symbolic = %pattern_type (constants.%pattern_type.764)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Int.loc4_49.1 [symbolic = %require_complete (constants.%require_complete.901)]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.bound: <bound method> = bound_method %N.loc4_6.1, constants.%Core.IntLiteral.as.Copy.impl.Op [symbolic = %Core.IntLiteral.as.Copy.impl.Op.bound (constants.%Core.IntLiteral.as.Copy.impl.Op.bound.555)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%n.param: @F.%Int.loc4_49.1 (%Int)) -> out %return.param: Core.IntLiteral {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %N.ref.loc5: Core.IntLiteral = name_ref N, %N.loc4_6.2 [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:     %impl.elem0: %.5e6 = impl_witness_access constants.%Copy.impl_witness.98e, element0 [concrete = constants.%Core.IntLiteral.as.Copy.impl.Op]\n// CHECK:STDOUT:     %bound_method: <bound method> = bound_method %N.ref.loc5, %impl.elem0 [symbolic = %Core.IntLiteral.as.Copy.impl.Op.bound (constants.%Core.IntLiteral.as.Copy.impl.Op.bound.555)]\n// CHECK:STDOUT:     %Core.IntLiteral.as.Copy.impl.Op.call: init Core.IntLiteral = call %bound_method(%N.ref.loc5) [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:     return %Core.IntLiteral.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%a.param: %i64) -> out %return.param: Core.IntLiteral {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %a.ref: %i64 = name_ref a, %a\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%int_64) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init Core.IntLiteral = call %F.specific_fn(%a.ref)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%N) {\n// CHECK:STDOUT:   %N.loc4_6.1 => constants.%N\n// CHECK:STDOUT:   %Int.loc4_49.1 => constants.%Int\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.764\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%int_64) {\n// CHECK:STDOUT:   %N.loc4_6.1 => constants.%int_64\n// CHECK:STDOUT:   %Int.loc4_49.1 => constants.%i64\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.95b\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.4a1\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.bound => constants.%Core.IntLiteral.as.Copy.impl.Op.bound.04a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- float.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]\n// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Float: type = class_type @Float, @Float(%N) [symbolic]\n// CHECK:STDOUT:   %pattern_type.7d0: type = pattern_type %Float [symbolic]\n// CHECK:STDOUT:   %.f7d: Core.Form = init_form Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.dc0: <witness> = require_complete_type %Float [symbolic]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.98e: <witness> = impl_witness imports.%Copy.impl_witness_table.d8f [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value Core.IntLiteral, (%Copy.impl_witness.98e) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.42e: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.5e6: type = fn_type_with_self_type %Copy.WithSelf.Op.type.42e, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.type: type = fn_type @Core.IntLiteral.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op: %Core.IntLiteral.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.bound.555: <bound method> = bound_method %N, %Core.IntLiteral.as.Copy.impl.Op [symbolic]\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %f64.794: type = float_type %int_64, f64 [concrete]\n// CHECK:STDOUT:   %complete_type.7b9: <witness> = complete_type_witness %f64.794 [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.bound.04a: <bound method> = bound_method %int_64, %Core.IntLiteral.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Float = %Core.Float\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.66a: %Core.IntLiteral.as.Copy.impl.Op.type = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [concrete = constants.%Core.IntLiteral.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.d8f = impl_witness_table (%Core.import_ref.66a), @Core.IntLiteral.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:     %n.patt: @F.%pattern_type (%pattern_type.7d0) = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: @F.%pattern_type (%pattern_type.7d0) = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.dc0 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.dc0 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Core.ref.loc4_57: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %IntLiteral.ref.loc4_61: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:     %IntLiteral.call.loc4_73: init type = call %IntLiteral.ref.loc4_61() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc4_73.1: type = value_of_initializer %IntLiteral.call.loc4_73 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc4_73.2: type = converted %IntLiteral.call.loc4_73, %.loc4_73.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc4_73.3: Core.Form = init_form %.loc4_73.2 [concrete = constants.%.f7d]\n// CHECK:STDOUT:     %.loc4_26.1: type = splice_block %.loc4_26.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Core.ref.loc4_10: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref.loc4_14: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call.loc4_26: init type = call %IntLiteral.ref.loc4_14() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_26.2: type = value_of_initializer %IntLiteral.call.loc4_26 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_26.3: type = converted %IntLiteral.call.loc4_26, %.loc4_26.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_6.2: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:     %n.param: @F.%Float.loc4_51.1 (%Float) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_51: type = splice_block %Float.loc4_51.2 [symbolic = %Float.loc4_51.1 (constants.%Float)] {\n// CHECK:STDOUT:       %Core.ref.loc4_39: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Float.ref: %Float.type = name_ref Float, imports.%Core.Float [concrete = constants.%Float.generic]\n// CHECK:STDOUT:       %N.ref.loc4: Core.IntLiteral = name_ref N, %N.loc4_6.2 [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:       %Float.loc4_51.2: type = class_type @Float, @Float(constants.%N) [symbolic = %Float.loc4_51.1 (constants.%Float)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %n: @F.%Float.loc4_51.1 (%Float) = value_binding n, %n.param\n// CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param call_param1\n// CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.0ae = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.0ae = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.dc0 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.dc0 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:     %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc8_33.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc8_33.2: type = converted %IntLiteral.call, %.loc8_33.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc8_33.3: Core.Form = init_form %.loc8_33.2 [concrete = constants.%.f7d]\n// CHECK:STDOUT:     %a.param: %f64.d77 = value_param call_param0\n// CHECK:STDOUT:     %f64: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:     %a: %f64.d77 = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param call_param1\n// CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%N.loc4_6.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N.loc4_6.1: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:   %Float.loc4_51.1: type = class_type @Float, @Float(%N.loc4_6.1) [symbolic = %Float.loc4_51.1 (constants.%Float)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Float.loc4_51.1 [symbolic = %pattern_type (constants.%pattern_type.7d0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Float.loc4_51.1 [symbolic = %require_complete (constants.%require_complete.dc0)]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.bound: <bound method> = bound_method %N.loc4_6.1, constants.%Core.IntLiteral.as.Copy.impl.Op [symbolic = %Core.IntLiteral.as.Copy.impl.Op.bound (constants.%Core.IntLiteral.as.Copy.impl.Op.bound.555)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%n.param: @F.%Float.loc4_51.1 (%Float)) -> out %return.param: Core.IntLiteral {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %N.ref.loc5: Core.IntLiteral = name_ref N, %N.loc4_6.2 [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:     %impl.elem0: %.5e6 = impl_witness_access constants.%Copy.impl_witness.98e, element0 [concrete = constants.%Core.IntLiteral.as.Copy.impl.Op]\n// CHECK:STDOUT:     %bound_method: <bound method> = bound_method %N.ref.loc5, %impl.elem0 [symbolic = %Core.IntLiteral.as.Copy.impl.Op.bound (constants.%Core.IntLiteral.as.Copy.impl.Op.bound.555)]\n// CHECK:STDOUT:     %Core.IntLiteral.as.Copy.impl.Op.call: init Core.IntLiteral = call %bound_method(%N.ref.loc5) [symbolic = %N.loc4_6.1 (constants.%N)]\n// CHECK:STDOUT:     return %Core.IntLiteral.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%a.param: %f64.d77) -> out %return.param: Core.IntLiteral {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %a.ref: %f64.d77 = name_ref a, %a\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%int_64) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init Core.IntLiteral = call %F.specific_fn(%a.ref)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%N) {\n// CHECK:STDOUT:   %N.loc4_6.1 => constants.%N\n// CHECK:STDOUT:   %Float.loc4_51.1 => constants.%Float\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7d0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%int_64) {\n// CHECK:STDOUT:   %N.loc4_6.1 => constants.%int_64\n// CHECK:STDOUT:   %Float.loc4_51.1 => constants.%f64.d77\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.0ae\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.7b9\n// CHECK:STDOUT:   %Core.IntLiteral.as.Copy.impl.Op.bound => constants.%Core.IntLiteral.as.Copy.impl.Op.bound.04a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/deduce/symbolic_facets.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/symbolic_facets.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/symbolic_facets.carbon\n\n// By placing each interface inside a generic class, a facet type refering to\n// the interface becomes symbolic. Normally they would be concrete. This can\n// affect decisions in deduce which unwraps symbolic constants, but still needs to\n// ensure they convert correctly.\n\n// --- fail_missing_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(CC:! type) {\n  interface A {}\n  fn F(unused T:! A) {}\n}\n\nclass D(DD:! type) {\n  interface B {}\n  fn G(T:! B) {\n    // T only implements D(DD).B, so should not convert to a facet value\n    // implementing C(()).A.\n    //\n    // CHECK:STDERR: fail_missing_interface.carbon:[[@LINE+7]]:5: error: cannot convert type `T` that implements `B` into type implementing `A` [ConversionFailureFacetToFacet]\n    // CHECK:STDERR:     C(()).F(T);\n    // CHECK:STDERR:     ^~~~~~~~~~\n    // CHECK:STDERR: fail_missing_interface.carbon:[[@LINE-12]]:3: note: while deducing parameters of generic declared here [DeductionGenericHere]\n    // CHECK:STDERR:   fn F(unused T:! A) {}\n    // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    C(()).F(T);\n  }\n}\n\n// --- fail_interface_wrong_generic_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(CC:! type) {\n  interface A {}\n  fn F(unused T:! A) {}\n}\n\nclass D(DD:! type) {\n  interface B {}\n  fn G(T:! B & C({}).A) {\n    // T implements C({}).A and D(DD).B, so should not convert to a facet value\n    // implementing C(()).A.\n    //\n    // CHECK:STDERR: fail_interface_wrong_generic_param.carbon:[[@LINE+7]]:5: error: cannot convert type `T` that implements `A & B` into type implementing `A` [ConversionFailureFacetToFacet]\n    // CHECK:STDERR:     C(()).F(T);\n    // CHECK:STDERR:     ^~~~~~~~~~\n    // CHECK:STDERR: fail_interface_wrong_generic_param.carbon:[[@LINE-12]]:3: note: while deducing parameters of generic declared here [DeductionGenericHere]\n    // CHECK:STDERR:   fn F(unused T:! A) {}\n    // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    C(()).F(T);\n  }\n}\n\n// --- compatible_deduce.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(CC:! type) {\n  interface A {}\n  fn F(unused T:! A) {}\n}\n\nclass D(DD:! type) {\n  interface B {}\n  fn G(T:! B & C(()).A) {\n    C(()).F(T);\n  }\n}\n"
  },
  {
    "path": "toolchain/check/testdata/deduce/tuple.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/tuple.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/tuple.carbon\n\n// --- tuple_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nclass D {}\n\nfn F[T:! type, U:! type](pair: (T, U)) -> U { return F(pair); }\n\nfn G(pair: (C, D)) -> D {\n  return F(pair);\n}\n\n// --- tuple_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass HasPair(Pair:! (i32, i32)) {}\n\nfn F[A:! i32, B:! i32](unused h: HasPair((A, B))) -> i32 { return B; }\n\nfn G(h: HasPair((1, 2))) -> i32 {\n  return F(h);\n}\n\n// --- fail_inconsistent.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nclass D {}\n\nfn F[T:! type](pair: (T, T)) -> T;\n\nfn G(pair: (C, D)) -> D {\n  // CHECK:STDERR: fail_inconsistent.carbon:[[@LINE+7]]:10: error: inconsistent deductions for value of generic parameter `T` [DeductionInconsistent]\n  // CHECK:STDERR:   return F(pair);\n  // CHECK:STDERR:          ^~~~~~~\n  // CHECK:STDERR: fail_inconsistent.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn F[T:! type](pair: (T, T)) -> T;\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return F(pair);\n}\n\n// CHECK:STDOUT: --- tuple_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.4b9: %tuple.type.24b = tuple_value (%T, %U) [symbolic]\n// CHECK:STDOUT:   %tuple.type.a5e: type = tuple_type (%T, %U) [symbolic]\n// CHECK:STDOUT:   %pattern_type.eee: type = pattern_type %tuple.type.a5e [symbolic]\n// CHECK:STDOUT:   %.822: Core.Form = init_form %U [symbolic]\n// CHECK:STDOUT:   %pattern_type.946: type = pattern_type %U [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %tuple.type.a5e [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.a54: <specific function> = specific_function %F, @F(%T, %U) [symbolic]\n// CHECK:STDOUT:   %tuple.a0a: %tuple.type.24b = tuple_value (%C, %D) [concrete]\n// CHECK:STDOUT:   %tuple.type.281: type = tuple_type (%C, %D) [concrete]\n// CHECK:STDOUT:   %pattern_type.881: type = pattern_type %tuple.type.281 [concrete]\n// CHECK:STDOUT:   %.9a5: Core.Form = init_form %D [concrete]\n// CHECK:STDOUT:   %pattern_type.9c8: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.107: <specific function> = specific_function %F, @F(%C, %D) [concrete]\n// CHECK:STDOUT:   %complete_type.734: <witness> = complete_type_witness %tuple.type.281 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %pair.patt: @F.%pattern_type.loc7_26 (%pattern_type.eee) = value_binding_pattern pair [concrete]\n// CHECK:STDOUT:     %pair.param_patt: @F.%pattern_type.loc7_26 (%pattern_type.eee) = value_param_pattern %pair.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc7_40 (%pattern_type.946) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc7_40 (%pattern_type.946) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %U.ref.loc7_43: type = name_ref U, %U.loc7_16.2 [symbolic = %U.loc7_16.1 (constants.%U)]\n// CHECK:STDOUT:     %.loc7_43.3: Core.Form = init_form %U.ref.loc7_43 [symbolic = %.loc7_43.2 (constants.%.822)]\n// CHECK:STDOUT:     %.loc7_10.1: type = splice_block %.loc7_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc7_20.1: type = splice_block %.loc7_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc7_16.2: type = symbolic_binding U, 1 [symbolic = %U.loc7_16.1 (constants.%U)]\n// CHECK:STDOUT:     %pair.param: @F.%tuple.type (%tuple.type.a5e) = value_param call_param0\n// CHECK:STDOUT:     %.loc7_37.1: type = splice_block %.loc7_37.3 [symbolic = %tuple.type (constants.%tuple.type.a5e)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc7_6.2 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:       %U.ref.loc7_36: type = name_ref U, %U.loc7_16.2 [symbolic = %U.loc7_16.1 (constants.%U)]\n// CHECK:STDOUT:       %.loc7_37.2: %tuple.type.24b = tuple_literal (%T.ref, %U.ref.loc7_36) [symbolic = %tuple (constants.%tuple.4b9)]\n// CHECK:STDOUT:       %.loc7_37.3: type = converted %.loc7_37.2, constants.%tuple.type.a5e [symbolic = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %pair: @F.%tuple.type (%tuple.type.a5e) = value_binding pair, %pair.param\n// CHECK:STDOUT:     %return.param: ref @F.%U.loc7_16.1 (%U) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%U.loc7_16.1 (%U) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %pair.patt: %pattern_type.881 = value_binding_pattern pair [concrete]\n// CHECK:STDOUT:     %pair.param_patt: %pattern_type.881 = value_param_pattern %pair.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.9c8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.9c8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref.loc9_23: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %.loc9_23.2: Core.Form = init_form %D.ref.loc9_23 [concrete = constants.%.9a5]\n// CHECK:STDOUT:     %pair.param: %tuple.type.281 = value_param call_param0\n// CHECK:STDOUT:     %.loc9_17.1: type = splice_block %.loc9_17.3 [concrete = constants.%tuple.type.281] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %D.ref.loc9_16: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:       %.loc9_17.2: %tuple.type.24b = tuple_literal (%C.ref, %D.ref.loc9_16) [concrete = constants.%tuple.a0a]\n// CHECK:STDOUT:       %.loc9_17.3: type = converted %.loc9_17.2, constants.%tuple.type.281 [concrete = constants.%tuple.type.281]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %pair: %tuple.type.281 = value_binding pair, %pair.param\n// CHECK:STDOUT:     %return.param: ref %D = out_param call_param1\n// CHECK:STDOUT:     %return: ref %D = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc7_6.2: type, %U.loc7_16.2: type) {\n// CHECK:STDOUT:   %T.loc7_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:   %U.loc7_16.1: type = symbolic_binding U, 1 [symbolic = %U.loc7_16.1 (constants.%U)]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%T.loc7_6.1, %U.loc7_16.1) [symbolic = %tuple (constants.%tuple.4b9)]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%T.loc7_6.1, %U.loc7_16.1) [symbolic = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:   %pattern_type.loc7_26: type = pattern_type %tuple.type [symbolic = %pattern_type.loc7_26 (constants.%pattern_type.eee)]\n// CHECK:STDOUT:   %.loc7_43.2: Core.Form = init_form %U.loc7_16.1 [symbolic = %.loc7_43.2 (constants.%.822)]\n// CHECK:STDOUT:   %pattern_type.loc7_40: type = pattern_type %U.loc7_16.1 [symbolic = %pattern_type.loc7_40 (constants.%pattern_type.946)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %tuple.type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %F.specific_fn.loc7_54.2: <specific function> = specific_function constants.%F, @F(%T.loc7_6.1, %U.loc7_16.1) [symbolic = %F.specific_fn.loc7_54.2 (constants.%F.specific_fn.a54)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%pair.param: @F.%tuple.type (%tuple.type.a5e)) -> out %return.param: @F.%U.loc7_16.1 (%U) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %pair.ref: @F.%tuple.type (%tuple.type.a5e) = name_ref pair, %pair\n// CHECK:STDOUT:     %F.specific_fn.loc7_54.1: <specific function> = specific_function %F.ref, @F(constants.%T, constants.%U) [symbolic = %F.specific_fn.loc7_54.2 (constants.%F.specific_fn.a54)]\n// CHECK:STDOUT:     %.loc7_43.1: ref @F.%U.loc7_16.1 (%U) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%U.loc7_16.1 (%U) to %.loc7_43.1 = call %F.specific_fn.loc7_54.1(%pair.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%pair.param: %tuple.type.281) -> out %return.param: %D {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %pair.ref: %tuple.type.281 = name_ref pair, %pair\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C, constants.%D) [concrete = constants.%F.specific_fn.107]\n// CHECK:STDOUT:   %.loc9_23.1: ref %D = splice_block %return.param {}\n// CHECK:STDOUT:   %F.call: init %D to %.loc9_23.1 = call %F.specific_fn(%pair.ref)\n// CHECK:STDOUT:   return %F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc7_6.1 => constants.%T\n// CHECK:STDOUT:   %U.loc7_16.1 => constants.%U\n// CHECK:STDOUT:   %tuple => constants.%tuple.4b9\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.a5e\n// CHECK:STDOUT:   %pattern_type.loc7_26 => constants.%pattern_type.eee\n// CHECK:STDOUT:   %.loc7_43.2 => constants.%.822\n// CHECK:STDOUT:   %pattern_type.loc7_40 => constants.%pattern_type.946\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %F.specific_fn.loc7_54.2 => constants.%F.specific_fn.a54\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C, constants.%D) {\n// CHECK:STDOUT:   %T.loc7_6.1 => constants.%C\n// CHECK:STDOUT:   %U.loc7_16.1 => constants.%D\n// CHECK:STDOUT:   %tuple => constants.%tuple.a0a\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.281\n// CHECK:STDOUT:   %pattern_type.loc7_26 => constants.%pattern_type.881\n// CHECK:STDOUT:   %.loc7_43.2 => constants.%.9a5\n// CHECK:STDOUT:   %pattern_type.loc7_40 => constants.%pattern_type.9c8\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.734\n// CHECK:STDOUT:   %F.specific_fn.loc7_54.2 => constants.%F.specific_fn.107\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- tuple_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.95a: %tuple.type.24b = tuple_value (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.511: type = pattern_type %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %Pair: %tuple.type.d07 = symbolic_binding Pair, 0 [symbolic]\n// CHECK:STDOUT:   %HasPair.type: type = generic_class_type @HasPair [concrete]\n// CHECK:STDOUT:   %HasPair.generic: %HasPair.type = struct_value () [concrete]\n// CHECK:STDOUT:   %HasPair.7cc: type = class_type @HasPair, @HasPair(%Pair) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %A: %i32 = symbolic_binding A, 0 [symbolic]\n// CHECK:STDOUT:   %B: %i32 = symbolic_binding B, 1 [symbolic]\n// CHECK:STDOUT:   %tuple.9c9: %tuple.type.d07 = tuple_value (%A, %B) [symbolic]\n// CHECK:STDOUT:   %HasPair.2e7: type = class_type @HasPair, @HasPair(%tuple.9c9) [symbolic]\n// CHECK:STDOUT:   %pattern_type.dc2: type = pattern_type %HasPair.2e7 [symbolic]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.76f: <witness> = require_complete_type %HasPair.2e7 [symbolic]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound.5f8: <bound method> = bound_method %B, %Int.as.Copy.impl.Op.664 [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.dfb: <bound method> = bound_method %B, %Int.as.Copy.impl.Op.specific_fn [symbolic]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.type.f94: type = tuple_type (Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.ad8: %tuple.type.f94 = tuple_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.21c: %tuple.type.d07 = tuple_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %HasPair.867: type = class_type @HasPair, @HasPair(%tuple.21c) [concrete]\n// CHECK:STDOUT:   %pattern_type.530: type = pattern_type %HasPair.867 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound.5e8: <bound method> = bound_method %int_2.ef8, %Int.as.Copy.impl.Op.664 [concrete]\n// CHECK:STDOUT:   %bound_method.f15: <bound method> = bound_method %int_2.ef8, %Int.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .HasPair = %HasPair.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %HasPair.decl: %HasPair.type = class_decl @HasPair [concrete = constants.%HasPair.generic] {\n// CHECK:STDOUT:     %Pair.patt: %pattern_type.511 = symbolic_binding_pattern Pair, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_31.1: type = splice_block %.loc4_31.3 [concrete = constants.%tuple.type.d07] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32.loc4_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %i32.loc4_28: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc4_31.2: %tuple.type.24b = tuple_literal (%i32.loc4_23, %i32.loc4_28) [concrete = constants.%tuple.95a]\n// CHECK:STDOUT:       %.loc4_31.3: type = converted %.loc4_31.2, constants.%tuple.type.d07 [concrete = constants.%tuple.type.d07]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Pair.loc4_15.2: %tuple.type.d07 = symbolic_binding Pair, 0 [symbolic = %Pair.loc4_15.1 (constants.%Pair)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %A.patt: %pattern_type.7ce = symbolic_binding_pattern A, 0 [concrete]\n// CHECK:STDOUT:     %B.patt: %pattern_type.7ce = symbolic_binding_pattern B, 1 [concrete]\n// CHECK:STDOUT:     %h.patt: @F.%pattern_type (%pattern_type.dc2) = value_binding_pattern h [concrete]\n// CHECK:STDOUT:     %h.param_patt: @F.%pattern_type (%pattern_type.dc2) = value_param_pattern %h.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6_54: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6_54: Core.Form = init_form %i32.loc6_54 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc6_10: type = splice_block %i32.loc6_10 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32.loc6_10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %A.loc6_6.2: %i32 = symbolic_binding A, 0 [symbolic = %A.loc6_6.1 (constants.%A)]\n// CHECK:STDOUT:     %.loc6_19: type = splice_block %i32.loc6_19 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32.loc6_19: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %B.loc6_15.2: %i32 = symbolic_binding B, 1 [symbolic = %B.loc6_15.1 (constants.%B)]\n// CHECK:STDOUT:     %h.param: @F.%HasPair.loc6_48.1 (%HasPair.2e7) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_48.1: type = splice_block %HasPair.loc6_48.2 [symbolic = %HasPair.loc6_48.1 (constants.%HasPair.2e7)] {\n// CHECK:STDOUT:       %HasPair.ref: %HasPair.type = name_ref HasPair, file.%HasPair.decl [concrete = constants.%HasPair.generic]\n// CHECK:STDOUT:       %A.ref: %i32 = name_ref A, %A.loc6_6.2 [symbolic = %A.loc6_6.1 (constants.%A)]\n// CHECK:STDOUT:       %B.ref.loc6_46: %i32 = name_ref B, %B.loc6_15.2 [symbolic = %B.loc6_15.1 (constants.%B)]\n// CHECK:STDOUT:       %.loc6_47: %tuple.type.d07 = tuple_literal (%A.ref, %B.ref.loc6_46) [symbolic = %tuple.loc6_47.1 (constants.%tuple.9c9)]\n// CHECK:STDOUT:       %tuple.loc6_47.2: %tuple.type.d07 = tuple_value (%A.ref, %B.ref.loc6_46) [symbolic = %tuple.loc6_47.1 (constants.%tuple.9c9)]\n// CHECK:STDOUT:       %.loc6_48.2: %tuple.type.d07 = converted %.loc6_47, %tuple.loc6_47.2 [symbolic = %tuple.loc6_47.1 (constants.%tuple.9c9)]\n// CHECK:STDOUT:       %HasPair.loc6_48.2: type = class_type @HasPair, @HasPair(constants.%tuple.9c9) [symbolic = %HasPair.loc6_48.1 (constants.%HasPair.2e7)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %h: @F.%HasPair.loc6_48.1 (%HasPair.2e7) = value_binding h, %h.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %h.patt: %pattern_type.530 = value_binding_pattern h [concrete]\n// CHECK:STDOUT:     %h.param_patt: %pattern_type.530 = value_param_pattern %h.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc8_29: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %h.param: %HasPair.867 = value_param call_param0\n// CHECK:STDOUT:     %.loc8_23.1: type = splice_block %HasPair [concrete = constants.%HasPair.867] {\n// CHECK:STDOUT:       %HasPair.ref: %HasPair.type = name_ref HasPair, file.%HasPair.decl [concrete = constants.%HasPair.generic]\n// CHECK:STDOUT:       %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:       %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:       %.loc8_22.1: %tuple.type.f94 = tuple_literal (%int_1, %int_2) [concrete = constants.%tuple.ad8]\n// CHECK:STDOUT:       %impl.elem0.loc8_22.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:       %bound_method.loc8_22.1: <bound method> = bound_method %int_1, %impl.elem0.loc8_22.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:       %specific_fn.loc8_22.1: <specific function> = specific_function %impl.elem0.loc8_22.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc8_22.2: <bound method> = bound_method %int_1, %specific_fn.loc8_22.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:       %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_22.1: init %i32 = call %bound_method.loc8_22.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:       %.loc8_22.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_22.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:       %.loc8_22.3: %i32 = converted %int_1, %.loc8_22.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:       %impl.elem0.loc8_22.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:       %bound_method.loc8_22.3: <bound method> = bound_method %int_2, %impl.elem0.loc8_22.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:       %specific_fn.loc8_22.2: <specific function> = specific_function %impl.elem0.loc8_22.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc8_22.4: <bound method> = bound_method %int_2, %specific_fn.loc8_22.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:       %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_22.2: init %i32 = call %bound_method.loc8_22.4(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:       %.loc8_22.4: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8_22.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:       %.loc8_22.5: %i32 = converted %int_2, %.loc8_22.4 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:       %tuple: %tuple.type.d07 = tuple_value (%.loc8_22.3, %.loc8_22.5) [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:       %.loc8_23.2: %tuple.type.d07 = converted %.loc8_22.1, %tuple [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:       %HasPair: type = class_type @HasPair, @HasPair(constants.%tuple.21c) [concrete = constants.%HasPair.867]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %h: %HasPair.867 = value_binding h, %h.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @HasPair(%Pair.loc4_15.2: %tuple.type.d07) {\n// CHECK:STDOUT:   %Pair.loc4_15.1: %tuple.type.d07 = symbolic_binding Pair, 0 [symbolic = %Pair.loc4_15.1 (constants.%Pair)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%HasPair.7cc\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%A.loc6_6.2: %i32, %B.loc6_15.2: %i32) {\n// CHECK:STDOUT:   %A.loc6_6.1: %i32 = symbolic_binding A, 0 [symbolic = %A.loc6_6.1 (constants.%A)]\n// CHECK:STDOUT:   %B.loc6_15.1: %i32 = symbolic_binding B, 1 [symbolic = %B.loc6_15.1 (constants.%B)]\n// CHECK:STDOUT:   %tuple.loc6_47.1: %tuple.type.d07 = tuple_value (%A.loc6_6.1, %B.loc6_15.1) [symbolic = %tuple.loc6_47.1 (constants.%tuple.9c9)]\n// CHECK:STDOUT:   %HasPair.loc6_48.1: type = class_type @HasPair, @HasPair(%tuple.loc6_47.1) [symbolic = %HasPair.loc6_48.1 (constants.%HasPair.2e7)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %HasPair.loc6_48.1 [symbolic = %pattern_type (constants.%pattern_type.dc2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %HasPair.loc6_48.1 [symbolic = %require_complete (constants.%require_complete.76f)]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound: <bound method> = bound_method %B.loc6_15.1, constants.%Int.as.Copy.impl.Op.664 [symbolic = %Int.as.Copy.impl.Op.bound (constants.%Int.as.Copy.impl.Op.bound.5f8)]\n// CHECK:STDOUT:   %bound_method.loc6_67.3: <bound method> = bound_method %B.loc6_15.1, constants.%Int.as.Copy.impl.Op.specific_fn [symbolic = %bound_method.loc6_67.3 (constants.%bound_method.dfb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%h.param: @F.%HasPair.loc6_48.1 (%HasPair.2e7)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %B.ref.loc6_67: %i32 = name_ref B, %B.loc6_15.2 [symbolic = %B.loc6_15.1 (constants.%B)]\n// CHECK:STDOUT:     %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:     %bound_method.loc6_67.1: <bound method> = bound_method %B.ref.loc6_67, %impl.elem0 [symbolic = %Int.as.Copy.impl.Op.bound (constants.%Int.as.Copy.impl.Op.bound.5f8)]\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_67.2: <bound method> = bound_method %B.ref.loc6_67, %specific_fn [symbolic = %bound_method.loc6_67.3 (constants.%bound_method.dfb)]\n// CHECK:STDOUT:     %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_67.2(%B.ref.loc6_67) [symbolic = %B.loc6_15.1 (constants.%B)]\n// CHECK:STDOUT:     return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%h.param: %HasPair.867) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %h.ref: %HasPair.867 = name_ref h, %h\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%int_1.5d2, constants.%int_2.ef8) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%h.ref)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasPair(constants.%Pair) {\n// CHECK:STDOUT:   %Pair.loc4_15.1 => constants.%Pair\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasPair(constants.%tuple.9c9) {\n// CHECK:STDOUT:   %Pair.loc4_15.1 => constants.%tuple.9c9\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%A, constants.%B) {\n// CHECK:STDOUT:   %A.loc6_6.1 => constants.%A\n// CHECK:STDOUT:   %B.loc6_15.1 => constants.%B\n// CHECK:STDOUT:   %tuple.loc6_47.1 => constants.%tuple.9c9\n// CHECK:STDOUT:   %HasPair.loc6_48.1 => constants.%HasPair.2e7\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.dc2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasPair(constants.%tuple.21c) {\n// CHECK:STDOUT:   %Pair.loc4_15.1 => constants.%tuple.21c\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%int_1.5d2, constants.%int_2.ef8) {\n// CHECK:STDOUT:   %A.loc6_6.1 => constants.%int_1.5d2\n// CHECK:STDOUT:   %B.loc6_15.1 => constants.%int_2.ef8\n// CHECK:STDOUT:   %tuple.loc6_47.1 => constants.%tuple.21c\n// CHECK:STDOUT:   %HasPair.loc6_48.1 => constants.%HasPair.867\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.530\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.357\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound => constants.%Int.as.Copy.impl.Op.bound.5e8\n// CHECK:STDOUT:   %bound_method.loc6_67.3 => constants.%bound_method.f15\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_inconsistent.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.11e: %tuple.type.24b = tuple_value (%T, %T) [symbolic]\n// CHECK:STDOUT:   %tuple.type.07a: type = tuple_type (%T, %T) [symbolic]\n// CHECK:STDOUT:   %pattern_type.c3f: type = pattern_type %tuple.type.07a [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.a0a: %tuple.type.24b = tuple_value (%C, %D) [concrete]\n// CHECK:STDOUT:   %tuple.type.281: type = tuple_type (%C, %D) [concrete]\n// CHECK:STDOUT:   %pattern_type.881: type = pattern_type %tuple.type.281 [concrete]\n// CHECK:STDOUT:   %.9a5: Core.Form = init_form %D [concrete]\n// CHECK:STDOUT:   %pattern_type.9c8: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %pair.patt: @F.%pattern_type.loc7_16 (%pattern_type.c3f) = value_binding_pattern pair [concrete]\n// CHECK:STDOUT:     %pair.param_patt: @F.%pattern_type.loc7_16 (%pattern_type.c3f) = value_param_pattern %pair.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc7_30 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc7_30 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc7_33: type = name_ref T, %T.loc7_6.2 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc7_33.2: Core.Form = init_form %T.ref.loc7_33 [symbolic = %.loc7_33.1 (constants.%.184)]\n// CHECK:STDOUT:     %.loc7_10.1: type = splice_block %.loc7_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:     %pair.param: @F.%tuple.type (%tuple.type.07a) = value_param call_param0\n// CHECK:STDOUT:     %.loc7_27.1: type = splice_block %.loc7_27.3 [symbolic = %tuple.type (constants.%tuple.type.07a)] {\n// CHECK:STDOUT:       %T.ref.loc7_23: type = name_ref T, %T.loc7_6.2 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:       %T.ref.loc7_26: type = name_ref T, %T.loc7_6.2 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:       %.loc7_27.2: %tuple.type.24b = tuple_literal (%T.ref.loc7_23, %T.ref.loc7_26) [symbolic = %tuple (constants.%tuple.11e)]\n// CHECK:STDOUT:       %.loc7_27.3: type = converted %.loc7_27.2, constants.%tuple.type.07a [symbolic = %tuple.type (constants.%tuple.type.07a)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %pair: @F.%tuple.type (%tuple.type.07a) = value_binding pair, %pair.param\n// CHECK:STDOUT:     %return.param: ref @F.%T.loc7_6.1 (%T) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%T.loc7_6.1 (%T) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %pair.patt: %pattern_type.881 = value_binding_pattern pair [concrete]\n// CHECK:STDOUT:     %pair.param_patt: %pattern_type.881 = value_param_pattern %pair.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.9c8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.9c8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref.loc9_23: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %.loc9_23: Core.Form = init_form %D.ref.loc9_23 [concrete = constants.%.9a5]\n// CHECK:STDOUT:     %pair.param: %tuple.type.281 = value_param call_param0\n// CHECK:STDOUT:     %.loc9_17.1: type = splice_block %.loc9_17.3 [concrete = constants.%tuple.type.281] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %D.ref.loc9_16: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:       %.loc9_17.2: %tuple.type.24b = tuple_literal (%C.ref, %D.ref.loc9_16) [concrete = constants.%tuple.a0a]\n// CHECK:STDOUT:       %.loc9_17.3: type = converted %.loc9_17.2, constants.%tuple.type.281 [concrete = constants.%tuple.type.281]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %pair: %tuple.type.281 = value_binding pair, %pair.param\n// CHECK:STDOUT:     %return.param: ref %D = out_param call_param1\n// CHECK:STDOUT:     %return: ref %D = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc7_6.2: type) {\n// CHECK:STDOUT:   %T.loc7_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T)]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%T.loc7_6.1, %T.loc7_6.1) [symbolic = %tuple (constants.%tuple.11e)]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%T.loc7_6.1, %T.loc7_6.1) [symbolic = %tuple.type (constants.%tuple.type.07a)]\n// CHECK:STDOUT:   %pattern_type.loc7_16: type = pattern_type %tuple.type [symbolic = %pattern_type.loc7_16 (constants.%pattern_type.c3f)]\n// CHECK:STDOUT:   %.loc7_33.1: Core.Form = init_form %T.loc7_6.1 [symbolic = %.loc7_33.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc7_30: type = pattern_type %T.loc7_6.1 [symbolic = %pattern_type.loc7_30 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%pair.param: @F.%tuple.type (%tuple.type.07a)) -> out %return.param: @F.%T.loc7_6.1 (%T);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%pair.param: %tuple.type.281) -> out %return.param: %D {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %pair.ref: %tuple.type.281 = name_ref pair, %pair\n// CHECK:STDOUT:   return <error> to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_6.1 => constants.%T\n// CHECK:STDOUT:   %tuple => constants.%tuple.11e\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.07a\n// CHECK:STDOUT:   %pattern_type.loc7_16 => constants.%pattern_type.c3f\n// CHECK:STDOUT:   %.loc7_33.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc7_30 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/deduce/type_operator.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/type_operator.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/type_operator.carbon\n\n// --- pointer.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[T:! type](p: T*) -> T { return F(p); }\n\nfn G(p: C*) -> C {\n  return F(p);\n}\n\n// --- const.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[T:! type](p: const T*) -> T { return F(p); }\n\nfn G(p: const C*) -> C {\n  return F(p);\n}\n\n// --- nonconst_from_const.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[T:! type](p: T*) -> T { return F(p); }\n\nfn G(p: const C*) -> const C {\n  return F(p);\n}\n\n// --- fail_const_from_nonconst.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn F[T:! type](p: const T*) -> T { return F(p); }\n\nfn G(p: C*) -> const C {\n  // CHECK:STDERR: fail_const_from_nonconst.carbon:[[@LINE+7]]:10: error: cannot deduce value for generic parameter `T` [DeductionIncomplete]\n  // CHECK:STDERR:   return F(p);\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR: fail_const_from_nonconst.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn F[T:! type](p: const T*) -> T { return F(p); }\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return F(p);\n}\n\n// CHECK:STDOUT: --- pointer.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.643: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.540: <specific function> = specific_function %F, @F(%C) [concrete]\n// CHECK:STDOUT:   %complete_type.17a: <witness> = complete_type_witness %ptr.31e [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %p.patt: @F.%pattern_type.loc6_16 (%pattern_type.4f4) = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: @F.%pattern_type.loc6_16 (%pattern_type.4f4) = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc6_23 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc6_23 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc6_26: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc6_26.3: Core.Form = init_form %T.ref.loc6_26 [symbolic = %.loc6_26.2 (constants.%.184)]\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %p.param: @F.%ptr.loc6_20.1 (%ptr.e8f) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_20: type = splice_block %ptr.loc6_20.2 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)] {\n// CHECK:STDOUT:       %T.ref.loc6_19: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:       %ptr.loc6_20.2: type = ptr_type %T.ref.loc6_19 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: @F.%ptr.loc6_20.1 (%ptr.e8f) = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref @F.%T.loc6_6.1 (%T) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%T.loc6_6.1 (%T) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.506 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.506 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc8_16: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc8_16.2: Core.Form = init_form %C.ref.loc8_16 [concrete = constants.%.a69]\n// CHECK:STDOUT:     %p.param: %ptr.31e = value_param call_param0\n// CHECK:STDOUT:     %.loc8_10: type = splice_block %ptr [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:       %C.ref.loc8_9: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %ptr: type = ptr_type %C.ref.loc8_9 [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.31e = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param1\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_6.2: type) {\n// CHECK:STDOUT:   %T.loc6_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc6_20.1: type = ptr_type %T.loc6_6.1 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %pattern_type.loc6_16: type = pattern_type %ptr.loc6_20.1 [symbolic = %pattern_type.loc6_16 (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:   %.loc6_26.2: Core.Form = init_form %T.loc6_6.1 [symbolic = %.loc6_26.2 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc6_23: type = pattern_type %T.loc6_6.1 [symbolic = %pattern_type.loc6_23 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %ptr.loc6_20.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.ef1)]\n// CHECK:STDOUT:   %require_complete.loc6_26: <witness> = require_complete_type %T.loc6_6.1 [symbolic = %require_complete.loc6_26 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %F.specific_fn.loc6_37.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_37.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_20.1 (%ptr.e8f)) -> out %return.param: @F.%T.loc6_6.1 (%T) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %p.ref: @F.%ptr.loc6_20.1 (%ptr.e8f) = name_ref p, %p\n// CHECK:STDOUT:     %F.specific_fn.loc6_37.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_37.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:     %.loc6_26.1: ref @F.%T.loc6_6.1 (%T) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) to %.loc6_26.1 = call %F.specific_fn.loc6_37.1(%p.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %ptr.31e) -> out %return.param: %C {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %p.ref: %ptr.31e = name_ref p, %p\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.540]\n// CHECK:STDOUT:   %.loc8_16.1: ref %C = splice_block %return.param {}\n// CHECK:STDOUT:   %F.call: init %C to %.loc8_16.1 = call %F.specific_fn(%p.ref)\n// CHECK:STDOUT:   return %F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%T\n// CHECK:STDOUT:   %ptr.loc6_20.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.4f4\n// CHECK:STDOUT:   %.loc6_26.2 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc6_23 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17 => constants.%require_complete.ef1\n// CHECK:STDOUT:   %require_complete.loc6_26 => constants.%require_complete.944\n// CHECK:STDOUT:   %F.specific_fn.loc6_37.2 => constants.%F.specific_fn.643\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%C\n// CHECK:STDOUT:   %ptr.loc6_20.1 => constants.%ptr.31e\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.506\n// CHECK:STDOUT:   %.loc6_26.2 => constants.%.a69\n// CHECK:STDOUT:   %pattern_type.loc6_23 => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17 => constants.%complete_type.17a\n// CHECK:STDOUT:   %require_complete.loc6_26 => constants.%complete_type.357\n// CHECK:STDOUT:   %F.specific_fn.loc6_37.2 => constants.%F.specific_fn.540\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %const.4ff: type = const_type %T [symbolic]\n// CHECK:STDOUT:   %ptr.a15: type = ptr_type %const.4ff [symbolic]\n// CHECK:STDOUT:   %pattern_type.26f: type = pattern_type %ptr.a15 [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.0c1: <witness> = require_complete_type %ptr.a15 [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.643: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT:   %const.0e5: type = const_type %C [concrete]\n// CHECK:STDOUT:   %ptr.c45: type = ptr_type %const.0e5 [concrete]\n// CHECK:STDOUT:   %pattern_type.6eb: type = pattern_type %ptr.c45 [concrete]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.540: <specific function> = specific_function %F, @F(%C) [concrete]\n// CHECK:STDOUT:   %complete_type.e6f: <witness> = complete_type_witness %ptr.c45 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %p.patt: @F.%pattern_type.loc6_16 (%pattern_type.26f) = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: @F.%pattern_type.loc6_16 (%pattern_type.26f) = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc6_29 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc6_29 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc6_32: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc6_32.3: Core.Form = init_form %T.ref.loc6_32 [symbolic = %.loc6_32.2 (constants.%.184)]\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %p.param: @F.%ptr.loc6_26.1 (%ptr.a15) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_26: type = splice_block %ptr.loc6_26.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.a15)] {\n// CHECK:STDOUT:       %T.ref.loc6_25: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:       %const.loc6_19.2: type = const_type %T.ref.loc6_25 [symbolic = %const.loc6_19.1 (constants.%const.4ff)]\n// CHECK:STDOUT:       %ptr.loc6_26.2: type = ptr_type %const.loc6_19.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.a15)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: @F.%ptr.loc6_26.1 (%ptr.a15) = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref @F.%T.loc6_6.1 (%T) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%T.loc6_6.1 (%T) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.6eb = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.6eb = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc8_22: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc8_22.2: Core.Form = init_form %C.ref.loc8_22 [concrete = constants.%.a69]\n// CHECK:STDOUT:     %p.param: %ptr.c45 = value_param call_param0\n// CHECK:STDOUT:     %.loc8_16: type = splice_block %ptr [concrete = constants.%ptr.c45] {\n// CHECK:STDOUT:       %C.ref.loc8_15: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %const: type = const_type %C.ref.loc8_15 [concrete = constants.%const.0e5]\n// CHECK:STDOUT:       %ptr: type = ptr_type %const [concrete = constants.%ptr.c45]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.c45 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param1\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_6.2: type) {\n// CHECK:STDOUT:   %T.loc6_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:   %const.loc6_19.1: type = const_type %T.loc6_6.1 [symbolic = %const.loc6_19.1 (constants.%const.4ff)]\n// CHECK:STDOUT:   %ptr.loc6_26.1: type = ptr_type %const.loc6_19.1 [symbolic = %ptr.loc6_26.1 (constants.%ptr.a15)]\n// CHECK:STDOUT:   %pattern_type.loc6_16: type = pattern_type %ptr.loc6_26.1 [symbolic = %pattern_type.loc6_16 (constants.%pattern_type.26f)]\n// CHECK:STDOUT:   %.loc6_32.2: Core.Form = init_form %T.loc6_6.1 [symbolic = %.loc6_32.2 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc6_29: type = pattern_type %T.loc6_6.1 [symbolic = %pattern_type.loc6_29 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %ptr.loc6_26.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.0c1)]\n// CHECK:STDOUT:   %require_complete.loc6_32: <witness> = require_complete_type %T.loc6_6.1 [symbolic = %require_complete.loc6_32 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %F.specific_fn.loc6_43.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_43.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_26.1 (%ptr.a15)) -> out %return.param: @F.%T.loc6_6.1 (%T) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %p.ref: @F.%ptr.loc6_26.1 (%ptr.a15) = name_ref p, %p\n// CHECK:STDOUT:     %F.specific_fn.loc6_43.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_43.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:     %.loc6_32.1: ref @F.%T.loc6_6.1 (%T) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) to %.loc6_32.1 = call %F.specific_fn.loc6_43.1(%p.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %ptr.c45) -> out %return.param: %C {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %p.ref: %ptr.c45 = name_ref p, %p\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.540]\n// CHECK:STDOUT:   %.loc8_22.1: ref %C = splice_block %return.param {}\n// CHECK:STDOUT:   %F.call: init %C to %.loc8_22.1 = call %F.specific_fn(%p.ref)\n// CHECK:STDOUT:   return %F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%T\n// CHECK:STDOUT:   %const.loc6_19.1 => constants.%const.4ff\n// CHECK:STDOUT:   %ptr.loc6_26.1 => constants.%ptr.a15\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.26f\n// CHECK:STDOUT:   %.loc6_32.2 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc6_29 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17 => constants.%require_complete.0c1\n// CHECK:STDOUT:   %require_complete.loc6_32 => constants.%require_complete.944\n// CHECK:STDOUT:   %F.specific_fn.loc6_43.2 => constants.%F.specific_fn.643\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%C\n// CHECK:STDOUT:   %const.loc6_19.1 => constants.%const.0e5\n// CHECK:STDOUT:   %ptr.loc6_26.1 => constants.%ptr.c45\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.6eb\n// CHECK:STDOUT:   %.loc6_32.2 => constants.%.a69\n// CHECK:STDOUT:   %pattern_type.loc6_29 => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17 => constants.%complete_type.e6f\n// CHECK:STDOUT:   %require_complete.loc6_32 => constants.%complete_type.357\n// CHECK:STDOUT:   %F.specific_fn.loc6_43.2 => constants.%F.specific_fn.540\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- nonconst_from_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.643: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT:   %const: type = const_type %C [concrete]\n// CHECK:STDOUT:   %ptr.c45: type = ptr_type %const [concrete]\n// CHECK:STDOUT:   %pattern_type.6eb: type = pattern_type %ptr.c45 [concrete]\n// CHECK:STDOUT:   %.007: Core.Form = init_form %const [concrete]\n// CHECK:STDOUT:   %pattern_type.03b: type = pattern_type %const [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.98a: <specific function> = specific_function %F, @F(%const) [concrete]\n// CHECK:STDOUT:   %complete_type.e6f: <witness> = complete_type_witness %ptr.c45 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %p.patt: @F.%pattern_type.loc6_16 (%pattern_type.4f4) = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: @F.%pattern_type.loc6_16 (%pattern_type.4f4) = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc6_23 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc6_23 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc6_26: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc6_26.3: Core.Form = init_form %T.ref.loc6_26 [symbolic = %.loc6_26.2 (constants.%.184)]\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %p.param: @F.%ptr.loc6_20.1 (%ptr.e8f) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_20: type = splice_block %ptr.loc6_20.2 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)] {\n// CHECK:STDOUT:       %T.ref.loc6_19: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:       %ptr.loc6_20.2: type = ptr_type %T.ref.loc6_19 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: @F.%ptr.loc6_20.1 (%ptr.e8f) = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref @F.%T.loc6_6.1 (%T) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%T.loc6_6.1 (%T) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.6eb = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.6eb = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.03b = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.03b = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc8_28: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %const.loc8_22: type = const_type %C.ref.loc8_28 [concrete = constants.%const]\n// CHECK:STDOUT:     %.loc8_22.2: Core.Form = init_form %const.loc8_22 [concrete = constants.%.007]\n// CHECK:STDOUT:     %p.param: %ptr.c45 = value_param call_param0\n// CHECK:STDOUT:     %.loc8_16: type = splice_block %ptr [concrete = constants.%ptr.c45] {\n// CHECK:STDOUT:       %C.ref.loc8_15: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %const.loc8_9: type = const_type %C.ref.loc8_15 [concrete = constants.%const]\n// CHECK:STDOUT:       %ptr: type = ptr_type %const.loc8_9 [concrete = constants.%ptr.c45]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.c45 = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %const = out_param call_param1\n// CHECK:STDOUT:     %return: ref %const = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_6.2: type) {\n// CHECK:STDOUT:   %T.loc6_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc6_20.1: type = ptr_type %T.loc6_6.1 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %pattern_type.loc6_16: type = pattern_type %ptr.loc6_20.1 [symbolic = %pattern_type.loc6_16 (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:   %.loc6_26.2: Core.Form = init_form %T.loc6_6.1 [symbolic = %.loc6_26.2 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc6_23: type = pattern_type %T.loc6_6.1 [symbolic = %pattern_type.loc6_23 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %ptr.loc6_20.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.ef1)]\n// CHECK:STDOUT:   %require_complete.loc6_26: <witness> = require_complete_type %T.loc6_6.1 [symbolic = %require_complete.loc6_26 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %F.specific_fn.loc6_37.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_37.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_20.1 (%ptr.e8f)) -> out %return.param: @F.%T.loc6_6.1 (%T) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %p.ref: @F.%ptr.loc6_20.1 (%ptr.e8f) = name_ref p, %p\n// CHECK:STDOUT:     %F.specific_fn.loc6_37.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_37.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:     %.loc6_26.1: ref @F.%T.loc6_6.1 (%T) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) to %.loc6_26.1 = call %F.specific_fn.loc6_37.1(%p.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %ptr.c45) -> out %return.param: %const {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %p.ref: %ptr.c45 = name_ref p, %p\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%const) [concrete = constants.%F.specific_fn.98a]\n// CHECK:STDOUT:   %.loc8_22.1: ref %const = splice_block %return.param {}\n// CHECK:STDOUT:   %F.call: init %const to %.loc8_22.1 = call %F.specific_fn(%p.ref)\n// CHECK:STDOUT:   return %F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%T\n// CHECK:STDOUT:   %ptr.loc6_20.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.4f4\n// CHECK:STDOUT:   %.loc6_26.2 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc6_23 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17 => constants.%require_complete.ef1\n// CHECK:STDOUT:   %require_complete.loc6_26 => constants.%require_complete.944\n// CHECK:STDOUT:   %F.specific_fn.loc6_37.2 => constants.%F.specific_fn.643\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%const) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%const\n// CHECK:STDOUT:   %ptr.loc6_20.1 => constants.%ptr.c45\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.6eb\n// CHECK:STDOUT:   %.loc6_26.2 => constants.%.007\n// CHECK:STDOUT:   %pattern_type.loc6_23 => constants.%pattern_type.03b\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17 => constants.%complete_type.e6f\n// CHECK:STDOUT:   %require_complete.loc6_26 => constants.%complete_type.357\n// CHECK:STDOUT:   %F.specific_fn.loc6_37.2 => constants.%F.specific_fn.98a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_const_from_nonconst.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %const.4ff: type = const_type %T [symbolic]\n// CHECK:STDOUT:   %ptr.a15: type = ptr_type %const.4ff [symbolic]\n// CHECK:STDOUT:   %pattern_type.26f: type = pattern_type %ptr.a15 [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.0c1: <witness> = require_complete_type %ptr.a15 [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %const.0e5: type = const_type %C [concrete]\n// CHECK:STDOUT:   %.007: Core.Form = init_form %const.0e5 [concrete]\n// CHECK:STDOUT:   %pattern_type.03b: type = pattern_type %const.0e5 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %p.patt: @F.%pattern_type.loc6_16 (%pattern_type.26f) = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: @F.%pattern_type.loc6_16 (%pattern_type.26f) = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc6_29 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc6_29 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc6_32: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc6_32.3: Core.Form = init_form %T.ref.loc6_32 [symbolic = %.loc6_32.2 (constants.%.184)]\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %p.param: @F.%ptr.loc6_26.1 (%ptr.a15) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_26: type = splice_block %ptr.loc6_26.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.a15)] {\n// CHECK:STDOUT:       %T.ref.loc6_25: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:       %const.loc6_19.2: type = const_type %T.ref.loc6_25 [symbolic = %const.loc6_19.1 (constants.%const.4ff)]\n// CHECK:STDOUT:       %ptr.loc6_26.2: type = ptr_type %const.loc6_19.2 [symbolic = %ptr.loc6_26.1 (constants.%ptr.a15)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: @F.%ptr.loc6_26.1 (%ptr.a15) = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref @F.%T.loc6_6.1 (%T) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%T.loc6_6.1 (%T) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.506 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.506 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.03b = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.03b = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc8_22: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %const: type = const_type %C.ref.loc8_22 [concrete = constants.%const.0e5]\n// CHECK:STDOUT:     %.loc8_16: Core.Form = init_form %const [concrete = constants.%.007]\n// CHECK:STDOUT:     %p.param: %ptr.31e = value_param call_param0\n// CHECK:STDOUT:     %.loc8_10: type = splice_block %ptr [concrete = constants.%ptr.31e] {\n// CHECK:STDOUT:       %C.ref.loc8_9: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %ptr: type = ptr_type %C.ref.loc8_9 [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.31e = value_binding p, %p.param\n// CHECK:STDOUT:     %return.param: ref %const.0e5 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %const.0e5 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_6.2: type) {\n// CHECK:STDOUT:   %T.loc6_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:   %const.loc6_19.1: type = const_type %T.loc6_6.1 [symbolic = %const.loc6_19.1 (constants.%const.4ff)]\n// CHECK:STDOUT:   %ptr.loc6_26.1: type = ptr_type %const.loc6_19.1 [symbolic = %ptr.loc6_26.1 (constants.%ptr.a15)]\n// CHECK:STDOUT:   %pattern_type.loc6_16: type = pattern_type %ptr.loc6_26.1 [symbolic = %pattern_type.loc6_16 (constants.%pattern_type.26f)]\n// CHECK:STDOUT:   %.loc6_32.2: Core.Form = init_form %T.loc6_6.1 [symbolic = %.loc6_32.2 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc6_29: type = pattern_type %T.loc6_6.1 [symbolic = %pattern_type.loc6_29 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17: <witness> = require_complete_type %ptr.loc6_26.1 [symbolic = %require_complete.loc6_17 (constants.%require_complete.0c1)]\n// CHECK:STDOUT:   %require_complete.loc6_32: <witness> = require_complete_type %T.loc6_6.1 [symbolic = %require_complete.loc6_32 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %F.specific_fn.loc6_43.2: <specific function> = specific_function constants.%F, @F(%T.loc6_6.1) [symbolic = %F.specific_fn.loc6_43.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_26.1 (%ptr.a15)) -> out %return.param: @F.%T.loc6_6.1 (%T) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %p.ref: @F.%ptr.loc6_26.1 (%ptr.a15) = name_ref p, %p\n// CHECK:STDOUT:     %F.specific_fn.loc6_43.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc6_43.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:     %.loc6_32.1: ref @F.%T.loc6_6.1 (%T) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%T.loc6_6.1 (%T) to %.loc6_32.1 = call %F.specific_fn.loc6_43.1(%p.ref)\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %ptr.31e) -> out %return.param: %const.0e5 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %p.ref: %ptr.31e = name_ref p, %p\n// CHECK:STDOUT:   return <error> to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%T\n// CHECK:STDOUT:   %const.loc6_19.1 => constants.%const.4ff\n// CHECK:STDOUT:   %ptr.loc6_26.1 => constants.%ptr.a15\n// CHECK:STDOUT:   %pattern_type.loc6_16 => constants.%pattern_type.26f\n// CHECK:STDOUT:   %.loc6_32.2 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc6_29 => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_17 => constants.%require_complete.0c1\n// CHECK:STDOUT:   %require_complete.loc6_32 => constants.%require_complete.944\n// CHECK:STDOUT:   %F.specific_fn.loc6_43.2 => constants.%F.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/deduce/value_with_type_through_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/value_with_type_through_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/value_with_type_through_access.carbon\n\n// --- tuple_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass HoldsType(T:! (type, )) {}\n\n// `a` is received as a value, and has a type that requires going through\n// TupleAccess. Building the value representation must handle this indirection.\nfn F[T:! (type, )](unused x: HoldsType(T), unused a: T.0) {}\n\nclass C {}\n\nfn G() {\n  F({} as HoldsType((C, )), {});\n}\n\n// --- struct_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass HoldsType(T:! {.t: type}) {}\n\n// `a` is received as a value, and has a type that requires going through\n// StructAccess. Building the value representation must handle this indirection.\nfn F[T:! {.t: type}](unused x: HoldsType(T), unused a: T.t) {}\n\nclass C {}\n\nfn G() {\n  F({} as HoldsType({.t = C}), {});\n}\n\n// --- fail_todo_class_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Class {\n  var t: type;\n}\n\nclass HoldsType(T:! Class) {}\n\n// `a` is received as a value, and has a type that requires going through\n// StructAccess. Building the value representation must handle this indirection.\n//\n// TODO: The `Class` value in `T` is a comptime constant and this expression\n// should be able to eval to a type. We would expect the `.` in `T.t` to be a\n// ClassElementAccess but it is an AcquireValue, which has a runtime value.\n//\n// CHECK:STDERR: fail_todo_class_access.carbon:[[@LINE+4]]:51: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n// CHECK:STDERR: fn F[T:! Class](unused x: HoldsType(T), unused a: T.t) {}\n// CHECK:STDERR:                                                   ^~~\n// CHECK:STDERR:\nfn F[T:! Class](unused x: HoldsType(T), unused a: T.t) {}\n\nclass C {}\n\nfn G(c:! Class) {\n  F({} as HoldsType(c), {});\n}\n\nfn H() {\n  // CHECK:STDERR: fail_todo_class_access.carbon:[[@LINE+7]]:3: error: argument for generic parameter is not a compile-time constant [CompTimeArgumentNotConstant]\n  // CHECK:STDERR:   G({.t = C});\n  // CHECK:STDERR:   ^~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_class_access.carbon:[[@LINE-8]]:6: note: initializing generic parameter `c` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn G(c:! Class) {\n  // CHECK:STDERR:      ^\n  // CHECK:STDERR:\n  G({.t = C});\n}\n\n// --- fail_todo_array_index.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass HoldsType(T:! array(type, 1)) {}\n\n// `a` is received as a value, and has a type that requires going through\n// ArrayIndex. Building the value representation must handle this indirection.\n// CHECK:STDERR: fail_todo_array_index.carbon:[[@LINE+4]]:60: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n// CHECK:STDERR: fn F[T:! array(type, 1)](unused x: HoldsType(T), unused a: T[0]) {}\n// CHECK:STDERR:                                                            ^~~~\n// CHECK:STDERR:\nfn F[T:! array(type, 1)](unused x: HoldsType(T), unused a: T[0]) {}\n\nclass C {}\n\nfn G() {\n  // CHECK:STDERR: fail_todo_array_index.carbon:[[@LINE+7]]:11: error: argument for generic parameter is not a compile-time constant [CompTimeArgumentNotConstant]\n  // CHECK:STDERR:   F({} as HoldsType((C, ) as array(type, 1)), {});\n  // CHECK:STDERR:           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_array_index.carbon:[[@LINE-16]]:17: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: class HoldsType(T:! array(type, 1)) {}\n  // CHECK:STDERR:                 ^\n  // CHECK:STDERR:\n  F({} as HoldsType((C, ) as array(type, 1)), {});\n}\n\n\n// CHECK:STDOUT: --- tuple_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple.0d2: %tuple.type = tuple_value (type) [concrete]\n// CHECK:STDOUT:   %pattern_type.f1e: type = pattern_type %tuple.type [concrete]\n// CHECK:STDOUT:   %T: %tuple.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %HoldsType.type: type = generic_class_type @HoldsType [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %HoldsType.generic: %HoldsType.type = struct_value () [concrete]\n// CHECK:STDOUT:   %HoldsType.f6a: type = class_type @HoldsType, @HoldsType(%T) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.17d: type = pattern_type %HoldsType.f6a [symbolic]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %tuple.elem0: type = tuple_access %T, element0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.e66: type = pattern_type %tuple.elem0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.7bf: <witness> = require_complete_type %HoldsType.f6a [symbolic]\n// CHECK:STDOUT:   %require_complete.e7a: <witness> = require_complete_type %tuple.elem0 [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.1f1: %tuple.type = tuple_value (%C) [concrete]\n// CHECK:STDOUT:   %HoldsType.a31: type = class_type @HoldsType, @HoldsType(%tuple.1f1) [concrete]\n// CHECK:STDOUT:   %HoldsType.val: %HoldsType.a31 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.a646: type = pattern_type %HoldsType.a31 [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%tuple.1f1) [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc13_30 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc13_8 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .HoldsType = %HoldsType.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %HoldsType.decl: %HoldsType.type = class_decl @HoldsType [concrete = constants.%HoldsType.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.f1e = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_28.1: type = splice_block %.loc4_28.3 [concrete = constants.%tuple.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_22: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.loc4_28.2: %tuple.type = tuple_literal (%.loc4_22) [concrete = constants.%tuple.0d2]\n// CHECK:STDOUT:       %.loc4_28.3: type = converted %.loc4_28.2, constants.%tuple.type [concrete = constants.%tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_17.2: %tuple.type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.f1e = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type.loc8_27 (%pattern_type.17d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type.loc8_27 (%pattern_type.17d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type.loc8_51 (%pattern_type.e66) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type.loc8_51 (%pattern_type.e66) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_17.1: type = splice_block %.loc8_17.3 [concrete = constants.%tuple.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_11: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.loc8_17.2: %tuple.type = tuple_literal (%.loc8_11) [concrete = constants.%tuple.0d2]\n// CHECK:STDOUT:       %.loc8_17.3: type = converted %.loc8_17.2, constants.%tuple.type [concrete = constants.%tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_6.2: %tuple.type = symbolic_binding T, 0 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @F.%HoldsType.loc8_41.1 (%HoldsType.f6a) = value_param call_param0\n// CHECK:STDOUT:     %.loc8_41: type = splice_block %HoldsType.loc8_41.2 [symbolic = %HoldsType.loc8_41.1 (constants.%HoldsType.f6a)] {\n// CHECK:STDOUT:       %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:       %T.ref.loc8_40: %tuple.type = name_ref T, %T.loc8_6.2 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:       %HoldsType.loc8_41.2: type = class_type @HoldsType, @HoldsType(constants.%T) [symbolic = %HoldsType.loc8_41.1 (constants.%HoldsType.f6a)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @F.%HoldsType.loc8_41.1 (%HoldsType.f6a) = value_binding x, %x.param\n// CHECK:STDOUT:     %a.param: @F.%tuple.elem0.loc8_55.1 (%tuple.elem0) = value_param call_param1\n// CHECK:STDOUT:     %.loc8_55: type = splice_block %tuple.elem0.loc8_55.2 [symbolic = %tuple.elem0.loc8_55.1 (constants.%tuple.elem0)] {\n// CHECK:STDOUT:       %T.ref.loc8_54: %tuple.type = name_ref T, %T.loc8_6.2 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:       %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:       %tuple.elem0.loc8_55.2: type = tuple_access %T.ref.loc8_54, element0 [symbolic = %tuple.elem0.loc8_55.1 (constants.%tuple.elem0)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%tuple.elem0.loc8_55.1 (%tuple.elem0) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @HoldsType(%T.loc4_17.2: %tuple.type) {\n// CHECK:STDOUT:   %T.loc4_17.1: %tuple.type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%HoldsType.f6a\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc8_6.2: %tuple.type) {\n// CHECK:STDOUT:   %T.loc8_6.1: %tuple.type = symbolic_binding T, 0 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:   %HoldsType.loc8_41.1: type = class_type @HoldsType, @HoldsType(%T.loc8_6.1) [symbolic = %HoldsType.loc8_41.1 (constants.%HoldsType.f6a)]\n// CHECK:STDOUT:   %pattern_type.loc8_27: type = pattern_type %HoldsType.loc8_41.1 [symbolic = %pattern_type.loc8_27 (constants.%pattern_type.17d)]\n// CHECK:STDOUT:   %tuple.elem0.loc8_55.1: type = tuple_access %T.loc8_6.1, element0 [symbolic = %tuple.elem0.loc8_55.1 (constants.%tuple.elem0)]\n// CHECK:STDOUT:   %pattern_type.loc8_51: type = pattern_type %tuple.elem0.loc8_55.1 [symbolic = %pattern_type.loc8_51 (constants.%pattern_type.e66)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc8_28: <witness> = require_complete_type %HoldsType.loc8_41.1 [symbolic = %require_complete.loc8_28 (constants.%require_complete.7bf)]\n// CHECK:STDOUT:   %require_complete.loc8_52: <witness> = require_complete_type %tuple.elem0.loc8_55.1 [symbolic = %require_complete.loc8_52 (constants.%require_complete.e7a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%HoldsType.loc8_41.1 (%HoldsType.f6a), %a.param: @F.%tuple.elem0.loc8_55.1 (%tuple.elem0)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc13_6.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc13_25: %tuple.type = tuple_literal (%C.ref) [concrete = constants.%tuple.1f1]\n// CHECK:STDOUT:   %tuple: %tuple.type = tuple_value (%C.ref) [concrete = constants.%tuple.1f1]\n// CHECK:STDOUT:   %.loc13_26: %tuple.type = converted %.loc13_25, %tuple [concrete = constants.%tuple.1f1]\n// CHECK:STDOUT:   %HoldsType: type = class_type @HoldsType, @HoldsType(constants.%tuple.1f1) [concrete = constants.%HoldsType.a31]\n// CHECK:STDOUT:   %.loc13_6.2: ref %HoldsType.a31 = temporary_storage\n// CHECK:STDOUT:   %.loc13_6.3: init %HoldsType.a31 to %.loc13_6.2 = class_init () [concrete = constants.%HoldsType.val]\n// CHECK:STDOUT:   %.loc13_8.1: init %HoldsType.a31 = converted %.loc13_6.1, %.loc13_6.3 [concrete = constants.%HoldsType.val]\n// CHECK:STDOUT:   %.loc13_30.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%tuple.1f1) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %.loc13_8.2: ref %HoldsType.a31 = temporary %.loc13_6.2, %.loc13_8.1\n// CHECK:STDOUT:   %.loc13_8.3: %HoldsType.a31 = acquire_value %.loc13_8.2\n// CHECK:STDOUT:   %.loc13_30.2: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc13_30.3: init %C to %.loc13_30.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc13_30.4: init %C = converted %.loc13_30.1, %.loc13_30.3 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc13_30.5: ref %C = temporary %.loc13_30.2, %.loc13_30.4\n// CHECK:STDOUT:   %.loc13_30.6: %C = acquire_value %.loc13_30.5\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc13_8.3, %.loc13_30.6)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13_30: <bound method> = bound_method %.loc13_30.5, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc13_30: init %empty_tuple.type = call %Destroy.Op.bound.loc13_30(%.loc13_30.5)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13_8: <bound method> = bound_method %.loc13_8.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc13_8: init %empty_tuple.type = call %Destroy.Op.bound.loc13_8(%.loc13_8.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc13_30(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc13_8(%self.param: ref %HoldsType.a31) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HoldsType(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_6.1 => constants.%T\n// CHECK:STDOUT:   %HoldsType.loc8_41.1 => constants.%HoldsType.f6a\n// CHECK:STDOUT:   %pattern_type.loc8_27 => constants.%pattern_type.17d\n// CHECK:STDOUT:   %tuple.elem0.loc8_55.1 => constants.%tuple.elem0\n// CHECK:STDOUT:   %pattern_type.loc8_51 => constants.%pattern_type.e66\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HoldsType(constants.%tuple.1f1) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%tuple.1f1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%tuple.1f1) {\n// CHECK:STDOUT:   %T.loc8_6.1 => constants.%tuple.1f1\n// CHECK:STDOUT:   %HoldsType.loc8_41.1 => constants.%HoldsType.a31\n// CHECK:STDOUT:   %pattern_type.loc8_27 => constants.%pattern_type.a646\n// CHECK:STDOUT:   %tuple.elem0.loc8_55.1 => constants.%C\n// CHECK:STDOUT:   %pattern_type.loc8_51 => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc8_28 => constants.%complete_type\n// CHECK:STDOUT:   %require_complete.loc8_52 => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- struct_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %struct_type.t: type = struct_type {.t: type} [concrete]\n// CHECK:STDOUT:   %pattern_type.7f2: type = pattern_type %struct_type.t [concrete]\n// CHECK:STDOUT:   %T: %struct_type.t = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %HoldsType.type: type = generic_class_type @HoldsType [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %HoldsType.generic: %HoldsType.type = struct_value () [concrete]\n// CHECK:STDOUT:   %HoldsType.cac: type = class_type @HoldsType, @HoldsType(%T) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.2de: type = pattern_type %HoldsType.cac [symbolic]\n// CHECK:STDOUT:   %.424: type = struct_access %T, element0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.92c: type = pattern_type %.424 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.276: <witness> = require_complete_type %HoldsType.cac [symbolic]\n// CHECK:STDOUT:   %require_complete.ba0: <witness> = require_complete_type %.424 [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.t = struct_value (%C) [concrete]\n// CHECK:STDOUT:   %HoldsType.673: type = class_type @HoldsType, @HoldsType(%struct) [concrete]\n// CHECK:STDOUT:   %HoldsType.val: %HoldsType.673 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.4e6: type = pattern_type %HoldsType.673 [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%struct) [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc13_33 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc13_8 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .HoldsType = %HoldsType.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %HoldsType.decl: %HoldsType.type = class_decl @HoldsType [concrete = constants.%HoldsType.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.7f2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_30: type = splice_block %struct_type.t [concrete = constants.%struct_type.t] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_26: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %struct_type.t: type = struct_type {.t: type} [concrete = constants.%struct_type.t]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_17.2: %struct_type.t = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.7f2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type.loc8_29 (%pattern_type.2de) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type.loc8_29 (%pattern_type.2de) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type.loc8_53 (%pattern_type.92c) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type.loc8_53 (%pattern_type.92c) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_19: type = splice_block %struct_type.t [concrete = constants.%struct_type.t] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_15: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %struct_type.t: type = struct_type {.t: type} [concrete = constants.%struct_type.t]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_6.2: %struct_type.t = symbolic_binding T, 0 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @F.%HoldsType.loc8_43.1 (%HoldsType.cac) = value_param call_param0\n// CHECK:STDOUT:     %.loc8_43: type = splice_block %HoldsType.loc8_43.2 [symbolic = %HoldsType.loc8_43.1 (constants.%HoldsType.cac)] {\n// CHECK:STDOUT:       %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:       %T.ref.loc8_42: %struct_type.t = name_ref T, %T.loc8_6.2 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:       %HoldsType.loc8_43.2: type = class_type @HoldsType, @HoldsType(constants.%T) [symbolic = %HoldsType.loc8_43.1 (constants.%HoldsType.cac)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @F.%HoldsType.loc8_43.1 (%HoldsType.cac) = value_binding x, %x.param\n// CHECK:STDOUT:     %a.param: @F.%.loc8_57.1 (%.424) = value_param call_param1\n// CHECK:STDOUT:     %.loc8_57.2: type = splice_block %.loc8_57.3 [symbolic = %.loc8_57.1 (constants.%.424)] {\n// CHECK:STDOUT:       %T.ref.loc8_56: %struct_type.t = name_ref T, %T.loc8_6.2 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:       %.loc8_57.3: type = struct_access %T.ref.loc8_56, element0 [symbolic = %.loc8_57.1 (constants.%.424)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%.loc8_57.1 (%.424) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @HoldsType(%T.loc4_17.2: %struct_type.t) {\n// CHECK:STDOUT:   %T.loc4_17.1: %struct_type.t = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%HoldsType.cac\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc8_6.2: %struct_type.t) {\n// CHECK:STDOUT:   %T.loc8_6.1: %struct_type.t = symbolic_binding T, 0 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:   %HoldsType.loc8_43.1: type = class_type @HoldsType, @HoldsType(%T.loc8_6.1) [symbolic = %HoldsType.loc8_43.1 (constants.%HoldsType.cac)]\n// CHECK:STDOUT:   %pattern_type.loc8_29: type = pattern_type %HoldsType.loc8_43.1 [symbolic = %pattern_type.loc8_29 (constants.%pattern_type.2de)]\n// CHECK:STDOUT:   %.loc8_57.1: type = struct_access %T.loc8_6.1, element0 [symbolic = %.loc8_57.1 (constants.%.424)]\n// CHECK:STDOUT:   %pattern_type.loc8_53: type = pattern_type %.loc8_57.1 [symbolic = %pattern_type.loc8_53 (constants.%pattern_type.92c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc8_30: <witness> = require_complete_type %HoldsType.loc8_43.1 [symbolic = %require_complete.loc8_30 (constants.%require_complete.276)]\n// CHECK:STDOUT:   %require_complete.loc8_54: <witness> = require_complete_type %.loc8_57.1 [symbolic = %require_complete.loc8_54 (constants.%require_complete.ba0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%HoldsType.loc8_43.1 (%HoldsType.cac), %a.param: @F.%.loc8_57.1 (%.424)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc13_6.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc13_28: %struct_type.t = struct_literal (%C.ref) [concrete = constants.%struct]\n// CHECK:STDOUT:   %struct: %struct_type.t = struct_value (%C.ref) [concrete = constants.%struct]\n// CHECK:STDOUT:   %.loc13_29: %struct_type.t = converted %.loc13_28, %struct [concrete = constants.%struct]\n// CHECK:STDOUT:   %HoldsType: type = class_type @HoldsType, @HoldsType(constants.%struct) [concrete = constants.%HoldsType.673]\n// CHECK:STDOUT:   %.loc13_6.2: ref %HoldsType.673 = temporary_storage\n// CHECK:STDOUT:   %.loc13_6.3: init %HoldsType.673 to %.loc13_6.2 = class_init () [concrete = constants.%HoldsType.val]\n// CHECK:STDOUT:   %.loc13_8.1: init %HoldsType.673 = converted %.loc13_6.1, %.loc13_6.3 [concrete = constants.%HoldsType.val]\n// CHECK:STDOUT:   %.loc13_33.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%struct) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %.loc13_8.2: ref %HoldsType.673 = temporary %.loc13_6.2, %.loc13_8.1\n// CHECK:STDOUT:   %.loc13_8.3: %HoldsType.673 = acquire_value %.loc13_8.2\n// CHECK:STDOUT:   %.loc13_33.2: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc13_33.3: init %C to %.loc13_33.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc13_33.4: init %C = converted %.loc13_33.1, %.loc13_33.3 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc13_33.5: ref %C = temporary %.loc13_33.2, %.loc13_33.4\n// CHECK:STDOUT:   %.loc13_33.6: %C = acquire_value %.loc13_33.5\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc13_8.3, %.loc13_33.6)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13_33: <bound method> = bound_method %.loc13_33.5, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc13_33: init %empty_tuple.type = call %Destroy.Op.bound.loc13_33(%.loc13_33.5)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc13_8: <bound method> = bound_method %.loc13_8.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc13_8: init %empty_tuple.type = call %Destroy.Op.bound.loc13_8(%.loc13_8.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc13_33(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc13_8(%self.param: ref %HoldsType.673) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HoldsType(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_6.1 => constants.%T\n// CHECK:STDOUT:   %HoldsType.loc8_43.1 => constants.%HoldsType.cac\n// CHECK:STDOUT:   %pattern_type.loc8_29 => constants.%pattern_type.2de\n// CHECK:STDOUT:   %.loc8_57.1 => constants.%.424\n// CHECK:STDOUT:   %pattern_type.loc8_53 => constants.%pattern_type.92c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HoldsType(constants.%struct) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%struct\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%struct) {\n// CHECK:STDOUT:   %T.loc8_6.1 => constants.%struct\n// CHECK:STDOUT:   %HoldsType.loc8_43.1 => constants.%HoldsType.673\n// CHECK:STDOUT:   %pattern_type.loc8_29 => constants.%pattern_type.4e6\n// CHECK:STDOUT:   %.loc8_57.1 => constants.%C\n// CHECK:STDOUT:   %pattern_type.loc8_53 => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc8_30 => constants.%complete_type\n// CHECK:STDOUT:   %require_complete.loc8_54 => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_class_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Class: type = class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.elem: type = unbound_element_type %Class, type [concrete]\n// CHECK:STDOUT:   %struct_type.t: type = struct_type {.t: type} [concrete]\n// CHECK:STDOUT:   %complete_type.509: <witness> = complete_type_witness %struct_type.t [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.904: type = pattern_type %Class [concrete]\n// CHECK:STDOUT:   %T.d7d: %Class = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %HoldsType.type: type = generic_class_type @HoldsType [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %HoldsType.generic: %HoldsType.type = struct_value () [concrete]\n// CHECK:STDOUT:   %HoldsType.47b504.1: type = class_type @HoldsType, @HoldsType(%T.d7d) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.3b8: type = pattern_type %HoldsType.47b504.1 [symbolic]\n// CHECK:STDOUT:   %.208: ref type = class_element_access %T.d7d, element0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.9b8c71.1: <witness> = require_complete_type %HoldsType.47b504.1 [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %c: %Class = symbolic_binding c, 0 [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %HoldsType.47b504.2: type = class_type @HoldsType, @HoldsType(%c) [symbolic]\n// CHECK:STDOUT:   %require_complete.9b8c71.2: <witness> = require_complete_type %HoldsType.47b504.2 [symbolic]\n// CHECK:STDOUT:   %HoldsType.val: %HoldsType.47b504.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]\n// CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.t = struct_value (%C) [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.b47: <witness> = impl_witness imports.%Copy.impl_witness_table.b1c [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value type, (%Copy.impl_witness.b47) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.a4f: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.070: type = fn_type_with_self_type %Copy.WithSelf.Op.type.a4f, %Copy.facet [concrete]\n// CHECK:STDOUT:   %type.as.Copy.impl.Op.type: type = fn_type @type.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.Copy.impl.Op: %type.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.Copy.impl.Op.bound: <bound method> = bound_method %C, %type.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %Class.val: %Class = struct_value (%C) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.1a7: %type.as.Copy.impl.Op.type = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.b1c = impl_witness_table (%Core.import_ref.1a7), @type.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:     .HoldsType = %HoldsType.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:     .H = %H.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: type = class_decl @Class [concrete = constants.%Class] {} {}\n// CHECK:STDOUT:   %HoldsType.decl: %HoldsType.type = class_decl @HoldsType [concrete = constants.%HoldsType.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.904 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8: type = splice_block %Class.ref [concrete = constants.%Class] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_17.2: %Class = symbolic_binding T, 0 [symbolic = %T.loc8_17.1 (constants.%T.d7d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.904 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.3b8) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.3b8) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %a.patt: <error> = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: <error> = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc21_10: type = splice_block %Class.ref [concrete = constants.%Class] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc21_6.2: %Class = symbolic_binding T, 0 [symbolic = %T.loc21_6.1 (constants.%T.d7d)]\n// CHECK:STDOUT:     %x.param: @F.%HoldsType.loc21_38.1 (%HoldsType.47b504.1) = value_param call_param0\n// CHECK:STDOUT:     %.loc21_38: type = splice_block %HoldsType.loc21_38.2 [symbolic = %HoldsType.loc21_38.1 (constants.%HoldsType.47b504.1)] {\n// CHECK:STDOUT:       %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:       %T.ref.loc21_37: %Class = name_ref T, %T.loc21_6.2 [symbolic = %T.loc21_6.1 (constants.%T.d7d)]\n// CHECK:STDOUT:       %HoldsType.loc21_38.2: type = class_type @HoldsType, @HoldsType(constants.%T.d7d) [symbolic = %HoldsType.loc21_38.1 (constants.%HoldsType.47b504.1)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @F.%HoldsType.loc21_38.1 (%HoldsType.47b504.1) = value_binding x, %x.param\n// CHECK:STDOUT:     %a.param: <error> = value_param call_param1\n// CHECK:STDOUT:     %.1: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:       %T.ref.loc21_51: %Class = name_ref T, %T.loc21_6.2 [symbolic = %T.loc21_6.1 (constants.%T.d7d)]\n// CHECK:STDOUT:       %t.ref: %Class.elem = name_ref t, @Class.%.loc5_8 [concrete = @Class.%.loc5_8]\n// CHECK:STDOUT:       %.loc21_52.2: ref type = class_element_access %T.ref.loc21_51, element0 [symbolic = %.loc21_52.1 (constants.%.208)]\n// CHECK:STDOUT:       %.loc21_52.3: type = acquire_value %.loc21_52.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: <error> = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.904 = symbolic_binding_pattern c, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc25: type = splice_block %Class.ref [concrete = constants.%Class] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Class.ref: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c.loc25_6.2: %Class = symbolic_binding c, 0 [symbolic = %c.loc25_6.1 (constants.%c)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Class {\n// CHECK:STDOUT:   %.loc5_10: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   %.loc5_8: %Class.elem = field_decl t, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.t [concrete = constants.%complete_type.509]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Class\n// CHECK:STDOUT:   .t = %.loc5_8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @HoldsType(%T.loc8_17.2: %Class) {\n// CHECK:STDOUT:   %T.loc8_17.1: %Class = symbolic_binding T, 0 [symbolic = %T.loc8_17.1 (constants.%T.d7d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%HoldsType.47b504.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc21_6.2: %Class) {\n// CHECK:STDOUT:   %T.loc21_6.1: %Class = symbolic_binding T, 0 [symbolic = %T.loc21_6.1 (constants.%T.d7d)]\n// CHECK:STDOUT:   %HoldsType.loc21_38.1: type = class_type @HoldsType, @HoldsType(%T.loc21_6.1) [symbolic = %HoldsType.loc21_38.1 (constants.%HoldsType.47b504.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %HoldsType.loc21_38.1 [symbolic = %pattern_type (constants.%pattern_type.3b8)]\n// CHECK:STDOUT:   %.loc21_52.1: ref type = class_element_access %T.loc21_6.1, element0 [symbolic = %.loc21_52.1 (constants.%.208)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %HoldsType.loc21_38.1 [symbolic = %require_complete (constants.%require_complete.9b8c71.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%HoldsType.loc21_38.1 (%HoldsType.47b504.1), %a.param: <error>) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%c.loc25_6.2: %Class) {\n// CHECK:STDOUT:   %c.loc25_6.1: %Class = symbolic_binding c, 0 [symbolic = %c.loc25_6.1 (constants.%c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %HoldsType.loc26_22.2: type = class_type @HoldsType, @HoldsType(%c.loc25_6.1) [symbolic = %HoldsType.loc26_22.2 (constants.%HoldsType.47b504.2)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %HoldsType.loc26_22.2 [symbolic = %require_complete (constants.%require_complete.9b8c71.2)]\n// CHECK:STDOUT:   %HoldsType.val: @G.%HoldsType.loc26_22.2 (%HoldsType.47b504.2) = struct_value () [symbolic = %HoldsType.val (constants.%HoldsType.val)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %.loc26_6.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:     %c.ref: %Class = name_ref c, %c.loc25_6.2 [symbolic = %c.loc25_6.1 (constants.%c)]\n// CHECK:STDOUT:     %HoldsType.loc26_22.1: type = class_type @HoldsType, @HoldsType(constants.%c) [symbolic = %HoldsType.loc26_22.2 (constants.%HoldsType.47b504.2)]\n// CHECK:STDOUT:     %.loc26_6.2: ref @G.%HoldsType.loc26_22.2 (%HoldsType.47b504.2) = temporary_storage\n// CHECK:STDOUT:     %.loc26_6.3: init @G.%HoldsType.loc26_22.2 (%HoldsType.47b504.2) to %.loc26_6.2 = class_init () [symbolic = %HoldsType.val (constants.%HoldsType.val)]\n// CHECK:STDOUT:     %.loc26_8: init @G.%HoldsType.loc26_22.2 (%HoldsType.47b504.2) = converted %.loc26_6.1, %.loc26_6.3 [symbolic = %HoldsType.val (constants.%HoldsType.val)]\n// CHECK:STDOUT:     %.loc26_26: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @H() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc37_12.1: %struct_type.t = struct_literal (%C.ref) [concrete = constants.%struct]\n// CHECK:STDOUT:   %impl.elem0: %.070 = impl_witness_access constants.%Copy.impl_witness.b47, element0 [concrete = constants.%type.as.Copy.impl.Op]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %C.ref, %impl.elem0 [concrete = constants.%type.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %type.as.Copy.impl.Op.call: init type = call %bound_method(%C.ref) [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc37_12.2: ref %Class = temporary_storage\n// CHECK:STDOUT:   %.loc37_12.3: ref type = class_element_access %.loc37_12.2, element0\n// CHECK:STDOUT:   %.loc37_12.4: init type to %.loc37_12.3 = in_place_init %type.as.Copy.impl.Op.call [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc37_12.5: init %Class to %.loc37_12.2 = class_init (%.loc37_12.4) [concrete = constants.%Class.val]\n// CHECK:STDOUT:   %.loc37_13.1: init %Class = converted %.loc37_12.1, %.loc37_12.5 [concrete = constants.%Class.val]\n// CHECK:STDOUT:   %.loc37_13.2: ref %Class = temporary %.loc37_12.2, %.loc37_13.1\n// CHECK:STDOUT:   %.loc37_13.3: %Class = acquire_value %.loc37_13.2\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc37_13.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc37_13.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Class) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HoldsType(constants.%T.d7d) {\n// CHECK:STDOUT:   %T.loc8_17.1 => constants.%T.d7d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.d7d) {\n// CHECK:STDOUT:   %T.loc21_6.1 => constants.%T.d7d\n// CHECK:STDOUT:   %HoldsType.loc21_38.1 => constants.%HoldsType.47b504.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.3b8\n// CHECK:STDOUT:   %.loc21_52.1 => constants.%.208\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%c) {\n// CHECK:STDOUT:   %c.loc25_6.1 => constants.%c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HoldsType(constants.%c) {\n// CHECK:STDOUT:   %T.loc8_17.1 => constants.%c\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_array_index.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_1, type [concrete]\n// CHECK:STDOUT:   %pattern_type.dcb: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %T.9b7: %array_type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %HoldsType.type: type = generic_class_type @HoldsType [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %HoldsType.generic: %HoldsType.type = struct_value () [concrete]\n// CHECK:STDOUT:   %HoldsType: type = class_type @HoldsType, @HoldsType(%T.9b7) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.342: type = pattern_type %HoldsType [symbolic]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.bd5: <witness> = require_complete_type %HoldsType [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple.1f1: %tuple.type.85c = tuple_value (%C) [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.b47: <witness> = impl_witness imports.%Copy.impl_witness_table.b1c [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value type, (%Copy.impl_witness.b47) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.a4f: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.070: type = fn_type_with_self_type %Copy.WithSelf.Op.type.a4f, %Copy.facet [concrete]\n// CHECK:STDOUT:   %type.as.Copy.impl.Op.type: type = fn_type @type.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.Copy.impl.Op: %type.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.Copy.impl.Op.bound: <bound method> = bound_method %C, %type.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%C) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.1a7: %type.as.Copy.impl.Op.type = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.b1c = impl_witness_table (%Core.import_ref.1a7), @type.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .HoldsType = %HoldsType.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %HoldsType.decl: %HoldsType.type = class_decl @HoldsType [concrete = constants.%HoldsType.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.dcb = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_34: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_27: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:       %array_type: type = array_type %int_1, %.loc4_27 [concrete = constants.%array_type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_17.2: %array_type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T.9b7)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.dcb = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.342) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.342) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %a.patt: <error> = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: <error> = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc12_23: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc12_16: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:       %array_type: type = array_type %int_1, %.loc12_16 [concrete = constants.%array_type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc12_6.2: %array_type = symbolic_binding T, 0 [symbolic = %T.loc12_6.1 (constants.%T.9b7)]\n// CHECK:STDOUT:     %x.param: @F.%HoldsType.loc12_47.1 (%HoldsType) = value_param call_param0\n// CHECK:STDOUT:     %.loc12_47: type = splice_block %HoldsType.loc12_47.2 [symbolic = %HoldsType.loc12_47.1 (constants.%HoldsType)] {\n// CHECK:STDOUT:       %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:       %T.ref.loc12_46: %array_type = name_ref T, %T.loc12_6.2 [symbolic = %T.loc12_6.1 (constants.%T.9b7)]\n// CHECK:STDOUT:       %HoldsType.loc12_47.2: type = class_type @HoldsType, @HoldsType(constants.%T.9b7) [symbolic = %HoldsType.loc12_47.1 (constants.%HoldsType)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @F.%HoldsType.loc12_47.1 (%HoldsType) = value_binding x, %x.param\n// CHECK:STDOUT:     %a.param: <error> = value_param call_param1\n// CHECK:STDOUT:     %.1: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:       %T.ref.loc12_60: %array_type = name_ref T, %T.loc12_6.2 [symbolic = %T.loc12_6.1 (constants.%T.9b7)]\n// CHECK:STDOUT:       %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:       %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:       %bound_method.loc12_62.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:       %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc12_62.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:       %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc12_62.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:       %.loc12_62.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:       %.loc12_62.2: %i32 = converted %int_0, %.loc12_62.1 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:       %.loc12_63.1: ref %array_type = value_as_ref %T.ref.loc12_60\n// CHECK:STDOUT:       %.loc12_63.2: ref type = array_index %.loc12_63.1, %.loc12_62.2\n// CHECK:STDOUT:       %.loc12_63.3: type = acquire_value %.loc12_63.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: <error> = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @HoldsType(%T.loc4_17.2: %array_type) {\n// CHECK:STDOUT:   %T.loc4_17.1: %array_type = symbolic_binding T, 0 [symbolic = %T.loc4_17.1 (constants.%T.9b7)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%HoldsType\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc12_6.2: %array_type) {\n// CHECK:STDOUT:   %T.loc12_6.1: %array_type = symbolic_binding T, 0 [symbolic = %T.loc12_6.1 (constants.%T.9b7)]\n// CHECK:STDOUT:   %HoldsType.loc12_47.1: type = class_type @HoldsType, @HoldsType(%T.loc12_6.1) [symbolic = %HoldsType.loc12_47.1 (constants.%HoldsType)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %HoldsType.loc12_47.1 [symbolic = %pattern_type (constants.%pattern_type.342)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %HoldsType.loc12_47.1 [symbolic = %require_complete (constants.%require_complete.bd5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%HoldsType.loc12_47.1 (%HoldsType), %a.param: <error>) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc24_6: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc24_25.1: %tuple.type.85c = tuple_literal (%C.ref) [concrete = constants.%tuple.1f1]\n// CHECK:STDOUT:   %.loc24_36: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %array_type: type = array_type %int_1, %.loc24_36 [concrete = constants.%array_type]\n// CHECK:STDOUT:   %impl.elem0: %.070 = impl_witness_access constants.%Copy.impl_witness.b47, element0 [concrete = constants.%type.as.Copy.impl.Op]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %C.ref, %impl.elem0 [concrete = constants.%type.as.Copy.impl.Op.bound]\n// CHECK:STDOUT:   %type.as.Copy.impl.Op.call: init type = call %bound_method(%C.ref) [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc24_25.2: ref %array_type = temporary_storage\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %.loc24_25.3: ref type = array_index %.loc24_25.2, %int_0\n// CHECK:STDOUT:   %.loc24_25.4: init type to %.loc24_25.3 = in_place_init %type.as.Copy.impl.Op.call [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc24_25.5: init %array_type to %.loc24_25.2 = array_init (%.loc24_25.4) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc24_27.1: init %array_type = converted %.loc24_25.1, %.loc24_25.5 [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc24_27.2: ref %array_type = temporary %.loc24_25.2, %.loc24_27.1\n// CHECK:STDOUT:   %.loc24_27.3: %array_type = acquire_value %.loc24_27.2\n// CHECK:STDOUT:   %.loc24_48: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc24_27.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc24_27.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HoldsType(constants.%T.9b7) {\n// CHECK:STDOUT:   %T.loc4_17.1 => constants.%T.9b7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.9b7) {\n// CHECK:STDOUT:   %T.loc12_6.1 => constants.%T.9b7\n// CHECK:STDOUT:   %HoldsType.loc12_47.1 => constants.%HoldsType\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.342\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/deduce/where.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/deduce/where.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/deduce/where.carbon\n\n// --- fail_todo_where.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n}\n\nclass C(unused T:! type) {}\n\nfn F[U:! type](unused T:! Z where .Z1 = C(U)) {}\n\nclass D {}\nfinal impl () as Z where .Z1 = C(D) {}\n\nfn G() {\n  // TODO: Should be able to see that ().(Z.Z1) is C(D), so deduce that C(U)\n  // is C(D) and U is D.\n  //\n  // CHECK:STDERR: fail_todo_where.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `U` [DeductionIncomplete]\n  // CHECK:STDERR:   F(() as type);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_where.carbon:[[@LINE-12]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn F[U:! type](unused T:! Z where .Z1 = C(U)) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  F(() as type);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/eval/aggregates.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/eval/aggregates.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/eval/aggregates.carbon\n\n// --- basics.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nvar tuple_copy: (i32, i32) = (1, 2) as (i32, i32);\n\nvar struct_copy: {.a: i32, .b: i32, .c: i32} = {.c = 3, .b = 2, .a = 1} as {.b: i32, .a: i32, .c: i32};\n\nvar tuple_index: array(i32, 1) = (0,) as array(i32, (5, 7, 1, 9).2);\n\nvar struct_access: array(i32, 1) = (0,) as array(i32, {.a = 3, .b = 1}.b);\n//@dump-sem-ir-end\n\n// --- fail_todo_array_temporary.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: This creates an array temporary, which we don't yet support evaluating.\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_todo_array_temporary.carbon:[[@LINE+4]]:53: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var array_index: array(i32, 1) = (0,) as array(i32, ((5, 7, 1, 9) as array(i32, 4))[2]);\n// CHECK:STDERR:                                                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar array_index: array(i32, 1) = (0,) as array(i32, ((5, 7, 1, 9) as array(i32, 4))[2]);\n//@dump-sem-ir-end\n\n// --- symbolic.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// Check that we propagate the `symbolic` tag through evaluations.\nfn F(T:! type) {\n  //@dump-sem-ir-begin\n  var unused u: (T*, const T);\n  var unused v: {.a: T};\n  var unused w: array(T, 5);\n  //@dump-sem-ir-end\n}\n\nfn G(N:! i32) {\n  //@dump-sem-ir-begin\n  var unused k: array(i32, N);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- basics.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.95a: %tuple.type.24b = tuple_value (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.511: type = pattern_type %tuple.type.d07 [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.type.f94: type = tuple_type (Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.ad8: %tuple.type.f94 = tuple_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.21c: %tuple.type.d07 = tuple_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %tuple.elem0: ref %i32 = tuple_access file.%tuple_copy.var, element0 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound.ee3: <bound method> = bound_method %int_1.5d2, %Int.as.Copy.impl.Op.664 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.4d7: <bound method> = bound_method %int_1.5d2, %Int.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT:   %tuple.elem1: ref %i32 = tuple_access file.%tuple_copy.var, element1 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound.5e8: <bound method> = bound_method %int_2.ef8, %Int.as.Copy.impl.Op.664 [concrete]\n// CHECK:STDOUT:   %bound_method.f15: <bound method> = bound_method %int_2.ef8, %Int.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.c: type = struct_type {.a: %i32, .b: %i32, .c: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.8ae: type = pattern_type %struct_type.a.b.c [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %struct_type.c.b.a: type = struct_type {.c: Core.IntLiteral, .b: Core.IntLiteral, .a: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.c75: %struct_type.c.b.a = struct_value (%int_3.1ba, %int_2.ecc, %int_1.5b8) [concrete]\n// CHECK:STDOUT:   %struct_type.b.a.c: type = struct_type {.b: %i32, .a: %i32, .c: %i32} [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %struct.21d: %struct_type.b.a.c = struct_value (%int_2.ef8, %int_1.5d2, %int_3.822) [concrete]\n// CHECK:STDOUT:   %.460: ref %i32 = struct_access file.%struct_copy.var, element1 [concrete]\n// CHECK:STDOUT:   %.61f: ref %i32 = struct_access file.%struct_copy.var, element0 [concrete]\n// CHECK:STDOUT:   %.f68: ref %i32 = struct_access file.%struct_copy.var, element2 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound.ecc: <bound method> = bound_method %int_3.822, %Int.as.Copy.impl.Op.664 [concrete]\n// CHECK:STDOUT:   %bound_method.4f5: <bound method> = bound_method %int_3.822, %Int.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT:   %struct.cff: %struct_type.a.b.c = struct_value (%int_1.5d2, %int_2.ef8, %int_3.822) [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_1.5b8, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.a98: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.4f2: %tuple.type.985 = tuple_value (%int_0.5c6) [concrete]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %int_7: Core.IntLiteral = int_value 7 [concrete]\n// CHECK:STDOUT:   %int_9: Core.IntLiteral = int_value 9 [concrete]\n// CHECK:STDOUT:   %tuple.type.d46: type = tuple_type (Core.IntLiteral, Core.IntLiteral, Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.869: %tuple.type.d46 = tuple_value (%int_5, %int_7, %int_1.5b8, %int_9) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.897: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.d2e: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%int_0.6a9) [concrete]\n// CHECK:STDOUT:   %struct_type.a.b: type = struct_type {.a: Core.IntLiteral, .b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.a81: %struct_type.a.b = struct_value (%int_3.1ba, %int_1.5b8) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %tuple_copy.patt: %pattern_type.511 = ref_binding_pattern tuple_copy [concrete]\n// CHECK:STDOUT:     %tuple_copy.var_patt: %pattern_type.511 = var_pattern %tuple_copy.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %tuple_copy.var: ref %tuple.type.d07 = var %tuple_copy.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_26.1: type = splice_block %.loc4_26.3 [concrete = constants.%tuple.type.d07] {\n// CHECK:STDOUT:     %i32.loc4_18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %i32.loc4_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4_26.2: %tuple.type.24b = tuple_literal (%i32.loc4_18, %i32.loc4_23) [concrete = constants.%tuple.95a]\n// CHECK:STDOUT:     %.loc4_26.3: type = converted %.loc4_26.2, constants.%tuple.type.d07 [concrete = constants.%tuple.type.d07]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %tuple_copy: ref %tuple.type.d07 = ref_binding tuple_copy, %tuple_copy.var [concrete = %tuple_copy.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %struct_copy.patt: %pattern_type.8ae = ref_binding_pattern struct_copy [concrete]\n// CHECK:STDOUT:     %struct_copy.var_patt: %pattern_type.8ae = var_pattern %struct_copy.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %struct_copy.var: ref %struct_type.a.b.c = var %struct_copy.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6: type = splice_block %struct_type.a.b.c [concrete = constants.%struct_type.a.b.c] {\n// CHECK:STDOUT:     %i32.loc6_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %i32.loc6_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %i32.loc6_41: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.a.b.c: type = struct_type {.a: %i32, .b: %i32, .c: %i32} [concrete = constants.%struct_type.a.b.c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %struct_copy: ref %struct_type.a.b.c = ref_binding struct_copy, %struct_copy.var [concrete = %struct_copy.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %tuple_index.patt: %pattern_type.a98 = ref_binding_pattern tuple_index [concrete]\n// CHECK:STDOUT:     %tuple_index.var_patt: %pattern_type.a98 = var_pattern %tuple_index.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %tuple_index.var: ref %array_type = var %tuple_index.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %array_type.loc8 [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %i32.loc8: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %int_1.loc8: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %array_type.loc8: type = array_type %int_1.loc8, %i32.loc8 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %tuple_index: ref %array_type = ref_binding tuple_index, %tuple_index.var [concrete = %tuple_index.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %struct_access.patt: %pattern_type.a98 = ref_binding_pattern struct_access [concrete]\n// CHECK:STDOUT:     %struct_access.var_patt: %pattern_type.a98 = var_pattern %struct_access.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %struct_access.var: ref %array_type = var %struct_access.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10: type = splice_block %array_type.loc10 [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %i32.loc10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %int_1.loc10: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %array_type.loc10: type = array_type %int_1.loc10, %i32.loc10 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %struct_access: ref %array_type = ref_binding struct_access, %struct_access.var [concrete = %struct_access.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1.loc4: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2.loc4: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc4_35.1: %tuple.type.f94 = tuple_literal (%int_1.loc4, %int_2.loc4) [concrete = constants.%tuple.ad8]\n// CHECK:STDOUT:   %i32.loc4_41: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %i32.loc4_46: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc4_49.1: %tuple.type.24b = tuple_literal (%i32.loc4_41, %i32.loc4_46) [concrete = constants.%tuple.95a]\n// CHECK:STDOUT:   %.loc4_49.2: type = converted %.loc4_49.1, constants.%tuple.type.d07 [concrete = constants.%tuple.type.d07]\n// CHECK:STDOUT:   %impl.elem0.loc4_35.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc4_35.1: <bound method> = bound_method %int_1.loc4, %impl.elem0.loc4_35.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc4_35.1: <specific function> = specific_function %impl.elem0.loc4_35.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc4_35.2: <bound method> = bound_method %int_1.loc4, %specific_fn.loc4_35.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc4_35.1: init %i32 = call %bound_method.loc4_35.2(%int_1.loc4) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc4_35.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc4_35.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc4_35.3: %i32 = converted %int_1.loc4, %.loc4_35.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc4_35.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc4_35.3: <bound method> = bound_method %int_2.loc4, %impl.elem0.loc4_35.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc4_35.2: <specific function> = specific_function %impl.elem0.loc4_35.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc4_35.4: <bound method> = bound_method %int_2.loc4, %specific_fn.loc4_35.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc4_35.2: init %i32 = call %bound_method.loc4_35.4(%int_2.loc4) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc4_35.4: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc4_35.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc4_35.5: %i32 = converted %int_2.loc4, %.loc4_35.4 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %tuple.loc4: %tuple.type.d07 = tuple_value (%.loc4_35.3, %.loc4_35.5) [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:   %.loc4_37.1: %tuple.type.d07 = converted %.loc4_35.1, %tuple.loc4 [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:   %tuple.elem0.loc4_37.1: %i32 = tuple_access %.loc4_37.1, element0 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc4_37.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc4_37.1: <bound method> = bound_method %tuple.elem0.loc4_37.1, %impl.elem0.loc4_37.1 [concrete = constants.%Int.as.Copy.impl.Op.bound.ee3]\n// CHECK:STDOUT:   %specific_fn.loc4_37.1: <specific function> = specific_function %impl.elem0.loc4_37.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc4_37.2: <bound method> = bound_method %tuple.elem0.loc4_37.1, %specific_fn.loc4_37.1 [concrete = constants.%bound_method.4d7]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc4_37.1: init %i32 = call %bound_method.loc4_37.2(%tuple.elem0.loc4_37.1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %tuple.elem0.loc4_37.2: ref %i32 = tuple_access file.%tuple_copy.var, element0 [concrete = constants.%tuple.elem0]\n// CHECK:STDOUT:   %.loc4_37.2: init %i32 to %tuple.elem0.loc4_37.2 = in_place_init %Int.as.Copy.impl.Op.call.loc4_37.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %tuple.elem1.loc4_37.1: %i32 = tuple_access %.loc4_37.1, element1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %impl.elem0.loc4_37.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc4_37.3: <bound method> = bound_method %tuple.elem1.loc4_37.1, %impl.elem0.loc4_37.2 [concrete = constants.%Int.as.Copy.impl.Op.bound.5e8]\n// CHECK:STDOUT:   %specific_fn.loc4_37.2: <specific function> = specific_function %impl.elem0.loc4_37.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc4_37.4: <bound method> = bound_method %tuple.elem1.loc4_37.1, %specific_fn.loc4_37.2 [concrete = constants.%bound_method.f15]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc4_37.2: init %i32 = call %bound_method.loc4_37.4(%tuple.elem1.loc4_37.1) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %tuple.elem1.loc4_37.2: ref %i32 = tuple_access file.%tuple_copy.var, element1 [concrete = constants.%tuple.elem1]\n// CHECK:STDOUT:   %.loc4_37.3: init %i32 to %tuple.elem1.loc4_37.2 = in_place_init %Int.as.Copy.impl.Op.call.loc4_37.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc4_37.4: init %tuple.type.d07 to file.%tuple_copy.var = tuple_init (%.loc4_37.2, %.loc4_37.3) [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:   %.loc4_1: init %tuple.type.d07 = converted %.loc4_37.1, %.loc4_37.4 [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:   assign file.%tuple_copy.var, %.loc4_1\n// CHECK:STDOUT:   %int_3.loc6: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %int_2.loc6: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %int_1.loc6: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc6_71.1: %struct_type.c.b.a = struct_literal (%int_3.loc6, %int_2.loc6, %int_1.loc6) [concrete = constants.%struct.c75]\n// CHECK:STDOUT:   %i32.loc6_81: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %i32.loc6_90: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %i32.loc6_99: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %struct_type.b.a.c: type = struct_type {.b: %i32, .a: %i32, .c: %i32} [concrete = constants.%struct_type.b.a.c]\n// CHECK:STDOUT:   %impl.elem0.loc6_71.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc6_71.1: <bound method> = bound_method %int_2.loc6, %impl.elem0.loc6_71.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc6_71.1: <specific function> = specific_function %impl.elem0.loc6_71.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_71.2: <bound method> = bound_method %int_2.loc6, %specific_fn.loc6_71.1 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_71.1: init %i32 = call %bound_method.loc6_71.2(%int_2.loc6) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc6_71.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_71.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc6_71.3: %i32 = converted %int_2.loc6, %.loc6_71.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %impl.elem0.loc6_71.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc6_71.3: <bound method> = bound_method %int_1.loc6, %impl.elem0.loc6_71.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc6_71.2: <specific function> = specific_function %impl.elem0.loc6_71.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_71.4: <bound method> = bound_method %int_1.loc6, %specific_fn.loc6_71.2 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_71.2: init %i32 = call %bound_method.loc6_71.4(%int_1.loc6) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc6_71.4: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_71.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc6_71.5: %i32 = converted %int_1.loc6, %.loc6_71.4 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc6_71.3: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc6_71.5: <bound method> = bound_method %int_3.loc6, %impl.elem0.loc6_71.3 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:   %specific_fn.loc6_71.3: <specific function> = specific_function %impl.elem0.loc6_71.3, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_71.6: <bound method> = bound_method %int_3.loc6, %specific_fn.loc6_71.3 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_71.3: init %i32 = call %bound_method.loc6_71.6(%int_3.loc6) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc6_71.6: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_71.3 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc6_71.7: %i32 = converted %int_3.loc6, %.loc6_71.6 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %struct.loc6: %struct_type.b.a.c = struct_value (%.loc6_71.3, %.loc6_71.5, %.loc6_71.7) [concrete = constants.%struct.21d]\n// CHECK:STDOUT:   %.loc6_73.1: %struct_type.b.a.c = converted %.loc6_71.1, %struct.loc6 [concrete = constants.%struct.21d]\n// CHECK:STDOUT:   %.loc6_73.2: %i32 = struct_access %.loc6_73.1, element1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc6_73.1: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc6_73.1: <bound method> = bound_method %.loc6_73.2, %impl.elem0.loc6_73.1 [concrete = constants.%Int.as.Copy.impl.Op.bound.ee3]\n// CHECK:STDOUT:   %specific_fn.loc6_73.1: <specific function> = specific_function %impl.elem0.loc6_73.1, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_73.2: <bound method> = bound_method %.loc6_73.2, %specific_fn.loc6_73.1 [concrete = constants.%bound_method.4d7]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc6_73.1: init %i32 = call %bound_method.loc6_73.2(%.loc6_73.2) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc6_73.3: ref %i32 = struct_access file.%struct_copy.var, element1 [concrete = constants.%.460]\n// CHECK:STDOUT:   %.loc6_73.4: init %i32 to %.loc6_73.3 = in_place_init %Int.as.Copy.impl.Op.call.loc6_73.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc6_73.5: %i32 = struct_access %.loc6_73.1, element0 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %impl.elem0.loc6_73.2: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc6_73.3: <bound method> = bound_method %.loc6_73.5, %impl.elem0.loc6_73.2 [concrete = constants.%Int.as.Copy.impl.Op.bound.5e8]\n// CHECK:STDOUT:   %specific_fn.loc6_73.2: <specific function> = specific_function %impl.elem0.loc6_73.2, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_73.4: <bound method> = bound_method %.loc6_73.5, %specific_fn.loc6_73.2 [concrete = constants.%bound_method.f15]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc6_73.2: init %i32 = call %bound_method.loc6_73.4(%.loc6_73.5) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc6_73.6: ref %i32 = struct_access file.%struct_copy.var, element0 [concrete = constants.%.61f]\n// CHECK:STDOUT:   %.loc6_73.7: init %i32 to %.loc6_73.6 = in_place_init %Int.as.Copy.impl.Op.call.loc6_73.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc6_73.8: %i32 = struct_access %.loc6_73.1, element2 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %impl.elem0.loc6_73.3: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc6_73.5: <bound method> = bound_method %.loc6_73.8, %impl.elem0.loc6_73.3 [concrete = constants.%Int.as.Copy.impl.Op.bound.ecc]\n// CHECK:STDOUT:   %specific_fn.loc6_73.3: <specific function> = specific_function %impl.elem0.loc6_73.3, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_73.6: <bound method> = bound_method %.loc6_73.8, %specific_fn.loc6_73.3 [concrete = constants.%bound_method.4f5]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call.loc6_73.3: init %i32 = call %bound_method.loc6_73.6(%.loc6_73.8) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc6_73.9: ref %i32 = struct_access file.%struct_copy.var, element2 [concrete = constants.%.f68]\n// CHECK:STDOUT:   %.loc6_73.10: init %i32 to %.loc6_73.9 = in_place_init %Int.as.Copy.impl.Op.call.loc6_73.3 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc6_73.11: init %struct_type.a.b.c to file.%struct_copy.var = struct_init (%.loc6_73.4, %.loc6_73.7, %.loc6_73.10) [concrete = constants.%struct.cff]\n// CHECK:STDOUT:   %.loc6_1: init %struct_type.a.b.c = converted %.loc6_73.1, %.loc6_73.11 [concrete = constants.%struct.cff]\n// CHECK:STDOUT:   assign file.%struct_copy.var, %.loc6_1\n// CHECK:STDOUT:   %int_0.loc8_35: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %.loc8_37.1: %tuple.type.985 = tuple_literal (%int_0.loc8_35) [concrete = constants.%tuple.4f2]\n// CHECK:STDOUT:   %i32.loc8: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5]\n// CHECK:STDOUT:   %int_7: Core.IntLiteral = int_value 7 [concrete = constants.%int_7]\n// CHECK:STDOUT:   %int_1.loc8: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_9: Core.IntLiteral = int_value 9 [concrete = constants.%int_9]\n// CHECK:STDOUT:   %.loc8_64.1: %tuple.type.d46 = tuple_literal (%int_5, %int_7, %int_1.loc8, %int_9) [concrete = constants.%tuple.869]\n// CHECK:STDOUT:   %int_2.loc8: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %tuple.loc8: %tuple.type.d46 = tuple_value (%int_5, %int_7, %int_1.loc8, %int_9) [concrete = constants.%tuple.869]\n// CHECK:STDOUT:   %.loc8_64.2: %tuple.type.d46 = converted %.loc8_64.1, %tuple.loc8 [concrete = constants.%tuple.869]\n// CHECK:STDOUT:   %tuple.elem2: Core.IntLiteral = tuple_access %.loc8_64.2, element2 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %array_type.loc8: type = array_type %tuple.elem2, %i32.loc8 [concrete = constants.%array_type]\n// CHECK:STDOUT:   %impl.elem0.loc8: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc8_37.1: <bound method> = bound_method %int_0.loc8_35, %impl.elem0.loc8 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.897]\n// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_37.2: <bound method> = bound_method %int_0.loc8_35, %specific_fn.loc8 [concrete = constants.%bound_method.d2e]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %i32 = call %bound_method.loc8_37.2(%int_0.loc8_35) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc8_37.2: init %i32 = converted %int_0.loc8_35, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc8_1: ref %array_type = splice_block file.%tuple_index.var [concrete = file.%tuple_index.var] {}\n// CHECK:STDOUT:   %int_0.loc8_37: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %.loc8_37.3: ref %i32 = array_index %.loc8_1, %int_0.loc8_37\n// CHECK:STDOUT:   %.loc8_37.4: init %i32 to %.loc8_37.3 = in_place_init %.loc8_37.2 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc8_37.5: init %array_type to %.loc8_1 = array_init (%.loc8_37.4) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc8_39: init %array_type = converted %.loc8_37.1, %.loc8_37.5 [concrete = constants.%array]\n// CHECK:STDOUT:   assign file.%tuple_index.var, %.loc8_39\n// CHECK:STDOUT:   %int_0.loc10_37: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %.loc10_39.1: %tuple.type.985 = tuple_literal (%int_0.loc10_37) [concrete = constants.%tuple.4f2]\n// CHECK:STDOUT:   %i32.loc10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %int_3.loc10: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %int_1.loc10: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc10_70.1: %struct_type.a.b = struct_literal (%int_3.loc10, %int_1.loc10) [concrete = constants.%struct.a81]\n// CHECK:STDOUT:   %struct.loc10: %struct_type.a.b = struct_value (%int_3.loc10, %int_1.loc10) [concrete = constants.%struct.a81]\n// CHECK:STDOUT:   %.loc10_70.2: %struct_type.a.b = converted %.loc10_70.1, %struct.loc10 [concrete = constants.%struct.a81]\n// CHECK:STDOUT:   %.loc10_71: Core.IntLiteral = struct_access %.loc10_70.2, element1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %array_type.loc10: type = array_type %.loc10_71, %i32.loc10 [concrete = constants.%array_type]\n// CHECK:STDOUT:   %impl.elem0.loc10: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc10_39.1: <bound method> = bound_method %int_0.loc10_37, %impl.elem0.loc10 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.897]\n// CHECK:STDOUT:   %specific_fn.loc10: <specific function> = specific_function %impl.elem0.loc10, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_39.2: <bound method> = bound_method %int_0.loc10_37, %specific_fn.loc10 [concrete = constants.%bound_method.d2e]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10: init %i32 = call %bound_method.loc10_39.2(%int_0.loc10_37) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc10_39.2: init %i32 = converted %int_0.loc10_37, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc10_1: ref %array_type = splice_block file.%struct_access.var [concrete = file.%struct_access.var] {}\n// CHECK:STDOUT:   %int_0.loc10_39: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %.loc10_39.3: ref %i32 = array_index %.loc10_1, %int_0.loc10_39\n// CHECK:STDOUT:   %.loc10_39.4: init %i32 to %.loc10_39.3 = in_place_init %.loc10_39.2 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc10_39.5: init %array_type to %.loc10_1 = array_init (%.loc10_39.4) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc10_41: init %array_type = converted %.loc10_39.1, %.loc10_39.5 [concrete = constants.%array]\n// CHECK:STDOUT:   assign file.%struct_access.var, %.loc10_41\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_array_temporary.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %array_type.0cb: type = array_type %int_1.5b8, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.a98: type = pattern_type %array_type.0cb [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.4f2: %tuple.type.985 = tuple_value (%int_0) [concrete]\n// CHECK:STDOUT:   %int_5.64b: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %int_7.29f: Core.IntLiteral = int_value 7 [concrete]\n// CHECK:STDOUT:   %int_9.988: Core.IntLiteral = int_value 9 [concrete]\n// CHECK:STDOUT:   %tuple.type.d46: type = tuple_type (Core.IntLiteral, Core.IntLiteral, Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.869: %tuple.type.d46 = tuple_value (%int_5.64b, %int_7.29f, %int_1.5b8, %int_9.988) [concrete]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %array_type.f32: type = array_type %int_4, %i32 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.e9d: <bound method> = bound_method %int_5.64b, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_5.0f6: %i32 = int_value 5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.1e0: <bound method> = bound_method %int_7.29f, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.bf2: <bound method> = bound_method %int_7.29f, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_7.0b1: %i32 = int_value 7 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.87d: <bound method> = bound_method %int_9.988, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.661: <bound method> = bound_method %int_9.988, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_9.f88: %i32 = int_value 9 [concrete]\n// CHECK:STDOUT:   %array: %array_type.f32 = tuple_value (%int_5.0f6, %int_7.0b1, %int_1.5d2, %int_9.f88) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %array_index.patt: %pattern_type.a98 = ref_binding_pattern array_index [concrete]\n// CHECK:STDOUT:     %array_index.var_patt: %pattern_type.a98 = var_pattern %array_index.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %array_index.var: ref %array_type.0cb = var %array_index.var_patt [concrete]\n// CHECK:STDOUT:   %.loc9: type = splice_block %array_type [concrete = constants.%array_type.0cb] {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %array_type: type = array_type %int_1, %i32 [concrete = constants.%array_type.0cb]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %array_index: ref %array_type.0cb = ref_binding array_index, %array_index.var [concrete = %array_index.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_0.loc9_35: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc9_37: %tuple.type.985 = tuple_literal (%int_0.loc9_35) [concrete = constants.%tuple.4f2]\n// CHECK:STDOUT:   %i32.loc9_48: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]\n// CHECK:STDOUT:   %int_7: Core.IntLiteral = int_value 7 [concrete = constants.%int_7.29f]\n// CHECK:STDOUT:   %int_1.loc9_61: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_9: Core.IntLiteral = int_value 9 [concrete = constants.%int_9.988]\n// CHECK:STDOUT:   %.loc9_65.1: %tuple.type.d46 = tuple_literal (%int_5, %int_7, %int_1.loc9_61, %int_9) [concrete = constants.%tuple.869]\n// CHECK:STDOUT:   %i32.loc9_76: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4]\n// CHECK:STDOUT:   %array_type: type = array_type %int_4, %i32.loc9_76 [concrete = constants.%array_type.f32]\n// CHECK:STDOUT:   %impl.elem0.loc9_65.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc9_65.1: <bound method> = bound_method %int_5, %impl.elem0.loc9_65.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.005]\n// CHECK:STDOUT:   %specific_fn.loc9_65.1: <specific function> = specific_function %impl.elem0.loc9_65.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_65.2: <bound method> = bound_method %int_5, %specific_fn.loc9_65.1 [concrete = constants.%bound_method.e9d]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_65.1: init %i32 = call %bound_method.loc9_65.2(%int_5) [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc9_65.2: init %i32 = converted %int_5, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_65.1 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %.loc9_65.3: ref %array_type.f32 = temporary_storage\n// CHECK:STDOUT:   %int_0.loc9_65: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc9_65.4: ref %i32 = array_index %.loc9_65.3, %int_0.loc9_65\n// CHECK:STDOUT:   %.loc9_65.5: init %i32 to %.loc9_65.4 = in_place_init %.loc9_65.2 [concrete = constants.%int_5.0f6]\n// CHECK:STDOUT:   %impl.elem0.loc9_65.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc9_65.3: <bound method> = bound_method %int_7, %impl.elem0.loc9_65.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.1e0]\n// CHECK:STDOUT:   %specific_fn.loc9_65.2: <specific function> = specific_function %impl.elem0.loc9_65.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_65.4: <bound method> = bound_method %int_7, %specific_fn.loc9_65.2 [concrete = constants.%bound_method.bf2]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_65.2: init %i32 = call %bound_method.loc9_65.4(%int_7) [concrete = constants.%int_7.0b1]\n// CHECK:STDOUT:   %.loc9_65.6: init %i32 = converted %int_7, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_65.2 [concrete = constants.%int_7.0b1]\n// CHECK:STDOUT:   %int_1.loc9_65: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc9_65.7: ref %i32 = array_index %.loc9_65.3, %int_1.loc9_65\n// CHECK:STDOUT:   %.loc9_65.8: init %i32 to %.loc9_65.7 = in_place_init %.loc9_65.6 [concrete = constants.%int_7.0b1]\n// CHECK:STDOUT:   %impl.elem0.loc9_65.3: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc9_65.5: <bound method> = bound_method %int_1.loc9_61, %impl.elem0.loc9_65.3 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc9_65.3: <specific function> = specific_function %impl.elem0.loc9_65.3, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_65.6: <bound method> = bound_method %int_1.loc9_61, %specific_fn.loc9_65.3 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_65.3: init %i32 = call %bound_method.loc9_65.6(%int_1.loc9_61) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc9_65.9: init %i32 = converted %int_1.loc9_61, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_65.3 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %int_2.loc9_65: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc9_65.10: ref %i32 = array_index %.loc9_65.3, %int_2.loc9_65\n// CHECK:STDOUT:   %.loc9_65.11: init %i32 to %.loc9_65.10 = in_place_init %.loc9_65.9 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc9_65.4: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc9_65.7: <bound method> = bound_method %int_9, %impl.elem0.loc9_65.4 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.87d]\n// CHECK:STDOUT:   %specific_fn.loc9_65.4: <specific function> = specific_function %impl.elem0.loc9_65.4, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_65.8: <bound method> = bound_method %int_9, %specific_fn.loc9_65.4 [concrete = constants.%bound_method.661]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_65.4: init %i32 = call %bound_method.loc9_65.8(%int_9) [concrete = constants.%int_9.f88]\n// CHECK:STDOUT:   %.loc9_65.12: init %i32 = converted %int_9, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_65.4 [concrete = constants.%int_9.f88]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:   %.loc9_65.13: ref %i32 = array_index %.loc9_65.3, %int_3\n// CHECK:STDOUT:   %.loc9_65.14: init %i32 to %.loc9_65.13 = in_place_init %.loc9_65.12 [concrete = constants.%int_9.f88]\n// CHECK:STDOUT:   %.loc9_65.15: init %array_type.f32 to %.loc9_65.3 = array_init (%.loc9_65.5, %.loc9_65.8, %.loc9_65.11, %.loc9_65.14) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc9_67.1: init %array_type.f32 = converted %.loc9_65.1, %.loc9_65.15 [concrete = constants.%array]\n// CHECK:STDOUT:   %int_2.loc9_85: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc9_67.2: ref %array_type.f32 = temporary %.loc9_65.3, %.loc9_67.1\n// CHECK:STDOUT:   %impl.elem0.loc9_85: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc9_85.1: <bound method> = bound_method %int_2.loc9_85, %impl.elem0.loc9_85 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc9_85: <specific function> = specific_function %impl.elem0.loc9_85, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_85.2: <bound method> = bound_method %int_2.loc9_85, %specific_fn.loc9_85 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_85: init %i32 = call %bound_method.loc9_85.2(%int_2.loc9_85) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc9_85.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc9_85 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc9_85.2: %i32 = converted %int_2.loc9_85, %.loc9_85.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc9_86.1: ref %i32 = array_index %.loc9_67.2, %.loc9_85.2\n// CHECK:STDOUT:   %.loc9_86.2: %i32 = acquire_value %.loc9_86.1\n// CHECK:STDOUT:   assign file.%array_index.var, <error>\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- symbolic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %const: type = const_type %T [symbolic]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%ptr.e8f, %const) [symbolic]\n// CHECK:STDOUT:   %tuple.type.3c8: type = tuple_type (%ptr.e8f, %const) [symbolic]\n// CHECK:STDOUT:   %require_complete.666: <witness> = require_complete_type %tuple.type.3c8 [symbolic]\n// CHECK:STDOUT:   %pattern_type.4ac: type = pattern_type %tuple.type.3c8 [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %.f7e: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%tuple.type.3c8) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.2ad: <witness> = lookup_impl_witness %tuple.type.3c8, @DefaultOrUnformed [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.9a0: %DefaultOrUnformed.type = facet_value %tuple.type.3c8, (%DefaultOrUnformed.lookup_impl_witness.2ad) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.0af: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.9a0) [symbolic]\n// CHECK:STDOUT:   %.246: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.0af, %DefaultOrUnformed.facet.9a0 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.c6f: %.246 = impl_witness_access %DefaultOrUnformed.lookup_impl_witness.2ad, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.58b: <specific function> = specific_impl_function %impl.elem0.c6f, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.9a0) [symbolic]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %T} [symbolic]\n// CHECK:STDOUT:   %require_complete.5d6: <witness> = require_complete_type %struct_type.a [symbolic]\n// CHECK:STDOUT:   %pattern_type.7b9: type = pattern_type %struct_type.a [symbolic]\n// CHECK:STDOUT:   %.d26: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%struct_type.a) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.169: <witness> = lookup_impl_witness %struct_type.a, @DefaultOrUnformed [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.ca5: %DefaultOrUnformed.type = facet_value %struct_type.a, (%DefaultOrUnformed.lookup_impl_witness.169) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.0c5: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.ca5) [symbolic]\n// CHECK:STDOUT:   %.9ac: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.0c5, %DefaultOrUnformed.facet.ca5 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.e9c: %.9ac = impl_witness_access %DefaultOrUnformed.lookup_impl_witness.169, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.cf6: <specific function> = specific_impl_function %impl.elem0.e9c, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.ca5) [symbolic]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %array_type.742: type = array_type %int_5, %T [symbolic]\n// CHECK:STDOUT:   %require_complete.345: <witness> = require_complete_type %array_type.742 [symbolic]\n// CHECK:STDOUT:   %pattern_type.d52: type = pattern_type %array_type.742 [symbolic]\n// CHECK:STDOUT:   %.617: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.742) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.945: <witness> = lookup_impl_witness %array_type.742, @DefaultOrUnformed [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.ad6: %DefaultOrUnformed.type = facet_value %array_type.742, (%DefaultOrUnformed.lookup_impl_witness.945) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.2f0: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.ad6) [symbolic]\n// CHECK:STDOUT:   %.544: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.2f0, %DefaultOrUnformed.facet.ad6 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.97e: %.544 = impl_witness_access %DefaultOrUnformed.lookup_impl_witness.945, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.261: <specific function> = specific_impl_function %impl.elem0.97e, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.ad6) [symbolic]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness.b29: <witness> = lookup_impl_witness %array_type.742, @Destroy [symbolic]\n// CHECK:STDOUT:   %Destroy.facet.ddc: %Destroy.type = facet_value %array_type.742, (%Destroy.lookup_impl_witness.b29) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.3c6: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.ddc) [symbolic]\n// CHECK:STDOUT:   %.950: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.3c6, %Destroy.facet.ddc [symbolic]\n// CHECK:STDOUT:   %impl.elem0.fa5: %.950 = impl_witness_access %Destroy.lookup_impl_witness.b29, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.ede: <specific function> = specific_impl_function %impl.elem0.fa5, @Destroy.WithSelf.Op(%Destroy.facet.ddc) [symbolic]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness.bed: <witness> = lookup_impl_witness %struct_type.a, @Destroy [symbolic]\n// CHECK:STDOUT:   %Destroy.facet.d21: %Destroy.type = facet_value %struct_type.a, (%Destroy.lookup_impl_witness.bed) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.873: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.d21) [symbolic]\n// CHECK:STDOUT:   %.511: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.873, %Destroy.facet.d21 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.12c: %.511 = impl_witness_access %Destroy.lookup_impl_witness.bed, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.c3a: <specific function> = specific_impl_function %impl.elem0.12c, @Destroy.WithSelf.Op(%Destroy.facet.d21) [symbolic]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness.7eb: <witness> = lookup_impl_witness %tuple.type.3c8, @Destroy [symbolic]\n// CHECK:STDOUT:   %Destroy.facet.66d: %Destroy.type = facet_value %tuple.type.3c8, (%Destroy.lookup_impl_witness.7eb) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.f23: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.66d) [symbolic]\n// CHECK:STDOUT:   %.f20: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.f23, %Destroy.facet.66d [symbolic]\n// CHECK:STDOUT:   %impl.elem0.f5f: %.f20 = impl_witness_access %Destroy.lookup_impl_witness.7eb, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.87c: <specific function> = specific_impl_function %impl.elem0.f5f, @Destroy.WithSelf.Op(%Destroy.facet.66d) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %N.5de: %i32 = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %From: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.2ed: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%From) [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.d29: %Int.as.ImplicitAs.impl.Convert.type.2ed = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.640: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.ea2, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.240: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.dd4: %Int.as.ImplicitAs.impl.Convert.type.240 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.139 = facet_value %i32, (%ImplicitAs.impl_witness.640) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.462: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.0a7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.462, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.dd4 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Int.as.ImplicitAs.impl.Convert.dd4, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method(%N.5de) [symbolic]\n// CHECK:STDOUT:   %array_type.2ec: type = array_type %Int.as.ImplicitAs.impl.Convert.call, %i32 [symbolic]\n// CHECK:STDOUT:   %require_complete.5d1: <witness> = require_complete_type %array_type.2ec [symbolic]\n// CHECK:STDOUT:   %pattern_type.99c: type = pattern_type %array_type.2ec [symbolic]\n// CHECK:STDOUT:   %.d6f: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.2ec) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.162: <witness> = lookup_impl_witness %array_type.2ec, @DefaultOrUnformed [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.0c7: %DefaultOrUnformed.type = facet_value %array_type.2ec, (%DefaultOrUnformed.lookup_impl_witness.162) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.839: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.0c7) [symbolic]\n// CHECK:STDOUT:   %.78e: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.839, %DefaultOrUnformed.facet.0c7 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.82a: %.78e = impl_witness_access %DefaultOrUnformed.lookup_impl_witness.162, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.fcf: <specific function> = specific_impl_function %impl.elem0.82a, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.0c7) [symbolic]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness.f5c: <witness> = lookup_impl_witness %array_type.2ec, @Destroy [symbolic]\n// CHECK:STDOUT:   %Destroy.facet.d1e: %Destroy.type = facet_value %array_type.2ec, (%Destroy.lookup_impl_witness.f5c) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.ff9: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.d1e) [symbolic]\n// CHECK:STDOUT:   %.63e: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.ff9, %Destroy.facet.d1e [symbolic]\n// CHECK:STDOUT:   %impl.elem0.2bf: %.63e = impl_witness_access %Destroy.lookup_impl_witness.f5c, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.0a5: <specific function> = specific_impl_function %impl.elem0.2bf, @Destroy.WithSelf.Op(%Destroy.facet.d1e) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.0bc: @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert.type (%Int.as.ImplicitAs.impl.Convert.type.2ed) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert (constants.%Int.as.ImplicitAs.impl.Convert.d29)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.ea2 = impl_witness_table (%Core.import_ref.0bc), @Int.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_6.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ptr.loc6_19.2: type = ptr_type %T.loc4_6.1 [symbolic = %ptr.loc6_19.2 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %const.loc6_22.2: type = const_type %T.loc4_6.1 [symbolic = %const.loc6_22.2 (constants.%const)]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%ptr.loc6_19.2, %const.loc6_22.2) [symbolic = %tuple (constants.%tuple)]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%ptr.loc6_19.2, %const.loc6_22.2) [symbolic = %tuple.type (constants.%tuple.type.3c8)]\n// CHECK:STDOUT:   %require_complete.loc6: <witness> = require_complete_type %tuple.type [symbolic = %require_complete.loc6 (constants.%require_complete.666)]\n// CHECK:STDOUT:   %pattern_type.loc6: type = pattern_type %tuple.type [symbolic = %pattern_type.loc6 (constants.%pattern_type.4ac)]\n// CHECK:STDOUT:   %.loc6_30.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%tuple.type) [symbolic = %.loc6_30.3 (constants.%.f7e)]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.loc6: <witness> = lookup_impl_witness %tuple.type, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness.loc6 (constants.%DefaultOrUnformed.lookup_impl_witness.2ad)]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc6_30.2: %DefaultOrUnformed.type = facet_value %tuple.type, (%DefaultOrUnformed.lookup_impl_witness.loc6) [symbolic = %DefaultOrUnformed.facet.loc6_30.2 (constants.%DefaultOrUnformed.facet.9a0)]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.loc6: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc6_30.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type.loc6 (constants.%DefaultOrUnformed.WithSelf.Op.type.0af)]\n// CHECK:STDOUT:   %.loc6_30.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.loc6, %DefaultOrUnformed.facet.loc6_30.2 [symbolic = %.loc6_30.4 (constants.%.246)]\n// CHECK:STDOUT:   %impl.elem0.loc6_30.2: @F.%.loc6_30.4 (%.246) = impl_witness_access %DefaultOrUnformed.lookup_impl_witness.loc6, element0 [symbolic = %impl.elem0.loc6_30.2 (constants.%impl.elem0.c6f)]\n// CHECK:STDOUT:   %specific_impl_fn.loc6_30.2: <specific function> = specific_impl_function %impl.elem0.loc6_30.2, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.loc6_30.2) [symbolic = %specific_impl_fn.loc6_30.2 (constants.%specific_impl_fn.58b)]\n// CHECK:STDOUT:   %struct_type.a.loc7_23.2: type = struct_type {.a: @F.%T.loc4_6.1 (%T)} [symbolic = %struct_type.a.loc7_23.2 (constants.%struct_type.a)]\n// CHECK:STDOUT:   %require_complete.loc7: <witness> = require_complete_type %struct_type.a.loc7_23.2 [symbolic = %require_complete.loc7 (constants.%require_complete.5d6)]\n// CHECK:STDOUT:   %pattern_type.loc7: type = pattern_type %struct_type.a.loc7_23.2 [symbolic = %pattern_type.loc7 (constants.%pattern_type.7b9)]\n// CHECK:STDOUT:   %.loc7_24.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%struct_type.a.loc7_23.2) [symbolic = %.loc7_24.3 (constants.%.d26)]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.loc7: <witness> = lookup_impl_witness %struct_type.a.loc7_23.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness.loc7 (constants.%DefaultOrUnformed.lookup_impl_witness.169)]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc7_24.2: %DefaultOrUnformed.type = facet_value %struct_type.a.loc7_23.2, (%DefaultOrUnformed.lookup_impl_witness.loc7) [symbolic = %DefaultOrUnformed.facet.loc7_24.2 (constants.%DefaultOrUnformed.facet.ca5)]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.loc7: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc7_24.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type.loc7 (constants.%DefaultOrUnformed.WithSelf.Op.type.0c5)]\n// CHECK:STDOUT:   %.loc7_24.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.loc7, %DefaultOrUnformed.facet.loc7_24.2 [symbolic = %.loc7_24.4 (constants.%.9ac)]\n// CHECK:STDOUT:   %impl.elem0.loc7_24.2: @F.%.loc7_24.4 (%.9ac) = impl_witness_access %DefaultOrUnformed.lookup_impl_witness.loc7, element0 [symbolic = %impl.elem0.loc7_24.2 (constants.%impl.elem0.e9c)]\n// CHECK:STDOUT:   %specific_impl_fn.loc7_24.2: <specific function> = specific_impl_function %impl.elem0.loc7_24.2, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.loc7_24.2) [symbolic = %specific_impl_fn.loc7_24.2 (constants.%specific_impl_fn.cf6)]\n// CHECK:STDOUT:   %array_type.loc8_27.2: type = array_type constants.%int_5, %T.loc4_6.1 [symbolic = %array_type.loc8_27.2 (constants.%array_type.742)]\n// CHECK:STDOUT:   %require_complete.loc8: <witness> = require_complete_type %array_type.loc8_27.2 [symbolic = %require_complete.loc8 (constants.%require_complete.345)]\n// CHECK:STDOUT:   %pattern_type.loc8: type = pattern_type %array_type.loc8_27.2 [symbolic = %pattern_type.loc8 (constants.%pattern_type.d52)]\n// CHECK:STDOUT:   %.loc8_28.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.loc8_27.2) [symbolic = %.loc8_28.3 (constants.%.617)]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness.loc8: <witness> = lookup_impl_witness %array_type.loc8_27.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness.loc8 (constants.%DefaultOrUnformed.lookup_impl_witness.945)]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc8_28.2: %DefaultOrUnformed.type = facet_value %array_type.loc8_27.2, (%DefaultOrUnformed.lookup_impl_witness.loc8) [symbolic = %DefaultOrUnformed.facet.loc8_28.2 (constants.%DefaultOrUnformed.facet.ad6)]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.loc8: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc8_28.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type.loc8 (constants.%DefaultOrUnformed.WithSelf.Op.type.2f0)]\n// CHECK:STDOUT:   %.loc8_28.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.loc8, %DefaultOrUnformed.facet.loc8_28.2 [symbolic = %.loc8_28.4 (constants.%.544)]\n// CHECK:STDOUT:   %impl.elem0.loc8_28.2: @F.%.loc8_28.4 (%.544) = impl_witness_access %DefaultOrUnformed.lookup_impl_witness.loc8, element0 [symbolic = %impl.elem0.loc8_28.2 (constants.%impl.elem0.97e)]\n// CHECK:STDOUT:   %specific_impl_fn.loc8_28.2: <specific function> = specific_impl_function %impl.elem0.loc8_28.2, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.loc8_28.2) [symbolic = %specific_impl_fn.loc8_28.2 (constants.%specific_impl_fn.261)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness.loc8: <witness> = lookup_impl_witness %array_type.loc8_27.2, @Destroy [symbolic = %Destroy.lookup_impl_witness.loc8 (constants.%Destroy.lookup_impl_witness.b29)]\n// CHECK:STDOUT:   %Destroy.facet.loc8: %Destroy.type = facet_value %array_type.loc8_27.2, (%Destroy.lookup_impl_witness.loc8) [symbolic = %Destroy.facet.loc8 (constants.%Destroy.facet.ddc)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.loc8: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.loc8) [symbolic = %Destroy.WithSelf.Op.type.loc8 (constants.%Destroy.WithSelf.Op.type.3c6)]\n// CHECK:STDOUT:   %.loc8_3.2: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.loc8, %Destroy.facet.loc8 [symbolic = %.loc8_3.2 (constants.%.950)]\n// CHECK:STDOUT:   %impl.elem0.loc8_3.2: @F.%.loc8_3.2 (%.950) = impl_witness_access %Destroy.lookup_impl_witness.loc8, element0 [symbolic = %impl.elem0.loc8_3.2 (constants.%impl.elem0.fa5)]\n// CHECK:STDOUT:   %specific_impl_fn.loc8_3.2: <specific function> = specific_impl_function %impl.elem0.loc8_3.2, @Destroy.WithSelf.Op(%Destroy.facet.loc8) [symbolic = %specific_impl_fn.loc8_3.2 (constants.%specific_impl_fn.ede)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness.loc7: <witness> = lookup_impl_witness %struct_type.a.loc7_23.2, @Destroy [symbolic = %Destroy.lookup_impl_witness.loc7 (constants.%Destroy.lookup_impl_witness.bed)]\n// CHECK:STDOUT:   %Destroy.facet.loc7: %Destroy.type = facet_value %struct_type.a.loc7_23.2, (%Destroy.lookup_impl_witness.loc7) [symbolic = %Destroy.facet.loc7 (constants.%Destroy.facet.d21)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.loc7: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.loc7) [symbolic = %Destroy.WithSelf.Op.type.loc7 (constants.%Destroy.WithSelf.Op.type.873)]\n// CHECK:STDOUT:   %.loc7_3: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.loc7, %Destroy.facet.loc7 [symbolic = %.loc7_3 (constants.%.511)]\n// CHECK:STDOUT:   %impl.elem0.loc7_3.2: @F.%.loc7_3 (%.511) = impl_witness_access %Destroy.lookup_impl_witness.loc7, element0 [symbolic = %impl.elem0.loc7_3.2 (constants.%impl.elem0.12c)]\n// CHECK:STDOUT:   %specific_impl_fn.loc7_3.2: <specific function> = specific_impl_function %impl.elem0.loc7_3.2, @Destroy.WithSelf.Op(%Destroy.facet.loc7) [symbolic = %specific_impl_fn.loc7_3.2 (constants.%specific_impl_fn.c3a)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness.loc6: <witness> = lookup_impl_witness %tuple.type, @Destroy [symbolic = %Destroy.lookup_impl_witness.loc6 (constants.%Destroy.lookup_impl_witness.7eb)]\n// CHECK:STDOUT:   %Destroy.facet.loc6: %Destroy.type = facet_value %tuple.type, (%Destroy.lookup_impl_witness.loc6) [symbolic = %Destroy.facet.loc6 (constants.%Destroy.facet.66d)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.loc6: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.loc6) [symbolic = %Destroy.WithSelf.Op.type.loc6 (constants.%Destroy.WithSelf.Op.type.f23)]\n// CHECK:STDOUT:   %.loc6_3.2: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.loc6, %Destroy.facet.loc6 [symbolic = %.loc6_3.2 (constants.%.f20)]\n// CHECK:STDOUT:   %impl.elem0.loc6_3.2: @F.%.loc6_3.2 (%.f20) = impl_witness_access %Destroy.lookup_impl_witness.loc6, element0 [symbolic = %impl.elem0.loc6_3.2 (constants.%impl.elem0.f5f)]\n// CHECK:STDOUT:   %specific_impl_fn.loc6_3.2: <specific function> = specific_impl_function %impl.elem0.loc6_3.2, @Destroy.WithSelf.Op(%Destroy.facet.loc6) [symbolic = %specific_impl_fn.loc6_3.2 (constants.%specific_impl_fn.87c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %u.patt: @F.%pattern_type.loc6 (%pattern_type.4ac) = ref_binding_pattern u [concrete]\n// CHECK:STDOUT:       %u.var_patt: @F.%pattern_type.loc6 (%pattern_type.4ac) = var_pattern %u.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %u.var: ref @F.%tuple.type (%tuple.type.3c8) = var %u.var_patt\n// CHECK:STDOUT:     %DefaultOrUnformed.facet.loc6_30.1: %DefaultOrUnformed.type = facet_value constants.%tuple.type.3c8, (constants.%DefaultOrUnformed.lookup_impl_witness.2ad) [symbolic = %DefaultOrUnformed.facet.loc6_30.2 (constants.%DefaultOrUnformed.facet.9a0)]\n// CHECK:STDOUT:     %.loc6_30.1: %DefaultOrUnformed.type = converted constants.%tuple.type.3c8, %DefaultOrUnformed.facet.loc6_30.1 [symbolic = %DefaultOrUnformed.facet.loc6_30.2 (constants.%DefaultOrUnformed.facet.9a0)]\n// CHECK:STDOUT:     %as_type.loc6: type = facet_access_type %.loc6_30.1 [symbolic = %tuple.type (constants.%tuple.type.3c8)]\n// CHECK:STDOUT:     %.loc6_30.2: type = converted %.loc6_30.1, %as_type.loc6 [symbolic = %tuple.type (constants.%tuple.type.3c8)]\n// CHECK:STDOUT:     %impl.elem0.loc6_30.1: @F.%.loc6_30.4 (%.246) = impl_witness_access constants.%DefaultOrUnformed.lookup_impl_witness.2ad, element0 [symbolic = %impl.elem0.loc6_30.2 (constants.%impl.elem0.c6f)]\n// CHECK:STDOUT:     %specific_impl_fn.loc6_30.1: <specific function> = specific_impl_function %impl.elem0.loc6_30.1, @DefaultOrUnformed.WithSelf.Op(constants.%DefaultOrUnformed.facet.9a0) [symbolic = %specific_impl_fn.loc6_30.2 (constants.%specific_impl_fn.58b)]\n// CHECK:STDOUT:     %.loc6_3.1: ref @F.%tuple.type (%tuple.type.3c8) = splice_block %u.var {}\n// CHECK:STDOUT:     %DefaultOrUnformed.WithSelf.Op.call.loc6: init @F.%tuple.type (%tuple.type.3c8) to %.loc6_3.1 = call %specific_impl_fn.loc6_30.1()\n// CHECK:STDOUT:     assign %u.var, %DefaultOrUnformed.WithSelf.Op.call.loc6\n// CHECK:STDOUT:     %.loc6_29.1: type = splice_block %.loc6_29.3 [symbolic = %tuple.type (constants.%tuple.type.3c8)] {\n// CHECK:STDOUT:       %T.ref.loc6_18: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:       %ptr.loc6_19.1: type = ptr_type %T.ref.loc6_18 [symbolic = %ptr.loc6_19.2 (constants.%ptr.e8f)]\n// CHECK:STDOUT:       %T.ref.loc6_28: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:       %const.loc6_22.1: type = const_type %T.ref.loc6_28 [symbolic = %const.loc6_22.2 (constants.%const)]\n// CHECK:STDOUT:       %.loc6_29.2: %tuple.type.24b = tuple_literal (%ptr.loc6_19.1, %const.loc6_22.1) [symbolic = %tuple (constants.%tuple)]\n// CHECK:STDOUT:       %.loc6_29.3: type = converted %.loc6_29.2, constants.%tuple.type.3c8 [symbolic = %tuple.type (constants.%tuple.type.3c8)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %u: ref @F.%tuple.type (%tuple.type.3c8) = ref_binding u, %u.var\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %v.patt: @F.%pattern_type.loc7 (%pattern_type.7b9) = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:       %v.var_patt: @F.%pattern_type.loc7 (%pattern_type.7b9) = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v.var: ref @F.%struct_type.a.loc7_23.2 (%struct_type.a) = var %v.var_patt\n// CHECK:STDOUT:     %DefaultOrUnformed.facet.loc7_24.1: %DefaultOrUnformed.type = facet_value constants.%struct_type.a, (constants.%DefaultOrUnformed.lookup_impl_witness.169) [symbolic = %DefaultOrUnformed.facet.loc7_24.2 (constants.%DefaultOrUnformed.facet.ca5)]\n// CHECK:STDOUT:     %.loc7_24.1: %DefaultOrUnformed.type = converted constants.%struct_type.a, %DefaultOrUnformed.facet.loc7_24.1 [symbolic = %DefaultOrUnformed.facet.loc7_24.2 (constants.%DefaultOrUnformed.facet.ca5)]\n// CHECK:STDOUT:     %as_type.loc7: type = facet_access_type %.loc7_24.1 [symbolic = %struct_type.a.loc7_23.2 (constants.%struct_type.a)]\n// CHECK:STDOUT:     %.loc7_24.2: type = converted %.loc7_24.1, %as_type.loc7 [symbolic = %struct_type.a.loc7_23.2 (constants.%struct_type.a)]\n// CHECK:STDOUT:     %impl.elem0.loc7_24.1: @F.%.loc7_24.4 (%.9ac) = impl_witness_access constants.%DefaultOrUnformed.lookup_impl_witness.169, element0 [symbolic = %impl.elem0.loc7_24.2 (constants.%impl.elem0.e9c)]\n// CHECK:STDOUT:     %specific_impl_fn.loc7_24.1: <specific function> = specific_impl_function %impl.elem0.loc7_24.1, @DefaultOrUnformed.WithSelf.Op(constants.%DefaultOrUnformed.facet.ca5) [symbolic = %specific_impl_fn.loc7_24.2 (constants.%specific_impl_fn.cf6)]\n// CHECK:STDOUT:     %DefaultOrUnformed.WithSelf.Op.call.loc7: init @F.%struct_type.a.loc7_23.2 (%struct_type.a) = call %specific_impl_fn.loc7_24.1()\n// CHECK:STDOUT:     assign %v.var, %DefaultOrUnformed.WithSelf.Op.call.loc7\n// CHECK:STDOUT:     %.loc7_23: type = splice_block %struct_type.a.loc7_23.1 [symbolic = %struct_type.a.loc7_23.2 (constants.%struct_type.a)] {\n// CHECK:STDOUT:       %T.ref.loc7: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:       %struct_type.a.loc7_23.1: type = struct_type {.a: @F.%T.loc4_6.1 (%T)} [symbolic = %struct_type.a.loc7_23.2 (constants.%struct_type.a)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v: ref @F.%struct_type.a.loc7_23.2 (%struct_type.a) = ref_binding v, %v.var\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %w.patt: @F.%pattern_type.loc8 (%pattern_type.d52) = ref_binding_pattern w [concrete]\n// CHECK:STDOUT:       %w.var_patt: @F.%pattern_type.loc8 (%pattern_type.d52) = var_pattern %w.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %w.var: ref @F.%array_type.loc8_27.2 (%array_type.742) = var %w.var_patt\n// CHECK:STDOUT:     %DefaultOrUnformed.facet.loc8_28.1: %DefaultOrUnformed.type = facet_value constants.%array_type.742, (constants.%DefaultOrUnformed.lookup_impl_witness.945) [symbolic = %DefaultOrUnformed.facet.loc8_28.2 (constants.%DefaultOrUnformed.facet.ad6)]\n// CHECK:STDOUT:     %.loc8_28.1: %DefaultOrUnformed.type = converted constants.%array_type.742, %DefaultOrUnformed.facet.loc8_28.1 [symbolic = %DefaultOrUnformed.facet.loc8_28.2 (constants.%DefaultOrUnformed.facet.ad6)]\n// CHECK:STDOUT:     %as_type.loc8: type = facet_access_type %.loc8_28.1 [symbolic = %array_type.loc8_27.2 (constants.%array_type.742)]\n// CHECK:STDOUT:     %.loc8_28.2: type = converted %.loc8_28.1, %as_type.loc8 [symbolic = %array_type.loc8_27.2 (constants.%array_type.742)]\n// CHECK:STDOUT:     %impl.elem0.loc8_28.1: @F.%.loc8_28.4 (%.544) = impl_witness_access constants.%DefaultOrUnformed.lookup_impl_witness.945, element0 [symbolic = %impl.elem0.loc8_28.2 (constants.%impl.elem0.97e)]\n// CHECK:STDOUT:     %specific_impl_fn.loc8_28.1: <specific function> = specific_impl_function %impl.elem0.loc8_28.1, @DefaultOrUnformed.WithSelf.Op(constants.%DefaultOrUnformed.facet.ad6) [symbolic = %specific_impl_fn.loc8_28.2 (constants.%specific_impl_fn.261)]\n// CHECK:STDOUT:     %.loc8_3.1: ref @F.%array_type.loc8_27.2 (%array_type.742) = splice_block %w.var {}\n// CHECK:STDOUT:     %DefaultOrUnformed.WithSelf.Op.call.loc8: init @F.%array_type.loc8_27.2 (%array_type.742) to %.loc8_3.1 = call %specific_impl_fn.loc8_28.1()\n// CHECK:STDOUT:     assign %w.var, %DefaultOrUnformed.WithSelf.Op.call.loc8\n// CHECK:STDOUT:     %.loc8_27: type = splice_block %array_type.loc8_27.1 [symbolic = %array_type.loc8_27.2 (constants.%array_type.742)] {\n// CHECK:STDOUT:       %T.ref.loc8: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:       %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5]\n// CHECK:STDOUT:       %array_type.loc8_27.1: type = array_type %int_5, %T.ref.loc8 [symbolic = %array_type.loc8_27.2 (constants.%array_type.742)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %w: ref @F.%array_type.loc8_27.2 (%array_type.742) = ref_binding w, %w.var\n// CHECK:STDOUT:     %impl.elem0.loc8_3.1: @F.%.loc8_3.2 (%.950) = impl_witness_access constants.%Destroy.lookup_impl_witness.b29, element0 [symbolic = %impl.elem0.loc8_3.2 (constants.%impl.elem0.fa5)]\n// CHECK:STDOUT:     %bound_method.loc8_3.1: <bound method> = bound_method %w.var, %impl.elem0.loc8_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc8_3.1: <specific function> = specific_impl_function %impl.elem0.loc8_3.1, @Destroy.WithSelf.Op(constants.%Destroy.facet.ddc) [symbolic = %specific_impl_fn.loc8_3.2 (constants.%specific_impl_fn.ede)]\n// CHECK:STDOUT:     %bound_method.loc8_3.2: <bound method> = bound_method %w.var, %specific_impl_fn.loc8_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call.loc8: init %empty_tuple.type = call %bound_method.loc8_3.2(%w.var)\n// CHECK:STDOUT:     %impl.elem0.loc7_3.1: @F.%.loc7_3 (%.511) = impl_witness_access constants.%Destroy.lookup_impl_witness.bed, element0 [symbolic = %impl.elem0.loc7_3.2 (constants.%impl.elem0.12c)]\n// CHECK:STDOUT:     %bound_method.loc7_3.1: <bound method> = bound_method %v.var, %impl.elem0.loc7_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc7_3.1: <specific function> = specific_impl_function %impl.elem0.loc7_3.1, @Destroy.WithSelf.Op(constants.%Destroy.facet.d21) [symbolic = %specific_impl_fn.loc7_3.2 (constants.%specific_impl_fn.c3a)]\n// CHECK:STDOUT:     %bound_method.loc7_3.2: <bound method> = bound_method %v.var, %specific_impl_fn.loc7_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call.loc7: init %empty_tuple.type = call %bound_method.loc7_3.2(%v.var)\n// CHECK:STDOUT:     %impl.elem0.loc6_3.1: @F.%.loc6_3.2 (%.f20) = impl_witness_access constants.%Destroy.lookup_impl_witness.7eb, element0 [symbolic = %impl.elem0.loc6_3.2 (constants.%impl.elem0.f5f)]\n// CHECK:STDOUT:     %bound_method.loc6_3.1: <bound method> = bound_method %u.var, %impl.elem0.loc6_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc6_3.1: <specific function> = specific_impl_function %impl.elem0.loc6_3.1, @Destroy.WithSelf.Op(constants.%Destroy.facet.66d) [symbolic = %specific_impl_fn.loc6_3.2 (constants.%specific_impl_fn.87c)]\n// CHECK:STDOUT:     %bound_method.loc6_3.2: <bound method> = bound_method %u.var, %specific_impl_fn.loc6_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call.loc6: init %empty_tuple.type = call %bound_method.loc6_3.2(%u.var)\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%N.loc12_6.2: %i32) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.loc12_6.1, constants.%Int.as.ImplicitAs.impl.Convert.dd4 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:   %bound_method.loc14_28.3: <bound method> = bound_method %N.loc12_6.1, constants.%Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic = %bound_method.loc14_28.3 (constants.%bound_method)]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call.loc14_28.2: init Core.IntLiteral = call %bound_method.loc14_28.3(%N.loc12_6.1) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc14_28.2 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:   %array_type.loc14_29.2: type = array_type %Int.as.ImplicitAs.impl.Convert.call.loc14_28.2, constants.%i32 [symbolic = %array_type.loc14_29.2 (constants.%array_type.2ec)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %array_type.loc14_29.2 [symbolic = %require_complete (constants.%require_complete.5d1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %array_type.loc14_29.2 [symbolic = %pattern_type (constants.%pattern_type.99c)]\n// CHECK:STDOUT:   %.loc14_30.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%array_type.loc14_29.2) [symbolic = %.loc14_30.3 (constants.%.d6f)]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %array_type.loc14_29.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness (constants.%DefaultOrUnformed.lookup_impl_witness.162)]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc14_30.2: %DefaultOrUnformed.type = facet_value %array_type.loc14_29.2, (%DefaultOrUnformed.lookup_impl_witness) [symbolic = %DefaultOrUnformed.facet.loc14_30.2 (constants.%DefaultOrUnformed.facet.0c7)]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc14_30.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type (constants.%DefaultOrUnformed.WithSelf.Op.type.839)]\n// CHECK:STDOUT:   %.loc14_30.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type, %DefaultOrUnformed.facet.loc14_30.2 [symbolic = %.loc14_30.4 (constants.%.78e)]\n// CHECK:STDOUT:   %impl.elem0.loc14_30.2: @G.%.loc14_30.4 (%.78e) = impl_witness_access %DefaultOrUnformed.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc14_30.2 (constants.%impl.elem0.82a)]\n// CHECK:STDOUT:   %specific_impl_fn.loc14_30.2: <specific function> = specific_impl_function %impl.elem0.loc14_30.2, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.loc14_30.2) [symbolic = %specific_impl_fn.loc14_30.2 (constants.%specific_impl_fn.fcf)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %array_type.loc14_29.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness.f5c)]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %array_type.loc14_29.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.d1e)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [symbolic = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.ff9)]\n// CHECK:STDOUT:   %.loc14_3.2: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %Destroy.facet [symbolic = %.loc14_3.2 (constants.%.63e)]\n// CHECK:STDOUT:   %impl.elem0.loc14_3.2: @G.%.loc14_3.2 (%.63e) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc14_3.2 (constants.%impl.elem0.2bf)]\n// CHECK:STDOUT:   %specific_impl_fn.loc14_3.2: <specific function> = specific_impl_function %impl.elem0.loc14_3.2, @Destroy.WithSelf.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc14_3.2 (constants.%specific_impl_fn.0a5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %k.patt: @G.%pattern_type (%pattern_type.99c) = ref_binding_pattern k [concrete]\n// CHECK:STDOUT:       %k.var_patt: @G.%pattern_type (%pattern_type.99c) = var_pattern %k.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %k.var: ref @G.%array_type.loc14_29.2 (%array_type.2ec) = var %k.var_patt\n// CHECK:STDOUT:     %DefaultOrUnformed.facet.loc14_30.1: %DefaultOrUnformed.type = facet_value constants.%array_type.2ec, (constants.%DefaultOrUnformed.lookup_impl_witness.162) [symbolic = %DefaultOrUnformed.facet.loc14_30.2 (constants.%DefaultOrUnformed.facet.0c7)]\n// CHECK:STDOUT:     %.loc14_30.1: %DefaultOrUnformed.type = converted constants.%array_type.2ec, %DefaultOrUnformed.facet.loc14_30.1 [symbolic = %DefaultOrUnformed.facet.loc14_30.2 (constants.%DefaultOrUnformed.facet.0c7)]\n// CHECK:STDOUT:     %as_type: type = facet_access_type %.loc14_30.1 [symbolic = %array_type.loc14_29.2 (constants.%array_type.2ec)]\n// CHECK:STDOUT:     %.loc14_30.2: type = converted %.loc14_30.1, %as_type [symbolic = %array_type.loc14_29.2 (constants.%array_type.2ec)]\n// CHECK:STDOUT:     %impl.elem0.loc14_30.1: @G.%.loc14_30.4 (%.78e) = impl_witness_access constants.%DefaultOrUnformed.lookup_impl_witness.162, element0 [symbolic = %impl.elem0.loc14_30.2 (constants.%impl.elem0.82a)]\n// CHECK:STDOUT:     %specific_impl_fn.loc14_30.1: <specific function> = specific_impl_function %impl.elem0.loc14_30.1, @DefaultOrUnformed.WithSelf.Op(constants.%DefaultOrUnformed.facet.0c7) [symbolic = %specific_impl_fn.loc14_30.2 (constants.%specific_impl_fn.fcf)]\n// CHECK:STDOUT:     %.loc14_3.1: ref @G.%array_type.loc14_29.2 (%array_type.2ec) = splice_block %k.var {}\n// CHECK:STDOUT:     %DefaultOrUnformed.WithSelf.Op.call: init @G.%array_type.loc14_29.2 (%array_type.2ec) to %.loc14_3.1 = call %specific_impl_fn.loc14_30.1()\n// CHECK:STDOUT:     assign %k.var, %DefaultOrUnformed.WithSelf.Op.call\n// CHECK:STDOUT:     %.loc14_29: type = splice_block %array_type.loc14_29.1 [symbolic = %array_type.loc14_29.2 (constants.%array_type.2ec)] {\n// CHECK:STDOUT:       %i32.loc14: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %N.ref: %i32 = name_ref N, %N.loc12_6.2 [symbolic = %N.loc12_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:       %impl.elem0.loc14_28: %.0a7 = impl_witness_access constants.%ImplicitAs.impl_witness.640, element0 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.dd4]\n// CHECK:STDOUT:       %bound_method.loc14_28.1: <bound method> = bound_method %N.ref, %impl.elem0.loc14_28 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:       %specific_fn: <specific function> = specific_function %impl.elem0.loc14_28, @Int.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Int.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc14_28.2: <bound method> = bound_method %N.ref, %specific_fn [symbolic = %bound_method.loc14_28.3 (constants.%bound_method)]\n// CHECK:STDOUT:       %Int.as.ImplicitAs.impl.Convert.call.loc14_28.1: init Core.IntLiteral = call %bound_method.loc14_28.2(%N.ref) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc14_28.2 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %.loc14_28.1: Core.IntLiteral = value_of_initializer %Int.as.ImplicitAs.impl.Convert.call.loc14_28.1 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc14_28.2 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %.loc14_28.2: Core.IntLiteral = converted %N.ref, %.loc14_28.1 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc14_28.2 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %array_type.loc14_29.1: type = array_type %.loc14_28.2, %i32.loc14 [symbolic = %array_type.loc14_29.2 (constants.%array_type.2ec)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %k: ref @G.%array_type.loc14_29.2 (%array_type.2ec) = ref_binding k, %k.var\n// CHECK:STDOUT:     %impl.elem0.loc14_3.1: @G.%.loc14_3.2 (%.63e) = impl_witness_access constants.%Destroy.lookup_impl_witness.f5c, element0 [symbolic = %impl.elem0.loc14_3.2 (constants.%impl.elem0.2bf)]\n// CHECK:STDOUT:     %bound_method.loc14_3.1: <bound method> = bound_method %k.var, %impl.elem0.loc14_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc14_3.1: <specific function> = specific_impl_function %impl.elem0.loc14_3.1, @Destroy.WithSelf.Op(constants.%Destroy.facet.d1e) [symbolic = %specific_impl_fn.loc14_3.2 (constants.%specific_impl_fn.0a5)]\n// CHECK:STDOUT:     %bound_method.loc14_3.2: <bound method> = bound_method %k.var, %specific_impl_fn.loc14_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call: init %empty_tuple.type = call %bound_method.loc14_3.2(%k.var)\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%N.5de) {\n// CHECK:STDOUT:   %N.loc12_6.1 => constants.%N.5de\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/eval/binding.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/eval/binding.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/eval/binding.carbon\n\n// --- local.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn F(a: i32) -> i32 {\n  let b: i32 = a;\n  let c: i32 = b;\n  return c;\n}\n\n//@dump-sem-ir-begin\nlet n: array(i32, F(3)) = (1, 2, 3);\n//@dump-sem-ir-end\n\n// --- fail_global.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// This is a runtime binding, even though it has a compile-time-constant value,\n// so is not accessible from within G.\nlet a: i32 = 3;\n\neval fn G() -> i32 {\n  // CHECK:STDERR: fail_global.carbon:[[@LINE+3]]:10: error: expression is runtime; expected constant [EvalRequiresConstantValue]\n  // CHECK:STDERR:   return a;\n  // CHECK:STDERR:          ^\n  return a;\n}\n\n// CHECK:STDERR: fail_global.carbon:[[@LINE+4]]:19: note: in call to G here [InCallToEvalFn]\n// CHECK:STDERR: let n: array(i32, G()) = (1, 2, 3);\n// CHECK:STDERR:                   ^~~\n// CHECK:STDERR:\nlet n: array(i32, G()) = (1, 2, 3);\n\n// --- fail_runtime_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() -> i32;\n\nlet a: i32 = F();\n\neval fn G() -> i32 {\n  // CHECK:STDERR: fail_runtime_value.carbon:[[@LINE+3]]:10: error: expression is runtime; expected constant [EvalRequiresConstantValue]\n  // CHECK:STDERR:   return a;\n  // CHECK:STDERR:          ^\n  return a;\n}\n\n// CHECK:STDERR: fail_runtime_value.carbon:[[@LINE+4]]:19: note: in call to G here [InCallToEvalFn]\n// CHECK:STDERR: let n: array(i32, G()) = (1, 2, 3);\n// CHECK:STDERR:                   ^~~\n// CHECK:STDERR:\nlet n: array(i32, G()) = (1, 2, 3);\n\n// CHECK:STDOUT: --- local.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %From: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.2ed: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%From) [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.d29: %Int.as.ImplicitAs.impl.Convert.type.2ed = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.b94: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet.b94) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet.b94 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.640: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.ea2, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.240: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.dd4: %Int.as.ImplicitAs.impl.Convert.type.240 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.290: %ImplicitAs.type.139 = facet_value %i32, (%ImplicitAs.impl_witness.640) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.462: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet.290) [concrete]\n// CHECK:STDOUT:   %.0a7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.462, %ImplicitAs.facet.290 [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_3.822, %Int.as.ImplicitAs.impl.Convert.dd4 [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Int.as.ImplicitAs.impl.Convert.dd4, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.17a: <bound method> = bound_method %int_3.822, %Int.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.5d8: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.type.37f: type = tuple_type (Core.IntLiteral, Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.2d5: %tuple.type.37f = tuple_value (%int_1.5b8, %int_2.ecc, %int_3.1ba) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%int_1.5d2, %int_2.ef8, %int_3.822) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.0bc: @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert.type (%Int.as.ImplicitAs.impl.Convert.type.2ed) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert (constants.%Int.as.ImplicitAs.impl.Convert.d29)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.ea2 = impl_witness_table (%Core.import_ref.0bc), @Int.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %n.patt: %pattern_type.5d8 = value_binding_pattern n [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc11_23: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, %F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %impl.elem0.loc11_21: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc11_21.1: <bound method> = bound_method %int_3, %impl.elem0.loc11_21 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:     %specific_fn.loc11_21: <specific function> = specific_function %impl.elem0.loc11_21, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc11_21.2: <bound method> = bound_method %int_3, %specific_fn.loc11_21 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_21: init %i32 = call %bound_method.loc11_21.2(%int_3) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %.loc11_21.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_21 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %.loc11_21.2: %i32 = converted %int_3, %.loc11_21.1 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %F.call: init %i32 = call %F.ref(%.loc11_21.2) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %impl.elem0.loc11_22: %.0a7 = impl_witness_access constants.%ImplicitAs.impl_witness.640, element0 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.dd4]\n// CHECK:STDOUT:     %bound_method.loc11_22.1: <bound method> = bound_method %F.call, %impl.elem0.loc11_22 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn.loc11_22: <specific function> = specific_function %impl.elem0.loc11_22, @Int.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Int.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc11_22.2: <bound method> = bound_method %F.call, %specific_fn.loc11_22 [concrete = constants.%bound_method.17a]\n// CHECK:STDOUT:     %.loc11_22.1: %i32 = value_of_initializer %F.call [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %.loc11_22.2: %i32 = converted %F.call, %.loc11_22.1 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %Int.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method.loc11_22.2(%.loc11_22.2) [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc11_22.3: Core.IntLiteral = value_of_initializer %Int.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc11_22.4: Core.IntLiteral = converted %F.call, %.loc11_22.3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %array_type: type = array_type %.loc11_22.4, %i32 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %impl.elem0.loc11_35.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc11_35.1: <bound method> = bound_method @__global_init.%int_1, %impl.elem0.loc11_35.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc11_35.1: <specific function> = specific_function %impl.elem0.loc11_35.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc11_35.2: <bound method> = bound_method @__global_init.%int_1, %specific_fn.loc11_35.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_35.1: init %i32 = call %bound_method.loc11_35.2(@__global_init.%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc11_35.1: init %i32 = converted @__global_init.%int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_35.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc11_35.2: ref %array_type = temporary_storage\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc11_35.3: ref %i32 = array_index %.loc11_35.2, %int_0\n// CHECK:STDOUT:   %.loc11_35.4: init %i32 to %.loc11_35.3 = in_place_init %.loc11_35.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc11_35.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc11_35.3: <bound method> = bound_method @__global_init.%int_2, %impl.elem0.loc11_35.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc11_35.2: <specific function> = specific_function %impl.elem0.loc11_35.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc11_35.4: <bound method> = bound_method @__global_init.%int_2, %specific_fn.loc11_35.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_35.2: init %i32 = call %bound_method.loc11_35.4(@__global_init.%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc11_35.5: init %i32 = converted @__global_init.%int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_35.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc11_35.6: ref %i32 = array_index %.loc11_35.2, %int_1\n// CHECK:STDOUT:   %.loc11_35.7: init %i32 to %.loc11_35.6 = in_place_init %.loc11_35.5 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %impl.elem0.loc11_35.3: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc11_35.5: <bound method> = bound_method @__global_init.%int_3, %impl.elem0.loc11_35.3 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:   %specific_fn.loc11_35.3: <specific function> = specific_function %impl.elem0.loc11_35.3, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc11_35.6: <bound method> = bound_method @__global_init.%int_3, %specific_fn.loc11_35.3 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_35.3: init %i32 = call %bound_method.loc11_35.6(@__global_init.%int_3) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc11_35.8: init %i32 = converted @__global_init.%int_3, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11_35.3 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc11_35.9: ref %i32 = array_index %.loc11_35.2, %int_2\n// CHECK:STDOUT:   %.loc11_35.10: init %i32 to %.loc11_35.9 = in_place_init %.loc11_35.8 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc11_35.11: init %array_type to %.loc11_35.2 = array_init (%.loc11_35.4, %.loc11_35.7, %.loc11_35.10) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc11_35.12: init %array_type = converted @__global_init.%.loc11, %.loc11_35.11 [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc11_35.13: ref %array_type = temporary %.loc11_35.2, %.loc11_35.12\n// CHECK:STDOUT:   %.loc11_35.14: %array_type = acquire_value %.loc11_35.13\n// CHECK:STDOUT:   %n: %array_type = value_binding n, %.loc11_35.14\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %.loc11: %tuple.type.37f = tuple_literal (%int_1, %int_2, %int_3) [concrete = constants.%tuple.2d5]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/eval/branch.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/bool.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/eval/branch.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/eval/branch.carbon\n\n// --- types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {}\nclass B {}\n\nfn MakeA() -> A { return {}; }\nfn MakeB() -> B { return {}; }\n\n// --- if_statement.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"types\";\n\neval fn F(b: bool) -> type {\n  if (b) {\n    return A;\n  } else {\n    return B;\n  }\n}\n\n//@dump-sem-ir-begin\nvar a: F(true) = MakeA();\nvar b: F(false) = MakeB();\n//@dump-sem-ir-end\n\n// --- if_expression_in_eval_fn.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"types\";\n\neval fn F(b: bool) -> type {\n  return if b then A else B;\n}\n\n//@dump-sem-ir-begin\nvar a: F(true) = MakeA();\nvar b: F(false) = MakeB();\n//@dump-sem-ir-end\n\n// --- fail_todo_if_expression_direct.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"types\";\n\n// CHECK:STDERR: fail_todo_if_expression_direct.carbon:[[@LINE+4]]:8: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n// CHECK:STDERR: var a: if true then A else B = MakeA();\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar a: if true then A else B = MakeA();\nvar b: if false then A else B = MakeB();\n\n// CHECK:STDOUT: --- if_statement.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %MakeA.type: type = fn_type @MakeA [concrete]\n// CHECK:STDOUT:   %MakeA: %MakeA.type = struct_value () [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %MakeB.type: type = fn_type @MakeB [concrete]\n// CHECK:STDOUT:   %MakeB: %MakeB.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.MakeA: %MakeA.type = import_ref Main//types, MakeA, loaded [concrete = constants.%MakeA]\n// CHECK:STDOUT:   %Main.MakeB: %MakeB.type = import_ref Main//types, MakeB, loaded [concrete = constants.%MakeB]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1ab = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.1ab = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %A = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc14_14.1: type = splice_block %.loc14_14.3 [concrete = constants.%A] {\n// CHECK:STDOUT:     %F.ref.loc14: %F.type = name_ref F, %F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %F.call.loc14: init type = call %F.ref.loc14(%true) [concrete = constants.%A]\n// CHECK:STDOUT:     %.loc14_14.2: type = value_of_initializer %F.call.loc14 [concrete = constants.%A]\n// CHECK:STDOUT:     %.loc14_14.3: type = converted %F.call.loc14, %.loc14_14.2 [concrete = constants.%A]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %A = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.1f4 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.1f4 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %B = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %.loc15_15.1: type = splice_block %.loc15_15.3 [concrete = constants.%B] {\n// CHECK:STDOUT:     %F.ref.loc15: %F.type = name_ref F, %F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:     %F.call.loc15: init type = call %F.ref.loc15(%false) [concrete = constants.%B]\n// CHECK:STDOUT:     %.loc15_15.2: type = value_of_initializer %F.call.loc15 [concrete = constants.%B]\n// CHECK:STDOUT:     %.loc15_15.3: type = converted %F.call.loc15, %.loc15_15.2 [concrete = constants.%B]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %B = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %MakeA.ref: %MakeA.type = name_ref MakeA, imports.%Main.MakeA [concrete = constants.%MakeA]\n// CHECK:STDOUT:   %.loc14: ref %A = splice_block file.%a.var [concrete = file.%a.var] {}\n// CHECK:STDOUT:   %MakeA.call: init %A to %.loc14 = call %MakeA.ref()\n// CHECK:STDOUT:   assign file.%a.var, %MakeA.call\n// CHECK:STDOUT:   %MakeB.ref: %MakeB.type = name_ref MakeB, imports.%Main.MakeB [concrete = constants.%MakeB]\n// CHECK:STDOUT:   %.loc15: ref %B = splice_block file.%b.var [concrete = file.%b.var] {}\n// CHECK:STDOUT:   %MakeB.call: init %B to %.loc15 = call %MakeB.ref()\n// CHECK:STDOUT:   assign file.%b.var, %MakeB.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- if_expression_in_eval_fn.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %MakeA.type: type = fn_type @MakeA [concrete]\n// CHECK:STDOUT:   %MakeA: %MakeA.type = struct_value () [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT:   %MakeB.type: type = fn_type @MakeB [concrete]\n// CHECK:STDOUT:   %MakeB: %MakeB.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.MakeA: %MakeA.type = import_ref Main//types, MakeA, loaded [concrete = constants.%MakeA]\n// CHECK:STDOUT:   %Main.MakeB: %MakeB.type = import_ref Main//types, MakeB, loaded [concrete = constants.%MakeB]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.1ab = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.1ab = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %A = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_14.1: type = splice_block %.loc10_14.3 [concrete = constants.%A] {\n// CHECK:STDOUT:     %F.ref.loc10: %F.type = name_ref F, %F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %F.call.loc10: init type = call %F.ref.loc10(%true) [concrete = constants.%A]\n// CHECK:STDOUT:     %.loc10_14.2: type = value_of_initializer %F.call.loc10 [concrete = constants.%A]\n// CHECK:STDOUT:     %.loc10_14.3: type = converted %F.call.loc10, %.loc10_14.2 [concrete = constants.%A]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %A = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.1f4 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.1f4 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %B = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %.loc11_15.1: type = splice_block %.loc11_15.3 [concrete = constants.%B] {\n// CHECK:STDOUT:     %F.ref.loc11: %F.type = name_ref F, %F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:     %F.call.loc11: init type = call %F.ref.loc11(%false) [concrete = constants.%B]\n// CHECK:STDOUT:     %.loc11_15.2: type = value_of_initializer %F.call.loc11 [concrete = constants.%B]\n// CHECK:STDOUT:     %.loc11_15.3: type = converted %F.call.loc11, %.loc11_15.2 [concrete = constants.%B]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %B = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %MakeA.ref: %MakeA.type = name_ref MakeA, imports.%Main.MakeA [concrete = constants.%MakeA]\n// CHECK:STDOUT:   %.loc10: ref %A = splice_block file.%a.var [concrete = file.%a.var] {}\n// CHECK:STDOUT:   %MakeA.call: init %A to %.loc10 = call %MakeA.ref()\n// CHECK:STDOUT:   assign file.%a.var, %MakeA.call\n// CHECK:STDOUT:   %MakeB.ref: %MakeB.type = name_ref MakeB, imports.%Main.MakeB [concrete = constants.%MakeB]\n// CHECK:STDOUT:   %.loc11: ref %B = splice_block file.%b.var [concrete = file.%b.var] {}\n// CHECK:STDOUT:   %MakeB.call: init %B to %.loc11 = call %MakeB.ref()\n// CHECK:STDOUT:   assign file.%b.var, %MakeB.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/eval/call.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/eval/call.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/eval/call.carbon\n\n// --- call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn F() -> i32 { return 3; }\n\nvar a: array(i32, F()) = (0, 1, 2);\n\n// --- fail_call_wrong_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn F() -> i32 { return 3; }\n\n// Ensure we get an error about the over-sized initializer and aren't just\n// treating all `eval fn` calls as silent errors.\n// CHECK:STDERR: fail_call_wrong_value.carbon:[[@LINE+4]]:26: error: cannot initialize array of 3 elements from 4 initializers [ArrayInitFromLiteralArgCountMismatch]\n// CHECK:STDERR: var a: array(i32, F()) = (0, 1, 2, 3);\n// CHECK:STDERR:                          ^~~~~~~~~~~~\n// CHECK:STDERR:\nvar a: array(i32, F()) = (0, 1, 2, 3);\n\n// --- fail_call_fn_not_eval.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() -> i32 { return 3; }\n\n// CHECK:STDERR: fail_call_fn_not_eval.carbon:[[@LINE+4]]:19: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var a: array(i32, F()) = (0, 1, 2);\n// CHECK:STDERR:                   ^~~\n// CHECK:STDERR:\nvar a: array(i32, F()) = (0, 1, 2);\n\n// --- fail_call_eval_fn_not_defined.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn F() -> i32;\n\n// TODO: We should be able to diagnose this better.\n// CHECK:STDERR: fail_call_eval_fn_not_defined.carbon:[[@LINE+4]]:19: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: var a: array(i32, F()) = (0, 1, 2);\n// CHECK:STDERR:                   ^~~\n// CHECK:STDERR:\nvar a: array(i32, F()) = (0, 1, 2);\n\n// --- param_and_return.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn F(x: i32) -> i32 { return x; }\n\nvar a: array(i32, F(3)) = (1, 2, 3);\n\n// --- fail_todo_dependent_call.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn F(x: i32) -> i32 { return x; }\n\nfn G(N:! i32) {\n  // CHECK:STDERR: fail_todo_dependent_call.carbon:[[@LINE+4]]:17: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   var unused a: array(i32, F(N)) = (0, 1, 2);\n  // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused a: array(i32, F(N)) = (0, 1, 2);\n}\n\nfn H() { G(3); }\n\n// --- fail_todo_dependent_call_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\neval fn F(_: i32) -> type {\n  return C;\n}\n\nfn UseFGenerically(X:! i32) {\n  // CHECK:STDERR: fail_todo_dependent_call_type.carbon:[[@LINE+12]]:3: error: member name of type `<dependent type>` in compound member access is not an instance member or an interface member [CompoundMemberAccessDoesNotUseBase]\n  // CHECK:STDERR:   var unused v: F(X) = {};\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_todo_dependent_call_type.carbon:[[@LINE+8]]:3: error: value of type `<dependent type>` is not callable [CallToNonCallable]\n  // CHECK:STDERR:   var unused v: F(X) = {};\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_todo_dependent_call_type.carbon:[[@LINE+4]]:3: error: cannot access member of interface `Core.Destroy` in type `<cannot stringify inst7C00018B: {kind: Call, arg0: inst7C00003E, arg1: inst_block7C000091, type: type(TypeType)}>` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   var unused v: F(X) = {};\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v: F(X) = {};\n}\n\nfn UseFSpecifically() {\n  UseFGenerically(3);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/eval/recursion.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Extend the \"int\" min_prelude to support basic integer operations, so we\n// can use it here.\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/eval/recursion.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/eval/recursion.carbon\n\n// --- recursion.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn F(n: i32) -> type {\n  if (n == 0) {\n    return i32;\n  }\n  return F(n - 1);\n}\n\nvar i: F(3) = 0;\n\n// TODO: Diagnose infinite recursion.\n"
  },
  {
    "path": "toolchain/check/testdata/eval/symbolic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/bool.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/eval/symbolic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/eval/symbolic.carbon\n\n// --- symbolic_call_to_eval_fn.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn F(B:! bool) -> type {\n  if (B) { return (); }\n  return ({}, {});\n}\n\nfn G(B:! bool) {\n  let unused n: F(B) = ({}, {});\n}\n\nfn H() {\n  G(false);\n}\n\n\n// --- fail_symbolic_call_to_eval_fn_invalid_instantiation.carbon\n// TODO: Provide a location for the error message.\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn F(B:! bool) -> type {\n  if (B) { return (); }\n  return ({}, {});\n}\n\nfn G(B:! bool) {\n  let unused n: F(B) = ({}, {});\n}\n\nfn H() {\n  // CHECK:STDERR: fail_symbolic_call_to_eval_fn_invalid_instantiation.carbon:[[@LINE+5]]:3: error: unable to monomorphize specific `G(true)` [ResolvingSpecificHere]\n  // CHECK:STDERR:   G(true);\n  // CHECK:STDERR:   ^\n  // CHECK:STDERR: fail_symbolic_call_to_eval_fn_invalid_instantiation.carbon: note: cannot initialize tuple of 0 elements from tuple with 2 elements [TupleInitElementCountMismatch]\n  // CHECK:STDERR:\n  G(true);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/eval/unexpected_runtime.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/eval/unexpected_runtime.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/eval/unexpected_runtime.carbon\n\n// --- fail_unexpected_runtime.carbon\n\nvar x: type;\n\ninterface Z {\n  let T:! type;\n}\n\nclass D {\n  // CHECK:STDERR: fail_unexpected_runtime.carbon:[[@LINE+4]]:31: error: expression is runtime; expected constant [EvalRequiresConstantValue]\n  // CHECK:STDERR:   extend impl as Z where .T = x {}\n  // CHECK:STDERR:                               ^\n  // CHECK:STDERR:\n  extend impl as Z where .T = x {}\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/access.carbon\n\n// --- access_assoc_fn.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  fn DoIt();\n}\n\nfn Use(T:! I) {\n//@dump-sem-ir-begin\n  T.DoIt();\n//@dump-sem-ir-end\n}\n\n// --- assoc_fn_using_self.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  fn Make() -> Self;\n}\n\nfn Use(T:! I) -> T {\n//@dump-sem-ir-begin\n  return T.Make();\n//@dump-sem-ir-end\n}\n\n// --- access_assoc_method.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  fn Copy[self: Self]() -> Self;\n}\n\n//@dump-sem-ir-begin\nfn Use[T:! I](x: T) -> T {\n  return x.Copy();\n}\n//@dump-sem-ir-end\n\n// --- access_selfless_method.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  fn Hello();\n}\n\nfn Use[T:! I](x: T){\n//@dump-sem-ir-begin\n  x.Hello();\n//@dump-sem-ir-end\n}\n\n// --- access_assoc_method_indirect.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  fn Copy[self: Self]() -> Self;\n}\n\nfn UseIndirect[T:! I](x: T) -> T {\n//@dump-sem-ir-begin\n  return x.(T.Copy)();\n//@dump-sem-ir-end\n}\n\n// --- fail_todo_convert_from_period_self_to_full_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n}\n\nfn F(U:! I where .I1 = .Self) {\n  // CHECK:STDERR: fail_todo_convert_from_period_self_to_full_facet_value.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I where .(I.I1) = .Self` into type implementing `I where .(I.I1) = U` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   U as (I where .I1 = U);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  U as (I where .I1 = U);\n  // CHECK:STDERR: fail_todo_convert_from_period_self_to_full_facet_value.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I where .(I.I1) = .Self` into type implementing `I where .(I.I1) = U` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   (U as type) as (I where .I1 = U);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  (U as type) as (I where .I1 = U);\n}\n\n// --- convert_to_period_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n  let I2:! type;\n}\n\nfn F(U:! I where .I1 = .Self and .I2 = ()) {\n  U as (I where .I1 = .Self);\n  (U as type) as (I where .I1 = .Self);\n}\n\n// --- access_through_call_once.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: Merge this test with the one below once it works.\n\ninterface I {\n  let X:! type;\n  fn G() -> X*;\n}\n\nfn F2[U:! I](unused V: U*) {}\n\nfn F(U:! I where .X = .Self, unused V: U) {\n  // The returned value of `G` type `U` which has access to the methods of `I`.\n  U.G()->G();\n  (U as type).G()->G();\n\n  // The returned value of type `U` can be used as a value of type `U`.\n  F2(U.G());\n}\n\n// --- fail_todo_access_through_call.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  fn G() -> X*;\n}\n\nfn F2[U:! I](unused V: U*) {}\nfn F3[U:! I where .X = .Self](unused V: U*) {}\n\nfn F(U:! I where .X = .Self, unused V: U*) {\n  // The returned value of `G` type `U` which has access to the methods of `I`.\n  //\n  // TODO: These should work.\n  // - The first `.` is on a NameRef of type FacetType for `I where .X = .Self`.\n  //   - This finds `G` through the FacetType.\n  // - The second `.` is on a Call of type FacetAccessType into `SymbolicBinding` with type FacetType for `I`.\n  //   - This finds `G` through the FacetType (impl lookup strips off FacetAccessType).\n  // - The third `.` is on a Call of type FacetAccessType into `ImplWitnessAccess` of `I.X` into `LookupImplWitness`, which has type `type`\n  //   - Can't make calls on an `ImplWitnessAccess`.\n  //   - We could expect that the constant value of the `ImplWitnessAccess` would\n  //     be the same type that we got for the second lookup.\n  // CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:3: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]\n  // CHECK:STDERR:   U.G()->G()->G();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~\n  // CHECK:STDERR:\n  U.G()->G()->G();\n  // CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:3: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]\n  // CHECK:STDERR:   (U as type).G()->G()->G();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  (U as type).G()->G()->G();\n\n  // The returned value of type `U` can be used as a value of type `U`.\n  //\n  // TODO: This should work.\n  // CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:6: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]\n  // CHECK:STDERR:   F2(U.G()->G()->G());\n  // CHECK:STDERR:      ^~~~~~~~~~~~~\n  // CHECK:STDERR:\n  F2(U.G()->G()->G());\n\n  // The constraints in the type `U` are preserved.\n  //\n  // TODO: These should work.\n  // CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+7]]:3: error: cannot convert type `.Self` that implements `I` into type implementing `I where .(I.X) = .Self` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F3(U.G());\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE-40]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn F3[U:! I where .X = .Self](unused V: U*) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  F3(U.G());\n  // CHECK:STDERR: fail_todo_access_through_call.carbon:[[@LINE+4]]:6: error: type `.(I.X)` does not support qualified expressions [QualifiedExprUnsupported]\n  // CHECK:STDERR:   F3(U.G()->G()->G());\n  // CHECK:STDERR:      ^~~~~~~~~~~~~\n  // CHECK:STDERR:\n  F3(U.G()->G()->G());\n}\n\n// --- fail_todo_compound_access_through_call.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  fn G() -> X;\n}\n\nfn F(U:! I where .X = .Self) {\n  // Compound member lookup through a non-type value is possible for methods\n  // which take a `self` parameter. But it's not possible for methods without\n  // `self`. For those you need to go directly throug the type.\n  // See: https://github.com/carbon-language/carbon-lang/issues/6025\n\n  // TODO: This step should work.\n  //\n  // CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+7]]:14: error: cannot implicitly convert expression of type `.Self` to `U` [ConversionFailure]\n  // CHECK:STDERR:   let u: U = U.(I.G)();\n  // CHECK:STDERR:              ^~~~~~~~~\n  // CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+4]]:14: note: type `.Self` does not implement interface `Core.ImplicitAs(U)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let u: U = U.(I.G)();\n  // CHECK:STDERR:              ^~~~~~~~~\n  // CHECK:STDERR:\n  let u: U = U.(I.G)();\n  // `u` is a non-type value. Can call methods with `self` through compound\n  // member lookup, but can't call methods without `self`. See the\n  // `compound_access_through_call_with_self_param.carbon` test for the former.\n  //\n  // CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+7]]:3: error: cannot implicitly convert non-type value of type `U` into type implementing `I` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   u.(I.G)();\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+4]]:3: note: type `U` does not implement interface `Core.ImplicitAs(I)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   u.(I.G)();\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  u.(I.G)();\n\n  // This is the same as the above, since G() returns a non-type value of type\n  // `U`.\n  //\n  // CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+7]]:3: error: cannot implicitly convert non-type value of type `.Self` into type implementing `I` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   U.(I.G)().(I.G)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_compound_access_through_call.carbon:[[@LINE+4]]:3: note: type `.Self` does not implement interface `Core.ImplicitAs(I)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   U.(I.G)().(I.G)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  U.(I.G)().(I.G)();\n}\n\n// --- fail_todo_compound_access_through_call_with_self_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  fn G[self: Self]() -> X*;\n}\n\nfn F(U:! I where .X = .Self, v: U) {\n  // Compound member lookup through a non-type value is possible for methods\n  // which take a `self` parameter.\n\n  // TODO: This should all work.\n\n  // CHECK:STDERR: fail_todo_compound_access_through_call_with_self_param.carbon:[[@LINE+7]]:15: error: cannot implicitly convert expression of type `.Self*` to `U*` [ConversionFailure]\n  // CHECK:STDERR:   let u: U* = v.(I.G)();\n  // CHECK:STDERR:               ^~~~~~~~~\n  // CHECK:STDERR: fail_todo_compound_access_through_call_with_self_param.carbon:[[@LINE+4]]:15: note: type `.Self*` does not implement interface `Core.ImplicitAs(U*)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let u: U* = v.(I.G)();\n  // CHECK:STDERR:               ^~~~~~~~~\n  // CHECK:STDERR:\n  let u: U* = v.(I.G)();\n  // `u` is a non-type value. Can call methods with `self` through compound\n  // member lookup, but can't call methods without `self`. See the\n  // `compound_access_through_call.carbon` test for the latter.\n  u->(I.G)();\n\n  // This is the same as the above, since G() returns a non-type value of type\n  // `U`. This works because G has a `self` parameter.\n  v.(I.G)()->(I.G)();\n}\n\n// --- fail_non_const_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let T:! type; }\nfn Id[U:! type](x: U) -> U { return Id(x); }\nimpl () as I where .T = () {}\n// Type of member expr is associated entity type,\n// but value is not constant.\n// CHECK:STDERR: fail_non_const_associated.carbon:[[@LINE+4]]:8: error: semantics TODO: `Non-constant associated entity value` [SemanticsTodo]\n// CHECK:STDERR: var v: ().(Id(I.T));\n// CHECK:STDERR:        ^~~~~~~~~~~~\n// CHECK:STDERR:\nvar v: ().(Id(I.T));\n\n// --- fail_non_const_associated_in_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn Id[U:! type](x: U) -> U { return Id(x); }\n\ninterface J {\n  let T:! type;\n  // CHECK:STDERR: fail_non_const_associated_in_interface.carbon:[[@LINE+4]]:13: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   fn F() -> Id(T);\n  // CHECK:STDERR:             ^~~~~\n  // CHECK:STDERR:\n  fn F() -> Id(T);\n}\n\n// --- fail_alias_to_non_const_assoc_entity.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let T:! type;\n}\n\n// CHECK:STDERR: fail_alias_to_non_const_assoc_entity.carbon:[[@LINE+4]]:8: error: semantics TODO: `HandleAutoTypeLiteral` [SemanticsTodo]\n// CHECK:STDERR: let x: auto = I.T;\n// CHECK:STDERR:        ^~~~\n// CHECK:STDERR:\nlet x: auto = I.T;\n\ninterface J {\n  // Is this valid?\n  alias U = x;\n  // type of U is an assoc entity type, but value is not constant.\n  fn F() -> U;\n}\n\n// --- to_import.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let T:! type;\n}\n\nalias U = I.T;\n\n// --- fail_access_alias_in_imported_library.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"to_import\";\n\ninterface J {\n  // extend I;\n  alias V = U;\n  // CHECK:STDERR: fail_access_alias_in_imported_library.carbon:[[@LINE+4]]:13: error: cannot convert type `Self` that implements `J` into type implementing `I` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   fn F() -> V;\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  fn F() -> V;\n}\n\n// --- access_constant_in_self_facet.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\ninterface A { let X:! type; }\n\nfn F(AA:! A where .X = ()) -> AA.X {\n  return ();\n}\n//@dump-sem-ir-end\n\n// --- access_constant_in_self_facet_with_multiple_interfaces.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A { let X:! type; }\ninterface B { let Y:! type; }\n\n// The rewrite rules of .X and .Y come in some canonically sorted order. The\n// ImplWitnessAccess instruction looks at them to try find a value for the\n// rewrite in the conversion target. We use different orderings to more reliably\n// create the scenario where the ImplWitnessAccess sees a rewrite of a value in\n// an interface other than the one it is accessing before finding the correct\n// rewrite.\n\n//@dump-sem-ir-begin\nfn F(AB:! A & B where .X = () and .Y = {}) -> AB.X {\n  return ();\n}\n\nfn G(AB:! A & B where .X = () and .Y = {}) -> AB.Y {\n  return {};\n}\n//@dump-sem-ir-end\n\n// --- symbolic_binding_type_of_impl_witness_access.carbon\n\ninterface Y {}\nimpl () as Y {}\n\ninterface Z {\n  let Y1:! Y;\n  fn G() -> Y1*;\n}\n\n// The type of `T` matches exactly the type of `Z.Y1`, which prevents the\n// specific in the call from F2 from deducing a `FacetValue`. Instead it just\n// passes in the `ImplWitnessAccess` instruction as is.\n//\n// The `t: T` creates a `T as type`, or a `SymbolicBindingType` that gets\n// evaluated against the specific. The facet value that it evaluates against is\n// the `ImplWitnessAccess` from the call in F2.\n//\n// This requires that `SymbolicBindingType` evaluation correctly handles\n// arbitrary facet value instructions. Not just the common case of `FacetValue`\n// or `SymbolicBinding`.\nfn F1(T:! Y, unused t: T*) {}\n\nfn F2(U:! Z) {\n  F1(U.Y1, U.G());\n}\n\n// CHECK:STDOUT: --- access_assoc_fn.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.DoIt.decl [concrete]\n// CHECK:STDOUT:   %T: %I.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.DoIt.type.66b: type = fn_type @I.WithSelf.DoIt, @I.WithSelf(%T) [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T, @I [symbolic]\n// CHECK:STDOUT:   %.f37: type = fn_type_with_self_type %I.WithSelf.DoIt.type.66b, %T [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.f37 = impl_witness_access %I.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @I.WithSelf.DoIt(%T) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Use(%T.loc8_8.2: %I.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc8_8.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc8_8.1, @I [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness)]\n// CHECK:STDOUT:   %I.WithSelf.DoIt.type: type = fn_type @I.WithSelf.DoIt, @I.WithSelf(%T.loc8_8.1) [symbolic = %I.WithSelf.DoIt.type (constants.%I.WithSelf.DoIt.type.66b)]\n// CHECK:STDOUT:   %.loc10_4.2: type = fn_type_with_self_type %I.WithSelf.DoIt.type, %T.loc8_8.1 [symbolic = %.loc10_4.2 (constants.%.f37)]\n// CHECK:STDOUT:   %impl.elem0.loc10_4.2: @Use.%.loc10_4.2 (%.f37) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc10_4.2: <specific function> = specific_impl_function %impl.elem0.loc10_4.2, @I.WithSelf.DoIt(%T.loc8_8.1) [symbolic = %specific_impl_fn.loc10_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %T.ref: %I.type = name_ref T, %T.loc8_8.2 [symbolic = %T.loc8_8.1 (constants.%T)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc10_4.1: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %DoIt.ref: %I.assoc_type = name_ref DoIt, @I.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc10_4.1: @Use.%.loc10_4.2 (%.f37) = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %specific_impl_fn.loc10_4.1: <specific function> = specific_impl_function %impl.elem0.loc10_4.1, @I.WithSelf.DoIt(constants.%T) [symbolic = %specific_impl_fn.loc10_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %I.WithSelf.DoIt.call: init %empty_tuple.type = call %specific_impl_fn.loc10_4.1()\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Use(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_8.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- assoc_fn_using_self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.Make.decl [concrete]\n// CHECK:STDOUT:   %T: %I.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %.ff7: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.422: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Make.type.f20: type = fn_type @I.WithSelf.Make, @I.WithSelf(%T) [symbolic]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T, @I [symbolic]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %I.WithSelf.Make.type.f20, %T [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access %I.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @I.WithSelf.Make(%T) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Use(%T.loc8_8.2: %I.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc8_8.1, @I [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness)]\n// CHECK:STDOUT:   %I.WithSelf.Make.type: type = fn_type @I.WithSelf.Make, @I.WithSelf(%T.loc8_8.1) [symbolic = %I.WithSelf.Make.type (constants.%I.WithSelf.Make.type.f20)]\n// CHECK:STDOUT:   %.loc10_11.2: type = fn_type_with_self_type %I.WithSelf.Make.type, %T.loc8_8.1 [symbolic = %.loc10_11.2 (constants.%.8e2)]\n// CHECK:STDOUT:   %impl.elem0.loc10_11.2: @Use.%.loc10_11.2 (%.8e2) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_11.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc10_11.2: <specific function> = specific_impl_function %impl.elem0.loc10_11.2, @I.WithSelf.Make(%T.loc8_8.1) [symbolic = %specific_impl_fn.loc10_11.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Use.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %T.ref.loc10: %I.type = name_ref T, %T.loc8_8.2 [symbolic = %T.loc8_8.1 (constants.%T)]\n// CHECK:STDOUT:     %T.as_type.loc10: type = facet_access_type %T.ref.loc10 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc10_11.1: type = converted %T.ref.loc10, %T.as_type.loc10 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %Make.ref: %I.assoc_type = name_ref Make, @I.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc10_11.1: @Use.%.loc10_11.2 (%.8e2) = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_11.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %specific_impl_fn.loc10_11.1: <specific function> = specific_impl_function %impl.elem0.loc10_11.1, @I.WithSelf.Make(constants.%T) [symbolic = %specific_impl_fn.loc10_11.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %I.WithSelf.Make.call: init @Use.%T.binding.as_type (%T.binding.as_type) to %.loc8_18.1 = call %specific_impl_fn.loc10_11.1()\n// CHECK:STDOUT:     return %I.WithSelf.Make.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Use(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_8.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %.loc8_18.2 => constants.%.ff7\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.422\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- access_assoc_method.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.Copy.decl [concrete]\n// CHECK:STDOUT:   %pattern_type.9d9: type = pattern_type %I.type [concrete]\n// CHECK:STDOUT:   %T: %I.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.422: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.ff7: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Use.type: type = fn_type @Use [concrete]\n// CHECK:STDOUT:   %Use: %Use.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Copy.type.035: type = fn_type @I.WithSelf.Copy, @I.WithSelf(%T) [symbolic]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T, @I [symbolic]\n// CHECK:STDOUT:   %.fa6: type = fn_type_with_self_type %I.WithSelf.Copy.type.035, %T [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.fa6 = impl_witness_access %I.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @I.WithSelf.Copy(%T) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Use.decl: %Use.type = fn_decl @Use [concrete = constants.%Use] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.9d9 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @Use.%pattern_type (%pattern_type.422) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @Use.%pattern_type (%pattern_type.422) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @Use.%pattern_type (%pattern_type.422) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @Use.%pattern_type (%pattern_type.422) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc9_24: %I.type = name_ref T, %T.loc9_8.2 [symbolic = %T.loc9_8.1 (constants.%T)]\n// CHECK:STDOUT:     %T.as_type.loc9_24: type = facet_access_type %T.ref.loc9_24 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc9_24.3: type = converted %T.ref.loc9_24, %T.as_type.loc9_24 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc9_24.4: Core.Form = init_form %.loc9_24.3 [symbolic = %.loc9_24.2 (constants.%.ff7)]\n// CHECK:STDOUT:     %.loc9_12: type = splice_block %I.ref [concrete = constants.%I.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9_8.2: %I.type = symbolic_binding T, 0 [symbolic = %T.loc9_8.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @Use.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc9_18.1: type = splice_block %.loc9_18.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref.loc9_18: %I.type = name_ref T, %T.loc9_8.2 [symbolic = %T.loc9_8.1 (constants.%T)]\n// CHECK:STDOUT:       %T.as_type.loc9_18: type = facet_access_type %T.ref.loc9_18 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_18.2: type = converted %T.ref.loc9_18, %T.as_type.loc9_18 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @Use.%T.binding.as_type (%T.binding.as_type) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @Use.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @Use.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Use(%T.loc9_8.2: %I.type) {\n// CHECK:STDOUT:   %T.loc9_8.1: %I.type = symbolic_binding T, 0 [symbolic = %T.loc9_8.1 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc9_8.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.422)]\n// CHECK:STDOUT:   %.loc9_24.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc9_24.2 (constants.%.ff7)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc9_8.1, @I [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness)]\n// CHECK:STDOUT:   %I.WithSelf.Copy.type: type = fn_type @I.WithSelf.Copy, @I.WithSelf(%T.loc9_8.1) [symbolic = %I.WithSelf.Copy.type (constants.%I.WithSelf.Copy.type.035)]\n// CHECK:STDOUT:   %.loc10: type = fn_type_with_self_type %I.WithSelf.Copy.type, %T.loc9_8.1 [symbolic = %.loc10 (constants.%.fa6)]\n// CHECK:STDOUT:   %impl.elem0.loc10_11.2: @Use.%.loc10 (%.fa6) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_11.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc10_11.2: <specific function> = specific_impl_function %impl.elem0.loc10_11.2, @I.WithSelf.Copy(%T.loc9_8.1) [symbolic = %specific_impl_fn.loc10_11.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @Use.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @Use.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @Use.%T.binding.as_type (%T.binding.as_type) = name_ref x, %x\n// CHECK:STDOUT:     %Copy.ref: %I.assoc_type = name_ref Copy, @I.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc10_11.1: @Use.%.loc10 (%.fa6) = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_11.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %bound_method.loc10_11: <bound method> = bound_method %x.ref, %impl.elem0.loc10_11.1\n// CHECK:STDOUT:     %specific_impl_fn.loc10_11.1: <specific function> = specific_impl_function %impl.elem0.loc10_11.1, @I.WithSelf.Copy(constants.%T) [symbolic = %specific_impl_fn.loc10_11.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %bound_method.loc10_17: <bound method> = bound_method %x.ref, %specific_impl_fn.loc10_11.1\n// CHECK:STDOUT:     %.loc9_24.1: ref @Use.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %I.WithSelf.Copy.call: init @Use.%T.binding.as_type (%T.binding.as_type) to %.loc9_24.1 = call %bound_method.loc10_17(%x.ref)\n// CHECK:STDOUT:     return %I.WithSelf.Copy.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Use(constants.%T) {\n// CHECK:STDOUT:   %T.loc9_8.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.422\n// CHECK:STDOUT:   %.loc9_24.2 => constants.%.ff7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- access_selfless_method.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.Hello.decl [concrete]\n// CHECK:STDOUT:   %T: %I.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.422: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Hello.type.3eb: type = fn_type @I.WithSelf.Hello, @I.WithSelf(%T) [symbolic]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T, @I [symbolic]\n// CHECK:STDOUT:   %.8de: type = fn_type_with_self_type %I.WithSelf.Hello.type.3eb, %T [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.8de = impl_witness_access %I.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @I.WithSelf.Hello(%T) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Use(%T.loc8_8.2: %I.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc8_8.1, @I [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness)]\n// CHECK:STDOUT:   %I.WithSelf.Hello.type: type = fn_type @I.WithSelf.Hello, @I.WithSelf(%T.loc8_8.1) [symbolic = %I.WithSelf.Hello.type (constants.%I.WithSelf.Hello.type.3eb)]\n// CHECK:STDOUT:   %.loc10: type = fn_type_with_self_type %I.WithSelf.Hello.type, %T.loc8_8.1 [symbolic = %.loc10 (constants.%.8de)]\n// CHECK:STDOUT:   %impl.elem0.loc10_4.2: @Use.%.loc10 (%.8de) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc10_4.2: <specific function> = specific_impl_function %impl.elem0.loc10_4.2, @I.WithSelf.Hello(%T.loc8_8.1) [symbolic = %specific_impl_fn.loc10_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @Use.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @Use.%T.binding.as_type (%T.binding.as_type) = name_ref x, %x\n// CHECK:STDOUT:     %Hello.ref: %I.assoc_type = name_ref Hello, @I.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc10_4.1: @Use.%.loc10 (%.8de) = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %specific_impl_fn.loc10_4.1: <specific function> = specific_impl_function %impl.elem0.loc10_4.1, @I.WithSelf.Hello(constants.%T) [symbolic = %specific_impl_fn.loc10_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %I.WithSelf.Hello.call: init %empty_tuple.type = call %specific_impl_fn.loc10_4.1()\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Use(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_8.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.422\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- access_assoc_method_indirect.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.Copy.decl [concrete]\n// CHECK:STDOUT:   %T: %I.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.422: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.ff7: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.Copy.type.035: type = fn_type @I.WithSelf.Copy, @I.WithSelf(%T) [symbolic]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T, @I [symbolic]\n// CHECK:STDOUT:   %.fa6: type = fn_type_with_self_type %I.WithSelf.Copy.type.035, %T [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.fa6 = impl_witness_access %I.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @I.WithSelf.Copy(%T) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @UseIndirect(%T.loc8_16.2: %I.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc8_16.1, @I [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness)]\n// CHECK:STDOUT:   %I.WithSelf.Copy.type: type = fn_type @I.WithSelf.Copy, @I.WithSelf(%T.loc8_16.1) [symbolic = %I.WithSelf.Copy.type (constants.%I.WithSelf.Copy.type.035)]\n// CHECK:STDOUT:   %.loc10_14.2: type = fn_type_with_self_type %I.WithSelf.Copy.type, %T.loc8_16.1 [symbolic = %.loc10_14.2 (constants.%.fa6)]\n// CHECK:STDOUT:   %impl.elem0.loc10_14.2: @UseIndirect.%.loc10_14.2 (%.fa6) = impl_witness_access %I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_14.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc10_14.2: <specific function> = specific_impl_function %impl.elem0.loc10_14.2, @I.WithSelf.Copy(%T.loc8_16.1) [symbolic = %specific_impl_fn.loc10_14.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @UseIndirect.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @UseIndirect.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @UseIndirect.%T.binding.as_type (%T.binding.as_type) = name_ref x, %x\n// CHECK:STDOUT:     %T.ref.loc10: %I.type = name_ref T, %T.loc8_16.2 [symbolic = %T.loc8_16.1 (constants.%T)]\n// CHECK:STDOUT:     %T.as_type.loc10: type = facet_access_type %T.ref.loc10 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc10_14.1: type = converted %T.ref.loc10, %T.as_type.loc10 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %Copy.ref: %I.assoc_type = name_ref Copy, @I.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc10_14.1: @UseIndirect.%.loc10_14.2 (%.fa6) = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_14.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %bound_method.loc10_11: <bound method> = bound_method %x.ref, %impl.elem0.loc10_14.1\n// CHECK:STDOUT:     %specific_impl_fn.loc10_14.1: <specific function> = specific_impl_function %impl.elem0.loc10_14.1, @I.WithSelf.Copy(constants.%T) [symbolic = %specific_impl_fn.loc10_14.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %bound_method.loc10_21: <bound method> = bound_method %x.ref, %specific_impl_fn.loc10_14.1\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %I.WithSelf.Copy.call: init @UseIndirect.%T.binding.as_type (%T.binding.as_type) to %.loc8_32.1 = call %bound_method.loc10_21(%x.ref)\n// CHECK:STDOUT:     return %I.WithSelf.Copy.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @UseIndirect(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_16.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.422\n// CHECK:STDOUT:   %.loc8_32.2 => constants.%.ff7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- access_constant_in_self_facet.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]\n// CHECK:STDOUT:   %Self: %A.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %A.assoc_type: type = assoc_entity_type @A [concrete]\n// CHECK:STDOUT:   %assoc0: %A.assoc_type = assoc_entity element0, @A.WithSelf.%X [concrete]\n// CHECK:STDOUT:   %.Self.091: %A.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.091 [symbolic_self]\n// CHECK:STDOUT:   %A.lookup_impl_witness.6a5: <witness> = lookup_impl_witness %.Self.091, @A [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %A.lookup_impl_witness.6a5, element0 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %A_where.type: type = facet_type <@A where %impl.elem0 = %empty_tuple.type> [concrete]\n// CHECK:STDOUT:   %pattern_type.dc8: type = pattern_type %A_where.type [concrete]\n// CHECK:STDOUT:   %AA: %A_where.type = symbolic_binding AA, 0 [symbolic]\n// CHECK:STDOUT:   %AA.binding.as_type: type = symbolic_binding_type AA, 0, %AA [symbolic]\n// CHECK:STDOUT:   %A.lookup_impl_witness.6c3: <witness> = lookup_impl_witness %AA, @A [symbolic]\n// CHECK:STDOUT:   %A.facet: %A.type = facet_value %AA.binding.as_type, (%A.lookup_impl_witness.6c3) [symbolic]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %A.decl: type = interface_decl @A [concrete = constants.%A.type] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %AA.patt: %pattern_type.dc8 = symbolic_binding_pattern AA, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AA.ref: %A_where.type = name_ref AA, %AA.loc6_6.2 [symbolic = %AA.loc6_6.1 (constants.%AA)]\n// CHECK:STDOUT:     %AA.as_type: type = facet_access_type %AA.ref [symbolic = %AA.binding.as_type (constants.%AA.binding.as_type)]\n// CHECK:STDOUT:     %.loc6_33.1: type = converted %AA.ref, %AA.as_type [symbolic = %AA.binding.as_type (constants.%AA.binding.as_type)]\n// CHECK:STDOUT:     %X.ref.loc6_33: %A.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc6_33: type = impl_witness_access constants.%A.lookup_impl_witness.6c3, element0 [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc6_33.2: Core.Form = init_form %impl.elem0.loc6_33 [concrete = constants.%.262]\n// CHECK:STDOUT:     %.loc6_13.1: type = splice_block %.loc6_13.2 [concrete = constants.%A_where.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.Self.ref: %A.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.091]\n// CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc6_19: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %X.ref.loc6_19: %A.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:       %impl.elem0.loc6_19: type = impl_witness_access constants.%A.lookup_impl_witness.6a5, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:       %.loc6_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc6_25.2: type = converted %.loc6_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.loc6_13.2: type = where_expr %.Self.2 [concrete = constants.%A_where.type] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%A.type\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc6_19, %.loc6_25.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %AA.loc6_6.2: %A_where.type = symbolic_binding AA, 0 [symbolic = %AA.loc6_6.1 (constants.%AA)]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @A {\n// CHECK:STDOUT:   %Self: %A.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %A.WithSelf.decl = interface_with_self_decl @A [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %X: type = assoc_const_decl @X [concrete] {\n// CHECK:STDOUT:     %assoc0: %A.assoc_type = assoc_entity element0, @A.WithSelf.%X [concrete = constants.%assoc0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .X = @X.%assoc0\n// CHECK:STDOUT:   witness = (@A.WithSelf.%X)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%AA.loc6_6.2: %A_where.type) {\n// CHECK:STDOUT:   %AA.loc6_6.1: %A_where.type = symbolic_binding AA, 0 [symbolic = %AA.loc6_6.1 (constants.%AA)]\n// CHECK:STDOUT:   %AA.binding.as_type: type = symbolic_binding_type AA, 0, %AA.loc6_6.1 [symbolic = %AA.binding.as_type (constants.%AA.binding.as_type)]\n// CHECK:STDOUT:   %A.lookup_impl_witness: <witness> = lookup_impl_witness %AA.loc6_6.1, @A [symbolic = %A.lookup_impl_witness (constants.%A.lookup_impl_witness.6c3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc7_11.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_11.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_12: init %empty_tuple.type = converted %.loc7_11.1, %.loc7_11.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     return %.loc7_12\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%.Self.091) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%AA) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%A.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%AA) {\n// CHECK:STDOUT:   %AA.loc6_6.1 => constants.%AA\n// CHECK:STDOUT:   %AA.binding.as_type => constants.%AA.binding.as_type\n// CHECK:STDOUT:   %A.lookup_impl_witness => constants.%A.lookup_impl_witness.6c3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- access_constant_in_self_facet_with_multiple_interfaces.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]\n// CHECK:STDOUT:   %A.assoc_type: type = assoc_entity_type @A [concrete]\n// CHECK:STDOUT:   %assoc0.df7: %A.assoc_type = assoc_entity element0, @A.WithSelf.%X [concrete]\n// CHECK:STDOUT:   %B.type: type = facet_type <@B> [concrete]\n// CHECK:STDOUT:   %B.assoc_type: type = assoc_entity_type @B [concrete]\n// CHECK:STDOUT:   %assoc0.6fa: %B.assoc_type = assoc_entity element0, @B.WithSelf.%Y [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.b10: type = facet_type <@BitAndWith, @BitAndWith(type)> [concrete]\n// CHECK:STDOUT:   %BitAndWith.impl_witness: <witness> = impl_witness imports.%BitAndWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %BitAndWith.facet: %BitAndWith.type.b10 = facet_value type, (%BitAndWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %BitAndWith.WithSelf.Op.type.4bd: type = fn_type @BitAndWith.WithSelf.Op, @BitAndWith.WithSelf(type, %BitAndWith.facet) [concrete]\n// CHECK:STDOUT:   %.d15: type = fn_type_with_self_type %BitAndWith.WithSelf.Op.type.4bd, %BitAndWith.facet [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.type: type = fn_type @type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op: %type.as.BitAndWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound: <bound method> = bound_method %A.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type.9bb: type = facet_type <@A & @B> [concrete]\n// CHECK:STDOUT:   %.Self.e7e: %facet_type.9bb = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.e7e [symbolic_self]\n// CHECK:STDOUT:   %A.lookup_impl_witness.6b3: <witness> = lookup_impl_witness %.Self.e7e, @A [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0.eb8: type = impl_witness_access %A.lookup_impl_witness.6b3, element0 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %B.lookup_impl_witness.d4f: <witness> = lookup_impl_witness %.Self.e7e, @B [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0.11d: type = impl_witness_access %B.lookup_impl_witness.d4f, element0 [symbolic_self]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %facet_type.82c: type = facet_type <@A & @B where %impl.elem0.eb8 = %empty_tuple.type and %impl.elem0.11d = %empty_struct_type> [concrete]\n// CHECK:STDOUT:   %pattern_type.77e: type = pattern_type %facet_type.82c [concrete]\n// CHECK:STDOUT:   %AB: %facet_type.82c = symbolic_binding AB, 0 [symbolic]\n// CHECK:STDOUT:   %AB.binding.as_type: type = symbolic_binding_type AB, 0, %AB [symbolic]\n// CHECK:STDOUT:   %A.lookup_impl_witness.1b9: <witness> = lookup_impl_witness %AB, @A [symbolic]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B.lookup_impl_witness.97b: <witness> = lookup_impl_witness %AB, @B [symbolic]\n// CHECK:STDOUT:   %.469: Core.Form = init_form %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.a96: type = pattern_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.8d3: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:   %BitAndWith.impl_witness_table = impl_witness_table (%Core.import_ref.8d3), @type.as.BitAndWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %AB.patt: %pattern_type.77e = symbolic_binding_pattern AB, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AB.ref: %facet_type.82c = name_ref AB, %AB.loc14_6.2 [symbolic = %AB.loc14_6.1 (constants.%AB)]\n// CHECK:STDOUT:     %AB.as_type: type = facet_access_type %AB.ref [symbolic = %AB.binding.as_type (constants.%AB.binding.as_type)]\n// CHECK:STDOUT:     %.loc14_49.1: type = converted %AB.ref, %AB.as_type [symbolic = %AB.binding.as_type (constants.%AB.binding.as_type)]\n// CHECK:STDOUT:     %X.ref.loc14_49: %A.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.df7]\n// CHECK:STDOUT:     %impl.elem0.loc14_49: type = impl_witness_access constants.%A.lookup_impl_witness.1b9, element0 [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc14_49.2: Core.Form = init_form %impl.elem0.loc14_49 [concrete = constants.%.262]\n// CHECK:STDOUT:     %.loc14_17.1: type = splice_block %.loc14_17.2 [concrete = constants.%facet_type.82c] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]\n// CHECK:STDOUT:       %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B.type]\n// CHECK:STDOUT:       %impl.elem0.loc14_13: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method: <bound method> = bound_method %A.ref, %impl.elem0.loc14_13 [concrete = constants.%type.as.BitAndWith.impl.Op.bound]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call: init type = call %bound_method(%A.ref, %B.ref) [concrete = constants.%facet_type.9bb]\n// CHECK:STDOUT:       %.loc14_13.1: type = value_of_initializer %type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type.9bb]\n// CHECK:STDOUT:       %.loc14_13.2: type = converted %type.as.BitAndWith.impl.Op.call, %.loc14_13.1 [concrete = constants.%facet_type.9bb]\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.Self.ref.loc14_23: %facet_type.9bb = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.e7e]\n// CHECK:STDOUT:       %.Self.as_type.loc14_23: type = facet_access_type %.Self.ref.loc14_23 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc14_23: type = converted %.Self.ref.loc14_23, %.Self.as_type.loc14_23 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %X.ref.loc14_23: %A.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.df7]\n// CHECK:STDOUT:       %impl.elem0.loc14_23: type = impl_witness_access constants.%A.lookup_impl_witness.6b3, element0 [symbolic_self = constants.%impl.elem0.eb8]\n// CHECK:STDOUT:       %.loc14_29.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc14_29.2: type = converted %.loc14_29.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.Self.ref.loc14_35: %facet_type.9bb = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.e7e]\n// CHECK:STDOUT:       %.Self.as_type.loc14_35: type = facet_access_type %.Self.ref.loc14_35 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc14_35: type = converted %.Self.ref.loc14_35, %.Self.as_type.loc14_35 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %Y.ref: %B.assoc_type = name_ref Y, @Y.%assoc0 [concrete = constants.%assoc0.6fa]\n// CHECK:STDOUT:       %impl.elem0.loc14_35: type = impl_witness_access constants.%B.lookup_impl_witness.d4f, element0 [symbolic_self = constants.%impl.elem0.11d]\n// CHECK:STDOUT:       %.loc14_41.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc14_41.2: type = converted %.loc14_41.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %.loc14_17.2: type = where_expr %.Self.2 [concrete = constants.%facet_type.82c] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%facet_type.9bb\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc14_23, %.loc14_29.2\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc14_35, %.loc14_41.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %AB.loc14_6.2: %facet_type.82c = symbolic_binding AB, 0 [symbolic = %AB.loc14_6.1 (constants.%AB)]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %AB.patt: %pattern_type.77e = symbolic_binding_pattern AB, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.a96 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.a96 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %AB.ref: %facet_type.82c = name_ref AB, %AB.loc18_6.2 [symbolic = %AB.loc18_6.1 (constants.%AB)]\n// CHECK:STDOUT:     %AB.as_type: type = facet_access_type %AB.ref [symbolic = %AB.binding.as_type (constants.%AB.binding.as_type)]\n// CHECK:STDOUT:     %.loc18_49.1: type = converted %AB.ref, %AB.as_type [symbolic = %AB.binding.as_type (constants.%AB.binding.as_type)]\n// CHECK:STDOUT:     %Y.ref.loc18_49: %B.assoc_type = name_ref Y, @Y.%assoc0 [concrete = constants.%assoc0.6fa]\n// CHECK:STDOUT:     %impl.elem0.loc18_49: type = impl_witness_access constants.%B.lookup_impl_witness.97b, element0 [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %.loc18_49.2: Core.Form = init_form %impl.elem0.loc18_49 [concrete = constants.%.469]\n// CHECK:STDOUT:     %.loc18_17.1: type = splice_block %.loc18_17.2 [concrete = constants.%facet_type.82c] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]\n// CHECK:STDOUT:       %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B.type]\n// CHECK:STDOUT:       %impl.elem0.loc18_13: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method: <bound method> = bound_method %A.ref, %impl.elem0.loc18_13 [concrete = constants.%type.as.BitAndWith.impl.Op.bound]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call: init type = call %bound_method(%A.ref, %B.ref) [concrete = constants.%facet_type.9bb]\n// CHECK:STDOUT:       %.loc18_13.1: type = value_of_initializer %type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type.9bb]\n// CHECK:STDOUT:       %.loc18_13.2: type = converted %type.as.BitAndWith.impl.Op.call, %.loc18_13.1 [concrete = constants.%facet_type.9bb]\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.Self.ref.loc18_23: %facet_type.9bb = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.e7e]\n// CHECK:STDOUT:       %.Self.as_type.loc18_23: type = facet_access_type %.Self.ref.loc18_23 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc18_23: type = converted %.Self.ref.loc18_23, %.Self.as_type.loc18_23 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %X.ref: %A.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.df7]\n// CHECK:STDOUT:       %impl.elem0.loc18_23: type = impl_witness_access constants.%A.lookup_impl_witness.6b3, element0 [symbolic_self = constants.%impl.elem0.eb8]\n// CHECK:STDOUT:       %.loc18_29.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc18_29.2: type = converted %.loc18_29.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.Self.ref.loc18_35: %facet_type.9bb = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.e7e]\n// CHECK:STDOUT:       %.Self.as_type.loc18_35: type = facet_access_type %.Self.ref.loc18_35 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc18_35: type = converted %.Self.ref.loc18_35, %.Self.as_type.loc18_35 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %Y.ref.loc18_35: %B.assoc_type = name_ref Y, @Y.%assoc0 [concrete = constants.%assoc0.6fa]\n// CHECK:STDOUT:       %impl.elem0.loc18_35: type = impl_witness_access constants.%B.lookup_impl_witness.d4f, element0 [symbolic_self = constants.%impl.elem0.11d]\n// CHECK:STDOUT:       %.loc18_41.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc18_41.2: type = converted %.loc18_41.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %.loc18_17.2: type = where_expr %.Self.2 [concrete = constants.%facet_type.82c] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%facet_type.9bb\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc18_23, %.loc18_29.2\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc18_35, %.loc18_41.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %AB.loc18_6.2: %facet_type.82c = symbolic_binding AB, 0 [symbolic = %AB.loc18_6.1 (constants.%AB)]\n// CHECK:STDOUT:     %return.param: ref %empty_struct_type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_struct_type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%AB.loc14_6.2: %facet_type.82c) {\n// CHECK:STDOUT:   %AB.loc14_6.1: %facet_type.82c = symbolic_binding AB, 0 [symbolic = %AB.loc14_6.1 (constants.%AB)]\n// CHECK:STDOUT:   %AB.binding.as_type: type = symbolic_binding_type AB, 0, %AB.loc14_6.1 [symbolic = %AB.binding.as_type (constants.%AB.binding.as_type)]\n// CHECK:STDOUT:   %A.lookup_impl_witness: <witness> = lookup_impl_witness %AB.loc14_6.1, @A [symbolic = %A.lookup_impl_witness (constants.%A.lookup_impl_witness.1b9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc15_11.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc15_11.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc15_12: init %empty_tuple.type = converted %.loc15_11.1, %.loc15_11.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     return %.loc15_12\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%AB.loc18_6.2: %facet_type.82c) {\n// CHECK:STDOUT:   %AB.loc18_6.1: %facet_type.82c = symbolic_binding AB, 0 [symbolic = %AB.loc18_6.1 (constants.%AB)]\n// CHECK:STDOUT:   %AB.binding.as_type: type = symbolic_binding_type AB, 0, %AB.loc18_6.1 [symbolic = %AB.binding.as_type (constants.%AB.binding.as_type)]\n// CHECK:STDOUT:   %B.lookup_impl_witness: <witness> = lookup_impl_witness %AB.loc18_6.1, @B [symbolic = %B.lookup_impl_witness (constants.%B.lookup_impl_witness.97b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %empty_struct_type {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc19_11.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc19_11.2: init %empty_struct_type = struct_init () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc19_12: init %empty_struct_type = converted %.loc19_11.1, %.loc19_11.2 [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     return %.loc19_12\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%AB) {\n// CHECK:STDOUT:   %AB.loc14_6.1 => constants.%AB\n// CHECK:STDOUT:   %AB.binding.as_type => constants.%AB.binding.as_type\n// CHECK:STDOUT:   %A.lookup_impl_witness => constants.%A.lookup_impl_witness.1b9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%AB) {\n// CHECK:STDOUT:   %AB.loc18_6.1 => constants.%AB\n// CHECK:STDOUT:   %AB.binding.as_type => constants.%AB.binding.as_type\n// CHECK:STDOUT:   %B.lookup_impl_witness => constants.%B.lookup_impl_witness.97b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/aggregate_through_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/aggregate_through_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/aggregate_through_access.carbon\n\n// --- fail_todo_tuple_access_through_witness.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let X:! type;\n}\n\n// CHECK:STDERR: fail_todo_tuple_access_through_witness.carbon:[[@LINE+4]]:34: error: type `type` does not support tuple indexing; only tuples can be indexed that way [TupleIndexOnANonTupleType]\n// CHECK:STDERR: fn F(T:! Z where .X = ({}, )) -> T.X.0 {\n// CHECK:STDERR:                                  ^~~~~\n// CHECK:STDERR:\nfn F(T:! Z where .X = ({}, )) -> T.X.0 {\n  return {};\n}\n\n// --- fail_todo_struct_access_through_witness.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let X:! type;\n}\n\n// CHECK:STDERR: fail_todo_struct_access_through_witness.carbon:[[@LINE+4]]:36: error: type `type` does not support qualified expressions [QualifiedExprUnsupported]\n// CHECK:STDERR: fn F(T:! Z where .X = {.t: ()}) -> T.X.t {\n// CHECK:STDERR:                                    ^~~~~\n// CHECK:STDERR:\nfn F(T:! Z where .X = {.t: ()}) -> T.X.t {\n  return ();\n}\n\n// --- fail_todo_array_access_through_witness.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let X:! type;\n}\n\n// CHECK:STDERR: fail_todo_array_access_through_witness.carbon:[[@LINE+4]]:40: error: cannot access member of interface `Core.IndexWith(Core.IntLiteral)` in type `type` that does not implement that interface [MissingImplInMemberAccess]\n// CHECK:STDERR: fn F(T:! Z where .X = array({}, 1)) -> T.X[0] {\n// CHECK:STDERR:                                        ^~~~~~\n// CHECK:STDERR:\nfn F(T:! Z where .X = array({}, 1)) -> T.X[0] {\n  return {};\n}\n\n// --- impl_access_through_witness.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let X1:! type;\n}\n\ninterface Y {\n  let X2:! type;\n}\n\nclass C;\nimpl C as Y where .X2 = {} {}\n\nfn F(T:! Z where .X1 = C) -> T.X1.(Y.X2) {\n  return {};\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/call_combined_impl_witness.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/call_combined_impl_witness.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/call_combined_impl_witness.carbon\n\ninterface Empty {\n}\ninterface A {\n  fn AA();\n}\ninterface B {\n  fn BB();\n}\n\nclass C {}\nimpl C as Empty {}\nimpl C as A {\n  fn AA() {}\n}\nimpl C as B {\n  fn BB() {}\n}\n\nfn G[T:! A & Empty & B](t: T) {\n  t.AA();\n  t.BB();\n\n  T.AA();\n  T.BB();\n\n  T.(A.AA)();\n  T.(B.BB)();\n}\n\nfn F() {\n  G({} as C);\n}\n\n// CHECK:STDOUT: --- call_combined_impl_witness.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Empty.type: type = facet_type <@Empty> [concrete]\n// CHECK:STDOUT:   %Self.61e: %Empty.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]\n// CHECK:STDOUT:   %Self.c51: %A.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %A.WithSelf.AA.type.236: type = fn_type @A.WithSelf.AA, @A.WithSelf(%Self.c51) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %A.WithSelf.AA.0c0: %A.WithSelf.AA.type.236 = struct_value () [symbolic]\n// CHECK:STDOUT:   %A.assoc_type: type = assoc_entity_type @A [concrete]\n// CHECK:STDOUT:   %assoc0.a62: %A.assoc_type = assoc_entity element0, @A.WithSelf.%A.WithSelf.AA.decl [concrete]\n// CHECK:STDOUT:   %B.type: type = facet_type <@B> [concrete]\n// CHECK:STDOUT:   %Self.d0b: %B.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %B.WithSelf.BB.type.17c: type = fn_type @B.WithSelf.BB, @B.WithSelf(%Self.d0b) [symbolic]\n// CHECK:STDOUT:   %B.WithSelf.BB.f00: %B.WithSelf.BB.type.17c = struct_value () [symbolic]\n// CHECK:STDOUT:   %B.assoc_type: type = assoc_entity_type @B [concrete]\n// CHECK:STDOUT:   %assoc0.00a: %B.assoc_type = assoc_entity element0, @B.WithSelf.%B.WithSelf.BB.decl [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Empty.impl_witness: <witness> = impl_witness @C.as.Empty.impl.%Empty.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Empty.facet: %Empty.type = facet_value %C, (%Empty.impl_witness) [concrete]\n// CHECK:STDOUT:   %A.impl_witness: <witness> = impl_witness @C.as.A.impl.%A.impl_witness_table [concrete]\n// CHECK:STDOUT:   %C.as.A.impl.AA.type: type = fn_type @C.as.A.impl.AA [concrete]\n// CHECK:STDOUT:   %C.as.A.impl.AA: %C.as.A.impl.AA.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.facet.34f: %A.type = facet_value %C, (%A.impl_witness) [concrete]\n// CHECK:STDOUT:   %A.WithSelf.AA.type.6ff: type = fn_type @A.WithSelf.AA, @A.WithSelf(%A.facet.34f) [concrete]\n// CHECK:STDOUT:   %A.WithSelf.AA.ff5: %A.WithSelf.AA.type.6ff = struct_value () [concrete]\n// CHECK:STDOUT:   %B.impl_witness: <witness> = impl_witness @C.as.B.impl.%B.impl_witness_table [concrete]\n// CHECK:STDOUT:   %C.as.B.impl.BB.type: type = fn_type @C.as.B.impl.BB [concrete]\n// CHECK:STDOUT:   %C.as.B.impl.BB: %C.as.B.impl.BB.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B.facet.e93: %B.type = facet_value %C, (%B.impl_witness) [concrete]\n// CHECK:STDOUT:   %B.WithSelf.BB.type.f5e: type = fn_type @B.WithSelf.BB, @B.WithSelf(%B.facet.e93) [concrete]\n// CHECK:STDOUT:   %B.WithSelf.BB.09b: %B.WithSelf.BB.type.f5e = struct_value () [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %BitAndWith.type.f2e: type = generic_interface_type @BitAndWith [concrete]\n// CHECK:STDOUT:   %BitAndWith.generic: %BitAndWith.type.f2e = struct_value () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.b10: type = facet_type <@BitAndWith, @BitAndWith(type)> [concrete]\n// CHECK:STDOUT:   %BitAndWith.impl_witness: <witness> = impl_witness imports.%BitAndWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %BitAndWith.facet: %BitAndWith.type.b10 = facet_value type, (%BitAndWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %BitAndWith.WithSelf.Op.type.4bd: type = fn_type @BitAndWith.WithSelf.Op, @BitAndWith.WithSelf(type, %BitAndWith.facet) [concrete]\n// CHECK:STDOUT:   %.d15: type = fn_type_with_self_type %BitAndWith.WithSelf.Op.type.4bd, %BitAndWith.facet [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.type: type = fn_type @type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op: %type.as.BitAndWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound.05b: <bound method> = bound_method %A.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type.902: type = facet_type <@Empty & @A> [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound.ab2: <bound method> = bound_method %facet_type.902, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type.dc7: type = facet_type <@Empty & @A & @B> [concrete]\n// CHECK:STDOUT:   %pattern_type.773: type = pattern_type %facet_type.dc7 [concrete]\n// CHECK:STDOUT:   %T: %facet_type.dc7 = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.2ee: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %A.WithSelf.AA.type.ce6: type = fn_type @A.WithSelf.AA, @A.WithSelf(%T) [symbolic]\n// CHECK:STDOUT:   %A.WithSelf.AA.020: %A.WithSelf.AA.type.ce6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %B.WithSelf.BB.type.374: type = fn_type @B.WithSelf.BB, @B.WithSelf(%T) [symbolic]\n// CHECK:STDOUT:   %B.WithSelf.BB.1c2: %B.WithSelf.BB.type.374 = struct_value () [symbolic]\n// CHECK:STDOUT:   %A.lookup_impl_witness: <witness> = lookup_impl_witness %T, @A [symbolic]\n// CHECK:STDOUT:   %A.facet.095: %A.type = facet_value %T.binding.as_type, (%A.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %A.WithSelf.AA.type.7b2: type = fn_type @A.WithSelf.AA, @A.WithSelf(%A.facet.095) [symbolic]\n// CHECK:STDOUT:   %A.WithSelf.AA.11e: %A.WithSelf.AA.type.7b2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.84b: type = fn_type_with_self_type %A.WithSelf.AA.type.7b2, %A.facet.095 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.26a: %.84b = impl_witness_access %A.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.567: <specific function> = specific_impl_function %impl.elem0.26a, @A.WithSelf.AA(%A.facet.095) [symbolic]\n// CHECK:STDOUT:   %B.lookup_impl_witness: <witness> = lookup_impl_witness %T, @B [symbolic]\n// CHECK:STDOUT:   %B.facet.0e7: %B.type = facet_value %T.binding.as_type, (%B.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %B.WithSelf.BB.type.5a2: type = fn_type @B.WithSelf.BB, @B.WithSelf(%B.facet.0e7) [symbolic]\n// CHECK:STDOUT:   %B.WithSelf.BB.b76: %B.WithSelf.BB.type.5a2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.dfd: type = fn_type_with_self_type %B.WithSelf.BB.type.5a2, %B.facet.0e7 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.557: %.dfd = impl_witness_access %B.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.fc3: <specific function> = specific_impl_function %impl.elem0.557, @B.WithSelf.BB(%B.facet.0e7) [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %facet_value: %facet_type.dc7 = facet_value %C, (%Empty.impl_witness, %A.impl_witness, %B.impl_witness) [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G, @G(%facet_value) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.171: type = fn_type_with_self_type %A.WithSelf.AA.type.6ff, %A.facet.34f [concrete]\n// CHECK:STDOUT:   %.e04: type = fn_type_with_self_type %B.WithSelf.BB.type.f5e, %B.facet.e93 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .BitAndWith = %Core.BitAndWith\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.BitAndWith: %BitAndWith.type.f2e = import_ref Core//prelude/parts/as, BitAndWith, loaded [concrete = constants.%BitAndWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.8d3: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:   %BitAndWith.impl_witness_table = impl_witness_table (%Core.import_ref.8d3), @type.as.BitAndWith.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Empty = %Empty.decl\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Empty.decl: type = interface_decl @Empty [concrete = constants.%Empty.type] {} {}\n// CHECK:STDOUT:   %A.decl: type = interface_decl @A [concrete = constants.%A.type] {} {}\n// CHECK:STDOUT:   %B.decl: type = interface_decl @B [concrete = constants.%B.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.Empty.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %Empty.ref: type = name_ref Empty, file.%Empty.decl [concrete = constants.%Empty.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.A.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.B.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.773 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %t.patt: @G.%pattern_type (%pattern_type.2ee) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: @G.%pattern_type (%pattern_type.2ee) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc33_20.1: type = splice_block %.loc33_20.3 [concrete = constants.%facet_type.dc7] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %A.ref.loc33: type = name_ref A, file.%A.decl [concrete = constants.%A.type]\n// CHECK:STDOUT:       %Empty.ref: type = name_ref Empty, file.%Empty.decl [concrete = constants.%Empty.type]\n// CHECK:STDOUT:       %impl.elem0.loc33_12: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method.loc33_12: <bound method> = bound_method %A.ref.loc33, %impl.elem0.loc33_12 [concrete = constants.%type.as.BitAndWith.impl.Op.bound.05b]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call.loc33_12: init type = call %bound_method.loc33_12(%A.ref.loc33, %Empty.ref) [concrete = constants.%facet_type.902]\n// CHECK:STDOUT:       %B.ref.loc33: type = name_ref B, file.%B.decl [concrete = constants.%B.type]\n// CHECK:STDOUT:       %impl.elem0.loc33_20: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method.loc33_20: <bound method> = bound_method %type.as.BitAndWith.impl.Op.call.loc33_12, %impl.elem0.loc33_20 [concrete = constants.%type.as.BitAndWith.impl.Op.bound.ab2]\n// CHECK:STDOUT:       %.loc33_12.1: type = value_of_initializer %type.as.BitAndWith.impl.Op.call.loc33_12 [concrete = constants.%facet_type.902]\n// CHECK:STDOUT:       %.loc33_12.2: type = converted %type.as.BitAndWith.impl.Op.call.loc33_12, %.loc33_12.1 [concrete = constants.%facet_type.902]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call.loc33_20: init type = call %bound_method.loc33_20(%.loc33_12.2, %B.ref.loc33) [concrete = constants.%facet_type.dc7]\n// CHECK:STDOUT:       %.loc33_20.2: type = value_of_initializer %type.as.BitAndWith.impl.Op.call.loc33_20 [concrete = constants.%facet_type.dc7]\n// CHECK:STDOUT:       %.loc33_20.3: type = converted %type.as.BitAndWith.impl.Op.call.loc33_20, %.loc33_20.2 [concrete = constants.%facet_type.dc7]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc33_6.2: %facet_type.dc7 = symbolic_binding T, 0 [symbolic = %T.loc33_6.1 (constants.%T)]\n// CHECK:STDOUT:     %t.param: @G.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc33_28.1: type = splice_block %.loc33_28.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref.loc33: %facet_type.dc7 = name_ref T, %T.loc33_6.2 [symbolic = %T.loc33_6.1 (constants.%T)]\n// CHECK:STDOUT:       %T.as_type.loc33: type = facet_access_type %T.ref.loc33 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc33_28.2: type = converted %T.ref.loc33, %T.as_type.loc33 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %t: @G.%T.binding.as_type (%T.binding.as_type) = value_binding t, %t.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Empty {\n// CHECK:STDOUT:   %Self: %Empty.type = symbolic_binding Self, 0 [symbolic = constants.%Self.61e]\n// CHECK:STDOUT:   %Empty.WithSelf.decl = interface_with_self_decl @Empty [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .AA = <poisoned>\n// CHECK:STDOUT:   .BB = <poisoned>\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @A {\n// CHECK:STDOUT:   %Self: %A.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c51]\n// CHECK:STDOUT:   %A.WithSelf.decl = interface_with_self_decl @A [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %A.WithSelf.AA.decl: @A.WithSelf.%A.WithSelf.AA.type (%A.WithSelf.AA.type.236) = fn_decl @A.WithSelf.AA [symbolic = @A.WithSelf.%A.WithSelf.AA (constants.%A.WithSelf.AA.0c0)] {} {}\n// CHECK:STDOUT:   %assoc0: %A.assoc_type = assoc_entity element0, %A.WithSelf.AA.decl [concrete = constants.%assoc0.a62]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .AA = @A.WithSelf.%assoc0\n// CHECK:STDOUT:   .BB = <poisoned>\n// CHECK:STDOUT:   witness = (@A.WithSelf.%A.WithSelf.AA.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @B {\n// CHECK:STDOUT:   %Self: %B.type = symbolic_binding Self, 0 [symbolic = constants.%Self.d0b]\n// CHECK:STDOUT:   %B.WithSelf.decl = interface_with_self_decl @B [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %B.WithSelf.BB.decl: @B.WithSelf.%B.WithSelf.BB.type (%B.WithSelf.BB.type.17c) = fn_decl @B.WithSelf.BB [symbolic = @B.WithSelf.%B.WithSelf.BB (constants.%B.WithSelf.BB.f00)] {} {}\n// CHECK:STDOUT:   %assoc0: %B.assoc_type = assoc_entity element0, %B.WithSelf.BB.decl [concrete = constants.%assoc0.00a]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .BB = @B.WithSelf.%assoc0\n// CHECK:STDOUT:   .AA = <poisoned>\n// CHECK:STDOUT:   witness = (@B.WithSelf.%B.WithSelf.BB.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.Empty.impl: %C.ref as %Empty.ref {\n// CHECK:STDOUT:   %Empty.impl_witness_table = impl_witness_table (), @C.as.Empty.impl [concrete]\n// CHECK:STDOUT:   %Empty.impl_witness: <witness> = impl_witness %Empty.impl_witness_table [concrete = constants.%Empty.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Empty.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.A.impl: %C.ref as %A.ref {\n// CHECK:STDOUT:   %C.as.A.impl.AA.decl: %C.as.A.impl.AA.type = fn_decl @C.as.A.impl.AA [concrete = constants.%C.as.A.impl.AA] {} {}\n// CHECK:STDOUT:   %A.impl_witness_table = impl_witness_table (%C.as.A.impl.AA.decl), @C.as.A.impl [concrete]\n// CHECK:STDOUT:   %A.impl_witness: <witness> = impl_witness %A.impl_witness_table [concrete = constants.%A.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .AA = %C.as.A.impl.AA.decl\n// CHECK:STDOUT:   witness = %A.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.B.impl: %C.ref as %B.ref {\n// CHECK:STDOUT:   %C.as.B.impl.BB.decl: %C.as.B.impl.BB.type = fn_decl @C.as.B.impl.BB [concrete = constants.%C.as.B.impl.BB] {} {}\n// CHECK:STDOUT:   %B.impl_witness_table = impl_witness_table (%C.as.B.impl.BB.decl), @C.as.B.impl [concrete]\n// CHECK:STDOUT:   %B.impl_witness: <witness> = impl_witness %B.impl_witness_table [concrete = constants.%B.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .BB = %C.as.B.impl.BB.decl\n// CHECK:STDOUT:   witness = %B.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @A.WithSelf.AA(@A.%Self: %A.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @B.WithSelf.BB(@B.%Self: %B.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.A.impl.AA() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.B.impl.BB() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%T.loc33_6.2: %facet_type.dc7) {\n// CHECK:STDOUT:   %T.loc33_6.1: %facet_type.dc7 = symbolic_binding T, 0 [symbolic = %T.loc33_6.1 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc33_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.2ee)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %A.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc33_6.1, @A [symbolic = %A.lookup_impl_witness (constants.%A.lookup_impl_witness)]\n// CHECK:STDOUT:   %A.facet.loc34: %A.type = facet_value %T.binding.as_type, (%A.lookup_impl_witness) [symbolic = %A.facet.loc34 (constants.%A.facet.095)]\n// CHECK:STDOUT:   %A.WithSelf.AA.type: type = fn_type @A.WithSelf.AA, @A.WithSelf(%A.facet.loc34) [symbolic = %A.WithSelf.AA.type (constants.%A.WithSelf.AA.type.7b2)]\n// CHECK:STDOUT:   %.loc34: type = fn_type_with_self_type %A.WithSelf.AA.type, %A.facet.loc34 [symbolic = %.loc34 (constants.%.84b)]\n// CHECK:STDOUT:   %impl.elem0.loc34_4.2: @G.%.loc34 (%.84b) = impl_witness_access %A.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc34_4.2 (constants.%impl.elem0.26a)]\n// CHECK:STDOUT:   %specific_impl_fn.loc34_4.2: <specific function> = specific_impl_function %impl.elem0.loc34_4.2, @A.WithSelf.AA(%A.facet.loc34) [symbolic = %specific_impl_fn.loc34_4.2 (constants.%specific_impl_fn.567)]\n// CHECK:STDOUT:   %B.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc33_6.1, @B [symbolic = %B.lookup_impl_witness (constants.%B.lookup_impl_witness)]\n// CHECK:STDOUT:   %B.facet.loc35: %B.type = facet_value %T.binding.as_type, (%B.lookup_impl_witness) [symbolic = %B.facet.loc35 (constants.%B.facet.0e7)]\n// CHECK:STDOUT:   %B.WithSelf.BB.type: type = fn_type @B.WithSelf.BB, @B.WithSelf(%B.facet.loc35) [symbolic = %B.WithSelf.BB.type (constants.%B.WithSelf.BB.type.5a2)]\n// CHECK:STDOUT:   %.loc35: type = fn_type_with_self_type %B.WithSelf.BB.type, %B.facet.loc35 [symbolic = %.loc35 (constants.%.dfd)]\n// CHECK:STDOUT:   %impl.elem0.loc35_4.2: @G.%.loc35 (%.dfd) = impl_witness_access %B.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc35_4.2 (constants.%impl.elem0.557)]\n// CHECK:STDOUT:   %specific_impl_fn.loc35_4.2: <specific function> = specific_impl_function %impl.elem0.loc35_4.2, @B.WithSelf.BB(%B.facet.loc35) [symbolic = %specific_impl_fn.loc35_4.2 (constants.%specific_impl_fn.fc3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%t.param: @G.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %t.ref.loc34: @G.%T.binding.as_type (%T.binding.as_type) = name_ref t, %t\n// CHECK:STDOUT:     %AA.ref.loc34: %A.assoc_type = name_ref AA, @A.WithSelf.%assoc0 [concrete = constants.%assoc0.a62]\n// CHECK:STDOUT:     %impl.elem0.loc34_4.1: @G.%.loc34 (%.84b) = impl_witness_access constants.%A.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc34_4.2 (constants.%impl.elem0.26a)]\n// CHECK:STDOUT:     %specific_impl_fn.loc34_4.1: <specific function> = specific_impl_function %impl.elem0.loc34_4.1, @A.WithSelf.AA(constants.%A.facet.095) [symbolic = %specific_impl_fn.loc34_4.2 (constants.%specific_impl_fn.567)]\n// CHECK:STDOUT:     %A.WithSelf.AA.call.loc34: init %empty_tuple.type = call %specific_impl_fn.loc34_4.1()\n// CHECK:STDOUT:     %t.ref.loc35: @G.%T.binding.as_type (%T.binding.as_type) = name_ref t, %t\n// CHECK:STDOUT:     %BB.ref.loc35: %B.assoc_type = name_ref BB, @B.WithSelf.%assoc0 [concrete = constants.%assoc0.00a]\n// CHECK:STDOUT:     %impl.elem0.loc35_4.1: @G.%.loc35 (%.dfd) = impl_witness_access constants.%B.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc35_4.2 (constants.%impl.elem0.557)]\n// CHECK:STDOUT:     %specific_impl_fn.loc35_4.1: <specific function> = specific_impl_function %impl.elem0.loc35_4.1, @B.WithSelf.BB(constants.%B.facet.0e7) [symbolic = %specific_impl_fn.loc35_4.2 (constants.%specific_impl_fn.fc3)]\n// CHECK:STDOUT:     %B.WithSelf.BB.call.loc35: init %empty_tuple.type = call %specific_impl_fn.loc35_4.1()\n// CHECK:STDOUT:     %T.ref.loc37: %facet_type.dc7 = name_ref T, %T.loc33_6.2 [symbolic = %T.loc33_6.1 (constants.%T)]\n// CHECK:STDOUT:     %T.as_type.loc37: type = facet_access_type %T.ref.loc37 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc37: type = converted %T.ref.loc37, %T.as_type.loc37 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %AA.ref.loc37: %A.assoc_type = name_ref AA, @A.WithSelf.%assoc0 [concrete = constants.%assoc0.a62]\n// CHECK:STDOUT:     %impl.elem0.loc37: @G.%.loc34 (%.84b) = impl_witness_access constants.%A.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc34_4.2 (constants.%impl.elem0.26a)]\n// CHECK:STDOUT:     %specific_impl_fn.loc37: <specific function> = specific_impl_function %impl.elem0.loc37, @A.WithSelf.AA(constants.%A.facet.095) [symbolic = %specific_impl_fn.loc34_4.2 (constants.%specific_impl_fn.567)]\n// CHECK:STDOUT:     %A.WithSelf.AA.call.loc37: init %empty_tuple.type = call %specific_impl_fn.loc37()\n// CHECK:STDOUT:     %T.ref.loc38: %facet_type.dc7 = name_ref T, %T.loc33_6.2 [symbolic = %T.loc33_6.1 (constants.%T)]\n// CHECK:STDOUT:     %T.as_type.loc38: type = facet_access_type %T.ref.loc38 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc38: type = converted %T.ref.loc38, %T.as_type.loc38 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %BB.ref.loc38: %B.assoc_type = name_ref BB, @B.WithSelf.%assoc0 [concrete = constants.%assoc0.00a]\n// CHECK:STDOUT:     %impl.elem0.loc38: @G.%.loc35 (%.dfd) = impl_witness_access constants.%B.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc35_4.2 (constants.%impl.elem0.557)]\n// CHECK:STDOUT:     %specific_impl_fn.loc38: <specific function> = specific_impl_function %impl.elem0.loc38, @B.WithSelf.BB(constants.%B.facet.0e7) [symbolic = %specific_impl_fn.loc35_4.2 (constants.%specific_impl_fn.fc3)]\n// CHECK:STDOUT:     %B.WithSelf.BB.call.loc38: init %empty_tuple.type = call %specific_impl_fn.loc38()\n// CHECK:STDOUT:     %T.ref.loc40: %facet_type.dc7 = name_ref T, %T.loc33_6.2 [symbolic = %T.loc33_6.1 (constants.%T)]\n// CHECK:STDOUT:     %A.ref.loc40: type = name_ref A, file.%A.decl [concrete = constants.%A.type]\n// CHECK:STDOUT:     %AA.ref.loc40: %A.assoc_type = name_ref AA, @A.WithSelf.%assoc0 [concrete = constants.%assoc0.a62]\n// CHECK:STDOUT:     %T.as_type.loc40: type = facet_access_type %T.ref.loc40 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %A.facet.loc40: %A.type = facet_value %T.as_type.loc40, (constants.%A.lookup_impl_witness) [symbolic = %A.facet.loc34 (constants.%A.facet.095)]\n// CHECK:STDOUT:     %.loc40: %A.type = converted %T.ref.loc40, %A.facet.loc40 [symbolic = %A.facet.loc34 (constants.%A.facet.095)]\n// CHECK:STDOUT:     %impl.elem0.loc40: @G.%.loc34 (%.84b) = impl_witness_access constants.%A.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc34_4.2 (constants.%impl.elem0.26a)]\n// CHECK:STDOUT:     %specific_impl_fn.loc40: <specific function> = specific_impl_function %impl.elem0.loc40, @A.WithSelf.AA(constants.%A.facet.095) [symbolic = %specific_impl_fn.loc34_4.2 (constants.%specific_impl_fn.567)]\n// CHECK:STDOUT:     %A.WithSelf.AA.call.loc40: init %empty_tuple.type = call %specific_impl_fn.loc40()\n// CHECK:STDOUT:     %T.ref.loc41: %facet_type.dc7 = name_ref T, %T.loc33_6.2 [symbolic = %T.loc33_6.1 (constants.%T)]\n// CHECK:STDOUT:     %B.ref.loc41: type = name_ref B, file.%B.decl [concrete = constants.%B.type]\n// CHECK:STDOUT:     %BB.ref.loc41: %B.assoc_type = name_ref BB, @B.WithSelf.%assoc0 [concrete = constants.%assoc0.00a]\n// CHECK:STDOUT:     %T.as_type.loc41: type = facet_access_type %T.ref.loc41 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %B.facet.loc41: %B.type = facet_value %T.as_type.loc41, (constants.%B.lookup_impl_witness) [symbolic = %B.facet.loc35 (constants.%B.facet.0e7)]\n// CHECK:STDOUT:     %.loc41: %B.type = converted %T.ref.loc41, %B.facet.loc41 [symbolic = %B.facet.loc35 (constants.%B.facet.0e7)]\n// CHECK:STDOUT:     %impl.elem0.loc41: @G.%.loc35 (%.dfd) = impl_witness_access constants.%B.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc35_4.2 (constants.%impl.elem0.557)]\n// CHECK:STDOUT:     %specific_impl_fn.loc41: <specific function> = specific_impl_function %impl.elem0.loc41, @B.WithSelf.BB(constants.%B.facet.0e7) [symbolic = %specific_impl_fn.loc35_4.2 (constants.%specific_impl_fn.fc3)]\n// CHECK:STDOUT:     %B.WithSelf.BB.call.loc41: init %empty_tuple.type = call %specific_impl_fn.loc41()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %.loc45_6.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc45_6.2: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc45_6.3: init %C to %.loc45_6.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc45_8.1: init %C = converted %.loc45_6.1, %.loc45_6.3 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %facet_value: %facet_type.dc7 = facet_value constants.%C, (constants.%Empty.impl_witness, constants.%A.impl_witness, constants.%B.impl_witness) [concrete = constants.%facet_value]\n// CHECK:STDOUT:   %.loc45_12: %facet_type.dc7 = converted constants.%C, %facet_value [concrete = constants.%facet_value]\n// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G.ref, @G(constants.%facet_value) [concrete = constants.%G.specific_fn]\n// CHECK:STDOUT:   %.loc45_8.2: ref %C = temporary %.loc45_6.2, %.loc45_8.1\n// CHECK:STDOUT:   %.loc45_8.3: %C = acquire_value %.loc45_8.2\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.specific_fn(%.loc45_8.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc45_8.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc45_8.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Empty.WithSelf(constants.%Self.61e) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%Self.c51) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.c51\n// CHECK:STDOUT:   %A.WithSelf.AA.type => constants.%A.WithSelf.AA.type.236\n// CHECK:STDOUT:   %A.WithSelf.AA => constants.%A.WithSelf.AA.0c0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf.AA(constants.%Self.c51) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.WithSelf(constants.%Self.d0b) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.d0b\n// CHECK:STDOUT:   %B.WithSelf.BB.type => constants.%B.WithSelf.BB.type.17c\n// CHECK:STDOUT:   %B.WithSelf.BB => constants.%B.WithSelf.BB.f00\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.WithSelf.BB(constants.%Self.d0b) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Empty.WithSelf(constants.%Empty.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%A.facet.34f) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%A.facet.34f\n// CHECK:STDOUT:   %A.WithSelf.AA.type => constants.%A.WithSelf.AA.type.6ff\n// CHECK:STDOUT:   %A.WithSelf.AA => constants.%A.WithSelf.AA.ff5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf.AA(constants.%A.facet.34f) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.WithSelf(constants.%B.facet.e93) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%B.facet.e93\n// CHECK:STDOUT:   %B.WithSelf.BB.type => constants.%B.WithSelf.BB.type.f5e\n// CHECK:STDOUT:   %B.WithSelf.BB => constants.%B.WithSelf.BB.09b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.WithSelf.BB(constants.%B.facet.e93) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%T) {\n// CHECK:STDOUT:   %T.loc33_6.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.2ee\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Empty.WithSelf(constants.%T) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%T) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%T\n// CHECK:STDOUT:   %A.WithSelf.AA.type => constants.%A.WithSelf.AA.type.ce6\n// CHECK:STDOUT:   %A.WithSelf.AA => constants.%A.WithSelf.AA.020\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.WithSelf(constants.%T) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%T\n// CHECK:STDOUT:   %B.WithSelf.BB.type => constants.%B.WithSelf.BB.type.374\n// CHECK:STDOUT:   %B.WithSelf.BB => constants.%B.WithSelf.BB.1c2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%A.facet.095) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%A.facet.095\n// CHECK:STDOUT:   %A.WithSelf.AA.type => constants.%A.WithSelf.AA.type.7b2\n// CHECK:STDOUT:   %A.WithSelf.AA => constants.%A.WithSelf.AA.11e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf.AA(constants.%A.facet.095) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.WithSelf(constants.%B.facet.0e7) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%B.facet.0e7\n// CHECK:STDOUT:   %B.WithSelf.BB.type => constants.%B.WithSelf.BB.type.5a2\n// CHECK:STDOUT:   %B.WithSelf.BB => constants.%B.WithSelf.BB.b76\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.WithSelf.BB(constants.%B.facet.0e7) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%facet_value) {\n// CHECK:STDOUT:   %T.loc33_6.1 => constants.%facet_value\n// CHECK:STDOUT:   %T.binding.as_type => constants.%C\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT:   %A.lookup_impl_witness => constants.%A.impl_witness\n// CHECK:STDOUT:   %A.facet.loc34 => constants.%A.facet.34f\n// CHECK:STDOUT:   %A.WithSelf.AA.type => constants.%A.WithSelf.AA.type.6ff\n// CHECK:STDOUT:   %.loc34 => constants.%.171\n// CHECK:STDOUT:   %impl.elem0.loc34_4.2 => constants.%C.as.A.impl.AA\n// CHECK:STDOUT:   %specific_impl_fn.loc34_4.2 => constants.%C.as.A.impl.AA\n// CHECK:STDOUT:   %B.lookup_impl_witness => constants.%B.impl_witness\n// CHECK:STDOUT:   %B.facet.loc35 => constants.%B.facet.e93\n// CHECK:STDOUT:   %B.WithSelf.BB.type => constants.%B.WithSelf.BB.type.f5e\n// CHECK:STDOUT:   %.loc35 => constants.%.e04\n// CHECK:STDOUT:   %impl.elem0.loc35_4.2 => constants.%C.as.B.impl.BB\n// CHECK:STDOUT:   %specific_impl_fn.loc35_4.2 => constants.%C.as.B.impl.BB\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/combine.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/combine.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/combine.carbon\n\n// --- fail_name_collision.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A {\n  fn G();\n}\ninterface B {\n  fn G();\n}\n\nclass C {}\nimpl C as A {\n  fn G();\n}\nimpl C as B {\n  fn G() {}\n}\n\nfn F() {\n  // TODO: This error message is wrong here, we are not using `extend`.\n\n  // CHECK:STDERR: fail_name_collision.carbon:[[@LINE+4]]:14: error: ambiguous use of name `G` found in multiple extended scopes [NameAmbiguousDueToExtend]\n  // CHECK:STDERR:   ({} as C).((A & B).G)();\n  // CHECK:STDERR:              ^~~~~~~~~\n  // CHECK:STDERR:\n  ({} as C).((A & B).G)();\n}\n\n// --- combine.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A {}\ninterface B {\n  fn BB[self: Self]();\n}\n\nclass C {}\nimpl C as A {}\nimpl C as B {\n  fn BB[unused self: Self]() {}\n}\n\nfn G[T:! A & B](unused t: T) {}\n\nfn F() {\n  ({} as C).((A & B).BB)();\n\n  (({} as C) as (C as (A & B))).((A & B).BB)();\n  (({} as C) as (C as (A & B))).(B.BB)();\n\n  G({} as C);\n}\n\n// --- generic_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A(T:! type) {}\ninterface B {}\n\nclass P1 {}\nclass P2 {}\n\nclass C {}\nimpl C as A(P1) {}\nimpl C as B {}\n\nfn G[T:! A(P1) & B](unused t: T) {}\n\nfn F() {\n  G({} as C);\n}\n\n// --- fail_wrong_generic_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A(T:! type) {}\ninterface B {}\n\nclass P1 {}\nclass P2 {}\n\nclass C {}\nimpl C as A(P1) {}\nimpl C as B {}\n\nfn G[T:! A(P2) & B](unused t: T) {}\n\nfn F() {\n  // CHECK:STDERR: fail_wrong_generic_interface.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `A(P2) & B` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   G({} as C);\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR: fail_wrong_generic_interface.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn G[T:! A(P2) & B](unused t: T) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  G({} as C);\n}\n\n// --- generic_forall_impl.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Iface {}\ninterface GenericIface(T:! type) {}\n\nclass GenericClass(T:! type) {}\n\nclass ImplIface {}\nimpl ImplIface as Iface {}\n\nclass C {}\nimpl C as Iface {}\n\nimpl forall [IfaceType:! Iface] C as GenericIface(GenericClass(IfaceType)) {}\n\nfn G[T:! Iface & GenericIface(GenericClass(ImplIface))](unused t: T) {}\n\nfn F() {\n  G({} as C);\n}\n\n// --- compare_equal.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass WrapType(T:! type) {}\nfn AssertSame[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}\nfn Type(T:! type) -> WrapType(T) { return {}; }\n\ninterface I;\ninterface J;\ninterface K(T:! type);\n\nfn TestIncomplete() {\n  AssertSame(Type(I), Type(I & I));\n  AssertSame(Type(I), Type(I & I & I));\n  AssertSame(Type(I & J), Type(J & I));\n  AssertSame(Type(I & J), Type(I & I & J));\n  AssertSame(Type(I & J), Type(I & J & I));\n  AssertSame(Type(I & J), Type(J & I & I));\n  AssertSame(Type(I & K({})), Type(K({}) & I));\n  AssertSame(Type(I & K({}) & K(())), Type(K(()) & K({}) & I));\n}\n\ninterface I {}\ninterface J {}\ninterface K(T:! type) {}\n\nfn TestComplete() {\n  AssertSame(Type(I), Type(I & I));\n  AssertSame(Type(I), Type(I & I & I));\n  AssertSame(Type(I & J), Type(J & I));\n  AssertSame(Type(I & J), Type(I & I & J));\n  AssertSame(Type(I & J), Type(I & J & I));\n  AssertSame(Type(I & J), Type(J & I & I));\n  AssertSame(Type(I & K({})), Type(K({}) & I));\n  AssertSame(Type(I & K({}) & K(())), Type(K(()) & K({}) & I));\n}\n\n// --- fail_compare_not_equal.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass WrapType(T:! type) {}\nfn Same[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}\nfn Type(T:! type) -> WrapType(T) { return {}; }\n\ninterface I {}\ninterface J {}\ninterface K {}\n\nfn Test() {\n  // CHECK:STDERR: fail_compare_not_equal.carbon:[[@LINE+7]]:3: error: inconsistent deductions for value of generic parameter `T` [DeductionInconsistent]\n  // CHECK:STDERR:   Same(Type(I & J), Type(K & I & J));\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_compare_not_equal.carbon:[[@LINE-11]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn Same[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Same(Type(I & J), Type(K & I & J));\n}\n\n// --- fail_compare_not_equal_parameterized.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass WrapType(T:! type) {}\nfn Same[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}\nfn Type(T:! type) -> WrapType(T) { return {}; }\n\ninterface I {}\ninterface J(T:! type) {}\n\nfn Test() {\n  // CHECK:STDERR: fail_compare_not_equal_parameterized.carbon:[[@LINE+7]]:3: error: inconsistent deductions for value of generic parameter `T` [DeductionInconsistent]\n  // CHECK:STDERR:   Same(Type(I & J(())), Type(J({}) & I));\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_compare_not_equal_parameterized.carbon:[[@LINE-10]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn Same[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Same(Type(I & J(())), Type(J({}) & I));\n}\n\n// --- fail_compare_not_equal_parameterized_extra.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass WrapType(T:! type) {}\nfn Same[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}\nfn Type(T:! type) -> WrapType(T) { return {}; }\n\ninterface I {}\ninterface J(T:! type) {}\n\nfn Test() {\n  // CHECK:STDERR: fail_compare_not_equal_parameterized_extra.carbon:[[@LINE+7]]:3: error: inconsistent deductions for value of generic parameter `T` [DeductionInconsistent]\n  // CHECK:STDERR:   Same(Type(I & J(())), Type(J(()) & J({}) & I));\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_compare_not_equal_parameterized_extra.carbon:[[@LINE-10]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn Same[T:! type](unused a: WrapType(T), unused b: WrapType(T)) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Same(Type(I & J(())), Type(J(()) & J({}) & I));\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_class_type_to_facet_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_class_type_to_facet_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_class_type_to_facet_type.carbon\n\ninterface Animal {}\n\nclass Goat {}\nimpl Goat as Animal {}\n\nfn WalkAnimal(unused A:! Animal) {}\n\nfn F() {\n  WalkAnimal(Goat);\n}\n\n// CHECK:STDOUT: --- convert_class_type_to_facet_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Goat: type = class_type @Goat [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness @Goat.as.Animal.impl.%Animal.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat, (%Animal.impl_witness) [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Animal.type [concrete]\n// CHECK:STDOUT:   %A: %Animal.type = symbolic_binding A, 0 [symbolic]\n// CHECK:STDOUT:   %WalkAnimal.type: type = fn_type @WalkAnimal [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %WalkAnimal: %WalkAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %WalkAnimal.specific_fn: <specific function> = specific_function %WalkAnimal, @WalkAnimal(%Animal.facet) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .Goat = %Goat.decl\n// CHECK:STDOUT:     .WalkAnimal = %WalkAnimal.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   %Goat.decl: type = class_decl @Goat [concrete = constants.%Goat] {} {}\n// CHECK:STDOUT:   impl_decl @Goat.as.Animal.impl [concrete] {} {\n// CHECK:STDOUT:     %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:     %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %WalkAnimal.decl: %WalkAnimal.type = fn_decl @WalkAnimal [concrete = constants.%WalkAnimal] {\n// CHECK:STDOUT:     %A.patt: %pattern_type = symbolic_binding_pattern A, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc20: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %A.loc20_22.2: %Animal.type = symbolic_binding A, 0 [symbolic = %A.loc20_22.1 (constants.%A)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Goat.as.Animal.impl: %Goat.ref as %Animal.ref {\n// CHECK:STDOUT:   %Animal.impl_witness_table = impl_witness_table (), @Goat.as.Animal.impl [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness %Animal.impl_witness_table [concrete = constants.%Animal.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Animal.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Goat {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Goat\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @WalkAnimal(%A.loc20_22.2: %Animal.type) {\n// CHECK:STDOUT:   %A.loc20_22.1: %Animal.type = symbolic_binding A, 0 [symbolic = %A.loc20_22.1 (constants.%A)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %WalkAnimal.ref: %WalkAnimal.type = name_ref WalkAnimal, file.%WalkAnimal.decl [concrete = constants.%WalkAnimal]\n// CHECK:STDOUT:   %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat.ref, (constants.%Animal.impl_witness) [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %.loc23: %Animal.type = converted %Goat.ref, %Animal.facet [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %WalkAnimal.specific_fn: <specific function> = specific_function %WalkAnimal.ref, @WalkAnimal(constants.%Animal.facet) [concrete = constants.%WalkAnimal.specific_fn]\n// CHECK:STDOUT:   %WalkAnimal.call: init %empty_tuple.type = call %WalkAnimal.specific_fn()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Animal.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WalkAnimal(constants.%A) {\n// CHECK:STDOUT:   %A.loc20_22.1 => constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WalkAnimal(constants.%Animal.facet) {\n// CHECK:STDOUT:   %A.loc20_22.1 => constants.%Animal.facet\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_class_type_to_generic_facet_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_class_type_to_generic_facet_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_class_type_to_generic_facet_value.carbon\n\n// --- generic_facet_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Generic(Scalar:! type) {\n  fn F();\n}\n\nclass GenericParam {}\n\nclass ImplsGeneric {}\nimpl ImplsGeneric as Generic(GenericParam) {\n  fn F() {}\n}\n\nfn CallGenericMethod(T:! type, unused U:! Generic(T)) {}\n\nfn G() {\n  CallGenericMethod(GenericParam, ImplsGeneric);\n}\n\nfn PassThroughToGenericMethod(T:! type, U:! Generic(T)) {\n  CallGenericMethod(T, U);\n}\n\nfn H() {\n  PassThroughToGenericMethod(GenericParam, ImplsGeneric);\n}\n\n// --- generic_facet_type_from_implicit_param.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Generic(Scalar:! type) {\n  fn F();\n}\n\nclass GenericParam {}\n\nclass ImplsGeneric {}\nimpl ImplsGeneric as Generic(GenericParam) {\n  fn F() {}\n}\n\nfn CallGenericMethod[T:! type](unused U:! Generic(T), unused t: T) {}\n\nfn G() {\n  CallGenericMethod(ImplsGeneric, {} as GenericParam);\n}\n\n// CHECK:STDOUT: --- generic_facet_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %Scalar: type = symbolic_binding Scalar, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.835: type = generic_interface_type @Generic [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Generic.generic: %Generic.type.835 = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.type.03dff7.1: type = facet_type <@Generic, @Generic(%Scalar)> [symbolic]\n// CHECK:STDOUT:   %Self.15d2d5.1: %Generic.type.03dff7.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.74390a.1: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%Scalar, %Self.15d2d5.1) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.baf95a.1: %Generic.WithSelf.F.type.74390a.1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.22afda.1: type = assoc_entity_type @Generic, @Generic(%Scalar) [symbolic]\n// CHECK:STDOUT:   %assoc0.e0dc00.1: %Generic.assoc_type.22afda.1 = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %GenericParam: type = class_type @GenericParam [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ImplsGeneric: type = class_type @ImplsGeneric [concrete]\n// CHECK:STDOUT:   %Generic.type.498: type = facet_type <@Generic, @Generic(%GenericParam)> [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness @ImplsGeneric.as.Generic.impl.%Generic.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.1f5: %Generic.type.498 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.a23: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Self.15d2d5.1) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.fe0: %Generic.WithSelf.F.type.a23 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.6dc: type = assoc_entity_type @Generic, @Generic(%GenericParam) [concrete]\n// CHECK:STDOUT:   %assoc0.717: %Generic.assoc_type.6dc = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.type: type = fn_type @ImplsGeneric.as.Generic.impl.F [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F: %ImplsGeneric.as.Generic.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value %ImplsGeneric, (%Generic.impl_witness) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.c86: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.1fd: %Generic.WithSelf.F.type.c86 = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.03dff7.2: type = facet_type <@Generic, @Generic(%T)> [symbolic]\n// CHECK:STDOUT:   %pattern_type.c49: type = pattern_type %Generic.type.03dff7.2 [symbolic]\n// CHECK:STDOUT:   %U.0f2266.1: %Generic.type.03dff7.2 = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %CallGenericMethod.type: type = fn_type @CallGenericMethod [concrete]\n// CHECK:STDOUT:   %CallGenericMethod: %CallGenericMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cba: type = pattern_type %Generic.type.498 [concrete]\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn.d64: <specific function> = specific_function %CallGenericMethod, @CallGenericMethod(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT:   %U.0f2266.2: %Generic.type.03dff7.2 = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %PassThroughToGenericMethod.type: type = fn_type @PassThroughToGenericMethod [concrete]\n// CHECK:STDOUT:   %PassThroughToGenericMethod: %PassThroughToGenericMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Self.15d2d5.2: %Generic.type.03dff7.2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.74390a.2: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%T, %Self.15d2d5.1) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.baf95a.2: %Generic.WithSelf.F.type.74390a.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.22afda.2: type = assoc_entity_type @Generic, @Generic(%T) [symbolic]\n// CHECK:STDOUT:   %assoc0.e0dc00.2: %Generic.assoc_type.22afda.2 = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn.6c1: <specific function> = specific_function %CallGenericMethod, @CallGenericMethod(%T, %U.0f2266.2) [symbolic]\n// CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]\n// CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %PassThroughToGenericMethod.specific_fn: <specific function> = specific_function %PassThroughToGenericMethod, @PassThroughToGenericMethod(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Generic = %Generic.decl\n// CHECK:STDOUT:     .GenericParam = %GenericParam.decl\n// CHECK:STDOUT:     .ImplsGeneric = %ImplsGeneric.decl\n// CHECK:STDOUT:     .CallGenericMethod = %CallGenericMethod.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:     .PassThroughToGenericMethod = %PassThroughToGenericMethod.decl\n// CHECK:STDOUT:     .H = %H.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Generic.decl: %Generic.type.835 = interface_decl @Generic [concrete = constants.%Generic.generic] {\n// CHECK:STDOUT:     %Scalar.patt: %pattern_type.98f = symbolic_binding_pattern Scalar, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_28.1: type = splice_block %.loc4_28.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_28.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Scalar.loc4_19.2: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc4_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %GenericParam.decl: type = class_decl @GenericParam [concrete = constants.%GenericParam] {} {}\n// CHECK:STDOUT:   %ImplsGeneric.decl: type = class_decl @ImplsGeneric [concrete = constants.%ImplsGeneric] {} {}\n// CHECK:STDOUT:   impl_decl @ImplsGeneric.as.Generic.impl [concrete] {} {\n// CHECK:STDOUT:     %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:     %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:     %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:     %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.498]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallGenericMethod.decl: %CallGenericMethod.type = fn_decl @CallGenericMethod [concrete = constants.%CallGenericMethod] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: @CallGenericMethod.%pattern_type (%pattern_type.c49) = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_26.1: type = splice_block %.loc15_26.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_26.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_22.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc15_52: type = splice_block %Generic.type.loc15_52.2 [symbolic = %Generic.type.loc15_52.1 (constants.%Generic.type.03dff7.2)] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc15_22.2 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:       %Generic.type.loc15_52.2: type = facet_type <@Generic, @Generic(constants.%T)> [symbolic = %Generic.type.loc15_52.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc15_39.2: @CallGenericMethod.%Generic.type.loc15_52.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc15_39.1 (constants.%U.0f2266.1)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT:   %PassThroughToGenericMethod.decl: %PassThroughToGenericMethod.type = fn_decl @PassThroughToGenericMethod [concrete = constants.%PassThroughToGenericMethod] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: @PassThroughToGenericMethod.%pattern_type (%pattern_type.c49) = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc21_35.1: type = splice_block %.loc21_35.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc21_35.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc21_31.2: type = symbolic_binding T, 0 [symbolic = %T.loc21_31.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc21_54: type = splice_block %Generic.type.loc21_54.2 [symbolic = %Generic.type.loc21_54.1 (constants.%Generic.type.03dff7.2)] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:       %T.ref.loc21: type = name_ref T, %T.loc21_31.2 [symbolic = %T.loc21_31.1 (constants.%T)]\n// CHECK:STDOUT:       %Generic.type.loc21_54.2: type = facet_type <@Generic, @Generic(constants.%T)> [symbolic = %Generic.type.loc21_54.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc21_41.2: @PassThroughToGenericMethod.%Generic.type.loc21_54.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc21_41.1 (constants.%U.0f2266.2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @Generic(%Scalar.loc4_19.2: type) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc4_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type: type = facet_type <@Generic, @Generic(%Scalar.loc4_19.1)> [symbolic = %Generic.type (constants.%Generic.type.03dff7.1)]\n// CHECK:STDOUT:   %Self.loc4_34.2: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc4_34.2 (constants.%Self.15d2d5.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc4_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc4_34.2 (constants.%Self.15d2d5.1)]\n// CHECK:STDOUT:     %Generic.WithSelf.decl = interface_with_self_decl @Generic [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %Generic.WithSelf.F.decl: @Generic.WithSelf.%Generic.WithSelf.F.type (%Generic.WithSelf.F.type.74390a.1) = fn_decl @Generic.WithSelf.F [symbolic = @Generic.WithSelf.%Generic.WithSelf.F (constants.%Generic.WithSelf.F.baf95a.1)] {} {}\n// CHECK:STDOUT:     %assoc0.loc5_9.1: @Generic.WithSelf.%Generic.assoc_type (%Generic.assoc_type.22afda.1) = assoc_entity element0, %Generic.WithSelf.F.decl [symbolic = %assoc0.loc5_9.2 (constants.%assoc0.e0dc00.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc4_34.1\n// CHECK:STDOUT:     .F = @Generic.WithSelf.%assoc0.loc5_9.1\n// CHECK:STDOUT:     witness = (@Generic.WithSelf.%Generic.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @ImplsGeneric.as.Generic.impl: %ImplsGeneric.ref as %Generic.type {\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.decl: %ImplsGeneric.as.Generic.impl.F.type = fn_decl @ImplsGeneric.as.Generic.impl.F [concrete = constants.%ImplsGeneric.as.Generic.impl.F] {} {}\n// CHECK:STDOUT:   %Generic.impl_witness_table = impl_witness_table (%ImplsGeneric.as.Generic.impl.F.decl), @ImplsGeneric.as.Generic.impl [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness %Generic.impl_witness_table [concrete = constants.%Generic.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %ImplsGeneric.as.Generic.impl.F.decl\n// CHECK:STDOUT:   witness = %Generic.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @GenericParam {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%GenericParam\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ImplsGeneric {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%ImplsGeneric\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Generic.WithSelf.F(@Generic.%Scalar.loc4_19.2: type, @Generic.%Self.loc4_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1)) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImplsGeneric.as.Generic.impl.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallGenericMethod(%T.loc15_22.2: type, %U.loc15_39.2: @CallGenericMethod.%Generic.type.loc15_52.1 (%Generic.type.03dff7.2)) {\n// CHECK:STDOUT:   %T.loc15_22.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:   %Generic.type.loc15_52.1: type = facet_type <@Generic, @Generic(%T.loc15_22.1)> [symbolic = %Generic.type.loc15_52.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:   %U.loc15_39.1: @CallGenericMethod.%Generic.type.loc15_52.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc15_39.1 (constants.%U.0f2266.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Generic.type.loc15_52.1 [symbolic = %pattern_type (constants.%pattern_type.c49)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod]\n// CHECK:STDOUT:   %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:   %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value constants.%ImplsGeneric, (constants.%Generic.impl_witness) [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %.loc18: %Generic.type.498 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn: <specific function> = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) [concrete = constants.%CallGenericMethod.specific_fn.d64]\n// CHECK:STDOUT:   %CallGenericMethod.call: init %empty_tuple.type = call %CallGenericMethod.specific_fn()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @PassThroughToGenericMethod(%T.loc21_31.2: type, %U.loc21_41.2: @PassThroughToGenericMethod.%Generic.type.loc21_54.1 (%Generic.type.03dff7.2)) {\n// CHECK:STDOUT:   %T.loc21_31.1: type = symbolic_binding T, 0 [symbolic = %T.loc21_31.1 (constants.%T)]\n// CHECK:STDOUT:   %Generic.type.loc21_54.1: type = facet_type <@Generic, @Generic(%T.loc21_31.1)> [symbolic = %Generic.type.loc21_54.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:   %U.loc21_41.1: @PassThroughToGenericMethod.%Generic.type.loc21_54.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc21_41.1 (constants.%U.0f2266.2)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Generic.type.loc21_54.1 [symbolic = %pattern_type (constants.%pattern_type.c49)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn.loc22_3.2: <specific function> = specific_function constants.%CallGenericMethod, @CallGenericMethod(%T.loc21_31.1, %U.loc21_41.1) [symbolic = %CallGenericMethod.specific_fn.loc22_3.2 (constants.%CallGenericMethod.specific_fn.6c1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod]\n// CHECK:STDOUT:     %T.ref.loc22: type = name_ref T, %T.loc21_31.2 [symbolic = %T.loc21_31.1 (constants.%T)]\n// CHECK:STDOUT:     %U.ref: @PassThroughToGenericMethod.%Generic.type.loc21_54.1 (%Generic.type.03dff7.2) = name_ref U, %U.loc21_41.2 [symbolic = %U.loc21_41.1 (constants.%U.0f2266.2)]\n// CHECK:STDOUT:     %CallGenericMethod.specific_fn.loc22_3.1: <specific function> = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%T, constants.%U.0f2266.2) [symbolic = %CallGenericMethod.specific_fn.loc22_3.2 (constants.%CallGenericMethod.specific_fn.6c1)]\n// CHECK:STDOUT:     %CallGenericMethod.call: init %empty_tuple.type = call %CallGenericMethod.specific_fn.loc22_3.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @H() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %PassThroughToGenericMethod.ref: %PassThroughToGenericMethod.type = name_ref PassThroughToGenericMethod, file.%PassThroughToGenericMethod.decl [concrete = constants.%PassThroughToGenericMethod]\n// CHECK:STDOUT:   %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:   %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value constants.%ImplsGeneric, (constants.%Generic.impl_witness) [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %.loc26: %Generic.type.498 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %PassThroughToGenericMethod.specific_fn: <specific function> = specific_function %PassThroughToGenericMethod.ref, @PassThroughToGenericMethod(constants.%GenericParam, constants.%Generic.facet) [concrete = constants.%PassThroughToGenericMethod.specific_fn]\n// CHECK:STDOUT:   %PassThroughToGenericMethod.call: init %empty_tuple.type = call %PassThroughToGenericMethod.specific_fn()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%Scalar) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1 => constants.%Scalar\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%Scalar, constants.%Self.15d2d5.1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%Scalar, constants.%Self.15d2d5.1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%GenericParam) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1 => constants.%GenericParam\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self.loc4_34.2 => constants.%Self.1f5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Self.15d2d5.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Self.15d2d5.1\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.a23\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.fe0\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc5_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Generic.facet\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.c86\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.1fd\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc5_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%GenericParam, constants.%Generic.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%T) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %Self.loc4_34.2 => constants.%Self.15d2d5.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%T, constants.%U.0f2266.1) {\n// CHECK:STDOUT:   %T.loc15_22.1 => constants.%T\n// CHECK:STDOUT:   %Generic.type.loc15_52.1 => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %U.loc15_39.1 => constants.%U.0f2266.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.c49\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT:   %T.loc15_22.1 => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type.loc15_52.1 => constants.%Generic.type.498\n// CHECK:STDOUT:   %U.loc15_39.1 => constants.%Generic.facet\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.cba\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @PassThroughToGenericMethod(constants.%T, constants.%U.0f2266.2) {\n// CHECK:STDOUT:   %T.loc21_31.1 => constants.%T\n// CHECK:STDOUT:   %Generic.type.loc21_54.1 => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %U.loc21_41.1 => constants.%U.0f2266.2\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.c49\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%T, constants.%Self.15d2d5.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%T\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %Self => constants.%Self.15d2d5.1\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.74390a.2\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.baf95a.2\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.22afda.2\n// CHECK:STDOUT:   %assoc0.loc5_9.2 => constants.%assoc0.e0dc00.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%T, constants.%U.0f2266.2) {\n// CHECK:STDOUT:   %T.loc15_22.1 => constants.%T\n// CHECK:STDOUT:   %Generic.type.loc15_52.1 => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %U.loc15_39.1 => constants.%U.0f2266.2\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.c49\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @PassThroughToGenericMethod(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT:   %T.loc21_31.1 => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type.loc21_54.1 => constants.%Generic.type.498\n// CHECK:STDOUT:   %U.loc21_41.1 => constants.%Generic.facet\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.cba\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn.loc22_3.2 => constants.%CallGenericMethod.specific_fn.d64\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- generic_facet_type_from_implicit_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %Scalar: type = symbolic_binding Scalar, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.835: type = generic_interface_type @Generic [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Generic.generic: %Generic.type.835 = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.type.03dff7.1: type = facet_type <@Generic, @Generic(%Scalar)> [symbolic]\n// CHECK:STDOUT:   %Self.15d: %Generic.type.03dff7.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.743: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%Scalar, %Self.15d) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.baf: %Generic.WithSelf.F.type.743 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.22a: type = assoc_entity_type @Generic, @Generic(%Scalar) [symbolic]\n// CHECK:STDOUT:   %assoc0.e0d: %Generic.assoc_type.22a = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %GenericParam: type = class_type @GenericParam [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ImplsGeneric: type = class_type @ImplsGeneric [concrete]\n// CHECK:STDOUT:   %Generic.type.498: type = facet_type <@Generic, @Generic(%GenericParam)> [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness @ImplsGeneric.as.Generic.impl.%Generic.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.1f5: %Generic.type.498 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.a23: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Self.15d) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.fe0: %Generic.WithSelf.F.type.a23 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.6dc: type = assoc_entity_type @Generic, @Generic(%GenericParam) [concrete]\n// CHECK:STDOUT:   %assoc0.717: %Generic.assoc_type.6dc = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.type: type = fn_type @ImplsGeneric.as.Generic.impl.F [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F: %ImplsGeneric.as.Generic.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value %ImplsGeneric, (%Generic.impl_witness) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.c86: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.1fd: %Generic.WithSelf.F.type.c86 = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.03dff7.2: type = facet_type <@Generic, @Generic(%T)> [symbolic]\n// CHECK:STDOUT:   %pattern_type.c49: type = pattern_type %Generic.type.03dff7.2 [symbolic]\n// CHECK:STDOUT:   %U: %Generic.type.03dff7.2 = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %CallGenericMethod.type: type = fn_type @CallGenericMethod [concrete]\n// CHECK:STDOUT:   %CallGenericMethod: %CallGenericMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %GenericParam.val: %GenericParam = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cba: type = pattern_type %Generic.type.498 [concrete]\n// CHECK:STDOUT:   %pattern_type.27a: type = pattern_type %GenericParam [concrete]\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn: <specific function> = specific_function %CallGenericMethod, @CallGenericMethod(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Generic = %Generic.decl\n// CHECK:STDOUT:     .GenericParam = %GenericParam.decl\n// CHECK:STDOUT:     .ImplsGeneric = %ImplsGeneric.decl\n// CHECK:STDOUT:     .CallGenericMethod = %CallGenericMethod.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Generic.decl: %Generic.type.835 = interface_decl @Generic [concrete = constants.%Generic.generic] {\n// CHECK:STDOUT:     %Scalar.patt: %pattern_type.98f = symbolic_binding_pattern Scalar, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_28.1: type = splice_block %.loc4_28.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_28.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Scalar.loc4_19.2: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc4_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %GenericParam.decl: type = class_decl @GenericParam [concrete = constants.%GenericParam] {} {}\n// CHECK:STDOUT:   %ImplsGeneric.decl: type = class_decl @ImplsGeneric [concrete = constants.%ImplsGeneric] {} {}\n// CHECK:STDOUT:   impl_decl @ImplsGeneric.as.Generic.impl [concrete] {} {\n// CHECK:STDOUT:     %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:     %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:     %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:     %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.498]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallGenericMethod.decl: %CallGenericMethod.type = fn_decl @CallGenericMethod [concrete = constants.%CallGenericMethod] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: @CallGenericMethod.%pattern_type.loc15_39 (%pattern_type.c49) = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %t.patt: @CallGenericMethod.%pattern_type.loc15_62 (%pattern_type.51d) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: @CallGenericMethod.%pattern_type.loc15_62 (%pattern_type.51d) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_26.1: type = splice_block %.loc15_26.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_26.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_22.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc15_52: type = splice_block %Generic.type.loc15_52.2 [symbolic = %Generic.type.loc15_52.1 (constants.%Generic.type.03dff7.2)] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:       %T.ref.loc15_51: type = name_ref T, %T.loc15_22.2 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:       %Generic.type.loc15_52.2: type = facet_type <@Generic, @Generic(constants.%T)> [symbolic = %Generic.type.loc15_52.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc15_39.2: @CallGenericMethod.%Generic.type.loc15_52.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc15_39.1 (constants.%U)]\n// CHECK:STDOUT:     %t.param: @CallGenericMethod.%T.loc15_22.1 (%T) = value_param call_param0\n// CHECK:STDOUT:     %T.ref.loc15_65: type = name_ref T, %T.loc15_22.2 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:     %t: @CallGenericMethod.%T.loc15_22.1 (%T) = value_binding t, %t.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @Generic(%Scalar.loc4_19.2: type) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc4_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type: type = facet_type <@Generic, @Generic(%Scalar.loc4_19.1)> [symbolic = %Generic.type (constants.%Generic.type.03dff7.1)]\n// CHECK:STDOUT:   %Self.loc4_34.2: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc4_34.2 (constants.%Self.15d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc4_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc4_34.2 (constants.%Self.15d)]\n// CHECK:STDOUT:     %Generic.WithSelf.decl = interface_with_self_decl @Generic [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %Generic.WithSelf.F.decl: @Generic.WithSelf.%Generic.WithSelf.F.type (%Generic.WithSelf.F.type.743) = fn_decl @Generic.WithSelf.F [symbolic = @Generic.WithSelf.%Generic.WithSelf.F (constants.%Generic.WithSelf.F.baf)] {} {}\n// CHECK:STDOUT:     %assoc0.loc5_9.1: @Generic.WithSelf.%Generic.assoc_type (%Generic.assoc_type.22a) = assoc_entity element0, %Generic.WithSelf.F.decl [symbolic = %assoc0.loc5_9.2 (constants.%assoc0.e0d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc4_34.1\n// CHECK:STDOUT:     .F = @Generic.WithSelf.%assoc0.loc5_9.1\n// CHECK:STDOUT:     witness = (@Generic.WithSelf.%Generic.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @ImplsGeneric.as.Generic.impl: %ImplsGeneric.ref as %Generic.type {\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.decl: %ImplsGeneric.as.Generic.impl.F.type = fn_decl @ImplsGeneric.as.Generic.impl.F [concrete = constants.%ImplsGeneric.as.Generic.impl.F] {} {}\n// CHECK:STDOUT:   %Generic.impl_witness_table = impl_witness_table (%ImplsGeneric.as.Generic.impl.F.decl), @ImplsGeneric.as.Generic.impl [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness %Generic.impl_witness_table [concrete = constants.%Generic.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %ImplsGeneric.as.Generic.impl.F.decl\n// CHECK:STDOUT:   witness = %Generic.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @GenericParam {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%GenericParam\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ImplsGeneric {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%ImplsGeneric\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Generic.WithSelf.F(@Generic.%Scalar.loc4_19.2: type, @Generic.%Self.loc4_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1)) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImplsGeneric.as.Generic.impl.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallGenericMethod(%T.loc15_22.2: type, %U.loc15_39.2: @CallGenericMethod.%Generic.type.loc15_52.1 (%Generic.type.03dff7.2)) {\n// CHECK:STDOUT:   %T.loc15_22.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:   %Generic.type.loc15_52.1: type = facet_type <@Generic, @Generic(%T.loc15_22.1)> [symbolic = %Generic.type.loc15_52.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:   %U.loc15_39.1: @CallGenericMethod.%Generic.type.loc15_52.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc15_39.1 (constants.%U)]\n// CHECK:STDOUT:   %pattern_type.loc15_39: type = pattern_type %Generic.type.loc15_52.1 [symbolic = %pattern_type.loc15_39 (constants.%pattern_type.c49)]\n// CHECK:STDOUT:   %pattern_type.loc15_62: type = pattern_type %T.loc15_22.1 [symbolic = %pattern_type.loc15_62 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc15_22.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%t.param: @CallGenericMethod.%T.loc15_22.1 (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod]\n// CHECK:STDOUT:   %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:   %.loc18_36.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:   %.loc18_36.2: ref %GenericParam = temporary_storage\n// CHECK:STDOUT:   %.loc18_36.3: init %GenericParam to %.loc18_36.2 = class_init () [concrete = constants.%GenericParam.val]\n// CHECK:STDOUT:   %.loc18_38.1: init %GenericParam = converted %.loc18_36.1, %.loc18_36.3 [concrete = constants.%GenericParam.val]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value constants.%ImplsGeneric, (constants.%Generic.impl_witness) [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %.loc18_53: %Generic.type.498 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn: <specific function> = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) [concrete = constants.%CallGenericMethod.specific_fn]\n// CHECK:STDOUT:   %.loc18_38.2: ref %GenericParam = temporary %.loc18_36.2, %.loc18_38.1\n// CHECK:STDOUT:   %.loc18_38.3: %GenericParam = acquire_value %.loc18_38.2\n// CHECK:STDOUT:   %CallGenericMethod.call: init %empty_tuple.type = call %CallGenericMethod.specific_fn(%.loc18_38.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc18_38.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc18_38.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %GenericParam) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%Scalar) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1 => constants.%Scalar\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%Scalar, constants.%Self.15d) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%Scalar, constants.%Self.15d) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%GenericParam) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1 => constants.%GenericParam\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self.loc4_34.2 => constants.%Self.1f5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Self.15d) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Self.15d\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.a23\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.fe0\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc5_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Generic.facet\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.c86\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.1fd\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc5_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%GenericParam, constants.%Generic.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%T) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc15_22.1 => constants.%T\n// CHECK:STDOUT:   %Generic.type.loc15_52.1 => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %U.loc15_39.1 => constants.%U\n// CHECK:STDOUT:   %pattern_type.loc15_39 => constants.%pattern_type.c49\n// CHECK:STDOUT:   %pattern_type.loc15_62 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT:   %T.loc15_22.1 => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type.loc15_52.1 => constants.%Generic.type.498\n// CHECK:STDOUT:   %U.loc15_39.1 => constants.%Generic.facet\n// CHECK:STDOUT:   %pattern_type.loc15_39 => constants.%pattern_type.cba\n// CHECK:STDOUT:   %pattern_type.loc15_62 => constants.%pattern_type.27a\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_class_value_to_facet_value_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_class_value_to_facet_value_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_class_value_to_facet_value_value.carbon\n\ninterface Animal {}\n\nfn WalkAnimal[T:! Animal](unused a: T) {}\n\nclass Goat {}\nimpl Goat as Animal {}\n\nfn F() {\n  WalkAnimal({} as Goat);\n}\n\n// CHECK:STDOUT: --- convert_class_value_to_facet_value_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self.c49: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.e10: type = pattern_type %Animal.type [concrete]\n// CHECK:STDOUT:   %T: %Animal.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.892: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %WalkAnimal.type: type = fn_type @WalkAnimal [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %WalkAnimal: %WalkAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Goat: type = class_type @Goat [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness @Goat.as.Animal.impl.%Animal.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat, (%Animal.impl_witness) [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Goat.val: %Goat = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.234: type = pattern_type %Goat [concrete]\n// CHECK:STDOUT:   %WalkAnimal.specific_fn: <specific function> = specific_function %WalkAnimal, @WalkAnimal(%Animal.facet) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .WalkAnimal = %WalkAnimal.decl\n// CHECK:STDOUT:     .Goat = %Goat.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   %WalkAnimal.decl: %WalkAnimal.type = fn_decl @WalkAnimal [concrete = constants.%WalkAnimal] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.e10 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @WalkAnimal.%pattern_type (%pattern_type.892) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @WalkAnimal.%pattern_type (%pattern_type.892) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc17_19: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc17_15.2: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc17_15.1 (constants.%T)]\n// CHECK:STDOUT:     %a.param: @WalkAnimal.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc17_37.1: type = splice_block %.loc17_37.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref: %Animal.type = name_ref T, %T.loc17_15.2 [symbolic = %T.loc17_15.1 (constants.%T)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc17_37.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @WalkAnimal.%T.binding.as_type (%T.binding.as_type) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Goat.decl: type = class_decl @Goat [concrete = constants.%Goat] {} {}\n// CHECK:STDOUT:   impl_decl @Goat.as.Animal.impl [concrete] {} {\n// CHECK:STDOUT:     %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:     %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c49]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Goat.as.Animal.impl: %Goat.ref as %Animal.ref {\n// CHECK:STDOUT:   %Animal.impl_witness_table = impl_witness_table (), @Goat.as.Animal.impl [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness %Animal.impl_witness_table [concrete = constants.%Animal.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Animal.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Goat {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Goat\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @WalkAnimal(%T.loc17_15.2: %Animal.type) {\n// CHECK:STDOUT:   %T.loc17_15.1: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc17_15.1 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc17_15.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.892)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @WalkAnimal.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %WalkAnimal.ref: %WalkAnimal.type = name_ref WalkAnimal, file.%WalkAnimal.decl [concrete = constants.%WalkAnimal]\n// CHECK:STDOUT:   %.loc23_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc23_15.2: ref %Goat = temporary_storage\n// CHECK:STDOUT:   %.loc23_15.3: init %Goat to %.loc23_15.2 = class_init () [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %.loc23_17.1: init %Goat = converted %.loc23_15.1, %.loc23_15.3 [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value constants.%Goat, (constants.%Animal.impl_witness) [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %.loc23_24: %Animal.type = converted constants.%Goat, %Animal.facet [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %WalkAnimal.specific_fn: <specific function> = specific_function %WalkAnimal.ref, @WalkAnimal(constants.%Animal.facet) [concrete = constants.%WalkAnimal.specific_fn]\n// CHECK:STDOUT:   %.loc23_17.2: ref %Goat = temporary %.loc23_15.2, %.loc23_17.1\n// CHECK:STDOUT:   %.loc23_17.3: %Goat = acquire_value %.loc23_17.2\n// CHECK:STDOUT:   %WalkAnimal.call: init %empty_tuple.type = call %WalkAnimal.specific_fn(%.loc23_17.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc23_17.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc23_17.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Goat) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self.c49) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WalkAnimal(constants.%T) {\n// CHECK:STDOUT:   %T.loc17_15.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.892\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Animal.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WalkAnimal(constants.%Animal.facet) {\n// CHECK:STDOUT:   %T.loc17_15.1 => constants.%Animal.facet\n// CHECK:STDOUT:   %T.binding.as_type => constants.%Goat\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.234\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_class_value_to_generic_facet_value_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_class_value_to_generic_facet_value_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_class_value_to_generic_facet_value_value.carbon\n\n// --- convert_class_value_to_generic_facet_value_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Generic(Scalar:! type) {\n  fn F();\n}\n\nclass GenericParam {}\n\nclass ImplsGeneric {}\nimpl ImplsGeneric as Generic(GenericParam) {\n  fn F() {}\n}\n\nfn CallGenericMethod[T:! type, U:! Generic(T)](unused a: U, unused s: T) {\n  U.F();\n}\n\nfn G() {\n  CallGenericMethod({} as ImplsGeneric, {} as GenericParam);\n}\n\n// --- multiple_generic_params_one_fixed_one_deduced.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(V:! type, W:! type) {}\n\nclass C {}\n\nimpl forall [T:! type] C as I(T, ()) {}\n\nfn A[T:! I({}, ())](unused t: T) {}\n\nfn B() {\n  A({} as C);\n}\n\n// --- fail_mismatch_impl_constraint_with_fixed_specific.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(V:! type, W:! type) {}\n\nclass C {}\n\nimpl forall [T:! type] C as I(T, ()) {}\n\nfn A[T:! I({}, {})](unused t: T) {}\n\nfn B() {\n  // CHECK:STDERR: fail_mismatch_impl_constraint_with_fixed_specific.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `I({}, {})` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   A({} as C);\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR: fail_mismatch_impl_constraint_with_fixed_specific.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn A[T:! I({}, {})](unused t: T) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  A({} as C);\n}\n\n// --- fail_mismatch_impl_self_with_fixed_specific.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\nclass C(V:! type, W:! type) {}\n\nimpl forall [T:! type] C(T, ()) as I {}\n\nfn A[T:! I](unused t: T) {}\n\nfn B() {\n  // CHECK:STDERR: fail_mismatch_impl_self_with_fixed_specific.carbon:[[@LINE+7]]:3: error: cannot convert type `C({}, {})` into type implementing `I` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   A({} as C({}, {}));\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_mismatch_impl_self_with_fixed_specific.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn A[T:! I](unused t: T) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  A({} as C({}, {}));\n}\n\n// CHECK:STDOUT: --- convert_class_value_to_generic_facet_value_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %Scalar: type = symbolic_binding Scalar, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.835: type = generic_interface_type @Generic [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Generic.generic: %Generic.type.835 = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.type.03dff7.1: type = facet_type <@Generic, @Generic(%Scalar)> [symbolic]\n// CHECK:STDOUT:   %Self.15d2d5.1: %Generic.type.03dff7.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.74390a.1: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%Scalar, %Self.15d2d5.1) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.baf95a.1: %Generic.WithSelf.F.type.74390a.1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.22afda.1: type = assoc_entity_type @Generic, @Generic(%Scalar) [symbolic]\n// CHECK:STDOUT:   %assoc0.e0dc00.1: %Generic.assoc_type.22afda.1 = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %GenericParam: type = class_type @GenericParam [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ImplsGeneric: type = class_type @ImplsGeneric [concrete]\n// CHECK:STDOUT:   %Generic.type.498: type = facet_type <@Generic, @Generic(%GenericParam)> [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness @ImplsGeneric.as.Generic.impl.%Generic.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.1f5: %Generic.type.498 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.a23: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Self.15d2d5.1) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.fe0: %Generic.WithSelf.F.type.a23 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.6dc: type = assoc_entity_type @Generic, @Generic(%GenericParam) [concrete]\n// CHECK:STDOUT:   %assoc0.717: %Generic.assoc_type.6dc = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.type: type = fn_type @ImplsGeneric.as.Generic.impl.F [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F: %ImplsGeneric.as.Generic.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value %ImplsGeneric, (%Generic.impl_witness) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.c86: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.1fd: %Generic.WithSelf.F.type.c86 = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.03dff7.2: type = facet_type <@Generic, @Generic(%T)> [symbolic]\n// CHECK:STDOUT:   %pattern_type.c49: type = pattern_type %Generic.type.03dff7.2 [symbolic]\n// CHECK:STDOUT:   %U: %Generic.type.03dff7.2 = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %Self.15d2d5.2: %Generic.type.03dff7.2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.74390a.2: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%T, %Self.15d2d5.1) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.baf95a.2: %Generic.WithSelf.F.type.74390a.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.22afda.2: type = assoc_entity_type @Generic, @Generic(%T) [symbolic]\n// CHECK:STDOUT:   %assoc0.e0dc00.2: %Generic.assoc_type.22afda.2 = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 1, %U [symbolic]\n// CHECK:STDOUT:   %pattern_type.46f: type = pattern_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %CallGenericMethod.type: type = fn_type @CallGenericMethod [concrete]\n// CHECK:STDOUT:   %CallGenericMethod: %CallGenericMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.186: <witness> = require_complete_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %require_complete.7da: <witness> = require_complete_type %Generic.type.03dff7.2 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.56e: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%T, %U) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.a99: %Generic.WithSelf.F.type.56e = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.lookup_impl_witness: <witness> = lookup_impl_witness %U, @Generic, @Generic(%T) [symbolic]\n// CHECK:STDOUT:   %.ab3: type = fn_type_with_self_type %Generic.WithSelf.F.type.56e, %U [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.ab3 = impl_witness_access %Generic.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Generic.WithSelf.F(%T, %U) [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.val: %ImplsGeneric = struct_value () [concrete]\n// CHECK:STDOUT:   %GenericParam.val: %GenericParam = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cba: type = pattern_type %Generic.type.498 [concrete]\n// CHECK:STDOUT:   %pattern_type.4da: type = pattern_type %ImplsGeneric [concrete]\n// CHECK:STDOUT:   %pattern_type.27a: type = pattern_type %GenericParam [concrete]\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn: <specific function> = specific_function %CallGenericMethod, @CallGenericMethod(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc20_44 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc20_24 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.57a: <witness> = complete_type_witness %Generic.type.498 [concrete]\n// CHECK:STDOUT:   %.fcf: type = fn_type_with_self_type %Generic.WithSelf.F.type.c86, %Generic.facet [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Generic = %Generic.decl\n// CHECK:STDOUT:     .GenericParam = %GenericParam.decl\n// CHECK:STDOUT:     .ImplsGeneric = %ImplsGeneric.decl\n// CHECK:STDOUT:     .CallGenericMethod = %CallGenericMethod.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Generic.decl: %Generic.type.835 = interface_decl @Generic [concrete = constants.%Generic.generic] {\n// CHECK:STDOUT:     %Scalar.patt: %pattern_type.98f = symbolic_binding_pattern Scalar, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_28.1: type = splice_block %.loc4_28.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_28.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Scalar.loc4_19.2: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc4_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %GenericParam.decl: type = class_decl @GenericParam [concrete = constants.%GenericParam] {} {}\n// CHECK:STDOUT:   %ImplsGeneric.decl: type = class_decl @ImplsGeneric [concrete = constants.%ImplsGeneric] {} {}\n// CHECK:STDOUT:   impl_decl @ImplsGeneric.as.Generic.impl [concrete] {} {\n// CHECK:STDOUT:     %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:     %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:     %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:     %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.498]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallGenericMethod.decl: %CallGenericMethod.type = fn_decl @CallGenericMethod [concrete = constants.%CallGenericMethod] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: @CallGenericMethod.%pattern_type.loc15_32 (%pattern_type.c49) = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %a.patt: @CallGenericMethod.%pattern_type.loc15_55 (%pattern_type.46f) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @CallGenericMethod.%pattern_type.loc15_55 (%pattern_type.46f) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %s.patt: @CallGenericMethod.%pattern_type.loc15_68 (%pattern_type.51d) = value_binding_pattern s [concrete]\n// CHECK:STDOUT:     %s.param_patt: @CallGenericMethod.%pattern_type.loc15_68 (%pattern_type.51d) = value_param_pattern %s.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_26.1: type = splice_block %.loc15_26.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_26.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_22.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc15_45: type = splice_block %Generic.type.loc15_45.2 [symbolic = %Generic.type.loc15_45.1 (constants.%Generic.type.03dff7.2)] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:       %T.ref.loc15_44: type = name_ref T, %T.loc15_22.2 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:       %Generic.type.loc15_45.2: type = facet_type <@Generic, @Generic(constants.%T)> [symbolic = %Generic.type.loc15_45.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc15_32.2: @CallGenericMethod.%Generic.type.loc15_45.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc15_32.1 (constants.%U)]\n// CHECK:STDOUT:     %a.param: @CallGenericMethod.%U.binding.as_type (%U.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc15_58.1: type = splice_block %.loc15_58.2 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)] {\n// CHECK:STDOUT:       %U.ref.loc15: @CallGenericMethod.%Generic.type.loc15_45.1 (%Generic.type.03dff7.2) = name_ref U, %U.loc15_32.2 [symbolic = %U.loc15_32.1 (constants.%U)]\n// CHECK:STDOUT:       %U.as_type.loc15: type = facet_access_type %U.ref.loc15 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:       %.loc15_58.2: type = converted %U.ref.loc15, %U.as_type.loc15 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @CallGenericMethod.%U.binding.as_type (%U.binding.as_type) = value_binding a, %a.param\n// CHECK:STDOUT:     %s.param: @CallGenericMethod.%T.loc15_22.1 (%T) = value_param call_param1\n// CHECK:STDOUT:     %T.ref.loc15_71: type = name_ref T, %T.loc15_22.2 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:     %s: @CallGenericMethod.%T.loc15_22.1 (%T) = value_binding s, %s.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @Generic(%Scalar.loc4_19.2: type) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc4_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type: type = facet_type <@Generic, @Generic(%Scalar.loc4_19.1)> [symbolic = %Generic.type (constants.%Generic.type.03dff7.1)]\n// CHECK:STDOUT:   %Self.loc4_34.2: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc4_34.2 (constants.%Self.15d2d5.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc4_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc4_34.2 (constants.%Self.15d2d5.1)]\n// CHECK:STDOUT:     %Generic.WithSelf.decl = interface_with_self_decl @Generic [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %Generic.WithSelf.F.decl: @Generic.WithSelf.%Generic.WithSelf.F.type (%Generic.WithSelf.F.type.74390a.1) = fn_decl @Generic.WithSelf.F [symbolic = @Generic.WithSelf.%Generic.WithSelf.F (constants.%Generic.WithSelf.F.baf95a.1)] {} {}\n// CHECK:STDOUT:     %assoc0.loc5_9.1: @Generic.WithSelf.%Generic.assoc_type (%Generic.assoc_type.22afda.1) = assoc_entity element0, %Generic.WithSelf.F.decl [symbolic = %assoc0.loc5_9.2 (constants.%assoc0.e0dc00.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc4_34.1\n// CHECK:STDOUT:     .F = @Generic.WithSelf.%assoc0.loc5_9.1\n// CHECK:STDOUT:     witness = (@Generic.WithSelf.%Generic.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @ImplsGeneric.as.Generic.impl: %ImplsGeneric.ref as %Generic.type {\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.decl: %ImplsGeneric.as.Generic.impl.F.type = fn_decl @ImplsGeneric.as.Generic.impl.F [concrete = constants.%ImplsGeneric.as.Generic.impl.F] {} {}\n// CHECK:STDOUT:   %Generic.impl_witness_table = impl_witness_table (%ImplsGeneric.as.Generic.impl.F.decl), @ImplsGeneric.as.Generic.impl [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness %Generic.impl_witness_table [concrete = constants.%Generic.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %ImplsGeneric.as.Generic.impl.F.decl\n// CHECK:STDOUT:   witness = %Generic.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @GenericParam {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%GenericParam\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ImplsGeneric {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%ImplsGeneric\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Generic.WithSelf.F(@Generic.%Scalar.loc4_19.2: type, @Generic.%Self.loc4_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1)) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImplsGeneric.as.Generic.impl.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallGenericMethod(%T.loc15_22.2: type, %U.loc15_32.2: @CallGenericMethod.%Generic.type.loc15_45.1 (%Generic.type.03dff7.2)) {\n// CHECK:STDOUT:   %T.loc15_22.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:   %Generic.type.loc15_45.1: type = facet_type <@Generic, @Generic(%T.loc15_22.1)> [symbolic = %Generic.type.loc15_45.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:   %U.loc15_32.1: @CallGenericMethod.%Generic.type.loc15_45.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc15_32.1 (constants.%U)]\n// CHECK:STDOUT:   %pattern_type.loc15_32: type = pattern_type %Generic.type.loc15_45.1 [symbolic = %pattern_type.loc15_32 (constants.%pattern_type.c49)]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 1, %U.loc15_32.1 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type.loc15_55: type = pattern_type %U.binding.as_type [symbolic = %pattern_type.loc15_55 (constants.%pattern_type.46f)]\n// CHECK:STDOUT:   %pattern_type.loc15_68: type = pattern_type %T.loc15_22.1 [symbolic = %pattern_type.loc15_68 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc15_56: <witness> = require_complete_type %U.binding.as_type [symbolic = %require_complete.loc15_56 (constants.%require_complete.186)]\n// CHECK:STDOUT:   %require_complete.loc15_69: <witness> = require_complete_type %T.loc15_22.1 [symbolic = %require_complete.loc15_69 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %require_complete.loc16: <witness> = require_complete_type %Generic.type.loc15_45.1 [symbolic = %require_complete.loc16 (constants.%require_complete.7da)]\n// CHECK:STDOUT:   %Generic.assoc_type: type = assoc_entity_type @Generic, @Generic(%T.loc15_22.1) [symbolic = %Generic.assoc_type (constants.%Generic.assoc_type.22afda.2)]\n// CHECK:STDOUT:   %assoc0: @CallGenericMethod.%Generic.assoc_type (%Generic.assoc_type.22afda.2) = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic = %assoc0 (constants.%assoc0.e0dc00.2)]\n// CHECK:STDOUT:   %Generic.lookup_impl_witness: <witness> = lookup_impl_witness %U.loc15_32.1, @Generic, @Generic(%T.loc15_22.1) [symbolic = %Generic.lookup_impl_witness (constants.%Generic.lookup_impl_witness)]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%T.loc15_22.1, %U.loc15_32.1) [symbolic = %Generic.WithSelf.F.type (constants.%Generic.WithSelf.F.type.56e)]\n// CHECK:STDOUT:   %.loc16_4.3: type = fn_type_with_self_type %Generic.WithSelf.F.type, %U.loc15_32.1 [symbolic = %.loc16_4.3 (constants.%.ab3)]\n// CHECK:STDOUT:   %impl.elem0.loc16_4.2: @CallGenericMethod.%.loc16_4.3 (%.ab3) = impl_witness_access %Generic.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc16_4.2: <specific function> = specific_impl_function %impl.elem0.loc16_4.2, @Generic.WithSelf.F(%T.loc15_22.1, %U.loc15_32.1) [symbolic = %specific_impl_fn.loc16_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @CallGenericMethod.%U.binding.as_type (%U.binding.as_type), %s.param: @CallGenericMethod.%T.loc15_22.1 (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %U.ref.loc16: @CallGenericMethod.%Generic.type.loc15_45.1 (%Generic.type.03dff7.2) = name_ref U, %U.loc15_32.2 [symbolic = %U.loc15_32.1 (constants.%U)]\n// CHECK:STDOUT:     %U.as_type.loc16: type = facet_access_type %U.ref.loc16 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     %.loc16_4.1: type = converted %U.ref.loc16, %U.as_type.loc16 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     %.loc16_4.2: @CallGenericMethod.%Generic.assoc_type (%Generic.assoc_type.22afda.2) = specific_constant @Generic.WithSelf.%assoc0.loc5_9.1, @Generic.WithSelf(constants.%T, constants.%U) [symbolic = %assoc0 (constants.%assoc0.e0dc00.2)]\n// CHECK:STDOUT:     %F.ref: @CallGenericMethod.%Generic.assoc_type (%Generic.assoc_type.22afda.2) = name_ref F, %.loc16_4.2 [symbolic = %assoc0 (constants.%assoc0.e0dc00.2)]\n// CHECK:STDOUT:     %impl.elem0.loc16_4.1: @CallGenericMethod.%.loc16_4.3 (%.ab3) = impl_witness_access constants.%Generic.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %specific_impl_fn.loc16_4.1: <specific function> = specific_impl_function %impl.elem0.loc16_4.1, @Generic.WithSelf.F(constants.%T, constants.%U) [symbolic = %specific_impl_fn.loc16_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %Generic.WithSelf.F.call: init %empty_tuple.type = call %specific_impl_fn.loc16_4.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod]\n// CHECK:STDOUT:   %.loc20_22.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:   %.loc20_22.2: ref %ImplsGeneric = temporary_storage\n// CHECK:STDOUT:   %.loc20_22.3: init %ImplsGeneric to %.loc20_22.2 = class_init () [concrete = constants.%ImplsGeneric.val]\n// CHECK:STDOUT:   %.loc20_24.1: init %ImplsGeneric = converted %.loc20_22.1, %.loc20_22.3 [concrete = constants.%ImplsGeneric.val]\n// CHECK:STDOUT:   %.loc20_42.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:   %.loc20_42.2: ref %GenericParam = temporary_storage\n// CHECK:STDOUT:   %.loc20_42.3: init %GenericParam to %.loc20_42.2 = class_init () [concrete = constants.%GenericParam.val]\n// CHECK:STDOUT:   %.loc20_44.1: init %GenericParam = converted %.loc20_42.1, %.loc20_42.3 [concrete = constants.%GenericParam.val]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value constants.%ImplsGeneric, (constants.%Generic.impl_witness) [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %.loc20_59: %Generic.type.498 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn: <specific function> = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) [concrete = constants.%CallGenericMethod.specific_fn]\n// CHECK:STDOUT:   %.loc20_24.2: ref %ImplsGeneric = temporary %.loc20_22.2, %.loc20_24.1\n// CHECK:STDOUT:   %.loc20_24.3: %ImplsGeneric = acquire_value %.loc20_24.2\n// CHECK:STDOUT:   %.loc20_44.2: ref %GenericParam = temporary %.loc20_42.2, %.loc20_44.1\n// CHECK:STDOUT:   %.loc20_44.3: %GenericParam = acquire_value %.loc20_44.2\n// CHECK:STDOUT:   %CallGenericMethod.call: init %empty_tuple.type = call %CallGenericMethod.specific_fn(%.loc20_24.3, %.loc20_44.3)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc20_44: <bound method> = bound_method %.loc20_44.2, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc20_44: init %empty_tuple.type = call %Destroy.Op.bound.loc20_44(%.loc20_44.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc20_24: <bound method> = bound_method %.loc20_24.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc20_24: init %empty_tuple.type = call %Destroy.Op.bound.loc20_24(%.loc20_24.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc20_44(%self.param: ref %GenericParam) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc20_24(%self.param: ref %ImplsGeneric) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%Scalar) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1 => constants.%Scalar\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%Scalar, constants.%Self.15d2d5.1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%Scalar, constants.%Self.15d2d5.1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%GenericParam) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1 => constants.%GenericParam\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self.loc4_34.2 => constants.%Self.1f5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Self.15d2d5.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Self.15d2d5.1\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.a23\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.fe0\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc5_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Generic.facet\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.c86\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.1fd\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc5_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%GenericParam, constants.%Generic.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%T) {\n// CHECK:STDOUT:   %Scalar.loc4_19.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %Self.loc4_34.2 => constants.%Self.15d2d5.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%T, constants.%Self.15d2d5.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%T\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %Self => constants.%Self.15d2d5.1\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.74390a.2\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.baf95a.2\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.22afda.2\n// CHECK:STDOUT:   %assoc0.loc5_9.2 => constants.%assoc0.e0dc00.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc15_22.1 => constants.%T\n// CHECK:STDOUT:   %Generic.type.loc15_45.1 => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %U.loc15_32.1 => constants.%U\n// CHECK:STDOUT:   %pattern_type.loc15_32 => constants.%pattern_type.c49\n// CHECK:STDOUT:   %U.binding.as_type => constants.%U.binding.as_type\n// CHECK:STDOUT:   %pattern_type.loc15_55 => constants.%pattern_type.46f\n// CHECK:STDOUT:   %pattern_type.loc15_68 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%T, constants.%U) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%T\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %Self => constants.%U\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.56e\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.a99\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.22afda.2\n// CHECK:STDOUT:   %assoc0.loc5_9.2 => constants.%assoc0.e0dc00.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%T, constants.%U) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT:   %T.loc15_22.1 => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type.loc15_45.1 => constants.%Generic.type.498\n// CHECK:STDOUT:   %U.loc15_32.1 => constants.%Generic.facet\n// CHECK:STDOUT:   %pattern_type.loc15_32 => constants.%pattern_type.cba\n// CHECK:STDOUT:   %U.binding.as_type => constants.%ImplsGeneric\n// CHECK:STDOUT:   %pattern_type.loc15_55 => constants.%pattern_type.4da\n// CHECK:STDOUT:   %pattern_type.loc15_68 => constants.%pattern_type.27a\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc15_56 => constants.%complete_type.357\n// CHECK:STDOUT:   %require_complete.loc15_69 => constants.%complete_type.357\n// CHECK:STDOUT:   %require_complete.loc16 => constants.%complete_type.57a\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.717\n// CHECK:STDOUT:   %Generic.lookup_impl_witness => constants.%Generic.impl_witness\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.c86\n// CHECK:STDOUT:   %.loc16_4.3 => constants.%.fcf\n// CHECK:STDOUT:   %impl.elem0.loc16_4.2 => constants.%ImplsGeneric.as.Generic.impl.F\n// CHECK:STDOUT:   %specific_impl_fn.loc16_4.2 => constants.%ImplsGeneric.as.Generic.impl.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- multiple_generic_params_one_fixed_one_deduced.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %V: type = symbolic_binding V, 0 [symbolic]\n// CHECK:STDOUT:   %W: type = symbolic_binding W, 1 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.54f: type = facet_type <@I, @I(%V, %W)> [symbolic]\n// CHECK:STDOUT:   %Self.8fa: %I.type.54f = symbolic_binding Self, 2 [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I.type.eb9: type = facet_type <@I, @I(%T.67d, %empty_tuple.type)> [symbolic]\n// CHECK:STDOUT:   %I.impl_witness.1cb: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table, @C.as.I.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %Self.061: %I.type.eb9 = symbolic_binding Self, 2 [symbolic]\n// CHECK:STDOUT:   %require_complete.d0a: <witness> = require_complete_type %I.type.eb9 [symbolic]\n// CHECK:STDOUT:   %I.facet.a6e: %I.type.eb9 = facet_value %C, (%I.impl_witness.1cb) [symbolic]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.5f7: type = facet_type <@I, @I(%empty_struct_type, %empty_tuple.type)> [concrete]\n// CHECK:STDOUT:   %pattern_type.eee: type = pattern_type %I.type.5f7 [concrete]\n// CHECK:STDOUT:   %T.bc3: %I.type.5f7 = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Self.2a6: %I.type.5f7 = symbolic_binding Self, 2 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.bc3 [symbolic]\n// CHECK:STDOUT:   %pattern_type.826: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.d69: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %I.impl_witness.1c4: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table, @C.as.I.impl(%empty_struct_type) [concrete]\n// CHECK:STDOUT:   %complete_type.1c0: <witness> = complete_type_witness %I.type.5f7 [concrete]\n// CHECK:STDOUT:   %I.facet.0e1: %I.type.5f7 = facet_value %C, (%I.impl_witness.1c4) [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %A.specific_fn: <specific function> = specific_function %A, @A(%I.facet.0e1) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %V.patt: %pattern_type.98f = symbolic_binding_pattern V, 0 [concrete]\n// CHECK:STDOUT:     %W.patt: %pattern_type.98f = symbolic_binding_pattern W, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc3_17.1: type = splice_block %.loc3_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc3_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %V.loc3_13.2: type = symbolic_binding V, 0 [symbolic = %V.loc3_13.1 (constants.%V)]\n// CHECK:STDOUT:     %.loc3_27.1: type = splice_block %.loc3_27.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc3_27.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %W.loc3_23.2: type = symbolic_binding W, 1 [symbolic = %W.loc3_23.1 (constants.%W)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc7_14.1 [symbolic = %T.loc7_14.2 (constants.%T.67d)]\n// CHECK:STDOUT:     %.loc7_35: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_36: type = converted %.loc7_35, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %I.type.loc7_36.1: type = facet_type <@I, @I(constants.%T.67d, constants.%empty_tuple.type)> [symbolic = %I.type.loc7_36.2 (constants.%I.type.eb9)]\n// CHECK:STDOUT:     %.loc7_18.1: type = splice_block %.loc7_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.eee = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %t.patt: @A.%pattern_type (%pattern_type.826) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: @A.%pattern_type (%pattern_type.826) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_18.1: type = splice_block %I.type [concrete = constants.%I.type.5f7] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %.loc9_13: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc9_17: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc9_18.2: type = converted %.loc9_13, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %.loc9_18.3: type = converted %.loc9_17, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %I.type: type = facet_type <@I, @I(constants.%empty_struct_type, constants.%empty_tuple.type)> [concrete = constants.%I.type.5f7]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9_6.2: %I.type.5f7 = symbolic_binding T, 0 [symbolic = %T.loc9_6.1 (constants.%T.bc3)]\n// CHECK:STDOUT:     %t.param: @A.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc9_31.1: type = splice_block %.loc9_31.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref: %I.type.5f7 = name_ref T, %T.loc9_6.2 [symbolic = %T.loc9_6.1 (constants.%T.bc3)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_31.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %t: @A.%T.binding.as_type (%T.binding.as_type) = value_binding t, %t.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%V.loc3_13.2: type, %W.loc3_23.2: type) {\n// CHECK:STDOUT:   %V.loc3_13.1: type = symbolic_binding V, 0 [symbolic = %V.loc3_13.1 (constants.%V)]\n// CHECK:STDOUT:   %W.loc3_23.1: type = symbolic_binding W, 1 [symbolic = %W.loc3_23.1 (constants.%W)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%V.loc3_13.1, %W.loc3_23.1)> [symbolic = %I.type (constants.%I.type.54f)]\n// CHECK:STDOUT:   %Self.loc3_33.2: @I.%I.type (%I.type.54f) = symbolic_binding Self, 2 [symbolic = %Self.loc3_33.2 (constants.%Self.8fa)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc3_33.1: @I.%I.type (%I.type.54f) = symbolic_binding Self, 2 [symbolic = %Self.loc3_33.2 (constants.%Self.8fa)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc3_33.1\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl(%T.loc7_14.1: type) {\n// CHECK:STDOUT:   %T.loc7_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T.67d)]\n// CHECK:STDOUT:   %I.type.loc7_36.2: type = facet_type <@I, @I(%T.loc7_14.2, constants.%empty_tuple.type)> [symbolic = %I.type.loc7_36.2 (constants.%I.type.eb9)]\n// CHECK:STDOUT:   %I.impl_witness.loc7_38.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(%T.loc7_14.2) [symbolic = %I.impl_witness.loc7_38.2 (constants.%I.impl_witness.1cb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.loc7_36.2 [symbolic = %require_complete (constants.%require_complete.d0a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %I.type.loc7_36.1 {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc7_38.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(constants.%T.67d) [symbolic = %I.impl_witness.loc7_38.2 (constants.%I.impl_witness.1cb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %I.impl_witness.loc7_38.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @A(%T.loc9_6.2: %I.type.5f7) {\n// CHECK:STDOUT:   %T.loc9_6.1: %I.type.5f7 = symbolic_binding T, 0 [symbolic = %T.loc9_6.1 (constants.%T.bc3)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc9_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.826)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.d69)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%t.param: @A.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc12_6.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc12_6.2: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc12_6.3: init %C to %.loc12_6.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc12_8.1: init %C = converted %.loc12_6.1, %.loc12_6.3 [concrete = constants.%C.val]\n// CHECK:STDOUT:   %I.facet: %I.type.5f7 = facet_value constants.%C, (constants.%I.impl_witness.1c4) [concrete = constants.%I.facet.0e1]\n// CHECK:STDOUT:   %.loc12_12: %I.type.5f7 = converted constants.%C, %I.facet [concrete = constants.%I.facet.0e1]\n// CHECK:STDOUT:   %A.specific_fn: <specific function> = specific_function %A.ref, @A(constants.%I.facet.0e1) [concrete = constants.%A.specific_fn]\n// CHECK:STDOUT:   %.loc12_8.2: ref %C = temporary %.loc12_6.2, %.loc12_8.1\n// CHECK:STDOUT:   %.loc12_8.3: %C = acquire_value %.loc12_8.2\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.specific_fn(%.loc12_8.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc12_8.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc12_8.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%V, constants.%W) {\n// CHECK:STDOUT:   %V.loc3_13.1 => constants.%V\n// CHECK:STDOUT:   %W.loc3_23.1 => constants.%W\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%V, constants.%W, constants.%Self.8fa) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T.67d, constants.%empty_tuple.type) {\n// CHECK:STDOUT:   %V.loc3_13.1 => constants.%T.67d\n// CHECK:STDOUT:   %W.loc3_23.1 => constants.%empty_tuple.type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.eb9\n// CHECK:STDOUT:   %Self.loc3_33.2 => constants.%Self.061\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc7_14.2 => constants.%T.67d\n// CHECK:STDOUT:   %I.type.loc7_36.2 => constants.%I.type.eb9\n// CHECK:STDOUT:   %I.impl_witness.loc7_38.2 => constants.%I.impl_witness.1cb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T.67d, constants.%empty_tuple.type, constants.%Self.8fa) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T.67d, constants.%empty_tuple.type, constants.%I.facet.a6e) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%empty_struct_type, constants.%empty_tuple.type) {\n// CHECK:STDOUT:   %V.loc3_13.1 => constants.%empty_struct_type\n// CHECK:STDOUT:   %W.loc3_23.1 => constants.%empty_tuple.type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.5f7\n// CHECK:STDOUT:   %Self.loc3_33.2 => constants.%Self.2a6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%empty_struct_type, constants.%empty_tuple.type, constants.%Self.8fa) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%T.bc3) {\n// CHECK:STDOUT:   %T.loc9_6.1 => constants.%T.bc3\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.826\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %T.loc7_14.2 => constants.%empty_struct_type\n// CHECK:STDOUT:   %I.type.loc7_36.2 => constants.%I.type.5f7\n// CHECK:STDOUT:   %I.impl_witness.loc7_38.2 => constants.%I.impl_witness.1c4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.1c0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%I.facet.0e1) {\n// CHECK:STDOUT:   %T.loc9_6.1 => constants.%I.facet.0e1\n// CHECK:STDOUT:   %T.binding.as_type => constants.%C\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.357\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_mismatch_impl_constraint_with_fixed_specific.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %V: type = symbolic_binding V, 0 [symbolic]\n// CHECK:STDOUT:   %W: type = symbolic_binding W, 1 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.54f: type = facet_type <@I, @I(%V, %W)> [symbolic]\n// CHECK:STDOUT:   %Self.8fa: %I.type.54f = symbolic_binding Self, 2 [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I.type.eb9: type = facet_type <@I, @I(%T.67d, %empty_tuple.type)> [symbolic]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table, @C.as.I.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %Self.061: %I.type.eb9 = symbolic_binding Self, 2 [symbolic]\n// CHECK:STDOUT:   %require_complete.d0a: <witness> = require_complete_type %I.type.eb9 [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type.eb9 = facet_value %C, (%I.impl_witness) [symbolic]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.7b9: type = facet_type <@I, @I(%empty_struct_type, %empty_struct_type)> [concrete]\n// CHECK:STDOUT:   %pattern_type.24a: type = pattern_type %I.type.7b9 [concrete]\n// CHECK:STDOUT:   %T.274: %I.type.7b9 = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Self.c70: %I.type.7b9 = symbolic_binding Self, 2 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.274 [symbolic]\n// CHECK:STDOUT:   %pattern_type.ced: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.b50: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %V.patt: %pattern_type.98f = symbolic_binding_pattern V, 0 [concrete]\n// CHECK:STDOUT:     %W.patt: %pattern_type.98f = symbolic_binding_pattern W, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc3_17.1: type = splice_block %.loc3_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc3_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %V.loc3_13.2: type = symbolic_binding V, 0 [symbolic = %V.loc3_13.1 (constants.%V)]\n// CHECK:STDOUT:     %.loc3_27.1: type = splice_block %.loc3_27.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc3_27.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %W.loc3_23.2: type = symbolic_binding W, 1 [symbolic = %W.loc3_23.1 (constants.%W)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc7_14.1 [symbolic = %T.loc7_14.2 (constants.%T.67d)]\n// CHECK:STDOUT:     %.loc7_35: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_36: type = converted %.loc7_35, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %I.type.loc7_36.1: type = facet_type <@I, @I(constants.%T.67d, constants.%empty_tuple.type)> [symbolic = %I.type.loc7_36.2 (constants.%I.type.eb9)]\n// CHECK:STDOUT:     %.loc7_18.1: type = splice_block %.loc7_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.24a = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %t.patt: @A.%pattern_type (%pattern_type.ced) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: @A.%pattern_type (%pattern_type.ced) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_18.1: type = splice_block %I.type [concrete = constants.%I.type.7b9] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %.loc9_13: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc9_17: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc9_18.2: type = converted %.loc9_13, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %.loc9_18.3: type = converted %.loc9_17, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %I.type: type = facet_type <@I, @I(constants.%empty_struct_type, constants.%empty_struct_type)> [concrete = constants.%I.type.7b9]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9_6.2: %I.type.7b9 = symbolic_binding T, 0 [symbolic = %T.loc9_6.1 (constants.%T.274)]\n// CHECK:STDOUT:     %t.param: @A.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc9_31.1: type = splice_block %.loc9_31.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref: %I.type.7b9 = name_ref T, %T.loc9_6.2 [symbolic = %T.loc9_6.1 (constants.%T.274)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_31.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %t: @A.%T.binding.as_type (%T.binding.as_type) = value_binding t, %t.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%V.loc3_13.2: type, %W.loc3_23.2: type) {\n// CHECK:STDOUT:   %V.loc3_13.1: type = symbolic_binding V, 0 [symbolic = %V.loc3_13.1 (constants.%V)]\n// CHECK:STDOUT:   %W.loc3_23.1: type = symbolic_binding W, 1 [symbolic = %W.loc3_23.1 (constants.%W)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%V.loc3_13.1, %W.loc3_23.1)> [symbolic = %I.type (constants.%I.type.54f)]\n// CHECK:STDOUT:   %Self.loc3_33.2: @I.%I.type (%I.type.54f) = symbolic_binding Self, 2 [symbolic = %Self.loc3_33.2 (constants.%Self.8fa)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc3_33.1: @I.%I.type (%I.type.54f) = symbolic_binding Self, 2 [symbolic = %Self.loc3_33.2 (constants.%Self.8fa)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc3_33.1\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl(%T.loc7_14.1: type) {\n// CHECK:STDOUT:   %T.loc7_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T.67d)]\n// CHECK:STDOUT:   %I.type.loc7_36.2: type = facet_type <@I, @I(%T.loc7_14.2, constants.%empty_tuple.type)> [symbolic = %I.type.loc7_36.2 (constants.%I.type.eb9)]\n// CHECK:STDOUT:   %I.impl_witness.loc7_38.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(%T.loc7_14.2) [symbolic = %I.impl_witness.loc7_38.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.loc7_36.2 [symbolic = %require_complete (constants.%require_complete.d0a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %I.type.loc7_36.1 {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc7_38.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(constants.%T.67d) [symbolic = %I.impl_witness.loc7_38.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %I.impl_witness.loc7_38.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @A(%T.loc9_6.2: %I.type.7b9) {\n// CHECK:STDOUT:   %T.loc9_6.1: %I.type.7b9 = symbolic_binding T, 0 [symbolic = %T.loc9_6.1 (constants.%T.274)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc9_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.ced)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.b50)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%t.param: @A.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc19_6.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc19_6.2: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc19_6.3: init %C to %.loc19_6.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc19_8: init %C = converted %.loc19_6.1, %.loc19_6.3 [concrete = constants.%C.val]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%V, constants.%W) {\n// CHECK:STDOUT:   %V.loc3_13.1 => constants.%V\n// CHECK:STDOUT:   %W.loc3_23.1 => constants.%W\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%V, constants.%W, constants.%Self.8fa) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T.67d, constants.%empty_tuple.type) {\n// CHECK:STDOUT:   %V.loc3_13.1 => constants.%T.67d\n// CHECK:STDOUT:   %W.loc3_23.1 => constants.%empty_tuple.type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.eb9\n// CHECK:STDOUT:   %Self.loc3_33.2 => constants.%Self.061\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc7_14.2 => constants.%T.67d\n// CHECK:STDOUT:   %I.type.loc7_36.2 => constants.%I.type.eb9\n// CHECK:STDOUT:   %I.impl_witness.loc7_38.2 => constants.%I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T.67d, constants.%empty_tuple.type, constants.%Self.8fa) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T.67d, constants.%empty_tuple.type, constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%empty_struct_type, constants.%empty_struct_type) {\n// CHECK:STDOUT:   %V.loc3_13.1 => constants.%empty_struct_type\n// CHECK:STDOUT:   %W.loc3_23.1 => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.7b9\n// CHECK:STDOUT:   %Self.loc3_33.2 => constants.%Self.c70\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%empty_struct_type, constants.%empty_struct_type, constants.%Self.8fa) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%T.274) {\n// CHECK:STDOUT:   %T.loc9_6.1 => constants.%T.274\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.ced\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_mismatch_impl_self_with_fixed_specific.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %V: type = symbolic_binding V, 0 [symbolic]\n// CHECK:STDOUT:   %W: type = symbolic_binding W, 1 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.2f8: type = class_type @C, @C(%V, %W) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %C.13c: type = class_type @C, @C(%T.67d, %empty_tuple.type) [symbolic]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table, @C.as.I.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C.13c, (%I.impl_witness) [symbolic]\n// CHECK:STDOUT:   %pattern_type.9d9: type = pattern_type %I.type [concrete]\n// CHECK:STDOUT:   %T.651: %I.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.651 [symbolic]\n// CHECK:STDOUT:   %pattern_type.422: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.9f1: type = class_type @C, @C(%empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %C.val: %C.9f1 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %V.patt: %pattern_type.98f = symbolic_binding_pattern V, 0 [concrete]\n// CHECK:STDOUT:     %W.patt: %pattern_type.98f = symbolic_binding_pattern W, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_13.1: type = splice_block %.loc5_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc5_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %V.loc5_9.2: type = symbolic_binding V, 0 [symbolic = %V.loc5_9.1 (constants.%V)]\n// CHECK:STDOUT:     %.loc5_23.1: type = splice_block %.loc5_23.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc5_23.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %W.loc5_19.2: type = symbolic_binding W, 1 [symbolic = %W.loc5_19.1 (constants.%W)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc7_14.1 [symbolic = %T.loc7_14.2 (constants.%T.67d)]\n// CHECK:STDOUT:     %.loc7_30: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_31: type = converted %.loc7_30, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %C.loc7_31.1: type = class_type @C, @C(constants.%T.67d, constants.%empty_tuple.type) [symbolic = %C.loc7_31.2 (constants.%C.13c)]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.loc7_18.1: type = splice_block %.loc7_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.9d9 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %t.patt: @A.%pattern_type (%pattern_type.422) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: @A.%pattern_type (%pattern_type.422) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_10: type = splice_block %I.ref [concrete = constants.%I.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9_6.2: %I.type = symbolic_binding T, 0 [symbolic = %T.loc9_6.1 (constants.%T.651)]\n// CHECK:STDOUT:     %t.param: @A.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc9_23.1: type = splice_block %.loc9_23.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref: %I.type = name_ref T, %T.loc9_6.2 [symbolic = %T.loc9_6.1 (constants.%T.651)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_23.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %t: @A.%T.binding.as_type (%T.binding.as_type) = value_binding t, %t.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl(%T.loc7_14.1: type) {\n// CHECK:STDOUT:   %T.loc7_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T.67d)]\n// CHECK:STDOUT:   %C.loc7_31.2: type = class_type @C, @C(%T.loc7_14.2, constants.%empty_tuple.type) [symbolic = %C.loc7_31.2 (constants.%C.13c)]\n// CHECK:STDOUT:   %I.impl_witness.loc7_38.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(%T.loc7_14.2) [symbolic = %I.impl_witness.loc7_38.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.loc7_31.1 as %I.ref {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc7_38.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(constants.%T.67d) [symbolic = %I.impl_witness.loc7_38.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %I.impl_witness.loc7_38.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%V.loc5_9.2: type, %W.loc5_19.2: type) {\n// CHECK:STDOUT:   %V.loc5_9.1: type = symbolic_binding V, 0 [symbolic = %V.loc5_9.1 (constants.%V)]\n// CHECK:STDOUT:   %W.loc5_19.1: type = symbolic_binding W, 1 [symbolic = %W.loc5_19.1 (constants.%W)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.2f8\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @A(%T.loc9_6.2: %I.type) {\n// CHECK:STDOUT:   %T.loc9_6.1: %I.type = symbolic_binding T, 0 [symbolic = %T.loc9_6.1 (constants.%T.651)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc9_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.422)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%t.param: @A.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc19_6.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %.loc19_14: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc19_18: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc19_19.1: type = converted %.loc19_14, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %.loc19_19.2: type = converted %.loc19_18, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(constants.%empty_struct_type, constants.%empty_struct_type) [concrete = constants.%C.9f1]\n// CHECK:STDOUT:   %.loc19_6.2: ref %C.9f1 = temporary_storage\n// CHECK:STDOUT:   %.loc19_6.3: init %C.9f1 to %.loc19_6.2 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc19_8: init %C.9f1 = converted %.loc19_6.1, %.loc19_6.3 [concrete = constants.%C.val]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%V, constants.%W) {\n// CHECK:STDOUT:   %V.loc5_9.1 => constants.%V\n// CHECK:STDOUT:   %W.loc5_19.1 => constants.%W\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T.67d, constants.%empty_tuple.type) {\n// CHECK:STDOUT:   %V.loc5_9.1 => constants.%T.67d\n// CHECK:STDOUT:   %W.loc5_19.1 => constants.%empty_tuple.type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc7_14.2 => constants.%T.67d\n// CHECK:STDOUT:   %C.loc7_31.2 => constants.%C.13c\n// CHECK:STDOUT:   %I.impl_witness.loc7_38.2 => constants.%I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%T.651) {\n// CHECK:STDOUT:   %T.loc9_6.1 => constants.%T.651\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.422\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%empty_struct_type, constants.%empty_struct_type) {\n// CHECK:STDOUT:   %V.loc5_9.1 => constants.%empty_struct_type\n// CHECK:STDOUT:   %W.loc5_19.1 => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_facet_type_to_facet_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_facet_type_to_facet_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_facet_type_to_facet_value.carbon\n\n// --- convert_facet_value_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Eats {}\ninterface Animal {}\n\n// TODO: This may be rejected in the future.\n// https://github.com/carbon-language/carbon-lang/issues/4853\nimpl Animal as Eats {}\n\nfn Feed(unused e:! Eats) {}\nfn F() {\n  Feed(Animal);\n}\n\n// --- fail_facet_value_to_facet_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Eats {}\ninterface Animal {}\n\n// TODO: This may be rejected in the future.\n// https://github.com/carbon-language/carbon-lang/issues/4853\nimpl Animal as Eats {}\n\nfn Feed(unused e:! Eats) {}\nclass Goat {}\nimpl Goat as Animal {}\n\nfn F() {\n  // CHECK:STDERR: fail_facet_value_to_facet_type.carbon:[[@LINE+7]]:3: error: cannot convert type `Goat as Animal` that implements `Animal` into type implementing `Eats` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   Feed(Goat as Animal);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_facet_value_to_facet_type.carbon:[[@LINE-8]]:16: note: initializing generic parameter `e` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn Feed(unused e:! Eats) {}\n  // CHECK:STDERR:                ^\n  // CHECK:STDERR:\n  Feed(Goat as Animal);\n}\n\n// --- fail_convert_multi_interface_facet_value_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Eats {}\ninterface Animal {}\ninterface Climbs {}\n\n// TODO: This may be rejected in the future.\n// https://github.com/carbon-language/carbon-lang/issues/4853\nimpl Animal as Eats {}\n\nfn Feed(unused e:! Eats) {}\nclass Goat {}\nimpl Goat as Animal {}\nimpl Goat as Climbs {}\n\n// These are expected to fail:\n// https://github.com/carbon-language/carbon-lang/issues/4853#issuecomment-2707673344\nfn F() {\n  // CHECK:STDERR: fail_convert_multi_interface_facet_value_to_facet_value.carbon:[[@LINE+7]]:3: error: cannot convert type `Goat as Animal & Climbs` that implements `Animal & Climbs` into type implementing `Eats` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   Feed(Goat as (Animal & Climbs));\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_convert_multi_interface_facet_value_to_facet_value.carbon:[[@LINE-11]]:16: note: initializing generic parameter `e` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn Feed(unused e:! Eats) {}\n  // CHECK:STDERR:                ^\n  // CHECK:STDERR:\n  Feed(Goat as (Animal & Climbs));\n\n  // CHECK:STDERR: fail_convert_multi_interface_facet_value_to_facet_value.carbon:[[@LINE+7]]:3: error: cannot convert type `Animal & Climbs` into type implementing `Eats` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   Feed(Animal & Climbs);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_convert_multi_interface_facet_value_to_facet_value.carbon:[[@LINE-20]]:16: note: initializing generic parameter `e` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn Feed(unused e:! Eats) {}\n  // CHECK:STDERR:                ^\n  // CHECK:STDERR:\n  Feed(Animal & Climbs);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_facet_value_as_type_knows_original_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_facet_value_as_type_knows_original_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_facet_value_as_type_knows_original_type.carbon\n\n// --- explicit_as_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Eats {}\ninterface Animal {}\n\nclass Goat {}\nimpl Goat as Animal {}\nimpl Goat as Eats {}\n\nfn Feed(unused e:! Eats) {}\n\nfn F() {\n  //@dump-sem-ir-begin\n  Feed((Goat as Animal) as type);\n  //@dump-sem-ir-end\n}\n\n// --- facet_type_in_type_position.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Eats {\n  fn Eat();\n}\ninterface Animal {}\n\nclass Goat {\n  fn Bleet() {}\n\n  impl as Animal {}\n  extend impl as Eats {\n    fn Eat() {}\n  }\n}\n\nfn F() {\n  // `Goat as Animal` in the type position retains/recovers the original type\n  // Goat, so member lookup can see more than just `Animal`.\n\n  //@dump-sem-ir-begin\n  let x: Goat as Animal = {} as Goat;\n  x.Bleet();\n  x.Eat();\n\n  (({} as Goat) as (Goat as Animal)).Bleet();\n  (({} as Goat) as (Goat as Animal)).Eat();\n  //@dump-sem-ir-end\n}\n\n// --- facet_access_type_converts_back_to_original_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface J {}\n\nclass C(A:! J, B:! A) {}\n\n// The class C is holding a specific with a 2 SymbolicBindings where one is a\n// *symbolic* type of the other.\n//\n// This means deduce will determine the argument type for `A`, then `B`. Then it\n// will traverse into deducing the type of `B` with the type of the parameter\n// `B`, which are both `FacetAccessType(A)`. This ultimately tries to deduce the\n// value for `A` again, so it needs to match, even though the argument is now\n// `FacetAccessType(A)`.\n//\n// This depends on unwrapping the `FacetAccessType(A)` when converting it to the\n// type of `A`, instead of evaluating to a `FacetValue` holding the\n// `FacetAccessType(A)` with a witness from the type of `A`. This preserves the\n// original facet value instead of constructing a different facet value\n// referring to the same symbolic type and with the same facet type.\n// Essentially, it allows lossless round trips through a FacetAccessType when\n// converting back to the type of its original facet value.\nfn G[A:! J, B:! A](unused x: C(A, B)) {}\n\nfn F[A:! J, B:! A](x: C(A, B)) {\n  //@dump-sem-ir-begin\n  G(x);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- explicit_as_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats> [concrete]\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Goat: type = class_type @Goat [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness @Goat.as.Animal.impl.%Animal.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat, (%Animal.impl_witness) [concrete]\n// CHECK:STDOUT:   %Eats.impl_witness: <witness> = impl_witness @Goat.as.Eats.impl.%Eats.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Eats.facet: %Eats.type = facet_value %Goat, (%Eats.impl_witness) [concrete]\n// CHECK:STDOUT:   %Feed.type: type = fn_type @Feed [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Feed: %Feed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Feed.specific_fn: <specific function> = specific_function %Feed, @Feed(%Eats.facet) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Feed.ref: %Feed.type = name_ref Feed, file.%Feed.decl [concrete = constants.%Feed]\n// CHECK:STDOUT:   %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat.ref, (constants.%Animal.impl_witness) [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %.loc14_14: %Animal.type = converted %Goat.ref, %Animal.facet [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %.loc14_28: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc14_14 [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc14_25: type = converted %.loc14_14, %as_type [concrete = constants.%Goat]\n// CHECK:STDOUT:   %Eats.facet: %Eats.type = facet_value %.loc14_25, (constants.%Eats.impl_witness) [concrete = constants.%Eats.facet]\n// CHECK:STDOUT:   %.loc14_32: %Eats.type = converted %.loc14_25, %Eats.facet [concrete = constants.%Eats.facet]\n// CHECK:STDOUT:   %Feed.specific_fn: <specific function> = specific_function %Feed.ref, @Feed(constants.%Eats.facet) [concrete = constants.%Feed.specific_fn]\n// CHECK:STDOUT:   %Feed.call: init %empty_tuple.type = call %Feed.specific_fn()\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- facet_type_in_type_position.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats> [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Eats.assoc_type: type = assoc_entity_type @Eats [concrete]\n// CHECK:STDOUT:   %assoc0.083: %Eats.assoc_type = assoc_entity element0, @Eats.WithSelf.%Eats.WithSelf.Eat.decl [concrete]\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Goat: type = class_type @Goat [concrete]\n// CHECK:STDOUT:   %Goat.Bleet.type: type = fn_type @Goat.Bleet [concrete]\n// CHECK:STDOUT:   %Goat.Bleet: %Goat.Bleet.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness @Goat.as.Animal.impl.%Animal.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat, (%Animal.impl_witness) [concrete]\n// CHECK:STDOUT:   %Eats.impl_witness: <witness> = impl_witness @Goat.as.Eats.impl.%Eats.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Goat.as.Eats.impl.Eat.type: type = fn_type @Goat.as.Eats.impl.Eat [concrete]\n// CHECK:STDOUT:   %Goat.as.Eats.impl.Eat: %Goat.as.Eats.impl.Eat.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Eats.facet: %Eats.type = facet_value %Goat, (%Eats.impl_witness) [concrete]\n// CHECK:STDOUT:   %Eats.WithSelf.Eat.type.b4d: type = fn_type @Eats.WithSelf.Eat, @Eats.WithSelf(%Eats.facet) [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %pattern_type.234: type = pattern_type %Goat [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Goat.val: %Goat = struct_value () [concrete]\n// CHECK:STDOUT:   %.35f: type = fn_type_with_self_type %Eats.WithSelf.Eat.type.b4d, %Eats.facet [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.234 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc22_28.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Goat.ref.loc22_33: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc22_28.2: ref %Goat = temporary_storage\n// CHECK:STDOUT:   %.loc22_28.3: init %Goat to %.loc22_28.2 = class_init () [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %.loc22_30.1: init %Goat = converted %.loc22_28.1, %.loc22_28.3 [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %.loc22_15.1: type = splice_block %.loc22_15.3 [concrete = constants.%Goat] {\n// CHECK:STDOUT:     %Goat.ref.loc22_10: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:     %Animal.ref.loc22: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     %Animal.facet.loc22: %Animal.type = facet_value %Goat.ref.loc22_10, (constants.%Animal.impl_witness) [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:     %.loc22_15.2: %Animal.type = converted %Goat.ref.loc22_10, %Animal.facet.loc22 [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:     %as_type.loc22: type = facet_access_type %.loc22_15.2 [concrete = constants.%Goat]\n// CHECK:STDOUT:     %.loc22_15.3: type = converted %.loc22_15.2, %as_type.loc22 [concrete = constants.%Goat]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc22_30.2: ref %Goat = temporary %.loc22_28.2, %.loc22_30.1\n// CHECK:STDOUT:   %.loc22_30.3: %Goat = acquire_value %.loc22_30.2\n// CHECK:STDOUT:   %x: %Goat = value_binding x, %.loc22_30.3\n// CHECK:STDOUT:   %x.ref.loc23: %Goat = name_ref x, %x\n// CHECK:STDOUT:   %Bleet.ref.loc23: %Goat.Bleet.type = name_ref Bleet, @Goat.%Goat.Bleet.decl [concrete = constants.%Goat.Bleet]\n// CHECK:STDOUT:   %Goat.Bleet.call.loc23: init %empty_tuple.type = call %Bleet.ref.loc23()\n// CHECK:STDOUT:   %x.ref.loc24: %Goat = name_ref x, %x\n// CHECK:STDOUT:   %Eat.ref.loc24: %Eats.assoc_type = name_ref Eat, @Eats.WithSelf.%assoc0 [concrete = constants.%assoc0.083]\n// CHECK:STDOUT:   %impl.elem0.loc24: %.35f = impl_witness_access constants.%Eats.impl_witness, element0 [concrete = constants.%Goat.as.Eats.impl.Eat]\n// CHECK:STDOUT:   %Goat.as.Eats.impl.Eat.call.loc24: init %empty_tuple.type = call %impl.elem0.loc24()\n// CHECK:STDOUT:   %.loc26_6.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Goat.ref.loc26_11: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc26_6.2: ref %Goat = temporary_storage\n// CHECK:STDOUT:   %.loc26_6.3: init %Goat to %.loc26_6.2 = class_init () [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %.loc26_8.1: init %Goat = converted %.loc26_6.1, %.loc26_6.3 [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %Goat.ref.loc26_21: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %Animal.ref.loc26: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:   %Animal.facet.loc26: %Animal.type = facet_value %Goat.ref.loc26_21, (constants.%Animal.impl_witness) [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %.loc26_26: %Animal.type = converted %Goat.ref.loc26_21, %Animal.facet.loc26 [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %as_type.loc26: type = facet_access_type %.loc26_26 [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc26_35: type = converted %.loc26_26, %as_type.loc26 [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc26_8.2: ref %Goat = temporary %.loc26_6.2, %.loc26_8.1\n// CHECK:STDOUT:   %Bleet.ref.loc26: %Goat.Bleet.type = name_ref Bleet, @Goat.%Goat.Bleet.decl [concrete = constants.%Goat.Bleet]\n// CHECK:STDOUT:   %Goat.Bleet.call.loc26: init %empty_tuple.type = call %Bleet.ref.loc26()\n// CHECK:STDOUT:   %.loc27_6.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Goat.ref.loc27_11: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc27_6.2: ref %Goat = temporary_storage\n// CHECK:STDOUT:   %.loc27_6.3: init %Goat to %.loc27_6.2 = class_init () [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %.loc27_8.1: init %Goat = converted %.loc27_6.1, %.loc27_6.3 [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %Goat.ref.loc27_21: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %Animal.ref.loc27: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:   %Animal.facet.loc27: %Animal.type = facet_value %Goat.ref.loc27_21, (constants.%Animal.impl_witness) [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %.loc27_26: %Animal.type = converted %Goat.ref.loc27_21, %Animal.facet.loc27 [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %as_type.loc27: type = facet_access_type %.loc27_26 [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc27_35: type = converted %.loc27_26, %as_type.loc27 [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc27_8.2: ref %Goat = temporary %.loc27_6.2, %.loc27_8.1\n// CHECK:STDOUT:   %Eat.ref.loc27: %Eats.assoc_type = name_ref Eat, @Eats.WithSelf.%assoc0 [concrete = constants.%assoc0.083]\n// CHECK:STDOUT:   %impl.elem0.loc27: %.35f = impl_witness_access constants.%Eats.impl_witness, element0 [concrete = constants.%Goat.as.Eats.impl.Eat]\n// CHECK:STDOUT:   %Goat.as.Eats.impl.Eat.call.loc27: init %empty_tuple.type = call %impl.elem0.loc27()\n// CHECK:STDOUT:   %Destroy.Op.bound.loc27: <bound method> = bound_method %.loc27_8.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc27: init %empty_tuple.type = call %Destroy.Op.bound.loc27(%.loc27_8.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc26: <bound method> = bound_method %.loc26_8.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc26: init %empty_tuple.type = call %Destroy.Op.bound.loc26(%.loc26_8.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc22: <bound method> = bound_method %.loc22_30.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc22: init %empty_tuple.type = call %Destroy.Op.bound.loc22(%.loc22_30.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Goat) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- facet_access_type_converts_back_to_original_facet_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]\n// CHECK:STDOUT:   %A: %J.type = symbolic_binding A, 0 [symbolic]\n// CHECK:STDOUT:   %A.binding.as_type: type = symbolic_binding_type A, 0, %A [symbolic]\n// CHECK:STDOUT:   %pattern_type.14f: type = pattern_type %A.binding.as_type [symbolic]\n// CHECK:STDOUT:   %B: %A.binding.as_type = symbolic_binding B, 1 [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%A, %B) [symbolic]\n// CHECK:STDOUT:   %pattern_type.e04: type = pattern_type %C [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G, @G(%A, %B) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%A.loc25_6.2: %J.type, %B.loc25_13.2: @F.%A.binding.as_type (%A.binding.as_type)) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %G.specific_fn.loc27_3.2: <specific function> = specific_function constants.%G, @G(%A.loc25_6.1, %B.loc25_13.1) [symbolic = %G.specific_fn.loc27_3.2 (constants.%G.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%C.loc25_29.1 (%C)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:     %x.ref: @F.%C.loc25_29.1 (%C) = name_ref x, %x\n// CHECK:STDOUT:     %.loc27: %J.type = converted constants.%A.binding.as_type, constants.%A [symbolic = %A.loc25_6.1 (constants.%A)]\n// CHECK:STDOUT:     %G.specific_fn.loc27_3.1: <specific function> = specific_function %G.ref, @G(constants.%A, constants.%B) [symbolic = %G.specific_fn.loc27_3.2 (constants.%G.specific_fn)]\n// CHECK:STDOUT:     %G.call: init %empty_tuple.type = call %G.specific_fn.loc27_3.1(%x.ref)\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%A, constants.%B) {\n// CHECK:STDOUT:   %A.loc25_6.1 => constants.%A\n// CHECK:STDOUT:   %A.binding.as_type => constants.%A.binding.as_type\n// CHECK:STDOUT:   %B.loc25_13.1 => constants.%B\n// CHECK:STDOUT:   %pattern_type.loc25_13 => constants.%pattern_type.14f\n// CHECK:STDOUT:   %C.loc25_29.1 => constants.%C\n// CHECK:STDOUT:   %pattern_type.loc25_20 => constants.%pattern_type.e04\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_facet_value_to_facet_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_facet_value_to_facet_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_facet_value_to_facet_value.carbon\n\n// --- convert_concrete_facet_value_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\ninterface Y {}\n\nclass C {}\nimpl C as Z {}\nimpl C as Y {}\n\nfn G(unused z:! Z) {}\n\nfn F() {\n  G(C);\n  G(C as Y);\n  G(C as Z);\n  G(C as (Y & Z));\n\n  G(((((C as Y) as type) as Y) as type) as Y);\n  G((((((C as Y) as type) as Y) as type) as Y) as type);\n}\n\n// --- convert_symbolic_facet_value_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\ninterface Y {}\nimpl forall [T:! Y] T as Z {}\n\nfn F(U:! Y) {\n  U as Z;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_facet_value_to_itself.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_facet_value_to_itself.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_facet_value_to_itself.carbon\n\ninterface Animal {}\n\nfn FeedAnimal(unused T:! Animal) {}\n\nfn HandleAnimal(T:! Animal) { FeedAnimal(T); }\n\nclass Goat {}\nimpl Goat as Animal {}\n\nfn F() {\n  HandleAnimal(Goat);\n}\n\n// CHECK:STDOUT: --- convert_facet_value_to_itself.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Animal.type [concrete]\n// CHECK:STDOUT:   %T.99815a.1: %Animal.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %FeedAnimal.type: type = fn_type @FeedAnimal [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %FeedAnimal: %FeedAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T.99815a.2: %Animal.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %HandleAnimal.type: type = fn_type @HandleAnimal [concrete]\n// CHECK:STDOUT:   %HandleAnimal: %HandleAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %FeedAnimal.specific_fn.ae9: <specific function> = specific_function %FeedAnimal, @FeedAnimal(%T.99815a.2) [symbolic]\n// CHECK:STDOUT:   %Goat: type = class_type @Goat [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness @Goat.as.Animal.impl.%Animal.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat, (%Animal.impl_witness) [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %HandleAnimal.specific_fn: <specific function> = specific_function %HandleAnimal, @HandleAnimal(%Animal.facet) [concrete]\n// CHECK:STDOUT:   %FeedAnimal.specific_fn.cc5: <specific function> = specific_function %FeedAnimal, @FeedAnimal(%Animal.facet) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .FeedAnimal = %FeedAnimal.decl\n// CHECK:STDOUT:     .HandleAnimal = %HandleAnimal.decl\n// CHECK:STDOUT:     .Goat = %Goat.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   %FeedAnimal.decl: %FeedAnimal.type = fn_decl @FeedAnimal [concrete = constants.%FeedAnimal] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc17: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc17_22.2: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc17_22.1 (constants.%T.99815a.1)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %HandleAnimal.decl: %HandleAnimal.type = fn_decl @HandleAnimal [concrete = constants.%HandleAnimal] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc19: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc19_17.2: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc19_17.1 (constants.%T.99815a.2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Goat.decl: type = class_decl @Goat [concrete = constants.%Goat] {} {}\n// CHECK:STDOUT:   impl_decl @Goat.as.Animal.impl [concrete] {} {\n// CHECK:STDOUT:     %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:     %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Goat.as.Animal.impl: %Goat.ref as %Animal.ref {\n// CHECK:STDOUT:   %Animal.impl_witness_table = impl_witness_table (), @Goat.as.Animal.impl [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness %Animal.impl_witness_table [concrete = constants.%Animal.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Animal.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Goat {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Goat\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @FeedAnimal(%T.loc17_22.2: %Animal.type) {\n// CHECK:STDOUT:   %T.loc17_22.1: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc17_22.1 (constants.%T.99815a.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @HandleAnimal(%T.loc19_17.2: %Animal.type) {\n// CHECK:STDOUT:   %T.loc19_17.1: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc19_17.1 (constants.%T.99815a.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %FeedAnimal.specific_fn.loc19_31.2: <specific function> = specific_function constants.%FeedAnimal, @FeedAnimal(%T.loc19_17.1) [symbolic = %FeedAnimal.specific_fn.loc19_31.2 (constants.%FeedAnimal.specific_fn.ae9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %FeedAnimal.ref: %FeedAnimal.type = name_ref FeedAnimal, file.%FeedAnimal.decl [concrete = constants.%FeedAnimal]\n// CHECK:STDOUT:     %T.ref: %Animal.type = name_ref T, %T.loc19_17.2 [symbolic = %T.loc19_17.1 (constants.%T.99815a.2)]\n// CHECK:STDOUT:     %FeedAnimal.specific_fn.loc19_31.1: <specific function> = specific_function %FeedAnimal.ref, @FeedAnimal(constants.%T.99815a.2) [symbolic = %FeedAnimal.specific_fn.loc19_31.2 (constants.%FeedAnimal.specific_fn.ae9)]\n// CHECK:STDOUT:     %FeedAnimal.call: init %empty_tuple.type = call %FeedAnimal.specific_fn.loc19_31.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %HandleAnimal.ref: %HandleAnimal.type = name_ref HandleAnimal, file.%HandleAnimal.decl [concrete = constants.%HandleAnimal]\n// CHECK:STDOUT:   %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat.ref, (constants.%Animal.impl_witness) [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %.loc25: %Animal.type = converted %Goat.ref, %Animal.facet [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %HandleAnimal.specific_fn: <specific function> = specific_function %HandleAnimal.ref, @HandleAnimal(constants.%Animal.facet) [concrete = constants.%HandleAnimal.specific_fn]\n// CHECK:STDOUT:   %HandleAnimal.call: init %empty_tuple.type = call %HandleAnimal.specific_fn()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @FeedAnimal(constants.%T.99815a.1) {\n// CHECK:STDOUT:   %T.loc17_22.1 => constants.%T.99815a.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleAnimal(constants.%T.99815a.2) {\n// CHECK:STDOUT:   %T.loc19_17.1 => constants.%T.99815a.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @FeedAnimal(constants.%T.99815a.2) {\n// CHECK:STDOUT:   %T.loc17_22.1 => constants.%T.99815a.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Animal.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleAnimal(constants.%Animal.facet) {\n// CHECK:STDOUT:   %T.loc19_17.1 => constants.%Animal.facet\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %FeedAnimal.specific_fn.loc19_31.2 => constants.%FeedAnimal.specific_fn.cc5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @FeedAnimal(constants.%Animal.facet) {\n// CHECK:STDOUT:   %T.loc17_22.1 => constants.%Animal.facet\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_facet_value_to_narrowed_facet_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_facet_value_to_narrowed_facet_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_facet_value_to_narrowed_facet_type.carbon\n\n// --- convert_to_narrowed_facet_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Eats {}\ninterface Animal {}\n\nfn Feed[T:! Eats](unused e: T) {}\n\nfn HandleAnimal[U:! Animal & Eats](a: U) { Feed(a); }\n\n// --- bigger.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Eats {}\ninterface Animal {}\ninterface Tame {}\n\nfn FeedTame[V:! Tame & Eats](unused v: V) {}\n\nfn HandleTameAnimal[W:! Eats & Animal & Tame](w: W) {\n  FeedTame(w);\n}\n\n// --- with_blanket.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Eats {}\ninterface Animal {}\ninterface Tame {}\n\nimpl forall [A:! Animal] A as Eats {}\n\nfn FeedTame2[V:! Tame & Eats](unused v: V) {}\n\nfn HandleTameAnimal2[W:! Animal & Tame](w: W) {\n  FeedTame2(w);\n}\n\n// --- equivalent.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// This is testing `FindWitnessInFacet` from impl_lookup.cpp\n\ninterface A {}\n\nfn TakesA[T:! A](unused x: T) {}\n\nfn WithExtraWhere[U:! A where .Self impls type](y: U) {\n  TakesA(y);\n}\n\n// --- no_interfaces_success.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn TakesTypeDeduced[T:! type](unused x: T) {}\nfn CallsWithExtraWhere[U:! type where .Self impls type](y: U) {\n  TakesTypeDeduced(y);\n}\n\nfn TakesTypeExplicit(unused T:! type) {}\nfn CallsWithExtraWhereExplicit(U:! type where .Self impls type) {\n  TakesTypeExplicit(U);\n}\n\n// --- no_interfaces.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn TakesExtraWhereDeduced[T:! type where .Self impls type](unused x: T) {}\nfn CallsWithType[U:! type](y: U) {\n  TakesExtraWhereDeduced(y);\n}\n\nfn TakesExtraWhereExplicit(unused T:! type where .Self impls type) {}\nfn CallsWithTypeExplicit(U:! type) {\n  TakesExtraWhereExplicit(U);\n}\n\n// CHECK:STDOUT: --- convert_to_narrowed_facet_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats> [concrete]\n// CHECK:STDOUT:   %Self.247: %Eats.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self.c49: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.0dc: type = pattern_type %Eats.type [concrete]\n// CHECK:STDOUT:   %T: %Eats.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.93e: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Feed.type: type = fn_type @Feed [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Feed: %Feed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.9d9: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %BitAndWith.type.f2e: type = generic_interface_type @BitAndWith [concrete]\n// CHECK:STDOUT:   %BitAndWith.generic: %BitAndWith.type.f2e = struct_value () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.b10: type = facet_type <@BitAndWith, @BitAndWith(type)> [concrete]\n// CHECK:STDOUT:   %BitAndWith.impl_witness: <witness> = impl_witness imports.%BitAndWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %BitAndWith.facet: %BitAndWith.type.b10 = facet_value type, (%BitAndWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %BitAndWith.WithSelf.Op.type.4bd: type = fn_type @BitAndWith.WithSelf.Op, @BitAndWith.WithSelf(type, %BitAndWith.facet) [concrete]\n// CHECK:STDOUT:   %.d15: type = fn_type_with_self_type %BitAndWith.WithSelf.Op.type.4bd, %BitAndWith.facet [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.type: type = fn_type @type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op: %type.as.BitAndWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound: <bound method> = bound_method %Animal.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type: type = facet_type <@Eats & @Animal> [concrete]\n// CHECK:STDOUT:   %pattern_type.37f: type = pattern_type %facet_type [concrete]\n// CHECK:STDOUT:   %U: %facet_type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U [symbolic]\n// CHECK:STDOUT:   %pattern_type.256: type = pattern_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %HandleAnimal.type: type = fn_type @HandleAnimal [concrete]\n// CHECK:STDOUT:   %HandleAnimal: %HandleAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.ff4: <witness> = require_complete_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %U, @Eats [symbolic]\n// CHECK:STDOUT:   %Eats.facet: %Eats.type = facet_value %U.binding.as_type, (%Eats.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Feed.specific_fn: <specific function> = specific_function %Feed, @Feed(%Eats.facet) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .BitAndWith = %Core.BitAndWith\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.BitAndWith: %BitAndWith.type.f2e = import_ref Core//prelude/parts/as, BitAndWith, loaded [concrete = constants.%BitAndWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.8d3: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:   %BitAndWith.impl_witness_table = impl_witness_table (%Core.import_ref.8d3), @type.as.BitAndWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Eats = %Eats.decl\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .Feed = %Feed.decl\n// CHECK:STDOUT:     .HandleAnimal = %HandleAnimal.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Eats.decl: type = interface_decl @Eats [concrete = constants.%Eats.type] {} {}\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   %Feed.decl: %Feed.type = fn_decl @Feed [concrete = constants.%Feed] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.0dc = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %e.patt: @Feed.%pattern_type (%pattern_type.93e) = value_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.param_patt: @Feed.%pattern_type (%pattern_type.93e) = value_param_pattern %e.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_13: type = splice_block %Eats.ref [concrete = constants.%Eats.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_9.2: %Eats.type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:     %e.param: @Feed.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_29.1: type = splice_block %.loc6_29.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref: %Eats.type = name_ref T, %T.loc6_9.2 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc6_29.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %e: @Feed.%T.binding.as_type (%T.binding.as_type) = value_binding e, %e.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %HandleAnimal.decl: %HandleAnimal.type = fn_decl @HandleAnimal [concrete = constants.%HandleAnimal] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.37f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @HandleAnimal.%pattern_type (%pattern_type.256) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @HandleAnimal.%pattern_type (%pattern_type.256) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_28.1: type = splice_block %.loc8_28.3 [concrete = constants.%facet_type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:       %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:       %impl.elem0: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method: <bound method> = bound_method %Animal.ref, %impl.elem0 [concrete = constants.%type.as.BitAndWith.impl.Op.bound]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call: init type = call %bound_method(%Animal.ref, %Eats.ref) [concrete = constants.%facet_type]\n// CHECK:STDOUT:       %.loc8_28.2: type = value_of_initializer %type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type]\n// CHECK:STDOUT:       %.loc8_28.3: type = converted %type.as.BitAndWith.impl.Op.call, %.loc8_28.2 [concrete = constants.%facet_type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc8_17.2: %facet_type = symbolic_binding U, 0 [symbolic = %U.loc8_17.1 (constants.%U)]\n// CHECK:STDOUT:     %a.param: @HandleAnimal.%U.binding.as_type (%U.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc8_39.1: type = splice_block %.loc8_39.2 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)] {\n// CHECK:STDOUT:       %U.ref: %facet_type = name_ref U, %U.loc8_17.2 [symbolic = %U.loc8_17.1 (constants.%U)]\n// CHECK:STDOUT:       %U.as_type: type = facet_access_type %U.ref [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:       %.loc8_39.2: type = converted %U.ref, %U.as_type [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @HandleAnimal.%U.binding.as_type (%U.binding.as_type) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Eats {\n// CHECK:STDOUT:   %Self: %Eats.type = symbolic_binding Self, 0 [symbolic = constants.%Self.247]\n// CHECK:STDOUT:   %Eats.WithSelf.decl = interface_with_self_decl @Eats [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c49]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Feed(%T.loc6_9.2: %Eats.type) {\n// CHECK:STDOUT:   %T.loc6_9.1: %Eats.type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc6_9.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.93e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.9d9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%e.param: @Feed.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @HandleAnimal(%U.loc8_17.2: %facet_type) {\n// CHECK:STDOUT:   %U.loc8_17.1: %facet_type = symbolic_binding U, 0 [symbolic = %U.loc8_17.1 (constants.%U)]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U.loc8_17.1 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %U.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.256)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %U.binding.as_type [symbolic = %require_complete (constants.%require_complete.ff4)]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %U.loc8_17.1, @Eats [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]\n// CHECK:STDOUT:   %Eats.facet.loc8_50.2: %Eats.type = facet_value %U.binding.as_type, (%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc8_50.2 (constants.%Eats.facet)]\n// CHECK:STDOUT:   %Feed.specific_fn.loc8_44.2: <specific function> = specific_function constants.%Feed, @Feed(%Eats.facet.loc8_50.2) [symbolic = %Feed.specific_fn.loc8_44.2 (constants.%Feed.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @HandleAnimal.%U.binding.as_type (%U.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %Feed.ref: %Feed.type = name_ref Feed, file.%Feed.decl [concrete = constants.%Feed]\n// CHECK:STDOUT:     %a.ref: @HandleAnimal.%U.binding.as_type (%U.binding.as_type) = name_ref a, %a\n// CHECK:STDOUT:     %Eats.facet.loc8_50.1: %Eats.type = facet_value constants.%U.binding.as_type, (constants.%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc8_50.2 (constants.%Eats.facet)]\n// CHECK:STDOUT:     %.loc8_50: %Eats.type = converted constants.%U.binding.as_type, %Eats.facet.loc8_50.1 [symbolic = %Eats.facet.loc8_50.2 (constants.%Eats.facet)]\n// CHECK:STDOUT:     %Feed.specific_fn.loc8_44.1: <specific function> = specific_function %Feed.ref, @Feed(constants.%Eats.facet) [symbolic = %Feed.specific_fn.loc8_44.2 (constants.%Feed.specific_fn)]\n// CHECK:STDOUT:     %Feed.call: init %empty_tuple.type = call %Feed.specific_fn.loc8_44.1(%a.ref)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Self.247) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self.c49) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Feed(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_9.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.93e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleAnimal(constants.%U) {\n// CHECK:STDOUT:   %U.loc8_17.1 => constants.%U\n// CHECK:STDOUT:   %U.binding.as_type => constants.%U.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.256\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Feed(constants.%Eats.facet) {\n// CHECK:STDOUT:   %T.loc6_9.1 => constants.%Eats.facet\n// CHECK:STDOUT:   %T.binding.as_type => constants.%U.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.256\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.ff4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- bigger.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats> [concrete]\n// CHECK:STDOUT:   %Self.247: %Eats.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self.c49: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Tame.type: type = facet_type <@Tame> [concrete]\n// CHECK:STDOUT:   %Self.ab8: %Tame.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %BitAndWith.type.f2e: type = generic_interface_type @BitAndWith [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %BitAndWith.generic: %BitAndWith.type.f2e = struct_value () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.b10: type = facet_type <@BitAndWith, @BitAndWith(type)> [concrete]\n// CHECK:STDOUT:   %BitAndWith.impl_witness: <witness> = impl_witness imports.%BitAndWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %BitAndWith.facet: %BitAndWith.type.b10 = facet_value type, (%BitAndWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %BitAndWith.WithSelf.Op.type.4bd: type = fn_type @BitAndWith.WithSelf.Op, @BitAndWith.WithSelf(type, %BitAndWith.facet) [concrete]\n// CHECK:STDOUT:   %.d15: type = fn_type_with_self_type %BitAndWith.WithSelf.Op.type.4bd, %BitAndWith.facet [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.type: type = fn_type @type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op: %type.as.BitAndWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound.a5f: <bound method> = bound_method %Tame.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type.2db: type = facet_type <@Eats & @Tame> [concrete]\n// CHECK:STDOUT:   %pattern_type.fa7: type = pattern_type %facet_type.2db [concrete]\n// CHECK:STDOUT:   %V: %facet_type.2db = symbolic_binding V, 0 [symbolic]\n// CHECK:STDOUT:   %V.binding.as_type: type = symbolic_binding_type V, 0, %V [symbolic]\n// CHECK:STDOUT:   %pattern_type.795: type = pattern_type %V.binding.as_type [symbolic]\n// CHECK:STDOUT:   %FeedTame.type: type = fn_type @FeedTame [concrete]\n// CHECK:STDOUT:   %FeedTame: %FeedTame.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.12d: <witness> = require_complete_type %V.binding.as_type [symbolic]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound.10c: <bound method> = bound_method %Eats.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type.a63: type = facet_type <@Eats & @Animal> [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound.986: <bound method> = bound_method %facet_type.a63, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type.206: type = facet_type <@Eats & @Animal & @Tame> [concrete]\n// CHECK:STDOUT:   %pattern_type.fb4: type = pattern_type %facet_type.206 [concrete]\n// CHECK:STDOUT:   %W: %facet_type.206 = symbolic_binding W, 0 [symbolic]\n// CHECK:STDOUT:   %W.binding.as_type: type = symbolic_binding_type W, 0, %W [symbolic]\n// CHECK:STDOUT:   %pattern_type.e8e: type = pattern_type %W.binding.as_type [symbolic]\n// CHECK:STDOUT:   %HandleTameAnimal.type: type = fn_type @HandleTameAnimal [concrete]\n// CHECK:STDOUT:   %HandleTameAnimal: %HandleTameAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.817: <witness> = require_complete_type %W.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %W, @Eats [symbolic]\n// CHECK:STDOUT:   %Tame.lookup_impl_witness: <witness> = lookup_impl_witness %W, @Tame [symbolic]\n// CHECK:STDOUT:   %facet_value: %facet_type.2db = facet_value %W.binding.as_type, (%Eats.lookup_impl_witness, %Tame.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %FeedTame.specific_fn: <specific function> = specific_function %FeedTame, @FeedTame(%facet_value) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .BitAndWith = %Core.BitAndWith\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.BitAndWith: %BitAndWith.type.f2e = import_ref Core//prelude/parts/as, BitAndWith, loaded [concrete = constants.%BitAndWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.8d3: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:   %BitAndWith.impl_witness_table = impl_witness_table (%Core.import_ref.8d3), @type.as.BitAndWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Eats = %Eats.decl\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .Tame = %Tame.decl\n// CHECK:STDOUT:     .FeedTame = %FeedTame.decl\n// CHECK:STDOUT:     .HandleTameAnimal = %HandleTameAnimal.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Eats.decl: type = interface_decl @Eats [concrete = constants.%Eats.type] {} {}\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   %Tame.decl: type = interface_decl @Tame [concrete = constants.%Tame.type] {} {}\n// CHECK:STDOUT:   %FeedTame.decl: %FeedTame.type = fn_decl @FeedTame [concrete = constants.%FeedTame] {\n// CHECK:STDOUT:     %V.patt: %pattern_type.fa7 = symbolic_binding_pattern V, 0 [concrete]\n// CHECK:STDOUT:     %v.patt: @FeedTame.%pattern_type (%pattern_type.795) = value_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.param_patt: @FeedTame.%pattern_type (%pattern_type.795) = value_param_pattern %v.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_22.1: type = splice_block %.loc7_22.3 [concrete = constants.%facet_type.2db] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Tame.ref: type = name_ref Tame, file.%Tame.decl [concrete = constants.%Tame.type]\n// CHECK:STDOUT:       %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:       %impl.elem0: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method: <bound method> = bound_method %Tame.ref, %impl.elem0 [concrete = constants.%type.as.BitAndWith.impl.Op.bound.a5f]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call: init type = call %bound_method(%Tame.ref, %Eats.ref) [concrete = constants.%facet_type.2db]\n// CHECK:STDOUT:       %.loc7_22.2: type = value_of_initializer %type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type.2db]\n// CHECK:STDOUT:       %.loc7_22.3: type = converted %type.as.BitAndWith.impl.Op.call, %.loc7_22.2 [concrete = constants.%facet_type.2db]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %V.loc7_13.2: %facet_type.2db = symbolic_binding V, 0 [symbolic = %V.loc7_13.1 (constants.%V)]\n// CHECK:STDOUT:     %v.param: @FeedTame.%V.binding.as_type (%V.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc7_40.1: type = splice_block %.loc7_40.2 [symbolic = %V.binding.as_type (constants.%V.binding.as_type)] {\n// CHECK:STDOUT:       %V.ref: %facet_type.2db = name_ref V, %V.loc7_13.2 [symbolic = %V.loc7_13.1 (constants.%V)]\n// CHECK:STDOUT:       %V.as_type: type = facet_access_type %V.ref [symbolic = %V.binding.as_type (constants.%V.binding.as_type)]\n// CHECK:STDOUT:       %.loc7_40.2: type = converted %V.ref, %V.as_type [symbolic = %V.binding.as_type (constants.%V.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v: @FeedTame.%V.binding.as_type (%V.binding.as_type) = value_binding v, %v.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %HandleTameAnimal.decl: %HandleTameAnimal.type = fn_decl @HandleTameAnimal [concrete = constants.%HandleTameAnimal] {\n// CHECK:STDOUT:     %W.patt: %pattern_type.fb4 = symbolic_binding_pattern W, 0 [concrete]\n// CHECK:STDOUT:     %w.patt: @HandleTameAnimal.%pattern_type (%pattern_type.e8e) = value_binding_pattern w [concrete]\n// CHECK:STDOUT:     %w.param_patt: @HandleTameAnimal.%pattern_type (%pattern_type.e8e) = value_param_pattern %w.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_39.1: type = splice_block %.loc9_39.3 [concrete = constants.%facet_type.206] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:       %impl.elem0.loc9_30: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method.loc9_30: <bound method> = bound_method %Eats.ref, %impl.elem0.loc9_30 [concrete = constants.%type.as.BitAndWith.impl.Op.bound.10c]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call.loc9_30: init type = call %bound_method.loc9_30(%Eats.ref, %Animal.ref) [concrete = constants.%facet_type.a63]\n// CHECK:STDOUT:       %Tame.ref: type = name_ref Tame, file.%Tame.decl [concrete = constants.%Tame.type]\n// CHECK:STDOUT:       %impl.elem0.loc9_39: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method.loc9_39: <bound method> = bound_method %type.as.BitAndWith.impl.Op.call.loc9_30, %impl.elem0.loc9_39 [concrete = constants.%type.as.BitAndWith.impl.Op.bound.986]\n// CHECK:STDOUT:       %.loc9_30.1: type = value_of_initializer %type.as.BitAndWith.impl.Op.call.loc9_30 [concrete = constants.%facet_type.a63]\n// CHECK:STDOUT:       %.loc9_30.2: type = converted %type.as.BitAndWith.impl.Op.call.loc9_30, %.loc9_30.1 [concrete = constants.%facet_type.a63]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call.loc9_39: init type = call %bound_method.loc9_39(%.loc9_30.2, %Tame.ref) [concrete = constants.%facet_type.206]\n// CHECK:STDOUT:       %.loc9_39.2: type = value_of_initializer %type.as.BitAndWith.impl.Op.call.loc9_39 [concrete = constants.%facet_type.206]\n// CHECK:STDOUT:       %.loc9_39.3: type = converted %type.as.BitAndWith.impl.Op.call.loc9_39, %.loc9_39.2 [concrete = constants.%facet_type.206]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %W.loc9_21.2: %facet_type.206 = symbolic_binding W, 0 [symbolic = %W.loc9_21.1 (constants.%W)]\n// CHECK:STDOUT:     %w.param: @HandleTameAnimal.%W.binding.as_type (%W.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc9_50.1: type = splice_block %.loc9_50.2 [symbolic = %W.binding.as_type (constants.%W.binding.as_type)] {\n// CHECK:STDOUT:       %W.ref: %facet_type.206 = name_ref W, %W.loc9_21.2 [symbolic = %W.loc9_21.1 (constants.%W)]\n// CHECK:STDOUT:       %W.as_type: type = facet_access_type %W.ref [symbolic = %W.binding.as_type (constants.%W.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_50.2: type = converted %W.ref, %W.as_type [symbolic = %W.binding.as_type (constants.%W.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %w: @HandleTameAnimal.%W.binding.as_type (%W.binding.as_type) = value_binding w, %w.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Eats {\n// CHECK:STDOUT:   %Self: %Eats.type = symbolic_binding Self, 0 [symbolic = constants.%Self.247]\n// CHECK:STDOUT:   %Eats.WithSelf.decl = interface_with_self_decl @Eats [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c49]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Tame {\n// CHECK:STDOUT:   %Self: %Tame.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab8]\n// CHECK:STDOUT:   %Tame.WithSelf.decl = interface_with_self_decl @Tame [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @FeedTame(%V.loc7_13.2: %facet_type.2db) {\n// CHECK:STDOUT:   %V.loc7_13.1: %facet_type.2db = symbolic_binding V, 0 [symbolic = %V.loc7_13.1 (constants.%V)]\n// CHECK:STDOUT:   %V.binding.as_type: type = symbolic_binding_type V, 0, %V.loc7_13.1 [symbolic = %V.binding.as_type (constants.%V.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %V.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.795)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %V.binding.as_type [symbolic = %require_complete (constants.%require_complete.12d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%v.param: @FeedTame.%V.binding.as_type (%V.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @HandleTameAnimal(%W.loc9_21.2: %facet_type.206) {\n// CHECK:STDOUT:   %W.loc9_21.1: %facet_type.206 = symbolic_binding W, 0 [symbolic = %W.loc9_21.1 (constants.%W)]\n// CHECK:STDOUT:   %W.binding.as_type: type = symbolic_binding_type W, 0, %W.loc9_21.1 [symbolic = %W.binding.as_type (constants.%W.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %W.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.e8e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %W.binding.as_type [symbolic = %require_complete (constants.%require_complete.817)]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %W.loc9_21.1, @Eats [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]\n// CHECK:STDOUT:   %Tame.lookup_impl_witness: <witness> = lookup_impl_witness %W.loc9_21.1, @Tame [symbolic = %Tame.lookup_impl_witness (constants.%Tame.lookup_impl_witness)]\n// CHECK:STDOUT:   %facet_value.loc10_13.2: %facet_type.2db = facet_value %W.binding.as_type, (%Eats.lookup_impl_witness, %Tame.lookup_impl_witness) [symbolic = %facet_value.loc10_13.2 (constants.%facet_value)]\n// CHECK:STDOUT:   %FeedTame.specific_fn.loc10_3.2: <specific function> = specific_function constants.%FeedTame, @FeedTame(%facet_value.loc10_13.2) [symbolic = %FeedTame.specific_fn.loc10_3.2 (constants.%FeedTame.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%w.param: @HandleTameAnimal.%W.binding.as_type (%W.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %FeedTame.ref: %FeedTame.type = name_ref FeedTame, file.%FeedTame.decl [concrete = constants.%FeedTame]\n// CHECK:STDOUT:     %w.ref: @HandleTameAnimal.%W.binding.as_type (%W.binding.as_type) = name_ref w, %w\n// CHECK:STDOUT:     %facet_value.loc10_13.1: %facet_type.2db = facet_value constants.%W.binding.as_type, (constants.%Eats.lookup_impl_witness, constants.%Tame.lookup_impl_witness) [symbolic = %facet_value.loc10_13.2 (constants.%facet_value)]\n// CHECK:STDOUT:     %.loc10: %facet_type.2db = converted constants.%W.binding.as_type, %facet_value.loc10_13.1 [symbolic = %facet_value.loc10_13.2 (constants.%facet_value)]\n// CHECK:STDOUT:     %FeedTame.specific_fn.loc10_3.1: <specific function> = specific_function %FeedTame.ref, @FeedTame(constants.%facet_value) [symbolic = %FeedTame.specific_fn.loc10_3.2 (constants.%FeedTame.specific_fn)]\n// CHECK:STDOUT:     %FeedTame.call: init %empty_tuple.type = call %FeedTame.specific_fn.loc10_3.1(%w.ref)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Self.247) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self.c49) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Tame.WithSelf(constants.%Self.ab8) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @FeedTame(constants.%V) {\n// CHECK:STDOUT:   %V.loc7_13.1 => constants.%V\n// CHECK:STDOUT:   %V.binding.as_type => constants.%V.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.795\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleTameAnimal(constants.%W) {\n// CHECK:STDOUT:   %W.loc9_21.1 => constants.%W\n// CHECK:STDOUT:   %W.binding.as_type => constants.%W.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.e8e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @FeedTame(constants.%facet_value) {\n// CHECK:STDOUT:   %V.loc7_13.1 => constants.%facet_value\n// CHECK:STDOUT:   %V.binding.as_type => constants.%W.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.e8e\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.817\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- with_blanket.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats> [concrete]\n// CHECK:STDOUT:   %Self.247: %Eats.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self.c49: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Tame.type: type = facet_type <@Tame> [concrete]\n// CHECK:STDOUT:   %Self.ab8: %Tame.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.e10: type = pattern_type %Animal.type [concrete]\n// CHECK:STDOUT:   %A: %Animal.type = symbolic_binding A, 0 [symbolic]\n// CHECK:STDOUT:   %A.binding.as_type: type = symbolic_binding_type A, 0, %A [symbolic]\n// CHECK:STDOUT:   %Eats.impl_witness.760: <witness> = impl_witness @A.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(%A) [symbolic]\n// CHECK:STDOUT:   %Eats.facet: %Eats.type = facet_value %A.binding.as_type, (%Eats.impl_witness.760) [symbolic]\n// CHECK:STDOUT:   %BitAndWith.type.f2e: type = generic_interface_type @BitAndWith [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %BitAndWith.generic: %BitAndWith.type.f2e = struct_value () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.b10: type = facet_type <@BitAndWith, @BitAndWith(type)> [concrete]\n// CHECK:STDOUT:   %BitAndWith.impl_witness: <witness> = impl_witness imports.%BitAndWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %BitAndWith.facet: %BitAndWith.type.b10 = facet_value type, (%BitAndWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %BitAndWith.WithSelf.Op.type.4bd: type = fn_type @BitAndWith.WithSelf.Op, @BitAndWith.WithSelf(type, %BitAndWith.facet) [concrete]\n// CHECK:STDOUT:   %.d15: type = fn_type_with_self_type %BitAndWith.WithSelf.Op.type.4bd, %BitAndWith.facet [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.type: type = fn_type @type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op: %type.as.BitAndWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound.a5f: <bound method> = bound_method %Tame.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type.2db: type = facet_type <@Eats & @Tame> [concrete]\n// CHECK:STDOUT:   %pattern_type.fa7: type = pattern_type %facet_type.2db [concrete]\n// CHECK:STDOUT:   %V: %facet_type.2db = symbolic_binding V, 0 [symbolic]\n// CHECK:STDOUT:   %V.binding.as_type: type = symbolic_binding_type V, 0, %V [symbolic]\n// CHECK:STDOUT:   %pattern_type.795: type = pattern_type %V.binding.as_type [symbolic]\n// CHECK:STDOUT:   %FeedTame2.type: type = fn_type @FeedTame2 [concrete]\n// CHECK:STDOUT:   %FeedTame2: %FeedTame2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.12d: <witness> = require_complete_type %V.binding.as_type [symbolic]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound.92c: <bound method> = bound_method %Animal.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type.afc: type = facet_type <@Animal & @Tame> [concrete]\n// CHECK:STDOUT:   %pattern_type.310: type = pattern_type %facet_type.afc [concrete]\n// CHECK:STDOUT:   %W: %facet_type.afc = symbolic_binding W, 0 [symbolic]\n// CHECK:STDOUT:   %W.binding.as_type: type = symbolic_binding_type W, 0, %W [symbolic]\n// CHECK:STDOUT:   %pattern_type.da7: type = pattern_type %W.binding.as_type [symbolic]\n// CHECK:STDOUT:   %HandleTameAnimal2.type: type = fn_type @HandleTameAnimal2 [concrete]\n// CHECK:STDOUT:   %HandleTameAnimal2: %HandleTameAnimal2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.80f: <witness> = require_complete_type %W.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Animal.lookup_impl_witness: <witness> = lookup_impl_witness %W, @Animal [symbolic]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %W.binding.as_type, (%Animal.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Eats.impl_witness.8ab: <witness> = impl_witness @A.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(%Animal.facet) [symbolic]\n// CHECK:STDOUT:   %.3cf: require_specific_def_type = require_specific_def @A.binding.as_type.as.Eats.impl(%Animal.facet) [symbolic]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %W, @Eats [symbolic]\n// CHECK:STDOUT:   %Tame.lookup_impl_witness: <witness> = lookup_impl_witness %W, @Tame [symbolic]\n// CHECK:STDOUT:   %facet_value: %facet_type.2db = facet_value %W.binding.as_type, (%Eats.lookup_impl_witness, %Tame.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %FeedTame2.specific_fn: <specific function> = specific_function %FeedTame2, @FeedTame2(%facet_value) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .BitAndWith = %Core.BitAndWith\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.BitAndWith: %BitAndWith.type.f2e = import_ref Core//prelude/parts/as, BitAndWith, loaded [concrete = constants.%BitAndWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.8d3: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:   %BitAndWith.impl_witness_table = impl_witness_table (%Core.import_ref.8d3), @type.as.BitAndWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Eats = %Eats.decl\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .Tame = %Tame.decl\n// CHECK:STDOUT:     .FeedTame2 = %FeedTame2.decl\n// CHECK:STDOUT:     .HandleTameAnimal2 = %HandleTameAnimal2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Eats.decl: type = interface_decl @Eats [concrete = constants.%Eats.type] {} {}\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   %Tame.decl: type = interface_decl @Tame [concrete = constants.%Tame.type] {} {}\n// CHECK:STDOUT:   impl_decl @A.binding.as_type.as.Eats.impl [concrete] {\n// CHECK:STDOUT:     %A.patt: %pattern_type.e10 = symbolic_binding_pattern A, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %A.ref: %Animal.type = name_ref A, %A.loc7_14.1 [symbolic = %A.loc7_14.2 (constants.%A)]\n// CHECK:STDOUT:     %A.as_type: type = facet_access_type %A.ref [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:     %.loc7_26: type = converted %A.ref, %A.as_type [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:     %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:     %.loc7_18: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %A.loc7_14.1: %Animal.type = symbolic_binding A, 0 [symbolic = %A.loc7_14.2 (constants.%A)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %FeedTame2.decl: %FeedTame2.type = fn_decl @FeedTame2 [concrete = constants.%FeedTame2] {\n// CHECK:STDOUT:     %V.patt: %pattern_type.fa7 = symbolic_binding_pattern V, 0 [concrete]\n// CHECK:STDOUT:     %v.patt: @FeedTame2.%pattern_type (%pattern_type.795) = value_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.param_patt: @FeedTame2.%pattern_type (%pattern_type.795) = value_param_pattern %v.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_23.1: type = splice_block %.loc9_23.3 [concrete = constants.%facet_type.2db] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Tame.ref: type = name_ref Tame, file.%Tame.decl [concrete = constants.%Tame.type]\n// CHECK:STDOUT:       %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:       %impl.elem0: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method: <bound method> = bound_method %Tame.ref, %impl.elem0 [concrete = constants.%type.as.BitAndWith.impl.Op.bound.a5f]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call: init type = call %bound_method(%Tame.ref, %Eats.ref) [concrete = constants.%facet_type.2db]\n// CHECK:STDOUT:       %.loc9_23.2: type = value_of_initializer %type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type.2db]\n// CHECK:STDOUT:       %.loc9_23.3: type = converted %type.as.BitAndWith.impl.Op.call, %.loc9_23.2 [concrete = constants.%facet_type.2db]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %V.loc9_14.2: %facet_type.2db = symbolic_binding V, 0 [symbolic = %V.loc9_14.1 (constants.%V)]\n// CHECK:STDOUT:     %v.param: @FeedTame2.%V.binding.as_type (%V.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc9_41.1: type = splice_block %.loc9_41.2 [symbolic = %V.binding.as_type (constants.%V.binding.as_type)] {\n// CHECK:STDOUT:       %V.ref: %facet_type.2db = name_ref V, %V.loc9_14.2 [symbolic = %V.loc9_14.1 (constants.%V)]\n// CHECK:STDOUT:       %V.as_type: type = facet_access_type %V.ref [symbolic = %V.binding.as_type (constants.%V.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_41.2: type = converted %V.ref, %V.as_type [symbolic = %V.binding.as_type (constants.%V.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v: @FeedTame2.%V.binding.as_type (%V.binding.as_type) = value_binding v, %v.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %HandleTameAnimal2.decl: %HandleTameAnimal2.type = fn_decl @HandleTameAnimal2 [concrete = constants.%HandleTameAnimal2] {\n// CHECK:STDOUT:     %W.patt: %pattern_type.310 = symbolic_binding_pattern W, 0 [concrete]\n// CHECK:STDOUT:     %w.patt: @HandleTameAnimal2.%pattern_type (%pattern_type.da7) = value_binding_pattern w [concrete]\n// CHECK:STDOUT:     %w.param_patt: @HandleTameAnimal2.%pattern_type (%pattern_type.da7) = value_param_pattern %w.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc11_33.1: type = splice_block %.loc11_33.3 [concrete = constants.%facet_type.afc] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:       %Tame.ref: type = name_ref Tame, file.%Tame.decl [concrete = constants.%Tame.type]\n// CHECK:STDOUT:       %impl.elem0: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method: <bound method> = bound_method %Animal.ref, %impl.elem0 [concrete = constants.%type.as.BitAndWith.impl.Op.bound.92c]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call: init type = call %bound_method(%Animal.ref, %Tame.ref) [concrete = constants.%facet_type.afc]\n// CHECK:STDOUT:       %.loc11_33.2: type = value_of_initializer %type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type.afc]\n// CHECK:STDOUT:       %.loc11_33.3: type = converted %type.as.BitAndWith.impl.Op.call, %.loc11_33.2 [concrete = constants.%facet_type.afc]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %W.loc11_22.2: %facet_type.afc = symbolic_binding W, 0 [symbolic = %W.loc11_22.1 (constants.%W)]\n// CHECK:STDOUT:     %w.param: @HandleTameAnimal2.%W.binding.as_type (%W.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc11_44.1: type = splice_block %.loc11_44.2 [symbolic = %W.binding.as_type (constants.%W.binding.as_type)] {\n// CHECK:STDOUT:       %W.ref: %facet_type.afc = name_ref W, %W.loc11_22.2 [symbolic = %W.loc11_22.1 (constants.%W)]\n// CHECK:STDOUT:       %W.as_type: type = facet_access_type %W.ref [symbolic = %W.binding.as_type (constants.%W.binding.as_type)]\n// CHECK:STDOUT:       %.loc11_44.2: type = converted %W.ref, %W.as_type [symbolic = %W.binding.as_type (constants.%W.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %w: @HandleTameAnimal2.%W.binding.as_type (%W.binding.as_type) = value_binding w, %w.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Eats {\n// CHECK:STDOUT:   %Self: %Eats.type = symbolic_binding Self, 0 [symbolic = constants.%Self.247]\n// CHECK:STDOUT:   %Eats.WithSelf.decl = interface_with_self_decl @Eats [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c49]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Tame {\n// CHECK:STDOUT:   %Self: %Tame.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab8]\n// CHECK:STDOUT:   %Tame.WithSelf.decl = interface_with_self_decl @Tame [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @A.binding.as_type.as.Eats.impl(%A.loc7_14.1: %Animal.type) {\n// CHECK:STDOUT:   %A.loc7_14.2: %Animal.type = symbolic_binding A, 0 [symbolic = %A.loc7_14.2 (constants.%A)]\n// CHECK:STDOUT:   %A.binding.as_type: type = symbolic_binding_type A, 0, %A.loc7_14.2 [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:   %Eats.impl_witness.loc7_36.2: <witness> = impl_witness %Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(%A.loc7_14.2) [symbolic = %Eats.impl_witness.loc7_36.2 (constants.%Eats.impl_witness.760)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc7_26 as %Eats.ref {\n// CHECK:STDOUT:     %Eats.impl_witness_table = impl_witness_table (), @A.binding.as_type.as.Eats.impl [concrete]\n// CHECK:STDOUT:     %Eats.impl_witness.loc7_36.1: <witness> = impl_witness %Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(constants.%A) [symbolic = %Eats.impl_witness.loc7_36.2 (constants.%Eats.impl_witness.760)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Eats.impl_witness.loc7_36.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @FeedTame2(%V.loc9_14.2: %facet_type.2db) {\n// CHECK:STDOUT:   %V.loc9_14.1: %facet_type.2db = symbolic_binding V, 0 [symbolic = %V.loc9_14.1 (constants.%V)]\n// CHECK:STDOUT:   %V.binding.as_type: type = symbolic_binding_type V, 0, %V.loc9_14.1 [symbolic = %V.binding.as_type (constants.%V.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %V.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.795)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %V.binding.as_type [symbolic = %require_complete (constants.%require_complete.12d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%v.param: @FeedTame2.%V.binding.as_type (%V.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @HandleTameAnimal2(%W.loc11_22.2: %facet_type.afc) {\n// CHECK:STDOUT:   %W.loc11_22.1: %facet_type.afc = symbolic_binding W, 0 [symbolic = %W.loc11_22.1 (constants.%W)]\n// CHECK:STDOUT:   %W.binding.as_type: type = symbolic_binding_type W, 0, %W.loc11_22.1 [symbolic = %W.binding.as_type (constants.%W.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %W.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.da7)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %W.binding.as_type [symbolic = %require_complete (constants.%require_complete.80f)]\n// CHECK:STDOUT:   %Animal.lookup_impl_witness: <witness> = lookup_impl_witness %W.loc11_22.1, @Animal [symbolic = %Animal.lookup_impl_witness (constants.%Animal.lookup_impl_witness)]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %W.binding.as_type, (%Animal.lookup_impl_witness) [symbolic = %Animal.facet (constants.%Animal.facet)]\n// CHECK:STDOUT:   %.loc12_14.2: require_specific_def_type = require_specific_def @A.binding.as_type.as.Eats.impl(%Animal.facet) [symbolic = %.loc12_14.2 (constants.%.3cf)]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %W.loc11_22.1, @Eats [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]\n// CHECK:STDOUT:   %Tame.lookup_impl_witness: <witness> = lookup_impl_witness %W.loc11_22.1, @Tame [symbolic = %Tame.lookup_impl_witness (constants.%Tame.lookup_impl_witness)]\n// CHECK:STDOUT:   %facet_value.loc12_14.2: %facet_type.2db = facet_value %W.binding.as_type, (%Eats.lookup_impl_witness, %Tame.lookup_impl_witness) [symbolic = %facet_value.loc12_14.2 (constants.%facet_value)]\n// CHECK:STDOUT:   %FeedTame2.specific_fn.loc12_3.2: <specific function> = specific_function constants.%FeedTame2, @FeedTame2(%facet_value.loc12_14.2) [symbolic = %FeedTame2.specific_fn.loc12_3.2 (constants.%FeedTame2.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%w.param: @HandleTameAnimal2.%W.binding.as_type (%W.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %FeedTame2.ref: %FeedTame2.type = name_ref FeedTame2, file.%FeedTame2.decl [concrete = constants.%FeedTame2]\n// CHECK:STDOUT:     %w.ref: @HandleTameAnimal2.%W.binding.as_type (%W.binding.as_type) = name_ref w, %w\n// CHECK:STDOUT:     %facet_value.loc12_14.1: %facet_type.2db = facet_value constants.%W.binding.as_type, (constants.%Eats.lookup_impl_witness, constants.%Tame.lookup_impl_witness) [symbolic = %facet_value.loc12_14.2 (constants.%facet_value)]\n// CHECK:STDOUT:     %.loc12_14.1: %facet_type.2db = converted constants.%W.binding.as_type, %facet_value.loc12_14.1 [symbolic = %facet_value.loc12_14.2 (constants.%facet_value)]\n// CHECK:STDOUT:     %FeedTame2.specific_fn.loc12_3.1: <specific function> = specific_function %FeedTame2.ref, @FeedTame2(constants.%facet_value) [symbolic = %FeedTame2.specific_fn.loc12_3.2 (constants.%FeedTame2.specific_fn)]\n// CHECK:STDOUT:     %FeedTame2.call: init %empty_tuple.type = call %FeedTame2.specific_fn.loc12_3.1(%w.ref)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Self.247) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self.c49) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Tame.WithSelf(constants.%Self.ab8) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.binding.as_type.as.Eats.impl(constants.%A) {\n// CHECK:STDOUT:   %A.loc7_14.2 => constants.%A\n// CHECK:STDOUT:   %A.binding.as_type => constants.%A.binding.as_type\n// CHECK:STDOUT:   %Eats.impl_witness.loc7_36.2 => constants.%Eats.impl_witness.760\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Eats.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @FeedTame2(constants.%V) {\n// CHECK:STDOUT:   %V.loc9_14.1 => constants.%V\n// CHECK:STDOUT:   %V.binding.as_type => constants.%V.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.795\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleTameAnimal2(constants.%W) {\n// CHECK:STDOUT:   %W.loc11_22.1 => constants.%W\n// CHECK:STDOUT:   %W.binding.as_type => constants.%W.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.da7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.binding.as_type.as.Eats.impl(constants.%Animal.facet) {\n// CHECK:STDOUT:   %A.loc7_14.2 => constants.%Animal.facet\n// CHECK:STDOUT:   %A.binding.as_type => constants.%W.binding.as_type\n// CHECK:STDOUT:   %Eats.impl_witness.loc7_36.2 => constants.%Eats.impl_witness.8ab\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @FeedTame2(constants.%facet_value) {\n// CHECK:STDOUT:   %V.loc9_14.1 => constants.%facet_value\n// CHECK:STDOUT:   %V.binding.as_type => constants.%W.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.da7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.80f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- equivalent.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]\n// CHECK:STDOUT:   %Self: %A.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.faf: type = pattern_type %A.type [concrete]\n// CHECK:STDOUT:   %T: %A.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.057cf4.1: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %TakesA.type: type = fn_type @TakesA [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %TakesA: %TakesA.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.1a7376.1: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.Self.091: %A.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.091 [symbolic_self]\n// CHECK:STDOUT:   %U: %A.type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U [symbolic]\n// CHECK:STDOUT:   %pattern_type.057cf4.2: type = pattern_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %WithExtraWhere.type: type = fn_type @WithExtraWhere [concrete]\n// CHECK:STDOUT:   %WithExtraWhere: %WithExtraWhere.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.1a7376.2: <witness> = require_complete_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %TakesA.specific_fn: <specific function> = specific_function %TakesA, @TakesA(%U) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .TakesA = %TakesA.decl\n// CHECK:STDOUT:     .WithExtraWhere = %WithExtraWhere.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = interface_decl @A [concrete = constants.%A.type] {} {}\n// CHECK:STDOUT:   %TakesA.decl: %TakesA.type = fn_decl @TakesA [concrete = constants.%TakesA] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.faf = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @TakesA.%pattern_type (%pattern_type.057cf4.1) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @TakesA.%pattern_type (%pattern_type.057cf4.1) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_15: type = splice_block %A.ref [concrete = constants.%A.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_11.2: %A.type = symbolic_binding T, 0 [symbolic = %T.loc7_11.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @TakesA.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc7_28.1: type = splice_block %.loc7_28.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref: %A.type = name_ref T, %T.loc7_11.2 [symbolic = %T.loc7_11.1 (constants.%T)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc7_28.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @TakesA.%T.binding.as_type (%T.binding.as_type) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %WithExtraWhere.decl: %WithExtraWhere.type = fn_decl @WithExtraWhere [concrete = constants.%WithExtraWhere] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.faf = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %y.patt: @WithExtraWhere.%pattern_type (%pattern_type.057cf4.2) = value_binding_pattern y [concrete]\n// CHECK:STDOUT:     %y.param_patt: @WithExtraWhere.%pattern_type (%pattern_type.057cf4.2) = value_param_pattern %y.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_25.1: type = splice_block %.loc9_25.2 [concrete = constants.%A.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]\n// CHECK:STDOUT:       %.Self.2: %A.type = symbolic_binding .Self [symbolic_self = constants.%.Self.091]\n// CHECK:STDOUT:       %.Self.ref: %A.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.091]\n// CHECK:STDOUT:       %.loc9_43: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc9_31: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc9_25.2: type = where_expr %.Self.2 [concrete = constants.%A.type] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%A.type\n// CHECK:STDOUT:         requirement_impls %.loc9_31, %.loc9_43\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc9_19.2: %A.type = symbolic_binding U, 0 [symbolic = %U.loc9_19.1 (constants.%U)]\n// CHECK:STDOUT:     %y.param: @WithExtraWhere.%U.binding.as_type (%U.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc9_52.1: type = splice_block %.loc9_52.2 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)] {\n// CHECK:STDOUT:       %U.ref: %A.type = name_ref U, %U.loc9_19.2 [symbolic = %U.loc9_19.1 (constants.%U)]\n// CHECK:STDOUT:       %U.as_type: type = facet_access_type %U.ref [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_52.2: type = converted %U.ref, %U.as_type [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %y: @WithExtraWhere.%U.binding.as_type (%U.binding.as_type) = value_binding y, %y.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @A {\n// CHECK:STDOUT:   %Self: %A.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %A.WithSelf.decl = interface_with_self_decl @A [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @TakesA(%T.loc7_11.2: %A.type) {\n// CHECK:STDOUT:   %T.loc7_11.1: %A.type = symbolic_binding T, 0 [symbolic = %T.loc7_11.1 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc7_11.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.057cf4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.1a7376.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @TakesA.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @WithExtraWhere(%U.loc9_19.2: %A.type) {\n// CHECK:STDOUT:   %U.loc9_19.1: %A.type = symbolic_binding U, 0 [symbolic = %U.loc9_19.1 (constants.%U)]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U.loc9_19.1 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %U.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.057cf4.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %U.binding.as_type [symbolic = %require_complete (constants.%require_complete.1a7376.2)]\n// CHECK:STDOUT:   %TakesA.specific_fn.loc10_3.2: <specific function> = specific_function constants.%TakesA, @TakesA(%U.loc9_19.1) [symbolic = %TakesA.specific_fn.loc10_3.2 (constants.%TakesA.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%y.param: @WithExtraWhere.%U.binding.as_type (%U.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %TakesA.ref: %TakesA.type = name_ref TakesA, file.%TakesA.decl [concrete = constants.%TakesA]\n// CHECK:STDOUT:     %y.ref: @WithExtraWhere.%U.binding.as_type (%U.binding.as_type) = name_ref y, %y\n// CHECK:STDOUT:     %.loc10: %A.type = converted constants.%U.binding.as_type, constants.%U [symbolic = %U.loc9_19.1 (constants.%U)]\n// CHECK:STDOUT:     %TakesA.specific_fn.loc10_3.1: <specific function> = specific_function %TakesA.ref, @TakesA(constants.%U) [symbolic = %TakesA.specific_fn.loc10_3.2 (constants.%TakesA.specific_fn)]\n// CHECK:STDOUT:     %TakesA.call: init %empty_tuple.type = call %TakesA.specific_fn.loc10_3.1(%y.ref)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesA(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_11.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.057cf4.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WithExtraWhere(constants.%U) {\n// CHECK:STDOUT:   %U.loc9_19.1 => constants.%U\n// CHECK:STDOUT:   %U.binding.as_type => constants.%U.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.057cf4.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesA(constants.%U) {\n// CHECK:STDOUT:   %T.loc7_11.1 => constants.%U\n// CHECK:STDOUT:   %T.binding.as_type => constants.%U.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.057cf4.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.1a7376.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- no_interfaces_success.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67db0b.1: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T.67db0b.1 [symbolic]\n// CHECK:STDOUT:   %TakesTypeDeduced.type: type = fn_type @TakesTypeDeduced [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %TakesTypeDeduced: %TakesTypeDeduced.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67db0b.1 [symbolic]\n// CHECK:STDOUT:   %.Self.16f: type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.9a5: type = pattern_type %type [concrete]\n// CHECK:STDOUT:   %U: %type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U [symbolic]\n// CHECK:STDOUT:   %pattern_type.349: type = pattern_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %CallsWithExtraWhere.type: type = fn_type @CallsWithExtraWhere [concrete]\n// CHECK:STDOUT:   %CallsWithExtraWhere: %CallsWithExtraWhere.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.d55: <witness> = require_complete_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %TakesTypeDeduced.specific_fn: <specific function> = specific_function %TakesTypeDeduced, @TakesTypeDeduced(%U.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %T.67db0b.2: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %TakesTypeExplicit.type: type = fn_type @TakesTypeExplicit [concrete]\n// CHECK:STDOUT:   %TakesTypeExplicit: %TakesTypeExplicit.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallsWithExtraWhereExplicit.type: type = fn_type @CallsWithExtraWhereExplicit [concrete]\n// CHECK:STDOUT:   %CallsWithExtraWhereExplicit: %CallsWithExtraWhereExplicit.type = struct_value () [concrete]\n// CHECK:STDOUT:   %TakesTypeExplicit.specific_fn: <specific function> = specific_function %TakesTypeExplicit, @TakesTypeExplicit(%U.binding.as_type) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .TakesTypeDeduced = %TakesTypeDeduced.decl\n// CHECK:STDOUT:     .CallsWithExtraWhere = %CallsWithExtraWhere.decl\n// CHECK:STDOUT:     .TakesTypeExplicit = %TakesTypeExplicit.decl\n// CHECK:STDOUT:     .CallsWithExtraWhereExplicit = %CallsWithExtraWhereExplicit.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %TakesTypeDeduced.decl: %TakesTypeDeduced.type = fn_decl @TakesTypeDeduced [concrete = constants.%TakesTypeDeduced] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @TakesTypeDeduced.%pattern_type (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @TakesTypeDeduced.%pattern_type (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc3_25.1: type = splice_block %.loc3_25.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc3_25.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc3_21.2: type = symbolic_binding T, 0 [symbolic = %T.loc3_21.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x.param: @TakesTypeDeduced.%T.loc3_21.1 (%T.67db0b.1) = value_param call_param0\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc3_21.2 [symbolic = %T.loc3_21.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x: @TakesTypeDeduced.%T.loc3_21.1 (%T.67db0b.1) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallsWithExtraWhere.decl: %CallsWithExtraWhere.type = fn_decl @CallsWithExtraWhere [concrete = constants.%CallsWithExtraWhere] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.9a5 = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %y.patt: @CallsWithExtraWhere.%pattern_type (%pattern_type.349) = value_binding_pattern y [concrete]\n// CHECK:STDOUT:     %y.param_patt: @CallsWithExtraWhere.%pattern_type (%pattern_type.349) = value_param_pattern %y.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_33.1: type = splice_block %.loc4_33.2 [concrete = constants.%type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc4_28: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.Self.2: type = symbolic_binding .Self [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %.Self.ref: type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %.loc4_51: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.loc4_33.2: type = where_expr %.Self.2 [concrete = constants.%type] {\n// CHECK:STDOUT:         requirement_base_facet_type type\n// CHECK:STDOUT:         requirement_impls %.Self.ref, %.loc4_51\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc4_24.2: %type = symbolic_binding U, 0 [symbolic = %U.loc4_24.1 (constants.%U)]\n// CHECK:STDOUT:     %y.param: @CallsWithExtraWhere.%U.binding.as_type (%U.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_60.1: type = splice_block %.loc4_60.2 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)] {\n// CHECK:STDOUT:       %U.ref: %type = name_ref U, %U.loc4_24.2 [symbolic = %U.loc4_24.1 (constants.%U)]\n// CHECK:STDOUT:       %U.as_type: type = facet_access_type %U.ref [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:       %.loc4_60.2: type = converted %U.ref, %U.as_type [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %y: @CallsWithExtraWhere.%U.binding.as_type (%U.binding.as_type) = value_binding y, %y.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %TakesTypeExplicit.decl: %TakesTypeExplicit.type = fn_decl @TakesTypeExplicit [concrete = constants.%TakesTypeExplicit] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_33.1: type = splice_block %.loc8_33.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc8_33.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_29.3: type = symbolic_binding T, 0 [symbolic = %T.loc8_29.2 (constants.%T.67db0b.2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallsWithExtraWhereExplicit.decl: %CallsWithExtraWhereExplicit.type = fn_decl @CallsWithExtraWhereExplicit [concrete = constants.%CallsWithExtraWhereExplicit] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.9a5 = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_41.1: type = splice_block %.loc9_41.2 [concrete = constants.%type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc9_36: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.Self.2: type = symbolic_binding .Self [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %.Self.ref: type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %.loc9_59: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.loc9_41.2: type = where_expr %.Self.2 [concrete = constants.%type] {\n// CHECK:STDOUT:         requirement_base_facet_type type\n// CHECK:STDOUT:         requirement_impls %.Self.ref, %.loc9_59\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc9_32.2: %type = symbolic_binding U, 0 [symbolic = %U.loc9_32.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @TakesTypeDeduced(%T.loc3_21.2: type) {\n// CHECK:STDOUT:   %T.loc3_21.1: type = symbolic_binding T, 0 [symbolic = %T.loc3_21.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc3_21.1 [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc3_21.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @TakesTypeDeduced.%T.loc3_21.1 (%T.67db0b.1)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallsWithExtraWhere(%U.loc4_24.2: %type) {\n// CHECK:STDOUT:   %U.loc4_24.1: %type = symbolic_binding U, 0 [symbolic = %U.loc4_24.1 (constants.%U)]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U.loc4_24.1 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %U.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.349)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %U.binding.as_type [symbolic = %require_complete (constants.%require_complete.d55)]\n// CHECK:STDOUT:   %TakesTypeDeduced.specific_fn.loc5_3.2: <specific function> = specific_function constants.%TakesTypeDeduced, @TakesTypeDeduced(%U.binding.as_type) [symbolic = %TakesTypeDeduced.specific_fn.loc5_3.2 (constants.%TakesTypeDeduced.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%y.param: @CallsWithExtraWhere.%U.binding.as_type (%U.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %TakesTypeDeduced.ref: %TakesTypeDeduced.type = name_ref TakesTypeDeduced, file.%TakesTypeDeduced.decl [concrete = constants.%TakesTypeDeduced]\n// CHECK:STDOUT:     %y.ref: @CallsWithExtraWhere.%U.binding.as_type (%U.binding.as_type) = name_ref y, %y\n// CHECK:STDOUT:     %TakesTypeDeduced.specific_fn.loc5_3.1: <specific function> = specific_function %TakesTypeDeduced.ref, @TakesTypeDeduced(constants.%U.binding.as_type) [symbolic = %TakesTypeDeduced.specific_fn.loc5_3.2 (constants.%TakesTypeDeduced.specific_fn)]\n// CHECK:STDOUT:     %TakesTypeDeduced.call: init %empty_tuple.type = call %TakesTypeDeduced.specific_fn.loc5_3.1(%y.ref)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @TakesTypeExplicit(%T.loc8_29.3: type) {\n// CHECK:STDOUT:   %T.loc8_29.1: type = symbolic_binding T, 0 [symbolic = %T.loc8_29.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   %T.loc8_29.2: type = symbolic_binding T, 0 [symbolic = %T.loc8_29.2 (constants.%T.67db0b.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallsWithExtraWhereExplicit(%U.loc9_32.2: %type) {\n// CHECK:STDOUT:   %U.loc9_32.1: %type = symbolic_binding U, 0 [symbolic = %U.loc9_32.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U.loc9_32.1 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:   %TakesTypeExplicit.specific_fn.loc10_3.2: <specific function> = specific_function constants.%TakesTypeExplicit, @TakesTypeExplicit(%U.binding.as_type) [symbolic = %TakesTypeExplicit.specific_fn.loc10_3.2 (constants.%TakesTypeExplicit.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %TakesTypeExplicit.ref: %TakesTypeExplicit.type = name_ref TakesTypeExplicit, file.%TakesTypeExplicit.decl [concrete = constants.%TakesTypeExplicit]\n// CHECK:STDOUT:     %U.ref: %type = name_ref U, %U.loc9_32.2 [symbolic = %U.loc9_32.1 (constants.%U)]\n// CHECK:STDOUT:     %U.as_type: type = facet_access_type %U.ref [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     %.loc10: type = converted %U.ref, %U.as_type [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     %TakesTypeExplicit.specific_fn.loc10_3.1: <specific function> = specific_function %TakesTypeExplicit.ref, @TakesTypeExplicit(constants.%U.binding.as_type) [symbolic = %TakesTypeExplicit.specific_fn.loc10_3.2 (constants.%TakesTypeExplicit.specific_fn)]\n// CHECK:STDOUT:     %TakesTypeExplicit.call: init %empty_tuple.type = call %TakesTypeExplicit.specific_fn.loc10_3.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesTypeDeduced(constants.%T.67db0b.1) {\n// CHECK:STDOUT:   %T.loc3_21.1 => constants.%T.67db0b.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallsWithExtraWhere(constants.%U) {\n// CHECK:STDOUT:   %U.loc4_24.1 => constants.%U\n// CHECK:STDOUT:   %U.binding.as_type => constants.%U.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.349\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesTypeDeduced(constants.%U.binding.as_type) {\n// CHECK:STDOUT:   %T.loc3_21.1 => constants.%U.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.349\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.d55\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesTypeExplicit(constants.%T.67db0b.2) {\n// CHECK:STDOUT:   %T.loc8_29.1 => constants.%T.67db0b.2\n// CHECK:STDOUT:   %T.loc8_29.2 => constants.%T.67db0b.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallsWithExtraWhereExplicit(constants.%U) {\n// CHECK:STDOUT:   %U.loc9_32.1 => constants.%U\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesTypeExplicit(constants.%U.binding.as_type) {\n// CHECK:STDOUT:   %T.loc8_29.1 => constants.%U.binding.as_type\n// CHECK:STDOUT:   %T.loc8_29.2 => constants.%U.binding.as_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- no_interfaces.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.16f: type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.9a5: type = pattern_type %type [concrete]\n// CHECK:STDOUT:   %T.f45530.1: %type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.f45530.1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.349: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %TakesExtraWhereDeduced.type: type = fn_type @TakesExtraWhereDeduced [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %TakesExtraWhereDeduced: %TakesExtraWhereDeduced.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.d55: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %U [symbolic]\n// CHECK:STDOUT:   %CallsWithType.type: type = fn_type @CallsWithType [concrete]\n// CHECK:STDOUT:   %CallsWithType: %CallsWithType.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %U [symbolic]\n// CHECK:STDOUT:   %facet_value: %type = facet_value %U, () [symbolic]\n// CHECK:STDOUT:   %TakesExtraWhereDeduced.specific_fn: <specific function> = specific_function %TakesExtraWhereDeduced, @TakesExtraWhereDeduced(%facet_value) [symbolic]\n// CHECK:STDOUT:   %T.f45530.2: %type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %TakesExtraWhereExplicit.type: type = fn_type @TakesExtraWhereExplicit [concrete]\n// CHECK:STDOUT:   %TakesExtraWhereExplicit: %TakesExtraWhereExplicit.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallsWithTypeExplicit.type: type = fn_type @CallsWithTypeExplicit [concrete]\n// CHECK:STDOUT:   %CallsWithTypeExplicit: %CallsWithTypeExplicit.type = struct_value () [concrete]\n// CHECK:STDOUT:   %TakesExtraWhereExplicit.specific_fn: <specific function> = specific_function %TakesExtraWhereExplicit, @TakesExtraWhereExplicit(%facet_value) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .TakesExtraWhereDeduced = %TakesExtraWhereDeduced.decl\n// CHECK:STDOUT:     .CallsWithType = %CallsWithType.decl\n// CHECK:STDOUT:     .TakesExtraWhereExplicit = %TakesExtraWhereExplicit.decl\n// CHECK:STDOUT:     .CallsWithTypeExplicit = %CallsWithTypeExplicit.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %TakesExtraWhereDeduced.decl: %TakesExtraWhereDeduced.type = fn_decl @TakesExtraWhereDeduced [concrete = constants.%TakesExtraWhereDeduced] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.9a5 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @TakesExtraWhereDeduced.%pattern_type (%pattern_type.349) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @TakesExtraWhereDeduced.%pattern_type (%pattern_type.349) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc3_36.1: type = splice_block %.loc3_36.2 [concrete = constants.%type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc3_31: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.Self.2: type = symbolic_binding .Self [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %.Self.ref: type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %.loc3_54: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.loc3_36.2: type = where_expr %.Self.2 [concrete = constants.%type] {\n// CHECK:STDOUT:         requirement_base_facet_type type\n// CHECK:STDOUT:         requirement_impls %.Self.ref, %.loc3_54\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc3_27.2: %type = symbolic_binding T, 0 [symbolic = %T.loc3_27.1 (constants.%T.f45530.1)]\n// CHECK:STDOUT:     %x.param: @TakesExtraWhereDeduced.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc3_70.1: type = splice_block %.loc3_70.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref: %type = name_ref T, %T.loc3_27.2 [symbolic = %T.loc3_27.1 (constants.%T.f45530.1)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc3_70.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @TakesExtraWhereDeduced.%T.binding.as_type (%T.binding.as_type) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallsWithType.decl: %CallsWithType.type = fn_decl @CallsWithType [concrete = constants.%CallsWithType] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %y.patt: @CallsWithType.%pattern_type (%pattern_type.51d) = value_binding_pattern y [concrete]\n// CHECK:STDOUT:     %y.param_patt: @CallsWithType.%pattern_type (%pattern_type.51d) = value_param_pattern %y.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_22.1: type = splice_block %.loc4_22.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc4_22.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc4_18.2: type = symbolic_binding U, 0 [symbolic = %U.loc4_18.1 (constants.%U)]\n// CHECK:STDOUT:     %y.param: @CallsWithType.%U.loc4_18.1 (%U) = value_param call_param0\n// CHECK:STDOUT:     %U.ref: type = name_ref U, %U.loc4_18.2 [symbolic = %U.loc4_18.1 (constants.%U)]\n// CHECK:STDOUT:     %y: @CallsWithType.%U.loc4_18.1 (%U) = value_binding y, %y.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %TakesExtraWhereExplicit.decl: %TakesExtraWhereExplicit.type = fn_decl @TakesExtraWhereExplicit [concrete = constants.%TakesExtraWhereExplicit] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.9a5 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_44.1: type = splice_block %.loc8_44.2 [concrete = constants.%type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc8_39: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.Self.2: type = symbolic_binding .Self [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %.Self.ref: type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.16f]\n// CHECK:STDOUT:       %.loc8_62: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.loc8_44.2: type = where_expr %.Self.2 [concrete = constants.%type] {\n// CHECK:STDOUT:         requirement_base_facet_type type\n// CHECK:STDOUT:         requirement_impls %.Self.ref, %.loc8_62\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_35.3: %type = symbolic_binding T, 0 [symbolic = %T.loc8_35.2 (constants.%T.f45530.2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallsWithTypeExplicit.decl: %CallsWithTypeExplicit.type = fn_decl @CallsWithTypeExplicit [concrete = constants.%CallsWithTypeExplicit] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_30.1: type = splice_block %.loc9_30.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc9_30.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc9_26.2: type = symbolic_binding U, 0 [symbolic = %U.loc9_26.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @TakesExtraWhereDeduced(%T.loc3_27.2: %type) {\n// CHECK:STDOUT:   %T.loc3_27.1: %type = symbolic_binding T, 0 [symbolic = %T.loc3_27.1 (constants.%T.f45530.1)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc3_27.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.349)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.d55)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @TakesExtraWhereDeduced.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallsWithType(%U.loc4_18.2: type) {\n// CHECK:STDOUT:   %U.loc4_18.1: type = symbolic_binding U, 0 [symbolic = %U.loc4_18.1 (constants.%U)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %U.loc4_18.1 [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %U.loc4_18.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %facet_value.loc5_27.2: %type = facet_value %U.loc4_18.1, () [symbolic = %facet_value.loc5_27.2 (constants.%facet_value)]\n// CHECK:STDOUT:   %TakesExtraWhereDeduced.specific_fn.loc5_3.2: <specific function> = specific_function constants.%TakesExtraWhereDeduced, @TakesExtraWhereDeduced(%facet_value.loc5_27.2) [symbolic = %TakesExtraWhereDeduced.specific_fn.loc5_3.2 (constants.%TakesExtraWhereDeduced.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%y.param: @CallsWithType.%U.loc4_18.1 (%U)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %TakesExtraWhereDeduced.ref: %TakesExtraWhereDeduced.type = name_ref TakesExtraWhereDeduced, file.%TakesExtraWhereDeduced.decl [concrete = constants.%TakesExtraWhereDeduced]\n// CHECK:STDOUT:     %y.ref: @CallsWithType.%U.loc4_18.1 (%U) = name_ref y, %y\n// CHECK:STDOUT:     %facet_value.loc5_27.1: %type = facet_value constants.%U, () [symbolic = %facet_value.loc5_27.2 (constants.%facet_value)]\n// CHECK:STDOUT:     %.loc5: %type = converted constants.%U, %facet_value.loc5_27.1 [symbolic = %facet_value.loc5_27.2 (constants.%facet_value)]\n// CHECK:STDOUT:     %TakesExtraWhereDeduced.specific_fn.loc5_3.1: <specific function> = specific_function %TakesExtraWhereDeduced.ref, @TakesExtraWhereDeduced(constants.%facet_value) [symbolic = %TakesExtraWhereDeduced.specific_fn.loc5_3.2 (constants.%TakesExtraWhereDeduced.specific_fn)]\n// CHECK:STDOUT:     %TakesExtraWhereDeduced.call: init %empty_tuple.type = call %TakesExtraWhereDeduced.specific_fn.loc5_3.1(%y.ref)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @TakesExtraWhereExplicit(%T.loc8_35.3: %type) {\n// CHECK:STDOUT:   %T.loc8_35.1: %type = symbolic_binding T, 0 [symbolic = %T.loc8_35.1 (constants.%T.f45530.1)]\n// CHECK:STDOUT:   %T.loc8_35.2: %type = symbolic_binding T, 0 [symbolic = %T.loc8_35.2 (constants.%T.f45530.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallsWithTypeExplicit(%U.loc9_26.2: type) {\n// CHECK:STDOUT:   %U.loc9_26.1: type = symbolic_binding U, 0 [symbolic = %U.loc9_26.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %facet_value.loc10_28.2: %type = facet_value %U.loc9_26.1, () [symbolic = %facet_value.loc10_28.2 (constants.%facet_value)]\n// CHECK:STDOUT:   %TakesExtraWhereExplicit.specific_fn.loc10_3.2: <specific function> = specific_function constants.%TakesExtraWhereExplicit, @TakesExtraWhereExplicit(%facet_value.loc10_28.2) [symbolic = %TakesExtraWhereExplicit.specific_fn.loc10_3.2 (constants.%TakesExtraWhereExplicit.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %TakesExtraWhereExplicit.ref: %TakesExtraWhereExplicit.type = name_ref TakesExtraWhereExplicit, file.%TakesExtraWhereExplicit.decl [concrete = constants.%TakesExtraWhereExplicit]\n// CHECK:STDOUT:     %U.ref: type = name_ref U, %U.loc9_26.2 [symbolic = %U.loc9_26.1 (constants.%U)]\n// CHECK:STDOUT:     %facet_value.loc10_28.1: %type = facet_value %U.ref, () [symbolic = %facet_value.loc10_28.2 (constants.%facet_value)]\n// CHECK:STDOUT:     %.loc10: %type = converted %U.ref, %facet_value.loc10_28.1 [symbolic = %facet_value.loc10_28.2 (constants.%facet_value)]\n// CHECK:STDOUT:     %TakesExtraWhereExplicit.specific_fn.loc10_3.1: <specific function> = specific_function %TakesExtraWhereExplicit.ref, @TakesExtraWhereExplicit(constants.%facet_value) [symbolic = %TakesExtraWhereExplicit.specific_fn.loc10_3.2 (constants.%TakesExtraWhereExplicit.specific_fn)]\n// CHECK:STDOUT:     %TakesExtraWhereExplicit.call: init %empty_tuple.type = call %TakesExtraWhereExplicit.specific_fn.loc10_3.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesExtraWhereDeduced(constants.%T.f45530.1) {\n// CHECK:STDOUT:   %T.loc3_27.1 => constants.%T.f45530.1\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.349\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallsWithType(constants.%U) {\n// CHECK:STDOUT:   %U.loc4_18.1 => constants.%U\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesExtraWhereDeduced(constants.%facet_value) {\n// CHECK:STDOUT:   %T.loc3_27.1 => constants.%facet_value\n// CHECK:STDOUT:   %T.binding.as_type => constants.%U\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.944\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesExtraWhereExplicit(constants.%T.f45530.2) {\n// CHECK:STDOUT:   %T.loc8_35.1 => constants.%T.f45530.2\n// CHECK:STDOUT:   %T.loc8_35.2 => constants.%T.f45530.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallsWithTypeExplicit(constants.%U) {\n// CHECK:STDOUT:   %U.loc9_26.1 => constants.%U\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TakesExtraWhereExplicit(constants.%facet_value) {\n// CHECK:STDOUT:   %T.loc8_35.1 => constants.%facet_value\n// CHECK:STDOUT:   %T.loc8_35.2 => constants.%facet_value\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_facet_value_value_to_blanket_impl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_facet_value_value_to_blanket_impl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_facet_value_value_to_blanket_impl.carbon\n\ninterface Eats {}\ninterface Animal {}\n\nimpl forall [A:! Animal] A as Eats {}\n\nfn Feed[T:! Eats](unused e: T) {}\n\nfn HandleAnimal[T:! Animal](a: T) { Feed(a); }\n\n// CHECK:STDOUT: --- convert_facet_value_value_to_blanket_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats> [concrete]\n// CHECK:STDOUT:   %Self.247: %Eats.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self.c49: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.e10: type = pattern_type %Animal.type [concrete]\n// CHECK:STDOUT:   %A: %Animal.type = symbolic_binding A, 0 [symbolic]\n// CHECK:STDOUT:   %A.binding.as_type: type = symbolic_binding_type A, 0, %A [symbolic]\n// CHECK:STDOUT:   %Eats.impl_witness.760d13.1: <witness> = impl_witness @A.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(%A) [symbolic]\n// CHECK:STDOUT:   %Eats.facet.6e5: %Eats.type = facet_value %A.binding.as_type, (%Eats.impl_witness.760d13.1) [symbolic]\n// CHECK:STDOUT:   %pattern_type.0dc: type = pattern_type %Eats.type [concrete]\n// CHECK:STDOUT:   %T.f11: %Eats.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.265: type = symbolic_binding_type T, 0, %T.f11 [symbolic]\n// CHECK:STDOUT:   %pattern_type.93e: type = pattern_type %T.binding.as_type.265 [symbolic]\n// CHECK:STDOUT:   %Feed.type: type = fn_type @Feed [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Feed: %Feed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.9d9: <witness> = require_complete_type %T.binding.as_type.265 [symbolic]\n// CHECK:STDOUT:   %T.998: %Animal.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.e4f: type = symbolic_binding_type T, 0, %T.998 [symbolic]\n// CHECK:STDOUT:   %pattern_type.892: type = pattern_type %T.binding.as_type.e4f [symbolic]\n// CHECK:STDOUT:   %HandleAnimal.type: type = fn_type @HandleAnimal [concrete]\n// CHECK:STDOUT:   %HandleAnimal: %HandleAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.72f: <witness> = require_complete_type %T.binding.as_type.e4f [symbolic]\n// CHECK:STDOUT:   %Eats.impl_witness.760d13.2: <witness> = impl_witness @A.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(%T.998) [symbolic]\n// CHECK:STDOUT:   %.860: require_specific_def_type = require_specific_def @A.binding.as_type.as.Eats.impl(%T.998) [symbolic]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %T.998, @Eats [symbolic]\n// CHECK:STDOUT:   %Eats.facet.a05: %Eats.type = facet_value %T.binding.as_type.e4f, (%Eats.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Feed.specific_fn: <specific function> = specific_function %Feed, @Feed(%Eats.facet.a05) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Eats = %Eats.decl\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .Feed = %Feed.decl\n// CHECK:STDOUT:     .HandleAnimal = %HandleAnimal.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Eats.decl: type = interface_decl @Eats [concrete = constants.%Eats.type] {} {}\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   impl_decl @A.binding.as_type.as.Eats.impl [concrete] {\n// CHECK:STDOUT:     %A.patt: %pattern_type.e10 = symbolic_binding_pattern A, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %A.ref: %Animal.type = name_ref A, %A.loc18_14.1 [symbolic = %A.loc18_14.2 (constants.%A)]\n// CHECK:STDOUT:     %A.as_type: type = facet_access_type %A.ref [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:     %.loc18_26: type = converted %A.ref, %A.as_type [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:     %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:     %.loc18_18: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %A.loc18_14.1: %Animal.type = symbolic_binding A, 0 [symbolic = %A.loc18_14.2 (constants.%A)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Feed.decl: %Feed.type = fn_decl @Feed [concrete = constants.%Feed] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.0dc = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %e.patt: @Feed.%pattern_type (%pattern_type.93e) = value_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.param_patt: @Feed.%pattern_type (%pattern_type.93e) = value_param_pattern %e.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc20_13: type = splice_block %Eats.ref [concrete = constants.%Eats.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc20_9.2: %Eats.type = symbolic_binding T, 0 [symbolic = %T.loc20_9.1 (constants.%T.f11)]\n// CHECK:STDOUT:     %e.param: @Feed.%T.binding.as_type (%T.binding.as_type.265) = value_param call_param0\n// CHECK:STDOUT:     %.loc20_29.1: type = splice_block %.loc20_29.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.265)] {\n// CHECK:STDOUT:       %T.ref: %Eats.type = name_ref T, %T.loc20_9.2 [symbolic = %T.loc20_9.1 (constants.%T.f11)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type.265)]\n// CHECK:STDOUT:       %.loc20_29.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type.265)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %e: @Feed.%T.binding.as_type (%T.binding.as_type.265) = value_binding e, %e.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %HandleAnimal.decl: %HandleAnimal.type = fn_decl @HandleAnimal [concrete = constants.%HandleAnimal] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.e10 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @HandleAnimal.%pattern_type (%pattern_type.892) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @HandleAnimal.%pattern_type (%pattern_type.892) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc22_21: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc22_17.2: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc22_17.1 (constants.%T.998)]\n// CHECK:STDOUT:     %a.param: @HandleAnimal.%T.binding.as_type (%T.binding.as_type.e4f) = value_param call_param0\n// CHECK:STDOUT:     %.loc22_32.1: type = splice_block %.loc22_32.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)] {\n// CHECK:STDOUT:       %T.ref: %Animal.type = name_ref T, %T.loc22_17.2 [symbolic = %T.loc22_17.1 (constants.%T.998)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)]\n// CHECK:STDOUT:       %.loc22_32.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @HandleAnimal.%T.binding.as_type (%T.binding.as_type.e4f) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Eats {\n// CHECK:STDOUT:   %Self: %Eats.type = symbolic_binding Self, 0 [symbolic = constants.%Self.247]\n// CHECK:STDOUT:   %Eats.WithSelf.decl = interface_with_self_decl @Eats [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c49]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @A.binding.as_type.as.Eats.impl(%A.loc18_14.1: %Animal.type) {\n// CHECK:STDOUT:   %A.loc18_14.2: %Animal.type = symbolic_binding A, 0 [symbolic = %A.loc18_14.2 (constants.%A)]\n// CHECK:STDOUT:   %A.binding.as_type: type = symbolic_binding_type A, 0, %A.loc18_14.2 [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:   %Eats.impl_witness.loc18_36.2: <witness> = impl_witness %Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(%A.loc18_14.2) [symbolic = %Eats.impl_witness.loc18_36.2 (constants.%Eats.impl_witness.760d13.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc18_26 as %Eats.ref {\n// CHECK:STDOUT:     %Eats.impl_witness_table = impl_witness_table (), @A.binding.as_type.as.Eats.impl [concrete]\n// CHECK:STDOUT:     %Eats.impl_witness.loc18_36.1: <witness> = impl_witness %Eats.impl_witness_table, @A.binding.as_type.as.Eats.impl(constants.%A) [symbolic = %Eats.impl_witness.loc18_36.2 (constants.%Eats.impl_witness.760d13.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Eats.impl_witness.loc18_36.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Feed(%T.loc20_9.2: %Eats.type) {\n// CHECK:STDOUT:   %T.loc20_9.1: %Eats.type = symbolic_binding T, 0 [symbolic = %T.loc20_9.1 (constants.%T.f11)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc20_9.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.265)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.93e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.9d9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%e.param: @Feed.%T.binding.as_type (%T.binding.as_type.265)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @HandleAnimal(%T.loc22_17.2: %Animal.type) {\n// CHECK:STDOUT:   %T.loc22_17.1: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc22_17.1 (constants.%T.998)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc22_17.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.892)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.72f)]\n// CHECK:STDOUT:   %.loc22_43.2: require_specific_def_type = require_specific_def @A.binding.as_type.as.Eats.impl(%T.loc22_17.1) [symbolic = %.loc22_43.2 (constants.%.860)]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc22_17.1, @Eats [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]\n// CHECK:STDOUT:   %Eats.facet.loc22_43.2: %Eats.type = facet_value %T.binding.as_type, (%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc22_43.2 (constants.%Eats.facet.a05)]\n// CHECK:STDOUT:   %Feed.specific_fn.loc22_37.2: <specific function> = specific_function constants.%Feed, @Feed(%Eats.facet.loc22_43.2) [symbolic = %Feed.specific_fn.loc22_37.2 (constants.%Feed.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @HandleAnimal.%T.binding.as_type (%T.binding.as_type.e4f)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %Feed.ref: %Feed.type = name_ref Feed, file.%Feed.decl [concrete = constants.%Feed]\n// CHECK:STDOUT:     %a.ref: @HandleAnimal.%T.binding.as_type (%T.binding.as_type.e4f) = name_ref a, %a\n// CHECK:STDOUT:     %Eats.facet.loc22_43.1: %Eats.type = facet_value constants.%T.binding.as_type.e4f, (constants.%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc22_43.2 (constants.%Eats.facet.a05)]\n// CHECK:STDOUT:     %.loc22_43.1: %Eats.type = converted constants.%T.binding.as_type.e4f, %Eats.facet.loc22_43.1 [symbolic = %Eats.facet.loc22_43.2 (constants.%Eats.facet.a05)]\n// CHECK:STDOUT:     %Feed.specific_fn.loc22_37.1: <specific function> = specific_function %Feed.ref, @Feed(constants.%Eats.facet.a05) [symbolic = %Feed.specific_fn.loc22_37.2 (constants.%Feed.specific_fn)]\n// CHECK:STDOUT:     %Feed.call: init %empty_tuple.type = call %Feed.specific_fn.loc22_37.1(%a.ref)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Self.247) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self.c49) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.binding.as_type.as.Eats.impl(constants.%A) {\n// CHECK:STDOUT:   %A.loc18_14.2 => constants.%A\n// CHECK:STDOUT:   %A.binding.as_type => constants.%A.binding.as_type\n// CHECK:STDOUT:   %Eats.impl_witness.loc18_36.2 => constants.%Eats.impl_witness.760d13.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Eats.facet.6e5) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Feed(constants.%T.f11) {\n// CHECK:STDOUT:   %T.loc20_9.1 => constants.%T.f11\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.265\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.93e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleAnimal(constants.%T.998) {\n// CHECK:STDOUT:   %T.loc22_17.1 => constants.%T.998\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.e4f\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.892\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.binding.as_type.as.Eats.impl(constants.%T.998) {\n// CHECK:STDOUT:   %A.loc18_14.2 => constants.%T.998\n// CHECK:STDOUT:   %A.binding.as_type => constants.%T.binding.as_type.e4f\n// CHECK:STDOUT:   %Eats.impl_witness.loc18_36.2 => constants.%Eats.impl_witness.760d13.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Feed(constants.%Eats.facet.a05) {\n// CHECK:STDOUT:   %T.loc20_9.1 => constants.%Eats.facet.a05\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.e4f\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.892\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.72f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_facet_value_value_to_generic_facet_value_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_facet_value_value_to_generic_facet_value_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_facet_value_value_to_generic_facet_value_value.carbon\n\ninterface Edible {}\n\nclass Grass {}\nimpl Grass as Edible {}\n\ninterface Animal {}\ninterface Eats(Food:! type) {}\n\n// When answering a query \"does Goat impl Animal\", we must avoid trying to deduce\n// parameters for this impl. Not only is doing so unnecessary, it would start a new\n// \"does Goat impl Animal\" query, leading to a \"cycle in impl lookup\" error.\nimpl forall [T:! Animal, U:! Edible] T as Eats(U) {}\n\nclass Goat {}\nimpl Goat as Animal {}\n\nfn Feed[Food:! Edible, T:! Eats(Food)](unused e: T, unused food: Food) {}\nfn HandleAnimal[A:! Animal, Food:! Edible](a: A, food: Food) { Feed(a, food); }\n\nfn F() {\n  HandleAnimal({} as Goat, {} as Grass);\n}\n\n// CHECK:STDOUT: --- convert_facet_value_value_to_generic_facet_value_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Edible.type: type = facet_type <@Edible> [concrete]\n// CHECK:STDOUT:   %Self.461: %Edible.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Grass: type = class_type @Grass [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Edible.impl_witness: <witness> = impl_witness @Grass.as.Edible.impl.%Edible.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Edible.facet: %Edible.type = facet_value %Grass, (%Edible.impl_witness) [concrete]\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self.c49: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %Food.67d: type = symbolic_binding Food, 0 [symbolic]\n// CHECK:STDOUT:   %Eats.type.321: type = generic_interface_type @Eats [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Eats.generic: %Eats.type.321 = struct_value () [concrete]\n// CHECK:STDOUT:   %Eats.type.394: type = facet_type <@Eats, @Eats(%Food.67d)> [symbolic]\n// CHECK:STDOUT:   %Self.857: %Eats.type.394 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.e10: type = pattern_type %Animal.type [concrete]\n// CHECK:STDOUT:   %T.998: %Animal.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.b51: type = pattern_type %Edible.type [concrete]\n// CHECK:STDOUT:   %U: %Edible.type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.e4f: type = symbolic_binding_type T, 0, %T.998 [symbolic]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 1, %U [symbolic]\n// CHECK:STDOUT:   %Eats.type.bb4cf6.1: type = facet_type <@Eats, @Eats(%U.binding.as_type)> [symbolic]\n// CHECK:STDOUT:   %Eats.impl_witness.0150b7.1: <witness> = impl_witness @T.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @T.binding.as_type.as.Eats.impl(%T.998, %U) [symbolic]\n// CHECK:STDOUT:   %Self.027: %Eats.type.bb4cf6.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %require_complete.a2722e.1: <witness> = require_complete_type %Eats.type.bb4cf6.1 [symbolic]\n// CHECK:STDOUT:   %Eats.facet.31f: %Eats.type.bb4cf6.1 = facet_value %T.binding.as_type.e4f, (%Eats.impl_witness.0150b7.1) [symbolic]\n// CHECK:STDOUT:   %Goat: type = class_type @Goat [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness @Goat.as.Animal.impl.%Animal.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat, (%Animal.impl_witness) [concrete]\n// CHECK:STDOUT:   %Food.d1c: %Edible.type = symbolic_binding Food, 0 [symbolic]\n// CHECK:STDOUT:   %Food.binding.as_type.8cc: type = symbolic_binding_type Food, 0, %Food.d1c [symbolic]\n// CHECK:STDOUT:   %Eats.type.570: type = facet_type <@Eats, @Eats(%Food.binding.as_type.8cc)> [symbolic]\n// CHECK:STDOUT:   %pattern_type.350: type = pattern_type %Eats.type.570 [symbolic]\n// CHECK:STDOUT:   %T.2b9: %Eats.type.570 = symbolic_binding T, 1 [symbolic]\n// CHECK:STDOUT:   %Self.a66: %Eats.type.570 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.8ae: type = symbolic_binding_type T, 1, %T.2b9 [symbolic]\n// CHECK:STDOUT:   %pattern_type.2b9: type = pattern_type %T.binding.as_type.8ae [symbolic]\n// CHECK:STDOUT:   %pattern_type.12a: type = pattern_type %Food.binding.as_type.8cc [symbolic]\n// CHECK:STDOUT:   %Feed.type: type = fn_type @Feed [concrete]\n// CHECK:STDOUT:   %Feed: %Feed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.0c1: <witness> = require_complete_type %T.binding.as_type.8ae [symbolic]\n// CHECK:STDOUT:   %require_complete.bd7: <witness> = require_complete_type %Food.binding.as_type.8cc [symbolic]\n// CHECK:STDOUT:   %A: %Animal.type = symbolic_binding A, 0 [symbolic]\n// CHECK:STDOUT:   %Food.2fc: %Edible.type = symbolic_binding Food, 1 [symbolic]\n// CHECK:STDOUT:   %A.binding.as_type: type = symbolic_binding_type A, 0, %A [symbolic]\n// CHECK:STDOUT:   %pattern_type.892: type = pattern_type %A.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Food.binding.as_type.e7e: type = symbolic_binding_type Food, 1, %Food.2fc [symbolic]\n// CHECK:STDOUT:   %pattern_type.9ed: type = pattern_type %Food.binding.as_type.e7e [symbolic]\n// CHECK:STDOUT:   %HandleAnimal.type: type = fn_type @HandleAnimal [concrete]\n// CHECK:STDOUT:   %HandleAnimal: %HandleAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.72f: <witness> = require_complete_type %A.binding.as_type [symbolic]\n// CHECK:STDOUT:   %require_complete.0a9: <witness> = require_complete_type %Food.binding.as_type.e7e [symbolic]\n// CHECK:STDOUT:   %Eats.type.bb4cf6.2: type = facet_type <@Eats, @Eats(%Food.binding.as_type.e7e)> [symbolic]\n// CHECK:STDOUT:   %Eats.impl_witness.0150b7.2: <witness> = impl_witness @T.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @T.binding.as_type.as.Eats.impl(%A, %Food.2fc) [symbolic]\n// CHECK:STDOUT:   %require_complete.a2722e.2: <witness> = require_complete_type %Eats.type.bb4cf6.2 [symbolic]\n// CHECK:STDOUT:   %.f9e: require_specific_def_type = require_specific_def @T.binding.as_type.as.Eats.impl(%A, %Food.2fc) [symbolic]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %A, @Eats, @Eats(%Food.binding.as_type.e7e) [symbolic]\n// CHECK:STDOUT:   %Eats.facet.702: %Eats.type.bb4cf6.2 = facet_value %A.binding.as_type, (%Eats.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %pattern_type.67b: type = pattern_type %Eats.type.bb4cf6.2 [symbolic]\n// CHECK:STDOUT:   %Feed.specific_fn.1f9: <specific function> = specific_function %Feed, @Feed(%Food.2fc, %Eats.facet.702) [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Goat.val: %Goat = struct_value () [concrete]\n// CHECK:STDOUT:   %Grass.val: %Grass = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.234: type = pattern_type %Goat [concrete]\n// CHECK:STDOUT:   %pattern_type.df6: type = pattern_type %Grass [concrete]\n// CHECK:STDOUT:   %HandleAnimal.specific_fn: <specific function> = specific_function %HandleAnimal, @HandleAnimal(%Animal.facet, %Edible.facet) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc35_31 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc35_19 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Eats.type.8c2: type = facet_type <@Eats, @Eats(%Grass)> [concrete]\n// CHECK:STDOUT:   %Eats.impl_witness.f54: <witness> = impl_witness @T.binding.as_type.as.Eats.impl.%Eats.impl_witness_table, @T.binding.as_type.as.Eats.impl(%Animal.facet, %Edible.facet) [concrete]\n// CHECK:STDOUT:   %Self.ebd: %Eats.type.8c2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %complete_type.cf8: <witness> = complete_type_witness %Eats.type.8c2 [concrete]\n// CHECK:STDOUT:   %.767: require_specific_def_type = require_specific_def @T.binding.as_type.as.Eats.impl(%Animal.facet, %Edible.facet) [concrete]\n// CHECK:STDOUT:   %Eats.facet.a4e: %Eats.type.8c2 = facet_value %Goat, (%Eats.impl_witness.f54) [concrete]\n// CHECK:STDOUT:   %pattern_type.968: type = pattern_type %Eats.type.8c2 [concrete]\n// CHECK:STDOUT:   %Feed.specific_fn.7dd: <specific function> = specific_function %Feed, @Feed(%Edible.facet, %Eats.facet.a4e) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Edible = %Edible.decl\n// CHECK:STDOUT:     .Grass = %Grass.decl\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .Eats = %Eats.decl\n// CHECK:STDOUT:     .Goat = %Goat.decl\n// CHECK:STDOUT:     .Feed = %Feed.decl\n// CHECK:STDOUT:     .HandleAnimal = %HandleAnimal.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Edible.decl: type = interface_decl @Edible [concrete = constants.%Edible.type] {} {}\n// CHECK:STDOUT:   %Grass.decl: type = class_decl @Grass [concrete = constants.%Grass] {} {}\n// CHECK:STDOUT:   impl_decl @Grass.as.Edible.impl [concrete] {} {\n// CHECK:STDOUT:     %Grass.ref: type = name_ref Grass, file.%Grass.decl [concrete = constants.%Grass]\n// CHECK:STDOUT:     %Edible.ref: type = name_ref Edible, file.%Edible.decl [concrete = constants.%Edible.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   %Eats.decl: %Eats.type.321 = interface_decl @Eats [concrete = constants.%Eats.generic] {\n// CHECK:STDOUT:     %Food.patt: %pattern_type.98f = symbolic_binding_pattern Food, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc21_23.1: type = splice_block %.loc21_23.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc21_23.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Food.loc21_16.2: type = symbolic_binding Food, 0 [symbolic = %Food.loc21_16.1 (constants.%Food.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.Eats.impl [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.e10 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.b51 = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: %Animal.type = name_ref T, %T.loc26_14.1 [symbolic = %T.loc26_14.2 (constants.%T.998)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)]\n// CHECK:STDOUT:     %.loc26_38: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)]\n// CHECK:STDOUT:     %Eats.ref: %Eats.type.321 = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.generic]\n// CHECK:STDOUT:     %U.ref: %Edible.type = name_ref U, %U.loc26_26.1 [symbolic = %U.loc26_26.2 (constants.%U)]\n// CHECK:STDOUT:     %U.as_type: type = facet_access_type %U.ref [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     %.loc26_49: type = converted %U.ref, %U.as_type [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     %Eats.type.loc26_49.1: type = facet_type <@Eats, @Eats(constants.%U.binding.as_type)> [symbolic = %Eats.type.loc26_49.2 (constants.%Eats.type.bb4cf6.1)]\n// CHECK:STDOUT:     %.loc26_18: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc26_14.1: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc26_14.2 (constants.%T.998)]\n// CHECK:STDOUT:     %.loc26_30: type = splice_block %Edible.ref [concrete = constants.%Edible.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Edible.ref: type = name_ref Edible, file.%Edible.decl [concrete = constants.%Edible.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc26_26.1: %Edible.type = symbolic_binding U, 1 [symbolic = %U.loc26_26.2 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Goat.decl: type = class_decl @Goat [concrete = constants.%Goat] {} {}\n// CHECK:STDOUT:   impl_decl @Goat.as.Animal.impl [concrete] {} {\n// CHECK:STDOUT:     %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:     %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Feed.decl: %Feed.type = fn_decl @Feed [concrete = constants.%Feed] {\n// CHECK:STDOUT:     %Food.patt: %pattern_type.b51 = symbolic_binding_pattern Food, 0 [concrete]\n// CHECK:STDOUT:     %T.patt: @Feed.%pattern_type.loc31_24 (%pattern_type.350) = symbolic_binding_pattern T, 1 [concrete]\n// CHECK:STDOUT:     %e.patt: @Feed.%pattern_type.loc31_47 (%pattern_type.2b9) = value_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.param_patt: @Feed.%pattern_type.loc31_47 (%pattern_type.2b9) = value_param_pattern %e.patt [concrete]\n// CHECK:STDOUT:     %food.patt: @Feed.%pattern_type.loc31_60 (%pattern_type.12a) = value_binding_pattern food [concrete]\n// CHECK:STDOUT:     %food.param_patt: @Feed.%pattern_type.loc31_60 (%pattern_type.12a) = value_param_pattern %food.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc31_16: type = splice_block %Edible.ref [concrete = constants.%Edible.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Edible.ref: type = name_ref Edible, file.%Edible.decl [concrete = constants.%Edible.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Food.loc31_9.2: %Edible.type = symbolic_binding Food, 0 [symbolic = %Food.loc31_9.1 (constants.%Food.d1c)]\n// CHECK:STDOUT:     %.loc31_37.1: type = splice_block %Eats.type.loc31_37.2 [symbolic = %Eats.type.loc31_37.1 (constants.%Eats.type.570)] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Eats.ref: %Eats.type.321 = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.generic]\n// CHECK:STDOUT:       %Food.ref.loc31_33: %Edible.type = name_ref Food, %Food.loc31_9.2 [symbolic = %Food.loc31_9.1 (constants.%Food.d1c)]\n// CHECK:STDOUT:       %Food.as_type.loc31_37: type = facet_access_type %Food.ref.loc31_33 [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.8cc)]\n// CHECK:STDOUT:       %.loc31_37.2: type = converted %Food.ref.loc31_33, %Food.as_type.loc31_37 [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.8cc)]\n// CHECK:STDOUT:       %Eats.type.loc31_37.2: type = facet_type <@Eats, @Eats(constants.%Food.binding.as_type.8cc)> [symbolic = %Eats.type.loc31_37.1 (constants.%Eats.type.570)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc31_24.2: @Feed.%Eats.type.loc31_37.1 (%Eats.type.570) = symbolic_binding T, 1 [symbolic = %T.loc31_24.1 (constants.%T.2b9)]\n// CHECK:STDOUT:     %e.param: @Feed.%T.binding.as_type (%T.binding.as_type.8ae) = value_param call_param0\n// CHECK:STDOUT:     %.loc31_50.1: type = splice_block %.loc31_50.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.8ae)] {\n// CHECK:STDOUT:       %T.ref: @Feed.%Eats.type.loc31_37.1 (%Eats.type.570) = name_ref T, %T.loc31_24.2 [symbolic = %T.loc31_24.1 (constants.%T.2b9)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type.8ae)]\n// CHECK:STDOUT:       %.loc31_50.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type.8ae)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %e: @Feed.%T.binding.as_type (%T.binding.as_type.8ae) = value_binding e, %e.param\n// CHECK:STDOUT:     %food.param: @Feed.%Food.binding.as_type (%Food.binding.as_type.8cc) = value_param call_param1\n// CHECK:STDOUT:     %.loc31_66.1: type = splice_block %.loc31_66.2 [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.8cc)] {\n// CHECK:STDOUT:       %Food.ref.loc31_66: %Edible.type = name_ref Food, %Food.loc31_9.2 [symbolic = %Food.loc31_9.1 (constants.%Food.d1c)]\n// CHECK:STDOUT:       %Food.as_type.loc31_66: type = facet_access_type %Food.ref.loc31_66 [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.8cc)]\n// CHECK:STDOUT:       %.loc31_66.2: type = converted %Food.ref.loc31_66, %Food.as_type.loc31_66 [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.8cc)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %food: @Feed.%Food.binding.as_type (%Food.binding.as_type.8cc) = value_binding food, %food.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %HandleAnimal.decl: %HandleAnimal.type = fn_decl @HandleAnimal [concrete = constants.%HandleAnimal] {\n// CHECK:STDOUT:     %A.patt: %pattern_type.e10 = symbolic_binding_pattern A, 0 [concrete]\n// CHECK:STDOUT:     %Food.patt: %pattern_type.b51 = symbolic_binding_pattern Food, 1 [concrete]\n// CHECK:STDOUT:     %a.patt: @HandleAnimal.%pattern_type.loc32_44 (%pattern_type.892) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @HandleAnimal.%pattern_type.loc32_44 (%pattern_type.892) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %food.patt: @HandleAnimal.%pattern_type.loc32_50 (%pattern_type.9ed) = value_binding_pattern food [concrete]\n// CHECK:STDOUT:     %food.param_patt: @HandleAnimal.%pattern_type.loc32_50 (%pattern_type.9ed) = value_param_pattern %food.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc32_21: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %A.loc32_17.2: %Animal.type = symbolic_binding A, 0 [symbolic = %A.loc32_17.1 (constants.%A)]\n// CHECK:STDOUT:     %.loc32_36: type = splice_block %Edible.ref [concrete = constants.%Edible.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Edible.ref: type = name_ref Edible, file.%Edible.decl [concrete = constants.%Edible.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Food.loc32_29.2: %Edible.type = symbolic_binding Food, 1 [symbolic = %Food.loc32_29.1 (constants.%Food.2fc)]\n// CHECK:STDOUT:     %a.param: @HandleAnimal.%A.binding.as_type (%A.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc32_47.1: type = splice_block %.loc32_47.2 [symbolic = %A.binding.as_type (constants.%A.binding.as_type)] {\n// CHECK:STDOUT:       %A.ref: %Animal.type = name_ref A, %A.loc32_17.2 [symbolic = %A.loc32_17.1 (constants.%A)]\n// CHECK:STDOUT:       %A.as_type: type = facet_access_type %A.ref [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:       %.loc32_47.2: type = converted %A.ref, %A.as_type [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @HandleAnimal.%A.binding.as_type (%A.binding.as_type) = value_binding a, %a.param\n// CHECK:STDOUT:     %food.param: @HandleAnimal.%Food.binding.as_type (%Food.binding.as_type.e7e) = value_param call_param1\n// CHECK:STDOUT:     %.loc32_56.1: type = splice_block %.loc32_56.2 [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.e7e)] {\n// CHECK:STDOUT:       %Food.ref: %Edible.type = name_ref Food, %Food.loc32_29.2 [symbolic = %Food.loc32_29.1 (constants.%Food.2fc)]\n// CHECK:STDOUT:       %Food.as_type: type = facet_access_type %Food.ref [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.e7e)]\n// CHECK:STDOUT:       %.loc32_56.2: type = converted %Food.ref, %Food.as_type [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.e7e)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %food: @HandleAnimal.%Food.binding.as_type (%Food.binding.as_type.e7e) = value_binding food, %food.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Edible {\n// CHECK:STDOUT:   %Self: %Edible.type = symbolic_binding Self, 0 [symbolic = constants.%Self.461]\n// CHECK:STDOUT:   %Edible.WithSelf.decl = interface_with_self_decl @Edible [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c49]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @Eats(%Food.loc21_16.2: type) {\n// CHECK:STDOUT:   %Food.loc21_16.1: type = symbolic_binding Food, 0 [symbolic = %Food.loc21_16.1 (constants.%Food.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats, @Eats(%Food.loc21_16.1)> [symbolic = %Eats.type (constants.%Eats.type.394)]\n// CHECK:STDOUT:   %Self.loc21_29.2: @Eats.%Eats.type (%Eats.type.394) = symbolic_binding Self, 1 [symbolic = %Self.loc21_29.2 (constants.%Self.857)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc21_29.1: @Eats.%Eats.type (%Eats.type.394) = symbolic_binding Self, 1 [symbolic = %Self.loc21_29.2 (constants.%Self.857)]\n// CHECK:STDOUT:     %Eats.WithSelf.decl = interface_with_self_decl @Eats [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc21_29.1\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Grass.as.Edible.impl: %Grass.ref as %Edible.ref {\n// CHECK:STDOUT:   %Edible.impl_witness_table = impl_witness_table (), @Grass.as.Edible.impl [concrete]\n// CHECK:STDOUT:   %Edible.impl_witness: <witness> = impl_witness %Edible.impl_witness_table [concrete = constants.%Edible.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Edible.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.binding.as_type.as.Eats.impl(%T.loc26_14.1: %Animal.type, %U.loc26_26.1: %Edible.type) {\n// CHECK:STDOUT:   %T.loc26_14.2: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc26_14.2 (constants.%T.998)]\n// CHECK:STDOUT:   %U.loc26_26.2: %Edible.type = symbolic_binding U, 1 [symbolic = %U.loc26_26.2 (constants.%U)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc26_14.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 1, %U.loc26_26.2 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:   %Eats.type.loc26_49.2: type = facet_type <@Eats, @Eats(%U.binding.as_type)> [symbolic = %Eats.type.loc26_49.2 (constants.%Eats.type.bb4cf6.1)]\n// CHECK:STDOUT:   %Eats.impl_witness.loc26_51.2: <witness> = impl_witness %Eats.impl_witness_table, @T.binding.as_type.as.Eats.impl(%T.loc26_14.2, %U.loc26_26.2) [symbolic = %Eats.impl_witness.loc26_51.2 (constants.%Eats.impl_witness.0150b7.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Eats.type.loc26_49.2 [symbolic = %require_complete (constants.%require_complete.a2722e.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc26_38 as %Eats.type.loc26_49.1 {\n// CHECK:STDOUT:     %Eats.impl_witness_table = impl_witness_table (), @T.binding.as_type.as.Eats.impl [concrete]\n// CHECK:STDOUT:     %Eats.impl_witness.loc26_51.1: <witness> = impl_witness %Eats.impl_witness_table, @T.binding.as_type.as.Eats.impl(constants.%T.998, constants.%U) [symbolic = %Eats.impl_witness.loc26_51.2 (constants.%Eats.impl_witness.0150b7.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Eats.impl_witness.loc26_51.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Goat.as.Animal.impl: %Goat.ref as %Animal.ref {\n// CHECK:STDOUT:   %Animal.impl_witness_table = impl_witness_table (), @Goat.as.Animal.impl [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness %Animal.impl_witness_table [concrete = constants.%Animal.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Animal.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Grass {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Grass\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Goat {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Goat\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Feed(%Food.loc31_9.2: %Edible.type, %T.loc31_24.2: @Feed.%Eats.type.loc31_37.1 (%Eats.type.570)) {\n// CHECK:STDOUT:   %Food.loc31_9.1: %Edible.type = symbolic_binding Food, 0 [symbolic = %Food.loc31_9.1 (constants.%Food.d1c)]\n// CHECK:STDOUT:   %Food.binding.as_type: type = symbolic_binding_type Food, 0, %Food.loc31_9.1 [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.8cc)]\n// CHECK:STDOUT:   %Eats.type.loc31_37.1: type = facet_type <@Eats, @Eats(%Food.binding.as_type)> [symbolic = %Eats.type.loc31_37.1 (constants.%Eats.type.570)]\n// CHECK:STDOUT:   %T.loc31_24.1: @Feed.%Eats.type.loc31_37.1 (%Eats.type.570) = symbolic_binding T, 1 [symbolic = %T.loc31_24.1 (constants.%T.2b9)]\n// CHECK:STDOUT:   %pattern_type.loc31_24: type = pattern_type %Eats.type.loc31_37.1 [symbolic = %pattern_type.loc31_24 (constants.%pattern_type.350)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 1, %T.loc31_24.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.8ae)]\n// CHECK:STDOUT:   %pattern_type.loc31_47: type = pattern_type %T.binding.as_type [symbolic = %pattern_type.loc31_47 (constants.%pattern_type.2b9)]\n// CHECK:STDOUT:   %pattern_type.loc31_60: type = pattern_type %Food.binding.as_type [symbolic = %pattern_type.loc31_60 (constants.%pattern_type.12a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc31_48: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete.loc31_48 (constants.%require_complete.0c1)]\n// CHECK:STDOUT:   %require_complete.loc31_64: <witness> = require_complete_type %Food.binding.as_type [symbolic = %require_complete.loc31_64 (constants.%require_complete.bd7)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%e.param: @Feed.%T.binding.as_type (%T.binding.as_type.8ae), %food.param: @Feed.%Food.binding.as_type (%Food.binding.as_type.8cc)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @HandleAnimal(%A.loc32_17.2: %Animal.type, %Food.loc32_29.2: %Edible.type) {\n// CHECK:STDOUT:   %A.loc32_17.1: %Animal.type = symbolic_binding A, 0 [symbolic = %A.loc32_17.1 (constants.%A)]\n// CHECK:STDOUT:   %Food.loc32_29.1: %Edible.type = symbolic_binding Food, 1 [symbolic = %Food.loc32_29.1 (constants.%Food.2fc)]\n// CHECK:STDOUT:   %A.binding.as_type: type = symbolic_binding_type A, 0, %A.loc32_17.1 [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type.loc32_44: type = pattern_type %A.binding.as_type [symbolic = %pattern_type.loc32_44 (constants.%pattern_type.892)]\n// CHECK:STDOUT:   %Food.binding.as_type: type = symbolic_binding_type Food, 1, %Food.loc32_29.1 [symbolic = %Food.binding.as_type (constants.%Food.binding.as_type.e7e)]\n// CHECK:STDOUT:   %pattern_type.loc32_50: type = pattern_type %Food.binding.as_type [symbolic = %pattern_type.loc32_50 (constants.%pattern_type.9ed)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc32_45: <witness> = require_complete_type %A.binding.as_type [symbolic = %require_complete.loc32_45 (constants.%require_complete.72f)]\n// CHECK:STDOUT:   %require_complete.loc32_54: <witness> = require_complete_type %Food.binding.as_type [symbolic = %require_complete.loc32_54 (constants.%require_complete.0a9)]\n// CHECK:STDOUT:   %.loc32_76.3: require_specific_def_type = require_specific_def @T.binding.as_type.as.Eats.impl(%A.loc32_17.1, %Food.loc32_29.1) [symbolic = %.loc32_76.3 (constants.%.f9e)]\n// CHECK:STDOUT:   %Eats.lookup_impl_witness: <witness> = lookup_impl_witness %A.loc32_17.1, @Eats, @Eats(%Food.binding.as_type) [symbolic = %Eats.lookup_impl_witness (constants.%Eats.lookup_impl_witness)]\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats, @Eats(%Food.binding.as_type)> [symbolic = %Eats.type (constants.%Eats.type.bb4cf6.2)]\n// CHECK:STDOUT:   %Eats.facet.loc32_76.2: @HandleAnimal.%Eats.type (%Eats.type.bb4cf6.2) = facet_value %A.binding.as_type, (%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc32_76.2 (constants.%Eats.facet.702)]\n// CHECK:STDOUT:   %Feed.specific_fn.loc32_64.2: <specific function> = specific_function constants.%Feed, @Feed(%Food.loc32_29.1, %Eats.facet.loc32_76.2) [symbolic = %Feed.specific_fn.loc32_64.2 (constants.%Feed.specific_fn.1f9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @HandleAnimal.%A.binding.as_type (%A.binding.as_type), %food.param: @HandleAnimal.%Food.binding.as_type (%Food.binding.as_type.e7e)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %Feed.ref: %Feed.type = name_ref Feed, file.%Feed.decl [concrete = constants.%Feed]\n// CHECK:STDOUT:     %a.ref: @HandleAnimal.%A.binding.as_type (%A.binding.as_type) = name_ref a, %a\n// CHECK:STDOUT:     %food.ref: @HandleAnimal.%Food.binding.as_type (%Food.binding.as_type.e7e) = name_ref food, %food\n// CHECK:STDOUT:     %.loc32_76.1: %Edible.type = converted constants.%Food.binding.as_type.e7e, constants.%Food.2fc [symbolic = %Food.loc32_29.1 (constants.%Food.2fc)]\n// CHECK:STDOUT:     %Eats.facet.loc32_76.1: @HandleAnimal.%Eats.type (%Eats.type.bb4cf6.2) = facet_value constants.%A.binding.as_type, (constants.%Eats.lookup_impl_witness) [symbolic = %Eats.facet.loc32_76.2 (constants.%Eats.facet.702)]\n// CHECK:STDOUT:     %.loc32_76.2: @HandleAnimal.%Eats.type (%Eats.type.bb4cf6.2) = converted constants.%A.binding.as_type, %Eats.facet.loc32_76.1 [symbolic = %Eats.facet.loc32_76.2 (constants.%Eats.facet.702)]\n// CHECK:STDOUT:     %Feed.specific_fn.loc32_64.1: <specific function> = specific_function %Feed.ref, @Feed(constants.%Food.2fc, constants.%Eats.facet.702) [symbolic = %Feed.specific_fn.loc32_64.2 (constants.%Feed.specific_fn.1f9)]\n// CHECK:STDOUT:     %Feed.call: init %empty_tuple.type = call %Feed.specific_fn.loc32_64.1(%a.ref, %food.ref)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %HandleAnimal.ref: %HandleAnimal.type = name_ref HandleAnimal, file.%HandleAnimal.decl [concrete = constants.%HandleAnimal]\n// CHECK:STDOUT:   %.loc35_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc35_17.2: ref %Goat = temporary_storage\n// CHECK:STDOUT:   %.loc35_17.3: init %Goat to %.loc35_17.2 = class_init () [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %.loc35_19.1: init %Goat = converted %.loc35_17.1, %.loc35_17.3 [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %.loc35_29.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Grass.ref: type = name_ref Grass, file.%Grass.decl [concrete = constants.%Grass]\n// CHECK:STDOUT:   %.loc35_29.2: ref %Grass = temporary_storage\n// CHECK:STDOUT:   %.loc35_29.3: init %Grass to %.loc35_29.2 = class_init () [concrete = constants.%Grass.val]\n// CHECK:STDOUT:   %.loc35_31.1: init %Grass = converted %.loc35_29.1, %.loc35_29.3 [concrete = constants.%Grass.val]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value constants.%Goat, (constants.%Animal.impl_witness) [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %.loc35_39.1: %Animal.type = converted constants.%Goat, %Animal.facet [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %Edible.facet: %Edible.type = facet_value constants.%Grass, (constants.%Edible.impl_witness) [concrete = constants.%Edible.facet]\n// CHECK:STDOUT:   %.loc35_39.2: %Edible.type = converted constants.%Grass, %Edible.facet [concrete = constants.%Edible.facet]\n// CHECK:STDOUT:   %HandleAnimal.specific_fn: <specific function> = specific_function %HandleAnimal.ref, @HandleAnimal(constants.%Animal.facet, constants.%Edible.facet) [concrete = constants.%HandleAnimal.specific_fn]\n// CHECK:STDOUT:   %.loc35_19.2: ref %Goat = temporary %.loc35_17.2, %.loc35_19.1\n// CHECK:STDOUT:   %.loc35_19.3: %Goat = acquire_value %.loc35_19.2\n// CHECK:STDOUT:   %.loc35_31.2: ref %Grass = temporary %.loc35_29.2, %.loc35_31.1\n// CHECK:STDOUT:   %.loc35_31.3: %Grass = acquire_value %.loc35_31.2\n// CHECK:STDOUT:   %HandleAnimal.call: init %empty_tuple.type = call %HandleAnimal.specific_fn(%.loc35_19.3, %.loc35_31.3)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc35_31: <bound method> = bound_method %.loc35_31.2, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc35_31: init %empty_tuple.type = call %Destroy.Op.bound.loc35_31(%.loc35_31.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc35_19: <bound method> = bound_method %.loc35_19.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc35_19: init %empty_tuple.type = call %Destroy.Op.bound.loc35_19(%.loc35_19.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc35_31(%self.param: ref %Grass) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc35_19(%self.param: ref %Goat) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Edible.WithSelf(constants.%Self.461) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Edible.WithSelf(constants.%Edible.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self.c49) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats(constants.%Food.67d) {\n// CHECK:STDOUT:   %Food.loc21_16.1 => constants.%Food.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Food.67d, constants.%Self.857) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats(constants.%U.binding.as_type) {\n// CHECK:STDOUT:   %Food.loc21_16.1 => constants.%U.binding.as_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Eats.type => constants.%Eats.type.bb4cf6.1\n// CHECK:STDOUT:   %Self.loc21_29.2 => constants.%Self.027\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.binding.as_type.as.Eats.impl(constants.%T.998, constants.%U) {\n// CHECK:STDOUT:   %T.loc26_14.2 => constants.%T.998\n// CHECK:STDOUT:   %U.loc26_26.2 => constants.%U\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.e4f\n// CHECK:STDOUT:   %U.binding.as_type => constants.%U.binding.as_type\n// CHECK:STDOUT:   %Eats.type.loc26_49.2 => constants.%Eats.type.bb4cf6.1\n// CHECK:STDOUT:   %Eats.impl_witness.loc26_51.2 => constants.%Eats.impl_witness.0150b7.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%U.binding.as_type, constants.%Self.857) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%U.binding.as_type, constants.%Eats.facet.31f) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Animal.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats(constants.%Food.binding.as_type.8cc) {\n// CHECK:STDOUT:   %Food.loc21_16.1 => constants.%Food.binding.as_type.8cc\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Eats.type => constants.%Eats.type.570\n// CHECK:STDOUT:   %Self.loc21_29.2 => constants.%Self.a66\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Food.binding.as_type.8cc, constants.%Self.857) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Feed(constants.%Food.d1c, constants.%T.2b9) {\n// CHECK:STDOUT:   %Food.loc31_9.1 => constants.%Food.d1c\n// CHECK:STDOUT:   %Food.binding.as_type => constants.%Food.binding.as_type.8cc\n// CHECK:STDOUT:   %Eats.type.loc31_37.1 => constants.%Eats.type.570\n// CHECK:STDOUT:   %T.loc31_24.1 => constants.%T.2b9\n// CHECK:STDOUT:   %pattern_type.loc31_24 => constants.%pattern_type.350\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.8ae\n// CHECK:STDOUT:   %pattern_type.loc31_47 => constants.%pattern_type.2b9\n// CHECK:STDOUT:   %pattern_type.loc31_60 => constants.%pattern_type.12a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleAnimal(constants.%A, constants.%Food.2fc) {\n// CHECK:STDOUT:   %A.loc32_17.1 => constants.%A\n// CHECK:STDOUT:   %Food.loc32_29.1 => constants.%Food.2fc\n// CHECK:STDOUT:   %A.binding.as_type => constants.%A.binding.as_type\n// CHECK:STDOUT:   %pattern_type.loc32_44 => constants.%pattern_type.892\n// CHECK:STDOUT:   %Food.binding.as_type => constants.%Food.binding.as_type.e7e\n// CHECK:STDOUT:   %pattern_type.loc32_50 => constants.%pattern_type.9ed\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats(constants.%Food.binding.as_type.e7e) {\n// CHECK:STDOUT:   %Food.loc21_16.1 => constants.%Food.binding.as_type.e7e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.binding.as_type.as.Eats.impl(constants.%A, constants.%Food.2fc) {\n// CHECK:STDOUT:   %T.loc26_14.2 => constants.%A\n// CHECK:STDOUT:   %U.loc26_26.2 => constants.%Food.2fc\n// CHECK:STDOUT:   %T.binding.as_type => constants.%A.binding.as_type\n// CHECK:STDOUT:   %U.binding.as_type => constants.%Food.binding.as_type.e7e\n// CHECK:STDOUT:   %Eats.type.loc26_49.2 => constants.%Eats.type.bb4cf6.2\n// CHECK:STDOUT:   %Eats.impl_witness.loc26_51.2 => constants.%Eats.impl_witness.0150b7.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.a2722e.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Feed(constants.%Food.2fc, constants.%Eats.facet.702) {\n// CHECK:STDOUT:   %Food.loc31_9.1 => constants.%Food.2fc\n// CHECK:STDOUT:   %Food.binding.as_type => constants.%Food.binding.as_type.e7e\n// CHECK:STDOUT:   %Eats.type.loc31_37.1 => constants.%Eats.type.bb4cf6.2\n// CHECK:STDOUT:   %T.loc31_24.1 => constants.%Eats.facet.702\n// CHECK:STDOUT:   %pattern_type.loc31_24 => constants.%pattern_type.67b\n// CHECK:STDOUT:   %T.binding.as_type => constants.%A.binding.as_type\n// CHECK:STDOUT:   %pattern_type.loc31_47 => constants.%pattern_type.892\n// CHECK:STDOUT:   %pattern_type.loc31_60 => constants.%pattern_type.9ed\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc31_48 => constants.%require_complete.72f\n// CHECK:STDOUT:   %require_complete.loc31_64 => constants.%require_complete.0a9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleAnimal(constants.%Animal.facet, constants.%Edible.facet) {\n// CHECK:STDOUT:   %A.loc32_17.1 => constants.%Animal.facet\n// CHECK:STDOUT:   %Food.loc32_29.1 => constants.%Edible.facet\n// CHECK:STDOUT:   %A.binding.as_type => constants.%Goat\n// CHECK:STDOUT:   %pattern_type.loc32_44 => constants.%pattern_type.234\n// CHECK:STDOUT:   %Food.binding.as_type => constants.%Grass\n// CHECK:STDOUT:   %pattern_type.loc32_50 => constants.%pattern_type.df6\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc32_45 => constants.%complete_type.357\n// CHECK:STDOUT:   %require_complete.loc32_54 => constants.%complete_type.357\n// CHECK:STDOUT:   %.loc32_76.3 => constants.%.767\n// CHECK:STDOUT:   %Eats.lookup_impl_witness => constants.%Eats.impl_witness.f54\n// CHECK:STDOUT:   %Eats.type => constants.%Eats.type.8c2\n// CHECK:STDOUT:   %Eats.facet.loc32_76.2 => constants.%Eats.facet.a4e\n// CHECK:STDOUT:   %Feed.specific_fn.loc32_64.2 => constants.%Feed.specific_fn.7dd\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.binding.as_type.as.Eats.impl(constants.%Animal.facet, constants.%Edible.facet) {\n// CHECK:STDOUT:   %T.loc26_14.2 => constants.%Animal.facet\n// CHECK:STDOUT:   %U.loc26_26.2 => constants.%Edible.facet\n// CHECK:STDOUT:   %T.binding.as_type => constants.%Goat\n// CHECK:STDOUT:   %U.binding.as_type => constants.%Grass\n// CHECK:STDOUT:   %Eats.type.loc26_49.2 => constants.%Eats.type.8c2\n// CHECK:STDOUT:   %Eats.impl_witness.loc26_51.2 => constants.%Eats.impl_witness.f54\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.cf8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats(constants.%Grass) {\n// CHECK:STDOUT:   %Food.loc21_16.1 => constants.%Grass\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Eats.type => constants.%Eats.type.8c2\n// CHECK:STDOUT:   %Self.loc21_29.2 => constants.%Self.ebd\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Grass, constants.%Self.857) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Feed(constants.%Edible.facet, constants.%Eats.facet.a4e) {\n// CHECK:STDOUT:   %Food.loc31_9.1 => constants.%Edible.facet\n// CHECK:STDOUT:   %Food.binding.as_type => constants.%Grass\n// CHECK:STDOUT:   %Eats.type.loc31_37.1 => constants.%Eats.type.8c2\n// CHECK:STDOUT:   %T.loc31_24.1 => constants.%Eats.facet.a4e\n// CHECK:STDOUT:   %pattern_type.loc31_24 => constants.%pattern_type.968\n// CHECK:STDOUT:   %T.binding.as_type => constants.%Goat\n// CHECK:STDOUT:   %pattern_type.loc31_47 => constants.%pattern_type.234\n// CHECK:STDOUT:   %pattern_type.loc31_60 => constants.%pattern_type.df6\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc31_48 => constants.%complete_type.357\n// CHECK:STDOUT:   %require_complete.loc31_64 => constants.%complete_type.357\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_facet_value_value_to_itself.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_facet_value_value_to_itself.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_facet_value_value_to_itself.carbon\n\ninterface Animal {}\n\nfn FeedAnimal[T:! Animal](unused a: T) {}\n\nfn HandleAnimal[T:! Animal](a: T) { FeedAnimal(a); }\n\nclass Goat {}\nimpl Goat as Animal {}\n\nfn F() {\n  HandleAnimal({} as Goat);\n}\n\n// CHECK:STDOUT: --- convert_facet_value_value_to_itself.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self.c49: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.e10: type = pattern_type %Animal.type [concrete]\n// CHECK:STDOUT:   %T: %Animal.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.892: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %FeedAnimal.type: type = fn_type @FeedAnimal [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %FeedAnimal: %FeedAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %HandleAnimal.type: type = fn_type @HandleAnimal [concrete]\n// CHECK:STDOUT:   %HandleAnimal: %HandleAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %FeedAnimal.specific_fn.ae9: <specific function> = specific_function %FeedAnimal, @FeedAnimal(%T) [symbolic]\n// CHECK:STDOUT:   %Goat: type = class_type @Goat [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness @Goat.as.Animal.impl.%Animal.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat, (%Animal.impl_witness) [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Goat.val: %Goat = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.234: type = pattern_type %Goat [concrete]\n// CHECK:STDOUT:   %HandleAnimal.specific_fn: <specific function> = specific_function %HandleAnimal, @HandleAnimal(%Animal.facet) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %FeedAnimal.specific_fn.cc5: <specific function> = specific_function %FeedAnimal, @FeedAnimal(%Animal.facet) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .FeedAnimal = %FeedAnimal.decl\n// CHECK:STDOUT:     .HandleAnimal = %HandleAnimal.decl\n// CHECK:STDOUT:     .Goat = %Goat.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   %FeedAnimal.decl: %FeedAnimal.type = fn_decl @FeedAnimal [concrete = constants.%FeedAnimal] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.e10 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @FeedAnimal.%pattern_type (%pattern_type.892) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @FeedAnimal.%pattern_type (%pattern_type.892) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc17_19: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc17_15.2: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc17_15.1 (constants.%T)]\n// CHECK:STDOUT:     %a.param: @FeedAnimal.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc17_37.1: type = splice_block %.loc17_37.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref: %Animal.type = name_ref T, %T.loc17_15.2 [symbolic = %T.loc17_15.1 (constants.%T)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc17_37.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @FeedAnimal.%T.binding.as_type (%T.binding.as_type) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %HandleAnimal.decl: %HandleAnimal.type = fn_decl @HandleAnimal [concrete = constants.%HandleAnimal] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.e10 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @HandleAnimal.%pattern_type (%pattern_type.892) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @HandleAnimal.%pattern_type (%pattern_type.892) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc19_21: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc19_17.2: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc19_17.1 (constants.%T)]\n// CHECK:STDOUT:     %a.param: @HandleAnimal.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc19_32.1: type = splice_block %.loc19_32.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref: %Animal.type = name_ref T, %T.loc19_17.2 [symbolic = %T.loc19_17.1 (constants.%T)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc19_32.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @HandleAnimal.%T.binding.as_type (%T.binding.as_type) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Goat.decl: type = class_decl @Goat [concrete = constants.%Goat] {} {}\n// CHECK:STDOUT:   impl_decl @Goat.as.Animal.impl [concrete] {} {\n// CHECK:STDOUT:     %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:     %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c49]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Goat.as.Animal.impl: %Goat.ref as %Animal.ref {\n// CHECK:STDOUT:   %Animal.impl_witness_table = impl_witness_table (), @Goat.as.Animal.impl [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness %Animal.impl_witness_table [concrete = constants.%Animal.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Animal.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Goat {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Goat\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @FeedAnimal(%T.loc17_15.2: %Animal.type) {\n// CHECK:STDOUT:   %T.loc17_15.1: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc17_15.1 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc17_15.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.892)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @FeedAnimal.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @HandleAnimal(%T.loc19_17.2: %Animal.type) {\n// CHECK:STDOUT:   %T.loc19_17.1: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc19_17.1 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc19_17.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.892)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %FeedAnimal.specific_fn.loc19_37.2: <specific function> = specific_function constants.%FeedAnimal, @FeedAnimal(%T.loc19_17.1) [symbolic = %FeedAnimal.specific_fn.loc19_37.2 (constants.%FeedAnimal.specific_fn.ae9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @HandleAnimal.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %FeedAnimal.ref: %FeedAnimal.type = name_ref FeedAnimal, file.%FeedAnimal.decl [concrete = constants.%FeedAnimal]\n// CHECK:STDOUT:     %a.ref: @HandleAnimal.%T.binding.as_type (%T.binding.as_type) = name_ref a, %a\n// CHECK:STDOUT:     %.loc19_49: %Animal.type = converted constants.%T.binding.as_type, constants.%T [symbolic = %T.loc19_17.1 (constants.%T)]\n// CHECK:STDOUT:     %FeedAnimal.specific_fn.loc19_37.1: <specific function> = specific_function %FeedAnimal.ref, @FeedAnimal(constants.%T) [symbolic = %FeedAnimal.specific_fn.loc19_37.2 (constants.%FeedAnimal.specific_fn.ae9)]\n// CHECK:STDOUT:     %FeedAnimal.call: init %empty_tuple.type = call %FeedAnimal.specific_fn.loc19_37.1(%a.ref)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %HandleAnimal.ref: %HandleAnimal.type = name_ref HandleAnimal, file.%HandleAnimal.decl [concrete = constants.%HandleAnimal]\n// CHECK:STDOUT:   %.loc25_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Goat.ref: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]\n// CHECK:STDOUT:   %.loc25_17.2: ref %Goat = temporary_storage\n// CHECK:STDOUT:   %.loc25_17.3: init %Goat to %.loc25_17.2 = class_init () [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %.loc25_19.1: init %Goat = converted %.loc25_17.1, %.loc25_17.3 [concrete = constants.%Goat.val]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value constants.%Goat, (constants.%Animal.impl_witness) [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %.loc25_26: %Animal.type = converted constants.%Goat, %Animal.facet [concrete = constants.%Animal.facet]\n// CHECK:STDOUT:   %HandleAnimal.specific_fn: <specific function> = specific_function %HandleAnimal.ref, @HandleAnimal(constants.%Animal.facet) [concrete = constants.%HandleAnimal.specific_fn]\n// CHECK:STDOUT:   %.loc25_19.2: ref %Goat = temporary %.loc25_17.2, %.loc25_19.1\n// CHECK:STDOUT:   %.loc25_19.3: %Goat = acquire_value %.loc25_19.2\n// CHECK:STDOUT:   %HandleAnimal.call: init %empty_tuple.type = call %HandleAnimal.specific_fn(%.loc25_19.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc25_19.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc25_19.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Goat) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self.c49) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @FeedAnimal(constants.%T) {\n// CHECK:STDOUT:   %T.loc17_15.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.892\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleAnimal(constants.%T) {\n// CHECK:STDOUT:   %T.loc19_17.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.892\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Animal.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleAnimal(constants.%Animal.facet) {\n// CHECK:STDOUT:   %T.loc19_17.1 => constants.%Animal.facet\n// CHECK:STDOUT:   %T.binding.as_type => constants.%Goat\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.234\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT:   %FeedAnimal.specific_fn.loc19_37.2 => constants.%FeedAnimal.specific_fn.cc5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @FeedAnimal(constants.%Animal.facet) {\n// CHECK:STDOUT:   %T.loc17_15.1 => constants.%Animal.facet\n// CHECK:STDOUT:   %T.binding.as_type => constants.%Goat\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.234\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/convert_interface.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/convert_interface.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/convert_interface.carbon\n\ninterface Eats {}\ninterface Animal {}\n\n// TODO: This may be rejected in the future.\n// https://github.com/carbon-language/carbon-lang/issues/4853\nimpl Animal as Eats {}\n\nfn F(unused e: Eats) {}\nfn G() { F(Animal); }\n\n// CHECK:STDOUT: --- convert_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats> [concrete]\n// CHECK:STDOUT:   %Self.247: %Eats.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self.c49: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Eats.impl_witness: <witness> = impl_witness @Animal.type.as.Eats.impl.%Eats.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Eats.facet: %Eats.type = facet_value %Animal.type, (%Eats.impl_witness) [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Eats.type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Eats = %Eats.decl\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Eats.decl: type = interface_decl @Eats [concrete = constants.%Eats.type] {} {}\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   impl_decl @Animal.type.as.Eats.impl [concrete] {} {\n// CHECK:STDOUT:     %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %e.patt: %pattern_type = value_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.param_patt: %pattern_type = value_param_pattern %e.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %e.param: %Eats.type = value_param call_param0\n// CHECK:STDOUT:     %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:     %e: %Eats.type = value_binding e, %e.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Eats {\n// CHECK:STDOUT:   %Self: %Eats.type = symbolic_binding Self, 0 [symbolic = constants.%Self.247]\n// CHECK:STDOUT:   %Eats.WithSelf.decl = interface_with_self_decl @Eats [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c49]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Animal.type.as.Eats.impl: %Animal.ref as %Eats.ref {\n// CHECK:STDOUT:   %Eats.impl_witness_table = impl_witness_table (), @Animal.type.as.Eats.impl [concrete]\n// CHECK:STDOUT:   %Eats.impl_witness: <witness> = impl_witness %Eats.impl_witness_table [concrete = constants.%Eats.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Eats.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%e.param: %Eats.type) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:   %Eats.facet: %Eats.type = facet_value %Animal.ref, (constants.%Eats.impl_witness) [concrete = constants.%Eats.facet]\n// CHECK:STDOUT:   %.loc23: %Eats.type = converted %Animal.ref, %Eats.facet [concrete = constants.%Eats.facet]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref(%.loc23)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Self.247) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self.c49) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Eats.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/early_rewrites.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/early_rewrites.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/early_rewrites.carbon\n\n// Tests where `ImplWitnessAccess` on the RHS of a rewrite constraint is used in\n// other constraints within the same facet type in ways that require the RHS to\n// be evaluated to a concrete value before the facet type is resolved (such as\n// by passing it as a parameter to a generic class). This can be done either by\n// eagerly reading rewrite constraints from the same facet type, or by relying\n// on implied constraints which are checked later.\n\n// --- fail_todo_implied_constraint_on_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\n\nclass C(T:! Z where .Z1 = ()) {}\n\ninterface J {\n  // Implied: .Z1 == ()\n  // CHECK:STDERR: fail_todo_implied_constraint_on_self.carbon:[[@LINE+7]]:26: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   let J1:! Z where .Z2 = C(.Self);\n  // CHECK:STDERR:                          ^~~~~~~~\n  // CHECK:STDERR: fail_todo_implied_constraint_on_self.carbon:[[@LINE-7]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n  // CHECK:STDERR:         ^\n  // CHECK:STDERR:\n  let J1:! Z where .Z2 = C(.Self);\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\n// CHECK:STDERR: fail_todo_implied_constraint_on_self.carbon:[[@LINE+7]]:38: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: impl D as Z where .Z1 = () and .Z2 = C(.Self) {}\n// CHECK:STDERR:                                      ^~~~~~~~\n// CHECK:STDERR: fail_todo_implied_constraint_on_self.carbon:[[@LINE-21]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nimpl D as Z where .Z1 = () and .Z2 = C(.Self) {}\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n\n// --- fail_todo_implied_constraint_on_associated_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\n\ninterface Tuple {}\nimpl () as Tuple {}\n\nclass C(T:! Tuple) {}\n\ninterface J {\n  // Implied: .Z1 impls Tuple\n  // CHECK:STDERR: fail_todo_implied_constraint_on_associated_constant.carbon:[[@LINE+7]]:26: error: cannot convert type `.(Z.Z1)` into type implementing `Tuple` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   let J1:! Z where .Z2 = C(.Z1);\n  // CHECK:STDERR:                          ^~~~~~\n  // CHECK:STDERR: fail_todo_implied_constraint_on_associated_constant.carbon:[[@LINE-7]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: class C(T:! Tuple) {}\n  // CHECK:STDERR:         ^\n  // CHECK:STDERR:\n  let J1:! Z where .Z2 = C(.Z1);\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\nimpl D as Z where .Z1 = () and .Z2 = C(()) {}\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n\n// --- fail_todo_nested_constraint_visible_in_type_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\n\nclass C(T:! Z where .Z1 = ()) {}\n\ninterface J {\n  // Implied: .Z1 == (), but this is also explicitly required for J1.\n  // CHECK:STDERR: fail_todo_nested_constraint_visible_in_type_parameter.carbon:[[@LINE+7]]:43: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   let J1:! (Z where .Z1 = ()) where .Z2 = C(.Self);\n  // CHECK:STDERR:                                           ^~~~~~~~\n  // CHECK:STDERR: fail_todo_nested_constraint_visible_in_type_parameter.carbon:[[@LINE-7]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n  // CHECK:STDERR:         ^\n  // CHECK:STDERR:\n  let J1:! (Z where .Z1 = ()) where .Z2 = C(.Self);\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\n// CHECK:STDERR: fail_todo_nested_constraint_visible_in_type_parameter.carbon:[[@LINE+7]]:38: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: impl D as Z where .Z1 = () and .Z2 = C(.Self) {}\n// CHECK:STDERR:                                      ^~~~~~~~\n// CHECK:STDERR: fail_todo_nested_constraint_visible_in_type_parameter.carbon:[[@LINE-21]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nimpl D as Z where .Z1 = () and .Z2 = C(.Self) {}\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n\n// --- fail_todo_outer_nested_constraint_visible_in_type_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\n\nclass C(T:! Z where .Z1 = ()) {}\n\ninterface J {\n  // Implied: .Z1 == (), but this is also explicitly required for J1.\n  // CHECK:STDERR: fail_todo_outer_nested_constraint_visible_in_type_parameter.carbon:[[@LINE+7]]:27: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   let J1:! (Z where .Z2 = C(.Self)) where .Z1 = ();\n  // CHECK:STDERR:                           ^~~~~~~~\n  // CHECK:STDERR: fail_todo_outer_nested_constraint_visible_in_type_parameter.carbon:[[@LINE-7]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n  // CHECK:STDERR:         ^\n  // CHECK:STDERR:\n  let J1:! (Z where .Z2 = C(.Self)) where .Z1 = ();\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\n// CHECK:STDERR: fail_todo_outer_nested_constraint_visible_in_type_parameter.carbon:[[@LINE+7]]:38: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: impl D as Z where .Z1 = () and .Z2 = C(.Self) {}\n// CHECK:STDERR:                                      ^~~~~~~~\n// CHECK:STDERR: fail_todo_outer_nested_constraint_visible_in_type_parameter.carbon:[[@LINE-21]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nimpl D as Z where .Z1 = () and .Z2 = C(.Self) {}\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n\n// --- fail_todo_earlier_constraint_visible_in_type_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\n\nclass C(T:! Z where .Z1 = ()) {}\n\ninterface J {\n  // Implied: .Z1 == (), but this is also explicitly required for J1.\n  // CHECK:STDERR: fail_todo_earlier_constraint_visible_in_type_parameter.carbon:[[@LINE+7]]:39: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   let J1:! Z where .Z1 = () and .Z2 = C(.Self);\n  // CHECK:STDERR:                                       ^~~~~~~~\n  // CHECK:STDERR: fail_todo_earlier_constraint_visible_in_type_parameter.carbon:[[@LINE-7]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n  // CHECK:STDERR:         ^\n  // CHECK:STDERR:\n  let J1:! Z where .Z1 = () and .Z2 = C(.Self);\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\n// CHECK:STDERR: fail_todo_earlier_constraint_visible_in_type_parameter.carbon:[[@LINE+7]]:38: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: impl D as Z where .Z1 = () and .Z2 = C(.Self) {}\n// CHECK:STDERR:                                      ^~~~~~~~\n// CHECK:STDERR: fail_todo_earlier_constraint_visible_in_type_parameter.carbon:[[@LINE-21]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nimpl D as Z where .Z1 = () and .Z2 = C(.Self) {}\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n\n// --- fail_todo_later_constraint_visible_in_type_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\n\nclass C(T:! Z where .Z1 = ()) {}\n\ninterface J {\n  // Implied: .Z1 == (), but this is also explicitly required for J1.\n  // CHECK:STDERR: fail_todo_later_constraint_visible_in_type_parameter.carbon:[[@LINE+7]]:26: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   let J1:! Z where .Z2 = C(.Self) and .Z1 = ();\n  // CHECK:STDERR:                          ^~~~~~~~\n  // CHECK:STDERR: fail_todo_later_constraint_visible_in_type_parameter.carbon:[[@LINE-7]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n  // CHECK:STDERR:         ^\n  // CHECK:STDERR:\n  let J1:! Z where .Z2 = C(.Self) and .Z1 = ();\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\n// CHECK:STDERR: fail_todo_later_constraint_visible_in_type_parameter.carbon:[[@LINE+7]]:38: error: cannot convert type `.Self` that implements `Z` into type implementing `Z where .(Z.Z1) = ()` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: impl D as Z where .Z1 = () and .Z2 = C(.Self) {}\n// CHECK:STDERR:                                      ^~~~~~~~\n// CHECK:STDERR: fail_todo_later_constraint_visible_in_type_parameter.carbon:[[@LINE-21]]:9: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: class C(T:! Z where .Z1 = ()) {}\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nimpl D as Z where .Z1 = () and .Z2 = C(.Self) {}\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n\n// --- early_rewrite_applied.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\n\ninterface Tuple {}\nimpl () as Tuple {}\nclass C(T:! Tuple) {}\n\ninterface J {\n  // Implied: .Z1 == (), but this is also explicitly required for J1.\n  let J1:! Z where .Z1 = () and .Z2 = C(.Z1);\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\nimpl D as Z where .Z1 = () and .Z2 = C(()) {}\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n\n// --- early_rewrite_applied_from_nested_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\n\ninterface Tuple {}\nimpl () as Tuple {}\nclass C(T:! Tuple) {}\n\ninterface J {\n  // Implied: .Z1 == (), but this is also explicitly required for J1.\n  let J1:! (Z where .Z1 = ()) where .Z2 = C(.Z1);\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\nimpl D as Z where .Z1 = () and .Z2 = C(()) {}\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n\n// --- fail_todo_early_rewrite_applied_extra_indirection.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\n\ninterface Y {\n  let Y1:! Z;\n}\n\ninterface Tuple {}\nimpl () as Tuple {}\nclass C(T:! Tuple) {}\n\ninterface J {\n  // Implied: .Z1 == (), but this is also explicitly required for J1.\n  let J1:! Y & Z where .Y1 = .Self and .Z1 = () and .Z2 = C(.Y1.Z1);\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\nimpl D as Z where .Z1 = () and .Z2 = C(()) {}\nimpl D as Y where .Y1 = D {}\n// CHECK:STDERR: fail_todo_early_rewrite_applied_extra_indirection.carbon:[[@LINE+4]]:24: error: cannot convert type `D` into type implementing `Z & Y where .(Y.Y1) = .Self as Z and .(Z.Z1) = () and .(Z.Z2) = C(() as Tuple)` [ConversionFailureTypeToFacet]\n// CHECK:STDERR: fn G(T:! J where .J1 = D) {\n// CHECK:STDERR:                        ^\n// CHECK:STDERR:\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n\n// --- fail_todo_resolved_constraint_visible_in_type_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {\n  let Y1:! type;\n}\n\ninterface Z {\n  let Z1:! Y;\n  let Z2:! type;\n  let Z3:! type;\n}\n\ninterface Tuple {}\nimpl () as Tuple {}\nclass C(T:! Tuple) {}\n\ninterface J {\n  // Implied: .Y1 impls Tuple, but this is also explicitly required for J1.\n  let J1:! Z & Y where .Y1 = () and .Z1 = .Self and .Z2 = .Z1.Y1 and .Z3 = C(.Z2);\n}\n\nfn F(unused T:! J) {}\n\nclass D;\n// Satisfies the implied constraint in J.J1.\nimpl D as Y where .Y1 = () {}\n// CHECK:STDERR: fail_todo_resolved_constraint_visible_in_type_parameter.carbon:[[@LINE+4]]:25: error: cannot convert type `.Self` that implements `Z` into type implementing `Y` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: impl D as Z where .Z1 = .Self and .Z2 = () and .Z3 = C(()) {}\n// CHECK:STDERR:                         ^~~~~\n// CHECK:STDERR:\nimpl D as Z where .Z1 = .Self and .Z2 = () and .Z3 = C(()) {}\n// CHECK:STDERR: fail_todo_resolved_constraint_visible_in_type_parameter.carbon:[[@LINE+4]]:24: error: cannot convert type `D` into type implementing `Y & Z where .(Y.Y1) = () and .(Z.Z1) = .Self as Y and .(Z.Z2) = () and .(Z.Z3) = C(() as Tuple)` [ConversionFailureTypeToFacet]\n// CHECK:STDERR: fn G(T:! J where .J1 = D) {\n// CHECK:STDERR:                        ^\n// CHECK:STDERR:\nfn G(T:! J where .J1 = D) {\n  F(T);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/facet_assoc_const.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/facet_assoc_const.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/facet_assoc_const.carbon\n\n// --- success.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let T:! type; }\n\nfn F(unused T:! I where .T = {}) {}\n\n// --- success_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let T:! type; let U:! type; }\n\nfn F(unused T:! I where .T = .U) {}\n\n// --- fail_two_different.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; }\n\n// CHECK:STDERR: fail_two_different.carbon:[[@LINE+4]]:17: error: associated constant `.(L.W)` given two different values `{}` and `()` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused T:! L where .W = {} and .W = ()) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! L where .W = {} and .W = ()) {}\n\n// --- fail_two_different_first_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; let X:! type; }\n\n// CHECK:STDERR: fail_two_different_first_associated.carbon:[[@LINE+4]]:17: error: associated constant `.(L.W)` given two different values `.(L.X)` and `()` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused T:! L where .W = .X and .W = ()) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! L where .W = .X and .W = ()) {}\n\n// --- fail_two_different_second_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; let X:! type; }\n\n// CHECK:STDERR: fail_two_different_second_associated.carbon:[[@LINE+4]]:17: error: associated constant `.(L.W)` given two different values `()` and `.(L.X)` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused T:! L where .W = () and .W = .X) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! L where .W = () and .W = .X) {}\n\n// --- fail_two_different_first_bad.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; }\n\n// CHECK:STDERR: fail_two_different_first_bad.carbon:[[@LINE+4]]:30: error: name `BAD5` not found [NameNotFound]\n// CHECK:STDERR: fn F(unused T:! L where .W = BAD5 and .W = ()) {}\n// CHECK:STDERR:                              ^~~~\n// CHECK:STDERR:\nfn F(unused T:! L where .W = BAD5 and .W = ()) {}\n\n// --- fail_two_different_second_bad.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; }\n\n// CHECK:STDERR: fail_two_different_second_bad.carbon:[[@LINE+4]]:42: error: name `BAD6` not found [NameNotFound]\n// CHECK:STDERR: fn F(unused T:! L where .W = {} and .W = BAD6) {}\n// CHECK:STDERR:                                          ^~~~\n// CHECK:STDERR:\nfn F(unused T:! L where .W = {} and .W = BAD6) {}\n\n// --- fail_two_different_both_bad.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; }\n\n// CHECK:STDERR: fail_two_different_both_bad.carbon:[[@LINE+8]]:30: error: name `BAD7` not found [NameNotFound]\n// CHECK:STDERR: fn F(unused T:! L where .W = BAD7 and .W = BAD8) {}\n// CHECK:STDERR:                              ^~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_two_different_both_bad.carbon:[[@LINE+4]]:44: error: name `BAD8` not found [NameNotFound]\n// CHECK:STDERR: fn F(unused T:! L where .W = BAD7 and .W = BAD8) {}\n// CHECK:STDERR:                                            ^~~~\n// CHECK:STDERR:\nfn F(unused T:! L where .W = BAD7 and .W = BAD8) {}\n\n// --- fail_two_different_combined_from_bitand.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; }\n\n// CHECK:STDERR: fail_two_different_combined_from_bitand.carbon:[[@LINE+4]]:17: error: associated constant `.(L.W)` given two different values `()` and `{}` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused T:! (L where .W = {}) & (L where .W = ())) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! (L where .W = {}) & (L where .W = ())) {}\n\n// --- two_different_combined_from_impl_and_facet.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; }\n\ninterface M {}\nimpl forall [T:! M] T as L where .W = () {}\n\nfn F(unused T:! M & (L where .W = {})) {}\n\nclass C;\nimpl C as L where .W = {} {}\nimpl C as M {}\n\nfn G() {\n  F(C);\n}\n\n// --- fail_two_different_combined_from_final_impl_and_facet.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; }\n\ninterface M {}\nfinal impl forall [T:! M] T as L where .W = () {}\n\nfn G(T:! M & L, a: T.W) -> () { return a; }\n\nfn H(T:! L where .W = {}, a: T.W) -> {} { return a; }\n\nfn F(T:! M & (L where .W = {}), a: T.W) {\n  // One of `b` or `c` must fail, because `T.W` is either found to be `()` from\n  // the impl or `{}` from the facet type of T.\n\n  let unused b: () = G(T, a);\n  // TODO: This diagnostic sucks. Can we make the facet type's value take\n  // precidence over final, since that's what is written in the code and more\n  // likely to show up in diagnostics? Or should we diagnose `T` as being\n  // invalid directly, where we can see both `.W` values and print them?\n  //\n  // CHECK:STDERR: fail_two_different_combined_from_final_impl_and_facet.carbon:[[@LINE+7]]:22: error: cannot convert type `T` that implements `L & M where .(L.W) = {}` into type implementing `L where .(L.W) = {}` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   let unused c: {} = H(T, a);\n  // CHECK:STDERR:                      ^~~~~~~\n  // CHECK:STDERR: fail_two_different_combined_from_final_impl_and_facet.carbon:[[@LINE-15]]:6: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn H(T:! L where .W = {}, a: T.W) -> {} { return a; }\n  // CHECK:STDERR:      ^\n  // CHECK:STDERR:\n  let unused c: {} = H(T, a);\n}\n\n// --- fail_many_different.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface L { let W:! type; }\n\n// CHECK:STDERR: fail_many_different.carbon:[[@LINE+4]]:17: error: associated constant `.(L.W)` given two different values `((), (), ())` and `({}, (), ())` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn G(unused T:! L where .W = ((), (), ()) and .W = ({}, (), ()) and .W = ({}, {}, ()) and .W = ({}, (), {})) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn G(unused T:! L where .W = ((), (), ()) and .W = ({}, (), ()) and .W = ({}, {}, ()) and .W = ({}, (), {})) {}\n\n// --- rewrite_uses_second_facet.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface M { let X:! type; let Y:! type; }\n\nfn F(T:! M where .X = (), U:! M where .Y = T.X) -> U.Y {\n  return ();\n}\n\n// --- fail_rewrite_conflicts_with_second_facet.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface M { let X:! type; let Y:! type; }\n\n// CHECK:STDERR: fail_rewrite_conflicts_with_second_facet.carbon:[[@LINE+4]]:38: error: associated constant `.(M.Y)` given two different values `T.(M.X)` and `.(M.X)` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(T:! M where .X = (), unused U:! M where .Y = T.X and .Y = .X) {}\n// CHECK:STDERR:                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(T:! M where .X = (), unused U:! M where .Y = T.X and .Y = .X) {}\n\n// --- repeated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface M { let X:! type; }\n\nfn F(unused T:! M where .X = {} and .X = {}) {}\n\nfn G(T:! M where .X = {}) {\n  F(T);\n}\n\n// --- repeated_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface M { let X:! type; let Y:! type; }\n\nfn F(unused T:! M where .X = .Y and .X = .Y) {}\n\nfn G(T:! M where .X = () and .Y = ()) {\n  F(T);\n}\n\n// --- repeated_concrete_value_and_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface M { let X:! type; let Y:! type; }\n\nfn F1(unused T:! M where .X = () and .Y = .X and .X = .Y) {}\n\nfn F2(unused T:! M where .X = () and .X = .X) {}\n\nfn G(T:! M where .X = () and .Y = ()) {\n  F1(T);\n  F2(T);\n}\n\n// --- repeated_with_bitand.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface M { let X:! type; let Y:! type; }\n\nfn F1(T:! (M where .X = .Y) & (M where .X = .Y and .Y = ())) -> T.X {\n  return ();\n}\n\nfn F2(T:! (M where .X = .Y and .Y = ()) & (M where .X = .Y)) -> T.X {\n  return ();\n}\n\n// --- fail_repeated_and_different.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface M { let X:! type; }\n\n// CHECK:STDERR: fail_repeated_and_different.carbon:[[@LINE+4]]:17: error: associated constant `.(M.X)` given two different values `{}` and `()` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused T:! M where .X = {} and .X = () and .X = {}) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! M where .X = {} and .X = () and .X = {}) {}\n\n// --- fail_cycle_single.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface M { let X:! type; }\n\n// This fails because it resolves to `.X = .X` which is cyclical.\n//\n// CHECK:STDERR: fail_cycle_single.carbon:[[@LINE+4]]:17: error: found cycle in facet type constraint for `.(M.X)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn F(unused T:! M where .X = .X) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! M where .X = .X) {}\n\n// Even though `.X = ()` is specified, the rewrites are resolved left to right\n// and a cycle `.X = .X` is found first.\n//\n// CHECK:STDERR: fail_cycle_single.carbon:[[@LINE+4]]:17: error: found cycle in facet type constraint for `.(M.X)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn G(unused T:! M where .X = .X and .X = ()) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn G(unused T:! M where .X = .X and .X = ()) {}\n\n// --- fail_cycle.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface M { let X:! type; let Y:! type; let Z:! type; }\n\n// This fails because it resolves to `.X = .X` which is cyclical.\n// The value of .X and .Y becomes <error> but .Z is still valid.\n//\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_cycle.carbon:[[@LINE+4]]:17: error: found cycle in facet type constraint for `.(M.Y)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn F(unused T:! M where .X = .Y and .Y = .X and .Z = ()) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! M where .X = .Y and .Y = .X and .Z = ()) {}\n//@dump-sem-ir-end\n\n// --- fail_cycle_between_interfaces.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n}\ninterface J {\n  let X3:! type;\n}\n\n// This fails because it resolves to `.X1 = .X1` which is cyclical.\n//\n// CHECK:STDERR: fail_cycle_between_interfaces.carbon:[[@LINE+4]]:17: error: found cycle in facet type constraint for `.(J.X3)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn G(unused T:! I & J where .X1 = .X3 and .X2 = .X1 and .X3 = .X2) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn G(unused T:! I & J where .X1 = .X3 and .X2 = .X1 and .X3 = .X2) {}\n\n// --- fail_indirect_cycle.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n}\n\n// This fails because it resolves to `.X1 = .X1**` which is cyclical.\n//\n// CHECK:STDERR: fail_indirect_cycle.carbon:[[@LINE+4]]:10: error: found cycle in facet type constraint for `.(I.X2)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn F(T:! I where .X1 = .X2* and .X2 = .X1*);\n// CHECK:STDERR:          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(T:! I where .X1 = .X2* and .X2 = .X1*);\n\nclass C(T:! type);\n// This fails because it resolves to `.X1 = C(C(.X1))` which is cyclical.\n//\n// CHECK:STDERR: fail_indirect_cycle.carbon:[[@LINE+4]]:10: error: found cycle in facet type constraint for `.(I.X2)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn G(T:! I where .X1 = C(.X2) and .X2 = C(.X1));\n// CHECK:STDERR:          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn G(T:! I where .X1 = C(.X2) and .X2 = C(.X1));\n\n// --- fail_complex_indirect_cycle.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n  let X3:! type;\n}\n\nclass C(T:! type, U:! type);\n\n// This fails because it resolves to `.X1 = C(C(.X3, .X1), .X3)` which is\n// cyclical.\n//\n// CHECK:STDERR: fail_complex_indirect_cycle.carbon:[[@LINE+4]]:10: error: found cycle in facet type constraint for `.(I.X2)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn F(T:! I where .X1 = C(.X2, .X3) and .X2 = C(.X3, .X1));\n// CHECK:STDERR:          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(T:! I where .X1 = C(.X2, .X3) and .X2 = C(.X3, .X1));\n\n// --- exponential_large.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T0:! type;\n  let T1:! type;\n  let T2:! type;\n  let T3:! type;\n  let T4:! type;\n  let T5:! type;\n  let T6:! type;\n  let T7:! type;\n  let T8:! type;\n  let T9:! type;\n}\n\n// A naive attempt to resolve the rewrite rules will run take minutes to\n// complete, since the resulting RHS values are exponential in size, and a naive\n// approach can recursively rebuild the RHS values from the ground up\n// repeatedly.\nfn F(\n    T:! Z where\n      .T0 = (.T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1) and\n      .T1 = (.T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2) and\n      .T2 = (.T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3) and\n      .T3 = (.T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4) and\n      .T4 = (.T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5) and\n      .T5 = (.T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6) and\n      .T6 = (.T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7) and\n      .T7 = (.T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8) and\n      .T8 = (.T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9) and\n      .T9 = ()\n    );\n\n// --- fail_exponential_large_cycle.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T0:! type;\n  let T1:! type;\n  let T2:! type;\n  let T3:! type;\n  let T4:! type;\n  let T5:! type;\n  let T6:! type;\n  let T7:! type;\n  let T8:! type;\n  let T9:! type;\n}\n\n// A naive attempt to resolve the rewrite rules will run take minutes to\n// complete, since the resulting RHS values are exponential in size, and a naive\n// approach can recursively rebuild the RHS values from the ground up\n// repeatedly.\nfn F(\n    // CHECK:STDERR: fail_exponential_large_cycle.carbon:[[@LINE+4]]:9: error: found cycle in facet type constraint for `.(Z.T0)` [FacetTypeConstraintCycle]\n    // CHECK:STDERR:     T:! Z where\n    // CHECK:STDERR:         ^~~~~~~\n    // CHECK:STDERR:\n    T:! Z where\n      .T9 = .T0 and\n      .T8 = (.T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9, .T9) and\n      .T7 = (.T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8, .T8) and\n      .T6 = (.T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7, .T7) and\n      .T5 = (.T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6, .T6) and\n      .T4 = (.T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5, .T5) and\n      .T3 = (.T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4, .T4) and\n      .T2 = (.T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3, .T3) and\n      .T1 = (.T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2, .T2) and\n      .T0 = (.T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1, .T1)\n    );\n\n// --- non-type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface N {\n  let Y:! {.a: {}};\n}\n\nfn F(unused T:! N where .Y = {.a = {}}) { }\n\n// --- non-type_repeated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface N {\n  let Y:! {.a: {}};\n}\n\nfn F(unused T:! N where .Y = {.a = {}} and .Y = {.a = {}}) { }\n\n// --- fail_non-type_different.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface N {\n  let Y:! {.a: type};\n}\n\n// CHECK:STDERR: fail_non-type_different.carbon:[[@LINE+4]]:17: error: associated constant `.(N.Y)` given two different values `{.a = {}}` and `{.a = ()}` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused T:! N where .Y = {.a = {}} and .Y = {.a = ()}) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! N where .Y = {.a = {}} and .Y = {.a = ()}) {}\n\n// --- self_repeated_explicitly.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface N {\n  let Y1:! type;\n  let Y2:! type;\n}\n\nfn F(unused T:! N where .Y2 = .Y1 and .Y2 = .Self.Y1) { }\n\n// --- self_repeated_explicitly_with_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface N {\n  let Y1:! type;\n  let Y2:! type;\n}\n\nfn F(unused T:! N where .Y1 = () and .Y2 = .Y1 and .Y2 = .Self.Y1) { }\n\n// --- fail_cycle_through_self_reference.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! Z;\n}\n\n// CHECK:STDERR: fail_cycle_through_self_reference.carbon:[[@LINE+4]]:17: error: found cycle in facet type constraint for `.(Z.T)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn F(unused A:! Z where .T = .U.T and .U = .Self) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused A:! Z where .T = .U.T and .U = .Self) {}\n\n// --- reference_same_constant_in_different_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! Z;\n}\n\nfn F(A:! Z where .T = (), unused B:! Z where .T = .U.T and .U = A) {}\n\n// --- non_cycle_with_self_reference.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n  let V:! Z;\n}\n\nfn F(A:! Z where .T = .V.U and .V = .Self and .U = ()) -> A.T {\n  return ();\n}\n\n// --- fail_cycle_with_unrelated_associated_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T0:! type;\n  let T1:! type;\n  let T2:! type;\n  let T3:! type;\n}\n\n// CHECK:STDERR: fail_cycle_with_unrelated_associated_constant.carbon:[[@LINE+4]]:17: error: found cycle in facet type constraint for `.(Z.T1)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn F(unused T:! Z where .T0 = .T1 and .T1 = .T0 and .T2 = .T3) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! Z where .T0 = .T1 and .T1 = .T0 and .T2 = .T3) {}\n\n// --- fail_cycle_with_branching_in_rhs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T0:! type;\n  let T1:! type;\n  let T2:! type;\n  let T3:! type;\n  let T4:! type;\n}\n\n// TODO: There should only be one diagnostic here.\n//\n// CHECK:STDERR: fail_cycle_with_branching_in_rhs.carbon:[[@LINE+4]]:17: error: found cycle in facet type constraint for `.(Z.T3)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn F(unused T:! Z where .T0 = .T1 and .T1 = (.T2, .T3) and .T2 = .T4 and .T3 = .T1) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused T:! Z where .T0 = .T1 and .T1 = (.T2, .T3) and .T2 = .T4 and .T3 = .T1) {}\n\n// CHECK:STDERR: fail_cycle_with_branching_in_rhs.carbon:[[@LINE+4]]:17: error: found cycle in facet type constraint for `.(Z.T1)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn G(unused T:! Z where .T0 = .T1 and .T1 = (.T2, .T3) and .T2 = .T4 and .T3 = .T0) {}\n// CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn G(unused T:! Z where .T0 = .T1 and .T1 = (.T2, .T3) and .T2 = .T4 and .T3 = .T0) {}\n\n// --- no_cycle_with_branching_in_rhs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T0:! type;\n  let T1:! type;\n  let T2:! type;\n  let T3:! type;\n  let T4:! type;\n  let T5:! type;\n}\n\n// These create misdiagnostics if the resolving algorithms messes up tracking\n// its stack during replacements by leaving either of .T2 or .T3 on the stack\n// (from the RHS of .T1) while resolving the other. Or it can fail to apply the\n// () up the chain correctly.\n\nfn F(T:! Z where .T0 = .T1 and .T1 = (.T2, .T3) and .T2 = .T4 and .T4 = () and .T3 = .T2) -> T.T0 {\n  return ((), ());\n}\n\nfn G(T:! Z where .T0 = .T1 and .T1 = (.T2, .T3) and .T2 = .T4 and .T4 = .T5 and .T5 = () and .T3 = .T2) -> T.T0 {\n  return ((), ());\n}\n\nfn H(T:! Z where .T0 = .T1 and .T1 = (.T2, .T3) and .T2 = (.T4, ()) and .T3 = .T2 and .T4 = {}) -> T.T0 {\n  return (({}, ()), ({}, ()));\n}\n\nfn I(T:! Z where .T0 = .T1 and .T1 = (.T2, .T3) and .T2 = .T4 and .T3 = .T2 and .T4 = ()) -> T.T0 {\n  return ((), ());\n}\n\nfn J(T:! Z where .T0 = .T1 and .T1 = (.T2, .T3) and .T2 = .T4 and .T4 = .T5 and .T3 = .T2 and .T5 = ()) -> T.T0 {\n  return ((), ());\n}\n\n// --- indirection_through_self_rhs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n  let I2:! type;\n}\n\ninterface J {\n  let J1:! I;\n}\n\n// The value of .I1 is (), but to know that requires resolving .J1 first then\n// .J1.I2.\nfn F(T:! I & J where .J1 = .Self and .I1 = .J1.I2 and .I2 = ()) -> T.I1 {\n  return ();\n}\n\n// --- indirection_through_not_self_rhs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n  let I2:! type;\n}\n\ninterface J {\n  let J1:! I;\n}\n\n// The value of .I1 is (), but to know that requires resolving .J1 first then\n// .J1.I2.\nfn F(U:! I where .I2 = (), T:! I & J where .J1 = U and .I1 = .J1.I2) -> T.I1 {\n  return ();\n}\n\n// --- indirection_through_unresolved_access_rhs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n  let I2:! type;\n}\n\ninterface J {\n  let J1:! I;\n}\n\n// If we assume the nested `.J1` access will resolve to a facet value, we may\n// loop forever trying to resolve the `.I2` access. We should gracefully accept\n// that it does not resolve further.\nfn F(unused T:! I & J where .I1 = .J1.I2) {}\n\n// CHECK:STDOUT: --- fail_cycle.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %M.type: type = facet_type <@M> [concrete]\n// CHECK:STDOUT:   %M.assoc_type: type = assoc_entity_type @M [concrete]\n// CHECK:STDOUT:   %assoc0: %M.assoc_type = assoc_entity element0, @M.WithSelf.%X [concrete]\n// CHECK:STDOUT:   %assoc1: %M.assoc_type = assoc_entity element1, @M.WithSelf.%Y [concrete]\n// CHECK:STDOUT:   %assoc2: %M.assoc_type = assoc_entity element2, @M.WithSelf.%Z [concrete]\n// CHECK:STDOUT:   %.Self.b4d: %M.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.b4d [symbolic_self]\n// CHECK:STDOUT:   %M.lookup_impl_witness: <witness> = lookup_impl_witness %.Self.b4d, @M [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %M.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %impl.elem1: type = impl_witness_access %M.lookup_impl_witness, element1 [symbolic_self]\n// CHECK:STDOUT:   %impl.elem2: type = impl_witness_access %M.lookup_impl_witness, element2 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: <error> = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc13_19.1: type = splice_block %.loc13_19.2 [concrete = <error>] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %M.ref: type = name_ref M, file.%M.decl [concrete = constants.%M.type]\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.Self.ref.loc13_25: %M.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.b4d]\n// CHECK:STDOUT:       %.Self.as_type.loc13_25: type = facet_access_type %.Self.ref.loc13_25 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc13_25: type = converted %.Self.ref.loc13_25, %.Self.as_type.loc13_25 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %X.ref.loc13_25: %M.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:       %impl.elem0.loc13_25: type = impl_witness_access constants.%M.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:       %.Self.ref.loc13_30: %M.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.b4d]\n// CHECK:STDOUT:       %.Self.as_type.loc13_30: type = facet_access_type %.Self.ref.loc13_30 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc13_30: type = converted %.Self.ref.loc13_30, %.Self.as_type.loc13_30 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %Y.ref.loc13_30: %M.assoc_type = name_ref Y, @Y.%assoc1 [concrete = constants.%assoc1]\n// CHECK:STDOUT:       %impl.elem1.loc13_30: type = impl_witness_access constants.%M.lookup_impl_witness, element1 [symbolic_self = constants.%impl.elem1]\n// CHECK:STDOUT:       %.Self.ref.loc13_37: %M.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.b4d]\n// CHECK:STDOUT:       %.Self.as_type.loc13_37: type = facet_access_type %.Self.ref.loc13_37 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc13_37: type = converted %.Self.ref.loc13_37, %.Self.as_type.loc13_37 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %Y.ref.loc13_37: %M.assoc_type = name_ref Y, @Y.%assoc1 [concrete = constants.%assoc1]\n// CHECK:STDOUT:       %impl.elem1.loc13_37: type = impl_witness_access constants.%M.lookup_impl_witness, element1 [symbolic_self = constants.%impl.elem1]\n// CHECK:STDOUT:       %.Self.ref.loc13_42: %M.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.b4d]\n// CHECK:STDOUT:       %.Self.as_type.loc13_42: type = facet_access_type %.Self.ref.loc13_42 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc13_42: type = converted %.Self.ref.loc13_42, %.Self.as_type.loc13_42 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %X.ref.loc13_42: %M.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:       %impl.elem0.loc13_42: type = impl_witness_access constants.%M.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:       %impl.elem0.subst: type = impl_witness_access_substituted %impl.elem0.loc13_42, %impl.elem1.loc13_30 [symbolic_self = constants.%impl.elem1]\n// CHECK:STDOUT:       %.Self.ref.loc13_49: %M.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.b4d]\n// CHECK:STDOUT:       %.Self.as_type.loc13_49: type = facet_access_type %.Self.ref.loc13_49 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc13_49: type = converted %.Self.ref.loc13_49, %.Self.as_type.loc13_49 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %Z.ref: %M.assoc_type = name_ref Z, @Z.%assoc2 [concrete = constants.%assoc2]\n// CHECK:STDOUT:       %impl.elem2: type = impl_witness_access constants.%M.lookup_impl_witness, element2 [symbolic_self = constants.%impl.elem2]\n// CHECK:STDOUT:       %.loc13_55.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc13_55.2: type = converted %.loc13_55.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.loc13_19.2: type = where_expr %.Self.2 [concrete = <error>] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%M.type\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc13_25, %impl.elem1.loc13_30\n// CHECK:STDOUT:         requirement_rewrite %impl.elem1.loc13_37, %impl.elem0.subst\n// CHECK:STDOUT:         requirement_rewrite %impl.elem2, %.loc13_55.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T: <error> = symbolic_binding T, 0 [concrete = <error>]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T: <error>) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(<error>) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/fail_convert_class_type_to_generic_facet_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/fail_convert_class_type_to_generic_facet_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/fail_convert_class_type_to_generic_facet_value.carbon\n\ninterface Generic(Scalar:! type) {\n  fn F();\n}\n\nclass GenericParam {}\nclass WrongGenericParam {}\n\nclass ImplsGeneric {}\nimpl ImplsGeneric as Generic(GenericParam) {\n  fn F() {}\n}\n\nfn CallGenericMethod(T:! type, unused U:! Generic(T)) {}\n\nfn G() {\n  // CHECK:STDERR: fail_convert_class_type_to_generic_facet_value.carbon:[[@LINE+7]]:3: error: cannot convert type `ImplsGeneric` into type implementing `Generic(WrongGenericParam)` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   CallGenericMethod(WrongGenericParam, ImplsGeneric);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_convert_class_type_to_generic_facet_value.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn CallGenericMethod(T:! type, unused U:! Generic(T)) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  CallGenericMethod(WrongGenericParam, ImplsGeneric);\n}\n\n// CHECK:STDOUT: --- fail_convert_class_type_to_generic_facet_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %Scalar: type = symbolic_binding Scalar, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.835: type = generic_interface_type @Generic [concrete]\n// CHECK:STDOUT:   %Generic.generic: %Generic.type.835 = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.type.03dff7.1: type = facet_type <@Generic, @Generic(%Scalar)> [symbolic]\n// CHECK:STDOUT:   %Self.15d: %Generic.type.03dff7.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.743: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%Scalar, %Self.15d) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.baf: %Generic.WithSelf.F.type.743 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.22a: type = assoc_entity_type @Generic, @Generic(%Scalar) [symbolic]\n// CHECK:STDOUT:   %assoc0.e0d: %Generic.assoc_type.22a = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %GenericParam: type = class_type @GenericParam [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %WrongGenericParam: type = class_type @WrongGenericParam [concrete]\n// CHECK:STDOUT:   %ImplsGeneric: type = class_type @ImplsGeneric [concrete]\n// CHECK:STDOUT:   %Generic.type.498: type = facet_type <@Generic, @Generic(%GenericParam)> [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness @ImplsGeneric.as.Generic.impl.%Generic.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.1f5: %Generic.type.498 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.a23: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Self.15d) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.fe0: %Generic.WithSelf.F.type.a23 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.6dc: type = assoc_entity_type @Generic, @Generic(%GenericParam) [concrete]\n// CHECK:STDOUT:   %assoc0.717: %Generic.assoc_type.6dc = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.type: type = fn_type @ImplsGeneric.as.Generic.impl.F [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F: %ImplsGeneric.as.Generic.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value %ImplsGeneric, (%Generic.impl_witness) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.c86: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.1fd: %Generic.WithSelf.F.type.c86 = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.03dff7.2: type = facet_type <@Generic, @Generic(%T)> [symbolic]\n// CHECK:STDOUT:   %pattern_type.c49: type = pattern_type %Generic.type.03dff7.2 [symbolic]\n// CHECK:STDOUT:   %U: %Generic.type.03dff7.2 = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %CallGenericMethod.type: type = fn_type @CallGenericMethod [concrete]\n// CHECK:STDOUT:   %CallGenericMethod: %CallGenericMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Generic = %Generic.decl\n// CHECK:STDOUT:     .GenericParam = %GenericParam.decl\n// CHECK:STDOUT:     .WrongGenericParam = %WrongGenericParam.decl\n// CHECK:STDOUT:     .ImplsGeneric = %ImplsGeneric.decl\n// CHECK:STDOUT:     .CallGenericMethod = %CallGenericMethod.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Generic.decl: %Generic.type.835 = interface_decl @Generic [concrete = constants.%Generic.generic] {\n// CHECK:STDOUT:     %Scalar.patt: %pattern_type.98f = symbolic_binding_pattern Scalar, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_28.1: type = splice_block %.loc15_28.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_28.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Scalar.loc15_19.2: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc15_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %GenericParam.decl: type = class_decl @GenericParam [concrete = constants.%GenericParam] {} {}\n// CHECK:STDOUT:   %WrongGenericParam.decl: type = class_decl @WrongGenericParam [concrete = constants.%WrongGenericParam] {} {}\n// CHECK:STDOUT:   %ImplsGeneric.decl: type = class_decl @ImplsGeneric [concrete = constants.%ImplsGeneric] {} {}\n// CHECK:STDOUT:   impl_decl @ImplsGeneric.as.Generic.impl [concrete] {} {\n// CHECK:STDOUT:     %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:     %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:     %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:     %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.498]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallGenericMethod.decl: %CallGenericMethod.type = fn_decl @CallGenericMethod [concrete = constants.%CallGenericMethod] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: @CallGenericMethod.%pattern_type (%pattern_type.c49) = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc27_26.1: type = splice_block %.loc27_26.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc27_26.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc27_22.2: type = symbolic_binding T, 0 [symbolic = %T.loc27_22.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc27_52: type = splice_block %Generic.type.loc27_52.2 [symbolic = %Generic.type.loc27_52.1 (constants.%Generic.type.03dff7.2)] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc27_22.2 [symbolic = %T.loc27_22.1 (constants.%T)]\n// CHECK:STDOUT:       %Generic.type.loc27_52.2: type = facet_type <@Generic, @Generic(constants.%T)> [symbolic = %Generic.type.loc27_52.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc27_39.2: @CallGenericMethod.%Generic.type.loc27_52.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc27_39.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @Generic(%Scalar.loc15_19.2: type) {\n// CHECK:STDOUT:   %Scalar.loc15_19.1: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc15_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type: type = facet_type <@Generic, @Generic(%Scalar.loc15_19.1)> [symbolic = %Generic.type (constants.%Generic.type.03dff7.1)]\n// CHECK:STDOUT:   %Self.loc15_34.2: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc15_34.2 (constants.%Self.15d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc15_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc15_34.2 (constants.%Self.15d)]\n// CHECK:STDOUT:     %Generic.WithSelf.decl = interface_with_self_decl @Generic [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %Generic.WithSelf.F.decl: @Generic.WithSelf.%Generic.WithSelf.F.type (%Generic.WithSelf.F.type.743) = fn_decl @Generic.WithSelf.F [symbolic = @Generic.WithSelf.%Generic.WithSelf.F (constants.%Generic.WithSelf.F.baf)] {} {}\n// CHECK:STDOUT:     %assoc0.loc16_9.1: @Generic.WithSelf.%Generic.assoc_type (%Generic.assoc_type.22a) = assoc_entity element0, %Generic.WithSelf.F.decl [symbolic = %assoc0.loc16_9.2 (constants.%assoc0.e0d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc15_34.1\n// CHECK:STDOUT:     .F = @Generic.WithSelf.%assoc0.loc16_9.1\n// CHECK:STDOUT:     witness = (@Generic.WithSelf.%Generic.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @ImplsGeneric.as.Generic.impl: %ImplsGeneric.ref as %Generic.type {\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.decl: %ImplsGeneric.as.Generic.impl.F.type = fn_decl @ImplsGeneric.as.Generic.impl.F [concrete = constants.%ImplsGeneric.as.Generic.impl.F] {} {}\n// CHECK:STDOUT:   %Generic.impl_witness_table = impl_witness_table (%ImplsGeneric.as.Generic.impl.F.decl), @ImplsGeneric.as.Generic.impl [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness %Generic.impl_witness_table [concrete = constants.%Generic.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %ImplsGeneric.as.Generic.impl.F.decl\n// CHECK:STDOUT:   witness = %Generic.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @GenericParam {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%GenericParam\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @WrongGenericParam {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%WrongGenericParam\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ImplsGeneric {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%ImplsGeneric\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Generic.WithSelf.F(@Generic.%Scalar.loc15_19.2: type, @Generic.%Self.loc15_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1)) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImplsGeneric.as.Generic.impl.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallGenericMethod(%T.loc27_22.2: type, %U.loc27_39.2: @CallGenericMethod.%Generic.type.loc27_52.1 (%Generic.type.03dff7.2)) {\n// CHECK:STDOUT:   %T.loc27_22.1: type = symbolic_binding T, 0 [symbolic = %T.loc27_22.1 (constants.%T)]\n// CHECK:STDOUT:   %Generic.type.loc27_52.1: type = facet_type <@Generic, @Generic(%T.loc27_22.1)> [symbolic = %Generic.type.loc27_52.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:   %U.loc27_39.1: @CallGenericMethod.%Generic.type.loc27_52.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc27_39.1 (constants.%U)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Generic.type.loc27_52.1 [symbolic = %pattern_type (constants.%pattern_type.c49)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod]\n// CHECK:STDOUT:   %WrongGenericParam.ref: type = name_ref WrongGenericParam, file.%WrongGenericParam.decl [concrete = constants.%WrongGenericParam]\n// CHECK:STDOUT:   %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%Scalar) {\n// CHECK:STDOUT:   %Scalar.loc15_19.1 => constants.%Scalar\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%Scalar, constants.%Self.15d) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%Scalar, constants.%Self.15d) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%GenericParam) {\n// CHECK:STDOUT:   %Scalar.loc15_19.1 => constants.%GenericParam\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self.loc15_34.2 => constants.%Self.1f5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Self.15d) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Self.15d\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.a23\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.fe0\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc16_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Generic.facet\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.c86\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.1fd\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc16_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%GenericParam, constants.%Generic.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%T) {\n// CHECK:STDOUT:   %Scalar.loc15_19.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc27_22.1 => constants.%T\n// CHECK:STDOUT:   %Generic.type.loc27_52.1 => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %U.loc27_39.1 => constants.%U\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.c49\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%WrongGenericParam) {\n// CHECK:STDOUT:   %Scalar.loc15_19.1 => constants.%WrongGenericParam\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/fail_convert_facet_value_to_missing_impl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/fail_convert_facet_value_to_missing_impl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/fail_convert_facet_value_to_missing_impl.carbon\n\ninterface Eats {}\ninterface Animal {}\n\nfn Feed[T:! Eats](unused e: T) {}\n\n// CHECK:STDERR: fail_convert_facet_value_to_missing_impl.carbon:[[@LINE+7]]:37: error: cannot convert type `T` that implements `Animal` into type implementing `Eats` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: fn HandleAnimal[T:! Animal](a: T) { Feed(a); }\n// CHECK:STDERR:                                     ^~~~~~~\n// CHECK:STDERR: fail_convert_facet_value_to_missing_impl.carbon:[[@LINE-5]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n// CHECK:STDERR: fn Feed[T:! Eats](unused e: T) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn HandleAnimal[T:! Animal](a: T) { Feed(a); }\n\n// CHECK:STDOUT: --- fail_convert_facet_value_to_missing_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Eats.type: type = facet_type <@Eats> [concrete]\n// CHECK:STDOUT:   %Self.247: %Eats.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self.c49: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.0dc: type = pattern_type %Eats.type [concrete]\n// CHECK:STDOUT:   %T.f11: %Eats.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.265: type = symbolic_binding_type T, 0, %T.f11 [symbolic]\n// CHECK:STDOUT:   %pattern_type.93e: type = pattern_type %T.binding.as_type.265 [symbolic]\n// CHECK:STDOUT:   %Feed.type: type = fn_type @Feed [concrete]\n// CHECK:STDOUT:   %Feed: %Feed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.9d9: <witness> = require_complete_type %T.binding.as_type.265 [symbolic]\n// CHECK:STDOUT:   %pattern_type.e10: type = pattern_type %Animal.type [concrete]\n// CHECK:STDOUT:   %T.998: %Animal.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.e4f: type = symbolic_binding_type T, 0, %T.998 [symbolic]\n// CHECK:STDOUT:   %pattern_type.892: type = pattern_type %T.binding.as_type.e4f [symbolic]\n// CHECK:STDOUT:   %HandleAnimal.type: type = fn_type @HandleAnimal [concrete]\n// CHECK:STDOUT:   %HandleAnimal: %HandleAnimal.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.72f: <witness> = require_complete_type %T.binding.as_type.e4f [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Eats = %Eats.decl\n// CHECK:STDOUT:     .Animal = %Animal.decl\n// CHECK:STDOUT:     .Feed = %Feed.decl\n// CHECK:STDOUT:     .HandleAnimal = %HandleAnimal.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Eats.decl: type = interface_decl @Eats [concrete = constants.%Eats.type] {} {}\n// CHECK:STDOUT:   %Animal.decl: type = interface_decl @Animal [concrete = constants.%Animal.type] {} {}\n// CHECK:STDOUT:   %Feed.decl: %Feed.type = fn_decl @Feed [concrete = constants.%Feed] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.0dc = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %e.patt: @Feed.%pattern_type (%pattern_type.93e) = value_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.param_patt: @Feed.%pattern_type (%pattern_type.93e) = value_param_pattern %e.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc18_13: type = splice_block %Eats.ref [concrete = constants.%Eats.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Eats.ref: type = name_ref Eats, file.%Eats.decl [concrete = constants.%Eats.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc18_9.2: %Eats.type = symbolic_binding T, 0 [symbolic = %T.loc18_9.1 (constants.%T.f11)]\n// CHECK:STDOUT:     %e.param: @Feed.%T.binding.as_type (%T.binding.as_type.265) = value_param call_param0\n// CHECK:STDOUT:     %.loc18_29.1: type = splice_block %.loc18_29.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.265)] {\n// CHECK:STDOUT:       %T.ref: %Eats.type = name_ref T, %T.loc18_9.2 [symbolic = %T.loc18_9.1 (constants.%T.f11)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type.265)]\n// CHECK:STDOUT:       %.loc18_29.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type.265)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %e: @Feed.%T.binding.as_type (%T.binding.as_type.265) = value_binding e, %e.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %HandleAnimal.decl: %HandleAnimal.type = fn_decl @HandleAnimal [concrete = constants.%HandleAnimal] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.e10 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @HandleAnimal.%pattern_type (%pattern_type.892) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @HandleAnimal.%pattern_type (%pattern_type.892) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc27_21: type = splice_block %Animal.ref [concrete = constants.%Animal.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Animal.ref: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc27_17.2: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc27_17.1 (constants.%T.998)]\n// CHECK:STDOUT:     %a.param: @HandleAnimal.%T.binding.as_type (%T.binding.as_type.e4f) = value_param call_param0\n// CHECK:STDOUT:     %.loc27_32.1: type = splice_block %.loc27_32.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)] {\n// CHECK:STDOUT:       %T.ref: %Animal.type = name_ref T, %T.loc27_17.2 [symbolic = %T.loc27_17.1 (constants.%T.998)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)]\n// CHECK:STDOUT:       %.loc27_32.2: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @HandleAnimal.%T.binding.as_type (%T.binding.as_type.e4f) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Eats {\n// CHECK:STDOUT:   %Self: %Eats.type = symbolic_binding Self, 0 [symbolic = constants.%Self.247]\n// CHECK:STDOUT:   %Eats.WithSelf.decl = interface_with_self_decl @Eats [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c49]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Feed(%T.loc18_9.2: %Eats.type) {\n// CHECK:STDOUT:   %T.loc18_9.1: %Eats.type = symbolic_binding T, 0 [symbolic = %T.loc18_9.1 (constants.%T.f11)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc18_9.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.265)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.93e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.9d9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%e.param: @Feed.%T.binding.as_type (%T.binding.as_type.265)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @HandleAnimal(%T.loc27_17.2: %Animal.type) {\n// CHECK:STDOUT:   %T.loc27_17.1: %Animal.type = symbolic_binding T, 0 [symbolic = %T.loc27_17.1 (constants.%T.998)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc27_17.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.e4f)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.892)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.72f)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @HandleAnimal.%T.binding.as_type (%T.binding.as_type.e4f)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %Feed.ref: %Feed.type = name_ref Feed, file.%Feed.decl [concrete = constants.%Feed]\n// CHECK:STDOUT:     %a.ref: @HandleAnimal.%T.binding.as_type (%T.binding.as_type.e4f) = name_ref a, %a\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Eats.WithSelf(constants.%Self.247) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self.c49) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Feed(constants.%T.f11) {\n// CHECK:STDOUT:   %T.loc18_9.1 => constants.%T.f11\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.265\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.93e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HandleAnimal(constants.%T.998) {\n// CHECK:STDOUT:   %T.loc27_17.1 => constants.%T.998\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.e4f\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.892\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/fail_convert_type_erased_type_to_facet.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/fail_convert_type_erased_type_to_facet.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/fail_convert_type_erased_type_to_facet.carbon\n\ninterface Animal {}\n\nclass Goat {}\nimpl Goat as Animal {}\n\nfn WalkAnimal(unused a:! Animal) {}\n\nfn F() {\n  // CHECK:STDERR: fail_convert_type_erased_type_to_facet.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let x:! type = Goat;\n  // CHECK:STDERR:       ^~~~~~~~\n  // CHECK:STDERR:\n  let x:! type = Goat;\n  WalkAnimal(x);\n}\n\n// CHECK:STDOUT: --- fail_convert_type_erased_type_to_facet.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Animal.type: type = facet_type <@Animal> [concrete]\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Goat: type = class_type @Goat [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Animal.impl_witness: <witness> = impl_witness <unexpected>.inst{{[0-9A-F]+}}.loc18_21 [concrete]\n// CHECK:STDOUT:   %Animal.facet: %Animal.type = facet_value %Goat, (%Animal.impl_witness) [concrete]\n// CHECK:STDOUT:   %a: %Animal.type = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Animal {\n// CHECK:STDOUT:   %Self: %Animal.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Animal.WithSelf.decl = interface_with_self_decl @Animal [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @<null name>: <unexpected>.inst{{[0-9A-F]+}}.loc18_6 as <unexpected>.inst{{[0-9A-F]+}}.loc18_14 {\n// CHECK:STDOUT:   impl_witness_table (), @<null name> [concrete]\n// CHECK:STDOUT:   <unexpected>.inst{{[0-9A-F]+}}.loc18_21: <witness> = impl_witness <unexpected>.inst{{[0-9A-F]+}}.loc18_21 [concrete = constants.%Animal.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <unexpected>.inst{{[0-9A-F]+}}.loc18_21\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Goat {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Goat\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @WalkAnimal(<unexpected>.inst{{[0-9A-F]+}}.loc20_22: %Animal.type) {\n// CHECK:STDOUT:   %a: %Animal.type = symbolic_binding a, 0 [symbolic = %a (constants.%a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Animal.WithSelf(constants.%Animal.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WalkAnimal(constants.%a) {\n// CHECK:STDOUT:   %a => constants.%a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/fail_deduction_uses_runtime_type_conversion.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/fail_deduction_uses_runtime_type_conversion.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/fail_deduction_uses_runtime_type_conversion.carbon\n\n// Uses a tuple to allow using the inner type as a type that isn't directly\n// deducible, without deducing through HoldsType.\nclass HoldsType(T:! (type, )) {}\n\nclass RuntimeConvertFrom {}\nclass RuntimeConvertTo {}\n\nimpl RuntimeConvertFrom as Core.ImplicitAs(RuntimeConvertTo) {\n  // Runtime conversion function\n  fn Convert[unused self: Self]() -> RuntimeConvertTo { return {}; }\n}\n\nfn F[T:! (type, )](unused A:! T.0, unused x: HoldsType(T)) {}\n\nfn G(holds_to: HoldsType((RuntimeConvertTo, )), from:! RuntimeConvertFrom) {\n  // CHECK:STDERR: fail_deduction_uses_runtime_type_conversion.carbon:[[@LINE+10]]:3: error: compile-time value requires runtime conversion, constructing value of type `RuntimeConvertTo` [RuntimeConversionDuringCompTimeDeduction]\n  // CHECK:STDERR:   F(from, holds_to);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduction_uses_runtime_type_conversion.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn F[T:! (type, )](unused A:! T.0, unused x: HoldsType(T)) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduction_uses_runtime_type_conversion.carbon:[[@LINE-9]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn F[T:! (type, )](unused A:! T.0, unused x: HoldsType(T)) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  F(from, holds_to);\n}\n\n// CHECK:STDOUT: --- fail_deduction_uses_runtime_type_conversion.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple.0d2: %tuple.type = tuple_value (type) [concrete]\n// CHECK:STDOUT:   %pattern_type.f1e: type = pattern_type %tuple.type [concrete]\n// CHECK:STDOUT:   %T: %tuple.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %HoldsType.type: type = generic_class_type @HoldsType [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %HoldsType.generic: %HoldsType.type = struct_value () [concrete]\n// CHECK:STDOUT:   %HoldsType.f6a: type = class_type @HoldsType, @HoldsType(%T) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %RuntimeConvertFrom: type = class_type @RuntimeConvertFrom [concrete]\n// CHECK:STDOUT:   %RuntimeConvertTo: type = class_type @RuntimeConvertTo [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.5cd: type = facet_type <@ImplicitAs, @ImplicitAs(%RuntimeConvertTo)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness @RuntimeConvertFrom.as.ImplicitAs.impl.%ImplicitAs.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.6bd: type = pattern_type %RuntimeConvertFrom [concrete]\n// CHECK:STDOUT:   %.993: Core.Form = init_form %RuntimeConvertTo [concrete]\n// CHECK:STDOUT:   %pattern_type.c89: type = pattern_type %RuntimeConvertTo [concrete]\n// CHECK:STDOUT:   %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.type: type = fn_type @RuntimeConvertFrom.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %RuntimeConvertFrom.as.ImplicitAs.impl.Convert: %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.5cd = facet_value %RuntimeConvertFrom, (%ImplicitAs.impl_witness) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.3a2: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%RuntimeConvertTo, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %RuntimeConvertTo.val: %RuntimeConvertTo = struct_value () [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %tuple.elem0: type = tuple_access %T, element0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.e66: type = pattern_type %tuple.elem0 [symbolic]\n// CHECK:STDOUT:   %A: %tuple.elem0 = symbolic_binding A, 1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.17d: type = pattern_type %HoldsType.f6a [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %HoldsType.f6a [symbolic]\n// CHECK:STDOUT:   %tuple.b95: %tuple.type = tuple_value (%RuntimeConvertTo) [concrete]\n// CHECK:STDOUT:   %HoldsType.0ca: type = class_type @HoldsType, @HoldsType(%tuple.b95) [concrete]\n// CHECK:STDOUT:   %pattern_type.c6f: type = pattern_type %HoldsType.0ca [concrete]\n// CHECK:STDOUT:   %from: %RuntimeConvertFrom = symbolic_binding from, 0 [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.8ab: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.3a2, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %from, %RuntimeConvertFrom.as.ImplicitAs.impl.Convert [symbolic]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .HoldsType = %HoldsType.decl\n// CHECK:STDOUT:     .RuntimeConvertFrom = %RuntimeConvertFrom.decl\n// CHECK:STDOUT:     .RuntimeConvertTo = %RuntimeConvertTo.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %HoldsType.decl: %HoldsType.type = class_decl @HoldsType [concrete = constants.%HoldsType.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.f1e = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc17_28.1: type = splice_block %.loc17_28.3 [concrete = constants.%tuple.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc17_22: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.loc17_28.2: %tuple.type = tuple_literal (%.loc17_22) [concrete = constants.%tuple.0d2]\n// CHECK:STDOUT:       %.loc17_28.3: type = converted %.loc17_28.2, constants.%tuple.type [concrete = constants.%tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc17_17.2: %tuple.type = symbolic_binding T, 0 [symbolic = %T.loc17_17.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %RuntimeConvertFrom.decl: type = class_decl @RuntimeConvertFrom [concrete = constants.%RuntimeConvertFrom] {} {}\n// CHECK:STDOUT:   %RuntimeConvertTo.decl: type = class_decl @RuntimeConvertTo [concrete = constants.%RuntimeConvertTo] {} {}\n// CHECK:STDOUT:   impl_decl @RuntimeConvertFrom.as.ImplicitAs.impl [concrete] {} {\n// CHECK:STDOUT:     %RuntimeConvertFrom.ref: type = name_ref RuntimeConvertFrom, file.%RuntimeConvertFrom.decl [concrete = constants.%RuntimeConvertFrom]\n// CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %ImplicitAs.ref: %ImplicitAs.type.cc7 = name_ref ImplicitAs, imports.%Core.ImplicitAs [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:     %RuntimeConvertTo.ref: type = name_ref RuntimeConvertTo, file.%RuntimeConvertTo.decl [concrete = constants.%RuntimeConvertTo]\n// CHECK:STDOUT:     %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%RuntimeConvertTo)> [concrete = constants.%ImplicitAs.type.5cd]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.f1e = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %A.patt: @F.%pattern_type.loc27_27 (%pattern_type.e66) = symbolic_binding_pattern A, 1 [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type.loc27_43 (%pattern_type.17d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type.loc27_43 (%pattern_type.17d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc27_17.1: type = splice_block %.loc27_17.3 [concrete = constants.%tuple.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc27_11: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.loc27_17.2: %tuple.type = tuple_literal (%.loc27_11) [concrete = constants.%tuple.0d2]\n// CHECK:STDOUT:       %.loc27_17.3: type = converted %.loc27_17.2, constants.%tuple.type [concrete = constants.%tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc27_6.2: %tuple.type = symbolic_binding T, 0 [symbolic = %T.loc27_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc27_32: type = splice_block %tuple.elem0.loc27_32.2 [symbolic = %tuple.elem0.loc27_32.1 (constants.%tuple.elem0)] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %T.ref.loc27_31: %tuple.type = name_ref T, %T.loc27_6.2 [symbolic = %T.loc27_6.1 (constants.%T)]\n// CHECK:STDOUT:       %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:       %tuple.elem0.loc27_32.2: type = tuple_access %T.ref.loc27_31, element0 [symbolic = %tuple.elem0.loc27_32.1 (constants.%tuple.elem0)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %A.loc27_27.2: @F.%tuple.elem0.loc27_32.1 (%tuple.elem0) = symbolic_binding A, 1 [symbolic = %A.loc27_27.1 (constants.%A)]\n// CHECK:STDOUT:     %x.param: @F.%HoldsType.loc27_57.1 (%HoldsType.f6a) = value_param call_param0\n// CHECK:STDOUT:     %.loc27_57: type = splice_block %HoldsType.loc27_57.2 [symbolic = %HoldsType.loc27_57.1 (constants.%HoldsType.f6a)] {\n// CHECK:STDOUT:       %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:       %T.ref.loc27_56: %tuple.type = name_ref T, %T.loc27_6.2 [symbolic = %T.loc27_6.1 (constants.%T)]\n// CHECK:STDOUT:       %HoldsType.loc27_57.2: type = class_type @HoldsType, @HoldsType(constants.%T) [symbolic = %HoldsType.loc27_57.1 (constants.%HoldsType.f6a)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @F.%HoldsType.loc27_57.1 (%HoldsType.f6a) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %holds_to.patt: %pattern_type.c6f = value_binding_pattern holds_to [concrete]\n// CHECK:STDOUT:     %holds_to.param_patt: %pattern_type.c6f = value_param_pattern %holds_to.patt [concrete]\n// CHECK:STDOUT:     %from.patt: %pattern_type.6bd = symbolic_binding_pattern from, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %holds_to.param: %HoldsType.0ca = value_param call_param0\n// CHECK:STDOUT:     %.loc29_46.1: type = splice_block %HoldsType [concrete = constants.%HoldsType.0ca] {\n// CHECK:STDOUT:       %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]\n// CHECK:STDOUT:       %RuntimeConvertTo.ref: type = name_ref RuntimeConvertTo, file.%RuntimeConvertTo.decl [concrete = constants.%RuntimeConvertTo]\n// CHECK:STDOUT:       %.loc29_45: %tuple.type = tuple_literal (%RuntimeConvertTo.ref) [concrete = constants.%tuple.b95]\n// CHECK:STDOUT:       %tuple.loc29: %tuple.type = tuple_value (%RuntimeConvertTo.ref) [concrete = constants.%tuple.b95]\n// CHECK:STDOUT:       %.loc29_46.2: %tuple.type = converted %.loc29_45, %tuple.loc29 [concrete = constants.%tuple.b95]\n// CHECK:STDOUT:       %HoldsType: type = class_type @HoldsType, @HoldsType(constants.%tuple.b95) [concrete = constants.%HoldsType.0ca]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %holds_to: %HoldsType.0ca = value_binding holds_to, %holds_to.param\n// CHECK:STDOUT:     %.loc29_56: type = splice_block %RuntimeConvertFrom.ref [concrete = constants.%RuntimeConvertFrom] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %RuntimeConvertFrom.ref: type = name_ref RuntimeConvertFrom, file.%RuntimeConvertFrom.decl [concrete = constants.%RuntimeConvertFrom]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %from.loc29_49.2: %RuntimeConvertFrom = symbolic_binding from, 0 [symbolic = %from.loc29_49.1 (constants.%from)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @RuntimeConvertFrom.as.ImplicitAs.impl: %RuntimeConvertFrom.ref as %ImplicitAs.type {\n// CHECK:STDOUT:   %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.decl: %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.type = fn_decl @RuntimeConvertFrom.as.ImplicitAs.impl.Convert [concrete = constants.%RuntimeConvertFrom.as.ImplicitAs.impl.Convert] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.6bd = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.6bd = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.c89 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.c89 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %RuntimeConvertTo.ref: type = name_ref RuntimeConvertTo, file.%RuntimeConvertTo.decl [concrete = constants.%RuntimeConvertTo]\n// CHECK:STDOUT:     %.loc24_38: Core.Form = init_form %RuntimeConvertTo.ref [concrete = constants.%.993]\n// CHECK:STDOUT:     %self.param: %RuntimeConvertFrom = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @RuntimeConvertFrom.as.ImplicitAs.impl.%RuntimeConvertFrom.ref [concrete = constants.%RuntimeConvertFrom]\n// CHECK:STDOUT:     %self: %RuntimeConvertFrom = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %RuntimeConvertTo = out_param call_param1\n// CHECK:STDOUT:     %return: ref %RuntimeConvertTo = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%RuntimeConvertFrom.as.ImplicitAs.impl.Convert.decl), @RuntimeConvertFrom.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness %ImplicitAs.impl_witness_table [concrete = constants.%ImplicitAs.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .RuntimeConvertTo = <poisoned>\n// CHECK:STDOUT:   .Convert = %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.decl\n// CHECK:STDOUT:   witness = %ImplicitAs.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @HoldsType(%T.loc17_17.2: %tuple.type) {\n// CHECK:STDOUT:   %T.loc17_17.1: %tuple.type = symbolic_binding T, 0 [symbolic = %T.loc17_17.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%HoldsType.f6a\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @RuntimeConvertFrom {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%RuntimeConvertFrom\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @RuntimeConvertTo {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%RuntimeConvertTo\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeConvertFrom.as.ImplicitAs.impl.Convert(%self.param: %RuntimeConvertFrom) -> out %return.param: %RuntimeConvertTo {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc24_65.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc24_65.2: init %RuntimeConvertTo to %return.param = class_init () [concrete = constants.%RuntimeConvertTo.val]\n// CHECK:STDOUT:   %.loc24_66: init %RuntimeConvertTo = converted %.loc24_65.1, %.loc24_65.2 [concrete = constants.%RuntimeConvertTo.val]\n// CHECK:STDOUT:   return %.loc24_66 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc27_6.2: %tuple.type, %A.loc27_27.2: @F.%tuple.elem0.loc27_32.1 (%tuple.elem0)) {\n// CHECK:STDOUT:   %T.loc27_6.1: %tuple.type = symbolic_binding T, 0 [symbolic = %T.loc27_6.1 (constants.%T)]\n// CHECK:STDOUT:   %tuple.elem0.loc27_32.1: type = tuple_access %T.loc27_6.1, element0 [symbolic = %tuple.elem0.loc27_32.1 (constants.%tuple.elem0)]\n// CHECK:STDOUT:   %A.loc27_27.1: @F.%tuple.elem0.loc27_32.1 (%tuple.elem0) = symbolic_binding A, 1 [symbolic = %A.loc27_27.1 (constants.%A)]\n// CHECK:STDOUT:   %pattern_type.loc27_27: type = pattern_type %tuple.elem0.loc27_32.1 [symbolic = %pattern_type.loc27_27 (constants.%pattern_type.e66)]\n// CHECK:STDOUT:   %HoldsType.loc27_57.1: type = class_type @HoldsType, @HoldsType(%T.loc27_6.1) [symbolic = %HoldsType.loc27_57.1 (constants.%HoldsType.f6a)]\n// CHECK:STDOUT:   %pattern_type.loc27_43: type = pattern_type %HoldsType.loc27_57.1 [symbolic = %pattern_type.loc27_43 (constants.%pattern_type.17d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %HoldsType.loc27_57.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%HoldsType.loc27_57.1 (%HoldsType.f6a)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%from.loc29_49.2: %RuntimeConvertFrom) {\n// CHECK:STDOUT:   %from.loc29_49.1: %RuntimeConvertFrom = symbolic_binding from, 0 [symbolic = %from.loc29_49.1 (constants.%from)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %from.loc29_49.1, constants.%RuntimeConvertFrom.as.ImplicitAs.impl.Convert [symbolic = %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.bound (constants.%RuntimeConvertFrom.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%holds_to.param: %HoldsType.0ca) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %from.ref: %RuntimeConvertFrom = name_ref from, %from.loc29_49.2 [symbolic = %from.loc29_49.1 (constants.%from)]\n// CHECK:STDOUT:     %holds_to.ref: %HoldsType.0ca = name_ref holds_to, %holds_to\n// CHECK:STDOUT:     %impl.elem0: %.8ab = impl_witness_access constants.%ImplicitAs.impl_witness, element0 [concrete = constants.%RuntimeConvertFrom.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:     %bound_method: <bound method> = bound_method constants.%from, %impl.elem0 [symbolic = %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.bound (constants.%RuntimeConvertFrom.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:     %.loc40_19.1: ref %RuntimeConvertTo = temporary_storage\n// CHECK:STDOUT:     %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.call: init %RuntimeConvertTo to %.loc40_19.1 = call %bound_method(constants.%from)\n// CHECK:STDOUT:     %.loc40_19.2: init %RuntimeConvertTo = converted constants.%from, %RuntimeConvertFrom.as.ImplicitAs.impl.Convert.call\n// CHECK:STDOUT:     %.loc40_19.3: ref %RuntimeConvertTo = temporary %.loc40_19.1, %.loc40_19.2\n// CHECK:STDOUT:     %.loc40_19.4: %RuntimeConvertTo = acquire_value %.loc40_19.3\n// CHECK:STDOUT:     %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%tuple.b95, <error>) [concrete = <error>]\n// CHECK:STDOUT:     %.loc40_19.5: %empty_tuple.type = call %F.specific_fn(%holds_to.ref)\n// CHECK:STDOUT:     %tuple.loc40: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc40_19.6: %empty_tuple.type = converted %.loc40_19.5, %tuple.loc40 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %Destroy.Op.bound: <bound method> = bound_method %.loc40_19.3, constants.%Destroy.Op\n// CHECK:STDOUT:     %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc40_19.3)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %RuntimeConvertTo) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HoldsType(constants.%T) {\n// CHECK:STDOUT:   %T.loc17_17.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T, constants.%A) {\n// CHECK:STDOUT:   %T.loc27_6.1 => constants.%T\n// CHECK:STDOUT:   %tuple.elem0.loc27_32.1 => constants.%tuple.elem0\n// CHECK:STDOUT:   %A.loc27_27.1 => constants.%A\n// CHECK:STDOUT:   %pattern_type.loc27_27 => constants.%pattern_type.e66\n// CHECK:STDOUT:   %HoldsType.loc27_57.1 => constants.%HoldsType.f6a\n// CHECK:STDOUT:   %pattern_type.loc27_43 => constants.%pattern_type.17d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HoldsType(constants.%tuple.b95) {\n// CHECK:STDOUT:   %T.loc17_17.1 => constants.%tuple.b95\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%from) {\n// CHECK:STDOUT:   %from.loc29_49.1 => constants.%from\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%tuple.b95, <error>) {\n// CHECK:STDOUT:   %T.loc27_6.1 => constants.%tuple.b95\n// CHECK:STDOUT:   %tuple.elem0.loc27_32.1 => constants.%RuntimeConvertTo\n// CHECK:STDOUT:   %A.loc27_27.1 => <error>\n// CHECK:STDOUT:   %pattern_type.loc27_27 => constants.%pattern_type.c89\n// CHECK:STDOUT:   %HoldsType.loc27_57.1 => constants.%HoldsType.0ca\n// CHECK:STDOUT:   %pattern_type.loc27_43 => constants.%pattern_type.c6f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/fail_incomplete.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/fail_incomplete.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/fail_incomplete.carbon\n\n// --- fail_impl_lookup_incomplete.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nconstraint Z;\n\nfn AsZ(unused T:! Z) {}\n\nfn F() {\n  // Requires Z identified.\n  // CHECK:STDERR: fail_impl_lookup_incomplete.carbon:[[@LINE+10]]:3: error: facet type `Z` can not be identified [ImplLookupInUnidentifiedFacetType]\n  // CHECK:STDERR:   AsZ(());\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_impl_lookup_incomplete.carbon:[[@LINE-9]]:1: note: constraint was forward declared here [NamedConstraintForwardDeclaredHere]\n  // CHECK:STDERR: constraint Z;\n  // CHECK:STDERR: ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_impl_lookup_incomplete.carbon:[[@LINE-10]]:15: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn AsZ(unused T:! Z) {}\n  // CHECK:STDERR:               ^\n  // CHECK:STDERR:\n  AsZ(());\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/fail_namespace_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/fail_namespace_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/fail_namespace_type.carbon\n\n// --- fail_namespace_as.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nnamespace N;\n\ninterface Z {}\n\nimpl forall [T:! type] T as Z {}\n\nfn F() {\n  // CHECK:STDERR: fail_namespace_as.carbon:[[@LINE+4]]:3: error: expression cannot be used as a value [UseOfNonExprAsValue]\n  // CHECK:STDERR:   N as Z;\n  // CHECK:STDERR:   ^\n  // CHECK:STDERR:\n  N as Z;\n}\n\n// --- fail_namespace_argument.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nnamespace N;\n\ninterface Z {}\n\nimpl forall [T:! type] T as Z {}\n\nfn G[T:! Z](unused a: T) {}\n\nfn F() {\n  // CHECK:STDERR: fail_namespace_argument.carbon:[[@LINE+7]]:5: error: expression cannot be used as a value [UseOfNonExprAsValue]\n  // CHECK:STDERR:   G(N);\n  // CHECK:STDERR:     ^\n  // CHECK:STDERR: fail_namespace_argument.carbon:[[@LINE-6]]:20: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn G[T:! Z](unused a: T) {}\n  // CHECK:STDERR:                    ^~~~\n  // CHECK:STDERR:\n  G(N);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/identify_self_canonicalized.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/identify_self_canonicalized.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/identify_self_canonicalized.carbon\n\n// --- identify_self_canonicalized.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\nconstraint W {\n  extend require impls Z;\n}\n\ninterface Y {}\n\n// T is a facet value (a SymbolicBinding), which is converted to `type`. The\n// identified facet type finds `(T as type) impls Z` from the top level facet\n// type. It also finds `T as Z` through `W`. It's possible for these to disagree\n// on the self and thus present as two different required interfaces in the\n// identified facet type. Instead we should only get a single interface with the\n// canonical `T` facet value as the self value.\n\nimpl forall [T:! Y] T as W & Z {}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/named_constant.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/named_constant.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/named_constant.carbon\n\n// --- fail_todo_named_constant_in_rewrite.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn Test() {\n  // CHECK:STDERR: fail_todo_named_constant_in_rewrite.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let Constant:! type = ();\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let Constant:! type = ();\n\n  fn F(T:! I where .X = Constant) {}\n\n  fn G(T:! I where .X = Constant) {\n    // TODO: The facet type T in G should match the facet type T in F.\n    F(T);\n  }\n}\n\n// --- fail_todo_named_constant_two_levels_in_rewrite.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn Test() {\n  // CHECK:STDERR: fail_todo_named_constant_two_levels_in_rewrite.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let Constant2:! type = ();\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let Constant2:! type = ();\n  let Constant:! type = (Constant2, );\n\n  fn F(T:! I where .X = Constant) {}\n\n  fn G(T:! I where .X = Constant) {\n    // TODO: The facet type T in G should match the facet type T in F.\n    F(T);\n  }\n}\n\n// --- fail_todo_named_constant_in_rewrite_callee.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn Test() {\n  // CHECK:STDERR: fail_todo_named_constant_in_rewrite_callee.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let Constant:! type = ();\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let Constant:! type = ();\n\n  fn F(T:! I where .X = Constant) {}\n\n  fn G(T:! I where .X = ()) {\n    // TODO: The facet type T in G should match the facet type T in F.\n    F(T);\n  }\n}\n\n// --- fail_todo_named_constant_in_rewrite_caller.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn Test() {\n  // CHECK:STDERR: fail_todo_named_constant_in_rewrite_caller.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let Constant:! type = ();\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let Constant:! type = ();\n\n  fn F(T:! I where .X = ()) {}\n\n  fn G(T:! I where .X = Constant) {\n    // TODO: The facet type T in G should match the facet type T in F.\n    F(T);\n  }\n}\n\n// --- fail_todo_named_constant_in_nested_facet_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn Test() {\n  // CHECK:STDERR: fail_todo_named_constant_in_nested_facet_type.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let Constant:! type = ();\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let Constant:! type = ();\n\n  // TODO: The .Self reference in each .X should be different, there should be\n  // no cycle here.\n  fn F(T:! I where .X = (I where .X = Constant)) {}\n\n  fn G(T:! I where .X = (I where .X = Constant)) {\n    // TODO: The facet type T in G should match the facet type T in F.\n    F(T);\n  }\n}\n\n// --- fail_todo_named_constant_in_nested_facet_type_caller.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn Test() {\n  // CHECK:STDERR: fail_todo_named_constant_in_nested_facet_type_caller.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let Constant:! type = ();\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let Constant:! type = ();\n\n  fn F(T:! I where .X = (I where .X = ())) {}\n\n  // TODO: The .Self reference in each .X should be different, there should be\n  // no cycle here.\n  fn G(T:! I where .X = (I where .X = Constant)) {\n    // TODO: The facet type T in G should match the facet type T in F.\n    F(T);\n  }\n}\n\n// --- fail_named_constant_in_nested_facet_type_callee.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn Test() {\n  // CHECK:STDERR: fail_named_constant_in_nested_facet_type_callee.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let Constant:! type = ();\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let Constant:! type = ();\n\n  // TODO: The .Self reference in each .X should be different, there should be\n  // no cycle here.\n  fn F(T:! I where .X = (I where .X = Constant)) {}\n\n  fn G(T:! I where .X = (I where .X = ())) {\n    // TODO: The facet type T in G should match the facet type T in F.\n    F(T);\n  }\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/nested_facet_types.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/nested_facet_types.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/nested_facet_types.carbon\n\n// --- nested_facet_types.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n}\n\nfn F(FF:! (Z where .T = ()) where .U = .T) -> FF.U {\n  return ();\n}\n\n// --- nested_facet_types_same.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n}\n\nfn F(FF:! ((Z where .T = ()) where .T = ()) where .T = ()) -> FF.T {\n  return ();\n}\n\n// --- nested_facet_types_same_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n}\n\nfn F(unused FF:! ((Z where .T = .U) where .T = .U) where .T = .U) {}\n\n// --- nested_facet_types_same_two_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n  let V:! type;\n}\n\nfn F(unused FF:! ((Z where .T = .U and .U = .V) where .T = .U and .U = .V) where .T = .U and .U = .V) {}\n\n// --- nested_facet_types_same_associated_in_generic_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n}\nclass C(T:! type) {}\n\nfn F(unused FF:! ((Z where .T = C(.U)) where .T = C(.U)) where .T = C(.U)) {}\n\n// --- fail_nested_facet_types_different.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n}\n\n// CHECK:STDERR: fail_nested_facet_types_different.carbon:[[@LINE+4]]:18: error: associated constant `.(Z.T)` given two different values `()` and `{}` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused FF:! (Z where .T = ()) where .T = {}) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused FF:! (Z where .T = ()) where .T = {}) {}\n\n// --- fail_nested_facet_types_different_with_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n}\n\n// CHECK:STDERR: fail_nested_facet_types_different_with_associated.carbon:[[@LINE+4]]:18: error: associated constant `.(Z.T)` given two different values `.(Z.U)` and `{}` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused FF:! (Z where .T = .U) where .T = {}) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused FF:! (Z where .T = .U) where .T = {}) {}\n\n// --- fail_nested_facet_types_different_with_associated_in_generic_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n}\nclass C(T:! type) {}\n\n// CHECK:STDERR: fail_nested_facet_types_different_with_associated_in_generic_parameter.carbon:[[@LINE+4]]:18: error: associated constant `.(Z.T)` given two different values `C(.(Z.U))` and `{}` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused FF:! (Z where .T = C(.U)) where .T = {}) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused FF:! (Z where .T = C(.U)) where .T = {}) {}\n\n// --- nested_facet_types_same_with_bitand.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n}\n\nfn F(unused FF:! ((Z where .T = .U) where .T = .U) & (Z where .T = .U)) {}\n\n// --- fail_nested_facet_types_different_with_bitand.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n}\n\n// CHECK:STDERR: fail_nested_facet_types_different_with_bitand.carbon:[[@LINE+4]]:18: error: associated constant `.(Z.T)` given two different values `.(Z.U)` and `{}` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused FF:! ((Z where .T = .U) where .T = .U) & (Z where .T = {})) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused FF:! ((Z where .T = .U) where .T = .U) & (Z where .T = {})) {}\n\n// --- fail_nested_facet_type_cycle.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let T:! type;\n  let U:! type;\n}\n\n// CHECK:STDERR: fail_nested_facet_type_cycle.carbon:[[@LINE+4]]:18: error: found cycle in facet type constraint for `.(Z.U)` [FacetTypeConstraintCycle]\n// CHECK:STDERR: fn F(unused FF:! (Z where .T = .U) where .U = .T) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused FF:! (Z where .T = .U) where .U = .T) {}\n\n// --- fail_nested_facet_types_different_separated_order_one.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let S:! type;\n  let T:! type;\n  let U:! type;\n  let V:! type;\n}\n\n// The ordering here is meant to find a way to insert a LHS between the two `.S`\n// ids, by producing different orderings to get an id between them.\n\n// CHECK:STDERR: fail_nested_facet_types_different_separated_order_one.carbon:[[@LINE+4]]:18: error: associated constant `.(Z.S)` given two different values `.(Z.U)` and `{}` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused FF:! (((Z where .S = .U) where .V = {}) where .T = .U) & (Z where .S = {})) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused FF:! (((Z where .S = .U) where .V = {}) where .T = .U) & (Z where .S = {})) {}\n\n// --- fail_nested_facet_types_different_separated_order_two.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let S:! type;\n  let T:! type;\n  let U:! type;\n  let V:! type;\n}\n\n// The ordering here is meant to find a way to insert a LHS between the two `.S`\n// ids, by producing different orderings to get an id between them. As of today,\n// this is the case where `.T` is sorted between the two `.S` rewrite rules.\n\n// CHECK:STDERR: fail_nested_facet_types_different_separated_order_two.carbon:[[@LINE+4]]:18: error: associated constant `.(Z.S)` given two different values `{}` and `.(Z.U)` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused FF:! (((Z where .V = {}) where .S = .U) where .T = .U) & (Z where .S = {})) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused FF:! (((Z where .V = {}) where .S = .U) where .T = .U) & (Z where .S = {})) {}\n\n// --- fail_nested_facet_types_different_separated_order_three.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let S:! type;\n  let T:! type;\n  let U:! type;\n  let V:! type;\n}\n\n// The ordering here is meant to find a way to insert a LHS between the two `.S`\n// ids, by producing different orderings to get an id between them.\n\n// CHECK:STDERR: fail_nested_facet_types_different_separated_order_three.carbon:[[@LINE+4]]:18: error: associated constant `.(Z.S)` given two different values `{}` and `.(Z.U)` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: fn F(unused FF:! (((Z where .V = {}) where .T = .U) where .S = .U) & (Z where .S = {})) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused FF:! (((Z where .V = {}) where .T = .U) where .S = .U) & (Z where .S = {})) {}\n\n// --- repeated_with_value_available.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z { let X:! type; let Y:! type; }\n\nfn F(T:! ((Z where .Y = ()) where .X = .Y) where .X = .Y) -> T.X {\n  return ();\n}\n\nclass C(T:! type) { adapt (); }\n\nfn F1(T:! (Z where .Y = C(()) and .X = C(.Y)) where .X = C(C(()))) -> T.X {\n  return () as C(C(()));\n}\n\nfn F2(T:! ((Z where .Y = C(())) where .X = C(.Y)) where .X = C(C(()))) -> T.X {\n  return () as C(C(()));\n}\n\nfn F3(T:! Z where .Y = C(()) and .X = C(.Y) and .X = C(C(()))) -> T.X {\n  return () as C(C(()));\n}\n\n// --- conflicting_syntax_same_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z { let X:! type; let Y:! type; }\n\nfn F1(T:! ((Z where .Y = ()) where .X = .Y) where .X = ()) -> T.X {\n  return ();\n}\n\nfn F2(T:! ((Z where .Y = ()) where .X = ()) where .X = .Y) -> T.X {\n  return ();\n}\n\n// --- nested_impls_repeated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\ninterface Z {\n  let T:! type;\n  let U:! type;\n}\nclass C(T:! type) {}\n\nfn F(unused FF:! ((Y where .Self impls (Z where .T = C(.U)))\n                where .Self impls (Z where .T = C(.U)))\n                  where .Self impls (Z where .T = C(.U))) {}\n\n// --- nested_impl_unique.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {\n  let Y1:! type;\n}\ninterface Z {\n  let Z1:! type;\n  let Z2:! type;\n}\nclass C(T:! type) { adapt (); }\n\nfn F(FF:! ((Y where .Y1 = ()) where .Self impls (Z where .Z1 = C(.Z2) and .Z2 = ()))) -> FF.(Z.Z1) {\n  return () as C(());\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/period_self.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/period_self.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/period_self.carbon\n\n// --- period_self_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\ninterface I(T:! type) {\n  let I1:! type;\n}\n\nfn F(T:! I(.Self) where .I1 = ()) -> T.I1 {\n  return ();\n}\n\nfn G(T:! I(.Self as type) where .I1 = ()) -> T.I1 {\n  return ();\n}\n//@dump-sem-ir-end\n\n// --- underscore_identifier_name.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  let I1:! type;\n}\n\n// Underscore as the identifier name produces a different parse tree for the\n// binding pattern.\nfn G(_:! I(.Self) where .I1 = ()) {}\n\n// --- fail_period_self_as_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: We should diagnose this use of `.Self` directly rather than later when\n// it is converted to `type`.\ninterface I(T:! .Self) {\n  // CHECK:STDERR: fail_period_self_as_type.carbon:[[@LINE+7]]:13: error: cannot implicitly convert non-type value of type `.Self` to `type` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   fn G() -> T;\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR: fail_period_self_as_type.carbon:[[@LINE+4]]:13: note: type `.Self` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   fn G() -> T;\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  fn G() -> T;\n}\n\n// --- fail_todo_convert_period_self_to_full_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {}\n\nfn F(U:! I(.Self)) {\n  // CHECK:STDERR: fail_todo_convert_period_self_to_full_facet_value.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I(.Self)` into type implementing `I(U)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   U as I(U);\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR:\n  U as I(U);\n  // CHECK:STDERR: fail_todo_convert_period_self_to_full_facet_value.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I(.Self)` into type implementing `I(U)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   (U as type) as I(U);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  (U as type) as I(U);\n}\n\n// --- fail_todo_convert_period_self_to_full_facet_value_with_assoc_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  let X:! type;\n}\n\nfn F(U:! I(.Self) where .X = .Self) {\n  // CHECK:STDERR: fail_todo_convert_period_self_to_full_facet_value_with_assoc_constant.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I(.Self) where .(I(.Self).X) = .Self` into type implementing `I(U) where .(I(U).X) = U` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   U as (I(U) where .X = U);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  U as (I(U) where .X = U);\n  // CHECK:STDERR: fail_todo_convert_period_self_to_full_facet_value_with_assoc_constant.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I(.Self) where .(I(.Self).X) = .Self` into type implementing `I(U) where .(I(U).X) = U` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   (U as type) as (I(U) where .X = U);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  (U as type) as (I(U) where .X = U);\n}\n\n// --- fail_todo_return_of_type_period_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  fn G() -> T*;\n}\n\ninterface J(T:! type) {\n  fn J1() -> T*;\n}\n\nfn F2[U:! I(.Self)](unused T: U*) {}\n\nfn F(U:! I(.Self)) {\n  // Caller sees the returned `.Self` type from `F()` as the full `U`.\n  // CHECK:STDERR: fail_todo_return_of_type_period_self.carbon:[[@LINE+4]]:3: error: member name `G` not found [MemberNameNotFound]\n  // CHECK:STDERR:   U.G()->G()->G();\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR:\n  U.G()->G()->G();\n  // Conversion to `type` retains access to all of `U`.\n  // CHECK:STDERR: fail_todo_return_of_type_period_self.carbon:[[@LINE+4]]:3: error: member name `G` not found [MemberNameNotFound]\n  // CHECK:STDERR:   (U as type).G()->G()->G();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  (U as type).G()->G()->G();\n\n  // Using the returned `.Self` as a facet value works, not just member lookup\n  // on its facet type.\n  // CHECK:STDERR: fail_todo_return_of_type_period_self.carbon:[[@LINE+4]]:6: error: member name `G` not found [MemberNameNotFound]\n  // CHECK:STDERR:   F2(U.G()->G()->G());\n  // CHECK:STDERR:      ^~~~~~~~\n  // CHECK:STDERR:\n  F2(U.G()->G()->G());\n}\n\n// --- fail_todo_return_of_type_period_self_extends_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  fn I1() -> T*;\n}\n\ninterface J(T:! type) {\n  fn J1() -> T*;\n}\n\nfn F2[U:! I(.Self) & J(.Self)](unused T: U*) {}\n\nfn F(U:! I(.Self) & J(.Self)) {\n  // TODO: The returned value of `I1` and `J1` has type `U` which has access to\n  // the methods of `I` and `J`.\n  // CHECK:STDERR: fail_todo_return_of_type_period_self_extends_interface.carbon:[[@LINE+4]]:3: error: member name `J1` not found [MemberNameNotFound]\n  // CHECK:STDERR:   U.I1()->J1()->I1()->J1()->I1()->J1();\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR:\n  U.I1()->J1()->I1()->J1()->I1()->J1();\n  // CHECK:STDERR: fail_todo_return_of_type_period_self_extends_interface.carbon:[[@LINE+4]]:3: error: member name `J1` not found [MemberNameNotFound]\n  // CHECK:STDERR:   (U as type).I1()->J1()->I1()->J1()->I1()->J1();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  (U as type).I1()->J1()->I1()->J1()->I1()->J1();\n\n  // TODO: Using the returned value of type `U` as a facet value works.\n  // CHECK:STDERR: fail_todo_return_of_type_period_self_extends_interface.carbon:[[@LINE+4]]:6: error: member name `J1` not found [MemberNameNotFound]\n  // CHECK:STDERR:   F2(U.I1()->J1()->I1()->J1()->I1()->J1());\n  // CHECK:STDERR:      ^~~~~~~~~~\n  // CHECK:STDERR:\n  F2(U.I1()->J1()->I1()->J1()->I1()->J1());\n}\n\n// --- fail_todo_return_of_period_self_impls_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  fn I1() -> T;\n}\n\ninterface J(T:! type) {\n  fn J1() -> T;\n}\n\nfn G(U:! I(.Self) where .Self impls J(.Self)) {\n  // Compound member lookup through a non-type value is possible for methods\n  // which take a `self` parameter. But it's not possible for methods without\n  // `self`. For those you need to go directly throug the type.\n  // See: https://github.com/carbon-language/carbon-lang/issues/6025\n\n  // TODO: This step should work.\n  //\n  // CHECK:STDERR: fail_todo_return_of_period_self_impls_interface.carbon:[[@LINE+7]]:14: error: cannot implicitly convert expression of type `.Self` to `U` [ConversionFailure]\n  // CHECK:STDERR:   let u: U = U.I1();\n  // CHECK:STDERR:              ^~~~~~\n  // CHECK:STDERR: fail_todo_return_of_period_self_impls_interface.carbon:[[@LINE+4]]:14: note: type `.Self` does not implement interface `Core.ImplicitAs(U)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let u: U = U.I1();\n  // CHECK:STDERR:              ^~~~~~\n  // CHECK:STDERR:\n  let u: U = U.I1();\n  // `u` is a non-type value. Can call methods with `self` through compound\n  // member lookup, but can't call methods without `self`. See the\n  // `compound_access_through_call_with_self_param.carbon` test for the former.\n  //\n  // CHECK:STDERR: fail_todo_return_of_period_self_impls_interface.carbon:[[@LINE+4]]:6: error: type `<type of J>` does not support qualified expressions [QualifiedExprUnsupported]\n  // CHECK:STDERR:   u.(J.J1)();\n  // CHECK:STDERR:      ^~~~\n  // CHECK:STDERR:\n  u.(J.J1)();\n\n  // This is the same as the above, since U.I1() returns a non-type value of\n  // type `U`.\n  //\n  // CHECK:STDERR: fail_todo_return_of_period_self_impls_interface.carbon:[[@LINE+4]]:11: error: type `<type of J>` does not support qualified expressions [QualifiedExprUnsupported]\n  // CHECK:STDERR:   U.I1().(J.J1)();\n  // CHECK:STDERR:           ^~~~\n  // CHECK:STDERR:\n  U.I1().(J.J1)();\n}\n\n// --- fail_todo_return_of_type_period_self_has_type_u.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  fn G() -> T;\n}\n\nfn F(U:! I(.Self)) {\n  // CHECK:STDERR: fail_todo_return_of_type_period_self_has_type_u.carbon:[[@LINE+7]]:21: error: cannot implicitly convert expression of type `.Self` to `U` [ConversionFailure]\n  // CHECK:STDERR:   let unused a: U = U.G();\n  // CHECK:STDERR:                     ^~~~~\n  // CHECK:STDERR: fail_todo_return_of_type_period_self_has_type_u.carbon:[[@LINE+4]]:21: note: type `.Self` does not implement interface `Core.ImplicitAs(U)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused a: U = U.G();\n  // CHECK:STDERR:                     ^~~~~\n  // CHECK:STDERR:\n  let unused a: U = U.G();\n}\n\n// --- fail_todo_return_of_type_period_self_assoc_const_has_type_u.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  fn G() -> X;\n}\n\nfn F(U:! I where .X = .Self) {\n  // CHECK:STDERR: fail_todo_return_of_type_period_self_assoc_const_has_type_u.carbon:[[@LINE+7]]:21: error: cannot implicitly convert expression of type `.Self` to `U` [ConversionFailure]\n  // CHECK:STDERR:   let unused a: U = U.G();\n  // CHECK:STDERR:                     ^~~~~\n  // CHECK:STDERR: fail_todo_return_of_type_period_self_assoc_const_has_type_u.carbon:[[@LINE+4]]:21: note: type `.Self` does not implement interface `Core.ImplicitAs(U)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused a: U = U.G();\n  // CHECK:STDERR:                     ^~~~~\n  // CHECK:STDERR:\n  let unused a: U = U.G();\n}\n\n// --- fail_todo_nested_period_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  let A:! type;\n  let B:! type;\n  fn G() -> T;\n}\n\n// Both `.Self` refer to `T`. The first because it's the interface for the\n// binding. The second because it refers to the top level facet type which is\n// constraining the binding.\nfn F(T:! I(.Self) where .A = ((I(.Self) where .B = {}) where .A = {}) and .B = {}, U:! T.A) {\n  // T.G() has type T.\n  // CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+7]]:21: error: cannot implicitly convert expression of type `.Self` to `T` [ConversionFailure]\n  // CHECK:STDERR:   let unused t: T = T.G();\n  // CHECK:STDERR:                     ^~~~~\n  // CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+4]]:21: note: type `.Self` does not implement interface `Core.ImplicitAs(T)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused t: T = T.G();\n  // CHECK:STDERR:                     ^~~~~\n  // CHECK:STDERR:\n  let unused t: T = T.G();\n    // U.G() has type T.\n  // CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+7]]:21: error: cannot implicitly convert expression of type `.Self` to `T` [ConversionFailure]\n  // CHECK:STDERR:   let unused u: T = U.G();\n  // CHECK:STDERR:                     ^~~~~\n  // CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+4]]:21: note: type `.Self` does not implement interface `Core.ImplicitAs(T)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused u: T = U.G();\n  // CHECK:STDERR:                     ^~~~~\n  // CHECK:STDERR:\n  let unused u: T = U.G();\n\n  // Shows both `I(.Self)` are `I(T)`.\n  // CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+4]]:9: error: found cycle in facet type constraint for `.(I(T).A)` [FacetTypeConstraintCycle]\n  // CHECK:STDERR:   T as (I(T) where .A = (I(T) where .A = {} and .B = {}));\n  // CHECK:STDERR:         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  T as (I(T) where .A = (I(T) where .A = {} and .B = {}));\n  // CHECK:STDERR: fail_todo_nested_period_self.carbon:[[@LINE+4]]:3: error: cannot convert type `U` that implements `I(.Self) where .(I(.Self).B) = {} and .(I(.Self).A) = {}` into type implementing `I(T) where .(I(T).A) = {} and .(I(T).B) = {}` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   U as (I(T) where .A = {} and .B = {});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  U as (I(T) where .A = {} and .B = {});\n}\n\n// --- todo_fail_nested_period_self_ambiguous.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  let A:! type;\n}\n\n// TODO: This should be an error: The third `.Self` becomes is not able to be\n// bound to anything unambiguous here, as it could refer to `T` or to something\n// later being constrained by `T.A`.\nfn F(unused T:! I(.Self) where .A = (I(.Self) where .A = I(.Self))) {}\n\n\n// --- period_self_parameter_sees_lhs_of_where_expr.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! Core.Destroy) {}\n\n// The `.Self` can see the LHS of the `where` to know `U` impls Core.Destroy.\nfn F(unused U:! Core.Destroy where .Self impls I(.Self)) {}\n\n// --- fail_todo_period_self_parameter_constraint_satisfied_with_type_and.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! Core.Destroy) {}\n\n// TODO: Implied constraints that `.Self` impls `Core.Destroy` are satisfied by\n// the `&` expression.\n//\n// CHECK:STDERR: fail_todo_period_self_parameter_constraint_satisfied_with_type_and.carbon:[[@LINE+7]]:32: error: cannot convert type `.Self` that implements `type` into type implementing `Core.Destroy` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: fn F(unused U:! Core.Destroy & I(.Self)) {}\n// CHECK:STDERR:                                ^~~~~~~~\n// CHECK:STDERR: fail_todo_period_self_parameter_constraint_satisfied_with_type_and.carbon:[[@LINE-8]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: interface I(T:! Core.Destroy) {}\n// CHECK:STDERR:             ^\n// CHECK:STDERR:\nfn F(unused U:! Core.Destroy & I(.Self)) {}\n\n// --- fail_todo_compound_lookup_on_returned_period_self_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! Core.Destroy) {\n  fn G[self: Self]() -> T;\n}\n\nfn F[U:! Core.Destroy where .Self impls I(.Self)](u: U) {\n  // This tests that both `I.G` is accessible and that `Destroy` is preserved;\n  // we'd get an error for missing Destroy otherwise since G() returns an\n  // initializing expression.\n\n  // CHECK:STDERR: fail_todo_compound_lookup_on_returned_period_self_parameter.carbon:[[@LINE+4]]:3: error: cannot access member of interface `I(U as Core.Destroy)` in type `U` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   u.(I(U).G)().(I(U).G)().(I(U).G)();\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR:\n  u.(I(U).G)().(I(U).G)().(I(U).G)();\n}\n\n// CHECK:STDOUT: --- period_self_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%T.67d)> [symbolic]\n// CHECK:STDOUT:   %Self.fdb: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type.76c: type = assoc_entity_type @I, @I(%T.67d) [symbolic]\n// CHECK:STDOUT:   %assoc0.99e: %I.assoc_type.76c = assoc_entity element0, @I.WithSelf.%I1 [symbolic]\n// CHECK:STDOUT:   %.Self.binding.as_type.8db: type = symbolic_binding_type .Self, %.Self.c39 [symbolic_self]\n// CHECK:STDOUT:   %I.type.bee: type = facet_type <@I, @I(%.Self.binding.as_type.8db)> [symbolic_self]\n// CHECK:STDOUT:   %.Self.dad: %I.type.bee = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %Self.fa8: %I.type.bee = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type.c03: type = assoc_entity_type @I, @I(%.Self.binding.as_type.8db) [symbolic_self]\n// CHECK:STDOUT:   %assoc0.fe4: %I.assoc_type.c03 = assoc_entity element0, @I.WithSelf.%I1 [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type.b0b: type = symbolic_binding_type .Self, %.Self.dad [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness.3fc: <witness> = lookup_impl_witness %.Self.dad, @I, @I(%.Self.binding.as_type.8db) [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %I.lookup_impl_witness.3fc, element0 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I, @I(%.Self.binding.as_type.8db) where %impl.elem0 = %empty_tuple.type> [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.033: type = pattern_type %I_where.type [symbolic_self]\n// CHECK:STDOUT:   %T.706: %I_where.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.706 [symbolic]\n// CHECK:STDOUT:   %I.lookup_impl_witness.94d: <witness> = lookup_impl_witness %T.706, @I, @I(%.Self.binding.as_type.8db) [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type.bee = facet_value %T.binding.as_type, (%I.lookup_impl_witness.94d) [symbolic]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.033 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: %I_where.type = name_ref T, %T.loc8_6.2 [symbolic = %T.loc8_6.1 (constants.%T.706)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc8_39.1: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc8_39.2: %I.assoc_type.c03 = specific_constant @I1.%assoc0, @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%T.706) [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:     %I1.ref.loc8_39: %I.assoc_type.c03 = name_ref I1, %.loc8_39.2 [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:     %impl.elem0.loc8_39: type = impl_witness_access constants.%I.lookup_impl_witness.94d, element0 [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc8_39.3: Core.Form = init_form %impl.elem0.loc8_39 [concrete = constants.%.262]\n// CHECK:STDOUT:     %.loc8_19.1: type = splice_block %.loc8_19.2 [symbolic_self = constants.%I_where.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %.Self.ref.loc8_12: %type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.Self.as_type.loc8_17: type = facet_access_type %.Self.ref.loc8_12 [symbolic_self = constants.%.Self.binding.as_type.8db]\n// CHECK:STDOUT:       %.loc8_17: type = converted %.Self.ref.loc8_12, %.Self.as_type.loc8_17 [symbolic_self = constants.%.Self.binding.as_type.8db]\n// CHECK:STDOUT:       %I.type: type = facet_type <@I, @I(constants.%.Self.binding.as_type.8db)> [symbolic_self = constants.%I.type.bee]\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.Self.ref.loc8_25: %I.type.bee = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.dad]\n// CHECK:STDOUT:       %.Self.as_type.loc8_25: type = facet_access_type %.Self.ref.loc8_25 [symbolic_self = constants.%.Self.binding.as_type.b0b]\n// CHECK:STDOUT:       %.loc8_25.1: type = converted %.Self.ref.loc8_25, %.Self.as_type.loc8_25 [symbolic_self = constants.%.Self.binding.as_type.b0b]\n// CHECK:STDOUT:       %.loc8_25.2: %I.assoc_type.c03 = specific_constant @I1.%assoc0, @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%.Self.dad) [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:       %I1.ref.loc8_25: %I.assoc_type.c03 = name_ref I1, %.loc8_25.2 [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:       %impl.elem0.loc8_25: type = impl_witness_access constants.%I.lookup_impl_witness.3fc, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:       %.loc8_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc8_32.2: type = converted %.loc8_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.loc8_19.2: type = where_expr %.Self.2 [symbolic_self = constants.%I_where.type] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type.bee\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc8_25, %.loc8_32.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_6.2: %I_where.type = symbolic_binding T, 0 [symbolic = %T.loc8_6.1 (constants.%T.706)]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.033 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: %I_where.type = name_ref T, %T.loc12_6.2 [symbolic = %T.loc12_6.1 (constants.%T.706)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc12_47.1: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc12_47.2: %I.assoc_type.c03 = specific_constant @I1.%assoc0, @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%T.706) [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:     %I1.ref.loc12_47: %I.assoc_type.c03 = name_ref I1, %.loc12_47.2 [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:     %impl.elem0.loc12_47: type = impl_witness_access constants.%I.lookup_impl_witness.94d, element0 [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc12_47.3: Core.Form = init_form %impl.elem0.loc12_47 [concrete = constants.%.262]\n// CHECK:STDOUT:     %.loc12_27.1: type = splice_block %.loc12_27.2 [symbolic_self = constants.%I_where.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %.Self.ref.loc12_12: %type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc12_21: type = type_literal type [concrete = type]\n// CHECK:STDOUT:       %.Self.as_type.loc12_18: type = facet_access_type %.Self.ref.loc12_12 [symbolic_self = constants.%.Self.binding.as_type.8db]\n// CHECK:STDOUT:       %.loc12_18: type = converted %.Self.ref.loc12_12, %.Self.as_type.loc12_18 [symbolic_self = constants.%.Self.binding.as_type.8db]\n// CHECK:STDOUT:       %I.type: type = facet_type <@I, @I(constants.%.Self.binding.as_type.8db)> [symbolic_self = constants.%I.type.bee]\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.Self.ref.loc12_33: %I.type.bee = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.dad]\n// CHECK:STDOUT:       %.Self.as_type.loc12_33: type = facet_access_type %.Self.ref.loc12_33 [symbolic_self = constants.%.Self.binding.as_type.b0b]\n// CHECK:STDOUT:       %.loc12_33.1: type = converted %.Self.ref.loc12_33, %.Self.as_type.loc12_33 [symbolic_self = constants.%.Self.binding.as_type.b0b]\n// CHECK:STDOUT:       %.loc12_33.2: %I.assoc_type.c03 = specific_constant @I1.%assoc0, @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%.Self.dad) [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:       %I1.ref.loc12_33: %I.assoc_type.c03 = name_ref I1, %.loc12_33.2 [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:       %impl.elem0.loc12_33: type = impl_witness_access constants.%I.lookup_impl_witness.3fc, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:       %.loc12_40.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc12_40.2: type = converted %.loc12_40.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.loc12_27.2: type = where_expr %.Self.2 [symbolic_self = constants.%I_where.type] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type.bee\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc12_33, %.loc12_40.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc12_6.2: %I_where.type = symbolic_binding T, 0 [symbolic = %T.loc12_6.1 (constants.%T.706)]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc4_13.1)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self.loc4_23.2: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc4_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc4_23.1: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc4_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %I1: type = assoc_const_decl @I1 [concrete] {\n// CHECK:STDOUT:       %assoc0: @I.WithSelf.%I.assoc_type (%I.assoc_type.76c) = assoc_entity element0, @I.WithSelf.%I1 [symbolic = @I.WithSelf.%assoc0 (constants.%assoc0.99e)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc4_23.1\n// CHECK:STDOUT:     .I1 = @I1.%assoc0\n// CHECK:STDOUT:     witness = (@I.WithSelf.%I1)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc8_6.2: %I_where.type) {\n// CHECK:STDOUT:   %T.loc8_6.1: %I_where.type = symbolic_binding T, 0 [symbolic = %T.loc8_6.1 (constants.%T.706)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc8_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc8_6.1, @I, @I(constants.%.Self.binding.as_type.8db) [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness.94d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc9_11.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc9_11.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc9_12: init %empty_tuple.type = converted %.loc9_11.1, %.loc9_11.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     return %.loc9_12\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%T.loc12_6.2: %I_where.type) {\n// CHECK:STDOUT:   %T.loc12_6.1: %I_where.type = symbolic_binding T, 0 [symbolic = %T.loc12_6.1 (constants.%T.706)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc12_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc12_6.1, @I, @I(constants.%.Self.binding.as_type.8db) [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness.94d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc13_11.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc13_11.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc13_12: init %empty_tuple.type = converted %.loc13_11.1, %.loc13_11.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     return %.loc13_12\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T.67d, constants.%Self.fdb) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%.Self.binding.as_type.8db) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%.Self.binding.as_type.8db\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.bee\n// CHECK:STDOUT:   %Self.loc4_23.2 => constants.%Self.fa8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%Self.fdb) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%.Self.binding.as_type.8db\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.c03\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.fe4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%.Self.dad) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%.Self.binding.as_type.8db\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.c03\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.fe4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%T.706) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%.Self.binding.as_type.8db\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.c03\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.fe4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%.Self.binding.as_type.8db\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.c03\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.fe4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.706) {\n// CHECK:STDOUT:   %T.loc8_6.1 => constants.%T.706\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %I.lookup_impl_witness => constants.%I.lookup_impl_witness.94d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%T.706) {\n// CHECK:STDOUT:   %T.loc12_6.1 => constants.%T.706\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %I.lookup_impl_witness => constants.%I.lookup_impl_witness.94d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/require_constrains_self.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/require_constrains_self.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/require_constrains_self.carbon\n\n// --- fail_self_doesnt_meet_constraint.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y2 {}\ninterface Y(T:! Y2) {}\n// TODO: The error should be that Self does not implement Y2, not that it can't\n// be identified. We should allow identifying `Self`.\n//\n// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE+17]]:37: error: facet type of value `Self` can not be identified [ImplLookupInUnidentifiedFacetTypeOfQuerySelf]\n// CHECK:STDERR: constraint W { extend require impls Y(Self); }\n// CHECK:STDERR:                                     ^~~~~~~\n// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE+14]]:1: note: constraint is currently being defined [NamedConstraintIncompleteWithinDefinition]\n// CHECK:STDERR: constraint W { extend require impls Y(Self); }\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE-10]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: interface Y(T:! Y2) {}\n// CHECK:STDERR:             ^\n// CHECK:STDERR:\n// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE+7]]:37: error: cannot convert type `Self` that implements `W` into type implementing `Y2` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: constraint W { extend require impls Y(Self); }\n// CHECK:STDERR:                                     ^~~~~~~\n// CHECK:STDERR: fail_self_doesnt_meet_constraint.carbon:[[@LINE-17]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: interface Y(T:! Y2) {}\n// CHECK:STDERR:             ^\n// CHECK:STDERR:\nconstraint W { extend require impls Y(Self); }\n\n// --- fail_todo_self_meets_constraint.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y2 {}\ninterface Y(T:! Y2) {}\nconstraint W {\n  // TODO: This should allow the next line to work, as Self should be known to impl Y2.\n  require impls Y2;\n  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE+17]]:24: error: facet type of value `Self` can not be identified [ImplLookupInUnidentifiedFacetTypeOfQuerySelf]\n  // CHECK:STDERR:   extend require impls Y(Self);\n  // CHECK:STDERR:                        ^~~~~~~\n  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE-6]]:1: note: constraint is currently being defined [NamedConstraintIncompleteWithinDefinition]\n  // CHECK:STDERR: constraint W {\n  // CHECK:STDERR: ^~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE-10]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: interface Y(T:! Y2) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE+7]]:24: error: cannot convert type `Self` that implements `W` into type implementing `Y2` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   extend require impls Y(Self);\n  // CHECK:STDERR:                        ^~~~~~~\n  // CHECK:STDERR: fail_todo_self_meets_constraint.carbon:[[@LINE-17]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: interface Y(T:! Y2) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  extend require impls Y(Self);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/require_import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/require_import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/require_import.carbon\n\n// --- a.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z(T:! type) {\n  fn F();\n}\n\ninterface Y {\n  extend require impls Z(Self);\n}\n\nconstraint X {\n  extend require impls Z(Self);\n}\n\n// --- a.impl.carbon\n//@include-in-dumps\nimpl library \"[[@TEST_NAME]]\";\n\nfn F(A:! X, unused B:! Y) {\n  A.F();\n}\n\n// --- fail_todo_symbolic_facet_interface_requires_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"a\";\n\nfn F(B:! Y) {\n  // TODO: We find the name F, but then fail to do impl lookup for `F` in `B:!\n  // Y` since the identified facet type doesn't include Z. We need to be able to\n  // find a symbolic facet from the require decl in Y during impl lookup.\n  //\n  // CHECK:STDERR: fail_todo_symbolic_facet_interface_requires_interface.carbon:[[@LINE+4]]:3: error: cannot access member of interface `Z(B)` in type `B` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   B.F();\n  // CHECK:STDERR:   ^~~\n  // CHECK:STDERR:\n  B.F();\n}\n\n// CHECK:STDOUT: --- a.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %X.type: type = facet_type <@X> [concrete]\n// CHECK:STDOUT:   %Self.f45: %X.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.f60: type = symbolic_binding_type Self, 0, %Self.f45 [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Z.type.0ed: type = facet_type <@Z, @Z(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.984: %Z.type.0ed = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Z.assoc_type.0bf: type = assoc_entity_type @Z, @Z(%T) [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.F.type.091: type = fn_type @Z.WithSelf.F, @Z.WithSelf(%T, %Self.984) [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.F.073: %Z.WithSelf.F.type.091 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Z.type.9f3244.1: type = facet_type <@Z, @Z(%Self.binding.as_type.f60)> [symbolic]\n// CHECK:STDOUT:   %Self.fcd60c.1: %Z.type.9f3244.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %require_complete.18ce0f.1: <witness> = require_complete_type %Z.type.9f3244.1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.9a5: type = pattern_type %X.type [concrete]\n// CHECK:STDOUT:   %A: %X.type = symbolic_binding A, 0 [symbolic]\n// CHECK:STDOUT:   %Y.type: type = facet_type <@Y> [concrete]\n// CHECK:STDOUT:   %Self.d4d: %Y.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.63e: type = symbolic_binding_type Self, 0, %Self.d4d [symbolic]\n// CHECK:STDOUT:   %Z.type.d16: type = facet_type <@Z, @Z(%Self.binding.as_type.63e)> [symbolic]\n// CHECK:STDOUT:   %Self.890: %Z.type.d16 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.95b: type = pattern_type %Y.type [concrete]\n// CHECK:STDOUT:   %B: %Y.type = symbolic_binding B, 1 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.binding.as_type: type = symbolic_binding_type A, 0, %A [symbolic]\n// CHECK:STDOUT:   %Z.type.9f3244.2: type = facet_type <@Z, @Z(%A.binding.as_type)> [symbolic]\n// CHECK:STDOUT:   %require_complete.18ce0f.2: <witness> = require_complete_type %Z.type.9f3244.2 [symbolic]\n// CHECK:STDOUT:   %Self.fcd60c.2: %Z.type.9f3244.2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.F.type.6cc: type = fn_type @Z.WithSelf.F, @Z.WithSelf(%A.binding.as_type, %Self.984) [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.F.926: %Z.WithSelf.F.type.6cc = struct_value () [symbolic]\n// CHECK:STDOUT:   %Z.assoc_type.449: type = assoc_entity_type @Z, @Z(%A.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %assoc0.9a4: %Z.assoc_type.449 = assoc_entity element0, imports.%Main.import_ref.7b4 [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.F.type.048: type = fn_type @Z.WithSelf.F, @Z.WithSelf(%A.binding.as_type, %A) [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.F.aaa: %Z.WithSelf.F.type.048 = struct_value () [symbolic]\n// CHECK:STDOUT:   %assoc0.20d: %Z.assoc_type.0bf = assoc_entity element0, imports.%Main.import_ref.47b [symbolic]\n// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %A, @Z, @Z(%A.binding.as_type) [symbolic]\n// CHECK:STDOUT:   %Z.facet: %Z.type.9f3244.2 = facet_value %A.binding.as_type, (%Z.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.F.type.501: type = fn_type @Z.WithSelf.F, @Z.WithSelf(%A.binding.as_type, %Z.facet) [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.F.cf6: %Z.WithSelf.F.type.501 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.d31: type = fn_type_with_self_type %Z.WithSelf.F.type.501, %Z.facet [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.d31 = impl_witness_access %Z.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Z.WithSelf.F(%A.binding.as_type, %Z.facet) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.Z = import_ref Main//a, Z, unloaded\n// CHECK:STDOUT:   %Main.Y: type = import_ref Main//a, Y, loaded [concrete = constants.%Y.type]\n// CHECK:STDOUT:   %Main.X: type = import_ref Main//a, X, loaded [concrete = constants.%X.type]\n// CHECK:STDOUT:   %Main.import_ref.13d: type = import_ref Main//a, loc12_31, loaded [symbolic = @X.WithSelf.%Z.type (constants.%Z.type.9f3244.1)]\n// CHECK:STDOUT:   %Main.import_ref.f56: @Z.WithSelf.%Z.assoc_type (%Z.assoc_type.0bf) = import_ref Main//a, loc4_9, loaded [symbolic = @Z.WithSelf.%assoc0 (constants.%assoc0.20d)]\n// CHECK:STDOUT:   %Main.F = import_ref Main//a, F, unloaded\n// CHECK:STDOUT:   %Main.import_ref.7b4: @Z.WithSelf.%Z.WithSelf.F.type (%Z.WithSelf.F.type.091) = import_ref Main//a, loc4_9, loaded [symbolic = @Z.WithSelf.%Z.WithSelf.F (constants.%Z.WithSelf.F.073)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//a, loc3_13, loaded [symbolic = @Z.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.1dc578.2: @Z.%Z.type (%Z.type.0ed) = import_ref Main//a, loc3_23, loaded [symbolic = @Z.%Self (constants.%Self.984)]\n// CHECK:STDOUT:   %Main.import_ref.145 = import_ref Main//a, loc3_23, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.3: type = import_ref Main//a, loc3_13, loaded [symbolic = @Z.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.67f: type = import_ref Main//a, loc12_18, loaded [symbolic = @X.WithSelf.Self.binding.as_type.impls.Z.type.require.%Self.binding.as_type (constants.%Self.binding.as_type.f60)]\n// CHECK:STDOUT:   %Main.import_ref.8d6: type = import_ref Main//a, loc12_30, loaded [symbolic = @X.WithSelf.Self.binding.as_type.impls.Z.type.require.%Z.type (constants.%Z.type.9f3244.1)]\n// CHECK:STDOUT:   %Main.import_ref.e33cd1.2: %X.type = import_ref Main//a, loc11_14, loaded [symbolic = constants.%Self.f45]\n// CHECK:STDOUT:   %Main.import_ref.65b = import_ref Main//a, loc11_14, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b51 = import_ref Main//a, loc8_31, unloaded\n// CHECK:STDOUT:   %Main.import_ref.7bb: type = import_ref Main//a, loc8_18, loaded [symbolic = @Y.WithSelf.Self.binding.as_type.impls.Z.type.require.%Self.binding.as_type (constants.%Self.binding.as_type.63e)]\n// CHECK:STDOUT:   %Main.import_ref.5ab: type = import_ref Main//a, loc8_30, loaded [symbolic = @Y.WithSelf.Self.binding.as_type.impls.Z.type.require.%Z.type (constants.%Z.type.d16)]\n// CHECK:STDOUT:   %Main.import_ref.8c73c0.2: %Y.type = import_ref Main//a, loc7_13, loaded [symbolic = constants.%Self.d4d]\n// CHECK:STDOUT:   %Main.import_ref.3e2 = import_ref Main//a, loc7_13, unloaded\n// CHECK:STDOUT:   %Main.import_ref.47b = import_ref Main//a, loc4_9, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Z = imports.%Main.Z\n// CHECK:STDOUT:     .Y = imports.%Main.Y\n// CHECK:STDOUT:     .X = imports.%Main.X\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_17.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_17.2 = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %A.patt: %pattern_type.9a5 = symbolic_binding_pattern A, 0 [concrete]\n// CHECK:STDOUT:     %B.patt: %pattern_type.95b = symbolic_binding_pattern B, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_10: type = splice_block %X.ref [concrete = constants.%X.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %X.ref: type = name_ref X, imports.%Main.X [concrete = constants.%X.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %A.loc4_6.2: %X.type = symbolic_binding A, 0 [symbolic = %A.loc4_6.1 (constants.%A)]\n// CHECK:STDOUT:     %.loc4_24: type = splice_block %Y.ref [concrete = constants.%Y.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Y.ref: type = name_ref Y, imports.%Main.Y [concrete = constants.%Y.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %B.loc4_20.2: %Y.type = symbolic_binding B, 1 [symbolic = %B.loc4_20.1 (constants.%B)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @Z(imports.%Main.import_ref.b3bc94.3: type) [from \"a.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z, @Z(%T)> [symbolic = %Z.type (constants.%Z.type.0ed)]\n// CHECK:STDOUT:   %Self: @Z.%Z.type (%Z.type.0ed) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.984)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.145\n// CHECK:STDOUT:     .F = imports.%Main.import_ref.f56\n// CHECK:STDOUT:     witness = (imports.%Main.F)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Y [from \"a.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.3e2\n// CHECK:STDOUT:   extend imports.%Main.import_ref.b51\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT:   @Y.WithSelf.Self.binding.as_type.impls.Z.type.require {\n// CHECK:STDOUT:     require imports.%Main.import_ref.7bb impls imports.%Main.import_ref.5ab\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: constraint @X [from \"a.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.65b\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend imports.%Main.import_ref.13d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT:   @X.WithSelf.Self.binding.as_type.impls.Z.type.require {\n// CHECK:STDOUT:     require imports.%Main.import_ref.67f impls imports.%Main.import_ref.8d6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @X.WithSelf.Self.binding.as_type.impls.Z.type.require(imports.%Main.import_ref.e33cd1.2: %X.type) [from \"a.carbon\"] {\n// CHECK:STDOUT:   %Self: %X.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.f45)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.f60)]\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z, @Z(%Self.binding.as_type)> [symbolic = %Z.type (constants.%Z.type.9f3244.1)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @Y.WithSelf.Self.binding.as_type.impls.Z.type.require(imports.%Main.import_ref.8c73c0.2: %Y.type) [from \"a.carbon\"] {\n// CHECK:STDOUT:   %Self: %Y.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.d4d)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.63e)]\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z, @Z(%Self.binding.as_type)> [symbolic = %Z.type (constants.%Z.type.d16)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Z.WithSelf.F(imports.%Main.import_ref.b3bc94.2: type, imports.%Main.import_ref.1dc578.2: @Z.%Z.type (%Z.type.0ed)) [from \"a.carbon\"] {\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%A.loc4_6.2: %X.type, %B.loc4_20.2: %Y.type) {\n// CHECK:STDOUT:   %A.loc4_6.1: %X.type = symbolic_binding A, 0 [symbolic = %A.loc4_6.1 (constants.%A)]\n// CHECK:STDOUT:   %B.loc4_20.1: %Y.type = symbolic_binding B, 1 [symbolic = %B.loc4_20.1 (constants.%B)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %A.binding.as_type: type = symbolic_binding_type A, 0, %A.loc4_6.1 [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z, @Z(%A.binding.as_type)> [symbolic = %Z.type (constants.%Z.type.9f3244.2)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Z.type [symbolic = %require_complete (constants.%require_complete.18ce0f.2)]\n// CHECK:STDOUT:   %Z.assoc_type: type = assoc_entity_type @Z, @Z(%A.binding.as_type) [symbolic = %Z.assoc_type (constants.%Z.assoc_type.449)]\n// CHECK:STDOUT:   %assoc0: @F.%Z.assoc_type (%Z.assoc_type.449) = assoc_entity element0, imports.%Main.import_ref.7b4 [symbolic = %assoc0 (constants.%assoc0.9a4)]\n// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %A.loc4_6.1, @Z, @Z(%A.binding.as_type) [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness)]\n// CHECK:STDOUT:   %Z.facet: @F.%Z.type (%Z.type.9f3244.2) = facet_value %A.binding.as_type, (%Z.lookup_impl_witness) [symbolic = %Z.facet (constants.%Z.facet)]\n// CHECK:STDOUT:   %Z.WithSelf.F.type: type = fn_type @Z.WithSelf.F, @Z.WithSelf(%A.binding.as_type, %Z.facet) [symbolic = %Z.WithSelf.F.type (constants.%Z.WithSelf.F.type.501)]\n// CHECK:STDOUT:   %.loc5_4.3: type = fn_type_with_self_type %Z.WithSelf.F.type, %Z.facet [symbolic = %.loc5_4.3 (constants.%.d31)]\n// CHECK:STDOUT:   %impl.elem0.loc5_4.2: @F.%.loc5_4.3 (%.d31) = impl_witness_access %Z.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc5_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc5_4.2: <specific function> = specific_impl_function %impl.elem0.loc5_4.2, @Z.WithSelf.F(%A.binding.as_type, %Z.facet) [symbolic = %specific_impl_fn.loc5_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %A.ref: %X.type = name_ref A, %A.loc4_6.2 [symbolic = %A.loc4_6.1 (constants.%A)]\n// CHECK:STDOUT:     %A.as_type: type = facet_access_type %A.ref [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:     %.loc5_4.1: type = converted %A.ref, %A.as_type [symbolic = %A.binding.as_type (constants.%A.binding.as_type)]\n// CHECK:STDOUT:     %.loc5_4.2: @F.%Z.assoc_type (%Z.assoc_type.449) = specific_constant imports.%Main.import_ref.f56, @Z.WithSelf(constants.%A.binding.as_type, constants.%A) [symbolic = %assoc0 (constants.%assoc0.9a4)]\n// CHECK:STDOUT:     %F.ref: @F.%Z.assoc_type (%Z.assoc_type.449) = name_ref F, %.loc5_4.2 [symbolic = %assoc0 (constants.%assoc0.9a4)]\n// CHECK:STDOUT:     %impl.elem0.loc5_4.1: @F.%.loc5_4.3 (%.d31) = impl_witness_access constants.%Z.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc5_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %specific_impl_fn.loc5_4.1: <specific function> = specific_impl_function %impl.elem0.loc5_4.1, @Z.WithSelf.F(constants.%A.binding.as_type, constants.%Z.facet) [symbolic = %specific_impl_fn.loc5_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %Z.WithSelf.F.call: init %empty_tuple.type = call %specific_impl_fn.loc5_4.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%T, constants.%Self.984) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf.F(constants.%T, constants.%Self.984) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z(constants.%Self.binding.as_type.f60) {\n// CHECK:STDOUT:   %T => constants.%Self.binding.as_type.f60\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.9f3244.1\n// CHECK:STDOUT:   %Self => constants.%Self.fcd60c.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.WithSelf(constants.%Self.f45) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.f45\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.f60\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.9f3244.1\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.18ce0f.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.WithSelf.Self.binding.as_type.impls.Z.type.require(constants.%Self.f45) {\n// CHECK:STDOUT:   %Self => constants.%Self.f45\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.f60\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.9f3244.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z(constants.%Self.binding.as_type.63e) {\n// CHECK:STDOUT:   %T => constants.%Self.binding.as_type.63e\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.d16\n// CHECK:STDOUT:   %Self => constants.%Self.890\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Y.WithSelf(constants.%Self.d4d) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Y.WithSelf.Self.binding.as_type.impls.Z.type.require(constants.%Self.d4d) {\n// CHECK:STDOUT:   %Self => constants.%Self.d4d\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.63e\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.d16\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%A, constants.%B) {\n// CHECK:STDOUT:   %A.loc4_6.1 => constants.%A\n// CHECK:STDOUT:   %B.loc4_20.1 => constants.%B\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.WithSelf(constants.%A) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%A\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%A.binding.as_type\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.9f3244.2\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.18ce0f.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z(constants.%A.binding.as_type) {\n// CHECK:STDOUT:   %T => constants.%A.binding.as_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.9f3244.2\n// CHECK:STDOUT:   %Self => constants.%Self.fcd60c.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%A.binding.as_type, constants.%Self.984) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%A.binding.as_type\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.9f3244.2\n// CHECK:STDOUT:   %Self => constants.%Self.984\n// CHECK:STDOUT:   %Z.WithSelf.F.type => constants.%Z.WithSelf.F.type.6cc\n// CHECK:STDOUT:   %Z.WithSelf.F => constants.%Z.WithSelf.F.926\n// CHECK:STDOUT:   %Z.assoc_type => constants.%Z.assoc_type.449\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.9a4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%A.binding.as_type, constants.%A) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%A.binding.as_type\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.9f3244.2\n// CHECK:STDOUT:   %Self => constants.%A\n// CHECK:STDOUT:   %Z.WithSelf.F.type => constants.%Z.WithSelf.F.type.048\n// CHECK:STDOUT:   %Z.WithSelf.F => constants.%Z.WithSelf.F.aaa\n// CHECK:STDOUT:   %Z.assoc_type => constants.%Z.assoc_type.449\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.9a4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.WithSelf.Self.binding.as_type.impls.Z.type.require(constants.%A) {\n// CHECK:STDOUT:   %Self => constants.%A\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%A.binding.as_type\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.9f3244.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%A.binding.as_type, constants.%Z.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%A.binding.as_type\n// CHECK:STDOUT:   %Z.type => constants.%Z.type.9f3244.2\n// CHECK:STDOUT:   %Self => constants.%Z.facet\n// CHECK:STDOUT:   %Z.WithSelf.F.type => constants.%Z.WithSelf.F.type.501\n// CHECK:STDOUT:   %Z.WithSelf.F => constants.%Z.WithSelf.F.cf6\n// CHECK:STDOUT:   %Z.assoc_type => constants.%Z.assoc_type.449\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.9a4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf.F(constants.%A.binding.as_type, constants.%Z.facet) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/require_invalid.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/require_invalid.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/require_invalid.carbon\n\n// --- fail_require_outside_scope.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\n\n// CHECK:STDERR: fail_require_outside_scope.carbon:[[@LINE+4]]:1: error: `require` can only be used in an `interface` or `constraint` [RequireInWrongScope]\n// CHECK:STDERR: require impls Y;\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nrequire impls Y;\n\n// --- fail_require_in_class.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\n\nclass C {\n  // CHECK:STDERR: fail_require_in_class.carbon:[[@LINE+4]]:3: error: `require` can only be used in an `interface` or `constraint` [RequireInWrongScope]\n  // CHECK:STDERR:   require impls Y;\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  require impls Y;\n}\n\n// --- fail_require_in_fn.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\n\nfn F() {\n  // require is not allowed outside of `interface` or `constraint`.\n  //\n  // CHECK:STDERR: fail_require_in_fn.carbon:[[@LINE+8]]:3: error: expected expression [ExpectedExpr]\n  // CHECK:STDERR:   require impls Y;\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_require_in_fn.carbon:[[@LINE+4]]:3: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n  // CHECK:STDERR:   require impls Y;\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  require impls Y;\n}\n\n// --- fail_require_in_nested_class.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\n\ninterface Z {\n  // TODO: Add `default` modifier.\n  fn F() {\n    class C {\n      // CHECK:STDERR: fail_require_in_nested_class.carbon:[[@LINE+4]]:7: error: `require` can only be used in an `interface` or `constraint` [RequireInWrongScope]\n      // CHECK:STDERR:       require impls Y;\n      // CHECK:STDERR:       ^~~~~~~\n      // CHECK:STDERR:\n      require impls Y;\n    }\n  }\n}\n\n// --- fail_require_in_nested_fn.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\n\ninterface Z {\n  // TODO: Add `default` modifier.\n  fn F() {\n    // require is not allowed outside of `interface` or `constraint`.\n    //\n    // CHECK:STDERR: fail_require_in_nested_fn.carbon:[[@LINE+8]]:5: error: expected expression [ExpectedExpr]\n    // CHECK:STDERR:     require impls Y;\n    // CHECK:STDERR:     ^~~~~~~\n    // CHECK:STDERR:\n    // CHECK:STDERR: fail_require_in_nested_fn.carbon:[[@LINE+4]]:5: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n    // CHECK:STDERR:     require impls Y;\n    // CHECK:STDERR:     ^~~~~~~\n    // CHECK:STDERR:\n    require impls Y;\n  }\n}\n\n// --- fail_errors_in_require_still_found.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  // The `require` is diagnosed as being in the wrong place. But we can still\n  // diagnose issues inside the decl too.\n  //\n  // CHECK:STDERR: fail_errors_in_require_still_found.carbon:[[@LINE+8]]:3: error: `require` can only be used in an `interface` or `constraint` [RequireInWrongScope]\n  // CHECK:STDERR:   require impls Y;\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_errors_in_require_still_found.carbon:[[@LINE+4]]:17: error: name `Y` not found [NameNotFound]\n  // CHECK:STDERR:   require impls Y;\n  // CHECK:STDERR:                 ^\n  // CHECK:STDERR:\n  require impls Y;\n}\n\n// --- fail_extend_require_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\n\ninterface Z {\n  // CHECK:STDERR: fail_extend_require_type.carbon:[[@LINE+4]]:18: error: `extend require impls` with explicit type [RequireImplsExtendWithExplicitSelf]\n  // CHECK:STDERR:   extend require () impls Y;\n  // CHECK:STDERR:                  ^~\n  // CHECK:STDERR:\n  extend require () impls Y;\n\n  fn F() {\n    // The erroneous self-type for an `extend` causes the error to be propagated\n    // into the interface scope, which prevents errors if we fail to find a name\n    // in that scope.\n    Self.A;\n  }\n}\n\n// --- fail_require_with_nonexistent_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\n\ninterface Z {\n  // CHECK:STDERR: fail_require_with_nonexistent_type.carbon:[[@LINE+4]]:11: error: name `nonexistent` not found [NameNotFound]\n  // CHECK:STDERR:   require nonexistent impls Y;\n  // CHECK:STDERR:           ^~~~~~~~~~~\n  // CHECK:STDERR:\n  require nonexistent impls Y;\n\n  fn F() {\n    // The name lookup error still happens, since the `require` is not `extend`.\n    // CHECK:STDERR: fail_require_with_nonexistent_type.carbon:[[@LINE+4]]:5: error: member name `A` not found in `Z` [MemberNameNotFoundInSpecificScope]\n    // CHECK:STDERR:     Self.A;\n    // CHECK:STDERR:     ^~~~~~\n    // CHECK:STDERR:\n    Self.A;\n  }\n}\n\n// --- fail_extend_require_with_nonexistent_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\n\ninterface Z {\n  // CHECK:STDERR: fail_extend_require_with_nonexistent_type.carbon:[[@LINE+4]]:18: error: name `nonexistent` not found [NameNotFound]\n  // CHECK:STDERR:   extend require nonexistent impls Y;\n  // CHECK:STDERR:                  ^~~~~~~~~~~\n  // CHECK:STDERR:\n  extend require nonexistent impls Y;\n\n  fn F() {\n    // The erroneous self-type for an `extend` causes the error to be propagated\n    // into the interface scope, which prevents errors if we fail to find a name\n    // in that scope.\n    Self.A;\n  }\n}\n\n// --- fail_extend_require_with_nonexistent_type_pointer.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\n\ninterface Z {\n  // CHECK:STDERR: fail_extend_require_with_nonexistent_type_pointer.carbon:[[@LINE+4]]:18: error: name `nonexistent` not found [NameNotFound]\n  // CHECK:STDERR:   extend require nonexistent* impls Y;\n  // CHECK:STDERR:                  ^~~~~~~~~~~\n  // CHECK:STDERR:\n  extend require nonexistent* impls Y;\n\n  fn F() {\n    // The erroneous self-type for an `extend` causes the error to be propagated\n    // into the interface scope, which prevents errors if we fail to find a name\n    // in that scope.\n    Self.A;\n  }\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/require_satisified.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/require_satisified.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/require_satisified.carbon\n\n// --- fail_missing_require_for_concrete_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\ninterface Y {\n  extend require impls Z;\n}\n\n// () does not need to impl Z yet.\nimpl () as Y;\n\n// () needs to impl Z at the start of the definition.\n// CHECK:STDERR: fail_missing_require_for_concrete_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `()` implements `Z` [RequireImplsNotImplemented]\n// CHECK:STDERR: impl () as Y {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as Y {}\n\n// --- fail_missing_require_for_symbolic_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\ninterface Y {\n  extend require impls Z;\n}\n\n// T does not need to impl Z yet.\nimpl forall [T:! type] T as Y;\n\n// T needs to impl Z at the start of the definition.\n// CHECK:STDERR: fail_missing_require_for_symbolic_type.carbon:[[@LINE+4]]:1: error: interface `Y` being implemented requires that `T` implements `Z` [RequireImplsNotImplemented]\n// CHECK:STDERR: impl forall [T:! type] T as Y {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] T as Y {}\n\n// --- fail_missing_require_double.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z1(T:! type) {}\ninterface Z2(T:! type) {}\n\nclass A;\nclass B;\n\ninterface Y(U:! type) {\n  extend require impls Z1(U) & Z2(B);\n}\n\n// CHECK:STDERR: fail_missing_require_double.carbon:[[@LINE+4]]:1: error: interface `Y(A)` being implemented requires that `()` implements `Z1(A) & Z2(B)` [RequireImplsNotImplemented]\n// CHECK:STDERR: impl () as Y(A) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as Y(A) {}\n\n// --- require_for_concrete_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\ninterface Y {\n  extend require impls Z;\n}\n\n// () does not need to impl Z yet.\nimpl () as Y;\n\n// Now we know () impls Z.\nimpl () as Z;\n\n// So no error here.\nimpl () as Y {}\n\nimpl () as Z {}\n\n// --- require_for_symbolic_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\ninterface Y {\n  extend require impls Z;\n}\n\n// T does not need to impl Z yet.\nimpl forall [T:! type] T as Y;\n\n// Now we know T impls Z.\nimpl forall [T:! type] T as Z;\n\n// So no error here.\nimpl forall [T:! type] T as Y {}\n\nimpl forall [T:! type] T as Z {}\n\n// --- require_for_symbolic_type_impl_matches_same_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\ninterface Y {\n  extend require impls Z;\n}\n\n// This only matches T that impl Z so no error here.\nimpl forall [T:! Z] T as Y {}\n\n// --- require_for_generic_interfaces.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z1(T:! type) {}\ninterface Z2(T:! type) {}\n\nclass A;\nclass B;\n\ninterface Y(U:! type) {\n  extend require impls Z1(U) & Z2(B);\n}\n\n// () does not need to impl Z1(A) and Z2(B) yet.\nimpl () as Y(A);\n\n// Now we know () impls Z1(A) and Z2(B).\nimpl () as Z1(A);\nimpl () as Z2(B);\n\n// So no error here.\nimpl () as Y(A) {}\n\nimpl () as Z1(A) {}\nimpl () as Z2(B) {}\n\n// --- fail_require_non_self_missing.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z(T:! type) {}\n\nclass C;\n\ninterface Y(U:! type) {\n  // `Self` must appear somewhere in the require decl, so it's in the interface\n  // specific because we want to test a different self-type.\n  require C impls Z(Self);\n}\n\n// Y requires that C impls Z(Self), but it does not do so.\n// CHECK:STDERR: fail_require_non_self_missing.carbon:[[@LINE+4]]:1: error: interface `Y(())` being implemented requires that `C` implements `Z(())` [RequireImplsNotImplemented]\n// CHECK:STDERR: impl () as Y(()) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as Y(()) {}\n\n// --- require_non_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z(T:! type) {}\n\nclass C;\n\ninterface Y(U:! type) {\n  // `Self` must appear somewhere in the require decl, so it's in the interface\n  // specific because we want to test a different self-type.\n  require C impls Z(Self);\n}\n\nimpl C as Z(());\n\n// Y requires that C impls Z(Self), which is done above.\nimpl () as Y(Self) {}\n\nimpl C as Z(()) {}\n\n// --- impl_requires_itself_cycle.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A { fn AA(); }\ninterface B {\n  require impls A;\n}\ninterface C {\n  require impls B;\n}\n\nimpl forall [T:! B] T as A { fn AA() {} }\n\n// When we get to the definition we check that anything B requires is satisfied.\n// - The interface B requires A, so we must check T impls A.\n// - The impl for A requires T impls B.\n// - This impl is what provides T impls B.\nimpl forall [T:! C] T as B {}\n\nfn F(T:! C) {\n  // If things go wrong, we find the impl `T as B`, but inside its definition is\n  // a lookup for `T as A`, which (through deducing `T`) includes a lookup for\n  // `T as B`. This creates a cycle of evaluating `T as B` recursively.\n  //\n  // This was solved by doing the check for requirements of `B` outside the\n  // definition of `T as B`.\n  // https://discord.com/channels/655572317891461132/941071822756143115/1463189087598022861\n  T.(A.AA)();\n}\n\n// --- fail_impl_requires_itself_cycle_with_monomorphization_error.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass W(T:! type) {\n  adapt {};\n}\n\ninterface A(N:! Core.IntLiteral()) {\n  fn AA() -> W(array((), N));\n}\ninterface B(N:! Core.IntLiteral()) {\n  require impls A(N);\n}\ninterface C(N:! Core.IntLiteral()) {\n  require impls B(N);\n}\n\nimpl forall [N:! Core.IntLiteral(), T:! B(N)] T as A(N) {\n  fn AA() -> W(array((), N)) { return {} as W(array((), N)); }\n}\n\nimpl forall [N:! Core.IntLiteral(), T:! C(N)] T as B(N) {\n  // The definition here does not contain the lookups verifying that C(N) impls\n  // `A(N)`, so they do not get re-evaluated for a specific `N`. That doesn't\n  // prevent us from producing a reasonable diagnostic when that `N` causes an\n  // error in the specific use of this impl, which we use to get from `C(N)` to\n  // `A(N)` (in the deduction of `T` in the impl as `A(N)`). The error just\n  // happens where we use `N` in `A(N)` instead of inside the verification that\n  // `T as B(N)` implies `T as A(N)`.\n}\n\nfn F(T:! C(-1)) {\n  // CHECK:STDERR: fail_impl_requires_itself_cycle_with_monomorphization_error.carbon:[[@LINE+7]]:3: error: unable to monomorphize specific `AA()` [ResolvingSpecificHere]\n  // CHECK:STDERR:   T.(A(-1).AA)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_impl_requires_itself_cycle_with_monomorphization_error.carbon:[[@LINE-27]]:26: note: array bound of -1 is negative [ArrayBoundNegative]\n  // CHECK:STDERR:   fn AA() -> W(array((), N));\n  // CHECK:STDERR:                          ^\n  // CHECK:STDERR:\n  T.(A(-1).AA)();\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/runtime_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/runtime_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/runtime_value.carbon\n\n// --- facet_value_copy_from_reference.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\nclass C {\n  var i: I;\n}\n\nfn F(c: C) {\n  // Member access produces a reference, which is copied into the value\n  // binding.\n  //@dump-sem-ir-begin\n  let unused a: I = c.i;\n  //@dump-sem-ir-end\n}\n\n// --- fail_todo_facet_copy_narrowing_from_reference.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\ninterface J {}\n\nclass C {\n  var ij: I & J;\n}\n\nfn F(c: C) {\n  // Member access produces a reference, which is copied into the value\n  // binding.\n  //\n  // TODO: This copy should work, but the narrowing prevents it currently.\n  //\n  //@dump-sem-ir-begin\n  // CHECK:STDERR: fail_todo_facet_copy_narrowing_from_reference.carbon:[[@LINE+4]]:21: error: semantics TODO: `conversion of runtime facet value` [SemanticsTodo]\n  // CHECK:STDERR:   let unused a: I = c.ij;\n  // CHECK:STDERR:                     ^~~~\n  // CHECK:STDERR:\n  let unused a: I = c.ij;\n  //@dump-sem-ir-end\n}\n\n// --- fail_compound_member_lookup_in_runtime_facet_without_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n    let X:! type;\n}\n\n// CHECK:STDERR: fail_compound_member_lookup_in_runtime_facet_without_value.carbon:[[@LINE+4]]:15: error: semantics TODO: `associated value lookup on runtime facet value` [SemanticsTodo]\n// CHECK:STDERR: fn F(T: Z, v: T.(Z.X));\n// CHECK:STDERR:               ^~~~~~~\n// CHECK:STDERR:\nfn F(T: Z, v: T.(Z.X));\n\n// --- fail_member_lookup_in_runtime_facet_without_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let X:! type;\n}\n\n// TODO: Improve this diagnostic. The problem is that T is a runtime facet\n// _and_ its facet type doesn't specific a value for `.X`. Or make this work\n// by producing an ImplWitnessAccess that functions against a runtime facet.\n//\n// CHECK:STDERR: fail_member_lookup_in_runtime_facet_without_value.carbon:[[@LINE+4]]:15: error: cannot access member of interface `Z` in type `Z` that does not implement that interface [MissingImplInMemberAccess]\n// CHECK:STDERR: fn F(T: Z, v: T.X);\n// CHECK:STDERR:               ^~~\n// CHECK:STDERR:\nfn F(T: Z, v: T.X);\n\n// --- fail_todo_compound_member_lookup_in_runtime_facet_with_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n    let X:! type;\n}\n\n// TODO: We should be able to get the value of `.X` from the `FacetType` of\n// `T`.\n//\n// CHECK:STDERR: fail_todo_compound_member_lookup_in_runtime_facet_with_value.carbon:[[@LINE+4]]:29: error: semantics TODO: `conversion of runtime facet value` [SemanticsTodo]\n// CHECK:STDERR: fn F(T: Z where .X = (), v: T.(Z.X));\n// CHECK:STDERR:                             ^~~~~~~\n// CHECK:STDERR:\nfn F(T: Z where .X = (), v: T.(Z.X));\n\n// --- fail_todo_member_lookup_in_runtime_facet_with_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let X:! type;\n}\n\n// TODO: We should be able to get the value of `.X` from the `FacetType` of\n// `T`.\n//\n// CHECK:STDERR: fail_todo_member_lookup_in_runtime_facet_with_value.carbon:[[@LINE+4]]:29: error: cannot access member of interface `Z` in type `Z where .(Z.X) = ()` that does not implement that interface [MissingImplInMemberAccess]\n// CHECK:STDERR: fn F(T: Z where .X = (), v: T.X);\n// CHECK:STDERR:                             ^~~\n// CHECK:STDERR:\nfn F(T: Z where .X = (), v: T.X);\n\n// --- fail_todo_member_lookup_in_type_of_runtime_facet_with_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  fn G();\n}\n\nfn F(T: Z) {\n  // CHECK:STDERR: fail_todo_member_lookup_in_type_of_runtime_facet_with_value.carbon:[[@LINE+4]]:3: error: cannot access member of interface `Z` in type `Z` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   T.G();\n  // CHECK:STDERR:   ^~~\n  // CHECK:STDERR:\n  T.G();\n}\n\n// CHECK:STDOUT: --- facet_value_copy_from_reference.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %I.type [concrete]\n// CHECK:STDOUT:   %pattern_type.9d9: type = pattern_type %I.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.9d9 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %i.ref: %C.elem = name_ref i, @C.%.loc6 [concrete = @C.%.loc6]\n// CHECK:STDOUT:   %.loc13_22.1: ref %I.type = class_element_access %c.ref, element0\n// CHECK:STDOUT:   %.loc13_22.2: %I.type = acquire_value %.loc13_22.1\n// CHECK:STDOUT:   %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   %a: %I.type = value_binding a, %.loc13_22.2\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_facet_copy_narrowing_from_reference.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %facet_type: type = facet_type <@I & @J> [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %facet_type [concrete]\n// CHECK:STDOUT:   %pattern_type.9d9: type = pattern_type %I.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.9d9 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %ij.ref: %C.elem = name_ref ij, @C.%.loc7_9 [concrete = @C.%.loc7_9]\n// CHECK:STDOUT:   %.loc21_22.1: ref %facet_type = class_element_access %c.ref, element0\n// CHECK:STDOUT:   %.loc21_22.2: %facet_type = acquire_value %.loc21_22.1\n// CHECK:STDOUT:   %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   %a: %I.type = value_binding a, <error> [concrete = <error>]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/self_in_interface_param.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/self_in_interface_param.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/self_in_interface_param.carbon\n\ninterface I(T:! type) {\n  let I1:! type;\n}\n\n//@dump-sem-ir-begin\nfn F(T:! I(.Self) where .I1 = ()) -> T.I1 {\n  return ();\n}\n//@dump-sem-ir-end\n\nfn G(_:! I(.Self) where .I1 = ()) {}\n\n// CHECK:STDOUT: --- self_in_interface_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %.Self.binding.as_type.8db: type = symbolic_binding_type .Self, %.Self.c39 [symbolic_self]\n// CHECK:STDOUT:   %I.type.bee: type = facet_type <@I, @I(%.Self.binding.as_type.8db)> [symbolic_self]\n// CHECK:STDOUT:   %.Self.dad: %I.type.bee = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %I.assoc_type.c03: type = assoc_entity_type @I, @I(%.Self.binding.as_type.8db) [symbolic_self]\n// CHECK:STDOUT:   %assoc0.fe4: %I.assoc_type.c03 = assoc_entity element0, @I.WithSelf.%I1 [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type.b0b: type = symbolic_binding_type .Self, %.Self.dad [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness.3fc: <witness> = lookup_impl_witness %.Self.dad, @I, @I(%.Self.binding.as_type.8db) [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %I.lookup_impl_witness.3fc, element0 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I, @I(%.Self.binding.as_type.8db) where %impl.elem0 = %empty_tuple.type> [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.033: type = pattern_type %I_where.type [symbolic_self]\n// CHECK:STDOUT:   %T.706: %I_where.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.706 [symbolic]\n// CHECK:STDOUT:   %I.lookup_impl_witness.94d: <witness> = lookup_impl_witness %T.706, @I, @I(%.Self.binding.as_type.8db) [symbolic]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.033 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: %I_where.type = name_ref T, %T.loc18_6.2 [symbolic = %T.loc18_6.1 (constants.%T.706)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc18_39.1: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc18_39.2: %I.assoc_type.c03 = specific_constant @I1.%assoc0, @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%T.706) [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:     %I1.ref.loc18_39: %I.assoc_type.c03 = name_ref I1, %.loc18_39.2 [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:     %impl.elem0.loc18_39: type = impl_witness_access constants.%I.lookup_impl_witness.94d, element0 [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc18_39.3: Core.Form = init_form %impl.elem0.loc18_39 [concrete = constants.%.262]\n// CHECK:STDOUT:     %.loc18_19.1: type = splice_block %.loc18_19.2 [symbolic_self = constants.%I_where.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %.Self.ref.loc18_12: %type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.Self.as_type.loc18_17: type = facet_access_type %.Self.ref.loc18_12 [symbolic_self = constants.%.Self.binding.as_type.8db]\n// CHECK:STDOUT:       %.loc18_17: type = converted %.Self.ref.loc18_12, %.Self.as_type.loc18_17 [symbolic_self = constants.%.Self.binding.as_type.8db]\n// CHECK:STDOUT:       %I.type: type = facet_type <@I, @I(constants.%.Self.binding.as_type.8db)> [symbolic_self = constants.%I.type.bee]\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.Self.ref.loc18_25: %I.type.bee = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.dad]\n// CHECK:STDOUT:       %.Self.as_type.loc18_25: type = facet_access_type %.Self.ref.loc18_25 [symbolic_self = constants.%.Self.binding.as_type.b0b]\n// CHECK:STDOUT:       %.loc18_25.1: type = converted %.Self.ref.loc18_25, %.Self.as_type.loc18_25 [symbolic_self = constants.%.Self.binding.as_type.b0b]\n// CHECK:STDOUT:       %.loc18_25.2: %I.assoc_type.c03 = specific_constant @I1.%assoc0, @I.WithSelf(constants.%.Self.binding.as_type.8db, constants.%.Self.dad) [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:       %I1.ref.loc18_25: %I.assoc_type.c03 = name_ref I1, %.loc18_25.2 [symbolic_self = constants.%assoc0.fe4]\n// CHECK:STDOUT:       %impl.elem0.loc18_25: type = impl_witness_access constants.%I.lookup_impl_witness.3fc, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:       %.loc18_32.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc18_32.2: type = converted %.loc18_32.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.loc18_19.2: type = where_expr %.Self.2 [symbolic_self = constants.%I_where.type] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type.bee\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc18_25, %.loc18_32.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc18_6.2: %I_where.type = symbolic_binding T, 0 [symbolic = %T.loc18_6.1 (constants.%T.706)]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc18_6.2: %I_where.type) {\n// CHECK:STDOUT:   %T.loc18_6.1: %I_where.type = symbolic_binding T, 0 [symbolic = %T.loc18_6.1 (constants.%T.706)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc18_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc18_6.1, @I, @I(constants.%.Self.binding.as_type.8db) [symbolic = %I.lookup_impl_witness (constants.%I.lookup_impl_witness.94d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc19_11.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc19_11.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc19_12: init %empty_tuple.type = converted %.loc19_11.1, %.loc19_11.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     return %.loc19_12\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.706) {\n// CHECK:STDOUT:   %T.loc18_6.1 => constants.%T.706\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %I.lookup_impl_witness => constants.%I.lookup_impl_witness.94d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/facet/tuple_and_struct_type_literal.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/tuple_and_struct_type_literal.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/tuple_and_struct_type_literal.carbon\n\n// --- tuple_literal_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\ninterface Z {\n  let X:! Y;\n}\n\nimpl () as Y {}\n\n// The tuple literal converts implicitly to a type, and then to a facet value\n// satisfying `Y`.\nimpl forall [T:! type] T as Z where .X = () {}\n\n// --- complex_tuple_literal_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\ninterface Z {\n  let X:! Y;\n}\n\nimpl ((), {}) as Y {}\n\n// The tuple literal converts implicitly to a type, and then to a facet value\n// satisfying `Y`.\nimpl forall [T:! type] T as Z where .X = ((), {}) {}\n\n// --- fail_mismatch_tuple_literal_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\ninterface Z {\n  let X:! Y;\n}\n\nimpl ((), {}) as Y {}\n\n// CHECK:STDERR: fail_mismatch_tuple_literal_to_facet_value.carbon:[[@LINE+4]]:42: error: cannot convert type `({}, {})` into type implementing `Y` [ConversionFailureTypeToFacet]\n// CHECK:STDERR: impl forall [T:! type] T as Z where .X = ({}, {}) {}\n// CHECK:STDERR:                                          ^~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] T as Z where .X = ({}, {}) {}\n\n// --- struct_literal_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\ninterface Z {\n  let X:! Y;\n}\n\nimpl {} as Y {}\n\n// The struct literal converts implicitly to a type, and then to a facet value\n// satisfying `Y`.\nimpl forall [T:! type] T as Z where .X = {} {}\n\n// --- complex_struct_literal_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\ninterface Z {\n  let X:! Y;\n}\n\nimpl {.a: (), .b: {}} as Y {}\n\n// The struct literal converts implicitly to a type, and then to a facet value\n// satisfying `Y`.\nimpl forall [T:! type] T as Z where .X = {.a: (), .b: {}} {}\n\n// --- fail_mismatch_struct_literal_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\ninterface Z {\n  let X:! Y;\n}\n\nimpl {.a: (), .b: {}} as Y {}\n\n// CHECK:STDERR: fail_mismatch_struct_literal_to_facet_value.carbon:[[@LINE+4]]:42: error: cannot convert type `{.a: {}, .b: {}}` into type implementing `Y` [ConversionFailureTypeToFacet]\n// CHECK:STDERR: impl forall [T:! type] T as Z where .X = {.a: {}, .b: {}} {}\n// CHECK:STDERR:                                          ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] T as Z where .X = {.a: {}, .b: {}} {}\n\n// --- struct_literal_to_facet_type_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\nimpl forall [U:! type] U as Z {}\n\nconstraint N {}\n\nfn InterfaceParam(unused U:! Z) {}\nfn ConstraintParam(unused U:! N) {}\n\nfn F() {\n  InterfaceParam({});\n  ConstraintParam({});\n}\n\n// --- fail_struct_literal_with_field_to_facet_type_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\nimpl forall [U:! type] U as Z {}\n\nconstraint N {}\n\nfn InterfaceParam(unused U:! Z) {}\nfn ConstraintParam(unused U:! N) {}\n\nfn F() {\n  // CHECK:STDERR: fail_struct_literal_with_field_to_facet_type_parameter.carbon:[[@LINE+10]]:3: error: cannot implicitly convert non-type value of type `{.a: ()}` into type implementing `Z` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   InterfaceParam({.a = ()});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_struct_literal_with_field_to_facet_type_parameter.carbon:[[@LINE+7]]:3: note: type `{.a: ()}` does not implement interface `Core.ImplicitAs(Z)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   InterfaceParam({.a = ()});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_struct_literal_with_field_to_facet_type_parameter.carbon:[[@LINE-10]]:26: note: initializing generic parameter `U` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn InterfaceParam(unused U:! Z) {}\n  // CHECK:STDERR:                          ^\n  // CHECK:STDERR:\n  InterfaceParam({.a = ()});\n  // CHECK:STDERR: fail_struct_literal_with_field_to_facet_type_parameter.carbon:[[@LINE+10]]:3: error: cannot implicitly convert non-type value of type `{.a: ()}` into type implementing `N` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   ConstraintParam({.a = ()});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_struct_literal_with_field_to_facet_type_parameter.carbon:[[@LINE+7]]:3: note: type `{.a: ()}` does not implement interface `Core.ImplicitAs(N)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   ConstraintParam({.a = ()});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_struct_literal_with_field_to_facet_type_parameter.carbon:[[@LINE-20]]:27: note: initializing generic parameter `U` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn ConstraintParam(unused U:! N) {}\n  // CHECK:STDERR:                           ^\n  // CHECK:STDERR:\n  ConstraintParam({.a = ()});\n}\n\n// --- tuple_literal_to_facet_type_parameter.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\nimpl forall [U:! type] U as Z {}\n\nconstraint N {}\n\nfn InterfaceParam(unused U:! Z) {}\nfn ConstraintParam(unused U:! N) {}\n\nfn F() {\n  InterfaceParam(());\n  ConstraintParam(());\n\n  InterfaceParam(({}, ));\n  ConstraintParam(({}, ));\n\n  class C;\n  InterfaceParam(({}, C));\n  ConstraintParam(({}, C));\n}\n\n// --- struct_literal_to_generic_facet_type_parameter_with_concrete_specific.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z(U:! type) {}\nimpl forall [T:! type, U:! type] U as Z(T) {}\n\nconstraint N(U:! type) {}\n\nclass C;\nfn InterfaceParam(unused U:! Z(C)) {}\nfn ConstraintParam(unused U:! N(C)) {}\n\nfn F() {\n  InterfaceParam({});\n  ConstraintParam({});\n}\n\n// --- tuple_literal_to_generic_facet_type_parameter_with_concrete_specific.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z(U:! type) {}\nimpl forall [T:! type, U:! type] U as Z(T) {}\n\nconstraint N(U:! type) {}\n\nclass C;\nfn InterfaceParam(unused U:! Z(C)) {}\nfn ConstraintParam(unused U:! N(C)) {}\n\nfn F() {\n  InterfaceParam(());\n  ConstraintParam(());\n\n  InterfaceParam(({}, ));\n  ConstraintParam(({}, ));\n\n  class C;\n  InterfaceParam(({}, C));\n  ConstraintParam(({}, C));\n}\n\n// --- struct_literal_to_generic_facet_type_parameter_with_symbolic_specific.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z(U:! type) {}\nimpl forall [T:! type, U:! type] U as Z(T) {}\n\nconstraint N(U:! type) {}\n\nfn InterfaceParam(T:! type, unused U:! Z(T)) {}\nfn ConstraintParam(T:! type, unused U:! N(T)) {}\n\nfn F(T:! type) {\n  InterfaceParam((), {});\n  ConstraintParam((), {});\n\n  InterfaceParam(T, {});\n  ConstraintParam(T, {});\n}\n\n// --- tuple_literal_to_generic_facet_type_parameter_with_symbolic_specific.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z(U:! type) {}\nimpl forall [T:! type, U:! type] U as Z(T) {}\n\nconstraint N(U:! type) {}\n\nfn InterfaceParam(T:! type, unused U:! Z(T)) {}\nfn ConstraintParam(T:! type, unused U:! N(T)) {}\n\nfn F(T:! type) {\n  InterfaceParam({}, ());\n  ConstraintParam({}, ());\n\n  InterfaceParam(T, ());\n  ConstraintParam(T, ());\n\n  InterfaceParam(T, ({}, ));\n  ConstraintParam(T, ({}, ));\n\n  class C;\n  InterfaceParam(T, ({}, C));\n  ConstraintParam(T, ({}, C));\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/tuple_and_struct_type_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/tuple_and_struct_type_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/tuple_and_struct_type_value.carbon\n\n// --- tuple_value_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\nimpl forall [U:! type] U as Z {}\n\nconstraint N {}\n\nfn InterfaceParam(unused U:! Z) {}\nfn ConstraintParam(unused U:! N) {}\n\nfn F(T:! (type, ), U:! type, Empty:! ()) {\n  // Passes a symbolic binding of type TupleType.\n  InterfaceParam(T);\n  ConstraintParam(T);\n\n  // Passes a symbolic `type`.\n  InterfaceParam(U);\n  ConstraintParam(U);\n\n  InterfaceParam(Empty);\n  ConstraintParam(Empty);\n}\n\nfn G(T:! (type, )) {\n  F(T, (T.0, ), ());\n}\n\nfn H() {\n  G(({}, ));\n}\n\n// --- struct_value_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\nimpl forall [U:! type] U as Z {}\n\nconstraint N {}\n\nfn InterfaceParam(unused U:! Z) {}\nfn ConstraintParam(unused U:! N) {}\n\nfn F(T:! {}) {\n  // Passes a symbolic binding of type StructType.\n  InterfaceParam(T);\n  ConstraintParam(T);\n}\n\nfn G() {\n  F({});\n}\n\n// --- fail_struct_value_with_field_to_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\nimpl forall [U:! type] U as Z {}\n\nconstraint N {}\n\nfn InterfaceParam(unused U:! Z) {}\nfn ConstraintParam(unused U:! N) {}\n\nfn F(T:! {.a: type}) {\n  // CHECK:STDERR: fail_struct_value_with_field_to_facet_value.carbon:[[@LINE+10]]:3: error: cannot implicitly convert non-type value of type `{.a: type}` into type implementing `Z` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   InterfaceParam(T);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_struct_value_with_field_to_facet_value.carbon:[[@LINE+7]]:3: note: type `{.a: type}` does not implement interface `Core.ImplicitAs(Z)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   InterfaceParam(T);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_struct_value_with_field_to_facet_value.carbon:[[@LINE-10]]:26: note: initializing generic parameter `U` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn InterfaceParam(unused U:! Z) {}\n  // CHECK:STDERR:                          ^\n  // CHECK:STDERR:\n  InterfaceParam(T);\n  // CHECK:STDERR: fail_struct_value_with_field_to_facet_value.carbon:[[@LINE+10]]:3: error: cannot implicitly convert non-type value of type `{.a: type}` into type implementing `N` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   ConstraintParam(T);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_struct_value_with_field_to_facet_value.carbon:[[@LINE+7]]:3: note: type `{.a: type}` does not implement interface `Core.ImplicitAs(N)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   ConstraintParam(T);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_struct_value_with_field_to_facet_value.carbon:[[@LINE-20]]:27: note: initializing generic parameter `U` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn ConstraintParam(unused U:! N) {}\n  // CHECK:STDERR:                           ^\n  // CHECK:STDERR:\n  ConstraintParam(T);\n}\n\nfn G() {\n  F({.a = ()});\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/validate_impl_constraints.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/validate_impl_constraints.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/validate_impl_constraints.carbon\n\n// --- self_impls_modifies_assoc_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nfn F(unused T:! I where .X = ()) {}\n\nfn G(T:! I where .Self impls (I where .X = ())) {\n  F(T);\n}\n\n// --- fail_self_impls_modifies_assoc_constant_type_differs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nfn F(unused T:! I where .X = ()) {}\n\nfn G(T:! I where .Self impls (I where .X = {})) {\n  // CHECK:STDERR: fail_self_impls_modifies_assoc_constant_type_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = {}` into type implementing `I where .(I.X) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_self_impls_modifies_assoc_constant_type_differs.carbon:[[@LINE-6]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .X = ()) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- fail_todo_where_impls_tests_associated_constant_of_generic_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(U:! type) {}\n\n// C(U) impls M if U impls L.\ninterface L {}\ninterface M { let M0:! type; }\nimpl forall [U:! L] C(U) as M where .M0 = {} {}\n\n// U requires that C(.Self) impls M.\n// - C(.Self) impls M can be rewritten as C(U) impls M.\n// - C(U) impls M if U impls L => Requires U impls L.\nfn F(unused U:! type where C(.Self) impls (M where .M0 = {})) {}\n\nfn G(T:! L) {\n  // CHECK:STDERR: fail_todo_where_impls_tests_associated_constant_of_generic_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `L` into type implementing `type where...` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_todo_where_impls_tests_associated_constant_of_generic_type.carbon:[[@LINE-6]]:13: note: initializing generic parameter `U` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! type where C(.Self) impls (M where .M0 = {})) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- fail_where_impls_tests_associated_constant_of_generic_type_type_differs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(U:! type) {}\n\n// C(U) impls M if U impls L.\ninterface L {}\ninterface M { let M0:! type; }\nimpl forall [U:! L] C(U) as M where .M0 = () {}\n\n// U requires that C(.Self) impls M.\n// - C(.Self) impls M can be rewritten as C(U) impls M.\n// - C(U) impls M if U impls L => Requires U impls L.\nfn F(unused U:! type where C(.Self) impls (M where .M0 = {})) {}\n\nfn G(T:! L) {\n  // CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_type_type_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `L` into type implementing `type where...` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_where_impls_tests_associated_constant_of_generic_type_type_differs.carbon:[[@LINE-6]]:13: note: initializing generic parameter `U` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! type where C(.Self) impls (M where .M0 = {})) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- self_in_interface_generic_param_unconstrained.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\ninterface I(T:! type) {}\n\nfn F(unused T:! I(.Self) where .Self impls Z) {}\n\nfn G(T:! Z & I(.Self)) {\n  F(T);\n}\n\n// --- fail_todo_self_in_interface_generic_param_constrained.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\ninterface I(T:! Z) {}\n\n// Implied constraint: .Self impls Z, which is satisfied and checked at the end\n// of the fn signature.\n// CHECK:STDERR: fail_todo_self_in_interface_generic_param_constrained.carbon:[[@LINE+7]]:17: error: cannot convert type `.Self` that implements `type` into type implementing `Z` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: fn F(unused T:! I(.Self) where .Self impls Z) {}\n// CHECK:STDERR:                 ^~~~~~~~\n// CHECK:STDERR: fail_todo_self_in_interface_generic_param_constrained.carbon:[[@LINE-7]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: interface I(T:! Z) {}\n// CHECK:STDERR:             ^\n// CHECK:STDERR:\nfn F(unused T:! I(.Self) where .Self impls Z) {}\n\n// CHECK:STDERR: fail_todo_self_in_interface_generic_param_constrained.carbon:[[@LINE+7]]:14: error: cannot convert type `.Self` that implements `type` into type implementing `Z` [ConversionFailureFacetToFacet]\n// CHECK:STDERR: fn G(T:! Z & I(.Self)) {\n// CHECK:STDERR:              ^~~~~~~~\n// CHECK:STDERR: fail_todo_self_in_interface_generic_param_constrained.carbon:[[@LINE-16]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n// CHECK:STDERR: interface I(T:! Z) {}\n// CHECK:STDERR:             ^\n// CHECK:STDERR:\nfn G(T:! Z & I(.Self)) {\n  F(T);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/facet/validate_rewrite_constraints.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/facet/validate_rewrite_constraints.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/facet/validate_rewrite_constraints.carbon\n\n// --- facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nfn F(unused T:! I where .X = ()) {}\n\nfn G(T:! I where .X = ()) {\n  F(T);\n}\n\n// --- generic_interface_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) { let X:! type; }\n\nclass C;\nfinal impl forall [T:! type] T as I(()) where .X = () {}\nfinal impl forall [T:! type] T as I({}) where .X = {} {}\n\nfn F(U:! type, unused T:! I(U) where .X = ()) {}\nfn G() {\n  F((), C);\n}\n\n// --- fail_generic_interface_facet_value_wrong_specific_impl.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) { let X:! type; }\n\nclass C;\nfinal impl forall [T:! type] T as I(()) where .X = () {}\nfinal impl forall [T:! type] T as I({}) where .X = {} {}\n\nfn F(U:! type, unused T:! I(U) where .X = ()) {}\nfn G() {\n  // This finds the impl where `.X = {}`, but F requires that `.X = ()`.\n  //\n  // CHECK:STDERR: fail_generic_interface_facet_value_wrong_specific_impl.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `I({}) where .(I({}).X) = ()` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   F({}, C);\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR: fail_generic_interface_facet_value_wrong_specific_impl.carbon:[[@LINE-7]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn F(U:! type, unused T:! I(U) where .X = ()) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  F({}, C);\n}\n\n// --- dependent_rules.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\ninterface J { let Y:! type; }\n\nfn F(T:! I & J where .X = .Y) {\n  // Allowed since `T impls I`, `T impls J`, and has constraint providing\n  // T.(I.X) = T.(J.Y)`.\n  F(T);\n}\n\n// --- fail_convert.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nfn F(unused T:! I where .X = {.a: (), .b: {}}) {}\n\nfn H() {\n  class C;\n  impl C as I where .X = {.b: {}, .a: ()} {}\n  // CHECK:STDERR: fail_convert.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `I where .(I.X) = {.a: (), .b: {}}` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   F(C);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_convert.carbon:[[@LINE-8]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .X = {.a: (), .b: {}}) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(C);\n}\n\nfn G(T:! I where .X = {.b: {}, .a: ()}) {\n  // CHECK:STDERR: fail_convert.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = {.b: {}, .a: ()}` into type implementing `I where .(I.X) = {.a: (), .b: {}}` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_convert.carbon:[[@LINE-19]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .X = {.a: (), .b: {}}) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- fail_todo_dependent_rules_compound.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\ninterface J { let Y:! type; }\n\n// CHECK:STDERR: fail_todo_dependent_rules_compound.carbon:[[@LINE+8]]:23: error: expected identifier or `Self` after `.` [ExpectedIdentifierOrSelfAfterPeriod]\n// CHECK:STDERR: fn F(T:! I & J where .(I.X) = .(J.Y)) {\n// CHECK:STDERR:                       ^\n// CHECK:STDERR:\n// CHECK:STDERR: fail_todo_dependent_rules_compound.carbon:[[@LINE+4]]:23: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n// CHECK:STDERR: fn F(T:! I & J where .(I.X) = .(J.Y)) {\n// CHECK:STDERR:                       ^\n// CHECK:STDERR:\nfn F(T:! I & J where .(I.X) = .(J.Y)) {\n  // Allowed since `T impls I`, `T impls J`, and has constraint providing\n  // T.(I.X) = T.(J.Y)`.\n  F(T);\n}\n\n// --- parameterized_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) { let X:! type; }\n\nfinal impl forall [J:! I(()) where .X = ()] J as I({}) where .X = {} {}\n\nfn F(unused T:! I({}) where .X = {}) {}\n\nfn G(T:! I(()) where .X = ()) {\n  F(T);\n}\n\n// --- fail_todo_parameterized_interface_compound.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) { let X:! type; }\n\nfinal impl forall [J:! I(())] J as I({}) where .X = {} {}\n\n// CHECK:STDERR: fail_todo_parameterized_interface_compound.carbon:[[@LINE+8]]:31: error: expected identifier or `Self` after `.` [ExpectedIdentifierOrSelfAfterPeriod]\n// CHECK:STDERR: fn F(T:! I(()) & I({}) where .(I(()).X) = () and .(I({}).X) = {}) {}\n// CHECK:STDERR:                               ^\n// CHECK:STDERR:\n// CHECK:STDERR: fail_todo_parameterized_interface_compound.carbon:[[@LINE+4]]:31: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n// CHECK:STDERR: fn F(T:! I(()) & I({}) where .(I(()).X) = () and .(I({}).X) = {}) {}\n// CHECK:STDERR:                               ^\n// CHECK:STDERR:\nfn F(T:! I(()) & I({}) where .(I(()).X) = () and .(I({}).X) = {}) {}\n\nfn G(T:! I(()) where .X = ()) {\n  F(T);\n}\n\n// --- fail_parameterized_interface_with_wrong_where_in_impl_deduction.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) { let X:! type; }\n\nfinal impl forall [J:! I(()) where .X = {}] J as I({}) where .X = {} {}\n\nfn F(unused T:! I({}) where .X = {}) {}\n\nfn G(T:! I(()) where .X = ()) {\n  // CHECK:STDERR: fail_parameterized_interface_with_wrong_where_in_impl_deduction.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I(()) where .(I(()).X) = ()` into type implementing `I({}) where .(I({}).X) = {}` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_parameterized_interface_with_wrong_where_in_impl_deduction.carbon:[[@LINE-6]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I({}) where .X = {}) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- source_rhs_is_assoc_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n}\n\nfn F(unused T:! I where .X1 = () and .X2 = ()) {}\n\nfn G() {\n  class C;\n  impl C as I where .X1 = .X2 and .X2 = () {}\n  F(C);\n}\n\nfn H(T:! I where .X1 = .X2 and .X2 = ()) {\n  F(T);\n}\n\n// --- target_rhs_is_assoc_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n}\n\nfn F(unused T:! I where .X1 = .X2 and .X2 = ()) {}\n\nfn G() {\n  class C;\n  impl C as I where .X1 = () and .X2 = () {}\n  F(C);\n}\n\nfn H(T:! I where .X1 = () and .X2 = ()) {\n  F(T);\n}\n\n// --- both_rhs_is_assoc_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n}\n\nfn F(unused T:! I where .X1 = .X2 and .X2 = ()) {}\n\nfn G() {\n  class C1;\n  impl C1 as I where .X1 = .X2 and .X2 = () {}\n  F(C1);\n\n  class C2;\n  impl C2 as I where .X1 = () and .X2 = .X1 {}\n  F(C2);\n}\n\nfn H1(T:! I where .X1 = .X2 and .X2 = ()) {\n  F(T);\n}\n\nfn H2(T:! I where .X1 = () and .X2 = .X1) {\n  F(T);\n}\n\n// --- fail_error_in_witness_table.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n}\n\nfn F(unused T:! I where .X1 = .X2) {}\n\nclass C;\n// .X2 is not set in the impl definition, so its value is an ErrorInst\n// in the impl's witness table.\n//\n// CHECK:STDERR: fail_error_in_witness_table.carbon:[[@LINE+7]]:1: error: associated constant X2 not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]\n// CHECK:STDERR: impl C as I where .X1 = () {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_error_in_witness_table.carbon:[[@LINE-12]]:7: note: associated constant declared here [AssociatedConstantHere]\n// CHECK:STDERR:   let X2:! type;\n// CHECK:STDERR:       ^~~~~~~~~\n// CHECK:STDERR:\nimpl C as I where .X1 = () {}\n\nfn G() {\n  // CHECK:STDERR: fail_error_in_witness_table.carbon:[[@LINE+7]]:3: error: cannot convert type `C` into type implementing `I where .(I.X1) = .(I.X2)` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   F(C);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_error_in_witness_table.carbon:[[@LINE-19]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .X1 = .X2) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(C);\n}\n\n// --- impl_provides_rewrite_requirements.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\ninterface J { let Y:! type; }\n\nclass C;\n\nfinal impl forall [T:! I] T as J where .Y = C {}\n\nfn F(unused T:! I & J where .Y = C) {}\nfn G(T:! I) {\n  F(T);\n}\n\n// --- facet_provides_rewrite_requirements.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\ninterface J { let Y:! type; }\n\nclass C;\n\nfinal impl forall [T:! J] T as I {}\n\nfn F(unused T:! I & J where .Y = C) {}\nfn G(T:! J where .Y = C) {\n  F(T);\n}\n\n// --- fail_non_final_impl_deduce.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nimpl forall [U:! type] U as I where .X = () {}\n\nfn F(unused T:! I where .X = ()) {}\n\nclass C(T:! type);\n\nfn G(T:! type) {\n  // The type `C(T)` is generic so that the resulting impl witness will not be\n  // effectively final.\n  //\n  // CHECK:STDERR: fail_non_final_impl_deduce.carbon:[[@LINE+7]]:3: error: cannot convert type `C(T)` into type implementing `I where .(I.X) = ()` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   F(C(T));\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_non_final_impl_deduce.carbon:[[@LINE-11]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .X = ()) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(C(T));\n}\n\n// --- fail_non_final_impl_explicit.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nimpl forall [U:! type] U as I where .X = () {}\n\nclass C(T:! type);\n\nfn F(T:! type) {\n  // The type `C(T)` is generic so that the resulting impl witness will not be\n  // effectively final.\n  //\n  // CHECK:STDERR: fail_non_final_impl_explicit.carbon:[[@LINE+4]]:3: error: cannot convert type `C(T)` into type implementing `I where .(I.X) = ()` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   C(T) as (I where .X = ());\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  C(T) as (I where .X = ());\n}\n\n// --- concrete_query_non_final_impl_deduce.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nimpl forall [U:! type] U as I where .X = () {}\n\nfn F(unused T:! I where .X = ()) {}\n\nfn G() {\n  class C;\n  F(C);\n}\n\n// --- concrete_query_non_final_impl_explicit_as.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nimpl forall [U:! type] U as I where .X = () {}\n\nfn F() {\nclass C;\n  C as (I where .X = ());\n}\n\n// --- final_impl_deduce.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nfinal impl forall [U:! type] U as I where .X = () {}\n\nfn F(unused T:! I where .X = ()) {}\n\nfn G() {\n  class C;\n  F(C);\n}\n\n// --- final_impl_explicit_as.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nfinal impl forall [U:! type] U as I where .X = () {}\n\nfn F() {\n  class C;\n  C as (I where .X = ());\n}\n\n// --- concrete_specialization_impl_deduce.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nclass C;\nimpl C as I where .X = () {}\n\nfn F(unused T:! I where .X = ()) {}\nfn G() {\n  F(C);\n}\n\n// --- concrete_specialization_impl_explicit_as.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\n\nclass C;\nimpl C as I where .X = () {}\n\nfn F() {\n  C as (I where .X = ());\n}\n\n// --- rewrite_value_in_class_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nclass C(T:! type);\n\nfn F(unused T:! I where .X = C(.Y)) {}\n\nfn G(T:! I where .X = C(()) and .Y = ()) {\n  F(T);\n}\n\n// --- fail_wrong_rewrite_value_in_class_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nclass C(T:! type);\n\nfn F(unused T:! I where .X = C(.Y)) {}\n\nfn G(T:! I where .X = C(()) and .Y = {}) {\n  // CHECK:STDERR: fail_wrong_rewrite_value_in_class_param.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = C(()) and .(I.Y) = {}` into type implementing `I where .(I.X) = C(.(I.Y))` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_wrong_rewrite_value_in_class_param.carbon:[[@LINE-6]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .X = C(.Y)) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- function_in_interface_ignored.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  fn F();\n}\n\nfn F(unused T:! I where .X = ()) {}\n\nfn G(T:! I where .X = ()) {\n  F(T);\n}\n\n// --- function_as_rewrite_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! X;\n  fn A();\n}\n\nfn F(unused T:! I where .Y = .A) {}\n\nfn G(T:! I where .Y = .A) {\n  F(T);\n}\n\n// --- fail_wrong_function_as_rewrite_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! X;\n  fn A();\n  fn B();\n}\n\nfn F(unused T:! I where .Y = .A) {}\n\nfn G(T:! I where .Y = .B) {\n  // CHECK:STDERR: fail_wrong_function_as_rewrite_value.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.Y) = .(I.B)` into type implementing `I where .(I.Y) = .(I.A)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_wrong_function_as_rewrite_value.carbon:[[@LINE-6]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .Y = .A) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- fail_wrong_function_as_rewrite_value_in_other_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! X;\n  fn A();\n}\n\ninterface J {\n  let J1:! type;\n  let J2:! type;\n  // B has the same index in J as A does in I, ensuring the index is not enough\n  // for comparing them.\n  fn B();\n}\n\nfn F(unused T:! I & J where .Y = .A) {}\n\nfn G(T:! I & J where .Y = .B) {\n  // CHECK:STDERR: fail_wrong_function_as_rewrite_value_in_other_interface.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I & J where .(I.Y) = .(J.B)` into type implementing `I & J where .(I.Y) = .(I.A)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_wrong_function_as_rewrite_value_in_other_interface.carbon:[[@LINE-6]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I & J where .Y = .A) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- recursive_facet.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I { let X:! type; }\ninterface K(Y:! type) {  }\n\nfn F(unused T:! I where .X = {.k: K(I where .X = ())}) {}\n\nfn G(T:! I where .X = {.k: K(I where .X = ())}) {\n  F(T);\n}\n\n// --- fail_facet_type_concrete_types_match_blanket_impl_concrete_types.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A { let X:! type; }\ninterface B { let Y:! type; }\n\ninterface C(BB:! B) { let AX:! type; let BY:! type; }\n\nimpl forall [AA:! A, BB:! B] AA as C(BB) where .AX = () and .BY = {} {}\n\nfn F(AA:! A where .X = (), BB:! B where .Y = {}) {\n  // The types match but there may be a specialization that specifies different\n  // types and would be prefered for a specific `AA` or `BB`.\n  //\n  // CHECK:STDERR: fail_facet_type_concrete_types_match_blanket_impl_concrete_types.carbon:[[@LINE+4]]:3: error: cannot convert type `AA` that implements `A where .(A.X) = ()` into type implementing `C(BB as B) where .(C(BB as B).AX) = () and .(C(BB as B).BY) = {}` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   AA as (C(BB) where .AX = () and .BY = {});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  AA as (C(BB) where .AX = () and .BY = {});\n}\n\n// --- fail_facet_type_concrete_types_become_blank_impl_types.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A { let X:! type; }\ninterface B { let Y:! type; }\n\ninterface C(BB:! B) { let AX:! type; let BY:! type; }\n\nimpl forall [AA:! A, BB:! B] AA as C(BB) where .AX = AA.X and .BY = BB.Y {}\n\nfn F(AA:! A where .X = (), BB:! B where .Y = {}) {\n  // The types match but there may be a specialization that specifies different\n  // types and would be prefered for a specific `AA` or `BB`.\n  //\n  // CHECK:STDERR: fail_facet_type_concrete_types_become_blank_impl_types.carbon:[[@LINE+4]]:3: error: cannot convert type `AA` that implements `A where .(A.X) = ()` into type implementing `C(BB as B) where .(C(BB as B).AX) = () and .(C(BB as B).BY) = {}` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   AA as (C(BB) where .AX = () and .BY = {});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  AA as (C(BB) where .AX = () and .BY = {});\n}\n\n// --- facet_type_concrete_types_match_final_blanket_impl_concrete_types.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A { let X:! type; }\ninterface B { let Y:! type; }\n\ninterface C(BB:! B) { let AX:! type; let BY:! type; }\n\nfinal impl forall [AA:! A, BB:! B] AA as C(BB) where .AX = () and .BY = {} {}\n\nfn F(AA:! A where .X = (), BB:! B where .Y = {}) {\n  AA as (C(BB) where .AX = () and .BY = {});\n}\n\n// --- facet_type_concrete_types_become_final_blanket_impl_types.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A { let X:! type; }\ninterface B { let Y:! type; }\n\ninterface C(BB:! B) { let AX:! type; let BY:! type; }\n\nfinal impl forall [AA:! A, BB:! B] AA as C(BB) where .AX = AA.X and .BY = BB.Y {}\n\nfn F(AA:! A where .X = (), BB:! B where .Y = {}) {\n  AA as (C(BB) where .AX = () and .BY = {});\n}\n\n// --- fail_facet_type_concrete_types_become_final_blanket_impl_types_wrong_types.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A { let X:! type; }\ninterface B { let Y:! type; }\n\ninterface C(BB:! B) { let AX:! type; let BY:! type; }\n\nfinal impl forall [AA:! A, BB:! B] AA as C(BB) where .AX = AA.X and .BY = BB.Y {}\n\nfn F(AA:! A where .X = (), BB:! B where .Y = {}) {\n  // CHECK:STDERR: fail_facet_type_concrete_types_become_final_blanket_impl_types_wrong_types.carbon:[[@LINE+4]]:3: error: cannot convert type `AA` that implements `A where .(A.X) = ()` into type implementing `C(BB as B) where .(C(BB as B).AX) = {} and .(C(BB as B).BY) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   AA as (C(BB) where .AX = {} and .BY = ());\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  AA as (C(BB) where .AX = {} and .BY = ());\n}\n\n// --- chain_in_target.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n  let X3:! type;\n}\n\nclass C(T:! type);\n\nfn F(unused T:! I where .X1 = .X3 and .X2 = C(.X3) and .X3 = ()) {}\n\nfn G(T:! I where .X1 = () and .X2 = C(()) and .X3 = ()) {\n  F(T);\n}\n\n// --- chain_in_source.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n  let X3:! type;\n}\n\nclass C(T:! type);\n\nfn F(unused T:! I where .X1 = () and .X2 = C(()) and .X3 = .X1) {}\n\nfn G(T:! I where .X1 = .X3 and .X2 = C(.X1) and .X3 = ()) {\n  F(T);\n}\n\n// --- reference_other_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! type;\n  let X2:! type;\n}\n\nfn F(U:! I where .X1 = {}, unused T:! I where .X1 = () and .X2 = U.X1) {}\n\nfn G(U:! I where .X1 = {} and .X2 = (), T:! I where .X1 = U.X2 and .X2 = {}) {\n  F(U, T);\n}\n\n// --- value_through_self_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X1:! I;\n  let X2:! type;\n  let X3:! type;\n}\n\nfn F(unused T:! I where .X1 = .Self and .X2 = .X1.X3 and .X3 = ()) {}\n\nfn G(T:! I where .X1 = .Self and .X2 = () and .X3 = ()) {\n  F(T);\n}\n\nfn H(T:! I where .X1 = .Self and .X2 = .X1.X3 and .X3 = ()) {\n  G(T);\n}\n\n// --- associated_constant_is_facet_type_of_same_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let A:! type;\n  let X:! type;\n}\n\nclass C;\n\n// This looks for a bug where `.Self.A` resolves to `C` from `.T.A` in the\n// incoming facet value, which is incorrect. It should be `.T.X.A` which\n// resolves to `{}`.\nfn F(unused U:! I where .X = (I where .A = {})) {}\n\nfn G(T:! I where .X = (I where .A = {}) and .A = C) {\n  F(T);\n}\n\n// --- rewrite_requires_subst_in_rhs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nclass C(T:! type);\n\nfn F(unused T:! I where .X = C(.Y)) {}\n\nfn G(T:! I where .X = C({}) and .Y = {}) {\n  F(T);\n}\n\n// --- fail_todo_rewrite_requires_subst_in_nested_facet_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  let X:! type;\n  let Y:! type;\n}\n\nclass C;\n\nfn F(unused T:! I(C) where .X = (I(.Y) where .Y = ())) {}\n\nfn G(T:! I(C) where .X = (I({}) where .Y = ()) and .Y = {}) {\n  // TODO: The T in G should match the T in F, once the .Self reference to the\n  // top level facet value in `I(.Y)` is correctly substituted by tracking that\n  // it is a .Self reference to the top level Self.\n  // CHECK:STDERR: fail_todo_rewrite_requires_subst_in_nested_facet_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I(C) where .(I(C).X) = I({}) where .(I({}).Y) = () and .(I(C).Y) = {}` into type implementing `I(C) where .(I(C).X) = I(.(I(C).Y)) where .(I(.(I(C).Y)).Y) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_todo_rewrite_requires_subst_in_nested_facet_type.carbon:[[@LINE-9]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I(C) where .X = (I(.Y) where .Y = ())) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\nfn G2(T:! I(C) where .X = (I(.Y) where .Y = ()) and .Y = {}) {\n  F(T);\n}\n\n// --- fail_rewrite_requires_subst_in_nested_facet_type_types_differ.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  let X:! type;\n  let Y:! type;\n}\n\nfn F(unused T:! I({}) where .X = (I(.Y) where .X = ())) {}\n\n// I(.Y) is I({}) which doesn't match I(()).\nfn G(T:! I({}) where .X = (I(()) where .X = ()) and .Y = {}) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_facet_type_types_differ.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I({}) where .(I({}).X) = I(()) where .(I(()).X) = () and .(I({}).Y) = {}` into type implementing `I({}) where .(I({}).X) = I(.(I({}).Y)) where .(I(.(I({}).Y)).X) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_facet_type_types_differ.carbon:[[@LINE-7]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I({}) where .X = (I(.Y) where .X = ())) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- facet_type_in_assoc_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn F(unused T:! I where .X = (I where .X = () and .Y = ())) {}\n\nfn G(T:! I where .X = (I where .X = .Y and .Y = ())) {\n  F(T);\n}\n\n// --- fail_facet_type_in_assoc_constant_differs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n  let Z:! type;\n}\n\nfn F(unused T:! I where .X = (I where .X = .Y)) {}\n\nfn G(T:! I where .X = (I where .X = () and .Y = () and .Z = {})) {\n  // CHECK:STDERR: fail_facet_type_in_assoc_constant_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = I where .(I.X) = () and .(I.Y) = () and .(I.Z) = {}` into type implementing `I where .(I.X) = I where .(I.X) = .(I.Y)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_facet_type_in_assoc_constant_differs.carbon:[[@LINE-6]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .X = (I where .X = .Y)) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- nested_facet_type_in_assoc_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n  let Z:! type;\n}\n\nfn F(unused T:! I where .X = (I where .Y = (I where .X = () and .Y = ()))) {}\n\nfn G(T:! I where .X = (I where .Y = (I where .X = .Y and .Y = ()))) {\n  F(T);\n}\n\n// --- fail_nested_facet_type_assigns_same_assoc_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn F(unused T:! I where .Y = ()) {}\n\n// The `.Y = ()` is on a different `.Self` than `T` (an unattached self), so\n// should not satisfy `F`.\nfn G(T:! I where .X = (I where .Y = ())) {\n  // CHECK:STDERR: fail_nested_facet_type_assigns_same_assoc_constant.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = I where .(I.Y) = ()` into type implementing `I where .(I.Y) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_nested_facet_type_assigns_same_assoc_constant.carbon:[[@LINE-8]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .Y = ()) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- fail_nested_facet_type_in_assoc_constant_differs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n  let Z:! type;\n}\n\nfn F(unused T:! I where .X = (I where .Y = (I where .X = .Y))) {}\n\n// `.X = .Y` does not match `.X = () and .Y = ()` as they are different resolved\n// facet types.\nfn G(T:! I where .X = (I where .Y = (I where .X = () and .Y = ()))) {\n  // CHECK:STDERR: fail_nested_facet_type_in_assoc_constant_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = I where .(I.Y) = I where .(I.X) = () and .(I.Y) = ()` into type implementing `I where .(I.X) = I where .(I.Y) = I where .(I.X) = .(I.Y)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_nested_facet_type_in_assoc_constant_differs.carbon:[[@LINE-8]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .X = (I where .Y = (I where .X = .Y))) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// The extra .Z rewrite makes a different resolved facet type which does not\n// match.\nfn G2(T:! I where .X = (I where .Y = (I where .X = .Y and .Z = {}))) {\n  // CHECK:STDERR: fail_nested_facet_type_in_assoc_constant_differs.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.X) = I where .(I.Y) = I where .(I.X) = .(I.Y) and .(I.Z) = {}` into type implementing `I where .(I.X) = I where .(I.Y) = I where .(I.X) = .(I.Y)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_nested_facet_type_in_assoc_constant_differs.carbon:[[@LINE-21]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .X = (I where .Y = (I where .X = .Y))) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- fail_nested_facet_type_from_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn F(unused T:! I where .X = (I where .Y = (I where .X = .Y, ))) {}\n\n// References to named constants in a facet type don't work at all. If they did,\n// then when the `Constant` facet type is put into the RHS of a rewrite\n// constraint, its references to `.Self` must be modified to not refer to the\n// top level `.Self` which is `T`. If done correctly, they will match the\n// `.Self` references in the same position in the parameter of `F`. If not, the\n// `.X` within becomes self-referential and makes a cycle.\n\nfn G1() {\n  // CHECK:STDERR: fail_nested_facet_type_from_constant.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let Constant:! type = I where .X = .Y;\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let Constant:! type = I where .X = .Y;\n\n  fn G(T:! I where .X = (I where .Y = (Constant, ))) {\n    F(T);\n  }\n}\n\nfn G2() {\n  let Constant:! type = (I where .X = .Y, );\n\n  fn G(T:! I where .X = (I where .Y = Constant)) {\n    F(T);\n  }\n}\n\nfn G3() {\n  let Constant:! type = I where .Y = (I where .X = .Y, );\n\n  fn G(T:! I where .X = Constant) {\n    F(T);\n  }\n}\n\nfn G4() {\n  let Constant2:! type = (I where .X = .Y, );\n  let Constant:! type = Constant2;\n\n  fn G(T:! I where .X = (I where .Y = Constant)) {\n    F(T);\n  }\n}\n\nfn G5() {\n  let Constant2:! type = I where .X = .Y;\n  let Constant:! type = (Constant2, );\n\n  fn G(T:! I where .X = (I where .Y = Constant)) {\n    F(T);\n  }\n}\n\nfn G6() {\n  let Constant2:! type = (I where .X = .Y, );\n  let Constant:! type = I where .Y = Constant2;\n\n  fn G(T:! I where .X = Constant) {\n    F(T);\n  }\n}\n\n// --- fail_nested_facet_type_from_constant_differs.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn F(unused T:! I where .X = (I where .Y = (I where .X = .Y, ))) {}\n\nfn G1() {\n  // CHECK:STDERR: fail_nested_facet_type_from_constant_differs.carbon:[[@LINE+4]]:7: error: semantics TODO: `local `let :!` bindings are currently unsupported` [SemanticsTodo]\n  // CHECK:STDERR:   let Constant:! type = I where .X = () and .Y = ();\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let Constant:! type = I where .X = () and .Y = ();\n\n  fn G(T:! I where .X = (I where .Y = (Constant, ))) {\n    F(T);\n  }\n}\n\n// --- rewrite_requires_subst_in_nested_access_of_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n  let I2:! type;\n}\n\ninterface J {\n  let J1:! I;\n}\n\ninterface K {\n  let K1:! J;\n}\n\nfn F(unused T:! I & J & K where .K1 = .Self and .J1 = .Self and .I1 = (.K1.J1).I2) {}\n\nfn G(T:! I & J & K where .K1 = .Self and .J1 = .Self and .I1 = .I2) {\n  F(T);\n}\n\n// --- fail_rewrite_requires_subst_in_nested_access_of_self_wrong_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n  let I2:! type;\n}\n\ninterface J {\n  let J1:! I;\n}\n\ninterface K {\n  let K1:! J;\n}\n\nfn F(unused T:! I & J & K where .K1 = .Self and .J1 = .Self and .I1 = (.K1.J1).I2) {}\n\n// F's requirement I1 = I2 is not met, as I1 = () and I2 = {}\nfn G(T:! I & J & K where .K1 = .Self and .J1 = .Self and .I1 = () and .I2 = {}) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_self_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I & J & K where .(K.K1) = .Self as J and .(J.J1) = .Self as I and .(I.I1) = () and .(I.I2) = {}` into type implementing `I & J & K where .(K.K1) = .Self as J and .(J.J1) = .Self as I and .(I.I1) = .(I.I2)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_self_wrong_type.carbon:[[@LINE-7]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I & J & K where .K1 = .Self and .J1 = .Self and .I1 = (.K1.J1).I2) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// F's requirement I1 = I2 is not met, as I1 = {} and I2 is unspecified\nfn G2(T:! I & J & K where .K1 = .Self and .J1 = .Self and .I1 = {}) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_self_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I & J & K where .(K.K1) = .Self as J and .(J.J1) = .Self as I and .(I.I1) = {}` into type implementing `I & J & K where .(K.K1) = .Self as J and .(J.J1) = .Self as I and .(I.I1) = .(I.I2)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_self_wrong_type.carbon:[[@LINE-19]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I & J & K where .K1 = .Self and .J1 = .Self and .I1 = (.K1.J1).I2) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// F's requirement I1 = I2 is not met, as I2 = {} and I1 is unspecified\nfn G3(T:! I & J & K where .K1 = .Self and .J1 = .Self and .I2 = {}) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_self_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I & J & K where .(K.K1) = .Self as J and .(J.J1) = .Self as I and .(I.I2) = {}` into type implementing `I & J & K where .(K.K1) = .Self as J and .(J.J1) = .Self as I and .(I.I1) = .(I.I2)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_self_wrong_type.carbon:[[@LINE-31]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I & J & K where .K1 = .Self and .J1 = .Self and .I1 = (.K1.J1).I2) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- fail_todo_rewrite_requires_subst_in_nested_access_of_other.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n}\n\ninterface J {\n  let J1:! I;\n  let J2:! type;\n}\n\ninterface K {\n  let K1:! J;\n}\n\n// .K1.J1 is an ImplWitnessAccess into Self. The Self witness will be subst'd in\n// for `U` and it will eval to the ImplWitnessAccess inside of `U.I1`. Then that\n// will need to be subst'd to find the value of I1 in U's witness.\nfn F(unused U:! I, unused T:! J & K where .J2 = (.K1.J1).I1) {}\n\nfn G(U:! I where .I1 = (), T:! J & K where .K1 = .Self and .J1 = U and .J2 = ()) {\n  // CHECK:STDERR: fail_todo_rewrite_requires_subst_in_nested_access_of_other.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `J & K where .(J.J2) = () and .(K.K1) = .Self as J and .(J.J1) = U as I` into type implementing `J & K where .(J.J2) = .(K.K1).(J.J1).(I.I1)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(U, T);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_todo_rewrite_requires_subst_in_nested_access_of_other.carbon:[[@LINE-6]]:27: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! I, unused T:! J & K where .J2 = (.K1.J1).I1) {}\n  // CHECK:STDERR:                           ^\n  // CHECK:STDERR:\n  F(U, T);\n}\n\n// --- fail_rewrite_requires_subst_in_nested_access_of_other_wrong_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n}\n\ninterface J {\n  let J1:! I;\n  let J2:! type;\n}\n\ninterface K {\n  let K1:! J;\n}\n\nfn F(unused U:! I, unused T:! J & K where .J2 = (.K1.J1).I1) {}\n\n// F's requirement J2 = I1 is not met as J2 = () and I1 = {}\nfn G(U:! I where .I1 = {}, T:! J & K where .K1 = .Self and .J1 = U and .J2 = ()) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `J & K where .(J.J2) = () and .(K.K1) = .Self as J and .(J.J1) = U as I` into type implementing `J & K where .(J.J2) = .(K.K1).(J.J1).(I.I1)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(U, T);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_wrong_type.carbon:[[@LINE-7]]:27: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! I, unused T:! J & K where .J2 = (.K1.J1).I1) {}\n  // CHECK:STDERR:                           ^\n  // CHECK:STDERR:\n  F(U, T);\n}\n\n// F's requirement J2 = I1 is not met as J2 = () and I1 is unspecified\nfn G2(U:! I, T:! J & K where .K1 = .Self and .J1 = U and .J2 = ()) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `J & K where .(J.J2) = () and .(K.K1) = .Self as J and .(J.J1) = U` into type implementing `J & K where .(J.J2) = .(K.K1).(J.J1).(I.I1)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(U, T);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_wrong_type.carbon:[[@LINE-19]]:27: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! I, unused T:! J & K where .J2 = (.K1.J1).I1) {}\n  // CHECK:STDERR:                           ^\n  // CHECK:STDERR:\n  F(U, T);\n}\n\n// F's requirement J2 = I1 is not met as I1 = {} and J2 is unspecified\nfn G3(U:! I where .I1 = {}, T:! J & K where .K1 = .Self and .J1 = U) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `J & K where .(K.K1) = .Self as J and .(J.J1) = U as I` into type implementing `J & K where .(J.J2) = .(K.K1).(J.J1).(I.I1)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(U, T);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_wrong_type.carbon:[[@LINE-31]]:27: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! I, unused T:! J & K where .J2 = (.K1.J1).I1) {}\n  // CHECK:STDERR:                           ^\n  // CHECK:STDERR:\n  F(U, T);\n}\n\n// --- rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n}\n\ninterface J {\n  let J1:! type;\n}\n\ninterface K {\n  let K1:! J & I;\n  let K2:! type;\n  let K3:! type;\n}\n\nfn F(unused U:! I & J, unused T:! K where .K2 = .K1.I1 and .K3 = .K1.J1) {}\n\nfn G(U:! I & J where .I1 = () and .J1 = {}, T:! K where .K1 = U and .K2 = () and .K3 = {}) {\n  F(U, T);\n}\n\n// --- fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n}\n\ninterface J {\n  let J1:! type;\n}\n\ninterface K {\n  let K1:! J & I;\n  let K2:! type;\n  let K3:! type;\n}\n\nfn F(unused U:! I & J, unused T:! K where .K2 = .K1.I1 and .K3 = .K1.J1) {}\n\n// K2 = I1 fails since K2 = {} and I1 = ()\nfn G(U:! I & J where .I1 = () and .J1 = {}, T:! K where .K1 = U and .K2 = {} and .K3 = {}) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `K where .(K.K2) = {} and .(K.K1) = U as I & J and .(K.K3) = {}` into type implementing `K where .(K.K2) = .(K.K1).(I.I1) and .(K.K3) = .(K.K1).(J.J1)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(U, T);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE-7]]:31: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! I & J, unused T:! K where .K2 = .K1.I1 and .K3 = .K1.J1) {}\n  // CHECK:STDERR:                               ^\n  // CHECK:STDERR:\n  F(U, T);\n}\n\n// K2 = I1 fails since I1 = () and K2 is unspecified.\nfn G2(U:! I & J where .I1 = () and .J1 = {}, T:! K where .K1 = U and .K3 = {}) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `K where .(K.K1) = U as I & J and .(K.K3) = {}` into type implementing `K where .(K.K2) = .(K.K1).(I.I1) and .(K.K3) = .(K.K1).(J.J1)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(U, T);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE-19]]:31: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! I & J, unused T:! K where .K2 = .K1.I1 and .K3 = .K1.J1) {}\n  // CHECK:STDERR:                               ^\n  // CHECK:STDERR:\n  F(U, T);\n}\n\n// K2 = I1 fails since K2 = () and I1 is unspecified.\nfn G3(U:! I & J where .J1 = {}, T:! K where .K1 = U and .K2 = () and .K3 = {}) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `K where .(K.K2) = () and .(K.K1) = U as I & J and .(K.K3) = {}` into type implementing `K where .(K.K2) = .(K.K1).(I.I1) and .(K.K3) = .(K.K1).(J.J1)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(U, T);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE-31]]:31: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! I & J, unused T:! K where .K2 = .K1.I1 and .K3 = .K1.J1) {}\n  // CHECK:STDERR:                               ^\n  // CHECK:STDERR:\n  F(U, T);\n}\n\n// K3 = J1 fails since J1 = {} and K3 is unspecified.\nfn G4(U:! I & J where .I1 = () and .J1 = {}, T:! K where .K1 = U and .K2 = ()) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `K where .(K.K2) = () and .(K.K1) = U as I & J` into type implementing `K where .(K.K2) = .(K.K1).(I.I1) and .(K.K3) = .(K.K1).(J.J1)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(U, T);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE-43]]:31: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! I & J, unused T:! K where .K2 = .K1.I1 and .K3 = .K1.J1) {}\n  // CHECK:STDERR:                               ^\n  // CHECK:STDERR:\n  F(U, T);\n}\n\n// K3 = J1 fails since K3 = {} and J1 is unspecified.\nfn G5(U:! I & J where .I1 = (), T:! K where .K1 = U and .K2 = () and .K3 = {}) {\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `K where .(K.K2) = () and .(K.K1) = U as I & J and .(K.K3) = {}` into type implementing `K where .(K.K2) = .(K.K1).(I.I1) and .(K.K3) = .(K.K1).(J.J1)` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(U, T);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_rewrite_requires_subst_in_nested_access_of_other_with_two_witnesses_wrong_type.carbon:[[@LINE-55]]:31: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused U:! I & J, unused T:! K where .K2 = .K1.I1 and .K3 = .K1.J1) {}\n  // CHECK:STDERR:                               ^\n  // CHECK:STDERR:\n  F(U, T);\n}\n\n// --- fail_target_rewrites_dont_apply_to_source.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let I1:! type;\n  let I2:! type;\n  let I3:! type;\n  let I4:! type;\n}\n\nfn F(unused T:! I where .I1 = () and .I2 = ()) {}\n\nfn G(T:! I where .I1 = .I2) {\n  // CHECK:STDERR: fail_target_rewrites_dont_apply_to_source.carbon:[[@LINE+7]]:3: error: cannot convert type `T` that implements `I where .(I.I1) = .(I.I2)` into type implementing `I where .(I.I1) = () and .(I.I2) = ()` [ConversionFailureFacetToFacet]\n  // CHECK:STDERR:   F(T);\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR: fail_target_rewrites_dont_apply_to_source.carbon:[[@LINE-6]]:13: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(unused T:! I where .I1 = () and .I2 = ()) {}\n  // CHECK:STDERR:             ^\n  // CHECK:STDERR:\n  F(T);\n}\n\n// --- nested_facet_type_used_as_root_facet_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! type;\n  let Y:! type;\n}\n\nfn F(T:! I where .X = (I where .Y = {}), unused U:! T.X) {}\n\nfn G(T:! I where .X = (I where .Y = {}), U:! I where .Y = {}) {\n  F(T, U);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/for/actual.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/for/actual.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/for/actual.carbon\n\n// --- lib.carbon\n\nlibrary \"lib\";\n\nclass IntRange(N:! Core.IntLiteral()) {\n  fn Make(start: Core.Int(N), end: Core.Int(N)) -> Self {\n    return {.start = start, .end = end};\n  }\n\n  impl as Core.Iterate where .CursorType = Core.Int(N) and .ElementType = Core.Int(N) {\n    fn NewCursor[self: Self]() -> Core.Int(N) { return self.start; }\n    fn Next[self: Self](cursor: Core.Int(N)*) -> Core.Optional(Core.Int(N)) {\n      var value: Core.Int(N) = *cursor;\n      if (value < self.end) {\n        ++*cursor;\n        return Core.Optional(Core.Int(N)).Some(value);\n      } else {\n        return Core.Optional(Core.Int(N)).None();\n      }\n    }\n  }\n\n  private var start: Core.Int(N);\n  private var end: Core.Int(N);\n}\n\nfn Range(end: i32) -> IntRange(32) {\n  return IntRange(32).Make(0, end);\n}\n\n// --- trivial.carbon\n\nimport library \"lib\";\n\nfn Read(y:! Core.IntLiteral()) {\n  var unused x: IntRange(32) = Range(y);\n}\n\n// CHECK:STDOUT: --- lib.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %IntRange.type: type = generic_class_type @IntRange [concrete]\n// CHECK:STDOUT:   %IntRange.generic: %IntRange.type = struct_value () [concrete]\n// CHECK:STDOUT:   %IntRange.265: type = class_type @IntRange, @IntRange(%N) [symbolic]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Int.fc6021.1: type = class_type @Int, @Int(%N) [symbolic]\n// CHECK:STDOUT:   %pattern_type.764eab.1: type = pattern_type %Int.fc6021.1 [symbolic]\n// CHECK:STDOUT:   %.e1e: Core.Form = init_form %IntRange.265 [symbolic]\n// CHECK:STDOUT:   %pattern_type.b16: type = pattern_type %IntRange.265 [symbolic]\n// CHECK:STDOUT:   %IntRange.Make.type.1df: type = fn_type @IntRange.Make, @IntRange(%N) [symbolic]\n// CHECK:STDOUT:   %IntRange.Make.8a9: %IntRange.Make.type.1df = struct_value () [symbolic]\n// CHECK:STDOUT:   %Iterate.type: type = facet_type <@Iterate> [concrete]\n// CHECK:STDOUT:   %OptionalStorage.type: type = facet_type <@OptionalStorage> [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %facet_type.7e2: type = facet_type <@Destroy & @Copy> [concrete]\n// CHECK:STDOUT:   %Optional.type: type = generic_class_type @Optional [concrete]\n// CHECK:STDOUT:   %Optional.generic: %Optional.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T.542: %OptionalStorage.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Optional.Some.type.eaa: type = fn_type @Optional.Some, @Optional(%T.542) [symbolic]\n// CHECK:STDOUT:   %Optional.Some.6ca: %Optional.Some.type.eaa = struct_value () [symbolic]\n// CHECK:STDOUT:   %Optional.None.type.fc5: type = fn_type @Optional.None, @Optional(%T.542) [symbolic]\n// CHECK:STDOUT:   %Optional.None.fcb: %Optional.None.type.fc5 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.Self.2b2: %Iterate.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %Iterate.lookup_impl_witness.53f: <witness> = lookup_impl_witness %.Self.2b2, @Iterate [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0.3b1: %facet_type.7e2 = impl_witness_access %Iterate.lookup_impl_witness.53f, element0 [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.2b2 [symbolic_self]\n// CHECK:STDOUT:   %Iterate.assoc_type: type = assoc_entity_type @Iterate [concrete]\n// CHECK:STDOUT:   %assoc1.a27: %Iterate.assoc_type = assoc_entity element1, imports.%Core.import_ref.cd6 [concrete]\n// CHECK:STDOUT:   %impl.elem1.49e: type = impl_witness_access %Iterate.lookup_impl_witness.53f, element1 [symbolic_self]\n// CHECK:STDOUT:   %assoc0.4bd: %Iterate.assoc_type = assoc_entity element0, imports.%Core.import_ref.f74 [concrete]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness.93c: <witness> = lookup_impl_witness %Int.fc6021.1, @Destroy [symbolic]\n// CHECK:STDOUT:   %require_complete.9019d7.1: <witness> = require_complete_type %Int.fc6021.1 [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.83cba3.1: Core.Form = init_form %Int.fc6021.1 [symbolic]\n// CHECK:STDOUT:   %.4f8: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.7a8: <witness> = lookup_impl_witness %Int.fc6021.1, @Copy [symbolic]\n// CHECK:STDOUT:   %facet_value: %facet_type.7e2 = facet_value %Int.fc6021.1, (%Destroy.lookup_impl_witness.93c, %Copy.lookup_impl_witness.7a8) [symbolic]\n// CHECK:STDOUT:   %Iterate_where.type: type = facet_type <@Iterate where %impl.elem0.3b1 = %facet_value and %impl.elem1.49e = %Int.fc6021.1> [symbolic]\n// CHECK:STDOUT:   %Iterate.impl_witness: <witness> = impl_witness @IntRange.as.Iterate.impl.%Iterate.impl_witness_table, @IntRange.as.Iterate.impl(%N) [symbolic]\n// CHECK:STDOUT:   %require_complete.234: <witness> = require_complete_type %Iterate_where.type [symbolic]\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor.type: type = fn_type @IntRange.as.Iterate.impl.NewCursor, @IntRange.as.Iterate.impl(%N) [symbolic]\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor: %IntRange.as.Iterate.impl.NewCursor.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %ptr.c9c: type = ptr_type %Int.fc6021.1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.bda: type = pattern_type %ptr.c9c [symbolic]\n// CHECK:STDOUT:   %.63c: require_specific_def_type = require_specific_def @T.binding.as_type.as.OptionalStorage.impl(%facet_value) [symbolic]\n// CHECK:STDOUT:   %OptionalStorage.lookup_impl_witness.b62: <witness> = lookup_impl_witness %Int.fc6021.1, @OptionalStorage [symbolic]\n// CHECK:STDOUT:   %OptionalStorage.facet.01e: %OptionalStorage.type = facet_value %Int.fc6021.1, (%OptionalStorage.lookup_impl_witness.b62) [symbolic]\n// CHECK:STDOUT:   %Optional.e48: type = class_type @Optional, @Optional(%OptionalStorage.facet.01e) [symbolic]\n// CHECK:STDOUT:   %.949: Core.Form = init_form %Optional.e48 [symbolic]\n// CHECK:STDOUT:   %pattern_type.0c2: type = pattern_type %Optional.e48 [symbolic]\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next.type: type = fn_type @IntRange.as.Iterate.impl.Next, @IntRange.as.Iterate.impl(%N) [symbolic]\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next: %IntRange.as.Iterate.impl.Next.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %IntRange.elem.541: type = unbound_element_type %IntRange.265, %Int.fc6021.1 [symbolic]\n// CHECK:STDOUT:   %struct_type.start.end.ff1: type = struct_type {.start: %Int.fc6021.1, .end: %Int.fc6021.1} [symbolic]\n// CHECK:STDOUT:   %complete_type.427: <witness> = complete_type_witness %struct_type.start.end.ff1 [symbolic]\n// CHECK:STDOUT:   %require_complete.8a1: <witness> = require_complete_type %IntRange.265 [symbolic]\n// CHECK:STDOUT:   %Copy.facet.3b9: %Copy.type = facet_value %Int.fc6021.1, (%Copy.lookup_impl_witness.7a8) [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.e13: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.3b9) [symbolic]\n// CHECK:STDOUT:   %.e29: type = fn_type_with_self_type %Copy.WithSelf.Op.type.e13, %Copy.facet.3b9 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.694: %.e29 = impl_witness_access %Copy.lookup_impl_witness.7a8, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bd4: <specific function> = specific_impl_function %impl.elem0.694, @Copy.WithSelf.Op(%Copy.facet.3b9) [symbolic]\n// CHECK:STDOUT:   %require_complete.45c: <witness> = require_complete_type %ptr.c9c [symbolic]\n// CHECK:STDOUT:   %Optional.None.type.d56: type = fn_type @Optional.None, @Optional(%OptionalStorage.facet.01e) [symbolic]\n// CHECK:STDOUT:   %Optional.None.b26: %Optional.None.type.d56 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Optional.Some.type.f74: type = fn_type @Optional.Some, @Optional(%OptionalStorage.facet.01e) [symbolic]\n// CHECK:STDOUT:   %Optional.Some.076: %Optional.Some.type.f74 = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.0bc: <witness> = require_complete_type %Optional.e48 [symbolic]\n// CHECK:STDOUT:   %OrderedWith.type.270: type = generic_interface_type @OrderedWith [concrete]\n// CHECK:STDOUT:   %OrderedWith.generic: %OrderedWith.type.270 = struct_value () [concrete]\n// CHECK:STDOUT:   %Other: type = symbolic_binding Other, 0 [symbolic]\n// CHECK:STDOUT:   %OrderedWith.type.ca8: type = facet_type <@OrderedWith, @OrderedWith(%Other)> [symbolic]\n// CHECK:STDOUT:   %Self.adc: %OrderedWith.type.ca8 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %OrderedWith.assoc_type.2b3: type = assoc_entity_type @OrderedWith, @OrderedWith(%Other) [symbolic]\n// CHECK:STDOUT:   %OrderedWith.WithSelf.Less.type.df2: type = fn_type @OrderedWith.WithSelf.Less, @OrderedWith.WithSelf(%Other, %Self.adc) [symbolic]\n// CHECK:STDOUT:   %OrderedWith.WithSelf.Less.1a4: %OrderedWith.WithSelf.Less.type.df2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %OrderedWith.type.e44: type = facet_type <@OrderedWith, @OrderedWith(%Int.fc6021.1)> [symbolic]\n// CHECK:STDOUT:   %OrderedWith.assoc_type.215: type = assoc_entity_type @OrderedWith, @OrderedWith(%Int.fc6021.1) [symbolic]\n// CHECK:STDOUT:   %assoc0.15c: %OrderedWith.assoc_type.215 = assoc_entity element0, imports.%Core.import_ref.255 [symbolic]\n// CHECK:STDOUT:   %require_complete.dd3: <witness> = require_complete_type %OrderedWith.type.e44 [symbolic]\n// CHECK:STDOUT:   %assoc0.666: %OrderedWith.assoc_type.2b3 = assoc_entity element0, imports.%Core.import_ref.e2b [symbolic]\n// CHECK:STDOUT:   %M: Core.IntLiteral = symbolic_binding M, 1 [symbolic]\n// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.type.5f1: type = fn_type @Int.as.OrderedWith.impl.Less.1, @Int.as.OrderedWith.impl.2e6(%N, %M) [symbolic]\n// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.a9b: %Int.as.OrderedWith.impl.Less.type.5f1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %OrderedWith.impl_witness.ea9: <witness> = impl_witness imports.%OrderedWith.impl_witness_table.b93, @Int.as.OrderedWith.impl.2e6(%N, %N) [symbolic]\n// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.type.3f1: type = fn_type @Int.as.OrderedWith.impl.Less.1, @Int.as.OrderedWith.impl.2e6(%N, %N) [symbolic]\n// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.4cf: %Int.as.OrderedWith.impl.Less.type.3f1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.4b5: require_specific_def_type = require_specific_def @Int.as.OrderedWith.impl.2e6(%N, %N) [symbolic]\n// CHECK:STDOUT:   %OrderedWith.facet: %OrderedWith.type.e44 = facet_value %Int.fc6021.1, (%OrderedWith.impl_witness.ea9) [symbolic]\n// CHECK:STDOUT:   %OrderedWith.WithSelf.Less.type.3a2: type = fn_type @OrderedWith.WithSelf.Less, @OrderedWith.WithSelf(%Int.fc6021.1, %OrderedWith.facet) [symbolic]\n// CHECK:STDOUT:   %.48d: type = fn_type_with_self_type %OrderedWith.WithSelf.Less.type.3a2, %OrderedWith.facet [symbolic]\n// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.specific_fn.4c2: <specific function> = specific_function %Int.as.OrderedWith.impl.Less.4cf, @Int.as.OrderedWith.impl.Less.1(%N, %N) [symbolic]\n// CHECK:STDOUT:   %Inc.type: type = facet_type <@Inc> [concrete]\n// CHECK:STDOUT:   %.53b: require_specific_def_type = require_specific_def @Int.as.Inc.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Inc.lookup_impl_witness: <witness> = lookup_impl_witness %Int.fc6021.1, @Inc [symbolic]\n// CHECK:STDOUT:   %Inc.facet: %Inc.type = facet_value %Int.fc6021.1, (%Inc.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Inc.WithSelf.Op.type.17b: type = fn_type @Inc.WithSelf.Op, @Inc.WithSelf(%Inc.facet) [symbolic]\n// CHECK:STDOUT:   %.9a6: type = fn_type_with_self_type %Inc.WithSelf.Op.type.17b, %Inc.facet [symbolic]\n// CHECK:STDOUT:   %impl.elem0.10c: %.9a6 = impl_witness_access %Inc.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.ed3: <specific function> = specific_impl_function %impl.elem0.10c, @Inc.WithSelf.Op(%Inc.facet) [symbolic]\n// CHECK:STDOUT:   %Optional.Some.specific_fn: <specific function> = specific_function %Optional.Some.076, @Optional.Some(%OptionalStorage.facet.01e) [symbolic]\n// CHECK:STDOUT:   %Destroy.facet.1c0: %Destroy.type = facet_value %Int.fc6021.1, (%Destroy.lookup_impl_witness.93c) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.297: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.1c0) [symbolic]\n// CHECK:STDOUT:   %.e63: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.297, %Destroy.facet.1c0 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.602: %.e63 = impl_witness_access %Destroy.lookup_impl_witness.93c, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.d65: <specific function> = specific_impl_function %impl.elem0.602, @Destroy.WithSelf.Op(%Destroy.facet.1c0) [symbolic]\n// CHECK:STDOUT:   %Optional.None.specific_fn: <specific function> = specific_function %Optional.None.b26, @Optional.None(%OptionalStorage.facet.01e) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %IntRange.a89: type = class_type @IntRange, @IntRange(%int_32) [concrete]\n// CHECK:STDOUT:   %.aec: Core.Form = init_form %IntRange.a89 [concrete]\n// CHECK:STDOUT:   %pattern_type.615: type = pattern_type %IntRange.a89 [concrete]\n// CHECK:STDOUT:   %Range.type: type = fn_type @Range [concrete]\n// CHECK:STDOUT:   %Range: %Range.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %IntRange.Make.type.045: type = fn_type @IntRange.Make, @IntRange(%int_32) [concrete]\n// CHECK:STDOUT:   %IntRange.Make.3e9: %IntRange.Make.type.045 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %.14e: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %IntRange.elem.a58: type = unbound_element_type %IntRange.a89, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.start.end.d0a: type = struct_type {.start: %i32, .end: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.c45: <witness> = complete_type_witness %struct_type.start.end.d0a [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %IntRange.Make.specific_fn: <specific function> = specific_function %IntRange.Make.3e9, @IntRange.Make(%int_32) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.b94: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet.b94) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet.b94 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Iterate = %Core.Iterate\n// CHECK:STDOUT:     .Optional = %Core.Optional\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .OrderedWith = %Core.OrderedWith\n// CHECK:STDOUT:     .Inc = %Core.Inc\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/types/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Iterate: type = import_ref Core//prelude/iterate, Iterate, loaded [concrete = constants.%Iterate.type]\n// CHECK:STDOUT:   %Core.import_ref.39b: %Iterate.assoc_type = import_ref Core//prelude/iterate, loc{{\\d+_\\d+}}, loaded [concrete = constants.%assoc0.4bd]\n// CHECK:STDOUT:   %Core.import_ref.0b0: %Iterate.assoc_type = import_ref Core//prelude/iterate, loc{{\\d+_\\d+}}, loaded [concrete = constants.%assoc1.a27]\n// CHECK:STDOUT:   %Core.import_ref.d20: @Optional.%Optional.None.type (%Optional.None.type.fc5) = import_ref Core//prelude/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.None (constants.%Optional.None.fcb)]\n// CHECK:STDOUT:   %Core.import_ref.aeb: @Optional.%Optional.Some.type (%Optional.Some.type.eaa) = import_ref Core//prelude/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.Some (constants.%Optional.Some.6ca)]\n// CHECK:STDOUT:   %Core.import_ref.cd6: type = import_ref Core//prelude/iterate, loc{{\\d+_\\d+}}, loaded [concrete = %CursorType]\n// CHECK:STDOUT:   %CursorType: type = assoc_const_decl @CursorType [concrete] {}\n// CHECK:STDOUT:   %Core.import_ref.f74: %facet_type.7e2 = import_ref Core//prelude/iterate, loc{{\\d+_\\d+}}, loaded [concrete = %ElementType]\n// CHECK:STDOUT:   %ElementType: %facet_type.7e2 = assoc_const_decl @ElementType [concrete] {}\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Optional: %Optional.type = import_ref Core//prelude/types/optional, Optional, loaded [concrete = constants.%Optional.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.OrderedWith: %OrderedWith.type.270 = import_ref Core//prelude/operators/comparison, OrderedWith, loaded [concrete = constants.%OrderedWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.7e9: @OrderedWith.WithSelf.%OrderedWith.assoc_type (%OrderedWith.assoc_type.2b3) = import_ref Core//prelude/operators/comparison, loc{{\\d+_\\d+}}, loaded [symbolic = @OrderedWith.WithSelf.%assoc0 (constants.%assoc0.666)]\n// CHECK:STDOUT:   %Core.import_ref.255: @OrderedWith.WithSelf.%OrderedWith.WithSelf.Less.type (%OrderedWith.WithSelf.Less.type.df2) = import_ref Core//prelude/operators/comparison, loc{{\\d+_\\d+}}, loaded [symbolic = @OrderedWith.WithSelf.%OrderedWith.WithSelf.Less (constants.%OrderedWith.WithSelf.Less.1a4)]\n// CHECK:STDOUT:   %Core.import_ref.e2b = import_ref Core//prelude/operators/comparison, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.12b: @Int.as.OrderedWith.impl.2e6.%Int.as.OrderedWith.impl.Less.type (%Int.as.OrderedWith.impl.Less.type.5f1) = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.OrderedWith.impl.2e6.%Int.as.OrderedWith.impl.Less (constants.%Int.as.OrderedWith.impl.Less.a9b)]\n// CHECK:STDOUT:   %Core.import_ref.d3d = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.5ef = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.806 = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %OrderedWith.impl_witness_table.b93 = impl_witness_table (%Core.import_ref.12b, %Core.import_ref.d3d, %Core.import_ref.5ef, %Core.import_ref.806), @Int.as.OrderedWith.impl.2e6 [concrete]\n// CHECK:STDOUT:   %Core.Inc: type = import_ref Core//prelude/operators/arithmetic, Inc, loaded [concrete = constants.%Inc.type]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .IntRange = %IntRange.decl\n// CHECK:STDOUT:     .Range = %Range.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %IntRange.decl: %IntRange.type = class_decl @IntRange [concrete = constants.%IntRange.generic] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_36.1: type = splice_block %.loc4_36.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %Core.ref.loc4: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_36.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_36.3: type = converted %IntLiteral.call, %.loc4_36.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_16.2: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_16.1 (constants.%N)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Range.decl: %Range.type = fn_decl @Range [concrete = constants.%Range] {\n// CHECK:STDOUT:     %end.patt: %pattern_type.7ce = value_binding_pattern end [concrete]\n// CHECK:STDOUT:     %end.param_patt: %pattern_type.7ce = value_param_pattern %end.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.615 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.615 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %IntRange.ref.loc26: %IntRange.type = name_ref IntRange, file.%IntRange.decl [concrete = constants.%IntRange.generic]\n// CHECK:STDOUT:     %int_32.loc26: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]\n// CHECK:STDOUT:     %IntRange.loc26: type = class_type @IntRange, @IntRange(constants.%int_32) [concrete = constants.%IntRange.a89]\n// CHECK:STDOUT:     %.loc26_34.2: Core.Form = init_form %IntRange.loc26 [concrete = constants.%.aec]\n// CHECK:STDOUT:     %end.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %end: %i32 = value_binding end, %end.param\n// CHECK:STDOUT:     %return.param: ref %IntRange.a89 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %IntRange.a89 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @IntRange.as.Iterate.impl(@IntRange.%N.loc4_16.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:   %Int.loc9_54.1: type = class_type @Int, @Int(%N) [symbolic = %Int.loc9_54.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc9_54.1, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness.93c)]\n// CHECK:STDOUT:   %.loc9_85.1: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc9_85.1 (constants.%.4f8)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc9_54.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.7a8)]\n// CHECK:STDOUT:   %facet_value.loc9_85.1: %facet_type.7e2 = facet_value %Int.loc9_54.1, (%Destroy.lookup_impl_witness, %Copy.lookup_impl_witness) [symbolic = %facet_value.loc9_85.1 (constants.%facet_value)]\n// CHECK:STDOUT:   %Iterate_where.type: type = facet_type <@Iterate where constants.%impl.elem0.3b1 = %facet_value.loc9_85.1 and constants.%impl.elem1.49e = %Int.loc9_54.1> [symbolic = %Iterate_where.type (constants.%Iterate_where.type)]\n// CHECK:STDOUT:   %Iterate.impl_witness.loc9_87.2: <witness> = impl_witness %Iterate.impl_witness_table, @IntRange.as.Iterate.impl(%N) [symbolic = %Iterate.impl_witness.loc9_87.2 (constants.%Iterate.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Iterate_where.type [symbolic = %require_complete (constants.%require_complete.234)]\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor.type: type = fn_type @IntRange.as.Iterate.impl.NewCursor, @IntRange.as.Iterate.impl(%N) [symbolic = %IntRange.as.Iterate.impl.NewCursor.type (constants.%IntRange.as.Iterate.impl.NewCursor.type)]\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor: @IntRange.as.Iterate.impl.%IntRange.as.Iterate.impl.NewCursor.type (%IntRange.as.Iterate.impl.NewCursor.type) = struct_value () [symbolic = %IntRange.as.Iterate.impl.NewCursor (constants.%IntRange.as.Iterate.impl.NewCursor)]\n// CHECK:STDOUT:   %.loc11: require_specific_def_type = require_specific_def @T.binding.as_type.as.OptionalStorage.impl(%facet_value.loc9_85.1) [symbolic = %.loc11 (constants.%.63c)]\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next.type: type = fn_type @IntRange.as.Iterate.impl.Next, @IntRange.as.Iterate.impl(%N) [symbolic = %IntRange.as.Iterate.impl.Next.type (constants.%IntRange.as.Iterate.impl.Next.type)]\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next: @IntRange.as.Iterate.impl.%IntRange.as.Iterate.impl.Next.type (%IntRange.as.Iterate.impl.Next.type) = struct_value () [symbolic = %IntRange.as.Iterate.impl.Next (constants.%IntRange.as.Iterate.impl.Next)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %Self.ref as %.loc9_24 {\n// CHECK:STDOUT:     %IntRange.as.Iterate.impl.NewCursor.decl: @IntRange.as.Iterate.impl.%IntRange.as.Iterate.impl.NewCursor.type (%IntRange.as.Iterate.impl.NewCursor.type) = fn_decl @IntRange.as.Iterate.impl.NewCursor [symbolic = @IntRange.as.Iterate.impl.%IntRange.as.Iterate.impl.NewCursor (constants.%IntRange.as.Iterate.impl.NewCursor)] {\n// CHECK:STDOUT:       %self.patt: @IntRange.as.Iterate.impl.NewCursor.%pattern_type.loc10_18 (%pattern_type.b16) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @IntRange.as.Iterate.impl.NewCursor.%pattern_type.loc10_18 (%pattern_type.b16) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @IntRange.as.Iterate.impl.NewCursor.%pattern_type.loc10_32 (%pattern_type.764eab.1) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @IntRange.as.Iterate.impl.NewCursor.%pattern_type.loc10_32 (%pattern_type.764eab.1) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Int.ref: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:       %N.ref: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:       %Int.loc10_45.2: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc10_45.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:       %.loc10_45.2: Core.Form = init_form %Int.loc10_45.2 [symbolic = %.loc10_45.1 (constants.%.83cba3.1)]\n// CHECK:STDOUT:       %self.param: @IntRange.as.Iterate.impl.NewCursor.%IntRange (%IntRange.265) = value_param call_param0\n// CHECK:STDOUT:       %.loc10_24.1: type = splice_block %Self.ref [symbolic = %IntRange (constants.%IntRange.265)] {\n// CHECK:STDOUT:         %.loc10_24.2: type = specific_constant constants.%IntRange.265, @IntRange(constants.%N) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc10_24.2 [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @IntRange.as.Iterate.impl.NewCursor.%IntRange (%IntRange.265) = value_binding self, %self.param\n// CHECK:STDOUT:       %return.param: ref @IntRange.as.Iterate.impl.NewCursor.%Int.loc10_45.1 (%Int.fc6021.1) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @IntRange.as.Iterate.impl.NewCursor.%Int.loc10_45.1 (%Int.fc6021.1) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %IntRange.as.Iterate.impl.Next.decl: @IntRange.as.Iterate.impl.%IntRange.as.Iterate.impl.Next.type (%IntRange.as.Iterate.impl.Next.type) = fn_decl @IntRange.as.Iterate.impl.Next [symbolic = @IntRange.as.Iterate.impl.%IntRange.as.Iterate.impl.Next (constants.%IntRange.as.Iterate.impl.Next)] {\n// CHECK:STDOUT:       %self.patt: @IntRange.as.Iterate.impl.Next.%pattern_type.loc11_13 (%pattern_type.b16) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @IntRange.as.Iterate.impl.Next.%pattern_type.loc11_13 (%pattern_type.b16) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %cursor.patt: @IntRange.as.Iterate.impl.Next.%pattern_type.loc11_25 (%pattern_type.bda) = value_binding_pattern cursor [concrete]\n// CHECK:STDOUT:       %cursor.param_patt: @IntRange.as.Iterate.impl.Next.%pattern_type.loc11_25 (%pattern_type.bda) = value_param_pattern %cursor.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @IntRange.as.Iterate.impl.Next.%pattern_type.loc11_47 (%pattern_type.0c2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @IntRange.as.Iterate.impl.Next.%pattern_type.loc11_47 (%pattern_type.0c2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Core.ref.loc11_50: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Optional.ref.loc11: %Optional.type = name_ref Optional, imports.%Core.Optional [concrete = constants.%Optional.generic]\n// CHECK:STDOUT:       %Core.ref.loc11_64: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Int.ref.loc11_68: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:       %N.ref.loc11_73: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:       %Int.loc11_74: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc11_43.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:       %OptionalStorage.facet.loc11_75.2: %OptionalStorage.type = facet_value %Int.loc11_74, (constants.%OptionalStorage.lookup_impl_witness.b62) [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]\n// CHECK:STDOUT:       %.loc11_75.5: %OptionalStorage.type = converted %Int.loc11_74, %OptionalStorage.facet.loc11_75.2 [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]\n// CHECK:STDOUT:       %Optional.loc11_75.2: type = class_type @Optional, @Optional(constants.%OptionalStorage.facet.01e) [symbolic = %Optional.loc11_75.1 (constants.%Optional.e48)]\n// CHECK:STDOUT:       %.loc11_75.6: Core.Form = init_form %Optional.loc11_75.2 [symbolic = %.loc11_75.4 (constants.%.949)]\n// CHECK:STDOUT:       %self.param: @IntRange.as.Iterate.impl.Next.%IntRange (%IntRange.265) = value_param call_param0\n// CHECK:STDOUT:       %.loc11_19.1: type = splice_block %Self.ref [symbolic = %IntRange (constants.%IntRange.265)] {\n// CHECK:STDOUT:         %.loc11_19.2: type = specific_constant constants.%IntRange.265, @IntRange(constants.%N) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc11_19.2 [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @IntRange.as.Iterate.impl.Next.%IntRange (%IntRange.265) = value_binding self, %self.param\n// CHECK:STDOUT:       %cursor.param: @IntRange.as.Iterate.impl.Next.%ptr.loc11_44.1 (%ptr.c9c) = value_param call_param1\n// CHECK:STDOUT:       %.loc11_44: type = splice_block %ptr.loc11_44.2 [symbolic = %ptr.loc11_44.1 (constants.%ptr.c9c)] {\n// CHECK:STDOUT:         %Core.ref.loc11_33: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:         %Int.ref.loc11_37: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:         %N.ref.loc11_42: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:         %Int.loc11_43.2: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc11_43.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:         %ptr.loc11_44.2: type = ptr_type %Int.loc11_43.2 [symbolic = %ptr.loc11_44.1 (constants.%ptr.c9c)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %cursor: @IntRange.as.Iterate.impl.Next.%ptr.loc11_44.1 (%ptr.c9c) = value_binding cursor, %cursor.param\n// CHECK:STDOUT:       %return.param: ref @IntRange.as.Iterate.impl.Next.%Optional.loc11_75.1 (%Optional.e48) = out_param call_param2\n// CHECK:STDOUT:       %return: ref @IntRange.as.Iterate.impl.Next.%Optional.loc11_75.1 (%Optional.e48) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Iterate.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant.loc9_87.1, %impl_witness_assoc_constant.loc9_87.2, %IntRange.as.Iterate.impl.NewCursor.decl, %IntRange.as.Iterate.impl.Next.decl), @IntRange.as.Iterate.impl [concrete]\n// CHECK:STDOUT:     %Iterate.impl_witness.loc9_87.1: <witness> = impl_witness %Iterate.impl_witness_table, @IntRange.as.Iterate.impl(constants.%N) [symbolic = %Iterate.impl_witness.loc9_87.2 (constants.%Iterate.impl_witness)]\n// CHECK:STDOUT:     %impl_witness_assoc_constant.loc9_87.1: %facet_type.7e2 = impl_witness_assoc_constant constants.%facet_value [symbolic = %facet_value.loc9_85.1 (constants.%facet_value)]\n// CHECK:STDOUT:     %impl_witness_assoc_constant.loc9_87.2: type = impl_witness_assoc_constant constants.%Int.fc6021.1 [symbolic = %Int.loc9_54.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .N = <poisoned>\n// CHECK:STDOUT:     .NewCursor = %IntRange.as.Iterate.impl.NewCursor.decl\n// CHECK:STDOUT:     .Next = %IntRange.as.Iterate.impl.Next.decl\n// CHECK:STDOUT:     witness = %Iterate.impl_witness.loc9_87.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @IntRange(%N.loc4_16.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N.loc4_16.1: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_16.1 (constants.%N)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %IntRange.Make.type: type = fn_type @IntRange.Make, @IntRange(%N.loc4_16.1) [symbolic = %IntRange.Make.type (constants.%IntRange.Make.type.1df)]\n// CHECK:STDOUT:   %IntRange.Make: @IntRange.%IntRange.Make.type (%IntRange.Make.type.1df) = struct_value () [symbolic = %IntRange.Make (constants.%IntRange.Make.8a9)]\n// CHECK:STDOUT:   %.loc9: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N.loc4_16.1) [symbolic = %.loc9 (constants.%.4f8)]\n// CHECK:STDOUT:   %Int.loc22_32.2: type = class_type @Int, @Int(%N.loc4_16.1) [symbolic = %Int.loc22_32.2 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Int.loc22_32.2 [symbolic = %require_complete (constants.%require_complete.9019d7.1)]\n// CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N.loc4_16.1) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:   %IntRange.elem: type = unbound_element_type %IntRange, %Int.loc22_32.2 [symbolic = %IntRange.elem (constants.%IntRange.elem.541)]\n// CHECK:STDOUT:   %struct_type.start.end: type = struct_type {.start: @IntRange.%Int.loc22_32.2 (%Int.fc6021.1), .end: @IntRange.%Int.loc22_32.2 (%Int.fc6021.1)} [symbolic = %struct_type.start.end (constants.%struct_type.start.end.ff1)]\n// CHECK:STDOUT:   %complete_type.loc24_1.2: <witness> = complete_type_witness %struct_type.start.end [symbolic = %complete_type.loc24_1.2 (constants.%complete_type.427)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %IntRange.Make.decl: @IntRange.%IntRange.Make.type (%IntRange.Make.type.1df) = fn_decl @IntRange.Make [symbolic = @IntRange.%IntRange.Make (constants.%IntRange.Make.8a9)] {\n// CHECK:STDOUT:       %start.patt: @IntRange.Make.%pattern_type.loc5_11 (%pattern_type.764eab.1) = value_binding_pattern start [concrete]\n// CHECK:STDOUT:       %start.param_patt: @IntRange.Make.%pattern_type.loc5_11 (%pattern_type.764eab.1) = value_param_pattern %start.patt [concrete]\n// CHECK:STDOUT:       %end.patt: @IntRange.Make.%pattern_type.loc5_11 (%pattern_type.764eab.1) = value_binding_pattern end [concrete]\n// CHECK:STDOUT:       %end.param_patt: @IntRange.Make.%pattern_type.loc5_11 (%pattern_type.764eab.1) = value_param_pattern %end.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @IntRange.Make.%pattern_type.loc5_49 (%pattern_type.b16) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @IntRange.Make.%pattern_type.loc5_49 (%pattern_type.b16) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc5_52.2: type = specific_constant constants.%IntRange.265, @IntRange(constants.%N) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:       %Self.ref: type = name_ref Self, %.loc5_52.2 [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:       %.loc5_52.3: Core.Form = init_form %Self.ref [symbolic = %.loc5_52.1 (constants.%.e1e)]\n// CHECK:STDOUT:       %start.param: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_28: type = splice_block %Int.loc5_28.2 [symbolic = %Int.loc5_28.1 (constants.%Int.fc6021.1)] {\n// CHECK:STDOUT:         %Core.ref.loc5_18: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:         %Int.ref.loc5_22: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:         %N.ref.loc5_27: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:         %Int.loc5_28.2: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc5_28.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %start: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = value_binding start, %start.param\n// CHECK:STDOUT:       %end.param: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = value_param call_param1\n// CHECK:STDOUT:       %.loc5_46: type = splice_block %Int.loc5_46 [symbolic = %Int.loc5_28.1 (constants.%Int.fc6021.1)] {\n// CHECK:STDOUT:         %Core.ref.loc5_36: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:         %Int.ref.loc5_40: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:         %N.ref.loc5_45: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:         %Int.loc5_46: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc5_28.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %end: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = value_binding end, %end.param\n// CHECK:STDOUT:       %return.param: ref @IntRange.Make.%IntRange (%IntRange.265) = out_param call_param2\n// CHECK:STDOUT:       %return: ref @IntRange.Make.%IntRange (%IntRange.265) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     impl_decl @IntRange.as.Iterate.impl [concrete] {} {\n// CHECK:STDOUT:       %Self.ref: type = name_ref Self, constants.%IntRange.265 [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:       %Core.ref.loc9_11: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Iterate.ref: type = name_ref Iterate, imports.%Core.Iterate [concrete = constants.%Iterate.type]\n// CHECK:STDOUT:       %.Self: %Iterate.type = symbolic_binding .Self [symbolic_self = constants.%.Self.2b2]\n// CHECK:STDOUT:       %.Self.ref.loc9_30: %Iterate.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self.2b2]\n// CHECK:STDOUT:       %.Self.as_type.loc9_30: type = facet_access_type %.Self.ref.loc9_30 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc9_30: type = converted %.Self.ref.loc9_30, %.Self.as_type.loc9_30 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %CursorType.ref: %Iterate.assoc_type = name_ref CursorType, imports.%Core.import_ref.0b0 [concrete = constants.%assoc1.a27]\n// CHECK:STDOUT:       %impl.elem1: type = impl_witness_access constants.%Iterate.lookup_impl_witness.53f, element1 [symbolic_self = constants.%impl.elem1.49e]\n// CHECK:STDOUT:       %Core.ref.loc9_44: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Int.ref.loc9_48: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:       %N.ref.loc9_53: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:       %Int.loc9_54.2: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc9_54.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:       %.Self.ref.loc9_60: %Iterate.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self.2b2]\n// CHECK:STDOUT:       %.Self.as_type.loc9_60: type = facet_access_type %.Self.ref.loc9_60 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc9_60: type = converted %.Self.ref.loc9_60, %.Self.as_type.loc9_60 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %ElementType.ref: %Iterate.assoc_type = name_ref ElementType, imports.%Core.import_ref.39b [concrete = constants.%assoc0.4bd]\n// CHECK:STDOUT:       %impl.elem0: %facet_type.7e2 = impl_witness_access constants.%Iterate.lookup_impl_witness.53f, element0 [symbolic_self = constants.%impl.elem0.3b1]\n// CHECK:STDOUT:       %Core.ref.loc9_75: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Int.ref.loc9_79: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:       %N.ref.loc9_84: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:       %Int.loc9_85: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc9_54.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:       %facet_value.loc9_85.2: %facet_type.7e2 = facet_value %Int.loc9_85, (constants.%Destroy.lookup_impl_witness.93c, constants.%Copy.lookup_impl_witness.7a8) [symbolic = %facet_value.loc9_85.1 (constants.%facet_value)]\n// CHECK:STDOUT:       %.loc9_85.2: %facet_type.7e2 = converted %Int.loc9_85, %facet_value.loc9_85.2 [symbolic = %facet_value.loc9_85.1 (constants.%facet_value)]\n// CHECK:STDOUT:       %.loc9_24: type = where_expr %.Self [symbolic = %Iterate_where.type (constants.%Iterate_where.type)] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%Iterate.type\n// CHECK:STDOUT:         requirement_rewrite %impl.elem1, %Int.loc9_54.2\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0, %.loc9_85.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Core.ref.loc22: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %Int.ref.loc22: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:     %N.ref.loc22: Core.IntLiteral = name_ref N, %N.loc4_16.2 [symbolic = %N.loc4_16.1 (constants.%N)]\n// CHECK:STDOUT:     %Int.loc22_32.1: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc22_32.2 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:     %.loc22: @IntRange.%IntRange.elem (%IntRange.elem.541) = field_decl start, element0 [concrete]\n// CHECK:STDOUT:     %Core.ref.loc23: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %Int.ref.loc23: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:     %N.ref.loc23: Core.IntLiteral = name_ref N, %N.loc4_16.2 [symbolic = %N.loc4_16.1 (constants.%N)]\n// CHECK:STDOUT:     %Int.loc23: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc22_32.2 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:     %.loc23: @IntRange.%IntRange.elem (%IntRange.elem.541) = field_decl end, element1 [concrete]\n// CHECK:STDOUT:     %complete_type.loc24_1.1: <witness> = complete_type_witness constants.%struct_type.start.end.ff1 [symbolic = %complete_type.loc24_1.2 (constants.%complete_type.427)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc24_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%IntRange.265\n// CHECK:STDOUT:     .N = <poisoned>\n// CHECK:STDOUT:     .Make = %IntRange.Make.decl\n// CHECK:STDOUT:     .start [private] = %.loc22\n// CHECK:STDOUT:     .end [private] = %.loc23\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @IntRange.Make(@IntRange.%N.loc4_16.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:   %Int.loc5_28.1: type = class_type @Int, @Int(%N) [symbolic = %Int.loc5_28.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:   %pattern_type.loc5_11: type = pattern_type %Int.loc5_28.1 [symbolic = %pattern_type.loc5_11 (constants.%pattern_type.764eab.1)]\n// CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:   %.loc5_52.1: Core.Form = init_form %IntRange [symbolic = %.loc5_52.1 (constants.%.e1e)]\n// CHECK:STDOUT:   %pattern_type.loc5_49: type = pattern_type %IntRange [symbolic = %pattern_type.loc5_49 (constants.%pattern_type.b16)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_16: <witness> = require_complete_type %Int.loc5_28.1 [symbolic = %require_complete.loc5_16 (constants.%require_complete.9019d7.1)]\n// CHECK:STDOUT:   %require_complete.loc5_52: <witness> = require_complete_type %IntRange [symbolic = %require_complete.loc5_52 (constants.%require_complete.8a1)]\n// CHECK:STDOUT:   %struct_type.start.end: type = struct_type {.start: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1), .end: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1)} [symbolic = %struct_type.start.end (constants.%struct_type.start.end.ff1)]\n// CHECK:STDOUT:   %.loc6_22.1: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc6_22.1 (constants.%.4f8)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc5_28.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.7a8)]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %Int.loc5_28.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.3b9)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.e13)]\n// CHECK:STDOUT:   %.loc6_22.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc6_22.2 (constants.%.e29)]\n// CHECK:STDOUT:   %impl.elem0.loc6_22.2: @IntRange.Make.%.loc6_22.2 (%.e29) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc6_22.2 (constants.%impl.elem0.694)]\n// CHECK:STDOUT:   %specific_impl_fn.loc6_22.2: <specific function> = specific_impl_function %impl.elem0.loc6_22.2, @Copy.WithSelf.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc6_22.2 (constants.%specific_impl_fn.bd4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%start.param: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1), %end.param: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1)) -> out %return.param: @IntRange.Make.%IntRange (%IntRange.265) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %start.ref: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = name_ref start, %start\n// CHECK:STDOUT:     %end.ref: @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = name_ref end, %end\n// CHECK:STDOUT:     %.loc6_39.1: @IntRange.Make.%struct_type.start.end (%struct_type.start.end.ff1) = struct_literal (%start.ref, %end.ref)\n// CHECK:STDOUT:     %impl.elem0.loc6_22.1: @IntRange.Make.%.loc6_22.2 (%.e29) = impl_witness_access constants.%Copy.lookup_impl_witness.7a8, element0 [symbolic = %impl.elem0.loc6_22.2 (constants.%impl.elem0.694)]\n// CHECK:STDOUT:     %bound_method.loc6_22.1: <bound method> = bound_method %start.ref, %impl.elem0.loc6_22.1\n// CHECK:STDOUT:     %specific_impl_fn.loc6_22.1: <specific function> = specific_impl_function %impl.elem0.loc6_22.1, @Copy.WithSelf.Op(constants.%Copy.facet.3b9) [symbolic = %specific_impl_fn.loc6_22.2 (constants.%specific_impl_fn.bd4)]\n// CHECK:STDOUT:     %bound_method.loc6_22.2: <bound method> = bound_method %start.ref, %specific_impl_fn.loc6_22.1\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call.loc6_22: init @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = call %bound_method.loc6_22.2(%start.ref)\n// CHECK:STDOUT:     %.loc6_39.2: ref @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = class_element_access %return.param, element0\n// CHECK:STDOUT:     %.loc6_39.3: init @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) to %.loc6_39.2 = in_place_init %Copy.WithSelf.Op.call.loc6_22\n// CHECK:STDOUT:     %impl.elem0.loc6_36: @IntRange.Make.%.loc6_22.2 (%.e29) = impl_witness_access constants.%Copy.lookup_impl_witness.7a8, element0 [symbolic = %impl.elem0.loc6_22.2 (constants.%impl.elem0.694)]\n// CHECK:STDOUT:     %bound_method.loc6_36.1: <bound method> = bound_method %end.ref, %impl.elem0.loc6_36\n// CHECK:STDOUT:     %specific_impl_fn.loc6_36: <specific function> = specific_impl_function %impl.elem0.loc6_36, @Copy.WithSelf.Op(constants.%Copy.facet.3b9) [symbolic = %specific_impl_fn.loc6_22.2 (constants.%specific_impl_fn.bd4)]\n// CHECK:STDOUT:     %bound_method.loc6_36.2: <bound method> = bound_method %end.ref, %specific_impl_fn.loc6_36\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call.loc6_36: init @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = call %bound_method.loc6_36.2(%end.ref)\n// CHECK:STDOUT:     %.loc6_39.4: ref @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) = class_element_access %return.param, element1\n// CHECK:STDOUT:     %.loc6_39.5: init @IntRange.Make.%Int.loc5_28.1 (%Int.fc6021.1) to %.loc6_39.4 = in_place_init %Copy.WithSelf.Op.call.loc6_36\n// CHECK:STDOUT:     %.loc6_39.6: init @IntRange.Make.%IntRange (%IntRange.265) to %return.param = class_init (%.loc6_39.3, %.loc6_39.5)\n// CHECK:STDOUT:     %.loc6_40: init @IntRange.Make.%IntRange (%IntRange.265) = converted %.loc6_39.1, %.loc6_39.6\n// CHECK:STDOUT:     return %.loc6_40 to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @IntRange.as.Iterate.impl.NewCursor(@IntRange.%N.loc4_16.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:   %pattern_type.loc10_18: type = pattern_type %IntRange [symbolic = %pattern_type.loc10_18 (constants.%pattern_type.b16)]\n// CHECK:STDOUT:   %Int.loc10_45.1: type = class_type @Int, @Int(%N) [symbolic = %Int.loc10_45.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:   %.loc10_45.1: Core.Form = init_form %Int.loc10_45.1 [symbolic = %.loc10_45.1 (constants.%.83cba3.1)]\n// CHECK:STDOUT:   %pattern_type.loc10_32: type = pattern_type %Int.loc10_45.1 [symbolic = %pattern_type.loc10_32 (constants.%pattern_type.764eab.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc10_22: <witness> = require_complete_type %IntRange [symbolic = %require_complete.loc10_22 (constants.%require_complete.8a1)]\n// CHECK:STDOUT:   %IntRange.elem: type = unbound_element_type %IntRange, %Int.loc10_45.1 [symbolic = %IntRange.elem (constants.%IntRange.elem.541)]\n// CHECK:STDOUT:   %require_complete.loc10_60: <witness> = require_complete_type %Int.loc10_45.1 [symbolic = %require_complete.loc10_60 (constants.%require_complete.9019d7.1)]\n// CHECK:STDOUT:   %.loc10_60.3: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc10_60.3 (constants.%.4f8)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc10_45.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.7a8)]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %Int.loc10_45.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.3b9)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.e13)]\n// CHECK:STDOUT:   %.loc10_60.4: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc10_60.4 (constants.%.e29)]\n// CHECK:STDOUT:   %impl.elem0.loc10_60.2: @IntRange.as.Iterate.impl.NewCursor.%.loc10_60.4 (%.e29) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc10_60.2 (constants.%impl.elem0.694)]\n// CHECK:STDOUT:   %specific_impl_fn.loc10_60.2: <specific function> = specific_impl_function %impl.elem0.loc10_60.2, @Copy.WithSelf.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc10_60.2 (constants.%specific_impl_fn.bd4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @IntRange.as.Iterate.impl.NewCursor.%IntRange (%IntRange.265)) -> out %return.param: @IntRange.as.Iterate.impl.NewCursor.%Int.loc10_45.1 (%Int.fc6021.1) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %self.ref: @IntRange.as.Iterate.impl.NewCursor.%IntRange (%IntRange.265) = name_ref self, %self\n// CHECK:STDOUT:     %start.ref: @IntRange.as.Iterate.impl.NewCursor.%IntRange.elem (%IntRange.elem.541) = name_ref start, @IntRange.%.loc22 [concrete = @IntRange.%.loc22]\n// CHECK:STDOUT:     %.loc10_60.1: ref @IntRange.as.Iterate.impl.NewCursor.%Int.loc10_45.1 (%Int.fc6021.1) = class_element_access %self.ref, element0\n// CHECK:STDOUT:     %.loc10_60.2: @IntRange.as.Iterate.impl.NewCursor.%Int.loc10_45.1 (%Int.fc6021.1) = acquire_value %.loc10_60.1\n// CHECK:STDOUT:     %impl.elem0.loc10_60.1: @IntRange.as.Iterate.impl.NewCursor.%.loc10_60.4 (%.e29) = impl_witness_access constants.%Copy.lookup_impl_witness.7a8, element0 [symbolic = %impl.elem0.loc10_60.2 (constants.%impl.elem0.694)]\n// CHECK:STDOUT:     %bound_method.loc10_60.1: <bound method> = bound_method %.loc10_60.2, %impl.elem0.loc10_60.1\n// CHECK:STDOUT:     %specific_impl_fn.loc10_60.1: <specific function> = specific_impl_function %impl.elem0.loc10_60.1, @Copy.WithSelf.Op(constants.%Copy.facet.3b9) [symbolic = %specific_impl_fn.loc10_60.2 (constants.%specific_impl_fn.bd4)]\n// CHECK:STDOUT:     %bound_method.loc10_60.2: <bound method> = bound_method %.loc10_60.2, %specific_impl_fn.loc10_60.1\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @IntRange.as.Iterate.impl.NewCursor.%Int.loc10_45.1 (%Int.fc6021.1) = call %bound_method.loc10_60.2(%.loc10_60.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @IntRange.as.Iterate.impl.Next(@IntRange.%N.loc4_16.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:   %pattern_type.loc11_13: type = pattern_type %IntRange [symbolic = %pattern_type.loc11_13 (constants.%pattern_type.b16)]\n// CHECK:STDOUT:   %Int.loc11_43.1: type = class_type @Int, @Int(%N) [symbolic = %Int.loc11_43.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:   %ptr.loc11_44.1: type = ptr_type %Int.loc11_43.1 [symbolic = %ptr.loc11_44.1 (constants.%ptr.c9c)]\n// CHECK:STDOUT:   %pattern_type.loc11_25: type = pattern_type %ptr.loc11_44.1 [symbolic = %pattern_type.loc11_25 (constants.%pattern_type.bda)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc11_43.1, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness.93c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc11_43.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.7a8)]\n// CHECK:STDOUT:   %facet_value: %facet_type.7e2 = facet_value %Int.loc11_43.1, (%Destroy.lookup_impl_witness, %Copy.lookup_impl_witness) [symbolic = %facet_value (constants.%facet_value)]\n// CHECK:STDOUT:   %.loc11_75.3: require_specific_def_type = require_specific_def @T.binding.as_type.as.OptionalStorage.impl(%facet_value) [symbolic = %.loc11_75.3 (constants.%.63c)]\n// CHECK:STDOUT:   %OptionalStorage.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc11_43.1, @OptionalStorage [symbolic = %OptionalStorage.lookup_impl_witness (constants.%OptionalStorage.lookup_impl_witness.b62)]\n// CHECK:STDOUT:   %OptionalStorage.facet.loc11_75.1: %OptionalStorage.type = facet_value %Int.loc11_43.1, (%OptionalStorage.lookup_impl_witness) [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]\n// CHECK:STDOUT:   %Optional.loc11_75.1: type = class_type @Optional, @Optional(%OptionalStorage.facet.loc11_75.1) [symbolic = %Optional.loc11_75.1 (constants.%Optional.e48)]\n// CHECK:STDOUT:   %.loc11_75.4: Core.Form = init_form %Optional.loc11_75.1 [symbolic = %.loc11_75.4 (constants.%.949)]\n// CHECK:STDOUT:   %pattern_type.loc11_47: type = pattern_type %Optional.loc11_75.1 [symbolic = %pattern_type.loc11_47 (constants.%pattern_type.0c2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc11_17: <witness> = require_complete_type %IntRange [symbolic = %require_complete.loc11_17 (constants.%require_complete.8a1)]\n// CHECK:STDOUT:   %require_complete.loc11_31: <witness> = require_complete_type %ptr.loc11_44.1 [symbolic = %require_complete.loc11_31 (constants.%require_complete.45c)]\n// CHECK:STDOUT:   %require_complete.loc11_75: <witness> = require_complete_type %Optional.loc11_75.1 [symbolic = %require_complete.loc11_75 (constants.%require_complete.0bc)]\n// CHECK:STDOUT:   %require_complete.loc12: <witness> = require_complete_type %Int.loc11_43.1 [symbolic = %require_complete.loc12 (constants.%require_complete.9019d7.1)]\n// CHECK:STDOUT:   %pattern_type.loc12: type = pattern_type %Int.loc11_43.1 [symbolic = %pattern_type.loc12 (constants.%pattern_type.764eab.1)]\n// CHECK:STDOUT:   %.loc12_32.3: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.loc12_32.3 (constants.%.4f8)]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %Int.loc11_43.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet.3b9)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.e13)]\n// CHECK:STDOUT:   %.loc12_32.4: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc12_32.4 (constants.%.e29)]\n// CHECK:STDOUT:   %impl.elem0.loc12_32.2: @IntRange.as.Iterate.impl.Next.%.loc12_32.4 (%.e29) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc12_32.2 (constants.%impl.elem0.694)]\n// CHECK:STDOUT:   %specific_impl_fn.loc12_32.2: <specific function> = specific_impl_function %impl.elem0.loc12_32.2, @Copy.WithSelf.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc12_32.2 (constants.%specific_impl_fn.bd4)]\n// CHECK:STDOUT:   %IntRange.elem: type = unbound_element_type %IntRange, %Int.loc11_43.1 [symbolic = %IntRange.elem (constants.%IntRange.elem.541)]\n// CHECK:STDOUT:   %OrderedWith.type.loc13_17.2: type = facet_type <@OrderedWith, @OrderedWith(%Int.loc11_43.1)> [symbolic = %OrderedWith.type.loc13_17.2 (constants.%OrderedWith.type.e44)]\n// CHECK:STDOUT:   %require_complete.loc13: <witness> = require_complete_type %OrderedWith.type.loc13_17.2 [symbolic = %require_complete.loc13 (constants.%require_complete.dd3)]\n// CHECK:STDOUT:   %OrderedWith.assoc_type: type = assoc_entity_type @OrderedWith, @OrderedWith(%Int.loc11_43.1) [symbolic = %OrderedWith.assoc_type (constants.%OrderedWith.assoc_type.215)]\n// CHECK:STDOUT:   %assoc0: @IntRange.as.Iterate.impl.Next.%OrderedWith.assoc_type (%OrderedWith.assoc_type.215) = assoc_entity element0, imports.%Core.import_ref.255 [symbolic = %assoc0 (constants.%assoc0.15c)]\n// CHECK:STDOUT:   %.loc13_17.2: require_specific_def_type = require_specific_def @Int.as.OrderedWith.impl.2e6(%N, %N) [symbolic = %.loc13_17.2 (constants.%.4b5)]\n// CHECK:STDOUT:   %OrderedWith.impl_witness: <witness> = impl_witness imports.%OrderedWith.impl_witness_table.b93, @Int.as.OrderedWith.impl.2e6(%N, %N) [symbolic = %OrderedWith.impl_witness (constants.%OrderedWith.impl_witness.ea9)]\n// CHECK:STDOUT:   %OrderedWith.facet: @IntRange.as.Iterate.impl.Next.%OrderedWith.type.loc13_17.2 (%OrderedWith.type.e44) = facet_value %Int.loc11_43.1, (%OrderedWith.impl_witness) [symbolic = %OrderedWith.facet (constants.%OrderedWith.facet)]\n// CHECK:STDOUT:   %OrderedWith.WithSelf.Less.type: type = fn_type @OrderedWith.WithSelf.Less, @OrderedWith.WithSelf(%Int.loc11_43.1, %OrderedWith.facet) [symbolic = %OrderedWith.WithSelf.Less.type (constants.%OrderedWith.WithSelf.Less.type.3a2)]\n// CHECK:STDOUT:   %.loc13_17.3: type = fn_type_with_self_type %OrderedWith.WithSelf.Less.type, %OrderedWith.facet [symbolic = %.loc13_17.3 (constants.%.48d)]\n// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.type: type = fn_type @Int.as.OrderedWith.impl.Less.1, @Int.as.OrderedWith.impl.2e6(%N, %N) [symbolic = %Int.as.OrderedWith.impl.Less.type (constants.%Int.as.OrderedWith.impl.Less.type.3f1)]\n// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less: @IntRange.as.Iterate.impl.Next.%Int.as.OrderedWith.impl.Less.type (%Int.as.OrderedWith.impl.Less.type.3f1) = struct_value () [symbolic = %Int.as.OrderedWith.impl.Less (constants.%Int.as.OrderedWith.impl.Less.4cf)]\n// CHECK:STDOUT:   %Int.as.OrderedWith.impl.Less.specific_fn: <specific function> = specific_function %Int.as.OrderedWith.impl.Less, @Int.as.OrderedWith.impl.Less.1(%N, %N) [symbolic = %Int.as.OrderedWith.impl.Less.specific_fn (constants.%Int.as.OrderedWith.impl.Less.specific_fn.4c2)]\n// CHECK:STDOUT:   %.loc14_9.1: require_specific_def_type = require_specific_def @Int.as.Inc.impl(%N) [symbolic = %.loc14_9.1 (constants.%.53b)]\n// CHECK:STDOUT:   %Inc.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc11_43.1, @Inc [symbolic = %Inc.lookup_impl_witness (constants.%Inc.lookup_impl_witness)]\n// CHECK:STDOUT:   %Inc.facet: %Inc.type = facet_value %Int.loc11_43.1, (%Inc.lookup_impl_witness) [symbolic = %Inc.facet (constants.%Inc.facet)]\n// CHECK:STDOUT:   %Inc.WithSelf.Op.type: type = fn_type @Inc.WithSelf.Op, @Inc.WithSelf(%Inc.facet) [symbolic = %Inc.WithSelf.Op.type (constants.%Inc.WithSelf.Op.type.17b)]\n// CHECK:STDOUT:   %.loc14_9.2: type = fn_type_with_self_type %Inc.WithSelf.Op.type, %Inc.facet [symbolic = %.loc14_9.2 (constants.%.9a6)]\n// CHECK:STDOUT:   %impl.elem0.loc14_9.2: @IntRange.as.Iterate.impl.Next.%.loc14_9.2 (%.9a6) = impl_witness_access %Inc.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc14_9.2 (constants.%impl.elem0.10c)]\n// CHECK:STDOUT:   %specific_impl_fn.loc14_9.2: <specific function> = specific_impl_function %impl.elem0.loc14_9.2, @Inc.WithSelf.Op(%Inc.facet) [symbolic = %specific_impl_fn.loc14_9.2 (constants.%specific_impl_fn.ed3)]\n// CHECK:STDOUT:   %Optional.Some.type: type = fn_type @Optional.Some, @Optional(%OptionalStorage.facet.loc11_75.1) [symbolic = %Optional.Some.type (constants.%Optional.Some.type.f74)]\n// CHECK:STDOUT:   %Optional.Some: @IntRange.as.Iterate.impl.Next.%Optional.Some.type (%Optional.Some.type.f74) = struct_value () [symbolic = %Optional.Some (constants.%Optional.Some.076)]\n// CHECK:STDOUT:   %Optional.Some.specific_fn.loc15_42.2: <specific function> = specific_function %Optional.Some, @Optional.Some(%OptionalStorage.facet.loc11_75.1) [symbolic = %Optional.Some.specific_fn.loc15_42.2 (constants.%Optional.Some.specific_fn)]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Int.loc11_43.1, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.1c0)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [symbolic = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.297)]\n// CHECK:STDOUT:   %.loc12_7: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %Destroy.facet [symbolic = %.loc12_7 (constants.%.e63)]\n// CHECK:STDOUT:   %impl.elem0.loc12_7.3: @IntRange.as.Iterate.impl.Next.%.loc12_7 (%.e63) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc12_7.3 (constants.%impl.elem0.602)]\n// CHECK:STDOUT:   %specific_impl_fn.loc12_7.3: <specific function> = specific_impl_function %impl.elem0.loc12_7.3, @Destroy.WithSelf.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc12_7.3 (constants.%specific_impl_fn.d65)]\n// CHECK:STDOUT:   %Optional.None.type: type = fn_type @Optional.None, @Optional(%OptionalStorage.facet.loc11_75.1) [symbolic = %Optional.None.type (constants.%Optional.None.type.d56)]\n// CHECK:STDOUT:   %Optional.None: @IntRange.as.Iterate.impl.Next.%Optional.None.type (%Optional.None.type.d56) = struct_value () [symbolic = %Optional.None (constants.%Optional.None.b26)]\n// CHECK:STDOUT:   %Optional.None.specific_fn.loc17_42.2: <specific function> = specific_function %Optional.None, @Optional.None(%OptionalStorage.facet.loc11_75.1) [symbolic = %Optional.None.specific_fn.loc17_42.2 (constants.%Optional.None.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @IntRange.as.Iterate.impl.Next.%IntRange (%IntRange.265), %cursor.param: @IntRange.as.Iterate.impl.Next.%ptr.loc11_44.1 (%ptr.c9c)) -> out %return.param: @IntRange.as.Iterate.impl.Next.%Optional.loc11_75.1 (%Optional.e48) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %value.patt: @IntRange.as.Iterate.impl.Next.%pattern_type.loc12 (%pattern_type.764eab.1) = ref_binding_pattern value [concrete]\n// CHECK:STDOUT:       %value.var_patt: @IntRange.as.Iterate.impl.Next.%pattern_type.loc12 (%pattern_type.764eab.1) = var_pattern %value.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %value.var: ref @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = var %value.var_patt\n// CHECK:STDOUT:     %cursor.ref.loc12: @IntRange.as.Iterate.impl.Next.%ptr.loc11_44.1 (%ptr.c9c) = name_ref cursor, %cursor\n// CHECK:STDOUT:     %.loc12_32.1: ref @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = deref %cursor.ref.loc12\n// CHECK:STDOUT:     %.loc12_32.2: @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = acquire_value %.loc12_32.1\n// CHECK:STDOUT:     %impl.elem0.loc12_32.1: @IntRange.as.Iterate.impl.Next.%.loc12_32.4 (%.e29) = impl_witness_access constants.%Copy.lookup_impl_witness.7a8, element0 [symbolic = %impl.elem0.loc12_32.2 (constants.%impl.elem0.694)]\n// CHECK:STDOUT:     %bound_method.loc12_32.1: <bound method> = bound_method %.loc12_32.2, %impl.elem0.loc12_32.1\n// CHECK:STDOUT:     %specific_impl_fn.loc12_32.1: <specific function> = specific_impl_function %impl.elem0.loc12_32.1, @Copy.WithSelf.Op(constants.%Copy.facet.3b9) [symbolic = %specific_impl_fn.loc12_32.2 (constants.%specific_impl_fn.bd4)]\n// CHECK:STDOUT:     %bound_method.loc12_32.2: <bound method> = bound_method %.loc12_32.2, %specific_impl_fn.loc12_32.1\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = call %bound_method.loc12_32.2(%.loc12_32.2)\n// CHECK:STDOUT:     assign %value.var, %Copy.WithSelf.Op.call\n// CHECK:STDOUT:     %.loc12_28: type = splice_block %Int.loc12 [symbolic = %Int.loc11_43.1 (constants.%Int.fc6021.1)] {\n// CHECK:STDOUT:       %Core.ref.loc12: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Int.ref.loc12: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:       %N.ref.loc12: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:       %Int.loc12: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc11_43.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %value: ref @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = ref_binding value, %value.var\n// CHECK:STDOUT:     %value.ref.loc13: ref @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = name_ref value, %value\n// CHECK:STDOUT:     %self.ref: @IntRange.as.Iterate.impl.Next.%IntRange (%IntRange.265) = name_ref self, %self\n// CHECK:STDOUT:     %end.ref: @IntRange.as.Iterate.impl.Next.%IntRange.elem (%IntRange.elem.541) = name_ref end, @IntRange.%.loc23 [concrete = @IntRange.%.loc23]\n// CHECK:STDOUT:     %.loc13_23.1: ref @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = class_element_access %self.ref, element1\n// CHECK:STDOUT:     %.loc13_23.2: @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = acquire_value %.loc13_23.1\n// CHECK:STDOUT:     %OrderedWith.type.loc13_17.1: type = facet_type <@OrderedWith, @OrderedWith(constants.%Int.fc6021.1)> [symbolic = %OrderedWith.type.loc13_17.2 (constants.%OrderedWith.type.e44)]\n// CHECK:STDOUT:     %.loc13_17.1: @IntRange.as.Iterate.impl.Next.%OrderedWith.assoc_type (%OrderedWith.assoc_type.215) = specific_constant imports.%Core.import_ref.7e9, @OrderedWith.WithSelf(constants.%Int.fc6021.1, constants.%Self.adc) [symbolic = %assoc0 (constants.%assoc0.15c)]\n// CHECK:STDOUT:     %Less.ref: @IntRange.as.Iterate.impl.Next.%OrderedWith.assoc_type (%OrderedWith.assoc_type.215) = name_ref Less, %.loc13_17.1 [symbolic = %assoc0 (constants.%assoc0.15c)]\n// CHECK:STDOUT:     %impl.elem0.loc13: @IntRange.as.Iterate.impl.Next.%.loc13_17.3 (%.48d) = impl_witness_access constants.%OrderedWith.impl_witness.ea9, element0 [symbolic = %Int.as.OrderedWith.impl.Less (constants.%Int.as.OrderedWith.impl.Less.4cf)]\n// CHECK:STDOUT:     %bound_method.loc13_17.1: <bound method> = bound_method %value.ref.loc13, %impl.elem0.loc13\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0.loc13, @Int.as.OrderedWith.impl.Less.1(constants.%N, constants.%N) [symbolic = %Int.as.OrderedWith.impl.Less.specific_fn (constants.%Int.as.OrderedWith.impl.Less.specific_fn.4c2)]\n// CHECK:STDOUT:     %bound_method.loc13_17.2: <bound method> = bound_method %value.ref.loc13, %specific_fn\n// CHECK:STDOUT:     %.loc13_11: @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = acquire_value %value.ref.loc13\n// CHECK:STDOUT:     %Int.as.OrderedWith.impl.Less.call: init bool = call %bound_method.loc13_17.2(%.loc13_11, %.loc13_23.2)\n// CHECK:STDOUT:     %.loc13_27.1: bool = value_of_initializer %Int.as.OrderedWith.impl.Less.call\n// CHECK:STDOUT:     %.loc13_27.2: bool = converted %Int.as.OrderedWith.impl.Less.call, %.loc13_27.1\n// CHECK:STDOUT:     if %.loc13_27.2 br !if.then else br !if.else\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !if.then:\n// CHECK:STDOUT:     %cursor.ref.loc14: @IntRange.as.Iterate.impl.Next.%ptr.loc11_44.1 (%ptr.c9c) = name_ref cursor, %cursor\n// CHECK:STDOUT:     %.loc14_11: ref @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = deref %cursor.ref.loc14\n// CHECK:STDOUT:     %impl.elem0.loc14_9.1: @IntRange.as.Iterate.impl.Next.%.loc14_9.2 (%.9a6) = impl_witness_access constants.%Inc.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc14_9.2 (constants.%impl.elem0.10c)]\n// CHECK:STDOUT:     %bound_method.loc14_9.1: <bound method> = bound_method %.loc14_11, %impl.elem0.loc14_9.1\n// CHECK:STDOUT:     %specific_impl_fn.loc14_9.1: <specific function> = specific_impl_function %impl.elem0.loc14_9.1, @Inc.WithSelf.Op(constants.%Inc.facet) [symbolic = %specific_impl_fn.loc14_9.2 (constants.%specific_impl_fn.ed3)]\n// CHECK:STDOUT:     %bound_method.loc14_9.2: <bound method> = bound_method %.loc14_11, %specific_impl_fn.loc14_9.1\n// CHECK:STDOUT:     %Inc.WithSelf.Op.call: init %empty_tuple.type = call %bound_method.loc14_9.2(%.loc14_11)\n// CHECK:STDOUT:     %Core.ref.loc15_16: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %Optional.ref.loc15: %Optional.type = name_ref Optional, imports.%Core.Optional [concrete = constants.%Optional.generic]\n// CHECK:STDOUT:     %Core.ref.loc15_30: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %Int.ref.loc15: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:     %N.ref.loc15: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:     %Int.loc15: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc11_43.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:     %OptionalStorage.facet.loc15_41: %OptionalStorage.type = facet_value %Int.loc15, (constants.%OptionalStorage.lookup_impl_witness.b62) [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]\n// CHECK:STDOUT:     %.loc15_41: %OptionalStorage.type = converted %Int.loc15, %OptionalStorage.facet.loc15_41 [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]\n// CHECK:STDOUT:     %Optional.loc15: type = class_type @Optional, @Optional(constants.%OptionalStorage.facet.01e) [symbolic = %Optional.loc11_75.1 (constants.%Optional.e48)]\n// CHECK:STDOUT:     %.loc15_42: @IntRange.as.Iterate.impl.Next.%Optional.Some.type (%Optional.Some.type.f74) = specific_constant imports.%Core.import_ref.aeb, @Optional(constants.%OptionalStorage.facet.01e) [symbolic = %Optional.Some (constants.%Optional.Some.076)]\n// CHECK:STDOUT:     %Some.ref: @IntRange.as.Iterate.impl.Next.%Optional.Some.type (%Optional.Some.type.f74) = name_ref Some, %.loc15_42 [symbolic = %Optional.Some (constants.%Optional.Some.076)]\n// CHECK:STDOUT:     %value.ref.loc15: ref @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = name_ref value, %value\n// CHECK:STDOUT:     %OptionalStorage.facet.loc15_53: %OptionalStorage.type = facet_value constants.%Int.fc6021.1, (constants.%OptionalStorage.lookup_impl_witness.b62) [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]\n// CHECK:STDOUT:     %.loc15_53: %OptionalStorage.type = converted constants.%Int.fc6021.1, %OptionalStorage.facet.loc15_53 [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]\n// CHECK:STDOUT:     %Optional.Some.specific_fn.loc15_42.1: <specific function> = specific_function %Some.ref, @Optional.Some(constants.%OptionalStorage.facet.01e) [symbolic = %Optional.Some.specific_fn.loc15_42.2 (constants.%Optional.Some.specific_fn)]\n// CHECK:STDOUT:     %.loc11_75.1: ref @IntRange.as.Iterate.impl.Next.%Optional.loc11_75.1 (%Optional.e48) = splice_block %return.param {}\n// CHECK:STDOUT:     %.loc15_48: @IntRange.as.Iterate.impl.Next.%Int.loc11_43.1 (%Int.fc6021.1) = acquire_value %value.ref.loc15\n// CHECK:STDOUT:     %Optional.Some.call: init @IntRange.as.Iterate.impl.Next.%Optional.loc11_75.1 (%Optional.e48) to %.loc11_75.1 = call %Optional.Some.specific_fn.loc15_42.1(%.loc15_48)\n// CHECK:STDOUT:     %impl.elem0.loc12_7.1: @IntRange.as.Iterate.impl.Next.%.loc12_7 (%.e63) = impl_witness_access constants.%Destroy.lookup_impl_witness.93c, element0 [symbolic = %impl.elem0.loc12_7.3 (constants.%impl.elem0.602)]\n// CHECK:STDOUT:     %bound_method.loc12_7.1: <bound method> = bound_method %value.var, %impl.elem0.loc12_7.1\n// CHECK:STDOUT:     %specific_impl_fn.loc12_7.1: <specific function> = specific_impl_function %impl.elem0.loc12_7.1, @Destroy.WithSelf.Op(constants.%Destroy.facet.1c0) [symbolic = %specific_impl_fn.loc12_7.3 (constants.%specific_impl_fn.d65)]\n// CHECK:STDOUT:     %bound_method.loc12_7.2: <bound method> = bound_method %value.var, %specific_impl_fn.loc12_7.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call.loc12_7.1: init %empty_tuple.type = call %bound_method.loc12_7.2(%value.var)\n// CHECK:STDOUT:     return %Optional.Some.call to %return.param\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !if.else:\n// CHECK:STDOUT:     %Core.ref.loc17_16: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %Optional.ref.loc17: %Optional.type = name_ref Optional, imports.%Core.Optional [concrete = constants.%Optional.generic]\n// CHECK:STDOUT:     %Core.ref.loc17_30: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %Int.ref.loc17: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:     %N.ref.loc17: Core.IntLiteral = name_ref N, @IntRange.%N.loc4_16.2 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:     %Int.loc17: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc11_43.1 (constants.%Int.fc6021.1)]\n// CHECK:STDOUT:     %OptionalStorage.facet.loc17: %OptionalStorage.type = facet_value %Int.loc17, (constants.%OptionalStorage.lookup_impl_witness.b62) [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]\n// CHECK:STDOUT:     %.loc17_41: %OptionalStorage.type = converted %Int.loc17, %OptionalStorage.facet.loc17 [symbolic = %OptionalStorage.facet.loc11_75.1 (constants.%OptionalStorage.facet.01e)]\n// CHECK:STDOUT:     %Optional.loc17: type = class_type @Optional, @Optional(constants.%OptionalStorage.facet.01e) [symbolic = %Optional.loc11_75.1 (constants.%Optional.e48)]\n// CHECK:STDOUT:     %.loc17_42: @IntRange.as.Iterate.impl.Next.%Optional.None.type (%Optional.None.type.d56) = specific_constant imports.%Core.import_ref.d20, @Optional(constants.%OptionalStorage.facet.01e) [symbolic = %Optional.None (constants.%Optional.None.b26)]\n// CHECK:STDOUT:     %None.ref: @IntRange.as.Iterate.impl.Next.%Optional.None.type (%Optional.None.type.d56) = name_ref None, %.loc17_42 [symbolic = %Optional.None (constants.%Optional.None.b26)]\n// CHECK:STDOUT:     %Optional.None.specific_fn.loc17_42.1: <specific function> = specific_function %None.ref, @Optional.None(constants.%OptionalStorage.facet.01e) [symbolic = %Optional.None.specific_fn.loc17_42.2 (constants.%Optional.None.specific_fn)]\n// CHECK:STDOUT:     %.loc11_75.2: ref @IntRange.as.Iterate.impl.Next.%Optional.loc11_75.1 (%Optional.e48) = splice_block %return.param {}\n// CHECK:STDOUT:     %Optional.None.call: init @IntRange.as.Iterate.impl.Next.%Optional.loc11_75.1 (%Optional.e48) to %.loc11_75.2 = call %Optional.None.specific_fn.loc17_42.1()\n// CHECK:STDOUT:     %impl.elem0.loc12_7.2: @IntRange.as.Iterate.impl.Next.%.loc12_7 (%.e63) = impl_witness_access constants.%Destroy.lookup_impl_witness.93c, element0 [symbolic = %impl.elem0.loc12_7.3 (constants.%impl.elem0.602)]\n// CHECK:STDOUT:     %bound_method.loc12_7.3: <bound method> = bound_method %value.var, %impl.elem0.loc12_7.2\n// CHECK:STDOUT:     %specific_impl_fn.loc12_7.2: <specific function> = specific_impl_function %impl.elem0.loc12_7.2, @Destroy.WithSelf.Op(constants.%Destroy.facet.1c0) [symbolic = %specific_impl_fn.loc12_7.3 (constants.%specific_impl_fn.d65)]\n// CHECK:STDOUT:     %bound_method.loc12_7.4: <bound method> = bound_method %value.var, %specific_impl_fn.loc12_7.2\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call.loc12_7.2: init %empty_tuple.type = call %bound_method.loc12_7.4(%value.var)\n// CHECK:STDOUT:     return %Optional.None.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Range(%end.param: %i32) -> out %return.param: %IntRange.a89 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %IntRange.ref.loc27: %IntRange.type = name_ref IntRange, file.%IntRange.decl [concrete = constants.%IntRange.generic]\n// CHECK:STDOUT:   %int_32.loc27: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]\n// CHECK:STDOUT:   %IntRange.loc27: type = class_type @IntRange, @IntRange(constants.%int_32) [concrete = constants.%IntRange.a89]\n// CHECK:STDOUT:   %.loc27_22: %IntRange.Make.type.045 = specific_constant @IntRange.%IntRange.Make.decl, @IntRange(constants.%int_32) [concrete = constants.%IntRange.Make.3e9]\n// CHECK:STDOUT:   %Make.ref: %IntRange.Make.type.045 = name_ref Make, %.loc27_22 [concrete = constants.%IntRange.Make.3e9]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %end.ref: %i32 = name_ref end, %end\n// CHECK:STDOUT:   %IntRange.Make.specific_fn: <specific function> = specific_function %Make.ref, @IntRange.Make(constants.%int_32) [concrete = constants.%IntRange.Make.specific_fn]\n// CHECK:STDOUT:   %.loc26_34.1: ref %IntRange.a89 = splice_block %return.param {}\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc27_28.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc27_28.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc27_28.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc27_28.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc27_28.2: %i32 = converted %int_0, %.loc27_28.1 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %IntRange.Make.call: init %IntRange.a89 to %.loc26_34.1 = call %IntRange.Make.specific_fn(%.loc27_28.2, %end.ref)\n// CHECK:STDOUT:   return %IntRange.Make.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange(constants.%N) {\n// CHECK:STDOUT:   %N.loc4_16.1 => constants.%N\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %IntRange.Make.type => constants.%IntRange.Make.type.1df\n// CHECK:STDOUT:   %IntRange.Make => constants.%IntRange.Make.8a9\n// CHECK:STDOUT:   %.loc9 => constants.%.4f8\n// CHECK:STDOUT:   %Int.loc22_32.2 => constants.%Int.fc6021.1\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.9019d7.1\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.265\n// CHECK:STDOUT:   %IntRange.elem => constants.%IntRange.elem.541\n// CHECK:STDOUT:   %struct_type.start.end => constants.%struct_type.start.end.ff1\n// CHECK:STDOUT:   %complete_type.loc24_1.2 => constants.%complete_type.427\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange.Make(constants.%N) {\n// CHECK:STDOUT:   %N => constants.%N\n// CHECK:STDOUT:   %Int.loc5_28.1 => constants.%Int.fc6021.1\n// CHECK:STDOUT:   %pattern_type.loc5_11 => constants.%pattern_type.764eab.1\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.265\n// CHECK:STDOUT:   %.loc5_52.1 => constants.%.e1e\n// CHECK:STDOUT:   %pattern_type.loc5_49 => constants.%pattern_type.b16\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange.as.Iterate.impl(constants.%N) {\n// CHECK:STDOUT:   %N => constants.%N\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.265\n// CHECK:STDOUT:   %Int.loc9_54.1 => constants.%Int.fc6021.1\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.lookup_impl_witness.93c\n// CHECK:STDOUT:   %.loc9_85.1 => constants.%.4f8\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.lookup_impl_witness.7a8\n// CHECK:STDOUT:   %facet_value.loc9_85.1 => constants.%facet_value\n// CHECK:STDOUT:   %Iterate_where.type => constants.%Iterate_where.type\n// CHECK:STDOUT:   %Iterate.impl_witness.loc9_87.2 => constants.%Iterate.impl_witness\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.234\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor.type => constants.%IntRange.as.Iterate.impl.NewCursor.type\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.NewCursor => constants.%IntRange.as.Iterate.impl.NewCursor\n// CHECK:STDOUT:   %.loc11 => constants.%.63c\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next.type => constants.%IntRange.as.Iterate.impl.Next.type\n// CHECK:STDOUT:   %IntRange.as.Iterate.impl.Next => constants.%IntRange.as.Iterate.impl.Next\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange.as.Iterate.impl.NewCursor(constants.%N) {\n// CHECK:STDOUT:   %N => constants.%N\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.265\n// CHECK:STDOUT:   %pattern_type.loc10_18 => constants.%pattern_type.b16\n// CHECK:STDOUT:   %Int.loc10_45.1 => constants.%Int.fc6021.1\n// CHECK:STDOUT:   %.loc10_45.1 => constants.%.83cba3.1\n// CHECK:STDOUT:   %pattern_type.loc10_32 => constants.%pattern_type.764eab.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange.as.Iterate.impl.Next(constants.%N) {\n// CHECK:STDOUT:   %N => constants.%N\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.265\n// CHECK:STDOUT:   %pattern_type.loc11_13 => constants.%pattern_type.b16\n// CHECK:STDOUT:   %Int.loc11_43.1 => constants.%Int.fc6021.1\n// CHECK:STDOUT:   %ptr.loc11_44.1 => constants.%ptr.c9c\n// CHECK:STDOUT:   %pattern_type.loc11_25 => constants.%pattern_type.bda\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%Destroy.lookup_impl_witness.93c\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.lookup_impl_witness.7a8\n// CHECK:STDOUT:   %facet_value => constants.%facet_value\n// CHECK:STDOUT:   %.loc11_75.3 => constants.%.63c\n// CHECK:STDOUT:   %OptionalStorage.lookup_impl_witness => constants.%OptionalStorage.lookup_impl_witness.b62\n// CHECK:STDOUT:   %OptionalStorage.facet.loc11_75.1 => constants.%OptionalStorage.facet.01e\n// CHECK:STDOUT:   %Optional.loc11_75.1 => constants.%Optional.e48\n// CHECK:STDOUT:   %.loc11_75.4 => constants.%.949\n// CHECK:STDOUT:   %pattern_type.loc11_47 => constants.%pattern_type.0c2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange(constants.%int_32) {\n// CHECK:STDOUT:   %N.loc4_16.1 => constants.%int_32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %IntRange.Make.type => constants.%IntRange.Make.type.045\n// CHECK:STDOUT:   %IntRange.Make => constants.%IntRange.Make.3e9\n// CHECK:STDOUT:   %.loc9 => constants.%.14e\n// CHECK:STDOUT:   %Int.loc22_32.2 => constants.%i32\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.a89\n// CHECK:STDOUT:   %IntRange.elem => constants.%IntRange.elem.a58\n// CHECK:STDOUT:   %struct_type.start.end => constants.%struct_type.start.end.d0a\n// CHECK:STDOUT:   %complete_type.loc24_1.2 => constants.%complete_type.c45\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange.Make(constants.%int_32) {\n// CHECK:STDOUT:   %N => constants.%int_32\n// CHECK:STDOUT:   %Int.loc5_28.1 => constants.%i32\n// CHECK:STDOUT:   %pattern_type.loc5_11 => constants.%pattern_type.7ce\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.a89\n// CHECK:STDOUT:   %.loc5_52.1 => constants.%.aec\n// CHECK:STDOUT:   %pattern_type.loc5_49 => constants.%pattern_type.615\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_16 => constants.%complete_type.f8a\n// CHECK:STDOUT:   %require_complete.loc5_52 => constants.%complete_type.c45\n// CHECK:STDOUT:   %struct_type.start.end => constants.%struct_type.start.end.d0a\n// CHECK:STDOUT:   %.loc6_22.1 => constants.%.14e\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.f17\n// CHECK:STDOUT:   %Copy.facet => constants.%Copy.facet.de4\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.081\n// CHECK:STDOUT:   %.loc6_22.2 => constants.%.8e2\n// CHECK:STDOUT:   %impl.elem0.loc6_22.2 => constants.%Int.as.Copy.impl.Op.664\n// CHECK:STDOUT:   %specific_impl_fn.loc6_22.2 => constants.%Int.as.Copy.impl.Op.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- trivial.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %y: Core.IntLiteral = symbolic_binding y, 0 [symbolic]\n// CHECK:STDOUT:   %Read.type: type = fn_type @Read [concrete]\n// CHECK:STDOUT:   %Read: %Read.type = struct_value () [concrete]\n// CHECK:STDOUT:   %IntRange.type: type = generic_class_type @IntRange [concrete]\n// CHECK:STDOUT:   %IntRange.generic: %IntRange.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %Int.b6d943.1: type = class_type @Int, @Int(%N) [symbolic]\n// CHECK:STDOUT:   %struct_type.start.end.79a: type = struct_type {.start: %Int.b6d943.1, .end: %Int.b6d943.1} [symbolic]\n// CHECK:STDOUT:   %complete_type.fb4: <witness> = complete_type_witness %struct_type.start.end.79a [symbolic]\n// CHECK:STDOUT:   %IntRange.265: type = class_type @IntRange, @IntRange(%N) [symbolic]\n// CHECK:STDOUT:   %IntRange.elem.302: type = unbound_element_type %IntRange.265, %Int.b6d943.1 [symbolic]\n// CHECK:STDOUT:   %require_complete.2ded7d.1: <witness> = require_complete_type %Int.b6d943.1 [symbolic]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.bb68b6.1: type = pattern_type %Int.b6d943.1 [symbolic]\n// CHECK:STDOUT:   %.b26: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %IntRange.Make.type.1df: type = fn_type @IntRange.Make, @IntRange(%N) [symbolic]\n// CHECK:STDOUT:   %IntRange.Make.8a9: %IntRange.Make.type.1df = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.b16: type = pattern_type %IntRange.265 [symbolic]\n// CHECK:STDOUT:   %.e1e: Core.Form = init_form %IntRange.265 [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.4c7: <witness> = lookup_impl_witness %Int.b6d943.1, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %Int.b6d943.1, (%Copy.lookup_impl_witness.4c7) [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.2e7: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]\n// CHECK:STDOUT:   %.cf8: type = fn_type_with_self_type %Copy.WithSelf.Op.type.2e7, %Copy.facet [symbolic]\n// CHECK:STDOUT:   %impl.elem0.84f: %.cf8 = impl_witness_access %Copy.lookup_impl_witness.4c7, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.508: <specific function> = specific_impl_function %impl.elem0.84f, @Copy.WithSelf.Op(%Copy.facet) [symbolic]\n// CHECK:STDOUT:   %require_complete.8a1: <witness> = require_complete_type %IntRange.265 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %IntRange.a89: type = class_type @IntRange, @IntRange(%int_32) [concrete]\n// CHECK:STDOUT:   %IntRange.Make.type.045: type = fn_type @IntRange.Make, @IntRange(%int_32) [concrete]\n// CHECK:STDOUT:   %IntRange.Make.3e9: %IntRange.Make.type.045 = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %.fc8: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %IntRange.elem.d76: type = unbound_element_type %IntRange.a89, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.start.end.0fe: type = struct_type {.start: %i32, .end: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.a43: <witness> = complete_type_witness %struct_type.start.end.0fe [concrete]\n// CHECK:STDOUT:   %pattern_type.615: type = pattern_type %IntRange.a89 [concrete]\n// CHECK:STDOUT:   %Range.type: type = fn_type @Range [concrete]\n// CHECK:STDOUT:   %Range: %Range.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cf3: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.255: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.58d: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.e45, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.cf3 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.58d) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.979: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.7c3: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.979, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %y, %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %y, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method(%y) [symbolic]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.IntRange: %IntRange.type = import_ref Main//lib, IntRange, loaded [concrete = constants.%IntRange.generic]\n// CHECK:STDOUT:   %Main.Range: %Range.type = import_ref Main//lib, Range, loaded [concrete = constants.%Range]\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/types/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Main.import_ref.6b552a.1: Core.IntLiteral = import_ref Main//lib, loc4_16, loaded [symbolic = @IntRange.%N (constants.%N)]\n// CHECK:STDOUT:   %Main.import_ref.4b6: <witness> = import_ref Main//lib, loc24_1, loaded [symbolic = @IntRange.%complete_type (constants.%complete_type.fb4)]\n// CHECK:STDOUT:   %Main.import_ref.011 = import_ref Main//lib, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.f89 = import_ref Main//lib, loc5_57, unloaded\n// CHECK:STDOUT:   %Main.import_ref.e7c = import_ref Main//lib, loc22_20, unloaded\n// CHECK:STDOUT:   %Main.import_ref.8ef = import_ref Main//lib, loc23_18, unloaded\n// CHECK:STDOUT:   %Main.import_ref.6b552a.2: Core.IntLiteral = import_ref Main//lib, loc4_16, loaded [symbolic = @IntRange.%N (constants.%N)]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.b25: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004) = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.255)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.e45 = impl_witness_table (%Core.import_ref.b25), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .IntRange = imports.%Main.IntRange\n// CHECK:STDOUT:     .Range = imports.%Main.Range\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .Read = %Read.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %Read.decl: %Read.type = fn_decl @Read [concrete = constants.%Read] {\n// CHECK:STDOUT:     %y.patt: %pattern_type.dc0 = symbolic_binding_pattern y, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_29.1: type = splice_block %.loc4_29.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core.ece [concrete = imports.%Core.ece]\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_29.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_29.3: type = converted %IntLiteral.call, %.loc4_29.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %y.loc4_9.2: Core.IntLiteral = symbolic_binding y, 0 [symbolic = %y.loc4_9.1 (constants.%y)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @IntRange(imports.%Main.import_ref.6b552a.2: Core.IntLiteral) [from \"lib.carbon\"] {\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %IntRange.Make.type: type = fn_type @IntRange.Make, @IntRange(%N) [symbolic = %IntRange.Make.type (constants.%IntRange.Make.type.1df)]\n// CHECK:STDOUT:   %IntRange.Make: @IntRange.%IntRange.Make.type (%IntRange.Make.type.1df) = struct_value () [symbolic = %IntRange.Make (constants.%IntRange.Make.8a9)]\n// CHECK:STDOUT:   %.1: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.1 (constants.%.b26)]\n// CHECK:STDOUT:   %Int: type = class_type @Int, @Int(%N) [symbolic = %Int (constants.%Int.b6d943.1)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Int [symbolic = %require_complete (constants.%require_complete.2ded7d.1)]\n// CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:   %IntRange.elem: type = unbound_element_type %IntRange, %Int [symbolic = %IntRange.elem (constants.%IntRange.elem.302)]\n// CHECK:STDOUT:   %struct_type.start.end: type = struct_type {.start: @IntRange.%Int (%Int.b6d943.1), .end: @IntRange.%Int (%Int.b6d943.1)} [symbolic = %struct_type.start.end (constants.%struct_type.start.end.79a)]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %struct_type.start.end [symbolic = %complete_type (constants.%complete_type.fb4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     complete_type_witness = imports.%Main.import_ref.4b6\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.011\n// CHECK:STDOUT:     .Make = imports.%Main.import_ref.f89\n// CHECK:STDOUT:     .start [private] = imports.%Main.import_ref.e7c\n// CHECK:STDOUT:     .end [private] = imports.%Main.import_ref.8ef\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Read(%y.loc4_9.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %y.loc4_9.1: Core.IntLiteral = symbolic_binding y, 0 [symbolic = %y.loc4_9.1 (constants.%y)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %y.loc4_9.1, constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:   %bound_method.loc5_38.3: <bound method> = bound_method %y.loc4_9.1, constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [symbolic = %bound_method.loc5_38.3 (constants.%bound_method)]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5_38.2: init %i32 = call %bound_method.loc5_38.3(%y.loc4_9.1) [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5_38.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %x.patt: %pattern_type.615 = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:       %x.var_patt: %pattern_type.615 = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.var: ref %IntRange.a89 = var %x.var_patt\n// CHECK:STDOUT:     %Range.ref: %Range.type = name_ref Range, imports.%Main.Range [concrete = constants.%Range]\n// CHECK:STDOUT:     %y.ref: Core.IntLiteral = name_ref y, %y.loc4_9.2 [symbolic = %y.loc4_9.1 (constants.%y)]\n// CHECK:STDOUT:     %.loc5_3: ref %IntRange.a89 = splice_block %x.var {}\n// CHECK:STDOUT:     %impl.elem0: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:     %bound_method.loc5_38.1: <bound method> = bound_method %y.ref, %impl.elem0 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc5_38.2: <bound method> = bound_method %y.ref, %specific_fn [symbolic = %bound_method.loc5_38.3 (constants.%bound_method)]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5_38.1: init %i32 = call %bound_method.loc5_38.2(%y.ref) [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5_38.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     %.loc5_38.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5_38.1 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5_38.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     %.loc5_38.2: %i32 = converted %y.ref, %.loc5_38.1 [symbolic = %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc5_38.2 (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:     %Range.call: init %IntRange.a89 to %.loc5_3 = call %Range.ref(%.loc5_38.2)\n// CHECK:STDOUT:     assign %x.var, %Range.call\n// CHECK:STDOUT:     %.loc5_28: type = splice_block %IntRange [concrete = constants.%IntRange.a89] {\n// CHECK:STDOUT:       %IntRange.ref: %IntRange.type = name_ref IntRange, imports.%Main.IntRange [concrete = constants.%IntRange.generic]\n// CHECK:STDOUT:       %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]\n// CHECK:STDOUT:       %IntRange: type = class_type @IntRange, @IntRange(constants.%int_32) [concrete = constants.%IntRange.a89]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: ref %IntRange.a89 = ref_binding x, %x.var\n// CHECK:STDOUT:     %Destroy.Op.bound: <bound method> = bound_method %x.var, constants.%Destroy.Op\n// CHECK:STDOUT:     %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%x.var)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @IntRange.Make(imports.%Main.import_ref.6b552a.1: Core.IntLiteral) [from \"lib.carbon\"] {\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N (constants.%N)]\n// CHECK:STDOUT:   %Int: type = class_type @Int, @Int(%N) [symbolic = %Int (constants.%Int.b6d943.1)]\n// CHECK:STDOUT:   %pattern_type.1: type = pattern_type %Int [symbolic = %pattern_type.1 (constants.%pattern_type.bb68b6.1)]\n// CHECK:STDOUT:   %IntRange: type = class_type @IntRange, @IntRange(%N) [symbolic = %IntRange (constants.%IntRange.265)]\n// CHECK:STDOUT:   %.1: Core.Form = init_form %IntRange [symbolic = %.1 (constants.%.e1e)]\n// CHECK:STDOUT:   %pattern_type.2: type = pattern_type %IntRange [symbolic = %pattern_type.2 (constants.%pattern_type.b16)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.1: <witness> = require_complete_type %Int [symbolic = %require_complete.1 (constants.%require_complete.2ded7d.1)]\n// CHECK:STDOUT:   %require_complete.2: <witness> = require_complete_type %IntRange [symbolic = %require_complete.2 (constants.%require_complete.8a1)]\n// CHECK:STDOUT:   %struct_type.start.end: type = struct_type {.start: @IntRange.Make.%Int (%Int.b6d943.1), .end: @IntRange.Make.%Int (%Int.b6d943.1)} [symbolic = %struct_type.start.end (constants.%struct_type.start.end.79a)]\n// CHECK:STDOUT:   %.2: require_specific_def_type = require_specific_def @Int.as.Copy.impl(%N) [symbolic = %.2 (constants.%.b26)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %Int, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.4c7)]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %Int, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.2e7)]\n// CHECK:STDOUT:   %.3: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.3 (constants.%.cf8)]\n// CHECK:STDOUT:   %impl.elem0: @IntRange.Make.%.3 (%.cf8) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0 (constants.%impl.elem0.84f)]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Copy.WithSelf.Op(%Copy.facet) [symbolic = %specific_impl_fn (constants.%specific_impl_fn.508)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Range [from \"lib.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %IntRange.a89) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Read(constants.%y) {\n// CHECK:STDOUT:   %y.loc4_9.1 => constants.%y\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange(constants.%N) {\n// CHECK:STDOUT:   %N => constants.%N\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %IntRange.Make.type => constants.%IntRange.Make.type.1df\n// CHECK:STDOUT:   %IntRange.Make => constants.%IntRange.Make.8a9\n// CHECK:STDOUT:   %.1 => constants.%.b26\n// CHECK:STDOUT:   %Int => constants.%Int.b6d943.1\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.2ded7d.1\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.265\n// CHECK:STDOUT:   %IntRange.elem => constants.%IntRange.elem.302\n// CHECK:STDOUT:   %struct_type.start.end => constants.%struct_type.start.end.79a\n// CHECK:STDOUT:   %complete_type => constants.%complete_type.fb4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange.Make(constants.%N) {\n// CHECK:STDOUT:   %N => constants.%N\n// CHECK:STDOUT:   %Int => constants.%Int.b6d943.1\n// CHECK:STDOUT:   %pattern_type.1 => constants.%pattern_type.bb68b6.1\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.265\n// CHECK:STDOUT:   %.1 => constants.%.e1e\n// CHECK:STDOUT:   %pattern_type.2 => constants.%pattern_type.b16\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @IntRange(constants.%int_32) {\n// CHECK:STDOUT:   %N => constants.%int_32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %IntRange.Make.type => constants.%IntRange.Make.type.045\n// CHECK:STDOUT:   %IntRange.Make => constants.%IntRange.Make.3e9\n// CHECK:STDOUT:   %.1 => constants.%.fc8\n// CHECK:STDOUT:   %Int => constants.%i32\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %IntRange => constants.%IntRange.a89\n// CHECK:STDOUT:   %IntRange.elem => constants.%IntRange.elem.d76\n// CHECK:STDOUT:   %struct_type.start.end => constants.%struct_type.start.end.0fe\n// CHECK:STDOUT:   %complete_type => constants.%complete_type.a43\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/for/basic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/for.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/for/basic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/for/basic.carbon\n\n// --- fail_not_range.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Run() {\n  // TODO: These diagnostics could be better. If nothing else, we should only diagnose once.\n  // CHECK:STDERR: fail_not_range.carbon:[[@LINE+8]]:7: error: cannot access member of interface `Core.Iterate` in type `{}` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   for (unused c: {} in {}) {\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_not_range.carbon:[[@LINE+4]]:7: error: cannot access member of interface `Core.Iterate` in type `{}` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   for (unused c: {} in {}) {\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  for (unused c: {} in {}) {\n  }\n}\n\n// --- trivial.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass TrivialRange {\n  impl as Core.Iterate where .CursorType = () and .ElementType = () {\n    fn NewCursor[unused self: Self]() {}\n    fn Next[unused self: Self](unused cursor: ()*) -> Core.Optional(()) {\n      return Core.Optional(()).None();\n    }\n  }\n}\n\nfn Body();\nfn AfterLoop();\n\nfn Run() {\n  //@dump-sem-ir-begin\n  for (_: () in {} as TrivialRange) {\n    Body();\n  }\n  AfterLoop();\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- trivial.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %TrivialRange: type = class_type @TrivialRange [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Iterate.type: type = facet_type <@Iterate> [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Optional.Get.type.5bc: type = fn_type @Optional.Get, @Optional(%T.035) [symbolic]\n// CHECK:STDOUT:   %Optional.Get.fa5: %Optional.Get.type.5bc = struct_value () [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.type.958: type = fn_type @Optional.HasValue, @Optional(%T.035) [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.d9c: %Optional.HasValue.type.958 = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.927: <witness> = impl_witness imports.%Copy.impl_witness_table.951 [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %empty_tuple.type, (%Copy.impl_witness.927) [concrete]\n// CHECK:STDOUT:   %Iterate.impl_witness: <witness> = impl_witness @TrivialRange.as.Iterate.impl.%Iterate.impl_witness_table [concrete]\n// CHECK:STDOUT:   %TrivialRange.as.Iterate.impl.NewCursor.type.408fa8.1: type = fn_type @TrivialRange.as.Iterate.impl.NewCursor.loc6_39.1 [concrete]\n// CHECK:STDOUT:   %TrivialRange.as.Iterate.impl.NewCursor.c71f42.1: %TrivialRange.as.Iterate.impl.NewCursor.type.408fa8.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.843: type = ptr_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Optional.311: type = class_type @Optional, @Optional(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %TrivialRange.as.Iterate.impl.Next.type: type = fn_type @TrivialRange.as.Iterate.impl.Next [concrete]\n// CHECK:STDOUT:   %TrivialRange.as.Iterate.impl.Next: %TrivialRange.as.Iterate.impl.Next.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Iterate.facet: %Iterate.type = facet_value %TrivialRange, (%Iterate.impl_witness) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.NewCursor.type.a3c: type = fn_type @Iterate.WithSelf.NewCursor, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.Next.type.9dc: type = fn_type @Iterate.WithSelf.Next, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %TrivialRange.as.Iterate.impl.NewCursor.type.408fa8.2: type = fn_type @TrivialRange.as.Iterate.impl.NewCursor.loc6_39.2 [concrete]\n// CHECK:STDOUT:   %TrivialRange.as.Iterate.impl.NewCursor.c71f42.2: %TrivialRange.as.Iterate.impl.NewCursor.type.408fa8.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.type.4db: type = fn_type @Optional.HasValue, @Optional(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.4fc: %Optional.HasValue.type.4db = struct_value () [concrete]\n// CHECK:STDOUT:   %Optional.Get.type.68c: type = fn_type @Optional.Get, @Optional(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.Get.756: %Optional.Get.type.68c = struct_value () [concrete]\n// CHECK:STDOUT:   %Body.type: type = fn_type @Body [concrete]\n// CHECK:STDOUT:   %Body: %Body.type = struct_value () [concrete]\n// CHECK:STDOUT:   %AfterLoop.type: type = fn_type @AfterLoop [concrete]\n// CHECK:STDOUT:   %AfterLoop: %AfterLoop.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %TrivialRange.val: %TrivialRange = struct_value () [concrete]\n// CHECK:STDOUT:   %.ccd: type = fn_type_with_self_type %Iterate.WithSelf.NewCursor.type.a3c, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %.827: type = fn_type_with_self_type %Iterate.WithSelf.Next.type.9dc, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %Optional.HasValue.4fc, @Optional.HasValue(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Optional.Get.756, @Optional.Get(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc18_35.1 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc18_35.2 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc18_20 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple.type.as.Copy.impl.Op.type: type = fn_type @empty_tuple.type.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %empty_tuple.type.as.Copy.impl.Op: %empty_tuple.type.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.228: @Optional.%Optional.HasValue.type (%Optional.HasValue.type.958) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.HasValue (constants.%Optional.HasValue.d9c)]\n// CHECK:STDOUT:   %Core.import_ref.f79: @Optional.%Optional.Get.type (%Optional.Get.type.5bc) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.Get (constants.%Optional.Get.fa5)]\n// CHECK:STDOUT:   %Core.import_ref.903: %empty_tuple.type.as.Copy.impl.Op.type = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [concrete = constants.%empty_tuple.type.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.951 = impl_witness_table (%Core.import_ref.903), @empty_tuple.type.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %_.patt: %pattern_type.cb1 = value_binding_pattern _ [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc18_18.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %TrivialRange.ref: type = name_ref TrivialRange, file.%TrivialRange.decl [concrete = constants.%TrivialRange]\n// CHECK:STDOUT:   %.loc18_18.2: ref %TrivialRange = temporary_storage\n// CHECK:STDOUT:   %.loc18_18.3: init %TrivialRange to %.loc18_18.2 = class_init () [concrete = constants.%TrivialRange.val]\n// CHECK:STDOUT:   %.loc18_20.1: init %TrivialRange = converted %.loc18_18.1, %.loc18_18.3 [concrete = constants.%TrivialRange.val]\n// CHECK:STDOUT:   %.loc18_20.2: ref %TrivialRange = temporary %.loc18_18.2, %.loc18_20.1\n// CHECK:STDOUT:   %impl.elem2: %.ccd = impl_witness_access constants.%Iterate.impl_witness, element2 [concrete = constants.%TrivialRange.as.Iterate.impl.NewCursor.c71f42.2]\n// CHECK:STDOUT:   %bound_method.loc18_35.1: <bound method> = bound_method %.loc18_20.2, %impl.elem2\n// CHECK:STDOUT:   %.loc18_20.3: %TrivialRange = acquire_value %.loc18_20.2\n// CHECK:STDOUT:   %NewCursor.ref: %TrivialRange.as.Iterate.impl.NewCursor.type.408fa8.1 = name_ref NewCursor, @TrivialRange.as.Iterate.impl.%TrivialRange.as.Iterate.impl.NewCursor.decl.loc6_39.1 [concrete = constants.%TrivialRange.as.Iterate.impl.NewCursor.c71f42.1]\n// CHECK:STDOUT:   %TrivialRange.as.Iterate.impl.NewCursor.bound: <bound method> = bound_method %.loc18_20.3, %NewCursor.ref\n// CHECK:STDOUT:   %TrivialRange.as.Iterate.impl.NewCursor.call: init %empty_tuple.type = call %TrivialRange.as.Iterate.impl.NewCursor.bound(%.loc18_20.3)\n// CHECK:STDOUT:   %var: ref %empty_tuple.type = var invalid\n// CHECK:STDOUT:   assign %var, %TrivialRange.as.Iterate.impl.NewCursor.call\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.next:\n// CHECK:STDOUT:   %addr: %ptr.843 = addr_of %var\n// CHECK:STDOUT:   %impl.elem3: %.827 = impl_witness_access constants.%Iterate.impl_witness, element3 [concrete = constants.%TrivialRange.as.Iterate.impl.Next]\n// CHECK:STDOUT:   %bound_method.loc18_35.2: <bound method> = bound_method %.loc18_20.2, %impl.elem3\n// CHECK:STDOUT:   %.loc18_35.1: ref %Optional.311 = temporary_storage\n// CHECK:STDOUT:   %.loc18_20.4: %TrivialRange = acquire_value %.loc18_20.2\n// CHECK:STDOUT:   %TrivialRange.as.Iterate.impl.Next.call: init %Optional.311 to %.loc18_35.1 = call %bound_method.loc18_35.2(%.loc18_20.4, %addr)\n// CHECK:STDOUT:   %.loc18_35.2: ref %Optional.311 = temporary %.loc18_35.1, %TrivialRange.as.Iterate.impl.Next.call\n// CHECK:STDOUT:   %.loc18_35.3: %Optional.HasValue.type.4db = specific_constant imports.%Core.import_ref.228, @Optional(constants.%Copy.facet) [concrete = constants.%Optional.HasValue.4fc]\n// CHECK:STDOUT:   %HasValue.ref: %Optional.HasValue.type.4db = name_ref HasValue, %.loc18_35.3 [concrete = constants.%Optional.HasValue.4fc]\n// CHECK:STDOUT:   %Optional.HasValue.bound: <bound method> = bound_method %.loc18_35.2, %HasValue.ref\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %HasValue.ref, @Optional.HasValue(constants.%Copy.facet) [concrete = constants.%Optional.HasValue.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_35.3: <bound method> = bound_method %.loc18_35.2, %Optional.HasValue.specific_fn\n// CHECK:STDOUT:   %.loc18_35.4: %Optional.311 = acquire_value %.loc18_35.2\n// CHECK:STDOUT:   %Optional.HasValue.call: init bool = call %bound_method.loc18_35.3(%.loc18_35.4)\n// CHECK:STDOUT:   %.loc18_35.5: bool = value_of_initializer %Optional.HasValue.call\n// CHECK:STDOUT:   %.loc18_35.6: bool = converted %Optional.HasValue.call, %.loc18_35.5\n// CHECK:STDOUT:   if %.loc18_35.6 br !for.body else br !for.done\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.body:\n// CHECK:STDOUT:   %.loc18_35.7: %Optional.Get.type.68c = specific_constant imports.%Core.import_ref.f79, @Optional(constants.%Copy.facet) [concrete = constants.%Optional.Get.756]\n// CHECK:STDOUT:   %Get.ref: %Optional.Get.type.68c = name_ref Get, %.loc18_35.7 [concrete = constants.%Optional.Get.756]\n// CHECK:STDOUT:   %Optional.Get.bound: <bound method> = bound_method %.loc18_35.2, %Get.ref\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Get.ref, @Optional.Get(constants.%Copy.facet) [concrete = constants.%Optional.Get.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_35.4: <bound method> = bound_method %.loc18_35.2, %Optional.Get.specific_fn\n// CHECK:STDOUT:   %.loc18_35.8: %Optional.311 = acquire_value %.loc18_35.2\n// CHECK:STDOUT:   %Optional.Get.call: init %empty_tuple.type = call %bound_method.loc18_35.4(%.loc18_35.8)\n// CHECK:STDOUT:   %.loc18_12.1: type = splice_block %.loc18_12.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc18_12.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc18_12.3: type = converted %.loc18_12.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc18_35.9: ref %empty_tuple.type = temporary_storage\n// CHECK:STDOUT:   %.loc18_35.10: ref %empty_tuple.type = temporary %.loc18_35.9, %Optional.Get.call\n// CHECK:STDOUT:   %tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc18_35.11: %empty_tuple.type = converted %Optional.Get.call, %tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %_: %empty_tuple.type = value_binding _, %.loc18_35.11\n// CHECK:STDOUT:   %Body.ref: %Body.type = name_ref Body, file.%Body.decl [concrete = constants.%Body]\n// CHECK:STDOUT:   %Body.call: init %empty_tuple.type = call %Body.ref()\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.done:\n// CHECK:STDOUT:   %AfterLoop.ref: %AfterLoop.type = name_ref AfterLoop, file.%AfterLoop.decl [concrete = constants.%AfterLoop]\n// CHECK:STDOUT:   %AfterLoop.call: init %empty_tuple.type = call %AfterLoop.ref()\n// CHECK:STDOUT:   %Destroy.Op.bound.loc18_35.1: <bound method> = bound_method %.loc18_35.10, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc18_35.1: init %empty_tuple.type = call %Destroy.Op.bound.loc18_35.1(%.loc18_35.10)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc18_35.2: <bound method> = bound_method %.loc18_35.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc18_35.2: init %empty_tuple.type = call %Destroy.Op.bound.loc18_35.2(%.loc18_35.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc18_35.3: <bound method> = bound_method %var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc18_35.3: init %empty_tuple.type = call %Destroy.Op.bound.loc18_35.3(%var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc18_20: <bound method> = bound_method %.loc18_20.2, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc18_20: init %empty_tuple.type = call %Destroy.Op.bound.loc18_20(%.loc18_20.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc18_35.1(%self.param: ref %empty_tuple.type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc18_35.2(%self.param: ref %Optional.311) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc18_20(%self.param: ref %TrivialRange) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/for/pattern.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/for.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/for/pattern.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/for/pattern.carbon\n\n// --- empty_range.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass EmptyRange(T:! Core.Copy) {\n  fn Make() -> Self { return {}; }\n\n  impl as Core.Iterate where .CursorType = {} and .ElementType = T {\n    fn NewCursor[unused self: Self]() -> {} {\n      return {};\n    }\n    fn Next[unused self: Self](unused cursor: {}*) -> Core.Optional(T) {\n      return Core.Optional(T).None();\n    }\n  }\n}\n\nclass C {\n  impl as Core.Copy {\n    fn Op[unused self: Self]() -> Self { return {}; }\n  }\n}\n\n// --- value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"empty_range\";\n\nfn Body(c: C);\n\nfn Run() {\n  //@dump-sem-ir-begin\n  for (c: C in EmptyRange(C).Make()) {\n    Body(c);\n  }\n  //@dump-sem-ir-end\n}\n\n// --- var.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"empty_range\";\n\nfn Body(c: C*);\n\nfn Run() {\n  //@dump-sem-ir-begin\n  for (var c: C in EmptyRange(C).Make()) {\n    Body(&c);\n  }\n  //@dump-sem-ir-end\n}\n\n// --- tuple.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"empty_range\";\n\nfn Body(a: bool, b: bool);\n\nfn Run() {\n  //@dump-sem-ir-begin\n  for ((a: bool, b: bool) in EmptyRange((bool, bool)).Make()) {\n    Body(a, b);\n  }\n  //@dump-sem-ir-end\n}\n\n// --- tuple_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"empty_range\";\n\nfn Body(a: C, b: C);\n\nfn Run() {\n  //@dump-sem-ir-begin\n  for ((a: C, b: C) in EmptyRange((C, C)).Make()) {\n    Body(a, b);\n  }\n  //@dump-sem-ir-end\n}\n\n// --- fail_bad_pattern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"empty_range\";\n\nclass X {}\n\nfn Run() {\n  // CHECK:STDERR: fail_bad_pattern.carbon:[[@LINE+7]]:7: error: cannot implicitly convert expression of type `C` to `X` [ConversionFailure]\n  // CHECK:STDERR:   for (unused x: X in EmptyRange(C).Make()) {\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_bad_pattern.carbon:[[@LINE+4]]:7: note: type `C` does not implement interface `Core.ImplicitAs(X)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   for (unused x: X in EmptyRange(C).Make()) {\n  // CHECK:STDERR:       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  for (unused x: X in EmptyRange(C).Make()) {\n  }\n}\n\n// CHECK:STDOUT: --- value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Body.type: type = fn_type @Body [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Body: %Body.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %EmptyRange.type: type = generic_class_type @EmptyRange [concrete]\n// CHECK:STDOUT:   %EmptyRange.generic: %EmptyRange.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.56c: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %EmptyRange.Make.type.8d6: type = fn_type @EmptyRange.Make, @EmptyRange(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.Make.0dc: %EmptyRange.Make.type.8d6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.fab: <witness> = impl_witness imports.%Copy.impl_witness_table.c52 [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %C, (%Copy.impl_witness.fab) [concrete]\n// CHECK:STDOUT:   %EmptyRange.77b: type = class_type @EmptyRange, @EmptyRange(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.type.c0f: type = fn_type @EmptyRange.Make, @EmptyRange(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.f9f: %EmptyRange.Make.type.c0f = struct_value () [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.specific_fn: <specific function> = specific_function %EmptyRange.Make.f9f, @EmptyRange.Make(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Iterate.type: type = facet_type <@Iterate> [concrete]\n// CHECK:STDOUT:   %Optional.Get.type.1ac: type = fn_type @Optional.Get, @Optional(%T.56c) [symbolic]\n// CHECK:STDOUT:   %Optional.Get.748: %Optional.Get.type.1ac = struct_value () [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.type.051: type = fn_type @Optional.HasValue, @Optional(%T.56c) [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.6ae: %Optional.HasValue.type.051 = struct_value () [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.type.b9d: type = fn_type @EmptyRange.as.Iterate.impl.Next, @EmptyRange.as.Iterate.impl(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.682: %EmptyRange.as.Iterate.impl.Next.type.b9d = struct_value () [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.type.16c: type = fn_type @EmptyRange.as.Iterate.impl.NewCursor, @EmptyRange.as.Iterate.impl(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.cbe: %EmptyRange.as.Iterate.impl.NewCursor.type.16c = struct_value () [symbolic]\n// CHECK:STDOUT:   %Iterate.impl_witness.96d: <witness> = impl_witness imports.%Iterate.impl_witness_table, @EmptyRange.as.Iterate.impl(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.type.268: type = fn_type @EmptyRange.as.Iterate.impl.NewCursor, @EmptyRange.as.Iterate.impl(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.da5: %EmptyRange.as.Iterate.impl.NewCursor.type.268 = struct_value () [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.type.046: type = fn_type @EmptyRange.as.Iterate.impl.Next, @EmptyRange.as.Iterate.impl(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.d08: %EmptyRange.as.Iterate.impl.Next.type.046 = struct_value () [concrete]\n// CHECK:STDOUT:   %Iterate.facet: %Iterate.type = facet_value %EmptyRange.77b, (%Iterate.impl_witness.96d) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.NewCursor.type.a35: type = fn_type @Iterate.WithSelf.NewCursor, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.Next.type.7b4: type = fn_type @Iterate.WithSelf.Next, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %.e1f: type = fn_type_with_self_type %Iterate.WithSelf.NewCursor.type.a35, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.specific_fn: <specific function> = specific_function %EmptyRange.as.Iterate.impl.NewCursor.da5, @EmptyRange.as.Iterate.impl.NewCursor(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.527: type = fn_type_with_self_type %Iterate.WithSelf.Next.type.7b4, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %Optional.e59: type = class_type @Optional, @Optional(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.specific_fn: <specific function> = specific_function %EmptyRange.as.Iterate.impl.Next.d08, @EmptyRange.as.Iterate.impl.Next(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.type.26b: type = fn_type @Optional.HasValue, @Optional(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.61c: %Optional.HasValue.type.26b = struct_value () [concrete]\n// CHECK:STDOUT:   %Optional.Get.type.7ce: type = fn_type @Optional.Get, @Optional(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.Get.bce: %Optional.Get.type.7ce = struct_value () [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %Optional.HasValue.61c, @Optional.HasValue(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Optional.Get.bce, @Optional.Get(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc10_36.1 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc10_36.2 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc10_36.3 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.4: type = fn_type @Destroy.Op.loc10_35 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.4: %Destroy.Op.type.bae255.4 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.as.Copy.impl.Op.type: type = fn_type @C.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %C.as.Copy.impl.Op: %C.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.EmptyRange: %EmptyRange.type = import_ref Main//empty_range, EmptyRange, loaded [concrete = constants.%EmptyRange.generic]\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//empty_range, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.299: @EmptyRange.%EmptyRange.Make.type (%EmptyRange.Make.type.8d6) = import_ref Main//empty_range, loc5_21, loaded [symbolic = @EmptyRange.%EmptyRange.Make (constants.%EmptyRange.Make.0dc)]\n// CHECK:STDOUT:   %Main.import_ref.cb5: %C.as.Copy.impl.Op.type = import_ref Main//empty_range, loc19_40, loaded [concrete = constants.%C.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c52 = impl_witness_table (%Main.import_ref.cb5), @C.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.f5d: @Optional.%Optional.HasValue.type (%Optional.HasValue.type.051) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.HasValue (constants.%Optional.HasValue.6ae)]\n// CHECK:STDOUT:   %Core.import_ref.ab7: @Optional.%Optional.Get.type (%Optional.Get.type.1ac) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.Get (constants.%Optional.Get.748)]\n// CHECK:STDOUT:   %Main.import_ref.888 = import_ref Main//empty_range, loc7_68, unloaded\n// CHECK:STDOUT:   %Main.import_ref.999 = import_ref Main//empty_range, loc7_68, unloaded\n// CHECK:STDOUT:   %Main.import_ref.868: @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.NewCursor.type (%EmptyRange.as.Iterate.impl.NewCursor.type.16c) = import_ref Main//empty_range, loc8_45, loaded [symbolic = @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.NewCursor (constants.%EmptyRange.as.Iterate.impl.NewCursor.cbe)]\n// CHECK:STDOUT:   %Main.import_ref.574: @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.Next.type (%EmptyRange.as.Iterate.impl.Next.type.b9d) = import_ref Main//empty_range, loc11_72, loaded [symbolic = @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.Next (constants.%EmptyRange.as.Iterate.impl.Next.682)]\n// CHECK:STDOUT:   %Iterate.impl_witness_table = impl_witness_table (%Main.import_ref.888, %Main.import_ref.999, %Main.import_ref.868, %Main.import_ref.574), @EmptyRange.as.Iterate.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %EmptyRange.ref: %EmptyRange.type = name_ref EmptyRange, imports.%Main.EmptyRange [concrete = constants.%EmptyRange.generic]\n// CHECK:STDOUT:   %C.ref.loc10_27: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %C.ref.loc10_27, (constants.%Copy.impl_witness.fab) [concrete = constants.%Copy.facet]\n// CHECK:STDOUT:   %.loc10_28: %Copy.type = converted %C.ref.loc10_27, %Copy.facet [concrete = constants.%Copy.facet]\n// CHECK:STDOUT:   %EmptyRange: type = class_type @EmptyRange, @EmptyRange(constants.%Copy.facet) [concrete = constants.%EmptyRange.77b]\n// CHECK:STDOUT:   %.loc10_29: %EmptyRange.Make.type.c0f = specific_constant imports.%Main.import_ref.299, @EmptyRange(constants.%Copy.facet) [concrete = constants.%EmptyRange.Make.f9f]\n// CHECK:STDOUT:   %Make.ref: %EmptyRange.Make.type.c0f = name_ref Make, %.loc10_29 [concrete = constants.%EmptyRange.Make.f9f]\n// CHECK:STDOUT:   %EmptyRange.Make.specific_fn: <specific function> = specific_function %Make.ref, @EmptyRange.Make(constants.%Copy.facet) [concrete = constants.%EmptyRange.Make.specific_fn]\n// CHECK:STDOUT:   %.loc10_35.1: ref %EmptyRange.77b = temporary_storage\n// CHECK:STDOUT:   %EmptyRange.Make.call: init %EmptyRange.77b to %.loc10_35.1 = call %EmptyRange.Make.specific_fn()\n// CHECK:STDOUT:   %.loc10_35.2: ref %EmptyRange.77b = temporary %.loc10_35.1, %EmptyRange.Make.call\n// CHECK:STDOUT:   %impl.elem2: %.e1f = impl_witness_access constants.%Iterate.impl_witness.96d, element2 [concrete = constants.%EmptyRange.as.Iterate.impl.NewCursor.da5]\n// CHECK:STDOUT:   %bound_method.loc10_36.1: <bound method> = bound_method %.loc10_35.2, %impl.elem2\n// CHECK:STDOUT:   %specific_fn.loc10_36.1: <specific function> = specific_function %impl.elem2, @EmptyRange.as.Iterate.impl.NewCursor(constants.%Copy.facet) [concrete = constants.%EmptyRange.as.Iterate.impl.NewCursor.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_36.2: <bound method> = bound_method %.loc10_35.2, %specific_fn.loc10_36.1\n// CHECK:STDOUT:   %.loc10_35.3: %EmptyRange.77b = acquire_value %.loc10_35.2\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.call: init %empty_struct_type = call %bound_method.loc10_36.2(%.loc10_35.3)\n// CHECK:STDOUT:   %var: ref %empty_struct_type = var invalid\n// CHECK:STDOUT:   assign %var, %EmptyRange.as.Iterate.impl.NewCursor.call\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.next:\n// CHECK:STDOUT:   %addr: %ptr.c28 = addr_of %var\n// CHECK:STDOUT:   %impl.elem3: %.527 = impl_witness_access constants.%Iterate.impl_witness.96d, element3 [concrete = constants.%EmptyRange.as.Iterate.impl.Next.d08]\n// CHECK:STDOUT:   %bound_method.loc10_36.3: <bound method> = bound_method %.loc10_35.2, %impl.elem3\n// CHECK:STDOUT:   %specific_fn.loc10_36.2: <specific function> = specific_function %impl.elem3, @EmptyRange.as.Iterate.impl.Next(constants.%Copy.facet) [concrete = constants.%EmptyRange.as.Iterate.impl.Next.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_36.4: <bound method> = bound_method %.loc10_35.2, %specific_fn.loc10_36.2\n// CHECK:STDOUT:   %.loc10_36.1: ref %Optional.e59 = temporary_storage\n// CHECK:STDOUT:   %.loc10_35.4: %EmptyRange.77b = acquire_value %.loc10_35.2\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.call: init %Optional.e59 to %.loc10_36.1 = call %bound_method.loc10_36.4(%.loc10_35.4, %addr)\n// CHECK:STDOUT:   %.loc10_36.2: ref %Optional.e59 = temporary %.loc10_36.1, %EmptyRange.as.Iterate.impl.Next.call\n// CHECK:STDOUT:   %.loc10_36.3: %Optional.HasValue.type.26b = specific_constant imports.%Core.import_ref.f5d, @Optional(constants.%Copy.facet) [concrete = constants.%Optional.HasValue.61c]\n// CHECK:STDOUT:   %HasValue.ref: %Optional.HasValue.type.26b = name_ref HasValue, %.loc10_36.3 [concrete = constants.%Optional.HasValue.61c]\n// CHECK:STDOUT:   %Optional.HasValue.bound: <bound method> = bound_method %.loc10_36.2, %HasValue.ref\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %HasValue.ref, @Optional.HasValue(constants.%Copy.facet) [concrete = constants.%Optional.HasValue.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_36.5: <bound method> = bound_method %.loc10_36.2, %Optional.HasValue.specific_fn\n// CHECK:STDOUT:   %.loc10_36.4: %Optional.e59 = acquire_value %.loc10_36.2\n// CHECK:STDOUT:   %Optional.HasValue.call: init bool = call %bound_method.loc10_36.5(%.loc10_36.4)\n// CHECK:STDOUT:   %.loc10_36.5: bool = value_of_initializer %Optional.HasValue.call\n// CHECK:STDOUT:   %.loc10_36.6: bool = converted %Optional.HasValue.call, %.loc10_36.5\n// CHECK:STDOUT:   if %.loc10_36.6 br !for.body else br !for.done\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.body:\n// CHECK:STDOUT:   %.loc10_36.7: %Optional.Get.type.7ce = specific_constant imports.%Core.import_ref.ab7, @Optional(constants.%Copy.facet) [concrete = constants.%Optional.Get.bce]\n// CHECK:STDOUT:   %Get.ref: %Optional.Get.type.7ce = name_ref Get, %.loc10_36.7 [concrete = constants.%Optional.Get.bce]\n// CHECK:STDOUT:   %Optional.Get.bound: <bound method> = bound_method %.loc10_36.2, %Get.ref\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Get.ref, @Optional.Get(constants.%Copy.facet) [concrete = constants.%Optional.Get.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_36.6: <bound method> = bound_method %.loc10_36.2, %Optional.Get.specific_fn\n// CHECK:STDOUT:   %.loc10_36.8: ref %C = temporary_storage\n// CHECK:STDOUT:   %.loc10_36.9: %Optional.e59 = acquire_value %.loc10_36.2\n// CHECK:STDOUT:   %Optional.Get.call: init %C to %.loc10_36.8 = call %bound_method.loc10_36.6(%.loc10_36.9)\n// CHECK:STDOUT:   %C.ref.loc10_11: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc10_36.10: ref %C = temporary %.loc10_36.8, %Optional.Get.call\n// CHECK:STDOUT:   %.loc10_36.11: %C = acquire_value %.loc10_36.10\n// CHECK:STDOUT:   %c: %C = value_binding c, %.loc10_36.11\n// CHECK:STDOUT:   %Body.ref: %Body.type = name_ref Body, file.%Body.decl [concrete = constants.%Body]\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %Body.call: init %empty_tuple.type = call %Body.ref(%c.ref)\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.done:\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_36.1: <bound method> = bound_method %.loc10_36.10, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_36.1: init %empty_tuple.type = call %Destroy.Op.bound.loc10_36.1(%.loc10_36.10)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_36.2: <bound method> = bound_method %.loc10_36.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_36.2: init %empty_tuple.type = call %Destroy.Op.bound.loc10_36.2(%.loc10_36.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_36.3: <bound method> = bound_method %var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_36.3: init %empty_tuple.type = call %Destroy.Op.bound.loc10_36.3(%var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_35: <bound method> = bound_method %.loc10_35.2, constants.%Destroy.Op.651ba6.4\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_35: init %empty_tuple.type = call %Destroy.Op.bound.loc10_35(%.loc10_35.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_36.1(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_36.2(%self.param: ref %Optional.e59) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_36.3(%self.param: ref %empty_struct_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_35(%self.param: ref %EmptyRange.77b) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- var.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %Body.type: type = fn_type @Body [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Body: %Body.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %EmptyRange.type: type = generic_class_type @EmptyRange [concrete]\n// CHECK:STDOUT:   %EmptyRange.generic: %EmptyRange.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.56c: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %EmptyRange.Make.type.8d6: type = fn_type @EmptyRange.Make, @EmptyRange(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.Make.0dc: %EmptyRange.Make.type.8d6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.fab: <witness> = impl_witness imports.%Copy.impl_witness_table.c52 [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %C, (%Copy.impl_witness.fab) [concrete]\n// CHECK:STDOUT:   %EmptyRange.77b: type = class_type @EmptyRange, @EmptyRange(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.type.c0f: type = fn_type @EmptyRange.Make, @EmptyRange(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.f9f: %EmptyRange.Make.type.c0f = struct_value () [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.specific_fn: <specific function> = specific_function %EmptyRange.Make.f9f, @EmptyRange.Make(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Iterate.type: type = facet_type <@Iterate> [concrete]\n// CHECK:STDOUT:   %Optional.Get.type.1ac: type = fn_type @Optional.Get, @Optional(%T.56c) [symbolic]\n// CHECK:STDOUT:   %Optional.Get.748: %Optional.Get.type.1ac = struct_value () [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.type.051: type = fn_type @Optional.HasValue, @Optional(%T.56c) [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.6ae: %Optional.HasValue.type.051 = struct_value () [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.type.b9d: type = fn_type @EmptyRange.as.Iterate.impl.Next, @EmptyRange.as.Iterate.impl(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.682: %EmptyRange.as.Iterate.impl.Next.type.b9d = struct_value () [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.type.16c: type = fn_type @EmptyRange.as.Iterate.impl.NewCursor, @EmptyRange.as.Iterate.impl(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.cbe: %EmptyRange.as.Iterate.impl.NewCursor.type.16c = struct_value () [symbolic]\n// CHECK:STDOUT:   %Iterate.impl_witness.96d: <witness> = impl_witness imports.%Iterate.impl_witness_table, @EmptyRange.as.Iterate.impl(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.type.268: type = fn_type @EmptyRange.as.Iterate.impl.NewCursor, @EmptyRange.as.Iterate.impl(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.da5: %EmptyRange.as.Iterate.impl.NewCursor.type.268 = struct_value () [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.type.046: type = fn_type @EmptyRange.as.Iterate.impl.Next, @EmptyRange.as.Iterate.impl(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.d08: %EmptyRange.as.Iterate.impl.Next.type.046 = struct_value () [concrete]\n// CHECK:STDOUT:   %Iterate.facet: %Iterate.type = facet_value %EmptyRange.77b, (%Iterate.impl_witness.96d) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.NewCursor.type.a35: type = fn_type @Iterate.WithSelf.NewCursor, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.Next.type.7b4: type = fn_type @Iterate.WithSelf.Next, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %.e1f: type = fn_type_with_self_type %Iterate.WithSelf.NewCursor.type.a35, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.specific_fn: <specific function> = specific_function %EmptyRange.as.Iterate.impl.NewCursor.da5, @EmptyRange.as.Iterate.impl.NewCursor(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.527: type = fn_type_with_self_type %Iterate.WithSelf.Next.type.7b4, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %Optional.e59: type = class_type @Optional, @Optional(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.specific_fn: <specific function> = specific_function %EmptyRange.as.Iterate.impl.Next.d08, @EmptyRange.as.Iterate.impl.Next(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.type.26b: type = fn_type @Optional.HasValue, @Optional(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.61c: %Optional.HasValue.type.26b = struct_value () [concrete]\n// CHECK:STDOUT:   %Optional.Get.type.7ce: type = fn_type @Optional.Get, @Optional(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.Get.bce: %Optional.Get.type.7ce = struct_value () [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %Optional.HasValue.61c, @Optional.HasValue(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Optional.Get.bce, @Optional.Get(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc10_8 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc10_40.1 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc10_40.2 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.4: type = fn_type @Destroy.Op.loc10_39 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.4: %Destroy.Op.type.bae255.4 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.as.Copy.impl.Op.type: type = fn_type @C.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %C.as.Copy.impl.Op: %C.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.EmptyRange: %EmptyRange.type = import_ref Main//empty_range, EmptyRange, loaded [concrete = constants.%EmptyRange.generic]\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//empty_range, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.299: @EmptyRange.%EmptyRange.Make.type (%EmptyRange.Make.type.8d6) = import_ref Main//empty_range, loc5_21, loaded [symbolic = @EmptyRange.%EmptyRange.Make (constants.%EmptyRange.Make.0dc)]\n// CHECK:STDOUT:   %Main.import_ref.cb5: %C.as.Copy.impl.Op.type = import_ref Main//empty_range, loc19_40, loaded [concrete = constants.%C.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c52 = impl_witness_table (%Main.import_ref.cb5), @C.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.f5d: @Optional.%Optional.HasValue.type (%Optional.HasValue.type.051) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.HasValue (constants.%Optional.HasValue.6ae)]\n// CHECK:STDOUT:   %Core.import_ref.ab7: @Optional.%Optional.Get.type (%Optional.Get.type.1ac) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.Get (constants.%Optional.Get.748)]\n// CHECK:STDOUT:   %Main.import_ref.888 = import_ref Main//empty_range, loc7_68, unloaded\n// CHECK:STDOUT:   %Main.import_ref.999 = import_ref Main//empty_range, loc7_68, unloaded\n// CHECK:STDOUT:   %Main.import_ref.868: @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.NewCursor.type (%EmptyRange.as.Iterate.impl.NewCursor.type.16c) = import_ref Main//empty_range, loc8_45, loaded [symbolic = @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.NewCursor (constants.%EmptyRange.as.Iterate.impl.NewCursor.cbe)]\n// CHECK:STDOUT:   %Main.import_ref.574: @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.Next.type (%EmptyRange.as.Iterate.impl.Next.type.b9d) = import_ref Main//empty_range, loc11_72, loaded [symbolic = @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.Next (constants.%EmptyRange.as.Iterate.impl.Next.682)]\n// CHECK:STDOUT:   %Iterate.impl_witness_table = impl_witness_table (%Main.import_ref.888, %Main.import_ref.999, %Main.import_ref.868, %Main.import_ref.574), @EmptyRange.as.Iterate.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.7c7 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %EmptyRange.ref: %EmptyRange.type = name_ref EmptyRange, imports.%Main.EmptyRange [concrete = constants.%EmptyRange.generic]\n// CHECK:STDOUT:   %C.ref.loc10_31: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %C.ref.loc10_31, (constants.%Copy.impl_witness.fab) [concrete = constants.%Copy.facet]\n// CHECK:STDOUT:   %.loc10_32: %Copy.type = converted %C.ref.loc10_31, %Copy.facet [concrete = constants.%Copy.facet]\n// CHECK:STDOUT:   %EmptyRange: type = class_type @EmptyRange, @EmptyRange(constants.%Copy.facet) [concrete = constants.%EmptyRange.77b]\n// CHECK:STDOUT:   %.loc10_33: %EmptyRange.Make.type.c0f = specific_constant imports.%Main.import_ref.299, @EmptyRange(constants.%Copy.facet) [concrete = constants.%EmptyRange.Make.f9f]\n// CHECK:STDOUT:   %Make.ref: %EmptyRange.Make.type.c0f = name_ref Make, %.loc10_33 [concrete = constants.%EmptyRange.Make.f9f]\n// CHECK:STDOUT:   %EmptyRange.Make.specific_fn: <specific function> = specific_function %Make.ref, @EmptyRange.Make(constants.%Copy.facet) [concrete = constants.%EmptyRange.Make.specific_fn]\n// CHECK:STDOUT:   %.loc10_39.1: ref %EmptyRange.77b = temporary_storage\n// CHECK:STDOUT:   %EmptyRange.Make.call: init %EmptyRange.77b to %.loc10_39.1 = call %EmptyRange.Make.specific_fn()\n// CHECK:STDOUT:   %.loc10_39.2: ref %EmptyRange.77b = temporary %.loc10_39.1, %EmptyRange.Make.call\n// CHECK:STDOUT:   %impl.elem2: %.e1f = impl_witness_access constants.%Iterate.impl_witness.96d, element2 [concrete = constants.%EmptyRange.as.Iterate.impl.NewCursor.da5]\n// CHECK:STDOUT:   %bound_method.loc10_40.1: <bound method> = bound_method %.loc10_39.2, %impl.elem2\n// CHECK:STDOUT:   %specific_fn.loc10_40.1: <specific function> = specific_function %impl.elem2, @EmptyRange.as.Iterate.impl.NewCursor(constants.%Copy.facet) [concrete = constants.%EmptyRange.as.Iterate.impl.NewCursor.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_40.2: <bound method> = bound_method %.loc10_39.2, %specific_fn.loc10_40.1\n// CHECK:STDOUT:   %.loc10_39.3: %EmptyRange.77b = acquire_value %.loc10_39.2\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.call: init %empty_struct_type = call %bound_method.loc10_40.2(%.loc10_39.3)\n// CHECK:STDOUT:   %var: ref %empty_struct_type = var invalid\n// CHECK:STDOUT:   assign %var, %EmptyRange.as.Iterate.impl.NewCursor.call\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.next:\n// CHECK:STDOUT:   %addr.loc10: %ptr.c28 = addr_of %var\n// CHECK:STDOUT:   %impl.elem3: %.527 = impl_witness_access constants.%Iterate.impl_witness.96d, element3 [concrete = constants.%EmptyRange.as.Iterate.impl.Next.d08]\n// CHECK:STDOUT:   %bound_method.loc10_40.3: <bound method> = bound_method %.loc10_39.2, %impl.elem3\n// CHECK:STDOUT:   %specific_fn.loc10_40.2: <specific function> = specific_function %impl.elem3, @EmptyRange.as.Iterate.impl.Next(constants.%Copy.facet) [concrete = constants.%EmptyRange.as.Iterate.impl.Next.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_40.4: <bound method> = bound_method %.loc10_39.2, %specific_fn.loc10_40.2\n// CHECK:STDOUT:   %.loc10_40.1: ref %Optional.e59 = temporary_storage\n// CHECK:STDOUT:   %.loc10_39.4: %EmptyRange.77b = acquire_value %.loc10_39.2\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.call: init %Optional.e59 to %.loc10_40.1 = call %bound_method.loc10_40.4(%.loc10_39.4, %addr.loc10)\n// CHECK:STDOUT:   %.loc10_40.2: ref %Optional.e59 = temporary %.loc10_40.1, %EmptyRange.as.Iterate.impl.Next.call\n// CHECK:STDOUT:   %.loc10_40.3: %Optional.HasValue.type.26b = specific_constant imports.%Core.import_ref.f5d, @Optional(constants.%Copy.facet) [concrete = constants.%Optional.HasValue.61c]\n// CHECK:STDOUT:   %HasValue.ref: %Optional.HasValue.type.26b = name_ref HasValue, %.loc10_40.3 [concrete = constants.%Optional.HasValue.61c]\n// CHECK:STDOUT:   %Optional.HasValue.bound: <bound method> = bound_method %.loc10_40.2, %HasValue.ref\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %HasValue.ref, @Optional.HasValue(constants.%Copy.facet) [concrete = constants.%Optional.HasValue.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_40.5: <bound method> = bound_method %.loc10_40.2, %Optional.HasValue.specific_fn\n// CHECK:STDOUT:   %.loc10_40.4: %Optional.e59 = acquire_value %.loc10_40.2\n// CHECK:STDOUT:   %Optional.HasValue.call: init bool = call %bound_method.loc10_40.5(%.loc10_40.4)\n// CHECK:STDOUT:   %.loc10_40.5: bool = value_of_initializer %Optional.HasValue.call\n// CHECK:STDOUT:   %.loc10_40.6: bool = converted %Optional.HasValue.call, %.loc10_40.5\n// CHECK:STDOUT:   if %.loc10_40.6 br !for.body else br !for.done\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.body:\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt\n// CHECK:STDOUT:   %.loc10_40.7: %Optional.Get.type.7ce = specific_constant imports.%Core.import_ref.ab7, @Optional(constants.%Copy.facet) [concrete = constants.%Optional.Get.bce]\n// CHECK:STDOUT:   %Get.ref: %Optional.Get.type.7ce = name_ref Get, %.loc10_40.7 [concrete = constants.%Optional.Get.bce]\n// CHECK:STDOUT:   %Optional.Get.bound: <bound method> = bound_method %.loc10_40.2, %Get.ref\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Get.ref, @Optional.Get(constants.%Copy.facet) [concrete = constants.%Optional.Get.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_40.6: <bound method> = bound_method %.loc10_40.2, %Optional.Get.specific_fn\n// CHECK:STDOUT:   %.loc10_8: ref %C = splice_block %c.var {}\n// CHECK:STDOUT:   %.loc10_40.8: %Optional.e59 = acquire_value %.loc10_40.2\n// CHECK:STDOUT:   %Optional.Get.call: init %C to %.loc10_8 = call %bound_method.loc10_40.6(%.loc10_40.8)\n// CHECK:STDOUT:   assign %c.var, %Optional.Get.call\n// CHECK:STDOUT:   %C.ref.loc10_15: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var\n// CHECK:STDOUT:   %Body.ref: %Body.type = name_ref Body, file.%Body.decl [concrete = constants.%Body]\n// CHECK:STDOUT:   %c.ref: ref %C = name_ref c, %c\n// CHECK:STDOUT:   %addr.loc11: %ptr.31e = addr_of %c.ref\n// CHECK:STDOUT:   %Body.call: init %empty_tuple.type = call %Body.ref(%addr.loc11)\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.done:\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_8: <bound method> = bound_method %c.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_8: init %empty_tuple.type = call %Destroy.Op.bound.loc10_8(%c.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_40.1: <bound method> = bound_method %.loc10_40.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_40.1: init %empty_tuple.type = call %Destroy.Op.bound.loc10_40.1(%.loc10_40.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_40.2: <bound method> = bound_method %var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_40.2: init %empty_tuple.type = call %Destroy.Op.bound.loc10_40.2(%var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_39: <bound method> = bound_method %.loc10_39.2, constants.%Destroy.Op.651ba6.4\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_39: init %empty_tuple.type = call %Destroy.Op.bound.loc10_39(%.loc10_39.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_8(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_40.1(%self.param: ref %Optional.e59) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_40.2(%self.param: ref %empty_struct_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_39(%self.param: ref %EmptyRange.77b) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- tuple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %Body.type: type = fn_type @Body [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Body: %Body.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.784: type = tuple_type (bool, bool) [concrete]\n// CHECK:STDOUT:   %pattern_type.860: type = pattern_type %tuple.type.784 [concrete]\n// CHECK:STDOUT:   %EmptyRange.type: type = generic_class_type @EmptyRange [concrete]\n// CHECK:STDOUT:   %EmptyRange.generic: %EmptyRange.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.56c: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %EmptyRange.Make.type.8d6: type = fn_type @EmptyRange.Make, @EmptyRange(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.Make.0dc: %EmptyRange.Make.type.8d6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.9fa: %tuple.type.24b = tuple_value (bool, bool) [concrete]\n// CHECK:STDOUT:   %U: %Copy.type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %tuple.type.as.Copy.impl.Op.type.57a: type = fn_type @tuple.type.as.Copy.impl.Op.1, @tuple.type.as.Copy.impl.da7(%T.56c, %U) [symbolic]\n// CHECK:STDOUT:   %tuple.type.as.Copy.impl.Op.7f4: %tuple.type.as.Copy.impl.Op.type.57a = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.819: <witness> = impl_witness imports.%Copy.impl_witness_table.164 [concrete]\n// CHECK:STDOUT:   %Copy.facet.07e: %Copy.type = facet_value bool, (%Copy.impl_witness.819) [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.f9f: <witness> = impl_witness imports.%Copy.impl_witness_table.3c8, @tuple.type.as.Copy.impl.da7(%Copy.facet.07e, %Copy.facet.07e) [concrete]\n// CHECK:STDOUT:   %Copy.facet.3ce: %Copy.type = facet_value %tuple.type.784, (%Copy.impl_witness.f9f) [concrete]\n// CHECK:STDOUT:   %EmptyRange.717: type = class_type @EmptyRange, @EmptyRange(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.type.a76: type = fn_type @EmptyRange.Make, @EmptyRange(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.d35: %EmptyRange.Make.type.a76 = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.specific_fn: <specific function> = specific_function %EmptyRange.Make.d35, @EmptyRange.Make(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %Iterate.type: type = facet_type <@Iterate> [concrete]\n// CHECK:STDOUT:   %Optional.Get.type.1ac: type = fn_type @Optional.Get, @Optional(%T.56c) [symbolic]\n// CHECK:STDOUT:   %Optional.Get.748: %Optional.Get.type.1ac = struct_value () [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.type.051: type = fn_type @Optional.HasValue, @Optional(%T.56c) [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.6ae: %Optional.HasValue.type.051 = struct_value () [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.type.b9d: type = fn_type @EmptyRange.as.Iterate.impl.Next, @EmptyRange.as.Iterate.impl(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.682: %EmptyRange.as.Iterate.impl.Next.type.b9d = struct_value () [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.type.16c: type = fn_type @EmptyRange.as.Iterate.impl.NewCursor, @EmptyRange.as.Iterate.impl(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.cbe: %EmptyRange.as.Iterate.impl.NewCursor.type.16c = struct_value () [symbolic]\n// CHECK:STDOUT:   %Iterate.impl_witness.04a: <witness> = impl_witness imports.%Iterate.impl_witness_table, @EmptyRange.as.Iterate.impl(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.type.a15: type = fn_type @EmptyRange.as.Iterate.impl.NewCursor, @EmptyRange.as.Iterate.impl(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.90c: %EmptyRange.as.Iterate.impl.NewCursor.type.a15 = struct_value () [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.type.f9b: type = fn_type @EmptyRange.as.Iterate.impl.Next, @EmptyRange.as.Iterate.impl(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.4a9: %EmptyRange.as.Iterate.impl.Next.type.f9b = struct_value () [concrete]\n// CHECK:STDOUT:   %Iterate.facet: %Iterate.type = facet_value %EmptyRange.717, (%Iterate.impl_witness.04a) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.NewCursor.type.fea: type = fn_type @Iterate.WithSelf.NewCursor, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.Next.type.346: type = fn_type @Iterate.WithSelf.Next, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %.a72: type = fn_type_with_self_type %Iterate.WithSelf.NewCursor.type.fea, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.specific_fn: <specific function> = specific_function %EmptyRange.as.Iterate.impl.NewCursor.90c, @EmptyRange.as.Iterate.impl.NewCursor(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %.28c: type = fn_type_with_self_type %Iterate.WithSelf.Next.type.346, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %Optional.678: type = class_type @Optional, @Optional(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.specific_fn: <specific function> = specific_function %EmptyRange.as.Iterate.impl.Next.4a9, @EmptyRange.as.Iterate.impl.Next(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.type.101: type = fn_type @Optional.HasValue, @Optional(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.960: %Optional.HasValue.type.101 = struct_value () [concrete]\n// CHECK:STDOUT:   %Optional.Get.type.758: type = fn_type @Optional.Get, @Optional(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %Optional.Get.2ff: %Optional.Get.type.758 = struct_value () [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %Optional.HasValue.960, @Optional.HasValue(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Optional.Get.2ff, @Optional.Get(%Copy.facet.3ce) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc10_61.1 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc10_61.2 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc10_61.3 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.4: type = fn_type @Destroy.Op.loc10_60 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.4: %Destroy.Op.type.bae255.4 = struct_value () [concrete]\n// CHECK:STDOUT:   %bool.as.Copy.impl.Op.type: type = fn_type @bool.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %bool.as.Copy.impl.Op: %bool.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.EmptyRange: %EmptyRange.type = import_ref Main//empty_range, EmptyRange, loaded [concrete = constants.%EmptyRange.generic]\n// CHECK:STDOUT:   %Main.import_ref.299: @EmptyRange.%EmptyRange.Make.type (%EmptyRange.Make.type.8d6) = import_ref Main//empty_range, loc5_21, loaded [symbolic = @EmptyRange.%EmptyRange.Make (constants.%EmptyRange.Make.0dc)]\n// CHECK:STDOUT:   %Core.import_ref.445: @tuple.type.as.Copy.impl.da7.%tuple.type.as.Copy.impl.Op.type (%tuple.type.as.Copy.impl.Op.type.57a) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @tuple.type.as.Copy.impl.da7.%tuple.type.as.Copy.impl.Op (constants.%tuple.type.as.Copy.impl.Op.7f4)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.3c8 = impl_witness_table (%Core.import_ref.445), @tuple.type.as.Copy.impl.da7 [concrete]\n// CHECK:STDOUT:   %Core.import_ref.4d6: %bool.as.Copy.impl.Op.type = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [concrete = constants.%bool.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.164 = impl_witness_table (%Core.import_ref.4d6), @bool.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.f5d: @Optional.%Optional.HasValue.type (%Optional.HasValue.type.051) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.HasValue (constants.%Optional.HasValue.6ae)]\n// CHECK:STDOUT:   %Core.import_ref.ab7: @Optional.%Optional.Get.type (%Optional.Get.type.1ac) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.Get (constants.%Optional.Get.748)]\n// CHECK:STDOUT:   %Main.import_ref.888 = import_ref Main//empty_range, loc7_68, unloaded\n// CHECK:STDOUT:   %Main.import_ref.999 = import_ref Main//empty_range, loc7_68, unloaded\n// CHECK:STDOUT:   %Main.import_ref.868: @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.NewCursor.type (%EmptyRange.as.Iterate.impl.NewCursor.type.16c) = import_ref Main//empty_range, loc8_45, loaded [symbolic = @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.NewCursor (constants.%EmptyRange.as.Iterate.impl.NewCursor.cbe)]\n// CHECK:STDOUT:   %Main.import_ref.574: @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.Next.type (%EmptyRange.as.Iterate.impl.Next.type.b9d) = import_ref Main//empty_range, loc11_72, loaded [symbolic = @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.Next (constants.%EmptyRange.as.Iterate.impl.Next.682)]\n// CHECK:STDOUT:   %Iterate.impl_witness_table = impl_witness_table (%Main.import_ref.888, %Main.import_ref.999, %Main.import_ref.868, %Main.import_ref.574), @EmptyRange.as.Iterate.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.831 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %.loc10_25: %pattern_type.860 = tuple_pattern (%a.patt, %b.patt) [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %EmptyRange.ref: %EmptyRange.type = name_ref EmptyRange, imports.%Main.EmptyRange [concrete = constants.%EmptyRange.generic]\n// CHECK:STDOUT:   %.loc10_42: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:   %.loc10_48: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:   %.loc10_52: %tuple.type.24b = tuple_literal (%.loc10_42, %.loc10_48) [concrete = constants.%tuple.9fa]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value constants.%tuple.type.784, (constants.%Copy.impl_witness.f9f) [concrete = constants.%Copy.facet.3ce]\n// CHECK:STDOUT:   %.loc10_53: %Copy.type = converted %.loc10_52, %Copy.facet [concrete = constants.%Copy.facet.3ce]\n// CHECK:STDOUT:   %EmptyRange: type = class_type @EmptyRange, @EmptyRange(constants.%Copy.facet.3ce) [concrete = constants.%EmptyRange.717]\n// CHECK:STDOUT:   %.loc10_54: %EmptyRange.Make.type.a76 = specific_constant imports.%Main.import_ref.299, @EmptyRange(constants.%Copy.facet.3ce) [concrete = constants.%EmptyRange.Make.d35]\n// CHECK:STDOUT:   %Make.ref: %EmptyRange.Make.type.a76 = name_ref Make, %.loc10_54 [concrete = constants.%EmptyRange.Make.d35]\n// CHECK:STDOUT:   %EmptyRange.Make.specific_fn: <specific function> = specific_function %Make.ref, @EmptyRange.Make(constants.%Copy.facet.3ce) [concrete = constants.%EmptyRange.Make.specific_fn]\n// CHECK:STDOUT:   %.loc10_60.1: ref %EmptyRange.717 = temporary_storage\n// CHECK:STDOUT:   %EmptyRange.Make.call: init %EmptyRange.717 to %.loc10_60.1 = call %EmptyRange.Make.specific_fn()\n// CHECK:STDOUT:   %.loc10_60.2: ref %EmptyRange.717 = temporary %.loc10_60.1, %EmptyRange.Make.call\n// CHECK:STDOUT:   %impl.elem2: %.a72 = impl_witness_access constants.%Iterate.impl_witness.04a, element2 [concrete = constants.%EmptyRange.as.Iterate.impl.NewCursor.90c]\n// CHECK:STDOUT:   %bound_method.loc10_61.1: <bound method> = bound_method %.loc10_60.2, %impl.elem2\n// CHECK:STDOUT:   %specific_fn.loc10_61.1: <specific function> = specific_function %impl.elem2, @EmptyRange.as.Iterate.impl.NewCursor(constants.%Copy.facet.3ce) [concrete = constants.%EmptyRange.as.Iterate.impl.NewCursor.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_61.2: <bound method> = bound_method %.loc10_60.2, %specific_fn.loc10_61.1\n// CHECK:STDOUT:   %.loc10_60.3: %EmptyRange.717 = acquire_value %.loc10_60.2\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.call: init %empty_struct_type = call %bound_method.loc10_61.2(%.loc10_60.3)\n// CHECK:STDOUT:   %var: ref %empty_struct_type = var invalid\n// CHECK:STDOUT:   assign %var, %EmptyRange.as.Iterate.impl.NewCursor.call\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.next:\n// CHECK:STDOUT:   %addr: %ptr.c28 = addr_of %var\n// CHECK:STDOUT:   %impl.elem3: %.28c = impl_witness_access constants.%Iterate.impl_witness.04a, element3 [concrete = constants.%EmptyRange.as.Iterate.impl.Next.4a9]\n// CHECK:STDOUT:   %bound_method.loc10_61.3: <bound method> = bound_method %.loc10_60.2, %impl.elem3\n// CHECK:STDOUT:   %specific_fn.loc10_61.2: <specific function> = specific_function %impl.elem3, @EmptyRange.as.Iterate.impl.Next(constants.%Copy.facet.3ce) [concrete = constants.%EmptyRange.as.Iterate.impl.Next.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_61.4: <bound method> = bound_method %.loc10_60.2, %specific_fn.loc10_61.2\n// CHECK:STDOUT:   %.loc10_61.1: ref %Optional.678 = temporary_storage\n// CHECK:STDOUT:   %.loc10_60.4: %EmptyRange.717 = acquire_value %.loc10_60.2\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.call: init %Optional.678 to %.loc10_61.1 = call %bound_method.loc10_61.4(%.loc10_60.4, %addr)\n// CHECK:STDOUT:   %.loc10_61.2: ref %Optional.678 = temporary %.loc10_61.1, %EmptyRange.as.Iterate.impl.Next.call\n// CHECK:STDOUT:   %.loc10_61.3: %Optional.HasValue.type.101 = specific_constant imports.%Core.import_ref.f5d, @Optional(constants.%Copy.facet.3ce) [concrete = constants.%Optional.HasValue.960]\n// CHECK:STDOUT:   %HasValue.ref: %Optional.HasValue.type.101 = name_ref HasValue, %.loc10_61.3 [concrete = constants.%Optional.HasValue.960]\n// CHECK:STDOUT:   %Optional.HasValue.bound: <bound method> = bound_method %.loc10_61.2, %HasValue.ref\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %HasValue.ref, @Optional.HasValue(constants.%Copy.facet.3ce) [concrete = constants.%Optional.HasValue.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_61.5: <bound method> = bound_method %.loc10_61.2, %Optional.HasValue.specific_fn\n// CHECK:STDOUT:   %.loc10_61.4: %Optional.678 = acquire_value %.loc10_61.2\n// CHECK:STDOUT:   %Optional.HasValue.call: init bool = call %bound_method.loc10_61.5(%.loc10_61.4)\n// CHECK:STDOUT:   %.loc10_61.5: bool = value_of_initializer %Optional.HasValue.call\n// CHECK:STDOUT:   %.loc10_61.6: bool = converted %Optional.HasValue.call, %.loc10_61.5\n// CHECK:STDOUT:   if %.loc10_61.6 br !for.body else br !for.done\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.body:\n// CHECK:STDOUT:   %.loc10_61.7: %Optional.Get.type.758 = specific_constant imports.%Core.import_ref.ab7, @Optional(constants.%Copy.facet.3ce) [concrete = constants.%Optional.Get.2ff]\n// CHECK:STDOUT:   %Get.ref: %Optional.Get.type.758 = name_ref Get, %.loc10_61.7 [concrete = constants.%Optional.Get.2ff]\n// CHECK:STDOUT:   %Optional.Get.bound: <bound method> = bound_method %.loc10_61.2, %Get.ref\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Get.ref, @Optional.Get(constants.%Copy.facet.3ce) [concrete = constants.%Optional.Get.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_61.6: <bound method> = bound_method %.loc10_61.2, %Optional.Get.specific_fn\n// CHECK:STDOUT:   %.loc10_61.8: ref %tuple.type.784 = temporary_storage\n// CHECK:STDOUT:   %.loc10_61.9: %Optional.678 = acquire_value %.loc10_61.2\n// CHECK:STDOUT:   %Optional.Get.call: init %tuple.type.784 to %.loc10_61.8 = call %bound_method.loc10_61.6(%.loc10_61.9)\n// CHECK:STDOUT:   %.loc10_61.10: ref %tuple.type.784 = temporary %.loc10_61.8, %Optional.Get.call\n// CHECK:STDOUT:   %tuple.elem0: ref bool = tuple_access %.loc10_61.10, element0\n// CHECK:STDOUT:   %tuple.elem1: ref bool = tuple_access %.loc10_61.10, element1\n// CHECK:STDOUT:   %.loc10_12: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:   %.loc10_61.11: bool = acquire_value %tuple.elem0\n// CHECK:STDOUT:   %a: bool = value_binding a, %.loc10_61.11\n// CHECK:STDOUT:   %.loc10_21: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:   %.loc10_61.12: bool = acquire_value %tuple.elem1\n// CHECK:STDOUT:   %b: bool = value_binding b, %.loc10_61.12\n// CHECK:STDOUT:   %Body.ref: %Body.type = name_ref Body, file.%Body.decl [concrete = constants.%Body]\n// CHECK:STDOUT:   %a.ref: bool = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b\n// CHECK:STDOUT:   %Body.call: init %empty_tuple.type = call %Body.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.done:\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_61.1: <bound method> = bound_method %.loc10_61.10, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_61.1: init %empty_tuple.type = call %Destroy.Op.bound.loc10_61.1(%.loc10_61.10)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_61.2: <bound method> = bound_method %.loc10_61.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_61.2: init %empty_tuple.type = call %Destroy.Op.bound.loc10_61.2(%.loc10_61.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_61.3: <bound method> = bound_method %var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_61.3: init %empty_tuple.type = call %Destroy.Op.bound.loc10_61.3(%var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_60: <bound method> = bound_method %.loc10_60.2, constants.%Destroy.Op.651ba6.4\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_60: init %empty_tuple.type = call %Destroy.Op.bound.loc10_60(%.loc10_60.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_61.1(%self.param: ref %tuple.type.784) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_61.2(%self.param: ref %Optional.678) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_61.3(%self.param: ref %empty_struct_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_60(%self.param: ref %EmptyRange.717) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- tuple_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Body.type: type = fn_type @Body [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Body: %Body.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %tuple.type.d23: type = tuple_type (%C, %C) [concrete]\n// CHECK:STDOUT:   %pattern_type.c3b: type = pattern_type %tuple.type.d23 [concrete]\n// CHECK:STDOUT:   %EmptyRange.type: type = generic_class_type @EmptyRange [concrete]\n// CHECK:STDOUT:   %EmptyRange.generic: %EmptyRange.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.56c: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %EmptyRange.Make.type.8d6: type = fn_type @EmptyRange.Make, @EmptyRange(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.Make.0dc: %EmptyRange.Make.type.8d6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.6f4: %tuple.type.24b = tuple_value (%C, %C) [concrete]\n// CHECK:STDOUT:   %U: %Copy.type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %tuple.type.as.Copy.impl.Op.type.57a: type = fn_type @tuple.type.as.Copy.impl.Op.1, @tuple.type.as.Copy.impl.da7(%T.56c, %U) [symbolic]\n// CHECK:STDOUT:   %tuple.type.as.Copy.impl.Op.7f4: %tuple.type.as.Copy.impl.Op.type.57a = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.fab: <witness> = impl_witness imports.%Copy.impl_witness_table.c52 [concrete]\n// CHECK:STDOUT:   %Copy.facet.54f: %Copy.type = facet_value %C, (%Copy.impl_witness.fab) [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.9e2: <witness> = impl_witness imports.%Copy.impl_witness_table.3c8, @tuple.type.as.Copy.impl.da7(%Copy.facet.54f, %Copy.facet.54f) [concrete]\n// CHECK:STDOUT:   %Copy.facet.ad0: %Copy.type = facet_value %tuple.type.d23, (%Copy.impl_witness.9e2) [concrete]\n// CHECK:STDOUT:   %EmptyRange.849: type = class_type @EmptyRange, @EmptyRange(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.type.7da: type = fn_type @EmptyRange.Make, @EmptyRange(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.38a: %EmptyRange.Make.type.7da = struct_value () [concrete]\n// CHECK:STDOUT:   %EmptyRange.Make.specific_fn: <specific function> = specific_function %EmptyRange.Make.38a, @EmptyRange.Make(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %Iterate.type: type = facet_type <@Iterate> [concrete]\n// CHECK:STDOUT:   %Optional.Get.type.1ac: type = fn_type @Optional.Get, @Optional(%T.56c) [symbolic]\n// CHECK:STDOUT:   %Optional.Get.748: %Optional.Get.type.1ac = struct_value () [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.type.051: type = fn_type @Optional.HasValue, @Optional(%T.56c) [symbolic]\n// CHECK:STDOUT:   %Optional.HasValue.6ae: %Optional.HasValue.type.051 = struct_value () [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.type.b9d: type = fn_type @EmptyRange.as.Iterate.impl.Next, @EmptyRange.as.Iterate.impl(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.682: %EmptyRange.as.Iterate.impl.Next.type.b9d = struct_value () [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.type.16c: type = fn_type @EmptyRange.as.Iterate.impl.NewCursor, @EmptyRange.as.Iterate.impl(%T.56c) [symbolic]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.cbe: %EmptyRange.as.Iterate.impl.NewCursor.type.16c = struct_value () [symbolic]\n// CHECK:STDOUT:   %Iterate.impl_witness.a9d: <witness> = impl_witness imports.%Iterate.impl_witness_table, @EmptyRange.as.Iterate.impl(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.type.a4b: type = fn_type @EmptyRange.as.Iterate.impl.NewCursor, @EmptyRange.as.Iterate.impl(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.94e: %EmptyRange.as.Iterate.impl.NewCursor.type.a4b = struct_value () [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.type.24c: type = fn_type @EmptyRange.as.Iterate.impl.Next, @EmptyRange.as.Iterate.impl(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.77c: %EmptyRange.as.Iterate.impl.Next.type.24c = struct_value () [concrete]\n// CHECK:STDOUT:   %Iterate.facet: %Iterate.type = facet_value %EmptyRange.849, (%Iterate.impl_witness.a9d) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.NewCursor.type.43a: type = fn_type @Iterate.WithSelf.NewCursor, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %Iterate.WithSelf.Next.type.cd1: type = fn_type @Iterate.WithSelf.Next, @Iterate.WithSelf(%Iterate.facet) [concrete]\n// CHECK:STDOUT:   %.722: type = fn_type_with_self_type %Iterate.WithSelf.NewCursor.type.43a, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.specific_fn: <specific function> = specific_function %EmptyRange.as.Iterate.impl.NewCursor.94e, @EmptyRange.as.Iterate.impl.NewCursor(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %.44b: type = fn_type_with_self_type %Iterate.WithSelf.Next.type.cd1, %Iterate.facet [concrete]\n// CHECK:STDOUT:   %Optional.2f4: type = class_type @Optional, @Optional(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.specific_fn: <specific function> = specific_function %EmptyRange.as.Iterate.impl.Next.77c, @EmptyRange.as.Iterate.impl.Next(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.type.6de: type = fn_type @Optional.HasValue, @Optional(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.de9: %Optional.HasValue.type.6de = struct_value () [concrete]\n// CHECK:STDOUT:   %Optional.Get.type.925: type = fn_type @Optional.Get, @Optional(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %Optional.Get.a9e: %Optional.Get.type.925 = struct_value () [concrete]\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %Optional.HasValue.de9, @Optional.HasValue(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Optional.Get.a9e, @Optional.Get(%Copy.facet.ad0) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc10_49.1 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc10_49.2 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc10_49.3 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.4: type = fn_type @Destroy.Op.loc10_48 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.4: %Destroy.Op.type.bae255.4 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.as.Copy.impl.Op.type: type = fn_type @C.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %C.as.Copy.impl.Op: %C.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.EmptyRange: %EmptyRange.type = import_ref Main//empty_range, EmptyRange, loaded [concrete = constants.%EmptyRange.generic]\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//empty_range, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.299: @EmptyRange.%EmptyRange.Make.type (%EmptyRange.Make.type.8d6) = import_ref Main//empty_range, loc5_21, loaded [symbolic = @EmptyRange.%EmptyRange.Make (constants.%EmptyRange.Make.0dc)]\n// CHECK:STDOUT:   %Core.import_ref.445: @tuple.type.as.Copy.impl.da7.%tuple.type.as.Copy.impl.Op.type (%tuple.type.as.Copy.impl.Op.type.57a) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @tuple.type.as.Copy.impl.da7.%tuple.type.as.Copy.impl.Op (constants.%tuple.type.as.Copy.impl.Op.7f4)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.3c8 = impl_witness_table (%Core.import_ref.445), @tuple.type.as.Copy.impl.da7 [concrete]\n// CHECK:STDOUT:   %Main.import_ref.cb5: %C.as.Copy.impl.Op.type = import_ref Main//empty_range, loc19_40, loaded [concrete = constants.%C.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c52 = impl_witness_table (%Main.import_ref.cb5), @C.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.f5d: @Optional.%Optional.HasValue.type (%Optional.HasValue.type.051) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.HasValue (constants.%Optional.HasValue.6ae)]\n// CHECK:STDOUT:   %Core.import_ref.ab7: @Optional.%Optional.Get.type (%Optional.Get.type.1ac) = import_ref Core//prelude/parts/iterate, inst{{[0-9A-F]+}} [indirect], loaded [symbolic = @Optional.%Optional.Get (constants.%Optional.Get.748)]\n// CHECK:STDOUT:   %Main.import_ref.888 = import_ref Main//empty_range, loc7_68, unloaded\n// CHECK:STDOUT:   %Main.import_ref.999 = import_ref Main//empty_range, loc7_68, unloaded\n// CHECK:STDOUT:   %Main.import_ref.868: @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.NewCursor.type (%EmptyRange.as.Iterate.impl.NewCursor.type.16c) = import_ref Main//empty_range, loc8_45, loaded [symbolic = @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.NewCursor (constants.%EmptyRange.as.Iterate.impl.NewCursor.cbe)]\n// CHECK:STDOUT:   %Main.import_ref.574: @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.Next.type (%EmptyRange.as.Iterate.impl.Next.type.b9d) = import_ref Main//empty_range, loc11_72, loaded [symbolic = @EmptyRange.as.Iterate.impl.%EmptyRange.as.Iterate.impl.Next (constants.%EmptyRange.as.Iterate.impl.Next.682)]\n// CHECK:STDOUT:   %Iterate.impl_witness_table = impl_witness_table (%Main.import_ref.888, %Main.import_ref.999, %Main.import_ref.868, %Main.import_ref.574), @EmptyRange.as.Iterate.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7c7 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7c7 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %.loc10_19: %pattern_type.c3b = tuple_pattern (%a.patt, %b.patt) [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %EmptyRange.ref: %EmptyRange.type = name_ref EmptyRange, imports.%Main.EmptyRange [concrete = constants.%EmptyRange.generic]\n// CHECK:STDOUT:   %C.ref.loc10_36: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %C.ref.loc10_39: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc10_40: %tuple.type.24b = tuple_literal (%C.ref.loc10_36, %C.ref.loc10_39) [concrete = constants.%tuple.6f4]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value constants.%tuple.type.d23, (constants.%Copy.impl_witness.9e2) [concrete = constants.%Copy.facet.ad0]\n// CHECK:STDOUT:   %.loc10_41: %Copy.type = converted %.loc10_40, %Copy.facet [concrete = constants.%Copy.facet.ad0]\n// CHECK:STDOUT:   %EmptyRange: type = class_type @EmptyRange, @EmptyRange(constants.%Copy.facet.ad0) [concrete = constants.%EmptyRange.849]\n// CHECK:STDOUT:   %.loc10_42: %EmptyRange.Make.type.7da = specific_constant imports.%Main.import_ref.299, @EmptyRange(constants.%Copy.facet.ad0) [concrete = constants.%EmptyRange.Make.38a]\n// CHECK:STDOUT:   %Make.ref: %EmptyRange.Make.type.7da = name_ref Make, %.loc10_42 [concrete = constants.%EmptyRange.Make.38a]\n// CHECK:STDOUT:   %EmptyRange.Make.specific_fn: <specific function> = specific_function %Make.ref, @EmptyRange.Make(constants.%Copy.facet.ad0) [concrete = constants.%EmptyRange.Make.specific_fn]\n// CHECK:STDOUT:   %.loc10_48.1: ref %EmptyRange.849 = temporary_storage\n// CHECK:STDOUT:   %EmptyRange.Make.call: init %EmptyRange.849 to %.loc10_48.1 = call %EmptyRange.Make.specific_fn()\n// CHECK:STDOUT:   %.loc10_48.2: ref %EmptyRange.849 = temporary %.loc10_48.1, %EmptyRange.Make.call\n// CHECK:STDOUT:   %impl.elem2: %.722 = impl_witness_access constants.%Iterate.impl_witness.a9d, element2 [concrete = constants.%EmptyRange.as.Iterate.impl.NewCursor.94e]\n// CHECK:STDOUT:   %bound_method.loc10_49.1: <bound method> = bound_method %.loc10_48.2, %impl.elem2\n// CHECK:STDOUT:   %specific_fn.loc10_49.1: <specific function> = specific_function %impl.elem2, @EmptyRange.as.Iterate.impl.NewCursor(constants.%Copy.facet.ad0) [concrete = constants.%EmptyRange.as.Iterate.impl.NewCursor.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_49.2: <bound method> = bound_method %.loc10_48.2, %specific_fn.loc10_49.1\n// CHECK:STDOUT:   %.loc10_48.3: %EmptyRange.849 = acquire_value %.loc10_48.2\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.NewCursor.call: init %empty_struct_type = call %bound_method.loc10_49.2(%.loc10_48.3)\n// CHECK:STDOUT:   %var: ref %empty_struct_type = var invalid\n// CHECK:STDOUT:   assign %var, %EmptyRange.as.Iterate.impl.NewCursor.call\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.next:\n// CHECK:STDOUT:   %addr: %ptr.c28 = addr_of %var\n// CHECK:STDOUT:   %impl.elem3: %.44b = impl_witness_access constants.%Iterate.impl_witness.a9d, element3 [concrete = constants.%EmptyRange.as.Iterate.impl.Next.77c]\n// CHECK:STDOUT:   %bound_method.loc10_49.3: <bound method> = bound_method %.loc10_48.2, %impl.elem3\n// CHECK:STDOUT:   %specific_fn.loc10_49.2: <specific function> = specific_function %impl.elem3, @EmptyRange.as.Iterate.impl.Next(constants.%Copy.facet.ad0) [concrete = constants.%EmptyRange.as.Iterate.impl.Next.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_49.4: <bound method> = bound_method %.loc10_48.2, %specific_fn.loc10_49.2\n// CHECK:STDOUT:   %.loc10_49.1: ref %Optional.2f4 = temporary_storage\n// CHECK:STDOUT:   %.loc10_48.4: %EmptyRange.849 = acquire_value %.loc10_48.2\n// CHECK:STDOUT:   %EmptyRange.as.Iterate.impl.Next.call: init %Optional.2f4 to %.loc10_49.1 = call %bound_method.loc10_49.4(%.loc10_48.4, %addr)\n// CHECK:STDOUT:   %.loc10_49.2: ref %Optional.2f4 = temporary %.loc10_49.1, %EmptyRange.as.Iterate.impl.Next.call\n// CHECK:STDOUT:   %.loc10_49.3: %Optional.HasValue.type.6de = specific_constant imports.%Core.import_ref.f5d, @Optional(constants.%Copy.facet.ad0) [concrete = constants.%Optional.HasValue.de9]\n// CHECK:STDOUT:   %HasValue.ref: %Optional.HasValue.type.6de = name_ref HasValue, %.loc10_49.3 [concrete = constants.%Optional.HasValue.de9]\n// CHECK:STDOUT:   %Optional.HasValue.bound: <bound method> = bound_method %.loc10_49.2, %HasValue.ref\n// CHECK:STDOUT:   %Optional.HasValue.specific_fn: <specific function> = specific_function %HasValue.ref, @Optional.HasValue(constants.%Copy.facet.ad0) [concrete = constants.%Optional.HasValue.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_49.5: <bound method> = bound_method %.loc10_49.2, %Optional.HasValue.specific_fn\n// CHECK:STDOUT:   %.loc10_49.4: %Optional.2f4 = acquire_value %.loc10_49.2\n// CHECK:STDOUT:   %Optional.HasValue.call: init bool = call %bound_method.loc10_49.5(%.loc10_49.4)\n// CHECK:STDOUT:   %.loc10_49.5: bool = value_of_initializer %Optional.HasValue.call\n// CHECK:STDOUT:   %.loc10_49.6: bool = converted %Optional.HasValue.call, %.loc10_49.5\n// CHECK:STDOUT:   if %.loc10_49.6 br !for.body else br !for.done\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.body:\n// CHECK:STDOUT:   %.loc10_49.7: %Optional.Get.type.925 = specific_constant imports.%Core.import_ref.ab7, @Optional(constants.%Copy.facet.ad0) [concrete = constants.%Optional.Get.a9e]\n// CHECK:STDOUT:   %Get.ref: %Optional.Get.type.925 = name_ref Get, %.loc10_49.7 [concrete = constants.%Optional.Get.a9e]\n// CHECK:STDOUT:   %Optional.Get.bound: <bound method> = bound_method %.loc10_49.2, %Get.ref\n// CHECK:STDOUT:   %Optional.Get.specific_fn: <specific function> = specific_function %Get.ref, @Optional.Get(constants.%Copy.facet.ad0) [concrete = constants.%Optional.Get.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_49.6: <bound method> = bound_method %.loc10_49.2, %Optional.Get.specific_fn\n// CHECK:STDOUT:   %.loc10_49.8: ref %tuple.type.d23 = temporary_storage\n// CHECK:STDOUT:   %.loc10_49.9: %Optional.2f4 = acquire_value %.loc10_49.2\n// CHECK:STDOUT:   %Optional.Get.call: init %tuple.type.d23 to %.loc10_49.8 = call %bound_method.loc10_49.6(%.loc10_49.9)\n// CHECK:STDOUT:   %.loc10_49.10: ref %tuple.type.d23 = temporary %.loc10_49.8, %Optional.Get.call\n// CHECK:STDOUT:   %tuple.elem0: ref %C = tuple_access %.loc10_49.10, element0\n// CHECK:STDOUT:   %tuple.elem1: ref %C = tuple_access %.loc10_49.10, element1\n// CHECK:STDOUT:   %C.ref.loc10_12: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc10_49.11: %C = acquire_value %tuple.elem0\n// CHECK:STDOUT:   %a: %C = value_binding a, %.loc10_49.11\n// CHECK:STDOUT:   %C.ref.loc10_18: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc10_49.12: %C = acquire_value %tuple.elem1\n// CHECK:STDOUT:   %b: %C = value_binding b, %.loc10_49.12\n// CHECK:STDOUT:   %Body.ref: %Body.type = name_ref Body, file.%Body.decl [concrete = constants.%Body]\n// CHECK:STDOUT:   %a.ref: %C = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %C = name_ref b, %b\n// CHECK:STDOUT:   %Body.call: init %empty_tuple.type = call %Body.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   br !for.next\n// CHECK:STDOUT:\n// CHECK:STDOUT: !for.done:\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_49.1: <bound method> = bound_method %.loc10_49.10, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_49.1: init %empty_tuple.type = call %Destroy.Op.bound.loc10_49.1(%.loc10_49.10)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_49.2: <bound method> = bound_method %.loc10_49.2, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_49.2: init %empty_tuple.type = call %Destroy.Op.bound.loc10_49.2(%.loc10_49.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_49.3: <bound method> = bound_method %var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_49.3: init %empty_tuple.type = call %Destroy.Op.bound.loc10_49.3(%var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc10_48: <bound method> = bound_method %.loc10_48.2, constants.%Destroy.Op.651ba6.4\n// CHECK:STDOUT:   %Destroy.Op.call.loc10_48: init %empty_tuple.type = call %Destroy.Op.bound.loc10_48(%.loc10_48.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_49.1(%self.param: ref %tuple.type.d23) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_49.2(%self.param: ref %Optional.2f4) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_49.3(%self.param: ref %empty_struct_type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc10_48(%self.param: ref %EmptyRange.849) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/builtin/adapted_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/builtin/adapted_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/builtin/adapted_type.carbon\n\n// --- adapt.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn IntLiteral() -> type = \"int_literal.make_type\";\n\nclass MyIntLiteral {\n  adapt IntLiteral();\n}\n\nfn Int(N: MyIntLiteral) -> type = \"int.make_type_signed\";\n\nclass MyInt32 {\n  adapt Int(32 as MyIntLiteral);\n\n  fn Make(a: MyIntLiteral) -> MyInt32;\n}\n\nfn MyInt32.Make(a: MyIntLiteral) -> MyInt32 = \"int.convert_checked\";\n\nfn MyAdd(a: MyInt32, b: MyInt32) -> MyInt32 = \"int.sadd\";\n\nvar v: MyInt32 = MyAdd(MyInt32.Make(1 as MyIntLiteral), MyInt32.Make(2 as MyIntLiteral));\n\n// --- fail_bad_adapt.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass MyIntLiteral {\n  adapt {};\n}\n\n// CHECK:STDERR: fail_bad_adapt.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.make_type_signed\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Int(N: MyIntLiteral) -> type = \"int.make_type_signed\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Int(N: MyIntLiteral) -> type = \"int.make_type_signed\";\n\n// CHECK:STDOUT: --- adapt.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %.805: Core.Form = init_form type [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %MyIntLiteral: type = class_type @MyIntLiteral [concrete]\n// CHECK:STDOUT:   %complete_type.972: <witness> = complete_type_witness Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %pattern_type.d59: type = pattern_type %MyIntLiteral [concrete]\n// CHECK:STDOUT:   %Int.type: type = fn_type @Int [concrete]\n// CHECK:STDOUT:   %Int: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %MyInt32: type = class_type @MyInt32 [concrete]\n// CHECK:STDOUT:   %int_32.be0: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %int_32.2f2: %MyIntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32.2f2 [concrete]\n// CHECK:STDOUT:   %.c88: Core.Form = init_form %MyInt32 [concrete]\n// CHECK:STDOUT:   %pattern_type.4d1: type = pattern_type %MyInt32 [concrete]\n// CHECK:STDOUT:   %MyInt32.Make.type: type = fn_type @MyInt32.Make [concrete]\n// CHECK:STDOUT:   %MyInt32.Make: %MyInt32.Make.type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.833: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %MyAdd.type: type = fn_type @MyAdd [concrete]\n// CHECK:STDOUT:   %MyAdd: %MyAdd.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_1.ed9: %MyIntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_1.6de: %MyInt32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_2.7bb: %MyIntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_2.035: %MyInt32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_3: %MyInt32 = int_value 3 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %IntLiteral.decl\n// CHECK:STDOUT:     .MyIntLiteral = %MyIntLiteral.decl\n// CHECK:STDOUT:     .Int = %Int.decl\n// CHECK:STDOUT:     .MyInt32 = %MyInt32.decl\n// CHECK:STDOUT:     .MyAdd = %MyAdd.decl\n// CHECK:STDOUT:     .v = %v\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %IntLiteral.decl: %IntLiteral.type = fn_decl @IntLiteral [concrete = constants.%IntLiteral] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.98f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.98f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_20.1: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc4_20.2: Core.Form = init_form %.loc4_20.1 [concrete = constants.%.805]\n// CHECK:STDOUT:     %return.param: ref type = out_param call_param0\n// CHECK:STDOUT:     %return: ref type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %MyIntLiteral.decl: type = class_decl @MyIntLiteral [concrete = constants.%MyIntLiteral] {} {}\n// CHECK:STDOUT:   %Int.decl: %Int.type = fn_decl @Int [concrete = constants.%Int] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.d59 = value_binding_pattern N [concrete]\n// CHECK:STDOUT:     %N.param_patt: %pattern_type.d59 = value_param_pattern %N.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.98f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.98f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc10_28.1: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc10_28.2: Core.Form = init_form %.loc10_28.1 [concrete = constants.%.805]\n// CHECK:STDOUT:     %N.param: %MyIntLiteral = value_param call_param0\n// CHECK:STDOUT:     %MyIntLiteral.ref: type = name_ref MyIntLiteral, file.%MyIntLiteral.decl [concrete = constants.%MyIntLiteral]\n// CHECK:STDOUT:     %N: %MyIntLiteral = value_binding N, %N.param\n// CHECK:STDOUT:     %return.param: ref type = out_param call_param1\n// CHECK:STDOUT:     %return: ref type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %MyInt32.decl: type = class_decl @MyInt32 [concrete = constants.%MyInt32] {} {}\n// CHECK:STDOUT:   %MyInt32.Make.decl: %MyInt32.Make.type = fn_decl @MyInt32.Make [concrete = constants.%MyInt32.Make] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.d59 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.d59 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.4d1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.4d1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %MyInt32.ref.loc18: type = name_ref MyInt32, file.%MyInt32.decl [concrete = constants.%MyInt32]\n// CHECK:STDOUT:     %.loc18: Core.Form = init_form %MyInt32.ref.loc18 [concrete = constants.%.c88]\n// CHECK:STDOUT:     %a.param.loc18: %MyIntLiteral = value_param call_param0\n// CHECK:STDOUT:     %MyIntLiteral.ref.loc18: type = name_ref MyIntLiteral, file.%MyIntLiteral.decl [concrete = constants.%MyIntLiteral]\n// CHECK:STDOUT:     %a.loc18: %MyIntLiteral = value_binding a, %a.param.loc18\n// CHECK:STDOUT:     %return.param.loc18: ref %MyInt32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc18: ref %MyInt32 = return_slot %return.param.loc18\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %MyAdd.decl: %MyAdd.type = fn_decl @MyAdd [concrete = constants.%MyAdd] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.4d1 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.4d1 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.4d1 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.4d1 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.4d1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.4d1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %MyInt32.ref.loc20_37: type = name_ref MyInt32, file.%MyInt32.decl [concrete = constants.%MyInt32]\n// CHECK:STDOUT:     %.loc20: Core.Form = init_form %MyInt32.ref.loc20_37 [concrete = constants.%.c88]\n// CHECK:STDOUT:     %a.param: %MyInt32 = value_param call_param0\n// CHECK:STDOUT:     %MyInt32.ref.loc20_13: type = name_ref MyInt32, file.%MyInt32.decl [concrete = constants.%MyInt32]\n// CHECK:STDOUT:     %a: %MyInt32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %MyInt32 = value_param call_param1\n// CHECK:STDOUT:     %MyInt32.ref.loc20_25: type = name_ref MyInt32, file.%MyInt32.decl [concrete = constants.%MyInt32]\n// CHECK:STDOUT:     %b: %MyInt32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %MyInt32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %MyInt32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.4d1 = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.4d1 = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %MyInt32 = var %v.var_patt [concrete]\n// CHECK:STDOUT:   %MyInt32.ref: type = name_ref MyInt32, %MyInt32.decl [concrete = constants.%MyInt32]\n// CHECK:STDOUT:   %v: ref %MyInt32 = ref_binding v, %v.var [concrete = %v.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @MyIntLiteral {\n// CHECK:STDOUT:   %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:   %.loc7_21.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:   %.loc7_21.2: type = converted %IntLiteral.call, %.loc7_21.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:   adapt_decl %.loc7_21.2 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness Core.IntLiteral [concrete = constants.%complete_type.972]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%MyIntLiteral\n// CHECK:STDOUT:   .IntLiteral = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @MyInt32 {\n// CHECK:STDOUT:   %Int.ref: %Int.type = name_ref Int, file.%Int.decl [concrete = constants.%Int]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32.be0]\n// CHECK:STDOUT:   %MyIntLiteral.ref: type = name_ref MyIntLiteral, file.%MyIntLiteral.decl [concrete = constants.%MyIntLiteral]\n// CHECK:STDOUT:   %.loc13_16.1: %MyIntLiteral = as_compatible %int_32 [concrete = constants.%int_32.2f2]\n// CHECK:STDOUT:   %.loc13_16.2: %MyIntLiteral = converted %int_32, %.loc13_16.1 [concrete = constants.%int_32.2f2]\n// CHECK:STDOUT:   %Int.call: init type = call %Int.ref(%.loc13_16.2) [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   %.loc13_32.1: type = value_of_initializer %Int.call [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   %.loc13_32.2: type = converted %Int.call, %.loc13_32.1 [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   adapt_decl %.loc13_32.2 [concrete]\n// CHECK:STDOUT:   %MyInt32.Make.decl: %MyInt32.Make.type = fn_decl @MyInt32.Make [concrete = constants.%MyInt32.Make] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.d59 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.d59 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.4d1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.4d1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %MyInt32.ref.loc15: type = name_ref MyInt32, file.%MyInt32.decl [concrete = constants.%MyInt32]\n// CHECK:STDOUT:     %.loc15: Core.Form = init_form %MyInt32.ref.loc15 [concrete = constants.%.c88]\n// CHECK:STDOUT:     %a.param.loc15: %MyIntLiteral = value_param call_param0\n// CHECK:STDOUT:     %MyIntLiteral.ref.loc15: type = name_ref MyIntLiteral, file.%MyIntLiteral.decl [concrete = constants.%MyIntLiteral]\n// CHECK:STDOUT:     %a.loc15: %MyIntLiteral = value_binding a, %a.param.loc15\n// CHECK:STDOUT:     %return.param.loc15: ref %MyInt32 = out_param call_param1\n// CHECK:STDOUT:     %return.loc15: ref %MyInt32 = return_slot %return.param.loc15\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%i32.builtin [concrete = constants.%complete_type.833]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%MyInt32\n// CHECK:STDOUT:   .Int = <poisoned>\n// CHECK:STDOUT:   .MyIntLiteral = <poisoned>\n// CHECK:STDOUT:   .MyInt32 = <poisoned>\n// CHECK:STDOUT:   .Make = %MyInt32.Make.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @IntLiteral() -> out %return.param: type = \"int_literal.make_type\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Int(%N.param: %MyIntLiteral) -> out %return.param: type = \"int.make_type_signed\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MyInt32.Make(%a.param.loc18: %MyIntLiteral) -> out %return.param.loc18: %MyInt32 = \"int.convert_checked\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MyAdd(%a.param: %MyInt32, %b.param: %MyInt32) -> out %return.param: %MyInt32 = \"int.sadd\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %MyAdd.ref: %MyAdd.type = name_ref MyAdd, file.%MyAdd.decl [concrete = constants.%MyAdd]\n// CHECK:STDOUT:   %MyInt32.ref.loc22_24: type = name_ref MyInt32, file.%MyInt32.decl [concrete = constants.%MyInt32]\n// CHECK:STDOUT:   %Make.ref.loc22_31: %MyInt32.Make.type = name_ref Make, @MyInt32.%MyInt32.Make.decl [concrete = constants.%MyInt32.Make]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %MyIntLiteral.ref.loc22_42: type = name_ref MyIntLiteral, file.%MyIntLiteral.decl [concrete = constants.%MyIntLiteral]\n// CHECK:STDOUT:   %.loc22_39.1: %MyIntLiteral = as_compatible %int_1 [concrete = constants.%int_1.ed9]\n// CHECK:STDOUT:   %.loc22_39.2: %MyIntLiteral = converted %int_1, %.loc22_39.1 [concrete = constants.%int_1.ed9]\n// CHECK:STDOUT:   %MyInt32.Make.call.loc22_54: init %MyInt32 = call %Make.ref.loc22_31(%.loc22_39.2) [concrete = constants.%int_1.6de]\n// CHECK:STDOUT:   %MyInt32.ref.loc22_57: type = name_ref MyInt32, file.%MyInt32.decl [concrete = constants.%MyInt32]\n// CHECK:STDOUT:   %Make.ref.loc22_64: %MyInt32.Make.type = name_ref Make, @MyInt32.%MyInt32.Make.decl [concrete = constants.%MyInt32.Make]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %MyIntLiteral.ref.loc22_75: type = name_ref MyIntLiteral, file.%MyIntLiteral.decl [concrete = constants.%MyIntLiteral]\n// CHECK:STDOUT:   %.loc22_72.1: %MyIntLiteral = as_compatible %int_2 [concrete = constants.%int_2.7bb]\n// CHECK:STDOUT:   %.loc22_72.2: %MyIntLiteral = converted %int_2, %.loc22_72.1 [concrete = constants.%int_2.7bb]\n// CHECK:STDOUT:   %MyInt32.Make.call.loc22_87: init %MyInt32 = call %Make.ref.loc22_64(%.loc22_72.2) [concrete = constants.%int_2.035]\n// CHECK:STDOUT:   %.loc22_54.1: %MyInt32 = value_of_initializer %MyInt32.Make.call.loc22_54 [concrete = constants.%int_1.6de]\n// CHECK:STDOUT:   %.loc22_54.2: %MyInt32 = converted %MyInt32.Make.call.loc22_54, %.loc22_54.1 [concrete = constants.%int_1.6de]\n// CHECK:STDOUT:   %.loc22_87.1: %MyInt32 = value_of_initializer %MyInt32.Make.call.loc22_87 [concrete = constants.%int_2.035]\n// CHECK:STDOUT:   %.loc22_87.2: %MyInt32 = converted %MyInt32.Make.call.loc22_87, %.loc22_87.1 [concrete = constants.%int_2.035]\n// CHECK:STDOUT:   %MyAdd.call: init %MyInt32 = call %MyAdd.ref(%.loc22_54.2, %.loc22_87.2) [concrete = constants.%int_3]\n// CHECK:STDOUT:   assign file.%v.var, %MyAdd.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_bad_adapt.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %MyIntLiteral: type = class_type @MyIntLiteral [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.d59: type = pattern_type %MyIntLiteral [concrete]\n// CHECK:STDOUT:   %.805: Core.Form = init_form type [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %Int.type: type = fn_type @Int [concrete]\n// CHECK:STDOUT:   %Int: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .MyIntLiteral = %MyIntLiteral.decl\n// CHECK:STDOUT:     .Int = %Int.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %MyIntLiteral.decl: type = class_decl @MyIntLiteral [concrete = constants.%MyIntLiteral] {} {}\n// CHECK:STDOUT:   %Int.decl: %Int.type = fn_decl @Int [concrete = constants.%Int] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.d59 = value_binding_pattern N [concrete]\n// CHECK:STDOUT:     %N.param_patt: %pattern_type.d59 = value_param_pattern %N.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.98f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.98f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc12_28.1: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc12_28.2: Core.Form = init_form %.loc12_28.1 [concrete = constants.%.805]\n// CHECK:STDOUT:     %N.param: %MyIntLiteral = value_param call_param0\n// CHECK:STDOUT:     %MyIntLiteral.ref: type = name_ref MyIntLiteral, file.%MyIntLiteral.decl [concrete = constants.%MyIntLiteral]\n// CHECK:STDOUT:     %N: %MyIntLiteral = value_binding N, %N.param\n// CHECK:STDOUT:     %return.param: ref type = out_param call_param1\n// CHECK:STDOUT:     %return: ref type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @MyIntLiteral {\n// CHECK:STDOUT:   %.loc5_10: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc5_11: type = converted %.loc5_10, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   adapt_decl %.loc5_11 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%MyIntLiteral\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Int(%N.param: %MyIntLiteral) -> out %return.param: type;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/builtin/call.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/builtin/call.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/builtin/call.carbon\n\nfn Add(a: i32, b: i32) -> i32 = \"int.sadd\";\n\nvar arr: array(i32, Add(1, 2));\n\nfn RuntimeCall(a: i32, b: i32) -> i32 {\n  return Add(a, b);\n}\n\n// CHECK:STDOUT: --- call.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Add.type: type = fn_type @Add [concrete]\n// CHECK:STDOUT:   %Add: %Add.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %From: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.2ed: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%From) [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.d29: %Int.as.ImplicitAs.impl.Convert.type.2ed = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.b94: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet.b94) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet.b94 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.640: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.ea2, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.240: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.dd4: %Int.as.ImplicitAs.impl.Convert.type.240 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.290: %ImplicitAs.type.139 = facet_value %i32, (%ImplicitAs.impl_witness.640) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.462: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet.290) [concrete]\n// CHECK:STDOUT:   %.0a7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.462, %ImplicitAs.facet.290 [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_3.822, %Int.as.ImplicitAs.impl.Convert.dd4 [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Int.as.ImplicitAs.impl.Convert.dd4, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.17a: <bound method> = bound_method %int_3.822, %Int.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.5d8: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.d11: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%array_type) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.576: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%array_type) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.9c0: %T.as.DefaultOrUnformed.impl.Op.type.576 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %array_type, (%DefaultOrUnformed.impl_witness.d11) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.9c0, @T.as.DefaultOrUnformed.impl.Op(%array_type) [concrete]\n// CHECK:STDOUT:   %RuntimeCall.type: type = fn_type @RuntimeCall [concrete]\n// CHECK:STDOUT:   %RuntimeCall: %RuntimeCall.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.0bc: @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert.type (%Int.as.ImplicitAs.impl.Convert.type.2ed) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert (constants.%Int.as.ImplicitAs.impl.Convert.d29)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.ea2 = impl_witness_table (%Core.import_ref.0bc), @Int.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Add = %Add.decl\n// CHECK:STDOUT:     .arr = %arr\n// CHECK:STDOUT:     .RuntimeCall = %RuntimeCall.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Add.decl: %Add.type = fn_decl @Add [concrete = constants.%Add] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc15_27: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15: Core.Form = init_form %i32.loc15_27 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc15_11: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc15_19: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %arr.patt: %pattern_type.5d8 = ref_binding_pattern arr [concrete]\n// CHECK:STDOUT:     %arr.var_patt: %pattern_type.5d8 = var_pattern %arr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %arr.var: ref %array_type = var %arr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc17_30: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %Add.ref: %Add.type = name_ref Add, %Add.decl [concrete = constants.%Add]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %impl.elem0.loc17_25: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc17_25.1: <bound method> = bound_method %int_1, %impl.elem0.loc17_25 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:     %specific_fn.loc17_25: <specific function> = specific_function %impl.elem0.loc17_25, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc17_25.2: <bound method> = bound_method %int_1, %specific_fn.loc17_25 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc17_25: init %i32 = call %bound_method.loc17_25.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc17_25.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc17_25 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc17_25.2: %i32 = converted %int_1, %.loc17_25.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %impl.elem0.loc17_28: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc17_28.1: <bound method> = bound_method %int_2, %impl.elem0.loc17_28 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:     %specific_fn.loc17_28: <specific function> = specific_function %impl.elem0.loc17_28, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc17_28.2: <bound method> = bound_method %int_2, %specific_fn.loc17_28 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc17_28: init %i32 = call %bound_method.loc17_28.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc17_28.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc17_28 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc17_28.2: %i32 = converted %int_2, %.loc17_28.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %Add.call: init %i32 = call %Add.ref(%.loc17_25.2, %.loc17_28.2) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %impl.elem0.loc17_29: %.0a7 = impl_witness_access constants.%ImplicitAs.impl_witness.640, element0 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.dd4]\n// CHECK:STDOUT:     %bound_method.loc17_29.1: <bound method> = bound_method %Add.call, %impl.elem0.loc17_29 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn.loc17_29: <specific function> = specific_function %impl.elem0.loc17_29, @Int.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Int.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc17_29.2: <bound method> = bound_method %Add.call, %specific_fn.loc17_29 [concrete = constants.%bound_method.17a]\n// CHECK:STDOUT:     %.loc17_29.1: %i32 = value_of_initializer %Add.call [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %.loc17_29.2: %i32 = converted %Add.call, %.loc17_29.1 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %Int.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method.loc17_29.2(%.loc17_29.2) [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc17_29.3: Core.IntLiteral = value_of_initializer %Int.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc17_29.4: Core.IntLiteral = converted %Add.call, %.loc17_29.3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %array_type: type = array_type %.loc17_29.4, %i32 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %arr: ref %array_type = ref_binding arr, %arr.var [concrete = %arr.var]\n// CHECK:STDOUT:   %RuntimeCall.decl: %RuntimeCall.type = fn_decl @RuntimeCall [concrete = constants.%RuntimeCall] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc19_35: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc19: Core.Form = init_form %i32.loc19_35 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc19_19: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc19_27: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Add(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 = \"int.sadd\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @RuntimeCall(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Add.ref: %Add.type = name_ref Add, file.%Add.decl [concrete = constants.%Add]\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %Add.call: init %i32 = call %Add.ref(%a.ref, %b.ref)\n// CHECK:STDOUT:   return %Add.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%array_type, (constants.%DefaultOrUnformed.impl_witness.d11) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc17_31.1: %DefaultOrUnformed.type = converted constants.%array_type, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc17_31.1 [concrete = constants.%array_type]\n// CHECK:STDOUT:   %.loc17_31.2: type = converted %.loc17_31.1, %as_type [concrete = constants.%array_type]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.9c0, @T.as.DefaultOrUnformed.impl.Op(constants.%array_type) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc17_1: ref %array_type = splice_block file.%arr.var [concrete = file.%arr.var] {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %array_type to %.loc17_1 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign file.%arr.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/builtin/call_from_operator.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/builtin/call_from_operator.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/builtin/call_from_operator.carbon\n\n// --- core.carbon\n\npackage Core;\n\nfn IntLiteral() -> type = \"int_literal.make_type\";\nfn Int(N: IntLiteral()) -> type = \"int.make_type_signed\";\n\ninterface AddWith(T:! type) {\n  fn Op[self: Self](other: Self) -> Self;\n}\n\ninterface As(T:! type) {\n  fn Convert[self: Self]() -> T;\n}\n\ninterface ImplicitAs(T:! type) {\n  fn Convert[self: Self]() -> T;\n}\n\nimpl i32 as AddWith(i32) {\n  fn Op[self: Self](other: Self) -> Self = \"int.sadd\";\n}\n\nimpl IntLiteral() as As(i32) {\n  fn Convert[self: Self]() -> i32 = \"int.convert_checked\";\n}\n\nimpl IntLiteral() as ImplicitAs(i32) {\n  fn Convert[self: Self]() -> i32 = \"int.convert_checked\";\n}\n\nimpl i32 as ImplicitAs(IntLiteral()) {\n  fn Convert[self: Self]() -> IntLiteral() = \"int.convert_checked\";\n}\n\n// --- user.carbon\n\nimport Core;\n\nvar arr: array(i32, (1 as i32) + (2 as i32)) = (3, 4, (3 as i32) + (4 as i32));\n\n// CHECK:STDOUT: --- core.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %.805: Core.Form = init_form type [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %Int.type: type = fn_type @Int [concrete]\n// CHECK:STDOUT:   %Int: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %AddWith.type.b56: type = generic_interface_type @AddWith [concrete]\n// CHECK:STDOUT:   %AddWith.generic: %AddWith.type.b56 = struct_value () [concrete]\n// CHECK:STDOUT:   %AddWith.type.26b: type = facet_type <@AddWith, @AddWith(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.a37: %AddWith.type.26b = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.73e: type = symbolic_binding_type Self, 1, %Self.a37 [symbolic]\n// CHECK:STDOUT:   %pattern_type.1f3: type = pattern_type %Self.binding.as_type.73e [symbolic]\n// CHECK:STDOUT:   %.409: Core.Form = init_form %Self.binding.as_type.73e [symbolic]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type.65a: type = fn_type @AddWith.WithSelf.Op, @AddWith.WithSelf(%T, %Self.a37) [symbolic]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.647: %AddWith.WithSelf.Op.type.65a = struct_value () [symbolic]\n// CHECK:STDOUT:   %AddWith.assoc_type.5ad: type = assoc_entity_type @AddWith, @AddWith(%T) [symbolic]\n// CHECK:STDOUT:   %assoc0.90d: %AddWith.assoc_type.5ad = assoc_entity element0, @AddWith.WithSelf.%AddWith.WithSelf.Op.decl [symbolic]\n// CHECK:STDOUT:   %As.type.3c9: type = generic_interface_type @As [concrete]\n// CHECK:STDOUT:   %As.generic: %As.type.3c9 = struct_value () [concrete]\n// CHECK:STDOUT:   %As.type.b54: type = facet_type <@As, @As(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.a8c: %As.type.b54 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.69d: type = symbolic_binding_type Self, 1, %Self.a8c [symbolic]\n// CHECK:STDOUT:   %pattern_type.24e: type = pattern_type %Self.binding.as_type.69d [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.aef: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%T, %Self.a8c) [symbolic]\n// CHECK:STDOUT:   %As.WithSelf.Convert.a95: %As.WithSelf.Convert.type.aef = struct_value () [symbolic]\n// CHECK:STDOUT:   %As.assoc_type.520: type = assoc_entity_type @As, @As(%T) [symbolic]\n// CHECK:STDOUT:   %assoc0.84c: %As.assoc_type.520 = assoc_entity element0, @As.WithSelf.%As.WithSelf.Convert.decl [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.595: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.595 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.9fe: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.7c0: %ImplicitAs.type.9fe = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.984: type = symbolic_binding_type Self, 1, %Self.7c0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.8de: type = pattern_type %Self.binding.as_type.984 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.f6b: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%T, %Self.7c0) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.de0: %ImplicitAs.WithSelf.Convert.type.f6b = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.b04: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%T) [symbolic]\n// CHECK:STDOUT:   %assoc0.361: %ImplicitAs.assoc_type.b04 = assoc_entity element0, @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.decl [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %AddWith.type.aed: type = facet_type <@AddWith, @AddWith(%i32.builtin)> [concrete]\n// CHECK:STDOUT:   %AddWith.impl_witness: <witness> = impl_witness @i32.builtin.as.AddWith.impl.%AddWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.aad: %AddWith.type.aed = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type.479: type = fn_type @AddWith.WithSelf.Op, @AddWith.WithSelf(%i32.builtin, %Self.a37) [symbolic]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.8bc: %AddWith.WithSelf.Op.type.479 = struct_value () [symbolic]\n// CHECK:STDOUT:   %AddWith.assoc_type.97c: type = assoc_entity_type @AddWith, @AddWith(%i32.builtin) [concrete]\n// CHECK:STDOUT:   %assoc0.4d8: %AddWith.assoc_type.97c = assoc_entity element0, @AddWith.WithSelf.%AddWith.WithSelf.Op.decl [concrete]\n// CHECK:STDOUT:   %pattern_type.956: type = pattern_type %i32.builtin [concrete]\n// CHECK:STDOUT:   %.9cb: Core.Form = init_form %i32.builtin [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.AddWith.impl.Op.type: type = fn_type @i32.builtin.as.AddWith.impl.Op [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.AddWith.impl.Op: %i32.builtin.as.AddWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %AddWith.facet: %AddWith.type.aed = facet_value %i32.builtin, (%AddWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type.493: type = fn_type @AddWith.WithSelf.Op, @AddWith.WithSelf(%i32.builtin, %AddWith.facet) [concrete]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.d6a: %AddWith.WithSelf.Op.type.493 = struct_value () [concrete]\n// CHECK:STDOUT:   %As.type.1ed: type = facet_type <@As, @As(%i32.builtin)> [concrete]\n// CHECK:STDOUT:   %As.impl_witness: <witness> = impl_witness @Core.IntLiteral.as.As.impl.%As.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.037: %As.type.1ed = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.a02: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%i32.builtin, %Self.a8c) [symbolic]\n// CHECK:STDOUT:   %As.WithSelf.Convert.98f: %As.WithSelf.Convert.type.a02 = struct_value () [symbolic]\n// CHECK:STDOUT:   %As.assoc_type.c44: type = assoc_entity_type @As, @As(%i32.builtin) [concrete]\n// CHECK:STDOUT:   %assoc0.43d: %As.assoc_type.c44 = assoc_entity element0, @As.WithSelf.%As.WithSelf.Convert.decl [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.type: type = fn_type @Core.IntLiteral.as.As.impl.Convert [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert: %Core.IntLiteral.as.As.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %As.facet: %As.type.1ed = facet_value Core.IntLiteral, (%As.impl_witness) [concrete]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.204: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%i32.builtin, %As.facet) [concrete]\n// CHECK:STDOUT:   %As.WithSelf.Convert.24c: %As.WithSelf.Convert.type.204 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.92b: type = facet_type <@ImplicitAs, @ImplicitAs(%i32.builtin)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.ccd: <witness> = impl_witness @Core.IntLiteral.as.ImplicitAs.impl.%ImplicitAs.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.597: %ImplicitAs.type.92b = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.d4c: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32.builtin, %Self.7c0) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.086: %ImplicitAs.WithSelf.Convert.type.d4c = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.c3f: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%i32.builtin) [concrete]\n// CHECK:STDOUT:   %assoc0.124: %ImplicitAs.assoc_type.c3f = assoc_entity element0, @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.decl [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.b36: %ImplicitAs.type.92b = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.ccd) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.07c: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32.builtin, %ImplicitAs.facet.b36) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.a38: %ImplicitAs.WithSelf.Convert.type.07c = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.79c: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.985: <witness> = impl_witness @i32.builtin.as.ImplicitAs.impl.%ImplicitAs.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.55f: %ImplicitAs.type.79c = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.25a: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %Self.7c0) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.1ae: %ImplicitAs.WithSelf.Convert.type.25a = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.793: type = assoc_entity_type @ImplicitAs, @ImplicitAs(Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %assoc0.e18: %ImplicitAs.assoc_type.793 = assoc_entity element0, @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.decl [concrete]\n// CHECK:STDOUT:   %.f7d: Core.Form = init_form Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.ImplicitAs.impl.Convert.type: type = fn_type @i32.builtin.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.ImplicitAs.impl.Convert: %i32.builtin.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.c5c: %ImplicitAs.type.79c = facet_value %i32.builtin, (%ImplicitAs.impl_witness.985) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.7aa: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet.c5c) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.090: %ImplicitAs.WithSelf.Convert.type.7aa = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %IntLiteral.decl\n// CHECK:STDOUT:     .Int = %Int.decl\n// CHECK:STDOUT:     .AddWith = %AddWith.decl\n// CHECK:STDOUT:     .As = %As.decl\n// CHECK:STDOUT:     .ImplicitAs = %ImplicitAs.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %IntLiteral.decl: %IntLiteral.type = fn_decl @IntLiteral [concrete = constants.%IntLiteral] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.98f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.98f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_20.1: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc4_20.2: Core.Form = init_form %.loc4_20.1 [concrete = constants.%.805]\n// CHECK:STDOUT:     %return.param: ref type = out_param call_param0\n// CHECK:STDOUT:     %return: ref type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Int.decl: %Int.type = fn_decl @Int [concrete = constants.%Int] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = value_binding_pattern N [concrete]\n// CHECK:STDOUT:     %N.param_patt: %pattern_type.dc0 = value_param_pattern %N.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.98f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.98f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_28.1: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc5_28.2: Core.Form = init_form %.loc5_28.1 [concrete = constants.%.805]\n// CHECK:STDOUT:     %N.param: Core.IntLiteral = value_param call_param0\n// CHECK:STDOUT:     %.loc5_22.1: type = splice_block %.loc5_22.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc5_22.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc5_22.3: type = converted %IntLiteral.call, %.loc5_22.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N: Core.IntLiteral = value_binding N, %N.param\n// CHECK:STDOUT:     %return.param: ref type = out_param call_param1\n// CHECK:STDOUT:     %return: ref type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %AddWith.decl: %AddWith.type.b56 = interface_decl @AddWith [concrete = constants.%AddWith.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_23.1: type = splice_block %.loc7_23.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_23.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_19.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_19.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %As.decl: %As.type.3c9 = interface_decl @As [concrete = constants.%As.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc11_18.1: type = splice_block %.loc11_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc11_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc11_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc11_14.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.decl: %ImplicitAs.type.595 = interface_decl @ImplicitAs [concrete = constants.%ImplicitAs.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_26.1: type = splice_block %.loc15_26.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_26.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_22.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @i32.builtin.as.AddWith.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc19_6: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %AddWith.ref: %AddWith.type.b56 = name_ref AddWith, file.%AddWith.decl [concrete = constants.%AddWith.generic]\n// CHECK:STDOUT:     %.loc19_21: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %AddWith.type: type = facet_type <@AddWith, @AddWith(constants.%i32.builtin)> [concrete = constants.%AddWith.type.aed]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @Core.IntLiteral.as.As.impl [concrete] {} {\n// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:     %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc23_17.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc23_17.2: type = converted %IntLiteral.call, %.loc23_17.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %As.ref: %As.type.3c9 = name_ref As, file.%As.decl [concrete = constants.%As.generic]\n// CHECK:STDOUT:     %.loc23_25: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %As.type: type = facet_type <@As, @As(constants.%i32.builtin)> [concrete = constants.%As.type.1ed]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @Core.IntLiteral.as.ImplicitAs.impl [concrete] {} {\n// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:     %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc27_17.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc27_17.2: type = converted %IntLiteral.call, %.loc27_17.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %ImplicitAs.ref: %ImplicitAs.type.595 = name_ref ImplicitAs, file.%ImplicitAs.decl [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:     %.loc27_33: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%i32.builtin)> [concrete = constants.%ImplicitAs.type.92b]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @i32.builtin.as.ImplicitAs.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc31_6: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %ImplicitAs.ref: %ImplicitAs.type.595 = name_ref ImplicitAs, file.%ImplicitAs.decl [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:     %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc31_36.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc31_36.2: type = converted %IntLiteral.call, %.loc31_36.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete = constants.%ImplicitAs.type.79c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @AddWith(%T.loc7_19.2: type) {\n// CHECK:STDOUT:   %T.loc7_19.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_19.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %AddWith.type: type = facet_type <@AddWith, @AddWith(%T.loc7_19.1)> [symbolic = %AddWith.type (constants.%AddWith.type.26b)]\n// CHECK:STDOUT:   %Self.loc7_29.2: @AddWith.%AddWith.type (%AddWith.type.26b) = symbolic_binding Self, 1 [symbolic = %Self.loc7_29.2 (constants.%Self.a37)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc7_29.1: @AddWith.%AddWith.type (%AddWith.type.26b) = symbolic_binding Self, 1 [symbolic = %Self.loc7_29.2 (constants.%Self.a37)]\n// CHECK:STDOUT:     %AddWith.WithSelf.decl = interface_with_self_decl @AddWith [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %AddWith.WithSelf.Op.decl: @AddWith.WithSelf.%AddWith.WithSelf.Op.type (%AddWith.WithSelf.Op.type.65a) = fn_decl @AddWith.WithSelf.Op [symbolic = @AddWith.WithSelf.%AddWith.WithSelf.Op (constants.%AddWith.WithSelf.Op.647)] {\n// CHECK:STDOUT:       %self.patt: @AddWith.WithSelf.Op.%pattern_type (%pattern_type.1f3) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @AddWith.WithSelf.Op.%pattern_type (%pattern_type.1f3) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %other.patt: @AddWith.WithSelf.Op.%pattern_type (%pattern_type.1f3) = value_binding_pattern other [concrete]\n// CHECK:STDOUT:       %other.param_patt: @AddWith.WithSelf.Op.%pattern_type (%pattern_type.1f3) = value_param_pattern %other.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @AddWith.WithSelf.Op.%pattern_type (%pattern_type.1f3) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @AddWith.WithSelf.Op.%pattern_type (%pattern_type.1f3) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc8_37.2: @AddWith.WithSelf.Op.%AddWith.type (%AddWith.type.26b) = specific_constant @AddWith.%Self.loc7_29.1, @AddWith(constants.%T) [symbolic = %Self (constants.%Self.a37)]\n// CHECK:STDOUT:       %Self.ref.loc8_37: @AddWith.WithSelf.Op.%AddWith.type (%AddWith.type.26b) = name_ref Self, %.loc8_37.2 [symbolic = %Self (constants.%Self.a37)]\n// CHECK:STDOUT:       %Self.as_type.loc8_37: type = facet_access_type %Self.ref.loc8_37 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.73e)]\n// CHECK:STDOUT:       %.loc8_37.3: type = converted %Self.ref.loc8_37, %Self.as_type.loc8_37 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.73e)]\n// CHECK:STDOUT:       %.loc8_37.4: Core.Form = init_form %.loc8_37.3 [symbolic = %.loc8_37.1 (constants.%.409)]\n// CHECK:STDOUT:       %self.param: @AddWith.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type.73e) = value_param call_param0\n// CHECK:STDOUT:       %.loc8_15.1: type = splice_block %.loc8_15.3 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.73e)] {\n// CHECK:STDOUT:         %.loc8_15.2: @AddWith.WithSelf.Op.%AddWith.type (%AddWith.type.26b) = specific_constant @AddWith.%Self.loc7_29.1, @AddWith(constants.%T) [symbolic = %Self (constants.%Self.a37)]\n// CHECK:STDOUT:         %Self.ref.loc8_15: @AddWith.WithSelf.Op.%AddWith.type (%AddWith.type.26b) = name_ref Self, %.loc8_15.2 [symbolic = %Self (constants.%Self.a37)]\n// CHECK:STDOUT:         %Self.as_type.loc8_15: type = facet_access_type %Self.ref.loc8_15 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.73e)]\n// CHECK:STDOUT:         %.loc8_15.3: type = converted %Self.ref.loc8_15, %Self.as_type.loc8_15 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.73e)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @AddWith.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type.73e) = value_binding self, %self.param\n// CHECK:STDOUT:       %other.param: @AddWith.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type.73e) = value_param call_param1\n// CHECK:STDOUT:       %.loc8_28.1: type = splice_block %.loc8_28.3 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.73e)] {\n// CHECK:STDOUT:         %.loc8_28.2: @AddWith.WithSelf.Op.%AddWith.type (%AddWith.type.26b) = specific_constant @AddWith.%Self.loc7_29.1, @AddWith(constants.%T) [symbolic = %Self (constants.%Self.a37)]\n// CHECK:STDOUT:         %Self.ref.loc8_28: @AddWith.WithSelf.Op.%AddWith.type (%AddWith.type.26b) = name_ref Self, %.loc8_28.2 [symbolic = %Self (constants.%Self.a37)]\n// CHECK:STDOUT:         %Self.as_type.loc8_28: type = facet_access_type %Self.ref.loc8_28 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.73e)]\n// CHECK:STDOUT:         %.loc8_28.3: type = converted %Self.ref.loc8_28, %Self.as_type.loc8_28 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.73e)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %other: @AddWith.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type.73e) = value_binding other, %other.param\n// CHECK:STDOUT:       %return.param: ref @AddWith.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type.73e) = out_param call_param2\n// CHECK:STDOUT:       %return: ref @AddWith.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type.73e) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %assoc0.loc8_41.1: @AddWith.WithSelf.%AddWith.assoc_type (%AddWith.assoc_type.5ad) = assoc_entity element0, %AddWith.WithSelf.Op.decl [symbolic = %assoc0.loc8_41.2 (constants.%assoc0.90d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc7_29.1\n// CHECK:STDOUT:     .Op = @AddWith.WithSelf.%assoc0.loc8_41.1\n// CHECK:STDOUT:     witness = (@AddWith.WithSelf.%AddWith.WithSelf.Op.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @As(%T.loc11_14.2: type) {\n// CHECK:STDOUT:   %T.loc11_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc11_14.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %As.type: type = facet_type <@As, @As(%T.loc11_14.1)> [symbolic = %As.type (constants.%As.type.b54)]\n// CHECK:STDOUT:   %Self.loc11_24.2: @As.%As.type (%As.type.b54) = symbolic_binding Self, 1 [symbolic = %Self.loc11_24.2 (constants.%Self.a8c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc11_24.1: @As.%As.type (%As.type.b54) = symbolic_binding Self, 1 [symbolic = %Self.loc11_24.2 (constants.%Self.a8c)]\n// CHECK:STDOUT:     %As.WithSelf.decl = interface_with_self_decl @As [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %As.WithSelf.Convert.decl: @As.WithSelf.%As.WithSelf.Convert.type (%As.WithSelf.Convert.type.aef) = fn_decl @As.WithSelf.Convert [symbolic = @As.WithSelf.%As.WithSelf.Convert (constants.%As.WithSelf.Convert.a95)] {\n// CHECK:STDOUT:       %self.patt: @As.WithSelf.Convert.%pattern_type.loc12_14 (%pattern_type.24e) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @As.WithSelf.Convert.%pattern_type.loc12_14 (%pattern_type.24e) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @As.WithSelf.Convert.%pattern_type.loc12_28 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @As.WithSelf.Convert.%pattern_type.loc12_28 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @As.%T.loc11_14.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %.loc12_31.2: Core.Form = init_form %T.ref [symbolic = %.loc12_31.1 (constants.%.184)]\n// CHECK:STDOUT:       %self.param: @As.WithSelf.Convert.%Self.binding.as_type (%Self.binding.as_type.69d) = value_param call_param0\n// CHECK:STDOUT:       %.loc12_20.1: type = splice_block %.loc12_20.3 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.69d)] {\n// CHECK:STDOUT:         %.loc12_20.2: @As.WithSelf.Convert.%As.type (%As.type.b54) = specific_constant @As.%Self.loc11_24.1, @As(constants.%T) [symbolic = %Self (constants.%Self.a8c)]\n// CHECK:STDOUT:         %Self.ref: @As.WithSelf.Convert.%As.type (%As.type.b54) = name_ref Self, %.loc12_20.2 [symbolic = %Self (constants.%Self.a8c)]\n// CHECK:STDOUT:         %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.69d)]\n// CHECK:STDOUT:         %.loc12_20.3: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.69d)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @As.WithSelf.Convert.%Self.binding.as_type (%Self.binding.as_type.69d) = value_binding self, %self.param\n// CHECK:STDOUT:       %return.param: ref @As.WithSelf.Convert.%T (%T) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @As.WithSelf.Convert.%T (%T) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %assoc0.loc12_32.1: @As.WithSelf.%As.assoc_type (%As.assoc_type.520) = assoc_entity element0, %As.WithSelf.Convert.decl [symbolic = %assoc0.loc12_32.2 (constants.%assoc0.84c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc11_24.1\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .Convert = @As.WithSelf.%assoc0.loc12_32.1\n// CHECK:STDOUT:     witness = (@As.WithSelf.%As.WithSelf.Convert.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @ImplicitAs(%T.loc15_22.2: type) {\n// CHECK:STDOUT:   %T.loc15_22.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_22.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T.loc15_22.1)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.9fe)]\n// CHECK:STDOUT:   %Self.loc15_32.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.9fe) = symbolic_binding Self, 1 [symbolic = %Self.loc15_32.2 (constants.%Self.7c0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc15_32.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.9fe) = symbolic_binding Self, 1 [symbolic = %Self.loc15_32.2 (constants.%Self.7c0)]\n// CHECK:STDOUT:     %ImplicitAs.WithSelf.decl = interface_with_self_decl @ImplicitAs [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %ImplicitAs.WithSelf.Convert.decl: @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.type (%ImplicitAs.WithSelf.Convert.type.f6b) = fn_decl @ImplicitAs.WithSelf.Convert [symbolic = @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert (constants.%ImplicitAs.WithSelf.Convert.de0)] {\n// CHECK:STDOUT:       %self.patt: @ImplicitAs.WithSelf.Convert.%pattern_type.loc16_14 (%pattern_type.8de) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @ImplicitAs.WithSelf.Convert.%pattern_type.loc16_14 (%pattern_type.8de) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @ImplicitAs.WithSelf.Convert.%pattern_type.loc16_28 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @ImplicitAs.WithSelf.Convert.%pattern_type.loc16_28 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @ImplicitAs.%T.loc15_22.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %.loc16_31.2: Core.Form = init_form %T.ref [symbolic = %.loc16_31.1 (constants.%.184)]\n// CHECK:STDOUT:       %self.param: @ImplicitAs.WithSelf.Convert.%Self.binding.as_type (%Self.binding.as_type.984) = value_param call_param0\n// CHECK:STDOUT:       %.loc16_20.1: type = splice_block %.loc16_20.3 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.984)] {\n// CHECK:STDOUT:         %.loc16_20.2: @ImplicitAs.WithSelf.Convert.%ImplicitAs.type (%ImplicitAs.type.9fe) = specific_constant @ImplicitAs.%Self.loc15_32.1, @ImplicitAs(constants.%T) [symbolic = %Self (constants.%Self.7c0)]\n// CHECK:STDOUT:         %Self.ref: @ImplicitAs.WithSelf.Convert.%ImplicitAs.type (%ImplicitAs.type.9fe) = name_ref Self, %.loc16_20.2 [symbolic = %Self (constants.%Self.7c0)]\n// CHECK:STDOUT:         %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.984)]\n// CHECK:STDOUT:         %.loc16_20.3: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.984)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @ImplicitAs.WithSelf.Convert.%Self.binding.as_type (%Self.binding.as_type.984) = value_binding self, %self.param\n// CHECK:STDOUT:       %return.param: ref @ImplicitAs.WithSelf.Convert.%T (%T) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @ImplicitAs.WithSelf.Convert.%T (%T) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %assoc0.loc16_32.1: @ImplicitAs.WithSelf.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.b04) = assoc_entity element0, %ImplicitAs.WithSelf.Convert.decl [symbolic = %assoc0.loc16_32.2 (constants.%assoc0.361)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc15_32.1\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .Convert = @ImplicitAs.WithSelf.%assoc0.loc16_32.1\n// CHECK:STDOUT:     witness = (@ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.builtin.as.AddWith.impl: %.loc19_6 as %AddWith.type {\n// CHECK:STDOUT:   %i32.builtin.as.AddWith.impl.Op.decl: %i32.builtin.as.AddWith.impl.Op.type = fn_decl @i32.builtin.as.AddWith.impl.Op [concrete = constants.%i32.builtin.as.AddWith.impl.Op] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.956 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.956 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %other.patt: %pattern_type.956 = value_binding_pattern other [concrete]\n// CHECK:STDOUT:     %other.param_patt: %pattern_type.956 = value_param_pattern %other.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.956 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.956 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Self.ref.loc20_37: type = name_ref Self, @i32.builtin.as.AddWith.impl.%.loc19_6 [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %.loc20: Core.Form = init_form %Self.ref.loc20_37 [concrete = constants.%.9cb]\n// CHECK:STDOUT:     %self.param: %i32.builtin = value_param call_param0\n// CHECK:STDOUT:     %Self.ref.loc20_15: type = name_ref Self, @i32.builtin.as.AddWith.impl.%.loc19_6 [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %self: %i32.builtin = value_binding self, %self.param\n// CHECK:STDOUT:     %other.param: %i32.builtin = value_param call_param1\n// CHECK:STDOUT:     %Self.ref.loc20_28: type = name_ref Self, @i32.builtin.as.AddWith.impl.%.loc19_6 [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %other: %i32.builtin = value_binding other, %other.param\n// CHECK:STDOUT:     %return.param: ref %i32.builtin = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32.builtin = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %AddWith.impl_witness_table = impl_witness_table (%i32.builtin.as.AddWith.impl.Op.decl), @i32.builtin.as.AddWith.impl [concrete]\n// CHECK:STDOUT:   %AddWith.impl_witness: <witness> = impl_witness %AddWith.impl_witness_table [concrete = constants.%AddWith.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Op = %i32.builtin.as.AddWith.impl.Op.decl\n// CHECK:STDOUT:   witness = %AddWith.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Core.IntLiteral.as.As.impl: %.loc23_17.2 as %As.type {\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.decl: %Core.IntLiteral.as.As.impl.Convert.type = fn_decl @Core.IntLiteral.as.As.impl.Convert [concrete = constants.%Core.IntLiteral.as.As.impl.Convert] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.dc0 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.dc0 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.956 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.956 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc24_31.1: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %.loc24_31.2: Core.Form = init_form %.loc24_31.1 [concrete = constants.%.9cb]\n// CHECK:STDOUT:     %self.param: Core.IntLiteral = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @Core.IntLiteral.as.As.impl.%.loc23_17.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %self: Core.IntLiteral = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32.builtin = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32.builtin = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %As.impl_witness_table = impl_witness_table (%Core.IntLiteral.as.As.impl.Convert.decl), @Core.IntLiteral.as.As.impl [concrete]\n// CHECK:STDOUT:   %As.impl_witness: <witness> = impl_witness %As.impl_witness_table [concrete = constants.%As.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Convert = %Core.IntLiteral.as.As.impl.Convert.decl\n// CHECK:STDOUT:   witness = %As.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Core.IntLiteral.as.ImplicitAs.impl: %.loc27_17.2 as %ImplicitAs.type {\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.decl: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type = fn_decl @Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.dc0 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.dc0 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.956 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.956 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc28_31.1: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %.loc28_31.2: Core.Form = init_form %.loc28_31.1 [concrete = constants.%.9cb]\n// CHECK:STDOUT:     %self.param: Core.IntLiteral = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @Core.IntLiteral.as.ImplicitAs.impl.%.loc27_17.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %self: Core.IntLiteral = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32.builtin = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32.builtin = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%Core.IntLiteral.as.ImplicitAs.impl.Convert.decl), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness %ImplicitAs.impl_witness_table [concrete = constants.%ImplicitAs.impl_witness.ccd]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Convert = %Core.IntLiteral.as.ImplicitAs.impl.Convert.decl\n// CHECK:STDOUT:   witness = %ImplicitAs.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.builtin.as.ImplicitAs.impl: %.loc31_6 as %ImplicitAs.type {\n// CHECK:STDOUT:   %i32.builtin.as.ImplicitAs.impl.Convert.decl: %i32.builtin.as.ImplicitAs.impl.Convert.type = fn_decl @i32.builtin.as.ImplicitAs.impl.Convert [concrete = constants.%i32.builtin.as.ImplicitAs.impl.Convert] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.956 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.956 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.dc0 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.dc0 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:     %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc32_42.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc32_42.2: type = converted %IntLiteral.call, %.loc32_42.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc32_42.3: Core.Form = init_form %.loc32_42.2 [concrete = constants.%.f7d]\n// CHECK:STDOUT:     %self.param: %i32.builtin = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @i32.builtin.as.ImplicitAs.impl.%.loc31_6 [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %self: %i32.builtin = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param call_param1\n// CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%i32.builtin.as.ImplicitAs.impl.Convert.decl), @i32.builtin.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness %ImplicitAs.impl_witness_table [concrete = constants.%ImplicitAs.impl_witness.985]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .IntLiteral = <poisoned>\n// CHECK:STDOUT:   .Convert = %i32.builtin.as.ImplicitAs.impl.Convert.decl\n// CHECK:STDOUT:   witness = %ImplicitAs.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @IntLiteral() -> out %return.param: type = \"int_literal.make_type\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Int(%N.param: Core.IntLiteral) -> out %return.param: type = \"int.make_type_signed\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @AddWith.WithSelf.Op(@AddWith.%T.loc7_19.2: type, @AddWith.%Self.loc7_29.1: @AddWith.%AddWith.type (%AddWith.type.26b)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %AddWith.type: type = facet_type <@AddWith, @AddWith(%T)> [symbolic = %AddWith.type (constants.%AddWith.type.26b)]\n// CHECK:STDOUT:   %Self: @AddWith.WithSelf.Op.%AddWith.type (%AddWith.type.26b) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.a37)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.73e)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.1f3)]\n// CHECK:STDOUT:   %.loc8_37.1: Core.Form = init_form %Self.binding.as_type [symbolic = %.loc8_37.1 (constants.%.409)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @AddWith.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type.73e), %other.param: @AddWith.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type.73e)) -> out %return.param: @AddWith.WithSelf.Op.%Self.binding.as_type (%Self.binding.as_type.73e);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @As.WithSelf.Convert(@As.%T.loc11_14.2: type, @As.%Self.loc11_24.1: @As.%As.type (%As.type.b54)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %As.type: type = facet_type <@As, @As(%T)> [symbolic = %As.type (constants.%As.type.b54)]\n// CHECK:STDOUT:   %Self: @As.WithSelf.Convert.%As.type (%As.type.b54) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.a8c)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.69d)]\n// CHECK:STDOUT:   %pattern_type.loc12_14: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type.loc12_14 (constants.%pattern_type.24e)]\n// CHECK:STDOUT:   %.loc12_31.1: Core.Form = init_form %T [symbolic = %.loc12_31.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc12_28: type = pattern_type %T [symbolic = %pattern_type.loc12_28 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @As.WithSelf.Convert.%Self.binding.as_type (%Self.binding.as_type.69d)) -> out %return.param: @As.WithSelf.Convert.%T (%T);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ImplicitAs.WithSelf.Convert(@ImplicitAs.%T.loc15_22.2: type, @ImplicitAs.%Self.loc15_32.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.9fe)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.9fe)]\n// CHECK:STDOUT:   %Self: @ImplicitAs.WithSelf.Convert.%ImplicitAs.type (%ImplicitAs.type.9fe) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.7c0)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.984)]\n// CHECK:STDOUT:   %pattern_type.loc16_14: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type.loc16_14 (constants.%pattern_type.8de)]\n// CHECK:STDOUT:   %.loc16_31.1: Core.Form = init_form %T [symbolic = %.loc16_31.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc16_28: type = pattern_type %T [symbolic = %pattern_type.loc16_28 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @ImplicitAs.WithSelf.Convert.%Self.binding.as_type (%Self.binding.as_type.984)) -> out %return.param: @ImplicitAs.WithSelf.Convert.%T (%T);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @i32.builtin.as.AddWith.impl.Op(%self.param: %i32.builtin, %other.param: %i32.builtin) -> out %return.param: %i32.builtin = \"int.sadd\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Core.IntLiteral.as.As.impl.Convert(%self.param: Core.IntLiteral) -> out %return.param: %i32.builtin = \"int.convert_checked\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Core.IntLiteral.as.ImplicitAs.impl.Convert(%self.param: Core.IntLiteral) -> out %return.param: %i32.builtin = \"int.convert_checked\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @i32.builtin.as.ImplicitAs.impl.Convert(%self.param: %i32.builtin) -> out %return.param: Core.IntLiteral = \"int.convert_checked\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_19.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith.WithSelf(constants.%T, constants.%Self.a37) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith.WithSelf.Op(constants.%T, constants.%Self.a37) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %AddWith.type => constants.%AddWith.type.26b\n// CHECK:STDOUT:   %Self => constants.%Self.a37\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.73e\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.1f3\n// CHECK:STDOUT:   %.loc8_37.1 => constants.%.409\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As(constants.%T) {\n// CHECK:STDOUT:   %T.loc11_14.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As.WithSelf(constants.%T, constants.%Self.a8c) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As.WithSelf.Convert(constants.%T, constants.%Self.a8c) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %As.type => constants.%As.type.b54\n// CHECK:STDOUT:   %Self => constants.%Self.a8c\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.69d\n// CHECK:STDOUT:   %pattern_type.loc12_14 => constants.%pattern_type.24e\n// CHECK:STDOUT:   %.loc12_31.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc12_28 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_22.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%T, constants.%Self.7c0) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf.Convert(constants.%T, constants.%Self.7c0) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.9fe\n// CHECK:STDOUT:   %Self => constants.%Self.7c0\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.984\n// CHECK:STDOUT:   %pattern_type.loc16_14 => constants.%pattern_type.8de\n// CHECK:STDOUT:   %.loc16_31.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc16_28 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith(constants.%i32.builtin) {\n// CHECK:STDOUT:   %T.loc7_19.1 => constants.%i32.builtin\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %AddWith.type => constants.%AddWith.type.aed\n// CHECK:STDOUT:   %Self.loc7_29.2 => constants.%Self.aad\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith.WithSelf(constants.%i32.builtin, constants.%Self.a37) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %AddWith.type => constants.%AddWith.type.aed\n// CHECK:STDOUT:   %Self => constants.%Self.a37\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type => constants.%AddWith.WithSelf.Op.type.479\n// CHECK:STDOUT:   %AddWith.WithSelf.Op => constants.%AddWith.WithSelf.Op.8bc\n// CHECK:STDOUT:   %AddWith.assoc_type => constants.%AddWith.assoc_type.97c\n// CHECK:STDOUT:   %assoc0.loc8_41.2 => constants.%assoc0.4d8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith.WithSelf(constants.%i32.builtin, constants.%AddWith.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %AddWith.type => constants.%AddWith.type.aed\n// CHECK:STDOUT:   %Self => constants.%AddWith.facet\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type => constants.%AddWith.WithSelf.Op.type.493\n// CHECK:STDOUT:   %AddWith.WithSelf.Op => constants.%AddWith.WithSelf.Op.d6a\n// CHECK:STDOUT:   %AddWith.assoc_type => constants.%AddWith.assoc_type.97c\n// CHECK:STDOUT:   %assoc0.loc8_41.2 => constants.%assoc0.4d8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith.WithSelf.Op(constants.%i32.builtin, constants.%AddWith.facet) {\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %AddWith.type => constants.%AddWith.type.aed\n// CHECK:STDOUT:   %Self => constants.%AddWith.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%i32.builtin\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.956\n// CHECK:STDOUT:   %.loc8_37.1 => constants.%.9cb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As(constants.%i32.builtin) {\n// CHECK:STDOUT:   %T.loc11_14.1 => constants.%i32.builtin\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %As.type => constants.%As.type.1ed\n// CHECK:STDOUT:   %Self.loc11_24.2 => constants.%Self.037\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As.WithSelf(constants.%i32.builtin, constants.%Self.a8c) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %As.type => constants.%As.type.1ed\n// CHECK:STDOUT:   %Self => constants.%Self.a8c\n// CHECK:STDOUT:   %As.WithSelf.Convert.type => constants.%As.WithSelf.Convert.type.a02\n// CHECK:STDOUT:   %As.WithSelf.Convert => constants.%As.WithSelf.Convert.98f\n// CHECK:STDOUT:   %As.assoc_type => constants.%As.assoc_type.c44\n// CHECK:STDOUT:   %assoc0.loc12_32.2 => constants.%assoc0.43d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As.WithSelf(constants.%i32.builtin, constants.%As.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %As.type => constants.%As.type.1ed\n// CHECK:STDOUT:   %Self => constants.%As.facet\n// CHECK:STDOUT:   %As.WithSelf.Convert.type => constants.%As.WithSelf.Convert.type.204\n// CHECK:STDOUT:   %As.WithSelf.Convert => constants.%As.WithSelf.Convert.24c\n// CHECK:STDOUT:   %As.assoc_type => constants.%As.assoc_type.c44\n// CHECK:STDOUT:   %assoc0.loc12_32.2 => constants.%assoc0.43d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As.WithSelf.Convert(constants.%i32.builtin, constants.%As.facet) {\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %As.type => constants.%As.type.1ed\n// CHECK:STDOUT:   %Self => constants.%As.facet\n// CHECK:STDOUT:   %Self.binding.as_type => Core.IntLiteral\n// CHECK:STDOUT:   %pattern_type.loc12_14 => constants.%pattern_type.dc0\n// CHECK:STDOUT:   %.loc12_31.1 => constants.%.9cb\n// CHECK:STDOUT:   %pattern_type.loc12_28 => constants.%pattern_type.956\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(constants.%i32.builtin) {\n// CHECK:STDOUT:   %T.loc15_22.1 => constants.%i32.builtin\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.92b\n// CHECK:STDOUT:   %Self.loc15_32.2 => constants.%Self.597\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%i32.builtin, constants.%Self.7c0) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.92b\n// CHECK:STDOUT:   %Self => constants.%Self.7c0\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.d4c\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.086\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.c3f\n// CHECK:STDOUT:   %assoc0.loc16_32.2 => constants.%assoc0.124\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%i32.builtin, constants.%ImplicitAs.facet.b36) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.92b\n// CHECK:STDOUT:   %Self => constants.%ImplicitAs.facet.b36\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.07c\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.a38\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.c3f\n// CHECK:STDOUT:   %assoc0.loc16_32.2 => constants.%assoc0.124\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf.Convert(constants.%i32.builtin, constants.%ImplicitAs.facet.b36) {\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.92b\n// CHECK:STDOUT:   %Self => constants.%ImplicitAs.facet.b36\n// CHECK:STDOUT:   %Self.binding.as_type => Core.IntLiteral\n// CHECK:STDOUT:   %pattern_type.loc16_14 => constants.%pattern_type.dc0\n// CHECK:STDOUT:   %.loc16_31.1 => constants.%.9cb\n// CHECK:STDOUT:   %pattern_type.loc16_28 => constants.%pattern_type.956\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(Core.IntLiteral) {\n// CHECK:STDOUT:   %T.loc15_22.1 => Core.IntLiteral\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.79c\n// CHECK:STDOUT:   %Self.loc15_32.2 => constants.%Self.55f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(Core.IntLiteral, constants.%Self.7c0) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => Core.IntLiteral\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.79c\n// CHECK:STDOUT:   %Self => constants.%Self.7c0\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.25a\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.1ae\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.793\n// CHECK:STDOUT:   %assoc0.loc16_32.2 => constants.%assoc0.e18\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(Core.IntLiteral, constants.%ImplicitAs.facet.c5c) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => Core.IntLiteral\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.79c\n// CHECK:STDOUT:   %Self => constants.%ImplicitAs.facet.c5c\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.7aa\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.090\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.793\n// CHECK:STDOUT:   %assoc0.loc16_32.2 => constants.%assoc0.e18\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf.Convert(Core.IntLiteral, constants.%ImplicitAs.facet.c5c) {\n// CHECK:STDOUT:   %T => Core.IntLiteral\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.79c\n// CHECK:STDOUT:   %Self => constants.%ImplicitAs.facet.c5c\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%i32.builtin\n// CHECK:STDOUT:   %pattern_type.loc16_14 => constants.%pattern_type.956\n// CHECK:STDOUT:   %.loc16_31.1 => constants.%.f7d\n// CHECK:STDOUT:   %pattern_type.loc16_28 => constants.%pattern_type.dc0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- user.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = fn_type @Int [concrete]\n// CHECK:STDOUT:   %Int: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %As.type.90f: type = generic_interface_type @As [concrete]\n// CHECK:STDOUT:   %As.generic: %As.type.90f = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %As.type.223: type = facet_type <@As, @As(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.2d0: %As.type.223 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %As.assoc_type.752: type = assoc_entity_type @As, @As(%T) [symbolic]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.bb7: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%T, %Self.2d0) [symbolic]\n// CHECK:STDOUT:   %As.WithSelf.Convert.923: %As.WithSelf.Convert.type.bb7 = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.297: type = symbolic_binding_type Self, 1, %Self.2d0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.760: type = pattern_type %Self.binding.as_type.297 [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %As.type.ffe: type = facet_type <@As, @As(%i32.builtin)> [concrete]\n// CHECK:STDOUT:   %Self.af0: %As.type.ffe = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.06b: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%i32.builtin, %Self.2d0) [symbolic]\n// CHECK:STDOUT:   %As.WithSelf.Convert.b84: %As.WithSelf.Convert.type.06b = struct_value () [symbolic]\n// CHECK:STDOUT:   %As.assoc_type.bc2: type = assoc_entity_type @As, @As(%i32.builtin) [concrete]\n// CHECK:STDOUT:   %assoc0.5d8: %As.assoc_type.bc2 = assoc_entity element0, imports.%Core.import_ref.0ec [concrete]\n// CHECK:STDOUT:   %assoc0.2f9: %As.assoc_type.752 = assoc_entity element0, imports.%Core.import_ref.4c6 [symbolic]\n// CHECK:STDOUT:   %As.impl_witness: <witness> = impl_witness imports.%As.impl_witness_table [concrete]\n// CHECK:STDOUT:   %As.facet: %As.type.ffe = facet_value Core.IntLiteral, (%As.impl_witness) [concrete]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.b07: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%i32.builtin, %As.facet) [concrete]\n// CHECK:STDOUT:   %As.WithSelf.Convert.2d0: %As.WithSelf.Convert.type.b07 = struct_value () [concrete]\n// CHECK:STDOUT:   %.e3a: type = fn_type_with_self_type %As.WithSelf.Convert.type.b07, %As.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.type: type = fn_type @Core.IntLiteral.as.As.impl.Convert [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert: %Core.IntLiteral.as.As.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.bound.4b3: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.As.impl.Convert [concrete]\n// CHECK:STDOUT:   %int_1.f38: %i32.builtin = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.bound.7b2: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.As.impl.Convert [concrete]\n// CHECK:STDOUT:   %int_2.5a1: %i32.builtin = int_value 2 [concrete]\n// CHECK:STDOUT:   %AddWith.type.e05: type = generic_interface_type @AddWith [concrete]\n// CHECK:STDOUT:   %AddWith.generic: %AddWith.type.e05 = struct_value () [concrete]\n// CHECK:STDOUT:   %AddWith.type.6d9: type = facet_type <@AddWith, @AddWith(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.b7c: %AddWith.type.6d9 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %AddWith.assoc_type.b6a: type = assoc_entity_type @AddWith, @AddWith(%T) [symbolic]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type.08f: type = fn_type @AddWith.WithSelf.Op, @AddWith.WithSelf(%T, %Self.b7c) [symbolic]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.fb8: %AddWith.WithSelf.Op.type.08f = struct_value () [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.14b: type = symbolic_binding_type Self, 1, %Self.b7c [symbolic]\n// CHECK:STDOUT:   %pattern_type.259: type = pattern_type %Self.binding.as_type.14b [symbolic]\n// CHECK:STDOUT:   %.730: Core.Form = init_form %Self.binding.as_type.14b [symbolic]\n// CHECK:STDOUT:   %AddWith.type.46d: type = facet_type <@AddWith, @AddWith(%i32.builtin)> [concrete]\n// CHECK:STDOUT:   %Self.365: %AddWith.type.46d = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type.de8: type = fn_type @AddWith.WithSelf.Op, @AddWith.WithSelf(%i32.builtin, %Self.b7c) [symbolic]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.31e: %AddWith.WithSelf.Op.type.de8 = struct_value () [symbolic]\n// CHECK:STDOUT:   %AddWith.assoc_type.dff: type = assoc_entity_type @AddWith, @AddWith(%i32.builtin) [concrete]\n// CHECK:STDOUT:   %assoc0.6d5: %AddWith.assoc_type.dff = assoc_entity element0, imports.%Core.import_ref.1b1 [concrete]\n// CHECK:STDOUT:   %assoc0.20f: %AddWith.assoc_type.b6a = assoc_entity element0, imports.%Core.import_ref.a84 [symbolic]\n// CHECK:STDOUT:   %AddWith.impl_witness: <witness> = impl_witness imports.%AddWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %AddWith.facet: %AddWith.type.46d = facet_value %i32.builtin, (%AddWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type.78e: type = fn_type @AddWith.WithSelf.Op, @AddWith.WithSelf(%i32.builtin, %AddWith.facet) [concrete]\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.d4d: %AddWith.WithSelf.Op.type.78e = struct_value () [concrete]\n// CHECK:STDOUT:   %.0ff: type = fn_type_with_self_type %AddWith.WithSelf.Op.type.78e, %AddWith.facet [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.AddWith.impl.Op.type: type = fn_type @i32.builtin.as.AddWith.impl.Op [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.AddWith.impl.Op: %i32.builtin.as.AddWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.AddWith.impl.Op.bound.abd: <bound method> = bound_method %int_1.f38, %i32.builtin.as.AddWith.impl.Op [concrete]\n// CHECK:STDOUT:   %int_3.a0f: %i32.builtin = int_value 3 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.031: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.738: %ImplicitAs.type.031 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.ff3: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%T) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b3a: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%T, %Self.738) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.1de: %ImplicitAs.WithSelf.Convert.type.b3a = struct_value () [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.a44: type = symbolic_binding_type Self, 1, %Self.738 [symbolic]\n// CHECK:STDOUT:   %pattern_type.e9a: type = pattern_type %Self.binding.as_type.a44 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %Self.cce: %ImplicitAs.type.139 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.577: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %Self.738) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.f0a: %ImplicitAs.WithSelf.Convert.type.577 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.959: type = assoc_entity_type @ImplicitAs, @ImplicitAs(Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %assoc0.461: %ImplicitAs.assoc_type.959 = assoc_entity element0, imports.%Core.import_ref.201 [concrete]\n// CHECK:STDOUT:   %assoc0.843: %ImplicitAs.assoc_type.ff3 = assoc_entity element0, imports.%Core.import_ref.cc1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.78a: type = facet_type <@ImplicitAs, @ImplicitAs(%i32.builtin)> [concrete]\n// CHECK:STDOUT:   %Self.dd8: %ImplicitAs.type.78a = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.304: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.267 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.7f3: %ImplicitAs.type.139 = facet_value %i32.builtin, (%ImplicitAs.impl_witness.304) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.e78: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet.7f3) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.e56: %ImplicitAs.WithSelf.Convert.type.e78 = struct_value () [concrete]\n// CHECK:STDOUT:   %.626: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.e78, %ImplicitAs.facet.7f3 [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.ImplicitAs.impl.Convert.type: type = fn_type @i32.builtin.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.ImplicitAs.impl.Convert: %i32.builtin.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_3.a0f, %i32.builtin.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32.builtin [concrete]\n// CHECK:STDOUT:   %pattern_type.9e2: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.bound.2b2: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.As.impl.Convert [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.bound.2d0: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.As.impl.Convert [concrete]\n// CHECK:STDOUT:   %int_4.4f1: %i32.builtin = int_value 4 [concrete]\n// CHECK:STDOUT:   %i32.builtin.as.AddWith.impl.Op.bound.bf8: <bound method> = bound_method %int_3.a0f, %i32.builtin.as.AddWith.impl.Op [concrete]\n// CHECK:STDOUT:   %int_7: %i32.builtin = int_value 7 [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (Core.IntLiteral, Core.IntLiteral, %i32.builtin) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type = tuple_value (%int_3.1ba, %int_4.0c1, %int_7) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.ea9: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32.builtin, %Self.738) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.149: %ImplicitAs.WithSelf.Convert.type.ea9 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.398: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%i32.builtin) [concrete]\n// CHECK:STDOUT:   %assoc0.4a0: %ImplicitAs.assoc_type.398 = assoc_entity element0, imports.%Core.import_ref.201 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.586: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.7a2 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.fa4: %ImplicitAs.type.78a = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.586) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.66f: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32.builtin, %ImplicitAs.facet.fa4) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.e20: %ImplicitAs.WithSelf.Convert.type.66f = struct_value () [concrete]\n// CHECK:STDOUT:   %.714: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.66f, %ImplicitAs.facet.fa4 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.a95: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.762: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%int_3.a0f, %int_4.4f1, %int_7) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .As = %Core.As\n// CHECK:STDOUT:     .AddWith = %Core.AddWith\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//default\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//default, Int, loaded [concrete = constants.%Int]\n// CHECK:STDOUT:   %Core.As: %As.type.90f = import_ref Core//default, As, loaded [concrete = constants.%As.generic]\n// CHECK:STDOUT:   %Core.import_ref.8db: @As.WithSelf.%As.assoc_type (%As.assoc_type.752) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @As.WithSelf.%assoc0 (constants.%assoc0.2f9)]\n// CHECK:STDOUT:   %Core.Convert.b81 = import_ref Core//default, Convert, unloaded\n// CHECK:STDOUT:   %Core.import_ref.0ec: @As.WithSelf.%As.WithSelf.Convert.type (%As.WithSelf.Convert.type.bb7) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @As.WithSelf.%As.WithSelf.Convert (constants.%As.WithSelf.Convert.923)]\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.2: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @As.%T (constants.%T)]\n// CHECK:STDOUT:   %Core.import_ref.1ac891.2: @As.%As.type (%As.type.223) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @As.%Self (constants.%Self.2d0)]\n// CHECK:STDOUT:   %Core.import_ref.0e7 = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.3: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @As.%T (constants.%T)]\n// CHECK:STDOUT:   %Core.import_ref.4c6 = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.ad5: <witness> = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%As.impl_witness]\n// CHECK:STDOUT:   %Core.import_ref.a86459.1: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = Core.IntLiteral]\n// CHECK:STDOUT:   %Core.import_ref.412: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%As.type.ffe]\n// CHECK:STDOUT:   %Core.import_ref.d9d: %Core.IntLiteral.as.As.impl.Convert.type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%Core.IntLiteral.as.As.impl.Convert]\n// CHECK:STDOUT:   %As.impl_witness_table = impl_witness_table (%Core.import_ref.d9d), @Core.IntLiteral.as.As.impl [concrete]\n// CHECK:STDOUT:   %Core.AddWith: %AddWith.type.e05 = import_ref Core//default, AddWith, loaded [concrete = constants.%AddWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.3f3: @AddWith.WithSelf.%AddWith.assoc_type (%AddWith.assoc_type.b6a) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @AddWith.WithSelf.%assoc0 (constants.%assoc0.20f)]\n// CHECK:STDOUT:   %Core.Op = import_ref Core//default, Op, unloaded\n// CHECK:STDOUT:   %Core.import_ref.1b1: @AddWith.WithSelf.%AddWith.WithSelf.Op.type (%AddWith.WithSelf.Op.type.08f) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @AddWith.WithSelf.%AddWith.WithSelf.Op (constants.%AddWith.WithSelf.Op.fb8)]\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.5: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @AddWith.%T (constants.%T)]\n// CHECK:STDOUT:   %Core.import_ref.c10145.2: @AddWith.%AddWith.type (%AddWith.type.6d9) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @AddWith.%Self (constants.%Self.b7c)]\n// CHECK:STDOUT:   %Core.import_ref.a40 = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.6: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @AddWith.%T (constants.%T)]\n// CHECK:STDOUT:   %Core.import_ref.a84 = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.bf0: <witness> = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%AddWith.impl_witness]\n// CHECK:STDOUT:   %Core.import_ref.63cbb1.2: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   %Core.import_ref.a41: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%AddWith.type.46d]\n// CHECK:STDOUT:   %Core.import_ref.b8a: %i32.builtin.as.AddWith.impl.Op.type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%i32.builtin.as.AddWith.impl.Op]\n// CHECK:STDOUT:   %AddWith.impl_witness_table = impl_witness_table (%Core.import_ref.b8a), @i32.builtin.as.AddWith.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//default, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.178: @ImplicitAs.WithSelf.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.ff3) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%assoc0 (constants.%assoc0.843)]\n// CHECK:STDOUT:   %Core.Convert.2a3 = import_ref Core//default, Convert, unloaded\n// CHECK:STDOUT:   %Core.import_ref.201: @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.type (%ImplicitAs.WithSelf.Convert.type.b3a) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert (constants.%ImplicitAs.WithSelf.Convert.1de)]\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.8: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.%T (constants.%T)]\n// CHECK:STDOUT:   %Core.import_ref.ac4dc5.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.031) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.%Self (constants.%Self.738)]\n// CHECK:STDOUT:   %Core.import_ref.9ec = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.9: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.%T (constants.%T)]\n// CHECK:STDOUT:   %Core.import_ref.cc1 = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.d1a: <witness> = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%ImplicitAs.impl_witness.586]\n// CHECK:STDOUT:   %Core.import_ref.a86459.2: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = Core.IntLiteral]\n// CHECK:STDOUT:   %Core.import_ref.7e7: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%ImplicitAs.type.78a]\n// CHECK:STDOUT:   %Core.import_ref.8be: <witness> = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%ImplicitAs.impl_witness.304]\n// CHECK:STDOUT:   %Core.import_ref.63cbb1.3: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   %Core.import_ref.79b: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%ImplicitAs.type.139]\n// CHECK:STDOUT:   %Core.import_ref.954: %i32.builtin.as.ImplicitAs.impl.Convert.type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%i32.builtin.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.267 = impl_witness_table (%Core.import_ref.954), @i32.builtin.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.d85: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.7a2 = impl_witness_table (%Core.import_ref.d85), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .arr = %arr\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %arr.patt: %pattern_type.9e2 = ref_binding_pattern arr [concrete]\n// CHECK:STDOUT:     %arr.var_patt: %pattern_type.9e2 = var_pattern %arr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %arr.var: ref %array_type = var %arr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_44: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %.loc4_16: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %.loc4_27: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %impl.elem0.loc4_24: %.e3a = impl_witness_access constants.%As.impl_witness, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert]\n// CHECK:STDOUT:     %bound_method.loc4_24: <bound method> = bound_method %int_1, %impl.elem0.loc4_24 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound.4b3]\n// CHECK:STDOUT:     %Core.IntLiteral.as.As.impl.Convert.call.loc4_24: init %i32.builtin = call %bound_method.loc4_24(%int_1) [concrete = constants.%int_1.f38]\n// CHECK:STDOUT:     %.loc4_24.1: %i32.builtin = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call.loc4_24 [concrete = constants.%int_1.f38]\n// CHECK:STDOUT:     %.loc4_24.2: %i32.builtin = converted %int_1, %.loc4_24.1 [concrete = constants.%int_1.f38]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %.loc4_40: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %impl.elem0.loc4_37: %.e3a = impl_witness_access constants.%As.impl_witness, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert]\n// CHECK:STDOUT:     %bound_method.loc4_37: <bound method> = bound_method %int_2, %impl.elem0.loc4_37 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound.7b2]\n// CHECK:STDOUT:     %Core.IntLiteral.as.As.impl.Convert.call.loc4_37: init %i32.builtin = call %bound_method.loc4_37(%int_2) [concrete = constants.%int_2.5a1]\n// CHECK:STDOUT:     %.loc4_37.1: %i32.builtin = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call.loc4_37 [concrete = constants.%int_2.5a1]\n// CHECK:STDOUT:     %.loc4_37.2: %i32.builtin = converted %int_2, %.loc4_37.1 [concrete = constants.%int_2.5a1]\n// CHECK:STDOUT:     %impl.elem0.loc4_32.1: %.0ff = impl_witness_access constants.%AddWith.impl_witness, element0 [concrete = constants.%i32.builtin.as.AddWith.impl.Op]\n// CHECK:STDOUT:     %bound_method.loc4_32.1: <bound method> = bound_method %.loc4_24.2, %impl.elem0.loc4_32.1 [concrete = constants.%i32.builtin.as.AddWith.impl.Op.bound.abd]\n// CHECK:STDOUT:     %i32.builtin.as.AddWith.impl.Op.call: init %i32.builtin = call %bound_method.loc4_32.1(%.loc4_24.2, %.loc4_37.2) [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:     %impl.elem0.loc4_32.2: %.626 = impl_witness_access constants.%ImplicitAs.impl_witness.304, element0 [concrete = constants.%i32.builtin.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:     %bound_method.loc4_32.2: <bound method> = bound_method %i32.builtin.as.AddWith.impl.Op.call, %impl.elem0.loc4_32.2 [concrete = constants.%i32.builtin.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:     %.loc4_32.1: %i32.builtin = value_of_initializer %i32.builtin.as.AddWith.impl.Op.call [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:     %.loc4_32.2: %i32.builtin = converted %i32.builtin.as.AddWith.impl.Op.call, %.loc4_32.1 [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:     %i32.builtin.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method.loc4_32.2(%.loc4_32.2) [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc4_32.3: Core.IntLiteral = value_of_initializer %i32.builtin.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc4_32.4: Core.IntLiteral = converted %i32.builtin.as.AddWith.impl.Op.call, %.loc4_32.3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %array_type: type = array_type %.loc4_32.4, %.loc4_16 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %arr: ref %array_type = ref_binding arr, %arr.var [concrete = %arr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @As(imports.%Core.import_ref.b3bc94.3: type) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %As.type: type = facet_type <@As, @As(%T)> [symbolic = %As.type (constants.%As.type.223)]\n// CHECK:STDOUT:   %Self: @As.%As.type (%As.type.223) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.2d0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Core.import_ref.0e7\n// CHECK:STDOUT:     .Convert = imports.%Core.import_ref.8db\n// CHECK:STDOUT:     witness = (imports.%Core.Convert.b81)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @AddWith(imports.%Core.import_ref.b3bc94.6: type) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %AddWith.type: type = facet_type <@AddWith, @AddWith(%T)> [symbolic = %AddWith.type (constants.%AddWith.type.6d9)]\n// CHECK:STDOUT:   %Self: @AddWith.%AddWith.type (%AddWith.type.6d9) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.b7c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Core.import_ref.a40\n// CHECK:STDOUT:     .Op = imports.%Core.import_ref.3f3\n// CHECK:STDOUT:     witness = (imports.%Core.Op)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @ImplicitAs(imports.%Core.import_ref.b3bc94.9: type) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.031)]\n// CHECK:STDOUT:   %Self: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.031) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.738)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Core.import_ref.9ec\n// CHECK:STDOUT:     .Convert = imports.%Core.import_ref.178\n// CHECK:STDOUT:     witness = (imports.%Core.Convert.2a3)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Core.IntLiteral.as.As.impl: imports.%Core.import_ref.a86459.1 as imports.%Core.import_ref.412 [from \"core.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = imports.%Core.import_ref.ad5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.builtin.as.AddWith.impl: imports.%Core.import_ref.63cbb1.2 as imports.%Core.import_ref.a41 [from \"core.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = imports.%Core.import_ref.bf0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Core.IntLiteral.as.ImplicitAs.impl: imports.%Core.import_ref.a86459.2 as imports.%Core.import_ref.7e7 [from \"core.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = imports.%Core.import_ref.d1a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.builtin.as.ImplicitAs.impl: imports.%Core.import_ref.63cbb1.3 as imports.%Core.import_ref.79b [from \"core.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = imports.%Core.import_ref.8be\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Int = \"int.make_type_signed\" [from \"core.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @As.WithSelf.Convert(imports.%Core.import_ref.b3bc94.2: type, imports.%Core.import_ref.1ac891.2: @As.%As.type (%As.type.223)) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %As.type: type = facet_type <@As, @As(%T)> [symbolic = %As.type (constants.%As.type.223)]\n// CHECK:STDOUT:   %Self: @As.WithSelf.Convert.%As.type (%As.type.223) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.2d0)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.297)]\n// CHECK:STDOUT:   %pattern_type.1: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type.1 (constants.%pattern_type.760)]\n// CHECK:STDOUT:   %.1: Core.Form = init_form %T [symbolic = %.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.2: type = pattern_type %T [symbolic = %pattern_type.2 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Core.IntLiteral.as.As.impl.Convert = \"int.convert_checked\" [from \"core.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @AddWith.WithSelf.Op(imports.%Core.import_ref.b3bc94.5: type, imports.%Core.import_ref.c10145.2: @AddWith.%AddWith.type (%AddWith.type.6d9)) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %AddWith.type: type = facet_type <@AddWith, @AddWith(%T)> [symbolic = %AddWith.type (constants.%AddWith.type.6d9)]\n// CHECK:STDOUT:   %Self: @AddWith.WithSelf.Op.%AddWith.type (%AddWith.type.6d9) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.b7c)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.14b)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.259)]\n// CHECK:STDOUT:   %.1: Core.Form = init_form %Self.binding.as_type [symbolic = %.1 (constants.%.730)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @i32.builtin.as.AddWith.impl.Op = \"int.sadd\" [from \"core.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ImplicitAs.WithSelf.Convert(imports.%Core.import_ref.b3bc94.8: type, imports.%Core.import_ref.ac4dc5.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.031)) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%T)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.031)]\n// CHECK:STDOUT:   %Self: @ImplicitAs.WithSelf.Convert.%ImplicitAs.type (%ImplicitAs.type.031) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.738)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.a44)]\n// CHECK:STDOUT:   %pattern_type.1: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type.1 (constants.%pattern_type.e9a)]\n// CHECK:STDOUT:   %.1: Core.Form = init_form %T [symbolic = %.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.2: type = pattern_type %T [symbolic = %pattern_type.2 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @i32.builtin.as.ImplicitAs.impl.Convert = \"int.convert_checked\" [from \"core.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Core.IntLiteral.as.ImplicitAs.impl.Convert = \"int.convert_checked\" [from \"core.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_3.loc4_49: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %int_4.loc4_52: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]\n// CHECK:STDOUT:   %int_3.loc4_56: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %.loc4_61: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   %impl.elem0.loc4_58: %.e3a = impl_witness_access constants.%As.impl_witness, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert]\n// CHECK:STDOUT:   %bound_method.loc4_58: <bound method> = bound_method %int_3.loc4_56, %impl.elem0.loc4_58 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound.2b2]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call.loc4_58: init %i32.builtin = call %bound_method.loc4_58(%int_3.loc4_56) [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:   %.loc4_58.1: %i32.builtin = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call.loc4_58 [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:   %.loc4_58.2: %i32.builtin = converted %int_3.loc4_56, %.loc4_58.1 [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:   %int_4.loc4_69: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]\n// CHECK:STDOUT:   %.loc4_74: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:   %impl.elem0.loc4_71: %.e3a = impl_witness_access constants.%As.impl_witness, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert]\n// CHECK:STDOUT:   %bound_method.loc4_71: <bound method> = bound_method %int_4.loc4_69, %impl.elem0.loc4_71 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound.2d0]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.call.loc4_71: init %i32.builtin = call %bound_method.loc4_71(%int_4.loc4_69) [concrete = constants.%int_4.4f1]\n// CHECK:STDOUT:   %.loc4_71.1: %i32.builtin = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call.loc4_71 [concrete = constants.%int_4.4f1]\n// CHECK:STDOUT:   %.loc4_71.2: %i32.builtin = converted %int_4.loc4_69, %.loc4_71.1 [concrete = constants.%int_4.4f1]\n// CHECK:STDOUT:   %impl.elem0.loc4_66: %.0ff = impl_witness_access constants.%AddWith.impl_witness, element0 [concrete = constants.%i32.builtin.as.AddWith.impl.Op]\n// CHECK:STDOUT:   %bound_method.loc4_66: <bound method> = bound_method %.loc4_58.2, %impl.elem0.loc4_66 [concrete = constants.%i32.builtin.as.AddWith.impl.Op.bound.bf8]\n// CHECK:STDOUT:   %i32.builtin.as.AddWith.impl.Op.call: init %i32.builtin = call %bound_method.loc4_66(%.loc4_58.2, %.loc4_71.2) [concrete = constants.%int_7]\n// CHECK:STDOUT:   %.loc4_78.1: %tuple.type = tuple_literal (%int_3.loc4_49, %int_4.loc4_52, %i32.builtin.as.AddWith.impl.Op.call) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %impl.elem0.loc4_78.1: %.714 = impl_witness_access constants.%ImplicitAs.impl_witness.586, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:   %bound_method.loc4_78.1: <bound method> = bound_method %int_3.loc4_49, %impl.elem0.loc4_78.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.a95]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc4_78.1: init %i32.builtin = call %bound_method.loc4_78.1(%int_3.loc4_49) [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:   %.loc4_78.2: init %i32.builtin = converted %int_3.loc4_49, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc4_78.1 [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc4_78.3: ref %i32.builtin = array_index file.%arr.var, %int_0\n// CHECK:STDOUT:   %.loc4_78.4: init %i32.builtin to %.loc4_78.3 = in_place_init %.loc4_78.2 [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:   %impl.elem0.loc4_78.2: %.714 = impl_witness_access constants.%ImplicitAs.impl_witness.586, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:   %bound_method.loc4_78.2: <bound method> = bound_method %int_4.loc4_52, %impl.elem0.loc4_78.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.762]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc4_78.2: init %i32.builtin = call %bound_method.loc4_78.2(%int_4.loc4_52) [concrete = constants.%int_4.4f1]\n// CHECK:STDOUT:   %.loc4_78.5: init %i32.builtin = converted %int_4.loc4_52, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc4_78.2 [concrete = constants.%int_4.4f1]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc4_78.6: ref %i32.builtin = array_index file.%arr.var, %int_1\n// CHECK:STDOUT:   %.loc4_78.7: init %i32.builtin to %.loc4_78.6 = in_place_init %.loc4_78.5 [concrete = constants.%int_4.4f1]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc4_78.8: ref %i32.builtin = array_index file.%arr.var, %int_2\n// CHECK:STDOUT:   %.loc4_78.9: init %i32.builtin to %.loc4_78.8 = in_place_init %i32.builtin.as.AddWith.impl.Op.call [concrete = constants.%int_7]\n// CHECK:STDOUT:   %.loc4_78.10: init %array_type to file.%arr.var = array_init (%.loc4_78.4, %.loc4_78.7, %.loc4_78.9) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc4_1: init %array_type = converted %.loc4_78.1, %.loc4_78.10 [concrete = constants.%array]\n// CHECK:STDOUT:   assign file.%arr.var, %.loc4_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As.WithSelf(constants.%T, constants.%Self.2d0) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As.WithSelf.Convert(constants.%T, constants.%Self.2d0) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %As.type => constants.%As.type.223\n// CHECK:STDOUT:   %Self => constants.%Self.2d0\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.297\n// CHECK:STDOUT:   %pattern_type.1 => constants.%pattern_type.760\n// CHECK:STDOUT:   %.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.2 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As(constants.%i32.builtin) {\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %As.type => constants.%As.type.ffe\n// CHECK:STDOUT:   %Self => constants.%Self.af0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As.WithSelf(constants.%i32.builtin, constants.%Self.2d0) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %As.type => constants.%As.type.ffe\n// CHECK:STDOUT:   %Self => constants.%Self.2d0\n// CHECK:STDOUT:   %As.WithSelf.Convert.type => constants.%As.WithSelf.Convert.type.06b\n// CHECK:STDOUT:   %As.WithSelf.Convert => constants.%As.WithSelf.Convert.b84\n// CHECK:STDOUT:   %As.assoc_type => constants.%As.assoc_type.bc2\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.5d8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @As.WithSelf(constants.%i32.builtin, constants.%As.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %As.type => constants.%As.type.ffe\n// CHECK:STDOUT:   %Self => constants.%As.facet\n// CHECK:STDOUT:   %As.WithSelf.Convert.type => constants.%As.WithSelf.Convert.type.b07\n// CHECK:STDOUT:   %As.WithSelf.Convert => constants.%As.WithSelf.Convert.2d0\n// CHECK:STDOUT:   %As.assoc_type => constants.%As.assoc_type.bc2\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.5d8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith.WithSelf(constants.%T, constants.%Self.b7c) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith.WithSelf.Op(constants.%T, constants.%Self.b7c) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %AddWith.type => constants.%AddWith.type.6d9\n// CHECK:STDOUT:   %Self => constants.%Self.b7c\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.14b\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.259\n// CHECK:STDOUT:   %.1 => constants.%.730\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith(constants.%i32.builtin) {\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %AddWith.type => constants.%AddWith.type.46d\n// CHECK:STDOUT:   %Self => constants.%Self.365\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith.WithSelf(constants.%i32.builtin, constants.%Self.b7c) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %AddWith.type => constants.%AddWith.type.46d\n// CHECK:STDOUT:   %Self => constants.%Self.b7c\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type => constants.%AddWith.WithSelf.Op.type.de8\n// CHECK:STDOUT:   %AddWith.WithSelf.Op => constants.%AddWith.WithSelf.Op.31e\n// CHECK:STDOUT:   %AddWith.assoc_type => constants.%AddWith.assoc_type.dff\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.6d5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @AddWith.WithSelf(constants.%i32.builtin, constants.%AddWith.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %AddWith.type => constants.%AddWith.type.46d\n// CHECK:STDOUT:   %Self => constants.%AddWith.facet\n// CHECK:STDOUT:   %AddWith.WithSelf.Op.type => constants.%AddWith.WithSelf.Op.type.78e\n// CHECK:STDOUT:   %AddWith.WithSelf.Op => constants.%AddWith.WithSelf.Op.d4d\n// CHECK:STDOUT:   %AddWith.assoc_type => constants.%AddWith.assoc_type.dff\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.6d5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%T, constants.%Self.738) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf.Convert(constants.%T, constants.%Self.738) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.031\n// CHECK:STDOUT:   %Self => constants.%Self.738\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.a44\n// CHECK:STDOUT:   %pattern_type.1 => constants.%pattern_type.e9a\n// CHECK:STDOUT:   %.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.2 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(Core.IntLiteral) {\n// CHECK:STDOUT:   %T => Core.IntLiteral\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.139\n// CHECK:STDOUT:   %Self => constants.%Self.cce\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(Core.IntLiteral, constants.%Self.738) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => Core.IntLiteral\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.139\n// CHECK:STDOUT:   %Self => constants.%Self.738\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.577\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.f0a\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.959\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.461\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(constants.%i32.builtin) {\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.78a\n// CHECK:STDOUT:   %Self => constants.%Self.dd8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(Core.IntLiteral, constants.%ImplicitAs.facet.7f3) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => Core.IntLiteral\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.139\n// CHECK:STDOUT:   %Self => constants.%ImplicitAs.facet.7f3\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.e78\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.e56\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.959\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.461\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%i32.builtin, constants.%Self.738) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.78a\n// CHECK:STDOUT:   %Self => constants.%Self.738\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.ea9\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.149\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.398\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.4a0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%i32.builtin, constants.%ImplicitAs.facet.fa4) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%i32.builtin\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.78a\n// CHECK:STDOUT:   %Self => constants.%ImplicitAs.facet.fa4\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.66f\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.e20\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.398\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.4a0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/builtin/definition.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/builtin/definition.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/builtin/definition.carbon\n\nfn Add(a: i32, b: i32) -> i32 = \"int.sadd\";\n\n// CHECK:STDOUT: --- definition.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Add.type: type = fn_type @Add [concrete]\n// CHECK:STDOUT:   %Add: %Add.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Add = %Add.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Add.decl: %Add.type = fn_decl @Add [concrete = constants.%Add] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc15_27: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15: Core.Form = init_form %i32.loc15_27 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc15_11: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc15_19: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Add(%a.param: %i32, %b.param: %i32) -> out %return.param: %i32 = \"int.sadd\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/builtin/fail_redefined.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/builtin/fail_redefined.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/builtin/fail_redefined.carbon\n\nfn A(n: i32, m: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: fail_redefined.carbon:[[@LINE+7]]:1: error: redefinition of `fn A` [RedeclRedef]\n// CHECK:STDERR: fn A(n: i32, unused m: i32) -> i32 { return n; }\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redefined.carbon:[[@LINE-4]]:1: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR: fn A(n: i32, m: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn A(n: i32, unused m: i32) -> i32 { return n; }\n\nfn B(n: i32, unused m: i32) -> i32 { return n; }\n// CHECK:STDERR: fail_redefined.carbon:[[@LINE+7]]:1: error: redefinition of `fn B` [RedeclRedef]\n// CHECK:STDERR: fn B(n: i32, m: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redefined.carbon:[[@LINE-4]]:1: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR: fn B(n: i32, unused m: i32) -> i32 { return n; }\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn B(n: i32, m: i32) -> i32 = \"int.sadd\";\n\nfn C(n: i32, m: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: fail_redefined.carbon:[[@LINE+7]]:1: error: redefinition of `fn C` [RedeclRedef]\n// CHECK:STDERR: fn C(n: i32, m: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redefined.carbon:[[@LINE-4]]:1: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR: fn C(n: i32, m: i32) -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn C(n: i32, m: i32) -> i32 = \"int.sadd\";\n\n// CHECK:STDOUT: --- fail_redefined.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %A.type.8165c1.1: type = fn_type @A.loc15 [concrete]\n// CHECK:STDOUT:   %A.8aef9d.1: %A.type.8165c1.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %A.type.8165c1.2: type = fn_type @A.loc23 [concrete]\n// CHECK:STDOUT:   %A.8aef9d.2: %A.type.8165c1.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %B.type.d6bcfe.1: type = fn_type @B.loc25 [concrete]\n// CHECK:STDOUT:   %B.5d732e.1: %B.type.d6bcfe.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %B.type.d6bcfe.2: type = fn_type @B.loc33 [concrete]\n// CHECK:STDOUT:   %B.5d732e.2: %B.type.d6bcfe.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type.0036b9.1: type = fn_type @C.loc35 [concrete]\n// CHECK:STDOUT:   %C.6a91b4.1: %C.type.0036b9.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type.0036b9.2: type = fn_type @C.loc43 [concrete]\n// CHECK:STDOUT:   %C.6a91b4.2: %C.type.0036b9.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl.loc15\n// CHECK:STDOUT:     .B = %B.decl.loc25\n// CHECK:STDOUT:     .C = %C.decl.loc35\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl.loc15: %A.type.8165c1.1 = fn_decl @A.loc15 [concrete = constants.%A.8aef9d.1] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %m.patt: %pattern_type.7ce = value_binding_pattern m [concrete]\n// CHECK:STDOUT:     %m.param_patt: %pattern_type.7ce = value_param_pattern %m.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc15_25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15: Core.Form = init_form %i32.loc15_25 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc15_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %m.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc15_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %m: %i32 = value_binding m, %m.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl.loc23: %A.type.8165c1.2 = fn_decl @A.loc23 [concrete = constants.%A.8aef9d.2] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %m.patt: %pattern_type.7ce = value_binding_pattern m [concrete]\n// CHECK:STDOUT:     %m.param_patt: %pattern_type.7ce = value_param_pattern %m.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc23_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc23: Core.Form = init_form %i32.loc23_32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc23_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %m.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc23_24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %m: %i32 = value_binding m, %m.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl.loc25: %B.type.d6bcfe.1 = fn_decl @B.loc25 [concrete = constants.%B.5d732e.1] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %m.patt: %pattern_type.7ce = value_binding_pattern m [concrete]\n// CHECK:STDOUT:     %m.param_patt: %pattern_type.7ce = value_param_pattern %m.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc25_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc25: Core.Form = init_form %i32.loc25_32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc25_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %m.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc25_24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %m: %i32 = value_binding m, %m.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl.loc33: %B.type.d6bcfe.2 = fn_decl @B.loc33 [concrete = constants.%B.5d732e.2] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %m.patt: %pattern_type.7ce = value_binding_pattern m [concrete]\n// CHECK:STDOUT:     %m.param_patt: %pattern_type.7ce = value_param_pattern %m.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc33_25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc33: Core.Form = init_form %i32.loc33_25 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc33_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %m.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc33_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %m: %i32 = value_binding m, %m.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc35: %C.type.0036b9.1 = fn_decl @C.loc35 [concrete = constants.%C.6a91b4.1] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %m.patt: %pattern_type.7ce = value_binding_pattern m [concrete]\n// CHECK:STDOUT:     %m.param_patt: %pattern_type.7ce = value_param_pattern %m.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc35_25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc35: Core.Form = init_form %i32.loc35_25 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc35_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %m.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc35_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %m: %i32 = value_binding m, %m.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc43: %C.type.0036b9.2 = fn_decl @C.loc43 [concrete = constants.%C.6a91b4.2] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %m.patt: %pattern_type.7ce = value_binding_pattern m [concrete]\n// CHECK:STDOUT:     %m.param_patt: %pattern_type.7ce = value_param_pattern %m.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc43_25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc43: Core.Form = init_form %i32.loc43_25 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc43_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %m.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc43_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %m: %i32 = value_binding m, %m.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.loc15(%n.param: %i32, %m.param: %i32) -> out %return.param: %i32 = \"int.sadd\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.loc23(%n.param: %i32, %m.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc23_45.1: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc23_45.2: <bound method> = bound_method %n.ref, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc23_45.2(%n.ref)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.loc25(%n.param: %i32, %m.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc25_45.1: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc25_45.2: <bound method> = bound_method %n.ref, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc25_45.2(%n.ref)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B.loc33(%n.param: %i32, %m.param: %i32) -> out %return.param: %i32 = \"int.sadd\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.loc35(%n.param: %i32, %m.param: %i32) -> out %return.param: %i32 = \"int.sadd\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.loc43(%n.param: %i32, %m.param: %i32) -> out %return.param: %i32 = \"int.sadd\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/builtin/fail_unknown.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/builtin/fail_unknown.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/builtin/fail_unknown.carbon\n\n// CHECK:STDERR: fail_unknown.carbon:[[@LINE+4]]:23: error: unknown builtin function name \"unknown.builtin.name\" [UnknownBuiltinFunctionName]\n// CHECK:STDERR: fn UnknownBuiltin() = \"unknown.builtin.name\";\n// CHECK:STDERR:                       ^~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn UnknownBuiltin() = \"unknown.builtin.name\";\n\n// CHECK:STDOUT: --- fail_unknown.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %UnknownBuiltin.type: type = fn_type @UnknownBuiltin [concrete]\n// CHECK:STDOUT:   %UnknownBuiltin: %UnknownBuiltin.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .UnknownBuiltin = %UnknownBuiltin.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %UnknownBuiltin.decl: %UnknownBuiltin.type = fn_decl @UnknownBuiltin [concrete = constants.%UnknownBuiltin] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @UnknownBuiltin();\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/builtin/import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/builtin/import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/builtin/import.carbon\n\n// --- core.carbon\n\npackage Core library \"[[@TEST_NAME]]\";\n\n\nfn IntLiteral() -> type = \"int_literal.make_type\";\nfn Int(N: IntLiteral()) -> type = \"int.make_type_signed\";\n\nfn AsI32(a: IntLiteral()) -> i32 = \"int.convert_checked\";\nfn AsIntLiteral(a: i32) -> IntLiteral() = \"int.convert_checked\";\n\nfn TestAdd(a: i32, b: i32) -> i32 = \"int.sadd\";\n\n// --- use.carbon\n\nimport Core library \"core\";\n\nvar arr: array(i32, Core.AsIntLiteral(Core.TestAdd(Core.AsI32(1), Core.AsI32(2)))) = (Core.AsI32(1), Core.AsI32(2), Core.AsI32(3));\n\n// CHECK:STDOUT: --- core.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %.805: Core.Form = init_form type [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %Int.type: type = fn_type @Int [concrete]\n// CHECK:STDOUT:   %Int: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %.9cb: Core.Form = init_form %i32.builtin [concrete]\n// CHECK:STDOUT:   %pattern_type.956: type = pattern_type %i32.builtin [concrete]\n// CHECK:STDOUT:   %AsI32.type: type = fn_type @AsI32 [concrete]\n// CHECK:STDOUT:   %AsI32: %AsI32.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.f7d: Core.Form = init_form Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %AsIntLiteral.type: type = fn_type @AsIntLiteral [concrete]\n// CHECK:STDOUT:   %AsIntLiteral: %AsIntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %TestAdd.type: type = fn_type @TestAdd [concrete]\n// CHECK:STDOUT:   %TestAdd: %TestAdd.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %IntLiteral.decl\n// CHECK:STDOUT:     .Int = %Int.decl\n// CHECK:STDOUT:     .AsI32 = %AsI32.decl\n// CHECK:STDOUT:     .AsIntLiteral = %AsIntLiteral.decl\n// CHECK:STDOUT:     .TestAdd = %TestAdd.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %IntLiteral.decl: %IntLiteral.type = fn_decl @IntLiteral [concrete = constants.%IntLiteral] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.98f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.98f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_20.1: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc5_20.2: Core.Form = init_form %.loc5_20.1 [concrete = constants.%.805]\n// CHECK:STDOUT:     %return.param: ref type = out_param call_param0\n// CHECK:STDOUT:     %return: ref type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Int.decl: %Int.type = fn_decl @Int [concrete = constants.%Int] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = value_binding_pattern N [concrete]\n// CHECK:STDOUT:     %N.param_patt: %pattern_type.dc0 = value_param_pattern %N.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.98f = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.98f = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_28.1: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc6_28.2: Core.Form = init_form %.loc6_28.1 [concrete = constants.%.805]\n// CHECK:STDOUT:     %N.param: Core.IntLiteral = value_param call_param0\n// CHECK:STDOUT:     %.loc6_22.1: type = splice_block %.loc6_22.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc6_22.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc6_22.3: type = converted %IntLiteral.call, %.loc6_22.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N: Core.IntLiteral = value_binding N, %N.param\n// CHECK:STDOUT:     %return.param: ref type = out_param call_param1\n// CHECK:STDOUT:     %return: ref type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %AsI32.decl: %AsI32.type = fn_decl @AsI32 [concrete = constants.%AsI32] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.dc0 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.dc0 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.956 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.956 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_30.1: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %.loc8_30.2: Core.Form = init_form %.loc8_30.1 [concrete = constants.%.9cb]\n// CHECK:STDOUT:     %a.param: Core.IntLiteral = value_param call_param0\n// CHECK:STDOUT:     %.loc8_24.1: type = splice_block %.loc8_24.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc8_24.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc8_24.3: type = converted %IntLiteral.call, %.loc8_24.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: Core.IntLiteral = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32.builtin = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32.builtin = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %AsIntLiteral.decl: %AsIntLiteral.type = fn_decl @AsIntLiteral [concrete = constants.%AsIntLiteral] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.956 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.956 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.dc0 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.dc0 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, file.%IntLiteral.decl [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:     %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc9_39.1: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc9_39.2: type = converted %IntLiteral.call, %.loc9_39.1 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     %.loc9_39.3: Core.Form = init_form %.loc9_39.2 [concrete = constants.%.f7d]\n// CHECK:STDOUT:     %a.param: %i32.builtin = value_param call_param0\n// CHECK:STDOUT:     %.loc9_20: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %a: %i32.builtin = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref Core.IntLiteral = out_param call_param1\n// CHECK:STDOUT:     %return: ref Core.IntLiteral = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %TestAdd.decl: %TestAdd.type = fn_decl @TestAdd [concrete = constants.%TestAdd] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.956 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.956 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.956 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.956 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.956 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.956 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc11_31.1: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %.loc11_31.2: Core.Form = init_form %.loc11_31.1 [concrete = constants.%.9cb]\n// CHECK:STDOUT:     %a.param: %i32.builtin = value_param call_param0\n// CHECK:STDOUT:     %.loc11_15: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %a: %i32.builtin = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32.builtin = value_param call_param1\n// CHECK:STDOUT:     %.loc11_23: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %b: %i32.builtin = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32.builtin = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32.builtin = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @IntLiteral() -> out %return.param: type = \"int_literal.make_type\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Int(%N.param: Core.IntLiteral) -> out %return.param: type = \"int.make_type_signed\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @AsI32(%a.param: Core.IntLiteral) -> out %return.param: %i32.builtin = \"int.convert_checked\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @AsIntLiteral(%a.param: %i32.builtin) -> out %return.param: Core.IntLiteral = \"int.convert_checked\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @TestAdd(%a.param: %i32.builtin, %b.param: %i32.builtin) -> out %return.param: %i32.builtin = \"int.sadd\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = fn_type @Int [concrete]\n// CHECK:STDOUT:   %Int: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %AsIntLiteral.type: type = fn_type @AsIntLiteral [concrete]\n// CHECK:STDOUT:   %AsIntLiteral: %AsIntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %TestAdd.type: type = fn_type @TestAdd [concrete]\n// CHECK:STDOUT:   %TestAdd: %TestAdd.type = struct_value () [concrete]\n// CHECK:STDOUT:   %AsI32.type: type = fn_type @AsI32 [concrete]\n// CHECK:STDOUT:   %AsI32: %AsI32.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_1.f38: %i32.builtin = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_2.5a1: %i32.builtin = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_3.a0f: %i32.builtin = int_value 3 [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32.builtin [concrete]\n// CHECK:STDOUT:   %pattern_type.9e2: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%i32.builtin, %i32.builtin, %i32.builtin) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type = tuple_value (%int_1.f38, %int_2.5a1, %int_3.a0f) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%int_1.f38, %int_2.5a1, %int_3.a0f) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .AsIntLiteral = %Core.AsIntLiteral\n// CHECK:STDOUT:     .TestAdd = %Core.TestAdd\n// CHECK:STDOUT:     .AsI32 = %Core.AsI32\n// CHECK:STDOUT:     import Core//core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//core, Int, loaded [concrete = constants.%Int]\n// CHECK:STDOUT:   %Core.AsIntLiteral: %AsIntLiteral.type = import_ref Core//core, AsIntLiteral, loaded [concrete = constants.%AsIntLiteral]\n// CHECK:STDOUT:   %Core.TestAdd: %TestAdd.type = import_ref Core//core, TestAdd, loaded [concrete = constants.%TestAdd]\n// CHECK:STDOUT:   %Core.AsI32: %AsI32.type = import_ref Core//core, AsI32, loaded [concrete = constants.%AsI32]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .arr = %arr\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %arr.patt: %pattern_type.9e2 = ref_binding_pattern arr [concrete]\n// CHECK:STDOUT:     %arr.var_patt: %pattern_type.9e2 = var_pattern %arr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %arr.var: ref %array_type = var %arr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_82: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %.loc4_16: type = type_literal constants.%i32.builtin [concrete = constants.%i32.builtin]\n// CHECK:STDOUT:     %Core.ref.loc4_21: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %AsIntLiteral.ref: %AsIntLiteral.type = name_ref AsIntLiteral, imports.%Core.AsIntLiteral [concrete = constants.%AsIntLiteral]\n// CHECK:STDOUT:     %Core.ref.loc4_39: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %TestAdd.ref: %TestAdd.type = name_ref TestAdd, imports.%Core.TestAdd [concrete = constants.%TestAdd]\n// CHECK:STDOUT:     %Core.ref.loc4_52: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %AsI32.ref.loc4_56: %AsI32.type = name_ref AsI32, imports.%Core.AsI32 [concrete = constants.%AsI32]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %AsI32.call.loc4_64: init %i32.builtin = call %AsI32.ref.loc4_56(%int_1) [concrete = constants.%int_1.f38]\n// CHECK:STDOUT:     %Core.ref.loc4_67: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %AsI32.ref.loc4_71: %AsI32.type = name_ref AsI32, imports.%Core.AsI32 [concrete = constants.%AsI32]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %AsI32.call.loc4_79: init %i32.builtin = call %AsI32.ref.loc4_71(%int_2) [concrete = constants.%int_2.5a1]\n// CHECK:STDOUT:     %.loc4_64.1: %i32.builtin = value_of_initializer %AsI32.call.loc4_64 [concrete = constants.%int_1.f38]\n// CHECK:STDOUT:     %.loc4_64.2: %i32.builtin = converted %AsI32.call.loc4_64, %.loc4_64.1 [concrete = constants.%int_1.f38]\n// CHECK:STDOUT:     %.loc4_79.1: %i32.builtin = value_of_initializer %AsI32.call.loc4_79 [concrete = constants.%int_2.5a1]\n// CHECK:STDOUT:     %.loc4_79.2: %i32.builtin = converted %AsI32.call.loc4_79, %.loc4_79.1 [concrete = constants.%int_2.5a1]\n// CHECK:STDOUT:     %TestAdd.call: init %i32.builtin = call %TestAdd.ref(%.loc4_64.2, %.loc4_79.2) [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:     %.loc4_80.1: %i32.builtin = value_of_initializer %TestAdd.call [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:     %.loc4_80.2: %i32.builtin = converted %TestAdd.call, %.loc4_80.1 [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:     %AsIntLiteral.call: init Core.IntLiteral = call %AsIntLiteral.ref(%.loc4_80.2) [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc4_81.1: Core.IntLiteral = value_of_initializer %AsIntLiteral.call [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc4_81.2: Core.IntLiteral = converted %AsIntLiteral.call, %.loc4_81.1 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %array_type: type = array_type %.loc4_81.2, %.loc4_16 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %arr: ref %array_type = ref_binding arr, %arr.var [concrete = %arr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Int = \"int.make_type_signed\" [from \"core.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @AsIntLiteral = \"int.convert_checked\" [from \"core.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @TestAdd = \"int.sadd\" [from \"core.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @AsI32 = \"int.convert_checked\" [from \"core.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Core.ref.loc4_87: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %AsI32.ref.loc4_91: %AsI32.type = name_ref AsI32, imports.%Core.AsI32 [concrete = constants.%AsI32]\n// CHECK:STDOUT:   %int_1.loc4_98: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %AsI32.call.loc4_99: init %i32.builtin = call %AsI32.ref.loc4_91(%int_1.loc4_98) [concrete = constants.%int_1.f38]\n// CHECK:STDOUT:   %Core.ref.loc4_102: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %AsI32.ref.loc4_106: %AsI32.type = name_ref AsI32, imports.%Core.AsI32 [concrete = constants.%AsI32]\n// CHECK:STDOUT:   %int_2.loc4_113: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %AsI32.call.loc4_114: init %i32.builtin = call %AsI32.ref.loc4_106(%int_2.loc4_113) [concrete = constants.%int_2.5a1]\n// CHECK:STDOUT:   %Core.ref.loc4_117: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:   %AsI32.ref.loc4_121: %AsI32.type = name_ref AsI32, imports.%Core.AsI32 [concrete = constants.%AsI32]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %AsI32.call.loc4_129: init %i32.builtin = call %AsI32.ref.loc4_121(%int_3) [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:   %.loc4_130.1: %tuple.type = tuple_literal (%AsI32.call.loc4_99, %AsI32.call.loc4_114, %AsI32.call.loc4_129) [concrete = constants.%tuple]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %.loc4_130.2: ref %i32.builtin = array_index file.%arr.var, %int_0\n// CHECK:STDOUT:   %.loc4_130.3: init %i32.builtin to %.loc4_130.2 = in_place_init %AsI32.call.loc4_99 [concrete = constants.%int_1.f38]\n// CHECK:STDOUT:   %int_1.loc4_130: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc4_130.4: ref %i32.builtin = array_index file.%arr.var, %int_1.loc4_130\n// CHECK:STDOUT:   %.loc4_130.5: init %i32.builtin to %.loc4_130.4 = in_place_init %AsI32.call.loc4_114 [concrete = constants.%int_2.5a1]\n// CHECK:STDOUT:   %int_2.loc4_130: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc4_130.6: ref %i32.builtin = array_index file.%arr.var, %int_2.loc4_130\n// CHECK:STDOUT:   %.loc4_130.7: init %i32.builtin to %.loc4_130.6 = in_place_init %AsI32.call.loc4_129 [concrete = constants.%int_3.a0f]\n// CHECK:STDOUT:   %.loc4_130.8: init %array_type to file.%arr.var = array_init (%.loc4_130.3, %.loc4_130.5, %.loc4_130.7) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc4_1: init %array_type = converted %.loc4_130.1, %.loc4_130.8 [concrete = constants.%array]\n// CHECK:STDOUT:   assign file.%arr.var, %.loc4_1\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/builtin/method.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/builtin/method.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/builtin/method.carbon\n\ninterface I {\n  fn F[self: Self](other: Self) -> Self;\n}\n\nimpl i32 as I {\n  fn F[self: i32](other: i32) -> i32 = \"int.sadd\";\n}\n\nvar arr: array(i32, (1 as i32).(I.F)(2));\n\n// CHECK:STDOUT: --- method.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.d31: type = symbolic_binding_type Self, 0, %Self.ab9 [symbolic]\n// CHECK:STDOUT:   %pattern_type.fa0: type = pattern_type %Self.binding.as_type.d31 [symbolic]\n// CHECK:STDOUT:   %.e46: Core.Form = init_form %Self.binding.as_type.d31 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.08c: type = fn_type @I.WithSelf.F, @I.WithSelf(%Self.ab9) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.705: %I.WithSelf.F.type.08c = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0.18e: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @i32.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %i32.as.I.impl.F.type: type = fn_type @i32.as.I.impl.F [concrete]\n// CHECK:STDOUT:   %i32.as.I.impl.F: %i32.as.I.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %i32, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.f37: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.b05: %I.WithSelf.F.type.f37 = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %As.type.90f: type = generic_interface_type @As [concrete]\n// CHECK:STDOUT:   %As.generic: %As.type.90f = struct_value () [concrete]\n// CHECK:STDOUT:   %As.type.047: type = facet_type <@As, @As(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.type.09e: type = fn_type @Core.IntLiteral.as.As.impl.Convert, @Core.IntLiteral.as.As.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.dbe: %Core.IntLiteral.as.As.impl.Convert.type.09e = struct_value () [symbolic]\n// CHECK:STDOUT:   %From: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %As.impl_witness.ab6: <witness> = impl_witness imports.%As.impl_witness_table.9fc, @Core.IntLiteral.as.As.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.type.8ec: type = fn_type @Core.IntLiteral.as.As.impl.Convert, @Core.IntLiteral.as.As.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.29b: %Core.IntLiteral.as.As.impl.Convert.type.8ec = struct_value () [concrete]\n// CHECK:STDOUT:   %As.facet: %As.type.047 = facet_value Core.IntLiteral, (%As.impl_witness.ab6) [concrete]\n// CHECK:STDOUT:   %As.WithSelf.Convert.type.e5b: type = fn_type @As.WithSelf.Convert, @As.WithSelf(%i32, %As.facet) [concrete]\n// CHECK:STDOUT:   %.9ed: type = fn_type_with_self_type %As.WithSelf.Convert.type.e5b, %As.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.As.impl.Convert.29b [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.As.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.As.impl.Convert.29b, @Core.IntLiteral.as.As.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.290: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.As.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %.131: type = fn_type_with_self_type %I.WithSelf.F.type.f37, %I.facet [concrete]\n// CHECK:STDOUT:   %i32.as.I.impl.F.bound: <bound method> = bound_method %int_1.5d2, %i32.as.I.impl.F [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.2ed: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%From) [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.d29: %Int.as.ImplicitAs.impl.Convert.type.2ed = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.b94: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet.b94) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet.b94 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.640: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.ea2, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.240: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.dd4: %Int.as.ImplicitAs.impl.Convert.type.240 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet.290: %ImplicitAs.type.139 = facet_value %i32, (%ImplicitAs.impl_witness.640) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.462: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet.290) [concrete]\n// CHECK:STDOUT:   %.0a7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.462, %ImplicitAs.facet.290 [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_3.822, %Int.as.ImplicitAs.impl.Convert.dd4 [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Int.as.ImplicitAs.impl.Convert.dd4, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.17a: <bound method> = bound_method %int_3.822, %Int.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_3.1ba, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.5d8: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.d11: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%array_type) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.576: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%array_type) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.9c0: %T.as.DefaultOrUnformed.impl.Op.type.576 = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %array_type, (%DefaultOrUnformed.impl_witness.d11) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.9c0, @T.as.DefaultOrUnformed.impl.Op(%array_type) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .As = %Core.As\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.As: %As.type.90f = import_ref Core//prelude/parts/as, As, loaded [concrete = constants.%As.generic]\n// CHECK:STDOUT:   %Core.import_ref.ca0: @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert.type (%Core.IntLiteral.as.As.impl.Convert.type.09e) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.As.impl.%Core.IntLiteral.as.As.impl.Convert (constants.%Core.IntLiteral.as.As.impl.Convert.dbe)]\n// CHECK:STDOUT:   %As.impl_witness_table.9fc = impl_witness_table (%Core.import_ref.ca0), @Core.IntLiteral.as.As.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.0bc: @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert.type (%Int.as.ImplicitAs.impl.Convert.type.2ed) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert (constants.%Int.as.ImplicitAs.impl.Convert.d29)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.ea2 = impl_witness_table (%Core.import_ref.0bc), @Int.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .arr = %arr\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @i32.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %arr.patt: %pattern_type.5d8 = ref_binding_pattern arr [concrete]\n// CHECK:STDOUT:     %arr.var_patt: %pattern_type.5d8 = var_pattern %arr.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %arr.var: ref %array_type = var %arr.var_patt [concrete]\n// CHECK:STDOUT:   %.loc23_40: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %i32.loc23_16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %i32.loc23_27: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %impl.elem0.loc23_24: %.9ed = impl_witness_access constants.%As.impl_witness.ab6, element0 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.29b]\n// CHECK:STDOUT:     %bound_method.loc23_24.1: <bound method> = bound_method %int_1, %impl.elem0.loc23_24 [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn.loc23_24: <specific function> = specific_function %impl.elem0.loc23_24, @Core.IntLiteral.as.As.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.As.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc23_24.2: <bound method> = bound_method %int_1, %specific_fn.loc23_24 [concrete = constants.%bound_method.290]\n// CHECK:STDOUT:     %Core.IntLiteral.as.As.impl.Convert.call: init %i32 = call %bound_method.loc23_24.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc23_24.1: %i32 = value_of_initializer %Core.IntLiteral.as.As.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc23_24.2: %i32 = converted %int_1, %.loc23_24.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, %I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %F.ref: %I.assoc_type = name_ref F, @I.WithSelf.%assoc0 [concrete = constants.%assoc0.18e]\n// CHECK:STDOUT:     %impl.elem0.loc23_31: %.131 = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%i32.as.I.impl.F]\n// CHECK:STDOUT:     %bound_method.loc23_31: <bound method> = bound_method %.loc23_24.2, %impl.elem0.loc23_31 [concrete = constants.%i32.as.I.impl.F.bound]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %impl.elem0.loc23_38: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc23_38.1: <bound method> = bound_method %int_2, %impl.elem0.loc23_38 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn.loc23_38: <specific function> = specific_function %impl.elem0.loc23_38, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc23_38.2: <bound method> = bound_method %int_2, %specific_fn.loc23_38 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc23_38.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc23_38.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc23_38.2: %i32 = converted %int_2, %.loc23_38.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %i32.as.I.impl.F.call: init %i32 = call %bound_method.loc23_31(%.loc23_24.2, %.loc23_38.2) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %impl.elem0.loc23_39: %.0a7 = impl_witness_access constants.%ImplicitAs.impl_witness.640, element0 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.dd4]\n// CHECK:STDOUT:     %bound_method.loc23_39.1: <bound method> = bound_method %i32.as.I.impl.F.call, %impl.elem0.loc23_39 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn.loc23_39: <specific function> = specific_function %impl.elem0.loc23_39, @Int.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Int.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc23_39.2: <bound method> = bound_method %i32.as.I.impl.F.call, %specific_fn.loc23_39 [concrete = constants.%bound_method.17a]\n// CHECK:STDOUT:     %.loc23_39.1: %i32 = value_of_initializer %i32.as.I.impl.F.call [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %.loc23_39.2: %i32 = converted %i32.as.I.impl.F.call, %.loc23_39.1 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %Int.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method.loc23_39.2(%.loc23_39.2) [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc23_39.3: Core.IntLiteral = value_of_initializer %Int.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %.loc23_39.4: Core.IntLiteral = converted %i32.as.I.impl.F.call, %.loc23_39.3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %array_type: type = array_type %.loc23_39.4, %i32.loc23_16 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %arr: ref %array_type = ref_binding arr, %arr.var [concrete = %arr.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %I.WithSelf.F.decl: @I.WithSelf.%I.WithSelf.F.type (%I.WithSelf.F.type.08c) = fn_decl @I.WithSelf.F [symbolic = @I.WithSelf.%I.WithSelf.F (constants.%I.WithSelf.F.705)] {\n// CHECK:STDOUT:     %self.patt: @I.WithSelf.F.%pattern_type (%pattern_type.fa0) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: @I.WithSelf.F.%pattern_type (%pattern_type.fa0) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %other.patt: @I.WithSelf.F.%pattern_type (%pattern_type.fa0) = value_binding_pattern other [concrete]\n// CHECK:STDOUT:     %other.param_patt: @I.WithSelf.F.%pattern_type (%pattern_type.fa0) = value_param_pattern %other.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @I.WithSelf.F.%pattern_type (%pattern_type.fa0) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @I.WithSelf.F.%pattern_type (%pattern_type.fa0) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Self.ref.loc16_36: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self.ab9)]\n// CHECK:STDOUT:     %Self.as_type.loc16_36: type = facet_access_type %Self.ref.loc16_36 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.d31)]\n// CHECK:STDOUT:     %.loc16_36.2: type = converted %Self.ref.loc16_36, %Self.as_type.loc16_36 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.d31)]\n// CHECK:STDOUT:     %.loc16_36.3: Core.Form = init_form %.loc16_36.2 [symbolic = %.loc16_36.1 (constants.%.e46)]\n// CHECK:STDOUT:     %self.param: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.d31) = value_param call_param0\n// CHECK:STDOUT:     %.loc16_14.1: type = splice_block %.loc16_14.2 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.d31)] {\n// CHECK:STDOUT:       %Self.ref.loc16_14: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self.ab9)]\n// CHECK:STDOUT:       %Self.as_type.loc16_14: type = facet_access_type %Self.ref.loc16_14 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.d31)]\n// CHECK:STDOUT:       %.loc16_14.2: type = converted %Self.ref.loc16_14, %Self.as_type.loc16_14 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.d31)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.d31) = value_binding self, %self.param\n// CHECK:STDOUT:     %other.param: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.d31) = value_param call_param1\n// CHECK:STDOUT:     %.loc16_27.1: type = splice_block %.loc16_27.2 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.d31)] {\n// CHECK:STDOUT:       %Self.ref.loc16_27: %I.type = name_ref Self, @I.%Self [symbolic = %Self (constants.%Self.ab9)]\n// CHECK:STDOUT:       %Self.as_type.loc16_27: type = facet_access_type %Self.ref.loc16_27 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.d31)]\n// CHECK:STDOUT:       %.loc16_27.2: type = converted %Self.ref.loc16_27, %Self.as_type.loc16_27 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.d31)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %other: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.d31) = value_binding other, %other.param\n// CHECK:STDOUT:     %return.param: ref @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.d31) = out_param call_param2\n// CHECK:STDOUT:     %return: ref @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.d31) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, %I.WithSelf.F.decl [concrete = constants.%assoc0.18e]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F = @I.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%I.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.as.I.impl: %i32 as %I.ref {\n// CHECK:STDOUT:   %i32.as.I.impl.F.decl: %i32.as.I.impl.F.type = fn_decl @i32.as.I.impl.F [concrete = constants.%i32.as.I.impl.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.7ce = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.7ce = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %other.patt: %pattern_type.7ce = value_binding_pattern other [concrete]\n// CHECK:STDOUT:     %other.param_patt: %pattern_type.7ce = value_param_pattern %other.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc20_34: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc20: Core.Form = init_form %i32.loc20_34 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc20_14: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %self: %i32 = value_binding self, %self.param\n// CHECK:STDOUT:     %other.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc20_26: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %other: %i32 = value_binding other, %other.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param2\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%i32.as.I.impl.F.decl), @i32.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %i32.as.I.impl.F.decl\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.F(@I.%Self: %I.type) {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.ab9)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.d31)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.fa0)]\n// CHECK:STDOUT:   %.loc16_36.1: Core.Form = init_form %Self.binding.as_type [symbolic = %.loc16_36.1 (constants.%.e46)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.d31), %other.param: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.d31)) -> out %return.param: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.d31);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @i32.as.I.impl.F(%self.param: %i32, %other.param: %i32) -> out %return.param: %i32 = \"int.sadd\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%array_type, (constants.%DefaultOrUnformed.impl_witness.d11) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc23_41.1: %DefaultOrUnformed.type = converted constants.%array_type, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc23_41.1 [concrete = constants.%array_type]\n// CHECK:STDOUT:   %.loc23_41.2: type = converted %.loc23_41.1, %as_type [concrete = constants.%array_type]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function constants.%T.as.DefaultOrUnformed.impl.Op.9c0, @T.as.DefaultOrUnformed.impl.Op(constants.%array_type) [concrete = constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn]\n// CHECK:STDOUT:   %.loc23_1: ref %array_type = splice_block file.%arr.var [concrete = file.%arr.var] {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %array_type to %.loc23_1 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign file.%arr.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.ab9\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.08c\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.705\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%Self.ab9) {\n// CHECK:STDOUT:   %Self => constants.%Self.ab9\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.d31\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.fa0\n// CHECK:STDOUT:   %.loc16_36.1 => constants.%.e46\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.f37\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.b05\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%I.facet) {\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%i32\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7ce\n// CHECK:STDOUT:   %.loc16_36.1 => constants.%.ff5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/builtin/positional.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/builtin/positional.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/builtin/positional.carbon\n\n// --- fail_positional.carbon\n\n// CHECK:STDERR: fail_positional.carbon:[[@LINE+8]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo]\n// CHECK:STDERR: fn Add -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_positional.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.sadd\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Add -> i32 = \"int.sadd\";\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Add -> i32 = \"int.sadd\";\n\n// CHECK:STDERR: fail_positional.carbon:[[@LINE+8]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo]\n// CHECK:STDERR: fn Mul = \"int.smul\";\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_positional.carbon:[[@LINE+4]]:1: error: invalid signature for builtin function \"int.smul\" [InvalidBuiltinSignature]\n// CHECK:STDERR: fn Mul = \"int.smul\";\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn Mul = \"int.smul\";\n\n// CHECK:STDOUT: --- fail_positional.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Add.type: type = fn_type @Add [concrete]\n// CHECK:STDOUT:   %Add: %Add.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Mul.type: type = fn_type @Mul [concrete]\n// CHECK:STDOUT:   %Mul: %Mul.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Add = %Add.decl\n// CHECK:STDOUT:     .Mul = %Mul.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Add.decl: %Add.type = fn_decl @Add [concrete = constants.%Add] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc10: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Mul.decl: %Mul.type = fn_decl @Mul [concrete = constants.%Mul] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Add() -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Mul;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/alias.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/alias.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/alias.carbon\n\nfn A() -> () { return (); }\n\nalias B = A;\n\nfn Main() {\n  var unused b: () = B();\n}\n\n// CHECK:STDOUT: --- alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc15_12.2: type = converted %.loc15_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc15_12.3: Core.Form = init_form %.loc15_12.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, %A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %B: %A.type = alias_binding B, %A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc15_24.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc15_24.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc15_25: init %empty_tuple.type = converted %.loc15_24.1, %.loc15_24.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   return %.loc15_25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.cb1 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.cb1 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %empty_tuple.type = var %b.var_patt\n// CHECK:STDOUT:   %B.ref: %A.type = name_ref B, file.%B [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %B.ref()\n// CHECK:STDOUT:   assign %b.var, %A.call\n// CHECK:STDOUT:   %.loc20_18.1: type = splice_block %.loc20_18.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc20_18.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc20_18.3: type = converted %.loc20_18.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %empty_tuple.type = ref_binding b, %b.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %b.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%b.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %empty_tuple.type) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/empty_struct.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/empty_struct.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/empty_struct.carbon\n\nfn Echo(a: {}) -> {} {\n  return a;\n}\n\nfn Main() {\n  Echo({});\n}\n\n// CHECK:STDOUT: --- empty_struct.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.469: Core.Form = init_form %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Echo.type: type = fn_type @Echo [concrete]\n// CHECK:STDOUT:   %Echo: %Echo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Echo = %Echo.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Echo.decl: %Echo.type = fn_decl @Echo [concrete = constants.%Echo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_20.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc15_20.2: type = converted %.loc15_20.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %.loc15_20.3: Core.Form = init_form %.loc15_20.2 [concrete = constants.%.469]\n// CHECK:STDOUT:     %a.param: %empty_struct_type = value_param call_param0\n// CHECK:STDOUT:     %.loc15_13.1: type = splice_block %.loc15_13.3 [concrete = constants.%empty_struct_type] {\n// CHECK:STDOUT:       %.loc15_13.2: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc15_13.3: type = converted %.loc15_13.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %empty_struct_type = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %empty_struct_type = out_param call_param1\n// CHECK:STDOUT:     %return: ref %empty_struct_type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Echo(%a.param: %empty_struct_type) -> out %return.param: %empty_struct_type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %empty_struct_type = name_ref a, %a\n// CHECK:STDOUT:   %.loc16_10: init %empty_struct_type = struct_init () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc16_11: init %empty_struct_type = converted %a.ref, %.loc16_10 [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   return %.loc16_11\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Echo.ref: %Echo.type = name_ref Echo, file.%Echo.decl [concrete = constants.%Echo]\n// CHECK:STDOUT:   %.loc20_9.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc20_9.2: %empty_struct_type = converted %.loc20_9.1, %empty_struct [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Echo.call: init %empty_struct_type = call %Echo.ref(%.loc20_9.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/empty_tuple.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/empty_tuple.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/empty_tuple.carbon\n\nfn Echo(a: ()) -> () {\n  return a;\n}\n\nfn Main() {\n  Echo(());\n}\n\n// CHECK:STDOUT: --- empty_tuple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Echo.type: type = fn_type @Echo [concrete]\n// CHECK:STDOUT:   %Echo: %Echo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Echo = %Echo.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Echo.decl: %Echo.type = fn_decl @Echo [concrete = constants.%Echo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_20.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc15_20.2: type = converted %.loc15_20.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc15_20.3: Core.Form = init_form %.loc15_20.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %a.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc15_13.1: type = splice_block %.loc15_13.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc15_13.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc15_13.3: type = converted %.loc15_13.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %empty_tuple.type = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param1\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Echo(%a.param: %empty_tuple.type) -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %empty_tuple.type = name_ref a, %a\n// CHECK:STDOUT:   %.loc16_10: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc16_11: init %empty_tuple.type = converted %a.ref, %.loc16_10 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   return %.loc16_11\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Echo.ref: %Echo.type = name_ref Echo, file.%Echo.decl [concrete = constants.%Echo]\n// CHECK:STDOUT:   %.loc20_9.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc20_9.2: %empty_tuple.type = converted %.loc20_9.1, %empty_tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %Echo.call: init %empty_tuple.type = call %Echo.ref(%.loc20_9.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/eval_musteval.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/eval_musteval.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/eval_musteval.carbon\n\n// --- no_eval.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Basic(unused n: i32) {}\neval fn Eval(unused n: i32) {}\n\nfn RuntimeArg(n: i32) {\n  Basic(n);\n  Eval(n);\n}\n\n// --- fail_no_eval_musteval.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nmusteval fn MustEval(unused n: i32) {}\n\nfn RuntimeArg(n: i32) {\n  // CHECK:STDERR: fail_no_eval_musteval.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   MustEval(n);\n  // CHECK:STDERR:   ^~~~~~~~~~~\n  // CHECK:STDERR: fail_no_eval_musteval.carbon:[[@LINE-6]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: musteval fn MustEval(unused n: i32) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  MustEval(n);\n}\n\n// --- eval.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Basic(unused n: i32) {}\neval fn Eval(unused n: i32) {}\nmusteval fn MustEval(unused n: i32) {}\n\nfn CompileTimeArg() {\n  Basic(1);\n  Eval(1);\n  MustEval(1);\n}\n\n// --- fail_todo_musteval_calls_musteval.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nmusteval fn MustEval(unused n: i32) {}\n\n// TODO: This should be accepted.\nmusteval fn CallMustEval(n: i32) {\n  // CHECK:STDERR: fail_todo_musteval_calls_musteval.carbon:[[@LINE+7]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   MustEval(n);\n  // CHECK:STDERR:   ^~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_musteval_calls_musteval.carbon:[[@LINE-7]]:1: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR: musteval fn MustEval(unused n: i32) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  MustEval(n);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/fail_explicit_self_param.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/fail_explicit_self_param.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/fail_explicit_self_param.carbon\n\n// CHECK:STDERR: fail_explicit_self_param.carbon:[[@LINE+4]]:6: error: `self` can only be declared in an implicit parameter list [SelfOutsideImplicitParamList]\n// CHECK:STDERR: fn F(self: ());\n// CHECK:STDERR:      ^~~~~~~~\n// CHECK:STDERR:\nfn F(self: ());\n\nfn Run() {\n  F(());\n}\n\n// CHECK:STDOUT: --- fail_explicit_self_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc19_13.1: type = splice_block %.loc19_13.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc19_13.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc19_13.3: type = converted %.loc19_13.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self: %empty_tuple.type = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%self.param: %empty_tuple.type);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc22_6.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc22_6.2: %empty_tuple.type = converted %.loc22_6.1, %empty_tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref(%.loc22_6.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/fail_not_callable.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/fail_not_callable.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/fail_not_callable.carbon\n\nfn Run() {\n  // CHECK:STDERR: fail_not_callable.carbon:[[@LINE+4]]:23: error: value of type `str` is not callable [CallToNonCallable]\n  // CHECK:STDERR:   var unused x: i32 = \"hello\"();\n  // CHECK:STDERR:                       ^~~~~~~~~\n  // CHECK:STDERR:\n  var unused x: i32 = \"hello\"();\n}\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/fail_param_count.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/fail_param_count.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/fail_param_count.carbon\n\nfn Run0() {}\nfn Run1(unused a: i32) {}\nfn Run2(unused a: i32, unused b: i32) {}\n\nfn Main() {\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+7]]:3: error: 1 argument passed to function expecting 0 arguments [CallArgCountMismatch]\n  // CHECK:STDERR:   Run0(1);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-8]]:1: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR: fn Run0() {}\n  // CHECK:STDERR: ^~~~~~~~~~~\n  // CHECK:STDERR:\n  Run0(1);\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+7]]:3: error: 2 arguments passed to function expecting 0 arguments [CallArgCountMismatch]\n  // CHECK:STDERR:   Run0(0, 1);\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-16]]:1: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR: fn Run0() {}\n  // CHECK:STDERR: ^~~~~~~~~~~\n  // CHECK:STDERR:\n  Run0(0, 1);\n\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+7]]:3: error: 0 arguments passed to function expecting 1 argument [CallArgCountMismatch]\n  // CHECK:STDERR:   Run1();\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-24]]:1: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR: fn Run1(unused a: i32) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Run1();\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+7]]:3: error: 2 arguments passed to function expecting 1 argument [CallArgCountMismatch]\n  // CHECK:STDERR:   Run1(0, 1);\n  // CHECK:STDERR:   ^~~~~~~~~~\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-32]]:1: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR: fn Run1(unused a: i32) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Run1(0, 1);\n\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+7]]:3: error: 0 arguments passed to function expecting 2 arguments [CallArgCountMismatch]\n  // CHECK:STDERR:   Run2();\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-40]]:1: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR: fn Run2(unused a: i32, unused b: i32) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Run2();\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE+7]]:3: error: 1 argument passed to function expecting 2 arguments [CallArgCountMismatch]\n  // CHECK:STDERR:   Run2(0);\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR: fail_param_count.carbon:[[@LINE-48]]:1: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR: fn Run2(unused a: i32, unused b: i32) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Run2(0);\n}\n\n// CHECK:STDOUT: --- fail_param_count.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Run0.type: type = fn_type @Run0 [concrete]\n// CHECK:STDOUT:   %Run0: %Run0.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Run1.type: type = fn_type @Run1 [concrete]\n// CHECK:STDOUT:   %Run1: %Run1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Run2.type: type = fn_type @Run2 [concrete]\n// CHECK:STDOUT:   %Run2: %Run2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Run0 = %Run0.decl\n// CHECK:STDOUT:     .Run1 = %Run1.decl\n// CHECK:STDOUT:     .Run2 = %Run2.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Run0.decl: %Run0.type = fn_decl @Run0 [concrete = constants.%Run0] {} {}\n// CHECK:STDOUT:   %Run1.decl: %Run1.type = fn_decl @Run1 [concrete = constants.%Run1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Run2.decl: %Run2.type = fn_decl @Run2 [concrete = constants.%Run2] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc17_19: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc17_34: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run0() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run1(%a.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run2(%a.param: %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Run0.ref.loc27: %Run0.type = name_ref Run0, file.%Run0.decl [concrete = constants.%Run0]\n// CHECK:STDOUT:   %int_1.loc27: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %Run0.ref.loc35: %Run0.type = name_ref Run0, file.%Run0.decl [concrete = constants.%Run0]\n// CHECK:STDOUT:   %int_0.loc35: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %int_1.loc35: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %Run1.ref.loc44: %Run1.type = name_ref Run1, file.%Run1.decl [concrete = constants.%Run1]\n// CHECK:STDOUT:   %Run1.ref.loc52: %Run1.type = name_ref Run1, file.%Run1.decl [concrete = constants.%Run1]\n// CHECK:STDOUT:   %int_0.loc52: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %int_1.loc52: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %Run2.ref.loc61: %Run2.type = name_ref Run2, file.%Run2.decl [concrete = constants.%Run2]\n// CHECK:STDOUT:   %Run2.ref.loc69: %Run2.type = name_ref Run2, file.%Run2.decl [concrete = constants.%Run2]\n// CHECK:STDOUT:   %int_0.loc69: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/fail_param_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/fail_param_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/fail_param_type.carbon\n\nfn G(unused a: i32) {}\n\nfn F() {\n  // CHECK:STDERR: fail_param_type.carbon:[[@LINE+10]]:5: error: cannot implicitly convert expression of type `Core.FloatLiteral` to `i32` [ConversionFailure]\n  // CHECK:STDERR:   G(1.0);\n  // CHECK:STDERR:     ^~~\n  // CHECK:STDERR: fail_param_type.carbon:[[@LINE+7]]:5: note: type `Core.FloatLiteral` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   G(1.0);\n  // CHECK:STDERR:     ^~~\n  // CHECK:STDERR: fail_param_type.carbon:[[@LINE-9]]:13: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn G(unused a: i32) {}\n  // CHECK:STDERR:             ^~~~~~\n  // CHECK:STDERR:\n  G(1.0);\n}\n\n// CHECK:STDOUT: --- fail_param_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%a.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float]\n// CHECK:STDOUT:   %.loc28: %i32 = converted %float, <error> [concrete = <error>]\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.ref(<error>)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/fail_return_type_mismatch.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/fail_return_type_mismatch.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/fail_return_type_mismatch.carbon\n\nfn Foo() -> f64 { return 1.0; }\n\nfn Run() {\n  // CHECK:STDERR: fail_return_type_mismatch.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `f64` to `i32` [ConversionFailure]\n  // CHECK:STDERR:   var unused x: i32 = Foo();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_return_type_mismatch.carbon:[[@LINE+4]]:3: note: type `f64` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var unused x: i32 = Foo();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused x: i32 = Foo();\n}\n\n// CHECK:STDOUT: --- fail_return_type_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]\n// CHECK:STDOUT:   %f64.d77: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %.49c: Core.Form = init_form %f64.d77 [concrete]\n// CHECK:STDOUT:   %pattern_type.0ae: type = pattern_type %f64.d77 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %float.6da: Core.FloatLiteral = float_literal_value 10e-1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.4a8: type = facet_type <@ImplicitAs, @ImplicitAs(%f64.d77)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.cb2: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.31a, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7: type = fn_type @Core.FloatLiteral.as.ImplicitAs.impl.Convert, @Core.FloatLiteral.as.ImplicitAs.impl(%int_64) [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239: %Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.2c7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.4a8 = facet_value Core.FloatLiteral, (%ImplicitAs.impl_witness.cb2) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.a33: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%f64.d77, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.6c5: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.a33, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239 [concrete]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.FloatLiteral.as.ImplicitAs.impl.Convert.239, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(%int_64) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %float.6da, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %float.d20: %f64.d77 = float_value 1 [concrete]\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Float = %Core.Float\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.38a: @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type (%Core.FloatLiteral.as.ImplicitAs.impl.Convert.type.02f) = import_ref Core//prelude/parts/float, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.FloatLiteral.as.ImplicitAs.impl.%Core.FloatLiteral.as.ImplicitAs.impl.Convert (constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.1f0)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.31a = impl_witness_table (%Core.import_ref.38a), @Core.FloatLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.0ae = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.0ae = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %f64: type = type_literal constants.%f64.d77 [concrete = constants.%f64.d77]\n// CHECK:STDOUT:     %.loc15_13: Core.Form = init_form %f64 [concrete = constants.%.49c]\n// CHECK:STDOUT:     %return.param: ref %f64.d77 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %f64.d77 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo() -> out %return.param: %f64.d77 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %float: Core.FloatLiteral = float_literal_value 10e-1 [concrete = constants.%float.6da]\n// CHECK:STDOUT:   %impl.elem0: %.6c5 = impl_witness_access constants.%ImplicitAs.impl_witness.cb2, element0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.239]\n// CHECK:STDOUT:   %bound_method.loc15_29.1: <bound method> = bound_method %float, %impl.elem0 [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.FloatLiteral.as.ImplicitAs.impl.Convert(constants.%int_64) [concrete = constants.%Core.FloatLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_29.2: <bound method> = bound_method %float, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call: init %f64.d77 = call %bound_method.loc15_29.2(%float) [concrete = constants.%float.d20]\n// CHECK:STDOUT:   %.loc15_29: init %f64.d77 = converted %float, %Core.FloatLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%float.d20]\n// CHECK:STDOUT:   return %.loc15_29\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type.7ce = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %i32 = var %x.var_patt\n// CHECK:STDOUT:   %Foo.ref: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]\n// CHECK:STDOUT:   %Foo.call: init %f64.d77 = call %Foo.ref()\n// CHECK:STDOUT:   %.loc25: %i32 = converted %Foo.call, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign %x.var, <error>\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %x: ref %i32 = ref_binding x, %x.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %x.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%x.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/fail_runtime_implicit_param.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/fail_runtime_implicit_param.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/fail_runtime_implicit_param.carbon\n\n// CHECK:STDERR: fail_runtime_implicit_param.carbon:[[@LINE+4]]:6: error: implicit parameters of functions must be constant or `self` [ImplictParamMustBeConstant]\n// CHECK:STDERR: fn F[s: ()]();\n// CHECK:STDERR:      ^~~~~\n// CHECK:STDERR:\nfn F[s: ()]();\n\nfn Run() {\n  F();\n}\n\n// CHECK:STDOUT: --- fail_runtime_implicit_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Run.type: type = fn_type @Run [concrete]\n// CHECK:STDOUT:   %Run: %Run.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .Run = %Run.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %Run.decl: %Run.type = fn_decl @Run [concrete = constants.%Run] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Run() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/form.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/form.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/form.carbon\n\n// --- ref_form_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F(x:? form(ref i32));\n//@dump-sem-ir-end\n\nfn G() {\n  var y: i32 = 0;\n  //@dump-sem-ir-begin\n  F(ref y);\n  //@dump-sem-ir-end\n}\n\n// --- var_form_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F(x:? form(var i32));\n//@dump-sem-ir-end\n\nfn G() {\n  //@dump-sem-ir-begin\n  F(0);\n  //@dump-sem-ir-end\n}\n\n// --- val_form_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F(x:? form(val i32));\n//@dump-sem-ir-end\n\nfn G() {\n  //@dump-sem-ir-begin\n  F(0);\n  //@dump-sem-ir-end\n}\n\n// --- type_component_needs_conversion.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F(x:? form(ref ()));\n//@dump-sem-ir-end\n\n// --- fail_param_form_not_constant.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() -> Core.Form();\n// CHECK:STDERR: fail_param_form_not_constant.carbon:[[@LINE+4]]:10: error: cannot evaluate form expression [FormExprEvaluationFailure]\n// CHECK:STDERR: fn G(x:? F());\n// CHECK:STDERR:          ^~~\n// CHECK:STDERR:\nfn G(x:? F());\n\n// --- fail_form_param_not_form.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_form_param_not_form.carbon:[[@LINE+7]]:10: error: cannot implicitly convert expression of type `type` to `Core.Form` [ConversionFailure]\n// CHECK:STDERR: fn F(x:? i32);\n// CHECK:STDERR:          ^~~\n// CHECK:STDERR: fail_form_param_not_form.carbon:[[@LINE+4]]:10: note: type `type` does not implement interface `Core.ImplicitAs(Core.Form)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: fn F(x:? i32);\n// CHECK:STDERR:          ^~~\n// CHECK:STDERR:\nfn F(x:? i32);\n// CHECK:STDERR: fail_form_param_not_form.carbon:[[@LINE+8]]:6: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n// CHECK:STDERR: fn G(ref x:? i32);\n// CHECK:STDERR:      ^~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_form_param_not_form.carbon:[[@LINE+4]]:6: error: expected `:` binding after `ref` [ExpectedRuntimeBindingPatternAfterRef]\n// CHECK:STDERR: fn G(ref x:? i32);\n// CHECK:STDERR:      ^~~\n// CHECK:STDERR:\nfn G(ref x:? i32);\n\n// --- fail_missing_ref_tag.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(x:? form(ref i32));\n\nfn G() {\n  var y: i32 = 0;\n  // CHECK:STDERR: fail_missing_ref_tag.carbon:[[@LINE+7]]:5: error: argument to `ref` parameter not marked with `ref` [RefParamNoRefTag]\n  // CHECK:STDERR:   F(y);\n  // CHECK:STDERR:     ^\n  // CHECK:STDERR: fail_missing_ref_tag.carbon:[[@LINE-7]]:6: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn F(x:? form(ref i32));\n  // CHECK:STDERR:      ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  F(y);\n}\n\n// --- fail_todo_form_generic_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_todo_form_generic_param.carbon:[[@LINE+4]]:26: error: semantics TODO: `Support symbolic form bindings` [SemanticsTodo]\n// CHECK:STDERR: fn F(Form:! Core.Form(), x:? Form);\n// CHECK:STDERR:                          ^~~~~~~~\n// CHECK:STDERR:\nfn F(Form:! Core.Form(), x:? Form);\n\nfn G() {\n  var x: i32;\n  F(form(var i32), x);\n}\n\n// --- fail_todo_local_init_form_binding.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {\n  // CHECK:STDERR: fail_todo_local_init_form_binding.carbon:[[@LINE+12]]:7: error: semantics TODO: `Support local initializing forms` [SemanticsTodo]\n  // CHECK:STDERR:   let x:? form(var i32) = 0;\n  // CHECK:STDERR:       ^\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_todo_local_init_form_binding.carbon:[[@LINE+8]]:27: error: cannot bind durable reference to non-reference value of type `i32` [ConversionFailureNonRefToRef]\n  // CHECK:STDERR:   let x:? form(var i32) = 0;\n  // CHECK:STDERR:                           ^\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_todo_local_init_form_binding.carbon:[[@LINE+4]]:7: warning: binding `x` unused [UnusedBinding]\n  // CHECK:STDERR:   let x:? form(var i32) = 0;\n  // CHECK:STDERR:       ^\n  // CHECK:STDERR:\n  let x:? form(var i32) = 0;\n}\n\n// --- fail_todo_local_symbolic_form_binding.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: this code should fail for a different reason, but right now we don't\n// have a way to write correct code that reaches the TODO we're exercising here.\nfn F(Form:! Core.Form()) {\n  // CHECK:STDERR: fail_todo_local_symbolic_form_binding.carbon:[[@LINE+4]]:7: error: semantics TODO: `Support symbolic form bindings` [SemanticsTodo]\n  // CHECK:STDERR:   let y:? Form = 0;\n  // CHECK:STDERR:       ^~~~~~~~\n  // CHECK:STDERR:\n  let y:? Form = 0;\n}\n\n// --- ref_return_form.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F() ->? form(ref i32);\n//@dump-sem-ir-end\n\nfn G() {\n  //@dump-sem-ir-begin\n  let ref _: i32 = F();\n  //@dump-sem-ir-end\n}\n\n// --- var_return_form.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F() ->? form(var i32);\n//@dump-sem-ir-end\n\nfn G() {\n  //@dump-sem-ir-begin\n  let var _: i32 = F();\n  //@dump-sem-ir-end\n}\n\n// --- val_return_form.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F() ->? form(val i32);\n//@dump-sem-ir-end\n\nfn G() {\n  //@dump-sem-ir-begin\n  let _: i32 = F();\n  //@dump-sem-ir-end\n}\n\n// --- fail_return_form_not_form.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_return_form_not_form.carbon:[[@LINE+7]]:12: error: cannot implicitly convert expression of type `type` to `Core.Form` [ConversionFailure]\n// CHECK:STDERR: fn F() ->? i32;\n// CHECK:STDERR:            ^~~\n// CHECK:STDERR: fail_return_form_not_form.carbon:[[@LINE+4]]:12: note: type `type` does not implement interface `Core.ImplicitAs(Core.Form)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: fn F() ->? i32;\n// CHECK:STDERR:            ^~~\n// CHECK:STDERR:\nfn F() ->? i32;\n// CHECK:STDERR: fail_return_form_not_form.carbon:[[@LINE+11]]:12: error: `ref` tag is not an argument to a `ref` parameter [RefTagNoRefParam]\n// CHECK:STDERR: fn F() ->? ref i32;\n// CHECK:STDERR:            ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_return_form_not_form.carbon:[[@LINE+7]]:12: error: cannot implicitly convert expression of type `type` to `Core.Form` [ConversionFailure]\n// CHECK:STDERR: fn F() ->? ref i32;\n// CHECK:STDERR:            ^~~~~~~\n// CHECK:STDERR: fail_return_form_not_form.carbon:[[@LINE+4]]:12: note: type `type` does not implement interface `Core.ImplicitAs(Core.Form)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: fn F() ->? ref i32;\n// CHECK:STDERR:            ^~~~~~~\n// CHECK:STDERR:\nfn F() ->? ref i32;\n\n// -- fail_todo_form_generic_return.carbon\n\n// CHECK:STDERR: fail_return_form_not_form.carbon:[[@LINE+11]]:26: error: semantics TODO: `Support symbolic return forms` [SemanticsTodo]\n// CHECK:STDERR: fn F(Form:! Core.Form()) ->? Form;\n// CHECK:STDERR:                          ^~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_return_form_not_form.carbon:[[@LINE+7]]:1: error: redeclaration differs because of parameter count of 1 [RedeclParamCountDiffers]\n// CHECK:STDERR: fn F(Form:! Core.Form()) ->? Form;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_return_form_not_form.carbon:[[@LINE-23]]:1: note: previously declared with parameter count of 0 [RedeclParamCountPrevious]\n// CHECK:STDERR: fn F() ->? i32;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(Form:! Core.Form()) ->? Form;\n\n// CHECK:STDOUT: --- ref_form_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.1da: Core.Form = ref_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = form_binding_pattern x [concrete]\n// CHECK:STDOUT:     %.loc4_7: %pattern_type.7ce = form_param_pattern %x.patt, constants.%.1da [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: ref %i32 = ref_param call_param0\n// CHECK:STDOUT:     %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.1da] {\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc4_15.2: Core.Form = ref_form %i32 [concrete = constants.%.1da]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: ref %i32 = form_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%x.param: ref %i32);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %y.ref: ref %i32 = name_ref y, %y\n// CHECK:STDOUT:   %.loc10: %i32 = ref_tag %y.ref\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref(%.loc10)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- var_form_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = form_binding_pattern x [concrete]\n// CHECK:STDOUT:     %.loc4_7: %pattern_type.7ce = form_param_pattern %x.patt, constants.%.ff5 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: ref %i32 = ref_param call_param0\n// CHECK:STDOUT:     %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.ff5] {\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc4_15.2: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: ref %i32 = form_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%x.param: ref %i32);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %.loc4_7.1: ref %i32 = temporary_storage\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc4_7.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc4_7.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc4_7.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc4_7.2: init %i32 = converted %int_0, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc4_7.3: ref %i32 = temporary %.loc4_7.1, %.loc4_7.2\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref(%.loc4_7.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc4_7.3, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc4_7.3)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- val_form_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.754: Core.Form = value_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = form_binding_pattern x [concrete]\n// CHECK:STDOUT:     %.loc4_7: %pattern_type.7ce = form_param_pattern %x.patt, constants.%.754 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.754] {\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc4_15.2: Core.Form = value_form %i32 [concrete = constants.%.754]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: %i32 = form_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%x.param: %i32);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc9_5.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc9_5.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc9_5.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc9_5.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc9_5.2: %i32 = converted %int_0, %.loc9_5.1 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref(%.loc9_5.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- type_component_needs_conversion.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %.9f9: Core.Form = ref_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type = form_binding_pattern x [concrete]\n// CHECK:STDOUT:     %.loc4_7: %pattern_type = form_param_pattern %x.patt, constants.%.9f9 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: ref %empty_tuple.type = ref_param call_param0\n// CHECK:STDOUT:     %.loc4_15.1: Core.Form = splice_block %.loc4_15.2 [concrete = constants.%.9f9] {\n// CHECK:STDOUT:       %.loc4_20.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc4_20.2: type = converted %.loc4_20.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.loc4_15.2: Core.Form = ref_form %.loc4_20.2 [concrete = constants.%.9f9]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: ref %empty_tuple.type = form_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%x.param: ref %empty_tuple.type);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- ref_return_form.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.1da: Core.Form = ref_form %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4: Core.Form = ref_form %i32 [concrete = constants.%.1da]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> ref %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %_.patt: %pattern_type.7ce = ref_binding_pattern _ [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: ref %i32 = call %F.ref()\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %_: ref %i32 = ref_binding _, %F.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- var_return_form.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %_.patt: %pattern_type.7ce = ref_binding_pattern _ [concrete]\n// CHECK:STDOUT:     %_.var_patt: %pattern_type.7ce = var_pattern %_.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %_.var: ref %i32 = var %_.var_patt\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.ref()\n// CHECK:STDOUT:   assign %_.var, %F.call\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %_: ref %i32 = ref_binding _, %_.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %_.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%_.var)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- val_return_form.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.754: Core.Form = value_form %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4: Core.Form = value_form %i32 [concrete = constants.%.754]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> val %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %_.patt: %pattern_type.7ce = value_binding_pattern _ [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: %i32 = call %F.ref()\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %_: %i32 = value_binding _, %F.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/i32.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/i32.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/i32.carbon\n\nfn Echo(a: i32) -> i32 {\n  return a;\n}\n\nfn Main() {\n  var unused b: i32 = Echo(1);\n}\n\n// CHECK:STDOUT: --- i32.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Echo.type: type = fn_type @Echo [concrete]\n// CHECK:STDOUT:   %Echo: %Echo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Echo = %Echo.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Echo.decl: %Echo.type = fn_decl @Echo [concrete = constants.%Echo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc15_20: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15: Core.Form = init_form %i32.loc15_20 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc15_12: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Echo(%a.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc16_10.1: <bound method> = bound_method %a.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_10.2: <bound method> = bound_method %a.ref, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc16_10.2(%a.ref)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt\n// CHECK:STDOUT:   %Echo.ref: %Echo.type = name_ref Echo, file.%Echo.decl [concrete = constants.%Echo]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc20_28.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc20_28.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc20_28.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc20_28.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc20_28.2: %i32 = converted %int_1, %.loc20_28.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %Echo.call: init %i32 = call %Echo.ref(%.loc20_28.2)\n// CHECK:STDOUT:   assign %b.var, %Echo.call\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %b.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%b.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/more_param_ir.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/more_param_ir.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/more_param_ir.carbon\n\nfn Foo(unused a: i32, unused b: i32) {}\n\nfn Main() {\n  var x: (i32,) = (1,);\n  // Generates multiple IR instructions for the first parameter.\n  Foo(x.0, 6);\n}\n\n// CHECK:STDOUT: --- more_param_ir.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple.896: %tuple.type.85c = tuple_value (%i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.b74: type = pattern_type %tuple.type.a1c [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.378: %tuple.type.985 = tuple_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %tuple.246: %tuple.type.a1c = tuple_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %int_6.462: Core.IntLiteral = int_value 6 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.502: <bound method> = bound_method %int_6.462, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.bc2: <bound method> = bound_method %int_6.462, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_6.e56: %i32 = int_value 6 [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc15_18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc15_33: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.b74 = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type.b74 = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %tuple.type.a1c = var %x.var_patt\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc18_22.1: %tuple.type.985 = tuple_literal (%int_1) [concrete = constants.%tuple.378]\n// CHECK:STDOUT:   %impl.elem0.loc18: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_22.1: <bound method> = bound_method %int_1, %impl.elem0.loc18 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc18: <specific function> = specific_function %impl.elem0.loc18, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_22.2: <bound method> = bound_method %int_1, %specific_fn.loc18 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18: init %i32 = call %bound_method.loc18_22.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_22.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_22.3: init %tuple.type.a1c to %x.var = tuple_init (%.loc18_22.2) [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %.loc18_3: init %tuple.type.a1c = converted %.loc18_22.1, %.loc18_22.3 [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   assign %x.var, %.loc18_3\n// CHECK:STDOUT:   %.loc18_15.1: type = splice_block %.loc18_15.3 [concrete = constants.%tuple.type.a1c] {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc18_15.2: %tuple.type.85c = tuple_literal (%i32) [concrete = constants.%tuple.896]\n// CHECK:STDOUT:     %.loc18_15.3: type = converted %.loc18_15.2, constants.%tuple.type.a1c [concrete = constants.%tuple.type.a1c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: ref %tuple.type.a1c = ref_binding x, %x.var\n// CHECK:STDOUT:   %Foo.ref: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]\n// CHECK:STDOUT:   %x.ref: ref %tuple.type.a1c = name_ref x, %x\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %tuple.elem0: ref %i32 = tuple_access %x.ref, element0\n// CHECK:STDOUT:   %int_6: Core.IntLiteral = int_value 6 [concrete = constants.%int_6.462]\n// CHECK:STDOUT:   %.loc20_8: %i32 = acquire_value %tuple.elem0\n// CHECK:STDOUT:   %impl.elem0.loc20: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc20_12.1: <bound method> = bound_method %int_6, %impl.elem0.loc20 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.502]\n// CHECK:STDOUT:   %specific_fn.loc20: <specific function> = specific_function %impl.elem0.loc20, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc20_12.2: <bound method> = bound_method %int_6, %specific_fn.loc20 [concrete = constants.%bound_method.bc2]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc20: init %i32 = call %bound_method.loc20_12.2(%int_6) [concrete = constants.%int_6.e56]\n// CHECK:STDOUT:   %.loc20_12.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc20 [concrete = constants.%int_6.e56]\n// CHECK:STDOUT:   %.loc20_12.2: %i32 = converted %int_6, %.loc20_12.1 [concrete = constants.%int_6.e56]\n// CHECK:STDOUT:   %Foo.call: init %empty_tuple.type = call %Foo.ref(%.loc20_8, %.loc20_12.2)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %x.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%x.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %tuple.type.a1c) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/params_one.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/params_one.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/params_one.carbon\n\nfn Foo(unused a: i32) {}\n\nfn Main() {\n  Foo(1);\n}\n\n// CHECK:STDOUT: --- params_one.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Foo.ref: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_7.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_7.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc18_7.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_7.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_7.2: %i32 = converted %int_1, %.loc18_7.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %Foo.call: init %empty_tuple.type = call %Foo.ref(%.loc18_7.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/params_one_comma.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/params_one_comma.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/params_one_comma.carbon\n\nfn Foo(unused a: i32,) {}\n\nfn Main() {\n  Foo(1);\n  Foo(1,);\n}\n\n// CHECK:STDOUT: --- params_one_comma.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Foo.ref.loc18: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]\n// CHECK:STDOUT:   %int_1.loc18: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc18: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_7.1: <bound method> = bound_method %int_1.loc18, %impl.elem0.loc18 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc18: <specific function> = specific_function %impl.elem0.loc18, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_7.2: <bound method> = bound_method %int_1.loc18, %specific_fn.loc18 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18: init %i32 = call %bound_method.loc18_7.2(%int_1.loc18) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_7.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_7.2: %i32 = converted %int_1.loc18, %.loc18_7.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %Foo.call.loc18: init %empty_tuple.type = call %Foo.ref.loc18(%.loc18_7.2)\n// CHECK:STDOUT:   %Foo.ref.loc19: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]\n// CHECK:STDOUT:   %int_1.loc19: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc19: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc19_7.1: <bound method> = bound_method %int_1.loc19, %impl.elem0.loc19 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc19: <specific function> = specific_function %impl.elem0.loc19, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc19_7.2: <bound method> = bound_method %int_1.loc19, %specific_fn.loc19 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc19: init %i32 = call %bound_method.loc19_7.2(%int_1.loc19) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc19_7.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc19 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc19_7.2: %i32 = converted %int_1.loc19, %.loc19_7.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %Foo.call.loc19: init %empty_tuple.type = call %Foo.ref.loc19(%.loc19_7.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/params_two.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/params_two.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/params_two.carbon\n\nfn Foo(unused a: i32, unused b: i32) {}\n\nfn Main() {\n  Foo(1, 2);\n}\n\n// CHECK:STDOUT: --- params_two.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc15_18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc15_33: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Foo.ref: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc18_7: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_7.1: <bound method> = bound_method %int_1, %impl.elem0.loc18_7 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc18_7: <specific function> = specific_function %impl.elem0.loc18_7, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_7.2: <bound method> = bound_method %int_1, %specific_fn.loc18_7 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_7: init %i32 = call %bound_method.loc18_7.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_7.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_7 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_7.2: %i32 = converted %int_1, %.loc18_7.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc18_10: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_10.1: <bound method> = bound_method %int_2, %impl.elem0.loc18_10 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc18_10: <specific function> = specific_function %impl.elem0.loc18_10, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_10.2: <bound method> = bound_method %int_2, %specific_fn.loc18_10 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_10: init %i32 = call %bound_method.loc18_10.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_10.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_10 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_10.2: %i32 = converted %int_2, %.loc18_10.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %Foo.call: init %empty_tuple.type = call %Foo.ref(%.loc18_7.2, %.loc18_10.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/params_two_comma.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/params_two_comma.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/params_two_comma.carbon\n\nfn Foo(unused a: i32, unused b: i32,) {}\n\nfn Main() {\n  Foo(1, 2);\n  Foo(1, 2,);\n}\n\n// CHECK:STDOUT: --- params_two_comma.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc15_18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc15_33: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Foo.ref.loc18: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]\n// CHECK:STDOUT:   %int_1.loc18: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2.loc18: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc18_7: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_7.1: <bound method> = bound_method %int_1.loc18, %impl.elem0.loc18_7 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc18_7: <specific function> = specific_function %impl.elem0.loc18_7, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_7.2: <bound method> = bound_method %int_1.loc18, %specific_fn.loc18_7 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_7: init %i32 = call %bound_method.loc18_7.2(%int_1.loc18) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_7.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_7 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_7.2: %i32 = converted %int_1.loc18, %.loc18_7.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc18_10: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_10.1: <bound method> = bound_method %int_2.loc18, %impl.elem0.loc18_10 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc18_10: <specific function> = specific_function %impl.elem0.loc18_10, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_10.2: <bound method> = bound_method %int_2.loc18, %specific_fn.loc18_10 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_10: init %i32 = call %bound_method.loc18_10.2(%int_2.loc18) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_10.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_10 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_10.2: %i32 = converted %int_2.loc18, %.loc18_10.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %Foo.call.loc18: init %empty_tuple.type = call %Foo.ref.loc18(%.loc18_7.2, %.loc18_10.2)\n// CHECK:STDOUT:   %Foo.ref.loc19: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]\n// CHECK:STDOUT:   %int_1.loc19: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2.loc19: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc19_7: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc19_7.1: <bound method> = bound_method %int_1.loc19, %impl.elem0.loc19_7 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc19_7: <specific function> = specific_function %impl.elem0.loc19_7, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc19_7.2: <bound method> = bound_method %int_1.loc19, %specific_fn.loc19_7 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc19_7: init %i32 = call %bound_method.loc19_7.2(%int_1.loc19) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc19_7.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc19_7 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc19_7.2: %i32 = converted %int_1.loc19, %.loc19_7.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc19_10: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc19_10.1: <bound method> = bound_method %int_2.loc19, %impl.elem0.loc19_10 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc19_10: <specific function> = specific_function %impl.elem0.loc19_10, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc19_10.2: <bound method> = bound_method %int_2.loc19, %specific_fn.loc19_10 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc19_10: init %i32 = call %bound_method.loc19_10.2(%int_2.loc19) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc19_10.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc19_10 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc19_10.2: %i32 = converted %int_2.loc19, %.loc19_10.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %Foo.call.loc19: init %empty_tuple.type = call %Foo.ref.loc19(%.loc19_7.2, %.loc19_10.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/params_zero.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/params_zero.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/params_zero.carbon\n\nfn Foo() {}\n\nfn Main() {\n  Foo();\n}\n\n// CHECK:STDOUT: --- params_zero.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {} {}\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Foo.ref: %Foo.type = name_ref Foo, file.%Foo.decl [concrete = constants.%Foo]\n// CHECK:STDOUT:   %Foo.call: init %empty_tuple.type = call %Foo.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/prefer_unqualified_lookup.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/prefer_unqualified_lookup.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/prefer_unqualified_lookup.carbon\n\n// --- prefer_unqualified_lookup.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// F in the lexical scope.\nclass Class(F:! type) {\n  class Inner {\n    // F in a non-lexical scope.\n    fn F() -> i32 { return 0; }\n    fn G() -> i32;\n  }\n}\n\nfn Class(F:! type).Inner.G() -> i32 { return F(); }\n\n// CHECK:STDOUT: --- prefer_unqualified_lookup.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %F: type = symbolic_binding F, 0 [symbolic]\n// CHECK:STDOUT:   %Class.type: type = generic_class_type @Class [concrete]\n// CHECK:STDOUT:   %Class.generic: %Class.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Class: type = class_type @Class, @Class(%F) [symbolic]\n// CHECK:STDOUT:   %Inner: type = class_type @Inner, @Inner(%F) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Inner.F.type: type = fn_type @Inner.F, @Inner(%F) [symbolic]\n// CHECK:STDOUT:   %Inner.F: %Inner.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.G.type: type = fn_type @Inner.G, @Inner(%F) [symbolic]\n// CHECK:STDOUT:   %Inner.G: %Inner.G.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %Inner.F.specific_fn: <specific function> = specific_function %Inner.F, @Inner.F(%F) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Class = %Class.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Class.decl: %Class.type = class_decl @Class [concrete = constants.%Class.generic] {\n// CHECK:STDOUT:     %F.patt: %pattern_type.98f = symbolic_binding_pattern F, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_17.1: type = splice_block %.loc5_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc5_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %F.loc5_13.2: type = symbolic_binding F, 0 [symbolic = %F.loc5_13.1 (constants.%F)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Inner.G.decl: %Inner.G.type = fn_decl @Inner.G [symbolic = constants.%Inner.G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc13_14.1: type = splice_block %.loc13_14.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_14.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %F.loc13_10: type = symbolic_binding F, 0 [symbolic = @Class.%F.loc5_13.1 (constants.%F)]\n// CHECK:STDOUT:     %i32.loc13: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc13_33: Core.Form = init_form %i32.loc13 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param.loc13: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return.loc13: ref %i32 = return_slot %return.param.loc13\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Class(%F.loc5_13.2: type) {\n// CHECK:STDOUT:   %F.loc5_13.1: type = symbolic_binding F, 0 [symbolic = %F.loc5_13.1 (constants.%F)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner: type = class_type @Inner, @Inner(%F.loc5_13.1) [symbolic = %Inner (constants.%Inner)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Inner.decl: type = class_decl @Inner [symbolic = @Class.%Inner (constants.%Inner)] {} {}\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Class\n// CHECK:STDOUT:     .Inner = %Inner.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Inner(@Class.%F.loc5_13.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %F: type = symbolic_binding F, 0 [symbolic = %F (constants.%F)]\n// CHECK:STDOUT:   %Inner.F.type: type = fn_type @Inner.F, @Inner(%F) [symbolic = %Inner.F.type (constants.%Inner.F.type)]\n// CHECK:STDOUT:   %Inner.F: @Inner.%Inner.F.type (%Inner.F.type) = struct_value () [symbolic = %Inner.F (constants.%Inner.F)]\n// CHECK:STDOUT:   %Inner.G.type: type = fn_type @Inner.G, @Inner(%F) [symbolic = %Inner.G.type (constants.%Inner.G.type)]\n// CHECK:STDOUT:   %Inner.G: @Inner.%Inner.G.type (%Inner.G.type) = struct_value () [symbolic = %Inner.G (constants.%Inner.G)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Inner.F.decl: @Inner.%Inner.F.type (%Inner.F.type) = fn_decl @Inner.F [symbolic = @Inner.%Inner.F (constants.%Inner.F)] {\n// CHECK:STDOUT:       %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc8_15: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:       %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:       %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Inner.G.decl: @Inner.%Inner.G.type (%Inner.G.type) = fn_decl @Inner.G [symbolic = @Inner.%Inner.G (constants.%Inner.G)] {\n// CHECK:STDOUT:       %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %i32.loc9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc9: Core.Form = init_form %i32.loc9 [concrete = constants.%.ff5]\n// CHECK:STDOUT:       %return.param.loc9: ref %i32 = out_param call_param0\n// CHECK:STDOUT:       %return.loc9: ref %i32 = return_slot %return.param.loc9\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Inner\n// CHECK:STDOUT:     .F = %Inner.F.decl\n// CHECK:STDOUT:     .G = %Inner.G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Inner.F(@Class.%F.loc5_13.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:     %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc8_29.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc8_29.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc8_29.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:     %.loc8_29: init %i32 = converted %int_0, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:     return %.loc8_29\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Inner.G(@Class.%F.loc5_13.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %F.loc13_46: type = symbolic_binding F, 0 [symbolic = %F.loc13_46 (constants.%F)]\n// CHECK:STDOUT:   %Inner.F.type: type = fn_type @Inner.F, @Inner(%F.loc13_46) [symbolic = %Inner.F.type (constants.%Inner.F.type)]\n// CHECK:STDOUT:   %Inner.F: @Inner.G.%Inner.F.type (%Inner.F.type) = struct_value () [symbolic = %Inner.F (constants.%Inner.F)]\n// CHECK:STDOUT:   %Inner.F.specific_fn.loc13_46.2: <specific function> = specific_function %Inner.F, @Inner.F(%F.loc13_46) [symbolic = %Inner.F.specific_fn.loc13_46.2 (constants.%Inner.F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param.loc13: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc13_46: @Inner.G.%Inner.F.type (%Inner.F.type) = specific_constant @Inner.%Inner.F.decl, @Inner(constants.%F) [symbolic = %Inner.F (constants.%Inner.F)]\n// CHECK:STDOUT:     %F.ref: @Inner.G.%Inner.F.type (%Inner.F.type) = name_ref F, %.loc13_46 [symbolic = %Inner.F (constants.%Inner.F)]\n// CHECK:STDOUT:     %Inner.F.specific_fn.loc13_46.1: <specific function> = specific_function %F.ref, @Inner.F(constants.%F) [symbolic = %Inner.F.specific_fn.loc13_46.2 (constants.%Inner.F.specific_fn)]\n// CHECK:STDOUT:     %Inner.F.call: init %i32 = call %Inner.F.specific_fn.loc13_46.1()\n// CHECK:STDOUT:     return %Inner.F.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Class(constants.%F) {\n// CHECK:STDOUT:   %F.loc5_13.1 => constants.%F\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner => constants.%Inner\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%F) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %F => constants.%F\n// CHECK:STDOUT:   %Inner.F.type => constants.%Inner.F.type\n// CHECK:STDOUT:   %Inner.F => constants.%Inner.F\n// CHECK:STDOUT:   %Inner.G.type => constants.%Inner.G.type\n// CHECK:STDOUT:   %Inner.G => constants.%Inner.G\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.F(constants.%F) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.G(constants.%F) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/ref.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=only\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/ref.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/ref.carbon\n\n// --- basics.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F(ref x: i32);\n\nfn G() {\n  var y: i32 = 0;\n\n  F(ref y);\n}\n//@dump-sem-ir-end\n\n// --- class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nclass C {\n  fn F[ref self: Self]();\n}\n\nfn G() {\n  var c: C;\n\n  c.F();\n}\n//@dump-sem-ir-end\n\n// --- fail_ref_not_durable_ref.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(ref x: i32);\n\nfn G() {\n  let y: i32 = 0;\n  // CHECK:STDERR: fail_ref_not_durable_ref.carbon:[[@LINE+7]]:9: error: expression tagged with `ref` is not a durable reference [RefTagNotDurableRef]\n  // CHECK:STDERR:   F(ref y);\n  // CHECK:STDERR:         ^\n  // CHECK:STDERR: fail_ref_not_durable_ref.carbon:[[@LINE-7]]:6: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn F(ref x: i32);\n  // CHECK:STDERR:      ^~~~~~~~~~\n  // CHECK:STDERR:\n  F(ref y);\n}\n\n// --- fail_missing_ref.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(ref x: i32);\n\nfn G() {\n  var y: i32 = 0;\n  // CHECK:STDERR: fail_missing_ref.carbon:[[@LINE+7]]:5: error: argument to `ref` parameter not marked with `ref` [RefParamNoRefTag]\n  // CHECK:STDERR:   F(y);\n  // CHECK:STDERR:     ^\n  // CHECK:STDERR: fail_missing_ref.carbon:[[@LINE-7]]:6: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn F(ref x: i32);\n  // CHECK:STDERR:      ^~~~~~~~~~\n  // CHECK:STDERR:\n  F(y);\n}\n\n// --- fail_unnecessary_ref.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(x: i32);\n\nfn G() {\n  var y: i32 = 0;\n\n  // CHECK:STDERR: fail_unnecessary_ref.carbon:[[@LINE+4]]:27: error: `ref` tag is not an argument to a `ref` parameter [RefTagNoRefParam]\n  // CHECK:STDERR:   var unused z: (i32,) = (ref y,);\n  // CHECK:STDERR:                           ^~~~~\n  // CHECK:STDERR:\n  var unused z: (i32,) = (ref y,);\n  // CHECK:STDERR: fail_unnecessary_ref.carbon:[[@LINE+7]]:5: error: `ref` tag is not an argument to a `ref` parameter [RefTagNoRefParam]\n  // CHECK:STDERR:   F(ref y);\n  // CHECK:STDERR:     ^~~~~\n  // CHECK:STDERR: fail_unnecessary_ref.carbon:[[@LINE-13]]:6: note: initializing function parameter [InCallToFunctionParam]\n  // CHECK:STDERR: fn F(x: i32);\n  // CHECK:STDERR:      ^~~~~~\n  // CHECK:STDERR:\n  F(ref y);\n}\n\n// CHECK:STDOUT: --- basics.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.7ce = ref_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: ref %i32 = ref_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %x: ref %i32 = ref_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%x.param: ref %i32);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %y.patt: %pattern_type.7ce = ref_binding_pattern y [concrete]\n// CHECK:STDOUT:     %y.var_patt: %pattern_type.7ce = var_pattern %y.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %y.var: ref %i32 = var %y.var_patt\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc8_3.1: <bound method> = bound_method %int_0, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_3.2: <bound method> = bound_method %int_0, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc8_3.2(%int_0) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc8: init %i32 = converted %int_0, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   assign %y.var, %.loc8\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %y: ref %i32 = ref_binding y, %y.var\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %y.ref: ref %i32 = name_ref y, %y\n// CHECK:STDOUT:   %.loc10: %i32 = ref_tag %y.ref\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref(%.loc10)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %y.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%y.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.6fd: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%C) [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %C, (%DefaultOrUnformed.impl_witness.6fd) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %C.F.decl: %C.F.type = fn_decl @C.F [concrete = constants.%C.F] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.7c7 = ref_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.7c7 = ref_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: ref %C = ref_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %self: ref %C = ref_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .F = %C.F.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F(%self.param: ref %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.7c7 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%C, (constants.%DefaultOrUnformed.impl_witness.6fd) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc10_11.1: %DefaultOrUnformed.type = converted constants.%C, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc10_11.1 [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc10_11.2: type = converted %.loc10_11.1, %as_type [concrete = constants.%C]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %.loc10_3: ref %C = splice_block %c.var {}\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %C to %.loc10_3 = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign %c.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var\n// CHECK:STDOUT:   %c.ref: ref %C = name_ref c, %c\n// CHECK:STDOUT:   %F.ref: %C.F.type = name_ref F, @C.%C.F.decl [concrete = constants.%C.F]\n// CHECK:STDOUT:   %C.F.bound: <bound method> = bound_method %c.ref, %F.ref\n// CHECK:STDOUT:   %C.F.call: init %empty_tuple.type = call %C.F.bound(%c.ref)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %c.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%c.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/call/return_implicit.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/call/return_implicit.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/call/return_implicit.carbon\n\nfn MakeImplicitEmptyTuple() {\n}\n\nfn Main() {\n  var unused b: () = MakeImplicitEmptyTuple();\n}\n\n// CHECK:STDOUT: --- return_implicit.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %MakeImplicitEmptyTuple.type: type = fn_type @MakeImplicitEmptyTuple [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %MakeImplicitEmptyTuple: %MakeImplicitEmptyTuple.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Main.type: type = fn_type @Main [concrete]\n// CHECK:STDOUT:   %Main: %Main.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .MakeImplicitEmptyTuple = %MakeImplicitEmptyTuple.decl\n// CHECK:STDOUT:     .Main = %Main.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %MakeImplicitEmptyTuple.decl: %MakeImplicitEmptyTuple.type = fn_decl @MakeImplicitEmptyTuple [concrete = constants.%MakeImplicitEmptyTuple] {} {}\n// CHECK:STDOUT:   %Main.decl: %Main.type = fn_decl @Main [concrete = constants.%Main] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @MakeImplicitEmptyTuple() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Main() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.cb1 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.cb1 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %empty_tuple.type = var %b.var_patt\n// CHECK:STDOUT:   %MakeImplicitEmptyTuple.ref: %MakeImplicitEmptyTuple.type = name_ref MakeImplicitEmptyTuple, file.%MakeImplicitEmptyTuple.decl [concrete = constants.%MakeImplicitEmptyTuple]\n// CHECK:STDOUT:   %MakeImplicitEmptyTuple.call: init %empty_tuple.type = call %MakeImplicitEmptyTuple.ref()\n// CHECK:STDOUT:   assign %b.var, %MakeImplicitEmptyTuple.call\n// CHECK:STDOUT:   %.loc19_18.1: type = splice_block %.loc19_18.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc19_18.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc19_18.3: type = converted %.loc19_18.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %empty_tuple.type = ref_binding b, %b.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %b.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%b.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %empty_tuple.type) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/eval_musteval.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/eval_musteval.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/eval_musteval.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Basic() -> i32 { return 0; }\neval fn Eval() -> i32 { return 0; }\nmusteval fn MustEval() -> i32 { return 0; }\n\n// --- member.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  eval fn Eval() {}\n  musteval fn MustEval() {}\n}\n\n// --- private.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nprivate eval fn Eval() -> i32 { return 0; }\nprivate musteval fn MustEval() -> i32 { return 0; }\n\n// --- fail_conflict.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_conflict.carbon:[[@LINE+7]]:6: error: `musteval` not allowed on declaration with `eval` [ModifierNotAllowedWith]\n// CHECK:STDERR: eval musteval fn Mixed();\n// CHECK:STDERR:      ^~~~~~~~\n// CHECK:STDERR: fail_conflict.carbon:[[@LINE+4]]:1: note: `eval` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: eval musteval fn Mixed();\n// CHECK:STDERR: ^~~~\n// CHECK:STDERR:\neval musteval fn Mixed();\n\n// --- fail_order.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_order.carbon:[[@LINE+7]]:6: error: `export` must appear before `eval` [ModifierMustAppearBefore]\n// CHECK:STDERR: eval export fn ExportEval();\n// CHECK:STDERR:      ^~~~~~\n// CHECK:STDERR: fail_order.carbon:[[@LINE+4]]:1: note: `eval` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: eval export fn ExportEval();\n// CHECK:STDERR: ^~~~\n// CHECK:STDERR:\neval export fn ExportEval();\n\n// CHECK:STDERR: fail_order.carbon:[[@LINE+7]]:6: error: `private` must appear before `eval` [ModifierMustAppearBefore]\n// CHECK:STDERR: eval private fn PrivateEval();\n// CHECK:STDERR:      ^~~~~~~\n// CHECK:STDERR: fail_order.carbon:[[@LINE+4]]:1: note: `eval` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: eval private fn PrivateEval();\n// CHECK:STDERR: ^~~~\n// CHECK:STDERR:\neval private fn PrivateEval();\n\nclass C {\n  // CHECK:STDERR: fail_order.carbon:[[@LINE+7]]:8: error: `virtual` must appear before `eval` [ModifierMustAppearBefore]\n  // CHECK:STDERR:   eval virtual fn VirtualEval();\n  // CHECK:STDERR:        ^~~~~~~\n  // CHECK:STDERR: fail_order.carbon:[[@LINE+4]]:3: note: `eval` previously appeared here [ModifierPrevious]\n  // CHECK:STDERR:   eval virtual fn VirtualEval();\n  // CHECK:STDERR:   ^~~~\n  // CHECK:STDERR:\n  eval virtual fn VirtualEval();\n}\n\n// --- fail_not_fn.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_not_fn.carbon:[[@LINE+4]]:1: error: `eval` not allowed on `var` declaration [ModifierNotAllowedOnDeclaration]\n// CHECK:STDERR: eval var x: i32;\n// CHECK:STDERR: ^~~~\n// CHECK:STDERR:\neval var x: i32;\n\n// CHECK:STDERR: fail_not_fn.carbon:[[@LINE+4]]:1: error: `eval` not allowed on `class` declaration [ModifierNotAllowedOnDeclaration]\n// CHECK:STDERR: eval class C {};\n// CHECK:STDERR: ^~~~\n// CHECK:STDERR:\neval class C {};\n\n// --- redecl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\neval fn A() -> i32;\neval fn A() -> i32 { return 0; }\n\nmusteval fn B() -> i32;\nmusteval fn B() -> i32 { return 0; }\n\n// --- fail_differ_in_redecl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn NoneThenEval();\nfn NoneThenMustEval();\neval fn EvalThenNone();\neval fn EvalThenMustEval();\nmusteval fn MustEvalThenNone();\nmusteval fn MustEvalThenEval();\n\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE+7]]:1: error: function redeclaration differs because new function is `eval` [FunctionRedeclEvaluationModeDiffers]\n// CHECK:STDERR: eval fn NoneThenEval() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE-10]]:1: note: previously not declared as `eval` [FunctionRedeclEvaluationModePrevious]\n// CHECK:STDERR: fn NoneThenEval();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\neval fn NoneThenEval() {}\n\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE+7]]:1: error: function redeclaration differs because new function is `musteval` [FunctionRedeclEvaluationModeDiffers]\n// CHECK:STDERR: musteval fn NoneThenMustEval() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE-18]]:1: note: previously not declared as `musteval` [FunctionRedeclEvaluationModePrevious]\n// CHECK:STDERR: fn NoneThenMustEval();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nmusteval fn NoneThenMustEval() {}\n\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE+7]]:1: error: function redeclaration differs because new function is not `eval` [FunctionRedeclEvaluationModeDiffers]\n// CHECK:STDERR: fn EvalThenNone() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE-26]]:1: note: previously declared as `eval` [FunctionRedeclEvaluationModePrevious]\n// CHECK:STDERR: eval fn EvalThenNone();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn EvalThenNone() {}\n\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE+7]]:1: error: function redeclaration differs because new function is `musteval` [FunctionRedeclEvaluationModeDiffers]\n// CHECK:STDERR: musteval fn EvalThenMustEval() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE-34]]:1: note: previously declared as `eval` [FunctionRedeclEvaluationModePrevious]\n// CHECK:STDERR: eval fn EvalThenMustEval();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nmusteval fn EvalThenMustEval() {}\n\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE+7]]:1: error: function redeclaration differs because new function is not `musteval` [FunctionRedeclEvaluationModeDiffers]\n// CHECK:STDERR: fn MustEvalThenNone() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE-42]]:1: note: previously declared as `musteval` [FunctionRedeclEvaluationModePrevious]\n// CHECK:STDERR: musteval fn MustEvalThenNone();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn MustEvalThenNone() {}\n\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE+7]]:1: error: function redeclaration differs because new function is `eval` [FunctionRedeclEvaluationModeDiffers]\n// CHECK:STDERR: eval fn MustEvalThenEval() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_differ_in_redecl.carbon:[[@LINE-50]]:1: note: previously declared as `musteval` [FunctionRedeclEvaluationModePrevious]\n// CHECK:STDERR: musteval fn MustEvalThenEval();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\neval fn MustEvalThenEval() {}\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/export_name.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/export_name.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/export_name.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- base.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F();\n\n// --- export.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"base\";\n\nexport F;\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- use_export.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"export\";\n\nvar f: () = F();\n\n// CHECK:STDOUT: --- base.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- export.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//base, F, loaded [concrete = constants.%F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F: %F.type = export F, imports.%Main.F [concrete = constants.%F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F [from \"base.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_export.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//export, F, loaded [concrete = constants.%F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F [from \"export.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, imports.%Main.F [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   assign file.%f.var, %F.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/extern.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/extern.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/extern.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F();\n\n// --- basic_use.carbon\n\nimport library \"basic\";\n\nvar x: () = F();\n\n// --- fail_redecl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F();\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE+7]]:1: error: redeclaration of `fn F` is redundant [RedeclRedundant]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn F();\n\n// --- fail_redecl_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F();\n// CHECK:STDERR: fail_redecl_extern.carbon:[[@LINE+7]]:1: error: redeclaration of `fn F` is redundant [RedeclRedundant]\n// CHECK:STDERR: fn F();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR: fail_redecl_extern.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F();\n\n// --- fail_member_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  // CHECK:STDERR: fail_member_extern.carbon:[[@LINE+4]]:3: error: `extern` not allowed; requires file or namespace scope [ModifierExternNotAllowed]\n  // CHECK:STDERR:   extern fn F();\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR:\n  extern fn F();\n  // CHECK:STDERR: fail_member_extern.carbon:[[@LINE+4]]:3: error: `extern` not allowed; requires file or namespace scope [ModifierExternNotAllowed]\n  // CHECK:STDERR:   extern fn G[self: Self]();\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR:\n  extern fn G[self: Self]();\n}\n\n// --- fail_extern_library_in_importer.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"basic\";\n\n// CHECK:STDERR: fail_extern_library_in_importer.carbon:[[@LINE+8]]:1: error: cannot declare imported `fn F` as `extern library` [ExternLibraryInImporter]\n// CHECK:STDERR: extern library \"basic\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_library_in_importer.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: basic.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern library \"basic\" fn F();\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- basic_use.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//basic, F, loaded [concrete = constants.%F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %empty_tuple.type = var %x.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_9.1: type = splice_block %.loc4_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc4_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc4_9.3: type = converted %.loc4_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: ref %empty_tuple.type = ref_binding x, %x.var [concrete = %x.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F [from \"basic.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, imports.%Main.F [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   assign file.%x.var, %F.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_redecl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc4: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %F.decl.loc12: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_redecl_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc4: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %F.decl.loc12: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_member_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F [concrete]\n// CHECK:STDOUT:   %C.F: %C.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %C.G.type: type = fn_type @C.G [concrete]\n// CHECK:STDOUT:   %C.G: %C.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %C.F.decl: %C.F.type = fn_decl @C.F [concrete = constants.%C.F] {} {}\n// CHECK:STDOUT:   %C.G.decl: %C.G.type = fn_decl @C.G [concrete = constants.%C.G] {\n// CHECK:STDOUT:     %self.patt: %pattern_type = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %C = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %self: %C = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .F = %C.F.decl\n// CHECK:STDOUT:   .G = %C.G.decl\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.G(%self.param: %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_library_in_importer.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = invalid\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F [from \"basic.carbon\"];\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/extern_library.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/extern_library.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/extern_library.carbon\n\n// --- extern_library.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"extern_library_owner\" fn F();\n\n// --- extern_library_owner.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_library\";\n\nextern fn F();\n\n// --- fail_extern_library_nonowner.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_library\";\n\n// CHECK:STDERR: fail_extern_library_nonowner.carbon:[[@LINE+8]]:1: error: declaration in library \"extern_library_nonowner\" doesn't match `extern library` declaration [ExternLibraryIncorrect]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_library_nonowner.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_library.carbon:4:1: note: previously declared with `extern library` here [ExternLibraryExpected]\n// CHECK:STDERR: extern library \"extern_library_owner\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn F();\n\n// --- fail_extern_library_nonextern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_library\";\n\n// CHECK:STDERR: fail_extern_library_nonextern.carbon:[[@LINE+8]]:1: error: redeclarations of `fn F` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: fn F();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR: fail_extern_library_nonextern.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_library.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern library \"extern_library_owner\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F();\n\n// --- fail_extern_library_redecl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_library\";\n\n// CHECK:STDERR: fail_extern_library_redecl.carbon:[[@LINE+8]]:1: error: declaration in library \"extern_library_redecl\" doesn't match `extern library` declaration [ExternLibraryIncorrect]\n// CHECK:STDERR: extern library \"extern_library_owner\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_library_redecl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_library.carbon:4:1: note: previously declared with `extern library` here [ExternLibraryExpected]\n// CHECK:STDERR: extern library \"extern_library_owner\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern library \"extern_library_owner\" fn F();\n\n// --- extern_library_copy.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"extern_library_owner\" fn F();\n\n// --- fail_extern_library_collision.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_extern_library_collision.carbon:[[@LINE+9]]:1: in import [InImport]\n// CHECK:STDERR: extern_library_copy.carbon:4:1: error: duplicate name `F` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern library \"extern_library_owner\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_library_collision.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: extern_library.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern library \"extern_library_owner\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimport library \"extern_library\";\nimport library \"extern_library_copy\";\n\n// --- extern_library_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"extern_library_owner\" fn F();\n\n// --- fail_extern_library_mismatch_owner.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_library_mismatch\"\n\n// CHECK:STDERR: fail_extern_library_mismatch_owner.carbon:[[@LINE+8]]:1: error: `import` declarations must end with a `;` [ExpectedDeclSemi]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_extern_library_mismatch_owner.carbon:[[@LINE-6]]:1: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n// CHECK:STDERR: import library \"extern_library_mismatch\"\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn F();\n\n// --- fail_extern_self_library.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_extern_self_library.carbon:[[@LINE+4]]:1: error: `extern library` cannot specify the current library [ExternLibraryIsCurrentLibrary]\n// CHECK:STDERR: extern library \"extern_self_library\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern library \"extern_self_library\" fn F();\n\n// --- extern_of_import.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F();\n\n// --- fail_extern_of_import_redecl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_of_import\";\n\n// CHECK:STDERR: fail_extern_of_import_redecl.carbon:[[@LINE+8]]:1: error: redeclarations of `fn F` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern library \"extern_of_import\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_of_import_redecl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_of_import.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn F();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nextern library \"extern_of_import\" fn F();\n\n// --- fail_extern_library_on_definition.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_extern_library_on_definition.carbon:[[@LINE+4]]:1: error: a library cannot be provided for an `extern` modifier on a definition [ExternLibraryOnDefinition]\n// CHECK:STDERR: extern library \"extern_library_owner\" fn F() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern library \"extern_library_owner\" fn F() {}\n\n// CHECK:STDOUT: --- extern_library.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_library_owner.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_library_nonowner.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_library_nonextern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_library_redecl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = invalid\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_library_copy.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_library_collision.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.F = import_ref Main//extern_library, F, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_library_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_library_mismatch_owner.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_self_library.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_of_import.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_of_import_redecl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = invalid\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F [from \"extern_of_import.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_library_on_definition.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/extern_library_for_default.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/extern_library_for_default.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/extern_library_for_default.carbon\n\n// --- default.carbon\n\npackage Foo;\n\nextern library \"expected\" fn F();\n\n// --- expected.carbon\n\npackage Foo library \"[[@TEST_NAME]]\";\n\nimport library default;\n\nextern fn F();\n\n// --- fail_wrong_library.carbon\n\npackage Foo library \"[[@TEST_NAME]]\";\n\nimport library default;\n\n// CHECK:STDERR: fail_wrong_library.carbon:[[@LINE+8]]:1: error: declaration in library \"wrong_library\" doesn't match `extern library` declaration [ExternLibraryIncorrect]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_wrong_library.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: default.carbon:4:1: note: previously declared with `extern library` here [ExternLibraryExpected]\n// CHECK:STDERR: extern library \"expected\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn F();\n\n// CHECK:STDOUT: --- default.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- expected.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_wrong_library.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/extern_library_from_default.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/extern_library_from_default.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/extern_library_from_default.carbon\n\n// --- extern_library.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library default fn F();\n\n// --- default.carbon\n\nimport library \"extern_library\";\n\nextern fn F();\n\n// --- fail_wrong_library.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_library\";\n\n// CHECK:STDERR: fail_wrong_library.carbon:[[@LINE+8]]:1: error: declaration in library \"wrong_library\" doesn't match `extern library` declaration [ExternLibraryIncorrect]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_wrong_library.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_library.carbon:4:1: note: previously declared with `extern library` here [ExternLibraryExpected]\n// CHECK:STDERR: extern library default fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn F();\n\n// CHECK:STDOUT: --- extern_library.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- default.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_wrong_library.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/fail_import_incomplete_return.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/fail_import_incomplete_return.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/fail_import_incomplete_return.carbon\n\n// --- fail_incomplete_return.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\nclass D;\n\nfn ReturnCUnused() -> C;\nfn ReturnCUsed() -> C;\nfn ReturnDUnused() -> D;\nfn ReturnDUsed() -> D;\n\nfn Call() {\n  // CHECK:STDERR: fail_incomplete_return.carbon:[[@LINE+10]]:3: error: function returns incomplete type `C` [IncompleteTypeInFunctionReturnType]\n  // CHECK:STDERR:   ReturnCUsed();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_incomplete_return.carbon:[[@LINE-12]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class C;\n  // CHECK:STDERR: ^~~~~~~~\n  // CHECK:STDERR: fail_incomplete_return.carbon:[[@LINE-11]]:21: note: return type declared here [IncompleteReturnTypeHere]\n  // CHECK:STDERR: fn ReturnCUsed() -> C;\n  // CHECK:STDERR:                     ^\n  // CHECK:STDERR:\n  ReturnCUsed();\n  // CHECK:STDERR: fail_incomplete_return.carbon:[[@LINE+10]]:3: error: function returns incomplete type `D` [IncompleteTypeInFunctionReturnType]\n  // CHECK:STDERR:   ReturnDUsed();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_incomplete_return.carbon:[[@LINE-22]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class D;\n  // CHECK:STDERR: ^~~~~~~~\n  // CHECK:STDERR: fail_incomplete_return.carbon:[[@LINE-20]]:21: note: return type declared here [IncompleteReturnTypeHere]\n  // CHECK:STDERR: fn ReturnDUsed() -> D;\n  // CHECK:STDERR:                     ^\n  // CHECK:STDERR:\n  ReturnDUsed();\n}\n\nclass D {}\n\n// --- fail_use_imported.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"incomplete_return\";\n\nfn CallFAndGIncomplete() {\n  // CHECK:STDERR: fail_use_imported.carbon:[[@LINE+12]]:3: error: function returns incomplete type `C` [IncompleteTypeInFunctionReturnType]\n  // CHECK:STDERR:   ReturnCUnused();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_use_imported.carbon:[[@LINE-6]]:1: in import [InImport]\n  // CHECK:STDERR: fail_incomplete_return.carbon:4:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class C;\n  // CHECK:STDERR: ^~~~~~~~\n  // CHECK:STDERR: fail_use_imported.carbon:[[@LINE-10]]:1: in import [InImport]\n  // CHECK:STDERR: fail_incomplete_return.carbon:7:23: note: return type declared here [IncompleteReturnTypeHere]\n  // CHECK:STDERR: fn ReturnCUnused() -> C;\n  // CHECK:STDERR:                       ^\n  // CHECK:STDERR:\n  ReturnCUnused();\n  // CHECK:STDERR: fail_use_imported.carbon:[[@LINE+12]]:3: error: function returns incomplete type `C` [IncompleteTypeInFunctionReturnType]\n  // CHECK:STDERR:   ReturnCUsed();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~\n  // CHECK:STDERR: fail_use_imported.carbon:[[@LINE-19]]:1: in import [InImport]\n  // CHECK:STDERR: fail_incomplete_return.carbon:4:1: note: class was forward declared here [ClassForwardDeclaredHere]\n  // CHECK:STDERR: class C;\n  // CHECK:STDERR: ^~~~~~~~\n  // CHECK:STDERR: fail_use_imported.carbon:[[@LINE-23]]:1: in import [InImport]\n  // CHECK:STDERR: fail_incomplete_return.carbon:8:21: note: return type declared here [IncompleteReturnTypeHere]\n  // CHECK:STDERR: fn ReturnCUsed() -> C;\n  // CHECK:STDERR:                     ^\n  // CHECK:STDERR:\n  ReturnCUsed();\n  ReturnDUnused();\n  ReturnDUsed();\n}\n\n// CHECK:STDOUT: --- fail_incomplete_return.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %ReturnCUnused.type: type = fn_type @ReturnCUnused [concrete]\n// CHECK:STDOUT:   %ReturnCUnused: %ReturnCUnused.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ReturnCUsed.type: type = fn_type @ReturnCUsed [concrete]\n// CHECK:STDOUT:   %ReturnCUsed: %ReturnCUsed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.9a5: Core.Form = init_form %D [concrete]\n// CHECK:STDOUT:   %pattern_type.9c8: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %ReturnDUnused.type: type = fn_type @ReturnDUnused [concrete]\n// CHECK:STDOUT:   %ReturnDUnused: %ReturnDUnused.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ReturnDUsed.type: type = fn_type @ReturnDUsed [concrete]\n// CHECK:STDOUT:   %ReturnDUsed: %ReturnDUsed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Call.type: type = fn_type @Call [concrete]\n// CHECK:STDOUT:   %Call: %Call.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl.loc5\n// CHECK:STDOUT:     .ReturnCUnused = %ReturnCUnused.decl\n// CHECK:STDOUT:     .ReturnCUsed = %ReturnCUsed.decl\n// CHECK:STDOUT:     .ReturnDUnused = %ReturnDUnused.decl\n// CHECK:STDOUT:     .ReturnDUsed = %ReturnDUsed.decl\n// CHECK:STDOUT:     .Call = %Call.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %D.decl.loc5: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %ReturnCUnused.decl: %ReturnCUnused.type = fn_decl @ReturnCUnused [concrete = constants.%ReturnCUnused] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc7: Core.Form = init_form %C.ref [concrete = constants.%.a69]\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param0\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ReturnCUsed.decl: %ReturnCUsed.type = fn_decl @ReturnCUsed [concrete = constants.%ReturnCUsed] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc8: Core.Form = init_form %C.ref [concrete = constants.%.a69]\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param0\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ReturnDUnused.decl: %ReturnDUnused.type = fn_decl @ReturnDUnused [concrete = constants.%ReturnDUnused] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.9c8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.9c8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl.loc5 [concrete = constants.%D]\n// CHECK:STDOUT:     %.loc9: Core.Form = init_form %D.ref [concrete = constants.%.9a5]\n// CHECK:STDOUT:     %return.param: ref %D = out_param call_param0\n// CHECK:STDOUT:     %return: ref %D = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ReturnDUsed.decl: %ReturnDUsed.type = fn_decl @ReturnDUsed [concrete = constants.%ReturnDUsed] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.9c8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.9c8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl.loc5 [concrete = constants.%D]\n// CHECK:STDOUT:     %.loc10: Core.Form = init_form %D.ref [concrete = constants.%.9a5]\n// CHECK:STDOUT:     %return.param: ref %D = out_param call_param0\n// CHECK:STDOUT:     %return: ref %D = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Call.decl: %Call.type = fn_decl @Call [concrete = constants.%Call] {} {}\n// CHECK:STDOUT:   %D.decl.loc37: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ReturnCUnused() -> out %return.param: %C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ReturnCUsed() -> out %return.param: %C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ReturnDUnused() -> out %return.param: %D;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ReturnDUsed() -> out %return.param: %D;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ReturnCUsed.ref: %ReturnCUsed.type = name_ref ReturnCUsed, file.%ReturnCUsed.decl [concrete = constants.%ReturnCUsed]\n// CHECK:STDOUT:   %ReturnCUsed.call: init <error> = call %ReturnCUsed.ref()\n// CHECK:STDOUT:   %ReturnDUsed.ref: %ReturnDUsed.type = name_ref ReturnDUsed, file.%ReturnDUsed.decl [concrete = constants.%ReturnDUsed]\n// CHECK:STDOUT:   %ReturnDUsed.call: init <error> = call %ReturnDUsed.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_use_imported.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %CallFAndGIncomplete.type: type = fn_type @CallFAndGIncomplete [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %CallFAndGIncomplete: %CallFAndGIncomplete.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ReturnCUnused.type: type = fn_type @ReturnCUnused [concrete]\n// CHECK:STDOUT:   %ReturnCUnused: %ReturnCUnused.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ReturnCUsed.type: type = fn_type @ReturnCUsed [concrete]\n// CHECK:STDOUT:   %ReturnCUsed: %ReturnCUsed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ReturnDUnused.type: type = fn_type @ReturnDUnused [concrete]\n// CHECK:STDOUT:   %ReturnDUnused: %ReturnDUnused.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ReturnDUsed.type: type = fn_type @ReturnDUsed [concrete]\n// CHECK:STDOUT:   %ReturnDUsed: %ReturnDUsed.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C = import_ref Main//incomplete_return, C, unloaded\n// CHECK:STDOUT:   %Main.D = import_ref Main//incomplete_return, D, unloaded\n// CHECK:STDOUT:   %Main.ReturnCUnused: %ReturnCUnused.type = import_ref Main//incomplete_return, ReturnCUnused, loaded [concrete = constants.%ReturnCUnused]\n// CHECK:STDOUT:   %Main.ReturnCUsed: %ReturnCUsed.type = import_ref Main//incomplete_return, ReturnCUsed, loaded [concrete = constants.%ReturnCUsed]\n// CHECK:STDOUT:   %Main.ReturnDUnused: %ReturnDUnused.type = import_ref Main//incomplete_return, ReturnDUnused, loaded [concrete = constants.%ReturnDUnused]\n// CHECK:STDOUT:   %Main.ReturnDUsed: %ReturnDUsed.type = import_ref Main//incomplete_return, ReturnDUsed, loaded [concrete = constants.%ReturnDUsed]\n// CHECK:STDOUT:   %Main.Call = import_ref Main//incomplete_return, Call, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//incomplete_return, loc37_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.1d5 = import_ref Main//incomplete_return, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .ReturnCUnused = imports.%Main.ReturnCUnused\n// CHECK:STDOUT:     .ReturnCUsed = imports.%Main.ReturnCUsed\n// CHECK:STDOUT:     .ReturnDUnused = imports.%Main.ReturnDUnused\n// CHECK:STDOUT:     .ReturnDUsed = imports.%Main.ReturnDUsed\n// CHECK:STDOUT:     .Call = imports.%Main.Call\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .CallFAndGIncomplete = %CallFAndGIncomplete.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %CallFAndGIncomplete.decl: %CallFAndGIncomplete.type = fn_decl @CallFAndGIncomplete [concrete = constants.%CallFAndGIncomplete] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"fail_incomplete_return.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D [from \"fail_incomplete_return.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.1d5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallFAndGIncomplete() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ReturnCUnused.ref: %ReturnCUnused.type = name_ref ReturnCUnused, imports.%Main.ReturnCUnused [concrete = constants.%ReturnCUnused]\n// CHECK:STDOUT:   %ReturnCUnused.call: init <error> = call %ReturnCUnused.ref()\n// CHECK:STDOUT:   %ReturnCUsed.ref: %ReturnCUsed.type = name_ref ReturnCUsed, imports.%Main.ReturnCUsed [concrete = constants.%ReturnCUsed]\n// CHECK:STDOUT:   %ReturnCUsed.call: init <error> = call %ReturnCUsed.ref()\n// CHECK:STDOUT:   %ReturnDUnused.ref: %ReturnDUnused.type = name_ref ReturnDUnused, imports.%Main.ReturnDUnused [concrete = constants.%ReturnDUnused]\n// CHECK:STDOUT:   %.loc33_17.1: ref %D = temporary_storage\n// CHECK:STDOUT:   %ReturnDUnused.call: init %D to %.loc33_17.1 = call %ReturnDUnused.ref()\n// CHECK:STDOUT:   %.loc33_17.2: ref %D = temporary %.loc33_17.1, %ReturnDUnused.call\n// CHECK:STDOUT:   %ReturnDUsed.ref: %ReturnDUsed.type = name_ref ReturnDUsed, imports.%Main.ReturnDUsed [concrete = constants.%ReturnDUsed]\n// CHECK:STDOUT:   %.loc34_15.1: ref %D = temporary_storage\n// CHECK:STDOUT:   %ReturnDUsed.call: init %D to %.loc34_15.1 = call %ReturnDUsed.ref()\n// CHECK:STDOUT:   %.loc34_15.2: ref %D = temporary %.loc34_15.1, %ReturnDUsed.call\n// CHECK:STDOUT:   %Destroy.Op.bound.loc34: <bound method> = bound_method %.loc34_15.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc34: init %empty_tuple.type = call %Destroy.Op.bound.loc34(%.loc34_15.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc33: <bound method> = bound_method %.loc33_17.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call.loc33: init %empty_tuple.type = call %Destroy.Op.bound.loc33(%.loc33_17.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ReturnCUnused [from \"fail_incomplete_return.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ReturnCUsed [from \"fail_incomplete_return.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ReturnDUnused [from \"fail_incomplete_return.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ReturnDUsed [from \"fail_incomplete_return.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %D) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/fail_modifiers.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/fail_modifiers.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/fail_modifiers.carbon\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:9: error: `protected` must appear before `default` [ModifierMustAppearBefore]\n// CHECK:STDERR: default protected fn WrongOrder();\n// CHECK:STDERR:         ^~~~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+8]]:1: note: `default` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: default protected fn WrongOrder();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `default` not allowed; requires interface scope [ModifierRequiresInterface]\n// CHECK:STDERR: default protected fn WrongOrder();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\ndefault protected fn WrongOrder();\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:9: error: `virtual` repeated on declaration [ModifierRepeated]\n// CHECK:STDERR: virtual virtual fn DuplicateVirtual() {}\n// CHECK:STDERR:         ^~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+8]]:1: note: `virtual` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: virtual virtual fn DuplicateVirtual() {}\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `virtual` not allowed; requires class scope [ModifierRequiresClass]\n// CHECK:STDERR: virtual virtual fn DuplicateVirtual() {}\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nvirtual virtual fn DuplicateVirtual() {}\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:9: error: `protected` not allowed on declaration with `private` [ModifierNotAllowedWith]\n// CHECK:STDERR: private protected fn TwoAccess();\n// CHECK:STDERR:         ^~~~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `private` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: private protected fn TwoAccess();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nprivate protected fn TwoAccess();\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:10: error: `virtual` not allowed on declaration with `abstract` [ModifierNotAllowedWith]\n// CHECK:STDERR: abstract virtual fn ModifiersConflict() {}\n// CHECK:STDERR:          ^~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+8]]:1: note: `abstract` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: abstract virtual fn ModifiersConflict() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `abstract` not allowed; requires class scope [ModifierRequiresClass]\n// CHECK:STDERR: abstract virtual fn ModifiersConflict() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nabstract virtual fn ModifiersConflict() {}\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `base` not allowed on `fn` declaration [ModifierNotAllowedOnDeclaration]\n// CHECK:STDERR: base fn InvalidModifier();\n// CHECK:STDERR: ^~~~\n// CHECK:STDERR:\nbase fn InvalidModifier();\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+18]]:9: error: `final` not allowed on declaration with `default` [ModifierNotAllowedWith]\n// CHECK:STDERR: default final virtual fn ModifiersConflict2() {}\n// CHECK:STDERR:         ^~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+15]]:1: note: `default` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: default final virtual fn ModifiersConflict2() {}\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+11]]:15: error: `virtual` not allowed on declaration with `default` [ModifierNotAllowedWith]\n// CHECK:STDERR: default final virtual fn ModifiersConflict2() {}\n// CHECK:STDERR:               ^~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+8]]:1: note: `default` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: default final virtual fn ModifiersConflict2() {}\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: error: `default` not allowed; requires interface scope [ModifierRequiresInterface]\n// CHECK:STDERR: default final virtual fn ModifiersConflict2() {}\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\ndefault final virtual fn ModifiersConflict2() {}\n\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+7]]:8: error: `private` must appear before `extern` [ModifierMustAppearBefore]\n// CHECK:STDERR: extern private fn ExternOrderAndConflict() {}\n// CHECK:STDERR:        ^~~~~~~\n// CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:1: note: `extern` previously appeared here [ModifierPrevious]\n// CHECK:STDERR: extern private fn ExternOrderAndConflict() {}\n// CHECK:STDERR: ^~~~~~\n// CHECK:STDERR:\nextern private fn ExternOrderAndConflict() {}\n\n// CHECK:STDOUT: --- fail_modifiers.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %WrongOrder.type: type = fn_type @WrongOrder [concrete]\n// CHECK:STDOUT:   %WrongOrder: %WrongOrder.type = struct_value () [concrete]\n// CHECK:STDOUT:   %DuplicateVirtual.type: type = fn_type @DuplicateVirtual [concrete]\n// CHECK:STDOUT:   %DuplicateVirtual: %DuplicateVirtual.type = struct_value () [concrete]\n// CHECK:STDOUT:   %TwoAccess.type: type = fn_type @TwoAccess [concrete]\n// CHECK:STDOUT:   %TwoAccess: %TwoAccess.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ModifiersConflict.type: type = fn_type @ModifiersConflict [concrete]\n// CHECK:STDOUT:   %ModifiersConflict: %ModifiersConflict.type = struct_value () [concrete]\n// CHECK:STDOUT:   %InvalidModifier.type: type = fn_type @InvalidModifier [concrete]\n// CHECK:STDOUT:   %InvalidModifier: %InvalidModifier.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ModifiersConflict2.type: type = fn_type @ModifiersConflict2 [concrete]\n// CHECK:STDOUT:   %ModifiersConflict2: %ModifiersConflict2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ExternOrderAndConflict.type: type = fn_type @ExternOrderAndConflict [concrete]\n// CHECK:STDOUT:   %ExternOrderAndConflict: %ExternOrderAndConflict.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .WrongOrder = %WrongOrder.decl\n// CHECK:STDOUT:     .DuplicateVirtual = %DuplicateVirtual.decl\n// CHECK:STDOUT:     .TwoAccess [private] = %TwoAccess.decl\n// CHECK:STDOUT:     .ModifiersConflict = %ModifiersConflict.decl\n// CHECK:STDOUT:     .InvalidModifier = %InvalidModifier.decl\n// CHECK:STDOUT:     .ModifiersConflict2 = %ModifiersConflict2.decl\n// CHECK:STDOUT:     .ExternOrderAndConflict = %ExternOrderAndConflict.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %WrongOrder.decl: %WrongOrder.type = fn_decl @WrongOrder [concrete = constants.%WrongOrder] {} {}\n// CHECK:STDOUT:   %DuplicateVirtual.decl: %DuplicateVirtual.type = fn_decl @DuplicateVirtual [concrete = constants.%DuplicateVirtual] {} {}\n// CHECK:STDOUT:   %TwoAccess.decl: %TwoAccess.type = fn_decl @TwoAccess [concrete = constants.%TwoAccess] {} {}\n// CHECK:STDOUT:   %ModifiersConflict.decl: %ModifiersConflict.type = fn_decl @ModifiersConflict [concrete = constants.%ModifiersConflict] {} {}\n// CHECK:STDOUT:   %InvalidModifier.decl: %InvalidModifier.type = fn_decl @InvalidModifier [concrete = constants.%InvalidModifier] {} {}\n// CHECK:STDOUT:   %ModifiersConflict2.decl: %ModifiersConflict2.type = fn_decl @ModifiersConflict2 [concrete = constants.%ModifiersConflict2] {} {}\n// CHECK:STDOUT:   %ExternOrderAndConflict.decl: %ExternOrderAndConflict.type = fn_decl @ExternOrderAndConflict [concrete = constants.%ExternOrderAndConflict] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @WrongOrder();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @DuplicateVirtual() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @TwoAccess();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ModifiersConflict() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InvalidModifier();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ModifiersConflict2() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @ExternOrderAndConflict() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/fail_param_in_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/fail_param_in_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/fail_param_in_type.carbon\n\n// CHECK:STDERR: fail_param_in_type.carbon:[[@LINE+4]]:28: error: array bound is not a constant [InvalidArrayExpr]\n// CHECK:STDERR: fn F(n: i32, a: array(i32, n)*);\n// CHECK:STDERR:                            ^\n// CHECK:STDERR:\nfn F(n: i32, a: array(i32, n)*);\n\n// CHECK:STDOUT: --- fail_param_in_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %a.patt: <error> = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: <error> = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc19_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %a.param: <error> = value_param call_param1\n// CHECK:STDOUT:     %.loc19: type = splice_block %ptr [concrete = <error>] {\n// CHECK:STDOUT:       %i32.loc19_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:       %ptr: type = ptr_type <error> [concrete = <error>]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: <error> = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%n.param: %i32, %a.param: <error>);\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/fail_param_redecl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/fail_param_redecl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/fail_param_redecl.carbon\n\n// CHECK:STDERR: fail_param_redecl.carbon:[[@LINE+7]]:14: error: duplicate name `n` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: fn F(n: i32, n: i32);\n// CHECK:STDERR:              ^\n// CHECK:STDERR: fail_param_redecl.carbon:[[@LINE+4]]:6: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: fn F(n: i32, n: i32);\n// CHECK:STDERR:      ^\n// CHECK:STDERR:\nfn F(n: i32, n: i32);\n\n// CHECK:STDOUT: --- fail_param_redecl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %n.patt.loc22_6: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt.loc22_7: %pattern_type.7ce = value_param_pattern %n.patt.loc22_6 [concrete]\n// CHECK:STDOUT:     %n.patt.loc22_14: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt.loc22_15: %pattern_type.7ce = value_param_pattern %n.patt.loc22_14 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %n.param.loc22_7: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc22_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n.loc22_6: %i32 = value_binding n, %n.param.loc22_7\n// CHECK:STDOUT:     %n.param.loc22_15: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc22_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n.loc22_14: %i32 = value_binding n, %n.param.loc22_15\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%n.param.loc22_7: %i32, %n.param.loc22_15: %i32);\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/fail_redecl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/fail_redecl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/fail_redecl.carbon\n\nfn A();\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE+7]]:1: error: redeclaration of `fn A` is redundant [RedeclRedundant]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nfn A();\n\nfn B(x: ());\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE+7]]:1: error: redeclaration of `fn B` is redundant [RedeclRedundant]\n// CHECK:STDERR: fn B(x: ());\n// CHECK:STDERR: ^~~~~~~~~~~~\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn B(x: ());\n// CHECK:STDERR: ^~~~~~~~~~~~\n// CHECK:STDERR:\nfn B(x: ());\n\nfn C();\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE+7]]:1: error: redeclaration differs because of parameter count of 1 [RedeclParamCountDiffers]\n// CHECK:STDERR: fn C(x: ());\n// CHECK:STDERR: ^~~~~~~~~~~~\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: note: previously declared with parameter count of 0 [RedeclParamCountPrevious]\n// CHECK:STDERR: fn C();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nfn C(x: ());\n\nfn D() {}\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE+7]]:1: error: redeclaration of `fn D` is redundant [RedeclRedundant]\n// CHECK:STDERR: fn D();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn D() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn D();\n\nfn E() {}\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE+7]]:1: error: redefinition of `fn E` [RedeclRedef]\n// CHECK:STDERR: fn E() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_redecl.carbon:[[@LINE-4]]:1: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR: fn E() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn E() {}\n\n// CHECK:STDOUT: --- fail_redecl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type.0036b9.1: type = fn_type @C.loc35 [concrete]\n// CHECK:STDOUT:   %C.6a91b4.1: %C.type.0036b9.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type.0036b9.2: type = fn_type @C.loc43 [concrete]\n// CHECK:STDOUT:   %C.6a91b4.2: %C.type.0036b9.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %E.type.e738e1.1: type = fn_type @E.loc55 [concrete]\n// CHECK:STDOUT:   %E.d326aa.1: %E.type.e738e1.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %E.type.e738e1.2: type = fn_type @E.loc63 [concrete]\n// CHECK:STDOUT:   %E.d326aa.2: %E.type.e738e1.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl.loc15\n// CHECK:STDOUT:     .B = %B.decl.loc25\n// CHECK:STDOUT:     .C = %C.decl.loc35\n// CHECK:STDOUT:     .D = %D.decl.loc45\n// CHECK:STDOUT:     .E = %E.decl.loc55\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl.loc15: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %A.decl.loc23: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl.loc25: %B.type = fn_decl @B [concrete = constants.%B] {\n// CHECK:STDOUT:     %x.patt: %pattern_type = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param.loc25: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc25_10.1: type = splice_block %.loc25_10.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc25_10.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc25_10.3: type = converted %.loc25_10.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.loc25: %empty_tuple.type = value_binding x, %x.param.loc25\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl.loc33: %B.type = fn_decl @B [concrete = constants.%B] {\n// CHECK:STDOUT:     %x.patt: %pattern_type = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param.loc33: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc33_10.1: type = splice_block %.loc33_10.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc33_10.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc33_10.3: type = converted %.loc33_10.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.loc33: %empty_tuple.type = value_binding x, %x.param.loc33\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc35: %C.type.0036b9.1 = fn_decl @C.loc35 [concrete = constants.%C.6a91b4.1] {} {}\n// CHECK:STDOUT:   %C.decl.loc43: %C.type.0036b9.2 = fn_decl @C.loc43 [concrete = constants.%C.6a91b4.2] {\n// CHECK:STDOUT:     %x.patt: %pattern_type = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc43_10.1: type = splice_block %.loc43_10.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc43_10.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc43_10.3: type = converted %.loc43_10.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: %empty_tuple.type = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl.loc45: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %D.decl.loc53: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %E.decl.loc55: %E.type.e738e1.1 = fn_decl @E.loc55 [concrete = constants.%E.d326aa.1] {} {}\n// CHECK:STDOUT:   %E.decl.loc63: %E.type.e738e1.2 = fn_decl @E.loc63 [concrete = constants.%E.d326aa.2] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B(%x.param.loc25: %empty_tuple.type);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.loc35();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.loc43(%x.param: %empty_tuple.type);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @D() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @E.loc55() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @E.loc63() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/fail_todo_no_params.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/fail_todo_no_params.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/fail_todo_no_params.carbon\n\n// --- fail_no_body.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDERR: fail_no_body.carbon:[[@LINE+4]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo]\n// CHECK:STDERR: fn A;\n// CHECK:STDERR: ^~~~~\n// CHECK:STDERR:\nfn A;\n\n// --- fail_todo_brace_body.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDERR: fail_todo_brace_body.carbon:[[@LINE+4]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo]\n// CHECK:STDERR: fn A {\n// CHECK:STDERR: ^~~~~~\n// CHECK:STDERR:\nfn A {\n}\n\n// --- fail_todo_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDERR: fail_todo_return_type.carbon:[[@LINE+4]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo]\n// CHECK:STDERR: fn A -> ();\n// CHECK:STDERR: ^~~~~~~~~~~\n// CHECK:STDERR:\nfn A -> ();\n\n// --- fail_todo_implicit_only.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDERR: fail_todo_implicit_only.carbon:[[@LINE+4]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo]\n// CHECK:STDERR: fn A[] -> ();\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR:\nfn A[] -> ();\n\n// --- fail_todo_arrow_body.carbon\n\n// TODO: We don't have parsing support for this yet.\nlibrary \"[[@TEST_NAME]]\";\n// CHECK:STDERR: fail_todo_arrow_body.carbon:[[@LINE+8]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo]\n// CHECK:STDERR: fn A => 0;\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_todo_arrow_body.carbon:[[@LINE+4]]:6: error: semantics TODO: `HandleTerseBodyArrow` [SemanticsTodo]\n// CHECK:STDERR: fn A => 0;\n// CHECK:STDERR:      ^~\n// CHECK:STDERR:\nfn A => 0;\n\n// --- fail_invalid_file_generic_regression_test.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_invalid_file_generic_regression_test.carbon:[[@LINE+8]]:5: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n// CHECK:STDERR: var x:! () = ();\n// CHECK:STDERR:     ^~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_invalid_file_generic_regression_test.carbon:[[@LINE+4]]:12: error: found `:!` pattern inside `var` pattern [NonRegularBindingInVarDecl]\n// CHECK:STDERR: var x:! () = ();\n// CHECK:STDERR:            ^\n// CHECK:STDERR:\nvar x:! () = ();\n\nfn A {\n  A();\n}\n\n// CHECK:STDOUT: --- fail_no_body.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_brace_body.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_return_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_10.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_10.2: type = converted %.loc7_10.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc7_10.3: Core.Form = init_form %.loc7_10.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() -> out %return.param: %empty_tuple.type;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_implicit_only.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_12.2: type = converted %.loc7_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc7_12.3: Core.Form = init_form %.loc7_12.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() -> out %return.param: %empty_tuple.type;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_arrow_body.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_invalid_file_generic_regression_test.carbon\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/implicit_import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/implicit_import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/implicit_import.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A();\n\n// --- basic.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nfn A() {}\n\n// --- extern_api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn A();\n\n// --- fail_extern_api.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE+12]]:1: error: redeclarations of `fn A` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn A();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nfn A();\n\n// --- extern_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A();\n\n// --- fail_extern_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE+8]]:1: error: redeclarations of `fn A` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern fn A();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_impl.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nextern fn A();\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- basic.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_21.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_21.2 = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() [from \"basic.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_api.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_26.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_26.2 = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @A [from \"extern_api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_27.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_27.2 = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A [from \"extern_impl.carbon\"];\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/import.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A();\nfn B(b: i32) -> i32;\nfn C(c: (i32,)) -> {.c: i32};\nextern fn D();\n\nnamespace NS;\nfn NS.E();\n\n// --- extern_api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"redecl_extern_api\" fn A();\nextern library \"redecl_extern_api\" fn B(b: i32) -> i32;\nextern library \"redecl_extern_api\" fn C(c: (i32,)) -> {.c: i32};\nextern library \"redecl_extern_api\" fn D();\n\nnamespace NS;\nextern library \"redecl_extern_api\" fn NS.E();\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- basics.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"api\";\n\nvar a: () = A();\nvar b: i32 = B(1);\nvar c: {.c: i32} = C((1,));\nvar d: () = D();\nvar e: () = NS.E();\n\n// --- fail_redecl_api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"api\";\n\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+8]]:1: error: redeclarations of `fn A` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern fn A();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nextern fn A();\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+8]]:1: error: redeclarations of `fn B` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern fn B(b: i32) -> i32;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-14]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:5:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn B(b: i32) -> i32;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn B(b: i32) -> i32;\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+8]]:1: error: redeclarations of `fn C` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern fn C(c: (i32,)) -> {.c: i32};\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-23]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:6:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32};\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn C(c: (i32,)) -> {.c: i32};\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+8]]:1: error: redeclaration of `fn D` is redundant [RedeclRedundant]\n// CHECK:STDERR: extern fn D();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-32]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:7:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn D();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn D();\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE+8]]:1: error: redeclarations of `fn E` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern fn NS.E();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redecl_api.carbon:[[@LINE-41]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:10:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn NS.E();\n// CHECK:STDERR: ^~~~~~~~~~\n// CHECK:STDERR:\nextern fn NS.E();\n\nvar a: () = A();\nvar b: i32 = B(1);\nvar c: {.c: i32} = C((1,));\nvar d: () = D();\nvar e: () = NS.E();\n\n// --- redecl_extern_api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_api\";\n\nextern fn A();\nextern fn B(b: i32) -> i32;\nextern fn C(c: (i32,)) -> {.c: i32};\nextern fn D();\nextern fn NS.E();\n\nvar a: () = A();\nvar b: i32 = B(1);\nvar c: {.c: i32} = C((1,));\nvar d: () = D();\nvar e: () = NS.E();\n\n// --- fail_merge.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+45]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:4:1: error: duplicate name `A` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn A();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+41]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+36]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:5:1: error: duplicate name `B` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn B(b: i32) -> i32;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+32]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:5:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: fn B(b: i32) -> i32;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+27]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:6:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn C(c: (i32,)) -> {.c: i32};\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+23]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:6:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32};\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+18]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:7:1: error: duplicate name `D` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn D();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+14]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:7:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern fn D();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+9]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:10:1: error: duplicate name `E` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn NS.E();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_merge.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:10:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: fn NS.E();\n// CHECK:STDERR: ^~~~~~~~~~\n// CHECK:STDERR:\nimport library \"api\";\nimport library \"extern_api\";\n\nvar a: () = A();\nvar b: i32 = B(1);\nvar c: {.c: i32} = C((1,));\nvar d: () = D();\nvar e: () = NS.E();\n\n// --- fail_merge_reverse.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+45]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:4:1: error: duplicate name `A` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+41]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:4:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn A();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+36]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:5:1: error: duplicate name `B` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: fn B(b: i32) -> i32;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+32]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:5:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn B(b: i32) -> i32;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+27]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:6:1: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: fn C(c: (i32,)) -> {.c: i32};\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+23]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:6:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn C(c: (i32,)) -> {.c: i32};\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+18]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:7:1: error: duplicate name `D` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: extern fn D();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+14]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:7:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn D();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+9]]:1: in import [InImport]\n// CHECK:STDERR: api.carbon:10:1: error: duplicate name `E` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: fn NS.E();\n// CHECK:STDERR: ^~~~~~~~~~\n// CHECK:STDERR: fail_merge_reverse.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:10:1: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: extern library \"redecl_extern_api\" fn NS.E();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimport library \"extern_api\";\nimport library \"api\";\n\nvar a: () = A();\nvar b: i32 = B(1);\nvar c: {.c: i32} = C((1,));\nvar d: () = D();\nvar e: () = NS.E();\n\n// --- unloaded.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"api\";\n\n// --- unloaded_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern_api\";\n\n// CHECK:STDOUT: --- api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.85c = tuple_value (%i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.b74: type = pattern_type %tuple.type.a1c [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %.da9: Core.Form = init_form %struct_type.c [concrete]\n// CHECK:STDOUT:   %pattern_type.688: type = pattern_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %E.type: type = fn_type @E [concrete]\n// CHECK:STDOUT:   %E: %E.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .NS = %NS\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc5_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5: Core.Form = init_form %i32.loc5_17 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc5_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.b74 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.b74 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.688 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.688 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6_25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:     %.loc6_28: Core.Form = init_form %struct_type.c [concrete = constants.%.da9]\n// CHECK:STDOUT:     %c.param: %tuple.type.a1c = value_param call_param0\n// CHECK:STDOUT:     %.loc6_14.1: type = splice_block %.loc6_14.3 [concrete = constants.%tuple.type.a1c] {\n// CHECK:STDOUT:       %i32.loc6_10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc6_14.2: %tuple.type.85c = tuple_literal (%i32.loc6_10) [concrete = constants.%tuple]\n// CHECK:STDOUT:       %.loc6_14.3: type = converted %.loc6_14.2, constants.%tuple.type.a1c [concrete = constants.%tuple.type.a1c]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %tuple.type.a1c = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %struct_type.c = out_param call_param1\n// CHECK:STDOUT:     %return: ref %struct_type.c = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %NS: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .E = %E.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %E.decl: %E.type = fn_decl @E [concrete = constants.%E] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B(%b.param: %i32) -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C(%c.param: %tuple.type.a1c) -> out %return.param: %struct_type.c;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @D();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @E();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.85c = tuple_value (%i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.b74: type = pattern_type %tuple.type.a1c [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %.da9: Core.Form = init_form %struct_type.c [concrete]\n// CHECK:STDOUT:   %pattern_type.688: type = pattern_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %E.type: type = fn_type @E [concrete]\n// CHECK:STDOUT:   %E: %E.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .NS = %NS\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc5_52: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5: Core.Form = init_form %i32.loc5_52 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc5_44: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.b74 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.b74 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.688 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.688 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6_60: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:     %.loc6_63: Core.Form = init_form %struct_type.c [concrete = constants.%.da9]\n// CHECK:STDOUT:     %c.param: %tuple.type.a1c = value_param call_param0\n// CHECK:STDOUT:     %.loc6_49.1: type = splice_block %.loc6_49.3 [concrete = constants.%tuple.type.a1c] {\n// CHECK:STDOUT:       %i32.loc6_45: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc6_49.2: %tuple.type.85c = tuple_literal (%i32.loc6_45) [concrete = constants.%tuple]\n// CHECK:STDOUT:       %.loc6_49.3: type = converted %.loc6_49.2, constants.%tuple.type.a1c [concrete = constants.%tuple.type.a1c]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %tuple.type.a1c = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %struct_type.c = out_param call_param1\n// CHECK:STDOUT:     %return: ref %struct_type.c = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %NS: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .E = %E.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %E.decl: %E.type = fn_decl @E [concrete = constants.%E] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @B(%b.param: %i32) -> out %return.param: %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @C(%c.param: %tuple.type.a1c) -> out %return.param: %struct_type.c;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @D();\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @E();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- basics.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.688: type = pattern_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.378: %tuple.type.985 = tuple_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %tuple.246: %tuple.type.a1c = tuple_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %E.type: type = fn_type @E [concrete]\n// CHECK:STDOUT:   %E: %E.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A: %A.type = import_ref Main//api, A, loaded [concrete = constants.%A]\n// CHECK:STDOUT:   %Main.B: %B.type = import_ref Main//api, B, loaded [concrete = constants.%B]\n// CHECK:STDOUT:   %Main.C: %C.type = import_ref Main//api, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.D: %D.type = import_ref Main//api, D, loaded [concrete = constants.%D]\n// CHECK:STDOUT:   %Main.NS: <namespace> = import_ref Main//api, NS, loaded\n// CHECK:STDOUT:   %NS: <namespace> = namespace %Main.NS, [concrete] {\n// CHECK:STDOUT:     .E = %Main.E\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.E: %E.type = import_ref Main//api, E, loaded [concrete = constants.%E]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .NS = imports.%NS\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:     .e = %e\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.cb1 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.cb1 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_tuple.type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %i32.loc7: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.688 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.688 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %struct_type.c = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %struct_type.c [concrete = constants.%struct_type.c] {\n// CHECK:STDOUT:     %i32.loc8: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %struct_type.c = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.cb1 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.cb1 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %empty_tuple.type = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %.loc9_9.1: type = splice_block %.loc9_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc9_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc9_9.3: type = converted %.loc9_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %empty_tuple.type = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %e.patt: %pattern_type.cb1 = ref_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.var_patt: %pattern_type.cb1 = var_pattern %e.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e.var: ref %empty_tuple.type = var %e.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_9.1: type = splice_block %.loc10_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc10_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc10_9.3: type = converted %.loc10_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e: ref %empty_tuple.type = ref_binding e, %e.var [concrete = %e.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @D [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @E [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, imports.%Main.A [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.ref()\n// CHECK:STDOUT:   assign file.%a.var, %A.call\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, imports.%Main.B [concrete = constants.%B]\n// CHECK:STDOUT:   %int_1.loc7: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc7: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc7_16.1: <bound method> = bound_method %int_1.loc7, %impl.elem0.loc7 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_16.2: <bound method> = bound_method %int_1.loc7, %specific_fn.loc7 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %i32 = call %bound_method.loc7_16.2(%int_1.loc7) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc7_16.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc7_16.2: %i32 = converted %int_1.loc7, %.loc7_16.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %B.call: init %i32 = call %B.ref(%.loc7_16.2)\n// CHECK:STDOUT:   assign file.%b.var, %B.call\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %int_1.loc8: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc8_25.1: %tuple.type.985 = tuple_literal (%int_1.loc8) [concrete = constants.%tuple.378]\n// CHECK:STDOUT:   %impl.elem0.loc8: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc8_25.1: <bound method> = bound_method %int_1.loc8, %impl.elem0.loc8 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_25.2: <bound method> = bound_method %int_1.loc8, %specific_fn.loc8 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %i32 = call %bound_method.loc8_25.2(%int_1.loc8) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc8_25.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc8_25.3: %i32 = converted %int_1.loc8, %.loc8_25.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %tuple: %tuple.type.a1c = tuple_value (%.loc8_25.3) [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %.loc8_25.4: %tuple.type.a1c = converted %.loc8_25.1, %tuple [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %C.call: init %struct_type.c = call %C.ref(%.loc8_25.4)\n// CHECK:STDOUT:   assign file.%c.var, %C.call\n// CHECK:STDOUT:   %D.ref: %D.type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:   %D.call: init %empty_tuple.type = call %D.ref()\n// CHECK:STDOUT:   assign file.%d.var, %D.call\n// CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, imports.%NS [concrete = imports.%NS]\n// CHECK:STDOUT:   %E.ref: %E.type = name_ref E, imports.%Main.E [concrete = constants.%E]\n// CHECK:STDOUT:   %E.call: init %empty_tuple.type = call %E.ref()\n// CHECK:STDOUT:   assign file.%e.var, %E.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_redecl_api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple.896: %tuple.type.85c = tuple_value (%i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %.da9: Core.Form = init_form %struct_type.c [concrete]\n// CHECK:STDOUT:   %pattern_type.688: type = pattern_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %E.type: type = fn_type @E [concrete]\n// CHECK:STDOUT:   %E: %E.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.378: %tuple.type.985 = tuple_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %tuple.246: %tuple.type.a1c = tuple_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.NS: <namespace> = import_ref Main//api, NS, loaded\n// CHECK:STDOUT:   %NS: <namespace> = namespace %Main.NS, [concrete] {\n// CHECK:STDOUT:     .E = file.%E.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .NS = imports.%NS\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:     .e = %e\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {\n// CHECK:STDOUT:     %i32.loc23_24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc23: Core.Form = init_form %i32.loc23_24 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc23_16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {} {\n// CHECK:STDOUT:     %i32.loc32_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:     %.loc32_35: Core.Form = init_form %struct_type.c [concrete = constants.%.da9]\n// CHECK:STDOUT:     %c.param: %tuple.type.a1c = value_param call_param0\n// CHECK:STDOUT:     %.loc32_21.1: type = splice_block %.loc32_21.3 [concrete = constants.%tuple.type.a1c] {\n// CHECK:STDOUT:       %i32.loc32_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc32_21.2: %tuple.type.85c = tuple_literal (%i32.loc32_17) [concrete = constants.%tuple.896]\n// CHECK:STDOUT:       %.loc32_21.3: type = converted %.loc32_21.2, constants.%tuple.type.a1c [concrete = constants.%tuple.type.a1c]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %tuple.type.a1c = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %struct_type.c = out_param call_param1\n// CHECK:STDOUT:     %return: ref %struct_type.c = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %E.decl: %E.type = fn_decl @E [concrete = constants.%E] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.cb1 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.cb1 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc52_9.1: type = splice_block %.loc52_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc52_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc52_9.3: type = converted %.loc52_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_tuple.type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %i32.loc53: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.688 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.688 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %struct_type.c = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc54: type = splice_block %struct_type.c [concrete = constants.%struct_type.c] {\n// CHECK:STDOUT:     %i32.loc54: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %struct_type.c = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.cb1 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.cb1 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %empty_tuple.type = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %.loc55_9.1: type = splice_block %.loc55_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc55_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc55_9.3: type = converted %.loc55_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %empty_tuple.type = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %e.patt: %pattern_type.cb1 = ref_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.var_patt: %pattern_type.cb1 = var_pattern %e.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e.var: ref %empty_tuple.type = var %e.var_patt [concrete]\n// CHECK:STDOUT:   %.loc56_9.1: type = splice_block %.loc56_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc56_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc56_9.3: type = converted %.loc56_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e: ref %empty_tuple.type = ref_binding e, %e.var [concrete = %e.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @D [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @E [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.ref()\n// CHECK:STDOUT:   assign file.%a.var, %A.call\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %int_1.loc53: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc53: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc53_16.1: <bound method> = bound_method %int_1.loc53, %impl.elem0.loc53 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc53: <specific function> = specific_function %impl.elem0.loc53, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc53_16.2: <bound method> = bound_method %int_1.loc53, %specific_fn.loc53 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc53: init %i32 = call %bound_method.loc53_16.2(%int_1.loc53) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc53_16.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc53 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc53_16.2: %i32 = converted %int_1.loc53, %.loc53_16.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %B.call: init %i32 = call %B.ref(%.loc53_16.2)\n// CHECK:STDOUT:   assign file.%b.var, %B.call\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %int_1.loc54: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc54_25.1: %tuple.type.985 = tuple_literal (%int_1.loc54) [concrete = constants.%tuple.378]\n// CHECK:STDOUT:   %impl.elem0.loc54: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc54_25.1: <bound method> = bound_method %int_1.loc54, %impl.elem0.loc54 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc54: <specific function> = specific_function %impl.elem0.loc54, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc54_25.2: <bound method> = bound_method %int_1.loc54, %specific_fn.loc54 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc54: init %i32 = call %bound_method.loc54_25.2(%int_1.loc54) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc54_25.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc54 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc54_25.3: %i32 = converted %int_1.loc54, %.loc54_25.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %tuple: %tuple.type.a1c = tuple_value (%.loc54_25.3) [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %.loc54_25.4: %tuple.type.a1c = converted %.loc54_25.1, %tuple [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %C.call: init %struct_type.c = call %C.ref(%.loc54_25.4)\n// CHECK:STDOUT:   assign file.%c.var, %C.call\n// CHECK:STDOUT:   %D.ref: %D.type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:   %D.call: init %empty_tuple.type = call %D.ref()\n// CHECK:STDOUT:   assign file.%d.var, %D.call\n// CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, imports.%NS [concrete = imports.%NS]\n// CHECK:STDOUT:   %E.ref: %E.type = name_ref E, file.%E.decl [concrete = constants.%E]\n// CHECK:STDOUT:   %E.call: init %empty_tuple.type = call %E.ref()\n// CHECK:STDOUT:   assign file.%e.var, %E.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- redecl_extern_api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.501: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.4ca: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.f5f: type = pattern_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %tuple.type.dd4: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %.dce: Core.Form = init_form %struct_type.c [concrete]\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %E.type: type = fn_type @E [concrete]\n// CHECK:STDOUT:   %E: %E.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple.38e: %tuple.type.85c = tuple_value (%i32) [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cf3: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.255: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.58d: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.e45, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.199 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.cf3 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.58d) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.979: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.7c3: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.979, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.47b: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.378: %tuple.type.985 = tuple_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %tuple.7dd: %tuple.type.dd4 = tuple_value (%int_1.47b) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.NS: <namespace> = import_ref Main//extern_api, NS, loaded\n// CHECK:STDOUT:   %NS: <namespace> = namespace %Main.NS, [concrete] {\n// CHECK:STDOUT:     .E = file.%E.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ece: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.b25: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.004) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.255)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.e45 = impl_witness_table (%Core.import_ref.b25), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .NS = imports.%NS\n// CHECK:STDOUT:     .Core = imports.%Core.ece\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:     .e = %e\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {\n// CHECK:STDOUT:     %i32.loc7_24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc7: Core.Form = init_form %i32.loc7_24 [concrete = constants.%.4ca]\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc7_16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {} {\n// CHECK:STDOUT:     %i32.loc8_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:     %.loc8_35: Core.Form = init_form %struct_type.c [concrete = constants.%.dce]\n// CHECK:STDOUT:     %c.param: %tuple.type.dd4 = value_param call_param0\n// CHECK:STDOUT:     %.loc8_21.1: type = splice_block %.loc8_21.3 [concrete = constants.%tuple.type.dd4] {\n// CHECK:STDOUT:       %i32.loc8_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc8_21.2: %tuple.type.85c = tuple_literal (%i32.loc8_17) [concrete = constants.%tuple.38e]\n// CHECK:STDOUT:       %.loc8_21.3: type = converted %.loc8_21.2, constants.%tuple.type.dd4 [concrete = constants.%tuple.type.dd4]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %tuple.type.dd4 = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %struct_type.c = out_param call_param1\n// CHECK:STDOUT:     %return: ref %struct_type.c = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %E.decl: %E.type = fn_decl @E [concrete = constants.%E] {} {}\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.cb1 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.cb1 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc12_9.1: type = splice_block %.loc12_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc12_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc12_9.3: type = converted %.loc12_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_tuple.type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.501 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.501 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %i32.loc13: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.f5f = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.f5f = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %struct_type.c = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc14: type = splice_block %struct_type.c [concrete = constants.%struct_type.c] {\n// CHECK:STDOUT:     %i32.loc14: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %struct_type.c = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.cb1 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.cb1 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %empty_tuple.type = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %.loc15_9.1: type = splice_block %.loc15_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc15_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc15_9.3: type = converted %.loc15_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %empty_tuple.type = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %e.patt: %pattern_type.cb1 = ref_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.var_patt: %pattern_type.cb1 = var_pattern %e.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e.var: ref %empty_tuple.type = var %e.var_patt [concrete]\n// CHECK:STDOUT:   %.loc16_9.1: type = splice_block %.loc16_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc16_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc16_9.3: type = converted %.loc16_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e: ref %empty_tuple.type = ref_binding e, %e.var [concrete = %e.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @A;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @B;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @D;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @E;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.ref()\n// CHECK:STDOUT:   assign file.%a.var, %A.call\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %int_1.loc13: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc13: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc13_16.1: <bound method> = bound_method %int_1.loc13, %impl.elem0.loc13 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc13: <specific function> = specific_function %impl.elem0.loc13, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_16.2: <bound method> = bound_method %int_1.loc13, %specific_fn.loc13 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13: init %i32 = call %bound_method.loc13_16.2(%int_1.loc13) [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc13_16.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc13 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc13_16.2: %i32 = converted %int_1.loc13, %.loc13_16.1 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %B.call: init %i32 = call %B.ref(%.loc13_16.2)\n// CHECK:STDOUT:   assign file.%b.var, %B.call\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %int_1.loc14: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc14_25.1: %tuple.type.985 = tuple_literal (%int_1.loc14) [concrete = constants.%tuple.378]\n// CHECK:STDOUT:   %impl.elem0.loc14: %.7c3 = impl_witness_access constants.%ImplicitAs.impl_witness.58d, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.5f4]\n// CHECK:STDOUT:   %bound_method.loc14_25.1: <bound method> = bound_method %int_1.loc14, %impl.elem0.loc14 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc14: <specific function> = specific_function %impl.elem0.loc14, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc14_25.2: <bound method> = bound_method %int_1.loc14, %specific_fn.loc14 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14: init %i32 = call %bound_method.loc14_25.2(%int_1.loc14) [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc14_25.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc14 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %.loc14_25.3: %i32 = converted %int_1.loc14, %.loc14_25.2 [concrete = constants.%int_1.47b]\n// CHECK:STDOUT:   %tuple: %tuple.type.dd4 = tuple_value (%.loc14_25.3) [concrete = constants.%tuple.7dd]\n// CHECK:STDOUT:   %.loc14_25.4: %tuple.type.dd4 = converted %.loc14_25.1, %tuple [concrete = constants.%tuple.7dd]\n// CHECK:STDOUT:   %C.call: init %struct_type.c = call %C.ref(%.loc14_25.4)\n// CHECK:STDOUT:   assign file.%c.var, %C.call\n// CHECK:STDOUT:   %D.ref: %D.type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:   %D.call: init %empty_tuple.type = call %D.ref()\n// CHECK:STDOUT:   assign file.%d.var, %D.call\n// CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, imports.%NS [concrete = imports.%NS]\n// CHECK:STDOUT:   %E.ref: %E.type = name_ref E, file.%E.decl [concrete = constants.%E]\n// CHECK:STDOUT:   %E.call: init %empty_tuple.type = call %E.ref()\n// CHECK:STDOUT:   assign file.%e.var, %E.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_merge.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.688: type = pattern_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.378: %tuple.type.985 = tuple_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %tuple.246: %tuple.type.a1c = tuple_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %E.type: type = fn_type @E [concrete]\n// CHECK:STDOUT:   %E: %E.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A: %A.type = import_ref Main//api, A, loaded [concrete = constants.%A]\n// CHECK:STDOUT:   %Main.B: %B.type = import_ref Main//api, B, loaded [concrete = constants.%B]\n// CHECK:STDOUT:   %Main.C: %C.type = import_ref Main//api, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.D: %D.type = import_ref Main//api, D, loaded [concrete = constants.%D]\n// CHECK:STDOUT:   %Main.NS: <namespace> = import_ref Main//api, NS, loaded\n// CHECK:STDOUT:   %NS: <namespace> = namespace %Main.NS, [concrete] {\n// CHECK:STDOUT:     .E = %Main.E\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.E: %E.type = import_ref Main//api, E, loaded [concrete = constants.%E]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .NS = imports.%NS\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:     .e = %e\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.cb1 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.cb1 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc52_9.1: type = splice_block %.loc52_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc52_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc52_9.3: type = converted %.loc52_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_tuple.type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %i32.loc53: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.688 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.688 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %struct_type.c = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc54: type = splice_block %struct_type.c [concrete = constants.%struct_type.c] {\n// CHECK:STDOUT:     %i32.loc54: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %struct_type.c = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.cb1 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.cb1 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %empty_tuple.type = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %.loc55_9.1: type = splice_block %.loc55_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc55_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc55_9.3: type = converted %.loc55_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %empty_tuple.type = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %e.patt: %pattern_type.cb1 = ref_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.var_patt: %pattern_type.cb1 = var_pattern %e.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e.var: ref %empty_tuple.type = var %e.var_patt [concrete]\n// CHECK:STDOUT:   %.loc56_9.1: type = splice_block %.loc56_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc56_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc56_9.3: type = converted %.loc56_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e: ref %empty_tuple.type = ref_binding e, %e.var [concrete = %e.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @D [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @E [from \"api.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, imports.%Main.A [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.ref()\n// CHECK:STDOUT:   assign file.%a.var, %A.call\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, imports.%Main.B [concrete = constants.%B]\n// CHECK:STDOUT:   %int_1.loc53: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc53: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc53_16.1: <bound method> = bound_method %int_1.loc53, %impl.elem0.loc53 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc53: <specific function> = specific_function %impl.elem0.loc53, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc53_16.2: <bound method> = bound_method %int_1.loc53, %specific_fn.loc53 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc53: init %i32 = call %bound_method.loc53_16.2(%int_1.loc53) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc53_16.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc53 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc53_16.2: %i32 = converted %int_1.loc53, %.loc53_16.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %B.call: init %i32 = call %B.ref(%.loc53_16.2)\n// CHECK:STDOUT:   assign file.%b.var, %B.call\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %int_1.loc54: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc54_25.1: %tuple.type.985 = tuple_literal (%int_1.loc54) [concrete = constants.%tuple.378]\n// CHECK:STDOUT:   %impl.elem0.loc54: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc54_25.1: <bound method> = bound_method %int_1.loc54, %impl.elem0.loc54 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc54: <specific function> = specific_function %impl.elem0.loc54, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc54_25.2: <bound method> = bound_method %int_1.loc54, %specific_fn.loc54 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc54: init %i32 = call %bound_method.loc54_25.2(%int_1.loc54) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc54_25.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc54 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc54_25.3: %i32 = converted %int_1.loc54, %.loc54_25.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %tuple: %tuple.type.a1c = tuple_value (%.loc54_25.3) [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %.loc54_25.4: %tuple.type.a1c = converted %.loc54_25.1, %tuple [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %C.call: init %struct_type.c = call %C.ref(%.loc54_25.4)\n// CHECK:STDOUT:   assign file.%c.var, %C.call\n// CHECK:STDOUT:   %D.ref: %D.type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:   %D.call: init %empty_tuple.type = call %D.ref()\n// CHECK:STDOUT:   assign file.%d.var, %D.call\n// CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, imports.%NS [concrete = imports.%NS]\n// CHECK:STDOUT:   %E.ref: %E.type = name_ref E, imports.%Main.E [concrete = constants.%E]\n// CHECK:STDOUT:   %E.call: init %empty_tuple.type = call %E.ref()\n// CHECK:STDOUT:   assign file.%e.var, %E.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_merge_reverse.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.688: type = pattern_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.378: %tuple.type.985 = tuple_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %tuple.246: %tuple.type.a1c = tuple_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT:   %E.type: type = fn_type @E [concrete]\n// CHECK:STDOUT:   %E: %E.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A: %A.type = import_ref Main//extern_api, A, loaded [concrete = constants.%A]\n// CHECK:STDOUT:   %Main.B: %B.type = import_ref Main//extern_api, B, loaded [concrete = constants.%B]\n// CHECK:STDOUT:   %Main.C: %C.type = import_ref Main//extern_api, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.D: %D.type = import_ref Main//extern_api, D, loaded [concrete = constants.%D]\n// CHECK:STDOUT:   %Main.NS: <namespace> = import_ref Main//extern_api, NS, loaded\n// CHECK:STDOUT:   %NS: <namespace> = namespace %Main.NS, [concrete] {\n// CHECK:STDOUT:     .E = %Main.E\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.E: %E.type = import_ref Main//extern_api, E, loaded [concrete = constants.%E]\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .NS = imports.%NS\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:     .d = %d\n// CHECK:STDOUT:     .e = %e\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.cb1 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.cb1 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc52_9.1: type = splice_block %.loc52_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc52_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc52_9.3: type = converted %.loc52_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_tuple.type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %i32.loc53: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.688 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.688 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %struct_type.c = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc54: type = splice_block %struct_type.c [concrete = constants.%struct_type.c] {\n// CHECK:STDOUT:     %i32.loc54: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %struct_type.c = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %d.patt: %pattern_type.cb1 = ref_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.var_patt: %pattern_type.cb1 = var_pattern %d.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d.var: ref %empty_tuple.type = var %d.var_patt [concrete]\n// CHECK:STDOUT:   %.loc55_9.1: type = splice_block %.loc55_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc55_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc55_9.3: type = converted %.loc55_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %d: ref %empty_tuple.type = ref_binding d, %d.var [concrete = %d.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %e.patt: %pattern_type.cb1 = ref_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.var_patt: %pattern_type.cb1 = var_pattern %e.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e.var: ref %empty_tuple.type = var %e.var_patt [concrete]\n// CHECK:STDOUT:   %.loc56_9.1: type = splice_block %.loc56_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc56_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc56_9.3: type = converted %.loc56_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %e: ref %empty_tuple.type = ref_binding e, %e.var [concrete = %e.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @A;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @B;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @D;\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @E;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, imports.%Main.A [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.ref()\n// CHECK:STDOUT:   assign file.%a.var, %A.call\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, imports.%Main.B [concrete = constants.%B]\n// CHECK:STDOUT:   %int_1.loc53: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc53: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc53_16.1: <bound method> = bound_method %int_1.loc53, %impl.elem0.loc53 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc53: <specific function> = specific_function %impl.elem0.loc53, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc53_16.2: <bound method> = bound_method %int_1.loc53, %specific_fn.loc53 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc53: init %i32 = call %bound_method.loc53_16.2(%int_1.loc53) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc53_16.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc53 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc53_16.2: %i32 = converted %int_1.loc53, %.loc53_16.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %B.call: init %i32 = call %B.ref(%.loc53_16.2)\n// CHECK:STDOUT:   assign file.%b.var, %B.call\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %int_1.loc54: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc54_25.1: %tuple.type.985 = tuple_literal (%int_1.loc54) [concrete = constants.%tuple.378]\n// CHECK:STDOUT:   %impl.elem0.loc54: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc54_25.1: <bound method> = bound_method %int_1.loc54, %impl.elem0.loc54 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc54: <specific function> = specific_function %impl.elem0.loc54, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc54_25.2: <bound method> = bound_method %int_1.loc54, %specific_fn.loc54 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc54: init %i32 = call %bound_method.loc54_25.2(%int_1.loc54) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc54_25.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc54 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc54_25.3: %i32 = converted %int_1.loc54, %.loc54_25.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %tuple: %tuple.type.a1c = tuple_value (%.loc54_25.3) [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %.loc54_25.4: %tuple.type.a1c = converted %.loc54_25.1, %tuple [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %C.call: init %struct_type.c = call %C.ref(%.loc54_25.4)\n// CHECK:STDOUT:   assign file.%c.var, %C.call\n// CHECK:STDOUT:   %D.ref: %D.type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:   %D.call: init %empty_tuple.type = call %D.ref()\n// CHECK:STDOUT:   assign file.%d.var, %D.call\n// CHECK:STDOUT:   %NS.ref: <namespace> = name_ref NS, imports.%NS [concrete = imports.%NS]\n// CHECK:STDOUT:   %E.ref: %E.type = name_ref E, imports.%Main.E [concrete = constants.%E]\n// CHECK:STDOUT:   %E.call: init %empty_tuple.type = call %E.ref()\n// CHECK:STDOUT:   assign file.%e.var, %E.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- unloaded.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A = import_ref Main//api, A, unloaded\n// CHECK:STDOUT:   %Main.B = import_ref Main//api, B, unloaded\n// CHECK:STDOUT:   %Main.C = import_ref Main//api, C, unloaded\n// CHECK:STDOUT:   %Main.D = import_ref Main//api, D, unloaded\n// CHECK:STDOUT:   %Main.NS: <namespace> = import_ref Main//api, NS, loaded\n// CHECK:STDOUT:   %NS: <namespace> = namespace %Main.NS, [concrete] {\n// CHECK:STDOUT:     .E = %Main.E\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.E = import_ref Main//api, E, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .NS = imports.%NS\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- unloaded_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A = import_ref Main//extern_api, A, unloaded\n// CHECK:STDOUT:   %Main.B = import_ref Main//extern_api, B, unloaded\n// CHECK:STDOUT:   %Main.C = import_ref Main//extern_api, C, unloaded\n// CHECK:STDOUT:   %Main.D = import_ref Main//extern_api, D, unloaded\n// CHECK:STDOUT:   %Main.NS: <namespace> = import_ref Main//extern_api, NS, loaded\n// CHECK:STDOUT:   %NS: <namespace> = namespace %Main.NS, [concrete] {\n// CHECK:STDOUT:     .E = %Main.E\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Main.E = import_ref Main//extern_api, E, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .NS = imports.%NS\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/name_poisoning.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/name_poisoning.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/name_poisoning.carbon\n\n// --- no_poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C1 {}\nclass C2 {}\n\nfn F1(x: C1);\n\n// `N.F2` uses `N.F1` and not `package.F1`.\nnamespace N;\nfn N.F1(x: C2);\nalias N.F2 = F1;\n\nfn TestCall(x: C2) {\n  // `N.F2` accepts a `C2` not a `C1`.\n  N.F2(x);\n}\n\n// --- poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F1();\n\n// Use `package.F1` and poison `N.F1`.\nnamespace N;\nalias N.F2 = F1;\n\n// --- fail_declare_after_poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F1();\n\nnamespace N;\n// Use `package.F1` and poison `N.F1`.\n// CHECK:STDERR: fail_declare_after_poison.carbon:[[@LINE+3]]:14: error: name `F1` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: alias N.F2 = F1;\n// CHECK:STDERR:              ^~\nalias N.F2 = F1;\n\n// Failure: `N.F1` declared after it was poisoned.\n// CHECK:STDERR: fail_declare_after_poison.carbon:[[@LINE+4]]:6: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: fn N.F1();\n// CHECK:STDERR:      ^~\n// CHECK:STDERR:\nfn N.F1();\n\n// --- fail_use_poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F1();\n\n// Use `package.F1` and poison `N.F1`.\nnamespace N;\nalias N.F2 = F1;\n\n// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:14: error: member name `F1` not found in `N` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: alias N.F3 = N.F1;\n// CHECK:STDERR:              ^~~~\n// CHECK:STDERR:\nalias N.F3 = N.F1;\n\n// --- fail_use_declaration_after_poison.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F1();\n\nnamespace N;\n// Use `package.F1` and poison `N.F1`.\n// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+3]]:14: error: name `F1` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: alias N.F2 = F1;\n// CHECK:STDERR:              ^~\nalias N.F2 = F1;\n\n// Failure: `N.F1` declared after it was poisoned.\n// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:6: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: fn N.F1();\n// CHECK:STDERR:      ^~\n// CHECK:STDERR:\nfn N.F1();\n\n// Failure: `N.F1` used after declaration failed.\n// TODO: #4622 - Allow defining a poisoned name so it would be found if used after it's declared.\n// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:14: error: member name `F1` not found in `N` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: alias N.F3 = N.F1;\n// CHECK:STDERR:              ^~~~\n// CHECK:STDERR:\nalias N.F3 = N.F1;\n\n// --- fail_poison_multiple_scopes.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F1();\n\nnamespace N1;\nnamespace N1.N2;\nnamespace N1.N2.N3;\n// Use `package.F1` and poison:\n// * `N1.F1`\n// * `N1.N2.F1`\n// * `N1.N2.N3.F1`\n// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+3]]:21: error: name `F1` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: alias N1.N2.N3.F2 = F1;\n// CHECK:STDERR:                     ^~\nalias N1.N2.N3.F2 = F1;\n\n// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+7]]:7: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: fn N1.F1();\n// CHECK:STDERR:       ^~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-6]]:21: error: name `F1` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: alias N1.N2.N3.F2 = F1;\n// CHECK:STDERR:                     ^~\nfn N1.F1();\n// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+7]]:10: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: fn N1.N2.F1();\n// CHECK:STDERR:          ^~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE-14]]:21: error: name `F1` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: alias N1.N2.N3.F2 = F1;\n// CHECK:STDERR:                     ^~\nfn N1.N2.F1();\n// CHECK:STDERR: fail_poison_multiple_scopes.carbon:[[@LINE+4]]:13: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: fn N1.N2.N3.F1();\n// CHECK:STDERR:             ^~\n// CHECK:STDERR:\nfn N1.N2.N3.F1();\n\n// --- fail_alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F();\n\nnamespace N;\n// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:13: error: name `F` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: alias N.F = F;\n// CHECK:STDERR:             ^\n// CHECK:STDERR: fail_alias.carbon:[[@LINE+4]]:9: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: alias N.F = F;\n// CHECK:STDERR:         ^\n// CHECK:STDERR:\nalias N.F = F;\n\n// --- ignored_poison_in_import.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"poison\";\n\n// This doesn't fail.\nfn N.F1();\n\n// --- poison.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// TODO: #4622 This should fail since `N.F1` was poisoned in the api.\nfn N.F1() {}\n\n// --- fail_poison_when_lookup_fails.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nnamespace N;\n// `N.F1` poisoned when not found.\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+7]]:14: error: name `F1` not found [NameNotFound]\n// CHECK:STDERR: alias N.F2 = F1;\n// CHECK:STDERR:              ^~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+3]]:14: error: name `F1` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: alias N.F2 = F1;\n// CHECK:STDERR:              ^~\nalias N.F2 = F1;\n\n// TODO: We should ideally only produce one diagnostic here.\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+7]]:4: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: fn F1();\n// CHECK:STDERR:    ^~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE-7]]:14: error: name `F1` used before it was declared [NameUseBeforeDecl]\n// CHECK:STDERR: alias N.F2 = F1;\n// CHECK:STDERR:              ^~\nfn F1();\n// CHECK:STDERR: fail_poison_when_lookup_fails.carbon:[[@LINE+4]]:6: note: declared here [NameUseBeforeDeclNote]\n// CHECK:STDERR: fn N.F1();\n// CHECK:STDERR:      ^~\n// CHECK:STDERR:\nfn N.F1();\n\n// --- fail_poison_with_lexical_result.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F1() {\n  fn F2();\n\n  class C {\n    // CHECK:STDERR: fail_poison_with_lexical_result.carbon:[[@LINE+3]]:16: error: name `F2` used before it was declared [NameUseBeforeDecl]\n    // CHECK:STDERR:     alias F3 = F2;\n    // CHECK:STDERR:                ^~\n    alias F3 = F2;\n\n    // CHECK:STDERR: fail_poison_with_lexical_result.carbon:[[@LINE+4]]:8: note: declared here [NameUseBeforeDeclNote]\n    // CHECK:STDERR:     fn F2();\n    // CHECK:STDERR:        ^~\n    // CHECK:STDERR:\n    fn F2();\n  }\n}\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/no_definition_in_impl_file.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/no_definition_in_impl_file.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/no_definition_in_impl_file.carbon\n\n// --- decl_in_api_definition_in_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A();\n\n// --- decl_in_api_definition_in_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nfn A();\n\nfn A() {}\n\n// --- use_decl_in_api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// --- use_decl_in_api.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nimport library \"decl_in_api_definition_in_impl\";\n\n// --- decl_only_in_api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn B();\n\n// --- decl_only_in_api.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// --- decl_in_api_decl_in_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn C();\n\n// --- fail_decl_in_api_decl_in_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_decl_in_api_decl_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]\n// CHECK:STDERR: fn C();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nfn C();\n\n// --- decl_only_in_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// --- fail_decl_only_in_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_decl_only_in_impl.impl.carbon:[[@LINE+4]]:1: error: no definition found for declaration in impl file [MissingDefinitionInImpl]\n// CHECK:STDERR: fn D();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nfn D();\n\n// CHECK:STDOUT: --- decl_in_api_definition_in_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_in_api_definition_in_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_46.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_46.2 = import <none>\n// CHECK:STDOUT:   %A.decl.loc4: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %A.decl.loc6: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() [from \"decl_in_api_definition_in_impl.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_decl_in_api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_decl_in_api.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A = import_ref Main//decl_in_api_definition_in_impl, A, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_31.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_31.2 = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_only_in_api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_only_in_api.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.B = import_ref Main//decl_only_in_api, B, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_32.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_32.2 = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_in_api_decl_in_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_decl_in_api_decl_in_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_40.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_40.2 = import <none>\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C [from \"decl_in_api_decl_in_impl.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- decl_only_in_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_decl_only_in_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_33.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_33.2 = import <none>\n// CHECK:STDOUT:   %D.decl: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @D();\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/param_same_name.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/param_same_name.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/param_same_name.carbon\n\nfn F(a: i32);\n\nfn G(a: i32);\n\n// CHECK:STDOUT: --- param_same_name.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %i32);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%a.param: %i32);\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/pattern_in_signature.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/pattern_in_signature.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/pattern_in_signature.carbon\n\n//@dump-sem-ir-begin\nfn F((unused a: {}, unused b: {}), unused c: {}) {}\n//@dump-sem-ir-end\n\n//@dump-sem-ir-begin\nfn CallF(ab: ({}, {}), c: {}) {\n  F(ab, c);\n}\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- pattern_in_signature.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %pattern_type.a96: type = pattern_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %tuple.type.b6b: type = tuple_type (%empty_struct_type, %empty_struct_type) [concrete]\n// CHECK:STDOUT:   %pattern_type.de4: type = pattern_type %tuple.type.b6b [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.b6b = tuple_value (%empty_struct, %empty_struct) [concrete]\n// CHECK:STDOUT:   %CallF.type: type = fn_type @CallF [concrete]\n// CHECK:STDOUT:   %CallF: %CallF.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.a96 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.a96 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.a96 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.a96 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %.loc14_33: %pattern_type.de4 = tuple_pattern (%a.param_patt, %b.param_patt) [concrete]\n// CHECK:STDOUT:     %c.patt: %pattern_type.a96 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.a96 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %empty_struct_type = value_param call_param0\n// CHECK:STDOUT:     %.loc14_18.1: type = splice_block %.loc14_18.3 [concrete = constants.%empty_struct_type] {\n// CHECK:STDOUT:       %.loc14_18.2: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc14_18.3: type = converted %.loc14_18.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %empty_struct_type = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %empty_struct_type = value_param call_param1\n// CHECK:STDOUT:     %.loc14_32.1: type = splice_block %.loc14_32.3 [concrete = constants.%empty_struct_type] {\n// CHECK:STDOUT:       %.loc14_32.2: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc14_32.3: type = converted %.loc14_32.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %b: %empty_struct_type = value_binding b, %b.param\n// CHECK:STDOUT:     %c.param: %empty_struct_type = value_param call_param2\n// CHECK:STDOUT:     %.loc14_47.1: type = splice_block %.loc14_47.3 [concrete = constants.%empty_struct_type] {\n// CHECK:STDOUT:       %.loc14_47.2: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc14_47.3: type = converted %.loc14_47.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %empty_struct_type = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallF.decl: %CallF.type = fn_decl @CallF [concrete = constants.%CallF] {\n// CHECK:STDOUT:     %ab.patt: %pattern_type.de4 = value_binding_pattern ab [concrete]\n// CHECK:STDOUT:     %ab.param_patt: %pattern_type.de4 = value_param_pattern %ab.patt [concrete]\n// CHECK:STDOUT:     %c.patt: %pattern_type.a96 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.a96 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %ab.param: %tuple.type.b6b = value_param call_param0\n// CHECK:STDOUT:     %.loc18_21.1: type = splice_block %.loc18_21.5 [concrete = constants.%tuple.type.b6b] {\n// CHECK:STDOUT:       %.loc18_16: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc18_20: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc18_21.2: %tuple.type.b6b = tuple_literal (%.loc18_16, %.loc18_20) [concrete = constants.%tuple]\n// CHECK:STDOUT:       %.loc18_21.3: type = converted constants.%empty_struct, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %.loc18_21.4: type = converted constants.%empty_struct, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %.loc18_21.5: type = converted %.loc18_21.2, constants.%tuple.type.b6b [concrete = constants.%tuple.type.b6b]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %ab: %tuple.type.b6b = value_binding ab, %ab.param\n// CHECK:STDOUT:     %c.param: %empty_struct_type = value_param call_param1\n// CHECK:STDOUT:     %.loc18_28.1: type = splice_block %.loc18_28.3 [concrete = constants.%empty_struct_type] {\n// CHECK:STDOUT:       %.loc18_28.2: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc18_28.3: type = converted %.loc18_28.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %empty_struct_type = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: %empty_struct_type, %b.param: %empty_struct_type, %c.param: %empty_struct_type) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallF(%ab.param: %tuple.type.b6b, %c.param: %empty_struct_type) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %ab.ref: %tuple.type.b6b = name_ref ab, %ab\n// CHECK:STDOUT:   %c.ref: %empty_struct_type = name_ref c, %c\n// CHECK:STDOUT:   %tuple.elem0: %empty_struct_type = tuple_access %ab.ref, element0\n// CHECK:STDOUT:   %tuple.elem1: %empty_struct_type = tuple_access %ab.ref, element1\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref(%tuple.elem0, %tuple.elem1, %c.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/ref.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// EXTRA-ARGS: --dump-sem-ir-ranges=only\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/ref.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/ref.carbon\n\n// --- ref_return.carbon\n\n//@include-in-dumps\n\nfn F() -> ref i32;\n\nfn G() {\n  let unused ref x: i32 = F();\n}\n\n// CHECK:STDOUT: --- ref_return.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.1da: Core.Form = ref_form %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4_11.1: type = ref_tag %i32\n// CHECK:STDOUT:     %.loc4_11.2: Core.Form = ref_form %i32 [concrete = constants.%.1da]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> ref %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.7ce = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: ref %i32 = call %F.ref()\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %x: ref %i32 = ref_binding x, %F.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/declaration/simple.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/declaration/simple.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/declaration/simple.carbon\n\nfn F();\n\nfn G() { F(); }\n\n// CHECK:STDOUT: --- simple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/basics.carbon",
    "content": "\n// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/basics.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/basics.carbon\n\n// --- fail_incomplete_type.carbon\n\nclass C;\n\n// CHECK:STDERR: fail_incomplete_type.carbon:[[@LINE+7]]:13: error: parameter has incomplete type `C` in function definition [IncompleteTypeInFunctionParam]\n// CHECK:STDERR: fn F(unused n: C) {}\n// CHECK:STDERR:             ^~~~\n// CHECK:STDERR: fail_incomplete_type.carbon:[[@LINE-5]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class C;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn F(unused n: C) {}\n\n// CHECK:STDOUT: --- fail_incomplete_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %n.patt: %pattern_type = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %n.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %n: %C = value_binding n, %n.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%n.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/extern.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/extern.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/extern.carbon\n\n// --- extern_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F() {}\n\n// --- def_for_extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F();\nextern fn F() {}\n\n// --- split_library.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F();\n\n// --- split_library.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nextern fn F() {}\n\n// --- fail_def_extern_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F();\n// CHECK:STDERR: fail_def_extern_mismatch.carbon:[[@LINE+7]]:1: error: redeclarations of `fn F` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: fn F() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_def_extern_mismatch.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F() {}\n\n// --- fail_def_extern_mismatch_reverse.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F();\n// CHECK:STDERR: fail_def_extern_mismatch_reverse.carbon:[[@LINE+7]]:1: error: redeclarations of `fn F` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern fn F() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_def_extern_mismatch_reverse.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn F();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nextern fn F() {}\n\n// --- fail_extern_diag_suppressed.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F();\n// CHECK:STDERR: fail_extern_diag_suppressed.carbon:[[@LINE+7]]:1: error: redeclaration of `fn F` is redundant [RedeclRedundant]\n// CHECK:STDERR: fn F();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR: fail_extern_diag_suppressed.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F();\n// CHECK:STDERR: fail_extern_diag_suppressed.carbon:[[@LINE+7]]:1: error: redeclarations of `fn F` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: fn F() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_extern_diag_suppressed.carbon:[[@LINE-12]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F() {}\n\n// --- fail_extern_decl_after_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {}\n// CHECK:STDERR: fail_extern_decl_after_def.carbon:[[@LINE+7]]:1: error: redeclaration of `fn F` is redundant [RedeclRedundant]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_decl_after_def.carbon:[[@LINE-4]]:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn F() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nextern fn F();\n\n// --- in_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// --- fail_in_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_in_impl.impl.carbon:[[@LINE+4]]:1: error: `extern` entities must have a declaration in the API file [ExternRequiresDeclInApiFile]\n// CHECK:STDERR: extern fn F() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn F() {}\n\n// CHECK:STDOUT: --- extern_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- def_for_extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc4: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %F.decl.loc5: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- split_library.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- split_library.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_29.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_29.2 = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() [from \"split_library.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_def_extern_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc4: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %F.decl.loc12: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_def_extern_mismatch_reverse.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc4: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %F.decl.loc12: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_diag_suppressed.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc4: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %F.decl.loc12: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %F.decl.loc20: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_decl_after_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc4: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %F.decl.loc12: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- in_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_in_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_23.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_23.2 = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/extern_library.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/extern_library.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/extern_library.carbon\n\n// --- one_file_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"one_file\" fn F();\n\n// --- one_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F() {}\n\n// --- two_file_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"two_file\" fn F();\n\n// --- two_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F();\n\n// --- two_file.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nextern fn F() {}\n\n// --- two_file_impl_mismatch_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"two_file_impl_mismatch\" fn F();\n\n// --- two_file_impl_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn F();\n\n// --- fail_two_file_impl_mismatch.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_two_file_impl_mismatch.impl.carbon:[[@LINE+8]]:1: error: redeclarations of `fn F` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: fn F() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_two_file_impl_mismatch.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: two_file_impl_mismatch.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F() {}\n\n// --- no_decl_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"no_decl\" fn F();\n\n// --- no_decl_extern.impl.carbon\n\nimpl library \"no_decl_extern\";\n\n// --- fail_no_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_no_decl.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: no_decl_extern.carbon:4:1: error: owning declaration required for non-owning declaration [MissingOwningDeclarationInApi]\n// CHECK:STDERR: extern library \"no_decl\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimport library \"no_decl_extern\";\n\n// --- indirect_two_file_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"indirect_two_file\" fn F();\n\n// --- fail_indirect_two_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_indirect_two_file.carbon:[[@LINE+5]]:1: in import [InImport]\n// CHECK:STDERR: indirect_two_file_extern.carbon:4:1: error: owning declaration required for non-owning declaration [MissingOwningDeclarationInApi]\n// CHECK:STDERR: extern library \"indirect_two_file\" fn F();\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimport library \"indirect_two_file_extern\";\n\n// --- fail_indirect_two_file.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_indirect_two_file.impl.carbon:[[@LINE+4]]:1: error: `extern` entities must have a declaration in the API file [ExternRequiresDeclInApiFile]\n// CHECK:STDERR: extern fn F() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn F() {}\n\n// --- in_impl_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"in_impl\" fn F();\n\n// --- in_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// --- fail_in_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nimport library \"in_impl_extern\";\n\n// CHECK:STDERR: fail_in_impl.impl.carbon:[[@LINE+4]]:1: error: `extern` entities must have a declaration in the API file [ExternRequiresDeclInApiFile]\n// CHECK:STDERR: extern fn F() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextern fn F() {}\n\n\n// --- cross_package_extern.carbon\n\npackage OtherPackage library \"[[@TEST_NAME]]\";\n\nextern library \"cross_package\" fn Extern();\n\n// --- cross_package.carbon\n\npackage ThisPackage library \"[[@TEST_NAME]]\";\n\nimport OtherPackage library \"cross_package_extern\";\n\n// This call causes the function to be imported.\nfn F() { OtherPackage.Extern(); }\n\n\n// --- unloaded_decl_extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern library \"unloaded_decl\" fn ExternDecl();\n\nfn NonExternDecl();\n\n// --- unloaded_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"unloaded_decl_extern\";\n\nextern fn ExternDecl();\n\n\n// CHECK:STDOUT: --- one_file_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- one_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- two_file_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- two_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- two_file.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_24.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_24.2 = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() [from \"two_file.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- two_file_impl_mismatch_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- two_file_impl_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_two_file_impl_mismatch.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_38.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_38.2 = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() [from \"two_file_impl_mismatch.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- no_decl_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- no_decl_extern.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.F = import_ref Main//no_decl_extern, F, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_30.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_30.2 = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_no_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//no_decl_extern, F, loaded [concrete = constants.%F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- indirect_two_file_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_indirect_two_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//indirect_two_file_extern, F, loaded [concrete = constants.%F]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_indirect_two_file.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_33.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_33.2 = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- in_impl_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- in_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_in_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_23.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_23.2 = import <none>\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- cross_package_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Extern.type: type = fn_type @Extern [concrete]\n// CHECK:STDOUT:   %Extern: %Extern.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Extern = %Extern.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Extern.decl: %Extern.type = fn_decl @Extern [concrete = constants.%Extern] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @Extern();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- cross_package.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Extern.type: type = fn_type @Extern [concrete]\n// CHECK:STDOUT:   %Extern: %Extern.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %OtherPackage: <namespace> = namespace file.%OtherPackage.import, [concrete] {\n// CHECK:STDOUT:     .Extern = %OtherPackage.Extern\n// CHECK:STDOUT:     import OtherPackage//cross_package_extern\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %OtherPackage.Extern: %Extern.type = import_ref OtherPackage//cross_package_extern, Extern, loaded [concrete = constants.%Extern]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .OtherPackage = imports.%OtherPackage\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %OtherPackage.import = import OtherPackage\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %OtherPackage.ref: <namespace> = name_ref OtherPackage, imports.%OtherPackage [concrete = imports.%OtherPackage]\n// CHECK:STDOUT:   %Extern.ref: %Extern.type = name_ref Extern, imports.%OtherPackage.Extern [concrete = constants.%Extern]\n// CHECK:STDOUT:   %Extern.call: init %empty_tuple.type = call %Extern.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @Extern;\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- unloaded_decl_extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %ExternDecl.type: type = fn_type @ExternDecl [concrete]\n// CHECK:STDOUT:   %ExternDecl: %ExternDecl.type = struct_value () [concrete]\n// CHECK:STDOUT:   %NonExternDecl.type: type = fn_type @NonExternDecl [concrete]\n// CHECK:STDOUT:   %NonExternDecl: %NonExternDecl.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .ExternDecl = %ExternDecl.decl\n// CHECK:STDOUT:     .NonExternDecl = %NonExternDecl.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ExternDecl.decl: %ExternDecl.type = fn_decl @ExternDecl [concrete = constants.%ExternDecl] {} {}\n// CHECK:STDOUT:   %NonExternDecl.decl: %NonExternDecl.type = fn_decl @NonExternDecl [concrete = constants.%NonExternDecl] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @ExternDecl();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @NonExternDecl();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- unloaded_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %ExternDecl.type: type = fn_type @ExternDecl [concrete]\n// CHECK:STDOUT:   %ExternDecl: %ExternDecl.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.NonExternDecl = import_ref Main//unloaded_decl_extern, NonExternDecl, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .ExternDecl = %ExternDecl.decl\n// CHECK:STDOUT:     .NonExternDecl = imports.%Main.NonExternDecl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %ExternDecl.decl: %ExternDecl.type = fn_decl @ExternDecl [concrete = constants.%ExternDecl] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @ExternDecl;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/fail_decl_param_mismatch.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/fail_decl_param_mismatch.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/fail_decl_param_mismatch.carbon\n\nfn F();\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+7]]:1: error: redeclaration differs because of parameter count of 1 [RedeclParamCountDiffers]\n// CHECK:STDERR: fn F(unused x: ()) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: note: previously declared with parameter count of 0 [RedeclParamCountPrevious]\n// CHECK:STDERR: fn F();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nfn F(unused x: ()) {}\n\nfn G(x: ());\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+7]]:1: error: redeclaration differs because of parameter count of 0 [RedeclParamCountDiffers]\n// CHECK:STDERR: fn G() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: note: previously declared with parameter count of 1 [RedeclParamCountPrevious]\n// CHECK:STDERR: fn G(x: ());\n// CHECK:STDERR: ^~~~~~~~~~~~\n// CHECK:STDERR:\nfn G() {}\n\nfn H(x: ());\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+4]]:16: error: `Core.Bool` implicitly referenced here, but package `Core` not found [CoreNotFound]\n// CHECK:STDERR: fn H(unused x: bool) {}\n// CHECK:STDERR:                ^~~~\n// CHECK:STDERR:\nfn H(unused x: bool) {}\n\nfn I();\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+7]]:1: error: function redeclaration differs because return type is `()` [FunctionRedeclReturnTypeDiffers]\n// CHECK:STDERR: fn I() -> () { return (); }\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: note: previously declared with no return type [FunctionRedeclReturnTypePreviousNoReturn]\n// CHECK:STDERR: fn I();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nfn I() -> () { return (); }\n\nfn J() -> ();\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+7]]:1: error: function redeclaration differs because no return type is provided [FunctionRedeclReturnTypeDiffersNoReturn]\n// CHECK:STDERR: fn J() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: note: previously declared with return type `()` [FunctionRedeclReturnTypePrevious]\n// CHECK:STDERR: fn J() -> ();\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR:\nfn J() {}\n\nfn K() -> ();\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE+7]]:1: error: function redeclaration differs because return type is `{}` [FunctionRedeclReturnTypeDiffers]\n// CHECK:STDERR: fn K() -> {} { return {}; }\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_decl_param_mismatch.carbon:[[@LINE-4]]:1: note: previously declared with return type `()` [FunctionRedeclReturnTypePrevious]\n// CHECK:STDERR: fn K() -> ();\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR:\nfn K() -> {} { return {}; }\n\n// CHECK:STDOUT: --- fail_decl_param_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type.117dbc.1: type = fn_type @F.loc15 [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F.d98bd5.1: %F.type.117dbc.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %F.type.117dbc.2: type = fn_type @F.loc23 [concrete]\n// CHECK:STDOUT:   %F.d98bd5.2: %F.type.117dbc.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type.90f93f.1: type = fn_type @G.loc25 [concrete]\n// CHECK:STDOUT:   %G.4dbc02.1: %G.type.90f93f.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type.90f93f.2: type = fn_type @G.loc33 [concrete]\n// CHECK:STDOUT:   %G.4dbc02.2: %G.type.90f93f.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %H.type.7917a6.1: type = fn_type @H.loc35 [concrete]\n// CHECK:STDOUT:   %H.414c03.1: %H.type.7917a6.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %H.type.7917a6.2: type = fn_type @H.loc40 [concrete]\n// CHECK:STDOUT:   %H.414c03.2: %H.type.7917a6.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.f30c8e.1: type = fn_type @I.loc42 [concrete]\n// CHECK:STDOUT:   %I.73832e.1: %I.type.f30c8e.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %I.type.f30c8e.2: type = fn_type @I.loc50 [concrete]\n// CHECK:STDOUT:   %I.73832e.2: %I.type.f30c8e.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.type.fe0423.1: type = fn_type @J.loc52 [concrete]\n// CHECK:STDOUT:   %J.6d8208.1: %J.type.fe0423.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.type.fe0423.2: type = fn_type @J.loc60 [concrete]\n// CHECK:STDOUT:   %J.6d8208.2: %J.type.fe0423.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %K.type.4b1c50.1: type = fn_type @K.loc62 [concrete]\n// CHECK:STDOUT:   %K.548a8d.1: %K.type.4b1c50.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %.469: Core.Form = init_form %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.a96: type = pattern_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %K.type.4b1c50.2: type = fn_type @K.loc70 [concrete]\n// CHECK:STDOUT:   %K.548a8d.2: %K.type.4b1c50.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl.loc15\n// CHECK:STDOUT:     .G = %G.decl.loc25\n// CHECK:STDOUT:     .H = %H.decl.loc35\n// CHECK:STDOUT:     .I = %I.decl.loc42\n// CHECK:STDOUT:     .J = %J.decl.loc52\n// CHECK:STDOUT:     .K = %K.decl.loc62\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc15: %F.type.117dbc.1 = fn_decl @F.loc15 [concrete = constants.%F.d98bd5.1] {} {}\n// CHECK:STDOUT:   %F.decl.loc23: %F.type.117dbc.2 = fn_decl @F.loc23 [concrete = constants.%F.d98bd5.2] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.cb1 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc23_17.1: type = splice_block %.loc23_17.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc23_17.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc23_17.3: type = converted %.loc23_17.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: %empty_tuple.type = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl.loc25: %G.type.90f93f.1 = fn_decl @G.loc25 [concrete = constants.%G.4dbc02.1] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.cb1 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc25_10.1: type = splice_block %.loc25_10.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc25_10.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc25_10.3: type = converted %.loc25_10.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: %empty_tuple.type = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl.loc33: %G.type.90f93f.2 = fn_decl @G.loc33 [concrete = constants.%G.4dbc02.2] {} {}\n// CHECK:STDOUT:   %H.decl.loc35: %H.type.7917a6.1 = fn_decl @H.loc35 [concrete = constants.%H.414c03.1] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.cb1 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.cb1 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc35_10.1: type = splice_block %.loc35_10.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc35_10.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc35_10.3: type = converted %.loc35_10.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: %empty_tuple.type = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %H.decl.loc40: %H.type.7917a6.2 = fn_decl @H.loc40 [concrete = constants.%H.414c03.2] {\n// CHECK:STDOUT:     %x.patt: <error> = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: <error> = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: <error> = value_param call_param0\n// CHECK:STDOUT:     %.loc40: type = type_literal <error> [concrete = <error>]\n// CHECK:STDOUT:     %x: <error> = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl.loc42: %I.type.f30c8e.1 = fn_decl @I.loc42 [concrete = constants.%I.73832e.1] {} {}\n// CHECK:STDOUT:   %I.decl.loc50: %I.type.f30c8e.2 = fn_decl @I.loc50 [concrete = constants.%I.73832e.2] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc50_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc50_12.2: type = converted %.loc50_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc50_12.3: Core.Form = init_form %.loc50_12.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.decl.loc52: %J.type.fe0423.1 = fn_decl @J.loc52 [concrete = constants.%J.6d8208.1] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc52_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc52_12.2: type = converted %.loc52_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc52_12.3: Core.Form = init_form %.loc52_12.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.decl.loc60: %J.type.fe0423.2 = fn_decl @J.loc60 [concrete = constants.%J.6d8208.2] {} {}\n// CHECK:STDOUT:   %K.decl.loc62: %K.type.4b1c50.1 = fn_decl @K.loc62 [concrete = constants.%K.548a8d.1] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc62_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc62_12.2: type = converted %.loc62_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc62_12.3: Core.Form = init_form %.loc62_12.2 [concrete = constants.%.262]\n// CHECK:STDOUT:     %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %K.decl.loc70: %K.type.4b1c50.2 = fn_decl @K.loc70 [concrete = constants.%K.548a8d.2] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.a96 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.a96 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc70_12.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc70_12.2: type = converted %.loc70_12.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %.loc70_12.3: Core.Form = init_form %.loc70_12.2 [concrete = constants.%.469]\n// CHECK:STDOUT:     %return.param: ref %empty_struct_type = out_param call_param0\n// CHECK:STDOUT:     %return: ref %empty_struct_type = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F.loc15();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F.loc23(%x.param: %empty_tuple.type) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G.loc25(%x.param: %empty_tuple.type);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G.loc33() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @H.loc35(%x.param: %empty_tuple.type);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @H.loc40(%x.param: <error>) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @I.loc42();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @I.loc50() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc50_24.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc50_24.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc50_25: init %empty_tuple.type = converted %.loc50_24.1, %.loc50_24.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   return %.loc50_25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @J.loc52() -> out %return.param: %empty_tuple.type;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @J.loc60() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @K.loc62() -> out %return.param: %empty_tuple.type;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @K.loc70() -> out %return.param: %empty_struct_type {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc70_24.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc70_24.2: init %empty_struct_type = struct_init () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc70_25: init %empty_struct_type = converted %.loc70_24.1, %.loc70_24.2 [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   return %.loc70_25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/fail_local_decl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/fail_local_decl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/fail_local_decl.carbon\n\n// --- fail_virtual.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {\n  // CHECK:STDERR: fail_virtual.carbon:[[@LINE+4]]:3: error: `default` not allowed; requires interface scope [ModifierRequiresInterface]\n  // CHECK:STDERR:   default fn F();\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  default fn F();\n  // CHECK:STDERR: fail_virtual.carbon:[[@LINE+4]]:3: error: `override` not allowed; requires class scope [ModifierRequiresClass]\n  // CHECK:STDERR:   override fn G();\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR:\n  override fn G();\n  // CHECK:STDERR: fail_virtual.carbon:[[@LINE+4]]:3: error: `virtual` not allowed; requires class scope [ModifierRequiresClass]\n  // CHECK:STDERR:   virtual fn H();\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  virtual fn H();\n}\n\n// --- fail_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {\n  // CHECK:STDERR: fail_access.carbon:[[@LINE+4]]:3: error: `private` not allowed; requires class or file scope [ModifierPrivateNotAllowed]\n  // CHECK:STDERR:   private var unused v: {} = {};\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  private var unused v: {} = {};\n  // CHECK:STDERR: fail_access.carbon:[[@LINE+4]]:3: error: `protected` not allowed; requires class scope [ModifierProtectedNotAllowed]\n  // CHECK:STDERR:   protected var unused w: {} = {};\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR:\n  protected var unused w: {} = {};\n}\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/fail_redef.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/fail_redef.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/fail_redef.carbon\n\nfn F() {}\n// CHECK:STDERR: fail_redef.carbon:[[@LINE+7]]:1: error: redefinition of `fn F` [RedeclRedef]\n// CHECK:STDERR: fn F() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_redef.carbon:[[@LINE-4]]:1: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR: fn F() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn F() {}\n\n// CHECK:STDOUT: --- fail_redef.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type.117dbc.1: type = fn_type @F.loc15 [concrete]\n// CHECK:STDOUT:   %F.d98bd5.1: %F.type.117dbc.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %F.type.117dbc.2: type = fn_type @F.loc23 [concrete]\n// CHECK:STDOUT:   %F.d98bd5.2: %F.type.117dbc.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl.loc15\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc15: %F.type.117dbc.1 = fn_decl @F.loc15 [concrete = constants.%F.d98bd5.1] {} {}\n// CHECK:STDOUT:   %F.decl.loc23: %F.type.117dbc.2 = fn_decl @F.loc23 [concrete = constants.%F.d98bd5.2] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F.loc15() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F.loc23() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/forward_decl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/forward_decl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/forward_decl.carbon\n\nfn Foo();\n\nfn Foo() {}\n\n// CHECK:STDOUT: --- forward_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc15\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc15: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc17: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/implicit_import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/implicit_import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/implicit_import.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A();\n\n// --- basic.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nfn A() {}\n\n// --- extern_api.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn A();\n\n// --- fail_extern_api.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE+8]]:1: error: redeclarations of `fn A` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: fn A() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_extern_api.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_api.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn A();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn A() {}\n\n// --- extern_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A();\n\n// --- fail_extern_impl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE+8]]:1: error: redeclarations of `fn A` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern fn A() {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_extern_impl.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern_impl.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nextern fn A() {}\n\n// --- redecl_after_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A() {}\n\n// --- fail_redecl_after_def.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_redecl_after_def.impl.carbon:[[@LINE+8]]:1: error: redeclaration of `fn A` is redundant [RedeclRedundant]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR: fail_redecl_after_def.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: redecl_after_def.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn A() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn A();\n\n// --- redef_after_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A() {}\n\n// --- fail_redef_after_def.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_redef_after_def.impl.carbon:[[@LINE+8]]:1: error: redefinition of `fn A` [RedeclRedef]\n// CHECK:STDERR: fn A() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_redef_after_def.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: redef_after_def.carbon:4:1: note: previously defined here [RedeclPrevDef]\n// CHECK:STDERR: fn A() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn A() {}\n\n// --- def_alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A();\nalias B = A;\n\n// --- fail_def_alias.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_def_alias.impl.carbon:[[@LINE+8]]:4: error: duplicate name `B` being declared in the same scope [NameDeclDuplicate]\n// CHECK:STDERR: fn B() {}\n// CHECK:STDERR:    ^\n// CHECK:STDERR: fail_def_alias.impl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: def_alias.carbon:5:7: note: name is previously declared here [NameDeclPrevious]\n// CHECK:STDERR: alias B = A;\n// CHECK:STDERR:       ^\n// CHECK:STDERR:\nfn B() {}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- basic.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_21.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_21.2 = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() [from \"basic.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_api.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_api.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_26.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_26.2 = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @A() [from \"extern_api.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extern_impl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_27.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_27.2 = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() [from \"extern_impl.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- redecl_after_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_redecl_after_def.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_32.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_32.2 = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A [from \"redecl_after_def.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- redef_after_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_redef_after_def.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type.8165c1.1: type = fn_type @A.1 [concrete]\n// CHECK:STDOUT:   %A.8aef9d.1: %A.type.8165c1.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %A.type.8165c1.2: type = fn_type @A.loc12 [concrete]\n// CHECK:STDOUT:   %A.8aef9d.2: %A.type.8165c1.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A: %A.type.8165c1.1 = import_ref Main//redef_after_def, A, loaded [concrete = constants.%A.8aef9d.1]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_31.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_31.2 = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type.8165c1.2 = fn_decl @A.loc12 [concrete = constants.%A.8aef9d.2] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.1 [from \"redef_after_def.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.loc12() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- def_alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, %A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %B: %A.type = alias_binding B, %A.decl [concrete = constants.%A]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_def_alias.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A = import_ref Main//def_alias, A, unloaded\n// CHECK:STDOUT:   %Main.B: %A.type = import_ref Main//def_alias, B, loaded [concrete = constants.%A]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_25.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_25.2 = import <none>\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A [from \"def_alias.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/import.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/import.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/import.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- fns.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn A() {}\nfn B(b: i32) -> i32 { return b; }\nfn C(c: (i32,)) -> {.c: i32} { return {.c = c.0}; }\nfn D();\n\n// --- extern.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nextern fn A();\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- basics.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"fns\";\n\nvar a: () = A();\nvar b: i32 = B(1);\nvar c: {.c: i32} = C((1,));\n\n// --- fail_def_ownership.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"fns\";\n\n// CHECK:STDERR: fail_def_ownership.carbon:[[@LINE+8]]:1: error: redeclaration of `fn A` is redundant [RedeclRedundant]\n// CHECK:STDERR: fn A() {};\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_def_ownership.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: fns.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn A() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn A() {};\n// CHECK:STDERR: fail_def_ownership.carbon:[[@LINE+8]]:1: error: redeclaration of `fn B` is redundant [RedeclRedundant]\n// CHECK:STDERR: fn B(b: i32) -> i32;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_def_ownership.carbon:[[@LINE-14]]:1: in import [InImport]\n// CHECK:STDERR: fns.carbon:5:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn B(b: i32) -> i32 { return b; }\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn B(b: i32) -> i32;\n\n// --- fail_redecl_then_def.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extern\";\n\n// CHECK:STDERR: fail_redecl_then_def.carbon:[[@LINE+8]]:1: error: redeclarations of `fn A` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: fn A();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR: fail_redecl_then_def.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: extern.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn A();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn A();\n\n// CHECK:STDERR: fail_redecl_then_def.carbon:[[@LINE+8]]:1: error: redeclarations of `fn A` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: fn A() {}\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR: fail_redecl_then_def.carbon:[[@LINE-15]]:1: in import [InImport]\n// CHECK:STDERR: extern.carbon:4:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: extern fn A();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn A() {}\n\n// --- fail_mix_extern_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"fns\";\n\n// CHECK:STDERR: fail_mix_extern_decl.carbon:[[@LINE+8]]:1: error: redeclarations of `fn D` must match use of `extern` [RedeclExternMismatch]\n// CHECK:STDERR: extern fn D();\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_mix_extern_decl.carbon:[[@LINE-5]]:1: in import [InImport]\n// CHECK:STDERR: fns.carbon:7:1: note: previously declared here [RedeclPrevDecl]\n// CHECK:STDERR: fn D();\n// CHECK:STDERR: ^~~~~~~\n// CHECK:STDERR:\nextern fn D();\n\nfn D() {}\n\n// CHECK:STDOUT: --- fns.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.85c: type = tuple_type (type) [concrete]\n// CHECK:STDOUT:   %tuple.896: %tuple.type.85c = tuple_value (%i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.b74: type = pattern_type %tuple.type.a1c [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %.da9: Core.Form = init_form %struct_type.c [concrete]\n// CHECK:STDOUT:   %pattern_type.688: type = pattern_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc5_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5: Core.Form = init_form %i32.loc5_17 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc5_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: %C.type = fn_decl @C [concrete = constants.%C] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.b74 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.b74 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.688 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.688 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6_25: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:     %.loc6_28: Core.Form = init_form %struct_type.c [concrete = constants.%.da9]\n// CHECK:STDOUT:     %c.param: %tuple.type.a1c = value_param call_param0\n// CHECK:STDOUT:     %.loc6_14.1: type = splice_block %.loc6_14.3 [concrete = constants.%tuple.type.a1c] {\n// CHECK:STDOUT:       %i32.loc6_10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc6_14.2: %tuple.type.85c = tuple_literal (%i32.loc6_10) [concrete = constants.%tuple.896]\n// CHECK:STDOUT:       %.loc6_14.3: type = converted %.loc6_14.2, constants.%tuple.type.a1c [concrete = constants.%tuple.type.a1c]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c: %tuple.type.a1c = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %struct_type.c = out_param call_param1\n// CHECK:STDOUT:     %return: ref %struct_type.c = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B(%b.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %b.ref: %i32 = name_ref b, %b\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc5_30.1: <bound method> = bound_method %b.ref, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc5_30.2: <bound method> = bound_method %b.ref, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc5_30.2(%b.ref)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C(%c.param: %tuple.type.a1c) -> out %return.param: %struct_type.c {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %c.ref: %tuple.type.a1c = name_ref c, %c\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %tuple.elem0: %i32 = tuple_access %c.ref, element0\n// CHECK:STDOUT:   %.loc6_48.1: %struct_type.c = struct_literal (%tuple.elem0)\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc6_46.1: <bound method> = bound_method %tuple.elem0, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc6_46.2: <bound method> = bound_method %tuple.elem0, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_46.2(%tuple.elem0)\n// CHECK:STDOUT:   %.loc6_48.2: init %struct_type.c = struct_init (%Int.as.Copy.impl.Op.call)\n// CHECK:STDOUT:   %.loc6_49: init %struct_type.c = converted %.loc6_48.1, %.loc6_48.2\n// CHECK:STDOUT:   return %.loc6_49\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @D();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extern.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @A();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- basics.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.688: type = pattern_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %C.type: type = fn_type @C [concrete]\n// CHECK:STDOUT:   %C: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %tuple.type.a1c: type = tuple_type (%i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.378: %tuple.type.985 = tuple_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %tuple.246: %tuple.type.a1c = tuple_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A: %A.type = import_ref Main//fns, A, loaded [concrete = constants.%A]\n// CHECK:STDOUT:   %Main.B: %B.type = import_ref Main//fns, B, loaded [concrete = constants.%B]\n// CHECK:STDOUT:   %Main.C: %C.type = import_ref Main//fns, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.D = import_ref Main//fns, D, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .a = %a\n// CHECK:STDOUT:     .b = %b\n// CHECK:STDOUT:     .c = %c\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.cb1 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.cb1 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_tuple.type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_tuple.type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt [concrete]\n// CHECK:STDOUT:   %i32.loc7: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var [concrete = %b.var]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.688 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.688 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %struct_type.c = var %c.var_patt [concrete]\n// CHECK:STDOUT:   %.loc8: type = splice_block %struct_type.c [concrete = constants.%struct_type.c] {\n// CHECK:STDOUT:     %i32.loc8: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %i32} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c: ref %struct_type.c = ref_binding c, %c.var [concrete = %c.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A [from \"fns.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B [from \"fns.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C [from \"fns.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, imports.%Main.A [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %empty_tuple.type = call %A.ref()\n// CHECK:STDOUT:   assign file.%a.var, %A.call\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, imports.%Main.B [concrete = constants.%B]\n// CHECK:STDOUT:   %int_1.loc7: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc7: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc7_16.1: <bound method> = bound_method %int_1.loc7, %impl.elem0.loc7 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc7: <specific function> = specific_function %impl.elem0.loc7, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_16.2: <bound method> = bound_method %int_1.loc7, %specific_fn.loc7 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7: init %i32 = call %bound_method.loc7_16.2(%int_1.loc7) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc7_16.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc7 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc7_16.2: %i32 = converted %int_1.loc7, %.loc7_16.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %B.call: init %i32 = call %B.ref(%.loc7_16.2)\n// CHECK:STDOUT:   assign file.%b.var, %B.call\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %int_1.loc8: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc8_25.1: %tuple.type.985 = tuple_literal (%int_1.loc8) [concrete = constants.%tuple.378]\n// CHECK:STDOUT:   %impl.elem0.loc8: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc8_25.1: <bound method> = bound_method %int_1.loc8, %impl.elem0.loc8 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc8: <specific function> = specific_function %impl.elem0.loc8, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_25.2: <bound method> = bound_method %int_1.loc8, %specific_fn.loc8 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8: init %i32 = call %bound_method.loc8_25.2(%int_1.loc8) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc8_25.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc8 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc8_25.3: %i32 = converted %int_1.loc8, %.loc8_25.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %tuple: %tuple.type.a1c = tuple_value (%.loc8_25.3) [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %.loc8_25.4: %tuple.type.a1c = converted %.loc8_25.1, %tuple [concrete = constants.%tuple.246]\n// CHECK:STDOUT:   %C.call: init %struct_type.c = call %C.ref(%.loc8_25.4)\n// CHECK:STDOUT:   assign file.%c.var, %C.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_def_ownership.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type.8165c1.1: type = fn_type @A.1 [concrete]\n// CHECK:STDOUT:   %A.8aef9d.1: %A.type.8165c1.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %A.type.8165c1.2: type = fn_type @A.loc14 [concrete]\n// CHECK:STDOUT:   %A.8aef9d.2: %A.type.8165c1.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A: %A.type.8165c1.1 = import_ref Main//fns, A, loaded [concrete = constants.%A.8aef9d.1]\n// CHECK:STDOUT:   %Main.C = import_ref Main//fns, C, unloaded\n// CHECK:STDOUT:   %Main.D = import_ref Main//fns, D, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %A.decl: %A.type.8165c1.2 = fn_decl @A.loc14 [concrete = constants.%A.8aef9d.2] {} {}\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {\n// CHECK:STDOUT:     %i32.loc23_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc23: Core.Form = init_form %i32.loc23_17 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc23_9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.1 [from \"fns.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A.loc14() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B [from \"fns.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_redecl_then_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = %A.decl.loc14\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %A.decl.loc14: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %A.decl.loc24: %A.type = fn_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: extern fn @A() [from \"extern.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_mix_extern_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %D.type: type = fn_type @D [concrete]\n// CHECK:STDOUT:   %D: %D.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.A = import_ref Main//fns, A, unloaded\n// CHECK:STDOUT:   %Main.B = import_ref Main//fns, B, unloaded\n// CHECK:STDOUT:   %Main.C = import_ref Main//fns, C, unloaded\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .A = imports.%Main.A\n// CHECK:STDOUT:     .B = imports.%Main.B\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = %D.decl.loc14\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %D.decl.loc14: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %D.decl.loc16: %D.type = fn_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @D() [from \"fns.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/import_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/import_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/import_access.carbon\n\n// ============================================================================\n// Setup files\n// ============================================================================\n\n// --- def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nprivate fn Def() {}\n\n// --- forward_with_def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nprivate fn ForwardWithDef();\n\nfn ForwardWithDef() {}\n\n// --- forward.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nprivate fn Forward();\n\n// ============================================================================\n// Test files\n// ============================================================================\n\n// --- def.impl.carbon\n\nimpl package Test library \"[[@TEST_NAME]]\";\n\nvar f: () = Def();\n\n// --- fail_local_def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nimport library \"def\";\n\n// CHECK:STDERR: fail_local_def.carbon:[[@LINE+4]]:13: error: name `Def` not found [NameNotFound]\n// CHECK:STDERR: var f: () = Def();\n// CHECK:STDERR:             ^~~\n// CHECK:STDERR:\nvar f: () = Def();\n\n// --- fail_other_def.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nimport Test library \"def\";\n\n// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:13: error: member name `Def` not found in `Test` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: var f: () = Test.Def();\n// CHECK:STDERR:             ^~~~~~~~\n// CHECK:STDERR:\nvar f: () = Test.Def();\n\n// --- forward_with_def.impl.carbon\n\nimpl package Test library \"[[@TEST_NAME]]\";\n\nvar f: () = ForwardWithDef();\n\n// --- fail_local_forward_with_def.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nimport library \"forward_with_def\";\n\n// CHECK:STDERR: fail_local_forward_with_def.carbon:[[@LINE+4]]:13: error: name `ForwardWithDef` not found [NameNotFound]\n// CHECK:STDERR: var f: () = ForwardWithDef();\n// CHECK:STDERR:             ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar f: () = ForwardWithDef();\n\n// --- fail_other_forward_with_def.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nimport Test library \"forward_with_def\";\n\n// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:13: error: member name `ForwardWithDef` not found in `Test` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: var f: () = Test.ForwardWithDef();\n// CHECK:STDERR:             ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar f: () = Test.ForwardWithDef();\n\n// --- forward.impl.carbon\n\nimpl package Test library \"[[@TEST_NAME]]\";\n\nvar f: () = Forward();\n\nfn Forward() {}\n\n// --- fail_local_forward.carbon\n\npackage Test library \"[[@TEST_NAME]]\";\n\nimport library \"forward\";\n\n// CHECK:STDERR: fail_local_forward.carbon:[[@LINE+4]]:13: error: name `Forward` not found [NameNotFound]\n// CHECK:STDERR: var f: () = Forward();\n// CHECK:STDERR:             ^~~~~~~\n// CHECK:STDERR:\nvar f: () = Forward();\n\n// --- fail_other_forward.carbon\n\npackage Other library \"[[@TEST_NAME]]\";\n\nimport Test library \"forward\";\n\n// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+4]]:13: error: member name `Forward` not found in `Test` [MemberNameNotFoundInInstScope]\n// CHECK:STDERR: var f: () = Test.Forward();\n// CHECK:STDERR:             ^~~~~~~~~~~~\n// CHECK:STDERR:\nvar f: () = Test.Forward();\n\n// --- todo_fail_private_on_redecl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nprivate fn Redecl();\n\nprivate fn Redecl() {}\n\n// CHECK:STDOUT: --- def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Def.type: type = fn_type @Def [concrete]\n// CHECK:STDOUT:   %Def: %Def.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Def [private] = %Def.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Def.decl: %Def.type = fn_decl @Def [concrete = constants.%Def] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Def() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- forward_with_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %ForwardWithDef.type: type = fn_type @ForwardWithDef [concrete]\n// CHECK:STDOUT:   %ForwardWithDef: %ForwardWithDef.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .ForwardWithDef [private] = %ForwardWithDef.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ForwardWithDef.decl.loc4: %ForwardWithDef.type = fn_decl @ForwardWithDef [concrete = constants.%ForwardWithDef] {} {}\n// CHECK:STDOUT:   %ForwardWithDef.decl.loc6: %ForwardWithDef.type = fn_decl @ForwardWithDef [concrete = constants.%ForwardWithDef] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ForwardWithDef() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- forward.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Forward.type: type = fn_type @Forward [concrete]\n// CHECK:STDOUT:   %Forward: %Forward.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Forward [private] = %Forward.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Forward.decl: %Forward.type = fn_decl @Forward [concrete = constants.%Forward] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Forward();\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- def.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Def.type: type = fn_type @Def [concrete]\n// CHECK:STDOUT:   %Def: %Def.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test.Def: %Def.type = import_ref Test//def, Def, loaded [concrete = constants.%Def]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Def [private] = imports.%Test.Def\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_9.1: type = splice_block %.loc4_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc4_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc4_9.3: type = converted %.loc4_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Def [from \"def.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Def.ref: %Def.type = name_ref Def, imports.%Test.Def [concrete = constants.%Def]\n// CHECK:STDOUT:   %Def.call: init %empty_tuple.type = call %Def.ref()\n// CHECK:STDOUT:   assign file.%f.var, %Def.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_local_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:     .Def = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_9.1: type = splice_block %.loc10_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc10_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc10_9.3: type = converted %.loc10_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Def.ref: <error> = name_ref Def, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%f.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_other_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test: <namespace> = namespace file.%Test.import, [concrete] {\n// CHECK:STDOUT:     .Def = <poisoned>\n// CHECK:STDOUT:     import Test//def\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Test = imports.%Test\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_9.1: type = splice_block %.loc10_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc10_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc10_9.3: type = converted %.loc10_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Test.ref: <namespace> = name_ref Test, imports.%Test [concrete = imports.%Test]\n// CHECK:STDOUT:   %Def.ref: <error> = name_ref Def, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%f.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- forward_with_def.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %ForwardWithDef.type: type = fn_type @ForwardWithDef [concrete]\n// CHECK:STDOUT:   %ForwardWithDef: %ForwardWithDef.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test.ForwardWithDef: %ForwardWithDef.type = import_ref Test//forward_with_def, ForwardWithDef, loaded [concrete = constants.%ForwardWithDef]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .ForwardWithDef [private] = imports.%Test.ForwardWithDef\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_9.1: type = splice_block %.loc4_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc4_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc4_9.3: type = converted %.loc4_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ForwardWithDef [from \"forward_with_def.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ForwardWithDef.ref: %ForwardWithDef.type = name_ref ForwardWithDef, imports.%Test.ForwardWithDef [concrete = constants.%ForwardWithDef]\n// CHECK:STDOUT:   %ForwardWithDef.call: init %empty_tuple.type = call %ForwardWithDef.ref()\n// CHECK:STDOUT:   assign file.%f.var, %ForwardWithDef.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_local_forward_with_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:     .ForwardWithDef = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_9.1: type = splice_block %.loc10_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc10_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc10_9.3: type = converted %.loc10_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ForwardWithDef.ref: <error> = name_ref ForwardWithDef, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%f.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_other_forward_with_def.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test: <namespace> = namespace file.%Test.import, [concrete] {\n// CHECK:STDOUT:     .ForwardWithDef = <poisoned>\n// CHECK:STDOUT:     import Test//forward_with_def\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Test = imports.%Test\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_9.1: type = splice_block %.loc10_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc10_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc10_9.3: type = converted %.loc10_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Test.ref: <namespace> = name_ref Test, imports.%Test [concrete = imports.%Test]\n// CHECK:STDOUT:   %ForwardWithDef.ref: <error> = name_ref ForwardWithDef, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%f.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- forward.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Forward.type: type = fn_type @Forward [concrete]\n// CHECK:STDOUT:   %Forward: %Forward.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test.Forward: %Forward.type = import_ref Test//forward, Forward, loaded [concrete = constants.%Forward]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Forward [private] = %Forward.decl\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_9.1: type = splice_block %.loc4_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc4_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc4_9.3: type = converted %.loc4_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT:   %Forward.decl: %Forward.type = fn_decl @Forward [concrete = constants.%Forward] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Forward() [from \"forward.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Forward.ref: %Forward.type = name_ref Forward, imports.%Test.Forward [concrete = constants.%Forward]\n// CHECK:STDOUT:   %Forward.call: init %empty_tuple.type = call %Forward.ref()\n// CHECK:STDOUT:   assign file.%f.var, %Forward.call\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_local_forward.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:     .Forward = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_9.1: type = splice_block %.loc10_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc10_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc10_9.3: type = converted %.loc10_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Forward.ref: <error> = name_ref Forward, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%f.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_other_forward.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Test: <namespace> = namespace file.%Test.import, [concrete] {\n// CHECK:STDOUT:     .Forward = <poisoned>\n// CHECK:STDOUT:     import Test//forward\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Test = imports.%Test\n// CHECK:STDOUT:     .f = %f\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test.import = import Test\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %f.patt: %pattern_type = ref_binding_pattern f [concrete]\n// CHECK:STDOUT:     %f.var_patt: %pattern_type = var_pattern %f.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f.var: ref %empty_tuple.type = var %f.var_patt [concrete]\n// CHECK:STDOUT:   %.loc10_9.1: type = splice_block %.loc10_9.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc10_9.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc10_9.3: type = converted %.loc10_9.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %f: ref %empty_tuple.type = ref_binding f, %f.var [concrete = %f.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Test.ref: <namespace> = name_ref Test, imports.%Test [concrete = imports.%Test]\n// CHECK:STDOUT:   %Forward.ref: <error> = name_ref Forward, <error> [concrete = <error>]\n// CHECK:STDOUT:   assign file.%f.var, <error>\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- todo_fail_private_on_redecl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Redecl.type: type = fn_type @Redecl [concrete]\n// CHECK:STDOUT:   %Redecl: %Redecl.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Redecl [private] = %Redecl.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Redecl.decl.loc4: %Redecl.type = fn_decl @Redecl [concrete = constants.%Redecl] {} {}\n// CHECK:STDOUT:   %Redecl.decl.loc6: %Redecl.type = fn_decl @Redecl [concrete = constants.%Redecl] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Redecl() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/order.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/order.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/order.carbon\n\nfn Foo() {}\nfn Bar() {}\nfn Baz() {}\n\n// CHECK:STDOUT: --- order.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Bar.type: type = fn_type @Bar [concrete]\n// CHECK:STDOUT:   %Bar: %Bar.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Baz.type: type = fn_type @Baz [concrete]\n// CHECK:STDOUT:   %Baz: %Baz.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Bar = %Bar.decl\n// CHECK:STDOUT:     .Baz = %Baz.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {} {}\n// CHECK:STDOUT:   %Bar.decl: %Bar.type = fn_decl @Bar [concrete = constants.%Bar] {} {}\n// CHECK:STDOUT:   %Baz.decl: %Baz.type = fn_decl @Baz [concrete = constants.%Baz] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Bar() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Baz() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/params_one.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/params_one.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/params_one.carbon\n\nfn Foo(unused a: i32) {}\n\n// CHECK:STDOUT: --- params_one.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/params_one_comma.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/params_one_comma.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/params_one_comma.carbon\n\nfn Foo(unused a: i32,) {}\n\n// CHECK:STDOUT: --- params_one_comma.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/params_two.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/params_two.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/params_two.carbon\n\nfn Foo(unused a: i32, unused b: i32) {}\n\n// CHECK:STDOUT: --- params_two.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc15_18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc15_33: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/params_two_comma.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/params_two_comma.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/params_two_comma.carbon\n\nfn Foo(unused a: i32, unused b: i32,) {}\n\n// CHECK:STDOUT: --- params_two_comma.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.7ce = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.7ce = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc15_18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %a: %i32 = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc15_33: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %b: %i32 = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %i32, %b.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/params_zero.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/params_zero.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/params_zero.carbon\n\nfn Foo() {}\n\n// CHECK:STDOUT: --- params_zero.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/definition/syntactic_merge.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/definition/syntactic_merge.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/definition/syntactic_merge.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nfn Foo(a: C);\nfn Foo(unused a: C) {}\n\nfn Bar(a: D);\nfn Bar(unused a: D) {}\n\n// --- spacing.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn Foo [ ] ( a : C );\nfn Foo[](unused a: C) {}\n\n// --- fail_parens.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn Foo(a: C);\n// CHECK:STDERR: fail_parens.carbon:[[@LINE+7]]:18: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: fn Foo(unused a: (C)) {}\n// CHECK:STDERR:                  ^\n// CHECK:STDERR: fail_parens.carbon:[[@LINE-4]]:11: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR: fn Foo(a: C);\n// CHECK:STDERR:           ^\n// CHECK:STDERR:\nfn Foo(unused a: (C)) {}\n\n// --- fail_only_implicit_params.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\n// CHECK:STDERR: fail_only_implicit_params.carbon:[[@LINE+8]]:8: error: implicit parameters of functions must be constant or `self` [ImplictParamMustBeConstant]\n// CHECK:STDERR: fn Foo[a: C];\n// CHECK:STDERR:        ^~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_only_implicit_params.carbon:[[@LINE+4]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo]\n// CHECK:STDERR: fn Foo[a: C];\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Foo[a: C];\n// CHECK:STDERR: fail_only_implicit_params.carbon:[[@LINE+8]]:8: error: implicit parameters of functions must be constant or `self` [ImplictParamMustBeConstant]\n// CHECK:STDERR: fn Foo[a: (C)] {}\n// CHECK:STDERR:        ^~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_only_implicit_params.carbon:[[@LINE+4]]:1: error: semantics TODO: `function with positional parameters` [SemanticsTodo]\n// CHECK:STDERR: fn Foo[a: (C)] {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn Foo[a: (C)] {}\n\n// --- todo_fail_raw_identifier.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn Foo(a: C);\nfn Foo(unused a: r#C) {}\n\n// --- two_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nfn Foo(a: C);\nfn Bar(a: D);\n\n// --- two_file.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nfn Foo(unused a: C) {}\nfn Bar(unused a: D) {}\n\n// --- fail_name_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nfn Foo(a: C);\n// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE+7]]:15: error: redeclaration differs at parameter 1 [RedeclParamDiffers]\n// CHECK:STDERR: fn Foo(unused b: D) {}\n// CHECK:STDERR:               ^~~~\n// CHECK:STDERR: fail_name_mismatch.carbon:[[@LINE-4]]:8: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n// CHECK:STDERR: fn Foo(a: C);\n// CHECK:STDERR:        ^~~~\n// CHECK:STDERR:\nfn Foo(unused b: D) {}\n\n// --- fail_alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nfn Foo(a: C);\n// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:18: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: fn Foo(unused a: D) {}\n// CHECK:STDERR:                  ^\n// CHECK:STDERR: fail_alias.carbon:[[@LINE-4]]:11: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR: fn Foo(a: C);\n// CHECK:STDERR:           ^\n// CHECK:STDERR:\nfn Foo(unused a: D) {}\n\n// --- fail_deduced_alias.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nfn Foo[a:! C]();\n// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE+7]]:19: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: fn Foo[unused a:! D]() {}\n// CHECK:STDERR:                   ^\n// CHECK:STDERR: fail_deduced_alias.carbon:[[@LINE-4]]:12: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR: fn Foo[a:! C]();\n// CHECK:STDERR:            ^\n// CHECK:STDERR:\nfn Foo[unused a:! D]() {}\n\n// --- todo_fail_alias_in_return.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\nalias D = C;\n\nfn Foo() -> C;\nfn Foo() -> D { return {}; }\n\n// --- alias_two_file.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn Foo(a: C);\n\n// --- todo_fail_alias_two_file.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\nalias D = C;\n\nfn Foo(unused a: D) {}\n\n// --- fail_repeat_const.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\n\nfn Foo(a: const C);\n// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+11]]:18: warning: `const` applied repeatedly to the same type has no additional effect [RepeatedConst]\n// CHECK:STDERR: fn Foo(unused a: const (const C)) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE+7]]:24: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers]\n// CHECK:STDERR: fn Foo(unused a: const (const C)) {}\n// CHECK:STDERR:                        ^\n// CHECK:STDERR: fail_repeat_const.carbon:[[@LINE-8]]:17: note: comparing with previous declaration here [RedeclParamSyntaxPrevious]\n// CHECK:STDERR: fn Foo(a: const C);\n// CHECK:STDERR:                 ^\n// CHECK:STDERR:\nfn Foo(unused a: const (const C)) {}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Bar.type: type = fn_type @Bar [concrete]\n// CHECK:STDOUT:   %Bar: %Bar.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc7\n// CHECK:STDOUT:     .Bar = %Bar.decl.loc10\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param.loc7: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a.loc7: %C = value_binding a, %a.param.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc8: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param.loc8: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a.loc8: %C = value_binding a, %a.param.loc8\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Bar.decl.loc10: %Bar.type = fn_decl @Bar [concrete = constants.%Bar] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param.loc10: %C = value_param call_param0\n// CHECK:STDOUT:     %D.ref.loc10: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     %a.loc10: %C = value_binding a, %a.param.loc10\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Bar.decl.loc11: %Bar.type = fn_decl @Bar [concrete = constants.%Bar] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param.loc11: %C = value_param call_param0\n// CHECK:STDOUT:     %D.ref.loc11: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     %a.loc11: %C = value_binding a, %a.param.loc11\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param.loc8: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Bar(%a.param.loc11: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- spacing.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param.loc6: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc6: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a.loc6: %C = value_binding a, %a.param.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param.loc7: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a.loc7: %C = value_binding a, %a.param.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param.loc7: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_parens.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.1: type = fn_type @Foo.loc6 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.1: %Foo.type.47530a.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.2: type = fn_type @Foo.loc14 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.2: %Foo.type.47530a.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type.47530a.1 = fn_decl @Foo.loc6 [concrete = constants.%Foo.9ec12f.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc14: %Foo.type.47530a.2 = fn_decl @Foo.loc14 [concrete = constants.%Foo.9ec12f.2] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc6(%a.param: %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc14(%a.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_only_implicit_params.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.1: type = fn_type @Foo.loc14 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.1: %Foo.type.47530a.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.2: type = fn_type @Foo.loc23 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.2: %Foo.type.47530a.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc14\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc14: %Foo.type.47530a.1 = fn_decl @Foo.loc14 [concrete = constants.%Foo.9ec12f.1] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc23: %Foo.type.47530a.2 = fn_decl @Foo.loc23 [concrete = constants.%Foo.9ec12f.2] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc14();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc23() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- todo_fail_raw_identifier.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param.loc6: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc6: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a.loc6: %C = value_binding a, %a.param.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param.loc7: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a.loc7: %C = value_binding a, %a.param.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param.loc7: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- two_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Bar.type: type = fn_type @Bar [concrete]\n// CHECK:STDOUT:   %Bar: %Bar.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Bar = %Bar.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Bar.decl: %Bar.type = fn_decl @Bar [concrete = constants.%Bar] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Bar(%a.param: %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- two_file.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Bar.type: type = fn_type @Bar [concrete]\n// CHECK:STDOUT:   %Bar: %Bar.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//two_file, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//two_file, D, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//two_file, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//two_file, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .Bar = %Bar.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_24.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_24.2 = import <none>\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Bar.decl: %Bar.type = fn_decl @Bar [concrete = constants.%Bar] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"two_file.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %C) [from \"two_file.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Bar(%a.param: %C) [from \"two_file.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_name_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.1: type = fn_type @Foo.loc7 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.1: %Foo.type.47530a.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.2: type = fn_type @Foo.loc15 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.2: %Foo.type.47530a.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type.47530a.1 = fn_decl @Foo.loc7 [concrete = constants.%Foo.9ec12f.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc15: %Foo.type.47530a.2 = fn_decl @Foo.loc15 [concrete = constants.%Foo.9ec12f.2] {\n// CHECK:STDOUT:     %b.patt: %pattern_type = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %b.param: %C = value_param call_param0\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     %b: %C = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc7(%a.param: %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc15(%b.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.1: type = fn_type @Foo.loc7 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.1: %Foo.type.47530a.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.2: type = fn_type @Foo.loc15 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.2: %Foo.type.47530a.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type.47530a.1 = fn_decl @Foo.loc7 [concrete = constants.%Foo.9ec12f.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc15: %Foo.type.47530a.2 = fn_decl @Foo.loc15 [concrete = constants.%Foo.9ec12f.2] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc7(%a.param: %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc15(%a.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_deduced_alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %a.9daf47.1: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type.47530a.1: type = fn_type @Foo.loc7 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.1: %Foo.type.47530a.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %a.9daf47.2: %C = symbolic_binding a, 0 [symbolic]\n// CHECK:STDOUT:   %Foo.type.47530a.2: type = fn_type @Foo.loc15 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.2: %Foo.type.47530a.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type.47530a.1 = fn_decl @Foo.loc7 [concrete = constants.%Foo.9ec12f.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc7_8.2: %C = symbolic_binding a, 0 [symbolic = %a.loc7_8.1 (constants.%a.9daf47.1)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc15: %Foo.type.47530a.2 = fn_decl @Foo.loc15 [concrete = constants.%Foo.9ec12f.2] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15: type = splice_block %D.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a.loc15_15.3: %C = symbolic_binding a, 0 [symbolic = %a.loc15_15.2 (constants.%a.9daf47.2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Foo.loc7(%a.loc7_8.2: %C) {\n// CHECK:STDOUT:   %a.loc7_8.1: %C = symbolic_binding a, 0 [symbolic = %a.loc7_8.1 (constants.%a.9daf47.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Foo.loc15(%a.loc15_15.3: %C) {\n// CHECK:STDOUT:   %a.loc15_15.1: %C = symbolic_binding a, 0 [symbolic = %a.loc15_15.1 (constants.%a.9daf47.1)]\n// CHECK:STDOUT:   %a.loc15_15.2: %C = symbolic_binding a, 0 [symbolic = %a.loc15_15.2 (constants.%a.9daf47.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc7(constants.%a.9daf47.1) {\n// CHECK:STDOUT:   %a.loc7_8.1 => constants.%a.9daf47.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Foo.loc15(constants.%a.9daf47.2) {\n// CHECK:STDOUT:   %a.loc15_15.1 => constants.%a.9daf47.2\n// CHECK:STDOUT:   %a.loc15_15.2 => constants.%a.9daf47.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- todo_fail_alias_in_return.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl.loc7: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc7: Core.Form = init_form %C.ref [concrete = constants.%.a69]\n// CHECK:STDOUT:     %return.param.loc7: ref %C = out_param call_param0\n// CHECK:STDOUT:     %return.loc7: ref %C = return_slot %return.param.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc8: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %return.patt: %pattern_type = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc8_13: Core.Form = init_form %D.ref [concrete = constants.%.a69]\n// CHECK:STDOUT:     %return.param.loc8: ref %C = out_param call_param0\n// CHECK:STDOUT:     %return.loc8: ref %C = return_slot %return.param.loc8\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo() -> out %return.param.loc8: %C {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc8_25.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc8_25.2: init %C to %return.param.loc8 = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc8_26: init %C = converted %.loc8_25.1, %.loc8_25.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   return %.loc8_26 to %return.param.loc8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- alias_two_file.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %C);\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- todo_fail_alias_two_file.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Foo.type: type = fn_type @Foo [concrete]\n// CHECK:STDOUT:   %Foo: %Foo.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//alias_two_file, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//alias_two_file, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//alias_two_file, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .Foo = %Foo.decl\n// CHECK:STDOUT:     .D = %D\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_30.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_30.2 = import <none>\n// CHECK:STDOUT:   %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %D: type = alias_binding D, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %Foo.decl: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %C = value_param call_param0\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D [concrete = constants.%C]\n// CHECK:STDOUT:     %a: %C = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"alias_two_file.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo(%a.param: %C) [from \"alias_two_file.carbon\"] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_repeat_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %const: type = const_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %const [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.1: type = fn_type @Foo.loc6 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.1: %Foo.type.47530a.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Foo.type.47530a.2: type = fn_type @Foo.loc18 [concrete]\n// CHECK:STDOUT:   %Foo.9ec12f.2: %Foo.type.47530a.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Foo = %Foo.decl.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Foo.decl.loc6: %Foo.type.47530a.1 = fn_decl @Foo.loc6 [concrete = constants.%Foo.9ec12f.1] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %const = value_param call_param0\n// CHECK:STDOUT:     %.loc6: type = splice_block %const [concrete = constants.%const] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %const: type = const_type %C.ref [concrete = constants.%const]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %const = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Foo.decl.loc18: %Foo.type.47530a.2 = fn_decl @Foo.loc18 [concrete = constants.%Foo.9ec12f.2] {\n// CHECK:STDOUT:     %a.patt: %pattern_type = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %a.param: %const = value_param call_param0\n// CHECK:STDOUT:     %.loc18: type = splice_block %const.loc18_18 [concrete = constants.%const] {\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:       %const.loc18_25: type = const_type %C.ref [concrete = constants.%const]\n// CHECK:STDOUT:       %const.loc18_18: type = const_type %const.loc18_25 [concrete = constants.%const]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: %const = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc6(%a.param: %const);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Foo.loc18(%a.param: %const) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/call.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/call.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/call.carbon\n\n// --- explicit.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn Function(T:! Core.Copy, x: T) -> T {\n  return x;\n}\n//@dump-sem-ir-end\n\nfn CallGeneric(T:! Core.Copy, x: T) -> T {\n  //@dump-sem-ir-begin\n  return Function(T, x);\n  //@dump-sem-ir-end\n}\n\nfn CallGenericPtr(T:! type, x: T*) -> T* {\n  //@dump-sem-ir-begin\n  return Function(T*, x);\n  //@dump-sem-ir-end\n}\n\nclass C {}\n\nfn CallSpecific(x: C*) -> C* {\n  //@dump-sem-ir-begin\n  return Function(C*, x);\n  //@dump-sem-ir-end\n}\n\n// --- deduced.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn Function[T:! Core.Copy](x: T) -> T {\n  return x;\n}\n//@dump-sem-ir-end\n\nfn CallGeneric(T:! Core.Copy, x: T) -> T {\n  //@dump-sem-ir-begin\n  return Function(x);\n  //@dump-sem-ir-end\n}\n\nfn CallGenericPtr(T:! type, x: T*) -> T* {\n  //@dump-sem-ir-begin\n  return Function(x);\n  //@dump-sem-ir-end\n}\n\nclass C {}\n\nfn CallSpecific(x: C*) -> C* {\n  //@dump-sem-ir-begin\n  return Function(x);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- explicit.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Function.type: type = fn_type @Function [concrete]\n// CHECK:STDOUT:   %Function: %Function.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T.67d [symbolic]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %Function.specific_fn.a87: <specific function> = specific_function %Function, @Function(%T.035) [symbolic]\n// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.facet.c25: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]\n// CHECK:STDOUT:   %Function.specific_fn.919: <specific function> = specific_function %Function, @Function(%Copy.facet.c25) [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %.de8: Core.Form = init_form %ptr.31e [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.411: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.ed9: %ptr.as.Copy.impl.Op.type.411 = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.17a: <witness> = complete_type_witness %ptr.31e [concrete]\n// CHECK:STDOUT:   %Copy.facet.a7f: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Function.specific_fn.9da: <specific function> = specific_function %Function, @Function(%Copy.facet.a7f) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.c25) [symbolic]\n// CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet.c25 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.1c7: %.299 = impl_witness_access %Copy.lookup_impl_witness.2e6, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.366: <specific function> = specific_impl_function %impl.elem0.1c7, @Copy.WithSelf.Op(%Copy.facet.c25) [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.259: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.a7f) [concrete]\n// CHECK:STDOUT:   %.64b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.259, %Copy.facet.a7f [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.ed9, @ptr.as.Copy.impl.Op(%C) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Function.decl: %Function.type = fn_decl @Function [concrete = constants.%Function] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @Function.%pattern_type (%pattern_type.9b9f0c.2) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @Function.%pattern_type (%pattern_type.9b9f0c.2) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @Function.%pattern_type (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @Function.%pattern_type (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc5_37: %Copy.type = name_ref T, %T.loc5_13.2 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type.loc5_37: type = facet_access_type %T.ref.loc5_37 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc5_37.3: type = converted %T.ref.loc5_37, %T.as_type.loc5_37 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc5_37.4: Core.Form = init_form %.loc5_37.3 [symbolic = %.loc5_37.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:     %.loc5_21: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_13.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:     %x.param: @Function.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc5_31.1: type = splice_block %.loc5_31.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref.loc5_31: %Copy.type = name_ref T, %T.loc5_13.2 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc5_31: type = facet_access_type %T.ref.loc5_31 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc5_31.2: type = converted %T.ref.loc5_31, %T.as_type.loc5_31 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @Function.%T.binding.as_type (%T.binding.as_type) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @Function.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @Function.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Function(%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc5_13.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc5_13.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:   %.loc5_37.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc5_37.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc5_13.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.loc5_13.1) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc6: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T.loc5_13.1 [symbolic = %.loc6 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2: @Function.%.loc6 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2: <specific function> = specific_impl_function %impl.elem0.loc6_10.2, @Copy.WithSelf.Op(%T.loc5_13.1) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @Function.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @Function.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @Function.%T.binding.as_type (%T.binding.as_type) = name_ref x, %x\n// CHECK:STDOUT:     %impl.elem0.loc6_10.1: @Function.%.loc6 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %x.ref, %impl.elem0.loc6_10.1\n// CHECK:STDOUT:     %specific_impl_fn.loc6_10.1: <specific function> = specific_impl_function %impl.elem0.loc6_10.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %x.ref, %specific_impl_fn.loc6_10.1\n// CHECK:STDOUT:     %.loc5_37.1: ref @Function.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Function.%T.binding.as_type (%T.binding.as_type) to %.loc5_37.1 = call %bound_method.loc6_10.2(%x.ref)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallGeneric(%T.loc10_16.2: %Copy.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %Function.specific_fn.loc12_10.2: <specific function> = specific_function constants.%Function, @Function(%T.loc10_16.1) [symbolic = %Function.specific_fn.loc12_10.2 (constants.%Function.specific_fn.a87)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @CallGeneric.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @CallGeneric.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %Function.ref: %Function.type = name_ref Function, file.%Function.decl [concrete = constants.%Function]\n// CHECK:STDOUT:     %T.ref.loc12: %Copy.type = name_ref T, %T.loc10_16.2 [symbolic = %T.loc10_16.1 (constants.%T.035)]\n// CHECK:STDOUT:     %x.ref: @CallGeneric.%T.binding.as_type (%T.binding.as_type) = name_ref x, %x\n// CHECK:STDOUT:     %.loc12: %Copy.type = converted constants.%T.binding.as_type, constants.%T.035 [symbolic = %T.loc10_16.1 (constants.%T.035)]\n// CHECK:STDOUT:     %Function.specific_fn.loc12_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%T.035) [symbolic = %Function.specific_fn.loc12_10.2 (constants.%Function.specific_fn.a87)]\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %Function.call: init @CallGeneric.%T.binding.as_type (%T.binding.as_type) to %.loc10_40.1 = call %Function.specific_fn.loc12_10.1(%x.ref)\n// CHECK:STDOUT:     return %Function.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallGenericPtr(%T.loc16_19.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %.loc18_24.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc16_19.1) [symbolic = %.loc18_24.3 (constants.%.2f2)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_33.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]\n// CHECK:STDOUT:   %Copy.facet.loc18_24.3: %Copy.type = facet_value %ptr.loc16_33.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet.loc18_24.3 (constants.%Copy.facet.c25)]\n// CHECK:STDOUT:   %Function.specific_fn.loc18_10.2: <specific function> = specific_function constants.%Function, @Function(%Copy.facet.loc18_24.3) [symbolic = %Function.specific_fn.loc18_10.2 (constants.%Function.specific_fn.919)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @CallGenericPtr.%ptr.loc16_33.1 (%ptr.e8f)) -> out %return.param: @CallGenericPtr.%ptr.loc16_33.1 (%ptr.e8f) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %Function.ref: %Function.type = name_ref Function, file.%Function.decl [concrete = constants.%Function]\n// CHECK:STDOUT:     %T.ref.loc18: type = name_ref T, %T.loc16_19.2 [symbolic = %T.loc16_19.1 (constants.%T.67d)]\n// CHECK:STDOUT:     %ptr.loc18: type = ptr_type %T.ref.loc18 [symbolic = %ptr.loc16_33.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     %x.ref: @CallGenericPtr.%ptr.loc16_33.1 (%ptr.e8f) = name_ref x, %x\n// CHECK:STDOUT:     %Copy.facet.loc18_24.1: %Copy.type = facet_value %ptr.loc18, (constants.%Copy.lookup_impl_witness.2e6) [symbolic = %Copy.facet.loc18_24.3 (constants.%Copy.facet.c25)]\n// CHECK:STDOUT:     %.loc18_24.1: %Copy.type = converted %ptr.loc18, %Copy.facet.loc18_24.1 [symbolic = %Copy.facet.loc18_24.3 (constants.%Copy.facet.c25)]\n// CHECK:STDOUT:     %Copy.facet.loc18_24.2: %Copy.type = facet_value constants.%ptr.e8f, (constants.%Copy.lookup_impl_witness.2e6) [symbolic = %Copy.facet.loc18_24.3 (constants.%Copy.facet.c25)]\n// CHECK:STDOUT:     %.loc18_24.2: %Copy.type = converted constants.%ptr.e8f, %Copy.facet.loc18_24.2 [symbolic = %Copy.facet.loc18_24.3 (constants.%Copy.facet.c25)]\n// CHECK:STDOUT:     %Function.specific_fn.loc18_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%Copy.facet.c25) [symbolic = %Function.specific_fn.loc18_10.2 (constants.%Function.specific_fn.919)]\n// CHECK:STDOUT:     %Function.call: init @CallGenericPtr.%ptr.loc16_33.1 (%ptr.e8f) = call %Function.specific_fn.loc18_10.1(%x.ref)\n// CHECK:STDOUT:     return %Function.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallSpecific(%x.param: %ptr.31e) -> out %return.param: %ptr.31e {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Function.ref: %Function.type = name_ref Function, file.%Function.decl [concrete = constants.%Function]\n// CHECK:STDOUT:   %C.ref.loc26: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %ptr.loc26: type = ptr_type %C.ref.loc26 [concrete = constants.%ptr.31e]\n// CHECK:STDOUT:   %x.ref: %ptr.31e = name_ref x, %x\n// CHECK:STDOUT:   %Copy.facet.loc26_24.1: %Copy.type = facet_value %ptr.loc26, (constants.%Copy.impl_witness.2c7) [concrete = constants.%Copy.facet.a7f]\n// CHECK:STDOUT:   %.loc26_24.1: %Copy.type = converted %ptr.loc26, %Copy.facet.loc26_24.1 [concrete = constants.%Copy.facet.a7f]\n// CHECK:STDOUT:   %Copy.facet.loc26_24.2: %Copy.type = facet_value constants.%ptr.31e, (constants.%Copy.impl_witness.2c7) [concrete = constants.%Copy.facet.a7f]\n// CHECK:STDOUT:   %.loc26_24.2: %Copy.type = converted constants.%ptr.31e, %Copy.facet.loc26_24.2 [concrete = constants.%Copy.facet.a7f]\n// CHECK:STDOUT:   %Function.specific_fn: <specific function> = specific_function %Function.ref, @Function(constants.%Copy.facet.a7f) [concrete = constants.%Function.specific_fn.9da]\n// CHECK:STDOUT:   %Function.call: init %ptr.31e = call %Function.specific_fn(%x.ref)\n// CHECK:STDOUT:   return %Function.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Function(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:   %.loc5_37.2 => constants.%.076a48.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.67c\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.lookup_impl_witness.58d\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.735e75.2\n// CHECK:STDOUT:   %.loc6 => constants.%.023\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2 => constants.%impl.elem0.594\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2 => constants.%specific_impl_fn.bdc\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGeneric(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc10_16.1 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:   %.loc10_40.2 => constants.%.076a48.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericPtr(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc16_19.1 => constants.%T.67d\n// CHECK:STDOUT:   %ptr.loc16_33.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT:   %.loc16_40.1 => constants.%.cb6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Function(constants.%Copy.facet.c25) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%Copy.facet.c25\n// CHECK:STDOUT:   %T.binding.as_type => constants.%ptr.e8f\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT:   %.loc5_37.2 => constants.%.cb6\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.ef1\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.lookup_impl_witness.2e6\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.d82\n// CHECK:STDOUT:   %.loc6 => constants.%.299\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2 => constants.%impl.elem0.1c7\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2 => constants.%specific_impl_fn.366\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Function(constants.%Copy.facet.a7f) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%Copy.facet.a7f\n// CHECK:STDOUT:   %T.binding.as_type => constants.%ptr.31e\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.506\n// CHECK:STDOUT:   %.loc5_37.2 => constants.%.de8\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.17a\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.2c7\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.259\n// CHECK:STDOUT:   %.loc6 => constants.%.64b\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2 => constants.%ptr.as.Copy.impl.Op.ed9\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2 => constants.%ptr.as.Copy.impl.Op.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- deduced.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %pattern_type.ce2: type = pattern_type %Copy.type [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Function.type: type = fn_type @Function [concrete]\n// CHECK:STDOUT:   %Function: %Function.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T.67d [symbolic]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %Function.specific_fn.a87: <specific function> = specific_function %Function, @Function(%T.035) [symbolic]\n// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.facet.c25: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]\n// CHECK:STDOUT:   %Function.specific_fn.919: <specific function> = specific_function %Function, @Function(%Copy.facet.c25) [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %ptr.31e: type = ptr_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.506: type = pattern_type %ptr.31e [concrete]\n// CHECK:STDOUT:   %.de8: Core.Form = init_form %ptr.31e [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.2c7: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.411: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%C) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.ed9: %ptr.as.Copy.impl.Op.type.411 = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.17a: <witness> = complete_type_witness %ptr.31e [concrete]\n// CHECK:STDOUT:   %Copy.facet.a7f: %Copy.type = facet_value %ptr.31e, (%Copy.impl_witness.2c7) [concrete]\n// CHECK:STDOUT:   %Function.specific_fn.9da: <specific function> = specific_function %Function, @Function(%Copy.facet.a7f) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.c25) [symbolic]\n// CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet.c25 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.1c7: %.299 = impl_witness_access %Copy.lookup_impl_witness.2e6, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.366: <specific function> = specific_impl_function %impl.elem0.1c7, @Copy.WithSelf.Op(%Copy.facet.c25) [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.259: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.a7f) [concrete]\n// CHECK:STDOUT:   %.64b: type = fn_type_with_self_type %Copy.WithSelf.Op.type.259, %Copy.facet.a7f [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.ed9, @ptr.as.Copy.impl.Op(%C) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %Function.decl: %Function.type = fn_decl @Function [concrete = constants.%Function] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.ce2 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @Function.%pattern_type (%pattern_type.9b9f0c.2) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @Function.%pattern_type (%pattern_type.9b9f0c.2) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @Function.%pattern_type (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @Function.%pattern_type (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc5_37: %Copy.type = name_ref T, %T.loc5_13.2 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:     %T.as_type.loc5_37: type = facet_access_type %T.ref.loc5_37 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc5_37.3: type = converted %T.ref.loc5_37, %T.as_type.loc5_37 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc5_37.4: Core.Form = init_form %.loc5_37.3 [symbolic = %.loc5_37.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:     %.loc5_21: type = splice_block %Copy.ref [concrete = constants.%Copy.type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Copy.ref: type = name_ref Copy, imports.%Core.Copy [concrete = constants.%Copy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_13.2: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:     %x.param: @Function.%T.binding.as_type (%T.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc5_31.1: type = splice_block %.loc5_31.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)] {\n// CHECK:STDOUT:       %T.ref.loc5_31: %Copy.type = name_ref T, %T.loc5_13.2 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type.loc5_31: type = facet_access_type %T.ref.loc5_31 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc5_31.2: type = converted %T.ref.loc5_31, %T.as_type.loc5_31 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @Function.%T.binding.as_type (%T.binding.as_type) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @Function.%T.binding.as_type (%T.binding.as_type) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @Function.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Function(%T.loc5_13.2: %Copy.type) {\n// CHECK:STDOUT:   %T.loc5_13.1: %Copy.type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc5_13.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:   %.loc5_37.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc5_37.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc5_13.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.loc5_13.1) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc6: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T.loc5_13.1 [symbolic = %.loc6 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2: @Function.%.loc6 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2: <specific function> = specific_impl_function %impl.elem0.loc6_10.2, @Copy.WithSelf.Op(%T.loc5_13.1) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @Function.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @Function.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @Function.%T.binding.as_type (%T.binding.as_type) = name_ref x, %x\n// CHECK:STDOUT:     %impl.elem0.loc6_10.1: @Function.%.loc6 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %x.ref, %impl.elem0.loc6_10.1\n// CHECK:STDOUT:     %specific_impl_fn.loc6_10.1: <specific function> = specific_impl_function %impl.elem0.loc6_10.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %x.ref, %specific_impl_fn.loc6_10.1\n// CHECK:STDOUT:     %.loc5_37.1: ref @Function.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Function.%T.binding.as_type (%T.binding.as_type) to %.loc5_37.1 = call %bound_method.loc6_10.2(%x.ref)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallGeneric(%T.loc10_16.2: %Copy.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %Function.specific_fn.loc12_10.2: <specific function> = specific_function constants.%Function, @Function(%T.loc10_16.1) [symbolic = %Function.specific_fn.loc12_10.2 (constants.%Function.specific_fn.a87)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @CallGeneric.%T.binding.as_type (%T.binding.as_type)) -> out %return.param: @CallGeneric.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %Function.ref: %Function.type = name_ref Function, file.%Function.decl [concrete = constants.%Function]\n// CHECK:STDOUT:     %x.ref: @CallGeneric.%T.binding.as_type (%T.binding.as_type) = name_ref x, %x\n// CHECK:STDOUT:     %.loc12: %Copy.type = converted constants.%T.binding.as_type, constants.%T.035 [symbolic = %T.loc10_16.1 (constants.%T.035)]\n// CHECK:STDOUT:     %Function.specific_fn.loc12_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%T.035) [symbolic = %Function.specific_fn.loc12_10.2 (constants.%Function.specific_fn.a87)]\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %Function.call: init @CallGeneric.%T.binding.as_type (%T.binding.as_type) to %.loc10_40.1 = call %Function.specific_fn.loc12_10.1(%x.ref)\n// CHECK:STDOUT:     return %Function.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallGenericPtr(%T.loc16_19.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %.loc18_20.2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc16_19.1) [symbolic = %.loc18_20.2 (constants.%.2f2)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_33.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]\n// CHECK:STDOUT:   %Copy.facet.loc18_20.2: %Copy.type = facet_value %ptr.loc16_33.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet.loc18_20.2 (constants.%Copy.facet.c25)]\n// CHECK:STDOUT:   %Function.specific_fn.loc18_10.2: <specific function> = specific_function constants.%Function, @Function(%Copy.facet.loc18_20.2) [symbolic = %Function.specific_fn.loc18_10.2 (constants.%Function.specific_fn.919)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @CallGenericPtr.%ptr.loc16_33.1 (%ptr.e8f)) -> out %return.param: @CallGenericPtr.%ptr.loc16_33.1 (%ptr.e8f) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %Function.ref: %Function.type = name_ref Function, file.%Function.decl [concrete = constants.%Function]\n// CHECK:STDOUT:     %x.ref: @CallGenericPtr.%ptr.loc16_33.1 (%ptr.e8f) = name_ref x, %x\n// CHECK:STDOUT:     %Copy.facet.loc18_20.1: %Copy.type = facet_value constants.%ptr.e8f, (constants.%Copy.lookup_impl_witness.2e6) [symbolic = %Copy.facet.loc18_20.2 (constants.%Copy.facet.c25)]\n// CHECK:STDOUT:     %.loc18_20.1: %Copy.type = converted constants.%ptr.e8f, %Copy.facet.loc18_20.1 [symbolic = %Copy.facet.loc18_20.2 (constants.%Copy.facet.c25)]\n// CHECK:STDOUT:     %Function.specific_fn.loc18_10.1: <specific function> = specific_function %Function.ref, @Function(constants.%Copy.facet.c25) [symbolic = %Function.specific_fn.loc18_10.2 (constants.%Function.specific_fn.919)]\n// CHECK:STDOUT:     %Function.call: init @CallGenericPtr.%ptr.loc16_33.1 (%ptr.e8f) = call %Function.specific_fn.loc18_10.1(%x.ref)\n// CHECK:STDOUT:     return %Function.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallSpecific(%x.param: %ptr.31e) -> out %return.param: %ptr.31e {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Function.ref: %Function.type = name_ref Function, file.%Function.decl [concrete = constants.%Function]\n// CHECK:STDOUT:   %x.ref: %ptr.31e = name_ref x, %x\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value constants.%ptr.31e, (constants.%Copy.impl_witness.2c7) [concrete = constants.%Copy.facet.a7f]\n// CHECK:STDOUT:   %.loc26: %Copy.type = converted constants.%ptr.31e, %Copy.facet [concrete = constants.%Copy.facet.a7f]\n// CHECK:STDOUT:   %Function.specific_fn: <specific function> = specific_function %Function.ref, @Function(constants.%Copy.facet.a7f) [concrete = constants.%Function.specific_fn.9da]\n// CHECK:STDOUT:   %Function.call: init %ptr.31e = call %Function.specific_fn(%x.ref)\n// CHECK:STDOUT:   return %Function.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Function(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:   %.loc5_37.2 => constants.%.076a48.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.67c\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.lookup_impl_witness.58d\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.735e75.2\n// CHECK:STDOUT:   %.loc6 => constants.%.023\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2 => constants.%impl.elem0.594\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2 => constants.%specific_impl_fn.bdc\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGeneric(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc10_16.1 => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:   %.loc10_40.2 => constants.%.076a48.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericPtr(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc16_19.1 => constants.%T.67d\n// CHECK:STDOUT:   %ptr.loc16_33.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT:   %.loc16_40.1 => constants.%.cb6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Function(constants.%Copy.facet.c25) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%Copy.facet.c25\n// CHECK:STDOUT:   %T.binding.as_type => constants.%ptr.e8f\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT:   %.loc5_37.2 => constants.%.cb6\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.ef1\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.lookup_impl_witness.2e6\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.d82\n// CHECK:STDOUT:   %.loc6 => constants.%.299\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2 => constants.%impl.elem0.1c7\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2 => constants.%specific_impl_fn.366\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Function(constants.%Copy.facet.a7f) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%Copy.facet.a7f\n// CHECK:STDOUT:   %T.binding.as_type => constants.%ptr.31e\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.506\n// CHECK:STDOUT:   %.loc5_37.2 => constants.%.de8\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.17a\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.2c7\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.259\n// CHECK:STDOUT:   %.loc6 => constants.%.64b\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2 => constants.%ptr.as.Copy.impl.Op.ed9\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2 => constants.%ptr.as.Copy.impl.Op.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/call_method_on_generic_facet.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/call_method_on_generic_facet.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/call_method_on_generic_facet.carbon\n\ninterface Generic(Scalar:! type) {\n  fn F();\n}\n\nclass GenericParam {}\n\nclass ImplsGeneric {}\nimpl ImplsGeneric as Generic(GenericParam) {\n  fn F() {}\n}\n\ninterface Other {\n  fn G();\n}\nimpl ImplsGeneric as Other {\n  fn G();\n}\n\nfn CallGenericMethod(T:! type, U:! Generic(T)) {\n  U.F();\n}\n\nfn G() {\n  CallGenericMethod(GenericParam, ImplsGeneric);\n}\n\n// CHECK:STDOUT: --- call_method_on_generic_facet.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %Scalar: type = symbolic_binding Scalar, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.835: type = generic_interface_type @Generic [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Generic.generic: %Generic.type.835 = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.type.03dff7.1: type = facet_type <@Generic, @Generic(%Scalar)> [symbolic]\n// CHECK:STDOUT:   %Self.15d2d5.1: %Generic.type.03dff7.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.74390a.1: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%Scalar, %Self.15d2d5.1) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.baf95a.1: %Generic.WithSelf.F.type.74390a.1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.22afda.1: type = assoc_entity_type @Generic, @Generic(%Scalar) [symbolic]\n// CHECK:STDOUT:   %assoc0.e0dc00.1: %Generic.assoc_type.22afda.1 = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %GenericParam: type = class_type @GenericParam [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %ImplsGeneric: type = class_type @ImplsGeneric [concrete]\n// CHECK:STDOUT:   %Generic.type.498: type = facet_type <@Generic, @Generic(%GenericParam)> [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness @ImplsGeneric.as.Generic.impl.%Generic.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.1f5: %Generic.type.498 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.a23: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Self.15d2d5.1) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.fe0: %Generic.WithSelf.F.type.a23 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.6dc: type = assoc_entity_type @Generic, @Generic(%GenericParam) [concrete]\n// CHECK:STDOUT:   %assoc0.717: %Generic.assoc_type.6dc = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.type: type = fn_type @ImplsGeneric.as.Generic.impl.F [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F: %ImplsGeneric.as.Generic.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value %ImplsGeneric, (%Generic.impl_witness) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.c86: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT:   %Generic.WithSelf.F.1fd: %Generic.WithSelf.F.type.c86 = struct_value () [concrete]\n// CHECK:STDOUT:   %Other.type: type = facet_type <@Other> [concrete]\n// CHECK:STDOUT:   %Self.8c4: %Other.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Other.WithSelf.G.type.acd: type = fn_type @Other.WithSelf.G, @Other.WithSelf(%Self.8c4) [symbolic]\n// CHECK:STDOUT:   %Other.WithSelf.G.63d: %Other.WithSelf.G.type.acd = struct_value () [symbolic]\n// CHECK:STDOUT:   %Other.assoc_type: type = assoc_entity_type @Other [concrete]\n// CHECK:STDOUT:   %assoc0.205: %Other.assoc_type = assoc_entity element0, @Other.WithSelf.%Other.WithSelf.G.decl [concrete]\n// CHECK:STDOUT:   %Other.impl_witness: <witness> = impl_witness @ImplsGeneric.as.Other.impl.%Other.impl_witness_table [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Other.impl.G.type: type = fn_type @ImplsGeneric.as.Other.impl.G [concrete]\n// CHECK:STDOUT:   %ImplsGeneric.as.Other.impl.G: %ImplsGeneric.as.Other.impl.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Other.facet: %Other.type = facet_value %ImplsGeneric, (%Other.impl_witness) [concrete]\n// CHECK:STDOUT:   %Other.WithSelf.G.type.1df: type = fn_type @Other.WithSelf.G, @Other.WithSelf(%Other.facet) [concrete]\n// CHECK:STDOUT:   %Other.WithSelf.G.13d: %Other.WithSelf.G.type.1df = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Generic.type.03dff7.2: type = facet_type <@Generic, @Generic(%T)> [symbolic]\n// CHECK:STDOUT:   %pattern_type.c49: type = pattern_type %Generic.type.03dff7.2 [symbolic]\n// CHECK:STDOUT:   %U: %Generic.type.03dff7.2 = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %CallGenericMethod.type: type = fn_type @CallGenericMethod [concrete]\n// CHECK:STDOUT:   %CallGenericMethod: %CallGenericMethod.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Self.15d2d5.2: %Generic.type.03dff7.2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.74390a.2: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%T, %Self.15d2d5.1) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.baf95a.2: %Generic.WithSelf.F.type.74390a.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Generic.assoc_type.22afda.2: type = assoc_entity_type @Generic, @Generic(%T) [symbolic]\n// CHECK:STDOUT:   %assoc0.e0dc00.2: %Generic.assoc_type.22afda.2 = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Generic.type.03dff7.2 [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type.56e: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%T, %U) [symbolic]\n// CHECK:STDOUT:   %Generic.WithSelf.F.a99: %Generic.WithSelf.F.type.56e = struct_value () [symbolic]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 1, %U [symbolic]\n// CHECK:STDOUT:   %Generic.lookup_impl_witness: <witness> = lookup_impl_witness %U, @Generic, @Generic(%T) [symbolic]\n// CHECK:STDOUT:   %.ab3: type = fn_type_with_self_type %Generic.WithSelf.F.type.56e, %U [symbolic]\n// CHECK:STDOUT:   %impl.elem0: %.ab3 = impl_witness_access %Generic.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn: <specific function> = specific_impl_function %impl.elem0, @Generic.WithSelf.F(%T, %U) [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cba: type = pattern_type %Generic.type.498 [concrete]\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn: <specific function> = specific_function %CallGenericMethod, @CallGenericMethod(%GenericParam, %Generic.facet) [concrete]\n// CHECK:STDOUT:   %complete_type.57a: <witness> = complete_type_witness %Generic.type.498 [concrete]\n// CHECK:STDOUT:   %.fcf: type = fn_type_with_self_type %Generic.WithSelf.F.type.c86, %Generic.facet [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Generic = %Generic.decl\n// CHECK:STDOUT:     .GenericParam = %GenericParam.decl\n// CHECK:STDOUT:     .ImplsGeneric = %ImplsGeneric.decl\n// CHECK:STDOUT:     .Other = %Other.decl\n// CHECK:STDOUT:     .CallGenericMethod = %CallGenericMethod.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Generic.decl: %Generic.type.835 = interface_decl @Generic [concrete = constants.%Generic.generic] {\n// CHECK:STDOUT:     %Scalar.patt: %pattern_type.98f = symbolic_binding_pattern Scalar, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_28.1: type = splice_block %.loc15_28.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_28.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Scalar.loc15_19.2: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc15_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %GenericParam.decl: type = class_decl @GenericParam [concrete = constants.%GenericParam] {} {}\n// CHECK:STDOUT:   %ImplsGeneric.decl: type = class_decl @ImplsGeneric [concrete = constants.%ImplsGeneric] {} {}\n// CHECK:STDOUT:   impl_decl @ImplsGeneric.as.Generic.impl [concrete] {} {\n// CHECK:STDOUT:     %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:     %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:     %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:     %Generic.type: type = facet_type <@Generic, @Generic(constants.%GenericParam)> [concrete = constants.%Generic.type.498]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Other.decl: type = interface_decl @Other [concrete = constants.%Other.type] {} {}\n// CHECK:STDOUT:   impl_decl @ImplsGeneric.as.Other.impl [concrete] {} {\n// CHECK:STDOUT:     %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:     %Other.ref: type = name_ref Other, file.%Other.decl [concrete = constants.%Other.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallGenericMethod.decl: %CallGenericMethod.type = fn_decl @CallGenericMethod [concrete = constants.%CallGenericMethod] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: @CallGenericMethod.%pattern_type (%pattern_type.c49) = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc33_26.1: type = splice_block %.loc33_26.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc33_26.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc33_22.2: type = symbolic_binding T, 0 [symbolic = %T.loc33_22.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc33_45: type = splice_block %Generic.type.loc33_45.2 [symbolic = %Generic.type.loc33_45.1 (constants.%Generic.type.03dff7.2)] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Generic.ref: %Generic.type.835 = name_ref Generic, file.%Generic.decl [concrete = constants.%Generic.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc33_22.2 [symbolic = %T.loc33_22.1 (constants.%T)]\n// CHECK:STDOUT:       %Generic.type.loc33_45.2: type = facet_type <@Generic, @Generic(constants.%T)> [symbolic = %Generic.type.loc33_45.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc33_32.2: @CallGenericMethod.%Generic.type.loc33_45.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc33_32.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @Generic(%Scalar.loc15_19.2: type) {\n// CHECK:STDOUT:   %Scalar.loc15_19.1: type = symbolic_binding Scalar, 0 [symbolic = %Scalar.loc15_19.1 (constants.%Scalar)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type: type = facet_type <@Generic, @Generic(%Scalar.loc15_19.1)> [symbolic = %Generic.type (constants.%Generic.type.03dff7.1)]\n// CHECK:STDOUT:   %Self.loc15_34.2: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc15_34.2 (constants.%Self.15d2d5.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc15_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1) = symbolic_binding Self, 1 [symbolic = %Self.loc15_34.2 (constants.%Self.15d2d5.1)]\n// CHECK:STDOUT:     %Generic.WithSelf.decl = interface_with_self_decl @Generic [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %Generic.WithSelf.F.decl: @Generic.WithSelf.%Generic.WithSelf.F.type (%Generic.WithSelf.F.type.74390a.1) = fn_decl @Generic.WithSelf.F [symbolic = @Generic.WithSelf.%Generic.WithSelf.F (constants.%Generic.WithSelf.F.baf95a.1)] {} {}\n// CHECK:STDOUT:     %assoc0.loc16_9.1: @Generic.WithSelf.%Generic.assoc_type (%Generic.assoc_type.22afda.1) = assoc_entity element0, %Generic.WithSelf.F.decl [symbolic = %assoc0.loc16_9.2 (constants.%assoc0.e0dc00.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc15_34.1\n// CHECK:STDOUT:     .F = @Generic.WithSelf.%assoc0.loc16_9.1\n// CHECK:STDOUT:     witness = (@Generic.WithSelf.%Generic.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Other {\n// CHECK:STDOUT:   %Self: %Other.type = symbolic_binding Self, 0 [symbolic = constants.%Self.8c4]\n// CHECK:STDOUT:   %Other.WithSelf.decl = interface_with_self_decl @Other [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %Other.WithSelf.G.decl: @Other.WithSelf.%Other.WithSelf.G.type (%Other.WithSelf.G.type.acd) = fn_decl @Other.WithSelf.G [symbolic = @Other.WithSelf.%Other.WithSelf.G (constants.%Other.WithSelf.G.63d)] {} {}\n// CHECK:STDOUT:   %assoc0: %Other.assoc_type = assoc_entity element0, %Other.WithSelf.G.decl [concrete = constants.%assoc0.205]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .G = @Other.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@Other.WithSelf.%Other.WithSelf.G.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @ImplsGeneric.as.Generic.impl: %ImplsGeneric.ref as %Generic.type {\n// CHECK:STDOUT:   %ImplsGeneric.as.Generic.impl.F.decl: %ImplsGeneric.as.Generic.impl.F.type = fn_decl @ImplsGeneric.as.Generic.impl.F [concrete = constants.%ImplsGeneric.as.Generic.impl.F] {} {}\n// CHECK:STDOUT:   %Generic.impl_witness_table = impl_witness_table (%ImplsGeneric.as.Generic.impl.F.decl), @ImplsGeneric.as.Generic.impl [concrete]\n// CHECK:STDOUT:   %Generic.impl_witness: <witness> = impl_witness %Generic.impl_witness_table [concrete = constants.%Generic.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %ImplsGeneric.as.Generic.impl.F.decl\n// CHECK:STDOUT:   witness = %Generic.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @ImplsGeneric.as.Other.impl: %ImplsGeneric.ref as %Other.ref {\n// CHECK:STDOUT:   %ImplsGeneric.as.Other.impl.G.decl: %ImplsGeneric.as.Other.impl.G.type = fn_decl @ImplsGeneric.as.Other.impl.G [concrete = constants.%ImplsGeneric.as.Other.impl.G] {} {}\n// CHECK:STDOUT:   %Other.impl_witness_table = impl_witness_table (%ImplsGeneric.as.Other.impl.G.decl), @ImplsGeneric.as.Other.impl [concrete]\n// CHECK:STDOUT:   %Other.impl_witness: <witness> = impl_witness %Other.impl_witness_table [concrete = constants.%Other.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .G = %ImplsGeneric.as.Other.impl.G.decl\n// CHECK:STDOUT:   witness = %Other.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @GenericParam {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%GenericParam\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @ImplsGeneric {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%ImplsGeneric\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Generic.WithSelf.F(@Generic.%Scalar.loc15_19.2: type, @Generic.%Self.loc15_34.1: @Generic.%Generic.type (%Generic.type.03dff7.1)) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImplsGeneric.as.Generic.impl.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Other.WithSelf.G(@Other.%Self: %Other.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ImplsGeneric.as.Other.impl.G();\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallGenericMethod(%T.loc33_22.2: type, %U.loc33_32.2: @CallGenericMethod.%Generic.type.loc33_45.1 (%Generic.type.03dff7.2)) {\n// CHECK:STDOUT:   %T.loc33_22.1: type = symbolic_binding T, 0 [symbolic = %T.loc33_22.1 (constants.%T)]\n// CHECK:STDOUT:   %Generic.type.loc33_45.1: type = facet_type <@Generic, @Generic(%T.loc33_22.1)> [symbolic = %Generic.type.loc33_45.1 (constants.%Generic.type.03dff7.2)]\n// CHECK:STDOUT:   %U.loc33_32.1: @CallGenericMethod.%Generic.type.loc33_45.1 (%Generic.type.03dff7.2) = symbolic_binding U, 1 [symbolic = %U.loc33_32.1 (constants.%U)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Generic.type.loc33_45.1 [symbolic = %pattern_type (constants.%pattern_type.c49)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Generic.type.loc33_45.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 1, %U.loc33_32.1 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:   %Generic.assoc_type: type = assoc_entity_type @Generic, @Generic(%T.loc33_22.1) [symbolic = %Generic.assoc_type (constants.%Generic.assoc_type.22afda.2)]\n// CHECK:STDOUT:   %assoc0: @CallGenericMethod.%Generic.assoc_type (%Generic.assoc_type.22afda.2) = assoc_entity element0, @Generic.WithSelf.%Generic.WithSelf.F.decl [symbolic = %assoc0 (constants.%assoc0.e0dc00.2)]\n// CHECK:STDOUT:   %Generic.lookup_impl_witness: <witness> = lookup_impl_witness %U.loc33_32.1, @Generic, @Generic(%T.loc33_22.1) [symbolic = %Generic.lookup_impl_witness (constants.%Generic.lookup_impl_witness)]\n// CHECK:STDOUT:   %Generic.WithSelf.F.type: type = fn_type @Generic.WithSelf.F, @Generic.WithSelf(%T.loc33_22.1, %U.loc33_32.1) [symbolic = %Generic.WithSelf.F.type (constants.%Generic.WithSelf.F.type.56e)]\n// CHECK:STDOUT:   %.loc34_4.3: type = fn_type_with_self_type %Generic.WithSelf.F.type, %U.loc33_32.1 [symbolic = %.loc34_4.3 (constants.%.ab3)]\n// CHECK:STDOUT:   %impl.elem0.loc34_4.2: @CallGenericMethod.%.loc34_4.3 (%.ab3) = impl_witness_access %Generic.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc34_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:   %specific_impl_fn.loc34_4.2: <specific function> = specific_impl_function %impl.elem0.loc34_4.2, @Generic.WithSelf.F(%T.loc33_22.1, %U.loc33_32.1) [symbolic = %specific_impl_fn.loc34_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %U.ref: @CallGenericMethod.%Generic.type.loc33_45.1 (%Generic.type.03dff7.2) = name_ref U, %U.loc33_32.2 [symbolic = %U.loc33_32.1 (constants.%U)]\n// CHECK:STDOUT:     %U.as_type: type = facet_access_type %U.ref [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     %.loc34_4.1: type = converted %U.ref, %U.as_type [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     %.loc34_4.2: @CallGenericMethod.%Generic.assoc_type (%Generic.assoc_type.22afda.2) = specific_constant @Generic.WithSelf.%assoc0.loc16_9.1, @Generic.WithSelf(constants.%T, constants.%U) [symbolic = %assoc0 (constants.%assoc0.e0dc00.2)]\n// CHECK:STDOUT:     %F.ref: @CallGenericMethod.%Generic.assoc_type (%Generic.assoc_type.22afda.2) = name_ref F, %.loc34_4.2 [symbolic = %assoc0 (constants.%assoc0.e0dc00.2)]\n// CHECK:STDOUT:     %impl.elem0.loc34_4.1: @CallGenericMethod.%.loc34_4.3 (%.ab3) = impl_witness_access constants.%Generic.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc34_4.2 (constants.%impl.elem0)]\n// CHECK:STDOUT:     %specific_impl_fn.loc34_4.1: <specific function> = specific_impl_function %impl.elem0.loc34_4.1, @Generic.WithSelf.F(constants.%T, constants.%U) [symbolic = %specific_impl_fn.loc34_4.2 (constants.%specific_impl_fn)]\n// CHECK:STDOUT:     %Generic.WithSelf.F.call: init %empty_tuple.type = call %specific_impl_fn.loc34_4.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %CallGenericMethod.ref: %CallGenericMethod.type = name_ref CallGenericMethod, file.%CallGenericMethod.decl [concrete = constants.%CallGenericMethod]\n// CHECK:STDOUT:   %GenericParam.ref: type = name_ref GenericParam, file.%GenericParam.decl [concrete = constants.%GenericParam]\n// CHECK:STDOUT:   %ImplsGeneric.ref: type = name_ref ImplsGeneric, file.%ImplsGeneric.decl [concrete = constants.%ImplsGeneric]\n// CHECK:STDOUT:   %Generic.facet: %Generic.type.498 = facet_value constants.%ImplsGeneric, (constants.%Generic.impl_witness) [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %.loc38: %Generic.type.498 = converted constants.%ImplsGeneric, %Generic.facet [concrete = constants.%Generic.facet]\n// CHECK:STDOUT:   %CallGenericMethod.specific_fn: <specific function> = specific_function %CallGenericMethod.ref, @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) [concrete = constants.%CallGenericMethod.specific_fn]\n// CHECK:STDOUT:   %CallGenericMethod.call: init %empty_tuple.type = call %CallGenericMethod.specific_fn()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%Scalar) {\n// CHECK:STDOUT:   %Scalar.loc15_19.1 => constants.%Scalar\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%Scalar, constants.%Self.15d2d5.1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%Scalar, constants.%Self.15d2d5.1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%GenericParam) {\n// CHECK:STDOUT:   %Scalar.loc15_19.1 => constants.%GenericParam\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self.loc15_34.2 => constants.%Self.1f5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Self.15d2d5.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Self.15d2d5.1\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.a23\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.fe0\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc16_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.498\n// CHECK:STDOUT:   %Self => constants.%Generic.facet\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.c86\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.1fd\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0.loc16_9.2 => constants.%assoc0.717\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%GenericParam, constants.%Generic.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Other.WithSelf(constants.%Self.8c4) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.8c4\n// CHECK:STDOUT:   %Other.WithSelf.G.type => constants.%Other.WithSelf.G.type.acd\n// CHECK:STDOUT:   %Other.WithSelf.G => constants.%Other.WithSelf.G.63d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Other.WithSelf.G(constants.%Self.8c4) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Other.WithSelf(constants.%Other.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Other.facet\n// CHECK:STDOUT:   %Other.WithSelf.G.type => constants.%Other.WithSelf.G.type.1df\n// CHECK:STDOUT:   %Other.WithSelf.G => constants.%Other.WithSelf.G.13d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Other.WithSelf.G(constants.%Other.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic(constants.%T) {\n// CHECK:STDOUT:   %Scalar.loc15_19.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %Self.loc15_34.2 => constants.%Self.15d2d5.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc33_22.1 => constants.%T\n// CHECK:STDOUT:   %Generic.type.loc33_45.1 => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %U.loc33_32.1 => constants.%U\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.c49\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%T, constants.%Self.15d2d5.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%T\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %Self => constants.%Self.15d2d5.1\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.74390a.2\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.baf95a.2\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.22afda.2\n// CHECK:STDOUT:   %assoc0.loc16_9.2 => constants.%assoc0.e0dc00.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf(constants.%T, constants.%U) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Scalar => constants.%T\n// CHECK:STDOUT:   %Generic.type => constants.%Generic.type.03dff7.2\n// CHECK:STDOUT:   %Self => constants.%U\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.56e\n// CHECK:STDOUT:   %Generic.WithSelf.F => constants.%Generic.WithSelf.F.a99\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.22afda.2\n// CHECK:STDOUT:   %assoc0.loc16_9.2 => constants.%assoc0.e0dc00.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Generic.WithSelf.F(constants.%T, constants.%U) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallGenericMethod(constants.%GenericParam, constants.%Generic.facet) {\n// CHECK:STDOUT:   %T.loc33_22.1 => constants.%GenericParam\n// CHECK:STDOUT:   %Generic.type.loc33_45.1 => constants.%Generic.type.498\n// CHECK:STDOUT:   %U.loc33_32.1 => constants.%Generic.facet\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.cba\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.57a\n// CHECK:STDOUT:   %U.binding.as_type => constants.%ImplsGeneric\n// CHECK:STDOUT:   %Generic.assoc_type => constants.%Generic.assoc_type.6dc\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.717\n// CHECK:STDOUT:   %Generic.lookup_impl_witness => constants.%Generic.impl_witness\n// CHECK:STDOUT:   %Generic.WithSelf.F.type => constants.%Generic.WithSelf.F.type.c86\n// CHECK:STDOUT:   %.loc34_4.3 => constants.%.fcf\n// CHECK:STDOUT:   %impl.elem0.loc34_4.2 => constants.%ImplsGeneric.as.Generic.impl.F\n// CHECK:STDOUT:   %specific_impl_fn.loc34_4.2 => constants.%ImplsGeneric.as.Generic.impl.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/deduce.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/deduce.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/deduce.carbon\n\n// --- deduce_explicit.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn ExplicitGenericParam(T:! type) -> T* { return ExplicitGenericParam(T); }\n\nfn CallExplicitGenericParam() -> i32* {\n  return ExplicitGenericParam(i32);\n}\n\nfn CallExplicitGenericParamWithGenericArg(T:! type) -> {.a: T}* {\n  return ExplicitGenericParam({.a: T});\n}\n\n// --- fail_deduce_explicit_non_constant.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn ExplicitGenericParam(T:! type) -> T* { return ExplicitGenericParam(T); }\n\nfn CallExplicitGenericParamConst(T:! type) {\n  ExplicitGenericParam(T);\n}\n\nfn CallExplicitGenericParamNonConst(T: type) {\n  // CHECK:STDERR: fail_deduce_explicit_non_constant.carbon:[[@LINE+7]]:3: error: argument for generic parameter is not a compile-time constant [CompTimeArgumentNotConstant]\n  // CHECK:STDERR:   ExplicitGenericParam(T);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduce_explicit_non_constant.carbon:[[@LINE-10]]:25: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn ExplicitGenericParam(T:! type) -> T* { return ExplicitGenericParam(T); }\n  // CHECK:STDERR:                         ^\n  // CHECK:STDERR:\n  ExplicitGenericParam(T);\n}\n\n// --- explicit_vs_deduced.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {}\n\nfn ExplicitAndAlsoDeduced(T:! type, x: T) -> T* {\n  return ExplicitAndAlsoDeduced(T, x);\n}\n\nfn CallExplicitAndAlsoDeduced() -> A* {\n  return ExplicitAndAlsoDeduced(A, {});\n}\n\n// --- deduce_implicit.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn ImplicitGenericParam[T:! type](x: T) -> T* { return ImplicitGenericParam(x); }\n\nfn CallImplicitGenericParam(n: i32) -> i32* {\n  return ImplicitGenericParam(n);\n}\n\n// --- deduce_nested_tuple.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn TupleParam[T:! type](unused x: (T, i32)) {}\n\nfn CallTupleParam() {\n  TupleParam((1, 2));\n}\n\n// --- deduce_nested_struct.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn StructParam[T:! type](unused x: {.a: T, .b: i32}) {}\n\nfn CallStructParam() {\n  StructParam({.a = 1, .b = 2});\n}\n\n// --- fail_deduce_bigger_struct.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn BigStructParam[T:! type](unused x: {.c: T, .d: i32, .e: i32}) {}\n\nfn CallBigStructParam() {\n  // CHECK:STDERR: fail_deduce_bigger_struct.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete]\n  // CHECK:STDERR:   BigStructParam({.c = 3, .d = 4});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduce_bigger_struct.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn BigStructParam[T:! type](unused x: {.c: T, .d: i32, .e: i32}) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  BigStructParam({.c = 3, .d = 4});\n}\n\n// --- fail_deduce_smaller_struct.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn SmallStructParam[T:! type](unused x: {.f: T, .g: i32}) {}\n\nfn CallSmallStructParam() {\n  // CHECK:STDERR: fail_deduce_smaller_struct.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete]\n  // CHECK:STDERR:   SmallStructParam({.f = 5, .g = 6, .h = 7});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduce_smaller_struct.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn SmallStructParam[T:! type](unused x: {.f: T, .g: i32}) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  SmallStructParam({.f = 5, .g = 6, .h = 7});\n}\n\n// --- fail_deduce_struct_wrong_name.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn WrongNameStructParam[T:! type](unused x: {.i: T, .different: i32}) {}\n\nfn CallWrongNameStructParam() {\n  // CHECK:STDERR: fail_deduce_struct_wrong_name.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete]\n  // CHECK:STDERR:   WrongNameStructParam({.i = 8, .j = 9});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduce_struct_wrong_name.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn WrongNameStructParam[T:! type](unused x: {.i: T, .different: i32}) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  WrongNameStructParam({.i = 8, .j = 9});\n}\n\n// --- fail_todo_deduce_struct_wrong_order.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn WrongOrderStructParam[T:! type](unused x: {.first: T, .second: i32}) {}\n\nfn CallWrongOrderStructParam() {\n  // CHECK:STDERR: fail_todo_deduce_struct_wrong_order.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete]\n  // CHECK:STDERR:   WrongOrderStructParam({.second = 11, .first = 10});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_deduce_struct_wrong_order.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn WrongOrderStructParam[T:! type](unused x: {.first: T, .second: i32}) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  WrongOrderStructParam({.second = 11, .first = 10});\n}\n\n// --- fail_deduce_incomplete.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: It would be nice to diagnose this at its point of declaration, because\n// U is not deducible.\nfn ImplicitNotDeducible[T:! type, U:! type](x: T) -> U;\n\nfn CallImplicitNotDeducible() {\n  // CHECK:STDERR: fail_deduce_incomplete.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `U` [DeductionIncomplete]\n  // CHECK:STDERR:   ImplicitNotDeducible(42);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduce_incomplete.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn ImplicitNotDeducible[T:! type, U:! type](x: T) -> U;\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  ImplicitNotDeducible(42);\n}\n\n// --- fail_deduce_inconsistent.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn ImplicitNotDeducible[T:! type](x: T, y: T) -> T;\n\nfn CallImplicitNotDeducible() {\n  // CHECK:STDERR: fail_deduce_inconsistent.carbon:[[@LINE+7]]:3: error: inconsistent deductions for value of generic parameter `T` [DeductionInconsistent]\n  // CHECK:STDERR:   ImplicitNotDeducible(42, {.x = 12});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduce_inconsistent.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn ImplicitNotDeducible[T:! type](x: T, y: T) -> T;\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  ImplicitNotDeducible(42, {.x = 12});\n}\n\n// --- deduce_nested_generic_class.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\nclass EE {}\nimpl EE as Z {}\n\nclass DD(E:! type) {}\nimpl forall [E:! type] DD(E) as Z {}\n\nclass CC(D:! Z) {}\nimpl forall [E:! type] CC(DD(E)) as Z {}\n\nfn F() {\n  CC(DD(EE)) as Z;\n}\n\n// CHECK:STDOUT: --- deduce_explicit.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %ExplicitGenericParam.type: type = fn_type @ExplicitGenericParam [concrete]\n// CHECK:STDOUT:   %ExplicitGenericParam: %ExplicitGenericParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.409: <specific function> = specific_function %ExplicitGenericParam, @ExplicitGenericParam(%T) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %.605: Core.Form = init_form %ptr.235 [concrete]\n// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr.235 [concrete]\n// CHECK:STDOUT:   %CallExplicitGenericParam.type: type = fn_type @CallExplicitGenericParam [concrete]\n// CHECK:STDOUT:   %CallExplicitGenericParam: %CallExplicitGenericParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.3d2: <specific function> = specific_function %ExplicitGenericParam, @ExplicitGenericParam(%i32) [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %T} [symbolic]\n// CHECK:STDOUT:   %ptr.88d: type = ptr_type %struct_type.a [symbolic]\n// CHECK:STDOUT:   %.edd: Core.Form = init_form %ptr.88d [symbolic]\n// CHECK:STDOUT:   %pattern_type.1cb: type = pattern_type %ptr.88d [symbolic]\n// CHECK:STDOUT:   %CallExplicitGenericParamWithGenericArg.type: type = fn_type @CallExplicitGenericParamWithGenericArg [concrete]\n// CHECK:STDOUT:   %CallExplicitGenericParamWithGenericArg: %CallExplicitGenericParamWithGenericArg.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.61f: <witness> = require_complete_type %ptr.88d [symbolic]\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.55c: <specific function> = specific_function %ExplicitGenericParam, @ExplicitGenericParam(%struct_type.a) [symbolic]\n// CHECK:STDOUT:   %complete_type.3d0: <witness> = complete_type_witness %ptr.235 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ExplicitGenericParam = %ExplicitGenericParam.decl\n// CHECK:STDOUT:     .CallExplicitGenericParam = %CallExplicitGenericParam.decl\n// CHECK:STDOUT:     .CallExplicitGenericParamWithGenericArg = %CallExplicitGenericParamWithGenericArg.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ExplicitGenericParam.decl: %ExplicitGenericParam.type = fn_decl @ExplicitGenericParam [concrete = constants.%ExplicitGenericParam] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: @ExplicitGenericParam.%pattern_type (%pattern_type.4f4) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @ExplicitGenericParam.%pattern_type (%pattern_type.4f4) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc4_38: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc4_39.2: type = ptr_type %T.ref.loc4_38 [symbolic = %ptr.loc4_39.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     %.loc4_39.2: Core.Form = init_form %ptr.loc4_39.2 [symbolic = %.loc4_39.1 (constants.%.cb6)]\n// CHECK:STDOUT:     %.loc4_29.1: type = splice_block %.loc4_29.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_29.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_25.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %return.param: ref @ExplicitGenericParam.%ptr.loc4_39.1 (%ptr.e8f) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @ExplicitGenericParam.%ptr.loc4_39.1 (%ptr.e8f) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallExplicitGenericParam.decl: %CallExplicitGenericParam.type = fn_decl @CallExplicitGenericParam [concrete = constants.%CallExplicitGenericParam] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.fe8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.fe8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr: type = ptr_type %i32.loc6 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:     %.loc6: Core.Form = init_form %ptr [concrete = constants.%.605]\n// CHECK:STDOUT:     %return.param: ref %ptr.235 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %ptr.235 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallExplicitGenericParamWithGenericArg.decl: %CallExplicitGenericParamWithGenericArg.type = fn_decl @CallExplicitGenericParamWithGenericArg [concrete = constants.%CallExplicitGenericParamWithGenericArg] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: @CallExplicitGenericParamWithGenericArg.%pattern_type (%pattern_type.1cb) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @CallExplicitGenericParamWithGenericArg.%pattern_type (%pattern_type.1cb) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc10: type = name_ref T, %T.loc10_43.2 [symbolic = %T.loc10_43.1 (constants.%T)]\n// CHECK:STDOUT:     %struct_type.a.loc10_62.2: type = struct_type {.a: @CallExplicitGenericParamWithGenericArg.%T.loc10_43.1 (%T)} [symbolic = %struct_type.a.loc10_62.1 (constants.%struct_type.a)]\n// CHECK:STDOUT:     %ptr.loc10_63.2: type = ptr_type %struct_type.a.loc10_62.2 [symbolic = %ptr.loc10_63.1 (constants.%ptr.88d)]\n// CHECK:STDOUT:     %.loc10_63.2: Core.Form = init_form %ptr.loc10_63.2 [symbolic = %.loc10_63.1 (constants.%.edd)]\n// CHECK:STDOUT:     %.loc10_47.1: type = splice_block %.loc10_47.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc10_47.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc10_43.2: type = symbolic_binding T, 0 [symbolic = %T.loc10_43.1 (constants.%T)]\n// CHECK:STDOUT:     %return.param: ref @CallExplicitGenericParamWithGenericArg.%ptr.loc10_63.1 (%ptr.88d) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @CallExplicitGenericParamWithGenericArg.%ptr.loc10_63.1 (%ptr.88d) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ExplicitGenericParam(%T.loc4_25.2: type) {\n// CHECK:STDOUT:   %T.loc4_25.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc4_39.1: type = ptr_type %T.loc4_25.1 [symbolic = %ptr.loc4_39.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %.loc4_39.1: Core.Form = init_form %ptr.loc4_39.1 [symbolic = %.loc4_39.1 (constants.%.cb6)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc4_39.1 [symbolic = %pattern_type (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc4_39.1 [symbolic = %require_complete (constants.%require_complete.ef1)]\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.loc4_50.2: <specific function> = specific_function constants.%ExplicitGenericParam, @ExplicitGenericParam(%T.loc4_25.1) [symbolic = %ExplicitGenericParam.specific_fn.loc4_50.2 (constants.%ExplicitGenericParam.specific_fn.409)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @ExplicitGenericParam.%ptr.loc4_39.1 (%ptr.e8f) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [concrete = constants.%ExplicitGenericParam]\n// CHECK:STDOUT:     %T.ref.loc4_71: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %ExplicitGenericParam.specific_fn.loc4_50.1: <specific function> = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(constants.%T) [symbolic = %ExplicitGenericParam.specific_fn.loc4_50.2 (constants.%ExplicitGenericParam.specific_fn.409)]\n// CHECK:STDOUT:     %ExplicitGenericParam.call: init @ExplicitGenericParam.%ptr.loc4_39.1 (%ptr.e8f) = call %ExplicitGenericParam.specific_fn.loc4_50.1()\n// CHECK:STDOUT:     return %ExplicitGenericParam.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallExplicitGenericParam() -> out %return.param: %ptr.235 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [concrete = constants.%ExplicitGenericParam]\n// CHECK:STDOUT:   %i32.loc7: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn: <specific function> = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(constants.%i32) [concrete = constants.%ExplicitGenericParam.specific_fn.3d2]\n// CHECK:STDOUT:   %ExplicitGenericParam.call: init %ptr.235 = call %ExplicitGenericParam.specific_fn()\n// CHECK:STDOUT:   return %ExplicitGenericParam.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallExplicitGenericParamWithGenericArg(%T.loc10_43.2: type) {\n// CHECK:STDOUT:   %T.loc10_43.1: type = symbolic_binding T, 0 [symbolic = %T.loc10_43.1 (constants.%T)]\n// CHECK:STDOUT:   %struct_type.a.loc10_62.1: type = struct_type {.a: @CallExplicitGenericParamWithGenericArg.%T.loc10_43.1 (%T)} [symbolic = %struct_type.a.loc10_62.1 (constants.%struct_type.a)]\n// CHECK:STDOUT:   %ptr.loc10_63.1: type = ptr_type %struct_type.a.loc10_62.1 [symbolic = %ptr.loc10_63.1 (constants.%ptr.88d)]\n// CHECK:STDOUT:   %.loc10_63.1: Core.Form = init_form %ptr.loc10_63.1 [symbolic = %.loc10_63.1 (constants.%.edd)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc10_63.1 [symbolic = %pattern_type (constants.%pattern_type.1cb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc10_63.1 [symbolic = %require_complete (constants.%require_complete.61f)]\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.loc11_10.2: <specific function> = specific_function constants.%ExplicitGenericParam, @ExplicitGenericParam(%struct_type.a.loc10_62.1) [symbolic = %ExplicitGenericParam.specific_fn.loc11_10.2 (constants.%ExplicitGenericParam.specific_fn.55c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @CallExplicitGenericParamWithGenericArg.%ptr.loc10_63.1 (%ptr.88d) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [concrete = constants.%ExplicitGenericParam]\n// CHECK:STDOUT:     %T.ref.loc11: type = name_ref T, %T.loc10_43.2 [symbolic = %T.loc10_43.1 (constants.%T)]\n// CHECK:STDOUT:     %struct_type.a.loc11: type = struct_type {.a: @CallExplicitGenericParamWithGenericArg.%T.loc10_43.1 (%T)} [symbolic = %struct_type.a.loc10_62.1 (constants.%struct_type.a)]\n// CHECK:STDOUT:     %ExplicitGenericParam.specific_fn.loc11_10.1: <specific function> = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(constants.%struct_type.a) [symbolic = %ExplicitGenericParam.specific_fn.loc11_10.2 (constants.%ExplicitGenericParam.specific_fn.55c)]\n// CHECK:STDOUT:     %ExplicitGenericParam.call: init @CallExplicitGenericParamWithGenericArg.%ptr.loc10_63.1 (%ptr.88d) = call %ExplicitGenericParam.specific_fn.loc11_10.1()\n// CHECK:STDOUT:     return %ExplicitGenericParam.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ExplicitGenericParam(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_25.1 => constants.%T\n// CHECK:STDOUT:   %ptr.loc4_39.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %.loc4_39.1 => constants.%.cb6\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.ef1\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.loc4_50.2 => constants.%ExplicitGenericParam.specific_fn.409\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ExplicitGenericParam(constants.%i32) {\n// CHECK:STDOUT:   %T.loc4_25.1 => constants.%i32\n// CHECK:STDOUT:   %ptr.loc4_39.1 => constants.%ptr.235\n// CHECK:STDOUT:   %.loc4_39.1 => constants.%.605\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.fe8\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.3d0\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.loc4_50.2 => constants.%ExplicitGenericParam.specific_fn.3d2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallExplicitGenericParamWithGenericArg(constants.%T) {\n// CHECK:STDOUT:   %T.loc10_43.1 => constants.%T\n// CHECK:STDOUT:   %struct_type.a.loc10_62.1 => constants.%struct_type.a\n// CHECK:STDOUT:   %ptr.loc10_63.1 => constants.%ptr.88d\n// CHECK:STDOUT:   %.loc10_63.1 => constants.%.edd\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.1cb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ExplicitGenericParam(constants.%struct_type.a) {\n// CHECK:STDOUT:   %T.loc4_25.1 => constants.%struct_type.a\n// CHECK:STDOUT:   %ptr.loc4_39.1 => constants.%ptr.88d\n// CHECK:STDOUT:   %.loc4_39.1 => constants.%.edd\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.1cb\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.61f\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.loc4_50.2 => constants.%ExplicitGenericParam.specific_fn.55c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_deduce_explicit_non_constant.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr [symbolic]\n// CHECK:STDOUT:   %ExplicitGenericParam.type: type = fn_type @ExplicitGenericParam [concrete]\n// CHECK:STDOUT:   %ExplicitGenericParam: %ExplicitGenericParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr [symbolic]\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn: <specific function> = specific_function %ExplicitGenericParam, @ExplicitGenericParam(%T) [symbolic]\n// CHECK:STDOUT:   %CallExplicitGenericParamConst.type: type = fn_type @CallExplicitGenericParamConst [concrete]\n// CHECK:STDOUT:   %CallExplicitGenericParamConst: %CallExplicitGenericParamConst.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallExplicitGenericParamNonConst.type: type = fn_type @CallExplicitGenericParamNonConst [concrete]\n// CHECK:STDOUT:   %CallExplicitGenericParamNonConst: %CallExplicitGenericParamNonConst.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ExplicitGenericParam = %ExplicitGenericParam.decl\n// CHECK:STDOUT:     .CallExplicitGenericParamConst = %CallExplicitGenericParamConst.decl\n// CHECK:STDOUT:     .CallExplicitGenericParamNonConst = %CallExplicitGenericParamNonConst.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ExplicitGenericParam.decl: %ExplicitGenericParam.type = fn_decl @ExplicitGenericParam [concrete = constants.%ExplicitGenericParam] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: @ExplicitGenericParam.%pattern_type (%pattern_type.4f4) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @ExplicitGenericParam.%pattern_type (%pattern_type.4f4) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc4_38: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc4_39.2: type = ptr_type %T.ref.loc4_38 [symbolic = %ptr.loc4_39.1 (constants.%ptr)]\n// CHECK:STDOUT:     %.loc4_39.2: Core.Form = init_form %ptr.loc4_39.2 [symbolic = %.loc4_39.1 (constants.%.cb6)]\n// CHECK:STDOUT:     %.loc4_29.1: type = splice_block %.loc4_29.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_29.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_25.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %return.param: ref @ExplicitGenericParam.%ptr.loc4_39.1 (%ptr) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @ExplicitGenericParam.%ptr.loc4_39.1 (%ptr) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallExplicitGenericParamConst.decl: %CallExplicitGenericParamConst.type = fn_decl @CallExplicitGenericParamConst [concrete = constants.%CallExplicitGenericParamConst] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_38.1: type = splice_block %.loc6_38.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_38.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_34.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_34.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallExplicitGenericParamNonConst.decl: %CallExplicitGenericParamNonConst.type = fn_decl @CallExplicitGenericParamNonConst [concrete = constants.%CallExplicitGenericParamNonConst] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = value_binding_pattern T [concrete]\n// CHECK:STDOUT:     %T.param_patt: %pattern_type.98f = value_param_pattern %T.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.param: type = value_param call_param0\n// CHECK:STDOUT:     %.loc10: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %T: type = value_binding T, %T.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ExplicitGenericParam(%T.loc4_25.2: type) {\n// CHECK:STDOUT:   %T.loc4_25.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc4_39.1: type = ptr_type %T.loc4_25.1 [symbolic = %ptr.loc4_39.1 (constants.%ptr)]\n// CHECK:STDOUT:   %.loc4_39.1: Core.Form = init_form %ptr.loc4_39.1 [symbolic = %.loc4_39.1 (constants.%.cb6)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc4_39.1 [symbolic = %pattern_type (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc4_39.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.loc4_50.2: <specific function> = specific_function constants.%ExplicitGenericParam, @ExplicitGenericParam(%T.loc4_25.1) [symbolic = %ExplicitGenericParam.specific_fn.loc4_50.2 (constants.%ExplicitGenericParam.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @ExplicitGenericParam.%ptr.loc4_39.1 (%ptr) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [concrete = constants.%ExplicitGenericParam]\n// CHECK:STDOUT:     %T.ref.loc4_71: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %ExplicitGenericParam.specific_fn.loc4_50.1: <specific function> = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(constants.%T) [symbolic = %ExplicitGenericParam.specific_fn.loc4_50.2 (constants.%ExplicitGenericParam.specific_fn)]\n// CHECK:STDOUT:     %ExplicitGenericParam.call: init @ExplicitGenericParam.%ptr.loc4_39.1 (%ptr) = call %ExplicitGenericParam.specific_fn.loc4_50.1()\n// CHECK:STDOUT:     return %ExplicitGenericParam.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @CallExplicitGenericParamConst(%T.loc6_34.2: type) {\n// CHECK:STDOUT:   %T.loc6_34.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_34.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.loc7_3.2: <specific function> = specific_function constants.%ExplicitGenericParam, @ExplicitGenericParam(%T.loc6_34.1) [symbolic = %ExplicitGenericParam.specific_fn.loc7_3.2 (constants.%ExplicitGenericParam.specific_fn)]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T.loc6_34.1 [symbolic = %ptr (constants.%ptr)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [concrete = constants.%ExplicitGenericParam]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc6_34.2 [symbolic = %T.loc6_34.1 (constants.%T)]\n// CHECK:STDOUT:     %ExplicitGenericParam.specific_fn.loc7_3.1: <specific function> = specific_function %ExplicitGenericParam.ref, @ExplicitGenericParam(constants.%T) [symbolic = %ExplicitGenericParam.specific_fn.loc7_3.2 (constants.%ExplicitGenericParam.specific_fn)]\n// CHECK:STDOUT:     %ExplicitGenericParam.call: init @CallExplicitGenericParamConst.%ptr (%ptr) = call %ExplicitGenericParam.specific_fn.loc7_3.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallExplicitGenericParamNonConst(%T.param: type) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ExplicitGenericParam.ref: %ExplicitGenericParam.type = name_ref ExplicitGenericParam, file.%ExplicitGenericParam.decl [concrete = constants.%ExplicitGenericParam]\n// CHECK:STDOUT:   %T.ref: type = name_ref T, %T\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ExplicitGenericParam(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_25.1 => constants.%T\n// CHECK:STDOUT:   %ptr.loc4_39.1 => constants.%ptr\n// CHECK:STDOUT:   %.loc4_39.1 => constants.%.cb6\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %ExplicitGenericParam.specific_fn.loc4_50.2 => constants.%ExplicitGenericParam.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CallExplicitGenericParamConst(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_34.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- explicit_vs_deduced.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.type: type = fn_type @ExplicitAndAlsoDeduced [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced: %ExplicitAndAlsoDeduced.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.specific_fn.7e7: <specific function> = specific_function %ExplicitAndAlsoDeduced, @ExplicitAndAlsoDeduced(%T) [symbolic]\n// CHECK:STDOUT:   %ptr.643: type = ptr_type %A [concrete]\n// CHECK:STDOUT:   %.ebf: Core.Form = init_form %ptr.643 [concrete]\n// CHECK:STDOUT:   %pattern_type.f29: type = pattern_type %ptr.643 [concrete]\n// CHECK:STDOUT:   %CallExplicitAndAlsoDeduced.type: type = fn_type @CallExplicitAndAlsoDeduced [concrete]\n// CHECK:STDOUT:   %CallExplicitAndAlsoDeduced: %CallExplicitAndAlsoDeduced.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.1ab: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.specific_fn.1f3: <specific function> = specific_function %ExplicitAndAlsoDeduced, @ExplicitAndAlsoDeduced(%A) [concrete]\n// CHECK:STDOUT:   %A.val: %A = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.8a0: <witness> = complete_type_witness %ptr.643 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .ExplicitAndAlsoDeduced = %ExplicitAndAlsoDeduced.decl\n// CHECK:STDOUT:     .CallExplicitAndAlsoDeduced = %CallExplicitAndAlsoDeduced.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = class_decl @A [concrete = constants.%A] {} {}\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.decl: %ExplicitAndAlsoDeduced.type = fn_decl @ExplicitAndAlsoDeduced [concrete = constants.%ExplicitAndAlsoDeduced] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @ExplicitAndAlsoDeduced.%pattern_type.loc6_37 (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @ExplicitAndAlsoDeduced.%pattern_type.loc6_37 (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @ExplicitAndAlsoDeduced.%pattern_type.loc6_43 (%pattern_type.4f4) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @ExplicitAndAlsoDeduced.%pattern_type.loc6_43 (%pattern_type.4f4) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc6_46: type = name_ref T, %T.loc6_27.2 [symbolic = %T.loc6_27.1 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc6_47.2: type = ptr_type %T.ref.loc6_46 [symbolic = %ptr.loc6_47.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     %.loc6_47.2: Core.Form = init_form %ptr.loc6_47.2 [symbolic = %.loc6_47.1 (constants.%.cb6)]\n// CHECK:STDOUT:     %.loc6_31.1: type = splice_block %.loc6_31.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_31.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_27.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_27.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @ExplicitAndAlsoDeduced.%T.loc6_27.1 (%T) = value_param call_param0\n// CHECK:STDOUT:     %T.ref.loc6_40: type = name_ref T, %T.loc6_27.2 [symbolic = %T.loc6_27.1 (constants.%T)]\n// CHECK:STDOUT:     %x: @ExplicitAndAlsoDeduced.%T.loc6_27.1 (%T) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.e8f) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.e8f) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallExplicitAndAlsoDeduced.decl: %CallExplicitAndAlsoDeduced.type = fn_decl @CallExplicitAndAlsoDeduced [concrete = constants.%CallExplicitAndAlsoDeduced] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.f29 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.f29 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %A.ref.loc10: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:     %ptr: type = ptr_type %A.ref.loc10 [concrete = constants.%ptr.643]\n// CHECK:STDOUT:     %.loc10: Core.Form = init_form %ptr [concrete = constants.%.ebf]\n// CHECK:STDOUT:     %return.param: ref %ptr.643 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %ptr.643 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @A {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ExplicitAndAlsoDeduced(%T.loc6_27.2: type) {\n// CHECK:STDOUT:   %T.loc6_27.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_27.1 (constants.%T)]\n// CHECK:STDOUT:   %pattern_type.loc6_37: type = pattern_type %T.loc6_27.1 [symbolic = %pattern_type.loc6_37 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:   %ptr.loc6_47.1: type = ptr_type %T.loc6_27.1 [symbolic = %ptr.loc6_47.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %.loc6_47.1: Core.Form = init_form %ptr.loc6_47.1 [symbolic = %.loc6_47.1 (constants.%.cb6)]\n// CHECK:STDOUT:   %pattern_type.loc6_43: type = pattern_type %ptr.loc6_47.1 [symbolic = %pattern_type.loc6_43 (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_38: <witness> = require_complete_type %T.loc6_27.1 [symbolic = %require_complete.loc6_38 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %require_complete.loc6_47: <witness> = require_complete_type %ptr.loc6_47.1 [symbolic = %require_complete.loc6_47 (constants.%require_complete.ef1)]\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.specific_fn.loc7_10.2: <specific function> = specific_function constants.%ExplicitAndAlsoDeduced, @ExplicitAndAlsoDeduced(%T.loc6_27.1) [symbolic = %ExplicitAndAlsoDeduced.specific_fn.loc7_10.2 (constants.%ExplicitAndAlsoDeduced.specific_fn.7e7)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @ExplicitAndAlsoDeduced.%T.loc6_27.1 (%T)) -> out %return.param: @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.e8f) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %ExplicitAndAlsoDeduced.ref: %ExplicitAndAlsoDeduced.type = name_ref ExplicitAndAlsoDeduced, file.%ExplicitAndAlsoDeduced.decl [concrete = constants.%ExplicitAndAlsoDeduced]\n// CHECK:STDOUT:     %T.ref.loc7: type = name_ref T, %T.loc6_27.2 [symbolic = %T.loc6_27.1 (constants.%T)]\n// CHECK:STDOUT:     %x.ref: @ExplicitAndAlsoDeduced.%T.loc6_27.1 (%T) = name_ref x, %x\n// CHECK:STDOUT:     %ExplicitAndAlsoDeduced.specific_fn.loc7_10.1: <specific function> = specific_function %ExplicitAndAlsoDeduced.ref, @ExplicitAndAlsoDeduced(constants.%T) [symbolic = %ExplicitAndAlsoDeduced.specific_fn.loc7_10.2 (constants.%ExplicitAndAlsoDeduced.specific_fn.7e7)]\n// CHECK:STDOUT:     %ExplicitAndAlsoDeduced.call: init @ExplicitAndAlsoDeduced.%ptr.loc6_47.1 (%ptr.e8f) = call %ExplicitAndAlsoDeduced.specific_fn.loc7_10.1(%x.ref)\n// CHECK:STDOUT:     return %ExplicitAndAlsoDeduced.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallExplicitAndAlsoDeduced() -> out %return.param: %ptr.643 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.ref: %ExplicitAndAlsoDeduced.type = name_ref ExplicitAndAlsoDeduced, file.%ExplicitAndAlsoDeduced.decl [concrete = constants.%ExplicitAndAlsoDeduced]\n// CHECK:STDOUT:   %A.ref.loc11: type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %.loc11_37.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.specific_fn: <specific function> = specific_function %ExplicitAndAlsoDeduced.ref, @ExplicitAndAlsoDeduced(constants.%A) [concrete = constants.%ExplicitAndAlsoDeduced.specific_fn.1f3]\n// CHECK:STDOUT:   %.loc11_37.2: ref %A = temporary_storage\n// CHECK:STDOUT:   %.loc11_37.3: init %A to %.loc11_37.2 = class_init () [concrete = constants.%A.val]\n// CHECK:STDOUT:   %.loc11_37.4: init %A = converted %.loc11_37.1, %.loc11_37.3 [concrete = constants.%A.val]\n// CHECK:STDOUT:   %.loc11_37.5: ref %A = temporary %.loc11_37.2, %.loc11_37.4\n// CHECK:STDOUT:   %.loc11_37.6: %A = acquire_value %.loc11_37.5\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.call: init %ptr.643 = call %ExplicitAndAlsoDeduced.specific_fn(%.loc11_37.6)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc11_37.5, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc11_37.5)\n// CHECK:STDOUT:   return %ExplicitAndAlsoDeduced.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %A) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ExplicitAndAlsoDeduced(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_27.1 => constants.%T\n// CHECK:STDOUT:   %pattern_type.loc6_37 => constants.%pattern_type.51d\n// CHECK:STDOUT:   %ptr.loc6_47.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %.loc6_47.1 => constants.%.cb6\n// CHECK:STDOUT:   %pattern_type.loc6_43 => constants.%pattern_type.4f4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_38 => constants.%require_complete.944\n// CHECK:STDOUT:   %require_complete.loc6_47 => constants.%require_complete.ef1\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.specific_fn.loc7_10.2 => constants.%ExplicitAndAlsoDeduced.specific_fn.7e7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ExplicitAndAlsoDeduced(constants.%A) {\n// CHECK:STDOUT:   %T.loc6_27.1 => constants.%A\n// CHECK:STDOUT:   %pattern_type.loc6_37 => constants.%pattern_type.1ab\n// CHECK:STDOUT:   %ptr.loc6_47.1 => constants.%ptr.643\n// CHECK:STDOUT:   %.loc6_47.1 => constants.%.ebf\n// CHECK:STDOUT:   %pattern_type.loc6_43 => constants.%pattern_type.f29\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6_38 => constants.%complete_type.357\n// CHECK:STDOUT:   %require_complete.loc6_47 => constants.%complete_type.8a0\n// CHECK:STDOUT:   %ExplicitAndAlsoDeduced.specific_fn.loc7_10.2 => constants.%ExplicitAndAlsoDeduced.specific_fn.1f3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- deduce_implicit.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %ImplicitGenericParam.type: type = fn_type @ImplicitGenericParam [concrete]\n// CHECK:STDOUT:   %ImplicitGenericParam: %ImplicitGenericParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %ImplicitGenericParam.specific_fn.7cc: <specific function> = specific_function %ImplicitGenericParam, @ImplicitGenericParam(%T) [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %.605: Core.Form = init_form %ptr.235 [concrete]\n// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr.235 [concrete]\n// CHECK:STDOUT:   %CallImplicitGenericParam.type: type = fn_type @CallImplicitGenericParam [concrete]\n// CHECK:STDOUT:   %CallImplicitGenericParam: %CallImplicitGenericParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %ImplicitGenericParam.specific_fn.be5: <specific function> = specific_function %ImplicitGenericParam, @ImplicitGenericParam(%i32) [concrete]\n// CHECK:STDOUT:   %complete_type.3d0: <witness> = complete_type_witness %ptr.235 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ImplicitGenericParam = %ImplicitGenericParam.decl\n// CHECK:STDOUT:     .CallImplicitGenericParam = %CallImplicitGenericParam.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ImplicitGenericParam.decl: %ImplicitGenericParam.type = fn_decl @ImplicitGenericParam [concrete = constants.%ImplicitGenericParam] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @ImplicitGenericParam.%pattern_type.loc4_35 (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @ImplicitGenericParam.%pattern_type.loc4_35 (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @ImplicitGenericParam.%pattern_type.loc4_41 (%pattern_type.4f4) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @ImplicitGenericParam.%pattern_type.loc4_41 (%pattern_type.4f4) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc4_44: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc4_45.2: type = ptr_type %T.ref.loc4_44 [symbolic = %ptr.loc4_45.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     %.loc4_45.2: Core.Form = init_form %ptr.loc4_45.2 [symbolic = %.loc4_45.1 (constants.%.cb6)]\n// CHECK:STDOUT:     %.loc4_29.1: type = splice_block %.loc4_29.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_29.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_25.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @ImplicitGenericParam.%T.loc4_25.1 (%T) = value_param call_param0\n// CHECK:STDOUT:     %T.ref.loc4_38: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %x: @ImplicitGenericParam.%T.loc4_25.1 (%T) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @ImplicitGenericParam.%ptr.loc4_45.1 (%ptr.e8f) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @ImplicitGenericParam.%ptr.loc4_45.1 (%ptr.e8f) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallImplicitGenericParam.decl: %CallImplicitGenericParam.type = fn_decl @CallImplicitGenericParam [concrete = constants.%CallImplicitGenericParam] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.fe8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.fe8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc6_40: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ptr: type = ptr_type %i32.loc6_40 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:     %.loc6: Core.Form = init_form %ptr [concrete = constants.%.605]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc6_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %return.param: ref %ptr.235 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %ptr.235 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ImplicitGenericParam(%T.loc4_25.2: type) {\n// CHECK:STDOUT:   %T.loc4_25.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:   %pattern_type.loc4_35: type = pattern_type %T.loc4_25.1 [symbolic = %pattern_type.loc4_35 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:   %ptr.loc4_45.1: type = ptr_type %T.loc4_25.1 [symbolic = %ptr.loc4_45.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %.loc4_45.1: Core.Form = init_form %ptr.loc4_45.1 [symbolic = %.loc4_45.1 (constants.%.cb6)]\n// CHECK:STDOUT:   %pattern_type.loc4_41: type = pattern_type %ptr.loc4_45.1 [symbolic = %pattern_type.loc4_41 (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc4_36: <witness> = require_complete_type %T.loc4_25.1 [symbolic = %require_complete.loc4_36 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %require_complete.loc4_45: <witness> = require_complete_type %ptr.loc4_45.1 [symbolic = %require_complete.loc4_45 (constants.%require_complete.ef1)]\n// CHECK:STDOUT:   %ImplicitGenericParam.specific_fn.loc4_56.2: <specific function> = specific_function constants.%ImplicitGenericParam, @ImplicitGenericParam(%T.loc4_25.1) [symbolic = %ImplicitGenericParam.specific_fn.loc4_56.2 (constants.%ImplicitGenericParam.specific_fn.7cc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @ImplicitGenericParam.%T.loc4_25.1 (%T)) -> out %return.param: @ImplicitGenericParam.%ptr.loc4_45.1 (%ptr.e8f) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %ImplicitGenericParam.ref: %ImplicitGenericParam.type = name_ref ImplicitGenericParam, file.%ImplicitGenericParam.decl [concrete = constants.%ImplicitGenericParam]\n// CHECK:STDOUT:     %x.ref: @ImplicitGenericParam.%T.loc4_25.1 (%T) = name_ref x, %x\n// CHECK:STDOUT:     %ImplicitGenericParam.specific_fn.loc4_56.1: <specific function> = specific_function %ImplicitGenericParam.ref, @ImplicitGenericParam(constants.%T) [symbolic = %ImplicitGenericParam.specific_fn.loc4_56.2 (constants.%ImplicitGenericParam.specific_fn.7cc)]\n// CHECK:STDOUT:     %ImplicitGenericParam.call: init @ImplicitGenericParam.%ptr.loc4_45.1 (%ptr.e8f) = call %ImplicitGenericParam.specific_fn.loc4_56.1(%x.ref)\n// CHECK:STDOUT:     return %ImplicitGenericParam.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallImplicitGenericParam(%n.param: %i32) -> out %return.param: %ptr.235 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ImplicitGenericParam.ref: %ImplicitGenericParam.type = name_ref ImplicitGenericParam, file.%ImplicitGenericParam.decl [concrete = constants.%ImplicitGenericParam]\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %ImplicitGenericParam.specific_fn: <specific function> = specific_function %ImplicitGenericParam.ref, @ImplicitGenericParam(constants.%i32) [concrete = constants.%ImplicitGenericParam.specific_fn.be5]\n// CHECK:STDOUT:   %ImplicitGenericParam.call: init %ptr.235 = call %ImplicitGenericParam.specific_fn(%n.ref)\n// CHECK:STDOUT:   return %ImplicitGenericParam.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitGenericParam(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_25.1 => constants.%T\n// CHECK:STDOUT:   %pattern_type.loc4_35 => constants.%pattern_type.51d\n// CHECK:STDOUT:   %ptr.loc4_45.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %.loc4_45.1 => constants.%.cb6\n// CHECK:STDOUT:   %pattern_type.loc4_41 => constants.%pattern_type.4f4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc4_36 => constants.%require_complete.944\n// CHECK:STDOUT:   %require_complete.loc4_45 => constants.%require_complete.ef1\n// CHECK:STDOUT:   %ImplicitGenericParam.specific_fn.loc4_56.2 => constants.%ImplicitGenericParam.specific_fn.7cc\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitGenericParam(constants.%i32) {\n// CHECK:STDOUT:   %T.loc4_25.1 => constants.%i32\n// CHECK:STDOUT:   %pattern_type.loc4_35 => constants.%pattern_type.7ce\n// CHECK:STDOUT:   %ptr.loc4_45.1 => constants.%ptr.235\n// CHECK:STDOUT:   %.loc4_45.1 => constants.%.605\n// CHECK:STDOUT:   %pattern_type.loc4_41 => constants.%pattern_type.fe8\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc4_36 => constants.%complete_type.f8a\n// CHECK:STDOUT:   %require_complete.loc4_45 => constants.%complete_type.3d0\n// CHECK:STDOUT:   %ImplicitGenericParam.specific_fn.loc4_56.2 => constants.%ImplicitGenericParam.specific_fn.be5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- deduce_nested_tuple.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.c27: %tuple.type.24b = tuple_value (%T, %i32) [symbolic]\n// CHECK:STDOUT:   %tuple.type.b01: type = tuple_type (%T, %i32) [symbolic]\n// CHECK:STDOUT:   %pattern_type.e77: type = pattern_type %tuple.type.b01 [symbolic]\n// CHECK:STDOUT:   %TupleParam.type: type = fn_type @TupleParam [concrete]\n// CHECK:STDOUT:   %TupleParam: %TupleParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.9d8: <witness> = require_complete_type %tuple.type.b01 [symbolic]\n// CHECK:STDOUT:   %CallTupleParam.type: type = fn_type @CallTupleParam [concrete]\n// CHECK:STDOUT:   %CallTupleParam: %CallTupleParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.type.f94: type = tuple_type (Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.ad8: %tuple.type.f94 = tuple_value (%int_1, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %tuple.ae9: %tuple.type.24b = tuple_value (Core.IntLiteral, %i32) [concrete]\n// CHECK:STDOUT:   %tuple.type.4c8: type = tuple_type (Core.IntLiteral, %i32) [concrete]\n// CHECK:STDOUT:   %pattern_type.6f2: type = pattern_type %tuple.type.4c8 [concrete]\n// CHECK:STDOUT:   %TupleParam.specific_fn: <specific function> = specific_function %TupleParam, @TupleParam(Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.c87: %tuple.type.4c8 = tuple_value (%int_1, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %complete_type.c49: <witness> = complete_type_witness %tuple.type.4c8 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .TupleParam = %TupleParam.decl\n// CHECK:STDOUT:     .CallTupleParam = %CallTupleParam.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %TupleParam.decl: %TupleParam.type = fn_decl @TupleParam [concrete = constants.%TupleParam] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @TupleParam.%pattern_type (%pattern_type.e77) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @TupleParam.%pattern_type (%pattern_type.e77) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @TupleParam.%tuple.type (%tuple.type.b01) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_42.1: type = splice_block %.loc4_42.3 [symbolic = %tuple.type (constants.%tuple.type.b01)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc4_15.2 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %.loc4_42.2: %tuple.type.24b = tuple_literal (%T.ref, %i32) [symbolic = %tuple (constants.%tuple.c27)]\n// CHECK:STDOUT:       %.loc4_42.3: type = converted %.loc4_42.2, constants.%tuple.type.b01 [symbolic = %tuple.type (constants.%tuple.type.b01)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @TupleParam.%tuple.type (%tuple.type.b01) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallTupleParam.decl: %CallTupleParam.type = fn_decl @CallTupleParam [concrete = constants.%CallTupleParam] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @TupleParam(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_15.1 (constants.%T)]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%T.loc4_15.1, constants.%i32) [symbolic = %tuple (constants.%tuple.c27)]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%T.loc4_15.1, constants.%i32) [symbolic = %tuple.type (constants.%tuple.type.b01)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %tuple.type [symbolic = %pattern_type (constants.%pattern_type.e77)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %tuple.type [symbolic = %require_complete (constants.%require_complete.9d8)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @TupleParam.%tuple.type (%tuple.type.b01)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallTupleParam() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %TupleParam.ref: %TupleParam.type = name_ref TupleParam, file.%TupleParam.decl [concrete = constants.%TupleParam]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc7_19.1: %tuple.type.f94 = tuple_literal (%int_1, %int_2) [concrete = constants.%tuple.ad8]\n// CHECK:STDOUT:   %TupleParam.specific_fn: <specific function> = specific_function %TupleParam.ref, @TupleParam(Core.IntLiteral) [concrete = constants.%TupleParam.specific_fn]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc7_19.1: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_19.2: <bound method> = bound_method %int_2, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc7_19.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc7_19.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc7_19.3: %i32 = converted %int_2, %.loc7_19.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %tuple: %tuple.type.4c8 = tuple_value (%int_1, %.loc7_19.3) [concrete = constants.%tuple.c87]\n// CHECK:STDOUT:   %.loc7_19.4: %tuple.type.4c8 = converted %.loc7_19.1, %tuple [concrete = constants.%tuple.c87]\n// CHECK:STDOUT:   %TupleParam.call: init %empty_tuple.type = call %TupleParam.specific_fn(%.loc7_19.4)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TupleParam(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T\n// CHECK:STDOUT:   %tuple => constants.%tuple.c27\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.b01\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.e77\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @TupleParam(Core.IntLiteral) {\n// CHECK:STDOUT:   %T.loc4_15.1 => Core.IntLiteral\n// CHECK:STDOUT:   %tuple => constants.%tuple.ae9\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.4c8\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.6f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.c49\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- deduce_nested_struct.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.702: type = struct_type {.a: %T, .b: %i32} [symbolic]\n// CHECK:STDOUT:   %pattern_type.8a5: type = pattern_type %struct_type.a.b.702 [symbolic]\n// CHECK:STDOUT:   %StructParam.type: type = fn_type @StructParam [concrete]\n// CHECK:STDOUT:   %StructParam: %StructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.19d: <witness> = require_complete_type %struct_type.a.b.702 [symbolic]\n// CHECK:STDOUT:   %CallStructParam.type: type = fn_type @CallStructParam [concrete]\n// CHECK:STDOUT:   %CallStructParam: %CallStructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.cfd: type = struct_type {.a: Core.IntLiteral, .b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.4aa: %struct_type.a.b.cfd = struct_value (%int_1, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.a13: type = struct_type {.a: Core.IntLiteral, .b: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.cfa: type = pattern_type %struct_type.a.b.a13 [concrete]\n// CHECK:STDOUT:   %StructParam.specific_fn: <specific function> = specific_function %StructParam, @StructParam(Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct.e87: %struct_type.a.b.a13 = struct_value (%int_1, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %complete_type.a4a: <witness> = complete_type_witness %struct_type.a.b.a13 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .StructParam = %StructParam.decl\n// CHECK:STDOUT:     .CallStructParam = %CallStructParam.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %StructParam.decl: %StructParam.type = fn_decl @StructParam [concrete = constants.%StructParam] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @StructParam.%pattern_type (%pattern_type.8a5) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @StructParam.%pattern_type (%pattern_type.8a5) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_20.1: type = splice_block %.loc4_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_16.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_16.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @StructParam.%struct_type.a.b.loc4_51.1 (%struct_type.a.b.702) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_51: type = splice_block %struct_type.a.b.loc4_51.2 [symbolic = %struct_type.a.b.loc4_51.1 (constants.%struct_type.a.b.702)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc4_16.2 [symbolic = %T.loc4_16.1 (constants.%T)]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.a.b.loc4_51.2: type = struct_type {.a: @StructParam.%T.loc4_16.1 (%T), .b: %i32} [symbolic = %struct_type.a.b.loc4_51.1 (constants.%struct_type.a.b.702)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @StructParam.%struct_type.a.b.loc4_51.1 (%struct_type.a.b.702) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallStructParam.decl: %CallStructParam.type = fn_decl @CallStructParam [concrete = constants.%CallStructParam] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @StructParam(%T.loc4_16.2: type) {\n// CHECK:STDOUT:   %T.loc4_16.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_16.1 (constants.%T)]\n// CHECK:STDOUT:   %struct_type.a.b.loc4_51.1: type = struct_type {.a: @StructParam.%T.loc4_16.1 (%T), .b: %i32} [symbolic = %struct_type.a.b.loc4_51.1 (constants.%struct_type.a.b.702)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %struct_type.a.b.loc4_51.1 [symbolic = %pattern_type (constants.%pattern_type.8a5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.a.b.loc4_51.1 [symbolic = %require_complete (constants.%require_complete.19d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @StructParam.%struct_type.a.b.loc4_51.1 (%struct_type.a.b.702)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallStructParam() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %StructParam.ref: %StructParam.type = name_ref StructParam, file.%StructParam.decl [concrete = constants.%StructParam]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc7_30.1: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2) [concrete = constants.%struct.4aa]\n// CHECK:STDOUT:   %StructParam.specific_fn: <specific function> = specific_function %StructParam.ref, @StructParam(Core.IntLiteral) [concrete = constants.%StructParam.specific_fn]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc7_30.1: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc7_30.2: <bound method> = bound_method %int_2, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc7_30.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc7_30.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc7_30.3: %i32 = converted %int_2, %.loc7_30.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %struct: %struct_type.a.b.a13 = struct_value (%int_1, %.loc7_30.3) [concrete = constants.%struct.e87]\n// CHECK:STDOUT:   %.loc7_30.4: %struct_type.a.b.a13 = converted %.loc7_30.1, %struct [concrete = constants.%struct.e87]\n// CHECK:STDOUT:   %StructParam.call: init %empty_tuple.type = call %StructParam.specific_fn(%.loc7_30.4)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @StructParam(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_16.1 => constants.%T\n// CHECK:STDOUT:   %struct_type.a.b.loc4_51.1 => constants.%struct_type.a.b.702\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.8a5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @StructParam(Core.IntLiteral) {\n// CHECK:STDOUT:   %T.loc4_16.1 => Core.IntLiteral\n// CHECK:STDOUT:   %struct_type.a.b.loc4_51.1 => constants.%struct_type.a.b.a13\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.cfa\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.a4a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_deduce_bigger_struct.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.c.d.e: type = struct_type {.c: %T, .d: %i32, .e: %i32} [symbolic]\n// CHECK:STDOUT:   %pattern_type.1d5: type = pattern_type %struct_type.c.d.e [symbolic]\n// CHECK:STDOUT:   %BigStructParam.type: type = fn_type @BigStructParam [concrete]\n// CHECK:STDOUT:   %BigStructParam: %BigStructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.32d: <witness> = require_complete_type %struct_type.c.d.e [symbolic]\n// CHECK:STDOUT:   %CallBigStructParam.type: type = fn_type @CallBigStructParam [concrete]\n// CHECK:STDOUT:   %CallBigStructParam: %CallBigStructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %struct_type.c.d: type = struct_type {.c: Core.IntLiteral, .d: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.c.d = struct_value (%int_3, %int_4) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .BigStructParam = %BigStructParam.decl\n// CHECK:STDOUT:     .CallBigStructParam = %CallBigStructParam.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %BigStructParam.decl: %BigStructParam.type = fn_decl @BigStructParam [concrete = constants.%BigStructParam] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @BigStructParam.%pattern_type (%pattern_type.1d5) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @BigStructParam.%pattern_type (%pattern_type.1d5) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_23.1: type = splice_block %.loc4_23.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_23.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_19.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_19.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @BigStructParam.%struct_type.c.d.e.loc4_63.1 (%struct_type.c.d.e) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_63: type = splice_block %struct_type.c.d.e.loc4_63.2 [symbolic = %struct_type.c.d.e.loc4_63.1 (constants.%struct_type.c.d.e)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc4_19.2 [symbolic = %T.loc4_19.1 (constants.%T)]\n// CHECK:STDOUT:       %i32.loc4_51: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %i32.loc4_60: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.c.d.e.loc4_63.2: type = struct_type {.c: @BigStructParam.%T.loc4_19.1 (%T), .d: %i32, .e: %i32} [symbolic = %struct_type.c.d.e.loc4_63.1 (constants.%struct_type.c.d.e)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @BigStructParam.%struct_type.c.d.e.loc4_63.1 (%struct_type.c.d.e) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallBigStructParam.decl: %CallBigStructParam.type = fn_decl @CallBigStructParam [concrete = constants.%CallBigStructParam] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @BigStructParam(%T.loc4_19.2: type) {\n// CHECK:STDOUT:   %T.loc4_19.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_19.1 (constants.%T)]\n// CHECK:STDOUT:   %struct_type.c.d.e.loc4_63.1: type = struct_type {.c: @BigStructParam.%T.loc4_19.1 (%T), .d: %i32, .e: %i32} [symbolic = %struct_type.c.d.e.loc4_63.1 (constants.%struct_type.c.d.e)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %struct_type.c.d.e.loc4_63.1 [symbolic = %pattern_type (constants.%pattern_type.1d5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.c.d.e.loc4_63.1 [symbolic = %require_complete (constants.%require_complete.32d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @BigStructParam.%struct_type.c.d.e.loc4_63.1 (%struct_type.c.d.e)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallBigStructParam() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %BigStructParam.ref: %BigStructParam.type = name_ref BigStructParam, file.%BigStructParam.decl [concrete = constants.%BigStructParam]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4]\n// CHECK:STDOUT:   %.loc14: %struct_type.c.d = struct_literal (%int_3, %int_4) [concrete = constants.%struct]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @BigStructParam(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_19.1 => constants.%T\n// CHECK:STDOUT:   %struct_type.c.d.e.loc4_63.1 => constants.%struct_type.c.d.e\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.1d5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_deduce_smaller_struct.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.f.g: type = struct_type {.f: %T, .g: %i32} [symbolic]\n// CHECK:STDOUT:   %pattern_type.958: type = pattern_type %struct_type.f.g [symbolic]\n// CHECK:STDOUT:   %SmallStructParam.type: type = fn_type @SmallStructParam [concrete]\n// CHECK:STDOUT:   %SmallStructParam: %SmallStructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.ed5: <witness> = require_complete_type %struct_type.f.g [symbolic]\n// CHECK:STDOUT:   %CallSmallStructParam.type: type = fn_type @CallSmallStructParam [concrete]\n// CHECK:STDOUT:   %CallSmallStructParam: %CallSmallStructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete]\n// CHECK:STDOUT:   %int_6: Core.IntLiteral = int_value 6 [concrete]\n// CHECK:STDOUT:   %int_7: Core.IntLiteral = int_value 7 [concrete]\n// CHECK:STDOUT:   %struct_type.f.g.h: type = struct_type {.f: Core.IntLiteral, .g: Core.IntLiteral, .h: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.f.g.h = struct_value (%int_5, %int_6, %int_7) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .SmallStructParam = %SmallStructParam.decl\n// CHECK:STDOUT:     .CallSmallStructParam = %CallSmallStructParam.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %SmallStructParam.decl: %SmallStructParam.type = fn_decl @SmallStructParam [concrete = constants.%SmallStructParam] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @SmallStructParam.%pattern_type (%pattern_type.958) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @SmallStructParam.%pattern_type (%pattern_type.958) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_25.1: type = splice_block %.loc4_25.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_25.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_21.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_21.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @SmallStructParam.%struct_type.f.g.loc4_56.1 (%struct_type.f.g) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_56: type = splice_block %struct_type.f.g.loc4_56.2 [symbolic = %struct_type.f.g.loc4_56.1 (constants.%struct_type.f.g)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc4_21.2 [symbolic = %T.loc4_21.1 (constants.%T)]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.f.g.loc4_56.2: type = struct_type {.f: @SmallStructParam.%T.loc4_21.1 (%T), .g: %i32} [symbolic = %struct_type.f.g.loc4_56.1 (constants.%struct_type.f.g)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @SmallStructParam.%struct_type.f.g.loc4_56.1 (%struct_type.f.g) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallSmallStructParam.decl: %CallSmallStructParam.type = fn_decl @CallSmallStructParam [concrete = constants.%CallSmallStructParam] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @SmallStructParam(%T.loc4_21.2: type) {\n// CHECK:STDOUT:   %T.loc4_21.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_21.1 (constants.%T)]\n// CHECK:STDOUT:   %struct_type.f.g.loc4_56.1: type = struct_type {.f: @SmallStructParam.%T.loc4_21.1 (%T), .g: %i32} [symbolic = %struct_type.f.g.loc4_56.1 (constants.%struct_type.f.g)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %struct_type.f.g.loc4_56.1 [symbolic = %pattern_type (constants.%pattern_type.958)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.f.g.loc4_56.1 [symbolic = %require_complete (constants.%require_complete.ed5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @SmallStructParam.%struct_type.f.g.loc4_56.1 (%struct_type.f.g)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallSmallStructParam() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %SmallStructParam.ref: %SmallStructParam.type = name_ref SmallStructParam, file.%SmallStructParam.decl [concrete = constants.%SmallStructParam]\n// CHECK:STDOUT:   %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5]\n// CHECK:STDOUT:   %int_6: Core.IntLiteral = int_value 6 [concrete = constants.%int_6]\n// CHECK:STDOUT:   %int_7: Core.IntLiteral = int_value 7 [concrete = constants.%int_7]\n// CHECK:STDOUT:   %.loc14: %struct_type.f.g.h = struct_literal (%int_5, %int_6, %int_7) [concrete = constants.%struct]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @SmallStructParam(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_21.1 => constants.%T\n// CHECK:STDOUT:   %struct_type.f.g.loc4_56.1 => constants.%struct_type.f.g\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.958\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_deduce_struct_wrong_name.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.i.different: type = struct_type {.i: %T, .different: %i32} [symbolic]\n// CHECK:STDOUT:   %pattern_type.ce4: type = pattern_type %struct_type.i.different [symbolic]\n// CHECK:STDOUT:   %WrongNameStructParam.type: type = fn_type @WrongNameStructParam [concrete]\n// CHECK:STDOUT:   %WrongNameStructParam: %WrongNameStructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.c84: <witness> = require_complete_type %struct_type.i.different [symbolic]\n// CHECK:STDOUT:   %CallWrongNameStructParam.type: type = fn_type @CallWrongNameStructParam [concrete]\n// CHECK:STDOUT:   %CallWrongNameStructParam: %CallWrongNameStructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_8: Core.IntLiteral = int_value 8 [concrete]\n// CHECK:STDOUT:   %int_9: Core.IntLiteral = int_value 9 [concrete]\n// CHECK:STDOUT:   %struct_type.i.j: type = struct_type {.i: Core.IntLiteral, .j: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.i.j = struct_value (%int_8, %int_9) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .WrongNameStructParam = %WrongNameStructParam.decl\n// CHECK:STDOUT:     .CallWrongNameStructParam = %CallWrongNameStructParam.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %WrongNameStructParam.decl: %WrongNameStructParam.type = fn_decl @WrongNameStructParam [concrete = constants.%WrongNameStructParam] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @WrongNameStructParam.%pattern_type (%pattern_type.ce4) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @WrongNameStructParam.%pattern_type (%pattern_type.ce4) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_29.1: type = splice_block %.loc4_29.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_29.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_25.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @WrongNameStructParam.%struct_type.i.different.loc4_68.1 (%struct_type.i.different) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_68: type = splice_block %struct_type.i.different.loc4_68.2 [symbolic = %struct_type.i.different.loc4_68.1 (constants.%struct_type.i.different)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.i.different.loc4_68.2: type = struct_type {.i: @WrongNameStructParam.%T.loc4_25.1 (%T), .different: %i32} [symbolic = %struct_type.i.different.loc4_68.1 (constants.%struct_type.i.different)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @WrongNameStructParam.%struct_type.i.different.loc4_68.1 (%struct_type.i.different) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallWrongNameStructParam.decl: %CallWrongNameStructParam.type = fn_decl @CallWrongNameStructParam [concrete = constants.%CallWrongNameStructParam] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @WrongNameStructParam(%T.loc4_25.2: type) {\n// CHECK:STDOUT:   %T.loc4_25.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:   %struct_type.i.different.loc4_68.1: type = struct_type {.i: @WrongNameStructParam.%T.loc4_25.1 (%T), .different: %i32} [symbolic = %struct_type.i.different.loc4_68.1 (constants.%struct_type.i.different)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %struct_type.i.different.loc4_68.1 [symbolic = %pattern_type (constants.%pattern_type.ce4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.i.different.loc4_68.1 [symbolic = %require_complete (constants.%require_complete.c84)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @WrongNameStructParam.%struct_type.i.different.loc4_68.1 (%struct_type.i.different)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallWrongNameStructParam() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %WrongNameStructParam.ref: %WrongNameStructParam.type = name_ref WrongNameStructParam, file.%WrongNameStructParam.decl [concrete = constants.%WrongNameStructParam]\n// CHECK:STDOUT:   %int_8: Core.IntLiteral = int_value 8 [concrete = constants.%int_8]\n// CHECK:STDOUT:   %int_9: Core.IntLiteral = int_value 9 [concrete = constants.%int_9]\n// CHECK:STDOUT:   %.loc14: %struct_type.i.j = struct_literal (%int_8, %int_9) [concrete = constants.%struct]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WrongNameStructParam(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_25.1 => constants.%T\n// CHECK:STDOUT:   %struct_type.i.different.loc4_68.1 => constants.%struct_type.i.different\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.ce4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_deduce_struct_wrong_order.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.first.second: type = struct_type {.first: %T, .second: %i32} [symbolic]\n// CHECK:STDOUT:   %pattern_type.ab3: type = pattern_type %struct_type.first.second [symbolic]\n// CHECK:STDOUT:   %WrongOrderStructParam.type: type = fn_type @WrongOrderStructParam [concrete]\n// CHECK:STDOUT:   %WrongOrderStructParam: %WrongOrderStructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.311: <witness> = require_complete_type %struct_type.first.second [symbolic]\n// CHECK:STDOUT:   %CallWrongOrderStructParam.type: type = fn_type @CallWrongOrderStructParam [concrete]\n// CHECK:STDOUT:   %CallWrongOrderStructParam: %CallWrongOrderStructParam.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_11: Core.IntLiteral = int_value 11 [concrete]\n// CHECK:STDOUT:   %int_10: Core.IntLiteral = int_value 10 [concrete]\n// CHECK:STDOUT:   %struct_type.second.first: type = struct_type {.second: Core.IntLiteral, .first: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.second.first = struct_value (%int_11, %int_10) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .WrongOrderStructParam = %WrongOrderStructParam.decl\n// CHECK:STDOUT:     .CallWrongOrderStructParam = %CallWrongOrderStructParam.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %WrongOrderStructParam.decl: %WrongOrderStructParam.type = fn_decl @WrongOrderStructParam [concrete = constants.%WrongOrderStructParam] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @WrongOrderStructParam.%pattern_type (%pattern_type.ab3) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @WrongOrderStructParam.%pattern_type (%pattern_type.ab3) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_30.1: type = splice_block %.loc4_30.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_30.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_26.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_26.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @WrongOrderStructParam.%struct_type.first.second.loc4_70.1 (%struct_type.first.second) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_70: type = splice_block %struct_type.first.second.loc4_70.2 [symbolic = %struct_type.first.second.loc4_70.1 (constants.%struct_type.first.second)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc4_26.2 [symbolic = %T.loc4_26.1 (constants.%T)]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.first.second.loc4_70.2: type = struct_type {.first: @WrongOrderStructParam.%T.loc4_26.1 (%T), .second: %i32} [symbolic = %struct_type.first.second.loc4_70.1 (constants.%struct_type.first.second)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @WrongOrderStructParam.%struct_type.first.second.loc4_70.1 (%struct_type.first.second) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallWrongOrderStructParam.decl: %CallWrongOrderStructParam.type = fn_decl @CallWrongOrderStructParam [concrete = constants.%CallWrongOrderStructParam] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @WrongOrderStructParam(%T.loc4_26.2: type) {\n// CHECK:STDOUT:   %T.loc4_26.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_26.1 (constants.%T)]\n// CHECK:STDOUT:   %struct_type.first.second.loc4_70.1: type = struct_type {.first: @WrongOrderStructParam.%T.loc4_26.1 (%T), .second: %i32} [symbolic = %struct_type.first.second.loc4_70.1 (constants.%struct_type.first.second)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %struct_type.first.second.loc4_70.1 [symbolic = %pattern_type (constants.%pattern_type.ab3)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.first.second.loc4_70.1 [symbolic = %require_complete (constants.%require_complete.311)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @WrongOrderStructParam.%struct_type.first.second.loc4_70.1 (%struct_type.first.second)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallWrongOrderStructParam() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %WrongOrderStructParam.ref: %WrongOrderStructParam.type = name_ref WrongOrderStructParam, file.%WrongOrderStructParam.decl [concrete = constants.%WrongOrderStructParam]\n// CHECK:STDOUT:   %int_11: Core.IntLiteral = int_value 11 [concrete = constants.%int_11]\n// CHECK:STDOUT:   %int_10: Core.IntLiteral = int_value 10 [concrete = constants.%int_10]\n// CHECK:STDOUT:   %.loc14: %struct_type.second.first = struct_literal (%int_11, %int_10) [concrete = constants.%struct]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @WrongOrderStructParam(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_26.1 => constants.%T\n// CHECK:STDOUT:   %struct_type.first.second.loc4_70.1 => constants.%struct_type.first.second\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.ab3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_deduce_incomplete.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %.822: Core.Form = init_form %U [symbolic]\n// CHECK:STDOUT:   %pattern_type.946: type = pattern_type %U [symbolic]\n// CHECK:STDOUT:   %ImplicitNotDeducible.type: type = fn_type @ImplicitNotDeducible [concrete]\n// CHECK:STDOUT:   %ImplicitNotDeducible: %ImplicitNotDeducible.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallImplicitNotDeducible.type: type = fn_type @CallImplicitNotDeducible [concrete]\n// CHECK:STDOUT:   %CallImplicitNotDeducible: %CallImplicitNotDeducible.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_42: Core.IntLiteral = int_value 42 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ImplicitNotDeducible = %ImplicitNotDeducible.decl\n// CHECK:STDOUT:     .CallImplicitNotDeducible = %CallImplicitNotDeducible.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ImplicitNotDeducible.decl: %ImplicitNotDeducible.type = fn_decl @ImplicitNotDeducible [concrete = constants.%ImplicitNotDeducible] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %x.patt: @ImplicitNotDeducible.%pattern_type.loc6_45 (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @ImplicitNotDeducible.%pattern_type.loc6_45 (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @ImplicitNotDeducible.%pattern_type.loc6_51 (%pattern_type.946) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @ImplicitNotDeducible.%pattern_type.loc6_51 (%pattern_type.946) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %U.ref: type = name_ref U, %U.loc6_35.2 [symbolic = %U.loc6_35.1 (constants.%U)]\n// CHECK:STDOUT:     %.loc6_54.2: Core.Form = init_form %U.ref [symbolic = %.loc6_54.1 (constants.%.822)]\n// CHECK:STDOUT:     %.loc6_29.1: type = splice_block %.loc6_29.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_29.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_25.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_25.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc6_39.1: type = splice_block %.loc6_39.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_39.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc6_35.2: type = symbolic_binding U, 1 [symbolic = %U.loc6_35.1 (constants.%U)]\n// CHECK:STDOUT:     %x.param: @ImplicitNotDeducible.%T.loc6_25.1 (%T) = value_param call_param0\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc6_25.2 [symbolic = %T.loc6_25.1 (constants.%T)]\n// CHECK:STDOUT:     %x: @ImplicitNotDeducible.%T.loc6_25.1 (%T) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @ImplicitNotDeducible.%U.loc6_35.1 (%U) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @ImplicitNotDeducible.%U.loc6_35.1 (%U) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallImplicitNotDeducible.decl: %CallImplicitNotDeducible.type = fn_decl @CallImplicitNotDeducible [concrete = constants.%CallImplicitNotDeducible] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ImplicitNotDeducible(%T.loc6_25.2: type, %U.loc6_35.2: type) {\n// CHECK:STDOUT:   %T.loc6_25.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_25.1 (constants.%T)]\n// CHECK:STDOUT:   %U.loc6_35.1: type = symbolic_binding U, 1 [symbolic = %U.loc6_35.1 (constants.%U)]\n// CHECK:STDOUT:   %pattern_type.loc6_45: type = pattern_type %T.loc6_25.1 [symbolic = %pattern_type.loc6_45 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:   %.loc6_54.1: Core.Form = init_form %U.loc6_35.1 [symbolic = %.loc6_54.1 (constants.%.822)]\n// CHECK:STDOUT:   %pattern_type.loc6_51: type = pattern_type %U.loc6_35.1 [symbolic = %pattern_type.loc6_51 (constants.%pattern_type.946)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @ImplicitNotDeducible.%T.loc6_25.1 (%T)) -> out %return.param: @ImplicitNotDeducible.%U.loc6_35.1 (%U);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallImplicitNotDeducible() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ImplicitNotDeducible.ref: %ImplicitNotDeducible.type = name_ref ImplicitNotDeducible, file.%ImplicitNotDeducible.decl [concrete = constants.%ImplicitNotDeducible]\n// CHECK:STDOUT:   %int_42: Core.IntLiteral = int_value 42 [concrete = constants.%int_42]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitNotDeducible(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc6_25.1 => constants.%T\n// CHECK:STDOUT:   %U.loc6_35.1 => constants.%U\n// CHECK:STDOUT:   %pattern_type.loc6_45 => constants.%pattern_type.51d\n// CHECK:STDOUT:   %.loc6_54.1 => constants.%.822\n// CHECK:STDOUT:   %pattern_type.loc6_51 => constants.%pattern_type.946\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_deduce_inconsistent.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %ImplicitNotDeducible.type: type = fn_type @ImplicitNotDeducible [concrete]\n// CHECK:STDOUT:   %ImplicitNotDeducible: %ImplicitNotDeducible.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallImplicitNotDeducible.type: type = fn_type @CallImplicitNotDeducible [concrete]\n// CHECK:STDOUT:   %CallImplicitNotDeducible: %CallImplicitNotDeducible.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_42: Core.IntLiteral = int_value 42 [concrete]\n// CHECK:STDOUT:   %int_12: Core.IntLiteral = int_value 12 [concrete]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.x = struct_value (%int_12) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ImplicitNotDeducible = %ImplicitNotDeducible.decl\n// CHECK:STDOUT:     .CallImplicitNotDeducible = %CallImplicitNotDeducible.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ImplicitNotDeducible.decl: %ImplicitNotDeducible.type = fn_decl @ImplicitNotDeducible [concrete = constants.%ImplicitNotDeducible] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @ImplicitNotDeducible.%pattern_type (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @ImplicitNotDeducible.%pattern_type (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %y.patt: @ImplicitNotDeducible.%pattern_type (%pattern_type.51d) = value_binding_pattern y [concrete]\n// CHECK:STDOUT:     %y.param_patt: @ImplicitNotDeducible.%pattern_type (%pattern_type.51d) = value_param_pattern %y.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @ImplicitNotDeducible.%pattern_type (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @ImplicitNotDeducible.%pattern_type (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc4_50: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc4_50.2: Core.Form = init_form %T.ref.loc4_50 [symbolic = %.loc4_50.1 (constants.%.184)]\n// CHECK:STDOUT:     %.loc4_29.1: type = splice_block %.loc4_29.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_29.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_25.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @ImplicitNotDeducible.%T.loc4_25.1 (%T) = value_param call_param0\n// CHECK:STDOUT:     %T.ref.loc4_38: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %x: @ImplicitNotDeducible.%T.loc4_25.1 (%T) = value_binding x, %x.param\n// CHECK:STDOUT:     %y.param: @ImplicitNotDeducible.%T.loc4_25.1 (%T) = value_param call_param1\n// CHECK:STDOUT:     %T.ref.loc4_44: type = name_ref T, %T.loc4_25.2 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:     %y: @ImplicitNotDeducible.%T.loc4_25.1 (%T) = value_binding y, %y.param\n// CHECK:STDOUT:     %return.param: ref @ImplicitNotDeducible.%T.loc4_25.1 (%T) = out_param call_param2\n// CHECK:STDOUT:     %return: ref @ImplicitNotDeducible.%T.loc4_25.1 (%T) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallImplicitNotDeducible.decl: %CallImplicitNotDeducible.type = fn_decl @CallImplicitNotDeducible [concrete = constants.%CallImplicitNotDeducible] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ImplicitNotDeducible(%T.loc4_25.2: type) {\n// CHECK:STDOUT:   %T.loc4_25.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_25.1 (constants.%T)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc4_25.1 [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:   %.loc4_50.1: Core.Form = init_form %T.loc4_25.1 [symbolic = %.loc4_50.1 (constants.%.184)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @ImplicitNotDeducible.%T.loc4_25.1 (%T), %y.param: @ImplicitNotDeducible.%T.loc4_25.1 (%T)) -> out %return.param: @ImplicitNotDeducible.%T.loc4_25.1 (%T);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallImplicitNotDeducible() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ImplicitNotDeducible.ref: %ImplicitNotDeducible.type = name_ref ImplicitNotDeducible, file.%ImplicitNotDeducible.decl [concrete = constants.%ImplicitNotDeducible]\n// CHECK:STDOUT:   %int_42: Core.IntLiteral = int_value 42 [concrete = constants.%int_42]\n// CHECK:STDOUT:   %int_12: Core.IntLiteral = int_value 12 [concrete = constants.%int_12]\n// CHECK:STDOUT:   %.loc14: %struct_type.x = struct_literal (%int_12) [concrete = constants.%struct]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitNotDeducible(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_25.1 => constants.%T\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT:   %.loc4_50.1 => constants.%.184\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- deduce_nested_generic_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %EE: type = class_type @EE [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Z.impl_witness.c05: <witness> = impl_witness @EE.as.Z.impl.%Z.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Z.facet.5dc: %Z.type = facet_value %EE, (%Z.impl_witness.c05) [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %E: type = symbolic_binding E, 0 [symbolic]\n// CHECK:STDOUT:   %DD.type: type = generic_class_type @DD [concrete]\n// CHECK:STDOUT:   %DD.generic: %DD.type = struct_value () [concrete]\n// CHECK:STDOUT:   %DD.a29: type = class_type @DD, @DD(%E) [symbolic]\n// CHECK:STDOUT:   %Z.impl_witness.437: <witness> = impl_witness @DD.as.Z.impl.%Z.impl_witness_table, @DD.as.Z.impl(%E) [symbolic]\n// CHECK:STDOUT:   %Z.facet.dc0: %Z.type = facet_value %DD.a29, (%Z.impl_witness.437) [symbolic]\n// CHECK:STDOUT:   %pattern_type.22b: type = pattern_type %Z.type [concrete]\n// CHECK:STDOUT:   %D: %Z.type = symbolic_binding D, 0 [symbolic]\n// CHECK:STDOUT:   %CC.type: type = generic_class_type @CC [concrete]\n// CHECK:STDOUT:   %CC.generic: %CC.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CC.a1b: type = class_type @CC, @CC(%D) [symbolic]\n// CHECK:STDOUT:   %.bf4: require_specific_def_type = require_specific_def @DD.as.Z.impl(%E) [symbolic]\n// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %DD.a29, @Z [symbolic]\n// CHECK:STDOUT:   %Z.facet.892: %Z.type = facet_value %DD.a29, (%Z.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %CC.4e1: type = class_type @CC, @CC(%Z.facet.892) [symbolic]\n// CHECK:STDOUT:   %Z.impl_witness.40e: <witness> = impl_witness @CC.as.Z.impl.%Z.impl_witness_table, @CC.as.Z.impl(%E) [symbolic]\n// CHECK:STDOUT:   %Z.facet.b7b: %Z.type = facet_value %CC.4e1, (%Z.impl_witness.40e) [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %DD.2e1: type = class_type @DD, @DD(%EE) [concrete]\n// CHECK:STDOUT:   %Z.impl_witness.8a3: <witness> = impl_witness @DD.as.Z.impl.%Z.impl_witness_table, @DD.as.Z.impl(%EE) [concrete]\n// CHECK:STDOUT:   %.36d: require_specific_def_type = require_specific_def @DD.as.Z.impl(%EE) [concrete]\n// CHECK:STDOUT:   %Z.facet.74c: %Z.type = facet_value %DD.2e1, (%Z.impl_witness.8a3) [concrete]\n// CHECK:STDOUT:   %CC.b19: type = class_type @CC, @CC(%Z.facet.74c) [concrete]\n// CHECK:STDOUT:   %Z.impl_witness.cb4: <witness> = impl_witness @CC.as.Z.impl.%Z.impl_witness_table, @CC.as.Z.impl(%EE) [concrete]\n// CHECK:STDOUT:   %Z.facet.145: %Z.type = facet_value %CC.b19, (%Z.impl_witness.cb4) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Z = %Z.decl\n// CHECK:STDOUT:     .EE = %EE.decl\n// CHECK:STDOUT:     .DD = %DD.decl\n// CHECK:STDOUT:     .CC = %CC.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Z.decl: type = interface_decl @Z [concrete = constants.%Z.type] {} {}\n// CHECK:STDOUT:   %EE.decl: type = class_decl @EE [concrete = constants.%EE] {} {}\n// CHECK:STDOUT:   impl_decl @EE.as.Z.impl [concrete] {} {\n// CHECK:STDOUT:     %EE.ref: type = name_ref EE, file.%EE.decl [concrete = constants.%EE]\n// CHECK:STDOUT:     %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %DD.decl: %DD.type = class_decl @DD [concrete = constants.%DD.generic] {\n// CHECK:STDOUT:     %E.patt: %pattern_type.98f = symbolic_binding_pattern E, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_14.1: type = splice_block %.loc8_14.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_14.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %E.loc8_10.2: type = symbolic_binding E, 0 [symbolic = %E.loc8_10.1 (constants.%E)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @DD.as.Z.impl [concrete] {\n// CHECK:STDOUT:     %E.patt: %pattern_type.98f = symbolic_binding_pattern E, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %DD.ref: %DD.type = name_ref DD, file.%DD.decl [concrete = constants.%DD.generic]\n// CHECK:STDOUT:     %E.ref: type = name_ref E, %E.loc9_14.1 [symbolic = %E.loc9_14.2 (constants.%E)]\n// CHECK:STDOUT:     %DD.loc9_28.1: type = class_type @DD, @DD(constants.%E) [symbolic = %DD.loc9_28.2 (constants.%DD.a29)]\n// CHECK:STDOUT:     %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:     %.loc9_18.1: type = splice_block %.loc9_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc9_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %E.loc9_14.1: type = symbolic_binding E, 0 [symbolic = %E.loc9_14.2 (constants.%E)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CC.decl: %CC.type = class_decl @CC [concrete = constants.%CC.generic] {\n// CHECK:STDOUT:     %D.patt: %pattern_type.22b = symbolic_binding_pattern D, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc11: type = splice_block %Z.ref [concrete = constants.%Z.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %D.loc11_10.2: %Z.type = symbolic_binding D, 0 [symbolic = %D.loc11_10.1 (constants.%D)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @CC.as.Z.impl [concrete] {\n// CHECK:STDOUT:     %E.patt: %pattern_type.98f = symbolic_binding_pattern E, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %CC.ref: %CC.type = name_ref CC, file.%CC.decl [concrete = constants.%CC.generic]\n// CHECK:STDOUT:     %DD.ref: %DD.type = name_ref DD, file.%DD.decl [concrete = constants.%DD.generic]\n// CHECK:STDOUT:     %E.ref: type = name_ref E, %E.loc12_14.1 [symbolic = %E.loc12_14.2 (constants.%E)]\n// CHECK:STDOUT:     %DD.loc12_31.1: type = class_type @DD, @DD(constants.%E) [symbolic = %DD.loc12_31.2 (constants.%DD.a29)]\n// CHECK:STDOUT:     %Z.facet.loc12_32.1: %Z.type = facet_value %DD.loc12_31.1, (constants.%Z.lookup_impl_witness) [symbolic = %Z.facet.loc12_32.2 (constants.%Z.facet.892)]\n// CHECK:STDOUT:     %.loc12_32.1: %Z.type = converted %DD.loc12_31.1, %Z.facet.loc12_32.1 [symbolic = %Z.facet.loc12_32.2 (constants.%Z.facet.892)]\n// CHECK:STDOUT:     %CC.loc12_32.1: type = class_type @CC, @CC(constants.%Z.facet.892) [symbolic = %CC.loc12_32.2 (constants.%CC.4e1)]\n// CHECK:STDOUT:     %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:     %.loc12_18.1: type = splice_block %.loc12_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc12_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %E.loc12_14.1: type = symbolic_binding E, 0 [symbolic = %E.loc12_14.2 (constants.%E)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Z {\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Z.WithSelf.decl = interface_with_self_decl @Z [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @EE.as.Z.impl: %EE.ref as %Z.ref {\n// CHECK:STDOUT:   %Z.impl_witness_table = impl_witness_table (), @EE.as.Z.impl [concrete]\n// CHECK:STDOUT:   %Z.impl_witness: <witness> = impl_witness %Z.impl_witness_table [concrete = constants.%Z.impl_witness.c05]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Z.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @DD.as.Z.impl(%E.loc9_14.1: type) {\n// CHECK:STDOUT:   %E.loc9_14.2: type = symbolic_binding E, 0 [symbolic = %E.loc9_14.2 (constants.%E)]\n// CHECK:STDOUT:   %DD.loc9_28.2: type = class_type @DD, @DD(%E.loc9_14.2) [symbolic = %DD.loc9_28.2 (constants.%DD.a29)]\n// CHECK:STDOUT:   %Z.impl_witness.loc9_35.2: <witness> = impl_witness %Z.impl_witness_table, @DD.as.Z.impl(%E.loc9_14.2) [symbolic = %Z.impl_witness.loc9_35.2 (constants.%Z.impl_witness.437)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %DD.loc9_28.1 as %Z.ref {\n// CHECK:STDOUT:     %Z.impl_witness_table = impl_witness_table (), @DD.as.Z.impl [concrete]\n// CHECK:STDOUT:     %Z.impl_witness.loc9_35.1: <witness> = impl_witness %Z.impl_witness_table, @DD.as.Z.impl(constants.%E) [symbolic = %Z.impl_witness.loc9_35.2 (constants.%Z.impl_witness.437)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Z.impl_witness.loc9_35.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @CC.as.Z.impl(%E.loc12_14.1: type) {\n// CHECK:STDOUT:   %E.loc12_14.2: type = symbolic_binding E, 0 [symbolic = %E.loc12_14.2 (constants.%E)]\n// CHECK:STDOUT:   %DD.loc12_31.2: type = class_type @DD, @DD(%E.loc12_14.2) [symbolic = %DD.loc12_31.2 (constants.%DD.a29)]\n// CHECK:STDOUT:   %.loc12_32.2: require_specific_def_type = require_specific_def @DD.as.Z.impl(%E.loc12_14.2) [symbolic = %.loc12_32.2 (constants.%.bf4)]\n// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %DD.loc12_31.2, @Z [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness)]\n// CHECK:STDOUT:   %Z.facet.loc12_32.2: %Z.type = facet_value %DD.loc12_31.2, (%Z.lookup_impl_witness) [symbolic = %Z.facet.loc12_32.2 (constants.%Z.facet.892)]\n// CHECK:STDOUT:   %CC.loc12_32.2: type = class_type @CC, @CC(%Z.facet.loc12_32.2) [symbolic = %CC.loc12_32.2 (constants.%CC.4e1)]\n// CHECK:STDOUT:   %Z.impl_witness.loc12_39.2: <witness> = impl_witness %Z.impl_witness_table, @CC.as.Z.impl(%E.loc12_14.2) [symbolic = %Z.impl_witness.loc12_39.2 (constants.%Z.impl_witness.40e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %CC.loc12_32.1 as %Z.ref {\n// CHECK:STDOUT:     %Z.impl_witness_table = impl_witness_table (), @CC.as.Z.impl [concrete]\n// CHECK:STDOUT:     %Z.impl_witness.loc12_39.1: <witness> = impl_witness %Z.impl_witness_table, @CC.as.Z.impl(constants.%E) [symbolic = %Z.impl_witness.loc12_39.2 (constants.%Z.impl_witness.40e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Z.impl_witness.loc12_39.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @EE {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%EE\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @DD(%E.loc8_10.2: type) {\n// CHECK:STDOUT:   %E.loc8_10.1: type = symbolic_binding E, 0 [symbolic = %E.loc8_10.1 (constants.%E)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%DD.a29\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @CC(%D.loc11_10.2: %Z.type) {\n// CHECK:STDOUT:   %D.loc11_10.1: %Z.type = symbolic_binding D, 0 [symbolic = %D.loc11_10.1 (constants.%D)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%CC.a1b\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %CC.ref: %CC.type = name_ref CC, file.%CC.decl [concrete = constants.%CC.generic]\n// CHECK:STDOUT:   %DD.ref: %DD.type = name_ref DD, file.%DD.decl [concrete = constants.%DD.generic]\n// CHECK:STDOUT:   %EE.ref: type = name_ref EE, file.%EE.decl [concrete = constants.%EE]\n// CHECK:STDOUT:   %DD: type = class_type @DD, @DD(constants.%EE) [concrete = constants.%DD.2e1]\n// CHECK:STDOUT:   %Z.facet.loc15_12: %Z.type = facet_value %DD, (constants.%Z.impl_witness.8a3) [concrete = constants.%Z.facet.74c]\n// CHECK:STDOUT:   %.loc15_12: %Z.type = converted %DD, %Z.facet.loc15_12 [concrete = constants.%Z.facet.74c]\n// CHECK:STDOUT:   %CC: type = class_type @CC, @CC(constants.%Z.facet.74c) [concrete = constants.%CC.b19]\n// CHECK:STDOUT:   %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:   %Z.facet.loc15_14: %Z.type = facet_value %CC, (constants.%Z.impl_witness.cb4) [concrete = constants.%Z.facet.145]\n// CHECK:STDOUT:   %.loc15_14: %Z.type = converted %CC, %Z.facet.loc15_14 [concrete = constants.%Z.facet.145]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Z.facet.5dc) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @DD(constants.%E) {\n// CHECK:STDOUT:   %E.loc8_10.1 => constants.%E\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @DD.as.Z.impl(constants.%E) {\n// CHECK:STDOUT:   %E.loc9_14.2 => constants.%E\n// CHECK:STDOUT:   %DD.loc9_28.2 => constants.%DD.a29\n// CHECK:STDOUT:   %Z.impl_witness.loc9_35.2 => constants.%Z.impl_witness.437\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Z.facet.dc0) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC(constants.%D) {\n// CHECK:STDOUT:   %D.loc11_10.1 => constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC(constants.%Z.facet.892) {\n// CHECK:STDOUT:   %D.loc11_10.1 => constants.%Z.facet.892\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC.as.Z.impl(constants.%E) {\n// CHECK:STDOUT:   %E.loc12_14.2 => constants.%E\n// CHECK:STDOUT:   %DD.loc12_31.2 => constants.%DD.a29\n// CHECK:STDOUT:   %.loc12_32.2 => constants.%.bf4\n// CHECK:STDOUT:   %Z.lookup_impl_witness => constants.%Z.lookup_impl_witness\n// CHECK:STDOUT:   %Z.facet.loc12_32.2 => constants.%Z.facet.892\n// CHECK:STDOUT:   %CC.loc12_32.2 => constants.%CC.4e1\n// CHECK:STDOUT:   %Z.impl_witness.loc12_39.2 => constants.%Z.impl_witness.40e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Z.facet.b7b) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @DD(constants.%EE) {\n// CHECK:STDOUT:   %E.loc8_10.1 => constants.%EE\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @DD.as.Z.impl(constants.%EE) {\n// CHECK:STDOUT:   %E.loc9_14.2 => constants.%EE\n// CHECK:STDOUT:   %DD.loc9_28.2 => constants.%DD.2e1\n// CHECK:STDOUT:   %Z.impl_witness.loc9_35.2 => constants.%Z.impl_witness.8a3\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC(constants.%Z.facet.74c) {\n// CHECK:STDOUT:   %D.loc11_10.1 => constants.%Z.facet.74c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC.as.Z.impl(constants.%EE) {\n// CHECK:STDOUT:   %E.loc12_14.2 => constants.%EE\n// CHECK:STDOUT:   %DD.loc12_31.2 => constants.%DD.2e1\n// CHECK:STDOUT:   %.loc12_32.2 => constants.%.36d\n// CHECK:STDOUT:   %Z.lookup_impl_witness => constants.%Z.impl_witness.8a3\n// CHECK:STDOUT:   %Z.facet.loc12_32.2 => constants.%Z.facet.74c\n// CHECK:STDOUT:   %CC.loc12_32.2 => constants.%CC.b19\n// CHECK:STDOUT:   %Z.impl_witness.loc12_39.2 => constants.%Z.impl_witness.cb4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/deduce_nested_facet_value.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/deduce_nested_facet_value.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/deduce_nested_facet_value.carbon\n\n// --- deduce_nested_facet_value.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Y {}\ninterface W {}\n\n// DD implements both Y and W.\nclass DD {}\nimpl DD as Y {}\nimpl DD as W {}\n\n// CC requires D to implement Y.\nclass CC(D:! Y) {}\n\ninterface Z {}\n\n// The `D` interface provides `Y` but not `W`, so we need to see that the\n// parameter to `CC` is `DD` which provides `Y & W`, not just a FacetValue\n// abstractly providing `Y.\nimpl forall [E:! Y & W] CC(E) as Z {}\n\nfn F() {\n  (CC(DD)) as Z;\n}\n\n// CHECK:STDOUT: --- deduce_nested_facet_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Y.type: type = facet_type <@Y> [concrete]\n// CHECK:STDOUT:   %Self.162: %Y.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %W.type: type = facet_type <@W> [concrete]\n// CHECK:STDOUT:   %Self.62a: %W.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %DD: type = class_type @DD [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Y.impl_witness: <witness> = impl_witness @DD.as.Y.impl.%Y.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Y.facet.215: %Y.type = facet_value %DD, (%Y.impl_witness) [concrete]\n// CHECK:STDOUT:   %W.impl_witness: <witness> = impl_witness @DD.as.W.impl.%W.impl_witness_table [concrete]\n// CHECK:STDOUT:   %W.facet: %W.type = facet_value %DD, (%W.impl_witness) [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.95b: type = pattern_type %Y.type [concrete]\n// CHECK:STDOUT:   %D: %Y.type = symbolic_binding D, 0 [symbolic]\n// CHECK:STDOUT:   %CC.type: type = generic_class_type @CC [concrete]\n// CHECK:STDOUT:   %CC.generic: %CC.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CC.fe5: type = class_type @CC, @CC(%D) [symbolic]\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]\n// CHECK:STDOUT:   %Self.c59: %Z.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %BitAndWith.type.f2e: type = generic_interface_type @BitAndWith [concrete]\n// CHECK:STDOUT:   %BitAndWith.generic: %BitAndWith.type.f2e = struct_value () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.b10: type = facet_type <@BitAndWith, @BitAndWith(type)> [concrete]\n// CHECK:STDOUT:   %BitAndWith.impl_witness: <witness> = impl_witness imports.%BitAndWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %BitAndWith.facet: %BitAndWith.type.b10 = facet_value type, (%BitAndWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %BitAndWith.WithSelf.Op.type.4bd: type = fn_type @BitAndWith.WithSelf.Op, @BitAndWith.WithSelf(type, %BitAndWith.facet) [concrete]\n// CHECK:STDOUT:   %.d15: type = fn_type_with_self_type %BitAndWith.WithSelf.Op.type.4bd, %BitAndWith.facet [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.type: type = fn_type @type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op: %type.as.BitAndWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound: <bound method> = bound_method %Y.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type: type = facet_type <@Y & @W> [concrete]\n// CHECK:STDOUT:   %pattern_type.935: type = pattern_type %facet_type [concrete]\n// CHECK:STDOUT:   %E: %facet_type = symbolic_binding E, 0 [symbolic]\n// CHECK:STDOUT:   %E.binding.as_type: type = symbolic_binding_type E, 0, %E [symbolic]\n// CHECK:STDOUT:   %Y.lookup_impl_witness: <witness> = lookup_impl_witness %E, @Y [symbolic]\n// CHECK:STDOUT:   %Y.facet.9df: %Y.type = facet_value %E.binding.as_type, (%Y.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %CC.dc2: type = class_type @CC, @CC(%Y.facet.9df) [symbolic]\n// CHECK:STDOUT:   %Z.impl_witness.506: <witness> = impl_witness @CC.as.Z.impl.%Z.impl_witness_table, @CC.as.Z.impl(%E) [symbolic]\n// CHECK:STDOUT:   %Z.facet.8c4: %Z.type = facet_value %CC.dc2, (%Z.impl_witness.506) [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CC.062: type = class_type @CC, @CC(%Y.facet.215) [concrete]\n// CHECK:STDOUT:   %facet_value: %facet_type = facet_value %DD, (%Y.impl_witness, %W.impl_witness) [concrete]\n// CHECK:STDOUT:   %Z.impl_witness.c39: <witness> = impl_witness @CC.as.Z.impl.%Z.impl_witness_table, @CC.as.Z.impl(%facet_value) [concrete]\n// CHECK:STDOUT:   %Z.facet.d22: %Z.type = facet_value %CC.062, (%Z.impl_witness.c39) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .BitAndWith = %Core.BitAndWith\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.BitAndWith: %BitAndWith.type.f2e = import_ref Core//prelude/parts/as, BitAndWith, loaded [concrete = constants.%BitAndWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.8d3: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:   %BitAndWith.impl_witness_table = impl_witness_table (%Core.import_ref.8d3), @type.as.BitAndWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Y = %Y.decl\n// CHECK:STDOUT:     .W = %W.decl\n// CHECK:STDOUT:     .DD = %DD.decl\n// CHECK:STDOUT:     .CC = %CC.decl\n// CHECK:STDOUT:     .Z = %Z.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Y.decl: type = interface_decl @Y [concrete = constants.%Y.type] {} {}\n// CHECK:STDOUT:   %W.decl: type = interface_decl @W [concrete = constants.%W.type] {} {}\n// CHECK:STDOUT:   %DD.decl: type = class_decl @DD [concrete = constants.%DD] {} {}\n// CHECK:STDOUT:   impl_decl @DD.as.Y.impl [concrete] {} {\n// CHECK:STDOUT:     %DD.ref: type = name_ref DD, file.%DD.decl [concrete = constants.%DD]\n// CHECK:STDOUT:     %Y.ref: type = name_ref Y, file.%Y.decl [concrete = constants.%Y.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @DD.as.W.impl [concrete] {} {\n// CHECK:STDOUT:     %DD.ref: type = name_ref DD, file.%DD.decl [concrete = constants.%DD]\n// CHECK:STDOUT:     %W.ref: type = name_ref W, file.%W.decl [concrete = constants.%W.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CC.decl: %CC.type = class_decl @CC [concrete = constants.%CC.generic] {\n// CHECK:STDOUT:     %D.patt: %pattern_type.95b = symbolic_binding_pattern D, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc12: type = splice_block %Y.ref [concrete = constants.%Y.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Y.ref: type = name_ref Y, file.%Y.decl [concrete = constants.%Y.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %D.loc12_10.2: %Y.type = symbolic_binding D, 0 [symbolic = %D.loc12_10.1 (constants.%D)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Z.decl: type = interface_decl @Z [concrete = constants.%Z.type] {} {}\n// CHECK:STDOUT:   impl_decl @CC.as.Z.impl [concrete] {\n// CHECK:STDOUT:     %E.patt: %pattern_type.935 = symbolic_binding_pattern E, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %CC.ref: %CC.type = name_ref CC, file.%CC.decl [concrete = constants.%CC.generic]\n// CHECK:STDOUT:     %E.ref: %facet_type = name_ref E, %E.loc19_14.1 [symbolic = %E.loc19_14.2 (constants.%E)]\n// CHECK:STDOUT:     %E.as_type: type = facet_access_type %E.ref [symbolic = %E.binding.as_type (constants.%E.binding.as_type)]\n// CHECK:STDOUT:     %Y.facet.loc19_29.1: %Y.type = facet_value %E.as_type, (constants.%Y.lookup_impl_witness) [symbolic = %Y.facet.loc19_29.2 (constants.%Y.facet.9df)]\n// CHECK:STDOUT:     %.loc19_29: %Y.type = converted %E.ref, %Y.facet.loc19_29.1 [symbolic = %Y.facet.loc19_29.2 (constants.%Y.facet.9df)]\n// CHECK:STDOUT:     %CC.loc19_29.1: type = class_type @CC, @CC(constants.%Y.facet.9df) [symbolic = %CC.loc19_29.2 (constants.%CC.dc2)]\n// CHECK:STDOUT:     %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:     %.loc19_20.1: type = splice_block %.loc19_20.3 [concrete = constants.%facet_type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Y.ref: type = name_ref Y, file.%Y.decl [concrete = constants.%Y.type]\n// CHECK:STDOUT:       %W.ref: type = name_ref W, file.%W.decl [concrete = constants.%W.type]\n// CHECK:STDOUT:       %impl.elem0: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:       %bound_method: <bound method> = bound_method %Y.ref, %impl.elem0 [concrete = constants.%type.as.BitAndWith.impl.Op.bound]\n// CHECK:STDOUT:       %type.as.BitAndWith.impl.Op.call: init type = call %bound_method(%Y.ref, %W.ref) [concrete = constants.%facet_type]\n// CHECK:STDOUT:       %.loc19_20.2: type = value_of_initializer %type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type]\n// CHECK:STDOUT:       %.loc19_20.3: type = converted %type.as.BitAndWith.impl.Op.call, %.loc19_20.2 [concrete = constants.%facet_type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %E.loc19_14.1: %facet_type = symbolic_binding E, 0 [symbolic = %E.loc19_14.2 (constants.%E)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Y {\n// CHECK:STDOUT:   %Self: %Y.type = symbolic_binding Self, 0 [symbolic = constants.%Self.162]\n// CHECK:STDOUT:   %Y.WithSelf.decl = interface_with_self_decl @Y [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @W {\n// CHECK:STDOUT:   %Self: %W.type = symbolic_binding Self, 0 [symbolic = constants.%Self.62a]\n// CHECK:STDOUT:   %W.WithSelf.decl = interface_with_self_decl @W [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Z {\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c59]\n// CHECK:STDOUT:   %Z.WithSelf.decl = interface_with_self_decl @Z [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @DD.as.Y.impl: %DD.ref as %Y.ref {\n// CHECK:STDOUT:   %Y.impl_witness_table = impl_witness_table (), @DD.as.Y.impl [concrete]\n// CHECK:STDOUT:   %Y.impl_witness: <witness> = impl_witness %Y.impl_witness_table [concrete = constants.%Y.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Y.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @DD.as.W.impl: %DD.ref as %W.ref {\n// CHECK:STDOUT:   %W.impl_witness_table = impl_witness_table (), @DD.as.W.impl [concrete]\n// CHECK:STDOUT:   %W.impl_witness: <witness> = impl_witness %W.impl_witness_table [concrete = constants.%W.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %W.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @CC.as.Z.impl(%E.loc19_14.1: %facet_type) {\n// CHECK:STDOUT:   %E.loc19_14.2: %facet_type = symbolic_binding E, 0 [symbolic = %E.loc19_14.2 (constants.%E)]\n// CHECK:STDOUT:   %E.binding.as_type: type = symbolic_binding_type E, 0, %E.loc19_14.2 [symbolic = %E.binding.as_type (constants.%E.binding.as_type)]\n// CHECK:STDOUT:   %Y.lookup_impl_witness: <witness> = lookup_impl_witness %E.loc19_14.2, @Y [symbolic = %Y.lookup_impl_witness (constants.%Y.lookup_impl_witness)]\n// CHECK:STDOUT:   %Y.facet.loc19_29.2: %Y.type = facet_value %E.binding.as_type, (%Y.lookup_impl_witness) [symbolic = %Y.facet.loc19_29.2 (constants.%Y.facet.9df)]\n// CHECK:STDOUT:   %CC.loc19_29.2: type = class_type @CC, @CC(%Y.facet.loc19_29.2) [symbolic = %CC.loc19_29.2 (constants.%CC.dc2)]\n// CHECK:STDOUT:   %Z.impl_witness.loc19_36.2: <witness> = impl_witness %Z.impl_witness_table, @CC.as.Z.impl(%E.loc19_14.2) [symbolic = %Z.impl_witness.loc19_36.2 (constants.%Z.impl_witness.506)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %CC.loc19_29.1 as %Z.ref {\n// CHECK:STDOUT:     %Z.impl_witness_table = impl_witness_table (), @CC.as.Z.impl [concrete]\n// CHECK:STDOUT:     %Z.impl_witness.loc19_36.1: <witness> = impl_witness %Z.impl_witness_table, @CC.as.Z.impl(constants.%E) [symbolic = %Z.impl_witness.loc19_36.2 (constants.%Z.impl_witness.506)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Z.impl_witness.loc19_36.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @DD {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%DD\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @CC(%D.loc12_10.2: %Y.type) {\n// CHECK:STDOUT:   %D.loc12_10.1: %Y.type = symbolic_binding D, 0 [symbolic = %D.loc12_10.1 (constants.%D)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%CC.fe5\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %CC.ref: %CC.type = name_ref CC, file.%CC.decl [concrete = constants.%CC.generic]\n// CHECK:STDOUT:   %DD.ref: type = name_ref DD, file.%DD.decl [concrete = constants.%DD]\n// CHECK:STDOUT:   %Y.facet: %Y.type = facet_value %DD.ref, (constants.%Y.impl_witness) [concrete = constants.%Y.facet.215]\n// CHECK:STDOUT:   %.loc22_9: %Y.type = converted %DD.ref, %Y.facet [concrete = constants.%Y.facet.215]\n// CHECK:STDOUT:   %CC: type = class_type @CC, @CC(constants.%Y.facet.215) [concrete = constants.%CC.062]\n// CHECK:STDOUT:   %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %CC, (constants.%Z.impl_witness.c39) [concrete = constants.%Z.facet.d22]\n// CHECK:STDOUT:   %.loc22_12: %Z.type = converted %CC, %Z.facet [concrete = constants.%Z.facet.d22]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Y.WithSelf(constants.%Self.162) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @W.WithSelf(constants.%Self.62a) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Y.WithSelf(constants.%Y.facet.215) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @W.WithSelf(constants.%W.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC(constants.%D) {\n// CHECK:STDOUT:   %D.loc12_10.1 => constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Self.c59) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC(constants.%Y.facet.9df) {\n// CHECK:STDOUT:   %D.loc12_10.1 => constants.%Y.facet.9df\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC.as.Z.impl(constants.%E) {\n// CHECK:STDOUT:   %E.loc19_14.2 => constants.%E\n// CHECK:STDOUT:   %E.binding.as_type => constants.%E.binding.as_type\n// CHECK:STDOUT:   %Y.lookup_impl_witness => constants.%Y.lookup_impl_witness\n// CHECK:STDOUT:   %Y.facet.loc19_29.2 => constants.%Y.facet.9df\n// CHECK:STDOUT:   %CC.loc19_29.2 => constants.%CC.dc2\n// CHECK:STDOUT:   %Z.impl_witness.loc19_36.2 => constants.%Z.impl_witness.506\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Z.facet.8c4) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC(constants.%Y.facet.215) {\n// CHECK:STDOUT:   %D.loc12_10.1 => constants.%Y.facet.215\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @CC.as.Z.impl(constants.%facet_value) {\n// CHECK:STDOUT:   %E.loc19_14.2 => constants.%facet_value\n// CHECK:STDOUT:   %E.binding.as_type => constants.%DD\n// CHECK:STDOUT:   %Y.lookup_impl_witness => constants.%Y.impl_witness\n// CHECK:STDOUT:   %Y.facet.loc19_29.2 => constants.%Y.facet.215\n// CHECK:STDOUT:   %CC.loc19_29.2 => constants.%CC.062\n// CHECK:STDOUT:   %Z.impl_witness.loc19_36.2 => constants.%Z.impl_witness.c39\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/fail_deduce_imported_function.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/fail_deduce_imported_function.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/fail_deduce_imported_function.carbon\n\n// --- lib.carbon\npackage Lib;\n\ninterface Z {}\nfn A[T:! Z](unused x: {.a: T}) {}\n\n// --- fail_deduce_imported_function.carbon\n\nimport Lib;\n\nfn A[T:! Lib.Z](unused x: {.a: T}) {}\n\nfn B() {\n  // CHECK:STDERR: fail_deduce_imported_function.carbon:[[@LINE+7]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete]\n  // CHECK:STDERR:   A({.b = {}});\n  // CHECK:STDERR:   ^~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduce_imported_function.carbon:[[@LINE-6]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn A[T:! Lib.Z](unused x: {.a: T}) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  A({.b = {}});\n\n  // CHECK:STDERR: fail_deduce_imported_function.carbon:[[@LINE+8]]:3: error: cannot deduce value for generic parameter `T` [DeductionIncomplete]\n  // CHECK:STDERR:   Lib.A({.b = {}});\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_deduce_imported_function.carbon:[[@LINE-17]]:1: in import [InImport]\n  // CHECK:STDERR: lib.carbon:4:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn A[T:! Z](unused x: {.a: T}) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Lib.A({.b = {}});\n}\n\n// CHECK:STDOUT: --- lib.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.473: type = pattern_type %Z.type [concrete]\n// CHECK:STDOUT:   %T: %Z.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %T.binding.as_type} [symbolic]\n// CHECK:STDOUT:   %pattern_type.3fc: type = pattern_type %struct_type.a [symbolic]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.a [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Z = %Z.decl\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Z.decl: type = interface_decl @Z [concrete = constants.%Z.type] {} {}\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.473 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @A.%pattern_type (%pattern_type.3fc) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @A.%pattern_type (%pattern_type.3fc) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_10: type = splice_block %Z.ref [concrete = constants.%Z.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_6.2: %Z.type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @A.%struct_type.a.loc4_29.1 (%struct_type.a) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_29: type = splice_block %struct_type.a.loc4_29.2 [symbolic = %struct_type.a.loc4_29.1 (constants.%struct_type.a)] {\n// CHECK:STDOUT:       %T.ref: %Z.type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc4_28: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %struct_type.a.loc4_29.2: type = struct_type {.a: @A.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.a.loc4_29.1 (constants.%struct_type.a)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @A.%struct_type.a.loc4_29.1 (%struct_type.a) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Z {\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Z.WithSelf.decl = interface_with_self_decl @Z [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @A(%T.loc4_6.2: %Z.type) {\n// CHECK:STDOUT:   %T.loc4_6.1: %Z.type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc4_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %struct_type.a.loc4_29.1: type = struct_type {.a: @A.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.a.loc4_29.1 (constants.%struct_type.a)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %struct_type.a.loc4_29.1 [symbolic = %pattern_type (constants.%pattern_type.3fc)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.a.loc4_29.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @A.%struct_type.a.loc4_29.1 (%struct_type.a)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %struct_type.a.loc4_29.1 => constants.%struct_type.a\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.3fc\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_deduce_imported_function.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.e5e: type = pattern_type %Z.type [concrete]\n// CHECK:STDOUT:   %T: %Z.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %T.binding.as_type} [symbolic]\n// CHECK:STDOUT:   %pattern_type.857: type = pattern_type %struct_type.a [symbolic]\n// CHECK:STDOUT:   %A.type.816: type = fn_type @A.loc4 [concrete]\n// CHECK:STDOUT:   %A.8ae: %A.type.816 = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.a [symbolic]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.b: type = struct_type {.b: %empty_struct_type} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.b = struct_value (%empty_struct) [concrete]\n// CHECK:STDOUT:   %A.type.fad: type = fn_type @A.1 [concrete]\n// CHECK:STDOUT:   %A.7a0: %A.type.fad = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Lib: <namespace> = namespace file.%Lib.import, [concrete] {\n// CHECK:STDOUT:     .Z = %Lib.Z\n// CHECK:STDOUT:     .A = %Lib.A\n// CHECK:STDOUT:     import Lib//default\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Lib.Z: type = import_ref Lib//default, Z, loaded [concrete = constants.%Z.type]\n// CHECK:STDOUT:   %Lib.import_ref.7bd = import_ref Lib//default, loc3_13, unloaded\n// CHECK:STDOUT:   %Lib.A: %A.type.fad = import_ref Lib//default, A, loaded [concrete = constants.%A.7a0]\n// CHECK:STDOUT:   %Lib.import_ref.4c8: %Z.type = import_ref Lib//default, loc4_6, loaded [symbolic = @A.1.%T (constants.%T)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Lib = imports.%Lib\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Lib.import = import Lib\n// CHECK:STDOUT:   %A.decl: %A.type.816 = fn_decl @A.loc4 [concrete = constants.%A.8ae] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.e5e = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @A.loc4.%pattern_type (%pattern_type.857) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @A.loc4.%pattern_type (%pattern_type.857) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13: type = splice_block %Z.ref [concrete = constants.%Z.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Lib.ref: <namespace> = name_ref Lib, imports.%Lib [concrete = imports.%Lib]\n// CHECK:STDOUT:       %Z.ref: type = name_ref Z, imports.%Lib.Z [concrete = constants.%Z.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_6.2: %Z.type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @A.loc4.%struct_type.a.loc4_33.1 (%struct_type.a) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_33: type = splice_block %struct_type.a.loc4_33.2 [symbolic = %struct_type.a.loc4_33.1 (constants.%struct_type.a)] {\n// CHECK:STDOUT:       %T.ref: %Z.type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc4_32: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %struct_type.a.loc4_33.2: type = struct_type {.a: @A.loc4.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.a.loc4_33.1 (constants.%struct_type.a)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @A.loc4.%struct_type.a.loc4_33.1 (%struct_type.a) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Z [from \"lib.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Lib.import_ref.7bd\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @A.loc4(%T.loc4_6.2: %Z.type) {\n// CHECK:STDOUT:   %T.loc4_6.1: %Z.type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc4_6.1 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %struct_type.a.loc4_33.1: type = struct_type {.a: @A.loc4.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.a.loc4_33.1 (constants.%struct_type.a)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %struct_type.a.loc4_33.1 [symbolic = %pattern_type (constants.%pattern_type.857)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.a.loc4_33.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @A.loc4.%struct_type.a.loc4_33.1 (%struct_type.a)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %A.ref.loc14: %A.type.816 = name_ref A, file.%A.decl [concrete = constants.%A.8ae]\n// CHECK:STDOUT:   %.loc14_12: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc14_13: %struct_type.b = struct_literal (%.loc14_12) [concrete = constants.%struct]\n// CHECK:STDOUT:   %Lib.ref: <namespace> = name_ref Lib, imports.%Lib [concrete = imports.%Lib]\n// CHECK:STDOUT:   %A.ref.loc24: %A.type.fad = name_ref A, imports.%Lib.A [concrete = constants.%A.7a0]\n// CHECK:STDOUT:   %.loc24_16: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc24_17: %struct_type.b = struct_literal (%.loc24_16) [concrete = constants.%struct]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @A.1(imports.%Lib.import_ref.4c8: %Z.type) [from \"lib.carbon\"] {\n// CHECK:STDOUT:   %T: %Z.type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: @A.1.%T.binding.as_type (%T.binding.as_type)} [symbolic = %struct_type.a (constants.%struct_type.a)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %struct_type.a [symbolic = %pattern_type (constants.%pattern_type.857)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %struct_type.a [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.loc4(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %struct_type.a.loc4_33.1 => constants.%struct_type.a\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.857\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.1(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %struct_type.a => constants.%struct_type.a\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.857\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/fail_type_param_mismatch.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/fail_type_param_mismatch.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/fail_type_param_mismatch.carbon\n\nfn F(T:! type, U:! type) {\n  var p: T*;\n  // CHECK:STDERR: fail_type_param_mismatch.carbon:[[@LINE+7]]:21: error: cannot implicitly convert expression of type `T` to `U` [ConversionFailure]\n  // CHECK:STDERR:   let unused n: U = *p;\n  // CHECK:STDERR:                     ^~\n  // CHECK:STDERR: fail_type_param_mismatch.carbon:[[@LINE+4]]:21: note: type `T` does not implement interface `Core.ImplicitAs(U)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let unused n: U = *p;\n  // CHECK:STDERR:                     ^~\n  // CHECK:STDERR:\n  let unused n: U = *p;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/forward_decl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/forward_decl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/forward_decl.carbon\n\nfn F(T:! type);\n\n// CHECK:STDOUT: --- forward_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_10.1: type = splice_block %.loc15_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_6.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc15_6.2: type) {\n// CHECK:STDOUT:   %T.loc15_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_6.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_6.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/import_specific.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/import_specific.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/import_specific.carbon\n\n// --- library.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(unused T:! type) {\n}\n\nfn G(T:! type) {\n  F(T);\n}\n\n// --- user.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"library\";\n\nclass C {}\n\nfn H() {\n  // TODO: We currently crash when importing G if we don't force F to be imported first.\n  F(C);\n\n  G(C);\n}\n\n// CHECK:STDOUT: --- library.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67db0b.1: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T.67db0b.2: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%T.67db0b.2) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_10.1: type = splice_block %.loc7_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T.67db0b.2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%T.loc7_6.2: type) {\n// CHECK:STDOUT:   %T.loc7_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_6.1 (constants.%T.67db0b.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %F.specific_fn.loc8_3.2: <specific function> = specific_function constants.%F, @F(%T.loc7_6.1) [symbolic = %F.specific_fn.loc8_3.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc7_6.2 [symbolic = %T.loc7_6.1 (constants.%T.67db0b.2)]\n// CHECK:STDOUT:     %F.specific_fn.loc8_3.1: <specific function> = specific_function %F.ref, @F(constants.%T.67db0b.2) [symbolic = %F.specific_fn.loc8_3.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:     %F.call: init %empty_tuple.type = call %F.specific_fn.loc8_3.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67db0b.1) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T.67db0b.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%T.67db0b.2) {\n// CHECK:STDOUT:   %T.loc7_6.1 => constants.%T.67db0b.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67db0b.2) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T.67db0b.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- user.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T.67db0b.1: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.540: <specific function> = specific_function %F, @F(%C) [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %T.67db0b.2: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.643: <specific function> = specific_function %F, @F(%T.67db0b.2) [symbolic]\n// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G, @G(%C) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.F: %F.type = import_ref Main//library, F, loaded [concrete = constants.%F]\n// CHECK:STDOUT:   %Main.G: %G.type = import_ref Main//library, G, loaded [concrete = constants.%G]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.1: type = import_ref Main//library, loc4_13, loaded [symbolic = @F.%T (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//library, loc7_6, loaded [symbolic = @G.%T (constants.%T.67db0b.2)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = imports.%Main.F\n// CHECK:STDOUT:     .G = imports.%Main.G\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .H = %H.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @H() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, imports.%Main.F [concrete = constants.%F]\n// CHECK:STDOUT:   %C.ref.loc10: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.540]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn()\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, imports.%Main.G [concrete = constants.%G]\n// CHECK:STDOUT:   %C.ref.loc12: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G.ref, @G(constants.%C) [concrete = constants.%G.specific_fn]\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.specific_fn()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(imports.%Main.import_ref.b3bc94.1: type) [from \"library.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T.67db0b.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(imports.%Main.import_ref.b3bc94.2: type) [from \"library.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T.67db0b.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function constants.%F, @F(%T) [symbolic = %F.specific_fn (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67db0b.1) {\n// CHECK:STDOUT:   %T => constants.%T.67db0b.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C) {\n// CHECK:STDOUT:   %T => constants.%C\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67db0b.2) {\n// CHECK:STDOUT:   %T => constants.%T.67db0b.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%T.67db0b.2) {\n// CHECK:STDOUT:   %T => constants.%T.67db0b.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%C) {\n// CHECK:STDOUT:   %T => constants.%C\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %F.specific_fn => constants.%F.specific_fn.540\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/indirect_generic_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/indirect_generic_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/indirect_generic_type.carbon\n\n// --- pointer_to_pointer.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(T:! type, p: T**) -> T* {\n  //@dump-sem-ir-begin\n  return *p;\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- pointer_to_pointer.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T.67d [symbolic]\n// CHECK:STDOUT:   %ptr.125: type = ptr_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %pattern_type.8bb: type = pattern_type %ptr.125 [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e8f, (%Copy.lookup_impl_witness.2e6) [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]\n// CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet [symbolic]\n// CHECK:STDOUT:   %impl.elem0.1c7: %.299 = impl_witness_access %Copy.lookup_impl_witness.2e6, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.366: <specific function> = specific_impl_function %impl.elem0.1c7, @Copy.WithSelf.Op(%Copy.facet) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_6.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %.loc6_10.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc4_6.1) [symbolic = %.loc6_10.3 (constants.%.2f2)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc4_20.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc4_20.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]\n// CHECK:STDOUT:   %.loc6_10.4: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc6_10.4 (constants.%.299)]\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2: @F.%.loc6_10.4 (%.299) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.1c7)]\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2: <specific function> = specific_impl_function %impl.elem0.loc6_10.2, @Copy.WithSelf.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.366)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc4_21.1 (%ptr.125)) -> out %return.param: @F.%ptr.loc4_20.1 (%ptr.e8f) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %p.ref: @F.%ptr.loc4_21.1 (%ptr.125) = name_ref p, %p\n// CHECK:STDOUT:     %.loc6_10.1: ref @F.%ptr.loc4_20.1 (%ptr.e8f) = deref %p.ref\n// CHECK:STDOUT:     %.loc6_10.2: @F.%ptr.loc4_20.1 (%ptr.e8f) = acquire_value %.loc6_10.1\n// CHECK:STDOUT:     %impl.elem0.loc6_10.1: @F.%.loc6_10.4 (%.299) = impl_witness_access constants.%Copy.lookup_impl_witness.2e6, element0 [symbolic = %impl.elem0.loc6_10.2 (constants.%impl.elem0.1c7)]\n// CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %.loc6_10.2, %impl.elem0.loc6_10.1\n// CHECK:STDOUT:     %specific_impl_fn.loc6_10.1: <specific function> = specific_impl_function %impl.elem0.loc6_10.1, @Copy.WithSelf.Op(constants.%Copy.facet) [symbolic = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.366)]\n// CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %.loc6_10.2, %specific_impl_fn.loc6_10.1\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @F.%ptr.loc4_20.1 (%ptr.e8f) = call %bound_method.loc6_10.2(%.loc6_10.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T.67d\n// CHECK:STDOUT:   %ptr.loc4_20.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %ptr.loc4_21.1 => constants.%ptr.125\n// CHECK:STDOUT:   %pattern_type.loc4_16 => constants.%pattern_type.8bb\n// CHECK:STDOUT:   %.loc4_28.1 => constants.%.cb6\n// CHECK:STDOUT:   %pattern_type.loc4_24 => constants.%pattern_type.4f4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/param_in_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/param_in_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/param_in_type.carbon\n\nfn F(N:! i32, a: array(i32, N)*);\n\n// CHECK:STDOUT: --- param_in_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %N.5de: %i32 = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.139: type = facet_type <@ImplicitAs, @ImplicitAs(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %From: Core.IntLiteral = symbolic_binding From, 0 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.2ed: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%From) [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.d29: %Int.as.ImplicitAs.impl.Convert.type.2ed = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.640: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.ea2, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.type.240: type = fn_type @Int.as.ImplicitAs.impl.Convert, @Int.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.dd4: %Int.as.ImplicitAs.impl.Convert.type.240 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.139 = facet_value %i32, (%ImplicitAs.impl_witness.640) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.462: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(Core.IntLiteral, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.0a7: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.462, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.dd4 [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Int.as.ImplicitAs.impl.Convert.dd4, @Int.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %N.5de, %Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call: init Core.IntLiteral = call %bound_method(%N.5de) [symbolic]\n// CHECK:STDOUT:   %array_type: type = array_type %Int.as.ImplicitAs.impl.Convert.call, %i32 [symbolic]\n// CHECK:STDOUT:   %ptr: type = ptr_type %array_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.bb8: type = pattern_type %ptr [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.0bc: @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert.type (%Int.as.ImplicitAs.impl.Convert.type.2ed) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.ImplicitAs.impl.%Int.as.ImplicitAs.impl.Convert (constants.%Int.as.ImplicitAs.impl.Convert.d29)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.ea2 = impl_witness_table (%Core.import_ref.0bc), @Int.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.7ce = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:     %a.patt: @F.%pattern_type (%pattern_type.bb8) = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: @F.%pattern_type (%pattern_type.bb8) = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_10: type = splice_block %i32.loc15_10 [concrete = constants.%i32] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %i32.loc15_10: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc15_6.2: %i32 = symbolic_binding N, 0 [symbolic = %N.loc15_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:     %a.param: @F.%ptr.loc15_31.1 (%ptr) = value_param call_param0\n// CHECK:STDOUT:     %.loc15_31: type = splice_block %ptr.loc15_31.2 [symbolic = %ptr.loc15_31.1 (constants.%ptr)] {\n// CHECK:STDOUT:       %i32.loc15_24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %N.ref: %i32 = name_ref N, %N.loc15_6.2 [symbolic = %N.loc15_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:       %impl.elem0: %.0a7 = impl_witness_access constants.%ImplicitAs.impl_witness.640, element0 [concrete = constants.%Int.as.ImplicitAs.impl.Convert.dd4]\n// CHECK:STDOUT:       %bound_method.loc15_29.2: <bound method> = bound_method %N.ref, %impl.elem0 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:       %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Int.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:       %bound_method.loc15_29.3: <bound method> = bound_method %N.ref, %specific_fn [symbolic = %bound_method.loc15_29.1 (constants.%bound_method)]\n// CHECK:STDOUT:       %Int.as.ImplicitAs.impl.Convert.call.loc15_29.2: init Core.IntLiteral = call %bound_method.loc15_29.3(%N.ref) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc15_29.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %.loc15_29.1: Core.IntLiteral = value_of_initializer %Int.as.ImplicitAs.impl.Convert.call.loc15_29.2 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc15_29.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %.loc15_29.2: Core.IntLiteral = converted %N.ref, %.loc15_29.1 [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc15_29.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:       %array_type.loc15_30.2: type = array_type %.loc15_29.2, %i32.loc15_24 [symbolic = %array_type.loc15_30.1 (constants.%array_type)]\n// CHECK:STDOUT:       %ptr.loc15_31.2: type = ptr_type %array_type.loc15_30.2 [symbolic = %ptr.loc15_31.1 (constants.%ptr)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %a: @F.%ptr.loc15_31.1 (%ptr) = value_binding a, %a.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%N.loc15_6.2: %i32) {\n// CHECK:STDOUT:   %N.loc15_6.1: %i32 = symbolic_binding N, 0 [symbolic = %N.loc15_6.1 (constants.%N.5de)]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %N.loc15_6.1, constants.%Int.as.ImplicitAs.impl.Convert.dd4 [symbolic = %Int.as.ImplicitAs.impl.Convert.bound (constants.%Int.as.ImplicitAs.impl.Convert.bound)]\n// CHECK:STDOUT:   %bound_method.loc15_29.1: <bound method> = bound_method %N.loc15_6.1, constants.%Int.as.ImplicitAs.impl.Convert.specific_fn [symbolic = %bound_method.loc15_29.1 (constants.%bound_method)]\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call.loc15_29.1: init Core.IntLiteral = call %bound_method.loc15_29.1(%N.loc15_6.1) [symbolic = %Int.as.ImplicitAs.impl.Convert.call.loc15_29.1 (constants.%Int.as.ImplicitAs.impl.Convert.call)]\n// CHECK:STDOUT:   %array_type.loc15_30.1: type = array_type %Int.as.ImplicitAs.impl.Convert.call.loc15_29.1, constants.%i32 [symbolic = %array_type.loc15_30.1 (constants.%array_type)]\n// CHECK:STDOUT:   %ptr.loc15_31.1: type = ptr_type %array_type.loc15_30.1 [symbolic = %ptr.loc15_31.1 (constants.%ptr)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc15_31.1 [symbolic = %pattern_type (constants.%pattern_type.bb8)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%a.param: @F.%ptr.loc15_31.1 (%ptr));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%N.5de) {\n// CHECK:STDOUT:   %N.loc15_6.1 => constants.%N.5de\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.bound => constants.%Int.as.ImplicitAs.impl.Convert.bound\n// CHECK:STDOUT:   %bound_method.loc15_29.1 => constants.%bound_method\n// CHECK:STDOUT:   %Int.as.ImplicitAs.impl.Convert.call.loc15_29.1 => constants.%Int.as.ImplicitAs.impl.Convert.call\n// CHECK:STDOUT:   %array_type.loc15_30.1 => constants.%array_type\n// CHECK:STDOUT:   %ptr.loc15_31.1 => constants.%ptr\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.bb8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/redeclare.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/redeclare.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/redeclare.carbon\n\n// --- redeclare.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(T:! type) -> T*;\n\nfn F(T:! type) -> T* {\n  return F(T);\n}\n\n// --- fail_different_return_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(T:! type, U:! type) -> T*;\n\n// CHECK:STDERR: fail_different_return_type.carbon:[[@LINE+7]]:1: error: function redeclaration differs because return type is `U*` [FunctionRedeclReturnTypeDiffers]\n// CHECK:STDERR: fn F(T:! type, U:! type) -> U* {\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_different_return_type.carbon:[[@LINE-5]]:1: note: previously declared with return type `T*` [FunctionRedeclReturnTypePrevious]\n// CHECK:STDERR: fn F(T:! type, U:! type) -> T*;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(T:! type, U:! type) -> U* {\n  // CHECK:STDERR: fail_different_return_type.carbon:[[@LINE+7]]:10: error: 1 argument passed to function expecting 2 arguments [CallArgCountMismatch]\n  // CHECK:STDERR:   return F(T);\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR: fail_different_return_type.carbon:[[@LINE-13]]:1: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR: fn F(T:! type, U:! type) -> T*;\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return F(T);\n}\n\n// --- fail_reorder.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(T:! type, U:! type) -> T*;\n\n// CHECK:STDERR: fail_reorder.carbon:[[@LINE+7]]:13: error: redeclaration differs at parameter 1 [RedeclParamDiffers]\n// CHECK:STDERR: fn F(unused U:! type, T:! type) -> T* {\n// CHECK:STDERR:             ^\n// CHECK:STDERR: fail_reorder.carbon:[[@LINE-5]]:6: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n// CHECK:STDERR: fn F(T:! type, U:! type) -> T*;\n// CHECK:STDERR:      ^\n// CHECK:STDERR:\nfn F(unused U:! type, T:! type) -> T* {\n  // CHECK:STDERR: fail_reorder.carbon:[[@LINE+7]]:10: error: 1 argument passed to function expecting 2 arguments [CallArgCountMismatch]\n  // CHECK:STDERR:   return F(T);\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR: fail_reorder.carbon:[[@LINE-13]]:1: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR: fn F(T:! type, U:! type) -> T*;\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return F(T);\n}\n\n// --- fail_rename.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(T:! type, U:! type) -> T*;\n\n// CHECK:STDERR: fail_rename.carbon:[[@LINE+7]]:6: error: redeclaration differs at parameter 1 [RedeclParamDiffers]\n// CHECK:STDERR: fn F(U:! type, T:! type) -> U* {\n// CHECK:STDERR:      ^\n// CHECK:STDERR: fail_rename.carbon:[[@LINE-5]]:6: note: previous declaration's corresponding parameter here [RedeclParamPrevious]\n// CHECK:STDERR: fn F(T:! type, U:! type) -> T*;\n// CHECK:STDERR:      ^\n// CHECK:STDERR:\nfn F(U:! type, T:! type) -> U* {\n  // CHECK:STDERR: fail_rename.carbon:[[@LINE+7]]:10: error: 1 argument passed to function expecting 2 arguments [CallArgCountMismatch]\n  // CHECK:STDERR:   return F(T);\n  // CHECK:STDERR:          ^~~~\n  // CHECK:STDERR: fail_rename.carbon:[[@LINE-13]]:1: note: calling function declared here [InCallToEntity]\n  // CHECK:STDERR: fn F(T:! type, U:! type) -> T*;\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  return F(T);\n}\n\n// CHECK:STDOUT: --- redeclare.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr [symbolic]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl.loc4: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type (%pattern_type.4f4) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type (%pattern_type.4f4) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc4: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc4_20.2: type = ptr_type %T.ref.loc4 [symbolic = %ptr.loc4_20.1 (constants.%ptr)]\n// CHECK:STDOUT:     %.loc4_20.2: Core.Form = init_form %ptr.loc4_20.2 [symbolic = %.loc4_20.1 (constants.%.cb6)]\n// CHECK:STDOUT:     %.loc4_10.1: type = splice_block %.loc4_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:     %return.param.loc4: ref @F.%ptr.loc4_20.1 (%ptr) = out_param call_param0\n// CHECK:STDOUT:     %return.loc4: ref @F.%ptr.loc4_20.1 (%ptr) = return_slot %return.param.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc6: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type (%pattern_type.4f4) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type (%pattern_type.4f4) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc6: type = name_ref T, %T.loc6 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc6: type = ptr_type %T.ref.loc6 [symbolic = %ptr.loc4_20.1 (constants.%ptr)]\n// CHECK:STDOUT:     %.loc6_20: Core.Form = init_form %ptr.loc6 [symbolic = %.loc4_20.1 (constants.%.cb6)]\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6: type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:     %return.param.loc6: ref @F.%ptr.loc4_20.1 (%ptr) = out_param call_param0\n// CHECK:STDOUT:     %return.loc6: ref @F.%ptr.loc4_20.1 (%ptr) = return_slot %return.param.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_6.2: type) {\n// CHECK:STDOUT:   %T.loc4_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc4_20.1: type = ptr_type %T.loc4_6.1 [symbolic = %ptr.loc4_20.1 (constants.%ptr)]\n// CHECK:STDOUT:   %.loc4_20.1: Core.Form = init_form %ptr.loc4_20.1 [symbolic = %.loc4_20.1 (constants.%.cb6)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc4_20.1 [symbolic = %pattern_type (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc4_20.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %F.specific_fn.loc7_10.2: <specific function> = specific_function constants.%F, @F(%T.loc4_6.1) [symbolic = %F.specific_fn.loc7_10.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param.loc6: @F.%ptr.loc4_20.1 (%ptr) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl.loc4 [concrete = constants.%F]\n// CHECK:STDOUT:     %T.ref.loc7: type = name_ref T, %T.loc6 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:     %F.specific_fn.loc7_10.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc7_10.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:     %F.call: init @F.%ptr.loc4_20.1 (%ptr) = call %F.specific_fn.loc7_10.1()\n// CHECK:STDOUT:     return %F.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T\n// CHECK:STDOUT:   %ptr.loc4_20.1 => constants.%ptr\n// CHECK:STDOUT:   %.loc4_20.1 => constants.%.cb6\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %F.specific_fn.loc7_10.2 => constants.%F.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_different_return_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %F.type.117dbc.1: type = fn_type @F.loc4 [concrete]\n// CHECK:STDOUT:   %F.d98bd5.1: %F.type.117dbc.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.18e: type = ptr_type %U [symbolic]\n// CHECK:STDOUT:   %.6d8: Core.Form = init_form %ptr.18e [symbolic]\n// CHECK:STDOUT:   %pattern_type.423: type = pattern_type %ptr.18e [symbolic]\n// CHECK:STDOUT:   %F.type.117dbc.2: type = fn_type @F.loc13 [concrete]\n// CHECK:STDOUT:   %F.d98bd5.2: %F.type.117dbc.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.18e [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl.loc4: %F.type.117dbc.1 = fn_decl @F.loc4 [concrete = constants.%F.d98bd5.1] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %return.patt: @F.loc4.%pattern_type (%pattern_type.4f4) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.loc4.%pattern_type (%pattern_type.4f4) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc4_30.2: type = ptr_type %T.ref [symbolic = %ptr.loc4_30.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     %.loc4_30.2: Core.Form = init_form %ptr.loc4_30.2 [symbolic = %.loc4_30.1 (constants.%.cb6)]\n// CHECK:STDOUT:     %.loc4_10.1: type = splice_block %.loc4_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc4_20.1: type = splice_block %.loc4_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc4_16.2: type = symbolic_binding U, 1 [symbolic = %U.loc4_16.1 (constants.%U)]\n// CHECK:STDOUT:     %return.param: ref @F.loc4.%ptr.loc4_30.1 (%ptr.e8f) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @F.loc4.%ptr.loc4_30.1 (%ptr.e8f) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc13: %F.type.117dbc.2 = fn_decl @F.loc13 [concrete = constants.%F.d98bd5.2] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %return.patt: @F.loc13.%pattern_type (%pattern_type.423) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.loc13.%pattern_type (%pattern_type.423) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %U.ref: type = name_ref U, %U.loc13_16.2 [symbolic = %U.loc13_16.1 (constants.%U)]\n// CHECK:STDOUT:     %ptr.loc13_30.2: type = ptr_type %U.ref [symbolic = %ptr.loc13_30.1 (constants.%ptr.18e)]\n// CHECK:STDOUT:     %.loc13_30.2: Core.Form = init_form %ptr.loc13_30.2 [symbolic = %.loc13_30.1 (constants.%.6d8)]\n// CHECK:STDOUT:     %.loc13_10.1: type = splice_block %.loc13_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc13_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc13_20.1: type = splice_block %.loc13_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc13_16.2: type = symbolic_binding U, 1 [symbolic = %U.loc13_16.1 (constants.%U)]\n// CHECK:STDOUT:     %return.param: ref @F.loc13.%ptr.loc13_30.1 (%ptr.18e) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @F.loc13.%ptr.loc13_30.1 (%ptr.18e) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F.loc4(%T.loc4_6.2: type, %U.loc4_16.2: type) {\n// CHECK:STDOUT:   %T.loc4_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T)]\n// CHECK:STDOUT:   %U.loc4_16.1: type = symbolic_binding U, 1 [symbolic = %U.loc4_16.1 (constants.%U)]\n// CHECK:STDOUT:   %ptr.loc4_30.1: type = ptr_type %T.loc4_6.1 [symbolic = %ptr.loc4_30.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %.loc4_30.1: Core.Form = init_form %ptr.loc4_30.1 [symbolic = %.loc4_30.1 (constants.%.cb6)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc4_30.1 [symbolic = %pattern_type (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @F.loc4.%ptr.loc4_30.1 (%ptr.e8f);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F.loc13(%T.loc13_6.2: type, %U.loc13_16.2: type) {\n// CHECK:STDOUT:   %T.loc13_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:   %U.loc13_16.1: type = symbolic_binding U, 1 [symbolic = %U.loc13_16.1 (constants.%U)]\n// CHECK:STDOUT:   %ptr.loc13_30.1: type = ptr_type %U.loc13_16.1 [symbolic = %ptr.loc13_30.1 (constants.%ptr.18e)]\n// CHECK:STDOUT:   %.loc13_30.1: Core.Form = init_form %ptr.loc13_30.1 [symbolic = %.loc13_30.1 (constants.%.6d8)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc13_30.1 [symbolic = %pattern_type (constants.%pattern_type.423)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc13_30.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @F.loc13.%ptr.loc13_30.1 (%ptr.18e) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type.117dbc.1 = name_ref F, file.%F.decl.loc4 [concrete = constants.%F.d98bd5.1]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc13_6.2 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:     return <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F.loc4(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T\n// CHECK:STDOUT:   %U.loc4_16.1 => constants.%U\n// CHECK:STDOUT:   %ptr.loc4_30.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %.loc4_30.1 => constants.%.cb6\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F.loc13(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc13_6.1 => constants.%T\n// CHECK:STDOUT:   %U.loc13_16.1 => constants.%U\n// CHECK:STDOUT:   %ptr.loc13_30.1 => constants.%ptr.18e\n// CHECK:STDOUT:   %.loc13_30.1 => constants.%.6d8\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.423\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_reorder.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %U.091: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T.67d [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %F.type.117dbc.1: type = fn_type @F.loc4 [concrete]\n// CHECK:STDOUT:   %F.d98bd5.1: %F.type.117dbc.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %U.67d: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %T.091: type = symbolic_binding T, 1 [symbolic]\n// CHECK:STDOUT:   %ptr.18e: type = ptr_type %T.091 [symbolic]\n// CHECK:STDOUT:   %.6d8: Core.Form = init_form %ptr.18e [symbolic]\n// CHECK:STDOUT:   %pattern_type.423: type = pattern_type %ptr.18e [symbolic]\n// CHECK:STDOUT:   %F.type.117dbc.2: type = fn_type @F.loc13 [concrete]\n// CHECK:STDOUT:   %F.d98bd5.2: %F.type.117dbc.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.18e [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl.loc4: %F.type.117dbc.1 = fn_decl @F.loc4 [concrete = constants.%F.d98bd5.1] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %return.patt: @F.loc4.%pattern_type (%pattern_type.4f4) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.loc4.%pattern_type (%pattern_type.4f4) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T.67d)]\n// CHECK:STDOUT:     %ptr.loc4_30.2: type = ptr_type %T.ref [symbolic = %ptr.loc4_30.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     %.loc4_30.2: Core.Form = init_form %ptr.loc4_30.2 [symbolic = %.loc4_30.1 (constants.%.cb6)]\n// CHECK:STDOUT:     %.loc4_10.1: type = splice_block %.loc4_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T.67d)]\n// CHECK:STDOUT:     %.loc4_20.1: type = splice_block %.loc4_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc4_16.2: type = symbolic_binding U, 1 [symbolic = %U.loc4_16.1 (constants.%U.091)]\n// CHECK:STDOUT:     %return.param: ref @F.loc4.%ptr.loc4_30.1 (%ptr.e8f) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @F.loc4.%ptr.loc4_30.1 (%ptr.e8f) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc13: %F.type.117dbc.2 = fn_decl @F.loc13 [concrete = constants.%F.d98bd5.2] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 1 [concrete]\n// CHECK:STDOUT:     %return.patt: @F.loc13.%pattern_type (%pattern_type.423) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.loc13.%pattern_type (%pattern_type.423) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc13: type = name_ref T, %T.loc13_23.2 [symbolic = %T.loc13_23.1 (constants.%T.091)]\n// CHECK:STDOUT:     %ptr.loc13_37.2: type = ptr_type %T.ref.loc13 [symbolic = %ptr.loc13_37.1 (constants.%ptr.18e)]\n// CHECK:STDOUT:     %.loc13_37.2: Core.Form = init_form %ptr.loc13_37.2 [symbolic = %.loc13_37.1 (constants.%.6d8)]\n// CHECK:STDOUT:     %.loc13_17.1: type = splice_block %.loc13_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc13_13.2: type = symbolic_binding U, 0 [symbolic = %U.loc13_13.1 (constants.%U.67d)]\n// CHECK:STDOUT:     %.loc13_27.1: type = splice_block %.loc13_27.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_27.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc13_23.2: type = symbolic_binding T, 1 [symbolic = %T.loc13_23.1 (constants.%T.091)]\n// CHECK:STDOUT:     %return.param: ref @F.loc13.%ptr.loc13_37.1 (%ptr.18e) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @F.loc13.%ptr.loc13_37.1 (%ptr.18e) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F.loc4(%T.loc4_6.2: type, %U.loc4_16.2: type) {\n// CHECK:STDOUT:   %T.loc4_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T.67d)]\n// CHECK:STDOUT:   %U.loc4_16.1: type = symbolic_binding U, 1 [symbolic = %U.loc4_16.1 (constants.%U.091)]\n// CHECK:STDOUT:   %ptr.loc4_30.1: type = ptr_type %T.loc4_6.1 [symbolic = %ptr.loc4_30.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %.loc4_30.1: Core.Form = init_form %ptr.loc4_30.1 [symbolic = %.loc4_30.1 (constants.%.cb6)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc4_30.1 [symbolic = %pattern_type (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @F.loc4.%ptr.loc4_30.1 (%ptr.e8f);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F.loc13(%U.loc13_13.2: type, %T.loc13_23.2: type) {\n// CHECK:STDOUT:   %U.loc13_13.1: type = symbolic_binding U, 0 [symbolic = %U.loc13_13.1 (constants.%U.67d)]\n// CHECK:STDOUT:   %T.loc13_23.1: type = symbolic_binding T, 1 [symbolic = %T.loc13_23.1 (constants.%T.091)]\n// CHECK:STDOUT:   %ptr.loc13_37.1: type = ptr_type %T.loc13_23.1 [symbolic = %ptr.loc13_37.1 (constants.%ptr.18e)]\n// CHECK:STDOUT:   %.loc13_37.1: Core.Form = init_form %ptr.loc13_37.1 [symbolic = %.loc13_37.1 (constants.%.6d8)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc13_37.1 [symbolic = %pattern_type (constants.%pattern_type.423)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc13_37.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @F.loc13.%ptr.loc13_37.1 (%ptr.18e) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type.117dbc.1 = name_ref F, file.%F.decl.loc4 [concrete = constants.%F.d98bd5.1]\n// CHECK:STDOUT:     %T.ref.loc21: type = name_ref T, %T.loc13_23.2 [symbolic = %T.loc13_23.1 (constants.%T.091)]\n// CHECK:STDOUT:     return <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F.loc4(constants.%T.67d, constants.%U.091) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T.67d\n// CHECK:STDOUT:   %U.loc4_16.1 => constants.%U.091\n// CHECK:STDOUT:   %ptr.loc4_30.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %.loc4_30.1 => constants.%.cb6\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F.loc13(constants.%U.67d, constants.%T.091) {\n// CHECK:STDOUT:   %U.loc13_13.1 => constants.%U.67d\n// CHECK:STDOUT:   %T.loc13_23.1 => constants.%T.091\n// CHECK:STDOUT:   %ptr.loc13_37.1 => constants.%ptr.18e\n// CHECK:STDOUT:   %.loc13_37.1 => constants.%.6d8\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.423\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_rename.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %U.091: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f8f9.1: type = ptr_type %T.67d [symbolic]\n// CHECK:STDOUT:   %.cb6cb9.1: Core.Form = init_form %ptr.e8f8f9.1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4b84.1: type = pattern_type %ptr.e8f8f9.1 [symbolic]\n// CHECK:STDOUT:   %F.type.117dbc.1: type = fn_type @F.loc4 [concrete]\n// CHECK:STDOUT:   %F.d98bd5.1: %F.type.117dbc.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %U.67d: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %T.091: type = symbolic_binding T, 1 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f8f9.2: type = ptr_type %U.67d [symbolic]\n// CHECK:STDOUT:   %.cb6cb9.2: Core.Form = init_form %ptr.e8f8f9.2 [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4b84.2: type = pattern_type %ptr.e8f8f9.2 [symbolic]\n// CHECK:STDOUT:   %F.type.117dbc.2: type = fn_type @F.loc13 [concrete]\n// CHECK:STDOUT:   %F.d98bd5.2: %F.type.117dbc.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.e8f8f9.2 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl.loc4: %F.type.117dbc.1 = fn_decl @F.loc4 [concrete = constants.%F.d98bd5.1] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %return.patt: @F.loc4.%pattern_type (%pattern_type.4f4b84.1) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.loc4.%pattern_type (%pattern_type.4f4b84.1) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T.67d)]\n// CHECK:STDOUT:     %ptr.loc4_30.2: type = ptr_type %T.ref [symbolic = %ptr.loc4_30.1 (constants.%ptr.e8f8f9.1)]\n// CHECK:STDOUT:     %.loc4_30.2: Core.Form = init_form %ptr.loc4_30.2 [symbolic = %.loc4_30.1 (constants.%.cb6cb9.1)]\n// CHECK:STDOUT:     %.loc4_10.1: type = splice_block %.loc4_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T.67d)]\n// CHECK:STDOUT:     %.loc4_20.1: type = splice_block %.loc4_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc4_16.2: type = symbolic_binding U, 1 [symbolic = %U.loc4_16.1 (constants.%U.091)]\n// CHECK:STDOUT:     %return.param: ref @F.loc4.%ptr.loc4_30.1 (%ptr.e8f8f9.1) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @F.loc4.%ptr.loc4_30.1 (%ptr.e8f8f9.1) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc13: %F.type.117dbc.2 = fn_decl @F.loc13 [concrete = constants.%F.d98bd5.2] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 1 [concrete]\n// CHECK:STDOUT:     %return.patt: @F.loc13.%pattern_type (%pattern_type.4f4b84.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.loc13.%pattern_type (%pattern_type.4f4b84.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %U.ref: type = name_ref U, %U.loc13_6.2 [symbolic = %U.loc13_6.1 (constants.%U.67d)]\n// CHECK:STDOUT:     %ptr.loc13_30.2: type = ptr_type %U.ref [symbolic = %ptr.loc13_30.1 (constants.%ptr.e8f8f9.2)]\n// CHECK:STDOUT:     %.loc13_30.2: Core.Form = init_form %ptr.loc13_30.2 [symbolic = %.loc13_30.1 (constants.%.cb6cb9.2)]\n// CHECK:STDOUT:     %.loc13_10.1: type = splice_block %.loc13_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc13_6.2: type = symbolic_binding U, 0 [symbolic = %U.loc13_6.1 (constants.%U.67d)]\n// CHECK:STDOUT:     %.loc13_20.1: type = splice_block %.loc13_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc13_16.2: type = symbolic_binding T, 1 [symbolic = %T.loc13_16.1 (constants.%T.091)]\n// CHECK:STDOUT:     %return.param: ref @F.loc13.%ptr.loc13_30.1 (%ptr.e8f8f9.2) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @F.loc13.%ptr.loc13_30.1 (%ptr.e8f8f9.2) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F.loc4(%T.loc4_6.2: type, %U.loc4_16.2: type) {\n// CHECK:STDOUT:   %T.loc4_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_6.1 (constants.%T.67d)]\n// CHECK:STDOUT:   %U.loc4_16.1: type = symbolic_binding U, 1 [symbolic = %U.loc4_16.1 (constants.%U.091)]\n// CHECK:STDOUT:   %ptr.loc4_30.1: type = ptr_type %T.loc4_6.1 [symbolic = %ptr.loc4_30.1 (constants.%ptr.e8f8f9.1)]\n// CHECK:STDOUT:   %.loc4_30.1: Core.Form = init_form %ptr.loc4_30.1 [symbolic = %.loc4_30.1 (constants.%.cb6cb9.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc4_30.1 [symbolic = %pattern_type (constants.%pattern_type.4f4b84.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @F.loc4.%ptr.loc4_30.1 (%ptr.e8f8f9.1);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F.loc13(%U.loc13_6.2: type, %T.loc13_16.2: type) {\n// CHECK:STDOUT:   %U.loc13_6.1: type = symbolic_binding U, 0 [symbolic = %U.loc13_6.1 (constants.%U.67d)]\n// CHECK:STDOUT:   %T.loc13_16.1: type = symbolic_binding T, 1 [symbolic = %T.loc13_16.1 (constants.%T.091)]\n// CHECK:STDOUT:   %ptr.loc13_30.1: type = ptr_type %U.loc13_6.1 [symbolic = %ptr.loc13_30.1 (constants.%ptr.e8f8f9.2)]\n// CHECK:STDOUT:   %.loc13_30.1: Core.Form = init_form %ptr.loc13_30.1 [symbolic = %.loc13_30.1 (constants.%.cb6cb9.2)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc13_30.1 [symbolic = %pattern_type (constants.%pattern_type.4f4b84.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc13_30.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @F.loc13.%ptr.loc13_30.1 (%ptr.e8f8f9.2) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type.117dbc.1 = name_ref F, file.%F.decl.loc4 [concrete = constants.%F.d98bd5.1]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc13_16.2 [symbolic = %T.loc13_16.1 (constants.%T.091)]\n// CHECK:STDOUT:     return <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F.loc4(constants.%T.67d, constants.%U.091) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T.67d\n// CHECK:STDOUT:   %U.loc4_16.1 => constants.%U.091\n// CHECK:STDOUT:   %ptr.loc4_30.1 => constants.%ptr.e8f8f9.1\n// CHECK:STDOUT:   %.loc4_30.1 => constants.%.cb6cb9.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4b84.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F.loc13(constants.%U.67d, constants.%T.091) {\n// CHECK:STDOUT:   %U.loc13_6.1 => constants.%U.67d\n// CHECK:STDOUT:   %T.loc13_16.1 => constants.%T.091\n// CHECK:STDOUT:   %ptr.loc13_30.1 => constants.%ptr.e8f8f9.2\n// CHECK:STDOUT:   %.loc13_30.1 => constants.%.cb6cb9.2\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4b84.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/resolve_used.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/resolve_used.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/resolve_used.carbon\n\n// --- fail_todo_call_monomorphization_error.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn ErrorIfNIsZero(N:! Core.IntLiteral()) {\n  // Check that we resolve the definition of a used specific function by\n  // ensuring we produce an error when doing so. Notionally this error is\n  // produced as a result of instantiating the `Core.Int` template, although\n  // that's not how we currently model `Core.Int`.\n  var unused v: Core.Int(N);\n}\n\nfn CallNegative() {\n  // CHECK:STDERR: fail_todo_call_monomorphization_error.carbon:[[@LINE+10]]:3: error: unable to monomorphize specific `ErrorIfNIsZero(0)` [ResolvingSpecificHere]\n  // CHECK:STDERR:   ErrorIfNIsZero(0);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_call_monomorphization_error.carbon:[[@LINE-7]]:17: note: `Core.Int(N)` evaluates to incomplete type `i0` [IncompleteTypeInMonomorphization]\n  // CHECK:STDERR:   var unused v: Core.Int(N);\n  // CHECK:STDERR:                 ^~~~~~~~~~~\n  // CHECK:STDERR: min_prelude/parts/int.carbon:11:9: note: integer type width of 0 is not positive [IntWidthNotPositive]\n  // CHECK:STDERR:   adapt MakeInt(N);\n  // CHECK:STDERR:         ^~~~~~~~~~\n  // CHECK:STDERR:\n  ErrorIfNIsZero(0);\n}\n\n// CHECK:STDOUT: --- fail_todo_call_monomorphization_error.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %ErrorIfNIsZero.type: type = fn_type @ErrorIfNIsZero [concrete]\n// CHECK:STDOUT:   %ErrorIfNIsZero: %ErrorIfNIsZero.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Int: type = class_type @Int, @Int(%N) [symbolic]\n// CHECK:STDOUT:   %require_complete.901: <witness> = require_complete_type %Int [symbolic]\n// CHECK:STDOUT:   %pattern_type.764: type = pattern_type %Int [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %.4a9: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%Int) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %Int, @DefaultOrUnformed [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.c82: %DefaultOrUnformed.type = facet_value %Int, (%DefaultOrUnformed.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.814: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.c82) [symbolic]\n// CHECK:STDOUT:   %.ca4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.814, %DefaultOrUnformed.facet.c82 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.12f: %.ca4 = impl_witness_access %DefaultOrUnformed.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.f0d: <specific function> = specific_impl_function %impl.elem0.12f, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.c82) [symbolic]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Int, @Destroy [symbolic]\n// CHECK:STDOUT:   %Destroy.facet.1c0: %Destroy.type = facet_value %Int, (%Destroy.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.297: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.1c0) [symbolic]\n// CHECK:STDOUT:   %.e63: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.297, %Destroy.facet.1c0 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.602: %.e63 = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.d65: <specific function> = specific_impl_function %impl.elem0.602, @Destroy.WithSelf.Op(%Destroy.facet.1c0) [symbolic]\n// CHECK:STDOUT:   %CallNegative.type: type = fn_type @CallNegative [concrete]\n// CHECK:STDOUT:   %CallNegative: %CallNegative.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ErrorIfNIsZero.specific_fn: <specific function> = specific_function %ErrorIfNIsZero, @ErrorIfNIsZero(%int_0) [concrete]\n// CHECK:STDOUT:   %i0: type = class_type @Int, @Int(%int_0) [concrete]\n// CHECK:STDOUT:   %complete_type.d94: <witness> = complete_type_witness <error> [concrete]\n// CHECK:STDOUT:   %pattern_type.47b: type = pattern_type %i0 [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.879: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%i0) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.7ec: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%i0) [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.5b7: %T.as.DefaultOrUnformed.impl.Op.type.7ec = struct_value () [concrete]\n// CHECK:STDOUT:   %.d6a: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%i0) [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.255: %DefaultOrUnformed.type = facet_value %i0, (%DefaultOrUnformed.impl_witness.879) [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.bd6: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.255) [concrete]\n// CHECK:STDOUT:   %.639: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.bd6, %DefaultOrUnformed.facet.255 [concrete]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.specific_fn: <specific function> = specific_function %T.as.DefaultOrUnformed.impl.Op.5b7, @T.as.DefaultOrUnformed.impl.Op(%i0) [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %custom_witness.8d7: <witness> = custom_witness (%Destroy.Op), @Destroy [concrete]\n// CHECK:STDOUT:   %Destroy.facet.eb2: %Destroy.type = facet_value %i0, (%custom_witness.8d7) [concrete]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.cef: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet.eb2) [concrete]\n// CHECK:STDOUT:   %.98d: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.cef, %Destroy.facet.eb2 [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ErrorIfNIsZero = %ErrorIfNIsZero.decl\n// CHECK:STDOUT:     .CallNegative = %CallNegative.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ErrorIfNIsZero.decl: %ErrorIfNIsZero.type = fn_decl @ErrorIfNIsZero [concrete = constants.%ErrorIfNIsZero] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_39.1: type = splice_block %.loc4_39.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Core.ref.loc4: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_39.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_39.3: type = converted %IntLiteral.call, %.loc4_39.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_19.2: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_19.1 (constants.%N)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallNegative.decl: %CallNegative.type = fn_decl @CallNegative [concrete = constants.%CallNegative] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ErrorIfNIsZero(%N.loc4_19.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N.loc4_19.1: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_19.1 (constants.%N)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Int.loc9_27.2: type = class_type @Int, @Int(%N.loc4_19.1) [symbolic = %Int.loc9_27.2 (constants.%Int)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Int.loc9_27.2 [symbolic = %require_complete (constants.%require_complete.901)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Int.loc9_27.2 [symbolic = %pattern_type (constants.%pattern_type.764)]\n// CHECK:STDOUT:   %.loc9_28.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%Int.loc9_27.2) [symbolic = %.loc9_28.3 (constants.%.4a9)]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc9_27.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness (constants.%DefaultOrUnformed.lookup_impl_witness)]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc9_28.2: %DefaultOrUnformed.type = facet_value %Int.loc9_27.2, (%DefaultOrUnformed.lookup_impl_witness) [symbolic = %DefaultOrUnformed.facet.loc9_28.2 (constants.%DefaultOrUnformed.facet.c82)]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc9_28.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type (constants.%DefaultOrUnformed.WithSelf.Op.type.814)]\n// CHECK:STDOUT:   %.loc9_28.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type, %DefaultOrUnformed.facet.loc9_28.2 [symbolic = %.loc9_28.4 (constants.%.ca4)]\n// CHECK:STDOUT:   %impl.elem0.loc9_28.2: @ErrorIfNIsZero.%.loc9_28.4 (%.ca4) = impl_witness_access %DefaultOrUnformed.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_28.2 (constants.%impl.elem0.12f)]\n// CHECK:STDOUT:   %specific_impl_fn.loc9_28.2: <specific function> = specific_impl_function %impl.elem0.loc9_28.2, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.loc9_28.2) [symbolic = %specific_impl_fn.loc9_28.2 (constants.%specific_impl_fn.f0d)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %Int.loc9_27.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %Int.loc9_27.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet.1c0)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [symbolic = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.297)]\n// CHECK:STDOUT:   %.loc9_3: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %Destroy.facet [symbolic = %.loc9_3 (constants.%.e63)]\n// CHECK:STDOUT:   %impl.elem0.loc9_3.2: @ErrorIfNIsZero.%.loc9_3 (%.e63) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_3.2 (constants.%impl.elem0.602)]\n// CHECK:STDOUT:   %specific_impl_fn.loc9_3.2: <specific function> = specific_impl_function %impl.elem0.loc9_3.2, @Destroy.WithSelf.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc9_3.2 (constants.%specific_impl_fn.d65)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %v.patt: @ErrorIfNIsZero.%pattern_type (%pattern_type.764) = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:       %v.var_patt: @ErrorIfNIsZero.%pattern_type (%pattern_type.764) = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v.var: ref @ErrorIfNIsZero.%Int.loc9_27.2 (%Int) = var %v.var_patt\n// CHECK:STDOUT:     %DefaultOrUnformed.facet.loc9_28.1: %DefaultOrUnformed.type = facet_value constants.%Int, (constants.%DefaultOrUnformed.lookup_impl_witness) [symbolic = %DefaultOrUnformed.facet.loc9_28.2 (constants.%DefaultOrUnformed.facet.c82)]\n// CHECK:STDOUT:     %.loc9_28.1: %DefaultOrUnformed.type = converted constants.%Int, %DefaultOrUnformed.facet.loc9_28.1 [symbolic = %DefaultOrUnformed.facet.loc9_28.2 (constants.%DefaultOrUnformed.facet.c82)]\n// CHECK:STDOUT:     %as_type: type = facet_access_type %.loc9_28.1 [symbolic = %Int.loc9_27.2 (constants.%Int)]\n// CHECK:STDOUT:     %.loc9_28.2: type = converted %.loc9_28.1, %as_type [symbolic = %Int.loc9_27.2 (constants.%Int)]\n// CHECK:STDOUT:     %impl.elem0.loc9_28.1: @ErrorIfNIsZero.%.loc9_28.4 (%.ca4) = impl_witness_access constants.%DefaultOrUnformed.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_28.2 (constants.%impl.elem0.12f)]\n// CHECK:STDOUT:     %specific_impl_fn.loc9_28.1: <specific function> = specific_impl_function %impl.elem0.loc9_28.1, @DefaultOrUnformed.WithSelf.Op(constants.%DefaultOrUnformed.facet.c82) [symbolic = %specific_impl_fn.loc9_28.2 (constants.%specific_impl_fn.f0d)]\n// CHECK:STDOUT:     %DefaultOrUnformed.WithSelf.Op.call: init @ErrorIfNIsZero.%Int.loc9_27.2 (%Int) = call %specific_impl_fn.loc9_28.1()\n// CHECK:STDOUT:     assign %v.var, %DefaultOrUnformed.WithSelf.Op.call\n// CHECK:STDOUT:     %.loc9_27: type = splice_block %Int.loc9_27.1 [symbolic = %Int.loc9_27.2 (constants.%Int)] {\n// CHECK:STDOUT:       %Core.ref.loc9: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Int.ref: %Int.type = name_ref Int, imports.%Core.Int [concrete = constants.%Int.generic]\n// CHECK:STDOUT:       %N.ref: Core.IntLiteral = name_ref N, %N.loc4_19.2 [symbolic = %N.loc4_19.1 (constants.%N)]\n// CHECK:STDOUT:       %Int.loc9_27.1: type = class_type @Int, @Int(constants.%N) [symbolic = %Int.loc9_27.2 (constants.%Int)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v: ref @ErrorIfNIsZero.%Int.loc9_27.2 (%Int) = ref_binding v, %v.var\n// CHECK:STDOUT:     %impl.elem0.loc9_3.1: @ErrorIfNIsZero.%.loc9_3 (%.e63) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_3.2 (constants.%impl.elem0.602)]\n// CHECK:STDOUT:     %bound_method.loc9_3.1: <bound method> = bound_method %v.var, %impl.elem0.loc9_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc9_3.1: <specific function> = specific_impl_function %impl.elem0.loc9_3.1, @Destroy.WithSelf.Op(constants.%Destroy.facet.1c0) [symbolic = %specific_impl_fn.loc9_3.2 (constants.%specific_impl_fn.d65)]\n// CHECK:STDOUT:     %bound_method.loc9_3.2: <bound method> = bound_method %v.var, %specific_impl_fn.loc9_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call: init %empty_tuple.type = call %bound_method.loc9_3.2(%v.var)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallNegative() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %ErrorIfNIsZero.ref: %ErrorIfNIsZero.type = name_ref ErrorIfNIsZero, file.%ErrorIfNIsZero.decl [concrete = constants.%ErrorIfNIsZero]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:   %ErrorIfNIsZero.specific_fn: <specific function> = specific_function %ErrorIfNIsZero.ref, @ErrorIfNIsZero(constants.%int_0) [concrete = constants.%ErrorIfNIsZero.specific_fn]\n// CHECK:STDOUT:   %ErrorIfNIsZero.call: init %empty_tuple.type = call %ErrorIfNIsZero.specific_fn()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %i0) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ErrorIfNIsZero(constants.%N) {\n// CHECK:STDOUT:   %N.loc4_19.1 => constants.%N\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ErrorIfNIsZero(constants.%int_0) {\n// CHECK:STDOUT:   %N.loc4_19.1 => constants.%int_0\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Int.loc9_27.2 => constants.%i0\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.d94\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.47b\n// CHECK:STDOUT:   %.loc9_28.3 => constants.%.d6a\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness => constants.%DefaultOrUnformed.impl_witness.879\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc9_28.2 => constants.%DefaultOrUnformed.facet.255\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type => constants.%DefaultOrUnformed.WithSelf.Op.type.bd6\n// CHECK:STDOUT:   %.loc9_28.4 => constants.%.639\n// CHECK:STDOUT:   %impl.elem0.loc9_28.2 => constants.%T.as.DefaultOrUnformed.impl.Op.5b7\n// CHECK:STDOUT:   %specific_impl_fn.loc9_28.2 => constants.%T.as.DefaultOrUnformed.impl.Op.specific_fn\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness => constants.%custom_witness.8d7\n// CHECK:STDOUT:   %Destroy.facet => constants.%Destroy.facet.eb2\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type => constants.%Destroy.WithSelf.Op.type.cef\n// CHECK:STDOUT:   %.loc9_3 => constants.%.98d\n// CHECK:STDOUT:   %impl.elem0.loc9_3.2 => constants.%Destroy.Op\n// CHECK:STDOUT:   %specific_impl_fn.loc9_3.2 => constants.%Destroy.Op\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/return_slot.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/return_slot.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/return_slot.carbon\n\nclass Wrap(T:! type) {\n  fn Make() -> T { return Make(); }\n}\n\nclass C { var arr: array(i32, 100); }\n\nfn G() {\n  var unused a: i32 = Wrap(i32).Make();\n  var unused b: () = Wrap(()).Make();\n  var unused c: C = Wrap(C).Make();\n}\n\n// CHECK:STDOUT: --- return_slot.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Wrap.type: type = generic_class_type @Wrap [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Wrap.generic: %Wrap.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Wrap.063: type = class_type @Wrap, @Wrap(%T) [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %Wrap.Make.type.6e9: type = fn_type @Wrap.Make, @Wrap(%T) [symbolic]\n// CHECK:STDOUT:   %Wrap.Make.e25: %Wrap.Make.type.6e9 = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.5c8: <specific function> = specific_function %Wrap.Make.e25, @Wrap.Make(%T) [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_100: Core.IntLiteral = int_value 100 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_100, %i32 [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %array_type [concrete]\n// CHECK:STDOUT:   %struct_type.arr.5f2: type = struct_type {.arr: %array_type} [concrete]\n// CHECK:STDOUT:   %complete_type.22a: <witness> = complete_type_witness %struct_type.arr.5f2 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Wrap.e80: type = class_type @Wrap, @Wrap(%i32) [concrete]\n// CHECK:STDOUT:   %Wrap.Make.type.939: type = fn_type @Wrap.Make, @Wrap(%i32) [concrete]\n// CHECK:STDOUT:   %Wrap.Make.6cb: %Wrap.Make.type.939 = struct_value () [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.35c: <specific function> = specific_function %Wrap.Make.6cb, @Wrap.Make(%i32) [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Wrap.0f1: type = class_type @Wrap, @Wrap(%empty_tuple.type) [concrete]\n// CHECK:STDOUT:   %Wrap.Make.type.fb0: type = fn_type @Wrap.Make, @Wrap(%empty_tuple.type) [concrete]\n// CHECK:STDOUT:   %Wrap.Make.b5c: %Wrap.Make.type.fb0 = struct_value () [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.c03: <specific function> = specific_function %Wrap.Make.b5c, @Wrap.Make(%empty_tuple.type) [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Wrap.3b1: type = class_type @Wrap, @Wrap(%C) [concrete]\n// CHECK:STDOUT:   %Wrap.Make.type.a8f: type = fn_type @Wrap.Make, @Wrap(%C) [concrete]\n// CHECK:STDOUT:   %Wrap.Make.62a: %Wrap.Make.type.a8f = struct_value () [concrete]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.cb9: <specific function> = specific_function %Wrap.Make.62a, @Wrap.Make(%C) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc24 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc23 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc22 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]\n// CHECK:STDOUT:   %complete_type.782: <witness> = complete_type_witness %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Wrap = %Wrap.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Wrap.decl: %Wrap.type = class_decl @Wrap [concrete = constants.%Wrap.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_16.1: type = splice_block %.loc15_16.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_16.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_12.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_12.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Wrap(%T.loc15_12.2: type) {\n// CHECK:STDOUT:   %T.loc15_12.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_12.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Wrap.Make.type: type = fn_type @Wrap.Make, @Wrap(%T.loc15_12.1) [symbolic = %Wrap.Make.type (constants.%Wrap.Make.type.6e9)]\n// CHECK:STDOUT:   %Wrap.Make: @Wrap.%Wrap.Make.type (%Wrap.Make.type.6e9) = struct_value () [symbolic = %Wrap.Make (constants.%Wrap.Make.e25)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Wrap.Make.decl: @Wrap.%Wrap.Make.type (%Wrap.Make.type.6e9) = fn_decl @Wrap.Make [symbolic = @Wrap.%Wrap.Make (constants.%Wrap.Make.e25)] {\n// CHECK:STDOUT:       %return.patt: @Wrap.Make.%pattern_type (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Wrap.Make.%pattern_type (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @Wrap.%T.loc15_12.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %.loc16_16.3: Core.Form = init_form %T.ref [symbolic = %.loc16_16.2 (constants.%.184)]\n// CHECK:STDOUT:       %return.param: ref @Wrap.Make.%T (%T) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @Wrap.Make.%T (%T) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Wrap.063\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .Make = %Wrap.Make.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %int_100: Core.IntLiteral = int_value 100 [concrete = constants.%int_100]\n// CHECK:STDOUT:   %array_type: type = array_type %int_100, %i32 [concrete = constants.%array_type]\n// CHECK:STDOUT:   %.loc19: %C.elem = field_decl arr, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.arr.5f2 [concrete = constants.%complete_type.22a]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .arr = %.loc19\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Wrap.Make(@Wrap.%T.loc15_12.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %.loc16_16.2: Core.Form = init_form %T [symbolic = %.loc16_16.2 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %Wrap.Make.type: type = fn_type @Wrap.Make, @Wrap(%T) [symbolic = %Wrap.Make.type (constants.%Wrap.Make.type.6e9)]\n// CHECK:STDOUT:   %Wrap.Make: @Wrap.Make.%Wrap.Make.type (%Wrap.Make.type.6e9) = struct_value () [symbolic = %Wrap.Make (constants.%Wrap.Make.e25)]\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.loc16_27.2: <specific function> = specific_function %Wrap.Make, @Wrap.Make(%T) [symbolic = %Wrap.Make.specific_fn.loc16_27.2 (constants.%Wrap.Make.specific_fn.5c8)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Wrap.Make.%T (%T) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc16_27: @Wrap.Make.%Wrap.Make.type (%Wrap.Make.type.6e9) = specific_constant @Wrap.%Wrap.Make.decl, @Wrap(constants.%T) [symbolic = %Wrap.Make (constants.%Wrap.Make.e25)]\n// CHECK:STDOUT:     %Make.ref: @Wrap.Make.%Wrap.Make.type (%Wrap.Make.type.6e9) = name_ref Make, %.loc16_27 [symbolic = %Wrap.Make (constants.%Wrap.Make.e25)]\n// CHECK:STDOUT:     %Wrap.Make.specific_fn.loc16_27.1: <specific function> = specific_function %Make.ref, @Wrap.Make(constants.%T) [symbolic = %Wrap.Make.specific_fn.loc16_27.2 (constants.%Wrap.Make.specific_fn.5c8)]\n// CHECK:STDOUT:     %.loc16_16.1: ref @Wrap.Make.%T (%T) = splice_block %return.param {}\n// CHECK:STDOUT:     %Wrap.Make.call: init @Wrap.Make.%T (%T) to %.loc16_16.1 = call %Wrap.Make.specific_fn.loc16_27.1()\n// CHECK:STDOUT:     return %Wrap.Make.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.7ce = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %i32 = var %a.var_patt\n// CHECK:STDOUT:   %Wrap.ref.loc22: %Wrap.type = name_ref Wrap, file.%Wrap.decl [concrete = constants.%Wrap.generic]\n// CHECK:STDOUT:   %i32.loc22_28: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %Wrap.loc22: type = class_type @Wrap, @Wrap(constants.%i32) [concrete = constants.%Wrap.e80]\n// CHECK:STDOUT:   %.loc22: %Wrap.Make.type.939 = specific_constant @Wrap.%Wrap.Make.decl, @Wrap(constants.%i32) [concrete = constants.%Wrap.Make.6cb]\n// CHECK:STDOUT:   %Make.ref.loc22: %Wrap.Make.type.939 = name_ref Make, %.loc22 [concrete = constants.%Wrap.Make.6cb]\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.loc22: <specific function> = specific_function %Make.ref.loc22, @Wrap.Make(constants.%i32) [concrete = constants.%Wrap.Make.specific_fn.35c]\n// CHECK:STDOUT:   %Wrap.Make.call.loc22: init %i32 = call %Wrap.Make.specific_fn.loc22()\n// CHECK:STDOUT:   assign %a.var, %Wrap.Make.call.loc22\n// CHECK:STDOUT:   %i32.loc22_17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %a: ref %i32 = ref_binding a, %a.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.cb1 = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.cb1 = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %empty_tuple.type = var %b.var_patt\n// CHECK:STDOUT:   %Wrap.ref.loc23: %Wrap.type = name_ref Wrap, file.%Wrap.decl [concrete = constants.%Wrap.generic]\n// CHECK:STDOUT:   %.loc23_28: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc23_29: type = converted %.loc23_28, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   %Wrap.loc23: type = class_type @Wrap, @Wrap(constants.%empty_tuple.type) [concrete = constants.%Wrap.0f1]\n// CHECK:STDOUT:   %.loc23_30: %Wrap.Make.type.fb0 = specific_constant @Wrap.%Wrap.Make.decl, @Wrap(constants.%empty_tuple.type) [concrete = constants.%Wrap.Make.b5c]\n// CHECK:STDOUT:   %Make.ref.loc23: %Wrap.Make.type.fb0 = name_ref Make, %.loc23_30 [concrete = constants.%Wrap.Make.b5c]\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.loc23: <specific function> = specific_function %Make.ref.loc23, @Wrap.Make(constants.%empty_tuple.type) [concrete = constants.%Wrap.Make.specific_fn.c03]\n// CHECK:STDOUT:   %Wrap.Make.call.loc23: init %empty_tuple.type = call %Wrap.Make.specific_fn.loc23()\n// CHECK:STDOUT:   assign %b.var, %Wrap.Make.call.loc23\n// CHECK:STDOUT:   %.loc23_18.1: type = splice_block %.loc23_18.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %.loc23_18.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc23_18.3: type = converted %.loc23_18.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b: ref %empty_tuple.type = ref_binding b, %b.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.7c7 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt\n// CHECK:STDOUT:   %Wrap.ref.loc24: %Wrap.type = name_ref Wrap, file.%Wrap.decl [concrete = constants.%Wrap.generic]\n// CHECK:STDOUT:   %C.ref.loc24_26: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %Wrap.loc24: type = class_type @Wrap, @Wrap(constants.%C) [concrete = constants.%Wrap.3b1]\n// CHECK:STDOUT:   %.loc24_28: %Wrap.Make.type.a8f = specific_constant @Wrap.%Wrap.Make.decl, @Wrap(constants.%C) [concrete = constants.%Wrap.Make.62a]\n// CHECK:STDOUT:   %Make.ref.loc24: %Wrap.Make.type.a8f = name_ref Make, %.loc24_28 [concrete = constants.%Wrap.Make.62a]\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.loc24: <specific function> = specific_function %Make.ref.loc24, @Wrap.Make(constants.%C) [concrete = constants.%Wrap.Make.specific_fn.cb9]\n// CHECK:STDOUT:   %.loc24_3: ref %C = splice_block %c.var {}\n// CHECK:STDOUT:   %Wrap.Make.call.loc24: init %C to %.loc24_3 = call %Wrap.Make.specific_fn.loc24()\n// CHECK:STDOUT:   assign %c.var, %Wrap.Make.call.loc24\n// CHECK:STDOUT:   %C.ref.loc24_17: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc24: <bound method> = bound_method %c.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc24: init %empty_tuple.type = call %Destroy.Op.bound.loc24(%c.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc23: <bound method> = bound_method %b.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc23: init %empty_tuple.type = call %Destroy.Op.bound.loc23(%b.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc22: <bound method> = bound_method %a.var, constants.%Destroy.Op.651ba6.3\n// CHECK:STDOUT:   %Destroy.Op.call.loc22: init %empty_tuple.type = call %Destroy.Op.bound.loc22(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc24(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc23(%self.param: ref %empty_tuple.type) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc22(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Wrap(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_12.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Wrap.Make.type => constants.%Wrap.Make.type.6e9\n// CHECK:STDOUT:   %Wrap.Make => constants.%Wrap.Make.e25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Wrap.Make(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %.loc16_16.2 => constants.%.184\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.944\n// CHECK:STDOUT:   %Wrap.Make.type => constants.%Wrap.Make.type.6e9\n// CHECK:STDOUT:   %Wrap.Make => constants.%Wrap.Make.e25\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.loc16_27.2 => constants.%Wrap.Make.specific_fn.5c8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Wrap(constants.%i32) {\n// CHECK:STDOUT:   %T.loc15_12.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Wrap.Make.type => constants.%Wrap.Make.type.939\n// CHECK:STDOUT:   %Wrap.Make => constants.%Wrap.Make.6cb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Wrap.Make(constants.%i32) {\n// CHECK:STDOUT:   %T => constants.%i32\n// CHECK:STDOUT:   %.loc16_16.2 => constants.%.ff5\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7ce\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %Wrap.Make.type => constants.%Wrap.Make.type.939\n// CHECK:STDOUT:   %Wrap.Make => constants.%Wrap.Make.6cb\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.loc16_27.2 => constants.%Wrap.Make.specific_fn.35c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Wrap(constants.%empty_tuple.type) {\n// CHECK:STDOUT:   %T.loc15_12.1 => constants.%empty_tuple.type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Wrap.Make.type => constants.%Wrap.Make.type.fb0\n// CHECK:STDOUT:   %Wrap.Make => constants.%Wrap.Make.b5c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Wrap.Make(constants.%empty_tuple.type) {\n// CHECK:STDOUT:   %T => constants.%empty_tuple.type\n// CHECK:STDOUT:   %.loc16_16.2 => constants.%.262\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.cb1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.782\n// CHECK:STDOUT:   %Wrap.Make.type => constants.%Wrap.Make.type.fb0\n// CHECK:STDOUT:   %Wrap.Make => constants.%Wrap.Make.b5c\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.loc16_27.2 => constants.%Wrap.Make.specific_fn.c03\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Wrap(constants.%C) {\n// CHECK:STDOUT:   %T.loc15_12.1 => constants.%C\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Wrap.Make.type => constants.%Wrap.Make.type.a8f\n// CHECK:STDOUT:   %Wrap.Make => constants.%Wrap.Make.62a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Wrap.Make(constants.%C) {\n// CHECK:STDOUT:   %T => constants.%C\n// CHECK:STDOUT:   %.loc16_16.2 => constants.%.a69\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.22a\n// CHECK:STDOUT:   %Wrap.Make.type => constants.%Wrap.Make.type.a8f\n// CHECK:STDOUT:   %Wrap.Make => constants.%Wrap.Make.62a\n// CHECK:STDOUT:   %Wrap.Make.specific_fn.loc16_27.2 => constants.%Wrap.Make.specific_fn.cb9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/template_param.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/template_param.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/template_param.carbon\n\n// --- fn.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(unused template T:! type) {\n}\n\nfn G() {\n  F({});\n}\n\n// CHECK:STDOUT: --- fn.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%empty_struct_type) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_26.1: type = splice_block %.loc4_26.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_26.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_22.2: type = symbolic_binding T, 0, template [template = %T.loc4_22.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_22.2: type) {\n// CHECK:STDOUT:   %T.loc4_22.1: type = symbolic_binding T, 0, template [template = %T.loc4_22.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc8_6: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc8_7: type = converted %.loc8_6, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%empty_struct_type) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_22.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %T.loc4_22.1 => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/type_param.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/type_param.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/type_param.carbon\n\nfn F(T:! type) {\n  var p: T*;\n  let unused n: T = *p;\n}\n\n// CHECK:STDOUT: --- type_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %.713: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %ptr, @DefaultOrUnformed [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %ptr, (%DefaultOrUnformed.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type.d74: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet) [symbolic]\n// CHECK:STDOUT:   %.425: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type.d74, %DefaultOrUnformed.facet [symbolic]\n// CHECK:STDOUT:   %impl.elem0.45d: %.425 = impl_witness_access %DefaultOrUnformed.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.a93: <specific function> = specific_impl_function %impl.elem0.45d, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet) [symbolic]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr, @Destroy [symbolic]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %ptr, (%Destroy.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.bb2: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [symbolic]\n// CHECK:STDOUT:   %.c3f: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.bb2, %Destroy.facet [symbolic]\n// CHECK:STDOUT:   %impl.elem0.b55: %.c3f = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.5c7: <specific function> = specific_impl_function %impl.elem0.b55, @Destroy.WithSelf.Op(%Destroy.facet) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .DefaultOrUnformed = %Core.DefaultOrUnformed\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.DefaultOrUnformed: type = import_ref Core//prelude/parts/default, DefaultOrUnformed, loaded [concrete = constants.%DefaultOrUnformed.type]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_10.1: type = splice_block %.loc15_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_6.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc15_6.2: type) {\n// CHECK:STDOUT:   %T.loc15_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_6.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ptr.loc16_11.2: type = ptr_type %T.loc15_6.1 [symbolic = %ptr.loc16_11.2 (constants.%ptr)]\n// CHECK:STDOUT:   %require_complete.loc16: <witness> = require_complete_type %ptr.loc16_11.2 [symbolic = %require_complete.loc16 (constants.%require_complete.ef1)]\n// CHECK:STDOUT:   %pattern_type.loc16: type = pattern_type %ptr.loc16_11.2 [symbolic = %pattern_type.loc16 (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:   %.loc16_12.3: require_specific_def_type = require_specific_def @T.as.DefaultOrUnformed.impl(%ptr.loc16_11.2) [symbolic = %.loc16_12.3 (constants.%.713)]\n// CHECK:STDOUT:   %DefaultOrUnformed.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_11.2, @DefaultOrUnformed [symbolic = %DefaultOrUnformed.lookup_impl_witness (constants.%DefaultOrUnformed.lookup_impl_witness)]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet.loc16_12.2: %DefaultOrUnformed.type = facet_value %ptr.loc16_11.2, (%DefaultOrUnformed.lookup_impl_witness) [symbolic = %DefaultOrUnformed.facet.loc16_12.2 (constants.%DefaultOrUnformed.facet)]\n// CHECK:STDOUT:   %DefaultOrUnformed.WithSelf.Op.type: type = fn_type @DefaultOrUnformed.WithSelf.Op, @DefaultOrUnformed.WithSelf(%DefaultOrUnformed.facet.loc16_12.2) [symbolic = %DefaultOrUnformed.WithSelf.Op.type (constants.%DefaultOrUnformed.WithSelf.Op.type.d74)]\n// CHECK:STDOUT:   %.loc16_12.4: type = fn_type_with_self_type %DefaultOrUnformed.WithSelf.Op.type, %DefaultOrUnformed.facet.loc16_12.2 [symbolic = %.loc16_12.4 (constants.%.425)]\n// CHECK:STDOUT:   %impl.elem0.loc16_12.2: @F.%.loc16_12.4 (%.425) = impl_witness_access %DefaultOrUnformed.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_12.2 (constants.%impl.elem0.45d)]\n// CHECK:STDOUT:   %specific_impl_fn.loc16_12.2: <specific function> = specific_impl_function %impl.elem0.loc16_12.2, @DefaultOrUnformed.WithSelf.Op(%DefaultOrUnformed.facet.loc16_12.2) [symbolic = %specific_impl_fn.loc16_12.2 (constants.%specific_impl_fn.a93)]\n// CHECK:STDOUT:   %require_complete.loc17: <witness> = require_complete_type %T.loc15_6.1 [symbolic = %require_complete.loc17 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %pattern_type.loc17: type = pattern_type %T.loc15_6.1 [symbolic = %pattern_type.loc17 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc16_11.2, @Destroy [symbolic = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]\n// CHECK:STDOUT:   %Destroy.facet: %Destroy.type = facet_value %ptr.loc16_11.2, (%Destroy.lookup_impl_witness) [symbolic = %Destroy.facet (constants.%Destroy.facet)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%Destroy.facet) [symbolic = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.bb2)]\n// CHECK:STDOUT:   %.loc16_3: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %Destroy.facet [symbolic = %.loc16_3 (constants.%.c3f)]\n// CHECK:STDOUT:   %impl.elem0.loc16_3.2: @F.%.loc16_3 (%.c3f) = impl_witness_access %Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_3.2 (constants.%impl.elem0.b55)]\n// CHECK:STDOUT:   %specific_impl_fn.loc16_3.2: <specific function> = specific_impl_function %impl.elem0.loc16_3.2, @Destroy.WithSelf.Op(%Destroy.facet) [symbolic = %specific_impl_fn.loc16_3.2 (constants.%specific_impl_fn.5c7)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %p.patt: @F.%pattern_type.loc16 (%pattern_type.4f4) = ref_binding_pattern p [concrete]\n// CHECK:STDOUT:       %p.var_patt: @F.%pattern_type.loc16 (%pattern_type.4f4) = var_pattern %p.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p.var: ref @F.%ptr.loc16_11.2 (%ptr) = var %p.var_patt\n// CHECK:STDOUT:     %DefaultOrUnformed.facet.loc16_12.1: %DefaultOrUnformed.type = facet_value constants.%ptr, (constants.%DefaultOrUnformed.lookup_impl_witness) [symbolic = %DefaultOrUnformed.facet.loc16_12.2 (constants.%DefaultOrUnformed.facet)]\n// CHECK:STDOUT:     %.loc16_12.1: %DefaultOrUnformed.type = converted constants.%ptr, %DefaultOrUnformed.facet.loc16_12.1 [symbolic = %DefaultOrUnformed.facet.loc16_12.2 (constants.%DefaultOrUnformed.facet)]\n// CHECK:STDOUT:     %as_type: type = facet_access_type %.loc16_12.1 [symbolic = %ptr.loc16_11.2 (constants.%ptr)]\n// CHECK:STDOUT:     %.loc16_12.2: type = converted %.loc16_12.1, %as_type [symbolic = %ptr.loc16_11.2 (constants.%ptr)]\n// CHECK:STDOUT:     %impl.elem0.loc16_12.1: @F.%.loc16_12.4 (%.425) = impl_witness_access constants.%DefaultOrUnformed.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_12.2 (constants.%impl.elem0.45d)]\n// CHECK:STDOUT:     %specific_impl_fn.loc16_12.1: <specific function> = specific_impl_function %impl.elem0.loc16_12.1, @DefaultOrUnformed.WithSelf.Op(constants.%DefaultOrUnformed.facet) [symbolic = %specific_impl_fn.loc16_12.2 (constants.%specific_impl_fn.a93)]\n// CHECK:STDOUT:     %DefaultOrUnformed.WithSelf.Op.call: init @F.%ptr.loc16_11.2 (%ptr) = call %specific_impl_fn.loc16_12.1()\n// CHECK:STDOUT:     assign %p.var, %DefaultOrUnformed.WithSelf.Op.call\n// CHECK:STDOUT:     %.loc16_11: type = splice_block %ptr.loc16_11.1 [symbolic = %ptr.loc16_11.2 (constants.%ptr)] {\n// CHECK:STDOUT:       %T.ref.loc16: type = name_ref T, %T.loc15_6.2 [symbolic = %T.loc15_6.1 (constants.%T)]\n// CHECK:STDOUT:       %ptr.loc16_11.1: type = ptr_type %T.ref.loc16 [symbolic = %ptr.loc16_11.2 (constants.%ptr)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: ref @F.%ptr.loc16_11.2 (%ptr) = ref_binding p, %p.var\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %n.patt: @F.%pattern_type.loc17 (%pattern_type.51d) = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p.ref: ref @F.%ptr.loc16_11.2 (%ptr) = name_ref p, %p\n// CHECK:STDOUT:     %.loc17_22: @F.%ptr.loc16_11.2 (%ptr) = acquire_value %p.ref\n// CHECK:STDOUT:     %.loc17_21.1: ref @F.%T.loc15_6.1 (%T) = deref %.loc17_22\n// CHECK:STDOUT:     %T.ref.loc17: type = name_ref T, %T.loc15_6.2 [symbolic = %T.loc15_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc17_21.2: @F.%T.loc15_6.1 (%T) = acquire_value %.loc17_21.1\n// CHECK:STDOUT:     %n: @F.%T.loc15_6.1 (%T) = value_binding n, %.loc17_21.2\n// CHECK:STDOUT:     %impl.elem0.loc16_3.1: @F.%.loc16_3 (%.c3f) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc16_3.2 (constants.%impl.elem0.b55)]\n// CHECK:STDOUT:     %bound_method.loc16_3.1: <bound method> = bound_method %p.var, %impl.elem0.loc16_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc16_3.1: <specific function> = specific_impl_function %impl.elem0.loc16_3.1, @Destroy.WithSelf.Op(constants.%Destroy.facet) [symbolic = %specific_impl_fn.loc16_3.2 (constants.%specific_impl_fn.5c7)]\n// CHECK:STDOUT:     %bound_method.loc16_3.2: <bound method> = bound_method %p.var, %specific_impl_fn.loc16_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call: init %empty_tuple.type = call %bound_method.loc16_3.2(%p.var)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_6.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/type_param_scope.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/type_param_scope.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/type_param_scope.carbon\n\n// --- local_let.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F(T:! type, n: T*) -> T* {\n  //@dump-sem-ir-begin\n  let m: T* = n;\n  return m;\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- local_let.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T.67d [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr [symbolic]\n// CHECK:STDOUT:   %.cb6: Core.Form = init_form %ptr [symbolic]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr, (%Copy.lookup_impl_witness.2e6) [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic]\n// CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet [symbolic]\n// CHECK:STDOUT:   %impl.elem0.1c7: %.299 = impl_witness_access %Copy.lookup_impl_witness.2e6, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.366: <specific function> = specific_impl_function %impl.elem0.1c7, @Copy.WithSelf.Op(%Copy.facet) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_6.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %.loc7_10.1: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc4_6.1) [symbolic = %.loc7_10.1 (constants.%.2f2)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc4_20.1, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc4_20.1, (%Copy.lookup_impl_witness) [symbolic = %Copy.facet (constants.%Copy.facet)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]\n// CHECK:STDOUT:   %.loc7_10.2: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [symbolic = %.loc7_10.2 (constants.%.299)]\n// CHECK:STDOUT:   %impl.elem0.loc7_10.2: @F.%.loc7_10.2 (%.299) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc7_10.2 (constants.%impl.elem0.1c7)]\n// CHECK:STDOUT:   %specific_impl_fn.loc7_10.2: <specific function> = specific_impl_function %impl.elem0.loc7_10.2, @Copy.WithSelf.Op(%Copy.facet) [symbolic = %specific_impl_fn.loc7_10.2 (constants.%specific_impl_fn.366)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%n.param: @F.%ptr.loc4_20.1 (%ptr)) -> out %return.param: @F.%ptr.loc4_20.1 (%ptr) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %m.patt: @F.%pattern_type (%pattern_type.4f4) = value_binding_pattern m [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %n.ref: @F.%ptr.loc4_20.1 (%ptr) = name_ref n, %n\n// CHECK:STDOUT:     %.loc6: type = splice_block %ptr.loc6 [symbolic = %ptr.loc4_20.1 (constants.%ptr)] {\n// CHECK:STDOUT:       %T.ref.loc6: type = name_ref T, %T.loc4_6.2 [symbolic = %T.loc4_6.1 (constants.%T.67d)]\n// CHECK:STDOUT:       %ptr.loc6: type = ptr_type %T.ref.loc6 [symbolic = %ptr.loc4_20.1 (constants.%ptr)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %m: @F.%ptr.loc4_20.1 (%ptr) = value_binding m, %n.ref\n// CHECK:STDOUT:     %m.ref: @F.%ptr.loc4_20.1 (%ptr) = name_ref m, %m\n// CHECK:STDOUT:     %impl.elem0.loc7_10.1: @F.%.loc7_10.2 (%.299) = impl_witness_access constants.%Copy.lookup_impl_witness.2e6, element0 [symbolic = %impl.elem0.loc7_10.2 (constants.%impl.elem0.1c7)]\n// CHECK:STDOUT:     %bound_method.loc7_10.1: <bound method> = bound_method %m.ref, %impl.elem0.loc7_10.1\n// CHECK:STDOUT:     %specific_impl_fn.loc7_10.1: <specific function> = specific_impl_function %impl.elem0.loc7_10.1, @Copy.WithSelf.Op(constants.%Copy.facet) [symbolic = %specific_impl_fn.loc7_10.2 (constants.%specific_impl_fn.366)]\n// CHECK:STDOUT:     %bound_method.loc7_10.2: <bound method> = bound_method %m.ref, %specific_impl_fn.loc7_10.1\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @F.%ptr.loc4_20.1 (%ptr) = call %bound_method.loc7_10.2(%m.ref)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc4_6.1 => constants.%T.67d\n// CHECK:STDOUT:   %ptr.loc4_20.1 => constants.%ptr\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT:   %.loc4_27.1 => constants.%.cb6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/function/generic/undefined.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/function/generic/undefined.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/function/generic/undefined.carbon\n\n// --- call_defined.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Defined[T:! type](unused x: T) {}\n\nfn CallDefined() {\n  Defined(0 as i32);\n}\n\n// --- call_defined_late.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Defined[T:! type](x: T);\n\nfn CallDefined() {\n  Defined(0 as i32);\n}\n\nfn Defined[T:! type](unused x: T) {}\n\n// --- fail_call_undefined.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn Undefined[T:! type](x: T);\n\nfn CallUndefined() {\n  // CHECK:STDERR: fail_call_undefined.carbon:[[@LINE+7]]:3: error: use of undefined generic function [MissingGenericFunctionDefinition]\n  // CHECK:STDERR:   Undefined(0 as i32);\n  // CHECK:STDERR:   ^~~~~~~~~\n  // CHECK:STDERR: fail_call_undefined.carbon:[[@LINE-6]]:1: note: generic function declared here [MissingGenericFunctionDefinitionHere]\n  // CHECK:STDERR: fn Undefined[T:! type](x: T);\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Undefined(0 as i32);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/generic/call_basic_depth.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/call_basic_depth.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/call_basic_depth.carbon\n\nclass C {\n  fn Cfn[unused self: Self, T:! type](unused x: T) {\n  }\n}\n\n//@dump-sem-ir-begin\nfn F[T:! type](unused x: T) {\n}\n//@dump-sem-ir-end\n\nfn H[T:! type](x: T) {\n  //@dump-sem-ir-begin\n  F(x);\n  //@dump-sem-ir-end\n}\n\nfn G[T:! type](x: T) {\n  //@dump-sem-ir-begin\n  H(x);\n  F(x);\n  //@dump-sem-ir-end\n\n  var c: C = {};\n  c.Cfn(x);\n}\n\nfn M() {\n  var n: C = {};\n\n  //@dump-sem-ir-begin\n  F(n);\n  G(n);\n  //@dump-sem-ir-end\n}\n\n// CHECK:STDOUT: --- call_basic_depth.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %C.Cfn.type: type = fn_type @C.Cfn [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %C.Cfn: %C.Cfn.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]\n// CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.643: <specific function> = specific_function %F, @F(%T) [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %H.specific_fn.965: <specific function> = specific_function %H, @H(%T) [symbolic]\n// CHECK:STDOUT:   %F.specific_fn.540: <specific function> = specific_function %F, @F(%C) [concrete]\n// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G, @G(%C) [concrete]\n// CHECK:STDOUT:   %H.specific_fn.d42: <specific function> = specific_function %H, @H(%C) [concrete]\n// CHECK:STDOUT:   %C.Cfn.specific_fn.f5e: <specific function> = specific_function %C.Cfn, @C.Cfn(%C) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc19_10.1: type = splice_block %.loc19_10.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc19_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc19_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc19_6.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @F.%T.loc19_6.1 (%T) = value_param call_param0\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc19_6.2 [symbolic = %T.loc19_6.1 (constants.%T)]\n// CHECK:STDOUT:     %x: @F.%T.loc19_6.1 (%T) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc19_6.2: type) {\n// CHECK:STDOUT:   %T.loc19_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc19_6.1 (constants.%T)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc19_6.1 [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc19_6.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%T.loc19_6.1 (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @H(%T.loc23_6.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %F.specific_fn.loc25_3.2: <specific function> = specific_function constants.%F, @F(%T.loc23_6.1) [symbolic = %F.specific_fn.loc25_3.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @H.%T.loc23_6.1 (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %x.ref: @H.%T.loc23_6.1 (%T) = name_ref x, %x\n// CHECK:STDOUT:     %F.specific_fn.loc25_3.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc25_3.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:     %F.call: init %empty_tuple.type = call %F.specific_fn.loc25_3.1(%x.ref)\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%T.loc29_6.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %H.specific_fn.loc31_3.2: <specific function> = specific_function constants.%H, @H(%T.loc29_6.1) [symbolic = %H.specific_fn.loc31_3.2 (constants.%H.specific_fn.965)]\n// CHECK:STDOUT:   %F.specific_fn.loc32_3.2: <specific function> = specific_function constants.%F, @F(%T.loc29_6.1) [symbolic = %F.specific_fn.loc32_3.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @G.%T.loc29_6.1 (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %H.ref: %H.type = name_ref H, file.%H.decl [concrete = constants.%H]\n// CHECK:STDOUT:     %x.ref.loc31: @G.%T.loc29_6.1 (%T) = name_ref x, %x\n// CHECK:STDOUT:     %H.specific_fn.loc31_3.1: <specific function> = specific_function %H.ref, @H(constants.%T) [symbolic = %H.specific_fn.loc31_3.2 (constants.%H.specific_fn.965)]\n// CHECK:STDOUT:     %H.call: init %empty_tuple.type = call %H.specific_fn.loc31_3.1(%x.ref.loc31)\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %x.ref.loc32: @G.%T.loc29_6.1 (%T) = name_ref x, %x\n// CHECK:STDOUT:     %F.specific_fn.loc32_3.1: <specific function> = specific_function %F.ref, @F(constants.%T) [symbolic = %F.specific_fn.loc32_3.2 (constants.%F.specific_fn.643)]\n// CHECK:STDOUT:     %F.call: init %empty_tuple.type = call %F.specific_fn.loc32_3.1(%x.ref.loc32)\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @M() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %n.ref.loc43: ref %C = name_ref n, %n\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.540]\n// CHECK:STDOUT:   %.loc43: %C = acquire_value %n.ref.loc43\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc43)\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %n.ref.loc44: ref %C = name_ref n, %n\n// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G.ref, @G(constants.%C) [concrete = constants.%G.specific_fn]\n// CHECK:STDOUT:   %.loc44: %C = acquire_value %n.ref.loc44\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.specific_fn(%.loc44)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc19_6.1 => constants.%T\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @H(constants.%T) {\n// CHECK:STDOUT:   %T.loc23_6.1 => constants.%T\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %F.specific_fn.loc25_3.2 => constants.%F.specific_fn.643\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%T) {\n// CHECK:STDOUT:   %T.loc29_6.1 => constants.%T\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C) {\n// CHECK:STDOUT:   %T.loc19_6.1 => constants.%C\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%C) {\n// CHECK:STDOUT:   %T.loc29_6.1 => constants.%C\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT:   %H.specific_fn.loc31_3.2 => constants.%H.specific_fn.d42\n// CHECK:STDOUT:   %F.specific_fn.loc32_3.2 => constants.%F.specific_fn.540\n// CHECK:STDOUT:   %C.Cfn.specific_fn.loc36_4.2 => constants.%C.Cfn.specific_fn.f5e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @H(constants.%C) {\n// CHECK:STDOUT:   %T.loc23_6.1 => constants.%C\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT:   %F.specific_fn.loc25_3.2 => constants.%F.specific_fn.540\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/generic/complete_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/complete_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/complete_type.carbon\n\n// --- fail_incomplete_in_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass B;\n\nclass A(T:! type) {\n  var v: T;\n}\n\n// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE+17]]:13: error: parameter has incomplete type `A(B)` in function definition [IncompleteTypeInFunctionParam]\n// CHECK:STDERR: fn F(unused x: A(B)) {}\n// CHECK:STDERR:             ^~~~~~~\n// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE-6]]:10: note: `T` evaluates to incomplete type `B` [IncompleteTypeInMonomorphization]\n// CHECK:STDERR:   var v: T;\n// CHECK:STDERR:          ^\n// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE-12]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class B;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE+7]]:13: error: parameter has incomplete type `A(B)` in function definition [IncompleteTypeInFunctionParam]\n// CHECK:STDERR: fn F(unused x: A(B)) {}\n// CHECK:STDERR:             ^~~~~~~\n// CHECK:STDERR: fail_incomplete_in_class.carbon:[[@LINE-19]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class B;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn F(unused x: A(B)) {}\n\nclass B {}\n\n// --- incomplete_in_function.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass B;\n\nfn F(T:! type, v: T*) {\n  *v;\n}\n\n// F(B) isn't resolved until the end of the file.\nfn G(p: B*) { F(B, p); }\n\nclass B {}\n\n// --- fail_incomplete_in_function_at_eof.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass B;\n\nfn F(T:! type, p: T*) {\n  let _: T = *p;\n}\n\n// CHECK:STDERR: fail_incomplete_in_function_at_eof.carbon:[[@LINE+10]]:15: error: unable to monomorphize specific `F(B)` [ResolvingSpecificHere]\n// CHECK:STDERR: fn G(p: B*) { F(B, p); }\n// CHECK:STDERR:               ^\n// CHECK:STDERR: fail_incomplete_in_function_at_eof.carbon:[[@LINE-6]]:10: note: `T` evaluates to incomplete type `B` [IncompleteTypeInMonomorphization]\n// CHECK:STDERR:   let _: T = *p;\n// CHECK:STDERR:          ^\n// CHECK:STDERR: fail_incomplete_in_function_at_eof.carbon:[[@LINE-12]]:1: note: class was forward declared here [ClassForwardDeclaredHere]\n// CHECK:STDERR: class B;\n// CHECK:STDERR: ^~~~~~~~\n// CHECK:STDERR:\nfn G(p: B*) { F(B, p); }\n\n// CHECK:STDOUT: --- fail_incomplete_in_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %A.type: type = generic_class_type @A [concrete]\n// CHECK:STDOUT:   %A.generic: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.95c: type = class_type @A, @A(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %A.elem.8a2: type = unbound_element_type %A.95c, %T [symbolic]\n// CHECK:STDOUT:   %struct_type.v.a4d: type = struct_type {.v: %T} [symbolic]\n// CHECK:STDOUT:   %complete_type.136: <witness> = complete_type_witness %struct_type.v.a4d [symbolic]\n// CHECK:STDOUT:   %A.764: type = class_type @A, @A(%B) [concrete]\n// CHECK:STDOUT:   %pattern_type.fa6: type = pattern_type %A.764 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.elem.46a: type = unbound_element_type %A.764, %B [concrete]\n// CHECK:STDOUT:   %struct_type.v.b74: type = struct_type {.v: %B} [concrete]\n// CHECK:STDOUT:   %complete_type.aac: <witness> = complete_type_witness %struct_type.v.b74 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .B = %B.decl.loc4\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %B.decl.loc4: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %A.decl: %A.type = class_decl @A [concrete = constants.%A.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_13.1: type = splice_block %.loc6_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_9.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.fa6 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.fa6 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %A.764 = value_param call_param0\n// CHECK:STDOUT:     %.loc27: type = splice_block %A [concrete = constants.%A.764] {\n// CHECK:STDOUT:       %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A.generic]\n// CHECK:STDOUT:       %B.ref: type = name_ref B, file.%B.decl.loc4 [concrete = constants.%B]\n// CHECK:STDOUT:       %A: type = class_type @A, @A(constants.%B) [concrete = constants.%A.764]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: %A.764 = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl.loc29: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @A(%T.loc6_9.2: type) {\n// CHECK:STDOUT:   %T.loc6_9.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc6_9.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %A: type = class_type @A, @A(%T.loc6_9.1) [symbolic = %A (constants.%A.95c)]\n// CHECK:STDOUT:   %A.elem: type = unbound_element_type %A, %T.loc6_9.1 [symbolic = %A.elem (constants.%A.elem.8a2)]\n// CHECK:STDOUT:   %struct_type.v: type = struct_type {.v: @A.%T.loc6_9.1 (%T)} [symbolic = %struct_type.v (constants.%struct_type.v.a4d)]\n// CHECK:STDOUT:   %complete_type.loc8_1.2: <witness> = complete_type_witness %struct_type.v [symbolic = %complete_type.loc8_1.2 (constants.%complete_type.136)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc6_9.2 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc7: @A.%A.elem (%A.elem.8a2) = field_decl v, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc8_1.1: <witness> = complete_type_witness constants.%struct_type.v.a4d [symbolic = %complete_type.loc8_1.2 (constants.%complete_type.136)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc8_1.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%A.95c\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .v = %.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%x.param: %A.764) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A(constants.%B) {\n// CHECK:STDOUT:   %T.loc6_9.1 => constants.%B\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => <error>\n// CHECK:STDOUT:   %A => constants.%A.764\n// CHECK:STDOUT:   %A.elem => constants.%A.elem.46a\n// CHECK:STDOUT:   %struct_type.v => constants.%struct_type.v.b74\n// CHECK:STDOUT:   %complete_type.loc8_1.2 => constants.%complete_type.aac\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- incomplete_in_function.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %ptr.27c: type = ptr_type %B [concrete]\n// CHECK:STDOUT:   %pattern_type.191: type = pattern_type %ptr.27c [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%B) [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %complete_type.04a: <witness> = complete_type_witness %ptr.27c [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .B = %B.decl.loc4\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %B.decl.loc4: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %v.patt: @F.%pattern_type (%pattern_type.4f4) = value_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.param_patt: @F.%pattern_type (%pattern_type.4f4) = value_param_pattern %v.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %v.param: @F.%ptr.loc6_20.1 (%ptr.e8f) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_20: type = splice_block %ptr.loc6_20.2 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)] {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:       %ptr.loc6_20.2: type = ptr_type %T.ref [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v: @F.%ptr.loc6_20.1 (%ptr.e8f) = value_binding v, %v.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.191 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.191 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %ptr.27c = value_param call_param0\n// CHECK:STDOUT:     %.loc11: type = splice_block %ptr [concrete = constants.%ptr.27c] {\n// CHECK:STDOUT:       %B.ref.loc11_9: type = name_ref B, file.%B.decl.loc4 [concrete = constants.%B]\n// CHECK:STDOUT:       %ptr: type = ptr_type %B.ref.loc11_9 [concrete = constants.%ptr.27c]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.27c = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl.loc13: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_6.2: type) {\n// CHECK:STDOUT:   %T.loc6_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc6_20.1: type = ptr_type %T.loc6_6.1 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %ptr.loc6_20.1 [symbolic = %pattern_type (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %ptr.loc6_20.1 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%v.param: @F.%ptr.loc6_20.1 (%ptr.e8f)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %v.ref: @F.%ptr.loc6_20.1 (%ptr.e8f) = name_ref v, %v\n// CHECK:STDOUT:     %.loc7: ref @F.%T.loc6_6.1 (%T) = deref %v.ref\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %ptr.27c) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %B.ref.loc11_17: type = name_ref B, file.%B.decl.loc4 [concrete = constants.%B]\n// CHECK:STDOUT:   %p.ref: %ptr.27c = name_ref p, %p\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%B) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn(%p.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%T\n// CHECK:STDOUT:   %ptr.loc6_20.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.4f4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%B) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%B\n// CHECK:STDOUT:   %ptr.loc6_20.1 => constants.%ptr.27c\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.191\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.04a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_incomplete_in_function_at_eof.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.4f4: type = pattern_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.ef1: <witness> = require_complete_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %ptr.27c: type = ptr_type %B [concrete]\n// CHECK:STDOUT:   %pattern_type.191: type = pattern_type %ptr.27c [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%B) [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %ptr.27c [concrete]\n// CHECK:STDOUT:   %pattern_type.1f4: type = pattern_type %B [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %B.decl: type = class_decl @B [concrete = constants.%B] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:     %p.patt: @F.%pattern_type.loc6 (%pattern_type.4f4) = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: @F.%pattern_type.loc6 (%pattern_type.4f4) = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6_10.1: type = splice_block %.loc6_10.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %p.param: @F.%ptr.loc6_20.1 (%ptr.e8f) = value_param call_param0\n// CHECK:STDOUT:     %.loc6_20: type = splice_block %ptr.loc6_20.2 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)] {\n// CHECK:STDOUT:       %T.ref.loc6: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:       %ptr.loc6_20.2: type = ptr_type %T.ref.loc6 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: @F.%ptr.loc6_20.1 (%ptr.e8f) = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.191 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.191 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %ptr.27c = value_param call_param0\n// CHECK:STDOUT:     %.loc20: type = splice_block %ptr [concrete = constants.%ptr.27c] {\n// CHECK:STDOUT:       %B.ref.loc20_9: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:       %ptr: type = ptr_type %B.ref.loc20_9 [concrete = constants.%ptr.27c]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr.27c = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B;\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_6.2: type) {\n// CHECK:STDOUT:   %T.loc6_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc6_20.1: type = ptr_type %T.loc6_6.1 [symbolic = %ptr.loc6_20.1 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %pattern_type.loc6: type = pattern_type %ptr.loc6_20.1 [symbolic = %pattern_type.loc6 (constants.%pattern_type.4f4)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6: <witness> = require_complete_type %ptr.loc6_20.1 [symbolic = %require_complete.loc6 (constants.%require_complete.ef1)]\n// CHECK:STDOUT:   %require_complete.loc7: <witness> = require_complete_type %T.loc6_6.1 [symbolic = %require_complete.loc7 (constants.%require_complete.944)]\n// CHECK:STDOUT:   %pattern_type.loc7: type = pattern_type %T.loc6_6.1 [symbolic = %pattern_type.loc7 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%p.param: @F.%ptr.loc6_20.1 (%ptr.e8f)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %_.patt: @F.%pattern_type.loc7 (%pattern_type.51d) = value_binding_pattern _ [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p.ref: @F.%ptr.loc6_20.1 (%ptr.e8f) = name_ref p, %p\n// CHECK:STDOUT:     %.loc7_14.1: ref @F.%T.loc6_6.1 (%T) = deref %p.ref\n// CHECK:STDOUT:     %T.ref.loc7: type = name_ref T, %T.loc6_6.2 [symbolic = %T.loc6_6.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc7_14.2: @F.%T.loc6_6.1 (%T) = acquire_value %.loc7_14.1\n// CHECK:STDOUT:     %_: @F.%T.loc6_6.1 (%T) = value_binding _, %.loc7_14.2\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%p.param: %ptr.27c) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %B.ref.loc20_17: type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %p.ref: %ptr.27c = name_ref p, %p\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%B) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn(%p.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%T\n// CHECK:STDOUT:   %ptr.loc6_20.1 => constants.%ptr.e8f\n// CHECK:STDOUT:   %pattern_type.loc6 => constants.%pattern_type.4f4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%B) {\n// CHECK:STDOUT:   %T.loc6_6.1 => constants.%B\n// CHECK:STDOUT:   %ptr.loc6_20.1 => constants.%ptr.27c\n// CHECK:STDOUT:   %pattern_type.loc6 => constants.%pattern_type.191\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc6 => constants.%complete_type\n// CHECK:STDOUT:   %require_complete.loc7 => <error>\n// CHECK:STDOUT:   %pattern_type.loc7 => constants.%pattern_type.1f4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/generic/dependent_param.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/dependent_param.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/dependent_param.carbon\n\n// --- nested_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Outer(T:! Core.Copy) {\n  class Inner(U:! T) {\n    //@dump-sem-ir-begin\n    fn Get() -> T { return U; }\n    //@dump-sem-ir-end\n  }\n}\n\n//@dump-sem-ir-begin\nvar n: i32 = Outer(i32).Inner(42).Get();\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- nested_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %T.035: %Copy.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Outer.type: type = generic_class_type @Outer [concrete]\n// CHECK:STDOUT:   %Outer.generic: %Outer.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Outer.4b9: type = class_type @Outer, @Outer(%T.035) [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.035 [symbolic]\n// CHECK:STDOUT:   %pattern_type.9b9f0c.2: type = pattern_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %U.959: %T.binding.as_type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %Inner.type.af4: type = generic_class_type @Inner, @Outer(%T.035) [symbolic]\n// CHECK:STDOUT:   %Inner.generic.994: %Inner.type.af4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Inner.c23: type = class_type @Inner, @Inner(%T.035, %U.959) [symbolic]\n// CHECK:STDOUT:   %.076a48.2: Core.Form = init_form %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Inner.Get.type.6ef: type = fn_type @Inner.Get, @Inner(%T.035, %U.959) [symbolic]\n// CHECK:STDOUT:   %Inner.Get.ba5: %Inner.Get.type.6ef = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.67c: <witness> = require_complete_type %T.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.58d: <witness> = lookup_impl_witness %T.035, @Copy [symbolic]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.735e75.2: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T.035) [symbolic]\n// CHECK:STDOUT:   %.023: type = fn_type_with_self_type %Copy.WithSelf.Op.type.735e75.2, %T.035 [symbolic]\n// CHECK:STDOUT:   %impl.elem0.594: %.023 = impl_witness_access %Copy.lookup_impl_witness.58d, element0 [symbolic]\n// CHECK:STDOUT:   %specific_impl_fn.bdc: <specific function> = specific_impl_function %impl.elem0.594, @Copy.WithSelf.Op(%T.035) [symbolic]\n// CHECK:STDOUT:   %bound_method.068: <bound method> = bound_method %U.959, %impl.elem0.594 [symbolic]\n// CHECK:STDOUT:   %bound_method.d5d: <bound method> = bound_method %U.959, %specific_impl_fn.bdc [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Outer.a6c: type = class_type @Outer, @Outer(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %Inner.type.518: type = generic_class_type @Inner, @Outer(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %Inner.generic.887: %Inner.type.518 = struct_value () [concrete]\n// CHECK:STDOUT:   %int_42.20e: Core.IntLiteral = int_value 42 [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.006: <witness> = impl_witness imports.%Copy.impl_witness_table.b6d [concrete]\n// CHECK:STDOUT:   %Copy.facet.cdd: %Copy.type = facet_value Core.IntLiteral, (%Copy.impl_witness.006) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_42.20e, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.cb9: <bound method> = bound_method %int_42.20e, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_42.c68: %i32 = int_value 42 [concrete]\n// CHECK:STDOUT:   %Inner.e4a: type = class_type @Inner, @Inner(%Copy.facet.de4, %int_42.c68) [concrete]\n// CHECK:STDOUT:   %Inner.Get.type.20d: type = fn_type @Inner.Get, @Inner(%Copy.facet.de4, %int_42.c68) [concrete]\n// CHECK:STDOUT:   %Inner.Get.f96: %Inner.Get.type.20d = struct_value () [concrete]\n// CHECK:STDOUT:   %Inner.Get.specific_fn: <specific function> = specific_function %Inner.Get.f96, @Inner.Get(%Copy.facet.de4, %int_42.c68) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.bound: <bound method> = bound_method %int_42.c68, %Int.as.Copy.impl.Op.664 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.d85: <bound method> = bound_method %int_42.c68, %Int.as.Copy.impl.Op.specific_fn [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.bb6 = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Copy.impl_witness_table.b6d = impl_witness_table (%Core.import_ref.bb6), @Core.IntLiteral.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = ref_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.var_patt: %pattern_type.7ce = var_pattern %n.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %n.var: ref %i32 = var %n.var_patt [concrete]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %n: ref %i32 = ref_binding n, %n.var [concrete = %n.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Outer(%T.loc4_13.2: %Copy.type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Outer.4b9\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .Inner = %Inner.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @Inner(@Outer.%T.loc4_13.2: %Copy.type, %U.loc5_15.2: @Inner.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.Get.type: type = fn_type @Inner.Get, @Inner(%T, %U.loc5_15.1) [symbolic = %Inner.Get.type (constants.%Inner.Get.type.6ef)]\n// CHECK:STDOUT:   %Inner.Get: @Inner.%Inner.Get.type (%Inner.Get.type.6ef) = struct_value () [symbolic = %Inner.Get (constants.%Inner.Get.ba5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %Inner.Get.decl: @Inner.%Inner.Get.type (%Inner.Get.type.6ef) = fn_decl @Inner.Get [symbolic = @Inner.%Inner.Get (constants.%Inner.Get.ba5)] {\n// CHECK:STDOUT:       %return.patt: @Inner.Get.%pattern_type (%pattern_type.9b9f0c.2) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @Inner.Get.%pattern_type (%pattern_type.9b9f0c.2) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: %Copy.type = name_ref T, @Outer.%T.loc4_13.2 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:       %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc7_17.3: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:       %.loc7_17.4: Core.Form = init_form %.loc7_17.3 [symbolic = %.loc7_17.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:       %return.param: ref @Inner.Get.%T.binding.as_type (%T.binding.as_type) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @Inner.Get.%T.binding.as_type (%T.binding.as_type) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%Inner.c23\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .Get = %Inner.Get.decl\n// CHECK:STDOUT:     .U = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Inner.Get(@Outer.%T.loc4_13.2: %Copy.type, @Inner.%U.loc5_15.2: @Inner.%T.binding.as_type (%T.binding.as_type)) {\n// CHECK:STDOUT:   %T: %Copy.type = symbolic_binding T, 0 [symbolic = %T (constants.%T.035)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %.loc7_17.2: Core.Form = init_form %T.binding.as_type [symbolic = %.loc7_17.2 (constants.%.076a48.2)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.9b9f0c.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [symbolic = %require_complete (constants.%require_complete.67c)]\n// CHECK:STDOUT:   %U: @Inner.Get.%T.binding.as_type (%T.binding.as_type) = symbolic_binding U, 1 [symbolic = %U (constants.%U.959)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Copy [symbolic = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.58d)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%T) [symbolic = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.735e75.2)]\n// CHECK:STDOUT:   %.loc7_28: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %T [symbolic = %.loc7_28 (constants.%.023)]\n// CHECK:STDOUT:   %impl.elem0.loc7_28.2: @Inner.Get.%.loc7_28 (%.023) = impl_witness_access %Copy.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc7_28.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:   %bound_method.loc7_28.3: <bound method> = bound_method %U, %impl.elem0.loc7_28.2 [symbolic = %bound_method.loc7_28.3 (constants.%bound_method.068)]\n// CHECK:STDOUT:   %specific_impl_fn.loc7_28.2: <specific function> = specific_impl_function %impl.elem0.loc7_28.2, @Copy.WithSelf.Op(%T) [symbolic = %specific_impl_fn.loc7_28.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:   %bound_method.loc7_28.4: <bound method> = bound_method %U, %specific_impl_fn.loc7_28.2 [symbolic = %bound_method.loc7_28.4 (constants.%bound_method.d5d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @Inner.Get.%T.binding.as_type (%T.binding.as_type) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %U.ref: @Inner.Get.%T.binding.as_type (%T.binding.as_type) = name_ref U, @Inner.%U.loc5_15.2 [symbolic = %U (constants.%U.959)]\n// CHECK:STDOUT:     %impl.elem0.loc7_28.1: @Inner.Get.%.loc7_28 (%.023) = impl_witness_access constants.%Copy.lookup_impl_witness.58d, element0 [symbolic = %impl.elem0.loc7_28.2 (constants.%impl.elem0.594)]\n// CHECK:STDOUT:     %bound_method.loc7_28.1: <bound method> = bound_method %U.ref, %impl.elem0.loc7_28.1 [symbolic = %bound_method.loc7_28.3 (constants.%bound_method.068)]\n// CHECK:STDOUT:     %specific_impl_fn.loc7_28.1: <specific function> = specific_impl_function %impl.elem0.loc7_28.1, @Copy.WithSelf.Op(constants.%T.035) [symbolic = %specific_impl_fn.loc7_28.2 (constants.%specific_impl_fn.bdc)]\n// CHECK:STDOUT:     %bound_method.loc7_28.2: <bound method> = bound_method %U.ref, %specific_impl_fn.loc7_28.1 [symbolic = %bound_method.loc7_28.4 (constants.%bound_method.d5d)]\n// CHECK:STDOUT:     %.loc7_17.1: ref @Inner.Get.%T.binding.as_type (%T.binding.as_type) = splice_block %return.param {}\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @Inner.Get.%T.binding.as_type (%T.binding.as_type) to %.loc7_17.1 = call %bound_method.loc7_28.2(%U.ref)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Outer.ref: %Outer.type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer.generic]\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %Copy.facet.loc13_23: %Copy.type = facet_value %i32, (constants.%Copy.impl_witness.f17) [concrete = constants.%Copy.facet.de4]\n// CHECK:STDOUT:   %.loc13_23: %Copy.type = converted %i32, %Copy.facet.loc13_23 [concrete = constants.%Copy.facet.de4]\n// CHECK:STDOUT:   %Outer: type = class_type @Outer, @Outer(constants.%Copy.facet.de4) [concrete = constants.%Outer.a6c]\n// CHECK:STDOUT:   %.loc13_24: %Inner.type.518 = specific_constant @Outer.%Inner.decl, @Outer(constants.%Copy.facet.de4) [concrete = constants.%Inner.generic.887]\n// CHECK:STDOUT:   %Inner.ref: %Inner.type.518 = name_ref Inner, %.loc13_24 [concrete = constants.%Inner.generic.887]\n// CHECK:STDOUT:   %int_42: Core.IntLiteral = int_value 42 [concrete = constants.%int_42.20e]\n// CHECK:STDOUT:   %Copy.facet.loc13_33: %Copy.type = facet_value Core.IntLiteral, (constants.%Copy.impl_witness.006) [concrete = constants.%Copy.facet.cdd]\n// CHECK:STDOUT:   %.loc13_33.1: %Copy.type = converted Core.IntLiteral, %Copy.facet.loc13_33 [concrete = constants.%Copy.facet.cdd]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc13_33.1: <bound method> = bound_method constants.%int_42.20e, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc13_33.2: <bound method> = bound_method constants.%int_42.20e, %specific_fn [concrete = constants.%bound_method.cb9]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc13_33.2(constants.%int_42.20e) [concrete = constants.%int_42.c68]\n// CHECK:STDOUT:   %.loc13_33.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_42.c68]\n// CHECK:STDOUT:   %.loc13_33.3: %i32 = converted constants.%int_42.20e, %.loc13_33.2 [concrete = constants.%int_42.c68]\n// CHECK:STDOUT:   %Inner: type = class_type @Inner, @Inner(constants.%Copy.facet.de4, constants.%int_42.c68) [concrete = constants.%Inner.e4a]\n// CHECK:STDOUT:   %.loc13_34: %Inner.Get.type.20d = specific_constant @Inner.%Inner.Get.decl, @Inner(constants.%Copy.facet.de4, constants.%int_42.c68) [concrete = constants.%Inner.Get.f96]\n// CHECK:STDOUT:   %Get.ref: %Inner.Get.type.20d = name_ref Get, %.loc13_34 [concrete = constants.%Inner.Get.f96]\n// CHECK:STDOUT:   %Inner.Get.specific_fn: <specific function> = specific_function %Get.ref, @Inner.Get(constants.%Copy.facet.de4, constants.%int_42.c68) [concrete = constants.%Inner.Get.specific_fn]\n// CHECK:STDOUT:   %Inner.Get.call: init %i32 = call %Inner.Get.specific_fn()\n// CHECK:STDOUT:   assign file.%n.var, %Inner.Get.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%T.035) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T.035\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.af4\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.994\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%T.035, constants.%U.959) {\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %U.loc5_15.1 => constants.%U.959\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.Get.type => constants.%Inner.Get.type.6ef\n// CHECK:STDOUT:   %Inner.Get => constants.%Inner.Get.ba5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.Get(constants.%T.035, constants.%U.959) {\n// CHECK:STDOUT:   %T => constants.%T.035\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %.loc7_17.2 => constants.%.076a48.2\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9b9f0c.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Outer(constants.%Copy.facet.de4) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%Copy.facet.de4\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.type => constants.%Inner.type.518\n// CHECK:STDOUT:   %Inner.generic => constants.%Inner.generic.887\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner(constants.%Copy.facet.de4, constants.%int_42.c68) {\n// CHECK:STDOUT:   %T => constants.%Copy.facet.de4\n// CHECK:STDOUT:   %T.binding.as_type => constants.%i32\n// CHECK:STDOUT:   %U.loc5_15.1 => constants.%int_42.c68\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7ce\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Inner.Get.type => constants.%Inner.Get.type.20d\n// CHECK:STDOUT:   %Inner.Get => constants.%Inner.Get.f96\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Inner.Get(constants.%Copy.facet.de4, constants.%int_42.c68) {\n// CHECK:STDOUT:   %T => constants.%Copy.facet.de4\n// CHECK:STDOUT:   %T.binding.as_type => constants.%i32\n// CHECK:STDOUT:   %.loc7_17.2 => constants.%.ff5\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7ce\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %U => constants.%int_42.c68\n// CHECK:STDOUT:   %Copy.lookup_impl_witness => constants.%Copy.impl_witness.f17\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type => constants.%Copy.WithSelf.Op.type.081\n// CHECK:STDOUT:   %.loc7_28 => constants.%.8e2\n// CHECK:STDOUT:   %impl.elem0.loc7_28.2 => constants.%Int.as.Copy.impl.Op.664\n// CHECK:STDOUT:   %bound_method.loc7_28.3 => constants.%Int.as.Copy.impl.Op.bound\n// CHECK:STDOUT:   %specific_impl_fn.loc7_28.2 => constants.%Int.as.Copy.impl.Op.specific_fn\n// CHECK:STDOUT:   %bound_method.loc7_28.4 => constants.%bound_method.d85\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/generic/dot_self_symbolic_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/dot_self_symbolic_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/dot_self_symbolic_type.carbon\n\n// --- fail_dot_self_symbolic_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A(AA:! type) { let X:! type; }\n\nclass C(CC:! type) {\n  //@dump-sem-ir-begin\n  // The `.Self` bind_symbolic_name here should have a\n  // symbolic constant value, not symbolic_self, because\n  // its type depends on `CC`.\n  fn F(unused T:! A(CC) where .X = CC) {}\n  //@dump-sem-ir-end\n}\n\nclass D(DD:! type) {\n  fn G(T:! type) {\n    //@dump-sem-ir-begin\n    // CHECK:STDERR: fail_dot_self_symbolic_type.carbon:[[@LINE+7]]:5: error: cannot convert type `T` into type implementing `A(DD) where .(A(DD).X) = DD` [ConversionFailureTypeToFacet]\n    // CHECK:STDERR:     C(DD).F(T);\n    // CHECK:STDERR:     ^~~~~~~~~~\n    // CHECK:STDERR: fail_dot_self_symbolic_type.carbon:[[@LINE-10]]:3: note: while deducing parameters of generic declared here [DeductionGenericHere]\n    // CHECK:STDERR:   fn F(unused T:! A(CC) where .X = CC) {}\n    // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    C(DD).F(T);\n    //@dump-sem-ir-end\n  }\n}\n\nfn H(T:! type) {\n  D({}).G(T);\n}\n\n// --- dot_self_symbolic_in_impl_lookup.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A(AA:! type) { let X:! type; }\n\ninterface B(AA:! type) {}\n\n//@dump-sem-ir-begin\nimpl forall [AA:! type, BB:! A(AA) where .X = ()] BB as B(AA*) {}\n//@dump-sem-ir-end\n\nimpl forall [AA:! type, BB:! type] BB as B(AA) {}\n\nclass D(DD:! type) {\n  fn G(T:! type) {\n    // TODO: This produces a `lookup_impl_witness` instruction looking\n    // for `.Self` as `A(DD)` in the generic eval block for `G`. That\n    // is from an impl we ended up not using, so shouldn't be included\n    // in the eval block.\n    //@dump-sem-ir-begin\n    T as B(DD*);\n    //@dump-sem-ir-end\n  }\n}\n\nfn H(T:! type) {\n  D({}).G(T);\n}\n\n// CHECK:STDOUT: --- fail_dot_self_symbolic_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type.464: type = generic_interface_type @A [concrete]\n// CHECK:STDOUT:   %A.generic: %A.type.464 = struct_value () [concrete]\n// CHECK:STDOUT:   %CC: type = symbolic_binding CC, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3350.1: type = class_type @C, @C(%CC) [symbolic]\n// CHECK:STDOUT:   %A.type.ade3d9.2: type = facet_type <@A, @A(%CC)> [symbolic]\n// CHECK:STDOUT:   %.Self.660472.1: %A.type.ade3d9.2 = symbolic_binding .Self [symbolic]\n// CHECK:STDOUT:   %A.assoc_type.9f4820.2: type = assoc_entity_type @A, @A(%CC) [symbolic]\n// CHECK:STDOUT:   %assoc0.9fa860.2: %A.assoc_type.9f4820.2 = assoc_entity element0, @A.WithSelf.%X [symbolic]\n// CHECK:STDOUT:   %require_complete.f58: <witness> = require_complete_type %A.type.ade3d9.2 [symbolic]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.660472.1 [symbolic]\n// CHECK:STDOUT:   %A.lookup_impl_witness.04abbb.1: <witness> = lookup_impl_witness %.Self.660472.1, @A, @A(%CC) [symbolic]\n// CHECK:STDOUT:   %impl.elem0.f51d29.1: type = impl_witness_access %A.lookup_impl_witness.04abbb.1, element0 [symbolic]\n// CHECK:STDOUT:   %A_where.type.4028e0.1: type = facet_type <@A, @A(%CC) where %impl.elem0.f51d29.1 = %CC> [symbolic]\n// CHECK:STDOUT:   %pattern_type.1d5: type = pattern_type %A_where.type.4028e0.1 [symbolic]\n// CHECK:STDOUT:   %T.6c0: %A_where.type.4028e0.1 = symbolic_binding T, 1 [symbolic]\n// CHECK:STDOUT:   %C.F.type.1f899e.1: type = fn_type @C.F, @C(%CC) [symbolic]\n// CHECK:STDOUT:   %C.F.faeec9.1: %C.F.type.1f899e.1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %DD: type = symbolic_binding DD, 0 [symbolic]\n// CHECK:STDOUT:   %D.bd6: type = class_type @D, @D(%DD) [symbolic]\n// CHECK:STDOUT:   %T.091: type = symbolic_binding T, 1 [symbolic]\n// CHECK:STDOUT:   %D.G.type.49d: type = fn_type @D.G, @D(%DD) [symbolic]\n// CHECK:STDOUT:   %D.G.891: %D.G.type.49d = struct_value () [symbolic]\n// CHECK:STDOUT:   %C.5a3350.2: type = class_type @C, @C(%DD) [symbolic]\n// CHECK:STDOUT:   %C.F.type.1f899e.2: type = fn_type @C.F, @C(%DD) [symbolic]\n// CHECK:STDOUT:   %C.F.faeec9.2: %C.F.type.1f899e.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete.32c: <witness> = require_complete_type %C.5a3350.2 [symbolic]\n// CHECK:STDOUT:   %A.type.ade3d9.3: type = facet_type <@A, @A(%DD)> [symbolic]\n// CHECK:STDOUT:   %.Self.660472.2: %A.type.ade3d9.3 = symbolic_binding .Self [symbolic]\n// CHECK:STDOUT:   %A.lookup_impl_witness.04abbb.2: <witness> = lookup_impl_witness %.Self.660472.2, @A, @A(%DD) [symbolic]\n// CHECK:STDOUT:   %impl.elem0.f51d29.2: type = impl_witness_access %A.lookup_impl_witness.04abbb.2, element0 [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %D.G.type.235: type = fn_type @D.G, @D(%empty_struct_type) [concrete]\n// CHECK:STDOUT:   %D.G.be1: %D.G.type.235 = struct_value () [concrete]\n// CHECK:STDOUT:   %C.850: type = class_type @C, @C(%empty_struct_type) [concrete]\n// CHECK:STDOUT:   %C.F.type.3ff: type = fn_type @C.F, @C(%empty_struct_type) [concrete]\n// CHECK:STDOUT:   %C.F.240: %C.F.type.3ff = struct_value () [concrete]\n// CHECK:STDOUT:   %A.type.69e: type = facet_type <@A, @A(%empty_struct_type)> [concrete]\n// CHECK:STDOUT:   %.Self.f50: %A.type.69e = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %A.lookup_impl_witness.219: <witness> = lookup_impl_witness %.Self.f50, @A, @A(%empty_struct_type) [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0.d97: type = impl_witness_access %A.lookup_impl_witness.219, element0 [symbolic_self]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%CC.loc6_9.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F, @C(%CC.loc6_9.1) [symbolic = %C.F.type (constants.%C.F.type.1f899e.1)]\n// CHECK:STDOUT:   %C.F: @C.%C.F.type (%C.F.type.1f899e.1) = struct_value () [symbolic = %C.F (constants.%C.F.faeec9.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %C.F.decl: @C.%C.F.type (%C.F.type.1f899e.1) = fn_decl @C.F [symbolic = @C.%C.F (constants.%C.F.faeec9.1)] {\n// CHECK:STDOUT:       %T.patt: @C.F.%pattern_type (%pattern_type.1d5) = symbolic_binding_pattern T, 1 [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc11_25.1: type = splice_block %.loc11_25.2 [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)] {\n// CHECK:STDOUT:         <elided>\n// CHECK:STDOUT:         %A.ref: %A.type.464 = name_ref A, file.%A.decl [concrete = constants.%A.generic]\n// CHECK:STDOUT:         %CC.ref.loc11_21: type = name_ref CC, @C.%CC.loc6_9.2 [symbolic = %CC (constants.%CC)]\n// CHECK:STDOUT:         %A.type.loc11_23.2: type = facet_type <@A, @A(constants.%CC)> [symbolic = %A.type.loc11_23.1 (constants.%A.type.ade3d9.2)]\n// CHECK:STDOUT:         <elided>\n// CHECK:STDOUT:         %.Self.ref: @C.F.%A.type.loc11_23.1 (%A.type.ade3d9.2) = name_ref .Self, %.Self.3 [symbolic = %.Self.1 (constants.%.Self.660472.1)]\n// CHECK:STDOUT:         %.Self.as_type: type = facet_access_type %.Self.ref [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]\n// CHECK:STDOUT:         %.loc11_31.1: type = converted %.Self.ref, %.Self.as_type [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]\n// CHECK:STDOUT:         %.loc11_31.2: @C.F.%A.assoc_type (%A.assoc_type.9f4820.2) = specific_constant @X.%assoc0, @A.WithSelf(constants.%CC, constants.%.Self.660472.1) [symbolic = %assoc0 (constants.%assoc0.9fa860.2)]\n// CHECK:STDOUT:         %X.ref: @C.F.%A.assoc_type (%A.assoc_type.9f4820.2) = name_ref X, %.loc11_31.2 [symbolic = %assoc0 (constants.%assoc0.9fa860.2)]\n// CHECK:STDOUT:         %impl.elem0.loc11_31.2: type = impl_witness_access constants.%A.lookup_impl_witness.04abbb.1, element0 [symbolic = %impl.elem0.loc11_31.1 (constants.%impl.elem0.f51d29.1)]\n// CHECK:STDOUT:         %CC.ref.loc11_36: type = name_ref CC, @C.%CC.loc6_9.2 [symbolic = %CC (constants.%CC)]\n// CHECK:STDOUT:         %.loc11_25.2: type = where_expr %.Self.3 [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)] {\n// CHECK:STDOUT:           requirement_base_facet_type constants.%A.type.ade3d9.2\n// CHECK:STDOUT:           requirement_rewrite %impl.elem0.loc11_31.2, %CC.ref.loc11_36\n// CHECK:STDOUT:         }\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %T.loc11_15.2: @C.F.%A_where.type (%A_where.type.4028e0.1) = symbolic_binding T, 1 [symbolic = %T.loc11_15.1 (constants.%T.6c0)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3350.1\n// CHECK:STDOUT:     .A = <poisoned>\n// CHECK:STDOUT:     .CC = <poisoned>\n// CHECK:STDOUT:     .F = %C.F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @D(%DD.loc15_9.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%D.bd6\n// CHECK:STDOUT:     .G = %D.G.decl\n// CHECK:STDOUT:     .C = <poisoned>\n// CHECK:STDOUT:     .DD = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @C.F(@C.%CC.loc6_9.2: type, %T.loc11_15.2: @C.F.%A_where.type (%A_where.type.4028e0.1)) {\n// CHECK:STDOUT:   %CC: type = symbolic_binding CC, 0 [symbolic = %CC (constants.%CC)]\n// CHECK:STDOUT:   %A.type.loc11_23.1: type = facet_type <@A, @A(%CC)> [symbolic = %A.type.loc11_23.1 (constants.%A.type.ade3d9.2)]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %A.type.loc11_23.1 [symbolic = %require_complete (constants.%require_complete.f58)]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.1 [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]\n// CHECK:STDOUT:   %A.assoc_type: type = assoc_entity_type @A, @A(%CC) [symbolic = %A.assoc_type (constants.%A.assoc_type.9f4820.2)]\n// CHECK:STDOUT:   %assoc0: @C.F.%A.assoc_type (%A.assoc_type.9f4820.2) = assoc_entity element0, @A.WithSelf.%X [symbolic = %assoc0 (constants.%assoc0.9fa860.2)]\n// CHECK:STDOUT:   %A.lookup_impl_witness: <witness> = lookup_impl_witness %.Self.1, @A, @A(%CC) [symbolic = %A.lookup_impl_witness (constants.%A.lookup_impl_witness.04abbb.1)]\n// CHECK:STDOUT:   %impl.elem0.loc11_31.1: type = impl_witness_access %A.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc11_31.1 (constants.%impl.elem0.f51d29.1)]\n// CHECK:STDOUT:   %A_where.type: type = facet_type <@A, @A(%CC) where %impl.elem0.loc11_31.1 = %CC> [symbolic = %A_where.type (constants.%A_where.type.4028e0.1)]\n// CHECK:STDOUT:   %T.loc11_15.1: @C.F.%A_where.type (%A_where.type.4028e0.1) = symbolic_binding T, 1 [symbolic = %T.loc11_15.1 (constants.%T.6c0)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %A_where.type [symbolic = %pattern_type (constants.%pattern_type.1d5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @D.G(@D.%DD.loc15_9.2: type, %T.loc16_8.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %DD: type = symbolic_binding DD, 0 [symbolic = %DD (constants.%DD)]\n// CHECK:STDOUT:   %C.loc25_9.2: type = class_type @C, @C(%DD) [symbolic = %C.loc25_9.2 (constants.%C.5a3350.2)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %C.loc25_9.2 [symbolic = %require_complete (constants.%require_complete.32c)]\n// CHECK:STDOUT:   %C.F.type: type = fn_type @C.F, @C(%DD) [symbolic = %C.F.type (constants.%C.F.type.1f899e.2)]\n// CHECK:STDOUT:   %C.F: @D.G.%C.F.type (%C.F.type.1f899e.2) = struct_value () [symbolic = %C.F (constants.%C.F.faeec9.2)]\n// CHECK:STDOUT:   %A.type: type = facet_type <@A, @A(%DD)> [symbolic = %A.type (constants.%A.type.ade3d9.3)]\n// CHECK:STDOUT:   %.Self.loc11: @D.G.%A.type (%A.type.ade3d9.3) = symbolic_binding .Self [symbolic = %.Self.loc11 (constants.%.Self.660472.2)]\n// CHECK:STDOUT:   %A.lookup_impl_witness: <witness> = lookup_impl_witness %.Self.loc11, @A, @A(%DD) [symbolic = %A.lookup_impl_witness (constants.%A.lookup_impl_witness.04abbb.2)]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %A.lookup_impl_witness, element0 [symbolic = %impl.elem0 (constants.%impl.elem0.f51d29.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %C.ref: %C.type = name_ref C, file.%C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %DD.ref: type = name_ref DD, @D.%DD.loc15_9.2 [symbolic = %DD (constants.%DD)]\n// CHECK:STDOUT:     %C.loc25_9.1: type = class_type @C, @C(constants.%DD) [symbolic = %C.loc25_9.2 (constants.%C.5a3350.2)]\n// CHECK:STDOUT:     %.loc25: @D.G.%C.F.type (%C.F.type.1f899e.2) = specific_constant @C.%C.F.decl, @C(constants.%DD) [symbolic = %C.F (constants.%C.F.faeec9.2)]\n// CHECK:STDOUT:     %F.ref: @D.G.%C.F.type (%C.F.type.1f899e.2) = name_ref F, %.loc25 [symbolic = %C.F (constants.%C.F.faeec9.2)]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc16_8.2 [symbolic = %T.loc16_8.1 (constants.%T.091)]\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%CC) {\n// CHECK:STDOUT:   %CC.loc6_9.1 => constants.%CC\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.F.type => constants.%C.F.type.1f899e.1\n// CHECK:STDOUT:   %C.F => constants.%C.F.faeec9.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.F(constants.%CC, constants.%T.6c0) {\n// CHECK:STDOUT:   %CC => constants.%CC\n// CHECK:STDOUT:   %A.type.loc11_23.1 => constants.%A.type.ade3d9.2\n// CHECK:STDOUT:   %.Self.1 => constants.%.Self.660472.1\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.f58\n// CHECK:STDOUT:   %.Self.binding.as_type => constants.%.Self.binding.as_type\n// CHECK:STDOUT:   %A.assoc_type => constants.%A.assoc_type.9f4820.2\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.9fa860.2\n// CHECK:STDOUT:   %A.lookup_impl_witness => constants.%A.lookup_impl_witness.04abbb.1\n// CHECK:STDOUT:   %impl.elem0.loc11_31.1 => constants.%impl.elem0.f51d29.1\n// CHECK:STDOUT:   %A_where.type => constants.%A_where.type.4028e0.1\n// CHECK:STDOUT:   %T.loc11_15.1 => constants.%T.6c0\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.1d5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D(constants.%DD) {\n// CHECK:STDOUT:   %DD.loc15_9.1 => constants.%DD\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %D.G.type => constants.%D.G.type.49d\n// CHECK:STDOUT:   %D.G => constants.%D.G.891\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.G(constants.%DD, constants.%T.091) {\n// CHECK:STDOUT:   %T.loc16_8.1 => constants.%T.091\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%DD) {\n// CHECK:STDOUT:   %CC.loc6_9.1 => constants.%DD\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.F.type => constants.%C.F.type.1f899e.2\n// CHECK:STDOUT:   %C.F => constants.%C.F.faeec9.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %DD.loc15_9.1 => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %D.G.type => constants.%D.G.type.235\n// CHECK:STDOUT:   %D.G => constants.%D.G.be1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.G(constants.%empty_struct_type, constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc16_8.1 => constants.%T.67d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %DD => constants.%empty_struct_type\n// CHECK:STDOUT:   %C.loc25_9.2 => constants.%C.850\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT:   %C.F.type => constants.%C.F.type.3ff\n// CHECK:STDOUT:   %C.F => constants.%C.F.240\n// CHECK:STDOUT:   %A.type => constants.%A.type.69e\n// CHECK:STDOUT:   %.Self.loc11 => constants.%.Self.f50\n// CHECK:STDOUT:   %A.lookup_impl_witness => constants.%A.lookup_impl_witness.219\n// CHECK:STDOUT:   %impl.elem0 => constants.%impl.elem0.d97\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %CC.loc6_9.1 => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.F.type => constants.%C.F.type.3ff\n// CHECK:STDOUT:   %C.F => constants.%C.F.240\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- dot_self_symbolic_in_impl_lookup.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %AA: type = symbolic_binding AA, 0 [symbolic]\n// CHECK:STDOUT:   %A.type.464: type = generic_interface_type @A [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %A.generic: %A.type.464 = struct_value () [concrete]\n// CHECK:STDOUT:   %A.type.ade3d9.1: type = facet_type <@A, @A(%AA)> [symbolic]\n// CHECK:STDOUT:   %A.assoc_type: type = assoc_entity_type @A, @A(%AA) [symbolic]\n// CHECK:STDOUT:   %assoc0: %A.assoc_type = assoc_entity element0, @A.WithSelf.%X [symbolic]\n// CHECK:STDOUT:   %B.type.5ae: type = generic_interface_type @B [concrete]\n// CHECK:STDOUT:   %B.generic: %B.type.5ae = struct_value () [concrete]\n// CHECK:STDOUT:   %.Self.660472.1: %A.type.ade3d9.1 = symbolic_binding .Self [symbolic]\n// CHECK:STDOUT:   %require_complete.f58: <witness> = require_complete_type %A.type.ade3d9.1 [symbolic]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.660472.1 [symbolic]\n// CHECK:STDOUT:   %A.lookup_impl_witness.04abbb.1: <witness> = lookup_impl_witness %.Self.660472.1, @A, @A(%AA) [symbolic]\n// CHECK:STDOUT:   %impl.elem0.f51d29.1: type = impl_witness_access %A.lookup_impl_witness.04abbb.1, element0 [symbolic]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %A_where.type.29f165.1: type = facet_type <@A, @A(%AA) where %impl.elem0.f51d29.1 = %empty_tuple.type> [symbolic]\n// CHECK:STDOUT:   %pattern_type.12a: type = pattern_type %A_where.type.29f165.1 [symbolic]\n// CHECK:STDOUT:   %BB.0b1: %A_where.type.29f165.1 = symbolic_binding BB, 1 [symbolic]\n// CHECK:STDOUT:   %BB.binding.as_type: type = symbolic_binding_type BB, 1, %BB.0b1 [symbolic]\n// CHECK:STDOUT:   %ptr.e8f8f9.1: type = ptr_type %AA [symbolic]\n// CHECK:STDOUT:   %B.type.abcc5d.1: type = facet_type <@B, @B(%ptr.e8f8f9.1)> [symbolic]\n// CHECK:STDOUT:   %B.impl_witness.bef: <witness> = impl_witness @BB.binding.as_type.as.B.impl.%B.impl_witness_table, @BB.binding.as_type.as.B.impl(%AA, %BB.0b1) [symbolic]\n// CHECK:STDOUT:   %require_complete.fe18c9.1: <witness> = require_complete_type %B.type.abcc5d.1 [symbolic]\n// CHECK:STDOUT:   %DD: type = symbolic_binding DD, 0 [symbolic]\n// CHECK:STDOUT:   %D.bd6: type = class_type @D, @D(%DD) [symbolic]\n// CHECK:STDOUT:   %T.091: type = symbolic_binding T, 1 [symbolic]\n// CHECK:STDOUT:   %D.G.type.49d: type = fn_type @D.G, @D(%DD) [symbolic]\n// CHECK:STDOUT:   %D.G.891: %D.G.type.49d = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %ptr.e8f8f9.2: type = ptr_type %DD [symbolic]\n// CHECK:STDOUT:   %B.type.abcc5d.2: type = facet_type <@B, @B(%ptr.e8f8f9.2)> [symbolic]\n// CHECK:STDOUT:   %.77d: require_specific_def_type = require_specific_def @BB.as.B.impl(%ptr.e8f8f9.2, %T.091) [symbolic]\n// CHECK:STDOUT:   %B.lookup_impl_witness.52c: <witness> = lookup_impl_witness %T.091, @B, @B(%ptr.e8f8f9.2) [symbolic]\n// CHECK:STDOUT:   %B.facet.b5c: %B.type.abcc5d.2 = facet_value %T.091, (%B.lookup_impl_witness.52c) [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %D.G.type.235: type = fn_type @D.G, @D(%empty_struct_type) [concrete]\n// CHECK:STDOUT:   %D.G.be1: %D.G.type.235 = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.c28: type = ptr_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %B.type.a69: type = facet_type <@B, @B(%ptr.c28)> [concrete]\n// CHECK:STDOUT:   %.5ef: require_specific_def_type = require_specific_def @BB.as.B.impl(%ptr.c28, %T.67d) [symbolic]\n// CHECK:STDOUT:   %B.lookup_impl_witness.eb0: <witness> = lookup_impl_witness %T.67d, @B, @B(%ptr.c28) [symbolic]\n// CHECK:STDOUT:   %B.facet.4b0: %B.type.a69 = facet_value %T.67d, (%B.lookup_impl_witness.eb0) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   impl_decl @BB.binding.as_type.as.B.impl [concrete] {\n// CHECK:STDOUT:     %AA.patt: %pattern_type.98f = symbolic_binding_pattern AA, 0 [concrete]\n// CHECK:STDOUT:     %BB.patt: @BB.binding.as_type.as.B.impl.%pattern_type (%pattern_type.12a) = symbolic_binding_pattern BB, 1 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %BB.ref: @BB.binding.as_type.as.B.impl.%A_where.type (%A_where.type.29f165.1) = name_ref BB, %BB.loc9_25.1 [symbolic = %BB.loc9_25.2 (constants.%BB.0b1)]\n// CHECK:STDOUT:     %BB.as_type: type = facet_access_type %BB.ref [symbolic = %BB.binding.as_type (constants.%BB.binding.as_type)]\n// CHECK:STDOUT:     %.loc9_51: type = converted %BB.ref, %BB.as_type [symbolic = %BB.binding.as_type (constants.%BB.binding.as_type)]\n// CHECK:STDOUT:     %B.ref: %B.type.5ae = name_ref B, file.%B.decl [concrete = constants.%B.generic]\n// CHECK:STDOUT:     %AA.ref.loc9_59: type = name_ref AA, %AA.loc9_14.1 [symbolic = %AA.loc9_14.2 (constants.%AA)]\n// CHECK:STDOUT:     %ptr.loc9_61.1: type = ptr_type %AA.ref.loc9_59 [symbolic = %ptr.loc9_61.2 (constants.%ptr.e8f8f9.1)]\n// CHECK:STDOUT:     %B.type.loc9_62.1: type = facet_type <@B, @B(constants.%ptr.e8f8f9.1)> [symbolic = %B.type.loc9_62.2 (constants.%B.type.abcc5d.1)]\n// CHECK:STDOUT:     %.loc9_19.1: type = splice_block %.loc9_19.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc9_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %AA.loc9_14.1: type = symbolic_binding AA, 0 [symbolic = %AA.loc9_14.2 (constants.%AA)]\n// CHECK:STDOUT:     %.loc9_36.1: type = splice_block %.loc9_36.2 [symbolic = %A_where.type (constants.%A_where.type.29f165.1)] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %A.ref: %A.type.464 = name_ref A, file.%A.decl [concrete = constants.%A.generic]\n// CHECK:STDOUT:       %AA.ref.loc9_32: type = name_ref AA, %AA.loc9_14.1 [symbolic = %AA.loc9_14.2 (constants.%AA)]\n// CHECK:STDOUT:       %A.type.loc9_34.1: type = facet_type <@A, @A(constants.%AA)> [symbolic = %A.type.loc9_34.2 (constants.%A.type.ade3d9.1)]\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.Self.ref: @BB.binding.as_type.as.B.impl.%A.type.loc9_34.2 (%A.type.ade3d9.1) = name_ref .Self, %.Self.2 [symbolic = %.Self.4 (constants.%.Self.660472.1)]\n// CHECK:STDOUT:       %.Self.as_type: type = facet_access_type %.Self.ref [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_42.1: type = converted %.Self.ref, %.Self.as_type [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]\n// CHECK:STDOUT:       %.loc9_42.2: @BB.binding.as_type.as.B.impl.%A.assoc_type (%A.assoc_type) = specific_constant @X.%assoc0, @A.WithSelf(constants.%AA, constants.%.Self.660472.1) [symbolic = %assoc0 (constants.%assoc0)]\n// CHECK:STDOUT:       %X.ref: @BB.binding.as_type.as.B.impl.%A.assoc_type (%A.assoc_type) = name_ref X, %.loc9_42.2 [symbolic = %assoc0 (constants.%assoc0)]\n// CHECK:STDOUT:       %impl.elem0.loc9_42.1: type = impl_witness_access constants.%A.lookup_impl_witness.04abbb.1, element0 [symbolic = %impl.elem0.loc9_42.2 (constants.%impl.elem0.f51d29.1)]\n// CHECK:STDOUT:       %.loc9_48.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc9_48.2: type = converted %.loc9_48.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.loc9_36.2: type = where_expr %.Self.2 [symbolic = %A_where.type (constants.%A_where.type.29f165.1)] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%A.type.ade3d9.1\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc9_42.1, %.loc9_48.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %BB.loc9_25.1: @BB.binding.as_type.as.B.impl.%A_where.type (%A_where.type.29f165.1) = symbolic_binding BB, 1 [symbolic = %BB.loc9_25.2 (constants.%BB.0b1)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @BB.binding.as_type.as.B.impl(%AA.loc9_14.1: type, %BB.loc9_25.1: @BB.binding.as_type.as.B.impl.%A_where.type (%A_where.type.29f165.1)) {\n// CHECK:STDOUT:   %AA.loc9_14.2: type = symbolic_binding AA, 0 [symbolic = %AA.loc9_14.2 (constants.%AA)]\n// CHECK:STDOUT:   %A.type.loc9_34.2: type = facet_type <@A, @A(%AA.loc9_14.2)> [symbolic = %A.type.loc9_34.2 (constants.%A.type.ade3d9.1)]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %require_complete.loc9_42: <witness> = require_complete_type %A.type.loc9_34.2 [symbolic = %require_complete.loc9_42 (constants.%require_complete.f58)]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.4 [symbolic = %.Self.binding.as_type (constants.%.Self.binding.as_type)]\n// CHECK:STDOUT:   %A.assoc_type: type = assoc_entity_type @A, @A(%AA.loc9_14.2) [symbolic = %A.assoc_type (constants.%A.assoc_type)]\n// CHECK:STDOUT:   %assoc0: @BB.binding.as_type.as.B.impl.%A.assoc_type (%A.assoc_type) = assoc_entity element0, @A.WithSelf.%X [symbolic = %assoc0 (constants.%assoc0)]\n// CHECK:STDOUT:   %A.lookup_impl_witness: <witness> = lookup_impl_witness %.Self.4, @A, @A(%AA.loc9_14.2) [symbolic = %A.lookup_impl_witness (constants.%A.lookup_impl_witness.04abbb.1)]\n// CHECK:STDOUT:   %impl.elem0.loc9_42.2: type = impl_witness_access %A.lookup_impl_witness, element0 [symbolic = %impl.elem0.loc9_42.2 (constants.%impl.elem0.f51d29.1)]\n// CHECK:STDOUT:   %A_where.type: type = facet_type <@A, @A(%AA.loc9_14.2) where %impl.elem0.loc9_42.2 = constants.%empty_tuple.type> [symbolic = %A_where.type (constants.%A_where.type.29f165.1)]\n// CHECK:STDOUT:   %BB.loc9_25.2: @BB.binding.as_type.as.B.impl.%A_where.type (%A_where.type.29f165.1) = symbolic_binding BB, 1 [symbolic = %BB.loc9_25.2 (constants.%BB.0b1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %A_where.type [symbolic = %pattern_type (constants.%pattern_type.12a)]\n// CHECK:STDOUT:   %BB.binding.as_type: type = symbolic_binding_type BB, 1, %BB.loc9_25.2 [symbolic = %BB.binding.as_type (constants.%BB.binding.as_type)]\n// CHECK:STDOUT:   %ptr.loc9_61.2: type = ptr_type %AA.loc9_14.2 [symbolic = %ptr.loc9_61.2 (constants.%ptr.e8f8f9.1)]\n// CHECK:STDOUT:   %B.type.loc9_62.2: type = facet_type <@B, @B(%ptr.loc9_61.2)> [symbolic = %B.type.loc9_62.2 (constants.%B.type.abcc5d.1)]\n// CHECK:STDOUT:   %B.impl_witness.loc9_64.2: <witness> = impl_witness %B.impl_witness_table, @BB.binding.as_type.as.B.impl(%AA.loc9_14.2, %BB.loc9_25.2) [symbolic = %B.impl_witness.loc9_64.2 (constants.%B.impl_witness.bef)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc9_62: <witness> = require_complete_type %B.type.loc9_62.2 [symbolic = %require_complete.loc9_62 (constants.%require_complete.fe18c9.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc9_51 as %B.type.loc9_62.1 {\n// CHECK:STDOUT:     %B.impl_witness_table = impl_witness_table (), @BB.binding.as_type.as.B.impl [concrete]\n// CHECK:STDOUT:     %B.impl_witness.loc9_64.1: <witness> = impl_witness %B.impl_witness_table, @BB.binding.as_type.as.B.impl(constants.%AA, constants.%BB.0b1) [symbolic = %B.impl_witness.loc9_64.2 (constants.%B.impl_witness.bef)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %B.impl_witness.loc9_64.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @D(%DD.loc14_9.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%D.bd6\n// CHECK:STDOUT:     .G = %D.G.decl\n// CHECK:STDOUT:     .B = <poisoned>\n// CHECK:STDOUT:     .DD = <poisoned>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @D.G(@D.%DD.loc14_9.2: type, %T.loc15_8.2: type) {\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %DD: type = symbolic_binding DD, 0 [symbolic = %DD (constants.%DD)]\n// CHECK:STDOUT:   %ptr.loc21_14.2: type = ptr_type %DD [symbolic = %ptr.loc21_14.2 (constants.%ptr.e8f8f9.2)]\n// CHECK:STDOUT:   %B.type.loc21_15.2: type = facet_type <@B, @B(%ptr.loc21_14.2)> [symbolic = %B.type.loc21_15.2 (constants.%B.type.abcc5d.2)]\n// CHECK:STDOUT:   %.loc21_7.2: require_specific_def_type = require_specific_def @BB.as.B.impl(%ptr.loc21_14.2, %T.loc15_8.1) [symbolic = %.loc21_7.2 (constants.%.77d)]\n// CHECK:STDOUT:   %B.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc15_8.1, @B, @B(%ptr.loc21_14.2) [symbolic = %B.lookup_impl_witness (constants.%B.lookup_impl_witness.52c)]\n// CHECK:STDOUT:   %B.facet.loc21_7.2: @D.G.%B.type.loc21_15.2 (%B.type.abcc5d.2) = facet_value %T.loc15_8.1, (%B.lookup_impl_witness) [symbolic = %B.facet.loc21_7.2 (constants.%B.facet.b5c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc15_8.2 [symbolic = %T.loc15_8.1 (constants.%T.091)]\n// CHECK:STDOUT:     %B.ref: %B.type.5ae = name_ref B, file.%B.decl [concrete = constants.%B.generic]\n// CHECK:STDOUT:     %DD.ref: type = name_ref DD, @D.%DD.loc14_9.2 [symbolic = %DD (constants.%DD)]\n// CHECK:STDOUT:     %ptr.loc21_14.1: type = ptr_type %DD.ref [symbolic = %ptr.loc21_14.2 (constants.%ptr.e8f8f9.2)]\n// CHECK:STDOUT:     %B.type.loc21_15.1: type = facet_type <@B, @B(constants.%ptr.e8f8f9.2)> [symbolic = %B.type.loc21_15.2 (constants.%B.type.abcc5d.2)]\n// CHECK:STDOUT:     %B.facet.loc21_7.1: @D.G.%B.type.loc21_15.2 (%B.type.abcc5d.2) = facet_value %T.ref, (constants.%B.lookup_impl_witness.52c) [symbolic = %B.facet.loc21_7.2 (constants.%B.facet.b5c)]\n// CHECK:STDOUT:     %.loc21_7.1: @D.G.%B.type.loc21_15.2 (%B.type.abcc5d.2) = converted %T.ref, %B.facet.loc21_7.1 [symbolic = %B.facet.loc21_7.2 (constants.%B.facet.b5c)]\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @BB.binding.as_type.as.B.impl(constants.%AA, constants.%BB.0b1) {\n// CHECK:STDOUT:   %AA.loc9_14.2 => constants.%AA\n// CHECK:STDOUT:   %A.type.loc9_34.2 => constants.%A.type.ade3d9.1\n// CHECK:STDOUT:   %.Self.4 => constants.%.Self.660472.1\n// CHECK:STDOUT:   %require_complete.loc9_42 => constants.%require_complete.f58\n// CHECK:STDOUT:   %.Self.binding.as_type => constants.%.Self.binding.as_type\n// CHECK:STDOUT:   %A.assoc_type => constants.%A.assoc_type\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0\n// CHECK:STDOUT:   %A.lookup_impl_witness => constants.%A.lookup_impl_witness.04abbb.1\n// CHECK:STDOUT:   %impl.elem0.loc9_42.2 => constants.%impl.elem0.f51d29.1\n// CHECK:STDOUT:   %A_where.type => constants.%A_where.type.29f165.1\n// CHECK:STDOUT:   %BB.loc9_25.2 => constants.%BB.0b1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.12a\n// CHECK:STDOUT:   %BB.binding.as_type => constants.%BB.binding.as_type\n// CHECK:STDOUT:   %ptr.loc9_61.2 => constants.%ptr.e8f8f9.1\n// CHECK:STDOUT:   %B.type.loc9_62.2 => constants.%B.type.abcc5d.1\n// CHECK:STDOUT:   %B.impl_witness.loc9_64.2 => constants.%B.impl_witness.bef\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D(constants.%DD) {\n// CHECK:STDOUT:   %DD.loc14_9.1 => constants.%DD\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %D.G.type => constants.%D.G.type.49d\n// CHECK:STDOUT:   %D.G => constants.%D.G.891\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.G(constants.%DD, constants.%T.091) {\n// CHECK:STDOUT:   %T.loc15_8.1 => constants.%T.091\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %DD.loc14_9.1 => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %D.G.type => constants.%D.G.type.235\n// CHECK:STDOUT:   %D.G => constants.%D.G.be1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.G(constants.%empty_struct_type, constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc15_8.1 => constants.%T.67d\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %DD => constants.%empty_struct_type\n// CHECK:STDOUT:   %ptr.loc21_14.2 => constants.%ptr.c28\n// CHECK:STDOUT:   %B.type.loc21_15.2 => constants.%B.type.a69\n// CHECK:STDOUT:   %.loc21_7.2 => constants.%.5ef\n// CHECK:STDOUT:   %B.lookup_impl_witness => constants.%B.lookup_impl_witness.eb0\n// CHECK:STDOUT:   %B.facet.loc21_7.2 => constants.%B.facet.4b0\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/generic/extend_type_completion.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/extend_type_completion.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/extend_type_completion.carbon\n\n// --- class_impl_doesnt_need_complete_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface K(T:! type) {}\n\nclass C(N:! i32) {\n  impl as K(array(i32, N)) {}\n}\n\n// C does not extend K so the type of K is not completed. No error.\nfn F(unused v: C(-1)) {}\n\n// --- fail_class_extend_impl_does_need_complete_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface K(T:! type) {}\n\nclass C(N:! i32) {\n  extend impl as K(array(i32, N)) {}\n}\n\n// C extends K so the type of K is completed, but is invalid.\n// CHECK:STDERR: fail_class_extend_impl_does_need_complete_interface.carbon:[[@LINE+7]]:13: error: parameter has incomplete type `C(-1)` in function definition [IncompleteTypeInFunctionParam]\n// CHECK:STDERR: fn F(unused v: C(-1)) {}\n// CHECK:STDERR:             ^~~~~~~~\n// CHECK:STDERR: fail_class_extend_impl_does_need_complete_interface.carbon:[[@LINE-7]]:18: note: array bound of -1 is negative [ArrayBoundNegative]\n// CHECK:STDERR:   extend impl as K(array(i32, N)) {}\n// CHECK:STDERR:                  ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused v: C(-1)) {}\n\n// --- interface_require_impls_doesnt_need_complete_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface K(T:! type) {}\ninterface J(N:! i32) {\n  require impls K(array(i32, N));\n}\n\n// J does not extend K so the type of K is not completed. No error.\nfn F(unused v: J(-1)) {}\n\n// --- fail_interface_extend_require_impls_does_need_complete_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface K(T:! type) {}\ninterface J(N:! i32) {\n  extend require impls K(array(i32, N));\n}\ninterface I(N:! i32) {\n  extend require impls J(N);\n}\n\n// I extends J extends K so the type of K is completed, but is invalid.\n//\n// TODO: The error location should be the type, like in the class case above. We\n// need a location for the type in context.bind_name_map() to use as the\n// location to Convert().\n//\n// CHECK:STDERR: fail_interface_extend_require_impls_does_need_complete_interface.carbon:[[@LINE+10]]:13: error: parameter has incomplete type `I(-1)` in function definition [IncompleteTypeInFunctionParam]\n// CHECK:STDERR: fn F(unused v: I(-1)) {}\n// CHECK:STDERR:             ^~~~~~~~\n// CHECK:STDERR: fail_interface_extend_require_impls_does_need_complete_interface.carbon:[[@LINE-12]]:24: note: `J(N)` evaluates to incomplete type `J(-1)` [IncompleteTypeInMonomorphization]\n// CHECK:STDERR:   extend require impls J(N);\n// CHECK:STDERR:                        ^~~~\n// CHECK:STDERR: fail_interface_extend_require_impls_does_need_complete_interface.carbon:[[@LINE-18]]:24: note: array bound of -1 is negative [ArrayBoundNegative]\n// CHECK:STDERR:   extend require impls K(array(i32, N));\n// CHECK:STDERR:                        ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused v: I(-1)) {}\n\n// --- constraint_require_impls_doesnt_need_complete_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface K(T:! type) {}\nconstraint J(N:! i32) {\n  require impls K(array(i32, N));\n}\n\n// J does not extend K so the type of K is not completed. No error.\nfn F(unused v: J(-1)) {}\n\n// --- fail_constraint_extend_require_impls_does_need_complete_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface K(T:! type) {}\nconstraint J(N:! i32) {\n  extend require impls K(array(i32, N));\n}\nconstraint I(N:! i32) {\n  extend require impls J(N);\n}\n\n// I extends J extends K so the type of K is completed, but is invalid.\n// CHECK:STDERR: fail_constraint_extend_require_impls_does_need_complete_interface.carbon:[[@LINE+10]]:13: error: parameter has incomplete type `I(-1)` in function definition [IncompleteTypeInFunctionParam]\n// CHECK:STDERR: fn F(unused v: I(-1)) {}\n// CHECK:STDERR:             ^~~~~~~~\n// CHECK:STDERR: fail_constraint_extend_require_impls_does_need_complete_interface.carbon:[[@LINE-7]]:24: note: `J(N)` evaluates to incomplete type `J(-1)` [IncompleteTypeInMonomorphization]\n// CHECK:STDERR:   extend require impls J(N);\n// CHECK:STDERR:                        ^~~~\n// CHECK:STDERR: fail_constraint_extend_require_impls_does_need_complete_interface.carbon:[[@LINE-13]]:24: note: array bound of -1 is negative [ArrayBoundNegative]\n// CHECK:STDERR:   extend require impls K(array(i32, N));\n// CHECK:STDERR:                        ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(unused v: I(-1)) {}\n\n// --- interface_require_impls_doesnt_need_complete_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface K {}\ninterface J(N:! i32) {\n  require array(Self, N) impls K;\n}\n\n// J does not extend K so the type of Self impling K is not completed. No error.\nfn F(unused v: J(-1)) {}\n\n// --- constraint_require_impls_doesnt_need_complete_self.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface K {}\nconstraint J(N:! i32) {\n  require array(Self, N) impls K;\n}\n\n// J does not extend K so the type of Self impling K is not completed. No error.\nfn F(unused v: J(-1)) {}\n"
  },
  {
    "path": "toolchain/check/testdata/generic/fail_generic_copy.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/fail_generic_copy.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/fail_generic_copy.carbon\n\n// --- fail_return.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[T:! type](x: T) -> T {\n  // CHECK:STDERR: fail_return.carbon:[[@LINE+7]]:10: error: cannot copy value of type `T` [CopyOfUncopyableType]\n  // CHECK:STDERR:   return x;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR: fail_return.carbon:[[@LINE+4]]:10: note: type `T` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   return x;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR:\n  return x;\n}\n\n// --- fail_var.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[T:! Core.Destroy](x: T) {\n  // CHECK:STDERR: fail_var.carbon:[[@LINE+7]]:21: error: cannot copy value of type `T` [CopyOfUncopyableType]\n  // CHECK:STDERR:   var unused y: T = x;\n  // CHECK:STDERR:                     ^\n  // CHECK:STDERR: fail_var.carbon:[[@LINE+4]]:21: note: type `T` does not implement interface `Core.Copy` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var unused y: T = x;\n  // CHECK:STDERR:                     ^\n  // CHECK:STDERR:\n  var unused y: T = x;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/generic/forward_decl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/forward_decl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/forward_decl.carbon\n\ninterface Z {}\n\nclass C {}\nimpl C as Z {}\n\nfn G[T:! Z](p: T);\n\nfn F() {\n    G({} as C);\n}\n\nfn G[T:! Z](unused p: T) {}\n"
  },
  {
    "path": "toolchain/check/testdata/generic/identify_specific_facet_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/identify_specific_facet_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/identify_specific_facet_type.carbon\n\n// --- fail_error_in_identifying_require_facet_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// Identification tries to form the specific interface `K(array(i32, -1))` which\n// is invalid, so the impl as a whole is invalid.\n\ninterface K(T:! type) {}\nconstraint L(N:! i32) {\n  require impls K(array(i32, N));\n}\nconstraint J(N:! i32) {\n  require impls L(N);\n}\n\n// CHECK:STDERR: fail_error_in_identifying_require_facet_type.carbon:[[@LINE+7]]:1: error: facet type `J(-1)` cannot be identified in `impl as` [ImplOfUnidentifiedFacetType]\n// CHECK:STDERR: impl {} as J(-1) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_error_in_identifying_require_facet_type.carbon:[[@LINE-9]]:30: note: array bound of -1 is negative [ArrayBoundNegative]\n// CHECK:STDERR:   require impls K(array(i32, N));\n// CHECK:STDERR:                              ^\n// CHECK:STDERR:\nimpl {} as J(-1) {}\n\n// --- fail_error_in_identifying_extend_require_facet_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// Identification tries to form the specific interface `K(array(i32, -1))` which\n// is invalid, so the impl as a whole is invalid.\n\ninterface K(T:! type) {}\nconstraint J(N:! i32) {\n  extend require impls K(array(i32, N));\n}\n\n// CHECK:STDERR: fail_error_in_identifying_extend_require_facet_type.carbon:[[@LINE+7]]:1: error: facet type `J(-1)` cannot be identified in `impl as` [ImplOfUnidentifiedFacetType]\n// CHECK:STDERR: impl {} as J(-1) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_error_in_identifying_extend_require_facet_type.carbon:[[@LINE-6]]:24: note: array bound of -1 is negative [ArrayBoundNegative]\n// CHECK:STDERR:   extend require impls K(array(i32, N));\n// CHECK:STDERR:                        ^~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl {} as J(-1) {}\n"
  },
  {
    "path": "toolchain/check/testdata/generic/local.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/local.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/local.carbon\n\n// --- class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {\n  class C(T:! type) {\n    var x: T;\n  }\n  var unused v: C(i32) = {.x = 1};\n}\n\n// --- fail_param_shadows_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {\n  // TODO: Decide on what behavior we want here. We don't reject the corresponding case outside of a function.\n  // CHECK:STDERR: fail_param_shadows_class.carbon:[[@LINE+7]]:9: error: duplicate name `C` being declared in the same scope [NameDeclDuplicate]\n  // CHECK:STDERR:   class C(C:! type) {\n  // CHECK:STDERR:         ^\n  // CHECK:STDERR: fail_param_shadows_class.carbon:[[@LINE+4]]:11: note: name is previously declared here [NameDeclPrevious]\n  // CHECK:STDERR:   class C(C:! type) {\n  // CHECK:STDERR:           ^\n  // CHECK:STDERR:\n  class C(C:! type) {\n  }\n}\n\n// --- nonlocal_param_shadows_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C(C:! type) {\n}\n\n// CHECK:STDOUT: --- class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5d4: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT:   %C.elem.d15: type = unbound_element_type %C.5d4, %T [symbolic]\n// CHECK:STDOUT:   %struct_type.x.0c5: type = struct_type {.x: %T} [symbolic]\n// CHECK:STDOUT:   %complete_type.735: <witness> = complete_type_witness %struct_type.x.0c5 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %C.d45: type = class_type @C, @C(%i32) [concrete]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %C.elem.f74: type = unbound_element_type %C.d45, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x.ed6: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x.ed6 [concrete]\n// CHECK:STDOUT:   %pattern_type.7db: type = pattern_type %C.d45 [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %struct_type.x.c96: type = struct_type {.x: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.x.c96 = struct_value (%int_1.5b8) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %C.val: %C.d45 = struct_value (%int_1.5d2) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc5_11.2: type) {\n// CHECK:STDOUT:   %T.loc5_11.1: type = symbolic_binding T, 0 [symbolic = %T.loc5_11.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc5_11.1 [symbolic = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T.loc5_11.1) [symbolic = %C (constants.%C.5d4)]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %T.loc5_11.1 [symbolic = %C.elem (constants.%C.elem.d15)]\n// CHECK:STDOUT:   %struct_type.x: type = struct_type {.x: @C.%T.loc5_11.1 (%T)} [symbolic = %struct_type.x (constants.%struct_type.x.0c5)]\n// CHECK:STDOUT:   %complete_type.loc7_3.2: <witness> = complete_type_witness %struct_type.x [symbolic = %complete_type.loc7_3.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc5_11.2 [symbolic = %T.loc5_11.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc6: @C.%C.elem (%C.elem.d15) = field_decl x, element0 [concrete]\n// CHECK:STDOUT:     %complete_type.loc7_3.1: <witness> = complete_type_witness constants.%struct_type.x.0c5 [symbolic = %complete_type.loc7_3.2 (constants.%complete_type.735)]\n// CHECK:STDOUT:     complete_type_witness = %complete_type.loc7_3.1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5d4\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .x = %.loc6\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_15.1: type = splice_block %.loc5_15.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc5_15.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_11.2: type = symbolic_binding T, 0 [symbolic = %T.loc5_11.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.7db = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.7db = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %C.d45 = var %v.var_patt\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %.loc8_33.1: %struct_type.x.c96 = struct_literal (%int_1) [concrete = constants.%struct]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc8_33.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc8_33.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc8_33.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc8_33.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc8_33.3: ref %i32 = class_element_access %v.var, element0\n// CHECK:STDOUT:   %.loc8_33.4: init %i32 to %.loc8_33.3 = in_place_init %.loc8_33.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc8_33.5: init %C.d45 to %v.var = class_init (%.loc8_33.4) [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc8_3: init %C.d45 = converted %.loc8_33.1, %.loc8_33.5 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign %v.var, %.loc8_3\n// CHECK:STDOUT:   %.loc8_22: type = splice_block %C [concrete = constants.%C.d45] {\n// CHECK:STDOUT:     %C.ref: %C.type = name_ref C, %C.decl [concrete = constants.%C.generic]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %C: type = class_type @C, @C(constants.%i32) [concrete = constants.%C.d45]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v: ref %C.d45 = ref_binding v, %v.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %v.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%v.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %C.d45) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc5_11.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%i32) {\n// CHECK:STDOUT:   %T.loc5_11.1 => constants.%i32\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %C => constants.%C.d45\n// CHECK:STDOUT:   %C.elem => constants.%C.elem.f74\n// CHECK:STDOUT:   %struct_type.x => constants.%struct_type.x.ed6\n// CHECK:STDOUT:   %complete_type.loc7_3.2 => constants.%complete_type.1ec\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_param_shadows_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %C.67d: type = symbolic_binding C, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5d4: type = class_type @C, @C(%C.67d) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%C.loc13_11.2: type) {\n// CHECK:STDOUT:   %C.loc13_11.1: type = symbolic_binding C, 0 [symbolic = %C.loc13_11.1 (constants.%C.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5d4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %C.patt: %pattern_type = symbolic_binding_pattern C, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc13_15.1: type = splice_block %.loc13_15.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc13_15.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %C.loc13_11.2: type = symbolic_binding C, 0 [symbolic = %C.loc13_11.1 (constants.%C.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%C.67d) {\n// CHECK:STDOUT:   %C.loc13_11.1 => constants.%C.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- nonlocal_param_shadows_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %C.67d: type = symbolic_binding C, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.5a3: type = class_type @C, @C(%C.67d) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %C.patt: %pattern_type = symbolic_binding_pattern C, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_13.1: type = splice_block %.loc4_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %C.loc4_9.2: type = symbolic_binding C, 0 [symbolic = %C.loc4_9.1 (constants.%C.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%C.loc4_9.2: type) {\n// CHECK:STDOUT:   %C.loc4_9.1: type = symbolic_binding C, 0 [symbolic = %C.loc4_9.1 (constants.%C.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.5a3\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%C.67d) {\n// CHECK:STDOUT:   %C.loc4_9.1 => constants.%C.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/generic/template/convert.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/template/convert.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/template/convert.carbon\n\n// --- convert.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[template T:! type](x: T) -> i32 {\n  let n: i32 = x;\n  return n;\n}\n\nfn Test1(n: i32) -> i32 {\n  return F(n);\n}\n\nclass C {\n  var n: i32;\n  impl as Core.ImplicitAs(i32) {\n    fn Convert[self: Self]() -> i32 { return self.n; }\n  }\n}\n\nfn Test2(c: C) -> i32 {\n  return F(c);\n}\n\n// --- fail_cannot_convert.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[template T:! type](x: T) -> i32 {\n  let n: i32 = x;\n  return n;\n}\n\nclass D {}\n\nfn Test(d: D) -> i32 {\n  // CHECK:STDERR: fail_cannot_convert.carbon:[[@LINE+10]]:10: error: unable to monomorphize specific `F(D)` [ResolvingSpecificHere]\n  // CHECK:STDERR:   return F(d);\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR: fail_cannot_convert.carbon:[[@LINE-10]]:16: note: cannot implicitly convert expression of type `D` to `i32` [ConversionFailure]\n  // CHECK:STDERR:   let n: i32 = x;\n  // CHECK:STDERR:                ^\n  // CHECK:STDERR: fail_cannot_convert.carbon:[[@LINE-13]]:16: note: type `D` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let n: i32 = x;\n  // CHECK:STDERR:                ^\n  // CHECK:STDERR:\n  return F(d);\n}\n\n// CHECK:STDOUT: --- convert.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67db0b.1: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %pattern_type.51d1c4.1: type = pattern_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %i32.builtin: type = int_type signed, %int_32 [concrete]\n// CHECK:STDOUT:   %complete_type.f8a: <witness> = complete_type_witness %i32.builtin [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Test1.type: type = fn_type @Test1 [concrete]\n// CHECK:STDOUT:   %Test1: %Test1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.d18: <specific function> = specific_function %F, @F(%i32) [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.892: <witness> = impl_witness @C.as.ImplicitAs.impl.%ImplicitAs.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %C.as.ImplicitAs.impl.Convert.type: type = fn_type @C.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %C.as.ImplicitAs.impl.Convert: %C.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value %C, (%ImplicitAs.impl_witness.892) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.ee5: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %Test2.type: type = fn_type @Test2 [concrete]\n// CHECK:STDOUT:   %Test2: %Test2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.540: <specific function> = specific_function %F, @F(%C) [concrete]\n// CHECK:STDOUT:   %inst.as_compatible.db5: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.9b1: %i32 = as_compatible @F.%x.ref\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.splice_block.e80: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.457: %i32 = splice_block %.9b1 {}\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.as_compatible.97f: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.b3d: %C = as_compatible @F.%x.ref\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.e4e: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.ee5, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %inst.splice_block.f09: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.774: %i32 = splice_block %.9e4 {\n// CHECK:STDOUT:       %impl.elem0.65e: %.e4e = impl_witness_access %ImplicitAs.impl_witness.892, element0 [concrete = %C.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:       %bound_method: <bound method> = bound_method %.b3d, %impl.elem0.65e\n// CHECK:STDOUT:       %C.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method(%.b3d)\n// CHECK:STDOUT:       %.6c6: %i32 = value_of_initializer %C.as.ImplicitAs.impl.Convert.call\n// CHECK:STDOUT:       %.9e4: %i32 = converted %.b3d, %.6c6\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .Test1 = %Test1.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Test2 = %Test2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.51d1c4.1) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.51d1c4.1) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc4: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4_34: Core.Form = init_form %i32.loc4 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x.param: @F.%T.loc4_15.1 (%T.67db0b.1) = value_param call_param0\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_15.2 [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x: @F.%T.loc4_15.1 (%T.67db0b.1) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test1.decl: %Test1.type = fn_decl @Test1 [concrete = constants.%Test1] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc9_21: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc9: Core.Form = init_form %i32.loc9_21 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32.loc9_13: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Test2.decl: %Test2.type = fn_decl @Test2 [concrete = constants.%Test2] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.7c7 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc20: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.ImplicitAs.impl: %Self.ref as %ImplicitAs.type {\n// CHECK:STDOUT:   %C.as.ImplicitAs.impl.Convert.decl: %C.as.ImplicitAs.impl.Convert.type = fn_decl @C.as.ImplicitAs.impl.Convert [concrete = constants.%C.as.ImplicitAs.impl.Convert] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.7c7 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.7c7 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16_33: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %self.param: %C = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %self: %C = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%C.as.ImplicitAs.impl.Convert.decl), @C.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness %ImplicitAs.impl_witness_table [concrete = constants.%ImplicitAs.impl_witness.892]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Convert = %C.as.ImplicitAs.impl.Convert.decl\n// CHECK:STDOUT:   witness = %ImplicitAs.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc14: %C.elem = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   impl_decl @C.as.ImplicitAs.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %ImplicitAs.ref: %ImplicitAs.type.cc7 = name_ref ImplicitAs, imports.%Core.ImplicitAs [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%i32)> [concrete = constants.%ImplicitAs.type.e8c]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .n = %.loc14\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc4_15.1 [template = %pattern_type (constants.%pattern_type.51d1c4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_15.1 [template = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %.loc5_16.3: <instruction> = refine_type_action %x.ref, %T.loc4_15.1 [template]\n// CHECK:STDOUT:   %.loc5_16.4: <instruction> = convert_to_value_action %.loc5_16.1, constants.%i32 [template]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%T.loc4_15.1 (%T.67db0b.1)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.ref: @F.%T.loc4_15.1 (%T.67db0b.1) = name_ref x, %x\n// CHECK:STDOUT:     %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5_16.1: @F.%T.loc4_15.1 (%T.67db0b.1) = splice_inst %.loc5_16.3\n// CHECK:STDOUT:     %.loc5_16.2: %i32 = splice_inst %.loc5_16.4\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %.loc5_16.2\n// CHECK:STDOUT:     %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:     %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %n.ref, %specific_fn\n// CHECK:STDOUT:     %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_10.2(%n.ref)\n// CHECK:STDOUT:     return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test1(%n.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%i32) [concrete = constants.%F.specific_fn.d18]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%n.ref)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.ImplicitAs.impl.Convert(%self.param: %C) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %self.ref: %C = name_ref self, %self\n// CHECK:STDOUT:   %n.ref: %C.elem = name_ref n, @C.%.loc14 [concrete = @C.%.loc14]\n// CHECK:STDOUT:   %.loc16_50.1: ref %i32 = class_element_access %self.ref, element0\n// CHECK:STDOUT:   %.loc16_50.2: %i32 = acquire_value %.loc16_50.1\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc16_50.1: <bound method> = bound_method %.loc16_50.2, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_50.2: <bound method> = bound_method %.loc16_50.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc16_50.2(%.loc16_50.2)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test2(%c.param: %C) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.540]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%c.ref)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67db0b.1) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T.67db0b.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d1c4.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%i32) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%i32\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7ce\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.f8a\n// CHECK:STDOUT:   %.loc5_16.3 => constants.%inst.as_compatible.db5\n// CHECK:STDOUT:   %.loc5_16.4 => constants.%inst.splice_block.e80\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%C\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.54b\n// CHECK:STDOUT:   %.loc5_16.3 => constants.%inst.as_compatible.97f\n// CHECK:STDOUT:   %.loc5_16.4 => constants.%inst.splice_block.f09\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_cannot_convert.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67db0b.1: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %pattern_type.51d1c4.1: type = pattern_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.9c8: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %Test.type: type = fn_type @Test [concrete]\n// CHECK:STDOUT:   %Test: %Test.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%D) [concrete]\n// CHECK:STDOUT:   %inst.as_compatible: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.759: %D = as_compatible @F.%x.ref\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %inst.splice_block: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.e29: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:       %.1ae: %i32 = converted %.759, <error> [concrete = <error>]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .Test = %Test.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.51d1c4.1) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.51d1c4.1) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc4: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4_34: Core.Form = init_form %i32.loc4 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x.param: @F.%T.loc4_15.1 (%T.67db0b.1) = value_param call_param0\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_15.2 [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x: @F.%T.loc4_15.1 (%T.67db0b.1) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %Test.decl: %Test.type = fn_decl @Test [concrete = constants.%Test] {\n// CHECK:STDOUT:     %d.patt: %pattern_type.9c8 = value_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.param_patt: %pattern_type.9c8 = value_param_pattern %d.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc11: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %d.param: %D = value_param call_param0\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %d: %D = value_binding d, %d.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc4_15.1 [template = %pattern_type (constants.%pattern_type.51d1c4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_15.1 [template = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %.loc5_16.3: <instruction> = refine_type_action %x.ref, %T.loc4_15.1 [template]\n// CHECK:STDOUT:   %.loc5_16.4: <instruction> = convert_to_value_action %.loc5_16.1, constants.%i32 [template]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%T.loc4_15.1 (%T.67db0b.1)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.ref: @F.%T.loc4_15.1 (%T.67db0b.1) = name_ref x, %x\n// CHECK:STDOUT:     %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5_16.1: @F.%T.loc4_15.1 (%T.67db0b.1) = splice_inst %.loc5_16.3\n// CHECK:STDOUT:     %.loc5_16.2: %i32 = splice_inst %.loc5_16.4\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %.loc5_16.2\n// CHECK:STDOUT:     %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:     %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %n.ref, %specific_fn\n// CHECK:STDOUT:     %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_10.2(%n.ref)\n// CHECK:STDOUT:     return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test(%d.param: %D) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %d.ref: %D = name_ref d, %d\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%D) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%d.ref)\n// CHECK:STDOUT:   return %F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67db0b.1) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T.67db0b.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d1c4.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%D) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%D\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9c8\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.357\n// CHECK:STDOUT:   %.loc5_16.3 => constants.%inst.as_compatible\n// CHECK:STDOUT:   %.loc5_16.4 => constants.%inst.splice_block\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/generic/template/fail_todo_template_access_assoc_const.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/template/fail_todo_template_access_assoc_const.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/template/fail_todo_template_access_assoc_const.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// TODO: This should check. The `T.I1` access should be deferred until we know\n// the value of the `template T`.\n//\n// CHECK:STDERR: fail_todo_template_access_assoc_const.carbon:[[@LINE+4]]:36: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n// CHECK:STDERR: interface I(template T:! type, N:! T.I1) {\n// CHECK:STDERR:                                    ^~~~\n// CHECK:STDERR:\ninterface I(template T:! type, N:! T.I1) {\n    let I1:! type;\n}\n"
  },
  {
    "path": "toolchain/check/testdata/generic/template/member_access.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/template/member_access.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/template/member_access.carbon\n\n// --- member_access.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[template T:! type](x: T) -> i32 {\n  let n: i32 = x.n;\n  return n;\n}\n\nclass C {\n  var n: i32;\n}\n\nfn Test1(c: C) {\n  F(c);\n}\n\nfn Test2(x: {.m: i32, .n: i32}) {\n  F(x);\n}\n\n// --- fail_no_such_member.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[template T:! type](x: T) -> i32 {\n  let n: i32 = x.n;\n  return n;\n}\n\nclass D {\n  var m: i32;\n}\n\nfn Test(d: D) {\n  // CHECK:STDERR: fail_no_such_member.carbon:[[@LINE+7]]:3: error: unable to monomorphize specific `F(D)` [ResolvingSpecificHere]\n  // CHECK:STDERR:   F(d);\n  // CHECK:STDERR:   ^\n  // CHECK:STDERR: fail_no_such_member.carbon:[[@LINE-12]]:16: note: member name `n` not found in `D` [MemberNameNotFoundInInstScope]\n  // CHECK:STDERR:   let n: i32 = x.n;\n  // CHECK:STDERR:                ^~~\n  // CHECK:STDERR:\n  F(d);\n}\n\n// --- fail_member_wrong_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[template T:! type](x: T) -> i32 {\n  let n: i32 = x.n;\n  return n;\n}\n\nclass E {\n  class F {}\n  var n: F;\n}\n\nfn Test(e: E) {\n  // CHECK:STDERR: fail_member_wrong_type.carbon:[[@LINE+10]]:3: error: unable to monomorphize specific `F(E)` [ResolvingSpecificHere]\n  // CHECK:STDERR:   F(e);\n  // CHECK:STDERR:   ^\n  // CHECK:STDERR: fail_member_wrong_type.carbon:[[@LINE-13]]:16: note: cannot implicitly convert expression of type `F` to `i32` [ConversionFailure]\n  // CHECK:STDERR:   let n: i32 = x.n;\n  // CHECK:STDERR:                ^~~\n  // CHECK:STDERR: fail_member_wrong_type.carbon:[[@LINE-16]]:16: note: type `F` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   let n: i32 = x.n;\n  // CHECK:STDERR:                ^~~\n  // CHECK:STDERR:\n  F(e);\n}\n\n// CHECK:STDOUT: --- member_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67db0b.1: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %Test1.type: type = fn_type @Test1 [concrete]\n// CHECK:STDOUT:   %Test1: %Test1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.540: <specific function> = specific_function %F, @F(%C) [concrete]\n// CHECK:STDOUT:   %struct_type.m.n: type = struct_type {.m: %i32, .n: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.811: type = pattern_type %struct_type.m.n [concrete]\n// CHECK:STDOUT:   %Test2.type: type = fn_type @Test2 [concrete]\n// CHECK:STDOUT:   %Test2: %Test2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn.bfc: <specific function> = specific_function %F, @F(%struct_type.m.n) [concrete]\n// CHECK:STDOUT:   %inst.as_compatible.97f: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.b3d: %C = as_compatible @F.%x.ref\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.splice_block.21d: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.b39: %i32 = splice_block %.b60 {\n// CHECK:STDOUT:       %n.ref: %C.elem = name_ref n, @C.%.loc10 [concrete = @C.%.loc10]\n// CHECK:STDOUT:       %.b01: ref %i32 = class_element_access %.b3d, element0\n// CHECK:STDOUT:       %.b60: %i32 = acquire_value %.b01\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.splice_block.ae1: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.eda: %i32 = splice_block %.b39 {}\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type.622: <witness> = complete_type_witness %struct_type.m.n [concrete]\n// CHECK:STDOUT:   %inst.as_compatible.5b4: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.298: %struct_type.m.n = as_compatible @F.%x.ref\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.struct_access: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.4b6: %i32 = struct_access %.298, element1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.splice_block.48b: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.498: %i32 = splice_block %.4b6 {}\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .Test1 = %Test1.decl\n// CHECK:STDOUT:     .Test2 = %Test2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc4: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4_34: Core.Form = init_form %i32.loc4 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x.param: @F.%T.loc4_15.1 (%T.67db0b.1) = value_param call_param0\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_15.2 [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x: @F.%T.loc4_15.1 (%T.67db0b.1) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %Test1.decl: %Test1.type = fn_decl @Test1 [concrete = constants.%Test1] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.7c7 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Test2.decl: %Test2.type = fn_decl @Test2 [concrete = constants.%Test2] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.811 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.811 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %struct_type.m.n = value_param call_param0\n// CHECK:STDOUT:     %.loc17: type = splice_block %struct_type.m.n [concrete = constants.%struct_type.m.n] {\n// CHECK:STDOUT:       %i32.loc17_18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %i32.loc17_27: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.m.n: type = struct_type {.m: %i32, .n: %i32} [concrete = constants.%struct_type.m.n]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: %struct_type.m.n = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc10: %C.elem = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .n = %.loc10\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc4_15.1 [template = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_15.1 [template = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %.loc5_17.4: <instruction> = refine_type_action %x.ref, %T.loc4_15.1 [template]\n// CHECK:STDOUT:   %.loc5_17.5: <instruction> = access_member_action %.loc5_17.1, n [template]\n// CHECK:STDOUT:   %.loc5_17.6: type = type_of_inst %.loc5_17.5 [template]\n// CHECK:STDOUT:   %.loc5_17.7: <instruction> = convert_to_value_action %.loc5_17.2, constants.%i32 [template]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%T.loc4_15.1 (%T.67db0b.1)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.ref: @F.%T.loc4_15.1 (%T.67db0b.1) = name_ref x, %x\n// CHECK:STDOUT:     %.loc5_17.1: @F.%T.loc4_15.1 (%T.67db0b.1) = splice_inst %.loc5_17.4\n// CHECK:STDOUT:     %.loc5_17.2: @F.%.loc5_17.6 (@F.%.loc5_17.6) = splice_inst %.loc5_17.5\n// CHECK:STDOUT:     %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5_17.3: %i32 = splice_inst %.loc5_17.7\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %.loc5_17.3\n// CHECK:STDOUT:     %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:     %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %n.ref, %specific_fn\n// CHECK:STDOUT:     %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_10.2(%n.ref)\n// CHECK:STDOUT:     return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test1(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%C) [concrete = constants.%F.specific_fn.540]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%c.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test2(%x.param: %struct_type.m.n) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %x.ref: %struct_type.m.n = name_ref x, %x\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%struct_type.m.n) [concrete = constants.%F.specific_fn.bfc]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%x.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67db0b.1) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T.67db0b.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%C) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%C\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.54b\n// CHECK:STDOUT:   %.loc5_17.4 => constants.%inst.as_compatible.97f\n// CHECK:STDOUT:   %.loc5_17.5 => constants.%inst.splice_block.21d\n// CHECK:STDOUT:   %.loc5_17.6 => constants.%i32\n// CHECK:STDOUT:   %.loc5_17.7 => constants.%inst.splice_block.ae1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%struct_type.m.n) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%struct_type.m.n\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.811\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.622\n// CHECK:STDOUT:   %.loc5_17.4 => constants.%inst.as_compatible.5b4\n// CHECK:STDOUT:   %.loc5_17.5 => constants.%inst.struct_access\n// CHECK:STDOUT:   %.loc5_17.6 => constants.%i32\n// CHECK:STDOUT:   %.loc5_17.7 => constants.%inst.splice_block.48b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_no_such_member.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67db0b.1: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %D.elem: type = unbound_element_type %D, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.m: type = struct_type {.m: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.218: <witness> = complete_type_witness %struct_type.m [concrete]\n// CHECK:STDOUT:   %pattern_type.9c8: type = pattern_type %D [concrete]\n// CHECK:STDOUT:   %Test.type: type = fn_type @Test [concrete]\n// CHECK:STDOUT:   %Test: %Test.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%D) [concrete]\n// CHECK:STDOUT:   %inst.as_compatible: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.759: %D = as_compatible @F.%x.ref\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.name_ref: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %n.ref: <error> = name_ref n, <error> [concrete = <error>]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.splice_block: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.432: <error> = splice_block <error> [concrete = <error>] {}\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .Test = %Test.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc4: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4_34: Core.Form = init_form %i32.loc4 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x.param: @F.%T.loc4_15.1 (%T.67db0b.1) = value_param call_param0\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_15.2 [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x: @F.%T.loc4_15.1 (%T.67db0b.1) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %Test.decl: %Test.type = fn_decl @Test [concrete = constants.%Test] {\n// CHECK:STDOUT:     %d.patt: %pattern_type.9c8 = value_binding_pattern d [concrete]\n// CHECK:STDOUT:     %d.param_patt: %pattern_type.9c8 = value_param_pattern %d.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %d.param: %D = value_param call_param0\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %d: %D = value_binding d, %d.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc10: %D.elem = field_decl m, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.m [concrete = constants.%complete_type.218]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT:   .m = %.loc10\n// CHECK:STDOUT:   .n = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc4_15.1 [template = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_15.1 [template = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %.loc5_17.4: <instruction> = refine_type_action %x.ref, %T.loc4_15.1 [template]\n// CHECK:STDOUT:   %.loc5_17.5: <instruction> = access_member_action %.loc5_17.1, n [template]\n// CHECK:STDOUT:   %.loc5_17.6: type = type_of_inst %.loc5_17.5 [template]\n// CHECK:STDOUT:   %.loc5_17.7: <instruction> = convert_to_value_action %.loc5_17.2, constants.%i32 [template]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%T.loc4_15.1 (%T.67db0b.1)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.ref: @F.%T.loc4_15.1 (%T.67db0b.1) = name_ref x, %x\n// CHECK:STDOUT:     %.loc5_17.1: @F.%T.loc4_15.1 (%T.67db0b.1) = splice_inst %.loc5_17.4\n// CHECK:STDOUT:     %.loc5_17.2: @F.%.loc5_17.6 (@F.%.loc5_17.6) = splice_inst %.loc5_17.5\n// CHECK:STDOUT:     %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5_17.3: %i32 = splice_inst %.loc5_17.7\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %.loc5_17.3\n// CHECK:STDOUT:     %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:     %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %n.ref, %specific_fn\n// CHECK:STDOUT:     %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_10.2(%n.ref)\n// CHECK:STDOUT:     return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test(%d.param: %D) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %d.ref: %D = name_ref d, %d\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%D) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%d.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67db0b.1) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T.67db0b.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%D) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%D\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9c8\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.218\n// CHECK:STDOUT:   %.loc5_17.4 => constants.%inst.as_compatible\n// CHECK:STDOUT:   %.loc5_17.5 => constants.%inst.name_ref\n// CHECK:STDOUT:   %.loc5_17.6 => <error>\n// CHECK:STDOUT:   %.loc5_17.7 => constants.%inst.splice_block\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_member_wrong_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67db0b.1: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %pattern_type.51d1c4.1: type = pattern_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F.loc4 [concrete]\n// CHECK:STDOUT:   %F.d98: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %E: type = class_type @E [concrete]\n// CHECK:STDOUT:   %F.c40: type = class_type @F.loc10 [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %E.elem: type = unbound_element_type %E, %F.c40 [concrete]\n// CHECK:STDOUT:   %struct_type.n.cae: type = struct_type {.n: %F.c40} [concrete]\n// CHECK:STDOUT:   %complete_type.7a8: <witness> = complete_type_witness %struct_type.n.cae [concrete]\n// CHECK:STDOUT:   %pattern_type.99f: type = pattern_type %E [concrete]\n// CHECK:STDOUT:   %Test.type: type = fn_type @Test [concrete]\n// CHECK:STDOUT:   %Test: %Test.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.d98, @F.loc4(%E) [concrete]\n// CHECK:STDOUT:   %inst.as_compatible: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.988: %E = as_compatible @F.loc4.%x.ref\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %inst.splice_block.518: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.619: %F.c40 = splice_block %.cde {\n// CHECK:STDOUT:       %n.ref: %E.elem = name_ref n, @E.%.loc11 [concrete = @E.%.loc11]\n// CHECK:STDOUT:       %.4af: ref %F.c40 = class_element_access %.988, element0\n// CHECK:STDOUT:       %.cde: %F.c40 = acquire_value %.4af\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %inst.splice_block.34e: <instruction> = inst_value [concrete] {\n// CHECK:STDOUT:     %.a50: <error> = splice_block <error> [concrete = <error>] {\n// CHECK:STDOUT:       %.ea5: %i32 = converted %.619, <error> [concrete = <error>]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .E = %E.decl\n// CHECK:STDOUT:     .Test = %Test.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F.loc4 [concrete = constants.%F.d98] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:     %x.patt: @F.loc4.%pattern_type (%pattern_type.51d1c4.1) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.loc4.%pattern_type (%pattern_type.51d1c4.1) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc4: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc4_34: Core.Form = init_form %i32.loc4 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc4_19.1: type = splice_block %.loc4_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x.param: @F.loc4.%T.loc4_15.1 (%T.67db0b.1) = value_param call_param0\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_15.2 [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x: @F.loc4.%T.loc4_15.1 (%T.67db0b.1) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %E.decl: type = class_decl @E [concrete = constants.%E] {} {}\n// CHECK:STDOUT:   %Test.decl: %Test.type = fn_decl @Test [concrete = constants.%Test] {\n// CHECK:STDOUT:     %e.patt: %pattern_type.99f = value_binding_pattern e [concrete]\n// CHECK:STDOUT:     %e.param_patt: %pattern_type.99f = value_param_pattern %e.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %e.param: %E = value_param call_param0\n// CHECK:STDOUT:     %E.ref: type = name_ref E, file.%E.decl [concrete = constants.%E]\n// CHECK:STDOUT:     %e: %E = value_binding e, %e.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @E {\n// CHECK:STDOUT:   %F.decl: type = class_decl @F.loc10 [concrete = constants.%F.c40] {} {}\n// CHECK:STDOUT:   %F.ref: type = name_ref F, %F.decl [concrete = constants.%F.c40]\n// CHECK:STDOUT:   %.loc11: %E.elem = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n.cae [concrete = constants.%complete_type.7a8]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%E\n// CHECK:STDOUT:   .F = %F.decl\n// CHECK:STDOUT:   .n = %.loc11\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @F.loc10 {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%F.c40\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F.loc4(%T.loc4_15.2: type) {\n// CHECK:STDOUT:   %T.loc4_15.1: type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc4_15.1 [template = %pattern_type (constants.%pattern_type.51d1c4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc4_15.1 [template = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %.loc5_17.4: <instruction> = refine_type_action %x.ref, %T.loc4_15.1 [template]\n// CHECK:STDOUT:   %.loc5_17.5: <instruction> = access_member_action %.loc5_17.1, n [template]\n// CHECK:STDOUT:   %.loc5_17.6: type = type_of_inst %.loc5_17.5 [template]\n// CHECK:STDOUT:   %.loc5_17.7: <instruction> = convert_to_value_action %.loc5_17.2, constants.%i32 [template]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.loc4.%T.loc4_15.1 (%T.67db0b.1)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.ref: @F.loc4.%T.loc4_15.1 (%T.67db0b.1) = name_ref x, %x\n// CHECK:STDOUT:     %.loc5_17.1: @F.loc4.%T.loc4_15.1 (%T.67db0b.1) = splice_inst %.loc5_17.4\n// CHECK:STDOUT:     %.loc5_17.2: @F.loc4.%.loc5_17.6 (@F.loc4.%.loc5_17.6) = splice_inst %.loc5_17.5\n// CHECK:STDOUT:     %i32.loc5: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc5_17.3: %i32 = splice_inst %.loc5_17.7\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %.loc5_17.3\n// CHECK:STDOUT:     %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:     %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:     %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %n.ref, %specific_fn\n// CHECK:STDOUT:     %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc6_10.2(%n.ref)\n// CHECK:STDOUT:     return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Test(%e.param: %E) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F.d98]\n// CHECK:STDOUT:   %e.ref: %E = name_ref e, %e\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F.loc4(constants.%E) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init %i32 = call %F.specific_fn(%e.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F.loc4(constants.%T.67db0b.1) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T.67db0b.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d1c4.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F.loc4(constants.%E) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%E\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.99f\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.7a8\n// CHECK:STDOUT:   %.loc5_17.4 => constants.%inst.as_compatible\n// CHECK:STDOUT:   %.loc5_17.5 => constants.%inst.splice_block.518\n// CHECK:STDOUT:   %.loc5_17.6 => constants.%F.c40\n// CHECK:STDOUT:   %.loc5_17.7 => constants.%inst.splice_block.34e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/generic/template/unimplemented.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/template/unimplemented.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/template/unimplemented.carbon\n\n// --- fail_todo_unimplemented_operator.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// Check that we get a reasonable diagnostic for an unimplemented operation on a\n// template dependent expression.\nfn F[template T:! type](x: T) -> i32 {\n  // CHECK:STDERR: fail_todo_unimplemented_operator.carbon:[[@LINE+4]]:10: error: cannot access member of interface `Core.MulWith(Core.IntLiteral)` in type `<dependent type>` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   return x.n * 3;\n  // CHECK:STDERR:          ^~~~~~~\n  // CHECK:STDERR:\n  return x.n * 3;\n}\n\n// --- fail_todo_unimplemented_value.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  var n: i32;\n}\n\n// Check that we get a reasonable diagnostic for an unimplemented operation on a\n// template dependent value where the type is concrete but determined through\n// the template dependent value.\nfn F(template c:! C) -> i32 {\n  // CHECK:STDERR: fail_todo_unimplemented_value.carbon:[[@LINE+4]]:10: error: cannot access member of interface `Core.MulWith(Core.IntLiteral)` in type `<dependent type>` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   return c.n * 3;\n  // CHECK:STDERR:          ^~~~~~~\n  // CHECK:STDERR:\n  return c.n * 3;\n}\n\n// --- fail_todo_unimplemented_convert.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nfn F[template T:! Core.Destroy](x: T) {\n  // TODO: These diagnostics aren't very good, and we should only produce one error here.\n  // CHECK:STDERR: fail_todo_unimplemented_convert.carbon:[[@LINE+8]]:3: error: member name of type `<dependent type>` in compound member access is not an instance member or an interface member [CompoundMemberAccessDoesNotUseBase]\n  // CHECK:STDERR:   var unused v: T = 0;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_todo_unimplemented_convert.carbon:[[@LINE+4]]:3: error: value of type `<dependent type>` is not callable [CallToNonCallable]\n  // CHECK:STDERR:   var unused v: T = 0;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v: T = 0;\n  // CHECK:STDERR: fail_todo_unimplemented_convert.carbon:[[@LINE+7]]:3: error: cannot implicitly convert expression of type `T` to `i32` [ConversionFailure]\n  // CHECK:STDERR:   var unused w: i32 = x;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_unimplemented_convert.carbon:[[@LINE+4]]:3: note: type `T` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   var unused w: i32 = x;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused w: i32 = x;\n}\n\n// CHECK:STDOUT: --- fail_todo_unimplemented_operator.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %pattern_type.51d1c4.1: type = pattern_type %T [template]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %T [template]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %MulWith.type.8b4: type = generic_interface_type @MulWith [concrete]\n// CHECK:STDOUT:   %MulWith.generic: %MulWith.type.8b4 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .MulWith = %Core.MulWith\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.MulWith: %MulWith.type.8b4 = import_ref Core//prelude/operators/arithmetic, MulWith, loaded [concrete = constants.%MulWith.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.51d1c4.1) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.51d1c4.1) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc6_34: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc6_19.1: type = splice_block %.loc6_19.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc6_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_15.2: type = symbolic_binding T, 0, template [template = %T.loc6_15.1 (constants.%T)]\n// CHECK:STDOUT:     %x.param: @F.%T.loc6_15.1 (%T) = value_param call_param0\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc6_15.2 [template = %T.loc6_15.1 (constants.%T)]\n// CHECK:STDOUT:     %x: @F.%T.loc6_15.1 (%T) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc6_15.2: type) {\n// CHECK:STDOUT:   %T.loc6_15.1: type = symbolic_binding T, 0, template [template = %T.loc6_15.1 (constants.%T)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.loc6_15.1 [template = %pattern_type (constants.%pattern_type.51d1c4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.loc6_15.1 [template = %require_complete (constants.%require_complete.944)]\n// CHECK:STDOUT:   %.loc11_11.3: <instruction> = refine_type_action %x.ref, %T.loc6_15.1 [template]\n// CHECK:STDOUT:   %.loc11_11.4: <instruction> = access_member_action %.loc11_11.1, n [template]\n// CHECK:STDOUT:   %.loc11_11.5: type = type_of_inst %.loc11_11.4 [template]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%T.loc6_15.1 (%T)) -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @F.%T.loc6_15.1 (%T) = name_ref x, %x\n// CHECK:STDOUT:     %.loc11_11.1: @F.%T.loc6_15.1 (%T) = splice_inst %.loc11_11.3\n// CHECK:STDOUT:     %.loc11_11.2: @F.%.loc11_11.5 (@F.%.loc11_11.5) = splice_inst %.loc11_11.4\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:     return <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_15.1 => constants.%T\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d1c4.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_unimplemented_value.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %C.elem: type = unbound_element_type %C, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.n: type = struct_type {.n: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.54b: <witness> = complete_type_witness %struct_type.n [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %c: %C = symbolic_binding c, 0, template [template]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %MulWith.type.8b4: type = generic_interface_type @MulWith [concrete]\n// CHECK:STDOUT:   %MulWith.generic: %MulWith.type.8b4 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .MulWith = %Core.MulWith\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.MulWith: %MulWith.type.8b4 = import_ref Core//prelude/operators/arithmetic, MulWith, loaded [concrete = constants.%MulWith.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = symbolic_binding_pattern c, 0, template [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc11_25: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %.loc11_19: type = splice_block %C.ref [concrete = constants.%C] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %c.loc11_15.2: %C = symbolic_binding c, 0, template [template = %c.loc11_15.1 (constants.%c)]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc5: %C.elem = field_decl n, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.n [concrete = constants.%complete_type.54b]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .n = %.loc5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%c.loc11_15.2: %C) {\n// CHECK:STDOUT:   %c.loc11_15.1: %C = symbolic_binding c, 0, template [template = %c.loc11_15.1 (constants.%c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %.loc16_11.2: <instruction> = access_member_action %c.ref, n [template]\n// CHECK:STDOUT:   %.loc16_11.3: type = type_of_inst %.loc16_11.2 [template]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %i32 {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %c.ref: %C = name_ref c, %c.loc11_15.2 [template = %c.loc11_15.1 (constants.%c)]\n// CHECK:STDOUT:     %.loc16_11.1: @F.%.loc16_11.3 (@F.%.loc16_11.3) = splice_inst %.loc16_11.2\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:     return <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%c) {\n// CHECK:STDOUT:   %c.loc11_15.1 => constants.%c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_unimplemented_convert.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %pattern_type.cac: type = pattern_type %Destroy.type [concrete]\n// CHECK:STDOUT:   %T.765: %Destroy.type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %T.binding.as_type.140: type = symbolic_binding_type T, 0, template, %T.765 [template]\n// CHECK:STDOUT:   %pattern_type.a64db1.2: type = pattern_type %T.binding.as_type.140 [template]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.6d1: <witness> = require_complete_type %T.binding.as_type.140 [template]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.112: type = facet_type <@ImplicitAs, @ImplicitAs(%T.binding.as_type.140)> [template]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %T.765, @Destroy [template]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type.cb2e47.2: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%T.765) [template]\n// CHECK:STDOUT:   %.d5f: type = fn_type_with_self_type %Destroy.WithSelf.Op.type.cb2e47.2, %T.765 [template]\n// CHECK:STDOUT:   %impl.elem0.a6b: %.d5f = impl_witness_access %Destroy.lookup_impl_witness, element0 [template]\n// CHECK:STDOUT:   %specific_impl_fn.761: <specific function> = specific_impl_function %impl.elem0.a6b, @Destroy.WithSelf.Op(%T.765) [template]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.cac = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type (%pattern_type.a64db1.2) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type (%pattern_type.a64db1.2) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_23: type = splice_block %Destroy.ref [concrete = constants.%Destroy.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %Destroy.ref: type = name_ref Destroy, imports.%Core.Destroy [concrete = constants.%Destroy.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_15.2: %Destroy.type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.765)]\n// CHECK:STDOUT:     %x.param: @F.%T.binding.as_type (%T.binding.as_type.140) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_36.1: type = splice_block %.loc4_36.2 [template = %T.binding.as_type (constants.%T.binding.as_type.140)] {\n// CHECK:STDOUT:       %T.ref.loc4: %Destroy.type = name_ref T, %T.loc4_15.2 [template = %T.loc4_15.1 (constants.%T.765)]\n// CHECK:STDOUT:       %T.as_type.loc4: type = facet_access_type %T.ref.loc4 [template = %T.binding.as_type (constants.%T.binding.as_type.140)]\n// CHECK:STDOUT:       %.loc4_36.2: type = converted %T.ref.loc4, %T.as_type.loc4 [template = %T.binding.as_type (constants.%T.binding.as_type.140)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @F.%T.binding.as_type (%T.binding.as_type.140) = value_binding x, %x.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc4_15.2: %Destroy.type) {\n// CHECK:STDOUT:   %T.loc4_15.1: %Destroy.type = symbolic_binding T, 0, template [template = %T.loc4_15.1 (constants.%T.765)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, template, %T.loc4_15.1 [template = %T.binding.as_type (constants.%T.binding.as_type.140)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T.binding.as_type [template = %pattern_type (constants.%pattern_type.a64db1.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T.binding.as_type [template = %require_complete (constants.%require_complete.6d1)]\n// CHECK:STDOUT:   %ImplicitAs.type.loc14_3.2: type = facet_type <@ImplicitAs, @ImplicitAs(%T.binding.as_type)> [template = %ImplicitAs.type.loc14_3.2 (constants.%ImplicitAs.type.112)]\n// CHECK:STDOUT:   %.loc14_3.3: <instruction> = access_member_action %ImplicitAs.type.loc14_3.1, Convert [template]\n// CHECK:STDOUT:   %.loc14_3.4: type = type_of_inst %.loc14_3.3 [template]\n// CHECK:STDOUT:   %Destroy.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc4_15.1, @Destroy [template = %Destroy.lookup_impl_witness (constants.%Destroy.lookup_impl_witness)]\n// CHECK:STDOUT:   %Destroy.WithSelf.Op.type: type = fn_type @Destroy.WithSelf.Op, @Destroy.WithSelf(%T.loc4_15.1) [template = %Destroy.WithSelf.Op.type (constants.%Destroy.WithSelf.Op.type.cb2e47.2)]\n// CHECK:STDOUT:   %.loc14_3.5: type = fn_type_with_self_type %Destroy.WithSelf.Op.type, %T.loc4_15.1 [template = %.loc14_3.5 (constants.%.d5f)]\n// CHECK:STDOUT:   %impl.elem0.loc14_3.2: @F.%.loc14_3.5 (%.d5f) = impl_witness_access %Destroy.lookup_impl_witness, element0 [template = %impl.elem0.loc14_3.2 (constants.%impl.elem0.a6b)]\n// CHECK:STDOUT:   %specific_impl_fn.loc14_3.2: <specific function> = specific_impl_function %impl.elem0.loc14_3.2, @Destroy.WithSelf.Op(%T.loc4_15.1) [template = %specific_impl_fn.loc14_3.2 (constants.%specific_impl_fn.761)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%T.binding.as_type (%T.binding.as_type.140)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %v.patt: @F.%pattern_type (%pattern_type.a64db1.2) = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:       %v.var_patt: @F.%pattern_type (%pattern_type.a64db1.2) = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v.var: ref @F.%T.binding.as_type (%T.binding.as_type.140) = var %v.var_patt\n// CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:     %ImplicitAs.type.loc14_3.1: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%T.binding.as_type.140)> [template = %ImplicitAs.type.loc14_3.2 (constants.%ImplicitAs.type.112)]\n// CHECK:STDOUT:     %.loc14_3.1: @F.%.loc14_3.4 (@F.%.loc14_3.4) = splice_inst %.loc14_3.3\n// CHECK:STDOUT:     %.loc14_3.2: @F.%T.binding.as_type (%T.binding.as_type.140) = converted %int_0, <error> [concrete = <error>]\n// CHECK:STDOUT:     assign %v.var, <error>\n// CHECK:STDOUT:     %.loc14_17.1: type = splice_block %.loc14_17.2 [template = %T.binding.as_type (constants.%T.binding.as_type.140)] {\n// CHECK:STDOUT:       %T.ref.loc14: %Destroy.type = name_ref T, %T.loc4_15.2 [template = %T.loc4_15.1 (constants.%T.765)]\n// CHECK:STDOUT:       %T.as_type.loc14: type = facet_access_type %T.ref.loc14 [template = %T.binding.as_type (constants.%T.binding.as_type.140)]\n// CHECK:STDOUT:       %.loc14_17.2: type = converted %T.ref.loc14, %T.as_type.loc14 [template = %T.binding.as_type (constants.%T.binding.as_type.140)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %v: ref @F.%T.binding.as_type (%T.binding.as_type.140) = ref_binding v, %v.var\n// CHECK:STDOUT:     name_binding_decl {\n// CHECK:STDOUT:       %w.patt: %pattern_type.7ce = ref_binding_pattern w [concrete]\n// CHECK:STDOUT:       %w.var_patt: %pattern_type.7ce = var_pattern %w.patt [concrete]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %w.var: ref %i32 = var %w.var_patt\n// CHECK:STDOUT:     %x.ref: @F.%T.binding.as_type (%T.binding.as_type.140) = name_ref x, %x\n// CHECK:STDOUT:     %.loc22: %i32 = converted %x.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:     assign %w.var, <error>\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %w: ref %i32 = ref_binding w, %w.var\n// CHECK:STDOUT:     %Destroy.Op.bound: <bound method> = bound_method %w.var, constants.%Destroy.Op\n// CHECK:STDOUT:     %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%w.var)\n// CHECK:STDOUT:     %impl.elem0.loc14_3.1: @F.%.loc14_3.5 (%.d5f) = impl_witness_access constants.%Destroy.lookup_impl_witness, element0 [template = %impl.elem0.loc14_3.2 (constants.%impl.elem0.a6b)]\n// CHECK:STDOUT:     %bound_method.loc14_3.1: <bound method> = bound_method %v.var, %impl.elem0.loc14_3.1\n// CHECK:STDOUT:     %specific_impl_fn.loc14_3.1: <specific function> = specific_impl_function %impl.elem0.loc14_3.1, @Destroy.WithSelf.Op(constants.%T.765) [template = %specific_impl_fn.loc14_3.2 (constants.%specific_impl_fn.761)]\n// CHECK:STDOUT:     %bound_method.loc14_3.2: <bound method> = bound_method %v.var, %specific_impl_fn.loc14_3.1\n// CHECK:STDOUT:     %Destroy.WithSelf.Op.call: init %empty_tuple.type = call %bound_method.loc14_3.2(%v.var)\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.765) {\n// CHECK:STDOUT:   %T.loc4_15.1 => constants.%T.765\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.140\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.a64db1.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/generic/template_dependence.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/generic/template_dependence.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/generic/template_dependence.carbon\n\n// --- type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F[template T:! type](x: T**) -> T* {\n  return *x;\n}\n//@dump-sem-ir-end\n\n// --- mixed.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn F(template T:! type, U:! type) -> (T, U) {\n  return F(T, U);\n}\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67db0b.1: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %ptr.e8f8f9.1: type = ptr_type %T.67db0b.1 [template]\n// CHECK:STDOUT:   %ptr.125: type = ptr_type %ptr.e8f8f9.1 [template]\n// CHECK:STDOUT:   %pattern_type.8bb: type = pattern_type %ptr.125 [template]\n// CHECK:STDOUT:   %.cb6cb9.1: Core.Form = init_form %ptr.e8f8f9.1 [template]\n// CHECK:STDOUT:   %pattern_type.4f4b84.1: type = pattern_type %ptr.e8f8f9.1 [template]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete.fbe: <witness> = require_complete_type %ptr.125 [template]\n// CHECK:STDOUT:   %require_complete.ef162c.1: <witness> = require_complete_type %ptr.e8f8f9.1 [template]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %.2f2: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.67db0b.1) [template]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness.2e6: <witness> = lookup_impl_witness %ptr.e8f8f9.1, @Copy [template]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.e8f8f9.1, (%Copy.lookup_impl_witness.2e6) [template]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.d82: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [template]\n// CHECK:STDOUT:   %.299: type = fn_type_with_self_type %Copy.WithSelf.Op.type.d82, %Copy.facet [template]\n// CHECK:STDOUT:   %impl.elem0.1c7: %.299 = impl_witness_access %Copy.lookup_impl_witness.2e6, element0 [template]\n// CHECK:STDOUT:   %specific_impl_fn.366: <specific function> = specific_impl_function %impl.elem0.1c7, @Copy.WithSelf.Op(%Copy.facet) [template]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:     %x.patt: @F.%pattern_type.loc5_25 (%pattern_type.8bb) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @F.%pattern_type.loc5_25 (%pattern_type.8bb) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type.loc5_33 (%pattern_type.4f4b84.1) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type.loc5_33 (%pattern_type.4f4b84.1) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc5_36: type = name_ref T, %T.loc5_15.2 [template = %T.loc5_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %ptr.loc5_37: type = ptr_type %T.ref.loc5_36 [template = %ptr.loc5_29.1 (constants.%ptr.e8f8f9.1)]\n// CHECK:STDOUT:     %.loc5_37.2: Core.Form = init_form %ptr.loc5_37 [template = %.loc5_37.1 (constants.%.cb6cb9.1)]\n// CHECK:STDOUT:     %.loc5_19.1: type = splice_block %.loc5_19.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc5_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_15.2: type = symbolic_binding T, 0, template [template = %T.loc5_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:     %x.param: @F.%ptr.loc5_30.1 (%ptr.125) = value_param call_param0\n// CHECK:STDOUT:     %.loc5_30: type = splice_block %ptr.loc5_30.2 [template = %ptr.loc5_30.1 (constants.%ptr.125)] {\n// CHECK:STDOUT:       %T.ref.loc5_28: type = name_ref T, %T.loc5_15.2 [template = %T.loc5_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:       %ptr.loc5_29.2: type = ptr_type %T.ref.loc5_28 [template = %ptr.loc5_29.1 (constants.%ptr.e8f8f9.1)]\n// CHECK:STDOUT:       %ptr.loc5_30.2: type = ptr_type %ptr.loc5_29.2 [template = %ptr.loc5_30.1 (constants.%ptr.125)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @F.%ptr.loc5_30.1 (%ptr.125) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @F.%ptr.loc5_29.1 (%ptr.e8f8f9.1) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @F.%ptr.loc5_29.1 (%ptr.e8f8f9.1) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc5_15.2: type) {\n// CHECK:STDOUT:   %T.loc5_15.1: type = symbolic_binding T, 0, template [template = %T.loc5_15.1 (constants.%T.67db0b.1)]\n// CHECK:STDOUT:   %ptr.loc5_29.1: type = ptr_type %T.loc5_15.1 [template = %ptr.loc5_29.1 (constants.%ptr.e8f8f9.1)]\n// CHECK:STDOUT:   %ptr.loc5_30.1: type = ptr_type %ptr.loc5_29.1 [template = %ptr.loc5_30.1 (constants.%ptr.125)]\n// CHECK:STDOUT:   %pattern_type.loc5_25: type = pattern_type %ptr.loc5_30.1 [template = %pattern_type.loc5_25 (constants.%pattern_type.8bb)]\n// CHECK:STDOUT:   %.loc5_37.1: Core.Form = init_form %ptr.loc5_29.1 [template = %.loc5_37.1 (constants.%.cb6cb9.1)]\n// CHECK:STDOUT:   %pattern_type.loc5_33: type = pattern_type %ptr.loc5_29.1 [template = %pattern_type.loc5_33 (constants.%pattern_type.4f4b84.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc5_26: <witness> = require_complete_type %ptr.loc5_30.1 [template = %require_complete.loc5_26 (constants.%require_complete.fbe)]\n// CHECK:STDOUT:   %require_complete.loc5_37: <witness> = require_complete_type %ptr.loc5_29.1 [template = %require_complete.loc5_37 (constants.%require_complete.ef162c.1)]\n// CHECK:STDOUT:   %.loc6_10.3: require_specific_def_type = require_specific_def @ptr.as.Copy.impl(%T.loc5_15.1) [template = %.loc6_10.3 (constants.%.2f2)]\n// CHECK:STDOUT:   %Copy.lookup_impl_witness: <witness> = lookup_impl_witness %ptr.loc5_29.1, @Copy [template = %Copy.lookup_impl_witness (constants.%Copy.lookup_impl_witness.2e6)]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %ptr.loc5_29.1, (%Copy.lookup_impl_witness) [template = %Copy.facet (constants.%Copy.facet)]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [template = %Copy.WithSelf.Op.type (constants.%Copy.WithSelf.Op.type.d82)]\n// CHECK:STDOUT:   %.loc6_10.4: type = fn_type_with_self_type %Copy.WithSelf.Op.type, %Copy.facet [template = %.loc6_10.4 (constants.%.299)]\n// CHECK:STDOUT:   %impl.elem0.loc6_10.2: @F.%.loc6_10.4 (%.299) = impl_witness_access %Copy.lookup_impl_witness, element0 [template = %impl.elem0.loc6_10.2 (constants.%impl.elem0.1c7)]\n// CHECK:STDOUT:   %specific_impl_fn.loc6_10.2: <specific function> = specific_impl_function %impl.elem0.loc6_10.2, @Copy.WithSelf.Op(%Copy.facet) [template = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.366)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @F.%ptr.loc5_30.1 (%ptr.125)) -> out %return.param: @F.%ptr.loc5_29.1 (%ptr.e8f8f9.1) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %x.ref: @F.%ptr.loc5_30.1 (%ptr.125) = name_ref x, %x\n// CHECK:STDOUT:     %.loc6_10.1: ref @F.%ptr.loc5_29.1 (%ptr.e8f8f9.1) = deref %x.ref\n// CHECK:STDOUT:     %.loc6_10.2: @F.%ptr.loc5_29.1 (%ptr.e8f8f9.1) = acquire_value %.loc6_10.1\n// CHECK:STDOUT:     %impl.elem0.loc6_10.1: @F.%.loc6_10.4 (%.299) = impl_witness_access constants.%Copy.lookup_impl_witness.2e6, element0 [template = %impl.elem0.loc6_10.2 (constants.%impl.elem0.1c7)]\n// CHECK:STDOUT:     %bound_method.loc6_10.1: <bound method> = bound_method %.loc6_10.2, %impl.elem0.loc6_10.1\n// CHECK:STDOUT:     %specific_impl_fn.loc6_10.1: <specific function> = specific_impl_function %impl.elem0.loc6_10.1, @Copy.WithSelf.Op(constants.%Copy.facet) [template = %specific_impl_fn.loc6_10.2 (constants.%specific_impl_fn.366)]\n// CHECK:STDOUT:     %bound_method.loc6_10.2: <bound method> = bound_method %.loc6_10.2, %specific_impl_fn.loc6_10.1\n// CHECK:STDOUT:     %Copy.WithSelf.Op.call: init @F.%ptr.loc5_29.1 (%ptr.e8f8f9.1) = call %bound_method.loc6_10.2(%.loc6_10.2)\n// CHECK:STDOUT:     return %Copy.WithSelf.Op.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T.67db0b.1) {\n// CHECK:STDOUT:   %T.loc5_15.1 => constants.%T.67db0b.1\n// CHECK:STDOUT:   %ptr.loc5_29.1 => constants.%ptr.e8f8f9.1\n// CHECK:STDOUT:   %ptr.loc5_30.1 => constants.%ptr.125\n// CHECK:STDOUT:   %pattern_type.loc5_25 => constants.%pattern_type.8bb\n// CHECK:STDOUT:   %.loc5_37.1 => constants.%.cb6cb9.1\n// CHECK:STDOUT:   %pattern_type.loc5_33 => constants.%pattern_type.4f4b84.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- mixed.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0, template [template]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 1 [symbolic]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%T, %U) [template]\n// CHECK:STDOUT:   %tuple.type.a5e: type = tuple_type (%T, %U) [template]\n// CHECK:STDOUT:   %.f18: Core.Form = init_form %tuple.type.a5e [template]\n// CHECK:STDOUT:   %pattern_type.eee: type = pattern_type %tuple.type.a5e [template]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %tuple.type.a5e [template]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%T, %U) [template]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0, template [concrete]\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 1 [concrete]\n// CHECK:STDOUT:     %return.patt: @F.%pattern_type (%pattern_type.eee) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @F.%pattern_type (%pattern_type.eee) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc5: type = name_ref T, %T.loc5_15.2 [template = %T.loc5_15.1 (constants.%T)]\n// CHECK:STDOUT:     %U.ref.loc5: type = name_ref U, %U.loc5_25.2 [symbolic = %U.loc5_25.1 (constants.%U)]\n// CHECK:STDOUT:     %.loc5_43.3: %tuple.type.24b = tuple_literal (%T.ref.loc5, %U.ref.loc5) [template = %tuple (constants.%tuple)]\n// CHECK:STDOUT:     %.loc5_43.4: type = converted %.loc5_43.3, constants.%tuple.type.a5e [template = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:     %.loc5_43.5: Core.Form = init_form %.loc5_43.4 [template = %.loc5_43.2 (constants.%.f18)]\n// CHECK:STDOUT:     %.loc5_19.1: type = splice_block %.loc5_19.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc5_19.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_15.2: type = symbolic_binding T, 0, template [template = %T.loc5_15.1 (constants.%T)]\n// CHECK:STDOUT:     %.loc5_29.1: type = splice_block %.loc5_29.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc5_29.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc5_25.2: type = symbolic_binding U, 1 [symbolic = %U.loc5_25.1 (constants.%U)]\n// CHECK:STDOUT:     %return.param: ref @F.%tuple.type (%tuple.type.a5e) = out_param call_param0\n// CHECK:STDOUT:     %return: ref @F.%tuple.type (%tuple.type.a5e) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc5_15.2: type, %U.loc5_25.2: type) {\n// CHECK:STDOUT:   %T.loc5_15.1: type = symbolic_binding T, 0, template [template = %T.loc5_15.1 (constants.%T)]\n// CHECK:STDOUT:   %U.loc5_25.1: type = symbolic_binding U, 1 [symbolic = %U.loc5_25.1 (constants.%U)]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%T.loc5_15.1, %U.loc5_25.1) [template = %tuple (constants.%tuple)]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%T.loc5_15.1, %U.loc5_25.1) [template = %tuple.type (constants.%tuple.type.a5e)]\n// CHECK:STDOUT:   %.loc5_43.2: Core.Form = init_form %tuple.type [template = %.loc5_43.2 (constants.%.f18)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %tuple.type [template = %pattern_type (constants.%pattern_type.eee)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %tuple.type [template = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:   %F.specific_fn.loc6_10.2: <specific function> = specific_function constants.%F, @F(%T.loc5_15.1, %U.loc5_25.1) [template = %F.specific_fn.loc6_10.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @F.%tuple.type (%tuple.type.a5e) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %T.ref.loc6: type = name_ref T, %T.loc5_15.2 [template = %T.loc5_15.1 (constants.%T)]\n// CHECK:STDOUT:     %U.ref.loc6: type = name_ref U, %U.loc5_25.2 [symbolic = %U.loc5_25.1 (constants.%U)]\n// CHECK:STDOUT:     %F.specific_fn.loc6_10.1: <specific function> = specific_function %F.ref, @F(constants.%T, constants.%U) [template = %F.specific_fn.loc6_10.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:     %.loc5_43.1: ref @F.%tuple.type (%tuple.type.a5e) = splice_block %return.param {}\n// CHECK:STDOUT:     %F.call: init @F.%tuple.type (%tuple.type.a5e) to %.loc5_43.1 = call %F.specific_fn.loc6_10.1()\n// CHECK:STDOUT:     return %F.call to %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T, constants.%U) {\n// CHECK:STDOUT:   %T.loc5_15.1 => constants.%T\n// CHECK:STDOUT:   %U.loc5_25.1 => constants.%U\n// CHECK:STDOUT:   %tuple => constants.%tuple\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.a5e\n// CHECK:STDOUT:   %.loc5_43.2 => constants.%.f18\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.eee\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete\n// CHECK:STDOUT:   %F.specific_fn.loc6_10.2 => constants.%F.specific_fn\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/global/basics.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/global/basics.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/global/basics.carbon\n\n// --- decl.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nvar a: {};\n//@dump-sem-ir-end\n\n// --- simple_init.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nvar a: {} = {};\n//@dump-sem-ir-end\n\n// --- simple_init_with_fn.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn Make() -> {};\n\n//@dump-sem-ir-begin\nvar a: {} = Make();\n//@dump-sem-ir-end\n\n// --- class_init.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {}\n\n//@dump-sem-ir-begin\nvar a: A = {};\n//@dump-sem-ir-end\n\n// --- class_init_from_fn.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass A {}\n\nfn Make() -> A;\n\n//@dump-sem-ir-begin\nvar a: A = Make();\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.a96: type = pattern_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.type.6c6: type = fn_type @T.as.DefaultOrUnformed.impl.Op, @T.as.DefaultOrUnformed.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.ae1: %T.as.DefaultOrUnformed.impl.Op.type.6c6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness.3f9: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table, @T.as.DefaultOrUnformed.impl(%empty_struct_type) [concrete]\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %empty_struct_type, (%DefaultOrUnformed.impl_witness.3f9) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.01d: @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op.type (%T.as.DefaultOrUnformed.impl.Op.type.6c6) = import_ref Core//prelude/parts/default, loc{{\\d+_\\d+}}, loaded [symbolic = @T.as.DefaultOrUnformed.impl.%T.as.DefaultOrUnformed.impl.Op (constants.%T.as.DefaultOrUnformed.impl.Op.ae1)]\n// CHECK:STDOUT:   %DefaultOrUnformed.impl_witness_table = impl_witness_table (%Core.import_ref.01d), @T.as.DefaultOrUnformed.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.a96 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.a96 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_struct_type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_9.1: type = splice_block %.loc4_9.3 [concrete = constants.%empty_struct_type] {\n// CHECK:STDOUT:     %.loc4_9.2: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc4_9.3: type = converted %.loc4_9.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_struct_type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%empty_struct_type, (constants.%DefaultOrUnformed.impl_witness.3f9) [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %.loc4_10.1: %DefaultOrUnformed.type = converted constants.%empty_struct_type, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]\n// CHECK:STDOUT:   %as_type: type = facet_access_type %.loc4_10.1 [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   %.loc4_10.2: type = converted %.loc4_10.1, %as_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %T.as.DefaultOrUnformed.impl.Op.call: init %empty_struct_type = call %T.as.DefaultOrUnformed.impl.Op.specific_fn()\n// CHECK:STDOUT:   assign file.%a.var, %T.as.DefaultOrUnformed.impl.Op.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- simple_init.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_struct_type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc4_9.1: type = splice_block %.loc4_9.3 [concrete = constants.%empty_struct_type] {\n// CHECK:STDOUT:     %.loc4_9.2: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc4_9.3: type = converted %.loc4_9.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_struct_type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc4_14.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc4_14.2: init %empty_struct_type = struct_init () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc4_1: init %empty_struct_type = converted %.loc4_14.1, %.loc4_14.2 [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   assign file.%a.var, %.loc4_1\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- simple_init_with_fn.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_struct_type [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %empty_struct_type = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %.loc6_9.1: type = splice_block %.loc6_9.3 [concrete = constants.%empty_struct_type] {\n// CHECK:STDOUT:     %.loc6_9.2: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc6_9.3: type = converted %.loc6_9.2, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %empty_struct_type = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %Make.call: init %empty_struct_type = call %Make.ref()\n// CHECK:STDOUT:   assign file.%a.var, %Make.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- class_init.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.val: %A = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %A = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %A.ref: type = name_ref A, %A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %a: ref %A = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc6_13.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc6_13.2: init %A to file.%a.var = class_init () [concrete = constants.%A.val]\n// CHECK:STDOUT:   %.loc6_1: init %A = converted %.loc6_13.1, %.loc6_13.2 [concrete = constants.%A.val]\n// CHECK:STDOUT:   assign file.%a.var, %.loc6_1\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- class_init_from_fn.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A: type = class_type @A [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %A [concrete]\n// CHECK:STDOUT:   %Make.type: type = fn_type @Make [concrete]\n// CHECK:STDOUT:   %Make: %Make.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %A = var %a.var_patt [concrete]\n// CHECK:STDOUT:   %A.ref: type = name_ref A, %A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %a: ref %A = ref_binding a, %a.var [concrete = %a.var]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Make.ref: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]\n// CHECK:STDOUT:   %.loc8: ref %A = splice_block file.%a.var [concrete = file.%a.var] {}\n// CHECK:STDOUT:   %Make.call: init %A to %.loc8 = call %Make.ref()\n// CHECK:STDOUT:   assign file.%a.var, %Make.call\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/if/basics.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/bool.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/if/basics.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/if/basics.carbon\n\n// --- else.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {}\nfn G() {}\nfn H() {}\n\n//@dump-sem-ir-begin\nfn If(b: bool) {\n  if (b) {\n    F();\n  } else {\n    G();\n  }\n  H();\n}\n//@dump-sem-ir-end\n\n// --- no_else.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn F() {}\nfn G() {}\n\n//@dump-sem-ir-begin\nfn If(b: bool) {\n  if (b) {\n    F();\n  }\n  G();\n}\n//@dump-sem-ir-end\n\n// --- unreachable_fallthrough.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n//@dump-sem-ir-begin\nfn If(b: bool) -> bool {\n  if (b) {\n    return false;\n  } else {\n    return true;\n  }\n  // Missing return here is OK.\n}\n//@dump-sem-ir-end\n\n// --- fail_reachable_fallthrough.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn If1(b: bool) -> bool {\n  if (b) {\n    return false;\n  } else {\n  }\n// CHECK:STDERR: fail_reachable_fallthrough.carbon:[[@LINE+4]]:1: error: missing `return` at end of function with declared return type [MissingReturnStatement]\n// CHECK:STDERR: }\n// CHECK:STDERR: ^\n// CHECK:STDERR:\n}\n\nfn If2(b: bool) -> bool {\n  if (b) {\n  } else {\n    return true;\n  }\n// CHECK:STDERR: fail_reachable_fallthrough.carbon:[[@LINE+4]]:1: error: missing `return` at end of function with declared return type [MissingReturnStatement]\n// CHECK:STDERR: }\n// CHECK:STDERR: ^\n// CHECK:STDERR:\n}\n\nfn If3(b: bool) -> bool {\n  if (b) {\n    return false;\n  }\n// CHECK:STDERR: fail_reachable_fallthrough.carbon:[[@LINE+4]]:1: error: missing `return` at end of function with declared return type [MissingReturnStatement]\n// CHECK:STDERR: }\n// CHECK:STDERR: ^\n// CHECK:STDERR:\n}\n\n// --- fail_scope.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nfn VarScope(b: bool) -> bool {\n  if (b) {\n    var n: bool = true;\n    return n;\n  }\n  // CHECK:STDERR: fail_scope.carbon:[[@LINE+4]]:10: error: name `n` not found [NameNotFound]\n  // CHECK:STDERR:   return n;\n  // CHECK:STDERR:          ^\n  // CHECK:STDERR:\n  return n;\n}\n\n// CHECK:STDOUT: --- else.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]\n// CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %If.type: type = fn_type @If [concrete]\n// CHECK:STDOUT:   %If: %If.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %If.decl: %If.type = fn_decl @If [concrete = constants.%If] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %b.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc8: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @If(%b.param: bool) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b\n// CHECK:STDOUT:   if %b.ref br !if.then else br !if.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.then:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   br !if.done\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.else:\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.ref()\n// CHECK:STDOUT:   br !if.done\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.done:\n// CHECK:STDOUT:   %H.ref: %H.type = name_ref H, file.%H.decl [concrete = constants.%H]\n// CHECK:STDOUT:   %H.call: init %empty_tuple.type = call %H.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- no_else.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %If.type: type = fn_type @If [concrete]\n// CHECK:STDOUT:   %If: %If.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %If.decl: %If.type = fn_decl @If [concrete = constants.%If] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %b.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc7: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @If(%b.param: bool) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b\n// CHECK:STDOUT:   if %b.ref br !if.then else br !if.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.then:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.ref()\n// CHECK:STDOUT:   br !if.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.else:\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- unreachable_fallthrough.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %.f34: Core.Form = init_form bool [concrete]\n// CHECK:STDOUT:   %If.type: type = fn_type @If [concrete]\n// CHECK:STDOUT:   %If: %If.type = struct_value () [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.348: <witness> = impl_witness imports.%Copy.impl_witness_table.3cc [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value bool, (%Copy.impl_witness.348) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.6dd: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.86d: type = fn_type_with_self_type %Copy.WithSelf.Op.type.6dd, %Copy.facet [concrete]\n// CHECK:STDOUT:   %bool.as.Copy.impl.Op.type: type = fn_type @bool.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %bool.as.Copy.impl.Op: %bool.as.Copy.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %bool.as.Copy.impl.Op.bound.082: <bound method> = bound_method %false, %bool.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %bool.as.Copy.impl.Op.bound.12b: <bound method> = bound_method %true, %bool.as.Copy.impl.Op [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.595: %bool.as.Copy.impl.Op.type = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [concrete = constants.%bool.as.Copy.impl.Op]\n// CHECK:STDOUT:   %Copy.impl_witness_table.3cc = impl_witness_table (%Core.import_ref.595), @bool.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %If.decl: %If.type = fn_decl @If [concrete = constants.%If] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_19.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc4_19.2: Core.Form = init_form %.loc4_19.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %b.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc4_10: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param1\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @If(%b.param: bool) -> out %return.param: bool {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b\n// CHECK:STDOUT:   if %b.ref br !if.then else br !if.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.then:\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:   %impl.elem0.loc6: %.86d = impl_witness_access constants.%Copy.impl_witness.348, element0 [concrete = constants.%bool.as.Copy.impl.Op]\n// CHECK:STDOUT:   %bound_method.loc6: <bound method> = bound_method %false, %impl.elem0.loc6 [concrete = constants.%bool.as.Copy.impl.Op.bound.082]\n// CHECK:STDOUT:   %bool.as.Copy.impl.Op.call.loc6: init bool = call %bound_method.loc6(%false) [concrete = constants.%false]\n// CHECK:STDOUT:   return %bool.as.Copy.impl.Op.call.loc6\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.else:\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:   %impl.elem0.loc8: %.86d = impl_witness_access constants.%Copy.impl_witness.348, element0 [concrete = constants.%bool.as.Copy.impl.Op]\n// CHECK:STDOUT:   %bound_method.loc8: <bound method> = bound_method %true, %impl.elem0.loc8 [concrete = constants.%bool.as.Copy.impl.Op.bound.12b]\n// CHECK:STDOUT:   %bool.as.Copy.impl.Op.call.loc8: init bool = call %bound_method.loc8(%true) [concrete = constants.%true]\n// CHECK:STDOUT:   return %bool.as.Copy.impl.Op.call.loc8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/if_expr/basic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/if_expr/basic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/if_expr/basic.carbon\n\nfn F(b: bool, n: i32, m: i32) -> i32 {\n  var x: array(i32, 1) = (0,);\n  return if b then x[m] else x[n];\n}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %array_type: type = array_type %int_1, %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.a98: type = pattern_type %array_type [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %tuple.type.985: type = tuple_type (Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.4f2: %tuple.type.985 = tuple_value (%int_0.5c6) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %array: %array_type = tuple_value (%int_0.6a9) [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:     %m.patt: %pattern_type.7ce = value_binding_pattern m [concrete]\n// CHECK:STDOUT:     %m.param_patt: %pattern_type.7ce = value_param_pattern %m.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc15_34: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15_34: Core.Form = init_form %i32.loc15_34 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %b.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc15_9: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param1\n// CHECK:STDOUT:     %i32.loc15_18: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:     %m.param: %i32 = value_param call_param2\n// CHECK:STDOUT:     %i32.loc15_26: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %m: %i32 = value_binding m, %m.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param3\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%b.param: bool, %n.param: %i32, %m.param: %i32) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type.a98 = ref_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.var_patt: %pattern_type.a98 = var_pattern %x.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x.var: ref %array_type = var %x.var_patt\n// CHECK:STDOUT:   %int_0.loc16_27: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %.loc16_29.1: %tuple.type.985 = tuple_literal (%int_0.loc16_27) [concrete = constants.%tuple.4f2]\n// CHECK:STDOUT:   %impl.elem0.loc16: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc16_29.1: <bound method> = bound_method %int_0.loc16_27, %impl.elem0.loc16 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn.loc16: <specific function> = specific_function %impl.elem0.loc16, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_29.2: <bound method> = bound_method %int_0.loc16_27, %specific_fn.loc16 [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc16_29.2(%int_0.loc16_27) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc16_29.2: init %i32 = converted %int_0.loc16_27, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %int_0.loc16_29: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:   %.loc16_29.3: ref %i32 = array_index %x.var, %int_0.loc16_29\n// CHECK:STDOUT:   %.loc16_29.4: init %i32 to %.loc16_29.3 = in_place_init %.loc16_29.2 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc16_29.5: init %array_type to %x.var = array_init (%.loc16_29.4) [concrete = constants.%array]\n// CHECK:STDOUT:   %.loc16_3: init %array_type = converted %.loc16_29.1, %.loc16_29.5 [concrete = constants.%array]\n// CHECK:STDOUT:   assign %x.var, %.loc16_3\n// CHECK:STDOUT:   %.loc16_22: type = splice_block %array_type [concrete = constants.%array_type] {\n// CHECK:STDOUT:     %i32.loc16: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:     %array_type: type = array_type %int_1, %i32.loc16 [concrete = constants.%array_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: ref %array_type = ref_binding x, %x.var\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b\n// CHECK:STDOUT:   if %b.ref br !if.expr.then else br !if.expr.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then:\n// CHECK:STDOUT:   %x.ref.loc17_20: ref %array_type = name_ref x, %x\n// CHECK:STDOUT:   %m.ref: %i32 = name_ref m, %m\n// CHECK:STDOUT:   %.loc17_23.1: ref %i32 = array_index %x.ref.loc17_20, %m.ref\n// CHECK:STDOUT:   %.loc17_23.2: %i32 = acquire_value %.loc17_23.1\n// CHECK:STDOUT:   br !if.expr.result(%.loc17_23.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else:\n// CHECK:STDOUT:   %x.ref.loc17_30: ref %array_type = name_ref x, %x\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %.loc17_33.1: ref %i32 = array_index %x.ref.loc17_30, %n.ref\n// CHECK:STDOUT:   %.loc17_33.2: %i32 = acquire_value %.loc17_33.1\n// CHECK:STDOUT:   br !if.expr.result(%.loc17_33.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result:\n// CHECK:STDOUT:   %.loc17_10: %i32 = block_arg !if.expr.result\n// CHECK:STDOUT:   %impl.elem0.loc17: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc17_10.1: <bound method> = bound_method %.loc17_10, %impl.elem0.loc17\n// CHECK:STDOUT:   %specific_fn.loc17: <specific function> = specific_function %impl.elem0.loc17, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc17_10.2: <bound method> = bound_method %.loc17_10, %specific_fn.loc17\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc17_10.2(%.loc17_10)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %x.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%x.var)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %array_type) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/if_expr/constant_condition.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/if_expr/constant_condition.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/if_expr/constant_condition.carbon\n\nfn A() -> i32 { return 1; }\nfn B() -> i32 { return 2; }\n\nfn F() -> i32 {\n  return if true then A() else B();\n}\n\nfn G() -> i32 {\n  return if false then A() else B();\n}\n\nfn Constant() -> i32 {\n  var v: if true then i32 else i32* = 1;\n  var w: if false then i32 else i32* = &v;\n  return *w;\n}\n\nfn PartiallyConstant(t: type) -> i32 {\n  var v: if true then i32 else t = 1;\n  var w: if false then t else i32* = &v;\n  return *w;\n}\n\n// CHECK:STDOUT: --- constant_condition.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.2d4: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%T.67d) [symbolic]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.74e: %ptr.as.Copy.impl.Op.type.2d4 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.de4: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.de4) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet.de4 [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %Constant.type: type = fn_type @Constant [concrete]\n// CHECK:STDOUT:   %Constant: %Constant.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr.235: type = ptr_type %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.fe8: type = pattern_type %ptr.235 [concrete]\n// CHECK:STDOUT:   %Copy.impl_witness.843: <witness> = impl_witness imports.%Copy.impl_witness_table.c3a, @ptr.as.Copy.impl(%i32) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.type.c3c: type = fn_type @ptr.as.Copy.impl.Op, @ptr.as.Copy.impl(%i32) [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.011: %ptr.as.Copy.impl.Op.type.c3c = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet.a7b: %Copy.type = facet_value %ptr.235, (%Copy.impl_witness.843) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.e01: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet.a7b) [concrete]\n// CHECK:STDOUT:   %.a62: type = fn_type_with_self_type %Copy.WithSelf.Op.type.e01, %Copy.facet.a7b [concrete]\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %ptr.as.Copy.impl.Op.011, @ptr.as.Copy.impl.Op(%i32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc28 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc27 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %PartiallyConstant.type: type = fn_type @PartiallyConstant [concrete]\n// CHECK:STDOUT:   %PartiallyConstant: %PartiallyConstant.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.import_ref.203: @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op.type (%ptr.as.Copy.impl.Op.type.2d4) = import_ref Core//prelude/parts/copy, loc{{\\d+_\\d+}}, loaded [symbolic = @ptr.as.Copy.impl.%ptr.as.Copy.impl.Op (constants.%ptr.as.Copy.impl.Op.74e)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.c3a = impl_witness_table (%Core.import_ref.203), @ptr.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:     .Constant = %Constant.decl\n// CHECK:STDOUT:     .PartiallyConstant = %PartiallyConstant.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15_11: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16_11: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc18: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc22: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Constant.decl: %Constant.type = fn_decl @Constant [concrete = constants.%Constant] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc26: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc26: Core.Form = init_form %i32.loc26 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %PartiallyConstant.decl: %PartiallyConstant.type = fn_decl @PartiallyConstant [concrete = constants.%PartiallyConstant] {\n// CHECK:STDOUT:     %t.patt: %pattern_type.98f = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: %pattern_type.98f = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32.loc32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc32_34: Core.Form = init_form %i32.loc32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %t.param: type = value_param call_param0\n// CHECK:STDOUT:     %.loc32_25: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %t: type = value_binding t, %t.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc15_25.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_25.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc15_25.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc15_25: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   return %.loc15_25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc16_25.1: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_25.2: <bound method> = bound_method %int_2, %specific_fn [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc16_25.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc16_25: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   return %.loc16_25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:   if %true br !if.expr.then else br !if.expr.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %i32 = call %A.ref()\n// CHECK:STDOUT:   %.loc19_25.1: %i32 = value_of_initializer %A.call\n// CHECK:STDOUT:   %.loc19_25.2: %i32 = converted %A.call, %.loc19_25.1\n// CHECK:STDOUT:   br !if.expr.result(%.loc19_25.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else:\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %B.call: init %i32 = call %B.ref()\n// CHECK:STDOUT:   %.loc19_27.1: %i32 = value_of_initializer %B.call\n// CHECK:STDOUT:   %.loc19_27.2: %i32 = converted %B.call, %.loc19_27.1\n// CHECK:STDOUT:   br !if.expr.result(%.loc19_27.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result:\n// CHECK:STDOUT:   %.loc19_10: %i32 = block_arg !if.expr.result\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc19_10.1: <bound method> = bound_method %.loc19_10, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc19_10.2: <bound method> = bound_method %.loc19_10, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc19_10.2(%.loc19_10)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:   if %false br !if.expr.then else br !if.expr.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %i32 = call %A.ref()\n// CHECK:STDOUT:   %.loc23_26.1: %i32 = value_of_initializer %A.call\n// CHECK:STDOUT:   %.loc23_26.2: %i32 = converted %A.call, %.loc23_26.1\n// CHECK:STDOUT:   br !if.expr.result(%.loc23_26.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else:\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %B.call: init %i32 = call %B.ref()\n// CHECK:STDOUT:   %.loc23_28.1: %i32 = value_of_initializer %B.call\n// CHECK:STDOUT:   %.loc23_28.2: %i32 = converted %B.call, %.loc23_28.1\n// CHECK:STDOUT:   br !if.expr.result(%.loc23_28.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result:\n// CHECK:STDOUT:   %.loc23_10: %i32 = block_arg !if.expr.result\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc23_10.1: <bound method> = bound_method %.loc23_10, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc23_10.2: <bound method> = bound_method %.loc23_10, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc23_10.2(%.loc23_10)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Constant() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.7ce = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.7ce = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %i32 = var %v.var_patt\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc27: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc27_3.1: <bound method> = bound_method %int_1, %impl.elem0.loc27 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc27: <specific function> = specific_function %impl.elem0.loc27, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc27_3.2: <bound method> = bound_method %int_1, %specific_fn.loc27 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc27_3.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc27_3: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   assign %v.var, %.loc27_3\n// CHECK:STDOUT:   br !.loc27_13\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc27_13:\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:   if %true br !if.expr.then.loc27 else br !if.expr.else.loc27\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then.loc27:\n// CHECK:STDOUT:   %i32.loc27_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   br !if.expr.result.loc27(%i32.loc27_23)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else.loc27:\n// CHECK:STDOUT:   %i32.loc27_32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %ptr.loc27: type = ptr_type %i32.loc27_32 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:   br !if.expr.result.loc27(%ptr.loc27)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result.loc27:\n// CHECK:STDOUT:   %.loc27_10: type = block_arg !if.expr.result.loc27 [concrete = constants.%i32]\n// CHECK:STDOUT:   br !.loc27_7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc27_7:\n// CHECK:STDOUT:   %v: ref %i32 = ref_binding v, %v.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %w.patt: %pattern_type.fe8 = ref_binding_pattern w [concrete]\n// CHECK:STDOUT:     %w.var_patt: %pattern_type.fe8 = var_pattern %w.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %w.var: ref %ptr.235 = var %w.var_patt\n// CHECK:STDOUT:   %v.ref: ref %i32 = name_ref v, %v\n// CHECK:STDOUT:   %addr: %ptr.235 = addr_of %v.ref\n// CHECK:STDOUT:   %impl.elem0.loc28: %.a62 = impl_witness_access constants.%Copy.impl_witness.843, element0 [concrete = constants.%ptr.as.Copy.impl.Op.011]\n// CHECK:STDOUT:   %bound_method.loc28_40.1: <bound method> = bound_method %addr, %impl.elem0.loc28\n// CHECK:STDOUT:   %specific_fn.loc28: <specific function> = specific_function %impl.elem0.loc28, @ptr.as.Copy.impl.Op(constants.%i32) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc28_40.2: <bound method> = bound_method %addr, %specific_fn.loc28\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.235 = call %bound_method.loc28_40.2(%addr)\n// CHECK:STDOUT:   assign %w.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   br !.loc28_13\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc28_13:\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:   if %false br !if.expr.then.loc28 else br !if.expr.else.loc28\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then.loc28:\n// CHECK:STDOUT:   %i32.loc28_24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   br !if.expr.result.loc28(%i32.loc28_24)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else.loc28:\n// CHECK:STDOUT:   %i32.loc28_33: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %ptr.loc28: type = ptr_type %i32.loc28_33 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:   br !if.expr.result.loc28(%ptr.loc28)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result.loc28:\n// CHECK:STDOUT:   %.loc28: type = block_arg !if.expr.result.loc28 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:   br !.loc28_7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc28_7:\n// CHECK:STDOUT:   %w: ref %ptr.235 = ref_binding w, %w.var\n// CHECK:STDOUT:   %w.ref: ref %ptr.235 = name_ref w, %w\n// CHECK:STDOUT:   %.loc29_11: %ptr.235 = acquire_value %w.ref\n// CHECK:STDOUT:   %.loc29_10.1: ref %i32 = deref %.loc29_11\n// CHECK:STDOUT:   %.loc29_10.2: %i32 = acquire_value %.loc29_10.1\n// CHECK:STDOUT:   %impl.elem0.loc29: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc29_10.1: <bound method> = bound_method %.loc29_10.2, %impl.elem0.loc29\n// CHECK:STDOUT:   %specific_fn.loc29: <specific function> = specific_function %impl.elem0.loc29, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc29_10.2: <bound method> = bound_method %.loc29_10.2, %specific_fn.loc29\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc29_10.2(%.loc29_10.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc28: <bound method> = bound_method %w.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc28: init %empty_tuple.type = call %Destroy.Op.bound.loc28(%w.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc27: <bound method> = bound_method %v.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc27: init %empty_tuple.type = call %Destroy.Op.bound.loc27(%v.var)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc28(%self.param: ref %ptr.235) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc27(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @PartiallyConstant(%t.param: type) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: %pattern_type.7ce = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: %pattern_type.7ce = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref %i32 = var %v.var_patt\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc33: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc33_3.1: <bound method> = bound_method %int_1, %impl.elem0.loc33 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc33: <specific function> = specific_function %impl.elem0.loc33, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc33_3.2: <bound method> = bound_method %int_1, %specific_fn.loc33 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc33_3.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc33_3: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   assign %v.var, %.loc33_3\n// CHECK:STDOUT:   br !.loc33_13\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc33_13:\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:   if %true br !if.expr.then.loc33 else br !if.expr.else.loc33\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then.loc33:\n// CHECK:STDOUT:   %i32.loc33: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   br !if.expr.result.loc33(%i32.loc33)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else.loc33:\n// CHECK:STDOUT:   %t.ref.loc33: type = name_ref t, %t\n// CHECK:STDOUT:   br !if.expr.result.loc33(%t.ref.loc33)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result.loc33:\n// CHECK:STDOUT:   %.loc33_10: type = block_arg !if.expr.result.loc33 [concrete = constants.%i32]\n// CHECK:STDOUT:   br !.loc33_7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc33_7:\n// CHECK:STDOUT:   %v: ref %i32 = ref_binding v, %v.var\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %w.patt: %pattern_type.fe8 = ref_binding_pattern w [concrete]\n// CHECK:STDOUT:     %w.var_patt: %pattern_type.fe8 = var_pattern %w.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %w.var: ref %ptr.235 = var %w.var_patt\n// CHECK:STDOUT:   %v.ref: ref %i32 = name_ref v, %v\n// CHECK:STDOUT:   %addr: %ptr.235 = addr_of %v.ref\n// CHECK:STDOUT:   %impl.elem0.loc34: %.a62 = impl_witness_access constants.%Copy.impl_witness.843, element0 [concrete = constants.%ptr.as.Copy.impl.Op.011]\n// CHECK:STDOUT:   %bound_method.loc34_38.1: <bound method> = bound_method %addr, %impl.elem0.loc34\n// CHECK:STDOUT:   %specific_fn.loc34: <specific function> = specific_function %impl.elem0.loc34, @ptr.as.Copy.impl.Op(constants.%i32) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc34_38.2: <bound method> = bound_method %addr, %specific_fn.loc34\n// CHECK:STDOUT:   %ptr.as.Copy.impl.Op.call: init %ptr.235 = call %bound_method.loc34_38.2(%addr)\n// CHECK:STDOUT:   assign %w.var, %ptr.as.Copy.impl.Op.call\n// CHECK:STDOUT:   br !.loc34_13\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc34_13:\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:   if %false br !if.expr.then.loc34 else br !if.expr.else.loc34\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then.loc34:\n// CHECK:STDOUT:   %t.ref.loc34: type = name_ref t, %t\n// CHECK:STDOUT:   br !if.expr.result.loc34(%t.ref.loc34)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else.loc34:\n// CHECK:STDOUT:   %i32.loc34: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %ptr: type = ptr_type %i32.loc34 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:   br !if.expr.result.loc34(%ptr)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result.loc34:\n// CHECK:STDOUT:   %.loc34: type = block_arg !if.expr.result.loc34 [concrete = constants.%ptr.235]\n// CHECK:STDOUT:   br !.loc34_7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc34_7:\n// CHECK:STDOUT:   %w: ref %ptr.235 = ref_binding w, %w.var\n// CHECK:STDOUT:   %w.ref: ref %ptr.235 = name_ref w, %w\n// CHECK:STDOUT:   %.loc35_11: %ptr.235 = acquire_value %w.ref\n// CHECK:STDOUT:   %.loc35_10.1: ref %i32 = deref %.loc35_11\n// CHECK:STDOUT:   %.loc35_10.2: %i32 = acquire_value %.loc35_10.1\n// CHECK:STDOUT:   %impl.elem0.loc35: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc35_10.1: <bound method> = bound_method %.loc35_10.2, %impl.elem0.loc35\n// CHECK:STDOUT:   %specific_fn.loc35: <specific function> = specific_function %impl.elem0.loc35, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc35_10.2: <bound method> = bound_method %.loc35_10.2, %specific_fn.loc35\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc35_10.2(%.loc35_10.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc34: <bound method> = bound_method %w.var, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc34: init %empty_tuple.type = call %Destroy.Op.bound.loc34(%w.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc33: <bound method> = bound_method %v.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc33: init %empty_tuple.type = call %Destroy.Op.bound.loc33(%v.var)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/if_expr/control_flow.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/if_expr/control_flow.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/if_expr/control_flow.carbon\n\nfn A() -> i32 { return 1; }\nfn B() -> i32 { return 2; }\n\nfn F(b: bool) -> i32 {\n  return if b then A() else B();\n}\n\n// CHECK:STDOUT: --- control_flow.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %A.type: type = fn_type @A [concrete]\n// CHECK:STDOUT:   %A: %A.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %B.type: type = fn_type @B [concrete]\n// CHECK:STDOUT:   %B: %B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .B = %B.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: %A.type = fn_decl @A [concrete = constants.%A] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15_11: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %B.decl: %B.type = fn_decl @B [concrete = constants.%B] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc16_11: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param0\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc18_18: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %b.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc18_9: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @A() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc15_25.1: <bound method> = bound_method %int_1, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_25.2: <bound method> = bound_method %int_1, %specific_fn [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc15_25.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc15_25: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   return %.loc15_25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @B() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc16_25.1: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_25.2: <bound method> = bound_method %int_2, %specific_fn [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc16_25.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc16_25: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   return %.loc16_25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%b.param: bool) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b\n// CHECK:STDOUT:   if %b.ref br !if.expr.then else br !if.expr.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then:\n// CHECK:STDOUT:   %A.ref: %A.type = name_ref A, file.%A.decl [concrete = constants.%A]\n// CHECK:STDOUT:   %A.call: init %i32 = call %A.ref()\n// CHECK:STDOUT:   %.loc19_22.1: %i32 = value_of_initializer %A.call\n// CHECK:STDOUT:   %.loc19_22.2: %i32 = converted %A.call, %.loc19_22.1\n// CHECK:STDOUT:   br !if.expr.result(%.loc19_22.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else:\n// CHECK:STDOUT:   %B.ref: %B.type = name_ref B, file.%B.decl [concrete = constants.%B]\n// CHECK:STDOUT:   %B.call: init %i32 = call %B.ref()\n// CHECK:STDOUT:   %.loc19_24.1: %i32 = value_of_initializer %B.call\n// CHECK:STDOUT:   %.loc19_24.2: %i32 = converted %B.call, %.loc19_24.1\n// CHECK:STDOUT:   br !if.expr.result(%.loc19_24.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result:\n// CHECK:STDOUT:   %.loc19_10: %i32 = block_arg !if.expr.result\n// CHECK:STDOUT:   %impl.elem0: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc19_10.1: <bound method> = bound_method %.loc19_10, %impl.elem0\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc19_10.2: <bound method> = bound_method %.loc19_10, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc19_10.2(%.loc19_10)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/if_expr/fail_not_in_function.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/if_expr/fail_not_in_function.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/if_expr/fail_not_in_function.carbon\n\n// --- fail_basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_basic.carbon:[[@LINE+12]]:14: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n// CHECK:STDERR: let x: i32 = if true then 1 else 0;\n// CHECK:STDERR:              ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_basic.carbon:[[@LINE+8]]:22: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n// CHECK:STDERR: let x: i32 = if true then 1 else 0;\n// CHECK:STDERR:                      ^~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_basic.carbon:[[@LINE+4]]:14: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n// CHECK:STDERR: let x: i32 = if true then 1 else 0;\n// CHECK:STDERR:              ^~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nlet x: i32 = if true then 1 else 0;\n\n// --- fail_types.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_types.carbon:[[@LINE+4]]:8: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n// CHECK:STDERR: var y: if true then i32 else f64;\n// CHECK:STDERR:        ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nvar y: if true then i32 else f64;\n\n// --- fail_in_param.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_in_param.carbon:[[@LINE+4]]:9: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n// CHECK:STDERR: fn F(a: if true then i32 else f64);\n// CHECK:STDERR:         ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfn F(a: if true then i32 else f64);\n\n// --- fail_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {\n  // CHECK:STDERR: fail_class.carbon:[[@LINE+12]]:10: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n  // CHECK:STDERR:   var n: if true then i32 else f64;\n  // CHECK:STDERR:          ^~~~~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_class.carbon:[[@LINE+8]]:18: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n  // CHECK:STDERR:   var n: if true then i32 else f64;\n  // CHECK:STDERR:                  ^~~~~~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_class.carbon:[[@LINE+4]]:10: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n  // CHECK:STDERR:   var n: if true then i32 else f64;\n  // CHECK:STDERR:          ^~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var n: if true then i32 else f64;\n}\n\n// --- fail_nested_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nbase class C(T:! type) {}\n\nfn F() {\n  class B {\n    // CHECK:STDERR: fail_nested_class.carbon:[[@LINE+4]]:20: error: semantics TODO: `Control flow expressions are currently only supported inside functions.` [SemanticsTodo]\n    // CHECK:STDERR:     extend base: C(if true then i32 else i32);\n    // CHECK:STDERR:                    ^~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    extend base: C(if true then i32 else i32);\n  }\n}\n\n// CHECK:STDOUT: --- fail_basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_types.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_in_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:   if %true br !if.expr.then else br !if.expr.else\n// CHECK:STDOUT:   complete_type_witness = invalid\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_nested_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %B: type = class_type @B [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(<unexpected>.inst{{[0-9A-F]+}}.loc4_14: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @B {\n// CHECK:STDOUT:   %C.ref: %C.type = name_ref C, <unexpected>.inst{{[0-9A-F]+}}.loc4_24 [concrete = constants.%C.generic]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:   if %true br !if.expr.then else br !if.expr.else\n// CHECK:STDOUT:   complete_type_witness = invalid\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%B\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F();\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/if_expr/fail_partial_constant.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/if_expr/fail_partial_constant.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/if_expr/fail_partial_constant.carbon\n\n// --- fail_non_constant_condition.carbon\n\npackage NonConstantCondition;\n\nfn ConditionIsNonConstant(b: bool) {\n  // We choose to not accept this even if both arms evaluate to the same\n  // constant value, because it notionally involves evaluating a non-constant\n  // condition.\n  // CHECK:STDERR: fail_non_constant_condition.carbon:[[@LINE+4]]:17: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   var unused v: if b then i32 else i32 = 1;\n  // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v: if b then i32 else i32 = 1;\n}\n\n// --- fail_non_constant_result.carbon\n\npackage NonConstantResult;\n\nfn ChosenBranchIsNonConstant(t: type) {\n  // CHECK:STDERR: fail_non_constant_result.carbon:[[@LINE+4]]:17: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   var unused v: if true then t else i32 = 1;\n  // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused v: if true then t else i32 = 1;\n  // CHECK:STDERR: fail_non_constant_result.carbon:[[@LINE+4]]:17: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   var unused w: if false then i32 else t = 1;\n  // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  var unused w: if false then i32 else t = 1;\n}\n\n// CHECK:STDOUT: --- fail_non_constant_condition.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %ConditionIsNonConstant.type: type = fn_type @ConditionIsNonConstant [concrete]\n// CHECK:STDOUT:   %ConditionIsNonConstant: %ConditionIsNonConstant.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ConditionIsNonConstant = %ConditionIsNonConstant.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ConditionIsNonConstant.decl: %ConditionIsNonConstant.type = fn_decl @ConditionIsNonConstant [concrete = constants.%ConditionIsNonConstant] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %b.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc4: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ConditionIsNonConstant(%b.param: bool) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: <error> = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: <error> = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref <error> = var %v.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   assign %v.var, <error>\n// CHECK:STDOUT:   br !.loc12_20\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc12_20:\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b\n// CHECK:STDOUT:   if %b.ref br !if.expr.then else br !if.expr.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then:\n// CHECK:STDOUT:   %i32.loc12_27: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   br !if.expr.result(%i32.loc12_27)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else:\n// CHECK:STDOUT:   %i32.loc12_36: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   br !if.expr.result(%i32.loc12_36)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result:\n// CHECK:STDOUT:   %.loc12: type = block_arg !if.expr.result\n// CHECK:STDOUT:   br !.loc12_14\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc12_14:\n// CHECK:STDOUT:   %v: ref <error> = ref_binding v, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_non_constant_result.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %ChosenBranchIsNonConstant.type: type = fn_type @ChosenBranchIsNonConstant [concrete]\n// CHECK:STDOUT:   %ChosenBranchIsNonConstant: %ChosenBranchIsNonConstant.type = struct_value () [concrete]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .ChosenBranchIsNonConstant = %ChosenBranchIsNonConstant.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %ChosenBranchIsNonConstant.decl: %ChosenBranchIsNonConstant.type = fn_decl @ChosenBranchIsNonConstant [concrete = constants.%ChosenBranchIsNonConstant] {\n// CHECK:STDOUT:     %t.patt: %pattern_type.98f = value_binding_pattern t [concrete]\n// CHECK:STDOUT:     %t.param_patt: %pattern_type.98f = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %t.param: type = value_param call_param0\n// CHECK:STDOUT:     %.loc4: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %t: type = value_binding t, %t.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @ChosenBranchIsNonConstant(%t.param: type) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %v.patt: <error> = ref_binding_pattern v [concrete]\n// CHECK:STDOUT:     %v.var_patt: <error> = var_pattern %v.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %v.var: ref <error> = var %v.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %int_1.loc9: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   assign %v.var, <error>\n// CHECK:STDOUT:   br !.loc9_20\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc9_20:\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:   if %true br !if.expr.then.loc9 else br !if.expr.else.loc9\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then.loc9:\n// CHECK:STDOUT:   %t.ref.loc9: type = name_ref t, %t\n// CHECK:STDOUT:   br !if.expr.result.loc9(%t.ref.loc9)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else.loc9:\n// CHECK:STDOUT:   %i32.loc9: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   br !if.expr.result.loc9(%i32.loc9)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result.loc9:\n// CHECK:STDOUT:   %.loc9: type = block_arg !if.expr.result.loc9\n// CHECK:STDOUT:   br !.loc9_14\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc9_14:\n// CHECK:STDOUT:   %v: ref <error> = ref_binding v, <error> [concrete = <error>]\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %w.patt: <error> = ref_binding_pattern w [concrete]\n// CHECK:STDOUT:     %w.var_patt: <error> = var_pattern %w.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %w.var: ref <error> = var %w.var_patt [concrete = <error>]\n// CHECK:STDOUT:   %int_1.loc14: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:   assign %w.var, <error>\n// CHECK:STDOUT:   br !.loc14_20\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc14_20:\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:   if %false br !if.expr.then.loc14 else br !if.expr.else.loc14\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then.loc14:\n// CHECK:STDOUT:   %i32.loc14: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   br !if.expr.result.loc14(%i32.loc14)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else.loc14:\n// CHECK:STDOUT:   %t.ref.loc14: type = name_ref t, %t\n// CHECK:STDOUT:   br !if.expr.result.loc14(%t.ref.loc14)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result.loc14:\n// CHECK:STDOUT:   %.loc14: type = block_arg !if.expr.result.loc14\n// CHECK:STDOUT:   br !.loc14_14\n// CHECK:STDOUT:\n// CHECK:STDOUT: !.loc14_14:\n// CHECK:STDOUT:   %w: ref <error> = ref_binding w, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/if_expr/nested.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/if_expr/nested.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/if_expr/nested.carbon\n\nfn F(a: bool, b: bool, c: bool) -> i32 {\n  return if a then if b then 1 else 2 else if c then 3 else 4;\n}\n\n// CHECK:STDOUT: --- nested.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %.ff5: Core.Form = init_form %i32 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.6d7: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_4.940: %i32 = int_value 4 [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %a.patt: %pattern_type.831 = value_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.param_patt: %pattern_type.831 = value_param_pattern %a.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %c.patt: %pattern_type.831 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.831 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %.loc15_36: Core.Form = init_form %i32 [concrete = constants.%.ff5]\n// CHECK:STDOUT:     %a.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc15_9: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %a: bool = value_binding a, %a.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %.loc15_18: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %c.param: bool = value_param call_param2\n// CHECK:STDOUT:     %.loc15_27: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %c: bool = value_binding c, %c.param\n// CHECK:STDOUT:     %return.param: ref %i32 = out_param call_param3\n// CHECK:STDOUT:     %return: ref %i32 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%a.param: bool, %b.param: bool, %c.param: bool) -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %a.ref: bool = name_ref a, %a\n// CHECK:STDOUT:   if %a.ref br !if.expr.then.loc16_10 else br !if.expr.else.loc16_10\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then.loc16_10:\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b\n// CHECK:STDOUT:   if %b.ref br !if.expr.then.loc16_20 else br !if.expr.else.loc16_20\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then.loc16_20:\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %impl.elem0.loc16_25: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc16_25.1: <bound method> = bound_method %int_1, %impl.elem0.loc16_25 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc16_25: <specific function> = specific_function %impl.elem0.loc16_25, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_25.2: <bound method> = bound_method %int_1, %specific_fn.loc16_25 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16_25: init %i32 = call %bound_method.loc16_25.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc16_25.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16_25 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc16_25.2: %i32 = converted %int_1, %.loc16_25.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   br !if.expr.result.loc16_20(%.loc16_25.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else.loc16_20:\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %impl.elem0.loc16_32: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc16_32.1: <bound method> = bound_method %int_2, %impl.elem0.loc16_32 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc16_32: <specific function> = specific_function %impl.elem0.loc16_32, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_32.2: <bound method> = bound_method %int_2, %specific_fn.loc16_32 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16_32: init %i32 = call %bound_method.loc16_32.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc16_32.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16_32 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc16_32.2: %i32 = converted %int_2, %.loc16_32.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   br !if.expr.result.loc16_20(%.loc16_32.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result.loc16_20:\n// CHECK:STDOUT:   %.loc16_20: %i32 = block_arg !if.expr.result.loc16_20\n// CHECK:STDOUT:   br !if.expr.result.loc16_10(%.loc16_20)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else.loc16_10:\n// CHECK:STDOUT:   %c.ref: bool = name_ref c, %c\n// CHECK:STDOUT:   if %c.ref br !if.expr.then.loc16_44 else br !if.expr.else.loc16_44\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then.loc16_44:\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:   %impl.elem0.loc16_49: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc16_49.1: <bound method> = bound_method %int_3, %impl.elem0.loc16_49 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:   %specific_fn.loc16_49: <specific function> = specific_function %impl.elem0.loc16_49, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_49.2: <bound method> = bound_method %int_3, %specific_fn.loc16_49 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16_49: init %i32 = call %bound_method.loc16_49.2(%int_3) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc16_49.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16_49 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   %.loc16_49.2: %i32 = converted %int_3, %.loc16_49.1 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:   br !if.expr.result.loc16_44(%.loc16_49.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else.loc16_44:\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]\n// CHECK:STDOUT:   %impl.elem0.loc16_56: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc16_56.1: <bound method> = bound_method %int_4, %impl.elem0.loc16_56 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c]\n// CHECK:STDOUT:   %specific_fn.loc16_56: <specific function> = specific_function %impl.elem0.loc16_56, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_56.2: <bound method> = bound_method %int_4, %specific_fn.loc16_56 [concrete = constants.%bound_method.6d7]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16_56: init %i32 = call %bound_method.loc16_56.2(%int_4) [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc16_56.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc16_56 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   %.loc16_56.2: %i32 = converted %int_4, %.loc16_56.1 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:   br !if.expr.result.loc16_44(%.loc16_56.2)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result.loc16_44:\n// CHECK:STDOUT:   %.loc16_44: %i32 = block_arg !if.expr.result.loc16_44\n// CHECK:STDOUT:   br !if.expr.result.loc16_10(%.loc16_44)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result.loc16_10:\n// CHECK:STDOUT:   %.loc16_10: %i32 = block_arg !if.expr.result.loc16_10\n// CHECK:STDOUT:   %impl.elem0.loc16_10: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc16_10.1: <bound method> = bound_method %.loc16_10, %impl.elem0.loc16_10\n// CHECK:STDOUT:   %specific_fn.loc16_10: <specific function> = specific_function %impl.elem0.loc16_10, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc16_10.2: <bound method> = bound_method %.loc16_10, %specific_fn.loc16_10\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc16_10.2(%.loc16_10)\n// CHECK:STDOUT:   return %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/if_expr/struct.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/if_expr/struct.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/if_expr/struct.carbon\n\nfn G(s: {.a: i32, .b: i32});\n\nfn F(cond: bool) {\n  var a: {.a: i32, .b: i32} = {.a = 1, .b = 2};\n  G(if cond then a else a);\n}\n\n// CHECK:STDOUT: --- struct.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.501: type = struct_type {.a: %i32, .b: %i32} [concrete]\n// CHECK:STDOUT:   %pattern_type.851: type = pattern_type %struct_type.a.b.501 [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.cfd: type = struct_type {.a: Core.IntLiteral, .b: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct.4aa: %struct_type.a.b.cfd = struct_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct.ed5: %struct_type.a.b.501 = struct_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %s.patt: %pattern_type.851 = value_binding_pattern s [concrete]\n// CHECK:STDOUT:     %s.param_patt: %pattern_type.851 = value_param_pattern %s.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %s.param: %struct_type.a.b.501 = value_param call_param0\n// CHECK:STDOUT:     %.loc15: type = splice_block %struct_type.a.b [concrete = constants.%struct_type.a.b.501] {\n// CHECK:STDOUT:       %i32.loc15_14: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %i32.loc15_23: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.a.b: type = struct_type {.a: %i32, .b: %i32} [concrete = constants.%struct_type.a.b.501]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %s: %struct_type.a.b.501 = value_binding s, %s.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %cond.patt: %pattern_type.831 = value_binding_pattern cond [concrete]\n// CHECK:STDOUT:     %cond.param_patt: %pattern_type.831 = value_param_pattern %cond.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %cond.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc17: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %cond: bool = value_binding cond, %cond.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%s.param: %struct_type.a.b.501);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%cond.param: bool) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.851 = ref_binding_pattern a [concrete]\n// CHECK:STDOUT:     %a.var_patt: %pattern_type.851 = var_pattern %a.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a.var: ref %struct_type.a.b.501 = var %a.var_patt\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc18_46.1: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2) [concrete = constants.%struct.4aa]\n// CHECK:STDOUT:   %impl.elem0.loc18_46.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_46.1: <bound method> = bound_method %int_1, %impl.elem0.loc18_46.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:   %specific_fn.loc18_46.1: <specific function> = specific_function %impl.elem0.loc18_46.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_46.2: <bound method> = bound_method %int_1, %specific_fn.loc18_46.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_46.1: init %i32 = call %bound_method.loc18_46.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_46.2: init %i32 = converted %int_1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_46.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %.loc18_46.3: ref %i32 = struct_access %a.var, element0\n// CHECK:STDOUT:   %.loc18_46.4: init %i32 to %.loc18_46.3 = in_place_init %.loc18_46.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:   %impl.elem0.loc18_46.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_46.3: <bound method> = bound_method %int_2, %impl.elem0.loc18_46.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc18_46.2: <specific function> = specific_function %impl.elem0.loc18_46.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_46.4: <bound method> = bound_method %int_2, %specific_fn.loc18_46.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_46.2: init %i32 = call %bound_method.loc18_46.4(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_46.5: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_46.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_46.6: ref %i32 = struct_access %a.var, element1\n// CHECK:STDOUT:   %.loc18_46.7: init %i32 to %.loc18_46.6 = in_place_init %.loc18_46.5 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_46.8: init %struct_type.a.b.501 to %a.var = struct_init (%.loc18_46.4, %.loc18_46.7) [concrete = constants.%struct.ed5]\n// CHECK:STDOUT:   %.loc18_3: init %struct_type.a.b.501 = converted %.loc18_46.1, %.loc18_46.8 [concrete = constants.%struct.ed5]\n// CHECK:STDOUT:   assign %a.var, %.loc18_3\n// CHECK:STDOUT:   %.loc18_27: type = splice_block %struct_type.a.b [concrete = constants.%struct_type.a.b.501] {\n// CHECK:STDOUT:     %i32.loc18_15: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %i32.loc18_24: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %struct_type.a.b: type = struct_type {.a: %i32, .b: %i32} [concrete = constants.%struct_type.a.b.501]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %a: ref %struct_type.a.b.501 = ref_binding a, %a.var\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %cond.ref: bool = name_ref cond, %cond\n// CHECK:STDOUT:   if %cond.ref br !if.expr.then else br !if.expr.else\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.then:\n// CHECK:STDOUT:   %a.ref.loc19_18: ref %struct_type.a.b.501 = name_ref a, %a\n// CHECK:STDOUT:   %.loc19_18.1: ref %i32 = struct_access %a.ref.loc19_18, element0\n// CHECK:STDOUT:   %.loc19_18.2: %i32 = acquire_value %.loc19_18.1\n// CHECK:STDOUT:   %.loc19_18.3: ref %i32 = struct_access %a.ref.loc19_18, element1\n// CHECK:STDOUT:   %.loc19_18.4: %i32 = acquire_value %.loc19_18.3\n// CHECK:STDOUT:   %struct.loc19_18: %struct_type.a.b.501 = struct_value (%.loc19_18.2, %.loc19_18.4)\n// CHECK:STDOUT:   %.loc19_18.5: %struct_type.a.b.501 = converted %a.ref.loc19_18, %struct.loc19_18\n// CHECK:STDOUT:   br !if.expr.result(%.loc19_18.5)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.else:\n// CHECK:STDOUT:   %a.ref.loc19_25: ref %struct_type.a.b.501 = name_ref a, %a\n// CHECK:STDOUT:   %.loc19_25.1: ref %i32 = struct_access %a.ref.loc19_25, element0\n// CHECK:STDOUT:   %.loc19_25.2: %i32 = acquire_value %.loc19_25.1\n// CHECK:STDOUT:   %.loc19_25.3: ref %i32 = struct_access %a.ref.loc19_25, element1\n// CHECK:STDOUT:   %.loc19_25.4: %i32 = acquire_value %.loc19_25.3\n// CHECK:STDOUT:   %struct.loc19_25: %struct_type.a.b.501 = struct_value (%.loc19_25.2, %.loc19_25.4)\n// CHECK:STDOUT:   %.loc19_20: %struct_type.a.b.501 = converted %a.ref.loc19_25, %struct.loc19_25\n// CHECK:STDOUT:   br !if.expr.result(%.loc19_20)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !if.expr.result:\n// CHECK:STDOUT:   %.loc19_5: %struct_type.a.b.501 = block_arg !if.expr.result\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.ref(%.loc19_5)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %a.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%a.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %struct_type.a.b.501) = \"no_op\";\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/assoc_const_self.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/assoc_const_self.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/assoc_const_self.carbon\n\n// --- assoc_const_self.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let V:! Self;\n}\n\nimpl {} as I where .V = {} {}\n\nimpl i32 as I where .V = 0 {}\n\n// --- fail_assoc_const_mismatch.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let V:! Self;\n}\n\n// CHECK:STDERR: fail_assoc_const_mismatch.carbon:[[@LINE+7]]:12: error: cannot implicitly convert expression of type `Core.IntLiteral` to `{}` [ConversionFailure]\n// CHECK:STDERR: impl {} as I where .V = 0 {}\n// CHECK:STDERR:            ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_assoc_const_mismatch.carbon:[[@LINE+4]]:12: note: type `Core.IntLiteral` does not implement interface `Core.ImplicitAs({})` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: impl {} as I where .V = 0 {}\n// CHECK:STDERR:            ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl {} as I where .V = 0 {}\n\n// --- fail_assoc_const_not_constant_after_conversion.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let V:! Self;\n}\n\nclass C {}\n\nimpl () as Core.ImplicitAs(C) {\n  fn Convert[unused self: ()]() -> C { return {}; }\n}\n\n// CHECK:STDERR: fail_assoc_const_not_constant_after_conversion.carbon:[[@LINE+4]]:11: error: associated constant V given value `()` that is not constant after conversion to `C` [AssociatedConstantNotConstantAfterConversion]\n// CHECK:STDERR: impl C as I where .V = () {}\n// CHECK:STDERR:           ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl C as I where .V = () {}\n\n// --- fail_monomorphization_failure.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(N:! Core.IntLiteral()) {\n  let V:! array(Self, N);\n}\n\n// CHECK:STDERR: fail_monomorphization_failure.carbon:[[@LINE+7]]:24: error: member access into facet of incomplete type `I(-1)` [IncompleteTypeInMemberAccessOfFacet]\n// CHECK:STDERR: impl {} as I(-1) where .V = () {}\n// CHECK:STDERR:                        ^~\n// CHECK:STDERR: fail_monomorphization_failure.carbon:[[@LINE-6]]:17: note: array bound of -1 is negative [ArrayBoundNegative]\n// CHECK:STDERR:   let V:! array(Self, N);\n// CHECK:STDERR:                 ^~~~\n// CHECK:STDERR:\nimpl {} as I(-1) where .V = () {}\n\n// --- fail_todo_constrained_fn.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let V:! Self;\n}\n\nfn F(T:! I where {} impls Core.ImplicitAs(.Self) and .V = {});\n\nfn CallF() {\n  // TODO: This call should eventually work.\n  // CHECK:STDERR: fail_todo_constrained_fn.carbon:[[@LINE+7]]:3: error: cannot convert type `{}` into type implementing `I where .(I.V) = {} and...` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   F({});\n  // CHECK:STDERR:   ^~~~~\n  // CHECK:STDERR: fail_todo_constrained_fn.carbon:[[@LINE-7]]:6: note: initializing generic parameter `T` declared here [InitializingGenericParam]\n  // CHECK:STDERR: fn F(T:! I where {} impls Core.ImplicitAs(.Self) and .V = {});\n  // CHECK:STDERR:      ^\n  // CHECK:STDERR:\n  F({});\n}\n\n// CHECK:STDOUT: --- assoc_const_self.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.d31: type = symbolic_binding_type Self, 0, %Self.ab9 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0.490: %I.assoc_type = assoc_entity element0, @I.WithSelf.%V [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: %.Self.binding.as_type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %I_where.type.ec3: type = facet_type <@I where %impl.elem0 = %empty_struct> [concrete]\n// CHECK:STDOUT:   %I.impl_witness.df7: <witness> = impl_witness @empty_struct_type.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %empty_struct.type.facet: %type = facet_value %empty_struct_type, () [concrete]\n// CHECK:STDOUT:   %I.facet.47f: %I.type = facet_value %empty_struct_type, (%I.impl_witness.df7) [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %int_0.5c6: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %I_where.type.b52: type = facet_type <@I where %impl.elem0 = %int_0.5c6> [concrete]\n// CHECK:STDOUT:   %I.impl_witness.550: <witness> = impl_witness @i32.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Int.type.facet: %type = facet_value %i32, () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_0.5c6, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_0.6a9: %i32 = int_value 0 [concrete]\n// CHECK:STDOUT:   %I.facet.608: %I.type = facet_value %i32, (%I.impl_witness.550) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc8_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc8_7.2: type = converted %.loc8_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc8_20: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %V.ref: %I.assoc_type = name_ref V, @V.%assoc0 [concrete = constants.%assoc0.490]\n// CHECK:STDOUT:     %impl.elem0: %.Self.binding.as_type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc8_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc8_26.2: %empty_struct_type = converted %.loc8_26.1, %empty_struct [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc8_14: type = where_expr %.Self [concrete = constants.%I_where.type.ec3] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0, %.loc8_26.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @i32.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc10_21: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %V.ref: %I.assoc_type = name_ref V, @V.%assoc0 [concrete = constants.%assoc0.490]\n// CHECK:STDOUT:     %impl.elem0.loc10_21: %.Self.binding.as_type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0.5c6]\n// CHECK:STDOUT:     %.loc10_15.1: type = where_expr %.Self [concrete = constants.%I_where.type.b52] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10_21, %int_0\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %V: @I.WithSelf.%Self.binding.as_type (%Self.binding.as_type.d31) = assoc_const_decl @V [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%V [concrete = constants.%assoc0.490]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .V = @V.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%V)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc8_7.2 as %.loc8_14 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @empty_struct_type.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.df7]\n// CHECK:STDOUT:   %impl_witness_assoc_constant: %empty_struct_type = impl_witness_assoc_constant constants.%empty_struct [concrete = constants.%empty_struct]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.as.I.impl: %i32 as %.loc10_15.1 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @i32.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.550]\n// CHECK:STDOUT:   %impl.elem0.loc10_15: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc10_15.1: <bound method> = bound_method constants.%int_0.5c6, %impl.elem0.loc10_15 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0.loc10_15, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc10_15.2: <bound method> = bound_method constants.%int_0.5c6, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc10_15.2(constants.%int_0.5c6) [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc10_15.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %.loc10_15.3: %i32 = converted constants.%int_0.5c6, %.loc10_15.2 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:   %impl_witness_assoc_constant: %i32 = impl_witness_assoc_constant constants.%int_0.6a9 [concrete = constants.%int_0.6a9]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.ab9\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.d31\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%.Self\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%.Self.binding.as_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%empty_struct.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%empty_struct.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%empty_struct_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.47f) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet.47f\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%empty_struct_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Int.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Int.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%i32\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.608) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet.608\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%i32\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_assoc_const_mismatch.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.d31: type = symbolic_binding_type Self, 0, %Self.ab9 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0.490: %I.assoc_type = assoc_entity element0, @I.WithSelf.%V [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: %.Self.binding.as_type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where %impl.elem0 = %int_0> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @empty_struct_type.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %empty_struct.type.facet: %type = facet_value %empty_struct_type, () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %empty_struct_type, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc15_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc15_7.2: type = converted %.loc15_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc15_20: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %V.ref: %I.assoc_type = name_ref V, @V.%assoc0 [concrete = constants.%assoc0.490]\n// CHECK:STDOUT:     %impl.elem0: %.Self.binding.as_type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:     %.loc15_14.1: type = where_expr %.Self [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0, %int_0\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %V: @I.WithSelf.%Self.binding.as_type (%Self.binding.as_type.d31) = assoc_const_decl @V [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%V [concrete = constants.%assoc0.490]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .V = @V.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%V)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc15_7.2 as %.loc15_14.1 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @empty_struct_type.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %.loc15_14.2: %empty_struct_type = converted constants.%int_0, <error> [concrete = <error>]\n// CHECK:STDOUT:   %impl_witness_assoc_constant: <error> = impl_witness_assoc_constant <error> [concrete = <error>]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.ab9\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.d31\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%.Self\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%.Self.binding.as_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%empty_struct.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%empty_struct.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%empty_struct_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%empty_struct_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_assoc_const_not_constant_after_conversion.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.d31: type = symbolic_binding_type Self, 0, %Self.ab9 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0.490: %I.assoc_type = assoc_entity element0, @I.WithSelf.%V [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.20a: type = facet_type <@ImplicitAs, @ImplicitAs(%C)> [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness @empty_tuple.type.as.ImplicitAs.impl.%ImplicitAs.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %.a69: Core.Form = init_form %C [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_tuple.type.as.ImplicitAs.impl.Convert.type: type = fn_type @empty_tuple.type.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %empty_tuple.type.as.ImplicitAs.impl.Convert: %empty_tuple.type.as.ImplicitAs.impl.Convert.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.20a = facet_value %empty_tuple.type, (%ImplicitAs.impl_witness) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.59f: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%C, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: %.Self.binding.as_type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where %impl.elem0 = %empty_tuple> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]\n// CHECK:STDOUT:   %.e9b: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.59f, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %empty_tuple.type.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %empty_tuple, %empty_tuple.type.as.ImplicitAs.impl.Convert [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @empty_tuple.type.as.ImplicitAs.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc10_7.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc10_7.2: type = converted %.loc10_7.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:     %ImplicitAs.ref: %ImplicitAs.type.cc7 = name_ref ImplicitAs, imports.%Core.ImplicitAs [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%C)> [concrete = constants.%ImplicitAs.type.20a]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc18_19: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %V.ref: %I.assoc_type = name_ref V, @V.%assoc0 [concrete = constants.%assoc0.490]\n// CHECK:STDOUT:     %impl.elem0.loc18_19: %.Self.binding.as_type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc18_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc18_25.2: %empty_tuple.type = converted %.loc18_25.1, %empty_tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc18_13.1: type = where_expr %.Self [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc18_19, %.loc18_25.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %V: @I.WithSelf.%Self.binding.as_type (%Self.binding.as_type.d31) = assoc_const_decl @V [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%V [concrete = constants.%assoc0.490]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .V = @V.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%V)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_tuple.type.as.ImplicitAs.impl: %.loc10_7.2 as %ImplicitAs.type {\n// CHECK:STDOUT:   %empty_tuple.type.as.ImplicitAs.impl.Convert.decl: %empty_tuple.type.as.ImplicitAs.impl.Convert.type = fn_decl @empty_tuple.type.as.ImplicitAs.impl.Convert [concrete = constants.%empty_tuple.type.as.ImplicitAs.impl.Convert] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.cb1 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.cb1 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.7c7 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.7c7 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc11_36: Core.Form = init_form %C.ref [concrete = constants.%.a69]\n// CHECK:STDOUT:     %self.param: %empty_tuple.type = value_param call_param0\n// CHECK:STDOUT:     %.loc11_28.1: type = splice_block %.loc11_28.3 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:       %.loc11_28.2: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc11_28.3: type = converted %.loc11_28.2, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self: %empty_tuple.type = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref %C = out_param call_param1\n// CHECK:STDOUT:     %return: ref %C = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table = impl_witness_table (%empty_tuple.type.as.ImplicitAs.impl.Convert.decl), @empty_tuple.type.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness: <witness> = impl_witness %ImplicitAs.impl_witness_table [concrete = constants.%ImplicitAs.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT:   .Convert = %empty_tuple.type.as.ImplicitAs.impl.Convert.decl\n// CHECK:STDOUT:   witness = %ImplicitAs.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %.loc18_13.1 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @C.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %impl.elem0.loc18_13: %.e9b = impl_witness_access constants.%ImplicitAs.impl_witness, element0 [concrete = constants.%empty_tuple.type.as.ImplicitAs.impl.Convert]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method constants.%empty_tuple, %impl.elem0.loc18_13 [concrete = constants.%empty_tuple.type.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %.loc18_13.2: ref %C = temporary_storage\n// CHECK:STDOUT:   %empty_tuple.type.as.ImplicitAs.impl.Convert.call: init %C to %.loc18_13.2 = call %bound_method(constants.%empty_tuple)\n// CHECK:STDOUT:   %.loc18_13.3: init %C = converted constants.%empty_tuple, %empty_tuple.type.as.ImplicitAs.impl.Convert.call\n// CHECK:STDOUT:   %.loc18_13.4: ref %C = temporary %.loc18_13.2, %.loc18_13.3\n// CHECK:STDOUT:   %.loc18_13.5: %C = acquire_value %.loc18_13.4\n// CHECK:STDOUT:   %impl_witness_assoc_constant: <error> = impl_witness_assoc_constant <error> [concrete = <error>]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @empty_tuple.type.as.ImplicitAs.impl.Convert(%self.param: %empty_tuple.type) -> out %return.param: %C {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc11_48.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc11_48.2: init %C to %return.param = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc11_49: init %C = converted %.loc11_48.1, %.loc11_48.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   return %.loc11_49 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.ab9\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.d31\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%.Self\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%.Self.binding.as_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%C.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%C.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_monomorphization_failure.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %IntLiteral.type: type = fn_type @IntLiteral [concrete]\n// CHECK:STDOUT:   %IntLiteral: %IntLiteral.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.dc0: type = pattern_type Core.IntLiteral [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.68b: type = facet_type <@I, @I(%N)> [symbolic]\n// CHECK:STDOUT:   %Self.cad: %I.type.68b = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.6f3: type = symbolic_binding_type Self, 1, %Self.cad [symbolic]\n// CHECK:STDOUT:   %array_type: type = array_type %N, %Self.binding.as_type.6f3 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type.223: type = assoc_entity_type @I, @I(%N) [symbolic]\n// CHECK:STDOUT:   %assoc0.b3d: %I.assoc_type.223 = assoc_entity element0, @I.WithSelf.%V [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_1: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %Negate.type: type = facet_type <@Negate> [concrete]\n// CHECK:STDOUT:   %Negate.impl_witness: <witness> = impl_witness imports.%Negate.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Negate.facet: %Negate.type = facet_value Core.IntLiteral, (%Negate.impl_witness) [concrete]\n// CHECK:STDOUT:   %Negate.WithSelf.Op.type.4dd: type = fn_type @Negate.WithSelf.Op, @Negate.WithSelf(%Negate.facet) [concrete]\n// CHECK:STDOUT:   %.b42: type = fn_type_with_self_type %Negate.WithSelf.Op.type.4dd, %Negate.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Negate.impl.Op.type: type = fn_type @Core.IntLiteral.as.Negate.impl.Op [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Negate.impl.Op: %Core.IntLiteral.as.Negate.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.Negate.impl.Op.bound: <bound method> = bound_method %int_1, %Core.IntLiteral.as.Negate.impl.Op [concrete]\n// CHECK:STDOUT:   %int_-1: Core.IntLiteral = int_value -1 [concrete]\n// CHECK:STDOUT:   %I.type.54b: type = facet_type <@I, @I(%int_-1)> [concrete]\n// CHECK:STDOUT:   %.Self.6e0: %I.type.54b = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %Self.575: %I.type.54b = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type.e1a: type = assoc_entity_type @I, @I(%int_-1) [concrete]\n// CHECK:STDOUT:   %assoc0.578: %I.assoc_type.e1a = assoc_entity element0, @I.WithSelf.%V [concrete]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.6e0 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .IntLiteral = %Core.IntLiteral\n// CHECK:STDOUT:     .Negate = %Core.Negate\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.IntLiteral: %IntLiteral.type = import_ref Core//prelude/parts/int_literal, IntLiteral, loaded [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:   %Core.Negate: type = import_ref Core//prelude/parts/int_literal, Negate, loaded [concrete = constants.%Negate.type]\n// CHECK:STDOUT:   %Core.import_ref.abd = import_ref Core//prelude/parts/int_literal, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.82e: %Core.IntLiteral.as.Negate.impl.Op.type = import_ref Core//prelude/parts/int_literal, loc{{\\d+_\\d+}}, loaded [concrete = constants.%Core.IntLiteral.as.Negate.impl.Op]\n// CHECK:STDOUT:   %Negate.impl_witness_table = impl_witness_table (%Core.import_ref.abd, %Core.import_ref.82e), @Core.IntLiteral.as.Negate.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %N.patt: %pattern_type.dc0 = symbolic_binding_pattern N, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_33.1: type = splice_block %.loc4_33.3 [concrete = Core.IntLiteral] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%Core.IntLiteral [concrete = constants.%IntLiteral]\n// CHECK:STDOUT:       %IntLiteral.call: init type = call %IntLiteral.ref() [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_33.2: type = value_of_initializer %IntLiteral.call [concrete = Core.IntLiteral]\n// CHECK:STDOUT:       %.loc4_33.3: type = converted %IntLiteral.call, %.loc4_33.2 [concrete = Core.IntLiteral]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %N.loc4_13.2: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_13.1 (constants.%N)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc15_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc15_7.2: type = converted %.loc15_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1]\n// CHECK:STDOUT:     %impl.elem1: %.b42 = impl_witness_access constants.%Negate.impl_witness, element1 [concrete = constants.%Core.IntLiteral.as.Negate.impl.Op]\n// CHECK:STDOUT:     %bound_method: <bound method> = bound_method %int_1, %impl.elem1 [concrete = constants.%Core.IntLiteral.as.Negate.impl.Op.bound]\n// CHECK:STDOUT:     %Core.IntLiteral.as.Negate.impl.Op.call: init Core.IntLiteral = call %bound_method(%int_1) [concrete = constants.%int_-1]\n// CHECK:STDOUT:     %.loc15_16.1: Core.IntLiteral = value_of_initializer %Core.IntLiteral.as.Negate.impl.Op.call [concrete = constants.%int_-1]\n// CHECK:STDOUT:     %.loc15_16.2: Core.IntLiteral = converted %Core.IntLiteral.as.Negate.impl.Op.call, %.loc15_16.1 [concrete = constants.%int_-1]\n// CHECK:STDOUT:     %I.type: type = facet_type <@I, @I(constants.%int_-1)> [concrete = constants.%I.type.54b]\n// CHECK:STDOUT:     %.Self: %I.type.54b = symbolic_binding .Self [symbolic_self = constants.%.Self.6e0]\n// CHECK:STDOUT:     %.Self.ref: %I.type.54b = name_ref .Self, %.Self [symbolic_self = constants.%.Self.6e0]\n// CHECK:STDOUT:     %.Self.as_type: type = facet_access_type %.Self.ref [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc15_24: type = converted %.Self.ref, %.Self.as_type [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %V.ref: <error> = name_ref V, <error> [concrete = <error>]\n// CHECK:STDOUT:     %.loc15_30: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc15_18: type = where_expr %.Self [concrete = <error>] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type.54b\n// CHECK:STDOUT:       requirement_rewrite %V.ref, <error>\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%N.loc4_13.2: Core.IntLiteral) {\n// CHECK:STDOUT:   %N.loc4_13.1: Core.IntLiteral = symbolic_binding N, 0 [symbolic = %N.loc4_13.1 (constants.%N)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%N.loc4_13.1)> [symbolic = %I.type (constants.%I.type.68b)]\n// CHECK:STDOUT:   %Self.loc4_36.2: @I.%I.type (%I.type.68b) = symbolic_binding Self, 1 [symbolic = %Self.loc4_36.2 (constants.%Self.cad)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc4_36.1: @I.%I.type (%I.type.68b) = symbolic_binding Self, 1 [symbolic = %Self.loc4_36.2 (constants.%Self.cad)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %V: @I.WithSelf.%array_type (%array_type) = assoc_const_decl @V [concrete] {\n// CHECK:STDOUT:       %assoc0: @I.WithSelf.%I.assoc_type (%I.assoc_type.223) = assoc_entity element0, @I.WithSelf.%V [symbolic = @I.WithSelf.%assoc0 (constants.%assoc0.b3d)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc4_36.1\n// CHECK:STDOUT:     .N = <poisoned>\n// CHECK:STDOUT:     .N = <poisoned>\n// CHECK:STDOUT:     .V = @V.%assoc0\n// CHECK:STDOUT:     witness = (@I.WithSelf.%V)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_struct_type.as.<error>.impl: %.loc15_7.2 as %.loc15_18 {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%N) {\n// CHECK:STDOUT:   %N.loc4_13.1 => constants.%N\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%N, constants.%Self.cad) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%int_-1) {\n// CHECK:STDOUT:   %N.loc4_13.1 => constants.%int_-1\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.54b\n// CHECK:STDOUT:   %Self.loc4_36.2 => constants.%Self.575\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%int_-1, constants.%Self.cad) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N => constants.%int_-1\n// CHECK:STDOUT:   %I.type => constants.%I.type.54b\n// CHECK:STDOUT:   %Self => constants.%Self.cad\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.6f3\n// CHECK:STDOUT:   %array_type => <error>\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.e1a\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.578\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_constrained_fn.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.d31: type = symbolic_binding_type Self, 0, %Self.ab9 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0.490: %I.assoc_type = assoc_entity element0, @I.WithSelf.%V [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.1dc: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.1dc [symbolic_self]\n// CHECK:STDOUT:   %ImplicitAs.type.d65: type = facet_type <@ImplicitAs, @ImplicitAs(%.Self.binding.as_type)> [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self.1dc, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: %.Self.binding.as_type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where %impl.elem0 = %empty_struct and TODO> [concrete]\n// CHECK:STDOUT:   %pattern_type.d53: type = pattern_type %I_where.type [concrete]\n// CHECK:STDOUT:   %T: %I_where.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %CallF.type: type = fn_type @CallF [concrete]\n// CHECK:STDOUT:   %CallF: %CallF.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:     .CallF = %CallF.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.d53 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_12.1: type = splice_block %.loc8_12.2 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:       %.Self.2: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self.1dc]\n// CHECK:STDOUT:       %.loc8_19.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %Core.ref: <namespace> = name_ref Core, imports.%Core [concrete = imports.%Core]\n// CHECK:STDOUT:       %ImplicitAs.ref: %ImplicitAs.type.cc7 = name_ref ImplicitAs, imports.%Core.ImplicitAs [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:       %.Self.ref.loc8_43: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.1dc]\n// CHECK:STDOUT:       %.Self.as_type.loc8_48: type = facet_access_type %.Self.ref.loc8_43 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc8_48: type = converted %.Self.ref.loc8_43, %.Self.as_type.loc8_48 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(constants.%.Self.binding.as_type)> [symbolic_self = constants.%ImplicitAs.type.d65]\n// CHECK:STDOUT:       %.loc8_19.2: type = converted %.loc8_19.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:       %.Self.ref.loc8_54: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.1dc]\n// CHECK:STDOUT:       %.Self.as_type.loc8_54: type = facet_access_type %.Self.ref.loc8_54 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc8_54: type = converted %.Self.ref.loc8_54, %.Self.as_type.loc8_54 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %V.ref: %I.assoc_type = name_ref V, @V.%assoc0 [concrete = constants.%assoc0.490]\n// CHECK:STDOUT:       %impl.elem0: %.Self.binding.as_type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:       %.loc8_60.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %empty_struct: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc8_60.2: %empty_struct_type = converted %.loc8_60.1, %empty_struct [concrete = constants.%empty_struct]\n// CHECK:STDOUT:       %.loc8_12.2: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:         requirement_impls %.loc8_19.2, %ImplicitAs.type\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0, %.loc8_60.2\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_6.2: %I_where.type = symbolic_binding T, 0 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %CallF.decl: %CallF.type = fn_decl @CallF [concrete = constants.%CallF] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %V: @I.WithSelf.%Self.binding.as_type (%Self.binding.as_type.d31) = assoc_const_decl @V [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%V [concrete = constants.%assoc0.490]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .V = @V.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%V)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%T.loc8_6.2: %I_where.type) {\n// CHECK:STDOUT:   %T.loc8_6.1: %I_where.type = symbolic_binding T, 0 [symbolic = %T.loc8_6.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @CallF() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc19: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.ab9\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.d31\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self.1dc) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%.Self.1dc\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%.Self.binding.as_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_6.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/basic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/basic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/basic.carbon\n\n// --- basic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Simple {\n  fn F();\n}\n\nclass C {}\n\n//@dump-sem-ir-begin\nimpl C as Simple {\n  fn F() {}\n}\n//@dump-sem-ir-end\n\n// --- fail_invalid_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  fn Op[unused self: Self]();\n}\n\nclass C {}\n\n// This produces an invalid impl.\n// CHECK:STDERR: fail_invalid_impl.carbon:[[@LINE+4]]:6: error: name `Unknown` not found [NameNotFound]\n// CHECK:STDERR: impl Unknown as I {\n// CHECK:STDERR:      ^~~~~~~\n// CHECK:STDERR:\nimpl Unknown as I {\n  fn Op[unused self: Self]() {}\n}\n\n// --- fail_import_invalid_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\nimport library \"invalid_impl\";\n\nfn F() {\n  // This impl doesn't exist, but it still tests that we can ignore the\n  // `impl Unknown as I` on import.\n  // CHECK:STDERR: fail_import_invalid_impl.carbon:[[@LINE+4]]:3: error: cannot access member of interface `I` in type `type` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   C.(I.Op)();\n  // CHECK:STDERR:   ^~~~~~~~\n  // CHECK:STDERR:\n  C.(I.Op)();\n}\n\n// --- fail_conflicting_bad_impls.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\nclass C(T:! type) {}\n\n// CHECK:STDERR: fail_conflicting_bad_impls.carbon:[[@LINE+4]]:12: error: name `invalid` not found [NameNotFound]\n// CHECK:STDERR: final impl invalid as I {}\n// CHECK:STDERR:            ^~~~~~~\n// CHECK:STDERR:\nfinal impl invalid as I {}\n// CHECK:STDERR: fail_conflicting_bad_impls.carbon:[[@LINE+11]]:12: error: name `invalid` not found [NameNotFound]\n// CHECK:STDERR: final impl invalid as I {}\n// CHECK:STDERR:            ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_conflicting_bad_impls.carbon:[[@LINE+7]]:1: error: redefinition of `impl <error> as I` [ImplRedefinition]\n// CHECK:STDERR: final impl invalid as I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_conflicting_bad_impls.carbon:[[@LINE-8]]:1: note: previous definition was here [ImplPreviousDefinition]\n// CHECK:STDERR: final impl invalid as I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfinal impl invalid as I {}\n\n// CHECK:STDERR: fail_conflicting_bad_impls.carbon:[[@LINE+4]]:12: error: name `alsoinvalid` not found [NameNotFound]\n// CHECK:STDERR: final impl alsoinvalid as I {}\n// CHECK:STDERR:            ^~~~~~~~~~~\n// CHECK:STDERR:\nfinal impl alsoinvalid as I {}\n\n// CHECK:STDERR: fail_conflicting_bad_impls.carbon:[[@LINE+4]]:14: error: name `invalid` not found [NameNotFound]\n// CHECK:STDERR: final impl C(invalid) as I {}\n// CHECK:STDERR:              ^~~~~~~\n// CHECK:STDERR:\nfinal impl C(invalid) as I {}\n// CHECK:STDERR: fail_conflicting_bad_impls.carbon:[[@LINE+11]]:14: error: name `invalid` not found [NameNotFound]\n// CHECK:STDERR: final impl C(invalid) as I {}\n// CHECK:STDERR:              ^~~~~~~\n// CHECK:STDERR:\n// CHECK:STDERR: fail_conflicting_bad_impls.carbon:[[@LINE+7]]:1: error: redefinition of `impl <error> as I` [ImplRedefinition]\n// CHECK:STDERR: final impl C(invalid) as I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_conflicting_bad_impls.carbon:[[@LINE-8]]:1: note: previous definition was here [ImplPreviousDefinition]\n// CHECK:STDERR: final impl C(invalid) as I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nfinal impl C(invalid) as I {}\n\n// CHECK:STDOUT: --- basic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Simple.type: type = facet_type <@Simple> [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %Simple.impl_witness: <witness> = impl_witness @C.as.Simple.impl.%Simple.impl_witness_table [concrete]\n// CHECK:STDOUT:   %C.as.Simple.impl.F.type: type = fn_type @C.as.Simple.impl.F [concrete]\n// CHECK:STDOUT:   %C.as.Simple.impl.F: %C.as.Simple.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   impl_decl @C.as.Simple.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %Simple.ref: type = name_ref Simple, file.%Simple.decl [concrete = constants.%Simple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.Simple.impl: %C.ref as %Simple.ref {\n// CHECK:STDOUT:   %C.as.Simple.impl.F.decl: %C.as.Simple.impl.F.type = fn_decl @C.as.Simple.impl.F [concrete = constants.%C.as.Simple.impl.F] {} {}\n// CHECK:STDOUT:   %Simple.impl_witness_table = impl_witness_table (%C.as.Simple.impl.F.decl), @C.as.Simple.impl [concrete]\n// CHECK:STDOUT:   %Simple.impl_witness: <witness> = impl_witness %Simple.impl_witness_table [concrete = constants.%Simple.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %C.as.Simple.impl.F.decl\n// CHECK:STDOUT:   witness = %Simple.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.Simple.impl.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/compound.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/compound.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/compound.carbon\n\n// --- core.carbon\npackage Core;\n\ninterface ImplicitAs(Dest:! type) {\n  fn Convert[self: Self]() -> Dest;\n}\n\n// --- non-instance_success.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface NonInstance1 {\n  fn F1();\n}\n\nimpl {.a: ()} as NonInstance1 {\n  fn F1() {}\n}\n\nfn NonInstanceCall1() {\n  {.a: ()}.(NonInstance1.F1)();\n}\n\n// --- fail_non-instance.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nimport Core;\n\ninterface NonInstance2 {\n  fn F2();\n}\n\nimpl {.b: ()} as NonInstance2 {\n  fn F2() {}\n}\n\nfn NonInstanceCall2(n: {.b: ()}) {\n  // CHECK:STDERR: fail_non-instance.carbon:[[@LINE+7]]:3: error: cannot implicitly convert non-type value of type `{.b: ()}` into type implementing `NonInstance2` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   n.(NonInstance2.F2)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_non-instance.carbon:[[@LINE+4]]:3: note: type `{.b: ()}` does not implement interface `Core.ImplicitAs(NonInstance2)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   n.(NonInstance2.F2)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  n.(NonInstance2.F2)();\n}\n\n// --- fail_non-instance_indirect.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nimport Core;\n\ninterface NonInstance3 {\n  fn F3();\n}\n\nimpl {.c: ()} as NonInstance3 {\n  fn F3() {}\n}\n\nfn NonInstanceCallIndirect(p: {.c: ()}*) {\n  // CHECK:STDERR: fail_non-instance_indirect.carbon:[[@LINE+7]]:3: error: cannot implicitly convert non-type value of type `{.c: ()}` into type implementing `NonInstance3` [ConversionFailureNonTypeToFacet]\n  // CHECK:STDERR:   p->(NonInstance3.F3)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_non-instance_indirect.carbon:[[@LINE+4]]:3: note: type `{.c: ()}` does not implement interface `Core.ImplicitAs(NonInstance3)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   p->(NonInstance3.F3)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  p->(NonInstance3.F3)();\n}\n\n// --- instance_success.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Instance1 {\n  fn G1[self: Self]();\n}\n\nimpl {.d: ()} as Instance1 {\n  fn G1[unused self: Self]() {}\n}\n\nfn InstanceCall(n: {.d: ()}) {\n  n.(Instance1.G1)();\n}\n\nfn InstanceCallIndirect(p: {.d: ()}*) {\n  p->(Instance1.G1)();\n}\n\n// --- fail_instance.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Instance2 {\n  fn G2[self: Self]();\n}\n\nimpl {.e: ()} as Instance2 {\n  fn G2[unused self: Self]() {}\n}\n\nfn InstanceCallFail() {\n  // CHECK:STDERR: fail_instance.carbon:[[@LINE+4]]:3: error: cannot access member of interface `Instance2` in type `type` that does not implement that interface [MissingImplInMemberAccess]\n  // CHECK:STDERR:   {.e: ()}.(Instance2.G2)();\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  {.e: ()}.(Instance2.G2)();\n}\n\n// CHECK:STDOUT: --- core.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.595: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.595 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.9fe: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic]\n// CHECK:STDOUT:   %Self: %ImplicitAs.type.9fe = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic]\n// CHECK:STDOUT:   %pattern_type.8de: type = pattern_type %Self.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %Dest [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %Dest [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Dest, %Self) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert: %ImplicitAs.WithSelf.Convert.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic]\n// CHECK:STDOUT:   %assoc0: %ImplicitAs.assoc_type = assoc_entity element0, @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.decl [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %ImplicitAs.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %ImplicitAs.decl: %ImplicitAs.type.595 = interface_decl @ImplicitAs [concrete = constants.%ImplicitAs.generic] {\n// CHECK:STDOUT:     %Dest.patt: %pattern_type.98f = symbolic_binding_pattern Dest, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc3_29.1: type = splice_block %.loc3_29.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc3_29.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %Dest.loc3_22.2: type = symbolic_binding Dest, 0 [symbolic = %Dest.loc3_22.1 (constants.%Dest)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @ImplicitAs(%Dest.loc3_22.2: type) {\n// CHECK:STDOUT:   %Dest.loc3_22.1: type = symbolic_binding Dest, 0 [symbolic = %Dest.loc3_22.1 (constants.%Dest)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest.loc3_22.1)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.9fe)]\n// CHECK:STDOUT:   %Self.loc3_35.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.9fe) = symbolic_binding Self, 1 [symbolic = %Self.loc3_35.2 (constants.%Self)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc3_35.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.9fe) = symbolic_binding Self, 1 [symbolic = %Self.loc3_35.2 (constants.%Self)]\n// CHECK:STDOUT:     %ImplicitAs.WithSelf.decl = interface_with_self_decl @ImplicitAs [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %ImplicitAs.WithSelf.Convert.decl: @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.type (%ImplicitAs.WithSelf.Convert.type) = fn_decl @ImplicitAs.WithSelf.Convert [symbolic = @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert (constants.%ImplicitAs.WithSelf.Convert)] {\n// CHECK:STDOUT:       %self.patt: @ImplicitAs.WithSelf.Convert.%pattern_type.loc4_14 (%pattern_type.8de) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @ImplicitAs.WithSelf.Convert.%pattern_type.loc4_14 (%pattern_type.8de) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %return.patt: @ImplicitAs.WithSelf.Convert.%pattern_type.loc4_28 (%pattern_type.51d) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @ImplicitAs.WithSelf.Convert.%pattern_type.loc4_28 (%pattern_type.51d) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Dest.ref: type = name_ref Dest, @ImplicitAs.%Dest.loc3_22.2 [symbolic = %Dest (constants.%Dest)]\n// CHECK:STDOUT:       %.loc4_31.2: Core.Form = init_form %Dest.ref [symbolic = %.loc4_31.1 (constants.%.184)]\n// CHECK:STDOUT:       %self.param: @ImplicitAs.WithSelf.Convert.%Self.binding.as_type (%Self.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:       %.loc4_20.1: type = splice_block %.loc4_20.3 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)] {\n// CHECK:STDOUT:         %.loc4_20.2: @ImplicitAs.WithSelf.Convert.%ImplicitAs.type (%ImplicitAs.type.9fe) = specific_constant @ImplicitAs.%Self.loc3_35.1, @ImplicitAs(constants.%Dest) [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:         %Self.ref: @ImplicitAs.WithSelf.Convert.%ImplicitAs.type (%ImplicitAs.type.9fe) = name_ref Self, %.loc4_20.2 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:         %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:         %.loc4_20.3: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @ImplicitAs.WithSelf.Convert.%Self.binding.as_type (%Self.binding.as_type) = value_binding self, %self.param\n// CHECK:STDOUT:       %return.param: ref @ImplicitAs.WithSelf.Convert.%Dest (%Dest) = out_param call_param1\n// CHECK:STDOUT:       %return: ref @ImplicitAs.WithSelf.Convert.%Dest (%Dest) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %assoc0.loc4_35.1: @ImplicitAs.WithSelf.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type) = assoc_entity element0, %ImplicitAs.WithSelf.Convert.decl [symbolic = %assoc0.loc4_35.2 (constants.%assoc0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc3_35.1\n// CHECK:STDOUT:     .Dest = <poisoned>\n// CHECK:STDOUT:     .Dest = <poisoned>\n// CHECK:STDOUT:     .Convert = @ImplicitAs.WithSelf.%assoc0.loc4_35.1\n// CHECK:STDOUT:     witness = (@ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ImplicitAs.WithSelf.Convert(@ImplicitAs.%Dest.loc3_22.2: type, @ImplicitAs.%Self.loc3_35.1: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.9fe)) {\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic = %Dest (constants.%Dest)]\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.9fe)]\n// CHECK:STDOUT:   %Self: @ImplicitAs.WithSelf.Convert.%ImplicitAs.type (%ImplicitAs.type.9fe) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type.loc4_14: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type.loc4_14 (constants.%pattern_type.8de)]\n// CHECK:STDOUT:   %.loc4_31.1: Core.Form = init_form %Dest [symbolic = %.loc4_31.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.loc4_28: type = pattern_type %Dest [symbolic = %pattern_type.loc4_28 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @ImplicitAs.WithSelf.Convert.%Self.binding.as_type (%Self.binding.as_type)) -> out %return.param: @ImplicitAs.WithSelf.Convert.%Dest (%Dest);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) {\n// CHECK:STDOUT:   %Dest.loc3_22.1 => constants.%Dest\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%Dest, constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf.Convert(constants.%Dest, constants.%Self) {\n// CHECK:STDOUT:   %Dest => constants.%Dest\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.9fe\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %pattern_type.loc4_14 => constants.%pattern_type.8de\n// CHECK:STDOUT:   %.loc4_31.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.loc4_28 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- non-instance_success.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %NonInstance1.type: type = facet_type <@NonInstance1> [concrete]\n// CHECK:STDOUT:   %Self: %NonInstance1.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %NonInstance1.WithSelf.F1.type.3a6: type = fn_type @NonInstance1.WithSelf.F1, @NonInstance1.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %NonInstance1.WithSelf.F1.898: %NonInstance1.WithSelf.F1.type.3a6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %NonInstance1.assoc_type: type = assoc_entity_type @NonInstance1 [concrete]\n// CHECK:STDOUT:   %assoc0: %NonInstance1.assoc_type = assoc_entity element0, @NonInstance1.WithSelf.%NonInstance1.WithSelf.F1.decl [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %NonInstance1.impl_witness: <witness> = impl_witness @struct_type.a.as.NonInstance1.impl.%NonInstance1.impl_witness_table [concrete]\n// CHECK:STDOUT:   %struct_type.a.as.NonInstance1.impl.F1.type: type = fn_type @struct_type.a.as.NonInstance1.impl.F1 [concrete]\n// CHECK:STDOUT:   %struct_type.a.as.NonInstance1.impl.F1: %struct_type.a.as.NonInstance1.impl.F1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %NonInstance1.facet: %NonInstance1.type = facet_value %struct_type.a, (%NonInstance1.impl_witness) [concrete]\n// CHECK:STDOUT:   %NonInstance1.WithSelf.F1.type.a2c: type = fn_type @NonInstance1.WithSelf.F1, @NonInstance1.WithSelf(%NonInstance1.facet) [concrete]\n// CHECK:STDOUT:   %NonInstance1.WithSelf.F1.e33: %NonInstance1.WithSelf.F1.type.a2c = struct_value () [concrete]\n// CHECK:STDOUT:   %NonInstanceCall1.type: type = fn_type @NonInstanceCall1 [concrete]\n// CHECK:STDOUT:   %NonInstanceCall1: %NonInstanceCall1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.737: type = fn_type_with_self_type %NonInstance1.WithSelf.F1.type.a2c, %NonInstance1.facet [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .NonInstance1 = %NonInstance1.decl\n// CHECK:STDOUT:     .NonInstanceCall1 = %NonInstanceCall1.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %NonInstance1.decl: type = interface_decl @NonInstance1 [concrete = constants.%NonInstance1.type] {} {}\n// CHECK:STDOUT:   impl_decl @struct_type.a.as.NonInstance1.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc7_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_12.2: type = converted %.loc7_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete = constants.%struct_type.a]\n// CHECK:STDOUT:     %NonInstance1.ref: type = name_ref NonInstance1, file.%NonInstance1.decl [concrete = constants.%NonInstance1.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %NonInstanceCall1.decl: %NonInstanceCall1.type = fn_decl @NonInstanceCall1 [concrete = constants.%NonInstanceCall1] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @NonInstance1 {\n// CHECK:STDOUT:   %Self: %NonInstance1.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %NonInstance1.WithSelf.decl = interface_with_self_decl @NonInstance1 [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %NonInstance1.WithSelf.F1.decl: @NonInstance1.WithSelf.%NonInstance1.WithSelf.F1.type (%NonInstance1.WithSelf.F1.type.3a6) = fn_decl @NonInstance1.WithSelf.F1 [symbolic = @NonInstance1.WithSelf.%NonInstance1.WithSelf.F1 (constants.%NonInstance1.WithSelf.F1.898)] {} {}\n// CHECK:STDOUT:   %assoc0: %NonInstance1.assoc_type = assoc_entity element0, %NonInstance1.WithSelf.F1.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F1 = @NonInstance1.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@NonInstance1.WithSelf.%NonInstance1.WithSelf.F1.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @struct_type.a.as.NonInstance1.impl: %struct_type.a as %NonInstance1.ref {\n// CHECK:STDOUT:   %struct_type.a.as.NonInstance1.impl.F1.decl: %struct_type.a.as.NonInstance1.impl.F1.type = fn_decl @struct_type.a.as.NonInstance1.impl.F1 [concrete = constants.%struct_type.a.as.NonInstance1.impl.F1] {} {}\n// CHECK:STDOUT:   %NonInstance1.impl_witness_table = impl_witness_table (%struct_type.a.as.NonInstance1.impl.F1.decl), @struct_type.a.as.NonInstance1.impl [concrete]\n// CHECK:STDOUT:   %NonInstance1.impl_witness: <witness> = impl_witness %NonInstance1.impl_witness_table [concrete = constants.%NonInstance1.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F1 = %struct_type.a.as.NonInstance1.impl.F1.decl\n// CHECK:STDOUT:   witness = %NonInstance1.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @NonInstance1.WithSelf.F1(@NonInstance1.%Self: %NonInstance1.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @struct_type.a.as.NonInstance1.impl.F1() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @NonInstanceCall1() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc12_9.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc12_9.2: type = converted %.loc12_9.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: %empty_tuple.type} [concrete = constants.%struct_type.a]\n// CHECK:STDOUT:   %NonInstance1.ref: type = name_ref NonInstance1, file.%NonInstance1.decl [concrete = constants.%NonInstance1.type]\n// CHECK:STDOUT:   %F1.ref: %NonInstance1.assoc_type = name_ref F1, @NonInstance1.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %NonInstance1.facet: %NonInstance1.type = facet_value %struct_type.a, (constants.%NonInstance1.impl_witness) [concrete = constants.%NonInstance1.facet]\n// CHECK:STDOUT:   %.loc12_11: %NonInstance1.type = converted %struct_type.a, %NonInstance1.facet [concrete = constants.%NonInstance1.facet]\n// CHECK:STDOUT:   %impl.elem0: %.737 = impl_witness_access constants.%NonInstance1.impl_witness, element0 [concrete = constants.%struct_type.a.as.NonInstance1.impl.F1]\n// CHECK:STDOUT:   %struct_type.a.as.NonInstance1.impl.F1.call: init %empty_tuple.type = call %impl.elem0()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance1.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %NonInstance1.WithSelf.F1.type => constants.%NonInstance1.WithSelf.F1.type.3a6\n// CHECK:STDOUT:   %NonInstance1.WithSelf.F1 => constants.%NonInstance1.WithSelf.F1.898\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance1.WithSelf.F1(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance1.WithSelf(constants.%NonInstance1.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%NonInstance1.facet\n// CHECK:STDOUT:   %NonInstance1.WithSelf.F1.type => constants.%NonInstance1.WithSelf.F1.type.a2c\n// CHECK:STDOUT:   %NonInstance1.WithSelf.F1 => constants.%NonInstance1.WithSelf.F1.e33\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance1.WithSelf.F1(constants.%NonInstance1.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_non-instance.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %NonInstance2.type: type = facet_type <@NonInstance2> [concrete]\n// CHECK:STDOUT:   %Self.e6c: %NonInstance2.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %NonInstance2.WithSelf.F2.type.824: type = fn_type @NonInstance2.WithSelf.F2, @NonInstance2.WithSelf(%Self.e6c) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %NonInstance2.WithSelf.F2.9da: %NonInstance2.WithSelf.F2.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %NonInstance2.assoc_type: type = assoc_entity_type @NonInstance2 [concrete]\n// CHECK:STDOUT:   %assoc0.56f: %NonInstance2.assoc_type = assoc_entity element0, @NonInstance2.WithSelf.%NonInstance2.WithSelf.F2.decl [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct_type.b: type = struct_type {.b: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %NonInstance2.impl_witness: <witness> = impl_witness @struct_type.b.as.NonInstance2.impl.%NonInstance2.impl_witness_table [concrete]\n// CHECK:STDOUT:   %struct_type.b.as.NonInstance2.impl.F2.type: type = fn_type @struct_type.b.as.NonInstance2.impl.F2 [concrete]\n// CHECK:STDOUT:   %struct_type.b.as.NonInstance2.impl.F2: %struct_type.b.as.NonInstance2.impl.F2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %NonInstance2.facet: %NonInstance2.type = facet_value %struct_type.b, (%NonInstance2.impl_witness) [concrete]\n// CHECK:STDOUT:   %NonInstance2.WithSelf.F2.type.041: type = fn_type @NonInstance2.WithSelf.F2, @NonInstance2.WithSelf(%NonInstance2.facet) [concrete]\n// CHECK:STDOUT:   %NonInstance2.WithSelf.F2.fc4: %NonInstance2.WithSelf.F2.type.041 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.d5c: type = pattern_type %struct_type.b [concrete]\n// CHECK:STDOUT:   %NonInstanceCall2.type: type = fn_type @NonInstanceCall2 [concrete]\n// CHECK:STDOUT:   %NonInstanceCall2: %NonInstanceCall2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.031: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic]\n// CHECK:STDOUT:   %Self.738: %ImplicitAs.type.031 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.ff3: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b3a: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Dest, %Self.738) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.1de: %ImplicitAs.WithSelf.Convert.type.b3a = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %Dest [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.738 [symbolic]\n// CHECK:STDOUT:   %pattern_type.e9a: type = pattern_type %Self.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %Dest [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.282: type = facet_type <@ImplicitAs, @ImplicitAs(%NonInstance2.type)> [concrete]\n// CHECK:STDOUT:   %Self.df1: %ImplicitAs.type.282 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.03b: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%NonInstance2.type, %Self.738) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.4fe: %ImplicitAs.WithSelf.Convert.type.03b = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.cd6: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%NonInstance2.type) [concrete]\n// CHECK:STDOUT:   %assoc0.af4: %ImplicitAs.assoc_type.cd6 = assoc_entity element0, imports.%Core.import_ref.201 [concrete]\n// CHECK:STDOUT:   %assoc0.843: %ImplicitAs.assoc_type.ff3 = assoc_entity element0, imports.%Core.import_ref.cc1 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//default\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//default, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.178: @ImplicitAs.WithSelf.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.ff3) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%assoc0 (constants.%assoc0.843)]\n// CHECK:STDOUT:   %Core.Convert = import_ref Core//default, Convert, unloaded\n// CHECK:STDOUT:   %Core.import_ref.201: @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.type (%ImplicitAs.WithSelf.Convert.type.b3a) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert (constants.%ImplicitAs.WithSelf.Convert.1de)]\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.2: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.%Dest (constants.%Dest)]\n// CHECK:STDOUT:   %Core.import_ref.ac4dc5.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.031) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.%Self (constants.%Self.738)]\n// CHECK:STDOUT:   %Core.import_ref.9ec = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.3: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.%Dest (constants.%Dest)]\n// CHECK:STDOUT:   %Core.import_ref.cc1 = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .NonInstance2 = %NonInstance2.decl\n// CHECK:STDOUT:     .NonInstanceCall2 = %NonInstanceCall2.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %NonInstance2.decl: type = interface_decl @NonInstance2 [concrete = constants.%NonInstance2.type] {} {}\n// CHECK:STDOUT:   impl_decl @struct_type.b.as.NonInstance2.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc9_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc9_12.2: type = converted %.loc9_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %struct_type.b: type = struct_type {.b: %empty_tuple.type} [concrete = constants.%struct_type.b]\n// CHECK:STDOUT:     %NonInstance2.ref: type = name_ref NonInstance2, file.%NonInstance2.decl [concrete = constants.%NonInstance2.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %NonInstanceCall2.decl: %NonInstanceCall2.type = fn_decl @NonInstanceCall2 [concrete = constants.%NonInstanceCall2] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.d5c = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.d5c = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %n.param: %struct_type.b = value_param call_param0\n// CHECK:STDOUT:     %.loc13_31: type = splice_block %struct_type.b [concrete = constants.%struct_type.b] {\n// CHECK:STDOUT:       %.loc13_30.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc13_30.2: type = converted %.loc13_30.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %struct_type.b: type = struct_type {.b: %empty_tuple.type} [concrete = constants.%struct_type.b]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %n: %struct_type.b = value_binding n, %n.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @NonInstance2 {\n// CHECK:STDOUT:   %Self: %NonInstance2.type = symbolic_binding Self, 0 [symbolic = constants.%Self.e6c]\n// CHECK:STDOUT:   %NonInstance2.WithSelf.decl = interface_with_self_decl @NonInstance2 [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %NonInstance2.WithSelf.F2.decl: @NonInstance2.WithSelf.%NonInstance2.WithSelf.F2.type (%NonInstance2.WithSelf.F2.type.824) = fn_decl @NonInstance2.WithSelf.F2 [symbolic = @NonInstance2.WithSelf.%NonInstance2.WithSelf.F2 (constants.%NonInstance2.WithSelf.F2.9da)] {} {}\n// CHECK:STDOUT:   %assoc0: %NonInstance2.assoc_type = assoc_entity element0, %NonInstance2.WithSelf.F2.decl [concrete = constants.%assoc0.56f]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F2 = @NonInstance2.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@NonInstance2.WithSelf.%NonInstance2.WithSelf.F2.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @ImplicitAs(imports.%Core.import_ref.b3bc94.3: type) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic = %Dest (constants.%Dest)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.031)]\n// CHECK:STDOUT:   %Self: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.031) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.738)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Core.import_ref.9ec\n// CHECK:STDOUT:     .Convert = imports.%Core.import_ref.178\n// CHECK:STDOUT:     witness = (imports.%Core.Convert)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @struct_type.b.as.NonInstance2.impl: %struct_type.b as %NonInstance2.ref {\n// CHECK:STDOUT:   %struct_type.b.as.NonInstance2.impl.F2.decl: %struct_type.b.as.NonInstance2.impl.F2.type = fn_decl @struct_type.b.as.NonInstance2.impl.F2 [concrete = constants.%struct_type.b.as.NonInstance2.impl.F2] {} {}\n// CHECK:STDOUT:   %NonInstance2.impl_witness_table = impl_witness_table (%struct_type.b.as.NonInstance2.impl.F2.decl), @struct_type.b.as.NonInstance2.impl [concrete]\n// CHECK:STDOUT:   %NonInstance2.impl_witness: <witness> = impl_witness %NonInstance2.impl_witness_table [concrete = constants.%NonInstance2.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F2 = %struct_type.b.as.NonInstance2.impl.F2.decl\n// CHECK:STDOUT:   witness = %NonInstance2.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @NonInstance2.WithSelf.F2(@NonInstance2.%Self: %NonInstance2.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @struct_type.b.as.NonInstance2.impl.F2() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @NonInstanceCall2(%n.param: %struct_type.b) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %struct_type.b = name_ref n, %n\n// CHECK:STDOUT:   %NonInstance2.ref: type = name_ref NonInstance2, file.%NonInstance2.decl [concrete = constants.%NonInstance2.type]\n// CHECK:STDOUT:   %F2.ref: %NonInstance2.assoc_type = name_ref F2, @NonInstance2.WithSelf.%assoc0 [concrete = constants.%assoc0.56f]\n// CHECK:STDOUT:   %.loc21: %NonInstance2.type = converted %n.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ImplicitAs.WithSelf.Convert(imports.%Core.import_ref.b3bc94.2: type, imports.%Core.import_ref.ac4dc5.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.031)) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic = %Dest (constants.%Dest)]\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.031)]\n// CHECK:STDOUT:   %Self: @ImplicitAs.WithSelf.Convert.%ImplicitAs.type (%ImplicitAs.type.031) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.738)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type.1: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type.1 (constants.%pattern_type.e9a)]\n// CHECK:STDOUT:   %.1: Core.Form = init_form %Dest [symbolic = %.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.2: type = pattern_type %Dest [symbolic = %pattern_type.2 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance2.WithSelf(constants.%Self.e6c) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.e6c\n// CHECK:STDOUT:   %NonInstance2.WithSelf.F2.type => constants.%NonInstance2.WithSelf.F2.type.824\n// CHECK:STDOUT:   %NonInstance2.WithSelf.F2 => constants.%NonInstance2.WithSelf.F2.9da\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance2.WithSelf.F2(constants.%Self.e6c) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance2.WithSelf(constants.%NonInstance2.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%NonInstance2.facet\n// CHECK:STDOUT:   %NonInstance2.WithSelf.F2.type => constants.%NonInstance2.WithSelf.F2.type.041\n// CHECK:STDOUT:   %NonInstance2.WithSelf.F2 => constants.%NonInstance2.WithSelf.F2.fc4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance2.WithSelf.F2(constants.%NonInstance2.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) {\n// CHECK:STDOUT:   %Dest => constants.%Dest\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%Dest, constants.%Self.738) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf.Convert(constants.%Dest, constants.%Self.738) {\n// CHECK:STDOUT:   %Dest => constants.%Dest\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.031\n// CHECK:STDOUT:   %Self => constants.%Self.738\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %pattern_type.1 => constants.%pattern_type.e9a\n// CHECK:STDOUT:   %.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.2 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(constants.%NonInstance2.type) {\n// CHECK:STDOUT:   %Dest => constants.%NonInstance2.type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.282\n// CHECK:STDOUT:   %Self => constants.%Self.df1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%NonInstance2.type, constants.%Self.738) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Dest => constants.%NonInstance2.type\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.282\n// CHECK:STDOUT:   %Self => constants.%Self.738\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.03b\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.4fe\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.cd6\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.af4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_non-instance_indirect.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %NonInstance3.type: type = facet_type <@NonInstance3> [concrete]\n// CHECK:STDOUT:   %Self.0da: %NonInstance3.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %NonInstance3.WithSelf.F3.type.c21: type = fn_type @NonInstance3.WithSelf.F3, @NonInstance3.WithSelf(%Self.0da) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %NonInstance3.WithSelf.F3.b62: %NonInstance3.WithSelf.F3.type.c21 = struct_value () [symbolic]\n// CHECK:STDOUT:   %NonInstance3.assoc_type: type = assoc_entity_type @NonInstance3 [concrete]\n// CHECK:STDOUT:   %assoc0.342: %NonInstance3.assoc_type = assoc_entity element0, @NonInstance3.WithSelf.%NonInstance3.WithSelf.F3.decl [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct_type.c: type = struct_type {.c: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %NonInstance3.impl_witness: <witness> = impl_witness @struct_type.c.as.NonInstance3.impl.%NonInstance3.impl_witness_table [concrete]\n// CHECK:STDOUT:   %struct_type.c.as.NonInstance3.impl.F3.type: type = fn_type @struct_type.c.as.NonInstance3.impl.F3 [concrete]\n// CHECK:STDOUT:   %struct_type.c.as.NonInstance3.impl.F3: %struct_type.c.as.NonInstance3.impl.F3.type = struct_value () [concrete]\n// CHECK:STDOUT:   %NonInstance3.facet: %NonInstance3.type = facet_value %struct_type.c, (%NonInstance3.impl_witness) [concrete]\n// CHECK:STDOUT:   %NonInstance3.WithSelf.F3.type.a3f: type = fn_type @NonInstance3.WithSelf.F3, @NonInstance3.WithSelf(%NonInstance3.facet) [concrete]\n// CHECK:STDOUT:   %NonInstance3.WithSelf.F3.04b: %NonInstance3.WithSelf.F3.type.a3f = struct_value () [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %struct_type.c [concrete]\n// CHECK:STDOUT:   %pattern_type.5f5: type = pattern_type %ptr [concrete]\n// CHECK:STDOUT:   %NonInstanceCallIndirect.type: type = fn_type @NonInstanceCallIndirect [concrete]\n// CHECK:STDOUT:   %NonInstanceCallIndirect: %NonInstanceCallIndirect.type = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.031: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic]\n// CHECK:STDOUT:   %Self.738: %ImplicitAs.type.031 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.ff3: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b3a: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%Dest, %Self.738) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.1de: %ImplicitAs.WithSelf.Convert.type.b3a = struct_value () [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %Dest [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.738 [symbolic]\n// CHECK:STDOUT:   %pattern_type.e9a: type = pattern_type %Self.binding.as_type [symbolic]\n// CHECK:STDOUT:   %.184: Core.Form = init_form %Dest [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.type.deb: type = facet_type <@ImplicitAs, @ImplicitAs(%NonInstance3.type)> [concrete]\n// CHECK:STDOUT:   %Self.9cf: %ImplicitAs.type.deb = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.8ec: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%NonInstance3.type, %Self.738) [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.0e4: %ImplicitAs.WithSelf.Convert.type.8ec = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.assoc_type.eea: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%NonInstance3.type) [concrete]\n// CHECK:STDOUT:   %assoc0.605: %ImplicitAs.assoc_type.eea = assoc_entity element0, imports.%Core.import_ref.201 [concrete]\n// CHECK:STDOUT:   %assoc0.843: %ImplicitAs.assoc_type.ff3 = assoc_entity element0, imports.%Core.import_ref.cc1 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//default\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//default, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.178: @ImplicitAs.WithSelf.%ImplicitAs.assoc_type (%ImplicitAs.assoc_type.ff3) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%assoc0 (constants.%assoc0.843)]\n// CHECK:STDOUT:   %Core.Convert = import_ref Core//default, Convert, unloaded\n// CHECK:STDOUT:   %Core.import_ref.201: @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert.type (%ImplicitAs.WithSelf.Convert.type.b3a) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.WithSelf.%ImplicitAs.WithSelf.Convert (constants.%ImplicitAs.WithSelf.Convert.1de)]\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.2: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.%Dest (constants.%Dest)]\n// CHECK:STDOUT:   %Core.import_ref.ac4dc5.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.031) = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.%Self (constants.%Self.738)]\n// CHECK:STDOUT:   %Core.import_ref.9ec = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.b3bc94.3: type = import_ref Core//default, loc{{\\d+_\\d+}}, loaded [symbolic = @ImplicitAs.%Dest (constants.%Dest)]\n// CHECK:STDOUT:   %Core.import_ref.cc1 = import_ref Core//default, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .NonInstance3 = %NonInstance3.decl\n// CHECK:STDOUT:     .NonInstanceCallIndirect = %NonInstanceCallIndirect.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %NonInstance3.decl: type = interface_decl @NonInstance3 [concrete = constants.%NonInstance3.type] {} {}\n// CHECK:STDOUT:   impl_decl @struct_type.c.as.NonInstance3.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc9_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc9_12.2: type = converted %.loc9_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %struct_type.c: type = struct_type {.c: %empty_tuple.type} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:     %NonInstance3.ref: type = name_ref NonInstance3, file.%NonInstance3.decl [concrete = constants.%NonInstance3.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %NonInstanceCallIndirect.decl: %NonInstanceCallIndirect.type = fn_decl @NonInstanceCallIndirect [concrete = constants.%NonInstanceCallIndirect] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.5f5 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.5f5 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %ptr = value_param call_param0\n// CHECK:STDOUT:     %.loc13_39: type = splice_block %ptr [concrete = constants.%ptr] {\n// CHECK:STDOUT:       %.loc13_37.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc13_37.2: type = converted %.loc13_37.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %struct_type.c: type = struct_type {.c: %empty_tuple.type} [concrete = constants.%struct_type.c]\n// CHECK:STDOUT:       %ptr: type = ptr_type %struct_type.c [concrete = constants.%ptr]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @NonInstance3 {\n// CHECK:STDOUT:   %Self: %NonInstance3.type = symbolic_binding Self, 0 [symbolic = constants.%Self.0da]\n// CHECK:STDOUT:   %NonInstance3.WithSelf.decl = interface_with_self_decl @NonInstance3 [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %NonInstance3.WithSelf.F3.decl: @NonInstance3.WithSelf.%NonInstance3.WithSelf.F3.type (%NonInstance3.WithSelf.F3.type.c21) = fn_decl @NonInstance3.WithSelf.F3 [symbolic = @NonInstance3.WithSelf.%NonInstance3.WithSelf.F3 (constants.%NonInstance3.WithSelf.F3.b62)] {} {}\n// CHECK:STDOUT:   %assoc0: %NonInstance3.assoc_type = assoc_entity element0, %NonInstance3.WithSelf.F3.decl [concrete = constants.%assoc0.342]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F3 = @NonInstance3.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@NonInstance3.WithSelf.%NonInstance3.WithSelf.F3.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @ImplicitAs(imports.%Core.import_ref.b3bc94.3: type) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic = %Dest (constants.%Dest)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.031)]\n// CHECK:STDOUT:   %Self: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.031) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.738)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Core.import_ref.9ec\n// CHECK:STDOUT:     .Convert = imports.%Core.import_ref.178\n// CHECK:STDOUT:     witness = (imports.%Core.Convert)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @struct_type.c.as.NonInstance3.impl: %struct_type.c as %NonInstance3.ref {\n// CHECK:STDOUT:   %struct_type.c.as.NonInstance3.impl.F3.decl: %struct_type.c.as.NonInstance3.impl.F3.type = fn_decl @struct_type.c.as.NonInstance3.impl.F3 [concrete = constants.%struct_type.c.as.NonInstance3.impl.F3] {} {}\n// CHECK:STDOUT:   %NonInstance3.impl_witness_table = impl_witness_table (%struct_type.c.as.NonInstance3.impl.F3.decl), @struct_type.c.as.NonInstance3.impl [concrete]\n// CHECK:STDOUT:   %NonInstance3.impl_witness: <witness> = impl_witness %NonInstance3.impl_witness_table [concrete = constants.%NonInstance3.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F3 = %struct_type.c.as.NonInstance3.impl.F3.decl\n// CHECK:STDOUT:   witness = %NonInstance3.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @NonInstance3.WithSelf.F3(@NonInstance3.%Self: %NonInstance3.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @struct_type.c.as.NonInstance3.impl.F3() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @NonInstanceCallIndirect(%p.param: %ptr) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr = name_ref p, %p\n// CHECK:STDOUT:   %NonInstance3.ref: type = name_ref NonInstance3, file.%NonInstance3.decl [concrete = constants.%NonInstance3.type]\n// CHECK:STDOUT:   %F3.ref: %NonInstance3.assoc_type = name_ref F3, @NonInstance3.WithSelf.%assoc0 [concrete = constants.%assoc0.342]\n// CHECK:STDOUT:   %.loc21_4.1: ref %struct_type.c = deref %p.ref\n// CHECK:STDOUT:   %.loc21_4.2: %NonInstance3.type = converted %.loc21_4.1, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @ImplicitAs.WithSelf.Convert(imports.%Core.import_ref.b3bc94.2: type, imports.%Core.import_ref.ac4dc5.2: @ImplicitAs.%ImplicitAs.type (%ImplicitAs.type.031)) [from \"core.carbon\"] {\n// CHECK:STDOUT:   %Dest: type = symbolic_binding Dest, 0 [symbolic = %Dest (constants.%Dest)]\n// CHECK:STDOUT:   %ImplicitAs.type: type = facet_type <@ImplicitAs, @ImplicitAs(%Dest)> [symbolic = %ImplicitAs.type (constants.%ImplicitAs.type.031)]\n// CHECK:STDOUT:   %Self: @ImplicitAs.WithSelf.Convert.%ImplicitAs.type (%ImplicitAs.type.031) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.738)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type.1: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type.1 (constants.%pattern_type.e9a)]\n// CHECK:STDOUT:   %.1: Core.Form = init_form %Dest [symbolic = %.1 (constants.%.184)]\n// CHECK:STDOUT:   %pattern_type.2: type = pattern_type %Dest [symbolic = %pattern_type.2 (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance3.WithSelf(constants.%Self.0da) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.0da\n// CHECK:STDOUT:   %NonInstance3.WithSelf.F3.type => constants.%NonInstance3.WithSelf.F3.type.c21\n// CHECK:STDOUT:   %NonInstance3.WithSelf.F3 => constants.%NonInstance3.WithSelf.F3.b62\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance3.WithSelf.F3(constants.%Self.0da) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance3.WithSelf(constants.%NonInstance3.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%NonInstance3.facet\n// CHECK:STDOUT:   %NonInstance3.WithSelf.F3.type => constants.%NonInstance3.WithSelf.F3.type.a3f\n// CHECK:STDOUT:   %NonInstance3.WithSelf.F3 => constants.%NonInstance3.WithSelf.F3.04b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @NonInstance3.WithSelf.F3(constants.%NonInstance3.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) {\n// CHECK:STDOUT:   %Dest => constants.%Dest\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%Dest, constants.%Self.738) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf.Convert(constants.%Dest, constants.%Self.738) {\n// CHECK:STDOUT:   %Dest => constants.%Dest\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.031\n// CHECK:STDOUT:   %Self => constants.%Self.738\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %pattern_type.1 => constants.%pattern_type.e9a\n// CHECK:STDOUT:   %.1 => constants.%.184\n// CHECK:STDOUT:   %pattern_type.2 => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs(constants.%NonInstance3.type) {\n// CHECK:STDOUT:   %Dest => constants.%NonInstance3.type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.deb\n// CHECK:STDOUT:   %Self => constants.%Self.9cf\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @ImplicitAs.WithSelf(constants.%NonInstance3.type, constants.%Self.738) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Dest => constants.%NonInstance3.type\n// CHECK:STDOUT:   %ImplicitAs.type => constants.%ImplicitAs.type.deb\n// CHECK:STDOUT:   %Self => constants.%Self.738\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type => constants.%ImplicitAs.WithSelf.Convert.type.8ec\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert => constants.%ImplicitAs.WithSelf.Convert.0e4\n// CHECK:STDOUT:   %ImplicitAs.assoc_type => constants.%ImplicitAs.assoc_type.eea\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.605\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- instance_success.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Instance1.type: type = facet_type <@Instance1> [concrete]\n// CHECK:STDOUT:   %Self: %Instance1.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic]\n// CHECK:STDOUT:   %pattern_type.97b: type = pattern_type %Self.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Instance1.WithSelf.G1.type.291: type = fn_type @Instance1.WithSelf.G1, @Instance1.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Instance1.WithSelf.G1.db7: %Instance1.WithSelf.G1.type.291 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Instance1.assoc_type: type = assoc_entity_type @Instance1 [concrete]\n// CHECK:STDOUT:   %assoc0: %Instance1.assoc_type = assoc_entity element0, @Instance1.WithSelf.%Instance1.WithSelf.G1.decl [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct_type.d: type = struct_type {.d: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %Instance1.impl_witness: <witness> = impl_witness @struct_type.d.as.Instance1.impl.%Instance1.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.515: type = pattern_type %struct_type.d [concrete]\n// CHECK:STDOUT:   %struct_type.d.as.Instance1.impl.G1.type: type = fn_type @struct_type.d.as.Instance1.impl.G1 [concrete]\n// CHECK:STDOUT:   %struct_type.d.as.Instance1.impl.G1: %struct_type.d.as.Instance1.impl.G1.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Instance1.facet: %Instance1.type = facet_value %struct_type.d, (%Instance1.impl_witness) [concrete]\n// CHECK:STDOUT:   %Instance1.WithSelf.G1.type.ba6: type = fn_type @Instance1.WithSelf.G1, @Instance1.WithSelf(%Instance1.facet) [concrete]\n// CHECK:STDOUT:   %Instance1.WithSelf.G1.ceb: %Instance1.WithSelf.G1.type.ba6 = struct_value () [concrete]\n// CHECK:STDOUT:   %InstanceCall.type: type = fn_type @InstanceCall [concrete]\n// CHECK:STDOUT:   %InstanceCall: %InstanceCall.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.276: type = fn_type_with_self_type %Instance1.WithSelf.G1.type.ba6, %Instance1.facet [concrete]\n// CHECK:STDOUT:   %ptr: type = ptr_type %struct_type.d [concrete]\n// CHECK:STDOUT:   %pattern_type.8d6: type = pattern_type %ptr [concrete]\n// CHECK:STDOUT:   %InstanceCallIndirect.type: type = fn_type @InstanceCallIndirect [concrete]\n// CHECK:STDOUT:   %InstanceCallIndirect: %InstanceCallIndirect.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.d = struct_value (%empty_tuple) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Instance1 = %Instance1.decl\n// CHECK:STDOUT:     .InstanceCall = %InstanceCall.decl\n// CHECK:STDOUT:     .InstanceCallIndirect = %InstanceCallIndirect.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Instance1.decl: type = interface_decl @Instance1 [concrete = constants.%Instance1.type] {} {}\n// CHECK:STDOUT:   impl_decl @struct_type.d.as.Instance1.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc7_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_12.2: type = converted %.loc7_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %struct_type.d: type = struct_type {.d: %empty_tuple.type} [concrete = constants.%struct_type.d]\n// CHECK:STDOUT:     %Instance1.ref: type = name_ref Instance1, file.%Instance1.decl [concrete = constants.%Instance1.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %InstanceCall.decl: %InstanceCall.type = fn_decl @InstanceCall [concrete = constants.%InstanceCall] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.515 = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.515 = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %n.param: %struct_type.d = value_param call_param0\n// CHECK:STDOUT:     %.loc11_27: type = splice_block %struct_type.d [concrete = constants.%struct_type.d] {\n// CHECK:STDOUT:       %.loc11_26.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc11_26.2: type = converted %.loc11_26.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %struct_type.d: type = struct_type {.d: %empty_tuple.type} [concrete = constants.%struct_type.d]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %n: %struct_type.d = value_binding n, %n.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %InstanceCallIndirect.decl: %InstanceCallIndirect.type = fn_decl @InstanceCallIndirect [concrete = constants.%InstanceCallIndirect] {\n// CHECK:STDOUT:     %p.patt: %pattern_type.8d6 = value_binding_pattern p [concrete]\n// CHECK:STDOUT:     %p.param_patt: %pattern_type.8d6 = value_param_pattern %p.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %p.param: %ptr = value_param call_param0\n// CHECK:STDOUT:     %.loc15_36: type = splice_block %ptr [concrete = constants.%ptr] {\n// CHECK:STDOUT:       %.loc15_34.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc15_34.2: type = converted %.loc15_34.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %struct_type.d: type = struct_type {.d: %empty_tuple.type} [concrete = constants.%struct_type.d]\n// CHECK:STDOUT:       %ptr: type = ptr_type %struct_type.d [concrete = constants.%ptr]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %p: %ptr = value_binding p, %p.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Instance1 {\n// CHECK:STDOUT:   %Self: %Instance1.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Instance1.WithSelf.decl = interface_with_self_decl @Instance1 [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %Instance1.WithSelf.G1.decl: @Instance1.WithSelf.%Instance1.WithSelf.G1.type (%Instance1.WithSelf.G1.type.291) = fn_decl @Instance1.WithSelf.G1 [symbolic = @Instance1.WithSelf.%Instance1.WithSelf.G1 (constants.%Instance1.WithSelf.G1.db7)] {\n// CHECK:STDOUT:     %self.patt: @Instance1.WithSelf.G1.%pattern_type (%pattern_type.97b) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: @Instance1.WithSelf.G1.%pattern_type (%pattern_type.97b) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: @Instance1.WithSelf.G1.%Self.binding.as_type (%Self.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_15.1: type = splice_block %.loc4_15.2 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)] {\n// CHECK:STDOUT:       %Self.ref: %Instance1.type = name_ref Self, @Instance1.%Self [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       %.loc4_15.2: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self: @Instance1.WithSelf.G1.%Self.binding.as_type (%Self.binding.as_type) = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %assoc0: %Instance1.assoc_type = assoc_entity element0, %Instance1.WithSelf.G1.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .G1 = @Instance1.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@Instance1.WithSelf.%Instance1.WithSelf.G1.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @struct_type.d.as.Instance1.impl: %struct_type.d as %Instance1.ref {\n// CHECK:STDOUT:   %struct_type.d.as.Instance1.impl.G1.decl: %struct_type.d.as.Instance1.impl.G1.type = fn_decl @struct_type.d.as.Instance1.impl.G1 [concrete = constants.%struct_type.d.as.Instance1.impl.G1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.515 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.515 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %struct_type.d = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @struct_type.d.as.Instance1.impl.%struct_type.d [concrete = constants.%struct_type.d]\n// CHECK:STDOUT:     %self: %struct_type.d = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Instance1.impl_witness_table = impl_witness_table (%struct_type.d.as.Instance1.impl.G1.decl), @struct_type.d.as.Instance1.impl [concrete]\n// CHECK:STDOUT:   %Instance1.impl_witness: <witness> = impl_witness %Instance1.impl_witness_table [concrete = constants.%Instance1.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .G1 = %struct_type.d.as.Instance1.impl.G1.decl\n// CHECK:STDOUT:   witness = %Instance1.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Instance1.WithSelf.G1(@Instance1.%Self: %Instance1.type) {\n// CHECK:STDOUT:   %Self: %Instance1.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.97b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @Instance1.WithSelf.G1.%Self.binding.as_type (%Self.binding.as_type));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @struct_type.d.as.Instance1.impl.G1(%self.param: %struct_type.d) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InstanceCall(%n.param: %struct_type.d) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %struct_type.d = name_ref n, %n\n// CHECK:STDOUT:   %Instance1.ref: type = name_ref Instance1, file.%Instance1.decl [concrete = constants.%Instance1.type]\n// CHECK:STDOUT:   %G1.ref: %Instance1.assoc_type = name_ref G1, @Instance1.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %impl.elem0: %.276 = impl_witness_access constants.%Instance1.impl_witness, element0 [concrete = constants.%struct_type.d.as.Instance1.impl.G1]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:   %struct_type.d.as.Instance1.impl.G1.call: init %empty_tuple.type = call %bound_method(%n.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InstanceCallIndirect(%p.param: %ptr) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %p.ref: %ptr = name_ref p, %p\n// CHECK:STDOUT:   %Instance1.ref: type = name_ref Instance1, file.%Instance1.decl [concrete = constants.%Instance1.type]\n// CHECK:STDOUT:   %G1.ref: %Instance1.assoc_type = name_ref G1, @Instance1.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %.loc16_4.1: ref %struct_type.d = deref %p.ref\n// CHECK:STDOUT:   %impl.elem0: %.276 = impl_witness_access constants.%Instance1.impl_witness, element0 [concrete = constants.%struct_type.d.as.Instance1.impl.G1]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %.loc16_4.1, %impl.elem0\n// CHECK:STDOUT:   %.loc16_4.2: ref %empty_tuple.type = struct_access %.loc16_4.1, element0\n// CHECK:STDOUT:   %tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc16_4.3: %empty_tuple.type = converted %.loc16_4.2, %tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %struct: %struct_type.d = struct_value (%.loc16_4.3) [concrete = constants.%struct]\n// CHECK:STDOUT:   %.loc16_4.4: %struct_type.d = converted %.loc16_4.1, %struct [concrete = constants.%struct]\n// CHECK:STDOUT:   %struct_type.d.as.Instance1.impl.G1.call: init %empty_tuple.type = call %bound_method(%.loc16_4.4)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Instance1.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Instance1.WithSelf.G1.type => constants.%Instance1.WithSelf.G1.type.291\n// CHECK:STDOUT:   %Instance1.WithSelf.G1 => constants.%Instance1.WithSelf.G1.db7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Instance1.WithSelf.G1(constants.%Self) {\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.97b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Instance1.WithSelf(constants.%Instance1.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Instance1.facet\n// CHECK:STDOUT:   %Instance1.WithSelf.G1.type => constants.%Instance1.WithSelf.G1.type.ba6\n// CHECK:STDOUT:   %Instance1.WithSelf.G1 => constants.%Instance1.WithSelf.G1.ceb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Instance1.WithSelf.G1(constants.%Instance1.facet) {\n// CHECK:STDOUT:   %Self => constants.%Instance1.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%struct_type.d\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.515\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_instance.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Instance2.type: type = facet_type <@Instance2> [concrete]\n// CHECK:STDOUT:   %Self: %Instance2.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic]\n// CHECK:STDOUT:   %pattern_type.a35: type = pattern_type %Self.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Instance2.WithSelf.G2.type.e15: type = fn_type @Instance2.WithSelf.G2, @Instance2.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Instance2.WithSelf.G2.6c8: %Instance2.WithSelf.G2.type.e15 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Instance2.assoc_type: type = assoc_entity_type @Instance2 [concrete]\n// CHECK:STDOUT:   %assoc0: %Instance2.assoc_type = assoc_entity element0, @Instance2.WithSelf.%Instance2.WithSelf.G2.decl [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %struct_type.e: type = struct_type {.e: %empty_tuple.type} [concrete]\n// CHECK:STDOUT:   %Instance2.impl_witness: <witness> = impl_witness @struct_type.e.as.Instance2.impl.%Instance2.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.efd: type = pattern_type %struct_type.e [concrete]\n// CHECK:STDOUT:   %struct_type.e.as.Instance2.impl.G2.type: type = fn_type @struct_type.e.as.Instance2.impl.G2 [concrete]\n// CHECK:STDOUT:   %struct_type.e.as.Instance2.impl.G2: %struct_type.e.as.Instance2.impl.G2.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Instance2.facet: %Instance2.type = facet_value %struct_type.e, (%Instance2.impl_witness) [concrete]\n// CHECK:STDOUT:   %Instance2.WithSelf.G2.type.008: type = fn_type @Instance2.WithSelf.G2, @Instance2.WithSelf(%Instance2.facet) [concrete]\n// CHECK:STDOUT:   %Instance2.WithSelf.G2.f23: %Instance2.WithSelf.G2.type.008 = struct_value () [concrete]\n// CHECK:STDOUT:   %InstanceCallFail.type: type = fn_type @InstanceCallFail [concrete]\n// CHECK:STDOUT:   %InstanceCallFail: %InstanceCallFail.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Instance2 = %Instance2.decl\n// CHECK:STDOUT:     .InstanceCallFail = %InstanceCallFail.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Instance2.decl: type = interface_decl @Instance2 [concrete = constants.%Instance2.type] {} {}\n// CHECK:STDOUT:   impl_decl @struct_type.e.as.Instance2.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc7_12.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_12.2: type = converted %.loc7_12.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %struct_type.e: type = struct_type {.e: %empty_tuple.type} [concrete = constants.%struct_type.e]\n// CHECK:STDOUT:     %Instance2.ref: type = name_ref Instance2, file.%Instance2.decl [concrete = constants.%Instance2.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %InstanceCallFail.decl: %InstanceCallFail.type = fn_decl @InstanceCallFail [concrete = constants.%InstanceCallFail] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Instance2 {\n// CHECK:STDOUT:   %Self: %Instance2.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Instance2.WithSelf.decl = interface_with_self_decl @Instance2 [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %Instance2.WithSelf.G2.decl: @Instance2.WithSelf.%Instance2.WithSelf.G2.type (%Instance2.WithSelf.G2.type.e15) = fn_decl @Instance2.WithSelf.G2 [symbolic = @Instance2.WithSelf.%Instance2.WithSelf.G2 (constants.%Instance2.WithSelf.G2.6c8)] {\n// CHECK:STDOUT:     %self.patt: @Instance2.WithSelf.G2.%pattern_type (%pattern_type.a35) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: @Instance2.WithSelf.G2.%pattern_type (%pattern_type.a35) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: @Instance2.WithSelf.G2.%Self.binding.as_type (%Self.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc4_15.1: type = splice_block %.loc4_15.2 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)] {\n// CHECK:STDOUT:       %Self.ref: %Instance2.type = name_ref Self, @Instance2.%Self [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       %.loc4_15.2: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self: @Instance2.WithSelf.G2.%Self.binding.as_type (%Self.binding.as_type) = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %assoc0: %Instance2.assoc_type = assoc_entity element0, %Instance2.WithSelf.G2.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .G2 = @Instance2.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@Instance2.WithSelf.%Instance2.WithSelf.G2.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @struct_type.e.as.Instance2.impl: %struct_type.e as %Instance2.ref {\n// CHECK:STDOUT:   %struct_type.e.as.Instance2.impl.G2.decl: %struct_type.e.as.Instance2.impl.G2.type = fn_decl @struct_type.e.as.Instance2.impl.G2 [concrete = constants.%struct_type.e.as.Instance2.impl.G2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.efd = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.efd = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %struct_type.e = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, @struct_type.e.as.Instance2.impl.%struct_type.e [concrete = constants.%struct_type.e]\n// CHECK:STDOUT:     %self: %struct_type.e = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Instance2.impl_witness_table = impl_witness_table (%struct_type.e.as.Instance2.impl.G2.decl), @struct_type.e.as.Instance2.impl [concrete]\n// CHECK:STDOUT:   %Instance2.impl_witness: <witness> = impl_witness %Instance2.impl_witness_table [concrete = constants.%Instance2.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .G2 = %struct_type.e.as.Instance2.impl.G2.decl\n// CHECK:STDOUT:   witness = %Instance2.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Instance2.WithSelf.G2(@Instance2.%Self: %Instance2.type) {\n// CHECK:STDOUT:   %Self: %Instance2.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.a35)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @Instance2.WithSelf.G2.%Self.binding.as_type (%Self.binding.as_type));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @struct_type.e.as.Instance2.impl.G2(%self.param: %struct_type.e) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InstanceCallFail() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc16_9.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc16_9.2: type = converted %.loc16_9.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   %struct_type.e: type = struct_type {.e: %empty_tuple.type} [concrete = constants.%struct_type.e]\n// CHECK:STDOUT:   %Instance2.ref: type = name_ref Instance2, file.%Instance2.decl [concrete = constants.%Instance2.type]\n// CHECK:STDOUT:   %G2.ref: %Instance2.assoc_type = name_ref G2, @Instance2.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Instance2.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Instance2.WithSelf.G2.type => constants.%Instance2.WithSelf.G2.type.e15\n// CHECK:STDOUT:   %Instance2.WithSelf.G2 => constants.%Instance2.WithSelf.G2.6c8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Instance2.WithSelf.G2(constants.%Self) {\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.a35\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Instance2.WithSelf(constants.%Instance2.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Instance2.facet\n// CHECK:STDOUT:   %Instance2.WithSelf.G2.type => constants.%Instance2.WithSelf.G2.type.008\n// CHECK:STDOUT:   %Instance2.WithSelf.G2 => constants.%Instance2.WithSelf.G2.f23\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Instance2.WithSelf.G2(constants.%Instance2.facet) {\n// CHECK:STDOUT:   %Self => constants.%Instance2.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%struct_type.e\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.efd\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/custom_witness/int_fits_in.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/custom_witness/int_fits_in.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/custom_witness/int_fits_in.carbon\n\n// --- core.carbon\n\npackage Core;\n\ninterface IntFitsIn(Dest:! type) {}\n\nfn CheckFitsIn[U:! type, T:! IntFitsIn(U)](unused t: T, unused u: U) {}\n\n// --- valid.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Core;\n\nfn CheckOk() {\n  Core.CheckFitsIn(1 as i32, 2 as i64);\n  Core.CheckFitsIn(1 as u32, 2 as u64);\n  Core.CheckFitsIn(1 as u32, 2 as i64);\n}\n\n// --- fail_narrowing.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Core;\n\nfn CheckFail() {\n  // CHECK:STDERR: fail_narrowing.carbon:[[@LINE+7]]:3: error: cannot convert type `i64` into type implementing `Core.IntFitsIn(i32)` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   Core.CheckFitsIn(1 as i64, 2 as i32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: core.carbon:6:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn CheckFitsIn[U:! type, T:! IntFitsIn(U)](unused t: T, unused u: U) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Core.CheckFitsIn(1 as i64, 2 as i32);\n  // CHECK:STDERR: fail_narrowing.carbon:[[@LINE+7]]:3: error: cannot convert type `i64` into type implementing `Core.IntFitsIn(u32)` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   Core.CheckFitsIn(1 as i64, 2 as u32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: core.carbon:6:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn CheckFitsIn[U:! type, T:! IntFitsIn(U)](unused t: T, unused u: U) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Core.CheckFitsIn(1 as i64, 2 as u32);\n  // CHECK:STDERR: fail_narrowing.carbon:[[@LINE+7]]:3: error: cannot convert type `u64` into type implementing `Core.IntFitsIn(i32)` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   Core.CheckFitsIn(1 as u64, 2 as i32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: core.carbon:6:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn CheckFitsIn[U:! type, T:! IntFitsIn(U)](unused t: T, unused u: U) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Core.CheckFitsIn(1 as u64, 2 as i32);\n  // CHECK:STDERR: fail_narrowing.carbon:[[@LINE+7]]:3: error: cannot convert type `u64` into type implementing `Core.IntFitsIn(u32)` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   Core.CheckFitsIn(1 as u64, 2 as u32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: core.carbon:6:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn CheckFitsIn[U:! type, T:! IntFitsIn(U)](unused t: T, unused u: U) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Core.CheckFitsIn(1 as u64, 2 as u32);\n}\n\n// --- fail_same_size_sign_change.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Core;\n\nfn CheckFail() {\n  // CHECK:STDERR: fail_same_size_sign_change.carbon:[[@LINE+7]]:3: error: cannot convert type `u32` into type implementing `Core.IntFitsIn(i32)` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   Core.CheckFitsIn(1 as u32, 2 as i32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: core.carbon:6:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn CheckFitsIn[U:! type, T:! IntFitsIn(U)](unused t: T, unused u: U) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Core.CheckFitsIn(1 as u32, 2 as i32);\n  // CHECK:STDERR: fail_same_size_sign_change.carbon:[[@LINE+7]]:3: error: cannot convert type `i32` into type implementing `Core.IntFitsIn(u32)` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   Core.CheckFitsIn(1 as i32, 2 as u32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: core.carbon:6:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn CheckFitsIn[U:! type, T:! IntFitsIn(U)](unused t: T, unused u: U) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Core.CheckFitsIn(1 as i32, 2 as u32);\n}\n\n// --- fail_signed_to_wider_unsigned.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport Core;\n\nfn CheckFail() {\n  // CHECK:STDERR: fail_signed_to_wider_unsigned.carbon:[[@LINE+7]]:3: error: cannot convert type `i32` into type implementing `Core.IntFitsIn(u32)` [ConversionFailureTypeToFacet]\n  // CHECK:STDERR:   Core.CheckFitsIn(1 as i32, 2 as u32);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: core.carbon:6:1: note: while deducing parameters of generic declared here [DeductionGenericHere]\n  // CHECK:STDERR: fn CheckFitsIn[U:! type, T:! IntFitsIn(U)](unused t: T, unused u: U) {}\n  // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  Core.CheckFitsIn(1 as i32, 2 as u32);\n}\n"
  },
  {
    "path": "toolchain/check/testdata/impl/declaration.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/declaration.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/declaration.carbon\n\ninterface I {}\n\nimpl i32 as I;\n\nimpl i32 as I {}\n\n// CHECK:STDOUT: --- declaration.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @i32.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %i32, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @i32.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %i32.loc17: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %I.ref.loc17: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @i32.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %i32.loc19: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %I.ref.loc19: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.as.I.impl: %i32.loc17 as %I.ref.loc17 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @i32.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/empty.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/empty.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/empty.carbon\n\ninterface Empty {\n}\n\nimpl i32 as Empty {\n}\n\n// CHECK:STDOUT: --- empty.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Empty.type: type = facet_type <@Empty> [concrete]\n// CHECK:STDOUT:   %Self: %Empty.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Empty.impl_witness: <witness> = impl_witness @i32.as.Empty.impl.%Empty.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Empty.facet: %Empty.type = facet_value %i32, (%Empty.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Empty = %Empty.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Empty.decl: type = interface_decl @Empty [concrete = constants.%Empty.type] {} {}\n// CHECK:STDOUT:   impl_decl @i32.as.Empty.impl [concrete] {} {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %Empty.ref: type = name_ref Empty, file.%Empty.decl [concrete = constants.%Empty.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Empty {\n// CHECK:STDOUT:   %Self: %Empty.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Empty.WithSelf.decl = interface_with_self_decl @Empty [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.as.Empty.impl: %i32 as %Empty.ref {\n// CHECK:STDOUT:   %Empty.impl_witness_table = impl_witness_table (), @i32.as.Empty.impl [concrete]\n// CHECK:STDOUT:   %Empty.impl_witness: <witness> = impl_witness %Empty.impl_witness_table [concrete = constants.%Empty.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Empty.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Empty.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Empty.WithSelf(constants.%Empty.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/error_recovery.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/error_recovery.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/error_recovery.carbon\n\n// --- fail_runtime_generic_param.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\ninterface I {}\n\n//@dump-sem-ir-begin\n// CHECK:STDERR: fail_runtime_generic_param.carbon:[[@LINE+4]]:14: error: parameters of generic types must be constant [GenericParamMustBeConstant]\n// CHECK:STDERR: impl forall [T: type] C as I {}\n// CHECK:STDERR:              ^~~~~~~\n// CHECK:STDERR:\nimpl forall [T: type] C as I {}\n//@dump-sem-ir-end\n\n// --- fail_nonfinal_lookup_impl_witness_error_in_import.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n// CHECK:STDERR: fail_nonfinal_lookup_impl_witness_error_in_import.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]\n// CHECK:STDERR: impl forall [T:! type] T as Z;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] T as Z;\n\nfn F(unused U:! Z) {}\n\n//@dump-sem-ir-begin\nfn G(T:! type) {\n  // This makes a LookupImplWitness instruction, but future lookups (evaluation\n  // of this instruction with a specific) will result in an error since the impl\n  // is never defined and is left with an error as its witness at the end of the\n  // file. The lookups should not fail entirely, just result in an error\n  // witness.\n  F(T);\n}\n//@dump-sem-ir-end\n\n// --- nonfinal_lookup_impl_witness_error_in_import.impl.carbon\nimpl library \"[[@TEST_NAME]]\";\n\nfn H() {\n  // The specific here contains errors, but does not fail entirely and crash\n  // when resolving the LookupImplWitness.\n  G(());\n}\n\n// --- fail_nonfinal_lookup_impl_witness_error.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n// CHECK:STDERR: fail_nonfinal_lookup_impl_witness_error.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]\n// CHECK:STDERR: impl forall [T:! type] T as Z;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] T as Z;\n\nfn F(unused U:! Z) {}\n\n//@dump-sem-ir-begin\nfn G(T:! type) {\n  // This makes a LookupImplWitness instruction, but future lookups (evaluation\n  // of this instruction with a specific) will fail with an error since the impl\n  // is never defined and is left with an error as its witness at the end of the\n  // file. The lookups should not fail entirely, just result in an error\n  // witness.\n  F(T);\n}\n//@dump-sem-ir-end\n\nfn H() {\n  // The specific here contains errors, but does not fail entirely and crash\n  // when resolving the LookupImplWitness.\n  G(());\n}\n\n// --- fail_final_lookup_impl_witness_error.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n// CHECK:STDERR: fail_final_lookup_impl_witness_error.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]\n// CHECK:STDERR: impl forall [T:! type] T as Z;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] T as Z;\n\nfn F(unused U:! Z) {}\n\nfn G() {\n  // This impl lookup resolves to a final witness, which poisons any future\n  // queries. At the end of the file, the poisoned queries are replayed to make\n  // sure they don't change. However, here it is changed by the impl being\n  // diagnosed with an error. The poisoning check should handle that gracefully.\n  //@dump-sem-ir-begin\n  F(());\n  //@dump-sem-ir-end\n}\n\n// --- fail_invalid_fn_syntax_in_impl.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  fn Op[self: Self]();\n}\n\nclass C {};\n//@dump-sem-ir-begin\nimpl C as I {\n  // This leaves the impl with a placeholder instruction in the witness table.\n  // CHECK:STDERR: fail_invalid_fn_syntax_in_impl.carbon:[[@LINE+8]]:11: error: expected `:`, `:!`, or `:?` in binding pattern [ExpectedBindingPattern]\n  // CHECK:STDERR:   fn Op[x self: C]() {}\n  // CHECK:STDERR:           ^~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_invalid_fn_syntax_in_impl.carbon:[[@LINE+4]]:11: error: semantics TODO: `handle invalid parse trees in `check`` [SemanticsTodo]\n  // CHECK:STDERR:   fn Op[x self: C]() {}\n  // CHECK:STDERR:           ^~~~\n  // CHECK:STDERR:\n  fn Op[x self: C]() {}\n}\n//@dump-sem-ir-end\n\n// CHECK:STDOUT: --- fail_runtime_generic_param.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %I.ref {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_nonfinal_lookup_impl_witness_error_in_import.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.242: require_specific_def_type = require_specific_def @T.as.Z.impl(%T) [symbolic]\n// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Z [symbolic]\n// CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %T, (%Z.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%Z.facet) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc13_10.1: type = splice_block %.loc13_10.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc13_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc13_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%T.loc13_6.2: type) {\n// CHECK:STDOUT:   %T.loc13_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %.loc19_6.2: require_specific_def_type = require_specific_def @T.as.Z.impl(%T.loc13_6.1) [symbolic = %.loc19_6.2 (constants.%.242)]\n// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc13_6.1, @Z [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness)]\n// CHECK:STDOUT:   %Z.facet.loc19_6.2: %Z.type = facet_value %T.loc13_6.1, (%Z.lookup_impl_witness) [symbolic = %Z.facet.loc19_6.2 (constants.%Z.facet)]\n// CHECK:STDOUT:   %F.specific_fn.loc19_3.2: <specific function> = specific_function constants.%F, @F(%Z.facet.loc19_6.2) [symbolic = %F.specific_fn.loc19_3.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc13_6.2 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:     %Z.facet.loc19_6.1: %Z.type = facet_value %T.ref, (constants.%Z.lookup_impl_witness) [symbolic = %Z.facet.loc19_6.2 (constants.%Z.facet)]\n// CHECK:STDOUT:     %.loc19_6.1: %Z.type = converted %T.ref, %Z.facet.loc19_6.1 [symbolic = %Z.facet.loc19_6.2 (constants.%Z.facet)]\n// CHECK:STDOUT:     %F.specific_fn.loc19_3.1: <specific function> = specific_function %F.ref, @F(constants.%Z.facet) [symbolic = %F.specific_fn.loc19_3.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:     %F.call: init %empty_tuple.type = call %F.specific_fn.loc19_3.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%T) {\n// CHECK:STDOUT:   %T.loc13_6.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_nonfinal_lookup_impl_witness_error.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.242: require_specific_def_type = require_specific_def @T.as.Z.impl(%T) [symbolic]\n// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %T, @Z [symbolic]\n// CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %T, (%Z.lookup_impl_witness) [symbolic]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%Z.facet) [symbolic]\n// CHECK:STDOUT:   %.194: require_specific_def_type = require_specific_def @T.as.Z.impl(%empty_tuple.type) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc13_10.1: type = splice_block %.loc13_10.2 [concrete = type] {\n// CHECK:STDOUT:       <elided>\n// CHECK:STDOUT:       %.loc13_10.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc13_6.2: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%T.loc13_6.2: type) {\n// CHECK:STDOUT:   %T.loc13_6.1: type = symbolic_binding T, 0 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %.loc19_6.2: require_specific_def_type = require_specific_def @T.as.Z.impl(%T.loc13_6.1) [symbolic = %.loc19_6.2 (constants.%.242)]\n// CHECK:STDOUT:   %Z.lookup_impl_witness: <witness> = lookup_impl_witness %T.loc13_6.1, @Z [symbolic = %Z.lookup_impl_witness (constants.%Z.lookup_impl_witness)]\n// CHECK:STDOUT:   %Z.facet.loc19_6.2: %Z.type = facet_value %T.loc13_6.1, (%Z.lookup_impl_witness) [symbolic = %Z.facet.loc19_6.2 (constants.%Z.facet)]\n// CHECK:STDOUT:   %F.specific_fn.loc19_3.2: <specific function> = specific_function constants.%F, @F(%Z.facet.loc19_6.2) [symbolic = %F.specific_fn.loc19_3.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc13_6.2 [symbolic = %T.loc13_6.1 (constants.%T)]\n// CHECK:STDOUT:     %Z.facet.loc19_6.1: %Z.type = facet_value %T.ref, (constants.%Z.lookup_impl_witness) [symbolic = %Z.facet.loc19_6.2 (constants.%Z.facet)]\n// CHECK:STDOUT:     %.loc19_6.1: %Z.type = converted %T.ref, %Z.facet.loc19_6.1 [symbolic = %Z.facet.loc19_6.2 (constants.%Z.facet)]\n// CHECK:STDOUT:     %F.specific_fn.loc19_3.1: <specific function> = specific_function %F.ref, @F(constants.%Z.facet) [symbolic = %F.specific_fn.loc19_3.2 (constants.%F.specific_fn)]\n// CHECK:STDOUT:     %F.call: init %empty_tuple.type = call %F.specific_fn.loc19_3.1()\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%T) {\n// CHECK:STDOUT:   %T.loc13_6.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%empty_tuple.type) {\n// CHECK:STDOUT:   %T.loc13_6.1 => constants.%empty_tuple.type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %.loc19_6.2 => constants.%.194\n// CHECK:STDOUT:   %Z.lookup_impl_witness => <error>\n// CHECK:STDOUT:   %Z.facet.loc19_6.2 => <error>\n// CHECK:STDOUT:   %F.specific_fn.loc19_3.2 => <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_final_lookup_impl_witness_error.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %Z.impl_witness.db1: <witness> = impl_witness @T.as.Z.impl.%Z.impl_witness_table, @T.as.Z.impl(%empty_tuple.type) [concrete]\n// CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %empty_tuple.type, (%Z.impl_witness.db1) [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%Z.facet) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]\n// CHECK:STDOUT:   %.loc18_6: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %Z.facet: %Z.type = facet_value constants.%empty_tuple.type, (constants.%Z.impl_witness.db1) [concrete = constants.%Z.facet]\n// CHECK:STDOUT:   %.loc18_7: %Z.type = converted %.loc18_6, %Z.facet [concrete = constants.%Z.facet]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%Z.facet) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn()\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_invalid_fn_syntax_in_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @<null name>: <unexpected>.inst{{[0-9A-F]+}}.loc9_6 as <unexpected>.inst{{[0-9A-F]+}}.loc9_11;\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/eval_musteval.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/eval_musteval.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/eval_musteval.carbon\n\n// --- interface.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Runtime {\n  fn F[self: Self]() -> type;\n}\n\ninterface Eval {\n  eval fn F[self: Self]() -> type;\n}\n\ninterface MustEval {\n  musteval fn F[self: Self]() -> type;\n}\n\n// --- impl_runtime.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"interface\";\n\nclass A { adapt {}; }\n\nimpl A as Runtime {\n  fn F[unused self: Self]() -> type { return A; }\n}\n\nimpl A as Eval {\n  // TODO: Consider rejecting this, as compile-time evaluation would always\n  // fail.\n  fn F[unused self: Self]() -> type { return A; }\n}\n\nimpl A as MustEval {\n  // TODO: Consider rejecting this, as compile-time evaluation would always\n  // fail.\n  fn F[unused self: Self]() -> type { return A; }\n}\n\nfn Call() {\n  ({} as A).(Runtime.F)();\n  ({} as A).(Eval.F)();\n  ({} as A).(MustEval.F)();\n}\n\n// --- fail_impl_runtime_eval.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"interface\";\n\nclass A { adapt {}; }\n\nimpl A as Runtime {\n  fn F[unused self: Self]() -> type { return A; }\n}\n\nimpl A as Eval {\n  fn F[unused self: Self]() -> type { return A; }\n}\n\nimpl A as MustEval {\n  fn F[unused self: Self]() -> type { return A; }\n}\n\nfn Call() {\n  // CHECK:STDERR: fail_impl_runtime_eval.carbon:[[@LINE+4]]:17: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   let unused t: ({} as A).(Runtime.F)() = {} as A;\n  // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused t: ({} as A).(Runtime.F)() = {} as A;\n  // CHECK:STDERR: fail_impl_runtime_eval.carbon:[[@LINE+4]]:17: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   let unused u: ({} as A).(Eval.F)() = {} as A;\n  // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused u: ({} as A).(Eval.F)() = {} as A;\n  // CHECK:STDERR: fail_impl_runtime_eval.carbon:[[@LINE+4]]:17: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   let unused v: ({} as A).(MustEval.F)() = {} as A;\n  // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused v: ({} as A).(MustEval.F)() = {} as A;\n}\n\n// --- impl_eval.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"interface\";\n\nclass A { adapt {}; }\n\nimpl A as Runtime {\n  eval fn F[unused self: Self]() -> type { return A; }\n}\n\nimpl A as Eval {\n  eval fn F[unused self: Self]() -> type { return A; }\n}\n\nimpl A as MustEval {\n  eval fn F[unused self: Self]() -> type { return A; }\n}\n\nfn Call() {\n  // TODO: Should we allow calling this at compile time? This is not allowed if\n  // we generate a thunk; see the next split for an example.\n  let unused t: ({} as A).(Runtime.F)() = {} as A;\n  let unused u: ({} as A).(Eval.F)() = {} as A;\n  let unused v: ({} as A).(MustEval.F)() = {} as A;\n}\n\n// --- fail_todo_impl_eval_from_runtime_thunk.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"interface\";\n\nclass B {}\n\nclass BView {}\nimpl B as Core.ImplicitAs(BView) {\n  fn Convert[unused self: Self]() -> BView { return {}; }\n}\n\nimpl B as Runtime {\n  eval fn F[unused self: BView]() -> type { return B; }\n}\n\nfn Call() {\n  // TODO: Should we allow calling this at compile time? This is allowed if we\n  // don't generate a thunk.\n  // CHECK:STDERR: fail_todo_impl_eval_from_runtime_thunk.carbon:[[@LINE+4]]:17: error: cannot evaluate type expression [TypeExprEvaluationFailure]\n  // CHECK:STDERR:   let unused t: ({} as B).(Runtime.F)() = {} as B;\n  // CHECK:STDERR:                 ^~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  let unused t: ({} as B).(Runtime.F)() = {} as B;\n}\n\n// --- fail_impl_musteval.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"interface\";\n\nclass B { adapt {}; }\n\nimpl B as Runtime {\n  // CHECK:STDERR: fail_impl_musteval.carbon:[[@LINE+11]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   musteval fn F[unused self: Self]() -> type { return B; }\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_impl_musteval.carbon:[[@LINE+8]]:3: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR:   musteval fn F[unused self: Self]() -> type { return B; }\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_impl_musteval.carbon:[[@LINE-11]]:1: in import [InImport]\n  // CHECK:STDERR: interface.carbon:5:3: note: while building thunk to match the signature of this function [ThunkSignature]\n  // CHECK:STDERR:   fn F[self: Self]() -> type;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  musteval fn F[unused self: Self]() -> type { return B; }\n}\n\nimpl B as Eval {\n  // CHECK:STDERR: fail_impl_musteval.carbon:[[@LINE+11]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   musteval fn F[unused self: Self]() -> type { return B; }\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_impl_musteval.carbon:[[@LINE+8]]:3: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR:   musteval fn F[unused self: Self]() -> type { return B; }\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_impl_musteval.carbon:[[@LINE-26]]:1: in import [InImport]\n  // CHECK:STDERR: interface.carbon:9:3: note: while building thunk to match the signature of this function [ThunkSignature]\n  // CHECK:STDERR:   eval fn F[self: Self]() -> type;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  musteval fn F[unused self: Self]() -> type { return B; }\n}\n\n// --- impl_musteval_from_musteval.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"interface\";\n\nclass B { adapt {}; }\n\nimpl B as MustEval {\n  musteval fn F[unused self: Self]() -> type { return B; }\n}\n\nfn Call() {\n  let unused t: ({} as B).(MustEval.F)() = {} as B;\n}\n\n// --- fail_todo_impl_musteval_from_musteval_thunk.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"interface\";\n\nclass B {}\n\nclass BView {}\nimpl B as Core.ImplicitAs(BView) {\n  fn Convert[unused self: Self]() -> BView { return {}; }\n}\n\nimpl B as MustEval {\n  // CHECK:STDERR: fail_todo_impl_musteval_from_musteval_thunk.carbon:[[@LINE+11]]:3: error: non-constant call to compile-time-only function [NonConstantCallToCompTimeOnlyFunction]\n  // CHECK:STDERR:   musteval fn F[unused self: BView]() -> type { return B; }\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_impl_musteval_from_musteval_thunk.carbon:[[@LINE+8]]:3: note: compile-time-only function declared here [CompTimeOnlyFunctionHere]\n  // CHECK:STDERR:   musteval fn F[unused self: BView]() -> type { return B; }\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_impl_musteval_from_musteval_thunk.carbon:[[@LINE-16]]:1: in import [InImport]\n  // CHECK:STDERR: interface.carbon:13:3: note: while building thunk to match the signature of this function [ThunkSignature]\n  // CHECK:STDERR:   musteval fn F[self: Self]() -> type;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  musteval fn F[unused self: BView]() -> type { return B; }\n}\n"
  },
  {
    "path": "toolchain/check/testdata/impl/extend_final.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/extend_final.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/extend_final.carbon\n\n// --- extend_final_impl.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  let X:! type;\n}\n\nclass C {\n  extend final impl as Z where .X = () {}\n}\n\nfn F() {\n  let unused b: C.X = ();\n}\n\n// --- fail_final_extend_impl.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\nclass C {\n  // CHECK:STDERR: fail_final_extend_impl.carbon:[[@LINE+7]]:9: error: `extend` must appear before `final` [ModifierMustAppearBefore]\n  // CHECK:STDERR:   final extend impl as Z {}\n  // CHECK:STDERR:         ^~~~~~\n  // CHECK:STDERR: fail_final_extend_impl.carbon:[[@LINE+4]]:3: note: `final` previously appeared here [ModifierPrevious]\n  // CHECK:STDERR:   final extend impl as Z {}\n  // CHECK:STDERR:   ^~~~~\n  // CHECK:STDERR:\n  final extend impl as Z {}\n}\n\n// --- fail_final_extend_impl_outside_class.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {}\n\nclass C {}\n\n// CHECK:STDERR: fail_final_extend_impl_outside_class.carbon:[[@LINE+4]]:1: error: `extend impl` can only be used in an interface or class [ExtendImplOutsideClass]\n// CHECK:STDERR: extend final impl C as Z {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextend final impl C as Z {}\n"
  },
  {
    "path": "toolchain/check/testdata/impl/extend_impl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/extend_impl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/extend_impl.carbon\n\n// --- extend_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface HasF {\n  fn F();\n}\n\n//@dump-sem-ir-begin\nclass C {\n  extend impl as HasF {\n    fn F() {}\n  }\n}\n//@dump-sem-ir-end\n\nfn G(c: C) {\n  C.F();\n  c.F();\n}\n\n// --- fail_extend_impl_nonexistent.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\nclass C {\n  // CHECK:STDERR: fail_extend_impl_nonexistent.carbon:[[@LINE+4]]:15: error: name `nonexistent` not found [NameNotFound]\n  // CHECK:STDERR:   extend impl nonexistent as I {}\n  // CHECK:STDERR:               ^~~~~~~~~~~\n  // CHECK:STDERR:\n  extend impl nonexistent as I {}\n\n  fn F() {\n    // The erroneous self-type for an `extend` causes the error to be propagated\n    // into the class scope, which prevents errors if we fail to find a name\n    // in that scope.\n    Self.A;\n  }\n}\n\n// --- fail_impl_nonexistent.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\nclass C {\n  // CHECK:STDERR: fail_impl_nonexistent.carbon:[[@LINE+4]]:8: error: name `nonexistent` not found [NameNotFound]\n  // CHECK:STDERR:   impl nonexistent as I {}\n  // CHECK:STDERR:        ^~~~~~~~~~~\n  // CHECK:STDERR:\n  impl nonexistent as I {}\n\n  fn F() {\n    // The name lookup error still happens, since the `require` is not `extend`.\n    // CHECK:STDERR: fail_impl_nonexistent.carbon:[[@LINE+4]]:5: error: member name `A` not found in `C` [MemberNameNotFoundInInstScope]\n    // CHECK:STDERR:     Self.A;\n    // CHECK:STDERR:     ^~~~~~\n    // CHECK:STDERR:\n    Self.A;\n  }\n}\n\n// --- fail_extend_impl_nonexistent_pointer.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\nclass C {\n  // CHECK:STDERR: fail_extend_impl_nonexistent_pointer.carbon:[[@LINE+4]]:15: error: name `nonexistent` not found [NameNotFound]\n  // CHECK:STDERR:   extend impl nonexistent* as I {}\n  // CHECK:STDERR:               ^~~~~~~~~~~\n  // CHECK:STDERR:\n  extend impl nonexistent* as I {}\n\n  fn F() {\n    // The erroneous self-type for an `extend` causes the error to be propagated\n    // into the class scope, which prevents errors if we fail to find a name\n    // in that scope.\n    Self.A;\n  }\n}\n\n// --- fail_extend_impl_nonexistent_outside_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n// CHECK:STDERR: fail_extend_impl_nonexistent_outside_class.carbon:[[@LINE+4]]:13: error: name `nonexistent` not found [NameNotFound]\n// CHECK:STDERR: extend impl nonexistent* as I {}\n// CHECK:STDERR:             ^~~~~~~~~~~\n// CHECK:STDERR:\nextend impl nonexistent* as I {}\n\n// CHECK:STDOUT: --- extend_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %HasF.type: type = facet_type <@HasF> [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %HasF.impl_witness: <witness> = impl_witness @C.as.HasF.impl.%HasF.impl_witness_table [concrete]\n// CHECK:STDOUT:   %C.as.HasF.impl.F.type: type = fn_type @C.as.HasF.impl.F [concrete]\n// CHECK:STDOUT:   %C.as.HasF.impl.F: %C.as.HasF.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.HasF.impl: %Self.ref as %HasF.ref {\n// CHECK:STDOUT:   %C.as.HasF.impl.F.decl: %C.as.HasF.impl.F.type = fn_decl @C.as.HasF.impl.F [concrete = constants.%C.as.HasF.impl.F] {} {}\n// CHECK:STDOUT:   %HasF.impl_witness_table = impl_witness_table (%C.as.HasF.impl.F.decl), @C.as.HasF.impl [concrete]\n// CHECK:STDOUT:   %HasF.impl_witness: <witness> = impl_witness %HasF.impl_witness_table [concrete = constants.%HasF.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %C.as.HasF.impl.F.decl\n// CHECK:STDOUT:   witness = %HasF.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   impl_decl @C.as.HasF.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %HasF.ref: type = name_ref HasF, file.%HasF.decl [concrete = constants.%HasF.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .HasF = <poisoned>\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend @C.as.HasF.impl.%HasF.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.HasF.impl.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/extend_impl_generic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/extend_impl_generic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/extend_impl_generic.carbon\n\n// --- extend_impl_generic_interface.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface HasF(T:! type) {\n  fn F() -> T;\n}\n\nclass Param {\n  var x: i32;\n}\n\nclass C {\n  extend impl as HasF(Param) {\n    fn F() -> Param {\n      return {.x = 2};\n    }\n  }\n}\n\nfn G(c: C) {\n  let unused a: i32 = C.F().x;\n  var unused b: i32 = c.F().x;\n}\n\n// --- extend_impl_generic_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {\n  fn F[self: Self](t: T);\n}\n\nclass X(U:! type) {\n  extend impl as I(U) {\n    fn F[unused self: Self](unused t: U) { }\n  }\n}\n\n// CHECK:STDOUT: --- extend_impl_generic_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T.67d: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %HasF.type.ee1: type = generic_interface_type @HasF [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %HasF.generic: %HasF.type.ee1 = struct_value () [concrete]\n// CHECK:STDOUT:   %HasF.type.8a4: type = facet_type <@HasF, @HasF(%T.67d)> [symbolic]\n// CHECK:STDOUT:   %Self.c1f: %HasF.type.8a4 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %.184347.1: Core.Form = init_form %T.67d [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d1c4.1: type = pattern_type %T.67d [symbolic]\n// CHECK:STDOUT:   %HasF.WithSelf.F.type.246: type = fn_type @HasF.WithSelf.F, @HasF.WithSelf(%T.67d, %Self.c1f) [symbolic]\n// CHECK:STDOUT:   %HasF.WithSelf.F.58b: %HasF.WithSelf.F.type.246 = struct_value () [symbolic]\n// CHECK:STDOUT:   %HasF.assoc_type.196: type = assoc_entity_type @HasF, @HasF(%T.67d) [symbolic]\n// CHECK:STDOUT:   %assoc0.b54: %HasF.assoc_type.196 = assoc_entity element0, @HasF.WithSelf.%HasF.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %Param: type = class_type @Param [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %N: Core.IntLiteral = symbolic_binding N, 0 [symbolic]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Param.elem: type = unbound_element_type %Param, %i32 [concrete]\n// CHECK:STDOUT:   %struct_type.x.ed6: type = struct_type {.x: %i32} [concrete]\n// CHECK:STDOUT:   %complete_type.1ec: <witness> = complete_type_witness %struct_type.x.ed6 [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %HasF.type.a3d: type = facet_type <@HasF, @HasF(%Param)> [concrete]\n// CHECK:STDOUT:   %HasF.impl_witness: <witness> = impl_witness @C.as.HasF.impl.%HasF.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.5e8: %HasF.type.a3d = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %HasF.WithSelf.F.type.a94: type = fn_type @HasF.WithSelf.F, @HasF.WithSelf(%Param, %Self.c1f) [symbolic]\n// CHECK:STDOUT:   %HasF.WithSelf.F.1c0: %HasF.WithSelf.F.type.a94 = struct_value () [symbolic]\n// CHECK:STDOUT:   %HasF.assoc_type.078: type = assoc_entity_type @HasF, @HasF(%Param) [concrete]\n// CHECK:STDOUT:   %assoc0.22c: %HasF.assoc_type.078 = assoc_entity element0, @HasF.WithSelf.%HasF.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %.436: Core.Form = init_form %Param [concrete]\n// CHECK:STDOUT:   %pattern_type.9ea: type = pattern_type %Param [concrete]\n// CHECK:STDOUT:   %C.as.HasF.impl.F.type: type = fn_type @C.as.HasF.impl.F [concrete]\n// CHECK:STDOUT:   %C.as.HasF.impl.F: %C.as.HasF.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %HasF.facet: %HasF.type.a3d = facet_value %C, (%HasF.impl_witness) [concrete]\n// CHECK:STDOUT:   %HasF.WithSelf.F.type.a36: type = fn_type @HasF.WithSelf.F, @HasF.WithSelf(%Param, %HasF.facet) [concrete]\n// CHECK:STDOUT:   %HasF.WithSelf.F.753: %HasF.WithSelf.F.type.a36 = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %struct_type.x.c96: type = struct_type {.x: Core.IntLiteral} [concrete]\n// CHECK:STDOUT:   %struct: %struct_type.x.c96 = struct_value (%int_2.ecc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %Param.val: %Param = struct_value (%int_2.ef8) [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]\n// CHECK:STDOUT:   %HasF.WithSelf.F.type.70d: type = fn_type @HasF.WithSelf.F, @HasF.WithSelf(%Param, %C.type.facet) [concrete]\n// CHECK:STDOUT:   %HasF.WithSelf.F.489: %HasF.WithSelf.F.type.70d = struct_value () [concrete]\n// CHECK:STDOUT:   %.095: type = fn_type_with_self_type %HasF.WithSelf.F.type.a36, %HasF.facet [concrete]\n// CHECK:STDOUT:   %Copy.type: type = facet_type <@Copy> [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.9b9: %Int.as.Copy.impl.Op.type.824 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Copy.impl_witness.f17: <witness> = impl_witness imports.%Copy.impl_witness_table.e76, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.type.546: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.664: %Int.as.Copy.impl.Op.type.546 = struct_value () [concrete]\n// CHECK:STDOUT:   %Copy.facet: %Copy.type = facet_value %i32, (%Copy.impl_witness.f17) [concrete]\n// CHECK:STDOUT:   %Copy.WithSelf.Op.type.081: type = fn_type @Copy.WithSelf.Op, @Copy.WithSelf(%Copy.facet) [concrete]\n// CHECK:STDOUT:   %.8e2: type = fn_type_with_self_type %Copy.WithSelf.Op.type.081, %Copy.facet [concrete]\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.specific_fn: <specific function> = specific_function %Int.as.Copy.impl.Op.664, @Int.as.Copy.impl.Op(%int_32) [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.1: type = fn_type @Destroy.Op.loc22_27 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.1: %Destroy.Op.type.bae255.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc22_3 [concrete]\n// CHECK:STDOUT:   %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Copy = %Core.Copy\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.Copy: type = import_ref Core//prelude/parts/copy, Copy, loaded [concrete = constants.%Copy.type]\n// CHECK:STDOUT:   %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)]\n// CHECK:STDOUT:   %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete]\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .HasF = %HasF.decl\n// CHECK:STDOUT:     .Param = %Param.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %HasF.decl: %HasF.type.ee1 = interface_decl @HasF [concrete = constants.%HasF.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_20.1: type = splice_block %.loc4_20.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_20.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_16.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_16.1 (constants.%T.67d)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Param.decl: type = class_decl @Param [concrete = constants.%Param] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.7c7 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc20: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @HasF(%T.loc4_16.2: type) {\n// CHECK:STDOUT:   %T.loc4_16.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_16.1 (constants.%T.67d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %HasF.type: type = facet_type <@HasF, @HasF(%T.loc4_16.1)> [symbolic = %HasF.type (constants.%HasF.type.8a4)]\n// CHECK:STDOUT:   %Self.loc4_26.2: @HasF.%HasF.type (%HasF.type.8a4) = symbolic_binding Self, 1 [symbolic = %Self.loc4_26.2 (constants.%Self.c1f)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc4_26.1: @HasF.%HasF.type (%HasF.type.8a4) = symbolic_binding Self, 1 [symbolic = %Self.loc4_26.2 (constants.%Self.c1f)]\n// CHECK:STDOUT:     %HasF.WithSelf.decl = interface_with_self_decl @HasF [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %HasF.WithSelf.F.decl: @HasF.WithSelf.%HasF.WithSelf.F.type (%HasF.WithSelf.F.type.246) = fn_decl @HasF.WithSelf.F [symbolic = @HasF.WithSelf.%HasF.WithSelf.F (constants.%HasF.WithSelf.F.58b)] {\n// CHECK:STDOUT:       %return.patt: @HasF.WithSelf.F.%pattern_type (%pattern_type.51d1c4.1) = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: @HasF.WithSelf.F.%pattern_type (%pattern_type.51d1c4.1) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @HasF.%T.loc4_16.2 [symbolic = %T (constants.%T.67d)]\n// CHECK:STDOUT:       %.loc5_13.2: Core.Form = init_form %T.ref [symbolic = %.loc5_13.1 (constants.%.184347.1)]\n// CHECK:STDOUT:       %return.param: ref @HasF.WithSelf.F.%T (%T.67d) = out_param call_param0\n// CHECK:STDOUT:       %return: ref @HasF.WithSelf.F.%T (%T.67d) = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %assoc0.loc5_14.1: @HasF.WithSelf.%HasF.assoc_type (%HasF.assoc_type.196) = assoc_entity element0, %HasF.WithSelf.F.decl [symbolic = %assoc0.loc5_14.2 (constants.%assoc0.b54)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc4_26.1\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = @HasF.WithSelf.%assoc0.loc5_14.1\n// CHECK:STDOUT:     .Param = <poisoned>\n// CHECK:STDOUT:     witness = (@HasF.WithSelf.%HasF.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.HasF.impl: %Self.ref as %HasF.type {\n// CHECK:STDOUT:   %C.as.HasF.impl.F.decl: %C.as.HasF.impl.F.type = fn_decl @C.as.HasF.impl.F [concrete = constants.%C.as.HasF.impl.F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.9ea = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.9ea = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Param.ref: type = name_ref Param, file.%Param.decl [concrete = constants.%Param]\n// CHECK:STDOUT:     %.loc14: Core.Form = init_form %Param.ref [concrete = constants.%.436]\n// CHECK:STDOUT:     %return.param: ref %Param = out_param call_param0\n// CHECK:STDOUT:     %return: ref %Param = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %HasF.impl_witness_table = impl_witness_table (%C.as.HasF.impl.F.decl), @C.as.HasF.impl [concrete]\n// CHECK:STDOUT:   %HasF.impl_witness: <witness> = impl_witness %HasF.impl_witness_table [concrete = constants.%HasF.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Param = <poisoned>\n// CHECK:STDOUT:   .F = %C.as.HasF.impl.F.decl\n// CHECK:STDOUT:   witness = %HasF.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Param {\n// CHECK:STDOUT:   %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc9: %Param.elem = field_decl x, element0 [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%struct_type.x.ed6 [concrete = constants.%complete_type.1ec]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Param\n// CHECK:STDOUT:   .x = %.loc9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   impl_decl @C.as.HasF.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %HasF.ref: %HasF.type.ee1 = name_ref HasF, file.%HasF.decl [concrete = constants.%HasF.generic]\n// CHECK:STDOUT:     %Param.ref: type = name_ref Param, file.%Param.decl [concrete = constants.%Param]\n// CHECK:STDOUT:     %HasF.type: type = facet_type <@HasF, @HasF(constants.%Param)> [concrete = constants.%HasF.type.a3d]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .HasF = <poisoned>\n// CHECK:STDOUT:   .Param = <poisoned>\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend @C.as.HasF.impl.%HasF.type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @HasF.WithSelf.F(@HasF.%T.loc4_16.2: type, @HasF.%Self.loc4_26.1: @HasF.%HasF.type (%HasF.type.8a4)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T.67d)]\n// CHECK:STDOUT:   %.loc5_13.1: Core.Form = init_form %T [symbolic = %.loc5_13.1 (constants.%.184347.1)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T [symbolic = %pattern_type (constants.%pattern_type.51d1c4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: @HasF.WithSelf.F.%T (%T.67d);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.HasF.impl.F() -> out %return.param: %Param {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %.loc15_21.1: %struct_type.x.c96 = struct_literal (%int_2) [concrete = constants.%struct]\n// CHECK:STDOUT:   %impl.elem0: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc15_21.1: <bound method> = bound_method %int_2, %impl.elem0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound]\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc15_21.2: <bound method> = bound_method %int_2, %specific_fn [concrete = constants.%bound_method]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call: init %i32 = call %bound_method.loc15_21.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc15_21.2: init %i32 = converted %int_2, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc15_21.3: ref %i32 = class_element_access %return.param, element0\n// CHECK:STDOUT:   %.loc15_21.4: init %i32 to %.loc15_21.3 = in_place_init %.loc15_21.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc15_21.5: init %Param to %return.param = class_init (%.loc15_21.4) [concrete = constants.%Param.val]\n// CHECK:STDOUT:   %.loc15_22: init %Param = converted %.loc15_21.1, %.loc15_21.5 [concrete = constants.%Param.val]\n// CHECK:STDOUT:   return %.loc15_22 to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %a.patt: %pattern_type.7ce = value_binding_pattern a [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.ref.loc21: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %.loc21_24: %HasF.assoc_type.078 = specific_constant @HasF.WithSelf.%assoc0.loc5_14.1, @HasF.WithSelf(constants.%Param, constants.%C.type.facet) [concrete = constants.%assoc0.22c]\n// CHECK:STDOUT:   %F.ref.loc21: %HasF.assoc_type.078 = name_ref F, %.loc21_24 [concrete = constants.%assoc0.22c]\n// CHECK:STDOUT:   %impl.elem0.loc21: %.095 = impl_witness_access constants.%HasF.impl_witness, element0 [concrete = constants.%C.as.HasF.impl.F]\n// CHECK:STDOUT:   %.loc21_27.1: ref %Param = temporary_storage\n// CHECK:STDOUT:   %C.as.HasF.impl.F.call.loc21: init %Param to %.loc21_27.1 = call %impl.elem0.loc21()\n// CHECK:STDOUT:   %.loc21_27.2: ref %Param = temporary %.loc21_27.1, %C.as.HasF.impl.F.call.loc21\n// CHECK:STDOUT:   %x.ref.loc21: %Param.elem = name_ref x, @Param.%.loc9 [concrete = @Param.%.loc9]\n// CHECK:STDOUT:   %.loc21_28.1: ref %i32 = class_element_access %.loc21_27.2, element0\n// CHECK:STDOUT:   %i32.loc21: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %.loc21_28.2: %i32 = acquire_value %.loc21_28.1\n// CHECK:STDOUT:   %a: %i32 = value_binding a, %.loc21_28.2\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %b.patt: %pattern_type.7ce = ref_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %b.var: ref %i32 = var %b.var_patt\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %.loc22_24: %HasF.assoc_type.078 = specific_constant @HasF.WithSelf.%assoc0.loc5_14.1, @HasF.WithSelf(constants.%Param, constants.%C.type.facet) [concrete = constants.%assoc0.22c]\n// CHECK:STDOUT:   %F.ref.loc22: %HasF.assoc_type.078 = name_ref F, %.loc22_24 [concrete = constants.%assoc0.22c]\n// CHECK:STDOUT:   %impl.elem0.loc22_24: %.095 = impl_witness_access constants.%HasF.impl_witness, element0 [concrete = constants.%C.as.HasF.impl.F]\n// CHECK:STDOUT:   %.loc22_27.1: ref %Param = temporary_storage\n// CHECK:STDOUT:   %C.as.HasF.impl.F.call.loc22: init %Param to %.loc22_27.1 = call %impl.elem0.loc22_24()\n// CHECK:STDOUT:   %.loc22_27.2: ref %Param = temporary %.loc22_27.1, %C.as.HasF.impl.F.call.loc22\n// CHECK:STDOUT:   %x.ref.loc22: %Param.elem = name_ref x, @Param.%.loc9 [concrete = @Param.%.loc9]\n// CHECK:STDOUT:   %.loc22_28.1: ref %i32 = class_element_access %.loc22_27.2, element0\n// CHECK:STDOUT:   %.loc22_28.2: %i32 = acquire_value %.loc22_28.1\n// CHECK:STDOUT:   %impl.elem0.loc22_28: %.8e2 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664]\n// CHECK:STDOUT:   %bound_method.loc22_28.1: <bound method> = bound_method %.loc22_28.2, %impl.elem0.loc22_28\n// CHECK:STDOUT:   %specific_fn: <specific function> = specific_function %impl.elem0.loc22_28, @Int.as.Copy.impl.Op(constants.%int_32) [concrete = constants.%Int.as.Copy.impl.Op.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc22_28.2: <bound method> = bound_method %.loc22_28.2, %specific_fn\n// CHECK:STDOUT:   %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc22_28.2(%.loc22_28.2)\n// CHECK:STDOUT:   assign %b.var, %Int.as.Copy.impl.Op.call\n// CHECK:STDOUT:   %i32.loc22: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   %b: ref %i32 = ref_binding b, %b.var\n// CHECK:STDOUT:   %Destroy.Op.bound.loc22_27: <bound method> = bound_method %.loc22_27.2, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc22_27: init %empty_tuple.type = call %Destroy.Op.bound.loc22_27(%.loc22_27.2)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc22_3: <bound method> = bound_method %b.var, constants.%Destroy.Op.651ba6.2\n// CHECK:STDOUT:   %Destroy.Op.call.loc22_3: init %empty_tuple.type = call %Destroy.Op.bound.loc22_3(%b.var)\n// CHECK:STDOUT:   %Destroy.Op.bound.loc21: <bound method> = bound_method %.loc21_27.2, constants.%Destroy.Op.651ba6.1\n// CHECK:STDOUT:   %Destroy.Op.call.loc21: init %empty_tuple.type = call %Destroy.Op.bound.loc21(%.loc21_27.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc22_27(%self.param: ref %Param) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op.loc22_3(%self.param: ref %i32) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasF(constants.%T.67d) {\n// CHECK:STDOUT:   %T.loc4_16.1 => constants.%T.67d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasF.WithSelf(constants.%T.67d, constants.%Self.c1f) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasF.WithSelf.F(constants.%T.67d, constants.%Self.c1f) {\n// CHECK:STDOUT:   %T => constants.%T.67d\n// CHECK:STDOUT:   %.loc5_13.1 => constants.%.184347.1\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d1c4.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasF(constants.%Param) {\n// CHECK:STDOUT:   %T.loc4_16.1 => constants.%Param\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %HasF.type => constants.%HasF.type.a3d\n// CHECK:STDOUT:   %Self.loc4_26.2 => constants.%Self.5e8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasF.WithSelf(constants.%Param, constants.%Self.c1f) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%Param\n// CHECK:STDOUT:   %HasF.type => constants.%HasF.type.a3d\n// CHECK:STDOUT:   %Self => constants.%Self.c1f\n// CHECK:STDOUT:   %HasF.WithSelf.F.type => constants.%HasF.WithSelf.F.type.a94\n// CHECK:STDOUT:   %HasF.WithSelf.F => constants.%HasF.WithSelf.F.1c0\n// CHECK:STDOUT:   %HasF.assoc_type => constants.%HasF.assoc_type.078\n// CHECK:STDOUT:   %assoc0.loc5_14.2 => constants.%assoc0.22c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasF.WithSelf(constants.%Param, constants.%HasF.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%Param\n// CHECK:STDOUT:   %HasF.type => constants.%HasF.type.a3d\n// CHECK:STDOUT:   %Self => constants.%HasF.facet\n// CHECK:STDOUT:   %HasF.WithSelf.F.type => constants.%HasF.WithSelf.F.type.a36\n// CHECK:STDOUT:   %HasF.WithSelf.F => constants.%HasF.WithSelf.F.753\n// CHECK:STDOUT:   %HasF.assoc_type => constants.%HasF.assoc_type.078\n// CHECK:STDOUT:   %assoc0.loc5_14.2 => constants.%assoc0.22c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasF.WithSelf.F(constants.%Param, constants.%HasF.facet) {\n// CHECK:STDOUT:   %T => constants.%Param\n// CHECK:STDOUT:   %.loc5_13.1 => constants.%.436\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.9ea\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @HasF.WithSelf(constants.%Param, constants.%C.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%Param\n// CHECK:STDOUT:   %HasF.type => constants.%HasF.type.a3d\n// CHECK:STDOUT:   %Self => constants.%C.type.facet\n// CHECK:STDOUT:   %HasF.WithSelf.F.type => constants.%HasF.WithSelf.F.type.70d\n// CHECK:STDOUT:   %HasF.WithSelf.F => constants.%HasF.WithSelf.F.489\n// CHECK:STDOUT:   %HasF.assoc_type => constants.%HasF.assoc_type.078\n// CHECK:STDOUT:   %assoc0.loc5_14.2 => constants.%assoc0.22c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- extend_impl_generic_class.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.1ab3e4.1: type = facet_type <@I, @I(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.fdb544.1: %I.type.1ab3e4.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.fdb544.1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.a8a: type = pattern_type %Self.binding.as_type [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d1c4.1: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.1d69d8.1: type = fn_type @I.WithSelf.F, @I.WithSelf(%T, %Self.fdb544.1) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.cd4fc9.1: %I.WithSelf.F.type.1d69d8.1 = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.assoc_type.76c031.1: type = assoc_entity_type @I, @I(%T) [symbolic]\n// CHECK:STDOUT:   %assoc0.203667.1: %I.assoc_type.76c031.1 = assoc_entity element0, @I.WithSelf.%I.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %X.type: type = generic_class_type @X [concrete]\n// CHECK:STDOUT:   %X.generic: %X.type = struct_value () [concrete]\n// CHECK:STDOUT:   %X: type = class_type @X, @X(%U) [symbolic]\n// CHECK:STDOUT:   %I.type.1ab3e4.2: type = facet_type <@I, @I(%U)> [symbolic]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @X.as.I.impl.%I.impl_witness_table, @X.as.I.impl(%U) [symbolic]\n// CHECK:STDOUT:   %Self.fdb544.2: %I.type.1ab3e4.2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.1d69d8.2: type = fn_type @I.WithSelf.F, @I.WithSelf(%U, %Self.fdb544.1) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.cd4fc9.2: %I.WithSelf.F.type.1d69d8.2 = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.assoc_type.76c031.2: type = assoc_entity_type @I, @I(%U) [symbolic]\n// CHECK:STDOUT:   %assoc0.203667.2: %I.assoc_type.76c031.2 = assoc_entity element0, @I.WithSelf.%I.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %require_complete.e36: <witness> = require_complete_type %I.type.1ab3e4.2 [symbolic]\n// CHECK:STDOUT:   %pattern_type.e07: type = pattern_type %X [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d1c4.2: type = pattern_type %U [symbolic]\n// CHECK:STDOUT:   %X.as.I.impl.F.type: type = fn_type @X.as.I.impl.F, @X.as.I.impl(%U) [symbolic]\n// CHECK:STDOUT:   %X.as.I.impl.F: %X.as.I.impl.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type.1ab3e4.2 = facet_value %X, (%I.impl_witness) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.94a: type = fn_type @I.WithSelf.F, @I.WithSelf(%U, %I.facet) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.8fe: %I.WithSelf.F.type.94a = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete.5dd: <witness> = require_complete_type %X [symbolic]\n// CHECK:STDOUT:   %require_complete.944: <witness> = require_complete_type %U [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .X = %X.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %X.decl: %X.type = class_decl @X [concrete = constants.%X.generic] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.98f = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc8_13.1: type = splice_block %.loc8_13.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_13.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc8_9.2: type = symbolic_binding U, 0 [symbolic = %U.loc8_9.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc4_13.1)> [symbolic = %I.type (constants.%I.type.1ab3e4.1)]\n// CHECK:STDOUT:   %Self.loc4_23.2: @I.%I.type (%I.type.1ab3e4.1) = symbolic_binding Self, 1 [symbolic = %Self.loc4_23.2 (constants.%Self.fdb544.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc4_23.1: @I.%I.type (%I.type.1ab3e4.1) = symbolic_binding Self, 1 [symbolic = %Self.loc4_23.2 (constants.%Self.fdb544.1)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %I.WithSelf.F.decl: @I.WithSelf.%I.WithSelf.F.type (%I.WithSelf.F.type.1d69d8.1) = fn_decl @I.WithSelf.F [symbolic = @I.WithSelf.%I.WithSelf.F (constants.%I.WithSelf.F.cd4fc9.1)] {\n// CHECK:STDOUT:       %self.patt: @I.WithSelf.F.%pattern_type.loc5_8 (%pattern_type.a8a) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @I.WithSelf.F.%pattern_type.loc5_8 (%pattern_type.a8a) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: @I.WithSelf.F.%pattern_type.loc5_20 (%pattern_type.51d1c4.1) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: @I.WithSelf.F.%pattern_type.loc5_20 (%pattern_type.51d1c4.1) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:       %.loc5_14.1: type = splice_block %.loc5_14.3 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)] {\n// CHECK:STDOUT:         %.loc5_14.2: @I.WithSelf.F.%I.type (%I.type.1ab3e4.1) = specific_constant @I.%Self.loc4_23.1, @I(constants.%T) [symbolic = %Self (constants.%Self.fdb544.1)]\n// CHECK:STDOUT:         %Self.ref: @I.WithSelf.F.%I.type (%I.type.1ab3e4.1) = name_ref Self, %.loc5_14.2 [symbolic = %Self (constants.%Self.fdb544.1)]\n// CHECK:STDOUT:         %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:         %.loc5_14.3: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: @I.WithSelf.F.%T (%T) = value_param call_param1\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @I.%T.loc4_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %t: @I.WithSelf.F.%T (%T) = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %assoc0.loc5_25.1: @I.WithSelf.%I.assoc_type (%I.assoc_type.76c031.1) = assoc_entity element0, %I.WithSelf.F.decl [symbolic = %assoc0.loc5_25.2 (constants.%assoc0.203667.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc4_23.1\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = @I.WithSelf.%assoc0.loc5_25.1\n// CHECK:STDOUT:     .U = <poisoned>\n// CHECK:STDOUT:     witness = (@I.WithSelf.%I.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @X.as.I.impl(@X.%U.loc8_9.2: type) {\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:   %X: type = class_type @X, @X(%U) [symbolic = %X (constants.%X)]\n// CHECK:STDOUT:   %I.type.loc9_21.1: type = facet_type <@I, @I(%U)> [symbolic = %I.type.loc9_21.1 (constants.%I.type.1ab3e4.2)]\n// CHECK:STDOUT:   %I.impl_witness.loc9_23.2: <witness> = impl_witness %I.impl_witness_table, @X.as.I.impl(%U) [symbolic = %I.impl_witness.loc9_23.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.loc9_21.1 [symbolic = %require_complete (constants.%require_complete.e36)]\n// CHECK:STDOUT:   %X.as.I.impl.F.type: type = fn_type @X.as.I.impl.F, @X.as.I.impl(%U) [symbolic = %X.as.I.impl.F.type (constants.%X.as.I.impl.F.type)]\n// CHECK:STDOUT:   %X.as.I.impl.F: @X.as.I.impl.%X.as.I.impl.F.type (%X.as.I.impl.F.type) = struct_value () [symbolic = %X.as.I.impl.F (constants.%X.as.I.impl.F)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %Self.ref as %I.type.loc9_21.2 {\n// CHECK:STDOUT:     %X.as.I.impl.F.decl: @X.as.I.impl.%X.as.I.impl.F.type (%X.as.I.impl.F.type) = fn_decl @X.as.I.impl.F [symbolic = @X.as.I.impl.%X.as.I.impl.F (constants.%X.as.I.impl.F)] {\n// CHECK:STDOUT:       %self.patt: @X.as.I.impl.F.%pattern_type.loc10_17 (%pattern_type.e07) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @X.as.I.impl.F.%pattern_type.loc10_17 (%pattern_type.e07) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:       %t.patt: @X.as.I.impl.F.%pattern_type.loc10_36 (%pattern_type.51d1c4.2) = value_binding_pattern t [concrete]\n// CHECK:STDOUT:       %t.param_patt: @X.as.I.impl.F.%pattern_type.loc10_36 (%pattern_type.51d1c4.2) = value_param_pattern %t.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @X.as.I.impl.F.%X (%X) = value_param call_param0\n// CHECK:STDOUT:       %.loc10_23.1: type = splice_block %Self.ref [symbolic = %X (constants.%X)] {\n// CHECK:STDOUT:         %.loc10_23.2: type = specific_constant constants.%X, @X(constants.%U) [symbolic = %X (constants.%X)]\n// CHECK:STDOUT:         %Self.ref: type = name_ref Self, %.loc10_23.2 [symbolic = %X (constants.%X)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @X.as.I.impl.F.%X (%X) = value_binding self, %self.param\n// CHECK:STDOUT:       %t.param: @X.as.I.impl.F.%U (%U) = value_param call_param1\n// CHECK:STDOUT:       %U.ref: type = name_ref U, @X.%U.loc8_9.2 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:       %t: @X.as.I.impl.F.%U (%U) = value_binding t, %t.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (%X.as.I.impl.F.decl), @X.as.I.impl [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc9_23.1: <witness> = impl_witness %I.impl_witness_table, @X.as.I.impl(constants.%U) [symbolic = %I.impl_witness.loc9_23.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .U = <poisoned>\n// CHECK:STDOUT:     .F = %X.as.I.impl.F.decl\n// CHECK:STDOUT:     witness = %I.impl_witness.loc9_23.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @X(%U.loc8_9.2: type) {\n// CHECK:STDOUT:   %U.loc8_9.1: type = symbolic_binding U, 0 [symbolic = %U.loc8_9.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%U.loc8_9.1)> [symbolic = %I.type (constants.%I.type.1ab3e4.2)]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete.e36)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     impl_decl @X.as.I.impl [concrete] {} {\n// CHECK:STDOUT:       %Self.ref: type = name_ref Self, constants.%X [symbolic = %X (constants.%X)]\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %U.ref: type = name_ref U, @X.%U.loc8_9.2 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:       %I.type.loc9_21.2: type = facet_type <@I, @I(constants.%U)> [symbolic = %I.type.loc9_21.1 (constants.%I.type.1ab3e4.2)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %.loc9: type = specific_constant @X.as.I.impl.%I.type.loc9_21.2, @X.as.I.impl(constants.%U) [symbolic = %I.type (constants.%I.type.1ab3e4.2)]\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%X\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     .U = <poisoned>\n// CHECK:STDOUT:     extend %.loc9\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.F(@I.%T.loc4_13.2: type, @I.%Self.loc4_23.1: @I.%I.type (%I.type.1ab3e4.1)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab3e4.1)]\n// CHECK:STDOUT:   %Self: @I.WithSelf.F.%I.type (%I.type.1ab3e4.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.fdb544.1)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type.loc5_8: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type.loc5_8 (constants.%pattern_type.a8a)]\n// CHECK:STDOUT:   %pattern_type.loc5_20: type = pattern_type %T [symbolic = %pattern_type.loc5_20 (constants.%pattern_type.51d1c4.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @I.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type), %t.param: @I.WithSelf.F.%T (%T));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @X.as.I.impl.F(@X.%U.loc8_9.2: type) {\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic = %U (constants.%U)]\n// CHECK:STDOUT:   %X: type = class_type @X, @X(%U) [symbolic = %X (constants.%X)]\n// CHECK:STDOUT:   %pattern_type.loc10_17: type = pattern_type %X [symbolic = %pattern_type.loc10_17 (constants.%pattern_type.e07)]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%U)> [symbolic = %I.type (constants.%I.type.1ab3e4.2)]\n// CHECK:STDOUT:   %require_complete.loc10_39: <witness> = require_complete_type %I.type [symbolic = %require_complete.loc10_39 (constants.%require_complete.e36)]\n// CHECK:STDOUT:   %pattern_type.loc10_36: type = pattern_type %U [symbolic = %pattern_type.loc10_36 (constants.%pattern_type.51d1c4.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete.loc10_21: <witness> = require_complete_type %X [symbolic = %require_complete.loc10_21 (constants.%require_complete.5dd)]\n// CHECK:STDOUT:   %require_complete.loc10_37: <witness> = require_complete_type %U [symbolic = %require_complete.loc10_37 (constants.%require_complete.944)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @X.as.I.impl.F.%X (%X), %t.param: @X.as.I.impl.F.%U (%U)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%Self.fdb544.1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%T, constants.%Self.fdb544.1) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab3e4.1\n// CHECK:STDOUT:   %Self => constants.%Self.fdb544.1\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %pattern_type.loc5_8 => constants.%pattern_type.a8a\n// CHECK:STDOUT:   %pattern_type.loc5_20 => constants.%pattern_type.51d1c4.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X(constants.%U) {\n// CHECK:STDOUT:   %U.loc8_9.1 => constants.%U\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab3e4.2\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.e36\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%U) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%U\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab3e4.2\n// CHECK:STDOUT:   %Self.loc4_23.2 => constants.%Self.fdb544.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.as.I.impl(constants.%U) {\n// CHECK:STDOUT:   %U => constants.%U\n// CHECK:STDOUT:   %X => constants.%X\n// CHECK:STDOUT:   %I.type.loc9_21.1 => constants.%I.type.1ab3e4.2\n// CHECK:STDOUT:   %I.impl_witness.loc9_23.2 => constants.%I.impl_witness\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.e36\n// CHECK:STDOUT:   %X.as.I.impl.F.type => constants.%X.as.I.impl.F.type\n// CHECK:STDOUT:   %X.as.I.impl.F => constants.%X.as.I.impl.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%U, constants.%Self.fdb544.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%U\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab3e4.2\n// CHECK:STDOUT:   %Self => constants.%Self.fdb544.1\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.1d69d8.2\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.cd4fc9.2\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.76c031.2\n// CHECK:STDOUT:   %assoc0.loc5_25.2 => constants.%assoc0.203667.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.as.I.impl.F(constants.%U) {\n// CHECK:STDOUT:   %U => constants.%U\n// CHECK:STDOUT:   %X => constants.%X\n// CHECK:STDOUT:   %pattern_type.loc10_17 => constants.%pattern_type.e07\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab3e4.2\n// CHECK:STDOUT:   %require_complete.loc10_39 => constants.%require_complete.e36\n// CHECK:STDOUT:   %pattern_type.loc10_36 => constants.%pattern_type.51d1c4.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%U, constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%U\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab3e4.2\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.94a\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.8fe\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.76c031.2\n// CHECK:STDOUT:   %assoc0.loc5_25.2 => constants.%assoc0.203667.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%U, constants.%I.facet) {\n// CHECK:STDOUT:   %T => constants.%U\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab3e4.2\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%X\n// CHECK:STDOUT:   %pattern_type.loc5_8 => constants.%pattern_type.e07\n// CHECK:STDOUT:   %pattern_type.loc5_20 => constants.%pattern_type.51d1c4.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_alias.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_alias.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_alias.carbon\n\ninterface I {}\nclass C {}\n\nalias AI = I;\nalias AC = C;\n\nimpl AC as AI {}\n\n// CHECK:STDERR: fail_alias.carbon:[[@LINE+7]]:1: error: redefinition of `impl AC as AI` [ImplRedefinition]\n// CHECK:STDERR: impl AC as AI {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_alias.carbon:[[@LINE-5]]:1: note: previous definition was here [ImplPreviousDefinition]\n// CHECK:STDERR: impl AC as AI {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl AC as AI {}\n\n// CHECK:STDOUT: --- fail_alias.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.e47215.1.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .AI = %AI\n// CHECK:STDOUT:     .AC = %AC\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %I.ref: type = name_ref I, %I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   %AI: type = alias_binding AI, %I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %AC: type = alias_binding AC, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.e47215.1 [concrete] {} {\n// CHECK:STDOUT:     %AC.ref: type = name_ref AC, file.%AC [concrete = constants.%C]\n// CHECK:STDOUT:     %AI.ref: type = name_ref AI, file.%AI [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.e47215.2 [concrete] {} {\n// CHECK:STDOUT:     %AC.ref: type = name_ref AC, file.%AC [concrete = constants.%C]\n// CHECK:STDOUT:     %AI.ref: type = name_ref AI, file.%AI [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl.e47215.1: %AC.ref as %AI.ref {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl.e47215.1 [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl.e47215.2: %AC.ref as %AI.ref {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_call_invalid.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_call_invalid.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_call_invalid.carbon\n\ninterface Simple {\n  fn G[self: Self]();\n}\n\nimpl i32 as Simple {\n  // CHECK:STDERR: fail_call_invalid.carbon:[[@LINE+4]]:14: error: name `Undeclared` not found [NameNotFound]\n  // CHECK:STDERR:   fn G[self: Undeclared]();\n  // CHECK:STDERR:              ^~~~~~~~~~\n  // CHECK:STDERR:\n  fn G[self: Undeclared]();\n}\n\nfn InstanceCall(n: i32) {\n  n.(Simple.G)();\n}\n\n// CHECK:STDOUT: --- fail_call_invalid.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Simple.type: type = facet_type <@Simple> [concrete]\n// CHECK:STDOUT:   %Self: %Simple.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic]\n// CHECK:STDOUT:   %pattern_type.5e9: type = pattern_type %Self.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Simple.WithSelf.G.type.d78: type = fn_type @Simple.WithSelf.G, @Simple.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Simple.WithSelf.G.41d: %Simple.WithSelf.G.type.d78 = struct_value () [symbolic]\n// CHECK:STDOUT:   %Simple.assoc_type: type = assoc_entity_type @Simple [concrete]\n// CHECK:STDOUT:   %assoc0: %Simple.assoc_type = assoc_entity element0, @Simple.WithSelf.%Simple.WithSelf.G.decl [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %Simple.impl_witness: <witness> = impl_witness @i32.as.Simple.impl.%Simple.impl_witness_table [concrete]\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.type.32ad7a.1: type = fn_type @i32.as.Simple.impl.G.loc24_27.1 [concrete]\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.4f6260.1: %i32.as.Simple.impl.G.type.32ad7a.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %Simple.facet: %Simple.type = facet_value %i32, (%Simple.impl_witness) [concrete]\n// CHECK:STDOUT:   %Simple.WithSelf.G.type.9d9: type = fn_type @Simple.WithSelf.G, @Simple.WithSelf(%Simple.facet) [concrete]\n// CHECK:STDOUT:   %Simple.WithSelf.G.26c: %Simple.WithSelf.G.type.9d9 = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.7ce: type = pattern_type %i32 [concrete]\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.type.32ad7a.2: type = fn_type @i32.as.Simple.impl.G.loc24_27.2 [concrete]\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.4f6260.2: %i32.as.Simple.impl.G.type.32ad7a.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %InstanceCall.type: type = fn_type @InstanceCall [concrete]\n// CHECK:STDOUT:   %InstanceCall: %InstanceCall.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.a46: type = fn_type_with_self_type %Simple.WithSelf.G.type.9d9, %Simple.facet [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Simple = %Simple.decl\n// CHECK:STDOUT:     .Undeclared = <poisoned>\n// CHECK:STDOUT:     .InstanceCall = %InstanceCall.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Simple.decl: type = interface_decl @Simple [concrete = constants.%Simple.type] {} {}\n// CHECK:STDOUT:   impl_decl @i32.as.Simple.impl [concrete] {} {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %Simple.ref: type = name_ref Simple, file.%Simple.decl [concrete = constants.%Simple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %InstanceCall.decl: %InstanceCall.type = fn_decl @InstanceCall [concrete = constants.%InstanceCall] {\n// CHECK:STDOUT:     %n.patt: %pattern_type.7ce = value_binding_pattern n [concrete]\n// CHECK:STDOUT:     %n.param_patt: %pattern_type.7ce = value_param_pattern %n.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %n.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %n: %i32 = value_binding n, %n.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Simple {\n// CHECK:STDOUT:   %Self: %Simple.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Simple.WithSelf.decl = interface_with_self_decl @Simple [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %Simple.WithSelf.G.decl: @Simple.WithSelf.%Simple.WithSelf.G.type (%Simple.WithSelf.G.type.d78) = fn_decl @Simple.WithSelf.G [symbolic = @Simple.WithSelf.%Simple.WithSelf.G (constants.%Simple.WithSelf.G.41d)] {\n// CHECK:STDOUT:     %self.patt: @Simple.WithSelf.G.%pattern_type (%pattern_type.5e9) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: @Simple.WithSelf.G.%pattern_type (%pattern_type.5e9) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: @Simple.WithSelf.G.%Self.binding.as_type (%Self.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc16_14.1: type = splice_block %.loc16_14.2 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)] {\n// CHECK:STDOUT:       %Self.ref: %Simple.type = name_ref Self, @Simple.%Self [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       %.loc16_14.2: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self: @Simple.WithSelf.G.%Self.binding.as_type (%Self.binding.as_type) = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %assoc0: %Simple.assoc_type = assoc_entity element0, %Simple.WithSelf.G.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .G = @Simple.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@Simple.WithSelf.%Simple.WithSelf.G.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.as.Simple.impl: %i32 as %Simple.ref {\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.decl.loc24_27.1: %i32.as.Simple.impl.G.type.32ad7a.1 = fn_decl @i32.as.Simple.impl.G.loc24_27.1 [concrete = constants.%i32.as.Simple.impl.G.4f6260.1] {\n// CHECK:STDOUT:     %self.patt: <error> = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: <error> = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: <error> = value_param call_param0\n// CHECK:STDOUT:     %Undeclared.ref: <error> = name_ref Undeclared, <error> [concrete = <error>]\n// CHECK:STDOUT:     %self: <error> = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.decl.loc24_27.2: %i32.as.Simple.impl.G.type.32ad7a.2 = fn_decl @i32.as.Simple.impl.G.loc24_27.2 [concrete = constants.%i32.as.Simple.impl.G.4f6260.2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.7ce = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.7ce = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %i32 = value_param call_param0\n// CHECK:STDOUT:     %self: %i32 = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Simple.impl_witness_table = impl_witness_table (%i32.as.Simple.impl.G.decl.loc24_27.2), @i32.as.Simple.impl [concrete]\n// CHECK:STDOUT:   %Simple.impl_witness: <witness> = impl_witness %Simple.impl_witness_table [concrete = constants.%Simple.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Undeclared = <poisoned>\n// CHECK:STDOUT:   .G = %i32.as.Simple.impl.G.decl.loc24_27.1\n// CHECK:STDOUT:   witness = %Simple.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Simple.WithSelf.G(@Simple.%Self: %Simple.type) {\n// CHECK:STDOUT:   %Self: %Simple.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.5e9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @Simple.WithSelf.G.%Self.binding.as_type (%Self.binding.as_type));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @i32.as.Simple.impl.G.loc24_27.1(%self.param: <error>);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @i32.as.Simple.impl.G.loc24_27.2(%self.param: %i32) [thunk @i32.as.Simple.impl.%i32.as.Simple.impl.G.decl.loc24_27.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %G.ref: %i32.as.Simple.impl.G.type.32ad7a.1 = name_ref G, @i32.as.Simple.impl.%i32.as.Simple.impl.G.decl.loc24_27.1 [concrete = constants.%i32.as.Simple.impl.G.4f6260.1]\n// CHECK:STDOUT:   %self.ref: %i32 = name_ref self, %self.param\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.bound: <bound method> = bound_method %self.ref, %G.ref\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.call: init %empty_tuple.type = call %i32.as.Simple.impl.G.bound(<error>)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @InstanceCall(%n.param: %i32) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %n.ref: %i32 = name_ref n, %n\n// CHECK:STDOUT:   %Simple.ref: type = name_ref Simple, file.%Simple.decl [concrete = constants.%Simple.type]\n// CHECK:STDOUT:   %G.ref.loc28_12: %Simple.assoc_type = name_ref G, @Simple.WithSelf.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %impl.elem0: %.a46 = impl_witness_access constants.%Simple.impl_witness, element0 [concrete = constants.%i32.as.Simple.impl.G.4f6260.2]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %n.ref, %impl.elem0\n// CHECK:STDOUT:   %G.ref.loc28_16: %i32.as.Simple.impl.G.type.32ad7a.1 = name_ref G, @i32.as.Simple.impl.%i32.as.Simple.impl.G.decl.loc24_27.1 [concrete = constants.%i32.as.Simple.impl.G.4f6260.1]\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.bound: <bound method> = bound_method %n.ref, %G.ref.loc28_16\n// CHECK:STDOUT:   %i32.as.Simple.impl.G.call: init %empty_tuple.type = call %i32.as.Simple.impl.G.bound(<error>)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Simple.WithSelf.G.type => constants.%Simple.WithSelf.G.type.d78\n// CHECK:STDOUT:   %Simple.WithSelf.G => constants.%Simple.WithSelf.G.41d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf.G(constants.%Self) {\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.5e9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf(constants.%Simple.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Simple.facet\n// CHECK:STDOUT:   %Simple.WithSelf.G.type => constants.%Simple.WithSelf.G.type.9d9\n// CHECK:STDOUT:   %Simple.WithSelf.G => constants.%Simple.WithSelf.G.26c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf.G(constants.%Simple.facet) {\n// CHECK:STDOUT:   %Self => constants.%Simple.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%i32\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7ce\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_extend_impl_forall.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_extend_impl_forall.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_extend_impl_forall.carbon\n\ninterface GenericInterface(T:! type) {\n  fn F(x: T);\n}\n\nclass C {\n  // CHECK:STDERR: fail_extend_impl_forall.carbon:[[@LINE+4]]:3: error: cannot `extend` a parameterized `impl` [ExtendImplForall]\n  // CHECK:STDERR:   extend impl forall [T:! type] as GenericInterface(T) {\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR:\n  extend impl forall [T:! type] as GenericInterface(T) {\n    fn F(unused x: T) {}\n  }\n}\n\n// CHECK:STDOUT: --- fail_extend_impl_forall.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %GenericInterface.type.21d: type = generic_interface_type @GenericInterface [concrete]\n// CHECK:STDOUT:   %GenericInterface.generic: %GenericInterface.type.21d = struct_value () [concrete]\n// CHECK:STDOUT:   %GenericInterface.type.8bc: type = facet_type <@GenericInterface, @GenericInterface(%T)> [symbolic]\n// CHECK:STDOUT:   %Self: %GenericInterface.type.8bc = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %pattern_type.51d: type = pattern_type %T [symbolic]\n// CHECK:STDOUT:   %GenericInterface.WithSelf.F.type: type = fn_type @GenericInterface.WithSelf.F, @GenericInterface.WithSelf(%T, %Self) [symbolic]\n// CHECK:STDOUT:   %GenericInterface.WithSelf.F: %GenericInterface.WithSelf.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %GenericInterface.assoc_type: type = assoc_entity_type @GenericInterface, @GenericInterface(%T) [symbolic]\n// CHECK:STDOUT:   %assoc0: %GenericInterface.assoc_type = assoc_entity element0, @GenericInterface.WithSelf.%GenericInterface.WithSelf.F.decl [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %GenericInterface.impl_witness: <witness> = impl_witness @C.as.GenericInterface.impl.%GenericInterface.impl_witness_table, @C.as.GenericInterface.impl(%T) [symbolic]\n// CHECK:STDOUT:   %C.as.GenericInterface.impl.F.type: type = fn_type @C.as.GenericInterface.impl.F, @C.as.GenericInterface.impl(%T) [symbolic]\n// CHECK:STDOUT:   %C.as.GenericInterface.impl.F: %C.as.GenericInterface.impl.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .GenericInterface = %GenericInterface.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %GenericInterface.decl: %GenericInterface.type.21d = interface_decl @GenericInterface [concrete = constants.%GenericInterface.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc15_32.1: type = splice_block %.loc15_32.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_32.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_28.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_28.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @GenericInterface(%T.loc15_28.2: type) {\n// CHECK:STDOUT:   %T.loc15_28.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_28.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %GenericInterface.type: type = facet_type <@GenericInterface, @GenericInterface(%T.loc15_28.1)> [symbolic = %GenericInterface.type (constants.%GenericInterface.type.8bc)]\n// CHECK:STDOUT:   %Self.loc15_38.2: @GenericInterface.%GenericInterface.type (%GenericInterface.type.8bc) = symbolic_binding Self, 1 [symbolic = %Self.loc15_38.2 (constants.%Self)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc15_38.1: @GenericInterface.%GenericInterface.type (%GenericInterface.type.8bc) = symbolic_binding Self, 1 [symbolic = %Self.loc15_38.2 (constants.%Self)]\n// CHECK:STDOUT:     %GenericInterface.WithSelf.decl = interface_with_self_decl @GenericInterface [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %GenericInterface.WithSelf.F.decl: @GenericInterface.WithSelf.%GenericInterface.WithSelf.F.type (%GenericInterface.WithSelf.F.type) = fn_decl @GenericInterface.WithSelf.F [symbolic = @GenericInterface.WithSelf.%GenericInterface.WithSelf.F (constants.%GenericInterface.WithSelf.F)] {\n// CHECK:STDOUT:       %x.patt: @GenericInterface.WithSelf.F.%pattern_type (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:       %x.param_patt: @GenericInterface.WithSelf.F.%pattern_type (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %x.param: @GenericInterface.WithSelf.F.%T (%T) = value_param call_param0\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @GenericInterface.%T.loc15_28.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %x: @GenericInterface.WithSelf.F.%T (%T) = value_binding x, %x.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %assoc0.loc16_13.1: @GenericInterface.WithSelf.%GenericInterface.assoc_type (%GenericInterface.assoc_type) = assoc_entity element0, %GenericInterface.WithSelf.F.decl [symbolic = %assoc0.loc16_13.2 (constants.%assoc0)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc15_38.1\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = @GenericInterface.WithSelf.%assoc0.loc16_13.1\n// CHECK:STDOUT:     witness = (@GenericInterface.WithSelf.%GenericInterface.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.GenericInterface.impl(%T.loc24_23.2: type) {\n// CHECK:STDOUT:   %T.loc24_23.1: type = symbolic_binding T, 0 [symbolic = %T.loc24_23.1 (constants.%T)]\n// CHECK:STDOUT:   %GenericInterface.type.loc24_54.1: type = facet_type <@GenericInterface, @GenericInterface(%T.loc24_23.1)> [symbolic = %GenericInterface.type.loc24_54.1 (constants.%GenericInterface.type.8bc)]\n// CHECK:STDOUT:   %GenericInterface.impl_witness.loc24_56.2: <witness> = impl_witness %GenericInterface.impl_witness_table, @C.as.GenericInterface.impl(%T.loc24_23.1) [symbolic = %GenericInterface.impl_witness.loc24_56.2 (constants.%GenericInterface.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.as.GenericInterface.impl.F.type: type = fn_type @C.as.GenericInterface.impl.F, @C.as.GenericInterface.impl(%T.loc24_23.1) [symbolic = %C.as.GenericInterface.impl.F.type (constants.%C.as.GenericInterface.impl.F.type)]\n// CHECK:STDOUT:   %C.as.GenericInterface.impl.F: @C.as.GenericInterface.impl.%C.as.GenericInterface.impl.F.type (%C.as.GenericInterface.impl.F.type) = struct_value () [symbolic = %C.as.GenericInterface.impl.F (constants.%C.as.GenericInterface.impl.F)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %Self.ref as %GenericInterface.type.loc24_54.2 {\n// CHECK:STDOUT:     %C.as.GenericInterface.impl.F.decl: @C.as.GenericInterface.impl.%C.as.GenericInterface.impl.F.type (%C.as.GenericInterface.impl.F.type) = fn_decl @C.as.GenericInterface.impl.F [symbolic = @C.as.GenericInterface.impl.%C.as.GenericInterface.impl.F (constants.%C.as.GenericInterface.impl.F)] {\n// CHECK:STDOUT:       %x.patt: @C.as.GenericInterface.impl.F.%pattern_type (%pattern_type.51d) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:       %x.param_patt: @C.as.GenericInterface.impl.F.%pattern_type (%pattern_type.51d) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %x.param: @C.as.GenericInterface.impl.F.%T (%T) = value_param call_param0\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @C.as.GenericInterface.impl.%T.loc24_23.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %x: @C.as.GenericInterface.impl.F.%T (%T) = value_binding x, %x.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %GenericInterface.impl_witness_table = impl_witness_table (), @C.as.GenericInterface.impl [concrete]\n// CHECK:STDOUT:     %GenericInterface.impl_witness.loc24_56.1: <witness> = impl_witness %GenericInterface.impl_witness_table, @C.as.GenericInterface.impl(constants.%T) [symbolic = %GenericInterface.impl_witness.loc24_56.2 (constants.%GenericInterface.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .F = %C.as.GenericInterface.impl.F.decl\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   impl_decl @C.as.GenericInterface.impl [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %GenericInterface.ref: %GenericInterface.type.21d = name_ref GenericInterface, file.%GenericInterface.decl [concrete = constants.%GenericInterface.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc24_23.2 [symbolic = %T.loc24_23.1 (constants.%T)]\n// CHECK:STDOUT:     %GenericInterface.type.loc24_54.2: type = facet_type <@GenericInterface, @GenericInterface(constants.%T)> [symbolic = %GenericInterface.type.loc24_54.1 (constants.%GenericInterface.type.8bc)]\n// CHECK:STDOUT:     %.loc24_27.1: type = splice_block %.loc24_27.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc24_27.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc24_23.2: type = symbolic_binding T, 0 [symbolic = %T.loc24_23.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .GenericInterface = <poisoned>\n// CHECK:STDOUT:   has_error\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @GenericInterface.WithSelf.F(@GenericInterface.%T.loc15_28.2: type, @GenericInterface.%Self.loc15_38.1: @GenericInterface.%GenericInterface.type (%GenericInterface.type.8bc)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @GenericInterface.WithSelf.F.%T (%T));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @C.as.GenericInterface.impl.F(@C.as.GenericInterface.impl.%T.loc24_23.2: type) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %T [symbolic = %pattern_type (constants.%pattern_type.51d)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %T [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @C.as.GenericInterface.impl.F.%T (%T)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericInterface(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_28.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericInterface.WithSelf(constants.%T, constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @GenericInterface.WithSelf.F(constants.%T, constants.%Self) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.GenericInterface.impl(constants.%T) {\n// CHECK:STDOUT:   %T.loc24_23.1 => constants.%T\n// CHECK:STDOUT:   %GenericInterface.type.loc24_54.1 => constants.%GenericInterface.type.8bc\n// CHECK:STDOUT:   %GenericInterface.impl_witness.loc24_56.2 => constants.%GenericInterface.impl_witness\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %C.as.GenericInterface.impl.F.type => constants.%C.as.GenericInterface.impl.F.type\n// CHECK:STDOUT:   %C.as.GenericInterface.impl.F => constants.%C.as.GenericInterface.impl.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.GenericInterface.impl.F(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.51d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_extend_impl_scope.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_extend_impl_scope.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_extend_impl_scope.carbon\n\n// --- fail_extend_impl_file_scope.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\n// CHECK:STDERR: fail_extend_impl_file_scope.carbon:[[@LINE+4]]:1: error: `extend impl` can only be used in an interface or class [ExtendImplOutsideClass]\n// CHECK:STDERR: extend impl () as I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nextend impl () as I {}\n\n// --- fail_extend_impl_function_scope.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface J {}\n\nfn F() {\n  // CHECK:STDERR: fail_extend_impl_function_scope.carbon:[[@LINE+4]]:3: error: `extend impl` can only be used in an interface or class [ExtendImplOutsideClass]\n  // CHECK:STDERR:   extend impl {} as J {}\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend impl {} as J {}\n}\n\n// --- fail_extend_impl_self_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  fn Zero();\n\n  // CHECK:STDERR: fail_extend_impl_self_interface.carbon:[[@LINE+4]]:15: error: `impl as` can only be used in a class [ImplAsOutsideClass]\n  // CHECK:STDERR:   extend impl as Z {\n  // CHECK:STDERR:               ^~\n  // CHECK:STDERR:\n  extend impl as Z {\n    fn Zero() {}\n  }\n}\n\nclass Point {\n  extend impl as Z {\n    fn Zero() {}\n  }\n}\n\nfn F() {\n  // Even if the `extend impl` is diagnosed above, we must not add the impl of\n  // the interface to itself in a way that allows it to be used during impl\n  // lookup, or we end up with infinite impl lookup recursion here.\n  ({} as Point).Zero();\n}\n\n// CHECK:STDOUT: --- fail_extend_impl_file_scope.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @empty_tuple.type.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_tuple.type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc9_14.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc9_14.2: type = converted %.loc9_14.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_tuple.type.as.I.impl: %.loc9_14.2 as %I.ref {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @empty_tuple.type.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extend_impl_function_scope.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]\n// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness @empty_struct_type.as.J.impl.%J.impl_witness_table [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .J = %J.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @J {\n// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %J.WithSelf.decl = interface_with_self_decl @J [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_struct_type.as.J.impl: %.loc10_16.2 as %J.ref {\n// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (), @empty_struct_type.as.J.impl [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.J.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc10_16.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc10_16.2: type = converted %.loc10_16.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_extend_impl_self_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]\n// CHECK:STDOUT:   %Self.c59: %Z.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type.e4a: type = fn_type @Z.WithSelf.Zero, @Z.WithSelf(%Self.c59) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.3f4: %Z.WithSelf.Zero.type.e4a = struct_value () [symbolic]\n// CHECK:STDOUT:   %Z.assoc_type: type = assoc_entity_type @Z [concrete]\n// CHECK:STDOUT:   %assoc0.cc0: %Z.assoc_type = assoc_entity element0, @Z.WithSelf.%Z.WithSelf.Zero.decl [concrete]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero.type: type = fn_type @<error>.as.Z.impl.Zero, @<error>.as.Z.impl(%Self.c59) [symbolic]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero: %<error>.as.Z.impl.Zero.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %Point: type = class_type @Point [concrete]\n// CHECK:STDOUT:   %Z.impl_witness: <witness> = impl_witness @Point.as.Z.impl.%Z.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Point.as.Z.impl.Zero.type: type = fn_type @Point.as.Z.impl.Zero [concrete]\n// CHECK:STDOUT:   %Point.as.Z.impl.Zero: %Point.as.Z.impl.Zero.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %Point, (%Z.impl_witness) [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type.bb1: type = fn_type @Z.WithSelf.Zero, @Z.WithSelf(%Z.facet) [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.22c: %Z.WithSelf.Zero.type.bb1 = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Point.val: %Point = struct_value () [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %Point.type.facet: %type = facet_value %Point, () [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type.15e: type = fn_type @Z.WithSelf.Zero, @Z.WithSelf(%Point.type.facet) [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.55b: %Z.WithSelf.Zero.type.15e = struct_value () [concrete]\n// CHECK:STDOUT:   %.c1b: type = fn_type_with_self_type %Z.WithSelf.Zero.type.bb1, %Z.facet [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Z = %Z.decl\n// CHECK:STDOUT:     .Point = %Point.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Z.decl: type = interface_decl @Z [concrete = constants.%Z.type] {} {}\n// CHECK:STDOUT:   %Point.decl: type = class_decl @Point [concrete = constants.%Point] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Z {\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c59]\n// CHECK:STDOUT:   %Z.WithSelf.decl = interface_with_self_decl @Z [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %Z.WithSelf.Zero.decl: @Z.WithSelf.%Z.WithSelf.Zero.type (%Z.WithSelf.Zero.type.e4a) = fn_decl @Z.WithSelf.Zero [symbolic = @Z.WithSelf.%Z.WithSelf.Zero (constants.%Z.WithSelf.Zero.3f4)] {} {}\n// CHECK:STDOUT:   %assoc0: %Z.assoc_type = assoc_entity element0, %Z.WithSelf.Zero.decl [concrete = constants.%assoc0.cc0]\n// CHECK:STDOUT:   impl_decl @<error>.as.Z.impl [concrete] {} {\n// CHECK:STDOUT:     %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .Z = <poisoned>\n// CHECK:STDOUT:   .Zero = @Z.WithSelf.%assoc0\n// CHECK:STDOUT:   .Z = <poisoned>\n// CHECK:STDOUT:   witness = (@Z.WithSelf.%Z.WithSelf.Zero.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @<error>.as.Z.impl(@Z.%Self: %Z.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.c59)]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero.type: type = fn_type @<error>.as.Z.impl.Zero, @<error>.as.Z.impl(%Self) [symbolic = %<error>.as.Z.impl.Zero.type (constants.%<error>.as.Z.impl.Zero.type)]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero: @<error>.as.Z.impl.%<error>.as.Z.impl.Zero.type (%<error>.as.Z.impl.Zero.type) = struct_value () [symbolic = %<error>.as.Z.impl.Zero (constants.%<error>.as.Z.impl.Zero)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: <error> as %Z.ref {\n// CHECK:STDOUT:     %<error>.as.Z.impl.Zero.decl: @<error>.as.Z.impl.%<error>.as.Z.impl.Zero.type (%<error>.as.Z.impl.Zero.type) = fn_decl @<error>.as.Z.impl.Zero [symbolic = @<error>.as.Z.impl.%<error>.as.Z.impl.Zero (constants.%<error>.as.Z.impl.Zero)] {} {}\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Zero = %<error>.as.Z.impl.Zero.decl\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Point.as.Z.impl: %Self.ref as %Z.ref {\n// CHECK:STDOUT:   %Point.as.Z.impl.Zero.decl: %Point.as.Z.impl.Zero.type = fn_decl @Point.as.Z.impl.Zero [concrete = constants.%Point.as.Z.impl.Zero] {} {}\n// CHECK:STDOUT:   %Z.impl_witness_table = impl_witness_table (%Point.as.Z.impl.Zero.decl), @Point.as.Z.impl [concrete]\n// CHECK:STDOUT:   %Z.impl_witness: <witness> = impl_witness %Z.impl_witness_table [concrete = constants.%Z.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Zero = %Point.as.Z.impl.Zero.decl\n// CHECK:STDOUT:   witness = %Z.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Point {\n// CHECK:STDOUT:   impl_decl @Point.as.Z.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Point [concrete = constants.%Point]\n// CHECK:STDOUT:     %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Point\n// CHECK:STDOUT:   .Z = <poisoned>\n// CHECK:STDOUT:   .Zero = <poisoned>\n// CHECK:STDOUT:   extend @Point.as.Z.impl.%Z.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Z.WithSelf.Zero(@Z.%Self: %Z.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @<error>.as.Z.impl.Zero(@Z.%Self: %Z.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Point.as.Z.impl.Zero() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc25_5.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Point.ref: type = name_ref Point, file.%Point.decl [concrete = constants.%Point]\n// CHECK:STDOUT:   %.loc25_5.2: ref %Point = temporary_storage\n// CHECK:STDOUT:   %.loc25_5.3: init %Point to %.loc25_5.2 = class_init () [concrete = constants.%Point.val]\n// CHECK:STDOUT:   %.loc25_7.1: init %Point = converted %.loc25_5.1, %.loc25_5.3 [concrete = constants.%Point.val]\n// CHECK:STDOUT:   %.loc25_7.2: ref %Point = temporary %.loc25_5.2, %.loc25_7.1\n// CHECK:STDOUT:   %Zero.ref: %Z.assoc_type = name_ref Zero, @Z.WithSelf.%assoc0 [concrete = constants.%assoc0.cc0]\n// CHECK:STDOUT:   %impl.elem0: %.c1b = impl_witness_access constants.%Z.impl_witness, element0 [concrete = constants.%Point.as.Z.impl.Zero]\n// CHECK:STDOUT:   %Point.as.Z.impl.Zero.call: init %empty_tuple.type = call %impl.elem0()\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc25_7.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc25_7.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Point) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Self.c59) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.c59\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type => constants.%Z.WithSelf.Zero.type.e4a\n// CHECK:STDOUT:   %Z.WithSelf.Zero => constants.%Z.WithSelf.Zero.3f4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf.Zero(constants.%Self.c59) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @<error>.as.Z.impl(constants.%Self.c59) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.c59\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero.type => constants.%<error>.as.Z.impl.Zero.type\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero => constants.%<error>.as.Z.impl.Zero\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @<error>.as.Z.impl.Zero(constants.%Self.c59) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Z.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Z.facet\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type => constants.%Z.WithSelf.Zero.type.bb1\n// CHECK:STDOUT:   %Z.WithSelf.Zero => constants.%Z.WithSelf.Zero.22c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf.Zero(constants.%Z.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Point.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Point.type.facet\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type => constants.%Z.WithSelf.Zero.type.15e\n// CHECK:STDOUT:   %Z.WithSelf.Zero => constants.%Z.WithSelf.Zero.55b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_extend_impl_type_as.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_extend_impl_type_as.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_extend_impl_type_as.carbon\n\ninterface I {}\n\nclass C {\n  // CHECK:STDERR: fail_extend_impl_type_as.carbon:[[@LINE+4]]:3: error: cannot `extend` an `impl` with an explicit self type [ExtendImplSelfAs]\n  // CHECK:STDERR:   extend impl i32 as I {}\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR:\n  extend impl i32 as I {}\n}\n\nclass D {\n  // CHECK:STDERR: fail_extend_impl_type_as.carbon:[[@LINE+7]]:3: error: cannot `extend` an `impl` with an explicit self type [ExtendImplSelfAs]\n  // CHECK:STDERR:   extend impl D as I;\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR: fail_extend_impl_type_as.carbon:[[@LINE+4]]:15: note: remove the explicit `Self` type here [ExtendImplSelfAsDefault]\n  // CHECK:STDERR:   extend impl D as I;\n  // CHECK:STDERR:               ^\n  // CHECK:STDERR:\n  extend impl D as I;\n}\n\nclass E {\n  // CHECK:STDERR: fail_extend_impl_type_as.carbon:[[@LINE+11]]:3: error: cannot `extend` an `impl` with an explicit self type [ExtendImplSelfAs]\n  // CHECK:STDERR:   extend impl Self as I {}\n  // CHECK:STDERR:   ^~~~~~\n  // CHECK:STDERR: fail_extend_impl_type_as.carbon:[[@LINE+8]]:15: note: remove the explicit `Self` type here [ExtendImplSelfAsDefault]\n  // CHECK:STDERR:   extend impl Self as I {}\n  // CHECK:STDERR:               ^~~~\n  // CHECK:STDERR:\n  // CHECK:STDERR: fail_extend_impl_type_as.carbon:[[@LINE-11]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   extend impl D as I;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend impl Self as I {}\n}\n\n// CHECK:STDOUT: --- fail_extend_impl_type_as.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %E: type = class_type @E [concrete]\n// CHECK:STDOUT:   %I.impl_witness.1f6: <witness> = impl_witness @E.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %E, (%I.impl_witness.1f6) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .E = %E.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %E.decl: type = class_decl @E [concrete = constants.%E] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @<error>.as.I.impl: <error> as %I.ref {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @D.as.I.impl: %D.ref as %I.ref;\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @E.as.I.impl: %Self.ref as %I.ref {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @E.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.1f6]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   impl_decl @<error>.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   has_error\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   impl_decl @D.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT:   .D = <poisoned>\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   extend @D.as.I.impl.%I.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @E {\n// CHECK:STDOUT:   impl_decl @E.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%E [concrete = constants.%E]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%E\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   extend @E.as.I.impl.%I.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_extend_non_interface.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_extend_non_interface.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_extend_non_interface.carbon\n\nclass C {\n  // CHECK:STDERR: fail_extend_non_interface.carbon:[[@LINE+4]]:3: error: impl as non-facet type `i32` [ImplAsNonFacetType]\n  // CHECK:STDERR:   extend impl as i32;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend impl as i32;\n}\n\n// CHECK:STDOUT: --- fail_extend_non_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.<error>.impl: %Self.ref as %i32;\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   impl_decl @C.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   has_error\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_extend_partially_defined_interface.carbon\n\ninterface I {\n  class C {\n    // CHECK:STDERR: fail_extend_partially_defined_interface.carbon:[[@LINE+7]]:5: error: `extend impl as` incomplete facet type `I` [ExtendImplAsIncomplete]\n    // CHECK:STDERR:     extend impl as I;\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_extend_partially_defined_interface.carbon:[[@LINE-5]]:1: note: interface is currently being defined [InterfaceIncompleteWithinDefinition]\n    // CHECK:STDERR: interface I {\n    // CHECK:STDERR: ^~~~~~~~~~~~~\n    // CHECK:STDERR:\n    extend impl as I;\n  }\n}\n\n// CHECK:STDOUT: --- fail_extend_partially_defined_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%Self) [symbolic]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table, @C.as.I.impl(%Self) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [symbolic = @I.WithSelf.%C (constants.%C)] {} {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   .C = @I.WithSelf.%C.decl\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl(@I.%Self: %I.type) {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%Self) [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:   %I.impl_witness.loc24_21.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(%Self) [symbolic = %I.impl_witness.loc24_21.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %Self.ref as %I.ref;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(@I.%Self: %I.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:       %Self.ref: type = name_ref Self, constants.%C [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:       %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     has_error\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl(constants.%Self) {\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %C => constants.%C\n// CHECK:STDOUT:   %I.impl_witness.loc24_21.2 => constants.%I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_extend_undefined_interface.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_extend_undefined_interface.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_extend_undefined_interface.carbon\n\ninterface I;\n\nclass C {\n  // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE+7]]:3: error: `extend impl as` incomplete facet type `I` [ExtendImplAsIncomplete]\n  // CHECK:STDERR:   extend impl as I;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_extend_undefined_interface.carbon:[[@LINE-6]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]\n  // CHECK:STDERR: interface I;\n  // CHECK:STDERR: ^~~~~~~~~~~~\n  // CHECK:STDERR:\n  extend impl as I;\n}\n\nfn F(c: C) {\n  C.F();\n  c.F();\n}\n\n// CHECK:STDOUT: --- fail_extend_undefined_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %c.patt: %pattern_type = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc28: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I;\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %Self.ref as %I.ref;\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   has_error\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %C.ref.loc29: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref.loc29: <error> = name_ref F, <error> [concrete = <error>]\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %F.ref.loc30: <error> = name_ref F, <error> [concrete = <error>]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_impl_as_scope.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_impl_as_scope.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_impl_as_scope.carbon\n\n// --- fail_impl_as_file_scope.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\nfn G() {}\n\n// CHECK:STDERR: fail_impl_as_file_scope.carbon:[[@LINE+4]]:6: error: `impl as` can only be used in a class [ImplAsOutsideClass]\n// CHECK:STDERR: impl as I {}\n// CHECK:STDERR:      ^~\n// CHECK:STDERR:\nimpl as I {}\n\nfn F() { G(); }\n\n// --- fail_impl_as_function_scope.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface J {}\n\nfn G() {}\n\nfn F() {\n  // CHECK:STDERR: fail_impl_as_function_scope.carbon:[[@LINE+4]]:8: error: `impl as` can only be used in a class [ImplAsOutsideClass]\n  // CHECK:STDERR:   impl as J {}\n  // CHECK:STDERR:        ^~\n  // CHECK:STDERR:\n  impl as J {}\n  G();\n}\n\n// --- fail_impl_as_self_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Z {\n  fn Zero();\n  fn Method[self: Self]();\n\n   // CHECK:STDERR: fail_impl_as_self_interface.carbon:[[@LINE+4]]:9: error: `impl as` can only be used in a class [ImplAsOutsideClass]\n   // CHECK:STDERR:    impl as Z {\n   // CHECK:STDERR:         ^~\n   // CHECK:STDERR:\n   impl as Z {\n    fn Zero() {}\n    fn Method[unused self: Self]() {}\n  }\n}\n\nclass Point {\n   impl as Z {\n    fn Zero() {}\n    fn Method[unused self: Self]() {}\n  }\n}\n\nfn F() {\n  // Even if the `impl` is diagnosed above, we must not add the impl of the\n  // interface to itself in a way that allows it to be used during impl lookup,\n  // or we end up with infinite impl lookup recursion here.\n  Point.(Z.Zero)();\n  ({} as Point).(Z.Method)();\n}\n\n// --- fail_impl_as_other_interface.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A {\n  fn B();\n}\ninterface C {}\n\nfn G() {}\n\nclass X {\n  impl as A {\n    // CHECK:STDERR: fail_impl_as_other_interface.carbon:[[@LINE+4]]:10: error: `impl as` can only be used in a class [ImplAsOutsideClass]\n    // CHECK:STDERR:     impl as C {}\n    // CHECK:STDERR:          ^~\n    // CHECK:STDERR:\n    impl as C {}\n    fn B() {\n      G();\n    }\n  }\n}\n\n// CHECK:STDOUT: --- fail_impl_as_file_scope.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT:   impl_decl @<error>.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @<error>.as.I.impl: <error> as %I.ref {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_as_function_scope.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]\n// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .J = %J.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @J {\n// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %J.WithSelf.decl = interface_with_self_decl @J [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @<error>.as.J.impl: <error> as %J.ref {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   impl_decl @<error>.as.J.impl [concrete] {} {\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_as_self_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Z.type: type = facet_type <@Z> [concrete]\n// CHECK:STDOUT:   %Self.c59: %Z.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type.e4a: type = fn_type @Z.WithSelf.Zero, @Z.WithSelf(%Self.c59) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.3f4: %Z.WithSelf.Zero.type.e4a = struct_value () [symbolic]\n// CHECK:STDOUT:   %Z.assoc_type: type = assoc_entity_type @Z [concrete]\n// CHECK:STDOUT:   %assoc0.cc0: %Z.assoc_type = assoc_entity element0, @Z.WithSelf.%Z.WithSelf.Zero.decl [concrete]\n// CHECK:STDOUT:   %Self.binding.as_type.62d: type = symbolic_binding_type Self, 0, %Self.c59 [symbolic]\n// CHECK:STDOUT:   %pattern_type.84b: type = pattern_type %Self.binding.as_type.62d [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.Method.type.dfd: type = fn_type @Z.WithSelf.Method, @Z.WithSelf(%Self.c59) [symbolic]\n// CHECK:STDOUT:   %Z.WithSelf.Method.324: %Z.WithSelf.Method.type.dfd = struct_value () [symbolic]\n// CHECK:STDOUT:   %assoc1: %Z.assoc_type = assoc_entity element1, @Z.WithSelf.%Z.WithSelf.Method.decl [concrete]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero.type: type = fn_type @<error>.as.Z.impl.Zero, @<error>.as.Z.impl(%Self.c59) [symbolic]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero: %<error>.as.Z.impl.Zero.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Method.type: type = fn_type @<error>.as.Z.impl.Method, @<error>.as.Z.impl(%Self.c59) [symbolic]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Method: %<error>.as.Z.impl.Method.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Self.binding.as_type.62d [symbolic]\n// CHECK:STDOUT:   %Point: type = class_type @Point [concrete]\n// CHECK:STDOUT:   %Z.impl_witness: <witness> = impl_witness @Point.as.Z.impl.%Z.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Point.as.Z.impl.Zero.type: type = fn_type @Point.as.Z.impl.Zero [concrete]\n// CHECK:STDOUT:   %Point.as.Z.impl.Zero: %Point.as.Z.impl.Zero.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.c86: type = pattern_type %Point [concrete]\n// CHECK:STDOUT:   %Point.as.Z.impl.Method.type: type = fn_type @Point.as.Z.impl.Method [concrete]\n// CHECK:STDOUT:   %Point.as.Z.impl.Method: %Point.as.Z.impl.Method.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %Point, (%Z.impl_witness) [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type.949: type = fn_type @Z.WithSelf.Zero, @Z.WithSelf(%Z.facet) [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Zero.3ae: %Z.WithSelf.Zero.type.949 = struct_value () [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Method.type.707: type = fn_type @Z.WithSelf.Method, @Z.WithSelf(%Z.facet) [concrete]\n// CHECK:STDOUT:   %Z.WithSelf.Method.74d: %Z.WithSelf.Method.type.707 = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %.8c9: type = fn_type_with_self_type %Z.WithSelf.Zero.type.949, %Z.facet [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %Point.val: %Point = struct_value () [concrete]\n// CHECK:STDOUT:   %.429: type = fn_type_with_self_type %Z.WithSelf.Method.type.707, %Z.facet [concrete]\n// CHECK:STDOUT:   %Point.as.Z.impl.Method.bound: <bound method> = bound_method %Point.val, %Point.as.Z.impl.Method [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Z = %Z.decl\n// CHECK:STDOUT:     .Point = %Point.decl\n// CHECK:STDOUT:     .F = %F.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Z.decl: type = interface_decl @Z [concrete = constants.%Z.type] {} {}\n// CHECK:STDOUT:   %Point.decl: type = class_decl @Point [concrete = constants.%Point] {} {}\n// CHECK:STDOUT:   %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Z {\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c59]\n// CHECK:STDOUT:   %Z.WithSelf.decl = interface_with_self_decl @Z [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %Z.WithSelf.Zero.decl: @Z.WithSelf.%Z.WithSelf.Zero.type (%Z.WithSelf.Zero.type.e4a) = fn_decl @Z.WithSelf.Zero [symbolic = @Z.WithSelf.%Z.WithSelf.Zero (constants.%Z.WithSelf.Zero.3f4)] {} {}\n// CHECK:STDOUT:   %assoc0: %Z.assoc_type = assoc_entity element0, %Z.WithSelf.Zero.decl [concrete = constants.%assoc0.cc0]\n// CHECK:STDOUT:   %Z.WithSelf.Method.decl: @Z.WithSelf.%Z.WithSelf.Method.type (%Z.WithSelf.Method.type.dfd) = fn_decl @Z.WithSelf.Method [symbolic = @Z.WithSelf.%Z.WithSelf.Method (constants.%Z.WithSelf.Method.324)] {\n// CHECK:STDOUT:     %self.patt: @Z.WithSelf.Method.%pattern_type (%pattern_type.84b) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: @Z.WithSelf.Method.%pattern_type (%pattern_type.84b) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: @Z.WithSelf.Method.%Self.binding.as_type (%Self.binding.as_type.62d) = value_param call_param0\n// CHECK:STDOUT:     %.loc5_19.1: type = splice_block %.loc5_19.2 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.62d)] {\n// CHECK:STDOUT:       %Self.ref: %Z.type = name_ref Self, @Z.%Self [symbolic = %Self (constants.%Self.c59)]\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.62d)]\n// CHECK:STDOUT:       %.loc5_19.2: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.62d)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %self: @Z.WithSelf.Method.%Self.binding.as_type (%Self.binding.as_type.62d) = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %assoc1: %Z.assoc_type = assoc_entity element1, %Z.WithSelf.Method.decl [concrete = constants.%assoc1]\n// CHECK:STDOUT:   impl_decl @<error>.as.Z.impl [concrete] {} {\n// CHECK:STDOUT:     %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .Z = <poisoned>\n// CHECK:STDOUT:   .Zero = @Z.WithSelf.%assoc0\n// CHECK:STDOUT:   .Method = @Z.WithSelf.%assoc1\n// CHECK:STDOUT:   .Z = <poisoned>\n// CHECK:STDOUT:   witness = (@Z.WithSelf.%Z.WithSelf.Zero.decl, @Z.WithSelf.%Z.WithSelf.Method.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @<error>.as.Z.impl(@Z.%Self: %Z.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.c59)]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero.type: type = fn_type @<error>.as.Z.impl.Zero, @<error>.as.Z.impl(%Self) [symbolic = %<error>.as.Z.impl.Zero.type (constants.%<error>.as.Z.impl.Zero.type)]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero: @<error>.as.Z.impl.%<error>.as.Z.impl.Zero.type (%<error>.as.Z.impl.Zero.type) = struct_value () [symbolic = %<error>.as.Z.impl.Zero (constants.%<error>.as.Z.impl.Zero)]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Method.type: type = fn_type @<error>.as.Z.impl.Method, @<error>.as.Z.impl(%Self) [symbolic = %<error>.as.Z.impl.Method.type (constants.%<error>.as.Z.impl.Method.type)]\n// CHECK:STDOUT:   %<error>.as.Z.impl.Method: @<error>.as.Z.impl.%<error>.as.Z.impl.Method.type (%<error>.as.Z.impl.Method.type) = struct_value () [symbolic = %<error>.as.Z.impl.Method (constants.%<error>.as.Z.impl.Method)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: <error> as %Z.ref {\n// CHECK:STDOUT:     %<error>.as.Z.impl.Zero.decl: @<error>.as.Z.impl.%<error>.as.Z.impl.Zero.type (%<error>.as.Z.impl.Zero.type) = fn_decl @<error>.as.Z.impl.Zero [symbolic = @<error>.as.Z.impl.%<error>.as.Z.impl.Zero (constants.%<error>.as.Z.impl.Zero)] {} {}\n// CHECK:STDOUT:     %<error>.as.Z.impl.Method.decl: @<error>.as.Z.impl.%<error>.as.Z.impl.Method.type (%<error>.as.Z.impl.Method.type) = fn_decl @<error>.as.Z.impl.Method [symbolic = @<error>.as.Z.impl.%<error>.as.Z.impl.Method (constants.%<error>.as.Z.impl.Method)] {\n// CHECK:STDOUT:       %self.patt: @<error>.as.Z.impl.Method.%pattern_type (%pattern_type.84b) = value_binding_pattern self [concrete]\n// CHECK:STDOUT:       %self.param_patt: @<error>.as.Z.impl.Method.%pattern_type (%pattern_type.84b) = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %self.param: @<error>.as.Z.impl.Method.%Self.binding.as_type (%Self.binding.as_type.62d) = value_param call_param0\n// CHECK:STDOUT:       %.loc13_28.1: type = splice_block %.loc13_28.2 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.62d)] {\n// CHECK:STDOUT:         %Self.ref: %Z.type = name_ref Self, @Z.%Self [symbolic = %Self (constants.%Self.c59)]\n// CHECK:STDOUT:         %Self.as_type: type = facet_access_type %Self.ref [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.62d)]\n// CHECK:STDOUT:         %.loc13_28.2: type = converted %Self.ref, %Self.as_type [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.62d)]\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:       %self: @<error>.as.Z.impl.Method.%Self.binding.as_type (%Self.binding.as_type.62d) = value_binding self, %self.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Zero = %<error>.as.Z.impl.Zero.decl\n// CHECK:STDOUT:     .Method = %<error>.as.Z.impl.Method.decl\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @Point.as.Z.impl: %Self.ref as %Z.ref {\n// CHECK:STDOUT:   %Point.as.Z.impl.Zero.decl: %Point.as.Z.impl.Zero.type = fn_decl @Point.as.Z.impl.Zero [concrete = constants.%Point.as.Z.impl.Zero] {} {}\n// CHECK:STDOUT:   %Point.as.Z.impl.Method.decl: %Point.as.Z.impl.Method.type = fn_decl @Point.as.Z.impl.Method [concrete = constants.%Point.as.Z.impl.Method] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.c86 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.c86 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %Point = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Point [concrete = constants.%Point]\n// CHECK:STDOUT:     %self: %Point = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Z.impl_witness_table = impl_witness_table (%Point.as.Z.impl.Zero.decl, %Point.as.Z.impl.Method.decl), @Point.as.Z.impl [concrete]\n// CHECK:STDOUT:   %Z.impl_witness: <witness> = impl_witness %Z.impl_witness_table [concrete = constants.%Z.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Zero = %Point.as.Z.impl.Zero.decl\n// CHECK:STDOUT:   .Method = %Point.as.Z.impl.Method.decl\n// CHECK:STDOUT:   witness = %Z.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @Point {\n// CHECK:STDOUT:   impl_decl @Point.as.Z.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%Point [concrete = constants.%Point]\n// CHECK:STDOUT:     %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%Point\n// CHECK:STDOUT:   .Z = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Z.WithSelf.Zero(@Z.%Self: %Z.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Z.WithSelf.Method(@Z.%Self: %Z.type) {\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.c59)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.62d)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.84b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @Z.WithSelf.Method.%Self.binding.as_type (%Self.binding.as_type.62d));\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @<error>.as.Z.impl.Zero(@Z.%Self: %Z.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @<error>.as.Z.impl.Method(@Z.%Self: %Z.type) {\n// CHECK:STDOUT:   %Self: %Z.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.c59)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.62d)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %Self.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.84b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %Self.binding.as_type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%self.param: @<error>.as.Z.impl.Method.%Self.binding.as_type (%Self.binding.as_type.62d)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Point.as.Z.impl.Zero() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Point.as.Z.impl.Method(%self.param: %Point) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %Point.ref.loc28: type = name_ref Point, file.%Point.decl [concrete = constants.%Point]\n// CHECK:STDOUT:   %Z.ref.loc28: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:   %Zero.ref: %Z.assoc_type = name_ref Zero, @Z.WithSelf.%assoc0 [concrete = constants.%assoc0.cc0]\n// CHECK:STDOUT:   %Z.facet: %Z.type = facet_value %Point.ref.loc28, (constants.%Z.impl_witness) [concrete = constants.%Z.facet]\n// CHECK:STDOUT:   %.loc28: %Z.type = converted %Point.ref.loc28, %Z.facet [concrete = constants.%Z.facet]\n// CHECK:STDOUT:   %impl.elem0: %.8c9 = impl_witness_access constants.%Z.impl_witness, element0 [concrete = constants.%Point.as.Z.impl.Zero]\n// CHECK:STDOUT:   %Point.as.Z.impl.Zero.call: init %empty_tuple.type = call %impl.elem0()\n// CHECK:STDOUT:   %.loc29_5.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Point.ref.loc29: type = name_ref Point, file.%Point.decl [concrete = constants.%Point]\n// CHECK:STDOUT:   %.loc29_5.2: ref %Point = temporary_storage\n// CHECK:STDOUT:   %.loc29_5.3: init %Point to %.loc29_5.2 = class_init () [concrete = constants.%Point.val]\n// CHECK:STDOUT:   %.loc29_7.1: init %Point = converted %.loc29_5.1, %.loc29_5.3 [concrete = constants.%Point.val]\n// CHECK:STDOUT:   %Z.ref.loc29: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]\n// CHECK:STDOUT:   %Method.ref: %Z.assoc_type = name_ref Method, @Z.WithSelf.%assoc1 [concrete = constants.%assoc1]\n// CHECK:STDOUT:   %impl.elem1: %.429 = impl_witness_access constants.%Z.impl_witness, element1 [concrete = constants.%Point.as.Z.impl.Method]\n// CHECK:STDOUT:   %bound_method: <bound method> = bound_method %.loc29_7.1, %impl.elem1 [concrete = constants.%Point.as.Z.impl.Method.bound]\n// CHECK:STDOUT:   %.loc29_7.2: ref %Point = temporary %.loc29_5.2, %.loc29_7.1\n// CHECK:STDOUT:   %.loc29_7.3: %Point = acquire_value %.loc29_7.2\n// CHECK:STDOUT:   %Point.as.Z.impl.Method.call: init %empty_tuple.type = call %bound_method(%.loc29_7.3)\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %.loc29_7.2, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%.loc29_7.2)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %Point) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Self.c59) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.c59\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type => constants.%Z.WithSelf.Zero.type.e4a\n// CHECK:STDOUT:   %Z.WithSelf.Zero => constants.%Z.WithSelf.Zero.3f4\n// CHECK:STDOUT:   %Z.WithSelf.Method.type => constants.%Z.WithSelf.Method.type.dfd\n// CHECK:STDOUT:   %Z.WithSelf.Method => constants.%Z.WithSelf.Method.324\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf.Zero(constants.%Self.c59) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf.Method(constants.%Self.c59) {\n// CHECK:STDOUT:   %Self => constants.%Self.c59\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.62d\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.84b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @<error>.as.Z.impl(constants.%Self.c59) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.c59\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero.type => constants.%<error>.as.Z.impl.Zero.type\n// CHECK:STDOUT:   %<error>.as.Z.impl.Zero => constants.%<error>.as.Z.impl.Zero\n// CHECK:STDOUT:   %<error>.as.Z.impl.Method.type => constants.%<error>.as.Z.impl.Method.type\n// CHECK:STDOUT:   %<error>.as.Z.impl.Method => constants.%<error>.as.Z.impl.Method\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @<error>.as.Z.impl.Zero(constants.%Self.c59) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @<error>.as.Z.impl.Method(constants.%Self.c59) {\n// CHECK:STDOUT:   %Self => constants.%Self.c59\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.62d\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.84b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf(constants.%Z.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Z.facet\n// CHECK:STDOUT:   %Z.WithSelf.Zero.type => constants.%Z.WithSelf.Zero.type.949\n// CHECK:STDOUT:   %Z.WithSelf.Zero => constants.%Z.WithSelf.Zero.3ae\n// CHECK:STDOUT:   %Z.WithSelf.Method.type => constants.%Z.WithSelf.Method.type.707\n// CHECK:STDOUT:   %Z.WithSelf.Method => constants.%Z.WithSelf.Method.74d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf.Zero(constants.%Z.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Z.WithSelf.Method(constants.%Z.facet) {\n// CHECK:STDOUT:   %Self => constants.%Z.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Point\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.c86\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_as_other_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %A.type: type = facet_type <@A> [concrete]\n// CHECK:STDOUT:   %Self.c51: %A.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %A.WithSelf.B.type.386: type = fn_type @A.WithSelf.B, @A.WithSelf(%Self.c51) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %A.WithSelf.B.b88: %A.WithSelf.B.type.386 = struct_value () [symbolic]\n// CHECK:STDOUT:   %A.assoc_type: type = assoc_entity_type @A [concrete]\n// CHECK:STDOUT:   %assoc0: %A.assoc_type = assoc_entity element0, @A.WithSelf.%A.WithSelf.B.decl [concrete]\n// CHECK:STDOUT:   %C.type: type = facet_type <@C> [concrete]\n// CHECK:STDOUT:   %Self.b7c: %C.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %X: type = class_type @X [concrete]\n// CHECK:STDOUT:   %A.impl_witness: <witness> = impl_witness @X.as.A.impl.%A.impl_witness_table [concrete]\n// CHECK:STDOUT:   %X.as.A.impl.B.type: type = fn_type @X.as.A.impl.B [concrete]\n// CHECK:STDOUT:   %X.as.A.impl.B: %X.as.A.impl.B.type = struct_value () [concrete]\n// CHECK:STDOUT:   %A.facet: %A.type = facet_value %X, (%A.impl_witness) [concrete]\n// CHECK:STDOUT:   %A.WithSelf.B.type.c6b: type = fn_type @A.WithSelf.B, @A.WithSelf(%A.facet) [concrete]\n// CHECK:STDOUT:   %A.WithSelf.B.f2a: %A.WithSelf.B.type.c6b = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .A = %A.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:     .X = %X.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %A.decl: type = interface_decl @A [concrete = constants.%A.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = interface_decl @C [concrete = constants.%C.type] {} {}\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {} {}\n// CHECK:STDOUT:   %X.decl: type = class_decl @X [concrete = constants.%X] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @A {\n// CHECK:STDOUT:   %Self: %A.type = symbolic_binding Self, 0 [symbolic = constants.%Self.c51]\n// CHECK:STDOUT:   %A.WithSelf.decl = interface_with_self_decl @A [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %A.WithSelf.B.decl: @A.WithSelf.%A.WithSelf.B.type (%A.WithSelf.B.type.386) = fn_decl @A.WithSelf.B [symbolic = @A.WithSelf.%A.WithSelf.B (constants.%A.WithSelf.B.b88)] {} {}\n// CHECK:STDOUT:   %assoc0: %A.assoc_type = assoc_entity element0, %A.WithSelf.B.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .B = @A.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@A.WithSelf.%A.WithSelf.B.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @C {\n// CHECK:STDOUT:   %Self: %C.type = symbolic_binding Self, 0 [symbolic = constants.%Self.b7c]\n// CHECK:STDOUT:   %C.WithSelf.decl = interface_with_self_decl @C [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @X.as.A.impl: %Self.ref as %A.ref {\n// CHECK:STDOUT:   impl_decl @<error>.as.C.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %X.as.A.impl.B.decl: %X.as.A.impl.B.type = fn_decl @X.as.A.impl.B [concrete = constants.%X.as.A.impl.B] {} {}\n// CHECK:STDOUT:   %A.impl_witness_table = impl_witness_table (%X.as.A.impl.B.decl), @X.as.A.impl [concrete]\n// CHECK:STDOUT:   %A.impl_witness: <witness> = impl_witness %A.impl_witness_table [concrete = constants.%A.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT:   .B = %X.as.A.impl.B.decl\n// CHECK:STDOUT:   .G = <poisoned>\n// CHECK:STDOUT:   witness = %A.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @<error>.as.C.impl: <error> as %C.ref {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @X {\n// CHECK:STDOUT:   impl_decl @X.as.A.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%X [concrete = constants.%X]\n// CHECK:STDOUT:     %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%X\n// CHECK:STDOUT:   .A = <poisoned>\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT:   .G = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @A.WithSelf.B(@A.%Self: %A.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @X.as.A.impl.B() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl [concrete = constants.%G]\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.ref()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%Self.c51) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.c51\n// CHECK:STDOUT:   %A.WithSelf.B.type => constants.%A.WithSelf.B.type.386\n// CHECK:STDOUT:   %A.WithSelf.B => constants.%A.WithSelf.B.b88\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf.B(constants.%Self.c51) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.WithSelf(constants.%Self.b7c) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf(constants.%A.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%A.facet\n// CHECK:STDOUT:   %A.WithSelf.B.type => constants.%A.WithSelf.B.type.c6b\n// CHECK:STDOUT:   %A.WithSelf.B => constants.%A.WithSelf.B.f2a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @A.WithSelf.B(constants.%A.facet) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_impl_bad_assoc_const.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_impl_bad_assoc_const.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_impl_bad_assoc_const.carbon\n\ninterface I { let T:! type; }\n\n// CHECK:STDERR: fail_impl_bad_assoc_const.carbon:[[@LINE+7]]:1: error: associated constant T not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]\n// CHECK:STDERR: impl () as I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR: fail_impl_bad_assoc_const.carbon:[[@LINE-5]]:19: note: associated constant declared here [AssociatedConstantHere]\n// CHECK:STDERR: interface I { let T:! type; }\n// CHECK:STDERR:                   ^~~~~~~~\n// CHECK:STDERR:\nimpl () as I {}\n\n// CHECK:STDOUT: --- fail_impl_bad_assoc_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @empty_tuple.type.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %empty_tuple.type, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_tuple.type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc24_7.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc24_7.2: type = converted %.loc24_7.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %T: type = assoc_const_decl @T [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete = constants.%assoc0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .T = @T.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%T)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_tuple.type.as.I.impl: %.loc24_7.2 as %I.ref {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (<error>), @empty_tuple.type.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon\n\ninterface I { fn F(); }\n\nclass NoF {\n  // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:3: error: missing implementation of F in impl of interface I [ImplMissingFunction]\n  // CHECK:STDERR:   impl as I {}\n  // CHECK:STDERR:   ^~~~~~~~~~~\n  // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-6]]:15: note: associated function F declared here [AssociatedFunctionHere]\n  // CHECK:STDERR: interface I { fn F(); }\n  // CHECK:STDERR:               ^~~~~~~\n  // CHECK:STDERR:\n  impl as I {}\n}\n\nclass FNotFunction {\n  impl as I {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: associated function F implemented by non-function [ImplFunctionWithNonFunction]\n    // CHECK:STDERR:     class F;\n    // CHECK:STDERR:     ^~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-18]]:15: note: associated function F declared here [AssociatedFunctionHere]\n    // CHECK:STDERR: interface I { fn F(); }\n    // CHECK:STDERR:               ^~~~~~~\n    // CHECK:STDERR:\n    class F;\n  }\n}\n\nfn PossiblyF();\n\n// TODO: Should this be permitted?\nclass FAlias {\n  impl as I {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:11: error: associated function F implemented by non-function [ImplFunctionWithNonFunction]\n    // CHECK:STDERR:     alias F = PossiblyF;\n    // CHECK:STDERR:           ^\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-34]]:15: note: associated function F declared here [AssociatedFunctionHere]\n    // CHECK:STDERR: interface I { fn F(); }\n    // CHECK:STDERR:               ^~~~~~~\n    // CHECK:STDERR:\n    alias F = PossiblyF;\n  }\n}\n\nclass FExtraParam {\n  impl as I {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:5: error: 0 arguments passed to function expecting 1 argument [CallArgCountMismatch]\n    // CHECK:STDERR:     fn F(b: bool);\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: note: calling function declared here [InCallToEntity]\n    // CHECK:STDERR:     fn F(b: bool);\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-50]]:15: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR: interface I { fn F(); }\n    // CHECK:STDERR:               ^~~~~~~\n    // CHECK:STDERR:\n    fn F(b: bool);\n  }\n}\n\nclass FExtraImplicitParam {\n  impl as I {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:5: error: missing object argument in method call [MissingObjectInMethodCall]\n    // CHECK:STDERR:     fn F[self: Self]();\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: note: calling function declared here [InCallToFunction]\n    // CHECK:STDERR:     fn F[self: Self]();\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-66]]:15: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR: interface I { fn F(); }\n    // CHECK:STDERR:               ^~~~~~~\n    // CHECK:STDERR:\n    fn F[self: Self]();\n  }\n}\n\n// TODO: Should this be permitted?\nclass FExtraReturnType {\n  impl as I {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: function redeclaration differs because return type is `bool` [FunctionRedeclReturnTypeDiffers]\n    // CHECK:STDERR:     fn F() -> bool;\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-80]]:15: note: previously declared with no return type [FunctionRedeclReturnTypePreviousNoReturn]\n    // CHECK:STDERR: interface I { fn F(); }\n    // CHECK:STDERR:               ^~~~~~~\n    // CHECK:STDERR:\n    fn F() -> bool;\n  }\n}\n\ninterface J { fn F[self: bool](b: bool) -> bool; }\n\nclass FMissingParam {\n  impl as J {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:5: error: 1 argument passed to function expecting 0 arguments [CallArgCountMismatch]\n    // CHECK:STDERR:     fn F[self: bool]() -> bool;\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: note: calling function declared here [InCallToEntity]\n    // CHECK:STDERR:     fn F[self: bool]() -> bool;\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-10]]:15: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    fn F[self: bool]() -> bool;\n  }\n}\n\nclass FMissingImplicitParam {\n  impl as J {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: error: member name of type `<type of F>` in compound member access is not an instance member or an interface member [CompoundMemberAccessDoesNotUseBase]\n    // CHECK:STDERR:     fn F(b: bool) -> bool;\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-23]]:15: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    fn F(b: bool) -> bool;\n  }\n}\n\nclass FMissingReturnType {\n  impl as J {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+16]]:5: error: cannot implicitly convert expression of type `()` to `bool` [ConversionFailure]\n    // CHECK:STDERR:     fn F[self: bool](b: bool);\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+13]]:5: note: type `()` does not implement interface `Core.ImplicitAs(bool)` [MissingImplInMemberAccessInContext]\n    // CHECK:STDERR:     fn F[self: bool](b: bool);\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-39]]:15: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-43]]:32: error: cannot implicitly convert expression of type `bool` to `FDifferentParamType` [ConversionFailure]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:                                ^~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-46]]:32: note: type `bool` does not implement interface `Core.ImplicitAs(FDifferentParamType)` [MissingImplInMemberAccessInContext]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:                                ^~~~~~~\n    fn F[self: bool](b: bool);\n  }\n}\n\nclass FDifferentParamType {\n  impl as J {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+13]]:22: note: initializing function parameter [InCallToFunctionParam]\n    // CHECK:STDERR:     fn F[self: bool](b: Self) -> bool;\n    // CHECK:STDERR:                      ^~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-58]]:15: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-62]]:20: error: cannot implicitly convert expression of type `bool` to `FDifferentImplicitParamType` [ConversionFailure]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:                    ^~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-65]]:20: note: type `bool` does not implement interface `Core.ImplicitAs(FDifferentImplicitParamType)` [MissingImplInMemberAccessInContext]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:                    ^~~~~~~~~~\n    fn F[self: bool](b: Self) -> bool;\n  }\n}\n\nclass FDifferentImplicitParamType {\n  impl as J {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:10: note: initializing function parameter [InCallToFunctionParam]\n    // CHECK:STDERR:     fn F[self: Self](b: bool) -> bool;\n    // CHECK:STDERR:          ^~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-77]]:15: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    fn F[self: Self](b: bool) -> bool;\n  }\n}\n\nclass FDifferentReturnType {\n  impl as J {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:5: error: cannot implicitly convert expression of type `FDifferentReturnType` to `bool` [ConversionFailure]\n    // CHECK:STDERR:     fn F[self: bool](b: bool) -> Self;\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: note: type `FDifferentReturnType` does not implement interface `Core.ImplicitAs(bool)` [MissingImplInMemberAccessInContext]\n    // CHECK:STDERR:     fn F[self: bool](b: bool) -> Self;\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-93]]:15: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR: interface J { fn F[self: bool](b: bool) -> bool; }\n    // CHECK:STDERR:               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    fn F[self: bool](b: bool) -> Self;\n  }\n}\n\ninterface SelfNested {\n  // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+6]]:8: error: cannot implicitly convert expression of type `SelfNestedBadParam` to `i32` [ConversionFailure]\n  // CHECK:STDERR:   fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4);\n  // CHECK:STDERR:        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+3]]:8: note: type `SelfNestedBadParam` does not implement interface `Core.ImplicitAs(i32)` [MissingImplInMemberAccessInContext]\n  // CHECK:STDERR:   fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4);\n  // CHECK:STDERR:        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4);\n}\n\nclass SelfNestedBadParam {\n  impl as SelfNested {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:10: note: initializing function parameter [InCallToFunctionParam]\n    // CHECK:STDERR:     fn F(x: (SelfNestedBadParam*, {.x: i32, .y: i32})) -> array(SelfNestedBadParam, 4);\n    // CHECK:STDERR:          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-8]]:3: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR:   fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4);\n    // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    fn F(x: (SelfNestedBadParam*, {.x: i32, .y: i32})) -> array(SelfNestedBadParam, 4);\n  }\n}\n\nclass SelfNestedBadReturnType {\n  impl as SelfNested {\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+10]]:5: error: cannot implicitly convert expression of type `array(SelfNestedBadParam, 4)` to `array(SelfNestedBadReturnType, 4)` [ConversionFailure]\n    // CHECK:STDERR:     fn F(x: (SelfNestedBadReturnType*, {.x: SelfNestedBadReturnType, .y: i32})) -> array(SelfNestedBadParam, 4);\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+7]]:5: note: type `array(SelfNestedBadParam, 4)` does not implement interface `Core.ImplicitAs(array(SelfNestedBadReturnType, 4))` [MissingImplInMemberAccessInContext]\n    // CHECK:STDERR:     fn F(x: (SelfNestedBadReturnType*, {.x: SelfNestedBadReturnType, .y: i32})) -> array(SelfNestedBadParam, 4);\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-24]]:3: note: while building thunk to match the signature of this function [ThunkSignature]\n    // CHECK:STDERR:   fn F(x: (Self*, {.x: Self, .y: i32})) -> array(Self, 4);\n    // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    fn F(x: (SelfNestedBadReturnType*, {.x: SelfNestedBadReturnType, .y: i32})) -> array(SelfNestedBadParam, 4);\n  }\n}\n\n// CHECK:STDOUT: --- fail_impl_bad_assoc_fn.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.08c: type = fn_type @I.WithSelf.F, @I.WithSelf(%Self.ab9) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.705: %I.WithSelf.F.type.08c = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0.18e: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %NoF: type = class_type @NoF [concrete]\n// CHECK:STDOUT:   %I.impl_witness.187: <witness> = impl_witness @NoF.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet.fc8: %I.type = facet_value %NoF, (%I.impl_witness.187) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.cec: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet.fc8) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.733: %I.WithSelf.F.type.cec = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %FNotFunction: type = class_type @FNotFunction [concrete]\n// CHECK:STDOUT:   %I.impl_witness.cf4: <witness> = impl_witness @FNotFunction.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %F: type = class_type @F [concrete]\n// CHECK:STDOUT:   %I.facet.c1a: %I.type = facet_value %FNotFunction, (%I.impl_witness.cf4) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.1b8: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet.c1a) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.7e3: %I.WithSelf.F.type.1b8 = struct_value () [concrete]\n// CHECK:STDOUT:   %PossiblyF.type: type = fn_type @PossiblyF [concrete]\n// CHECK:STDOUT:   %PossiblyF: %PossiblyF.type = struct_value () [concrete]\n// CHECK:STDOUT:   %FAlias: type = class_type @FAlias [concrete]\n// CHECK:STDOUT:   %I.impl_witness.109: <witness> = impl_witness @FAlias.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet.574: %I.type = facet_value %FAlias, (%I.impl_witness.109) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.f26: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet.574) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.5e6: %I.WithSelf.F.type.f26 = struct_value () [concrete]\n// CHECK:STDOUT:   %FExtraParam: type = class_type @FExtraParam [concrete]\n// CHECK:STDOUT:   %I.impl_witness.627: <witness> = impl_witness @FExtraParam.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %pattern_type.831: type = pattern_type bool [concrete]\n// CHECK:STDOUT:   %FExtraParam.as.I.impl.F.type.531438.1: type = fn_type @FExtraParam.as.I.impl.F.loc69_18.1 [concrete]\n// CHECK:STDOUT:   %FExtraParam.as.I.impl.F.33e1fe.1: %FExtraParam.as.I.impl.F.type.531438.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.facet.b53: %I.type = facet_value %FExtraParam, (%I.impl_witness.627) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.99d: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet.b53) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.eab: %I.WithSelf.F.type.99d = struct_value () [concrete]\n// CHECK:STDOUT:   %FExtraParam.as.I.impl.F.type.531438.2: type = fn_type @FExtraParam.as.I.impl.F.loc69_18.2 [concrete]\n// CHECK:STDOUT:   %FExtraParam.as.I.impl.F.33e1fe.2: %FExtraParam.as.I.impl.F.type.531438.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %FExtraImplicitParam: type = class_type @FExtraImplicitParam [concrete]\n// CHECK:STDOUT:   %I.impl_witness.e9e: <witness> = impl_witness @FExtraImplicitParam.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.235: type = pattern_type %FExtraImplicitParam [concrete]\n// CHECK:STDOUT:   %FExtraImplicitParam.as.I.impl.F.type.9dd145.1: type = fn_type @FExtraImplicitParam.as.I.impl.F.loc85_23.1 [concrete]\n// CHECK:STDOUT:   %FExtraImplicitParam.as.I.impl.F.99eae8.1: %FExtraImplicitParam.as.I.impl.F.type.9dd145.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.facet.5a5: %I.type = facet_value %FExtraImplicitParam, (%I.impl_witness.e9e) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.e46: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet.5a5) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.5bc: %I.WithSelf.F.type.e46 = struct_value () [concrete]\n// CHECK:STDOUT:   %FExtraImplicitParam.as.I.impl.F.type.9dd145.2: type = fn_type @FExtraImplicitParam.as.I.impl.F.loc85_23.2 [concrete]\n// CHECK:STDOUT:   %FExtraImplicitParam.as.I.impl.F.99eae8.2: %FExtraImplicitParam.as.I.impl.F.type.9dd145.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %FExtraReturnType: type = class_type @FExtraReturnType [concrete]\n// CHECK:STDOUT:   %I.impl_witness.247: <witness> = impl_witness @FExtraReturnType.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %.f34: Core.Form = init_form bool [concrete]\n// CHECK:STDOUT:   %FExtraReturnType.as.I.impl.F.type: type = fn_type @FExtraReturnType.as.I.impl.F [concrete]\n// CHECK:STDOUT:   %FExtraReturnType.as.I.impl.F: %FExtraReturnType.as.I.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.facet.1ed: %I.type = facet_value %FExtraReturnType, (%I.impl_witness.247) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.cd5: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet.1ed) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.aee: %I.WithSelf.F.type.cd5 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]\n// CHECK:STDOUT:   %Self.8a1: %J.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %J.WithSelf.F.type.adb: type = fn_type @J.WithSelf.F, @J.WithSelf(%Self.8a1) [symbolic]\n// CHECK:STDOUT:   %J.WithSelf.F.569: %J.WithSelf.F.type.adb = struct_value () [symbolic]\n// CHECK:STDOUT:   %J.assoc_type: type = assoc_entity_type @J [concrete]\n// CHECK:STDOUT:   %assoc0.481: %J.assoc_type = assoc_entity element0, @J.WithSelf.%J.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %FMissingParam: type = class_type @FMissingParam [concrete]\n// CHECK:STDOUT:   %J.impl_witness.5e2: <witness> = impl_witness @FMissingParam.as.J.impl.%J.impl_witness_table [concrete]\n// CHECK:STDOUT:   %FMissingParam.as.J.impl.F.type.0f71d8.1: type = fn_type @FMissingParam.as.J.impl.F.loc117_31.1 [concrete]\n// CHECK:STDOUT:   %FMissingParam.as.J.impl.F.7540f6.1: %FMissingParam.as.J.impl.F.type.0f71d8.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.facet.567: %J.type = facet_value %FMissingParam, (%J.impl_witness.5e2) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.type.54f: type = fn_type @J.WithSelf.F, @J.WithSelf(%J.facet.567) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.7e8: %J.WithSelf.F.type.54f = struct_value () [concrete]\n// CHECK:STDOUT:   %FMissingParam.as.J.impl.F.type.0f71d8.2: type = fn_type @FMissingParam.as.J.impl.F.loc117_31.2 [concrete]\n// CHECK:STDOUT:   %FMissingParam.as.J.impl.F.7540f6.2: %FMissingParam.as.J.impl.F.type.0f71d8.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %FMissingImplicitParam: type = class_type @FMissingImplicitParam [concrete]\n// CHECK:STDOUT:   %J.impl_witness.1e4: <witness> = impl_witness @FMissingImplicitParam.as.J.impl.%J.impl_witness_table [concrete]\n// CHECK:STDOUT:   %FMissingImplicitParam.as.J.impl.F.type.80a56b.1: type = fn_type @FMissingImplicitParam.as.J.impl.F.loc130_26.1 [concrete]\n// CHECK:STDOUT:   %FMissingImplicitParam.as.J.impl.F.c6a0b7.1: %FMissingImplicitParam.as.J.impl.F.type.80a56b.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.facet.266: %J.type = facet_value %FMissingImplicitParam, (%J.impl_witness.1e4) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.type.56e: type = fn_type @J.WithSelf.F, @J.WithSelf(%J.facet.266) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.d17: %J.WithSelf.F.type.56e = struct_value () [concrete]\n// CHECK:STDOUT:   %FMissingImplicitParam.as.J.impl.F.type.80a56b.2: type = fn_type @FMissingImplicitParam.as.J.impl.F.loc130_26.2 [concrete]\n// CHECK:STDOUT:   %FMissingImplicitParam.as.J.impl.F.c6a0b7.2: %FMissingImplicitParam.as.J.impl.F.type.80a56b.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %FMissingReturnType: type = class_type @FMissingReturnType [concrete]\n// CHECK:STDOUT:   %J.impl_witness.7c7: <witness> = impl_witness @FMissingReturnType.as.J.impl.%J.impl_witness_table [concrete]\n// CHECK:STDOUT:   %FMissingReturnType.as.J.impl.F.type.ce0d21.1: type = fn_type @FMissingReturnType.as.J.impl.F.loc152_30.1 [concrete]\n// CHECK:STDOUT:   %FMissingReturnType.as.J.impl.F.5b613a.1: %FMissingReturnType.as.J.impl.F.type.ce0d21.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.facet.a9e: %J.type = facet_value %FMissingReturnType, (%J.impl_witness.7c7) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.type.8be: type = fn_type @J.WithSelf.F, @J.WithSelf(%J.facet.a9e) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.2a5: %J.WithSelf.F.type.8be = struct_value () [concrete]\n// CHECK:STDOUT:   %FMissingReturnType.as.J.impl.F.type.ce0d21.2: type = fn_type @FMissingReturnType.as.J.impl.F.loc152_30.2 [concrete]\n// CHECK:STDOUT:   %FMissingReturnType.as.J.impl.F.5b613a.2: %FMissingReturnType.as.J.impl.F.type.ce0d21.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %FDifferentParamType: type = class_type @FDifferentParamType [concrete]\n// CHECK:STDOUT:   %J.impl_witness.cd7: <witness> = impl_witness @FDifferentParamType.as.J.impl.%J.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.b79: type = pattern_type %FDifferentParamType [concrete]\n// CHECK:STDOUT:   %FDifferentParamType.as.J.impl.F.type.10926d.1: type = fn_type @FDifferentParamType.as.J.impl.F.loc171_38.1 [concrete]\n// CHECK:STDOUT:   %FDifferentParamType.as.J.impl.F.f1245a.1: %FDifferentParamType.as.J.impl.F.type.10926d.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.facet.bd2: %J.type = facet_value %FDifferentParamType, (%J.impl_witness.cd7) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.type.06a: type = fn_type @J.WithSelf.F, @J.WithSelf(%J.facet.bd2) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.cad: %J.WithSelf.F.type.06a = struct_value () [concrete]\n// CHECK:STDOUT:   %FDifferentParamType.as.J.impl.F.type.10926d.2: type = fn_type @FDifferentParamType.as.J.impl.F.loc171_38.2 [concrete]\n// CHECK:STDOUT:   %FDifferentParamType.as.J.impl.F.f1245a.2: %FDifferentParamType.as.J.impl.F.type.10926d.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %FDifferentImplicitParamType: type = class_type @FDifferentImplicitParamType [concrete]\n// CHECK:STDOUT:   %J.impl_witness.4d2: <witness> = impl_witness @FDifferentImplicitParamType.as.J.impl.%J.impl_witness_table [concrete]\n// CHECK:STDOUT:   %pattern_type.b8f: type = pattern_type %FDifferentImplicitParamType [concrete]\n// CHECK:STDOUT:   %FDifferentImplicitParamType.as.J.impl.F.type.955391.1: type = fn_type @FDifferentImplicitParamType.as.J.impl.F.loc184_38.1 [concrete]\n// CHECK:STDOUT:   %FDifferentImplicitParamType.as.J.impl.F.a9ece4.1: %FDifferentImplicitParamType.as.J.impl.F.type.955391.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.facet.030: %J.type = facet_value %FDifferentImplicitParamType, (%J.impl_witness.4d2) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.type.f29: type = fn_type @J.WithSelf.F, @J.WithSelf(%J.facet.030) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.5b7: %J.WithSelf.F.type.f29 = struct_value () [concrete]\n// CHECK:STDOUT:   %FDifferentImplicitParamType.as.J.impl.F.type.955391.2: type = fn_type @FDifferentImplicitParamType.as.J.impl.F.loc184_38.2 [concrete]\n// CHECK:STDOUT:   %FDifferentImplicitParamType.as.J.impl.F.a9ece4.2: %FDifferentImplicitParamType.as.J.impl.F.type.955391.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %FDifferentReturnType: type = class_type @FDifferentReturnType [concrete]\n// CHECK:STDOUT:   %J.impl_witness.a49: <witness> = impl_witness @FDifferentReturnType.as.J.impl.%J.impl_witness_table [concrete]\n// CHECK:STDOUT:   %.2a9: Core.Form = init_form %FDifferentReturnType [concrete]\n// CHECK:STDOUT:   %pattern_type.5c8: type = pattern_type %FDifferentReturnType [concrete]\n// CHECK:STDOUT:   %FDifferentReturnType.as.J.impl.F.type.7bcb67.1: type = fn_type @FDifferentReturnType.as.J.impl.F.loc200_38.1 [concrete]\n// CHECK:STDOUT:   %FDifferentReturnType.as.J.impl.F.a709b1.1: %FDifferentReturnType.as.J.impl.F.type.7bcb67.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.facet.4a1: %J.type = facet_value %FDifferentReturnType, (%J.impl_witness.a49) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.type.8e3: type = fn_type @J.WithSelf.F, @J.WithSelf(%J.facet.4a1) [concrete]\n// CHECK:STDOUT:   %J.WithSelf.F.182: %J.WithSelf.F.type.8e3 = struct_value () [concrete]\n// CHECK:STDOUT:   %FDifferentReturnType.as.J.impl.F.type.7bcb67.2: type = fn_type @FDifferentReturnType.as.J.impl.F.loc200_38.2 [concrete]\n// CHECK:STDOUT:   %FDifferentReturnType.as.J.impl.F.a709b1.2: %FDifferentReturnType.as.J.impl.F.type.7bcb67.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %SelfNested.type: type = facet_type <@SelfNested> [concrete]\n// CHECK:STDOUT:   %Self.aed: %SelfNested.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type.07b: type = symbolic_binding_type Self, 0, %Self.aed [symbolic]\n// CHECK:STDOUT:   %ptr.d99: type = ptr_type %Self.binding.as_type.07b [symbolic]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %struct_type.x.y.e05: type = struct_type {.x: %Self.binding.as_type.07b, .y: %i32} [symbolic]\n// CHECK:STDOUT:   %tuple.type.24b: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple.179: %tuple.type.24b = tuple_value (%ptr.d99, %struct_type.x.y.e05) [symbolic]\n// CHECK:STDOUT:   %tuple.type.9cf: type = tuple_type (%ptr.d99, %struct_type.x.y.e05) [symbolic]\n// CHECK:STDOUT:   %pattern_type.37a: type = pattern_type %tuple.type.9cf [symbolic]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %array_type.eba: type = array_type %int_4, %Self.binding.as_type.07b [symbolic]\n// CHECK:STDOUT:   %.efe: Core.Form = init_form %array_type.eba [symbolic]\n// CHECK:STDOUT:   %pattern_type.dfe: type = pattern_type %array_type.eba [symbolic]\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.type.430: type = fn_type @SelfNested.WithSelf.F, @SelfNested.WithSelf(%Self.aed) [symbolic]\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.257: %SelfNested.WithSelf.F.type.430 = struct_value () [symbolic]\n// CHECK:STDOUT:   %SelfNested.assoc_type: type = assoc_entity_type @SelfNested [concrete]\n// CHECK:STDOUT:   %assoc0.da4: %SelfNested.assoc_type = assoc_entity element0, @SelfNested.WithSelf.%SelfNested.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %SelfNestedBadParam: type = class_type @SelfNestedBadParam [concrete]\n// CHECK:STDOUT:   %SelfNested.impl_witness.7e8: <witness> = impl_witness @SelfNestedBadParam.as.SelfNested.impl.%SelfNested.impl_witness_table [concrete]\n// CHECK:STDOUT:   %ptr.cf2: type = ptr_type %SelfNestedBadParam [concrete]\n// CHECK:STDOUT:   %struct_type.x.y.871: type = struct_type {.x: %i32, .y: %i32} [concrete]\n// CHECK:STDOUT:   %tuple.bb3: %tuple.type.24b = tuple_value (%ptr.cf2, %struct_type.x.y.871) [concrete]\n// CHECK:STDOUT:   %tuple.type.70f: type = tuple_type (%ptr.cf2, %struct_type.x.y.871) [concrete]\n// CHECK:STDOUT:   %pattern_type.395: type = pattern_type %tuple.type.70f [concrete]\n// CHECK:STDOUT:   %array_type.388: type = array_type %int_4, %SelfNestedBadParam [concrete]\n// CHECK:STDOUT:   %.0cb: Core.Form = init_form %array_type.388 [concrete]\n// CHECK:STDOUT:   %pattern_type.ec1: type = pattern_type %array_type.388 [concrete]\n// CHECK:STDOUT:   %SelfNestedBadParam.as.SelfNested.impl.F.type.789632.1: type = fn_type @SelfNestedBadParam.as.SelfNested.impl.F.loc223_87.1 [concrete]\n// CHECK:STDOUT:   %SelfNestedBadParam.as.SelfNested.impl.F.6e1661.1: %SelfNestedBadParam.as.SelfNested.impl.F.type.789632.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %SelfNested.facet.b9f: %SelfNested.type = facet_value %SelfNestedBadParam, (%SelfNested.impl_witness.7e8) [concrete]\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.type.4de: type = fn_type @SelfNested.WithSelf.F, @SelfNested.WithSelf(%SelfNested.facet.b9f) [concrete]\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.5e9: %SelfNested.WithSelf.F.type.4de = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.x.y.62a: type = struct_type {.x: %SelfNestedBadParam, .y: %i32} [concrete]\n// CHECK:STDOUT:   %tuple.73b: %tuple.type.24b = tuple_value (%ptr.cf2, %struct_type.x.y.62a) [concrete]\n// CHECK:STDOUT:   %tuple.type.7ea: type = tuple_type (%ptr.cf2, %struct_type.x.y.62a) [concrete]\n// CHECK:STDOUT:   %pattern_type.8d7: type = pattern_type %tuple.type.7ea [concrete]\n// CHECK:STDOUT:   %SelfNestedBadParam.as.SelfNested.impl.F.type.789632.2: type = fn_type @SelfNestedBadParam.as.SelfNested.impl.F.loc223_87.2 [concrete]\n// CHECK:STDOUT:   %SelfNestedBadParam.as.SelfNested.impl.F.6e1661.2: %SelfNestedBadParam.as.SelfNested.impl.F.type.789632.2 = struct_value () [concrete]\n// CHECK:STDOUT:   %SelfNestedBadReturnType: type = class_type @SelfNestedBadReturnType [concrete]\n// CHECK:STDOUT:   %SelfNested.impl_witness.d9c: <witness> = impl_witness @SelfNestedBadReturnType.as.SelfNested.impl.%SelfNested.impl_witness_table [concrete]\n// CHECK:STDOUT:   %ptr.cbe: type = ptr_type %SelfNestedBadReturnType [concrete]\n// CHECK:STDOUT:   %struct_type.x.y.cfa: type = struct_type {.x: %SelfNestedBadReturnType, .y: %i32} [concrete]\n// CHECK:STDOUT:   %tuple.c42: %tuple.type.24b = tuple_value (%ptr.cbe, %struct_type.x.y.cfa) [concrete]\n// CHECK:STDOUT:   %tuple.type.064: type = tuple_type (%ptr.cbe, %struct_type.x.y.cfa) [concrete]\n// CHECK:STDOUT:   %pattern_type.1f1: type = pattern_type %tuple.type.064 [concrete]\n// CHECK:STDOUT:   %SelfNestedBadReturnType.as.SelfNested.impl.F.type.75d128.1: type = fn_type @SelfNestedBadReturnType.as.SelfNested.impl.F.loc239_112.1 [concrete]\n// CHECK:STDOUT:   %SelfNestedBadReturnType.as.SelfNested.impl.F.587f77.1: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.75d128.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %SelfNested.facet.23f: %SelfNested.type = facet_value %SelfNestedBadReturnType, (%SelfNested.impl_witness.d9c) [concrete]\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.type.156: type = fn_type @SelfNested.WithSelf.F, @SelfNested.WithSelf(%SelfNested.facet.23f) [concrete]\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.edc: %SelfNested.WithSelf.F.type.156 = struct_value () [concrete]\n// CHECK:STDOUT:   %array_type.31b: type = array_type %int_4, %SelfNestedBadReturnType [concrete]\n// CHECK:STDOUT:   %.369: Core.Form = init_form %array_type.31b [concrete]\n// CHECK:STDOUT:   %pattern_type.1fd: type = pattern_type %array_type.31b [concrete]\n// CHECK:STDOUT:   %SelfNestedBadReturnType.as.SelfNested.impl.F.type.75d128.2: type = fn_type @SelfNestedBadReturnType.as.SelfNested.impl.F.loc239_112.2 [concrete]\n// CHECK:STDOUT:   %SelfNestedBadReturnType.as.SelfNested.impl.F.587f77.2: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.75d128.2 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .NoF = %NoF.decl\n// CHECK:STDOUT:     .FNotFunction = %FNotFunction.decl\n// CHECK:STDOUT:     .PossiblyF = %PossiblyF.decl\n// CHECK:STDOUT:     .FAlias = %FAlias.decl\n// CHECK:STDOUT:     .FExtraParam = %FExtraParam.decl\n// CHECK:STDOUT:     .FExtraImplicitParam = %FExtraImplicitParam.decl\n// CHECK:STDOUT:     .FExtraReturnType = %FExtraReturnType.decl\n// CHECK:STDOUT:     .J = %J.decl\n// CHECK:STDOUT:     .FMissingParam = %FMissingParam.decl\n// CHECK:STDOUT:     .FMissingImplicitParam = %FMissingImplicitParam.decl\n// CHECK:STDOUT:     .FMissingReturnType = %FMissingReturnType.decl\n// CHECK:STDOUT:     .FDifferentParamType = %FDifferentParamType.decl\n// CHECK:STDOUT:     .FDifferentImplicitParamType = %FDifferentImplicitParamType.decl\n// CHECK:STDOUT:     .FDifferentReturnType = %FDifferentReturnType.decl\n// CHECK:STDOUT:     .SelfNested = %SelfNested.decl\n// CHECK:STDOUT:     .SelfNestedBadParam = %SelfNestedBadParam.decl\n// CHECK:STDOUT:     .SelfNestedBadReturnType = %SelfNestedBadReturnType.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %NoF.decl: type = class_decl @NoF [concrete = constants.%NoF] {} {}\n// CHECK:STDOUT:   %FNotFunction.decl: type = class_decl @FNotFunction [concrete = constants.%FNotFunction] {} {}\n// CHECK:STDOUT:   %PossiblyF.decl: %PossiblyF.type = fn_decl @PossiblyF [concrete = constants.%PossiblyF] {} {}\n// CHECK:STDOUT:   %FAlias.decl: type = class_decl @FAlias [concrete = constants.%FAlias] {} {}\n// CHECK:STDOUT:   %FExtraParam.decl: type = class_decl @FExtraParam [concrete = constants.%FExtraParam] {} {}\n// CHECK:STDOUT:   %FExtraImplicitParam.decl: type = class_decl @FExtraImplicitParam [concrete = constants.%FExtraImplicitParam] {} {}\n// CHECK:STDOUT:   %FExtraReturnType.decl: type = class_decl @FExtraReturnType [concrete = constants.%FExtraReturnType] {} {}\n// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}\n// CHECK:STDOUT:   %FMissingParam.decl: type = class_decl @FMissingParam [concrete = constants.%FMissingParam] {} {}\n// CHECK:STDOUT:   %FMissingImplicitParam.decl: type = class_decl @FMissingImplicitParam [concrete = constants.%FMissingImplicitParam] {} {}\n// CHECK:STDOUT:   %FMissingReturnType.decl: type = class_decl @FMissingReturnType [concrete = constants.%FMissingReturnType] {} {}\n// CHECK:STDOUT:   %FDifferentParamType.decl: type = class_decl @FDifferentParamType [concrete = constants.%FDifferentParamType] {} {}\n// CHECK:STDOUT:   %FDifferentImplicitParamType.decl: type = class_decl @FDifferentImplicitParamType [concrete = constants.%FDifferentImplicitParamType] {} {}\n// CHECK:STDOUT:   %FDifferentReturnType.decl: type = class_decl @FDifferentReturnType [concrete = constants.%FDifferentReturnType] {} {}\n// CHECK:STDOUT:   %SelfNested.decl: type = interface_decl @SelfNested [concrete = constants.%SelfNested.type] {} {}\n// CHECK:STDOUT:   %SelfNestedBadParam.decl: type = class_decl @SelfNestedBadParam [concrete = constants.%SelfNestedBadParam] {} {}\n// CHECK:STDOUT:   %SelfNestedBadReturnType.decl: type = class_decl @SelfNestedBadReturnType [concrete = constants.%SelfNestedBadReturnType] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %I.WithSelf.F.decl: @I.WithSelf.%I.WithSelf.F.type (%I.WithSelf.F.type.08c) = fn_decl @I.WithSelf.F [symbolic = @I.WithSelf.%I.WithSelf.F (constants.%I.WithSelf.F.705)] {} {}\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, %I.WithSelf.F.decl [concrete = constants.%assoc0.18e]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F = @I.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%I.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @J {\n// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self.8a1]\n// CHECK:STDOUT:   %J.WithSelf.decl = interface_with_self_decl @J [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %J.WithSelf.F.decl: @J.WithSelf.%J.WithSelf.F.type (%J.WithSelf.F.type.adb) = fn_decl @J.WithSelf.F [symbolic = @J.WithSelf.%J.WithSelf.F (constants.%J.WithSelf.F.569)] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc103_44.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc103_44.2: Core.Form = init_form %.loc103_44.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc103_26: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %.loc103_35: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param2\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %assoc0: %J.assoc_type = assoc_entity element0, %J.WithSelf.F.decl [concrete = constants.%assoc0.481]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F = @J.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@J.WithSelf.%J.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @SelfNested {\n// CHECK:STDOUT:   %Self: %SelfNested.type = symbolic_binding Self, 0 [symbolic = constants.%Self.aed]\n// CHECK:STDOUT:   %SelfNested.WithSelf.decl = interface_with_self_decl @SelfNested [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.decl: @SelfNested.WithSelf.%SelfNested.WithSelf.F.type (%SelfNested.WithSelf.F.type.430) = fn_decl @SelfNested.WithSelf.F [symbolic = @SelfNested.WithSelf.%SelfNested.WithSelf.F (constants.%SelfNested.WithSelf.F.257)] {\n// CHECK:STDOUT:     %x.patt: @SelfNested.WithSelf.F.%pattern_type.loc211_8 (%pattern_type.37a) = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: @SelfNested.WithSelf.F.%pattern_type.loc211_8 (%pattern_type.37a) = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: @SelfNested.WithSelf.F.%pattern_type.loc211_41 (%pattern_type.dfe) = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: @SelfNested.WithSelf.F.%pattern_type.loc211_41 (%pattern_type.dfe) = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Self.ref.loc211_50: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.aed)]\n// CHECK:STDOUT:     %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4]\n// CHECK:STDOUT:     %Self.as_type.loc211_50: type = facet_access_type %Self.ref.loc211_50 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.07b)]\n// CHECK:STDOUT:     %.loc211_50: type = converted %Self.ref.loc211_50, %Self.as_type.loc211_50 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.07b)]\n// CHECK:STDOUT:     %array_type.loc211_57.2: type = array_type %int_4, %.loc211_50 [symbolic = %array_type.loc211_57.1 (constants.%array_type.eba)]\n// CHECK:STDOUT:     %.loc211_57.2: Core.Form = init_form %array_type.loc211_57.2 [symbolic = %.loc211_57.1 (constants.%.efe)]\n// CHECK:STDOUT:     %x.param: @SelfNested.WithSelf.F.%tuple.type (%tuple.type.9cf) = value_param call_param0\n// CHECK:STDOUT:     %.loc211_38.1: type = splice_block %.loc211_38.3 [symbolic = %tuple.type (constants.%tuple.type.9cf)] {\n// CHECK:STDOUT:       %Self.ref.loc211_12: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.aed)]\n// CHECK:STDOUT:       %Self.as_type.loc211_16: type = facet_access_type %Self.ref.loc211_12 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.07b)]\n// CHECK:STDOUT:       %.loc211_16: type = converted %Self.ref.loc211_12, %Self.as_type.loc211_16 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.07b)]\n// CHECK:STDOUT:       %ptr.loc211_16.2: type = ptr_type %.loc211_16 [symbolic = %ptr.loc211_16.1 (constants.%ptr.d99)]\n// CHECK:STDOUT:       %Self.ref.loc211_24: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.aed)]\n// CHECK:STDOUT:       %Self.as_type.loc211_24: type = facet_access_type %Self.ref.loc211_24 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.07b)]\n// CHECK:STDOUT:       %.loc211_24: type = converted %Self.ref.loc211_24, %Self.as_type.loc211_24 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.07b)]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.x.y.loc211_37.2: type = struct_type {.x: @SelfNested.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.07b), .y: %i32} [symbolic = %struct_type.x.y.loc211_37.1 (constants.%struct_type.x.y.e05)]\n// CHECK:STDOUT:       %.loc211_38.2: %tuple.type.24b = tuple_literal (%ptr.loc211_16.2, %struct_type.x.y.loc211_37.2) [symbolic = %tuple (constants.%tuple.179)]\n// CHECK:STDOUT:       %.loc211_38.3: type = converted %.loc211_38.2, constants.%tuple.type.9cf [symbolic = %tuple.type (constants.%tuple.type.9cf)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: @SelfNested.WithSelf.F.%tuple.type (%tuple.type.9cf) = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref @SelfNested.WithSelf.F.%array_type.loc211_57.1 (%array_type.eba) = out_param call_param1\n// CHECK:STDOUT:     %return: ref @SelfNested.WithSelf.F.%array_type.loc211_57.1 (%array_type.eba) = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %assoc0: %SelfNested.assoc_type = assoc_entity element0, %SelfNested.WithSelf.F.decl [concrete = constants.%assoc0.da4]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F = @SelfNested.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@SelfNested.WithSelf.%SelfNested.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @NoF.as.I.impl: %Self.ref as %I.ref {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (<error>), @NoF.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.187]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FNotFunction.as.I.impl: %Self.ref as %I.ref {\n// CHECK:STDOUT:   %F.decl: type = class_decl @F [concrete = constants.%F] {} {}\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (<error>), @FNotFunction.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.cf4]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %F.decl\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FAlias.as.I.impl: %Self.ref as %I.ref {\n// CHECK:STDOUT:   %PossiblyF.ref: %PossiblyF.type = name_ref PossiblyF, file.%PossiblyF.decl [concrete = constants.%PossiblyF]\n// CHECK:STDOUT:   %F: %PossiblyF.type = alias_binding F, file.%PossiblyF.decl [concrete = constants.%PossiblyF]\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (<error>), @FAlias.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.109]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .PossiblyF = <poisoned>\n// CHECK:STDOUT:   .F = %F\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FExtraParam.as.I.impl: %Self.ref as %I.ref {\n// CHECK:STDOUT:   %FExtraParam.as.I.impl.F.decl.loc69_18.1: %FExtraParam.as.I.impl.F.type.531438.1 = fn_decl @FExtraParam.as.I.impl.F.loc69_18.1 [concrete = constants.%FExtraParam.as.I.impl.F.33e1fe.1] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %b.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc69: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %FExtraParam.as.I.impl.F.decl.loc69_18.2: %FExtraParam.as.I.impl.F.type.531438.2 = fn_decl @FExtraParam.as.I.impl.F.loc69_18.2 [concrete = constants.%FExtraParam.as.I.impl.F.33e1fe.2] {} {}\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%FExtraParam.as.I.impl.F.decl.loc69_18.2), @FExtraParam.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.627]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %FExtraParam.as.I.impl.F.decl.loc69_18.1\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FExtraImplicitParam.as.I.impl: %Self.ref as %I.ref {\n// CHECK:STDOUT:   %FExtraImplicitParam.as.I.impl.F.decl.loc85_23.1: %FExtraImplicitParam.as.I.impl.F.type.9dd145.1 = fn_decl @FExtraImplicitParam.as.I.impl.F.loc85_23.1 [concrete = constants.%FExtraImplicitParam.as.I.impl.F.99eae8.1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.235 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.235 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: %FExtraImplicitParam = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FExtraImplicitParam [concrete = constants.%FExtraImplicitParam]\n// CHECK:STDOUT:     %self: %FExtraImplicitParam = value_binding self, %self.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %FExtraImplicitParam.as.I.impl.F.decl.loc85_23.2: %FExtraImplicitParam.as.I.impl.F.type.9dd145.2 = fn_decl @FExtraImplicitParam.as.I.impl.F.loc85_23.2 [concrete = constants.%FExtraImplicitParam.as.I.impl.F.99eae8.2] {} {}\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%FExtraImplicitParam.as.I.impl.F.decl.loc85_23.2), @FExtraImplicitParam.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.e9e]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %FExtraImplicitParam.as.I.impl.F.decl.loc85_23.1\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FExtraReturnType.as.I.impl: %Self.ref as %I.ref {\n// CHECK:STDOUT:   %FExtraReturnType.as.I.impl.F.decl: %FExtraReturnType.as.I.impl.F.type = fn_decl @FExtraReturnType.as.I.impl.F [concrete = constants.%FExtraReturnType.as.I.impl.F] {\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc99_15.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc99_15.2: Core.Form = init_form %.loc99_15.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param0\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (<error>), @FExtraReturnType.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.247]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %FExtraReturnType.as.I.impl.F.decl\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FMissingParam.as.J.impl: %Self.ref as %J.ref {\n// CHECK:STDOUT:   %FMissingParam.as.J.impl.F.decl.loc117_31.1: %FMissingParam.as.J.impl.F.type.0f71d8.1 = fn_decl @FMissingParam.as.J.impl.F.loc117_31.1 [concrete = constants.%FMissingParam.as.J.impl.F.7540f6.1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc117_27.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc117_27.2: Core.Form = init_form %.loc117_27.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc117_16: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param1\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc103_44.1: type = specific_constant @J.WithSelf.F.%.loc103_44.1, @J.WithSelf.F(constants.%J.facet.567) [concrete = bool]\n// CHECK:STDOUT:   %.loc103_44.2: type = specific_constant @J.WithSelf.F.%.loc103_44.2, @J.WithSelf.F(constants.%J.facet.567) [concrete = constants.%.f34]\n// CHECK:STDOUT:   %FMissingParam.as.J.impl.F.decl.loc117_31.2: %FMissingParam.as.J.impl.F.type.0f71d8.2 = fn_decl @FMissingParam.as.J.impl.F.loc117_31.2 [concrete = constants.%FMissingParam.as.J.impl.F.7540f6.2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param2\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (%FMissingParam.as.J.impl.F.decl.loc117_31.2), @FMissingParam.as.J.impl [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.5e2]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %FMissingParam.as.J.impl.F.decl.loc117_31.1\n// CHECK:STDOUT:   witness = %J.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FMissingImplicitParam.as.J.impl: %Self.ref as %J.ref {\n// CHECK:STDOUT:   %FMissingImplicitParam.as.J.impl.F.decl.loc130_26.1: %FMissingImplicitParam.as.J.impl.F.type.80a56b.1 = fn_decl @FMissingImplicitParam.as.J.impl.F.loc130_26.1 [concrete = constants.%FMissingImplicitParam.as.J.impl.F.c6a0b7.1] {\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc130_22.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc130_22.2: Core.Form = init_form %.loc130_22.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %b.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc130_13: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param1\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc103_44.1: type = specific_constant @J.WithSelf.F.%.loc103_44.1, @J.WithSelf.F(constants.%J.facet.266) [concrete = bool]\n// CHECK:STDOUT:   %.loc103_44.2: type = specific_constant @J.WithSelf.F.%.loc103_44.2, @J.WithSelf.F(constants.%J.facet.266) [concrete = constants.%.f34]\n// CHECK:STDOUT:   %FMissingImplicitParam.as.J.impl.F.decl.loc130_26.2: %FMissingImplicitParam.as.J.impl.F.type.80a56b.2 = fn_decl @FMissingImplicitParam.as.J.impl.F.loc130_26.2 [concrete = constants.%FMissingImplicitParam.as.J.impl.F.c6a0b7.2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param2\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (%FMissingImplicitParam.as.J.impl.F.decl.loc130_26.2), @FMissingImplicitParam.as.J.impl [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.1e4]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %FMissingImplicitParam.as.J.impl.F.decl.loc130_26.1\n// CHECK:STDOUT:   witness = %J.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FMissingReturnType.as.J.impl: %Self.ref as %J.ref {\n// CHECK:STDOUT:   %FMissingReturnType.as.J.impl.F.decl.loc152_30.1: %FMissingReturnType.as.J.impl.F.type.ce0d21.1 = fn_decl @FMissingReturnType.as.J.impl.F.loc152_30.1 [concrete = constants.%FMissingReturnType.as.J.impl.F.5b613a.1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc152_16: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %.loc152_25: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc103_44.1: type = specific_constant @J.WithSelf.F.%.loc103_44.1, @J.WithSelf.F(constants.%J.facet.a9e) [concrete = bool]\n// CHECK:STDOUT:   %.loc103_44.2: type = specific_constant @J.WithSelf.F.%.loc103_44.2, @J.WithSelf.F(constants.%J.facet.a9e) [concrete = constants.%.f34]\n// CHECK:STDOUT:   %FMissingReturnType.as.J.impl.F.decl.loc152_30.2: %FMissingReturnType.as.J.impl.F.type.ce0d21.2 = fn_decl @FMissingReturnType.as.J.impl.F.loc152_30.2 [concrete = constants.%FMissingReturnType.as.J.impl.F.5b613a.2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param2\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (%FMissingReturnType.as.J.impl.F.decl.loc152_30.2), @FMissingReturnType.as.J.impl [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.7c7]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %FMissingReturnType.as.J.impl.F.decl.loc152_30.1\n// CHECK:STDOUT:   witness = %J.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FDifferentParamType.as.J.impl: %Self.ref as %J.ref {\n// CHECK:STDOUT:   %FDifferentParamType.as.J.impl.F.decl.loc171_38.1: %FDifferentParamType.as.J.impl.F.type.10926d.1 = fn_decl @FDifferentParamType.as.J.impl.F.loc171_38.1 [concrete = constants.%FDifferentParamType.as.J.impl.F.f1245a.1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.b79 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.b79 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc171_34.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc171_34.2: Core.Form = init_form %.loc171_34.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc171_16: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: %FDifferentParamType = value_param call_param1\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FDifferentParamType [concrete = constants.%FDifferentParamType]\n// CHECK:STDOUT:     %b: %FDifferentParamType = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param2\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc103_44.1: type = specific_constant @J.WithSelf.F.%.loc103_44.1, @J.WithSelf.F(constants.%J.facet.bd2) [concrete = bool]\n// CHECK:STDOUT:   %.loc103_44.2: type = specific_constant @J.WithSelf.F.%.loc103_44.2, @J.WithSelf.F(constants.%J.facet.bd2) [concrete = constants.%.f34]\n// CHECK:STDOUT:   %FDifferentParamType.as.J.impl.F.decl.loc171_38.2: %FDifferentParamType.as.J.impl.F.type.10926d.2 = fn_decl @FDifferentParamType.as.J.impl.F.loc171_38.2 [concrete = constants.%FDifferentParamType.as.J.impl.F.f1245a.2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param2\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (%FDifferentParamType.as.J.impl.F.decl.loc171_38.2), @FDifferentParamType.as.J.impl [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.cd7]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %FDifferentParamType.as.J.impl.F.decl.loc171_38.1\n// CHECK:STDOUT:   witness = %J.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FDifferentImplicitParamType.as.J.impl: %Self.ref as %J.ref {\n// CHECK:STDOUT:   %FDifferentImplicitParamType.as.J.impl.F.decl.loc184_38.1: %FDifferentImplicitParamType.as.J.impl.F.type.955391.1 = fn_decl @FDifferentImplicitParamType.as.J.impl.F.loc184_38.1 [concrete = constants.%FDifferentImplicitParamType.as.J.impl.F.a9ece4.1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.b8f = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.b8f = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc184_34.1: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc184_34.2: Core.Form = init_form %.loc184_34.1 [concrete = constants.%.f34]\n// CHECK:STDOUT:     %self.param: %FDifferentImplicitParamType = value_param call_param0\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FDifferentImplicitParamType [concrete = constants.%FDifferentImplicitParamType]\n// CHECK:STDOUT:     %self: %FDifferentImplicitParamType = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %.loc184_25: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param2\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc103_44.1: type = specific_constant @J.WithSelf.F.%.loc103_44.1, @J.WithSelf.F(constants.%J.facet.030) [concrete = bool]\n// CHECK:STDOUT:   %.loc103_44.2: type = specific_constant @J.WithSelf.F.%.loc103_44.2, @J.WithSelf.F(constants.%J.facet.030) [concrete = constants.%.f34]\n// CHECK:STDOUT:   %FDifferentImplicitParamType.as.J.impl.F.decl.loc184_38.2: %FDifferentImplicitParamType.as.J.impl.F.type.955391.2 = fn_decl @FDifferentImplicitParamType.as.J.impl.F.loc184_38.2 [concrete = constants.%FDifferentImplicitParamType.as.J.impl.F.a9ece4.2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param2\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (%FDifferentImplicitParamType.as.J.impl.F.decl.loc184_38.2), @FDifferentImplicitParamType.as.J.impl [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.4d2]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %FDifferentImplicitParamType.as.J.impl.F.decl.loc184_38.1\n// CHECK:STDOUT:   witness = %J.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @FDifferentReturnType.as.J.impl: %Self.ref as %J.ref {\n// CHECK:STDOUT:   %FDifferentReturnType.as.J.impl.F.decl.loc200_38.1: %FDifferentReturnType.as.J.impl.F.type.7bcb67.1 = fn_decl @FDifferentReturnType.as.J.impl.F.loc200_38.1 [concrete = constants.%FDifferentReturnType.as.J.impl.F.a709b1.1] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.5c8 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.5c8 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FDifferentReturnType [concrete = constants.%FDifferentReturnType]\n// CHECK:STDOUT:     %.loc200_34: Core.Form = init_form %Self.ref [concrete = constants.%.2a9]\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %.loc200_16: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %.loc200_25: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref %FDifferentReturnType = out_param call_param2\n// CHECK:STDOUT:     %return: ref %FDifferentReturnType = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc103_44.1: type = specific_constant @J.WithSelf.F.%.loc103_44.1, @J.WithSelf.F(constants.%J.facet.4a1) [concrete = bool]\n// CHECK:STDOUT:   %.loc103_44.2: type = specific_constant @J.WithSelf.F.%.loc103_44.2, @J.WithSelf.F(constants.%J.facet.4a1) [concrete = constants.%.f34]\n// CHECK:STDOUT:   %FDifferentReturnType.as.J.impl.F.decl.loc200_38.2: %FDifferentReturnType.as.J.impl.F.type.7bcb67.2 = fn_decl @FDifferentReturnType.as.J.impl.F.loc200_38.2 [concrete = constants.%FDifferentReturnType.as.J.impl.F.a709b1.2] {\n// CHECK:STDOUT:     %self.patt: %pattern_type.831 = value_binding_pattern self [concrete]\n// CHECK:STDOUT:     %self.param_patt: %pattern_type.831 = value_param_pattern %self.patt [concrete]\n// CHECK:STDOUT:     %b.patt: %pattern_type.831 = value_binding_pattern b [concrete]\n// CHECK:STDOUT:     %b.param_patt: %pattern_type.831 = value_param_pattern %b.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.831 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.831 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %self.param: bool = value_param call_param0\n// CHECK:STDOUT:     %self: bool = value_binding self, %self.param\n// CHECK:STDOUT:     %b.param: bool = value_param call_param1\n// CHECK:STDOUT:     %b: bool = value_binding b, %b.param\n// CHECK:STDOUT:     %return.param: ref bool = out_param call_param2\n// CHECK:STDOUT:     %return: ref bool = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (%FDifferentReturnType.as.J.impl.F.decl.loc200_38.2), @FDifferentReturnType.as.J.impl [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.a49]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %FDifferentReturnType.as.J.impl.F.decl.loc200_38.1\n// CHECK:STDOUT:   witness = %J.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @SelfNestedBadParam.as.SelfNested.impl: %Self.ref as %SelfNested.ref {\n// CHECK:STDOUT:   %SelfNestedBadParam.as.SelfNested.impl.F.decl.loc223_87.1: %SelfNestedBadParam.as.SelfNested.impl.F.type.789632.1 = fn_decl @SelfNestedBadParam.as.SelfNested.impl.F.loc223_87.1 [concrete = constants.%SelfNestedBadParam.as.SelfNested.impl.F.6e1661.1] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.395 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.395 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.ec1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.ec1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %SelfNestedBadParam.ref.loc223_65: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam]\n// CHECK:STDOUT:     %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4]\n// CHECK:STDOUT:     %array_type: type = array_type %int_4, %SelfNestedBadParam.ref.loc223_65 [concrete = constants.%array_type.388]\n// CHECK:STDOUT:     %.loc223_86: Core.Form = init_form %array_type [concrete = constants.%.0cb]\n// CHECK:STDOUT:     %x.param: %tuple.type.70f = value_param call_param0\n// CHECK:STDOUT:     %.loc223_53.1: type = splice_block %.loc223_53.3 [concrete = constants.%tuple.type.70f] {\n// CHECK:STDOUT:       %SelfNestedBadParam.ref.loc223_14: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam]\n// CHECK:STDOUT:       %ptr: type = ptr_type %SelfNestedBadParam.ref.loc223_14 [concrete = constants.%ptr.cf2]\n// CHECK:STDOUT:       %i32.loc223_40: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %i32.loc223_49: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.x.y: type = struct_type {.x: %i32, .y: %i32} [concrete = constants.%struct_type.x.y.871]\n// CHECK:STDOUT:       %.loc223_53.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) [concrete = constants.%tuple.bb3]\n// CHECK:STDOUT:       %.loc223_53.3: type = converted %.loc223_53.2, constants.%tuple.type.70f [concrete = constants.%tuple.type.70f]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: %tuple.type.70f = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %array_type.388 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %array_type.388 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc211_57.1: type = specific_constant @SelfNested.WithSelf.F.%array_type.loc211_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.b9f) [concrete = constants.%array_type.388]\n// CHECK:STDOUT:   %.loc211_57.2: type = specific_constant @SelfNested.WithSelf.F.%.loc211_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.b9f) [concrete = constants.%.0cb]\n// CHECK:STDOUT:   %SelfNestedBadParam.as.SelfNested.impl.F.decl.loc223_87.2: %SelfNestedBadParam.as.SelfNested.impl.F.type.789632.2 = fn_decl @SelfNestedBadParam.as.SelfNested.impl.F.loc223_87.2 [concrete = constants.%SelfNestedBadParam.as.SelfNested.impl.F.6e1661.2] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.8d7 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.8d7 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.ec1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.ec1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %tuple.type.7ea = value_param call_param0\n// CHECK:STDOUT:     %x: %tuple.type.7ea = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %array_type.388 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %array_type.388 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %SelfNested.impl_witness_table = impl_witness_table (%SelfNestedBadParam.as.SelfNested.impl.F.decl.loc223_87.2), @SelfNestedBadParam.as.SelfNested.impl [concrete]\n// CHECK:STDOUT:   %SelfNested.impl_witness: <witness> = impl_witness %SelfNested.impl_witness_table [concrete = constants.%SelfNested.impl_witness.7e8]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .SelfNestedBadParam = <poisoned>\n// CHECK:STDOUT:   .F = %SelfNestedBadParam.as.SelfNested.impl.F.decl.loc223_87.1\n// CHECK:STDOUT:   witness = %SelfNested.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @SelfNestedBadReturnType.as.SelfNested.impl: %Self.ref as %SelfNested.ref {\n// CHECK:STDOUT:   %SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc239_112.1: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.75d128.1 = fn_decl @SelfNestedBadReturnType.as.SelfNested.impl.F.loc239_112.1 [concrete = constants.%SelfNestedBadReturnType.as.SelfNested.impl.F.587f77.1] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.1f1 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.1f1 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.ec1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.ec1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %SelfNestedBadParam.ref: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam]\n// CHECK:STDOUT:     %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4]\n// CHECK:STDOUT:     %array_type: type = array_type %int_4, %SelfNestedBadParam.ref [concrete = constants.%array_type.388]\n// CHECK:STDOUT:     %.loc239_111: Core.Form = init_form %array_type [concrete = constants.%.0cb]\n// CHECK:STDOUT:     %x.param: %tuple.type.064 = value_param call_param0\n// CHECK:STDOUT:     %.loc239_78.1: type = splice_block %.loc239_78.3 [concrete = constants.%tuple.type.064] {\n// CHECK:STDOUT:       %SelfNestedBadReturnType.ref.loc239_14: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType]\n// CHECK:STDOUT:       %ptr: type = ptr_type %SelfNestedBadReturnType.ref.loc239_14 [concrete = constants.%ptr.cbe]\n// CHECK:STDOUT:       %SelfNestedBadReturnType.ref.loc239_45: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType]\n// CHECK:STDOUT:       %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:       %struct_type.x.y: type = struct_type {.x: %SelfNestedBadReturnType, .y: %i32} [concrete = constants.%struct_type.x.y.cfa]\n// CHECK:STDOUT:       %.loc239_78.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) [concrete = constants.%tuple.c42]\n// CHECK:STDOUT:       %.loc239_78.3: type = converted %.loc239_78.2, constants.%tuple.type.064 [concrete = constants.%tuple.type.064]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x: %tuple.type.064 = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %array_type.388 = out_param call_param1\n// CHECK:STDOUT:     %return: ref %array_type.388 = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc211_57.1: type = specific_constant @SelfNested.WithSelf.F.%array_type.loc211_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.23f) [concrete = constants.%array_type.31b]\n// CHECK:STDOUT:   %.loc211_57.2: type = specific_constant @SelfNested.WithSelf.F.%.loc211_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.23f) [concrete = constants.%.369]\n// CHECK:STDOUT:   %SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc239_112.2: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.75d128.2 = fn_decl @SelfNestedBadReturnType.as.SelfNested.impl.F.loc239_112.2 [concrete = constants.%SelfNestedBadReturnType.as.SelfNested.impl.F.587f77.2] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.1f1 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.1f1 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:     %return.patt: %pattern_type.1fd = return_slot_pattern [concrete]\n// CHECK:STDOUT:     %return.param_patt: %pattern_type.1fd = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param: %tuple.type.064 = value_param call_param0\n// CHECK:STDOUT:     %x: %tuple.type.064 = value_binding x, %x.param\n// CHECK:STDOUT:     %return.param: ref %array_type.31b = out_param call_param1\n// CHECK:STDOUT:     %return: ref %array_type.31b = return_slot %return.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %SelfNested.impl_witness_table = impl_witness_table (%SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc239_112.2), @SelfNestedBadReturnType.as.SelfNested.impl [concrete]\n// CHECK:STDOUT:   %SelfNested.impl_witness: <witness> = impl_witness %SelfNested.impl_witness_table [concrete = constants.%SelfNested.impl_witness.d9c]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .SelfNestedBadReturnType = <poisoned>\n// CHECK:STDOUT:   .SelfNestedBadParam = <poisoned>\n// CHECK:STDOUT:   .F = %SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc239_112.1\n// CHECK:STDOUT:   witness = %SelfNested.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @NoF {\n// CHECK:STDOUT:   impl_decl @NoF.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%NoF [concrete = constants.%NoF]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%NoF\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FNotFunction {\n// CHECK:STDOUT:   impl_decl @FNotFunction.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FNotFunction [concrete = constants.%FNotFunction]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FNotFunction\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @F;\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FAlias {\n// CHECK:STDOUT:   impl_decl @FAlias.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FAlias [concrete = constants.%FAlias]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FAlias\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   .PossiblyF = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FExtraParam {\n// CHECK:STDOUT:   impl_decl @FExtraParam.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FExtraParam [concrete = constants.%FExtraParam]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FExtraParam\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FExtraImplicitParam {\n// CHECK:STDOUT:   impl_decl @FExtraImplicitParam.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FExtraImplicitParam [concrete = constants.%FExtraImplicitParam]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FExtraImplicitParam\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FExtraReturnType {\n// CHECK:STDOUT:   impl_decl @FExtraReturnType.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FExtraReturnType [concrete = constants.%FExtraReturnType]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FExtraReturnType\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FMissingParam {\n// CHECK:STDOUT:   impl_decl @FMissingParam.as.J.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FMissingParam [concrete = constants.%FMissingParam]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FMissingParam\n// CHECK:STDOUT:   .J = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FMissingImplicitParam {\n// CHECK:STDOUT:   impl_decl @FMissingImplicitParam.as.J.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FMissingImplicitParam [concrete = constants.%FMissingImplicitParam]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FMissingImplicitParam\n// CHECK:STDOUT:   .J = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FMissingReturnType {\n// CHECK:STDOUT:   impl_decl @FMissingReturnType.as.J.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FMissingReturnType [concrete = constants.%FMissingReturnType]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FMissingReturnType\n// CHECK:STDOUT:   .J = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FDifferentParamType {\n// CHECK:STDOUT:   impl_decl @FDifferentParamType.as.J.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FDifferentParamType [concrete = constants.%FDifferentParamType]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FDifferentParamType\n// CHECK:STDOUT:   .J = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FDifferentImplicitParamType {\n// CHECK:STDOUT:   impl_decl @FDifferentImplicitParamType.as.J.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FDifferentImplicitParamType [concrete = constants.%FDifferentImplicitParamType]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FDifferentImplicitParamType\n// CHECK:STDOUT:   .J = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @FDifferentReturnType {\n// CHECK:STDOUT:   impl_decl @FDifferentReturnType.as.J.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%FDifferentReturnType [concrete = constants.%FDifferentReturnType]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%FDifferentReturnType\n// CHECK:STDOUT:   .J = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SelfNestedBadParam {\n// CHECK:STDOUT:   impl_decl @SelfNestedBadParam.as.SelfNested.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%SelfNestedBadParam [concrete = constants.%SelfNestedBadParam]\n// CHECK:STDOUT:     %SelfNested.ref: type = name_ref SelfNested, file.%SelfNested.decl [concrete = constants.%SelfNested.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SelfNestedBadParam\n// CHECK:STDOUT:   .SelfNested = <poisoned>\n// CHECK:STDOUT:   .SelfNestedBadParam = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @SelfNestedBadReturnType {\n// CHECK:STDOUT:   impl_decl @SelfNestedBadReturnType.as.SelfNested.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%SelfNestedBadReturnType [concrete = constants.%SelfNestedBadReturnType]\n// CHECK:STDOUT:     %SelfNested.ref: type = name_ref SelfNested, file.%SelfNested.decl [concrete = constants.%SelfNested.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%SelfNestedBadReturnType\n// CHECK:STDOUT:   .SelfNested = <poisoned>\n// CHECK:STDOUT:   .SelfNestedBadReturnType = <poisoned>\n// CHECK:STDOUT:   .SelfNestedBadParam = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.F(@I.%Self: %I.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @PossiblyF();\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FExtraParam.as.I.impl.F.loc69_18.1(%b.param: bool);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FExtraParam.as.I.impl.F.loc69_18.2() [thunk @FExtraParam.as.I.impl.%FExtraParam.as.I.impl.F.decl.loc69_18.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %FExtraParam.as.I.impl.F.type.531438.1 = name_ref F, @FExtraParam.as.I.impl.%FExtraParam.as.I.impl.F.decl.loc69_18.1 [concrete = constants.%FExtraParam.as.I.impl.F.33e1fe.1]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FExtraImplicitParam.as.I.impl.F.loc85_23.1(%self.param: %FExtraImplicitParam);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FExtraImplicitParam.as.I.impl.F.loc85_23.2() [thunk @FExtraImplicitParam.as.I.impl.%FExtraImplicitParam.as.I.impl.F.decl.loc85_23.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %FExtraImplicitParam.as.I.impl.F.type.9dd145.1 = name_ref F, @FExtraImplicitParam.as.I.impl.%FExtraImplicitParam.as.I.impl.F.decl.loc85_23.1 [concrete = constants.%FExtraImplicitParam.as.I.impl.F.99eae8.1]\n// CHECK:STDOUT:   %FExtraImplicitParam.as.I.impl.F.call: init %empty_tuple.type = call %F.ref(<error>)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FExtraReturnType.as.I.impl.F() -> out %return.param: bool;\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @J.WithSelf.F(@J.%Self: %J.type) {\n// CHECK:STDOUT:   fn(%self.param: bool, %b.param: bool) -> out %return.param: bool;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FMissingParam.as.J.impl.F.loc117_31.1(%self.param: bool) -> out %return.param: bool;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FMissingParam.as.J.impl.F.loc117_31.2(%self.param: bool, %b.param: bool) -> out %return.param: bool [thunk @FMissingParam.as.J.impl.%FMissingParam.as.J.impl.F.decl.loc117_31.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %FMissingParam.as.J.impl.F.type.0f71d8.1 = name_ref F, @FMissingParam.as.J.impl.%FMissingParam.as.J.impl.F.decl.loc117_31.1 [concrete = constants.%FMissingParam.as.J.impl.F.7540f6.1]\n// CHECK:STDOUT:   %self.ref: bool = name_ref self, %self.param\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b.param\n// CHECK:STDOUT:   %return.ref: ref bool = name_ref <return slot>, %return.param\n// CHECK:STDOUT:   %FMissingParam.as.J.impl.F.bound: <bound method> = bound_method %self.ref, %F.ref\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FMissingImplicitParam.as.J.impl.F.loc130_26.1(%b.param: bool) -> out %return.param: bool;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FMissingImplicitParam.as.J.impl.F.loc130_26.2(%self.param: bool, %b.param: bool) -> out %return.param: bool [thunk @FMissingImplicitParam.as.J.impl.%FMissingImplicitParam.as.J.impl.F.decl.loc130_26.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %FMissingImplicitParam.as.J.impl.F.type.80a56b.1 = name_ref F, @FMissingImplicitParam.as.J.impl.%FMissingImplicitParam.as.J.impl.F.decl.loc130_26.1 [concrete = constants.%FMissingImplicitParam.as.J.impl.F.c6a0b7.1]\n// CHECK:STDOUT:   %self.ref: bool = name_ref self, %self.param\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b.param\n// CHECK:STDOUT:   %return.ref: ref bool = name_ref <return slot>, %return.param\n// CHECK:STDOUT:   %FMissingImplicitParam.as.J.impl.F.call: init bool = call %F.ref(%b.ref)\n// CHECK:STDOUT:   return %FMissingImplicitParam.as.J.impl.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FMissingReturnType.as.J.impl.F.loc152_30.1(%self.param: bool, %b.param: bool);\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FMissingReturnType.as.J.impl.F.loc152_30.2(%self.param: bool, %b.param: bool) -> out %return.param: bool [thunk @FMissingReturnType.as.J.impl.%FMissingReturnType.as.J.impl.F.decl.loc152_30.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %FMissingReturnType.as.J.impl.F.type.ce0d21.1 = name_ref F, @FMissingReturnType.as.J.impl.%FMissingReturnType.as.J.impl.F.decl.loc152_30.1 [concrete = constants.%FMissingReturnType.as.J.impl.F.5b613a.1]\n// CHECK:STDOUT:   %self.ref: bool = name_ref self, %self.param\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b.param\n// CHECK:STDOUT:   %return.ref: ref bool = name_ref <return slot>, %return.param\n// CHECK:STDOUT:   %FMissingReturnType.as.J.impl.F.bound: <bound method> = bound_method %self.ref, %F.ref\n// CHECK:STDOUT:   %FMissingReturnType.as.J.impl.F.call: init %empty_tuple.type = call %FMissingReturnType.as.J.impl.F.bound(%self.ref, %b.ref)\n// CHECK:STDOUT:   %.loc152: bool = converted %FMissingReturnType.as.J.impl.F.call, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FDifferentParamType.as.J.impl.F.loc171_38.1(%self.param: bool, %b.param: %FDifferentParamType) -> out %return.param: bool;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FDifferentParamType.as.J.impl.F.loc171_38.2(%self.param: bool, %b.param: bool) -> out %return.param: bool [thunk @FDifferentParamType.as.J.impl.%FDifferentParamType.as.J.impl.F.decl.loc171_38.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %FDifferentParamType.as.J.impl.F.type.10926d.1 = name_ref F, @FDifferentParamType.as.J.impl.%FDifferentParamType.as.J.impl.F.decl.loc171_38.1 [concrete = constants.%FDifferentParamType.as.J.impl.F.f1245a.1]\n// CHECK:STDOUT:   %self.ref: bool = name_ref self, %self.param\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b.param\n// CHECK:STDOUT:   %return.ref: ref bool = name_ref <return slot>, %return.param\n// CHECK:STDOUT:   %FDifferentParamType.as.J.impl.F.bound: <bound method> = bound_method %self.ref, %F.ref\n// CHECK:STDOUT:   %.loc103: %FDifferentParamType = converted %b.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %FDifferentParamType.as.J.impl.F.call: init bool = call %FDifferentParamType.as.J.impl.F.bound(%self.ref, <error>)\n// CHECK:STDOUT:   return %FDifferentParamType.as.J.impl.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FDifferentImplicitParamType.as.J.impl.F.loc184_38.1(%self.param: %FDifferentImplicitParamType, %b.param: bool) -> out %return.param: bool;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FDifferentImplicitParamType.as.J.impl.F.loc184_38.2(%self.param: bool, %b.param: bool) -> out %return.param: bool [thunk @FDifferentImplicitParamType.as.J.impl.%FDifferentImplicitParamType.as.J.impl.F.decl.loc184_38.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %FDifferentImplicitParamType.as.J.impl.F.type.955391.1 = name_ref F, @FDifferentImplicitParamType.as.J.impl.%FDifferentImplicitParamType.as.J.impl.F.decl.loc184_38.1 [concrete = constants.%FDifferentImplicitParamType.as.J.impl.F.a9ece4.1]\n// CHECK:STDOUT:   %self.ref: bool = name_ref self, %self.param\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b.param\n// CHECK:STDOUT:   %return.ref: ref bool = name_ref <return slot>, %return.param\n// CHECK:STDOUT:   %FDifferentImplicitParamType.as.J.impl.F.bound: <bound method> = bound_method %self.ref, %F.ref\n// CHECK:STDOUT:   %.loc103: %FDifferentImplicitParamType = converted %self.ref, <error> [concrete = <error>]\n// CHECK:STDOUT:   %FDifferentImplicitParamType.as.J.impl.F.call: init bool = call %FDifferentImplicitParamType.as.J.impl.F.bound(<error>, %b.ref)\n// CHECK:STDOUT:   return %FDifferentImplicitParamType.as.J.impl.F.call\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FDifferentReturnType.as.J.impl.F.loc200_38.1(%self.param: bool, %b.param: bool) -> out %return.param: %FDifferentReturnType;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @FDifferentReturnType.as.J.impl.F.loc200_38.2(%self.param: bool, %b.param: bool) -> out %return.param: bool [thunk @FDifferentReturnType.as.J.impl.%FDifferentReturnType.as.J.impl.F.decl.loc200_38.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %FDifferentReturnType.as.J.impl.F.type.7bcb67.1 = name_ref F, @FDifferentReturnType.as.J.impl.%FDifferentReturnType.as.J.impl.F.decl.loc200_38.1 [concrete = constants.%FDifferentReturnType.as.J.impl.F.a709b1.1]\n// CHECK:STDOUT:   %self.ref: bool = name_ref self, %self.param\n// CHECK:STDOUT:   %b.ref: bool = name_ref b, %b.param\n// CHECK:STDOUT:   %return.ref: ref bool = name_ref <return slot>, %return.param\n// CHECK:STDOUT:   %FDifferentReturnType.as.J.impl.F.bound: <bound method> = bound_method %self.ref, %F.ref\n// CHECK:STDOUT:   %.loc200_38.1: ref %FDifferentReturnType = temporary_storage\n// CHECK:STDOUT:   %FDifferentReturnType.as.J.impl.F.call: init %FDifferentReturnType to %.loc200_38.1 = call %FDifferentReturnType.as.J.impl.F.bound(%self.ref, %b.ref)\n// CHECK:STDOUT:   %.loc200_38.2: bool = converted %FDifferentReturnType.as.J.impl.F.call, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @SelfNested.WithSelf.F(@SelfNested.%Self: %SelfNested.type) {\n// CHECK:STDOUT:   %Self: %SelfNested.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.aed)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 0, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type.07b)]\n// CHECK:STDOUT:   %ptr.loc211_16.1: type = ptr_type %Self.binding.as_type [symbolic = %ptr.loc211_16.1 (constants.%ptr.d99)]\n// CHECK:STDOUT:   %struct_type.x.y.loc211_37.1: type = struct_type {.x: @SelfNested.WithSelf.F.%Self.binding.as_type (%Self.binding.as_type.07b), .y: %i32} [symbolic = %struct_type.x.y.loc211_37.1 (constants.%struct_type.x.y.e05)]\n// CHECK:STDOUT:   %tuple: %tuple.type.24b = tuple_value (%ptr.loc211_16.1, %struct_type.x.y.loc211_37.1) [symbolic = %tuple (constants.%tuple.179)]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (%ptr.loc211_16.1, %struct_type.x.y.loc211_37.1) [symbolic = %tuple.type (constants.%tuple.type.9cf)]\n// CHECK:STDOUT:   %pattern_type.loc211_8: type = pattern_type %tuple.type [symbolic = %pattern_type.loc211_8 (constants.%pattern_type.37a)]\n// CHECK:STDOUT:   %array_type.loc211_57.1: type = array_type constants.%int_4, %Self.binding.as_type [symbolic = %array_type.loc211_57.1 (constants.%array_type.eba)]\n// CHECK:STDOUT:   %.loc211_57.1: Core.Form = init_form %array_type.loc211_57.1 [symbolic = %.loc211_57.1 (constants.%.efe)]\n// CHECK:STDOUT:   %pattern_type.loc211_41: type = pattern_type %array_type.loc211_57.1 [symbolic = %pattern_type.loc211_41 (constants.%pattern_type.dfe)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%x.param: @SelfNested.WithSelf.F.%tuple.type (%tuple.type.9cf)) -> out %return.param: @SelfNested.WithSelf.F.%array_type.loc211_57.1 (%array_type.eba);\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @SelfNestedBadParam.as.SelfNested.impl.F.loc223_87.1(%x.param: %tuple.type.70f) -> out %return.param: %array_type.388;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @SelfNestedBadParam.as.SelfNested.impl.F.loc223_87.2(%x.param: %tuple.type.7ea) -> out %return.param: %array_type.388 [thunk @SelfNestedBadParam.as.SelfNested.impl.%SelfNestedBadParam.as.SelfNested.impl.F.decl.loc223_87.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %SelfNestedBadParam.as.SelfNested.impl.F.type.789632.1 = name_ref F, @SelfNestedBadParam.as.SelfNested.impl.%SelfNestedBadParam.as.SelfNested.impl.F.decl.loc223_87.1 [concrete = constants.%SelfNestedBadParam.as.SelfNested.impl.F.6e1661.1]\n// CHECK:STDOUT:   %x.ref: %tuple.type.7ea = name_ref x, %x.param\n// CHECK:STDOUT:   %return.ref: ref %array_type.388 = name_ref <return slot>, %return.param\n// CHECK:STDOUT:   %.loc211_57: ref %array_type.388 = splice_block %return.param {}\n// CHECK:STDOUT:   %tuple.elem0: %ptr.cf2 = tuple_access %x.ref, element0\n// CHECK:STDOUT:   %tuple.elem1: %struct_type.x.y.62a = tuple_access %x.ref, element1\n// CHECK:STDOUT:   %.loc211_9.1: %SelfNestedBadParam = struct_access %tuple.elem1, element0\n// CHECK:STDOUT:   %.loc211_9.2: %i32 = converted %.loc211_9.1, <error> [concrete = <error>]\n// CHECK:STDOUT:   %SelfNestedBadParam.as.SelfNested.impl.F.call: init %array_type.388 to %.loc211_57 = call %F.ref(<error>)\n// CHECK:STDOUT:   return %SelfNestedBadParam.as.SelfNested.impl.F.call to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @SelfNestedBadReturnType.as.SelfNested.impl.F.loc239_112.1(%x.param: %tuple.type.064) -> out %return.param: %array_type.388;\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @SelfNestedBadReturnType.as.SelfNested.impl.F.loc239_112.2(%x.param: %tuple.type.064) -> out %return.param: %array_type.31b [thunk @SelfNestedBadReturnType.as.SelfNested.impl.%SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc239_112.1] {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.75d128.1 = name_ref F, @SelfNestedBadReturnType.as.SelfNested.impl.%SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc239_112.1 [concrete = constants.%SelfNestedBadReturnType.as.SelfNested.impl.F.587f77.1]\n// CHECK:STDOUT:   %x.ref: %tuple.type.064 = name_ref x, %x.param\n// CHECK:STDOUT:   %return.ref: ref %array_type.31b = name_ref <return slot>, %return.param\n// CHECK:STDOUT:   %.loc239_112.1: ref %array_type.388 = temporary_storage\n// CHECK:STDOUT:   %SelfNestedBadReturnType.as.SelfNested.impl.F.call: init %array_type.388 to %.loc239_112.1 = call %F.ref(%x.ref)\n// CHECK:STDOUT:   %.loc239_112.2: %array_type.31b = converted %SelfNestedBadReturnType.as.SelfNested.impl.F.call, <error> [concrete = <error>]\n// CHECK:STDOUT:   return <error> to %return.param\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.ab9\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.08c\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.705\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%Self.ab9) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.fc8) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet.fc8\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.cec\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.733\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.c1a) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet.c1a\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.1b8\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.7e3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.574) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet.574\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.f26\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.5e6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.b53) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet.b53\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.99d\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.eab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%I.facet.b53) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.5a5) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet.5a5\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.e46\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.5bc\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%I.facet.5a5) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.1ed) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet.1ed\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.cd5\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.aee\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%I.facet.1ed) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%Self.8a1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.8a1\n// CHECK:STDOUT:   %J.WithSelf.F.type => constants.%J.WithSelf.F.type.adb\n// CHECK:STDOUT:   %J.WithSelf.F => constants.%J.WithSelf.F.569\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.F(constants.%Self.8a1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%J.facet.567) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%J.facet.567\n// CHECK:STDOUT:   %J.WithSelf.F.type => constants.%J.WithSelf.F.type.54f\n// CHECK:STDOUT:   %J.WithSelf.F => constants.%J.WithSelf.F.7e8\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.F(constants.%J.facet.567) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%J.facet.266) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%J.facet.266\n// CHECK:STDOUT:   %J.WithSelf.F.type => constants.%J.WithSelf.F.type.56e\n// CHECK:STDOUT:   %J.WithSelf.F => constants.%J.WithSelf.F.d17\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.F(constants.%J.facet.266) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%J.facet.a9e) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%J.facet.a9e\n// CHECK:STDOUT:   %J.WithSelf.F.type => constants.%J.WithSelf.F.type.8be\n// CHECK:STDOUT:   %J.WithSelf.F => constants.%J.WithSelf.F.2a5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.F(constants.%J.facet.a9e) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%J.facet.bd2) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%J.facet.bd2\n// CHECK:STDOUT:   %J.WithSelf.F.type => constants.%J.WithSelf.F.type.06a\n// CHECK:STDOUT:   %J.WithSelf.F => constants.%J.WithSelf.F.cad\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.F(constants.%J.facet.bd2) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%J.facet.030) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%J.facet.030\n// CHECK:STDOUT:   %J.WithSelf.F.type => constants.%J.WithSelf.F.type.f29\n// CHECK:STDOUT:   %J.WithSelf.F => constants.%J.WithSelf.F.5b7\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.F(constants.%J.facet.030) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%J.facet.4a1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%J.facet.4a1\n// CHECK:STDOUT:   %J.WithSelf.F.type => constants.%J.WithSelf.F.type.8e3\n// CHECK:STDOUT:   %J.WithSelf.F => constants.%J.WithSelf.F.182\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.F(constants.%J.facet.4a1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @SelfNested.WithSelf(constants.%Self.aed) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.aed\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.type => constants.%SelfNested.WithSelf.F.type.430\n// CHECK:STDOUT:   %SelfNested.WithSelf.F => constants.%SelfNested.WithSelf.F.257\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @SelfNested.WithSelf.F(constants.%Self.aed) {\n// CHECK:STDOUT:   %Self => constants.%Self.aed\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type.07b\n// CHECK:STDOUT:   %ptr.loc211_16.1 => constants.%ptr.d99\n// CHECK:STDOUT:   %struct_type.x.y.loc211_37.1 => constants.%struct_type.x.y.e05\n// CHECK:STDOUT:   %tuple => constants.%tuple.179\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.9cf\n// CHECK:STDOUT:   %pattern_type.loc211_8 => constants.%pattern_type.37a\n// CHECK:STDOUT:   %array_type.loc211_57.1 => constants.%array_type.eba\n// CHECK:STDOUT:   %.loc211_57.1 => constants.%.efe\n// CHECK:STDOUT:   %pattern_type.loc211_41 => constants.%pattern_type.dfe\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @SelfNested.WithSelf(constants.%SelfNested.facet.b9f) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%SelfNested.facet.b9f\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.type => constants.%SelfNested.WithSelf.F.type.4de\n// CHECK:STDOUT:   %SelfNested.WithSelf.F => constants.%SelfNested.WithSelf.F.5e9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @SelfNested.WithSelf.F(constants.%SelfNested.facet.b9f) {\n// CHECK:STDOUT:   %Self => constants.%SelfNested.facet.b9f\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%SelfNestedBadParam\n// CHECK:STDOUT:   %ptr.loc211_16.1 => constants.%ptr.cf2\n// CHECK:STDOUT:   %struct_type.x.y.loc211_37.1 => constants.%struct_type.x.y.62a\n// CHECK:STDOUT:   %tuple => constants.%tuple.73b\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.7ea\n// CHECK:STDOUT:   %pattern_type.loc211_8 => constants.%pattern_type.8d7\n// CHECK:STDOUT:   %array_type.loc211_57.1 => constants.%array_type.388\n// CHECK:STDOUT:   %.loc211_57.1 => constants.%.0cb\n// CHECK:STDOUT:   %pattern_type.loc211_41 => constants.%pattern_type.ec1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @SelfNested.WithSelf(constants.%SelfNested.facet.23f) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%SelfNested.facet.23f\n// CHECK:STDOUT:   %SelfNested.WithSelf.F.type => constants.%SelfNested.WithSelf.F.type.156\n// CHECK:STDOUT:   %SelfNested.WithSelf.F => constants.%SelfNested.WithSelf.F.edc\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @SelfNested.WithSelf.F(constants.%SelfNested.facet.23f) {\n// CHECK:STDOUT:   %Self => constants.%SelfNested.facet.23f\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%SelfNestedBadReturnType\n// CHECK:STDOUT:   %ptr.loc211_16.1 => constants.%ptr.cbe\n// CHECK:STDOUT:   %struct_type.x.y.loc211_37.1 => constants.%struct_type.x.y.cfa\n// CHECK:STDOUT:   %tuple => constants.%tuple.c42\n// CHECK:STDOUT:   %tuple.type => constants.%tuple.type.064\n// CHECK:STDOUT:   %pattern_type.loc211_8 => constants.%pattern_type.1f1\n// CHECK:STDOUT:   %array_type.loc211_57.1 => constants.%array_type.31b\n// CHECK:STDOUT:   %.loc211_57.1 => constants.%.369\n// CHECK:STDOUT:   %pattern_type.loc211_41 => constants.%pattern_type.1fd\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_impl_bad_interface.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_impl_bad_interface.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_impl_bad_interface.carbon\n\n// --- fail_impl_as_false.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_impl_as_false.carbon:[[@LINE+7]]:13: error: cannot implicitly convert non-type value of type `bool` to `type` [ConversionFailureNonTypeToFacet]\n// CHECK:STDERR: impl i32 as false {}\n// CHECK:STDERR:             ^~~~~\n// CHECK:STDERR: fail_impl_as_false.carbon:[[@LINE+4]]:13: note: type `bool` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: impl i32 as false {}\n// CHECK:STDERR:             ^~~~~\n// CHECK:STDERR:\nimpl i32 as false {}\n\n// --- fail_impl_as_type.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_impl_as_type.carbon:[[@LINE+4]]:1: error: impl as non-facet type `type` [ImplAsNonFacetType]\n// CHECK:STDERR: impl bool as type {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl bool as type {}\n\n// --- fail_impl_as_type_where.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_impl_as_type_where.carbon:[[@LINE+4]]:1: error: impl as 0 interfaces, expected 1 [ImplOfNotOneInterface]\n// CHECK:STDERR: impl f64 as type where .Self impls type {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl f64 as type where .Self impls type {}\n\n// --- fail_impl_as_type_where_impls_interface.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\n\n// CHECK:STDERR: fail_impl_as_type_where_impls_interface.carbon:[[@LINE+4]]:1: error: impl as 0 interfaces, expected 1 [ImplOfNotOneInterface]\n// CHECK:STDERR: impl {.a: bool} as type where .Self impls I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl {.a: bool} as type where .Self impls I {}\n\n// CHECK:STDOUT: --- fail_impl_as_false.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/parts/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %.loc11: type = converted @i32.as.<error>.impl.%false, <error> [concrete = <error>]\n// CHECK:STDOUT:   impl_decl @i32.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %i32: type = type_literal constants.%i32 [concrete = constants.%i32]\n// CHECK:STDOUT:     %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @i32.as.<error>.impl: %i32 as <error> {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_as_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   impl_decl @bool.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc8_6: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %.loc8_14: type = type_literal type [concrete = type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @bool.as.<error>.impl: %.loc8_6 as %.loc8_14 {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_as_type_where.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_64: Core.IntLiteral = int_value 64 [concrete]\n// CHECK:STDOUT:   %Float.type: type = generic_class_type @Float [concrete]\n// CHECK:STDOUT:   %Float.generic: %Float.type = struct_value () [concrete]\n// CHECK:STDOUT:   %f64: type = class_type @Float, @Float(%int_64) [concrete]\n// CHECK:STDOUT:   %.Self: type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Float = %Core.Float\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Float: %Float.type = import_ref Core//prelude/parts/float, Float, loaded [concrete = constants.%Float.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   impl_decl @f64.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %f64: type = type_literal constants.%f64 [concrete = constants.%f64]\n// CHECK:STDOUT:     %.loc8_13: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.Self: type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref: type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.loc8_36: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.loc8_18: type = where_expr %.Self [concrete = constants.%type] {\n// CHECK:STDOUT:       requirement_base_facet_type type\n// CHECK:STDOUT:       requirement_impls %.Self.ref, %.loc8_36\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @f64.as.<error>.impl: %f64 as %.loc8_18 {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_impl_as_type_where_impls_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %struct_type.a: type = struct_type {.a: bool} [concrete]\n// CHECK:STDOUT:   %.Self: type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %type_where: type = facet_type <type where .Self impls @I> [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/parts/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @struct_type.a.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc10_11: type = type_literal bool [concrete = bool]\n// CHECK:STDOUT:     %struct_type.a: type = struct_type {.a: bool} [concrete = constants.%struct_type.a]\n// CHECK:STDOUT:     %.loc10_20: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     %.Self: type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref: type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.loc10_25: type = where_expr %.Self [concrete = constants.%type_where] {\n// CHECK:STDOUT:       requirement_base_facet_type type\n// CHECK:STDOUT:       requirement_impls %.Self.ref, %I.ref\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @struct_type.a.as.<error>.impl: %struct_type.a as %.loc10_25 {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_impl_bad_type.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_impl_bad_type.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_impl_bad_type.carbon\n\ninterface I {}\n\n// CHECK:STDERR: fail_impl_bad_type.carbon:[[@LINE+7]]:6: error: cannot implicitly convert non-type value of type `bool` to `type` [ConversionFailureNonTypeToFacet]\n// CHECK:STDERR: impl true as I {}\n// CHECK:STDERR:      ^~~~\n// CHECK:STDERR: fail_impl_bad_type.carbon:[[@LINE+4]]:6: note: type `bool` does not implement interface `Core.ImplicitAs(type)` [MissingImplInMemberAccessInContext]\n// CHECK:STDERR: impl true as I {}\n// CHECK:STDERR:      ^~~~\n// CHECK:STDERR:\nimpl true as I {}\n\n// CHECK:STDOUT: --- fail_impl_bad_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/parts/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @<error>.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %.loc24: type = converted %true, <error> [concrete = <error>]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @<error>.as.I.impl: <error> as %I.ref {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/fail_todo_form_thunk.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/fail_todo_form_thunk.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/fail_todo_form_thunk.carbon\n\ninterface I {\n  let T:! type;\n  // CHECK:STDERR: fail_todo_form_thunk.carbon:[[@LINE+4]]:8: error: semantics TODO: `Support for cloning form bindings` [SemanticsTodo]\n  // CHECK:STDERR:   fn F(x:? form(ref ()), y: T);\n  // CHECK:STDERR:        ^\n  // CHECK:STDERR:\n  fn F(x:? form(ref ()), y: T);\n}\n\nclass C {\n  impl as I where .T = () {\n    fn F(x:? form(ref ()), ());\n  }\n}\n"
  },
  {
    "path": "toolchain/check/testdata/impl/forward_decls.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/forward_decls.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/forward_decls.carbon\n\n// --- empty.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I;\nimpl {} as I;\n\ninterface I {}\nimpl {} as I {}\n\n// --- method.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I;\nimpl {} as I;\n\ninterface I {\n  fn G();\n}\nimpl {} as I {\n  fn G() {}\n}\n\n// --- combine.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I;\nimpl {} as I & I;\n\ninterface I {}\nimpl {} as I & I {}\n\n// --- associated_const.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let T:! type;\n}\nimpl {} as I where .T = ();\n\nimpl {} as I where .T = () {}\n\n// --- associated_const_compound_member_access.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let T:! type;\n}\nclass C {}\nimpl C as I where .T = ();\n\nlet x: C.(I.T) = ();\n\nimpl C as I where .T = () {}\n\n// --- associated_const_of_facet.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let T:! type;\n}\nclass C {}\nimpl C as I where .T = ();\n\nlet x: (C as I).T = ();\n\nimpl C as I where .T = () {}\n\n// --- fail_unset_associated_const.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let T:! type;\n}\nclass C {}\nimpl C as I;\n\n// CHECK:STDERR: fail_unset_associated_const.carbon:[[@LINE+4]]:8: error: accessing member from impl before it has a defined value [ImplAccessMemberBeforeSet]\n// CHECK:STDERR: let x: (C as I).T = ();\n// CHECK:STDERR:        ^~~~~~~~~~\n// CHECK:STDERR:\nlet x: (C as I).T = ();\n\n// CHECK:STDERR: fail_unset_associated_const.carbon:[[@LINE+7]]:1: error: associated constant T not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]\n// CHECK:STDERR: impl C as I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR: fail_unset_associated_const.carbon:[[@LINE-14]]:7: note: associated constant declared here [AssociatedConstantHere]\n// CHECK:STDERR:   let T:! type;\n// CHECK:STDERR:       ^~~~~~~~\n// CHECK:STDERR:\nimpl C as I {}\n\n// --- fail_associated_const_before_interface_definition.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I;\nclass C;\nclass D {}\n// CHECK:STDERR: fail_associated_const_before_interface_definition.carbon:[[@LINE+7]]:19: error: member access into facet of incomplete type `I` [IncompleteTypeInMemberAccessOfFacet]\n// CHECK:STDERR: impl D as I where .T = C;\n// CHECK:STDERR:                   ^~\n// CHECK:STDERR: fail_associated_const_before_interface_definition.carbon:[[@LINE-6]]:1: note: interface was forward declared here [InterfaceForwardDeclaredHere]\n// CHECK:STDERR: interface I;\n// CHECK:STDERR: ^~~~~~~~~~~~\n// CHECK:STDERR:\nimpl D as I where .T = C;\n\ninterface I {}\nclass C {}\n// CHECK:STDERR: fail_associated_const_before_interface_definition.carbon:[[@LINE+4]]:19: error: member name `T` not found in `I` [MemberNameNotFoundInSpecificScope]\n// CHECK:STDERR: impl D as I where .T = C {}\n// CHECK:STDERR:                   ^~\n// CHECK:STDERR:\nimpl D as I where .T = C {}\n\n// --- associated_const_of_parameterized.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(U:! type) {\n  let T:! type;\n}\nclass C;\nclass D {}\nimpl D as I(C) where .T = C;\n\nclass C {}\nimpl D as I(C) where .T = C {}\n\n// --- find_incomplete_impl.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I;\nclass D {}\nimpl D as I;\nclass C(T:! I);\n\nfn F(x: C(D));\n\ninterface I {}\nimpl D as I {}\nclass C(T:! I) {}\n\nfn F(unused x: C(D)) {}\n\n// --- fail_todo_two_interfaces.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I;\ninterface J;\n\n// CHECK:STDERR: fail_todo_two_interfaces.carbon:[[@LINE+4]]:1: error: impl as 2 interfaces, expected 1 [ImplOfNotOneInterface]\n// CHECK:STDERR: impl {} as I & J;\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl {} as I & J;\n\ninterface I {}\ninterface J {}\n\n// --- fail_never_assigned_associated_const.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let T:! type;\n  let U:! type;\n}\nclass C {}\n\nimpl C as I where .T = ();\n\n// CHECK:STDERR: fail_never_assigned_associated_const.carbon:[[@LINE+7]]:1: error: associated constant U not given a value in impl of interface I [ImplAssociatedConstantNeedsValue]\n// CHECK:STDERR: impl C as I where .T = () {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_never_assigned_associated_const.carbon:[[@LINE-9]]:7: note: associated constant declared here [AssociatedConstantHere]\n// CHECK:STDERR:   let U:! type;\n// CHECK:STDERR:       ^~~~~~~~\n// CHECK:STDERR:\nimpl C as I where .T = () {}\n\n// --- example_from_proposal_5168.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface X;\n\n// Allowed to use incomplete interfaces in function declarations.\nfn F(_:! X);\nfn G[U:! X](u: U);\n\nclass C;\n\n// Allowed to use incomplete types and interfaces in impl declarations.\nimpl C as X;\n\ninterface Y;\n\ninterface X {\n  // TODO: Should be allowed to use an incomplete interface here,\n  // but `require Self impls` is not supported yet.\n  // require Self impls Y;\n}\n\n// Classes must be defined before being used in a function definition.\nclass C {}\n\nfn H(c: C) {\n  // Allowed since C is complete and we have a declaration `impl C as X;`\n  F(C);\n  G(c);\n}\n\n// The above declarations require that `interface Y`, `fn F` (since it is\n// generic), and `impl C as X` are defined in the same file.\ninterface Y {}\nfn F(_:! X) {}\nfn G[U:! X](unused u: U) {}\nimpl C as Y;\nimpl C as X {}\nimpl C as Y {}\n\n// --- fail_todo_impl_in_interface_definition.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// This test uses many unsupported features, and is expected to change.\ninterface I {\n  // CHECK:STDERR: fail_todo_impl_in_interface_definition.carbon:[[@LINE+4]]:3: error: semantics TODO: `interface modifier` [SemanticsTodo]\n  // CHECK:STDERR:   default fn F() {\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  default fn F() {\n    class C {}\n    impl C as I;\n\n    // CHECK:STDERR: fail_todo_impl_in_interface_definition.carbon:[[@LINE+7]]:5: error: missing implementation of F in impl of interface I [ImplMissingFunction]\n    // CHECK:STDERR:     impl C as I {}\n    // CHECK:STDERR:     ^~~~~~~~~~~~~\n    // CHECK:STDERR: fail_todo_impl_in_interface_definition.carbon:[[@LINE-7]]:3: note: associated function F declared here [AssociatedFunctionHere]\n    // CHECK:STDERR:   default fn F() {\n    // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    impl C as I {}\n  }\n}\n\n// --- fail_todo_impl_in_interface_definition_with_associated.carbon\nlibrary \"[[@TEST_NAME]]\";\n\n// This test uses many unsupported features, and is expected to change.\ninterface I {\n  let U:! type;\n  // CHECK:STDERR: fail_todo_impl_in_interface_definition_with_associated.carbon:[[@LINE+4]]:3: error: semantics TODO: `interface modifier` [SemanticsTodo]\n  // CHECK:STDERR:   default fn F() {\n  // CHECK:STDERR:   ^~~~~~~\n  // CHECK:STDERR:\n  default fn F() {\n    class C {}\n    impl C as I where .U = C;\n\n    // CHECK:STDERR: fail_todo_impl_in_interface_definition_with_associated.carbon:[[@LINE+7]]:5: error: missing implementation of F in impl of interface I [ImplMissingFunction]\n    // CHECK:STDERR:     impl C as I where .U = C {}\n    // CHECK:STDERR:     ^~~~~~~~~~~~~~~~~~~~~~~~~~\n    // CHECK:STDERR: fail_todo_impl_in_interface_definition_with_associated.carbon:[[@LINE-7]]:3: note: associated function F declared here [AssociatedFunctionHere]\n    // CHECK:STDERR:   default fn F() {\n    // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n    // CHECK:STDERR:\n    impl C as I where .U = C {}\n  }\n}\n\n// CHECK:STDOUT: --- empty.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @empty_struct_type.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %empty_struct_type, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl.loc3\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl.loc3: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc4_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc4_7.2: type = converted %.loc4_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref.loc4: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl.loc6: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc7_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc7_7.2: type = converted %.loc7_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref.loc7: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc4_7.2 as %I.ref.loc4 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @empty_struct_type.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- method.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @empty_struct_type.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.G.type.047: type = fn_type @I.WithSelf.G, @I.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.G.8c4: %I.WithSelf.G.type.047 = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.G.decl [concrete]\n// CHECK:STDOUT:   %empty_struct_type.as.I.impl.G.type: type = fn_type @empty_struct_type.as.I.impl.G [concrete]\n// CHECK:STDOUT:   %empty_struct_type.as.I.impl.G: %empty_struct_type.as.I.impl.G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %empty_struct_type, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.G.type.ed6: type = fn_type @I.WithSelf.G, @I.WithSelf(%I.facet) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.G.42b: %I.WithSelf.G.type.ed6 = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl.loc3\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl.loc3: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc4_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc4_7.2: type = converted %.loc4_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref.loc4: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl.loc6: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc9_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc9_7.2: type = converted %.loc9_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref.loc9: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %I.WithSelf.G.decl: @I.WithSelf.%I.WithSelf.G.type (%I.WithSelf.G.type.047) = fn_decl @I.WithSelf.G [symbolic = @I.WithSelf.%I.WithSelf.G (constants.%I.WithSelf.G.8c4)] {} {}\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, %I.WithSelf.G.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .G = @I.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%I.WithSelf.G.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc4_7.2 as %I.ref.loc4 {\n// CHECK:STDOUT:   %empty_struct_type.as.I.impl.G.decl: %empty_struct_type.as.I.impl.G.type = fn_decl @empty_struct_type.as.I.impl.G [concrete = constants.%empty_struct_type.as.I.impl.G] {} {}\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%empty_struct_type.as.I.impl.G.decl), @empty_struct_type.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .G = %empty_struct_type.as.I.impl.G.decl\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.G(@I.%Self: %I.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @empty_struct_type.as.I.impl.G() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %I.WithSelf.G.type => constants.%I.WithSelf.G.type.047\n// CHECK:STDOUT:   %I.WithSelf.G => constants.%I.WithSelf.G.8c4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.G(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %I.WithSelf.G.type => constants.%I.WithSelf.G.type.ed6\n// CHECK:STDOUT:   %I.WithSelf.G => constants.%I.WithSelf.G.42b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.G(constants.%I.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- combine.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.f2e: type = generic_interface_type @BitAndWith [concrete]\n// CHECK:STDOUT:   %BitAndWith.generic: %BitAndWith.type.f2e = struct_value () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.b10: type = facet_type <@BitAndWith, @BitAndWith(type)> [concrete]\n// CHECK:STDOUT:   %BitAndWith.impl_witness: <witness> = impl_witness imports.%BitAndWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %BitAndWith.facet: %BitAndWith.type.b10 = facet_value type, (%BitAndWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %BitAndWith.WithSelf.Op.type.4bd: type = fn_type @BitAndWith.WithSelf.Op, @BitAndWith.WithSelf(type, %BitAndWith.facet) [concrete]\n// CHECK:STDOUT:   %.d15: type = fn_type_with_self_type %BitAndWith.WithSelf.Op.type.4bd, %BitAndWith.facet [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.type: type = fn_type @type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op: %type.as.BitAndWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound: <bound method> = bound_method %I.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @empty_struct_type.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %empty_struct_type, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .BitAndWith = %Core.BitAndWith\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.BitAndWith: %BitAndWith.type.f2e = import_ref Core//prelude/parts/as, BitAndWith, loaded [concrete = constants.%BitAndWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.8d3: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:   %BitAndWith.impl_witness_table = impl_witness_table (%Core.import_ref.8d3), @type.as.BitAndWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl.loc3\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl.loc3: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %.loc4_14.1: type = value_of_initializer @empty_struct_type.as.I.impl.%type.as.BitAndWith.impl.Op.call.loc4 [concrete = constants.%I.type]\n// CHECK:STDOUT:   %.loc4_14.2: type = converted @empty_struct_type.as.I.impl.%type.as.BitAndWith.impl.Op.call.loc4, %.loc4_14.1 [concrete = constants.%I.type]\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc4_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc4_7.2: type = converted %.loc4_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref.loc4_12: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:     %I.ref.loc4_16: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:     %impl.elem0.loc4: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:     %bound_method.loc4: <bound method> = bound_method %I.ref.loc4_12, %impl.elem0.loc4 [concrete = constants.%type.as.BitAndWith.impl.Op.bound]\n// CHECK:STDOUT:     %type.as.BitAndWith.impl.Op.call.loc4: init type = call %bound_method.loc4(%I.ref.loc4_12, %I.ref.loc4_16) [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl.loc6: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %.loc7_14.1: type = value_of_initializer @empty_struct_type.as.I.impl.%type.as.BitAndWith.impl.Op.call.loc7 [concrete = constants.%I.type]\n// CHECK:STDOUT:   %.loc7_14.2: type = converted @empty_struct_type.as.I.impl.%type.as.BitAndWith.impl.Op.call.loc7, %.loc7_14.1 [concrete = constants.%I.type]\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc7_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc7_7.2: type = converted %.loc7_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref.loc7_12: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:     %I.ref.loc7_16: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:     %impl.elem0.loc7: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:     %bound_method.loc7: <bound method> = bound_method %I.ref.loc7_12, %impl.elem0.loc7 [concrete = constants.%type.as.BitAndWith.impl.Op.bound]\n// CHECK:STDOUT:     %type.as.BitAndWith.impl.Op.call.loc7: init type = call %bound_method.loc7(%I.ref.loc7_12, %I.ref.loc7_16) [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc4_7.2 as file.%.loc4_14.2 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @empty_struct_type.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- associated_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where %impl.elem0 = %empty_tuple.type> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @empty_struct_type.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %empty_struct_type, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc6_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc6_7.2: type = converted %.loc6_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref.loc6: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.2: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc6: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc6: type = facet_access_type %.Self.ref.loc6 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc6_20: type = converted %.Self.ref.loc6, %.Self.as_type.loc6 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc6: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc6: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc6_26.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_26.2: type = converted %.loc6_26.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc6_14: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc6, %.loc6_26.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc8_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc8_7.2: type = converted %.loc8_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref.loc8: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.1: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc8: %I.type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc8: type = facet_access_type %.Self.ref.loc8 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc8_20: type = converted %.Self.ref.loc8, %.Self.as_type.loc8 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc8: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc8: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc8_26.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc8_26.2: type = converted %.loc8_26.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc8_14: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc8, %.loc8_26.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %T: type = assoc_const_decl @T [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete = constants.%assoc0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .T = @T.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%T)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_struct_type.as.I.impl: %.loc6_7.2 as %.loc6_14 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @empty_struct_type.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- associated_const_compound_member_access.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where %impl.elem0 = %empty_tuple.type> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc7: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.2: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc7: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc7: type = facet_access_type %.Self.ref.loc7 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc7_19: type = converted %.Self.ref.loc7, %.Self.as_type.loc7 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc7: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc7: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc7_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_25.2: type = converted %.loc7_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc7_13: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc7, %.loc7_25.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type = value_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc9_9.1: type = splice_block %impl.elem0 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, %I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %T.ref: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %I.facet: %I.type = facet_value %C.ref, (constants.%I.impl_witness) [concrete = constants.%I.facet]\n// CHECK:STDOUT:     %.loc9_9.2: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet]\n// CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_19: %empty_tuple.type = converted @__global_init.%.loc9, %empty_tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %x: %empty_tuple.type = value_binding x, %.loc9_19\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc11: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc11: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.1: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc11: %I.type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc11: type = facet_access_type %.Self.ref.loc11 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc11_19: type = converted %.Self.ref.loc11, %.Self.as_type.loc11 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc11: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc11: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc11_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc11_25.2: type = converted %.loc11_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc11_13: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc11, %.loc11_25.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %T: type = assoc_const_decl @T [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete = constants.%assoc0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .T = @T.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%T)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %C.ref.loc7 as %.loc7_13 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @C.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc9: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- associated_const_of_facet.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where %impl.elem0 = %empty_tuple.type> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc7: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.2: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc7: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc7: type = facet_access_type %.Self.ref.loc7 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc7_19: type = converted %.Self.ref.loc7, %.Self.as_type.loc7 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc7: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc7: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc7_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc7_25.2: type = converted %.loc7_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc7_13: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc7, %.loc7_25.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: %pattern_type = value_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc9_16.1: type = splice_block %impl.elem0 [concrete = constants.%empty_tuple.type] {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, %I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %I.facet: %I.type = facet_value %C.ref, (constants.%I.impl_witness) [concrete = constants.%I.facet]\n// CHECK:STDOUT:     %.loc9_11: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet]\n// CHECK:STDOUT:     %as_type: type = facet_access_type %.loc9_11 [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc9_16.2: type = converted %.loc9_11, %as_type [concrete = constants.%C]\n// CHECK:STDOUT:     %T.ref: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %.loc9_22: %empty_tuple.type = converted @__global_init.%.loc9, %empty_tuple [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   %x: %empty_tuple.type = value_binding x, %.loc9_22\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc11: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc11: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.1: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc11: %I.type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc11: type = facet_access_type %.Self.ref.loc11 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc11_19: type = converted %.Self.ref.loc11, %.Self.as_type.loc11 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc11: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc11: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc11_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc11_25.2: type = converted %.loc11_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc11_13: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc11, %.loc11_25.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %T: type = assoc_const_decl @T [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete = constants.%assoc0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .T = @T.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%T)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %C.ref.loc7 as %.loc7_13 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @C.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc9: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_unset_associated_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .x = %x\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc7: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %x.patt: <error> = value_binding_pattern x [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %.loc13_16.1: type = splice_block %impl.elem0 [concrete = <error>] {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, %C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, %I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %I.facet: %I.type = facet_value %C.ref, (constants.%I.impl_witness) [concrete = constants.%I.facet]\n// CHECK:STDOUT:     %.loc13_11: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet]\n// CHECK:STDOUT:     %as_type: type = facet_access_type %.loc13_11 [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc13_16.2: type = converted %.loc13_11, %as_type [concrete = constants.%C]\n// CHECK:STDOUT:     %T.ref: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0: type = impl_witness_access constants.%I.impl_witness, element0 [concrete = <error>]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %x: <error> = value_binding x, <error> [concrete = <error>]\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc22: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc22: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %T: type = assoc_const_decl @T [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete = constants.%assoc0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .T = @T.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%T)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %C.ref.loc7 as %I.ref.loc7 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (<error>), @C.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @__global_init() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %.loc13: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_associated_const_before_interface_definition.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl.loc3\n// CHECK:STDOUT:     .C = %C.decl.loc4\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl.loc3: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl.loc4: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   impl_decl @D.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %D.ref.loc13: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %I.ref.loc13: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.2: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc13: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc13: type = facet_access_type %.Self.ref.loc13 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc13_19: type = converted %.Self.ref.loc13, %.Self.as_type.loc13 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc13: <error> = name_ref T, <error> [concrete = <error>]\n// CHECK:STDOUT:     %C.ref.loc13: type = name_ref C, file.%C.decl.loc4 [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc13_13: type = where_expr %.Self.2 [concrete = <error>] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %T.ref.loc13, <error>\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl.loc15: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl.loc16: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @D.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %D.ref.loc21: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %I.ref.loc21: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.1: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc21: %I.type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc21: type = facet_access_type %.Self.ref.loc21 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc21_19: type = converted %.Self.ref.loc21, %.Self.as_type.loc21 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc21: <error> = name_ref T, <error> [concrete = <error>]\n// CHECK:STDOUT:     %C.ref.loc21: type = name_ref C, file.%C.decl.loc4 [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc21_13: type = where_expr %.Self.1 [concrete = <error>] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %T.ref.loc21, <error>\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .T = <poisoned>\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @D.as.<error>.impl: %D.ref.loc13 as %.loc13_13 {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- associated_const_of_parameterized.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self.c39: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %U: type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%U)> [symbolic]\n// CHECK:STDOUT:   %Self.fdb: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type.76c: type = assoc_entity_type @I, @I(%U) [symbolic]\n// CHECK:STDOUT:   %assoc0.eea: %I.assoc_type.76c = assoc_entity element0, @I.WithSelf.%T [symbolic]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %I.type.807: type = facet_type <@I, @I(%C)> [concrete]\n// CHECK:STDOUT:   %.Self.9dc: %I.type.807 = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %Self.b60: %I.type.807 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type.2e0: type = assoc_entity_type @I, @I(%C) [concrete]\n// CHECK:STDOUT:   %assoc0.501: %I.assoc_type.2e0 = assoc_entity element0, @I.WithSelf.%T [concrete]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.9dc [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self.9dc, @I, @I(%C) [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I, @I(%C) where %impl.elem0 = %C> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @D.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type.807 = facet_value %D, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl.loc6\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %U.patt: %pattern_type = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc3_17.1: type = splice_block %.loc3_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self.c39]\n// CHECK:STDOUT:       %.loc3_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc3_13.2: type = symbolic_binding U, 0 [symbolic = %U.loc3_13.1 (constants.%U)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc6: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   impl_decl @D.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %D.ref.loc8: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %I.ref.loc8: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %C.ref.loc8_13: type = name_ref C, file.%C.decl.loc6 [concrete = constants.%C]\n// CHECK:STDOUT:     %I.type.loc8: type = facet_type <@I, @I(constants.%C)> [concrete = constants.%I.type.807]\n// CHECK:STDOUT:     %.Self.2: %I.type.807 = symbolic_binding .Self [symbolic_self = constants.%.Self.9dc]\n// CHECK:STDOUT:     %.Self.ref.loc8: %I.type.807 = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self.9dc]\n// CHECK:STDOUT:     %.Self.as_type.loc8: type = facet_access_type %.Self.ref.loc8 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc8_22.1: type = converted %.Self.ref.loc8, %.Self.as_type.loc8 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc8_22.2: %I.assoc_type.2e0 = specific_constant @T.%assoc0, @I.WithSelf(constants.%C, constants.%.Self.9dc) [concrete = constants.%assoc0.501]\n// CHECK:STDOUT:     %T.ref.loc8: %I.assoc_type.2e0 = name_ref T, %.loc8_22.2 [concrete = constants.%assoc0.501]\n// CHECK:STDOUT:     %impl.elem0.loc8: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %C.ref.loc8_27: type = name_ref C, file.%C.decl.loc6 [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc8_16: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type.807\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc8, %C.ref.loc8_27\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc10: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @D.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %D.ref.loc11: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %I.ref.loc11: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %C.ref.loc11_13: type = name_ref C, file.%C.decl.loc6 [concrete = constants.%C]\n// CHECK:STDOUT:     %I.type.loc11: type = facet_type <@I, @I(constants.%C)> [concrete = constants.%I.type.807]\n// CHECK:STDOUT:     %.Self.1: %I.type.807 = symbolic_binding .Self [symbolic_self = constants.%.Self.9dc]\n// CHECK:STDOUT:     %.Self.ref.loc11: %I.type.807 = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self.9dc]\n// CHECK:STDOUT:     %.Self.as_type.loc11: type = facet_access_type %.Self.ref.loc11 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc11_22.1: type = converted %.Self.ref.loc11, %.Self.as_type.loc11 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc11_22.2: %I.assoc_type.2e0 = specific_constant @T.%assoc0, @I.WithSelf(constants.%C, constants.%.Self.9dc) [concrete = constants.%assoc0.501]\n// CHECK:STDOUT:     %T.ref.loc11: %I.assoc_type.2e0 = name_ref T, %.loc11_22.2 [concrete = constants.%assoc0.501]\n// CHECK:STDOUT:     %impl.elem0.loc11: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %C.ref.loc11_27: type = name_ref C, file.%C.decl.loc6 [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc11_16: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type.807\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc11, %C.ref.loc11_27\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%U.loc3_13.2: type) {\n// CHECK:STDOUT:   %U.loc3_13.1: type = symbolic_binding U, 0 [symbolic = %U.loc3_13.1 (constants.%U)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%U.loc3_13.1)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self.loc3_23.2: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc3_23.1: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %T: type = assoc_const_decl @T [concrete] {\n// CHECK:STDOUT:       %assoc0: @I.WithSelf.%I.assoc_type (%I.assoc_type.76c) = assoc_entity element0, @I.WithSelf.%T [symbolic = @I.WithSelf.%assoc0 (constants.%assoc0.eea)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc3_23.1\n// CHECK:STDOUT:     .T = @T.%assoc0\n// CHECK:STDOUT:     witness = (@I.WithSelf.%T)\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @D.as.I.impl: %D.ref.loc8 as %.loc8_16 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @D.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%U) {\n// CHECK:STDOUT:   %U.loc3_13.1 => constants.%U\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%U, constants.%Self.fdb) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%C) {\n// CHECK:STDOUT:   %U.loc3_13.1 => constants.%C\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.807\n// CHECK:STDOUT:   %Self.loc3_23.2 => constants.%Self.b60\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%C, constants.%Self.fdb) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %U => constants.%C\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.2e0\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.501\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%C, constants.%.Self.9dc) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %U => constants.%C\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.2e0\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.501\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%C, constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %U => constants.%C\n// CHECK:STDOUT:   %I.assoc_type => constants.%I.assoc_type.2e0\n// CHECK:STDOUT:   %assoc0 => constants.%assoc0.501\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- find_incomplete_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @D.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.9d9: type = pattern_type %I.type [concrete]\n// CHECK:STDOUT:   %T: %I.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %C.type: type = generic_class_type @C [concrete]\n// CHECK:STDOUT:   %C.generic: %C.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.bba: type = class_type @C, @C(%T) [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %D, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %C.229: type = class_type @C, @C(%I.facet) [concrete]\n// CHECK:STDOUT:   %pattern_type.b40: type = pattern_type %C.229 [concrete]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl.loc3\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .C = %C.decl.loc6\n// CHECK:STDOUT:     .F = %F.decl.loc8\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl.loc3: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   impl_decl @D.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %D.ref.loc5: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %I.ref.loc5: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc6: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.9d9 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %I.ref.loc6 [concrete = constants.%I.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %I.ref.loc6: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_9.2: %I.type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc8: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.b40 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.b40 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param.loc8: %C.229 = value_param call_param0\n// CHECK:STDOUT:     %.loc8_12.1: type = splice_block %C.loc8 [concrete = constants.%C.229] {\n// CHECK:STDOUT:       %C.ref.loc8: %C.type = name_ref C, file.%C.decl.loc6 [concrete = constants.%C.generic]\n// CHECK:STDOUT:       %D.ref.loc8: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:       %I.facet.loc8: %I.type = facet_value %D.ref.loc8, (constants.%I.impl_witness) [concrete = constants.%I.facet]\n// CHECK:STDOUT:       %.loc8_12.2: %I.type = converted %D.ref.loc8, %I.facet.loc8 [concrete = constants.%I.facet]\n// CHECK:STDOUT:       %C.loc8: type = class_type @C, @C(constants.%I.facet) [concrete = constants.%C.229]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.loc8: %C.229 = value_binding x, %x.param.loc8\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl.loc10: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @D.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %D.ref.loc11: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %I.ref.loc11: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc12: %C.type = class_decl @C [concrete = constants.%C.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.9d9 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc12: type = splice_block %I.ref.loc12 [concrete = constants.%I.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %I.ref.loc12: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc12: %I.type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %F.decl.loc14: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %x.patt: %pattern_type.b40 = value_binding_pattern x [concrete]\n// CHECK:STDOUT:     %x.param_patt: %pattern_type.b40 = value_param_pattern %x.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %x.param.loc14: %C.229 = value_param call_param0\n// CHECK:STDOUT:     %.loc14_19.1: type = splice_block %C.loc14 [concrete = constants.%C.229] {\n// CHECK:STDOUT:       %C.ref.loc14: %C.type = name_ref C, file.%C.decl.loc6 [concrete = constants.%C.generic]\n// CHECK:STDOUT:       %D.ref.loc14: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:       %I.facet.loc14: %I.type = facet_value %D.ref.loc14, (constants.%I.impl_witness) [concrete = constants.%I.facet]\n// CHECK:STDOUT:       %.loc14_19.2: %I.type = converted %D.ref.loc14, %I.facet.loc14 [concrete = constants.%I.facet]\n// CHECK:STDOUT:       %C.loc14: type = class_type @C, @C(constants.%I.facet) [concrete = constants.%C.229]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %x.loc14: %C.229 = value_binding x, %x.param.loc14\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @D.as.I.impl: %D.ref.loc5 as %I.ref.loc5 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @D.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(%T.loc6_9.2: %I.type) {\n// CHECK:STDOUT:   %T.loc6_9.1: %I.type = symbolic_binding T, 0 [symbolic = %T.loc6_9.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C.bba\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @F(%x.param.loc14: %C.229) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_9.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%I.facet) {\n// CHECK:STDOUT:   %T.loc6_9.1 => constants.%I.facet\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_two_interfaces.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.f2e: type = generic_interface_type @BitAndWith [concrete]\n// CHECK:STDOUT:   %BitAndWith.generic: %BitAndWith.type.f2e = struct_value () [concrete]\n// CHECK:STDOUT:   %BitAndWith.type.b10: type = facet_type <@BitAndWith, @BitAndWith(type)> [concrete]\n// CHECK:STDOUT:   %BitAndWith.impl_witness: <witness> = impl_witness imports.%BitAndWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %BitAndWith.facet: %BitAndWith.type.b10 = facet_value type, (%BitAndWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %BitAndWith.WithSelf.Op.type.4bd: type = fn_type @BitAndWith.WithSelf.Op, @BitAndWith.WithSelf(type, %BitAndWith.facet) [concrete]\n// CHECK:STDOUT:   %.d15: type = fn_type_with_self_type %BitAndWith.WithSelf.Op.type.4bd, %BitAndWith.facet [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.type: type = fn_type @type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op: %type.as.BitAndWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %type.as.BitAndWith.impl.Op.bound: <bound method> = bound_method %I.type, %type.as.BitAndWith.impl.Op [concrete]\n// CHECK:STDOUT:   %facet_type: type = facet_type <@I & @J> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Self.8a1: %J.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .BitAndWith = %Core.BitAndWith\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.BitAndWith: %BitAndWith.type.f2e = import_ref Core//prelude/parts/as, BitAndWith, loaded [concrete = constants.%BitAndWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.8d3: %type.as.BitAndWith.impl.Op.type = import_ref Core//prelude/parts/as, loc{{\\d+_\\d+}}, loaded [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:   %BitAndWith.impl_witness_table = impl_witness_table (%Core.import_ref.8d3), @type.as.BitAndWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl.loc3\n// CHECK:STDOUT:     .J = %J.decl.loc4\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl.loc3: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %J.decl.loc4: type = interface_decl @J [concrete = constants.%J.type] {} {}\n// CHECK:STDOUT:   %.loc10_14.1: type = value_of_initializer @empty_struct_type.as.<error>.impl.%type.as.BitAndWith.impl.Op.call [concrete = constants.%facet_type]\n// CHECK:STDOUT:   %.loc10_14.2: type = converted @empty_struct_type.as.<error>.impl.%type.as.BitAndWith.impl.Op.call, %.loc10_14.1 [concrete = constants.%facet_type]\n// CHECK:STDOUT:   impl_decl @empty_struct_type.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc10_7.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc10_7.2: type = converted %.loc10_7.1, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl.loc3 [concrete = constants.%I.type]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl.loc4 [concrete = constants.%J.type]\n// CHECK:STDOUT:     %impl.elem0: %.d15 = impl_witness_access constants.%BitAndWith.impl_witness, element0 [concrete = constants.%type.as.BitAndWith.impl.Op]\n// CHECK:STDOUT:     %bound_method: <bound method> = bound_method %I.ref, %impl.elem0 [concrete = constants.%type.as.BitAndWith.impl.Op.bound]\n// CHECK:STDOUT:     %type.as.BitAndWith.impl.Op.call: init type = call %bound_method(%I.ref, %J.ref) [concrete = constants.%facet_type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl.loc12: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %J.decl.loc13: type = interface_decl @J [concrete = constants.%J.type] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @J {\n// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self.8a1]\n// CHECK:STDOUT:   %J.WithSelf.decl = interface_with_self_decl @J [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_struct_type.as.<error>.impl: %.loc10_7.2 as file.%.loc10_14.2;\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%Self.8a1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_never_assigned_associated_const.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete]\n// CHECK:STDOUT:   %assoc1: %I.assoc_type = assoc_entity element1, @I.WithSelf.%U [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where %impl.elem0 = %empty_tuple.type> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc9: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc9: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.2: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc9: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc9: type = facet_access_type %.Self.ref.loc9 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc9_19: type = converted %.Self.ref.loc9, %.Self.as_type.loc9 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc9: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc9: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc9_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc9_25.2: type = converted %.loc9_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc9_13: type = where_expr %.Self.2 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc9, %.loc9_25.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc18: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc18: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self.1: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc18: %I.type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc18: type = facet_access_type %.Self.ref.loc18 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc18_19: type = converted %.Self.ref.loc18, %.Self.as_type.loc18 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %T.ref.loc18: %I.assoc_type = name_ref T, @T.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:     %impl.elem0.loc18: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:     %.loc18_25.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc18_25.2: type = converted %.loc18_25.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %.loc18_13: type = where_expr %.Self.1 [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc18, %.loc18_25.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %T: type = assoc_const_decl @T [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%T [concrete = constants.%assoc0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %U: type = assoc_const_decl @U [concrete] {\n// CHECK:STDOUT:     %assoc1: %I.assoc_type = assoc_entity element1, @I.WithSelf.%U [concrete = constants.%assoc1]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .T = @T.%assoc0\n// CHECK:STDOUT:   .U = @U.%assoc1\n// CHECK:STDOUT:   witness = (@I.WithSelf.%T, @I.WithSelf.%U)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %C.ref.loc9 as %.loc9_13 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, <error>), @C.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- example_from_proposal_5168.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %X.type: type = facet_type <@X> [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.b4b: type = pattern_type %X.type [concrete]\n// CHECK:STDOUT:   %_: %X.type = symbolic_binding _, 0 [symbolic]\n// CHECK:STDOUT:   %F.type: type = fn_type @F [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %F: %F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %U: %X.type = symbolic_binding U, 0 [symbolic]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U [symbolic]\n// CHECK:STDOUT:   %pattern_type.b36: type = pattern_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %X.impl_witness: <witness> = impl_witness @C.as.X.impl.%X.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Y.type: type = facet_type <@Y> [concrete]\n// CHECK:STDOUT:   %Self.e52: %X.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %H.type: type = fn_type @H [concrete]\n// CHECK:STDOUT:   %H: %H.type = struct_value () [concrete]\n// CHECK:STDOUT:   %X.facet: %X.type = facet_value %C, (%X.impl_witness) [concrete]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F, @F(%X.facet) [concrete]\n// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G, @G(%X.facet) [concrete]\n// CHECK:STDOUT:   %Self.162: %Y.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %U.binding.as_type [symbolic]\n// CHECK:STDOUT:   %Y.impl_witness: <witness> = impl_witness @C.as.Y.impl.%Y.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Y.facet: %Y.type = facet_value %C, (%Y.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .X = %X.decl.loc3\n// CHECK:STDOUT:     .F = %F.decl.loc6\n// CHECK:STDOUT:     .G = %G.decl.loc7\n// CHECK:STDOUT:     .C = %C.decl.loc9\n// CHECK:STDOUT:     .Y = %Y.decl.loc14\n// CHECK:STDOUT:     .H = %H.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %X.decl.loc3: type = interface_decl @X [concrete = constants.%X.type] {} {}\n// CHECK:STDOUT:   %F.decl.loc6: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %_.patt: %pattern_type.b4b = symbolic_binding_pattern _, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc6: type = splice_block %X.ref.loc6 [concrete = constants.%X.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %X.ref.loc6: type = name_ref X, file.%X.decl.loc3 [concrete = constants.%X.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %_.loc6_6.2: %X.type = symbolic_binding _, 0 [symbolic = %_.loc6_6.1 (constants.%_)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl.loc7: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.b4b = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %u.patt: @G.%pattern_type (%pattern_type.b36) = value_binding_pattern u [concrete]\n// CHECK:STDOUT:     %u.param_patt: @G.%pattern_type (%pattern_type.b36) = value_param_pattern %u.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_10: type = splice_block %X.ref.loc7 [concrete = constants.%X.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %X.ref.loc7: type = name_ref X, file.%X.decl.loc3 [concrete = constants.%X.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc7_6.2: %X.type = symbolic_binding U, 0 [symbolic = %U.loc7_6.1 (constants.%U)]\n// CHECK:STDOUT:     %u.param.loc7: @G.%U.binding.as_type (%U.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc7_16.1: type = splice_block %.loc7_16.2 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)] {\n// CHECK:STDOUT:       %U.ref.loc7: %X.type = name_ref U, %U.loc7_6.2 [symbolic = %U.loc7_6.1 (constants.%U)]\n// CHECK:STDOUT:       %U.as_type.loc7: type = facet_access_type %U.ref.loc7 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:       %.loc7_16.2: type = converted %U.ref.loc7, %U.as_type.loc7 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %u.loc7: @G.%U.binding.as_type (%U.binding.as_type) = value_binding u, %u.param.loc7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl.loc9: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.X.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc12: type = name_ref C, file.%C.decl.loc9 [concrete = constants.%C]\n// CHECK:STDOUT:     %X.ref.loc12: type = name_ref X, file.%X.decl.loc3 [concrete = constants.%X.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Y.decl.loc14: type = interface_decl @Y [concrete = constants.%Y.type] {} {}\n// CHECK:STDOUT:   %X.decl.loc16: type = interface_decl @X [concrete = constants.%X.type] {} {}\n// CHECK:STDOUT:   %C.decl.loc23: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %H.decl: %H.type = fn_decl @H [concrete = constants.%H] {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type.7c7 = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc25: type = name_ref C, file.%C.decl.loc9 [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Y.decl.loc33: type = interface_decl @Y [concrete = constants.%Y.type] {} {}\n// CHECK:STDOUT:   %F.decl.loc34: %F.type = fn_decl @F [concrete = constants.%F] {\n// CHECK:STDOUT:     %_.patt: %pattern_type.b4b = symbolic_binding_pattern _, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc34: type = splice_block %X.ref.loc34 [concrete = constants.%X.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %X.ref.loc34: type = name_ref X, file.%X.decl.loc3 [concrete = constants.%X.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %_.loc34: %X.type = symbolic_binding _, 0 [symbolic = %_.loc6_6.1 (constants.%_)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %G.decl.loc35: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %U.patt: %pattern_type.b4b = symbolic_binding_pattern U, 0 [concrete]\n// CHECK:STDOUT:     %u.patt: @G.%pattern_type (%pattern_type.b36) = value_binding_pattern u [concrete]\n// CHECK:STDOUT:     %u.param_patt: @G.%pattern_type (%pattern_type.b36) = value_param_pattern %u.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc35_10: type = splice_block %X.ref.loc35 [concrete = constants.%X.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %X.ref.loc35: type = name_ref X, file.%X.decl.loc3 [concrete = constants.%X.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %U.loc35: %X.type = symbolic_binding U, 0 [symbolic = %U.loc7_6.1 (constants.%U)]\n// CHECK:STDOUT:     %u.param.loc35: @G.%U.binding.as_type (%U.binding.as_type) = value_param call_param0\n// CHECK:STDOUT:     %.loc35_23.1: type = splice_block %.loc35_23.2 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)] {\n// CHECK:STDOUT:       %U.ref.loc35: %X.type = name_ref U, %U.loc35 [symbolic = %U.loc7_6.1 (constants.%U)]\n// CHECK:STDOUT:       %U.as_type.loc35: type = facet_access_type %U.ref.loc35 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:       %.loc35_23.2: type = converted %U.ref.loc35, %U.as_type.loc35 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %u.loc35: @G.%U.binding.as_type (%U.binding.as_type) = value_binding u, %u.param.loc35\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.Y.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc36: type = name_ref C, file.%C.decl.loc9 [concrete = constants.%C]\n// CHECK:STDOUT:     %Y.ref.loc36: type = name_ref Y, file.%Y.decl.loc14 [concrete = constants.%Y.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.X.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc37: type = name_ref C, file.%C.decl.loc9 [concrete = constants.%C]\n// CHECK:STDOUT:     %X.ref.loc37: type = name_ref X, file.%X.decl.loc3 [concrete = constants.%X.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.Y.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc38: type = name_ref C, file.%C.decl.loc9 [concrete = constants.%C]\n// CHECK:STDOUT:     %Y.ref.loc38: type = name_ref Y, file.%Y.decl.loc14 [concrete = constants.%Y.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @X {\n// CHECK:STDOUT:   %Self: %X.type = symbolic_binding Self, 0 [symbolic = constants.%Self.e52]\n// CHECK:STDOUT:   %X.WithSelf.decl = interface_with_self_decl @X [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Y {\n// CHECK:STDOUT:   %Self: %Y.type = symbolic_binding Self, 0 [symbolic = constants.%Self.162]\n// CHECK:STDOUT:   %Y.WithSelf.decl = interface_with_self_decl @Y [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.X.impl: %C.ref.loc12 as %X.ref.loc12 {\n// CHECK:STDOUT:   %X.impl_witness_table = impl_witness_table (), @C.as.X.impl [concrete]\n// CHECK:STDOUT:   %X.impl_witness: <witness> = impl_witness %X.impl_witness_table [concrete = constants.%X.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %X.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.Y.impl: %C.ref.loc36 as %Y.ref.loc36 {\n// CHECK:STDOUT:   %Y.impl_witness_table = impl_witness_table (), @C.as.Y.impl [concrete]\n// CHECK:STDOUT:   %Y.impl_witness: <witness> = impl_witness %Y.impl_witness_table [concrete = constants.%Y.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %Y.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @F(%_.loc6_6.2: %X.type) {\n// CHECK:STDOUT:   %_.loc6_6.1: %X.type = symbolic_binding _, 0 [symbolic = %_.loc6_6.1 (constants.%_)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @G(%U.loc7_6.2: %X.type) {\n// CHECK:STDOUT:   %U.loc7_6.1: %X.type = symbolic_binding U, 0 [symbolic = %U.loc7_6.1 (constants.%U)]\n// CHECK:STDOUT:   %U.binding.as_type: type = symbolic_binding_type U, 0, %U.loc7_6.1 [symbolic = %U.binding.as_type (constants.%U.binding.as_type)]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %U.binding.as_type [symbolic = %pattern_type (constants.%pattern_type.b36)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %U.binding.as_type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn(%u.param.loc35: @G.%U.binding.as_type (%U.binding.as_type)) {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @H(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %F.ref: %F.type = name_ref F, file.%F.decl.loc6 [concrete = constants.%F]\n// CHECK:STDOUT:   %C.ref.loc27: type = name_ref C, file.%C.decl.loc9 [concrete = constants.%C]\n// CHECK:STDOUT:   %X.facet.loc27: %X.type = facet_value %C.ref.loc27, (constants.%X.impl_witness) [concrete = constants.%X.facet]\n// CHECK:STDOUT:   %.loc27: %X.type = converted %C.ref.loc27, %X.facet.loc27 [concrete = constants.%X.facet]\n// CHECK:STDOUT:   %F.specific_fn: <specific function> = specific_function %F.ref, @F(constants.%X.facet) [concrete = constants.%F.specific_fn]\n// CHECK:STDOUT:   %F.call: init %empty_tuple.type = call %F.specific_fn()\n// CHECK:STDOUT:   %G.ref: %G.type = name_ref G, file.%G.decl.loc7 [concrete = constants.%G]\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %X.facet.loc28: %X.type = facet_value constants.%C, (constants.%X.impl_witness) [concrete = constants.%X.facet]\n// CHECK:STDOUT:   %.loc28: %X.type = converted constants.%C, %X.facet.loc28 [concrete = constants.%X.facet]\n// CHECK:STDOUT:   %G.specific_fn: <specific function> = specific_function %G.ref, @G(constants.%X.facet) [concrete = constants.%G.specific_fn]\n// CHECK:STDOUT:   %G.call: init %empty_tuple.type = call %G.specific_fn(%c.ref)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%_) {\n// CHECK:STDOUT:   %_.loc6_6.1 => constants.%_\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%U) {\n// CHECK:STDOUT:   %U.loc7_6.1 => constants.%U\n// CHECK:STDOUT:   %U.binding.as_type => constants.%U.binding.as_type\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.b36\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.WithSelf(constants.%Self.e52) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @F(constants.%X.facet) {\n// CHECK:STDOUT:   %_.loc6_6.1 => constants.%X.facet\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @G(constants.%X.facet) {\n// CHECK:STDOUT:   %U.loc7_6.1 => constants.%X.facet\n// CHECK:STDOUT:   %U.binding.as_type => constants.%C\n// CHECK:STDOUT:   %pattern_type => constants.%pattern_type.7c7\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete => constants.%complete_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Y.WithSelf(constants.%Self.162) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @X.WithSelf(constants.%X.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Y.WithSelf(constants.%Y.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_impl_in_interface_definition.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.08c: type = fn_type @I.WithSelf.F, @I.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.705: %I.WithSelf.F.type.08c = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%Self) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table, @C.as.I.impl(%Self) [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.5dd: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.f5e: %I.WithSelf.F.type.5dd = struct_value () [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %I.WithSelf.F.decl: @I.WithSelf.%I.WithSelf.F.type (%I.WithSelf.F.type.08c) = fn_decl @I.WithSelf.F [symbolic = @I.WithSelf.%I.WithSelf.F (constants.%I.WithSelf.F.705)] {} {}\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, %I.WithSelf.F.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   .F = @I.WithSelf.%assoc0\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   witness = (@I.WithSelf.%I.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl(@I.%Self: %I.type) {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%Self) [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:   %I.impl_witness.loc11_16.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(%Self) [symbolic = %I.impl_witness.loc11_16.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref.loc11 as %I.ref.loc11 {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (<error>), @C.as.I.impl [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc11_16.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(constants.%Self) [symbolic = %I.impl_witness.loc11_16.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .F = <poisoned>\n// CHECK:STDOUT:     witness = %I.impl_witness.loc11_16.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(@I.%Self: %I.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.F(@I.%Self: %I.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%Self) [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %C.decl: type = class_decl @C [symbolic = @I.WithSelf.F.%C (constants.%C)] {} {}\n// CHECK:STDOUT:     impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:       %C.ref.loc11: type = name_ref C, @I.WithSelf.F.%C.decl [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:       %I.ref.loc11: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:       %C.ref.loc20: type = name_ref C, @I.WithSelf.F.%C.decl [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:       %I.ref.loc20: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.08c\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.705\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl(constants.%Self) {\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %C => constants.%C\n// CHECK:STDOUT:   %I.impl_witness.loc11_16.2 => constants.%I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.5dd\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.f5e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_todo_impl_in_interface_definition_with_associated.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%U [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.08c: type = fn_type @I.WithSelf.F, @I.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.705: %I.WithSelf.F.type.08c = struct_value () [symbolic]\n// CHECK:STDOUT:   %assoc1: %I.assoc_type = assoc_entity element1, @I.WithSelf.%I.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%Self) [symbolic]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %I.WithSelf.F.type.29d: type = fn_type @I.WithSelf.F, @I.WithSelf(%.Self) [symbolic_self]\n// CHECK:STDOUT:   %I.WithSelf.F.8ec: %I.WithSelf.F.type.29d = struct_value () [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0: type = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where %impl.elem0 = %C> [symbolic]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table, @C.as.I.impl(%Self) [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I_where.type [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.000: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.a8c: %I.WithSelf.F.type.000 = struct_value () [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %U: type = assoc_const_decl @U [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%U [concrete = constants.%assoc0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.WithSelf.F.decl: @I.WithSelf.%I.WithSelf.F.type (%I.WithSelf.F.type.08c) = fn_decl @I.WithSelf.F [symbolic = @I.WithSelf.%I.WithSelf.F (constants.%I.WithSelf.F.705)] {} {}\n// CHECK:STDOUT:   %assoc1: %I.assoc_type = assoc_entity element1, %I.WithSelf.F.decl [concrete = constants.%assoc1]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   .U = @U.%assoc0\n// CHECK:STDOUT:   .F = @I.WithSelf.%assoc1\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   witness = (@I.WithSelf.%U, @I.WithSelf.%I.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl(@I.%Self: %I.type) {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%Self) [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where constants.%impl.elem0 = %C> [symbolic = %I_where.type (constants.%I_where.type)]\n// CHECK:STDOUT:   %I.impl_witness.loc12_29.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(%Self) [symbolic = %I.impl_witness.loc12_29.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I_where.type [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref.loc12_10 as %.loc12_17 {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant, <error>), @C.as.I.impl [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc12_29.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(constants.%Self) [symbolic = %I.impl_witness.loc12_29.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:     %impl_witness_assoc_constant: type = impl_witness_assoc_constant constants.%C [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .F = <poisoned>\n// CHECK:STDOUT:     witness = %I.impl_witness.loc12_29.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic class @C(@I.%Self: %I.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   class {\n// CHECK:STDOUT:     %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:     complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = constants.%C\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.F(@I.%Self: %I.type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self)]\n// CHECK:STDOUT:   %C: type = class_type @C, @C(%Self) [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %C.decl: type = class_decl @C [symbolic = @I.WithSelf.F.%C (constants.%C)] {} {}\n// CHECK:STDOUT:     impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:       %C.ref.loc12_10: type = name_ref C, @I.WithSelf.F.%C.decl [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:       %I.ref.loc12: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:       %.Self.2: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.Self.ref.loc12: %I.type = name_ref .Self, %.Self.2 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.Self.as_type.loc12: type = facet_access_type %.Self.ref.loc12 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc12_23: type = converted %.Self.ref.loc12, %.Self.as_type.loc12 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %U.ref.loc12: %I.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:       %impl.elem0.loc12: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:       %C.ref.loc12_28: type = name_ref C, @I.WithSelf.F.%C.decl [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:       %.loc12_17: type = where_expr %.Self.2 [symbolic = %I_where.type (constants.%I_where.type)] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc12, %C.ref.loc12_28\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:       %C.ref.loc21_10: type = name_ref C, @I.WithSelf.F.%C.decl [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:       %I.ref.loc21: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:       %.Self.1: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.Self.ref.loc21: %I.type = name_ref .Self, %.Self.1 [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.Self.as_type.loc21: type = facet_access_type %.Self.ref.loc21 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %.loc21_23: type = converted %.Self.ref.loc21, %.Self.as_type.loc21 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:       %U.ref.loc21: %I.assoc_type = name_ref U, @U.%assoc0 [concrete = constants.%assoc0]\n// CHECK:STDOUT:       %impl.elem0.loc21: type = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0]\n// CHECK:STDOUT:       %C.ref.loc21_28: type = name_ref C, @I.WithSelf.F.%C.decl [symbolic = %C (constants.%C)]\n// CHECK:STDOUT:       %.loc21_17: type = where_expr %.Self.1 [symbolic = %I_where.type (constants.%I_where.type)] {\n// CHECK:STDOUT:         requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:         requirement_rewrite %impl.elem0.loc21, %C.ref.loc21_28\n// CHECK:STDOUT:       }\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.08c\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.705\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%.Self\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.29d\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.8ec\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl(constants.%Self) {\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %C => constants.%C\n// CHECK:STDOUT:   %I_where.type => constants.%I_where.type\n// CHECK:STDOUT:   %I.impl_witness.loc12_29.2 => constants.%I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.000\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.a8c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/generic_redeclaration.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/generic_redeclaration.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/generic_redeclaration.carbon\n\n// --- fail_todo_same_self_and_interface.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Interface {}\n\ninterface I {}\ninterface J {}\ninterface K {}\ninterface L {}\n\n// TODO: Put these in a match_first so the test will pass again.\nimpl forall [T:! I] T as Interface;\nimpl forall [T:! J] T as Interface;\nimpl forall [T:! K] T as Interface;\nimpl forall [T:! L] T as Interface;\n\n// These are different impls, so they are not redefinitions, even though the\n// self type and constraint type are the same.\nimpl forall [T:! I] T as Interface {}\n// CHECK:STDERR: fail_todo_same_self_and_interface.carbon:[[@LINE+7]]:1: error: found non-final `impl` with the same type structure as another non-final `impl` [ImplNonFinalSameTypeStructure]\n// CHECK:STDERR: impl forall [T:! J] T as Interface {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_todo_same_self_and_interface.carbon:[[@LINE-4]]:1: note: other `impl` here [ImplNonFinalSameTypeStructureNote]\n// CHECK:STDERR: impl forall [T:! I] T as Interface {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! J] T as Interface {}\n// CHECK:STDERR: fail_todo_same_self_and_interface.carbon:[[@LINE+7]]:1: error: found non-final `impl` with the same type structure as another non-final `impl` [ImplNonFinalSameTypeStructure]\n// CHECK:STDERR: impl forall [T:! K] T as Interface {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_todo_same_self_and_interface.carbon:[[@LINE-12]]:1: note: other `impl` here [ImplNonFinalSameTypeStructureNote]\n// CHECK:STDERR: impl forall [T:! I] T as Interface {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! K] T as Interface {}\n// CHECK:STDERR: fail_todo_same_self_and_interface.carbon:[[@LINE+7]]:1: error: found non-final `impl` with the same type structure as another non-final `impl` [ImplNonFinalSameTypeStructure]\n// CHECK:STDERR: impl forall [T:! L] T as Interface {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_todo_same_self_and_interface.carbon:[[@LINE-20]]:1: note: other `impl` here [ImplNonFinalSameTypeStructureNote]\n// CHECK:STDERR: impl forall [T:! I] T as Interface {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! L] T as Interface {}\n\n// --- fail_same_self_and_interface_redefined.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {}\ninterface J {}\n\nimpl forall [T:! I] T as J {}\n// CHECK:STDERR: fail_same_self_and_interface_redefined.carbon:[[@LINE+7]]:1: error: redefinition of `impl T as J` [ImplRedefinition]\n// CHECK:STDERR: impl forall [T:! I] T as J {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_same_self_and_interface_redefined.carbon:[[@LINE-4]]:1: note: previous definition was here [ImplPreviousDefinition]\n// CHECK:STDERR: impl forall [T:! I] T as J {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! I] T as J {}\n\n// --- fail_same_type_different_spelling.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C;\ninterface I {}\n\n// Since the spelling is different, it's not caught as a redefinition, but it\n// is diagnosed as an overlapping impl without using a `match_first` block.\nimpl C as I {}\n// CHECK:STDERR: fail_same_type_different_spelling.carbon:[[@LINE+7]]:1: error: found non-final `impl` with the same type structure as another non-final `impl` [ImplNonFinalSameTypeStructure]\n// CHECK:STDERR: impl (C, C).0 as I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_same_type_different_spelling.carbon:[[@LINE-4]]:1: note: other `impl` here [ImplNonFinalSameTypeStructureNote]\n// CHECK:STDERR: impl C as I {}\n// CHECK:STDERR: ^~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl (C, C).0 as I {}\n\n// --- fail_redefinition_generic_regions.carbon\n\ninterface I {}\n\nimpl forall [T:! type] T as I {\n  fn A() {}\n}\n\n// CHECK:STDERR: fail_redefinition_generic_regions.carbon:[[@LINE+7]]:1: error: redefinition of `impl T as I` [ImplRedefinition]\n// CHECK:STDERR: impl forall [T:! type] T as I {\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_redefinition_generic_regions.carbon:[[@LINE-7]]:1: note: previous definition was here [ImplPreviousDefinition]\n// CHECK:STDERR: impl forall [T:! type] T as I {\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] T as I {\n  // Although not referenced, B has the same generic region index of A, and\n  // makes C a different index. We used to merge, and this was a crash.\n  fn B() {}\n  fn C() -> () { return (); }\n  fn D() -> () {\n    return C();\n  }\n}\n\n// CHECK:STDOUT: --- fail_todo_same_self_and_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Interface.type: type = facet_type <@Interface> [concrete]\n// CHECK:STDOUT:   %Self.887: %Interface.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]\n// CHECK:STDOUT:   %Self.8a1: %J.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %K.type: type = facet_type <@K> [concrete]\n// CHECK:STDOUT:   %Self.44d: %K.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %L.type: type = facet_type <@L> [concrete]\n// CHECK:STDOUT:   %Self.cbc: %L.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.9d9: type = pattern_type %I.type [concrete]\n// CHECK:STDOUT:   %T.651: %I.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.3af: type = symbolic_binding_type T, 0, %T.651 [symbolic]\n// CHECK:STDOUT:   %Interface.impl_witness.779: <witness> = impl_witness @T.binding.as_type.as.Interface.impl.973.%Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.973(%T.651) [symbolic]\n// CHECK:STDOUT:   %pattern_type.f76: type = pattern_type %J.type [concrete]\n// CHECK:STDOUT:   %T.612: %J.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.50b: type = symbolic_binding_type T, 0, %T.612 [symbolic]\n// CHECK:STDOUT:   %Interface.impl_witness.8e2: <witness> = impl_witness @T.binding.as_type.as.Interface.impl.5eb.%Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.5eb(%T.612) [symbolic]\n// CHECK:STDOUT:   %pattern_type.250: type = pattern_type %K.type [concrete]\n// CHECK:STDOUT:   %T.9b2: %K.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.bec: type = symbolic_binding_type T, 0, %T.9b2 [symbolic]\n// CHECK:STDOUT:   %Interface.impl_witness.84e: <witness> = impl_witness @T.binding.as_type.as.Interface.impl.edf.%Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.edf(%T.9b2) [symbolic]\n// CHECK:STDOUT:   %pattern_type.88f: type = pattern_type %L.type [concrete]\n// CHECK:STDOUT:   %T.0fc: %L.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type.29d: type = symbolic_binding_type T, 0, %T.0fc [symbolic]\n// CHECK:STDOUT:   %Interface.impl_witness.8e9: <witness> = impl_witness @T.binding.as_type.as.Interface.impl.410.%Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.410(%T.0fc) [symbolic]\n// CHECK:STDOUT:   %Interface.facet.9bb: %Interface.type = facet_value %T.binding.as_type.3af, (%Interface.impl_witness.779) [symbolic]\n// CHECK:STDOUT:   %Interface.facet.08d: %Interface.type = facet_value %T.binding.as_type.50b, (%Interface.impl_witness.8e2) [symbolic]\n// CHECK:STDOUT:   %Interface.facet.842: %Interface.type = facet_value %T.binding.as_type.bec, (%Interface.impl_witness.84e) [symbolic]\n// CHECK:STDOUT:   %Interface.facet.f9d: %Interface.type = facet_value %T.binding.as_type.29d, (%Interface.impl_witness.8e9) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Interface = %Interface.decl\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .J = %J.decl\n// CHECK:STDOUT:     .K = %K.decl\n// CHECK:STDOUT:     .L = %L.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Interface.decl: type = interface_decl @Interface [concrete = constants.%Interface.type] {} {}\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}\n// CHECK:STDOUT:   %K.decl: type = interface_decl @K [concrete = constants.%K.type] {} {}\n// CHECK:STDOUT:   %L.decl: type = interface_decl @L [concrete = constants.%L.type] {} {}\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.Interface.impl.973 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.9d9 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc12: %I.type = name_ref T, %T.loc12_14.1 [symbolic = %T.loc12_14.2 (constants.%T.651)]\n// CHECK:STDOUT:     %T.as_type.loc12: type = facet_access_type %T.ref.loc12 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.3af)]\n// CHECK:STDOUT:     %.loc12_21: type = converted %T.ref.loc12, %T.as_type.loc12 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.3af)]\n// CHECK:STDOUT:     %Interface.ref.loc12: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]\n// CHECK:STDOUT:     %.loc12_18: type = splice_block %I.ref.loc12 [concrete = constants.%I.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %I.ref.loc12: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc12_14.1: %I.type = symbolic_binding T, 0 [symbolic = %T.loc12_14.2 (constants.%T.651)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.Interface.impl.5eb [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.f76 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc13: %J.type = name_ref T, %T.loc13_14.1 [symbolic = %T.loc13_14.2 (constants.%T.612)]\n// CHECK:STDOUT:     %T.as_type.loc13: type = facet_access_type %T.ref.loc13 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.50b)]\n// CHECK:STDOUT:     %.loc13_21: type = converted %T.ref.loc13, %T.as_type.loc13 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.50b)]\n// CHECK:STDOUT:     %Interface.ref.loc13: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]\n// CHECK:STDOUT:     %.loc13_18: type = splice_block %J.ref.loc13 [concrete = constants.%J.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %J.ref.loc13: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc13_14.1: %J.type = symbolic_binding T, 0 [symbolic = %T.loc13_14.2 (constants.%T.612)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.Interface.impl.edf [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.250 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc14: %K.type = name_ref T, %T.loc14_14.1 [symbolic = %T.loc14_14.2 (constants.%T.9b2)]\n// CHECK:STDOUT:     %T.as_type.loc14: type = facet_access_type %T.ref.loc14 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.bec)]\n// CHECK:STDOUT:     %.loc14_21: type = converted %T.ref.loc14, %T.as_type.loc14 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.bec)]\n// CHECK:STDOUT:     %Interface.ref.loc14: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]\n// CHECK:STDOUT:     %.loc14_18: type = splice_block %K.ref.loc14 [concrete = constants.%K.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %K.ref.loc14: type = name_ref K, file.%K.decl [concrete = constants.%K.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc14_14.1: %K.type = symbolic_binding T, 0 [symbolic = %T.loc14_14.2 (constants.%T.9b2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.Interface.impl.410 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.88f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc15: %L.type = name_ref T, %T.loc15_14.1 [symbolic = %T.loc15_14.2 (constants.%T.0fc)]\n// CHECK:STDOUT:     %T.as_type.loc15: type = facet_access_type %T.ref.loc15 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.29d)]\n// CHECK:STDOUT:     %.loc15_21: type = converted %T.ref.loc15, %T.as_type.loc15 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.29d)]\n// CHECK:STDOUT:     %Interface.ref.loc15: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]\n// CHECK:STDOUT:     %.loc15_18: type = splice_block %L.ref.loc15 [concrete = constants.%L.type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %L.ref.loc15: type = name_ref L, file.%L.decl [concrete = constants.%L.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_14.1: %L.type = symbolic_binding T, 0 [symbolic = %T.loc15_14.2 (constants.%T.0fc)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.Interface.impl.973 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.9d9 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc19: %I.type = name_ref T, %T.loc19 [symbolic = %T.loc12_14.2 (constants.%T.651)]\n// CHECK:STDOUT:     %T.as_type.loc19: type = facet_access_type %T.ref.loc19 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.3af)]\n// CHECK:STDOUT:     %.loc19_21: type = converted %T.ref.loc19, %T.as_type.loc19 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.3af)]\n// CHECK:STDOUT:     %Interface.ref.loc19: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]\n// CHECK:STDOUT:     %.loc19_18: type = splice_block %I.ref.loc19 [concrete = constants.%I.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %I.ref.loc19: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc19: %I.type = symbolic_binding T, 0 [symbolic = %T.loc12_14.2 (constants.%T.651)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.Interface.impl.5eb [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.f76 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc27: %J.type = name_ref T, %T.loc27 [symbolic = %T.loc13_14.2 (constants.%T.612)]\n// CHECK:STDOUT:     %T.as_type.loc27: type = facet_access_type %T.ref.loc27 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.50b)]\n// CHECK:STDOUT:     %.loc27_21: type = converted %T.ref.loc27, %T.as_type.loc27 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.50b)]\n// CHECK:STDOUT:     %Interface.ref.loc27: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]\n// CHECK:STDOUT:     %.loc27_18: type = splice_block %J.ref.loc27 [concrete = constants.%J.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %J.ref.loc27: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc27: %J.type = symbolic_binding T, 0 [symbolic = %T.loc13_14.2 (constants.%T.612)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.Interface.impl.edf [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.250 = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc35: %K.type = name_ref T, %T.loc35 [symbolic = %T.loc14_14.2 (constants.%T.9b2)]\n// CHECK:STDOUT:     %T.as_type.loc35: type = facet_access_type %T.ref.loc35 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.bec)]\n// CHECK:STDOUT:     %.loc35_21: type = converted %T.ref.loc35, %T.as_type.loc35 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.bec)]\n// CHECK:STDOUT:     %Interface.ref.loc35: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]\n// CHECK:STDOUT:     %.loc35_18: type = splice_block %K.ref.loc35 [concrete = constants.%K.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %K.ref.loc35: type = name_ref K, file.%K.decl [concrete = constants.%K.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc35: %K.type = symbolic_binding T, 0 [symbolic = %T.loc14_14.2 (constants.%T.9b2)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.Interface.impl.410 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.88f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref.loc43: %L.type = name_ref T, %T.loc43 [symbolic = %T.loc15_14.2 (constants.%T.0fc)]\n// CHECK:STDOUT:     %T.as_type.loc43: type = facet_access_type %T.ref.loc43 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.29d)]\n// CHECK:STDOUT:     %.loc43_21: type = converted %T.ref.loc43, %T.as_type.loc43 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.29d)]\n// CHECK:STDOUT:     %Interface.ref.loc43: type = name_ref Interface, file.%Interface.decl [concrete = constants.%Interface.type]\n// CHECK:STDOUT:     %.loc43_18: type = splice_block %L.ref.loc43 [concrete = constants.%L.type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %L.ref.loc43: type = name_ref L, file.%L.decl [concrete = constants.%L.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc43: %L.type = symbolic_binding T, 0 [symbolic = %T.loc15_14.2 (constants.%T.0fc)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Interface {\n// CHECK:STDOUT:   %Self: %Interface.type = symbolic_binding Self, 0 [symbolic = constants.%Self.887]\n// CHECK:STDOUT:   %Interface.WithSelf.decl = interface_with_self_decl @Interface [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @J {\n// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self.8a1]\n// CHECK:STDOUT:   %J.WithSelf.decl = interface_with_self_decl @J [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @K {\n// CHECK:STDOUT:   %Self: %K.type = symbolic_binding Self, 0 [symbolic = constants.%Self.44d]\n// CHECK:STDOUT:   %K.WithSelf.decl = interface_with_self_decl @K [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @L {\n// CHECK:STDOUT:   %Self: %L.type = symbolic_binding Self, 0 [symbolic = constants.%Self.cbc]\n// CHECK:STDOUT:   %L.WithSelf.decl = interface_with_self_decl @L [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.binding.as_type.as.Interface.impl.973(%T.loc12_14.1: %I.type) {\n// CHECK:STDOUT:   %T.loc12_14.2: %I.type = symbolic_binding T, 0 [symbolic = %T.loc12_14.2 (constants.%T.651)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc12_14.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.3af)]\n// CHECK:STDOUT:   %Interface.impl_witness.loc12_35.2: <witness> = impl_witness %Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.973(%T.loc12_14.2) [symbolic = %Interface.impl_witness.loc12_35.2 (constants.%Interface.impl_witness.779)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc12_21 as %Interface.ref.loc12 {\n// CHECK:STDOUT:     %Interface.impl_witness_table = impl_witness_table (), @T.binding.as_type.as.Interface.impl.973 [concrete]\n// CHECK:STDOUT:     %Interface.impl_witness.loc12_35.1: <witness> = impl_witness %Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.973(constants.%T.651) [symbolic = %Interface.impl_witness.loc12_35.2 (constants.%Interface.impl_witness.779)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Interface.impl_witness.loc12_35.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.binding.as_type.as.Interface.impl.5eb(%T.loc13_14.1: %J.type) {\n// CHECK:STDOUT:   %T.loc13_14.2: %J.type = symbolic_binding T, 0 [symbolic = %T.loc13_14.2 (constants.%T.612)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc13_14.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.50b)]\n// CHECK:STDOUT:   %Interface.impl_witness.loc13_35.2: <witness> = impl_witness %Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.5eb(%T.loc13_14.2) [symbolic = %Interface.impl_witness.loc13_35.2 (constants.%Interface.impl_witness.8e2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc13_21 as %Interface.ref.loc13 {\n// CHECK:STDOUT:     %Interface.impl_witness_table = impl_witness_table (), @T.binding.as_type.as.Interface.impl.5eb [concrete]\n// CHECK:STDOUT:     %Interface.impl_witness.loc13_35.1: <witness> = impl_witness %Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.5eb(constants.%T.612) [symbolic = %Interface.impl_witness.loc13_35.2 (constants.%Interface.impl_witness.8e2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Interface.impl_witness.loc13_35.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.binding.as_type.as.Interface.impl.edf(%T.loc14_14.1: %K.type) {\n// CHECK:STDOUT:   %T.loc14_14.2: %K.type = symbolic_binding T, 0 [symbolic = %T.loc14_14.2 (constants.%T.9b2)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc14_14.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.bec)]\n// CHECK:STDOUT:   %Interface.impl_witness.loc14_35.2: <witness> = impl_witness %Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.edf(%T.loc14_14.2) [symbolic = %Interface.impl_witness.loc14_35.2 (constants.%Interface.impl_witness.84e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc14_21 as %Interface.ref.loc14 {\n// CHECK:STDOUT:     %Interface.impl_witness_table = impl_witness_table (), @T.binding.as_type.as.Interface.impl.edf [concrete]\n// CHECK:STDOUT:     %Interface.impl_witness.loc14_35.1: <witness> = impl_witness %Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.edf(constants.%T.9b2) [symbolic = %Interface.impl_witness.loc14_35.2 (constants.%Interface.impl_witness.84e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Interface.impl_witness.loc14_35.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.binding.as_type.as.Interface.impl.410(%T.loc15_14.1: %L.type) {\n// CHECK:STDOUT:   %T.loc15_14.2: %L.type = symbolic_binding T, 0 [symbolic = %T.loc15_14.2 (constants.%T.0fc)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc15_14.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type.29d)]\n// CHECK:STDOUT:   %Interface.impl_witness.loc15_35.2: <witness> = impl_witness %Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.410(%T.loc15_14.2) [symbolic = %Interface.impl_witness.loc15_35.2 (constants.%Interface.impl_witness.8e9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc15_21 as %Interface.ref.loc15 {\n// CHECK:STDOUT:     %Interface.impl_witness_table = impl_witness_table (), @T.binding.as_type.as.Interface.impl.410 [concrete]\n// CHECK:STDOUT:     %Interface.impl_witness.loc15_35.1: <witness> = impl_witness %Interface.impl_witness_table, @T.binding.as_type.as.Interface.impl.410(constants.%T.0fc) [symbolic = %Interface.impl_witness.loc15_35.2 (constants.%Interface.impl_witness.8e9)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %Interface.impl_witness.loc15_35.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Interface.WithSelf(constants.%Self.887) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%Self.8a1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @K.WithSelf(constants.%Self.44d) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @L.WithSelf(constants.%Self.cbc) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.binding.as_type.as.Interface.impl.973(constants.%T.651) {\n// CHECK:STDOUT:   %T.loc12_14.2 => constants.%T.651\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.3af\n// CHECK:STDOUT:   %Interface.impl_witness.loc12_35.2 => constants.%Interface.impl_witness.779\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.binding.as_type.as.Interface.impl.5eb(constants.%T.612) {\n// CHECK:STDOUT:   %T.loc13_14.2 => constants.%T.612\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.50b\n// CHECK:STDOUT:   %Interface.impl_witness.loc13_35.2 => constants.%Interface.impl_witness.8e2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.binding.as_type.as.Interface.impl.edf(constants.%T.9b2) {\n// CHECK:STDOUT:   %T.loc14_14.2 => constants.%T.9b2\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.bec\n// CHECK:STDOUT:   %Interface.impl_witness.loc14_35.2 => constants.%Interface.impl_witness.84e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.binding.as_type.as.Interface.impl.410(constants.%T.0fc) {\n// CHECK:STDOUT:   %T.loc15_14.2 => constants.%T.0fc\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type.29d\n// CHECK:STDOUT:   %Interface.impl_witness.loc15_35.2 => constants.%Interface.impl_witness.8e9\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Interface.WithSelf(constants.%Interface.facet.9bb) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Interface.WithSelf(constants.%Interface.facet.08d) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Interface.WithSelf(constants.%Interface.facet.842) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Interface.WithSelf(constants.%Interface.facet.f9d) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_same_self_and_interface_redefined.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J> [concrete]\n// CHECK:STDOUT:   %Self.8a1: %J.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %I.type [concrete]\n// CHECK:STDOUT:   %T: %I.type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T [symbolic]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness @T.binding.as_type.as.J.impl.c4ee06.1.%J.impl_witness_table, @T.binding.as_type.as.J.impl.c4ee06.1(%T) [symbolic]\n// CHECK:STDOUT:   %J.facet: %J.type = facet_value %T.binding.as_type, (%J.impl_witness) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .J = %J.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %J.decl: type = interface_decl @J [concrete = constants.%J.type] {} {}\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.J.impl.c4ee06.1 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: %I.type = name_ref T, %T.loc7_14.1 [symbolic = %T.loc7_14.2 (constants.%T)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc7_21: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:     %.loc7_18: type = splice_block %I.ref [concrete = constants.%I.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_14.1: %I.type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.binding.as_type.as.J.impl.c4ee06.2 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: %I.type = name_ref T, %T.loc15_14.1 [symbolic = %T.loc15_14.2 (constants.%T)]\n// CHECK:STDOUT:     %T.as_type: type = facet_access_type %T.ref [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %.loc15_21: type = converted %T.ref, %T.as_type [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:     %J.ref: type = name_ref J, file.%J.decl [concrete = constants.%J.type]\n// CHECK:STDOUT:     %.loc15_18: type = splice_block %I.ref [concrete = constants.%I.type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_14.1: %I.type = symbolic_binding T, 0 [symbolic = %T.loc15_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @J {\n// CHECK:STDOUT:   %Self: %J.type = symbolic_binding Self, 0 [symbolic = constants.%Self.8a1]\n// CHECK:STDOUT:   %J.WithSelf.decl = interface_with_self_decl @J [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.binding.as_type.as.J.impl.c4ee06.1(%T.loc7_14.1: %I.type) {\n// CHECK:STDOUT:   %T.loc7_14.2: %I.type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc7_14.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:   %J.impl_witness.loc7_28.2: <witness> = impl_witness %J.impl_witness_table, @T.binding.as_type.as.J.impl.c4ee06.1(%T.loc7_14.2) [symbolic = %J.impl_witness.loc7_28.2 (constants.%J.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc7_21 as %J.ref {\n// CHECK:STDOUT:     %J.impl_witness_table = impl_witness_table (), @T.binding.as_type.as.J.impl.c4ee06.1 [concrete]\n// CHECK:STDOUT:     %J.impl_witness.loc7_28.1: <witness> = impl_witness %J.impl_witness_table, @T.binding.as_type.as.J.impl.c4ee06.1(constants.%T) [symbolic = %J.impl_witness.loc7_28.2 (constants.%J.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %J.impl_witness.loc7_28.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.binding.as_type.as.J.impl.c4ee06.2(%T.loc15_14.1: %I.type) {\n// CHECK:STDOUT:   %T.loc15_14.2: %I.type = symbolic_binding T, 0 [symbolic = %T.loc15_14.2 (constants.%T)]\n// CHECK:STDOUT:   %T.binding.as_type: type = symbolic_binding_type T, 0, %T.loc15_14.2 [symbolic = %T.binding.as_type (constants.%T.binding.as_type)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %.loc15_21 as %J.ref {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%Self.8a1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.binding.as_type.as.J.impl.c4ee06.1(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_14.2 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT:   %J.impl_witness.loc7_28.2 => constants.%J.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%J.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.binding.as_type.as.J.impl.c4ee06.2(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_14.2 => constants.%T\n// CHECK:STDOUT:   %T.binding.as_type => constants.%T.binding.as_type\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_same_type_different_spelling.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.impl_witness.6465e0.1: <witness> = impl_witness @C.as.I.impl.e47215.1.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet.f94759.1: %I.type = facet_value %C, (%I.impl_witness.6465e0.1) [concrete]\n// CHECK:STDOUT:   %tuple.type: type = tuple_type (type, type) [concrete]\n// CHECK:STDOUT:   %tuple: %tuple.type = tuple_value (%C, %C) [concrete]\n// CHECK:STDOUT:   %int_0: Core.IntLiteral = int_value 0 [concrete]\n// CHECK:STDOUT:   %I.impl_witness.6465e0.2: <witness> = impl_witness @C.as.I.impl.e47215.2.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet.f94759.2: %I.type = facet_value %C, (%I.impl_witness.6465e0.2) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.e47215.1 [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.e47215.2 [concrete] {} {\n// CHECK:STDOUT:     %C.ref.loc17_7: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %C.ref.loc17_10: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %.loc17_11.1: %tuple.type = tuple_literal (%C.ref.loc17_7, %C.ref.loc17_10) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]\n// CHECK:STDOUT:     %tuple: %tuple.type = tuple_value (%C.ref.loc17_7, %C.ref.loc17_10) [concrete = constants.%tuple]\n// CHECK:STDOUT:     %.loc17_11.2: %tuple.type = converted %.loc17_11.1, %tuple [concrete = constants.%tuple]\n// CHECK:STDOUT:     %tuple.elem0: type = tuple_access %.loc17_11.2, element0 [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl.e47215.1: %C.ref as %I.ref {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl.e47215.1 [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.6465e0.1]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl.e47215.2: %tuple.elem0 as %I.ref {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl.e47215.2 [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness.6465e0.2]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C;\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.f94759.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet.f94759.2) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_redefinition_generic_regions.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type.98f: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @T.as.I.impl.f7b5a3.1.%I.impl_witness_table, @T.as.I.impl.f7b5a3.1(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.I.impl.A.type: type = fn_type @T.as.I.impl.A, @T.as.I.impl.f7b5a3.1(%T) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %T.as.I.impl.A: %T.as.I.impl.A.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %T, (%I.impl_witness) [symbolic]\n// CHECK:STDOUT:   %T.as.I.impl.B.type: type = fn_type @T.as.I.impl.B, @T.as.I.impl.f7b5a3.2(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.I.impl.B: %T.as.I.impl.B.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %.262: Core.Form = init_form %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %pattern_type.cb1: type = pattern_type %empty_tuple.type [concrete]\n// CHECK:STDOUT:   %T.as.I.impl.C.type: type = fn_type @T.as.I.impl.C, @T.as.I.impl.f7b5a3.2(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.I.impl.C: %T.as.I.impl.C.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %T.as.I.impl.D.type: type = fn_type @T.as.I.impl.D, @T.as.I.impl.f7b5a3.2(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.I.impl.D: %T.as.I.impl.D.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %T.as.I.impl.C.specific_fn: <specific function> = specific_function %T.as.I.impl.C, @T.as.I.impl.C(%T) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @T.as.I.impl.f7b5a3.1 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc4_14.2 [symbolic = %T.loc4_14.1 (constants.%T)]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.loc4_18.1: type = splice_block %.loc4_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_14.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @T.as.I.impl.f7b5a3.2 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type.98f = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc15_14.2 [symbolic = %T.loc15_14.1 (constants.%T)]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.loc15_18.1: type = splice_block %.loc15_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_14.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.as.I.impl.f7b5a3.1(%T.loc4_14.2: type) {\n// CHECK:STDOUT:   %T.loc4_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_14.1 (constants.%T)]\n// CHECK:STDOUT:   %I.impl_witness.loc4_31.2: <witness> = impl_witness %I.impl_witness_table, @T.as.I.impl.f7b5a3.1(%T.loc4_14.1) [symbolic = %I.impl_witness.loc4_31.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T.as.I.impl.A.type: type = fn_type @T.as.I.impl.A, @T.as.I.impl.f7b5a3.1(%T.loc4_14.1) [symbolic = %T.as.I.impl.A.type (constants.%T.as.I.impl.A.type)]\n// CHECK:STDOUT:   %T.as.I.impl.A: @T.as.I.impl.f7b5a3.1.%T.as.I.impl.A.type (%T.as.I.impl.A.type) = struct_value () [symbolic = %T.as.I.impl.A (constants.%T.as.I.impl.A)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %T.ref as %I.ref {\n// CHECK:STDOUT:     %T.as.I.impl.A.decl: @T.as.I.impl.f7b5a3.1.%T.as.I.impl.A.type (%T.as.I.impl.A.type) = fn_decl @T.as.I.impl.A [symbolic = @T.as.I.impl.f7b5a3.1.%T.as.I.impl.A (constants.%T.as.I.impl.A)] {} {}\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (), @T.as.I.impl.f7b5a3.1 [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc4_31.1: <witness> = impl_witness %I.impl_witness_table, @T.as.I.impl.f7b5a3.1(constants.%T) [symbolic = %I.impl_witness.loc4_31.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .A = %T.as.I.impl.A.decl\n// CHECK:STDOUT:     witness = %I.impl_witness.loc4_31.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.as.I.impl.f7b5a3.2(%T.loc15_14.2: type) {\n// CHECK:STDOUT:   %T.loc15_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_14.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T.as.I.impl.B.type: type = fn_type @T.as.I.impl.B, @T.as.I.impl.f7b5a3.2(%T.loc15_14.1) [symbolic = %T.as.I.impl.B.type (constants.%T.as.I.impl.B.type)]\n// CHECK:STDOUT:   %T.as.I.impl.B: @T.as.I.impl.f7b5a3.2.%T.as.I.impl.B.type (%T.as.I.impl.B.type) = struct_value () [symbolic = %T.as.I.impl.B (constants.%T.as.I.impl.B)]\n// CHECK:STDOUT:   %T.as.I.impl.C.type: type = fn_type @T.as.I.impl.C, @T.as.I.impl.f7b5a3.2(%T.loc15_14.1) [symbolic = %T.as.I.impl.C.type (constants.%T.as.I.impl.C.type)]\n// CHECK:STDOUT:   %T.as.I.impl.C: @T.as.I.impl.f7b5a3.2.%T.as.I.impl.C.type (%T.as.I.impl.C.type) = struct_value () [symbolic = %T.as.I.impl.C (constants.%T.as.I.impl.C)]\n// CHECK:STDOUT:   %T.as.I.impl.D.type: type = fn_type @T.as.I.impl.D, @T.as.I.impl.f7b5a3.2(%T.loc15_14.1) [symbolic = %T.as.I.impl.D.type (constants.%T.as.I.impl.D.type)]\n// CHECK:STDOUT:   %T.as.I.impl.D: @T.as.I.impl.f7b5a3.2.%T.as.I.impl.D.type (%T.as.I.impl.D.type) = struct_value () [symbolic = %T.as.I.impl.D (constants.%T.as.I.impl.D)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %T.ref as %I.ref {\n// CHECK:STDOUT:     %T.as.I.impl.B.decl: @T.as.I.impl.f7b5a3.2.%T.as.I.impl.B.type (%T.as.I.impl.B.type) = fn_decl @T.as.I.impl.B [symbolic = @T.as.I.impl.f7b5a3.2.%T.as.I.impl.B (constants.%T.as.I.impl.B)] {} {}\n// CHECK:STDOUT:     %T.as.I.impl.C.decl: @T.as.I.impl.f7b5a3.2.%T.as.I.impl.C.type (%T.as.I.impl.C.type) = fn_decl @T.as.I.impl.C [symbolic = @T.as.I.impl.f7b5a3.2.%T.as.I.impl.C (constants.%T.as.I.impl.C)] {\n// CHECK:STDOUT:       %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc19_14.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc19_14.2: type = converted %.loc19_14.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.loc19_14.3: Core.Form = init_form %.loc19_14.2 [concrete = constants.%.262]\n// CHECK:STDOUT:       %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:       %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.as.I.impl.D.decl: @T.as.I.impl.f7b5a3.2.%T.as.I.impl.D.type (%T.as.I.impl.D.type) = fn_decl @T.as.I.impl.D [symbolic = @T.as.I.impl.f7b5a3.2.%T.as.I.impl.D (constants.%T.as.I.impl.D)] {\n// CHECK:STDOUT:       %return.patt: %pattern_type.cb1 = return_slot_pattern [concrete]\n// CHECK:STDOUT:       %return.param_patt: %pattern_type.cb1 = out_param_pattern %return.patt [concrete]\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %.loc20_14.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:       %.loc20_14.2: type = converted %.loc20_14.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:       %.loc20_14.3: Core.Form = init_form %.loc20_14.2 [concrete = constants.%.262]\n// CHECK:STDOUT:       %return.param: ref %empty_tuple.type = out_param call_param0\n// CHECK:STDOUT:       %return: ref %empty_tuple.type = return_slot %return.param\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .B = %T.as.I.impl.B.decl\n// CHECK:STDOUT:     .C = %T.as.I.impl.C.decl\n// CHECK:STDOUT:     .D = %T.as.I.impl.D.decl\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @T.as.I.impl.A(@T.as.I.impl.f7b5a3.1.%T.loc4_14.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @T.as.I.impl.B(@T.as.I.impl.f7b5a3.2.%T.loc15_14.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @T.as.I.impl.C(@T.as.I.impl.f7b5a3.2.%T.loc15_14.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc19_26.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc19_26.2: init %empty_tuple.type = tuple_init () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc19_27: init %empty_tuple.type = converted %.loc19_26.1, %.loc19_26.2 [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     return %.loc19_27\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @T.as.I.impl.D(@T.as.I.impl.f7b5a3.2.%T.loc15_14.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %T.as.I.impl.C.type: type = fn_type @T.as.I.impl.C, @T.as.I.impl.f7b5a3.2(%T) [symbolic = %T.as.I.impl.C.type (constants.%T.as.I.impl.C.type)]\n// CHECK:STDOUT:   %T.as.I.impl.C: @T.as.I.impl.D.%T.as.I.impl.C.type (%T.as.I.impl.C.type) = struct_value () [symbolic = %T.as.I.impl.C (constants.%T.as.I.impl.C)]\n// CHECK:STDOUT:   %T.as.I.impl.C.specific_fn.loc21_12.2: <specific function> = specific_function %T.as.I.impl.C, @T.as.I.impl.C(%T) [symbolic = %T.as.I.impl.C.specific_fn.loc21_12.2 (constants.%T.as.I.impl.C.specific_fn)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() -> out %return.param: %empty_tuple.type {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     %.loc21: @T.as.I.impl.D.%T.as.I.impl.C.type (%T.as.I.impl.C.type) = specific_constant @T.as.I.impl.f7b5a3.2.%T.as.I.impl.C.decl, @T.as.I.impl.f7b5a3.2(constants.%T) [symbolic = %T.as.I.impl.C (constants.%T.as.I.impl.C)]\n// CHECK:STDOUT:     %C.ref: @T.as.I.impl.D.%T.as.I.impl.C.type (%T.as.I.impl.C.type) = name_ref C, %.loc21 [symbolic = %T.as.I.impl.C (constants.%T.as.I.impl.C)]\n// CHECK:STDOUT:     %T.as.I.impl.C.specific_fn.loc21_12.1: <specific function> = specific_function %C.ref, @T.as.I.impl.C(constants.%T) [symbolic = %T.as.I.impl.C.specific_fn.loc21_12.2 (constants.%T.as.I.impl.C.specific_fn)]\n// CHECK:STDOUT:     %T.as.I.impl.C.call: init %empty_tuple.type = call %T.as.I.impl.C.specific_fn.loc21_12.1()\n// CHECK:STDOUT:     return %T.as.I.impl.C.call\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.as.I.impl.f7b5a3.1(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_14.1 => constants.%T\n// CHECK:STDOUT:   %I.impl_witness.loc4_31.2 => constants.%I.impl_witness\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T.as.I.impl.A.type => constants.%T.as.I.impl.A.type\n// CHECK:STDOUT:   %T.as.I.impl.A => constants.%T.as.I.impl.A\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.as.I.impl.A(constants.%T) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.as.I.impl.f7b5a3.2(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_14.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T.as.I.impl.B.type => constants.%T.as.I.impl.B.type\n// CHECK:STDOUT:   %T.as.I.impl.B => constants.%T.as.I.impl.B\n// CHECK:STDOUT:   %T.as.I.impl.C.type => constants.%T.as.I.impl.C.type\n// CHECK:STDOUT:   %T.as.I.impl.C => constants.%T.as.I.impl.C\n// CHECK:STDOUT:   %T.as.I.impl.D.type => constants.%T.as.I.impl.D.type\n// CHECK:STDOUT:   %T.as.I.impl.D => constants.%T.as.I.impl.D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.as.I.impl.B(constants.%T) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.as.I.impl.C(constants.%T) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.as.I.impl.D(constants.%T) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/impl_as.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/impl_as.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/impl_as.carbon\n\ninterface Simple {\n  fn F();\n}\n\nclass C {\n  impl as Simple {\n    fn F() {\n      // C is a complete type here.\n      var unused c: C = {};\n    }\n  }\n}\n\n// CHECK:STDOUT: --- impl_as.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Simple.type: type = facet_type <@Simple> [concrete]\n// CHECK:STDOUT:   %Self.af2: %Simple.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Simple.WithSelf.F.type.75b: type = fn_type @Simple.WithSelf.F, @Simple.WithSelf(%Self.af2) [symbolic]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Simple.WithSelf.F.58c: %Simple.WithSelf.F.type.75b = struct_value () [symbolic]\n// CHECK:STDOUT:   %Simple.assoc_type: type = assoc_entity_type @Simple [concrete]\n// CHECK:STDOUT:   %assoc0.db6: %Simple.assoc_type = assoc_entity element0, @Simple.WithSelf.%Simple.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %Simple.impl_witness: <witness> = impl_witness @C.as.Simple.impl.%Simple.impl_witness_table [concrete]\n// CHECK:STDOUT:   %C.as.Simple.impl.F.type: type = fn_type @C.as.Simple.impl.F [concrete]\n// CHECK:STDOUT:   %C.as.Simple.impl.F: %C.as.Simple.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Simple.facet: %Simple.type = facet_value %C, (%Simple.impl_witness) [concrete]\n// CHECK:STDOUT:   %Simple.WithSelf.F.type.839: type = fn_type @Simple.WithSelf.F, @Simple.WithSelf(%Simple.facet) [concrete]\n// CHECK:STDOUT:   %Simple.WithSelf.F.79e: %Simple.WithSelf.F.type.839 = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type.7c7: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %C.val: %C = struct_value () [concrete]\n// CHECK:STDOUT:   %Destroy.type: type = facet_type <@Destroy> [concrete]\n// CHECK:STDOUT:   %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]\n// CHECK:STDOUT:   %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Destroy = %Core.Destroy\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Destroy: type = import_ref Core//prelude/parts/destroy, Destroy, loaded [concrete = constants.%Destroy.type]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .Simple = %Simple.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %Simple.decl: type = interface_decl @Simple [concrete = constants.%Simple.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Simple {\n// CHECK:STDOUT:   %Self: %Simple.type = symbolic_binding Self, 0 [symbolic = constants.%Self.af2]\n// CHECK:STDOUT:   %Simple.WithSelf.decl = interface_with_self_decl @Simple [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %Simple.WithSelf.F.decl: @Simple.WithSelf.%Simple.WithSelf.F.type (%Simple.WithSelf.F.type.75b) = fn_decl @Simple.WithSelf.F [symbolic = @Simple.WithSelf.%Simple.WithSelf.F (constants.%Simple.WithSelf.F.58c)] {} {}\n// CHECK:STDOUT:   %assoc0: %Simple.assoc_type = assoc_entity element0, %Simple.WithSelf.F.decl [concrete = constants.%assoc0.db6]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F = @Simple.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@Simple.WithSelf.%Simple.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.Simple.impl: %Self.ref as %Simple.ref {\n// CHECK:STDOUT:   %C.as.Simple.impl.F.decl: %C.as.Simple.impl.F.type = fn_decl @C.as.Simple.impl.F [concrete = constants.%C.as.Simple.impl.F] {} {}\n// CHECK:STDOUT:   %Simple.impl_witness_table = impl_witness_table (%C.as.Simple.impl.F.decl), @C.as.Simple.impl [concrete]\n// CHECK:STDOUT:   %Simple.impl_witness: <witness> = impl_witness %Simple.impl_witness_table [concrete = constants.%Simple.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %C.as.Simple.impl.F.decl\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT:   witness = %Simple.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   impl_decl @C.as.Simple.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %Simple.ref: type = name_ref Simple, file.%Simple.decl [concrete = constants.%Simple.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .Simple = <poisoned>\n// CHECK:STDOUT:   .C = <poisoned>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Simple.WithSelf.F(@Simple.%Self: %Simple.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.Simple.impl.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   name_binding_decl {\n// CHECK:STDOUT:     %c.patt: %pattern_type.7c7 = ref_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.var_patt: %pattern_type.7c7 = var_pattern %c.patt [concrete]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %c.var: ref %C = var %c.var_patt\n// CHECK:STDOUT:   %.loc23_26.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %.loc23_26.2: init %C to %c.var = class_init () [concrete = constants.%C.val]\n// CHECK:STDOUT:   %.loc23_7: init %C = converted %.loc23_26.1, %.loc23_26.2 [concrete = constants.%C.val]\n// CHECK:STDOUT:   assign %c.var, %.loc23_7\n// CHECK:STDOUT:   %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:   %c: ref %C = ref_binding c, %c.var\n// CHECK:STDOUT:   %Destroy.Op.bound: <bound method> = bound_method %c.var, constants.%Destroy.Op\n// CHECK:STDOUT:   %Destroy.Op.call: init %empty_tuple.type = call %Destroy.Op.bound(%c.var)\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref %C) = \"no_op\";\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf(constants.%Self.af2) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self.af2\n// CHECK:STDOUT:   %Simple.WithSelf.F.type => constants.%Simple.WithSelf.F.type.75b\n// CHECK:STDOUT:   %Simple.WithSelf.F => constants.%Simple.WithSelf.F.58c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf.F(constants.%Self.af2) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf(constants.%Simple.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Simple.facet\n// CHECK:STDOUT:   %Simple.WithSelf.F.type => constants.%Simple.WithSelf.F.type.839\n// CHECK:STDOUT:   %Simple.WithSelf.F => constants.%Simple.WithSelf.F.79e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf.F(constants.%Simple.facet) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/impl_as_named_constraint.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/impl_as_named_constraint.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/impl_as_named_constraint.carbon\n\n// --- fail_empty_constraint.carbon\nlibrary \"[[@TEST_NAME]]\";\n\nconstraint A {}\n\n// CHECK:STDERR: fail_empty_constraint.carbon:[[@LINE+4]]:1: error: impl as 0 interfaces, expected 1 [ImplOfNotOneInterface]\n// CHECK:STDERR: impl () as A {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as A {}\n\n// --- fail_too_many_interfaces_in_constraint.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A1 {}\ninterface A2 {}\nconstraint B {\n  extend require impls A1;\n  extend require impls A2;\n}\n\n// CHECK:STDERR: fail_too_many_interfaces_in_constraint.carbon:[[@LINE+4]]:1: error: impl as 2 interfaces, expected 1 [ImplOfNotOneInterface]\n// CHECK:STDERR: impl () as B {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as B {}\n\n// --- one_extend_impls_interface_in_constraint.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A {}\nconstraint B {\n  extend require impls A;\n}\n\nimpl () as B {}\n\n// --- fail_one_impls_interface_in_constraint.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A;\nconstraint B {\n  require impls A;\n}\n\n// CHECK:STDERR: fail_one_impls_interface_in_constraint.carbon:[[@LINE+4]]:1: error: impl as 0 interfaces, expected 1 [ImplOfNotOneInterface]\n// CHECK:STDERR: impl () as B {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as B {}\n\n// --- nested_constraints.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A {}\nconstraint B {\n  extend require impls A;\n}\nconstraint C {\n  extend require impls B;\n}\n\nimpl () as C {}\n\n// --- fail_nested_constraints_not_extend_outer.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A {}\n\nconstraint B {\n  extend require impls A;\n}\nconstraint C {\n  require impls B;\n}\n\n// CHECK:STDERR: fail_nested_constraints_not_extend_outer.carbon:[[@LINE+4]]:1: error: impl as 0 interfaces, expected 1 [ImplOfNotOneInterface]\n// CHECK:STDERR: impl () as C {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as C {}\n\n// --- fail_nested_constraints_not_extend_inner.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A {}\n\nconstraint B {\n  require impls A;\n}\nconstraint C {\n  extend require impls B;\n}\n\n// CHECK:STDERR: fail_nested_constraints_not_extend_inner.carbon:[[@LINE+4]]:1: error: impl as 0 interfaces, expected 1 [ImplOfNotOneInterface]\n// CHECK:STDERR: impl () as C {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as C {}\n\n// --- fail_nested_constraints_not_extend_both.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A {}\n\nconstraint B {\n  require impls A;\n}\nconstraint C {\n  require impls B;\n}\n\n// CHECK:STDERR: fail_nested_constraints_not_extend_both.carbon:[[@LINE+4]]:1: error: impl as 0 interfaces, expected 1 [ImplOfNotOneInterface]\n// CHECK:STDERR: impl () as C {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as C {}\n\n// --- fail_duplicate_through_generic_constraint.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A(T:! type) {}\n\nconstraint B(X:! type, Y:! type) {\n  extend require impls A(Y);\n}\n\n// This should impl () as A({}).\nimpl () as B((), {}) {}\n\n// CHECK:STDERR: fail_duplicate_through_generic_constraint.carbon:[[@LINE+7]]:1: error: found non-final `impl` with the same type structure as another non-final `impl` [ImplNonFinalSameTypeStructure]\n// CHECK:STDERR: impl () as A({}) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~\n// CHECK:STDERR: fail_duplicate_through_generic_constraint.carbon:[[@LINE-5]]:1: note: other `impl` here [ImplNonFinalSameTypeStructureNote]\n// CHECK:STDERR: impl () as B((), {}) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as A({}) {}\n\n// --- fail_error_self_in_require.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface A(T:! type) {}\n\n// This makes the type of `Self` into an ErrorInst. No `require` is added to\n// the constraint.\n//@dump-sem-ir-begin\n//\n// CHECK:STDERR: fail_error_self_in_require.carbon:[[@LINE+4]]:18: error: name `Undefined` not found [NameNotFound]\n// CHECK:STDERR: constraint B(X:! Undefined) {\n// CHECK:STDERR:                  ^~~~~~~~~\n// CHECK:STDERR:\nconstraint B(X:! Undefined) {\n  extend require impls A(X);\n}\n//@dump-sem-ir-end\n\nimpl () as B(1) {}\n\n// CHECK:STDOUT: --- fail_error_self_in_require.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %B.type: type = generic_named_constaint_type @B [concrete]\n// CHECK:STDOUT:   %empty_struct: %B.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   %B.decl: %B.type = constraint_decl @B [concrete = constants.%empty_struct] {\n// CHECK:STDOUT:     %X.patt: <error> = symbolic_binding_pattern X, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     <elided>\n// CHECK:STDOUT:     %X: <error> = symbolic_binding X, 0 [concrete = <error>]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic constraint @B(%X: <error>) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   constraint {\n// CHECK:STDOUT:     %Self: <error> = symbolic_binding Self, 1 [concrete = <error>]\n// CHECK:STDOUT:     %B.WithSelf.decl = constraint_with_self_decl @B [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self\n// CHECK:STDOUT:     .A = <poisoned>\n// CHECK:STDOUT:     .X = <poisoned>\n// CHECK:STDOUT:     .A = <poisoned>\n// CHECK:STDOUT:     .X = <poisoned>\n// CHECK:STDOUT:     has_error\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B(<error>) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @B.WithSelf(<error>, <error>) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/impl_assoc_const_with_prelude.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/impl_assoc_const_with_prelude.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/impl_assoc_const_with_prelude.carbon\n\n// --- same_non_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! {.a: bool, .b: (i32, i32)};\n}\nimpl () as I where .X = {.a = true, .b = (1, 2)} and .X = {.a = not false, .b = (3 - 2, 4 / 2)} {}\n\n// --- fail_two_different_non_type.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  let X:! {.a: bool, .b: (i32, i32)};\n}\n// CHECK:STDERR: fail_two_different_non_type.carbon:[[@LINE+4]]:12: error: associated constant `.(I.X)` given two different values `{.a = true, .b = (1, 2)}` and `{.a = false, .b = (3, 4)}` [AssociatedConstantWithDifferentValues]\n// CHECK:STDERR: impl () as I where .X = {.a = true, .b = (1, 2)} and .X = {.a = false, .b = (3, 4)} {}\n// CHECK:STDERR:            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl () as I where .X = {.a = true, .b = (1, 2)} and .X = {.a = false, .b = (3, 4)} {}\n\n// CHECK:STDOUT: --- same_non_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.fe2: type = struct_type {.a: bool, .b: %tuple.type.d07} [concrete]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0.be0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%X [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %.Self.1dc: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self.1dc [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self.1dc, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0.358da: %struct_type.a.b.fe2 = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.type.f94: type = tuple_type (Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.ad8: %tuple.type.f94 = tuple_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.aa4: type = struct_type {.a: bool, .b: %tuple.type.f94} [concrete]\n// CHECK:STDOUT:   %struct.e57: %struct_type.a.b.aa4 = struct_value (%true, %tuple.ad8) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.21c: %tuple.type.d07 = tuple_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %struct.682: %struct_type.a.b.fe2 = struct_value (%true, %tuple.21c) [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %int_3: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %SubWith.type.378: type = generic_interface_type @SubWith [concrete]\n// CHECK:STDOUT:   %SubWith.generic: %SubWith.type.378 = struct_value () [concrete]\n// CHECK:STDOUT:   %SubWith.type.a89: type = facet_type <@SubWith, @SubWith(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %SubWith.impl_witness: <witness> = impl_witness imports.%SubWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %SubWith.facet: %SubWith.type.a89 = facet_value Core.IntLiteral, (%SubWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %SubWith.WithSelf.Op.type.7ed: type = fn_type @SubWith.WithSelf.Op, @SubWith.WithSelf(Core.IntLiteral, %SubWith.facet) [concrete]\n// CHECK:STDOUT:   %.24b: type = fn_type_with_self_type %SubWith.WithSelf.Op.type.7ed, %SubWith.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.SubWith.impl.Op.type: type = fn_type @Core.IntLiteral.as.SubWith.impl.Op [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.SubWith.impl.Op: %Core.IntLiteral.as.SubWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.SubWith.impl.Op.bound: <bound method> = bound_method %int_3, %Core.IntLiteral.as.SubWith.impl.Op [concrete]\n// CHECK:STDOUT:   %int_4: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %DivWith.type.fc9: type = generic_interface_type @DivWith [concrete]\n// CHECK:STDOUT:   %DivWith.generic: %DivWith.type.fc9 = struct_value () [concrete]\n// CHECK:STDOUT:   %DivWith.type.234: type = facet_type <@DivWith, @DivWith(Core.IntLiteral)> [concrete]\n// CHECK:STDOUT:   %DivWith.impl_witness: <witness> = impl_witness imports.%DivWith.impl_witness_table [concrete]\n// CHECK:STDOUT:   %DivWith.facet: %DivWith.type.234 = facet_value Core.IntLiteral, (%DivWith.impl_witness) [concrete]\n// CHECK:STDOUT:   %DivWith.WithSelf.Op.type.04d: type = fn_type @DivWith.WithSelf.Op, @DivWith.WithSelf(Core.IntLiteral, %DivWith.facet) [concrete]\n// CHECK:STDOUT:   %.d00: type = fn_type_with_self_type %DivWith.WithSelf.Op.type.04d, %DivWith.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.DivWith.impl.Op.type: type = fn_type @Core.IntLiteral.as.DivWith.impl.Op [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.DivWith.impl.Op: %Core.IntLiteral.as.DivWith.impl.Op.type = struct_value () [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.DivWith.impl.Op.bound: <bound method> = bound_method %int_4, %Core.IntLiteral.as.DivWith.impl.Op [concrete]\n// CHECK:STDOUT:   %I_where.type: type = facet_type <@I where %impl.elem0.358da = %struct.682> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @empty_tuple.type.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %empty_tuple.type, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     .SubWith = %Core.SubWith\n// CHECK:STDOUT:     .DivWith = %Core.DivWith\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/types/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT:   %Core.SubWith: %SubWith.type.378 = import_ref Core//prelude/operators/arithmetic, SubWith, loaded [concrete = constants.%SubWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.abd97d.1 = import_ref Core//prelude/operators/arithmetic, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.d95: %Core.IntLiteral.as.SubWith.impl.Op.type = import_ref Core//prelude/operators/arithmetic, loc{{\\d+_\\d+}}, loaded [concrete = constants.%Core.IntLiteral.as.SubWith.impl.Op]\n// CHECK:STDOUT:   %SubWith.impl_witness_table = impl_witness_table (%Core.import_ref.abd97d.1, %Core.import_ref.d95), @Core.IntLiteral.as.SubWith.impl [concrete]\n// CHECK:STDOUT:   %Core.DivWith: %DivWith.type.fc9 = import_ref Core//prelude/operators/arithmetic, DivWith, loaded [concrete = constants.%DivWith.generic]\n// CHECK:STDOUT:   %Core.import_ref.abd97d.2 = import_ref Core//prelude/operators/arithmetic, loc{{\\d+_\\d+}}, unloaded\n// CHECK:STDOUT:   %Core.import_ref.93eb: %Core.IntLiteral.as.DivWith.impl.Op.type = import_ref Core//prelude/operators/arithmetic, loc{{\\d+_\\d+}}, loaded [concrete = constants.%Core.IntLiteral.as.DivWith.impl.Op]\n// CHECK:STDOUT:   %DivWith.impl_witness_table = impl_witness_table (%Core.import_ref.abd97d.2, %Core.import_ref.93eb), @Core.IntLiteral.as.DivWith.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_tuple.type.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc6_7.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc6_7.2: type = converted %.loc6_7.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self.1dc]\n// CHECK:STDOUT:     %.Self.ref.loc6_20: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self.1dc]\n// CHECK:STDOUT:     %.Self.as_type.loc6_20: type = facet_access_type %.Self.ref.loc6_20 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc6_20: type = converted %.Self.ref.loc6_20, %.Self.as_type.loc6_20 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %X.ref.loc6_20: %I.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.be0]\n// CHECK:STDOUT:     %impl.elem0.loc6_20: %struct_type.a.b.fe2 = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0.358da]\n// CHECK:STDOUT:     %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %int_2.loc6_46: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %.loc6_47.1: %tuple.type.f94 = tuple_literal (%int_1, %int_2.loc6_46) [concrete = constants.%tuple.ad8]\n// CHECK:STDOUT:     %.loc6_48.1: %struct_type.a.b.aa4 = struct_literal (%true, %.loc6_47.1) [concrete = constants.%struct.e57]\n// CHECK:STDOUT:     %impl.elem0.loc6_47.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc6_47.1: <bound method> = bound_method %int_1, %impl.elem0.loc6_47.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:     %specific_fn.loc6_47.1: <specific function> = specific_function %impl.elem0.loc6_47.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_47.2: <bound method> = bound_method %int_1, %specific_fn.loc6_47.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_47.1: init %i32 = call %bound_method.loc6_47.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc6_47.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_47.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc6_47.3: %i32 = converted %int_1, %.loc6_47.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %impl.elem0.loc6_47.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc6_47.3: <bound method> = bound_method %int_2.loc6_46, %impl.elem0.loc6_47.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:     %specific_fn.loc6_47.2: <specific function> = specific_function %impl.elem0.loc6_47.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_47.4: <bound method> = bound_method %int_2.loc6_46, %specific_fn.loc6_47.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_47.2: init %i32 = call %bound_method.loc6_47.4(%int_2.loc6_46) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc6_47.4: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_47.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc6_47.5: %i32 = converted %int_2.loc6_46, %.loc6_47.4 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %tuple.loc6_47: %tuple.type.d07 = tuple_value (%.loc6_47.3, %.loc6_47.5) [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:     %.loc6_48.2: %tuple.type.d07 = converted %.loc6_47.1, %tuple.loc6_47 [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:     %struct.loc6_48: %struct_type.a.b.fe2 = struct_value (%true, %.loc6_48.2) [concrete = constants.%struct.682]\n// CHECK:STDOUT:     %.loc6_48.3: %struct_type.a.b.fe2 = converted %.loc6_48.1, %struct.loc6_48 [concrete = constants.%struct.682]\n// CHECK:STDOUT:     %.Self.ref.loc6_54: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self.1dc]\n// CHECK:STDOUT:     %.Self.as_type.loc6_54: type = facet_access_type %.Self.ref.loc6_54 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc6_54: type = converted %.Self.ref.loc6_54, %.Self.as_type.loc6_54 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %X.ref.loc6_54: %I.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.be0]\n// CHECK:STDOUT:     %impl.elem0.loc6_54: %struct_type.a.b.fe2 = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0.358da]\n// CHECK:STDOUT:     %impl.elem0.subst: %struct_type.a.b.fe2 = impl_witness_access_substituted %impl.elem0.loc6_54, %.loc6_48.3 [concrete = constants.%struct.682]\n// CHECK:STDOUT:     %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:     %.loc6_65: bool = not %false [concrete = constants.%true]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3]\n// CHECK:STDOUT:     %int_2.loc6_86: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %impl.elem1.loc6_84: %.24b = impl_witness_access constants.%SubWith.impl_witness, element1 [concrete = constants.%Core.IntLiteral.as.SubWith.impl.Op]\n// CHECK:STDOUT:     %bound_method.loc6_84: <bound method> = bound_method %int_3, %impl.elem1.loc6_84 [concrete = constants.%Core.IntLiteral.as.SubWith.impl.Op.bound]\n// CHECK:STDOUT:     %Core.IntLiteral.as.SubWith.impl.Op.call: init Core.IntLiteral = call %bound_method.loc6_84(%int_3, %int_2.loc6_86) [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4]\n// CHECK:STDOUT:     %int_2.loc6_93: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %impl.elem1.loc6_91: %.d00 = impl_witness_access constants.%DivWith.impl_witness, element1 [concrete = constants.%Core.IntLiteral.as.DivWith.impl.Op]\n// CHECK:STDOUT:     %bound_method.loc6_91: <bound method> = bound_method %int_4, %impl.elem1.loc6_91 [concrete = constants.%Core.IntLiteral.as.DivWith.impl.Op.bound]\n// CHECK:STDOUT:     %Core.IntLiteral.as.DivWith.impl.Op.call: init Core.IntLiteral = call %bound_method.loc6_91(%int_4, %int_2.loc6_93) [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %.loc6_94.1: %tuple.type.f94 = tuple_literal (%Core.IntLiteral.as.SubWith.impl.Op.call, %Core.IntLiteral.as.DivWith.impl.Op.call) [concrete = constants.%tuple.ad8]\n// CHECK:STDOUT:     %.loc6_95.1: %struct_type.a.b.aa4 = struct_literal (%.loc6_65, %.loc6_94.1) [concrete = constants.%struct.e57]\n// CHECK:STDOUT:     %impl.elem0.loc6_94.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc6_94.1: <bound method> = bound_method %Core.IntLiteral.as.SubWith.impl.Op.call, %impl.elem0.loc6_94.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:     %specific_fn.loc6_94.1: <specific function> = specific_function %impl.elem0.loc6_94.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_94.2: <bound method> = bound_method %Core.IntLiteral.as.SubWith.impl.Op.call, %specific_fn.loc6_94.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:     %.loc6_84.1: Core.IntLiteral = value_of_initializer %Core.IntLiteral.as.SubWith.impl.Op.call [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %.loc6_84.2: Core.IntLiteral = converted %Core.IntLiteral.as.SubWith.impl.Op.call, %.loc6_84.1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_94.1: init %i32 = call %bound_method.loc6_94.2(%.loc6_84.2) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc6_94.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_94.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc6_94.3: %i32 = converted %Core.IntLiteral.as.SubWith.impl.Op.call, %.loc6_94.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %impl.elem0.loc6_94.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc6_94.3: <bound method> = bound_method %Core.IntLiteral.as.DivWith.impl.Op.call, %impl.elem0.loc6_94.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:     %specific_fn.loc6_94.2: <specific function> = specific_function %impl.elem0.loc6_94.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc6_94.4: <bound method> = bound_method %Core.IntLiteral.as.DivWith.impl.Op.call, %specific_fn.loc6_94.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:     %.loc6_91.1: Core.IntLiteral = value_of_initializer %Core.IntLiteral.as.DivWith.impl.Op.call [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %.loc6_91.2: Core.IntLiteral = converted %Core.IntLiteral.as.DivWith.impl.Op.call, %.loc6_91.1 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_94.2: init %i32 = call %bound_method.loc6_94.4(%.loc6_91.2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc6_94.4: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc6_94.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc6_94.5: %i32 = converted %Core.IntLiteral.as.DivWith.impl.Op.call, %.loc6_94.4 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %tuple.loc6_94: %tuple.type.d07 = tuple_value (%.loc6_94.3, %.loc6_94.5) [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:     %.loc6_95.2: %tuple.type.d07 = converted %.loc6_94.1, %tuple.loc6_94 [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:     %struct.loc6_95: %struct_type.a.b.fe2 = struct_value (%.loc6_65, %.loc6_95.2) [concrete = constants.%struct.682]\n// CHECK:STDOUT:     %.loc6_95.3: %struct_type.a.b.fe2 = converted %.loc6_95.1, %struct.loc6_95 [concrete = constants.%struct.682]\n// CHECK:STDOUT:     %.loc6_14: type = where_expr %.Self [concrete = constants.%I_where.type] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc6_20, %.loc6_48.3\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst, %.loc6_95.3\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %X: %struct_type.a.b.fe2 = assoc_const_decl @X [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%X [concrete = constants.%assoc0.be0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .X = @X.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%X)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_tuple.type.as.I.impl: %.loc6_7.2 as %.loc6_14 {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%impl_witness_assoc_constant), @empty_tuple.type.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %impl_witness_assoc_constant: %struct_type.a.b.fe2 = impl_witness_assoc_constant constants.%struct.682 [concrete = constants.%struct.682]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self.1dc) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_two_different_non_type.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self.ab9: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Bool.type: type = fn_type @Bool [concrete]\n// CHECK:STDOUT:   %Bool: %Bool.type = struct_value () [concrete]\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %Int.type: type = generic_class_type @Int [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %Int.generic: %Int.type = struct_value () [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %tuple.type.d07: type = tuple_type (%i32, %i32) [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.fe2: type = struct_type {.a: bool, .b: %tuple.type.d07} [concrete]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0.be0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%X [concrete]\n// CHECK:STDOUT:   %empty_tuple: %empty_tuple.type = tuple_value () [concrete]\n// CHECK:STDOUT:   %.Self: %I.type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %.Self.binding.as_type: type = symbolic_binding_type .Self, %.Self [symbolic_self]\n// CHECK:STDOUT:   %I.lookup_impl_witness: <witness> = lookup_impl_witness %.Self, @I [symbolic_self]\n// CHECK:STDOUT:   %impl.elem0.358: %struct_type.a.b.fe2 = impl_witness_access %I.lookup_impl_witness, element0 [symbolic_self]\n// CHECK:STDOUT:   %true: bool = bool_literal true [concrete]\n// CHECK:STDOUT:   %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.type.f94: type = tuple_type (Core.IntLiteral, Core.IntLiteral) [concrete]\n// CHECK:STDOUT:   %tuple.ad8: %tuple.type.f94 = tuple_value (%int_1.5b8, %int_2.ecc) [concrete]\n// CHECK:STDOUT:   %struct_type.a.b.aa4: type = struct_type {.a: bool, .b: %tuple.type.f94} [concrete]\n// CHECK:STDOUT:   %struct.e57: %struct_type.a.b.aa4 = struct_value (%true, %tuple.ad8) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]\n// CHECK:STDOUT:   %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %bound_method.38b: <bound method> = bound_method %int_1.5b8, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_1.5d2: %i32 = int_value 1 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %tuple.21c: %tuple.type.d07 = tuple_value (%int_1.5d2, %int_2.ef8) [concrete]\n// CHECK:STDOUT:   %struct.682: %struct_type.a.b.fe2 = struct_value (%true, %tuple.21c) [concrete]\n// CHECK:STDOUT:   %false: bool = bool_literal false [concrete]\n// CHECK:STDOUT:   %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]\n// CHECK:STDOUT:   %int_4.0c1: Core.IntLiteral = int_value 4 [concrete]\n// CHECK:STDOUT:   %tuple.302: %tuple.type.f94 = tuple_value (%int_3.1ba, %int_4.0c1) [concrete]\n// CHECK:STDOUT:   %struct.1ec: %struct_type.a.b.aa4 = struct_value (%false, %tuple.302) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.fa7: <bound method> = bound_method %int_3.1ba, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_3.822: %i32 = int_value 3 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.6d7: <bound method> = bound_method %int_4.0c1, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_4.940: %i32 = int_value 4 [concrete]\n// CHECK:STDOUT:   %tuple.ffd: %tuple.type.d07 = tuple_value (%int_3.822, %int_4.940) [concrete]\n// CHECK:STDOUT:   %struct.68c: %struct_type.a.b.fe2 = struct_value (%false, %tuple.ffd) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core: <namespace> = namespace file.%Core.import, [concrete] {\n// CHECK:STDOUT:     .Bool = %Core.Bool\n// CHECK:STDOUT:     .Int = %Core.Int\n// CHECK:STDOUT:     .ImplicitAs = %Core.ImplicitAs\n// CHECK:STDOUT:     import Core//prelude\n// CHECK:STDOUT:     import Core//prelude/...\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.Bool: %Bool.type = import_ref Core//prelude/types/bool, Bool, loaded [concrete = constants.%Bool]\n// CHECK:STDOUT:   %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]\n// CHECK:STDOUT:   %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/types/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Core = imports.%Core\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Core.import = import Core\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   impl_decl @empty_tuple.type.as.<error>.impl [concrete] {} {\n// CHECK:STDOUT:     %.loc10_7.1: %empty_tuple.type = tuple_literal () [concrete = constants.%empty_tuple]\n// CHECK:STDOUT:     %.loc10_7.2: type = converted %.loc10_7.1, constants.%empty_tuple.type [concrete = constants.%empty_tuple.type]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:     %.Self: %I.type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.ref.loc10_20: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc10_20: type = facet_access_type %.Self.ref.loc10_20 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc10_20: type = converted %.Self.ref.loc10_20, %.Self.as_type.loc10_20 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %X.ref.loc10_20: %I.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.be0]\n// CHECK:STDOUT:     %impl.elem0.loc10_20: %struct_type.a.b.fe2 = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0.358]\n// CHECK:STDOUT:     %true: bool = bool_literal true [concrete = constants.%true]\n// CHECK:STDOUT:     %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]\n// CHECK:STDOUT:     %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:     %.loc10_47.1: %tuple.type.f94 = tuple_literal (%int_1, %int_2) [concrete = constants.%tuple.ad8]\n// CHECK:STDOUT:     %.loc10_48.1: %struct_type.a.b.aa4 = struct_literal (%true, %.loc10_47.1) [concrete = constants.%struct.e57]\n// CHECK:STDOUT:     %impl.elem0.loc10_47.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc10_47.1: <bound method> = bound_method %int_1, %impl.elem0.loc10_47.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.215]\n// CHECK:STDOUT:     %specific_fn.loc10_47.1: <specific function> = specific_function %impl.elem0.loc10_47.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc10_47.2: <bound method> = bound_method %int_1, %specific_fn.loc10_47.1 [concrete = constants.%bound_method.38b]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_47.1: init %i32 = call %bound_method.loc10_47.2(%int_1) [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc10_47.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_47.1 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %.loc10_47.3: %i32 = converted %int_1, %.loc10_47.2 [concrete = constants.%int_1.5d2]\n// CHECK:STDOUT:     %impl.elem0.loc10_47.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc10_47.3: <bound method> = bound_method %int_2, %impl.elem0.loc10_47.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:     %specific_fn.loc10_47.2: <specific function> = specific_function %impl.elem0.loc10_47.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc10_47.4: <bound method> = bound_method %int_2, %specific_fn.loc10_47.2 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_47.2: init %i32 = call %bound_method.loc10_47.4(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc10_47.4: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_47.2 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %.loc10_47.5: %i32 = converted %int_2, %.loc10_47.4 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:     %tuple.loc10_47: %tuple.type.d07 = tuple_value (%.loc10_47.3, %.loc10_47.5) [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:     %.loc10_48.2: %tuple.type.d07 = converted %.loc10_47.1, %tuple.loc10_47 [concrete = constants.%tuple.21c]\n// CHECK:STDOUT:     %struct.loc10_48: %struct_type.a.b.fe2 = struct_value (%true, %.loc10_48.2) [concrete = constants.%struct.682]\n// CHECK:STDOUT:     %.loc10_48.3: %struct_type.a.b.fe2 = converted %.loc10_48.1, %struct.loc10_48 [concrete = constants.%struct.682]\n// CHECK:STDOUT:     %.Self.ref.loc10_54: %I.type = name_ref .Self, %.Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:     %.Self.as_type.loc10_54: type = facet_access_type %.Self.ref.loc10_54 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %.loc10_54: type = converted %.Self.ref.loc10_54, %.Self.as_type.loc10_54 [symbolic_self = constants.%.Self.binding.as_type]\n// CHECK:STDOUT:     %X.ref.loc10_54: %I.assoc_type = name_ref X, @X.%assoc0 [concrete = constants.%assoc0.be0]\n// CHECK:STDOUT:     %impl.elem0.loc10_54: %struct_type.a.b.fe2 = impl_witness_access constants.%I.lookup_impl_witness, element0 [symbolic_self = constants.%impl.elem0.358]\n// CHECK:STDOUT:     %impl.elem0.subst: %struct_type.a.b.fe2 = impl_witness_access_substituted %impl.elem0.loc10_54, %.loc10_48.3 [concrete = constants.%struct.682]\n// CHECK:STDOUT:     %false: bool = bool_literal false [concrete = constants.%false]\n// CHECK:STDOUT:     %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]\n// CHECK:STDOUT:     %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4.0c1]\n// CHECK:STDOUT:     %.loc10_82.1: %tuple.type.f94 = tuple_literal (%int_3, %int_4) [concrete = constants.%tuple.302]\n// CHECK:STDOUT:     %.loc10_83.1: %struct_type.a.b.aa4 = struct_literal (%false, %.loc10_82.1) [concrete = constants.%struct.1ec]\n// CHECK:STDOUT:     %impl.elem0.loc10_82.1: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc10_82.1: <bound method> = bound_method %int_3, %impl.elem0.loc10_82.1 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.061]\n// CHECK:STDOUT:     %specific_fn.loc10_82.1: <specific function> = specific_function %impl.elem0.loc10_82.1, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc10_82.2: <bound method> = bound_method %int_3, %specific_fn.loc10_82.1 [concrete = constants.%bound_method.fa7]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_82.1: init %i32 = call %bound_method.loc10_82.2(%int_3) [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %.loc10_82.2: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_82.1 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %.loc10_82.3: %i32 = converted %int_3, %.loc10_82.2 [concrete = constants.%int_3.822]\n// CHECK:STDOUT:     %impl.elem0.loc10_82.2: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:     %bound_method.loc10_82.3: <bound method> = bound_method %int_4, %impl.elem0.loc10_82.2 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.f0c]\n// CHECK:STDOUT:     %specific_fn.loc10_82.2: <specific function> = specific_function %impl.elem0.loc10_82.2, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:     %bound_method.loc10_82.4: <bound method> = bound_method %int_4, %specific_fn.loc10_82.2 [concrete = constants.%bound_method.6d7]\n// CHECK:STDOUT:     %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_82.2: init %i32 = call %bound_method.loc10_82.4(%int_4) [concrete = constants.%int_4.940]\n// CHECK:STDOUT:     %.loc10_82.4: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_82.2 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:     %.loc10_82.5: %i32 = converted %int_4, %.loc10_82.4 [concrete = constants.%int_4.940]\n// CHECK:STDOUT:     %tuple.loc10_82: %tuple.type.d07 = tuple_value (%.loc10_82.3, %.loc10_82.5) [concrete = constants.%tuple.ffd]\n// CHECK:STDOUT:     %.loc10_83.2: %tuple.type.d07 = converted %.loc10_82.1, %tuple.loc10_82 [concrete = constants.%tuple.ffd]\n// CHECK:STDOUT:     %struct.loc10_83: %struct_type.a.b.fe2 = struct_value (%false, %.loc10_83.2) [concrete = constants.%struct.68c]\n// CHECK:STDOUT:     %.loc10_83.3: %struct_type.a.b.fe2 = converted %.loc10_83.1, %struct.loc10_83 [concrete = constants.%struct.68c]\n// CHECK:STDOUT:     %.loc10_14: type = where_expr %.Self [concrete = <error>] {\n// CHECK:STDOUT:       requirement_base_facet_type constants.%I.type\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.loc10_20, %.loc10_48.3\n// CHECK:STDOUT:       requirement_rewrite %impl.elem0.subst, %.loc10_83.3\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self.ab9]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %X: %struct_type.a.b.fe2 = assoc_const_decl @X [concrete] {\n// CHECK:STDOUT:     %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%X [concrete = constants.%assoc0.be0]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .X = @X.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%X)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @empty_tuple.type.as.<error>.impl: %.loc10_7.2 as %.loc10_14 {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = <error>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self.ab9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%.Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/impl_forall.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/impl_forall.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/impl_forall.carbon\n\ninterface Simple {\n  fn F();\n}\n\nimpl forall [T:! type] T as Simple {\n  fn F() {}\n}\n\n// CHECK:STDOUT: --- impl_forall.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %Simple.type: type = facet_type <@Simple> [concrete]\n// CHECK:STDOUT:   %Self: %Simple.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %Simple.WithSelf.F.type.75b: type = fn_type @Simple.WithSelf.F, @Simple.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %Simple.WithSelf.F.58c: %Simple.WithSelf.F.type.75b = struct_value () [symbolic]\n// CHECK:STDOUT:   %Simple.assoc_type: type = assoc_entity_type @Simple [concrete]\n// CHECK:STDOUT:   %assoc0: %Simple.assoc_type = assoc_entity element0, @Simple.WithSelf.%Simple.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %Simple.impl_witness: <witness> = impl_witness @T.as.Simple.impl.%Simple.impl_witness_table, @T.as.Simple.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.Simple.impl.F.type: type = fn_type @T.as.Simple.impl.F, @T.as.Simple.impl(%T) [symbolic]\n// CHECK:STDOUT:   %T.as.Simple.impl.F: %T.as.Simple.impl.F.type = struct_value () [symbolic]\n// CHECK:STDOUT:   %Simple.facet: %Simple.type = facet_value %T, (%Simple.impl_witness) [symbolic]\n// CHECK:STDOUT:   %Simple.WithSelf.F.type.b56: type = fn_type @Simple.WithSelf.F, @Simple.WithSelf(%Simple.facet) [symbolic]\n// CHECK:STDOUT:   %Simple.WithSelf.F.2ed: %Simple.WithSelf.F.type.b56 = struct_value () [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .Simple = %Simple.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %Simple.decl: type = interface_decl @Simple [concrete = constants.%Simple.type] {} {}\n// CHECK:STDOUT:   impl_decl @T.as.Simple.impl [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc19_14.2 [symbolic = %T.loc19_14.1 (constants.%T)]\n// CHECK:STDOUT:     %Simple.ref: type = name_ref Simple, file.%Simple.decl [concrete = constants.%Simple.type]\n// CHECK:STDOUT:     %.loc19_18.1: type = splice_block %.loc19_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc19_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc19_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc19_14.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @Simple {\n// CHECK:STDOUT:   %Self: %Simple.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Simple.WithSelf.decl = interface_with_self_decl @Simple [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %Simple.WithSelf.F.decl: @Simple.WithSelf.%Simple.WithSelf.F.type (%Simple.WithSelf.F.type.75b) = fn_decl @Simple.WithSelf.F [symbolic = @Simple.WithSelf.%Simple.WithSelf.F (constants.%Simple.WithSelf.F.58c)] {} {}\n// CHECK:STDOUT:   %assoc0: %Simple.assoc_type = assoc_entity element0, %Simple.WithSelf.F.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F = @Simple.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@Simple.WithSelf.%Simple.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @T.as.Simple.impl(%T.loc19_14.2: type) {\n// CHECK:STDOUT:   %T.loc19_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc19_14.1 (constants.%T)]\n// CHECK:STDOUT:   %Simple.impl_witness.loc19_36.2: <witness> = impl_witness %Simple.impl_witness_table, @T.as.Simple.impl(%T.loc19_14.1) [symbolic = %Simple.impl_witness.loc19_36.2 (constants.%Simple.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T.as.Simple.impl.F.type: type = fn_type @T.as.Simple.impl.F, @T.as.Simple.impl(%T.loc19_14.1) [symbolic = %T.as.Simple.impl.F.type (constants.%T.as.Simple.impl.F.type)]\n// CHECK:STDOUT:   %T.as.Simple.impl.F: @T.as.Simple.impl.%T.as.Simple.impl.F.type (%T.as.Simple.impl.F.type) = struct_value () [symbolic = %T.as.Simple.impl.F (constants.%T.as.Simple.impl.F)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %T.ref as %Simple.ref {\n// CHECK:STDOUT:     %T.as.Simple.impl.F.decl: @T.as.Simple.impl.%T.as.Simple.impl.F.type (%T.as.Simple.impl.F.type) = fn_decl @T.as.Simple.impl.F [symbolic = @T.as.Simple.impl.%T.as.Simple.impl.F (constants.%T.as.Simple.impl.F)] {} {}\n// CHECK:STDOUT:     %Simple.impl_witness_table = impl_witness_table (%T.as.Simple.impl.F.decl), @T.as.Simple.impl [concrete]\n// CHECK:STDOUT:     %Simple.impl_witness.loc19_36.1: <witness> = impl_witness %Simple.impl_witness_table, @T.as.Simple.impl(constants.%T) [symbolic = %Simple.impl_witness.loc19_36.2 (constants.%Simple.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .F = %T.as.Simple.impl.F.decl\n// CHECK:STDOUT:     witness = %Simple.impl_witness.loc19_36.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @Simple.WithSelf.F(@Simple.%Self: %Simple.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @T.as.Simple.impl.F(@T.as.Simple.impl.%T.loc19_14.2: type) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   fn() {\n// CHECK:STDOUT:   !entry:\n// CHECK:STDOUT:     return\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %Simple.WithSelf.F.type => constants.%Simple.WithSelf.F.type.75b\n// CHECK:STDOUT:   %Simple.WithSelf.F => constants.%Simple.WithSelf.F.58c\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf.F(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.as.Simple.impl(constants.%T) {\n// CHECK:STDOUT:   %T.loc19_14.1 => constants.%T\n// CHECK:STDOUT:   %Simple.impl_witness.loc19_36.2 => constants.%Simple.impl_witness\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T.as.Simple.impl.F.type => constants.%T.as.Simple.impl.F.type\n// CHECK:STDOUT:   %T.as.Simple.impl.F => constants.%T.as.Simple.impl.F\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @T.as.Simple.impl.F(constants.%T) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf(constants.%Simple.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Simple.facet\n// CHECK:STDOUT:   %Simple.WithSelf.F.type => constants.%Simple.WithSelf.F.type.b56\n// CHECK:STDOUT:   %Simple.WithSelf.F => constants.%Simple.WithSelf.F.2ed\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @Simple.WithSelf.F(constants.%Simple.facet) {}\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/impl_self_as.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/impl_self_as.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/impl_self_as.carbon\n\n// --- match.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I1 {}\ninterface I2 {}\ninterface J1(T1:! type) {}\ninterface J2(T2:! type) {}\n\n// `impl Self as` should match `impl as`, so these should not trigger impl\n// declaration without definition diagnostics.\n\nclass C1 {\n  impl Self as I1;\n  impl as I1 {}\n\n  impl as I2;\n  impl Self as I2 {}\n\n  impl forall [U:! type] Self as J1(U);\n  impl forall [U:! type] as J1(U) {}\n\n  impl forall [V:! type] as J2(V);\n  impl forall [V:! type] Self as J2(V) {}\n}\n\nclass C2(W:! type) {\n  impl Self as I1;\n  impl as I1 {}\n\n  impl as I2;\n  impl Self as I2 {}\n\n  impl forall [X:! type] Self as J1(X);\n  impl forall [X:! type] as J1(X) {}\n\n  impl forall [Y:! type] as J2(Y);\n  impl forall [Y:! type] Self as J2(Y) {}\n}\n\n\n// --- fail_no_match.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I3 {}\ninterface I4 {}\ninterface I5 {}\ninterface I6 {}\ninterface J3(T3:! type) {}\ninterface J4(T4:! type) {}\ninterface J5(T5:! type) {}\ninterface J6(T6:! type) {}\n\n// `impl C as` should not match `impl Self as` or `impl as`.\n\nclass C3 {\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl C3 as I3;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl C3 as I3;\n  impl as I3 {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl C3 as I4;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl C3 as I4;\n  impl Self as I4 {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl as I5;\n  // CHECK:STDERR:   ^~~~~~~~~~~\n  // CHECK:STDERR:\n  impl as I5;\n  impl C3 as I5 {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl Self as I6;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl Self as I6;\n  impl C3 as I6 {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl forall [Z3:! type] C3 as J3(Z3);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl forall [Z3:! type] C3 as J3(Z3);\n  impl forall [Z3:! type] as J3(Z3) {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl forall [Z4:! type] C3 as J4(Z4);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl forall [Z4:! type] C3 as J4(Z4);\n  impl forall [Z4:! type] Self as J4(Z4) {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl forall [Z5:! type] as J5(Z5);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl forall [Z5:! type] as J5(Z5);\n  impl forall [Z5:! type] C3 as J5(Z5) {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl forall [Z6:! type] Self as J6(Z6);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl forall [Z6:! type] Self as J6(Z6);\n  impl forall [Z6:! type] C3 as J6(Z6) {}\n}\n\nclass C4(A:! type) {\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl C4(A) as I3;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl C4(A) as I3;\n  impl as I3 {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl C4(A) as I4;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl C4(A) as I4;\n  impl Self as I4 {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl as I5;\n  // CHECK:STDERR:   ^~~~~~~~~~~\n  // CHECK:STDERR:\n  impl as I5;\n  impl C4(A) as I5 {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl Self as I6;\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl Self as I6;\n  impl C4(A) as I6 {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl forall [B3:! type] C4(A) as J3(B3);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl forall [B3:! type] C4(A) as J3(B3);\n  impl forall [B3:! type] as J3(B3) {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl forall [B4:! type] C4(A) as J4(B4);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl forall [B4:! type] C4(A) as J4(B4);\n  impl forall [B4:! type] Self as J4(B4) {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl forall [B5:! type] as J5(B5);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl forall [B5:! type] as J5(B5);\n  impl forall [B5:! type] C4(A) as J5(B5) {}\n\n  // CHECK:STDERR: fail_no_match.carbon:[[@LINE+4]]:3: error: impl declared but not defined [ImplMissingDefinition]\n  // CHECK:STDERR:   impl forall [B6:! type] Self as J6(B6);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  impl forall [B6:! type] Self as J6(B6);\n  impl forall [B6:! type] C4(A) as J6(B6) {}\n}\n"
  },
  {
    "path": "toolchain/check/testdata/impl/impl_thunk_min_prelude.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/int.carbon\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/impl_thunk_min_prelude.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/impl_thunk_min_prelude.carbon\n\n// --- convert_in_class.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface X(T:! type, U:! type) {\n  fn F(t: T) -> U;\n}\n\nclass ConvertsToA {}\nclass ConvertsToB {}\n\n// Check that we don't try to define a thunk for `A.B.(as X).F` until we reach\n// the end of `A`. If we tried earlier, we wouldn't find a conversion from\n// `ConvertsToA` to `A` or from `ConvertsToB` to `B`.\nclass A {\n  class B {\n    impl as X(ConvertsToA, B) {\n      fn F(a: A) -> ConvertsToB;\n    }\n\n    impl ConvertsToB as Core.ImplicitAs(B) {\n      fn Convert[unused self: Self]() -> B { return {}; }\n    }\n  }\n\n  impl ConvertsToA as Core.ImplicitAs(A) {\n    fn Convert[unused self: Self]() -> A { return {}; }\n  }\n}\n\n// --- fail_todo_out_of_line_thunk.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Wrap(T:! type) {}\n\ninterface OpWith(U:! type) {\n  fn Op[self: Self](u: U);\n}\n\nimpl forall [T:! type, U:! Core.ImplicitAs(Wrap(T))] Wrap(T) as OpWith(U) {\n  // CHECK:STDERR: fail_todo_out_of_line_thunk.carbon:[[@LINE+7]]:3: error: use of undefined generic function [MissingGenericFunctionDefinition]\n  // CHECK:STDERR:   fn Op[self: Self](other: Self);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR: fail_todo_out_of_line_thunk.carbon:[[@LINE+4]]:3: note: generic function declared here [MissingGenericFunctionDefinitionHere]\n  // CHECK:STDERR:   fn Op[self: Self](other: Self);\n  // CHECK:STDERR:   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n  // CHECK:STDERR:\n  fn Op[self: Self](other: Self);\n}\n\n// TODO: Once we support the syntax for defining impl members out of line,\n// define the above function here.\n// fn (forall [T:! type, U:! Core.ImplicitAs(Wrap(T))] Wrap(T) as OpWith(U)).Op[self: Self](other: Self) {}\n\n// --- builtin_thunk.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass Wrap(T:! type) {}\n\ninterface OpWith(U:! type) {\n  fn Op[self: Self](u: U);\n}\n\nimpl forall [T:! type, U:! Core.ImplicitAs(Wrap(T))] Wrap(T) as OpWith(U) {\n  fn Op[self: Self](other: Self) = \"no_op\";\n}\n\n// --- thunk_literal_convert.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface Add(T:! type) {\n  fn Op(a: Self, b: T) -> Self;\n}\nimpl forall [T:! Core.ImplicitAs(i32)] i32 as Add(T) {\n  fn Op(a: Self, b: Self) -> Self = \"int.sadd\";\n}\n\nfn Call() -> i32 {\n  let a: i32 = 1;\n  // The conversion from 2 to IntLiteral here relies on having the\n  // constant value available, so is only possible if the thunk is\n  // inlined.\n  return i32.(Add(Core.IntLiteral()).Op)\n  //@dump-sem-ir-begin\n        (a, 2)\n  //@dump-sem-ir-end\n  ;\n}\n\n// CHECK:STDOUT: --- thunk_literal_convert.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %int_32: Core.IntLiteral = int_value 32 [concrete]\n// CHECK:STDOUT:   %i32: type = class_type @Int, @Int(%int_32) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.type.e8c: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]\n// CHECK:STDOUT:   %To: Core.IntLiteral = symbolic_binding To, 0 [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%To) [symbolic]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6 = struct_value () [symbolic]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness.6bc: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.74f, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d: type = fn_type @Core.IntLiteral.as.ImplicitAs.impl.Convert, @Core.IntLiteral.as.ImplicitAs.impl(%int_32) [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5: %Core.IntLiteral.as.ImplicitAs.impl.Convert.type.e0d = struct_value () [concrete]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.6bc) [concrete]\n// CHECK:STDOUT:   %ImplicitAs.WithSelf.Convert.type.b37: type = fn_type @ImplicitAs.WithSelf.Convert, @ImplicitAs.WithSelf(%i32, %ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %.545: type = fn_type_with_self_type %ImplicitAs.WithSelf.Convert.type.b37, %ImplicitAs.facet [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn: <specific function> = specific_function %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5, @Core.IntLiteral.as.ImplicitAs.impl.Convert(%int_32) [concrete]\n// CHECK:STDOUT:   %i32.as.Add.impl.Op.type.73828b.1: type = fn_type @i32.as.Add.impl.Op.loc8_35.1, @i32.as.Add.impl(%ImplicitAs.facet) [concrete]\n// CHECK:STDOUT:   %i32.as.Add.impl.Op.0aa775.1: %i32.as.Add.impl.Op.type.73828b.1 = struct_value () [concrete]\n// CHECK:STDOUT:   %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5 [concrete]\n// CHECK:STDOUT:   %bound_method.646: <bound method> = bound_method %int_2.ecc, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]\n// CHECK:STDOUT:   %int_2.ef8: %i32 = int_value 2 [concrete]\n// CHECK:STDOUT:   %i32.as.Add.impl.Op.specific_fn.0f6a75.2: <specific function> = specific_function %i32.as.Add.impl.Op.0aa775.1, @i32.as.Add.impl.Op.loc8_35.1(%ImplicitAs.facet) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Core.import_ref.42d: @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert.type (%Core.IntLiteral.as.ImplicitAs.impl.Convert.type.4e6) = import_ref Core//prelude/parts/int, loc{{\\d+_\\d+}}, loaded [symbolic = @Core.IntLiteral.as.ImplicitAs.impl.%Core.IntLiteral.as.ImplicitAs.impl.Convert (constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.3c2)]\n// CHECK:STDOUT:   %ImplicitAs.impl_witness_table.74f = impl_witness_table (%Core.import_ref.42d), @Core.IntLiteral.as.ImplicitAs.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @Call() -> out %return.param: %i32 {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %a.ref: %i32 = name_ref a, %a\n// CHECK:STDOUT:   %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]\n// CHECK:STDOUT:   %ImplicitAs.facet: %ImplicitAs.type.e8c = facet_value Core.IntLiteral, (constants.%ImplicitAs.impl_witness.6bc) [concrete = constants.%ImplicitAs.facet]\n// CHECK:STDOUT:   %.loc18_14.1: %ImplicitAs.type.e8c = converted Core.IntLiteral, %ImplicitAs.facet [concrete = constants.%ImplicitAs.facet]\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT:   %.loc18_14.2: %i32.as.Add.impl.Op.type.73828b.1 = specific_constant @i32.as.Add.impl.%i32.as.Add.impl.Op.decl.loc8_35.1, @i32.as.Add.impl(constants.%ImplicitAs.facet) [concrete = constants.%i32.as.Add.impl.Op.0aa775.1]\n// CHECK:STDOUT:   %Op.ref.loc18: %i32.as.Add.impl.Op.type.73828b.1 = name_ref Op, %.loc18_14.2 [concrete = constants.%i32.as.Add.impl.Op.0aa775.1]\n// CHECK:STDOUT:   %impl.elem0.loc18_14: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_14.1: <bound method> = bound_method %int_2, %impl.elem0.loc18_14 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc18_14: <specific function> = specific_function %impl.elem0.loc18_14, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_14.2: <bound method> = bound_method %int_2, %specific_fn.loc18_14 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_14: init %i32 = call %bound_method.loc18_14.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_14.3: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_14 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_14.4: %i32 = converted %int_2, %.loc18_14.3 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %i32.as.Add.impl.Op.specific_fn: <specific function> = specific_function %Op.ref.loc18, @i32.as.Add.impl.Op.loc8_35.1(constants.%ImplicitAs.facet) [concrete = constants.%i32.as.Add.impl.Op.specific_fn.0f6a75.2]\n// CHECK:STDOUT:   %impl.elem0.loc18_13: %.545 = impl_witness_access constants.%ImplicitAs.impl_witness.6bc, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.0b5]\n// CHECK:STDOUT:   %bound_method.loc18_13.1: <bound method> = bound_method %int_2, %impl.elem0.loc18_13 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.4e5]\n// CHECK:STDOUT:   %specific_fn.loc18_13: <specific function> = specific_function %impl.elem0.loc18_13, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]\n// CHECK:STDOUT:   %bound_method.loc18_13.2: <bound method> = bound_method %int_2, %specific_fn.loc18_13 [concrete = constants.%bound_method.646]\n// CHECK:STDOUT:   %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_13: init %i32 = call %bound_method.loc18_13.2(%int_2) [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_13.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc18_13 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %.loc18_13.2: %i32 = converted %int_2, %.loc18_13.1 [concrete = constants.%int_2.ef8]\n// CHECK:STDOUT:   %i32.as.Add.impl.Op.call: init %i32 = call %i32.as.Add.impl.Op.specific_fn(%a.ref, %.loc18_13.2)\n// CHECK:STDOUT:   <elided>\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/import_extend_impl.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/import_extend_impl.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/import_extend_impl.carbon\n\n// --- extend_impl_library.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I {\n  fn F();\n}\n\nclass C {\n  extend impl as I {\n    fn F() {}\n  }\n}\n\n// --- use_imported_class_extend_impl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nimport library \"extend_impl_library\";\n\nfn G(c: C) {\n  C.F();\n  c.F();\n}\n\n// CHECK:STDOUT: --- extend_impl_library.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.08c: type = fn_type @I.WithSelf.F, @I.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.705: %I.WithSelf.F.type.08c = struct_value () [symbolic]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, @I.WithSelf.%I.WithSelf.F.decl [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %C.as.I.impl.F.type: type = fn_type @C.as.I.impl.F [concrete]\n// CHECK:STDOUT:   %C.as.I.impl.F: %C.as.I.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.ba3: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.0e5: %I.WithSelf.F.type.ba3 = struct_value () [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl: type = interface_decl @I [concrete = constants.%I.type] {} {}\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I {\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic = constants.%Self]\n// CHECK:STDOUT:   %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !with Self:\n// CHECK:STDOUT:   %I.WithSelf.F.decl: @I.WithSelf.%I.WithSelf.F.type (%I.WithSelf.F.type.08c) = fn_decl @I.WithSelf.F [symbolic = @I.WithSelf.%I.WithSelf.F (constants.%I.WithSelf.F.705)] {} {}\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, %I.WithSelf.F.decl [concrete = constants.%assoc0]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = %Self\n// CHECK:STDOUT:   .F = @I.WithSelf.%assoc0\n// CHECK:STDOUT:   witness = (@I.WithSelf.%I.WithSelf.F.decl)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %Self.ref as %I.ref {\n// CHECK:STDOUT:   %C.as.I.impl.F.decl: %C.as.I.impl.F.type = fn_decl @C.as.I.impl.F [concrete = constants.%C.as.I.impl.F] {} {}\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%C.as.I.impl.F.decl), @C.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .F = %C.as.I.impl.F.decl\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %Self.ref: type = name_ref Self, constants.%C [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: type = name_ref I, file.%I.decl [concrete = constants.%I.type]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT:   .I = <poisoned>\n// CHECK:STDOUT:   extend @C.as.I.impl.%I.ref\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.F(@I.%Self: %I.type) {\n// CHECK:STDOUT:   fn();\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.I.impl.F() {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.08c\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.705\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.ba3\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.0e5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%I.facet) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- use_imported_class_extend_impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type %C [concrete]\n// CHECK:STDOUT:   %G.type: type = fn_type @G [concrete]\n// CHECK:STDOUT:   %empty_tuple.type: type = tuple_type () [concrete]\n// CHECK:STDOUT:   %G: %G.type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I> [concrete]\n// CHECK:STDOUT:   %Self: %I.type = symbolic_binding Self, 0 [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.type.a1f: type = fn_type @I.WithSelf.F, @I.WithSelf(%Self) [symbolic]\n// CHECK:STDOUT:   %I.WithSelf.F.cc3: %I.WithSelf.F.type.a1f = struct_value () [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.b59: type = fn_type @I.WithSelf.F, @I.WithSelf(%C.type.facet) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.521: %I.WithSelf.F.type.b59 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.assoc_type: type = assoc_entity_type @I [concrete]\n// CHECK:STDOUT:   %assoc0: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.972 [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness imports.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.type.7f9: type = fn_type @I.WithSelf.F, @I.WithSelf(%I.facet) [concrete]\n// CHECK:STDOUT:   %I.WithSelf.F.c5a: %I.WithSelf.F.type.7f9 = struct_value () [concrete]\n// CHECK:STDOUT:   %.a40: type = fn_type_with_self_type %I.WithSelf.F.type.7f9, %I.facet [concrete]\n// CHECK:STDOUT:   %C.as.I.impl.F.type: type = fn_type @C.as.I.impl.F [concrete]\n// CHECK:STDOUT:   %C.as.I.impl.F: %C.as.I.impl.F.type = struct_value () [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.I = import_ref Main//extend_impl_library, I, unloaded\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//extend_impl_library, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//extend_impl_library, loc12_1, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//extend_impl_library, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %Main.import_ref.72a4a5.1: type = import_ref Main//extend_impl_library, loc9_18, loaded [concrete = constants.%I.type]\n// CHECK:STDOUT:   %Main.import_ref.a54: %I.assoc_type = import_ref Main//extend_impl_library, loc5_9, loaded [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %Main.F = import_ref Main//extend_impl_library, F, unloaded\n// CHECK:STDOUT:   %Main.import_ref.2362f8.2: %I.type = import_ref Main//extend_impl_library, loc4_13, loaded [symbolic = constants.%Self]\n// CHECK:STDOUT:   %Main.import_ref.c82 = import_ref Main//extend_impl_library, loc4_13, unloaded\n// CHECK:STDOUT:   %Main.import_ref.972: @I.WithSelf.%I.WithSelf.F.type (%I.WithSelf.F.type.a1f) = import_ref Main//extend_impl_library, loc5_9, loaded [symbolic = @I.WithSelf.%I.WithSelf.F (constants.%I.WithSelf.F.cc3)]\n// CHECK:STDOUT:   %Main.import_ref.a3d: <witness> = import_ref Main//extend_impl_library, loc9_20, loaded [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:   %Main.import_ref.569: type = import_ref Main//extend_impl_library, loc9_15, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.72a4a5.2: type = import_ref Main//extend_impl_library, loc9_18, loaded [concrete = constants.%I.type]\n// CHECK:STDOUT:   %Main.import_ref.d12: %C.as.I.impl.F.type = import_ref Main//extend_impl_library, loc10_12, loaded [concrete = constants.%C.as.I.impl.F]\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (%Main.import_ref.d12), @C.as.I.impl [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = imports.%Main.I\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .G = %G.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import = import <none>\n// CHECK:STDOUT:   %G.decl: %G.type = fn_decl @G [concrete = constants.%G] {\n// CHECK:STDOUT:     %c.patt: %pattern_type = value_binding_pattern c [concrete]\n// CHECK:STDOUT:     %c.param_patt: %pattern_type = value_param_pattern %c.patt [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %c.param: %C = value_param call_param0\n// CHECK:STDOUT:     %C.ref.loc6: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %c: %C = value_binding c, %c.param\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: interface @I [from \"extend_impl_library.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.c82\n// CHECK:STDOUT:   .F = imports.%Main.import_ref.a54\n// CHECK:STDOUT:   witness = (imports.%Main.F)\n// CHECK:STDOUT:\n// CHECK:STDOUT: !requires:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: imports.%Main.import_ref.569 as imports.%Main.import_ref.72a4a5.2 [from \"extend_impl_library.carbon\"] {\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = imports.%Main.import_ref.a3d\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"extend_impl_library.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT:   .F = <poisoned>\n// CHECK:STDOUT:   extend imports.%Main.import_ref.72a4a5.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @G(%c.param: %C) {\n// CHECK:STDOUT: !entry:\n// CHECK:STDOUT:   %C.ref.loc7: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:   %F.ref.loc7: %I.assoc_type = name_ref F, imports.%Main.import_ref.a54 [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %impl.elem0.loc7: %.a40 = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%C.as.I.impl.F]\n// CHECK:STDOUT:   %C.as.I.impl.F.call.loc7: init %empty_tuple.type = call %impl.elem0.loc7()\n// CHECK:STDOUT:   %c.ref: %C = name_ref c, %c\n// CHECK:STDOUT:   %F.ref.loc8: %I.assoc_type = name_ref F, imports.%Main.import_ref.a54 [concrete = constants.%assoc0]\n// CHECK:STDOUT:   %impl.elem0.loc8: %.a40 = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%C.as.I.impl.F]\n// CHECK:STDOUT:   %C.as.I.impl.F.call.loc8: init %empty_tuple.type = call %impl.elem0.loc8()\n// CHECK:STDOUT:   return\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic fn @I.WithSelf.F(imports.%Main.import_ref.2362f8.2: %I.type) [from \"extend_impl_library.carbon\"] {\n// CHECK:STDOUT:   fn;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: fn @C.as.I.impl.F [from \"extend_impl_library.carbon\"];\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%Self) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%Self\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.a1f\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.cc3\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf.F(constants.%Self) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%C.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%C.type.facet\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.b59\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.521\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %Self => constants.%I.facet\n// CHECK:STDOUT:   %I.WithSelf.F.type => constants.%I.WithSelf.F.type.7f9\n// CHECK:STDOUT:   %I.WithSelf.F => constants.%I.WithSelf.F.c5a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/check/testdata/impl/import_generic.carbon",
    "content": "// Part of the Carbon Language project, under the Apache License v2.0 with LLVM\n// Exceptions. See /LICENSE for license information.\n// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n//\n// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/none.carbon\n// TODO: Add ranges and switch to \"--dump-sem-ir-ranges=only\".\n// EXTRA-ARGS: --dump-sem-ir-ranges=if-present\n//\n// AUTOUPDATE\n// TIP: To test this file alone, run:\n// TIP:   bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/impl/import_generic.carbon\n// TIP: To dump output, run:\n// TIP:   bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/impl/import_generic.carbon\n\n// --- basic_import_generic_interface.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {}\ninterface J(T:! type) {\n  extend require impls I(T);\n}\n\n// --- basic_import_generic_interface.impl.carbon\nimpl library \"[[@TEST_NAME]]\";\n\nclass C {}\n\nimpl C as I({}) {}\n\nimpl C as J({}) {}\n\n// --- basic_import_generic_constraint.carbon\nlibrary \"[[@TEST_NAME]]\";\n\ninterface I(T:! type) {}\nconstraint J(T:! type) {\n  extend require impls I(T);\n}\n\n// --- basic_import_generic_constraint.impl.carbon\nimpl library \"[[@TEST_NAME]]\";\n\nclass C {}\n\nimpl C as J({}) {}\n\n// --- import_generic.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\ninterface I(T:! type) {}\n\n// Has both declaration and definition.\nimpl forall [T:! type] C as I(T);\nimpl forall [T:! type] C as I(T) {}\n\n// Only has definition.\nimpl forall [T:! type] C as I(T*) {}\n\nconstraint N(T:! type) {\n  extend require impls I(T);\n}\n\n// --- fail_import_generic.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_import_generic.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] C as I(T);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] C as I(T);\n\n// CHECK:STDERR: fail_import_generic.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] C as I(T) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] C as I(T) {}\n\n// CHECK:STDERR: fail_import_generic.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] C as I(T*);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] C as I(T*);\n\n// CHECK:STDERR: fail_import_generic.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] C as I(T*) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] C as I(T*) {}\n\n// CHECK:STDERR: fail_import_generic.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] C as N(T);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] C as N(T);\n// CHECK:STDERR: fail_import_generic.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] C as N(T*);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] C as N(T*);\n\n// --- import_generic_with_different_specific.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass C {}\ninterface I(T:! type) {}\n\nimpl forall [T:! type] C as I(T) {}\n\nconstraint N(T:! type) {\n  extend require impls I(T);\n}\n\n// --- import_generic_with_different_specific.impl.carbon\nimpl library \"[[@TEST_NAME]]\";\n\n// These have different specifics than any impl decl in the api file, so they\n// are allowed.\nimpl forall [T:! type] C as I(T*) {}\nimpl forall [T:! type] C as N(T**) {}\n\n// --- fail_import_generic_decl.carbon\n\nlibrary \"[[@TEST_NAME]]\";\n\nclass D {}\ninterface J(T:! type) {}\n\nconstraint N(T:! type) {\n  extend require impls J(T);\n}\n\n// CHECK:STDERR: fail_import_generic_decl.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]\n// CHECK:STDERR: impl forall [T:! type] D as J(T);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] D as J(T);\n\n// CHECK:STDERR: fail_import_generic_decl.carbon:[[@LINE+4]]:1: error: impl declared but not defined [ImplMissingDefinition]\n// CHECK:STDERR: impl forall [T:! type] D as J(T*);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] D as J(T*);\n\n// --- fail_import_generic_decl.impl.carbon\n\nimpl library \"[[@TEST_NAME]]\";\n\n// CHECK:STDERR: fail_import_generic_decl.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] D as J(T);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] D as J(T);\n\n// CHECK:STDERR: fail_import_generic_decl.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] D as J(T) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] D as J(T) {}\n\n// CHECK:STDERR: fail_import_generic_decl.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] D as J(T*);\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] D as J(T*);\n\n// CHECK:STDERR: fail_import_generic_decl.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] D as J(T*) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] D as J(T*) {}\n\n// CHECK:STDERR: fail_import_generic_decl.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] D as N(T) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] D as N(T) {}\n\n// CHECK:STDERR: fail_import_generic_decl.impl.carbon:[[@LINE+4]]:1: error: redeclaration of imported impl [RedeclImportedImpl]\n// CHECK:STDERR: impl forall [T:! type] D as N(T*) {}\n// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n// CHECK:STDERR:\nimpl forall [T:! type] D as N(T*) {}\n\n// CHECK:STDOUT: --- basic_import_generic_interface.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.fdb: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %J.type.885: type = generic_interface_type @J [concrete]\n// CHECK:STDOUT:   %J.generic: %J.type.885 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.type.04e: type = facet_type <@J, @J(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.a60: %J.type.04e = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.a60 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .J = %J.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc3_17.1: type = splice_block %.loc3_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc3_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc3_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.decl: %J.type.885 = interface_decl @J [concrete = constants.%J.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_17.1: type = splice_block %.loc4_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%T.loc3_13.2: type) {\n// CHECK:STDOUT:   %T.loc3_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc3_13.1)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self.loc3_23.2: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc3_23.1: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc3_23.1\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @J(%T.loc4_13.2: type) {\n// CHECK:STDOUT:   %T.loc4_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T.loc4_13.1)> [symbolic = %J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:   %Self.loc4_23.2: @J.%J.type (%J.type.04e) = symbolic_binding Self, 1 [symbolic = %Self.loc4_23.2 (constants.%Self.a60)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc4_23.1: @J.%J.type (%J.type.04e) = symbolic_binding Self, 1 [symbolic = %Self.loc4_23.2 (constants.%Self.a60)]\n// CHECK:STDOUT:     %J.WithSelf.decl = interface_with_self_decl @J [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %J.WithSelf.Self.binding.as_type.impls.I.type.require.decl = require_decl @J.WithSelf.Self.binding.as_type.impls.I.type.require [concrete] {\n// CHECK:STDOUT:       require %Self.as_type impls %I.type.loc5_27.1\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type @J.%Self.loc4_23.1 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @J.%T.loc4_13.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %I.type.loc5_27.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc5_27.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %.loc5: type = specific_constant @J.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type.loc5_27.1, @J.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.a60) [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc4_23.1\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     extend @J.WithSelf.%.loc5\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @J.WithSelf.Self.binding.as_type.impls.I.type.require {\n// CHECK:STDOUT:       require @J.WithSelf.Self.binding.as_type.impls.I.type.require.%Self.as_type impls @J.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type.loc5_27.1\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @J.WithSelf.Self.binding.as_type.impls.I.type.require(@J.%T.loc4_13.2: type, @J.%Self.loc4_23.1: @J.%J.type (%J.type.04e)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:   %Self: @J.WithSelf.Self.binding.as_type.impls.I.type.require.%J.type (%J.type.04e) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.a60)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %I.type.loc5_27.2: type = facet_type <@I, @I(%T)> [symbolic = %I.type.loc5_27.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T.loc3_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %Self.loc3_23.2 => constants.%Self.fdb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%Self.fdb) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_13.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%T, constants.%Self.a60) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.a60) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %J.type => constants.%J.type.04e\n// CHECK:STDOUT:   %Self => constants.%Self.a60\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %I.type.loc5_27.2 => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- basic_import_generic_interface.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.c1b: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %empty_struct: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.ab5: type = facet_type <@I, @I(%empty_struct_type)> [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %Self.025: %I.type.ab5 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type.ab5 = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT:   %J.type.885: type = generic_interface_type @J [concrete]\n// CHECK:STDOUT:   %J.generic: %J.type.885 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.type.04e: type = facet_type <@J, @J(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.c25: %J.type.04e = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.c25 [symbolic]\n// CHECK:STDOUT:   %J.type.d6f: type = facet_type <@J, @J(%empty_struct_type)> [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness @C.as.J.impl.%J.impl_witness_table [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]\n// CHECK:STDOUT:   %complete_type.5b1: <witness> = complete_type_witness %I.type.ab5 [concrete]\n// CHECK:STDOUT:   %Self.9e4: %J.type.d6f = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %J.facet: %J.type.d6f = facet_value %C, (%J.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.I: %I.type.609 = import_ref Main//basic_import_generic_interface, I, loaded [concrete = constants.%I.generic]\n// CHECK:STDOUT:   %Main.J: %J.type.885 = import_ref Main//basic_import_generic_interface, J, loaded [concrete = constants.%J.generic]\n// CHECK:STDOUT:   %Main.import_ref.3fa = import_ref Main//basic_import_generic_interface, loc3_23, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//basic_import_generic_interface, loc3_13, loaded [symbolic = @I.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.7bf = import_ref Main//basic_import_generic_interface, loc5_28, unloaded\n// CHECK:STDOUT:   %Main.import_ref.2ff: type = import_ref Main//basic_import_generic_interface, loc5_18, loaded [symbolic = @J.WithSelf.Self.binding.as_type.impls.I.type.require.%Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %Main.import_ref.358: type = import_ref Main//basic_import_generic_interface, loc5_27, loaded [symbolic = @J.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.4: type = import_ref Main//basic_import_generic_interface, loc4_13, loaded [symbolic = @J.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.99f327.2: @J.%J.type (%J.type.04e) = import_ref Main//basic_import_generic_interface, loc4_23, loaded [symbolic = @J.%Self (constants.%Self.c25)]\n// CHECK:STDOUT:   %Main.import_ref.e9b = import_ref Main//basic_import_generic_interface, loc4_23, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.5: type = import_ref Main//basic_import_generic_interface, loc4_13, loaded [symbolic = @J.%T (constants.%T)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = imports.%Main.I\n// CHECK:STDOUT:     .J = imports.%Main.J\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc1_46.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc1_46.2 = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, imports.%Main.I [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %.loc5_14: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc5_15: type = converted %.loc5_14, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %I.type: type = facet_type <@I, @I(constants.%empty_struct_type)> [concrete = constants.%I.type.ab5]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.J.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %J.ref: %J.type.885 = name_ref J, imports.%Main.J [concrete = constants.%J.generic]\n// CHECK:STDOUT:     %.loc7_14: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %.loc7_15: type = converted %.loc7_14, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %J.type: type = facet_type <@J, @J(constants.%empty_struct_type)> [concrete = constants.%J.type.d6f]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(imports.%Main.import_ref.b3bc94.2: type) [from \"basic_import_generic_interface.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.c1b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.3fa\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @J(imports.%Main.import_ref.b3bc94.5: type) [from \"basic_import_generic_interface.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:   %Self: @J.%J.type (%J.type.04e) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.c25)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.e9b\n// CHECK:STDOUT:     extend imports.%Main.import_ref.7bf\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @J.WithSelf.Self.binding.as_type.impls.I.type.require {\n// CHECK:STDOUT:       require imports.%Main.import_ref.2ff impls imports.%Main.import_ref.358\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @J.WithSelf.Self.binding.as_type.impls.I.type.require(imports.%Main.import_ref.b3bc94.4: type, imports.%Main.import_ref.99f327.2: @J.%J.type (%J.type.04e)) [from \"basic_import_generic_interface.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:   %Self: @J.WithSelf.Self.binding.as_type.impls.I.type.require.%J.type (%J.type.04e) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.c25)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %I.type {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.J.impl: %C.ref as %J.type {\n// CHECK:STDOUT:   %J.impl_witness_table = impl_witness_table (), @C.as.J.impl [concrete]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %J.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %Self => constants.%Self.c1b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%Self.c1b) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.ab5\n// CHECK:STDOUT:   %Self => constants.%Self.025\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%empty_struct_type, constants.%Self.c1b) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%empty_struct_type, constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%T, constants.%Self.c25) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.c25) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %J.type => constants.%J.type.04e\n// CHECK:STDOUT:   %Self => constants.%Self.c25\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type => constants.%J.type.d6f\n// CHECK:STDOUT:   %Self => constants.%Self.9e4\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%C.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:   %I.type => constants.%I.type.ab5\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.5b1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%empty_struct_type, constants.%C.type.facet) {\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:   %J.type => constants.%J.type.d6f\n// CHECK:STDOUT:   %Self => constants.%C.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C\n// CHECK:STDOUT:   %I.type => constants.%I.type.ab5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%Self.c25) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:   %I.type => constants.%I.type.ab5\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.5b1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%J.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:   %I.type => constants.%I.type.ab5\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.5b1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- basic_import_generic_constraint.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.fdb: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %J.type.d08: type = generic_named_constaint_type @J [concrete]\n// CHECK:STDOUT:   %empty_struct: %J.type.d08 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.type.d68: type = facet_type <@J, @J(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.31c: %J.type.d68 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.31c [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .J = %J.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc3_17.1: type = splice_block %.loc3_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc3_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc3_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %J.decl: %J.type.d08 = constraint_decl @J [concrete = constants.%empty_struct] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc4_18.1: type = splice_block %.loc4_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc4_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc4_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc4_14.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%T.loc3_13.2: type) {\n// CHECK:STDOUT:   %T.loc3_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc3_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc3_13.1)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self.loc3_23.2: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc3_23.1: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc3_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc3_23.1\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic constraint @J(%T.loc4_14.2: type) {\n// CHECK:STDOUT:   %T.loc4_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc4_14.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T.loc4_14.1)> [symbolic = %J.type (constants.%J.type.d68)]\n// CHECK:STDOUT:   %Self.loc4_24.2: @J.%J.type (%J.type.d68) = symbolic_binding Self, 1 [symbolic = %Self.loc4_24.2 (constants.%Self.31c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   constraint {\n// CHECK:STDOUT:     %Self.loc4_24.1: @J.%J.type (%J.type.d68) = symbolic_binding Self, 1 [symbolic = %Self.loc4_24.2 (constants.%Self.31c)]\n// CHECK:STDOUT:     %J.WithSelf.decl = constraint_with_self_decl @J [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %J.WithSelf.Self.binding.as_type.impls.I.type.require.decl = require_decl @J.WithSelf.Self.binding.as_type.impls.I.type.require [concrete] {\n// CHECK:STDOUT:       require %Self.as_type impls %I.type.loc5_27.1\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type @J.%Self.loc4_24.1 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @J.%T.loc4_14.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %I.type.loc5_27.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc5_27.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %.loc5: type = specific_constant @J.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type.loc5_27.1, @J.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.31c) [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc4_24.1\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     extend @J.WithSelf.%.loc5\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @J.WithSelf.Self.binding.as_type.impls.I.type.require {\n// CHECK:STDOUT:       require @J.WithSelf.Self.binding.as_type.impls.I.type.require.%Self.as_type impls @J.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type.loc5_27.1\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @J.WithSelf.Self.binding.as_type.impls.I.type.require(@J.%T.loc4_14.2: type, @J.%Self.loc4_24.1: @J.%J.type (%J.type.d68)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.d68)]\n// CHECK:STDOUT:   %Self: @J.WithSelf.Self.binding.as_type.impls.I.type.require.%J.type (%J.type.d68) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.31c)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %I.type.loc5_27.2: type = facet_type <@I, @I(%T)> [symbolic = %I.type.loc5_27.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T.loc3_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %Self.loc3_23.2 => constants.%Self.fdb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%Self.fdb) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%T) {\n// CHECK:STDOUT:   %T.loc4_14.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%T, constants.%Self.31c) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.31c) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %J.type => constants.%J.type.d68\n// CHECK:STDOUT:   %Self => constants.%Self.31c\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %I.type.loc5_27.2 => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- basic_import_generic_constraint.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type.357: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %J.type.d08: type = generic_named_constaint_type @J [concrete]\n// CHECK:STDOUT:   %empty_struct.d2a: %J.type.d08 = struct_value () [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %J.type.d682d6.1: type = facet_type <@J, @J(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.e1f642.1: %J.type.d682d6.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.c1b: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f642.1 [symbolic]\n// CHECK:STDOUT:   %empty_struct.a40: %empty_struct_type = struct_value () [concrete]\n// CHECK:STDOUT:   %J.type.d682d6.2: type = facet_type <@J, @J(%empty_struct_type)> [concrete]\n// CHECK:STDOUT:   %Self.e1f642.2: %J.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.type.ab5: type = facet_type <@I, @I(%empty_struct_type)> [concrete]\n// CHECK:STDOUT:   %Self.025: %I.type.ab5 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %complete_type.5b1: <witness> = complete_type_witness %I.type.ab5 [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table [concrete]\n// CHECK:STDOUT:   %I.facet: %I.type.ab5 = facet_value %C, (%I.impl_witness) [concrete]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.I = import_ref Main//basic_import_generic_constraint, I, unloaded\n// CHECK:STDOUT:   %Main.J: %J.type.d08 = import_ref Main//basic_import_generic_constraint, J, loaded [concrete = constants.%empty_struct.d2a]\n// CHECK:STDOUT:   %Main.import_ref.7b1 = import_ref Main//basic_import_generic_constraint, loc5_28, unloaded\n// CHECK:STDOUT:   %Main.import_ref.3fa = import_ref Main//basic_import_generic_constraint, loc3_23, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.3: type = import_ref Main//basic_import_generic_constraint, loc3_13, loaded [symbolic = @I.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.213: type = import_ref Main//basic_import_generic_constraint, loc5_18, loaded [symbolic = @J.WithSelf.Self.binding.as_type.impls.I.type.require.%Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %Main.import_ref.358: type = import_ref Main//basic_import_generic_constraint, loc5_27, loaded [symbolic = @J.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.4: type = import_ref Main//basic_import_generic_constraint, loc4_14, loaded [symbolic = @J.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.2fc394.2: @J.%J.type (%J.type.d682d6.1) = import_ref Main//basic_import_generic_constraint, loc4_24, loaded [symbolic = @J.%Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:   %Main.import_ref.830 = import_ref Main//basic_import_generic_constraint, loc4_24, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.5: type = import_ref Main//basic_import_generic_constraint, loc4_14, loaded [symbolic = @J.%T (constants.%T)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .I = imports.%Main.I\n// CHECK:STDOUT:     .J = imports.%Main.J\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc1_47.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc1_47.2 = import <none>\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {} {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %J.ref: %J.type.d08 = name_ref J, imports.%Main.J [concrete = constants.%empty_struct.d2a]\n// CHECK:STDOUT:     %.loc5_14: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct.a40]\n// CHECK:STDOUT:     %.loc5_15: type = converted %.loc5_14, constants.%empty_struct_type [concrete = constants.%empty_struct_type]\n// CHECK:STDOUT:     %J.type: type = facet_type <@J, @J(constants.%empty_struct_type)> [concrete = constants.%J.type.d682d6.2]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(imports.%Main.import_ref.b3bc94.3: type) [from \"basic_import_generic_constraint.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.c1b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.3fa\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic constraint @J(imports.%Main.import_ref.b3bc94.5: type) [from \"basic_import_generic_constraint.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.d682d6.1)]\n// CHECK:STDOUT:   %Self: @J.%J.type (%J.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   constraint {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.830\n// CHECK:STDOUT:     extend imports.%Main.import_ref.7b1\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @J.WithSelf.Self.binding.as_type.impls.I.type.require {\n// CHECK:STDOUT:       require imports.%Main.import_ref.213 impls imports.%Main.import_ref.358\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @J.WithSelf.Self.binding.as_type.impls.I.type.require(imports.%Main.import_ref.b3bc94.4: type, imports.%Main.import_ref.2fc394.2: @J.%J.type (%J.type.d682d6.1)) [from \"basic_import_generic_constraint.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.d682d6.1)]\n// CHECK:STDOUT:   %Self: @J.WithSelf.Self.binding.as_type.impls.I.type.require.%J.type (%J.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: impl @C.as.I.impl: %C.ref as %J.type {\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness %I.impl_witness_table [concrete = constants.%I.impl_witness]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   witness = %I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %Self => constants.%Self.c1b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%Self.c1b) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%T, constants.%Self.e1f642.1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.e1f642.1) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %J.type => constants.%J.type.d682d6.1\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type => constants.%J.type.d682d6.2\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%Self.e1f642.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:   %I.type => constants.%I.type.ab5\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.5b1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%empty_struct_type) {\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.ab5\n// CHECK:STDOUT:   %Self => constants.%Self.025\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%empty_struct_type, constants.%Self.c1b) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%empty_struct_type, constants.%C.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:   %I.type => constants.%I.type.ab5\n// CHECK:STDOUT:   %require_complete => constants.%complete_type.5b1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%empty_struct_type, constants.%C.type.facet) {\n// CHECK:STDOUT:   %T => constants.%empty_struct_type\n// CHECK:STDOUT:   %J.type => constants.%J.type.d682d6.2\n// CHECK:STDOUT:   %Self => constants.%C.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C\n// CHECK:STDOUT:   %I.type => constants.%I.type.ab5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%empty_struct_type, constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- import_generic.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.fdb: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.impl_witness.9f5: <witness> = impl_witness @C.as.I.impl.431.%I.impl_witness_table, @C.as.I.impl.431(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.e36: <witness> = require_complete_type %I.type.1ab [symbolic]\n// CHECK:STDOUT:   %I.facet.b43: %I.type.1ab = facet_value %C, (%I.impl_witness.9f5) [symbolic]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %I.type.e19: type = facet_type <@I, @I(%ptr)> [symbolic]\n// CHECK:STDOUT:   %I.impl_witness.18a: <witness> = impl_witness @C.as.I.impl.815.%I.impl_witness_table, @C.as.I.impl.815(%T) [symbolic]\n// CHECK:STDOUT:   %Self.eff: %I.type.e19 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %require_complete.ffd: <witness> = require_complete_type %I.type.e19 [symbolic]\n// CHECK:STDOUT:   %I.facet.064: %I.type.e19 = facet_value %C, (%I.impl_witness.18a) [symbolic]\n// CHECK:STDOUT:   %N.type.b47: type = generic_named_constaint_type @N [concrete]\n// CHECK:STDOUT:   %empty_struct: %N.type.b47 = struct_value () [concrete]\n// CHECK:STDOUT:   %N.type.d68: type = facet_type <@N, @N(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.31c: %N.type.d68 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.31c [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .N = %N.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_17.1: type = splice_block %.loc5_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc5_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.431 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc8: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc8: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref.loc8: type = name_ref T, %T.loc8_14.1 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:     %I.type.loc8_32.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc8_32.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:     %.loc8_18.1: type = splice_block %.loc8_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.2: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.431 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref.loc9: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref.loc9: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref.loc9: type = name_ref T, %T.loc9 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:     %I.type.loc9: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc8_32.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:     %.loc9_18.1: type = splice_block %.loc9_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self.1: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc9_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9: type = symbolic_binding T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.815 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc12_14.1 [symbolic = %T.loc12_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc12_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc12_32.2 (constants.%ptr)]\n// CHECK:STDOUT:     %I.type.loc12_33.1: type = facet_type <@I, @I(constants.%ptr)> [symbolic = %I.type.loc12_33.2 (constants.%I.type.e19)]\n// CHECK:STDOUT:     %.loc12_18.1: type = splice_block %.loc12_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc12_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc12_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc12_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %N.decl: %N.type.b47 = constraint_decl @N [concrete = constants.%empty_struct] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc14_18.1: type = splice_block %.loc14_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc14_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc14_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc14_14.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%T.loc5_13.2: type) {\n// CHECK:STDOUT:   %T.loc5_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc5_13.1)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self.loc5_23.2: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc5_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc5_23.1: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc5_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc5_23.1\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic constraint @N(%T.loc14_14.2: type) {\n// CHECK:STDOUT:   %T.loc14_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc14_14.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T.loc14_14.1)> [symbolic = %N.type (constants.%N.type.d68)]\n// CHECK:STDOUT:   %Self.loc14_24.2: @N.%N.type (%N.type.d68) = symbolic_binding Self, 1 [symbolic = %Self.loc14_24.2 (constants.%Self.31c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   constraint {\n// CHECK:STDOUT:     %Self.loc14_24.1: @N.%N.type (%N.type.d68) = symbolic_binding Self, 1 [symbolic = %Self.loc14_24.2 (constants.%Self.31c)]\n// CHECK:STDOUT:     %N.WithSelf.decl = constraint_with_self_decl @N [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %N.WithSelf.Self.binding.as_type.impls.I.type.require.decl = require_decl @N.WithSelf.Self.binding.as_type.impls.I.type.require [concrete] {\n// CHECK:STDOUT:       require %Self.as_type impls %I.type.loc15_27.1\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type @N.%Self.loc14_24.1 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @N.%T.loc14_14.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %I.type.loc15_27.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc15_27.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %.loc15: type = specific_constant @N.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type.loc15_27.1, @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.31c) [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc14_24.1\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     extend @N.WithSelf.%.loc15\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @N.WithSelf.Self.binding.as_type.impls.I.type.require {\n// CHECK:STDOUT:       require @N.WithSelf.Self.binding.as_type.impls.I.type.require.%Self.as_type impls @N.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type.loc15_27.1\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @N.WithSelf.Self.binding.as_type.impls.I.type.require(@N.%T.loc14_14.2: type, @N.%Self.loc14_24.1: @N.%N.type (%N.type.d68)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d68)]\n// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.I.type.require.%N.type (%N.type.d68) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.31c)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %I.type.loc15_27.2: type = facet_type <@I, @I(%T)> [symbolic = %I.type.loc15_27.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.431(%T.loc8_14.1: type) {\n// CHECK:STDOUT:   %T.loc8_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:   %I.type.loc8_32.2: type = facet_type <@I, @I(%T.loc8_14.2)> [symbolic = %I.type.loc8_32.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %I.impl_witness.loc8_33.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl.431(%T.loc8_14.2) [symbolic = %I.impl_witness.loc8_33.2 (constants.%I.impl_witness.9f5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.loc8_32.2 [symbolic = %require_complete (constants.%require_complete.e36)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref.loc8 as %I.type.loc8_32.1 {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (), @C.as.I.impl.431 [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc8_33.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl.431(constants.%T) [symbolic = %I.impl_witness.loc8_33.2 (constants.%I.impl_witness.9f5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %I.impl_witness.loc8_33.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.815(%T.loc12_14.1: type) {\n// CHECK:STDOUT:   %T.loc12_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc12_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc12_32.2: type = ptr_type %T.loc12_14.2 [symbolic = %ptr.loc12_32.2 (constants.%ptr)]\n// CHECK:STDOUT:   %I.type.loc12_33.2: type = facet_type <@I, @I(%ptr.loc12_32.2)> [symbolic = %I.type.loc12_33.2 (constants.%I.type.e19)]\n// CHECK:STDOUT:   %I.impl_witness.loc12_35.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl.815(%T.loc12_14.2) [symbolic = %I.impl_witness.loc12_35.2 (constants.%I.impl_witness.18a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.loc12_33.2 [symbolic = %require_complete (constants.%require_complete.ffd)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %I.type.loc12_33.1 {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (), @C.as.I.impl.815 [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc12_35.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl.815(constants.%T) [symbolic = %I.impl_witness.loc12_35.2 (constants.%I.impl_witness.18a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %I.impl_witness.loc12_35.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %Self.loc5_23.2 => constants.%Self.fdb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%Self.fdb) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.431(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_14.2 => constants.%T\n// CHECK:STDOUT:   %I.type.loc8_32.2 => constants.%I.type.1ab\n// CHECK:STDOUT:   %I.impl_witness.loc8_33.2 => constants.%I.impl_witness.9f5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%I.facet.b43) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%ptr) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%ptr\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.e19\n// CHECK:STDOUT:   %Self.loc5_23.2 => constants.%Self.eff\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.815(constants.%T) {\n// CHECK:STDOUT:   %T.loc12_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc12_32.2 => constants.%ptr\n// CHECK:STDOUT:   %I.type.loc12_33.2 => constants.%I.type.e19\n// CHECK:STDOUT:   %I.impl_witness.loc12_35.2 => constants.%I.impl_witness.18a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%ptr, constants.%Self.fdb) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%ptr, constants.%I.facet.064) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N(constants.%T) {\n// CHECK:STDOUT:   %T.loc14_14.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.31c) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.31c) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %N.type => constants.%N.type.d68\n// CHECK:STDOUT:   %Self => constants.%Self.31c\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %I.type.loc15_27.2 => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_import_generic.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.c1b: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %I.impl_witness.9f5: <witness> = impl_witness imports.%I.impl_witness_table.2ac, @C.as.I.impl.431d5e.1(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.e36: <witness> = require_complete_type %I.type.1ab [symbolic]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %I.type.e19: type = facet_type <@I, @I(%ptr)> [symbolic]\n// CHECK:STDOUT:   %Self.dda: %I.type.e19 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.impl_witness.18a: <witness> = impl_witness imports.%I.impl_witness_table.a23, @C.as.I.impl.8159c7.1(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.ffd: <witness> = require_complete_type %I.type.e19 [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %N.type.b47: type = generic_named_constaint_type @N [concrete]\n// CHECK:STDOUT:   %empty_struct: %N.type.b47 = struct_value () [concrete]\n// CHECK:STDOUT:   %N.type.d682d6.1: type = facet_type <@N, @N(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.e1f642.1: %N.type.d682d6.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f642.1 [symbolic]\n// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]\n// CHECK:STDOUT:   %N.type.d682d6.2: type = facet_type <@N, @N(%ptr)> [symbolic]\n// CHECK:STDOUT:   %Self.e1f642.2: %N.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//import_generic, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.I: %I.type.609 = import_ref Main//import_generic, I, loaded [concrete = constants.%I.generic]\n// CHECK:STDOUT:   %Main.N: %N.type.b47 = import_ref Main//import_generic, N, loaded [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Main.import_ref.3fa = import_ref Main//import_generic, loc5_23, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//import_generic, loc5_13, loaded [symbolic = @I.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.e08 = import_ref Main//import_generic, loc8_33, unloaded\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//import_generic, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//import_generic, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %I.impl_witness_table.2ac = impl_witness_table (), @C.as.I.impl.431d5e.1 [concrete]\n// CHECK:STDOUT:   %Main.import_ref.61cd7d.1: type = import_ref Main//import_generic, loc8_24, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.3582b1.1: type = import_ref Main//import_generic, loc8_32, loaded [symbolic = @C.as.I.impl.431d5e.1.%I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.3: type = import_ref Main//import_generic, loc8_14, loaded [symbolic = @C.as.I.impl.431d5e.1.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.2c7 = import_ref Main//import_generic, loc12_35, unloaded\n// CHECK:STDOUT:   %I.impl_witness_table.a23 = impl_witness_table (), @C.as.I.impl.8159c7.1 [concrete]\n// CHECK:STDOUT:   %Main.import_ref.61cd7d.2: type = import_ref Main//import_generic, loc12_24, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.ada: type = import_ref Main//import_generic, loc12_33, loaded [symbolic = @C.as.I.impl.8159c7.1.%I.type (constants.%I.type.e19)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.4: type = import_ref Main//import_generic, loc12_14, loaded [symbolic = @C.as.I.impl.8159c7.1.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.a5e = import_ref Main//import_generic, loc15_28, unloaded\n// CHECK:STDOUT:   %Main.import_ref.213: type = import_ref Main//import_generic, loc15_18, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.I.type.require.%Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %Main.import_ref.3582b1.2: type = import_ref Main//import_generic, loc15_27, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.6: type = import_ref Main//import_generic, loc14_14, loaded [symbolic = @N.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1) = import_ref Main//import_generic, loc14_24, loaded [symbolic = @N.%Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:   %Main.import_ref.830 = import_ref Main//import_generic, loc14_24, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.7: type = import_ref Main//import_generic, loc14_14, loaded [symbolic = @N.%T (constants.%T)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .I = imports.%Main.I\n// CHECK:STDOUT:     .N = imports.%Main.N\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_30.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_30.2 = import <none>\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.431d5e.2 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, imports.%Main.I [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc8_14.1 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:     %I.type.loc8_32.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc8_32.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:     %.loc8_18.1: type = splice_block %.loc8_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.431d5e.3 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, imports.%Main.I [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc14_14.1 [symbolic = %T.loc14_14.2 (constants.%T)]\n// CHECK:STDOUT:     %I.type.loc14_32.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc14_32.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:     %.loc14_18.1: type = splice_block %.loc14_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc14_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc14_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc14_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.8159c7.2 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, imports.%Main.I [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc20_14.1 [symbolic = %T.loc20_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc20_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc20_32.2 (constants.%ptr)]\n// CHECK:STDOUT:     %I.type.loc20_33.1: type = facet_type <@I, @I(constants.%ptr)> [symbolic = %I.type.loc20_33.2 (constants.%I.type.e19)]\n// CHECK:STDOUT:     %.loc20_18.1: type = splice_block %.loc20_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc20_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc20_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc20_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.8159c7.3 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, imports.%Main.I [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc26_14.1 [symbolic = %T.loc26_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc26_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc26_32.2 (constants.%ptr)]\n// CHECK:STDOUT:     %I.type.loc26_33.1: type = facet_type <@I, @I(constants.%ptr)> [symbolic = %I.type.loc26_33.2 (constants.%I.type.e19)]\n// CHECK:STDOUT:     %.loc26_18.1: type = splice_block %.loc26_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc26_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc26_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc26_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.c9332a.1 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %N.ref: %N.type.b47 = name_ref N, imports.%Main.N [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc32_14.1 [symbolic = %T.loc32_14.2 (constants.%T)]\n// CHECK:STDOUT:     %N.type.loc32_32.1: type = facet_type <@N, @N(constants.%T)> [symbolic = %N.type.loc32_32.2 (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:     %.loc32_18.1: type = splice_block %.loc32_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc32_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc32_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc32_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.c9332a.2 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %N.ref: %N.type.b47 = name_ref N, imports.%Main.N [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc37_14.1 [symbolic = %T.loc37_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc37_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc37_32.2 (constants.%ptr)]\n// CHECK:STDOUT:     %N.type.loc37_33.1: type = facet_type <@N, @N(constants.%ptr)> [symbolic = %N.type.loc37_33.2 (constants.%N.type.d682d6.2)]\n// CHECK:STDOUT:     %.loc37_18.1: type = splice_block %.loc37_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc37_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc37_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc37_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(imports.%Main.import_ref.b3bc94.2: type) [from \"import_generic.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.c1b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.3fa\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic constraint @N(imports.%Main.import_ref.b3bc94.7: type) [from \"import_generic.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   constraint {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.830\n// CHECK:STDOUT:     extend imports.%Main.import_ref.a5e\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @N.WithSelf.Self.binding.as_type.impls.I.type.require {\n// CHECK:STDOUT:       require imports.%Main.import_ref.213 impls imports.%Main.import_ref.3582b1.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @N.WithSelf.Self.binding.as_type.impls.I.type.require(imports.%Main.import_ref.b3bc94.6: type, imports.%Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1)) [from \"import_generic.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.I.type.require.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.431d5e.1(imports.%Main.import_ref.b3bc94.3: type) [from \"import_generic.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness imports.%I.impl_witness_table.2ac, @C.as.I.impl.431d5e.1(%T) [symbolic = %I.impl_witness (constants.%I.impl_witness.9f5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete.e36)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: imports.%Main.import_ref.61cd7d.1 as imports.%Main.import_ref.3582b1.1 {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = imports.%Main.import_ref.e08\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.8159c7.1(imports.%Main.import_ref.b3bc94.4: type) [from \"import_generic.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic = %ptr (constants.%ptr)]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%ptr)> [symbolic = %I.type (constants.%I.type.e19)]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness imports.%I.impl_witness_table.a23, @C.as.I.impl.8159c7.1(%T) [symbolic = %I.impl_witness (constants.%I.impl_witness.18a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete.ffd)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: imports.%Main.import_ref.61cd7d.2 as imports.%Main.import_ref.ada {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = imports.%Main.import_ref.2c7\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.431d5e.2(%T.loc8_14.1: type) {\n// CHECK:STDOUT:   %T.loc8_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:   %I.type.loc8_32.2: type = facet_type <@I, @I(%T.loc8_14.2)> [symbolic = %I.type.loc8_32.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %I.type.loc8_32.1;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.431d5e.3(%T.loc14_14.1: type) {\n// CHECK:STDOUT:   %T.loc14_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc14_14.2 (constants.%T)]\n// CHECK:STDOUT:   %I.type.loc14_32.2: type = facet_type <@I, @I(%T.loc14_14.2)> [symbolic = %I.type.loc14_32.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %I.type.loc14_32.1 {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.8159c7.2(%T.loc20_14.1: type) {\n// CHECK:STDOUT:   %T.loc20_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc20_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc20_32.2: type = ptr_type %T.loc20_14.2 [symbolic = %ptr.loc20_32.2 (constants.%ptr)]\n// CHECK:STDOUT:   %I.type.loc20_33.2: type = facet_type <@I, @I(%ptr.loc20_32.2)> [symbolic = %I.type.loc20_33.2 (constants.%I.type.e19)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %I.type.loc20_33.1;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.8159c7.3(%T.loc26_14.1: type) {\n// CHECK:STDOUT:   %T.loc26_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc26_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc26_32.2: type = ptr_type %T.loc26_14.2 [symbolic = %ptr.loc26_32.2 (constants.%ptr)]\n// CHECK:STDOUT:   %I.type.loc26_33.2: type = facet_type <@I, @I(%ptr.loc26_32.2)> [symbolic = %I.type.loc26_33.2 (constants.%I.type.e19)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %I.type.loc26_33.1 {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.c9332a.1(%T.loc32_14.1: type) {\n// CHECK:STDOUT:   %T.loc32_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc32_14.2 (constants.%T)]\n// CHECK:STDOUT:   %N.type.loc32_32.2: type = facet_type <@N, @N(%T.loc32_14.2)> [symbolic = %N.type.loc32_32.2 (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %N.type.loc32_32.1;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.c9332a.2(%T.loc37_14.1: type) {\n// CHECK:STDOUT:   %T.loc37_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc37_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc37_32.2: type = ptr_type %T.loc37_14.2 [symbolic = %ptr.loc37_32.2 (constants.%ptr)]\n// CHECK:STDOUT:   %N.type.loc37_33.2: type = facet_type <@N, @N(%ptr.loc37_32.2)> [symbolic = %N.type.loc37_33.2 (constants.%N.type.d682d6.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %N.type.loc37_33.1;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"import_generic.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %Self => constants.%Self.c1b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%Self.c1b) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.431d5e.1(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %I.impl_witness => constants.%I.impl_witness.9f5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%ptr) {\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.e19\n// CHECK:STDOUT:   %Self => constants.%Self.dda\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.8159c7.1(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %ptr => constants.%ptr\n// CHECK:STDOUT:   %I.type => constants.%I.type.e19\n// CHECK:STDOUT:   %I.impl_witness => constants.%I.impl_witness.18a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.431d5e.2(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_14.2 => constants.%T\n// CHECK:STDOUT:   %I.type.loc8_32.2 => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.431d5e.3(constants.%T) {\n// CHECK:STDOUT:   %T.loc14_14.2 => constants.%T\n// CHECK:STDOUT:   %I.type.loc14_32.2 => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.8159c7.2(constants.%T) {\n// CHECK:STDOUT:   %T.loc20_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc20_32.2 => constants.%ptr\n// CHECK:STDOUT:   %I.type.loc20_33.2 => constants.%I.type.e19\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.8159c7.3(constants.%T) {\n// CHECK:STDOUT:   %T.loc26_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc26_32.2 => constants.%ptr\n// CHECK:STDOUT:   %I.type.loc26_33.2 => constants.%I.type.e19\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.e1f642.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.e36\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.e1f642.1) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%C.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.e36\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%C.type.facet) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1\n// CHECK:STDOUT:   %Self => constants.%C.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.c9332a.1(constants.%T) {\n// CHECK:STDOUT:   %T.loc32_14.2 => constants.%T\n// CHECK:STDOUT:   %N.type.loc32_32.2 => constants.%N.type.d682d6.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N(constants.%ptr) {\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.2\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr, constants.%Self.e1f642.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT:   %I.type => constants.%I.type.e19\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.ffd\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr, constants.%C.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT:   %I.type => constants.%I.type.e19\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.ffd\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%ptr, constants.%C.type.facet) {\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.2\n// CHECK:STDOUT:   %Self => constants.%C.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C\n// CHECK:STDOUT:   %I.type => constants.%I.type.e19\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.c9332a.2(constants.%T) {\n// CHECK:STDOUT:   %T.loc37_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc37_32.2 => constants.%ptr\n// CHECK:STDOUT:   %N.type.loc37_33.2 => constants.%N.type.d682d6.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- import_generic_with_different_specific.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.fdb: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness @C.as.I.impl.%I.impl_witness_table, @C.as.I.impl(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.1ab [symbolic]\n// CHECK:STDOUT:   %I.facet: %I.type.1ab = facet_value %C, (%I.impl_witness) [symbolic]\n// CHECK:STDOUT:   %N.type.b47: type = generic_named_constaint_type @N [concrete]\n// CHECK:STDOUT:   %empty_struct: %N.type.b47 = struct_value () [concrete]\n// CHECK:STDOUT:   %N.type.d68: type = facet_type <@N, @N(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.31c: %N.type.d68 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.31c [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = %C.decl\n// CHECK:STDOUT:     .I = %I.decl\n// CHECK:STDOUT:     .N = %N.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %C.decl: type = class_decl @C [concrete = constants.%C] {} {}\n// CHECK:STDOUT:   %I.decl: %I.type.609 = interface_decl @I [concrete = constants.%I.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_17.1: type = splice_block %.loc5_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc5_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc7_14.1 [symbolic = %T.loc7_14.2 (constants.%T)]\n// CHECK:STDOUT:     %I.type.loc7_32.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc7_32.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:     %.loc7_18.1: type = splice_block %.loc7_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %N.decl: %N.type.b47 = constraint_decl @N [concrete = constants.%empty_struct] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc9_18.1: type = splice_block %.loc9_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc9_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc9_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc9_14.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(%T.loc5_13.2: type) {\n// CHECK:STDOUT:   %T.loc5_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T.loc5_13.1)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self.loc5_23.2: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc5_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc5_23.1: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self.loc5_23.2 (constants.%Self.fdb)]\n// CHECK:STDOUT:     %I.WithSelf.decl = interface_with_self_decl @I [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc5_23.1\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic constraint @N(%T.loc9_14.2: type) {\n// CHECK:STDOUT:   %T.loc9_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc9_14.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T.loc9_14.1)> [symbolic = %N.type (constants.%N.type.d68)]\n// CHECK:STDOUT:   %Self.loc9_24.2: @N.%N.type (%N.type.d68) = symbolic_binding Self, 1 [symbolic = %Self.loc9_24.2 (constants.%Self.31c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   constraint {\n// CHECK:STDOUT:     %Self.loc9_24.1: @N.%N.type (%N.type.d68) = symbolic_binding Self, 1 [symbolic = %Self.loc9_24.2 (constants.%Self.31c)]\n// CHECK:STDOUT:     %N.WithSelf.decl = constraint_with_self_decl @N [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %N.WithSelf.Self.binding.as_type.impls.I.type.require.decl = require_decl @N.WithSelf.Self.binding.as_type.impls.I.type.require [concrete] {\n// CHECK:STDOUT:       require %Self.as_type impls %I.type.loc10_27.1\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type @N.%Self.loc9_24.1 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       %I.ref: %I.type.609 = name_ref I, file.%I.decl [concrete = constants.%I.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @N.%T.loc9_14.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %I.type.loc10_27.1: type = facet_type <@I, @I(constants.%T)> [symbolic = %I.type.loc10_27.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %.loc10: type = specific_constant @N.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type.loc10_27.1, @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.31c) [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc9_24.1\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .I = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     extend @N.WithSelf.%.loc10\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @N.WithSelf.Self.binding.as_type.impls.I.type.require {\n// CHECK:STDOUT:       require @N.WithSelf.Self.binding.as_type.impls.I.type.require.%Self.as_type impls @N.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type.loc10_27.1\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @N.WithSelf.Self.binding.as_type.impls.I.type.require(@N.%T.loc9_14.2: type, @N.%Self.loc9_24.1: @N.%N.type (%N.type.d68)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d68)]\n// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.I.type.require.%N.type (%N.type.d68) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.31c)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %I.type.loc10_27.2: type = facet_type <@I, @I(%T)> [symbolic = %I.type.loc10_27.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl(%T.loc7_14.1: type) {\n// CHECK:STDOUT:   %T.loc7_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.2 (constants.%T)]\n// CHECK:STDOUT:   %I.type.loc7_32.2: type = facet_type <@I, @I(%T.loc7_14.2)> [symbolic = %I.type.loc7_32.2 (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %I.impl_witness.loc7_34.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(%T.loc7_14.2) [symbolic = %I.impl_witness.loc7_34.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.loc7_32.2 [symbolic = %require_complete (constants.%require_complete)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %I.type.loc7_32.1 {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (), @C.as.I.impl [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc7_34.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl(constants.%T) [symbolic = %I.impl_witness.loc7_34.2 (constants.%I.impl_witness)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %I.impl_witness.loc7_34.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%C\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %Self.loc5_23.2 => constants.%Self.fdb\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%Self.fdb) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_14.2 => constants.%T\n// CHECK:STDOUT:   %I.type.loc7_32.2 => constants.%I.type.1ab\n// CHECK:STDOUT:   %I.impl_witness.loc7_34.2 => constants.%I.impl_witness\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%I.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N(constants.%T) {\n// CHECK:STDOUT:   %T.loc9_14.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.31c) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.31c) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %N.type => constants.%N.type.d68\n// CHECK:STDOUT:   %Self => constants.%Self.31c\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %I.type.loc10_27.2 => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- import_generic_with_different_specific.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %I.type.609: type = generic_interface_type @I [concrete]\n// CHECK:STDOUT:   %I.generic: %I.type.609 = struct_value () [concrete]\n// CHECK:STDOUT:   %I.type.1ab: type = facet_type <@I, @I(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.c1b: %I.type.1ab = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %C: type = class_type @C [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %I.impl_witness.9f5: <witness> = impl_witness imports.%I.impl_witness_table, @C.as.I.impl.431(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.e36: <witness> = require_complete_type %I.type.1ab [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %ptr.e8f: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %I.type.e19: type = facet_type <@I, @I(%ptr.e8f)> [symbolic]\n// CHECK:STDOUT:   %I.impl_witness.18a: <witness> = impl_witness @C.as.I.impl.815.%I.impl_witness_table, @C.as.I.impl.815(%T) [symbolic]\n// CHECK:STDOUT:   %Self.dda: %I.type.e19 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %require_complete.ffd: <witness> = require_complete_type %I.type.e19 [symbolic]\n// CHECK:STDOUT:   %I.facet.064: %I.type.e19 = facet_value %C, (%I.impl_witness.18a) [symbolic]\n// CHECK:STDOUT:   %N.type.b47: type = generic_named_constaint_type @N [concrete]\n// CHECK:STDOUT:   %empty_struct: %N.type.b47 = struct_value () [concrete]\n// CHECK:STDOUT:   %N.type.d682d6.1: type = facet_type <@N, @N(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.e1f642.1: %N.type.d682d6.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f642.1 [symbolic]\n// CHECK:STDOUT:   %ptr.125: type = ptr_type %ptr.e8f [symbolic]\n// CHECK:STDOUT:   %N.type.d682d6.2: type = facet_type <@N, @N(%ptr.125)> [symbolic]\n// CHECK:STDOUT:   %Self.e1f642.2: %N.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %I.type.08a: type = facet_type <@I, @I(%ptr.125)> [symbolic]\n// CHECK:STDOUT:   %require_complete.ea6: <witness> = require_complete_type %I.type.08a [symbolic]\n// CHECK:STDOUT:   %C.type.facet: %type = facet_value %C, () [concrete]\n// CHECK:STDOUT:   %I.impl_witness.d57: <witness> = impl_witness @C.as.I.impl.c93.%I.impl_witness_table, @C.as.I.impl.c93(%T) [symbolic]\n// CHECK:STDOUT:   %require_complete.533: <witness> = require_complete_type %N.type.d682d6.2 [symbolic]\n// CHECK:STDOUT:   %I.facet.3e9: %I.type.08a = facet_value %C, (%I.impl_witness.d57) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.C: type = import_ref Main//import_generic_with_different_specific, C, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.I: %I.type.609 = import_ref Main//import_generic_with_different_specific, I, loaded [concrete = constants.%I.generic]\n// CHECK:STDOUT:   %Main.N: %N.type.b47 = import_ref Main//import_generic_with_different_specific, N, loaded [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Main.import_ref.3fa = import_ref Main//import_generic_with_different_specific, loc5_23, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//import_generic_with_different_specific, loc5_13, loaded [symbolic = @I.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.e08 = import_ref Main//import_generic_with_different_specific, loc7_34, unloaded\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//import_generic_with_different_specific, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.743 = import_ref Main//import_generic_with_different_specific, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %I.impl_witness_table = impl_witness_table (), @C.as.I.impl.431 [concrete]\n// CHECK:STDOUT:   %Main.import_ref.61c: type = import_ref Main//import_generic_with_different_specific, loc7_24, loaded [concrete = constants.%C]\n// CHECK:STDOUT:   %Main.import_ref.3582b1.1: type = import_ref Main//import_generic_with_different_specific, loc7_32, loaded [symbolic = @C.as.I.impl.431.%I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.3: type = import_ref Main//import_generic_with_different_specific, loc7_14, loaded [symbolic = @C.as.I.impl.431.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.a5e = import_ref Main//import_generic_with_different_specific, loc10_28, unloaded\n// CHECK:STDOUT:   %Main.import_ref.213: type = import_ref Main//import_generic_with_different_specific, loc10_18, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.I.type.require.%Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %Main.import_ref.3582b1.2: type = import_ref Main//import_generic_with_different_specific, loc10_27, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.I.type.require.%I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.5: type = import_ref Main//import_generic_with_different_specific, loc9_14, loaded [symbolic = @N.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1) = import_ref Main//import_generic_with_different_specific, loc9_24, loaded [symbolic = @N.%Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:   %Main.import_ref.830 = import_ref Main//import_generic_with_different_specific, loc9_24, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.6: type = import_ref Main//import_generic_with_different_specific, loc9_14, loaded [symbolic = @N.%T (constants.%T)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .C = imports.%Main.C\n// CHECK:STDOUT:     .I = imports.%Main.I\n// CHECK:STDOUT:     .N = imports.%Main.N\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc1_54.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc1_54.2 = import <none>\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.815 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %I.ref: %I.type.609 = name_ref I, imports.%Main.I [concrete = constants.%I.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc5_14.1 [symbolic = %T.loc5_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc5_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc5_32.2 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     %I.type.loc5_33.1: type = facet_type <@I, @I(constants.%ptr.e8f)> [symbolic = %I.type.loc5_33.2 (constants.%I.type.e19)]\n// CHECK:STDOUT:     %.loc5_18.1: type = splice_block %.loc5_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc5_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc5_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @C.as.I.impl.c93 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C]\n// CHECK:STDOUT:     %N.ref: %N.type.b47 = name_ref N, imports.%Main.N [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc6_14.1 [symbolic = %T.loc6_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc6_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc6_32.2 (constants.%ptr.e8f)]\n// CHECK:STDOUT:     %ptr.loc6_33.1: type = ptr_type %ptr.loc6_32.1 [symbolic = %ptr.loc6_33.2 (constants.%ptr.125)]\n// CHECK:STDOUT:     %N.type.loc6_34.1: type = facet_type <@N, @N(constants.%ptr.125)> [symbolic = %N.type.loc6_34.2 (constants.%N.type.d682d6.2)]\n// CHECK:STDOUT:     %.loc6_18.1: type = splice_block %.loc6_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc6_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc6_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc6_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @I(imports.%Main.import_ref.b3bc94.2: type) [from \"import_generic_with_different_specific.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %Self: @I.%I.type (%I.type.1ab) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.c1b)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.3fa\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic constraint @N(imports.%Main.import_ref.b3bc94.6: type) [from \"import_generic_with_different_specific.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   constraint {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.830\n// CHECK:STDOUT:     extend imports.%Main.import_ref.a5e\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @N.WithSelf.Self.binding.as_type.impls.I.type.require {\n// CHECK:STDOUT:       require imports.%Main.import_ref.213 impls imports.%Main.import_ref.3582b1.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @N.WithSelf.Self.binding.as_type.impls.I.type.require(imports.%Main.import_ref.b3bc94.5: type, imports.%Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1)) [from \"import_generic_with_different_specific.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.I.type.require.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.431(imports.%Main.import_ref.b3bc94.3: type) [from \"import_generic_with_different_specific.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %I.type: type = facet_type <@I, @I(%T)> [symbolic = %I.type (constants.%I.type.1ab)]\n// CHECK:STDOUT:   %I.impl_witness: <witness> = impl_witness imports.%I.impl_witness_table, @C.as.I.impl.431(%T) [symbolic = %I.impl_witness (constants.%I.impl_witness.9f5)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type [symbolic = %require_complete (constants.%require_complete.e36)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: imports.%Main.import_ref.61c as imports.%Main.import_ref.3582b1.1 {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = imports.%Main.import_ref.e08\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.815(%T.loc5_14.1: type) {\n// CHECK:STDOUT:   %T.loc5_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc5_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc5_32.2: type = ptr_type %T.loc5_14.2 [symbolic = %ptr.loc5_32.2 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %I.type.loc5_33.2: type = facet_type <@I, @I(%ptr.loc5_32.2)> [symbolic = %I.type.loc5_33.2 (constants.%I.type.e19)]\n// CHECK:STDOUT:   %I.impl_witness.loc5_35.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl.815(%T.loc5_14.2) [symbolic = %I.impl_witness.loc5_35.2 (constants.%I.impl_witness.18a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %I.type.loc5_33.2 [symbolic = %require_complete (constants.%require_complete.ffd)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %I.type.loc5_33.1 {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (), @C.as.I.impl.815 [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc5_35.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl.815(constants.%T) [symbolic = %I.impl_witness.loc5_35.2 (constants.%I.impl_witness.18a)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %I.impl_witness.loc5_35.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @C.as.I.impl.c93(%T.loc6_14.1: type) {\n// CHECK:STDOUT:   %T.loc6_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc6_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc6_32.2: type = ptr_type %T.loc6_14.2 [symbolic = %ptr.loc6_32.2 (constants.%ptr.e8f)]\n// CHECK:STDOUT:   %ptr.loc6_33.2: type = ptr_type %ptr.loc6_32.2 [symbolic = %ptr.loc6_33.2 (constants.%ptr.125)]\n// CHECK:STDOUT:   %N.type.loc6_34.2: type = facet_type <@N, @N(%ptr.loc6_33.2)> [symbolic = %N.type.loc6_34.2 (constants.%N.type.d682d6.2)]\n// CHECK:STDOUT:   %I.impl_witness.loc6_36.2: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl.c93(%T.loc6_14.2) [symbolic = %I.impl_witness.loc6_36.2 (constants.%I.impl_witness.d57)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %require_complete: <witness> = require_complete_type %N.type.loc6_34.2 [symbolic = %require_complete (constants.%require_complete.533)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %C.ref as %N.type.loc6_34.1 {\n// CHECK:STDOUT:     %I.impl_witness_table = impl_witness_table (), @C.as.I.impl.c93 [concrete]\n// CHECK:STDOUT:     %I.impl_witness.loc6_36.1: <witness> = impl_witness %I.impl_witness_table, @C.as.I.impl.c93(constants.%T) [symbolic = %I.impl_witness.loc6_36.2 (constants.%I.impl_witness.d57)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = %I.impl_witness.loc6_36.1\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @C [from \"import_generic_with_different_specific.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.743\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %Self => constants.%Self.c1b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%T, constants.%Self.c1b) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.431(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT:   %I.impl_witness => constants.%I.impl_witness.9f5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%ptr.e8f) {\n// CHECK:STDOUT:   %T => constants.%ptr.e8f\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %I.type => constants.%I.type.e19\n// CHECK:STDOUT:   %Self => constants.%Self.dda\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.815(constants.%T) {\n// CHECK:STDOUT:   %T.loc5_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc5_32.2 => constants.%ptr.e8f\n// CHECK:STDOUT:   %I.type.loc5_33.2 => constants.%I.type.e19\n// CHECK:STDOUT:   %I.impl_witness.loc5_35.2 => constants.%I.impl_witness.18a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%ptr.e8f, constants.%Self.c1b) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%ptr.e8f, constants.%I.facet.064) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.e1f642.1) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%T, constants.%Self.e1f642.1) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %I.type => constants.%I.type.1ab\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N(constants.%ptr.125) {\n// CHECK:STDOUT:   %T => constants.%ptr.125\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.2\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr.125, constants.%Self.e1f642.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%ptr.125\n// CHECK:STDOUT:   %I.type => constants.%I.type.08a\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.ea6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I(constants.%ptr.125) {\n// CHECK:STDOUT:   %T => constants.%ptr.125\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr.125, constants.%C.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%ptr.125\n// CHECK:STDOUT:   %I.type => constants.%I.type.08a\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.ea6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.I.type.require(constants.%ptr.125, constants.%C.type.facet) {\n// CHECK:STDOUT:   %T => constants.%ptr.125\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.2\n// CHECK:STDOUT:   %Self => constants.%C.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%C\n// CHECK:STDOUT:   %I.type => constants.%I.type.08a\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @C.as.I.impl.c93(constants.%T) {\n// CHECK:STDOUT:   %T.loc6_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc6_32.2 => constants.%ptr.e8f\n// CHECK:STDOUT:   %ptr.loc6_33.2 => constants.%ptr.125\n// CHECK:STDOUT:   %N.type.loc6_34.2 => constants.%N.type.d682d6.2\n// CHECK:STDOUT:   %I.impl_witness.loc6_36.2 => constants.%I.impl_witness.d57\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @I.WithSelf(constants.%ptr.125, constants.%I.facet.3e9) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_import_generic_decl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %J.type.885: type = generic_interface_type @J [concrete]\n// CHECK:STDOUT:   %J.generic: %J.type.885 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.type.04e: type = facet_type <@J, @J(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.a60: %J.type.04e = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %N.type.b47: type = generic_named_constaint_type @N [concrete]\n// CHECK:STDOUT:   %empty_struct: %N.type.b47 = struct_value () [concrete]\n// CHECK:STDOUT:   %N.type.d68: type = facet_type <@N, @N(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.31c: %N.type.d68 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.31c [symbolic]\n// CHECK:STDOUT:   %J.impl_witness.861: <witness> = impl_witness @D.as.J.impl.b25.%J.impl_witness_table, @D.as.J.impl.b25(%T) [symbolic]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %J.type.80f: type = facet_type <@J, @J(%ptr)> [symbolic]\n// CHECK:STDOUT:   %J.impl_witness.f4f: <witness> = impl_witness @D.as.J.impl.f05.%J.impl_witness_table, @D.as.J.impl.f05(%T) [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = %D.decl\n// CHECK:STDOUT:     .J = %J.decl\n// CHECK:STDOUT:     .N = %N.decl\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %D.decl: type = class_decl @D [concrete = constants.%D] {} {}\n// CHECK:STDOUT:   %J.decl: %J.type.885 = interface_decl @J [concrete = constants.%J.generic] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc5_17.1: type = splice_block %.loc5_17.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc5_17.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc5_13.2: type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %N.decl: %N.type.b47 = constraint_decl @N [concrete = constants.%empty_struct] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %.loc7_18.1: type = splice_block %.loc7_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc7_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc7_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.1 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @D.as.J.impl.b25 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %J.ref: %J.type.885 = name_ref J, file.%J.decl [concrete = constants.%J.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc15_14.1 [symbolic = %T.loc15_14.2 (constants.%T)]\n// CHECK:STDOUT:     %J.type.loc15_32.1: type = facet_type <@J, @J(constants.%T)> [symbolic = %J.type.loc15_32.2 (constants.%J.type.04e)]\n// CHECK:STDOUT:     %.loc15_18.1: type = splice_block %.loc15_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc15_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc15_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc15_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @D.as.J.impl.f05 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, file.%D.decl [concrete = constants.%D]\n// CHECK:STDOUT:     %J.ref: %J.type.885 = name_ref J, file.%J.decl [concrete = constants.%J.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc21_14.1 [symbolic = %T.loc21_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc21_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc21_32.2 (constants.%ptr)]\n// CHECK:STDOUT:     %J.type.loc21_33.1: type = facet_type <@J, @J(constants.%ptr)> [symbolic = %J.type.loc21_33.2 (constants.%J.type.80f)]\n// CHECK:STDOUT:     %.loc21_18.1: type = splice_block %.loc21_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc21_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc21_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc21_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @J(%T.loc5_13.2: type) {\n// CHECK:STDOUT:   %T.loc5_13.1: type = symbolic_binding T, 0 [symbolic = %T.loc5_13.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T.loc5_13.1)> [symbolic = %J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:   %Self.loc5_23.2: @J.%J.type (%J.type.04e) = symbolic_binding Self, 1 [symbolic = %Self.loc5_23.2 (constants.%Self.a60)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:     %Self.loc5_23.1: @J.%J.type (%J.type.04e) = symbolic_binding Self, 1 [symbolic = %Self.loc5_23.2 (constants.%Self.a60)]\n// CHECK:STDOUT:     %J.WithSelf.decl = interface_with_self_decl @J [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc5_23.1\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic constraint @N(%T.loc7_14.2: type) {\n// CHECK:STDOUT:   %T.loc7_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc7_14.1 (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T.loc7_14.1)> [symbolic = %N.type (constants.%N.type.d68)]\n// CHECK:STDOUT:   %Self.loc7_24.2: @N.%N.type (%N.type.d68) = symbolic_binding Self, 1 [symbolic = %Self.loc7_24.2 (constants.%Self.31c)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   constraint {\n// CHECK:STDOUT:     %Self.loc7_24.1: @N.%N.type (%N.type.d68) = symbolic_binding Self, 1 [symbolic = %Self.loc7_24.2 (constants.%Self.31c)]\n// CHECK:STDOUT:     %N.WithSelf.decl = constraint_with_self_decl @N [concrete]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !with Self:\n// CHECK:STDOUT:     %N.WithSelf.Self.binding.as_type.impls.J.type.require.decl = require_decl @N.WithSelf.Self.binding.as_type.impls.J.type.require [concrete] {\n// CHECK:STDOUT:       require %Self.as_type impls %J.type.loc8_27.1\n// CHECK:STDOUT:     } {\n// CHECK:STDOUT:       %Self.as_type: type = facet_access_type @N.%Self.loc7_24.1 [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:       %J.ref: %J.type.885 = name_ref J, file.%J.decl [concrete = constants.%J.generic]\n// CHECK:STDOUT:       %T.ref: type = name_ref T, @N.%T.loc7_14.2 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:       %J.type.loc8_27.1: type = facet_type <@J, @J(constants.%T)> [symbolic = %J.type.loc8_27.2 (constants.%J.type.04e)]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %.loc8: type = specific_constant @N.WithSelf.Self.binding.as_type.impls.J.type.require.%J.type.loc8_27.1, @N.WithSelf.Self.binding.as_type.impls.J.type.require(constants.%T, constants.%Self.31c) [symbolic = %J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = %Self.loc7_24.1\n// CHECK:STDOUT:     .J = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     .J = <poisoned>\n// CHECK:STDOUT:     .T = <poisoned>\n// CHECK:STDOUT:     extend @N.WithSelf.%.loc8\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @N.WithSelf.Self.binding.as_type.impls.J.type.require {\n// CHECK:STDOUT:       require @N.WithSelf.Self.binding.as_type.impls.J.type.require.%Self.as_type impls @N.WithSelf.Self.binding.as_type.impls.J.type.require.%J.type.loc8_27.1\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @N.WithSelf.Self.binding.as_type.impls.J.type.require(@N.%T.loc7_14.2: type, @N.%Self.loc7_24.1: @N.%N.type (%N.type.d68)) {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d68)]\n// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.J.type.require.%N.type (%N.type.d68) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.31c)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %J.type.loc8_27.2: type = facet_type <@J, @J(%T)> [symbolic = %J.type.loc8_27.2 (constants.%J.type.04e)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.b25(%T.loc15_14.1: type) {\n// CHECK:STDOUT:   %T.loc15_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc15_14.2 (constants.%T)]\n// CHECK:STDOUT:   %J.type.loc15_32.2: type = facet_type <@J, @J(%T.loc15_14.2)> [symbolic = %J.type.loc15_32.2 (constants.%J.type.04e)]\n// CHECK:STDOUT:   %J.impl_witness.loc15_33.2: <witness> = impl_witness %J.impl_witness_table, @D.as.J.impl.b25(%T.loc15_14.2) [symbolic = %J.impl_witness.loc15_33.2 (constants.%J.impl_witness.861)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %D.ref as %J.type.loc15_32.1;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.f05(%T.loc21_14.1: type) {\n// CHECK:STDOUT:   %T.loc21_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc21_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc21_32.2: type = ptr_type %T.loc21_14.2 [symbolic = %ptr.loc21_32.2 (constants.%ptr)]\n// CHECK:STDOUT:   %J.type.loc21_33.2: type = facet_type <@J, @J(%ptr.loc21_32.2)> [symbolic = %J.type.loc21_33.2 (constants.%J.type.80f)]\n// CHECK:STDOUT:   %J.impl_witness.loc21_34.2: <witness> = impl_witness %J.impl_witness_table, @D.as.J.impl.f05(%T.loc21_14.2) [symbolic = %J.impl_witness.loc21_34.2 (constants.%J.impl_witness.f4f)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %D.ref as %J.type.loc21_33.1;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D {\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type]\n// CHECK:STDOUT:   complete_type_witness = %complete_type\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = constants.%D\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%T) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type => constants.%J.type.04e\n// CHECK:STDOUT:   %Self.loc5_23.2 => constants.%Self.a60\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%T, constants.%Self.a60) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N(constants.%T) {\n// CHECK:STDOUT:   %T.loc7_14.1 => constants.%T\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.31c) {}\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.J.type.require(constants.%T, constants.%Self.31c) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %N.type => constants.%N.type.d68\n// CHECK:STDOUT:   %Self => constants.%Self.31c\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %J.type.loc8_27.2 => constants.%J.type.04e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.b25(constants.%T) {\n// CHECK:STDOUT:   %T.loc15_14.2 => constants.%T\n// CHECK:STDOUT:   %J.type.loc15_32.2 => constants.%J.type.04e\n// CHECK:STDOUT:   %J.impl_witness.loc15_33.2 => constants.%J.impl_witness.861\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%ptr) {\n// CHECK:STDOUT:   %T.loc5_13.1 => constants.%ptr\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.f05(constants.%T) {\n// CHECK:STDOUT:   %T.loc21_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc21_32.2 => constants.%ptr\n// CHECK:STDOUT:   %J.type.loc21_33.2 => constants.%J.type.80f\n// CHECK:STDOUT:   %J.impl_witness.loc21_34.2 => constants.%J.impl_witness.f4f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: --- fail_import_generic_decl.impl.carbon\n// CHECK:STDOUT:\n// CHECK:STDOUT: constants {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic]\n// CHECK:STDOUT:   %J.type.885: type = generic_interface_type @J [concrete]\n// CHECK:STDOUT:   %J.generic: %J.type.885 = struct_value () [concrete]\n// CHECK:STDOUT:   %J.type.04e: type = facet_type <@J, @J(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.c25: %J.type.04e = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %pattern_type: type = pattern_type type [concrete]\n// CHECK:STDOUT:   %D: type = class_type @D [concrete]\n// CHECK:STDOUT:   %empty_struct_type: type = struct_type {} [concrete]\n// CHECK:STDOUT:   %complete_type: <witness> = complete_type_witness %empty_struct_type [concrete]\n// CHECK:STDOUT:   %J.impl_witness.861: <witness> = impl_witness imports.%J.impl_witness_table.50b, @D.as.J.impl.b25a4e.1(%T) [symbolic]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic]\n// CHECK:STDOUT:   %J.type.80f: type = facet_type <@J, @J(%ptr)> [symbolic]\n// CHECK:STDOUT:   %J.impl_witness.f4f: <witness> = impl_witness imports.%J.impl_witness_table.a37, @D.as.J.impl.f050b9.1(%T) [symbolic]\n// CHECK:STDOUT:   %type: type = facet_type <type> [concrete]\n// CHECK:STDOUT:   %.Self: %type = symbolic_binding .Self [symbolic_self]\n// CHECK:STDOUT:   %N.type.b47: type = generic_named_constaint_type @N [concrete]\n// CHECK:STDOUT:   %empty_struct: %N.type.b47 = struct_value () [concrete]\n// CHECK:STDOUT:   %N.type.d682d6.1: type = facet_type <@N, @N(%T)> [symbolic]\n// CHECK:STDOUT:   %Self.e1f642.1: %N.type.d682d6.1 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %require_complete.cc6: <witness> = require_complete_type %J.type.04e [symbolic]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self.e1f642.1 [symbolic]\n// CHECK:STDOUT:   %D.type.facet: %type = facet_value %D, () [concrete]\n// CHECK:STDOUT:   %N.type.d682d6.2: type = facet_type <@N, @N(%ptr)> [symbolic]\n// CHECK:STDOUT:   %Self.e1f642.2: %N.type.d682d6.2 = symbolic_binding Self, 1 [symbolic]\n// CHECK:STDOUT:   %require_complete.19b: <witness> = require_complete_type %J.type.80f [symbolic]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: imports {\n// CHECK:STDOUT:   %Main.D: type = import_ref Main//import_generic_decl, D, loaded [concrete = constants.%D]\n// CHECK:STDOUT:   %Main.J: %J.type.885 = import_ref Main//import_generic_decl, J, loaded [concrete = constants.%J.generic]\n// CHECK:STDOUT:   %Main.N: %N.type.b47 = import_ref Main//import_generic_decl, N, loaded [concrete = constants.%empty_struct]\n// CHECK:STDOUT:   %Main.import_ref.e9b = import_ref Main//import_generic_decl, loc5_23, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.2: type = import_ref Main//import_generic_decl, loc5_13, loaded [symbolic = @J.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.8f2: <witness> = import_ref Main//import_generic_decl, loc4_10, loaded [concrete = constants.%complete_type]\n// CHECK:STDOUT:   %Main.import_ref.1d5 = import_ref Main//import_generic_decl, inst{{[0-9A-F]+}} [no loc], unloaded\n// CHECK:STDOUT:   %J.impl_witness_table.50b = impl_witness_table (), @D.as.J.impl.b25a4e.1 [concrete]\n// CHECK:STDOUT:   %Main.import_ref.4ae308.1: type = import_ref Main//import_generic_decl, loc15_24, loaded [concrete = constants.%D]\n// CHECK:STDOUT:   %Main.import_ref.f2a55c.1: type = import_ref Main//import_generic_decl, loc15_32, loaded [symbolic = @D.as.J.impl.b25a4e.1.%J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.3: type = import_ref Main//import_generic_decl, loc15_14, loaded [symbolic = @D.as.J.impl.b25a4e.1.%T (constants.%T)]\n// CHECK:STDOUT:   %J.impl_witness_table.a37 = impl_witness_table (), @D.as.J.impl.f050b9.1 [concrete]\n// CHECK:STDOUT:   %Main.import_ref.4ae308.2: type = import_ref Main//import_generic_decl, loc21_24, loaded [concrete = constants.%D]\n// CHECK:STDOUT:   %Main.import_ref.739: type = import_ref Main//import_generic_decl, loc21_33, loaded [symbolic = @D.as.J.impl.f050b9.1.%J.type (constants.%J.type.80f)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.4: type = import_ref Main//import_generic_decl, loc21_14, loaded [symbolic = @D.as.J.impl.f050b9.1.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.9d6 = import_ref Main//import_generic_decl, loc8_28, unloaded\n// CHECK:STDOUT:   %Main.import_ref.213: type = import_ref Main//import_generic_decl, loc8_18, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.J.type.require.%Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %Main.import_ref.f2a55c.2: type = import_ref Main//import_generic_decl, loc8_27, loaded [symbolic = @N.WithSelf.Self.binding.as_type.impls.J.type.require.%J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.6: type = import_ref Main//import_generic_decl, loc7_14, loaded [symbolic = @N.%T (constants.%T)]\n// CHECK:STDOUT:   %Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1) = import_ref Main//import_generic_decl, loc7_24, loaded [symbolic = @N.%Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:   %Main.import_ref.830 = import_ref Main//import_generic_decl, loc7_24, unloaded\n// CHECK:STDOUT:   %Main.import_ref.b3bc94.7: type = import_ref Main//import_generic_decl, loc7_14, loaded [symbolic = @N.%T (constants.%T)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: file {\n// CHECK:STDOUT:   package: <namespace> = namespace [concrete] {\n// CHECK:STDOUT:     .D = imports.%Main.D\n// CHECK:STDOUT:     .J = imports.%Main.J\n// CHECK:STDOUT:     .N = imports.%Main.N\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   %default.import.loc2_35.1 = import <none>\n// CHECK:STDOUT:   %default.import.loc2_35.2 = import <none>\n// CHECK:STDOUT:   impl_decl @D.as.J.impl.b25a4e.2 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:     %J.ref: %J.type.885 = name_ref J, imports.%Main.J [concrete = constants.%J.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc8_14.1 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:     %J.type.loc8_32.1: type = facet_type <@J, @J(constants.%T)> [symbolic = %J.type.loc8_32.2 (constants.%J.type.04e)]\n// CHECK:STDOUT:     %.loc8_18.1: type = splice_block %.loc8_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc8_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc8_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @D.as.J.impl.b25a4e.3 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:     %J.ref: %J.type.885 = name_ref J, imports.%Main.J [concrete = constants.%J.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc14_14.1 [symbolic = %T.loc14_14.2 (constants.%T)]\n// CHECK:STDOUT:     %J.type.loc14_32.1: type = facet_type <@J, @J(constants.%T)> [symbolic = %J.type.loc14_32.2 (constants.%J.type.04e)]\n// CHECK:STDOUT:     %.loc14_18.1: type = splice_block %.loc14_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc14_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc14_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc14_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @D.as.J.impl.f050b9.2 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:     %J.ref: %J.type.885 = name_ref J, imports.%Main.J [concrete = constants.%J.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc20_14.1 [symbolic = %T.loc20_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc20_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc20_32.2 (constants.%ptr)]\n// CHECK:STDOUT:     %J.type.loc20_33.1: type = facet_type <@J, @J(constants.%ptr)> [symbolic = %J.type.loc20_33.2 (constants.%J.type.80f)]\n// CHECK:STDOUT:     %.loc20_18.1: type = splice_block %.loc20_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc20_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc20_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc20_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @D.as.J.impl.f050b9.3 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:     %J.ref: %J.type.885 = name_ref J, imports.%Main.J [concrete = constants.%J.generic]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc26_14.1 [symbolic = %T.loc26_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc26_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc26_32.2 (constants.%ptr)]\n// CHECK:STDOUT:     %J.type.loc26_33.1: type = facet_type <@J, @J(constants.%ptr)> [symbolic = %J.type.loc26_33.2 (constants.%J.type.80f)]\n// CHECK:STDOUT:     %.loc26_18.1: type = splice_block %.loc26_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc26_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc26_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc26_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @D.as.J.impl.e28c26.1 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:     %N.ref: %N.type.b47 = name_ref N, imports.%Main.N [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc32_14.1 [symbolic = %T.loc32_14.2 (constants.%T)]\n// CHECK:STDOUT:     %N.type.loc32_32.1: type = facet_type <@N, @N(constants.%T)> [symbolic = %N.type.loc32_32.2 (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:     %.loc32_18.1: type = splice_block %.loc32_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc32_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc32_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc32_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT:   impl_decl @D.as.J.impl.e28c26.2 [concrete] {\n// CHECK:STDOUT:     %T.patt: %pattern_type = symbolic_binding_pattern T, 0 [concrete]\n// CHECK:STDOUT:   } {\n// CHECK:STDOUT:     %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%D]\n// CHECK:STDOUT:     %N.ref: %N.type.b47 = name_ref N, imports.%Main.N [concrete = constants.%empty_struct]\n// CHECK:STDOUT:     %T.ref: type = name_ref T, %T.loc38_14.1 [symbolic = %T.loc38_14.2 (constants.%T)]\n// CHECK:STDOUT:     %ptr.loc38_32.1: type = ptr_type %T.ref [symbolic = %ptr.loc38_32.2 (constants.%ptr)]\n// CHECK:STDOUT:     %N.type.loc38_33.1: type = facet_type <@N, @N(constants.%ptr)> [symbolic = %N.type.loc38_33.2 (constants.%N.type.d682d6.2)]\n// CHECK:STDOUT:     %.loc38_18.1: type = splice_block %.loc38_18.2 [concrete = type] {\n// CHECK:STDOUT:       %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self]\n// CHECK:STDOUT:       %.loc38_18.2: type = type_literal type [concrete = type]\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:     %T.loc38_14.1: type = symbolic_binding T, 0 [symbolic = %T.loc38_14.2 (constants.%T)]\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic interface @J(imports.%Main.import_ref.b3bc94.2: type) [from \"fail_import_generic_decl.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:   %Self: @J.%J.type (%J.type.04e) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.c25)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   interface {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.e9b\n// CHECK:STDOUT:     witness = ()\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic constraint @N(imports.%Main.import_ref.b3bc94.7: type) [from \"fail_import_generic_decl.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:   %Self: @N.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   constraint {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     .Self = imports.%Main.import_ref.830\n// CHECK:STDOUT:     extend imports.%Main.import_ref.9d6\n// CHECK:STDOUT:\n// CHECK:STDOUT:   !requires:\n// CHECK:STDOUT:     @N.WithSelf.Self.binding.as_type.impls.J.type.require {\n// CHECK:STDOUT:       require imports.%Main.import_ref.213 impls imports.%Main.import_ref.f2a55c.2\n// CHECK:STDOUT:     }\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic require @N.WithSelf.Self.binding.as_type.impls.J.type.require(imports.%Main.import_ref.b3bc94.6: type, imports.%Main.import_ref.2fc394.2: @N.%N.type (%N.type.d682d6.1)) [from \"fail_import_generic_decl.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %N.type: type = facet_type <@N, @N(%T)> [symbolic = %N.type (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:   %Self: @N.WithSelf.Self.binding.as_type.impls.J.type.require.%N.type (%N.type.d682d6.1) = symbolic_binding Self, 1 [symbolic = %Self (constants.%Self.e1f642.1)]\n// CHECK:STDOUT:   %Self.binding.as_type: type = symbolic_binding_type Self, 1, %Self [symbolic = %Self.binding.as_type (constants.%Self.binding.as_type)]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.04e)]\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.b25a4e.1(imports.%Main.import_ref.b3bc94.3: type) [from \"fail_import_generic_decl.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%T)> [symbolic = %J.type (constants.%J.type.04e)]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness imports.%J.impl_witness_table.50b, @D.as.J.impl.b25a4e.1(%T) [symbolic = %J.impl_witness (constants.%J.impl_witness.861)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: imports.%Main.import_ref.4ae308.1 as imports.%Main.import_ref.f2a55c.1;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.f050b9.1(imports.%Main.import_ref.b3bc94.4: type) [from \"fail_import_generic_decl.carbon\"] {\n// CHECK:STDOUT:   %T: type = symbolic_binding T, 0 [symbolic = %T (constants.%T)]\n// CHECK:STDOUT:   %ptr: type = ptr_type %T [symbolic = %ptr (constants.%ptr)]\n// CHECK:STDOUT:   %J.type: type = facet_type <@J, @J(%ptr)> [symbolic = %J.type (constants.%J.type.80f)]\n// CHECK:STDOUT:   %J.impl_witness: <witness> = impl_witness imports.%J.impl_witness_table.a37, @D.as.J.impl.f050b9.1(%T) [symbolic = %J.impl_witness (constants.%J.impl_witness.f4f)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: imports.%Main.import_ref.4ae308.2 as imports.%Main.import_ref.739;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.b25a4e.2(%T.loc8_14.1: type) {\n// CHECK:STDOUT:   %T.loc8_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc8_14.2 (constants.%T)]\n// CHECK:STDOUT:   %J.type.loc8_32.2: type = facet_type <@J, @J(%T.loc8_14.2)> [symbolic = %J.type.loc8_32.2 (constants.%J.type.04e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %D.ref as %J.type.loc8_32.1;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.b25a4e.3(%T.loc14_14.1: type) {\n// CHECK:STDOUT:   %T.loc14_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc14_14.2 (constants.%T)]\n// CHECK:STDOUT:   %J.type.loc14_32.2: type = facet_type <@J, @J(%T.loc14_14.2)> [symbolic = %J.type.loc14_32.2 (constants.%J.type.04e)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %D.ref as %J.type.loc14_32.1 {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.f050b9.2(%T.loc20_14.1: type) {\n// CHECK:STDOUT:   %T.loc20_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc20_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc20_32.2: type = ptr_type %T.loc20_14.2 [symbolic = %ptr.loc20_32.2 (constants.%ptr)]\n// CHECK:STDOUT:   %J.type.loc20_33.2: type = facet_type <@J, @J(%ptr.loc20_32.2)> [symbolic = %J.type.loc20_33.2 (constants.%J.type.80f)]\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %D.ref as %J.type.loc20_33.1;\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.f050b9.3(%T.loc26_14.1: type) {\n// CHECK:STDOUT:   %T.loc26_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc26_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc26_32.2: type = ptr_type %T.loc26_14.2 [symbolic = %ptr.loc26_32.2 (constants.%ptr)]\n// CHECK:STDOUT:   %J.type.loc26_33.2: type = facet_type <@J, @J(%ptr.loc26_32.2)> [symbolic = %J.type.loc26_33.2 (constants.%J.type.80f)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %D.ref as %J.type.loc26_33.1 {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.e28c26.1(%T.loc32_14.1: type) {\n// CHECK:STDOUT:   %T.loc32_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc32_14.2 (constants.%T)]\n// CHECK:STDOUT:   %N.type.loc32_32.2: type = facet_type <@N, @N(%T.loc32_14.2)> [symbolic = %N.type.loc32_32.2 (constants.%N.type.d682d6.1)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %D.ref as %N.type.loc32_32.1 {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: generic impl @D.as.J.impl.e28c26.2(%T.loc38_14.1: type) {\n// CHECK:STDOUT:   %T.loc38_14.2: type = symbolic_binding T, 0 [symbolic = %T.loc38_14.2 (constants.%T)]\n// CHECK:STDOUT:   %ptr.loc38_32.2: type = ptr_type %T.loc38_14.2 [symbolic = %ptr.loc38_32.2 (constants.%ptr)]\n// CHECK:STDOUT:   %N.type.loc38_33.2: type = facet_type <@N, @N(%ptr.loc38_32.2)> [symbolic = %N.type.loc38_33.2 (constants.%N.type.d682d6.2)]\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:\n// CHECK:STDOUT:   impl: %D.ref as %N.type.loc38_33.1 {\n// CHECK:STDOUT:   !members:\n// CHECK:STDOUT:     witness = <error>\n// CHECK:STDOUT:   }\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: class @D [from \"fail_import_generic_decl.carbon\"] {\n// CHECK:STDOUT:   complete_type_witness = imports.%Main.import_ref.8f2\n// CHECK:STDOUT:\n// CHECK:STDOUT: !members:\n// CHECK:STDOUT:   .Self = imports.%Main.import_ref.1d5\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %J.type => constants.%J.type.04e\n// CHECK:STDOUT:   %Self => constants.%Self.c25\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J.WithSelf(constants.%T, constants.%Self.c25) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.b25a4e.1(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %J.type => constants.%J.type.04e\n// CHECK:STDOUT:   %J.impl_witness => constants.%J.impl_witness.861\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @J(constants.%ptr) {\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.f050b9.1(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %ptr => constants.%ptr\n// CHECK:STDOUT:   %J.type => constants.%J.type.80f\n// CHECK:STDOUT:   %J.impl_witness => constants.%J.impl_witness.f4f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.b25a4e.2(constants.%T) {\n// CHECK:STDOUT:   %T.loc8_14.2 => constants.%T\n// CHECK:STDOUT:   %J.type.loc8_32.2 => constants.%J.type.04e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.b25a4e.3(constants.%T) {\n// CHECK:STDOUT:   %T.loc14_14.2 => constants.%T\n// CHECK:STDOUT:   %J.type.loc14_32.2 => constants.%J.type.04e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.f050b9.2(constants.%T) {\n// CHECK:STDOUT:   %T.loc20_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc20_32.2 => constants.%ptr\n// CHECK:STDOUT:   %J.type.loc20_33.2 => constants.%J.type.80f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.f050b9.3(constants.%T) {\n// CHECK:STDOUT:   %T.loc26_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc26_32.2 => constants.%ptr\n// CHECK:STDOUT:   %J.type.loc26_33.2 => constants.%J.type.80f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N(constants.%T) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%Self.e1f642.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %J.type => constants.%J.type.04e\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.cc6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.J.type.require(constants.%T, constants.%Self.e1f642.1) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.1\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%Self.binding.as_type\n// CHECK:STDOUT:   %J.type => constants.%J.type.04e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%T, constants.%D.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %J.type => constants.%J.type.04e\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.cc6\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.J.type.require(constants.%T, constants.%D.type.facet) {\n// CHECK:STDOUT:   %T => constants.%T\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.1\n// CHECK:STDOUT:   %Self => constants.%D.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%D\n// CHECK:STDOUT:   %J.type => constants.%J.type.04e\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.e28c26.1(constants.%T) {\n// CHECK:STDOUT:   %T.loc32_14.2 => constants.%T\n// CHECK:STDOUT:   %N.type.loc32_32.2 => constants.%N.type.d682d6.1\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N(constants.%ptr) {\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT:\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.2\n// CHECK:STDOUT:   %Self => constants.%Self.e1f642.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr, constants.%Self.e1f642.1) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT:   %J.type => constants.%J.type.80f\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.19b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf(constants.%ptr, constants.%D.type.facet) {\n// CHECK:STDOUT: !definition:\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT:   %J.type => constants.%J.type.80f\n// CHECK:STDOUT:   %require_complete => constants.%require_complete.19b\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @N.WithSelf.Self.binding.as_type.impls.J.type.require(constants.%ptr, constants.%D.type.facet) {\n// CHECK:STDOUT:   %T => constants.%ptr\n// CHECK:STDOUT:   %N.type => constants.%N.type.d682d6.2\n// CHECK:STDOUT:   %Self => constants.%D.type.facet\n// CHECK:STDOUT:   %Self.binding.as_type => constants.%D\n// CHECK:STDOUT:   %J.type => constants.%J.type.80f\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n// CHECK:STDOUT: specific @D.as.J.impl.e28c26.2(constants.%T) {\n// CHECK:STDOUT:   %T.loc38_14.2 => constants.%T\n// CHECK:STDOUT:   %ptr.loc38_32.2 => constants.%ptr\n// CHECK:STDOUT:   %N.type.loc38_33.2 => constants.%N.type.d682d6.2\n// CHECK:STDOUT: }\n// CHECK:STDOUT:\n"
  },
  {
    "path": "toolchain/install/bazel/empty.BUILD",
    "content": ""
  }
]